@hugpy/video-intelligence-ui 0.1.1 → 0.3.1

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 (107) hide show
  1. package/README.md +43 -0
  2. package/index.html +2 -0
  3. package/package.json +1 -4
  4. package/src/config.ts +44 -0
  5. package/src/demo/demoFetch.ts +126 -3
  6. package/src/demo/fixtures.ts +97 -27
  7. package/src/demo/mediaBase.ts +62 -0
  8. package/src/demo/promptAssist.ts +25 -0
  9. package/src/demo/sampleData.ts +961 -0
  10. package/src/demo/sampleSets.ts +173 -0
  11. package/src/stations/ActiveProcessesStation.tsx +18 -3
  12. package/src/stations/GenerateStation.tsx +901 -366
  13. package/src/stations/GoalComposer.tsx +9 -1
  14. package/src/stations/ScriptFirstStation.tsx +1081 -0
  15. package/src/stations/ToksPanel.tsx +188 -0
  16. package/src/stations/WorkbenchDrawer.tsx +4 -3
  17. package/src/stations/WorkbenchSidebar.tsx +6 -3
  18. package/src/stations/oracle/DagPanel.tsx +391 -0
  19. package/src/stations/oracle/OracleStation.tsx +304 -0
  20. package/src/stations/oracle/SpatialTab.tsx +185 -0
  21. package/src/stations/oracle/StewardPanel.tsx +165 -0
  22. package/src/stations/oracle/oracle.css +467 -0
  23. package/src/stations/oracle/oracleShared.tsx +160 -0
  24. package/src/stations/oracle/oracleTypes.ts +304 -0
  25. package/src/stations/oracle/useOracle.ts +560 -0
  26. package/src/stations/registry.ts +37 -0
  27. package/src/stations/scriptFirst.css +350 -0
  28. package/src/stations/studio/IdentitiesStation.tsx +219 -292
  29. package/src/stations/studio/IdentityCreatePanel.tsx +390 -0
  30. package/src/stations/studio/StudioGenerateTab.tsx +10 -17
  31. package/src/stations/studio/StudioMovieComposer.tsx +296 -59
  32. package/src/stations/studio/StudioPlane.tsx +35 -3
  33. package/src/stations/studio/StudioViewer.tsx +116 -14
  34. package/src/stations/studio/coordinationBadge.tsx +206 -0
  35. package/src/stations/studio/identityUpload.ts +66 -0
  36. package/src/stations/studio/promptCard.tsx +362 -59
  37. package/src/stations/studio/useIdentityCreateJob.ts +184 -0
  38. package/src/stations/studio/useIdentityProfiles.ts +66 -0
  39. package/src/stations/useScriptFirstRun.ts +596 -0
  40. package/src/style/app.css +157 -0
  41. package/src/video/LengthRow.tsx +189 -0
  42. package/src/video/coordinationReport.ts +266 -0
  43. package/src/video/jobClock.ts +104 -0
  44. package/src/video/spreadAssist.ts +26 -0
  45. package/src/video/useMediaJobs.ts +26 -0
  46. package/src/video/useOperatorHistory.ts +5 -0
  47. package/src/video/useToks.ts +193 -0
  48. package/assets/sampels/images/bycycle/bd8603bad35d4f179f4d1134d8faf2ee.mp4 +0 -0
  49. package/assets/sampels/images/bycycle/frame_00000.png +0 -0
  50. package/assets/sampels/images/bycycle/frame_00001.png +0 -0
  51. package/assets/sampels/images/bycycle/frame_00002.png +0 -0
  52. package/assets/sampels/images/bycycle/frame_00003.png +0 -0
  53. package/assets/sampels/images/bycycle/frame_00004.png +0 -0
  54. package/assets/sampels/images/bycycle/frame_00005.png +0 -0
  55. package/assets/sampels/images/forrest/ff23090611b844a6b85c224f388bd542.mp4 +0 -0
  56. package/assets/sampels/images/forrest/frame_00000.png +0 -0
  57. package/assets/sampels/images/forrest/frame_00001.png +0 -0
  58. package/assets/sampels/images/forrest/frame_00002.png +0 -0
  59. package/assets/sampels/images/forrest/frame_00003.png +0 -0
  60. package/assets/sampels/images/forrest/frame_00004.png +0 -0
  61. package/assets/sampels/images/forrest/frame_00005.png +0 -0
  62. package/assets/sampels/images/shenzo/e1a4fcd623084ab4a986d11c8cd00db8.mp4 +0 -0
  63. package/assets/sampels/images/shenzo/frame_00000.png +0 -0
  64. package/assets/sampels/images/shenzo/frame_00001.png +0 -0
  65. package/assets/sampels/images/shenzo/frame_00002.png +0 -0
  66. package/assets/sampels/images/shenzo/frame_00003.png +0 -0
  67. package/assets/sampels/images/shenzo/frame_00004.png +0 -0
  68. package/assets/sampels/images/shenzo/frame_00005.png +0 -0
  69. package/assets/sampels/scenes/man.mp4 +0 -0
  70. package/assets/sampels/scenes/woman.mp4 +0 -0
  71. package/assets/sampels/studio_movies/caverns/_assembly/contrib_00.mp4 +0 -0
  72. package/assets/sampels/studio_movies/caverns/movie.json +0 -67
  73. package/assets/sampels/studio_movies/caverns/movie.mp4 +0 -0
  74. package/assets/sampels/studio_movies/caverns/segment_00/5eea7770a554fef0c3bdc38f8f38b925dcf75f13c015d423e8eadec47d41bf6b/clip.mp4 +0 -0
  75. package/assets/sampels/studio_movies/caverns/segment_00/5eea7770a554fef0c3bdc38f8f38b925dcf75f13c015d423e8eadec47d41bf6b/manifest.json +0 -87
  76. package/assets/sampels/studio_movies/caverns/segment_00/5eea7770a554fef0c3bdc38f8f38b925dcf75f13c015d423e8eadec47d41bf6b/provenance.json +0 -7
  77. package/assets/sampels/studio_movies/caverns/segment_01/branch.png +0 -0
  78. package/assets/sampels/studio_movies/keeper-matrix/_assembly/concat_list.txt +0 -2
  79. package/assets/sampels/studio_movies/keeper-matrix/_assembly/contrib_00.mp4 +0 -0
  80. package/assets/sampels/studio_movies/keeper-matrix/_assembly/contrib_01.mp4 +0 -0
  81. package/assets/sampels/studio_movies/keeper-matrix/movie.json +0 -81
  82. package/assets/sampels/studio_movies/keeper-matrix/movie.mp4 +0 -0
  83. package/assets/sampels/studio_movies/keeper-matrix/segment_00/64854c6a21d47ce10b23e884e12de448b25bfb0a375d33238dd0bec8056c076d/clip.mp4 +0 -0
  84. package/assets/sampels/studio_movies/keeper-matrix/segment_00/64854c6a21d47ce10b23e884e12de448b25bfb0a375d33238dd0bec8056c076d/manifest.json +0 -87
  85. package/assets/sampels/studio_movies/keeper-matrix/segment_00/64854c6a21d47ce10b23e884e12de448b25bfb0a375d33238dd0bec8056c076d/provenance.json +0 -7
  86. package/assets/sampels/studio_movies/keeper-matrix/segment_01/branch.png +0 -0
  87. package/assets/sampels/studio_movies/keeper-matrix/segment_01/cc926b44a42b90d7d291a4e50e3859458306c207a17c718086a3466e4049d6c6/clip.mp4 +0 -0
  88. package/assets/sampels/studio_movies/keeper-matrix/segment_01/cc926b44a42b90d7d291a4e50e3859458306c207a17c718086a3466e4049d6c6/manifest.json +0 -87
  89. package/assets/sampels/studio_movies/keeper-matrix/segment_01/cc926b44a42b90d7d291a4e50e3859458306c207a17c718086a3466e4049d6c6/provenance.json +0 -7
  90. package/assets/sampels/videos/a_red_paper_boat_drifting_on_a_calm_pond__gentle_ripples__mo_a62d6c28.mp4 +0 -0
  91. package/assets/sampels/videos/aurora.mp4 +0 -0
  92. package/assets/sampels/videos/dark_night.mp4 +0 -0
  93. package/assets/sampels/videos/fire_and_soul.mp4 +0 -0
  94. package/assets/sampels/videos/harsh_seas.mp4 +0 -0
  95. package/src/demo/assets/demo-audio.mp3 +0 -0
  96. package/src/demo/assets/demo-clip.mp4 +0 -0
  97. package/src/demo/assets/demo-crop.mp4 +0 -0
  98. package/src/demo/assets/demo-poster.jpg +0 -0
  99. package/src/demo/assets/frame-1.jpg +0 -0
  100. package/src/demo/assets/frame-2.jpg +0 -0
  101. package/src/demo/assets/frame-3.jpg +0 -0
  102. package/src/demo/assets/frame-4.jpg +0 -0
  103. package/src/demo/assets/frame-5.jpg +0 -0
  104. package/src/demo/assets/frame-6.jpg +0 -0
  105. package/src/demo/assets/gen-1.jpg +0 -0
  106. package/src/demo/assets/gen-2.jpg +0 -0
  107. package/src/demo/assets.d.ts +0 -14
@@ -0,0 +1,173 @@
1
+ // PRE-RENDERED SAMPLE SETS for the canned /video/generate demo (2026-08-13).
2
+ //
3
+ // The operator's ruling: the demo must NEVER touch a GPU or a model — every
4
+ // "render" is a pre-rendered sample, and the ✨ Generate prompt button hands
5
+ // out the REAL prompts that produced those samples, per section. Source of
6
+ // truth: /mnt/llm_storage/video_intel/generate-samples (each render dir now
7
+ // carries prompt.txt + manifest.json, reconstructed from media_jobs.db where
8
+ // the renders originally shipped without them). A curated ~8 MB subset is
9
+ // bundled here; the full set stays on the share.
10
+ //
11
+ // THE COUPLING CONTRACT (what makes the demo read as real):
12
+ // ✨ assist (mode "generate") → assistPrompt(section) ARMS a sample set and
13
+ // returns its prompt; the next enqueue for that section CONSUMES the armed
14
+ // set, so the media that "renders" is the media that prompt actually made.
15
+ // Generating without assist just round-robins the sets. Selection happens
16
+ // at ENQUEUE (stored on the job) so repeated polls stay stable.
17
+ //
18
+ // Honest exclusions: renders whose real prompt was operator keyboard-mash
19
+ // ("asdasd") keep their on-disk manifest but are not showcased in the assist
20
+ // bank — the demo only advertises prompts worth reading.
21
+
22
+ import type { MediaRef } from "../video/contract";
23
+
24
+ // scene: desert roads (job 187ac900…, sd-turbo, 6 frames @512)
25
+ import { demoMedia } from "./mediaBase";
26
+ const sdF0 = demoMedia("generate/scene-desert/frame_00000.png");
27
+ const sdF1 = demoMedia("generate/scene-desert/frame_00001.png");
28
+ const sdF2 = demoMedia("generate/scene-desert/frame_00002.png");
29
+ const sdF3 = demoMedia("generate/scene-desert/frame_00003.png");
30
+ const sdF4 = demoMedia("generate/scene-desert/frame_00004.png");
31
+ const sdF5 = demoMedia("generate/scene-desert/frame_00005.png");
32
+ const sdClip = demoMedia("generate/scene-desert/scene.mp4");
33
+ // scene: vintage frames (job 69a7bbcf…) — render showcased, prompt not
34
+ const svF0 = demoMedia("generate/scene-vintage/frame_00000.png");
35
+ const svF1 = demoMedia("generate/scene-vintage/frame_00001.png");
36
+ const svF2 = demoMedia("generate/scene-vintage/frame_00002.png");
37
+ const svClip = demoMedia("generate/scene-vintage/scene.mp4");
38
+ // movie: sunny meadow (job 5ca10b84…, 2 goals) + swirling galaxy (1eed0b95…, 4 goals)
39
+ const mmSeg0 = demoMedia("generate/movie-medow/seg_00.mp4");
40
+ const mmSeg1 = demoMedia("generate/movie-medow/seg_01.mp4");
41
+ const mmMovie = demoMedia("generate/movie-medow/movie.mp4");
42
+ const mgSeg0 = demoMedia("generate/movie-galaxy/seg_00.mp4");
43
+ const mgSeg1 = demoMedia("generate/movie-galaxy/seg_01.mp4");
44
+ const mgSeg2 = demoMedia("generate/movie-galaxy/seg_02.mp4");
45
+ const mgSeg3 = demoMedia("generate/movie-galaxy/seg_03.mp4");
46
+ const mgMovie = demoMedia("generate/movie-galaxy/movie.mp4");
47
+ // clips (studio i2v manifests carry the prompts)
48
+ const clCat = demoMedia("generate/clips/cat-lounge.mp4");
49
+ const clDrone = demoMedia("generate/clips/drone-city.mp4");
50
+ const clSails = demoMedia("generate/clips/paper-sails.mp4");
51
+ // cinema: dank cavern (movie.json segment prompts; seg_01 was a branch-only
52
+ // render, so the set is segment_00 + the assembled movie LAST)
53
+ const ccSeg0 = demoMedia("generate/cinema-cavern/seg_00.mp4");
54
+ const ccMovie = demoMedia("generate/cinema-cavern/movie.mp4");
55
+
56
+ function img(id: string, uri: string): MediaRef {
57
+ return { asset_id: id, kind: "image", uri, mime: "image/png",
58
+ width: 512, height: 512, duration_s: null, fps_native: null,
59
+ sample_rate: null, channels: null };
60
+ }
61
+ function vid(id: string, uri: string, dur = 4.0): MediaRef {
62
+ return { asset_id: id, kind: "video", uri, mime: "video/mp4",
63
+ width: 512, height: 512, duration_s: dur, fps_native: 6,
64
+ sample_rate: null, channels: null };
65
+ }
66
+
67
+ export type SectionKind = "image" | "scene" | "movie" | "clip" | "cinema";
68
+
69
+ export interface SampleSet {
70
+ title: string;
71
+ /** The REAL prompt(s) that produced this render (joined for the assist). */
72
+ prompt: string;
73
+ /** Contract-ordered outputs (frames first, assembled clip/movie LAST). */
74
+ outputs: MediaRef[];
75
+ /** Showcased by ✨ generate? (false = render-only; prompt was junk/empty) */
76
+ showcase: boolean;
77
+ }
78
+
79
+ const DESERT_PROMPT =
80
+ "this is the first scene in view. its california and the air is crisp\n\n" +
81
+ "the last frame needs to be the gentlment in the left side having walked allwthe way across";
82
+
83
+ export const SAMPLE_SETS: Record<SectionKind, SampleSet[]> = {
84
+ image: [
85
+ { title: "california crisp", prompt: "this is the first scene in view. its california and the air is crisp",
86
+ outputs: [img("gs-img-desert", sdF0)], showcase: true },
87
+ { title: "meadow still", prompt: "a sunny green meadow with wildflowers",
88
+ outputs: [img("gs-img-vintage", svF0)], showcase: true },
89
+ ],
90
+ scene: [
91
+ { title: "desert roads", prompt: DESERT_PROMPT,
92
+ outputs: [img("gs-sd-0", sdF0), img("gs-sd-1", sdF1), img("gs-sd-2", sdF2),
93
+ img("gs-sd-3", sdF3), img("gs-sd-4", sdF4), img("gs-sd-5", sdF5),
94
+ vid("gs-sd-clip", sdClip)], showcase: true },
95
+ { title: "vintage frames", prompt: "asdasd",
96
+ outputs: [img("gs-sv-0", svF0), img("gs-sv-1", svF1), img("gs-sv-2", svF2),
97
+ vid("gs-sv-clip", svClip)], showcase: false },
98
+ ],
99
+ movie: [
100
+ { title: "sunny meadow", prompt:
101
+ "a sunny green meadow with wildflowers\n\nthe same meadow at golden sunset, warm light",
102
+ outputs: [vid("gs-mm-0", mmSeg0), vid("gs-mm-1", mmSeg1),
103
+ vid("gs-mm-movie", mmMovie, 8.0)], showcase: true },
104
+ { title: "swirling galaxy", prompt:
105
+ "a vast spiral galaxy in deep space, distant wide view, scattered stars\n\n" +
106
+ "zooming toward a glowing blue and purple nebula, cosmic dust\n\n" +
107
+ "a closer view of swirling cosmic gas clouds and brilliant clustered stars\n\n" +
108
+ "a single radiant star filling the frame, blinding light, lens flare",
109
+ outputs: [vid("gs-mg-0", mgSeg0), vid("gs-mg-1", mgSeg1), vid("gs-mg-2", mgSeg2),
110
+ vid("gs-mg-3", mgSeg3), vid("gs-mg-movie", mgMovie, 16.0)], showcase: true },
111
+ ],
112
+ clip: [
113
+ { title: "cat lounge", prompt: "a cat",
114
+ outputs: [vid("gs-cl-cat", clCat)], showcase: true },
115
+ { title: "drone over city lights", prompt: "the same glowing night city, camera slowly orbiting",
116
+ outputs: [vid("gs-cl-drone", clDrone)], showcase: true },
117
+ { title: "paper sails", prompt: "",
118
+ outputs: [vid("gs-cl-sails", clSails)], showcase: false },
119
+ ],
120
+ cinema: [
121
+ { title: "dank cavern", prompt:
122
+ "In a subterranean cavern bathed in the harsh midday sun, a towering structure " +
123
+ "dwarfs its surroundings, casting short, sharp black shadows that dance across " +
124
+ "the cavern's walls. The shot begins with a sweeping establishing view; as the " +
125
+ "camera slowly pushes in, the structure's intricate details come into focus.",
126
+ outputs: [vid("gs-cc-0", ccSeg0), vid("gs-cc-movie", ccMovie, 10.0)], showcase: true },
127
+ ],
128
+ };
129
+
130
+ // ── the assist⇄enqueue coupling ─────────────────────────────────────────────
131
+ const cursors: Record<SectionKind, number> = {
132
+ image: 0, scene: 0, movie: 0, clip: 0, cinema: 0,
133
+ };
134
+ const armed: Partial<Record<SectionKind, SampleSet>> = {};
135
+
136
+ function showcased(kind: SectionKind): SampleSet[] {
137
+ const all = SAMPLE_SETS[kind];
138
+ const s = all.filter((x) => x.showcase);
139
+ return s.length ? s : all;
140
+ }
141
+
142
+ /** ✨ generate: arm the next showcased set for `kind` and return its prompt. */
143
+ export function assistPrompt(kind: SectionKind): string {
144
+ const sets = showcased(kind);
145
+ const set = sets[cursors[kind] % sets.length];
146
+ cursors[kind] = (cursors[kind] + 1) % sets.length;
147
+ armed[kind] = set;
148
+ return set.prompt;
149
+ }
150
+
151
+ let rr: Record<SectionKind, number> = { image: 0, scene: 0, movie: 0, clip: 0, cinema: 0 };
152
+
153
+ /** Enqueue-time selection: the armed set if ✨ ran, else round-robin. */
154
+ export function takeSet(kind: SectionKind): SampleSet {
155
+ const a = armed[kind];
156
+ if (a) { delete armed[kind]; return a; }
157
+ const sets = showcased(kind);
158
+ const set = sets[rr[kind] % sets.length];
159
+ rr[kind] = (rr[kind] + 1) % sets.length;
160
+ return set;
161
+ }
162
+
163
+ /** Map an assist/job context kind onto a sample section. */
164
+ export function sectionFor(kind: string): SectionKind {
165
+ if (kind === "image" || kind === "scene" || kind === "movie" || kind === "clip" || kind === "cinema")
166
+ return kind;
167
+ if (kind === "generate_image") return "image";
168
+ if (kind === "generate_scene") return "scene";
169
+ if (kind === "generate_movie") return "movie";
170
+ if (kind === "studio_i2v") return "clip";
171
+ if (kind === "generate_studio_movie") return "cinema";
172
+ return "scene";
173
+ }
@@ -32,11 +32,13 @@ import {
32
32
  placementLine,
33
33
  isExternal,
34
34
  reservedGib,
35
- elapsedSince,
36
35
  progressLabel,
37
36
  latestEvent,
38
37
  type MediaJob,
39
38
  } from "../video/useMediaJobs";
39
+ // k117 — the honest clock/stage helpers. Kept OUT of this component so the
40
+ // studio's Sessions sections (which reuse JobRow) get the same fix for free.
41
+ import { jobClockParts, jobStageLabel, terminalAtStage } from "../video/jobClock";
40
42
 
41
43
  function PhaseChip({ job }: { job: MediaJob }) {
42
44
  if (job.phase === "awaiting_capacity") {
@@ -129,8 +131,21 @@ export function JobRow({
129
131
  </span>
130
132
  ) : null}
131
133
  {gib ? <span>· {gib}</span> : null}
132
- {j.stage ? <span>· {j.stage}</span> : null}
133
- <span>· {elapsedSince(j.createdAt)}</span>
134
+ {/* k117: the stage label and the clock, told honestly. A TERMINAL row
135
+ says what it ENDED as (with the stage it was in as a parenthetical)
136
+ and shows its FROZEN duration; a live row shows time-in-stage and
137
+ queue-wait as separate chips. Both come from the server's lifecycle
138
+ fields — nothing here counts off the browser clock, which is what
139
+ made a 9.4s render read as "946m · archiving". */}
140
+ {jobStageLabel(j) ? <span>· {jobStageLabel(j)}</span> : null}
141
+ {terminalAtStage(j) ? (
142
+ <span className="vi-knob-hint" title="the stage it was in when it ended">
143
+ (in {terminalAtStage(j)})
144
+ </span>
145
+ ) : null}
146
+ {jobClockParts(j).map((part) => (
147
+ <span key={part}>· {part}</span>
148
+ ))}
134
149
  </div>
135
150
  <ProgressBar job={j} />
136
151
  {event ? <p className="vi-job-latest">{event}</p> : null}