agent-nuvira 3.3.1 → 3.3.4
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 +18 -13
- package/dist/agent-sdk/src/agent.d.ts +2 -0
- package/dist/agent-sdk/src/agent.d.ts.map +1 -1
- package/dist/agent-sdk/src/define.d.ts +64 -0
- package/dist/agent-sdk/src/define.d.ts.map +1 -0
- package/dist/agent-sdk/src/define.js +76 -0
- package/dist/agent-sdk/src/define.js.map +1 -0
- package/dist/agent-sdk/src/index.d.ts +9 -0
- package/dist/agent-sdk/src/index.d.ts.map +1 -1
- package/dist/agent-sdk/src/index.js +9 -0
- package/dist/agent-sdk/src/index.js.map +1 -1
- package/dist/agent-sdk/src/scaffold.d.ts +11 -0
- package/dist/agent-sdk/src/scaffold.d.ts.map +1 -1
- package/dist/agent-sdk/src/scaffold.js +16 -6
- package/dist/agent-sdk/src/scaffold.js.map +1 -1
- package/dist/agents/agents/runner.d.ts +9 -0
- package/dist/agents/agents/runner.d.ts.map +1 -1
- package/dist/agents/agents/runner.js +34 -12
- package/dist/agents/agents/runner.js.map +1 -1
- package/dist/agents/agents/writer-tool-calling.d.ts.map +1 -1
- package/dist/agents/agents/writer-tool-calling.js +7 -2
- package/dist/agents/agents/writer-tool-calling.js.map +1 -1
- package/dist/agents/agents/writer.d.ts.map +1 -1
- package/dist/agents/agents/writer.js +7 -1
- package/dist/agents/agents/writer.js.map +1 -1
- package/dist/agents/artifact-verification.d.ts +102 -0
- package/dist/agents/artifact-verification.d.ts.map +1 -0
- package/dist/agents/artifact-verification.js +216 -0
- package/dist/agents/artifact-verification.js.map +1 -0
- package/dist/agents/checkpoint-store.d.ts +73 -0
- package/dist/agents/checkpoint-store.d.ts.map +1 -1
- package/dist/agents/checkpoint-store.js +161 -0
- package/dist/agents/checkpoint-store.js.map +1 -1
- package/dist/agents/credential-store.d.ts +120 -0
- package/dist/agents/credential-store.d.ts.map +1 -1
- package/dist/agents/credential-store.js +358 -19
- package/dist/agents/credential-store.js.map +1 -1
- package/dist/agents/long-form-plan.d.ts.map +1 -1
- package/dist/agents/long-form-plan.js +2 -1
- package/dist/agents/long-form-plan.js.map +1 -1
- package/dist/agents/orchestrator.d.ts +10 -1
- package/dist/agents/orchestrator.d.ts.map +1 -1
- package/dist/agents/orchestrator.js +239 -79
- package/dist/agents/orchestrator.js.map +1 -1
- package/dist/agents/phase-engine.d.ts +61 -0
- package/dist/agents/phase-engine.d.ts.map +1 -1
- package/dist/agents/phase-engine.js +68 -2
- package/dist/agents/phase-engine.js.map +1 -1
- package/dist/agents/prompt-assembly.d.ts +11 -0
- package/dist/agents/prompt-assembly.d.ts.map +1 -1
- package/dist/agents/prompt-assembly.js +17 -0
- package/dist/agents/prompt-assembly.js.map +1 -1
- package/dist/agents/release-preflight.d.ts +121 -0
- package/dist/agents/release-preflight.d.ts.map +1 -0
- package/dist/agents/release-preflight.js +259 -0
- package/dist/agents/release-preflight.js.map +1 -0
- package/dist/agents/release-runner.d.ts +157 -0
- package/dist/agents/release-runner.d.ts.map +1 -0
- package/dist/agents/release-runner.js +719 -0
- package/dist/agents/release-runner.js.map +1 -0
- package/dist/agents/step-handoff.d.ts +190 -0
- package/dist/agents/step-handoff.d.ts.map +1 -0
- package/dist/agents/step-handoff.js +443 -0
- package/dist/agents/step-handoff.js.map +1 -0
- package/dist/cli/agent.d.ts +2 -2
- package/dist/cli/agent.js +10 -10
- package/dist/cli/benchmark.d.ts.map +1 -1
- package/dist/cli/benchmark.js +11 -4
- package/dist/cli/benchmark.js.map +1 -1
- package/dist/cli/chat.d.ts +94 -0
- package/dist/cli/chat.d.ts.map +1 -1
- package/dist/cli/chat.js +379 -24
- package/dist/cli/chat.js.map +1 -1
- package/dist/cli/cli-program.d.ts.map +1 -1
- package/dist/cli/cli-program.js +8 -0
- package/dist/cli/cli-program.js.map +1 -1
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +9 -1
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/credentials.d.ts +28 -0
- package/dist/cli/credentials.d.ts.map +1 -0
- package/dist/cli/credentials.js +213 -0
- package/dist/cli/credentials.js.map +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +3 -2
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/edit.js +2 -2
- package/dist/cli/eval.d.ts +17 -0
- package/dist/cli/eval.d.ts.map +1 -1
- package/dist/cli/eval.js +105 -2
- package/dist/cli/eval.js.map +1 -1
- package/dist/cli/execute.d.ts +16 -1
- package/dist/cli/execute.d.ts.map +1 -1
- package/dist/cli/execute.js +192 -22
- package/dist/cli/execute.js.map +1 -1
- package/dist/cli/failover-runner.d.ts.map +1 -1
- package/dist/cli/failover-runner.js +9 -3
- package/dist/cli/failover-runner.js.map +1 -1
- package/dist/cli/loop-executor.d.ts +55 -0
- package/dist/cli/loop-executor.d.ts.map +1 -1
- package/dist/cli/loop-executor.js +285 -19
- package/dist/cli/loop-executor.js.map +1 -1
- package/dist/cli/model.d.ts.map +1 -1
- package/dist/cli/model.js +9 -8
- package/dist/cli/model.js.map +1 -1
- package/dist/cli/models.d.ts +1 -1
- package/dist/cli/models.js +4 -4
- package/dist/cli/nlu.d.ts.map +1 -1
- package/dist/cli/nlu.js +8 -2
- package/dist/cli/nlu.js.map +1 -1
- package/dist/cli/parity.d.ts +85 -0
- package/dist/cli/parity.d.ts.map +1 -0
- package/dist/cli/parity.js +506 -0
- package/dist/cli/parity.js.map +1 -0
- package/dist/cli/plan.d.ts.map +1 -1
- package/dist/cli/plan.js +2 -1
- package/dist/cli/plan.js.map +1 -1
- package/dist/cli/publish.d.ts +22 -0
- package/dist/cli/publish.d.ts.map +1 -1
- package/dist/cli/publish.js +109 -13
- package/dist/cli/publish.js.map +1 -1
- package/dist/cli/retrieval.d.ts.map +1 -1
- package/dist/cli/retrieval.js +5 -4
- package/dist/cli/retrieval.js.map +1 -1
- package/dist/cli/sdk.js +4 -4
- package/dist/cli/sdk.js.map +1 -1
- package/dist/cli/trace.d.ts.map +1 -1
- package/dist/cli/trace.js +2 -1
- package/dist/cli/trace.js.map +1 -1
- package/dist/cli/workflow.js +2 -2
- package/dist/cli/workflow.js.map +1 -1
- package/dist/config/live-credentials.d.ts +57 -0
- package/dist/config/live-credentials.d.ts.map +1 -0
- package/dist/config/live-credentials.js +126 -0
- package/dist/config/live-credentials.js.map +1 -0
- package/dist/config/paths.d.ts +18 -0
- package/dist/config/paths.d.ts.map +1 -1
- package/dist/config/paths.js +25 -0
- package/dist/config/paths.js.map +1 -1
- package/dist/config/types.d.ts +44 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/federation/a2a-types.js +1 -1
- package/dist/federation/a2a-types.js.map +1 -1
- package/dist/findings/verdicts.d.ts +241 -0
- package/dist/findings/verdicts.d.ts.map +1 -0
- package/dist/findings/verdicts.js +284 -0
- package/dist/findings/verdicts.js.map +1 -0
- package/dist/gateway/adapters.d.ts +65 -0
- package/dist/gateway/adapters.d.ts.map +1 -1
- package/dist/gateway/adapters.js +216 -10
- package/dist/gateway/adapters.js.map +1 -1
- package/dist/gateway/channel-directory.d.ts +31 -0
- package/dist/gateway/channel-directory.d.ts.map +1 -1
- package/dist/gateway/channel-directory.js +40 -0
- package/dist/gateway/channel-directory.js.map +1 -1
- package/dist/gateway/gateway-log.d.ts +1 -1
- package/dist/gateway/gateway-log.d.ts.map +1 -1
- package/dist/gateway/gateway-log.js.map +1 -1
- package/dist/gateway/hooks.d.ts +87 -19
- package/dist/gateway/hooks.d.ts.map +1 -1
- package/dist/gateway/hooks.js +62 -23
- package/dist/gateway/hooks.js.map +1 -1
- package/dist/gateway/inbound-media.d.ts +147 -0
- package/dist/gateway/inbound-media.d.ts.map +1 -0
- package/dist/gateway/inbound-media.js +317 -0
- package/dist/gateway/inbound-media.js.map +1 -0
- package/dist/gateway/inbox.d.ts +8 -1
- package/dist/gateway/inbox.d.ts.map +1 -1
- package/dist/gateway/inbox.js.map +1 -1
- package/dist/gateway/platform-config.d.ts +14 -0
- package/dist/gateway/platform-config.d.ts.map +1 -1
- package/dist/gateway/platform-config.js +26 -8
- package/dist/gateway/platform-config.js.map +1 -1
- package/dist/gateway/realtime.d.ts +114 -0
- package/dist/gateway/realtime.d.ts.map +1 -0
- package/dist/gateway/realtime.js +402 -0
- package/dist/gateway/realtime.js.map +1 -0
- package/dist/gateway/registry.d.ts +31 -0
- package/dist/gateway/registry.d.ts.map +1 -1
- package/dist/gateway/registry.js +224 -4
- package/dist/gateway/registry.js.map +1 -1
- package/dist/gateway/whatsapp/baileys-bridge.d.ts +11 -1
- package/dist/gateway/whatsapp/baileys-bridge.d.ts.map +1 -1
- package/dist/gateway/whatsapp/baileys-bridge.js +123 -4
- package/dist/gateway/whatsapp/baileys-bridge.js.map +1 -1
- package/dist/gateway/whatsapp/bridge.d.ts +6 -2
- package/dist/gateway/whatsapp/bridge.d.ts.map +1 -1
- package/dist/gateway/whatsapp/bridge.js.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/inference/factory.d.ts +14 -0
- package/dist/inference/factory.d.ts.map +1 -1
- package/dist/inference/factory.js +17 -0
- package/dist/inference/factory.js.map +1 -1
- package/dist/inference/groq-adapter.d.ts +2 -0
- package/dist/inference/groq-adapter.d.ts.map +1 -1
- package/dist/inference/groq-adapter.js +16 -6
- package/dist/inference/groq-adapter.js.map +1 -1
- package/dist/inference/model-validator.d.ts +6 -1
- package/dist/inference/model-validator.d.ts.map +1 -1
- package/dist/inference/model-validator.js +7 -2
- package/dist/inference/model-validator.js.map +1 -1
- package/dist/inference/route-resolver.d.ts +116 -0
- package/dist/inference/route-resolver.d.ts.map +1 -0
- package/dist/inference/route-resolver.js +159 -0
- package/dist/inference/route-resolver.js.map +1 -0
- package/dist/inference/tools.d.ts.map +1 -1
- package/dist/inference/tools.js +29 -0
- package/dist/inference/tools.js.map +1 -1
- package/dist/learning/autonomy-policy.d.ts +18 -0
- package/dist/learning/autonomy-policy.d.ts.map +1 -1
- package/dist/learning/autonomy-policy.js +35 -0
- package/dist/learning/autonomy-policy.js.map +1 -1
- package/dist/learning/benchmark.d.ts.map +1 -1
- package/dist/learning/benchmark.js +3 -2
- package/dist/learning/benchmark.js.map +1 -1
- package/dist/learning/continuation.d.ts.map +1 -1
- package/dist/learning/continuation.js +2 -1
- package/dist/learning/continuation.js.map +1 -1
- package/dist/learning/cost-tracker.d.ts.map +1 -1
- package/dist/learning/cost-tracker.js +2 -1
- package/dist/learning/cost-tracker.js.map +1 -1
- package/dist/learning/deferred-task.d.ts.map +1 -1
- package/dist/learning/deferred-task.js +13 -4
- package/dist/learning/deferred-task.js.map +1 -1
- package/dist/learning/eval-framework.d.ts.map +1 -1
- package/dist/learning/eval-framework.js +2 -1
- package/dist/learning/eval-framework.js.map +1 -1
- package/dist/learning/long-form.d.ts.map +1 -1
- package/dist/learning/long-form.js +2 -1
- package/dist/learning/long-form.js.map +1 -1
- package/dist/learning/model-registry.d.ts.map +1 -1
- package/dist/learning/model-registry.js +2 -1
- package/dist/learning/model-registry.js.map +1 -1
- package/dist/learning/reasoning-cache.d.ts.map +1 -1
- package/dist/learning/reasoning-cache.js +2 -1
- package/dist/learning/reasoning-cache.js.map +1 -1
- package/dist/learning/reasoning-trace.d.ts +38 -2
- package/dist/learning/reasoning-trace.d.ts.map +1 -1
- package/dist/learning/reasoning-trace.js +91 -1
- package/dist/learning/reasoning-trace.js.map +1 -1
- package/dist/learning/resilient-call.d.ts.map +1 -1
- package/dist/learning/resilient-call.js +31 -18
- package/dist/learning/resilient-call.js.map +1 -1
- package/dist/learning/retrieval.d.ts.map +1 -1
- package/dist/learning/retrieval.js +2 -1
- package/dist/learning/retrieval.js.map +1 -1
- package/dist/learning/seeded-benchmark.d.ts +160 -0
- package/dist/learning/seeded-benchmark.d.ts.map +1 -0
- package/dist/learning/seeded-benchmark.js +321 -0
- package/dist/learning/seeded-benchmark.js.map +1 -0
- package/dist/learning/seeded-bugs.d.ts +142 -0
- package/dist/learning/seeded-bugs.d.ts.map +1 -0
- package/dist/learning/seeded-bugs.js +535 -0
- package/dist/learning/seeded-bugs.js.map +1 -0
- package/dist/learning/skill-store.d.ts.map +1 -1
- package/dist/learning/skill-store.js +30 -9
- package/dist/learning/skill-store.js.map +1 -1
- package/dist/learning/step-checkpoint.d.ts +127 -0
- package/dist/learning/step-checkpoint.d.ts.map +1 -0
- package/dist/learning/step-checkpoint.js +244 -0
- package/dist/learning/step-checkpoint.js.map +1 -0
- package/dist/mcp/catalog.js +2 -3
- package/dist/mcp/catalog.js.map +1 -1
- package/dist/mcp/manager.d.ts.map +1 -1
- package/dist/mcp/manager.js +5 -3
- package/dist/mcp/manager.js.map +1 -1
- package/dist/nlu/intent-confirm.d.ts +23 -1
- package/dist/nlu/intent-confirm.d.ts.map +1 -1
- package/dist/nlu/intent-confirm.js +85 -2
- package/dist/nlu/intent-confirm.js.map +1 -1
- package/dist/nlu/learnings.d.ts +7 -0
- package/dist/nlu/learnings.d.ts.map +1 -1
- package/dist/nlu/learnings.js +7 -0
- package/dist/nlu/learnings.js.map +1 -1
- package/dist/observability/debug-log.d.ts +250 -0
- package/dist/observability/debug-log.d.ts.map +1 -0
- package/dist/observability/debug-log.js +500 -0
- package/dist/observability/debug-log.js.map +1 -0
- package/dist/observability/event-bus.d.ts.map +1 -1
- package/dist/observability/event-bus.js +4 -1
- package/dist/observability/event-bus.js.map +1 -1
- package/dist/observability/otel.d.ts +278 -0
- package/dist/observability/otel.d.ts.map +1 -0
- package/dist/observability/otel.js +590 -0
- package/dist/observability/otel.js.map +1 -0
- package/dist/parity/drivers.d.ts +99 -0
- package/dist/parity/drivers.d.ts.map +1 -0
- package/dist/parity/drivers.js +1362 -0
- package/dist/parity/drivers.js.map +1 -0
- package/dist/parity/graph.d.ts +73 -0
- package/dist/parity/graph.d.ts.map +1 -0
- package/dist/parity/graph.js +162 -0
- package/dist/parity/graph.js.map +1 -0
- package/dist/parity/matrix.d.ts +105 -0
- package/dist/parity/matrix.d.ts.map +1 -0
- package/dist/parity/matrix.js +352 -0
- package/dist/parity/matrix.js.map +1 -0
- package/dist/parity/observation.d.ts +444 -0
- package/dist/parity/observation.d.ts.map +1 -0
- package/dist/parity/observation.js +333 -0
- package/dist/parity/observation.js.map +1 -0
- package/dist/parity/scenarios.d.ts +229 -0
- package/dist/parity/scenarios.d.ts.map +1 -0
- package/dist/parity/scenarios.js +175 -0
- package/dist/parity/scenarios.js.map +1 -0
- package/dist/parity/surfaces.d.ts +122 -0
- package/dist/parity/surfaces.d.ts.map +1 -0
- package/dist/parity/surfaces.js +190 -0
- package/dist/parity/surfaces.js.map +1 -0
- package/dist/runtime/fault-injection.d.ts +173 -0
- package/dist/runtime/fault-injection.d.ts.map +1 -0
- package/dist/runtime/fault-injection.js +281 -0
- package/dist/runtime/fault-injection.js.map +1 -0
- package/dist/skills/secret-capture.d.ts.map +1 -1
- package/dist/skills/secret-capture.js +9 -4
- package/dist/skills/secret-capture.js.map +1 -1
- package/dist/tools/child-agent-entry.d.ts +23 -0
- package/dist/tools/child-agent-entry.d.ts.map +1 -0
- package/dist/tools/child-agent-entry.js +129 -0
- package/dist/tools/child-agent-entry.js.map +1 -0
- package/dist/tools/child-agent-runtime.d.ts +124 -0
- package/dist/tools/child-agent-runtime.d.ts.map +1 -0
- package/dist/tools/child-agent-runtime.js +704 -0
- package/dist/tools/child-agent-runtime.js.map +1 -0
- package/dist/tools/coding-tools.d.ts.map +1 -1
- package/dist/tools/coding-tools.js +82 -10
- package/dist/tools/coding-tools.js.map +1 -1
- package/dist/tools/credentials-tool.d.ts +24 -0
- package/dist/tools/credentials-tool.d.ts.map +1 -0
- package/dist/tools/credentials-tool.js +125 -0
- package/dist/tools/credentials-tool.js.map +1 -0
- package/dist/tools/delegation-system.d.ts +31 -0
- package/dist/tools/delegation-system.d.ts.map +1 -1
- package/dist/tools/delegation-system.js +70 -9
- package/dist/tools/delegation-system.js.map +1 -1
- package/dist/tools/extract/docx.d.ts +27 -0
- package/dist/tools/extract/docx.d.ts.map +1 -0
- package/dist/tools/extract/docx.js +48 -0
- package/dist/tools/extract/docx.js.map +1 -0
- package/dist/tools/extract/html-text.d.ts +27 -0
- package/dist/tools/extract/html-text.d.ts.map +1 -0
- package/dist/tools/extract/html-text.js +86 -0
- package/dist/tools/extract/html-text.js.map +1 -0
- package/dist/tools/extract/pdf-ocr.d.ts +58 -0
- package/dist/tools/extract/pdf-ocr.d.ts.map +1 -0
- package/dist/tools/extract/pdf-ocr.js +116 -0
- package/dist/tools/extract/pdf-ocr.js.map +1 -0
- package/dist/tools/extract/pdf.d.ts +65 -0
- package/dist/tools/extract/pdf.d.ts.map +1 -0
- package/dist/tools/extract/pdf.js +197 -0
- package/dist/tools/extract/pdf.js.map +1 -0
- package/dist/tools/extract/pptx.d.ts +32 -0
- package/dist/tools/extract/pptx.d.ts.map +1 -0
- package/dist/tools/extract/pptx.js +77 -0
- package/dist/tools/extract/pptx.js.map +1 -0
- package/dist/tools/extract/xlsx.d.ts +47 -0
- package/dist/tools/extract/xlsx.d.ts.map +1 -0
- package/dist/tools/extract/xlsx.js +111 -0
- package/dist/tools/extract/xlsx.js.map +1 -0
- package/dist/tools/finding-tool.d.ts +76 -0
- package/dist/tools/finding-tool.d.ts.map +1 -0
- package/dist/tools/finding-tool.js +125 -0
- package/dist/tools/finding-tool.js.map +1 -0
- package/dist/tools/git-tool.d.ts +25 -7
- package/dist/tools/git-tool.d.ts.map +1 -1
- package/dist/tools/git-tool.js +155 -15
- package/dist/tools/git-tool.js.map +1 -1
- package/dist/tools/loop-project-context.d.ts.map +1 -1
- package/dist/tools/loop-project-context.js +16 -0
- package/dist/tools/loop-project-context.js.map +1 -1
- package/dist/tools/loop-route-feed.d.ts +57 -0
- package/dist/tools/loop-route-feed.d.ts.map +1 -0
- package/dist/tools/loop-route-feed.js +101 -0
- package/dist/tools/loop-route-feed.js.map +1 -0
- package/dist/tools/messaging-tools.d.ts +41 -11
- package/dist/tools/messaging-tools.d.ts.map +1 -1
- package/dist/tools/messaging-tools.js +104 -55
- package/dist/tools/messaging-tools.js.map +1 -1
- package/dist/tools/neutts-synth.d.ts +27 -3
- package/dist/tools/neutts-synth.d.ts.map +1 -1
- package/dist/tools/neutts-synth.js +57 -13
- package/dist/tools/neutts-synth.js.map +1 -1
- package/dist/tools/pipeline-tool.d.ts +43 -1
- package/dist/tools/pipeline-tool.d.ts.map +1 -1
- package/dist/tools/pipeline-tool.js +21 -4
- package/dist/tools/pipeline-tool.js.map +1 -1
- package/dist/tools/publish-tool.d.ts.map +1 -1
- package/dist/tools/publish-tool.js +76 -10
- package/dist/tools/publish-tool.js.map +1 -1
- package/dist/tools/read-extract.d.ts +116 -45
- package/dist/tools/read-extract.d.ts.map +1 -1
- package/dist/tools/read-extract.js +494 -158
- package/dist/tools/read-extract.js.map +1 -1
- package/dist/tools/registry.d.ts +23 -3
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +196 -29
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/run-terminal.d.ts +9 -0
- package/dist/tools/run-terminal.d.ts.map +1 -1
- package/dist/tools/run-terminal.js +80 -2
- package/dist/tools/run-terminal.js.map +1 -1
- package/dist/tools/subagent-refusal.d.ts +15 -0
- package/dist/tools/subagent-refusal.d.ts.map +1 -0
- package/dist/tools/subagent-refusal.js +18 -0
- package/dist/tools/subagent-refusal.js.map +1 -0
- package/dist/tools/subagent-spawner.d.ts +122 -0
- package/dist/tools/subagent-spawner.d.ts.map +1 -1
- package/dist/tools/subagent-spawner.js +249 -28
- package/dist/tools/subagent-spawner.js.map +1 -1
- package/dist/tools/tool-hooks.d.ts +177 -0
- package/dist/tools/tool-hooks.d.ts.map +1 -0
- package/dist/tools/tool-hooks.js +427 -0
- package/dist/tools/tool-hooks.js.map +1 -0
- package/dist/tools/tool-loop.d.ts +94 -5
- package/dist/tools/tool-loop.d.ts.map +1 -1
- package/dist/tools/tool-loop.js +315 -9
- package/dist/tools/tool-loop.js.map +1 -1
- package/dist/tools/tool-refusal.d.ts +68 -0
- package/dist/tools/tool-refusal.d.ts.map +1 -0
- package/dist/tools/tool-refusal.js +78 -0
- package/dist/tools/tool-refusal.js.map +1 -0
- package/dist/tools/toolsets.d.ts +8 -0
- package/dist/tools/toolsets.d.ts.map +1 -1
- package/dist/tools/toolsets.js +14 -4
- package/dist/tools/toolsets.js.map +1 -1
- package/dist/tools/vision-tools.d.ts +88 -83
- package/dist/tools/vision-tools.d.ts.map +1 -1
- package/dist/tools/vision-tools.js +134 -103
- package/dist/tools/vision-tools.js.map +1 -1
- package/dist/tools/worktree.d.ts +210 -0
- package/dist/tools/worktree.d.ts.map +1 -0
- package/dist/tools/worktree.js +374 -0
- package/dist/tools/worktree.js.map +1 -0
- package/dist/utils/format.d.ts +3 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +32 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/web-dashboard/attachment-extract.d.ts +64 -0
- package/dist/web-dashboard/attachment-extract.d.ts.map +1 -0
- package/dist/web-dashboard/attachment-extract.js +154 -0
- package/dist/web-dashboard/attachment-extract.js.map +1 -0
- package/dist/web-dashboard/chat-console.d.ts +108 -1
- package/dist/web-dashboard/chat-console.d.ts.map +1 -1
- package/dist/web-dashboard/chat-console.js +36 -0
- package/dist/web-dashboard/chat-console.js.map +1 -1
- package/dist/web-dashboard/hub-data.d.ts +37 -0
- package/dist/web-dashboard/hub-data.d.ts.map +1 -1
- package/dist/web-dashboard/hub-data.js +61 -1
- package/dist/web-dashboard/hub-data.js.map +1 -1
- package/dist/web-dashboard/server.d.ts +14 -0
- package/dist/web-dashboard/server.d.ts.map +1 -1
- package/dist/web-dashboard/server.js +247 -13
- package/dist/web-dashboard/server.js.map +1 -1
- package/dist/web-dashboard/src/types.d.ts +196 -48
- package/dist/web-dashboard/src/types.d.ts.map +1 -1
- package/dist/workflow/registry.js +1 -1
- package/dist/workflow/registry.js.map +1 -1
- package/package.json +22 -6
- package/src/web-dashboard/public/assets/{index-Cyd6tIew.css → index-XJjj2cBX.css} +1 -1
- package/src/web-dashboard/public/assets/index-YWF9FpwQ.js +207 -0
- package/src/web-dashboard/public/assets/index-YWF9FpwQ.js.map +1 -0
- package/src/web-dashboard/public/index.html +2 -2
- package/dist/tools/child-agent-worker.js +0 -212
- package/src/web-dashboard/public/assets/index-CjvoBhlz.js +0 -207
- package/src/web-dashboard/public/assets/index-CjvoBhlz.js.map +0 -1
|
@@ -1,34 +1,102 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* read_extract — Document-to-text extraction.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
4
|
+
* IMPLEMENTED:
|
|
5
|
+
* - Text-ish: plain text, Markdown, HTML, CSV, JSON, XML, YAML (no dependency)
|
|
6
|
+
* - PDF — `pdfjs-dist/legacy` with geometry-based row reconstruction (extract/pdf.ts)
|
|
7
|
+
* - DOCX — `mammoth`, HTML output flattened structure-preservingly (extract/docx.ts)
|
|
8
|
+
* - XLSX — SheetJS with cell number formats applied (extract/xlsx.ts)
|
|
9
|
+
* - PPTX — `fflate` + direct `<a:t>` reading (extract/pptx.ts)
|
|
10
|
+
*
|
|
11
|
+
* NOT IMPLEMENTED — refused with a typed `unsupported_format` and alternatives:
|
|
12
|
+
* legacy binary Office formats (.doc/.xls/.ppt), .rtf, .odt — see PENDING_FORMATS.
|
|
13
|
+
*
|
|
14
|
+
* History: this module used to read a PDF and a DOCX by `readFileSync(path, 'utf-8')`
|
|
15
|
+
* and stripping non-printable bytes, then report `success: true`. A PDF stores its
|
|
16
|
+
* text inside compressed content streams and a DOCX is a ZIP of XML parts, so that
|
|
17
|
+
* path could only ever return the container. On 2026-09-27 exactly that reached the
|
|
18
|
+
* model as a health report it then could not assess, with no signal that extraction
|
|
19
|
+
* had failed. Every extractor below either does the real work or refuses.
|
|
20
|
+
*
|
|
21
|
+
* The container readers are imported dynamically: pdf.js and SheetJS are megabytes
|
|
22
|
+
* that the CLI, the dashboard server and the tool registry should not pay for at
|
|
23
|
+
* startup, and a failure to load one is reported as `not_configured` rather than
|
|
24
|
+
* silently degrading.
|
|
25
|
+
*
|
|
26
|
+
* See TOOL_TRUTHFULNESS_TRACKER.md (P0.1, P0.2, P1.2–P1.5).
|
|
12
27
|
*/
|
|
13
28
|
import * as fs from 'fs';
|
|
14
29
|
import * as path from 'path';
|
|
30
|
+
import { refusalFields } from './tool-refusal.js';
|
|
31
|
+
import { htmlToText } from './extract/html-text.js';
|
|
32
|
+
// ─── Budgets ────────────────────────────────────────────────────────────────
|
|
33
|
+
/**
|
|
34
|
+
* Character budget for one extraction. Documents are unbounded input flowing into
|
|
35
|
+
* a bounded context window, so the output is capped and `metadata.truncated` says
|
|
36
|
+
* whether it was hit — a partial document is never presented as the whole one.
|
|
37
|
+
*/
|
|
38
|
+
const MAX_EXTRACT_CHARS = 40_000;
|
|
39
|
+
// ─── Format model ───────────────────────────────────────────────────────────
|
|
40
|
+
/** Formats with a working extractor. */
|
|
41
|
+
const IMPLEMENTED_FORMATS = new Set([
|
|
42
|
+
'.txt', '.md', '.markdown', '.text', '.log',
|
|
43
|
+
'.html', '.htm', '.csv', '.tsv', '.json', '.xml', '.yaml', '.yml',
|
|
44
|
+
'.pdf', '.docx', '.xlsx', '.pptx',
|
|
45
|
+
]);
|
|
46
|
+
/**
|
|
47
|
+
* Formats the tool does not read, with the reason surfaced to the model. Kept as a
|
|
48
|
+
* map so the gap is explicit and greppable rather than implied by a missing `case`.
|
|
49
|
+
*/
|
|
50
|
+
const PENDING_FORMATS = new Map([
|
|
51
|
+
['.doc', 'Legacy binary Word (.doc) is not supported — only the OOXML .docx container.'],
|
|
52
|
+
['.xls', 'Legacy binary Excel (.xls) is not supported — only the OOXML .xlsx container.'],
|
|
53
|
+
['.ppt', 'Legacy binary PowerPoint (.ppt) is not supported — only the OOXML .pptx container.'],
|
|
54
|
+
['.rtf', 'RTF is not supported.'],
|
|
55
|
+
['.odt', 'ODF (.odt) is not supported — only OOXML .docx.'],
|
|
56
|
+
['.ods', 'ODF (.ods) is not supported — only OOXML .xlsx.'],
|
|
57
|
+
]);
|
|
58
|
+
/** What to do instead, per unsupported format. */
|
|
59
|
+
const PENDING_ALTERNATIVES = {
|
|
60
|
+
'.doc': ['Save as .docx and read that', 'Convert with LibreOffice (`soffice --convert-to docx`)'],
|
|
61
|
+
'.xls': ['Save as .xlsx or CSV and read that'],
|
|
62
|
+
'.ppt': ['Save as .pptx and read that'],
|
|
63
|
+
'.rtf': ['Save as .docx or plain text and read that'],
|
|
64
|
+
'.odt': ['Save as .docx and read that'],
|
|
65
|
+
'.ods': ['Save as .xlsx or CSV and read that'],
|
|
66
|
+
};
|
|
67
|
+
/** Container formats whose reader is loaded on demand. */
|
|
68
|
+
const CONTAINER_FORMATS = new Set(['.pdf', '.docx', '.xlsx', '.pptx']);
|
|
15
69
|
// ─── Read Extract Manager ───────────────────────────────────────────────────
|
|
16
70
|
class ReadExtractManager {
|
|
17
|
-
supportedFormats = new Set([
|
|
18
|
-
'.txt', '.md', '.markdown', '.html', '.htm', '.csv', '.json', '.xml', '.yaml', '.yml',
|
|
19
|
-
'.pdf', '.docx', '.xlsx', '.pptx',
|
|
20
|
-
]);
|
|
21
71
|
/**
|
|
22
|
-
* Extract text from a file.
|
|
72
|
+
* Extract text from a file. Never throws: an unreadable, unsupported or
|
|
73
|
+
* package-less format comes back as `success: false` with a typed `code`.
|
|
23
74
|
*/
|
|
24
|
-
async extract(filePath) {
|
|
75
|
+
async extract(filePath, opts = {}) {
|
|
25
76
|
const ext = path.extname(filePath).toLowerCase();
|
|
26
|
-
if (
|
|
77
|
+
if (PENDING_FORMATS.has(ext)) {
|
|
78
|
+
return this.refused(ext, PENDING_FORMATS.get(ext), PENDING_ALTERNATIVES[ext] ?? []);
|
|
79
|
+
}
|
|
80
|
+
if (!IMPLEMENTED_FORMATS.has(ext)) {
|
|
81
|
+
// An image is a common arrival here (usually from a chat attachment). The reader
|
|
82
|
+
// cannot transcribe it, but a vision backend can — so say that plainly rather
|
|
83
|
+
// than only listing the formats this module knows.
|
|
84
|
+
const isImage = /^\.(png|jpe?g|gif|webp|bmp|tiff?)$/i.test(ext);
|
|
85
|
+
return this.refused(ext || '(no extension)', `Unsupported format: ${ext || '(no extension)'}.`, isImage
|
|
86
|
+
? [
|
|
87
|
+
'Use describe_image — a vision backend can read this image directly',
|
|
88
|
+
`Readable text formats: ${this.getSupportedFormats().join(', ')}`,
|
|
89
|
+
]
|
|
90
|
+
: [`Readable formats: ${this.getSupportedFormats().join(', ')}`]);
|
|
91
|
+
}
|
|
92
|
+
if (!fs.existsSync(filePath)) {
|
|
27
93
|
return {
|
|
28
94
|
text: '',
|
|
29
95
|
format: ext,
|
|
30
96
|
success: false,
|
|
31
|
-
|
|
97
|
+
code: 'no_data',
|
|
98
|
+
error: `No such file: ${filePath}`,
|
|
99
|
+
alternatives: ['Check the path (it is resolved relative to the workspace)'],
|
|
32
100
|
};
|
|
33
101
|
}
|
|
34
102
|
try {
|
|
@@ -36,12 +104,15 @@ class ReadExtractManager {
|
|
|
36
104
|
case '.txt':
|
|
37
105
|
case '.md':
|
|
38
106
|
case '.markdown':
|
|
107
|
+
case '.text':
|
|
108
|
+
case '.log':
|
|
39
109
|
return this.extractPlainText(filePath);
|
|
40
110
|
case '.html':
|
|
41
111
|
case '.htm':
|
|
42
112
|
return this.extractHTML(filePath);
|
|
43
113
|
case '.csv':
|
|
44
|
-
|
|
114
|
+
case '.tsv':
|
|
115
|
+
return this.extractDelimited(filePath, ext === '.tsv' ? '\t' : ',');
|
|
45
116
|
case '.json':
|
|
46
117
|
return this.extractJSON(filePath);
|
|
47
118
|
case '.xml':
|
|
@@ -50,15 +121,15 @@ class ReadExtractManager {
|
|
|
50
121
|
case '.yml':
|
|
51
122
|
return this.extractYAML(filePath);
|
|
52
123
|
case '.pdf':
|
|
53
|
-
return this.
|
|
124
|
+
return await this.extractPdf(filePath, opts);
|
|
54
125
|
case '.docx':
|
|
55
|
-
return this.
|
|
126
|
+
return await this.extractDocx(filePath);
|
|
56
127
|
case '.xlsx':
|
|
57
|
-
return this.
|
|
128
|
+
return await this.extractXlsx(filePath);
|
|
58
129
|
case '.pptx':
|
|
59
|
-
return this.
|
|
130
|
+
return await this.extractPptx(filePath);
|
|
60
131
|
default:
|
|
61
|
-
return
|
|
132
|
+
return this.refused(ext, `Unsupported format: ${ext}`, []);
|
|
62
133
|
}
|
|
63
134
|
}
|
|
64
135
|
catch (err) {
|
|
@@ -66,200 +137,465 @@ class ReadExtractManager {
|
|
|
66
137
|
text: '',
|
|
67
138
|
format: ext,
|
|
68
139
|
success: false,
|
|
69
|
-
|
|
140
|
+
code: 'unavailable',
|
|
141
|
+
error: err?.message ? String(err.message) : String(err),
|
|
70
142
|
};
|
|
71
143
|
}
|
|
72
144
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Extract CSV to text.
|
|
110
|
-
*/
|
|
111
|
-
extractCSV(filePath) {
|
|
112
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
113
|
-
const lines = content.split('\n').filter((l) => l.trim());
|
|
114
|
-
// Simple CSV to text
|
|
115
|
-
const text = lines.map((line) => {
|
|
116
|
-
const cells = line.split(',').map((c) => c.trim());
|
|
117
|
-
return cells.join(' | ');
|
|
118
|
-
}).join('\n');
|
|
145
|
+
// ─── Container extractors ─────────────────────────────────────────────────
|
|
146
|
+
async extractPdf(filePath, opts = {}) {
|
|
147
|
+
let mod;
|
|
148
|
+
try {
|
|
149
|
+
mod = await import('./extract/pdf.js');
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
return this.notConfigured('.pdf', 'the PDF reader (pdfjs-dist)', err);
|
|
153
|
+
}
|
|
154
|
+
let result;
|
|
155
|
+
try {
|
|
156
|
+
result = await mod.extractPdfText(new Uint8Array(fs.readFileSync(filePath)), {
|
|
157
|
+
maxChars: MAX_EXTRACT_CHARS,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
const encrypted = err instanceof mod.PdfExtractError && err.encrypted;
|
|
162
|
+
return {
|
|
163
|
+
text: '',
|
|
164
|
+
format: 'pdf',
|
|
165
|
+
success: false,
|
|
166
|
+
code: 'unavailable',
|
|
167
|
+
error: err instanceof Error ? err.message : String(err),
|
|
168
|
+
alternatives: encrypted
|
|
169
|
+
? ['Remove the password (print/export to a new PDF) and read that']
|
|
170
|
+
: ['Re-export the PDF', 'Send the pages as screenshots so describe_image can read them'],
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
// No page yielded text: a scanned document, not an empty one. Reported as a
|
|
174
|
+
// typed refusal because "success with empty text" is the defect this workstream
|
|
175
|
+
// removed — a caller cannot act on it.
|
|
176
|
+
if (result.pagesWithText === 0) {
|
|
177
|
+
return this.scannedPdfResult(filePath, result, opts);
|
|
178
|
+
}
|
|
119
179
|
return {
|
|
120
|
-
text,
|
|
121
|
-
format: '
|
|
180
|
+
text: result.text,
|
|
181
|
+
format: 'pdf',
|
|
122
182
|
success: true,
|
|
123
183
|
metadata: {
|
|
124
|
-
|
|
184
|
+
pages: result.pages,
|
|
185
|
+
pagesWithText: result.pagesWithText,
|
|
186
|
+
words: countWords(result.text),
|
|
187
|
+
truncated: result.truncated,
|
|
188
|
+
...(result.pagesWithoutText.length > 0
|
|
189
|
+
? { warnings: [`Page(s) ${result.pagesWithoutText.join(', ')} have no text layer (scanned images).`] }
|
|
190
|
+
: {}),
|
|
125
191
|
},
|
|
126
192
|
};
|
|
127
193
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
*/
|
|
131
|
-
extractJSON(filePath) {
|
|
132
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
194
|
+
async extractDocx(filePath) {
|
|
195
|
+
let mod;
|
|
133
196
|
try {
|
|
134
|
-
|
|
135
|
-
|
|
197
|
+
mod = await import('./extract/docx.js');
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
return this.notConfigured('.docx', 'the DOCX reader (mammoth)', err);
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
const result = await mod.extractDocxText(fs.readFileSync(filePath), { maxChars: MAX_EXTRACT_CHARS });
|
|
136
204
|
return {
|
|
137
|
-
text,
|
|
138
|
-
format: '
|
|
205
|
+
text: result.text,
|
|
206
|
+
format: 'docx',
|
|
139
207
|
success: true,
|
|
208
|
+
metadata: {
|
|
209
|
+
words: countWords(result.text),
|
|
210
|
+
truncated: result.truncated,
|
|
211
|
+
...(result.warnings.length > 0 ? { warnings: result.warnings } : {}),
|
|
212
|
+
},
|
|
140
213
|
};
|
|
141
214
|
}
|
|
142
|
-
catch {
|
|
215
|
+
catch (err) {
|
|
143
216
|
return {
|
|
144
|
-
text:
|
|
145
|
-
format: '
|
|
146
|
-
success:
|
|
217
|
+
text: '',
|
|
218
|
+
format: 'docx',
|
|
219
|
+
success: false,
|
|
220
|
+
code: 'unavailable',
|
|
221
|
+
error: err instanceof Error ? err.message : String(err),
|
|
222
|
+
alternatives: ['Re-export the document', 'Save it as .txt or .md and read that'],
|
|
147
223
|
};
|
|
148
224
|
}
|
|
149
225
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
226
|
+
async extractXlsx(filePath) {
|
|
227
|
+
let mod;
|
|
228
|
+
try {
|
|
229
|
+
mod = await import('./extract/xlsx.js');
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
return this.notConfigured('.xlsx', 'the spreadsheet reader (SheetJS)', err);
|
|
233
|
+
}
|
|
234
|
+
try {
|
|
235
|
+
const result = await mod.extractXlsxText(fs.readFileSync(filePath), { maxChars: MAX_EXTRACT_CHARS });
|
|
236
|
+
if (result.text.trim().length === 0) {
|
|
237
|
+
return {
|
|
238
|
+
text: '',
|
|
239
|
+
format: 'xlsx',
|
|
240
|
+
success: false,
|
|
241
|
+
code: 'no_data',
|
|
242
|
+
error: `The workbook has ${result.sheets.length} sheet(s) but no non-empty cells.`,
|
|
243
|
+
alternatives: ['Check the sheet is not empty, or export it as CSV'],
|
|
244
|
+
metadata: { sheets: result.sheets },
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
text: result.text,
|
|
249
|
+
format: 'xlsx',
|
|
250
|
+
success: true,
|
|
251
|
+
metadata: {
|
|
252
|
+
sheets: result.sheets,
|
|
253
|
+
rows: result.rows,
|
|
254
|
+
words: countWords(result.text),
|
|
255
|
+
truncated: result.truncated,
|
|
256
|
+
...(result.skippedSheets.length > 0
|
|
257
|
+
? { warnings: [`Sheet(s) not read (character budget): ${result.skippedSheets.join(', ')}`] }
|
|
258
|
+
: {}),
|
|
259
|
+
},
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
catch (err) {
|
|
263
|
+
return {
|
|
264
|
+
text: '',
|
|
265
|
+
format: 'xlsx',
|
|
266
|
+
success: false,
|
|
267
|
+
code: 'unavailable',
|
|
268
|
+
error: err instanceof Error ? err.message : String(err),
|
|
269
|
+
alternatives: ['Re-export the workbook', 'Export the sheet as CSV and read that'],
|
|
270
|
+
};
|
|
271
|
+
}
|
|
176
272
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
*/
|
|
180
|
-
extractPDF(filePath) {
|
|
181
|
-
// Simplified PDF extraction
|
|
182
|
-
// In production, use pdf-parse library
|
|
273
|
+
async extractPptx(filePath) {
|
|
274
|
+
let mod;
|
|
183
275
|
try {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
276
|
+
mod = await import('./extract/pptx.js');
|
|
277
|
+
}
|
|
278
|
+
catch (err) {
|
|
279
|
+
return this.notConfigured('.pptx', 'the ZIP reader (fflate)', err);
|
|
280
|
+
}
|
|
281
|
+
try {
|
|
282
|
+
const result = await mod.extractPptxText(fs.readFileSync(filePath), { maxChars: MAX_EXTRACT_CHARS });
|
|
283
|
+
if (result.text.trim().length === 0) {
|
|
284
|
+
return {
|
|
285
|
+
text: '',
|
|
286
|
+
format: 'pptx',
|
|
287
|
+
success: false,
|
|
288
|
+
code: 'no_data',
|
|
289
|
+
error: `All ${result.slides} slide(s) are text-free (images only).`,
|
|
290
|
+
alternatives: ['Send the slides as screenshots so the vision model can read them'],
|
|
291
|
+
metadata: { slides: result.slides },
|
|
292
|
+
};
|
|
293
|
+
}
|
|
190
294
|
return {
|
|
191
|
-
text: text
|
|
192
|
-
format: '
|
|
295
|
+
text: result.text,
|
|
296
|
+
format: 'pptx',
|
|
193
297
|
success: true,
|
|
194
298
|
metadata: {
|
|
195
|
-
|
|
299
|
+
slides: result.slides,
|
|
300
|
+
words: countWords(result.text),
|
|
301
|
+
truncated: result.truncated,
|
|
302
|
+
...(result.emptySlides.length > 0
|
|
303
|
+
? { warnings: [`Slide(s) with no text: ${result.emptySlides.join(', ')}`] }
|
|
304
|
+
: {}),
|
|
196
305
|
},
|
|
197
306
|
};
|
|
198
307
|
}
|
|
199
|
-
catch {
|
|
308
|
+
catch (err) {
|
|
200
309
|
return {
|
|
201
310
|
text: '',
|
|
202
|
-
format: '
|
|
311
|
+
format: 'pptx',
|
|
203
312
|
success: false,
|
|
204
|
-
|
|
313
|
+
code: 'unavailable',
|
|
314
|
+
error: err instanceof Error ? err.message : String(err),
|
|
315
|
+
alternatives: ['Re-export the presentation', 'Export the slides as images'],
|
|
205
316
|
};
|
|
206
317
|
}
|
|
207
318
|
}
|
|
208
319
|
/**
|
|
209
|
-
*
|
|
320
|
+
* A PDF with no text layer: either transcribe it (when the caller asked for OCR and
|
|
321
|
+
* the route is available) or refuse with the way to ask. Both outcomes are explicit.
|
|
210
322
|
*/
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
323
|
+
async scannedPdfResult(filePath, result, opts) {
|
|
324
|
+
const base = {
|
|
325
|
+
pages: result.pages,
|
|
326
|
+
pagesWithText: 0,
|
|
327
|
+
truncated: result.truncated,
|
|
328
|
+
};
|
|
329
|
+
const alternatives = [
|
|
330
|
+
opts.ocr
|
|
331
|
+
? 'Install a PDF rasteriser (Poppler: pdftoppm/pdftocairo) and configure a vision backend'
|
|
332
|
+
: 'Call read_extract again with ocr:true to transcribe the pages with the vision model',
|
|
333
|
+
'Send the page as a screenshot so the vision model can read it (describe_image)',
|
|
334
|
+
'Paste the report text',
|
|
335
|
+
];
|
|
336
|
+
if (!opts.ocr) {
|
|
337
|
+
return {
|
|
338
|
+
text: '',
|
|
339
|
+
format: 'pdf',
|
|
340
|
+
success: false,
|
|
341
|
+
code: 'no_data',
|
|
342
|
+
error: `The PDF has ${result.pages} page(s) but no text layer — it is a scan/image, so there is no text to extract.`,
|
|
343
|
+
alternatives,
|
|
344
|
+
metadata: base,
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
// OCR was requested — attempt it, and if a prerequisite is missing say WHICH.
|
|
214
348
|
try {
|
|
215
|
-
const
|
|
216
|
-
const
|
|
217
|
-
.replace(/<[^>]+>/g, ' ')
|
|
218
|
-
.replace(/\s+/g, ' ')
|
|
219
|
-
.trim();
|
|
349
|
+
const ocr = await import('./extract/pdf-ocr.js');
|
|
350
|
+
const transcribed = await ocr.ocrScannedPdf(filePath, result.pages, opts.ocrOptions ?? {});
|
|
220
351
|
return {
|
|
221
|
-
text: text
|
|
222
|
-
format: '
|
|
352
|
+
text: transcribed.text,
|
|
353
|
+
format: 'pdf',
|
|
223
354
|
success: true,
|
|
355
|
+
metadata: {
|
|
356
|
+
...base,
|
|
357
|
+
ocr: true,
|
|
358
|
+
ocrRenderer: transcribed.renderer,
|
|
359
|
+
words: countWords(transcribed.text),
|
|
360
|
+
truncated: transcribed.truncated,
|
|
361
|
+
warnings: [
|
|
362
|
+
'Text recovered by OCR from rendered page images — a transcription, not a parsed '
|
|
363
|
+
+ 'text layer. Verify digits (lab values, dates, doses) against the original.',
|
|
364
|
+
],
|
|
365
|
+
},
|
|
224
366
|
};
|
|
225
367
|
}
|
|
226
|
-
catch {
|
|
368
|
+
catch (err) {
|
|
369
|
+
const ocr = await import('./extract/pdf-ocr.js');
|
|
370
|
+
const code = err instanceof ocr.PdfOcrError ? err.code : 'unavailable';
|
|
227
371
|
return {
|
|
228
372
|
text: '',
|
|
229
|
-
format: '
|
|
373
|
+
format: 'pdf',
|
|
230
374
|
success: false,
|
|
231
|
-
|
|
375
|
+
code,
|
|
376
|
+
error: err instanceof Error ? err.message : String(err),
|
|
377
|
+
alternatives,
|
|
378
|
+
metadata: base,
|
|
232
379
|
};
|
|
233
380
|
}
|
|
234
381
|
}
|
|
235
|
-
/**
|
|
236
|
-
|
|
237
|
-
*/
|
|
238
|
-
extractXLSX(filePath) {
|
|
382
|
+
/** An optional reader that failed to load is a typed refusal, never a silent gap. */
|
|
383
|
+
notConfigured(format, what, err) {
|
|
239
384
|
return {
|
|
240
385
|
text: '',
|
|
241
|
-
format
|
|
386
|
+
format,
|
|
242
387
|
success: false,
|
|
243
|
-
error:
|
|
388
|
+
error: `${what} is not available in this install, so ${format} could not be read (${err instanceof Error ? err.message : String(err)}).`,
|
|
389
|
+
...refusalFields('not_configured', [`Reinstall dependencies (npm install) to restore ${what}`]),
|
|
244
390
|
};
|
|
245
391
|
}
|
|
246
|
-
/**
|
|
247
|
-
|
|
248
|
-
*/
|
|
249
|
-
extractPPTX(filePath) {
|
|
392
|
+
/** A refusal in the module's result shape (empty text, no fabricated metadata). */
|
|
393
|
+
refused(format, reason, alternatives) {
|
|
250
394
|
return {
|
|
251
395
|
text: '',
|
|
252
|
-
format
|
|
396
|
+
format,
|
|
253
397
|
success: false,
|
|
254
|
-
error:
|
|
398
|
+
error: reason,
|
|
399
|
+
...refusalFields('unsupported_format', alternatives),
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
// ─── Text extractors ──────────────────────────────────────────────────────
|
|
403
|
+
/**
|
|
404
|
+
* A NUL byte in the first 8 KB means the file is not text, whatever extension it
|
|
405
|
+
* carries — the same probe `read_file` uses (`coding-tools.ts:looksBinary`). Without
|
|
406
|
+
* it a mislabelled binary reaches the model as mojibake, which is the very class
|
|
407
|
+
* of defect this module now refuses.
|
|
408
|
+
*/
|
|
409
|
+
looksBinary(filePath) {
|
|
410
|
+
const fd = fs.openSync(filePath, 'r');
|
|
411
|
+
try {
|
|
412
|
+
const probe = Buffer.alloc(8192);
|
|
413
|
+
const read = fs.readSync(fd, probe, 0, probe.length, 0);
|
|
414
|
+
return probe.subarray(0, read).includes(0);
|
|
415
|
+
}
|
|
416
|
+
finally {
|
|
417
|
+
fs.closeSync(fd);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
extractPlainText(filePath) {
|
|
421
|
+
if (this.looksBinary(filePath)) {
|
|
422
|
+
return this.refused('text', `'${path.basename(filePath)}' looks binary (a text/Markdown file with NUL bytes) — its bytes are not text.`, ['Check the real file type and use the matching reader']);
|
|
423
|
+
}
|
|
424
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
425
|
+
const truncated = content.length > MAX_EXTRACT_CHARS;
|
|
426
|
+
return {
|
|
427
|
+
text: truncated ? `${content.slice(0, MAX_EXTRACT_CHARS)}\n…[truncated]` : content,
|
|
428
|
+
format: 'text',
|
|
429
|
+
success: true,
|
|
430
|
+
metadata: {
|
|
431
|
+
words: countWords(content),
|
|
432
|
+
truncated,
|
|
433
|
+
},
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* HTML → text. Structure-preserving (`htmlToText`): cells stay on one line so a
|
|
438
|
+
* table's value/column pairing survives. Layout (CSS) is not reconstructed and is
|
|
439
|
+
* not claimed to be.
|
|
440
|
+
*/
|
|
441
|
+
extractHTML(filePath) {
|
|
442
|
+
const text = htmlToText(fs.readFileSync(filePath, 'utf-8'));
|
|
443
|
+
const truncated = text.length > MAX_EXTRACT_CHARS;
|
|
444
|
+
return {
|
|
445
|
+
text: truncated ? `${text.slice(0, MAX_EXTRACT_CHARS)}\n…[truncated]` : text,
|
|
446
|
+
format: 'html',
|
|
447
|
+
success: true,
|
|
448
|
+
metadata: {
|
|
449
|
+
words: countWords(text),
|
|
450
|
+
truncated,
|
|
451
|
+
},
|
|
255
452
|
};
|
|
256
453
|
}
|
|
257
454
|
/**
|
|
258
|
-
*
|
|
455
|
+
* CSV/TSV → text, with RFC 4180 quoting rules rather than `split(',')`. The naive
|
|
456
|
+
* split silently corrupted any row containing a quoted separator — a lab row like
|
|
457
|
+
* `Glucose,112,"HIGH, range 70-99"` became four fields with the reference range torn
|
|
458
|
+
* apart, while the result still reported success.
|
|
259
459
|
*/
|
|
460
|
+
extractDelimited(filePath, delimiter) {
|
|
461
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
462
|
+
const lines = content.split(/\r?\n/).filter((l) => l.trim());
|
|
463
|
+
const rows = lines.map((line) => parseDelimitedRow(line, delimiter));
|
|
464
|
+
// Rows stay themselves — separated by newlines, cells by ` | ` — so the table
|
|
465
|
+
// shape the file encoded is the shape the model reads.
|
|
466
|
+
const text = rows.map((cells) => cells.join(' | ')).join('\n');
|
|
467
|
+
const truncated = text.length > MAX_EXTRACT_CHARS;
|
|
468
|
+
return {
|
|
469
|
+
text: truncated ? `${text.slice(0, MAX_EXTRACT_CHARS)}\n…[truncated]` : text,
|
|
470
|
+
format: delimiter === '\t' ? 'tsv' : 'csv',
|
|
471
|
+
success: true,
|
|
472
|
+
metadata: {
|
|
473
|
+
words: countWords(text),
|
|
474
|
+
rows: rows.length,
|
|
475
|
+
truncated,
|
|
476
|
+
},
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
extractJSON(filePath) {
|
|
480
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
481
|
+
let text;
|
|
482
|
+
let valid = true;
|
|
483
|
+
try {
|
|
484
|
+
text = JSON.stringify(JSON.parse(content), null, 2);
|
|
485
|
+
}
|
|
486
|
+
catch {
|
|
487
|
+
// Not valid JSON — return the raw text, and say so rather than implying a parse.
|
|
488
|
+
text = content;
|
|
489
|
+
valid = false;
|
|
490
|
+
}
|
|
491
|
+
const truncated = text.length > MAX_EXTRACT_CHARS;
|
|
492
|
+
return {
|
|
493
|
+
text: truncated ? `${text.slice(0, MAX_EXTRACT_CHARS)}\n…[truncated]` : text,
|
|
494
|
+
format: 'json',
|
|
495
|
+
success: true,
|
|
496
|
+
metadata: {
|
|
497
|
+
truncated,
|
|
498
|
+
// A success result never carries an `error` string: the two together are
|
|
499
|
+
// exactly the ambiguity ("did it work?") this module removes.
|
|
500
|
+
...(valid ? {} : { warnings: ['File is not valid JSON — raw text returned'] }),
|
|
501
|
+
},
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
extractXML(filePath) {
|
|
505
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
506
|
+
const text = htmlToText(content);
|
|
507
|
+
const truncated = text.length > MAX_EXTRACT_CHARS;
|
|
508
|
+
return {
|
|
509
|
+
text: truncated ? `${text.slice(0, MAX_EXTRACT_CHARS)}\n…[truncated]` : text,
|
|
510
|
+
format: 'xml',
|
|
511
|
+
success: true,
|
|
512
|
+
metadata: { words: countWords(text), truncated },
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
extractYAML(filePath) {
|
|
516
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
517
|
+
const truncated = content.length > MAX_EXTRACT_CHARS;
|
|
518
|
+
return {
|
|
519
|
+
text: truncated ? `${content.slice(0, MAX_EXTRACT_CHARS)}\n…[truncated]` : content,
|
|
520
|
+
format: 'yaml',
|
|
521
|
+
success: true,
|
|
522
|
+
metadata: { words: countWords(content), truncated },
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
// ─── Capability surface ───────────────────────────────────────────────────
|
|
526
|
+
/** Formats with a working extractor. Feeds the tool description. */
|
|
260
527
|
getSupportedFormats() {
|
|
261
|
-
return Array.from(
|
|
528
|
+
return Array.from(IMPLEMENTED_FORMATS);
|
|
529
|
+
}
|
|
530
|
+
/** Formats the description does not advertise because nothing reads them. */
|
|
531
|
+
getPendingFormats() {
|
|
532
|
+
return Array.from(PENDING_FORMATS, ([format, reason]) => ({ format, reason }));
|
|
533
|
+
}
|
|
534
|
+
/** Whether a specific path's extension has a working extractor. */
|
|
535
|
+
isFormatAvailable(filePath) {
|
|
536
|
+
return IMPLEMENTED_FORMATS.has(path.extname(filePath).toLowerCase());
|
|
537
|
+
}
|
|
538
|
+
/** Whether a path's format needs a heavy on-demand reader. */
|
|
539
|
+
isContainerFormat(filePath) {
|
|
540
|
+
return CONTAINER_FORMATS.has(path.extname(filePath).toLowerCase());
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
544
|
+
function countWords(text) {
|
|
545
|
+
return text.split(/\s+/).filter(Boolean).length;
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Split one delimited line into fields, honouring `"…"` quoting and escaped `""`.
|
|
549
|
+
* Exported for tests. `parseCsvRow` is kept as the comma-specific alias.
|
|
550
|
+
*/
|
|
551
|
+
export function parseDelimitedRow(line, delimiter = ',') {
|
|
552
|
+
const cells = [];
|
|
553
|
+
let field = '';
|
|
554
|
+
let inQuotes = false;
|
|
555
|
+
for (let i = 0; i < line.length; i++) {
|
|
556
|
+
const ch = line[i];
|
|
557
|
+
if (inQuotes) {
|
|
558
|
+
if (ch === '"') {
|
|
559
|
+
if (line[i + 1] === '"') {
|
|
560
|
+
field += '"';
|
|
561
|
+
i++;
|
|
562
|
+
}
|
|
563
|
+
else
|
|
564
|
+
inQuotes = false;
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
field += ch;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
else if (ch === '"') {
|
|
571
|
+
inQuotes = true;
|
|
572
|
+
}
|
|
573
|
+
else if (ch === delimiter) {
|
|
574
|
+
cells.push(field.trim());
|
|
575
|
+
field = '';
|
|
576
|
+
}
|
|
577
|
+
else {
|
|
578
|
+
field += ch;
|
|
579
|
+
}
|
|
262
580
|
}
|
|
581
|
+
cells.push(field.trim());
|
|
582
|
+
return cells;
|
|
583
|
+
}
|
|
584
|
+
/** CSV-specific alias (kept for callers/tests that name the comma case). */
|
|
585
|
+
export function parseCsvRow(line) {
|
|
586
|
+
return parseDelimitedRow(line, ',');
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Probe mirrored into the `read_extract` tool description: true when the path's
|
|
590
|
+
* format can actually be extracted. Callers use it to choose a tool *before*
|
|
591
|
+
* spending a step on a refusal.
|
|
592
|
+
*/
|
|
593
|
+
export function isReadExtractAvailable(filePath) {
|
|
594
|
+
return getReadExtractManager().isFormatAvailable(filePath);
|
|
595
|
+
}
|
|
596
|
+
/** Formats with a working extractor (module-level convenience). */
|
|
597
|
+
export function getReadExtractFormats() {
|
|
598
|
+
return getReadExtractManager().getSupportedFormats();
|
|
263
599
|
}
|
|
264
600
|
// ─── Singleton ──────────────────────────────────────────────────────────────
|
|
265
601
|
let _instance = null;
|
|
@@ -268,5 +604,5 @@ export function getReadExtractManager() {
|
|
|
268
604
|
_instance = new ReadExtractManager();
|
|
269
605
|
return _instance;
|
|
270
606
|
}
|
|
271
|
-
export { ReadExtractManager };
|
|
607
|
+
export { ReadExtractManager, MAX_EXTRACT_CHARS };
|
|
272
608
|
//# sourceMappingURL=read-extract.js.map
|