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.
- package/lib/globals/aiModels/enums.d.ts +1 -0
- package/lib/globals/aiModels/enums.d.ts.map +1 -1
- package/lib/globals/aiModels/enums.js +3 -0
- package/lib/globals/aiModels/extendCapability.d.ts +26 -0
- package/lib/globals/aiModels/extendCapability.d.ts.map +1 -0
- package/lib/globals/aiModels/extendCapability.js +42 -0
- package/lib/globals/aiModels/index.d.ts +1 -0
- package/lib/globals/aiModels/index.d.ts.map +1 -1
- package/lib/globals/aiModels/index.js +1 -0
- package/lib/globals/aiModels/providers/hostedAvatars.js +10 -10
- package/lib/globals/creditUnit.d.ts +20 -33
- package/lib/globals/creditUnit.d.ts.map +1 -1
- package/lib/globals/creditUnit.js +20 -33
- package/lib/globals/types.d.ts +34 -2
- package/lib/globals/types.d.ts.map +1 -1
- package/lib/globals/types.js +37 -0
- package/lib/models/demoVideoProject.model.d.ts +213 -0
- package/lib/models/demoVideoProject.model.d.ts.map +1 -1
- package/lib/models/index.d.ts +2 -0
- package/lib/models/index.d.ts.map +1 -1
- package/lib/models/index.js +2 -0
- package/lib/models/mediaUpload.model.d.ts +25 -0
- package/lib/models/mediaUpload.model.d.ts.map +1 -1
- package/lib/models/productConnection.model.d.ts +57 -0
- package/lib/models/productConnection.model.d.ts.map +1 -0
- package/lib/models/productConnection.model.js +7 -0
- package/lib/models/video.model.d.ts +11 -0
- package/lib/models/video.model.d.ts.map +1 -1
- package/lib/models/videoQaJob.model.d.ts +61 -0
- package/lib/models/videoQaJob.model.d.ts.map +1 -0
- package/lib/models/videoQaJob.model.js +16 -0
- package/lib/schemas/brandKit.schema.d.ts +3 -1
- package/lib/schemas/brandKit.schema.d.ts.map +1 -1
- package/lib/schemas/brandKit.schema.js +9 -0
- package/lib/schemas/brief.schema.d.ts +5 -4
- package/lib/schemas/brief.schema.d.ts.map +1 -1
- package/lib/schemas/brief.schema.js +23 -1
- package/lib/schemas/demoQuestion.schema.d.ts +24 -4
- package/lib/schemas/demoQuestion.schema.d.ts.map +1 -1
- package/lib/schemas/demoQuestion.schema.js +8 -2
- package/lib/schemas/demoSpec.schema.d.ts +40 -6
- package/lib/schemas/demoSpec.schema.d.ts.map +1 -1
- package/lib/schemas/demoSpec.schema.js +46 -1
- package/lib/schemas/project.schema.d.ts +33 -3
- package/lib/schemas/project.schema.d.ts.map +1 -1
- package/lib/schemas/project.schema.js +22 -0
- package/lib/schemas/social.schema.d.ts +1 -1
- package/lib/schemas/videoPlan.schema.d.ts +22 -20
- package/lib/schemas/videoPlan.schema.d.ts.map +1 -1
- package/lib/schemas/videoPlan.schema.js +19 -0
- package/lib/services/agent/editClassifier.d.ts +10 -10
- package/lib/services/agent/eval/types.d.ts +3 -2
- package/lib/services/agent/eval/types.d.ts.map +1 -1
- package/lib/services/agent/executor/core.d.ts.map +1 -1
- package/lib/services/agent/executor/core.js +11 -0
- package/lib/services/agent/planner/Planner.d.ts.map +1 -1
- package/lib/services/agent/planner/Planner.js +5 -0
- package/lib/services/agent/planner/overlayRegen.d.ts.map +1 -1
- package/lib/services/agent/planner/overlayRegen.js +5 -0
- package/lib/services/agent/planner/plannerMessages.d.ts.map +1 -1
- package/lib/services/agent/planner/plannerMessages.js +10 -1
- package/lib/services/agent/planner/scriptFirstPlanner.d.ts.map +1 -1
- package/lib/services/agent/planner/scriptFirstPlanner.js +2 -0
- package/lib/services/agent/regenCore.d.ts.map +1 -1
- package/lib/services/agent/regenCore.js +11 -1
- package/lib/services/agent/runHelpers.d.ts +8 -0
- package/lib/services/agent/runHelpers.d.ts.map +1 -1
- package/lib/services/agent/runHelpers.js +5 -1
- package/lib/services/agent/tools/chapterOutline.tool.d.ts +8 -0
- package/lib/services/agent/tools/chapterOutline.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/chapterOutline.tool.js +21 -8
- package/lib/services/agent/tools/composeScene.tool.d.ts +32 -2
- package/lib/services/agent/tools/composeScene.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/estimateCost.tool.d.ts +11 -1
- package/lib/services/agent/tools/estimateCost.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/extendVideo.tool.d.ts +9 -3
- package/lib/services/agent/tools/extendVideo.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/extendVideo.tool.js +12 -27
- package/lib/services/agent/tools/generateAvatarVideo.tool.d.ts +1 -1
- package/lib/services/agent/tools/generateScript.tool.d.ts +3 -2
- package/lib/services/agent/tools/generateScript.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/generateScript.tool.js +16 -7
- package/lib/services/agent/tools/generateVoiceover.tool.d.ts +1 -1
- package/lib/services/agent/tools/planVideo.tool.d.ts +11 -8
- package/lib/services/agent/tools/planVideo.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/render.tool.d.ts +11 -1
- package/lib/services/agent/tools/render.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/searchStock.tool.d.ts +1 -1
- package/lib/services/agent/tools/searchUserLibrary.tool.d.ts +4 -4
- package/lib/services/aiGen/providers/kling/kling.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/kling/kling.service.js +22 -3
- package/lib/services/aiGen/providers/kling/klingStatus.d.ts +7 -0
- package/lib/services/aiGen/providers/kling/klingStatus.d.ts.map +1 -1
- package/lib/services/aiGen/providers/kling/klingStatus.js +41 -4
- package/lib/services/aiGen/providers/pixverse/pixverse.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/pixverse/pixverse.service.js +25 -0
- package/lib/services/aiGen/providers/types.d.ts +20 -0
- package/lib/services/aiGen/providers/types.d.ts.map +1 -1
- package/lib/services/avatarGen/avatarProviderFactory.d.ts.map +1 -1
- package/lib/services/avatarGen/avatarProviderFactory.js +3 -0
- package/lib/services/avatarGen/index.d.ts +1 -0
- package/lib/services/avatarGen/index.d.ts.map +1 -1
- package/lib/services/avatarGen/index.js +1 -0
- package/lib/services/avatarGen/providers/synthesiaAvatarProvider.d.ts +53 -0
- package/lib/services/avatarGen/providers/synthesiaAvatarProvider.d.ts.map +1 -0
- package/lib/services/avatarGen/providers/synthesiaAvatarProvider.js +176 -0
- package/lib/services/demo/demoAuthor.d.ts +7 -0
- package/lib/services/demo/demoAuthor.d.ts.map +1 -1
- package/lib/services/demo/demoAuthor.js +2 -0
- package/lib/services/demo/demoAuthorPrompt.d.ts +6 -0
- package/lib/services/demo/demoAuthorPrompt.d.ts.map +1 -1
- package/lib/services/demo/demoAuthorPrompt.js +24 -2
- package/lib/services/demo/demoCaptions.d.ts +69 -0
- package/lib/services/demo/demoCaptions.d.ts.map +1 -0
- package/lib/services/demo/demoCaptions.js +152 -0
- package/lib/services/demo/demoMusic.d.ts +8 -1
- package/lib/services/demo/demoMusic.d.ts.map +1 -1
- package/lib/services/demo/demoMusic.js +32 -16
- package/lib/services/demo/demoScriptPrompt.d.ts +2 -1
- package/lib/services/demo/demoScriptPrompt.d.ts.map +1 -1
- package/lib/services/demo/demoScriptPrompt.js +29 -2
- package/lib/services/demo/demoStockAssets.d.ts +29 -0
- package/lib/services/demo/demoStockAssets.d.ts.map +1 -0
- package/lib/services/demo/demoStockAssets.js +107 -0
- package/lib/services/demo/index.d.ts +3 -0
- package/lib/services/demo/index.d.ts.map +1 -1
- package/lib/services/demo/index.js +3 -0
- package/lib/services/demo/productConnection.service.d.ts +78 -0
- package/lib/services/demo/productConnection.service.d.ts.map +1 -0
- package/lib/services/demo/productConnection.service.js +125 -0
- package/lib/services/editor/planToProject.d.ts.map +1 -1
- package/lib/services/editor/planToProject.helpers.d.ts +1 -0
- package/lib/services/editor/planToProject.helpers.d.ts.map +1 -1
- package/lib/services/editor/planToProject.helpers.js +3 -0
- package/lib/services/editor/planToProject.js +39 -0
- package/lib/services/editor/projectToDesign.js +13 -1
- package/lib/services/firestore.service.d.ts +14 -0
- package/lib/services/firestore.service.d.ts.map +1 -1
- package/lib/services/firestore.service.js +16 -0
- package/lib/services/translation/index.d.ts +1 -0
- package/lib/services/translation/index.d.ts.map +1 -1
- package/lib/services/translation/index.js +8 -1
- package/lib/services/translation/outputLanguage.d.ts +75 -0
- package/lib/services/translation/outputLanguage.d.ts.map +1 -0
- package/lib/services/translation/outputLanguage.js +190 -0
- package/lib/services/translation/translation.service.d.ts +13 -2
- package/lib/services/translation/translation.service.d.ts.map +1 -1
- package/lib/services/translation/translation.service.js +66 -5
- package/lib/services/tts/index.d.ts +1 -0
- package/lib/services/tts/index.d.ts.map +1 -1
- package/lib/services/tts/index.js +1 -0
- package/lib/services/tts/providers/elevenlabs.service.d.ts +7 -0
- package/lib/services/tts/providers/elevenlabs.service.d.ts.map +1 -1
- package/lib/services/tts/providers/elevenlabs.service.js +69 -13
- package/lib/services/tts/types.d.ts +29 -0
- package/lib/services/tts/types.d.ts.map +1 -1
- package/lib/services/tts/wordTimings.d.ts +27 -0
- package/lib/services/tts/wordTimings.d.ts.map +1 -0
- package/lib/services/tts/wordTimings.js +57 -0
- package/lib/utils/billableDuration.d.ts +11 -0
- package/lib/utils/billableDuration.d.ts.map +1 -0
- package/lib/utils/billableDuration.js +91 -0
- package/lib/utils/index.d.ts +3 -0
- package/lib/utils/index.d.ts.map +1 -1
- package/lib/utils/index.js +3 -0
- package/lib/utils/mp4Duration.d.ts +38 -0
- package/lib/utils/mp4Duration.d.ts.map +1 -0
- package/lib/utils/mp4Duration.js +164 -0
- package/lib/utils/socialEntitlements.d.ts +51 -0
- package/lib/utils/socialEntitlements.d.ts.map +1 -0
- package/lib/utils/socialEntitlements.js +65 -0
- 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,
|
|
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
|
|
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
|
-
|
|
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":"AAAA,OAAO,EACL,YAAY,EAEZ,gBAAgB,EAEhB,aAAa,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,iBAAiB,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAelC;;;;GAIG;AACH,qBAAa,gBAAgB;IAE3B,MAAM,CAAC,YAAY,oDAEqC;IAExD,MAAM,CAAC,YAAY,oDAEqC;IAExD,MAAM,CAAC,gBAAgB,wDAEqC;IAE5D,MAAM,CAAC,OAAO,+CAEqC;IAEnD,MAAM,CAAC,QAAQ,gDAEqC;IAEpD,MAAM,CAAC,UAAU;;;;;;;;;;;;;;;;;;;qBAEqC;IAEtD,MAAM,CAAC,aAAa,uDAEuC;IAE3D,MAAM,CAAC,gBAAgB,0DAEuC;IAE9D,MAAM,CAAC,YAAY,oDAEqC;IAExD,MAAM,CAAC,cAAc,uDAEsC;IAE3D,MAAM,CAAC,gBAAgB,wDAEqC;IAE5D,MAAM,CAAC,YAAY,oDAEqC;IAExD,MAAM,CAAC,SAAS,iDAEqC;IAErD,MAAM,CAAC,eAAe,uDAEqC;IAG3D,MAAM,CAAC,oBAAoB,4DAEqC;IAEhE,8EAA8E;IAC9E,MAAM,CAAC,oBAAoB,4DAEqC;
|
|
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 +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
|
|
38
|
-
*
|
|
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;
|
|
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"}
|