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.
- package/README.md +49 -6
- package/dist/concurrent-shared-world-lab.js +20 -7
- package/dist/concurrent-shared-world-lab.js.map +1 -1
- package/dist/cua-actor-lab.d.ts +101 -4
- package/dist/cua-actor-lab.js +456 -77
- package/dist/cua-actor-lab.js.map +1 -1
- package/dist/device-presets.d.ts +4 -4
- package/dist/device-presets.js +5 -5
- package/dist/device-presets.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lab-config.d.ts +2 -2
- package/dist/observer-assets.js +92 -15
- package/dist/observer-assets.js.map +1 -1
- package/dist/observer-auth.d.ts +21 -0
- package/dist/observer-auth.js +92 -0
- package/dist/observer-auth.js.map +1 -0
- package/dist/observer-library.d.ts +19 -0
- package/dist/observer-library.js +189 -0
- package/dist/observer-library.js.map +1 -0
- package/dist/observer-serve.d.ts +111 -0
- package/dist/observer-serve.js +369 -0
- package/dist/observer-serve.js.map +1 -0
- package/dist/observer.d.ts +31 -0
- package/dist/observer.js +10 -5
- package/dist/observer.js.map +1 -1
- package/dist/oss-meta-lab.js +2 -4
- package/dist/oss-meta-lab.js.map +1 -1
- package/dist/program.js +242 -0
- package/dist/program.js.map +1 -1
- package/dist/run.d.ts +38 -0
- package/dist/run.js +71 -1
- package/dist/run.js.map +1 -1
- package/dist/serve-tunnel.d.ts +16 -0
- package/dist/serve-tunnel.js +104 -0
- package/dist/serve-tunnel.js.map +1 -0
- package/dist/shared-world-lab.d.ts +20 -1
- package/dist/shared-world-lab.js +197 -23
- package/dist/shared-world-lab.js.map +1 -1
- package/docs/architecture/observer.md +7 -0
- package/docs/architecture/serve.md +140 -0
- package/docs/assets/humanish-drawdb-hero.png +0 -0
- package/docs/contracts/run-bundle.md +19 -0
- package/docs/contracts/schemas.md +23 -1
- package/docs/goals/current.md +4 -3
- package/docs/principles/invariants-and-defaults.md +1 -0
- package/docs/ramp/README.md +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-presets.js","sourceRoot":"","sources":["../src/device-presets.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"device-presets.js","sourceRoot":"","sources":["../src/device-presets.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,4FAA4F;AAC5F,+FAA+F;AAC/F,kFAAkF;AAClF,EAAE;AACF,+FAA+F;AAC/F,4FAA4F;AAC5F,0FAA0F;AAC1F,6FAA6F;AAC7F,gGAAgG;AAChG,4FAA4F;AAC5F,iGAAiG;AACjG,qFAAqF;AAarF;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,oCAAoC;IACpC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE;IACzE,0CAA0C;IAC1C,cAAc,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE;IACjF,qBAAqB;IACrB,eAAe,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE;IAClF,qCAAqC;IACrC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,EAAE;IAC3E,gGAAgG;IAChG,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,EAAE;IAC5E,oDAAoD;IACpD,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,EAAE;CAC3B,CAAC;AAIlD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAqB,SAAS,CAAC;AAEjE,oEAAoE;AACpE,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAuB,CAAC;AAErF,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,cAAc,CAAC;AAC9D,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,mBAAmB,CAAC,IAAkC;IACpE,OAAO,cAAc,CAAC,IAAI,IAAI,qBAAqB,CAAC,CAAC;AACvD,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ export { DEFAULT_OSS_REPOS, OSS_LAB_SCHEMA, normalizeOssRepoSlugs, runOssLab, va
|
|
|
36
36
|
export type { OssLabOptions, OssLabRepoResult, OssLabResult, OssLabStep } from "./oss-lab.js";
|
|
37
37
|
export { CLEANUP_SCHEMA, DOCTOR_SCHEMA, REVIEW_SCHEMA, RUNS_SCHEMA, RUN_BUNDLE_SCHEMA, VERIFY_SCHEMA, cleanupRun, doctor, extractLocalActorVerdict, listRuns, normalizeLocalActorTranscript, readReview, runDryRun, verifyRun } from "./run.js";
|
|
38
38
|
export { SHARED_WORLD_SCHEMA } from "./run.js";
|
|
39
|
-
export type { CleanupAdapterResult, CleanupResourceResult, CleanupResult, DoctorResult, ReviewSummary, RunAdapterArtifact, RunAdapterScore, RunAttributionClass, RunBundle, RunEvent, RunFeedbackCandidate, RunMeaningfulUseComponentId, RunMeaningfulUseScore, RunCleanupHooks, RunOptions, RunProviderResource, RunResult, RunSimulation, RunStream, RunStreamKind, RunSubjectProvenance, RunSubjectStateStepRecord, RunsResult, SharedWorldCheckpoint, SharedWorldEvidence, SharedWorldLaneWindow, SharedWorldOutcome, SharedWorldPlane, SharedWorldStateSnapshot, SharedWorldTimelineEntry, SharedWorldTurn, VerifyResult } from "./run.js";
|
|
39
|
+
export type { CleanupAdapterResult, CleanupResourceResult, CleanupResult, DoctorResult, ReviewSummary, RunAdapterArtifact, RunAdapterScore, RunAttributionClass, RunBundle, RunDesktopGeometry, RunEvent, RunFeedbackCandidate, RunMeaningfulUseComponentId, RunMeaningfulUseScore, RunCleanupHooks, RunOptions, RunProviderResource, RunResult, RunSimulation, RunStream, RunStreamKind, RunSubjectProvenance, RunSubjectStateStepRecord, RunsResult, SharedWorldCheckpoint, SharedWorldEvidence, SharedWorldLaneWindow, SharedWorldOutcome, SharedWorldPlane, SharedWorldStateSnapshot, SharedWorldTimelineEntry, SharedWorldTurn, VerifyResult } from "./run.js";
|
|
40
40
|
export { CUA_ACTOR_LAB_PROVIDER_METADATA, CUA_ACTOR_LAB_SCHEMA, CUA_FANOUT_STRATEGY, buildCuaBundle, buildCuaFanoutBundle, resolveCuaLanePlan, runCuaActorLab } from "./cua-actor-lab.js";
|
|
41
41
|
export type { CuaActorLabErrorCode, CuaActorLabHooks, CuaActorLabResult, CuaLanePlan, CuaLanePlanEntry, CuaLaneResult, CuaLaneSummary, CuaSubjectProjection, RunCuaActorLabOptions, SubjectPhaseEvent } from "./cua-actor-lab.js";
|
|
42
42
|
export { SCRIPTED_BROWSER_PROVIDER, runScriptedBrowserSession } from "./scripted-browser-actor.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,6BAA6B,EAC7B,6BAA6B,EAC7B,2BAA2B,EAC3B,uBAAuB,EACvB,6BAA6B,EAC9B,MAAM,qBAAqB,CAAC;AAa7B,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,oBAAoB,EAAE,gCAAgC,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAEjJ,OAAO,EACL,mCAAmC,EACnC,uBAAuB,EACxB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAY3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EACL,uBAAuB,EACvB,gCAAgC,EAChC,6BAA6B,EAC9B,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,0BAA0B,EAC1B,gCAAgC,EAChC,wBAAwB,EACzB,MAAM,wBAAwB,CAAC;AAOhC,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,6BAA6B,EAC7B,wBAAwB,EACzB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,cAAc,EACf,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1D,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAExF,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE3F,OAAO,EACL,oBAAoB,EACpB,2BAA2B,EAC3B,yBAAyB,EACzB,8BAA8B,EAC9B,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAM9B,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,SAAS,EACT,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,cAAc,EACd,aAAa,EACb,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,UAAU,EACV,MAAM,EACN,wBAAwB,EACxB,QAAQ,EACR,6BAA6B,EAC7B,UAAU,EACV,SAAS,EACT,SAAS,EACV,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/lab-config.d.ts
CHANGED
|
@@ -233,7 +233,7 @@ export interface LabActorLane {
|
|
|
233
233
|
caseGroup?: string;
|
|
234
234
|
/** Persona id/label threaded into this lane's actor prompt. Default: actors[0].persona. */
|
|
235
235
|
persona?: string;
|
|
236
|
-
/** Named
|
|
236
|
+
/** Named hosted-screen preset for this lane. XOR raw execution.desktop.resolution. */
|
|
237
237
|
device?: string;
|
|
238
238
|
/** Per-lane steer appended to this lane's mission (the roster's per-lane focus). */
|
|
239
239
|
instruction?: string;
|
|
@@ -332,7 +332,7 @@ export interface LabExecutionDesktop {
|
|
|
332
332
|
* width-based responsive CSS fires) — touch/DPR/UA are sim-parity prompt signals, not rendered.
|
|
333
333
|
*/
|
|
334
334
|
device?: string;
|
|
335
|
-
/** Raw
|
|
335
|
+
/** Raw hosted screen resolution [width, height] — an escape hatch that overrides `device`. */
|
|
336
336
|
resolution?: [number, number];
|
|
337
337
|
/**
|
|
338
338
|
* Browser family to launch for hosted desktop actor lanes. Absent/default preserves the
|
package/dist/observer-assets.js
CHANGED
|
@@ -335,7 +335,7 @@ a { color: inherit; text-decoration: none; }
|
|
|
335
335
|
display: grid;
|
|
336
336
|
gap: 14px;
|
|
337
337
|
grid-template-columns: repeat(auto-fill, minmax(min(var(--tile-min), 100%), 1fr));
|
|
338
|
-
align-content: start;
|
|
338
|
+
align-content: start; align-items: start;
|
|
339
339
|
}
|
|
340
340
|
|
|
341
341
|
.tile {
|
|
@@ -354,12 +354,12 @@ a { color: inherit; text-decoration: none; }
|
|
|
354
354
|
|
|
355
355
|
.tile-head {
|
|
356
356
|
display: flex; align-items: center; gap: 8px;
|
|
357
|
-
padding: 0 10px; height:
|
|
357
|
+
padding: 0 10px; height: 38px; flex: none;
|
|
358
358
|
border-bottom: 1px solid var(--line);
|
|
359
359
|
background: var(--surface-1);
|
|
360
360
|
}
|
|
361
|
-
.tile-idx { font-family: var(--mono); font-size:
|
|
362
|
-
.tile-name { font-size:
|
|
361
|
+
.tile-idx { font-family: var(--mono); font-size: 11px; color: var(--text-4); flex: none; }
|
|
362
|
+
.tile-name { font-size: 15px; font-weight: 520; color: var(--text-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; }
|
|
363
363
|
.kind-badge {
|
|
364
364
|
font-family: var(--mono); font-size: 9px; letter-spacing: .08em; text-transform: uppercase;
|
|
365
365
|
padding: 2px 6px; border-radius: 5px; flex: none;
|
|
@@ -400,10 +400,10 @@ a { color: inherit; text-decoration: none; }
|
|
|
400
400
|
}
|
|
401
401
|
.tile-foot {
|
|
402
402
|
display: flex; align-items: center; gap: 8px;
|
|
403
|
-
padding: 0 10px; height:
|
|
403
|
+
padding: 0 10px; height: 36px; flex: none;
|
|
404
404
|
border-top: 1px solid var(--line); background: var(--surface-1);
|
|
405
405
|
}
|
|
406
|
-
.tile-foot-text { font-size:
|
|
406
|
+
.tile-foot-text { font-size: 14px; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; }
|
|
407
407
|
.tile-foot-text .now-dot { color: var(--accent); margin-right: 6px; }
|
|
408
408
|
.mini-prog { width: 46px; height: 3px; border-radius: 2px; background: var(--line); overflow: hidden; flex: none; }
|
|
409
409
|
.mini-prog > span { display: block; height: 100%; background: var(--accent); transition: width .6s var(--ease-out); }
|
|
@@ -416,6 +416,7 @@ a { color: inherit; text-decoration: none; }
|
|
|
416
416
|
|
|
417
417
|
/* ============================================================ STREAM SURFACES */
|
|
418
418
|
.surface-fill { position: absolute; inset: 0; width: 100%; height: 100%; }
|
|
419
|
+
.surface-screenshot { object-fit: contain; object-position: top center; }
|
|
419
420
|
.live-stream-mount { position: absolute; inset: 0; overflow: hidden; background: #000; }
|
|
420
421
|
.live-stream-overlay { position: absolute; overflow: hidden; pointer-events: none; z-index: 2; }
|
|
421
422
|
.live-stream-overlay[data-focus="true"] .bw-lab-dock { max-height: 86px; }
|
|
@@ -657,6 +658,15 @@ a.cx-artifact:hover { border-color: var(--line-3); color: var(--text-1); }
|
|
|
657
658
|
max-width: 100%; max-height: 100%;
|
|
658
659
|
width: auto; height: 100%;
|
|
659
660
|
}
|
|
661
|
+
.focus-geometry {
|
|
662
|
+
position: absolute; z-index: 4; left: 50%; bottom: 3px; transform: translateX(-50%);
|
|
663
|
+
display: inline-flex; align-items: center; gap: 7px; max-width: calc(100% - 44px);
|
|
664
|
+
height: 19px; padding: 0 8px; border: 1px solid var(--line-2); border-radius: var(--radius-pill);
|
|
665
|
+
background: var(--surface-0); box-shadow: var(--shadow-1); color: var(--text-3);
|
|
666
|
+
font-family: var(--mono); font-size: 8.5px; letter-spacing: .04em; white-space: nowrap;
|
|
667
|
+
}
|
|
668
|
+
.focus-geometry strong { color: var(--text-2); font-weight: 500; }
|
|
669
|
+
.focus-geometry-sep { color: var(--text-4); }
|
|
660
670
|
@supports not (aspect-ratio: 1) { .focus-frame { height: 100%; width: 100%; } }
|
|
661
671
|
|
|
662
672
|
/* side panel */
|
|
@@ -846,6 +856,10 @@ html[data-theme="light"] .scrim { background: rgba(20,28,40,.32); }
|
|
|
846
856
|
width: 100%; height: auto; max-height: none;
|
|
847
857
|
min-height: 280px;
|
|
848
858
|
}
|
|
859
|
+
.focus-geometry {
|
|
860
|
+
position: relative; left: auto; bottom: auto; transform: none;
|
|
861
|
+
width: max-content; max-width: 100%; margin: 8px auto 0; overflow-x: auto;
|
|
862
|
+
}
|
|
849
863
|
.focus-side {
|
|
850
864
|
position: relative; left: auto; right: auto; bottom: auto; top: auto; z-index: auto;
|
|
851
865
|
min-height: 360px; max-height: none; border-left: none; border-top: 1px solid var(--line-2);
|
|
@@ -1024,6 +1038,7 @@ html[data-motion="reduced"] *, html[data-motion="reduced"] *::before, html[data-
|
|
|
1024
1038
|
.sb-counts { display: inline-flex; align-items: center; gap: 8px; flex: none; }
|
|
1025
1039
|
.sb-count { display: inline-flex; align-items: center; gap: 5px; color: var(--text-2); }
|
|
1026
1040
|
.sb-count .si-dot { width: 7px; height: 7px; border-radius: 50%; }
|
|
1041
|
+
.sb-count-number, .sb-count-label { white-space: nowrap; }
|
|
1027
1042
|
.sb-run { color: var(--text-4); font-size: 10.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
1028
1043
|
|
|
1029
1044
|
.sb-console {
|
|
@@ -1046,6 +1061,12 @@ html[data-motion="reduced"] *, html[data-motion="reduced"] *::before, html[data-
|
|
|
1046
1061
|
/* when docked above the bar, drop the console's bottom rounding/shadow seam */
|
|
1047
1062
|
.console + .statusbar { border-top-color: var(--line); }
|
|
1048
1063
|
|
|
1064
|
+
@media (max-width: 1024px) {
|
|
1065
|
+
.sb-count-label { display: none; }
|
|
1066
|
+
}
|
|
1067
|
+
@media (max-width: 900px) {
|
|
1068
|
+
.sb-console-peek { display: none; }
|
|
1069
|
+
}
|
|
1049
1070
|
@media (max-width: 720px) {
|
|
1050
1071
|
.sb-counts, .sb-run, .sb-prog { display: none; }
|
|
1051
1072
|
.sb-console-label { display: none; }
|
|
@@ -1200,17 +1221,71 @@ export function observerClientJs() {
|
|
|
1200
1221
|
function laneEvents(s) { return s.timeline || []; }
|
|
1201
1222
|
function laneArtifacts(s) { return s.artifacts || []; }
|
|
1202
1223
|
|
|
1224
|
+
function geometrySize(value) {
|
|
1225
|
+
var width = value && Number(value.width);
|
|
1226
|
+
var height = value && Number(value.height);
|
|
1227
|
+
return width > 0 && height > 0 ? { width: width, height: height } : null;
|
|
1228
|
+
}
|
|
1229
|
+
function screenSizeFor(s) {
|
|
1230
|
+
var screen = s.desktopGeometry && s.desktopGeometry.screen;
|
|
1231
|
+
return geometrySize(screen && screen.verified) || geometrySize(screen && screen.requested);
|
|
1232
|
+
}
|
|
1233
|
+
function geometrySource(value) {
|
|
1234
|
+
if (value === "cdp") return "CDP";
|
|
1235
|
+
return String(value || "runtime");
|
|
1236
|
+
}
|
|
1237
|
+
function geometryDetailFor(s) {
|
|
1238
|
+
var geometry = s.desktopGeometry;
|
|
1239
|
+
if (!geometry) return "";
|
|
1240
|
+
var screen = geometry.screen || {};
|
|
1241
|
+
var requested = geometrySize(screen.requested);
|
|
1242
|
+
var verified = geometrySize(screen.verified);
|
|
1243
|
+
var browserWindow = geometrySize(geometry.browserWindow);
|
|
1244
|
+
var viewport = geometrySize(geometry.viewport);
|
|
1245
|
+
var bits = [];
|
|
1246
|
+
if (verified) {
|
|
1247
|
+
bits.push("Screen " + verified.width + TIMES + verified.height + " (verified via " + geometrySource(screen.verified && screen.verified.source) + (requested ? "; requested " + requested.width + TIMES + requested.height : "") + ")");
|
|
1248
|
+
} else if (requested) {
|
|
1249
|
+
bits.push("Screen " + requested.width + TIMES + requested.height + " (requested; runtime verification unavailable)");
|
|
1250
|
+
}
|
|
1251
|
+
if (browserWindow) {
|
|
1252
|
+
var x = Number(geometry.browserWindow.x);
|
|
1253
|
+
var y = Number(geometry.browserWindow.y);
|
|
1254
|
+
var origin = isFinite(x) && isFinite(y) ? " at " + x + "," + y : "";
|
|
1255
|
+
bits.push("Browser window " + browserWindow.width + TIMES + browserWindow.height + origin + " (" + geometrySource(geometry.browserWindow.source) + ")");
|
|
1256
|
+
}
|
|
1257
|
+
if (viewport) {
|
|
1258
|
+
var dpr = Number(geometry.viewport.deviceScaleFactor);
|
|
1259
|
+
bits.push("CSS viewport " + viewport.width + TIMES + viewport.height + (dpr > 0 ? ", DPR " + dpr : "") + " (" + geometrySource(geometry.viewport.source) + ")");
|
|
1260
|
+
}
|
|
1261
|
+
return bits.join(" · ");
|
|
1262
|
+
}
|
|
1263
|
+
function focusGeometry(s) {
|
|
1264
|
+
var screen = screenSizeFor(s);
|
|
1265
|
+
var viewport = geometrySize(s.desktopGeometry && s.desktopGeometry.viewport);
|
|
1266
|
+
if (!screen && !viewport) return "";
|
|
1267
|
+
var parts = [];
|
|
1268
|
+
if (screen) parts.push('<span>SCREEN <strong>' + screen.width + TIMES + screen.height + '</strong></span>');
|
|
1269
|
+
if (viewport) {
|
|
1270
|
+
var dpr = Number(s.desktopGeometry.viewport.deviceScaleFactor);
|
|
1271
|
+
parts.push('<span>VIEWPORT <strong>' + viewport.width + TIMES + viewport.height + '</strong>' + (dpr > 0 ? ' · DPR <strong>' + esc(dpr) + '</strong>' : '') + '</span>');
|
|
1272
|
+
}
|
|
1273
|
+
var detail = geometryDetailFor(s);
|
|
1274
|
+
return '<div class="focus-geometry" title="' + esc(detail) + '" aria-label="' + esc(detail) + '">' + parts.join('<span class="focus-geometry-sep">·</span>') + '</div>';
|
|
1275
|
+
}
|
|
1203
1276
|
function aspectFor(s) {
|
|
1204
1277
|
if (s.kind === "terminal" || s.kind === "tui") return "16 / 10";
|
|
1205
|
-
var
|
|
1206
|
-
if (
|
|
1278
|
+
var frame = screenSizeFor(s) || geometrySize(s.viewport);
|
|
1279
|
+
if (frame) return frame.width + " / " + frame.height;
|
|
1207
1280
|
return "16 / 9";
|
|
1208
1281
|
}
|
|
1209
1282
|
function dimsFor(s) {
|
|
1210
1283
|
if (s.kind === "terminal") return "CLI";
|
|
1211
1284
|
if (s.kind === "tui") return "TUI";
|
|
1212
1285
|
if (s.kind === "codex-ui") return "CODEX";
|
|
1213
|
-
var
|
|
1286
|
+
var screen = screenSizeFor(s);
|
|
1287
|
+
if (screen) return screen.width + TIMES + screen.height;
|
|
1288
|
+
var vp = geometrySize(s.viewport);
|
|
1214
1289
|
if (vp) return vp.width > vp.height ? (vp.width + TIMES + vp.height) : "MOB";
|
|
1215
1290
|
return "SIM";
|
|
1216
1291
|
}
|
|
@@ -1514,7 +1589,7 @@ export function observerClientJs() {
|
|
|
1514
1589
|
var dock = focus ? browserLabDock(s, shot) : "";
|
|
1515
1590
|
var body;
|
|
1516
1591
|
if (liveUrl && S.media === "live") body = liveStreamMount(s, liveUrl);
|
|
1517
|
-
else if (shot) body = '<img class="surface-fill
|
|
1592
|
+
else if (shot) body = '<img class="surface-fill surface-screenshot" src="' + esc(shot) + '" alt="' + (s.desktopGeometry ? "desktop screenshot" : "browser screenshot") + '"/>';
|
|
1518
1593
|
else body = '<div class="bw-app-wait"><div class="wait-spinner" style="width:24px;height:24px"></div>'
|
|
1519
1594
|
+ '<div class="mono" style="font-size:9px">' + esc(route) + '</div>'
|
|
1520
1595
|
+ '<div style="font-size:10px">' + esc(laneStep(s)) + '</div></div>';
|
|
@@ -1917,11 +1992,13 @@ export function observerClientJs() {
|
|
|
1917
1992
|
var TILE_MIN = { comfortable: "440px", compact: "330px", dense: "240px" };
|
|
1918
1993
|
function buildTile(s, i) {
|
|
1919
1994
|
var live = tone(s.status) === "running";
|
|
1920
|
-
|
|
1995
|
+
var geometryDetail = geometryDetailFor(s);
|
|
1996
|
+
var accessibleLabel = "Open lane " + pad2(i + 1) + ": " + laneName(s) + (geometryDetail ? ". " + geometryDetail : "");
|
|
1997
|
+
return '<article class="tile" data-selected="' + (s.id === S.focusedId ? "true" : "false") + '" tabindex="0" role="button" data-action="open:' + esc(s.id) + '" aria-label="' + esc(accessibleLabel) + '">'
|
|
1921
1998
|
+ '<header class="tile-head"><span class="tile-idx mono">' + pad2(i + 1) + '</span>' + pip(s.status, live)
|
|
1922
1999
|
+ '<span class="tile-name" title="' + esc(laneName(s)) + '">' + esc(laneName(s)) + '</span>'
|
|
1923
2000
|
+ '<span class="kind-badge" data-kind="' + esc(s.kind) + '">' + esc(s.kindLabel || s.kind) + '</span>'
|
|
1924
|
-
+ '<span class="tile-dims mono">' + esc(dimsFor(s)) + '</span>'
|
|
2001
|
+
+ '<span class="tile-dims mono"' + (geometryDetail ? ' title="' + esc(geometryDetail) + '"' : '') + '>' + esc(dimsFor(s)) + '</span>'
|
|
1925
2002
|
+ '<span class="tile-open">' + icon("expand", 13) + '</span></header>'
|
|
1926
2003
|
+ '<div class="tile-surface" style="--aspect:' + aspectFor(s) + '">' + streamSurface(s, false) + '</div>'
|
|
1927
2004
|
+ '<footer class="tile-foot" data-status="' + esc(s.status) + '"><span class="tile-foot-text">' + (live ? '<span class="now-dot">▸</span>' : '') + esc(laneStep(s)) + '</span>'
|
|
@@ -2104,7 +2181,7 @@ export function observerClientJs() {
|
|
|
2104
2181
|
+ '<span class="rail-meta"><span class="rail-name">' + esc(laneName(r)) + '</span><span class="rail-sub">' + pip(r.status, tone(r.status) === "running") + ' ' + esc(r.kindLabel || r.kind) + '</span></span></button>';
|
|
2105
2182
|
}).join("") + '</div></aside>';
|
|
2106
2183
|
|
|
2107
|
-
var stage = '<section class="focus-stage"><div class="focus-stage-area"><div class="focus-frame" style="--aspect:' + aspectFor(s) + '">' + streamSurface(s, true) + '</div
|
|
2184
|
+
var stage = '<section class="focus-stage"><div class="focus-stage-area"><div class="focus-frame" style="--aspect:' + aspectFor(s) + '">' + streamSurface(s, true) + '</div>' + focusGeometry(s) + '</div></section>';
|
|
2108
2185
|
|
|
2109
2186
|
var side = '<aside class="focus-side" aria-hidden="' + (S.sideCollapsed ? "true" : "false") + '" data-sheet="' + (S.sheetOpen ? "open" : "closed") + '">'
|
|
2110
2187
|
+ '<button class="sheet-grip" data-action="toggle-sheet" aria-label="Toggle details"></button>'
|
|
@@ -2150,8 +2227,8 @@ export function observerClientJs() {
|
|
|
2150
2227
|
return '<footer class="statusbar">'
|
|
2151
2228
|
+ '<span class="sb-status" data-tone="' + tone(overall) + '">' + pip(overall, tone(overall) === "running") + '<span class="sb-status-label mono">' + statusLabel(overall) + '</span><span class="sb-pct mono">' + pct + '%</span></span>'
|
|
2152
2229
|
+ '<span class="sb-prog"><span style="width:' + pct + '%" data-tone="' + tone(overall) + '"></span></span>'
|
|
2153
|
-
+ '<span class="sb-counts">' + counts.map(function (c) { return '<span class="sb-count" title="' + c.count + ' ' + c.label + '"><span class="si-dot" style="background:' + c.color + '"></span><span class="mono">' + c.count + '</span></span>'; }).join("") + '</span>'
|
|
2154
|
-
+ '<span class="sb-run mono">' + esc((run.mode || "") + " · " + (run.runId || "")) + '</span>'
|
|
2230
|
+
+ '<span class="sb-counts">' + counts.map(function (c) { return '<span class="sb-count" title="' + c.count + ' ' + c.label + '"><span class="si-dot" style="background:' + c.color + '"></span><span class="mono sb-count-number">' + c.count + '</span><span class="mono sb-count-label">' + c.label + '</span></span>'; }).join("") + '</span>'
|
|
2231
|
+
+ '<span class="sb-run mono">' + esc("mode: " + (run.mode || "unknown") + " · " + (run.runId || "")) + '</span>'
|
|
2155
2232
|
+ '<div class="tb-spacer"></div>'
|
|
2156
2233
|
+ '<button class="sb-console" aria-expanded="' + (S.consoleOpen ? "true" : "false") + '" data-action="toggle-console" title="Run console (backtick)">' + icon("terminal", 14)
|
|
2157
2234
|
+ '<span class="sb-console-label">Run console</span>' + peek
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observer-assets.js","sourceRoot":"","sources":["../src/observer-assets.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,gFAAgF;AAChF,+EAA+E;AAC/E,iEAAiE;AACjE,EAAE;AACF,8EAA8E;AAC9E,8EAA8E;AAC9E,4EAA4E;AAC5E,+CAA+C;AAE/C,MAAM,UAAU,WAAW;IACzB,OAAO
|
|
1
|
+
{"version":3,"file":"observer-assets.js","sourceRoot":"","sources":["../src/observer-assets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
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;
|
|
@@ -0,0 +1,92 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observer-auth.js","sourceRoot":"","sources":["../src/observer-auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface LibraryHistory {
|
|
2
|
+
latestRunId: string | null;
|
|
3
|
+
runs: Array<{
|
|
4
|
+
runId: string;
|
|
5
|
+
createdAt: string | null;
|
|
6
|
+
mode: string | null;
|
|
7
|
+
href: string;
|
|
8
|
+
status: string;
|
|
9
|
+
streamCount: number;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
export interface LibraryRenderOptions {
|
|
13
|
+
mode: "loopback" | "capability-link" | "share-safe-open";
|
|
14
|
+
safe: boolean;
|
|
15
|
+
capabilities: {
|
|
16
|
+
actions: boolean;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export declare function renderLibraryHtml(history: LibraryHistory, opts: LibraryRenderOptions): string;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
const STATUS_TONES = {
|
|
2
|
+
passed: "#3fb970",
|
|
3
|
+
running: "#4f8ff7",
|
|
4
|
+
failed: "#e5534b",
|
|
5
|
+
blocked: "#d29922",
|
|
6
|
+
timed_out: "#d29922"
|
|
7
|
+
};
|
|
8
|
+
export function renderLibraryHtml(history, opts) {
|
|
9
|
+
const emptyState = opts.safe
|
|
10
|
+
? "No share_ready runs yet — run `humanish verify` to see why."
|
|
11
|
+
: "No runs yet — run `humanish watch` to create one.";
|
|
12
|
+
return `<!doctype html>
|
|
13
|
+
<html lang="en" data-theme="dark">
|
|
14
|
+
<head>
|
|
15
|
+
<meta charset="utf-8">
|
|
16
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
17
|
+
<title>Humanish Library</title>
|
|
18
|
+
<style>${libraryCss()}</style>
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
<header class="bar">
|
|
22
|
+
<span class="mark">humanish</span>
|
|
23
|
+
<span class="title">Run Library</span>
|
|
24
|
+
<span class="mode">${escapeHtml(modeLabel(opts))}</span>
|
|
25
|
+
</header>
|
|
26
|
+
<main>
|
|
27
|
+
<p class="note" id="note" hidden></p>
|
|
28
|
+
<ul class="runs" id="runs"></ul>
|
|
29
|
+
<p class="empty" id="empty" hidden>${escapeHtml(emptyState)}</p>
|
|
30
|
+
</main>
|
|
31
|
+
<script type="application/json" id="serve-capabilities">${escapeJsonScript(opts.capabilities)}</script>
|
|
32
|
+
<script type="application/json" id="library-data">${escapeJsonScript(history)}</script>
|
|
33
|
+
<script>${libraryClientJs()}</script>
|
|
34
|
+
</body>
|
|
35
|
+
</html>
|
|
36
|
+
`;
|
|
37
|
+
}
|
|
38
|
+
function modeLabel(opts) {
|
|
39
|
+
const auth = opts.mode === "capability-link" ? "capability link" : opts.mode === "share-safe-open" ? "open" : "loopback";
|
|
40
|
+
return opts.safe ? `${auth} · share_ready only` : auth;
|
|
41
|
+
}
|
|
42
|
+
function libraryCss() {
|
|
43
|
+
return `
|
|
44
|
+
:root { color-scheme: dark; }
|
|
45
|
+
* { box-sizing: border-box; margin: 0; }
|
|
46
|
+
body {
|
|
47
|
+
background: #0c0e12; color: #e6e8ec; min-height: 100vh;
|
|
48
|
+
font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
49
|
+
}
|
|
50
|
+
.bar {
|
|
51
|
+
display: flex; align-items: baseline; gap: 0.6rem;
|
|
52
|
+
padding: 1rem 1.1rem; border-bottom: 1px solid #1e222b;
|
|
53
|
+
position: sticky; top: 0; background: rgba(12,14,18,0.95); backdrop-filter: blur(6px);
|
|
54
|
+
}
|
|
55
|
+
.mark { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-weight: 600; color: #9aa3b2; }
|
|
56
|
+
.title { font-weight: 600; }
|
|
57
|
+
.mode { margin-left: auto; font-size: 0.75rem; color: #9aa3b2; font-family: ui-monospace, "SF Mono", Menlo, monospace; }
|
|
58
|
+
main { padding: 1rem 1.1rem 3rem; max-width: 44rem; margin: 0 auto; }
|
|
59
|
+
.note { font-size: 0.8rem; color: #d29922; padding: 0.5rem 0; }
|
|
60
|
+
.runs { list-style: none; padding: 0; display: grid; gap: 0.6rem; }
|
|
61
|
+
.runs a {
|
|
62
|
+
display: block; text-decoration: none; color: inherit;
|
|
63
|
+
border: 1px solid #1e222b; border-radius: 10px; padding: 0.8rem 0.9rem; background: #11141a;
|
|
64
|
+
}
|
|
65
|
+
.runs a:active { background: #171b23; }
|
|
66
|
+
.run-top { display: flex; align-items: center; gap: 0.5rem; }
|
|
67
|
+
.pip { width: 9px; height: 9px; border-radius: 50%; flex: none; }
|
|
68
|
+
.pip.running { animation: pulse 1.6s ease-in-out infinite; }
|
|
69
|
+
@keyframes pulse { 50% { opacity: 0.35; } }
|
|
70
|
+
.run-id {
|
|
71
|
+
font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 0.8rem;
|
|
72
|
+
overflow-wrap: anywhere;
|
|
73
|
+
}
|
|
74
|
+
.badge {
|
|
75
|
+
margin-left: auto; flex: none; font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.06em;
|
|
76
|
+
border: 1px solid #2c5f8a; color: #7cb8ec; border-radius: 999px; padding: 0.1rem 0.5rem;
|
|
77
|
+
}
|
|
78
|
+
.badge.latest { border-color: #3fb970; color: #7ee2a8; }
|
|
79
|
+
.run-meta { margin-top: 0.35rem; font-size: 0.75rem; color: #9aa3b2; }
|
|
80
|
+
.empty { color: #9aa3b2; font-size: 0.85rem; padding: 2rem 0; text-align: center; }
|
|
81
|
+
`;
|
|
82
|
+
}
|
|
83
|
+
function libraryClientJs() {
|
|
84
|
+
const tones = JSON.stringify(STATUS_TONES);
|
|
85
|
+
return `
|
|
86
|
+
(function () {
|
|
87
|
+
var TONES = ${tones};
|
|
88
|
+
var POLL_MS = 15000;
|
|
89
|
+
var stopped = false;
|
|
90
|
+
|
|
91
|
+
function render(history) {
|
|
92
|
+
var list = document.getElementById("runs");
|
|
93
|
+
var empty = document.getElementById("empty");
|
|
94
|
+
list.textContent = "";
|
|
95
|
+
var runs = history.runs || [];
|
|
96
|
+
empty.hidden = runs.length !== 0;
|
|
97
|
+
for (var i = 0; i < runs.length; i += 1) {
|
|
98
|
+
var run = runs[i];
|
|
99
|
+
var item = document.createElement("li");
|
|
100
|
+
var link = document.createElement("a");
|
|
101
|
+
link.href = run.href;
|
|
102
|
+
var top = document.createElement("div");
|
|
103
|
+
top.className = "run-top";
|
|
104
|
+
var pip = document.createElement("span");
|
|
105
|
+
pip.className = run.status === "running" ? "pip running" : "pip";
|
|
106
|
+
pip.style.background = TONES[run.status] || "#57606f";
|
|
107
|
+
var id = document.createElement("span");
|
|
108
|
+
id.className = "run-id";
|
|
109
|
+
id.textContent = run.runId;
|
|
110
|
+
top.appendChild(pip);
|
|
111
|
+
top.appendChild(id);
|
|
112
|
+
if (run.runId === history.latestRunId) {
|
|
113
|
+
var latest = document.createElement("span");
|
|
114
|
+
latest.className = "badge latest";
|
|
115
|
+
latest.textContent = "latest";
|
|
116
|
+
top.appendChild(latest);
|
|
117
|
+
} else if (run.status === "running") {
|
|
118
|
+
var live = document.createElement("span");
|
|
119
|
+
live.className = "badge";
|
|
120
|
+
live.textContent = "live";
|
|
121
|
+
top.appendChild(live);
|
|
122
|
+
}
|
|
123
|
+
var meta = document.createElement("div");
|
|
124
|
+
meta.className = "run-meta";
|
|
125
|
+
meta.textContent = [run.mode || "unknown", run.streamCount + " lanes", run.createdAt || ""].filter(Boolean).join(" \\u00b7 ");
|
|
126
|
+
link.appendChild(top);
|
|
127
|
+
link.appendChild(meta);
|
|
128
|
+
item.appendChild(link);
|
|
129
|
+
list.appendChild(item);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function note(text) {
|
|
134
|
+
var element = document.getElementById("note");
|
|
135
|
+
element.hidden = !text;
|
|
136
|
+
element.textContent = text || "";
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function poll() {
|
|
140
|
+
if (stopped) return;
|
|
141
|
+
fetch("/_humanish/history.json", { cache: "no-store" }).then(function (response) {
|
|
142
|
+
if (response.status === 401) {
|
|
143
|
+
stopped = true;
|
|
144
|
+
note("session expired \\u2014 tap your capability link again");
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
return response.json();
|
|
148
|
+
}).then(function (history) {
|
|
149
|
+
if (history) {
|
|
150
|
+
note("");
|
|
151
|
+
render(history);
|
|
152
|
+
}
|
|
153
|
+
}).catch(function () {
|
|
154
|
+
note("connection lost \\u2014 retrying");
|
|
155
|
+
}).then(function () {
|
|
156
|
+
if (!stopped) setTimeout(poll, POLL_MS);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
render(JSON.parse(document.getElementById("library-data").textContent));
|
|
161
|
+
setTimeout(poll, POLL_MS);
|
|
162
|
+
})();
|
|
163
|
+
`;
|
|
164
|
+
}
|
|
165
|
+
function escapeHtml(value) {
|
|
166
|
+
return value.replace(/[&<>"']/g, (char) => {
|
|
167
|
+
switch (char) {
|
|
168
|
+
case "&":
|
|
169
|
+
return "&";
|
|
170
|
+
case "<":
|
|
171
|
+
return "<";
|
|
172
|
+
case ">":
|
|
173
|
+
return ">";
|
|
174
|
+
case "\"":
|
|
175
|
+
return """;
|
|
176
|
+
default:
|
|
177
|
+
return "'";
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
function escapeJsonScript(value) {
|
|
182
|
+
return JSON.stringify(value)
|
|
183
|
+
.replace(/</g, "\\u003c")
|
|
184
|
+
.replace(/>/g, "\\u003e")
|
|
185
|
+
.replace(/&/g, "\\u0026")
|
|
186
|
+
.replace(/\u2028/g, "\\u2028")
|
|
187
|
+
.replace(/\u2029/g, "\\u2029");
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=observer-library.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observer-library.js","sourceRoot":"","sources":["../src/observer-library.ts"],"names":[],"mappings":"AAkBA,MAAM,YAAY,GAA2B;IAC3C,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,SAAS;CACrB,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,OAAuB,EAAE,IAA0B;IACnF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI;QAC1B,CAAC,CAAC,6DAA6D;QAC/D,CAAC,CAAC,mDAAmD,CAAC;IAExD,OAAO;;;;;;SAMA,UAAU,EAAE;;;;;;uBAME,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;;;;;uCAKX,UAAU,CAAC,UAAU,CAAC;;0DAEH,gBAAgB,CAAC,IAAI,CAAC,YAAY,CAAC;oDACzC,gBAAgB,CAAC,OAAO,CAAC;UACnE,eAAe,EAAE;;;CAG1B,CAAC;AACF,CAAC;AAED,SAAS,SAAS,CAAC,IAA0B;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,KAAK,iBAAiB,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;IACzH,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC;AACzD,CAAC;AAED,SAAS,UAAU;IACjB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCR,CAAC;AACF,CAAC;AAED,SAAS,eAAe;IACtB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IAC3C,OAAO;;gBAEO,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4EpB,CAAC;AACF,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE;QACxC,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,GAAG;gBACN,OAAO,OAAO,CAAC;YACjB,KAAK,GAAG;gBACN,OAAO,MAAM,CAAC;YAChB,KAAK,GAAG;gBACN,OAAO,MAAM,CAAC;YAChB,KAAK,IAAI;gBACP,OAAO,QAAQ,CAAC;YAClB;gBACE,OAAO,OAAO,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACtC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;SACzB,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC;SACxB,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC;SACxB,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC;SACxB,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC;SAC7B,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACnC,CAAC"}
|