@nodaro/shared 2.14.0 → 2.16.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/dist/index.cjs +94 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +145 -11
- package/dist/index.d.ts +145 -11
- package/dist/index.js +90 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/image-mention-slug.test.ts +303 -0
- package/src/__tests__/prompt-length-limits.test.ts +2 -2
- package/src/__tests__/to-connected-references.test.ts +45 -0
- package/src/__tests__/video-analysis.test.ts +11 -0
- package/src/character-voice.ts +4 -3
- package/src/image-mention-slug.ts +236 -0
- package/src/index.ts +9 -0
- package/src/model-catalog.ts +10 -7
- package/src/model-constants.ts +8 -6
- package/src/model-tree.ts +1 -0
- package/src/to-connected-references.ts +16 -2
- package/src/video-analysis.ts +9 -0
package/dist/index.cjs
CHANGED
|
@@ -1978,18 +1978,17 @@ var AUDIO_MODELS = {
|
|
|
1978
1978
|
"elevenlabs-dialogue": {
|
|
1979
1979
|
id: "elevenlabs-dialogue",
|
|
1980
1980
|
kind: "audio",
|
|
1981
|
-
|
|
1981
|
+
// Its own mode, never "tts": the script shape (inputs[]) doesn't fit the
|
|
1982
|
+
// single-text generate_speech contract, so list_models must never offer
|
|
1983
|
+
// it there. The dialogue-capable MCP verb is `generate_dialogue`.
|
|
1984
|
+
modes: ["dialogue"],
|
|
1982
1985
|
family: "ElevenLabs",
|
|
1983
1986
|
label: "ElevenLabs Dialogue v3",
|
|
1984
1987
|
series: "ElevenLabs",
|
|
1985
|
-
description: "Multi-speaker dialogue
|
|
1988
|
+
description: "Multi-speaker dialogue via the direct ElevenLabs API \u2014 give it a script, it voices each role (any voice: premade, library, or cloned).",
|
|
1986
1989
|
useCases: ["tts", "dialogue", "multi-speaker"],
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
// shape), NOT the single-text generate_speech verb. Hide from MCP
|
|
1990
|
-
// list_models so generate_speech (TTS_PROVIDERS) can't advertise it and
|
|
1991
|
-
// then 400. Re-expose if a dialogue-capable MCP verb is added.
|
|
1992
|
-
mcpHidden: true
|
|
1990
|
+
features: ["audio-tags", "voice-cloning"],
|
|
1991
|
+
pricing: [{ identifier: "elevenlabs-dialogue", credits: 25, note: "per 1K chars" }]
|
|
1993
1992
|
},
|
|
1994
1993
|
// ── ElevenLabs voice utilities ──
|
|
1995
1994
|
"voice-clone": {
|
|
@@ -2548,10 +2547,10 @@ var MAX_TTS_CHARS_BY_PROVIDER = {
|
|
|
2548
2547
|
// == eleven_flash_v2_5 (functionally equivalent)
|
|
2549
2548
|
"elevenlabs-multilingual": 1e4,
|
|
2550
2549
|
// eleven_multilingual_v2
|
|
2551
|
-
"elevenlabs-v3":
|
|
2552
|
-
//
|
|
2553
|
-
"elevenlabs-dialogue":
|
|
2554
|
-
//
|
|
2550
|
+
"elevenlabs-v3": 5e3,
|
|
2551
|
+
// official cap (probed: 5,200 chars accepted; keep the clamp)
|
|
2552
|
+
"elevenlabs-dialogue": 5e3
|
|
2553
|
+
// total across lines; ≤2,000 recommended for best quality
|
|
2555
2554
|
};
|
|
2556
2555
|
function getMaxTtsChars(provider) {
|
|
2557
2556
|
return provider && MAX_TTS_CHARS_BY_PROVIDER[provider] || TTS_TEXT_MAX;
|
|
@@ -9917,6 +9916,65 @@ function findLocationMentionTokens(prompt, knownLocationSlugs) {
|
|
|
9917
9916
|
return tokens;
|
|
9918
9917
|
}
|
|
9919
9918
|
|
|
9919
|
+
// src/image-mention-slug.ts
|
|
9920
|
+
var IMAGE_SLUG_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
9921
|
+
function imageMentionSlug(name) {
|
|
9922
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
9923
|
+
}
|
|
9924
|
+
function parseImageMentionToken(text) {
|
|
9925
|
+
if (!text.startsWith("@")) return null;
|
|
9926
|
+
let rest = text.slice(1);
|
|
9927
|
+
if (rest.length === 0 || !/^[a-z]/.test(rest)) return null;
|
|
9928
|
+
let lockField = {};
|
|
9929
|
+
if (rest.endsWith("~nolock")) {
|
|
9930
|
+
rest = rest.slice(0, -"~nolock".length);
|
|
9931
|
+
lockField = { lock: false };
|
|
9932
|
+
} else if (rest.endsWith("~lock")) {
|
|
9933
|
+
rest = rest.slice(0, -"~lock".length);
|
|
9934
|
+
lockField = { lock: true };
|
|
9935
|
+
}
|
|
9936
|
+
const parts = rest.split(":");
|
|
9937
|
+
if (parts.length < 2 || parts.length > 3) return null;
|
|
9938
|
+
const [imageSlug, indexStr, third] = parts;
|
|
9939
|
+
if (!IMAGE_SLUG_PATTERN.test(imageSlug)) return null;
|
|
9940
|
+
if (!/^\d+$/.test(indexStr)) return null;
|
|
9941
|
+
const imageIndex = parseInt(indexStr, 10);
|
|
9942
|
+
if (!Number.isInteger(imageIndex) || imageIndex < 1) return null;
|
|
9943
|
+
if (parts.length === 2) return { imageSlug, imageIndex, ...lockField };
|
|
9944
|
+
if (!IMAGE_SLUG_PATTERN.test(third)) return null;
|
|
9945
|
+
return { imageSlug, imageIndex, role: third, ...lockField };
|
|
9946
|
+
}
|
|
9947
|
+
function findImageMentionTokens(prompt, knownImageSlugs) {
|
|
9948
|
+
const tokens = [];
|
|
9949
|
+
const regex = /(?:^|[^a-zA-Z0-9])(@[a-z][a-z0-9-]*:\d+(?::[a-z][a-z0-9-]*)?(?:~(?:no)?lock(?![a-z0-9-]))?)(?![:a-z0-9-])/g;
|
|
9950
|
+
const knownSet = new Set(knownImageSlugs);
|
|
9951
|
+
for (const match of prompt.matchAll(regex)) {
|
|
9952
|
+
const token = match[1];
|
|
9953
|
+
const offset = (match.index ?? 0) + (match[0].length - token.length);
|
|
9954
|
+
if (/^\/[a-z]/.test(prompt.slice(offset + token.length))) continue;
|
|
9955
|
+
const parsed = parseImageMentionToken(token);
|
|
9956
|
+
if (parsed && knownSet.has(parsed.imageSlug)) {
|
|
9957
|
+
tokens.push({ token, ...parsed, offset });
|
|
9958
|
+
}
|
|
9959
|
+
}
|
|
9960
|
+
return tokens;
|
|
9961
|
+
}
|
|
9962
|
+
function imageMentionSlugForRef(r) {
|
|
9963
|
+
if (r.source !== "wired-image" && r.source !== "manual") return null;
|
|
9964
|
+
if (r.isExtraRef === true) return null;
|
|
9965
|
+
if (!r.url || !r.defaultName) return null;
|
|
9966
|
+
const slug = imageMentionSlug(r.defaultName);
|
|
9967
|
+
return IMAGE_SLUG_PATTERN.test(slug) ? slug : null;
|
|
9968
|
+
}
|
|
9969
|
+
function knownImageSlugsFromRefs(refs) {
|
|
9970
|
+
const out = /* @__PURE__ */ new Set();
|
|
9971
|
+
for (const r of refs) {
|
|
9972
|
+
const slug = imageMentionSlugForRef(r);
|
|
9973
|
+
if (slug) out.add(slug);
|
|
9974
|
+
}
|
|
9975
|
+
return [...out];
|
|
9976
|
+
}
|
|
9977
|
+
|
|
9920
9978
|
// src/to-connected-references.ts
|
|
9921
9979
|
function toConnectedReference(entity) {
|
|
9922
9980
|
if (entity.kind === "character") {
|
|
@@ -9932,6 +9990,15 @@ function toConnectedReference(entity) {
|
|
|
9932
9990
|
variantDisplayName: entity.variant ?? "canonical"
|
|
9933
9991
|
};
|
|
9934
9992
|
}
|
|
9993
|
+
if (entity.kind === "image") {
|
|
9994
|
+
return {
|
|
9995
|
+
id: entity.id,
|
|
9996
|
+
defaultName: entity.name,
|
|
9997
|
+
source: "wired-image",
|
|
9998
|
+
url: entity.url ?? "",
|
|
9999
|
+
...entity.description ? { description: entity.description } : {}
|
|
10000
|
+
};
|
|
10001
|
+
}
|
|
9935
10002
|
if (entity.kind === "creature") {
|
|
9936
10003
|
return {
|
|
9937
10004
|
id: entity.id,
|
|
@@ -12818,6 +12885,7 @@ var MODE_TO_NODE = {
|
|
|
12818
12885
|
"dubbing": "dubbing",
|
|
12819
12886
|
"forced-alignment": "forced-alignment",
|
|
12820
12887
|
"stt": "transcribe",
|
|
12888
|
+
"dialogue": "text-to-dialogue",
|
|
12821
12889
|
"video-analysis": "video-analysis"
|
|
12822
12890
|
};
|
|
12823
12891
|
function modelToNodeTarget(modelId) {
|
|
@@ -13217,6 +13285,15 @@ var windowSceneBase = zod.z.object({
|
|
|
13217
13285
|
/** Effects on this shot's PICTURE. Absent ⇒ a clean image. */
|
|
13218
13286
|
effects: zod.z.array(zod.z.enum(VIDEO_ANALYSIS_VISUAL_EFFECTS)).optional(),
|
|
13219
13287
|
transitionOut: zod.z.enum(VIDEO_ANALYSIS_TRANSITIONS).optional(),
|
|
13288
|
+
// Round 4 (2026-08-30, recast shot craft rev 1.5 Appendix F.8): the edit into
|
|
13289
|
+
// the next scene in the analyser's OWN WORDS — a few words of what it saw
|
|
13290
|
+
// ("fast blurred pan left", "fade to black", "zoom-blur warp into the tunnel")
|
|
13291
|
+
// — or absent when the take continues through the change or no edit is seen
|
|
13292
|
+
// (nothing asserted: the video model decides from story and refs). The closed
|
|
13293
|
+
// `transitionOut` vocabulary above is LEGACY from here on: kept so stored
|
|
13294
|
+
// blueprints still parse, never emitted again. Readers take
|
|
13295
|
+
// `transition ?? transitionOut`.
|
|
13296
|
+
transition: zod.z.string().trim().min(1).max(120).optional(),
|
|
13220
13297
|
// Array of concurrent layers (music + speech + sfx together); [] = silence.
|
|
13221
13298
|
audio: zod.z.array(audioLayerSchema),
|
|
13222
13299
|
/** slotId → variationId for slots wearing a NON-default look in this scene
|
|
@@ -14226,6 +14303,7 @@ exports.extractVideoDurationFromNode = extractVideoDurationFromNode;
|
|
|
14226
14303
|
exports.fieldKeyFromHandle = fieldKeyFromHandle;
|
|
14227
14304
|
exports.filterCloneNodes = filterCloneNodes;
|
|
14228
14305
|
exports.findCharacterMentionTokens = findCharacterMentionTokens;
|
|
14306
|
+
exports.findImageMentionTokens = findImageMentionTokens;
|
|
14229
14307
|
exports.findLocationMentionTokens = findLocationMentionTokens;
|
|
14230
14308
|
exports.findSeedance2AudioOverLimit = findSeedance2AudioOverLimit;
|
|
14231
14309
|
exports.firstSightExtraRole = firstSightExtraRole;
|
|
@@ -14280,6 +14358,8 @@ exports.hasContiguousSegmentDurations = hasContiguousSegmentDurations;
|
|
|
14280
14358
|
exports.hasFeature = hasFeature;
|
|
14281
14359
|
exports.hexToRgbaArray = hexToRgbaArray;
|
|
14282
14360
|
exports.humanizeSlotSid = humanizeSlotSid;
|
|
14361
|
+
exports.imageMentionSlug = imageMentionSlug;
|
|
14362
|
+
exports.imageMentionSlugForRef = imageMentionSlugForRef;
|
|
14283
14363
|
exports.imageReferenceLimit = imageReferenceLimit;
|
|
14284
14364
|
exports.inferMusicVideo = inferMusicVideo;
|
|
14285
14365
|
exports.isAggregateableType = isAggregateableType;
|
|
@@ -14305,6 +14385,7 @@ exports.isVeoProvider = isVeoProvider;
|
|
|
14305
14385
|
exports.isVideoAnalysisMixedTier = isVideoAnalysisMixedTier;
|
|
14306
14386
|
exports.isVideoAnalysisTier = isVideoAnalysisTier;
|
|
14307
14387
|
exports.jsonResultToList = jsonResultToList;
|
|
14388
|
+
exports.knownImageSlugsFromRefs = knownImageSlugsFromRefs;
|
|
14308
14389
|
exports.listBoardTemplates = listBoardTemplates;
|
|
14309
14390
|
exports.listModels = listModels;
|
|
14310
14391
|
exports.listSlotSids = listSlotSids;
|
|
@@ -14339,6 +14420,7 @@ exports.parseAttributedDialogue = parseAttributedDialogue;
|
|
|
14339
14420
|
exports.parseCharacterMentionToken = parseCharacterMentionToken;
|
|
14340
14421
|
exports.parseGroupHandle = parseGroupHandle;
|
|
14341
14422
|
exports.parseHandleId = parseHandleId;
|
|
14423
|
+
exports.parseImageMentionToken = parseImageMentionToken;
|
|
14342
14424
|
exports.parseListExpression = parseListExpression;
|
|
14343
14425
|
exports.parseLocationMentionToken = parseLocationMentionToken;
|
|
14344
14426
|
exports.parseNodePresetExport = parseNodePresetExport;
|