@lingjingai/scriptctl 0.35.0 → 0.36.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/README.md +21 -5
- package/changes/0.36.0.md +22 -0
- package/dist/bin.js +0 -0
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +52 -128
- package/dist/cli.js.map +1 -1
- package/dist/common.d.ts +0 -16
- package/dist/common.js +2 -342
- package/dist/common.js.map +1 -1
- package/dist/domain/ingest/apply-plan.d.ts +23 -0
- package/dist/domain/ingest/apply-plan.js +210 -0
- package/dist/domain/ingest/apply-plan.js.map +1 -0
- package/dist/domain/ingest/assembler.d.ts +57 -0
- package/dist/domain/ingest/assembler.js +181 -0
- package/dist/domain/ingest/assembler.js.map +1 -0
- package/dist/domain/ingest/chunker.d.ts +9 -0
- package/dist/domain/ingest/chunker.js +38 -0
- package/dist/domain/ingest/chunker.js.map +1 -0
- package/dist/domain/ingest/evidence.d.ts +5 -0
- package/dist/domain/ingest/evidence.js +66 -0
- package/dist/domain/ingest/evidence.js.map +1 -0
- package/dist/domain/ingest/govern.d.ts +3 -0
- package/dist/domain/ingest/govern.js +127 -0
- package/dist/domain/ingest/govern.js.map +1 -0
- package/dist/domain/ingest/jsonl-parser.d.ts +6 -0
- package/dist/domain/ingest/jsonl-parser.js +187 -0
- package/dist/domain/ingest/jsonl-parser.js.map +1 -0
- package/dist/domain/ingest/markdown-parser.d.ts +6 -0
- package/dist/domain/ingest/markdown-parser.js +186 -0
- package/dist/domain/ingest/markdown-parser.js.map +1 -0
- package/dist/domain/ingest/records.d.ts +71 -0
- package/dist/domain/ingest/records.js +9 -0
- package/dist/domain/ingest/records.js.map +1 -0
- package/dist/domain/ingest/renumber.d.ts +14 -0
- package/dist/domain/ingest/renumber.js +130 -0
- package/dist/domain/ingest/renumber.js.map +1 -0
- package/dist/domain/ingest/script-v3.d.ts +94 -0
- package/dist/domain/ingest/script-v3.js +7 -0
- package/dist/domain/ingest/script-v3.js.map +1 -0
- package/dist/domain/ingest/state-reconcile.d.ts +11 -0
- package/dist/domain/ingest/state-reconcile.js +90 -0
- package/dist/domain/ingest/state-reconcile.js.map +1 -0
- package/dist/domain/ingest/validation.d.ts +11 -0
- package/dist/domain/ingest/validation.js +168 -0
- package/dist/domain/ingest/validation.js.map +1 -0
- package/dist/domain/ingest/video-aggregate.d.ts +23 -0
- package/dist/domain/ingest/video-aggregate.js +89 -0
- package/dist/domain/ingest/video-aggregate.js.map +1 -0
- package/dist/domain/ingest/video-apply.d.ts +37 -0
- package/dist/domain/ingest/video-apply.js +236 -0
- package/dist/domain/ingest/video-apply.js.map +1 -0
- package/dist/domain/ingest/video-md-parser.d.ts +2 -0
- package/dist/domain/ingest/video-md-parser.js +233 -0
- package/dist/domain/ingest/video-md-parser.js.map +1 -0
- package/dist/domain/ingest/video-records.d.ts +56 -0
- package/dist/domain/ingest/video-records.js +9 -0
- package/dist/domain/ingest/video-records.js.map +1 -0
- package/dist/domain/loom/index.d.ts +2 -1
- package/dist/domain/loom/index.js +12 -10
- package/dist/domain/loom/index.js.map +1 -1
- package/dist/domain/loom/types.d.ts +3 -2
- package/dist/domain/script/lookups.d.ts +3 -2
- package/dist/domain/script/lookups.js +25 -8
- package/dist/domain/script/lookups.js.map +1 -1
- package/dist/domain/script/patch/apply.js +2 -2
- package/dist/domain/script/patch/apply.js.map +1 -1
- package/dist/domain/script/patch/helpers.d.ts +3 -7
- package/dist/domain/script/patch/helpers.js +23 -96
- package/dist/domain/script/patch/helpers.js.map +1 -1
- package/dist/domain/script/patch/ops-action.d.ts +0 -2
- package/dist/domain/script/patch/ops-action.js +34 -100
- package/dist/domain/script/patch/ops-action.js.map +1 -1
- package/dist/domain/script/patch/ops-asset.d.ts +1 -0
- package/dist/domain/script/patch/ops-asset.js +102 -155
- package/dist/domain/script/patch/ops-asset.js.map +1 -1
- package/dist/domain/script/patch/ops-dialogue.d.ts +1 -4
- package/dist/domain/script/patch/ops-dialogue.js +43 -220
- package/dist/domain/script/patch/ops-dialogue.js.map +1 -1
- package/dist/domain/script/patch/ops-extend.js +8 -2
- package/dist/domain/script/patch/ops-extend.js.map +1 -1
- package/dist/domain/script/patch/ops-meta.js.map +1 -1
- package/dist/domain/script/patch/ops-scene.js +26 -39
- package/dist/domain/script/patch/ops-scene.js.map +1 -1
- package/dist/domain/script/patch/ops-state.d.ts +3 -3
- package/dist/domain/script/patch/ops-state.js +33 -49
- package/dist/domain/script/patch/ops-state.js.map +1 -1
- package/dist/domain/script/patch/registry.js +9 -13
- package/dist/domain/script/patch/registry.js.map +1 -1
- package/dist/domain/script/refs.js +23 -111
- package/dist/domain/script/refs.js.map +1 -1
- package/dist/domain/script/scene-refs.d.ts +3 -0
- package/dist/domain/script/scene-refs.js +35 -0
- package/dist/domain/script/scene-refs.js.map +1 -0
- package/dist/domain/script/schema.js +17 -21
- package/dist/domain/script/schema.js.map +1 -1
- package/dist/domain/script/text-util.d.ts +7 -0
- package/dist/domain/script/text-util.js +91 -0
- package/dist/domain/script/text-util.js.map +1 -0
- package/dist/help-text.js +117 -410
- package/dist/help-text.js.map +1 -1
- package/dist/infra/converters.js +1 -1
- package/dist/infra/converters.js.map +1 -1
- package/dist/infra/episode-title.d.ts +4 -0
- package/dist/infra/episode-title.js +129 -0
- package/dist/infra/episode-title.js.map +1 -0
- package/dist/infra/ingest/review-renderer.d.ts +1 -0
- package/dist/infra/ingest/review-renderer.js +431 -0
- package/dist/infra/ingest/review-renderer.js.map +1 -0
- package/dist/infra/ingest/source-resolver.d.ts +21 -0
- package/dist/infra/ingest/source-resolver.js +51 -0
- package/dist/infra/ingest/source-resolver.js.map +1 -0
- package/dist/infra/ingest/text-reader.d.ts +3 -0
- package/dist/infra/ingest/text-reader.js +27 -0
- package/dist/infra/ingest/text-reader.js.map +1 -0
- package/dist/infra/ingest/video-discovery.d.ts +8 -0
- package/dist/infra/ingest/video-discovery.js +60 -0
- package/dist/infra/ingest/video-discovery.js.map +1 -0
- package/dist/infra/ingest/workspace-store.d.ts +18 -0
- package/dist/infra/ingest/workspace-store.js +70 -0
- package/dist/infra/ingest/workspace-store.js.map +1 -0
- package/dist/infra/llm/anthropic-model.d.ts +11 -0
- package/dist/infra/llm/anthropic-model.js +109 -0
- package/dist/infra/llm/anthropic-model.js.map +1 -0
- package/dist/infra/llm/gemini-upload.d.ts +9 -0
- package/dist/infra/llm/gemini-upload.js +94 -0
- package/dist/infra/llm/gemini-upload.js.map +1 -0
- package/dist/infra/llm/gemini-video-model.d.ts +47 -0
- package/dist/infra/llm/gemini-video-model.js +167 -0
- package/dist/infra/llm/gemini-video-model.js.map +1 -0
- package/dist/infra/llm/openai-compatible-model.d.ts +13 -0
- package/dist/infra/llm/openai-compatible-model.js +143 -0
- package/dist/infra/llm/openai-compatible-model.js.map +1 -0
- package/dist/infra/llm/proxy.d.ts +1 -0
- package/dist/infra/llm/proxy.js +30 -0
- package/dist/infra/llm/proxy.js.map +1 -0
- package/dist/infra/llm/retry.d.ts +5 -0
- package/dist/infra/llm/retry.js +20 -0
- package/dist/infra/llm/retry.js.map +1 -0
- package/dist/llm/composition.d.ts +5 -0
- package/dist/llm/composition.js +5 -0
- package/dist/llm/composition.js.map +1 -0
- package/dist/llm/config.d.ts +26 -0
- package/dist/llm/config.js +201 -0
- package/dist/llm/config.js.map +1 -0
- package/dist/llm/registry.d.ts +44 -0
- package/dist/llm/registry.js +48 -0
- package/dist/llm/registry.js.map +1 -0
- package/dist/llm/router.d.ts +23 -0
- package/dist/llm/router.js +0 -0
- package/dist/llm/router.js.map +1 -0
- package/dist/llm/tasks/ingest/asset-curate.d.ts +13 -0
- package/dist/llm/tasks/ingest/asset-curate.js +45 -0
- package/dist/llm/tasks/ingest/asset-curate.js.map +1 -0
- package/dist/llm/tasks/ingest/asset-extract.d.ts +12 -0
- package/dist/llm/tasks/ingest/asset-extract.js +51 -0
- package/dist/llm/tasks/ingest/asset-extract.js.map +1 -0
- package/dist/llm/tasks/ingest/asset-govern.d.ts +22 -0
- package/dist/llm/tasks/ingest/asset-govern.js +143 -0
- package/dist/llm/tasks/ingest/asset-govern.js.map +1 -0
- package/dist/llm/tasks/ingest/mention-resolve.d.ts +9 -0
- package/dist/llm/tasks/ingest/mention-resolve.js +39 -0
- package/dist/llm/tasks/ingest/mention-resolve.js.map +1 -0
- package/dist/llm/tasks/ingest/plot-speaker.d.ts +11 -0
- package/dist/llm/tasks/ingest/plot-speaker.js +72 -0
- package/dist/llm/tasks/ingest/plot-speaker.js.map +1 -0
- package/dist/llm/tasks/ingest/roster-merge.d.ts +46 -0
- package/dist/llm/tasks/ingest/roster-merge.js +235 -0
- package/dist/llm/tasks/ingest/roster-merge.js.map +1 -0
- package/dist/llm/tasks/ingest/state-merge.d.ts +10 -0
- package/dist/llm/tasks/ingest/state-merge.js +84 -0
- package/dist/llm/tasks/ingest/state-merge.js.map +1 -0
- package/dist/llm/tasks/ingest/state-reconcile.d.ts +8 -0
- package/dist/llm/tasks/ingest/state-reconcile.js +44 -0
- package/dist/llm/tasks/ingest/state-reconcile.js.map +1 -0
- package/dist/llm/tasks/ingest/text-normalize.d.ts +10 -0
- package/dist/llm/tasks/ingest/text-normalize.js +89 -0
- package/dist/llm/tasks/ingest/text-normalize.js.map +1 -0
- package/dist/llm/tasks/ingest/video-correct.d.ts +30 -0
- package/dist/llm/tasks/ingest/video-correct.js +144 -0
- package/dist/llm/tasks/ingest/video-correct.js.map +1 -0
- package/dist/llm/tasks/ingest/video-transcribe.d.ts +4 -0
- package/dist/llm/tasks/ingest/video-transcribe.js +105 -0
- package/dist/llm/tasks/ingest/video-transcribe.js.map +1 -0
- package/dist/llm/tasks/schemas.d.ts +5 -0
- package/dist/llm/tasks/schemas.js +107 -0
- package/dist/llm/tasks/schemas.js.map +1 -0
- package/dist/llm/types.d.ts +97 -0
- package/dist/llm/types.js +13 -0
- package/dist/llm/types.js.map +1 -0
- package/dist/usecases/doctor.d.ts +1 -1
- package/dist/usecases/doctor.js +36 -9
- package/dist/usecases/doctor.js.map +1 -1
- package/dist/usecases/ingest/command.d.ts +5 -0
- package/dist/usecases/ingest/command.js +57 -0
- package/dist/usecases/ingest/command.js.map +1 -0
- package/dist/usecases/ingest/fanout.d.ts +10 -0
- package/dist/usecases/ingest/fanout.js +23 -0
- package/dist/usecases/ingest/fanout.js.map +1 -0
- package/dist/usecases/ingest/pass4-mention-resolve.d.ts +11 -0
- package/dist/usecases/ingest/pass4-mention-resolve.js +52 -0
- package/dist/usecases/ingest/pass4-mention-resolve.js.map +1 -0
- package/dist/usecases/ingest/pass5-extract.d.ts +7 -0
- package/dist/usecases/ingest/pass5-extract.js +50 -0
- package/dist/usecases/ingest/pass5-extract.js.map +1 -0
- package/dist/usecases/ingest/pass5-govern.d.ts +13 -0
- package/dist/usecases/ingest/pass5-govern.js +155 -0
- package/dist/usecases/ingest/pass5-govern.js.map +1 -0
- package/dist/usecases/ingest/pipeline.d.ts +28 -0
- package/dist/usecases/ingest/pipeline.js +144 -0
- package/dist/usecases/ingest/pipeline.js.map +1 -0
- package/dist/usecases/ingest/publish-command.d.ts +4 -0
- package/dist/usecases/ingest/publish-command.js +77 -0
- package/dist/usecases/ingest/publish-command.js.map +1 -0
- package/dist/usecases/ingest/status.d.ts +39 -0
- package/dist/usecases/ingest/status.js +155 -0
- package/dist/usecases/ingest/status.js.map +1 -0
- package/dist/usecases/ingest/video-pass3.d.ts +26 -0
- package/dist/usecases/ingest/video-pass3.js +0 -0
- package/dist/usecases/ingest/video-pass3.js.map +1 -0
- package/dist/usecases/ingest/video-pipeline.d.ts +32 -0
- package/dist/usecases/ingest/video-pipeline.js +202 -0
- package/dist/usecases/ingest/video-pipeline.js.map +1 -0
- package/dist/usecases/ingest/view-command.d.ts +4 -0
- package/dist/usecases/ingest/view-command.js +51 -0
- package/dist/usecases/ingest/view-command.js.map +1 -0
- package/dist/usecases/script/actions.js +2 -2
- package/dist/usecases/script/actions.js.map +1 -1
- package/dist/usecases/script/actor.js.map +1 -1
- package/dist/usecases/script/actors.js.map +1 -1
- package/dist/usecases/script/add-actor.js.map +1 -1
- package/dist/usecases/script/add-episode.js.map +1 -1
- package/dist/usecases/script/add-location.js.map +1 -1
- package/dist/usecases/script/add-prop.js.map +1 -1
- package/dist/usecases/script/alias.js.map +1 -1
- package/dist/usecases/script/assets.js.map +1 -1
- package/dist/usecases/script/context.js.map +1 -1
- package/dist/usecases/script/create.js +3 -6
- package/dist/usecases/script/create.js.map +1 -1
- package/dist/usecases/script/delete.js.map +1 -1
- package/dist/usecases/script/describe.js.map +1 -1
- package/dist/usecases/script/dialogue.js +6 -13
- package/dist/usecases/script/dialogue.js.map +1 -1
- package/dist/usecases/script/do.js +1 -1
- package/dist/usecases/script/do.js.map +1 -1
- package/dist/usecases/script/episodes.js.map +1 -1
- package/dist/usecases/script/{add-speaker.d.ts → importance.d.ts} +1 -1
- package/dist/usecases/script/importance.js +17 -0
- package/dist/usecases/script/importance.js.map +1 -0
- package/dist/usecases/script/insert.js.map +1 -1
- package/dist/usecases/script/issues.js.map +1 -1
- package/dist/usecases/script/lib.d.ts +8 -6
- package/dist/usecases/script/lib.js +81 -97
- package/dist/usecases/script/lib.js.map +1 -1
- package/dist/usecases/script/locations.js.map +1 -1
- package/dist/usecases/script/merge.js.map +1 -1
- package/dist/usecases/script/move.js.map +1 -1
- package/dist/usecases/script/props.js.map +1 -1
- package/dist/usecases/script/refs.js.map +1 -1
- package/dist/usecases/script/rename.js.map +1 -1
- package/dist/usecases/script/replace.js.map +1 -1
- package/dist/usecases/script/role.js.map +1 -1
- package/dist/usecases/script/scenes.js +8 -15
- package/dist/usecases/script/scenes.js.map +1 -1
- package/dist/usecases/script/script-patch.js +1 -1
- package/dist/usecases/script/script-patch.js.map +1 -1
- package/dist/usecases/script/script-validate.js +1 -1
- package/dist/usecases/script/script-validate.js.map +1 -1
- package/dist/usecases/script/session.d.ts +4 -4
- package/dist/usecases/script/session.js +57 -78
- package/dist/usecases/script/session.js.map +1 -1
- package/dist/usecases/script/split.js.map +1 -1
- package/dist/usecases/script/state-add.js.map +1 -1
- package/dist/usecases/script/state-delete.js.map +1 -1
- package/dist/usecases/script/state-rename.js.map +1 -1
- package/dist/usecases/script/summary.js.map +1 -1
- package/dist/usecases/script/synopsis-generate.d.ts +4 -5
- package/dist/usecases/script/synopsis-generate.js +30 -46
- package/dist/usecases/script/synopsis-generate.js.map +1 -1
- package/dist/usecases/script/transition.js.map +1 -1
- package/dist/usecases/script/type.js.map +1 -1
- package/dist/usecases/script/worldview.js.map +1 -1
- package/package.json +22 -17
- package/skills/scriptctl/SKILL.md +140 -120
- package/skills/scriptctl/references/atomic-write-workflow.md +12 -9
- package/skills/scriptctl/references/ingest-workflow.md +85 -0
- package/skills/scriptctl/references/state-reference-repair.md +26 -39
- package/dist/domain/direct/runner.d.ts +0 -25
- package/dist/domain/direct/runner.js +0 -88
- package/dist/domain/direct/runner.js.map +0 -1
- package/dist/domain/direct/stage.d.ts +0 -108
- package/dist/domain/direct/stage.js +0 -134
- package/dist/domain/direct/stage.js.map +0 -1
- package/dist/domain/direct/stages/asset-curation.d.ts +0 -2
- package/dist/domain/direct/stages/asset-curation.js +0 -10
- package/dist/domain/direct/stages/asset-curation.js.map +0 -1
- package/dist/domain/direct/stages/batch-extract.d.ts +0 -2
- package/dist/domain/direct/stages/batch-extract.js +0 -12
- package/dist/domain/direct/stages/batch-extract.js.map +0 -1
- package/dist/domain/direct/stages/batch-plan.d.ts +0 -2
- package/dist/domain/direct/stages/batch-plan.js +0 -9
- package/dist/domain/direct/stages/batch-plan.js.map +0 -1
- package/dist/domain/direct/stages/episode-merge.d.ts +0 -2
- package/dist/domain/direct/stages/episode-merge.js +0 -11
- package/dist/domain/direct/stages/episode-merge.js.map +0 -1
- package/dist/domain/direct/stages/episode-plan.d.ts +0 -2
- package/dist/domain/direct/stages/episode-plan.js +0 -9
- package/dist/domain/direct/stages/episode-plan.js.map +0 -1
- package/dist/domain/direct/stages/episode-synopsis.d.ts +0 -2
- package/dist/domain/direct/stages/episode-synopsis.js +0 -12
- package/dist/domain/direct/stages/episode-synopsis.js.map +0 -1
- package/dist/domain/direct/stages/episode-titles.d.ts +0 -2
- package/dist/domain/direct/stages/episode-titles.js +0 -12
- package/dist/domain/direct/stages/episode-titles.js.map +0 -1
- package/dist/domain/direct/stages/index.d.ts +0 -19
- package/dist/domain/direct/stages/index.js +0 -41
- package/dist/domain/direct/stages/index.js.map +0 -1
- package/dist/domain/direct/stages/metadata.d.ts +0 -2
- package/dist/domain/direct/stages/metadata.js +0 -11
- package/dist/domain/direct/stages/metadata.js.map +0 -1
- package/dist/domain/direct/stages/script-merge.d.ts +0 -2
- package/dist/domain/direct/stages/script-merge.js +0 -15
- package/dist/domain/direct/stages/script-merge.js.map +0 -1
- package/dist/domain/direct/stages/script-synopsis.d.ts +0 -2
- package/dist/domain/direct/stages/script-synopsis.js +0 -12
- package/dist/domain/direct/stages/script-synopsis.js.map +0 -1
- package/dist/domain/direct/stages/source-prepare.d.ts +0 -2
- package/dist/domain/direct/stages/source-prepare.js +0 -9
- package/dist/domain/direct/stages/source-prepare.js.map +0 -1
- package/dist/domain/direct/stages/state-binding.d.ts +0 -2
- package/dist/domain/direct/stages/state-binding.js +0 -9
- package/dist/domain/direct/stages/state-binding.js.map +0 -1
- package/dist/domain/direct/stages/state-curation.d.ts +0 -2
- package/dist/domain/direct/stages/state-curation.js +0 -10
- package/dist/domain/direct/stages/state-curation.js.map +0 -1
- package/dist/domain/direct/stages/validate.d.ts +0 -2
- package/dist/domain/direct/stages/validate.js +0 -10
- package/dist/domain/direct/stages/validate.js.map +0 -1
- package/dist/domain/direct-core.d.ts +0 -313
- package/dist/domain/direct-core.js +0 -8514
- package/dist/domain/direct-core.js.map +0 -1
- package/dist/domain/script/validate.d.ts +0 -22
- package/dist/domain/script/validate.js +0 -997
- package/dist/domain/script/validate.js.map +0 -1
- package/dist/infra/providers.d.ts +0 -97
- package/dist/infra/providers.js +0 -1396
- package/dist/infra/providers.js.map +0 -1
- package/dist/usecases/direct.d.ts +0 -27
- package/dist/usecases/direct.js +0 -4172
- package/dist/usecases/direct.js.map +0 -1
- package/dist/usecases/parse.d.ts +0 -15
- package/dist/usecases/parse.js +0 -429
- package/dist/usecases/parse.js.map +0 -1
- package/dist/usecases/script/add-speaker.js +0 -22
- package/dist/usecases/script/add-speaker.js.map +0 -1
- package/dist/usecases/script/export.d.ts +0 -3
- package/dist/usecases/script/export.js +0 -111
- package/dist/usecases/script/export.js.map +0 -1
- package/dist/usecases/script/overlap.d.ts +0 -3
- package/dist/usecases/script/overlap.js +0 -21
- package/dist/usecases/script/overlap.js.map +0 -1
- package/dist/usecases/script/speakers.d.ts +0 -3
- package/dist/usecases/script/speakers.js +0 -28
- package/dist/usecases/script/speakers.js.map +0 -1
- package/dist/usecases/script/state-change.d.ts +0 -3
- package/dist/usecases/script/state-change.js +0 -24
- package/dist/usecases/script/state-change.js.map +0 -1
- package/skills/scriptctl/references/direct-workflow.md +0 -72
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare function atomicWrite(filePath: string, data: string | Buffer): void;
|
|
2
|
+
export declare function writeJson(filePath: string, value: unknown): void;
|
|
3
|
+
export declare function readJson<T = unknown>(filePath: string): T;
|
|
4
|
+
export declare function exists(filePath: string): boolean;
|
|
5
|
+
export declare class WorkspaceStore {
|
|
6
|
+
readonly root: string;
|
|
7
|
+
constructor(root: string);
|
|
8
|
+
private abs;
|
|
9
|
+
ensure(): void;
|
|
10
|
+
passDir(name: string): string;
|
|
11
|
+
readText(rel: string): string;
|
|
12
|
+
writeText(rel: string, data: string): void;
|
|
13
|
+
writeJson(rel: string, value: unknown): void;
|
|
14
|
+
readJson<T = unknown>(rel: string): T;
|
|
15
|
+
has(rel: string): boolean;
|
|
16
|
+
path(rel: string): string;
|
|
17
|
+
clearError(rel: string): void;
|
|
18
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Ingest workspace store (§5/§12.4). Owns the on-disk workspace: atomic writes
|
|
2
|
+
// (same-dir temp + fsync + rename), pass directories, manifest and run_state.
|
|
3
|
+
// All JSON is written atomically so a crash never leaves a half-written product.
|
|
4
|
+
import * as fs from "node:fs";
|
|
5
|
+
import * as path from "node:path";
|
|
6
|
+
export function atomicWrite(filePath, data) {
|
|
7
|
+
const dir = path.dirname(filePath);
|
|
8
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
9
|
+
const tmp = path.join(dir, `.${path.basename(filePath)}.${process.pid}.tmp`);
|
|
10
|
+
const fd = fs.openSync(tmp, "w");
|
|
11
|
+
try {
|
|
12
|
+
fs.writeFileSync(fd, data);
|
|
13
|
+
fs.fsyncSync(fd);
|
|
14
|
+
}
|
|
15
|
+
finally {
|
|
16
|
+
fs.closeSync(fd);
|
|
17
|
+
}
|
|
18
|
+
fs.renameSync(tmp, filePath);
|
|
19
|
+
}
|
|
20
|
+
export function writeJson(filePath, value) {
|
|
21
|
+
atomicWrite(filePath, JSON.stringify(value, null, 2) + "\n");
|
|
22
|
+
}
|
|
23
|
+
export function readJson(filePath) {
|
|
24
|
+
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
25
|
+
}
|
|
26
|
+
export function exists(filePath) {
|
|
27
|
+
return fs.existsSync(filePath);
|
|
28
|
+
}
|
|
29
|
+
export class WorkspaceStore {
|
|
30
|
+
root;
|
|
31
|
+
constructor(root) {
|
|
32
|
+
this.root = root;
|
|
33
|
+
}
|
|
34
|
+
abs(rel) {
|
|
35
|
+
return path.join(this.root, rel);
|
|
36
|
+
}
|
|
37
|
+
ensure() {
|
|
38
|
+
fs.mkdirSync(this.root, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
passDir(name) {
|
|
41
|
+
const dir = this.abs(name);
|
|
42
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
43
|
+
return dir;
|
|
44
|
+
}
|
|
45
|
+
readText(rel) {
|
|
46
|
+
return fs.readFileSync(this.abs(rel), "utf-8");
|
|
47
|
+
}
|
|
48
|
+
writeText(rel, data) {
|
|
49
|
+
atomicWrite(this.abs(rel), data);
|
|
50
|
+
}
|
|
51
|
+
writeJson(rel, value) {
|
|
52
|
+
writeJson(this.abs(rel), value);
|
|
53
|
+
}
|
|
54
|
+
readJson(rel) {
|
|
55
|
+
return readJson(this.abs(rel));
|
|
56
|
+
}
|
|
57
|
+
has(rel) {
|
|
58
|
+
return fs.existsSync(this.abs(rel));
|
|
59
|
+
}
|
|
60
|
+
path(rel) {
|
|
61
|
+
return this.abs(rel);
|
|
62
|
+
}
|
|
63
|
+
// Remove a unit's stale error sidecar after it succeeds (§5.3).
|
|
64
|
+
clearError(rel) {
|
|
65
|
+
const p = this.abs(rel);
|
|
66
|
+
if (fs.existsSync(p))
|
|
67
|
+
fs.rmSync(p);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=workspace-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-store.js","sourceRoot":"","sources":["../../../src/infra/ingest/workspace-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LlmProviderConfig, LlmModelConfig } from "../../llm/config.js";
|
|
2
|
+
import { type LlmAdapter, type TextGenerationRequest, type TextGenerationResponse, type ToolGenerationRequest, type ToolGenerationResponse } from "../../llm/types.js";
|
|
3
|
+
export declare class AnthropicModel implements LlmAdapter {
|
|
4
|
+
private readonly provider;
|
|
5
|
+
private readonly model;
|
|
6
|
+
private readonly client;
|
|
7
|
+
constructor(provider: LlmProviderConfig, model: LlmModelConfig, apiKey: string);
|
|
8
|
+
private params;
|
|
9
|
+
generateText(request: TextGenerationRequest): Promise<TextGenerationResponse>;
|
|
10
|
+
generateTool(request: ToolGenerationRequest): Promise<ToolGenerationResponse>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import Anthropic, { APIConnectionError, APIConnectionTimeoutError, APIError, APIUserAbortError } from "@anthropic-ai/sdk";
|
|
2
|
+
import { LlmTransportError, } from "../../llm/types.js";
|
|
3
|
+
import { withTransientRetry } from "./retry.js";
|
|
4
|
+
function requestError(error) {
|
|
5
|
+
if (error instanceof LlmTransportError)
|
|
6
|
+
return error;
|
|
7
|
+
if (error instanceof APIUserAbortError)
|
|
8
|
+
return new LlmTransportError("request_failed", "Anthropic request was aborted.");
|
|
9
|
+
if (error instanceof APIConnectionTimeoutError)
|
|
10
|
+
return new LlmTransportError("timeout", "Anthropic request timed out.", { retryable: true });
|
|
11
|
+
if (error instanceof APIConnectionError)
|
|
12
|
+
return new LlmTransportError("request_failed", "Anthropic connection failed.", { retryable: true, details: [error.message.slice(0, 500)] });
|
|
13
|
+
if (error instanceof APIError) {
|
|
14
|
+
const status = error.status ?? 0;
|
|
15
|
+
const retryable = status === 408 || status === 429 || status >= 500;
|
|
16
|
+
const code = status === 401 || status === 403 ? "auth" : status === 429 ? "rate_limited" : "request_failed";
|
|
17
|
+
return new LlmTransportError(code, "Anthropic request failed.", { retryable, details: [`status: ${status}`, error.message.slice(0, 500)] });
|
|
18
|
+
}
|
|
19
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
20
|
+
return new LlmTransportError("request_failed", "Anthropic request failed.", { details: [message.slice(0, 500)] });
|
|
21
|
+
}
|
|
22
|
+
export class AnthropicModel {
|
|
23
|
+
provider;
|
|
24
|
+
model;
|
|
25
|
+
client;
|
|
26
|
+
constructor(provider, model, apiKey) {
|
|
27
|
+
this.provider = provider;
|
|
28
|
+
this.model = model;
|
|
29
|
+
const options = { apiKey };
|
|
30
|
+
if (provider.baseUrl)
|
|
31
|
+
options.baseURL = provider.baseUrl;
|
|
32
|
+
this.client = new Anthropic({ ...options, maxRetries: 0 });
|
|
33
|
+
}
|
|
34
|
+
params(request) {
|
|
35
|
+
const params = {
|
|
36
|
+
model: this.model.model,
|
|
37
|
+
max_tokens: request.maxOutputTokens,
|
|
38
|
+
stream: false,
|
|
39
|
+
messages: [{ role: "user", content: request.user }],
|
|
40
|
+
};
|
|
41
|
+
if (request.system.trim())
|
|
42
|
+
params.system = request.system;
|
|
43
|
+
if (this.model.thinkingBudgetTokens !== undefined) {
|
|
44
|
+
params.thinking = { type: "enabled", budget_tokens: this.model.thinkingBudgetTokens };
|
|
45
|
+
}
|
|
46
|
+
return params;
|
|
47
|
+
}
|
|
48
|
+
async generateText(request) {
|
|
49
|
+
const result = await withTransientRetry(this.provider.maxAttempts, async () => {
|
|
50
|
+
try {
|
|
51
|
+
const response = await this.client.messages.create(this.params(request), {
|
|
52
|
+
timeout: this.provider.timeoutMs,
|
|
53
|
+
signal: request.signal,
|
|
54
|
+
});
|
|
55
|
+
if (response.stop_reason === "max_tokens") {
|
|
56
|
+
throw new LlmTransportError("truncated", "Provider output was truncated.");
|
|
57
|
+
}
|
|
58
|
+
if (response.stop_reason === "refusal")
|
|
59
|
+
throw new LlmTransportError("content_filtered", "Provider filtered the response.");
|
|
60
|
+
const text = response.content
|
|
61
|
+
.filter((block) => block.type === "text")
|
|
62
|
+
.map((block) => block.text)
|
|
63
|
+
.join("\n")
|
|
64
|
+
.trim();
|
|
65
|
+
if (!text)
|
|
66
|
+
throw new LlmTransportError("empty_response", "Provider returned an empty text response.");
|
|
67
|
+
return { text, finishReason: response.stop_reason ?? "", raw: response };
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
throw requestError(error);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
return { ...result.value, attempts: result.attempts };
|
|
74
|
+
}
|
|
75
|
+
async generateTool(request) {
|
|
76
|
+
const result = await withTransientRetry(this.provider.maxAttempts, async () => {
|
|
77
|
+
try {
|
|
78
|
+
const tool = {
|
|
79
|
+
name: request.tool.name,
|
|
80
|
+
description: request.tool.description,
|
|
81
|
+
input_schema: { type: "object", ...request.tool.inputSchema },
|
|
82
|
+
};
|
|
83
|
+
const response = await this.client.messages.create({
|
|
84
|
+
...this.params(request),
|
|
85
|
+
tools: [tool],
|
|
86
|
+
tool_choice: { type: "tool", name: request.tool.name, disable_parallel_tool_use: true },
|
|
87
|
+
}, {
|
|
88
|
+
timeout: this.provider.timeoutMs,
|
|
89
|
+
signal: request.signal,
|
|
90
|
+
});
|
|
91
|
+
if (response.stop_reason === "max_tokens") {
|
|
92
|
+
throw new LlmTransportError("truncated", "Provider tool output was truncated.");
|
|
93
|
+
}
|
|
94
|
+
if (response.stop_reason === "refusal")
|
|
95
|
+
throw new LlmTransportError("content_filtered", "Provider filtered the response.");
|
|
96
|
+
const block = response.content.find((item) => item.type === "tool_use" && item.name === request.tool.name);
|
|
97
|
+
if (!block || block.type !== "tool_use") {
|
|
98
|
+
throw new LlmTransportError("invalid_response", "Provider did not return the required tool call.");
|
|
99
|
+
}
|
|
100
|
+
return { input: block.input, finishReason: response.stop_reason ?? "", raw: response };
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
throw requestError(error);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
return { ...result.value, attempts: result.attempts };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=anthropic-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic-model.js","sourceRoot":"","sources":["../../../src/infra/llm/anthropic-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Gemini Files API resumable upload over Node's built-in https (not undici).
|
|
2
|
+
// undici's strict content-length parser rejects the resumable-upload response
|
|
3
|
+
// when it traverses a local HTTP proxy (Clash) with "invalid content-length
|
|
4
|
+
// header"; Node's https parser is lenient and works. Only the upload step needs
|
|
5
|
+
// this — files.get/delete and generateContent are plain requests the SDK's fetch
|
|
6
|
+
// handles fine. The file body is streamed (never fully buffered).
|
|
7
|
+
import * as fs from "node:fs";
|
|
8
|
+
import * as https from "node:https";
|
|
9
|
+
import { HttpsProxyAgent } from "https-proxy-agent";
|
|
10
|
+
import { LlmTransportError } from "../../llm/types.js";
|
|
11
|
+
const HOST = "generativelanguage.googleapis.com";
|
|
12
|
+
function proxyAgent(proxyUrl) {
|
|
13
|
+
return proxyUrl ? new HttpsProxyAgent(proxyUrl) : undefined;
|
|
14
|
+
}
|
|
15
|
+
function request(opts, body, signal) {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const req = https.request(opts, (res) => {
|
|
18
|
+
let data = "";
|
|
19
|
+
res.on("data", (c) => (data += c));
|
|
20
|
+
res.on("end", () => resolve({ status: res.statusCode ?? 0, headers: res.headers, body: data }));
|
|
21
|
+
});
|
|
22
|
+
req.on("error", reject);
|
|
23
|
+
if (signal) {
|
|
24
|
+
if (signal.aborted) {
|
|
25
|
+
req.destroy(new Error("aborted"));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
signal.addEventListener("abort", () => req.destroy(new Error("aborted")), { once: true });
|
|
29
|
+
}
|
|
30
|
+
if (body && typeof body.pipe === "function")
|
|
31
|
+
body.pipe(req);
|
|
32
|
+
else {
|
|
33
|
+
if (body)
|
|
34
|
+
req.write(body);
|
|
35
|
+
req.end();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function header(h, name) {
|
|
40
|
+
const v = h[name];
|
|
41
|
+
return Array.isArray(v) ? (v[0] ?? "") : (v ?? "");
|
|
42
|
+
}
|
|
43
|
+
export async function resumableUpload(params) {
|
|
44
|
+
const size = fs.statSync(params.filePath).size;
|
|
45
|
+
const agent = proxyAgent(params.proxyUrl ?? "");
|
|
46
|
+
const common = { agent, timeout: params.timeoutMs };
|
|
47
|
+
let start;
|
|
48
|
+
try {
|
|
49
|
+
start = await request({
|
|
50
|
+
...common, method: "POST", host: HOST, path: `/upload/v1beta/files?key=${params.apiKey}`,
|
|
51
|
+
headers: {
|
|
52
|
+
"X-Goog-Upload-Protocol": "resumable", "X-Goog-Upload-Command": "start",
|
|
53
|
+
"X-Goog-Upload-Header-Content-Length": String(size), "X-Goog-Upload-Header-Content-Type": params.mimeType,
|
|
54
|
+
"Content-Type": "application/json",
|
|
55
|
+
},
|
|
56
|
+
}, JSON.stringify({ file: {} }), params.signal);
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
throw new LlmTransportError("request_failed", "Gemini upload start failed.", { retryable: !params.signal?.aborted, details: [e instanceof Error ? e.message : String(e)] });
|
|
60
|
+
}
|
|
61
|
+
if (start.status === 401 || start.status === 403)
|
|
62
|
+
throw new LlmTransportError("auth", "Gemini upload unauthorized.", { details: [start.body.slice(0, 300)] });
|
|
63
|
+
const uploadUrl = header(start.headers, "x-goog-upload-url");
|
|
64
|
+
if (start.status < 200 || start.status >= 300 || !uploadUrl) {
|
|
65
|
+
const retryable = start.status === 429 || start.status >= 500;
|
|
66
|
+
throw new LlmTransportError("request_failed", "Gemini upload start returned no upload URL.", { retryable, details: [`status: ${start.status}`, start.body.slice(0, 300)] });
|
|
67
|
+
}
|
|
68
|
+
const u = new URL(uploadUrl);
|
|
69
|
+
let up;
|
|
70
|
+
try {
|
|
71
|
+
up = await request({
|
|
72
|
+
...common, method: "POST", host: u.hostname, path: u.pathname + u.search,
|
|
73
|
+
headers: { "Content-Length": String(size), "X-Goog-Upload-Offset": "0", "X-Goog-Upload-Command": "upload, finalize" },
|
|
74
|
+
}, fs.createReadStream(params.filePath), params.signal);
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
throw new LlmTransportError("request_failed", "Gemini upload transfer failed.", { retryable: !params.signal?.aborted, details: [e instanceof Error ? e.message : String(e)] });
|
|
78
|
+
}
|
|
79
|
+
if (up.status < 200 || up.status >= 300) {
|
|
80
|
+
const retryable = up.status === 429 || up.status >= 500;
|
|
81
|
+
throw new LlmTransportError("request_failed", "Gemini upload transfer failed.", { retryable, details: [`status: ${up.status}`, up.body.slice(0, 300)] });
|
|
82
|
+
}
|
|
83
|
+
let parsed;
|
|
84
|
+
try {
|
|
85
|
+
parsed = JSON.parse(up.body);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
throw new LlmTransportError("invalid_response", "Gemini upload returned invalid JSON.", { details: [up.body.slice(0, 300)] });
|
|
89
|
+
}
|
|
90
|
+
if (!parsed.file)
|
|
91
|
+
throw new LlmTransportError("invalid_response", "Gemini upload returned no file.", { details: [up.body.slice(0, 300)] });
|
|
92
|
+
return parsed.file;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=gemini-upload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-upload.js","sourceRoot":"","sources":["../../../src/infra/llm/gemini-upload.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { LlmModelConfig, LlmProviderConfig } from "../../llm/config.js";
|
|
2
|
+
import { type VideoFileHandle, type VideoGenerationRequest, type VideoGenerationResponse, type VideoUnderstandingPort } from "../../llm/types.js";
|
|
3
|
+
export interface GeminiFile {
|
|
4
|
+
name?: string;
|
|
5
|
+
uri?: string;
|
|
6
|
+
mimeType?: string;
|
|
7
|
+
state?: string;
|
|
8
|
+
error?: {
|
|
9
|
+
message?: string;
|
|
10
|
+
} | undefined;
|
|
11
|
+
}
|
|
12
|
+
export interface GeminiGenerateResponse {
|
|
13
|
+
text?: string;
|
|
14
|
+
candidates?: Array<{
|
|
15
|
+
finishReason?: string;
|
|
16
|
+
}>;
|
|
17
|
+
usageMetadata?: unknown;
|
|
18
|
+
}
|
|
19
|
+
export interface GeminiClient {
|
|
20
|
+
files: {
|
|
21
|
+
upload(params: {
|
|
22
|
+
file: string;
|
|
23
|
+
config?: {
|
|
24
|
+
mimeType?: string;
|
|
25
|
+
};
|
|
26
|
+
}): Promise<GeminiFile>;
|
|
27
|
+
get(params: {
|
|
28
|
+
name: string;
|
|
29
|
+
}): Promise<GeminiFile>;
|
|
30
|
+
delete(params: {
|
|
31
|
+
name: string;
|
|
32
|
+
}): Promise<unknown>;
|
|
33
|
+
};
|
|
34
|
+
models: {
|
|
35
|
+
generateContent(params: Record<string, unknown>): Promise<GeminiGenerateResponse>;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export declare class GeminiVideoModel implements VideoUnderstandingPort {
|
|
39
|
+
private readonly provider;
|
|
40
|
+
private readonly model;
|
|
41
|
+
private readonly client;
|
|
42
|
+
constructor(provider: LlmProviderConfig, model: LlmModelConfig, apiKey: string, client?: GeminiClient);
|
|
43
|
+
upload(localPath: string, mimeType: string, signal?: AbortSignal): Promise<VideoFileHandle>;
|
|
44
|
+
private pollActive;
|
|
45
|
+
generate(request: VideoGenerationRequest): Promise<VideoGenerationResponse>;
|
|
46
|
+
delete(handle: VideoFileHandle, signal?: AbortSignal): Promise<void>;
|
|
47
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// Gemini video-understanding adapter (§10.5). Implements VideoUnderstandingPort
|
|
2
|
+
// over the Files API: upload a media file once, poll to ACTIVE, generate against
|
|
3
|
+
// the file reference (fps at the media-part level), and delete when done. The
|
|
4
|
+
// adapter owns transport only — it never builds business prompts or imports the
|
|
5
|
+
// ingest domain. The Google SDK is reached through a narrow structural client so
|
|
6
|
+
// tests inject a fake and never hit the network.
|
|
7
|
+
import { createRequire } from "node:module";
|
|
8
|
+
import { LlmTransportError, } from "../../llm/types.js";
|
|
9
|
+
import { resumableUpload } from "./gemini-upload.js";
|
|
10
|
+
import { installProxyFromEnv } from "./proxy.js";
|
|
11
|
+
import { withTransientRetry } from "./retry.js";
|
|
12
|
+
// Poll cadence while an uploaded file is still PROCESSING. Overall budget is the
|
|
13
|
+
// provider timeout; tests inject clients that return ACTIVE immediately.
|
|
14
|
+
const POLL_INTERVAL_MS = 2000;
|
|
15
|
+
function delay(ms) {
|
|
16
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
17
|
+
}
|
|
18
|
+
function statusOf(error) {
|
|
19
|
+
if (error && typeof error === "object" && typeof error.status === "number") {
|
|
20
|
+
return error.status;
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
// Map an SDK/network error to a transport error with the same retry policy as
|
|
25
|
+
// the other adapters: retry only transient network/timeout/408/429/5xx.
|
|
26
|
+
function toTransportError(error, signal, what) {
|
|
27
|
+
if (error instanceof LlmTransportError)
|
|
28
|
+
return error;
|
|
29
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
30
|
+
const status = statusOf(error);
|
|
31
|
+
if (status !== null) {
|
|
32
|
+
const retryable = status === 408 || status === 429 || status >= 500;
|
|
33
|
+
const code = status === 401 || status === 403 ? "auth" : status === 429 ? "rate_limited" : "request_failed";
|
|
34
|
+
return new LlmTransportError(code, `Gemini ${what} failed.`, { retryable, details: [`status: ${status}`, message.slice(0, 500)] });
|
|
35
|
+
}
|
|
36
|
+
const aborted = signal?.aborted ?? false;
|
|
37
|
+
return new LlmTransportError(aborted ? "request_failed" : "timeout", `Gemini ${what} failed.`, {
|
|
38
|
+
retryable: !aborted,
|
|
39
|
+
details: [message.slice(0, 500)],
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
export class GeminiVideoModel {
|
|
43
|
+
provider;
|
|
44
|
+
model;
|
|
45
|
+
client;
|
|
46
|
+
constructor(provider, model, apiKey, client) {
|
|
47
|
+
this.provider = provider;
|
|
48
|
+
this.model = model;
|
|
49
|
+
this.client = client ?? createGoogleClient(apiKey, provider.timeoutMs);
|
|
50
|
+
}
|
|
51
|
+
async upload(localPath, mimeType, signal) {
|
|
52
|
+
const { value: file } = await withTransientRetry(this.provider.maxAttempts, async () => {
|
|
53
|
+
try {
|
|
54
|
+
return await this.client.files.upload({ file: localPath, config: { mimeType } });
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
throw toTransportError(error, signal, "upload");
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
const active = await this.pollActive(file, signal);
|
|
61
|
+
if (!active.name || !active.uri) {
|
|
62
|
+
throw new LlmTransportError("invalid_response", "Gemini upload returned no file reference.");
|
|
63
|
+
}
|
|
64
|
+
return { name: active.name, uri: active.uri, mimeType: active.mimeType ?? mimeType };
|
|
65
|
+
}
|
|
66
|
+
async pollActive(initial, signal) {
|
|
67
|
+
let file = initial;
|
|
68
|
+
const deadline = Date.now() + this.provider.timeoutMs;
|
|
69
|
+
// Media-processing failure is terminal — never retried (§12.3).
|
|
70
|
+
while ((file.state ?? "").toUpperCase() === "PROCESSING") {
|
|
71
|
+
if (signal?.aborted)
|
|
72
|
+
throw new LlmTransportError("request_failed", "Gemini upload aborted.");
|
|
73
|
+
if (Date.now() >= deadline)
|
|
74
|
+
throw new LlmTransportError("timeout", "Gemini file processing timed out.");
|
|
75
|
+
await delay(POLL_INTERVAL_MS);
|
|
76
|
+
if (!file.name)
|
|
77
|
+
throw new LlmTransportError("invalid_response", "Gemini upload returned no file name to poll.");
|
|
78
|
+
try {
|
|
79
|
+
file = await this.client.files.get({ name: file.name });
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
throw toTransportError(error, signal, "file poll");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if ((file.state ?? "").toUpperCase() === "FAILED") {
|
|
86
|
+
throw new LlmTransportError("invalid_response", "Gemini file processing failed.", { details: [file.error?.message ?? "unknown media error"] });
|
|
87
|
+
}
|
|
88
|
+
return file;
|
|
89
|
+
}
|
|
90
|
+
async generate(request) {
|
|
91
|
+
const config = {
|
|
92
|
+
// High media resolution reads small on-screen text (subtitles, name cards)
|
|
93
|
+
// and fine visual anchors (§10.3).
|
|
94
|
+
mediaResolution: "MEDIA_RESOLUTION_HIGH",
|
|
95
|
+
maxOutputTokens: request.maxOutputTokens,
|
|
96
|
+
};
|
|
97
|
+
if (request.system?.trim())
|
|
98
|
+
config["systemInstruction"] = request.system;
|
|
99
|
+
if (request.responseJsonSchema) {
|
|
100
|
+
config["responseMimeType"] = "application/json";
|
|
101
|
+
config["responseJsonSchema"] = request.responseJsonSchema;
|
|
102
|
+
}
|
|
103
|
+
const params = {
|
|
104
|
+
model: this.model.model,
|
|
105
|
+
contents: [{
|
|
106
|
+
role: "user",
|
|
107
|
+
parts: [
|
|
108
|
+
{ text: request.user },
|
|
109
|
+
// fps is part-level; >1 fps unlocks sub-second MM:SS.sss timecodes (§10.3).
|
|
110
|
+
{ fileData: { fileUri: request.file.uri, mimeType: request.file.mimeType }, videoMetadata: { fps: request.fps } },
|
|
111
|
+
],
|
|
112
|
+
}],
|
|
113
|
+
config,
|
|
114
|
+
};
|
|
115
|
+
const { value, attempts } = await withTransientRetry(this.provider.maxAttempts, async () => {
|
|
116
|
+
let response;
|
|
117
|
+
try {
|
|
118
|
+
response = await this.client.models.generateContent(params);
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
throw toTransportError(error, request.signal, "generateContent");
|
|
122
|
+
}
|
|
123
|
+
const finishReason = response.candidates?.[0]?.finishReason ?? "";
|
|
124
|
+
if (finishReason === "MAX_TOKENS")
|
|
125
|
+
throw new LlmTransportError("truncated", "Gemini output was truncated.");
|
|
126
|
+
if (finishReason === "SAFETY" || finishReason === "PROHIBITED_CONTENT")
|
|
127
|
+
throw new LlmTransportError("content_filtered", "Gemini filtered the response.");
|
|
128
|
+
const text = (response.text ?? "").trim();
|
|
129
|
+
if (!text)
|
|
130
|
+
throw new LlmTransportError("empty_response", "Gemini returned an empty response.");
|
|
131
|
+
return { text, finishReason, raw: response };
|
|
132
|
+
});
|
|
133
|
+
return { text: value.text, finishReason: value.finishReason, attempts, raw: value.raw };
|
|
134
|
+
}
|
|
135
|
+
async delete(handle, signal) {
|
|
136
|
+
try {
|
|
137
|
+
await this.client.files.delete({ name: handle.name });
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
// Cleanup is best-effort (§10.5); a failed delete must not fail the run.
|
|
141
|
+
void error;
|
|
142
|
+
void signal;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Lazily import the SDK so the dependency is only loaded when a video route is
|
|
147
|
+
// actually exercised (keeps text-only runs free of @google/genai).
|
|
148
|
+
const require = createRequire(import.meta.url);
|
|
149
|
+
function createGoogleClient(apiKey, timeoutMs) {
|
|
150
|
+
// Route Google egress through the proxy env (Node fetch ignores it otherwise);
|
|
151
|
+
// gateway/loopback stay direct. No-op without a proxy env.
|
|
152
|
+
installProxyFromEnv();
|
|
153
|
+
const { GoogleGenAI } = require("@google/genai");
|
|
154
|
+
const sdk = new GoogleGenAI({ apiKey });
|
|
155
|
+
const proxyUrl = (process.env.https_proxy ?? process.env.HTTPS_PROXY ?? process.env.http_proxy ?? process.env.HTTP_PROXY ?? "").trim();
|
|
156
|
+
// upload goes through Node https (undici rejects the resumable response's
|
|
157
|
+
// content-length behind a proxy); get/delete/generateContent use the SDK.
|
|
158
|
+
return {
|
|
159
|
+
files: {
|
|
160
|
+
upload: (p) => resumableUpload({ apiKey, filePath: p.file, mimeType: p.config?.mimeType ?? "video/mp4", timeoutMs, proxyUrl }),
|
|
161
|
+
get: (p) => sdk.files.get(p),
|
|
162
|
+
delete: (p) => sdk.files.delete(p),
|
|
163
|
+
},
|
|
164
|
+
models: { generateContent: (p) => sdk.models.generateContent(p) },
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=gemini-video-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-video-model.js","sourceRoot":"","sources":["../../../src/infra/llm/gemini-video-model.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,iFAAiF;AACjF,8EAA8E;AAC9E,gFAAgF;AAChF,iFAAiF;AACjF,iDAAiD;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,EACL,iBAAiB,GAKlB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA6BhD,iFAAiF;AACjF,yEAAyE;AACzE,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAQ,KAA8B,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACrG,OAAQ,KAA4B,CAAC,MAAM,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,8EAA8E;AAC9E,wEAAwE;AACxE,SAAS,gBAAgB,CAAC,KAAc,EAAE,MAA+B,EAAE,IAAY;IACrF,IAAI,KAAK,YAAY,iBAAiB;QAAE,OAAO,KAAK,CAAC;IACrD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,MAAM,SAAS,GAAG,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC;QACpE,MAAM,IAAI,GAAG,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,gBAAgB,CAAC;QAC5G,OAAO,IAAI,iBAAiB,CAAC,IAAI,EAAE,UAAU,IAAI,UAAU,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,WAAW,MAAM,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;IACrI,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,EAAE,OAAO,IAAI,KAAK,CAAC;IACzC,OAAO,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,EAAE,UAAU,IAAI,UAAU,EAAE;QAC7F,SAAS,EAAE,CAAC,OAAO;QACnB,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;KACjC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,OAAO,gBAAgB;IAIR;IACA;IAJF,MAAM,CAAe;IAEtC,YACmB,QAA2B,EAC3B,KAAqB,EACtC,MAAc,EACd,MAAqB;QAHJ,aAAQ,GAAR,QAAQ,CAAmB;QAC3B,UAAK,GAAL,KAAK,CAAgB;QAItC,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,kBAAkB,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAAiB,EAAE,QAAgB,EAAE,MAAoB;QACpE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;YACrF,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;YACnF,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;YAClD,CAAC;QACH,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;YAChC,MAAM,IAAI,iBAAiB,CAAC,kBAAkB,EAAE,2CAA2C,CAAC,CAAC;QAC/F,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAC;IACvF,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,OAAmB,EAAE,MAAoB;QAChE,IAAI,IAAI,GAAG,OAAO,CAAC;QACnB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;QACtD,gEAAgE;QAChE,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,YAAY,EAAE,CAAC;YACzD,IAAI,MAAM,EAAE,OAAO;gBAAE,MAAM,IAAI,iBAAiB,CAAC,gBAAgB,EAAE,wBAAwB,CAAC,CAAC;YAC7F,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ;gBAAE,MAAM,IAAI,iBAAiB,CAAC,SAAS,EAAE,mCAAmC,CAAC,CAAC;YACxG,MAAM,KAAK,CAAC,gBAAgB,CAAC,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,iBAAiB,CAAC,kBAAkB,EAAE,8CAA8C,CAAC,CAAC;YAChH,IAAI,CAAC;gBACH,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,QAAQ,EAAE,CAAC;YAClD,MAAM,IAAI,iBAAiB,CAAC,kBAAkB,EAAE,gCAAgC,EAAE,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,IAAI,qBAAqB,CAAC,EAAE,CAAC,CAAC;QACjJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAA+B;QAC5C,MAAM,MAAM,GAA4B;YACtC,2EAA2E;YAC3E,mCAAmC;YACnC,eAAe,EAAE,uBAAuB;YACxC,eAAe,EAAE,OAAO,CAAC,eAAe;SACzC,CAAC;QACF,IAAI,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE;YAAE,MAAM,CAAC,mBAAmB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;QACzE,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;YAC/B,MAAM,CAAC,kBAAkB,CAAC,GAAG,kBAAkB,CAAC;YAChD,MAAM,CAAC,oBAAoB,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC;QAC5D,CAAC;QACD,MAAM,MAAM,GAA4B;YACtC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK;YACvB,QAAQ,EAAE,CAAC;oBACT,IAAI,EAAE,MAAM;oBACZ,KAAK,EAAE;wBACL,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;wBACtB,4EAA4E;wBAC5E,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE;qBAClH;iBACF,CAAC;YACF,MAAM;SACP,CAAC;QAEF,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;YACzF,IAAI,QAAgC,CAAC;YACrC,IAAI,CAAC;gBACH,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;YAC9D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;YACnE,CAAC;YACD,MAAM,YAAY,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,IAAI,EAAE,CAAC;YAClE,IAAI,YAAY,KAAK,YAAY;gBAAE,MAAM,IAAI,iBAAiB,CAAC,WAAW,EAAE,8BAA8B,CAAC,CAAC;YAC5G,IAAI,YAAY,KAAK,QAAQ,IAAI,YAAY,KAAK,oBAAoB;gBAAE,MAAM,IAAI,iBAAiB,CAAC,kBAAkB,EAAE,+BAA+B,CAAC,CAAC;YACzJ,MAAM,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1C,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,iBAAiB,CAAC,gBAAgB,EAAE,oCAAoC,CAAC,CAAC;YAC/F,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;QAC/C,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;IAC1F,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAuB,EAAE,MAAoB;QACxD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,yEAAyE;YACzE,KAAK,KAAK,CAAC;YACX,KAAK,MAAM,CAAC;QACd,CAAC;IACH,CAAC;CACF;AAED,+EAA+E;AAC/E,mEAAmE;AACnE,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,SAAS,kBAAkB,CAAC,MAAc,EAAE,SAAiB;IAC3D,+EAA+E;IAC/E,2DAA2D;IAC3D,mBAAmB,EAAE,CAAC;IACtB,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,eAAe,CAAmC,CAAC;IACnF,MAAM,GAAG,GAAG,IAAI,WAAW,CAAC,EAAE,MAAM,EAAE,CAGrC,CAAC;IACF,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvI,0EAA0E;IAC1E,0EAA0E;IAC1E,OAAO;QACL,KAAK,EAAE;YACL,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,QAAQ,IAAI,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;YAC9H,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5B,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;SACnC;QACD,MAAM,EAAE,EAAE,eAAe,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE;KAClE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LlmModelConfig, LlmProviderConfig } from "../../llm/config.js";
|
|
2
|
+
import { type LlmAdapter, type TextGenerationRequest, type TextGenerationResponse, type ToolGenerationRequest, type ToolGenerationResponse } from "../../llm/types.js";
|
|
3
|
+
export declare class OpenAiCompatibleModel implements LlmAdapter {
|
|
4
|
+
private readonly provider;
|
|
5
|
+
private readonly model;
|
|
6
|
+
private readonly apiKey;
|
|
7
|
+
private readonly url;
|
|
8
|
+
constructor(provider: LlmProviderConfig, model: LlmModelConfig, apiKey: string);
|
|
9
|
+
private post;
|
|
10
|
+
private baseBody;
|
|
11
|
+
generateText(request: TextGenerationRequest): Promise<TextGenerationResponse>;
|
|
12
|
+
generateTool(request: ToolGenerationRequest): Promise<ToolGenerationResponse>;
|
|
13
|
+
}
|