@adminide-stack/yantra-mobile 12.0.121 → 12.0.123
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/lib/features/apps/appArt.js +1 -1
- package/lib/features/apps/appArt.js.map +1 -1
- package/lib/features/apps/mobileAppCatalog.js +15 -11
- package/lib/features/apps/mobileAppCatalog.js.map +1 -1
- package/lib/features/canvas/CanvasAgentChatPane.js +82 -20
- package/lib/features/canvas/CanvasAgentChatPane.js.map +1 -1
- package/lib/features/canvas/CanvasBoardsGrid.js +291 -100
- package/lib/features/canvas/CanvasBoardsGrid.js.map +1 -1
- package/lib/features/canvas/CanvasEditToolsPanel.js +105 -12
- package/lib/features/canvas/CanvasEditToolsPanel.js.map +1 -1
- package/lib/features/canvas/CanvasExperience.js +266 -68
- package/lib/features/canvas/CanvasExperience.js.map +1 -1
- package/lib/features/canvas/CanvasGeneratePanel.js +204 -66
- package/lib/features/canvas/CanvasGeneratePanel.js.map +1 -1
- package/lib/features/canvas/CanvasLibrarySheet.js +31 -13
- package/lib/features/canvas/CanvasLibrarySheet.js.map +1 -1
- package/lib/features/canvas/CanvasModelPicker.js +176 -0
- package/lib/features/canvas/CanvasModelPicker.js.map +1 -0
- package/lib/features/canvas/CanvasTasksPanel.js +325 -29
- package/lib/features/canvas/CanvasTasksPanel.js.map +1 -1
- package/lib/features/canvas/CanvasTemplatesPanel.js +5 -4
- package/lib/features/canvas/CanvasTemplatesPanel.js.map +1 -1
- package/lib/features/canvas/CanvasToolDock.js +137 -61
- package/lib/features/canvas/CanvasToolDock.js.map +1 -1
- package/lib/features/canvas/FrameExtractorExperience.js +33 -2
- package/lib/features/canvas/FrameExtractorExperience.js.map +1 -1
- package/lib/features/canvas/GeneratorReferenceSlots.js +197 -0
- package/lib/features/canvas/GeneratorReferenceSlots.js.map +1 -0
- package/lib/features/canvas/NativeCanvasViewer.js +89 -11
- package/lib/features/canvas/NativeCanvasViewer.js.map +1 -1
- package/lib/features/canvas/PromoContextFields.js +55 -2
- package/lib/features/canvas/PromoContextFields.js.map +1 -1
- package/lib/features/canvas/SetStudioExperience.js +323 -13
- package/lib/features/canvas/SetStudioExperience.js.map +1 -1
- package/lib/features/canvas/VideoEditExperience.js +1 -53
- package/lib/features/canvas/VideoEditExperience.js.map +1 -1
- package/lib/features/canvas/VideoEditorExperience.js +697 -506
- package/lib/features/canvas/VideoEditorExperience.js.map +1 -1
- package/lib/features/canvas/VideoGeneratorExperience.js +22 -5
- package/lib/features/canvas/VideoGeneratorExperience.js.map +1 -1
- package/lib/features/canvas/canvasAgentChat.js +125 -11
- package/lib/features/canvas/canvasAgentChat.js.map +1 -1
- package/lib/features/canvas/canvasCore.js +117 -12
- package/lib/features/canvas/canvasCore.js.map +1 -1
- package/lib/features/canvas/canvasEditOps.js +148 -111
- package/lib/features/canvas/canvasEditOps.js.map +1 -1
- package/lib/features/canvas/canvasTaskSync.js +235 -0
- package/lib/features/canvas/canvasTaskSync.js.map +1 -0
- package/lib/features/canvas/canvasTasks.js +98 -11
- package/lib/features/canvas/canvasTasks.js.map +1 -1
- package/lib/features/canvas/createTiles.js +247 -0
- package/lib/features/canvas/createTiles.js.map +1 -0
- package/lib/features/canvas/deepLinks.js +83 -0
- package/lib/features/canvas/deepLinks.js.map +1 -0
- package/lib/features/canvas/frameExtract.js +13 -1
- package/lib/features/canvas/frameExtract.js.map +1 -1
- package/lib/features/canvas/generationModels.js +36 -8
- package/lib/features/canvas/generationModels.js.map +1 -1
- package/lib/features/canvas/generatorCommands.js +106 -0
- package/lib/features/canvas/generatorCommands.js.map +1 -0
- package/lib/features/canvas/generatorReferences.js +82 -0
- package/lib/features/canvas/generatorReferences.js.map +1 -0
- package/lib/features/canvas/homeWork.js +74 -0
- package/lib/features/canvas/homeWork.js.map +1 -0
- package/lib/features/canvas/linksRpc.js +130 -0
- package/lib/features/canvas/linksRpc.js.map +1 -0
- package/lib/features/canvas/mediaRecheck.js +176 -0
- package/lib/features/canvas/mediaRecheck.js.map +1 -0
- package/lib/features/canvas/mediaUrls.js +258 -0
- package/lib/features/canvas/mediaUrls.js.map +1 -0
- package/lib/features/canvas/nativeViewerRegistry.js.map +1 -1
- package/lib/features/canvas/promoProjectImport.js +80 -13
- package/lib/features/canvas/promoProjectImport.js.map +1 -1
- package/lib/features/canvas/promoVideo.js +106 -15
- package/lib/features/canvas/promoVideo.js.map +1 -1
- package/lib/features/canvas/reframe.js +228 -0
- package/lib/features/canvas/reframe.js.map +1 -0
- package/lib/features/canvas/serverTasks.js +697 -0
- package/lib/features/canvas/serverTasks.js.map +1 -0
- package/lib/features/canvas/set/SetViewportWebView.js +207 -28
- package/lib/features/canvas/set/SetViewportWebView.js.map +1 -1
- package/lib/features/canvas/set/agent/prompt.js +66 -0
- package/lib/features/canvas/set/agent/prompt.js.map +1 -0
- package/lib/features/canvas/set/agent/setOps.js +203 -0
- package/lib/features/canvas/set/agent/setOps.js.map +1 -0
- package/lib/features/canvas/set/agent/setTurn.js +128 -0
- package/lib/features/canvas/set/agent/setTurn.js.map +1 -0
- package/lib/features/canvas/set/agent/snapshot.js +43 -0
- package/lib/features/canvas/set/agent/snapshot.js.map +1 -0
- package/lib/features/canvas/set/agent/tools.js +580 -0
- package/lib/features/canvas/set/agent/tools.js.map +1 -0
- package/lib/features/canvas/set/setProject.js +43 -4
- package/lib/features/canvas/set/setProject.js.map +1 -1
- package/lib/features/canvas/set/supplyLibrary.js +397 -0
- package/lib/features/canvas/set/supplyLibrary.js.map +1 -0
- package/lib/features/canvas/storageLibrary.js +113 -52
- package/lib/features/canvas/storageLibrary.js.map +1 -1
- package/lib/features/canvas/studioCatalog.js +15 -2
- package/lib/features/canvas/studioCatalog.js.map +1 -1
- package/lib/features/canvas/studioLooks.js +1 -8
- package/lib/features/canvas/studioLooks.js.map +1 -1
- package/lib/features/canvas/useBoardMediaRefresh.js +66 -0
- package/lib/features/canvas/useBoardMediaRefresh.js.map +1 -0
- package/lib/features/canvas/useMediaSource.js +84 -0
- package/lib/features/canvas/useMediaSource.js.map +1 -0
- package/lib/features/canvas/video3d.js +11 -10
- package/lib/features/canvas/video3d.js.map +1 -1
- package/lib/features/canvas/videoEditor/BlurBoxOverlay.js +46 -0
- package/lib/features/canvas/videoEditor/BlurBoxOverlay.js.map +1 -0
- package/lib/features/canvas/videoEditor/ExportTaskCard.js +134 -0
- package/lib/features/canvas/videoEditor/ExportTaskCard.js.map +1 -0
- package/lib/features/canvas/videoEditor/agent/AgentCutPane.js +45 -7
- package/lib/features/canvas/videoEditor/agent/AgentCutPane.js.map +1 -1
- package/lib/features/canvas/videoEditor/agent/agentLoop.js +4 -2
- package/lib/features/canvas/videoEditor/agent/agentLoop.js.map +1 -1
- package/lib/features/canvas/videoEditor/agent/attachments.js +304 -0
- package/lib/features/canvas/videoEditor/agent/attachments.js.map +1 -0
- package/lib/features/canvas/videoEditor/agent/brainClient.js +3 -2
- package/lib/features/canvas/videoEditor/agent/brainClient.js.map +1 -1
- package/lib/features/canvas/videoEditor/agent/cutTools.js +207 -7
- package/lib/features/canvas/videoEditor/agent/cutTools.js.map +1 -1
- package/lib/features/canvas/videoEditor/blurBox.js +34 -0
- package/lib/features/canvas/videoEditor/blurBox.js.map +1 -0
- package/lib/features/canvas/videoEditor/compileTimeline.js +668 -0
- package/lib/features/canvas/videoEditor/compileTimeline.js.map +1 -0
- package/lib/features/canvas/videoEditor/editorModel.js +56 -22
- package/lib/features/canvas/videoEditor/editorModel.js.map +1 -1
- package/lib/features/canvas/videoEditor/exportPipeline.js +77 -0
- package/lib/features/canvas/videoEditor/exportPipeline.js.map +1 -0
- package/lib/features/canvas/videoEditor/exportRenderer.js +19 -12
- package/lib/features/canvas/videoEditor/exportRenderer.js.map +1 -1
- package/lib/features/canvas/videoEditor/exportTask.js +216 -0
- package/lib/features/canvas/videoEditor/exportTask.js.map +1 -0
- package/lib/features/canvas/videoEditor/formWidgets.js +142 -0
- package/lib/features/canvas/videoEditor/formWidgets.js.map +1 -0
- package/lib/features/canvas/videoEditor/produce/ProduceVideoSheet.js +195 -0
- package/lib/features/canvas/videoEditor/produce/ProduceVideoSheet.js.map +1 -0
- package/lib/features/canvas/videoEditor/produce/produceScenes.js +158 -0
- package/lib/features/canvas/videoEditor/produce/produceScenes.js.map +1 -0
- package/lib/features/canvas/videoEditor/remoteMediaClient.js +17 -5
- package/lib/features/canvas/videoEditor/remoteMediaClient.js.map +1 -1
- package/lib/features/canvas/videoEditor/renderTimeline.js +207 -0
- package/lib/features/canvas/videoEditor/renderTimeline.js.map +1 -0
- package/lib/features/canvas/videoEditor/renewLinks.js +64 -0
- package/lib/features/canvas/videoEditor/renewLinks.js.map +1 -0
- package/lib/features/canvas/videoEditor/sceneLayers.js +101 -0
- package/lib/features/canvas/videoEditor/sceneLayers.js.map +1 -0
- package/lib/features/canvas/videoEditor/tools/ToolsDrawer.js +283 -0
- package/lib/features/canvas/videoEditor/tools/ToolsDrawer.js.map +1 -0
- package/lib/features/canvas/videoEditor/tools/catalog.js +576 -0
- package/lib/features/canvas/videoEditor/tools/catalog.js.map +1 -0
- package/lib/features/canvas/videoEditor/videoProjectsStore.js +27 -3
- package/lib/features/canvas/videoEditor/videoProjectsStore.js.map +1 -1
- package/lib/features/webbuilder/WebBuilderExperience.js +29 -1
- package/lib/features/webbuilder/WebBuilderExperience.js.map +1 -1
- package/lib/features/webbuilder/buildFragments.js +8 -4
- package/lib/features/webbuilder/buildFragments.js.map +1 -1
- package/lib/features/webbuilder/codezenHandoff.js +108 -0
- package/lib/features/webbuilder/codezenHandoff.js.map +1 -0
- package/lib/features/webbuilder/workflow.js.map +1 -1
- package/lib/hooks/useChatApi.js +1 -2
- package/lib/hooks/useChatApi.js.map +1 -1
- package/lib/screens/CanvasBoard/index.js +12 -1
- package/lib/screens/CanvasBoard/index.js.map +1 -1
- package/lib/screens/Home/HomeScreen.js.map +1 -1
- package/lib/screens/Home/components/HomeSuggestions.js +3 -3
- package/lib/screens/Home/components/HomeSuggestions.js.map +1 -1
- package/lib/screens/WebBuilder/index.js +4 -2
- package/lib/screens/WebBuilder/index.js.map +1 -1
- package/lib/screens/WebBuilderNative/index.js +29 -2
- package/lib/screens/WebBuilderNative/index.js.map +1 -1
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js +30 -6
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js.map +1 -1
- package/package.json +3 -3
- /package/lib/assets/apps/{paper2poster.webp → poster.webp} +0 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
5
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
+
var __spreadValues = (a, b) => {
|
|
7
|
+
for (var prop in b || (b = {}))
|
|
8
|
+
if (__hasOwnProp.call(b, prop))
|
|
9
|
+
__defNormalProp(a, prop, b[prop]);
|
|
10
|
+
if (__getOwnPropSymbols)
|
|
11
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
12
|
+
if (__propIsEnum.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
}
|
|
15
|
+
return a;
|
|
16
|
+
};
|
|
17
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
|
|
18
|
+
const ATTACHMENT_BLOCK_HEADER = "[Attached with this message]";
|
|
19
|
+
const LINK_MAX_BYTES = 25 * 1024 * 1024;
|
|
20
|
+
const MAX_LINKS_PER_MESSAGE = 5;
|
|
21
|
+
const FETCH_TIMEOUT_MS = 6e4;
|
|
22
|
+
const BROWSER_UA = "Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1";
|
|
23
|
+
const ACCEPT_ANY = "text/html,application/xhtml+xml,image/avif,image/webp,image/*,video/*,audio/*;q=0.9,*/*;q=0.8";
|
|
24
|
+
const ACCEPT_MEDIA = "image/avif,image/webp,image/*,video/*,audio/*;q=0.9,*/*;q=0.5";
|
|
25
|
+
function linksIn(text, max = MAX_LINKS_PER_MESSAGE) {
|
|
26
|
+
const found = [];
|
|
27
|
+
for (const m of text.matchAll(/https?:\/\/[^\s<>"'`]+/gi)) {
|
|
28
|
+
let link = m[0].replace(/[.,;:!?]+$/, "");
|
|
29
|
+
for (const [open, close] of [["(", ")"], ["[", "]"]]) {
|
|
30
|
+
while (link.endsWith(close) && link.split(open).length < link.split(close).length) link = link.slice(0, -1);
|
|
31
|
+
}
|
|
32
|
+
if (!/^https?:\/\/[^/\s]+\.[^/\s]+/i.test(link)) continue;
|
|
33
|
+
if (!found.includes(link)) found.push(link);
|
|
34
|
+
if (found.length >= max) break;
|
|
35
|
+
}
|
|
36
|
+
return found;
|
|
37
|
+
}
|
|
38
|
+
const hostOf = (url) => {
|
|
39
|
+
var _a, _b, _c;
|
|
40
|
+
return (_c = (_b = (_a = /^https?:\/\/([^/?#:]+)/i.exec(url)) == null ? void 0 : _a[1]) == null ? void 0 : _b.replace(/^www\./, "")) != null ? _c : "that site";
|
|
41
|
+
};
|
|
42
|
+
function linkLabel(url) {
|
|
43
|
+
var _a;
|
|
44
|
+
const m = /^https?:\/\/([^/?#]+)([^?#]*)/i.exec(url);
|
|
45
|
+
if (!m) return url.length > 60 ? `${url.slice(0, 59)}\u2026` : url;
|
|
46
|
+
const host = m[1].replace(/^www\./, "");
|
|
47
|
+
const segments = m[2].split("/").filter(Boolean);
|
|
48
|
+
const last = (_a = segments[segments.length - 1]) != null ? _a : "";
|
|
49
|
+
if (!last) return host;
|
|
50
|
+
const name = last.length > 40 ? `${last.slice(0, 39)}\u2026` : last;
|
|
51
|
+
return segments.length > 1 ? `${host}/\u2026/${name}` : `${host}/${name}`;
|
|
52
|
+
}
|
|
53
|
+
function linkMediaKind(contentType, url = "") {
|
|
54
|
+
const mime = contentType.split(";")[0].trim().toLowerCase();
|
|
55
|
+
if (mime.startsWith("image/") && mime !== "image/svg+xml") return "image";
|
|
56
|
+
if (mime.startsWith("video/")) return "video";
|
|
57
|
+
if (mime.startsWith("audio/")) return "audio";
|
|
58
|
+
if (!mime || mime === "application/octet-stream" || mime === "binary/octet-stream") {
|
|
59
|
+
const path = url.split(/[?#]/)[0].toLowerCase();
|
|
60
|
+
if (/\.(png|jpe?g|gif|webp|avif|heic|heif|bmp|tiff?)$/.test(path)) return "image";
|
|
61
|
+
if (/\.(mp4|mov|m4v|webm|mkv)$/.test(path)) return "video";
|
|
62
|
+
if (/\.(mp3|wav|m4a|aac|ogg|flac)$/.test(path)) return "audio";
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
function decodeEntities(v) {
|
|
67
|
+
return v.replace(/&/g, "&").replace(/"/g, '"').replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
68
|
+
}
|
|
69
|
+
function absolute(u, pageUrl) {
|
|
70
|
+
var _a;
|
|
71
|
+
if (!u) return void 0;
|
|
72
|
+
const v = decodeEntities(u.trim());
|
|
73
|
+
if (/^https?:\/\//i.test(v)) return v;
|
|
74
|
+
if (v.startsWith("//")) return `https:${v}`;
|
|
75
|
+
const origin = (_a = /^(https?:\/\/[^/?#]+)/i.exec(pageUrl)) == null ? void 0 : _a[1];
|
|
76
|
+
if (!origin) return void 0;
|
|
77
|
+
if (v.startsWith("/")) return `${origin}${v}`;
|
|
78
|
+
const base = pageUrl.replace(/[?#].*$/, "").replace(/[^/]*$/, "");
|
|
79
|
+
return `${base}${v}`;
|
|
80
|
+
}
|
|
81
|
+
const DIRECT_VIDEO = /\.(mp4|mov|m4v|webm)(?:$|[?#])/i;
|
|
82
|
+
function pageMedia(html, pageUrl) {
|
|
83
|
+
var _a, _b, _c, _d, _e;
|
|
84
|
+
const metas = [...html.matchAll(/<meta\b[^>]*>/gi)].map((m) => m[0]);
|
|
85
|
+
const attr = (tag, name) => {
|
|
86
|
+
var _a2;
|
|
87
|
+
return (_a2 = new RegExp(`\\b${name}\\s*=\\s*("([^"]*)"|'([^']*)')`, "i").exec(tag)) == null ? void 0 : _a2.slice(2).find((x) => x !== void 0);
|
|
88
|
+
};
|
|
89
|
+
const meta = (...names) => {
|
|
90
|
+
var _a2;
|
|
91
|
+
for (const name of names) {
|
|
92
|
+
const tag = metas.find((t) => {
|
|
93
|
+
var _a3, _b2;
|
|
94
|
+
return ((_b2 = (_a3 = attr(t, "property")) != null ? _a3 : attr(t, "name")) == null ? void 0 : _b2.toLowerCase()) === name;
|
|
95
|
+
});
|
|
96
|
+
const content = tag ? (_a2 = attr(tag, "content")) == null ? void 0 : _a2.trim() : void 0;
|
|
97
|
+
if (content) return content;
|
|
98
|
+
}
|
|
99
|
+
return void 0;
|
|
100
|
+
};
|
|
101
|
+
const titleTag = (_b = (_a = /<title[^>]*>([^<]*)<\/title>/i.exec(html)) == null ? void 0 : _a[1]) == null ? void 0 : _b.trim();
|
|
102
|
+
const title = decodeEntities((_d = (_c = meta("og:title", "twitter:title")) != null ? _c : titleTag) != null ? _d : "") || void 0;
|
|
103
|
+
const videoType = (_e = meta("og:video:type")) != null ? _e : "";
|
|
104
|
+
const video = absolute(meta("og:video:secure_url", "og:video:url", "og:video", "twitter:player:stream"), pageUrl);
|
|
105
|
+
if (video && (/^video\//i.test(videoType) || DIRECT_VIDEO.test(video))) return {
|
|
106
|
+
url: video,
|
|
107
|
+
kind: "video",
|
|
108
|
+
title
|
|
109
|
+
};
|
|
110
|
+
const image = absolute(meta("og:image:secure_url", "og:image:url", "og:image", "twitter:image", "twitter:image:src"), pageUrl);
|
|
111
|
+
return image ? {
|
|
112
|
+
url: image,
|
|
113
|
+
kind: "image",
|
|
114
|
+
title
|
|
115
|
+
} : null;
|
|
116
|
+
}
|
|
117
|
+
const EXT = {
|
|
118
|
+
"image/jpeg": "jpg",
|
|
119
|
+
"image/png": "png",
|
|
120
|
+
"image/webp": "webp",
|
|
121
|
+
"image/gif": "gif",
|
|
122
|
+
"image/avif": "avif",
|
|
123
|
+
"video/mp4": "mp4",
|
|
124
|
+
"video/webm": "webm",
|
|
125
|
+
"video/quicktime": "mov",
|
|
126
|
+
"audio/mpeg": "mp3",
|
|
127
|
+
"audio/wav": "wav",
|
|
128
|
+
"audio/mp4": "m4a"
|
|
129
|
+
};
|
|
130
|
+
function linkFileName(url, mimeType, title) {
|
|
131
|
+
var _a, _b;
|
|
132
|
+
const ext = (_a = EXT[mimeType.split(";")[0].trim().toLowerCase()]) != null ? _a : "";
|
|
133
|
+
let base = (title != null ? title : "").replace(/\s+/g, " ").trim();
|
|
134
|
+
if (!base) {
|
|
135
|
+
const path = /^https?:\/\/([^/?#]+)([^?#]*)/i.exec(url);
|
|
136
|
+
let last = (_b = path == null ? void 0 : path[2].split("/").filter(Boolean).pop()) != null ? _b : "";
|
|
137
|
+
try {
|
|
138
|
+
last = decodeURIComponent(last);
|
|
139
|
+
} catch (e) {
|
|
140
|
+
}
|
|
141
|
+
base = last || (path == null ? void 0 : path[1]) || "link";
|
|
142
|
+
}
|
|
143
|
+
base = base.replace(/[\\/:*?"<>|#%{}^~[\]`]+/g, " ").replace(/\s+/g, " ").trim().slice(0, 60).trim() || "link";
|
|
144
|
+
if (!ext || base.toLowerCase().endsWith(`.${ext}`)) return base;
|
|
145
|
+
return `${base.replace(/\.(jpe?g|png|webp|gif|avif|heic|bmp|tiff?|mp4|m4v|mov|webm|mp3|wav|m4a|aac|ogg)$/i, "")}.${ext}`;
|
|
146
|
+
}
|
|
147
|
+
function linkFailureMessage(url, err) {
|
|
148
|
+
var _a;
|
|
149
|
+
const raw = err instanceof Error ? err.message : String(err != null ? err : "");
|
|
150
|
+
const host = hostOf(url);
|
|
151
|
+
const paste = "Save the picture to Photos and attach it instead.";
|
|
152
|
+
if (/just a moment|cf-mitigated|captcha|challenge|attention required|access denied/i.test(raw)) {
|
|
153
|
+
return `${host} only shows this to a person in a browser, so it cannot be fetched. ${paste}`;
|
|
154
|
+
}
|
|
155
|
+
const status = (_a = /HTTP (\d{3})/.exec(raw)) == null ? void 0 : _a[1];
|
|
156
|
+
if (status === "401" || status === "403" || status === "429") return `${host} refused the download (HTTP ${status}). ${paste}`;
|
|
157
|
+
if (status === "404" || status === "410") return `Nothing is at that link on ${host} (HTTP ${status}).`;
|
|
158
|
+
if (/over the \d+-byte limit|too large/i.test(raw)) return "The file at that link is over 25 MB. Download it and attach it instead.";
|
|
159
|
+
if (/timed out|timeout/i.test(raw)) return `${host} took too long to answer.`;
|
|
160
|
+
if (/https|public|private|loopback|not allowed|blocked/i.test(raw)) return "Only public web links can be taken in.";
|
|
161
|
+
if (status) return `${host} answered HTTP ${status}.`;
|
|
162
|
+
return `${host} could not be reached.`;
|
|
163
|
+
}
|
|
164
|
+
class LinkImportError extends Error {
|
|
165
|
+
constructor(url, message) {
|
|
166
|
+
super(message);
|
|
167
|
+
__publicField(this, "url");
|
|
168
|
+
this.name = "LinkImportError";
|
|
169
|
+
this.url = url;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async function fetchLinkViaAgent(run, url, accept) {
|
|
173
|
+
var _a, _b;
|
|
174
|
+
const result = await run("yantra-storage", "YANTRA_STORAGE_HTTP_SEND", {
|
|
175
|
+
url,
|
|
176
|
+
method: "GET",
|
|
177
|
+
headers: {
|
|
178
|
+
"User-Agent": BROWSER_UA,
|
|
179
|
+
Accept: accept,
|
|
180
|
+
"Accept-Language": "en-US,en;q=0.9"
|
|
181
|
+
},
|
|
182
|
+
responseType: "auto",
|
|
183
|
+
maxBytes: LINK_MAX_BYTES,
|
|
184
|
+
timeoutMs: FETCH_TIMEOUT_MS
|
|
185
|
+
});
|
|
186
|
+
if (result.successful === false) throw new Error(String((_a = result.error) != null ? _a : "the request failed"));
|
|
187
|
+
const data = result.bodyBase64 !== void 0 || result.bodyText !== void 0 ? result : (_b = result.data) != null ? _b : result;
|
|
188
|
+
const status = Number(data.status) || 0;
|
|
189
|
+
if (status >= 400) throw new Error(`HTTP ${status}`);
|
|
190
|
+
return {
|
|
191
|
+
status,
|
|
192
|
+
url: typeof data.url === "string" && data.url ? data.url : url,
|
|
193
|
+
contentType: typeof data.contentType === "string" ? data.contentType : "",
|
|
194
|
+
bodyBase64: typeof data.bodyBase64 === "string" ? data.bodyBase64 : void 0,
|
|
195
|
+
bodyText: typeof data.bodyText === "string" ? data.bodyText : void 0
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
async function importLink(url, deps) {
|
|
199
|
+
const fetchMedia = async (target, accept) => {
|
|
200
|
+
try {
|
|
201
|
+
return await deps.fetchUrl(target, accept);
|
|
202
|
+
} catch (err) {
|
|
203
|
+
throw new LinkImportError(url, linkFailureMessage(target, err));
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
let res = await fetchMedia(url, ACCEPT_ANY);
|
|
207
|
+
let kind = linkMediaKind(res.contentType, res.url);
|
|
208
|
+
let via;
|
|
209
|
+
let title;
|
|
210
|
+
if (!kind) {
|
|
211
|
+
if (!res.bodyText || !/html/i.test(res.contentType)) {
|
|
212
|
+
throw new LinkImportError(url, `That link is ${res.contentType.split(";")[0] || "not a file"}, not a picture, video or sound.`);
|
|
213
|
+
}
|
|
214
|
+
const found = pageMedia(res.bodyText, res.url);
|
|
215
|
+
if (!found) throw new LinkImportError(url, `The page at ${hostOf(url)} names no picture or video to take.`);
|
|
216
|
+
via = found.url;
|
|
217
|
+
title = found.title;
|
|
218
|
+
res = await fetchMedia(found.url, ACCEPT_MEDIA);
|
|
219
|
+
kind = linkMediaKind(res.contentType, res.url);
|
|
220
|
+
if (!kind) throw new LinkImportError(url, `The picture that page points to (${hostOf(found.url)}) did not come back as one.`);
|
|
221
|
+
}
|
|
222
|
+
if (!res.bodyBase64) throw new LinkImportError(url, `${hostOf(url)} sent an empty file.`);
|
|
223
|
+
const mimeType = res.contentType.split(";")[0].trim().toLowerCase() || `${kind}/*`;
|
|
224
|
+
const name = linkFileName(via != null ? via : res.url, mimeType, title);
|
|
225
|
+
const src = await deps.upload(`data:${mimeType};base64,${res.bodyBase64}`, name);
|
|
226
|
+
return __spreadValues({
|
|
227
|
+
url,
|
|
228
|
+
src,
|
|
229
|
+
kind,
|
|
230
|
+
mimeType,
|
|
231
|
+
name
|
|
232
|
+
}, via ? {
|
|
233
|
+
via
|
|
234
|
+
} : {});
|
|
235
|
+
}
|
|
236
|
+
async function intakeLinks(links, deps) {
|
|
237
|
+
var _a;
|
|
238
|
+
const out = [];
|
|
239
|
+
for (const link of links) {
|
|
240
|
+
const known = (_a = deps.existing) == null ? void 0 : _a.call(deps, link);
|
|
241
|
+
if (known) {
|
|
242
|
+
out.push({
|
|
243
|
+
name: known.name,
|
|
244
|
+
kind: known.type,
|
|
245
|
+
link,
|
|
246
|
+
assetId: known.id,
|
|
247
|
+
src: known.src
|
|
248
|
+
});
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
const got = await importLink(link, deps);
|
|
253
|
+
const assetId = deps.addAsset({
|
|
254
|
+
type: got.kind,
|
|
255
|
+
src: got.src,
|
|
256
|
+
name: got.name,
|
|
257
|
+
sourceUrl: link
|
|
258
|
+
});
|
|
259
|
+
out.push({
|
|
260
|
+
name: got.name,
|
|
261
|
+
kind: got.kind,
|
|
262
|
+
link,
|
|
263
|
+
assetId,
|
|
264
|
+
src: got.src
|
|
265
|
+
});
|
|
266
|
+
} catch (err) {
|
|
267
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
268
|
+
out.push({
|
|
269
|
+
name: linkLabel(link),
|
|
270
|
+
kind: "unusable",
|
|
271
|
+
link,
|
|
272
|
+
reason
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return out;
|
|
277
|
+
}
|
|
278
|
+
function attachmentBlock(attachments) {
|
|
279
|
+
if (attachments.length === 0) return "";
|
|
280
|
+
const lines = attachments.map((a) => {
|
|
281
|
+
var _a, _b;
|
|
282
|
+
const what = (kind) => a.link ? `${kind} from link ${a.link} ("${a.name}")` : `${kind} "${a.name}"`;
|
|
283
|
+
if (a.kind === "image") return `- ${what("image")} is library item id=${a.assetId} \xB7 shown to you with this message`;
|
|
284
|
+
if (a.kind === "video" || a.kind === "audio") return `- ${what(a.kind)} is library item id=${a.assetId}`;
|
|
285
|
+
return a.link ? `- link ${a.link} could not be taken in: ${(_a = a.reason) != null ? _a : "unreadable"}` : `- "${a.name}" could not be used: ${(_b = a.reason) != null ? _b : "unreadable"}`;
|
|
286
|
+
});
|
|
287
|
+
return `${ATTACHMENT_BLOCK_HEADER}
|
|
288
|
+
${lines.join("\n")}`;
|
|
289
|
+
}
|
|
290
|
+
function userContent(text, attachments = []) {
|
|
291
|
+
const block = attachmentBlock(attachments);
|
|
292
|
+
const words = block ? [text.trim(), block].filter(Boolean).join("\n\n") : text;
|
|
293
|
+
const images = attachments.filter((a) => a.kind === "image" && a.src && /^https?:\/\//i.test(a.src));
|
|
294
|
+
if (!images.length) return words;
|
|
295
|
+
return [{
|
|
296
|
+
type: "text",
|
|
297
|
+
text: words
|
|
298
|
+
}, ...images.map((a) => ({
|
|
299
|
+
type: "image_url",
|
|
300
|
+
image_url: {
|
|
301
|
+
url: a.src
|
|
302
|
+
}
|
|
303
|
+
}))];
|
|
304
|
+
}export{ATTACHMENT_BLOCK_HEADER,LINK_MAX_BYTES,LinkImportError,MAX_LINKS_PER_MESSAGE,attachmentBlock,fetchLinkViaAgent,importLink,intakeLinks,linkFailureMessage,linkFileName,linkLabel,linkMediaKind,linksIn,pageMedia,userContent};//# sourceMappingURL=attachments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachments.js","sources":["../../../../../src/features/canvas/videoEditor/agent/attachments.ts"],"sourcesContent":["/**\n * Files and links attached to a studio-agent message - native twin of web\n * agent/attachments.ts + rpc/linkImportRpc.ts.\n *\n * An attached picture goes to the model as an `image_url` part (it sees it\n * on the turn that carries it), and every attachment is named in an\n * `[Attached with this message]` block with the library id it became, so\n * \"the attached one\" resolves to something a tool can name.\n *\n * A pasted link is fetched on the agent through the storage connector's\n * guarded HTTP lane (YANTRA_STORAGE_HTTP_SEND: public https only, 25 MB cap);\n * a page is read for the media it names for link previews (og:video,\n * og:image, twitter:image) and that is fetched the same way. The bytes are\n * stored through the host uploader (a data: URL), so the item is a library\n * item with a hosted URL every connector can read.\n *\n * Pure except for the injected deps; no DOMParser/URL reliance (React Native).\n */\nimport type { RunMediaAction } from '../mediaActions';\nimport type { BrainContentPart } from './brainClient';\n\nexport type LinkMediaKind = 'image' | 'video' | 'audio';\n\nexport interface AgentAttachment {\n name: string;\n kind: LinkMediaKind | 'unusable';\n /** The link it came from, when it was a link. */\n link?: string;\n /** Library item id it became. */\n assetId?: string;\n /** Hosted URL. */\n src?: string;\n /** Why it could not be used. */\n reason?: string;\n}\n\nexport const ATTACHMENT_BLOCK_HEADER = '[Attached with this message]';\nexport const LINK_MAX_BYTES = 25 * 1024 * 1024;\nexport const MAX_LINKS_PER_MESSAGE = 5;\nconst FETCH_TIMEOUT_MS = 60_000;\nconst BROWSER_UA =\n 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1';\nconst ACCEPT_ANY = 'text/html,application/xhtml+xml,image/avif,image/webp,image/*,video/*,audio/*;q=0.9,*/*;q=0.8';\nconst ACCEPT_MEDIA = 'image/avif,image/webp,image/*,video/*,audio/*;q=0.9,*/*;q=0.5';\n\n/** http(s) links in a message, in order, deduplicated, trailing punctuation dropped. */\nexport function linksIn(text: string, max = MAX_LINKS_PER_MESSAGE): string[] {\n const found: string[] = [];\n for (const m of text.matchAll(/https?:\\/\\/[^\\s<>\"'`]+/gi)) {\n let link = m[0].replace(/[.,;:!?]+$/, '');\n for (const [open, close] of [\n ['(', ')'],\n ['[', ']'],\n ] as const) {\n while (link.endsWith(close) && link.split(open).length < link.split(close).length) link = link.slice(0, -1);\n }\n if (!/^https?:\\/\\/[^/\\s]+\\.[^/\\s]+/i.test(link)) continue;\n if (!found.includes(link)) found.push(link);\n if (found.length >= max) break;\n }\n return found;\n}\n\nconst hostOf = (url: string): string => /^https?:\\/\\/([^/?#:]+)/i.exec(url)?.[1]?.replace(/^www\\./, '') ?? 'that site';\n\n/** \"team-bhp.com/…/cover.jpg\" */\nexport function linkLabel(url: string): string {\n const m = /^https?:\\/\\/([^/?#]+)([^?#]*)/i.exec(url);\n if (!m) return url.length > 60 ? `${url.slice(0, 59)}…` : url;\n const host = m[1].replace(/^www\\./, '');\n const segments = m[2].split('/').filter(Boolean);\n const last = segments[segments.length - 1] ?? '';\n if (!last) return host;\n const name = last.length > 40 ? `${last.slice(0, 39)}…` : last;\n return segments.length > 1 ? `${host}/…/${name}` : `${host}/${name}`;\n}\n\n/** The lane a response's type puts it in, or null for anything that is not media. */\nexport function linkMediaKind(contentType: string, url = ''): LinkMediaKind | null {\n const mime = contentType.split(';')[0].trim().toLowerCase();\n if (mime.startsWith('image/') && mime !== 'image/svg+xml') return 'image';\n if (mime.startsWith('video/')) return 'video';\n if (mime.startsWith('audio/')) return 'audio';\n if (!mime || mime === 'application/octet-stream' || mime === 'binary/octet-stream') {\n const path = url.split(/[?#]/)[0].toLowerCase();\n if (/\\.(png|jpe?g|gif|webp|avif|heic|heif|bmp|tiff?)$/.test(path)) return 'image';\n if (/\\.(mp4|mov|m4v|webm|mkv)$/.test(path)) return 'video';\n if (/\\.(mp3|wav|m4a|aac|ogg|flac)$/.test(path)) return 'audio';\n }\n return null;\n}\n\nfunction decodeEntities(v: string): string {\n return v\n .replace(/&/g, '&')\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n\n/** Resolve a (possibly relative) URL against a page, http(s) only. */\nfunction absolute(u: string | undefined, pageUrl: string): string | undefined {\n if (!u) return undefined;\n const v = decodeEntities(u.trim());\n if (/^https?:\\/\\//i.test(v)) return v;\n if (v.startsWith('//')) return `https:${v}`;\n const origin = /^(https?:\\/\\/[^/?#]+)/i.exec(pageUrl)?.[1];\n if (!origin) return undefined;\n if (v.startsWith('/')) return `${origin}${v}`;\n const base = pageUrl.replace(/[?#].*$/, '').replace(/[^/]*$/, '');\n return `${base}${v}`;\n}\n\nconst DIRECT_VIDEO = /\\.(mp4|mov|m4v|webm)(?:$|[?#])/i;\n\n/** The media a page names for link previews, best first (regex read - no DOM on the phone). */\nexport function pageMedia(html: string, pageUrl: string): { url: string; kind: LinkMediaKind; title?: string } | null {\n const metas = [...html.matchAll(/<meta\\b[^>]*>/gi)].map((m) => m[0]);\n const attr = (tag: string, name: string) =>\n new RegExp(`\\\\b${name}\\\\s*=\\\\s*(\"([^\"]*)\"|'([^']*)')`, 'i')\n .exec(tag)\n ?.slice(2)\n .find((x) => x !== undefined);\n const meta = (...names: string[]): string | undefined => {\n for (const name of names) {\n const tag = metas.find((t) => (attr(t, 'property') ?? attr(t, 'name'))?.toLowerCase() === name);\n const content = tag ? attr(tag, 'content')?.trim() : undefined;\n if (content) return content;\n }\n return undefined;\n };\n const titleTag = /<title[^>]*>([^<]*)<\\/title>/i.exec(html)?.[1]?.trim();\n const title = decodeEntities(meta('og:title', 'twitter:title') ?? titleTag ?? '') || undefined;\n const videoType = meta('og:video:type') ?? '';\n const video = absolute(meta('og:video:secure_url', 'og:video:url', 'og:video', 'twitter:player:stream'), pageUrl);\n if (video && (/^video\\//i.test(videoType) || DIRECT_VIDEO.test(video))) return { url: video, kind: 'video', title };\n const image = absolute(\n meta('og:image:secure_url', 'og:image:url', 'og:image', 'twitter:image', 'twitter:image:src'),\n pageUrl,\n );\n return image ? { url: image, kind: 'image', title } : null;\n}\n\nconst EXT: Record<string, string> = {\n 'image/jpeg': 'jpg',\n 'image/png': 'png',\n 'image/webp': 'webp',\n 'image/gif': 'gif',\n 'image/avif': 'avif',\n 'video/mp4': 'mp4',\n 'video/webm': 'webm',\n 'video/quicktime': 'mov',\n 'audio/mpeg': 'mp3',\n 'audio/wav': 'wav',\n 'audio/mp4': 'm4a',\n};\n\n/** A library name: the page title or the URL's last segment, with the type's extension. */\nexport function linkFileName(url: string, mimeType: string, title?: string): string {\n const ext = EXT[mimeType.split(';')[0].trim().toLowerCase()] ?? '';\n let base = (title ?? '').replace(/\\s+/g, ' ').trim();\n if (!base) {\n const path = /^https?:\\/\\/([^/?#]+)([^?#]*)/i.exec(url);\n let last = path?.[2].split('/').filter(Boolean).pop() ?? '';\n try {\n last = decodeURIComponent(last);\n } catch {\n // keep it encoded\n }\n base = last || path?.[1] || 'link';\n }\n base =\n base\n .replace(/[\\\\/:*?\"<>|#%{}^~[\\]`]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim()\n .slice(0, 60)\n .trim() || 'link';\n if (!ext || base.toLowerCase().endsWith(`.${ext}`)) return base;\n return `${base.replace(/\\.(jpe?g|png|webp|gif|avif|heic|bmp|tiff?|mp4|m4v|mov|webm|mp3|wav|m4a|aac|ogg)$/i, '')}.${ext}`;\n}\n\n/** The connector's failure as a sentence about the link. */\nexport function linkFailureMessage(url: string, err: unknown): string {\n const raw = err instanceof Error ? err.message : String(err ?? '');\n const host = hostOf(url);\n const paste = 'Save the picture to Photos and attach it instead.';\n if (/just a moment|cf-mitigated|captcha|challenge|attention required|access denied/i.test(raw)) {\n return `${host} only shows this to a person in a browser, so it cannot be fetched. ${paste}`;\n }\n const status = /HTTP (\\d{3})/.exec(raw)?.[1];\n if (status === '401' || status === '403' || status === '429')\n return `${host} refused the download (HTTP ${status}). ${paste}`;\n if (status === '404' || status === '410') return `Nothing is at that link on ${host} (HTTP ${status}).`;\n if (/over the \\d+-byte limit|too large/i.test(raw))\n return 'The file at that link is over 25 MB. Download it and attach it instead.';\n if (/timed out|timeout/i.test(raw)) return `${host} took too long to answer.`;\n if (/https|public|private|loopback|not allowed|blocked/i.test(raw)) return 'Only public web links can be taken in.';\n if (status) return `${host} answered HTTP ${status}.`;\n return `${host} could not be reached.`;\n}\n\nexport class LinkImportError extends Error {\n readonly url: string;\n constructor(url: string, message: string) {\n super(message);\n this.name = 'LinkImportError';\n this.url = url;\n }\n}\n\nexport interface FetchedLink {\n status: number;\n url: string;\n contentType: string;\n bodyBase64?: string;\n bodyText?: string;\n}\n\nexport interface ImportedLink {\n url: string;\n src: string;\n kind: LinkMediaKind;\n mimeType: string;\n name: string;\n via?: string;\n}\n\n/** One GET through the agent's guarded HTTP lane. */\nexport async function fetchLinkViaAgent(run: RunMediaAction, url: string, accept: string): Promise<FetchedLink> {\n const result = await run('yantra-storage', 'YANTRA_STORAGE_HTTP_SEND', {\n url,\n method: 'GET',\n headers: { 'User-Agent': BROWSER_UA, Accept: accept, 'Accept-Language': 'en-US,en;q=0.9' },\n responseType: 'auto',\n maxBytes: LINK_MAX_BYTES,\n timeoutMs: FETCH_TIMEOUT_MS,\n });\n if (result.successful === false) throw new Error(String(result.error ?? 'the request failed'));\n const data = (\n result.bodyBase64 !== undefined || result.bodyText !== undefined ? result : (result.data ?? result)\n ) as Record<string, unknown>;\n const status = Number(data.status) || 0;\n if (status >= 400) throw new Error(`HTTP ${status}`);\n return {\n status,\n url: typeof data.url === 'string' && data.url ? data.url : url,\n contentType: typeof data.contentType === 'string' ? data.contentType : '',\n bodyBase64: typeof data.bodyBase64 === 'string' ? data.bodyBase64 : undefined,\n bodyText: typeof data.bodyText === 'string' ? data.bodyText : undefined,\n };\n}\n\nexport interface LinkImportDeps {\n fetchUrl: (url: string, accept: string) => Promise<FetchedLink>;\n /** Store bytes given as a data: URL; resolves to the hosted URL (the host uploadMedia seam). */\n upload: (dataUrl: string, name: string) => Promise<string>;\n}\n\n/** Take one link in: fetch it, follow a page to its media, store the bytes. Throws LinkImportError. */\nexport async function importLink(url: string, deps: LinkImportDeps): Promise<ImportedLink> {\n const fetchMedia = async (target: string, accept: string): Promise<FetchedLink> => {\n try {\n return await deps.fetchUrl(target, accept);\n } catch (err) {\n throw new LinkImportError(url, linkFailureMessage(target, err));\n }\n };\n let res = await fetchMedia(url, ACCEPT_ANY);\n let kind = linkMediaKind(res.contentType, res.url);\n let via: string | undefined;\n let title: string | undefined;\n if (!kind) {\n if (!res.bodyText || !/html/i.test(res.contentType)) {\n throw new LinkImportError(\n url,\n `That link is ${res.contentType.split(';')[0] || 'not a file'}, not a picture, video or sound.`,\n );\n }\n const found = pageMedia(res.bodyText, res.url);\n if (!found) throw new LinkImportError(url, `The page at ${hostOf(url)} names no picture or video to take.`);\n via = found.url;\n title = found.title;\n res = await fetchMedia(found.url, ACCEPT_MEDIA);\n kind = linkMediaKind(res.contentType, res.url);\n if (!kind)\n throw new LinkImportError(\n url,\n `The picture that page points to (${hostOf(found.url)}) did not come back as one.`,\n );\n }\n if (!res.bodyBase64) throw new LinkImportError(url, `${hostOf(url)} sent an empty file.`);\n const mimeType = res.contentType.split(';')[0].trim().toLowerCase() || `${kind}/*`;\n const name = linkFileName(via ?? res.url, mimeType, title);\n const src = await deps.upload(`data:${mimeType};base64,${res.bodyBase64}`, name);\n return { url, src, kind, mimeType, name, ...(via ? { via } : {}) };\n}\n\nexport interface LinkIntakeDeps extends LinkImportDeps {\n /** Put the item in the library; returns the id it got. */\n addAsset: (asset: { type: LinkMediaKind; src: string; name: string; sourceUrl: string }) => string;\n /** The library item a link was already taken in as. */\n existing?: (url: string) => { id: string; type: LinkMediaKind; src: string; name: string } | undefined;\n}\n\n/** Take the links of a message in as library media; a failure is recorded with why, never thrown. */\nexport async function intakeLinks(links: readonly string[], deps: LinkIntakeDeps): Promise<AgentAttachment[]> {\n const out: AgentAttachment[] = [];\n for (const link of links) {\n const known = deps.existing?.(link);\n if (known) {\n out.push({ name: known.name, kind: known.type, link, assetId: known.id, src: known.src });\n continue;\n }\n try {\n const got = await importLink(link, deps);\n const assetId = deps.addAsset({ type: got.kind, src: got.src, name: got.name, sourceUrl: link });\n out.push({ name: got.name, kind: got.kind, link, assetId, src: got.src });\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n out.push({ name: linkLabel(link), kind: 'unusable', link, reason });\n }\n }\n return out;\n}\n\n/** What the model reads about a message's attachments: one line each, with the id it can use. */\nexport function attachmentBlock(attachments: readonly AgentAttachment[]): string {\n if (attachments.length === 0) return '';\n const lines = attachments.map((a) => {\n const what = (kind: string) => (a.link ? `${kind} from link ${a.link} (\"${a.name}\")` : `${kind} \"${a.name}\"`);\n if (a.kind === 'image')\n return `- ${what('image')} is library item id=${a.assetId} · shown to you with this message`;\n if (a.kind === 'video' || a.kind === 'audio') return `- ${what(a.kind)} is library item id=${a.assetId}`;\n return a.link\n ? `- link ${a.link} could not be taken in: ${a.reason ?? 'unreadable'}`\n : `- \"${a.name}\" could not be used: ${a.reason ?? 'unreadable'}`;\n });\n return `${ATTACHMENT_BLOCK_HEADER}\\n${lines.join('\\n')}`;\n}\n\n/**\n * The user turn's content: the words plus the attachment block, and every\n * attached picture as an `image_url` part so the model sees it. Plain text\n * when nothing was attached.\n */\nexport function userContent(text: string, attachments: readonly AgentAttachment[] = []): string | BrainContentPart[] {\n const block = attachmentBlock(attachments);\n const words = block ? [text.trim(), block].filter(Boolean).join('\\n\\n') : text;\n const images = attachments.filter((a) => a.kind === 'image' && a.src && /^https?:\\/\\//i.test(a.src));\n if (!images.length) return words;\n return [\n { type: 'text', text: words },\n ...images.map((a) => ({ type: 'image_url' as const, image_url: { url: a.src! } })),\n ];\n}\n"],"names":["_a","_b"],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ var __spreadValues = (a, b) => {
|
|
|
14
14
|
}
|
|
15
15
|
return a;
|
|
16
16
|
};
|
|
17
|
+
const BRAIN_SMART_MODEL = "yantra-brain/smart";
|
|
17
18
|
async function brainChat(args) {
|
|
18
19
|
var _a, _b, _c;
|
|
19
20
|
const resp = await fetch(`${args.agentEndpoint}/v1/yantra-brain/chat/completions`, {
|
|
@@ -23,7 +24,7 @@ async function brainChat(args) {
|
|
|
23
24
|
authorization: `Bearer ${args.token}`
|
|
24
25
|
},
|
|
25
26
|
body: JSON.stringify(__spreadValues({
|
|
26
|
-
model: args.model ||
|
|
27
|
+
model: args.model || BRAIN_SMART_MODEL,
|
|
27
28
|
messages: args.messages
|
|
28
29
|
}, ((_a = args.tools) == null ? void 0 : _a.length) ? {
|
|
29
30
|
tools: args.tools,
|
|
@@ -42,4 +43,4 @@ async function brainChat(args) {
|
|
|
42
43
|
content,
|
|
43
44
|
tool_calls
|
|
44
45
|
};
|
|
45
|
-
}export{brainChat};//# sourceMappingURL=brainClient.js.map
|
|
46
|
+
}export{BRAIN_SMART_MODEL,brainChat};//# sourceMappingURL=brainClient.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brainClient.js","sources":["../../../../../src/features/canvas/videoEditor/agent/brainClient.ts"],"sourcesContent":["/** Brain chat transport for the studio agent (gateway /v1/yantra-brain). */\nexport interface BrainMessage {\n role: 'system' | 'user' | 'assistant' | 'tool';\n content: string;\n tool_call_id?: string;\n name?: string;\n}\n\nexport interface BrainTool {\n type: 'function';\n function: { name: string; description: string; parameters: Record<string, unknown> };\n}\n\nexport interface BrainToolCall {\n id: string;\n type: 'function';\n function: { name: string; arguments: string };\n}\n\nexport interface BrainReply {\n content: string;\n tool_calls?: BrainToolCall[];\n}\n\nexport type BrainChat = (args: {\n messages: BrainMessage[];\n tools?: BrainTool[];\n model?: string;\n token: string;\n agentEndpoint: string;\n}) => Promise<BrainReply>;\n\nexport async function brainChat(args: {\n messages: BrainMessage[];\n tools?: BrainTool[];\n model?: string;\n token: string;\n agentEndpoint: string;\n}): Promise<BrainReply> {\n const resp = await fetch(`${args.agentEndpoint}/v1/yantra-brain/chat/completions`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n authorization: `Bearer ${args.token}`,\n },\n body: JSON.stringify({\n model: args.model ||
|
|
1
|
+
{"version":3,"file":"brainClient.js","sources":["../../../../../src/features/canvas/videoEditor/agent/brainClient.ts"],"sourcesContent":["/** Brain chat transport for the studio agent (gateway /v1/yantra-brain). */\n\n/** Gateway tier alias (web `editors/shared/brainClient.ts`); resolves server-side. */\nexport const BRAIN_SMART_MODEL = 'yantra-brain/smart';\n/** OpenAI-style multimodal part: a user message can carry pictures as `image_url` parts. */\nexport type BrainContentPart = { type: 'text'; text: string } | { type: 'image_url'; image_url: { url: string } };\n\nexport interface BrainMessage {\n role: 'system' | 'user' | 'assistant' | 'tool';\n /** Plain text, or (user turns) text + image parts. */\n content: string | BrainContentPart[];\n tool_call_id?: string;\n name?: string;\n}\n\n/** The text of a message, whichever shape its content has. */\nexport function messageText(content: BrainMessage['content']): string {\n if (typeof content === 'string') return content;\n return content\n .filter((p): p is Extract<BrainContentPart, { type: 'text' }> => p.type === 'text')\n .map((p) => p.text)\n .join('\\n');\n}\n\nexport interface BrainTool {\n type: 'function';\n function: { name: string; description: string; parameters: Record<string, unknown> };\n}\n\nexport interface BrainToolCall {\n id: string;\n type: 'function';\n function: { name: string; arguments: string };\n}\n\nexport interface BrainReply {\n content: string;\n tool_calls?: BrainToolCall[];\n}\n\nexport type BrainChat = (args: {\n messages: BrainMessage[];\n tools?: BrainTool[];\n model?: string;\n token: string;\n agentEndpoint: string;\n}) => Promise<BrainReply>;\n\nexport async function brainChat(args: {\n messages: BrainMessage[];\n tools?: BrainTool[];\n model?: string;\n token: string;\n agentEndpoint: string;\n}): Promise<BrainReply> {\n const resp = await fetch(`${args.agentEndpoint}/v1/yantra-brain/chat/completions`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n authorization: `Bearer ${args.token}`,\n },\n body: JSON.stringify({\n model: args.model || BRAIN_SMART_MODEL,\n messages: args.messages,\n ...(args.tools?.length ? { tools: args.tools, tool_choice: 'auto' } : {}),\n }),\n });\n const json = (await resp.json().catch(() => ({}))) as Record<string, unknown>;\n if (!resp.ok) {\n throw new Error(typeof json.error === 'string' ? json.error : `Brain chat failed (HTTP ${resp.status})`);\n }\n const choices = json.choices as Array<{ message?: Record<string, unknown> }> | undefined;\n const message = choices?.[0]?.message ?? {};\n const content = typeof message.content === 'string' ? message.content : '';\n const tool_calls = Array.isArray(message.tool_calls) ? (message.tool_calls as BrainToolCall[]) : undefined;\n return { content, tool_calls };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAGO,MAAM,iBAAoB,GAAA;AAqDjC,eAAsB,UAAU,IAMR,EAAA;AA9DxB,EAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA;AA+DE,EAAA,MAAM,OAAO,MAAM,KAAA,CAAM,CAAG,EAAA,IAAA,CAAK,aAAa,CAAqC,iCAAA,CAAA,EAAA;AAAA,IACjF,MAAQ,EAAA,MAAA;AAAA,IACR,OAAS,EAAA;AAAA,MACP,cAAgB,EAAA,kBAAA;AAAA,MAChB,aAAA,EAAe,CAAU,OAAA,EAAA,IAAA,CAAK,KAAK,CAAA;AAAA,KACrC;AAAA,IACA,IAAA,EAAM,KAAK,SAAU,CAAA,cAAA,CAAA;AAAA,MACnB,KAAA,EAAO,KAAK,KAAS,IAAA,iBAAA;AAAA,MACrB,UAAU,IAAK,CAAA;AAAA,KACX,EAAA,CAAA,CAAA,EAAA,GAAA,IAAA,CAAK,KAAL,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAY,MAAS,IAAA;AAAA,MACvB,OAAO,IAAK,CAAA,KAAA;AAAA,MACZ,WAAa,EAAA;AAAA,KACf,GAAI,EACL,CAAA;AAAA,GACF,CAAA;AACD,EAAM,MAAA,IAAA,GAAQ,MAAM,IAAK,CAAA,IAAA,GAAO,KAAM,CAAA,OAAO,EAAG,CAAA,CAAA;AAChD,EAAI,IAAA,CAAC,KAAK,EAAI,EAAA;AACZ,IAAM,MAAA,IAAI,KAAM,CAAA,OAAO,IAAK,CAAA,KAAA,KAAU,QAAW,GAAA,IAAA,CAAK,KAAQ,GAAA,CAAA,wBAAA,EAA2B,IAAK,CAAA,MAAM,CAAG,CAAA,CAAA,CAAA;AAAA;AAEzG,EAAA,MAAM,UAAU,IAAK,CAAA,OAAA;AAGrB,EAAA,MAAM,WAAU,EAAU,GAAA,CAAA,EAAA,GAAA,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAA,CAAA,CAAA,KAAV,IAAc,GAAA,MAAA,GAAA,EAAA,CAAA,OAAA,KAAd,YAAyB,EAAC;AAC1C,EAAA,MAAM,UAAU,OAAO,OAAA,CAAQ,OAAY,KAAA,QAAA,GAAW,QAAQ,OAAU,GAAA,EAAA;AACxE,EAAA,MAAM,aAAa,KAAM,CAAA,OAAA,CAAQ,QAAQ,UAAU,CAAA,GAAI,QAAQ,UAAgC,GAAA,MAAA;AAC/F,EAAO,OAAA;AAAA,IACL,OAAA;AAAA,IACA;AAAA,GACF;AACF"}
|
|
@@ -1,4 +1,28 @@
|
|
|
1
|
-
import {removeClip,moveClip,updateClip}from'../editorModel.js';
|
|
1
|
+
import {removeClip,moveClip,updateClip,clipFromColor,textClipAt}from'../editorModel.js';import {sceneSpans}from'../sceneLayers.js';var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
const SHOT_SEC_RANGE = {
|
|
21
|
+
min: 2,
|
|
22
|
+
max: 15,
|
|
23
|
+
default: 6
|
|
24
|
+
};
|
|
25
|
+
const CUT_AGENT_TOOLS = [{
|
|
2
26
|
type: "function",
|
|
3
27
|
function: {
|
|
4
28
|
name: "get_timeline",
|
|
@@ -66,21 +90,98 @@ import {removeClip,moveClip,updateClip}from'../editorModel.js';const CUT_AGENT_T
|
|
|
66
90
|
required: ["id"]
|
|
67
91
|
}
|
|
68
92
|
}
|
|
93
|
+
}, {
|
|
94
|
+
type: "function",
|
|
95
|
+
function: {
|
|
96
|
+
name: "add_scene",
|
|
97
|
+
description: "Add a scene for the AI video model to FILM: a colour scene carrying its shot (picture only - subject, setting, action, light, camera move; no on-screen text). Optional title is laid on it. Then call film_scenes. Returns the scene id.",
|
|
98
|
+
parameters: {
|
|
99
|
+
type: "object",
|
|
100
|
+
properties: {
|
|
101
|
+
shot: {
|
|
102
|
+
type: "string"
|
|
103
|
+
},
|
|
104
|
+
seconds: {
|
|
105
|
+
type: "number",
|
|
106
|
+
description: "How long it plays (default 6, 2-15)."
|
|
107
|
+
},
|
|
108
|
+
title: {
|
|
109
|
+
type: "string",
|
|
110
|
+
description: "On-screen title for this scene."
|
|
111
|
+
},
|
|
112
|
+
index: {
|
|
113
|
+
type: "integer",
|
|
114
|
+
description: "Position in the cut (default: the end)."
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
required: ["shot"]
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}, {
|
|
121
|
+
type: "function",
|
|
122
|
+
function: {
|
|
123
|
+
name: "add_text",
|
|
124
|
+
description: "Lay a title on a scene (it moves with the scene). Times are seconds from the scene start.",
|
|
125
|
+
parameters: {
|
|
126
|
+
type: "object",
|
|
127
|
+
properties: {
|
|
128
|
+
scene_id: {
|
|
129
|
+
type: "string"
|
|
130
|
+
},
|
|
131
|
+
text: {
|
|
132
|
+
type: "string"
|
|
133
|
+
},
|
|
134
|
+
at_sec: {
|
|
135
|
+
type: "number"
|
|
136
|
+
},
|
|
137
|
+
seconds: {
|
|
138
|
+
type: "number"
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
required: ["scene_id", "text"]
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}, {
|
|
145
|
+
type: "function",
|
|
146
|
+
function: {
|
|
147
|
+
name: "film_scenes",
|
|
148
|
+
description: "Film scenes that have a shot with the AI video model. Starts the filming and returns at once; each clip lands in its scene a few minutes later, keeping the scene's length and titles. Default: every colour scene with a shot.",
|
|
149
|
+
parameters: {
|
|
150
|
+
type: "object",
|
|
151
|
+
properties: {
|
|
152
|
+
scene_ids: {
|
|
153
|
+
type: "array",
|
|
154
|
+
items: {
|
|
155
|
+
type: "string"
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
69
161
|
}];
|
|
70
162
|
async function executeCutTool(name, rawArgs, ctx) {
|
|
163
|
+
var _a, _b;
|
|
71
164
|
const args = rawArgs && typeof rawArgs === "object" ? rawArgs : {};
|
|
72
165
|
if (name === "get_timeline") {
|
|
73
166
|
const t = ctx.getTimeline();
|
|
167
|
+
const spans = sceneSpans(t.clips);
|
|
74
168
|
const rows = t.clips.map((c, i) => {
|
|
75
|
-
var
|
|
76
|
-
return {
|
|
169
|
+
var _a2;
|
|
170
|
+
return __spreadProps(__spreadValues(__spreadValues({
|
|
77
171
|
index: i,
|
|
78
172
|
id: c.id,
|
|
79
|
-
|
|
173
|
+
kind: c.fillColor ? c.shot ? "shot to film" : "colour scene" : c.type
|
|
174
|
+
}, c.fillColor ? {} : {
|
|
175
|
+
src: (_a2 = c.src) == null ? void 0 : _a2.slice(0, 80)
|
|
176
|
+
}), c.shot ? {
|
|
177
|
+
shot: c.shot.slice(0, 160)
|
|
178
|
+
} : {}), {
|
|
179
|
+
startSec: Math.round(spans[i].startSec * 10) / 10,
|
|
80
180
|
durationSec: c.durationSec,
|
|
81
181
|
trimStartSec: c.trimStartSec,
|
|
82
|
-
trimEndSec: c.trimEndSec
|
|
83
|
-
|
|
182
|
+
trimEndSec: c.trimEndSec,
|
|
183
|
+
titles: t.texts.filter((x) => x.sceneId === c.id).map((x) => x.text)
|
|
184
|
+
});
|
|
84
185
|
});
|
|
85
186
|
return {
|
|
86
187
|
ok: true,
|
|
@@ -121,9 +222,108 @@ async function executeCutTool(name, rawArgs, ctx) {
|
|
|
121
222
|
content: "ok"
|
|
122
223
|
};
|
|
123
224
|
}
|
|
225
|
+
if (name === "add_scene") {
|
|
226
|
+
const shot = typeof args.shot === "string" ? args.shot.trim() : "";
|
|
227
|
+
if (!shot) return {
|
|
228
|
+
ok: false,
|
|
229
|
+
label: "Add scene",
|
|
230
|
+
content: "error: a scene to film needs a shot"
|
|
231
|
+
};
|
|
232
|
+
const asked = typeof args.seconds === "number" ? args.seconds : SHOT_SEC_RANGE.default;
|
|
233
|
+
const seconds = Math.min(SHOT_SEC_RANGE.max, Math.max(SHOT_SEC_RANGE.min, asked));
|
|
234
|
+
const t = ctx.getTimeline();
|
|
235
|
+
const scene = __spreadProps(__spreadValues({}, clipFromColor("#101014")), {
|
|
236
|
+
name: shot.slice(0, 32),
|
|
237
|
+
shot,
|
|
238
|
+
durationSec: seconds
|
|
239
|
+
});
|
|
240
|
+
const index = typeof args.index === "number" && args.index >= 0 && args.index <= t.clips.length ? Math.floor(args.index) : t.clips.length;
|
|
241
|
+
const clips = [...t.clips];
|
|
242
|
+
clips.splice(index, 0, scene);
|
|
243
|
+
let next = __spreadProps(__spreadValues({}, t), {
|
|
244
|
+
clips
|
|
245
|
+
});
|
|
246
|
+
const title = typeof args.title === "string" ? args.title.trim() : "";
|
|
247
|
+
if (title) {
|
|
248
|
+
const start = (_b = (_a = sceneSpans(clips).find((s) => s.id === scene.id)) == null ? void 0 : _a.startSec) != null ? _b : 0;
|
|
249
|
+
const text = __spreadProps(__spreadValues({}, textClipAt(start, {
|
|
250
|
+
text: title,
|
|
251
|
+
x: 0.5,
|
|
252
|
+
y: 0.5
|
|
253
|
+
})), {
|
|
254
|
+
durationSec: Math.min(3, seconds),
|
|
255
|
+
sceneId: scene.id
|
|
256
|
+
});
|
|
257
|
+
next = __spreadProps(__spreadValues({}, next), {
|
|
258
|
+
texts: [...next.texts, text]
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
ctx.setTimeline(next);
|
|
262
|
+
const note = seconds !== asked ? ` (a scene to film runs ${SHOT_SEC_RANGE.min}-${SHOT_SEC_RANGE.max}s, used ${seconds}s)` : "";
|
|
263
|
+
return {
|
|
264
|
+
ok: true,
|
|
265
|
+
label: `Added scene \xB7 ${shot.slice(0, 32)}`,
|
|
266
|
+
content: JSON.stringify({
|
|
267
|
+
scene_id: scene.id
|
|
268
|
+
}) + note
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
if (name === "add_text") {
|
|
272
|
+
const t = ctx.getTimeline();
|
|
273
|
+
const sceneId = typeof args.scene_id === "string" ? args.scene_id : "";
|
|
274
|
+
const span = sceneSpans(t.clips).find((s) => s.id === sceneId);
|
|
275
|
+
const words = typeof args.text === "string" ? args.text.trim() : "";
|
|
276
|
+
if (!span || !words) return {
|
|
277
|
+
ok: false,
|
|
278
|
+
label: "Add text",
|
|
279
|
+
content: "error: needs a scene_id from get_timeline and text"
|
|
280
|
+
};
|
|
281
|
+
const len = Math.max(0.5, span.endSec - span.startSec);
|
|
282
|
+
const at = Math.min(len - 0.5, Math.max(0, typeof args.at_sec === "number" ? args.at_sec : 0));
|
|
283
|
+
const seconds = Math.min(len - at, Math.max(0.5, typeof args.seconds === "number" ? args.seconds : len - at));
|
|
284
|
+
const text = __spreadProps(__spreadValues({}, textClipAt(span.startSec + at, {
|
|
285
|
+
text: words,
|
|
286
|
+
x: 0.5,
|
|
287
|
+
y: 0.5
|
|
288
|
+
})), {
|
|
289
|
+
durationSec: seconds,
|
|
290
|
+
sceneId
|
|
291
|
+
});
|
|
292
|
+
ctx.setTimeline(__spreadProps(__spreadValues({}, t), {
|
|
293
|
+
texts: [...t.texts, text]
|
|
294
|
+
}));
|
|
295
|
+
return {
|
|
296
|
+
ok: true,
|
|
297
|
+
label: `Title \xB7 ${words.slice(0, 24)}`,
|
|
298
|
+
content: JSON.stringify({
|
|
299
|
+
text_id: text.id
|
|
300
|
+
})
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
if (name === "film_scenes") {
|
|
304
|
+
if (!ctx.film) return {
|
|
305
|
+
ok: false,
|
|
306
|
+
label: "Film scenes",
|
|
307
|
+
content: "error: filming is not available here"
|
|
308
|
+
};
|
|
309
|
+
const t = ctx.getTimeline();
|
|
310
|
+
const asked = Array.isArray(args.scene_ids) ? args.scene_ids.filter((x) => typeof x === "string") : [];
|
|
311
|
+
const ids = (asked.length ? asked : t.clips.filter((c) => c.fillColor && c.shot).map((c) => c.id)).filter((id) => t.clips.some((c) => c.id === id));
|
|
312
|
+
if (!ids.length) return {
|
|
313
|
+
ok: false,
|
|
314
|
+
label: "Film scenes",
|
|
315
|
+
content: "error: no scene with a shot to film"
|
|
316
|
+
};
|
|
317
|
+
ctx.film(ids);
|
|
318
|
+
return {
|
|
319
|
+
ok: true,
|
|
320
|
+
label: `Filming ${ids.length} scene${ids.length === 1 ? "" : "s"}`,
|
|
321
|
+
content: `filming ${ids.length} scene(s); each lands in place in a few minutes`
|
|
322
|
+
};
|
|
323
|
+
}
|
|
124
324
|
return {
|
|
125
325
|
ok: false,
|
|
126
326
|
label: name,
|
|
127
327
|
content: `Unknown tool ${name}`
|
|
128
328
|
};
|
|
129
|
-
}export{CUT_AGENT_TOOLS,executeCutTool};//# sourceMappingURL=cutTools.js.map
|
|
329
|
+
}export{CUT_AGENT_TOOLS,SHOT_SEC_RANGE,executeCutTool};//# sourceMappingURL=cutTools.js.map
|