@gentbajko/slopify 3.25.9 → 4.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/dist/adapters/account-limits.js +30 -0
- package/dist/adapters/alignment/audio.js +1 -1
- package/dist/adapters/alignment/cache.js +4 -6
- package/dist/adapters/alignment/ctc.js +1 -2
- package/dist/adapters/alignment/lock.js +4 -3
- package/dist/adapters/alignment/multilingual.js +2 -4
- package/dist/adapters/alignment/prefetch.js +2 -1
- package/dist/adapters/alignment/runner.js +1 -1
- package/dist/adapters/alignment/worker.js +3 -2
- package/dist/adapters/explain.js +10 -12
- package/dist/adapters/ffmpeg.js +19 -1
- package/dist/adapters/host-cli/index.js +21 -4
- package/dist/adapters/host-cli/transport.js +2 -1
- package/dist/adapters/http-failure.js +53 -0
- package/dist/adapters/image/bytes.js +2 -1
- package/dist/adapters/image/codex.js +42 -9
- package/dist/adapters/image/fal.js +21 -53
- package/dist/adapters/image/google.js +33 -56
- package/dist/adapters/image/models.js +2 -2
- package/dist/adapters/image/openai.js +22 -48
- package/dist/adapters/image/reference.js +36 -0
- package/dist/adapters/image/replicate.js +21 -49
- package/dist/adapters/image/video.js +2 -1
- package/dist/adapters/interest/search-interest.js +113 -0
- package/dist/adapters/key-probes.js +54 -3
- package/dist/adapters/llm/antigravity-models.js +1 -1
- package/dist/adapters/llm/antigravity.js +11 -6
- package/dist/adapters/llm/assistant-cli.js +388 -0
- package/dist/adapters/llm/child-session.js +83 -0
- package/dist/adapters/llm/claude-code-models.js +52 -99
- package/dist/adapters/llm/claude-code.js +16 -4
- package/dist/adapters/llm/codex-limits.js +27 -68
- package/dist/adapters/llm/codex-models.js +1 -1
- package/dist/adapters/llm/codex-server-models.js +61 -109
- package/dist/adapters/llm/codex.js +12 -1
- package/dist/adapters/llm/document-workspace.js +3 -2
- package/dist/adapters/llm/image-workspace.js +3 -2
- package/dist/adapters/llm/openrouter.js +12 -48
- package/dist/adapters/llm/run-cli.js +9 -24
- package/dist/adapters/llm/sse-lines.js +5 -1
- package/dist/adapters/model-access.js +37 -0
- package/dist/adapters/tts/cartesia.js +15 -46
- package/dist/adapters/tts/elevenlabs.js +20 -52
- package/dist/adapters/tts/gemini.js +21 -41
- package/dist/adapters/tts/inworld-async.js +6 -2
- package/dist/adapters/tts/inworld.js +6 -2
- package/dist/adapters/tts/openai.js +20 -50
- package/dist/adapters/tts/system.js +2 -1
- package/dist/assets/models-lifecycle.yaml +6 -0
- package/dist/assistant-wiring.js +60 -0
- package/dist/autopilot-timers.js +59 -0
- package/dist/catalog/lifecycle.js +52 -0
- package/dist/catalog/propose.js +204 -0
- package/dist/catalog/registry.js +23 -14
- package/dist/catalog/schema.js +4 -1
- package/dist/catalog/store.js +39 -0
- package/dist/catalog/validate.js +5 -2
- package/dist/edge/autostart/native.js +3 -5
- package/dist/edge/autostart/prompt.js +2 -1
- package/dist/edge/autostart/service.js +3 -4
- package/dist/edge/cli-args.js +3 -4
- package/dist/edge/cli.js +2 -1
- package/dist/edge/docker-install/apply.js +11 -11
- package/dist/edge/docker-install/run.js +2 -1
- package/dist/edge/docker-install/state.js +4 -3
- package/dist/edge/docker-install/tree.js +2 -4
- package/dist/edge/docker-install/volume.js +3 -2
- package/dist/edge/docker.js +5 -4
- package/dist/edge/events/hub.js +5 -5
- package/dist/edge/http/actions.js +11 -32
- package/dist/edge/http/actor.js +5 -3
- package/dist/edge/http/app.js +86 -11
- package/dist/edge/http/assistant.js +129 -0
- package/dist/edge/http/audio-preview.js +4 -11
- package/dist/edge/http/auditions.js +1 -1
- package/dist/edge/http/autostart.js +5 -5
- package/dist/edge/http/backups.js +2 -4
- package/dist/edge/http/channel-memory.js +9 -22
- package/dist/edge/http/channels.js +14 -27
- package/dist/edge/http/checkpoints.js +39 -21
- package/dist/edge/http/design-templates.js +167 -0
- package/dist/edge/http/designs.js +178 -0
- package/dist/edge/http/diagnostics.js +5 -1
- package/dist/edge/http/document-themes.js +5 -14
- package/dist/edge/http/draft-files.js +1 -3
- package/dist/edge/http/draft-problem.js +5 -10
- package/dist/edge/http/drafts.js +3 -3
- package/dist/edge/http/entries.js +6 -9
- package/dist/edge/http/extension-auth.js +27 -0
- package/dist/edge/http/external-reviews.js +12 -11
- package/dist/edge/http/files.js +5 -11
- package/dist/edge/http/folder-location.js +1 -4
- package/dist/edge/http/fonts.js +0 -7
- package/dist/edge/http/home.js +47 -14
- package/dist/edge/http/host-cli.js +18 -8
- package/dist/edge/http/ids.js +8 -0
- package/dist/edge/http/keywords.js +35 -0
- package/dist/edge/http/model-checks.js +132 -0
- package/dist/edge/http/narration-peaks.js +5 -13
- package/dist/edge/http/onboarding.js +30 -26
- package/dist/edge/http/open-folder.js +5 -10
- package/dist/edge/http/outputs.js +7 -14
- package/dist/edge/http/patch-notes.js +6 -12
- package/dist/edge/http/planning.js +3 -7
- package/dist/edge/http/problem.js +2 -4
- package/dist/edge/http/project-create.js +2 -1
- package/dist/edge/http/project-templates.js +31 -19
- package/dist/edge/http/projects.js +24 -16
- package/dist/edge/http/prompts.js +9 -16
- package/dist/edge/http/pronunciations.js +1 -2
- package/dist/edge/http/providers.js +48 -34
- package/dist/edge/http/refusal.js +29 -0
- package/dist/edge/http/remote-access.js +40 -0
- package/dist/edge/http/remote-guard.js +71 -0
- package/dist/edge/http/request-guard.js +91 -0
- package/dist/edge/http/reviews.js +12 -25
- package/dist/edge/http/revision-files.js +6 -11
- package/dist/edge/http/revisions.js +14 -19
- package/dist/edge/http/run-cost.js +1 -2
- package/dist/edge/http/same-page.js +80 -0
- package/dist/edge/http/schedules.js +69 -40
- package/dist/edge/http/settings.js +27 -14
- package/dist/edge/http/social.js +283 -0
- package/dist/edge/http/staging.js +3 -5
- package/dist/edge/http/storage-files.js +5 -7
- package/dist/edge/http/storage.js +33 -25
- package/dist/edge/http/studio.js +94 -69
- package/dist/edge/http/style-preview.js +3 -6
- package/dist/edge/http/subtitles.js +3 -17
- package/dist/edge/http/template-studio.js +436 -0
- package/dist/edge/http/trash.js +11 -12
- package/dist/edge/http/tutorial.js +1 -2
- package/dist/edge/http/tutorials.js +5 -11
- package/dist/edge/http/update.js +7 -13
- package/dist/edge/http/waveform.js +3 -6
- package/dist/edge/http/youtube-edits.js +3 -4
- package/dist/edge/mcp/assistant.js +279 -0
- package/dist/edge/mcp/attribution.js +8 -2
- package/dist/edge/mcp/call-route.js +11 -2
- package/dist/edge/mcp/excluded-routes.js +29 -3
- package/dist/edge/mcp/http.js +11 -2
- package/dist/edge/mcp/instructions.js +6 -4
- package/dist/edge/mcp/library-tools.js +9 -5
- package/dist/edge/mcp/remake-tools.js +7 -4
- package/dist/edge/mcp/route-tool.js +35 -15
- package/dist/edge/mcp/server.js +13 -8
- package/dist/edge/mcp/tools-channels.js +11 -9
- package/dist/edge/mcp/tools-designs.js +165 -0
- package/dist/edge/mcp/tools-library.js +19 -7
- package/dist/edge/mcp/tools-planning.js +40 -21
- package/dist/edge/mcp/tools-projects.js +38 -11
- package/dist/edge/mcp/tools-publishing.js +9 -9
- package/dist/edge/mcp/tools-runs.js +23 -10
- package/dist/edge/mcp/tools-schedules.js +32 -8
- package/dist/edge/mcp/tools-setup.js +75 -11
- package/dist/edge/mcp/tools-social.js +47 -0
- package/dist/edge/mcp/tools-storage.js +11 -3
- package/dist/edge/mcp/tools-template-studio.js +166 -0
- package/dist/edge/mcp/tools.js +6 -0
- package/dist/edge/remote-access/cli.js +71 -0
- package/dist/edge/remote-access/model.js +32 -0
- package/dist/edge/remote-access/rules.js +207 -0
- package/dist/edge/remote-access/service.js +203 -0
- package/dist/edge/remote-access/store.js +44 -0
- package/dist/edge/remote-access/views.js +43 -0
- package/dist/extension/slopify-studio-chrome.zip +0 -0
- package/dist/extension/slopify-studio-firefox.zip +0 -0
- package/dist/host-cli/install.js +2 -2
- package/dist/host-cli/open-folder.js +2 -2
- package/dist/host-cli/paths.js +2 -4
- package/dist/host-cli/server.js +4 -4
- package/dist/host-cli/service.js +3 -3
- package/dist/host-cli/status.js +7 -7
- package/dist/kernel/db/migrations/0063-model-checks.sql +20 -0
- package/dist/kernel/db/migrations/0064-template-studio.sql +46 -0
- package/dist/kernel/db/migrations/0065-promise-and-assistant-reviews.sql +58 -0
- package/dist/kernel/db/migrations/0066-assistant.sql +44 -0
- package/dist/kernel/db/migrations/0067-autopilot.sql +6 -0
- package/dist/kernel/db/migrations/0068-topic-scores.sql +17 -0
- package/dist/kernel/db/migrations/0070-designs.sql +53 -0
- package/dist/kernel/db/migrations/0071-design-usage.sql +33 -0
- package/dist/kernel/db/migrations/0072-design-templates.sql +33 -0
- package/dist/kernel/db/migrations/0073-schedule-design-kind.sql +5 -0
- package/dist/kernel/db/migrations/0074-template-bakeoffs.sql +44 -0
- package/dist/kernel/db/migrations/0075-social-posts.sql +25 -0
- package/dist/kernel/db/migrations/0076-channel-social.sql +5 -0
- package/dist/kernel/db/migrations/0077-post-prompts.sql +17 -0
- package/dist/kernel/db/migrations/0078-uploaded-from-links.sql +7 -0
- package/dist/kernel/db/tx.js +2 -4
- package/dist/kernel/errors.js +27 -1
- package/dist/kernel/json-answer.js +15 -0
- package/dist/kernel/lock.js +4 -9
- package/dist/kernel/paths.js +8 -0
- package/dist/kernel/pipeline.js +12 -0
- package/dist/kernel/ports/assistant-cli.js +4 -0
- package/dist/kernel/ports/host-cli.js +3 -0
- package/dist/kernel/ports/interest.js +4 -0
- package/dist/kernel/ports/languages.js +0 -3
- package/dist/kernel/ports/model.js +2 -0
- package/dist/kernel/ports/settings-places.js +31 -0
- package/dist/kernel/ports/system-speech.js +31 -3
- package/dist/kernel/runner/attempt.js +14 -4
- package/dist/kernel/runner/audition.js +3 -1
- package/dist/kernel/runner/checkpoint-authority.js +2 -1
- package/dist/kernel/runner/index.js +8 -10
- package/dist/kernel/runner/model-access.js +40 -0
- package/dist/kernel/runner/model-check.js +153 -0
- package/dist/kernel/runner/providers.js +18 -12
- package/dist/kernel/runner/standalone.js +11 -7
- package/dist/main.js +338 -21
- package/dist/model-catalog.js +20 -0
- package/dist/model-checks.js +166 -0
- package/dist/patch-notes/4.0.0.md +51 -0
- package/dist/patch-notes/4.1.0.md +42 -0
- package/dist/patch-notes/index.json +12 -0
- package/dist/slices/admission/heads.js +2 -1
- package/dist/slices/admission/listing-facts.js +95 -0
- package/dist/slices/admission/repo.js +11 -7
- package/dist/slices/admission/rules.js +50 -15
- package/dist/slices/admission/schema.js +8 -0
- package/dist/slices/admission/stage-writes.js +0 -3
- package/dist/slices/admission/start.js +48 -31
- package/dist/slices/admission/state-words.js +34 -5
- package/dist/slices/admission/substitute.js +7 -4
- package/dist/slices/agents/attention-posts.js +31 -0
- package/dist/slices/agents/attention-templates.js +33 -0
- package/dist/slices/agents/attention.js +10 -1
- package/dist/slices/agents/connection.js +2 -6
- package/dist/slices/agents/model.js +6 -3
- package/dist/slices/agents/repo.js +15 -7
- package/dist/slices/article/continuation.js +0 -63
- package/dist/slices/article/plain.js +3 -2
- package/dist/slices/article/segments.js +2 -62
- package/dist/slices/assistant/access.js +1 -0
- package/dist/slices/assistant/asks.js +80 -0
- package/dist/slices/assistant/cost.js +54 -0
- package/dist/slices/assistant/gate.js +222 -0
- package/dist/slices/assistant/model.js +86 -0
- package/dist/slices/assistant/names.js +23 -0
- package/dist/slices/assistant/prompt.js +74 -0
- package/dist/slices/assistant/repo.js +74 -0
- package/dist/slices/assistant/tokens.js +18 -0
- package/dist/slices/assistant/turn.js +344 -0
- package/dist/slices/autopilot/buffer.js +76 -0
- package/dist/slices/autopilot/model.js +14 -0
- package/dist/slices/autopilot/notify.js +27 -0
- package/dist/slices/autopilot/repo.js +34 -0
- package/dist/slices/autopilot/signals.js +194 -0
- package/dist/slices/autopilot/warnings.js +85 -0
- package/dist/slices/autopilot/weekly.js +100 -0
- package/dist/slices/backups/files.js +2 -6
- package/dist/slices/backups/repo.js +3 -15
- package/dist/slices/backups/service.js +8 -7
- package/dist/slices/channels/cast-images.js +3 -2
- package/dist/slices/channels/model.js +0 -1
- package/dist/slices/channels/rebrand.js +0 -3
- package/dist/slices/channels/repo.js +4 -0
- package/dist/slices/channels/schema.js +7 -1
- package/dist/slices/channels/service.js +10 -0
- package/dist/slices/channels/videos.js +3 -15
- package/dist/slices/checkpoints/index.js +0 -1
- package/dist/slices/control/providers.js +2 -28
- package/dist/slices/designs/artwork.js +66 -0
- package/dist/slices/designs/budget.js +23 -0
- package/dist/slices/designs/calls.js +124 -0
- package/dist/slices/designs/check-context.js +38 -0
- package/dist/slices/designs/check-text.js +43 -0
- package/dist/slices/designs/fields.js +88 -0
- package/dist/slices/designs/frames.js +34 -0
- package/dist/slices/designs/gate.js +130 -0
- package/dist/slices/designs/layout.js +293 -0
- package/dist/slices/designs/model.js +35 -0
- package/dist/slices/designs/pdf-job.js +23 -0
- package/dist/slices/designs/pdf-pages.js +30 -0
- package/dist/slices/designs/pdf-runner.js +68 -0
- package/dist/slices/designs/pdf-worker.js +24 -0
- package/dist/slices/designs/picture-size.js +79 -0
- package/dist/slices/designs/pictures.js +55 -0
- package/dist/slices/designs/quote.js +24 -0
- package/dist/slices/designs/render-args.js +36 -0
- package/dist/slices/designs/render-input.js +59 -0
- package/dist/slices/designs/render.js +215 -0
- package/dist/slices/designs/repo.js +101 -0
- package/dist/slices/designs/requests.js +80 -0
- package/dist/slices/designs/runner.js +239 -0
- package/dist/slices/designs/sample-repo.js +91 -0
- package/dist/slices/designs/sample.js +223 -0
- package/dist/slices/designs/schema.js +87 -0
- package/dist/slices/designs/sections.js +44 -0
- package/dist/slices/designs/service.js +233 -0
- package/dist/slices/designs/steps-repo.js +102 -0
- package/dist/slices/designs/studio-kind.js +39 -0
- package/dist/slices/designs/template-checks.js +44 -0
- package/dist/slices/designs/template-make.js +118 -0
- package/dist/slices/designs/templates.js +218 -0
- package/dist/slices/document/fonts.js +2 -1
- package/dist/slices/document/model.js +7 -4
- package/dist/slices/document/render.js +2 -1
- package/dist/slices/document/theme-schema.js +1 -1
- package/dist/slices/document/theme.js +49 -3
- package/dist/slices/episodes/summarize.js +6 -2
- package/dist/slices/estimate/index.js +72 -28
- package/dist/slices/estimate/requests.js +4 -4
- package/dist/slices/fixes/rules.js +3 -1
- package/dist/slices/fonts/catalog.js +5 -3
- package/dist/slices/fonts/coverage.js +2 -1
- package/dist/slices/fonts/discovery.js +3 -2
- package/dist/slices/fonts/files.js +2 -6
- package/dist/slices/fonts/index.js +0 -1
- package/dist/slices/fonts/sfnt.js +45 -10
- package/dist/slices/images/appearance.js +8 -16
- package/dist/slices/images/scenes.js +102 -28
- package/dist/slices/keywords/digest.js +85 -0
- package/dist/slices/keywords/facts.js +92 -0
- package/dist/slices/keywords/fill.js +80 -0
- package/dist/slices/keywords/model.js +75 -0
- package/dist/slices/keywords/rules.js +187 -0
- package/dist/slices/keywords/schema.js +28 -0
- package/dist/slices/keywords/specs.js +260 -0
- package/dist/slices/keywords/values.js +74 -0
- package/dist/slices/library/lint.js +29 -12
- package/dist/slices/library/model.js +2 -0
- package/dist/slices/library/photorealistic.js +4 -12
- package/dist/slices/library/rename.js +9 -7
- package/dist/slices/library/save.js +14 -10
- package/dist/slices/library/slots.js +37 -11
- package/dist/slices/library/transfer.js +5 -4
- package/dist/slices/library/used-by.js +25 -10
- package/dist/slices/loudness/loudnorm.js +53 -12
- package/dist/slices/loudness/model.js +3 -2
- package/dist/slices/loudness/sentence-level.js +2 -1
- package/dist/slices/model-checks/cost.js +61 -0
- package/dist/slices/model-checks/listing.js +124 -0
- package/dist/slices/model-checks/model.js +20 -0
- package/dist/slices/model-checks/record.js +32 -0
- package/dist/slices/model-checks/repo.js +120 -0
- package/dist/slices/model-checks/rules.js +125 -0
- package/dist/slices/model-checks/run.js +143 -0
- package/dist/slices/model-checks/service.js +198 -0
- package/dist/slices/model-upkeep/model.js +1 -1
- package/dist/slices/model-upkeep/switch.js +72 -27
- package/dist/slices/model-upkeep/usage.js +39 -13
- package/dist/slices/narration/breaths.js +3 -1
- package/dist/slices/narration/clean-pieces.js +3 -1
- package/dist/slices/narration/concat.js +2 -1
- package/dist/slices/narration/pauses-model.js +3 -2
- package/dist/slices/narration/peaks.js +3 -4
- package/dist/slices/narration/pronunciation-chunks.js +4 -3
- package/dist/slices/narration/pronunciation.js +6 -4
- package/dist/slices/narration/steering.js +4 -3
- package/dist/slices/notifications/notifier.js +4 -3
- package/dist/slices/notifications/rules.js +5 -2
- package/dist/slices/notifications/settings.js +4 -12
- package/dist/slices/notifications/subject.js +4 -3
- package/dist/slices/onboarding/copy.js +21 -3
- package/dist/slices/onboarding/first-run.js +16 -40
- package/dist/slices/onboarding/full-video.js +3 -2
- package/dist/slices/onboarding/install.js +6 -4
- package/dist/slices/onboarding/model.js +26 -37
- package/dist/slices/onboarding/packs.js +22 -22
- package/dist/slices/onboarding/preferred-model.js +14 -0
- package/dist/slices/onboarding/quick-short.js +105 -65
- package/dist/slices/onboarding/sample.js +4 -2
- package/dist/slices/onboarding/state.js +9 -11
- package/dist/slices/onboarding/template.js +8 -6
- package/dist/slices/outputs/add.js +3 -2
- package/dist/slices/outputs/service.js +2 -2
- package/dist/slices/patch-notes/library.js +4 -3
- package/dist/slices/play-drafts/convert.js +4 -0
- package/dist/slices/play-drafts/readiness.js +3 -3
- package/dist/slices/play-drafts/review-inputs.js +9 -3
- package/dist/slices/play-drafts/review.js +5 -4
- package/dist/slices/play-drafts/schema.js +4 -0
- package/dist/slices/play-drafts/service.js +17 -7
- package/dist/slices/project-templates/from-project.js +9 -2
- package/dist/slices/project-templates/next-chapter.js +2 -1
- package/dist/slices/project-templates/provider-defaults.js +22 -0
- package/dist/slices/project-templates/repo.js +6 -1
- package/dist/slices/project-templates/setup-sections.js +26 -0
- package/dist/slices/project-templates/setup.js +14 -1
- package/dist/slices/project-templates/stand-ins.js +22 -0
- package/dist/slices/rebuild/activity.js +2 -0
- package/dist/slices/rebuild/admission-repo.js +3 -2
- package/dist/slices/rebuild/narration-history.js +4 -5
- package/dist/slices/rebuild/narration-retry.js +2 -1
- package/dist/slices/rebuild/preview-details.js +32 -14
- package/dist/slices/rebuild/preview-plan.js +3 -8
- package/dist/slices/rebuild/recipe-build.js +8 -3
- package/dist/slices/rebuild/recipe-describe.js +3 -3
- package/dist/slices/rebuild/recipe-digest.js +58 -0
- package/dist/slices/rebuild/recipe-input-schema.js +10 -0
- package/dist/slices/rebuild/recipe-keywords.js +71 -0
- package/dist/slices/rebuild/recipe-legacy.js +5 -1
- package/dist/slices/rebuild/recipe-model.js +4 -0
- package/dist/slices/rebuild/recipe-narration-text.js +2 -1
- package/dist/slices/rebuild/recipe-preparation.js +4 -4
- package/dist/slices/rebuild/recipe-reference.js +8 -4
- package/dist/slices/rebuild/recipe-reviews.js +27 -7
- package/dist/slices/rebuild/recipe-save.js +8 -5
- package/dist/slices/rebuild/recipe-scenes.js +40 -11
- package/dist/slices/rebuild/recipe-shorts.js +8 -8
- package/dist/slices/rebuild/recipe-social.js +46 -0
- package/dist/slices/rebuild/recipe-text.js +64 -20
- package/dist/slices/rebuild/recipe-validation.js +102 -31
- package/dist/slices/rebuild/recipe-visual.js +55 -16
- package/dist/slices/rebuild/recipe-voices.js +3 -2
- package/dist/slices/rebuild/recipe-work.js +19 -7
- package/dist/slices/rebuild/recipe-youtube.js +4 -3
- package/dist/slices/rebuild/recovery-selection.js +3 -1
- package/dist/slices/rebuild/recovery.js +9 -8
- package/dist/slices/rebuild/remake-outdated.js +5 -5
- package/dist/slices/rebuild/repo.js +4 -3
- package/dist/slices/rebuild/review-promise.js +25 -0
- package/dist/slices/rebuild/review-redo.js +3 -2
- package/dist/slices/rebuild/runtime-admission.js +4 -3
- package/dist/slices/rebuild/runtime-agent-review.js +11 -5
- package/dist/slices/rebuild/runtime-animate.js +10 -9
- package/dist/slices/rebuild/runtime-article.js +7 -5
- package/dist/slices/rebuild/runtime-checkpoints.js +5 -4
- package/dist/slices/rebuild/runtime-document.js +11 -13
- package/dist/slices/rebuild/runtime-export-bed.js +8 -12
- package/dist/slices/rebuild/runtime-export-edit.js +8 -16
- package/dist/slices/rebuild/runtime-export-inputs.js +12 -11
- package/dist/slices/rebuild/runtime-export-short.js +9 -5
- package/dist/slices/rebuild/runtime-export.js +38 -15
- package/dist/slices/rebuild/runtime-figure-card.js +2 -1
- package/dist/slices/rebuild/runtime-image.js +8 -12
- package/dist/slices/rebuild/runtime-instructions.js +2 -0
- package/dist/slices/rebuild/runtime-keywords.js +59 -0
- package/dist/slices/rebuild/runtime-lines.js +2 -11
- package/dist/slices/rebuild/runtime-local.js +17 -22
- package/dist/slices/rebuild/runtime-narration-publication.js +2 -5
- package/dist/slices/rebuild/runtime-narration-reuse.js +9 -13
- package/dist/slices/rebuild/runtime-narration-text.js +13 -17
- package/dist/slices/rebuild/runtime-pictures.js +2 -4
- package/dist/slices/rebuild/runtime-piece-label.js +10 -6
- package/dist/slices/rebuild/runtime-plan.js +31 -5
- package/dist/slices/rebuild/runtime-provider.js +67 -25
- package/dist/slices/rebuild/runtime-publication.js +10 -9
- package/dist/slices/rebuild/runtime-review.js +39 -33
- package/dist/slices/rebuild/runtime-run.js +4 -1
- package/dist/slices/rebuild/runtime-shorts.js +31 -50
- package/dist/slices/rebuild/runtime-store.js +20 -10
- package/dist/slices/rebuild/runtime-subtitles.js +28 -25
- package/dist/slices/rebuild/runtime-voices.js +10 -16
- package/dist/slices/rebuild/runtime-youtube.js +14 -31
- package/dist/slices/rebuild/service-readiness.js +11 -3
- package/dist/slices/rebuild/transition-repo.js +6 -5
- package/dist/slices/rebuild/work-records.js +6 -0
- package/dist/slices/reruns/cascade.js +1 -2
- package/dist/slices/reruns/index.js +6 -9
- package/dist/slices/research/synthesis.js +3 -2
- package/dist/slices/reviews/external-model.js +4 -1
- package/dist/slices/reviews/external-repo.js +2 -1
- package/dist/slices/reviews/external-rows.js +2 -3
- package/dist/slices/reviews/holds.js +5 -4
- package/dist/slices/reviews/model.js +32 -11
- package/dist/slices/reviews/repo.js +2 -1
- package/dist/slices/reviews/rules.js +4 -3
- package/dist/slices/reviews/verdict.js +2 -1
- package/dist/slices/reviews/view.js +5 -2
- package/dist/slices/revisions/downloads.js +4 -5
- package/dist/slices/revisions/image-plan.js +1 -1
- package/dist/slices/revisions/mutation-assets.js +9 -5
- package/dist/slices/revisions/mutation-cues.js +2 -5
- package/dist/slices/revisions/mutations.js +3 -3
- package/dist/slices/revisions/repo.js +3 -1
- package/dist/slices/revisions/schema.js +1 -0
- package/dist/slices/revisions/view.js +20 -0
- package/dist/slices/run-cost/limits.js +5 -2
- package/dist/slices/run-cost/meter.js +12 -5
- package/dist/slices/run-cost/panel.js +8 -74
- package/dist/slices/run-cost/plan-readings.js +127 -0
- package/dist/slices/run-cost/plan-use.js +169 -0
- package/dist/slices/run-cost/pricing.js +3 -3
- package/dist/slices/run-cost/week.js +32 -4
- package/dist/slices/schedules/agenda.js +18 -7
- package/dist/slices/schedules/by-date.js +42 -0
- package/dist/slices/schedules/calendar.js +5 -0
- package/dist/slices/schedules/design-agenda.js +36 -0
- package/dist/slices/schedules/design-check.js +41 -0
- package/dist/slices/schedules/design-run.js +126 -0
- package/dist/slices/schedules/next-run.js +62 -0
- package/dist/slices/schedules/prepare.js +18 -2
- package/dist/slices/schedules/repo.js +30 -21
- package/dist/slices/schedules/rescore.js +35 -0
- package/dist/slices/schedules/scheduler.js +13 -3
- package/dist/slices/schedules/schema.js +57 -3
- package/dist/slices/schedules/score.js +107 -0
- package/dist/slices/schedules/service.js +57 -24
- package/dist/slices/schedules/topic-list.js +15 -0
- package/dist/slices/schedules/topic-scores.js +104 -0
- package/dist/slices/schedules/topics.js +53 -41
- package/dist/slices/settings/cli-paths.js +4 -6
- package/dist/slices/settings/first-run.js +8 -43
- package/dist/slices/settings/health.js +30 -15
- package/dist/slices/settings/key-test.js +1 -1
- package/dist/slices/settings/model-reach.js +3 -17
- package/dist/slices/settings/model.js +14 -2
- package/dist/slices/settings/playback.js +34 -23
- package/dist/slices/settings/probe-read.js +16 -0
- package/dist/slices/settings/repo.js +33 -0
- package/dist/slices/settings/tutorial.js +2 -2
- package/dist/slices/settings/voices.js +4 -12
- package/dist/slices/shorts/keep.js +2 -1
- package/dist/slices/shorts/pick.js +6 -18
- package/dist/slices/shorts/prompts.js +4 -14
- package/dist/slices/shorts/render.js +6 -2
- package/dist/slices/social/channel.js +44 -0
- package/dist/slices/social/defaults.js +17 -0
- package/dist/slices/social/due.js +36 -0
- package/dist/slices/social/extension.js +18 -0
- package/dist/slices/social/fit.js +115 -0
- package/dist/slices/social/limits.js +186 -0
- package/dist/slices/social/links.js +21 -0
- package/dist/slices/social/media.js +132 -0
- package/dist/slices/social/model.js +75 -0
- package/dist/slices/social/notice.js +19 -0
- package/dist/slices/social/pack.js +176 -0
- package/dist/slices/social/post-prompt.js +56 -0
- package/dist/slices/social/queue.js +31 -0
- package/dist/slices/social/repo.js +133 -0
- package/dist/slices/social/reshape.js +97 -0
- package/dist/slices/social/rules.js +5 -0
- package/dist/slices/social/schema.js +70 -0
- package/dist/slices/social/serve.js +51 -0
- package/dist/slices/social/service.js +129 -0
- package/dist/slices/social/settings.js +21 -0
- package/dist/slices/social/sources.js +114 -0
- package/dist/slices/social/state.js +110 -0
- package/dist/slices/social/text.js +149 -0
- package/dist/slices/storage/arrange.js +3 -1
- package/dist/slices/storage/assets.js +8 -10
- package/dist/slices/storage/backup-designs.js +74 -0
- package/dist/slices/storage/backup-export.js +8 -3
- package/dist/slices/storage/backup-format.js +10 -0
- package/dist/slices/storage/backup-import.js +22 -4
- package/dist/slices/storage/delete-project.js +6 -5
- package/dist/slices/storage/files-location.js +6 -8
- package/dist/slices/storage/layout.js +13 -2
- package/dist/slices/storage/model.js +3 -0
- package/dist/slices/storage/portable.js +17 -12
- package/dist/slices/storage/schema.js +2 -0
- package/dist/slices/storage/staging-refs.js +2 -1
- package/dist/slices/storage/staging.js +6 -9
- package/dist/slices/storage/trim.js +26 -9
- package/dist/slices/studio/calendar.js +7 -2
- package/dist/slices/studio/disclosure.js +4 -4
- package/dist/slices/studio/model.js +1 -1
- package/dist/slices/studio/pack.js +9 -8
- package/dist/slices/studio/pick.js +2 -11
- package/dist/slices/studio/plan.js +7 -16
- package/dist/slices/studio/queue.js +3 -14
- package/dist/slices/studio/releases.js +26 -0
- package/dist/slices/studio/settings.js +20 -57
- package/dist/slices/studio/videos.js +35 -4
- package/dist/slices/style-preview/render.js +37 -16
- package/dist/slices/style-preview/schema.js +14 -1
- package/dist/slices/style-preview/service.js +2 -1
- package/dist/slices/style-preview/settings.js +33 -5
- package/dist/slices/subtitles/captions.js +1 -1
- package/dist/slices/telemetry/collector-client.js +2 -4
- package/dist/slices/telemetry/flush.js +2 -4
- package/dist/slices/telemetry/model.js +0 -7
- package/dist/slices/telemetry/record.js +10 -3
- package/dist/slices/template-studio/anatomy-view.js +161 -0
- package/dist/slices/template-studio/anatomy.js +73 -0
- package/dist/slices/template-studio/bakeoff-make.js +225 -0
- package/dist/slices/template-studio/bakeoff-repo.js +83 -0
- package/dist/slices/template-studio/bakeoff.js +333 -0
- package/dist/slices/template-studio/budget.js +106 -0
- package/dist/slices/template-studio/cards.js +78 -0
- package/dist/slices/template-studio/checks.js +322 -0
- package/dist/slices/template-studio/document-sample.js +56 -0
- package/dist/slices/template-studio/edit.js +15 -0
- package/dist/slices/template-studio/for-all.js +161 -0
- package/dist/slices/template-studio/free-video.js +31 -0
- package/dist/slices/template-studio/free.js +176 -0
- package/dist/slices/template-studio/gate.js +40 -0
- package/dist/slices/template-studio/hidden.js +20 -0
- package/dist/slices/template-studio/jobs.js +79 -0
- package/dist/slices/template-studio/loudness.js +111 -0
- package/dist/slices/template-studio/make.js +40 -0
- package/dist/slices/template-studio/model.js +58 -0
- package/dist/slices/template-studio/pack-import.js +253 -0
- package/dist/slices/template-studio/pack-samples.js +60 -0
- package/dist/slices/template-studio/pack.js +207 -0
- package/dist/slices/template-studio/paid-view.js +66 -0
- package/dist/slices/template-studio/paid.js +355 -0
- package/dist/slices/template-studio/quote.js +155 -0
- package/dist/slices/template-studio/ready.js +104 -0
- package/dist/slices/template-studio/repo.js +134 -0
- package/dist/slices/template-studio/reviews-path.js +58 -0
- package/dist/slices/template-studio/runner.js +84 -0
- package/dist/slices/template-studio/save.js +236 -0
- package/dist/slices/template-studio/say-it-as.js +248 -0
- package/dist/slices/template-studio/schedule-gate.js +34 -0
- package/dist/slices/template-studio/schedule-price.js +32 -0
- package/dist/slices/template-studio/schedule-sample.js +91 -0
- package/dist/slices/template-studio/schema.js +243 -0
- package/dist/slices/template-studio/scope.js +124 -0
- package/dist/slices/template-studio/sections.js +176 -0
- package/dist/slices/template-studio/service.js +175 -0
- package/dist/slices/template-studio/status.js +191 -0
- package/dist/slices/template-studio/topic.js +223 -0
- package/dist/slices/thumbnail/by-llm.js +1 -1
- package/dist/slices/trash/designs.js +76 -0
- package/dist/slices/trash/model.js +13 -4
- package/dist/slices/trash/service.js +52 -2
- package/dist/slices/tutorials/library.js +3 -2
- package/dist/slices/uploads/repo.js +37 -1
- package/dist/slices/uploads/rules.js +3 -2
- package/dist/slices/video/ass-text.js +17 -0
- package/dist/slices/video/audio-export.js +2 -64
- package/dist/slices/video/edit-list.js +2 -2
- package/dist/slices/video/edit-settings.js +1 -1
- package/dist/slices/video/encoding.js +169 -0
- package/dist/slices/video/ffmpeg.js +23 -21
- package/dist/slices/video/figure-card.js +1 -15
- package/dist/slices/video/plan.js +2 -1
- package/dist/slices/video/slideshow.js +43 -18
- package/dist/slices/voices/attribution.js +3 -2
- package/dist/slices/voices/model.js +9 -8
- package/dist/slices/voices/palette.js +0 -3
- package/dist/slices/voices/script.js +2 -1
- package/dist/slices/youtube/answer.js +4 -16
- package/dist/slices/youtube/edits-repo.js +3 -12
- package/dist/tutorials/AI-CLIs.md +25 -25
- package/dist/tutorials/Agents-MCP.md +34 -33
- package/dist/tutorials/Assistant.md +42 -0
- package/dist/tutorials/Backups.md +7 -7
- package/dist/tutorials/Calendar.md +17 -25
- package/dist/tutorials/Cast-Library.md +19 -19
- package/dist/tutorials/Channels.md +42 -35
- package/dist/tutorials/Costs-and-Run-Cost.md +38 -40
- package/dist/tutorials/Create-Article.md +114 -0
- package/dist/tutorials/Create-Extras.md +112 -0
- package/dist/tutorials/Create-Images.md +165 -0
- package/dist/tutorials/Create-Narration.md +178 -0
- package/dist/tutorials/Create-Overview.md +244 -0
- package/dist/tutorials/Create-Video-and-Style.md +144 -0
- package/dist/tutorials/Docker.md +3 -3
- package/dist/tutorials/Document-Themes.md +32 -32
- package/dist/tutorials/Editing-a-Project.md +94 -94
- package/dist/tutorials/FAQ.md +18 -18
- package/dist/tutorials/First-Launch-and-Welcome.md +50 -64
- package/dist/tutorials/Home-and-Projects.md +115 -71
- package/dist/tutorials/Home.md +33 -33
- package/dist/tutorials/Install.md +14 -13
- package/dist/tutorials/Intros-and-Outros.md +33 -34
- package/dist/tutorials/Keyboard-Shortcuts-and-Command-Palette.md +62 -58
- package/dist/tutorials/Keywords-Slopify-Fills.md +87 -0
- package/dist/tutorials/Models.md +53 -21
- package/dist/tutorials/Multiple-Voices.md +41 -40
- package/dist/tutorials/Narration-Aliases-and-Glossary.md +14 -14
- package/dist/tutorials/Notifications.md +27 -17
- package/dist/tutorials/Other-Languages.md +15 -15
- package/dist/tutorials/PDF-Documents.md +38 -29
- package/dist/tutorials/Posting-to-Social-Sites.md +121 -0
- package/dist/tutorials/Project-Page.md +118 -120
- package/dist/tutorials/Prompts-and-Templates.md +84 -0
- package/dist/tutorials/Prompts.md +48 -44
- package/dist/tutorials/Providers-and-Keys.md +105 -98
- package/dist/tutorials/Publishing-to-YouTube.md +31 -31
- package/dist/tutorials/Recovery-and-Retries.md +31 -31
- package/dist/tutorials/Remote-Access.md +63 -0
- package/dist/tutorials/Reviews-and-Checkpoints.md +98 -90
- package/dist/tutorials/Schedules.md +46 -27
- package/dist/tutorials/Settings-Reference.md +194 -174
- package/dist/tutorials/Shorts.md +34 -33
- package/dist/tutorials/Start-at-Login.md +3 -3
- package/dist/tutorials/Studio-Extension.md +22 -24
- package/dist/tutorials/Template-Studio.md +128 -0
- package/dist/tutorials/Templates.md +51 -77
- package/dist/tutorials/Trash.md +4 -4
- package/dist/tutorials/Troubleshooting.md +44 -44
- package/dist/tutorials/Uninstalling-and-Moving.md +5 -5
- package/dist/tutorials/Updating-and-Patch-Notes.md +18 -18
- package/dist/tutorials/Video-Editing.md +34 -34
- package/dist/tutorials/Where-Your-Files-Live.md +10 -10
- package/dist/tutorials/YouTube-Description.md +26 -26
- package/dist/tutorials/Your-First-Short.md +35 -35
- package/dist/tutorials/_Sidebar.md +19 -14
- package/dist/updater/work-in-progress.js +42 -12
- package/dist/web/assets/index-BNftKQrA.css +1 -0
- package/dist/web/assets/index-Cpa58woP.js +459 -0
- package/dist/web/assets/pdf-BKh8f7R6.js +56 -0
- package/dist/web/assets/pdf.worker.min-BmVo14Nb.mjs +28 -0
- package/dist/web/assets/pdf.worker.min-D7i8o3wR.js +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +6 -2
- package/dist/slices/article/provided-entries.js +0 -66
- package/dist/slices/article/run.js +0 -145
- package/dist/slices/images/run.js +0 -234
- package/dist/slices/narration/legacy-plan.js +0 -58
- package/dist/slices/narration/run.js +0 -270
- package/dist/slices/rebuild/runtime-actions.js +0 -90
- package/dist/slices/research/run.js +0 -224
- package/dist/slices/subtitles/prepare.js +0 -194
- package/dist/slices/subtitles/transcript.js +0 -34
- package/dist/slices/thumbnail/run.js +0 -219
- package/dist/slices/video/audio-inputs.js +0 -33
- package/dist/slices/video/reuse-audio.js +0 -62
- package/dist/slices/video/run.js +0 -78
- package/dist/slices/video/write-export.js +0 -158
- package/dist/slices/video/write-subtitles.js +0 -59
- package/dist/tutorials/Library-Overview.md +0 -76
- package/dist/tutorials/Play-Images.md +0 -161
- package/dist/tutorials/Play-Narration.md +0 -167
- package/dist/tutorials/Play-Outputs.md +0 -109
- package/dist/tutorials/Play-Overview.md +0 -227
- package/dist/tutorials/Play-Title-and-Article.md +0 -136
- package/dist/tutorials/Play-Video-and-Style.md +0 -143
- package/dist/web/assets/index-BadsoORk.css +0 -1
- package/dist/web/assets/index-D8LqNsCl.js +0 -326
- package/dist/web/assets/pdf-T7MCwjIv.js +0 -54
- package/dist/web/assets/pdf.worker.min-Dswkl-cV.mjs +0 -29
- package/dist/web/assets/pdf.worker.min-zC6nfbxG.js +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { transact } from "../../kernel/db/tx.js";
|
|
3
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
3
4
|
import { rebrandedEdit } from "../channels/rebrand.js";
|
|
4
5
|
import { projectChannelId, resolveChannelId, setProjectChannel } from "../channels/repo.js";
|
|
5
6
|
import { carryCheckpointGates } from "../checkpoints/recovery.js";
|
|
@@ -26,7 +27,6 @@ import { bindNarrationSources, validateNarrationIntent, validateTemplateIntent }
|
|
|
26
27
|
import { revisionEditSchema } from "./schema.js";
|
|
27
28
|
import { keptSubject } from "./subject.js";
|
|
28
29
|
import { withEarlierJoins } from "./view.js";
|
|
29
|
-
export { bindUpload } from "./mutation-assets.js";
|
|
30
30
|
export { restoreRevision } from "./restore.js";
|
|
31
31
|
export async function saveRevision(deps, input) {
|
|
32
32
|
const parsed = revisionEditSchema.safeParse(input.edit);
|
|
@@ -205,14 +205,14 @@ function settingProblems(edit) {
|
|
|
205
205
|
? []
|
|
206
206
|
: ambientBedProblems(bed).map((problem) => ({
|
|
207
207
|
field: `ambientBed.${problem.field}`,
|
|
208
|
-
message: `${problem.message} Change it
|
|
208
|
+
message: `${problem.message} Change it under Ambient sound in ${editSettings.sound}.`,
|
|
209
209
|
}))),
|
|
210
210
|
...(scaleProblem === undefined
|
|
211
211
|
? []
|
|
212
212
|
: [
|
|
213
213
|
{
|
|
214
214
|
field: "imageScale",
|
|
215
|
-
message: `${scaleProblem} Change it
|
|
215
|
+
message: `${scaleProblem} Change it under More images for long videos in ${editSettings.images}.`,
|
|
216
216
|
},
|
|
217
217
|
]),
|
|
218
218
|
];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { agentRevisionIds } from "../agents/repo.js";
|
|
2
|
+
import { agentRevisionIds, assistantRevisionIds } from "../agents/repo.js";
|
|
3
3
|
import { projectRevisionSchema } from "./schema.js";
|
|
4
4
|
export { insertManifestOutput, insertManifestPiece, outputsForRevision, piecesForRevision, selectOutputRecord, selectPieceRecord, } from "./manifest-repo.js";
|
|
5
5
|
const revisionRow = z.object({
|
|
@@ -39,6 +39,7 @@ export function currentRevisionId(db, projectId) {
|
|
|
39
39
|
export function listRevisionHistory(db, projectId) {
|
|
40
40
|
const head = currentRevisionId(db, projectId);
|
|
41
41
|
const byAgent = agentRevisionIds(db, projectId);
|
|
42
|
+
const byAssistant = assistantRevisionIds(db, projectId);
|
|
42
43
|
return db
|
|
43
44
|
.prepare("SELECT * FROM project_revisions WHERE project_id=? ORDER BY created_at DESC,id DESC")
|
|
44
45
|
.all(projectId)
|
|
@@ -52,6 +53,7 @@ export function listRevisionHistory(db, projectId) {
|
|
|
52
53
|
createdAt: revision.createdAt,
|
|
53
54
|
current: revision.id === head,
|
|
54
55
|
...(byAgent.has(revision.id) ? { byAgent: true } : {}),
|
|
56
|
+
...(byAssistant.has(revision.id) ? { byAssistant: true } : {}),
|
|
55
57
|
};
|
|
56
58
|
});
|
|
57
59
|
}
|
|
@@ -221,6 +221,7 @@ export const revisionSummarySchema = z.object({
|
|
|
221
221
|
createdAt: z.string(),
|
|
222
222
|
current: z.boolean(),
|
|
223
223
|
byAgent: z.boolean().optional(),
|
|
224
|
+
byAssistant: z.boolean().optional(),
|
|
224
225
|
});
|
|
225
226
|
export const revisionMutationSuccessSchema = z.object({
|
|
226
227
|
ok: z.literal(true),
|
|
@@ -33,6 +33,26 @@ export function getRevisionView(deps, projectId, revisionId) {
|
|
|
33
33
|
articleMarkdown: resolvedArticleMarkdown(deps, revision, outputs),
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
|
+
export function isReadyOutput(row, match = {}) {
|
|
37
|
+
return (row.selected &&
|
|
38
|
+
row.available &&
|
|
39
|
+
row.state === "ready" &&
|
|
40
|
+
(match.role === undefined || row.output.role === match.role) &&
|
|
41
|
+
(match.workKey === undefined || row.workKey === match.workKey));
|
|
42
|
+
}
|
|
43
|
+
export function readyOutput(view, match = {}) {
|
|
44
|
+
return view.outputs.find((row) => isReadyOutput(row, match));
|
|
45
|
+
}
|
|
46
|
+
// A piece a step can read: selected, its file (if any) on disk and done, under `key` when given.
|
|
47
|
+
export function isDonePiece(row, key) {
|
|
48
|
+
return (row.selected &&
|
|
49
|
+
row.available &&
|
|
50
|
+
row.piece.state === "done" &&
|
|
51
|
+
(key === undefined || row.key === key));
|
|
52
|
+
}
|
|
53
|
+
export function donePiece(view, key) {
|
|
54
|
+
return view.pieces.find((row) => isDonePiece(row, key));
|
|
55
|
+
}
|
|
36
56
|
export function resolvedArticleMarkdown(deps, revision, outputs) {
|
|
37
57
|
if (revision.content.articleEdited === true && revision.content.articleMarkdown !== undefined)
|
|
38
58
|
return revision.content.articleMarkdown;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { causedBy } from "../../kernel/errors.js";
|
|
3
|
+
import { notTemplateSample } from "../template-studio/repo.js";
|
|
3
4
|
// Living within a CLI's plan limits. When a CLI says its allowance is used up, the time it
|
|
4
5
|
// returns is stored per account; every call to that CLI - from any project, and after a
|
|
5
6
|
// restart - waits for it instead of failing. Other providers are untouched, so a project
|
|
@@ -99,13 +100,15 @@ export function createLimitGate(deps) {
|
|
|
99
100
|
// At start, a stage that was waiting on a plan limit when the app stopped was marked
|
|
100
101
|
// interrupted like any other (main.ts markInterruptedStages). Those projects are resumed so
|
|
101
102
|
// the wait carries on by itself - their calls meet the stored reset and wait again. A project
|
|
102
|
-
// paused or cancelled meanwhile is left as it is.
|
|
103
|
+
// paused or cancelled meanwhile is left as it is. A template studio sample is the studio's own
|
|
104
|
+
// recovery's to resume, which checks the sample budget and its plans switch first.
|
|
103
105
|
export async function resumeAfterRestart(db, resume, log) {
|
|
104
106
|
const projects = db
|
|
105
107
|
.prepare(`SELECT DISTINCT w.project_id AS id FROM plan_limit_waiters w
|
|
106
108
|
JOIN stages s ON s.project_id = w.project_id AND s.kind = w.stage
|
|
107
109
|
WHERE s.state = 'failed' AND s.failure_reason = 'interrupted'
|
|
108
|
-
AND NOT EXISTS (SELECT 1 FROM project_controls c WHERE c.project_id = w.project_id AND c.paused = 1)
|
|
110
|
+
AND NOT EXISTS (SELECT 1 FROM project_controls c WHERE c.project_id = w.project_id AND c.paused = 1)
|
|
111
|
+
AND ${notTemplateSample("w", "project_id")}`)
|
|
109
112
|
.all()
|
|
110
113
|
.map((row) => z.string().parse(row.id));
|
|
111
114
|
db.prepare("DELETE FROM plan_limit_waiters").run();
|
|
@@ -9,15 +9,17 @@ export function createUsageMeter(deps) {
|
|
|
9
9
|
record: (call) => {
|
|
10
10
|
const priced = priceCall(call, deps.catalogue());
|
|
11
11
|
const at = deps.clock.now().toISOString();
|
|
12
|
+
const usageId = deps.ids.next();
|
|
12
13
|
deps.db
|
|
13
14
|
.prepare(`INSERT INTO provider_usage (id, project_id, stage, kind, provider, model, tokens_in, tokens_out, tokens_cached, characters, images, seconds, size, quality, wall_ms, on_plan, cost, api_model, api_cost, price_json, created_at)
|
|
14
15
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
15
|
-
.run(
|
|
16
|
+
.run(usageId, call.projectId, call.stage, call.kind, call.provider, call.model, call.tokensIn ?? null, call.tokensOut ?? null, call.cachedTokens ?? null, call.characters ?? null, call.images ?? null, call.seconds ?? null, call.size ?? null, call.quality ?? null, Math.round(call.wallMs), priced.onPlan ? 1 : 0, priced.cost, priced.apiModel, priced.apiCost, priced.price === null ? null : JSON.stringify(priced.price), at);
|
|
17
|
+
// The reading names its call, so the Run cost tab knows when the call ran and its tokens.
|
|
16
18
|
const account = planAccountOf(call.provider);
|
|
17
19
|
if (account !== undefined && call.limits !== undefined)
|
|
18
20
|
deps.db
|
|
19
21
|
.prepare("INSERT INTO plan_limit_readings (id, project_id, account, reading_json, created_at) VALUES (?, ?, ?, ?, ?)")
|
|
20
|
-
.run(deps.ids.next(), call.projectId, account, JSON.stringify(call.limits), at);
|
|
22
|
+
.run(deps.ids.next(), call.projectId, account, JSON.stringify({ ...call.limits, usageId }), at);
|
|
21
23
|
},
|
|
22
24
|
};
|
|
23
25
|
}
|
|
@@ -40,8 +42,13 @@ export function createStandaloneMeter(deps) {
|
|
|
40
42
|
}
|
|
41
43
|
// A schedule counts under its template's channel; one whose template is gone, like a channel
|
|
42
44
|
// this install doesn't have, under the default channel.
|
|
45
|
+
// A design counts under its own channel; one deleted since, under the default channel.
|
|
43
46
|
function channelOf(db, owner) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
if (owner.kind === "schedule")
|
|
48
|
+
return resolveChannelId(db, scheduleChannel(db, owner.id)?.id);
|
|
49
|
+
if (owner.kind === "design") {
|
|
50
|
+
const row = db.prepare("SELECT channel_id FROM designs WHERE id=?").get(owner.id);
|
|
51
|
+
return resolveChannelId(db, row === undefined ? undefined : String(row.channel_id));
|
|
52
|
+
}
|
|
53
|
+
return resolveChannelId(db, owner.id);
|
|
47
54
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { stageKinds } from "../../kernel/pipeline.js";
|
|
3
|
-
import { planAccountNames,
|
|
3
|
+
import { planAccountNames, planAccounts, } from "../../kernel/ports/plan-limits.js";
|
|
4
|
+
import { isSampleStandIn } from "../settings/model.js";
|
|
5
|
+
import { planUses } from "./plan-readings.js";
|
|
4
6
|
import { projectTiming } from "./timing.js";
|
|
5
7
|
const usageRow = z.object({
|
|
6
8
|
stage: z.enum(stageKinds),
|
|
@@ -19,15 +21,6 @@ const usageRow = z.object({
|
|
|
19
21
|
api_cost: z.number().nullable(),
|
|
20
22
|
price_json: z.string().nullable(),
|
|
21
23
|
});
|
|
22
|
-
const windowSchema = z.object({
|
|
23
|
-
kind: z.enum(["five_hour", "weekly", "other"]),
|
|
24
|
-
usedPercent: z.number(),
|
|
25
|
-
resetsAt: z.string().nullable(),
|
|
26
|
-
});
|
|
27
|
-
const readingSchema = z.object({
|
|
28
|
-
before: z.array(windowSchema).optional(),
|
|
29
|
-
after: z.array(windowSchema).optional(),
|
|
30
|
-
});
|
|
31
24
|
const emptyTotals = {
|
|
32
25
|
tokensIn: 0,
|
|
33
26
|
tokensOut: 0,
|
|
@@ -45,11 +38,13 @@ const emptyLine = {
|
|
|
45
38
|
};
|
|
46
39
|
function add(into, row) {
|
|
47
40
|
const onPlan = row.on_plan === 1;
|
|
41
|
+
// The bundled samples' calls were stored with no price; their stand-ins are free.
|
|
42
|
+
const cost = row.cost ?? (isSampleStandIn(row.provider) ? 0 : null);
|
|
48
43
|
return {
|
|
49
44
|
...into,
|
|
50
45
|
calls: into.calls + 1,
|
|
51
|
-
cost: into.cost + (
|
|
52
|
-
unpriced: into.unpriced + (
|
|
46
|
+
cost: into.cost + (cost ?? 0),
|
|
47
|
+
unpriced: into.unpriced + (cost === null ? 1 : 0),
|
|
53
48
|
apiEquivalent: onPlan ? (into.apiEquivalent ?? 0) + (row.api_cost ?? 0) : into.apiEquivalent,
|
|
54
49
|
apiUnpriced: into.apiUnpriced + (onPlan && row.api_cost === null ? 1 : 0),
|
|
55
50
|
tokensIn: into.tokensIn + (row.tokens_in ?? 0),
|
|
@@ -95,7 +90,7 @@ export function runCostOf(db, projectId, now = Date.now()) {
|
|
|
95
90
|
for (const [stage, wallMs] of walls)
|
|
96
91
|
if (!stages.has(stage))
|
|
97
92
|
stages.set(stage, { stage, wallMs, ...emptyLine, ...emptyTotals });
|
|
98
|
-
const plans = planUses(db, projectId, rows);
|
|
93
|
+
const plans = planUses(db, projectId, rows.map((row) => row.provider));
|
|
99
94
|
return {
|
|
100
95
|
currency: "USD",
|
|
101
96
|
...total,
|
|
@@ -128,67 +123,6 @@ function catalogueOf(json) {
|
|
|
128
123
|
const parsed = z.object({ catalogue: z.string() }).safeParse(JSON.parse(json));
|
|
129
124
|
return parsed.success ? parsed.data.catalogue : null;
|
|
130
125
|
}
|
|
131
|
-
// Two readings belong to the same window when their resets agree to within a few minutes;
|
|
132
|
-
// a reset moving on means the window rolled over between them.
|
|
133
|
-
const sameWindowMs = 5 * 60_000;
|
|
134
|
-
export function windowUse(readings) {
|
|
135
|
-
const byKind = new Map();
|
|
136
|
-
for (const reading of readings)
|
|
137
|
-
for (const window of reading)
|
|
138
|
-
byKind.set(window.kind, [...(byKind.get(window.kind) ?? []), window]);
|
|
139
|
-
const uses = [];
|
|
140
|
-
for (const [kind, seen] of byKind) {
|
|
141
|
-
let used = 0;
|
|
142
|
-
for (let at = 1; at < seen.length; at += 1) {
|
|
143
|
-
const previous = seen[at - 1];
|
|
144
|
-
const current = seen[at];
|
|
145
|
-
if (previous === undefined || current === undefined)
|
|
146
|
-
continue;
|
|
147
|
-
const same = previous.resetsAt === current.resetsAt ||
|
|
148
|
-
(previous.resetsAt !== null &&
|
|
149
|
-
current.resetsAt !== null &&
|
|
150
|
-
Math.abs(Date.parse(previous.resetsAt) - Date.parse(current.resetsAt)) < sameWindowMs);
|
|
151
|
-
used += same ? Math.max(0, current.usedPercent - previous.usedPercent) : current.usedPercent;
|
|
152
|
-
}
|
|
153
|
-
const last = seen.at(-1);
|
|
154
|
-
if (last !== undefined)
|
|
155
|
-
uses.push({ kind, usedPercent: used, nowPercent: last.usedPercent, resetsAt: last.resetsAt });
|
|
156
|
-
}
|
|
157
|
-
const order = ["five_hour", "weekly", "other"];
|
|
158
|
-
return uses.toSorted((left, right) => order.indexOf(left.kind) - order.indexOf(right.kind));
|
|
159
|
-
}
|
|
160
|
-
function planUses(db, projectId, rows) {
|
|
161
|
-
const readings = db
|
|
162
|
-
.prepare("SELECT account, reading_json FROM plan_limit_readings WHERE project_id = ? ORDER BY created_at, rowid")
|
|
163
|
-
.all(projectId)
|
|
164
|
-
.map((row) => z.object({ account: z.string(), reading_json: z.string() }).parse(row));
|
|
165
|
-
return planAccounts.flatMap((account) => {
|
|
166
|
-
const calls = rows.filter((row) => planAccountOf(row.provider) === account).length;
|
|
167
|
-
if (calls === 0)
|
|
168
|
-
return [];
|
|
169
|
-
const sequence = [];
|
|
170
|
-
for (const row of readings) {
|
|
171
|
-
if (row.account !== account)
|
|
172
|
-
continue;
|
|
173
|
-
const parsed = readingSchema.safeParse(JSON.parse(row.reading_json));
|
|
174
|
-
if (!parsed.success)
|
|
175
|
-
continue;
|
|
176
|
-
if (parsed.data.before?.length)
|
|
177
|
-
sequence.push(parsed.data.before);
|
|
178
|
-
if (parsed.data.after?.length)
|
|
179
|
-
sequence.push(parsed.data.after);
|
|
180
|
-
}
|
|
181
|
-
return [
|
|
182
|
-
{
|
|
183
|
-
account,
|
|
184
|
-
name: planAccountNames[account],
|
|
185
|
-
calls,
|
|
186
|
-
reported: sequence.length > 0,
|
|
187
|
-
windows: windowUse(sequence),
|
|
188
|
-
},
|
|
189
|
-
];
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
126
|
export function limitWaitsOf(db, projectId) {
|
|
193
127
|
return limitWaitRows(db, projectId).map((row) => row.wait);
|
|
194
128
|
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { planAccountNames, planAccountOf, planAccounts, } from "../../kernel/ports/plan-limits.js";
|
|
3
|
+
import { beforeGapMs, windowUse, } from "./plan-use.js";
|
|
4
|
+
const windowSchema = z.object({
|
|
5
|
+
kind: z.enum(["five_hour", "weekly", "other"]),
|
|
6
|
+
usedPercent: z.number(),
|
|
7
|
+
resetsAt: z.string().nullable(),
|
|
8
|
+
});
|
|
9
|
+
// `usageId` names the call's provider_usage row; readings stored before it was kept lack it.
|
|
10
|
+
export const readingSchema = z.object({
|
|
11
|
+
before: z.array(windowSchema).optional(),
|
|
12
|
+
after: z.array(windowSchema).optional(),
|
|
13
|
+
usageId: z.string().optional(),
|
|
14
|
+
});
|
|
15
|
+
const callRow = z.object({
|
|
16
|
+
id: z.string(),
|
|
17
|
+
provider: z.string(),
|
|
18
|
+
tokens_in: z.number().nullable(),
|
|
19
|
+
tokens_out: z.number().nullable(),
|
|
20
|
+
wall_ms: z.number(),
|
|
21
|
+
created_at: z.string(),
|
|
22
|
+
});
|
|
23
|
+
const readingRow = z.object({
|
|
24
|
+
id: z.string(),
|
|
25
|
+
account: z.string().nullable(),
|
|
26
|
+
reading_json: z.string().nullable(),
|
|
27
|
+
created_at: z.string(),
|
|
28
|
+
});
|
|
29
|
+
function callOf(row) {
|
|
30
|
+
const endMs = Date.parse(row.created_at);
|
|
31
|
+
return {
|
|
32
|
+
id: row.id,
|
|
33
|
+
startMs: endMs - row.wall_ms,
|
|
34
|
+
endMs,
|
|
35
|
+
tokens: row.tokens_in === null && row.tokens_out === null
|
|
36
|
+
? null
|
|
37
|
+
: (row.tokens_in ?? 0) + (row.tokens_out ?? 0),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function parseReading(json) {
|
|
41
|
+
if (json === null)
|
|
42
|
+
return undefined;
|
|
43
|
+
const parsed = readingSchema.safeParse(JSON.parse(json));
|
|
44
|
+
return parsed.success ? parsed.data : undefined;
|
|
45
|
+
}
|
|
46
|
+
function readingOf(stored, usageId, createdAt, calls) {
|
|
47
|
+
const call = usageId === undefined ? undefined : calls.get(usageId);
|
|
48
|
+
const at = Date.parse(createdAt);
|
|
49
|
+
return {
|
|
50
|
+
usageId: call === undefined ? null : call.id,
|
|
51
|
+
startMs: call?.startMs ?? at,
|
|
52
|
+
endMs: call?.endMs ?? at,
|
|
53
|
+
tokens: call?.tokens ?? null,
|
|
54
|
+
before: stored.before,
|
|
55
|
+
after: stored.after,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function planUses(db, projectId, providers) {
|
|
59
|
+
const ownCalls = db
|
|
60
|
+
.prepare("SELECT id, provider, tokens_in, tokens_out, wall_ms, created_at FROM provider_usage WHERE project_id = ?")
|
|
61
|
+
.all(projectId)
|
|
62
|
+
.map((row) => callRow.parse(row));
|
|
63
|
+
const ownReadings = db
|
|
64
|
+
.prepare("SELECT id, account, reading_json, created_at FROM plan_limit_readings WHERE project_id = ? ORDER BY created_at, rowid")
|
|
65
|
+
.all(projectId)
|
|
66
|
+
.map((row) => readingRow.parse(row));
|
|
67
|
+
return planAccounts.flatMap((account) => {
|
|
68
|
+
const calls = providers.filter((provider) => planAccountOf(provider) === account).length;
|
|
69
|
+
if (calls === 0)
|
|
70
|
+
return [];
|
|
71
|
+
const mine = ownReadings.filter((row) => row.account === account);
|
|
72
|
+
const activity = accountActivity(db, account, ownCalls, projectId);
|
|
73
|
+
const own = mine.flatMap((row) => {
|
|
74
|
+
const stored = parseReading(row.reading_json);
|
|
75
|
+
if (stored === undefined || (!stored.before?.length && !stored.after?.length))
|
|
76
|
+
return [];
|
|
77
|
+
return [readingOf(stored, stored.usageId, row.created_at, activity.byId)];
|
|
78
|
+
});
|
|
79
|
+
return [
|
|
80
|
+
{
|
|
81
|
+
account,
|
|
82
|
+
name: planAccountNames[account],
|
|
83
|
+
calls,
|
|
84
|
+
reported: own.length > 0,
|
|
85
|
+
windows: windowUse(own, {
|
|
86
|
+
calls: [...activity.byId.values()],
|
|
87
|
+
readings: activity.readings,
|
|
88
|
+
}),
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// Every call on the account from when this project's first call began (less the gap an
|
|
94
|
+
// after-only call may look back), from any project or schedule.
|
|
95
|
+
function accountActivity(db, account, ownCalls, projectId) {
|
|
96
|
+
const starts = ownCalls.map((row) => callOf(row).startMs);
|
|
97
|
+
const byId = new Map();
|
|
98
|
+
if (starts.length === 0)
|
|
99
|
+
return { byId, readings: [] };
|
|
100
|
+
const since = new Date(Math.min(...starts) - beforeGapMs).toISOString();
|
|
101
|
+
const projectCalls = db
|
|
102
|
+
.prepare("SELECT id, provider, tokens_in, tokens_out, wall_ms, created_at FROM provider_usage WHERE created_at >= ?")
|
|
103
|
+
.all(since)
|
|
104
|
+
.map((row) => callRow.parse(row));
|
|
105
|
+
const standalone = db
|
|
106
|
+
.prepare("SELECT id, provider, tokens_in, tokens_out, wall_ms, created_at, account, reading_json FROM standalone_usage WHERE created_at >= ?")
|
|
107
|
+
.all(since);
|
|
108
|
+
for (const row of [...projectCalls, ...standalone.map((raw) => callRow.parse(raw))])
|
|
109
|
+
if (planAccountOf(row.provider) === account)
|
|
110
|
+
byId.set(row.id, callOf(row));
|
|
111
|
+
const readings = [];
|
|
112
|
+
for (const raw of db
|
|
113
|
+
.prepare("SELECT id, account, reading_json, created_at FROM plan_limit_readings WHERE account = ? AND project_id != ? AND created_at >= ?")
|
|
114
|
+
.all(account, projectId, since)) {
|
|
115
|
+
const row = readingRow.parse(raw);
|
|
116
|
+
const stored = parseReading(row.reading_json);
|
|
117
|
+
if (stored !== undefined)
|
|
118
|
+
readings.push(readingOf(stored, stored.usageId, row.created_at, byId));
|
|
119
|
+
}
|
|
120
|
+
for (const raw of standalone) {
|
|
121
|
+
const row = readingRow.parse(raw);
|
|
122
|
+
const stored = row.account === account ? parseReading(row.reading_json) : undefined;
|
|
123
|
+
if (stored !== undefined)
|
|
124
|
+
readings.push(readingOf(stored, row.id, row.created_at, byId));
|
|
125
|
+
}
|
|
126
|
+
return { byId, readings };
|
|
127
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// How much of a CLI plan's windows a project's calls took. A plan's readings are account-wide:
|
|
2
|
+
// they move with every use of the account, this project's or not. So a call is charged only
|
|
3
|
+
// its own before→after rise, and only when nothing else on the account ran during it; calls
|
|
4
|
+
// that overlapped split their rise by tokens; anything else is said to be shared, not guessed.
|
|
5
|
+
// "measured": every call's rise was its own. "split": some overlapped and split their rise by
|
|
6
|
+
// tokens. "shared": some calls' share could not be told apart from other use. "approximate":
|
|
7
|
+
// stored before each call's own readings were kept, so only the account's rise is known.
|
|
8
|
+
export const windowBases = ["measured", "split", "shared", "approximate"];
|
|
9
|
+
// An after-only call (Claude Code reports its windows once) takes the account's reading just
|
|
10
|
+
// before it as its "before"; one older than this says nothing about the call alone.
|
|
11
|
+
export const beforeGapMs = 15 * 60_000;
|
|
12
|
+
// A stated reset that moves by less than this is drift, not a new window.
|
|
13
|
+
const resetDriftMs = 60 * 60_000;
|
|
14
|
+
const kindOrder = ["five_hour", "weekly", "other"];
|
|
15
|
+
const windowOf = (windows, kind) => windows?.find((window) => window.kind === kind);
|
|
16
|
+
export function windowUse(own, account = { calls: [], readings: [] }) {
|
|
17
|
+
const kinds = new Set();
|
|
18
|
+
for (const reading of own)
|
|
19
|
+
for (const window of [...(reading.before ?? []), ...(reading.after ?? [])])
|
|
20
|
+
kinds.add(window.kind);
|
|
21
|
+
return kindOrder.flatMap((kind) => {
|
|
22
|
+
if (!kinds.has(kind))
|
|
23
|
+
return [];
|
|
24
|
+
const use = kindUse(kind, own, account);
|
|
25
|
+
return use === undefined ? [] : [use];
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function kindUse(kind, own, account) {
|
|
29
|
+
const mine = own.filter((reading) => windowOf(reading.before, kind) !== undefined || windowOf(reading.after, kind) !== undefined);
|
|
30
|
+
const legacy = mine.some((reading) => reading.usageId === null);
|
|
31
|
+
const calls = new Map();
|
|
32
|
+
for (const call of account.calls)
|
|
33
|
+
calls.set(call.id, call);
|
|
34
|
+
for (const reading of own)
|
|
35
|
+
if (reading.usageId !== null)
|
|
36
|
+
calls.set(reading.usageId, {
|
|
37
|
+
id: reading.usageId,
|
|
38
|
+
startMs: reading.startMs,
|
|
39
|
+
endMs: reading.endMs,
|
|
40
|
+
tokens: reading.tokens,
|
|
41
|
+
});
|
|
42
|
+
const everyReading = [...own, ...account.readings];
|
|
43
|
+
const points = [];
|
|
44
|
+
let used = 0;
|
|
45
|
+
let measured = 0;
|
|
46
|
+
let split = 0;
|
|
47
|
+
let shared = 0;
|
|
48
|
+
for (const reading of mine) {
|
|
49
|
+
const before = windowOf(reading.before, kind);
|
|
50
|
+
const after = windowOf(reading.after, kind);
|
|
51
|
+
if (before !== undefined)
|
|
52
|
+
points.push({ atMs: reading.startMs, window: before });
|
|
53
|
+
if (after !== undefined)
|
|
54
|
+
points.push({ atMs: reading.endMs, window: after });
|
|
55
|
+
if (legacy || reading.usageId === null)
|
|
56
|
+
continue;
|
|
57
|
+
const start = before === undefined ? pointBefore(kind, reading, everyReading) : undefined;
|
|
58
|
+
if (start !== undefined)
|
|
59
|
+
points.push(start);
|
|
60
|
+
const from = before ?? start?.window;
|
|
61
|
+
const spanStart = before === undefined ? start?.atMs : reading.startMs;
|
|
62
|
+
if (from === undefined || after === undefined || spanStart === undefined) {
|
|
63
|
+
shared += 1;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const rise = rolledOver(from, after, reading.endMs)
|
|
67
|
+
? after.usedPercent
|
|
68
|
+
: after.usedPercent - from.usedPercent;
|
|
69
|
+
const beside = [...calls.values()].filter((call) => call.id !== reading.usageId && call.endMs > spanStart && call.startMs < reading.endMs);
|
|
70
|
+
if (beside.length === 0) {
|
|
71
|
+
used += rise;
|
|
72
|
+
measured += 1;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const tokens = reading.tokens ?? 0;
|
|
76
|
+
const others = beside.map((call) => call.tokens);
|
|
77
|
+
if (tokens <= 0 || others.some((count) => count === null)) {
|
|
78
|
+
shared += 1;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const total = others.reduce((sum, count) => sum + (count ?? 0), tokens);
|
|
82
|
+
used += (rise * tokens) / total;
|
|
83
|
+
split += 1;
|
|
84
|
+
}
|
|
85
|
+
const sorted = points.toSorted((left, right) => left.atMs - right.atMs);
|
|
86
|
+
const first = sorted[0];
|
|
87
|
+
const last = sorted.at(-1);
|
|
88
|
+
if (first === undefined || last === undefined)
|
|
89
|
+
return undefined;
|
|
90
|
+
const { rise: accountPercent, segments } = accountRise(sorted);
|
|
91
|
+
const share = legacy
|
|
92
|
+
? accountPercent
|
|
93
|
+
: measured + split === 0
|
|
94
|
+
? null
|
|
95
|
+
: Math.min(Math.max(0, used), accountPercent);
|
|
96
|
+
return {
|
|
97
|
+
kind,
|
|
98
|
+
usedPercent: share,
|
|
99
|
+
basis: legacy ? "approximate" : shared > 0 ? "shared" : split > 0 ? "split" : "measured",
|
|
100
|
+
sharedCalls: legacy ? 0 : shared,
|
|
101
|
+
fromPercent: first.window.usedPercent,
|
|
102
|
+
accountPercent,
|
|
103
|
+
rolledOver: segments > 1,
|
|
104
|
+
nowPercent: last.window.usedPercent,
|
|
105
|
+
resetsAt: last.window.resetsAt,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// The latest reading on the account at or before the call began, from any call but itself.
|
|
109
|
+
function pointBefore(kind, call, readings) {
|
|
110
|
+
let found;
|
|
111
|
+
for (const reading of readings) {
|
|
112
|
+
if (reading.usageId !== null && reading.usageId === call.usageId)
|
|
113
|
+
continue;
|
|
114
|
+
const candidates = [];
|
|
115
|
+
const before = windowOf(reading.before, kind);
|
|
116
|
+
const after = windowOf(reading.after, kind);
|
|
117
|
+
if (before !== undefined)
|
|
118
|
+
candidates.push({ atMs: reading.startMs, window: before });
|
|
119
|
+
if (after !== undefined)
|
|
120
|
+
candidates.push({ atMs: reading.endMs, window: after });
|
|
121
|
+
for (const point of candidates)
|
|
122
|
+
if (point.atMs <= call.startMs &&
|
|
123
|
+
point.atMs >= call.startMs - beforeGapMs &&
|
|
124
|
+
(found === undefined || point.atMs > found.atMs))
|
|
125
|
+
found = point;
|
|
126
|
+
}
|
|
127
|
+
return found;
|
|
128
|
+
}
|
|
129
|
+
// Within one call the window reset when the reading dropped or the stated reset passed.
|
|
130
|
+
function rolledOver(before, after, endMs) {
|
|
131
|
+
if (after.usedPercent < before.usedPercent)
|
|
132
|
+
return true;
|
|
133
|
+
return before.resetsAt !== null && Date.parse(before.resetsAt) <= endMs;
|
|
134
|
+
}
|
|
135
|
+
// Across many calls' readings a drop alone is not a reset: parallel calls report out of
|
|
136
|
+
// order. A new window needs the stated reset to have passed, or a drop with the reset moved
|
|
137
|
+
// on by more than drift. The rise is counted per window from its readings' range, at most 100.
|
|
138
|
+
function accountRise(points) {
|
|
139
|
+
let segments = 1;
|
|
140
|
+
let rise = 0;
|
|
141
|
+
let base = points[0]?.window.usedPercent ?? 0;
|
|
142
|
+
let peak = base;
|
|
143
|
+
for (let at = 1; at < points.length; at += 1) {
|
|
144
|
+
const previous = points[at - 1];
|
|
145
|
+
const current = points[at];
|
|
146
|
+
if (previous === undefined || current === undefined)
|
|
147
|
+
continue;
|
|
148
|
+
if (newWindow(previous, current)) {
|
|
149
|
+
rise += Math.max(0, peak - base);
|
|
150
|
+
segments += 1;
|
|
151
|
+
base = 0;
|
|
152
|
+
peak = current.window.usedPercent;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
peak = Math.max(peak, current.window.usedPercent);
|
|
156
|
+
}
|
|
157
|
+
rise += Math.max(0, peak - base);
|
|
158
|
+
return { rise: Math.min(100, rise), segments };
|
|
159
|
+
}
|
|
160
|
+
function newWindow(previous, current) {
|
|
161
|
+
const passed = previous.window.resetsAt !== null && Date.parse(previous.window.resetsAt) <= current.atMs;
|
|
162
|
+
if (passed)
|
|
163
|
+
return true;
|
|
164
|
+
if (current.window.usedPercent >= previous.window.usedPercent)
|
|
165
|
+
return false;
|
|
166
|
+
return (previous.window.resetsAt !== null &&
|
|
167
|
+
current.window.resetsAt !== null &&
|
|
168
|
+
Date.parse(current.window.resetsAt) - Date.parse(previous.window.resetsAt) > resetDriftMs);
|
|
169
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isLocalCliProvider, systemVoiceProvider } from "../settings/model.js";
|
|
1
|
+
import { isLocalCliProvider, isSampleStandIn, systemVoiceProvider } from "../settings/model.js";
|
|
2
2
|
// Per million tokens; cached input at its own rate when the catalogue gives one.
|
|
3
3
|
export function tokenCost(rates, tokensIn, tokensOut, cachedTokens = 0) {
|
|
4
4
|
if (rates.inputPerMillionTokens === undefined || rates.outputPerMillionTokens === undefined)
|
|
@@ -57,8 +57,8 @@ export function priceCall(call, catalogue) {
|
|
|
57
57
|
price: api === undefined ? null : { catalogue: date, model: api.id, ...api.pricing },
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
|
-
// The computer's own voice
|
|
61
|
-
if (call.provider === systemVoiceProvider)
|
|
60
|
+
// The computer's own voice and the samples' stand-ins cost nothing.
|
|
61
|
+
if (call.provider === systemVoiceProvider || isSampleStandIn(call.provider))
|
|
62
62
|
return { onPlan: false, cost: 0, apiModel: null, apiCost: null, price: null };
|
|
63
63
|
const family = call.kind === "video" ? "image" : call.kind;
|
|
64
64
|
const entry = catalogue[family].find((model) => model.provider === call.provider && model.id === call.model);
|
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { planAccountNames, planAccounts, } from "../../kernel/ports/plan-limits.js";
|
|
3
3
|
import { defaultChannelId } from "../channels/model.js";
|
|
4
4
|
import { projectChannels } from "../channels/repo.js";
|
|
5
|
+
import { notTemplateSample, templateSampleProjects } from "../template-studio/repo.js";
|
|
5
6
|
const usageRow = z.object({
|
|
6
7
|
project_id: z.string(),
|
|
7
8
|
on_plan: z.number(),
|
|
@@ -42,13 +43,30 @@ export function weekSummary(db, since, channelId) {
|
|
|
42
43
|
if (row.on_plan === 1)
|
|
43
44
|
apiEquivalent = (apiEquivalent ?? 0) + (row.api_cost ?? 0);
|
|
44
45
|
};
|
|
46
|
+
let studioCost = 0;
|
|
47
|
+
const hidden = templateSampleProjects(db);
|
|
45
48
|
for (const raw of db
|
|
46
49
|
.prepare("SELECT project_id, on_plan, cost, api_cost FROM provider_usage WHERE created_at >= ?")
|
|
47
50
|
.all(since)) {
|
|
48
51
|
const row = usageRow.parse(raw);
|
|
49
|
-
if (
|
|
50
|
-
|
|
52
|
+
if (hidden.has(row.project_id)) {
|
|
53
|
+
if (channelId !== undefined)
|
|
54
|
+
continue;
|
|
55
|
+
studioCost += row.cost ?? 0;
|
|
56
|
+
}
|
|
57
|
+
else if (!projectInScope(row.project_id))
|
|
58
|
+
continue;
|
|
59
|
+
count(row);
|
|
51
60
|
}
|
|
61
|
+
// A sample or bake-off copy removed since keeps what it was charged here.
|
|
62
|
+
if (channelId === undefined)
|
|
63
|
+
for (const raw of db
|
|
64
|
+
.prepare("SELECT cost FROM template_studio_spend WHERE created_at >= ?")
|
|
65
|
+
.all(since)) {
|
|
66
|
+
const spent = z.object({ cost: z.number() }).parse(raw).cost;
|
|
67
|
+
studioCost += spent;
|
|
68
|
+
count({ channel_id: "", on_plan: 0, cost: spent, api_cost: null });
|
|
69
|
+
}
|
|
52
70
|
for (const raw of db
|
|
53
71
|
.prepare("SELECT channel_id, on_plan, cost, api_cost FROM standalone_usage WHERE created_at >= ?")
|
|
54
72
|
.all(since)) {
|
|
@@ -59,11 +77,21 @@ export function weekSummary(db, since, channelId) {
|
|
|
59
77
|
count(row);
|
|
60
78
|
}
|
|
61
79
|
// A video is made when its file lands; a remade video counts again, as it was made again.
|
|
80
|
+
// A template's studio sample is no video of the person's (its spend still counts above).
|
|
62
81
|
const videos = db
|
|
63
|
-
.prepare(
|
|
82
|
+
.prepare(`SELECT project_id FROM outputs WHERE role = 'video' AND created_at >= ? AND ${notTemplateSample("outputs", "project_id")}`)
|
|
64
83
|
.all(since)
|
|
65
84
|
.filter((row) => projectInScope(String(row.project_id))).length;
|
|
66
|
-
return {
|
|
85
|
+
return {
|
|
86
|
+
since,
|
|
87
|
+
videos,
|
|
88
|
+
calls,
|
|
89
|
+
cost,
|
|
90
|
+
unpriced,
|
|
91
|
+
studioCost,
|
|
92
|
+
apiEquivalent,
|
|
93
|
+
plans: planStandings(db),
|
|
94
|
+
};
|
|
67
95
|
}
|
|
68
96
|
function knownChannels(db) {
|
|
69
97
|
return new Set(db
|