@nodaro/shared 2.0.2 → 2.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nodaro/shared",
3
- "version": "2.0.2",
3
+ "version": "2.1.0",
4
4
  "description": "Shared types, model catalog, wire contracts, and structural vocabularies for the Nodaro platform and SDK.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -56,12 +56,15 @@ describe("scraper-actors", () => {
56
56
  }
57
57
  })
58
58
 
59
+ // Values match `STATIC_CREDIT_COSTS` / `model_pricing`; the backend-side guard
60
+ // `shared-credit-table-sync.test.ts` is what keeps the two equal. This one only
61
+ // pins that every SKU is present and priced.
59
62
  it("credit costs include bare fallback + every composite SKU", () => {
60
- expect(SCRAPER_CREDIT_COSTS["web-scrape"]).toBe(2)
61
- expect(SCRAPER_CREDIT_COSTS["web-scrape:google-search"]).toBe(3)
62
- expect(SCRAPER_CREDIT_COSTS["web-scrape:content-crawler"]).toBe(1)
63
- expect(SCRAPER_CREDIT_COSTS["web-scrape:content-crawler:site"]).toBe(5)
64
- expect(SCRAPER_CREDIT_COSTS["web-scrape:instagram"]).toBe(1)
65
- expect(SCRAPER_CREDIT_COSTS["web-scrape:tiktok"]).toBe(1)
63
+ expect(SCRAPER_CREDIT_COSTS["web-scrape"]).toBe(20)
64
+ expect(SCRAPER_CREDIT_COSTS["web-scrape:google-search"]).toBe(30)
65
+ expect(SCRAPER_CREDIT_COSTS["web-scrape:content-crawler"]).toBe(10)
66
+ expect(SCRAPER_CREDIT_COSTS["web-scrape:content-crawler:site"]).toBe(50)
67
+ expect(SCRAPER_CREDIT_COSTS["web-scrape:instagram"]).toBe(10)
68
+ expect(SCRAPER_CREDIT_COSTS["web-scrape:tiktok"]).toBe(10)
66
69
  })
67
70
  })
@@ -88,10 +88,11 @@ describe("bare video-analysis node-type credit id", () => {
88
88
  }
89
89
  // The migration writes this number; keep them in lockstep (277 wrote 200,
90
90
  // 279 wrote 739, 283 wrote 346, 284 wrote 350 — `smart` owns the ceiling and
91
- // gained the continuity pass — 288 wrote 3500 as a x10 of that, and 293
92
- // corrects it to 3496 by RE-DERIVING `smart:600s` from the plugin formula
93
- // instead of scaling it, same as every other row in the table).
94
- expect(ceiling).toBe(3496)
91
+ // gained the continuity pass — 288 wrote 3500 as a x10 of that, 293
92
+ // corrected it to 3496 by RE-DERIVING `smart:600s` from the plugin formula,
93
+ // and 294 wrote 1868: the smart re-base measured 6 fps equal-or-better than
94
+ // 24 and the schedule regenerated ~47% lower at the ceiling bucket).
95
+ expect(ceiling).toBe(1868)
95
96
  })
96
97
 
97
98
  it("the bare id still bounds the default tier at the ceiling bucket", () => {
@@ -144,11 +144,14 @@ export interface ModelRecommendation {
144
144
  export const MODEL_RECOMMENDATIONS: readonly ModelRecommendation[] = [
145
145
  // image
146
146
  { intent: "best for typography / logos / text-heavy", modelIds: ["nano-banana-pro", "gpt-image-2"], note: "Nano Banana Pro for diagrams / complex text; GPT Image 2 for logos and short copy." },
147
- { intent: "cheapest realistic image", modelIds: ["z-image", "qwen", "imagen4-fast"], note: "Z-Image is the cheapest at 1 credit. Qwen / Imagen4 Fast for slightly higher quality." },
147
+ // Notes name the RANKING, not the price the price sits in the generated
148
+ // table directly below them and in `pricing`, so restating it here just
149
+ // creates a copy that rots (this one said "1 credit" long after it was 2).
150
+ { intent: "cheapest realistic image", modelIds: ["z-image", "qwen", "imagen4-fast"], note: "Z-Image is the cheapest. Qwen / Imagen4 Fast for slightly higher quality." },
148
151
  { intent: "highest fidelity image", modelIds: ["nano-banana-pro", "imagen4-ultra", "flux-flex"], note: "Pick by family preference; all three are premium tiers." },
149
152
  { intent: "image edit / restyle", modelIds: ["flux-kontext", "ideogram-remix", "seedream-5-pro-i2i"], note: "Flux Kontext preserves identity; Ideogram Remix is character-aware; Seedream 5 Pro for instruction-based edits (5 Lite is the budget option)." },
150
153
  { intent: "highest-resolution image (4K / 8K)", modelIds: ["topaz-image-upscale", "nano-banana-pro", "gpt-image-2"], note: "Generate at native then Topaz upscale for 8K." },
151
- { intent: "background removal / cutout", modelIds: ["recraft-remove-bg"], note: "1 credit, no prompt needed." },
154
+ { intent: "background removal / cutout", modelIds: ["recraft-remove-bg"], note: "Cheap, no prompt needed." },
152
155
  // video
153
156
  { intent: "best cinematic video", modelIds: ["veo3", "kling-3.0", "seedance-2"], note: "VEO 3.1 Quality for premium narrative; Kling 3.0 for music-synced motion; Seedance 2 for reference-driven consistency." },
154
157
  { intent: "cheap batch video clips", modelIds: ["veo3.1", "wan-turbo", "bytedance-lite"], note: "VEO 3.1 Fast is the best price/quality balance with native audio." },
@@ -1815,11 +1818,11 @@ const VIDEO_MODELS: Record<string, ModelCatalogEntry> = {
1815
1818
  description: "Legacy fast-tier analysis model (pre-2026-07). Kept so stored raw-model configs keep running and keep pricing under their own identifier; new fast-tier runs use the current fast model.",
1816
1819
  useCases: ["video-analysis", "shot-list", "fast"],
1817
1820
  pricing: [
1818
- { identifier: "video-analysis:gemini-3-flash", credits: 136, note: "10-min ceiling (no duration given)" },
1819
- { identifier: "video-analysis:gemini-3-flash:60s", credits: 23 },
1820
- { identifier: "video-analysis:gemini-3-flash:180s", credits: 32 },
1821
- { identifier: "video-analysis:gemini-3-flash:360s", credits: 81 },
1822
- { identifier: "video-analysis:gemini-3-flash:600s", credits: 136, note: "10-min ceiling" },
1821
+ { identifier: "video-analysis:gemini-3-flash", credits: 143, note: "10-min ceiling (no duration given)" },
1822
+ { identifier: "video-analysis:gemini-3-flash:60s", credits: 24 },
1823
+ { identifier: "video-analysis:gemini-3-flash:180s", credits: 33 },
1824
+ { identifier: "video-analysis:gemini-3-flash:360s", credits: 86 },
1825
+ { identifier: "video-analysis:gemini-3-flash:600s", credits: 143, note: "10-min ceiling" },
1823
1826
  ],
1824
1827
  },
1825
1828
  "gemini-3.6-flash-video-analysis": {
@@ -1832,11 +1835,11 @@ const VIDEO_MODELS: Record<string, ModelCatalogEntry> = {
1832
1835
  description: "Analyze a video into a structured shot list (scenes, camera, audio) — fast, economy tier. Billed per duration bucket.",
1833
1836
  useCases: ["video-analysis", "shot-list", "fast"],
1834
1837
  pricing: [
1835
- { identifier: "video-analysis:gemini-3.6-flash", credits: 374, note: "10-min ceiling (no duration given)" },
1836
- { identifier: "video-analysis:gemini-3.6-flash:60s", credits: 61 },
1837
- { identifier: "video-analysis:gemini-3.6-flash:180s", credits: 88 },
1838
- { identifier: "video-analysis:gemini-3.6-flash:360s", credits: 224 },
1839
- { identifier: "video-analysis:gemini-3.6-flash:600s", credits: 374, note: "10-min ceiling" },
1838
+ { identifier: "video-analysis:gemini-3.6-flash", credits: 395, note: "10-min ceiling (no duration given)" },
1839
+ { identifier: "video-analysis:gemini-3.6-flash:60s", credits: 65 },
1840
+ { identifier: "video-analysis:gemini-3.6-flash:180s", credits: 92 },
1841
+ { identifier: "video-analysis:gemini-3.6-flash:360s", credits: 237 },
1842
+ { identifier: "video-analysis:gemini-3.6-flash:600s", credits: 395, note: "10-min ceiling" },
1840
1843
  ],
1841
1844
  },
1842
1845
  "gemini-3.1-pro-video-analysis": {
@@ -1849,11 +1852,11 @@ const VIDEO_MODELS: Record<string, ModelCatalogEntry> = {
1849
1852
  description: "Analyze a video into a structured shot list (scenes, camera, audio) — higher-fidelity, default tier. Billed per duration bucket.",
1850
1853
  useCases: ["video-analysis", "shot-list", "cinematic"],
1851
1854
  pricing: [
1852
- { identifier: "video-analysis:gemini-3.1-pro", credits: 486, note: "10-min ceiling (no duration given)" },
1853
- { identifier: "video-analysis:gemini-3.1-pro:60s", credits: 82 },
1854
- { identifier: "video-analysis:gemini-3.1-pro:180s", credits: 111 },
1855
- { identifier: "video-analysis:gemini-3.1-pro:360s", credits: 291 },
1856
- { identifier: "video-analysis:gemini-3.1-pro:600s", credits: 486, note: "10-min ceiling" },
1855
+ { identifier: "video-analysis:gemini-3.1-pro", credits: 509, note: "10-min ceiling (no duration given)" },
1856
+ { identifier: "video-analysis:gemini-3.1-pro:60s", credits: 87 },
1857
+ { identifier: "video-analysis:gemini-3.1-pro:180s", credits: 116 },
1858
+ { identifier: "video-analysis:gemini-3.1-pro:360s", credits: 305 },
1859
+ { identifier: "video-analysis:gemini-3.1-pro:600s", credits: 509, note: "10-min ceiling" },
1857
1860
  ],
1858
1861
  },
1859
1862
  // Both mixed tiers are variants of the same advanced multi-engine analysis
@@ -1869,11 +1872,11 @@ const VIDEO_MODELS: Record<string, ModelCatalogEntry> = {
1869
1872
  description: "Our most advanced analysis tier — multiple analysis engines combined into one result for maximum completeness and accuracy. Billed per duration bucket.",
1870
1873
  useCases: ["video-analysis", "shot-list", "premium", "most-complete"],
1871
1874
  pricing: [
1872
- { identifier: "video-analysis:mixed", credits: 621, note: "10-min ceiling (no duration given)" },
1873
- { identifier: "video-analysis:mixed:60s", credits: 104 },
1874
- { identifier: "video-analysis:mixed:180s", credits: 142 },
1875
- { identifier: "video-analysis:mixed:360s", credits: 372 },
1876
- { identifier: "video-analysis:mixed:600s", credits: 621, note: "10-min ceiling" },
1875
+ { identifier: "video-analysis:mixed", credits: 651, note: "10-min ceiling (no duration given)" },
1876
+ { identifier: "video-analysis:mixed:60s", credits: 110 },
1877
+ { identifier: "video-analysis:mixed:180s", credits: 149 },
1878
+ { identifier: "video-analysis:mixed:360s", credits: 390 },
1879
+ { identifier: "video-analysis:mixed:600s", credits: 651, note: "10-min ceiling" },
1877
1880
  ],
1878
1881
  },
1879
1882
  // SMART — the accuracy tier, and the only one that does not rely on voting.
@@ -1890,11 +1893,11 @@ const VIDEO_MODELS: Record<string, ModelCatalogEntry> = {
1890
1893
  description: "Highest-accuracy analysis — a single deep pass that reads the footage frame by frame, finds its own shot boundaries, and identifies the cast by appearance. Best choice when the shot list will drive regeneration. Billed per duration bucket.",
1891
1894
  useCases: ["video-analysis", "shot-list", "premium", "most-accurate"],
1892
1895
  pricing: [
1893
- { identifier: "video-analysis:smart", credits: 3496, note: "10-min ceiling (no duration given)" },
1894
- { identifier: "video-analysis:smart:60s", credits: 454 },
1895
- { identifier: "video-analysis:smart:180s", credits: 975 },
1896
- { identifier: "video-analysis:smart:360s", credits: 2105 },
1897
- { identifier: "video-analysis:smart:600s", credits: 3496, note: "10-min ceiling" },
1896
+ { identifier: "video-analysis:smart", credits: 1868, note: "10-min ceiling (no duration given)" },
1897
+ { identifier: "video-analysis:smart:60s", credits: 333 },
1898
+ { identifier: "video-analysis:smart:180s", credits: 470 },
1899
+ { identifier: "video-analysis:smart:360s", credits: 1135 },
1900
+ { identifier: "video-analysis:smart:600s", credits: 1868, note: "10-min ceiling" },
1898
1901
  ],
1899
1902
  },
1900
1903
  }
@@ -72,12 +72,18 @@ export const TIER_PIPELINE_PARALLELISM: Record<string, number> = {
72
72
  }
73
73
 
74
74
  // Tier → default hard cost cap when max_cost_credits omitted (Architecture §6.6.3)
75
+ //
76
+ // These are a FRACTION OF THE TIER'S GRANT, so they move with `TIER_CREDITS`:
77
+ // the 2026-07-30 ×10 re-denomination multiplied every grant, and leaving these
78
+ // behind would have silently tightened each cap tenfold — a basic-tier pipeline
79
+ // would abort at 300 credits out of a 4,500-credit grant, i.e. 6% of the plan
80
+ // the user paid for, instead of the intended two-thirds.
75
81
  export const TIER_MAX_PIPELINE_COST_CREDITS: Record<string, number> = {
76
82
  free: 0,
77
- basic: 300,
78
- standard: 800,
79
- pro: 2000,
80
- business: 5000,
83
+ basic: 3000,
84
+ standard: 8000,
85
+ pro: 20000,
86
+ business: 50000,
81
87
  }
82
88
 
83
89
  // Per-stage soft timeout (matches workflow-orchestration)
@@ -16,15 +16,20 @@ export const SCRAPER_ACTOR_LABELS: Record<ScraperActorId, string> = {
16
16
  "rss": "RSS Feed",
17
17
  }
18
18
 
19
- /** Credit costs per composite SKU — must stay in sync with STATIC_CREDIT_COSTS in backend. */
19
+ /** Credit costs per composite SKU — must stay in sync with STATIC_CREDIT_COSTS in backend.
20
+ *
21
+ * "Must stay in sync" was doing no work: these were left at the pre-2026-07-30
22
+ * credit base while the backend moved, so every SKU here read a tenth of the
23
+ * real price. Values below are copied from `model_pricing`, which is what the
24
+ * user is actually charged. */
20
25
  export const SCRAPER_CREDIT_COSTS: Record<string, number> = {
21
- "web-scrape": 2,
22
- "web-scrape:google-search": 3,
23
- "web-scrape:content-crawler": 1,
24
- "web-scrape:content-crawler:site": 5,
25
- "web-scrape:instagram": 1,
26
- "web-scrape:tiktok": 1,
27
- "web-scrape:rss": 1,
26
+ "web-scrape": 20,
27
+ "web-scrape:google-search": 30,
28
+ "web-scrape:content-crawler": 10,
29
+ "web-scrape:content-crawler:site": 50,
30
+ "web-scrape:instagram": 10,
31
+ "web-scrape:tiktok": 10,
32
+ "web-scrape:rss": 10,
28
33
  }
29
34
 
30
35
  export function isScraperActor(value: unknown): value is ScraperActorId {
@@ -60,37 +60,45 @@ export const VIDEO_ANALYSIS_WINDOW = { LEN: WINDOW_LEN, STRIDE: WINDOW_STRIDE, O
60
60
  // from the same roll plan, so they are formula-derived too (mixed:60s is 104,
61
61
  // not 110). The plugin's cost test now covers sentinels as well, so this class
62
62
  // of drift fails CI instead of shipping.
63
+ // REGENERATED 2026-07-31 with the smart-tier re-base (formula inputs moved in
64
+ // the plugin: sampling 24→6 fps after a 43-run measurement found 6 equal on
65
+ // content and strictly better on cast stability; the system-prompt and
66
+ // per-window output-token constants trued-up to directly measured values).
67
+ // Net effect: smart drops 27–47% per bucket — the 24 fps token spend was also
68
+ // partly paying for media tokens the provider clamped and never counted — and
69
+ // the economy rows tick up 3–6% from the prompt-token true-up.
63
70
  export const VIDEO_ANALYSIS_BUCKET_CREDITS: Record<string, number> = {
64
71
  // Legacy fast-tier model (pre-2026-07) — kept for stored raw-id configs.
65
- "video-analysis:gemini-3-flash:60s": 23,
66
- "video-analysis:gemini-3-flash:180s": 32,
67
- "video-analysis:gemini-3-flash:360s": 81,
68
- "video-analysis:gemini-3-flash:600s": 136,
72
+ "video-analysis:gemini-3-flash:60s": 24,
73
+ "video-analysis:gemini-3-flash:180s": 33,
74
+ "video-analysis:gemini-3-flash:360s": 86,
75
+ "video-analysis:gemini-3-flash:600s": 143,
69
76
  // Current fast tier — regenerated from the private formula for its backing
70
77
  // model; higher than the legacy fast schedule but still ≤ pro per bucket.
71
- "video-analysis:gemini-3.6-flash:60s": 61,
72
- "video-analysis:gemini-3.6-flash:180s": 88,
73
- "video-analysis:gemini-3.6-flash:360s": 224,
74
- "video-analysis:gemini-3.6-flash:600s": 374,
75
- "video-analysis:gemini-3.1-pro:60s": 82,
76
- "video-analysis:gemini-3.1-pro:180s": 111,
77
- "video-analysis:gemini-3.1-pro:360s": 291,
78
- "video-analysis:gemini-3.1-pro:600s": 486,
78
+ "video-analysis:gemini-3.6-flash:60s": 65,
79
+ "video-analysis:gemini-3.6-flash:180s": 92,
80
+ "video-analysis:gemini-3.6-flash:360s": 237,
81
+ "video-analysis:gemini-3.6-flash:600s": 395,
82
+ "video-analysis:gemini-3.1-pro:60s": 87,
83
+ "video-analysis:gemini-3.1-pro:180s": 116,
84
+ "video-analysis:gemini-3.1-pro:360s": 305,
85
+ "video-analysis:gemini-3.1-pro:600s": 509,
79
86
  // Mixed tiers (`mixed` + `mixed-fast`) share ONE credit family — they are
80
87
  // variants of the same engine plan (plan internals live in the private
81
88
  // analysis plugin). Admin-tunable via model_pricing like every other row.
82
- "video-analysis:mixed:60s": 104,
83
- "video-analysis:mixed:180s": 142,
84
- "video-analysis:mixed:360s": 372,
85
- "video-analysis:mixed:600s": 621,
86
- // SMART — the one native-transport plan: a single pass with reasoning and
87
- // frame sampling turned all the way up. Priced well above the economy tiers
88
- // because it genuinely costs more to run, and it is the only tier whose
89
- // accuracy was measured against a hand-counted edit list.
90
- "video-analysis:smart:60s": 454,
91
- "video-analysis:smart:180s": 975,
92
- "video-analysis:smart:360s": 2105,
93
- "video-analysis:smart:600s": 3496,
89
+ "video-analysis:mixed:60s": 110,
90
+ "video-analysis:mixed:180s": 149,
91
+ "video-analysis:mixed:360s": 390,
92
+ "video-analysis:mixed:600s": 651,
93
+ // SMART — the one native-transport plan: a single pass with reasoning turned
94
+ // all the way up at a measured-optimal sampling rate. Priced above the
95
+ // economy tiers because it genuinely costs more to run; the only tier whose
96
+ // accuracy is validated against a hand-counted edit list, re-validated at
97
+ // the current sampling rate before this schedule shipped.
98
+ "video-analysis:smart:60s": 333,
99
+ "video-analysis:smart:180s": 470,
100
+ "video-analysis:smart:360s": 1135,
101
+ "video-analysis:smart:600s": 1868,
94
102
  }
95
103
 
96
104
  /**