@adminide-stack/yantra-mobile 12.0.121 → 12.0.123-alpha.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.
Files changed (175) hide show
  1. package/lib/features/apps/appArt.js +1 -1
  2. package/lib/features/apps/appArt.js.map +1 -1
  3. package/lib/features/apps/mobileAppCatalog.js +15 -11
  4. package/lib/features/apps/mobileAppCatalog.js.map +1 -1
  5. package/lib/features/canvas/CanvasAgentChatPane.js +82 -20
  6. package/lib/features/canvas/CanvasAgentChatPane.js.map +1 -1
  7. package/lib/features/canvas/CanvasBoardsGrid.js +291 -100
  8. package/lib/features/canvas/CanvasBoardsGrid.js.map +1 -1
  9. package/lib/features/canvas/CanvasEditToolsPanel.js +105 -12
  10. package/lib/features/canvas/CanvasEditToolsPanel.js.map +1 -1
  11. package/lib/features/canvas/CanvasExperience.js +266 -68
  12. package/lib/features/canvas/CanvasExperience.js.map +1 -1
  13. package/lib/features/canvas/CanvasGeneratePanel.js +204 -66
  14. package/lib/features/canvas/CanvasGeneratePanel.js.map +1 -1
  15. package/lib/features/canvas/CanvasLibrarySheet.js +31 -13
  16. package/lib/features/canvas/CanvasLibrarySheet.js.map +1 -1
  17. package/lib/features/canvas/CanvasModelPicker.js +176 -0
  18. package/lib/features/canvas/CanvasModelPicker.js.map +1 -0
  19. package/lib/features/canvas/CanvasTasksPanel.js +325 -29
  20. package/lib/features/canvas/CanvasTasksPanel.js.map +1 -1
  21. package/lib/features/canvas/CanvasTemplatesPanel.js +5 -4
  22. package/lib/features/canvas/CanvasTemplatesPanel.js.map +1 -1
  23. package/lib/features/canvas/CanvasToolDock.js +137 -61
  24. package/lib/features/canvas/CanvasToolDock.js.map +1 -1
  25. package/lib/features/canvas/FrameExtractorExperience.js +33 -2
  26. package/lib/features/canvas/FrameExtractorExperience.js.map +1 -1
  27. package/lib/features/canvas/GeneratorReferenceSlots.js +197 -0
  28. package/lib/features/canvas/GeneratorReferenceSlots.js.map +1 -0
  29. package/lib/features/canvas/NativeCanvasViewer.js +89 -11
  30. package/lib/features/canvas/NativeCanvasViewer.js.map +1 -1
  31. package/lib/features/canvas/PromoContextFields.js +55 -2
  32. package/lib/features/canvas/PromoContextFields.js.map +1 -1
  33. package/lib/features/canvas/SetStudioExperience.js +323 -13
  34. package/lib/features/canvas/SetStudioExperience.js.map +1 -1
  35. package/lib/features/canvas/VideoEditExperience.js +1 -53
  36. package/lib/features/canvas/VideoEditExperience.js.map +1 -1
  37. package/lib/features/canvas/VideoEditorExperience.js +697 -506
  38. package/lib/features/canvas/VideoEditorExperience.js.map +1 -1
  39. package/lib/features/canvas/VideoGeneratorExperience.js +22 -5
  40. package/lib/features/canvas/VideoGeneratorExperience.js.map +1 -1
  41. package/lib/features/canvas/canvasAgentChat.js +125 -11
  42. package/lib/features/canvas/canvasAgentChat.js.map +1 -1
  43. package/lib/features/canvas/canvasCore.js +117 -12
  44. package/lib/features/canvas/canvasCore.js.map +1 -1
  45. package/lib/features/canvas/canvasEditOps.js +148 -111
  46. package/lib/features/canvas/canvasEditOps.js.map +1 -1
  47. package/lib/features/canvas/canvasTaskSync.js +235 -0
  48. package/lib/features/canvas/canvasTaskSync.js.map +1 -0
  49. package/lib/features/canvas/canvasTasks.js +98 -11
  50. package/lib/features/canvas/canvasTasks.js.map +1 -1
  51. package/lib/features/canvas/createTiles.js +247 -0
  52. package/lib/features/canvas/createTiles.js.map +1 -0
  53. package/lib/features/canvas/deepLinks.js +83 -0
  54. package/lib/features/canvas/deepLinks.js.map +1 -0
  55. package/lib/features/canvas/frameExtract.js +13 -1
  56. package/lib/features/canvas/frameExtract.js.map +1 -1
  57. package/lib/features/canvas/generationModels.js +36 -8
  58. package/lib/features/canvas/generationModels.js.map +1 -1
  59. package/lib/features/canvas/generatorCommands.js +106 -0
  60. package/lib/features/canvas/generatorCommands.js.map +1 -0
  61. package/lib/features/canvas/generatorReferences.js +82 -0
  62. package/lib/features/canvas/generatorReferences.js.map +1 -0
  63. package/lib/features/canvas/homeWork.js +74 -0
  64. package/lib/features/canvas/homeWork.js.map +1 -0
  65. package/lib/features/canvas/linksRpc.js +130 -0
  66. package/lib/features/canvas/linksRpc.js.map +1 -0
  67. package/lib/features/canvas/mediaRecheck.js +176 -0
  68. package/lib/features/canvas/mediaRecheck.js.map +1 -0
  69. package/lib/features/canvas/mediaUrls.js +258 -0
  70. package/lib/features/canvas/mediaUrls.js.map +1 -0
  71. package/lib/features/canvas/nativeViewerRegistry.js.map +1 -1
  72. package/lib/features/canvas/promoProjectImport.js +80 -13
  73. package/lib/features/canvas/promoProjectImport.js.map +1 -1
  74. package/lib/features/canvas/promoVideo.js +106 -15
  75. package/lib/features/canvas/promoVideo.js.map +1 -1
  76. package/lib/features/canvas/reframe.js +228 -0
  77. package/lib/features/canvas/reframe.js.map +1 -0
  78. package/lib/features/canvas/serverTasks.js +697 -0
  79. package/lib/features/canvas/serverTasks.js.map +1 -0
  80. package/lib/features/canvas/set/SetViewportWebView.js +207 -28
  81. package/lib/features/canvas/set/SetViewportWebView.js.map +1 -1
  82. package/lib/features/canvas/set/agent/prompt.js +66 -0
  83. package/lib/features/canvas/set/agent/prompt.js.map +1 -0
  84. package/lib/features/canvas/set/agent/setOps.js +203 -0
  85. package/lib/features/canvas/set/agent/setOps.js.map +1 -0
  86. package/lib/features/canvas/set/agent/setTurn.js +128 -0
  87. package/lib/features/canvas/set/agent/setTurn.js.map +1 -0
  88. package/lib/features/canvas/set/agent/snapshot.js +43 -0
  89. package/lib/features/canvas/set/agent/snapshot.js.map +1 -0
  90. package/lib/features/canvas/set/agent/tools.js +580 -0
  91. package/lib/features/canvas/set/agent/tools.js.map +1 -0
  92. package/lib/features/canvas/set/setProject.js +43 -4
  93. package/lib/features/canvas/set/setProject.js.map +1 -1
  94. package/lib/features/canvas/set/supplyLibrary.js +397 -0
  95. package/lib/features/canvas/set/supplyLibrary.js.map +1 -0
  96. package/lib/features/canvas/storageLibrary.js +113 -52
  97. package/lib/features/canvas/storageLibrary.js.map +1 -1
  98. package/lib/features/canvas/studioCatalog.js +15 -2
  99. package/lib/features/canvas/studioCatalog.js.map +1 -1
  100. package/lib/features/canvas/studioLooks.js +1 -8
  101. package/lib/features/canvas/studioLooks.js.map +1 -1
  102. package/lib/features/canvas/useBoardMediaRefresh.js +66 -0
  103. package/lib/features/canvas/useBoardMediaRefresh.js.map +1 -0
  104. package/lib/features/canvas/useMediaSource.js +84 -0
  105. package/lib/features/canvas/useMediaSource.js.map +1 -0
  106. package/lib/features/canvas/video3d.js +11 -10
  107. package/lib/features/canvas/video3d.js.map +1 -1
  108. package/lib/features/canvas/videoEditor/BlurBoxOverlay.js +46 -0
  109. package/lib/features/canvas/videoEditor/BlurBoxOverlay.js.map +1 -0
  110. package/lib/features/canvas/videoEditor/ExportTaskCard.js +134 -0
  111. package/lib/features/canvas/videoEditor/ExportTaskCard.js.map +1 -0
  112. package/lib/features/canvas/videoEditor/agent/AgentCutPane.js +45 -7
  113. package/lib/features/canvas/videoEditor/agent/AgentCutPane.js.map +1 -1
  114. package/lib/features/canvas/videoEditor/agent/agentLoop.js +4 -2
  115. package/lib/features/canvas/videoEditor/agent/agentLoop.js.map +1 -1
  116. package/lib/features/canvas/videoEditor/agent/attachments.js +304 -0
  117. package/lib/features/canvas/videoEditor/agent/attachments.js.map +1 -0
  118. package/lib/features/canvas/videoEditor/agent/brainClient.js +3 -2
  119. package/lib/features/canvas/videoEditor/agent/brainClient.js.map +1 -1
  120. package/lib/features/canvas/videoEditor/agent/cutTools.js +207 -7
  121. package/lib/features/canvas/videoEditor/agent/cutTools.js.map +1 -1
  122. package/lib/features/canvas/videoEditor/blurBox.js +34 -0
  123. package/lib/features/canvas/videoEditor/blurBox.js.map +1 -0
  124. package/lib/features/canvas/videoEditor/compileTimeline.js +668 -0
  125. package/lib/features/canvas/videoEditor/compileTimeline.js.map +1 -0
  126. package/lib/features/canvas/videoEditor/editorModel.js +56 -22
  127. package/lib/features/canvas/videoEditor/editorModel.js.map +1 -1
  128. package/lib/features/canvas/videoEditor/exportPipeline.js +77 -0
  129. package/lib/features/canvas/videoEditor/exportPipeline.js.map +1 -0
  130. package/lib/features/canvas/videoEditor/exportRenderer.js +19 -12
  131. package/lib/features/canvas/videoEditor/exportRenderer.js.map +1 -1
  132. package/lib/features/canvas/videoEditor/exportTask.js +216 -0
  133. package/lib/features/canvas/videoEditor/exportTask.js.map +1 -0
  134. package/lib/features/canvas/videoEditor/formWidgets.js +142 -0
  135. package/lib/features/canvas/videoEditor/formWidgets.js.map +1 -0
  136. package/lib/features/canvas/videoEditor/produce/ProduceVideoSheet.js +195 -0
  137. package/lib/features/canvas/videoEditor/produce/ProduceVideoSheet.js.map +1 -0
  138. package/lib/features/canvas/videoEditor/produce/produceScenes.js +158 -0
  139. package/lib/features/canvas/videoEditor/produce/produceScenes.js.map +1 -0
  140. package/lib/features/canvas/videoEditor/remoteMediaClient.js +17 -5
  141. package/lib/features/canvas/videoEditor/remoteMediaClient.js.map +1 -1
  142. package/lib/features/canvas/videoEditor/renderTimeline.js +207 -0
  143. package/lib/features/canvas/videoEditor/renderTimeline.js.map +1 -0
  144. package/lib/features/canvas/videoEditor/renewLinks.js +64 -0
  145. package/lib/features/canvas/videoEditor/renewLinks.js.map +1 -0
  146. package/lib/features/canvas/videoEditor/sceneLayers.js +101 -0
  147. package/lib/features/canvas/videoEditor/sceneLayers.js.map +1 -0
  148. package/lib/features/canvas/videoEditor/tools/ToolsDrawer.js +283 -0
  149. package/lib/features/canvas/videoEditor/tools/ToolsDrawer.js.map +1 -0
  150. package/lib/features/canvas/videoEditor/tools/catalog.js +576 -0
  151. package/lib/features/canvas/videoEditor/tools/catalog.js.map +1 -0
  152. package/lib/features/canvas/videoEditor/videoProjectsStore.js +27 -3
  153. package/lib/features/canvas/videoEditor/videoProjectsStore.js.map +1 -1
  154. package/lib/features/webbuilder/WebBuilderExperience.js +29 -1
  155. package/lib/features/webbuilder/WebBuilderExperience.js.map +1 -1
  156. package/lib/features/webbuilder/buildFragments.js +8 -4
  157. package/lib/features/webbuilder/buildFragments.js.map +1 -1
  158. package/lib/features/webbuilder/codezenHandoff.js +108 -0
  159. package/lib/features/webbuilder/codezenHandoff.js.map +1 -0
  160. package/lib/features/webbuilder/workflow.js.map +1 -1
  161. package/lib/hooks/useChatApi.js +1 -2
  162. package/lib/hooks/useChatApi.js.map +1 -1
  163. package/lib/screens/CanvasBoard/index.js +12 -1
  164. package/lib/screens/CanvasBoard/index.js.map +1 -1
  165. package/lib/screens/Home/HomeScreen.js.map +1 -1
  166. package/lib/screens/Home/components/HomeSuggestions.js +3 -3
  167. package/lib/screens/Home/components/HomeSuggestions.js.map +1 -1
  168. package/lib/screens/WebBuilder/index.js +4 -2
  169. package/lib/screens/WebBuilder/index.js.map +1 -1
  170. package/lib/screens/WebBuilderNative/index.js +29 -2
  171. package/lib/screens/WebBuilderNative/index.js.map +1 -1
  172. package/lib/screens/WebBuilderNative/useWebBuilderHost.js +30 -6
  173. package/lib/screens/WebBuilderNative/useWebBuilderHost.js.map +1 -1
  174. package/package.json +4 -4
  175. /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(/&amp;/g, "&").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&lt;/g, "<").replace(/&gt;/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(/&amp;/g, '&')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .replace(/&lt;/g, '<')\n .replace(/&gt;/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 || "yantra-brain-smart",
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 || 'yantra-brain-smart',\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":";;;;;;;;;;;;;;;;AAkCA,eAAsB,UAAU,IAMR,EAAA;AAxCxB,EAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA;AAyCE,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,oBAAA;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
+ {"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';const CUT_AGENT_TOOLS = [{
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 _a;
76
- return {
169
+ var _a2;
170
+ return __spreadProps(__spreadValues(__spreadValues({
77
171
  index: i,
78
172
  id: c.id,
79
- src: (_a = c.src) == null ? void 0 : _a.slice(0, 80),
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