@a1hvdy/cc-openclaw 0.3.2
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 +22 -0
- package/README.md +207 -0
- package/configs/.gitkeep +0 -0
- package/configs/council-reviewer-prompt.md +82 -0
- package/configs/council-system-prompt.md +141 -0
- package/dist/scripts/bench/ab-harness.d.ts +58 -0
- package/dist/scripts/bench/ab-harness.d.ts.map +1 -0
- package/dist/scripts/bench/ab-harness.js +78 -0
- package/dist/scripts/bench/ab-harness.js.map +1 -0
- package/dist/src/channels/adapter.d.ts +103 -0
- package/dist/src/channels/adapter.d.ts.map +1 -0
- package/dist/src/channels/adapter.js +38 -0
- package/dist/src/channels/adapter.js.map +1 -0
- package/dist/src/channels/telegram/completion-summary.d.ts +22 -0
- package/dist/src/channels/telegram/completion-summary.d.ts.map +1 -0
- package/dist/src/channels/telegram/completion-summary.js +186 -0
- package/dist/src/channels/telegram/completion-summary.js.map +1 -0
- package/dist/src/channels/telegram/error-renderer.d.ts +30 -0
- package/dist/src/channels/telegram/error-renderer.d.ts.map +1 -0
- package/dist/src/channels/telegram/error-renderer.js +133 -0
- package/dist/src/channels/telegram/error-renderer.js.map +1 -0
- package/dist/src/channels/telegram/event-reducer.d.ts +34 -0
- package/dist/src/channels/telegram/event-reducer.d.ts.map +1 -0
- package/dist/src/channels/telegram/event-reducer.js +579 -0
- package/dist/src/channels/telegram/event-reducer.js.map +1 -0
- package/dist/src/channels/telegram/index.d.ts +14 -0
- package/dist/src/channels/telegram/index.d.ts.map +1 -0
- package/dist/src/channels/telegram/index.js +14 -0
- package/dist/src/channels/telegram/index.js.map +1 -0
- package/dist/src/channels/telegram/injector.d.ts +54 -0
- package/dist/src/channels/telegram/injector.d.ts.map +1 -0
- package/dist/src/channels/telegram/injector.js +200 -0
- package/dist/src/channels/telegram/injector.js.map +1 -0
- package/dist/src/channels/telegram/live-card.d.ts +230 -0
- package/dist/src/channels/telegram/live-card.d.ts.map +1 -0
- package/dist/src/channels/telegram/live-card.js +916 -0
- package/dist/src/channels/telegram/live-card.js.map +1 -0
- package/dist/src/channels/telegram/state-machine.d.ts +23 -0
- package/dist/src/channels/telegram/state-machine.d.ts.map +1 -0
- package/dist/src/channels/telegram/state-machine.js +72 -0
- package/dist/src/channels/telegram/state-machine.js.map +1 -0
- package/dist/src/channels/telegram/tool-tracker.d.ts +147 -0
- package/dist/src/channels/telegram/tool-tracker.d.ts.map +1 -0
- package/dist/src/channels/telegram/tool-tracker.js +520 -0
- package/dist/src/channels/telegram/tool-tracker.js.map +1 -0
- package/dist/src/circuit-breaker.d.ts +22 -0
- package/dist/src/circuit-breaker.d.ts.map +1 -0
- package/dist/src/circuit-breaker.js +47 -0
- package/dist/src/circuit-breaker.js.map +1 -0
- package/dist/src/command-router/cc-handler.d.ts +67 -0
- package/dist/src/command-router/cc-handler.d.ts.map +1 -0
- package/dist/src/command-router/cc-handler.js +980 -0
- package/dist/src/command-router/cc-handler.js.map +1 -0
- package/dist/src/command-router/index.d.ts +3 -0
- package/dist/src/command-router/index.d.ts.map +1 -0
- package/dist/src/command-router/index.js +2 -0
- package/dist/src/command-router/index.js.map +1 -0
- package/dist/src/constants.d.ts +132 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +140 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/council/consensus.d.ts +21 -0
- package/dist/src/council/consensus.d.ts.map +1 -0
- package/dist/src/council/consensus.js +52 -0
- package/dist/src/council/consensus.js.map +1 -0
- package/dist/src/council/council.d.ts +68 -0
- package/dist/src/council/council.d.ts.map +1 -0
- package/dist/src/council/council.js +914 -0
- package/dist/src/council/council.js.map +1 -0
- package/dist/src/council/index.d.ts +3 -0
- package/dist/src/council/index.d.ts.map +1 -0
- package/dist/src/council/index.js +3 -0
- package/dist/src/council/index.js.map +1 -0
- package/dist/src/engines/base-oneshot-session.d.ts +88 -0
- package/dist/src/engines/base-oneshot-session.d.ts.map +1 -0
- package/dist/src/engines/base-oneshot-session.js +228 -0
- package/dist/src/engines/base-oneshot-session.js.map +1 -0
- package/dist/src/engines/index.d.ts +7 -0
- package/dist/src/engines/index.d.ts.map +1 -0
- package/dist/src/engines/index.js +7 -0
- package/dist/src/engines/index.js.map +1 -0
- package/dist/src/engines/persistent-codex-session.d.ts +17 -0
- package/dist/src/engines/persistent-codex-session.d.ts.map +1 -0
- package/dist/src/engines/persistent-codex-session.js +106 -0
- package/dist/src/engines/persistent-codex-session.js.map +1 -0
- package/dist/src/engines/persistent-cursor-session.d.ts +22 -0
- package/dist/src/engines/persistent-cursor-session.d.ts.map +1 -0
- package/dist/src/engines/persistent-cursor-session.js +242 -0
- package/dist/src/engines/persistent-cursor-session.js.map +1 -0
- package/dist/src/engines/persistent-custom-session.d.ts +79 -0
- package/dist/src/engines/persistent-custom-session.d.ts.map +1 -0
- package/dist/src/engines/persistent-custom-session.js +939 -0
- package/dist/src/engines/persistent-custom-session.js.map +1 -0
- package/dist/src/engines/persistent-gemini-session.d.ts +22 -0
- package/dist/src/engines/persistent-gemini-session.d.ts.map +1 -0
- package/dist/src/engines/persistent-gemini-session.js +217 -0
- package/dist/src/engines/persistent-gemini-session.js.map +1 -0
- package/dist/src/engines/persistent-session.d.ts +77 -0
- package/dist/src/engines/persistent-session.d.ts.map +1 -0
- package/dist/src/engines/persistent-session.js +730 -0
- package/dist/src/engines/persistent-session.js.map +1 -0
- package/dist/src/health/handler.d.ts +40 -0
- package/dist/src/health/handler.d.ts.map +1 -0
- package/dist/src/health/handler.js +70 -0
- package/dist/src/health/handler.js.map +1 -0
- package/dist/src/health/index.d.ts +2 -0
- package/dist/src/health/index.d.ts.map +1 -0
- package/dist/src/health/index.js +2 -0
- package/dist/src/health/index.js.map +1 -0
- package/dist/src/index.d.ts +49 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +84 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lib/auto-recovery.d.ts +45 -0
- package/dist/src/lib/auto-recovery.d.ts.map +1 -0
- package/dist/src/lib/auto-recovery.js +217 -0
- package/dist/src/lib/auto-recovery.js.map +1 -0
- package/dist/src/lib/cache-parity.d.ts +39 -0
- package/dist/src/lib/cache-parity.d.ts.map +1 -0
- package/dist/src/lib/cache-parity.js +92 -0
- package/dist/src/lib/cache-parity.js.map +1 -0
- package/dist/src/lib/circuit-breaker.d.ts +22 -0
- package/dist/src/lib/circuit-breaker.d.ts.map +1 -0
- package/dist/src/lib/circuit-breaker.js +47 -0
- package/dist/src/lib/circuit-breaker.js.map +1 -0
- package/dist/src/lib/config.d.ts +74 -0
- package/dist/src/lib/config.d.ts.map +1 -0
- package/dist/src/lib/config.js +244 -0
- package/dist/src/lib/config.js.map +1 -0
- package/dist/src/lib/drift-detector.d.ts +47 -0
- package/dist/src/lib/drift-detector.d.ts.map +1 -0
- package/dist/src/lib/drift-detector.js +192 -0
- package/dist/src/lib/drift-detector.js.map +1 -0
- package/dist/src/lib/error-formatter.d.ts +78 -0
- package/dist/src/lib/error-formatter.d.ts.map +1 -0
- package/dist/src/lib/error-formatter.js +149 -0
- package/dist/src/lib/error-formatter.js.map +1 -0
- package/dist/src/lib/heartbeat-workaround.d.ts +45 -0
- package/dist/src/lib/heartbeat-workaround.d.ts.map +1 -0
- package/dist/src/lib/heartbeat-workaround.js +61 -0
- package/dist/src/lib/heartbeat-workaround.js.map +1 -0
- package/dist/src/lib/index.d.ts +8 -0
- package/dist/src/lib/index.d.ts.map +1 -0
- package/dist/src/lib/index.js +8 -0
- package/dist/src/lib/index.js.map +1 -0
- package/dist/src/lib/register-guard.d.ts +49 -0
- package/dist/src/lib/register-guard.d.ts.map +1 -0
- package/dist/src/lib/register-guard.js +73 -0
- package/dist/src/lib/register-guard.js.map +1 -0
- package/dist/src/lib/route-flag.d.ts +50 -0
- package/dist/src/lib/route-flag.d.ts.map +1 -0
- package/dist/src/lib/route-flag.js +52 -0
- package/dist/src/lib/route-flag.js.map +1 -0
- package/dist/src/lib/sysprompt-strip.d.ts +54 -0
- package/dist/src/lib/sysprompt-strip.d.ts.map +1 -0
- package/dist/src/lib/sysprompt-strip.js +75 -0
- package/dist/src/lib/sysprompt-strip.js.map +1 -0
- package/dist/src/lib/telemetry.d.ts +39 -0
- package/dist/src/lib/telemetry.d.ts.map +1 -0
- package/dist/src/lib/telemetry.js +73 -0
- package/dist/src/lib/telemetry.js.map +1 -0
- package/dist/src/lib/test-mode.d.ts +27 -0
- package/dist/src/lib/test-mode.d.ts.map +1 -0
- package/dist/src/lib/test-mode.js +38 -0
- package/dist/src/lib/test-mode.js.map +1 -0
- package/dist/src/lib/vendor-paths.d.ts +15 -0
- package/dist/src/lib/vendor-paths.d.ts.map +1 -0
- package/dist/src/lib/vendor-paths.js +32 -0
- package/dist/src/lib/vendor-paths.js.map +1 -0
- package/dist/src/logger.d.ts +17 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +46 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/mcp/bridge.d.ts +22 -0
- package/dist/src/mcp/bridge.d.ts.map +1 -0
- package/dist/src/mcp/bridge.js +78 -0
- package/dist/src/mcp/bridge.js.map +1 -0
- package/dist/src/mcp/index.d.ts +3 -0
- package/dist/src/mcp/index.d.ts.map +1 -0
- package/dist/src/mcp/index.js +2 -0
- package/dist/src/mcp/index.js.map +1 -0
- package/dist/src/models.d.ts +70 -0
- package/dist/src/models.d.ts.map +1 -0
- package/dist/src/models.js +289 -0
- package/dist/src/models.js.map +1 -0
- package/dist/src/openai-compat/cli-stream-parser.d.ts +135 -0
- package/dist/src/openai-compat/cli-stream-parser.d.ts.map +1 -0
- package/dist/src/openai-compat/cli-stream-parser.js +195 -0
- package/dist/src/openai-compat/cli-stream-parser.js.map +1 -0
- package/dist/src/openai-compat/index.d.ts +2 -0
- package/dist/src/openai-compat/index.d.ts.map +1 -0
- package/dist/src/openai-compat/index.js +2 -0
- package/dist/src/openai-compat/index.js.map +1 -0
- package/dist/src/openai-compat/openai-compat.d.ts +281 -0
- package/dist/src/openai-compat/openai-compat.d.ts.map +1 -0
- package/dist/src/openai-compat/openai-compat.js +939 -0
- package/dist/src/openai-compat/openai-compat.js.map +1 -0
- package/dist/src/openai-compat/skill-resolver.d.ts +36 -0
- package/dist/src/openai-compat/skill-resolver.d.ts.map +1 -0
- package/dist/src/openai-compat/skill-resolver.js +134 -0
- package/dist/src/openai-compat/skill-resolver.js.map +1 -0
- package/dist/src/openai-compat/sse-translator.d.ts +32 -0
- package/dist/src/openai-compat/sse-translator.d.ts.map +1 -0
- package/dist/src/openai-compat/sse-translator.js +155 -0
- package/dist/src/openai-compat/sse-translator.js.map +1 -0
- package/dist/src/proxy/anthropic-adapter.d.ts +137 -0
- package/dist/src/proxy/anthropic-adapter.d.ts.map +1 -0
- package/dist/src/proxy/anthropic-adapter.js +392 -0
- package/dist/src/proxy/anthropic-adapter.js.map +1 -0
- package/dist/src/proxy/handler.d.ts +40 -0
- package/dist/src/proxy/handler.d.ts.map +1 -0
- package/dist/src/proxy/handler.js +378 -0
- package/dist/src/proxy/handler.js.map +1 -0
- package/dist/src/proxy/index.d.ts +5 -0
- package/dist/src/proxy/index.d.ts.map +1 -0
- package/dist/src/proxy/index.js +5 -0
- package/dist/src/proxy/index.js.map +1 -0
- package/dist/src/proxy/schema-cleaner.d.ts +12 -0
- package/dist/src/proxy/schema-cleaner.d.ts.map +1 -0
- package/dist/src/proxy/schema-cleaner.js +34 -0
- package/dist/src/proxy/schema-cleaner.js.map +1 -0
- package/dist/src/proxy/thought-cache.d.ts +20 -0
- package/dist/src/proxy/thought-cache.d.ts.map +1 -0
- package/dist/src/proxy/thought-cache.js +53 -0
- package/dist/src/proxy/thought-cache.js.map +1 -0
- package/dist/src/session/embedded-server.d.ts +26 -0
- package/dist/src/session/embedded-server.d.ts.map +1 -0
- package/dist/src/session/embedded-server.js +367 -0
- package/dist/src/session/embedded-server.js.map +1 -0
- package/dist/src/session/inbox-manager.d.ts +39 -0
- package/dist/src/session/inbox-manager.d.ts.map +1 -0
- package/dist/src/session/inbox-manager.js +111 -0
- package/dist/src/session/inbox-manager.js.map +1 -0
- package/dist/src/session/index.d.ts +4 -0
- package/dist/src/session/index.d.ts.map +1 -0
- package/dist/src/session/index.js +4 -0
- package/dist/src/session/index.js.map +1 -0
- package/dist/src/session/session-manager.d.ts +212 -0
- package/dist/src/session/session-manager.d.ts.map +1 -0
- package/dist/src/session/session-manager.js +1351 -0
- package/dist/src/session/session-manager.js.map +1 -0
- package/dist/src/session-bootstrap/cwd-patch.d.ts +51 -0
- package/dist/src/session-bootstrap/cwd-patch.d.ts.map +1 -0
- package/dist/src/session-bootstrap/cwd-patch.js +955 -0
- package/dist/src/session-bootstrap/cwd-patch.js.map +1 -0
- package/dist/src/session-bootstrap/index.d.ts +4 -0
- package/dist/src/session-bootstrap/index.d.ts.map +1 -0
- package/dist/src/session-bootstrap/index.js +4 -0
- package/dist/src/session-bootstrap/index.js.map +1 -0
- package/dist/src/session-bootstrap/sysprompt-strip.d.ts +26 -0
- package/dist/src/session-bootstrap/sysprompt-strip.d.ts.map +1 -0
- package/dist/src/session-bootstrap/sysprompt-strip.js +57 -0
- package/dist/src/session-bootstrap/sysprompt-strip.js.map +1 -0
- package/dist/src/session-bootstrap/think-conflict-resolver.d.ts +33 -0
- package/dist/src/session-bootstrap/think-conflict-resolver.d.ts.map +1 -0
- package/dist/src/session-bootstrap/think-conflict-resolver.js +234 -0
- package/dist/src/session-bootstrap/think-conflict-resolver.js.map +1 -0
- package/dist/src/types.d.ts +489 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +8 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/validation.d.ts +32 -0
- package/dist/src/validation.d.ts.map +1 -0
- package/dist/src/validation.js +104 -0
- package/dist/src/validation.js.map +1 -0
- package/dist/tests/_helpers/subprocess-mock.d.ts +35 -0
- package/dist/tests/_helpers/subprocess-mock.d.ts.map +1 -0
- package/dist/tests/_helpers/subprocess-mock.js +136 -0
- package/dist/tests/_helpers/subprocess-mock.js.map +1 -0
- package/dist/tests/auto-recovery.test.d.ts +2 -0
- package/dist/tests/auto-recovery.test.d.ts.map +1 -0
- package/dist/tests/auto-recovery.test.js +189 -0
- package/dist/tests/auto-recovery.test.js.map +1 -0
- package/dist/tests/bench-harness.test.d.ts +2 -0
- package/dist/tests/bench-harness.test.d.ts.map +1 -0
- package/dist/tests/bench-harness.test.js +21 -0
- package/dist/tests/bench-harness.test.js.map +1 -0
- package/dist/tests/cache-parity.test.d.ts +2 -0
- package/dist/tests/cache-parity.test.d.ts.map +1 -0
- package/dist/tests/cache-parity.test.js +401 -0
- package/dist/tests/cache-parity.test.js.map +1 -0
- package/dist/tests/command-router.test.d.ts +2 -0
- package/dist/tests/command-router.test.d.ts.map +1 -0
- package/dist/tests/command-router.test.js +60 -0
- package/dist/tests/command-router.test.js.map +1 -0
- package/dist/tests/council.test.d.ts +2 -0
- package/dist/tests/council.test.d.ts.map +1 -0
- package/dist/tests/council.test.js +20 -0
- package/dist/tests/council.test.js.map +1 -0
- package/dist/tests/drift-detector.test.d.ts +2 -0
- package/dist/tests/drift-detector.test.d.ts.map +1 -0
- package/dist/tests/drift-detector.test.js +268 -0
- package/dist/tests/drift-detector.test.js.map +1 -0
- package/dist/tests/eager-bootstrap-gating.test.d.ts +9 -0
- package/dist/tests/eager-bootstrap-gating.test.d.ts.map +1 -0
- package/dist/tests/eager-bootstrap-gating.test.js +97 -0
- package/dist/tests/eager-bootstrap-gating.test.js.map +1 -0
- package/dist/tests/engines.test.d.ts +2 -0
- package/dist/tests/engines.test.d.ts.map +1 -0
- package/dist/tests/engines.test.js +8 -0
- package/dist/tests/engines.test.js.map +1 -0
- package/dist/tests/error-formatter.test.d.ts +2 -0
- package/dist/tests/error-formatter.test.d.ts.map +1 -0
- package/dist/tests/error-formatter.test.js +220 -0
- package/dist/tests/error-formatter.test.js.map +1 -0
- package/dist/tests/health.test.d.ts +2 -0
- package/dist/tests/health.test.d.ts.map +1 -0
- package/dist/tests/health.test.js +110 -0
- package/dist/tests/health.test.js.map +1 -0
- package/dist/tests/heartbeat-workaround.test.d.ts +2 -0
- package/dist/tests/heartbeat-workaround.test.d.ts.map +1 -0
- package/dist/tests/heartbeat-workaround.test.js +90 -0
- package/dist/tests/heartbeat-workaround.test.js.map +1 -0
- package/dist/tests/index.test.d.ts +2 -0
- package/dist/tests/index.test.d.ts.map +1 -0
- package/dist/tests/index.test.js +7 -0
- package/dist/tests/index.test.js.map +1 -0
- package/dist/tests/lib-sysprompt-strip.test.d.ts +2 -0
- package/dist/tests/lib-sysprompt-strip.test.d.ts.map +1 -0
- package/dist/tests/lib-sysprompt-strip.test.js +145 -0
- package/dist/tests/lib-sysprompt-strip.test.js.map +1 -0
- package/dist/tests/listener-activation.test.d.ts +2 -0
- package/dist/tests/listener-activation.test.d.ts.map +1 -0
- package/dist/tests/listener-activation.test.js +87 -0
- package/dist/tests/listener-activation.test.js.map +1 -0
- package/dist/tests/mcp-bridge.test.d.ts +2 -0
- package/dist/tests/mcp-bridge.test.d.ts.map +1 -0
- package/dist/tests/mcp-bridge.test.js +137 -0
- package/dist/tests/mcp-bridge.test.js.map +1 -0
- package/dist/tests/openai-compat.test.d.ts +2 -0
- package/dist/tests/openai-compat.test.d.ts.map +1 -0
- package/dist/tests/openai-compat.test.js +8 -0
- package/dist/tests/openai-compat.test.js.map +1 -0
- package/dist/tests/proxy-heartbeat-integration.test.d.ts +15 -0
- package/dist/tests/proxy-heartbeat-integration.test.d.ts.map +1 -0
- package/dist/tests/proxy-heartbeat-integration.test.js +122 -0
- package/dist/tests/proxy-heartbeat-integration.test.js.map +1 -0
- package/dist/tests/proxy.test.d.ts +2 -0
- package/dist/tests/proxy.test.d.ts.map +1 -0
- package/dist/tests/proxy.test.js +8 -0
- package/dist/tests/proxy.test.js.map +1 -0
- package/dist/tests/register-guard-stacking.test.d.ts +2 -0
- package/dist/tests/register-guard-stacking.test.d.ts.map +1 -0
- package/dist/tests/register-guard-stacking.test.js +61 -0
- package/dist/tests/register-guard-stacking.test.js.map +1 -0
- package/dist/tests/register-guard.test.d.ts +2 -0
- package/dist/tests/register-guard.test.d.ts.map +1 -0
- package/dist/tests/register-guard.test.js +129 -0
- package/dist/tests/register-guard.test.js.map +1 -0
- package/dist/tests/route-flag-rollback.test.d.ts +2 -0
- package/dist/tests/route-flag-rollback.test.d.ts.map +1 -0
- package/dist/tests/route-flag-rollback.test.js +70 -0
- package/dist/tests/route-flag-rollback.test.js.map +1 -0
- package/dist/tests/route-flag.test.d.ts +2 -0
- package/dist/tests/route-flag.test.d.ts.map +1 -0
- package/dist/tests/route-flag.test.js +101 -0
- package/dist/tests/route-flag.test.js.map +1 -0
- package/dist/tests/session-bootstrap.test.d.ts +2 -0
- package/dist/tests/session-bootstrap.test.d.ts.map +1 -0
- package/dist/tests/session-bootstrap.test.js +183 -0
- package/dist/tests/session-bootstrap.test.js.map +1 -0
- package/dist/tests/session.test.d.ts +2 -0
- package/dist/tests/session.test.d.ts.map +1 -0
- package/dist/tests/session.test.js +17 -0
- package/dist/tests/session.test.js.map +1 -0
- package/dist/tests/state-machine.test.d.ts +2 -0
- package/dist/tests/state-machine.test.d.ts.map +1 -0
- package/dist/tests/state-machine.test.js +133 -0
- package/dist/tests/state-machine.test.js.map +1 -0
- package/dist/tests/streaming/cli-stream-parser.test.d.ts +2 -0
- package/dist/tests/streaming/cli-stream-parser.test.d.ts.map +1 -0
- package/dist/tests/streaming/cli-stream-parser.test.js +233 -0
- package/dist/tests/streaming/cli-stream-parser.test.js.map +1 -0
- package/dist/tests/streaming/feature-flag.test.d.ts +14 -0
- package/dist/tests/streaming/feature-flag.test.d.ts.map +1 -0
- package/dist/tests/streaming/feature-flag.test.js +163 -0
- package/dist/tests/streaming/feature-flag.test.js.map +1 -0
- package/dist/tests/streaming/no-tools-prompt.test.d.ts +17 -0
- package/dist/tests/streaming/no-tools-prompt.test.d.ts.map +1 -0
- package/dist/tests/streaming/no-tools-prompt.test.js +229 -0
- package/dist/tests/streaming/no-tools-prompt.test.js.map +1 -0
- package/dist/tests/streaming/skill-plus-tools.test.d.ts +14 -0
- package/dist/tests/streaming/skill-plus-tools.test.d.ts.map +1 -0
- package/dist/tests/streaming/skill-plus-tools.test.js +234 -0
- package/dist/tests/streaming/skill-plus-tools.test.js.map +1 -0
- package/dist/tests/streaming/sse-translator.test.d.ts +2 -0
- package/dist/tests/streaming/sse-translator.test.d.ts.map +1 -0
- package/dist/tests/streaming/sse-translator.test.js +227 -0
- package/dist/tests/streaming/sse-translator.test.js.map +1 -0
- package/dist/tests/streaming/tool-result-roundtrip.test.d.ts +11 -0
- package/dist/tests/streaming/tool-result-roundtrip.test.d.ts.map +1 -0
- package/dist/tests/streaming/tool-result-roundtrip.test.js +215 -0
- package/dist/tests/streaming/tool-result-roundtrip.test.js.map +1 -0
- package/dist/tests/streaming/tool-use-translation.test.d.ts +10 -0
- package/dist/tests/streaming/tool-use-translation.test.d.ts.map +1 -0
- package/dist/tests/streaming/tool-use-translation.test.js +251 -0
- package/dist/tests/streaming/tool-use-translation.test.js.map +1 -0
- package/dist/tests/telegram-bridge.test.d.ts +2 -0
- package/dist/tests/telegram-bridge.test.d.ts.map +1 -0
- package/dist/tests/telegram-bridge.test.js +17 -0
- package/dist/tests/telegram-bridge.test.js.map +1 -0
- package/dist/tests/telegram-injector.test.d.ts +2 -0
- package/dist/tests/telegram-injector.test.d.ts.map +1 -0
- package/dist/tests/telegram-injector.test.js +74 -0
- package/dist/tests/telegram-injector.test.js.map +1 -0
- package/dist/tests/telemetry.test.d.ts +2 -0
- package/dist/tests/telemetry.test.d.ts.map +1 -0
- package/dist/tests/telemetry.test.js +405 -0
- package/dist/tests/telemetry.test.js.map +1 -0
- package/dist/tests/test-mode.test.d.ts +2 -0
- package/dist/tests/test-mode.test.d.ts.map +1 -0
- package/dist/tests/test-mode.test.js +39 -0
- package/dist/tests/test-mode.test.js.map +1 -0
- package/mcp-config.template.json +13 -0
- package/mcp-tools.json +1 -0
- package/openclaw-mcp-bridge.cjs +152 -0
- package/openclaw.plugin.json +30 -0
- package/package.json +45 -0
- package/skills/.gitkeep +0 -0
- package/stubs/commands-status-deps.runtime.js +10 -0
- package/stubs/status.runtime.js +149 -0
- package/vendor/base-oneshot-session.d.ts +87 -0
- package/vendor/base-oneshot-session.js +227 -0
- package/vendor/base-oneshot-session.js.map +1 -0
- package/vendor/circuit-breaker.d.ts +21 -0
- package/vendor/circuit-breaker.js +47 -0
- package/vendor/circuit-breaker.js.map +1 -0
- package/vendor/consensus.d.ts +20 -0
- package/vendor/consensus.js +52 -0
- package/vendor/consensus.js.map +1 -0
- package/vendor/constants.d.ts +130 -0
- package/vendor/constants.js +139 -0
- package/vendor/constants.js.map +1 -0
- package/vendor/council.d.ts +67 -0
- package/vendor/council.js +913 -0
- package/vendor/council.js.map +1 -0
- package/vendor/embedded-server.d.ts +25 -0
- package/vendor/embedded-server.js +360 -0
- package/vendor/embedded-server.js.map +1 -0
- package/vendor/inbox-manager.d.ts +38 -0
- package/vendor/inbox-manager.js +111 -0
- package/vendor/inbox-manager.js.map +1 -0
- package/vendor/index.d.ts +63 -0
- package/vendor/index.js +705 -0
- package/vendor/index.js.map +1 -0
- package/vendor/logger.d.ts +16 -0
- package/vendor/logger.js +44 -0
- package/vendor/logger.js.map +1 -0
- package/vendor/models.d.ts +69 -0
- package/vendor/models.js +289 -0
- package/vendor/models.js.map +1 -0
- package/vendor/openai-compat.d.ts +197 -0
- package/vendor/openai-compat.js +721 -0
- package/vendor/openai-compat.js.map +1 -0
- package/vendor/persistent-codex-session.d.ts +16 -0
- package/vendor/persistent-codex-session.js +105 -0
- package/vendor/persistent-codex-session.js.map +1 -0
- package/vendor/persistent-cursor-session.d.ts +21 -0
- package/vendor/persistent-cursor-session.js +241 -0
- package/vendor/persistent-cursor-session.js.map +1 -0
- package/vendor/persistent-custom-session.d.ts +78 -0
- package/vendor/persistent-custom-session.js +937 -0
- package/vendor/persistent-custom-session.js.map +1 -0
- package/vendor/persistent-gemini-session.d.ts +21 -0
- package/vendor/persistent-gemini-session.js +216 -0
- package/vendor/persistent-gemini-session.js.map +1 -0
- package/vendor/persistent-session.d.ts +74 -0
- package/vendor/persistent-session.js +684 -0
- package/vendor/persistent-session.js.map +1 -0
- package/vendor/proxy/anthropic-adapter.d.ts +136 -0
- package/vendor/proxy/anthropic-adapter.js +392 -0
- package/vendor/proxy/anthropic-adapter.js.map +1 -0
- package/vendor/proxy/handler.d.ts +39 -0
- package/vendor/proxy/handler.js +323 -0
- package/vendor/proxy/handler.js.map +1 -0
- package/vendor/proxy/schema-cleaner.d.ts +11 -0
- package/vendor/proxy/schema-cleaner.js +34 -0
- package/vendor/proxy/schema-cleaner.js.map +1 -0
- package/vendor/proxy/thought-cache.d.ts +19 -0
- package/vendor/proxy/thought-cache.js +53 -0
- package/vendor/proxy/thought-cache.js.map +1 -0
- package/vendor/session-manager.d.ts +211 -0
- package/vendor/session-manager.js +1345 -0
- package/vendor/session-manager.js.map +1 -0
- package/vendor/skill-resolver.js +107 -0
- package/vendor/types.d.ts +466 -0
- package/vendor/types.js +8 -0
- package/vendor/types.js.map +1 -0
- package/vendor/validation.d.ts +31 -0
- package/vendor/validation.js +104 -0
- package/vendor/validation.js.map +1 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channel Adapter — generic interface for delivering session UX
|
|
3
|
+
* to chat channels (Telegram, Discord, Signal, etc.).
|
|
4
|
+
*
|
|
5
|
+
* Telegram is the first concrete implementation (src/channels/telegram/).
|
|
6
|
+
* Discord and Signal are deferred to v1.1 (Nice-to-Have).
|
|
7
|
+
*
|
|
8
|
+
* Each adapter:
|
|
9
|
+
* - Renders live session cards (progress, tool calls, summaries)
|
|
10
|
+
* - Receives inbound channel messages and forwards them as session inputs
|
|
11
|
+
* - Sends session outputs back to the channel
|
|
12
|
+
* - Provides idempotent register() to wire OpenClaw plugin lifecycle hooks
|
|
13
|
+
*
|
|
14
|
+
* AUDIT — B2 (PRP_v3 §11 vs reality, 2026-04-28):
|
|
15
|
+
*
|
|
16
|
+
* PRP_v3 §11.1 documents an event vocabulary (`session.created`,
|
|
17
|
+
* `session.turn.start`, `session.tool.start`, `plugin.heartbeat`, etc.)
|
|
18
|
+
* that does NOT exist in the actual codebase. Every `api.on()` call
|
|
19
|
+
* site in src/ uses the openclaw-claude-code hook-event vocabulary
|
|
20
|
+
* documented in `ChannelHookEvent` below. Likewise §11.2's
|
|
21
|
+
* `api.emit('session.result', ...)` is unimplemented — no `api.emit`
|
|
22
|
+
* call sites exist.
|
|
23
|
+
*
|
|
24
|
+
* Resolution: this audit treats the *code* as canonical and the spec
|
|
25
|
+
* as drifted. The `ChannelHookEvent` literal union captures the actual
|
|
26
|
+
* contract any future channel adapter must speak. The §11.x doc
|
|
27
|
+
* sections need a v3.1 revision to match — tracked as a docs-tier
|
|
28
|
+
* follow-up (Tier 3 §24), not a code-tier blocker.
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* Canonical hook event vocabulary — every event name passed to `api.on()`
|
|
32
|
+
* across src/channels/, src/command-router/, and src/session-bootstrap/
|
|
33
|
+
* (verified by `rg "api\\.on\\(" src/`).
|
|
34
|
+
*
|
|
35
|
+
* This is the contract: any channel/handler that wants to subscribe to
|
|
36
|
+
* gateway events MUST use one of these names. Adding a new event name
|
|
37
|
+
* here without a corresponding gateway emitter is dead-code-typing.
|
|
38
|
+
*/
|
|
39
|
+
export type ChannelHookEvent = 'before_dispatch' | 'before_prompt_build' | 'before_model_resolve' | 'before_tool_call' | 'after_tool_call' | 'reply_dispatch' | 'message_sending';
|
|
40
|
+
/** Hook handler signature — gateway passes (event, ctx?) positional args. */
|
|
41
|
+
export type ChannelHookHandler = (...args: unknown[]) => unknown | Promise<unknown>;
|
|
42
|
+
export interface PluginApi {
|
|
43
|
+
/**
|
|
44
|
+
* Subscribe to a gateway hook event.
|
|
45
|
+
*
|
|
46
|
+
* Accepts `ChannelHookEvent` for compile-time event-name checking, or
|
|
47
|
+
* `string` as an escape hatch for adapter-specific events not yet
|
|
48
|
+
* canonicalized into the union. Future tightening: drop the `| string`
|
|
49
|
+
* overload once all hook sites use the union.
|
|
50
|
+
*/
|
|
51
|
+
on(event: ChannelHookEvent, handler: ChannelHookHandler): void;
|
|
52
|
+
on(event: string, handler: ChannelHookHandler): void;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Outbound message from session → channel.
|
|
56
|
+
*/
|
|
57
|
+
export interface ChannelMessage {
|
|
58
|
+
channel: string;
|
|
59
|
+
target: string;
|
|
60
|
+
text?: string;
|
|
61
|
+
buttons?: ChannelButton[];
|
|
62
|
+
metadata?: Record<string, unknown>;
|
|
63
|
+
}
|
|
64
|
+
export interface ChannelButton {
|
|
65
|
+
text: string;
|
|
66
|
+
callbackData?: string;
|
|
67
|
+
url?: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Inbound envelope from channel → session.
|
|
71
|
+
*/
|
|
72
|
+
export interface ChannelInbound {
|
|
73
|
+
channel: string;
|
|
74
|
+
fromUserId: string;
|
|
75
|
+
text: string;
|
|
76
|
+
metadata?: Record<string, unknown>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Channel adapter contract. Each concrete adapter (e.g. Telegram) implements
|
|
80
|
+
* this interface so cc-openclaw can route session events to any wired channel.
|
|
81
|
+
*/
|
|
82
|
+
export interface ChannelAdapter {
|
|
83
|
+
/** Adapter identifier — must be unique across registered adapters. */
|
|
84
|
+
readonly id: string;
|
|
85
|
+
/**
|
|
86
|
+
* Idempotent registration of OpenClaw plugin lifecycle hooks.
|
|
87
|
+
* Multiple calls with the same api MUST NOT stack listeners.
|
|
88
|
+
*/
|
|
89
|
+
register(api: PluginApi): void;
|
|
90
|
+
/** Send an outbound message to the channel. */
|
|
91
|
+
send(message: ChannelMessage): Promise<void>;
|
|
92
|
+
/** Update an existing live card in-place (rendering progress). */
|
|
93
|
+
updateCard?(target: string, message: ChannelMessage): Promise<void>;
|
|
94
|
+
/** Render a final completion summary to the channel. */
|
|
95
|
+
completionSummary?(target: string, summary: ChannelMessage): Promise<void>;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Helper to wire any ChannelAdapter via the plugin's main register() flow.
|
|
99
|
+
* Centralizes the per-adapter `register()` call so src/index.ts can
|
|
100
|
+
* iterate a list of adapters without coupling to each adapter's internals.
|
|
101
|
+
*/
|
|
102
|
+
export declare function registerChannelAdapter(api: PluginApi, adapter: ChannelAdapter): void;
|
|
103
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/channels/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,GACxB,iBAAiB,GACjB,qBAAqB,GACrB,sBAAsB,GACtB,kBAAkB,GAClB,iBAAiB,GACjB,gBAAgB,GAChB,iBAAiB,CAAC;AAEtB,6EAA6E;AAC7E,MAAM,MAAM,kBAAkB,GAC5B,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAErD,MAAM,WAAW,SAAS;IACxB;;;;;;;OAOG;IACH,EAAE,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC/D,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACtD;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IAE/B,+CAA+C;IAC/C,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C,kEAAkE;IAClE,UAAU,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpE,wDAAwD;IACxD,iBAAiB,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5E;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAEpF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channel Adapter — generic interface for delivering session UX
|
|
3
|
+
* to chat channels (Telegram, Discord, Signal, etc.).
|
|
4
|
+
*
|
|
5
|
+
* Telegram is the first concrete implementation (src/channels/telegram/).
|
|
6
|
+
* Discord and Signal are deferred to v1.1 (Nice-to-Have).
|
|
7
|
+
*
|
|
8
|
+
* Each adapter:
|
|
9
|
+
* - Renders live session cards (progress, tool calls, summaries)
|
|
10
|
+
* - Receives inbound channel messages and forwards them as session inputs
|
|
11
|
+
* - Sends session outputs back to the channel
|
|
12
|
+
* - Provides idempotent register() to wire OpenClaw plugin lifecycle hooks
|
|
13
|
+
*
|
|
14
|
+
* AUDIT — B2 (PRP_v3 §11 vs reality, 2026-04-28):
|
|
15
|
+
*
|
|
16
|
+
* PRP_v3 §11.1 documents an event vocabulary (`session.created`,
|
|
17
|
+
* `session.turn.start`, `session.tool.start`, `plugin.heartbeat`, etc.)
|
|
18
|
+
* that does NOT exist in the actual codebase. Every `api.on()` call
|
|
19
|
+
* site in src/ uses the openclaw-claude-code hook-event vocabulary
|
|
20
|
+
* documented in `ChannelHookEvent` below. Likewise §11.2's
|
|
21
|
+
* `api.emit('session.result', ...)` is unimplemented — no `api.emit`
|
|
22
|
+
* call sites exist.
|
|
23
|
+
*
|
|
24
|
+
* Resolution: this audit treats the *code* as canonical and the spec
|
|
25
|
+
* as drifted. The `ChannelHookEvent` literal union captures the actual
|
|
26
|
+
* contract any future channel adapter must speak. The §11.x doc
|
|
27
|
+
* sections need a v3.1 revision to match — tracked as a docs-tier
|
|
28
|
+
* follow-up (Tier 3 §24), not a code-tier blocker.
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* Helper to wire any ChannelAdapter via the plugin's main register() flow.
|
|
32
|
+
* Centralizes the per-adapter `register()` call so src/index.ts can
|
|
33
|
+
* iterate a list of adapters without coupling to each adapter's internals.
|
|
34
|
+
*/
|
|
35
|
+
export function registerChannelAdapter(api, adapter) {
|
|
36
|
+
adapter.register(api);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/channels/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAwFH;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAc,EAAE,OAAuB;IAC5E,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* telegram completion-summary — TypeScript port of savvy-claude-code/ux-bridge.js
|
|
3
|
+
*
|
|
4
|
+
* Handles reply_dispatch finalization for Savvy cards:
|
|
5
|
+
* - Marks card done, generates next-steps, renders final state
|
|
6
|
+
* - Auto-collapse after delay, TTL-delete collapsed card
|
|
7
|
+
* - Completion reactions + auto-pin/unpin error cards
|
|
8
|
+
* - Persists card summary to daily JSONL log
|
|
9
|
+
* - Updates session history cache
|
|
10
|
+
*
|
|
11
|
+
* Source lines: 2077–2222 of ux-bridge.js
|
|
12
|
+
*/
|
|
13
|
+
export interface PluginApi {
|
|
14
|
+
on(event: string, handler: (...args: unknown[]) => unknown | Promise<unknown>): void;
|
|
15
|
+
logger?: Console;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Register the completion-summary plugin hook (reply_dispatch).
|
|
19
|
+
* Idempotent — subsequent calls are no-ops.
|
|
20
|
+
*/
|
|
21
|
+
export declare function register(api: PluginApi): void;
|
|
22
|
+
//# sourceMappingURL=completion-summary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completion-summary.d.ts","sourceRoot":"","sources":["../../../../src/channels/telegram/completion-summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAqBH,MAAM,WAAW,SAAS;IACxB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IACrF,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAgBD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CA2J7C"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* telegram completion-summary — TypeScript port of savvy-claude-code/ux-bridge.js
|
|
3
|
+
*
|
|
4
|
+
* Handles reply_dispatch finalization for Savvy cards:
|
|
5
|
+
* - Marks card done, generates next-steps, renders final state
|
|
6
|
+
* - Auto-collapse after delay, TTL-delete collapsed card
|
|
7
|
+
* - Completion reactions + auto-pin/unpin error cards
|
|
8
|
+
* - Persists card summary to daily JSONL log
|
|
9
|
+
* - Updates session history cache
|
|
10
|
+
*
|
|
11
|
+
* Source lines: 2077–2222 of ux-bridge.js
|
|
12
|
+
*/
|
|
13
|
+
import { appendFileSync, mkdirSync } from 'node:fs';
|
|
14
|
+
import { defaultRegisterGuard } from '../../lib/register-guard.js';
|
|
15
|
+
import { telegramApi, _logger, } from './live-card.js';
|
|
16
|
+
import { activeSavvyCards, activeSavvyChatIds, savvyQuotaFetcher, setSavvyQuotaFetcher, sessionHistoryCache, savvyButtons, renderSavvyCard, generateNextSteps, } from './tool-tracker.js';
|
|
17
|
+
// ── Constants ─────────────────────────────────────────────────────────────
|
|
18
|
+
const PLUGIN_TAG = '[cc-openclaw/telegram/completion-summary]';
|
|
19
|
+
const SAVVY_LOG_DIR = '/home/a1xai/.openclaw/sessions/savvy-turns';
|
|
20
|
+
const MAX_HISTORY_CACHE = 50;
|
|
21
|
+
// Track last pinned error card per chat for auto-unpin on clean follow-up
|
|
22
|
+
const lastPinnedErrorCard = new Map(); // chatId → messageId
|
|
23
|
+
// ── Internal types ────────────────────────────────────────────────────────
|
|
24
|
+
// (local alias — tool-tracker's SavvyCardState is not re-exported, use unknown cast)
|
|
25
|
+
// ── register() ────────────────────────────────────────────────────────────
|
|
26
|
+
/**
|
|
27
|
+
* Register the completion-summary plugin hook (reply_dispatch).
|
|
28
|
+
* Idempotent — subsequent calls are no-ops.
|
|
29
|
+
*/
|
|
30
|
+
export function register(api) {
|
|
31
|
+
const logger = api.logger || _logger;
|
|
32
|
+
defaultRegisterGuard.guard('channels/telegram/completion-summary', api, () => {
|
|
33
|
+
// ── reply_dispatch: finalize card when Savvy sends its reply ──────────
|
|
34
|
+
api.on('reply_dispatch', (event) => {
|
|
35
|
+
const ev = event;
|
|
36
|
+
const sk = ev.sessionKey;
|
|
37
|
+
if (!sk)
|
|
38
|
+
return;
|
|
39
|
+
const entry = activeSavvyCards.get(sk);
|
|
40
|
+
if (!entry)
|
|
41
|
+
return;
|
|
42
|
+
// Clean up bridge + stall timer
|
|
43
|
+
if (entry._bridgeCleanup) {
|
|
44
|
+
entry._bridgeCleanup();
|
|
45
|
+
entry._bridgeCleanup = null;
|
|
46
|
+
}
|
|
47
|
+
if (entry._stallTimer)
|
|
48
|
+
clearInterval(entry._stallTimer);
|
|
49
|
+
// If debounce timer never fired, skip card entirely (fast turn)
|
|
50
|
+
if (entry._initialTimer && !entry._initialSent) {
|
|
51
|
+
clearTimeout(entry._initialTimer);
|
|
52
|
+
if (entry._typingInterval) {
|
|
53
|
+
clearInterval(entry._typingInterval);
|
|
54
|
+
entry._typingInterval = null;
|
|
55
|
+
}
|
|
56
|
+
activeSavvyChatIds.delete(entry.chatId);
|
|
57
|
+
activeSavvyCards.delete(sk);
|
|
58
|
+
logger.info(`${PLUGIN_TAG} [savvy-card] Fast turn — skipped card for sessionKey=${sk}`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// Flush pending throttled edit — final render supersedes
|
|
62
|
+
if (entry._pendingEdit?.timer) {
|
|
63
|
+
clearTimeout(entry._pendingEdit.timer);
|
|
64
|
+
entry._pendingEdit = null;
|
|
65
|
+
}
|
|
66
|
+
entry._lastEditAt = 0;
|
|
67
|
+
if (entry._typingInterval) {
|
|
68
|
+
clearInterval(entry._typingInterval);
|
|
69
|
+
entry._typingInterval = null;
|
|
70
|
+
}
|
|
71
|
+
entry.state.markDone();
|
|
72
|
+
if (generateNextSteps) {
|
|
73
|
+
// TODO(P2): SavvyCardState type lives in tool-tracker — cast via unknown
|
|
74
|
+
const steps = generateNextSteps(entry.state.getState());
|
|
75
|
+
entry.state.setNextSteps(steps);
|
|
76
|
+
}
|
|
77
|
+
const finalState = entry.state.getState();
|
|
78
|
+
const _render = renderSavvyCard;
|
|
79
|
+
if (_render) {
|
|
80
|
+
const cardText = _render(finalState);
|
|
81
|
+
const markup = savvyButtons(finalState, sk, entry.chatId);
|
|
82
|
+
entry.queue.updateCard(cardText, markup);
|
|
83
|
+
}
|
|
84
|
+
activeSavvyChatIds.delete(entry.chatId);
|
|
85
|
+
activeSavvyCards.delete(sk);
|
|
86
|
+
if (savvyQuotaFetcher && activeSavvyCards.size === 0) {
|
|
87
|
+
savvyQuotaFetcher.stopPolling();
|
|
88
|
+
setSavvyQuotaFetcher(null);
|
|
89
|
+
}
|
|
90
|
+
// Auto-collapse after delay (skip error-heavy 🔴 cards)
|
|
91
|
+
if (!finalState.delegated && finalState.qualityScore?.emoji !== '🔴') {
|
|
92
|
+
const collapseDelay = finalState.qualityScore?.emoji === '🟡' ? 30000 : 20000;
|
|
93
|
+
const collapseQueue = entry.queue;
|
|
94
|
+
const collapseEntry = entry;
|
|
95
|
+
setTimeout(() => {
|
|
96
|
+
const elapsedSec = Math.round((finalState.elapsedMs || 0) / 1000);
|
|
97
|
+
const qualEmoji = finalState.qualityScore?.emoji || '✅';
|
|
98
|
+
let collapsed;
|
|
99
|
+
if (finalState.filesModified && finalState.filesModified.length > 0) {
|
|
100
|
+
const fileList = finalState.filesModified.slice(0, 3).join(', ');
|
|
101
|
+
const extra = finalState.filesModified.length > 3 ? ` \\+${finalState.filesModified.length - 3}` : '';
|
|
102
|
+
collapsed = `${qualEmoji} *Savvy* — edited ${fileList}${extra} \\(${elapsedSec}s\\)`;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
collapsed = `${qualEmoji} *Savvy* — ${finalState.toolCount} tools in ${elapsedSec}s`;
|
|
106
|
+
}
|
|
107
|
+
collapseQueue.updateCard(collapsed, { inline_keyboard: [] });
|
|
108
|
+
setTimeout(() => {
|
|
109
|
+
if (collapseQueue.cardMessageId) {
|
|
110
|
+
telegramApi('deleteMessage', {
|
|
111
|
+
chat_id: collapseEntry.chatId,
|
|
112
|
+
message_id: collapseQueue.cardMessageId,
|
|
113
|
+
}).catch(() => { });
|
|
114
|
+
}
|
|
115
|
+
}, 5 * 60 * 1000);
|
|
116
|
+
}, collapseDelay);
|
|
117
|
+
}
|
|
118
|
+
// Completion reaction on card
|
|
119
|
+
const cardMsgId = entry.queue.cardMessageId;
|
|
120
|
+
if (cardMsgId) {
|
|
121
|
+
const reactionEmoji = finalState.qualityScore?.emoji === '🔴' ? '😬'
|
|
122
|
+
: finalState.qualityScore?.emoji === '🟡' ? '🤔'
|
|
123
|
+
: '👍';
|
|
124
|
+
telegramApi('setMessageReaction', {
|
|
125
|
+
chat_id: entry.chatId,
|
|
126
|
+
message_id: cardMsgId,
|
|
127
|
+
reaction: [{ type: 'emoji', emoji: reactionEmoji }],
|
|
128
|
+
}).catch(() => { });
|
|
129
|
+
if (finalState.qualityScore?.emoji === '🔴') {
|
|
130
|
+
telegramApi('pinChatMessage', {
|
|
131
|
+
chat_id: entry.chatId,
|
|
132
|
+
message_id: cardMsgId,
|
|
133
|
+
disable_notification: true,
|
|
134
|
+
}).catch(() => { });
|
|
135
|
+
lastPinnedErrorCard.set(entry.chatId, cardMsgId);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Auto-unpin previous error card on clean follow-up
|
|
139
|
+
if (finalState.qualityScore?.emoji === '🟢') {
|
|
140
|
+
const pinnedId = lastPinnedErrorCard.get(entry.chatId);
|
|
141
|
+
if (pinnedId) {
|
|
142
|
+
telegramApi('unpinChatMessage', {
|
|
143
|
+
chat_id: entry.chatId,
|
|
144
|
+
message_id: pinnedId,
|
|
145
|
+
}).catch(() => { });
|
|
146
|
+
lastPinnedErrorCard.delete(entry.chatId);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Persist card summary to daily JSONL log
|
|
150
|
+
try {
|
|
151
|
+
const dayStr = new Date().toISOString().slice(0, 10);
|
|
152
|
+
mkdirSync(SAVVY_LOG_DIR, { recursive: true });
|
|
153
|
+
appendFileSync(`${SAVVY_LOG_DIR}/${dayStr}.jsonl`, JSON.stringify({
|
|
154
|
+
ts: Date.now(),
|
|
155
|
+
sessionKey: sk,
|
|
156
|
+
chatId: entry.chatId,
|
|
157
|
+
cardMessageId: cardMsgId || null,
|
|
158
|
+
toolCount: finalState.toolCount,
|
|
159
|
+
errorCount: finalState.errorCount,
|
|
160
|
+
elapsedMs: finalState.elapsedMs,
|
|
161
|
+
filesModified: finalState.filesModified,
|
|
162
|
+
qualityScore: finalState.qualityScore,
|
|
163
|
+
status: finalState.status,
|
|
164
|
+
}) + '\n');
|
|
165
|
+
}
|
|
166
|
+
catch (e) {
|
|
167
|
+
logger.warn(`${PLUGIN_TAG} Failed to persist Savvy card summary: ${e.message}`);
|
|
168
|
+
}
|
|
169
|
+
// Update session history cache for next card's badge
|
|
170
|
+
sessionHistoryCache.set(String(entry.chatId), {
|
|
171
|
+
toolCount: finalState.toolCount,
|
|
172
|
+
elapsedMs: finalState.elapsedMs,
|
|
173
|
+
qualityEmoji: finalState.qualityScore?.emoji || '✅',
|
|
174
|
+
ts: Date.now(),
|
|
175
|
+
});
|
|
176
|
+
if (sessionHistoryCache.size > MAX_HISTORY_CACHE) {
|
|
177
|
+
const oldest = sessionHistoryCache.keys().next().value;
|
|
178
|
+
if (oldest)
|
|
179
|
+
sessionHistoryCache.delete(oldest);
|
|
180
|
+
}
|
|
181
|
+
logger.info(`${PLUGIN_TAG} [savvy-card] Done → finalized sessionKey=${sk}`);
|
|
182
|
+
});
|
|
183
|
+
logger.info(`${PLUGIN_TAG} completion-summary hooks registered (reply_dispatch)`);
|
|
184
|
+
}); // end defaultRegisterGuard.guard
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=completion-summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completion-summary.js","sourceRoot":"","sources":["../../../../src/channels/telegram/completion-summary.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* error-renderer — send formatted errors to Telegram via the existing queue.
|
|
3
|
+
*
|
|
4
|
+
* Takes a FormattedError (from error-formatter) and dispatches it via the
|
|
5
|
+
* live-card's telegramApi, with per-code 1h dedup to avoid noise.
|
|
6
|
+
* Reads BOT_TOKEN and chat routing from the live-card module's shared state.
|
|
7
|
+
*/
|
|
8
|
+
import type { FormattedError, Severity } from '../../lib/error-formatter.js';
|
|
9
|
+
/** Test-only reset. */
|
|
10
|
+
export declare function _resetDedupForTests(): void;
|
|
11
|
+
export interface RenderOptions {
|
|
12
|
+
/** Override chat ID (e.g. session-specific routing). */
|
|
13
|
+
chatId?: string;
|
|
14
|
+
/** Thread ID for Telegram topic groups. */
|
|
15
|
+
threadId?: string;
|
|
16
|
+
/** Skip dedup check — force send regardless of window. */
|
|
17
|
+
forceSend?: boolean;
|
|
18
|
+
/** Write to drift jsonl as well. Defaults to true for warning+ severity. */
|
|
19
|
+
writeJsonl?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Send a FormattedError to Telegram.
|
|
23
|
+
*
|
|
24
|
+
* Returns true if the message was sent, false if deduped/silenced/no-token.
|
|
25
|
+
*/
|
|
26
|
+
export declare function renderError(formatted: FormattedError, opts?: RenderOptions): Promise<boolean>;
|
|
27
|
+
/** Only send if severity is 'critical' or 'error'. */
|
|
28
|
+
export declare function renderErrorIfSevere(formatted: FormattedError, opts?: RenderOptions): Promise<boolean>;
|
|
29
|
+
export type { Severity };
|
|
30
|
+
//# sourceMappingURL=error-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-renderer.d.ts","sourceRoot":"","sources":["../../../../src/channels/telegram/error-renderer.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAa,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAkCxF,uBAAuB;AACvB,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AA6BD,MAAM,WAAW,aAAa;IAC5B,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,cAAc,EACzB,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,OAAO,CAAC,CAqDlB;AAID,sDAAsD;AACtD,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,cAAc,EACzB,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,OAAO,CAAC,CAQlB;AAID,YAAY,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// phase: 4 | pillar: 2 | agent: P2.B
|
|
2
|
+
/**
|
|
3
|
+
* error-renderer — send formatted errors to Telegram via the existing queue.
|
|
4
|
+
*
|
|
5
|
+
* Takes a FormattedError (from error-formatter) and dispatches it via the
|
|
6
|
+
* live-card's telegramApi, with per-code 1h dedup to avoid noise.
|
|
7
|
+
* Reads BOT_TOKEN and chat routing from the live-card module's shared state.
|
|
8
|
+
*/
|
|
9
|
+
import { appendFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
import { homedir } from 'node:os';
|
|
12
|
+
import { telegramApi, BOT_TOKEN } from './live-card.js';
|
|
13
|
+
// ─── Config ───────────────────────────────────────────────────────────────────
|
|
14
|
+
/** Milliseconds between repeated Telegram alerts for the same error code. */
|
|
15
|
+
function getDedupWindowMs() {
|
|
16
|
+
const v = process.env.OPENCLAW_CC_OPENCLAW_DRIFT_DEDUPE_WINDOW_MS;
|
|
17
|
+
const n = v !== undefined ? parseInt(v, 10) : NaN;
|
|
18
|
+
return Number.isFinite(n) && n > 0 ? n : 3_600_000; // default 1h
|
|
19
|
+
}
|
|
20
|
+
/** Path for drift/error jsonl log. */
|
|
21
|
+
const DRIFT_JSONL_PATH = join(homedir(), '.openclaw', 'workspace', 'memory', 'cc-openclaw-drift.jsonl');
|
|
22
|
+
// ─── Dedup state ─────────────────────────────────────────────────────────────
|
|
23
|
+
/**
|
|
24
|
+
* Per-code last-sent timestamps for dedup. Module-level singleton so it
|
|
25
|
+
* persists across calls within a process lifetime.
|
|
26
|
+
*/
|
|
27
|
+
const _lastSentAt = new Map();
|
|
28
|
+
/** Returns true if this code was sent within the dedup window. */
|
|
29
|
+
function isDupe(code) {
|
|
30
|
+
const last = _lastSentAt.get(code);
|
|
31
|
+
if (last === undefined)
|
|
32
|
+
return false;
|
|
33
|
+
return Date.now() - last < getDedupWindowMs();
|
|
34
|
+
}
|
|
35
|
+
/** Mark a code as sent now. */
|
|
36
|
+
function markSent(code) {
|
|
37
|
+
_lastSentAt.set(code, Date.now());
|
|
38
|
+
}
|
|
39
|
+
/** Test-only reset. */
|
|
40
|
+
export function _resetDedupForTests() {
|
|
41
|
+
_lastSentAt.clear();
|
|
42
|
+
}
|
|
43
|
+
// ─── Chat ID resolution ───────────────────────────────────────────────────────
|
|
44
|
+
/**
|
|
45
|
+
* Resolve the Telegram chat ID to send error alerts to.
|
|
46
|
+
* Prefers OPENCLAW_ERROR_CHAT_ID env var, falls back to
|
|
47
|
+
* OPENCLAW_ADMIN_CHAT_ID, falls back to null (silenced).
|
|
48
|
+
*/
|
|
49
|
+
function resolveErrorChatId() {
|
|
50
|
+
const v = process.env.OPENCLAW_ERROR_CHAT_ID || process.env.OPENCLAW_ADMIN_CHAT_ID;
|
|
51
|
+
return v && v.trim() ? v.trim() : null;
|
|
52
|
+
}
|
|
53
|
+
// ─── JSONL writer ─────────────────────────────────────────────────────────────
|
|
54
|
+
function writeDriftJsonl(formatted) {
|
|
55
|
+
try {
|
|
56
|
+
const dir = join(homedir(), '.openclaw', 'workspace', 'memory');
|
|
57
|
+
if (!existsSync(dir))
|
|
58
|
+
mkdirSync(dir, { recursive: true });
|
|
59
|
+
appendFileSync(DRIFT_JSONL_PATH, JSON.stringify(formatted.jsonlRow) + '\n');
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
// Must never crash the plugin — stderr only
|
|
63
|
+
process.stderr.write(`[cc-openclaw/error-renderer] jsonl write failed: ${err.message}\n`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Send a FormattedError to Telegram.
|
|
68
|
+
*
|
|
69
|
+
* Returns true if the message was sent, false if deduped/silenced/no-token.
|
|
70
|
+
*/
|
|
71
|
+
export async function renderError(formatted, opts = {}) {
|
|
72
|
+
const { jsonlRow, telegramText } = formatted;
|
|
73
|
+
// Always write jsonl for warning/critical/error unless explicitly disabled
|
|
74
|
+
const shouldWriteJsonl = opts.writeJsonl !== false && jsonlRow.severity !== 'info';
|
|
75
|
+
if (shouldWriteJsonl) {
|
|
76
|
+
writeDriftJsonl(formatted);
|
|
77
|
+
}
|
|
78
|
+
// Check dedup
|
|
79
|
+
if (!opts.forceSend && isDupe(jsonlRow.code)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
// Resolve destination
|
|
83
|
+
const chatId = opts.chatId ?? resolveErrorChatId();
|
|
84
|
+
if (!chatId)
|
|
85
|
+
return false;
|
|
86
|
+
// Require bot token
|
|
87
|
+
if (!BOT_TOKEN)
|
|
88
|
+
return false;
|
|
89
|
+
const params = {
|
|
90
|
+
chat_id: chatId,
|
|
91
|
+
text: telegramText,
|
|
92
|
+
parse_mode: 'MarkdownV2',
|
|
93
|
+
};
|
|
94
|
+
if (opts.threadId) {
|
|
95
|
+
params.message_thread_id = opts.threadId;
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
const res = await telegramApi('sendMessage', params);
|
|
99
|
+
if (res.ok) {
|
|
100
|
+
markSent(jsonlRow.code);
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
// If MarkdownV2 fails (parse error), fall back to plain text
|
|
104
|
+
if (res.error_code === 400) {
|
|
105
|
+
const fallback = await telegramApi('sendMessage', {
|
|
106
|
+
chat_id: chatId,
|
|
107
|
+
text: `${jsonlRow.code}: ${jsonlRow.message} (${jsonlRow.ts.slice(0, 19)})`,
|
|
108
|
+
...(opts.threadId ? { message_thread_id: opts.threadId } : {}),
|
|
109
|
+
});
|
|
110
|
+
if (fallback.ok) {
|
|
111
|
+
markSent(jsonlRow.code);
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
process.stderr.write(`[cc-openclaw/error-renderer] send failed: ${err.message}\n`);
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// ─── Severity-filtered convenience ───────────────────────────────────────────
|
|
123
|
+
/** Only send if severity is 'critical' or 'error'. */
|
|
124
|
+
export async function renderErrorIfSevere(formatted, opts = {}) {
|
|
125
|
+
const sev = formatted.jsonlRow.severity;
|
|
126
|
+
if (sev === 'info' || sev === 'warning') {
|
|
127
|
+
// Still write jsonl
|
|
128
|
+
writeDriftJsonl(formatted);
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
return renderError(formatted, opts);
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=error-renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-renderer.js","sourceRoot":"","sources":["../../../../src/channels/telegram/error-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* telegram event-reducer — TypeScript port of savvy-claude-code/ux-bridge.js
|
|
3
|
+
*
|
|
4
|
+
* Central register() that wires all remaining api.on() hooks:
|
|
5
|
+
* before_dispatch ×4 — /quota command, /sessions command, claude-local UX
|
|
6
|
+
* feed, callback_query routing
|
|
7
|
+
* before_model_resolve — per-chat model override (F5)
|
|
8
|
+
* before_tool_call — Stage 4 gateway UX metadata injection
|
|
9
|
+
* MiniMax usage tracking (before_dispatch)
|
|
10
|
+
*
|
|
11
|
+
* Depends on: live-card, tool-tracker, completion-summary, state-machine
|
|
12
|
+
* (all must be registered before or alongside this module).
|
|
13
|
+
*
|
|
14
|
+
* Source lines: 1042–1615 of ux-bridge.js
|
|
15
|
+
*/
|
|
16
|
+
export interface PluginApi {
|
|
17
|
+
on(event: string, handler: (...args: unknown[]) => unknown | Promise<unknown>): void;
|
|
18
|
+
logger?: Console;
|
|
19
|
+
config?: Record<string, unknown>;
|
|
20
|
+
runtime?: {
|
|
21
|
+
subagent?: {
|
|
22
|
+
run?(opts: Record<string, unknown>): Promise<{
|
|
23
|
+
runId?: string;
|
|
24
|
+
}>;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Register all event-reducer hooks (command dispatch, model override,
|
|
30
|
+
* callback routing, Stage 4 injection).
|
|
31
|
+
* Idempotent — subsequent calls are no-ops.
|
|
32
|
+
*/
|
|
33
|
+
export declare function register(api: PluginApi): void;
|
|
34
|
+
//# sourceMappingURL=event-reducer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-reducer.d.ts","sourceRoot":"","sources":["../../../../src/channels/telegram/event-reducer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA4BH,MAAM,WAAW,SAAS;IACxB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IACrF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE;YACT,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;gBAAE,KAAK,CAAC,EAAE,MAAM,CAAA;aAAE,CAAC,CAAC;SAClE,CAAC;KACH,CAAC;CACH;AA2CD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CA+hB7C"}
|