@readymadeit/mcp 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -2
- package/bundle/LICENSE +201 -0
- package/bundle/boards/aggregator-demo-board.json +54 -0
- package/bundle/boards/alpaca-board.json +316 -0
- package/bundle/boards/animate-board.json +159 -0
- package/bundle/boards/ascii-art-demo-board.json +33 -0
- package/bundle/boards/ascii-cam-board.json +184 -0
- package/bundle/boards/asset-demo-board.json +54 -0
- package/bundle/boards/audio-encode-demo-board.json +153 -0
- package/bundle/boards/audiolize-board.json +152 -0
- package/bundle/boards/batcher-demo-board.json +43 -0
- package/bundle/boards/buffer-demo-board.json +53 -0
- package/bundle/boards/cache-demo-board.json +59 -0
- package/bundle/boards/camera-demo-board.json +28 -0
- package/bundle/boards/canvas-demo-board.json +55 -0
- package/bundle/boards/changes-demo-board.json +60 -0
- package/bundle/boards/court-booking-browser-demo-board.json +221 -0
- package/bundle/boards/court-booking-demo-board.json +218 -0
- package/bundle/boards/current-time-board.json +32 -0
- package/bundle/boards/debounce-demo-board.json +43 -0
- package/bundle/boards/decrypt-demo-board.json +47 -0
- package/bundle/boards/delay-demo-board.json +28 -0
- package/bundle/boards/detect-demo-board.json +64 -0
- package/bundle/boards/document-extract-demo-board.json +55 -0
- package/bundle/boards/dropitapp-board.json +138 -0
- package/bundle/boards/encode-demo-board.json +39 -0
- package/bundle/boards/encrypt-board.json +185 -0
- package/bundle/boards/encrypt-demo-board.json +39 -0
- package/bundle/boards/face-alert-board.json +181 -0
- package/bundle/boards/fetcher-demo-board.json +40 -0
- package/bundle/boards/fft-demo-board.json +28 -0
- package/bundle/boards/filter-demo-board.json +55 -0
- package/bundle/boards/flat-map-demo-board.json +42 -0
- package/bundle/boards/frame-limit-test-board.json +130 -0
- package/bundle/boards/game-board.json +413 -0
- package/bundle/boards/game-of-life-board.json +139 -0
- package/bundle/boards/game-of-life-demo-board.json +34 -0
- package/bundle/boards/gather-demo-board.json +62 -0
- package/bundle/boards/group-by-demo-board.json +62 -0
- package/bundle/boards/hacker-demo-board.json +45 -0
- package/bundle/boards/hacker-news-board.json +741 -0
- package/bundle/boards/hash-demo-board.json +40 -0
- package/bundle/boards/health-log-browser-demo-board.json +537 -0
- package/bundle/boards/health-log-demo-board.json +498 -0
- package/bundle/boards/helloworld-board.json +57 -0
- package/bundle/boards/hold-demo-board.json +67 -0
- package/bundle/boards/hold-scopes-demo-board.json +141 -0
- package/bundle/boards/http-client-browser-demo-board.json +379 -0
- package/bundle/boards/http-client-demo-board.json +380 -0
- package/bundle/boards/image-picker-demo-board.json +22 -0
- package/bundle/boards/imap-email-demo-board.json +35 -0
- package/bundle/boards/injector-demo-board.json +55 -0
- package/bundle/boards/iterator-demo-board.json +55 -0
- package/bundle/boards/limit-demo-board.json +66 -0
- package/bundle/boards/link-debugger.json +32 -0
- package/bundle/boards/live-location-demo-board.json +93 -0
- package/bundle/boards/live-radio-cloud-demo-board.json +216 -0
- package/bundle/boards/live-radio-cloud-direct-demo-board.json +311 -0
- package/bundle/boards/live-radio-demo-board.json +211 -0
- package/bundle/boards/live-radio-members-demo-board.json +314 -0
- package/bundle/boards/local-storage-demo-board.json +30 -0
- package/bundle/boards/lz-compress-demo-board.json +52 -0
- package/bundle/boards/map-demo-board.json +46 -0
- package/bundle/boards/match-filter-demo-board.json +43 -0
- package/bundle/boards/meeting-poll-browser-demo-board.json +649 -0
- package/bundle/boards/meeting-poll-demo-board.json +650 -0
- package/bundle/boards/microphone-monitor-demo-board.json +28 -0
- package/bundle/boards/microphone-speaker-demo-board.json +86 -0
- package/bundle/boards/monitor-demo-board.json +52 -0
- package/bundle/boards/mounted-endpoint-demo-board-hkp-rt.json +84 -0
- package/bundle/boards/mounted-endpoint-demo-board.json +84 -0
- package/bundle/boards/nested-rhythm-demo-board.json +1160 -0
- package/bundle/boards/next-bus-board.json +52 -0
- package/bundle/boards/next-bus-switch-board.json +79 -0
- package/bundle/boards/night-groove-demo-board.json +742 -0
- package/bundle/boards/noise-alert-board.json +146 -0
- package/bundle/boards/offer-followup-demo-board.json +291 -0
- package/bundle/boards/offer-intake-demo-board.json +289 -0
- package/bundle/boards/offer-intake-hetzner-demo-board.json +286 -0
- package/bundle/boards/offer-intake-imap-demo-board.json +289 -0
- package/bundle/boards/offer-intake-imap-hetzner-demo-board.json +354 -0
- package/bundle/boards/p2p-receiver-demo-board.json +65 -0
- package/bundle/boards/p2p-sender-demo-board.json +94 -0
- package/bundle/boards/pad-groove-demo-board.json +644 -0
- package/bundle/boards/peer-chat-board.json +109 -0
- package/bundle/boards/peer-chat-node-board.json +97 -0
- package/bundle/boards/qr-code-demo-board.json +22 -0
- package/bundle/boards/queue-demo-board.json +239 -0
- package/bundle/boards/reduce-demo-board.json +54 -0
- package/bundle/boards/remote-named-demo-board-hkp-rt.json +61 -0
- package/bundle/boards/remote-named-demo-board.json +61 -0
- package/bundle/boards/rss-demo-board.json +530 -0
- package/bundle/boards/rss-radio-board.json +515 -0
- package/bundle/boards/rss-radio-brief-one-board.json +237 -0
- package/bundle/boards/rss-radio-editor-unit-board.json +555 -0
- package/bundle/boards/rss-radio-library-unit-board.json +293 -0
- package/bundle/boards/rss-radio-unit-board.json +809 -0
- package/bundle/boards/rss-radio-voice-unit-board.json +146 -0
- package/bundle/boards/runtime-configs/hold-example.json +41 -0
- package/bundle/boards/runtime-configs/injector-example.json +23 -0
- package/bundle/boards/runtime-configs/speech-to-text-example.json +35 -0
- package/bundle/boards/runtime-configs/text-generation-example.json +31 -0
- package/bundle/boards/runtime-configs/text-to-speech-example.json +28 -0
- package/bundle/boards/runtime-configs/text-to-speech-inflect-example.json +28 -0
- package/bundle/boards/runtime-configs/ws-audio-playback-example.json +23 -0
- package/bundle/boards/select-demo-board.json +32 -0
- package/bundle/boards/send-ntfy-board.json +52 -0
- package/bundle/boards/shared-costs-demo-board.json +361 -0
- package/bundle/boards/sign-demo-board.json +41 -0
- package/bundle/boards/skill-router-demo-board.json +210 -0
- package/bundle/boards/smooth-demo-board.json +91 -0
- package/bundle/boards/smtp-email-demo-board.json +34 -0
- package/bundle/boards/sort-demo-board.json +55 -0
- package/bundle/boards/sound-demo-board.json +65 -0
- package/bundle/boards/spectral-modifier-board.json +98 -0
- package/bundle/boards/speech-synth-demo-board.json +37 -0
- package/bundle/boards/speech-to-text-demo-board.json +146 -0
- package/bundle/boards/spotify-board.json +75 -0
- package/bundle/boards/spread-demo-board.json +35 -0
- package/bundle/boards/sql-demo-board.json +56 -0
- package/bundle/boards/sql-explorer-board.json +447 -0
- package/bundle/boards/sql-explorer-node-board.json +474 -0
- package/bundle/boards/sql-import-board.json +156 -0
- package/bundle/boards/state-demo-board.json +65 -0
- package/bundle/boards/stopper-demo-board.json +40 -0
- package/bundle/boards/storage-demo-board.json +193 -0
- package/bundle/boards/store-demo-board.json +63 -0
- package/bundle/boards/swimlanes-demo-board.json +197 -0
- package/bundle/boards/switch-demo-board.json +51 -0
- package/bundle/boards/syn-board.json +19 -0
- package/bundle/boards/syn-booking-unit-board.json +998 -0
- package/bundle/boards/syn-conversations-anthropic-demo-board.json +925 -0
- package/bundle/boards/syn-conversations-demo-board.json +925 -0
- package/bundle/boards/syn-hotels-unit-board.json +287 -0
- package/bundle/boards/syn-mail-desk-board.json +25 -0
- package/bundle/boards/syn-mail-desk-unit-board.json +254 -0
- package/bundle/boards/telegram-listener-demo-board.json +31 -0
- package/bundle/boards/text-generation-anthropic-demo-board.json +66 -0
- package/bundle/boards/text-generation-demo-board.json +51 -0
- package/bundle/boards/text-generation-local-demo-board.json +80 -0
- package/bundle/boards/text-to-speech-demo-board.json +58 -0
- package/bundle/boards/timeline-demo-board.json +477 -0
- package/bundle/boards/timer-demo-board.json +35 -0
- package/bundle/boards/tracks-demo-board.json +95 -0
- package/bundle/boards/trigger-pad-demo-board.json +47 -0
- package/bundle/boards/triggerpad-board.json +31 -0
- package/bundle/boards/triggerpad-recorder-board.json +56 -0
- package/bundle/boards/uuid-generator-demo-board.json +166 -0
- package/bundle/boards/voice-assistant-demo-board.json +230 -0
- package/bundle/boards/voice-assistant-hkp-rt-demo-board.json +239 -0
- package/bundle/boards/voice-assistant-local-demo-board.json +232 -0
- package/bundle/boards/voice-assistant-skills-demo-board.json +316 -0
- package/bundle/boards/voice-assistant-skills-local-demo-board.json +316 -0
- package/bundle/boards/xy-pad-demo-board.json +36 -0
- package/bundle/docs/content/board-json.md +277 -0
- package/bundle/docs/content/boards/alpaca-board.md +56 -0
- package/bundle/docs/content/boards/animate-board.md +40 -0
- package/bundle/docs/content/boards/ascii-cam-board.md +37 -0
- package/bundle/docs/content/boards/audiolize-board.md +47 -0
- package/bundle/docs/content/boards/court-booking-browser-demo-board.md +43 -0
- package/bundle/docs/content/boards/court-booking-demo-board.md +120 -0
- package/bundle/docs/content/boards/current-time-board.md +32 -0
- package/bundle/docs/content/boards/dropitapp-board.md +57 -0
- package/bundle/docs/content/boards/encrypt-board.md +36 -0
- package/bundle/docs/content/boards/face-alert-board.md +50 -0
- package/bundle/docs/content/boards/game-board.md +69 -0
- package/bundle/docs/content/boards/game-of-life-board.md +47 -0
- package/bundle/docs/content/boards/hacker-news-board.md +76 -0
- package/bundle/docs/content/boards/health-log-browser-demo-board.md +56 -0
- package/bundle/docs/content/boards/health-log-demo-board.md +138 -0
- package/bundle/docs/content/boards/helloworld-board.md +40 -0
- package/bundle/docs/content/boards/link-debugger.md +31 -0
- package/bundle/docs/content/boards/live-radio-cloud-demo-board.md +70 -0
- package/bundle/docs/content/boards/live-radio-cloud-direct-demo-board.md +89 -0
- package/bundle/docs/content/boards/live-radio-demo-board.md +102 -0
- package/bundle/docs/content/boards/live-radio-members-demo-board.md +91 -0
- package/bundle/docs/content/boards/meeting-poll-browser-demo-board.md +45 -0
- package/bundle/docs/content/boards/meeting-poll-demo-board.md +121 -0
- package/bundle/docs/content/boards/mounted-endpoint-demo-board-hkp-rt.md +50 -0
- package/bundle/docs/content/boards/nested-rhythm-demo-board.md +165 -0
- package/bundle/docs/content/boards/next-bus-board.md +38 -0
- package/bundle/docs/content/boards/next-bus-switch-board.md +44 -0
- package/bundle/docs/content/boards/night-groove-demo-board.md +110 -0
- package/bundle/docs/content/boards/noise-alert-board.md +44 -0
- package/bundle/docs/content/boards/pad-groove-demo-board.md +93 -0
- package/bundle/docs/content/boards/peer-chat-board.md +49 -0
- package/bundle/docs/content/boards/peer-chat-node-board.md +47 -0
- package/bundle/docs/content/boards/rss-radio-board.md +221 -0
- package/bundle/docs/content/boards/send-ntfy-board.md +33 -0
- package/bundle/docs/content/boards/shared-costs-demo-board.md +65 -0
- package/bundle/docs/content/boards/spectral-modifier-board.md +55 -0
- package/bundle/docs/content/boards/spotify-board.md +46 -0
- package/bundle/docs/content/boards/sql-explorer-board.md +70 -0
- package/bundle/docs/content/boards/sql-explorer-node-board.md +76 -0
- package/bundle/docs/content/boards/sql-import-board.md +37 -0
- package/bundle/docs/content/boards/swimlanes-demo-board.md +148 -0
- package/bundle/docs/content/boards/syn-mail-desk-board.md +52 -0
- package/bundle/docs/content/boards/timeline-demo-board.md +115 -0
- package/bundle/docs/content/boards/triggerpad-board.md +32 -0
- package/bundle/docs/content/boards/triggerpad-recorder-board.md +52 -0
- package/bundle/docs/content/boards/voice-assistant-demo-board.md +51 -0
- package/bundle/docs/content/concepts/assets.md +245 -0
- package/bundle/docs/content/concepts/blocks.md +300 -0
- package/bundle/docs/content/concepts/board-assistant.md +307 -0
- package/bundle/docs/content/concepts/board.md +265 -0
- package/bundle/docs/content/concepts/cloud-boards.md +803 -0
- package/bundle/docs/content/concepts/coordinator.md +297 -0
- package/bundle/docs/content/concepts/logging.md +293 -0
- package/bundle/docs/content/concepts/mounts.md +314 -0
- package/bundle/docs/content/concepts/presets.md +360 -0
- package/bundle/docs/content/concepts/remotes.md +423 -0
- package/bundle/docs/content/concepts/runtime.md +664 -0
- package/bundle/docs/content/concepts/scopes.md +256 -0
- package/bundle/docs/content/concepts/service.md +227 -0
- package/bundle/docs/content/concepts/units.md +321 -0
- package/bundle/docs/content/introduction.md +163 -0
- package/bundle/docs/content/llm/circle-text-board.json +55 -0
- package/bundle/docs/content/llm/howto-workflow.md +369 -0
- package/bundle/docs/content/repository.md +161 -0
- package/bundle/docs/content/services/aggregator.md +76 -0
- package/bundle/docs/content/services/analyzer.md +44 -0
- package/bundle/docs/content/services/ascii-art.md +58 -0
- package/bundle/docs/content/services/asset.md +88 -0
- package/bundle/docs/content/services/audio-editor.md +57 -0
- package/bundle/docs/content/services/audio-encode.md +115 -0
- package/bundle/docs/content/services/audio-io.md +173 -0
- package/bundle/docs/content/services/batcher.md +49 -0
- package/bundle/docs/content/services/board-service.md +48 -0
- package/bundle/docs/content/services/browser-sub-service.md +75 -0
- package/bundle/docs/content/services/buffer.md +70 -0
- package/bundle/docs/content/services/cache.md +92 -0
- package/bundle/docs/content/services/camera.md +85 -0
- package/bundle/docs/content/services/canvas.md +196 -0
- package/bundle/docs/content/services/changes.md +87 -0
- package/bundle/docs/content/services/chunked-file-provider.md +63 -0
- package/bundle/docs/content/services/communication-dispatcher.md +190 -0
- package/bundle/docs/content/services/configurator.md +66 -0
- package/bundle/docs/content/services/conversations.md +244 -0
- package/bundle/docs/content/services/debounce.md +45 -0
- package/bundle/docs/content/services/decrypt.md +53 -0
- package/bundle/docs/content/services/delay.md +55 -0
- package/bundle/docs/content/services/detect.md +101 -0
- package/bundle/docs/content/services/document-extract.md +174 -0
- package/bundle/docs/content/services/download.md +67 -0
- package/bundle/docs/content/services/encode.md +63 -0
- package/bundle/docs/content/services/encrypt.md +53 -0
- package/bundle/docs/content/services/fetcher.md +122 -0
- package/bundle/docs/content/services/fft.md +96 -0
- package/bundle/docs/content/services/file-source.md +67 -0
- package/bundle/docs/content/services/filesystem.md +157 -0
- package/bundle/docs/content/services/filter.md +133 -0
- package/bundle/docs/content/services/flat-map.md +62 -0
- package/bundle/docs/content/services/game-of-life.md +93 -0
- package/bundle/docs/content/services/gather.md +135 -0
- package/bundle/docs/content/services/gif-encoder.md +56 -0
- package/bundle/docs/content/services/github.md +85 -0
- package/bundle/docs/content/services/group-by.md +54 -0
- package/bundle/docs/content/services/hacker.md +79 -0
- package/bundle/docs/content/services/hash.md +59 -0
- package/bundle/docs/content/services/hold.md +182 -0
- package/bundle/docs/content/services/http-relay-client.md +48 -0
- package/bundle/docs/content/services/http-uploader.md +62 -0
- package/bundle/docs/content/services/http.md +424 -0
- package/bundle/docs/content/services/if.md +79 -0
- package/bundle/docs/content/services/ifft.md +46 -0
- package/bundle/docs/content/services/image-picker.md +50 -0
- package/bundle/docs/content/services/imap-email.md +104 -0
- package/bundle/docs/content/services/injector.md +129 -0
- package/bundle/docs/content/services/input.md +90 -0
- package/bundle/docs/content/services/iterator.md +186 -0
- package/bundle/docs/content/services/join.md +153 -0
- package/bundle/docs/content/services/limit.md +47 -0
- package/bundle/docs/content/services/local-storage.md +47 -0
- package/bundle/docs/content/services/looper.md +62 -0
- package/bundle/docs/content/services/lz-compress.md +52 -0
- package/bundle/docs/content/services/map.md +257 -0
- package/bundle/docs/content/services/match-filter.md +38 -0
- package/bundle/docs/content/services/microphone-monitor.md +66 -0
- package/bundle/docs/content/services/monitor.md +67 -0
- package/bundle/docs/content/services/ollama.md +116 -0
- package/bundle/docs/content/services/openai-prompt.md +74 -0
- package/bundle/docs/content/services/output.md +107 -0
- package/bundle/docs/content/services/peer-socket.md +61 -0
- package/bundle/docs/content/services/qr-code.md +48 -0
- package/bundle/docs/content/services/queue.md +201 -0
- package/bundle/docs/content/services/reduce.md +51 -0
- package/bundle/docs/content/services/rss.md +232 -0
- package/bundle/docs/content/services/select.md +47 -0
- package/bundle/docs/content/services/sign.md +53 -0
- package/bundle/docs/content/services/skill-router.md +154 -0
- package/bundle/docs/content/services/smooth.md +59 -0
- package/bundle/docs/content/services/smtp-email.md +129 -0
- package/bundle/docs/content/services/sort.md +48 -0
- package/bundle/docs/content/services/sound.md +87 -0
- package/bundle/docs/content/services/speech-synth.md +46 -0
- package/bundle/docs/content/services/speech-to-text.md +172 -0
- package/bundle/docs/content/services/spotify.md +77 -0
- package/bundle/docs/content/services/spread.md +111 -0
- package/bundle/docs/content/services/sql.md +491 -0
- package/bundle/docs/content/services/state.md +57 -0
- package/bundle/docs/content/services/static.md +47 -0
- package/bundle/docs/content/services/stopper.md +55 -0
- package/bundle/docs/content/services/storage.md +155 -0
- package/bundle/docs/content/services/store.md +255 -0
- package/bundle/docs/content/services/sub-service.md +152 -0
- package/bundle/docs/content/services/switch.md +67 -0
- package/bundle/docs/content/services/telegram-listener.md +76 -0
- package/bundle/docs/content/services/text-generation.md +390 -0
- package/bundle/docs/content/services/text-to-speech.md +130 -0
- package/bundle/docs/content/services/timeline.md +333 -0
- package/bundle/docs/content/services/timer.md +113 -0
- package/bundle/docs/content/services/tracks.md +207 -0
- package/bundle/docs/content/services/trigger-pad.md +68 -0
- package/bundle/docs/content/services/uuid-generator.md +48 -0
- package/bundle/docs/content/services/wav-reader.md +66 -0
- package/bundle/docs/content/services/websocket.md +189 -0
- package/bundle/docs/content/services/workflow-board-builder.md +65 -0
- package/bundle/docs/content/services/xy-pad.md +60 -0
- package/bundle/docs/content/targets.md +434 -0
- package/bundle/docs/content/testing.md +263 -0
- package/bundle/docs/content/vocabulary.md +171 -0
- package/bundle/hkp-frontend/src/runtime/browser/BrowserRegistry.tsx +141 -0
- package/bundle/hkp-frontend/src/runtime/browser/BrowserRuntime.tsx +202 -0
- package/bundle/hkp-frontend/src/runtime/browser/BrowserRuntimeApi.ts +306 -0
- package/bundle/hkp-frontend/src/runtime/browser/BrowserRuntimeApp.ts +310 -0
- package/bundle/hkp-frontend/src/runtime/browser/BrowserRuntimeScope.ts +500 -0
- package/bundle/hkp-frontend/src/runtime/browser/UIRegistry.ts +150 -0
- package/bundle/hkp-frontend/src/runtime/browser/assetResolver.ts +123 -0
- package/bundle/hkp-frontend/src/runtime/browser/pipelineNames.ts +65 -0
- package/bundle/hkp-frontend/src/runtime/browser/registry/Default.ts +237 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Aggregator.ts +127 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AggregatorUI.tsx +83 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Analyzer.tsx +43 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AnalyzerUI/Bars.tsx +33 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AnalyzerUI/HorizontalSpectrogram.tsx +53 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AnalyzerUI/VerticalSpectogram.tsx +56 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AnalyzerUI/Waveform.tsx +109 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AnalyzerUI/index.tsx +99 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AsciiArt.ts +119 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AsciiArtUI.tsx +131 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Asset.ts +125 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AssetUI.tsx +37 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AudioDeviceSettings.tsx +56 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AudioEditor.ts +129 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AudioEditorUI.tsx +549 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AudioInput.ts +298 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AudioInputUI.tsx +257 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AudioOutput.ts +189 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/AudioOutputUI.tsx +63 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Batcher.ts +11 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/BoardService.tsx +86 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/BoardServiceUI.tsx +410 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/BrowserGather.ts +311 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/BrowserIterator.ts +167 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/BrowserSubService.tsx +583 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/BrowserSubServiceUI.tsx +187 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/BrowserTracks.tsx +477 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Buffer.ts +11 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Cache.ts +134 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/CacheUI.tsx +125 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Camera.ts +90 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/CameraUI.tsx +321 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Canvas.ts +139 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/CanvasUI/canvasDraw.ts +543 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/CanvasUI/canvasUtils.ts +39 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/CanvasUI/index.tsx +287 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/CanvasUI/tests/canvasDraw.test.ts +355 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/CanvasUI/tests/canvasUtils.test.ts +89 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/CanvasUI/tests/fullscreen.test.tsx +26 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Changes.ts +201 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/ChangesUI.tsx +85 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/ChunkedFileProvider.tsx +183 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Configurator.ts +258 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/ConfiguratorUI.tsx +83 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/ConsideredHacker.tsx +28 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Debounce.ts +75 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/DebounceUI.tsx +70 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Decrypt.ts +127 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/DecryptUI.tsx +39 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Delay.tsx +110 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Detect.ts +214 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/DetectUI.tsx +86 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Download.ts +120 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/DownloadUI.tsx +61 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Encode.ts +138 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/EncodeUI.tsx +52 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Encrypt.ts +125 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/EncryptUI.tsx +39 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/FFT.tsx +238 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/FFTUI.tsx +112 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/FeedbackService.ts +247 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/FeedbackServiceUI.tsx +35 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Fetcher.tsx +232 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/FetcherUI.tsx +154 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/FileSource.tsx +171 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Filter.tsx +18 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/FilterUI.tsx +89 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/FlatMap.ts +68 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/FlatMapUI.tsx +38 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/GameOfLife.ts +210 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/GameOfLifeRenderer.ts +182 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/GameOfLifeRendererUI.tsx +48 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/GameOfLifeUI.tsx +58 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/GatherUI.tsx +84 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/GifEncoder.tsx +651 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/GithubAPI.ts +294 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/GithubComponents.tsx +389 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/GithubSink.tsx +109 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/GithubSinkUI.tsx +143 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/GithubSource.tsx +86 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/GithubSourceUI.tsx +162 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/GroupBy.ts +11 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/HTTPUploader.ts +102 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Hacker.ts +73 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/HackerUI.tsx +134 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Hash.ts +134 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/HashUI.tsx +45 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Hold.ts +288 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/HoldUI.tsx +43 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/HttpClient.ts +558 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/HttpClientUI.tsx +212 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/HttpUploaderTokenInjector.ts +149 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/IfService.ts +231 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/IfServiceUI.tsx +50 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/ImagePicker.tsx +118 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Injector.ts +61 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/InjectorUI.tsx +389 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Input.ts +214 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/InputUI.tsx +71 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/IteratorUI.tsx +59 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/LZCompress.ts +63 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Limit.ts +39 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/LimitUI.tsx +41 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/LocalStorage.ts +65 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/LocalStorageUI.tsx +72 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Map.ts +14 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/MapUI.tsx +334 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/MapUIModeAssist.tsx +61 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/MatchFilter.ts +11 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/MicrophoneMonitor.ts +190 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/MicrophoneMonitorUI.tsx +94 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Monitor.tsx +15 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/MonitorUI.tsx +281 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/OllamaPrompt.ts +237 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/OllamaPromptUI/BusyIndicator.tsx +18 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/OllamaPromptUI/PromptInput.tsx +71 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/OllamaPromptUI/StreamingPreview.tsx +24 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/OllamaPromptUI/index.tsx +156 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/OpenAIPrompt.ts +254 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/OpenAIPromptUI.tsx +189 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Output.tsx +145 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/OutputUI.tsx +118 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/PeerChatTemplate.json +43 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/PeerConnection.ts +260 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/PeerSocket.tsx +268 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/PeerSocketReceiverTemplate.json +29 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/PeerSocketUI.tsx +341 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/PlaceholderUI.tsx +72 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/QrCode.ts +63 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/QrCodeUI.tsx +197 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Select.ts +40 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SelectUI.tsx +41 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/ServiceBase.ts +50 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SetRuntimeVariable.ts +65 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SetRuntimeVariableUI.tsx +50 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Sign.ts +182 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SignUI.tsx +55 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Smooth.ts +101 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SmoothUI.tsx +50 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Sort.ts +59 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SortUI.tsx +61 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Sound.ts +541 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SoundUI.tsx +183 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SpeechSynth.ts +56 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SpeechSynthUI.tsx +108 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Spotify.tsx +111 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SpotifyAPI.ts +113 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SpotifyComponents.tsx +104 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SpotifyUI.tsx +186 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Spread.ts +117 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SpreadUI.tsx +38 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Sql.ts +448 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SqlInspector.tsx +332 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SqlUI.tsx +226 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/State.ts +149 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Stopper.ts +29 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Switch.tsx +419 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/SwitchUI.tsx +171 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/TickRuleDelta.ts +101 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/TickRuleDeltaUI.tsx +56 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Timeline.ts +709 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/TimelineUI/TimelinePanel.tsx +79 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/TimelineUI/TimelineRows.tsx +574 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/TimelineUI/Transport.tsx +141 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/TimelineUI/index.tsx +119 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/TimelineUI/model.ts +425 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/TimelineUI/parts.tsx +708 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/Timer.ts +15 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/TimerUI.tsx +213 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/TracksUI.tsx +81 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/TriggerPad.ts +108 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/TriggerPadUI.tsx +160 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/UuidGenerator.ts +74 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/UuidGeneratorUI.tsx +59 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/WaveformDisplay.tsx +104 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/WebsocketClient.ts +114 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/WebsocketClientUI.tsx +42 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/WorkflowBoardBuilder.ts +499 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/WorkflowBoardBuilderUI.tsx +521 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/XYPad.ts +68 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/XYPadUI.tsx +274 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/audio/audioHelper.ts +36 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/base/Batcher.ts +76 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/base/Buffer.ts +142 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/base/Filter.ts +125 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/base/GroupBy.ts +101 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/base/Map.ts +543 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/base/MatchFilter.ts +49 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/base/Monitor.ts +75 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/base/Reduce.ts +74 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/base/Timer.ts +342 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/base/bundle.js +7375 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/base/eval.ts +208 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/base/expressionEval.ts +223 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/base/helpers.ts +10 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/base/index.ts +37 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/camera/videoCapture.ts +78 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/changes-modes.ts +9 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/colorpalette.ts +26 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/detect/DetectionPreview.tsx +76 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/detect/mediapipe.ts +34 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/detect/models/README.md +14 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/detect/models/blaze_face_short_range.tflite +0 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/detect-modes.ts +7 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/encode-modes.ts +10 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/helpers.ts +300 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/http-client-methods.ts +10 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/sql-database.ts +594 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/sql-dump.ts +192 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/sql-inspect.ts +130 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/sql-inspector.css +155 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/sql-modes.ts +27 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/TESTING_APPROACH.md +169 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/__snapshots__/service-ui.future-enhancements.test.tsx.snap +5 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/audio-input-permissions.test.ts +42 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/audiolizeLanes.test.ts +70 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/browser-scopes.test.ts +305 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/cache-service.test.ts +53 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/camera-video-capture.test.ts +24 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/changes-service.test.ts +133 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/crypto-secrets.test.ts +196 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/detect-service.test.ts +119 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/download.test.ts +100 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/expressionEval.test.ts +117 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/fetcher-panel.test.tsx +35 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/fetcher-service.test.ts +80 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/filter-service.test.ts +37 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/github-secrets.test.ts +108 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/group-by-board.test.ts +42 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/hold-service.test.ts +199 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/http-client-service.test.ts +474 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/http-uploader-token-injector.test.ts +152 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/iterator-gather-service.test.ts +277 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/map-service.test.ts +1047 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/map-ui.test.tsx +70 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/nested-rhythm-board.test.ts +311 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/night-groove-board.test.ts +290 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/pad-groove-board.test.ts +230 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/peer-host-discovery.test.ts +77 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/peer-socket-discovery.test.ts +69 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/pipeline-names.test.ts +63 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/secret-canary.test.ts +121 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/service-modules.contract.test.ts +229 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/service-ui.advanced.test.tsx +670 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/service-ui.future-enhancements.test.tsx +219 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/service-ui.integration.test.tsx +432 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/service-ui.smoke.test.tsx +140 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/sound-service.test.ts +293 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/spread-service.test.ts +137 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/sql-dump.test.ts +172 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/sql-inspect.test.ts +163 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/sql-inspector.test.tsx +121 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/sql.test.ts +702 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/sub-service-in-block.test.tsx +84 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/switch-service.test.ts +254 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/timeline-board.test.ts +218 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/timeline-service.test.ts +1002 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/timeline-ui-model.test.ts +230 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/timeline-ui.test.tsx +371 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/timer-service.test.ts +902 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/tracks-service.test.ts +275 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/tracks-ui.test.tsx +126 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/triggerpad-recorder-board.test.ts +100 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/tests/uuid-generator-service.test.ts +214 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/timeline-core.ts +410 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/workflow-prompt/DefaultWorkflowBoard.ts +90 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/workflow-prompt/RefinementSession.ts +121 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/workflow-prompt/SystemPromptCatalog.ts +245 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/workflow-prompt/catalog/browser-service-specs.json +110 -0
- package/bundle/hkp-frontend/src/runtime/browser/services/workflow-prompt/catalog/runtime-capabilities.json +37 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/asset-service.test.ts +73 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/board-persistence.integration.test.tsx +391 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/browser-runtime.identity-binding.test.tsx +81 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/demo-boards.regression.test.tsx +386 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/failed-call-lifecycle.test.ts +56 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/http-client.integration.test.ts +146 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/nested-run.integration.test.ts +415 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/replay-next.test.ts +391 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/rerun.test.ts +71 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/run-no-input.test.ts +72 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/runtime-add.integration.test.tsx +256 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/runtime-operations.integration.test.tsx +310 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/runtime-processing.integration.test.ts +311 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/runtime-removal.integration.test.tsx +454 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/runtime-update.identity.integration.test.tsx +145 -0
- package/bundle/hkp-frontend/src/runtime/browser/tests/service-operations.integration.test.tsx +511 -0
- package/bundle/hkp-node/src/address.ts +72 -0
- package/bundle/hkp-node/src/assets.ts +582 -0
- package/bundle/hkp-node/src/auth.ts +369 -0
- package/bundle/hkp-node/src/callReport.ts +281 -0
- package/bundle/hkp-node/src/coordinator/auth.ts +85 -0
- package/bundle/hkp-node/src/coordinator/binaryFrame.ts +189 -0
- package/bundle/hkp-node/src/coordinator/boardStore.ts +0 -0
- package/bundle/hkp-node/src/coordinator/bridge.ts +242 -0
- package/bundle/hkp-node/src/coordinator/bridgeProtocol.ts +200 -0
- package/bundle/hkp-node/src/coordinator/coordinator.ts +594 -0
- package/bundle/hkp-node/src/coordinator/facadeAccess.ts +426 -0
- package/bundle/hkp-node/src/coordinator/fileBoardStore.ts +159 -0
- package/bundle/hkp-node/src/coordinator/frameLimits.ts +41 -0
- package/bundle/hkp-node/src/coordinator/index.ts +12 -0
- package/bundle/hkp-node/src/coordinator/join.ts +62 -0
- package/bundle/hkp-node/src/coordinator/logStore.ts +335 -0
- package/bundle/hkp-node/src/coordinator/members.ts +133 -0
- package/bundle/hkp-node/src/coordinator/mount.ts +124 -0
- package/bundle/hkp-node/src/coordinator/participantProtocol.ts +169 -0
- package/bundle/hkp-node/src/coordinator/participants.ts +666 -0
- package/bundle/hkp-node/src/coordinator/router.ts +416 -0
- package/bundle/hkp-node/src/coordinator/session.ts +1610 -0
- package/bundle/hkp-node/src/coordinator/types.ts +95 -0
- package/bundle/hkp-node/src/coordinatorLinks.ts +712 -0
- package/bundle/hkp-node/src/credentialedFetch.ts +122 -0
- package/bundle/hkp-node/src/egress.ts +344 -0
- package/bundle/hkp-node/src/expressionEval.ts +223 -0
- package/bundle/hkp-node/src/index.ts +470 -0
- package/bundle/hkp-node/src/instance.ts +172 -0
- package/bundle/hkp-node/src/mounts.ts +296 -0
- package/bundle/hkp-node/src/origins.ts +201 -0
- package/bundle/hkp-node/src/reset.ts +187 -0
- package/bundle/hkp-node/src/runtime.ts +1345 -0
- package/bundle/hkp-node/src/secrets.ts +292 -0
- package/bundle/hkp-node/src/server.ts +2120 -0
- package/bundle/hkp-node/src/services/asset.ts +150 -0
- package/bundle/hkp-node/src/services/claudeModels.ts +370 -0
- package/bundle/hkp-node/src/services/communication-dispatcher.ts +735 -0
- package/bundle/hkp-node/src/services/conversations.ts +914 -0
- package/bundle/hkp-node/src/services/database.ts +386 -0
- package/bundle/hkp-node/src/services/document-extract.ts +575 -0
- package/bundle/hkp-node/src/services/expression.ts +417 -0
- package/bundle/hkp-node/src/services/fileStore.ts +369 -0
- package/bundle/hkp-node/src/services/filesystem.ts +280 -0
- package/bundle/hkp-node/src/services/gather.ts +335 -0
- package/bundle/hkp-node/src/services/hold.ts +275 -0
- package/bundle/hkp-node/src/services/http-client.ts +525 -0
- package/bundle/hkp-node/src/services/http-server.ts +1222 -0
- package/bundle/hkp-node/src/services/imap-email.ts +627 -0
- package/bundle/hkp-node/src/services/injector.ts +135 -0
- package/bundle/hkp-node/src/services/iterator.ts +203 -0
- package/bundle/hkp-node/src/services/join.ts +226 -0
- package/bundle/hkp-node/src/services/map.ts +632 -0
- package/bundle/hkp-node/src/services/monitor.ts +128 -0
- package/bundle/hkp-node/src/services/nested-pipeline.ts +405 -0
- package/bundle/hkp-node/src/services/peer-server.ts +268 -0
- package/bundle/hkp-node/src/services/queue-store.ts +301 -0
- package/bundle/hkp-node/src/services/queue.ts +316 -0
- package/bundle/hkp-node/src/services/recordStore.ts +341 -0
- package/bundle/hkp-node/src/services/rss-parse.ts +281 -0
- package/bundle/hkp-node/src/services/rss.ts +392 -0
- package/bundle/hkp-node/src/services/smtp-email.ts +398 -0
- package/bundle/hkp-node/src/services/spread.ts +153 -0
- package/bundle/hkp-node/src/services/sql-dump.ts +192 -0
- package/bundle/hkp-node/src/services/sql.ts +429 -0
- package/bundle/hkp-node/src/services/stopper.ts +69 -0
- package/bundle/hkp-node/src/services/storage.ts +332 -0
- package/bundle/hkp-node/src/services/store.ts +609 -0
- package/bundle/hkp-node/src/services/stream.ts +367 -0
- package/bundle/hkp-node/src/services/sub-service.ts +600 -0
- package/bundle/hkp-node/src/services/telegram-listener.ts +263 -0
- package/bundle/hkp-node/src/services/telegram-sender.ts +136 -0
- package/bundle/hkp-node/src/services/text-generation.ts +1249 -0
- package/bundle/hkp-node/src/services/timer.ts +273 -0
- package/bundle/hkp-node/src/services/tracks.ts +381 -0
- package/bundle/hkp-node/src/services/websocket-reader.ts +364 -0
- package/bundle/hkp-node/src/types.ts +465 -0
- package/bundle/hkp-node/src/wsTickets.ts +77 -0
- package/bundle/hkp-node/src/yas.ts +95 -0
- package/bundle/hkp-python/src/hkp/__init__.py +1 -0
- package/bundle/hkp-python/src/hkp/__main__.py +241 -0
- package/bundle/hkp-python/src/hkp/address.py +56 -0
- package/bundle/hkp-python/src/hkp/assets.py +439 -0
- package/bundle/hkp-python/src/hkp/auth.py +252 -0
- package/bundle/hkp-python/src/hkp/binary_frame.py +100 -0
- package/bundle/hkp-python/src/hkp/call_report.py +201 -0
- package/bundle/hkp-python/src/hkp/coordinator_links.py +667 -0
- package/bundle/hkp-python/src/hkp/data.py +118 -0
- package/bundle/hkp-python/src/hkp/egress.py +310 -0
- package/bundle/hkp-python/src/hkp/mount.py +46 -0
- package/bundle/hkp-python/src/hkp/mounts.py +288 -0
- package/bundle/hkp-python/src/hkp/origins.py +169 -0
- package/bundle/hkp-python/src/hkp/runtime.py +1131 -0
- package/bundle/hkp-python/src/hkp/secrets.py +261 -0
- package/bundle/hkp-python/src/hkp/server.py +1714 -0
- package/bundle/hkp-python/src/hkp/services/__init__.py +0 -0
- package/bundle/hkp-python/src/hkp/services/asset.py +123 -0
- package/bundle/hkp-python/src/hkp/services/audio_encode.py +190 -0
- package/bundle/hkp-python/src/hkp/services/expression.py +942 -0
- package/bundle/hkp-python/src/hkp/services/gather.py +266 -0
- package/bundle/hkp-python/src/hkp/services/hold.py +246 -0
- package/bundle/hkp-python/src/hkp/services/http_client.py +444 -0
- package/bundle/hkp-python/src/hkp/services/http_server.py +790 -0
- package/bundle/hkp-python/src/hkp/services/iterator.py +141 -0
- package/bundle/hkp-python/src/hkp/services/join.py +173 -0
- package/bundle/hkp-python/src/hkp/services/map_service.py +452 -0
- package/bundle/hkp-python/src/hkp/services/monitor.py +99 -0
- package/bundle/hkp-python/src/hkp/services/nested_pipeline.py +278 -0
- package/bundle/hkp-python/src/hkp/services/skill_router.py +388 -0
- package/bundle/hkp-python/src/hkp/services/speech_to_text.py +186 -0
- package/bundle/hkp-python/src/hkp/services/spread.py +114 -0
- package/bundle/hkp-python/src/hkp/services/stopper.py +59 -0
- package/bundle/hkp-python/src/hkp/services/sub_service.py +417 -0
- package/bundle/hkp-python/src/hkp/services/text_generation.py +498 -0
- package/bundle/hkp-python/src/hkp/services/text_to_speech.py +237 -0
- package/bundle/hkp-python/src/hkp/services/timer.py +267 -0
- package/bundle/hkp-python/src/hkp/services/tracks.py +251 -0
- package/bundle/hkp-python/src/hkp/types.py +412 -0
- package/bundle/hkp-python/src/hkp/ws_tickets.py +54 -0
- package/bundle/hkp-python/src/hkp/yas.py +192 -0
- package/bundle/hkp-rt/lib/CMakeLists.txt +193 -0
- package/bundle/hkp-rt/lib/hkp-bundles/CMakeLists.txt +55 -0
- package/bundle/hkp-rt/lib/hkp-bundles/plugin_register.cpp +14 -0
- package/bundle/hkp-rt/lib/include/app.h +201 -0
- package/bundle/hkp-rt/lib/include/assets.h +239 -0
- package/bundle/hkp-rt/lib/include/auth.h +167 -0
- package/bundle/hkp-rt/lib/include/call_report.h +197 -0
- package/bundle/hkp-rt/lib/include/coordinator_links.h +127 -0
- package/bundle/hkp-rt/lib/include/discovery_hooks.h +29 -0
- package/bundle/hkp-rt/lib/include/egress.h +379 -0
- package/bundle/hkp-rt/lib/include/files.h +275 -0
- package/bundle/hkp-rt/lib/include/log_entry.h +131 -0
- package/bundle/hkp-rt/lib/include/mounts.h +139 -0
- package/bundle/hkp-rt/lib/include/origins.h +363 -0
- package/bundle/hkp-rt/lib/include/registry.h +119 -0
- package/bundle/hkp-rt/lib/include/secrets.h +414 -0
- package/bundle/hkp-rt/lib/include/server.h +122 -0
- package/bundle/hkp-rt/lib/include/service.h +190 -0
- package/bundle/hkp-rt/lib/include/slot_store.h +41 -0
- package/bundle/hkp-rt/lib/include/standalone_config.h +253 -0
- package/bundle/hkp-rt/lib/include/types/audio.h +3 -0
- package/bundle/hkp-rt/lib/include/types/data.h +152 -0
- package/bundle/hkp-rt/lib/include/types/message.h +56 -0
- package/bundle/hkp-rt/lib/include/types/models.h +154 -0
- package/bundle/hkp-rt/lib/include/types/owns_me.h +19 -0
- package/bundle/hkp-rt/lib/include/types/ringbuffer.h +86 -0
- package/bundle/hkp-rt/lib/include/types/types.h +33 -0
- package/bundle/hkp-rt/lib/include/types/validation.h +205 -0
- package/bundle/hkp-rt/lib/src/address.h +88 -0
- package/bundle/hkp-rt/lib/src/app.cpp +591 -0
- package/bundle/hkp-rt/lib/src/assets.cpp +686 -0
- package/bundle/hkp-rt/lib/src/binary_frame.h +154 -0
- package/bundle/hkp-rt/lib/src/common/expression.h +1481 -0
- package/bundle/hkp-rt/lib/src/common/inja.h +36 -0
- package/bundle/hkp-rt/lib/src/common/link_socket.cpp +437 -0
- package/bundle/hkp-rt/lib/src/common/link_socket.h +97 -0
- package/bundle/hkp-rt/lib/src/common/realtime_wakeup.h +120 -0
- package/bundle/hkp-rt/lib/src/common/stream_broadcast.h +250 -0
- package/bundle/hkp-rt/lib/src/common/string_util.h +31 -0
- package/bundle/hkp-rt/lib/src/common/websocket_client_session.cpp +217 -0
- package/bundle/hkp-rt/lib/src/common/websocket_client_session.h +37 -0
- package/bundle/hkp-rt/lib/src/common/websocket_config.h +119 -0
- package/bundle/hkp-rt/lib/src/common/websocket_protocol.h +32 -0
- package/bundle/hkp-rt/lib/src/common/websocket_server.cpp +82 -0
- package/bundle/hkp-rt/lib/src/common/websocket_server.h +57 -0
- package/bundle/hkp-rt/lib/src/common/websocket_server_listener.cpp +115 -0
- package/bundle/hkp-rt/lib/src/common/websocket_server_listener.h +35 -0
- package/bundle/hkp-rt/lib/src/common/websocket_server_session.cpp +172 -0
- package/bundle/hkp-rt/lib/src/common/websocket_server_session.h +53 -0
- package/bundle/hkp-rt/lib/src/common.h +13 -0
- package/bundle/hkp-rt/lib/src/coordinator_links.cpp +1142 -0
- package/bundle/hkp-rt/lib/src/discovery/discovery.cpp +707 -0
- package/bundle/hkp-rt/lib/src/discovery/discovery.h +89 -0
- package/bundle/hkp-rt/lib/src/http/auth.cpp +569 -0
- package/bundle/hkp-rt/lib/src/http/front_door.cpp +518 -0
- package/bundle/hkp-rt/lib/src/http/front_door.h +131 -0
- package/bundle/hkp-rt/lib/src/http/server.cpp +1539 -0
- package/bundle/hkp-rt/lib/src/http/ws_tickets.h +125 -0
- package/bundle/hkp-rt/lib/src/mount.h +63 -0
- package/bundle/hkp-rt/lib/src/process_context.h +335 -0
- package/bundle/hkp-rt/lib/src/process_depth.h +20 -0
- package/bundle/hkp-rt/lib/src/registry.cpp +233 -0
- package/bundle/hkp-rt/lib/src/runtime.cpp +986 -0
- package/bundle/hkp-rt/lib/src/runtime.h +225 -0
- package/bundle/hkp-rt/lib/src/runtime_host.h +180 -0
- package/bundle/hkp-rt/lib/src/service.cpp +315 -0
- package/bundle/hkp-rt/lib/src/services/asset.h +185 -0
- package/bundle/hkp-rt/lib/src/services/audio_encode.cpp +372 -0
- package/bundle/hkp-rt/lib/src/services/audio_encode.h +97 -0
- package/bundle/hkp-rt/lib/src/services/cache.h +362 -0
- package/bundle/hkp-rt/lib/src/services/cache_subservices.h +463 -0
- package/bundle/hkp-rt/lib/src/services/core_audio.cpp +384 -0
- package/bundle/hkp-rt/lib/src/services/core_audio.h +22 -0
- package/bundle/hkp-rt/lib/src/services/core_input.h +337 -0
- package/bundle/hkp-rt/lib/src/services/core_output.h +370 -0
- package/bundle/hkp-rt/lib/src/services/ffmpeg/detail.cpp +749 -0
- package/bundle/hkp-rt/lib/src/services/ffmpeg/detail.h +29 -0
- package/bundle/hkp-rt/lib/src/services/ffmpeg/ffmpeg.cpp +193 -0
- package/bundle/hkp-rt/lib/src/services/ffmpeg/ffmpeg.h +40 -0
- package/bundle/hkp-rt/lib/src/services/ffmpeg/types.h +120 -0
- package/bundle/hkp-rt/lib/src/services/fft_service.h +190 -0
- package/bundle/hkp-rt/lib/src/services/filesystem.h +309 -0
- package/bundle/hkp-rt/lib/src/services/filter.h +208 -0
- package/bundle/hkp-rt/lib/src/services/gather.h +272 -0
- package/bundle/hkp-rt/lib/src/services/hold.h +304 -0
- package/bundle/hkp-rt/lib/src/services/http_client.cpp +347 -0
- package/bundle/hkp-rt/lib/src/services/http_client.h +67 -0
- package/bundle/hkp-rt/lib/src/services/http_client_impl.h +45 -0
- package/bundle/hkp-rt/lib/src/services/http_client_template_examples.md +202 -0
- package/bundle/hkp-rt/lib/src/services/http_server/http_listener.cpp +130 -0
- package/bundle/hkp-rt/lib/src/services/http_server/http_listener.h +33 -0
- package/bundle/hkp-rt/lib/src/services/http_server/http_server.cpp +351 -0
- package/bundle/hkp-rt/lib/src/services/http_server/http_server.h +79 -0
- package/bundle/hkp-rt/lib/src/services/http_server/http_server_impl.cpp +230 -0
- package/bundle/hkp-rt/lib/src/services/http_server/http_server_impl.h +64 -0
- package/bundle/hkp-rt/lib/src/services/http_server/http_server_subservices.cpp +950 -0
- package/bundle/hkp-rt/lib/src/services/http_server/http_server_subservices.h +253 -0
- package/bundle/hkp-rt/lib/src/services/http_server/http_session.cpp +495 -0
- package/bundle/hkp-rt/lib/src/services/http_server/http_session.h +169 -0
- package/bundle/hkp-rt/lib/src/services/http_server/http_stream_listener.cpp +270 -0
- package/bundle/hkp-rt/lib/src/services/http_server/http_stream_listener.h +104 -0
- package/bundle/hkp-rt/lib/src/services/http_server/request_decode.h +164 -0
- package/bundle/hkp-rt/lib/src/services/if_service.h +210 -0
- package/bundle/hkp-rt/lib/src/services/ifft_service.h +198 -0
- package/bundle/hkp-rt/lib/src/services/injector.h +162 -0
- package/bundle/hkp-rt/lib/src/services/iterator.h +201 -0
- package/bundle/hkp-rt/lib/src/services/map.h +641 -0
- package/bundle/hkp-rt/lib/src/services/monitor.h +161 -0
- package/bundle/hkp-rt/lib/src/services/mp3_frames.h +119 -0
- package/bundle/hkp-rt/lib/src/services/mp4_to_wav.cpp +281 -0
- package/bundle/hkp-rt/lib/src/services/mp4_to_wav.h +263 -0
- package/bundle/hkp-rt/lib/src/services/peer_server/peer_registry.cpp +88 -0
- package/bundle/hkp-rt/lib/src/services/peer_server/peer_registry.h +43 -0
- package/bundle/hkp-rt/lib/src/services/peer_server/peer_server.h +163 -0
- package/bundle/hkp-rt/lib/src/services/peer_server/peer_server_listener.cpp +133 -0
- package/bundle/hkp-rt/lib/src/services/peer_server/peer_server_listener.h +46 -0
- package/bundle/hkp-rt/lib/src/services/peer_server/peer_server_session.cpp +165 -0
- package/bundle/hkp-rt/lib/src/services/peer_server/peer_server_session.h +44 -0
- package/bundle/hkp-rt/lib/src/services/peer_server/peer_ws_session.cpp +184 -0
- package/bundle/hkp-rt/lib/src/services/peer_server/peer_ws_session.h +55 -0
- package/bundle/hkp-rt/lib/src/services/receiver_session.h +172 -0
- package/bundle/hkp-rt/lib/src/services/root_certificates.h +3959 -0
- package/bundle/hkp-rt/lib/src/services/sha256_openssl.h +49 -0
- package/bundle/hkp-rt/lib/src/services/speech_http.h +306 -0
- package/bundle/hkp-rt/lib/src/services/speech_to_text.cpp +595 -0
- package/bundle/hkp-rt/lib/src/services/speech_to_text.h +69 -0
- package/bundle/hkp-rt/lib/src/services/static.cpp +45 -0
- package/bundle/hkp-rt/lib/src/services/static.h +41 -0
- package/bundle/hkp-rt/lib/src/services/stopper.h +72 -0
- package/bundle/hkp-rt/lib/src/services/sub_service.h +286 -0
- package/bundle/hkp-rt/lib/src/services/text_generation.cpp +1132 -0
- package/bundle/hkp-rt/lib/src/services/text_generation.h +71 -0
- package/bundle/hkp-rt/lib/src/services/text_to_speech.cpp +853 -0
- package/bundle/hkp-rt/lib/src/services/text_to_speech.h +97 -0
- package/bundle/hkp-rt/lib/src/services/timer.h +300 -0
- package/bundle/hkp-rt/lib/src/services/tracks.h +397 -0
- package/bundle/hkp-rt/lib/src/services/tts_inflect.cpp +149 -0
- package/bundle/hkp-rt/lib/src/services/tts_inflect.h +82 -0
- package/bundle/hkp-rt/lib/src/services/wav_reader.h +213 -0
- package/bundle/hkp-rt/lib/src/services/websocket_client_service.h +182 -0
- package/bundle/hkp-rt/lib/src/services/websocket_reader.h +148 -0
- package/bundle/hkp-rt/lib/src/services/websocket_server_service.h +196 -0
- package/bundle/hkp-rt/lib/src/services/websocket_writer.cpp +641 -0
- package/bundle/hkp-rt/lib/src/services/websocket_writer.h +117 -0
- package/bundle/hkp-rt/lib/src/sub_runtime.cpp +234 -0
- package/bundle/hkp-rt/lib/src/sub_runtime.h +160 -0
- package/bundle/hkp-rt/lib/src/types/data.cpp +237 -0
- package/bundle/hkp-rt/lib/src/types/message.cpp +148 -0
- package/bundle/hkp-rt/lib/src/types/models.cpp +83 -0
- package/bundle/hkp-rt/lib/src/types/ringbuffer.cpp +336 -0
- package/bundle/hkp-rt/lib/src/uuid.h +12 -0
- package/bundle/readymade-mcp-commits.json +5 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +79 -0
- package/dist/git.d.ts +8 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +53 -0
- package/dist/http.d.ts +17 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +130 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/repository.d.ts +49 -0
- package/dist/repository.d.ts.map +1 -0
- package/dist/repository.js +452 -0
- package/dist/schemas.d.ts +156 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +43 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +83 -0
- package/dist/types.d.ts +63 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +20 -0
- package/dist/validation.d.ts +9 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +101 -0
- package/package.json +52 -4
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A request whose headers may name secrets, sent so that each secret reaches
|
|
3
|
+
* only the hosts its audience allows — the first one and every one a redirect
|
|
4
|
+
* leads to.
|
|
5
|
+
*
|
|
6
|
+
* `fetch` follows redirects on its own and re-sends the headers it was given,
|
|
7
|
+
* which were resolved for the address first called. It withholds
|
|
8
|
+
* `Authorization` from another origin, and nothing else: a secret in any other
|
|
9
|
+
* header would travel to wherever the first host pointed. So redirects are
|
|
10
|
+
* followed here instead, and the headers are resolved again for each hop.
|
|
11
|
+
*
|
|
12
|
+
* A header that may not go to the next hop is left out and the request goes on
|
|
13
|
+
* without it, rather than being refused. A host that takes a token and answers
|
|
14
|
+
* with a redirect to storage — a signed URL, which must not be sent the token —
|
|
15
|
+
* is the ordinary case of a credentialed download. Once left out, a header
|
|
16
|
+
* stays out for the rest of the chain, as it does in `fetch`.
|
|
17
|
+
*/
|
|
18
|
+
import { SecretVault, resolveCredential } from "./secrets";
|
|
19
|
+
|
|
20
|
+
/** How many redirects one request follows before it is given up. */
|
|
21
|
+
const MAX_REDIRECTS = 10;
|
|
22
|
+
|
|
23
|
+
const REDIRECT_STATUS = new Set([301, 302, 303, 307, 308]);
|
|
24
|
+
|
|
25
|
+
/** What `fetch` itself withholds from a redirect to another origin. */
|
|
26
|
+
const ORIGIN_BOUND = new Set(["authorization", "cookie", "proxy-authorization"]);
|
|
27
|
+
|
|
28
|
+
/** What describes a body, and goes when a redirect drops the body. */
|
|
29
|
+
const BODY_HEADERS = new Set([
|
|
30
|
+
"content-type",
|
|
31
|
+
"content-length",
|
|
32
|
+
"content-encoding",
|
|
33
|
+
"content-language",
|
|
34
|
+
"content-location",
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
export type CredentialedRequest = {
|
|
38
|
+
method?: string;
|
|
39
|
+
/** As configured: a value may name secrets, or be a literal. */
|
|
40
|
+
headers?: Record<string, string>;
|
|
41
|
+
body?: BodyInit;
|
|
42
|
+
signal?: AbortSignal;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The response at the end of the redirects, or a sentence saying why there is
|
|
47
|
+
* none: a secret that may not be sent to the address called, a redirect to
|
|
48
|
+
* something that is not an `http(s)` address, or too many of them.
|
|
49
|
+
*/
|
|
50
|
+
export async function fetchWithCredentials(
|
|
51
|
+
vault: SecretVault | null | undefined,
|
|
52
|
+
url: string,
|
|
53
|
+
request: CredentialedRequest = {},
|
|
54
|
+
fetchImpl: typeof fetch = fetch,
|
|
55
|
+
): Promise<{ response: Response } | { problem: string }> {
|
|
56
|
+
let current = url;
|
|
57
|
+
let method = (request.method ?? "GET").toUpperCase();
|
|
58
|
+
let body = request.body;
|
|
59
|
+
let held = { ...(request.headers ?? {}) };
|
|
60
|
+
|
|
61
|
+
for (let redirects = 0; ; redirects++) {
|
|
62
|
+
// Only the address called can have a problem: what may not go to a later
|
|
63
|
+
// hop was left out before getting here.
|
|
64
|
+
const { value: headers, problem } = resolveCredential(vault, held, current);
|
|
65
|
+
if (problem) {
|
|
66
|
+
return { problem };
|
|
67
|
+
}
|
|
68
|
+
const response = await fetchImpl(current, {
|
|
69
|
+
method,
|
|
70
|
+
headers,
|
|
71
|
+
body,
|
|
72
|
+
signal: request.signal,
|
|
73
|
+
redirect: "manual",
|
|
74
|
+
});
|
|
75
|
+
const location = REDIRECT_STATUS.has(response.status)
|
|
76
|
+
? response.headers.get("location")
|
|
77
|
+
: null;
|
|
78
|
+
if (!location) {
|
|
79
|
+
return { response };
|
|
80
|
+
}
|
|
81
|
+
await response.body?.cancel();
|
|
82
|
+
if (redirects >= MAX_REDIRECTS) {
|
|
83
|
+
return { problem: `${url} redirected more than ${MAX_REDIRECTS} times` };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const from = new URL(current);
|
|
87
|
+
let to: URL;
|
|
88
|
+
try {
|
|
89
|
+
to = new URL(location, from);
|
|
90
|
+
} catch {
|
|
91
|
+
return { problem: `${current} redirected to ${JSON.stringify(location)}, which is not a URL` };
|
|
92
|
+
}
|
|
93
|
+
if (to.protocol !== "http:" && to.protocol !== "https:") {
|
|
94
|
+
return { problem: `${current} redirected to a ${to.protocol}// address` };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// As `fetch` does: a 303 is fetched, and so is what a POST was sent to by
|
|
98
|
+
// a 301 or 302; a 307 or 308 repeats the request as it was.
|
|
99
|
+
const becomesGet =
|
|
100
|
+
(response.status === 303 && method !== "GET" && method !== "HEAD") ||
|
|
101
|
+
((response.status === 301 || response.status === 302) && method === "POST");
|
|
102
|
+
if (becomesGet) {
|
|
103
|
+
method = "GET";
|
|
104
|
+
body = undefined;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const crossOrigin = to.origin !== from.origin;
|
|
108
|
+
held = Object.fromEntries(
|
|
109
|
+
Object.entries(held).filter(([name, value]) => {
|
|
110
|
+
const header = name.toLowerCase();
|
|
111
|
+
if (becomesGet && BODY_HEADERS.has(header)) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
if (crossOrigin && ORIGIN_BOUND.has(header)) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
return !resolveCredential(vault, value, to.href).problem;
|
|
118
|
+
}),
|
|
119
|
+
);
|
|
120
|
+
current = to.href;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a board may make this server connect to.
|
|
3
|
+
*
|
|
4
|
+
* A board names destinations — an HTTP Client's URL, a feed, a mail server, a
|
|
5
|
+
* model's base URL — and the server dials them. On a person's own machine that
|
|
6
|
+
* is the point: a board talks to the printer, the NAS, a model on the LAN. On
|
|
7
|
+
* a server several people's boards run on it is not: a destination on the
|
|
8
|
+
* server's loopback, its private network or a cloud provider's metadata
|
|
9
|
+
* endpoint (`169.254.169.254`, which hands out the instance's credentials) is
|
|
10
|
+
* something the server can reach and the board's author should not.
|
|
11
|
+
*
|
|
12
|
+
* So a server can be told it is hosted: with `HKP_EGRESS=public`, a destination
|
|
13
|
+
* is reached only when every address its name resolves to is a public internet
|
|
14
|
+
* address. Unset, nothing is refused.
|
|
15
|
+
*
|
|
16
|
+
* **Judged where the socket opens, on the address it opens to.** Not on the
|
|
17
|
+
* name a board wrote: a name is whatever its owner points it at, and a name
|
|
18
|
+
* that resolved to a public address when it was checked may resolve to
|
|
19
|
+
* `127.0.0.1` when it is dialled. Checking at the connection covers that, every
|
|
20
|
+
* hop of a redirect, and every spelling of an address (`2130706433`, `0x7f.1`),
|
|
21
|
+
* which are addresses by then.
|
|
22
|
+
*
|
|
23
|
+
* Every `fetch` in the process goes through a dispatcher installed here, so a
|
|
24
|
+
* service written later is covered without doing anything. A service that
|
|
25
|
+
* opens its own socket — IMAP, SMTP — asks `reachableAddress` first and
|
|
26
|
+
* connects to what it answers. `tests/egress-sources.test.ts` fails on any
|
|
27
|
+
* other way out.
|
|
28
|
+
*
|
|
29
|
+
* Connections the operator configured rather than a board — the coordinator
|
|
30
|
+
* link, the token issuer's keys — are not a board's destinations and are not
|
|
31
|
+
* judged here.
|
|
32
|
+
*/
|
|
33
|
+
import dns from "node:dns";
|
|
34
|
+
import net from "node:net";
|
|
35
|
+
|
|
36
|
+
// Types only at the top: importing undici installs a dispatcher of its own as
|
|
37
|
+
// the process's when none is set, and an open server is to keep the one it
|
|
38
|
+
// had. It is loaded when a policy is set that needs it.
|
|
39
|
+
import type { Dispatcher } from "undici";
|
|
40
|
+
|
|
41
|
+
/** An address range: the address as bytes, and how many leading bits count. */
|
|
42
|
+
type Range = { bytes: number[]; bits: number };
|
|
43
|
+
|
|
44
|
+
export type EgressPolicy =
|
|
45
|
+
| { mode: "open" }
|
|
46
|
+
| {
|
|
47
|
+
mode: "public";
|
|
48
|
+
/** Addresses and ranges reached anyway, as the operator listed them. */
|
|
49
|
+
allow: Range[];
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* What is not the public internet: this host, private networks, link-local
|
|
54
|
+
* (where the metadata endpoints are), shared address space, and what is not
|
|
55
|
+
* an address one connects to at all. `::/96` is the deprecated IPv4-compatible
|
|
56
|
+
* form (`::127.0.0.1`); `64:ff9b:1::/48` is a network's own NAT64 prefix, which
|
|
57
|
+
* may translate to private IPv4 and puts the IPv4 address where that network
|
|
58
|
+
* chose, so the whole range is refused rather than judged by what it carries.
|
|
59
|
+
*/
|
|
60
|
+
const NOT_PUBLIC = [
|
|
61
|
+
"0.0.0.0/8",
|
|
62
|
+
"127.0.0.0/8",
|
|
63
|
+
"10.0.0.0/8",
|
|
64
|
+
"172.16.0.0/12",
|
|
65
|
+
"192.168.0.0/16",
|
|
66
|
+
"100.64.0.0/10",
|
|
67
|
+
"169.254.0.0/16",
|
|
68
|
+
"192.0.0.0/24",
|
|
69
|
+
"198.18.0.0/15",
|
|
70
|
+
"224.0.0.0/4",
|
|
71
|
+
"240.0.0.0/4",
|
|
72
|
+
"::/96",
|
|
73
|
+
"::1/128",
|
|
74
|
+
"fe80::/10",
|
|
75
|
+
"fc00::/7",
|
|
76
|
+
"ff00::/8",
|
|
77
|
+
"64:ff9b:1::/48",
|
|
78
|
+
].map(parseRange);
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* IPv6 forms that carry an IPv4 address, and where it sits. An address in one
|
|
82
|
+
* of them is the IPv4 address inside it — `::ffff:127.0.0.1` is loopback — and
|
|
83
|
+
* is judged as that.
|
|
84
|
+
*/
|
|
85
|
+
const CARRY_IPV4: Array<{ range: Range; at: number }> = [
|
|
86
|
+
{ range: parseRange("::ffff:0:0/96"), at: 12 },
|
|
87
|
+
{ range: parseRange("64:ff9b::/96"), at: 12 },
|
|
88
|
+
{ range: parseRange("2002::/16"), at: 2 },
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
/** An address as bytes: 4 for IPv4, 16 for IPv6. Null when it is neither. */
|
|
92
|
+
function toBytes(address: string): number[] | null {
|
|
93
|
+
const plain = address.replace(/^\[|\]$/g, "").replace(/%.*$/, "");
|
|
94
|
+
const kind = net.isIP(plain);
|
|
95
|
+
if (kind === 4) {
|
|
96
|
+
return plain.split(".").map(Number);
|
|
97
|
+
}
|
|
98
|
+
if (kind !== 6) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
// A dotted IPv4 tail ("::ffff:127.0.0.1") becomes the two groups it is.
|
|
102
|
+
let text = plain;
|
|
103
|
+
const tail = /(\d+\.\d+\.\d+\.\d+)$/.exec(text);
|
|
104
|
+
if (tail) {
|
|
105
|
+
const [a, b, c, d] = tail[1].split(".").map(Number);
|
|
106
|
+
text = `${text.slice(0, tail.index)}${((a << 8) | b).toString(16)}:${((c << 8) | d).toString(16)}`;
|
|
107
|
+
}
|
|
108
|
+
const [head, rest] = text.split("::");
|
|
109
|
+
const groupsOf = (part: string | undefined) =>
|
|
110
|
+
part ? part.split(":").map((group) => parseInt(group, 16)) : [];
|
|
111
|
+
const left = groupsOf(head);
|
|
112
|
+
const right = groupsOf(rest);
|
|
113
|
+
const groups =
|
|
114
|
+
rest === undefined
|
|
115
|
+
? left
|
|
116
|
+
: [...left, ...new Array(8 - left.length - right.length).fill(0), ...right];
|
|
117
|
+
return groups.flatMap((group) => [group >> 8, group & 0xff]);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function parseRange(text: string): Range {
|
|
121
|
+
const [address, bits] = text.split("/");
|
|
122
|
+
const bytes = toBytes(address);
|
|
123
|
+
if (!bytes) {
|
|
124
|
+
throw new Error(`Not an address or a range: ${text}`);
|
|
125
|
+
}
|
|
126
|
+
return { bytes, bits: bits === undefined ? bytes.length * 8 : Number(bits) };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function inRange(bytes: number[], range: Range): boolean {
|
|
130
|
+
if (bytes.length !== range.bytes.length) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
for (let bit = 0; bit < range.bits; bit += 1) {
|
|
134
|
+
const byte = bit >> 3;
|
|
135
|
+
const mask = 0x80 >> (bit & 7);
|
|
136
|
+
if ((bytes[byte] & mask) !== (range.bytes[byte] & mask)) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Whether `address` is a public internet address. Not an address: false. */
|
|
144
|
+
export function isPublicAddress(address: string): boolean {
|
|
145
|
+
const bytes = toBytes(address);
|
|
146
|
+
if (!bytes) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
for (const { range, at } of CARRY_IPV4) {
|
|
150
|
+
if (inRange(bytes, range)) {
|
|
151
|
+
return isPublicAddress(bytes.slice(at, at + 4).join("."));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return !NOT_PUBLIC.some((range) => inRange(bytes, range));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Reads `HKP_EGRESS` and `HKP_EGRESS_ALLOW`. An entry of the list that is not
|
|
159
|
+
* an address or a range is an error rather than skipped: an operator who
|
|
160
|
+
* meant to allow something should learn now that nothing was.
|
|
161
|
+
*/
|
|
162
|
+
export function readEgressPolicy(env: NodeJS.ProcessEnv): EgressPolicy {
|
|
163
|
+
const mode = (env.HKP_EGRESS ?? "").trim().toLowerCase();
|
|
164
|
+
if (!mode || mode === "open") {
|
|
165
|
+
return { mode: "open" };
|
|
166
|
+
}
|
|
167
|
+
if (mode !== "public") {
|
|
168
|
+
throw new Error(`HKP_EGRESS must be "public" or unset, not "${env.HKP_EGRESS}"`);
|
|
169
|
+
}
|
|
170
|
+
const allow = (env.HKP_EGRESS_ALLOW ?? "")
|
|
171
|
+
.split(",")
|
|
172
|
+
.map((entry) => entry.trim())
|
|
173
|
+
.filter(Boolean)
|
|
174
|
+
.map((entry) => {
|
|
175
|
+
try {
|
|
176
|
+
return parseRange(entry);
|
|
177
|
+
} catch {
|
|
178
|
+
throw new Error(
|
|
179
|
+
`HKP_EGRESS_ALLOW: "${entry}" is not an address or a range (names are not accepted: an allowed name could be repointed)`,
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
return { mode: "public", allow };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Whether a destination at `address` may be reached under `policy`. */
|
|
187
|
+
export function mayReach(policy: EgressPolicy, address: string): boolean {
|
|
188
|
+
if (policy.mode === "open") {
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
const bytes = toBytes(address);
|
|
192
|
+
if (bytes && policy.allow.some((range) => inRange(bytes, range))) {
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
return isPublicAddress(address);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** A destination this server will not connect to, and why. */
|
|
199
|
+
export class EgressRefused extends Error {
|
|
200
|
+
readonly code = "EHKPEGRESS";
|
|
201
|
+
|
|
202
|
+
constructor(
|
|
203
|
+
readonly host: string,
|
|
204
|
+
readonly address: string,
|
|
205
|
+
) {
|
|
206
|
+
super(
|
|
207
|
+
host === address
|
|
208
|
+
? `This server does not reach private addresses (${address})`
|
|
209
|
+
: `This server does not reach private addresses (${host} is ${address})`,
|
|
210
|
+
);
|
|
211
|
+
this.name = "EgressRefused";
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
let active: EgressPolicy = { mode: "open" };
|
|
216
|
+
let before: Dispatcher | null = null;
|
|
217
|
+
|
|
218
|
+
export function egressPolicy(): EgressPolicy {
|
|
219
|
+
return active;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* `dns.lookup`, refusing a name any of whose addresses may not be reached.
|
|
224
|
+
*
|
|
225
|
+
* All of them, not the one that would be used: a name answering with a public
|
|
226
|
+
* address and a private one is a name somebody arranged, and which of the two
|
|
227
|
+
* a connection ends up on is not this function's to promise.
|
|
228
|
+
*/
|
|
229
|
+
export const egressLookup = ((
|
|
230
|
+
hostname: string,
|
|
231
|
+
options: dns.LookupOptions | number | ((...args: unknown[]) => void),
|
|
232
|
+
callback?: (...args: unknown[]) => void,
|
|
233
|
+
) => {
|
|
234
|
+
const done = (typeof options === "function" ? options : callback)!;
|
|
235
|
+
const asked: dns.LookupOptions =
|
|
236
|
+
typeof options === "object" ? options : typeof options === "number" ? { family: options } : {};
|
|
237
|
+
dns.lookup(hostname, { ...asked, all: true }, (err, addresses) => {
|
|
238
|
+
if (err) {
|
|
239
|
+
done(err);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
const refused = addresses.find(({ address }) => !mayReach(active, address));
|
|
243
|
+
if (refused) {
|
|
244
|
+
done(new EgressRefused(hostname, refused.address));
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (asked.all) {
|
|
248
|
+
done(null, addresses);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
done(null, addresses[0].address, addresses[0].family);
|
|
252
|
+
});
|
|
253
|
+
}) as typeof dns.lookup;
|
|
254
|
+
|
|
255
|
+
/** Resolves `host` through `egressLookup`: every address, or the refusal. */
|
|
256
|
+
function lookupAll(host: string): Promise<dns.LookupAddress[]> {
|
|
257
|
+
return new Promise((resolve, reject) => {
|
|
258
|
+
egressLookup(host, { all: true }, (err, addresses) =>
|
|
259
|
+
err ? reject(err) : resolve(addresses as unknown as dns.LookupAddress[]),
|
|
260
|
+
);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Where a service that opens its own socket should connect, for `host`.
|
|
266
|
+
*
|
|
267
|
+
* Open: `host` itself, as before. Hosted: the address the guard checked, with
|
|
268
|
+
* `host` as the name to verify the certificate against — connecting to the
|
|
269
|
+
* name instead would resolve it again, and the second answer is not the one
|
|
270
|
+
* that was judged.
|
|
271
|
+
*/
|
|
272
|
+
export async function reachableAddress(
|
|
273
|
+
host: string,
|
|
274
|
+
): Promise<{ host: string; servername?: string }> {
|
|
275
|
+
if (active.mode === "open") {
|
|
276
|
+
return { host };
|
|
277
|
+
}
|
|
278
|
+
if (net.isIP(host.replace(/^\[|\]$/g, ""))) {
|
|
279
|
+
if (!mayReach(active, host)) {
|
|
280
|
+
throw new EgressRefused(host, host);
|
|
281
|
+
}
|
|
282
|
+
return { host };
|
|
283
|
+
}
|
|
284
|
+
const [first] = await lookupAll(host);
|
|
285
|
+
return { host: first.address, servername: host };
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Makes `policy` the process's. Hosted, every `fetch` is dispatched through a
|
|
290
|
+
* connector that refuses what may not be reached; open, the dispatcher that
|
|
291
|
+
* was there before is put back.
|
|
292
|
+
*
|
|
293
|
+
* The connector judges an address literal itself: a socket opened to one is
|
|
294
|
+
* never looked up, so `egressLookup` alone would let `http://127.0.0.1/`
|
|
295
|
+
* through.
|
|
296
|
+
*/
|
|
297
|
+
export async function setEgressPolicy(policy: EgressPolicy): Promise<void> {
|
|
298
|
+
active = policy;
|
|
299
|
+
if (policy.mode === "open" && !before) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
const { Agent, buildConnector, getGlobalDispatcher, setGlobalDispatcher } =
|
|
303
|
+
await import("undici");
|
|
304
|
+
if (policy.mode === "open") {
|
|
305
|
+
setGlobalDispatcher(before!);
|
|
306
|
+
before = null;
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
before ??= getGlobalDispatcher();
|
|
310
|
+
const connect = buildConnector({ lookup: egressLookup });
|
|
311
|
+
setGlobalDispatcher(
|
|
312
|
+
new Agent({
|
|
313
|
+
connect: (options, callback) => {
|
|
314
|
+
const host = (options.hostname ?? "").replace(/^\[|\]$/g, "");
|
|
315
|
+
if (net.isIP(host) && !mayReach(active, host)) {
|
|
316
|
+
callback(new EgressRefused(host, host), null);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
connect(options, callback);
|
|
320
|
+
},
|
|
321
|
+
}),
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* What to say about a failed request: the refusal when this was one. `fetch`
|
|
327
|
+
* reports every connection failure as "fetch failed" and keeps the reason as
|
|
328
|
+
* its cause.
|
|
329
|
+
*/
|
|
330
|
+
export function failureReason(err: unknown): string {
|
|
331
|
+
return refusalIn(err)?.message ?? (err instanceof Error ? err.message : String(err));
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/** The refusal an error is, or was caused by. */
|
|
335
|
+
export function refusalIn(err: unknown): EgressRefused | null {
|
|
336
|
+
let current: unknown = err;
|
|
337
|
+
for (let depth = 0; current && depth < 5; depth += 1) {
|
|
338
|
+
if (current instanceof EgressRefused) {
|
|
339
|
+
return current;
|
|
340
|
+
}
|
|
341
|
+
current = (current as { cause?: unknown }).cause;
|
|
342
|
+
}
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The expressions a board writes — a Map's terms, a Filter's predicate — and
|
|
3
|
+
* what evaluating one may reach.
|
|
4
|
+
*
|
|
5
|
+
* This is the boundary between a board, which somebody else may have written,
|
|
6
|
+
* and the process it runs in: on a hosted server, everyone the server lets in.
|
|
7
|
+
* It was the `expression-eval` package until its author stopped maintaining
|
|
8
|
+
* it; it is kept here so that it is read and changed like the security code it
|
|
9
|
+
* is (`docs/content/concepts/runtime.md`). Parsing is `jsep`'s, pinned.
|
|
10
|
+
*
|
|
11
|
+
* What an expression can do is what the scope it is given can do, and nothing
|
|
12
|
+
* else:
|
|
13
|
+
*
|
|
14
|
+
* - **No way to code.** Nothing here compiles a string, and the routes to
|
|
15
|
+
* something that does — `constructor`, `prototype`, `__proto__`, and every
|
|
16
|
+
* other `__`-prefixed member — are refused by name, however the name is
|
|
17
|
+
* arrived at (`a.b`, `a["b"]`, `a[["b"]]`).
|
|
18
|
+
* - **No assignment.** The grammar has none, so an expression reads and calls
|
|
19
|
+
* but never writes a property.
|
|
20
|
+
* - **Only the scope.** A name resolves to the scope's own property or to
|
|
21
|
+
* nothing; what the scope inherits from `Object.prototype` is not a name.
|
|
22
|
+
*
|
|
23
|
+
* A member of nothing is nothing: `params.a.b` with no `a` is `undefined`, read
|
|
24
|
+
* as `params.a?.b` would be, rather than an error — the way hkp-rt and
|
|
25
|
+
* hkp-python read it, so a term evaluates alike wherever it runs. Whoever wants
|
|
26
|
+
* to know which reads came up empty passes `onMissing`.
|
|
27
|
+
*
|
|
28
|
+
* Twin of `hkp-frontend/src/runtime/browser/services/base/expressionEval.ts`;
|
|
29
|
+
* the two are kept identical, so a term evaluates alike in either runtime.
|
|
30
|
+
*/
|
|
31
|
+
import jsep from "jsep";
|
|
32
|
+
|
|
33
|
+
export type Expression = jsep.Expression;
|
|
34
|
+
|
|
35
|
+
type Scope = Record<string, unknown>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Told the path of a read that found nothing — `params.titel` — once per
|
|
39
|
+
* chain: in `params.a.b.c` with no `a`, only `params.a` is reported.
|
|
40
|
+
*/
|
|
41
|
+
export type OnMissing = (path: string) => void;
|
|
42
|
+
|
|
43
|
+
const BINARY: Record<string, (a: any, b: any) => unknown> = {
|
|
44
|
+
"|": (a, b) => a | b,
|
|
45
|
+
"^": (a, b) => a ^ b,
|
|
46
|
+
"&": (a, b) => a & b,
|
|
47
|
+
"==": (a, b) => a == b, // eslint-disable-line eqeqeq
|
|
48
|
+
"!=": (a, b) => a != b, // eslint-disable-line eqeqeq
|
|
49
|
+
"===": (a, b) => a === b,
|
|
50
|
+
"!==": (a, b) => a !== b,
|
|
51
|
+
"<": (a, b) => a < b,
|
|
52
|
+
">": (a, b) => a > b,
|
|
53
|
+
"<=": (a, b) => a <= b,
|
|
54
|
+
">=": (a, b) => a >= b,
|
|
55
|
+
"<<": (a, b) => a << b,
|
|
56
|
+
">>": (a, b) => a >> b,
|
|
57
|
+
">>>": (a, b) => a >>> b,
|
|
58
|
+
"+": (a, b) => a + b,
|
|
59
|
+
"-": (a, b) => a - b,
|
|
60
|
+
"*": (a, b) => a * b,
|
|
61
|
+
"/": (a, b) => a / b,
|
|
62
|
+
"%": (a, b) => a % b,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const UNARY: Record<string, (a: any) => unknown> = {
|
|
66
|
+
"-": (a) => -a,
|
|
67
|
+
"+": (a) => +a,
|
|
68
|
+
"~": (a) => ~a,
|
|
69
|
+
"!": (a) => !a,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/** Members that lead from a value to the code behind it. */
|
|
73
|
+
const REFUSED_MEMBERS = new Set(["constructor", "prototype"]);
|
|
74
|
+
|
|
75
|
+
/** Parses an expression; throws on one that does not parse. */
|
|
76
|
+
export function parse(source: string): Expression {
|
|
77
|
+
return jsep(source);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** The member a key names, or a refusal when it names a way out. */
|
|
81
|
+
function memberKey(key: unknown): string | number {
|
|
82
|
+
if (typeof key === "number") {
|
|
83
|
+
return key;
|
|
84
|
+
}
|
|
85
|
+
// As a property access would read it: `a[["b"]]` is `a.b`.
|
|
86
|
+
const name = String(key);
|
|
87
|
+
if (REFUSED_MEMBERS.has(name) || name.startsWith("__")) {
|
|
88
|
+
throw new Error(`Access to member "${name}" disallowed.`);
|
|
89
|
+
}
|
|
90
|
+
return name;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** How a read is named when it is reported: `params.items[0].title`. */
|
|
94
|
+
function pathOf(node: Expression): string {
|
|
95
|
+
switch (node.type) {
|
|
96
|
+
case "Identifier":
|
|
97
|
+
return (node as jsep.Identifier).name;
|
|
98
|
+
case "ThisExpression":
|
|
99
|
+
return "this";
|
|
100
|
+
case "MemberExpression": {
|
|
101
|
+
const read = node as jsep.MemberExpression;
|
|
102
|
+
const object = pathOf(read.object);
|
|
103
|
+
if (!read.computed) {
|
|
104
|
+
return `${object}.${(read.property as jsep.Identifier).name}`;
|
|
105
|
+
}
|
|
106
|
+
return read.property.type === "Literal"
|
|
107
|
+
? `${object}[${JSON.stringify((read.property as jsep.Literal).value)}]`
|
|
108
|
+
: `${object}[…]`;
|
|
109
|
+
}
|
|
110
|
+
default:
|
|
111
|
+
return "…";
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function member(
|
|
116
|
+
node: jsep.MemberExpression,
|
|
117
|
+
scope: Scope,
|
|
118
|
+
onMissing?: OnMissing,
|
|
119
|
+
): [unknown, unknown] {
|
|
120
|
+
const object = evaluate(node.object, scope, onMissing) as any;
|
|
121
|
+
const key = memberKey(
|
|
122
|
+
node.computed
|
|
123
|
+
? evaluate(node.property, scope, onMissing)
|
|
124
|
+
: (node.property as jsep.Identifier).name,
|
|
125
|
+
);
|
|
126
|
+
const nothing = object === undefined || object === null;
|
|
127
|
+
const value = nothing ? undefined : object[key];
|
|
128
|
+
// A read past a link that came up empty was reported with it; one past a
|
|
129
|
+
// link that is there but null is reported itself.
|
|
130
|
+
const pastMissing =
|
|
131
|
+
object === undefined && node.object.type === "MemberExpression";
|
|
132
|
+
if (value === undefined && onMissing && !pastMissing) {
|
|
133
|
+
onMissing(pathOf(node));
|
|
134
|
+
}
|
|
135
|
+
return [object, value];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Evaluates a parsed expression with `scope` as everything it may name;
|
|
140
|
+
* `onMissing` hears about every read that found nothing.
|
|
141
|
+
*/
|
|
142
|
+
export function evaluate(
|
|
143
|
+
node: Expression,
|
|
144
|
+
scope: Scope,
|
|
145
|
+
onMissing?: OnMissing,
|
|
146
|
+
): unknown {
|
|
147
|
+
switch (node.type) {
|
|
148
|
+
case "ArrayExpression":
|
|
149
|
+
return (node as jsep.ArrayExpression).elements.map((element) =>
|
|
150
|
+
evaluate(element, scope, onMissing),
|
|
151
|
+
);
|
|
152
|
+
case "BinaryExpression": {
|
|
153
|
+
const binary = node as jsep.BinaryExpression;
|
|
154
|
+
const operator = BINARY[binary.operator];
|
|
155
|
+
if (!operator) {
|
|
156
|
+
throw new Error(`Unsupported operator "${binary.operator}"`);
|
|
157
|
+
}
|
|
158
|
+
return operator(
|
|
159
|
+
evaluate(binary.left, scope, onMissing),
|
|
160
|
+
evaluate(binary.right, scope, onMissing),
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
case "LogicalExpression": {
|
|
164
|
+
const logical = node as jsep.LogicalExpression;
|
|
165
|
+
if (logical.operator === "||") {
|
|
166
|
+
return (
|
|
167
|
+
evaluate(logical.left, scope, onMissing) ||
|
|
168
|
+
evaluate(logical.right, scope, onMissing)
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
if (logical.operator === "&&") {
|
|
172
|
+
return (
|
|
173
|
+
evaluate(logical.left, scope, onMissing) &&
|
|
174
|
+
evaluate(logical.right, scope, onMissing)
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
throw new Error(`Unsupported operator "${logical.operator}"`);
|
|
178
|
+
}
|
|
179
|
+
case "CallExpression": {
|
|
180
|
+
const call = node as jsep.CallExpression;
|
|
181
|
+
let self: unknown;
|
|
182
|
+
let fn: unknown;
|
|
183
|
+
if (call.callee.type === "MemberExpression") {
|
|
184
|
+
[self, fn] = member(call.callee as jsep.MemberExpression, scope, onMissing);
|
|
185
|
+
} else {
|
|
186
|
+
fn = evaluate(call.callee, scope, onMissing);
|
|
187
|
+
}
|
|
188
|
+
if (typeof fn !== "function") {
|
|
189
|
+
throw new TypeError(`${pathOf(call.callee)} is not a function`);
|
|
190
|
+
}
|
|
191
|
+
return fn.apply(
|
|
192
|
+
self,
|
|
193
|
+
call.arguments.map((argument) => evaluate(argument, scope, onMissing)),
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
case "ConditionalExpression": {
|
|
197
|
+
const conditional = node as jsep.ConditionalExpression;
|
|
198
|
+
return evaluate(conditional.test, scope, onMissing)
|
|
199
|
+
? evaluate(conditional.consequent, scope, onMissing)
|
|
200
|
+
: evaluate(conditional.alternate, scope, onMissing);
|
|
201
|
+
}
|
|
202
|
+
case "Identifier": {
|
|
203
|
+
const name = (node as jsep.Identifier).name;
|
|
204
|
+
return Object.prototype.hasOwnProperty.call(scope, name) ? scope[name] : undefined;
|
|
205
|
+
}
|
|
206
|
+
case "Literal":
|
|
207
|
+
return (node as jsep.Literal).value;
|
|
208
|
+
case "MemberExpression":
|
|
209
|
+
return member(node as jsep.MemberExpression, scope, onMissing)[1];
|
|
210
|
+
case "ThisExpression":
|
|
211
|
+
return scope;
|
|
212
|
+
case "UnaryExpression": {
|
|
213
|
+
const unary = node as jsep.UnaryExpression;
|
|
214
|
+
const operator = UNARY[unary.operator];
|
|
215
|
+
if (!operator) {
|
|
216
|
+
throw new Error(`Unsupported operator "${unary.operator}"`);
|
|
217
|
+
}
|
|
218
|
+
return operator(evaluate(unary.argument, scope, onMissing));
|
|
219
|
+
}
|
|
220
|
+
default:
|
|
221
|
+
return undefined;
|
|
222
|
+
}
|
|
223
|
+
}
|