@agent-native/core-corpus 0.222.2 → 0.222.3-nightly-20261029212408
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/corpus/README.md +1 -1
- package/corpus/templates/analytics/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/assets/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/brain/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/calendar/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/chat/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/clips/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/clips/app/components/editor/editor-layout.tsx +5 -2
- package/corpus/templates/clips/app/components/editor/timeline-track.tsx +98 -55
- package/corpus/templates/clips/app/components/editor/waveform.tsx +1 -8
- package/corpus/templates/clips/app/routes/_app.r.$recordingId.tsx +35 -20
- package/corpus/templates/content/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/crm/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/design/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/design/.generated/bridge/native-builtin-metadata.generated.ts +326 -0
- package/corpus/templates/design/.generated/bridge/native-worker-source.generated.ts +6 -0
- package/corpus/templates/dispatch/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/factory/.agents/skills/factory-workflows/SKILL.md +2 -0
- package/corpus/templates/factory/actions/delete-factory.ts +2 -0
- package/corpus/templates/factory/actions/discard-factory-workflow-draft.ts +39 -0
- package/corpus/templates/factory/actions/get-factory-workflow-draft.ts +71 -0
- package/corpus/templates/factory/actions/get-factory-workflow.ts +6 -1
- package/corpus/templates/factory/actions/save-factory-workflow-draft.ts +52 -0
- package/corpus/templates/factory/actions/save-factory-workflow.ts +3 -0
- package/corpus/templates/factory/app/components/factory/ConnectProviderButton.tsx +9 -12
- package/corpus/templates/factory/app/components/factory/SettingsView.tsx +9 -3
- package/corpus/templates/factory/app/components/workflow/NodeAuditPanel.tsx +7 -3
- package/corpus/templates/factory/app/components/workflow/RunPicker.tsx +9 -2
- package/corpus/templates/factory/app/components/workflow/WorkflowPage.tsx +167 -52
- package/corpus/templates/factory/app/components/workflow/WorkflowToolbar.tsx +0 -22
- package/corpus/templates/factory/app/components/workflow/items/ItemListRow.tsx +3 -6
- package/corpus/templates/factory/app/components/workflow/items/item-status.ts +8 -3
- package/corpus/templates/factory/app/components/workflow/node-details/NodeDetailsDialog.tsx +6 -2
- package/corpus/templates/factory/app/components/workflow/node-details/NodeDetailsParameters.tsx +4 -0
- package/corpus/templates/factory/app/components/workflow/use-workflow-draft.ts +105 -0
- package/corpus/templates/factory/app/components/workflow/workflow-drafts.ts +259 -0
- package/corpus/templates/factory/app/components/workflow/workflow-run-overlay.ts +41 -2
- package/corpus/templates/factory/app/components/workflow/workflow-strings.ts +8 -3
- package/corpus/templates/factory/app/components/workflow/workflow-time.ts +17 -0
- package/corpus/templates/factory/app/components/workflow/workflow-types.ts +4 -0
- package/corpus/templates/factory/app/components/workflow-canvas/CanvasTestButton.tsx +5 -2
- package/corpus/templates/factory/app/components/workflow-canvas/WorkflowCanvas.tsx +2 -1
- package/corpus/templates/factory/app/i18n/en-US.ts +7 -3
- package/corpus/templates/factory/app/lib/__tests__/strings-probes.ts +2 -0
- package/corpus/templates/factory/changelog/2026-10-28-a-run-now-marks-only-the-steps-that-did-work-so-steps-nothin.md +6 -0
- package/corpus/templates/factory/changelog/2026-10-28-a-step-s-output-now-shows-its-data-as-soon-as-a-test-step-or.md +6 -0
- package/corpus/templates/factory/changelog/2026-10-28-connect-opens-in-a-new-tab-so-the-workflow-you-are-editing-s.md +6 -0
- package/corpus/templates/factory/changelog/2026-10-28-dry-run-is-now-a-single-button-on-the-canvas-instead-of-one-.md +6 -0
- package/corpus/templates/factory/changelog/2026-10-28-items-no-longer-say-there-was-no-activity-for-an-item-that-h.md +6 -0
- package/corpus/templates/factory/changelog/2026-10-28-side-panels-opened-from-step-details-now-appear-on-top-the-p.md +6 -0
- package/corpus/templates/factory/changelog/2026-10-28-typing-a-slack-channel-id-in-a-channel-field-finds-that-chan.md +6 -0
- package/corpus/templates/factory/changelog/2026-10-28-unsaved-workflow-edits-are-kept-as-a-private-draft-and-come-.md +6 -0
- package/corpus/templates/factory/server/db/schema.ts +23 -0
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +18 -0
- package/corpus/templates/factory/server/workflow/adapter.ts +55 -1
- package/corpus/templates/factory/server/workflow/store-rules.ts +51 -0
- package/corpus/templates/factory/server/workflow/testing/in-memory-store.ts +66 -0
- package/corpus/templates/factory/server/workflow/testing/store-conformance.ts +240 -0
- package/corpus/templates/factory/server/workflow-host/option-listers/registry.ts +9 -3
- package/corpus/templates/factory/server/workflow-host/option-listers/slack-channels.ts +55 -19
- package/corpus/templates/factory/server/workflow-host/option-listers/types.ts +9 -0
- package/corpus/templates/factory/server/workflow-host/store.ts +119 -0
- package/corpus/templates/forms/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/mail/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/plan/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/slides/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/slides-2/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/package.json +1 -1
package/corpus/README.md
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","analytics-alert-jobs","analytics-rollup-backfill-jobs","auth","collab","config","content-metrics-collection-jobs","core-routes","creative-context","dashboard-report-jobs","db","feature-flags","labs","onboarding","otel","session-replay-retention-jobs","transactional-emails","uptime-monitor-jobs"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","auth","creative-context","db","labs","onboarding","otel"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","auth","brain-jobs","core-routes","db","otel"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","auth","core-routes","db","event-rules","oauth-refresh","otel","transactional-emails"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","auth","otel"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","auth","calendar-jobs","config","core-routes","db","feature-flags","labs","onboarding","onboarding-calendar","otel","transactional-email-catalog"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -480,6 +480,9 @@ export function EditorLayout({
|
|
|
480
480
|
viewportX: number;
|
|
481
481
|
} | null>(null);
|
|
482
482
|
|
|
483
|
+
// The container only mounts once the loading skeleton is gone.
|
|
484
|
+
const editorReady = !playerDataQuery.isLoading && resumeState !== "waiting";
|
|
485
|
+
|
|
483
486
|
useEffect(() => {
|
|
484
487
|
if (!containerRef.current) return;
|
|
485
488
|
const el = containerRef.current;
|
|
@@ -490,7 +493,7 @@ export function EditorLayout({
|
|
|
490
493
|
ro.observe(el);
|
|
491
494
|
setViewportWidth(Math.max(1, Math.floor(contentWidthOf(el))));
|
|
492
495
|
return () => ro.disconnect();
|
|
493
|
-
}, [activeSurface]);
|
|
496
|
+
}, [activeSurface, editorReady]);
|
|
494
497
|
|
|
495
498
|
const totalWidth = useMemo(
|
|
496
499
|
() => getTimelineTotalWidth(viewportWidth, zoom),
|
|
@@ -656,7 +659,7 @@ export function EditorLayout({
|
|
|
656
659
|
el.removeEventListener("gesturechange", handleGestureChange);
|
|
657
660
|
el.removeEventListener("gestureend", handleGestureEnd);
|
|
658
661
|
};
|
|
659
|
-
}, [scrollLeft, setAnchoredZoom, viewportWidth, zoom]);
|
|
662
|
+
}, [editorReady, scrollLeft, setAnchoredZoom, viewportWidth, zoom]);
|
|
660
663
|
|
|
661
664
|
useEffect(() => {
|
|
662
665
|
const v = videoRef.current;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useT } from "@agent-native/core/client/i18n";
|
|
2
2
|
import { IconArrowBackUp } from "@tabler/icons-react";
|
|
3
|
-
import { useCallback,
|
|
3
|
+
import { useCallback, useMemo, useRef, useState } from "react";
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
addCut,
|
|
@@ -40,6 +40,7 @@ export const MIN_PIECE_MS = 80;
|
|
|
40
40
|
const DRAG_THRESHOLD_PX = 3;
|
|
41
41
|
const EDGE_HANDLE_PX = 13;
|
|
42
42
|
const RESTORE_BUTTON_MIN_PX = 26;
|
|
43
|
+
const RANGE_EDGE_PX = 6;
|
|
43
44
|
|
|
44
45
|
export type EdgeSide = "clip-start" | "clip-end";
|
|
45
46
|
|
|
@@ -74,7 +75,14 @@ interface RangeDragState {
|
|
|
74
75
|
kind: "range";
|
|
75
76
|
pointerId: number;
|
|
76
77
|
startClientX: number;
|
|
78
|
+
/** "new" and "resize" grow from `startMs`; "move" slides `from` by the pointer delta. */
|
|
79
|
+
mode: "new" | "resize" | "move";
|
|
77
80
|
startMs: number;
|
|
81
|
+
/** Where the pointer went down; `startMs` is the far edge when resizing. */
|
|
82
|
+
pressMs: number;
|
|
83
|
+
from: { startMs: number; endMs: number } | null;
|
|
84
|
+
/** Set when the drag began on a removed section, so a plain click selects it. */
|
|
85
|
+
gapCutId: string | null;
|
|
78
86
|
moved: boolean;
|
|
79
87
|
}
|
|
80
88
|
|
|
@@ -84,6 +92,32 @@ function clamp(value: number, min: number, max: number): number {
|
|
|
84
92
|
return Math.max(min, Math.min(max, value));
|
|
85
93
|
}
|
|
86
94
|
|
|
95
|
+
function dragRange(drag: RangeDragState, ms: number, durationMs: number) {
|
|
96
|
+
if (drag.mode !== "move" || !drag.from) {
|
|
97
|
+
return selectionRange(drag.startMs, ms);
|
|
98
|
+
}
|
|
99
|
+
const length = drag.from.endMs - drag.from.startMs;
|
|
100
|
+
const startMs = clamp(
|
|
101
|
+
drag.from.startMs + ms - drag.startMs,
|
|
102
|
+
0,
|
|
103
|
+
Math.max(0, durationMs - length),
|
|
104
|
+
);
|
|
105
|
+
return selectionRange(startMs, startMs + length);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function rangeZone(
|
|
109
|
+
range: { startMs: number; endMs: number },
|
|
110
|
+
atMs: number,
|
|
111
|
+
toX: (ms: number) => number,
|
|
112
|
+
): "edge" | "inside" | "outside" {
|
|
113
|
+
const x = toX(atMs);
|
|
114
|
+
const left = toX(range.startMs);
|
|
115
|
+
const right = toX(range.endMs);
|
|
116
|
+
const edge = Math.min(RANGE_EDGE_PX, (right - left) / 3);
|
|
117
|
+
if (Math.abs(x - left) <= edge || Math.abs(x - right) <= edge) return "edge";
|
|
118
|
+
return x > left && x < right ? "inside" : "outside";
|
|
119
|
+
}
|
|
120
|
+
|
|
87
121
|
function selectionRange(startMs: number, endMs: number): TrackSelection {
|
|
88
122
|
return {
|
|
89
123
|
kind: "range",
|
|
@@ -218,38 +252,7 @@ export function TimelineTrack({
|
|
|
218
252
|
const rootRef = useRef<HTMLDivElement | null>(null);
|
|
219
253
|
const dragRef = useRef<DragState | null>(null);
|
|
220
254
|
const [dragging, setDragging] = useState(false);
|
|
221
|
-
const [
|
|
222
|
-
|
|
223
|
-
useEffect(() => {
|
|
224
|
-
const handleKeyDown = (e: KeyboardEvent) => {
|
|
225
|
-
const target = e.target as HTMLElement | null;
|
|
226
|
-
const tag = target?.tagName?.toLowerCase();
|
|
227
|
-
if (
|
|
228
|
-
e.code !== "KeyR" ||
|
|
229
|
-
e.metaKey ||
|
|
230
|
-
e.ctrlKey ||
|
|
231
|
-
e.altKey ||
|
|
232
|
-
tag === "input" ||
|
|
233
|
-
tag === "textarea" ||
|
|
234
|
-
target?.isContentEditable
|
|
235
|
-
) {
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
setRangeMode(true);
|
|
239
|
-
};
|
|
240
|
-
const handleKeyUp = (e: KeyboardEvent) => {
|
|
241
|
-
if (e.code === "KeyR") setRangeMode(false);
|
|
242
|
-
};
|
|
243
|
-
const clearRangeMode = () => setRangeMode(false);
|
|
244
|
-
window.addEventListener("keydown", handleKeyDown);
|
|
245
|
-
window.addEventListener("keyup", handleKeyUp);
|
|
246
|
-
window.addEventListener("blur", clearRangeMode);
|
|
247
|
-
return () => {
|
|
248
|
-
window.removeEventListener("keydown", handleKeyDown);
|
|
249
|
-
window.removeEventListener("keyup", handleKeyUp);
|
|
250
|
-
window.removeEventListener("blur", clearRangeMode);
|
|
251
|
-
};
|
|
252
|
-
}, []);
|
|
255
|
+
const [rangeCursor, setRangeCursor] = useState<string | null>(null);
|
|
253
256
|
|
|
254
257
|
const pieces = useMemo(
|
|
255
258
|
() => buildTimelinePieces(durationMs, edits),
|
|
@@ -295,21 +298,32 @@ export function TimelineTrack({
|
|
|
295
298
|
const handleMove = useCallback(
|
|
296
299
|
(e: React.PointerEvent) => {
|
|
297
300
|
const drag = dragRef.current;
|
|
298
|
-
if (!drag
|
|
301
|
+
if (!drag) {
|
|
302
|
+
if (selection?.kind !== "range" || disabled) {
|
|
303
|
+
setRangeCursor(null);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const zone = rangeZone(selection, toMs(e.clientX), toX);
|
|
307
|
+
setRangeCursor(
|
|
308
|
+
zone === "edge" ? "ew-resize" : zone === "inside" ? "grab" : null,
|
|
309
|
+
);
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
if (drag.pointerId !== e.pointerId) return;
|
|
299
313
|
if (!drag.moved) {
|
|
300
314
|
if (Math.abs(e.clientX - drag.startClientX) < DRAG_THRESHOLD_PX) return;
|
|
301
315
|
drag.moved = true;
|
|
302
316
|
setDragging(true);
|
|
303
317
|
}
|
|
304
318
|
if (drag.kind === "range") {
|
|
305
|
-
onSelectionChange(
|
|
319
|
+
onSelectionChange(dragRange(drag, toMs(e.clientX), durationMs));
|
|
306
320
|
} else {
|
|
307
321
|
onPreview(
|
|
308
322
|
applyDrag(drag.base, durationMs, drag.target, toMs(e.clientX)),
|
|
309
323
|
);
|
|
310
324
|
}
|
|
311
325
|
},
|
|
312
|
-
[durationMs, onPreview, onSelectionChange, toMs],
|
|
326
|
+
[disabled, durationMs, onPreview, onSelectionChange, selection, toMs, toX],
|
|
313
327
|
);
|
|
314
328
|
|
|
315
329
|
const endDrag = useCallback(
|
|
@@ -322,10 +336,12 @@ export function TimelineTrack({
|
|
|
322
336
|
if (!commit) return;
|
|
323
337
|
if (drag.kind === "range") {
|
|
324
338
|
if (drag.moved) {
|
|
325
|
-
onSelectionChange(
|
|
339
|
+
onSelectionChange(dragRange(drag, toMs(e.clientX), durationMs));
|
|
340
|
+
} else if (drag.gapCutId) {
|
|
341
|
+
onSelectionChange({ kind: "gap", cutId: drag.gapCutId });
|
|
326
342
|
} else {
|
|
327
|
-
onSelectionChange({ kind: "clip", anchorMs: drag.
|
|
328
|
-
onSeek?.(drag.
|
|
343
|
+
onSelectionChange({ kind: "clip", anchorMs: drag.pressMs });
|
|
344
|
+
onSeek?.(drag.pressMs);
|
|
329
345
|
}
|
|
330
346
|
return;
|
|
331
347
|
}
|
|
@@ -340,13 +356,38 @@ export function TimelineTrack({
|
|
|
340
356
|
[durationMs, onCommit, onPreview, onSeek, onSelectionChange, toMs],
|
|
341
357
|
);
|
|
342
358
|
|
|
343
|
-
const beginRangeDrag = (
|
|
359
|
+
const beginRangeDrag = (
|
|
360
|
+
e: React.PointerEvent,
|
|
361
|
+
at: number,
|
|
362
|
+
gapCutId: string | null,
|
|
363
|
+
) => {
|
|
344
364
|
rootRef.current?.setPointerCapture?.(e.pointerId);
|
|
365
|
+
let mode: RangeDragState["mode"] = "new";
|
|
366
|
+
let startMs = at;
|
|
367
|
+
let from: RangeDragState["from"] = null;
|
|
368
|
+
if (selection?.kind === "range") {
|
|
369
|
+
const zone = rangeZone(selection, at, toX);
|
|
370
|
+
if (zone === "edge") {
|
|
371
|
+
mode = "resize";
|
|
372
|
+
startMs =
|
|
373
|
+
Math.abs(toX(at) - toX(selection.startMs)) <=
|
|
374
|
+
Math.abs(toX(at) - toX(selection.endMs))
|
|
375
|
+
? selection.endMs
|
|
376
|
+
: selection.startMs;
|
|
377
|
+
} else if (zone === "inside") {
|
|
378
|
+
mode = "move";
|
|
379
|
+
from = { startMs: selection.startMs, endMs: selection.endMs };
|
|
380
|
+
}
|
|
381
|
+
}
|
|
345
382
|
dragRef.current = {
|
|
346
383
|
kind: "range",
|
|
347
384
|
pointerId: e.pointerId,
|
|
348
385
|
startClientX: e.clientX,
|
|
386
|
+
mode,
|
|
349
387
|
startMs,
|
|
388
|
+
pressMs: at,
|
|
389
|
+
from,
|
|
390
|
+
gapCutId,
|
|
350
391
|
moved: false,
|
|
351
392
|
};
|
|
352
393
|
};
|
|
@@ -372,7 +413,11 @@ export function TimelineTrack({
|
|
|
372
413
|
<div
|
|
373
414
|
ref={rootRef}
|
|
374
415
|
className={cn("relative select-none", className)}
|
|
375
|
-
style={{
|
|
416
|
+
style={{
|
|
417
|
+
width,
|
|
418
|
+
height,
|
|
419
|
+
cursor: dragging ? undefined : (rangeCursor ?? undefined),
|
|
420
|
+
}}
|
|
376
421
|
onPointerMove={handleMove}
|
|
377
422
|
onPointerUp={(e) => endDrag(e, true)}
|
|
378
423
|
onPointerCancel={(e) => endDrag(e, false)}
|
|
@@ -406,15 +451,15 @@ export function TimelineTrack({
|
|
|
406
451
|
: "cursor-pointer hover:bg-rose-500/15",
|
|
407
452
|
selected && "bg-rose-500/20 ring-2 ring-inset ring-rose-400",
|
|
408
453
|
)}
|
|
409
|
-
style={{
|
|
454
|
+
style={{
|
|
455
|
+
left,
|
|
456
|
+
width: pieceWidth,
|
|
457
|
+
cursor: rangeCursor ?? undefined,
|
|
458
|
+
}}
|
|
410
459
|
onPointerDown={(e) => {
|
|
411
460
|
if (disabled || e.button !== 0) return;
|
|
412
461
|
e.preventDefault();
|
|
413
|
-
|
|
414
|
-
beginRangeDrag(e, toMs(e.clientX));
|
|
415
|
-
return;
|
|
416
|
-
}
|
|
417
|
-
onSelectionChange({ kind: "gap", cutId: piece.cutId });
|
|
462
|
+
beginRangeDrag(e, toMs(e.clientX), piece.cutId);
|
|
418
463
|
}}
|
|
419
464
|
>
|
|
420
465
|
{pieceWidth >= RESTORE_BUTTON_MIN_PX ? (
|
|
@@ -456,17 +501,15 @@ export function TimelineTrack({
|
|
|
456
501
|
? "border-primary bg-primary/15 ring-2 ring-inset ring-primary"
|
|
457
502
|
: "border-transparent hover:border-primary/50 hover:bg-primary/5",
|
|
458
503
|
)}
|
|
459
|
-
style={{
|
|
504
|
+
style={{
|
|
505
|
+
left,
|
|
506
|
+
width: pieceWidth,
|
|
507
|
+
cursor: rangeCursor ?? undefined,
|
|
508
|
+
}}
|
|
460
509
|
onPointerDown={(e) => {
|
|
461
510
|
if (disabled || e.button !== 0) return;
|
|
462
511
|
e.preventDefault();
|
|
463
|
-
|
|
464
|
-
if (rangeMode) {
|
|
465
|
-
beginRangeDrag(e, at);
|
|
466
|
-
return;
|
|
467
|
-
}
|
|
468
|
-
onSelectionChange({ kind: "clip", anchorMs: at });
|
|
469
|
-
onSeek?.(at);
|
|
512
|
+
beginRangeDrag(e, toMs(e.clientX), null);
|
|
470
513
|
}}
|
|
471
514
|
/>
|
|
472
515
|
);
|
|
@@ -45,9 +45,6 @@ const getQuietColor = (overImagery = false) =>
|
|
|
45
45
|
// guard:allow-raw-color — as above: read against the frames, not the theme.
|
|
46
46
|
overImagery ? "rgba(226, 232, 240, 0.45)" : getBrandColorAlpha(0.2);
|
|
47
47
|
const getWaveBg = () => getBrandColorAlpha(0.08);
|
|
48
|
-
/** Darkens the band behind the bars when they sit over filmstrip frames. */
|
|
49
|
-
// guard:allow-raw-color — a scrim over video frames, which are whatever the recording holds; it has to darken them in either theme.
|
|
50
|
-
const WAVE_SCRIM = "rgba(2, 6, 23, 0.46)";
|
|
51
48
|
const EXCLUDED_FILL = "rgba(15, 23, 42, 0.65)";
|
|
52
49
|
const EXCLUDED_STROKE = "rgba(148, 163, 184, 0.4)";
|
|
53
50
|
const EMPTY_FRAMES: FilmstripFrame[] = [];
|
|
@@ -175,11 +172,7 @@ export function Waveform({
|
|
|
175
172
|
);
|
|
176
173
|
|
|
177
174
|
ctx.clearRect(0, 0, totalWidth, height);
|
|
178
|
-
if (hasImagery) {
|
|
179
|
-
const bandHeight = Math.min(height, Math.max(28, height * 0.62));
|
|
180
|
-
ctx.fillStyle = WAVE_SCRIM;
|
|
181
|
-
ctx.fillRect(0, (height - bandHeight) / 2, totalWidth, bandHeight);
|
|
182
|
-
} else {
|
|
175
|
+
if (!hasImagery) {
|
|
183
176
|
ctx.fillStyle = getWaveBg();
|
|
184
177
|
ctx.fillRect(0, 0, totalWidth, height);
|
|
185
178
|
}
|
|
@@ -709,7 +709,17 @@ export default function RecordingPage() {
|
|
|
709
709
|
storageKey: "clips:share-sidebar-collapsed",
|
|
710
710
|
});
|
|
711
711
|
const [theaterMode, setTheaterMode] = useState(false);
|
|
712
|
-
|
|
712
|
+
// Lives in the URL so the editor can be linked to and survives a reload.
|
|
713
|
+
const editing = searchParams.get("edit") === "1";
|
|
714
|
+
const setEditing = useCallback(
|
|
715
|
+
(next: boolean) => {
|
|
716
|
+
const nextParams = new URLSearchParams(searchParams);
|
|
717
|
+
if (next) nextParams.set("edit", "1");
|
|
718
|
+
else nextParams.delete("edit");
|
|
719
|
+
setSearchParams(nextParams, { replace: true });
|
|
720
|
+
},
|
|
721
|
+
[searchParams, setSearchParams],
|
|
722
|
+
);
|
|
713
723
|
const [chapterEditRequest, setChapterEditRequest] = useState(0);
|
|
714
724
|
const [tagEditRequest, setTagEditRequest] = useState(0);
|
|
715
725
|
const openingMetadataEditor = useRef(false);
|
|
@@ -741,7 +751,7 @@ export default function RecordingPage() {
|
|
|
741
751
|
const [editorRedactions, setEditorRedactions] = useState(0);
|
|
742
752
|
const isCompactLayout = useIsCompactRecordingLayout();
|
|
743
753
|
const openSidePanel = useCallback(
|
|
744
|
-
(next: ToolbarPanel) => {
|
|
754
|
+
(next: ToolbarPanel, options?: { leaveEditor?: boolean }) => {
|
|
745
755
|
if (panel !== next) {
|
|
746
756
|
trackEvent("clip_panel_opened", {
|
|
747
757
|
app_name: "clips",
|
|
@@ -754,6 +764,9 @@ export default function RecordingPage() {
|
|
|
754
764
|
setSidePanelCollapsed(false);
|
|
755
765
|
const nextParams = new URLSearchParams(searchParams);
|
|
756
766
|
nextParams.set("panel", next);
|
|
767
|
+
// One write: a separate setEditing(false) would copy the same params
|
|
768
|
+
// snapshot and this write would put `edit` back.
|
|
769
|
+
if (options?.leaveEditor) nextParams.delete("edit");
|
|
757
770
|
setSearchParams(nextParams, { replace: true });
|
|
758
771
|
if (!isCompactLayout) return;
|
|
759
772
|
requestAnimationFrame(() => {
|
|
@@ -799,19 +812,22 @@ export default function RecordingPage() {
|
|
|
799
812
|
setSearchParams,
|
|
800
813
|
setSidePanelCollapsed,
|
|
801
814
|
]);
|
|
802
|
-
const openAgentPanel = useCallback(
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
+
const openAgentPanel = useCallback(
|
|
816
|
+
(options?: { leaveEditor?: boolean }) => {
|
|
817
|
+
if (recordingId) {
|
|
818
|
+
trackEvent("builtin_agent_used", {
|
|
819
|
+
app_name: "clips",
|
|
820
|
+
template_name: "clips",
|
|
821
|
+
output_id: recordingId,
|
|
822
|
+
output_type: "clip",
|
|
823
|
+
query_type: "clip",
|
|
824
|
+
surface: "recording_page",
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
openSidePanel("agent", options);
|
|
828
|
+
},
|
|
829
|
+
[openSidePanel, recordingId],
|
|
830
|
+
);
|
|
815
831
|
const transcriptKickedRef = useRef<string | null>(null);
|
|
816
832
|
const [processingTimeout, setProcessingTimeout] = useState(false);
|
|
817
833
|
const [retryingFinalize, setRetryingFinalize] = useState(false);
|
|
@@ -2515,8 +2531,7 @@ export default function RecordingPage() {
|
|
|
2515
2531
|
function handleGenerateWorkflow(kind: WorkflowKind) {
|
|
2516
2532
|
if (!recording) return;
|
|
2517
2533
|
if (aiRequestBusy || isRecentWorkflowGeneration(generatedWorkflow)) return;
|
|
2518
|
-
|
|
2519
|
-
openAgentPanel();
|
|
2534
|
+
openAgentPanel({ leaveEditor: true });
|
|
2520
2535
|
workflowLifecycleActiveRef.current = true;
|
|
2521
2536
|
primeCompletionCue();
|
|
2522
2537
|
startWorkflowToast(t("recordingPage.workflowQueued"));
|
|
@@ -2536,8 +2551,8 @@ export default function RecordingPage() {
|
|
|
2536
2551
|
}, [canEdit, panel, recording]);
|
|
2537
2552
|
|
|
2538
2553
|
useEffect(() => {
|
|
2539
|
-
if (!canUseNativeEditor && editing) setEditing(false);
|
|
2540
|
-
}, [canUseNativeEditor, editing]);
|
|
2554
|
+
if (recording && !canUseNativeEditor && editing) setEditing(false);
|
|
2555
|
+
}, [canUseNativeEditor, editing, recording, setEditing]);
|
|
2541
2556
|
|
|
2542
2557
|
useEffect(() => {
|
|
2543
2558
|
if (!recording) return;
|
|
@@ -3304,7 +3319,7 @@ export default function RecordingPage() {
|
|
|
3304
3319
|
none of those, so those actions are hidden. */}
|
|
3305
3320
|
{isImage ? null : (
|
|
3306
3321
|
<>
|
|
3307
|
-
<DropdownMenuItem onSelect={openAgentPanel}>
|
|
3322
|
+
<DropdownMenuItem onSelect={() => openAgentPanel()}>
|
|
3308
3323
|
{t("recordingPage.askAboutClip")}
|
|
3309
3324
|
</DropdownMenuItem>
|
|
3310
3325
|
<DropdownMenuSeparator />
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","auth","builder-private-payload-cleanup","collab","content-webhooks","core-routes","creative-context","db","feature-flags","github-source-sync","labs","live-body-backfill","onboarding","otel","suggested-edits","transactional-emails"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","auth","core-routes","db","otel"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","assets-mcp","auth","builder-host-embed-headers","collab","config","core-routes","creative-context","db","e2e-attachment-storage","feature-flags","getting-started","journey-canvas-stage-cleanup","labs","local-import-asset-upload","otel","review"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|