@theoremjs/agents 0.3.0 → 0.3.1
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 +276 -995
- package/esm/mod.d.ts +33 -19
- package/esm/mod.js +18 -11
- package/esm/src/cli/commands/bench.js +36 -14
- package/esm/src/cli/commands/detect-compile.d.ts +17 -0
- package/esm/src/cli/commands/detect-compile.js +22 -0
- package/esm/src/cli/commands/eval.d.ts +3 -3
- package/esm/src/cli/commands/fuzz-canary.js +55 -16
- package/esm/src/cli/commands/profile.js +4 -4
- package/esm/src/cli/commands/run.d.ts +2 -2
- package/esm/src/cli/commands/run.js +1 -1
- package/esm/src/cli/commands/test.d.ts +4 -3
- package/esm/src/cli/commands/test.js +2 -2
- package/esm/src/cli/index.js +9 -9
- package/esm/src/cli/matrix/fixtures.js +25 -30
- package/esm/src/evals/attachments.d.ts +1 -0
- package/esm/src/evals/attachments.js +4 -2
- package/esm/src/evals/breakdown.d.ts +2 -0
- package/esm/src/evals/breakdown.js +1 -0
- package/esm/src/evals/graders/answer.d.ts +3 -0
- package/esm/src/evals/graders/answer.js +1 -0
- package/esm/src/evals/graders/code.d.ts +7 -31
- package/esm/src/evals/graders/code.js +4 -25
- package/esm/src/evals/graders/judge.d.ts +4 -0
- package/esm/src/evals/graders/judge.js +7 -5
- package/esm/src/evals/graders/latency.d.ts +1 -0
- package/esm/src/evals/graders/latency.js +3 -2
- package/esm/src/evals/graders/live.d.ts +3 -0
- package/esm/src/evals/graders/live.js +2 -0
- package/esm/src/evals/graders/media.js +1 -2
- package/esm/src/evals/graders/shared.js +1 -1
- package/esm/src/evals/graders/transcript.d.ts +2 -0
- package/esm/src/evals/graders/transcript.js +5 -3
- package/esm/src/evals/mod.d.ts +1 -9
- package/esm/src/evals/mod.js +1 -9
- package/esm/src/evals/record.d.ts +6 -0
- package/esm/src/evals/record.js +4 -2
- package/esm/src/evals/rubrics/mod.d.ts +1 -1
- package/esm/src/evals/rubrics/mod.js +1 -1
- package/esm/src/evals/rubrics/mustache.js +1 -1
- package/esm/src/evals/rubrics/types.js +1 -1
- package/esm/src/evals/run.d.ts +9 -52
- package/esm/src/evals/run.js +12 -46
- package/esm/src/evals/suite.d.ts +12 -3
- package/esm/src/evals/suite.js +9 -4
- package/esm/src/evals/summary.d.ts +3 -0
- package/esm/src/evals/summary.js +1 -0
- package/esm/src/evals/trial.d.ts +3 -16
- package/esm/src/evals/trial.js +7 -30
- package/esm/src/evals/types.d.ts +30 -121
- package/esm/src/evals/types.js +3 -16
- package/esm/src/evals/verdict.d.ts +5 -0
- package/esm/src/evals/verdict.js +4 -1
- package/esm/src/guardrails/boundaries.d.ts +41 -0
- package/esm/src/guardrails/boundaries.js +103 -0
- package/esm/src/guardrails/canary-gate.d.ts +1 -0
- package/esm/src/guardrails/canary.d.ts +49 -15
- package/esm/src/guardrails/canary.js +103 -30
- package/esm/src/guardrails/compile-egress.d.ts +6 -5
- package/esm/src/guardrails/compile-egress.js +6 -5
- package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +3 -1
- package/esm/src/guardrails/corpus/canary-egress-attacks.js +4 -2
- package/esm/src/guardrails/corpus/fuzz-inbound.js +14 -17
- package/esm/src/guardrails/corpus/inbound-payloads.d.ts +2 -0
- package/esm/src/guardrails/corpus/inbound-payloads.js +4 -2
- package/esm/src/guardrails/corpus/live-attacks.d.ts +2 -0
- package/esm/src/guardrails/corpus/live-attacks.js +6 -1
- package/esm/src/guardrails/corpus/mod.d.ts +1 -1
- package/esm/src/guardrails/corpus/secrets.d.ts +3 -3
- package/esm/src/guardrails/corpus/secrets.js +2 -2
- package/esm/src/guardrails/corpus/strings.d.ts +1 -1
- package/esm/src/guardrails/corpus/strings.js +1 -1
- package/esm/src/guardrails/corpus/types.d.ts +5 -1
- package/esm/src/guardrails/credential-rules.d.ts +36 -0
- package/esm/src/guardrails/credential-rules.js +3001 -0
- package/esm/src/guardrails/credential-scan.d.ts +45 -0
- package/esm/src/guardrails/credential-scan.js +172 -0
- package/esm/src/guardrails/destinations.d.ts +45 -0
- package/esm/src/guardrails/destinations.js +234 -0
- package/esm/src/guardrails/detect-at.d.ts +107 -0
- package/esm/src/guardrails/detect-at.js +434 -0
- package/esm/src/guardrails/detect-reply.d.ts +61 -0
- package/esm/src/guardrails/detect-reply.js +95 -0
- package/esm/src/guardrails/detect-stream.d.ts +33 -0
- package/esm/src/guardrails/detect-stream.js +77 -0
- package/esm/src/guardrails/detectors.d.ts +216 -0
- package/esm/src/guardrails/detectors.js +503 -0
- package/esm/src/guardrails/egress-automata.d.ts +4 -6
- package/esm/src/guardrails/egress-automata.js +24095 -4572
- package/esm/src/guardrails/egress-compiler.d.ts +38 -16
- package/esm/src/guardrails/egress-compiler.js +254 -60
- package/esm/src/guardrails/egress-patterns.d.ts +4 -2
- package/esm/src/guardrails/egress-patterns.js +6 -2
- package/esm/src/guardrails/egress-stream.d.ts +54 -36
- package/esm/src/guardrails/egress-stream.js +253 -124
- package/esm/src/guardrails/egress-urls.d.ts +6 -3
- package/esm/src/guardrails/egress-urls.js +14 -22
- package/esm/src/guardrails/egress.d.ts +26 -86
- package/esm/src/guardrails/egress.js +59 -309
- package/esm/src/guardrails/error.d.ts +13 -8
- package/esm/src/guardrails/error.js +23 -18
- package/esm/src/guardrails/event-schemas.d.ts +46 -3
- package/esm/src/guardrails/event-schemas.js +12 -5
- package/esm/src/guardrails/events.d.ts +5 -1
- package/esm/src/guardrails/events.js +4 -1
- package/esm/src/guardrails/hints.d.ts +14 -0
- package/esm/src/guardrails/hints.js +57 -0
- package/esm/src/guardrails/hits.d.ts +7 -1
- package/esm/src/guardrails/hits.js +12 -1
- package/esm/src/guardrails/host-patterns.d.ts +85 -0
- package/esm/src/guardrails/host-patterns.js +173 -0
- package/esm/src/guardrails/injection-patterns.d.ts +6 -1
- package/esm/src/guardrails/injection-patterns.js +33 -1
- package/esm/src/guardrails/injection-reversed.d.ts +9 -0
- package/esm/src/guardrails/injection-reversed.js +49 -0
- package/esm/src/guardrails/injection.d.ts +17 -1
- package/esm/src/guardrails/injection.js +259 -36
- package/esm/src/guardrails/labels.d.ts +40 -0
- package/esm/src/guardrails/labels.js +874 -0
- package/esm/src/guardrails/live-outbound-gate.d.ts +9 -8
- package/esm/src/guardrails/live-outbound-gate.js +100 -107
- package/esm/src/guardrails/mod.d.ts +29 -21
- package/esm/src/guardrails/mod.js +18 -13
- package/esm/src/guardrails/network.d.ts +4 -0
- package/esm/src/guardrails/network.js +21 -19
- package/esm/src/guardrails/normalize.d.ts +15 -1
- package/esm/src/guardrails/normalize.js +34 -1
- package/esm/src/guardrails/policy.d.ts +2 -17
- package/esm/src/guardrails/policy.js +12 -41
- package/esm/src/guardrails/progressive-yield.d.ts +65 -24
- package/esm/src/guardrails/progressive-yield.js +191 -147
- package/esm/src/guardrails/prompt-echo.d.ts +4 -2
- package/esm/src/guardrails/prompt-echo.js +87 -6
- package/esm/src/guardrails/quota.d.ts +1 -0
- package/esm/src/guardrails/quota.js +1 -1
- package/esm/src/guardrails/rules.d.ts +20 -29
- package/esm/src/guardrails/rules.js +23 -30
- package/esm/src/guardrails/sanitize.d.ts +32 -15
- package/esm/src/guardrails/sanitize.js +100 -124
- package/esm/src/guardrails/sensitive-groups.d.ts +21 -0
- package/esm/src/guardrails/sensitive-groups.js +12 -0
- package/esm/src/guardrails/sensitive.d.ts +16 -23
- package/esm/src/guardrails/sensitive.js +168 -47
- package/esm/src/guardrails/serialize.d.ts +1 -0
- package/esm/src/guardrails/testing.d.ts +4 -2
- package/esm/src/guardrails/testing.js +4 -2
- package/esm/src/guardrails/theorem-error.d.ts +4 -1
- package/esm/src/guardrails/theorem-error.js +3 -2
- package/esm/src/guardrails/thought-guard.d.ts +34 -13
- package/esm/src/guardrails/thought-guard.js +264 -64
- package/esm/src/guardrails/tool-directives.d.ts +29 -10
- package/esm/src/guardrails/tool-directives.js +133 -47
- package/esm/src/guardrails/tool-leak.d.ts +26 -0
- package/esm/src/guardrails/tool-leak.js +45 -0
- package/esm/src/guardrails/tool-result.d.ts +45 -14
- package/esm/src/guardrails/tool-result.js +94 -70
- package/esm/src/guardrails/types.d.ts +79 -71
- package/esm/src/guardrails/types.js +11 -7
- package/esm/src/host/client-turn.d.ts +29 -2
- package/esm/src/host/client-turn.js +46 -4
- package/esm/src/host/mint-trace.d.ts +1 -0
- package/esm/src/host/mint-trace.js +3 -2
- package/esm/src/host/mod.d.ts +2 -2
- package/esm/src/host/mod.js +1 -1
- package/esm/src/host/readStreamingJsonStringField.js +2 -43
- package/esm/src/host/reply.d.ts +6 -0
- package/esm/src/host/reply.js +7 -1
- package/esm/src/interface/blocks.d.ts +3 -0
- package/esm/src/interface/blocks.js +84 -14
- package/esm/src/interface/composer-actions.d.ts +4 -0
- package/esm/src/interface/composer-actions.js +5 -3
- package/esm/src/interface/draft.d.ts +6 -0
- package/esm/src/interface/draft.js +22 -11
- package/esm/src/interface/from-profile.d.ts +13 -1
- package/esm/src/interface/from-profile.js +66 -31
- package/esm/src/interface/history.d.ts +9 -3
- package/esm/src/interface/history.js +33 -24
- package/esm/src/interface/inputs.d.ts +1 -0
- package/esm/src/interface/inputs.js +3 -0
- package/esm/src/interface/mod.d.ts +4 -2
- package/esm/src/interface/mod.js +3 -2
- package/esm/src/interface/models.d.ts +7 -0
- package/esm/src/interface/models.js +5 -0
- package/esm/src/interface/pending.d.ts +9 -0
- package/esm/src/interface/pending.js +9 -3
- package/esm/src/interface/profile-interface.js +54 -40
- package/esm/src/interface/session.d.ts +12 -5
- package/esm/src/interface/session.js +17 -10
- package/esm/src/interface/stop.d.ts +13 -0
- package/esm/src/interface/stop.js +28 -0
- package/esm/src/interface/tool-calls.d.ts +14 -2
- package/esm/src/interface/tool-calls.js +64 -10
- package/esm/src/interface/tool-invoke.d.ts +2 -0
- package/esm/src/interface/tool-invoke.js +3 -1
- package/esm/src/interface/tool-media.d.ts +2 -0
- package/esm/src/interface/tool-media.js +2 -1
- package/esm/src/interface/types.d.ts +105 -40
- package/esm/src/interface/types.js +1 -0
- package/esm/src/kernel/api-catalog.d.ts +85 -0
- package/esm/src/kernel/api-catalog.js +229 -0
- package/esm/src/kernel/auth/crypto.d.ts +7 -2
- package/esm/src/kernel/auth/crypto.js +12 -10
- package/esm/src/kernel/auth/oauth.d.ts +2 -1
- package/esm/src/kernel/auth/oauth.js +23 -22
- package/esm/src/kernel/auth/typed-secret.js +2 -2
- package/esm/src/kernel/auth/types.d.ts +13 -0
- package/esm/src/kernel/checkpoint.d.ts +43 -0
- package/esm/src/kernel/checkpoint.js +58 -0
- package/esm/src/kernel/default-scope.d.ts +43 -5
- package/esm/src/kernel/default-scope.js +54 -5
- package/esm/src/kernel/engine/call-trace.d.ts +19 -0
- package/esm/src/kernel/engine/call-trace.js +29 -0
- package/esm/src/kernel/engine/compaction.d.ts +6 -5
- package/esm/src/kernel/engine/compaction.js +12 -11
- package/esm/src/kernel/engine/decision.d.ts +10 -8
- package/esm/src/kernel/engine/decision.js +173 -146
- package/esm/src/kernel/engine/embedding.d.ts +8 -0
- package/esm/src/kernel/engine/embedding.js +118 -0
- package/esm/src/kernel/engine/live-inbound.d.ts +14 -4
- package/esm/src/kernel/engine/live-inbound.js +36 -11
- package/esm/src/kernel/engine/live-ingress.d.ts +6 -0
- package/esm/src/kernel/engine/live-ingress.js +6 -1
- package/esm/src/kernel/engine/repair.js +12 -12
- package/esm/src/kernel/engine/runner/gates.d.ts +2 -2
- package/esm/src/kernel/engine/runner/gates.js +287 -101
- package/esm/src/kernel/engine/runner/mod.d.ts +19 -5
- package/esm/src/kernel/engine/runner/mod.js +107 -56
- package/esm/src/kernel/engine/runner/nested.d.ts +32 -0
- package/esm/src/kernel/engine/runner/nested.js +134 -0
- package/esm/src/kernel/engine/runner/schema-validation.d.ts +24 -3
- package/esm/src/kernel/engine/runner/schema-validation.js +78 -4
- package/esm/src/kernel/engine/runner/stages.d.ts +1 -1
- package/esm/src/kernel/engine/runner/stages.js +1 -8
- package/esm/src/kernel/engine/runner/state.d.ts +33 -12
- package/esm/src/kernel/engine/runner/state.js +11 -1
- package/esm/src/kernel/engine/runner/step-order.d.ts +27 -0
- package/esm/src/kernel/engine/runner/step-order.js +165 -0
- package/esm/src/kernel/engine/runner/steps.d.ts +2 -2
- package/esm/src/kernel/engine/runner/steps.js +328 -169
- package/esm/src/kernel/engine/runner/stream.d.ts +42 -11
- package/esm/src/kernel/engine/runner/stream.js +197 -46
- package/esm/src/kernel/engine/runner/usage.d.ts +5 -5
- package/esm/src/kernel/engine/runner/usage.js +12 -14
- package/esm/src/kernel/engine/session/mod.d.ts +8 -6
- package/esm/src/kernel/engine/session/mod.js +360 -129
- package/esm/src/kernel/engine/session/session-trace.d.ts +10 -10
- package/esm/src/kernel/engine/session/session-trace.js +41 -30
- package/esm/src/kernel/engine/token-estimate.d.ts +10 -64
- package/esm/src/kernel/engine/token-estimate.js +14 -194
- package/esm/src/kernel/engine/tool-trace.d.ts +3 -3
- package/esm/src/kernel/engine/tool-trace.js +2 -1
- package/esm/src/kernel/engine/turn-trace.d.ts +8 -7
- package/esm/src/kernel/engine/turn-trace.js +28 -36
- package/esm/src/kernel/engine/usage.d.ts +6 -0
- package/esm/src/kernel/engine/usage.js +17 -0
- package/esm/src/kernel/interaction-parts.d.ts +3 -0
- package/esm/src/kernel/interaction-parts.js +18 -0
- package/esm/src/kernel/json.d.ts +10 -0
- package/esm/src/kernel/json.js +3 -0
- package/esm/src/kernel/mod.d.ts +38 -11
- package/esm/src/kernel/mod.js +22 -7
- package/esm/src/kernel/profile-graph.d.ts +11 -6
- package/esm/src/kernel/profile-graph.js +14 -7
- package/esm/src/kernel/profile-presence.d.ts +10 -1
- package/esm/src/kernel/profile-presence.js +90 -75
- package/esm/src/kernel/profile-scope.d.ts +7 -3
- package/esm/src/kernel/profile-scope.js +67 -55
- package/esm/src/kernel/protocols/binding.d.ts +65 -0
- package/esm/src/kernel/protocols/binding.js +125 -0
- package/esm/src/kernel/protocols/limits.d.ts +15 -0
- package/esm/src/kernel/protocols/limits.js +28 -0
- package/esm/src/kernel/protocols/mod.d.ts +5 -0
- package/esm/src/kernel/protocols/mod.js +5 -0
- package/esm/src/kernel/protocols/prices.d.ts +36 -0
- package/esm/src/kernel/protocols/prices.js +37 -0
- package/esm/src/kernel/protocols/protocol.d.ts +253 -0
- package/esm/src/kernel/protocols/protocol.js +253 -0
- package/esm/src/kernel/protocols/provider.d.ts +108 -0
- package/esm/src/kernel/protocols/provider.js +143 -0
- package/esm/src/kernel/protocols/runtime.d.ts +55 -0
- package/esm/src/kernel/protocols/runtime.js +534 -0
- package/esm/src/kernel/provider-budget.d.ts +32 -0
- package/esm/src/kernel/provider-budget.js +262 -0
- package/esm/src/kernel/provider-dispatch.d.ts +13 -0
- package/esm/src/kernel/provider-dispatch.js +36 -0
- package/esm/src/kernel/provider-live.d.ts +7 -0
- package/esm/src/kernel/provider-live.js +189 -0
- package/esm/src/kernel/provider-runtime.d.ts +57 -0
- package/esm/src/kernel/provider-runtime.js +524 -0
- package/esm/src/kernel/registry/attachments.d.ts +15 -4
- package/esm/src/kernel/registry/attachments.js +31 -22
- package/esm/src/kernel/registry/catalog.d.ts +6 -0
- package/esm/src/kernel/registry/catalog.js +9 -2
- package/esm/src/kernel/registry/embedding-rules.d.ts +28 -0
- package/esm/src/kernel/registry/embedding-rules.js +66 -0
- package/esm/src/kernel/registry/ingress.d.ts +6 -2
- package/esm/src/kernel/registry/ingress.js +55 -10
- package/esm/src/kernel/registry/kernel-registry.d.ts +3 -0
- package/esm/src/kernel/registry/kernel-registry.js +9 -2
- package/esm/src/kernel/registry/profile-outputs.js +4 -1
- package/esm/src/kernel/registry/profiles.d.ts +38 -14
- package/esm/src/kernel/registry/profiles.js +280 -205
- package/esm/src/kernel/registry/provider-request.d.ts +3 -3
- package/esm/src/kernel/registry/provider-request.js +5 -13
- package/esm/src/kernel/registry/resolve.d.ts +4 -1
- package/esm/src/kernel/registry/resolve.js +59 -58
- package/esm/src/kernel/registry/schemas.d.ts +3 -0
- package/esm/src/kernel/registry/schemas.js +3 -1
- package/esm/src/kernel/registry/slot-fill.d.ts +7 -0
- package/esm/src/kernel/registry/slot-fill.js +22 -0
- package/esm/src/kernel/registry/system-prompt.js +7 -8
- package/esm/src/kernel/registry/vault.d.ts +14 -13
- package/esm/src/kernel/registry/vault.js +1 -14
- package/esm/src/kernel/schema.d.ts +100 -46
- package/esm/src/kernel/schema.js +499 -257
- package/esm/src/kernel/scope.d.ts +12 -5
- package/esm/src/kernel/scope.js +23 -3
- package/esm/src/kernel/stages.d.ts +38 -3
- package/esm/src/kernel/stages.js +82 -39
- package/esm/src/kernel/stop.d.ts +29 -6
- package/esm/src/kernel/stop.js +16 -4
- package/esm/src/kernel/system-parts.js +6 -6
- package/esm/src/kernel/tools/activity-label.d.ts +12 -6
- package/esm/src/kernel/tools/activity-label.js +258 -32
- package/esm/src/kernel/tools/agent.d.ts +66 -0
- package/esm/src/kernel/tools/agent.js +212 -0
- package/esm/src/kernel/tools/coordinate.d.ts +4 -0
- package/esm/src/kernel/tools/coordinate.js +165 -0
- package/esm/src/kernel/tools/events.d.ts +21 -6
- package/esm/src/kernel/tools/events.js +53 -18
- package/esm/src/kernel/tools/execute.d.ts +47 -11
- package/esm/src/kernel/tools/execute.js +508 -136
- package/esm/src/kernel/tools/gate-answer.d.ts +12 -2
- package/esm/src/kernel/tools/gate-answer.js +17 -6
- package/esm/src/kernel/tools/handler-events.d.ts +45 -0
- package/esm/src/kernel/tools/handler-events.js +106 -0
- package/esm/src/kernel/tools/harness.d.ts +1 -0
- package/esm/src/kernel/tools/harness.js +2 -1
- package/esm/src/kernel/tools/http-limit.d.ts +27 -0
- package/esm/src/kernel/tools/http-limit.js +85 -0
- package/esm/src/kernel/tools/invoke.d.ts +27 -5
- package/esm/src/kernel/tools/invoke.js +223 -70
- package/esm/src/kernel/tools/mcp-sessions.d.ts +4 -1
- package/esm/src/kernel/tools/mcp-sessions.js +13 -8
- package/esm/src/kernel/tools/mod.d.ts +4 -3
- package/esm/src/kernel/tools/mod.js +3 -2
- package/esm/src/kernel/tools/model-text.d.ts +10 -5
- package/esm/src/kernel/tools/model-text.js +18 -12
- package/esm/src/kernel/tools/operation.d.ts +76 -0
- package/esm/src/kernel/tools/operation.js +100 -0
- package/esm/src/kernel/tools/page-answer.d.ts +8 -0
- package/esm/src/kernel/tools/page-answer.js +19 -0
- package/esm/src/kernel/tools/permission.d.ts +11 -2
- package/esm/src/kernel/tools/permission.js +12 -12
- package/esm/src/kernel/tools/project.d.ts +4 -1
- package/esm/src/kernel/tools/project.js +32 -2
- package/esm/src/kernel/tools/registry.d.ts +9 -2
- package/esm/src/kernel/tools/registry.js +69 -10
- package/esm/src/kernel/tools/remote.d.ts +40 -6
- package/esm/src/kernel/tools/remote.js +219 -92
- package/esm/src/kernel/tools/resolve.d.ts +3 -0
- package/esm/src/kernel/tools/resolve.js +12 -4
- package/esm/src/kernel/tools/run.d.ts +28 -0
- package/esm/src/kernel/tools/run.js +86 -0
- package/esm/src/kernel/tools/schema.d.ts +3 -3
- package/esm/src/kernel/tools/schema.js +21 -100
- package/esm/src/kernel/tools/signed-in-fetch.d.ts +2 -1
- package/esm/src/kernel/tools/signed-in-fetch.js +3 -3
- package/esm/src/kernel/tools/stage-run.d.ts +27 -4
- package/esm/src/kernel/tools/stage-run.js +75 -17
- package/esm/src/kernel/tools/types.d.ts +235 -25
- package/esm/src/kernel/tools/unchecked-output.d.ts +14 -0
- package/esm/src/kernel/tools/unchecked-output.js +18 -0
- package/esm/src/kernel/turn-events.d.ts +208 -31
- package/esm/src/kernel/turn-events.js +127 -9
- package/esm/src/kernel/types.d.ts +302 -161
- package/esm/src/kernel/util/base64.d.ts +2 -0
- package/esm/src/kernel/util/base64.js +2 -0
- package/esm/src/kernel/util/partial-json.d.ts +23 -0
- package/esm/src/kernel/util/partial-json.js +128 -0
- package/esm/src/kernel/util/record.d.ts +1 -0
- package/esm/src/kernel/util/record.js +1 -0
- package/esm/src/observability/destinations.d.ts +5 -0
- package/esm/src/observability/destinations.js +7 -2
- package/esm/src/observability/jsonl.d.ts +2 -2
- package/esm/src/observability/jsonl.js +15 -22
- package/esm/src/observability/mod.d.ts +3 -3
- package/esm/src/observability/mod.js +2 -2
- package/esm/src/observability/openinference.d.ts +1 -1
- package/esm/src/observability/openinference.js +3 -3
- package/esm/src/observability/otlp.d.ts +3 -0
- package/esm/src/observability/otlp.js +3 -3
- package/esm/src/observability/phoenix.d.ts +1 -0
- package/esm/src/observability/policy.d.ts +3 -0
- package/esm/src/observability/policy.js +5 -1
- package/esm/src/observability/resolve-policy.js +11 -5
- package/esm/src/observability/spans.d.ts +8 -2
- package/esm/src/observability/spans.js +21 -5
- package/esm/src/observability/trace-catalog.d.ts +19 -2
- package/esm/src/observability/trace-catalog.js +128 -87
- package/esm/src/observability/trace-record.js +22 -17
- package/esm/src/observability/trace-schema.d.ts +3 -0
- package/esm/src/observability/trace-schema.js +1 -1
- package/esm/src/observability/trace-sink.d.ts +1 -0
- package/esm/src/observability/trace-sink.js +1 -1
- package/esm/src/observability/trace-span.d.ts +7 -1
- package/esm/src/observability/trace-span.js +3 -1
- package/esm/src/observability/trace.d.ts +2 -0
- package/esm/src/observability/trace.js +4 -2
- package/esm/src/observability/types.d.ts +35 -11
- package/esm/src/observability/types.js +1 -1
- package/esm/src/presets/google/speech-voices.d.ts +1 -0
- package/esm/src/presets/google-limits.d.ts +1 -0
- package/esm/src/presets/google.d.ts +27 -12
- package/esm/src/presets/google.js +34 -25
- package/esm/src/presets/local.d.ts +26 -0
- package/esm/src/presets/local.js +30 -0
- package/esm/src/presets/mod.d.ts +5 -4
- package/esm/src/presets/mod.js +4 -4
- package/esm/src/presets/openrouter.d.ts +14 -1
- package/esm/src/presets/openrouter.js +19 -1
- package/esm/src/providers/embedding-limits.d.ts +7 -0
- package/esm/src/providers/embedding-limits.js +12 -0
- package/esm/src/providers/gemini/embedding-protocol.d.ts +8 -0
- package/esm/src/providers/gemini/embedding-protocol.js +125 -0
- package/esm/src/providers/gemini/interactions-protocol.d.ts +8 -0
- package/esm/src/providers/gemini/interactions-protocol.js +105 -0
- package/esm/src/providers/gemini/live-protocol.d.ts +3 -0
- package/esm/src/providers/gemini/live-protocol.js +191 -0
- package/esm/src/providers/gemini/prices.d.ts +3 -0
- package/esm/src/providers/gemini/prices.js +63 -0
- package/esm/src/providers/gemini/provider.d.ts +7 -0
- package/esm/src/providers/gemini/provider.js +39 -0
- package/esm/src/providers/google/builtins.d.ts +14 -0
- package/esm/src/providers/google/builtins.js +57 -0
- package/esm/src/providers/google/grounding.d.ts +4 -4
- package/esm/src/providers/google/interactions/framing.d.ts +20 -8
- package/esm/src/providers/google/interactions/framing.js +85 -44
- package/esm/src/providers/google/interactions/steps.d.ts +5 -5
- package/esm/src/providers/google/interactions/steps.js +4 -4
- package/esm/src/providers/google/interactions/stream.d.ts +10 -11
- package/esm/src/providers/google/interactions/stream.js +33 -100
- package/esm/src/providers/google/live/framing.d.ts +15 -5
- package/esm/src/providers/google/live/framing.js +25 -25
- package/esm/src/providers/google/live/stream.d.ts +6 -44
- package/esm/src/providers/google/live/stream.js +3 -209
- package/esm/src/providers/google/urls.d.ts +1 -3
- package/esm/src/providers/google/urls.js +1 -3
- package/esm/src/providers/google/usage.js +2 -2
- package/esm/src/providers/live.d.ts +6 -0
- package/esm/src/providers/live.js +6 -0
- package/esm/src/providers/local/embedding-protocol.d.ts +7 -0
- package/esm/src/providers/local/embedding-protocol.js +60 -0
- package/esm/src/providers/local/provider.d.ts +7 -0
- package/esm/src/providers/local/provider.js +28 -0
- package/esm/src/providers/mod.d.ts +28 -7
- package/esm/src/providers/mod.js +19 -3
- package/esm/src/providers/open-ai/protocol.d.ts +3 -0
- package/esm/src/providers/open-ai/protocol.js +189 -0
- package/esm/src/providers/openrouter/embedding-protocol.d.ts +6 -0
- package/esm/src/providers/openrouter/embedding-protocol.js +86 -0
- package/esm/src/providers/openrouter/image.d.ts +0 -9
- package/esm/src/providers/openrouter/image.js +0 -153
- package/esm/src/providers/openrouter/images-protocol.d.ts +3 -0
- package/esm/src/providers/openrouter/images-protocol.js +82 -0
- package/esm/src/providers/openrouter/openai/compat.d.ts +2 -2
- package/esm/src/providers/openrouter/openai/compat.js +6 -6
- package/esm/src/providers/openrouter/openai/image-payload.d.ts +2 -2
- package/esm/src/providers/openrouter/openai/reasoning-state.d.ts +2 -0
- package/esm/src/providers/openrouter/openai/reasoning-state.js +31 -0
- package/esm/src/providers/openrouter/protocol.d.ts +8 -0
- package/esm/src/providers/openrouter/protocol.js +171 -0
- package/esm/src/providers/openrouter/provider.d.ts +10 -0
- package/esm/src/providers/openrouter/provider.js +50 -0
- package/esm/src/providers/shared/carried-tool-files.d.ts +7 -0
- package/esm/src/providers/shared/carried-tool-files.js +43 -0
- package/esm/src/providers/shared/pcm.js +2 -2
- package/esm/src/providers/shared/protocol-events.d.ts +8 -0
- package/esm/src/providers/shared/protocol-events.js +20 -0
- package/esm/src/providers/shared/response-identity.d.ts +2 -2
- package/esm/src/providers/shared/retry.d.ts +17 -0
- package/esm/src/providers/shared/retry.js +90 -0
- package/esm/src/providers/shared/sse.d.ts +0 -4
- package/esm/src/providers/shared/sse.js +50 -36
- package/esm/src/providers/shared/tool-args.d.ts +6 -7
- package/esm/src/providers/shared/tool-args.js +10 -6
- package/esm/src/providers/shared/tool-draft.d.ts +16 -0
- package/esm/src/providers/shared/tool-draft.js +14 -0
- package/esm/src/providers/shared/upstream-tap.d.ts +2 -2
- package/esm/src/providers/shared/upstream-tape.js +1 -1
- package/esm/src/providers/system-one/protocol.d.ts +8 -0
- package/esm/src/providers/system-one/protocol.js +93 -0
- package/esm/src/providers/types.d.ts +48 -16
- package/esm/src/providers/types.js +2 -1
- package/esm/src/providers/typesafe/provider.d.ts +7 -0
- package/esm/src/providers/typesafe/provider.js +24 -0
- package/esm/src/surface/formats.d.ts +19 -1
- package/esm/src/surface/formats.js +68 -29
- package/esm/src/surface/mod.d.ts +4 -2
- package/esm/src/surface/mod.js +4 -2
- package/esm/src/surface/runtime.d.ts +4 -0
- package/esm/src/surface/runtime.js +2 -0
- package/esm/src/surface/tools.d.ts +2 -8
- package/esm/src/surface/tools.js +4 -22
- package/esm/src/surface/types.d.ts +6 -0
- package/package.json +5 -13
- package/esm/src/cli/commands/egress-compile.d.ts +0 -17
- package/esm/src/cli/commands/egress-compile.js +0 -25
- package/esm/src/guardrails/egress-policy.d.ts +0 -27
- package/esm/src/guardrails/egress-policy.js +0 -76
- package/esm/src/guardrails/egress-rules.d.ts +0 -54
- package/esm/src/guardrails/egress-rules.js +0 -49
- package/esm/src/guardrails/lexicon.d.ts +0 -30
- package/esm/src/guardrails/lexicon.js +0 -478
- package/esm/src/kernel/engine/media-probe/audio.d.ts +0 -7
- package/esm/src/kernel/engine/media-probe/audio.js +0 -342
- package/esm/src/kernel/engine/media-probe/bytes.d.ts +0 -6
- package/esm/src/kernel/engine/media-probe/bytes.js +0 -26
- package/esm/src/kernel/engine/media-probe/image.d.ts +0 -5
- package/esm/src/kernel/engine/media-probe/image.js +0 -171
- package/esm/src/kernel/engine/media-probe/iso-bmff.d.ts +0 -19
- package/esm/src/kernel/engine/media-probe/iso-bmff.js +0 -48
- package/esm/src/kernel/engine/media-probe/matroska.d.ts +0 -35
- package/esm/src/kernel/engine/media-probe/matroska.js +0 -226
- package/esm/src/kernel/engine/media-probe/mp4.d.ts +0 -22
- package/esm/src/kernel/engine/media-probe/mp4.js +0 -279
- package/esm/src/kernel/engine/media-probe/opus.d.ts +0 -4
- package/esm/src/kernel/engine/media-probe/opus.js +0 -23
- package/esm/src/kernel/engine/media-probe/pdf.d.ts +0 -5
- package/esm/src/kernel/engine/media-probe/pdf.js +0 -117
- package/esm/src/kernel/engine/media-probe/video.d.ts +0 -15
- package/esm/src/kernel/engine/media-probe/video.js +0 -49
- package/esm/src/presets/typesafe.d.ts +0 -2
- package/esm/src/presets/typesafe.js +0 -2
- package/esm/src/providers/create-provider.d.ts +0 -21
- package/esm/src/providers/create-provider.js +0 -90
- package/esm/src/providers/decision/usage.d.ts +0 -3
- package/esm/src/providers/decision/usage.js +0 -25
- package/esm/src/providers/google/interactions/mod.d.ts +0 -2
- package/esm/src/providers/google/interactions/mod.js +0 -2
- package/esm/src/providers/google/keys.d.ts +0 -20
- package/esm/src/providers/google/keys.js +0 -87
- package/esm/src/providers/google/live/mod.d.ts +0 -7
- package/esm/src/providers/google/live/mod.js +0 -7
- package/esm/src/providers/google/live/openapi-schema.d.ts +0 -1
- package/esm/src/providers/google/live/openapi-schema.js +0 -42
- package/esm/src/providers/google/live/session.d.ts +0 -14
- package/esm/src/providers/google/live/session.js +0 -150
- package/esm/src/providers/local/local.d.ts +0 -12
- package/esm/src/providers/local/local.js +0 -186
- package/esm/src/providers/local/mod.d.ts +0 -8
- package/esm/src/providers/local/mod.js +0 -8
- package/esm/src/providers/openrouter/cache-control.d.ts +0 -5
- package/esm/src/providers/openrouter/cache-control.js +0 -4
- package/esm/src/providers/openrouter/chat.d.ts +0 -64
- package/esm/src/providers/openrouter/chat.js +0 -490
- package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +0 -10
- package/esm/src/providers/openrouter/openai/sdk-messages.js +0 -99
- package/esm/src/providers/openrouter/resolve-api-key.d.ts +0 -3
- package/esm/src/providers/openrouter/resolve-api-key.js +0 -8
- package/esm/src/providers/openrouter/speech.d.ts +0 -18
- package/esm/src/providers/openrouter/speech.js +0 -109
- package/esm/src/providers/probe.d.ts +0 -5
- package/esm/src/providers/probe.js +0 -15
- package/esm/src/providers/shared/builtin-wire.d.ts +0 -4
- package/esm/src/providers/shared/builtin-wire.js +0 -9
- package/esm/src/providers/shared/vault.d.ts +0 -13
- package/esm/src/providers/shared/vault.js +0 -41
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
import { ascii, view } from './bytes.js';
|
|
2
|
-
import { OPUS_RATE, opusPacketSamples } from './opus.js';
|
|
3
|
-
const EBML_HEADER = 0x1a45dfa3;
|
|
4
|
-
const MKV_SEGMENT = 0x18538067;
|
|
5
|
-
const MKV_INFO = 0x1549a966;
|
|
6
|
-
const MKV_TIMECODE_SCALE = 0x2ad7b1;
|
|
7
|
-
const MKV_DURATION = 0x4489;
|
|
8
|
-
const MKV_TRACKS = 0x1654ae6b;
|
|
9
|
-
const MKV_TRACK_ENTRY = 0xae;
|
|
10
|
-
const MKV_TRACK_NUMBER = 0xd7;
|
|
11
|
-
const MKV_TRACK_TYPE = 0x83;
|
|
12
|
-
const MKV_CODEC_ID = 0x86;
|
|
13
|
-
const MKV_CODEC_DELAY = 0x56aa;
|
|
14
|
-
const MKV_DEFAULT_DURATION = 0x23e383;
|
|
15
|
-
const MKV_VIDEO = 0xe0;
|
|
16
|
-
const MKV_PIXEL_WIDTH = 0xb0;
|
|
17
|
-
const MKV_PIXEL_HEIGHT = 0xba;
|
|
18
|
-
const MKV_CLUSTER = 0x1f43b675;
|
|
19
|
-
const MKV_CLUSTER_TIMECODE = 0xe7;
|
|
20
|
-
const MKV_SIMPLE_BLOCK = 0xa3;
|
|
21
|
-
const MKV_BLOCK_GROUP = 0xa0;
|
|
22
|
-
const MKV_BLOCK = 0xa1;
|
|
23
|
-
const MKV_DISCARD_PADDING = 0x75a2;
|
|
24
|
-
const MKV_DEFAULT_TIMECODE_SCALE = 1_000_000;
|
|
25
|
-
const MKV_LACING = 0x06;
|
|
26
|
-
/** Track number (vint), relative timestamp (int16), and flags open every block. */
|
|
27
|
-
const MKV_BLOCK_FIXED = 3;
|
|
28
|
-
const NS_PER_SECOND = 1e9;
|
|
29
|
-
/**
|
|
30
|
-
* Masters are walked into whatever their size says, since live recordings (MediaRecorder,
|
|
31
|
-
* streaming muxers) leave Segment and Cluster sizes unknown; every other element is skipped by size.
|
|
32
|
-
*/
|
|
33
|
-
const MKV_DESCEND = new Set([
|
|
34
|
-
MKV_SEGMENT,
|
|
35
|
-
MKV_INFO,
|
|
36
|
-
MKV_TRACKS,
|
|
37
|
-
MKV_TRACK_ENTRY,
|
|
38
|
-
MKV_VIDEO,
|
|
39
|
-
MKV_CLUSTER,
|
|
40
|
-
]);
|
|
41
|
-
/** Matroska `TrackType` values. */
|
|
42
|
-
export const MKV_VIDEO_TRACK = 1;
|
|
43
|
-
export const MKV_AUDIO_TRACK = 2;
|
|
44
|
-
/** Variable-length integer: `value` with the length marker removed, `unknown` when all ones. */
|
|
45
|
-
function vint(bytes, at, keepMarker) {
|
|
46
|
-
const first = bytes[at];
|
|
47
|
-
if (first === undefined || first === 0)
|
|
48
|
-
return undefined;
|
|
49
|
-
const length = Math.clz32(first) - 23;
|
|
50
|
-
if (at + length > bytes.length)
|
|
51
|
-
return undefined;
|
|
52
|
-
let value = keepMarker ? first : first & (0xff >> length);
|
|
53
|
-
let allOnes = value === 0xff >> length;
|
|
54
|
-
for (let i = 1; i < length; i++) {
|
|
55
|
-
value = value * 256 + bytes[at + i];
|
|
56
|
-
allOnes &&= bytes[at + i] === 0xff;
|
|
57
|
-
}
|
|
58
|
-
return { value, length, unknown: !keepMarker && allOnes };
|
|
59
|
-
}
|
|
60
|
-
function ebmlElement(bytes, at) {
|
|
61
|
-
const id = vint(bytes, at, true);
|
|
62
|
-
if (!id)
|
|
63
|
-
return undefined;
|
|
64
|
-
const size = vint(bytes, at + id.length, false);
|
|
65
|
-
if (!size)
|
|
66
|
-
return undefined;
|
|
67
|
-
return {
|
|
68
|
-
id: id.value,
|
|
69
|
-
body: at + id.length + size.length,
|
|
70
|
-
size: size.value,
|
|
71
|
-
unknown: size.unknown,
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
function mkvUint(bytes, at, size) {
|
|
75
|
-
let n = 0;
|
|
76
|
-
for (let i = 0; i < size; i++)
|
|
77
|
-
n = n * 256 + bytes[at + i];
|
|
78
|
-
return n;
|
|
79
|
-
}
|
|
80
|
-
function mkvInt(bytes, at, size) {
|
|
81
|
-
const n = mkvUint(bytes, at, size);
|
|
82
|
-
return size > 0 && bytes[at] & 0x80 ? n - 2 ** (8 * size) : n;
|
|
83
|
-
}
|
|
84
|
-
/** Nanoseconds as a whole count of 48 kHz Opus samples. */
|
|
85
|
-
export function opusSamplesFromNs(ns) {
|
|
86
|
-
return Math.round((ns * OPUS_RATE) / NS_PER_SECOND);
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* `undefined` without an EBML header. A truncated or unknown-sized leaf element, or an unreadable
|
|
90
|
-
* block header, stops the walk with `complete: false`.
|
|
91
|
-
*/
|
|
92
|
-
export function matroska(bytes) {
|
|
93
|
-
const head = vint(bytes, 0, true);
|
|
94
|
-
if (head?.value !== EBML_HEADER)
|
|
95
|
-
return undefined;
|
|
96
|
-
const walk = { tracks: [], scale: MKV_DEFAULT_TIMECODE_SCALE, clusterTimecode: 0 };
|
|
97
|
-
let at = 0;
|
|
98
|
-
while (at < bytes.length) {
|
|
99
|
-
const el = ebmlElement(bytes, at);
|
|
100
|
-
if (!el)
|
|
101
|
-
return undefined;
|
|
102
|
-
if (MKV_DESCEND.has(el.id)) {
|
|
103
|
-
if (el.id === MKV_TRACK_ENTRY)
|
|
104
|
-
walk.tracks.push({ codecDelayNs: 0, opusSamples: 0 });
|
|
105
|
-
at = el.body;
|
|
106
|
-
continue;
|
|
107
|
-
}
|
|
108
|
-
const incomplete = el.unknown || el.body + el.size > bytes.length;
|
|
109
|
-
if (incomplete || !readLeaf(bytes, el, walk)) {
|
|
110
|
-
// Past here nothing can be walked; only a stated duration still holds.
|
|
111
|
-
return {
|
|
112
|
-
tracks: walk.tracks,
|
|
113
|
-
durationSeconds: seconds(walk.duration, walk.scale),
|
|
114
|
-
complete: false,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
at = el.body + el.size;
|
|
118
|
-
}
|
|
119
|
-
return {
|
|
120
|
-
tracks: walk.tracks,
|
|
121
|
-
durationSeconds: seconds(walk.duration, walk.scale),
|
|
122
|
-
complete: true,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
/** Record one leaf element; `false` when a block in it cannot be read. */
|
|
126
|
-
function readLeaf(bytes, el, walk) {
|
|
127
|
-
const track = walk.tracks.at(-1);
|
|
128
|
-
const v = view(bytes);
|
|
129
|
-
switch (el.id) {
|
|
130
|
-
case MKV_TIMECODE_SCALE:
|
|
131
|
-
walk.scale = mkvUint(bytes, el.body, el.size);
|
|
132
|
-
break;
|
|
133
|
-
case MKV_DURATION:
|
|
134
|
-
walk.duration =
|
|
135
|
-
el.size === 4 ? v.getFloat32(el.body) : el.size === 8 ? v.getFloat64(el.body) : undefined;
|
|
136
|
-
break;
|
|
137
|
-
case MKV_TRACK_NUMBER:
|
|
138
|
-
if (track)
|
|
139
|
-
track.number = mkvUint(bytes, el.body, el.size);
|
|
140
|
-
break;
|
|
141
|
-
case MKV_TRACK_TYPE:
|
|
142
|
-
if (track)
|
|
143
|
-
track.type = mkvUint(bytes, el.body, el.size);
|
|
144
|
-
break;
|
|
145
|
-
case MKV_CODEC_ID:
|
|
146
|
-
if (track)
|
|
147
|
-
track.codec = ascii(bytes, el.body, el.size).replace(/\0+$/, '');
|
|
148
|
-
break;
|
|
149
|
-
case MKV_CODEC_DELAY:
|
|
150
|
-
if (track)
|
|
151
|
-
track.codecDelayNs = mkvUint(bytes, el.body, el.size);
|
|
152
|
-
break;
|
|
153
|
-
case MKV_DEFAULT_DURATION:
|
|
154
|
-
if (track)
|
|
155
|
-
track.defaultDurationNs = mkvUint(bytes, el.body, el.size);
|
|
156
|
-
break;
|
|
157
|
-
case MKV_PIXEL_WIDTH:
|
|
158
|
-
if (track)
|
|
159
|
-
track.pixelWidth = mkvUint(bytes, el.body, el.size);
|
|
160
|
-
break;
|
|
161
|
-
case MKV_PIXEL_HEIGHT:
|
|
162
|
-
if (track)
|
|
163
|
-
track.pixelHeight = mkvUint(bytes, el.body, el.size);
|
|
164
|
-
break;
|
|
165
|
-
case MKV_CLUSTER_TIMECODE:
|
|
166
|
-
walk.clusterTimecode = mkvUint(bytes, el.body, el.size);
|
|
167
|
-
break;
|
|
168
|
-
case MKV_SIMPLE_BLOCK:
|
|
169
|
-
return addBlock(bytes, el.body, el.body + el.size, walk, 0);
|
|
170
|
-
case MKV_BLOCK_GROUP:
|
|
171
|
-
return addBlockGroup(bytes, el, walk);
|
|
172
|
-
}
|
|
173
|
-
return true;
|
|
174
|
-
}
|
|
175
|
-
function seconds(duration, scale) {
|
|
176
|
-
return duration === undefined ? undefined : (duration * scale) / NS_PER_SECOND;
|
|
177
|
-
}
|
|
178
|
-
/** One `BlockGroup`: its `Block`, less any `DiscardPadding` declared beside it. */
|
|
179
|
-
function addBlockGroup(bytes, group, walk) {
|
|
180
|
-
const end = group.body + group.size;
|
|
181
|
-
let block;
|
|
182
|
-
let discardNs = 0;
|
|
183
|
-
for (let at = group.body; at < end;) {
|
|
184
|
-
const el = ebmlElement(bytes, at);
|
|
185
|
-
if (!el || el.unknown || el.body + el.size > end)
|
|
186
|
-
return false;
|
|
187
|
-
if (el.id === MKV_BLOCK)
|
|
188
|
-
block = el;
|
|
189
|
-
if (el.id === MKV_DISCARD_PADDING)
|
|
190
|
-
discardNs = mkvInt(bytes, el.body, el.size);
|
|
191
|
-
at = el.body + el.size;
|
|
192
|
-
}
|
|
193
|
-
return (block !== undefined && addBlock(bytes, block.body, block.body + block.size, walk, discardNs));
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Credit one block to its track: its timestamp, and — for an Opus track — its
|
|
197
|
-
* decoded samples. `false` when the block header itself cannot be read.
|
|
198
|
-
*/
|
|
199
|
-
function addBlock(bytes, at, end, walk, discardNs) {
|
|
200
|
-
const trackNumber = vint(bytes, at, false);
|
|
201
|
-
if (!trackNumber)
|
|
202
|
-
return false;
|
|
203
|
-
const header = at + trackNumber.length;
|
|
204
|
-
if (header + MKV_BLOCK_FIXED > end)
|
|
205
|
-
return false;
|
|
206
|
-
const track = walk.tracks.find((t) => t.number === trackNumber.value);
|
|
207
|
-
if (!track)
|
|
208
|
-
return true;
|
|
209
|
-
const relative = view(bytes).getInt16(header);
|
|
210
|
-
const ns = (walk.clusterTimecode + relative) * walk.scale;
|
|
211
|
-
if (track.lastNs === undefined || ns > track.lastNs) {
|
|
212
|
-
track.previousNs = track.lastNs;
|
|
213
|
-
track.lastNs = ns;
|
|
214
|
-
}
|
|
215
|
-
else if (ns < track.lastNs && (track.previousNs === undefined || ns > track.previousNs)) {
|
|
216
|
-
track.previousNs = ns;
|
|
217
|
-
}
|
|
218
|
-
if (track.opusSamples === undefined)
|
|
219
|
-
return true;
|
|
220
|
-
const samples = track.codec === 'A_OPUS' && !(bytes[header + 2] & MKV_LACING)
|
|
221
|
-
? opusPacketSamples(bytes, header + MKV_BLOCK_FIXED, end)
|
|
222
|
-
: undefined;
|
|
223
|
-
track.opusSamples =
|
|
224
|
-
samples === undefined ? undefined : track.opusSamples + samples - opusSamplesFromNs(discardNs);
|
|
225
|
-
return true;
|
|
226
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export declare const MP4_SOUND = "soun";
|
|
2
|
-
export declare const MP4_VIDEO = "vide";
|
|
3
|
-
export interface Mp4Track {
|
|
4
|
-
/** `hdlr` handler type — `soun`, `vide`, … */
|
|
5
|
-
handler: string;
|
|
6
|
-
/**
|
|
7
|
-
* Presented length: the `tkhd` duration (edit-list aware), else the sum of
|
|
8
|
-
* the track's sample durations. `undefined` when neither can be read.
|
|
9
|
-
*/
|
|
10
|
-
seconds?: number;
|
|
11
|
-
/**
|
|
12
|
-
* From the edit list's leading skip (encoder priming, reorder delay) to the end of the sample the
|
|
13
|
-
* edit ends in, which a decoder keeps whole. `undefined` when the samples cannot be summed, or the
|
|
14
|
-
* edit list holds more than one non-empty edit or ends before the last sample.
|
|
15
|
-
*/
|
|
16
|
-
decodedSeconds?: number;
|
|
17
|
-
/** Coded frame size from the first visual sample entry (video tracks). */
|
|
18
|
-
width?: number;
|
|
19
|
-
height?: number;
|
|
20
|
-
}
|
|
21
|
-
/** `undefined` when the bytes do not open with `ftyp` and hold a `moov`. */
|
|
22
|
-
export declare function mp4Tracks(bytes: Uint8Array): Mp4Track[] | undefined;
|
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
import { ascii, uint64, view } from './bytes.js';
|
|
2
|
-
import { boxes, FULL_BOX_HEADER } from './iso-bmff.js';
|
|
3
|
-
const TIMED_V0_SCALE = 12;
|
|
4
|
-
const TIMED_V1_SCALE = 20;
|
|
5
|
-
const TKHD_V0_TRACK_ID = 12;
|
|
6
|
-
const TKHD_V1_TRACK_ID = 20;
|
|
7
|
-
const TKHD_V0_DURATION = 20;
|
|
8
|
-
const TKHD_V1_DURATION = 28;
|
|
9
|
-
const STTS_ENTRIES = FULL_BOX_HEADER + 4;
|
|
10
|
-
const STTS_ENTRY = 8;
|
|
11
|
-
const HDLR_TYPE = FULL_BOX_HEADER + 4;
|
|
12
|
-
/** Visual sample entry: 8-byte box header, 6 reserved, data reference, 16 pre-defined/reserved. */
|
|
13
|
-
const VISUAL_ENTRY_WIDTH = 8 + 6 + 2 + 16;
|
|
14
|
-
const STSD_ENTRIES = FULL_BOX_HEADER + 4;
|
|
15
|
-
const TFHD_DEFAULT_DURATION = 0x08;
|
|
16
|
-
const TFHD_OPTIONAL = [
|
|
17
|
-
[0x01, 8],
|
|
18
|
-
[0x02, 4],
|
|
19
|
-
];
|
|
20
|
-
const TRUN_DATA_OFFSET = 0x01;
|
|
21
|
-
const TRUN_FIRST_FLAGS = 0x04;
|
|
22
|
-
const TRUN_DURATION = 0x100;
|
|
23
|
-
const TRUN_FIELDS = [0x100, 0x200, 0x400, 0x800];
|
|
24
|
-
const U32_UNKNOWN = 0xffffffff;
|
|
25
|
-
/** `elst` media time of an empty edit — a gap that plays no samples. */
|
|
26
|
-
const EMPTY_EDIT = -1;
|
|
27
|
-
const ELST_ENTRIES = FULL_BOX_HEADER + 4;
|
|
28
|
-
const ELST_V0_ENTRY = 12;
|
|
29
|
-
const ELST_V1_ENTRY = 20;
|
|
30
|
-
export const MP4_SOUND = 'soun';
|
|
31
|
-
export const MP4_VIDEO = 'vide';
|
|
32
|
-
const MPEG4_AUDIO = 'mp4a';
|
|
33
|
-
/** Timescale and duration from an `mvhd` or `mdhd` payload. */
|
|
34
|
-
function timedHeader(bytes, box) {
|
|
35
|
-
const v = view(bytes);
|
|
36
|
-
const version = bytes[box.start];
|
|
37
|
-
const scaleAt = box.start + (version === 1 ? TIMED_V1_SCALE : TIMED_V0_SCALE);
|
|
38
|
-
if (scaleAt + (version === 1 ? 12 : 8) > box.end)
|
|
39
|
-
return undefined;
|
|
40
|
-
const scale = v.getUint32(scaleAt);
|
|
41
|
-
const duration = version === 1 ? uint64(v, scaleAt + 4) : knownU32(v.getUint32(scaleAt + 4));
|
|
42
|
-
return scale > 0 ? { scale, duration } : undefined;
|
|
43
|
-
}
|
|
44
|
-
function knownU32(n) {
|
|
45
|
-
return n === U32_UNKNOWN ? undefined : n;
|
|
46
|
-
}
|
|
47
|
-
function childList(bytes, box) {
|
|
48
|
-
return boxes(bytes, box.start, box.end).list;
|
|
49
|
-
}
|
|
50
|
-
function descend(bytes, box, path) {
|
|
51
|
-
let at = box;
|
|
52
|
-
for (const type of path) {
|
|
53
|
-
at = at ? childList(bytes, at).find((b) => b.type === type) : undefined;
|
|
54
|
-
}
|
|
55
|
-
return at;
|
|
56
|
-
}
|
|
57
|
-
/** Track id and presented duration (movie timescale) from `tkhd`. */
|
|
58
|
-
function trackHeader(bytes, tkhd) {
|
|
59
|
-
const v = view(bytes);
|
|
60
|
-
const wide = bytes[tkhd.start] === 1;
|
|
61
|
-
const idAt = tkhd.start + (wide ? TKHD_V1_TRACK_ID : TKHD_V0_TRACK_ID);
|
|
62
|
-
const durationAt = tkhd.start + (wide ? TKHD_V1_DURATION : TKHD_V0_DURATION);
|
|
63
|
-
if (durationAt + (wide ? 8 : 4) > tkhd.end)
|
|
64
|
-
return undefined;
|
|
65
|
-
const duration = wide ? uint64(v, durationAt) : knownU32(v.getUint32(durationAt));
|
|
66
|
-
return { id: v.getUint32(idAt), duration };
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* The track's non-empty edit — `{ mediaTime: 0, duration: 0 }` without an edit
|
|
70
|
-
* list; `undefined` when the list cannot be read or holds more than one.
|
|
71
|
-
*/
|
|
72
|
-
function soleEdit(bytes, elst) {
|
|
73
|
-
if (!elst)
|
|
74
|
-
return { mediaTime: 0, duration: 0 };
|
|
75
|
-
const v = view(bytes);
|
|
76
|
-
const wide = bytes[elst.start] === 1;
|
|
77
|
-
const size = wide ? ELST_V1_ENTRY : ELST_V0_ENTRY;
|
|
78
|
-
if (elst.start + ELST_ENTRIES > elst.end)
|
|
79
|
-
return undefined;
|
|
80
|
-
const count = v.getUint32(elst.start + FULL_BOX_HEADER);
|
|
81
|
-
let edit;
|
|
82
|
-
for (let i = 0, at = elst.start + ELST_ENTRIES; i < count; i++, at += size) {
|
|
83
|
-
if (at + size > elst.end)
|
|
84
|
-
return undefined;
|
|
85
|
-
const duration = wide ? uint64(v, at) : v.getUint32(at);
|
|
86
|
-
const mediaTime = wide ? int64(v, at + 8) : v.getInt32(at + 4);
|
|
87
|
-
if (duration === undefined || mediaTime === undefined)
|
|
88
|
-
return undefined;
|
|
89
|
-
if (mediaTime === EMPTY_EDIT)
|
|
90
|
-
continue;
|
|
91
|
-
if (edit)
|
|
92
|
-
return undefined;
|
|
93
|
-
edit = { mediaTime, duration };
|
|
94
|
-
}
|
|
95
|
-
return edit ?? { mediaTime: 0, duration: 0 };
|
|
96
|
-
}
|
|
97
|
-
function int64(v, at) {
|
|
98
|
-
const n = v.getBigInt64(at);
|
|
99
|
-
return n >= BigInt(Number.MIN_SAFE_INTEGER) && n <= BigInt(Number.MAX_SAFE_INTEGER)
|
|
100
|
-
? Number(n)
|
|
101
|
-
: undefined;
|
|
102
|
-
}
|
|
103
|
-
/** Four-character type of the first sample entry in `stsd`. */
|
|
104
|
-
function sampleEntry(bytes, stsd) {
|
|
105
|
-
const at = stsd.start + STSD_ENTRIES;
|
|
106
|
-
return at + 8 <= stsd.end ? ascii(bytes, at + 4, 4) : undefined;
|
|
107
|
-
}
|
|
108
|
-
function visualSize(bytes, stsd) {
|
|
109
|
-
const entry = stsd.start + STSD_ENTRIES;
|
|
110
|
-
const at = entry + VISUAL_ENTRY_WIDTH;
|
|
111
|
-
if (at + 4 > stsd.end)
|
|
112
|
-
return undefined;
|
|
113
|
-
const v = view(bytes);
|
|
114
|
-
const width = v.getUint16(at);
|
|
115
|
-
const height = v.getUint16(at + 2);
|
|
116
|
-
return width > 0 && height > 0 ? { width, height } : undefined;
|
|
117
|
-
}
|
|
118
|
-
/** Default sample duration for `trackId` from `moov/mvex/trex`. */
|
|
119
|
-
function trexDuration(bytes, moov, trackId) {
|
|
120
|
-
const mvex = descend(bytes, moov, ['mvex']);
|
|
121
|
-
if (!mvex)
|
|
122
|
-
return undefined;
|
|
123
|
-
const v = view(bytes);
|
|
124
|
-
for (const trex of childList(bytes, mvex).filter((b) => b.type === 'trex')) {
|
|
125
|
-
const at = trex.start + FULL_BOX_HEADER;
|
|
126
|
-
if (at + 12 <= trex.end && v.getUint32(at) === trackId)
|
|
127
|
-
return v.getUint32(at + 8);
|
|
128
|
-
}
|
|
129
|
-
return undefined;
|
|
130
|
-
}
|
|
131
|
-
function addSamples(sum, count, delta) {
|
|
132
|
-
if (count === 0)
|
|
133
|
-
return sum ?? { ticks: 0, last: 0 };
|
|
134
|
-
return {
|
|
135
|
-
ticks: (sum?.ticks ?? 0) + count * delta,
|
|
136
|
-
last: delta,
|
|
137
|
-
previous: count > 1 ? delta : sum?.last,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
function sttsSamples(bytes, stts) {
|
|
141
|
-
if (!stts || stts.start + STTS_ENTRIES > stts.end)
|
|
142
|
-
return undefined;
|
|
143
|
-
const v = view(bytes);
|
|
144
|
-
const count = v.getUint32(stts.start + FULL_BOX_HEADER);
|
|
145
|
-
let sum;
|
|
146
|
-
for (let i = 0, at = stts.start + STTS_ENTRIES; i < count; i++, at += STTS_ENTRY) {
|
|
147
|
-
if (at + STTS_ENTRY > stts.end)
|
|
148
|
-
return undefined;
|
|
149
|
-
sum = addSamples(sum, v.getUint32(at), v.getUint32(at + 4));
|
|
150
|
-
}
|
|
151
|
-
return sum;
|
|
152
|
-
}
|
|
153
|
-
function fragmentSamples(bytes, top, trackId, trex) {
|
|
154
|
-
const v = view(bytes);
|
|
155
|
-
let sum;
|
|
156
|
-
for (const moof of top.filter((b) => b.type === 'moof')) {
|
|
157
|
-
for (const traf of childList(bytes, moof).filter((b) => b.type === 'traf')) {
|
|
158
|
-
const inner = childList(bytes, traf);
|
|
159
|
-
const tfhd = inner.find((b) => b.type === 'tfhd');
|
|
160
|
-
if (!tfhd || tfhd.start + 8 > tfhd.end)
|
|
161
|
-
return undefined;
|
|
162
|
-
const tfhdFlags = v.getUint32(tfhd.start) & 0xffffff;
|
|
163
|
-
if (v.getUint32(tfhd.start + FULL_BOX_HEADER) !== trackId)
|
|
164
|
-
continue;
|
|
165
|
-
let at = tfhd.start + 8;
|
|
166
|
-
for (const [flag, width] of TFHD_OPTIONAL)
|
|
167
|
-
if (tfhdFlags & flag)
|
|
168
|
-
at += width;
|
|
169
|
-
const fallback = tfhdFlags & TFHD_DEFAULT_DURATION && at + 4 <= tfhd.end ? v.getUint32(at) : trex;
|
|
170
|
-
for (const trun of inner.filter((b) => b.type === 'trun')) {
|
|
171
|
-
const next = runSamples(v, trun, fallback, sum);
|
|
172
|
-
if (next === undefined)
|
|
173
|
-
return undefined;
|
|
174
|
-
sum = next;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
return sum;
|
|
179
|
-
}
|
|
180
|
-
function runSamples(v, trun, fallback, sum) {
|
|
181
|
-
const flags = v.getUint32(trun.start) & 0xffffff;
|
|
182
|
-
const count = v.getUint32(trun.start + FULL_BOX_HEADER);
|
|
183
|
-
let at = trun.start + 8;
|
|
184
|
-
if (flags & TRUN_DATA_OFFSET)
|
|
185
|
-
at += 4;
|
|
186
|
-
if (flags & TRUN_FIRST_FLAGS)
|
|
187
|
-
at += 4;
|
|
188
|
-
if (!(flags & TRUN_DURATION)) {
|
|
189
|
-
return fallback === undefined ? undefined : addSamples(sum, count, fallback);
|
|
190
|
-
}
|
|
191
|
-
const stride = TRUN_FIELDS.filter((f) => flags & f).length * 4;
|
|
192
|
-
if (at + stride * count > trun.end)
|
|
193
|
-
return undefined;
|
|
194
|
-
let next = addSamples(sum, 0, 0);
|
|
195
|
-
for (let i = 0; i < count; i++)
|
|
196
|
-
next = addSamples(next, 1, v.getUint32(at + i * stride));
|
|
197
|
-
return next;
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Decoded ticks: from the edit's start to the end of the sample it ends in.
|
|
201
|
-
* `undefined` when the edit ends before the last sample begins.
|
|
202
|
-
*
|
|
203
|
-
* MPEG-4 audio (`mp4a`) decodes whole frames: a final sample whose `stts`
|
|
204
|
-
* duration is shortened (how ffmpeg marks encoder padding) still decodes as
|
|
205
|
-
* long as the frame before it.
|
|
206
|
-
*/
|
|
207
|
-
function decodedTicks(samples, edit, mediaScale, movieScale, wholeFrames) {
|
|
208
|
-
const lastStart = samples.ticks - samples.last;
|
|
209
|
-
if (edit.duration > 0) {
|
|
210
|
-
if (!movieScale)
|
|
211
|
-
return undefined;
|
|
212
|
-
const editEnd = edit.mediaTime + (edit.duration * mediaScale) / movieScale;
|
|
213
|
-
if (editEnd <= lastStart)
|
|
214
|
-
return undefined;
|
|
215
|
-
}
|
|
216
|
-
const frame = wholeFrames && samples.previous !== undefined
|
|
217
|
-
? Math.max(samples.last, samples.previous)
|
|
218
|
-
: samples.last;
|
|
219
|
-
return lastStart + frame - edit.mediaTime;
|
|
220
|
-
}
|
|
221
|
-
function positive(seconds) {
|
|
222
|
-
return Number.isFinite(seconds) && seconds > 0 ? seconds : undefined;
|
|
223
|
-
}
|
|
224
|
-
function trackSamples(bytes, movie, stbl, trackId) {
|
|
225
|
-
const table = sttsSamples(bytes, stbl && descend(bytes, stbl, ['stts']));
|
|
226
|
-
const fragments = trackId === undefined
|
|
227
|
-
? undefined
|
|
228
|
-
: fragmentSamples(bytes, movie.top, trackId, trexDuration(bytes, movie.moov, trackId));
|
|
229
|
-
if (!table || !fragments)
|
|
230
|
-
return fragments ?? table;
|
|
231
|
-
// Fragments follow the samples `moov` lists; the last sample is theirs.
|
|
232
|
-
return {
|
|
233
|
-
ticks: table.ticks + fragments.ticks,
|
|
234
|
-
last: fragments.last,
|
|
235
|
-
previous: fragments.previous ?? table.last,
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
function presentedSeconds(duration, movie, samples, mediaScale) {
|
|
239
|
-
if (duration && movie.scale)
|
|
240
|
-
return positive(duration / movie.scale);
|
|
241
|
-
return samples && mediaScale ? positive(samples.ticks / mediaScale) : undefined;
|
|
242
|
-
}
|
|
243
|
-
function readTrack(bytes, movie, trak) {
|
|
244
|
-
const tkhd = descend(bytes, trak, ['tkhd']);
|
|
245
|
-
const hdlr = descend(bytes, trak, ['mdia', 'hdlr']);
|
|
246
|
-
const mdhd = descend(bytes, trak, ['mdia', 'mdhd']);
|
|
247
|
-
if (!tkhd || !hdlr || !mdhd || hdlr.start + HDLR_TYPE + 4 > hdlr.end)
|
|
248
|
-
return undefined;
|
|
249
|
-
const handler = ascii(bytes, hdlr.start + HDLR_TYPE, 4);
|
|
250
|
-
const header = trackHeader(bytes, tkhd);
|
|
251
|
-
const media = timedHeader(bytes, mdhd);
|
|
252
|
-
const stbl = descend(bytes, trak, ['mdia', 'minf', 'stbl']);
|
|
253
|
-
const stsd = stbl && descend(bytes, stbl, ['stsd']);
|
|
254
|
-
const samples = trackSamples(bytes, movie, stbl, header?.id);
|
|
255
|
-
const edit = soleEdit(bytes, descend(bytes, trak, ['edts', 'elst']));
|
|
256
|
-
const wholeFrames = stsd !== undefined && sampleEntry(bytes, stsd) === MPEG4_AUDIO;
|
|
257
|
-
const decoded = samples && media && edit
|
|
258
|
-
? decodedTicks(samples, edit, media.scale, movie.scale, wholeFrames)
|
|
259
|
-
: undefined;
|
|
260
|
-
return {
|
|
261
|
-
handler,
|
|
262
|
-
seconds: presentedSeconds(header?.duration, movie, samples, media?.scale),
|
|
263
|
-
decodedSeconds: decoded === undefined || !media ? undefined : positive(decoded / media.scale),
|
|
264
|
-
...(handler === MP4_VIDEO && stsd ? visualSize(bytes, stsd) : undefined),
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
/** `undefined` when the bytes do not open with `ftyp` and hold a `moov`. */
|
|
268
|
-
export function mp4Tracks(bytes) {
|
|
269
|
-
const top = boxes(bytes).list;
|
|
270
|
-
const moov = top.find((b) => b.type === 'moov');
|
|
271
|
-
if (top[0]?.type !== 'ftyp' || !moov)
|
|
272
|
-
return undefined;
|
|
273
|
-
const mvhd = descend(bytes, moov, ['mvhd']);
|
|
274
|
-
const movie = { top, moov, scale: mvhd ? timedHeader(bytes, mvhd)?.scale : undefined };
|
|
275
|
-
return childList(bytes, moov)
|
|
276
|
-
.filter((b) => b.type === 'trak')
|
|
277
|
-
.map((trak) => readTrack(bytes, movie, trak))
|
|
278
|
-
.filter((track) => track !== undefined);
|
|
279
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/** Opus always decodes at 48 kHz. */
|
|
2
|
-
export const OPUS_RATE = 48_000;
|
|
3
|
-
const MS_PER_SECOND = 1000;
|
|
4
|
-
const TOC_CONFIG_SHIFT = 3;
|
|
5
|
-
const TOC_FRAME_CODE = 0x03;
|
|
6
|
-
const FRAME_COUNT_MASK = 0x3f;
|
|
7
|
-
const SILK_CONFIGS = 12;
|
|
8
|
-
const HYBRID_CONFIGS = 16;
|
|
9
|
-
/** Opus packet duration in 48 kHz samples from its TOC byte (RFC 6716 §3.1). */
|
|
10
|
-
export function opusPacketSamples(bytes, at, end) {
|
|
11
|
-
if (at >= end)
|
|
12
|
-
return undefined;
|
|
13
|
-
const toc = bytes[at];
|
|
14
|
-
const config = toc >> TOC_CONFIG_SHIFT;
|
|
15
|
-
const frameMs = config < SILK_CONFIGS
|
|
16
|
-
? [10, 20, 40, 60][config % 4]
|
|
17
|
-
: config < HYBRID_CONFIGS
|
|
18
|
-
? [10, 20][config % 2]
|
|
19
|
-
: [2.5, 5, 10, 20][config % 4];
|
|
20
|
-
const code = toc & TOC_FRAME_CODE;
|
|
21
|
-
const frames = code === 0 ? 1 : code < 3 ? 2 : at + 1 < end ? bytes[at + 1] & FRAME_COUNT_MASK : undefined;
|
|
22
|
-
return frames === undefined ? undefined : (frameMs * frames * OPUS_RATE) / MS_PER_SECOND;
|
|
23
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The last page-tree root in file order wins, so an incremental update that rewrites the page tree
|
|
3
|
-
* beats the original. `undefined` when no root can be read (encrypted object streams, damage).
|
|
4
|
-
*/
|
|
5
|
-
export declare function pdfPageCount(bytes: Uint8Array): Promise<number | undefined>;
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
const PDF_PAGES_TYPE = /\/Type\s*\/Pages(?![A-Za-z])/g;
|
|
2
|
-
const PDF_COUNT = /\/Count\s+(\d+)/;
|
|
3
|
-
const PDF_PARENT = /\/Parent(?![A-Za-z])/;
|
|
4
|
-
const PDF_OBJSTM = /\/Type\s*\/ObjStm(?![A-Za-z])/g;
|
|
5
|
-
const PDF_STREAM_START = /stream\r?\n/g;
|
|
6
|
-
/** Direct `/Length n` — not an indirect `/Length n 0 R`. */
|
|
7
|
-
const PDF_DIRECT_LENGTH = /\/Length\s+(\d+)(?!\d)(?!\s+\d+\s+R)/;
|
|
8
|
-
/** End-of-line before `endstream`; not part of the stream data. */
|
|
9
|
-
const PDF_TRAILING_EOL = /\r?\n$|\r$/;
|
|
10
|
-
const PDF_HEADER = '%PDF-';
|
|
11
|
-
function latin1(bytes) {
|
|
12
|
-
return new TextDecoder('latin1').decode(bytes);
|
|
13
|
-
}
|
|
14
|
-
/** Innermost `<< … >>` dictionary that contains `at`, with its end offset. */
|
|
15
|
-
function enclosingDict(text, at) {
|
|
16
|
-
let depth = 0;
|
|
17
|
-
let start = -1;
|
|
18
|
-
for (let i = at; i > 0; i--) {
|
|
19
|
-
if (text[i] === '>' && text[i - 1] === '>') {
|
|
20
|
-
depth++;
|
|
21
|
-
i--;
|
|
22
|
-
}
|
|
23
|
-
else if (text[i] === '<' && text[i - 1] === '<') {
|
|
24
|
-
if (depth === 0) {
|
|
25
|
-
start = i - 1;
|
|
26
|
-
break;
|
|
27
|
-
}
|
|
28
|
-
depth--;
|
|
29
|
-
i--;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
if (start < 0)
|
|
33
|
-
return undefined;
|
|
34
|
-
depth = 0;
|
|
35
|
-
for (let i = start; i < text.length - 1; i++) {
|
|
36
|
-
if (text[i] === '<' && text[i + 1] === '<') {
|
|
37
|
-
depth++;
|
|
38
|
-
i++;
|
|
39
|
-
}
|
|
40
|
-
else if (text[i] === '>' && text[i + 1] === '>') {
|
|
41
|
-
depth--;
|
|
42
|
-
i++;
|
|
43
|
-
if (depth === 0)
|
|
44
|
-
return { dict: text.slice(start, i + 1), end: i + 1 };
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return undefined;
|
|
48
|
-
}
|
|
49
|
-
/** Page-tree roots in `text`, each placed at `at` (or at its own offset when `at` is omitted). */
|
|
50
|
-
function pageTreeRoots(text, at) {
|
|
51
|
-
const roots = [];
|
|
52
|
-
for (const match of text.matchAll(PDF_PAGES_TYPE)) {
|
|
53
|
-
const dict = enclosingDict(text, match.index)?.dict;
|
|
54
|
-
if (!dict || PDF_PARENT.test(dict))
|
|
55
|
-
continue;
|
|
56
|
-
const count = PDF_COUNT.exec(dict)?.[1];
|
|
57
|
-
if (count !== undefined)
|
|
58
|
-
roots.push({ at: at ?? match.index, count: Number(count) });
|
|
59
|
-
}
|
|
60
|
-
return roots;
|
|
61
|
-
}
|
|
62
|
-
async function inflate(bytes) {
|
|
63
|
-
try {
|
|
64
|
-
const stream = new Blob([bytes.slice()])
|
|
65
|
-
.stream()
|
|
66
|
-
.pipeThrough(new DecompressionStream('deflate'));
|
|
67
|
-
return new Uint8Array(await new Response(stream).arrayBuffer());
|
|
68
|
-
}
|
|
69
|
-
catch {
|
|
70
|
-
return undefined;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
/** End offset of stream data: the direct `/Length`, else up to `endstream` less its EOL. */
|
|
74
|
-
function streamEnd(text, bodyStart, dict) {
|
|
75
|
-
const length = PDF_DIRECT_LENGTH.exec(dict)?.[1];
|
|
76
|
-
if (length !== undefined && bodyStart + Number(length) <= text.length) {
|
|
77
|
-
return bodyStart + Number(length);
|
|
78
|
-
}
|
|
79
|
-
const keyword = text.indexOf('endstream', bodyStart);
|
|
80
|
-
if (keyword < 0)
|
|
81
|
-
return undefined;
|
|
82
|
-
const eol = PDF_TRAILING_EOL.exec(text.slice(bodyStart, keyword));
|
|
83
|
-
return keyword - (eol?.[0].length ?? 0);
|
|
84
|
-
}
|
|
85
|
-
/** Page-tree roots inside FlateDecode object streams (`/Type /ObjStm`), placed at the stream. */
|
|
86
|
-
async function objectStreamRoots(text, bytes) {
|
|
87
|
-
const roots = [];
|
|
88
|
-
for (const match of text.matchAll(PDF_OBJSTM)) {
|
|
89
|
-
const found = enclosingDict(text, match.index);
|
|
90
|
-
if (!found?.dict.includes('/FlateDecode'))
|
|
91
|
-
continue;
|
|
92
|
-
PDF_STREAM_START.lastIndex = found.end;
|
|
93
|
-
const start = PDF_STREAM_START.exec(text);
|
|
94
|
-
if (!start || text.slice(found.end, start.index).trim() !== '')
|
|
95
|
-
continue;
|
|
96
|
-
const bodyStart = start.index + start[0].length;
|
|
97
|
-
const bodyEnd = streamEnd(text, bodyStart, found.dict);
|
|
98
|
-
if (bodyEnd === undefined)
|
|
99
|
-
continue;
|
|
100
|
-
const inflated = await inflate(bytes.subarray(bodyStart, bodyEnd));
|
|
101
|
-
if (inflated)
|
|
102
|
-
roots.push(...pageTreeRoots(latin1(inflated), match.index));
|
|
103
|
-
}
|
|
104
|
-
return roots;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* The last page-tree root in file order wins, so an incremental update that rewrites the page tree
|
|
108
|
-
* beats the original. `undefined` when no root can be read (encrypted object streams, damage).
|
|
109
|
-
*/
|
|
110
|
-
export async function pdfPageCount(bytes) {
|
|
111
|
-
const text = latin1(bytes);
|
|
112
|
-
if (!text.startsWith(PDF_HEADER))
|
|
113
|
-
return undefined;
|
|
114
|
-
const roots = [...pageTreeRoots(text), ...(await objectStreamRoots(text, bytes))];
|
|
115
|
-
const last = roots.sort((a, b) => a.at - b.at).at(-1);
|
|
116
|
-
return last && last.count > 0 ? last.count : undefined;
|
|
117
|
-
}
|