humanish 0.15.3 → 0.17.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.
Files changed (48) hide show
  1. package/README.md +49 -6
  2. package/dist/concurrent-shared-world-lab.js +20 -7
  3. package/dist/concurrent-shared-world-lab.js.map +1 -1
  4. package/dist/cua-actor-lab.d.ts +101 -4
  5. package/dist/cua-actor-lab.js +456 -77
  6. package/dist/cua-actor-lab.js.map +1 -1
  7. package/dist/device-presets.d.ts +4 -4
  8. package/dist/device-presets.js +5 -5
  9. package/dist/device-presets.js.map +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/lab-config.d.ts +2 -2
  13. package/dist/observer-assets.js +92 -15
  14. package/dist/observer-assets.js.map +1 -1
  15. package/dist/observer-auth.d.ts +21 -0
  16. package/dist/observer-auth.js +92 -0
  17. package/dist/observer-auth.js.map +1 -0
  18. package/dist/observer-library.d.ts +19 -0
  19. package/dist/observer-library.js +189 -0
  20. package/dist/observer-library.js.map +1 -0
  21. package/dist/observer-serve.d.ts +111 -0
  22. package/dist/observer-serve.js +369 -0
  23. package/dist/observer-serve.js.map +1 -0
  24. package/dist/observer.d.ts +31 -0
  25. package/dist/observer.js +10 -5
  26. package/dist/observer.js.map +1 -1
  27. package/dist/oss-meta-lab.js +2 -4
  28. package/dist/oss-meta-lab.js.map +1 -1
  29. package/dist/program.js +242 -0
  30. package/dist/program.js.map +1 -1
  31. package/dist/run.d.ts +38 -0
  32. package/dist/run.js +71 -1
  33. package/dist/run.js.map +1 -1
  34. package/dist/serve-tunnel.d.ts +16 -0
  35. package/dist/serve-tunnel.js +104 -0
  36. package/dist/serve-tunnel.js.map +1 -0
  37. package/dist/shared-world-lab.d.ts +20 -1
  38. package/dist/shared-world-lab.js +197 -23
  39. package/dist/shared-world-lab.js.map +1 -1
  40. package/docs/architecture/observer.md +7 -0
  41. package/docs/architecture/serve.md +140 -0
  42. package/docs/assets/humanish-drawdb-hero.png +0 -0
  43. package/docs/contracts/run-bundle.md +19 -0
  44. package/docs/contracts/schemas.md +23 -1
  45. package/docs/goals/current.md +4 -3
  46. package/docs/principles/invariants-and-defaults.md +1 -0
  47. package/docs/ramp/README.md +1 -1
  48. package/package.json +1 -1
@@ -0,0 +1,111 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import type { PinnedDirectory } from "./observer.js";
3
+ import type { ServeSessionStore } from "./observer-auth.js";
4
+ import type { LibraryHistory } from "./observer-library.js";
5
+ import { verifyRun } from "./run.js";
6
+ export declare const SERVE_SCHEMA = "humanish.serve-result.v1";
7
+ export type ServeMode = "loopback" | "capability-link" | "share-safe-open";
8
+ export type ServeErrorCode = "HUMANISH_INVALID_PORT" | "HUMANISH_SERVE_INVALID_TTL" | "HUMANISH_SERVE_OPTION_CONFLICT" | "HUMANISH_SERVE_TUNNEL_REQUIRES_EXPOSE" | "HUMANISH_SERVE_EXPOSE_REQUIRES_ORIGIN" | "HUMANISH_SERVE_OPEN_REQUIRES_SAFE" | "HUMANISH_SERVE_TUNNEL_NOT_FOUND" | "HUMANISH_SERVE_TUNNEL_START_FAILED" | "HUMANISH_RUN_NOT_FOUND" | "HUMANISH_SERVE_RUN_NOT_SHAREABLE";
9
+ export interface ServeResult {
10
+ schema: typeof SERVE_SCHEMA;
11
+ ok: boolean;
12
+ cwd: string;
13
+ mode: ServeMode;
14
+ safe: boolean;
15
+ host: "127.0.0.1";
16
+ port?: number;
17
+ url?: string;
18
+ capabilityUrl?: string;
19
+ publicUrl?: string;
20
+ publicCapabilityUrl?: string;
21
+ tunnel?: {
22
+ provider: "ngrok";
23
+ url: string;
24
+ };
25
+ ttlMinutes?: number;
26
+ runsListed: number;
27
+ shareReadyCount?: number;
28
+ entryRunId?: string;
29
+ opened?: boolean;
30
+ openCommand?: string;
31
+ warnings: string[];
32
+ error?: {
33
+ code: ServeErrorCode;
34
+ message: string;
35
+ };
36
+ }
37
+ export interface ServeControlPlane {
38
+ startRun?(request: {
39
+ labId: string;
40
+ dryRun: boolean;
41
+ }): Promise<{
42
+ accepted: boolean;
43
+ runId?: string;
44
+ }>;
45
+ }
46
+ export interface ShareSafetyAdmission {
47
+ admit(runId: string): Promise<boolean>;
48
+ }
49
+ export declare function createShareSafetyAdmission(cwd: string, options?: {
50
+ verifyImpl?: typeof verifyRun;
51
+ ttlMs?: number;
52
+ now?: () => number;
53
+ }): ShareSafetyAdmission;
54
+ export declare function buildServeSecurityHeaders(): Record<string, string>;
55
+ export declare function hostAllowed(hostHeader: string | undefined, allowlist: ReadonlySet<string>): boolean;
56
+ export declare function parsePublicOrigin(value: string): {
57
+ origin: string;
58
+ host: string;
59
+ scheme: "http" | "https";
60
+ } | null;
61
+ export interface ServeAuthContext {
62
+ tokenDigest: Buffer;
63
+ sessions: ServeSessionStore;
64
+ ttlSeconds: number;
65
+ publicScheme?: "http" | "https";
66
+ }
67
+ export interface ServeRequestHandlerOptions {
68
+ proofRoot: PinnedDirectory;
69
+ safe: boolean;
70
+ admit: (runId: string) => Promise<boolean>;
71
+ auth?: ServeAuthContext | null;
72
+ hostAllowlist: ReadonlySet<string>;
73
+ entryRunId?: string;
74
+ renderLibrary: (history: LibraryHistory) => string;
75
+ controlPlane?: ServeControlPlane;
76
+ }
77
+ export declare function createServeRequestHandler(options: ServeRequestHandlerOptions): (request: IncomingMessage, response: ServerResponse) => Promise<void>;
78
+ export interface ServeLibraryOptions {
79
+ port: number;
80
+ safe: boolean;
81
+ expose: boolean;
82
+ authMode: "link" | "none";
83
+ ttlMinutes: number;
84
+ publicOrigin?: string;
85
+ entryRunId?: string;
86
+ controlPlane?: ServeControlPlane;
87
+ verifyImpl?: typeof verifyRun;
88
+ now?: () => number;
89
+ }
90
+ export interface ServeLibraryServer {
91
+ url: string;
92
+ port: number;
93
+ mode: ServeMode;
94
+ capabilityToken?: string;
95
+ runsListed: number;
96
+ shareReadyCount?: number;
97
+ entryRunId?: string;
98
+ addPublicOrigin(origin: string): void;
99
+ close(): Promise<void>;
100
+ }
101
+ export type ServeLibraryStart = {
102
+ ok: true;
103
+ server: ServeLibraryServer;
104
+ } | {
105
+ ok: false;
106
+ error: {
107
+ code: ServeErrorCode;
108
+ message: string;
109
+ };
110
+ };
111
+ export declare function serveObserverLibrary(cwdInput: string, options: ServeLibraryOptions): Promise<ServeLibraryStart>;
@@ -0,0 +1,369 @@
1
+ import { createServer } from "node:http";
2
+ import { lstat } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { buildHistoryIndex, matchRunRoute, pinDirectChildDirectory, pinDirectory, serveRunPath } from "./observer.js";
5
+ import { buildSessionCookie, createServeSessionStore, mintServeToken, sha256Digest, verifyTokenDigest } from "./observer-auth.js";
6
+ import { renderLibraryHtml } from "./observer-library.js";
7
+ import { listRuns, verifyRun } from "./run.js";
8
+ export const SERVE_SCHEMA = "humanish.serve-result.v1";
9
+ export function createShareSafetyAdmission(cwd, options = {}) {
10
+ const verifyImpl = options.verifyImpl ?? verifyRun;
11
+ const now = options.now ?? (() => Date.now());
12
+ // verifyRun scans the ENTIRE run tree, but the cache key is run.json's stat
13
+ // identity, so an out-of-band edit to a scanned artifact that leaves run.json
14
+ // untouched would otherwise keep a stale share_ready verdict. A short TTL
15
+ // bounds that window: any mutation is re-scanned within ttlMs even when
16
+ // run.json never changes. Defense in depth on top of pre-persist redaction.
17
+ const ttlMs = options.ttlMs ?? 30_000;
18
+ const cache = new Map();
19
+ const bundleIdentity = async (runId) => {
20
+ try {
21
+ const stats = await lstat(path.join(cwd, ".humanish", "runs", runId, "run.json"), { bigint: true });
22
+ if (!stats.isFile()) {
23
+ return null;
24
+ }
25
+ return `${stats.dev}:${stats.ino}:${stats.mtimeNs}:${stats.size}`;
26
+ }
27
+ catch {
28
+ return null;
29
+ }
30
+ };
31
+ return {
32
+ async admit(runId) {
33
+ const identity = await bundleIdentity(runId);
34
+ if (!identity) {
35
+ cache.delete(runId);
36
+ return false;
37
+ }
38
+ const cached = cache.get(runId);
39
+ if (cached && cached.identity === identity && now() - cached.verifiedAt < ttlMs) {
40
+ return cached.admitted;
41
+ }
42
+ const admitted = verifyImpl(cwd, runId)
43
+ .then((verified) => verified.ok === true && verified.shareSafety.status === "share_ready")
44
+ .catch(() => false);
45
+ cache.set(runId, { identity, verifiedAt: now(), admitted });
46
+ return admitted;
47
+ }
48
+ };
49
+ }
50
+ export function buildServeSecurityHeaders() {
51
+ return {
52
+ "cache-control": "no-store",
53
+ "referrer-policy": "no-referrer",
54
+ "x-content-type-options": "nosniff",
55
+ "x-frame-options": "DENY",
56
+ "x-robots-tag": "noindex, nofollow"
57
+ };
58
+ }
59
+ export function hostAllowed(hostHeader, allowlist) {
60
+ return typeof hostHeader === "string" && allowlist.has(hostHeader.trim().toLowerCase());
61
+ }
62
+ export function parsePublicOrigin(value) {
63
+ let parsed;
64
+ try {
65
+ parsed = new URL(value);
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
71
+ return null;
72
+ }
73
+ if ((parsed.pathname !== "/" && parsed.pathname !== "") || parsed.search || parsed.hash || !parsed.host) {
74
+ return null;
75
+ }
76
+ return {
77
+ origin: parsed.origin,
78
+ host: parsed.host.toLowerCase(),
79
+ scheme: parsed.protocol === "https:" ? "https" : "http"
80
+ };
81
+ }
82
+ const UNAUTHORIZED_BODY = "humanish serve: capability link required";
83
+ export function createServeRequestHandler(options) {
84
+ return async (request, response) => {
85
+ try {
86
+ for (const [name, value] of Object.entries(buildServeSecurityHeaders())) {
87
+ response.setHeader(name, value);
88
+ }
89
+ const method = request.method ?? "GET";
90
+ if (method !== "GET" && method !== "HEAD") {
91
+ writeText(response, 405, "Method Not Allowed");
92
+ return;
93
+ }
94
+ if (!hostAllowed(request.headers.host, options.hostAllowlist)) {
95
+ writeText(response, 421, "Misdirected Request");
96
+ return;
97
+ }
98
+ const url = new URL(request.url ?? "/", `http://${request.headers.host ?? "127.0.0.1"}`);
99
+ if (options.auth) {
100
+ const mintMatch = url.pathname.match(/^\/_humanish\/auth\/([^/]+)$/);
101
+ if (mintMatch) {
102
+ let candidate = "";
103
+ try {
104
+ candidate = decodeURIComponent(mintMatch[1] ?? "");
105
+ }
106
+ catch {
107
+ candidate = "";
108
+ }
109
+ if (candidate && verifyTokenDigest(candidate, options.auth.tokenDigest)) {
110
+ const { cookieValue } = options.auth.sessions.mint();
111
+ const secure = options.auth.publicScheme === "https";
112
+ response.setHeader("set-cookie", buildSessionCookie(cookieValue, { ttlSeconds: options.auth.ttlSeconds, secure }));
113
+ response.writeHead(302, { location: "/" });
114
+ response.end();
115
+ return;
116
+ }
117
+ writeText(response, 401, UNAUTHORIZED_BODY);
118
+ return;
119
+ }
120
+ // Every route below requires a valid session, regardless of source
121
+ // address: the tunnel agent connects from 127.0.0.1, so a loopback-peer
122
+ // trust shortcut would disable auth in exactly the deployment it protects.
123
+ if (!options.auth.sessions.validate(request.headers.cookie)) {
124
+ writeText(response, 401, UNAUTHORIZED_BODY);
125
+ return;
126
+ }
127
+ }
128
+ else if (url.pathname.startsWith("/_humanish/auth/")) {
129
+ writeText(response, 404, "Not found");
130
+ return;
131
+ }
132
+ if (url.pathname === "/_humanish/api" || url.pathname.startsWith("/_humanish/api/")) {
133
+ writeText(response, 501, `${JSON.stringify({
134
+ error: {
135
+ code: "HUMANISH_SERVE_CONTROL_PLANE_DISABLED",
136
+ message: "control plane not enabled in this version"
137
+ }
138
+ }, null, 2)}\n`, "application/json; charset=utf-8");
139
+ return;
140
+ }
141
+ if (url.pathname === "/") {
142
+ if (options.entryRunId) {
143
+ response.writeHead(302, {
144
+ location: `/_humanish/runs/${encodeURIComponent(options.entryRunId)}/observer/index.html`
145
+ });
146
+ response.end();
147
+ return;
148
+ }
149
+ const history = await loadFilteredHistory(options);
150
+ writeText(response, 200, options.renderLibrary(history), "text/html; charset=utf-8");
151
+ return;
152
+ }
153
+ if (url.pathname === "/_humanish/history.json") {
154
+ const history = await loadFilteredHistory(options);
155
+ writeText(response, 200, JSON.stringify(history, null, 2), "application/json; charset=utf-8");
156
+ return;
157
+ }
158
+ if (url.pathname.startsWith("/_humanish/runs/")) {
159
+ const runRoute = matchRunRoute(url.pathname);
160
+ if (!runRoute) {
161
+ writeText(response, 404, "Run not found");
162
+ return;
163
+ }
164
+ if (options.safe && !(await options.admit(runRoute.runId))) {
165
+ // Byte-identical to the nonexistent-run 404: no existence oracle.
166
+ writeText(response, 404, "Run not found");
167
+ return;
168
+ }
169
+ const targetRoot = await pinDirectChildDirectory(options.proofRoot, runRoute.runId);
170
+ if (!targetRoot) {
171
+ writeText(response, 404, "Run not found");
172
+ return;
173
+ }
174
+ // The explicit empty runtimeStreamUrls keeps a future refactor from
175
+ // reintroducing auth-keyed stream injection on the serve surface.
176
+ await serveRunPath(targetRoot, runRoute.relativePath || "observer/index.html", response, []);
177
+ return;
178
+ }
179
+ writeText(response, 404, "Not found");
180
+ }
181
+ catch {
182
+ writeText(response, 500, "Observer request failed");
183
+ }
184
+ };
185
+ }
186
+ async function loadFilteredHistory(options) {
187
+ const history = await buildHistoryIndex(options.proofRoot);
188
+ if (!options.safe) {
189
+ return history;
190
+ }
191
+ const admissions = await Promise.all(history.runs.map(async (run) => ((await options.admit(run.runId)) === true ? run : null)));
192
+ const runs = admissions.filter((run) => run !== null);
193
+ const latestRunId = runs.some((run) => run.runId === history.latestRunId)
194
+ ? history.latestRunId
195
+ : runs[0]?.runId ?? null;
196
+ return { latestRunId, runs };
197
+ }
198
+ export async function serveObserverLibrary(cwdInput, options) {
199
+ const cwd = path.resolve(cwdInput);
200
+ const verifyImpl = options.verifyImpl ?? verifyRun;
201
+ let proofRoot;
202
+ try {
203
+ proofRoot = await pinDirectory(path.join(cwd, ".humanish", "runs"));
204
+ }
205
+ catch {
206
+ return {
207
+ ok: false,
208
+ error: {
209
+ code: "HUMANISH_RUN_NOT_FOUND",
210
+ message: "No run library found under .humanish/runs. Run `humanish watch` to create the first run."
211
+ }
212
+ };
213
+ }
214
+ const admission = createShareSafetyAdmission(cwd, {
215
+ verifyImpl,
216
+ ...(options.now ? { now: options.now } : {})
217
+ });
218
+ const mode = options.expose
219
+ ? options.authMode === "link" ? "capability-link" : "share-safe-open"
220
+ : "loopback";
221
+ let entryRunId;
222
+ if (options.entryRunId) {
223
+ const resolved = options.entryRunId === "latest"
224
+ ? (await listRuns(cwd)).latest ?? null
225
+ : options.entryRunId;
226
+ const pinned = resolved ? await pinDirectChildDirectory(proofRoot, resolved) : null;
227
+ if (!resolved || !pinned) {
228
+ return {
229
+ ok: false,
230
+ error: { code: "HUMANISH_RUN_NOT_FOUND", message: `Run not found: ${options.entryRunId}` }
231
+ };
232
+ }
233
+ if (options.safe && !(await admission.admit(resolved))) {
234
+ const verified = await verifyImpl(cwd, resolved).catch(() => null);
235
+ const status = verified?.shareSafety.status ?? "unverifiable";
236
+ const reasons = verified?.shareSafety.reasons.map((reason) => reason.code).join(", ") || "VERIFY_FAILED";
237
+ return {
238
+ ok: false,
239
+ error: {
240
+ code: "HUMANISH_SERVE_RUN_NOT_SHAREABLE",
241
+ message: `Run ${resolved} is not share_ready (shareSafety: ${status}; reasons: ${reasons}); --safe refuses to serve it.`
242
+ }
243
+ };
244
+ }
245
+ entryRunId = resolved;
246
+ }
247
+ // Counts are computed over the UNCAPPED run list, not the 80-item history
248
+ // index: a capability link (non-safe) grants access to every run by direct
249
+ // URL, and share-safe modes admit every share_ready run per request, so a
250
+ // count capped at 80 would understate exactly what the exposure warning
251
+ // claims. runsListed feeds the operator's declared-friction warning.
252
+ const allRuns = (await listRuns(cwd)).runs;
253
+ let runsListed;
254
+ let shareReadyCount;
255
+ if (options.safe) {
256
+ const admitted = await Promise.all(allRuns.map((run) => admission.admit(run.runId)));
257
+ shareReadyCount = admitted.filter(Boolean).length;
258
+ runsListed = shareReadyCount;
259
+ }
260
+ else {
261
+ runsListed = allRuns.length;
262
+ }
263
+ const declaredOrigin = options.publicOrigin ? parsePublicOrigin(options.publicOrigin) : null;
264
+ let auth = null;
265
+ let capabilityToken;
266
+ if (options.expose && options.authMode === "link") {
267
+ capabilityToken = mintServeToken();
268
+ auth = {
269
+ tokenDigest: sha256Digest(capabilityToken),
270
+ sessions: createServeSessionStore({
271
+ ttlMs: options.ttlMinutes * 60_000,
272
+ ...(options.now ? { now: options.now } : {})
273
+ }),
274
+ ttlSeconds: options.ttlMinutes * 60,
275
+ ...(declaredOrigin ? { publicScheme: declaredOrigin.scheme } : {})
276
+ };
277
+ }
278
+ const hostAllowlist = new Set();
279
+ const handler = createServeRequestHandler({
280
+ proofRoot,
281
+ safe: options.safe,
282
+ admit: (runId) => admission.admit(runId),
283
+ auth,
284
+ hostAllowlist,
285
+ ...(entryRunId ? { entryRunId } : {}),
286
+ renderLibrary: (history) => renderLibraryHtml(history, {
287
+ mode,
288
+ safe: options.safe,
289
+ capabilities: { actions: false }
290
+ }),
291
+ ...(options.controlPlane ? { controlPlane: options.controlPlane } : {})
292
+ });
293
+ const server = createServer((request, response) => {
294
+ void handler(request, response);
295
+ });
296
+ const port = await listen(server, options.port);
297
+ hostAllowlist.add(`127.0.0.1:${port}`);
298
+ hostAllowlist.add(`localhost:${port}`);
299
+ hostAllowlist.add(`[::1]:${port}`);
300
+ if (declaredOrigin) {
301
+ hostAllowlist.add(declaredOrigin.host);
302
+ }
303
+ return {
304
+ ok: true,
305
+ server: {
306
+ url: `http://127.0.0.1:${port}/`,
307
+ port,
308
+ mode,
309
+ ...(capabilityToken ? { capabilityToken } : {}),
310
+ runsListed,
311
+ ...(shareReadyCount !== undefined ? { shareReadyCount } : {}),
312
+ ...(entryRunId ? { entryRunId } : {}),
313
+ // A tunnel's public origin is only known after the tunnel starts (post
314
+ // bind); this lets the caller declare it, extending the Host allowlist and
315
+ // — for an https origin like every ngrok tunnel — marking cookies Secure.
316
+ addPublicOrigin(origin) {
317
+ const parsed = parsePublicOrigin(origin);
318
+ if (!parsed) {
319
+ return;
320
+ }
321
+ hostAllowlist.add(parsed.host);
322
+ if (auth) {
323
+ auth.publicScheme = parsed.scheme;
324
+ }
325
+ },
326
+ close: async () => {
327
+ auth?.sessions.revokeAll();
328
+ const closed = closeServer(server);
329
+ // Keep-alive sockets would otherwise keep close() pending past the point
330
+ // the operator believes Ctrl-C tore the server down.
331
+ server.closeAllConnections?.();
332
+ await closed;
333
+ }
334
+ }
335
+ };
336
+ }
337
+ function writeText(response, status, body, contentType = "text/plain; charset=utf-8") {
338
+ response.writeHead(status, { "content-type": contentType });
339
+ response.end(body);
340
+ }
341
+ function listen(server, port) {
342
+ return new Promise((resolve, reject) => {
343
+ server.once("error", reject);
344
+ // The serve surface never binds beyond loopback; exposure only ever happens
345
+ // through a tunnel or proxy forwarding to this port.
346
+ server.listen(port, "127.0.0.1", () => {
347
+ server.off("error", reject);
348
+ const address = server.address();
349
+ if (!address || typeof address === "string") {
350
+ reject(new Error("Serve library server did not bind to a TCP port."));
351
+ return;
352
+ }
353
+ resolve(address.port);
354
+ });
355
+ });
356
+ }
357
+ function closeServer(server) {
358
+ return new Promise((resolve, reject) => {
359
+ server.close((error) => {
360
+ if (error) {
361
+ reject(error);
362
+ }
363
+ else {
364
+ resolve();
365
+ }
366
+ });
367
+ });
368
+ }
369
+ //# sourceMappingURL=observer-serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observer-serve.js","sourceRoot":"","sources":["../src/observer-serve.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { type ServerResponse } from "node:http";
1
2
  export declare const OBSERVER_SCHEMA = "humanish.observer-result.v1";
2
3
  export interface ObserverResult {
3
4
  schema: typeof OBSERVER_SCHEMA;
@@ -36,9 +37,39 @@ export interface ObserverRuntimeStreamUrl {
36
37
  streamId: string;
37
38
  url: string;
38
39
  }
40
+ /** internal: consumed by observer-serve */
41
+ export interface PinnedDirectory {
42
+ readonly birthtimeNs: bigint;
43
+ readonly dev: bigint;
44
+ readonly ino: bigint;
45
+ readonly physicalPath: string;
46
+ }
39
47
  export declare function attachObserverRuntimeStreamUrls(result: ObserverResult, streams: ObserverRuntimeStreamUrl[]): void;
40
48
  export declare function renderObserver(cwdInput: string, runInput: string, options?: ObserverOptions): Promise<ObserverResult>;
41
49
  export declare function serveObserver(result: ObserverResult, options?: ObserverServeOptions): Promise<ObserverServer>;
50
+ /** internal: consumed by observer-serve */
51
+ export declare function serveRunPath(runRoot: PinnedDirectory, relativePath: string, response: ServerResponse, runtimeStreamUrls?: ObserverRuntimeStreamUrl[]): Promise<void>;
52
+ /** internal: consumed by observer-serve */
53
+ export declare function buildHistoryIndex(proofRoot: PinnedDirectory): Promise<{
54
+ latestRunId: string | null;
55
+ runs: Array<{
56
+ runId: string;
57
+ createdAt: string | null;
58
+ mode: string | null;
59
+ href: string;
60
+ status: string;
61
+ streamCount: number;
62
+ }>;
63
+ }>;
64
+ /** internal: consumed by observer-serve */
65
+ export declare function matchRunRoute(pathname: string): {
66
+ runId: string;
67
+ relativePath: string;
68
+ } | null;
69
+ /** internal: consumed by observer-serve */
70
+ export declare function pinDirectory(directoryInput: string): Promise<PinnedDirectory>;
71
+ /** internal: consumed by observer-serve */
72
+ export declare function pinDirectChildDirectory(root: PinnedDirectory, name: string): Promise<PinnedDirectory | null>;
42
73
  export declare function openTarget(target: string): {
43
74
  opened: boolean;
44
75
  command?: string;
package/dist/observer.js CHANGED
@@ -219,7 +219,8 @@ function renderObserverHtml(data) {
219
219
  </html>
220
220
  `;
221
221
  }
222
- async function serveRunPath(runRoot, relativePath, response, runtimeStreamUrls = []) {
222
+ /** internal: consumed by observer-serve */
223
+ export async function serveRunPath(runRoot, relativePath, response, runtimeStreamUrls = []) {
223
224
  const root = runRoot.physicalPath;
224
225
  const cleanedRelativePath = relativePath === "" ? "observer/index.html" : relativePath;
225
226
  const filePath = path.resolve(root, cleanedRelativePath);
@@ -309,7 +310,8 @@ function withRuntimeStreamUrls(data, runtimeStreamUrls) {
309
310
  })
310
311
  };
311
312
  }
312
- async function buildHistoryIndex(proofRoot) {
313
+ /** internal: consumed by observer-serve */
314
+ export async function buildHistoryIndex(proofRoot) {
313
315
  await assertPinnedDirectory(proofRoot);
314
316
  const physicalCwd = path.dirname(path.dirname(proofRoot.physicalPath));
315
317
  const listed = await listRuns(physicalCwd);
@@ -331,7 +333,8 @@ async function buildHistoryIndex(proofRoot) {
331
333
  runs
332
334
  };
333
335
  }
334
- function matchRunRoute(pathname) {
336
+ /** internal: consumed by observer-serve */
337
+ export function matchRunRoute(pathname) {
335
338
  const match = pathname.match(/^\/_humanish\/runs\/([^/]+)(?:\/(.*))?$/);
336
339
  if (!match)
337
340
  return null;
@@ -414,7 +417,8 @@ async function inspectContainedRegularFile(root, filePath) {
414
417
  return null;
415
418
  return fileIdentity;
416
419
  }
417
- async function pinDirectory(directoryInput) {
420
+ /** internal: consumed by observer-serve */
421
+ export async function pinDirectory(directoryInput) {
418
422
  const physicalPath = await realpath(path.resolve(directoryInput));
419
423
  const stats = await lstat(physicalPath, { bigint: true });
420
424
  if (stats.isSymbolicLink() || !stats.isDirectory()) {
@@ -422,7 +426,8 @@ async function pinDirectory(directoryInput) {
422
426
  }
423
427
  return Object.freeze({ birthtimeNs: stats.birthtimeNs, dev: stats.dev, ino: stats.ino, physicalPath });
424
428
  }
425
- async function pinDirectChildDirectory(root, name) {
429
+ /** internal: consumed by observer-serve */
430
+ export async function pinDirectChildDirectory(root, name) {
426
431
  if (!isSafeRunIdSegment(name))
427
432
  return null;
428
433
  try {