vidspotai-shared 1.0.99 → 1.0.101-dev.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 (172) hide show
  1. package/lib/globals/aiModels/enums.d.ts +1 -0
  2. package/lib/globals/aiModels/enums.d.ts.map +1 -1
  3. package/lib/globals/aiModels/enums.js +3 -0
  4. package/lib/globals/aiModels/extendCapability.d.ts +26 -0
  5. package/lib/globals/aiModels/extendCapability.d.ts.map +1 -0
  6. package/lib/globals/aiModels/extendCapability.js +42 -0
  7. package/lib/globals/aiModels/index.d.ts +1 -0
  8. package/lib/globals/aiModels/index.d.ts.map +1 -1
  9. package/lib/globals/aiModels/index.js +1 -0
  10. package/lib/globals/aiModels/providers/hostedAvatars.js +10 -10
  11. package/lib/globals/creditUnit.d.ts +20 -33
  12. package/lib/globals/creditUnit.d.ts.map +1 -1
  13. package/lib/globals/creditUnit.js +20 -33
  14. package/lib/globals/types.d.ts +34 -2
  15. package/lib/globals/types.d.ts.map +1 -1
  16. package/lib/globals/types.js +37 -0
  17. package/lib/models/demoVideoProject.model.d.ts +213 -0
  18. package/lib/models/demoVideoProject.model.d.ts.map +1 -1
  19. package/lib/models/index.d.ts +2 -0
  20. package/lib/models/index.d.ts.map +1 -1
  21. package/lib/models/index.js +2 -0
  22. package/lib/models/mediaUpload.model.d.ts +25 -0
  23. package/lib/models/mediaUpload.model.d.ts.map +1 -1
  24. package/lib/models/productConnection.model.d.ts +57 -0
  25. package/lib/models/productConnection.model.d.ts.map +1 -0
  26. package/lib/models/productConnection.model.js +7 -0
  27. package/lib/models/video.model.d.ts +11 -0
  28. package/lib/models/video.model.d.ts.map +1 -1
  29. package/lib/models/videoQaJob.model.d.ts +61 -0
  30. package/lib/models/videoQaJob.model.d.ts.map +1 -0
  31. package/lib/models/videoQaJob.model.js +16 -0
  32. package/lib/schemas/brandKit.schema.d.ts +3 -1
  33. package/lib/schemas/brandKit.schema.d.ts.map +1 -1
  34. package/lib/schemas/brandKit.schema.js +9 -0
  35. package/lib/schemas/brief.schema.d.ts +5 -4
  36. package/lib/schemas/brief.schema.d.ts.map +1 -1
  37. package/lib/schemas/brief.schema.js +23 -1
  38. package/lib/schemas/demoQuestion.schema.d.ts +24 -4
  39. package/lib/schemas/demoQuestion.schema.d.ts.map +1 -1
  40. package/lib/schemas/demoQuestion.schema.js +8 -2
  41. package/lib/schemas/demoSpec.schema.d.ts +40 -6
  42. package/lib/schemas/demoSpec.schema.d.ts.map +1 -1
  43. package/lib/schemas/demoSpec.schema.js +46 -1
  44. package/lib/schemas/project.schema.d.ts +33 -3
  45. package/lib/schemas/project.schema.d.ts.map +1 -1
  46. package/lib/schemas/project.schema.js +22 -0
  47. package/lib/schemas/social.schema.d.ts +1 -1
  48. package/lib/schemas/videoPlan.schema.d.ts +22 -20
  49. package/lib/schemas/videoPlan.schema.d.ts.map +1 -1
  50. package/lib/schemas/videoPlan.schema.js +19 -0
  51. package/lib/services/agent/editClassifier.d.ts +10 -10
  52. package/lib/services/agent/eval/types.d.ts +3 -2
  53. package/lib/services/agent/eval/types.d.ts.map +1 -1
  54. package/lib/services/agent/executor/core.d.ts.map +1 -1
  55. package/lib/services/agent/executor/core.js +11 -0
  56. package/lib/services/agent/planner/Planner.d.ts.map +1 -1
  57. package/lib/services/agent/planner/Planner.js +5 -0
  58. package/lib/services/agent/planner/overlayRegen.d.ts.map +1 -1
  59. package/lib/services/agent/planner/overlayRegen.js +5 -0
  60. package/lib/services/agent/planner/plannerMessages.d.ts.map +1 -1
  61. package/lib/services/agent/planner/plannerMessages.js +10 -1
  62. package/lib/services/agent/planner/scriptFirstPlanner.d.ts.map +1 -1
  63. package/lib/services/agent/planner/scriptFirstPlanner.js +2 -0
  64. package/lib/services/agent/regenCore.d.ts.map +1 -1
  65. package/lib/services/agent/regenCore.js +11 -1
  66. package/lib/services/agent/runHelpers.d.ts +8 -0
  67. package/lib/services/agent/runHelpers.d.ts.map +1 -1
  68. package/lib/services/agent/runHelpers.js +5 -1
  69. package/lib/services/agent/tools/chapterOutline.tool.d.ts +8 -0
  70. package/lib/services/agent/tools/chapterOutline.tool.d.ts.map +1 -1
  71. package/lib/services/agent/tools/chapterOutline.tool.js +21 -8
  72. package/lib/services/agent/tools/composeScene.tool.d.ts +32 -2
  73. package/lib/services/agent/tools/composeScene.tool.d.ts.map +1 -1
  74. package/lib/services/agent/tools/estimateCost.tool.d.ts +11 -1
  75. package/lib/services/agent/tools/estimateCost.tool.d.ts.map +1 -1
  76. package/lib/services/agent/tools/extendVideo.tool.d.ts +9 -3
  77. package/lib/services/agent/tools/extendVideo.tool.d.ts.map +1 -1
  78. package/lib/services/agent/tools/extendVideo.tool.js +12 -27
  79. package/lib/services/agent/tools/generateAvatarVideo.tool.d.ts +1 -1
  80. package/lib/services/agent/tools/generateScript.tool.d.ts +3 -2
  81. package/lib/services/agent/tools/generateScript.tool.d.ts.map +1 -1
  82. package/lib/services/agent/tools/generateScript.tool.js +16 -7
  83. package/lib/services/agent/tools/generateVoiceover.tool.d.ts +1 -1
  84. package/lib/services/agent/tools/planVideo.tool.d.ts +11 -8
  85. package/lib/services/agent/tools/planVideo.tool.d.ts.map +1 -1
  86. package/lib/services/agent/tools/render.tool.d.ts +11 -1
  87. package/lib/services/agent/tools/render.tool.d.ts.map +1 -1
  88. package/lib/services/agent/tools/searchStock.tool.d.ts +1 -1
  89. package/lib/services/agent/tools/searchUserLibrary.tool.d.ts +4 -4
  90. package/lib/services/aiGen/providers/kling/kling.service.d.ts.map +1 -1
  91. package/lib/services/aiGen/providers/kling/kling.service.js +22 -3
  92. package/lib/services/aiGen/providers/kling/klingStatus.d.ts +7 -0
  93. package/lib/services/aiGen/providers/kling/klingStatus.d.ts.map +1 -1
  94. package/lib/services/aiGen/providers/kling/klingStatus.js +41 -4
  95. package/lib/services/aiGen/providers/pixverse/pixverse.service.d.ts.map +1 -1
  96. package/lib/services/aiGen/providers/pixverse/pixverse.service.js +25 -0
  97. package/lib/services/aiGen/providers/types.d.ts +20 -0
  98. package/lib/services/aiGen/providers/types.d.ts.map +1 -1
  99. package/lib/services/avatarGen/avatarProviderFactory.d.ts.map +1 -1
  100. package/lib/services/avatarGen/avatarProviderFactory.js +3 -0
  101. package/lib/services/avatarGen/index.d.ts +1 -0
  102. package/lib/services/avatarGen/index.d.ts.map +1 -1
  103. package/lib/services/avatarGen/index.js +1 -0
  104. package/lib/services/avatarGen/providers/synthesiaAvatarProvider.d.ts +53 -0
  105. package/lib/services/avatarGen/providers/synthesiaAvatarProvider.d.ts.map +1 -0
  106. package/lib/services/avatarGen/providers/synthesiaAvatarProvider.js +176 -0
  107. package/lib/services/demo/demoAuthor.d.ts +7 -0
  108. package/lib/services/demo/demoAuthor.d.ts.map +1 -1
  109. package/lib/services/demo/demoAuthor.js +2 -0
  110. package/lib/services/demo/demoAuthorPrompt.d.ts +6 -0
  111. package/lib/services/demo/demoAuthorPrompt.d.ts.map +1 -1
  112. package/lib/services/demo/demoAuthorPrompt.js +24 -2
  113. package/lib/services/demo/demoCaptions.d.ts +69 -0
  114. package/lib/services/demo/demoCaptions.d.ts.map +1 -0
  115. package/lib/services/demo/demoCaptions.js +152 -0
  116. package/lib/services/demo/demoMusic.d.ts +8 -1
  117. package/lib/services/demo/demoMusic.d.ts.map +1 -1
  118. package/lib/services/demo/demoMusic.js +32 -16
  119. package/lib/services/demo/demoScriptPrompt.d.ts +2 -1
  120. package/lib/services/demo/demoScriptPrompt.d.ts.map +1 -1
  121. package/lib/services/demo/demoScriptPrompt.js +29 -2
  122. package/lib/services/demo/demoStockAssets.d.ts +29 -0
  123. package/lib/services/demo/demoStockAssets.d.ts.map +1 -0
  124. package/lib/services/demo/demoStockAssets.js +107 -0
  125. package/lib/services/demo/index.d.ts +3 -0
  126. package/lib/services/demo/index.d.ts.map +1 -1
  127. package/lib/services/demo/index.js +3 -0
  128. package/lib/services/demo/productConnection.service.d.ts +78 -0
  129. package/lib/services/demo/productConnection.service.d.ts.map +1 -0
  130. package/lib/services/demo/productConnection.service.js +125 -0
  131. package/lib/services/editor/planToProject.d.ts.map +1 -1
  132. package/lib/services/editor/planToProject.helpers.d.ts +1 -0
  133. package/lib/services/editor/planToProject.helpers.d.ts.map +1 -1
  134. package/lib/services/editor/planToProject.helpers.js +3 -0
  135. package/lib/services/editor/planToProject.js +39 -0
  136. package/lib/services/editor/projectToDesign.js +13 -1
  137. package/lib/services/firestore.service.d.ts +14 -0
  138. package/lib/services/firestore.service.d.ts.map +1 -1
  139. package/lib/services/firestore.service.js +16 -0
  140. package/lib/services/translation/index.d.ts +1 -0
  141. package/lib/services/translation/index.d.ts.map +1 -1
  142. package/lib/services/translation/index.js +8 -1
  143. package/lib/services/translation/outputLanguage.d.ts +75 -0
  144. package/lib/services/translation/outputLanguage.d.ts.map +1 -0
  145. package/lib/services/translation/outputLanguage.js +190 -0
  146. package/lib/services/translation/translation.service.d.ts +13 -2
  147. package/lib/services/translation/translation.service.d.ts.map +1 -1
  148. package/lib/services/translation/translation.service.js +66 -5
  149. package/lib/services/tts/index.d.ts +1 -0
  150. package/lib/services/tts/index.d.ts.map +1 -1
  151. package/lib/services/tts/index.js +1 -0
  152. package/lib/services/tts/providers/elevenlabs.service.d.ts +7 -0
  153. package/lib/services/tts/providers/elevenlabs.service.d.ts.map +1 -1
  154. package/lib/services/tts/providers/elevenlabs.service.js +69 -13
  155. package/lib/services/tts/types.d.ts +29 -0
  156. package/lib/services/tts/types.d.ts.map +1 -1
  157. package/lib/services/tts/wordTimings.d.ts +27 -0
  158. package/lib/services/tts/wordTimings.d.ts.map +1 -0
  159. package/lib/services/tts/wordTimings.js +57 -0
  160. package/lib/utils/billableDuration.d.ts +11 -0
  161. package/lib/utils/billableDuration.d.ts.map +1 -0
  162. package/lib/utils/billableDuration.js +91 -0
  163. package/lib/utils/index.d.ts +3 -0
  164. package/lib/utils/index.d.ts.map +1 -1
  165. package/lib/utils/index.js +3 -0
  166. package/lib/utils/mp4Duration.d.ts +38 -0
  167. package/lib/utils/mp4Duration.d.ts.map +1 -0
  168. package/lib/utils/mp4Duration.js +164 -0
  169. package/lib/utils/socialEntitlements.d.ts +51 -0
  170. package/lib/utils/socialEntitlements.d.ts.map +1 -0
  171. package/lib/utils/socialEntitlements.js +65 -0
  172. package/package.json +1 -1
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hostOf = hostOf;
4
+ exports.isProductConnectionEnabled = isProductConnectionEnabled;
5
+ exports.saveProductConnection = saveProductConnection;
6
+ exports.getProductConnection = getProductConnection;
7
+ exports.listProductConnections = listProductConnections;
8
+ exports.deleteProductConnection = deleteProductConnection;
9
+ exports.markProductConnectionExpired = markProductConnectionExpired;
10
+ exports.touchProductConnection = touchProductConnection;
11
+ const firestore_1 = require("firebase-admin/firestore");
12
+ const firestore_service_1 = require("../firestore.service");
13
+ const productConnection_model_1 = require("../../models/productConnection.model");
14
+ const tokenVault_1 = require("../crypto/tokenVault");
15
+ /** Origin host of a URL, lowercased, or null if unparseable. */
16
+ function hostOf(url) {
17
+ try {
18
+ return new URL(url).host.toLowerCase();
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ }
24
+ /** Earliest real cookie expiry (epoch ms) across the snapshot, for the reconnect UX. */
25
+ function earliestCookieExpiry(state) {
26
+ const future = state.cookies
27
+ .map((c) => c.expires)
28
+ .filter((e) => typeof e === "number" && e > 0)
29
+ .map((e) => e * 1000);
30
+ return future.length ? Math.min(...future) : undefined;
31
+ }
32
+ /** True when the vault is configured — connections are unusable without it. */
33
+ function isProductConnectionEnabled() {
34
+ return (0, tokenVault_1.isTokenVaultConfigured)();
35
+ }
36
+ /**
37
+ * Upsert a captured sign-in session (encrypted). Idempotent per (user, host):
38
+ * re-connecting the same product replaces the expired snapshot. Returns the
39
+ * host used as the connection key.
40
+ */
41
+ async function saveProductConnection(args) {
42
+ const { userId, productUrl, storageState, label } = args;
43
+ const host = hostOf(productUrl);
44
+ if (!host)
45
+ throw new Error("saveProductConnection: unparseable productUrl");
46
+ const origins = [
47
+ ...new Set(storageState.origins
48
+ .map((o) => o.origin)
49
+ .concat(new URL(productUrl).origin)),
50
+ ];
51
+ const expiresHint = earliestCookieExpiry(storageState);
52
+ const stateEnc = (0, tokenVault_1.encryptToken)(JSON.stringify(storageState));
53
+ const doc = {
54
+ userId,
55
+ host,
56
+ productUrl,
57
+ origins,
58
+ ...(label ? { label } : {}),
59
+ stateEnc,
60
+ ...(expiresHint ? { expiresHint } : {}),
61
+ status: "active",
62
+ capturedAt: firestore_1.FieldValue.serverTimestamp(),
63
+ updatedAt: firestore_1.FieldValue.serverTimestamp(),
64
+ };
65
+ await firestore_service_1.FirestoreService.productConnectionsCol
66
+ .doc((0, productConnection_model_1.productConnectionDocId)(userId, host))
67
+ .set(doc);
68
+ return { host };
69
+ }
70
+ /**
71
+ * Read + decrypt a user's connection for a host. Returns the storageState +
72
+ * metadata, or null when there's no ACTIVE connection / the vault can't decrypt
73
+ * (best-effort — the caller treats null as "not connected" and asks the user).
74
+ */
75
+ async function getProductConnection(userId, host) {
76
+ const snap = await firestore_service_1.FirestoreService.productConnectionsCol
77
+ .doc((0, productConnection_model_1.productConnectionDocId)(userId, host))
78
+ .get();
79
+ const conn = snap.data();
80
+ if (!conn || conn.status !== "active" || !conn.stateEnc)
81
+ return null;
82
+ try {
83
+ const state = JSON.parse((0, tokenVault_1.decryptToken)(conn.stateEnc));
84
+ return { state, conn };
85
+ }
86
+ catch {
87
+ return null;
88
+ }
89
+ }
90
+ /** List a user's connections as public-safe summaries (no encrypted state). */
91
+ async function listProductConnections(userId) {
92
+ const snap = await firestore_service_1.FirestoreService.productConnectionsCol
93
+ .where("userId", "==", userId)
94
+ .get();
95
+ return snap.docs.map((d) => {
96
+ const c = d.data();
97
+ return {
98
+ host: c.host,
99
+ productUrl: c.productUrl,
100
+ origins: c.origins,
101
+ ...(c.label ? { label: c.label } : {}),
102
+ status: c.status,
103
+ ...(c.expiresHint ? { expiresHint: c.expiresHint } : {}),
104
+ };
105
+ });
106
+ }
107
+ /** Delete (revoke) a user's connection for a host. */
108
+ async function deleteProductConnection(userId, host) {
109
+ await firestore_service_1.FirestoreService.productConnectionsCol
110
+ .doc((0, productConnection_model_1.productConnectionDocId)(userId, host))
111
+ .delete();
112
+ }
113
+ /** Flag a connection expired after a replay found the session no longer authenticates. */
114
+ async function markProductConnectionExpired(userId, host) {
115
+ await firestore_service_1.FirestoreService.productConnectionsCol
116
+ .doc((0, productConnection_model_1.productConnectionDocId)(userId, host))
117
+ .set({ status: "expired", updatedAt: firestore_1.FieldValue.serverTimestamp() }, { merge: true });
118
+ }
119
+ /** Stamp lastUsedAt after a successful replay (observability; best-effort). */
120
+ async function touchProductConnection(userId, host) {
121
+ await firestore_service_1.FirestoreService.productConnectionsCol
122
+ .doc((0, productConnection_model_1.productConnectionDocId)(userId, host))
123
+ .set({ lastUsedAt: firestore_1.FieldValue.serverTimestamp(), updatedAt: firestore_1.FieldValue.serverTimestamp() }, { merge: true })
124
+ .catch(() => { });
125
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"planToProject.d.ts","sourceRoot":"","sources":["../../../src/services/editor/planToProject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAKV,OAAO,EAIR,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAehE,OAAO,EAAE,QAAQ,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEpF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAwZhE"}
1
+ {"version":3,"file":"planToProject.d.ts","sourceRoot":"","sources":["../../../src/services/editor/planToProject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAKV,OAAO,EAIR,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAehE,OAAO,EAAE,QAAQ,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEpF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CA6bhE"}
@@ -15,6 +15,7 @@ export declare const TRACK_ID: {
15
15
  readonly music: "track-music";
16
16
  readonly text: "track-text";
17
17
  readonly caption: "track-caption";
18
+ readonly logo: "track-logo";
18
19
  };
19
20
  export declare function isStillStrategy(s: SceneAssetStrategy): boolean;
20
21
  /** A passable URL we can put in skeleton clips so ProjectSchema.url() passes. */
@@ -1 +1 @@
1
- {"version":3,"file":"planToProject.helpers.d.ts","sourceRoot":"","sources":["../../../src/services/editor/planToProject.helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,QAAQ,EACR,KAAK,EACL,UAAU,EACX,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,cAAc,EACd,SAAS,EACV,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE;;;;;;GAMG;AAIH,eAAO,MAAM,QAAQ;;;;;;;CASX,CAAC;AASX,wBAAgB,eAAe,CAAC,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAE9D;AAED,iFAAiF;AACjF,eAAO,MAAM,eAAe,sBAAsB,CAAC;AAInD,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAW5F;AAID,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC,GAAG,IAAI,CASjF,CAAC;AAIF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,kBAAkB,GAAG,SAAS,GACtC,UAAU,CAiBZ;AA4CD;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,SAAS,WAAW,EAAE,EAChC,WAAW,EAAE,MAAM;AACnB;;;;GAIG;AACH,SAAS,CAAC,EAAE,aAAa,GACxB,QAAQ,EAAE,CA2CZ;AAED,wBAAgB,SAAS,CACvB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,EACnB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,aAAa,CAAC,EAAE,MAAM,GACrB,KAAK,CAYP"}
1
+ {"version":3,"file":"planToProject.helpers.d.ts","sourceRoot":"","sources":["../../../src/services/editor/planToProject.helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,QAAQ,EACR,KAAK,EACL,UAAU,EACX,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,cAAc,EACd,SAAS,EACV,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE;;;;;;GAMG;AAIH,eAAO,MAAM,QAAQ;;;;;;;;CAYX,CAAC;AASX,wBAAgB,eAAe,CAAC,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAE9D;AAED,iFAAiF;AACjF,eAAO,MAAM,eAAe,sBAAsB,CAAC;AAInD,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAW5F;AAID,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC,GAAG,IAAI,CASjF,CAAC;AAIF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,kBAAkB,GAAG,SAAS,GACtC,UAAU,CAiBZ;AA4CD;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,SAAS,WAAW,EAAE,EAChC,WAAW,EAAE,MAAM;AACnB;;;;GAIG;AACH,SAAS,CAAC,EAAE,aAAa,GACxB,QAAQ,EAAE,CA2CZ;AAED,wBAAgB,SAAS,CACvB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,EACnB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,aAAa,CAAC,EAAE,MAAM,GACrB,KAAK,CAYP"}
@@ -24,6 +24,9 @@ exports.TRACK_ID = {
24
24
  music: "track-music",
25
25
  text: "track-text",
26
26
  caption: "track-caption",
27
+ // Brand-logo overlay lane — a single image clip pinned to a corner, spanning
28
+ // the whole video, painted on top of everything (Reach per-recipient logo).
29
+ logo: "track-logo",
27
30
  };
28
31
  // ─── strategy → clip kind ────────────────────────────────────────────────
29
32
  const STILL_STRATEGIES = new Set([
@@ -335,6 +335,39 @@ function planToProject(input) {
335
335
  };
336
336
  clips.push(musicClip);
337
337
  }
338
+ // Reach per-recipient brand logo — a single contained ImageClip pinned to the
339
+ // top-right corner, spanning the whole video, painted on top of every track.
340
+ // Only emitted when the outreach fan-out injected plan.brandLogoUrl (the
341
+ // planner never sets it), so scene visuals are untouched for every other flow.
342
+ let hasLogo = false;
343
+ if (plan.brandLogoUrl && offsetMs > 0) {
344
+ hasLogo = true;
345
+ // Square box (contain letterboxes any logo aspect — no crop), ~16% of the
346
+ // short side, inset by a ~4%-of-width margin from the top-right corner.
347
+ const side = Math.round(Math.min(size.width, size.height) * 0.16);
348
+ const margin = Math.round(size.width * 0.04);
349
+ const logoClip = {
350
+ id: "brand-logo",
351
+ trackId: planToProject_helpers_1.TRACK_ID.logo,
352
+ type: "image",
353
+ display: { from: 0, to: offsetMs },
354
+ name: "Brand logo",
355
+ src: plan.brandLogoUrl,
356
+ fit: "contain",
357
+ box: {
358
+ left: size.width - side - margin,
359
+ top: margin,
360
+ width: side,
361
+ height: side,
362
+ },
363
+ provenance: { tier: "T0", source: "user-upload", creditsSpent: 0 },
364
+ effects: [],
365
+ transform: { x: 0, y: 0, scaleX: 1, scaleY: 1, rotation: 0, opacity: 1 },
366
+ locked: false,
367
+ metadata: { brandLogo: true },
368
+ };
369
+ clips.push(logoClip);
370
+ }
338
371
  // Stage 7 (lock enforcement) — overlay preserved clips verbatim. Runs after
339
372
  // ALL clips (incl. music) are built so a preserved clip cleanly displaces
340
373
  // its freshly-rebuilt twin by id (ids are deterministic: scene-N-visual /
@@ -376,6 +409,9 @@ function planToProject(input) {
376
409
  case planToProject_helpers_1.TRACK_ID.caption:
377
410
  hasCaptions = true;
378
411
  break;
412
+ case planToProject_helpers_1.TRACK_ID.logo:
413
+ hasLogo = true;
414
+ break;
379
415
  default: break; // visual track is always declared
380
416
  }
381
417
  }
@@ -400,6 +436,9 @@ function planToProject(input) {
400
436
  // row per source group, and regen/new captions route back onto it.
401
437
  if (hasCaptions)
402
438
  tracks.push((0, planToProject_helpers_1.makeTrack)(planToProject_helpers_1.TRACK_ID.caption, "caption", trackIndex++, "Voiceover · Captions", planToProject_helpers_1.TRACK_ID.voiceover));
439
+ // Logo lane is declared LAST → highest track index → painted on top of all.
440
+ if (hasLogo)
441
+ tracks.push((0, planToProject_helpers_1.makeTrack)(planToProject_helpers_1.TRACK_ID.logo, "video", trackIndex++, "Logo"));
403
442
  const durationMs = Math.max(1, offsetMs);
404
443
  return {
405
444
  schemaVersion: project_schema_1.PROJECT_SCHEMA_VERSION,
@@ -153,7 +153,19 @@ function videoDetails(clip) {
153
153
  };
154
154
  }
155
155
  function imageDetails(clip) {
156
- return { src: clip.src };
156
+ const d = { src: clip.src };
157
+ // Positioned overlay images (e.g. a corner brand logo) carry an explicit
158
+ // pixel box + fit; the renderer's container/media styles read left/top/
159
+ // width/height/objectFit. Absent → full-frame cover as before.
160
+ if (clip.box) {
161
+ d.left = clip.box.left;
162
+ d.top = clip.box.top;
163
+ d.width = clip.box.width;
164
+ d.height = clip.box.height;
165
+ }
166
+ if (clip.fit)
167
+ d.objectFit = clip.fit;
168
+ return d;
157
169
  }
158
170
  function audioDetails(clip) {
159
171
  return {
@@ -13,7 +13,9 @@ import { IShareModel } from "../models/share.model";
13
13
  import { IUserModel } from "../models/user.model";
14
14
  import { IVideoJobModel } from "../models/video.model";
15
15
  import { IDemoVideoProjectModel } from "../models/demoVideoProject.model";
16
+ import { IVideoQaJobModel } from "../models/videoQaJob.model";
16
17
  import { IGithubConnectionModel } from "../models/githubConnection.model";
18
+ import { IProductConnectionModel } from "../models/productConnection.model";
17
19
  import { IOutreachCampaignModel, IOutreachRecipientModel, IOutreachTemplateModel, IPersonalizedVideoModel, IVideoViewModel } from "../models/outreach.model";
18
20
  /**
19
21
  * FirestoreService
@@ -55,8 +57,20 @@ export declare class FirestoreService {
55
57
  static sharesCol: CollectionReference<IShareModel, DocumentData>;
56
58
  static mediaUploadsCol: CollectionReference<IMediaUploadModel, DocumentData>;
57
59
  static demoVideoProjectsCol: CollectionReference<IDemoVideoProjectModel, DocumentData>;
60
+ /**
61
+ * Output-QA requests against a finished `videoJobs` output (MCP
62
+ * check_video_quality / repair_video). One doc per request; the worker writes
63
+ * the report back and the MCP tool polls it. See videoQaJob.model.ts.
64
+ */
65
+ static videoQaJobsCol: CollectionReference<IVideoQaJobModel, DocumentData>;
58
66
  /** GitHub OAuth connections — one doc per user (doc id = userId). Phase 9. */
59
67
  static githubConnectionsCol: CollectionReference<IGithubConnectionModel, DocumentData>;
68
+ /**
69
+ * Product sign-in connections — the encrypted, replayable storageState a user
70
+ * captured for their own SaaS product so the worker can record its
71
+ * authenticated UI (Tier 2 product-footage-capture). Doc id = `${userId}__${host}`.
72
+ */
73
+ static productConnectionsCol: CollectionReference<IProductConnectionModel, DocumentData>;
60
74
  static socialAccountsCol: CollectionReference<ISocialAccountModel, DocumentData>;
61
75
  static socialPostsCol: CollectionReference<ISocialPostModel, DocumentData>;
62
76
  static socialAnalyticsCol: CollectionReference<ISocialAnalyticsModel, DocumentData>;
@@ -1 +1 @@
1
- {"version":3,"file":"firestore.service.d.ts","sourceRoot":"","sources":["../../src/services/firestore.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"firestore.service.d.ts","sourceRoot":"","sources":["../../src/services/firestore.service.ts"],"names":[],"mappings":"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"}
@@ -168,10 +168,26 @@ FirestoreService.mediaUploadsCol = firebase_1.firestore
168
168
  FirestoreService.demoVideoProjectsCol = firebase_1.firestore
169
169
  .collection("demoVideoProjects")
170
170
  .withConverter(collectionConverter());
171
+ /**
172
+ * Output-QA requests against a finished `videoJobs` output (MCP
173
+ * check_video_quality / repair_video). One doc per request; the worker writes
174
+ * the report back and the MCP tool polls it. See videoQaJob.model.ts.
175
+ */
176
+ FirestoreService.videoQaJobsCol = firebase_1.firestore
177
+ .collection("videoQaJobs")
178
+ .withConverter(collectionConverter());
171
179
  /** GitHub OAuth connections — one doc per user (doc id = userId). Phase 9. */
172
180
  FirestoreService.githubConnectionsCol = firebase_1.firestore
173
181
  .collection("githubConnections")
174
182
  .withConverter(collectionConverter());
183
+ /**
184
+ * Product sign-in connections — the encrypted, replayable storageState a user
185
+ * captured for their own SaaS product so the worker can record its
186
+ * authenticated UI (Tier 2 product-footage-capture). Doc id = `${userId}__${host}`.
187
+ */
188
+ FirestoreService.productConnectionsCol = firebase_1.firestore
189
+ .collection("productConnections")
190
+ .withConverter(collectionConverter());
175
191
  // 🔹 X8 Social Suite — see notes/SOCIAL_SUITE_PLAN.md
176
192
  FirestoreService.socialAccountsCol = firebase_1.firestore
177
193
  .collection("socialAccounts")
@@ -1,2 +1,3 @@
1
1
  export { translationService } from "./translation.service";
2
+ export { LANGUAGE_DISPLAY_NAMES, buildOutputLanguageSection, isEnglish, languageDisplayName, normalizeLanguageTag, resolveOutputLanguage, } from "./outputLanguage";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/translation/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/translation/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EACL,sBAAsB,EACtB,0BAA0B,EAC1B,SAAS,EACT,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC"}
@@ -1,9 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.translationService = void 0;
3
+ exports.resolveOutputLanguage = exports.normalizeLanguageTag = exports.languageDisplayName = exports.isEnglish = exports.buildOutputLanguageSection = exports.LANGUAGE_DISPLAY_NAMES = exports.translationService = void 0;
4
4
  // Only the new API is exported from the services barrel. The legacy aliases
5
5
  // (getTranslationWrapper / detectLang / TRANSLATION_FAILED) are re-exported via
6
6
  // utils/helpers instead, so each name reaches the package root through exactly
7
7
  // one star-export path (no ambiguous duplicate re-export).
8
8
  var translation_service_1 = require("./translation.service");
9
9
  Object.defineProperty(exports, "translationService", { enumerable: true, get: function () { return translation_service_1.translationService; } });
10
+ var outputLanguage_1 = require("./outputLanguage");
11
+ Object.defineProperty(exports, "LANGUAGE_DISPLAY_NAMES", { enumerable: true, get: function () { return outputLanguage_1.LANGUAGE_DISPLAY_NAMES; } });
12
+ Object.defineProperty(exports, "buildOutputLanguageSection", { enumerable: true, get: function () { return outputLanguage_1.buildOutputLanguageSection; } });
13
+ Object.defineProperty(exports, "isEnglish", { enumerable: true, get: function () { return outputLanguage_1.isEnglish; } });
14
+ Object.defineProperty(exports, "languageDisplayName", { enumerable: true, get: function () { return outputLanguage_1.languageDisplayName; } });
15
+ Object.defineProperty(exports, "normalizeLanguageTag", { enumerable: true, get: function () { return outputLanguage_1.normalizeLanguageTag; } });
16
+ Object.defineProperty(exports, "resolveOutputLanguage", { enumerable: true, get: function () { return outputLanguage_1.resolveOutputLanguage; } });
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Output language — the language the VIEWER hears and reads.
3
+ *
4
+ * WHY THIS EXISTS
5
+ * ---------------
6
+ * Until now the product had no concept of an output language at all. The brief
7
+ * carried `voice.language` (defaulting to "en") that nothing read, the planner
8
+ * prompt never mentioned language, and the TTS/ASR layers were handed no hint.
9
+ * Net effect: a user could write their whole brief in Spanish and get an
10
+ * English-narrated video back. This module is the single place that decides
11
+ * what language the narration, captions, and on-screen copy should be in.
12
+ *
13
+ * IMPORTANT — output language is NOT prompt language. The visual `prompt` /
14
+ * `intent` fields that feed the image/video models stay English (the providers
15
+ * are tuned on English and degrade noticeably otherwise). Only viewer-facing
16
+ * text follows the output language. `localizePlanText` in
17
+ * `utils/outreachTemplate.ts` draws the same line for the Reach path.
18
+ *
19
+ * RESOLUTION ORDER ("auto" — no user-facing picker)
20
+ * 1. The language the user actually WROTE the brief in. This is the
21
+ * strongest signal of intent and beats the UI chrome: people routinely
22
+ * browse an English UI and then type their brief in their own language.
23
+ * 2. The UI locale they submitted from, when detection is unavailable or
24
+ * says it isn't confident.
25
+ * 3. English, as the terminal fallback.
26
+ */
27
+ /**
28
+ * Display names for the languages the product advertises support for (the set
29
+ * behind the marketing pages' locale switcher). Used to address the model in
30
+ * plain English ("Write in Spanish") rather than by bare ISO code, which
31
+ * measurably improves instruction-following on the smaller planner models.
32
+ *
33
+ * A code missing from this map is NOT an error — `languageDisplayName` falls
34
+ * back to naming the ISO code, and the LLM handles it fine. The map exists to
35
+ * make the common cases read naturally, not to gate-keep a closed set.
36
+ */
37
+ export declare const LANGUAGE_DISPLAY_NAMES: Record<string, string>;
38
+ /**
39
+ * Normalize a BCP-47 locale to the tag we key on: lowercased, and reduced to
40
+ * the primary subtag UNLESS the full tag is one we name distinctly (the
41
+ * Chinese scripts, where "zh-cn" vs "zh-tw" is a real content difference and
42
+ * collapsing to "zh" would lose it).
43
+ *
44
+ * "es-419" → "es", "pt_BR" → "pt", "zh-CN" → "zh-cn". Empty input → undefined.
45
+ */
46
+ export declare function normalizeLanguageTag(locale?: string): string | undefined;
47
+ /** Human-readable language name for prompt injection; falls back to the code. */
48
+ export declare function languageDisplayName(code: string): string;
49
+ /** True when `code` resolves to English (or is absent). */
50
+ export declare function isEnglish(code?: string): boolean;
51
+ /**
52
+ * Decide the output language for a piece of work. See the resolution order in
53
+ * the module docblock.
54
+ *
55
+ * Never throws and never blocks: detection is best-effort and every failure
56
+ * path degrades to the UI locale, then to English. A language lookup must not
57
+ * be able to fail a generation run.
58
+ *
59
+ * @param promptText The user's own words (brief.rawPrompt / video prompt).
60
+ * @param uiLocale The locale the request was submitted from, if the client sent one.
61
+ */
62
+ export declare function resolveOutputLanguage(params: {
63
+ promptText?: string;
64
+ uiLocale?: string;
65
+ }): Promise<string>;
66
+ /**
67
+ * Render the output-language rule for an LLM system prompt. Returns "" for
68
+ * English so the (overwhelmingly common) English path adds zero tokens and
69
+ * behaves exactly as it did before this feature existed.
70
+ *
71
+ * `kinds` names the viewer-facing surfaces the callee actually produces, so
72
+ * each prompt gets a rule about its own output rather than a generic one.
73
+ */
74
+ export declare function buildOutputLanguageSection(outputLanguage: string | undefined, kinds: string): string;
75
+ //# sourceMappingURL=outputLanguage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outputLanguage.d.ts","sourceRoot":"","sources":["../../../src/services/translation/outputLanguage.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAwCzD,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAOxE;AAED,iFAAiF;AACjF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED,2DAA2D;AAC3D,wBAAgB,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAGhD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmClB;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,KAAK,EAAE,MAAM,GACZ,MAAM,CAeR"}
@@ -0,0 +1,190 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LANGUAGE_DISPLAY_NAMES = void 0;
4
+ exports.normalizeLanguageTag = normalizeLanguageTag;
5
+ exports.languageDisplayName = languageDisplayName;
6
+ exports.isEnglish = isEnglish;
7
+ exports.resolveOutputLanguage = resolveOutputLanguage;
8
+ exports.buildOutputLanguageSection = buildOutputLanguageSection;
9
+ const types_1 = require("../../globals/types");
10
+ const logger_1 = require("../../utils/logger");
11
+ const translation_service_1 = require("./translation.service");
12
+ /**
13
+ * Output language — the language the VIEWER hears and reads.
14
+ *
15
+ * WHY THIS EXISTS
16
+ * ---------------
17
+ * Until now the product had no concept of an output language at all. The brief
18
+ * carried `voice.language` (defaulting to "en") that nothing read, the planner
19
+ * prompt never mentioned language, and the TTS/ASR layers were handed no hint.
20
+ * Net effect: a user could write their whole brief in Spanish and get an
21
+ * English-narrated video back. This module is the single place that decides
22
+ * what language the narration, captions, and on-screen copy should be in.
23
+ *
24
+ * IMPORTANT — output language is NOT prompt language. The visual `prompt` /
25
+ * `intent` fields that feed the image/video models stay English (the providers
26
+ * are tuned on English and degrade noticeably otherwise). Only viewer-facing
27
+ * text follows the output language. `localizePlanText` in
28
+ * `utils/outreachTemplate.ts` draws the same line for the Reach path.
29
+ *
30
+ * RESOLUTION ORDER ("auto" — no user-facing picker)
31
+ * 1. The language the user actually WROTE the brief in. This is the
32
+ * strongest signal of intent and beats the UI chrome: people routinely
33
+ * browse an English UI and then type their brief in their own language.
34
+ * 2. The UI locale they submitted from, when detection is unavailable or
35
+ * says it isn't confident.
36
+ * 3. English, as the terminal fallback.
37
+ */
38
+ /**
39
+ * Display names for the languages the product advertises support for (the set
40
+ * behind the marketing pages' locale switcher). Used to address the model in
41
+ * plain English ("Write in Spanish") rather than by bare ISO code, which
42
+ * measurably improves instruction-following on the smaller planner models.
43
+ *
44
+ * A code missing from this map is NOT an error — `languageDisplayName` falls
45
+ * back to naming the ISO code, and the LLM handles it fine. The map exists to
46
+ * make the common cases read naturally, not to gate-keep a closed set.
47
+ */
48
+ exports.LANGUAGE_DISPLAY_NAMES = {
49
+ en: "English",
50
+ ar: "Arabic",
51
+ bg: "Bulgarian",
52
+ ca: "Catalan",
53
+ cs: "Czech",
54
+ da: "Danish",
55
+ de: "German",
56
+ el: "Greek",
57
+ es: "Spanish",
58
+ fi: "Finnish",
59
+ fr: "French",
60
+ he: "Hebrew",
61
+ hi: "Hindi",
62
+ hr: "Croatian",
63
+ hu: "Hungarian",
64
+ id: "Indonesian",
65
+ it: "Italian",
66
+ // `iw` is Google's legacy code for Hebrew and is what the detect endpoint
67
+ // still returns; keep both so neither path falls through to the ISO wording.
68
+ iw: "Hebrew",
69
+ ja: "Japanese",
70
+ ko: "Korean",
71
+ ms: "Malay",
72
+ nl: "Dutch",
73
+ no: "Norwegian",
74
+ pl: "Polish",
75
+ pt: "Portuguese",
76
+ ro: "Romanian",
77
+ ru: "Russian",
78
+ sk: "Slovak",
79
+ sv: "Swedish",
80
+ th: "Thai",
81
+ tl: "Filipino",
82
+ tr: "Turkish",
83
+ uk: "Ukrainian",
84
+ vi: "Vietnamese",
85
+ zh: "Chinese",
86
+ "zh-cn": "Chinese (Simplified)",
87
+ "zh-tw": "Chinese (Traditional)",
88
+ };
89
+ /**
90
+ * Normalize a BCP-47 locale to the tag we key on: lowercased, and reduced to
91
+ * the primary subtag UNLESS the full tag is one we name distinctly (the
92
+ * Chinese scripts, where "zh-cn" vs "zh-tw" is a real content difference and
93
+ * collapsing to "zh" would lose it).
94
+ *
95
+ * "es-419" → "es", "pt_BR" → "pt", "zh-CN" → "zh-cn". Empty input → undefined.
96
+ */
97
+ function normalizeLanguageTag(locale) {
98
+ if (!locale)
99
+ return undefined;
100
+ const lower = locale.trim().toLowerCase().replace(/_/g, "-");
101
+ if (!lower)
102
+ return undefined;
103
+ if (exports.LANGUAGE_DISPLAY_NAMES[lower])
104
+ return lower;
105
+ const base = lower.split("-")[0];
106
+ return base || undefined;
107
+ }
108
+ /** Human-readable language name for prompt injection; falls back to the code. */
109
+ function languageDisplayName(code) {
110
+ const tag = normalizeLanguageTag(code);
111
+ if (!tag)
112
+ return "English";
113
+ return exports.LANGUAGE_DISPLAY_NAMES[tag] ?? `the language with ISO code "${tag}"`;
114
+ }
115
+ /** True when `code` resolves to English (or is absent). */
116
+ function isEnglish(code) {
117
+ const tag = normalizeLanguageTag(code);
118
+ return !tag || tag === types_1.ELANGUAGE_CODE.en;
119
+ }
120
+ /**
121
+ * Decide the output language for a piece of work. See the resolution order in
122
+ * the module docblock.
123
+ *
124
+ * Never throws and never blocks: detection is best-effort and every failure
125
+ * path degrades to the UI locale, then to English. A language lookup must not
126
+ * be able to fail a generation run.
127
+ *
128
+ * @param promptText The user's own words (brief.rawPrompt / video prompt).
129
+ * @param uiLocale The locale the request was submitted from, if the client sent one.
130
+ */
131
+ async function resolveOutputLanguage(params) {
132
+ const uiTag = normalizeLanguageTag(params.uiLocale);
133
+ const text = params.promptText?.trim();
134
+ // Too short to detect on. Single words and stock phrases ("make me a video")
135
+ // trip the detector into false positives, so don't even ask — the UI locale
136
+ // is the better signal at this length.
137
+ if (!text || text.length < 12) {
138
+ return uiTag ?? types_1.ELANGUAGE_CODE.en;
139
+ }
140
+ try {
141
+ const detected = await translation_service_1.translationService.detectLanguage(text);
142
+ const top = detected.languages?.[0];
143
+ // `reliable` is the detector's own confidence flag. Historically every
144
+ // caller ignored it, which is precisely how a timed-out detect call (which
145
+ // fails open to en/100%/reliable:false) silently forced English on
146
+ // everyone. Honour it: an unreliable verdict defers to the UI locale.
147
+ if (detected.reliable && top?.code) {
148
+ const tag = normalizeLanguageTag(top.code);
149
+ if (tag)
150
+ return tag;
151
+ }
152
+ logger_1.logger.info("outputLanguage: detection unreliable, using UI locale", {
153
+ uiLocale: uiTag,
154
+ topCode: top?.code,
155
+ reliable: detected.reliable,
156
+ });
157
+ }
158
+ catch (err) {
159
+ logger_1.logger.warn("outputLanguage: detection threw, using UI locale", {
160
+ uiLocale: uiTag,
161
+ err: err instanceof Error ? err.message : String(err),
162
+ });
163
+ }
164
+ return uiTag ?? types_1.ELANGUAGE_CODE.en;
165
+ }
166
+ /**
167
+ * Render the output-language rule for an LLM system prompt. Returns "" for
168
+ * English so the (overwhelmingly common) English path adds zero tokens and
169
+ * behaves exactly as it did before this feature existed.
170
+ *
171
+ * `kinds` names the viewer-facing surfaces the callee actually produces, so
172
+ * each prompt gets a rule about its own output rather than a generic one.
173
+ */
174
+ function buildOutputLanguageSection(outputLanguage, kinds) {
175
+ if (isEnglish(outputLanguage))
176
+ return "";
177
+ const name = languageDisplayName(outputLanguage);
178
+ return [
179
+ "",
180
+ `OUTPUT LANGUAGE — write ${kinds} in ${name}.`,
181
+ ` - This is what the viewer hears and reads. It is NOT optional styling:`,
182
+ ` the user wrote their brief in ${name} and expects a ${name} video.`,
183
+ ` - Keep proper nouns, brand names, product names, and hashtags as-is.`,
184
+ ` - Do NOT translate the visual prompt / intent fields — those feed the`,
185
+ ` image and video models, which are tuned on English. They stay English`,
186
+ ` even though the spoken and on-screen copy is ${name}.`,
187
+ ` - Write natively in ${name}: idiomatic phrasing a native speaker would`,
188
+ ` use, not a word-for-word translation of an English script.`,
189
+ ].join("\n");
190
+ }
@@ -34,8 +34,19 @@ export declare const TRANSLATION_FAILED = "TRANSLATION_FAILED";
34
34
  */
35
35
  declare function translate(text: string, from: ELANGUAGE_CODE, to?: ELANGUAGE_CODE, version?: "v1" | "v2"): Promise<string>;
36
36
  /**
37
- * Detect the language of `text`. Primary CF; on failure fails OPEN to English
38
- * (matches prior behavior — language detection must never block generation).
37
+ * Detect the language of `text`. Primary CF → cheap LLM → fail OPEN to English.
38
+ *
39
+ * The LLM layer matters more here than it does for `translate`. The primary
40
+ * endpoint is the same flaky Cloud Function, but detection's failure mode is
41
+ * silent rather than loud: it used to return en/100% with `reliable: false`,
42
+ * and since every caller ignored that flag, a detect timeout quietly forced
43
+ * English on a non-English user. That is one of the ways the product ended up
44
+ * English-only regardless of what the user wrote.
45
+ *
46
+ * The terminal fallback still returns English so detection can never block a
47
+ * generation run — but it keeps `reliable: false`, and callers
48
+ * (`resolveOutputLanguage`) now honour that flag and defer to the UI locale
49
+ * instead of treating the guess as fact.
39
50
  */
40
51
  declare function detectLanguage(text: string): Promise<IDetectLang>;
41
52
  export declare const translationService: {
@@ -1 +1 @@
1
- {"version":3,"file":"translation.service.d.ts","sourceRoot":"","sources":["../../../src/services/translation/translation.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AA+EvD;;;;GAIG;AACH,iBAAe,SAAS,CACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,cAAc,EACpB,EAAE,GAAE,cAAkC,EACtC,OAAO,GAAE,IAAI,GAAG,IAAW,GAC1B,OAAO,CAAC,MAAM,CAAC,CAsCjB;AAED;;;GAGG;AACH,iBAAe,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAwBhE;AAOD,eAAO,MAAM,kBAAkB;;;CAG9B,CAAC;AAGF,qDAAqD;AACrD,eAAO,MAAM,qBAAqB,kBAAY,CAAC;AAC/C,0DAA0D;AAC1D,eAAO,MAAM,UAAU,uBAAiB,CAAC"}
1
+ {"version":3,"file":"translation.service.d.ts","sourceRoot":"","sources":["../../../src/services/translation/translation.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AA+EvD;;;;GAIG;AACH,iBAAe,SAAS,CACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,cAAc,EACpB,EAAE,GAAE,cAAkC,EACtC,OAAO,GAAE,IAAI,GAAG,IAAW,GAC1B,OAAO,CAAC,MAAM,CAAC,CAsCjB;AAiCD;;;;;;;;;;;;;;GAcG;AACH,iBAAe,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA8ChE;AAOD,eAAO,MAAM,kBAAkB;;;CAG9B,CAAC;AAGF,qDAAqD;AACrD,eAAO,MAAM,qBAAqB,kBAAY,CAAC;AAC/C,0DAA0D;AAC1D,eAAO,MAAM,UAAU,uBAAiB,CAAC"}