@tangle-network/agent-app 0.11.0 → 0.12.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 (42) hide show
  1. package/dist/TimelineEditor-OXPJZDP2.js +12 -0
  2. package/dist/TimelineEditor-OXPJZDP2.js.map +1 -0
  3. package/dist/apply-Cp8c3K9D.d.ts +249 -0
  4. package/dist/billing/index.js +1 -1
  5. package/dist/chunk-3WAJWYKD.js +1730 -0
  6. package/dist/chunk-3WAJWYKD.js.map +1 -0
  7. package/dist/chunk-CF5DZELC.js +111 -0
  8. package/dist/chunk-CF5DZELC.js.map +1 -0
  9. package/dist/{chunk-4YTWB5MG.js → chunk-ETX4O4BB.js} +98 -1
  10. package/dist/chunk-ETX4O4BB.js.map +1 -0
  11. package/dist/{chunk-YS6A6G57.js → chunk-G3HCU7TA.js} +37 -4
  12. package/dist/chunk-G3HCU7TA.js.map +1 -0
  13. package/dist/chunk-IHR6K3GF.js +2367 -0
  14. package/dist/chunk-IHR6K3GF.js.map +1 -0
  15. package/dist/{chunk-OLCVUGGI.js → chunk-IJZJWKUK.js} +1 -61
  16. package/dist/chunk-IJZJWKUK.js.map +1 -0
  17. package/dist/{chunk-EYXTDVDY.js → chunk-SAOAAA3S.js} +2 -2
  18. package/dist/chunk-ZYBWGSAZ.js +130 -0
  19. package/dist/chunk-ZYBWGSAZ.js.map +1 -0
  20. package/dist/index.d.ts +6 -2
  21. package/dist/index.js +130 -8
  22. package/dist/mcp-CIupfjxV.d.ts +112 -0
  23. package/dist/preset-cloudflare/index.js +2 -2
  24. package/dist/runtime/index.d.ts +108 -1
  25. package/dist/runtime/index.js +7 -1
  26. package/dist/sequences/drizzle.d.ts +1244 -0
  27. package/dist/sequences/drizzle.js +368 -0
  28. package/dist/sequences/drizzle.js.map +1 -0
  29. package/dist/sequences/index.d.ts +327 -0
  30. package/dist/sequences/index.js +114 -0
  31. package/dist/sequences/index.js.map +1 -0
  32. package/dist/sequences-react/index.d.ts +752 -0
  33. package/dist/sequences-react/index.js +241 -0
  34. package/dist/sequences-react/index.js.map +1 -0
  35. package/dist/store-gckrNq-g.d.ts +242 -0
  36. package/dist/tools/index.d.ts +24 -108
  37. package/dist/tools/index.js +12 -6
  38. package/package.json +37 -2
  39. package/dist/chunk-4YTWB5MG.js.map +0 -1
  40. package/dist/chunk-OLCVUGGI.js.map +0 -1
  41. package/dist/chunk-YS6A6G57.js.map +0 -1
  42. /package/dist/{chunk-EYXTDVDY.js.map → chunk-SAOAAA3S.js.map} +0 -0
@@ -0,0 +1,241 @@
1
+ import {
2
+ COMMAND_HISTORY_LIMIT,
3
+ DEFAULT_MAX_MEDIA_ELEMENTS,
4
+ PreviewCanvas,
5
+ SEEK_TIMEOUT_MS,
6
+ SEEK_TOLERANCE_SECONDS,
7
+ SEQUENCE_MEDIA_DRAG_TYPE,
8
+ SnapIndicatorLine,
9
+ TimelineClipChip,
10
+ TimelineEditor,
11
+ TimelinePlayhead,
12
+ TimelineRuler,
13
+ TimelineTrackRow,
14
+ ZoomControl,
15
+ addCaptionCommand,
16
+ applySnap,
17
+ captionFontPx,
18
+ chooseMoveSnap,
19
+ classifyMediaUrl,
20
+ clipChipGeometry,
21
+ collectSnapPoints,
22
+ compositeCommand,
23
+ computeWaveform,
24
+ containFitRect,
25
+ createCommandStack,
26
+ createImageFrameProvider,
27
+ createMediaElementPool,
28
+ createPlaybackClock,
29
+ createVideoElementFrameProvider,
30
+ createZoomMath,
31
+ deleteClipCommand,
32
+ drawWaveform,
33
+ frameToPixel,
34
+ framesFromPixelDelta,
35
+ letterboxRect,
36
+ loadWaveform,
37
+ moveClipCommand,
38
+ moveDragStartFrame,
39
+ needsSeek,
40
+ pixelToFrame,
41
+ placeClipCommand,
42
+ selectTickStepSeconds,
43
+ setClipTextCommand,
44
+ snapPixel,
45
+ splitClipCommand,
46
+ toggleClipDisabledCommand,
47
+ trimClipCommand,
48
+ trimEndDrag,
49
+ trimStartDrag
50
+ } from "../chunk-IHR6K3GF.js";
51
+ import "../chunk-ZYBWGSAZ.js";
52
+
53
+ // src/sequences-react/media/transcription.ts
54
+ var DEFAULT_WHISPER_MODEL = "onnx-community/whisper-large-v3-turbo";
55
+ var WHISPER_SAMPLE_RATE = 16e3;
56
+ var TRANSCRIPTION_PEER = "@huggingface/transformers";
57
+ var PEER_MISSING_MESSAGE = "transcription requires optional peer @huggingface/transformers";
58
+ function mixdownToMono(buffer) {
59
+ if (buffer.numberOfChannels < 1) throw new Error("audio buffer has no channels \u2014 cannot mix down");
60
+ if (buffer.numberOfChannels === 1) return buffer.getChannelData(0);
61
+ const mono = new Float32Array(buffer.length);
62
+ for (let channel = 0; channel < buffer.numberOfChannels; channel++) {
63
+ const data = buffer.getChannelData(channel);
64
+ if (data.length !== buffer.length) {
65
+ throw new Error(`channel ${channel} has ${data.length} samples, expected ${buffer.length}`);
66
+ }
67
+ for (let i = 0; i < data.length; i++) {
68
+ mono[i] = mono[i] + data[i];
69
+ }
70
+ }
71
+ const scale = 1 / buffer.numberOfChannels;
72
+ for (let i = 0; i < mono.length; i++) {
73
+ mono[i] = mono[i] * scale;
74
+ }
75
+ return mono;
76
+ }
77
+ function mapWhisperOutput(output, durationSeconds, mediaUrl) {
78
+ const first = Array.isArray(output) ? output[0] : output;
79
+ if (first === void 0) throw new Error(`whisper produced no output for ${mediaUrl}`);
80
+ const chunks = first.chunks;
81
+ if (chunks === void 0 || chunks.length === 0) {
82
+ const text = first.text.trim();
83
+ return text.length === 0 ? [] : [{ text, startSeconds: 0, endSeconds: durationSeconds }];
84
+ }
85
+ const segments = [];
86
+ for (const chunk of chunks) {
87
+ const text = chunk.text.trim();
88
+ if (text.length === 0) continue;
89
+ const [start, end] = chunk.timestamp;
90
+ if (!Number.isFinite(start)) {
91
+ throw new Error(`whisper returned a non-numeric start timestamp for "${text}" in ${mediaUrl}`);
92
+ }
93
+ segments.push({ text, startSeconds: start, endSeconds: end === null ? durationSeconds : end });
94
+ }
95
+ return segments;
96
+ }
97
+ async function loadTransformers() {
98
+ try {
99
+ return await import(
100
+ /* @vite-ignore */
101
+ /* webpackIgnore: true */
102
+ TRANSCRIPTION_PEER
103
+ );
104
+ } catch (error) {
105
+ throw new Error(PEER_MISSING_MESSAGE, { cause: error });
106
+ }
107
+ }
108
+ async function fetchMonoAudio(mediaUrl) {
109
+ const response = await fetch(mediaUrl);
110
+ if (!response.ok) {
111
+ throw new Error(`failed to fetch media for transcription: ${response.status} ${response.statusText} from ${mediaUrl}`);
112
+ }
113
+ const bytes = await response.arrayBuffer();
114
+ if (typeof OfflineAudioContext === "undefined") {
115
+ throw new Error("transcription requires Web Audio (OfflineAudioContext) \u2014 call transcribe() from a browser");
116
+ }
117
+ const context = new OfflineAudioContext(1, 1, WHISPER_SAMPLE_RATE);
118
+ const decoded = await context.decodeAudioData(bytes);
119
+ return { samples: mixdownToMono(decoded), durationSeconds: decoded.duration };
120
+ }
121
+ function createWhisperTranscriptionProvider(opts) {
122
+ const model = opts?.model ?? DEFAULT_WHISPER_MODEL;
123
+ let availability = null;
124
+ let pipelinePromise = null;
125
+ const probeAvailability = () => {
126
+ if (availability !== null) return availability;
127
+ const resolve = import.meta.resolve;
128
+ if (typeof resolve !== "function") {
129
+ availability = false;
130
+ return availability;
131
+ }
132
+ try {
133
+ resolve.call(import.meta, TRANSCRIPTION_PEER);
134
+ availability = true;
135
+ } catch {
136
+ availability = false;
137
+ }
138
+ return availability;
139
+ };
140
+ const getPipeline = (transformers, onProgress) => {
141
+ if (pipelinePromise === null) {
142
+ const device = typeof navigator !== "undefined" && "gpu" in navigator ? "webgpu" : "wasm";
143
+ pipelinePromise = transformers.pipeline("automatic-speech-recognition", model, {
144
+ dtype: "q4",
145
+ device,
146
+ // Model download progress only — it dwarfs inference time on first
147
+ // use, and only the first transcribe ever sees a download.
148
+ progress_callback: (event) => {
149
+ if (event.status === "progress" && typeof event.progress === "number" && onProgress !== void 0) {
150
+ onProgress(Math.min(1, Math.max(0, event.progress / 100)));
151
+ }
152
+ }
153
+ });
154
+ pipelinePromise.catch(() => {
155
+ pipelinePromise = null;
156
+ });
157
+ }
158
+ return pipelinePromise;
159
+ };
160
+ return {
161
+ get available() {
162
+ return probeAvailability();
163
+ },
164
+ async transcribe(mediaUrl, transcribeOpts) {
165
+ const transformers = await loadTransformers();
166
+ availability = true;
167
+ const audio = await fetchMonoAudio(mediaUrl);
168
+ const transcriber = await getPipeline(transformers, transcribeOpts?.onProgress);
169
+ const options = {
170
+ return_timestamps: true,
171
+ chunk_length_s: 30,
172
+ stride_length_s: 5
173
+ };
174
+ if (transcribeOpts?.language !== void 0) options.language = transcribeOpts.language;
175
+ const output = await transcriber(audio.samples, options);
176
+ const segments = mapWhisperOutput(output, audio.durationSeconds, mediaUrl);
177
+ transcribeOpts?.onProgress?.(1);
178
+ return segments;
179
+ }
180
+ };
181
+ }
182
+
183
+ // src/sequences-react/lazy.tsx
184
+ import React from "react";
185
+ var SequenceTimelineEditorLazy = React.lazy(() => import("../TimelineEditor-OXPJZDP2.js"));
186
+ export {
187
+ COMMAND_HISTORY_LIMIT,
188
+ DEFAULT_MAX_MEDIA_ELEMENTS,
189
+ DEFAULT_WHISPER_MODEL,
190
+ PreviewCanvas,
191
+ SEEK_TIMEOUT_MS,
192
+ SEEK_TOLERANCE_SECONDS,
193
+ SEQUENCE_MEDIA_DRAG_TYPE,
194
+ SequenceTimelineEditorLazy,
195
+ SnapIndicatorLine,
196
+ TimelineClipChip,
197
+ TimelineEditor,
198
+ TimelinePlayhead,
199
+ TimelineRuler,
200
+ TimelineTrackRow,
201
+ ZoomControl,
202
+ addCaptionCommand,
203
+ applySnap,
204
+ captionFontPx,
205
+ chooseMoveSnap,
206
+ classifyMediaUrl,
207
+ clipChipGeometry,
208
+ collectSnapPoints,
209
+ compositeCommand,
210
+ computeWaveform,
211
+ containFitRect,
212
+ createCommandStack,
213
+ createImageFrameProvider,
214
+ createMediaElementPool,
215
+ createPlaybackClock,
216
+ createVideoElementFrameProvider,
217
+ createWhisperTranscriptionProvider,
218
+ createZoomMath,
219
+ deleteClipCommand,
220
+ drawWaveform,
221
+ frameToPixel,
222
+ framesFromPixelDelta,
223
+ letterboxRect,
224
+ loadWaveform,
225
+ mapWhisperOutput,
226
+ mixdownToMono,
227
+ moveClipCommand,
228
+ moveDragStartFrame,
229
+ needsSeek,
230
+ pixelToFrame,
231
+ placeClipCommand,
232
+ selectTickStepSeconds,
233
+ setClipTextCommand,
234
+ snapPixel,
235
+ splitClipCommand,
236
+ toggleClipDisabledCommand,
237
+ trimClipCommand,
238
+ trimEndDrag,
239
+ trimStartDrag
240
+ };
241
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/sequences-react/media/transcription.ts","../../src/sequences-react/lazy.tsx"],"sourcesContent":["/**\n * Whisper transcription behind the `TranscriptionProvider` seam, powered by\n * the OPTIONAL peer `@huggingface/transformers`. The peer is loaded with a\n * dynamic variable-specifier import inside `transcribe()` so bundlers leave\n * it external and apps that never transcribe never pay for it. `available`\n * is the sync UI affordance signal; `transcribe()` re-verifies with the real\n * import and is the source of truth.\n */\n\nimport type { TranscriptionProvider, TranscriptionSegment } from '../contracts'\nimport type { AudioBufferLike } from './waveform'\n\nexport const DEFAULT_WHISPER_MODEL = 'onnx-community/whisper-large-v3-turbo'\n\n/** Whisper models are trained on 16 kHz mono — decoding through a 16 kHz\n * OfflineAudioContext resamples any source rate in one step. */\nconst WHISPER_SAMPLE_RATE = 16_000\n\nconst TRANSCRIPTION_PEER = '@huggingface/transformers'\nconst PEER_MISSING_MESSAGE = 'transcription requires optional peer @huggingface/transformers'\n\ninterface WhisperChunk {\n text: string\n timestamp: [number, number | null]\n}\n\nexport interface WhisperOutput {\n text: string\n chunks?: WhisperChunk[]\n}\n\ntype WhisperPipeline = (\n audio: Float32Array,\n options: Record<string, unknown>,\n) => Promise<WhisperOutput | WhisperOutput[]>\n\ninterface TransformersProgressEvent {\n status: string\n progress?: number\n}\n\ninterface TransformersModule {\n pipeline(\n task: 'automatic-speech-recognition',\n model: string,\n options?: Record<string, unknown>,\n ): Promise<WhisperPipeline>\n}\n\n/** Mean-mixdown to mono. Single-channel buffers return the live channel data\n * without copying — callers must treat the result as read-only. */\nexport function mixdownToMono(buffer: AudioBufferLike): Float32Array {\n if (buffer.numberOfChannels < 1) throw new Error('audio buffer has no channels — cannot mix down')\n if (buffer.numberOfChannels === 1) return buffer.getChannelData(0)\n const mono = new Float32Array(buffer.length)\n for (let channel = 0; channel < buffer.numberOfChannels; channel++) {\n const data = buffer.getChannelData(channel)\n if (data.length !== buffer.length) {\n throw new Error(`channel ${channel} has ${data.length} samples, expected ${buffer.length}`)\n }\n for (let i = 0; i < data.length; i++) {\n // in range by the length assertion above; casts silence noUncheckedIndexedAccess\n mono[i] = (mono[i] as number) + (data[i] as number)\n }\n }\n const scale = 1 / buffer.numberOfChannels\n for (let i = 0; i < mono.length; i++) {\n mono[i] = (mono[i] as number) * scale\n }\n return mono\n}\n\n/** Map whisper chunk output to contract segments. A `null` end timestamp is\n * whisper's \"ran past the end of the audio\" sentinel on the final chunk and\n * resolves to the audio duration. */\nexport function mapWhisperOutput(\n output: WhisperOutput | WhisperOutput[],\n durationSeconds: number,\n mediaUrl: string,\n): TranscriptionSegment[] {\n const first = Array.isArray(output) ? output[0] : output\n if (first === undefined) throw new Error(`whisper produced no output for ${mediaUrl}`)\n const chunks = first.chunks\n if (chunks === undefined || chunks.length === 0) {\n const text = first.text.trim()\n return text.length === 0 ? [] : [{ text, startSeconds: 0, endSeconds: durationSeconds }]\n }\n const segments: TranscriptionSegment[] = []\n for (const chunk of chunks) {\n const text = chunk.text.trim()\n if (text.length === 0) continue\n const [start, end] = chunk.timestamp\n if (!Number.isFinite(start)) {\n throw new Error(`whisper returned a non-numeric start timestamp for \"${text}\" in ${mediaUrl}`)\n }\n segments.push({ text, startSeconds: start, endSeconds: end === null ? durationSeconds : end })\n }\n return segments\n}\n\nasync function loadTransformers(): Promise<TransformersModule> {\n try {\n // Variable specifier + ignore pragmas keep bundlers from statically\n // resolving an optional peer that may not be installed.\n return (await import(/* @vite-ignore */ /* webpackIgnore: true */ TRANSCRIPTION_PEER)) as TransformersModule\n } catch (error) {\n throw new Error(PEER_MISSING_MESSAGE, { cause: error })\n }\n}\n\nasync function fetchMonoAudio(mediaUrl: string): Promise<{ samples: Float32Array; durationSeconds: number }> {\n const response = await fetch(mediaUrl)\n if (!response.ok) {\n throw new Error(`failed to fetch media for transcription: ${response.status} ${response.statusText} from ${mediaUrl}`)\n }\n const bytes = await response.arrayBuffer()\n if (typeof OfflineAudioContext === 'undefined') {\n throw new Error('transcription requires Web Audio (OfflineAudioContext) — call transcribe() from a browser')\n }\n // decodeAudioData resamples to the context rate per the Web Audio spec, so\n // a 16 kHz context yields whisper-ready samples from any source rate.\n const context = new OfflineAudioContext(1, 1, WHISPER_SAMPLE_RATE)\n const decoded = await context.decodeAudioData(bytes)\n return { samples: mixdownToMono(decoded), durationSeconds: decoded.duration }\n}\n\nexport function createWhisperTranscriptionProvider(opts?: { model?: string }): TranscriptionProvider {\n const model = opts?.model ?? DEFAULT_WHISPER_MODEL\n let availability: boolean | null = null\n let pipelinePromise: Promise<WhisperPipeline> | null = null\n\n const probeAvailability = (): boolean => {\n if (availability !== null) return availability\n const resolve = (import.meta as ImportMeta & { resolve?: (specifier: string) => string }).resolve\n if (typeof resolve !== 'function') {\n // No sync resolver in this runtime — report unavailable rather than\n // guess; transcribe() still attempts the real import either way.\n availability = false\n return availability\n }\n try {\n resolve.call(import.meta, TRANSCRIPTION_PEER)\n availability = true\n } catch {\n availability = false\n }\n return availability\n }\n\n const getPipeline = (\n transformers: TransformersModule,\n onProgress?: (fraction: number) => void,\n ): Promise<WhisperPipeline> => {\n if (pipelinePromise === null) {\n const device = typeof navigator !== 'undefined' && 'gpu' in navigator ? 'webgpu' : 'wasm'\n pipelinePromise = transformers.pipeline('automatic-speech-recognition', model, {\n dtype: 'q4',\n device,\n // Model download progress only — it dwarfs inference time on first\n // use, and only the first transcribe ever sees a download.\n progress_callback: (event: TransformersProgressEvent) => {\n if (event.status === 'progress' && typeof event.progress === 'number' && onProgress !== undefined) {\n onProgress(Math.min(1, Math.max(0, event.progress / 100)))\n }\n },\n })\n // A failed load must not poison the cache — the next transcribe retries.\n pipelinePromise.catch(() => {\n pipelinePromise = null\n })\n }\n return pipelinePromise\n }\n\n return {\n get available() {\n return probeAvailability()\n },\n async transcribe(mediaUrl, transcribeOpts) {\n const transformers = await loadTransformers()\n // A successful import is ground truth and overrides a false probe.\n availability = true\n const audio = await fetchMonoAudio(mediaUrl)\n const transcriber = await getPipeline(transformers, transcribeOpts?.onProgress)\n const options: Record<string, unknown> = {\n return_timestamps: true,\n chunk_length_s: 30,\n stride_length_s: 5,\n }\n if (transcribeOpts?.language !== undefined) options.language = transcribeOpts.language\n const output = await transcriber(audio.samples, options)\n const segments = mapWhisperOutput(output, audio.durationSeconds, mediaUrl)\n transcribeOpts?.onProgress?.(1)\n return segments\n },\n }\n}\n","/**\n * Code-split entry for the timeline editor. The editor pulls in canvas\n * painting, waveform decode, and gesture machinery products only need on the\n * sequence route — `React.lazy` keeps it out of their main bundle. Mount\n * inside a `<Suspense>` boundary.\n */\n\nimport React from 'react'\n\nexport const SequenceTimelineEditorLazy = React.lazy(() => import('./components/TimelineEditor'))\n"],"mappings":"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","names":[]}
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Frame-accurate sequence timeline model — the product-agnostic spine of the
3
+ * sequences surface. A sequence is a fixed-fps, fixed-duration timeline of
4
+ * tracks; clips sit on tracks at integer frame positions with non-destructive
5
+ * source in/out points. Products bind this model to their own storage through
6
+ * `SequenceStore` (./store) and surface it to agents through the MCP toolset
7
+ * (./mcp).
8
+ *
9
+ * All positions and durations are integer FRAMES at the sequence's fps.
10
+ * Seconds appear only at the API edge (agent tools speak seconds; the
11
+ * dispatcher converts exactly once). Nothing here touches a database, the DOM,
12
+ * or React.
13
+ */
14
+ declare const MIN_SEQUENCE_CLIP_FRAMES = 1;
15
+ /** Track kinds. `reference` holds non-rendered guide media; `agent` holds the
16
+ * agent-decision lane rendered as markers, never as media. */
17
+ type SequenceTrackKind = 'video' | 'audio' | 'caption' | 'reference' | 'agent';
18
+ type SequenceStatus = 'draft' | 'active' | 'exporting' | 'archived';
19
+ type SequenceExportFormat = 'mp4' | 'otio' | 'xml' | 'edl' | 'vtt' | 'srt' | 'contact_sheet';
20
+ type SequenceExportStatus = 'queued' | 'processing' | 'completed' | 'failed' | 'cancelled';
21
+ type SequenceMediaKind = 'video' | 'image' | 'audio';
22
+ interface SequenceMeta {
23
+ id: string;
24
+ title: string;
25
+ fps: number;
26
+ width: number;
27
+ height: number;
28
+ aspectRatio: string;
29
+ durationFrames: number;
30
+ status: SequenceStatus;
31
+ metadata: Record<string, unknown>;
32
+ }
33
+ interface SequenceTrack {
34
+ id: string;
35
+ kind: SequenceTrackKind;
36
+ name: string;
37
+ sortOrder: number;
38
+ locked: boolean;
39
+ muted: boolean;
40
+ metadata: Record<string, unknown>;
41
+ }
42
+ /** Resolved playable media behind a clip. The store resolves product-specific
43
+ * references (generation rows, asset rows) into this shape; the core model
44
+ * never sees the product's tables. */
45
+ interface SequenceClipMedia {
46
+ url: string;
47
+ kind: SequenceMediaKind;
48
+ /** Natural duration of the source media when known. */
49
+ durationSeconds?: number;
50
+ /** Provider job state for media still rendering upstream. */
51
+ providerStatus?: 'queued' | 'processing' | 'completed' | 'failed';
52
+ }
53
+ interface SequenceClip {
54
+ id: string;
55
+ trackId: string;
56
+ label: string;
57
+ startFrame: number;
58
+ durationFrames: number;
59
+ /** Source-relative in point (frames into the source media). */
60
+ sourceInFrame: number;
61
+ /** Source-relative out point; null = natural end of the source. */
62
+ sourceOutFrame: number | null;
63
+ disabled: boolean;
64
+ /** Caption/text body for clips on caption tracks. */
65
+ text?: string;
66
+ /** BCP-47 language tag for caption clips (e.g. 'en', 'es', 'ja'). */
67
+ language?: string;
68
+ /** Opaque product reference to a generation row, when the clip came from one. */
69
+ generationId?: string;
70
+ /** Opaque product reference to an asset row, when the clip came from one. */
71
+ assetId?: string;
72
+ media?: SequenceClipMedia;
73
+ metadata: Record<string, unknown>;
74
+ }
75
+ /** One entry in the sequence's decision log — human edits, agent proposals,
76
+ * agent edits, exports, and notes all land here so the edit history is a
77
+ * single auditable lane. */
78
+ interface SequenceDecision {
79
+ id: string;
80
+ clipId: string | null;
81
+ kind: 'human_edit' | 'agent_proposal' | 'agent_edit' | 'export' | 'note';
82
+ instruction: string;
83
+ reasoningSummary: string | null;
84
+ accepted: boolean | null;
85
+ metadata: Record<string, unknown>;
86
+ createdAt: Date;
87
+ }
88
+ interface SequenceExportRecord {
89
+ id: string;
90
+ format: SequenceExportFormat;
91
+ status: SequenceExportStatus;
92
+ resultUrl: string | null;
93
+ metadata: Record<string, unknown>;
94
+ createdAt: Date;
95
+ }
96
+ /** The full timeline aggregate — what `get_timeline_state` returns and what
97
+ * every operation validates against. */
98
+ interface SequenceTimeline {
99
+ sequence: SequenceMeta;
100
+ tracks: SequenceTrack[];
101
+ clips: SequenceClip[];
102
+ }
103
+ /** What is on screen/audible at a single frame — the answer shape for
104
+ * "what is happening at 0:34". */
105
+ interface SequenceFrameSnapshot {
106
+ frame: number;
107
+ seconds: number;
108
+ /** Active (enabled, in-range) clips at this frame, with their track. */
109
+ active: Array<{
110
+ track: SequenceTrack;
111
+ clip: SequenceClip;
112
+ }>;
113
+ /** Caption text visible at this frame, in track sort order. */
114
+ captions: Array<{
115
+ text: string;
116
+ language?: string;
117
+ clipId: string;
118
+ }>;
119
+ }
120
+ declare function secondsToFrames(seconds: number, fps: number): number;
121
+ declare function framesToSeconds(frames: number, fps: number): number;
122
+ declare function formatSeconds(seconds: number): string;
123
+ /** `m:ss.ff` timecode for UI and agent-readable frame references. */
124
+ declare function formatTimecode(frames: number, fps: number): string;
125
+ interface TimelineClipBounds {
126
+ startFrame: number;
127
+ durationFrames: number;
128
+ }
129
+ interface TimelineInterval {
130
+ startFrame: number;
131
+ endFrame: number;
132
+ }
133
+ declare function clampClipStart(input: {
134
+ startFrame: number;
135
+ durationFrames: number;
136
+ sequenceDurationFrames: number;
137
+ }): number;
138
+ declare function clampClipDuration(input: {
139
+ startFrame: number;
140
+ durationFrames: number;
141
+ sequenceDurationFrames: number;
142
+ }): number;
143
+ declare function assertClipFitsSequence(input: {
144
+ startFrame: number;
145
+ durationFrames: number;
146
+ sequenceDurationFrames: number;
147
+ label: string;
148
+ }): void;
149
+ /** Place a caption near the playhead inside FREE space only — the caption
150
+ * track never double-books. Prefers fps*3 frames, floors at fps. The gap
151
+ * holding (or first after) the playhead wins; with everything ahead occupied
152
+ * the latest earlier gap is used instead. Throws when no gap can hold the
153
+ * minimum — the caller must supply explicit bounds or clear space. */
154
+ declare function chooseCaptionPlacement(input: {
155
+ playheadFrame: number;
156
+ fps: number;
157
+ sequenceDurationFrames: number;
158
+ occupiedIntervals: TimelineInterval[];
159
+ }): TimelineClipBounds;
160
+ /** Resolve everything active at one frame — the core of `get_frame_at_time`. */
161
+ declare function snapshotFrame(timeline: SequenceTimeline, frame: number): SequenceFrameSnapshot;
162
+ /** Occupied intervals on one track, for placement collision checks. */
163
+ declare function trackIntervals(timeline: SequenceTimeline, trackId: string): TimelineInterval[];
164
+
165
+ /**
166
+ * Storage contract binding the sequence model to a product's database. The
167
+ * product constructs one store per (workspace, sequence, actor) request scope —
168
+ * RBAC and workspace isolation happen BEFORE construction (the product's
169
+ * `requireWorkspaceAccess` equivalent); the store never re-checks identity.
170
+ *
171
+ * Every method throws on failure — no silent nulls, no `{ ok: false }` wrappers
172
+ * at this layer. The MCP dispatcher (./mcp) is the boundary that converts
173
+ * thrown errors into structured tool errors the model can read and react to.
174
+ *
175
+ * Mutations append to the decision log themselves only when the operation
176
+ * dispatcher asks (`recordDecision`); plain CRUD stays log-free so human edits
177
+ * driven by the UI can batch their own decision entries.
178
+ */
179
+
180
+ interface NewSequenceTrack {
181
+ kind: SequenceTrackKind;
182
+ name: string;
183
+ sortOrder?: number;
184
+ }
185
+ interface NewSequenceClip {
186
+ trackId: string;
187
+ label: string;
188
+ startFrame: number;
189
+ durationFrames: number;
190
+ sourceInFrame?: number;
191
+ sourceOutFrame?: number | null;
192
+ text?: string;
193
+ language?: string;
194
+ generationId?: string;
195
+ assetId?: string;
196
+ metadata?: Record<string, unknown>;
197
+ }
198
+ interface SequenceClipPatch {
199
+ trackId?: string;
200
+ label?: string;
201
+ startFrame?: number;
202
+ durationFrames?: number;
203
+ sourceInFrame?: number;
204
+ sourceOutFrame?: number | null;
205
+ disabled?: boolean;
206
+ text?: string;
207
+ language?: string;
208
+ metadata?: Record<string, unknown>;
209
+ }
210
+ interface NewSequenceDecision {
211
+ clipId?: string | null;
212
+ kind: SequenceDecision['kind'];
213
+ instruction: string;
214
+ reasoningSummary?: string | null;
215
+ accepted?: boolean | null;
216
+ metadata?: Record<string, unknown>;
217
+ }
218
+ interface SequenceStore {
219
+ /** Full aggregate: sequence meta + tracks + clips with resolved media. */
220
+ getTimeline(): Promise<SequenceTimeline>;
221
+ getClip(clipId: string): Promise<SequenceClip>;
222
+ createTrack(input: NewSequenceTrack): Promise<SequenceTrack>;
223
+ createClip(input: NewSequenceClip): Promise<SequenceClip>;
224
+ updateClip(clipId: string, patch: SequenceClipPatch): Promise<SequenceClip>;
225
+ deleteClip(clipId: string): Promise<void>;
226
+ /** Grow (or shrink, never below the last clip end) the sequence duration. */
227
+ updateSequenceDuration(durationFrames: number): Promise<SequenceMeta>;
228
+ recordDecision(input: NewSequenceDecision): Promise<SequenceDecision>;
229
+ createExport(format: SequenceExportFormat, metadata?: Record<string, unknown>): Promise<SequenceExportRecord>;
230
+ listDecisions(limit?: number): Promise<SequenceDecision[]>;
231
+ listExports(limit?: number): Promise<SequenceExportRecord[]>;
232
+ }
233
+ /** Per-request scope a product binds when constructing its store. Carried so
234
+ * decision rows and export rows attribute to the acting user; never trusted
235
+ * from tool arguments. */
236
+ interface SequenceStoreScope {
237
+ workspaceId: string;
238
+ sequenceId: string;
239
+ userId: string;
240
+ }
241
+
242
+ export { snapshotFrame as A, trackIntervals as B, MIN_SEQUENCE_CLIP_FRAMES as M, type NewSequenceClip as N, type SequenceClip as S, type TimelineClipBounds as T, type NewSequenceDecision as a, type NewSequenceTrack as b, type SequenceClipMedia as c, type SequenceClipPatch as d, type SequenceDecision as e, type SequenceExportFormat as f, type SequenceExportRecord as g, type SequenceExportStatus as h, type SequenceFrameSnapshot as i, type SequenceMediaKind as j, type SequenceMeta as k, type SequenceStatus as l, type SequenceStore as m, type SequenceStoreScope as n, type SequenceTimeline as o, type SequenceTrack as p, type SequenceTrackKind as q, type TimelineInterval as r, assertClipFitsSequence as s, chooseCaptionPlacement as t, clampClipDuration as u, clampClipStart as v, formatSeconds as w, formatTimecode as x, framesToSeconds as y, secondsToFrames as z };
@@ -1,4 +1,6 @@
1
- import { b as AppToolContext, f as AppToolTaxonomy, c as AppToolHandlers, e as AppToolProducedEvent, d as AppToolOutcome } from '../types-By4B3K37.js';
1
+ import { b as AppToolName, f as ToolHeaderNames } from '../mcp-CIupfjxV.js';
2
+ export { A as APP_TOOL_NAMES, a as AppToolMcpServer, c as AuthenticateOptions, B as BuildHttpMcpServerOptions, d as BuildMcpServerOptions, D as DEFAULT_APP_TOOL_PATHS, e as DEFAULT_HEADER_NAMES, O as OpenAIFunctionTool, T as ToolAuthResult, g as authenticateToolRequest, h as buildAppToolMcpServer, i as buildAppToolOpenAITools, j as buildHttpMcpServer, k as isAppToolName, r as readToolArgs } from '../mcp-CIupfjxV.js';
3
+ import { c as AppToolHandlers, f as AppToolTaxonomy, b as AppToolContext, e as AppToolProducedEvent, d as AppToolOutcome } from '../types-By4B3K37.js';
2
4
  export { A as AddCitationArgs, a as AddCitationResult, R as RenderUiArgs, g as RenderUiResult, S as ScheduleFollowupArgs, h as ScheduleFollowupResult, i as SubmitProposalArgs, j as SubmitProposalResult } from '../types-By4B3K37.js';
3
5
 
4
6
  /** A correctable bad-input error a tool handler throws; the HTTP layer maps it
@@ -39,65 +41,29 @@ declare function createCapabilityToken(userId: string, opts: CapabilityTokenOpti
39
41
  /** Verify a capability token against `userId`. Returns false (never throws) for
40
42
  * an unconfigured secret, a wrong prefix, a malformed token, or a mismatch. */
41
43
  declare function verifyCapabilityToken(userId: string, token: string, opts: CapabilityTokenOptions): Promise<boolean>;
42
-
43
- /**
44
- * Header names carrying the server-set per-turn context + the capability token.
45
- * Defaults are product-neutral (`X-Agent-App-*`); a product that already ships
46
- * a header convention (e.g. `X-Acme-User-Id`) passes its own.
47
- */
48
- interface ToolHeaderNames {
49
- userId: string;
50
- workspaceId: string;
51
- threadId: string;
52
- }
53
- declare const DEFAULT_HEADER_NAMES: ToolHeaderNames;
54
- interface AuthenticateOptions {
55
- /** Verify the bearer capability token belongs to `userId`. The product's
56
- * HMAC/JWT impl — the seam that keeps token crypto out of this package. */
57
- verifyToken: (userId: string, bearer: string) => Promise<boolean>;
58
- headerNames?: ToolHeaderNames;
59
- }
60
- type ToolAuthResult = {
61
- ok: true;
62
- ctx: AppToolContext;
63
- } | {
64
- ok: false;
65
- response: Response;
66
- };
67
- /**
68
- * Recover + verify the trusted context for a tool request. The user comes from
69
- * a server-set header and the bearer token MUST verify against THAT user; the
70
- * workspace comes from a header too — never from tool args — so the model can
71
- * neither forge identity nor target another workspace. Fail-closed: any missing
72
- * credential or a token minted for another user yields a 401/400 Response.
73
- */
74
- declare function authenticateToolRequest(request: Request, opts: AuthenticateOptions): Promise<ToolAuthResult>;
75
- /** Read a tool's argument object from the request body, tolerant of MCP host
76
- * aliases (`args` / `arguments`) or a bare body. Returns null on non-JSON. */
77
- declare function readToolArgs<T>(request: Request): Promise<T | null>;
78
-
79
- /** The four canonical app-tool names. Stable identifiers the model calls in
80
- * both the sandbox (MCP server name) and runtime (function-tool name) paths. */
81
- declare const APP_TOOL_NAMES: readonly ["submit_proposal", "schedule_followup", "render_ui", "add_citation"];
82
- type AppToolName = (typeof APP_TOOL_NAMES)[number];
83
- declare function isAppToolName(name: string): name is AppToolName;
84
- /** A minimal OpenAI Chat Completions function-tool shape — structurally
85
- * compatible with `@tangle-network/agent-runtime`'s `OpenAIChatTool` without
86
- * importing it (keeps this package runtime-free). */
87
- interface OpenAIFunctionTool {
88
- type: 'function';
89
- function: {
90
- name: string;
91
- description: string;
92
- parameters: Record<string, unknown>;
93
- };
44
+ interface ExpiringCapabilityTokenOptions extends CapabilityTokenOptions {
45
+ /** Token lifetime. Expired tokens verify false regardless of signature. */
46
+ expiresInMs: number;
47
+ /** Clock injection for tests; defaults to Date.now. */
48
+ now?: () => number;
94
49
  }
95
50
  /**
96
- * Build the four app tools in OpenAI function-tool shape. `submit_proposal`'s
97
- * `type` enum is the product's {@link AppToolTaxonomy.proposalTypes}; the other
98
- * three are fixed. Pass the result to the agent-runtime backend's `tools`.
51
+ * Mint an EXPIRING capability token: `<prefix><base64url(payload)>.<sig>` where
52
+ * the payload carries `{ sub, exp, n }` (subject, epoch-ms expiry, random
53
+ * nonce) and the signature is HMAC-SHA256 over the encoded payload. Use this
54
+ * for user-initiated scoped channels (e.g. a per-sequence MCP endpoint) where
55
+ * a captured token must not stay valid past its window; the bare
56
+ * {@link createCapabilityToken} remains for turn-scoped tool bridges whose
57
+ * mint+verify happen inside one request cycle. Fail-closed like the bare
58
+ * variant: no secret → no token.
99
59
  */
100
- declare function buildAppToolOpenAITools(taxonomy: AppToolTaxonomy): OpenAIFunctionTool[];
60
+ declare function createExpiringCapabilityToken(subject: string, opts: ExpiringCapabilityTokenOptions): Promise<string | undefined>;
61
+ /** Verify an expiring token against `subject`: prefix, payload integrity,
62
+ * subject match, and expiry all checked; returns false (never throws) on any
63
+ * failure including a malformed payload. */
64
+ declare function verifyExpiringCapabilityToken(subject: string, token: string, opts: CapabilityTokenOptions & {
65
+ now?: () => number;
66
+ }): Promise<boolean>;
101
67
 
102
68
  interface DispatchOptions {
103
69
  handlers: AppToolHandlers;
@@ -168,54 +134,4 @@ interface HandleToolRequestOptions extends DispatchOptions {
168
134
  */
169
135
  declare function handleAppToolRequest(request: Request, opts: HandleToolRequestOptions): Promise<Response>;
170
136
 
171
- /** Default route path each app tool is served at. A product mounts its routes
172
- * at these paths (or supplies its own via {@link BuildMcpServerOptions.paths}). */
173
- declare const DEFAULT_APP_TOOL_PATHS: Record<AppToolName, string>;
174
- /** The portable MCP server entry the sandbox SDK accepts (transport + url +
175
- * headers). Matches `AgentProfileMcpServer` structurally without importing the
176
- * sandbox SDK — products spread it into their profile's `mcp` map. */
177
- interface AppToolMcpServer {
178
- transport: 'http';
179
- url: string;
180
- headers: Record<string, string>;
181
- enabled: true;
182
- metadata: {
183
- description: string;
184
- };
185
- }
186
- interface BuildHttpMcpServerOptions {
187
- /** Route path on the app the sandbox POSTs to (e.g. `/api/tools/propose`). */
188
- path: string;
189
- /** App base URL the sandbox reaches back to (no trailing slash required). */
190
- baseUrl: string;
191
- /** Per-user capability token, baked into the Authorization header. */
192
- token: string;
193
- ctx: AppToolContext;
194
- /** Tool description the model sees. */
195
- description: string;
196
- headerNames?: ToolHeaderNames;
197
- }
198
- /**
199
- * Build ONE HTTP MCP server entry — the generic agent→app bridge. The
200
- * capability token + the user/workspace/thread ids ride in server-set headers
201
- * (never tool args), so the model can't forge identity or target another
202
- * workspace. Workspace/thread headers are omitted when their `ctx` value is
203
- * empty/null (e.g. an integration-invoke bridge that's user-scoped only). Used
204
- * directly for non-app-tool bridges (integration_invoke) and via
205
- * {@link buildAppToolMcpServer} for the four app tools.
206
- */
207
- declare function buildHttpMcpServer(opts: BuildHttpMcpServerOptions): AppToolMcpServer;
208
- interface BuildMcpServerOptions {
209
- tool: AppToolName;
210
- baseUrl: string;
211
- token: string;
212
- ctx: AppToolContext;
213
- description: string;
214
- headerNames?: ToolHeaderNames;
215
- paths?: Partial<Record<AppToolName, string>>;
216
- }
217
- /** Build one of the four app-tool MCP servers — a thin wrapper over
218
- * {@link buildHttpMcpServer} that maps the tool name to its route path. */
219
- declare function buildAppToolMcpServer(opts: BuildMcpServerOptions): AppToolMcpServer;
220
-
221
- export { APP_TOOL_NAMES, AppToolContext, AppToolHandlers, type AppToolMcpServer, type AppToolName, AppToolOutcome, AppToolProducedEvent, type AppToolRuntimeExecutor, AppToolTaxonomy, type AuthenticateOptions, type BuildHttpMcpServerOptions, type BuildMcpServerOptions, type CapabilityTokenOptions, DEFAULT_APP_TOOL_PATHS, DEFAULT_HEADER_NAMES, type DispatchOptions, type HandleToolRequestOptions, type OpenAIFunctionTool, type RuntimeExecutorOptions, type ToolAuthResult, type ToolHeaderNames, ToolInputError, authenticateToolRequest, buildAppToolMcpServer, buildAppToolOpenAITools, buildHttpMcpServer, createAppToolRuntimeExecutor, createCapabilityToken, dispatchAppTool, handleAppToolRequest, isAppToolName, outcomeStatus, readToolArgs, verifyCapabilityToken };
137
+ export { AppToolContext, AppToolHandlers, AppToolName, AppToolOutcome, AppToolProducedEvent, type AppToolRuntimeExecutor, AppToolTaxonomy, type CapabilityTokenOptions, type DispatchOptions, type ExpiringCapabilityTokenOptions, type HandleToolRequestOptions, type RuntimeExecutorOptions, ToolHeaderNames, ToolInputError, createAppToolRuntimeExecutor, createCapabilityToken, createExpiringCapabilityToken, dispatchAppTool, handleAppToolRequest, outcomeStatus, verifyCapabilityToken, verifyExpiringCapabilityToken };