@neta-art/cohub 5.5.0 → 5.7.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 +10 -0
- package/dist/board/codec.js +15 -0
- package/dist/board/core/shape-types.d.ts +5 -1
- package/dist/board/index.d.ts +4 -3
- package/dist/board/index.js +3 -2
- package/dist/board/render/audio-waveform.d.ts +12 -0
- package/dist/board/render/audio-waveform.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/audio-card-renderer.d.ts +5 -0
- package/dist/board/render/renderers/audio-card-renderer.js +120 -0
- package/dist/board/render/renderers/board-renderer-registry.js +2 -0
- package/dist/board/render/renderers/task-card-renderer.d.ts +2 -1
- package/dist/board/render/renderers/task-card-renderer.js +6 -41
- package/dist/board/task.d.ts +15 -0
- package/dist/board/task.js +182 -0
- package/dist/chunks/http.d.ts +6 -0
- package/dist/chunks/http.js +11 -0
- package/dist/chunks/websocket.d.ts +1 -1
- package/dist/protocol/dist/board-document.d.ts +117 -6
- package/dist/protocol/dist/board-document.js +15 -4
- package/dist/types.d.ts +35 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -124,6 +124,16 @@ const stop = board.subscribe({
|
|
|
124
124
|
stop();
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
+
Task nodes keep a small, replaceable display snapshot beside their stable `taskRunId`. The SDK can build that projection from an authoritative TaskRun without copying the full payload, result or inline media into a Board:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
import { taskRunToBoardTaskSnapshot } from "@neta-art/cohub/board";
|
|
131
|
+
|
|
132
|
+
const snapshot = taskRunToBoardTaskSnapshot(taskRun);
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Use `client.tasks.getMany(ids, { spaceId })` to restore the TaskRuns for a Board in one request. The server applies the same Space permissions and result sanitization as the regular task list endpoint.
|
|
136
|
+
|
|
127
137
|
Board is split by dependency: the model runs anywhere, drawing needs PixiJS.
|
|
128
138
|
`@neta-art/cohub/board` carries the document schema, geometry, the shape layer,
|
|
129
139
|
timeline compilation and export planning, with no renderer and no PixiJS — so
|
package/dist/board/codec.js
CHANGED
|
@@ -193,6 +193,21 @@ function boardNodeToItemValue(node) {
|
|
|
193
193
|
style
|
|
194
194
|
};
|
|
195
195
|
}
|
|
196
|
+
case "audio": {
|
|
197
|
+
const path = spaceFilePathFromNode(node) ?? "missing";
|
|
198
|
+
return {
|
|
199
|
+
id: node.nodeId,
|
|
200
|
+
type: "audio",
|
|
201
|
+
ref: {
|
|
202
|
+
kind: "space-file",
|
|
203
|
+
path
|
|
204
|
+
},
|
|
205
|
+
snapshot: node.view,
|
|
206
|
+
frame,
|
|
207
|
+
...locked ? { locked } : {},
|
|
208
|
+
style
|
|
209
|
+
};
|
|
210
|
+
}
|
|
196
211
|
case "file": {
|
|
197
212
|
const path = spaceFilePathFromNode(node) ?? "missing";
|
|
198
213
|
const parsed = BoardFileSnapshotSchema.safeParse(node.view ?? {});
|
|
@@ -142,5 +142,9 @@ type VideoShapeProps = {
|
|
|
142
142
|
path: string;
|
|
143
143
|
mimeType?: string;
|
|
144
144
|
};
|
|
145
|
+
type AudioShapeProps = {
|
|
146
|
+
path: string;
|
|
147
|
+
mimeType?: string;
|
|
148
|
+
};
|
|
145
149
|
//#endregion
|
|
146
|
-
export { ArrowEndpoint, ArrowShapeProps, DrawPoint, DrawShapeProps, FULL_CAPABILITIES, GEO_KINDS, GeoKind, GeoShapeProps, HandleDragResult, ImageShapeProps, ShapeCapabilities, ShapeGeometry, ShapeHandle, ShapeHandleId, ShapeResizeMode, TextShapeProps, VideoShapeProps, isGeoKind, resizeModeForCapabilities };
|
|
150
|
+
export { ArrowEndpoint, ArrowShapeProps, AudioShapeProps, DrawPoint, DrawShapeProps, FULL_CAPABILITIES, GEO_KINDS, GeoKind, GeoShapeProps, HandleDragResult, ImageShapeProps, ShapeCapabilities, ShapeGeometry, ShapeHandle, ShapeHandleId, ShapeResizeMode, TextShapeProps, VideoShapeProps, isGeoKind, resizeModeForCapabilities };
|
package/dist/board/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, clampBoardStrokeSize } fr
|
|
|
2
2
|
import { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BoardConnection, BoardConnectionAnchor, BoardConnectionAnchorSchema, BoardConnectionDirection, BoardConnectionEndpoint, BoardConnectionEndpointSchema, BoardConnectionInput, BoardConnectionLine, BoardConnectionPatch, BoardConnectionPatchSchema, BoardConnectionRecord, BoardConnectionRouting, BoardConnectionRoutingConfig, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionSide, BoardConnectionStyle, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardRelationSchema, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, connectionNodeIds, connectionOtherNodeId, connectionTouchesNode, createBoardConnection, flipBoardConnection, normalizeBoardConnectionStyle } from "../protocol/dist/board-connection.js";
|
|
3
3
|
import { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardManifest, BoardNodeRecord, BoardRecord, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest } from "../protocol/dist/board.js";
|
|
4
4
|
import { BoardExtensionDefinition, BoardExtensionRegistry, BoardPresetDefinition, CompiledSequence, DEFAULT_BOARD_LIMITS, QualityProfile, RenderBounds, TimelineClipInput, TimelineInput, clip, compileSequence, createBoardExtensionRegistry, timeline } from "./animation.js";
|
|
5
|
-
import { BoardAppearance, BoardAppearanceSchema, BoardArrowItem, BoardArrowItemSchema, BoardDocument, BoardDocumentSchema, BoardDrawItem, BoardDrawItemSchema, BoardFileItem, BoardFileItemSchema, BoardFileSnapshot, BoardFileSnapshotSchema, BoardFrame, BoardFrameItem, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItem, BoardGeoItemSchema, BoardImageItem, BoardImageItemSchema, BoardItem, BoardItemSchema, BoardItemStyle, BoardItemStyleSchema, BoardKnownItem, BoardMediaSnapshot, BoardMediaSnapshotSchema, BoardPoint, BoardPointSchema, BoardTaskItem, BoardTaskItemSchema, BoardTaskOutput, BoardTaskOutputSchema, BoardTaskSnapshot, BoardTaskSnapshotSchema, BoardTextItem, BoardTextItemSchema, BoardUnknownItem, BoardVideoItem, BoardVideoItemSchema, BoardViewport, BoardViewportSchema, DrawPoint, DrawPointSchema, KNOWN_BOARD_ITEM_TYPES, KnownBoardItemType, SpaceFileRef, SpaceFileRefSchema, UNKNOWN_BOARD_ITEM_TYPE, isFileBackedItem, isMediaItem, isUnknownItem, parseBoardDocument, parseBoardItemLoose, unknownRealType, withResolvedConnections } from "../protocol/dist/board-document.js";
|
|
5
|
+
import { BoardAppearance, BoardAppearanceSchema, BoardArrowItem, BoardArrowItemSchema, BoardAudioItem, BoardAudioItemSchema, BoardDocument, BoardDocumentSchema, BoardDrawItem, BoardDrawItemSchema, BoardFileItem, BoardFileItemSchema, BoardFileSnapshot, BoardFileSnapshotSchema, BoardFrame, BoardFrameItem, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItem, BoardGeoItemSchema, BoardImageItem, BoardImageItemSchema, BoardItem, BoardItemSchema, BoardItemStyle, BoardItemStyleSchema, BoardKnownItem, BoardMediaSnapshot, BoardMediaSnapshotSchema, BoardPoint, BoardPointSchema, BoardTaskItem, BoardTaskItemSchema, BoardTaskOutput, BoardTaskOutputSchema, BoardTaskSnapshot, BoardTaskSnapshotSchema, BoardTextItem, BoardTextItemSchema, BoardUnknownItem, BoardVideoItem, BoardVideoItemSchema, BoardViewport, BoardViewportSchema, DrawPoint, DrawPointSchema, KNOWN_BOARD_ITEM_TYPES, KnownBoardItemType, SpaceFileRef, SpaceFileRefSchema, UNKNOWN_BOARD_ITEM_TYPE, isFileBackedItem, isMediaItem, isUnknownItem, parseBoardDocument, parseBoardItemLoose, unknownRealType, withResolvedConnections } from "../protocol/dist/board-document.js";
|
|
6
6
|
import { BOARD_NODE_SOURCE, DEFAULT_BOARD_APPEARANCE, ITEM_BASE_KEYS, WireBackedBoardItem, boardBootstrapToDocument, boardNodeToItem, isRecord, nodeInputFromRecord, sourceForItem } from "./codec.js";
|
|
7
7
|
import { CORNER_RESIZE_HANDLES, CORNER_ROTATION_ZONE_WIDTH, CornerResizeHandle, EDGE_RESIZE_HANDLES, FIT_PADDING, HANDLE_DIRECTION, HANDLE_HIT_RADIUS, MAX_BOARD_ZOOM, MIN_BOARD_ZOOM, MIN_ITEM_SIZE, Point, RESIZE_HANDLES, ROTATION_HANDLE_OFFSET, Rect, ResizeHandle, ScreenPoint, Size, VIEWPORT_MARGIN_RATIO, WorldPoint, angleFromCenter, clamp, clampZoom, degToRad, expandRect, fitToContent, frameContainsPoint, frameCornerRotationHandleAt, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, handlePosition, itemBounds, normalizeRotation, normalizeViewport, panBy, pointToWorld, radToDeg, rectCenter, rectContainsPoint, rectsIntersect, resizeFrame, resizeFrameToSize, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, scaleFrames, screenPoint, screenToWorld, selectionBounds, unionRects, visibleWorldRect, worldPoint, worldToScreen, zoomAround } from "./geometry.js";
|
|
8
8
|
import { ResolvedArrow, arrowBounds, arrowFrame, distanceToArrow, resolveArrow, sampleArrow, translateArrow } from "./core/arrow-geometry.js";
|
|
@@ -12,9 +12,10 @@ import { BOARD_EXPORT_MAX_TEXTURES, BoardExportAssetSelection, selectBoardExport
|
|
|
12
12
|
import { BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, BoardExportPlan, BoardExportPlanInput, BoardExportRegion, boardFrameLookup, exportConnectionBounds, exportItemBounds, normalizeBoardDocument, planBoardExport } from "./core/export-plan.js";
|
|
13
13
|
import { BoardFileSnapshotFacts, BuildSnapshotInput, FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, FileAvailability, FilePreviewKind, ResolvedCover, availabilityFromError, buildFileExcerpt, buildFileSnapshot, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, formatFileSize, isFileSnapshotFresh, mergeFileSnapshot, readCoverFromFrontmatter, readTitleFromFrontmatter, resolveCoverRef, resolveSpacePath, shouldFetchFileExcerpt, splitFrontmatter } from "./core/file-preview.js";
|
|
14
14
|
import { BOARD_COLORS, BoardColorEntry, BoardColorId, BoardColorValue, BoardShapeColors, DEFAULT_BOARD_COLOR, boardColorCssVar, buildFallbackShapeColors, isBoardColorId, pickBoardColor, resolveBoardColor } from "./core/palette.js";
|
|
15
|
-
import { ArrowShapeProps, DrawShapeProps, FULL_CAPABILITIES, GEO_KINDS, GeoKind, GeoShapeProps, HandleDragResult, ImageShapeProps, ShapeCapabilities, ShapeGeometry, ShapeHandle, ShapeHandleId, ShapeResizeMode, TextShapeProps, VideoShapeProps, isGeoKind, resizeModeForCapabilities } from "./core/shape-types.js";
|
|
15
|
+
import { ArrowShapeProps, AudioShapeProps, DrawShapeProps, FULL_CAPABILITIES, GEO_KINDS, GeoKind, GeoShapeProps, HandleDragResult, ImageShapeProps, ShapeCapabilities, ShapeGeometry, ShapeHandle, ShapeHandleId, ShapeResizeMode, TextShapeProps, VideoShapeProps, isGeoKind, resizeModeForCapabilities } from "./core/shape-types.js";
|
|
16
16
|
import { ShapeDefinition, definitionForItem, getShapeDefinition, registerShapeDefinition, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, unknownShapeDefinition } from "./core/shape-definition.js";
|
|
17
17
|
import { TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, boardTextLineHeight, clampBoardTextFontSize, measureBoardText, setBoardTextMeasurer } from "./core/text-metrics.js";
|
|
18
18
|
import { BoardStyledToolId, BoardToolStyleMap, BoardToolStylePatch, DEFAULT_BOARD_TOOL_STYLES, createBoardToolStyles } from "./core/tool-styles.js";
|
|
19
19
|
import { boardImageKeySource, imageAssetKey } from "./image-key.js";
|
|
20
|
-
|
|
20
|
+
import { normalizeBoardTaskOutputUrl, taskRunToBoardTaskSnapshot } from "./task.js";
|
|
21
|
+
export { AUTO_BOARD_CONNECTION_ANCHOR, type ArrowShapeProps, type AudioShapeProps, BOARD_COLORS, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BOARD_DOCUMENT_KIND, BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, BOARD_EXPORT_MAX_TEXTURES, BOARD_EXTENSION, BOARD_NODE_SOURCE, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BoardAppearance, BoardAppearanceSchema, BoardArrowItem, BoardArrowItemSchema, BoardAudioItem, BoardAudioItemSchema, BoardColorEntry, BoardColorId, BoardColorValue, BoardConnection, BoardConnectionAnchor, BoardConnectionAnchorSchema, BoardConnectionDirection, BoardConnectionEndpoint, BoardConnectionEndpointSchema, BoardConnectionInput, BoardConnectionLine, BoardConnectionPatch, BoardConnectionPatchSchema, BoardConnectionRecord, BoardConnectionRouting, BoardConnectionRoutingConfig, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionSide, BoardConnectionStyle, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardDocument, BoardDocumentSchema, BoardDrawItem, BoardDrawItemSchema, BoardExportAssetSelection, BoardExportPlan, BoardExportPlanInput, BoardExportRegion, BoardExtensionDefinition, BoardExtensionRegistry, BoardFileItem, BoardFileItemSchema, BoardFileSnapshot, BoardFileSnapshotFacts, BoardFileSnapshotSchema, BoardFrame, BoardFrameItem, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItem, BoardGeoItemSchema, BoardImageItem, BoardImageItemSchema, BoardItem, BoardItemSchema, BoardItemStyle, BoardItemStyleSchema, BoardKnownItem, type BoardManifest, BoardMediaSnapshot, BoardMediaSnapshotSchema, type BoardNodeRecord, BoardPoint, BoardPointSchema, BoardPresetDefinition, type BoardRecord, BoardRelationSchema, BoardShapeColors, BoardStyledToolId, BoardTaskItem, BoardTaskItemSchema, BoardTaskOutput, BoardTaskOutputSchema, BoardTaskSnapshot, BoardTaskSnapshotSchema, BoardTextItem, BoardTextItemSchema, BoardToolStyleMap, BoardToolStylePatch, BoardUnknownItem, BoardVideoItem, BoardVideoItemSchema, BoardViewport, BoardViewportSchema, BuildSnapshotInput, CONNECTION_ENDPOINT_GAP, CORNER_RESIZE_HANDLES, CORNER_ROTATION_ZONE_WIDTH, CompiledSequence, ConnectionIndex, CornerResizeHandle, DEFAULT_BOARD_APPEARANCE, DEFAULT_BOARD_COLOR, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_LIMITS, DEFAULT_BOARD_RELATION, DEFAULT_BOARD_TOOL_STYLES, DrawPoint, DrawPointSchema, type DrawShapeProps, EDGE_RESIZE_HANDLES, FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, FIT_PADDING, FULL_CAPABILITIES, FileAvailability, FilePreviewKind, FrameLookup, GEO_KINDS, type GeoKind, type GeoShapeProps, HANDLE_DIRECTION, HANDLE_HIT_RADIUS, type HandleDragResult, ITEM_BASE_KEYS, type ImageShapeProps, InvalidBoardFileError, KNOWN_BOARD_ITEM_TYPES, KnownBoardItemType, MAX_BOARD_ZOOM, MIN_BOARD_ZOOM, MIN_ITEM_SIZE, Point, QualityProfile, RESIZE_HANDLES, ROTATION_HANDLE_OFFSET, Rect, RenderBounds, ResizeHandle, ResolvedArrow, ResolvedConnection, ResolvedConnectionEndpoint, ResolvedCover, ScreenPoint, type ShapeCapabilities, ShapeDefinition, type ShapeGeometry, type ShapeHandle, type ShapeHandleId, type ShapeResizeMode, Size, SpaceFileRef, SpaceFileRefSchema, TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, type TextShapeProps, TimelineClipInput, TimelineInput, UNKNOWN_BOARD_ITEM_TYPE, VIEWPORT_MARGIN_RATIO, type VideoShapeProps, WireBackedBoardItem, WorldPoint, anchorPointOnFrame, anchorToWorld, angleFromCenter, arrowBounds, arrowFrame, autoConnectionSide, availabilityFromError, boardBootstrapToDocument, boardColorCssVar, boardFrameLookup, boardImageKeySource, boardNodeToItem, boardTextLineHeight, buildFallbackShapeColors, buildFileExcerpt, buildFileSnapshot, buildStrokeOutline, clamp, clampBoardStrokeSize, clampBoardTextFontSize, clampZoom, clip, compileSequence, computeDrawBounds, connectionArrowheads, connectionBounds, connectionHitTest, connectionNodeIds, connectionOtherNodeId, connectionTouchesNode, createBoardConnection, createBoardExtensionRegistry, createBoardToolStyles, createConnectionIndex, definitionForItem, degToRad, distanceToArrow, distanceToConnection, distanceToStroke, expandRect, exportConnectionBounds, exportItemBounds, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, fitToContent, flipBoardConnection, formatFileSize, frameContainsPoint, frameCornerRotationHandleAt, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, getShapeDefinition, handlePosition, imageAssetKey, isBoardColorId, isBoardPath, isFileBackedItem, isFileSnapshotFresh, isGeoKind, isMediaItem, isRecord, isUnknownItem, itemBounds, measureBoardText, mergeFileSnapshot, nodeInputFromRecord, normalizeBoardConnectionStyle, normalizeBoardDocument, normalizeBoardTaskOutputUrl, normalizeRotation, normalizeViewport, panBy, parseBoardDocument, parseBoardItemLoose, parseBoardManifest, pathMidpoint, pickBoardColor, planBoardExport, pointToWorld, radToDeg, readCoverFromFrontmatter, readTitleFromFrontmatter, rectCenter, rectContainsPoint, rectsIntersect, registerShapeDefinition, resizeFrame, resizeFrameToSize, resizeModeForCapabilities, resolveArrow, resolveBoardColor, resolveConnection, resolveCoverRef, resolveSpacePath, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, sampleArrow, sampleRadius, scaleFrames, screenPoint, screenToWorld, selectBoardExportAssets, selectionBounds, serializeBoardManifest, setBoardTextMeasurer, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, shouldFetchFileExcerpt, simplifyDrawIndices, sourceForItem, splitFrontmatter, taskRunToBoardTaskSnapshot, timeline, translateArrow, unionRects, unknownRealType, unknownShapeDefinition, visibleWorldRect, withResolvedConnections, worldPoint, worldToAnchor, worldToScreen, zoomAround };
|
package/dist/board/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, clampBoardStrokeSize } fr
|
|
|
2
2
|
import { BoardExtensionRegistry, DEFAULT_BOARD_LIMITS, clip, compileSequence, createBoardExtensionRegistry, timeline } from "./animation.js";
|
|
3
3
|
import { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BoardConnectionAnchorSchema, BoardConnectionEndpointSchema, BoardConnectionPatchSchema, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardRelationSchema, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, connectionNodeIds, connectionOtherNodeId, connectionTouchesNode, createBoardConnection, flipBoardConnection, normalizeBoardConnectionStyle } from "../protocol/dist/board-connection.js";
|
|
4
4
|
import { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest } from "../protocol/dist/board.js";
|
|
5
|
-
import { BoardAppearanceSchema, BoardArrowItemSchema, BoardDocumentSchema, BoardDrawItemSchema, BoardFileItemSchema, BoardFileSnapshotSchema, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItemSchema, BoardImageItemSchema, BoardItemSchema, BoardItemStyleSchema, BoardMediaSnapshotSchema, BoardPointSchema, BoardTaskItemSchema, BoardTaskOutputSchema, BoardTaskSnapshotSchema, BoardTextItemSchema, BoardVideoItemSchema, BoardViewportSchema, DrawPointSchema, KNOWN_BOARD_ITEM_TYPES, SpaceFileRefSchema, UNKNOWN_BOARD_ITEM_TYPE, isFileBackedItem, isMediaItem, isUnknownItem, parseBoardDocument, parseBoardItemLoose, unknownRealType, withResolvedConnections } from "../protocol/dist/board-document.js";
|
|
5
|
+
import { BoardAppearanceSchema, BoardArrowItemSchema, BoardAudioItemSchema, BoardDocumentSchema, BoardDrawItemSchema, BoardFileItemSchema, BoardFileSnapshotSchema, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItemSchema, BoardImageItemSchema, BoardItemSchema, BoardItemStyleSchema, BoardMediaSnapshotSchema, BoardPointSchema, BoardTaskItemSchema, BoardTaskOutputSchema, BoardTaskSnapshotSchema, BoardTextItemSchema, BoardVideoItemSchema, BoardViewportSchema, DrawPointSchema, KNOWN_BOARD_ITEM_TYPES, SpaceFileRefSchema, UNKNOWN_BOARD_ITEM_TYPE, isFileBackedItem, isMediaItem, isUnknownItem, parseBoardDocument, parseBoardItemLoose, unknownRealType, withResolvedConnections } from "../protocol/dist/board-document.js";
|
|
6
6
|
import { TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, boardTextLineHeight, clampBoardTextFontSize, measureBoardText, setBoardTextMeasurer } from "./core/text-metrics.js";
|
|
7
7
|
import { BOARD_NODE_SOURCE, DEFAULT_BOARD_APPEARANCE, ITEM_BASE_KEYS, boardBootstrapToDocument, boardNodeToItem, isRecord, nodeInputFromRecord, sourceForItem } from "./codec.js";
|
|
8
8
|
import { CORNER_RESIZE_HANDLES, CORNER_ROTATION_ZONE_WIDTH, EDGE_RESIZE_HANDLES, FIT_PADDING, HANDLE_DIRECTION, HANDLE_HIT_RADIUS, MAX_BOARD_ZOOM, MIN_BOARD_ZOOM, MIN_ITEM_SIZE, RESIZE_HANDLES, ROTATION_HANDLE_OFFSET, VIEWPORT_MARGIN_RATIO, angleFromCenter, clamp, clampZoom, degToRad, expandRect, fitToContent, frameContainsPoint, frameCornerRotationHandleAt, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, handlePosition, itemBounds, normalizeRotation, normalizeViewport, panBy, pointToWorld, radToDeg, rectCenter, rectContainsPoint, rectsIntersect, resizeFrame, resizeFrameToSize, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, scaleFrames, screenPoint, screenToWorld, selectionBounds, unionRects, visibleWorldRect, worldPoint, worldToScreen, zoomAround } from "./geometry.js";
|
|
@@ -17,4 +17,5 @@ import { BOARD_COLORS, DEFAULT_BOARD_COLOR, boardColorCssVar, buildFallbackShape
|
|
|
17
17
|
import { FULL_CAPABILITIES, GEO_KINDS, isGeoKind, resizeModeForCapabilities } from "./core/shape-types.js";
|
|
18
18
|
import { definitionForItem, getShapeDefinition, registerShapeDefinition, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, unknownShapeDefinition } from "./core/shape-definition.js";
|
|
19
19
|
import { DEFAULT_BOARD_TOOL_STYLES, createBoardToolStyles } from "./core/tool-styles.js";
|
|
20
|
-
|
|
20
|
+
import { normalizeBoardTaskOutputUrl, taskRunToBoardTaskSnapshot } from "./task.js";
|
|
21
|
+
export { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_COLORS, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BOARD_DOCUMENT_KIND, BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, BOARD_EXPORT_MAX_TEXTURES, BOARD_EXTENSION, BOARD_NODE_SOURCE, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BoardAppearanceSchema, BoardArrowItemSchema, BoardAudioItemSchema, BoardConnectionAnchorSchema, BoardConnectionEndpointSchema, BoardConnectionPatchSchema, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardDocumentSchema, BoardDrawItemSchema, BoardExtensionRegistry, BoardFileItemSchema, BoardFileSnapshotSchema, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItemSchema, BoardImageItemSchema, BoardItemSchema, BoardItemStyleSchema, BoardMediaSnapshotSchema, BoardPointSchema, BoardRelationSchema, BoardTaskItemSchema, BoardTaskOutputSchema, BoardTaskSnapshotSchema, BoardTextItemSchema, BoardVideoItemSchema, BoardViewportSchema, CONNECTION_ENDPOINT_GAP, CORNER_RESIZE_HANDLES, CORNER_ROTATION_ZONE_WIDTH, DEFAULT_BOARD_APPEARANCE, DEFAULT_BOARD_COLOR, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_LIMITS, DEFAULT_BOARD_RELATION, DEFAULT_BOARD_TOOL_STYLES, DrawPointSchema, EDGE_RESIZE_HANDLES, FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, FIT_PADDING, FULL_CAPABILITIES, GEO_KINDS, HANDLE_DIRECTION, HANDLE_HIT_RADIUS, ITEM_BASE_KEYS, InvalidBoardFileError, KNOWN_BOARD_ITEM_TYPES, MAX_BOARD_ZOOM, MIN_BOARD_ZOOM, MIN_ITEM_SIZE, RESIZE_HANDLES, ROTATION_HANDLE_OFFSET, SpaceFileRefSchema, TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, UNKNOWN_BOARD_ITEM_TYPE, VIEWPORT_MARGIN_RATIO, anchorPointOnFrame, anchorToWorld, angleFromCenter, arrowBounds, arrowFrame, autoConnectionSide, availabilityFromError, boardBootstrapToDocument, boardColorCssVar, boardFrameLookup, boardImageKeySource, boardNodeToItem, boardTextLineHeight, buildFallbackShapeColors, buildFileExcerpt, buildFileSnapshot, buildStrokeOutline, clamp, clampBoardStrokeSize, clampBoardTextFontSize, clampZoom, clip, compileSequence, computeDrawBounds, connectionArrowheads, connectionBounds, connectionHitTest, connectionNodeIds, connectionOtherNodeId, connectionTouchesNode, createBoardConnection, createBoardExtensionRegistry, createBoardToolStyles, createConnectionIndex, definitionForItem, degToRad, distanceToArrow, distanceToConnection, distanceToStroke, expandRect, exportConnectionBounds, exportItemBounds, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, fitToContent, flipBoardConnection, formatFileSize, frameContainsPoint, frameCornerRotationHandleAt, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, getShapeDefinition, handlePosition, imageAssetKey, isBoardColorId, isBoardPath, isFileBackedItem, isFileSnapshotFresh, isGeoKind, isMediaItem, isRecord, isUnknownItem, itemBounds, measureBoardText, mergeFileSnapshot, nodeInputFromRecord, normalizeBoardConnectionStyle, normalizeBoardDocument, normalizeBoardTaskOutputUrl, normalizeRotation, normalizeViewport, panBy, parseBoardDocument, parseBoardItemLoose, parseBoardManifest, pathMidpoint, pickBoardColor, planBoardExport, pointToWorld, radToDeg, readCoverFromFrontmatter, readTitleFromFrontmatter, rectCenter, rectContainsPoint, rectsIntersect, registerShapeDefinition, resizeFrame, resizeFrameToSize, resizeModeForCapabilities, resolveArrow, resolveBoardColor, resolveConnection, resolveCoverRef, resolveSpacePath, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, sampleArrow, sampleRadius, scaleFrames, screenPoint, screenToWorld, selectBoardExportAssets, selectionBounds, serializeBoardManifest, setBoardTextMeasurer, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, shouldFetchFileExcerpt, simplifyDrawIndices, sourceForItem, splitFrontmatter, taskRunToBoardTaskSnapshot, timeline, translateArrow, unionRects, unknownRealType, unknownShapeDefinition, visibleWorldRect, withResolvedConnections, worldPoint, worldToAnchor, worldToScreen, zoomAround };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Graphics } from "pixi.js";
|
|
2
|
+
//#region src/board/render/audio-waveform.d.ts
|
|
3
|
+
/** Stable placeholder amplitudes without reading or decoding the audio file. */
|
|
4
|
+
declare function audioWaveformBars(seed: string, count: number): number[];
|
|
5
|
+
declare function drawAudioWaveform(graphics: Graphics, seed: string, rect: {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
}, color: number, alpha?: number): void;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { audioWaveformBars, drawAudioWaveform };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//#region src/board/render/audio-waveform.ts
|
|
2
|
+
const DEFAULT_BARS = 44;
|
|
3
|
+
const BAR_GAP = 2;
|
|
4
|
+
/** Stable placeholder amplitudes without reading or decoding the audio file. */
|
|
5
|
+
function audioWaveformBars(seed, count) {
|
|
6
|
+
let hash = 2166136261;
|
|
7
|
+
for (let index = 0; index < seed.length; index += 1) {
|
|
8
|
+
hash ^= seed.charCodeAt(index);
|
|
9
|
+
hash = Math.imul(hash, 16777619);
|
|
10
|
+
}
|
|
11
|
+
const bars = [];
|
|
12
|
+
for (let index = 0; index < count; index += 1) {
|
|
13
|
+
hash ^= hash << 13;
|
|
14
|
+
hash ^= hash >>> 17;
|
|
15
|
+
hash ^= hash << 5;
|
|
16
|
+
bars.push(.2 + (hash >>> 0) / 4294967295 * .8);
|
|
17
|
+
}
|
|
18
|
+
return bars;
|
|
19
|
+
}
|
|
20
|
+
function drawAudioWaveform(graphics, seed, rect, color, alpha = .72) {
|
|
21
|
+
const count = Math.max(8, Math.min(DEFAULT_BARS, Math.floor(rect.width / 4)));
|
|
22
|
+
const step = rect.width / count;
|
|
23
|
+
const barWidth = Math.max(1.5, step - BAR_GAP);
|
|
24
|
+
const centerY = rect.y + rect.height / 2;
|
|
25
|
+
const maxHeight = Math.max(2, rect.height * .72);
|
|
26
|
+
const bars = audioWaveformBars(seed, count);
|
|
27
|
+
for (let index = 0; index < count; index += 1) {
|
|
28
|
+
const height = Math.max(2, (bars[index] ?? .4) * maxHeight);
|
|
29
|
+
graphics.roundRect(rect.x + index * step, centerY - height / 2, barWidth, height, barWidth / 2).fill({
|
|
30
|
+
color,
|
|
31
|
+
alpha
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { audioWaveformBars, drawAudioWaveform };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ConnectionLayer, ConnectionRenderInput, createConnectionLayer, framesFromItems } from "./connection-layer.js";
|
|
2
2
|
import { BoardCardRenderer, BoardRenderContext, BoardRenderPalette, boardCardRenderersForTest, getBoardCardRenderer, registerBoardCardRenderer } from "./renderers/board-renderer-registry.js";
|
|
3
3
|
import { defaultBoardPalette } from "./palette.js";
|
|
4
|
+
import { TASK_CARD_FULL_DETAIL_ZOOM } from "./renderers/task-card-renderer.js";
|
|
4
5
|
import { ensureBoardTextMeasurement, installBoardTextMeasurement } from "./text-measurement.js";
|
|
5
6
|
import { getBoardResolution, syncTextResolution, syncTextWrapWidth, textResolutionForZoom, textZoomBucket } from "./text-resolution.js";
|
|
6
7
|
import { BoardThemeContext, BoardThemeRenderer, getBoardThemeRenderer, registerBoardThemeRenderer } from "./themes/board-theme-registry.js";
|
|
7
|
-
export { BoardCardRenderer, BoardRenderContext, BoardRenderPalette, BoardThemeContext, BoardThemeRenderer, ConnectionLayer, ConnectionRenderInput, boardCardRenderersForTest, createConnectionLayer, defaultBoardPalette, ensureBoardTextMeasurement, framesFromItems, getBoardCardRenderer, getBoardResolution, getBoardThemeRenderer, installBoardTextMeasurement, registerBoardCardRenderer, registerBoardThemeRenderer, syncTextResolution, syncTextWrapWidth, textResolutionForZoom, textZoomBucket };
|
|
8
|
+
export { BoardCardRenderer, BoardRenderContext, BoardRenderPalette, BoardThemeContext, BoardThemeRenderer, ConnectionLayer, ConnectionRenderInput, TASK_CARD_FULL_DETAIL_ZOOM, boardCardRenderersForTest, createConnectionLayer, defaultBoardPalette, ensureBoardTextMeasurement, framesFromItems, getBoardCardRenderer, getBoardResolution, getBoardThemeRenderer, installBoardTextMeasurement, registerBoardCardRenderer, registerBoardThemeRenderer, syncTextResolution, syncTextWrapWidth, textResolutionForZoom, textZoomBucket };
|
|
@@ -2,6 +2,7 @@ import { getBoardResolution, syncTextResolution, syncTextWrapWidth, textResoluti
|
|
|
2
2
|
import { createConnectionLayer, framesFromItems } from "./connection-layer.js";
|
|
3
3
|
import { defaultBoardPalette } from "./palette.js";
|
|
4
4
|
import { ensureBoardTextMeasurement, installBoardTextMeasurement } from "./text-measurement.js";
|
|
5
|
+
import { TASK_CARD_FULL_DETAIL_ZOOM } from "./renderers/task-card-renderer.js";
|
|
5
6
|
import { boardCardRenderersForTest, getBoardCardRenderer, registerBoardCardRenderer } from "./renderers/board-renderer-registry.js";
|
|
6
7
|
import { getBoardThemeRenderer, registerBoardThemeRenderer } from "./themes/board-theme-registry.js";
|
|
7
|
-
export { boardCardRenderersForTest, createConnectionLayer, defaultBoardPalette, ensureBoardTextMeasurement, framesFromItems, getBoardCardRenderer, getBoardResolution, getBoardThemeRenderer, installBoardTextMeasurement, registerBoardCardRenderer, registerBoardThemeRenderer, syncTextResolution, syncTextWrapWidth, textResolutionForZoom, textZoomBucket };
|
|
8
|
+
export { TASK_CARD_FULL_DETAIL_ZOOM, boardCardRenderersForTest, createConnectionLayer, defaultBoardPalette, ensureBoardTextMeasurement, framesFromItems, getBoardCardRenderer, getBoardResolution, getBoardThemeRenderer, installBoardTextMeasurement, registerBoardCardRenderer, registerBoardThemeRenderer, syncTextResolution, syncTextWrapWidth, textResolutionForZoom, textZoomBucket };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { BOARD_FONT_STACK } from "../../../protocol/dist/board-constants.js";
|
|
2
|
+
import { syncTextResolution, syncTextWrapWidth, textResolutionForZoom } from "../text-resolution.js";
|
|
3
|
+
import { drawFarPlate } from "./far-plate.js";
|
|
4
|
+
import { drawAudioWaveform } from "../audio-waveform.js";
|
|
5
|
+
import { positionShell } from "./base-card-renderer.js";
|
|
6
|
+
import { Container, Graphics, Text } from "pixi.js";
|
|
7
|
+
//#region src/board/render/renderers/audio-card-renderer.ts
|
|
8
|
+
const RADIUS = 4;
|
|
9
|
+
const PLAY_RADIUS = 18;
|
|
10
|
+
const partsByContainer = /* @__PURE__ */ new WeakMap();
|
|
11
|
+
function sync(container, item, context) {
|
|
12
|
+
const parts = partsByContainer.get(container);
|
|
13
|
+
if (!parts) return;
|
|
14
|
+
positionShell(parts.root, item);
|
|
15
|
+
const { width, height } = item.frame;
|
|
16
|
+
const selected = context.selectedIds.has(item.id);
|
|
17
|
+
const hovered = context.hoveredId === item.id;
|
|
18
|
+
const title = item.snapshot?.title ?? item.ref.path.split("/").pop() ?? "Audio";
|
|
19
|
+
syncTextResolution(parts.label, parts, context.zoom);
|
|
20
|
+
if (parts.label.text !== title) parts.label.text = title;
|
|
21
|
+
syncTextWrapWidth(parts.label, parts, Math.max(1, width - 24), false);
|
|
22
|
+
parts.label.position.set(12, Math.max(8, height - parts.label.height - 8));
|
|
23
|
+
const sig = [
|
|
24
|
+
width,
|
|
25
|
+
height,
|
|
26
|
+
selected,
|
|
27
|
+
hovered,
|
|
28
|
+
title,
|
|
29
|
+
parts.label.height,
|
|
30
|
+
context.palette.surface,
|
|
31
|
+
context.palette.brand,
|
|
32
|
+
context.palette.border,
|
|
33
|
+
context.palette.muted,
|
|
34
|
+
context.palette.text
|
|
35
|
+
].join("|");
|
|
36
|
+
if (sig === parts.sig) return;
|
|
37
|
+
parts.sig = sig;
|
|
38
|
+
parts.plate.clear().roundRect(0, 0, width, height, RADIUS).fill({
|
|
39
|
+
color: context.palette.surface,
|
|
40
|
+
alpha: .98
|
|
41
|
+
}).roundRect(0, 0, width, height, RADIUS).stroke({
|
|
42
|
+
color: selected ? context.palette.brand : hovered ? context.palette.muted : context.palette.border,
|
|
43
|
+
width: selected ? 2 : 1,
|
|
44
|
+
alpha: selected ? .96 : .84
|
|
45
|
+
});
|
|
46
|
+
const labelBand = Math.min(height * .38, parts.label.height + 16);
|
|
47
|
+
const waveformInset = Math.min(24, width * .08);
|
|
48
|
+
parts.waveform.clear();
|
|
49
|
+
drawAudioWaveform(parts.waveform, `${item.ref.path}:${item.snapshot?.mtimeMs ?? "unknown"}`, {
|
|
50
|
+
x: waveformInset,
|
|
51
|
+
y: 10,
|
|
52
|
+
width: Math.max(1, width - waveformInset * 2),
|
|
53
|
+
height: Math.max(8, height - labelBand - 16)
|
|
54
|
+
}, context.palette.brand);
|
|
55
|
+
const cx = width / 2;
|
|
56
|
+
const cy = Math.max(24, (height - labelBand) / 2);
|
|
57
|
+
parts.chrome.clear().circle(cx, cy, PLAY_RADIUS).fill({
|
|
58
|
+
color: selected ? context.palette.brand : context.palette.surface,
|
|
59
|
+
alpha: .92
|
|
60
|
+
});
|
|
61
|
+
const triangle = PLAY_RADIUS * .58;
|
|
62
|
+
parts.chrome.moveTo(cx - triangle * .35, cy - triangle * .62).lineTo(cx - triangle * .35, cy + triangle * .62).lineTo(cx + triangle * .72, cy).closePath().fill({
|
|
63
|
+
color: context.palette.text,
|
|
64
|
+
alpha: .96
|
|
65
|
+
});
|
|
66
|
+
parts.label.style.fill = context.palette.text;
|
|
67
|
+
}
|
|
68
|
+
const audioCardRenderer = {
|
|
69
|
+
id: "audio-card",
|
|
70
|
+
canRender: (item) => item.type === "audio",
|
|
71
|
+
create: (item, context) => {
|
|
72
|
+
const root = new Container();
|
|
73
|
+
const plate = new Graphics();
|
|
74
|
+
const waveform = new Graphics();
|
|
75
|
+
const chrome = new Graphics();
|
|
76
|
+
const resolution = textResolutionForZoom(context.zoom);
|
|
77
|
+
const label = new Text({
|
|
78
|
+
text: "",
|
|
79
|
+
style: {
|
|
80
|
+
fill: context.palette.text,
|
|
81
|
+
fontFamily: BOARD_FONT_STACK,
|
|
82
|
+
fontSize: 12,
|
|
83
|
+
fontWeight: "500",
|
|
84
|
+
wordWrap: true
|
|
85
|
+
},
|
|
86
|
+
resolution,
|
|
87
|
+
roundPixels: true
|
|
88
|
+
});
|
|
89
|
+
root.addChild(plate, waveform, chrome, label);
|
|
90
|
+
partsByContainer.set(root, {
|
|
91
|
+
root,
|
|
92
|
+
plate,
|
|
93
|
+
waveform,
|
|
94
|
+
chrome,
|
|
95
|
+
label,
|
|
96
|
+
sig: "",
|
|
97
|
+
wrapWidth: 0,
|
|
98
|
+
resolution
|
|
99
|
+
});
|
|
100
|
+
if (item.type === "audio") sync(root, item, context);
|
|
101
|
+
return root;
|
|
102
|
+
},
|
|
103
|
+
update: (container, item, context) => {
|
|
104
|
+
if (item.type === "audio") sync(container, item, context);
|
|
105
|
+
},
|
|
106
|
+
renderFar: (graphics, item, context) => {
|
|
107
|
+
drawFarPlate(graphics, item.frame, {
|
|
108
|
+
fill: context.palette.surface,
|
|
109
|
+
fillAlpha: .96,
|
|
110
|
+
accent: context.palette.brand,
|
|
111
|
+
accentAlpha: .72
|
|
112
|
+
});
|
|
113
|
+
},
|
|
114
|
+
destroy: (container) => {
|
|
115
|
+
partsByContainer.get(container)?.root.destroy({ children: true });
|
|
116
|
+
partsByContainer.delete(container);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
//#endregion
|
|
120
|
+
export { audioCardRenderer };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ensureBoardTextMeasurement } from "../text-measurement.js";
|
|
2
2
|
import { arrowCardRenderer } from "./arrow-card-renderer.js";
|
|
3
|
+
import { audioCardRenderer } from "./audio-card-renderer.js";
|
|
3
4
|
import { drawCardRenderer } from "./draw-card-renderer.js";
|
|
4
5
|
import { fileCardRenderer } from "./file-card-renderer.js";
|
|
5
6
|
import { frameCardRenderer } from "./frame-card-renderer.js";
|
|
@@ -14,6 +15,7 @@ const boardCardRenderers = [
|
|
|
14
15
|
textCardRenderer,
|
|
15
16
|
imageCardRenderer,
|
|
16
17
|
videoCardRenderer,
|
|
18
|
+
audioCardRenderer,
|
|
17
19
|
fileCardRenderer,
|
|
18
20
|
taskCardRenderer,
|
|
19
21
|
geoCardRenderer,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BoardCardRenderer } from "./board-renderer-registry.js";
|
|
2
2
|
//#region src/board/render/renderers/task-card-renderer.d.ts
|
|
3
|
+
declare const TASK_CARD_FULL_DETAIL_ZOOM = 0.55;
|
|
3
4
|
/** Scale a texture into a frame without cropping or distortion. */
|
|
4
5
|
declare function containTaskPreviewRect(width: number, height: number, imageWidth: number, imageHeight: number): {
|
|
5
6
|
x: number;
|
|
@@ -9,4 +10,4 @@ declare function containTaskPreviewRect(width: number, height: number, imageWidt
|
|
|
9
10
|
};
|
|
10
11
|
declare const taskCardRenderer: BoardCardRenderer;
|
|
11
12
|
//#endregion
|
|
12
|
-
export { containTaskPreviewRect, taskCardRenderer };
|
|
13
|
+
export { TASK_CARD_FULL_DETAIL_ZOOM, containTaskPreviewRect, taskCardRenderer };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BOARD_FONT_STACK, BOARD_MONO_FONT_STACK } from "../../../protocol/dist/board-constants.js";
|
|
2
2
|
import { syncTextResolution, textResolutionForZoom } from "../text-resolution.js";
|
|
3
3
|
import { drawFarPlate } from "./far-plate.js";
|
|
4
|
+
import { drawAudioWaveform } from "../audio-waveform.js";
|
|
4
5
|
import { positionShell } from "./base-card-renderer.js";
|
|
5
6
|
import { fitTextToLines } from "./file-card-renderer.js";
|
|
6
7
|
import { Container, Graphics, Sprite, Text } from "pixi.js";
|
|
@@ -8,9 +9,7 @@ import { Container, Graphics, Sprite, Text } from "pixi.js";
|
|
|
8
9
|
const RADIUS = 4;
|
|
9
10
|
const PADDING = 12;
|
|
10
11
|
const META_HEIGHT = 28;
|
|
11
|
-
const
|
|
12
|
-
const WAVEFORM_BARS = 44;
|
|
13
|
-
const WAVEFORM_GAP = 2;
|
|
12
|
+
const TASK_CARD_FULL_DETAIL_ZOOM = .55;
|
|
14
13
|
const PLAY_BADGE_RADIUS = 15;
|
|
15
14
|
const partsByContainer = /* @__PURE__ */ new WeakMap();
|
|
16
15
|
function previewKindFor(item) {
|
|
@@ -68,40 +67,6 @@ function containTaskPreviewRect(width, height, imageWidth, imageHeight) {
|
|
|
68
67
|
height: renderedHeight
|
|
69
68
|
};
|
|
70
69
|
}
|
|
71
|
-
function waveformBars(seed, count) {
|
|
72
|
-
let hash = 2166136261;
|
|
73
|
-
for (let index = 0; index < seed.length; index += 1) {
|
|
74
|
-
hash ^= seed.charCodeAt(index);
|
|
75
|
-
hash = Math.imul(hash, 16777619) >>> 0;
|
|
76
|
-
}
|
|
77
|
-
const bars = [];
|
|
78
|
-
for (let index = 0; index < count; index += 1) {
|
|
79
|
-
hash ^= hash << 13;
|
|
80
|
-
hash ^= hash >>> 17;
|
|
81
|
-
hash ^= hash << 5;
|
|
82
|
-
hash >>>= 0;
|
|
83
|
-
const unit = hash % 1e3 / 1e3;
|
|
84
|
-
const envelope = Math.sin(Math.PI * (index + .5) / count);
|
|
85
|
-
bars.push(.18 + unit * .82 * (.45 + envelope * .55));
|
|
86
|
-
}
|
|
87
|
-
return bars;
|
|
88
|
-
}
|
|
89
|
-
function drawWaveform(graphics, seed, rect, color) {
|
|
90
|
-
const count = Math.max(8, Math.min(WAVEFORM_BARS, Math.floor(rect.width / 4)));
|
|
91
|
-
const step = rect.width / count;
|
|
92
|
-
const barWidth = Math.max(1.5, step - WAVEFORM_GAP);
|
|
93
|
-
const centerY = rect.y + rect.height / 2;
|
|
94
|
-
const maxHeight = Math.max(2, rect.height * .68);
|
|
95
|
-
const bars = waveformBars(seed, count);
|
|
96
|
-
for (let index = 0; index < count; index += 1) {
|
|
97
|
-
const amplitude = (bars[index] ?? .4) * maxHeight;
|
|
98
|
-
graphics.roundRect(rect.x + index * step + (step - barWidth) / 2, centerY - amplitude / 2, barWidth, amplitude, barWidth / 2);
|
|
99
|
-
}
|
|
100
|
-
graphics.fill({
|
|
101
|
-
color,
|
|
102
|
-
alpha: .68
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
70
|
function drawPlayBadge(graphics, rect, context) {
|
|
106
71
|
const radius = Math.min(PLAY_BADGE_RADIUS, Math.max(8, Math.min(rect.width, rect.height) * .16));
|
|
107
72
|
const cx = rect.x + rect.width / 2;
|
|
@@ -194,7 +159,7 @@ function sync(container, item, context) {
|
|
|
194
159
|
const { width, height } = item.frame;
|
|
195
160
|
const selected = context.selectedIds.has(item.id);
|
|
196
161
|
const hovered = context.hoveredId === item.id;
|
|
197
|
-
const full = context.zoom >=
|
|
162
|
+
const full = context.zoom >= TASK_CARD_FULL_DETAIL_ZOOM;
|
|
198
163
|
const color = statusColor(item, context);
|
|
199
164
|
const key = context.assetKey(item);
|
|
200
165
|
if (key !== parts.assetKey) {
|
|
@@ -255,14 +220,14 @@ function sync(container, item, context) {
|
|
|
255
220
|
parts.previewArt.clear();
|
|
256
221
|
if (kind === "waveform") {
|
|
257
222
|
const bottomInset = showMeta ? META_HEIGHT : 0;
|
|
258
|
-
|
|
223
|
+
drawAudioWaveform(parts.previewArt, item.taskRunId, {
|
|
259
224
|
x: frame.x + PADDING,
|
|
260
225
|
y: frame.y + PADDING,
|
|
261
226
|
width: Math.max(1, frame.width - PADDING * 2),
|
|
262
227
|
height: Math.max(1, frame.height - PADDING * 2 - bottomInset)
|
|
263
228
|
}, context.colors.brand.stroke);
|
|
264
229
|
}
|
|
265
|
-
if (
|
|
230
|
+
if (full && (item.snapshot.primaryOutput?.type === "audio" || item.snapshot.primaryOutput?.type === "video" && texture)) drawPlayBadge(parts.previewArt, frame, context);
|
|
266
231
|
if (surface) {
|
|
267
232
|
const markY = frame.y + frame.height / 2 - (full && stateLabel(surface) ? 10 : 0);
|
|
268
233
|
drawStateMark(parts.previewArt, surface, frame.x + frame.width / 2, markY, surface === "failed" ? color : context.colors.neutral.stroke);
|
|
@@ -386,4 +351,4 @@ const taskCardRenderer = {
|
|
|
386
351
|
}
|
|
387
352
|
};
|
|
388
353
|
//#endregion
|
|
389
|
-
export { containTaskPreviewRect, taskCardRenderer };
|
|
354
|
+
export { TASK_CARD_FULL_DETAIL_ZOOM, containTaskPreviewRect, taskCardRenderer };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BoardTaskSnapshot } from "../protocol/dist/board-document.js";
|
|
2
|
+
import { TaskRunRecord } from "../types.js";
|
|
3
|
+
//#region src/board/task.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Normalize a persistable remote media URL and reject credentialed or visibly
|
|
6
|
+
* non-public hosts. Server-side fetchers must still validate resolved DNS addresses.
|
|
7
|
+
*/
|
|
8
|
+
declare function normalizeBoardTaskOutputUrl(value: unknown): string | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Project an authoritative TaskRun into a small, replaceable Board display cache.
|
|
11
|
+
* Raw payloads, complete results and inline media are never copied into the Board.
|
|
12
|
+
*/
|
|
13
|
+
declare function taskRunToBoardTaskSnapshot(run: TaskRunRecord): BoardTaskSnapshot;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { normalizeBoardTaskOutputUrl, taskRunToBoardTaskSnapshot };
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
//#region src/board/task.ts
|
|
2
|
+
const EXCERPT_LIMIT = 240;
|
|
3
|
+
function record(value) {
|
|
4
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
5
|
+
}
|
|
6
|
+
function cleanExcerpt(value, limit = EXCERPT_LIMIT) {
|
|
7
|
+
if (typeof value !== "string") return void 0;
|
|
8
|
+
const clean = value.replace(/\s+/g, " ").trim();
|
|
9
|
+
if (!clean) return void 0;
|
|
10
|
+
return clean.length > limit ? `${clean.slice(0, limit - 3).trimEnd()}...` : clean;
|
|
11
|
+
}
|
|
12
|
+
function parseIpv4(host) {
|
|
13
|
+
const parts = host.split(".").map(Number);
|
|
14
|
+
return parts.length === 4 && parts.every((part) => Number.isInteger(part) && part >= 0 && part <= 255) ? parts : null;
|
|
15
|
+
}
|
|
16
|
+
function isBlockedIpv4(host) {
|
|
17
|
+
const parts = parseIpv4(host);
|
|
18
|
+
if (!parts) return false;
|
|
19
|
+
const [first, second, third] = parts;
|
|
20
|
+
if (first === 0 || first === 10 || first === 127) return true;
|
|
21
|
+
if (first === 100 && second >= 64 && second <= 127) return true;
|
|
22
|
+
if (first === 169 && second === 254) return true;
|
|
23
|
+
if (first === 172 && second >= 16 && second <= 31) return true;
|
|
24
|
+
if (first === 192 && second === 168) return true;
|
|
25
|
+
if (first === 192 && second === 0 && (third === 0 || third === 2)) return true;
|
|
26
|
+
if (first === 192 && second === 88 && third === 99) return true;
|
|
27
|
+
if (first === 198 && (second === 18 || second === 19)) return true;
|
|
28
|
+
if (first === 198 && second === 51 && third === 100) return true;
|
|
29
|
+
if (first === 203 && second === 0 && third === 113) return true;
|
|
30
|
+
return first >= 224;
|
|
31
|
+
}
|
|
32
|
+
function expandIpv6(host) {
|
|
33
|
+
const [head, tail, extra] = host.toLowerCase().split("::");
|
|
34
|
+
if (extra !== void 0) return null;
|
|
35
|
+
const headParts = head ? head.split(":").filter(Boolean) : [];
|
|
36
|
+
const tailParts = tail ? tail.split(":").filter(Boolean) : [];
|
|
37
|
+
const missing = 8 - headParts.length - tailParts.length;
|
|
38
|
+
if (missing < 0 || tail === void 0 && missing !== 0) return null;
|
|
39
|
+
const parts = [
|
|
40
|
+
...headParts,
|
|
41
|
+
...Array.from({ length: missing }, () => "0"),
|
|
42
|
+
...tailParts
|
|
43
|
+
];
|
|
44
|
+
if (parts.length !== 8 || parts.some((part) => !/^[0-9a-f]{1,4}$/.test(part))) return null;
|
|
45
|
+
return parts.map((part) => part.padStart(4, "0"));
|
|
46
|
+
}
|
|
47
|
+
function isBlockedIpv6(host) {
|
|
48
|
+
const parts = expandIpv6(host);
|
|
49
|
+
if (!parts) return true;
|
|
50
|
+
if (parts.every((part) => part === "0000")) return true;
|
|
51
|
+
if (parts.slice(0, 7).every((part) => part === "0000") && parts[7] === "0001") return true;
|
|
52
|
+
if (parts.slice(0, 5).every((part) => part === "0000") && parts[5] === "ffff") {
|
|
53
|
+
const high = Number.parseInt(parts[6] ?? "0", 16);
|
|
54
|
+
const low = Number.parseInt(parts[7] ?? "0", 16);
|
|
55
|
+
return isBlockedIpv4(`${high >> 8}.${high & 255}.${low >> 8}.${low & 255}`);
|
|
56
|
+
}
|
|
57
|
+
if (parts.slice(0, 6).every((part) => part === "0000")) return true;
|
|
58
|
+
const first = Number.parseInt(parts[0] ?? "0", 16);
|
|
59
|
+
if ((first & 65024) === 64512) return true;
|
|
60
|
+
if ((first & 65472) === 65152 || (first & 65472) === 65216) return true;
|
|
61
|
+
if ((first & 65280) === 65280) return true;
|
|
62
|
+
return parts[0] === "2001" && parts[1] === "0db8";
|
|
63
|
+
}
|
|
64
|
+
function isBlockedTaskOutputHost(hostname) {
|
|
65
|
+
const host = hostname.toLowerCase().replace(/^\[|\]$/g, "").replace(/\.$/, "");
|
|
66
|
+
if (host === "localhost" || host.endsWith(".localhost") || host.endsWith(".local") || host.endsWith(".internal")) return true;
|
|
67
|
+
if (parseIpv4(host)) return isBlockedIpv4(host);
|
|
68
|
+
return host.includes(":") && isBlockedIpv6(host);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Normalize a persistable remote media URL and reject credentialed or visibly
|
|
72
|
+
* non-public hosts. Server-side fetchers must still validate resolved DNS addresses.
|
|
73
|
+
*/
|
|
74
|
+
function normalizeBoardTaskOutputUrl(value) {
|
|
75
|
+
if (typeof value !== "string") return void 0;
|
|
76
|
+
try {
|
|
77
|
+
const url = new URL(value.trim());
|
|
78
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") return void 0;
|
|
79
|
+
if (url.username || url.password || isBlockedTaskOutputHost(url.hostname)) return void 0;
|
|
80
|
+
return url.toString();
|
|
81
|
+
} catch {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function blockText(block) {
|
|
86
|
+
return cleanExcerpt(block.text ?? block.content ?? block.value);
|
|
87
|
+
}
|
|
88
|
+
function blockUrl(block) {
|
|
89
|
+
const source = record(block.source);
|
|
90
|
+
return normalizeBoardTaskOutputUrl(source?.url ?? source?.src ?? block.url ?? block.src);
|
|
91
|
+
}
|
|
92
|
+
function blockMimeType(block) {
|
|
93
|
+
const source = record(block.source);
|
|
94
|
+
const value = source?.mediaType ?? source?.media_type ?? source?.mimeType ?? block.mediaType ?? block.media_type ?? block.mimeType;
|
|
95
|
+
return typeof value === "string" ? value : void 0;
|
|
96
|
+
}
|
|
97
|
+
function positiveNumber(value) {
|
|
98
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
99
|
+
}
|
|
100
|
+
function blockNaturalSize(block) {
|
|
101
|
+
const source = record(block.source);
|
|
102
|
+
const naturalWidth = positiveNumber(source?.width ?? source?.naturalWidth ?? block.width ?? block.naturalWidth);
|
|
103
|
+
const naturalHeight = positiveNumber(source?.height ?? source?.naturalHeight ?? block.height ?? block.naturalHeight);
|
|
104
|
+
return {
|
|
105
|
+
...naturalWidth ? { naturalWidth } : {},
|
|
106
|
+
...naturalHeight ? { naturalHeight } : {}
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function contentBlocks(value) {
|
|
110
|
+
return Array.isArray(value) ? value.filter((item) => record(item)) : [];
|
|
111
|
+
}
|
|
112
|
+
function taskData(run) {
|
|
113
|
+
const payload = record(run.payload);
|
|
114
|
+
return record(payload?.data) ?? payload;
|
|
115
|
+
}
|
|
116
|
+
function generationOutput(run) {
|
|
117
|
+
return contentBlocks(record(run.result)?.output);
|
|
118
|
+
}
|
|
119
|
+
function generationPrompt(run) {
|
|
120
|
+
for (const block of contentBlocks(taskData(run)?.content)) {
|
|
121
|
+
const text = blockText(block);
|
|
122
|
+
if (text) return text;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function primaryOutput(blocks) {
|
|
126
|
+
for (const block of blocks) {
|
|
127
|
+
if (block.type !== "image" && block.type !== "video") continue;
|
|
128
|
+
const url = blockUrl(block);
|
|
129
|
+
if (!url) continue;
|
|
130
|
+
const mimeType = blockMimeType(block);
|
|
131
|
+
return {
|
|
132
|
+
type: block.type,
|
|
133
|
+
url,
|
|
134
|
+
...mimeType ? { mimeType } : {},
|
|
135
|
+
...blockNaturalSize(block)
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
for (const block of blocks) {
|
|
139
|
+
if (block.type === "audio") {
|
|
140
|
+
const url = blockUrl(block);
|
|
141
|
+
const mimeType = blockMimeType(block);
|
|
142
|
+
return {
|
|
143
|
+
type: "audio",
|
|
144
|
+
...url ? { url } : {},
|
|
145
|
+
...mimeType ? { mimeType } : {}
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
if (block.type === "text") {
|
|
149
|
+
const textExcerpt = blockText(block);
|
|
150
|
+
if (textExcerpt) return {
|
|
151
|
+
type: "text",
|
|
152
|
+
textExcerpt
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function taskTypeTitle(taskType) {
|
|
158
|
+
return taskType.replace(/[._-]+/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Project an authoritative TaskRun into a small, replaceable Board display cache.
|
|
162
|
+
* Raw payloads, complete results and inline media are never copied into the Board.
|
|
163
|
+
*/
|
|
164
|
+
function taskRunToBoardTaskSnapshot(run) {
|
|
165
|
+
const data = taskData(run);
|
|
166
|
+
const blocks = run.taskType === "generation" ? generationOutput(run) : [];
|
|
167
|
+
const promptExcerpt = run.taskType === "generation" ? generationPrompt(run) : cleanExcerpt(data?.command ?? data?.prompt ?? data?.title);
|
|
168
|
+
const model = typeof data?.model === "string" ? data.model : void 0;
|
|
169
|
+
const primary = primaryOutput(blocks);
|
|
170
|
+
return {
|
|
171
|
+
taskType: run.taskType,
|
|
172
|
+
status: run.status,
|
|
173
|
+
title: promptExcerpt ?? taskTypeTitle(run.taskType),
|
|
174
|
+
...model ? { model } : {},
|
|
175
|
+
...promptExcerpt ? { promptExcerpt } : {},
|
|
176
|
+
outputCount: blocks.length,
|
|
177
|
+
...primary ? { primaryOutput: primary } : {},
|
|
178
|
+
updatedAt: run.updatedAt
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
//#endregion
|
|
182
|
+
export { normalizeBoardTaskOutputUrl, taskRunToBoardTaskSnapshot };
|
package/dist/chunks/http.d.ts
CHANGED
|
@@ -1662,7 +1662,13 @@ declare class TasksApi {
|
|
|
1662
1662
|
private readonly transport;
|
|
1663
1663
|
constructor(transport: HttpTransport);
|
|
1664
1664
|
get(taskRunId: string): Promise<TaskRunDetailResponse>;
|
|
1665
|
+
getMany(taskRunIds: string[], options?: {
|
|
1666
|
+
spaceId?: string;
|
|
1667
|
+
}): Promise<{
|
|
1668
|
+
runs: TaskRunRecord[];
|
|
1669
|
+
}>;
|
|
1665
1670
|
list(filters?: {
|
|
1671
|
+
ids?: string[];
|
|
1666
1672
|
cronJobId?: string;
|
|
1667
1673
|
spaceId?: string;
|
|
1668
1674
|
sessionId?: string;
|
package/dist/chunks/http.js
CHANGED
|
@@ -3135,8 +3135,19 @@ var TasksApi = class {
|
|
|
3135
3135
|
get(taskRunId) {
|
|
3136
3136
|
return this.transport.request(`/api/tasks/${taskRunId}`);
|
|
3137
3137
|
}
|
|
3138
|
+
getMany(taskRunIds, options) {
|
|
3139
|
+
const ids = [...new Set(taskRunIds.filter(Boolean))];
|
|
3140
|
+
if (ids.length === 0) return Promise.resolve({ runs: [] });
|
|
3141
|
+
if (ids.length > 100) throw new Error("At most 100 task runs can be fetched at once");
|
|
3142
|
+
return this.list({
|
|
3143
|
+
ids,
|
|
3144
|
+
spaceId: options?.spaceId,
|
|
3145
|
+
limit: ids.length
|
|
3146
|
+
}).then(({ runs }) => ({ runs }));
|
|
3147
|
+
}
|
|
3138
3148
|
list(filters) {
|
|
3139
3149
|
const params = new URLSearchParams();
|
|
3150
|
+
if (filters?.ids?.length) params.set("ids", [...new Set(filters.ids)].join(","));
|
|
3140
3151
|
if (filters?.cronJobId) params.set("cronJobId", filters.cronJobId);
|
|
3141
3152
|
if (filters?.spaceId) params.set("spaceId", filters.spaceId);
|
|
3142
3153
|
if (filters?.sessionId) params.set("sessionId", filters.sessionId);
|
|
@@ -2877,7 +2877,7 @@ type BillingRedemptionResult = {
|
|
|
2877
2877
|
};
|
|
2878
2878
|
type BillingConversionIntent = {
|
|
2879
2879
|
level: "soft" | "hard";
|
|
2880
|
-
reason: "negative_balance" | "negative_balance_limit_exceeded" | "minimum_balance_not_met" | "feature_not_entitled";
|
|
2880
|
+
reason: "negative_balance" | "negative_balance_limit_exceeded" | "balance_not_positive" | "minimum_balance_not_met" | "feature_not_entitled";
|
|
2881
2881
|
audience: "free" | "paid" | "unknown";
|
|
2882
2882
|
preferredOfferKind: "plan" | "upgrade" | "addon" | "mixed";
|
|
2883
2883
|
title: string;
|
|
@@ -370,6 +370,50 @@ declare const BoardVideoItemSchema: z.ZodObject<{
|
|
|
370
370
|
naturalHeight: z.ZodOptional<z.ZodNumber>;
|
|
371
371
|
}, z.core.$strip>>;
|
|
372
372
|
}, z.core.$strip>;
|
|
373
|
+
/** Audio node — space file only. Playback state is local UI, never synced. */
|
|
374
|
+
declare const BoardAudioItemSchema: z.ZodObject<{
|
|
375
|
+
id: z.ZodString;
|
|
376
|
+
frame: z.ZodObject<{
|
|
377
|
+
x: z.ZodNumber;
|
|
378
|
+
y: z.ZodNumber;
|
|
379
|
+
width: z.ZodNumber;
|
|
380
|
+
height: z.ZodNumber;
|
|
381
|
+
rotation: z.ZodDefault<z.ZodNumber>;
|
|
382
|
+
}, z.core.$strip>;
|
|
383
|
+
locked: z.ZodOptional<z.ZodBoolean>;
|
|
384
|
+
style: z.ZodOptional<z.ZodObject<{
|
|
385
|
+
variant: z.ZodDefault<z.ZodString>;
|
|
386
|
+
theme: z.ZodOptional<z.ZodString>;
|
|
387
|
+
accentColor: z.ZodOptional<z.ZodString>;
|
|
388
|
+
size: z.ZodDefault<z.ZodEnum<{
|
|
389
|
+
lg: "lg";
|
|
390
|
+
md: "md";
|
|
391
|
+
sm: "sm";
|
|
392
|
+
}>>;
|
|
393
|
+
emphasis: z.ZodDefault<z.ZodEnum<{
|
|
394
|
+
epic: "epic";
|
|
395
|
+
legendary: "legendary";
|
|
396
|
+
normal: "normal";
|
|
397
|
+
rare: "rare";
|
|
398
|
+
}>>;
|
|
399
|
+
effects: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
400
|
+
}, z.core.$strip>>;
|
|
401
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
402
|
+
type: z.ZodLiteral<"audio">;
|
|
403
|
+
ref: z.ZodObject<{
|
|
404
|
+
kind: z.ZodLiteral<"space-file">;
|
|
405
|
+
path: z.ZodString;
|
|
406
|
+
}, z.core.$strip>;
|
|
407
|
+
snapshot: z.ZodOptional<z.ZodObject<{
|
|
408
|
+
title: z.ZodOptional<z.ZodString>;
|
|
409
|
+
mimeType: z.ZodOptional<z.ZodString>;
|
|
410
|
+
size: z.ZodOptional<z.ZodNumber>;
|
|
411
|
+
mtimeMs: z.ZodOptional<z.ZodNumber>;
|
|
412
|
+
naturalWidth: z.ZodOptional<z.ZodNumber>;
|
|
413
|
+
naturalHeight: z.ZodOptional<z.ZodNumber>;
|
|
414
|
+
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
415
|
+
}, z.core.$strip>>;
|
|
416
|
+
}, z.core.$strip>;
|
|
373
417
|
/**
|
|
374
418
|
* Cached display facts for a file card.
|
|
375
419
|
*
|
|
@@ -549,7 +593,7 @@ declare const BoardTaskItemSchema: z.ZodObject<{
|
|
|
549
593
|
* authored by newer clients round-trip losslessly — data is never dropped or
|
|
550
594
|
* silently downgraded just because this client predates a shape type.
|
|
551
595
|
*/
|
|
552
|
-
declare const KNOWN_BOARD_ITEM_TYPES: readonly ["image", "video", "file", "task", "text", "geo", "draw", "arrow", "frame"];
|
|
596
|
+
declare const KNOWN_BOARD_ITEM_TYPES: readonly ["image", "video", "audio", "file", "task", "text", "geo", "draw", "arrow", "frame"];
|
|
553
597
|
type KnownBoardItemType = (typeof KNOWN_BOARD_ITEM_TYPES)[number];
|
|
554
598
|
/**
|
|
555
599
|
* A forward-compatible carrier for shape types this client does not recognise.
|
|
@@ -640,6 +684,39 @@ declare const BoardItemSchema: z.ZodPipe<z.ZodAny, z.ZodTransform<BoardUnknownIt
|
|
|
640
684
|
naturalWidth?: number | undefined;
|
|
641
685
|
naturalHeight?: number | undefined;
|
|
642
686
|
} | undefined;
|
|
687
|
+
} | {
|
|
688
|
+
id: string;
|
|
689
|
+
frame: {
|
|
690
|
+
x: number;
|
|
691
|
+
y: number;
|
|
692
|
+
width: number;
|
|
693
|
+
height: number;
|
|
694
|
+
rotation: number;
|
|
695
|
+
};
|
|
696
|
+
locked?: boolean | undefined;
|
|
697
|
+
style?: {
|
|
698
|
+
variant: string;
|
|
699
|
+
theme?: string | undefined;
|
|
700
|
+
accentColor?: string | undefined;
|
|
701
|
+
size: "lg" | "md" | "sm";
|
|
702
|
+
emphasis: "epic" | "legendary" | "normal" | "rare";
|
|
703
|
+
effects: string[];
|
|
704
|
+
} | undefined;
|
|
705
|
+
metadata?: Record<string, unknown> | undefined;
|
|
706
|
+
type: "audio";
|
|
707
|
+
ref: {
|
|
708
|
+
kind: "space-file";
|
|
709
|
+
path: string;
|
|
710
|
+
};
|
|
711
|
+
snapshot?: {
|
|
712
|
+
title?: string | undefined;
|
|
713
|
+
mimeType?: string | undefined;
|
|
714
|
+
size?: number | undefined;
|
|
715
|
+
mtimeMs?: number | undefined;
|
|
716
|
+
naturalWidth?: number | undefined;
|
|
717
|
+
naturalHeight?: number | undefined;
|
|
718
|
+
durationMs?: number | undefined;
|
|
719
|
+
} | undefined;
|
|
643
720
|
} | {
|
|
644
721
|
id: string;
|
|
645
722
|
frame: {
|
|
@@ -953,6 +1030,39 @@ declare const BoardDocumentSchema: z.ZodObject<{
|
|
|
953
1030
|
naturalWidth?: number | undefined;
|
|
954
1031
|
naturalHeight?: number | undefined;
|
|
955
1032
|
} | undefined;
|
|
1033
|
+
} | {
|
|
1034
|
+
id: string;
|
|
1035
|
+
frame: {
|
|
1036
|
+
x: number;
|
|
1037
|
+
y: number;
|
|
1038
|
+
width: number;
|
|
1039
|
+
height: number;
|
|
1040
|
+
rotation: number;
|
|
1041
|
+
};
|
|
1042
|
+
locked?: boolean | undefined;
|
|
1043
|
+
style?: {
|
|
1044
|
+
variant: string;
|
|
1045
|
+
theme?: string | undefined;
|
|
1046
|
+
accentColor?: string | undefined;
|
|
1047
|
+
size: "lg" | "md" | "sm";
|
|
1048
|
+
emphasis: "epic" | "legendary" | "normal" | "rare";
|
|
1049
|
+
effects: string[];
|
|
1050
|
+
} | undefined;
|
|
1051
|
+
metadata?: Record<string, unknown> | undefined;
|
|
1052
|
+
type: "audio";
|
|
1053
|
+
ref: {
|
|
1054
|
+
kind: "space-file";
|
|
1055
|
+
path: string;
|
|
1056
|
+
};
|
|
1057
|
+
snapshot?: {
|
|
1058
|
+
title?: string | undefined;
|
|
1059
|
+
mimeType?: string | undefined;
|
|
1060
|
+
size?: number | undefined;
|
|
1061
|
+
mtimeMs?: number | undefined;
|
|
1062
|
+
naturalWidth?: number | undefined;
|
|
1063
|
+
naturalHeight?: number | undefined;
|
|
1064
|
+
durationMs?: number | undefined;
|
|
1065
|
+
} | undefined;
|
|
956
1066
|
} | {
|
|
957
1067
|
id: string;
|
|
958
1068
|
frame: {
|
|
@@ -1241,13 +1351,14 @@ type BoardArrowItem = z.infer<typeof BoardArrowItemSchema>;
|
|
|
1241
1351
|
type BoardFrameItem = z.infer<typeof BoardFrameItemSchema>;
|
|
1242
1352
|
type BoardImageItem = z.infer<typeof BoardImageItemSchema>;
|
|
1243
1353
|
type BoardVideoItem = z.infer<typeof BoardVideoItemSchema>;
|
|
1354
|
+
type BoardAudioItem = z.infer<typeof BoardAudioItemSchema>;
|
|
1244
1355
|
type BoardFileSnapshot = z.infer<typeof BoardFileSnapshotSchema>;
|
|
1245
1356
|
type BoardFileItem = z.infer<typeof BoardFileItemSchema>;
|
|
1246
1357
|
type BoardTaskOutput = z.infer<typeof BoardTaskOutputSchema>;
|
|
1247
1358
|
type BoardTaskSnapshot = z.infer<typeof BoardTaskSnapshotSchema>;
|
|
1248
1359
|
type BoardTaskItem = z.infer<typeof BoardTaskItemSchema>;
|
|
1249
1360
|
/** Known (natively handled) item variants. */
|
|
1250
|
-
type BoardKnownItem = BoardImageItem | BoardVideoItem | BoardFileItem | BoardTaskItem | BoardTextItem | BoardGeoItem | BoardDrawItem | BoardArrowItem | BoardFrameItem;
|
|
1361
|
+
type BoardKnownItem = BoardImageItem | BoardVideoItem | BoardAudioItem | BoardFileItem | BoardTaskItem | BoardTextItem | BoardGeoItem | BoardDrawItem | BoardArrowItem | BoardFrameItem;
|
|
1251
1362
|
/** Any item, including forward-compatible unknown types. */
|
|
1252
1363
|
type BoardItem = BoardKnownItem | BoardUnknownItem;
|
|
1253
1364
|
type BoardDocument = z.infer<typeof BoardDocumentSchema>;
|
|
@@ -1268,8 +1379,8 @@ declare function parseBoardDocument(input: unknown): BoardDocument;
|
|
|
1268
1379
|
/** Keep only the connections whose endpoints both exist in `items`. */
|
|
1269
1380
|
declare function withResolvedConnections(document: BoardDocument): BoardDocument;
|
|
1270
1381
|
declare function isUnknownItem(item: BoardItem): item is BoardUnknownItem;
|
|
1271
|
-
declare function isMediaItem(item: BoardItem): item is BoardImageItem | BoardVideoItem;
|
|
1272
|
-
/** Whether an item references a workspace file (
|
|
1273
|
-
declare function isFileBackedItem(item: BoardItem): item is BoardImageItem | BoardVideoItem | BoardFileItem;
|
|
1382
|
+
declare function isMediaItem(item: BoardItem): item is BoardImageItem | BoardVideoItem | BoardAudioItem;
|
|
1383
|
+
/** Whether an item references a workspace file (media or file card). */
|
|
1384
|
+
declare function isFileBackedItem(item: BoardItem): item is BoardImageItem | BoardVideoItem | BoardAudioItem | BoardFileItem;
|
|
1274
1385
|
//#endregion
|
|
1275
|
-
export { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardAppearance, BoardAppearanceSchema, BoardArrowItem, BoardArrowItemSchema, BoardDocument, BoardDocumentSchema, BoardDrawItem, BoardDrawItemSchema, BoardFileItem, BoardFileItemSchema, BoardFileSnapshot, BoardFileSnapshotSchema, BoardFrame, BoardFrameItem, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItem, BoardGeoItemSchema, BoardImageItem, BoardImageItemSchema, BoardItem, BoardItemSchema, BoardItemStyle, BoardItemStyleSchema, BoardKnownItem, BoardMediaSnapshot, BoardMediaSnapshotSchema, BoardPoint, BoardPointSchema, BoardTaskItem, BoardTaskItemSchema, BoardTaskOutput, BoardTaskOutputSchema, BoardTaskSnapshot, BoardTaskSnapshotSchema, BoardTextItem, BoardTextItemSchema, BoardUnknownItem, BoardVideoItem, BoardVideoItemSchema, BoardViewport, BoardViewportSchema, DrawPoint, DrawPointSchema, KNOWN_BOARD_ITEM_TYPES, KnownBoardItemType, SpaceFileRef, SpaceFileRefSchema, UNKNOWN_BOARD_ITEM_TYPE, isFileBackedItem, isMediaItem, isUnknownItem, parseBoardDocument, parseBoardItemLoose, unknownRealType, withResolvedConnections };
|
|
1386
|
+
export { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardAppearance, BoardAppearanceSchema, BoardArrowItem, BoardArrowItemSchema, BoardAudioItem, BoardAudioItemSchema, BoardDocument, BoardDocumentSchema, BoardDrawItem, BoardDrawItemSchema, BoardFileItem, BoardFileItemSchema, BoardFileSnapshot, BoardFileSnapshotSchema, BoardFrame, BoardFrameItem, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItem, BoardGeoItemSchema, BoardImageItem, BoardImageItemSchema, BoardItem, BoardItemSchema, BoardItemStyle, BoardItemStyleSchema, BoardKnownItem, BoardMediaSnapshot, BoardMediaSnapshotSchema, BoardPoint, BoardPointSchema, BoardTaskItem, BoardTaskItemSchema, BoardTaskOutput, BoardTaskOutputSchema, BoardTaskSnapshot, BoardTaskSnapshotSchema, BoardTextItem, BoardTextItemSchema, BoardUnknownItem, BoardVideoItem, BoardVideoItemSchema, BoardViewport, BoardViewportSchema, DrawPoint, DrawPointSchema, KNOWN_BOARD_ITEM_TYPES, KnownBoardItemType, SpaceFileRef, SpaceFileRefSchema, UNKNOWN_BOARD_ITEM_TYPE, isFileBackedItem, isMediaItem, isUnknownItem, parseBoardDocument, parseBoardItemLoose, unknownRealType, withResolvedConnections };
|
|
@@ -167,6 +167,12 @@ const BoardVideoItemSchema = BoardItemBaseSchema.extend({
|
|
|
167
167
|
ref: SpaceFileRefSchema,
|
|
168
168
|
snapshot: BoardMediaSnapshotSchema.optional()
|
|
169
169
|
});
|
|
170
|
+
/** Audio node — space file only. Playback state is local UI, never synced. */
|
|
171
|
+
const BoardAudioItemSchema = BoardItemBaseSchema.extend({
|
|
172
|
+
type: z.literal("audio"),
|
|
173
|
+
ref: SpaceFileRefSchema,
|
|
174
|
+
snapshot: BoardMediaSnapshotSchema.extend({ durationMs: z.number().finite().nonnegative().optional() }).optional()
|
|
175
|
+
});
|
|
170
176
|
/**
|
|
171
177
|
* Cached display facts for a file card.
|
|
172
178
|
*
|
|
@@ -251,6 +257,7 @@ const BoardTaskItemSchema = BoardItemBaseSchema.extend({
|
|
|
251
257
|
const KNOWN_BOARD_ITEM_TYPES = [
|
|
252
258
|
"image",
|
|
253
259
|
"video",
|
|
260
|
+
"audio",
|
|
254
261
|
"file",
|
|
255
262
|
"task",
|
|
256
263
|
"text",
|
|
@@ -288,6 +295,10 @@ function parseBoardItemLoose(raw) {
|
|
|
288
295
|
const parsed = BoardVideoItemSchema.safeParse(raw);
|
|
289
296
|
return parsed.success ? parsed.data : makeUnknownItem(raw);
|
|
290
297
|
}
|
|
298
|
+
case "audio": {
|
|
299
|
+
const parsed = BoardAudioItemSchema.safeParse(raw);
|
|
300
|
+
return parsed.success ? parsed.data : makeUnknownItem(raw);
|
|
301
|
+
}
|
|
291
302
|
case "file": {
|
|
292
303
|
const parsed = BoardFileItemSchema.safeParse(raw);
|
|
293
304
|
return parsed.success ? parsed.data : makeUnknownItem(raw);
|
|
@@ -396,11 +407,11 @@ function isUnknownItem(item) {
|
|
|
396
407
|
return item.type === UNKNOWN_BOARD_ITEM_TYPE;
|
|
397
408
|
}
|
|
398
409
|
function isMediaItem(item) {
|
|
399
|
-
return item.type === "image" || item.type === "video";
|
|
410
|
+
return item.type === "image" || item.type === "video" || item.type === "audio";
|
|
400
411
|
}
|
|
401
|
-
/** Whether an item references a workspace file (
|
|
412
|
+
/** Whether an item references a workspace file (media or file card). */
|
|
402
413
|
function isFileBackedItem(item) {
|
|
403
|
-
return item.type === "image" || item.type === "video" || item.type === "file";
|
|
414
|
+
return item.type === "image" || item.type === "video" || item.type === "audio" || item.type === "file";
|
|
404
415
|
}
|
|
405
416
|
//#endregion
|
|
406
|
-
export { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardAppearanceSchema, BoardArrowItemSchema, BoardDocumentSchema, BoardDrawItemSchema, BoardFileItemSchema, BoardFileSnapshotSchema, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItemSchema, BoardImageItemSchema, BoardItemSchema, BoardItemStyleSchema, BoardMediaSnapshotSchema, BoardPointSchema, BoardTaskItemSchema, BoardTaskOutputSchema, BoardTaskSnapshotSchema, BoardTextItemSchema, BoardVideoItemSchema, BoardViewportSchema, DrawPointSchema, KNOWN_BOARD_ITEM_TYPES, SpaceFileRefSchema, UNKNOWN_BOARD_ITEM_TYPE, isFileBackedItem, isMediaItem, isUnknownItem, parseBoardDocument, parseBoardItemLoose, unknownRealType, withResolvedConnections };
|
|
417
|
+
export { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardAppearanceSchema, BoardArrowItemSchema, BoardAudioItemSchema, BoardDocumentSchema, BoardDrawItemSchema, BoardFileItemSchema, BoardFileSnapshotSchema, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItemSchema, BoardImageItemSchema, BoardItemSchema, BoardItemStyleSchema, BoardMediaSnapshotSchema, BoardPointSchema, BoardTaskItemSchema, BoardTaskOutputSchema, BoardTaskSnapshotSchema, BoardTextItemSchema, BoardVideoItemSchema, BoardViewportSchema, DrawPointSchema, KNOWN_BOARD_ITEM_TYPES, SpaceFileRefSchema, UNKNOWN_BOARD_ITEM_TYPE, isFileBackedItem, isMediaItem, isUnknownItem, parseBoardDocument, parseBoardItemLoose, unknownRealType, withResolvedConnections };
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { BoardCapability, BoardRenderCost } from "./protocol/dist/board-constants.js";
|
|
2
|
+
import { BoardAssetRef, BoardClip, BoardDiagnostic, BoardEffect, BoardManifest, BoardNodeInput, BoardNodeRecord, BoardRecord, BoardSequence, BoardTarget, BoardValidationResult } from "./protocol/dist/board.js";
|
|
3
|
+
import "./protocol/dist/index.js";
|
|
4
|
+
//#region src/types.d.ts
|
|
5
|
+
type UserProfile = {
|
|
6
|
+
userUuid: string;
|
|
7
|
+
logtoUserId?: string;
|
|
8
|
+
username: string | null;
|
|
9
|
+
displayName: string;
|
|
10
|
+
avatarUrl: string | null;
|
|
11
|
+
syncedAt?: string;
|
|
12
|
+
};
|
|
13
|
+
type TaskRunRecord = {
|
|
14
|
+
id: string;
|
|
15
|
+
jobId: string;
|
|
16
|
+
cronJobId: string | null;
|
|
17
|
+
taskType: string;
|
|
18
|
+
status: "pending" | "running" | "completed" | "failed";
|
|
19
|
+
payload: unknown;
|
|
20
|
+
result: unknown;
|
|
21
|
+
errorMessage: string | null;
|
|
22
|
+
attemptCount: number;
|
|
23
|
+
spaceId: string | null;
|
|
24
|
+
sessionId: string | null;
|
|
25
|
+
turnId: string | null;
|
|
26
|
+
userUuid: string | null;
|
|
27
|
+
userProfile?: UserProfile;
|
|
28
|
+
scheduledAt: string | null;
|
|
29
|
+
startedAt: string | null;
|
|
30
|
+
finishedAt: string | null;
|
|
31
|
+
createdAt: string;
|
|
32
|
+
updatedAt: string;
|
|
33
|
+
};
|
|
34
|
+
//#endregion
|
|
35
|
+
export { TaskRunRecord, UserProfile };
|