@pipedog/core 0.0.0 → 0.2.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/LICENSE +25 -0
- package/NOTICE +9 -0
- package/dist/adapters/base_llm_adapter.d.ts +266 -0
- package/dist/adapters/base_llm_adapter.js +489 -0
- package/dist/adapters/index.d.ts +2 -0
- package/dist/adapters/index.js +8 -0
- package/dist/adapters/schemas/direct_function.d.ts +202 -0
- package/dist/adapters/schemas/direct_function.js +302 -0
- package/dist/adapters/schemas/function_schema.d.ts +67 -0
- package/dist/adapters/schemas/function_schema.js +72 -0
- package/dist/adapters/schemas/index.d.ts +2 -0
- package/dist/adapters/schemas/index.js +8 -0
- package/dist/adapters/schemas/tools_schema.d.ts +57 -0
- package/dist/adapters/schemas/tools_schema.js +79 -0
- package/dist/adapters/services/index.d.ts +2 -0
- package/dist/adapters/services/index.js +8 -0
- package/dist/adapters/services/open_ai_adapter.d.ts +147 -0
- package/dist/adapters/services/open_ai_adapter.js +250 -0
- package/dist/audio/dtmf/dtmf_data.d.ts +3 -0
- package/dist/audio/dtmf/dtmf_data.js +22 -0
- package/dist/audio/dtmf/index.d.ts +2 -0
- package/dist/audio/dtmf/index.js +8 -0
- package/dist/audio/dtmf/types.d.ts +31 -0
- package/dist/audio/dtmf/types.js +35 -0
- package/dist/audio/dtmf/utils.d.ts +13 -0
- package/dist/audio/dtmf/utils.js +62 -0
- package/dist/audio/filters/base_audio_filter.d.ts +51 -0
- package/dist/audio/filters/base_audio_filter.js +17 -0
- package/dist/audio/filters/index.d.ts +2 -0
- package/dist/audio/filters/index.js +8 -0
- package/dist/audio/index.d.ts +2 -0
- package/dist/audio/index.js +8 -0
- package/dist/audio/krisp_instance.d.ts +95 -0
- package/dist/audio/krisp_instance.js +229 -0
- package/dist/audio/mixers/base_audio_mixer.d.ts +56 -0
- package/dist/audio/mixers/base_audio_mixer.js +16 -0
- package/dist/audio/mixers/index.d.ts +2 -0
- package/dist/audio/mixers/index.js +8 -0
- package/dist/audio/resamplers/base_audio_resampler.d.ts +46 -0
- package/dist/audio/resamplers/base_audio_resampler.js +35 -0
- package/dist/audio/resamplers/engine.d.ts +60 -0
- package/dist/audio/resamplers/engine.js +89 -0
- package/dist/audio/resamplers/index.d.ts +2 -0
- package/dist/audio/resamplers/index.js +8 -0
- package/dist/audio/resamplers/resampy_resampler.d.ts +10 -0
- package/dist/audio/resamplers/resampy_resampler.js +15 -0
- package/dist/audio/resamplers/sinc_engine.d.ts +10 -0
- package/dist/audio/resamplers/sinc_engine.js +235 -0
- package/dist/audio/resamplers/soxr_resampler.d.ts +58 -0
- package/dist/audio/resamplers/soxr_resampler.js +79 -0
- package/dist/audio/resamplers/soxr_stream_resampler.d.ts +78 -0
- package/dist/audio/resamplers/soxr_stream_resampler.js +159 -0
- package/dist/audio/turn/base_turn_analyzer.d.ts +84 -0
- package/dist/audio/turn/base_turn_analyzer.js +61 -0
- package/dist/audio/turn/index.d.ts +2 -0
- package/dist/audio/turn/index.js +8 -0
- package/dist/audio/turn/smart_turn/_whisper_features.d.ts +30 -0
- package/dist/audio/turn/smart_turn/_whisper_features.js +225 -0
- package/dist/audio/turn/smart_turn/base_smart_turn.d.ts +94 -0
- package/dist/audio/turn/smart_turn/base_smart_turn.js +239 -0
- package/dist/audio/turn/smart_turn/local_smart_turn_v3.d.ts +76 -0
- package/dist/audio/turn/smart_turn/local_smart_turn_v3.js +151 -0
- package/dist/audio/utils.d.ts +224 -0
- package/dist/audio/utils.js +634 -0
- package/dist/audio/vad/data/index.d.ts +2 -0
- package/dist/audio/vad/data/index.js +8 -0
- package/dist/audio/vad/index.d.ts +2 -0
- package/dist/audio/vad/index.js +8 -0
- package/dist/audio/vad/vad_analyzer.d.ts +134 -0
- package/dist/audio/vad/vad_analyzer.js +249 -0
- package/dist/audio/vad/vad_controller.d.ts +143 -0
- package/dist/audio/vad/vad_controller.js +228 -0
- package/dist/audio/volume.d.ts +38 -0
- package/dist/audio/volume.js +75 -0
- package/dist/bus/adapters/base.d.ts +35 -0
- package/dist/bus/adapters/base.js +19 -0
- package/dist/bus/adapters/index.d.ts +10 -0
- package/dist/bus/adapters/index.js +15 -0
- package/dist/bus/adapters/llm_context_adapter.d.ts +36 -0
- package/dist/bus/adapters/llm_context_adapter.js +82 -0
- package/dist/bus/adapters/tools_schema_adapter.d.ts +25 -0
- package/dist/bus/adapters/tools_schema_adapter.js +70 -0
- package/dist/bus/bridge_processor.d.ts +111 -0
- package/dist/bus/bridge_processor.js +166 -0
- package/dist/bus/bus.d.ts +110 -0
- package/dist/bus/bus.js +200 -0
- package/dist/bus/index.d.ts +22 -0
- package/dist/bus/index.js +27 -0
- package/dist/bus/local/async_queue.d.ts +12 -0
- package/dist/bus/local/async_queue.js +21 -0
- package/dist/bus/local/index.d.ts +3 -0
- package/dist/bus/local/index.js +8 -0
- package/dist/bus/messages.d.ts +378 -0
- package/dist/bus/messages.js +357 -0
- package/dist/bus/network/index.d.ts +16 -0
- package/dist/bus/network/index.js +21 -0
- package/dist/bus/queue.d.ts +27 -0
- package/dist/bus/queue.js +51 -0
- package/dist/bus/serializers/base.d.ts +25 -0
- package/dist/bus/serializers/base.js +14 -0
- package/dist/bus/serializers/index.d.ts +9 -0
- package/dist/bus/serializers/index.js +14 -0
- package/dist/bus/serializers/json.d.ts +77 -0
- package/dist/bus/serializers/json.js +367 -0
- package/dist/bus/subscriber.d.ts +46 -0
- package/dist/bus/subscriber.js +27 -0
- package/dist/bus/ui/index.d.ts +3 -0
- package/dist/bus/ui/index.js +8 -0
- package/dist/bus/ui/messages.d.ts +186 -0
- package/dist/bus/ui/messages.js +171 -0
- package/dist/classifiers/base_classifier.d.ts +263 -0
- package/dist/classifiers/base_classifier.js +346 -0
- package/dist/classifiers/cloudflare/clef/classifier.d.ts +70 -0
- package/dist/classifiers/cloudflare/clef/classifier.js +204 -0
- package/dist/classifiers/cloudflare/clef/client.d.ts +104 -0
- package/dist/classifiers/cloudflare/clef/client.js +234 -0
- package/dist/classifiers/cloudflare/clef/index.d.ts +2 -0
- package/dist/classifiers/cloudflare/clef/index.js +8 -0
- package/dist/classifiers/cloudflare/index.d.ts +2 -0
- package/dist/classifiers/cloudflare/index.js +8 -0
- package/dist/classifiers/http_client.d.ts +70 -0
- package/dist/classifiers/http_client.js +161 -0
- package/dist/classifiers/index.d.ts +2 -0
- package/dist/classifiers/index.js +8 -0
- package/dist/classifiers/jev/classifier.d.ts +8 -0
- package/dist/classifiers/jev/classifier.js +13 -0
- package/dist/classifiers/jev/client.d.ts +8 -0
- package/dist/classifiers/jev/client.js +13 -0
- package/dist/classifiers/jev/index.d.ts +2 -0
- package/dist/classifiers/jev/index.js +8 -0
- package/dist/classifiers/llm/classifier.d.ts +72 -0
- package/dist/classifiers/llm/classifier.js +304 -0
- package/dist/classifiers/llm/index.d.ts +2 -0
- package/dist/classifiers/llm/index.js +8 -0
- package/dist/classifiers/openai/decisions/classifier.d.ts +77 -0
- package/dist/classifiers/openai/decisions/classifier.js +241 -0
- package/dist/classifiers/openai/decisions/client.d.ts +108 -0
- package/dist/classifiers/openai/decisions/client.js +234 -0
- package/dist/classifiers/openai/decisions/index.d.ts +2 -0
- package/dist/classifiers/openai/decisions/index.js +8 -0
- package/dist/classifiers/openai/index.d.ts +2 -0
- package/dist/classifiers/openai/index.js +8 -0
- package/dist/classifiers/typesafe/index.d.ts +2 -0
- package/dist/classifiers/typesafe/index.js +8 -0
- package/dist/classifiers/typesafe/jev/classifier.d.ts +70 -0
- package/dist/classifiers/typesafe/jev/classifier.js +220 -0
- package/dist/classifiers/typesafe/jev/client.d.ts +105 -0
- package/dist/classifiers/typesafe/jev/client.js +233 -0
- package/dist/classifiers/typesafe/jev/index.d.ts +2 -0
- package/dist/classifiers/typesafe/jev/index.js +8 -0
- package/dist/clocks/base_clock.d.ts +13 -0
- package/dist/clocks/base_clock.js +14 -0
- package/dist/clocks/index.d.ts +2 -0
- package/dist/clocks/index.js +8 -0
- package/dist/clocks/system_clock.d.ts +15 -0
- package/dist/clocks/system_clock.js +25 -0
- package/dist/frames/frames.d.ts +2533 -0
- package/dist/frames/frames.js +2485 -0
- package/dist/frames/index.d.ts +2 -0
- package/dist/frames/index.js +8 -0
- package/dist/frames/protobufs/frames_pb2.d.ts +229 -0
- package/dist/frames/protobufs/frames_pb2.js +466 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +56 -0
- package/dist/metrics/index.d.ts +2 -0
- package/dist/metrics/index.js +8 -0
- package/dist/metrics/metrics.d.ts +276 -0
- package/dist/metrics/metrics.js +254 -0
- package/dist/observers/base_observer.d.ts +173 -0
- package/dist/observers/base_observer.js +151 -0
- package/dist/observers/error_observer.d.ts +75 -0
- package/dist/observers/error_observer.js +87 -0
- package/dist/observers/function_call_observer.d.ts +157 -0
- package/dist/observers/function_call_observer.js +222 -0
- package/dist/observers/index.d.ts +2 -0
- package/dist/observers/index.js +8 -0
- package/dist/observers/loggers/debug_log_observer.d.ts +91 -0
- package/dist/observers/loggers/debug_log_observer.js +228 -0
- package/dist/observers/loggers/index.d.ts +2 -0
- package/dist/observers/loggers/index.js +8 -0
- package/dist/observers/loggers/llm_log_observer.d.ts +24 -0
- package/dist/observers/loggers/llm_log_observer.js +110 -0
- package/dist/observers/loggers/metrics_log_observer.d.ts +85 -0
- package/dist/observers/loggers/metrics_log_observer.js +186 -0
- package/dist/observers/loggers/transcription_log_observer.d.ts +23 -0
- package/dist/observers/loggers/transcription_log_observer.js +74 -0
- package/dist/observers/service_metrics_observer.d.ts +168 -0
- package/dist/observers/service_metrics_observer.js +236 -0
- package/dist/observers/speaking_observer.d.ts +104 -0
- package/dist/observers/speaking_observer.js +150 -0
- package/dist/observers/startup_timing_observer.d.ts +221 -0
- package/dist/observers/startup_timing_observer.js +365 -0
- package/dist/observers/turn_tracking_observer.d.ts +78 -0
- package/dist/observers/turn_tracking_observer.js +189 -0
- package/dist/observers/user_bot_latency_observer.d.ts +411 -0
- package/dist/observers/user_bot_latency_observer.js +974 -0
- package/dist/pipeline/base_pipeline.d.ts +49 -0
- package/dist/pipeline/base_pipeline.js +101 -0
- package/dist/pipeline/capabilities.d.ts +76 -0
- package/dist/pipeline/capabilities.js +97 -0
- package/dist/pipeline/index.d.ts +2 -0
- package/dist/pipeline/index.js +8 -0
- package/dist/pipeline/job_context.d.ts +317 -0
- package/dist/pipeline/job_context.js +450 -0
- package/dist/pipeline/job_decorator.d.ts +54 -0
- package/dist/pipeline/job_decorator.js +92 -0
- package/dist/pipeline/llm_switcher.d.ts +84 -0
- package/dist/pipeline/llm_switcher.js +107 -0
- package/dist/pipeline/llm_with_backend.d.ts +435 -0
- package/dist/pipeline/llm_with_backend.js +806 -0
- package/dist/pipeline/parallel_pipeline.d.ts +83 -0
- package/dist/pipeline/parallel_pipeline.js +200 -0
- package/dist/pipeline/pipeline.d.ts +126 -0
- package/dist/pipeline/pipeline.js +196 -0
- package/dist/pipeline/service_switcher.d.ts +287 -0
- package/dist/pipeline/service_switcher.js +509 -0
- package/dist/pipeline/sync_parallel_pipeline.d.ts +192 -0
- package/dist/pipeline/sync_parallel_pipeline.js +387 -0
- package/dist/pipeline/worker.d.ts +821 -0
- package/dist/pipeline/worker.js +1656 -0
- package/dist/pipeline/worker_observer.d.ts +131 -0
- package/dist/pipeline/worker_observer.js +274 -0
- package/dist/pipeline/worker_ready_decorator.d.ts +45 -0
- package/dist/pipeline/worker_ready_decorator.js +76 -0
- package/dist/processors/aggregators/async_tool_messages.d.ts +146 -0
- package/dist/processors/aggregators/async_tool_messages.js +291 -0
- package/dist/processors/aggregators/dtmf_aggregator.d.ts +61 -0
- package/dist/processors/aggregators/dtmf_aggregator.js +144 -0
- package/dist/processors/aggregators/gated.d.ts +43 -0
- package/dist/processors/aggregators/gated.js +86 -0
- package/dist/processors/aggregators/gated_llm_context.d.ts +42 -0
- package/dist/processors/aggregators/gated_llm_context.js +86 -0
- package/dist/processors/aggregators/index.d.ts +2 -0
- package/dist/processors/aggregators/index.js +8 -0
- package/dist/processors/aggregators/llm_context.d.ts +370 -0
- package/dist/processors/aggregators/llm_context.js +580 -0
- package/dist/processors/aggregators/llm_context_summarizer.d.ts +219 -0
- package/dist/processors/aggregators/llm_context_summarizer.js +447 -0
- package/dist/processors/aggregators/llm_response.d.ts +37 -0
- package/dist/processors/aggregators/llm_response.js +71 -0
- package/dist/processors/aggregators/llm_response_universal.d.ts +966 -0
- package/dist/processors/aggregators/llm_response_universal.js +2394 -0
- package/dist/processors/aggregators/llm_text_processor.d.ts +53 -0
- package/dist/processors/aggregators/llm_text_processor.js +102 -0
- package/dist/processors/aggregators/sentence.d.ts +39 -0
- package/dist/processors/aggregators/sentence.js +69 -0
- package/dist/processors/async_generator.d.ts +42 -0
- package/dist/processors/async_generator.js +76 -0
- package/dist/processors/audio/audio_buffer_processor.d.ts +241 -0
- package/dist/processors/audio/audio_buffer_processor.js +565 -0
- package/dist/processors/audio/index.d.ts +2 -0
- package/dist/processors/audio/index.js +8 -0
- package/dist/processors/audio/vad_processor.d.ts +67 -0
- package/dist/processors/audio/vad_processor.js +103 -0
- package/dist/processors/consumer_processor.d.ts +49 -0
- package/dist/processors/consumer_processor.js +85 -0
- package/dist/processors/filters/frame_filter.d.ts +39 -0
- package/dist/processors/filters/frame_filter.js +52 -0
- package/dist/processors/filters/function_filter.d.ts +59 -0
- package/dist/processors/filters/function_filter.js +78 -0
- package/dist/processors/filters/identity_filter.d.ts +33 -0
- package/dist/processors/filters/identity_filter.js +37 -0
- package/dist/processors/filters/index.d.ts +2 -0
- package/dist/processors/filters/index.js +8 -0
- package/dist/processors/filters/null_filter.d.ts +34 -0
- package/dist/processors/filters/null_filter.js +47 -0
- package/dist/processors/filters/wake_notifier_filter.d.ts +48 -0
- package/dist/processors/filters/wake_notifier_filter.js +49 -0
- package/dist/processors/frame_processor.d.ts +360 -0
- package/dist/processors/frame_processor.js +932 -0
- package/dist/processors/frameworks/index.d.ts +2 -0
- package/dist/processors/frameworks/index.js +8 -0
- package/dist/processors/frameworks/rtvi/frames.d.ts +241 -0
- package/dist/processors/frameworks/rtvi/frames.js +259 -0
- package/dist/processors/frameworks/rtvi/index.d.ts +6 -0
- package/dist/processors/frameworks/rtvi/index.js +11 -0
- package/dist/processors/frameworks/rtvi/models.d.ts +1741 -0
- package/dist/processors/frameworks/rtvi/models.js +1807 -0
- package/dist/processors/frameworks/rtvi/observer.d.ts +340 -0
- package/dist/processors/frameworks/rtvi/observer.js +1113 -0
- package/dist/processors/frameworks/rtvi/processor.d.ts +182 -0
- package/dist/processors/frameworks/rtvi/processor.js +676 -0
- package/dist/processors/idle_frame_processor.d.ts +44 -0
- package/dist/processors/idle_frame_processor.js +86 -0
- package/dist/processors/index.d.ts +2 -0
- package/dist/processors/index.js +8 -0
- package/dist/processors/logger.d.ts +42 -0
- package/dist/processors/logger.js +87 -0
- package/dist/processors/metrics/frame_processor_metrics.d.ts +172 -0
- package/dist/processors/metrics/frame_processor_metrics.js +372 -0
- package/dist/processors/metrics/index.d.ts +2 -0
- package/dist/processors/metrics/index.js +8 -0
- package/dist/processors/producer_processor.d.ts +68 -0
- package/dist/processors/producer_processor.js +78 -0
- package/dist/processors/text_transformer.d.ts +30 -0
- package/dist/processors/text_transformer.js +48 -0
- package/dist/registry/index.d.ts +3 -0
- package/dist/registry/index.js +8 -0
- package/dist/registry/registry.d.ts +69 -0
- package/dist/registry/registry.js +149 -0
- package/dist/registry/types.d.ts +47 -0
- package/dist/registry/types.js +39 -0
- package/dist/serializers/base_serializer.d.ts +94 -0
- package/dist/serializers/base_serializer.js +82 -0
- package/dist/serializers/index.d.ts +2 -0
- package/dist/serializers/index.js +8 -0
- package/dist/services/ai_service.d.ts +145 -0
- package/dist/services/ai_service.js +262 -0
- package/dist/services/anthropic/index.d.ts +2 -0
- package/dist/services/anthropic/index.js +7 -0
- package/dist/services/assemblyai/index.d.ts +2 -0
- package/dist/services/assemblyai/index.js +7 -0
- package/dist/services/asyncai/index.d.ts +2 -0
- package/dist/services/asyncai/index.js +7 -0
- package/dist/services/aws/index.d.ts +2 -0
- package/dist/services/aws/index.js +7 -0
- package/dist/services/azure/index.d.ts +2 -0
- package/dist/services/azure/index.js +7 -0
- package/dist/services/baseten/index.d.ts +2 -0
- package/dist/services/baseten/index.js +7 -0
- package/dist/services/bland/index.d.ts +2 -0
- package/dist/services/bland/index.js +7 -0
- package/dist/services/camb/index.d.ts +2 -0
- package/dist/services/camb/index.js +7 -0
- package/dist/services/cartesia/index.d.ts +2 -0
- package/dist/services/cartesia/index.js +7 -0
- package/dist/services/cerebras/index.d.ts +2 -0
- package/dist/services/cerebras/index.js +7 -0
- package/dist/services/crusoe/index.d.ts +2 -0
- package/dist/services/crusoe/index.js +7 -0
- package/dist/services/deepgram/index.d.ts +2 -0
- package/dist/services/deepgram/index.js +7 -0
- package/dist/services/deepseek/index.d.ts +2 -0
- package/dist/services/deepseek/index.js +7 -0
- package/dist/services/elevenlabs/index.d.ts +2 -0
- package/dist/services/elevenlabs/index.js +7 -0
- package/dist/services/fal/index.d.ts +2 -0
- package/dist/services/fal/index.js +7 -0
- package/dist/services/fireworks/index.d.ts +2 -0
- package/dist/services/fireworks/index.js +7 -0
- package/dist/services/fish/index.d.ts +2 -0
- package/dist/services/fish/index.js +7 -0
- package/dist/services/funasr/index.d.ts +3 -0
- package/dist/services/funasr/index.js +8 -0
- package/dist/services/gladia/index.d.ts +2 -0
- package/dist/services/gladia/index.js +7 -0
- package/dist/services/google/index.d.ts +2 -0
- package/dist/services/google/index.js +7 -0
- package/dist/services/gradium/index.d.ts +2 -0
- package/dist/services/gradium/index.js +7 -0
- package/dist/services/grok/index.d.ts +2 -0
- package/dist/services/grok/index.js +7 -0
- package/dist/services/groq/index.d.ts +2 -0
- package/dist/services/groq/index.js +7 -0
- package/dist/services/heygen/index.d.ts +2 -0
- package/dist/services/heygen/index.js +7 -0
- package/dist/services/hume/index.d.ts +2 -0
- package/dist/services/hume/index.js +7 -0
- package/dist/services/image_service.d.ts +52 -0
- package/dist/services/image_service.js +60 -0
- package/dist/services/inception/index.d.ts +2 -0
- package/dist/services/inception/index.js +7 -0
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.js +8 -0
- package/dist/services/inworld/index.d.ts +2 -0
- package/dist/services/inworld/index.js +7 -0
- package/dist/services/keenable/index.d.ts +2 -0
- package/dist/services/keenable/index.js +7 -0
- package/dist/services/kokoro/index.d.ts +2 -0
- package/dist/services/kokoro/index.js +7 -0
- package/dist/services/llm_service.d.ts +1106 -0
- package/dist/services/llm_service.js +2231 -0
- package/dist/services/mem0/index.d.ts +2 -0
- package/dist/services/mem0/index.js +7 -0
- package/dist/services/meta/index.d.ts +2 -0
- package/dist/services/meta/index.js +7 -0
- package/dist/services/minimax/index.d.ts +2 -0
- package/dist/services/minimax/index.js +7 -0
- package/dist/services/mistral/index.d.ts +2 -0
- package/dist/services/mistral/index.js +7 -0
- package/dist/services/moondream/index.d.ts +2 -0
- package/dist/services/moondream/index.js +7 -0
- package/dist/services/moonshine/index.d.ts +2 -0
- package/dist/services/moonshine/index.js +7 -0
- package/dist/services/nebius/index.d.ts +2 -0
- package/dist/services/nebius/index.js +7 -0
- package/dist/services/neuphonic/index.d.ts +2 -0
- package/dist/services/neuphonic/index.js +7 -0
- package/dist/services/novita/index.d.ts +2 -0
- package/dist/services/novita/index.js +7 -0
- package/dist/services/nvidia/index.d.ts +2 -0
- package/dist/services/nvidia/index.js +11 -0
- package/dist/services/ollama/index.d.ts +2 -0
- package/dist/services/ollama/index.js +7 -0
- package/dist/services/openai/index.d.ts +2 -0
- package/dist/services/openai/index.js +7 -0
- package/dist/services/openclaw/index.d.ts +14 -0
- package/dist/services/openclaw/index.js +19 -0
- package/dist/services/openrouter/index.d.ts +2 -0
- package/dist/services/openrouter/index.js +7 -0
- package/dist/services/perplexity/index.d.ts +2 -0
- package/dist/services/perplexity/index.js +7 -0
- package/dist/services/piper/index.d.ts +2 -0
- package/dist/services/piper/index.js +7 -0
- package/dist/services/pocket_tts/index.d.ts +2 -0
- package/dist/services/pocket_tts/index.js +7 -0
- package/dist/services/qwen/index.d.ts +2 -0
- package/dist/services/qwen/index.js +7 -0
- package/dist/services/resembleai/index.d.ts +2 -0
- package/dist/services/resembleai/index.js +7 -0
- package/dist/services/rime/index.d.ts +2 -0
- package/dist/services/rime/index.js +7 -0
- package/dist/services/sambanova/index.d.ts +2 -0
- package/dist/services/sambanova/index.js +7 -0
- package/dist/services/sarvam/index.d.ts +2 -0
- package/dist/services/sarvam/index.js +7 -0
- package/dist/services/settings.d.ts +356 -0
- package/dist/services/settings.js +437 -0
- package/dist/services/simli/index.d.ts +2 -0
- package/dist/services/simli/index.js +7 -0
- package/dist/services/smallest/index.d.ts +2 -0
- package/dist/services/smallest/index.js +7 -0
- package/dist/services/soniox/index.d.ts +2 -0
- package/dist/services/soniox/index.js +7 -0
- package/dist/services/speechify/index.d.ts +2 -0
- package/dist/services/speechify/index.js +7 -0
- package/dist/services/speechmatics/index.d.ts +2 -0
- package/dist/services/speechmatics/index.js +7 -0
- package/dist/services/stt_latency.d.ts +62 -0
- package/dist/services/stt_latency.js +71 -0
- package/dist/services/stt_service.d.ts +601 -0
- package/dist/services/stt_service.js +1044 -0
- package/dist/services/tavus/index.d.ts +2 -0
- package/dist/services/tavus/index.js +7 -0
- package/dist/services/together/index.d.ts +2 -0
- package/dist/services/together/index.js +7 -0
- package/dist/services/tts_service.d.ts +909 -0
- package/dist/services/tts_service.js +2018 -0
- package/dist/services/ultravox/index.d.ts +2 -0
- package/dist/services/ultravox/index.js +9 -0
- package/dist/services/vision_service.d.ts +56 -0
- package/dist/services/vision_service.js +62 -0
- package/dist/services/websocket_service.d.ts +213 -0
- package/dist/services/websocket_service.js +654 -0
- package/dist/services/whisper/index.d.ts +2 -0
- package/dist/services/whisper/index.js +9 -0
- package/dist/services/xai/index.d.ts +2 -0
- package/dist/services/xai/index.js +9 -0
- package/dist/services/xtts/index.d.ts +2 -0
- package/dist/services/xtts/index.js +9 -0
- package/dist/tests/index.d.ts +2 -0
- package/dist/tests/index.js +8 -0
- package/dist/tests/utils.d.ts +123 -0
- package/dist/tests/utils.js +212 -0
- package/dist/transcriptions/index.d.ts +2 -0
- package/dist/transcriptions/index.js +8 -0
- package/dist/transcriptions/language.d.ts +376 -0
- package/dist/transcriptions/language.js +543 -0
- package/dist/transports/base_input.d.ts +149 -0
- package/dist/transports/base_input.js +338 -0
- package/dist/transports/base_output.d.ts +432 -0
- package/dist/transports/base_output.js +1231 -0
- package/dist/transports/base_transport.d.ts +223 -0
- package/dist/transports/base_transport.js +167 -0
- package/dist/transports/daily/index.d.ts +2 -0
- package/dist/transports/daily/index.js +9 -0
- package/dist/transports/heygen/index.d.ts +2 -0
- package/dist/transports/heygen/index.js +9 -0
- package/dist/transports/index.d.ts +2 -0
- package/dist/transports/index.js +8 -0
- package/dist/transports/lemonslice/index.d.ts +2 -0
- package/dist/transports/lemonslice/index.js +9 -0
- package/dist/transports/livekit/index.d.ts +2 -0
- package/dist/transports/livekit/index.js +9 -0
- package/dist/transports/local/index.d.ts +2 -0
- package/dist/transports/local/index.js +9 -0
- package/dist/transports/moq/index.d.ts +2 -0
- package/dist/transports/moq/index.js +9 -0
- package/dist/transports/smallwebrtc/index.d.ts +2 -0
- package/dist/transports/smallwebrtc/index.js +9 -0
- package/dist/transports/tavus/index.d.ts +2 -0
- package/dist/transports/tavus/index.js +9 -0
- package/dist/transports/video_in_sampler.d.ts +157 -0
- package/dist/transports/video_in_sampler.js +258 -0
- package/dist/transports/vonage/index.d.ts +2 -0
- package/dist/transports/vonage/index.js +9 -0
- package/dist/transports/websocket/index.d.ts +2 -0
- package/dist/transports/websocket/index.js +9 -0
- package/dist/transports/whatsapp/index.d.ts +2 -0
- package/dist/transports/whatsapp/index.js +9 -0
- package/dist/turns/eager_end_of_turn_mixin.d.ts +70 -0
- package/dist/turns/eager_end_of_turn_mixin.js +122 -0
- package/dist/turns/empty_user_turn.d.ts +55 -0
- package/dist/turns/empty_user_turn.js +53 -0
- package/dist/turns/index.d.ts +2 -0
- package/dist/turns/index.js +8 -0
- package/dist/turns/speculation_gate.d.ts +169 -0
- package/dist/turns/speculation_gate.js +294 -0
- package/dist/turns/types.d.ts +33 -0
- package/dist/turns/types.js +35 -0
- package/dist/turns/user_idle_controller.d.ts +94 -0
- package/dist/turns/user_idle_controller.js +187 -0
- package/dist/turns/user_mute/always_user_mute_strategy.d.ts +15 -0
- package/dist/turns/user_mute/always_user_mute_strategy.js +29 -0
- package/dist/turns/user_mute/base_user_mute_strategy.d.ts +39 -0
- package/dist/turns/user_mute/base_user_mute_strategy.js +45 -0
- package/dist/turns/user_mute/first_speech_user_mute_strategy.d.ts +28 -0
- package/dist/turns/user_mute/first_speech_user_mute_strategy.js +52 -0
- package/dist/turns/user_mute/function_call_user_mute_strategy.d.ts +25 -0
- package/dist/turns/user_mute/function_call_user_mute_strategy.js +50 -0
- package/dist/turns/user_mute/index.d.ts +6 -0
- package/dist/turns/user_mute/index.js +11 -0
- package/dist/turns/user_mute/mute_until_first_bot_complete_user_mute_strategy.d.ts +43 -0
- package/dist/turns/user_mute/mute_until_first_bot_complete_user_mute_strategy.js +76 -0
- package/dist/turns/user_start/base_user_turn_start_strategy.d.ts +135 -0
- package/dist/turns/user_start/base_user_turn_start_strategy.js +134 -0
- package/dist/turns/user_start/external_user_turn_start_strategy.d.ts +45 -0
- package/dist/turns/user_start/external_user_turn_start_strategy.js +64 -0
- package/dist/turns/user_start/index.d.ts +8 -0
- package/dist/turns/user_start/index.js +16 -0
- package/dist/turns/user_start/krisp_viva_ip_user_turn_start_strategy.d.ts +133 -0
- package/dist/turns/user_start/krisp_viva_ip_user_turn_start_strategy.js +243 -0
- package/dist/turns/user_start/min_words_user_turn_start_strategy.d.ts +60 -0
- package/dist/turns/user_start/min_words_user_turn_start_strategy.js +102 -0
- package/dist/turns/user_start/transcription_user_turn_start_strategy.d.ts +29 -0
- package/dist/turns/user_start/transcription_user_turn_start_strategy.js +43 -0
- package/dist/turns/user_start/vad_user_turn_start_strategy.d.ts +20 -0
- package/dist/turns/user_start/vad_user_turn_start_strategy.js +31 -0
- package/dist/turns/user_start/wake_phrase_user_turn_start_strategy.d.ts +141 -0
- package/dist/turns/user_start/wake_phrase_user_turn_start_strategy.js +238 -0
- package/dist/turns/user_stop/base_user_turn_stop_strategy.d.ts +174 -0
- package/dist/turns/user_stop/base_user_turn_stop_strategy.js +170 -0
- package/dist/turns/user_stop/deferred_user_turn_stop_strategy.d.ts +81 -0
- package/dist/turns/user_stop/deferred_user_turn_stop_strategy.js +107 -0
- package/dist/turns/user_stop/eager_match_policy.d.ts +36 -0
- package/dist/turns/user_stop/eager_match_policy.js +50 -0
- package/dist/turns/user_stop/eager_user_turn_stop_strategy.d.ts +84 -0
- package/dist/turns/user_stop/eager_user_turn_stop_strategy.js +154 -0
- package/dist/turns/user_stop/external_user_turn_completion_stop_strategy.d.ts +45 -0
- package/dist/turns/user_stop/external_user_turn_completion_stop_strategy.js +55 -0
- package/dist/turns/user_stop/external_user_turn_stop_strategy.d.ts +115 -0
- package/dist/turns/user_stop/external_user_turn_stop_strategy.js +205 -0
- package/dist/turns/user_stop/index.d.ts +10 -0
- package/dist/turns/user_stop/index.js +15 -0
- package/dist/turns/user_stop/llm_turn_completion_user_turn_stop_strategy.d.ts +44 -0
- package/dist/turns/user_stop/llm_turn_completion_user_turn_stop_strategy.js +59 -0
- package/dist/turns/user_stop/speech_timeout_user_turn_stop_strategy.d.ts +140 -0
- package/dist/turns/user_stop/speech_timeout_user_turn_stop_strategy.js +303 -0
- package/dist/turns/user_stop/turn_analyzer_user_turn_stop_strategy.d.ts +135 -0
- package/dist/turns/user_stop/turn_analyzer_user_turn_stop_strategy.js +332 -0
- package/dist/turns/user_turn_completion_mixin.d.ts +147 -0
- package/dist/turns/user_turn_completion_mixin.js +591 -0
- package/dist/turns/user_turn_controller.d.ts +134 -0
- package/dist/turns/user_turn_controller.js +335 -0
- package/dist/turns/user_turn_processor.d.ts +87 -0
- package/dist/turns/user_turn_processor.js +180 -0
- package/dist/turns/user_turn_strategies.d.ts +187 -0
- package/dist/turns/user_turn_strategies.js +222 -0
- package/dist/utils/async_tool_cancellation.d.ts +35 -0
- package/dist/utils/async_tool_cancellation.js +78 -0
- package/dist/utils/asyncio/index.d.ts +2 -0
- package/dist/utils/asyncio/index.js +7 -0
- package/dist/utils/asyncio/task_manager.d.ts +49 -0
- package/dist/utils/asyncio/task_manager.js +105 -0
- package/dist/utils/base_object.d.ts +76 -0
- package/dist/utils/base_object.js +154 -0
- package/dist/utils/context/aggregated_frame_sequencer.d.ts +491 -0
- package/dist/utils/context/aggregated_frame_sequencer.js +803 -0
- package/dist/utils/context/audio_context_manager.d.ts +131 -0
- package/dist/utils/context/audio_context_manager.js +233 -0
- package/dist/utils/context/index.d.ts +2 -0
- package/dist/utils/context/index.js +7 -0
- package/dist/utils/context/llm_context_summarization.d.ts +258 -0
- package/dist/utils/context/llm_context_summarization.js +511 -0
- package/dist/utils/context/text_segment_map.d.ts +611 -0
- package/dist/utils/context/text_segment_map.js +1132 -0
- package/dist/utils/context/word_completion_tracker.d.ts +273 -0
- package/dist/utils/context/word_completion_tracker.js +441 -0
- package/dist/utils/context/word_timestamp_tracker.d.ts +72 -0
- package/dist/utils/context/word_timestamp_tracker.js +98 -0
- package/dist/utils/deprecation.d.ts +28 -0
- package/dist/utils/deprecation.js +75 -0
- package/dist/utils/env.d.ts +38 -0
- package/dist/utils/env.js +62 -0
- package/dist/utils/errors.d.ts +75 -0
- package/dist/utils/errors.js +202 -0
- package/dist/utils/file_resolver.d.ts +126 -0
- package/dist/utils/file_resolver.js +314 -0
- package/dist/utils/file_storage.d.ts +115 -0
- package/dist/utils/file_storage.js +178 -0
- package/dist/utils/frame_queue.d.ts +36 -0
- package/dist/utils/frame_queue.js +66 -0
- package/dist/utils/http.d.ts +39 -0
- package/dist/utils/http.js +53 -0
- package/dist/utils/image.d.ts +14 -0
- package/dist/utils/image.js +63 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/jpeg_encoder.d.ts +14 -0
- package/dist/utils/jpeg_encoder.js +315 -0
- package/dist/utils/log_config.d.ts +34 -0
- package/dist/utils/log_config.js +76 -0
- package/dist/utils/logger.d.ts +40 -0
- package/dist/utils/logger.js +91 -0
- package/dist/utils/mixin.d.ts +14 -0
- package/dist/utils/mixin.js +63 -0
- package/dist/utils/network.d.ts +73 -0
- package/dist/utils/network.js +90 -0
- package/dist/utils/security/allowed_origins.d.ts +16 -0
- package/dist/utils/security/allowed_origins.js +34 -0
- package/dist/utils/security/index.d.ts +2 -0
- package/dist/utils/security/index.js +7 -0
- package/dist/utils/security/redaction.d.ts +27 -0
- package/dist/utils/security/redaction.js +123 -0
- package/dist/utils/security/ssrf.d.ts +79 -0
- package/dist/utils/security/ssrf.js +327 -0
- package/dist/utils/shared.d.ts +35 -0
- package/dist/utils/shared.js +136 -0
- package/dist/utils/startup.d.ts +17 -0
- package/dist/utils/startup.js +130 -0
- package/dist/utils/string.d.ts +116 -0
- package/dist/utils/string.js +460 -0
- package/dist/utils/sync/base_notifier.d.ts +25 -0
- package/dist/utils/sync/base_notifier.js +16 -0
- package/dist/utils/sync/event_notifier.d.ts +38 -0
- package/dist/utils/sync/event_notifier.js +51 -0
- package/dist/utils/sync/index.d.ts +2 -0
- package/dist/utils/sync/index.js +7 -0
- package/dist/utils/text/alnum_utils.d.ts +109 -0
- package/dist/utils/text/alnum_utils.js +262 -0
- package/dist/utils/text/base_text_aggregator.d.ts +146 -0
- package/dist/utils/text/base_text_aggregator.js +102 -0
- package/dist/utils/text/base_text_filter.d.ts +54 -0
- package/dist/utils/text/base_text_filter.js +50 -0
- package/dist/utils/text/index.d.ts +2 -0
- package/dist/utils/text/index.js +7 -0
- package/dist/utils/text/markdown_text_filter.d.ts +147 -0
- package/dist/utils/text/markdown_text_filter.js +522 -0
- package/dist/utils/text/markup_utils.d.ts +54 -0
- package/dist/utils/text/markup_utils.js +156 -0
- package/dist/utils/text/pattern_pair_aggregator.d.ts +251 -0
- package/dist/utils/text/pattern_pair_aggregator.js +478 -0
- package/dist/utils/text/phonemes.d.ts +60 -0
- package/dist/utils/text/phonemes.js +172 -0
- package/dist/utils/text/simple_text_aggregator.d.ts +135 -0
- package/dist/utils/text/simple_text_aggregator.js +254 -0
- package/dist/utils/text/skip_tags_aggregator.d.ts +85 -0
- package/dist/utils/text/skip_tags_aggregator.js +147 -0
- package/dist/utils/text/transforms/acronyms.d.ts +21 -0
- package/dist/utils/text/transforms/acronyms.js +31 -0
- package/dist/utils/text/transforms/currency.d.ts +16 -0
- package/dist/utils/text/transforms/currency.js +56 -0
- package/dist/utils/text/transforms/dates.d.ts +18 -0
- package/dist/utils/text/transforms/dates.js +102 -0
- package/dist/utils/text/transforms/email.d.ts +17 -0
- package/dist/utils/text/transforms/email.js +35 -0
- package/dist/utils/text/transforms/index.d.ts +37 -0
- package/dist/utils/text/transforms/index.js +42 -0
- package/dist/utils/text/transforms/numbers.d.ts +25 -0
- package/dist/utils/text/transforms/numbers.js +59 -0
- package/dist/utils/text/transforms/percentages.d.ts +16 -0
- package/dist/utils/text/transforms/percentages.js +32 -0
- package/dist/utils/text/transforms/phone.d.ts +21 -0
- package/dist/utils/text/transforms/phone.js +39 -0
- package/dist/utils/text/transforms/pronunciations.d.ts +65 -0
- package/dist/utils/text/transforms/pronunciations.js +112 -0
- package/dist/utils/text/transforms/replacements.d.ts +39 -0
- package/dist/utils/text/transforms/replacements.js +46 -0
- package/dist/utils/text/transforms/strip_markdown.d.ts +25 -0
- package/dist/utils/text/transforms/strip_markdown.js +60 -0
- package/dist/utils/text/transforms/units.d.ts +22 -0
- package/dist/utils/text/transforms/units.js +81 -0
- package/dist/utils/text/transforms/voice_formatter.d.ts +86 -0
- package/dist/utils/text/transforms/voice_formatter.js +98 -0
- package/dist/utils/text/unicode_digits.d.ts +3 -0
- package/dist/utils/text/unicode_digits.js +34 -0
- package/dist/utils/text/word_timestamp_utils.d.ts +26 -0
- package/dist/utils/text/word_timestamp_utils.js +52 -0
- package/dist/utils/time.d.ts +13 -0
- package/dist/utils/time.js +31 -0
- package/dist/utils/tracing/index.d.ts +3 -0
- package/dist/utils/tracing/index.js +8 -0
- package/dist/utils/tracing/service_attributes.d.ts +198 -0
- package/dist/utils/tracing/service_attributes.js +434 -0
- package/dist/utils/tracing/service_decorators.d.ts +214 -0
- package/dist/utils/tracing/service_decorators.js +1662 -0
- package/dist/utils/tracing/setup.d.ts +107 -0
- package/dist/utils/tracing/setup.js +160 -0
- package/dist/utils/tracing/tracing_context.d.ts +55 -0
- package/dist/utils/tracing/tracing_context.js +97 -0
- package/dist/utils/tracing/turn_trace_observer.d.ts +95 -0
- package/dist/utils/tracing/turn_trace_observer.js +233 -0
- package/dist/utils/types.d.ts +80 -0
- package/dist/utils/types.js +108 -0
- package/dist/utils/utils.d.ts +5 -0
- package/dist/utils/utils.js +22 -0
- package/dist/utils/yaml.d.ts +179 -0
- package/dist/utils/yaml.js +556 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.js +7 -0
- package/dist/workers/base_worker.d.ts +772 -0
- package/dist/workers/base_worker.js +1298 -0
- package/dist/workers/index.d.ts +2 -0
- package/dist/workers/index.js +8 -0
- package/dist/workers/llm/backend_llm_worker.d.ts +552 -0
- package/dist/workers/llm/backend_llm_worker.js +1055 -0
- package/dist/workers/llm/index.d.ts +6 -0
- package/dist/workers/llm/index.js +11 -0
- package/dist/workers/llm/llm_context_worker.d.ts +66 -0
- package/dist/workers/llm/llm_context_worker.js +72 -0
- package/dist/workers/llm/llm_worker.d.ts +180 -0
- package/dist/workers/llm/llm_worker.js +323 -0
- package/dist/workers/llm/tool_decorator.d.ts +68 -0
- package/dist/workers/llm/tool_decorator.js +60 -0
- package/dist/workers/proxy/index.d.ts +3 -0
- package/dist/workers/proxy/index.js +9 -0
- package/dist/workers/proxy/websocket/client.d.ts +110 -0
- package/dist/workers/proxy/websocket/client.js +196 -0
- package/dist/workers/proxy/websocket/index.d.ts +3 -0
- package/dist/workers/proxy/websocket/index.js +10 -0
- package/dist/workers/runner.d.ts +268 -0
- package/dist/workers/runner.js +489 -0
- package/dist/workers/ui/index.d.ts +22 -0
- package/dist/workers/ui/index.js +27 -0
- package/dist/workers/ui/ui_event_decorator.d.ts +43 -0
- package/dist/workers/ui/ui_event_decorator.js +75 -0
- package/dist/workers/ui/ui_job_context.d.ts +12 -0
- package/dist/workers/ui/ui_job_context.js +17 -0
- package/dist/workers/ui/ui_prompts.d.ts +21 -0
- package/dist/workers/ui/ui_prompts.js +41 -0
- package/dist/workers/ui/ui_tools.d.ts +32 -0
- package/dist/workers/ui/ui_tools.js +112 -0
- package/dist/workers/ui/ui_worker.d.ts +571 -0
- package/dist/workers/ui/ui_worker.js +1156 -0
- package/package.json +61 -3
- package/README.md +0 -5
|
@@ -0,0 +1,1298 @@
|
|
|
1
|
+
// Copyright (c) 2024-2026, Daily
|
|
2
|
+
// Copyright (c) 2026, pipedog contributors
|
|
3
|
+
// SPDX-License-Identifier: BSD-2-Clause
|
|
4
|
+
//
|
|
5
|
+
// Ported from pipecat: src/pipecat/workers/base_worker.py
|
|
6
|
+
/**
|
|
7
|
+
* Abstract base worker for the multi-worker framework.
|
|
8
|
+
*
|
|
9
|
+
* Provides the `BaseWorker` class that all workers inherit from, handling
|
|
10
|
+
* worker lifecycle, parent-child relationships, and long-running job
|
|
11
|
+
* coordination on the bus.
|
|
12
|
+
*
|
|
13
|
+
* Porting notes:
|
|
14
|
+
* - The deprecated per-argument job spelling (`name=`, `payload=`,
|
|
15
|
+
* `timeout=`, `cancel_on_error=` on `request_job`, `job`,
|
|
16
|
+
* `request_job_group`, `job_group` and `create_job_group_and_request_job`)
|
|
17
|
+
* and `resolve_job_params` are not ported; pass `params` instead.
|
|
18
|
+
* - Methods that take `*names` plus keyword arguments take the names as rest
|
|
19
|
+
* arguments and an optional trailing options object:
|
|
20
|
+
* `this.jobGroup("w1", "w2", { params })`, `this.addWorkers(a, b, { watch: false })`.
|
|
21
|
+
*/
|
|
22
|
+
import { CancelledError, currentTask, Event, gather, Lock, sleep, TimeoutError, time, waitFor, } from "@pipedog/asyncio";
|
|
23
|
+
import { BusActivateWorkerMessage, BusAddWorkerMessage, BusCancelMessage, BusCancelWorkerMessage, BusDeactivateWorkerMessage, BusEndMessage, BusEndWorkerMessage, BusFrameMessage, BusJobCancelMessage, BusJobRequestMessage, BusJobResponseMessage, BusJobResponseUrgentMessage, BusJobStreamDataMessage, BusJobStreamEndMessage, BusJobStreamStartMessage, BusJobUpdateMessage, BusJobUpdateRequestMessage, BusJobUpdateUrgentMessage, BusWorkerErrorMessage, BusWorkerLocalErrorMessage, BusWorkerReadyMessage, } from "../bus/messages.js";
|
|
24
|
+
import { BusSubscriber } from "../bus/subscriber.js";
|
|
25
|
+
import { JobContext, JobGroup, JobGroupContext, JobGroupError, JobGroupEvent, JobGroupParams, JobGroupResponse, JobParams, JobStatus, } from "../pipeline/job_context.js";
|
|
26
|
+
import { _collectJobHandlers } from "../pipeline/job_decorator.js";
|
|
27
|
+
import { _collectWorkerReadyHandlers } from "../pipeline/worker_ready_decorator.js";
|
|
28
|
+
import { WorkerErrorData, WorkerReadyData } from "../registry/types.js";
|
|
29
|
+
import { BaseObject } from "../utils/base_object.js";
|
|
30
|
+
import { logger } from "../utils/logger.js";
|
|
31
|
+
/**
|
|
32
|
+
* Configuration parameters for worker execution.
|
|
33
|
+
*
|
|
34
|
+
* - `taskManager`: Task manager for handling asyncio tasks.
|
|
35
|
+
*/
|
|
36
|
+
export class WorkerParams {
|
|
37
|
+
taskManager;
|
|
38
|
+
constructor(options) {
|
|
39
|
+
this.taskManager = options.taskManager;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Base activation arguments for any worker.
|
|
44
|
+
*
|
|
45
|
+
* - `metadata`: Optional structured data passed during activation.
|
|
46
|
+
*
|
|
47
|
+
* Subclasses add fields (with defaults) and accept them in their options
|
|
48
|
+
* object; `fromDict` and `toDict` work off the instance's own fields.
|
|
49
|
+
*/
|
|
50
|
+
export class WorkerActivationArgs {
|
|
51
|
+
metadata;
|
|
52
|
+
constructor(options = {}) {
|
|
53
|
+
this.metadata = options.metadata ?? null;
|
|
54
|
+
}
|
|
55
|
+
/** Create from a dict, ignoring unknown keys. */
|
|
56
|
+
static fromDict(data) {
|
|
57
|
+
const fields = new Set(Object.keys(new this({})));
|
|
58
|
+
return new this(Object.fromEntries(Object.entries(data).filter(([k]) => fields.has(k))));
|
|
59
|
+
}
|
|
60
|
+
/** Convert to a dict, excluding null values. */
|
|
61
|
+
toDict() {
|
|
62
|
+
return Object.fromEntries(Object.entries(this).filter(([, value]) => value !== null && value !== undefined));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Messages an inactive worker still receives: the ones that change whether it
|
|
67
|
+
* is active, and the ones that stop it. Gating these would leave it with no
|
|
68
|
+
* way to be woken or shut down.
|
|
69
|
+
*/
|
|
70
|
+
const ALWAYS_DELIVERED = [
|
|
71
|
+
BusActivateWorkerMessage,
|
|
72
|
+
BusDeactivateWorkerMessage,
|
|
73
|
+
BusEndWorkerMessage,
|
|
74
|
+
BusCancelWorkerMessage,
|
|
75
|
+
];
|
|
76
|
+
/** Split `(...names, options?)` rest arguments. */
|
|
77
|
+
function splitTrailingOptions(args, isItem) {
|
|
78
|
+
const last = args[args.length - 1];
|
|
79
|
+
if (args.length > 0 && !isItem(last) && typeof last === "object" && last !== null) {
|
|
80
|
+
return [args.slice(0, -1), last];
|
|
81
|
+
}
|
|
82
|
+
return [args, {}];
|
|
83
|
+
}
|
|
84
|
+
function checkWorkerNames(worker, workerNames) {
|
|
85
|
+
for (const workerName of workerNames) {
|
|
86
|
+
if (typeof workerName !== "string") {
|
|
87
|
+
const typeName = workerName === null
|
|
88
|
+
? "NoneType"
|
|
89
|
+
: typeof workerName === "object"
|
|
90
|
+
? workerName.constructor.name
|
|
91
|
+
: typeof workerName;
|
|
92
|
+
throw new TypeError(`${worker} Expected worker name as str, got ${typeName}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Abstract base for workers in framework.
|
|
98
|
+
*
|
|
99
|
+
* A worker connects to a `WorkerBus`, registers itself in the shared
|
|
100
|
+
* registry, accepts activation/deactivation, and exchanges job
|
|
101
|
+
* requests/responses with other workers. Concrete subclasses
|
|
102
|
+
* (e.g. `PipelineWorker`) provide the runtime that actually drives
|
|
103
|
+
* the worker's work.
|
|
104
|
+
*
|
|
105
|
+
* Overridable lifecycle methods (always call `super`):
|
|
106
|
+
*
|
|
107
|
+
* - `onActivated(args)`: Called when this worker is activated.
|
|
108
|
+
* - `onDeactivated()`: Called when this worker is deactivated.
|
|
109
|
+
* - `onWorkerReady(data)`: Called when another worker is ready to receive
|
|
110
|
+
* messages. For local root workers, fires automatically. For children,
|
|
111
|
+
* fires only on the parent. For remote workers, fires only for workers
|
|
112
|
+
* watched via `watchWorkers()`.
|
|
113
|
+
* - `onJobRequest(message)`: Called when a job request is received.
|
|
114
|
+
* - `onJobResponse(message)`: Called when a worker sends a response.
|
|
115
|
+
* - `onJobUpdate(message)`: Called when a worker sends a progress update.
|
|
116
|
+
* - `onJobUpdateRequested(message)`: Called when the requester asks for a
|
|
117
|
+
* progress update.
|
|
118
|
+
* - `onJobCompleted(result)`: Called when all workers in a job group have
|
|
119
|
+
* responded.
|
|
120
|
+
* - `onJobError(message)`: Called when a worker errors and the group is
|
|
121
|
+
* cancelled (`cancelOnError`).
|
|
122
|
+
* - `onJobStreamStart(message)`: Called when a worker begins streaming.
|
|
123
|
+
* - `onJobStreamData(message)`: Called for each streaming chunk from a worker.
|
|
124
|
+
* - `onJobStreamEnd(message)`: Called when a worker finishes streaming.
|
|
125
|
+
* - `onJobCancelled(message)`: Called when this worker's job is cancelled by
|
|
126
|
+
* the requester.
|
|
127
|
+
* - `onBusMessage(message)`: Called for bus messages after default lifecycle
|
|
128
|
+
* handling.
|
|
129
|
+
*
|
|
130
|
+
* Event handlers available:
|
|
131
|
+
*
|
|
132
|
+
* - on_activated: Worker was activated.
|
|
133
|
+
* - on_deactivated: Worker was deactivated.
|
|
134
|
+
* - on_worker_ready: Another worker is ready.
|
|
135
|
+
* - on_worker_failed: A child worker reported an error.
|
|
136
|
+
* - on_job_request: Received a job request.
|
|
137
|
+
* - on_job_response: A worker sent a response.
|
|
138
|
+
* - on_job_update: A worker sent a progress update.
|
|
139
|
+
* - on_job_update_requested: Requester asked for a progress update.
|
|
140
|
+
* - on_job_completed: All workers in a job group responded.
|
|
141
|
+
* - on_job_error: A worker errored and the group was cancelled.
|
|
142
|
+
* - on_job_stream_start: A worker started streaming.
|
|
143
|
+
* - on_job_stream_data: A worker sent a streaming chunk.
|
|
144
|
+
* - on_job_stream_end: A worker finished streaming.
|
|
145
|
+
* - on_job_cancelled: This worker's job was cancelled.
|
|
146
|
+
* - on_bus_message: A bus message was received.
|
|
147
|
+
*/
|
|
148
|
+
export class BaseWorker extends BusSubscriber(BaseObject) {
|
|
149
|
+
// Only the owner of a task manager reports its dangling tasks. A worker
|
|
150
|
+
// that's handed its own task manager owns it; one that falls back to the
|
|
151
|
+
// runner's shared task manager does not (the runner reports instead).
|
|
152
|
+
_checkDanglingTasks;
|
|
153
|
+
_ownsTaskManager;
|
|
154
|
+
// Runner-provided context. Populated by `attach()` before `run()` is
|
|
155
|
+
// called. Accessing `this.bus` / `this.registry` before `attach()` throws.
|
|
156
|
+
_bus = null;
|
|
157
|
+
_registry = null;
|
|
158
|
+
_workerRunner = null;
|
|
159
|
+
// Activation. Pending activation is deferred until the worker starts, then
|
|
160
|
+
// onActivated fires.
|
|
161
|
+
_active;
|
|
162
|
+
_pendingActivation;
|
|
163
|
+
_activationArgs = null;
|
|
164
|
+
// Worker lifecycle. Parent/children form a tree. Finished is set when the
|
|
165
|
+
// worker stops.
|
|
166
|
+
_parent = null;
|
|
167
|
+
_children = [];
|
|
168
|
+
_startedAt = null;
|
|
169
|
+
_finishedEvent = new Event();
|
|
170
|
+
// Job coordination. Worker state tracks active job requests keyed by
|
|
171
|
+
// jobId, supporting multiple jobs in flight (e.g. parallel job handlers).
|
|
172
|
+
// Each running handler has a tracked task so it can be cancelled by system
|
|
173
|
+
// messages. Requester state tracks job groups launched by this worker. Job
|
|
174
|
+
// handlers are collected from `job()` decorated methods at init.
|
|
175
|
+
_activeJobs = new Map();
|
|
176
|
+
_jobHandlerTasks = new Map();
|
|
177
|
+
_jobGroups = new Map();
|
|
178
|
+
_jobHandlers;
|
|
179
|
+
_jobLocks = new Map();
|
|
180
|
+
// Worker-ready handlers collected from `workerReady()` decorated methods.
|
|
181
|
+
_workerReadyHandlers;
|
|
182
|
+
// A stable handler for registry watches (the registry ignores a handler it
|
|
183
|
+
// already holds, as Python's bound-method equality does).
|
|
184
|
+
_onWatchedWorkerReadyHandler = (data) => this._onWatchedWorkerReady(data);
|
|
185
|
+
/** Initialize the BaseWorker. */
|
|
186
|
+
constructor(options = {}) {
|
|
187
|
+
super(options);
|
|
188
|
+
this._checkDanglingTasks = options.checkDanglingTasks ?? true;
|
|
189
|
+
this._ownsTaskManager = options.taskManager !== undefined && options.taskManager !== null;
|
|
190
|
+
this._active = options.active ?? true;
|
|
191
|
+
this._pendingActivation = this._active;
|
|
192
|
+
this._jobHandlers = _collectJobHandlers(this);
|
|
193
|
+
this._workerReadyHandlers = _collectWorkerReadyHandlers(this);
|
|
194
|
+
// Worker lifecycle events
|
|
195
|
+
this._registerEventHandler("on_activated");
|
|
196
|
+
this._registerEventHandler("on_deactivated");
|
|
197
|
+
this._registerEventHandler("on_bus_message");
|
|
198
|
+
this._registerEventHandler("on_job_request");
|
|
199
|
+
this._registerEventHandler("on_job_response");
|
|
200
|
+
this._registerEventHandler("on_job_update");
|
|
201
|
+
this._registerEventHandler("on_job_update_requested");
|
|
202
|
+
this._registerEventHandler("on_job_completed");
|
|
203
|
+
this._registerEventHandler("on_job_error");
|
|
204
|
+
this._registerEventHandler("on_job_stream_start");
|
|
205
|
+
this._registerEventHandler("on_job_stream_data");
|
|
206
|
+
this._registerEventHandler("on_job_stream_end");
|
|
207
|
+
this._registerEventHandler("on_job_cancelled");
|
|
208
|
+
// Other workers
|
|
209
|
+
this._registerEventHandler("on_worker_ready");
|
|
210
|
+
this._registerEventHandler("on_worker_failed");
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* The bus this worker is attached to.
|
|
214
|
+
*
|
|
215
|
+
* @throws Error If accessed before `attach()` has been called.
|
|
216
|
+
*/
|
|
217
|
+
get bus() {
|
|
218
|
+
if (this._bus === null) {
|
|
219
|
+
throw new Error(`Worker '${this}': bus is not set; call attach() first.`);
|
|
220
|
+
}
|
|
221
|
+
return this._bus;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Whether this worker is accepting bus messages.
|
|
225
|
+
*
|
|
226
|
+
* An active worker takes everything addressed to it. An inactive one takes
|
|
227
|
+
* only activation, deactivation, end or cancel messages, so no job request,
|
|
228
|
+
* frame or UI event reaches it and none of its `onBusMessage` handling runs.
|
|
229
|
+
*
|
|
230
|
+
* It matters mainly in multi-worker setups, where a worker is put out of
|
|
231
|
+
* the way while the others carry on.
|
|
232
|
+
*
|
|
233
|
+
* Registry watches sit outside this: `workerReady` handlers fire from
|
|
234
|
+
* `WorkerRegistry` whatever this returns, because they never travel over
|
|
235
|
+
* the bus.
|
|
236
|
+
*/
|
|
237
|
+
get active() {
|
|
238
|
+
return this._active;
|
|
239
|
+
}
|
|
240
|
+
/** The arguments from the most recent activation, or null if inactive. */
|
|
241
|
+
get activationArgs() {
|
|
242
|
+
return this._activationArgs;
|
|
243
|
+
}
|
|
244
|
+
/** The name of the parent worker, or null if this is a root worker. */
|
|
245
|
+
get parent() {
|
|
246
|
+
return this._parent;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* The shared worker registry this worker is attached to.
|
|
250
|
+
*
|
|
251
|
+
* @throws Error If accessed before `attach()` has been called.
|
|
252
|
+
*/
|
|
253
|
+
get registry() {
|
|
254
|
+
if (this._registry === null) {
|
|
255
|
+
throw new Error(`Worker '${this}': registry is not set; call attach() first.`);
|
|
256
|
+
}
|
|
257
|
+
return this._registry;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* The runner this worker is attached to.
|
|
261
|
+
*
|
|
262
|
+
* Use it to reach another worker on the same runner by name, e.g.
|
|
263
|
+
* `this.workerRunner.getWorker("ui-jobs")`.
|
|
264
|
+
*
|
|
265
|
+
* @throws Error If accessed before `attach()` has been called.
|
|
266
|
+
*/
|
|
267
|
+
get workerRunner() {
|
|
268
|
+
if (this._workerRunner === null) {
|
|
269
|
+
throw new Error(`Worker '${this}': runner is not set; call attach() first.`);
|
|
270
|
+
}
|
|
271
|
+
return this._workerRunner;
|
|
272
|
+
}
|
|
273
|
+
/** Unix timestamp (seconds) when this worker became ready, or null if not yet started. */
|
|
274
|
+
get startedAt() {
|
|
275
|
+
return this._startedAt;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Whether this worker is bridged onto the bus.
|
|
279
|
+
*
|
|
280
|
+
* Subclasses (e.g. `PipelineWorker`) override when they auto-wrap their
|
|
281
|
+
* pipeline with bus edge processors.
|
|
282
|
+
*/
|
|
283
|
+
get bridged() {
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
/** The list of child workers added via `addWorkers()`. */
|
|
287
|
+
get children() {
|
|
288
|
+
return this._children;
|
|
289
|
+
}
|
|
290
|
+
/** Active job requests this worker is currently working on, keyed by jobId. */
|
|
291
|
+
get activeJobs() {
|
|
292
|
+
return this._activeJobs;
|
|
293
|
+
}
|
|
294
|
+
/** Active job groups launched by this worker, keyed by jobId. */
|
|
295
|
+
get jobGroups() {
|
|
296
|
+
return this._jobGroups;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Attach the worker to a runner-provided registry and bus.
|
|
300
|
+
*
|
|
301
|
+
* Called by the runner (typically from `addWorkers()`) before the worker
|
|
302
|
+
* is run. After this call, `registry` and `bus` return the provided
|
|
303
|
+
* instances, and the worker is subscribed to the bus — so workers added
|
|
304
|
+
* later are listening before any worker emits its first message.
|
|
305
|
+
*/
|
|
306
|
+
async attach(options) {
|
|
307
|
+
this._registry = options.registry;
|
|
308
|
+
this._bus = options.bus;
|
|
309
|
+
this._workerRunner = options.workerRunner;
|
|
310
|
+
await this._bus.subscribe(this);
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Clean up the worker and release resources.
|
|
314
|
+
*
|
|
315
|
+
* Cancels running jobs, unsubscribes from the bus, and signals that the
|
|
316
|
+
* worker has stopped.
|
|
317
|
+
*/
|
|
318
|
+
async cleanup() {
|
|
319
|
+
await super.cleanup();
|
|
320
|
+
await this.stop();
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Run this worker until it finishes.
|
|
324
|
+
*
|
|
325
|
+
* The default implementation is for bus-only workers: it subscribes to the
|
|
326
|
+
* bus, marks the worker as started, then waits until `stop()` (or
|
|
327
|
+
* `_finishedEvent`) is signalled. Subclasses with their own runtime (e.g.
|
|
328
|
+
* `PipelineWorker`) override this method.
|
|
329
|
+
*
|
|
330
|
+
* @param params Configuration parameters for worker execution.
|
|
331
|
+
*/
|
|
332
|
+
async run(params) {
|
|
333
|
+
await super.setup(this._taskManager ?? params.taskManager);
|
|
334
|
+
await this.start();
|
|
335
|
+
try {
|
|
336
|
+
await this._finishedEvent.wait();
|
|
337
|
+
}
|
|
338
|
+
catch (e) {
|
|
339
|
+
if (!(e instanceof CancelledError))
|
|
340
|
+
throw e;
|
|
341
|
+
}
|
|
342
|
+
finally {
|
|
343
|
+
await this.stop();
|
|
344
|
+
this._printDanglingTasks();
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
/** Mark the worker as started, register, and activate if requested. */
|
|
348
|
+
async start() {
|
|
349
|
+
this._startedAt = time();
|
|
350
|
+
await this._registerReady();
|
|
351
|
+
await this._maybeActivate();
|
|
352
|
+
await this._watchDecoratedWorkers();
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Clean up and signal that this worker has stopped.
|
|
356
|
+
*
|
|
357
|
+
* Cancels all running job groups and reports any still-active job
|
|
358
|
+
* requests back to their requesters as `CANCELLED`, so parents aren't left
|
|
359
|
+
* waiting, and cancels the handlers still running for them, such as one
|
|
360
|
+
* holding a long-lived job open.
|
|
361
|
+
*/
|
|
362
|
+
async stop() {
|
|
363
|
+
for (const jobId of [...this._jobGroups.keys()]) {
|
|
364
|
+
await this.cancelJobGroup(jobId, { reason: `worker '${this}' stopped` });
|
|
365
|
+
}
|
|
366
|
+
for (const jobId of [...this._activeJobs.keys()]) {
|
|
367
|
+
await this.sendJobResponse(jobId, null, { status: JobStatus.CANCELLED });
|
|
368
|
+
}
|
|
369
|
+
// Cancel every handler still running, including any that may have
|
|
370
|
+
// already responded (so are no longer in `_activeJobs`) but live on for
|
|
371
|
+
// some reason.
|
|
372
|
+
for (const task of [...this._jobHandlerTasks.values()]) {
|
|
373
|
+
await this.cancelTask(task);
|
|
374
|
+
}
|
|
375
|
+
this._finishedEvent.set();
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Request a graceful end of the session.
|
|
379
|
+
*
|
|
380
|
+
* @param options.reason Optional human-readable reason for ending.
|
|
381
|
+
*/
|
|
382
|
+
async end(options = {}) {
|
|
383
|
+
await this.sendBusMessage(new BusEndMessage({ source: this.name, reason: options.reason }));
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Request an immediate cancellation of all workers.
|
|
387
|
+
*
|
|
388
|
+
* @param options.reason Optional human-readable reason. Propagated through
|
|
389
|
+
* the runner to every root worker's `BusCancelWorkerMessage`.
|
|
390
|
+
*/
|
|
391
|
+
async cancel(options = {}) {
|
|
392
|
+
await this.sendBusMessage(new BusCancelMessage({ source: this.name, reason: options.reason }));
|
|
393
|
+
}
|
|
394
|
+
/** Wait for this worker to finish. */
|
|
395
|
+
async wait() {
|
|
396
|
+
await this._finishedEvent.wait();
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Called when this worker is activated.
|
|
400
|
+
*
|
|
401
|
+
* Override in subclasses to react to activation. Always call
|
|
402
|
+
* `super.onActivated(args)`.
|
|
403
|
+
*
|
|
404
|
+
* @param args Optional arguments from the caller.
|
|
405
|
+
*/
|
|
406
|
+
async onActivated(_args) { }
|
|
407
|
+
/**
|
|
408
|
+
* Called when this worker is deactivated.
|
|
409
|
+
*
|
|
410
|
+
* Override in subclasses to react to deactivation. Always call
|
|
411
|
+
* `super.onDeactivated()`.
|
|
412
|
+
*/
|
|
413
|
+
async onDeactivated() { }
|
|
414
|
+
/**
|
|
415
|
+
* Called when another worker is ready to receive messages.
|
|
416
|
+
*
|
|
417
|
+
* For local root workers this fires automatically. For remote workers it
|
|
418
|
+
* fires only for workers watched via `watchWorkers()`. For child workers
|
|
419
|
+
* it fires only on the parent that created them.
|
|
420
|
+
*
|
|
421
|
+
* @param data Information about the ready worker.
|
|
422
|
+
*/
|
|
423
|
+
async onWorkerReady(_data) { }
|
|
424
|
+
/**
|
|
425
|
+
* Called when a child worker reports an error.
|
|
426
|
+
*
|
|
427
|
+
* @param data Information about the error.
|
|
428
|
+
*/
|
|
429
|
+
async onWorkerFailed(_data) { }
|
|
430
|
+
/**
|
|
431
|
+
* Take bus messages only while active.
|
|
432
|
+
*
|
|
433
|
+
* An inactive worker is handed only activation, deactivation, end or
|
|
434
|
+
* cancel messages. Work addressed to it, and everything it would merely
|
|
435
|
+
* observe, is dropped by the bus rather than reaching `onBusMessage`.
|
|
436
|
+
*
|
|
437
|
+
* Registry notifications are unaffected, since `workerReady` watches fire
|
|
438
|
+
* from `WorkerRegistry` rather than travelling over the bus.
|
|
439
|
+
*
|
|
440
|
+
* @param message The bus message about to be delivered.
|
|
441
|
+
* @returns Whether to deliver the message.
|
|
442
|
+
*/
|
|
443
|
+
acceptsBusMessage(message) {
|
|
444
|
+
return this._active || ALWAYS_DELIVERED.some((cls) => message instanceof cls);
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Called for every bus message after built-in lifecycle handling.
|
|
448
|
+
*
|
|
449
|
+
* Override to handle custom message types. Built-in message types
|
|
450
|
+
* (activation, end, cancel, job) are already dispatched to their
|
|
451
|
+
* respective hooks before this method is called.
|
|
452
|
+
*
|
|
453
|
+
* @param message The `BusMessage` to process.
|
|
454
|
+
*/
|
|
455
|
+
async onBusMessage(message) {
|
|
456
|
+
// Frame messages are not handled by the base worker.
|
|
457
|
+
if (message instanceof BusFrameMessage) {
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
// Ignore targeted messages for other workers
|
|
461
|
+
if (message.target && message.target !== this.name) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
if (message instanceof BusWorkerErrorMessage || message instanceof BusWorkerLocalErrorMessage) {
|
|
465
|
+
await this._handleWorkerError(message);
|
|
466
|
+
}
|
|
467
|
+
else if (message instanceof BusActivateWorkerMessage) {
|
|
468
|
+
await this._handleWorkerActivate(message);
|
|
469
|
+
}
|
|
470
|
+
else if (message instanceof BusDeactivateWorkerMessage) {
|
|
471
|
+
await this._handleWorkerDeactivate(message);
|
|
472
|
+
}
|
|
473
|
+
else if (message instanceof BusEndWorkerMessage) {
|
|
474
|
+
await this._handleWorkerEnd(message);
|
|
475
|
+
}
|
|
476
|
+
else if (message instanceof BusCancelWorkerMessage) {
|
|
477
|
+
await this._handleWorkerCancel(message);
|
|
478
|
+
}
|
|
479
|
+
else if (message instanceof BusJobRequestMessage) {
|
|
480
|
+
await this._handleJobRequest(message);
|
|
481
|
+
}
|
|
482
|
+
else if (message instanceof BusJobResponseMessage ||
|
|
483
|
+
message instanceof BusJobResponseUrgentMessage) {
|
|
484
|
+
await this._handleJobResponse(message);
|
|
485
|
+
}
|
|
486
|
+
else if (message instanceof BusJobUpdateMessage ||
|
|
487
|
+
message instanceof BusJobUpdateUrgentMessage) {
|
|
488
|
+
await this._handleJobUpdate(message);
|
|
489
|
+
}
|
|
490
|
+
else if (message instanceof BusJobUpdateRequestMessage) {
|
|
491
|
+
await this._handleJobUpdateRequest(message);
|
|
492
|
+
}
|
|
493
|
+
else if (message instanceof BusJobCancelMessage) {
|
|
494
|
+
await this._handleJobCancel(message);
|
|
495
|
+
}
|
|
496
|
+
else if (message instanceof BusJobStreamStartMessage) {
|
|
497
|
+
await this._handleJobStreamStart(message);
|
|
498
|
+
}
|
|
499
|
+
else if (message instanceof BusJobStreamDataMessage) {
|
|
500
|
+
await this._handleJobStreamData(message);
|
|
501
|
+
}
|
|
502
|
+
else if (message instanceof BusJobStreamEndMessage) {
|
|
503
|
+
await this._handleJobStreamEnd(message);
|
|
504
|
+
}
|
|
505
|
+
await this._callEventHandler("on_bus_message", message);
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Called when this worker receives a job request.
|
|
509
|
+
*
|
|
510
|
+
* Override to perform work. Use `sendJobUpdate()` to report progress and
|
|
511
|
+
* `sendJobResponse()` to return results.
|
|
512
|
+
*/
|
|
513
|
+
async onJobRequest(_message) { }
|
|
514
|
+
/**
|
|
515
|
+
* Called when a worker sends a response.
|
|
516
|
+
*
|
|
517
|
+
* Override to process individual results as they arrive.
|
|
518
|
+
*/
|
|
519
|
+
async onJobResponse(_message) { }
|
|
520
|
+
/** Called when a worker sends a progress update. */
|
|
521
|
+
async onJobUpdate(_message) { }
|
|
522
|
+
/**
|
|
523
|
+
* Called when the requester asks for a progress update.
|
|
524
|
+
*
|
|
525
|
+
* Override to send back a progress update via `sendJobUpdate()`.
|
|
526
|
+
*/
|
|
527
|
+
async onJobUpdateRequested(_message) { }
|
|
528
|
+
/** Called when all workers in a job group have responded. */
|
|
529
|
+
async onJobCompleted(_result) { }
|
|
530
|
+
/**
|
|
531
|
+
* Called when a job group is cancelled due to a worker error.
|
|
532
|
+
*
|
|
533
|
+
* Fires when a worker responds with `ERROR` or `FAILED` status and
|
|
534
|
+
* `cancelOnError` is set. The group is cancelled and `onJobCompleted`
|
|
535
|
+
* will not fire. Partial responses from workers that completed before the
|
|
536
|
+
* error are available in the job group's `responses`.
|
|
537
|
+
*/
|
|
538
|
+
async onJobError(_message) { }
|
|
539
|
+
/** Called when a worker begins streaming. */
|
|
540
|
+
async onJobStreamStart(_message) { }
|
|
541
|
+
/** Called for each streaming chunk from a worker. */
|
|
542
|
+
async onJobStreamData(_message) { }
|
|
543
|
+
/** Called when a worker finishes streaming. */
|
|
544
|
+
async onJobStreamEnd(_message) { }
|
|
545
|
+
/**
|
|
546
|
+
* Called when this worker's job is cancelled by the requester.
|
|
547
|
+
*
|
|
548
|
+
* Override to clean up resources or stop in-progress work.
|
|
549
|
+
*/
|
|
550
|
+
async onJobCancelled(_message) { }
|
|
551
|
+
/**
|
|
552
|
+
* Send a message on the bus.
|
|
553
|
+
*
|
|
554
|
+
* @param message The `BusMessage` to send.
|
|
555
|
+
*/
|
|
556
|
+
async sendBusMessage(message) {
|
|
557
|
+
if (this._bus) {
|
|
558
|
+
await this._bus.send(message);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Report an error on the bus.
|
|
563
|
+
*
|
|
564
|
+
* Child workers send a local-only message to the parent. Root workers
|
|
565
|
+
* broadcast over the network.
|
|
566
|
+
*
|
|
567
|
+
* @param error Description of the error.
|
|
568
|
+
*/
|
|
569
|
+
async sendBusErrorMessage(error) {
|
|
570
|
+
if (this._parent) {
|
|
571
|
+
await this.sendBusMessage(new BusWorkerLocalErrorMessage({ source: this.name, error }));
|
|
572
|
+
}
|
|
573
|
+
else {
|
|
574
|
+
await this.sendBusMessage(new BusWorkerErrorMessage({ source: this.name, error }));
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
async addWorkers(...args) {
|
|
578
|
+
const [workers, options] = splitTrailingOptions(args, (v) => v instanceof BaseWorker);
|
|
579
|
+
const watch = options.watch ?? true;
|
|
580
|
+
const addedNames = [];
|
|
581
|
+
for (const worker of workers) {
|
|
582
|
+
if (worker._parent !== null) {
|
|
583
|
+
logger.warning(`Worker '${worker.name}' already has parent '${worker._parent}', skipping`);
|
|
584
|
+
continue;
|
|
585
|
+
}
|
|
586
|
+
worker._parent = this.name;
|
|
587
|
+
this._children.push(worker);
|
|
588
|
+
addedNames.push(worker.name);
|
|
589
|
+
await this.sendBusMessage(new BusAddWorkerMessage({ source: this.name, worker }));
|
|
590
|
+
}
|
|
591
|
+
if (watch && addedNames.length > 0) {
|
|
592
|
+
await this.watchWorkers(...addedNames);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Activate a worker by name.
|
|
597
|
+
*
|
|
598
|
+
* The target worker's `onActivated` hook will be called with the provided
|
|
599
|
+
* arguments. The target need not be active already: an activation reaches
|
|
600
|
+
* an inactive worker, which is what lets it become active.
|
|
601
|
+
*
|
|
602
|
+
* @param workerName The name of the worker to activate.
|
|
603
|
+
* @param options.args Optional `WorkerActivationArgs` forwarded to the
|
|
604
|
+
* target worker's `onActivated`.
|
|
605
|
+
* @param options.deactivateSelf Whether to deactivate this worker before
|
|
606
|
+
* activating the target.
|
|
607
|
+
*/
|
|
608
|
+
async activateWorker(workerName, options = {}) {
|
|
609
|
+
const args = options.args ?? null;
|
|
610
|
+
const deactivateSelf = options.deactivateSelf ?? false;
|
|
611
|
+
if (this._active && deactivateSelf) {
|
|
612
|
+
// Deactivate immediately (don't wait for the bus round-trip) so this
|
|
613
|
+
// worker and the target are never briefly active at the same time.
|
|
614
|
+
this._active = false;
|
|
615
|
+
await this.deactivateWorker(this.name);
|
|
616
|
+
}
|
|
617
|
+
await this.sendBusMessage(new BusActivateWorkerMessage({
|
|
618
|
+
source: this.name,
|
|
619
|
+
target: workerName,
|
|
620
|
+
args: args ? args.toDict() : null,
|
|
621
|
+
}));
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Deactivate a worker by name.
|
|
625
|
+
*
|
|
626
|
+
* The target worker's `onDeactivated` hook will be called.
|
|
627
|
+
*
|
|
628
|
+
* @param workerName The name of the worker to deactivate.
|
|
629
|
+
*/
|
|
630
|
+
async deactivateWorker(workerName) {
|
|
631
|
+
await this.sendBusMessage(new BusDeactivateWorkerMessage({ source: this.name, target: workerName }));
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Request notification when one or more workers register.
|
|
635
|
+
*
|
|
636
|
+
* For each name: if the worker is already registered, `onWorkerReady`
|
|
637
|
+
* fires immediately. Otherwise `onWorkerReady` fires when the worker
|
|
638
|
+
* eventually registers.
|
|
639
|
+
*
|
|
640
|
+
* @param workerNames Names of workers to watch for.
|
|
641
|
+
*/
|
|
642
|
+
async watchWorkers(...workerNames) {
|
|
643
|
+
if (!this._registry) {
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
for (const workerName of workerNames) {
|
|
647
|
+
logger.debug(`Worker '${this}': watching for worker '${workerName}'`);
|
|
648
|
+
await this._registry.watch(workerName, this._onWatchedWorkerReadyHandler);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Send a job request to a single worker (fire-and-forget).
|
|
653
|
+
*
|
|
654
|
+
* Waits for the worker to be ready before sending the request. Does not
|
|
655
|
+
* wait for the job to complete; use callbacks (`onJobResponse`,
|
|
656
|
+
* `onJobCompleted`) or `job()` for that.
|
|
657
|
+
*
|
|
658
|
+
* @param workerName Name of the worker to send the job to.
|
|
659
|
+
* @param options.params How to run the job. See `JobParams`.
|
|
660
|
+
* @returns The generated jobId.
|
|
661
|
+
*/
|
|
662
|
+
async requestJob(workerName, options = {}) {
|
|
663
|
+
const jobParams = options.params ?? new JobParams();
|
|
664
|
+
const group = await this.createJobGroupAndRequestJob([workerName], {
|
|
665
|
+
params: new JobGroupParams({
|
|
666
|
+
name: jobParams.name,
|
|
667
|
+
payload: jobParams.payload,
|
|
668
|
+
timeout: jobParams.timeout,
|
|
669
|
+
label: jobParams.label,
|
|
670
|
+
cancellable: jobParams.cancellable,
|
|
671
|
+
}),
|
|
672
|
+
});
|
|
673
|
+
return group.jobId;
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Create a single-worker job context.
|
|
677
|
+
*
|
|
678
|
+
* Waits for the worker to be ready, sends a job request, and waits for the
|
|
679
|
+
* response on exit. Supports `for await` inside the block to receive
|
|
680
|
+
* intermediate events (updates and streaming data) from the worker while
|
|
681
|
+
* waiting.
|
|
682
|
+
*
|
|
683
|
+
* On normal completion, the result is available via `response`. On worker
|
|
684
|
+
* error or timeout, throws `JobError`.
|
|
685
|
+
*
|
|
686
|
+
* @param workerName Name of the worker to send the job to.
|
|
687
|
+
* @param options.params How to run the job. See `JobParams`.
|
|
688
|
+
* @returns A `JobContext` (Python's `async with` → `await ctx.run(...)`).
|
|
689
|
+
*
|
|
690
|
+
* @example
|
|
691
|
+
* const t = this.job("worker", { params: new JobParams({ payload: data }) });
|
|
692
|
+
* await t.run(async (t) => {
|
|
693
|
+
* for await (const event of t) {
|
|
694
|
+
* if (event.type === JobEvent.UPDATE) console.log(event.data);
|
|
695
|
+
* }
|
|
696
|
+
* });
|
|
697
|
+
* console.log(t.response);
|
|
698
|
+
*/
|
|
699
|
+
job(workerName, options = {}) {
|
|
700
|
+
return new JobContext(this, workerName, { params: options.params ?? new JobParams() });
|
|
701
|
+
}
|
|
702
|
+
async requestJobGroup(...args) {
|
|
703
|
+
const [workerNames, options] = splitTrailingOptions(args, (v) => typeof v === "string");
|
|
704
|
+
checkWorkerNames(this, workerNames);
|
|
705
|
+
const groupParams = options.params ?? new JobGroupParams();
|
|
706
|
+
const group = await this.createJobGroupAndRequestJob([...workerNames], {
|
|
707
|
+
params: groupParams,
|
|
708
|
+
});
|
|
709
|
+
return group.jobId;
|
|
710
|
+
}
|
|
711
|
+
jobGroup(...args) {
|
|
712
|
+
const [workerNames, options] = splitTrailingOptions(args, (v) => typeof v === "string");
|
|
713
|
+
checkWorkerNames(this, workerNames);
|
|
714
|
+
const groupParams = options.params ?? new JobGroupParams();
|
|
715
|
+
return new JobGroupContext(this, workerNames, { params: groupParams });
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Cancel a running job group.
|
|
719
|
+
*
|
|
720
|
+
* @param jobId The job identifier to cancel.
|
|
721
|
+
* @param options.reason Optional human-readable reason for cancellation.
|
|
722
|
+
*/
|
|
723
|
+
async cancelJobGroup(jobId, options = {}) {
|
|
724
|
+
const reason = options.reason ?? null;
|
|
725
|
+
const group = this._jobGroups.get(jobId);
|
|
726
|
+
this._jobGroups.delete(jobId);
|
|
727
|
+
if (group) {
|
|
728
|
+
// On the timeout path this runs on the timeout task itself, which is
|
|
729
|
+
// already on its last statement. Cancelling it here would abandon the
|
|
730
|
+
// rest of this method, leaving the group's waiter blocked forever.
|
|
731
|
+
if (group.timeoutTask && group.timeoutTask !== currentTask()) {
|
|
732
|
+
await this.cancelTask(group.timeoutTask);
|
|
733
|
+
}
|
|
734
|
+
for (const workerName of group.workerNames) {
|
|
735
|
+
await this.sendBusMessage(new BusJobCancelMessage({ source: this.name, target: workerName, jobId, reason }));
|
|
736
|
+
}
|
|
737
|
+
group.fail(reason);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Honor an externally requested cancellation, if the group allows it.
|
|
742
|
+
*
|
|
743
|
+
* The door for cancellation asked for from outside the worker, by a client
|
|
744
|
+
* UI or an operator endpoint, which `JobGroupParams.cancellable` governs.
|
|
745
|
+
* Cancellation the worker decides on itself (shutdown, a timeout,
|
|
746
|
+
* `cancelOnError`) goes straight to `cancelJobGroup()` and is never
|
|
747
|
+
* refused.
|
|
748
|
+
*
|
|
749
|
+
* @param jobId The job identifier to cancel.
|
|
750
|
+
* @param options.reason Optional human-readable reason for cancellation.
|
|
751
|
+
* @returns Whether the group was cancelled. False means it is unknown or
|
|
752
|
+
* was dispatched as non-cancellable.
|
|
753
|
+
*/
|
|
754
|
+
async requestCancelJobGroup(jobId, options = {}) {
|
|
755
|
+
const group = this._jobGroups.get(jobId);
|
|
756
|
+
if (group === undefined || !group.cancellable) {
|
|
757
|
+
return false;
|
|
758
|
+
}
|
|
759
|
+
await this.cancelJobGroup(jobId, { reason: options.reason ?? null });
|
|
760
|
+
return true;
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Request a progress update from a worker.
|
|
764
|
+
*
|
|
765
|
+
* @param jobId The job identifier.
|
|
766
|
+
* @param workerName The name of the worker to request an update from.
|
|
767
|
+
*/
|
|
768
|
+
async requestJobUpdate(jobId, workerName) {
|
|
769
|
+
await this.sendBusMessage(new BusJobUpdateRequestMessage({ source: this.name, target: workerName, jobId }));
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Wait for workers to be ready, create a job group, and send requests.
|
|
773
|
+
*
|
|
774
|
+
* Waits for all workers to be registered as ready, then creates the group
|
|
775
|
+
* and sends a job request to each worker. Does not wait for the group to
|
|
776
|
+
* complete; call `group.wait()` or use `jobGroup()` for that.
|
|
777
|
+
*
|
|
778
|
+
* @param workerNames Names of the workers to send the job to.
|
|
779
|
+
* @param options.params How to run the group. See `JobGroupParams`.
|
|
780
|
+
* @returns The created `JobGroup`.
|
|
781
|
+
* @throws JobGroupError If workers are not ready within the timeout.
|
|
782
|
+
*/
|
|
783
|
+
async createJobGroupAndRequestJob(workerNames, options = {}) {
|
|
784
|
+
const groupParams = options.params ?? new JobGroupParams();
|
|
785
|
+
const allReady = await this._waitWorkersReady(workerNames);
|
|
786
|
+
try {
|
|
787
|
+
await waitFor(allReady, groupParams.timeout);
|
|
788
|
+
}
|
|
789
|
+
catch (e) {
|
|
790
|
+
if (e instanceof TimeoutError) {
|
|
791
|
+
throw new JobGroupError("workers not ready within timeout");
|
|
792
|
+
}
|
|
793
|
+
throw e;
|
|
794
|
+
}
|
|
795
|
+
const group = this._createJobGroup(workerNames, { params: groupParams });
|
|
796
|
+
for (const workerName of workerNames) {
|
|
797
|
+
await this._sendJobRequest(workerName, group.jobId, {
|
|
798
|
+
jobName: groupParams.name,
|
|
799
|
+
payload: groupParams.payload,
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
return group;
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Send a job response back to the requester.
|
|
806
|
+
*
|
|
807
|
+
* After sending, the job is removed from the set of active jobs.
|
|
808
|
+
*
|
|
809
|
+
* @param jobId The identifier of the job being responded to.
|
|
810
|
+
* @param response Optional result data.
|
|
811
|
+
* @param options.status Completion status. Defaults to `JobStatus.COMPLETED`.
|
|
812
|
+
* @param options.urgent When true, the response is delivered with system
|
|
813
|
+
* priority, preempting queued data messages.
|
|
814
|
+
* @throws Error If there is no active job with this `jobId`.
|
|
815
|
+
*/
|
|
816
|
+
async sendJobResponse(jobId, response = null, options = {}) {
|
|
817
|
+
const status = options.status ?? JobStatus.COMPLETED;
|
|
818
|
+
const urgent = options.urgent ?? false;
|
|
819
|
+
const request = this._activeJobs.get(jobId);
|
|
820
|
+
if (request === undefined) {
|
|
821
|
+
throw new Error(`Worker '${this}': no active job '${jobId}' to respond to`);
|
|
822
|
+
}
|
|
823
|
+
const MsgClass = urgent ? BusJobResponseUrgentMessage : BusJobResponseMessage;
|
|
824
|
+
await this.sendBusMessage(new MsgClass({
|
|
825
|
+
source: this.name,
|
|
826
|
+
target: request.source,
|
|
827
|
+
jobId,
|
|
828
|
+
response,
|
|
829
|
+
status,
|
|
830
|
+
}));
|
|
831
|
+
this._activeJobs.delete(jobId);
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Send a progress update to the requester.
|
|
835
|
+
*
|
|
836
|
+
* @param jobId The identifier of the job being updated.
|
|
837
|
+
* @param update Optional progress data.
|
|
838
|
+
* @param options.urgent When true, the update is delivered with system
|
|
839
|
+
* priority, preempting queued data messages.
|
|
840
|
+
* @throws Error If there is no active job with this `jobId`.
|
|
841
|
+
*/
|
|
842
|
+
async sendJobUpdate(jobId, update = null, options = {}) {
|
|
843
|
+
const urgent = options.urgent ?? false;
|
|
844
|
+
const request = this._activeJobs.get(jobId);
|
|
845
|
+
if (request === undefined) {
|
|
846
|
+
throw new Error(`Worker '${this}': no active job '${jobId}' to update`);
|
|
847
|
+
}
|
|
848
|
+
const MsgClass = urgent ? BusJobUpdateUrgentMessage : BusJobUpdateMessage;
|
|
849
|
+
await this.sendBusMessage(new MsgClass({
|
|
850
|
+
source: this.name,
|
|
851
|
+
target: request.source,
|
|
852
|
+
jobId,
|
|
853
|
+
update,
|
|
854
|
+
}));
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Begin streaming job results back to the requester.
|
|
858
|
+
*
|
|
859
|
+
* @param jobId The identifier of the job being streamed.
|
|
860
|
+
* @param data Optional metadata about the stream.
|
|
861
|
+
* @throws Error If there is no active job with this `jobId`.
|
|
862
|
+
*/
|
|
863
|
+
async sendJobStreamStart(jobId, data = null) {
|
|
864
|
+
const request = this._activeJobs.get(jobId);
|
|
865
|
+
if (request === undefined) {
|
|
866
|
+
throw new Error(`Worker '${this}': no active job '${jobId}' to stream`);
|
|
867
|
+
}
|
|
868
|
+
await this.sendBusMessage(new BusJobStreamStartMessage({
|
|
869
|
+
source: this.name,
|
|
870
|
+
target: request.source,
|
|
871
|
+
jobId,
|
|
872
|
+
data,
|
|
873
|
+
}));
|
|
874
|
+
}
|
|
875
|
+
/**
|
|
876
|
+
* Send a streaming chunk to the requester.
|
|
877
|
+
*
|
|
878
|
+
* @param jobId The identifier of the job being streamed.
|
|
879
|
+
* @param data The chunk payload.
|
|
880
|
+
* @throws Error If there is no active job with this `jobId`.
|
|
881
|
+
*/
|
|
882
|
+
async sendJobStreamData(jobId, data = null) {
|
|
883
|
+
const request = this._activeJobs.get(jobId);
|
|
884
|
+
if (request === undefined) {
|
|
885
|
+
throw new Error(`Worker '${this}': no active job '${jobId}' to stream`);
|
|
886
|
+
}
|
|
887
|
+
await this.sendBusMessage(new BusJobStreamDataMessage({
|
|
888
|
+
source: this.name,
|
|
889
|
+
target: request.source,
|
|
890
|
+
jobId,
|
|
891
|
+
data,
|
|
892
|
+
}));
|
|
893
|
+
}
|
|
894
|
+
/**
|
|
895
|
+
* End the current stream and mark this worker's job as complete.
|
|
896
|
+
*
|
|
897
|
+
* After sending, the job is removed from the set of active jobs.
|
|
898
|
+
*
|
|
899
|
+
* @param jobId The identifier of the job being streamed.
|
|
900
|
+
* @param data Optional final metadata.
|
|
901
|
+
* @throws Error If there is no active job with this `jobId`.
|
|
902
|
+
*/
|
|
903
|
+
async sendJobStreamEnd(jobId, data = null) {
|
|
904
|
+
const request = this._activeJobs.get(jobId);
|
|
905
|
+
if (request === undefined) {
|
|
906
|
+
throw new Error(`Worker '${this}': no active job '${jobId}' to stream`);
|
|
907
|
+
}
|
|
908
|
+
await this.sendBusMessage(new BusJobStreamEndMessage({
|
|
909
|
+
source: this.name,
|
|
910
|
+
target: request.source,
|
|
911
|
+
jobId,
|
|
912
|
+
data,
|
|
913
|
+
}));
|
|
914
|
+
this._activeJobs.delete(jobId);
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
* Register this worker as ready in the shared registry.
|
|
918
|
+
*
|
|
919
|
+
* The registry notifies watchers (parent for children, runner for root
|
|
920
|
+
* workers).
|
|
921
|
+
*/
|
|
922
|
+
async _registerReady() {
|
|
923
|
+
if (this._registry) {
|
|
924
|
+
// Send the bus message before registering. Registration fires watchers
|
|
925
|
+
// synchronously, which may send additional messages (e.g.
|
|
926
|
+
// ActivateWorker). Sending the ready message first preserves correct
|
|
927
|
+
// chronological order for observers.
|
|
928
|
+
await this.sendBusMessage(new BusWorkerReadyMessage({
|
|
929
|
+
source: this.name,
|
|
930
|
+
runner: this._registry.runnerName,
|
|
931
|
+
parent: this._parent,
|
|
932
|
+
active: this._active,
|
|
933
|
+
bridged: this.bridged,
|
|
934
|
+
startedAt: this._startedAt,
|
|
935
|
+
}));
|
|
936
|
+
await this._registry.register(new WorkerReadyData({
|
|
937
|
+
workerName: this.name,
|
|
938
|
+
runner: this._registry.runnerName,
|
|
939
|
+
}));
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
/** Activate the worker, call onActivated, and fire event handlers. */
|
|
943
|
+
async _maybeActivate() {
|
|
944
|
+
if (this._startedAt !== null && this._pendingActivation) {
|
|
945
|
+
logger.debug(`Worker '${this}': activated`);
|
|
946
|
+
this._active = true;
|
|
947
|
+
this._pendingActivation = false;
|
|
948
|
+
await this.onActivated(this._activationArgs);
|
|
949
|
+
await this._callEventHandler("on_activated", this._activationArgs);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
/** Register watches for all `workerReady` decorated handlers. */
|
|
953
|
+
async _watchDecoratedWorkers() {
|
|
954
|
+
await this.watchWorkers(...this._workerReadyHandlers.keys());
|
|
955
|
+
}
|
|
956
|
+
/**
|
|
957
|
+
* Called when a watched worker is ready.
|
|
958
|
+
*
|
|
959
|
+
* Dispatches to the `workerReady` handler if one exists for this worker,
|
|
960
|
+
* otherwise proxies to `onWorkerReady`.
|
|
961
|
+
*/
|
|
962
|
+
async _onWatchedWorkerReady(data) {
|
|
963
|
+
logger.debug(`Worker '${this}': worker '${data.workerName}' ready`);
|
|
964
|
+
const handler = this._workerReadyHandlers.get(data.workerName);
|
|
965
|
+
if (handler) {
|
|
966
|
+
await handler(data);
|
|
967
|
+
}
|
|
968
|
+
await this.onWorkerReady(data);
|
|
969
|
+
await this._callEventHandler("on_worker_ready", data);
|
|
970
|
+
}
|
|
971
|
+
/** Handle an error reported by a child or remote worker. */
|
|
972
|
+
async _handleWorkerError(message) {
|
|
973
|
+
const childNames = new Set(this._children.map((child) => child.name));
|
|
974
|
+
if (childNames.has(message.source)) {
|
|
975
|
+
const errorInfo = new WorkerErrorData({ workerName: message.source, error: message.error });
|
|
976
|
+
await this.onWorkerFailed(errorInfo);
|
|
977
|
+
await this._callEventHandler("on_worker_failed", errorInfo);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
/**
|
|
981
|
+
* Handle an activation message.
|
|
982
|
+
*
|
|
983
|
+
* Stores the activation arguments and marks the worker as pending
|
|
984
|
+
* activation, then delegates to `_maybeActivate()`.
|
|
985
|
+
*
|
|
986
|
+
* @param message The `BusActivateWorkerMessage` requesting activation.
|
|
987
|
+
*/
|
|
988
|
+
async _handleWorkerActivate(message) {
|
|
989
|
+
this._activationArgs = message.args;
|
|
990
|
+
this._pendingActivation = true;
|
|
991
|
+
await this._maybeActivate();
|
|
992
|
+
}
|
|
993
|
+
/**
|
|
994
|
+
* Deactivate this worker.
|
|
995
|
+
*
|
|
996
|
+
* @param message The `BusDeactivateWorkerMessage` requesting deactivation.
|
|
997
|
+
*/
|
|
998
|
+
async _handleWorkerDeactivate(_message) {
|
|
999
|
+
logger.debug(`Worker '${this}': deactivated`);
|
|
1000
|
+
this._active = false;
|
|
1001
|
+
this._activationArgs = null;
|
|
1002
|
+
await this.onDeactivated();
|
|
1003
|
+
await this._callEventHandler("on_deactivated");
|
|
1004
|
+
}
|
|
1005
|
+
/**
|
|
1006
|
+
* Propagate end to children, wait for them, then stop this worker.
|
|
1007
|
+
*
|
|
1008
|
+
* Subclasses with their own runtime (e.g. `PipelineWorker`) call
|
|
1009
|
+
* `_propagateEndToChildren()` directly and drive their own shutdown so
|
|
1010
|
+
* `_finishedEvent` fires at the right moment.
|
|
1011
|
+
*
|
|
1012
|
+
* @param message The `BusEndWorkerMessage` requesting a graceful end.
|
|
1013
|
+
*/
|
|
1014
|
+
async _handleWorkerEnd(message) {
|
|
1015
|
+
logger.debug(`Worker '${this}': received end`);
|
|
1016
|
+
await this._propagateEndToChildren(message);
|
|
1017
|
+
await this.stop();
|
|
1018
|
+
}
|
|
1019
|
+
/**
|
|
1020
|
+
* Propagate cancel to children, then stop this worker.
|
|
1021
|
+
*
|
|
1022
|
+
* Subclasses with their own runtime (e.g. `PipelineWorker`) call
|
|
1023
|
+
* `_propagateCancelToChildren()` directly and drive their own shutdown so
|
|
1024
|
+
* `_finishedEvent` fires at the right moment.
|
|
1025
|
+
*
|
|
1026
|
+
* @param message The `BusCancelWorkerMessage` requesting cancellation.
|
|
1027
|
+
*/
|
|
1028
|
+
async _handleWorkerCancel(message) {
|
|
1029
|
+
logger.debug(`Worker '${this}': received cancel`);
|
|
1030
|
+
await this._propagateCancelToChildren(message);
|
|
1031
|
+
await this.stop();
|
|
1032
|
+
}
|
|
1033
|
+
/** Forward a `BusEndWorkerMessage` to each child and wait for them. */
|
|
1034
|
+
async _propagateEndToChildren(message) {
|
|
1035
|
+
for (const child of this._children) {
|
|
1036
|
+
await this.sendBusMessage(new BusEndWorkerMessage({ source: this.name, target: child.name, reason: message.reason }));
|
|
1037
|
+
}
|
|
1038
|
+
await gather(...this._children.map((child) => () => child.wait()));
|
|
1039
|
+
}
|
|
1040
|
+
/** Forward a `BusCancelWorkerMessage` to each child. */
|
|
1041
|
+
async _propagateCancelToChildren(message) {
|
|
1042
|
+
for (const child of this._children) {
|
|
1043
|
+
await this.sendBusMessage(new BusCancelWorkerMessage({
|
|
1044
|
+
source: this.name,
|
|
1045
|
+
target: child.name,
|
|
1046
|
+
reason: message.reason,
|
|
1047
|
+
}));
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
/**
|
|
1051
|
+
* Handle an incoming job request.
|
|
1052
|
+
*
|
|
1053
|
+
* Dispatches to `job()` handlers if any match, otherwise falls back to
|
|
1054
|
+
* onJobRequest. The handler always runs in its own task so the bus message
|
|
1055
|
+
* loop is never blocked. When the matched handler is marked
|
|
1056
|
+
* `sequential: true`, requests with the same job name are queued and run
|
|
1057
|
+
* one at a time in FIFO order.
|
|
1058
|
+
*/
|
|
1059
|
+
async _handleJobRequest(message) {
|
|
1060
|
+
this._activeJobs.set(message.jobId, message);
|
|
1061
|
+
let handler = message.jobName
|
|
1062
|
+
? this._jobHandlers.get(message.jobName)
|
|
1063
|
+
: undefined;
|
|
1064
|
+
if (handler === undefined) {
|
|
1065
|
+
handler = (m) => this.onJobRequest(m);
|
|
1066
|
+
}
|
|
1067
|
+
let lock = null;
|
|
1068
|
+
if (message.jobName && handler.jobSequential) {
|
|
1069
|
+
lock = this._jobLocks.get(message.jobName) ?? null;
|
|
1070
|
+
if (lock === null) {
|
|
1071
|
+
lock = new Lock();
|
|
1072
|
+
this._jobLocks.set(message.jobName, lock);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
const jobHandler = handler;
|
|
1076
|
+
const task = this.createTask(() => this._runJobHandler(message.jobId, jobHandler, message, lock), `${this.name}::job_${message.jobName || "default"}`);
|
|
1077
|
+
this._jobHandlerTasks.set(message.jobId, task);
|
|
1078
|
+
await this._callEventHandler("on_job_request", message);
|
|
1079
|
+
}
|
|
1080
|
+
async _runJobHandler(jobId, handler, message, lock = null) {
|
|
1081
|
+
try {
|
|
1082
|
+
if (lock !== null) {
|
|
1083
|
+
await lock.run(async () => {
|
|
1084
|
+
await handler(message);
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
else {
|
|
1088
|
+
await handler(message);
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
catch (e) {
|
|
1092
|
+
if (!(e instanceof CancelledError))
|
|
1093
|
+
throw e;
|
|
1094
|
+
}
|
|
1095
|
+
finally {
|
|
1096
|
+
this._jobHandlerTasks.delete(jobId);
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
/** Handle a job response and track group completion. */
|
|
1100
|
+
async _handleJobResponse(message) {
|
|
1101
|
+
this._markWorkerTerminated(message.jobId, message.source);
|
|
1102
|
+
await this.onJobResponse(message);
|
|
1103
|
+
await this._callEventHandler("on_job_response", message);
|
|
1104
|
+
// Auto-cancel the group on error/failed if cancelOnError is set
|
|
1105
|
+
if (message.status === JobStatus.ERROR || message.status === JobStatus.FAILED) {
|
|
1106
|
+
const group = this._jobGroups.get(message.jobId);
|
|
1107
|
+
if (group?.cancelOnError) {
|
|
1108
|
+
group.responses[message.source] = message.response ?? {};
|
|
1109
|
+
await this.onJobError(message);
|
|
1110
|
+
await this._callEventHandler("on_job_error", message);
|
|
1111
|
+
await this.cancelJobGroup(message.jobId, {
|
|
1112
|
+
reason: `worker '${message.source}' errored`,
|
|
1113
|
+
});
|
|
1114
|
+
return;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
await this._trackJobGroupResponse(message.jobId, message.source, message.response);
|
|
1118
|
+
}
|
|
1119
|
+
/**
|
|
1120
|
+
* Record that a worker of a group has reached a terminal state.
|
|
1121
|
+
*
|
|
1122
|
+
* A worker terminates either by responding or by ending its stream.
|
|
1123
|
+
* `cancelJobGroup` reads this to tell apart the workers a cancellation
|
|
1124
|
+
* actually cut short from those that had already finished on their own.
|
|
1125
|
+
*/
|
|
1126
|
+
_markWorkerTerminated(jobId, workerName) {
|
|
1127
|
+
const group = this._jobGroups.get(jobId);
|
|
1128
|
+
if (group) {
|
|
1129
|
+
group.terminated.add(workerName);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
/** Handle a job progress update. */
|
|
1133
|
+
async _handleJobUpdate(message) {
|
|
1134
|
+
await this.onJobUpdate(message);
|
|
1135
|
+
await this._callEventHandler("on_job_update", message);
|
|
1136
|
+
this._pushJobGroupEvent(message.jobId, new JobGroupEvent({
|
|
1137
|
+
type: JobGroupEvent.UPDATE,
|
|
1138
|
+
workerName: message.source,
|
|
1139
|
+
data: message.update,
|
|
1140
|
+
}));
|
|
1141
|
+
}
|
|
1142
|
+
/** Handle a job update request from the requester. */
|
|
1143
|
+
async _handleJobUpdateRequest(message) {
|
|
1144
|
+
if (this._activeJobs.has(message.jobId)) {
|
|
1145
|
+
await this.onJobUpdateRequested(message);
|
|
1146
|
+
await this._callEventHandler("on_job_update_requested", message);
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
/**
|
|
1150
|
+
* Handle a job cancellation.
|
|
1151
|
+
*
|
|
1152
|
+
* Cancels the running handler task (if any), calls the `onJobCancelled`
|
|
1153
|
+
* hook for cleanup, then automatically sends a cancelled response back to
|
|
1154
|
+
* the requester. The requester receives `onJobResponse` with
|
|
1155
|
+
* `status: "cancelled"`, same path as completed or failed jobs.
|
|
1156
|
+
*/
|
|
1157
|
+
async _handleJobCancel(message) {
|
|
1158
|
+
if (this._activeJobs.has(message.jobId)) {
|
|
1159
|
+
const handlerTask = this._jobHandlerTasks.get(message.jobId);
|
|
1160
|
+
if (handlerTask) {
|
|
1161
|
+
await this.cancelTask(handlerTask);
|
|
1162
|
+
}
|
|
1163
|
+
await this.onJobCancelled(message);
|
|
1164
|
+
await this._callEventHandler("on_job_cancelled", message);
|
|
1165
|
+
await this.sendJobResponse(message.jobId, null, { status: JobStatus.CANCELLED });
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
/** Handle the start of a streaming job response. */
|
|
1169
|
+
async _handleJobStreamStart(message) {
|
|
1170
|
+
await this.onJobStreamStart(message);
|
|
1171
|
+
await this._callEventHandler("on_job_stream_start", message);
|
|
1172
|
+
this._pushJobGroupEvent(message.jobId, new JobGroupEvent({
|
|
1173
|
+
type: JobGroupEvent.STREAM_START,
|
|
1174
|
+
workerName: message.source,
|
|
1175
|
+
data: message.data,
|
|
1176
|
+
}));
|
|
1177
|
+
}
|
|
1178
|
+
/** Handle a streaming job data chunk. */
|
|
1179
|
+
async _handleJobStreamData(message) {
|
|
1180
|
+
await this.onJobStreamData(message);
|
|
1181
|
+
await this._callEventHandler("on_job_stream_data", message);
|
|
1182
|
+
this._pushJobGroupEvent(message.jobId, new JobGroupEvent({
|
|
1183
|
+
type: JobGroupEvent.STREAM_DATA,
|
|
1184
|
+
workerName: message.source,
|
|
1185
|
+
data: message.data,
|
|
1186
|
+
}));
|
|
1187
|
+
}
|
|
1188
|
+
/** Handle the end of a streaming job response. */
|
|
1189
|
+
async _handleJobStreamEnd(message) {
|
|
1190
|
+
this._markWorkerTerminated(message.jobId, message.source);
|
|
1191
|
+
await this.onJobStreamEnd(message);
|
|
1192
|
+
await this._callEventHandler("on_job_stream_end", message);
|
|
1193
|
+
this._pushJobGroupEvent(message.jobId, new JobGroupEvent({
|
|
1194
|
+
type: JobGroupEvent.STREAM_END,
|
|
1195
|
+
workerName: message.source,
|
|
1196
|
+
data: message.data,
|
|
1197
|
+
}));
|
|
1198
|
+
await this._trackJobGroupResponse(message.jobId, message.source, message.data);
|
|
1199
|
+
}
|
|
1200
|
+
_createJobGroup(workerNames, options) {
|
|
1201
|
+
const { params } = options;
|
|
1202
|
+
const jobId = crypto.randomUUID();
|
|
1203
|
+
const group = new JobGroup({
|
|
1204
|
+
jobId,
|
|
1205
|
+
workerNames: [...workerNames],
|
|
1206
|
+
cancelOnError: params.cancelOnError,
|
|
1207
|
+
label: params.label,
|
|
1208
|
+
cancellable: params.cancellable,
|
|
1209
|
+
});
|
|
1210
|
+
this._jobGroups.set(jobId, group);
|
|
1211
|
+
const timeout = params.timeout;
|
|
1212
|
+
if (timeout !== null) {
|
|
1213
|
+
group.timeoutTask = this.createTask(() => this._taskTimeout(jobId, timeout), `task_timeout_${jobId.slice(0, 8)}`);
|
|
1214
|
+
}
|
|
1215
|
+
return group;
|
|
1216
|
+
}
|
|
1217
|
+
/**
|
|
1218
|
+
* Return a coroutine function that resolves when all named workers are ready.
|
|
1219
|
+
*
|
|
1220
|
+
* The watches are registered before this returns; callers race the
|
|
1221
|
+
* returned function against a timeout (`waitFor(allReady, timeout)`) or a
|
|
1222
|
+
* group done signal. Upstream returns an `asyncio.Future`; a function is
|
|
1223
|
+
* returned here because awaiting an async function that returns a Task
|
|
1224
|
+
* would adopt (wait for) it.
|
|
1225
|
+
*
|
|
1226
|
+
* @throws Error If the registry is not available.
|
|
1227
|
+
*/
|
|
1228
|
+
async _waitWorkersReady(workerNames) {
|
|
1229
|
+
if (!this._registry) {
|
|
1230
|
+
throw new Error(`Worker '${this}': registry not available`);
|
|
1231
|
+
}
|
|
1232
|
+
const readyEvents = new Map();
|
|
1233
|
+
for (const name of workerNames) {
|
|
1234
|
+
const event = new Event();
|
|
1235
|
+
readyEvents.set(name, event);
|
|
1236
|
+
const onReady = async (_data) => {
|
|
1237
|
+
event.set();
|
|
1238
|
+
};
|
|
1239
|
+
await this._registry.watch(name, onReady);
|
|
1240
|
+
}
|
|
1241
|
+
return async () => {
|
|
1242
|
+
await gather(...[...readyEvents.values()].map((ev) => () => ev.wait()));
|
|
1243
|
+
};
|
|
1244
|
+
}
|
|
1245
|
+
async _sendJobRequest(workerName, jobId, options = {}) {
|
|
1246
|
+
await this.sendBusMessage(new BusJobRequestMessage({
|
|
1247
|
+
source: this.name,
|
|
1248
|
+
target: workerName,
|
|
1249
|
+
jobId,
|
|
1250
|
+
jobName: options.jobName ?? null,
|
|
1251
|
+
payload: options.payload ?? null,
|
|
1252
|
+
}));
|
|
1253
|
+
}
|
|
1254
|
+
async _taskTimeout(jobId, timeout) {
|
|
1255
|
+
try {
|
|
1256
|
+
await sleep(timeout);
|
|
1257
|
+
}
|
|
1258
|
+
catch (e) {
|
|
1259
|
+
if (e instanceof CancelledError)
|
|
1260
|
+
return;
|
|
1261
|
+
throw e;
|
|
1262
|
+
}
|
|
1263
|
+
await this.cancelJobGroup(jobId, { reason: "timeout" });
|
|
1264
|
+
}
|
|
1265
|
+
_pushJobGroupEvent(jobId, event) {
|
|
1266
|
+
const group = this._jobGroups.get(jobId);
|
|
1267
|
+
if (group?.eventQueue) {
|
|
1268
|
+
group.eventQueue.putNowait(event);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
/** Record a worker's response and fire completion when all have responded. */
|
|
1272
|
+
async _trackJobGroupResponse(jobId, source, response) {
|
|
1273
|
+
const group = this._jobGroups.get(jobId);
|
|
1274
|
+
if (group) {
|
|
1275
|
+
group.responses[source] = response ?? {};
|
|
1276
|
+
if (group.workerNames.every((name) => Object.hasOwn(group.responses, name))) {
|
|
1277
|
+
if (group.timeoutTask) {
|
|
1278
|
+
await this.cancelTask(group.timeoutTask);
|
|
1279
|
+
}
|
|
1280
|
+
this._jobGroups.delete(jobId);
|
|
1281
|
+
const result = new JobGroupResponse({ jobId, responses: group.responses });
|
|
1282
|
+
await this.onJobCompleted(result);
|
|
1283
|
+
await this._callEventHandler("on_job_completed", result);
|
|
1284
|
+
group.complete();
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
/** Warn about tasks left running on the task manager this worker owns. */
|
|
1289
|
+
_printDanglingTasks() {
|
|
1290
|
+
if (this._checkDanglingTasks && this._ownsTaskManager) {
|
|
1291
|
+
const tasks = this.taskManager.currentTasks().map((t) => t.getName());
|
|
1292
|
+
if (tasks.length > 0) {
|
|
1293
|
+
logger.warning(`${this} dangling tasks detected: [${tasks.map((t) => `'${t}'`).join(", ")}]`);
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
//# sourceMappingURL=base_worker.js.map
|