@neta-art/cohub 5.9.0 → 6.0.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 +42 -46
- package/dist/board/animation.d.ts +156 -67
- package/dist/board/animation.js +162 -277
- package/dist/board/codec.js +1 -1
- package/dist/board/export/index.d.ts +6 -0
- package/dist/board/export/index.js +6 -3
- package/dist/board/export/scene.d.ts +6 -0
- package/dist/board/export/scene.js +26 -2
- package/dist/board/geometry.d.ts +27 -1
- package/dist/board/geometry.js +92 -1
- package/dist/board/headless/index.d.ts +7 -1
- package/dist/board/headless/index.js +6 -2
- package/dist/board/index.d.ts +8 -6
- package/dist/board/index.js +7 -6
- package/dist/board/mutation.d.ts +15 -0
- package/dist/board/mutation.js +67 -0
- package/dist/board/render/css-color.d.ts +4 -0
- package/dist/board/render/css-color.js +36 -0
- package/dist/board/render/index.d.ts +2 -1
- package/dist/board/render/index.js +2 -1
- package/dist/board/render/renderers/base-card-renderer.js +3 -20
- package/dist/board/render/themes/clean-theme.js +6 -3
- package/dist/chunks/http.d.ts +30 -7
- package/dist/chunks/http.js +785 -289
- package/dist/chunks/websocket.d.ts +2675 -187
- package/dist/http.d.ts +3 -3
- package/dist/index.d.ts +158 -299
- package/dist/index.js +164 -279
- package/dist/protocol/dist/board-authoring.d.ts +1 -0
- package/dist/protocol/dist/board-authoring.js +217 -0
- package/dist/protocol/dist/board-capability-registry.d.ts +2 -0
- package/dist/protocol/dist/board-capability-registry.js +74 -0
- package/dist/protocol/dist/board-codec.d.ts +2 -0
- package/dist/protocol/dist/board-codec.js +4 -0
- package/dist/protocol/dist/board-composition.d.ts +258 -0
- package/dist/protocol/dist/board-composition.js +318 -0
- package/dist/protocol/dist/board-constants.d.ts +2 -1
- package/dist/protocol/dist/board-constants.js +40 -10
- package/dist/protocol/dist/board-document.d.ts +28 -2
- package/dist/protocol/dist/board-document.js +16 -3
- package/dist/protocol/dist/board-node.d.ts +1 -11
- package/dist/protocol/dist/board-node.js +1 -81
- package/dist/protocol/dist/board-upgrade.d.ts +1 -0
- package/dist/protocol/dist/board-upgrade.js +2 -0
- package/dist/protocol/dist/board-url.d.ts +2 -1
- package/dist/protocol/dist/board-url.js +8 -3
- package/dist/protocol/dist/board.d.ts +135 -76
- package/dist/protocol/dist/board.js +50 -69
- package/dist/protocol/dist/index.d.ts +9 -4
- package/dist/protocol/dist/index.js +9 -4
- package/dist/types.d.ts +3 -2
- package/docs/work-runtime-guide.md +19 -3
- package/package.json +3 -2
- package/dist/board/nodes.d.ts +0 -113
- package/dist/board/nodes.js +0 -154
package/dist/chunks/http.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { D as getRealtimeBoardRoom, O as getRealtimeSpaceRoom, n as HttpTransport, t as HttpError, y as isUuid } from "./transport.js";
|
|
2
2
|
import { a as resolveApiBaseUrl } from "./environment.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
import "perfect-freehand";
|
|
5
4
|
//#region src/apis/channels.ts
|
|
6
5
|
var ChannelsApi = class {
|
|
7
6
|
transport;
|
|
@@ -454,7 +453,6 @@ const DEFAULT_BOARD_RENDER_LIMITS = {
|
|
|
454
453
|
simulationSteps: 1e5
|
|
455
454
|
};
|
|
456
455
|
const BOARD_BUILTIN_CLIP_KINDS = [
|
|
457
|
-
"motion.keyframes",
|
|
458
456
|
"motion.path",
|
|
459
457
|
"draw.reveal",
|
|
460
458
|
"draw.handwrite",
|
|
@@ -463,9 +461,7 @@ const BOARD_BUILTIN_CLIP_KINDS = [
|
|
|
463
461
|
"effects.trail",
|
|
464
462
|
"effects.impact",
|
|
465
463
|
"effects.flash",
|
|
466
|
-
"
|
|
467
|
-
"camera.pan",
|
|
468
|
-
"camera.zoom",
|
|
464
|
+
"camera.focus",
|
|
469
465
|
"camera.shake"
|
|
470
466
|
];
|
|
471
467
|
const BOARD_BUILTIN_EFFECT_KINDS = ["effects.pulse", "effects.float"];
|
|
@@ -475,12 +471,45 @@ function clampBoardStrokeSize(size) {
|
|
|
475
471
|
if (!Number.isFinite(size)) return BOARD_CONNECTION_STROKE_SIZE;
|
|
476
472
|
return Math.min(64, Math.max(1, size));
|
|
477
473
|
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
}
|
|
474
|
+
function clipSchema(id) {
|
|
475
|
+
switch (id) {
|
|
476
|
+
case "motion.path": return { params: { points: {
|
|
477
|
+
coordinateSpace: "world-offset",
|
|
478
|
+
unit: "board"
|
|
479
|
+
} } };
|
|
480
|
+
case "effects.particles": return { params: { bounds: {
|
|
481
|
+
coordinateSpace: "world",
|
|
482
|
+
unit: "board"
|
|
483
|
+
} } };
|
|
484
|
+
case "camera.focus": return { params: {
|
|
485
|
+
focus: {
|
|
486
|
+
coordinateSpace: "world",
|
|
487
|
+
unit: "board"
|
|
488
|
+
},
|
|
489
|
+
padding: {
|
|
490
|
+
coordinateSpace: "screen",
|
|
491
|
+
unit: "css-px"
|
|
492
|
+
},
|
|
493
|
+
minZoom: { unit: "ratio" },
|
|
494
|
+
maxZoom: { unit: "ratio" }
|
|
495
|
+
} };
|
|
496
|
+
case "camera.shake": return { params: { amount: {
|
|
497
|
+
coordinateSpace: "screen-offset",
|
|
498
|
+
unit: "css-px"
|
|
499
|
+
} } };
|
|
500
|
+
default: return;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
const BOARD_BUILTIN_CAPABILITIES = [...BOARD_BUILTIN_CLIP_KINDS.map((id) => {
|
|
504
|
+
const schema = clipSchema(id);
|
|
505
|
+
return {
|
|
506
|
+
kind: "clip",
|
|
507
|
+
id,
|
|
508
|
+
version: 1,
|
|
509
|
+
renderers: ["webgpu", "webgl"],
|
|
510
|
+
...schema ? { schema } : {}
|
|
511
|
+
};
|
|
512
|
+
}), ...BOARD_BUILTIN_EFFECT_KINDS.map((id) => ({
|
|
484
513
|
kind: "effect",
|
|
485
514
|
id,
|
|
486
515
|
version: 1,
|
|
@@ -638,13 +667,529 @@ function createBoardConnection(input) {
|
|
|
638
667
|
};
|
|
639
668
|
}
|
|
640
669
|
//#endregion
|
|
641
|
-
//#region
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
670
|
+
//#region ../protocol/dist/board-composition.js
|
|
671
|
+
const idSchema$3 = z.string().min(1).max(160);
|
|
672
|
+
const finiteSchema$3 = z.number().finite();
|
|
673
|
+
const jsonObjectSchema$2 = z.record(z.string(), z.unknown());
|
|
674
|
+
const BoardEasingSchema = z.enum([
|
|
675
|
+
"linear",
|
|
676
|
+
"ease-in-quad",
|
|
677
|
+
"ease-out-quad",
|
|
678
|
+
"ease-in-out-quad",
|
|
679
|
+
"ease-in-cubic",
|
|
680
|
+
"ease-out-cubic",
|
|
681
|
+
"ease-in-out-cubic",
|
|
682
|
+
"ease-out-quart",
|
|
683
|
+
"ease-out-expo"
|
|
684
|
+
]);
|
|
685
|
+
const BoardAnimationTargetSchema = z.discriminatedUnion("type", [
|
|
686
|
+
z.object({
|
|
687
|
+
type: z.literal("item"),
|
|
688
|
+
itemId: idSchema$3
|
|
689
|
+
}).strict(),
|
|
690
|
+
z.object({
|
|
691
|
+
type: z.literal("effect"),
|
|
692
|
+
effectId: idSchema$3
|
|
693
|
+
}).strict(),
|
|
694
|
+
z.object({ type: z.literal("camera") }).strict(),
|
|
695
|
+
z.object({ type: z.literal("board") }).strict()
|
|
696
|
+
]);
|
|
697
|
+
const vector2Schema = z.object({
|
|
698
|
+
x: finiteSchema$3,
|
|
699
|
+
y: finiteSchema$3
|
|
700
|
+
}).strict();
|
|
701
|
+
const scaleSchema = z.union([finiteSchema$3.positive(), z.object({
|
|
702
|
+
x: finiteSchema$3.positive(),
|
|
703
|
+
y: finiteSchema$3.positive()
|
|
704
|
+
}).strict()]);
|
|
705
|
+
const BOARD_ANIMATION_CHANNELS = {
|
|
706
|
+
"transform.translation": {
|
|
707
|
+
targets: ["item"],
|
|
708
|
+
value: vector2Schema,
|
|
709
|
+
interpolations: ["linear", "step"],
|
|
710
|
+
coordinateSpace: "world-offset",
|
|
711
|
+
unit: "board"
|
|
712
|
+
},
|
|
713
|
+
"transform.rotation": {
|
|
714
|
+
targets: ["item"],
|
|
715
|
+
value: finiteSchema$3,
|
|
716
|
+
interpolations: ["linear", "step"],
|
|
717
|
+
unit: "radian"
|
|
718
|
+
},
|
|
719
|
+
"transform.scale": {
|
|
720
|
+
targets: ["item"],
|
|
721
|
+
value: scaleSchema,
|
|
722
|
+
interpolations: ["linear", "step"],
|
|
723
|
+
unit: "ratio"
|
|
724
|
+
},
|
|
725
|
+
"style.opacity": {
|
|
726
|
+
targets: ["item"],
|
|
727
|
+
value: finiteSchema$3.min(0).max(1),
|
|
728
|
+
interpolations: ["linear", "step"],
|
|
729
|
+
unit: "ratio"
|
|
730
|
+
}
|
|
731
|
+
};
|
|
732
|
+
const BoardTrackKeyframeSchema = z.object({
|
|
733
|
+
time: finiteSchema$3.nonnegative(),
|
|
734
|
+
value: z.unknown(),
|
|
735
|
+
easing: BoardEasingSchema.optional()
|
|
736
|
+
}).strict();
|
|
737
|
+
const BoardTrackSchema = z.object({
|
|
738
|
+
id: idSchema$3,
|
|
739
|
+
target: BoardAnimationTargetSchema,
|
|
740
|
+
channel: z.string().min(1).max(160),
|
|
741
|
+
channelVersion: z.number().int().positive().default(1),
|
|
742
|
+
interpolation: z.enum(["linear", "step"]).default("linear"),
|
|
743
|
+
fill: z.enum([
|
|
744
|
+
"none",
|
|
745
|
+
"backwards",
|
|
746
|
+
"forwards",
|
|
747
|
+
"both"
|
|
748
|
+
]).default("none"),
|
|
749
|
+
keyframes: z.array(BoardTrackKeyframeSchema).min(1).max(1e5),
|
|
750
|
+
metadata: jsonObjectSchema$2.default({})
|
|
751
|
+
}).strict().superRefine((track, context) => {
|
|
752
|
+
let previous = -1;
|
|
753
|
+
for (const [index, keyframe] of track.keyframes.entries()) {
|
|
754
|
+
if (keyframe.time <= previous) context.addIssue({
|
|
755
|
+
code: "custom",
|
|
756
|
+
message: "keyframe times must be strictly increasing",
|
|
757
|
+
path: [
|
|
758
|
+
"keyframes",
|
|
759
|
+
index,
|
|
760
|
+
"time"
|
|
761
|
+
]
|
|
762
|
+
});
|
|
763
|
+
previous = keyframe.time;
|
|
764
|
+
}
|
|
765
|
+
const channel = BOARD_ANIMATION_CHANNELS[track.channel];
|
|
766
|
+
if (!channel) {
|
|
767
|
+
if (!/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+){2,}$/.test(track.channel)) context.addIssue({
|
|
768
|
+
code: "custom",
|
|
769
|
+
message: `unknown channel: ${track.channel}`,
|
|
770
|
+
path: ["channel"]
|
|
771
|
+
});
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
if (!channel.targets.includes(track.target.type)) context.addIssue({
|
|
775
|
+
code: "custom",
|
|
776
|
+
message: `${track.channel} cannot target ${track.target.type}`,
|
|
777
|
+
path: ["target"]
|
|
646
778
|
});
|
|
779
|
+
if (!channel.interpolations.includes(track.interpolation)) context.addIssue({
|
|
780
|
+
code: "custom",
|
|
781
|
+
message: `${track.channel} does not support ${track.interpolation} interpolation`,
|
|
782
|
+
path: ["interpolation"]
|
|
783
|
+
});
|
|
784
|
+
for (const [index, keyframe] of track.keyframes.entries()) {
|
|
785
|
+
const parsed = channel.value.safeParse(keyframe.value);
|
|
786
|
+
if (!parsed.success) context.addIssue({
|
|
787
|
+
code: "custom",
|
|
788
|
+
message: parsed.error.issues[0]?.message ?? `invalid value for ${track.channel}`,
|
|
789
|
+
path: [
|
|
790
|
+
"keyframes",
|
|
791
|
+
index,
|
|
792
|
+
"value"
|
|
793
|
+
]
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
});
|
|
797
|
+
const extensionKindSchema = z.string().regex(/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)+$/).max(160);
|
|
798
|
+
const BoardProceduralClipSchema = z.object({
|
|
799
|
+
id: idSchema$3,
|
|
800
|
+
kind: extensionKindSchema,
|
|
801
|
+
kindVersion: z.number().int().positive(),
|
|
802
|
+
target: BoardAnimationTargetSchema,
|
|
803
|
+
start: finiteSchema$3.nonnegative(),
|
|
804
|
+
duration: finiteSchema$3.positive(),
|
|
805
|
+
layer: z.enum([
|
|
806
|
+
"behind",
|
|
807
|
+
"content",
|
|
808
|
+
"front",
|
|
809
|
+
"screen"
|
|
810
|
+
]).default("content"),
|
|
811
|
+
fill: z.enum([
|
|
812
|
+
"none",
|
|
813
|
+
"backwards",
|
|
814
|
+
"forwards",
|
|
815
|
+
"both"
|
|
816
|
+
]).default("none"),
|
|
817
|
+
easing: BoardEasingSchema.default("linear"),
|
|
818
|
+
params: jsonObjectSchema$2.default({}),
|
|
819
|
+
assetRefs: z.array(z.object({
|
|
820
|
+
type: z.enum(["space-file", "extension"]),
|
|
821
|
+
ref: z.string().min(1).max(4096),
|
|
822
|
+
digest: z.string().min(16).max(160).optional()
|
|
823
|
+
}).strict()).default([]),
|
|
824
|
+
seed: idSchema$3,
|
|
825
|
+
metadata: jsonObjectSchema$2.default({})
|
|
826
|
+
}).strict();
|
|
827
|
+
const BoardTimelineMarkerSchema = z.object({
|
|
828
|
+
id: idSchema$3,
|
|
829
|
+
time: finiteSchema$3.nonnegative(),
|
|
830
|
+
duration: finiteSchema$3.nonnegative().optional(),
|
|
831
|
+
metadata: jsonObjectSchema$2.default({})
|
|
832
|
+
}).strict();
|
|
833
|
+
const BoardTimelineSchema = z.object({
|
|
834
|
+
duration: finiteSchema$3.nonnegative(),
|
|
835
|
+
tracks: z.array(BoardTrackSchema).max(5e4).default([]),
|
|
836
|
+
clips: z.array(BoardProceduralClipSchema).max(5e4).default([]),
|
|
837
|
+
markers: z.array(BoardTimelineMarkerSchema).max(1e4).default([])
|
|
838
|
+
}).strict().superRefine((timeline, context) => {
|
|
839
|
+
const ids = /* @__PURE__ */ new Set();
|
|
840
|
+
const channels = /* @__PURE__ */ new Set();
|
|
841
|
+
for (const [index, track] of timeline.tracks.entries()) {
|
|
842
|
+
if (ids.has(track.id)) context.addIssue({
|
|
843
|
+
code: "custom",
|
|
844
|
+
message: `duplicate timeline id: ${track.id}`,
|
|
845
|
+
path: [
|
|
846
|
+
"tracks",
|
|
847
|
+
index,
|
|
848
|
+
"id"
|
|
849
|
+
]
|
|
850
|
+
});
|
|
851
|
+
ids.add(track.id);
|
|
852
|
+
const targetId = track.target.type === "item" ? track.target.itemId : track.target.type === "effect" ? track.target.effectId : track.target.type;
|
|
853
|
+
const key = `${track.target.type}:${targetId}:${track.channel}`;
|
|
854
|
+
if (channels.has(key)) context.addIssue({
|
|
855
|
+
code: "custom",
|
|
856
|
+
message: `multiple tracks control ${key}`,
|
|
857
|
+
path: [
|
|
858
|
+
"tracks",
|
|
859
|
+
index,
|
|
860
|
+
"channel"
|
|
861
|
+
]
|
|
862
|
+
});
|
|
863
|
+
channels.add(key);
|
|
864
|
+
for (const [keyframeIndex, keyframe] of track.keyframes.entries()) if (keyframe.time > timeline.duration) context.addIssue({
|
|
865
|
+
code: "custom",
|
|
866
|
+
message: "keyframe exceeds timeline duration",
|
|
867
|
+
path: [
|
|
868
|
+
"tracks",
|
|
869
|
+
index,
|
|
870
|
+
"keyframes",
|
|
871
|
+
keyframeIndex,
|
|
872
|
+
"time"
|
|
873
|
+
]
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
for (const [index, clip] of timeline.clips.entries()) {
|
|
877
|
+
if (ids.has(clip.id)) context.addIssue({
|
|
878
|
+
code: "custom",
|
|
879
|
+
message: `duplicate timeline id: ${clip.id}`,
|
|
880
|
+
path: [
|
|
881
|
+
"clips",
|
|
882
|
+
index,
|
|
883
|
+
"id"
|
|
884
|
+
]
|
|
885
|
+
});
|
|
886
|
+
ids.add(clip.id);
|
|
887
|
+
if (clip.start + clip.duration > timeline.duration) context.addIssue({
|
|
888
|
+
code: "custom",
|
|
889
|
+
message: "clip exceeds timeline duration",
|
|
890
|
+
path: [
|
|
891
|
+
"clips",
|
|
892
|
+
index,
|
|
893
|
+
"duration"
|
|
894
|
+
]
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
for (const [index, marker] of timeline.markers.entries()) {
|
|
898
|
+
if (ids.has(marker.id)) context.addIssue({
|
|
899
|
+
code: "custom",
|
|
900
|
+
message: `duplicate timeline id: ${marker.id}`,
|
|
901
|
+
path: [
|
|
902
|
+
"markers",
|
|
903
|
+
index,
|
|
904
|
+
"id"
|
|
905
|
+
]
|
|
906
|
+
});
|
|
907
|
+
ids.add(marker.id);
|
|
908
|
+
if (marker.time + (marker.duration ?? 0) > timeline.duration) context.addIssue({
|
|
909
|
+
code: "custom",
|
|
910
|
+
message: "marker exceeds timeline duration",
|
|
911
|
+
path: ["markers", index]
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
const BoardCompositionPlaybackSchema = z.object({
|
|
916
|
+
loop: z.boolean().default(false),
|
|
917
|
+
endBehavior: z.enum(["hold", "reset"]).default("hold"),
|
|
918
|
+
reducedMotion: z.discriminatedUnion("mode", [
|
|
919
|
+
z.object({ mode: z.literal("base") }).strict(),
|
|
920
|
+
z.object({
|
|
921
|
+
mode: z.literal("time"),
|
|
922
|
+
time: finiteSchema$3.nonnegative()
|
|
923
|
+
}).strict(),
|
|
924
|
+
z.object({
|
|
925
|
+
mode: z.literal("marker"),
|
|
926
|
+
markerId: idSchema$3
|
|
927
|
+
}).strict()
|
|
928
|
+
]).default({ mode: "base" })
|
|
929
|
+
}).strict();
|
|
930
|
+
const compositionFields = {
|
|
931
|
+
id: idSchema$3,
|
|
932
|
+
name: z.string().min(1).max(255),
|
|
933
|
+
timeline: BoardTimelineSchema,
|
|
934
|
+
playback: BoardCompositionPlaybackSchema.default({
|
|
935
|
+
loop: false,
|
|
936
|
+
endBehavior: "hold",
|
|
937
|
+
reducedMotion: { mode: "base" }
|
|
938
|
+
}),
|
|
939
|
+
metadata: jsonObjectSchema$2.default({})
|
|
940
|
+
};
|
|
941
|
+
function validateCompositionFallback(composition, context) {
|
|
942
|
+
const fallback = composition.playback.reducedMotion;
|
|
943
|
+
if (fallback.mode === "time" && fallback.time > composition.timeline.duration) context.addIssue({
|
|
944
|
+
code: "custom",
|
|
945
|
+
message: "reduced-motion time exceeds timeline duration",
|
|
946
|
+
path: [
|
|
947
|
+
"playback",
|
|
948
|
+
"reducedMotion",
|
|
949
|
+
"time"
|
|
950
|
+
]
|
|
951
|
+
});
|
|
952
|
+
if (fallback.mode === "marker" && !composition.timeline.markers.some((marker) => marker.id === fallback.markerId)) context.addIssue({
|
|
953
|
+
code: "custom",
|
|
954
|
+
message: `marker does not exist: ${fallback.markerId}`,
|
|
955
|
+
path: [
|
|
956
|
+
"playback",
|
|
957
|
+
"reducedMotion",
|
|
958
|
+
"markerId"
|
|
959
|
+
]
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
const BoardCompositionInputSchema = z.object(compositionFields).strict().superRefine(validateCompositionFallback);
|
|
963
|
+
const BoardCompositionSchema = z.object({
|
|
964
|
+
...compositionFields,
|
|
965
|
+
revision: z.number().int().nonnegative().default(0)
|
|
966
|
+
}).strict().superRefine(validateCompositionFallback);
|
|
967
|
+
/** Accept inspect/get output as apply input while stripping server-owned revision. */
|
|
968
|
+
function parseBoardCompositionInput(value) {
|
|
969
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
970
|
+
const { revision: _revision, ...input } = value;
|
|
971
|
+
return BoardCompositionInputSchema.parse(input);
|
|
972
|
+
}
|
|
973
|
+
return BoardCompositionInputSchema.parse(value);
|
|
647
974
|
}
|
|
975
|
+
const BOARD_ANIMATION_CHANNEL_CAPABILITIES = Object.entries(BOARD_ANIMATION_CHANNELS).map(([id, definition]) => ({
|
|
976
|
+
id,
|
|
977
|
+
version: 1,
|
|
978
|
+
targets: definition.targets,
|
|
979
|
+
interpolations: definition.interpolations,
|
|
980
|
+
..."coordinateSpace" in definition ? { coordinateSpace: definition.coordinateSpace } : {},
|
|
981
|
+
..."unit" in definition ? { unit: definition.unit } : {},
|
|
982
|
+
valueSchema: z.toJSONSchema(definition.value)
|
|
983
|
+
}));
|
|
984
|
+
//#endregion
|
|
985
|
+
//#region ../protocol/dist/board-authoring.js
|
|
986
|
+
const BOARD_COLOR_IDS$1 = [
|
|
987
|
+
"brand",
|
|
988
|
+
"neutral",
|
|
989
|
+
"black",
|
|
990
|
+
"white",
|
|
991
|
+
"blue",
|
|
992
|
+
"green",
|
|
993
|
+
"amber",
|
|
994
|
+
"violet",
|
|
995
|
+
"rose"
|
|
996
|
+
];
|
|
997
|
+
const BOARD_GEO_KINDS$1 = [
|
|
998
|
+
"rectangle",
|
|
999
|
+
"rounded",
|
|
1000
|
+
"ellipse",
|
|
1001
|
+
"diamond",
|
|
1002
|
+
"triangle"
|
|
1003
|
+
];
|
|
1004
|
+
const idSchema$2 = z.string().min(1).max(160);
|
|
1005
|
+
const jsonObjectSchema$1 = z.record(z.string(), z.unknown());
|
|
1006
|
+
const finiteSchema$2 = z.number().finite();
|
|
1007
|
+
const extensionTypeSchema = z.string().regex(/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)+$/).max(160);
|
|
1008
|
+
const BoardAuthoringFrameSchema = z.object({
|
|
1009
|
+
x: finiteSchema$2,
|
|
1010
|
+
y: finiteSchema$2,
|
|
1011
|
+
width: finiteSchema$2.positive(),
|
|
1012
|
+
height: finiteSchema$2.positive(),
|
|
1013
|
+
rotation: finiteSchema$2.default(0)
|
|
1014
|
+
}).strict();
|
|
1015
|
+
const pointSchema$1 = z.object({
|
|
1016
|
+
x: finiteSchema$2,
|
|
1017
|
+
y: finiteSchema$2,
|
|
1018
|
+
p: finiteSchema$2.min(0).max(1).default(.5)
|
|
1019
|
+
}).strict();
|
|
1020
|
+
const worldPointSchema$1 = z.object({
|
|
1021
|
+
x: finiteSchema$2,
|
|
1022
|
+
y: finiteSchema$2
|
|
1023
|
+
}).strict();
|
|
1024
|
+
const cropSchema = z.object({
|
|
1025
|
+
x: finiteSchema$2.min(0).max(1),
|
|
1026
|
+
y: finiteSchema$2.min(0).max(1),
|
|
1027
|
+
w: finiteSchema$2.min(0).max(1),
|
|
1028
|
+
h: finiteSchema$2.min(0).max(1)
|
|
1029
|
+
}).strict();
|
|
1030
|
+
const BoardItemStyleSchema$1 = z.object({
|
|
1031
|
+
color: z.enum(BOARD_COLOR_IDS$1).optional(),
|
|
1032
|
+
strokeWidth: finiteSchema$2.min(1).max(64).optional(),
|
|
1033
|
+
fillOpacity: finiteSchema$2.min(0).max(1).optional()
|
|
1034
|
+
}).strict();
|
|
1035
|
+
const sourceSnapshotSchema = z.record(z.string(), z.unknown());
|
|
1036
|
+
function isSafeBoardSourcePath(value) {
|
|
1037
|
+
return value.length > 0 && value.length <= 4096 && !value.startsWith("/") && !value.startsWith("\\") && !value.includes("\\") && value.split("/").every((part) => part.length > 0 && part !== "." && part !== "..");
|
|
1038
|
+
}
|
|
1039
|
+
const BoardItemSourceSchema = z.object({
|
|
1040
|
+
kind: z.literal("space-file"),
|
|
1041
|
+
path: z.string().refine(isSafeBoardSourcePath, "source path must be a safe relative Board file path"),
|
|
1042
|
+
snapshot: sourceSnapshotSchema.optional()
|
|
1043
|
+
}).strict();
|
|
1044
|
+
const baseFields = {
|
|
1045
|
+
id: idSchema$2,
|
|
1046
|
+
frame: BoardAuthoringFrameSchema,
|
|
1047
|
+
parentId: idSchema$2.nullable().optional(),
|
|
1048
|
+
locked: z.boolean().optional(),
|
|
1049
|
+
metadata: jsonObjectSchema$1.optional()
|
|
1050
|
+
};
|
|
1051
|
+
const styledBaseFields = {
|
|
1052
|
+
...baseFields,
|
|
1053
|
+
style: BoardItemStyleSchema$1.optional()
|
|
1054
|
+
};
|
|
1055
|
+
const BoardTextAuthoringItemSchema = z.object({
|
|
1056
|
+
...styledBaseFields,
|
|
1057
|
+
type: z.literal("text"),
|
|
1058
|
+
props: z.object({
|
|
1059
|
+
text: z.string().default(""),
|
|
1060
|
+
fontSize: finiteSchema$2.min(2).max(512).default(24)
|
|
1061
|
+
}).strict()
|
|
1062
|
+
}).strict();
|
|
1063
|
+
const BoardGeoAuthoringItemSchema = z.object({
|
|
1064
|
+
...styledBaseFields,
|
|
1065
|
+
type: z.literal("geo"),
|
|
1066
|
+
props: z.object({
|
|
1067
|
+
shape: z.enum(BOARD_GEO_KINDS$1).default("rectangle"),
|
|
1068
|
+
text: z.string().default("")
|
|
1069
|
+
}).strict()
|
|
1070
|
+
}).strict();
|
|
1071
|
+
const BoardDrawAuthoringItemSchema = z.object({
|
|
1072
|
+
...styledBaseFields,
|
|
1073
|
+
type: z.literal("draw"),
|
|
1074
|
+
props: z.object({ points: z.array(pointSchema$1).min(1) }).strict()
|
|
1075
|
+
}).strict();
|
|
1076
|
+
const BoardArrowAuthoringItemSchema = z.object({
|
|
1077
|
+
...styledBaseFields,
|
|
1078
|
+
type: z.literal("arrow"),
|
|
1079
|
+
props: z.object({
|
|
1080
|
+
start: worldPointSchema$1,
|
|
1081
|
+
end: worldPointSchema$1,
|
|
1082
|
+
bend: finiteSchema$2.min(-.85).max(.85).default(0),
|
|
1083
|
+
arrowStart: z.boolean().default(false),
|
|
1084
|
+
arrowEnd: z.boolean().default(true),
|
|
1085
|
+
label: z.string().default("")
|
|
1086
|
+
}).strict()
|
|
1087
|
+
}).strict();
|
|
1088
|
+
const BoardFrameAuthoringItemSchema = z.object({
|
|
1089
|
+
...styledBaseFields,
|
|
1090
|
+
type: z.literal("frame"),
|
|
1091
|
+
props: z.object({ label: z.string().default("Frame") }).strict()
|
|
1092
|
+
}).strict();
|
|
1093
|
+
const fileBackedFields = {
|
|
1094
|
+
...baseFields,
|
|
1095
|
+
style: z.object({}).strict().optional(),
|
|
1096
|
+
source: BoardItemSourceSchema
|
|
1097
|
+
};
|
|
1098
|
+
const builtinItemSchemas = [
|
|
1099
|
+
BoardTextAuthoringItemSchema,
|
|
1100
|
+
BoardGeoAuthoringItemSchema,
|
|
1101
|
+
BoardDrawAuthoringItemSchema,
|
|
1102
|
+
BoardArrowAuthoringItemSchema,
|
|
1103
|
+
BoardFrameAuthoringItemSchema,
|
|
1104
|
+
z.object({
|
|
1105
|
+
...fileBackedFields,
|
|
1106
|
+
type: z.literal("image"),
|
|
1107
|
+
props: z.object({ crop: cropSchema.optional() }).strict()
|
|
1108
|
+
}).strict(),
|
|
1109
|
+
z.object({
|
|
1110
|
+
...fileBackedFields,
|
|
1111
|
+
type: z.literal("video"),
|
|
1112
|
+
props: z.object({}).strict()
|
|
1113
|
+
}).strict(),
|
|
1114
|
+
z.object({
|
|
1115
|
+
...fileBackedFields,
|
|
1116
|
+
type: z.literal("audio"),
|
|
1117
|
+
props: z.object({}).strict()
|
|
1118
|
+
}).strict(),
|
|
1119
|
+
z.object({
|
|
1120
|
+
...fileBackedFields,
|
|
1121
|
+
type: z.literal("file"),
|
|
1122
|
+
props: z.object({}).strict()
|
|
1123
|
+
}).strict(),
|
|
1124
|
+
z.object({
|
|
1125
|
+
...baseFields,
|
|
1126
|
+
type: z.literal("task"),
|
|
1127
|
+
props: z.object({
|
|
1128
|
+
taskRunId: z.string().min(1),
|
|
1129
|
+
snapshot: z.record(z.string(), z.unknown())
|
|
1130
|
+
}).strict(),
|
|
1131
|
+
style: z.object({}).strict().optional()
|
|
1132
|
+
}).strict()
|
|
1133
|
+
];
|
|
1134
|
+
const BoardBuiltinAuthoringItemSchema = z.discriminatedUnion("type", builtinItemSchemas);
|
|
1135
|
+
const BoardExtensionAuthoringItemSchema = z.object({
|
|
1136
|
+
...baseFields,
|
|
1137
|
+
type: extensionTypeSchema,
|
|
1138
|
+
kindVersion: z.number().int().positive(),
|
|
1139
|
+
props: jsonObjectSchema$1,
|
|
1140
|
+
style: jsonObjectSchema$1.optional(),
|
|
1141
|
+
source: z.object({
|
|
1142
|
+
kind: z.string().min(1).max(80),
|
|
1143
|
+
ref: z.string().min(1).max(4096),
|
|
1144
|
+
snapshot: jsonObjectSchema$1.optional()
|
|
1145
|
+
}).strict().optional()
|
|
1146
|
+
}).strict();
|
|
1147
|
+
const BoardAuthoringItemSchema = z.union([BoardBuiltinAuthoringItemSchema, BoardExtensionAuthoringItemSchema]);
|
|
1148
|
+
const framePatchSchema = z.object({
|
|
1149
|
+
x: finiteSchema$2.optional(),
|
|
1150
|
+
y: finiteSchema$2.optional(),
|
|
1151
|
+
width: finiteSchema$2.positive().optional(),
|
|
1152
|
+
height: finiteSchema$2.positive().optional(),
|
|
1153
|
+
rotation: finiteSchema$2.optional()
|
|
1154
|
+
}).strict();
|
|
1155
|
+
/** JSON Merge Patch semantics, constrained to the stable Item envelope. */
|
|
1156
|
+
const BoardItemPatchSchema = z.object({
|
|
1157
|
+
frame: framePatchSchema.optional(),
|
|
1158
|
+
parentId: idSchema$2.nullable().optional(),
|
|
1159
|
+
locked: z.boolean().nullable().optional(),
|
|
1160
|
+
props: jsonObjectSchema$1.optional(),
|
|
1161
|
+
style: jsonObjectSchema$1.nullable().optional(),
|
|
1162
|
+
source: jsonObjectSchema$1.nullable().optional(),
|
|
1163
|
+
metadata: jsonObjectSchema$1.nullable().optional()
|
|
1164
|
+
}).strict().refine((patch) => Object.keys(patch).length > 0, "item patch is empty");
|
|
1165
|
+
const BoardSemanticCommandSchema = z.discriminatedUnion("type", [
|
|
1166
|
+
z.object({
|
|
1167
|
+
type: z.literal("item.create"),
|
|
1168
|
+
item: BoardAuthoringItemSchema
|
|
1169
|
+
}).strict(),
|
|
1170
|
+
z.object({
|
|
1171
|
+
type: z.literal("item.patch"),
|
|
1172
|
+
itemId: idSchema$2,
|
|
1173
|
+
patch: BoardItemPatchSchema
|
|
1174
|
+
}).strict(),
|
|
1175
|
+
z.object({
|
|
1176
|
+
type: z.literal("item.replace"),
|
|
1177
|
+
itemId: idSchema$2,
|
|
1178
|
+
item: BoardAuthoringItemSchema
|
|
1179
|
+
}).strict(),
|
|
1180
|
+
z.object({
|
|
1181
|
+
type: z.literal("item.delete"),
|
|
1182
|
+
itemId: idSchema$2,
|
|
1183
|
+
cascade: z.boolean().default(false)
|
|
1184
|
+
}).strict()
|
|
1185
|
+
]);
|
|
1186
|
+
z.object({
|
|
1187
|
+
mutationId: idSchema$2,
|
|
1188
|
+
baseVersion: z.number().int().nonnegative(),
|
|
1189
|
+
clientId: idSchema$2.optional(),
|
|
1190
|
+
undoGroupId: idSchema$2.optional(),
|
|
1191
|
+
commands: z.array(BoardSemanticCommandSchema).min(1).max(5e4)
|
|
1192
|
+
}).strict();
|
|
648
1193
|
//#endregion
|
|
649
1194
|
//#region ../protocol/dist/board.js
|
|
650
1195
|
const BOARD_DOCUMENT_KIND = "cohub.board";
|
|
@@ -659,62 +1204,59 @@ z.object({
|
|
|
659
1204
|
boardId: z.string().uuid(),
|
|
660
1205
|
title: z.string().min(1).max(255)
|
|
661
1206
|
});
|
|
662
|
-
|
|
1207
|
+
z.object({
|
|
1208
|
+
centerX: finiteSchema$1,
|
|
1209
|
+
centerY: finiteSchema$1,
|
|
1210
|
+
zoom: finiteSchema$1.positive()
|
|
1211
|
+
});
|
|
1212
|
+
const BoardCameraFocusSchema = z.discriminatedUnion("type", [
|
|
663
1213
|
z.object({
|
|
664
|
-
type: z.literal("
|
|
665
|
-
|
|
1214
|
+
type: z.literal("rect"),
|
|
1215
|
+
rect: z.object({
|
|
1216
|
+
x: finiteSchema$1,
|
|
1217
|
+
y: finiteSchema$1,
|
|
1218
|
+
width: finiteSchema$1.positive(),
|
|
1219
|
+
height: finiteSchema$1.positive()
|
|
1220
|
+
})
|
|
666
1221
|
}),
|
|
667
1222
|
z.object({
|
|
668
|
-
type: z.literal("
|
|
669
|
-
|
|
1223
|
+
type: z.literal("item"),
|
|
1224
|
+
itemId: idSchema$1
|
|
1225
|
+
}),
|
|
1226
|
+
z.object({
|
|
1227
|
+
type: z.literal("items"),
|
|
1228
|
+
itemIds: z.array(idSchema$1).min(1).max(1e3)
|
|
670
1229
|
}),
|
|
671
|
-
z.object({
|
|
672
|
-
|
|
1230
|
+
z.object({
|
|
1231
|
+
type: z.literal("frame"),
|
|
1232
|
+
frameId: idSchema$1
|
|
1233
|
+
})
|
|
673
1234
|
]);
|
|
1235
|
+
const BoardCameraFocusParamsSchema = z.object({
|
|
1236
|
+
focus: BoardCameraFocusSchema,
|
|
1237
|
+
fit: z.enum(["contain", "cover"]).default("contain"),
|
|
1238
|
+
padding: finiteSchema$1.nonnegative().default(32),
|
|
1239
|
+
minZoom: finiteSchema$1.positive().optional(),
|
|
1240
|
+
maxZoom: finiteSchema$1.positive().optional()
|
|
1241
|
+
}).superRefine((value, context) => {
|
|
1242
|
+
if (value.minZoom !== void 0 && value.maxZoom !== void 0 && value.minZoom > value.maxZoom) context.addIssue({
|
|
1243
|
+
code: "custom",
|
|
1244
|
+
message: "minZoom must not exceed maxZoom",
|
|
1245
|
+
path: ["minZoom"]
|
|
1246
|
+
});
|
|
1247
|
+
});
|
|
674
1248
|
const BoardAssetRefSchema = z.object({
|
|
675
1249
|
type: z.enum(["space-file", "extension"]),
|
|
676
1250
|
ref: z.string().min(1).max(4096),
|
|
677
1251
|
digest: z.string().min(16).max(160).optional()
|
|
678
1252
|
});
|
|
679
|
-
const BoardKeyframeSchema = z.object({
|
|
680
|
-
at: finiteSchema$1.nonnegative(),
|
|
681
|
-
value: z.unknown(),
|
|
682
|
-
easing: z.string().min(1).max(80).optional()
|
|
683
|
-
});
|
|
684
|
-
const BoardClipSchema = z.object({
|
|
685
|
-
id: idSchema$1,
|
|
686
|
-
sequenceId: idSchema$1,
|
|
687
|
-
kind: extensionIdSchema,
|
|
688
|
-
kindVersion: z.number().int().positive(),
|
|
689
|
-
target: BoardTargetSchema,
|
|
690
|
-
start: finiteSchema$1.nonnegative(),
|
|
691
|
-
duration: finiteSchema$1.positive(),
|
|
692
|
-
layer: z.enum([
|
|
693
|
-
"behind",
|
|
694
|
-
"content",
|
|
695
|
-
"front",
|
|
696
|
-
"screen"
|
|
697
|
-
]).default("content"),
|
|
698
|
-
fill: z.enum([
|
|
699
|
-
"none",
|
|
700
|
-
"backwards",
|
|
701
|
-
"forwards",
|
|
702
|
-
"both"
|
|
703
|
-
]).default("none"),
|
|
704
|
-
easing: z.string().min(1).max(80).default("linear"),
|
|
705
|
-
params: jsonObjectSchema.default({}),
|
|
706
|
-
keyframes: z.array(BoardKeyframeSchema).default([]),
|
|
707
|
-
assetRefs: z.array(BoardAssetRefSchema).default([]),
|
|
708
|
-
seed: z.string().min(1).max(160),
|
|
709
|
-
metadata: jsonObjectSchema.default({})
|
|
710
|
-
});
|
|
711
1253
|
const BoardEffectSchema = z.object({
|
|
712
1254
|
id: idSchema$1,
|
|
713
1255
|
boardId: z.string().uuid(),
|
|
714
1256
|
target: z.discriminatedUnion("type", [z.object({
|
|
715
|
-
type: z.literal("
|
|
716
|
-
|
|
717
|
-
}), z.object({ type: z.literal("board") })]),
|
|
1257
|
+
type: z.literal("item"),
|
|
1258
|
+
itemId: idSchema$1
|
|
1259
|
+
}).strict(), z.object({ type: z.literal("board") }).strict()]),
|
|
718
1260
|
kind: extensionIdSchema,
|
|
719
1261
|
kindVersion: z.number().int().positive(),
|
|
720
1262
|
enabled: z.boolean().default(true),
|
|
@@ -739,17 +1281,7 @@ const BoardEffectSchema = z.object({
|
|
|
739
1281
|
metadata: jsonObjectSchema.default({}),
|
|
740
1282
|
revision: z.number().int().nonnegative()
|
|
741
1283
|
});
|
|
742
|
-
|
|
743
|
-
id: idSchema$1,
|
|
744
|
-
boardId: z.string().uuid(),
|
|
745
|
-
name: z.string().min(1).max(255),
|
|
746
|
-
duration: finiteSchema$1.nonnegative(),
|
|
747
|
-
seed: z.string().min(1).max(160),
|
|
748
|
-
restPose: jsonObjectSchema.default({}),
|
|
749
|
-
metadata: jsonObjectSchema.default({}),
|
|
750
|
-
revision: z.number().int().nonnegative()
|
|
751
|
-
});
|
|
752
|
-
const BoardNodeInputSchema = z.object({
|
|
1284
|
+
z.object({
|
|
753
1285
|
nodeId: idSchema$1,
|
|
754
1286
|
type: z.string().min(1).max(40),
|
|
755
1287
|
parentId: idSchema$1.nullable(),
|
|
@@ -772,27 +1304,20 @@ z.object({
|
|
|
772
1304
|
mutationId: z.string().max(128).optional(),
|
|
773
1305
|
title: z.string().min(1).max(255).optional(),
|
|
774
1306
|
metadata: jsonObjectSchema.optional(),
|
|
775
|
-
|
|
1307
|
+
items: z.array(BoardAuthoringItemSchema).max(5e4).optional(),
|
|
776
1308
|
connections: z.array(BoardConnectionSchema).max(5e4).optional(),
|
|
777
1309
|
effects: z.array(BoardEffectSchema.omit({
|
|
778
1310
|
boardId: true,
|
|
779
1311
|
revision: true
|
|
780
1312
|
})).optional(),
|
|
781
|
-
|
|
782
|
-
sequence: BoardSequenceSchema.omit({
|
|
783
|
-
boardId: true,
|
|
784
|
-
revision: true
|
|
785
|
-
}),
|
|
786
|
-
clips: z.array(BoardClipSchema.omit({ sequenceId: true }))
|
|
787
|
-
})).optional()
|
|
1313
|
+
compositions: z.array(BoardCompositionInputSchema).optional()
|
|
788
1314
|
});
|
|
789
1315
|
z.object({
|
|
790
1316
|
include: z.array(z.enum([
|
|
791
1317
|
"nodes",
|
|
792
1318
|
"connections",
|
|
793
1319
|
"effects",
|
|
794
|
-
"
|
|
795
|
-
"clips",
|
|
1320
|
+
"compositions",
|
|
796
1321
|
"playback"
|
|
797
1322
|
])).optional(),
|
|
798
1323
|
viewport: z.object({
|
|
@@ -804,10 +1329,9 @@ z.object({
|
|
|
804
1329
|
});
|
|
805
1330
|
/** Persisted on `boards.metadata.playback`: how a Board plays when opened. */
|
|
806
1331
|
const BoardPlaybackPolicySchema = z.object({
|
|
807
|
-
|
|
1332
|
+
compositionId: idSchema$1,
|
|
808
1333
|
/** Delay before the first local playback after opening the Board, in milliseconds. */
|
|
809
|
-
delayMs: finiteSchema$1.nonnegative().default(0)
|
|
810
|
-
loop: z.boolean().default(false)
|
|
1334
|
+
delayMs: finiteSchema$1.nonnegative().default(0)
|
|
811
1335
|
});
|
|
812
1336
|
function parseBoardPlaybackPolicy(metadata) {
|
|
813
1337
|
const parsed = BoardPlaybackPolicySchema.safeParse(metadata.playback);
|
|
@@ -817,7 +1341,7 @@ z.discriminatedUnion("type", [
|
|
|
817
1341
|
z.object({
|
|
818
1342
|
commandId: idSchema$1,
|
|
819
1343
|
type: z.literal("play"),
|
|
820
|
-
|
|
1344
|
+
compositionId: idSchema$1,
|
|
821
1345
|
position: finiteSchema$1.nonnegative().optional(),
|
|
822
1346
|
timeScale: finiteSchema$1.positive().max(4).optional(),
|
|
823
1347
|
shared: z.boolean().optional(),
|
|
@@ -840,27 +1364,77 @@ z.discriminatedUnion("type", [
|
|
|
840
1364
|
playbackId: z.string().uuid()
|
|
841
1365
|
})
|
|
842
1366
|
]);
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
]
|
|
852
|
-
const
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
})
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
1367
|
+
//#endregion
|
|
1368
|
+
//#region ../protocol/dist/board-capability-registry.js
|
|
1369
|
+
const CLIPS = new Set(BOARD_BUILTIN_CLIP_KINDS);
|
|
1370
|
+
new Set(BOARD_BUILTIN_EFFECT_KINDS);
|
|
1371
|
+
const record = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
1372
|
+
const finite = (value) => typeof value === "number" && Number.isFinite(value);
|
|
1373
|
+
function validateBuiltinBoardClip(clip, path = "clip") {
|
|
1374
|
+
if (!CLIPS.has(clip.kind)) return [];
|
|
1375
|
+
const errors = [];
|
|
1376
|
+
const error = (message, suffix, coordinateSpace, code = "INVALID_BOARD_CLIP") => {
|
|
1377
|
+
errors.push({
|
|
1378
|
+
severity: "error",
|
|
1379
|
+
code,
|
|
1380
|
+
message,
|
|
1381
|
+
path: `${path}.${suffix}`,
|
|
1382
|
+
...coordinateSpace ? { coordinateSpace } : {}
|
|
1383
|
+
});
|
|
1384
|
+
};
|
|
1385
|
+
if ((clip.kind.startsWith("motion.") || clip.kind.startsWith("draw.") || clip.kind === "text.reveal" || clip.kind === "effects.trail") && clip.target.type !== "item") error(`${clip.kind} must target an item`, "target");
|
|
1386
|
+
if (clip.kind.startsWith("camera.") && clip.target.type !== "camera") error(`${clip.kind} must target the camera`, "target");
|
|
1387
|
+
if (clip.kind === "motion.path") {
|
|
1388
|
+
const points = clip.params.points;
|
|
1389
|
+
if (!Array.isArray(points) || points.length < 2 || points.length > 1e4) error("motion path must contain 2 to 10000 world-offset points", "params.points", "world-offset");
|
|
1390
|
+
else for (const [index, point] of points.entries()) if (!record(point) || !finite(point.x) || !finite(point.y)) error("motion path point must contain finite x and y", `params.points.${index}`, "world-offset");
|
|
1391
|
+
}
|
|
1392
|
+
if (clip.kind === "effects.particles") {
|
|
1393
|
+
const count = clip.params.count;
|
|
1394
|
+
if (!Number.isSafeInteger(count) || count < 1 || count > DEFAULT_BOARD_RENDER_LIMITS.particles) error(`particle count must be an integer from 1 to ${DEFAULT_BOARD_RENDER_LIMITS.particles}`, "params.count", void 0, "INVALID_PARTICLE_COUNT");
|
|
1395
|
+
const bounds = clip.params.bounds;
|
|
1396
|
+
if (!record(bounds) || !finite(bounds.x) || !finite(bounds.y) || !finite(bounds.width) || !finite(bounds.height) || bounds.width <= 0 || bounds.height <= 0) error("particles require positive finite world bounds", "params.bounds", "world", "PARTICLE_BOUNDS_REQUIRED");
|
|
1397
|
+
}
|
|
1398
|
+
if (clip.kind === "camera.focus") {
|
|
1399
|
+
const parsed = BoardCameraFocusParamsSchema.safeParse(clip.params);
|
|
1400
|
+
if (!parsed.success) error(parsed.error.issues[0]?.message ?? "invalid camera focus", "params", "world");
|
|
1401
|
+
}
|
|
1402
|
+
return errors;
|
|
1403
|
+
}
|
|
1404
|
+
function estimateBuiltinBoardClipCost(clip) {
|
|
1405
|
+
switch (clip.kind) {
|
|
1406
|
+
case "effects.particles": {
|
|
1407
|
+
const count = Number.isSafeInteger(clip.params.count) ? Math.max(0, clip.params.count) : 0;
|
|
1408
|
+
return {
|
|
1409
|
+
particles: count,
|
|
1410
|
+
vertices: count * 4,
|
|
1411
|
+
dynamicVertices: count * 4,
|
|
1412
|
+
drawCalls: 1,
|
|
1413
|
+
bufferBytes: count * 48,
|
|
1414
|
+
simulationSteps: count
|
|
1415
|
+
};
|
|
1416
|
+
}
|
|
1417
|
+
case "effects.trail": return {
|
|
1418
|
+
vertices: 32,
|
|
1419
|
+
dynamicVertices: 32,
|
|
1420
|
+
drawCalls: 1,
|
|
1421
|
+
bufferBytes: 1024,
|
|
1422
|
+
simulationSteps: 16
|
|
1423
|
+
};
|
|
1424
|
+
case "effects.impact":
|
|
1425
|
+
case "effects.flash": return {
|
|
1426
|
+
vertices: 64,
|
|
1427
|
+
drawCalls: 1
|
|
1428
|
+
};
|
|
1429
|
+
case "draw.reveal":
|
|
1430
|
+
case "draw.handwrite": return {
|
|
1431
|
+
drawCalls: 1,
|
|
1432
|
+
dynamicVertices: 1
|
|
1433
|
+
};
|
|
1434
|
+
case "motion.path": return { simulationSteps: Array.isArray(clip.params.points) ? clip.params.points.length : 0 };
|
|
1435
|
+
default: return {};
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
864
1438
|
//#endregion
|
|
865
1439
|
//#region ../protocol/dist/board-url.js
|
|
866
1440
|
const BOARD_REMOTE_URL_MAX_LENGTH = 4096;
|
|
@@ -916,11 +1490,16 @@ function isBlockedIpv6(host) {
|
|
|
916
1490
|
if ((first & 65280) === 65280) return true;
|
|
917
1491
|
return parts[0] === "2001" && parts[1] === "0db8";
|
|
918
1492
|
}
|
|
1493
|
+
function isPublicBoardRemoteAddress(value) {
|
|
1494
|
+
const address = value.toLowerCase().replace(/^\[|\]$/g, "").replace(/\.$/, "");
|
|
1495
|
+
if (parseIpv4(address)) return !isBlockedIpv4(address);
|
|
1496
|
+
return address.includes(":") && !isBlockedIpv6(address);
|
|
1497
|
+
}
|
|
919
1498
|
function isBlockedHost(hostname) {
|
|
920
1499
|
const host = hostname.toLowerCase().replace(/^\[|\]$/g, "").replace(/\.$/, "");
|
|
921
1500
|
if (host === "localhost" || host.endsWith(".localhost") || host.endsWith(".local") || host.endsWith(".internal")) return true;
|
|
922
|
-
if (parseIpv4(host)) return
|
|
923
|
-
return
|
|
1501
|
+
if (parseIpv4(host) || host.includes(":")) return !isPublicBoardRemoteAddress(host);
|
|
1502
|
+
return false;
|
|
924
1503
|
}
|
|
925
1504
|
/**
|
|
926
1505
|
* Normalize a browser-loadable public HTTP(S) URL. This blocks explicit local
|
|
@@ -974,7 +1553,20 @@ const BoardAppearanceSchema = z.object({
|
|
|
974
1553
|
"custom"
|
|
975
1554
|
]).default("dots"),
|
|
976
1555
|
color: z.string().optional(),
|
|
977
|
-
imageUrl:
|
|
1556
|
+
imageUrl: BoardRemoteUrlSchema.optional(),
|
|
1557
|
+
fit: z.enum([
|
|
1558
|
+
"cover",
|
|
1559
|
+
"contain",
|
|
1560
|
+
"repeat"
|
|
1561
|
+
]).optional(),
|
|
1562
|
+
position: z.enum([
|
|
1563
|
+
"center",
|
|
1564
|
+
"top",
|
|
1565
|
+
"bottom",
|
|
1566
|
+
"left",
|
|
1567
|
+
"right"
|
|
1568
|
+
]).optional(),
|
|
1569
|
+
opacity: z.number().finite().min(0).max(1).optional()
|
|
978
1570
|
}).default({ kind: "solid" }),
|
|
979
1571
|
grid: z.object({
|
|
980
1572
|
visible: z.boolean().default(false),
|
|
@@ -1573,6 +2165,27 @@ function validateBoardNodeInput(node, path = "node") {
|
|
|
1573
2165
|
}
|
|
1574
2166
|
return [];
|
|
1575
2167
|
}
|
|
2168
|
+
const BoardContentKindSchema = z.enum([
|
|
2169
|
+
"text",
|
|
2170
|
+
"image",
|
|
2171
|
+
"video",
|
|
2172
|
+
"audio",
|
|
2173
|
+
"file",
|
|
2174
|
+
"json",
|
|
2175
|
+
"collection"
|
|
2176
|
+
]);
|
|
2177
|
+
const BoardPortSchema = z.object({
|
|
2178
|
+
id: z.string().min(1).max(120),
|
|
2179
|
+
kind: BoardContentKindSchema,
|
|
2180
|
+
role: z.string().min(1).max(80).optional(),
|
|
2181
|
+
required: z.boolean().optional(),
|
|
2182
|
+
multiple: z.boolean().optional(),
|
|
2183
|
+
maxItems: z.number().int().positive().optional()
|
|
2184
|
+
}).strict();
|
|
2185
|
+
z.object({
|
|
2186
|
+
inputs: z.array(BoardPortSchema),
|
|
2187
|
+
outputs: z.array(BoardPortSchema)
|
|
2188
|
+
}).strict();
|
|
1576
2189
|
//#endregion
|
|
1577
2190
|
//#region ../protocol/dist/realtime/board-awareness.js
|
|
1578
2191
|
const idSchema = z.string().min(1).max(160);
|
|
@@ -2033,186 +2646,12 @@ const buildWorkComposerChipClear = (key) => ({
|
|
|
2033
2646
|
key
|
|
2034
2647
|
});
|
|
2035
2648
|
//#endregion
|
|
2036
|
-
//#region src/
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
}
|
|
2042
|
-
/** Axis-aligned bounds of a stroke in its local space, padded by stroke width. */
|
|
2043
|
-
function computeDrawBounds(points, size) {
|
|
2044
|
-
if (points.length === 0) return {
|
|
2045
|
-
x: 0,
|
|
2046
|
-
y: 0,
|
|
2047
|
-
width: 1,
|
|
2048
|
-
height: 1
|
|
2049
|
-
};
|
|
2050
|
-
let minX = Number.POSITIVE_INFINITY;
|
|
2051
|
-
let minY = Number.POSITIVE_INFINITY;
|
|
2052
|
-
let maxX = Number.NEGATIVE_INFINITY;
|
|
2053
|
-
let maxY = Number.NEGATIVE_INFINITY;
|
|
2054
|
-
for (const point of points) {
|
|
2055
|
-
const r = sampleRadius(size, point.p);
|
|
2056
|
-
minX = Math.min(minX, point.x - r);
|
|
2057
|
-
minY = Math.min(minY, point.y - r);
|
|
2058
|
-
maxX = Math.max(maxX, point.x + r);
|
|
2059
|
-
maxY = Math.max(maxY, point.y + r);
|
|
2060
|
-
}
|
|
2061
|
-
return {
|
|
2062
|
-
x: minX,
|
|
2063
|
-
y: minY,
|
|
2064
|
-
width: Math.max(1, maxX - minX),
|
|
2065
|
-
height: Math.max(1, maxY - minY)
|
|
2066
|
-
};
|
|
2067
|
-
}
|
|
2068
|
-
//#endregion
|
|
2069
|
-
//#region src/board/nodes.ts
|
|
2070
|
-
var BoardInputError = class extends Error {
|
|
2071
|
-
code = "INVALID_BOARD_NODE";
|
|
2072
|
-
diagnostics;
|
|
2073
|
-
body;
|
|
2074
|
-
constructor(diagnostics) {
|
|
2075
|
-
const message = diagnostics[0]?.message ?? "Invalid Board node";
|
|
2076
|
-
super(message);
|
|
2077
|
-
this.name = "BoardInputError";
|
|
2078
|
-
this.diagnostics = diagnostics;
|
|
2079
|
-
this.body = {
|
|
2080
|
-
code: this.code,
|
|
2081
|
-
message,
|
|
2082
|
-
diagnostics
|
|
2083
|
-
};
|
|
2084
|
-
}
|
|
2085
|
-
};
|
|
2086
|
-
function baseNode(spec, frame) {
|
|
2087
|
-
return {
|
|
2088
|
-
nodeId: spec.id,
|
|
2089
|
-
type: spec.type,
|
|
2090
|
-
parentId: spec.parentId ?? null,
|
|
2091
|
-
orderKey: spec.orderKey ?? null,
|
|
2092
|
-
x: frame.x,
|
|
2093
|
-
y: frame.y,
|
|
2094
|
-
width: frame.width,
|
|
2095
|
-
height: frame.height,
|
|
2096
|
-
rotation: frame.rotation ?? 0,
|
|
2097
|
-
refKind: null,
|
|
2098
|
-
refPath: null,
|
|
2099
|
-
refUrl: null,
|
|
2100
|
-
view: {},
|
|
2101
|
-
style: spec.style ?? {},
|
|
2102
|
-
data: {}
|
|
2103
|
-
};
|
|
2104
|
-
}
|
|
2105
|
-
function arrowFrame(start, end) {
|
|
2106
|
-
const padding = 16;
|
|
2107
|
-
return {
|
|
2108
|
-
x: Math.min(start.x, end.x) - padding,
|
|
2109
|
-
y: Math.min(start.y, end.y) - padding,
|
|
2110
|
-
width: Math.max(1, Math.abs(end.x - start.x) + padding * 2),
|
|
2111
|
-
height: Math.max(1, Math.abs(end.y - start.y) + padding * 2)
|
|
2112
|
-
};
|
|
2113
|
-
}
|
|
2114
|
-
/**
|
|
2115
|
-
* Create one validated wire node from semantic Board input.
|
|
2116
|
-
*
|
|
2117
|
-
* Box nodes take an explicit world-space frame. Draw samples and arrow endpoints
|
|
2118
|
-
* take world coordinates; the builder derives their frame and local storage form.
|
|
2119
|
-
*/
|
|
2120
|
-
function createBoardNode(spec) {
|
|
2121
|
-
let node;
|
|
2122
|
-
if (spec.type === "draw") {
|
|
2123
|
-
const size = spec.size ?? 4;
|
|
2124
|
-
const worldPoints = spec.points.map((point) => ({
|
|
2125
|
-
x: point.x,
|
|
2126
|
-
y: point.y,
|
|
2127
|
-
p: point.p ?? .5
|
|
2128
|
-
}));
|
|
2129
|
-
const bounds = computeDrawBounds(worldPoints, size);
|
|
2130
|
-
node = baseNode(spec, bounds);
|
|
2131
|
-
node.data = {
|
|
2132
|
-
points: worldPoints.map((point) => ({
|
|
2133
|
-
x: point.x - bounds.x,
|
|
2134
|
-
y: point.y - bounds.y,
|
|
2135
|
-
p: point.p
|
|
2136
|
-
})),
|
|
2137
|
-
color: spec.color ?? "brand",
|
|
2138
|
-
size
|
|
2139
|
-
};
|
|
2140
|
-
} else if (spec.type === "arrow") {
|
|
2141
|
-
node = baseNode(spec, arrowFrame(spec.start, spec.end));
|
|
2142
|
-
node.data = {
|
|
2143
|
-
start: spec.start,
|
|
2144
|
-
end: spec.end,
|
|
2145
|
-
bend: spec.bend ?? 0,
|
|
2146
|
-
color: spec.color ?? "brand",
|
|
2147
|
-
size: spec.size ?? 2.5,
|
|
2148
|
-
arrowStart: spec.arrowStart ?? false,
|
|
2149
|
-
arrowEnd: spec.arrowEnd ?? true,
|
|
2150
|
-
label: spec.label ?? ""
|
|
2151
|
-
};
|
|
2152
|
-
} else {
|
|
2153
|
-
node = baseNode(spec, spec.frame);
|
|
2154
|
-
switch (spec.type) {
|
|
2155
|
-
case "text":
|
|
2156
|
-
node.data = {
|
|
2157
|
-
text: spec.text ?? "",
|
|
2158
|
-
color: spec.color ?? "neutral",
|
|
2159
|
-
fontSize: spec.fontSize ?? 24
|
|
2160
|
-
};
|
|
2161
|
-
break;
|
|
2162
|
-
case "geo":
|
|
2163
|
-
node.data = {
|
|
2164
|
-
geo: spec.geo ?? "rectangle",
|
|
2165
|
-
text: spec.text ?? "",
|
|
2166
|
-
color: spec.color ?? "brand",
|
|
2167
|
-
fillOpacity: spec.fillOpacity ?? 0
|
|
2168
|
-
};
|
|
2169
|
-
break;
|
|
2170
|
-
case "frame":
|
|
2171
|
-
node.data = {
|
|
2172
|
-
label: spec.label ?? "Frame",
|
|
2173
|
-
color: spec.color ?? "neutral"
|
|
2174
|
-
};
|
|
2175
|
-
break;
|
|
2176
|
-
case "image":
|
|
2177
|
-
node.refKind = "space_file";
|
|
2178
|
-
node.refPath = spec.path;
|
|
2179
|
-
node.view = spec.snapshot ?? {};
|
|
2180
|
-
node.data = spec.crop ? { crop: spec.crop } : {};
|
|
2181
|
-
break;
|
|
2182
|
-
case "video":
|
|
2183
|
-
case "audio":
|
|
2184
|
-
node.refKind = "space_file";
|
|
2185
|
-
node.refPath = spec.path;
|
|
2186
|
-
node.view = spec.snapshot ?? {};
|
|
2187
|
-
break;
|
|
2188
|
-
case "file":
|
|
2189
|
-
node.refKind = "space_file";
|
|
2190
|
-
node.refPath = spec.path;
|
|
2191
|
-
node.view = spec.snapshot ?? {};
|
|
2192
|
-
break;
|
|
2193
|
-
case "task":
|
|
2194
|
-
node.view = spec.snapshot;
|
|
2195
|
-
node.data = { taskRunId: spec.taskRunId };
|
|
2196
|
-
break;
|
|
2197
|
-
}
|
|
2198
|
-
}
|
|
2199
|
-
assertBoardNodes([node]);
|
|
2200
|
-
return node;
|
|
2201
|
-
}
|
|
2202
|
-
function validateBoardNodes(nodes, path = "nodes") {
|
|
2203
|
-
return nodes.flatMap((node, index) => validateBoardNodeInput(node, `${path}.${index}`));
|
|
2204
|
-
}
|
|
2205
|
-
function assertBoardNodes(nodes, path = "nodes") {
|
|
2206
|
-
const diagnostics = validateBoardNodes(nodes, path);
|
|
2207
|
-
if (diagnostics.length > 0) throw new BoardInputError(diagnostics);
|
|
2208
|
-
}
|
|
2209
|
-
function assertBoardTransactionNodeCreates(operations) {
|
|
2210
|
-
const diagnostics = operations.flatMap((operation, index) => {
|
|
2211
|
-
if (operation.type !== "node.create") return [];
|
|
2212
|
-
const payload = operation.payload;
|
|
2213
|
-
return payload.node ? validateBoardNodeInput(payload.node, `operations.${index}.payload.node`) : [];
|
|
2649
|
+
//#region src/realtime.ts
|
|
2650
|
+
function ensureRealtimeConnected(websocketClient) {
|
|
2651
|
+
if (websocketClient.state === "open" || websocketClient.state === "connecting" || websocketClient.state === "reconnecting") return;
|
|
2652
|
+
websocketClient.connect().catch((error) => {
|
|
2653
|
+
console.error("[CohubClient] Failed to connect realtime websocket:", error);
|
|
2214
2654
|
});
|
|
2215
|
-
if (diagnostics.length > 0) throw new BoardInputError(diagnostics);
|
|
2216
2655
|
}
|
|
2217
2656
|
//#endregion
|
|
2218
2657
|
//#region src/session-patch-reducer.ts
|
|
@@ -4265,6 +4704,51 @@ var BoardClient = class {
|
|
|
4265
4704
|
capabilities(customFetch) {
|
|
4266
4705
|
return this.boards.capabilities(this.id, customFetch);
|
|
4267
4706
|
}
|
|
4707
|
+
summary(customFetch) {
|
|
4708
|
+
return this.boards.summary(this.id, customFetch);
|
|
4709
|
+
}
|
|
4710
|
+
authoring(customFetch) {
|
|
4711
|
+
return this.boards.authoring(this.id, customFetch);
|
|
4712
|
+
}
|
|
4713
|
+
mutateSemantic(input) {
|
|
4714
|
+
return this.boards.mutateSemantic(this.id, {
|
|
4715
|
+
...input,
|
|
4716
|
+
mutationId: input.mutationId ?? randomBoardId()
|
|
4717
|
+
});
|
|
4718
|
+
}
|
|
4719
|
+
async mutate(input) {
|
|
4720
|
+
const retries = input.retries ?? 1;
|
|
4721
|
+
if (!Number.isSafeInteger(retries) || retries < 0 || retries > 3) throw new RangeError("Board mutation retries must be an integer from 0 to 3");
|
|
4722
|
+
for (let attempt = 0;; attempt += 1) {
|
|
4723
|
+
const current = await this.inspect({ include: input.include ?? [] });
|
|
4724
|
+
const operations = await input.build(current);
|
|
4725
|
+
if (operations.length === 0) return {
|
|
4726
|
+
mutationId: randomBoardId(),
|
|
4727
|
+
status: "validated",
|
|
4728
|
+
replayed: false,
|
|
4729
|
+
board: {
|
|
4730
|
+
id: current.board.id,
|
|
4731
|
+
version: current.board.version
|
|
4732
|
+
},
|
|
4733
|
+
changed: {
|
|
4734
|
+
items: [],
|
|
4735
|
+
connections: [],
|
|
4736
|
+
effects: [],
|
|
4737
|
+
compositions: [],
|
|
4738
|
+
board: false
|
|
4739
|
+
}
|
|
4740
|
+
};
|
|
4741
|
+
try {
|
|
4742
|
+
return await this.apply({
|
|
4743
|
+
txId: randomBoardId(),
|
|
4744
|
+
baseVersion: current.board.version,
|
|
4745
|
+
operations
|
|
4746
|
+
});
|
|
4747
|
+
} catch (cause) {
|
|
4748
|
+
if (!(cause instanceof BoardTransactionError) || !cause.isVersionConflict || attempt >= retries) throw cause;
|
|
4749
|
+
}
|
|
4750
|
+
}
|
|
4751
|
+
}
|
|
4268
4752
|
validate(transaction) {
|
|
4269
4753
|
return this.boards.validate({
|
|
4270
4754
|
...transaction,
|
|
@@ -4405,7 +4889,7 @@ var SpaceBoardsApi = class {
|
|
|
4405
4889
|
return new BoardClient(this.spaceId, boardId, this.transport, this.websocketClient);
|
|
4406
4890
|
}
|
|
4407
4891
|
create(input) {
|
|
4408
|
-
|
|
4892
|
+
for (const item of input.items ?? []) BoardAuthoringItemSchema.parse(item);
|
|
4409
4893
|
return this.transport.request(`/api/spaces/${this.spaceId}/boards`, {
|
|
4410
4894
|
method: "POST",
|
|
4411
4895
|
headers: { "Content-Type": "application/json" },
|
|
@@ -4419,6 +4903,19 @@ var SpaceBoardsApi = class {
|
|
|
4419
4903
|
const query = params.toString();
|
|
4420
4904
|
return this.transport.request(`/api/spaces/${this.spaceId}/boards/${boardId}${query ? `?${query}` : ""}`, { fetch: customFetch });
|
|
4421
4905
|
}
|
|
4906
|
+
authoring(boardId, customFetch) {
|
|
4907
|
+
return this.transport.request(`/api/spaces/${this.spaceId}/boards/${boardId}/authoring`, { fetch: customFetch });
|
|
4908
|
+
}
|
|
4909
|
+
mutateSemantic(boardId, mutation) {
|
|
4910
|
+
return this.transport.request(`/api/spaces/${this.spaceId}/boards/${boardId}/mutations`, {
|
|
4911
|
+
method: "POST",
|
|
4912
|
+
headers: { "Content-Type": "application/json" },
|
|
4913
|
+
body: JSON.stringify(mutation)
|
|
4914
|
+
});
|
|
4915
|
+
}
|
|
4916
|
+
summary(boardId, customFetch) {
|
|
4917
|
+
return this.transport.request(`/api/spaces/${this.spaceId}/boards/${boardId}/summary`, { fetch: customFetch });
|
|
4918
|
+
}
|
|
4422
4919
|
capabilities(boardId, customFetch) {
|
|
4423
4920
|
return this.transport.request(`/api/spaces/${this.spaceId}/boards/${boardId}/capabilities`, { fetch: customFetch });
|
|
4424
4921
|
}
|
|
@@ -4430,7 +4927,6 @@ var SpaceBoardsApi = class {
|
|
|
4430
4927
|
});
|
|
4431
4928
|
}
|
|
4432
4929
|
async apply(transaction) {
|
|
4433
|
-
assertBoardTransactionNodeCreates(transaction.operations);
|
|
4434
4930
|
try {
|
|
4435
4931
|
return await this.transport.request(`/api/spaces/${this.spaceId}/boards/${transaction.boardId}/transactions`, {
|
|
4436
4932
|
method: "POST",
|
|
@@ -5221,4 +5717,4 @@ var CohubHttpClient = class {
|
|
|
5221
5717
|
};
|
|
5222
5718
|
const createHttpClient = (options) => new CohubHttpClient(options);
|
|
5223
5719
|
//#endregion
|
|
5224
|
-
export {
|
|
5720
|
+
export { BOARD_GEO_KINDS as $, buildWorkComposerChipSet as A, UI_COMMAND_MAX_TIMEOUT_MS as B, ensureRealtimeConnected as C, SkillsApi as Ct, WORK_SURFACE_READY_TIMEOUT_MS as D, CronJobsApi as Dt, WORK_COMPOSER_CHIP_LABEL_MAX_LENGTH as E, GenerationsApi as Et, parseWorkComposerChipSet as F, UI_COMMAND_VERSION as G, UI_COMMAND_PENDING_TTL_SECONDS as H, parseWorkSurfaceReady as I, parseUiCommand as J, isTerminalUiCommandStatus as K, parseWorkSurfaceRequest as L, buildWorkSurfaceRequest as M, buildWorkSurfaceResponse as N, WORK_SURFACE_REQUEST_TIMEOUT_MS as O, ChannelsApi as Ot, parseWorkComposerChipClear as P, BOARD_COLOR_IDS as Q, parseWorkSurfaceResponse as R, createSessionPatchReducer as S, PublicAssetsApi as St, WORK_COMPOSER_CHIP_KEY_MAX_LENGTH as T, ModelsApi as Tt, UI_COMMAND_SETTLEMENT_GRACE_SECONDS as U, UI_COMMAND_PAYLOAD_MAX_BYTES as V, UI_COMMAND_TERMINAL_TTL_SECONDS as W, parseUsername as X, parseSpaceSlug as Y, BoardAwarenessClientPayloadSchema as Z, buildSpacePath as _, BOARD_BUILTIN_CAPABILITIES as _t, ReferralsApi as a, BoardEffectSchema as at, parseAssistantMessageCommit as b, ReferencesApi as bt, UiCommandsApi as c, BoardAuthoringItemSchema as ct, BoardTransactionError as d, BOARD_ANIMATION_CHANNEL_CAPABILITIES as dt, BOARD_NATIVE_NODE_TYPES as et, SpaceClient as f, BoardCompositionInputSchema as ft, buildSpaceInvitePath as g, parseBoardCompositionInput as gt, PublicInviteApi as h, BoardTrackSchema as ht, WorksApi as i, validateBuiltinBoardClip as it, buildWorkSurfaceReady as j, buildWorkComposerChipClear as k, TasksApi as l, BoardItemPatchSchema as lt, SpacesApi as m, BoardProceduralClipSchema as mt, createHttpClient as n, validateBoardNodeInput as nt, UsersApi as o, BoardPlaybackPolicySchema as ot, SpacePublicFilesApi as p, BoardCompositionSchema as pt, isUiSurfaceMethod as q, WorkCommerceApi as r, estimateBuiltinBoardClipCost as rt, UserApi as s, parseBoardPlaybackPolicy as st, CohubHttpClient as t, BOARD_NODE_CONTRACT as tt, BoardClient as u, BOARD_ANIMATION_CHANNELS as ut, SessionGenerationStreamClient as v, DEFAULT_BOARD_RENDER_LIMITS as vt, WORK_COMPOSER_CHIP_CONTENT_MAX_BYTES as w, PromptsApi as wt, SessionPatchReducer as x, SearchApi as xt, createSessionGenerationStreamClient as y, SessionAccessApi as yt, UI_COMMAND_DEFAULT_TIMEOUT_MS as z };
|