@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,790 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
# Service Documentation
|
|
4
|
+
# Service ID: http-server-subservices
|
|
5
|
+
# Service Name: HttpServerSubservices
|
|
6
|
+
# Runtime: hkp-python
|
|
7
|
+
# Modes: none — the entry points a board declares say what it is for
|
|
8
|
+
# Key Config: bypass/onProcess/onRequest (the endpoint is assigned, not configured)
|
|
9
|
+
# IO: in=request envelope -> out=response envelope
|
|
10
|
+
# Arrays: not primary
|
|
11
|
+
# Binary: depends on endpoint + nested services
|
|
12
|
+
# MixedData: not native in runtime
|
|
13
|
+
#
|
|
14
|
+
# **There are two ways in, and a board names the ones it uses.** `onRequest` is
|
|
15
|
+
# a caller arriving; `onProcess` is a pass of the board's own chain. Each is a
|
|
16
|
+
# pipeline of its own, because they are different jobs:
|
|
17
|
+
#
|
|
18
|
+
# { "onRequest": [ … ] } requests; a pass goes through
|
|
19
|
+
# { "onProcess": [ … ] } passes; the board answers
|
|
20
|
+
# { "onProcess": [ … ], "onRequest": [ … ] } both, separately
|
|
21
|
+
# { "pipeline": [ … ] } one pipeline, entered from both
|
|
22
|
+
#
|
|
23
|
+
# **Declaring `onRequest` is what takes the answer away from the chain.** With
|
|
24
|
+
# one, that pipeline is the handler and what it returns is what the caller gets;
|
|
25
|
+
# the services after this one still run — that is where a board acts on having
|
|
26
|
+
# served a request — but after the answer is decided. Without one, the request
|
|
27
|
+
# flows into the services after this one and whatever they return is the answer,
|
|
28
|
+
# which is the inversion of control this service is built around.
|
|
29
|
+
#
|
|
30
|
+
# So an endpoint can have something to run on a pass without silently becoming
|
|
31
|
+
# an HTTP handler, which is what a single unnamed pipeline could not express:
|
|
32
|
+
# having one at all decided who answered.
|
|
33
|
+
#
|
|
34
|
+
# **A value does not survive between the two on its own.** They are separate
|
|
35
|
+
# pipelines, and a pass ends where it ends — so an endpoint that publishes what
|
|
36
|
+
# the board last handed it holds that value in a slot (see `hold`), in cells
|
|
37
|
+
# this service owns and lends to both of its pipelines. Legacy boards say the
|
|
38
|
+
# same thing as `mode: "process_on_data"`, which is this arrangement built in
|
|
39
|
+
# and unnamed; `_entry_for` is where the older spellings are read.
|
|
40
|
+
#
|
|
41
|
+
# What the handler answers with is the envelope read backwards: a value carrying
|
|
42
|
+
# `meta.status` beside `body` or `binary` sets the status, the content type and
|
|
43
|
+
# the headers, and anything else is answered as JSON — which is what a board
|
|
44
|
+
# written before this got. Raw bytes are the one value whose own type decides.
|
|
45
|
+
# That is what lets one endpoint serve a feed as XML and the next serve audio as
|
|
46
|
+
# audio; without it an endpoint can only ever say `application/json`, whatever
|
|
47
|
+
# it is holding. Byte answers are seekable: `Range` is honoured against the
|
|
48
|
+
# bytes the handler produced.
|
|
49
|
+
#
|
|
50
|
+
# A `body` that is an `hkp-asset://<id>` reference is answered with that asset's
|
|
51
|
+
# content, resolved from the runtime's asset store as the answer is written, and
|
|
52
|
+
# with the asset's media type unless `meta` names one — so editing the asset
|
|
53
|
+
# changes the next response without reconfiguring the endpoint.
|
|
54
|
+
#
|
|
55
|
+
# Mirrors hkp-node's `http-server-subservices`, which reads the same shapes.
|
|
56
|
+
|
|
57
|
+
import asyncio
|
|
58
|
+
import json
|
|
59
|
+
import re
|
|
60
|
+
import uuid as _uuid_mod
|
|
61
|
+
from typing import Any, Callable
|
|
62
|
+
from urllib.parse import parse_qsl, urlparse
|
|
63
|
+
|
|
64
|
+
from aiohttp import web
|
|
65
|
+
|
|
66
|
+
from ..mounts import MountContext, MountHandle, decode_body
|
|
67
|
+
from ..runtime import new_run
|
|
68
|
+
from ..mount import MOUNT_FIELD
|
|
69
|
+
from ..assets import parse_asset_ref
|
|
70
|
+
from ..types import (
|
|
71
|
+
ProcessContext,
|
|
72
|
+
JsonRecord,
|
|
73
|
+
NotifyCallback,
|
|
74
|
+
RuntimeHost,
|
|
75
|
+
RuntimeNotification,
|
|
76
|
+
ServiceConfiguration,
|
|
77
|
+
ServiceCreator,
|
|
78
|
+
ServiceRegistryEntry,
|
|
79
|
+
SlotStore,
|
|
80
|
+
)
|
|
81
|
+
from .nested_pipeline import NestedPipeline
|
|
82
|
+
from .sub_service import _is_json_record
|
|
83
|
+
|
|
84
|
+
#: The two ways into this service, named.
|
|
85
|
+
#:
|
|
86
|
+
#: ``onProcess`` is a pass of the board's own chain arriving; ``onRequest`` is a
|
|
87
|
+
#: caller. They are declared as separate pipelines because they are separate
|
|
88
|
+
#: jobs — which is what the ``mode`` flag was standing in for, badly: one
|
|
89
|
+
#: unnamed list could not say what it was for, so a flag beside it had to.
|
|
90
|
+
ENTRY_NAMES = ("onProcess", "onRequest")
|
|
91
|
+
|
|
92
|
+
HTTP_SERVER_SUBSERVICES_DESCRIPTOR = ServiceRegistryEntry(
|
|
93
|
+
service_id="http-server-subservices",
|
|
94
|
+
service_name="HttpServerSubservices",
|
|
95
|
+
capabilities=["subservices"],
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _filename_from_disposition(disposition: str | None) -> str | None:
|
|
100
|
+
"""Extract ``filename="…"`` from a Content-Disposition header, if present."""
|
|
101
|
+
if not disposition:
|
|
102
|
+
return None
|
|
103
|
+
match = re.search(r"filename\*?=(?:UTF-8'')?\"?([^\";]+)\"?", disposition, re.I)
|
|
104
|
+
return match.group(1) if match else None
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _as_response_envelope(value: Any) -> dict[str, Any] | None:
|
|
108
|
+
"""A value read as a response envelope, or None when it is not one.
|
|
109
|
+
|
|
110
|
+
**A status is what tells a response from a request.** Both are the same
|
|
111
|
+
shape — ``meta`` beside ``body`` or ``binary`` — so a pipeline that passes
|
|
112
|
+
its input through returns a request, and reading any ``meta`` as a response
|
|
113
|
+
would answer the caller with the content type they sent. A request carries
|
|
114
|
+
no status and a response always does, which makes ``meta.status`` the one
|
|
115
|
+
field that cannot be a coincidence. It is also what ``http-client`` reports
|
|
116
|
+
a call's response as, so proxying one takes no translation.
|
|
117
|
+
"""
|
|
118
|
+
if not isinstance(value, dict):
|
|
119
|
+
return None
|
|
120
|
+
meta = value.get("meta")
|
|
121
|
+
if not isinstance(meta, dict):
|
|
122
|
+
return None
|
|
123
|
+
if not isinstance(meta.get("status"), int) or isinstance(meta.get("status"), bool):
|
|
124
|
+
return None
|
|
125
|
+
return value if ("binary" in value or "body" in value) else None
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _envelope_headers(meta: dict[str, Any]) -> dict[str, str]:
|
|
129
|
+
"""Header map from an envelope's ``meta.headers``, names lower-cased."""
|
|
130
|
+
declared = meta.get("headers")
|
|
131
|
+
if not isinstance(declared, dict):
|
|
132
|
+
return {}
|
|
133
|
+
return {
|
|
134
|
+
str(name).lower(): str(value)
|
|
135
|
+
for name, value in declared.items()
|
|
136
|
+
if value is not None
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _to_answer(value: Any) -> tuple[int, dict[str, str], bytes]:
|
|
141
|
+
"""The status, headers and bytes a value stands for.
|
|
142
|
+
|
|
143
|
+
Without an envelope the answer is JSON, which is what every board written
|
|
144
|
+
before this got and still gets. The single exception is raw bytes, which are
|
|
145
|
+
sent as bytes: there is no JSON encoding of them anybody wanted.
|
|
146
|
+
"""
|
|
147
|
+
envelope = _as_response_envelope(value)
|
|
148
|
+
if envelope is not None:
|
|
149
|
+
meta = envelope.get("meta") or {}
|
|
150
|
+
headers = _envelope_headers(meta)
|
|
151
|
+
status = int(meta["status"])
|
|
152
|
+
declared = meta.get("contentType")
|
|
153
|
+
declared = declared if isinstance(declared, str) else None
|
|
154
|
+
|
|
155
|
+
binary = envelope.get("binary")
|
|
156
|
+
if isinstance(binary, (bytes, bytearray, memoryview)):
|
|
157
|
+
headers["content-type"] = (
|
|
158
|
+
declared or headers.get("content-type") or "application/octet-stream"
|
|
159
|
+
)
|
|
160
|
+
return status, headers, bytes(binary)
|
|
161
|
+
|
|
162
|
+
body = envelope.get("body")
|
|
163
|
+
if isinstance(body, str):
|
|
164
|
+
headers["content-type"] = (
|
|
165
|
+
declared or headers.get("content-type") or "text/plain; charset=utf-8"
|
|
166
|
+
)
|
|
167
|
+
return status, headers, body.encode("utf-8")
|
|
168
|
+
|
|
169
|
+
headers["content-type"] = (
|
|
170
|
+
declared or headers.get("content-type") or "application/json"
|
|
171
|
+
)
|
|
172
|
+
return status, headers, json.dumps(body, default=str).encode("utf-8")
|
|
173
|
+
|
|
174
|
+
if isinstance(value, (bytes, bytearray, memoryview)):
|
|
175
|
+
return 200, {"content-type": "application/octet-stream"}, bytes(value)
|
|
176
|
+
|
|
177
|
+
return (
|
|
178
|
+
200,
|
|
179
|
+
{"content-type": "application/json"},
|
|
180
|
+
json.dumps(value if value is not None else None, default=str).encode("utf-8"),
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _charset_of(content_type: str) -> str | None:
|
|
185
|
+
"""The charset a content type declares, which aiohttp takes separately."""
|
|
186
|
+
for parameter in content_type.split(";")[1:]:
|
|
187
|
+
name, _, value = parameter.partition("=")
|
|
188
|
+
if name.strip().lower() == "charset":
|
|
189
|
+
return value.strip() or None
|
|
190
|
+
return None
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def _requested_range(header: str | None, length: int) -> tuple[int, int] | None:
|
|
194
|
+
"""The range a ``Range: bytes=…`` header asks for, clamped to what there is.
|
|
195
|
+
|
|
196
|
+
None when the header asks for nothing this can serve — absent, a unit other
|
|
197
|
+
than bytes, several ranges, or a start past the end. A player seeking inside
|
|
198
|
+
an audio file sends one of these, and a server that ignores it re-sends the
|
|
199
|
+
whole file every time somebody drags the scrubber.
|
|
200
|
+
"""
|
|
201
|
+
if not header:
|
|
202
|
+
return None
|
|
203
|
+
match = re.fullmatch(r"bytes=(\d*)-(\d*)", header.strip())
|
|
204
|
+
if not match:
|
|
205
|
+
return None
|
|
206
|
+
raw_start, raw_end = match.groups()
|
|
207
|
+
if not raw_start and not raw_end:
|
|
208
|
+
return None
|
|
209
|
+
|
|
210
|
+
# "bytes=-500" is the last 500 bytes, not a range starting at zero.
|
|
211
|
+
if not raw_start:
|
|
212
|
+
span = int(raw_end)
|
|
213
|
+
return (max(0, length - span), length - 1) if span else None
|
|
214
|
+
|
|
215
|
+
start = int(raw_start)
|
|
216
|
+
if start >= length:
|
|
217
|
+
return None
|
|
218
|
+
end = min(int(raw_end), length - 1) if raw_end else length - 1
|
|
219
|
+
return (start, end) if end >= start else None
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class HttpServerSubservicesService:
|
|
223
|
+
service_id = HTTP_SERVER_SUBSERVICES_DESCRIPTOR.service_id
|
|
224
|
+
service_name = HTTP_SERVER_SUBSERVICES_DESCRIPTOR.service_name
|
|
225
|
+
version: str | None = None
|
|
226
|
+
capabilities = HTTP_SERVER_SUBSERVICES_DESCRIPTOR.capabilities
|
|
227
|
+
|
|
228
|
+
def __init__(
|
|
229
|
+
self,
|
|
230
|
+
config: ServiceConfiguration,
|
|
231
|
+
create_service: ServiceCreator,
|
|
232
|
+
# Upper bound on a request body, in bytes; 0 disables the limit.
|
|
233
|
+
# Supplied by the server because the endpoint is public and shared.
|
|
234
|
+
max_body_bytes: int = 0,
|
|
235
|
+
) -> None:
|
|
236
|
+
self._max_body_bytes = max_body_bytes
|
|
237
|
+
self.uuid = config.uuid
|
|
238
|
+
self._bypass = True
|
|
239
|
+
self._mode: str = "process_on_session"
|
|
240
|
+
self._latest_data: Any = None
|
|
241
|
+
self._mount: MountHandle | None = None
|
|
242
|
+
#: What this endpoint is called, which is what its public address is
|
|
243
|
+
#: derived from. Empty falls back to the service's uuid, which is stable
|
|
244
|
+
#: in a board file too — so an address only changes when a board
|
|
245
|
+
#: deliberately renames it.
|
|
246
|
+
self._mount_name = ""
|
|
247
|
+
#: Which way the board declared its pipelines; see the module header.
|
|
248
|
+
#:
|
|
249
|
+
#: Kept because state reports what was declared rather than a canonical
|
|
250
|
+
#: form: a board saved after being loaded has to come back out the way
|
|
251
|
+
#: it went in, or every board on the older spelling rewrites itself the
|
|
252
|
+
#: first time somebody saves it.
|
|
253
|
+
self._form = "legacy"
|
|
254
|
+
#: The one pipeline a legacy board declares, entered from whichever side
|
|
255
|
+
#: its `mode` says.
|
|
256
|
+
self._legacy: NestedPipeline | None = None
|
|
257
|
+
self._entries: dict[str, NestedPipeline | None] = {
|
|
258
|
+
"onProcess": None,
|
|
259
|
+
"onRequest": None,
|
|
260
|
+
}
|
|
261
|
+
#: The cells this endpoint's pipelines hold values in.
|
|
262
|
+
#:
|
|
263
|
+
#: Owned here because the two entry points are pipelines that never
|
|
264
|
+
#: meet: a value one of them produces has nowhere to live until the
|
|
265
|
+
#: other runs. One store per endpoint is also what keeps the names in it
|
|
266
|
+
#: private, so two endpoints on a runtime may both call a slot
|
|
267
|
+
#: ``document``.
|
|
268
|
+
self._slot_store = SlotStore()
|
|
269
|
+
#: Which of a request's headers the pipeline is shown, or None for all.
|
|
270
|
+
#:
|
|
271
|
+
#: Headers are where a caller puts a credential, and ``meta`` goes
|
|
272
|
+
#: wherever the pipeline takes it — including into a board, if a service
|
|
273
|
+
#: is wired to write it there. Naming the ones a board actually reads is
|
|
274
|
+
#: how it stops carrying the ones it does not: an empty list forwards
|
|
275
|
+
#: none, and no list at all forwards everything, which is what a board
|
|
276
|
+
#: that has not thought about it gets.
|
|
277
|
+
self._forward_headers: list[str] | None = None
|
|
278
|
+
self._create_service = create_service
|
|
279
|
+
self._host: RuntimeHost | None = None
|
|
280
|
+
|
|
281
|
+
if config.state:
|
|
282
|
+
self.configure(config.state)
|
|
283
|
+
|
|
284
|
+
def configure(self, config: JsonRecord) -> JsonRecord:
|
|
285
|
+
# `port` is accepted and ignored: the endpoint is served by the shared
|
|
286
|
+
# runtime server under an assigned path, so a service no longer picks a
|
|
287
|
+
# port. Older boards still carry the field, and rejecting it would fail
|
|
288
|
+
# them on load for a setting that no longer means anything.
|
|
289
|
+
|
|
290
|
+
# An array is a decision, including an empty one. Anything else —
|
|
291
|
+
# absent, None, a string — leaves the default of forwarding all of them.
|
|
292
|
+
if "forwardHeaders" in config:
|
|
293
|
+
names = config["forwardHeaders"]
|
|
294
|
+
self._forward_headers = (
|
|
295
|
+
[n.lower() for n in names if isinstance(n, str)]
|
|
296
|
+
if isinstance(names, list)
|
|
297
|
+
else None
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
if isinstance(config.get("mountName"), str):
|
|
301
|
+
# Renaming rotates this endpoint's address, so an already-claimed
|
|
302
|
+
# mount is released and claimed again under the new name rather than
|
|
303
|
+
# left answering on the old one.
|
|
304
|
+
renamed = config["mountName"] != self._mount_name
|
|
305
|
+
self._mount_name = config["mountName"]
|
|
306
|
+
if renamed and self._mount:
|
|
307
|
+
self._release_mount()
|
|
308
|
+
|
|
309
|
+
# How a board that predates named entry points says which side enters
|
|
310
|
+
# the one pipeline it declares. Still accepted, and still reported back
|
|
311
|
+
# to a board that arrived carrying it; _entry_for is the whole of what
|
|
312
|
+
# it means now.
|
|
313
|
+
if config.get("mode") in (
|
|
314
|
+
"process_on_session",
|
|
315
|
+
"process_on_data",
|
|
316
|
+
"process_on_both",
|
|
317
|
+
):
|
|
318
|
+
self._mode = config["mode"]
|
|
319
|
+
|
|
320
|
+
# Declaring an entry point by name is what puts this endpoint in the
|
|
321
|
+
# newer form, and from then on its state is reported that way.
|
|
322
|
+
for name in ENTRY_NAMES:
|
|
323
|
+
if isinstance(config.get(name), list):
|
|
324
|
+
self._form = "entries"
|
|
325
|
+
self._entry_pipeline(name).set_pipeline(config[name])
|
|
326
|
+
|
|
327
|
+
# An edit aimed at one named entry. The unscoped verbs below cannot say
|
|
328
|
+
# which pipeline they mean once there is more than one.
|
|
329
|
+
if _is_json_record(config.get("configurePipeline")):
|
|
330
|
+
payload = config["configurePipeline"]
|
|
331
|
+
if payload.get("entry") in ENTRY_NAMES:
|
|
332
|
+
self._form = "entries"
|
|
333
|
+
self._edit_pipeline(self._entry_pipeline(payload["entry"]), payload)
|
|
334
|
+
|
|
335
|
+
if (
|
|
336
|
+
isinstance(config.get("pipeline"), list)
|
|
337
|
+
or _is_json_record(config.get("appendService"))
|
|
338
|
+
or isinstance(config.get("removeService"), str)
|
|
339
|
+
or _is_json_record(config.get("configureService"))
|
|
340
|
+
):
|
|
341
|
+
# The unscoped verbs belong to the one pipeline a legacy board
|
|
342
|
+
# declares. Left working rather than redirected at an entry, because
|
|
343
|
+
# which entry they would mean is exactly what the older form cannot
|
|
344
|
+
# say.
|
|
345
|
+
self._edit_pipeline(self._legacy_pipeline(), config)
|
|
346
|
+
|
|
347
|
+
# Bypass toggle
|
|
348
|
+
if isinstance(config.get("bypass"), bool) and config["bypass"] != self._bypass:
|
|
349
|
+
self._bypass = config["bypass"]
|
|
350
|
+
if self._bypass:
|
|
351
|
+
self._release_mount()
|
|
352
|
+
else:
|
|
353
|
+
self._claim_mount()
|
|
354
|
+
|
|
355
|
+
# Anything above may have left this without an endpoint it should have —
|
|
356
|
+
# coming out of bypass, or a rename that released the old address. One
|
|
357
|
+
# check covers them rather than one per cause.
|
|
358
|
+
if not self._bypass and not self._mount:
|
|
359
|
+
self._claim_mount()
|
|
360
|
+
|
|
361
|
+
return self.get_state()
|
|
362
|
+
|
|
363
|
+
def _request_headers(self, request: Any) -> JsonRecord:
|
|
364
|
+
"""The headers this pipeline is shown, lower-cased as HTTP names compare.
|
|
365
|
+
|
|
366
|
+
A caller that has to prove who it is does so in a header — a shared
|
|
367
|
+
secret, a signature, a bearer token — so a pipeline that cannot see them
|
|
368
|
+
cannot check one. What a board does not name, it does not receive.
|
|
369
|
+
"""
|
|
370
|
+
headers: JsonRecord = {}
|
|
371
|
+
for name, value in request.headers.items():
|
|
372
|
+
lowered = name.lower()
|
|
373
|
+
if self._forward_headers is not None and lowered not in self._forward_headers:
|
|
374
|
+
continue
|
|
375
|
+
headers[lowered] = value
|
|
376
|
+
return headers
|
|
377
|
+
|
|
378
|
+
def find_nested(self, instance_id: str):
|
|
379
|
+
"""The nested service a scoped address names, searching every pipeline
|
|
380
|
+
this endpoint owns. The two entries are separate pipelines rather than
|
|
381
|
+
branches of one, so an instanceId used in both resolves to whichever
|
|
382
|
+
``_pipelines()`` lists first.
|
|
383
|
+
"""
|
|
384
|
+
for pipeline in self._pipelines():
|
|
385
|
+
found = pipeline.find(instance_id)
|
|
386
|
+
if found is not None:
|
|
387
|
+
return found
|
|
388
|
+
return None
|
|
389
|
+
|
|
390
|
+
def remount(self) -> None:
|
|
391
|
+
"""See HostedService.remount: the runtime can serve one now.
|
|
392
|
+
|
|
393
|
+
Bypassed is the same answer it gives at set_host: an endpoint switched
|
|
394
|
+
off holds no address, and gaining somewhere to claim one does not
|
|
395
|
+
switch it back on.
|
|
396
|
+
"""
|
|
397
|
+
if not self._bypass:
|
|
398
|
+
self._claim_mount()
|
|
399
|
+
|
|
400
|
+
def get_state(self) -> JsonRecord:
|
|
401
|
+
common = {
|
|
402
|
+
"bypass": self._bypass,
|
|
403
|
+
# Name this endpoint is known by; see the field on the service.
|
|
404
|
+
"mountName": self._mount_name,
|
|
405
|
+
# Public endpoint assigned by the runtime; empty while bypassed.
|
|
406
|
+
# Reserved name: generic board machinery reads and rewrites it (see
|
|
407
|
+
# the frontend's runtime/board/mount).
|
|
408
|
+
MOUNT_FIELD: self._mount.url if self._mount else "",
|
|
409
|
+
"forwardHeaders": self._forward_headers,
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
# What was declared, not what it was understood as. A board that named
|
|
413
|
+
# its entries gets them back; one that carries a `mode` keeps it,
|
|
414
|
+
# because that is the version an older runtime can still load.
|
|
415
|
+
if self._form == "entries":
|
|
416
|
+
state: JsonRecord = dict(common)
|
|
417
|
+
for name in ENTRY_NAMES:
|
|
418
|
+
pipeline = self._entries[name]
|
|
419
|
+
if pipeline is not None:
|
|
420
|
+
state[name] = pipeline.state()
|
|
421
|
+
return state
|
|
422
|
+
|
|
423
|
+
return {
|
|
424
|
+
**common,
|
|
425
|
+
"mode": self._mode,
|
|
426
|
+
"pipeline": self._legacy.state() if self._legacy else [],
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
# ── Pipelines ──────────────────────────────────────────────────────────────
|
|
430
|
+
|
|
431
|
+
def _entry_pipeline(self, name: str) -> NestedPipeline:
|
|
432
|
+
"""The pipeline behind one entry point, built on first use.
|
|
433
|
+
|
|
434
|
+
Built lazily because an endpoint declaring only ``onRequest`` should not
|
|
435
|
+
carry an empty runtime for the side it never uses — and because an empty
|
|
436
|
+
pipeline and an absent one differ here: only the second leaves the board
|
|
437
|
+
answering.
|
|
438
|
+
"""
|
|
439
|
+
existing = self._entries[name]
|
|
440
|
+
if existing is not None:
|
|
441
|
+
return existing
|
|
442
|
+
created = self._new_pipeline(name)
|
|
443
|
+
self._entries[name] = created
|
|
444
|
+
return created
|
|
445
|
+
|
|
446
|
+
def _legacy_pipeline(self) -> NestedPipeline:
|
|
447
|
+
if self._legacy is None:
|
|
448
|
+
self._legacy = self._new_pipeline("pipeline")
|
|
449
|
+
return self._legacy
|
|
450
|
+
|
|
451
|
+
def _new_pipeline(self, label: str) -> NestedPipeline:
|
|
452
|
+
pipeline = NestedPipeline(
|
|
453
|
+
f"{self.uuid}:{label}",
|
|
454
|
+
self._create_service,
|
|
455
|
+
"HttpServerSubservices",
|
|
456
|
+
self.uuid,
|
|
457
|
+
)
|
|
458
|
+
# Both entries hold in the same cells: that they can is the whole reason
|
|
459
|
+
# for declaring them separately.
|
|
460
|
+
pipeline.share_slots(self._slot_store)
|
|
461
|
+
if self._host:
|
|
462
|
+
pipeline.attach(self._host)
|
|
463
|
+
return pipeline
|
|
464
|
+
|
|
465
|
+
def _edit_pipeline(self, pipeline: NestedPipeline, payload: JsonRecord) -> None:
|
|
466
|
+
"""The four edit verbs, applied to whichever pipeline was named."""
|
|
467
|
+
if isinstance(payload.get("pipeline"), list):
|
|
468
|
+
pipeline.set_pipeline(payload["pipeline"])
|
|
469
|
+
elif _is_json_record(payload.get("appendService")):
|
|
470
|
+
pipeline.append(payload["appendService"])
|
|
471
|
+
elif isinstance(payload.get("removeService"), str):
|
|
472
|
+
pipeline.remove(payload["removeService"])
|
|
473
|
+
elif _is_json_record(payload.get("configureService")):
|
|
474
|
+
edit = payload["configureService"]
|
|
475
|
+
if isinstance(edit.get("instanceId"), str) and _is_json_record(edit.get("state")):
|
|
476
|
+
pipeline.configure_service(edit["instanceId"], edit["state"])
|
|
477
|
+
|
|
478
|
+
def _pipelines(self) -> list[NestedPipeline]:
|
|
479
|
+
"""Every pipeline this endpoint owns, each one only once."""
|
|
480
|
+
seen: list[NestedPipeline] = []
|
|
481
|
+
for pipeline in (self._legacy, self._entries["onProcess"], self._entries["onRequest"]):
|
|
482
|
+
if pipeline is not None and not any(p is pipeline for p in seen):
|
|
483
|
+
seen.append(pipeline)
|
|
484
|
+
return seen
|
|
485
|
+
|
|
486
|
+
def _entry_for(self, name: str) -> NestedPipeline | None:
|
|
487
|
+
"""The pipeline one side enters through, or None where it has none.
|
|
488
|
+
|
|
489
|
+
This is where a legacy ``mode`` is read, and the only place it is: a
|
|
490
|
+
board that names its entries never reaches the table below.
|
|
491
|
+
|
|
492
|
+
===================== ========= =========
|
|
493
|
+
declared onProcess onRequest
|
|
494
|
+
===================== ========= =========
|
|
495
|
+
``process_on_session`` — the one
|
|
496
|
+
``process_on_both`` the one the one
|
|
497
|
+
``process_on_data`` — —
|
|
498
|
+
===================== ========= =========
|
|
499
|
+
|
|
500
|
+
``process_on_both`` answers with *the same instance* on both sides,
|
|
501
|
+
never a second copy of the configuration: a pipeline holding a Hold, a
|
|
502
|
+
timer or a mount is one running thing, and duplicating it would give a
|
|
503
|
+
board two of each and a slot that never reaches itself.
|
|
504
|
+
"""
|
|
505
|
+
if self._form == "entries":
|
|
506
|
+
return self._entries[name]
|
|
507
|
+
if self._mode == "process_on_data":
|
|
508
|
+
return None
|
|
509
|
+
if name == "onProcess" and self._mode != "process_on_both":
|
|
510
|
+
return None
|
|
511
|
+
return self._legacy
|
|
512
|
+
|
|
513
|
+
def set_host(self, host: RuntimeHost) -> None:
|
|
514
|
+
self._host = host
|
|
515
|
+
# A pipeline built in the constructor was built before there was a host
|
|
516
|
+
# to ask what board it belongs to, or to report through.
|
|
517
|
+
for pipeline in self._pipelines():
|
|
518
|
+
pipeline.attach(host)
|
|
519
|
+
# State is applied in the constructor, before the host exists, so a
|
|
520
|
+
# service configured as already-active has nothing to claim its mount
|
|
521
|
+
# from until now. Claiming here is what makes a board load into a live
|
|
522
|
+
# endpoint.
|
|
523
|
+
if not self._bypass and not self._mount:
|
|
524
|
+
self._claim_mount()
|
|
525
|
+
|
|
526
|
+
def process(self, input: Any, _notify: NotifyCallback) -> Any:
|
|
527
|
+
# The legacy built-in slot: what the board hands this endpoint is what a
|
|
528
|
+
# caller gets back. Expressible now as an ``onProcess`` that writes a
|
|
529
|
+
# slot and an ``onRequest`` that reads it, and kept because boards carry
|
|
530
|
+
# the older spelling and a board is a document people keep.
|
|
531
|
+
if self._form == "legacy" and self._mode == "process_on_data":
|
|
532
|
+
self._latest_data = input
|
|
533
|
+
return input
|
|
534
|
+
|
|
535
|
+
entry = None if self._bypass else self._entry_for("onProcess")
|
|
536
|
+
if entry is None:
|
|
537
|
+
return input
|
|
538
|
+
|
|
539
|
+
# Routing only: what the pass's own pipeline returns carries on down the
|
|
540
|
+
# chain. Whatever has to survive until a request arrives — a value this
|
|
541
|
+
# side produces and the other reads — belongs in a slot, which is a
|
|
542
|
+
# service's job and not this one's.
|
|
543
|
+
return self._run_entry(entry, input)
|
|
544
|
+
|
|
545
|
+
def destroy(self) -> None:
|
|
546
|
+
self._release_mount()
|
|
547
|
+
# Nested services hold the same things top-level ones do — timers,
|
|
548
|
+
# sockets, mounts — and nothing else will ever reach them once this
|
|
549
|
+
# service is gone.
|
|
550
|
+
for pipeline in self._pipelines():
|
|
551
|
+
pipeline.destroy()
|
|
552
|
+
self._legacy = None
|
|
553
|
+
self._entries["onProcess"] = None
|
|
554
|
+
self._entries["onRequest"] = None
|
|
555
|
+
|
|
556
|
+
# ── Mount ──────────────────────────────────────────────────────────────────
|
|
557
|
+
|
|
558
|
+
def _claim_mount(self) -> None:
|
|
559
|
+
if self._mount or not self._host:
|
|
560
|
+
return
|
|
561
|
+
mount = self._host.mount(self.uuid, self._handle_request, self._mount_name)
|
|
562
|
+
if not mount:
|
|
563
|
+
return
|
|
564
|
+
self._mount = mount
|
|
565
|
+
# A board reads the assigned endpoint from here (or from state), since
|
|
566
|
+
# it is not knowable at design time.
|
|
567
|
+
self._do_notify({MOUNT_FIELD: mount.url}, self.uuid)
|
|
568
|
+
|
|
569
|
+
def _release_mount(self) -> None:
|
|
570
|
+
if self._mount:
|
|
571
|
+
self._mount.release()
|
|
572
|
+
self._mount = None
|
|
573
|
+
|
|
574
|
+
async def _handle_request(
|
|
575
|
+
self, request: web.Request, context: MountContext
|
|
576
|
+
) -> web.Response:
|
|
577
|
+
if self._bypass:
|
|
578
|
+
return web.Response(
|
|
579
|
+
status=503,
|
|
580
|
+
content_type="application/json",
|
|
581
|
+
text=json.dumps({"error": "http-server-subservices is bypassed"}),
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
# Serving a request is one run, however many pipelines it passes
|
|
585
|
+
# through: the nested handler below descends from it, and the outer
|
|
586
|
+
# chain afterwards continues it. Minting one here rather than letting
|
|
587
|
+
# each leg mint its own is what keeps a request's trace joined up
|
|
588
|
+
# instead of arriving as two unrelated runs sharing a timestamp.
|
|
589
|
+
run_context = new_run("mount")
|
|
590
|
+
|
|
591
|
+
# Whether the answer is already decided here, or is whatever the rest
|
|
592
|
+
# of the outer chain makes of what this service emitted.
|
|
593
|
+
answered_here = False
|
|
594
|
+
if self._form == "legacy" and self._mode == "process_on_data":
|
|
595
|
+
process_input = self._latest_data
|
|
596
|
+
output: Any = process_input
|
|
597
|
+
# The mode's whole contract: what the board handed this endpoint is
|
|
598
|
+
# what a caller gets back, verbatim. The services after it still run
|
|
599
|
+
# — having served a request is something a board may want to act on
|
|
600
|
+
# — but what they make of it is theirs, not the answer. Letting the
|
|
601
|
+
# chain's tail answer instead would mean an endpoint could only ever
|
|
602
|
+
# be the last service in its runtime, so a runtime could publish
|
|
603
|
+
# only one document.
|
|
604
|
+
answered_here = True
|
|
605
|
+
else:
|
|
606
|
+
process_input = await self._read_request(request, context)
|
|
607
|
+
# A declared handler is what takes the answer away from the chain —
|
|
608
|
+
# not the presence of a pipeline, which says only that this endpoint
|
|
609
|
+
# has something to run, possibly on the other side. Without one the
|
|
610
|
+
# board answers, which is the inversion of control this service is
|
|
611
|
+
# built around.
|
|
612
|
+
handler = self._entry_for("onRequest")
|
|
613
|
+
answered_here = handler is not None and not handler.is_empty()
|
|
614
|
+
output = (
|
|
615
|
+
self._run_entry(handler, process_input, run_context)
|
|
616
|
+
if handler is not None
|
|
617
|
+
else process_input
|
|
618
|
+
)
|
|
619
|
+
|
|
620
|
+
# What the nested pipeline produced, before the outer runtime sees it.
|
|
621
|
+
answer = output
|
|
622
|
+
|
|
623
|
+
if self._host:
|
|
624
|
+
# process_from reports this service's own call-process pair, so
|
|
625
|
+
# there is no manual pair here — emitting one too would double every
|
|
626
|
+
# request in the UI. It also reports the right value: what this
|
|
627
|
+
# service emitted, rather than what the whole downstream chain
|
|
628
|
+
# finally returned.
|
|
629
|
+
#
|
|
630
|
+
# The callback is a no-op: the runtime already fans notifications
|
|
631
|
+
# out to its targets, and re-notifying would deliver each twice.
|
|
632
|
+
output = self._host.process_from(
|
|
633
|
+
self.uuid, output, lambda _n: None, run_context
|
|
634
|
+
)
|
|
635
|
+
self._host.emit_result(output)
|
|
636
|
+
|
|
637
|
+
# With a nested pipeline configured, that pipeline is the handler and
|
|
638
|
+
# what it returned is the answer; the outer runtime ran for its side
|
|
639
|
+
# effects. Without one, the rest of the board is the handler — except in
|
|
640
|
+
# `process_on_data`, where the stored document is the answer.
|
|
641
|
+
response_value = answer if answered_here else output
|
|
642
|
+
return self._answer(request, await self._resolve_asset_body(response_value))
|
|
643
|
+
|
|
644
|
+
async def _resolve_asset_body(self, value: Any) -> Any:
|
|
645
|
+
"""An answer whose ``body`` is an ``hkp-asset://`` reference, with the
|
|
646
|
+
asset's content in its place.
|
|
647
|
+
|
|
648
|
+
Resolved as the answer is written, so what an endpoint serves is whatever
|
|
649
|
+
the asset holds now. A reference that does not resolve is answered as a
|
|
650
|
+
500 naming the asset and why, and reported — sending the reference itself
|
|
651
|
+
as the page would be a quieter failure, and a worse one.
|
|
652
|
+
"""
|
|
653
|
+
envelope = _as_response_envelope(value)
|
|
654
|
+
if envelope is None or not parse_asset_ref(envelope.get("body")):
|
|
655
|
+
return value
|
|
656
|
+
store = (
|
|
657
|
+
self._host.assets()
|
|
658
|
+
if self._host is not None and hasattr(self._host, "assets")
|
|
659
|
+
else None
|
|
660
|
+
)
|
|
661
|
+
if store is None:
|
|
662
|
+
resolution_problem = "this runtime has no assets"
|
|
663
|
+
asset = None
|
|
664
|
+
else:
|
|
665
|
+
# A URL source is fetched blocking; keep it off the server's loop.
|
|
666
|
+
resolution = await asyncio.to_thread(store.resolve, envelope["body"])
|
|
667
|
+
asset, resolution_problem = resolution.asset, resolution.problem
|
|
668
|
+
if asset is None:
|
|
669
|
+
self._do_notify({"error": resolution_problem})
|
|
670
|
+
return {
|
|
671
|
+
"meta": {"status": 500, "contentType": "application/json"},
|
|
672
|
+
"body": {"error": resolution_problem},
|
|
673
|
+
}
|
|
674
|
+
meta = dict(envelope.get("meta") or {})
|
|
675
|
+
if not (isinstance(meta.get("contentType"), str) and meta["contentType"]):
|
|
676
|
+
meta["contentType"] = asset.media_type
|
|
677
|
+
answer = {key: item for key, item in envelope.items() if key != "body"}
|
|
678
|
+
return {**answer, "meta": meta, "binary": asset.content}
|
|
679
|
+
|
|
680
|
+
def _answer(self, request: web.Request, value: Any) -> web.Response:
|
|
681
|
+
"""Writes what the handler produced, honouring a range request when the
|
|
682
|
+
answer is bytes a caller can seek inside."""
|
|
683
|
+
status, headers, payload = _to_answer(value)
|
|
684
|
+
content_type = headers.pop("content-type", "application/octet-stream")
|
|
685
|
+
|
|
686
|
+
if status == 200:
|
|
687
|
+
headers["accept-ranges"] = "bytes"
|
|
688
|
+
wanted = _requested_range(request.headers.get("Range"), len(payload))
|
|
689
|
+
if wanted:
|
|
690
|
+
start, end = wanted
|
|
691
|
+
headers["content-range"] = f"bytes {start}-{end}/{len(payload)}"
|
|
692
|
+
return web.Response(
|
|
693
|
+
status=206,
|
|
694
|
+
headers=headers,
|
|
695
|
+
content_type=content_type.split(";")[0].strip(),
|
|
696
|
+
charset=_charset_of(content_type),
|
|
697
|
+
body=payload[start : end + 1],
|
|
698
|
+
)
|
|
699
|
+
|
|
700
|
+
return web.Response(
|
|
701
|
+
status=status,
|
|
702
|
+
headers=headers,
|
|
703
|
+
content_type=content_type.split(";")[0].strip(),
|
|
704
|
+
charset=_charset_of(content_type),
|
|
705
|
+
body=payload,
|
|
706
|
+
)
|
|
707
|
+
|
|
708
|
+
async def _read_request(
|
|
709
|
+
self, request: web.Request, context: MountContext
|
|
710
|
+
) -> JsonRecord:
|
|
711
|
+
"""Build the MixedData an incoming request becomes: JSON ``meta``
|
|
712
|
+
describing it, plus the body in whichever single form is useful —
|
|
713
|
+
decoded as ``body`` when the content type says what the bytes mean, raw
|
|
714
|
+
as ``binary`` otherwise. Matches hkp-node's http-server-subservices so a
|
|
715
|
+
pipeline written for one runtime works on the other.
|
|
716
|
+
"""
|
|
717
|
+
# The mount prefix is transport addressing, not part of the route the
|
|
718
|
+
# pipeline matches on, so the pipeline sees the path below the mount.
|
|
719
|
+
parsed = urlparse(context.sub_path)
|
|
720
|
+
meta: JsonRecord = {
|
|
721
|
+
"method": request.method,
|
|
722
|
+
"path": parsed.path or "/",
|
|
723
|
+
"query": dict(parse_qsl(parsed.query)),
|
|
724
|
+
"headers": self._request_headers(request),
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
content_type = request.headers.get("Content-Type")
|
|
728
|
+
if content_type:
|
|
729
|
+
meta["contentType"] = content_type
|
|
730
|
+
filename = _filename_from_disposition(
|
|
731
|
+
request.headers.get("Content-Disposition")
|
|
732
|
+
)
|
|
733
|
+
if filename:
|
|
734
|
+
meta["filename"] = filename
|
|
735
|
+
|
|
736
|
+
body = await self._read_body(request)
|
|
737
|
+
|
|
738
|
+
# Exactly one representation of the body, or neither when there was none.
|
|
739
|
+
decoded = decode_body(body, content_type)
|
|
740
|
+
if decoded is not None:
|
|
741
|
+
return {"meta": meta, "body": decoded}
|
|
742
|
+
if body:
|
|
743
|
+
return {"meta": meta, "binary": body}
|
|
744
|
+
return {"meta": meta}
|
|
745
|
+
|
|
746
|
+
async def _read_body(self, request: web.Request) -> bytes:
|
|
747
|
+
"""Read the request body, refusing anything past the configured cap.
|
|
748
|
+
|
|
749
|
+
A mount is reachable without a token by design, so an unbounded read is
|
|
750
|
+
a way for anyone holding the URL to exhaust the host — which on a shared
|
|
751
|
+
instance is everyone else's problem too. The cap is enforced while
|
|
752
|
+
reading rather than from Content-Length, which a client controls.
|
|
753
|
+
"""
|
|
754
|
+
chunks: list[bytes] = []
|
|
755
|
+
total = 0
|
|
756
|
+
while True:
|
|
757
|
+
chunk = await request.content.readany()
|
|
758
|
+
if not chunk:
|
|
759
|
+
break
|
|
760
|
+
total += len(chunk)
|
|
761
|
+
if self._max_body_bytes and total > self._max_body_bytes:
|
|
762
|
+
raise web.HTTPRequestEntityTooLarge(
|
|
763
|
+
max_size=self._max_body_bytes, actual_size=total
|
|
764
|
+
)
|
|
765
|
+
chunks.append(chunk)
|
|
766
|
+
return b"".join(chunks)
|
|
767
|
+
|
|
768
|
+
# ── Pipeline helpers ───────────────────────────────────────────────────────
|
|
769
|
+
|
|
770
|
+
def _run_entry(
|
|
771
|
+
self,
|
|
772
|
+
pipeline: NestedPipeline,
|
|
773
|
+
input: Any,
|
|
774
|
+
parent: ProcessContext | None = None,
|
|
775
|
+
) -> Any:
|
|
776
|
+
"""Runs one entry's pipeline as a run descended from ``parent``.
|
|
777
|
+
|
|
778
|
+
Both entry points land here, and they differ only in what they descend
|
|
779
|
+
from: a request brings the run its caller minted for the whole exchange,
|
|
780
|
+
while data from the outer chain arrives mid-call and descends from
|
|
781
|
+
whatever that call is running as.
|
|
782
|
+
"""
|
|
783
|
+
context = parent
|
|
784
|
+
if context is None and self._host:
|
|
785
|
+
context = self._host.current_context()
|
|
786
|
+
return pipeline.process(input, context)
|
|
787
|
+
|
|
788
|
+
def _do_notify(self, payload: Any, instance_id: str | None = None) -> None:
|
|
789
|
+
if self._host:
|
|
790
|
+
self._host.notify(payload, instance_id or self.uuid)
|