@neta-art/cohub 5.5.0 → 5.6.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/index.d.ts +2 -1
- package/dist/board/index.js +2 -1
- 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/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/index.d.ts
CHANGED
|
@@ -17,4 +17,5 @@ import { ShapeDefinition, definitionForItem, getShapeDefinition, registerShapeDe
|
|
|
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, 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, 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
|
@@ -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, 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,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);
|
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 };
|