@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,296 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
import { Duplex } from "node:stream";
|
|
3
|
+
import { createHmac, randomBytes } from "node:crypto";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Where a mount is served and how much of the request path belongs to it.
|
|
7
|
+
*/
|
|
8
|
+
export type MountContext = {
|
|
9
|
+
/** Public path prefix this mount owns, e.g. `/hosted/ab12…`. */
|
|
10
|
+
mountPath: string;
|
|
11
|
+
/**
|
|
12
|
+
* Request target with `mountPath` removed; always starts with `/` and keeps
|
|
13
|
+
* any query string, so a handler can parse it as a URL and see both.
|
|
14
|
+
*/
|
|
15
|
+
subPath: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type MountRequestHandler = (
|
|
19
|
+
req: IncomingMessage,
|
|
20
|
+
res: ServerResponse,
|
|
21
|
+
context: MountContext,
|
|
22
|
+
) => void;
|
|
23
|
+
|
|
24
|
+
export type MountUpgradeHandler = (
|
|
25
|
+
req: IncomingMessage,
|
|
26
|
+
socket: Duplex,
|
|
27
|
+
head: Buffer,
|
|
28
|
+
context: MountContext,
|
|
29
|
+
) => void;
|
|
30
|
+
|
|
31
|
+
export type MountHandlers = {
|
|
32
|
+
request: MountRequestHandler;
|
|
33
|
+
/** Only needed by mounts that speak WebSocket (e.g. PeerJS signalling). */
|
|
34
|
+
upgrade?: MountUpgradeHandler;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/** A live mount, handed back to the service that registered it. */
|
|
38
|
+
export type MountHandle = {
|
|
39
|
+
/** Public URL clients should be pointed at. */
|
|
40
|
+
url: string;
|
|
41
|
+
/** Path prefix of `url`, useful for clients configured by host/port/path. */
|
|
42
|
+
path: string;
|
|
43
|
+
release(): void;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
type MountRecord = {
|
|
47
|
+
owner: string;
|
|
48
|
+
/** The space the runtime lives in; see `boardSpace`. */
|
|
49
|
+
space: string;
|
|
50
|
+
runtimeId: string;
|
|
51
|
+
serviceUuid: string;
|
|
52
|
+
handlers: MountHandlers;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/** Requests under this prefix are served by mounts rather than the REST API. */
|
|
56
|
+
export const MOUNT_PREFIX = "/hosted";
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Routes public traffic to services that need to expose an endpoint, without
|
|
60
|
+
* any of them binding a port of their own.
|
|
61
|
+
*
|
|
62
|
+
* A service asks for a mount and gets back an opaque, server-assigned id. That
|
|
63
|
+
* id — rather than a port or a caller-chosen path — is what makes the endpoint
|
|
64
|
+
* addressable, which matters for three reasons:
|
|
65
|
+
*
|
|
66
|
+
* - Ports are a single machine-wide namespace. With several tenants on one
|
|
67
|
+
* host, a service asking for a specific port is a land grab: the second
|
|
68
|
+
* claimant fails, and whoever wins receives traffic the other expected.
|
|
69
|
+
* - Runtime ids are only unique per tenant (boards ship stable ones like
|
|
70
|
+
* `node`), so they cannot appear in a globally-routable path.
|
|
71
|
+
* - These endpoints are deliberately unauthenticated — they exist to be called
|
|
72
|
+
* by outside parties. An unguessable id therefore doubles as the capability
|
|
73
|
+
* to reach them, and it carries no user identifier that a public URL would
|
|
74
|
+
* otherwise leak.
|
|
75
|
+
*
|
|
76
|
+
* The id is **derived, not drawn**: an HMAC of who owns the mount, which board
|
|
77
|
+
* and runtime it is in, and what it is called, keyed by a secret only the
|
|
78
|
+
* server holds. Randomness would be just as unguessable and was what this did
|
|
79
|
+
* first, but it made the address change every time a board was loaded — so
|
|
80
|
+
* anything outside pointing at it (a webhook configured in somebody else's
|
|
81
|
+
* product) broke on every restart, and a board could not be redeployed without
|
|
82
|
+
* reconfiguring its callers.
|
|
83
|
+
*
|
|
84
|
+
* Deriving it keeps the address stable across reloads, restarts and redeploys
|
|
85
|
+
* while keeping the secret out of the board: the board says only what the mount
|
|
86
|
+
* is *called*, which is not sensitive, and the server turns that into an
|
|
87
|
+
* address nobody can compute without the key. Rotating the key rotates every
|
|
88
|
+
* endpoint, and renaming one mount rotates only that one.
|
|
89
|
+
*/
|
|
90
|
+
export class MountRegistry {
|
|
91
|
+
/**
|
|
92
|
+
* Every claim to an address, oldest first. An address is derived from what
|
|
93
|
+
* the mount is called, so more than one runtime may claim the same one: a
|
|
94
|
+
* runtime rebuilt under its id claims it before the one it replaces lets
|
|
95
|
+
* go, and a board open in a client and also deployed holds two copies of
|
|
96
|
+
* each of its mounts. One claim answers — see `answering` — and the others
|
|
97
|
+
* are kept, so that releasing one leaves the address with whoever still
|
|
98
|
+
* claims it.
|
|
99
|
+
*/
|
|
100
|
+
private readonly mounts = new Map<string, MountRecord[]>();
|
|
101
|
+
private readonly secret: string;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @param publicUrlFor Resolves a mount path to the URL clients should use.
|
|
105
|
+
* Returns undefined before the server is listening, since the port is not
|
|
106
|
+
* known until then.
|
|
107
|
+
* @param secret Keys the id derivation. A server that is given none draws one
|
|
108
|
+
* for this process, which is the old behaviour: addresses that work but do
|
|
109
|
+
* not survive a restart. `index.ts` persists one so they do.
|
|
110
|
+
*/
|
|
111
|
+
constructor(
|
|
112
|
+
private readonly publicUrlFor: (mountPath: string) => string | undefined,
|
|
113
|
+
secret?: string,
|
|
114
|
+
) {
|
|
115
|
+
this.secret = secret || randomBytes(32).toString("hex");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* The address a given mount always gets.
|
|
120
|
+
*
|
|
121
|
+
* Every part that identifies the mount goes in, so two services cannot derive
|
|
122
|
+
* the same id: the tenant, the board, the runtime, and the mount's name. NUL
|
|
123
|
+
* separates them, as it cannot occur in any of them — the same reasoning as
|
|
124
|
+
* `tenantKey` in the server.
|
|
125
|
+
*/
|
|
126
|
+
private deriveId(
|
|
127
|
+
owner: string,
|
|
128
|
+
boardName: string,
|
|
129
|
+
runtimeId: string,
|
|
130
|
+
name: string,
|
|
131
|
+
): string {
|
|
132
|
+
return createHmac("sha256", this.secret)
|
|
133
|
+
.update([owner, boardName, runtimeId, name].join("\u0000"))
|
|
134
|
+
.digest("hex")
|
|
135
|
+
.slice(0, 32);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
register(
|
|
139
|
+
owner: string,
|
|
140
|
+
runtimeId: string,
|
|
141
|
+
serviceUuid: string,
|
|
142
|
+
handlers: MountHandlers,
|
|
143
|
+
// What the mount is called, and the board's, so the address survives a
|
|
144
|
+
// reload. A service that names nothing is identified by its own uuid, which
|
|
145
|
+
// is stable in a board file too.
|
|
146
|
+
options: { boardName?: string; mountName?: string; space?: string } = {},
|
|
147
|
+
): MountHandle | null {
|
|
148
|
+
const mountId = this.deriveId(
|
|
149
|
+
owner,
|
|
150
|
+
options.boardName ?? "",
|
|
151
|
+
runtimeId,
|
|
152
|
+
options.mountName || serviceUuid,
|
|
153
|
+
);
|
|
154
|
+
const mountPath = `${MOUNT_PREFIX}/${mountId}`;
|
|
155
|
+
const url = this.publicUrlFor(mountPath);
|
|
156
|
+
if (!url) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const record: MountRecord = {
|
|
161
|
+
owner,
|
|
162
|
+
space: options.space ?? owner,
|
|
163
|
+
runtimeId,
|
|
164
|
+
serviceUuid,
|
|
165
|
+
handlers,
|
|
166
|
+
};
|
|
167
|
+
this.mounts.set(mountId, [...(this.mounts.get(mountId) ?? []), record]);
|
|
168
|
+
return {
|
|
169
|
+
url,
|
|
170
|
+
path: mountPath,
|
|
171
|
+
// This claim and no other.
|
|
172
|
+
release: () => this.drop(mountId, (claim) => claim === record),
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* The claim that answers at an address: a deployed board's before a
|
|
178
|
+
* client's, and the newest of its kind. A board somebody deployed is meant
|
|
179
|
+
* to be reachable whoever else has it open, so opening it in a client
|
|
180
|
+
* neither takes its address nor, on leaving, takes the address away.
|
|
181
|
+
*/
|
|
182
|
+
private answering(mountId: string): MountRecord | undefined {
|
|
183
|
+
const claims = this.mounts.get(mountId) ?? [];
|
|
184
|
+
const deployed = claims.filter((claim) => claim.space !== claim.owner);
|
|
185
|
+
return deployed.at(-1) ?? claims.at(-1);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
private drop(mountId: string, gone: (claim: MountRecord) => boolean): void {
|
|
189
|
+
const claims = this.mounts.get(mountId);
|
|
190
|
+
if (!claims) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const kept = claims.filter((claim) => !gone(claim));
|
|
194
|
+
if (kept.length === 0) {
|
|
195
|
+
this.mounts.delete(mountId);
|
|
196
|
+
} else if (kept.length !== claims.length) {
|
|
197
|
+
this.mounts.set(mountId, kept);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Drop every mount belonging to a runtime. Services release their own mounts
|
|
203
|
+
* on destroy; this is the backstop so a torn-down runtime can never leave a
|
|
204
|
+
* publicly reachable endpoint behind.
|
|
205
|
+
*/
|
|
206
|
+
releaseRuntime(space: string, runtimeId: string): void {
|
|
207
|
+
for (const mountId of [...this.mounts.keys()]) {
|
|
208
|
+
this.drop(
|
|
209
|
+
mountId,
|
|
210
|
+
(claim) => claim.space === space && claim.runtimeId === runtimeId,
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/** Drops the mounts of what a tenant's clients created; a deployed board's
|
|
216
|
+
* go with its runtimes. */
|
|
217
|
+
releaseOwner(owner: string): void {
|
|
218
|
+
for (const mountId of [...this.mounts.keys()]) {
|
|
219
|
+
this.drop(mountId, (claim) => claim.space === owner);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
get size(): number {
|
|
224
|
+
return this.mounts.size;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** Number of live mounts for a tenant, for quota checks. */
|
|
228
|
+
countForOwner(owner: string): number {
|
|
229
|
+
let count = 0;
|
|
230
|
+
for (const claims of this.mounts.values()) {
|
|
231
|
+
count += claims.filter((claim) => claim.owner === owner).length;
|
|
232
|
+
}
|
|
233
|
+
return count;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Serve a request if it targets a mount. Returns false when the path is not
|
|
238
|
+
* a mount path, so the caller can fall through to the REST API.
|
|
239
|
+
*/
|
|
240
|
+
handleRequest(req: IncomingMessage, res: ServerResponse): boolean {
|
|
241
|
+
const resolved = this.resolve(req.url);
|
|
242
|
+
if (!resolved) {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
resolved.record.handlers.request(req, res, resolved.context);
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Serve a WebSocket upgrade if it targets a mount. Returns false when the
|
|
251
|
+
* path is not a mount path. A mount without an upgrade handler still returns
|
|
252
|
+
* true — the request was addressed to it, and refusing it here is correct
|
|
253
|
+
* rather than letting it fall through to runtime socket handling.
|
|
254
|
+
*/
|
|
255
|
+
handleUpgrade(req: IncomingMessage, socket: Duplex, head: Buffer): boolean {
|
|
256
|
+
const resolved = this.resolve(req.url);
|
|
257
|
+
if (!resolved) {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
const upgrade = resolved.record.handlers.upgrade;
|
|
261
|
+
if (!upgrade) {
|
|
262
|
+
socket.write("HTTP/1.1 404 Not Found\r\n\r\n");
|
|
263
|
+
socket.destroy();
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
upgrade(req, socket, head, resolved.context);
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
private resolve(
|
|
271
|
+
rawUrl: string | undefined,
|
|
272
|
+
): { record: MountRecord; context: MountContext } | null {
|
|
273
|
+
if (!rawUrl) {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
// The base is a placeholder for parsing; only the path and query matter.
|
|
277
|
+
const { pathname, search } = new URL(rawUrl, "http://localhost");
|
|
278
|
+
if (!pathname.startsWith(`${MOUNT_PREFIX}/`)) {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const remainder = pathname.slice(MOUNT_PREFIX.length + 1);
|
|
283
|
+
const slash = remainder.indexOf("/");
|
|
284
|
+
const mountId = slash === -1 ? remainder : remainder.slice(0, slash);
|
|
285
|
+
const record = this.answering(mountId);
|
|
286
|
+
if (!record) {
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const subPath = (slash === -1 ? "/" : remainder.slice(slash)) + search;
|
|
291
|
+
return {
|
|
292
|
+
record,
|
|
293
|
+
context: { mountPath: `${MOUNT_PREFIX}/${mountId}`, subPath },
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which browser pages may call this server, and when a request that carries no
|
|
3
|
+
* credential is let in.
|
|
4
|
+
*
|
|
5
|
+
* Being reachable only from this machine is not the same as being called only
|
|
6
|
+
* by this machine's owner: a page in their browser is a local caller too, and
|
|
7
|
+
* any site can address `127.0.0.1`. So a request admitted without a credential
|
|
8
|
+
* — a server running without auth — must also not come from a foreign page,
|
|
9
|
+
* and must address the server by a name the server knows. A browser states the
|
|
10
|
+
* first in `Origin` (or, on a request it sends without one, in
|
|
11
|
+
* `Sec-Fetch-Site`) and the second in `Host`; a page cannot forge either.
|
|
12
|
+
*
|
|
13
|
+
* A caller that is not a browser sends none of these, and is let in as before:
|
|
14
|
+
* another process on this machine is not what this guards against.
|
|
15
|
+
*
|
|
16
|
+
* A request a proxy passed on is never let in this way. A reverse proxy on the
|
|
17
|
+
* same host — nginx, Caddy — makes every request arrive from this machine at a
|
|
18
|
+
* name the server knows, so where it comes from says nothing any more. One
|
|
19
|
+
* that says so (`Forwarded`, `X-Forwarded-For`, `X-Real-IP`) is refused; one
|
|
20
|
+
* that says nothing cannot be told apart, which is why a loopback bind is a
|
|
21
|
+
* boundary only while nothing forwards to it.
|
|
22
|
+
*
|
|
23
|
+
* The same rule, row for row, is in hkp-rt (`lib/include/origins.h`) and
|
|
24
|
+
* hkp-python (`hkp/origins.py`).
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The origins a server was told may call it, the way `ALLOWED_ORIGINS` gives
|
|
29
|
+
* them:
|
|
30
|
+
*
|
|
31
|
+
* - `"default"` — nothing was said: the origins Readymade's own apps run from,
|
|
32
|
+
* and any page served from this machine;
|
|
33
|
+
* - a list — exactly those;
|
|
34
|
+
* - `"*"` — any origin, for a request that carries a credential. A request
|
|
35
|
+
* that carries none is never let in on the strength of `*`: for it, `*`
|
|
36
|
+
* reads as nothing was said.
|
|
37
|
+
*/
|
|
38
|
+
export type AllowedOrigins = "default" | "*" | string[];
|
|
39
|
+
|
|
40
|
+
/** Where the Readymade apps load their pages from: desktop, iOS, Android. */
|
|
41
|
+
const APP_ORIGINS = [
|
|
42
|
+
"saucer://embedded",
|
|
43
|
+
"hkp://app",
|
|
44
|
+
"https://appassets.androidplatform.net",
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
/** Reads `ALLOWED_ORIGINS`. */
|
|
48
|
+
export function parseAllowedOrigins(value: string | undefined): AllowedOrigins {
|
|
49
|
+
const trimmed = value?.trim();
|
|
50
|
+
if (!trimmed) {
|
|
51
|
+
return "default";
|
|
52
|
+
}
|
|
53
|
+
if (trimmed === "*") {
|
|
54
|
+
return "*";
|
|
55
|
+
}
|
|
56
|
+
return trimmed
|
|
57
|
+
.split(",")
|
|
58
|
+
.map((origin) => origin.trim().toLowerCase())
|
|
59
|
+
.filter(Boolean);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Four dot-separated numbers and nothing else. Strict, because the names this
|
|
64
|
+
* is asked about come from a request: `127.0.0.1.example.com` is a name
|
|
65
|
+
* somebody else resolves, not an address.
|
|
66
|
+
*/
|
|
67
|
+
function isIPv4Literal(host: string): boolean {
|
|
68
|
+
const parts = host.split(".");
|
|
69
|
+
return (
|
|
70
|
+
parts.length === 4 &&
|
|
71
|
+
parts.every((part) => /^\d{1,3}$/.test(part) && Number(part) <= 255)
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function isIPv6Literal(host: string): boolean {
|
|
76
|
+
return /^\[[0-9a-f:.]*:[0-9a-f:.]*\]$/.test(host);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Splits `host[:port]` — a `Host` header, or what follows an origin's scheme. */
|
|
80
|
+
function splitHostPort(value: string): { host: string } | null {
|
|
81
|
+
const match = /^(\[[^\]]*\]|[^:]+)(?::(\d+))?$/.exec(value);
|
|
82
|
+
return match ? { host: match[1].toLowerCase() } : null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function isLoopbackName(host: string): boolean {
|
|
86
|
+
return (
|
|
87
|
+
host === "localhost" ||
|
|
88
|
+
host === "[::1]" ||
|
|
89
|
+
(isIPv4Literal(host) && host.startsWith("127."))
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** True for the origin of a page served from this machine, on any port. */
|
|
94
|
+
export function isLoopbackOrigin(origin: string): boolean {
|
|
95
|
+
const match = /^https?:\/\/(.*)$/.exec(origin.toLowerCase());
|
|
96
|
+
if (!match) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
const parsed = splitHostPort(match[1]);
|
|
100
|
+
return parsed !== null && isLoopbackName(parsed.host);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* True when a `Host` header names the server by something a page cannot have
|
|
105
|
+
* arranged: an address, `localhost`, or a name the server was told is its own.
|
|
106
|
+
*
|
|
107
|
+
* A page that resolves its own name to this machine (DNS rebinding) is
|
|
108
|
+
* same-origin with the server as far as the browser can tell, and sends no
|
|
109
|
+
* `Origin` to refuse — but the name it used is still in `Host`. A request
|
|
110
|
+
* without the header was not sent by a browser.
|
|
111
|
+
*/
|
|
112
|
+
export function isKnownHost(
|
|
113
|
+
hostHeader: string | undefined,
|
|
114
|
+
ownNames: string[],
|
|
115
|
+
): boolean {
|
|
116
|
+
const value = hostHeader?.trim();
|
|
117
|
+
if (!value) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
const parsed = splitHostPort(value);
|
|
121
|
+
if (!parsed) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
const { host } = parsed;
|
|
125
|
+
if (host === "localhost" || isIPv4Literal(host) || isIPv6Literal(host)) {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
return ownNames.some((name) => name !== "" && name.toLowerCase() === host);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Whether a page at `origin` may call the server with nothing but where it is
|
|
133
|
+
* calling from.
|
|
134
|
+
*/
|
|
135
|
+
export function allowsOriginWithoutCredential(
|
|
136
|
+
origin: string | undefined,
|
|
137
|
+
allowed: AllowedOrigins,
|
|
138
|
+
): boolean {
|
|
139
|
+
const value = origin?.trim().toLowerCase();
|
|
140
|
+
if (!value) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
if (Array.isArray(allowed)) {
|
|
144
|
+
return allowed.includes(value);
|
|
145
|
+
}
|
|
146
|
+
return APP_ORIGINS.includes(value) || isLoopbackOrigin(value);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Whether a page at `origin` may read what the server answers, and call it
|
|
151
|
+
* with a credential.
|
|
152
|
+
*/
|
|
153
|
+
export function allowsOrigin(
|
|
154
|
+
origin: string | undefined,
|
|
155
|
+
allowed: AllowedOrigins,
|
|
156
|
+
): boolean {
|
|
157
|
+
return allowed === "*" || allowsOriginWithoutCredential(origin, allowed);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** What a request says about where it came from. */
|
|
161
|
+
export type RequestSource = {
|
|
162
|
+
origin?: string;
|
|
163
|
+
secFetchSite?: string;
|
|
164
|
+
host?: string;
|
|
165
|
+
/** A proxy says it passed the request on; see `isForwarded`. */
|
|
166
|
+
forwarded?: boolean;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/** Whether a request carries a header a proxy adds when it passes one on. */
|
|
170
|
+
export function isForwarded(
|
|
171
|
+
headers: Record<string, string | string[] | undefined>,
|
|
172
|
+
): boolean {
|
|
173
|
+
return ["forwarded", "x-forwarded-for", "x-real-ip"].some((name) => {
|
|
174
|
+
const value = headers[name];
|
|
175
|
+
return (Array.isArray(value) ? value.join(",") : (value ?? "")).trim() !== "";
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Whether a request that carries no credential may be let in on the strength
|
|
181
|
+
* of where it comes from. See the top of this file.
|
|
182
|
+
*/
|
|
183
|
+
export function admitsWithoutCredential(
|
|
184
|
+
source: RequestSource,
|
|
185
|
+
allowed: AllowedOrigins,
|
|
186
|
+
ownNames: string[],
|
|
187
|
+
): boolean {
|
|
188
|
+
if (source.forwarded) {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
if (source.origin?.trim()) {
|
|
192
|
+
if (!allowsOriginWithoutCredential(source.origin, allowed)) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
} else if (source.secFetchSite?.trim().toLowerCase() === "cross-site") {
|
|
196
|
+
// A browser leaves `Origin` off a plain GET it makes for another site's
|
|
197
|
+
// page — an image, a script — and says so here instead.
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
return isKnownHost(source.host, ownNames);
|
|
201
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forgetting everything one instance kept, for a fresh start.
|
|
3
|
+
*
|
|
4
|
+
* What a server restores on starting is easy to forget is there: a deployed
|
|
5
|
+
* board, a ticket to a coordinator, a table with last month's schema. When it
|
|
6
|
+
* is the cause of something, it is the last place anybody looks. Resetting
|
|
7
|
+
* moves the instance's folder aside and lets the next start begin empty.
|
|
8
|
+
*
|
|
9
|
+
* Moved, not deleted. The stale file is often exactly what is worth looking at
|
|
10
|
+
* once the problem is gone, so it is kept where it can be found:
|
|
11
|
+
*
|
|
12
|
+
* ~/.hkp/node-<instance>.reset-2026-10-17T09-12/
|
|
13
|
+
*
|
|
14
|
+
* The name says how old it is and that nothing depends on it; deleting it is
|
|
15
|
+
* whoever reset's to do.
|
|
16
|
+
*
|
|
17
|
+
* The mount secret is carried over unless asked otherwise: it is what keeps a
|
|
18
|
+
* public endpoint's address the same, and a reset for debugging should not
|
|
19
|
+
* break a webhook somebody configured elsewhere.
|
|
20
|
+
*/
|
|
21
|
+
import fs from "fs";
|
|
22
|
+
import path from "path";
|
|
23
|
+
|
|
24
|
+
import {
|
|
25
|
+
Instance,
|
|
26
|
+
InstanceInUseError,
|
|
27
|
+
acquireInstanceLock,
|
|
28
|
+
} from "./instance";
|
|
29
|
+
|
|
30
|
+
const LOCK = "instance.lock";
|
|
31
|
+
const MOUNT_SECRET = "mount-secret";
|
|
32
|
+
|
|
33
|
+
export type ResetOptions = {
|
|
34
|
+
/** Move the folder; without it, only say what would be moved. */
|
|
35
|
+
apply?: boolean;
|
|
36
|
+
/** Leave the mount secret behind as well, which changes every mount address. */
|
|
37
|
+
includeMountSecret?: boolean;
|
|
38
|
+
/** When the reset happens; what the moved folder is named after. */
|
|
39
|
+
now?: Date;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type ResetOutcome = {
|
|
43
|
+
/** Nothing there: the instance has never run, or was reset already. */
|
|
44
|
+
empty: boolean;
|
|
45
|
+
/** What is in the folder: each top-level entry and how many files it holds. */
|
|
46
|
+
entries: Array<{ name: string; files: number }>;
|
|
47
|
+
/** Where the folder goes, or went. */
|
|
48
|
+
movedTo: string;
|
|
49
|
+
/** Whether the mount secret is carried over into the fresh folder. */
|
|
50
|
+
keepsMountSecret: boolean;
|
|
51
|
+
applied: boolean;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
function pad(value: number): string {
|
|
55
|
+
return String(value).padStart(2, "0");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** `2026-10-17T09-12`, in local time: when a person reset it, as they'd say it. */
|
|
59
|
+
export function resetStamp(now: Date): string {
|
|
60
|
+
return (
|
|
61
|
+
`${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}` +
|
|
62
|
+
`T${pad(now.getHours())}-${pad(now.getMinutes())}`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Where the folder goes: a name not yet taken, should two resets share a minute. */
|
|
67
|
+
function destination(instance: Instance, now: Date): string {
|
|
68
|
+
const base = `${instance.dir}.reset-${resetStamp(now)}`;
|
|
69
|
+
let candidate = base;
|
|
70
|
+
for (let n = 2; fs.existsSync(candidate); n++) {
|
|
71
|
+
candidate = `${base}-${n}`;
|
|
72
|
+
}
|
|
73
|
+
return candidate;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function countFiles(location: string): number {
|
|
77
|
+
const stat = fs.statSync(location);
|
|
78
|
+
if (!stat.isDirectory()) {
|
|
79
|
+
return 1;
|
|
80
|
+
}
|
|
81
|
+
return fs
|
|
82
|
+
.readdirSync(location)
|
|
83
|
+
.reduce((sum, entry) => sum + countFiles(path.join(location, entry)), 0);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Resets `instance`, or with `apply` unset, says what resetting it would do.
|
|
88
|
+
*
|
|
89
|
+
* Refuses — with the lock's own message — while a server runs as the
|
|
90
|
+
* instance: it holds the same state in memory and would write it back. And
|
|
91
|
+
* holds the lock itself while it works, so no server starts halfway through.
|
|
92
|
+
*/
|
|
93
|
+
export function resetInstance(
|
|
94
|
+
instance: Instance,
|
|
95
|
+
options: ResetOptions = {},
|
|
96
|
+
): ResetOutcome {
|
|
97
|
+
const now = options.now ?? new Date();
|
|
98
|
+
const keepsMountSecret = !options.includeMountSecret;
|
|
99
|
+
const movedTo = destination(instance, now);
|
|
100
|
+
|
|
101
|
+
const names = fs.existsSync(instance.dir)
|
|
102
|
+
? fs.readdirSync(instance.dir).filter((name) => name !== LOCK)
|
|
103
|
+
: [];
|
|
104
|
+
const entries = names.sort().map((name) => ({
|
|
105
|
+
name,
|
|
106
|
+
files: countFiles(path.join(instance.dir, name)),
|
|
107
|
+
}));
|
|
108
|
+
const outcome: ResetOutcome = {
|
|
109
|
+
empty: entries.length === 0,
|
|
110
|
+
entries,
|
|
111
|
+
movedTo,
|
|
112
|
+
keepsMountSecret,
|
|
113
|
+
applied: false,
|
|
114
|
+
};
|
|
115
|
+
if (outcome.empty) {
|
|
116
|
+
return outcome;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Taken in a dry run too: being told what would be moved from under a
|
|
120
|
+
// running server is being told something that would not happen.
|
|
121
|
+
let release: () => void;
|
|
122
|
+
try {
|
|
123
|
+
release = acquireInstanceLock(instance);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
if (error instanceof InstanceInUseError) {
|
|
126
|
+
const where = error.port ? ` on port ${error.port}` : "";
|
|
127
|
+
throw new InstanceInUseError(
|
|
128
|
+
`hkp-node instance "${instance.name}" is running (pid ${error.pid}` +
|
|
129
|
+
`${where}). Stop it before resetting it: it holds the same state ` +
|
|
130
|
+
"and would write it back.",
|
|
131
|
+
error.pid,
|
|
132
|
+
error.port,
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
if (!options.apply) {
|
|
138
|
+
release();
|
|
139
|
+
return outcome;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
fs.renameSync(instance.dir, movedTo);
|
|
143
|
+
// The lock went along with the folder; it was this process's and is done.
|
|
144
|
+
fs.rmSync(path.join(movedTo, LOCK), { force: true });
|
|
145
|
+
|
|
146
|
+
const secret = path.join(movedTo, MOUNT_SECRET);
|
|
147
|
+
if (keepsMountSecret && fs.existsSync(secret)) {
|
|
148
|
+
fs.mkdirSync(instance.dir, { recursive: true, mode: 0o700 });
|
|
149
|
+
fs.copyFileSync(secret, path.join(instance.dir, MOUNT_SECRET));
|
|
150
|
+
fs.chmodSync(path.join(instance.dir, MOUNT_SECRET), 0o600);
|
|
151
|
+
}
|
|
152
|
+
return { ...outcome, applied: true };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** What a reset run from the command line prints, from what it did. */
|
|
156
|
+
export function describeReset(
|
|
157
|
+
instance: Instance,
|
|
158
|
+
outcome: ResetOutcome,
|
|
159
|
+
): string {
|
|
160
|
+
if (outcome.empty) {
|
|
161
|
+
return `Nothing to reset: ${instance.dir} holds nothing.`;
|
|
162
|
+
}
|
|
163
|
+
const lines = outcome.entries.map(
|
|
164
|
+
({ name, files }) =>
|
|
165
|
+
` ${name}${name === MOUNT_SECRET && outcome.keepsMountSecret ? " (copied back)" : ""}` +
|
|
166
|
+
` — ${files} file${files === 1 ? "" : "s"}`,
|
|
167
|
+
);
|
|
168
|
+
const secret = outcome.keepsMountSecret
|
|
169
|
+
? "The mount secret is copied back, so public endpoint addresses stay the same."
|
|
170
|
+
: "The mount secret goes too: every public endpoint address will change.";
|
|
171
|
+
if (!outcome.applied) {
|
|
172
|
+
return [
|
|
173
|
+
`Resetting instance "${instance.name}" would move ${instance.dir}`,
|
|
174
|
+
...lines,
|
|
175
|
+
`to ${outcome.movedTo}.`,
|
|
176
|
+
secret,
|
|
177
|
+
"Nothing has been changed. Run again with --yes to reset.",
|
|
178
|
+
].join("\n");
|
|
179
|
+
}
|
|
180
|
+
return [
|
|
181
|
+
`Reset instance "${instance.name}": moved ${instance.dir}`,
|
|
182
|
+
...lines,
|
|
183
|
+
`to ${outcome.movedTo}.`,
|
|
184
|
+
secret,
|
|
185
|
+
"Nothing depends on the moved folder; delete it once it is of no more use.",
|
|
186
|
+
].join("\n");
|
|
187
|
+
}
|