@qvac/harness 0.0.0 → 0.1.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/LICENSE.md +198 -0
- package/NOTICE.md +13 -0
- package/README.md +68 -0
- package/SECURITY.md +6 -0
- package/dist/harness.bundle +48339 -0
- package/dist/harness.cjs +18 -0
- package/dist/harness.d.ts +8 -0
- package/dist/prebuilds-manifest.json +379 -0
- package/dist-lib/index.d.ts +240 -0
- package/dist-lib/index.js +1063 -0
- package/dist-lib/lib/audio-transcode-bare.d.ts +2 -0
- package/dist-lib/lib/audio-transcode-bare.js +145 -0
- package/dist-lib/lib/audio-transcode-node.d.ts +2 -0
- package/dist-lib/lib/audio-transcode-node.js +6 -0
- package/dist-lib/lib/capabilities/audio-resample.d.ts +14 -0
- package/dist-lib/lib/capabilities/audio-resample.js +72 -0
- package/dist-lib/lib/capabilities/completion.d.ts +288 -0
- package/dist-lib/lib/capabilities/completion.js +1077 -0
- package/dist-lib/lib/capabilities/download.d.ts +46 -0
- package/dist-lib/lib/capabilities/download.js +124 -0
- package/dist-lib/lib/capabilities/embed.d.ts +20 -0
- package/dist-lib/lib/capabilities/embed.js +13 -0
- package/dist-lib/lib/capabilities/kv-cache.d.ts +13 -0
- package/dist-lib/lib/capabilities/kv-cache.js +21 -0
- package/dist-lib/lib/capabilities/prompt-prefix.d.ts +6 -0
- package/dist-lib/lib/capabilities/prompt-prefix.js +10 -0
- package/dist-lib/lib/capabilities/speech-lexicon.d.ts +5 -0
- package/dist-lib/lib/capabilities/speech-lexicon.js +32 -0
- package/dist-lib/lib/capabilities/speech-text.d.ts +6 -0
- package/dist-lib/lib/capabilities/speech-text.js +79 -0
- package/dist-lib/lib/capabilities/tool-names.d.ts +3 -0
- package/dist-lib/lib/capabilities/tool-names.js +3 -0
- package/dist-lib/lib/capabilities/tool-selection.d.ts +43 -0
- package/dist-lib/lib/capabilities/tool-selection.js +60 -0
- package/dist-lib/lib/capabilities/tool-turns.d.ts +9 -0
- package/dist-lib/lib/capabilities/tool-turns.js +101 -0
- package/dist-lib/lib/capabilities/usage-breakdown.d.ts +27 -0
- package/dist-lib/lib/capabilities/usage-breakdown.js +44 -0
- package/dist-lib/lib/capabilities/vision-history.d.ts +3 -0
- package/dist-lib/lib/capabilities/vision-history.js +21 -0
- package/dist-lib/lib/capabilities/voice.d.ts +78 -0
- package/dist-lib/lib/capabilities/voice.js +189 -0
- package/dist-lib/lib/connect.d.ts +76 -0
- package/dist-lib/lib/connect.js +789 -0
- package/dist-lib/lib/context-window.d.ts +7 -0
- package/dist-lib/lib/context-window.js +90 -0
- package/dist-lib/lib/contract-types.d.ts +210 -0
- package/dist-lib/lib/contract-types.js +1 -0
- package/dist-lib/lib/diagram-repair.d.ts +21 -0
- package/dist-lib/lib/diagram-repair.js +58 -0
- package/dist-lib/lib/dns-lookup.d.ts +1 -0
- package/dist-lib/lib/dns-lookup.js +13 -0
- package/dist-lib/lib/error-fields.d.ts +2 -0
- package/dist-lib/lib/error-fields.js +8 -0
- package/dist-lib/lib/fetch-node.d.ts +1 -0
- package/dist-lib/lib/fetch-node.js +1 -0
- package/dist-lib/lib/hardware/capability-probe.d.ts +9 -0
- package/dist-lib/lib/hardware/capability-probe.js +99 -0
- package/dist-lib/lib/hardware/gpu-classify.d.ts +2 -0
- package/dist-lib/lib/hardware/gpu-classify.js +32 -0
- package/dist-lib/lib/hardware/gpu-probe-addon.d.ts +2 -0
- package/dist-lib/lib/hardware/gpu-probe-addon.js +42 -0
- package/dist-lib/lib/hardware/gpu-stats.bare.d.ts +1 -0
- package/dist-lib/lib/hardware/gpu-stats.bare.js +24 -0
- package/dist-lib/lib/hardware/gpu-stats.stub.d.ts +1 -0
- package/dist-lib/lib/hardware/gpu-stats.stub.js +3 -0
- package/dist-lib/lib/hardware/memory-budget.d.ts +8 -0
- package/dist-lib/lib/hardware/memory-budget.js +1 -0
- package/dist-lib/lib/hardware/parsers.d.ts +7 -0
- package/dist-lib/lib/hardware/parsers.js +41 -0
- package/dist-lib/lib/headers-bare.d.ts +1 -0
- package/dist-lib/lib/headers-bare.js +1 -0
- package/dist-lib/lib/headers-node.d.ts +4 -0
- package/dist-lib/lib/headers-node.js +1 -0
- package/dist-lib/lib/helpers/buffer-burst.d.ts +1 -0
- package/dist-lib/lib/helpers/buffer-burst.js +20 -0
- package/dist-lib/lib/helpers/control-tokens.d.ts +7 -0
- package/dist-lib/lib/helpers/control-tokens.js +32 -0
- package/dist-lib/lib/helpers/join-guard.d.ts +6 -0
- package/dist-lib/lib/helpers/join-guard.js +46 -0
- package/dist-lib/lib/helpers/markup-stream-filter.d.ts +5 -0
- package/dist-lib/lib/helpers/markup-stream-filter.js +75 -0
- package/dist-lib/lib/helpers/race-abort.d.ts +5 -0
- package/dist-lib/lib/helpers/race-abort.js +18 -0
- package/dist-lib/lib/helpers/retry-memo.d.ts +5 -0
- package/dist-lib/lib/helpers/retry-memo.js +12 -0
- package/dist-lib/lib/helpers/run-outcome.d.ts +33 -0
- package/dist-lib/lib/helpers/run-outcome.js +204 -0
- package/dist-lib/lib/helpers/spawn-path.d.ts +5 -0
- package/dist-lib/lib/helpers/spawn-path.js +57 -0
- package/dist-lib/lib/helpers/text-coalescer.d.ts +15 -0
- package/dist-lib/lib/helpers/text-coalescer.js +34 -0
- package/dist-lib/lib/helpers/thinking.d.ts +8 -0
- package/dist-lib/lib/helpers/thinking.js +95 -0
- package/dist-lib/lib/helpers/tool-call-markup.d.ts +20 -0
- package/dist-lib/lib/helpers/tool-call-markup.js +201 -0
- package/dist-lib/lib/helpers/tool-intent.d.ts +7 -0
- package/dist-lib/lib/helpers/tool-intent.js +21 -0
- package/dist-lib/lib/helpers/tool-label.d.ts +8 -0
- package/dist-lib/lib/helpers/tool-label.js +131 -0
- package/dist-lib/lib/hooks/built-in/arg-repair.d.ts +5 -0
- package/dist-lib/lib/hooks/built-in/arg-repair.js +88 -0
- package/dist-lib/lib/hooks/built-in/egress.d.ts +5 -0
- package/dist-lib/lib/hooks/built-in/egress.js +29 -0
- package/dist-lib/lib/hooks/built-in/index.d.ts +3 -0
- package/dist-lib/lib/hooks/built-in/index.js +3 -0
- package/dist-lib/lib/hooks/built-in/skill-catalog.d.ts +10 -0
- package/dist-lib/lib/hooks/built-in/skill-catalog.js +17 -0
- package/dist-lib/lib/hooks/pipeline.d.ts +20 -0
- package/dist-lib/lib/hooks/pipeline.js +49 -0
- package/dist-lib/lib/hooks/registry.d.ts +2 -0
- package/dist-lib/lib/hooks/registry.js +6 -0
- package/dist-lib/lib/hooks/run.d.ts +5 -0
- package/dist-lib/lib/hooks/run.js +83 -0
- package/dist-lib/lib/hooks/types.d.ts +57 -0
- package/dist-lib/lib/hooks/types.js +1 -0
- package/dist-lib/lib/log.d.ts +5 -0
- package/dist-lib/lib/log.js +37 -0
- package/dist-lib/lib/model-download-progress.d.ts +22 -0
- package/dist-lib/lib/model-download-progress.js +95 -0
- package/dist-lib/lib/models/context.d.ts +5 -0
- package/dist-lib/lib/models/context.js +12 -0
- package/dist-lib/lib/models/embed-config.d.ts +14 -0
- package/dist-lib/lib/models/embed-config.js +31 -0
- package/dist-lib/lib/models/gpu-selection.d.ts +3 -0
- package/dist-lib/lib/models/gpu-selection.js +26 -0
- package/dist-lib/lib/models/kv-cache.d.ts +4 -0
- package/dist-lib/lib/models/kv-cache.js +6 -0
- package/dist-lib/lib/models/llm-presets.d.ts +10 -0
- package/dist-lib/lib/models/llm-presets.js +58 -0
- package/dist-lib/lib/models/model-catalog-constants.d.ts +29 -0
- package/dist-lib/lib/models/model-catalog-constants.js +103 -0
- package/dist-lib/lib/models/model-catalog.d.ts +125 -0
- package/dist-lib/lib/models/model-catalog.js +371 -0
- package/dist-lib/lib/models/model-delete.d.ts +18 -0
- package/dist-lib/lib/models/model-delete.js +47 -0
- package/dist-lib/lib/models/model-handle.d.ts +18 -0
- package/dist-lib/lib/models/model-handle.js +33 -0
- package/dist-lib/lib/models/model-list.d.ts +42 -0
- package/dist-lib/lib/models/model-list.js +123 -0
- package/dist-lib/lib/models/model-pool.d.ts +116 -0
- package/dist-lib/lib/models/model-pool.js +356 -0
- package/dist-lib/lib/models/model-source.d.ts +6 -0
- package/dist-lib/lib/models/model-source.js +21 -0
- package/dist-lib/lib/models/music-catalog.d.ts +12 -0
- package/dist-lib/lib/models/music-catalog.js +26 -0
- package/dist-lib/lib/models/opencl-cache.d.ts +5 -0
- package/dist-lib/lib/models/opencl-cache.js +50 -0
- package/dist-lib/lib/models/sdk-faults.d.ts +21 -0
- package/dist-lib/lib/models/sdk-faults.js +66 -0
- package/dist-lib/lib/models/tool-dialect.d.ts +2 -0
- package/dist-lib/lib/models/tool-dialect.js +19 -0
- package/dist-lib/lib/models/tts-model-default.d.ts +3 -0
- package/dist-lib/lib/models/tts-model-default.js +13 -0
- package/dist-lib/lib/no-redirect-fetch-bare.d.ts +15 -0
- package/dist-lib/lib/no-redirect-fetch-bare.js +59 -0
- package/dist-lib/lib/no-redirect-fetch-impl.d.ts +39 -0
- package/dist-lib/lib/no-redirect-fetch-impl.js +80 -0
- package/dist-lib/lib/no-redirect-fetch-node.d.ts +4 -0
- package/dist-lib/lib/no-redirect-fetch-node.js +52 -0
- package/dist-lib/lib/prompt.d.ts +22 -0
- package/dist-lib/lib/prompt.js +77 -0
- package/dist-lib/lib/queue.d.ts +9 -0
- package/dist-lib/lib/queue.js +48 -0
- package/dist-lib/lib/resolution-detector.d.ts +5 -0
- package/dist-lib/lib/resolution-detector.js +100 -0
- package/dist-lib/lib/rpc-session.d.ts +8 -0
- package/dist-lib/lib/rpc-session.js +20 -0
- package/dist-lib/lib/sdk-config-loader.node.d.ts +1 -0
- package/dist-lib/lib/sdk-config-loader.node.js +1 -0
- package/dist-lib/lib/sdk-loader.d.ts +30 -0
- package/dist-lib/lib/sdk-loader.js +53 -0
- package/dist-lib/lib/sdk-storage.d.ts +8 -0
- package/dist-lib/lib/sdk-storage.js +24 -0
- package/dist-lib/lib/serve.d.ts +3 -0
- package/dist-lib/lib/serve.js +612 -0
- package/dist-lib/lib/spawn.d.ts +62 -0
- package/dist-lib/lib/spawn.js +71 -0
- package/dist-lib/lib/staging.d.ts +4 -0
- package/dist-lib/lib/staging.js +28 -0
- package/dist-lib/lib/storage.d.ts +18 -0
- package/dist-lib/lib/storage.js +26 -0
- package/dist-lib/lib/tmp-path.d.ts +7 -0
- package/dist-lib/lib/tmp-path.js +17 -0
- package/dist-lib/lib/tool-call-display.d.ts +21 -0
- package/dist-lib/lib/tool-call-display.js +1 -0
- package/dist-lib/lib/tools/catalog.d.ts +13 -0
- package/dist-lib/lib/tools/catalog.js +13 -0
- package/dist-lib/lib/tools/create-documents.d.ts +3 -0
- package/dist-lib/lib/tools/create-documents.js +87 -0
- package/dist-lib/lib/tools/edit-documents.d.ts +3 -0
- package/dist-lib/lib/tools/edit-documents.js +122 -0
- package/dist-lib/lib/tools/edit-image.d.ts +25 -0
- package/dist-lib/lib/tools/edit-image.js +271 -0
- package/dist-lib/lib/tools/exec/adapters/adapter.d.ts +27 -0
- package/dist-lib/lib/tools/exec/adapters/adapter.js +1 -0
- package/dist-lib/lib/tools/exec/adapters/python/attachments.d.ts +26 -0
- package/dist-lib/lib/tools/exec/adapters/python/attachments.js +160 -0
- package/dist-lib/lib/tools/exec/adapters/python/create-effect.d.ts +7 -0
- package/dist-lib/lib/tools/exec/adapters/python/create-effect.js +290 -0
- package/dist-lib/lib/tools/exec/adapters/python/loader.d.ts +11 -0
- package/dist-lib/lib/tools/exec/adapters/python/loader.js +94 -0
- package/dist-lib/lib/tools/exec/adapters/python/memfs.d.ts +47 -0
- package/dist-lib/lib/tools/exec/adapters/python/memfs.js +85 -0
- package/dist-lib/lib/tools/exec/adapters/python/output-policy.d.ts +13 -0
- package/dist-lib/lib/tools/exec/adapters/python/output-policy.js +129 -0
- package/dist-lib/lib/tools/exec/adapters/python/pyodide.d.ts +19 -0
- package/dist-lib/lib/tools/exec/adapters/python/pyodide.js +107 -0
- package/dist-lib/lib/tools/exec/adapters/python/python-adapter.d.ts +75 -0
- package/dist-lib/lib/tools/exec/adapters/python/python-adapter.js +1094 -0
- package/dist-lib/lib/tools/exec/adapters/python/run-session.d.ts +75 -0
- package/dist-lib/lib/tools/exec/adapters/python/run-session.js +273 -0
- package/dist-lib/lib/tools/exec/adapters/python/wheels.d.ts +38 -0
- package/dist-lib/lib/tools/exec/adapters/python/wheels.js +102 -0
- package/dist-lib/lib/tools/exec/adapters/python/worker/client.d.ts +7 -0
- package/dist-lib/lib/tools/exec/adapters/python/worker/client.js +188 -0
- package/dist-lib/lib/tools/exec/adapters/python/worker/entry.d.ts +1 -0
- package/dist-lib/lib/tools/exec/adapters/python/worker/entry.js +105 -0
- package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.d.ts +38 -0
- package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.js +41 -0
- package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-bare.d.ts +2 -0
- package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-bare.js +30 -0
- package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.d.ts +13 -0
- package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.js +45 -0
- package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.d.ts +12 -0
- package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.js +20 -0
- package/dist-lib/lib/tools/exec/obsidian/cli-process.d.ts +8 -0
- package/dist-lib/lib/tools/exec/obsidian/cli-process.js +74 -0
- package/dist-lib/lib/tools/exec/obsidian/cli.d.ts +18 -0
- package/dist-lib/lib/tools/exec/obsidian/cli.js +153 -0
- package/dist-lib/lib/tools/exec/obsidian/command.d.ts +5 -0
- package/dist-lib/lib/tools/exec/obsidian/command.js +18 -0
- package/dist-lib/lib/tools/exec/obsidian/guidance.d.ts +5 -0
- package/dist-lib/lib/tools/exec/obsidian/guidance.js +18 -0
- package/dist-lib/lib/tools/exec/obsidian/note-name.d.ts +1 -0
- package/dist-lib/lib/tools/exec/obsidian/note-name.js +6 -0
- package/dist-lib/lib/tools/exec/obsidian/output.d.ts +1 -0
- package/dist-lib/lib/tools/exec/obsidian/output.js +31 -0
- package/dist-lib/lib/tools/exec/obsidian/route.d.ts +19 -0
- package/dist-lib/lib/tools/exec/obsidian/route.js +85 -0
- package/dist-lib/lib/tools/exec/obsidian/safe-path.d.ts +3 -0
- package/dist-lib/lib/tools/exec/obsidian/safe-path.js +56 -0
- package/dist-lib/lib/tools/exec/obsidian/vault-create.d.ts +1 -0
- package/dist-lib/lib/tools/exec/obsidian/vault-create.js +40 -0
- package/dist-lib/lib/tools/exec/obsidian/vault-fs.d.ts +3 -0
- package/dist-lib/lib/tools/exec/obsidian/vault-fs.js +57 -0
- package/dist-lib/lib/tools/exec/obsidian/vault-paths.d.ts +20 -0
- package/dist-lib/lib/tools/exec/obsidian/vault-paths.js +171 -0
- package/dist-lib/lib/tools/exec/obsidian/vault-read.d.ts +11 -0
- package/dist-lib/lib/tools/exec/obsidian/vault-read.js +119 -0
- package/dist-lib/lib/tools/exec/obsidian/vault-write.d.ts +7 -0
- package/dist-lib/lib/tools/exec/obsidian/vault-write.js +134 -0
- package/dist-lib/lib/tools/exec/runner.d.ts +62 -0
- package/dist-lib/lib/tools/exec/runner.js +87 -0
- package/dist-lib/lib/tools/exec/scope.d.ts +3 -0
- package/dist-lib/lib/tools/exec/scope.js +97 -0
- package/dist-lib/lib/tools/exec/shell-argv.d.ts +2 -0
- package/dist-lib/lib/tools/exec/shell-argv.js +48 -0
- package/dist-lib/lib/tools/exec.d.ts +29 -0
- package/dist-lib/lib/tools/exec.js +459 -0
- package/dist-lib/lib/tools/file-glob.d.ts +15 -0
- package/dist-lib/lib/tools/file-glob.js +112 -0
- package/dist-lib/lib/tools/fs/drive.d.ts +26 -0
- package/dist-lib/lib/tools/fs/drive.js +1 -0
- package/dist-lib/lib/tools/fs/glob.d.ts +1 -0
- package/dist-lib/lib/tools/fs/glob.js +34 -0
- package/dist-lib/lib/tools/fs/local.d.ts +2 -0
- package/dist-lib/lib/tools/fs/local.js +29 -0
- package/dist-lib/lib/tools/fs/read.d.ts +2 -0
- package/dist-lib/lib/tools/fs/read.js +17 -0
- package/dist-lib/lib/tools/fs/remote-protocol.d.ts +40 -0
- package/dist-lib/lib/tools/fs/remote-protocol.js +1 -0
- package/dist-lib/lib/tools/fs/remote.d.ts +17 -0
- package/dist-lib/lib/tools/fs/remote.js +131 -0
- package/dist-lib/lib/tools/fs/scope.d.ts +37 -0
- package/dist-lib/lib/tools/fs/scope.js +130 -0
- package/dist-lib/lib/tools/fs/walk.d.ts +15 -0
- package/dist-lib/lib/tools/fs/walk.js +38 -0
- package/dist-lib/lib/tools/fs/write.d.ts +4 -0
- package/dist-lib/lib/tools/fs/write.js +5 -0
- package/dist-lib/lib/tools/generate-image.d.ts +111 -0
- package/dist-lib/lib/tools/generate-image.js +369 -0
- package/dist-lib/lib/tools/generate-music.d.ts +124 -0
- package/dist-lib/lib/tools/generate-music.js +522 -0
- package/dist-lib/lib/tools/grep.d.ts +5 -0
- package/dist-lib/lib/tools/grep.js +158 -0
- package/dist-lib/lib/tools/http-methods.d.ts +1 -0
- package/dist-lib/lib/tools/http-methods.js +1 -0
- package/dist-lib/lib/tools/http-request/encode-fields.d.ts +2 -0
- package/dist-lib/lib/tools/http-request/encode-fields.js +69 -0
- package/dist-lib/lib/tools/http-request/truncate-response.d.ts +1 -0
- package/dist-lib/lib/tools/http-request/truncate-response.js +83 -0
- package/dist-lib/lib/tools/http-request/utils.d.ts +27 -0
- package/dist-lib/lib/tools/http-request/utils.js +84 -0
- package/dist-lib/lib/tools/http-request.d.ts +20 -0
- package/dist-lib/lib/tools/http-request.js +177 -0
- package/dist-lib/lib/tools/mcp/utils.d.ts +47 -0
- package/dist-lib/lib/tools/mcp/utils.js +172 -0
- package/dist-lib/lib/tools/mcp-call.d.ts +14 -0
- package/dist-lib/lib/tools/mcp-call.js +155 -0
- package/dist-lib/lib/tools/model-args.d.ts +1 -0
- package/dist-lib/lib/tools/model-args.js +4 -0
- package/dist-lib/lib/tools/operations/builders.d.ts +17 -0
- package/dist-lib/lib/tools/operations/builders.js +179 -0
- package/dist-lib/lib/tools/operations/compile.d.ts +7 -0
- package/dist-lib/lib/tools/operations/compile.js +92 -0
- package/dist-lib/lib/tools/operations/gmail-message.d.ts +15 -0
- package/dist-lib/lib/tools/operations/gmail-message.js +62 -0
- package/dist-lib/lib/tools/operations/manifest.d.ts +60 -0
- package/dist-lib/lib/tools/operations/manifest.js +50 -0
- package/dist-lib/lib/tools/outbound-guard.d.ts +10 -0
- package/dist-lib/lib/tools/outbound-guard.js +127 -0
- package/dist-lib/lib/tools/private-ip.d.ts +4 -0
- package/dist-lib/lib/tools/private-ip.js +126 -0
- package/dist-lib/lib/tools/rag-search.d.ts +2 -0
- package/dist-lib/lib/tools/rag-search.js +98 -0
- package/dist-lib/lib/tools/read-files.d.ts +5 -0
- package/dist-lib/lib/tools/read-files.js +153 -0
- package/dist-lib/lib/tools/skill.d.ts +10 -0
- package/dist-lib/lib/tools/skill.js +123 -0
- package/dist-lib/lib/tools/skills/auth-resolver.d.ts +43 -0
- package/dist-lib/lib/tools/skills/auth-resolver.js +121 -0
- package/dist-lib/lib/tools/skills/bin-check.d.ts +9 -0
- package/dist-lib/lib/tools/skills/bin-check.js +56 -0
- package/dist-lib/lib/tools/skills/bundled-dir.d.ts +2 -0
- package/dist-lib/lib/tools/skills/bundled-dir.js +117 -0
- package/dist-lib/lib/tools/skills/bundled-hash.d.ts +4 -0
- package/dist-lib/lib/tools/skills/bundled-hash.js +12 -0
- package/dist-lib/lib/tools/skills/catalog.d.ts +60 -0
- package/dist-lib/lib/tools/skills/catalog.js +203 -0
- package/dist-lib/lib/tools/skills/cli-argv.d.ts +9 -0
- package/dist-lib/lib/tools/skills/cli-argv.js +147 -0
- package/dist-lib/lib/tools/skills/cli-schema-check.d.ts +3 -0
- package/dist-lib/lib/tools/skills/cli-schema-check.js +62 -0
- package/dist-lib/lib/tools/skills/cli-schema-load.d.ts +4 -0
- package/dist-lib/lib/tools/skills/cli-schema-load.js +90 -0
- package/dist-lib/lib/tools/skills/cli-schema-types.d.ts +30 -0
- package/dist-lib/lib/tools/skills/cli-schema-types.js +1 -0
- package/dist-lib/lib/tools/skills/cli-schema.d.ts +7 -0
- package/dist-lib/lib/tools/skills/cli-schema.js +35 -0
- package/dist-lib/lib/tools/skills/credential-check.d.ts +20 -0
- package/dist-lib/lib/tools/skills/credential-check.js +94 -0
- package/dist-lib/lib/tools/skills/credential-grants.d.ts +9 -0
- package/dist-lib/lib/tools/skills/credential-grants.js +25 -0
- package/dist-lib/lib/tools/skills/credential-health.d.ts +8 -0
- package/dist-lib/lib/tools/skills/credential-health.js +51 -0
- package/dist-lib/lib/tools/skills/credential-slots.d.ts +7 -0
- package/dist-lib/lib/tools/skills/credential-slots.js +8 -0
- package/dist-lib/lib/tools/skills/frontmatter-parser.d.ts +23 -0
- package/dist-lib/lib/tools/skills/frontmatter-parser.js +68 -0
- package/dist-lib/lib/tools/skills/index.d.ts +5 -0
- package/dist-lib/lib/tools/skills/index.js +5 -0
- package/dist-lib/lib/tools/skills/manifest-parse.d.ts +12 -0
- package/dist-lib/lib/tools/skills/manifest-parse.js +199 -0
- package/dist-lib/lib/tools/skills/manifest.d.ts +47 -0
- package/dist-lib/lib/tools/skills/manifest.js +1 -0
- package/dist-lib/lib/tools/skills/mention-name.d.ts +1 -0
- package/dist-lib/lib/tools/skills/mention-name.js +4 -0
- package/dist-lib/lib/tools/skills/mention.d.ts +6 -0
- package/dist-lib/lib/tools/skills/mention.js +42 -0
- package/dist-lib/lib/tools/skills/obsidian-readiness.d.ts +16 -0
- package/dist-lib/lib/tools/skills/obsidian-readiness.js +95 -0
- package/dist-lib/lib/tools/skills/overlay-crud.d.ts +18 -0
- package/dist-lib/lib/tools/skills/overlay-crud.js +98 -0
- package/dist-lib/lib/tools/skills/overlay-dir.d.ts +2 -0
- package/dist-lib/lib/tools/skills/overlay-dir.js +22 -0
- package/dist-lib/lib/tools/skills/overlay-watch.d.ts +13 -0
- package/dist-lib/lib/tools/skills/overlay-watch.js +44 -0
- package/dist-lib/lib/tools/skills/scope-key.d.ts +7 -0
- package/dist-lib/lib/tools/skills/scope-key.js +7 -0
- package/dist-lib/lib/tools/skills/setup-routes.d.ts +4 -0
- package/dist-lib/lib/tools/skills/setup-routes.js +14 -0
- package/dist-lib/lib/tools/skills/skill-settings.d.ts +16 -0
- package/dist-lib/lib/tools/skills/skill-settings.js +33 -0
- package/dist-lib/lib/tools/skills/skill-state-constants.d.ts +12 -0
- package/dist-lib/lib/tools/skills/skill-state-constants.js +14 -0
- package/dist-lib/lib/tools/skills/skill-state.d.ts +40 -0
- package/dist-lib/lib/tools/skills/skill-state.js +117 -0
- package/dist-lib/lib/tools/skills/tool-grants.d.ts +5 -0
- package/dist-lib/lib/tools/skills/tool-grants.js +14 -0
- package/dist-lib/lib/tools/toolsets.d.ts +8 -0
- package/dist-lib/lib/tools/toolsets.js +20 -0
- package/dist-lib/lib/tools/url-guard.d.ts +8 -0
- package/dist-lib/lib/tools/url-guard.js +40 -0
- package/dist-lib/lib/tools/web-fetch.d.ts +8 -0
- package/dist-lib/lib/tools/web-fetch.js +302 -0
- package/dist-lib/lib/tools/web-search.d.ts +6 -0
- package/dist-lib/lib/tools/web-search.js +55 -0
- package/dist-lib/lib/transport.d.ts +12 -0
- package/dist-lib/lib/transport.js +59 -0
- package/dist-lib/lib/user-agent.d.ts +1 -0
- package/dist-lib/lib/user-agent.js +1 -0
- package/dist-lib/lib/validating-lookup.d.ts +17 -0
- package/dist-lib/lib/validating-lookup.js +25 -0
- package/dist-lib/lib/wav-encode.d.ts +5 -0
- package/dist-lib/lib/wav-encode.js +24 -0
- package/dist-lib/lib/web-fetch/embedded-state.d.ts +1 -0
- package/dist-lib/lib/web-fetch/embedded-state.js +131 -0
- package/dist-lib/lib/web-fetch/extract.d.ts +6 -0
- package/dist-lib/lib/web-fetch/extract.js +65 -0
- package/dist-lib/lib/web-fetch/images.d.ts +3 -0
- package/dist-lib/lib/web-fetch/images.js +43 -0
- package/dist-lib/lib/web-fetch/video.d.ts +5 -0
- package/dist-lib/lib/web-fetch/video.js +42 -0
- package/dist-lib/lib/web-search/engine-registry.d.ts +7 -0
- package/dist-lib/lib/web-search/engine-registry.js +17 -0
- package/dist-lib/lib/web-search/engines/aol.d.ts +3 -0
- package/dist-lib/lib/web-search/engines/aol.js +81 -0
- package/dist-lib/lib/web-search/engines/bing.d.ts +3 -0
- package/dist-lib/lib/web-search/engines/bing.js +111 -0
- package/dist-lib/lib/web-search/engines/brave.d.ts +3 -0
- package/dist-lib/lib/web-search/engines/brave.js +59 -0
- package/dist-lib/lib/web-search/engines/duckduckgo.d.ts +3 -0
- package/dist-lib/lib/web-search/engines/duckduckgo.js +112 -0
- package/dist-lib/lib/web-search/engines/google.d.ts +3 -0
- package/dist-lib/lib/web-search/engines/google.js +92 -0
- package/dist-lib/lib/web-search/engines/wikipedia.d.ts +3 -0
- package/dist-lib/lib/web-search/engines/wikipedia.js +37 -0
- package/dist-lib/lib/web-search/engines/yahoo.d.ts +3 -0
- package/dist-lib/lib/web-search/engines/yahoo.js +81 -0
- package/dist-lib/lib/web-search/fetch-html.d.ts +25 -0
- package/dist-lib/lib/web-search/fetch-html.js +97 -0
- package/dist-lib/lib/web-search/format-results.d.ts +3 -0
- package/dist-lib/lib/web-search/format-results.js +14 -0
- package/dist-lib/lib/web-search/html-helpers.d.ts +3 -0
- package/dist-lib/lib/web-search/html-helpers.js +24 -0
- package/dist-lib/lib/web-search/merge-results.d.ts +2 -0
- package/dist-lib/lib/web-search/merge-results.js +53 -0
- package/dist-lib/lib/web-search/orchestrator.d.ts +14 -0
- package/dist-lib/lib/web-search/orchestrator.js +50 -0
- package/dist-lib/lib/web-search/types.d.ts +34 -0
- package/dist-lib/lib/web-search/types.js +1 -0
- package/dist-lib/lib/web-search/url-helpers.d.ts +1 -0
- package/dist-lib/lib/web-search/url-helpers.js +11 -0
- package/dist-lib/lib/web-search/url-normalize.d.ts +1 -0
- package/dist-lib/lib/web-search/url-normalize.js +25 -0
- package/dist-lib/lib/web-search/user-agents.d.ts +3 -0
- package/dist-lib/lib/web-search/user-agents.js +3 -0
- package/dist-lib/lib/wire.d.ts +50 -0
- package/dist-lib/lib/wire.js +145 -0
- package/dist-lib/schema/baseline.d.ts +8 -0
- package/dist-lib/schema/baseline.js +35 -0
- package/dist-lib/schema/build.d.ts +1 -0
- package/dist-lib/schema/build.js +39 -0
- package/dist-lib/schema/generate.d.ts +20 -0
- package/dist-lib/schema/generate.js +149 -0
- package/dist-lib/schema/harness.d.ts +2 -0
- package/dist-lib/schema/harness.js +745 -0
- package/dist-lib/schema/release-tags.d.ts +5 -0
- package/dist-lib/schema/release-tags.js +58 -0
- package/dist-lib/spec/bind.d.ts +2 -0
- package/dist-lib/spec/bind.js +124 -0
- package/dist-lib/spec/calls.d.ts +3 -0
- package/dist-lib/spec/calls.js +41 -0
- package/dist-lib/spec/hrpc/hrpc.json +356 -0
- package/dist-lib/spec/hrpc/index.d.ts +3 -0
- package/dist-lib/spec/hrpc/index.js +463 -0
- package/dist-lib/spec/hrpc/messages.d.ts +4 -0
- package/dist-lib/spec/hrpc/messages.js +3102 -0
- package/dist-lib/spec/hyperschema/index.js +3102 -0
- package/dist-lib/spec/hyperschema/schema.json +2290 -0
- package/dist-lib/spec/hyperschema/types.d.ts +554 -0
- package/dist-lib/spec/index.d.ts +8 -0
- package/dist-lib/spec/index.js +1 -0
- package/package.json +418 -1
- package/wheels/cffi-2.0.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl +0 -0
- package/wheels/cryptography-47.0.0-cp314-abi3-pyemscripten_2026_0_wasm32.whl +0 -0
- package/wheels/defusedxml-0.7.1-py2.py3-none-any.whl +0 -0
- package/wheels/et_xmlfile-2.0.0-py3-none-any.whl +0 -0
- package/wheels/fonttools-4.62.1-py3-none-any.whl +0 -0
- package/wheels/fpdf2-2.8.8-py3-none-any.whl +0 -0
- package/wheels/lxml-6.0.2-cp314-cp314-pyemscripten_2026_0_wasm32.whl +0 -0
- package/wheels/manifest.json +155 -0
- package/wheels/micropip-0.11.1-py3-none-any.whl +0 -0
- package/wheels/openpyxl-3.1.5-py2.py3-none-any.whl +0 -0
- package/wheels/pillow-12.2.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl +0 -0
- package/wheels/pycparser-3.0-py3-none-any.whl +0 -0
- package/wheels/pypdf-6.15.0-py3-none-any.whl +0 -0
- package/wheels/python_docx-1.2.0-py3-none-any.whl +0 -0
- package/wheels/python_pptx-1.0.2-py3-none-any.whl +0 -0
- package/wheels/six-1.17.0-py2.py3-none-any.whl +0 -0
- package/wheels/typing_extensions-4.15.0-py3-none-any.whl +0 -0
- package/wheels/xlsxwriter-3.2.9-py3-none-any.whl +0 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { fetchHtml } from "../fetch-html.js";
|
|
2
|
+
import { clean } from "../html-helpers.js";
|
|
3
|
+
import { urlMatchesHost } from "../url-helpers.js";
|
|
4
|
+
function extractDdgUrl(raw) {
|
|
5
|
+
if (raw.includes('uddg=')) {
|
|
6
|
+
const m = raw.match(/uddg=([^&]+)/);
|
|
7
|
+
if (m?.[1]) {
|
|
8
|
+
return decodeURIComponent(m[1]);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return raw;
|
|
12
|
+
}
|
|
13
|
+
function isOrganicUrl(url) {
|
|
14
|
+
return url.startsWith('http') && !urlMatchesHost(url, 'duckduckgo.com');
|
|
15
|
+
}
|
|
16
|
+
function parseLinksMain(html) {
|
|
17
|
+
const results = [];
|
|
18
|
+
const pat = /<div[^>]*class="[^"]*links_main[^"]*"[^>]*>[\s\S]*?<a[^>]*href="([^"]*)"[^>]*>([\s\S]*?)<\/a>[\s\S]*?<a[^>]*class="[^"]*result__snippet[^"]*"[^>]*>([\s\S]*?)<\/a>/gi;
|
|
19
|
+
for (const m of html.matchAll(pat)) {
|
|
20
|
+
const url = extractDdgUrl(m[1] || '');
|
|
21
|
+
const title = clean(m[2] || '');
|
|
22
|
+
const content = clean(m[3] || '');
|
|
23
|
+
if (url && title && isOrganicUrl(url)) {
|
|
24
|
+
results.push({ title, url, content: content || title, position: results.length + 1 });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return results;
|
|
28
|
+
}
|
|
29
|
+
function extractLinks(html) {
|
|
30
|
+
const linkPat = /<a[^>]*class="[^"]*result__a[^"]*"[^>]*href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/gi;
|
|
31
|
+
const links = [];
|
|
32
|
+
for (const lm of html.matchAll(linkPat)) {
|
|
33
|
+
const url = extractDdgUrl(lm[1] || '');
|
|
34
|
+
const title = clean(lm[2] || '');
|
|
35
|
+
if (url && title && isOrganicUrl(url)) {
|
|
36
|
+
links.push({ url, title });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return links;
|
|
40
|
+
}
|
|
41
|
+
function extractSnippets(html) {
|
|
42
|
+
const snipPat = /<a[^>]*class="[^"]*result__snippet[^"]*"[^>]*>([\s\S]*?)<\/a>/gi;
|
|
43
|
+
const snippets = [];
|
|
44
|
+
for (const sm of html.matchAll(snipPat)) {
|
|
45
|
+
const s = clean(sm[1] || '');
|
|
46
|
+
if (s) {
|
|
47
|
+
snippets.push(s);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return snippets;
|
|
51
|
+
}
|
|
52
|
+
function parseResultLinks(html) {
|
|
53
|
+
const links = extractLinks(html);
|
|
54
|
+
const snippets = extractSnippets(html);
|
|
55
|
+
const results = [];
|
|
56
|
+
for (let i = 0; i < links.length; i++) {
|
|
57
|
+
const link = links[i];
|
|
58
|
+
if (!link) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
results.push({
|
|
62
|
+
title: link.title,
|
|
63
|
+
url: link.url,
|
|
64
|
+
content: snippets[i] || link.title,
|
|
65
|
+
position: results.length + 1
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return results;
|
|
69
|
+
}
|
|
70
|
+
function parseUddgFallback(html) {
|
|
71
|
+
const results = [];
|
|
72
|
+
const uddgPat = /uddg=([^&"]+)/gi;
|
|
73
|
+
const seen = new Set();
|
|
74
|
+
for (const um of html.matchAll(uddgPat)) {
|
|
75
|
+
try {
|
|
76
|
+
const url = decodeURIComponent(um[1] || '');
|
|
77
|
+
if (url.startsWith('http') && !seen.has(url) && !urlMatchesHost(url, 'duckduckgo.com')) {
|
|
78
|
+
seen.add(url);
|
|
79
|
+
const host = new URL(url).hostname;
|
|
80
|
+
results.push({
|
|
81
|
+
title: host,
|
|
82
|
+
url,
|
|
83
|
+
content: `Result from ${host}`,
|
|
84
|
+
position: results.length + 1,
|
|
85
|
+
weak: true
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch { }
|
|
90
|
+
}
|
|
91
|
+
return results;
|
|
92
|
+
}
|
|
93
|
+
export async function searchDuckDuckGo(query, fetcher, signal) {
|
|
94
|
+
const body = `q=${encodeURIComponent(query)}`;
|
|
95
|
+
const html = await fetchHtml(fetcher, 'https://html.duckduckgo.com/html/', {
|
|
96
|
+
method: 'POST',
|
|
97
|
+
headers: {
|
|
98
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
99
|
+
Referer: 'https://html.duckduckgo.com/'
|
|
100
|
+
},
|
|
101
|
+
body
|
|
102
|
+
}, signal);
|
|
103
|
+
const primary = parseLinksMain(html);
|
|
104
|
+
if (primary.length > 0) {
|
|
105
|
+
return primary;
|
|
106
|
+
}
|
|
107
|
+
const secondary = parseResultLinks(html);
|
|
108
|
+
if (secondary.length > 0) {
|
|
109
|
+
return secondary;
|
|
110
|
+
}
|
|
111
|
+
return parseUddgFallback(html);
|
|
112
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { fetchHtml } from "../fetch-html.js";
|
|
2
|
+
import { clean } from "../html-helpers.js";
|
|
3
|
+
import { urlMatchesHost } from "../url-helpers.js";
|
|
4
|
+
import { GOOGLE_GSA_UA } from "../user-agents.js";
|
|
5
|
+
function resolveGoogleUrl(rawUrl) {
|
|
6
|
+
if (rawUrl.startsWith('/url?q=')) {
|
|
7
|
+
return decodeURIComponent(rawUrl.slice(7).split('&')[0] || '');
|
|
8
|
+
}
|
|
9
|
+
return rawUrl;
|
|
10
|
+
}
|
|
11
|
+
function isGoogleSearchSelfLink(url) {
|
|
12
|
+
try {
|
|
13
|
+
const u = new URL(url);
|
|
14
|
+
const h = u.hostname.toLowerCase();
|
|
15
|
+
return (h === 'google.com' || h === 'www.google.com') && u.pathname === '/search';
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function isSkippableUrl(url) {
|
|
22
|
+
return isGoogleSearchSelfLink(url) || urlMatchesHost(url, 'accounts.google.com');
|
|
23
|
+
}
|
|
24
|
+
function extractTitle(anchorBody) {
|
|
25
|
+
const titleMatch = anchorBody.match(/<(?:div|h3)[^>]*>([\s\S]*?)<\/(?:div|h3)>/i);
|
|
26
|
+
return titleMatch ? clean(titleMatch[1] || '') : clean(anchorBody);
|
|
27
|
+
}
|
|
28
|
+
function parseAnchor(am, html, snippetPat, existing) {
|
|
29
|
+
const rawUrl = resolveGoogleUrl(am[1] || '');
|
|
30
|
+
if (isSkippableUrl(rawUrl) || !rawUrl.startsWith('http')) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const title = extractTitle(am[2] || '');
|
|
34
|
+
if (!title || title.length < 3 || existing.some((r) => r.url === rawUrl)) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const region = html.slice(am.index, (am.index ?? 0) + 3000);
|
|
38
|
+
snippetPat.lastIndex = 0;
|
|
39
|
+
const sm = snippetPat.exec(region);
|
|
40
|
+
const content = sm ? clean(sm[1] || '') : '';
|
|
41
|
+
return { title, url: rawUrl, content, position: 0 };
|
|
42
|
+
}
|
|
43
|
+
function parseDataVedAnchors(html) {
|
|
44
|
+
const results = [];
|
|
45
|
+
const snippetPat = /<div[^>]*class="[^"]*VwiC3b[^"]*"[^>]*>([\s\S]*?)<\/div>/gi;
|
|
46
|
+
const anchorPat = /<a[^>]*\shref="(\/url\?q=[^"]+|https?:\/\/[^"]+)"[^>]*data-ved="[^"]*"[^>]*>([\s\S]*?)<\/a>/gi;
|
|
47
|
+
for (const am of html.matchAll(anchorPat)) {
|
|
48
|
+
const parsed = parseAnchor(am, html, snippetPat, results);
|
|
49
|
+
if (parsed) {
|
|
50
|
+
results.push({ ...parsed, position: results.length + 1 });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return results;
|
|
54
|
+
}
|
|
55
|
+
function parseH3Match(hm, existing) {
|
|
56
|
+
let rawUrl = hm[2] || '';
|
|
57
|
+
const title = clean(hm[1] || '');
|
|
58
|
+
if (!title || title.length < 3) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
rawUrl = resolveGoogleUrl(rawUrl);
|
|
62
|
+
if (!rawUrl.startsWith('http')) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
if (existing.some((r) => r.url === rawUrl)) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
return { title, url: rawUrl, content: '', position: 0 };
|
|
69
|
+
}
|
|
70
|
+
function parseH3Fallback(html) {
|
|
71
|
+
const results = [];
|
|
72
|
+
const h3Pat = /<h3[^>]*>([\s\S]*?)<\/h3>[\s\S]*?<a[^>]*href="(\/url\?q=[^"]+|https?:\/\/(?!google\.com)[^"]+)"[^>]*>/gi;
|
|
73
|
+
for (const hm of html.matchAll(h3Pat)) {
|
|
74
|
+
const parsed = parseH3Match(hm, results);
|
|
75
|
+
if (parsed) {
|
|
76
|
+
results.push({ ...parsed, position: results.length + 1 });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return results;
|
|
80
|
+
}
|
|
81
|
+
export async function searchGoogle(query, fetcher, signal) {
|
|
82
|
+
const url = `https://www.google.com/search?q=${encodeURIComponent(query)}&hl=en&ie=utf8&oe=utf8&filter=0`;
|
|
83
|
+
const html = await fetchHtml(fetcher, url, { headers: { 'User-Agent': GOOGLE_GSA_UA, Accept: '*/*' }, cookies: { CONSENT: 'YES+' } }, signal);
|
|
84
|
+
if (html.includes('detected unusual traffic') || html.includes('g-recaptcha')) {
|
|
85
|
+
throw new Error('Google CAPTCHA detected');
|
|
86
|
+
}
|
|
87
|
+
const primary = parseDataVedAnchors(html);
|
|
88
|
+
if (primary.length > 0) {
|
|
89
|
+
return primary;
|
|
90
|
+
}
|
|
91
|
+
return parseH3Fallback(html);
|
|
92
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { AbortSignal as BareAbortSignal } from 'bare-abort-controller';
|
|
2
|
+
import type { Fetcher, RankedResult } from '../types.ts';
|
|
3
|
+
export declare function searchWikipedia(query: string, fetcher: Fetcher, signal?: BareAbortSignal): Promise<ReadonlyArray<RankedResult>>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { fetchJson } from "../fetch-html.js";
|
|
2
|
+
import { clean } from "../html-helpers.js";
|
|
3
|
+
function extractSearchItems(data) {
|
|
4
|
+
if (typeof data !== 'object' || data === null) {
|
|
5
|
+
return [];
|
|
6
|
+
}
|
|
7
|
+
const query = data.query;
|
|
8
|
+
if (typeof query !== 'object' || query === null) {
|
|
9
|
+
return [];
|
|
10
|
+
}
|
|
11
|
+
const search = query.search;
|
|
12
|
+
if (!Array.isArray(search)) {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
const items = [];
|
|
16
|
+
for (const entry of search) {
|
|
17
|
+
if (typeof entry !== 'object' || entry === null) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const { title, snippet } = entry;
|
|
21
|
+
if (typeof title === 'string' && typeof snippet === 'string') {
|
|
22
|
+
items.push({ title, snippet });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return items;
|
|
26
|
+
}
|
|
27
|
+
export async function searchWikipedia(query, fetcher, signal) {
|
|
28
|
+
const apiUrl = `https://en.wikipedia.org/w/api.php?action=query&list=search&srsearch=${encodeURIComponent(query)}&format=json&srlimit=5&utf8=1`;
|
|
29
|
+
const data = await fetchJson(fetcher, apiUrl, undefined, signal);
|
|
30
|
+
const items = extractSearchItems(data);
|
|
31
|
+
return items.map((item, idx) => ({
|
|
32
|
+
title: item.title,
|
|
33
|
+
url: `https://en.wikipedia.org/wiki/${encodeURIComponent(item.title.replace(/ /g, '_'))}`,
|
|
34
|
+
content: clean(item.snippet || item.title),
|
|
35
|
+
position: idx + 1
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { fetchHtml } from "../fetch-html.js";
|
|
2
|
+
import { clean } from "../html-helpers.js";
|
|
3
|
+
import { urlMatchesHost } from "../url-helpers.js";
|
|
4
|
+
function decodeRuUrl(encoded) {
|
|
5
|
+
try {
|
|
6
|
+
const href = decodeURIComponent(encoded);
|
|
7
|
+
if (!href.startsWith('http')) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
if (urlMatchesHost(href, 'search.yahoo.com') || urlMatchesHost(href, 'shopping.yahoo.com')) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
return href;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function parseAlgoBlock(inner) {
|
|
20
|
+
const ruMatch = inner.match(/\/RU=(https?%3a%2f%2f[^/]*?)\/RK/i);
|
|
21
|
+
if (!ruMatch) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const href = decodeRuUrl(ruMatch[1] || '');
|
|
25
|
+
if (!href) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const titleMatch = inner.match(/<span[^>]*class="[^"]*fz-20[^"]*"[^>]*>([\s\S]*?)<\/span>/i);
|
|
29
|
+
const title = titleMatch ? clean(titleMatch[1] || '') : '';
|
|
30
|
+
if (!title) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const snippetMatch = inner.match(/class="compText[^"]*"[^>]*>[\s\S]*?<p[^>]*>([\s\S]*?)<\/p>/i);
|
|
34
|
+
const content = snippetMatch ? clean(snippetMatch[1] || '') : title;
|
|
35
|
+
return { title, url: href, content, position: 0 };
|
|
36
|
+
}
|
|
37
|
+
function parseAlgoBlocks(html) {
|
|
38
|
+
const results = [];
|
|
39
|
+
const blocks = html.split(/algo algo-sr/i);
|
|
40
|
+
for (let i = 1; i < blocks.length; i++) {
|
|
41
|
+
const inner = blocks[i]?.slice(0, 5000) || '';
|
|
42
|
+
const parsed = parseAlgoBlock(inner);
|
|
43
|
+
if (parsed) {
|
|
44
|
+
results.push({ ...parsed, position: results.length + 1 });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return results;
|
|
48
|
+
}
|
|
49
|
+
function parseRuFallback(html) {
|
|
50
|
+
const results = [];
|
|
51
|
+
const seen = new Set();
|
|
52
|
+
const ruGlobal = /\/RU=(https?%3a%2f%2f[^/]*?)\/RK/gi;
|
|
53
|
+
for (const rm of html.matchAll(ruGlobal)) {
|
|
54
|
+
const href = decodeRuUrl(rm[1] || '');
|
|
55
|
+
if (!href || seen.has(href)) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
seen.add(href);
|
|
59
|
+
const host = new URL(href).hostname;
|
|
60
|
+
results.push({
|
|
61
|
+
title: host,
|
|
62
|
+
url: href,
|
|
63
|
+
content: `Result from ${host}`,
|
|
64
|
+
position: results.length + 1,
|
|
65
|
+
weak: true
|
|
66
|
+
});
|
|
67
|
+
if (results.length >= 15) {
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return results;
|
|
72
|
+
}
|
|
73
|
+
export async function searchYahoo(query, fetcher, signal) {
|
|
74
|
+
const url = `https://search.yahoo.com/search?p=${encodeURIComponent(query)}`;
|
|
75
|
+
const html = await fetchHtml(fetcher, url, undefined, signal);
|
|
76
|
+
const primary = parseAlgoBlocks(html);
|
|
77
|
+
if (primary.length > 0) {
|
|
78
|
+
return primary;
|
|
79
|
+
}
|
|
80
|
+
return parseRuFallback(html);
|
|
81
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type AbortSignal as BareAbortSignal } from 'bare-abort-controller';
|
|
2
|
+
import type { Fetcher } from './types.ts';
|
|
3
|
+
export declare const ENGINE_TIMEOUT_MS = 8000;
|
|
4
|
+
export declare const MAX_HTML_CHARS = 2000000;
|
|
5
|
+
export declare class TimeoutError extends Error {
|
|
6
|
+
constructor(ms: number);
|
|
7
|
+
}
|
|
8
|
+
export declare class AbortError extends Error {
|
|
9
|
+
constructor();
|
|
10
|
+
}
|
|
11
|
+
type FetchOptions = {
|
|
12
|
+
readonly method?: string;
|
|
13
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
14
|
+
readonly body?: string;
|
|
15
|
+
readonly cookies?: Readonly<Record<string, string>>;
|
|
16
|
+
readonly accept?: string;
|
|
17
|
+
readonly timeoutMs?: number;
|
|
18
|
+
};
|
|
19
|
+
export declare function fetchHtml(fetcher: Fetcher, url: string, options?: FetchOptions, signal?: BareAbortSignal): Promise<string>;
|
|
20
|
+
export declare class JsonParseError extends Error {
|
|
21
|
+
readonly cause?: unknown;
|
|
22
|
+
constructor(message: string, cause?: unknown);
|
|
23
|
+
}
|
|
24
|
+
export declare function fetchJson(fetcher: Fetcher, url: string, options?: FetchOptions, signal?: BareAbortSignal): Promise<unknown>;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { AbortController } from 'bare-abort-controller';
|
|
2
|
+
import { BROWSER_UA } from "./user-agents.js";
|
|
3
|
+
export const ENGINE_TIMEOUT_MS = 8000;
|
|
4
|
+
export const MAX_HTML_CHARS = 2_000_000;
|
|
5
|
+
export class TimeoutError extends Error {
|
|
6
|
+
constructor(ms) {
|
|
7
|
+
super(`Request timed out after ${ms}ms`);
|
|
8
|
+
this.name = 'TimeoutError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export class AbortError extends Error {
|
|
12
|
+
constructor() {
|
|
13
|
+
super('Request cancelled');
|
|
14
|
+
this.name = 'AbortError';
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function buildInit(options, signal) {
|
|
18
|
+
const headers = {
|
|
19
|
+
'User-Agent': BROWSER_UA,
|
|
20
|
+
Accept: options?.accept ?? 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
|
21
|
+
'Accept-Language': 'en-US,en;q=0.5',
|
|
22
|
+
...options?.headers
|
|
23
|
+
};
|
|
24
|
+
if (options?.cookies && Object.keys(options.cookies).length > 0) {
|
|
25
|
+
headers['Cookie'] = Object.entries(options.cookies)
|
|
26
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
27
|
+
.join('; ');
|
|
28
|
+
}
|
|
29
|
+
const init = {
|
|
30
|
+
method: options?.method ?? 'GET',
|
|
31
|
+
headers,
|
|
32
|
+
redirect: 'follow',
|
|
33
|
+
signal
|
|
34
|
+
};
|
|
35
|
+
if (options?.body) {
|
|
36
|
+
return { ...init, body: options.body };
|
|
37
|
+
}
|
|
38
|
+
return init;
|
|
39
|
+
}
|
|
40
|
+
async function fetchWithTimeout(fetcher, url, options, callerSignal) {
|
|
41
|
+
if (callerSignal?.aborted) {
|
|
42
|
+
throw new AbortError();
|
|
43
|
+
}
|
|
44
|
+
let timedOut = false;
|
|
45
|
+
const ac = new AbortController();
|
|
46
|
+
const timeoutMs = options?.timeoutMs ?? ENGINE_TIMEOUT_MS;
|
|
47
|
+
const timeoutId = setTimeout(() => {
|
|
48
|
+
timedOut = true;
|
|
49
|
+
ac.abort(undefined);
|
|
50
|
+
}, timeoutMs);
|
|
51
|
+
const onCallerAbort = () => ac.abort(undefined);
|
|
52
|
+
callerSignal?.addEventListener('abort', onCallerAbort);
|
|
53
|
+
try {
|
|
54
|
+
const resp = await fetcher(url, buildInit(options, ac.signal));
|
|
55
|
+
const raw = await resp.text();
|
|
56
|
+
const text = raw.length > MAX_HTML_CHARS ? raw.slice(0, MAX_HTML_CHARS) : raw;
|
|
57
|
+
return { ok: resp.ok, status: resp.status, text };
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
if (timedOut)
|
|
61
|
+
throw new TimeoutError(timeoutMs);
|
|
62
|
+
if (callerSignal?.aborted)
|
|
63
|
+
throw new AbortError();
|
|
64
|
+
throw err;
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
clearTimeout(timeoutId);
|
|
68
|
+
callerSignal?.removeEventListener('abort', onCallerAbort);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export async function fetchHtml(fetcher, url, options, signal) {
|
|
72
|
+
const { ok, status, text } = await fetchWithTimeout(fetcher, url, options, signal);
|
|
73
|
+
if (!ok) {
|
|
74
|
+
throw new Error(`HTTP ${status}`);
|
|
75
|
+
}
|
|
76
|
+
return text;
|
|
77
|
+
}
|
|
78
|
+
export class JsonParseError extends Error {
|
|
79
|
+
cause;
|
|
80
|
+
constructor(message, cause) {
|
|
81
|
+
super(message);
|
|
82
|
+
this.cause = cause;
|
|
83
|
+
this.name = 'JsonParseError';
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export async function fetchJson(fetcher, url, options, signal) {
|
|
87
|
+
const { ok, status, text } = await fetchWithTimeout(fetcher, url, { ...options, accept: options?.accept ?? 'application/json' }, signal);
|
|
88
|
+
if (!ok) {
|
|
89
|
+
throw new Error(`HTTP ${status}`);
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
return JSON.parse(text);
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
throw new JsonParseError(`Response was not valid JSON (${text.length} chars): ${(err instanceof Error ? err : new Error(String(err))).message}`, err);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const MAX_CONTENT_CHARS = 800;
|
|
2
|
+
export function formatResultsForPrompt(results) {
|
|
3
|
+
if (results.length === 0) {
|
|
4
|
+
return '';
|
|
5
|
+
}
|
|
6
|
+
return results
|
|
7
|
+
.map((result, index) => {
|
|
8
|
+
const content = result.content.length > MAX_CONTENT_CHARS
|
|
9
|
+
? `${result.content.slice(0, MAX_CONTENT_CHARS)}…`
|
|
10
|
+
: result.content;
|
|
11
|
+
return `[${index + 1}] ${result.title}\nSource: ${result.url}\n${content}`;
|
|
12
|
+
})
|
|
13
|
+
.join('\n\n');
|
|
14
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function stripHtmlTags(text) {
|
|
2
|
+
let out = text;
|
|
3
|
+
let prev = '';
|
|
4
|
+
while (out !== prev) {
|
|
5
|
+
prev = out;
|
|
6
|
+
out = out.replace(/<[^>]*>/g, '');
|
|
7
|
+
}
|
|
8
|
+
return out;
|
|
9
|
+
}
|
|
10
|
+
const NAMED_ENTITIES = {
|
|
11
|
+
'<': '<',
|
|
12
|
+
'>': '>',
|
|
13
|
+
'"': '"',
|
|
14
|
+
' ': ' ',
|
|
15
|
+
'&': '&'
|
|
16
|
+
};
|
|
17
|
+
export function decodeHtmlEntities(text) {
|
|
18
|
+
return text.replace(/&(?:lt|gt|quot|nbsp|amp|#\d+);/g, (match) => match.startsWith('&#')
|
|
19
|
+
? String.fromCodePoint(parseInt(match.slice(2, -1), 10))
|
|
20
|
+
: (NAMED_ENTITIES[match] ?? match));
|
|
21
|
+
}
|
|
22
|
+
export function clean(raw) {
|
|
23
|
+
return decodeHtmlEntities(stripHtmlTags(raw)).trim();
|
|
24
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { normalizeUrl } from "./url-normalize.js";
|
|
2
|
+
const WEAK_RESULT_PENALTY = 0.2;
|
|
3
|
+
function scoreFor(r) {
|
|
4
|
+
const base = 1 / r.position;
|
|
5
|
+
return r.weak ? base * WEAK_RESULT_PENALTY : base;
|
|
6
|
+
}
|
|
7
|
+
function updateEntry(existing, r, engine) {
|
|
8
|
+
if (r.title.length > existing.title.length) {
|
|
9
|
+
existing.title = r.title;
|
|
10
|
+
}
|
|
11
|
+
if (r.content.length > existing.content.length) {
|
|
12
|
+
existing.content = r.content;
|
|
13
|
+
}
|
|
14
|
+
existing.score += scoreFor(r);
|
|
15
|
+
existing.engines.add(engine);
|
|
16
|
+
}
|
|
17
|
+
export function mergeResults(engineResults, maxResults) {
|
|
18
|
+
const map = new Map();
|
|
19
|
+
for (const { engine, results } of engineResults) {
|
|
20
|
+
for (const r of results) {
|
|
21
|
+
const key = normalizeUrl(r.url);
|
|
22
|
+
const existing = map.get(key);
|
|
23
|
+
if (existing) {
|
|
24
|
+
updateEntry(existing, r, engine);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
map.set(key, {
|
|
28
|
+
title: r.title,
|
|
29
|
+
url: r.url,
|
|
30
|
+
content: r.content,
|
|
31
|
+
score: scoreFor(r),
|
|
32
|
+
engines: new Set([engine])
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const sorted = Array.from(map.values()).sort((a, b) => {
|
|
38
|
+
if (b.score !== a.score) {
|
|
39
|
+
return b.score - a.score;
|
|
40
|
+
}
|
|
41
|
+
if (b.engines.size !== a.engines.size) {
|
|
42
|
+
return b.engines.size - a.engines.size;
|
|
43
|
+
}
|
|
44
|
+
return b.content.length - a.content.length;
|
|
45
|
+
});
|
|
46
|
+
return sorted.slice(0, maxResults).map((entry) => ({
|
|
47
|
+
title: entry.title,
|
|
48
|
+
url: entry.url,
|
|
49
|
+
content: entry.content,
|
|
50
|
+
score: Math.round(entry.score * 100) / 100,
|
|
51
|
+
engines: Array.from(entry.engines)
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AbortSignal as BareAbortSignal } from 'bare-abort-controller';
|
|
2
|
+
import type { Fetcher, WebSearchResult } from './types.ts';
|
|
3
|
+
export type EngineSummaryEntry = {
|
|
4
|
+
readonly engine: string;
|
|
5
|
+
readonly status: 'ok' | 'timeout' | 'error';
|
|
6
|
+
readonly resultCount: number;
|
|
7
|
+
readonly durationMs: number;
|
|
8
|
+
};
|
|
9
|
+
export type SearchWebResult = {
|
|
10
|
+
readonly results: ReadonlyArray<WebSearchResult>;
|
|
11
|
+
readonly engineSummary: ReadonlyArray<EngineSummaryEntry>;
|
|
12
|
+
};
|
|
13
|
+
export declare function classifyEngineError(reason: unknown): 'timeout' | 'error';
|
|
14
|
+
export declare function searchWeb(fetcher: Fetcher, query: string, maxResults?: number, signal?: BareAbortSignal): Promise<SearchWebResult>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { DEFAULT_MAX_RESULTS, ENGINES } from "./engine-registry.js";
|
|
2
|
+
import { TimeoutError } from "./fetch-html.js";
|
|
3
|
+
import { mergeResults } from "./merge-results.js";
|
|
4
|
+
export function classifyEngineError(reason) {
|
|
5
|
+
return reason instanceof TimeoutError ? 'timeout' : 'error';
|
|
6
|
+
}
|
|
7
|
+
function processSettledResult(engineName, result, outcomes, engineSummary) {
|
|
8
|
+
if (result.status === 'fulfilled') {
|
|
9
|
+
outcomes.push(result.value);
|
|
10
|
+
engineSummary.push({
|
|
11
|
+
engine: engineName,
|
|
12
|
+
status: 'ok',
|
|
13
|
+
resultCount: result.value.results.length,
|
|
14
|
+
durationMs: result.value.durationMs
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
engineSummary.push({
|
|
19
|
+
engine: engineName,
|
|
20
|
+
status: classifyEngineError(result.reason),
|
|
21
|
+
resultCount: 0,
|
|
22
|
+
durationMs: 0
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export async function searchWeb(fetcher, query, maxResults = DEFAULT_MAX_RESULTS, signal) {
|
|
27
|
+
const settled = await Promise.allSettled(ENGINES.map(async ({ name, fn }) => {
|
|
28
|
+
const start = Date.now();
|
|
29
|
+
const results = await fn(query, fetcher, signal);
|
|
30
|
+
return {
|
|
31
|
+
engine: name,
|
|
32
|
+
results: [...results],
|
|
33
|
+
durationMs: Date.now() - start
|
|
34
|
+
};
|
|
35
|
+
}));
|
|
36
|
+
const outcomes = [];
|
|
37
|
+
const engineSummary = [];
|
|
38
|
+
for (let i = 0; i < ENGINES.length; i++) {
|
|
39
|
+
const engine = ENGINES[i];
|
|
40
|
+
const settledResult = settled[i];
|
|
41
|
+
if (!engine || !settledResult) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
processSettledResult(engine.name, settledResult, outcomes, engineSummary);
|
|
45
|
+
}
|
|
46
|
+
if (outcomes.length === 0) {
|
|
47
|
+
return { results: [], engineSummary };
|
|
48
|
+
}
|
|
49
|
+
return { results: mergeResults(outcomes, maxResults), engineSummary };
|
|
50
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AbortSignal as BareAbortSignal } from 'bare-abort-controller';
|
|
2
|
+
export interface RankedResult {
|
|
3
|
+
title: string;
|
|
4
|
+
url: string;
|
|
5
|
+
content: string;
|
|
6
|
+
position: number;
|
|
7
|
+
weak?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface WebSearchResult {
|
|
10
|
+
title: string;
|
|
11
|
+
url: string;
|
|
12
|
+
content: string;
|
|
13
|
+
score?: number;
|
|
14
|
+
engines?: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface EngineOutcome {
|
|
17
|
+
engine: string;
|
|
18
|
+
results: RankedResult[];
|
|
19
|
+
durationMs: number;
|
|
20
|
+
}
|
|
21
|
+
export interface FetchInit {
|
|
22
|
+
method?: string;
|
|
23
|
+
headers?: Record<string, string>;
|
|
24
|
+
body?: string;
|
|
25
|
+
redirect?: 'follow' | 'manual' | 'error';
|
|
26
|
+
signal?: BareAbortSignal;
|
|
27
|
+
}
|
|
28
|
+
export interface Response {
|
|
29
|
+
ok: boolean;
|
|
30
|
+
status: number;
|
|
31
|
+
text(): Promise<string>;
|
|
32
|
+
}
|
|
33
|
+
export type Fetcher = (url: string, init?: FetchInit) => Promise<Response>;
|
|
34
|
+
export type SearchEngine = (query: string, fetcher: Fetcher, signal?: BareAbortSignal) => Promise<ReadonlyArray<RankedResult>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function urlMatchesHost(url: string, host: string): boolean;
|