@neta-art/cohub 8.5.0 → 8.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -339,4 +339,4 @@ viewer a single seat instead.
339
339
 
340
340
  For the complete API-to-scope mapping, initialization recipe, capability
341
341
  recipes, a full working example, and a pitfalls checklist, see the
342
- **[App Runtime Guide](./docs/work-runtime-guide.md)**.
342
+ **[App Runtime Guide](./docs/app-runtime-guide.md)**.
@@ -12,14 +12,31 @@ declare function computeDrawBounds(points: DrawPoint[], size: number): Rect;
12
12
  */
13
13
  declare function simplifyDrawIndices(points: DrawPoint[], tolerance: number): number[];
14
14
  /**
15
- * Build a closed, pressure-sensitive outline suitable for a filled Pixi polygon.
16
- * The raw samples remain authoritative; the outline is derived with rounded caps
17
- * and joins that stay stable through sharp turns and self-intersections.
15
+ * Build the legacy closed outline used by exports and callers that need a path.
16
+ * Interactive Board rendering uses `buildStrokeRibbonGeometry` below instead:
17
+ * filling one outline is unsafe when a freehand path folds back over itself.
18
18
  */
19
19
  declare function buildStrokeOutline(points: DrawPoint[], size: number): Array<{
20
20
  x: number;
21
21
  y: number;
22
22
  }>;
23
+ /** Whether a sample needs a round join rather than the neighboring segment caps. */
24
+ declare function isStrokeCorner(points: readonly DrawPoint[], index: number): boolean;
25
+ type StrokeRibbonGeometry = {
26
+ positions: Float32Array;
27
+ indices: Uint32Array;
28
+ uvs: Float32Array;
29
+ /** Normalized distance along the centerline for reveal animations. */
30
+ progress: Float32Array;
31
+ };
32
+ /**
33
+ * Tessellate a freehand stroke as independent, convex primitives.
34
+ *
35
+ * A whole-path polygon is deliberately avoided: a path that folds back can make
36
+ * its outline self-intersect, and GPU polygon triangulation then creates a large
37
+ * accidental fill. Segment quads plus round point joins overlap safely instead.
38
+ */
39
+ declare function buildStrokeRibbonGeometry(points: readonly DrawPoint[], size: number): StrokeRibbonGeometry;
23
40
  /**
24
41
  * Distance from a world point to the stroke's polyline, in the shape's local
25
42
  * space. Used for hit testing: a hit registers within half the stroke width plus
@@ -27,4 +44,4 @@ declare function buildStrokeOutline(points: DrawPoint[], size: number): Array<{
27
44
  */
28
45
  declare function distanceToStroke(points: DrawPoint[], local: WorldPoint): number;
29
46
  //#endregion
30
- export { buildStrokeOutline, computeDrawBounds, distanceToStroke, sampleRadius, simplifyDrawIndices };
47
+ export { StrokeRibbonGeometry, buildStrokeOutline, buildStrokeRibbonGeometry, computeDrawBounds, distanceToStroke, isStrokeCorner, sampleRadius, simplifyDrawIndices };
@@ -81,9 +81,9 @@ function perpendicularDistance(point, a, b) {
81
81
  return Math.hypot(point.x - projX, point.y - projY);
82
82
  }
83
83
  /**
84
- * Build a closed, pressure-sensitive outline suitable for a filled Pixi polygon.
85
- * The raw samples remain authoritative; the outline is derived with rounded caps
86
- * and joins that stay stable through sharp turns and self-intersections.
84
+ * Build the legacy closed outline used by exports and callers that need a path.
85
+ * Interactive Board rendering uses `buildStrokeRibbonGeometry` below instead:
86
+ * filling one outline is unsafe when a freehand path folds back over itself.
87
87
  */
88
88
  function buildStrokeOutline(points, size) {
89
89
  const n = points.length;
@@ -147,6 +147,95 @@ function buildStrokeOutline(points, size) {
147
147
  y
148
148
  }));
149
149
  }
150
+ const RIBBON_CIRCLE_SIDES = 8;
151
+ /** Whether a sample needs a round join rather than the neighboring segment caps. */
152
+ function isStrokeCorner(points, index) {
153
+ if (index === 0 || index === points.length - 1) return true;
154
+ const before = points[index - 1];
155
+ const point = points[index];
156
+ const after = points[index + 1];
157
+ if (!before || !point || !after) return false;
158
+ const ax = point.x - before.x;
159
+ const ay = point.y - before.y;
160
+ const bx = after.x - point.x;
161
+ const by = after.y - point.y;
162
+ const aLength = Math.hypot(ax, ay);
163
+ const bLength = Math.hypot(bx, by);
164
+ if (aLength < 1e-6 || bLength < 1e-6) return true;
165
+ return (ax * bx + ay * by) / (aLength * bLength) < .92;
166
+ }
167
+ /**
168
+ * Tessellate a freehand stroke as independent, convex primitives.
169
+ *
170
+ * A whole-path polygon is deliberately avoided: a path that folds back can make
171
+ * its outline self-intersect, and GPU polygon triangulation then creates a large
172
+ * accidental fill. Segment quads plus round point joins overlap safely instead.
173
+ */
174
+ function buildStrokeRibbonGeometry(points, size) {
175
+ const positions = [];
176
+ const indices = [];
177
+ const uvs = [];
178
+ const progress = [];
179
+ if (points.length === 0) return {
180
+ positions: /* @__PURE__ */ new Float32Array(),
181
+ indices: /* @__PURE__ */ new Uint32Array(),
182
+ uvs: /* @__PURE__ */ new Float32Array(),
183
+ progress: /* @__PURE__ */ new Float32Array()
184
+ };
185
+ const lengths = new Array(points.length).fill(0);
186
+ for (let i = 1; i < points.length; i += 1) {
187
+ const from = points[i - 1];
188
+ const to = points[i];
189
+ if (from && to) lengths[i] = (lengths[i - 1] ?? 0) + Math.hypot(to.x - from.x, to.y - from.y);
190
+ }
191
+ const total = Math.max(lengths.at(-1) ?? 0, 1e-6);
192
+ const addVertex = (x, y, at) => {
193
+ const normalized = at / total;
194
+ positions.push(x, y);
195
+ uvs.push(normalized, 0);
196
+ progress.push(normalized);
197
+ return positions.length / 2 - 1;
198
+ };
199
+ const addTriangle = (a, b, c) => indices.push(a, b, c);
200
+ const addRoundPoint = (point, at) => {
201
+ const radius = sampleRadius(size, point.p);
202
+ const center = addVertex(point.x, point.y, at);
203
+ const circle = [];
204
+ for (let side = 0; side < RIBBON_CIRCLE_SIDES; side += 1) {
205
+ const angle = side / RIBBON_CIRCLE_SIDES * Math.PI * 2;
206
+ circle.push(addVertex(point.x + Math.cos(angle) * radius, point.y + Math.sin(angle) * radius, at));
207
+ }
208
+ for (let side = 0; side < RIBBON_CIRCLE_SIDES; side += 1) addTriangle(center, circle[side], circle[(side + 1) % RIBBON_CIRCLE_SIDES]);
209
+ };
210
+ for (let i = 0; i < points.length; i += 1) {
211
+ const point = points[i];
212
+ if (!point) continue;
213
+ if (isStrokeCorner(points, i)) addRoundPoint(point, lengths[i] ?? 0);
214
+ if (i === points.length - 1) continue;
215
+ const next = points[i + 1];
216
+ if (!next) continue;
217
+ const dx = next.x - point.x;
218
+ const dy = next.y - point.y;
219
+ const length = Math.hypot(dx, dy);
220
+ if (length < 1e-6) continue;
221
+ const normalX = -dy / length;
222
+ const normalY = dx / length;
223
+ const radius = sampleRadius(size, point.p);
224
+ const leftA = addVertex(point.x + normalX * radius, point.y + normalY * radius, lengths[i] ?? 0);
225
+ const rightA = addVertex(point.x - normalX * radius, point.y - normalY * radius, lengths[i] ?? 0);
226
+ const nextRadius = sampleRadius(size, next.p);
227
+ const leftB = addVertex(next.x + normalX * nextRadius, next.y + normalY * nextRadius, lengths[i + 1] ?? 0);
228
+ const rightB = addVertex(next.x - normalX * nextRadius, next.y - normalY * nextRadius, lengths[i + 1] ?? 0);
229
+ addTriangle(leftA, rightA, leftB);
230
+ addTriangle(rightA, rightB, leftB);
231
+ }
232
+ return {
233
+ positions: new Float32Array(positions),
234
+ indices: new Uint32Array(indices),
235
+ uvs: new Float32Array(uvs),
236
+ progress: new Float32Array(progress)
237
+ };
238
+ }
150
239
  /**
151
240
  * Distance from a world point to the stroke's polyline, in the shape's local
152
241
  * space. Used for hit testing: a hit registers within half the stroke width plus
@@ -172,4 +261,4 @@ function distanceToStroke(points, local) {
172
261
  return min;
173
262
  }
174
263
  //#endregion
175
- export { buildStrokeOutline, computeDrawBounds, distanceToStroke, sampleRadius, simplifyDrawIndices };
264
+ export { buildStrokeOutline, buildStrokeRibbonGeometry, computeDrawBounds, distanceToStroke, isStrokeCorner, sampleRadius, simplifyDrawIndices };
@@ -19,7 +19,7 @@
19
19
  * snapshot rides along in every board transaction — so this stays small. */
20
20
  const FILE_EXCERPT_MAX_CHARS = 480;
21
21
  /** Files above this size are shown as `blank`; we never pull them for a preview. */
22
- const FILE_EXCERPT_MAX_BYTES = 256 * 1024;
22
+ const FILE_EXCERPT_MAX_BYTES = 262144;
23
23
  /** Frontmatter keys checked for a cover image, in precedence order. */
24
24
  const COVER_KEYS = [
25
25
  "cover",
@@ -409,9 +409,10 @@ function resizeFrame(frame, handle, pointer, minSize = 24, keepAspect = false) {
409
409
  let width = direction.x !== 0 ? clamp(direction.x * local.x, minSize, Number.POSITIVE_INFINITY) : rect.width;
410
410
  let height = direction.y !== 0 ? clamp(direction.y * local.y, minSize, Number.POSITIVE_INFINITY) : rect.height;
411
411
  if (keepAspect) {
412
- if (direction.x !== 0 && direction.y !== 0) if (Math.abs(width / aspect) > height) height = width / aspect;
413
- else width = height * aspect;
414
- else if (direction.x !== 0) height = width / aspect;
412
+ if (direction.x !== 0 && direction.y !== 0) {
413
+ if (Math.abs(width / aspect) > height) height = width / aspect;
414
+ else width = height * aspect;
415
+ } else if (direction.x !== 0) height = width / aspect;
415
416
  else if (direction.y !== 0) width = height * aspect;
416
417
  width = Math.max(minSize, width);
417
418
  height = Math.max(minSize, height);
@@ -10,7 +10,7 @@ import { BOARD_TASK_ARTIFACT_LIMIT, BoardAppearance, BoardAppearanceSchema, Boar
10
10
  import { BoardNormalizedPoint, BoardScreenOffset, BoardScreenPoint, BoardWorldOffset, BoardWorldPoint, BoardWorldRect, 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, cameraForFocus, cameraForRect, cameraForState, clamp, clampZoom, degToRad, expandRect, fitToContent, frameContainsPoint, frameCornerRotationHandleAt, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, handlePosition, itemBounds, normalizeRotation, normalizeViewport, normalizedPoint, panBy, pointToWorld, pointsBounds, radToDeg, rectCenter, rectContainsPoint, rectForCameraFocus, rectsIntersect, resizeFrame, resizeFrameToSize, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, scaleFrames, screenOffset, screenPoint, screenToWorld, selectionBounds, unionRects, visibleWorldRect, worldOffset, worldPoint, worldRect, worldToScreen, zoomAround } from "./geometry.js";
11
11
  import { ResolvedArrow, arrowBounds, arrowFrame, distanceToArrow, resolveArrow, sampleArrow, translateArrow } from "./core/arrow-geometry.js";
12
12
  import { CONNECTION_ENDPOINT_GAP, ConnectionIndex, FrameLookup, ResolvedConnection, ResolvedConnectionEndpoint, anchorPointOnFrame, anchorToWorld, autoConnectionSide, connectionArrowheads, connectionBounds, connectionHitTest, createConnectionIndex, distanceToConnection, pathMidpoint, resolveConnection, worldToAnchor } from "./core/connections.js";
13
- import { buildStrokeOutline, computeDrawBounds, distanceToStroke, sampleRadius, simplifyDrawIndices } from "./core/draw-geometry.js";
13
+ import { StrokeRibbonGeometry, buildStrokeOutline, buildStrokeRibbonGeometry, computeDrawBounds, distanceToStroke, isStrokeCorner, sampleRadius, simplifyDrawIndices } from "./core/draw-geometry.js";
14
14
  import { BOARD_EXPORT_MAX_TEXTURES, BoardExportAssetSelection, selectBoardExportAssets } from "./core/export-assets.js";
15
15
  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";
16
16
  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";
@@ -26,4 +26,4 @@ import { BoardAssetSource, BoardPlayableMedia, playableBoardMedia, playableBoard
26
26
  import { patchBoardAppearance } from "./mutation.js";
27
27
  import { applyBoardSemanticCommands, boardDocumentToSemanticCommands } from "./semantic-mutation.js";
28
28
  import { featuredTaskArtifact, rankedTaskArtifacts, taskArtifactPreviewUrl, taskArtifacts, taskRunToBoardTaskSnapshot } from "./task.js";
29
- export { AUTO_BOARD_CONNECTION_ANCHOR, type ArrowShapeProps, type AudioShapeProps, BOARD_CHANNELS, 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_REMOTE_URL_MAX_LENGTH, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BOARD_TASK_ARTIFACT_LIMIT, BoardAppearance, BoardAppearanceSchema, BoardArrowItem, BoardArrowItemSchema, BoardAssetSource, BoardAudioItem, BoardAudioItemSchema, type BoardCameraFocus, type BoardCameraFocusParams, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, type BoardCameraState, BoardCameraStateSchema, BoardColorEntry, type 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, BoardMediaKind, BoardMediaSnapshot, BoardMediaSnapshotSchema, BoardNormalizedPoint, BoardPlayableMedia, BoardPoint, BoardPointSchema, BoardPresetDefinition, BoardRelationSchema, BoardRemoteUrlSchema, BoardScreenOffset, BoardScreenPoint, BoardShapeColors, BoardStyledToolId, BoardTaskArtifact, BoardTaskArtifactSchema, BoardTaskItem, BoardTaskItemSchema, BoardTaskSnapshot, BoardTaskSnapshotSchema, BoardTextItem, BoardTextItemSchema, BoardToolStyleMap, BoardToolStylePatch, type BoardTrackInterpolation, BoardUnknownItem, BoardVideoItem, BoardVideoItemSchema, BoardViewport, BoardViewportSchema, BoardWorldOffset, BoardWorldPoint, BoardWorldRect, BuildSnapshotInput, CONNECTION_ENDPOINT_GAP, CORNER_RESIZE_HANDLES, CORNER_ROTATION_ZONE_WIDTH, CompositionInput, 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, type ImageShapeProps, KNOWN_BOARD_ITEM_TYPES, KnownBoardItemType, MAX_BOARD_ZOOM, MIN_BOARD_ZOOM, MIN_ITEM_SIZE, Point, ProceduralClipInput, QualityProfile, RESIZE_HANDLES, ROTATION_HANDLE_OFFSET, Rect, RenderBounds, ResizeHandle, ResolvedArrow, ResolvedConnection, ResolvedConnectionEndpoint, ResolvedCover, SampledTrack, 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, TrackInput, UNKNOWN_BOARD_ITEM_TYPE, VIEWPORT_MARGIN_RATIO, type VideoShapeProps, WorldPoint, anchorPointOnFrame, anchorToWorld, angleFromCenter, applyBoardAuthoringSnapshot, applyBoardSemanticCommands, arrowBounds, arrowFrame, autoConnectionSide, availabilityFromError, boardAuthoringItemToDocumentItem, boardAuthoringSnapshotToDocument, boardColorCssVar, boardDocumentToSemanticCommands, boardFrameLookup, boardImageKeySource, boardItemToAuthoringItem, boardTextLineHeight, buildFallbackShapeColors, buildFileExcerpt, buildFileSnapshot, buildStrokeOutline, cameraForFocus, cameraForRect, cameraForState, clamp, clampBoardStrokeSize, clampBoardTextFontSize, clampZoom, compileComposition, composition, computeDrawBounds, connectionArrowheads, connectionBounds, connectionHitTest, connectionItemIds, connectionOtherItemId, connectionTouchesItem, createBoardConnection, createBoardExtensionRegistry, createBoardToolStyles, createConnectionIndex, definitionForItem, degToRad, distanceToArrow, distanceToConnection, distanceToStroke, expandRect, exportConnectionBounds, exportItemBounds, featuredTaskArtifact, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, fitToContent, flipBoardConnection, formatFileSize, frameContainsPoint, frameCornerRotationHandleAt, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, getMediaExtension, getMediaResourceTitle, getShapeDefinition, handlePosition, imageAssetKey, inferBoardMediaKind, isBoardColorId, isBoardPath, isFileBackedItem, isFileSnapshotFresh, isGeoKind, isMediaItem, isPublicBoardRemoteAddress, isUnknownItem, itemBounds, measureBoardText, mergeFileSnapshot, normalizeBoardConnectionStyle, normalizeBoardDocument, normalizeBoardRemoteUrl, normalizeRotation, normalizeViewport, normalizedPoint, panBy, parseBoardDocument, parseBoardItemLoose, parseBoardManifest, patchBoardAppearance, pathMidpoint, pickBoardColor, planBoardExport, playableBoardMedia, playableBoardMediaList, pointToWorld, pointsBounds, proceduralClip, radToDeg, rankedTaskArtifacts, readCoverFromFrontmatter, readTitleFromFrontmatter, rectCenter, rectContainsPoint, rectForCameraFocus, rectsIntersect, registerShapeDefinition, resetBoardPlaybackUrlCache, resizeFrame, resizeFrameToSize, resizeModeForCapabilities, resolveArrow, resolveBoardColor, resolveConnection, resolveCoverRef, resolveSpacePath, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, sampleArrow, sampleCompositionTracks, sampleEasing, sampleRadius, sampleTrack, scaleFrames, screenOffset, screenPoint, screenToWorld, selectBoardExportAssets, selectionBounds, serializeBoardManifest, setBoardTextMeasurer, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, shouldFetchFileExcerpt, simplifyDrawIndices, splitFrontmatter, taskArtifactPreviewUrl, taskArtifacts, taskRunToBoardTaskSnapshot, track, translateArrow, unionRects, unknownRealType, unknownShapeDefinition, visibleWorldRect, withResolvedConnections, worldOffset, worldPoint, worldRect, worldToAnchor, worldToScreen, zoomAround };
29
+ export { AUTO_BOARD_CONNECTION_ANCHOR, type ArrowShapeProps, type AudioShapeProps, BOARD_CHANNELS, 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_REMOTE_URL_MAX_LENGTH, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BOARD_TASK_ARTIFACT_LIMIT, BoardAppearance, BoardAppearanceSchema, BoardArrowItem, BoardArrowItemSchema, BoardAssetSource, BoardAudioItem, BoardAudioItemSchema, type BoardCameraFocus, type BoardCameraFocusParams, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, type BoardCameraState, BoardCameraStateSchema, BoardColorEntry, type 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, BoardMediaKind, BoardMediaSnapshot, BoardMediaSnapshotSchema, BoardNormalizedPoint, BoardPlayableMedia, BoardPoint, BoardPointSchema, BoardPresetDefinition, BoardRelationSchema, BoardRemoteUrlSchema, BoardScreenOffset, BoardScreenPoint, BoardShapeColors, BoardStyledToolId, BoardTaskArtifact, BoardTaskArtifactSchema, BoardTaskItem, BoardTaskItemSchema, BoardTaskSnapshot, BoardTaskSnapshotSchema, BoardTextItem, BoardTextItemSchema, BoardToolStyleMap, BoardToolStylePatch, type BoardTrackInterpolation, BoardUnknownItem, BoardVideoItem, BoardVideoItemSchema, BoardViewport, BoardViewportSchema, BoardWorldOffset, BoardWorldPoint, BoardWorldRect, BuildSnapshotInput, CONNECTION_ENDPOINT_GAP, CORNER_RESIZE_HANDLES, CORNER_ROTATION_ZONE_WIDTH, CompositionInput, 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, type ImageShapeProps, KNOWN_BOARD_ITEM_TYPES, KnownBoardItemType, MAX_BOARD_ZOOM, MIN_BOARD_ZOOM, MIN_ITEM_SIZE, Point, ProceduralClipInput, QualityProfile, RESIZE_HANDLES, ROTATION_HANDLE_OFFSET, Rect, RenderBounds, ResizeHandle, ResolvedArrow, ResolvedConnection, ResolvedConnectionEndpoint, ResolvedCover, SampledTrack, ScreenPoint, type ShapeCapabilities, ShapeDefinition, type ShapeGeometry, type ShapeHandle, type ShapeHandleId, type ShapeResizeMode, Size, SpaceFileRef, SpaceFileRefSchema, StrokeRibbonGeometry, TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, type TextShapeProps, TrackInput, UNKNOWN_BOARD_ITEM_TYPE, VIEWPORT_MARGIN_RATIO, type VideoShapeProps, WorldPoint, anchorPointOnFrame, anchorToWorld, angleFromCenter, applyBoardAuthoringSnapshot, applyBoardSemanticCommands, arrowBounds, arrowFrame, autoConnectionSide, availabilityFromError, boardAuthoringItemToDocumentItem, boardAuthoringSnapshotToDocument, boardColorCssVar, boardDocumentToSemanticCommands, boardFrameLookup, boardImageKeySource, boardItemToAuthoringItem, boardTextLineHeight, buildFallbackShapeColors, buildFileExcerpt, buildFileSnapshot, buildStrokeOutline, buildStrokeRibbonGeometry, cameraForFocus, cameraForRect, cameraForState, clamp, clampBoardStrokeSize, clampBoardTextFontSize, clampZoom, compileComposition, composition, computeDrawBounds, connectionArrowheads, connectionBounds, connectionHitTest, connectionItemIds, connectionOtherItemId, connectionTouchesItem, createBoardConnection, createBoardExtensionRegistry, createBoardToolStyles, createConnectionIndex, definitionForItem, degToRad, distanceToArrow, distanceToConnection, distanceToStroke, expandRect, exportConnectionBounds, exportItemBounds, featuredTaskArtifact, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, fitToContent, flipBoardConnection, formatFileSize, frameContainsPoint, frameCornerRotationHandleAt, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, getMediaExtension, getMediaResourceTitle, getShapeDefinition, handlePosition, imageAssetKey, inferBoardMediaKind, isBoardColorId, isBoardPath, isFileBackedItem, isFileSnapshotFresh, isGeoKind, isMediaItem, isPublicBoardRemoteAddress, isStrokeCorner, isUnknownItem, itemBounds, measureBoardText, mergeFileSnapshot, normalizeBoardConnectionStyle, normalizeBoardDocument, normalizeBoardRemoteUrl, normalizeRotation, normalizeViewport, normalizedPoint, panBy, parseBoardDocument, parseBoardItemLoose, parseBoardManifest, patchBoardAppearance, pathMidpoint, pickBoardColor, planBoardExport, playableBoardMedia, playableBoardMediaList, pointToWorld, pointsBounds, proceduralClip, radToDeg, rankedTaskArtifacts, readCoverFromFrontmatter, readTitleFromFrontmatter, rectCenter, rectContainsPoint, rectForCameraFocus, rectsIntersect, registerShapeDefinition, resetBoardPlaybackUrlCache, resizeFrame, resizeFrameToSize, resizeModeForCapabilities, resolveArrow, resolveBoardColor, resolveConnection, resolveCoverRef, resolveSpacePath, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, sampleArrow, sampleCompositionTracks, sampleEasing, sampleRadius, sampleTrack, scaleFrames, screenOffset, screenPoint, screenToWorld, selectBoardExportAssets, selectionBounds, serializeBoardManifest, setBoardTextMeasurer, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, shouldFetchFileExcerpt, simplifyDrawIndices, splitFrontmatter, taskArtifactPreviewUrl, taskArtifacts, taskRunToBoardTaskSnapshot, track, translateArrow, unionRects, unknownRealType, unknownShapeDefinition, visibleWorldRect, withResolvedConnections, worldOffset, worldPoint, worldRect, worldToAnchor, worldToScreen, zoomAround };
@@ -10,7 +10,7 @@ import { boardImageKeySource, imageAssetKey } from "./image-key.js";
10
10
  import { DEFAULT_BOARD_APPEARANCE, applyBoardAuthoringSnapshot, boardAuthoringItemToDocumentItem, boardAuthoringSnapshotToDocument, boardItemToAuthoringItem } from "./semantic-document.js";
11
11
  import { arrowBounds, arrowFrame, distanceToArrow, resolveArrow, sampleArrow, translateArrow } from "./core/arrow-geometry.js";
12
12
  import { CONNECTION_ENDPOINT_GAP, anchorPointOnFrame, anchorToWorld, autoConnectionSide, connectionArrowheads, connectionBounds, connectionHitTest, createConnectionIndex, distanceToConnection, pathMidpoint, resolveConnection, worldToAnchor } from "./core/connections.js";
13
- import { buildStrokeOutline, computeDrawBounds, distanceToStroke, sampleRadius, simplifyDrawIndices } from "./core/draw-geometry.js";
13
+ import { buildStrokeOutline, buildStrokeRibbonGeometry, computeDrawBounds, distanceToStroke, isStrokeCorner, sampleRadius, simplifyDrawIndices } from "./core/draw-geometry.js";
14
14
  import { BOARD_EXPORT_MAX_TEXTURES, selectBoardExportAssets } from "./core/export-assets.js";
15
15
  import { BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, boardFrameLookup, exportConnectionBounds, exportItemBounds, normalizeBoardDocument, planBoardExport } from "./core/export-plan.js";
16
16
  import { FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, availabilityFromError, buildFileExcerpt, buildFileSnapshot, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, formatFileSize, isFileSnapshotFresh, mergeFileSnapshot, readCoverFromFrontmatter, readTitleFromFrontmatter, resolveCoverRef, resolveSpacePath, shouldFetchFileExcerpt, splitFrontmatter } from "./core/file-preview.js";
@@ -23,4 +23,4 @@ import { getMediaExtension, getMediaResourceTitle, inferBoardMediaKind } from ".
23
23
  import { playableBoardMedia, playableBoardMediaList, resetBoardPlaybackUrlCache } from "./media-playback.js";
24
24
  import { patchBoardAppearance } from "./mutation.js";
25
25
  import { applyBoardSemanticCommands, boardDocumentToSemanticCommands } from "./semantic-mutation.js";
26
- export { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CHANNELS, 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_REMOTE_URL_MAX_LENGTH, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BOARD_TASK_ARTIFACT_LIMIT, BoardAppearanceSchema, BoardArrowItemSchema, BoardAudioItemSchema, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraStateSchema, BoardConnectionAnchorSchema, BoardConnectionEndpointSchema, BoardConnectionPatchSchema, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardDocumentSchema, BoardDrawItemSchema, BoardExtensionRegistry, BoardFileItemSchema, BoardFileSnapshotSchema, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItemSchema, BoardImageItemSchema, BoardItemSchema, BoardItemStyleSchema, BoardMediaSnapshotSchema, BoardPointSchema, BoardRelationSchema, BoardRemoteUrlSchema, BoardTaskArtifactSchema, BoardTaskItemSchema, 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, 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, applyBoardAuthoringSnapshot, applyBoardSemanticCommands, arrowBounds, arrowFrame, autoConnectionSide, availabilityFromError, boardAuthoringItemToDocumentItem, boardAuthoringSnapshotToDocument, boardColorCssVar, boardDocumentToSemanticCommands, boardFrameLookup, boardImageKeySource, boardItemToAuthoringItem, boardTextLineHeight, buildFallbackShapeColors, buildFileExcerpt, buildFileSnapshot, buildStrokeOutline, cameraForFocus, cameraForRect, cameraForState, clamp, clampBoardStrokeSize, clampBoardTextFontSize, clampZoom, compileComposition, composition, computeDrawBounds, connectionArrowheads, connectionBounds, connectionHitTest, connectionItemIds, connectionOtherItemId, connectionTouchesItem, createBoardConnection, createBoardExtensionRegistry, createBoardToolStyles, createConnectionIndex, definitionForItem, degToRad, distanceToArrow, distanceToConnection, distanceToStroke, expandRect, exportConnectionBounds, exportItemBounds, featuredTaskArtifact, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, fitToContent, flipBoardConnection, formatFileSize, frameContainsPoint, frameCornerRotationHandleAt, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, getMediaExtension, getMediaResourceTitle, getShapeDefinition, handlePosition, imageAssetKey, inferBoardMediaKind, isBoardColorId, isBoardPath, isFileBackedItem, isFileSnapshotFresh, isGeoKind, isMediaItem, isPublicBoardRemoteAddress, isUnknownItem, itemBounds, measureBoardText, mergeFileSnapshot, normalizeBoardConnectionStyle, normalizeBoardDocument, normalizeBoardRemoteUrl, normalizeRotation, normalizeViewport, normalizedPoint, panBy, parseBoardDocument, parseBoardItemLoose, parseBoardManifest, patchBoardAppearance, pathMidpoint, pickBoardColor, planBoardExport, playableBoardMedia, playableBoardMediaList, pointToWorld, pointsBounds, proceduralClip, radToDeg, rankedTaskArtifacts, readCoverFromFrontmatter, readTitleFromFrontmatter, rectCenter, rectContainsPoint, rectForCameraFocus, rectsIntersect, registerShapeDefinition, resetBoardPlaybackUrlCache, resizeFrame, resizeFrameToSize, resizeModeForCapabilities, resolveArrow, resolveBoardColor, resolveConnection, resolveCoverRef, resolveSpacePath, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, sampleArrow, sampleCompositionTracks, sampleEasing, sampleRadius, sampleTrack, scaleFrames, screenOffset, screenPoint, screenToWorld, selectBoardExportAssets, selectionBounds, serializeBoardManifest, setBoardTextMeasurer, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, shouldFetchFileExcerpt, simplifyDrawIndices, splitFrontmatter, taskArtifactPreviewUrl, taskArtifacts, taskRunToBoardTaskSnapshot, track, translateArrow, unionRects, unknownRealType, unknownShapeDefinition, visibleWorldRect, withResolvedConnections, worldOffset, worldPoint, worldRect, worldToAnchor, worldToScreen, zoomAround };
26
+ export { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CHANNELS, 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_REMOTE_URL_MAX_LENGTH, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BOARD_TASK_ARTIFACT_LIMIT, BoardAppearanceSchema, BoardArrowItemSchema, BoardAudioItemSchema, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraStateSchema, BoardConnectionAnchorSchema, BoardConnectionEndpointSchema, BoardConnectionPatchSchema, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardDocumentSchema, BoardDrawItemSchema, BoardExtensionRegistry, BoardFileItemSchema, BoardFileSnapshotSchema, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItemSchema, BoardImageItemSchema, BoardItemSchema, BoardItemStyleSchema, BoardMediaSnapshotSchema, BoardPointSchema, BoardRelationSchema, BoardRemoteUrlSchema, BoardTaskArtifactSchema, BoardTaskItemSchema, 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, 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, applyBoardAuthoringSnapshot, applyBoardSemanticCommands, arrowBounds, arrowFrame, autoConnectionSide, availabilityFromError, boardAuthoringItemToDocumentItem, boardAuthoringSnapshotToDocument, boardColorCssVar, boardDocumentToSemanticCommands, boardFrameLookup, boardImageKeySource, boardItemToAuthoringItem, boardTextLineHeight, buildFallbackShapeColors, buildFileExcerpt, buildFileSnapshot, buildStrokeOutline, buildStrokeRibbonGeometry, cameraForFocus, cameraForRect, cameraForState, clamp, clampBoardStrokeSize, clampBoardTextFontSize, clampZoom, compileComposition, composition, computeDrawBounds, connectionArrowheads, connectionBounds, connectionHitTest, connectionItemIds, connectionOtherItemId, connectionTouchesItem, createBoardConnection, createBoardExtensionRegistry, createBoardToolStyles, createConnectionIndex, definitionForItem, degToRad, distanceToArrow, distanceToConnection, distanceToStroke, expandRect, exportConnectionBounds, exportItemBounds, featuredTaskArtifact, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, fitToContent, flipBoardConnection, formatFileSize, frameContainsPoint, frameCornerRotationHandleAt, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, getMediaExtension, getMediaResourceTitle, getShapeDefinition, handlePosition, imageAssetKey, inferBoardMediaKind, isBoardColorId, isBoardPath, isFileBackedItem, isFileSnapshotFresh, isGeoKind, isMediaItem, isPublicBoardRemoteAddress, isStrokeCorner, isUnknownItem, itemBounds, measureBoardText, mergeFileSnapshot, normalizeBoardConnectionStyle, normalizeBoardDocument, normalizeBoardRemoteUrl, normalizeRotation, normalizeViewport, normalizedPoint, panBy, parseBoardDocument, parseBoardItemLoose, parseBoardManifest, patchBoardAppearance, pathMidpoint, pickBoardColor, planBoardExport, playableBoardMedia, playableBoardMediaList, pointToWorld, pointsBounds, proceduralClip, radToDeg, rankedTaskArtifacts, readCoverFromFrontmatter, readTitleFromFrontmatter, rectCenter, rectContainsPoint, rectForCameraFocus, rectsIntersect, registerShapeDefinition, resetBoardPlaybackUrlCache, resizeFrame, resizeFrameToSize, resizeModeForCapabilities, resolveArrow, resolveBoardColor, resolveConnection, resolveCoverRef, resolveSpacePath, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, sampleArrow, sampleCompositionTracks, sampleEasing, sampleRadius, sampleTrack, scaleFrames, screenOffset, screenPoint, screenToWorld, selectBoardExportAssets, selectionBounds, serializeBoardManifest, setBoardTextMeasurer, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, shouldFetchFileExcerpt, simplifyDrawIndices, splitFrontmatter, taskArtifactPreviewUrl, taskArtifacts, taskRunToBoardTaskSnapshot, track, translateArrow, unionRects, unknownRealType, unknownShapeDefinition, visibleWorldRect, withResolvedConnections, worldOffset, worldPoint, worldRect, worldToAnchor, worldToScreen, zoomAround };
@@ -1,8 +1,8 @@
1
- import { buildStrokeOutline, computeDrawBounds } from "../../core/draw-geometry.js";
1
+ import { buildStrokeRibbonGeometry, computeDrawBounds } from "../../core/draw-geometry.js";
2
2
  import { pickBoardColor } from "../../core/palette.js";
3
3
  import { positionShell } from "./base-card-renderer.js";
4
4
  import { drawFarStroke } from "./far-plate.js";
5
- import { Container, Graphics } from "pixi.js";
5
+ import { Container, Mesh, MeshGeometry, Texture } from "pixi.js";
6
6
  //#region src/board/render/renderers/draw-card-renderer.ts
7
7
  const partsByContainer = /* @__PURE__ */ new WeakMap();
8
8
  function sync(container, item, context) {
@@ -25,21 +25,22 @@ function sync(container, item, context) {
25
25
  parts.sig = sig;
26
26
  parts.points = item.points;
27
27
  parts.baseWidth = computeDrawBounds(item.points, item.size).width;
28
- parts.stroke.clear();
29
- const outline = buildStrokeOutline(item.points, item.size);
30
- const origin = outline[0];
31
- if (origin && outline.length >= 3) {
32
- parts.stroke.moveTo(origin.x, origin.y);
33
- for (let i = 1; i < outline.length; i += 1) {
34
- const point = outline[i];
35
- if (point) parts.stroke.lineTo(point.x, point.y);
36
- }
37
- parts.stroke.closePath();
38
- parts.stroke.fill({
39
- color: color.stroke,
40
- alpha: selected || hovered ? 1 : .92
41
- });
42
- }
28
+ const ribbon = buildStrokeRibbonGeometry(item.points, item.size);
29
+ const geometry = new MeshGeometry({
30
+ positions: ribbon.positions,
31
+ indices: ribbon.indices
32
+ });
33
+ const nextStroke = new Mesh({
34
+ geometry,
35
+ texture: Texture.WHITE
36
+ });
37
+ nextStroke.tint = color.stroke;
38
+ nextStroke.alpha = selected || hovered ? 1 : .92;
39
+ const previous = parts.stroke;
40
+ parts.stroke = nextStroke;
41
+ parts.root.removeChild(previous);
42
+ previous.destroy({ children: true });
43
+ parts.root.addChild(nextStroke);
43
44
  }
44
45
  const previewScale = item.frame.width / Math.max(1e-4, parts.baseWidth);
45
46
  parts.stroke.scale.set(Number.isFinite(previewScale) ? previewScale : 1);
@@ -49,7 +50,13 @@ const drawCardRenderer = {
49
50
  canRender: (item) => item.type === "draw",
50
51
  create: (item, context) => {
51
52
  const root = new Container();
52
- const stroke = new Graphics();
53
+ const stroke = new Mesh({
54
+ geometry: new MeshGeometry({
55
+ positions: /* @__PURE__ */ new Float32Array(),
56
+ indices: /* @__PURE__ */ new Uint32Array()
57
+ }),
58
+ texture: Texture.WHITE
59
+ });
53
60
  root.addChild(stroke);
54
61
  partsByContainer.set(root, {
55
62
  root,
@@ -228,7 +228,7 @@ function sync(container, item, context) {
228
228
  if (detail === "plate") return;
229
229
  const title = item.snapshot?.title || fileBaseName(item.ref.path);
230
230
  const excerpt = item.snapshot?.excerpt ?? "";
231
- const innerWidth = Math.max(1, width - PADDING * 2);
231
+ const innerWidth = Math.max(1, width - 20);
232
232
  const textSig = [
233
233
  title,
234
234
  excerpt,
@@ -6,7 +6,6 @@ import { drawFarPlate } from "./far-plate.js";
6
6
  import { Container, Graphics, Text } from "pixi.js";
7
7
  //#region src/board/render/renderers/geo-card-renderer.ts
8
8
  const RADIUS = 8;
9
- const LABEL_PADDING = 8;
10
9
  const partsByContainer = /* @__PURE__ */ new WeakMap();
11
10
  function traceOutline(graphics, geo, width, height) {
12
11
  switch (geo) {
@@ -68,7 +67,7 @@ function sync(container, item, context) {
68
67
  parts.label.visible = item.text.length > 0;
69
68
  parts.label.style.fill = color.label;
70
69
  }
71
- syncTextWrapWidth(parts.label, parts, Math.max(1, width - LABEL_PADDING * 2), resizing);
70
+ syncTextWrapWidth(parts.label, parts, Math.max(1, width - 16), resizing);
72
71
  parts.label.position.set(width / 2, height / 2);
73
72
  }
74
73
  const geoCardRenderer = {
@@ -141,12 +141,11 @@ function drawStateMark(graphics, surface, cx, cy, color) {
141
141
  }
142
142
  function drawFailedBadge(graphics, width, color, context) {
143
143
  const cx = Math.max(12, width - 12);
144
- const cy = 12;
145
- graphics.circle(cx, cy, 8).fill({
144
+ graphics.circle(cx, 12, 8).fill({
146
145
  color: context.palette.bg,
147
146
  alpha: .72
148
147
  });
149
- graphics.moveTo(cx - 2.5, cy - 2.5).lineTo(cx + 2.5, 14.5).moveTo(cx + 2.5, cy - 2.5).lineTo(cx - 2.5, 14.5).stroke({
148
+ graphics.moveTo(cx - 2.5, 9.5).lineTo(cx + 2.5, 14.5).moveTo(cx + 2.5, 9.5).lineTo(cx - 2.5, 14.5).stroke({
150
149
  color,
151
150
  width: 1.5,
152
151
  alpha: .96,
@@ -214,7 +213,7 @@ function sync(container, item, context) {
214
213
  width: selected ? 2 : 1,
215
214
  alpha: selected ? .96 : .82
216
215
  });
217
- parts.clip.clear().roundRect(1, 1, frame.width, frame.height, RADIUS - 1).fill({ color: 16777215 });
216
+ parts.clip.clear().roundRect(1, 1, frame.width, frame.height, 3).fill({ color: 16777215 });
218
217
  parts.previewBg.clear().rect(frame.x, frame.y, frame.width, frame.height).fill({
219
218
  color: context.palette.hover,
220
219
  alpha: .5
@@ -226,8 +225,8 @@ function sync(container, item, context) {
226
225
  drawAudioWaveform(parts.previewArt, item.taskRunId, {
227
226
  x: frame.x + PADDING,
228
227
  y: frame.y + PADDING,
229
- width: Math.max(1, frame.width - PADDING * 2),
230
- height: Math.max(1, frame.height - PADDING * 2 - bottomInset)
228
+ width: Math.max(1, frame.width - 24),
229
+ height: Math.max(1, frame.height - 24 - bottomInset)
231
230
  }, context.colors.brand.stroke);
232
231
  }
233
232
  if (full && (artifact?.type === "audio" || artifact?.type === "video" && texture)) drawPlayBadge(parts.previewArt, frame, context);
@@ -264,9 +263,9 @@ function sync(container, item, context) {
264
263
  if (textSig !== parts.textSig) {
265
264
  parts.textSig = textSig;
266
265
  parts.body.style.fill = surface === "failed" ? color : context.palette.text;
267
- fitTextToLines(parts.body, bodyText, kind === "text" ? Math.max(1, Math.floor((height - PADDING * 2 - (showMeta ? META_HEIGHT : 0)) / 16)) : 1, Math.max(24, width - PADDING * 2));
266
+ fitTextToLines(parts.body, bodyText, kind === "text" ? Math.max(1, Math.floor((height - 24 - (showMeta ? META_HEIGHT : 0)) / 16)) : 1, Math.max(24, width - 24));
268
267
  parts.meta.style.fill = context.palette.text;
269
- fitTextToLines(parts.meta, metaText, 1, Math.max(24, width - PADDING * 2));
268
+ fitTextToLines(parts.meta, metaText, 1, Math.max(24, width - 24));
270
269
  }
271
270
  parts.body.visible = full && Boolean(bodyText);
272
271
  parts.meta.visible = showMeta;
@@ -41,10 +41,11 @@ const textCardRenderer = {
41
41
  const root = new Container();
42
42
  const resolution = textResolutionForZoom(context.zoom);
43
43
  const color = pickBoardColor(context.colors, item.type === "text" ? item.color || "neutral" : "neutral", context.colorScheme);
44
+ const ink = item.type === "text" && (item.color === "neutral" || !item.color) ? context.palette.text : color.stroke;
44
45
  const body = new Text({
45
46
  text: "",
46
47
  style: {
47
- fill: item.type === "text" && (item.color === "neutral" || !item.color) ? context.palette.text : color.stroke,
48
+ fill: ink,
48
49
  fontFamily: BOARD_FONT_STACK,
49
50
  fontSize: TEXT_FONT_SIZE,
50
51
  fontWeight: "500",
@@ -40,7 +40,7 @@ function sync(container, item, context) {
40
40
  width: selected ? 2 : 1,
41
41
  alpha: .8
42
42
  });
43
- parts.box.roundRect(6, 6, width - 12, height - 12, RADIUS - 4).stroke({
43
+ parts.box.roundRect(6, 6, width - 12, height - 12, 6).stroke({
44
44
  color: context.palette.muted,
45
45
  width: 1,
46
46
  alpha: .4
@@ -24,7 +24,7 @@ function textZoomBucket(zoom) {
24
24
  /** Effective text resolution for a given camera zoom. */
25
25
  function textResolutionForZoom(zoom) {
26
26
  const bucket = textZoomBucket(zoom);
27
- return Math.min(getBoardResolution() * Math.max(1, bucket), MAX_BOARD_RESOLUTION * 3);
27
+ return Math.min(getBoardResolution() * Math.max(1, bucket), 6);
28
28
  }
29
29
  /** Update a Pixi text texture only when zoom crosses a resolution bucket. */
30
30
  function syncTextResolution(text, state, zoom) {
@@ -62,8 +62,9 @@ function sync(parts, context) {
62
62
  parts.sprite.destroy();
63
63
  previousTexture.destroy(true);
64
64
  }
65
+ const texture = buildGridTexture(context, size, palette.border, opacity, kind);
65
66
  parts.sprite = new TilingSprite({
66
- texture: buildGridTexture(context, size, palette.border, opacity, kind),
67
+ texture,
67
68
  width,
68
69
  height
69
70
  });
@@ -82,7 +82,7 @@ var CronJobsApi = class {
82
82
  //#endregion
83
83
  //#region src/apis/generations.ts
84
84
  const DEFAULT_INTERVAL_MS = 1500;
85
- const DEFAULT_TIMEOUT_MS = 1800 * 1e3;
85
+ const DEFAULT_TIMEOUT_MS = 18e5;
86
86
  function sleep$1(ms, signal) {
87
87
  if (signal?.aborted) return Promise.reject(signal.reason ?? /* @__PURE__ */ new Error("Generation wait aborted"));
88
88
  return new Promise((resolve, reject) => {
@@ -423,8 +423,8 @@ const DEFAULT_BOARD_RENDER_LIMITS = {
423
423
  drawCalls: 400,
424
424
  filterPasses: 24,
425
425
  renderTexturePixels: 16777216,
426
- textureBytes: 512 * 1024 * 1024,
427
- bufferBytes: 256 * 1024 * 1024,
426
+ textureBytes: 536870912,
427
+ bufferBytes: 268435456,
428
428
  simulationSteps: 1e5
429
429
  };
430
430
  const BOARD_BUILTIN_CLIP_KINDS = [
@@ -1287,11 +1287,11 @@ const NAVIGATION_ERROR_MESSAGE_MAX_LENGTH = 2e3;
1287
1287
  */
1288
1288
  const DESKTOP_COMMAND_VERSION = 1;
1289
1289
  /** Persisted and broadcast, so every field is capped; MAX_BYTES bounds the whole. */
1290
- const DESKTOP_COMMAND_PAYLOAD_MAX_BYTES = 32 * 1024;
1291
- const DESKTOP_COMMAND_MAX_BYTES = 40 * 1024;
1290
+ const DESKTOP_COMMAND_PAYLOAD_MAX_BYTES = 32768;
1291
+ const DESKTOP_COMMAND_MAX_BYTES = 40960;
1292
1292
  const DESKTOP_COMMAND_LAUNCH_MAX_LENGTH = NAVIGATION_LAUNCH_MAX_LENGTH;
1293
- const DESKTOP_COMMAND_DEFAULT_TIMEOUT_MS = 600 * 1e3;
1294
- const DESKTOP_COMMAND_MAX_TIMEOUT_MS = 720 * 60 * 1e3;
1293
+ const DESKTOP_COMMAND_DEFAULT_TIMEOUT_MS = 6e5;
1294
+ const DESKTOP_COMMAND_MAX_TIMEOUT_MS = 432e5;
1295
1295
  const DESKTOP_COMMAND_SETTLEMENT_GRACE_SECONDS = 600;
1296
1296
  /** Keeps pending commands reportable for the full wait window plus settlement grace. */
1297
1297
  const DESKTOP_COMMAND_PENDING_TTL_SECONDS = 43800;
@@ -3846,7 +3846,8 @@ var SpaceClient = class {
3846
3846
  };
3847
3847
  return result;
3848
3848
  }
3849
- throw new HttpError(body && typeof body === "object" && typeof body.message === "string" ? body.message : "Unexpected completion response", raw.response.status, body);
3849
+ const message = body && typeof body === "object" && typeof body.message === "string" ? body.message : "Unexpected completion response";
3850
+ throw new HttpError(message, raw.response.status, body);
3850
3851
  }
3851
3852
  if (!raw.response.body) throw new HttpError("Empty completion stream", 502, null);
3852
3853
  const reader = raw.response.body.getReader();
@@ -4067,7 +4068,8 @@ var UserApi = class {
4067
4068
  const response = await fetch(this.transportBaseUrl ? `${this.transportBaseUrl}/api/me` : "/api/me", { headers: { Authorization: `Bearer ${trimmedToken}` } });
4068
4069
  if (!response.ok) {
4069
4070
  const body = (response.headers.get("content-type") ?? "").includes("application/json") ? await response.json().catch(() => null) : await response.text().catch(() => response.statusText);
4070
- throw new HttpError((typeof body === "string" ? body : JSON.stringify(body ?? null)) || response.statusText, response.status, body);
4071
+ const message = typeof body === "string" ? body : JSON.stringify(body ?? null);
4072
+ throw new HttpError(message || response.statusText, response.status, body);
4071
4073
  }
4072
4074
  this.setStoredAuthToken?.(trimmedToken);
4073
4075
  return response.json();
@@ -17,7 +17,7 @@ const isRealtimeDomain = (value) => typeof value === "string" && REALTIME_DOMAIN
17
17
  /** Accepted room event names. Shared so a client can reject one before sending. */
18
18
  const REALTIME_ROOM_EVENT_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/;
19
19
  /** Maximum encoded size of a room event payload. */
20
- const REALTIME_ROOM_MAX_PAYLOAD_BYTES = 16 * 1024;
20
+ const REALTIME_ROOM_MAX_PAYLOAD_BYTES = 16384;
21
21
  const getRealtimeSpaceRoom = (spaceId) => `space:${spaceId}`;
22
22
  const getRealtimeBoardRoom = (boardId) => `board:${boardId}`;
23
23
  const parseRealtimeRoom = (room) => {
@@ -2361,7 +2361,7 @@ declare const BoardSemanticCommandSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
2361
2361
  digest: z.ZodOptional<z.ZodString>;
2362
2362
  }, z.core.$strict>>>;
2363
2363
  metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2364
- }, z.core.$strict>>;
2364
+ }, z.core.$strict>, unknown>;
2365
2365
  }, z.core.$strict>, z.ZodObject<{
2366
2366
  type: z.ZodLiteral<"effect.delete">;
2367
2367
  effectId: z.ZodString;
@@ -2490,7 +2490,7 @@ declare const BoardSemanticCommandSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
2490
2490
  }, z.core.$strict>], "mode">>;
2491
2491
  }, z.core.$strict>>;
2492
2492
  metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2493
- }, z.core.$strict>>;
2493
+ }, z.core.$strict>, unknown>;
2494
2494
  }, z.core.$strict>, z.ZodObject<{
2495
2495
  type: z.ZodLiteral<"composition.delete">;
2496
2496
  compositionId: z.ZodString;
@@ -3340,7 +3340,7 @@ declare const BoardSemanticMutationSchema: z.ZodObject<{
3340
3340
  digest: z.ZodOptional<z.ZodString>;
3341
3341
  }, z.core.$strict>>>;
3342
3342
  metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
3343
- }, z.core.$strict>>;
3343
+ }, z.core.$strict>, unknown>;
3344
3344
  }, z.core.$strict>, z.ZodObject<{
3345
3345
  type: z.ZodLiteral<"effect.delete">;
3346
3346
  effectId: z.ZodString;
@@ -3469,7 +3469,7 @@ declare const BoardSemanticMutationSchema: z.ZodObject<{
3469
3469
  }, z.core.$strict>], "mode">>;
3470
3470
  }, z.core.$strict>>;
3471
3471
  metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
3472
- }, z.core.$strict>>;
3472
+ }, z.core.$strict>, unknown>;
3473
3473
  }, z.core.$strict>, z.ZodObject<{
3474
3474
  type: z.ZodLiteral<"composition.delete">;
3475
3475
  compositionId: z.ZodString;
@@ -4058,7 +4058,7 @@ declare const BoardCreateInputSchema: z.ZodObject<{
4058
4058
  digest: z.ZodOptional<z.ZodString>;
4059
4059
  }, z.core.$strict>>>;
4060
4060
  metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
4061
- }, z.core.$strict>>>>;
4061
+ }, z.core.$strict>, unknown>>>;
4062
4062
  compositions: z.ZodOptional<z.ZodArray<z.ZodPreprocess<z.ZodObject<{
4063
4063
  id: z.ZodString;
4064
4064
  name: z.ZodString;
@@ -4182,7 +4182,7 @@ declare const BoardCreateInputSchema: z.ZodObject<{
4182
4182
  }, z.core.$strict>], "mode">>;
4183
4183
  }, z.core.$strict>>;
4184
4184
  metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
4185
- }, z.core.$strict>>>>;
4185
+ }, z.core.$strict>, unknown>>>;
4186
4186
  }, z.core.$strip>;
4187
4187
  type BoardCreateInput = z.infer<typeof BoardCreateInputSchema>;
4188
4188
  type BoardAuthoringSchemas = {
@@ -5208,6 +5208,12 @@ type BoardChangedEvent = {
5208
5208
  mutationId: string;
5209
5209
  version: number;
5210
5210
  changed: BoardMutationReceipt["changed"];
5211
+ /** Server-authored animation rows for a small, pure animation mutation. */
5212
+ animationPatch?: {
5213
+ effects: BoardEffect[];
5214
+ compositions: BoardComposition[];
5215
+ playback?: BoardPlaybackSnapshot | null;
5216
+ };
5211
5217
  source?: RequestSource;
5212
5218
  };
5213
5219
  };
@@ -5386,7 +5392,7 @@ type BoardColorId = (typeof BOARD_COLOR_IDS)[number];
5386
5392
  declare const BOARD_GEO_KINDS: readonly ["rectangle", "rounded", "ellipse", "diamond", "triangle"];
5387
5393
  type BoardGeoKind = (typeof BOARD_GEO_KINDS)[number];
5388
5394
  //#endregion
5389
- //#region ../../node_modules/.pnpm/@neta-art+generation@0.1.22/node_modules/@neta-art/generation/dist/builtins-8R5iZQ10.d.ts
5395
+ //#region ../../node_modules/.pnpm/@neta-art+generation@0.1.23/node_modules/@neta-art/generation/dist/builtins-8R5iZQ10.d.ts
5390
5396
  //#region src/types.d.ts
5391
5397
  declare const MODEL_SCHEMA: "neta.generation.model.v1";
5392
5398
  type GenerationSource = {
@@ -8,6 +8,7 @@ interface CohubDebuggerOptions {
8
8
  maxNetworkEntries?: number;
9
9
  maxPayloadBytes?: number;
10
10
  maxLineBytes?: number;
11
+ maxResponseCaptureBytes?: number;
11
12
  captureHeaders?: boolean;
12
13
  captureRequestBody?: boolean;
13
14
  captureResponseBody?: boolean;
@@ -63,6 +64,7 @@ interface CohubNetworkEntry {
63
64
  truncated?: boolean;
64
65
  eventName?: string;
65
66
  payload?: SerializedValue | string;
67
+ bodyCaptureSkipped?: boolean;
66
68
  error?: string;
67
69
  close?: {
68
70
  code: number;
package/dist/debugger.js CHANGED
@@ -3,8 +3,9 @@ const DEFAULT_OPTIONS = {
3
3
  enabled: true,
4
4
  maxConsoleEntries: 1e3,
5
5
  maxNetworkEntries: 5e3,
6
- maxPayloadBytes: 64 * 1024,
7
- maxLineBytes: 16 * 1024,
6
+ maxPayloadBytes: 65536,
7
+ maxLineBytes: 16384,
8
+ maxResponseCaptureBytes: 262144,
8
9
  captureHeaders: true,
9
10
  captureRequestBody: true,
10
11
  captureResponseBody: true,
@@ -109,6 +110,7 @@ function installFetchCollector(state) {
109
110
  const responseUrl = normalizeHarUrl(response.url || requestInfo.url);
110
111
  state.instrumentedRequestUrls.add(responseUrl);
111
112
  const responseHeaders = state.options.captureHeaders ? headersToRecord(response.headers, state.options) : void 0;
113
+ const responseBodyCaptureSkipped = isResponseBodyCaptureSkipped(response, state.options);
112
114
  appendNetwork(state, {
113
115
  connectionId,
114
116
  kind: "fetch",
@@ -118,7 +120,8 @@ function installFetchCollector(state) {
118
120
  status: response.status,
119
121
  statusText: response.statusText,
120
122
  durationMs,
121
- responseHeaders
123
+ responseHeaders,
124
+ bodyCaptureSkipped: responseBodyCaptureSkipped
122
125
  });
123
126
  collectFetchResponseBody(state, connectionId, requestInfo.method, responseUrl, response);
124
127
  return response;
@@ -199,7 +202,7 @@ function installXhrCollector(state) {
199
202
  statusText: this.statusText,
200
203
  durationMs: meta.startedAtMs ? Date.now() - meta.startedAtMs : void 0,
201
204
  responseHeaders: state.options.captureHeaders ? parseRawHeaders(this.getAllResponseHeaders(), state.options) : void 0,
202
- payload: getXhrResponsePreview(this, state.options)
205
+ ...getXhrResponsePreview(this, state.options)
203
206
  });
204
207
  });
205
208
  this.addEventListener("error", () => {
@@ -513,7 +516,7 @@ function resourceKindFromInitiator(initiatorType, url) {
513
516
  return "resource";
514
517
  }
515
518
  function collectFetchResponseBody(state, connectionId, method, url, response) {
516
- if (!state.options.captureResponseBody || !response.body) return;
519
+ if (!state.options.captureResponseBody || !response.body || isResponseBodyCaptureSkipped(response, state.options)) return;
517
520
  const clone = response.clone();
518
521
  if ((clone.headers.get("content-type") ?? "").includes("text/event-stream")) {
519
522
  collectReadableStreamLines(state, {
@@ -526,6 +529,7 @@ function collectFetchResponseBody(state, connectionId, method, url, response) {
526
529
  return;
527
530
  }
528
531
  clone.text().then((text) => {
532
+ const preview = createTextPreview(text, state.options.maxPayloadBytes);
529
533
  appendNetwork(state, {
530
534
  connectionId,
531
535
  kind: "fetch",
@@ -534,9 +538,9 @@ function collectFetchResponseBody(state, connectionId, method, url, response) {
534
538
  url,
535
539
  direction: "incoming",
536
540
  lineNumber: 1,
537
- payload: truncateText(text, state.options.maxPayloadBytes),
538
- sizeBytes: byteLength(text),
539
- truncated: byteLength(text) > state.options.maxPayloadBytes
541
+ payload: preview.payload,
542
+ sizeBytes: preview.sizeBytes,
543
+ truncated: preview.truncated
540
544
  });
541
545
  }, () => {});
542
546
  }
@@ -669,9 +673,7 @@ function appendLine(state, details) {
669
673
  direction: details.direction,
670
674
  lineNumber: details.lineNumber,
671
675
  eventName: details.eventName,
672
- payload: truncateText(details.text, state.options.maxLineBytes),
673
- sizeBytes: byteLength(details.text),
674
- truncated: byteLength(details.text) > state.options.maxLineBytes
676
+ ...createTextPreview(details.text, state.options.maxLineBytes)
675
677
  });
676
678
  }
677
679
  function nextXhrLineNumber(meta) {
@@ -694,28 +696,17 @@ function normalizeFetchRequest(input, init, options) {
694
696
  };
695
697
  }
696
698
  function getXhrResponsePreview(xhr, options) {
697
- if (!options.captureResponseBody) return;
698
- if (xhr.responseType && xhr.responseType !== "text") return serializeValue({
699
+ if (!options.captureResponseBody) return {};
700
+ if (xhr.responseType && xhr.responseType !== "text") return { payload: serializeValue({
699
701
  responseType: xhr.responseType,
700
702
  note: "Non-text XHR response body was not captured."
701
- }, options);
702
- return truncateText(xhr.responseText, options.maxPayloadBytes);
703
+ }, options) };
704
+ return createTextPreview(xhr.responseText, options.maxPayloadBytes);
703
705
  }
704
706
  function serializeBodyPreview(body, options) {
705
707
  if (body == null) return;
706
- if (typeof body === "string") return {
707
- payload: truncateText(body, options.maxPayloadBytes),
708
- sizeBytes: byteLength(body),
709
- truncated: byteLength(body) > options.maxPayloadBytes
710
- };
711
- if (typeof URLSearchParams !== "undefined" && body instanceof URLSearchParams) {
712
- const text = body.toString();
713
- return {
714
- payload: truncateText(text, options.maxPayloadBytes),
715
- sizeBytes: byteLength(text),
716
- truncated: byteLength(text) > options.maxPayloadBytes
717
- };
718
- }
708
+ if (typeof body === "string") return createTextPreview(body, options.maxPayloadBytes);
709
+ if (typeof URLSearchParams !== "undefined" && body instanceof URLSearchParams) return createTextPreview(body.toString(), options.maxPayloadBytes);
719
710
  if (typeof Blob !== "undefined" && body instanceof Blob) return {
720
711
  payload: {
721
712
  type: "Blob",
@@ -1192,21 +1183,40 @@ function redactUrl(url) {
1192
1183
  if (typeof url !== "string" || url.indexOf("?") === -1) return url;
1193
1184
  return url.replace(/([?&])([^=&#?]*)=([^&#]*)/g, (match, sep, key) => isSensitiveKey(key) || /token|secret|pass|key|auth|credential/i.test(key) ? `${sep}${key}=[redacted]` : match);
1194
1185
  }
1195
- function truncateText(text, maxBytes) {
1196
- if (byteLength(text) <= maxBytes) return text;
1197
- let result = "";
1198
- let size = 0;
1199
- for (const char of text) {
1200
- const charSize = byteLength(char);
1201
- if (size + charSize > maxBytes) break;
1202
- result += char;
1203
- size += charSize;
1186
+ function createTextPreview(text, maxBytes) {
1187
+ const sizeBytes = byteLength(text);
1188
+ return {
1189
+ payload: truncateText(text, maxBytes, sizeBytes),
1190
+ sizeBytes,
1191
+ truncated: sizeBytes > maxBytes
1192
+ };
1193
+ }
1194
+ function truncateText(text, maxBytes, knownSizeBytes = byteLength(text)) {
1195
+ if (knownSizeBytes <= maxBytes) return text;
1196
+ let low = 0;
1197
+ let high = Math.min(text.length, maxBytes);
1198
+ while (low < high) {
1199
+ const middle = Math.ceil((low + high) / 2);
1200
+ if (byteLength(text.slice(0, middle)) <= maxBytes) low = middle;
1201
+ else high = middle - 1;
1204
1202
  }
1205
- return `${result}\n[truncated at ${maxBytes} bytes]`;
1203
+ if (low > 0 && low < text.length) {
1204
+ const previous = text.charCodeAt(low - 1);
1205
+ const next = text.charCodeAt(low);
1206
+ if (previous >= 55296 && previous <= 56319 && next >= 56320 && next <= 57343) low -= 1;
1207
+ }
1208
+ return `${text.slice(0, low)}\n[truncated at ${maxBytes} bytes]`;
1206
1209
  }
1207
1210
  function byteLength(text) {
1208
1211
  return textEncoder.encode(text).byteLength;
1209
1212
  }
1213
+ function isResponseBodyCaptureSkipped(response, options) {
1214
+ if (!options.captureResponseBody) return false;
1215
+ const contentLength = response.headers.get("content-length");
1216
+ if (contentLength === null) return false;
1217
+ const size = Number(contentLength);
1218
+ return Number.isFinite(size) && size > options.maxResponseCaptureBytes;
1219
+ }
1210
1220
  function errorToString(error) {
1211
1221
  if (error instanceof Error) return `${error.name}: ${error.message}`;
1212
1222
  return String(error);
package/dist/index.js CHANGED
@@ -1172,7 +1172,7 @@ const APP_SURFACE_READY_TIMEOUT_MS = 1e4;
1172
1172
  const APP_SURFACE_REQUEST_TIMEOUT_MS = 15e3;
1173
1173
  const APP_COMPOSER_CHIP_KEY_MAX_LENGTH = 80;
1174
1174
  const APP_COMPOSER_CHIP_LABEL_MAX_LENGTH = 120;
1175
- const APP_COMPOSER_CHIP_CONTENT_MAX_BYTES = 32 * 1024;
1175
+ const APP_COMPOSER_CHIP_CONTENT_MAX_BYTES = 32768;
1176
1176
  const isRecord$1 = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
1177
1177
  const isSurfaceEnvelope = (value) => isRecord$1(value) && value.protocol === "cohub.app.surface" && value.version === 1;
1178
1178
  const parseAppSurfaceReady = (value) => {
@@ -2796,7 +2796,7 @@ const formatWorkRef = formatAppRef;
2796
2796
  //#region src/app-grant-cache.ts
2797
2797
  const STORAGE_PREFIX = "cohub:work-grants";
2798
2798
  const CACHE_VERSION = 1;
2799
- const MAX_AGE_MS = 336 * 60 * 60 * 1e3;
2799
+ const MAX_AGE_MS = 12096e5;
2800
2800
  function isBrowser() {
2801
2801
  return typeof localStorage !== "undefined";
2802
2802
  }
@@ -1148,7 +1148,7 @@ declare const BoardSemanticCommandSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1148
1148
  digest: z.ZodOptional<z.ZodString>;
1149
1149
  }, z.core.$strict>>>;
1150
1150
  metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1151
- }, z.core.$strict>>;
1151
+ }, z.core.$strict>, unknown>;
1152
1152
  }, z.core.$strict>, z.ZodObject<{
1153
1153
  type: z.ZodLiteral<"effect.delete">;
1154
1154
  effectId: z.ZodString;
@@ -1277,7 +1277,7 @@ declare const BoardSemanticCommandSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1277
1277
  }, z.core.$strict>], "mode">>;
1278
1278
  }, z.core.$strict>>;
1279
1279
  metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1280
- }, z.core.$strict>>;
1280
+ }, z.core.$strict>, unknown>;
1281
1281
  }, z.core.$strict>, z.ZodObject<{
1282
1282
  type: z.ZodLiteral<"composition.delete">;
1283
1283
  compositionId: z.ZodString;
@@ -6,8 +6,8 @@ const DEFAULT_BOARD_RENDER_LIMITS = {
6
6
  drawCalls: 400,
7
7
  filterPasses: 24,
8
8
  renderTexturePixels: 16777216,
9
- textureBytes: 512 * 1024 * 1024,
10
- bufferBytes: 256 * 1024 * 1024,
9
+ textureBytes: 536870912,
10
+ bufferBytes: 268435456,
11
11
  simulationSteps: 1e5
12
12
  };
13
13
  const BOARD_BUILTIN_CLIP_KINDS = [
@@ -1,4 +1,3 @@
1
- import { BOARD_BUILTIN_CAPABILITIES, DEFAULT_BOARD_RENDER_LIMITS } from "./board-constants.js";
2
1
  import { BoardConnectionSchema } from "./board-connection.js";
3
2
  import { BoardCompositionInputSchema } from "./board-composition.js";
4
3
  import { BoardEffectInputSchema } from "./board-effect.js";
@@ -196,4 +195,4 @@ function isBoardPath(path) {
196
195
  return path.toLowerCase().endsWith(BOARD_EXTENSION);
197
196
  }
198
197
  //#endregion
199
- export { BOARD_AUTHORING_SCHEMAS, BOARD_BUILTIN_CAPABILITIES, BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BOARD_MANIFEST_KIND, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraStateSchema, BoardCreateInputSchema, BoardManifestSchema, DEFAULT_BOARD_RENDER_LIMITS, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest };
198
+ export { BOARD_AUTHORING_SCHEMAS, BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BOARD_MANIFEST_KIND, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraStateSchema, BoardCreateInputSchema, BoardManifestSchema, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest };
@@ -1,4 +1,4 @@
1
- import { BoardCapability, BoardCoordinateSpace, BoardRenderCost } from "./board-constants.js";
1
+ import { BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BoardCapability, BoardCoordinateSpace, BoardRenderCost, clampBoardStrokeSize } from "./board-constants.js";
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, connectionItemIds, connectionOtherItemId, connectionTouchesItem, createBoardConnection, flipBoardConnection, normalizeBoardConnectionStyle } from "./board-connection.js";
3
3
  import { BoardAnimationTarget, BoardAnimationTargetSchema, BoardComposition, BoardCompositionInput, BoardCompositionInputSchema, BoardCompositionSchema, BoardEasing, BoardEasingSchema, BoardProceduralClip, BoardProceduralClipSchema, BoardTimelineMarker, BoardTimelineMarkerSchema, BoardTrack, BoardTrackInterpolation, BoardTrackSchema } from "./board-composition.js";
4
4
  import { BoardAssetRef, BoardAssetRefSchema, BoardEffect, BoardEffectInput, BoardEffectInputSchema, BoardEffectSchema } from "./board-effect.js";
@@ -11,4 +11,4 @@ import { BOARD_COLOR_IDS, BOARD_GEO_KINDS, BoardColorId, BoardGeoKind } from "./
11
11
  import "./realtime/board-awareness.js";
12
12
  import "./app.js";
13
13
  import "./realtime/types.js";
14
- export { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_COLOR_IDS, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BOARD_GEO_KINDS, BoardAnimationTarget, BoardAnimationTargetSchema, type BoardAssetRef, BoardAuthoringItem, BoardAuthoringItemSchema, BoardAuthoringSnapshot, BoardCameraFocus, BoardCameraFocusParams, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraState, BoardCameraStateSchema, type BoardCapability, BoardColorId, BoardComposition, BoardCompositionInput, BoardCompositionInputSchema, BoardCompositionSchema, BoardConnection, BoardConnectionAnchor, BoardConnectionAnchorSchema, BoardConnectionDirection, BoardConnectionEndpoint, BoardConnectionEndpointSchema, BoardConnectionInput, BoardConnectionLine, BoardConnectionPatch, BoardConnectionPatchSchema, BoardConnectionRecord, BoardConnectionRouting, BoardConnectionRoutingConfig, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionSide, BoardConnectionStyle, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardDiagnostic, BoardEasing, BoardEasingSchema, type BoardEffect, BoardGeoKind, BoardManifest, BoardManifestSchema, BoardMutationReceipt, BoardPlaybackSnapshot, BoardPlaybackStatus, BoardProceduralClip, BoardProceduralClipSchema, BoardRelationSchema, type BoardRenderCost, BoardSemanticCommand, BoardSemanticCommandSchema, BoardTimelineMarker, BoardTimelineMarkerSchema, BoardTrack, BoardTrackInterpolation, BoardTrackSchema, BoardValidationResult, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, connectionItemIds, connectionOtherItemId, connectionTouchesItem, createBoardConnection, flipBoardConnection, isBoardPath, normalizeBoardConnectionStyle, parseBoardManifest, serializeBoardManifest };
14
+ export { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_COLOR_IDS, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BOARD_GEO_KINDS, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BoardAnimationTarget, BoardAnimationTargetSchema, type BoardAssetRef, BoardAuthoringItem, BoardAuthoringItemSchema, BoardAuthoringSnapshot, BoardCameraFocus, BoardCameraFocusParams, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraState, BoardCameraStateSchema, BoardCapability, BoardColorId, BoardComposition, BoardCompositionInput, BoardCompositionInputSchema, BoardCompositionSchema, BoardConnection, BoardConnectionAnchor, BoardConnectionAnchorSchema, BoardConnectionDirection, BoardConnectionEndpoint, BoardConnectionEndpointSchema, BoardConnectionInput, BoardConnectionLine, BoardConnectionPatch, BoardConnectionPatchSchema, BoardConnectionRecord, BoardConnectionRouting, BoardConnectionRoutingConfig, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionSide, BoardConnectionStyle, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardDiagnostic, BoardEasing, BoardEasingSchema, type BoardEffect, BoardGeoKind, BoardManifest, BoardManifestSchema, BoardMutationReceipt, BoardPlaybackSnapshot, BoardPlaybackStatus, BoardProceduralClip, BoardProceduralClipSchema, BoardRelationSchema, BoardRenderCost, BoardSemanticCommand, BoardSemanticCommandSchema, BoardTimelineMarker, BoardTimelineMarkerSchema, BoardTrack, BoardTrackInterpolation, BoardTrackSchema, BoardValidationResult, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, clampBoardStrokeSize, connectionItemIds, connectionOtherItemId, connectionTouchesItem, createBoardConnection, flipBoardConnection, isBoardPath, normalizeBoardConnectionStyle, parseBoardManifest, serializeBoardManifest };
@@ -1,3 +1,5 @@
1
+ import "../board-composition.js";
2
+ import "../board-effect.js";
1
3
  import "../board.js";
2
4
  import "./board-awareness.js";
3
5
  import "../app.js";
@@ -3,7 +3,7 @@ import { s as resolveVoiceInputWebsocketUrl } from "./chunks/environment.js";
3
3
  const TARGET_SAMPLE_RATE = 16e3;
4
4
  const CHUNK_SAMPLES = TARGET_SAMPLE_RATE * 200 / 1e3;
5
5
  const DEFAULT_CONNECTION_TIMEOUT_MS = 1e4;
6
- const DEFAULT_IDLE_CONNECTION_TIMEOUT_MS = 30 * 6e4;
6
+ const DEFAULT_IDLE_CONNECTION_TIMEOUT_MS = 18e5;
7
7
  const WEBSOCKET_OPEN = 1;
8
8
  const getDefaultWebSocket = () => {
9
9
  const WebSocketImpl = globalThis.WebSocket;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neta-art/cohub",
3
- "version": "8.5.0",
3
+ "version": "8.5.1",
4
4
  "description": "Cohub SDK for spaces, sessions, boards, and realtime agent collaboration.",
5
5
  "license": "Apache-2.0",
6
6
  "private": false,
@@ -72,15 +72,15 @@
72
72
  ],
73
73
  "dependencies": {
74
74
  "perfect-freehand": "1.2.3",
75
- "zod": "^4.4.3"
75
+ "zod": "^4.5.4"
76
76
  },
77
77
  "devDependencies": {
78
- "@biomejs/biome": "2.5.3",
79
- "@napi-rs/canvas": "^1.0.2",
80
- "@types/node": "26.1.1",
81
- "pixi.js": "^8.19.0",
82
- "tsdown": "^0.22.7",
83
- "tsx": "4.23.1",
78
+ "@biomejs/biome": "2.5.11",
79
+ "@napi-rs/canvas": "^1.0.8",
80
+ "@types/node": "26.4.0",
81
+ "pixi.js": "^8.20.1",
82
+ "tsdown": "^0.22.14",
83
+ "tsx": "4.23.13",
84
84
  "typescript": "^7.0.2",
85
85
  "@cohub/protocol": "2.0.0"
86
86
  },