@a1hvdy/cc-openclaw 0.26.4 → 0.26.6

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.
Files changed (444) hide show
  1. package/dist/src/channels/adapter.js +0 -1
  2. package/dist/src/channels/telegram-mirror/askuser.js +16 -10
  3. package/dist/src/channels/telegram-mirror/burst-accumulator.js +0 -1
  4. package/dist/src/channels/telegram-mirror/callback-mapping.js +0 -1
  5. package/dist/src/channels/telegram-mirror/card-renderer.js +63 -21
  6. package/dist/src/channels/telegram-mirror/card-state.js +0 -1
  7. package/dist/src/channels/telegram-mirror/commands.js +0 -1
  8. package/dist/src/channels/telegram-mirror/compose-buffer.js +0 -1
  9. package/dist/src/channels/telegram-mirror/cost-views.js +0 -1
  10. package/dist/src/channels/telegram-mirror/failure/callback-data-overflow.js +0 -1
  11. package/dist/src/channels/telegram-mirror/failure/gateway-down.js +0 -1
  12. package/dist/src/channels/telegram-mirror/failure/in-flight-conflict.js +0 -1
  13. package/dist/src/channels/telegram-mirror/failure/index.js +0 -1
  14. package/dist/src/channels/telegram-mirror/failure/model-5xx.js +0 -1
  15. package/dist/src/channels/telegram-mirror/failure/network-blip.js +0 -1
  16. package/dist/src/channels/telegram-mirror/failure/pool-exhausted-fallback.js +0 -1
  17. package/dist/src/channels/telegram-mirror/failure/rate-limit.js +0 -1
  18. package/dist/src/channels/telegram-mirror/failure/returning-after-24h.js +0 -1
  19. package/dist/src/channels/telegram-mirror/failure/types.js +0 -1
  20. package/dist/src/channels/telegram-mirror/inbound-handler.js +0 -1
  21. package/dist/src/channels/telegram-mirror/index.js +0 -1
  22. package/dist/src/channels/telegram-mirror/plan-attachment.js +0 -1
  23. package/dist/src/channels/telegram-mirror/quota-reader.js +0 -1
  24. package/dist/src/channels/telegram-mirror/sessions-keyboard.js +0 -1
  25. package/dist/src/channels/telegram-mirror/soak-log.js +0 -1
  26. package/dist/src/channels/telegram-mirror/state-machine.js +21 -2
  27. package/dist/src/channels/telegram-mirror/status-line.js +0 -1
  28. package/dist/src/channels/telegram-mirror/sync-commands.js +0 -1
  29. package/dist/src/channels/telegram-mirror/threshold-watcher.js +0 -1
  30. package/dist/src/channels/telegram-mirror/turn-bridge.js +21 -2
  31. package/dist/src/cli/checks/bridge-wiring.js +0 -1
  32. package/dist/src/cli/checks/config-schema.js +0 -1
  33. package/dist/src/cli/checks/critical-openclaw-json-keys.js +0 -1
  34. package/dist/src/cli/checks/install-path.js +0 -1
  35. package/dist/src/cli/checks/patch-scaffold.js +0 -1
  36. package/dist/src/cli/doctor.js +0 -1
  37. package/dist/src/cli/index.js +0 -1
  38. package/dist/src/cli/migrate.js +0 -1
  39. package/dist/src/command-router/cc-handler.js +0 -1
  40. package/dist/src/command-router/index.js +0 -1
  41. package/dist/src/command-router/launch-policy.js +0 -1
  42. package/dist/src/command-router/resume-policy.js +0 -1
  43. package/dist/src/command-router/turn-formatter.js +0 -1
  44. package/dist/src/config/drift-detector.js +0 -1
  45. package/dist/src/config/loader.js +0 -1
  46. package/dist/src/config/schema.js +0 -1
  47. package/dist/src/constants.js +0 -1
  48. package/dist/src/council/build-agent-prompt.js +0 -1
  49. package/dist/src/council/cleanup-worktrees.js +0 -1
  50. package/dist/src/council/consensus.js +0 -1
  51. package/dist/src/council/council.js +0 -1
  52. package/dist/src/council/index.js +0 -1
  53. package/dist/src/council/system-prompt.js +0 -1
  54. package/dist/src/council/write-worktree-claude-md.js +0 -1
  55. package/dist/src/engines/base-oneshot-session.js +0 -1
  56. package/dist/src/engines/heartbeat-guard.js +0 -1
  57. package/dist/src/engines/index.js +0 -1
  58. package/dist/src/engines/persistent-codex-session.js +0 -1
  59. package/dist/src/engines/persistent-cursor-session.js +0 -1
  60. package/dist/src/engines/persistent-custom-session.js +0 -1
  61. package/dist/src/engines/persistent-gemini-session.js +0 -1
  62. package/dist/src/engines/persistent-session.js +30 -1
  63. package/dist/src/engines/resolve-bin.js +0 -1
  64. package/dist/src/engines/subprocess-pool.js +0 -1
  65. package/dist/src/health/handler.js +0 -1
  66. package/dist/src/health/index.js +0 -1
  67. package/dist/src/health/metrics.js +0 -1
  68. package/dist/src/index.js +0 -1
  69. package/dist/src/lib/auto-recovery.js +0 -1
  70. package/dist/src/lib/cache-parity.js +0 -1
  71. package/dist/src/lib/circuit-breaker.js +0 -1
  72. package/dist/src/lib/config-service.js +0 -1
  73. package/dist/src/lib/config.js +0 -1
  74. package/dist/src/lib/cost-rollup.js +0 -1
  75. package/dist/src/lib/debounce.js +0 -1
  76. package/dist/src/lib/debug-tap.js +0 -1
  77. package/dist/src/lib/domain-error.js +0 -1
  78. package/dist/src/lib/drift-detector.js +0 -1
  79. package/dist/src/lib/env-overrides.js +0 -1
  80. package/dist/src/lib/error-formatter.js +0 -1
  81. package/dist/src/lib/error-renderer.js +0 -1
  82. package/dist/src/lib/heartbeat-config.js +0 -1
  83. package/dist/src/lib/heartbeat-workaround.js +0 -1
  84. package/dist/src/lib/http-agent.js +0 -1
  85. package/dist/src/lib/index.js +0 -1
  86. package/dist/src/lib/json-array.js +0 -1
  87. package/dist/src/lib/markdown-to-mdv2.js +0 -1
  88. package/dist/src/lib/markdown-v2.js +0 -1
  89. package/dist/src/lib/perf/async-compact.js +0 -1
  90. package/dist/src/lib/perf/direct-sdk.js +0 -1
  91. package/dist/src/lib/perf/haiku-route.js +0 -1
  92. package/dist/src/lib/perf/predictive-continuation.js +0 -1
  93. package/dist/src/lib/perf/read-batch.js +0 -1
  94. package/dist/src/lib/perf/skill-list-collapse.js +0 -1
  95. package/dist/src/lib/perf/speculative-bubble.js +0 -1
  96. package/dist/src/lib/perf/typing-prefetch.js +0 -1
  97. package/dist/src/lib/register-guard.js +0 -1
  98. package/dist/src/lib/req-shape-log.js +0 -1
  99. package/dist/src/lib/safe-upstream-probes.js +0 -1
  100. package/dist/src/lib/session-registry.js +0 -1
  101. package/dist/src/lib/spawn-async.js +0 -1
  102. package/dist/src/lib/stale-pid-files.js +0 -1
  103. package/dist/src/lib/status-tee-reader.js +0 -1
  104. package/dist/src/lib/sysprompt-strip.js +0 -1
  105. package/dist/src/lib/telegram-bot-api.js +0 -1
  106. package/dist/src/lib/telemetry.js +0 -1
  107. package/dist/src/lib/test-mode.js +0 -1
  108. package/dist/src/lib/trajectory.js +0 -1
  109. package/dist/src/lib/vendor-paths.js +0 -1
  110. package/dist/src/lifecycle/boot.js +0 -1
  111. package/dist/src/lifecycle/patch-manifest.js +0 -1
  112. package/dist/src/lifecycle/phase-import-upstream.js +0 -1
  113. package/dist/src/lifecycle/phase-install-patches.js +0 -1
  114. package/dist/src/lifecycle/phase-schedule-jobs.js +0 -1
  115. package/dist/src/lifecycle/phase-start-server.js +0 -1
  116. package/dist/src/lifecycle/phase-validate-config.js +0 -1
  117. package/dist/src/lifecycle/phase-validate-upstream.js +0 -1
  118. package/dist/src/lifecycle/phase-wire-handlers.js +0 -1
  119. package/dist/src/lifecycle/safe-restart.js +0 -1
  120. package/dist/src/logger.js +0 -1
  121. package/dist/src/mcp/bridge.js +0 -1
  122. package/dist/src/mcp/index.js +0 -1
  123. package/dist/src/models.js +0 -1
  124. package/dist/src/observability/event-bus.js +0 -1
  125. package/dist/src/observability/get-event-bus.js +0 -1
  126. package/dist/src/observability/observability-service.js +0 -1
  127. package/dist/src/observability/perf-telemetry.js +0 -1
  128. package/dist/src/observability/subscribers/metrics.js +0 -1
  129. package/dist/src/observability/subscribers/session-capture.js +0 -1
  130. package/dist/src/openai-compat/bridges/allowlist.js +0 -1
  131. package/dist/src/openai-compat/bridges/factory.js +0 -1
  132. package/dist/src/openai-compat/bridges/media-bridge.js +0 -1
  133. package/dist/src/openai-compat/bridges/openclaw-api-shim.js +0 -1
  134. package/dist/src/openai-compat/bridges/openclaw-native-tools.js +0 -1
  135. package/dist/src/openai-compat/bridges/openclaw-tool-registry.js +0 -1
  136. package/dist/src/openai-compat/bridges/tts-media-bridge.js +0 -1
  137. package/dist/src/openai-compat/cli-stream-parser.js +0 -1
  138. package/dist/src/openai-compat/index.js +0 -1
  139. package/dist/src/openai-compat/message-extractor.js +0 -1
  140. package/dist/src/openai-compat/mode-flags.js +0 -1
  141. package/dist/src/openai-compat/non-streaming-handler.js +4 -2
  142. package/dist/src/openai-compat/openai-chunk-types.js +0 -1
  143. package/dist/src/openai-compat/openai-compat.js +0 -1
  144. package/dist/src/openai-compat/openai-types.js +0 -1
  145. package/dist/src/openai-compat/parse-route-body.js +0 -1
  146. package/dist/src/openai-compat/prompts.js +0 -1
  147. package/dist/src/openai-compat/response-formatter.js +0 -1
  148. package/dist/src/openai-compat/session-key-resolver.js +0 -1
  149. package/dist/src/openai-compat/skill-resolver.js +0 -1
  150. package/dist/src/openai-compat/sse-translator.js +0 -1
  151. package/dist/src/openai-compat/status-reporter.js +0 -1
  152. package/dist/src/openai-compat/streaming-handler.js +6 -2
  153. package/dist/src/openai-compat/tool-calls-parser.js +0 -1
  154. package/dist/src/openai-compat/tool-results-serializer.js +0 -1
  155. package/dist/src/openai-compat/tts-rule.js +0 -1
  156. package/dist/src/openai-compat/voice-recovery.js +0 -1
  157. package/dist/src/patches/cache-parity-registry.js +0 -1
  158. package/dist/src/patches/claude-md-injection.js +0 -1
  159. package/dist/src/patches/cwd-redirect.js +0 -1
  160. package/dist/src/patches/embedded-server-route.js +0 -1
  161. package/dist/src/patches/pricing-overrides.js +0 -1
  162. package/dist/src/patches/resume-registry-restore.js +0 -1
  163. package/dist/src/patches/session-pid-tracking.js +0 -1
  164. package/dist/src/patches/sysprompt-strip.js +0 -1
  165. package/dist/src/patches/tools-restoration.js +0 -1
  166. package/dist/src/persistence/migration-v0.js +0 -1
  167. package/dist/src/persistence/session-registry.js +0 -1
  168. package/dist/src/persistence/snapshot.js +0 -1
  169. package/dist/src/persistence/wal.js +0 -1
  170. package/dist/src/proxy/anthropic-adapter.js +0 -1
  171. package/dist/src/proxy/handler.js +0 -1
  172. package/dist/src/proxy/index.js +0 -1
  173. package/dist/src/proxy/schema-cleaner.js +0 -1
  174. package/dist/src/proxy/thought-cache.js +0 -1
  175. package/dist/src/session/embedded-server.js +0 -1
  176. package/dist/src/session/inbox-manager.js +0 -1
  177. package/dist/src/session/index.js +0 -1
  178. package/dist/src/session/persisted-sessions.js +0 -1
  179. package/dist/src/session/session-manager.js +0 -1
  180. package/dist/src/session/watchdogs.js +0 -1
  181. package/dist/src/session-bootstrap/boot-self-heal.js +0 -1
  182. package/dist/src/session-bootstrap/cwd-patch.js +0 -1
  183. package/dist/src/session-bootstrap/index.js +0 -1
  184. package/dist/src/session-bootstrap/resume-registry.js +0 -1
  185. package/dist/src/session-bootstrap/session-hygiene.js +0 -1
  186. package/dist/src/session-bootstrap/sysprompt-strip.js +0 -1
  187. package/dist/src/session-bootstrap/think-conflict-resolver.js +0 -1
  188. package/dist/src/types/index.js +0 -1
  189. package/dist/src/types/route.js +0 -1
  190. package/dist/src/types/runtime-config.js +0 -1
  191. package/dist/src/types/session.js +0 -1
  192. package/dist/src/types/sse.js +0 -1
  193. package/dist/src/types/tool-bridge.js +0 -1
  194. package/dist/src/types/upstream.js +0 -1
  195. package/dist/src/types.js +0 -1
  196. package/dist/src/validation.js +0 -1
  197. package/package.json +1 -1
  198. package/dist/src/channels/adapter.js.map +0 -1
  199. package/dist/src/channels/telegram/card-renderer.d.ts +0 -80
  200. package/dist/src/channels/telegram/card-renderer.js +0 -169
  201. package/dist/src/channels/telegram/card-renderer.js.map +0 -1
  202. package/dist/src/channels/telegram/completion-summary.d.ts +0 -21
  203. package/dist/src/channels/telegram/completion-summary.js +0 -218
  204. package/dist/src/channels/telegram/completion-summary.js.map +0 -1
  205. package/dist/src/channels/telegram/edit-cadence.d.ts +0 -37
  206. package/dist/src/channels/telegram/edit-cadence.js +0 -50
  207. package/dist/src/channels/telegram/edit-cadence.js.map +0 -1
  208. package/dist/src/channels/telegram/error-renderer.d.ts +0 -29
  209. package/dist/src/channels/telegram/error-renderer.js +0 -133
  210. package/dist/src/channels/telegram/error-renderer.js.map +0 -1
  211. package/dist/src/channels/telegram/event-reducer.d.ts +0 -33
  212. package/dist/src/channels/telegram/event-reducer.js +0 -647
  213. package/dist/src/channels/telegram/event-reducer.js.map +0 -1
  214. package/dist/src/channels/telegram/format-helpers.d.ts +0 -20
  215. package/dist/src/channels/telegram/format-helpers.js +0 -34
  216. package/dist/src/channels/telegram/format-helpers.js.map +0 -1
  217. package/dist/src/channels/telegram/index.d.ts +0 -13
  218. package/dist/src/channels/telegram/index.js +0 -14
  219. package/dist/src/channels/telegram/index.js.map +0 -1
  220. package/dist/src/channels/telegram/injector.d.ts +0 -53
  221. package/dist/src/channels/telegram/injector.js +0 -271
  222. package/dist/src/channels/telegram/injector.js.map +0 -1
  223. package/dist/src/channels/telegram/insight-formatter.d.ts +0 -36
  224. package/dist/src/channels/telegram/insight-formatter.js +0 -36
  225. package/dist/src/channels/telegram/insight-formatter.js.map +0 -1
  226. package/dist/src/channels/telegram/live-card.d.ts +0 -185
  227. package/dist/src/channels/telegram/live-card.js +0 -868
  228. package/dist/src/channels/telegram/live-card.js.map +0 -1
  229. package/dist/src/channels/telegram/logger.d.ts +0 -10
  230. package/dist/src/channels/telegram/logger.js +0 -13
  231. package/dist/src/channels/telegram/logger.js.map +0 -1
  232. package/dist/src/channels/telegram/result-preview.d.ts +0 -12
  233. package/dist/src/channels/telegram/result-preview.js +0 -48
  234. package/dist/src/channels/telegram/result-preview.js.map +0 -1
  235. package/dist/src/channels/telegram/speculative-bubble.d.ts +0 -33
  236. package/dist/src/channels/telegram/speculative-bubble.js +0 -42
  237. package/dist/src/channels/telegram/speculative-bubble.js.map +0 -1
  238. package/dist/src/channels/telegram/state-machine.d.ts +0 -22
  239. package/dist/src/channels/telegram/state-machine.js +0 -72
  240. package/dist/src/channels/telegram/state-machine.js.map +0 -1
  241. package/dist/src/channels/telegram/throttle-controller.d.ts +0 -88
  242. package/dist/src/channels/telegram/throttle-controller.js +0 -203
  243. package/dist/src/channels/telegram/throttle-controller.js.map +0 -1
  244. package/dist/src/channels/telegram/tool-tracker.d.ts +0 -149
  245. package/dist/src/channels/telegram/tool-tracker.js +0 -578
  246. package/dist/src/channels/telegram/tool-tracker.js.map +0 -1
  247. package/dist/src/channels/telegram-mirror/askuser.js.map +0 -1
  248. package/dist/src/channels/telegram-mirror/burst-accumulator.js.map +0 -1
  249. package/dist/src/channels/telegram-mirror/callback-mapping.js.map +0 -1
  250. package/dist/src/channels/telegram-mirror/card-renderer.js.map +0 -1
  251. package/dist/src/channels/telegram-mirror/card-state.js.map +0 -1
  252. package/dist/src/channels/telegram-mirror/commands.js.map +0 -1
  253. package/dist/src/channels/telegram-mirror/compose-buffer.js.map +0 -1
  254. package/dist/src/channels/telegram-mirror/cost-views.js.map +0 -1
  255. package/dist/src/channels/telegram-mirror/failure/callback-data-overflow.js.map +0 -1
  256. package/dist/src/channels/telegram-mirror/failure/gateway-down.js.map +0 -1
  257. package/dist/src/channels/telegram-mirror/failure/in-flight-conflict.js.map +0 -1
  258. package/dist/src/channels/telegram-mirror/failure/index.js.map +0 -1
  259. package/dist/src/channels/telegram-mirror/failure/model-5xx.js.map +0 -1
  260. package/dist/src/channels/telegram-mirror/failure/network-blip.js.map +0 -1
  261. package/dist/src/channels/telegram-mirror/failure/pool-exhausted-fallback.js.map +0 -1
  262. package/dist/src/channels/telegram-mirror/failure/rate-limit.js.map +0 -1
  263. package/dist/src/channels/telegram-mirror/failure/returning-after-24h.js.map +0 -1
  264. package/dist/src/channels/telegram-mirror/failure/types.js.map +0 -1
  265. package/dist/src/channels/telegram-mirror/inbound-handler.js.map +0 -1
  266. package/dist/src/channels/telegram-mirror/index.js.map +0 -1
  267. package/dist/src/channels/telegram-mirror/plan-attachment.js.map +0 -1
  268. package/dist/src/channels/telegram-mirror/quota-reader.js.map +0 -1
  269. package/dist/src/channels/telegram-mirror/sessions-keyboard.js.map +0 -1
  270. package/dist/src/channels/telegram-mirror/soak-log.js.map +0 -1
  271. package/dist/src/channels/telegram-mirror/state-machine.js.map +0 -1
  272. package/dist/src/channels/telegram-mirror/status-line.js.map +0 -1
  273. package/dist/src/channels/telegram-mirror/sync-commands.js.map +0 -1
  274. package/dist/src/channels/telegram-mirror/threshold-watcher.js.map +0 -1
  275. package/dist/src/channels/telegram-mirror/turn-bridge.js.map +0 -1
  276. package/dist/src/cli/checks/bridge-wiring.js.map +0 -1
  277. package/dist/src/cli/checks/config-schema.js.map +0 -1
  278. package/dist/src/cli/checks/critical-openclaw-json-keys.js.map +0 -1
  279. package/dist/src/cli/checks/install-path.js.map +0 -1
  280. package/dist/src/cli/checks/patch-scaffold.js.map +0 -1
  281. package/dist/src/cli/doctor.js.map +0 -1
  282. package/dist/src/cli/index.js.map +0 -1
  283. package/dist/src/cli/migrate.js.map +0 -1
  284. package/dist/src/command-router/cc-handler.js.map +0 -1
  285. package/dist/src/command-router/index.js.map +0 -1
  286. package/dist/src/command-router/launch-policy.js.map +0 -1
  287. package/dist/src/command-router/resume-policy.js.map +0 -1
  288. package/dist/src/command-router/turn-formatter.js.map +0 -1
  289. package/dist/src/config/drift-detector.js.map +0 -1
  290. package/dist/src/config/loader.js.map +0 -1
  291. package/dist/src/config/schema.js.map +0 -1
  292. package/dist/src/constants.js.map +0 -1
  293. package/dist/src/council/build-agent-prompt.js.map +0 -1
  294. package/dist/src/council/cleanup-worktrees.js.map +0 -1
  295. package/dist/src/council/consensus.js.map +0 -1
  296. package/dist/src/council/council.js.map +0 -1
  297. package/dist/src/council/index.js.map +0 -1
  298. package/dist/src/council/system-prompt.js.map +0 -1
  299. package/dist/src/council/write-worktree-claude-md.js.map +0 -1
  300. package/dist/src/engines/base-oneshot-session.js.map +0 -1
  301. package/dist/src/engines/heartbeat-guard.js.map +0 -1
  302. package/dist/src/engines/index.js.map +0 -1
  303. package/dist/src/engines/persistent-codex-session.js.map +0 -1
  304. package/dist/src/engines/persistent-cursor-session.js.map +0 -1
  305. package/dist/src/engines/persistent-custom-session.js.map +0 -1
  306. package/dist/src/engines/persistent-gemini-session.js.map +0 -1
  307. package/dist/src/engines/persistent-session.js.map +0 -1
  308. package/dist/src/engines/resolve-bin.js.map +0 -1
  309. package/dist/src/engines/subprocess-pool.js.map +0 -1
  310. package/dist/src/health/handler.js.map +0 -1
  311. package/dist/src/health/index.js.map +0 -1
  312. package/dist/src/health/metrics.js.map +0 -1
  313. package/dist/src/index.js.map +0 -1
  314. package/dist/src/lib/auto-recovery.js.map +0 -1
  315. package/dist/src/lib/cache-parity.js.map +0 -1
  316. package/dist/src/lib/circuit-breaker.js.map +0 -1
  317. package/dist/src/lib/config-service.js.map +0 -1
  318. package/dist/src/lib/config.js.map +0 -1
  319. package/dist/src/lib/cost-rollup.js.map +0 -1
  320. package/dist/src/lib/debounce.js.map +0 -1
  321. package/dist/src/lib/debug-tap.js.map +0 -1
  322. package/dist/src/lib/domain-error.js.map +0 -1
  323. package/dist/src/lib/drift-detector.js.map +0 -1
  324. package/dist/src/lib/env-overrides.js.map +0 -1
  325. package/dist/src/lib/error-formatter.js.map +0 -1
  326. package/dist/src/lib/error-renderer.js.map +0 -1
  327. package/dist/src/lib/heartbeat-config.js.map +0 -1
  328. package/dist/src/lib/heartbeat-workaround.js.map +0 -1
  329. package/dist/src/lib/http-agent.js.map +0 -1
  330. package/dist/src/lib/index.js.map +0 -1
  331. package/dist/src/lib/json-array.js.map +0 -1
  332. package/dist/src/lib/markdown-to-mdv2.js.map +0 -1
  333. package/dist/src/lib/markdown-v2.js.map +0 -1
  334. package/dist/src/lib/perf/async-compact.js.map +0 -1
  335. package/dist/src/lib/perf/direct-sdk.js.map +0 -1
  336. package/dist/src/lib/perf/haiku-route.js.map +0 -1
  337. package/dist/src/lib/perf/predictive-continuation.js.map +0 -1
  338. package/dist/src/lib/perf/read-batch.js.map +0 -1
  339. package/dist/src/lib/perf/skill-list-collapse.js.map +0 -1
  340. package/dist/src/lib/perf/speculative-bubble.js.map +0 -1
  341. package/dist/src/lib/perf/typing-prefetch.js.map +0 -1
  342. package/dist/src/lib/register-guard.js.map +0 -1
  343. package/dist/src/lib/req-shape-log.js.map +0 -1
  344. package/dist/src/lib/safe-upstream-probes.js.map +0 -1
  345. package/dist/src/lib/session-registry.js.map +0 -1
  346. package/dist/src/lib/spawn-async.js.map +0 -1
  347. package/dist/src/lib/stale-pid-files.js.map +0 -1
  348. package/dist/src/lib/status-tee-reader.js.map +0 -1
  349. package/dist/src/lib/sysprompt-strip.js.map +0 -1
  350. package/dist/src/lib/telegram-bot-api.js.map +0 -1
  351. package/dist/src/lib/telemetry.js.map +0 -1
  352. package/dist/src/lib/test-mode.js.map +0 -1
  353. package/dist/src/lib/trajectory.js.map +0 -1
  354. package/dist/src/lib/vendor-paths.js.map +0 -1
  355. package/dist/src/lifecycle/boot.js.map +0 -1
  356. package/dist/src/lifecycle/patch-manifest.js.map +0 -1
  357. package/dist/src/lifecycle/phase-import-upstream.js.map +0 -1
  358. package/dist/src/lifecycle/phase-install-patches.js.map +0 -1
  359. package/dist/src/lifecycle/phase-schedule-jobs.js.map +0 -1
  360. package/dist/src/lifecycle/phase-start-server.js.map +0 -1
  361. package/dist/src/lifecycle/phase-validate-config.js.map +0 -1
  362. package/dist/src/lifecycle/phase-validate-upstream.js.map +0 -1
  363. package/dist/src/lifecycle/phase-wire-handlers.js.map +0 -1
  364. package/dist/src/lifecycle/safe-restart.js.map +0 -1
  365. package/dist/src/logger.js.map +0 -1
  366. package/dist/src/mcp/bridge.js.map +0 -1
  367. package/dist/src/mcp/index.js.map +0 -1
  368. package/dist/src/models.js.map +0 -1
  369. package/dist/src/observability/event-bus.js.map +0 -1
  370. package/dist/src/observability/get-event-bus.js.map +0 -1
  371. package/dist/src/observability/observability-service.js.map +0 -1
  372. package/dist/src/observability/perf-telemetry.js.map +0 -1
  373. package/dist/src/observability/subscribers/metrics.js.map +0 -1
  374. package/dist/src/observability/subscribers/session-capture.js.map +0 -1
  375. package/dist/src/openai-compat/bridges/allowlist.js.map +0 -1
  376. package/dist/src/openai-compat/bridges/factory.js.map +0 -1
  377. package/dist/src/openai-compat/bridges/media-bridge.js.map +0 -1
  378. package/dist/src/openai-compat/bridges/openclaw-api-shim.js.map +0 -1
  379. package/dist/src/openai-compat/bridges/openclaw-native-tools.js.map +0 -1
  380. package/dist/src/openai-compat/bridges/openclaw-tool-registry.js.map +0 -1
  381. package/dist/src/openai-compat/bridges/tts-media-bridge.js.map +0 -1
  382. package/dist/src/openai-compat/cli-stream-parser.js.map +0 -1
  383. package/dist/src/openai-compat/index.js.map +0 -1
  384. package/dist/src/openai-compat/message-extractor.js.map +0 -1
  385. package/dist/src/openai-compat/mode-flags.js.map +0 -1
  386. package/dist/src/openai-compat/non-streaming-handler.js.map +0 -1
  387. package/dist/src/openai-compat/openai-chunk-types.js.map +0 -1
  388. package/dist/src/openai-compat/openai-compat.js.map +0 -1
  389. package/dist/src/openai-compat/openai-types.js.map +0 -1
  390. package/dist/src/openai-compat/parse-route-body.js.map +0 -1
  391. package/dist/src/openai-compat/prompts.js.map +0 -1
  392. package/dist/src/openai-compat/response-formatter.js.map +0 -1
  393. package/dist/src/openai-compat/session-key-resolver.js.map +0 -1
  394. package/dist/src/openai-compat/skill-resolver.js.map +0 -1
  395. package/dist/src/openai-compat/sse-translator.js.map +0 -1
  396. package/dist/src/openai-compat/status-reporter.js.map +0 -1
  397. package/dist/src/openai-compat/streaming-handler.js.map +0 -1
  398. package/dist/src/openai-compat/tool-calls-parser.js.map +0 -1
  399. package/dist/src/openai-compat/tool-results-serializer.js.map +0 -1
  400. package/dist/src/openai-compat/tts-rule.js.map +0 -1
  401. package/dist/src/openai-compat/voice-recovery.js.map +0 -1
  402. package/dist/src/patches/cache-parity-registry.js.map +0 -1
  403. package/dist/src/patches/claude-md-injection.js.map +0 -1
  404. package/dist/src/patches/cwd-redirect.js.map +0 -1
  405. package/dist/src/patches/embedded-server-route.js.map +0 -1
  406. package/dist/src/patches/pricing-overrides.js.map +0 -1
  407. package/dist/src/patches/resume-registry-restore.js.map +0 -1
  408. package/dist/src/patches/session-pid-tracking.js.map +0 -1
  409. package/dist/src/patches/sysprompt-strip.js.map +0 -1
  410. package/dist/src/patches/sysprompt-strip.spec.d.ts +0 -33
  411. package/dist/src/patches/sysprompt-strip.spec.js +0 -53
  412. package/dist/src/patches/sysprompt-strip.spec.js.map +0 -1
  413. package/dist/src/patches/tools-restoration.js.map +0 -1
  414. package/dist/src/persistence/migration-v0.js.map +0 -1
  415. package/dist/src/persistence/session-registry.js.map +0 -1
  416. package/dist/src/persistence/snapshot.js.map +0 -1
  417. package/dist/src/persistence/wal.js.map +0 -1
  418. package/dist/src/proxy/anthropic-adapter.js.map +0 -1
  419. package/dist/src/proxy/handler.js.map +0 -1
  420. package/dist/src/proxy/index.js.map +0 -1
  421. package/dist/src/proxy/schema-cleaner.js.map +0 -1
  422. package/dist/src/proxy/thought-cache.js.map +0 -1
  423. package/dist/src/session/embedded-server.js.map +0 -1
  424. package/dist/src/session/inbox-manager.js.map +0 -1
  425. package/dist/src/session/index.js.map +0 -1
  426. package/dist/src/session/persisted-sessions.js.map +0 -1
  427. package/dist/src/session/session-manager.js.map +0 -1
  428. package/dist/src/session/watchdogs.js.map +0 -1
  429. package/dist/src/session-bootstrap/boot-self-heal.js.map +0 -1
  430. package/dist/src/session-bootstrap/cwd-patch.js.map +0 -1
  431. package/dist/src/session-bootstrap/index.js.map +0 -1
  432. package/dist/src/session-bootstrap/resume-registry.js.map +0 -1
  433. package/dist/src/session-bootstrap/session-hygiene.js.map +0 -1
  434. package/dist/src/session-bootstrap/sysprompt-strip.js.map +0 -1
  435. package/dist/src/session-bootstrap/think-conflict-resolver.js.map +0 -1
  436. package/dist/src/types/index.js.map +0 -1
  437. package/dist/src/types/route.js.map +0 -1
  438. package/dist/src/types/runtime-config.js.map +0 -1
  439. package/dist/src/types/session.js.map +0 -1
  440. package/dist/src/types/sse.js.map +0 -1
  441. package/dist/src/types/tool-bridge.js.map +0 -1
  442. package/dist/src/types/upstream.js.map +0 -1
  443. package/dist/src/types.js.map +0 -1
  444. package/dist/src/validation.js.map +0 -1
@@ -1,868 +0,0 @@
1
- /**
2
- * telegram live-card — TypeScript port of savvy-claude-code/ux-bridge.js
3
- *
4
- * Handles:
5
- * - Telegram Bot API HTTP calls (sendTg, editTg, telegramApi)
6
- * - TelegramMessageQueue — serialises per-session card edits
7
- * - bridgeEvent — maps raw stream events to TranscriptEntry shape
8
- * - applyPatch — patches SessionManager.prototype.sendMessage to drive
9
- * TelegramUXPipeline for every Telegram-originating CC session
10
- *
11
- * Source lines: 1–930 of ux-bridge.js
12
- */
13
- import { readFileSync, unlinkSync, mkdirSync, appendFileSync } from 'node:fs';
14
- import { cleanStalePidFiles } from '../../lib/stale-pid-files.js';
15
- import { readFile as readFileAsync } from 'node:fs/promises';
16
- import { createRequire } from 'node:module';
17
- import { telegramApi, editTg, bridgeEvent } from './card-renderer.js';
18
- import { defaultRegisterGuard } from '../../lib/register-guard.js';
19
- import { isTestMode } from '../../lib/test-mode.js';
20
- import { getQuotaPausePct } from '../../lib/config.js';
21
- import { VENDOR_FILES } from '../../lib/vendor-paths.js';
22
- import { _logger, setLogger } from './logger.js';
23
- import { detectSlashCommand } from '../../openai-compat/skill-resolver.js';
24
- import { TelegramMessageQueue, markDispatchedToTelegram, _sendMessageDedup, _hashPayload, DEDUP_WINDOW_MS, _inputFingerprint, } from './throttle-controller.js';
25
- const __require = createRequire(import.meta.url);
26
- // ── Constants ─────────────────────────────────────────────────────────────
27
- const PLUGIN_TAG = '[cc-openclaw/telegram/live-card]';
28
- const CC_PLUGIN_PATH = VENDOR_FILES.sessionManager;
29
- export const UX_MODULE_PATH = '/home/a1xai/.openclaw/workspace/lib/telegram-ux';
30
- export const VERBOSITY_STORE = '/home/a1xai/.openclaw/workspace/lib/telegram-ux/verbosity-prefs.json';
31
- const OPENCLAW_CONFIG_PATH = '/home/a1xai/.openclaw/openclaw.json';
32
- const STATUS_TEE_DIR = '/tmp/openclaw-ux-status';
33
- const STATUS_POLL_MS = 30000;
34
- const GPT_POLL_MS = 30000;
35
- const QUOTA_POLL_MS = 30000;
36
- // ── Shared mutable state (module-level singletons) ───────────────────────
37
- export let BOT_TOKEN = '';
38
- // eslint-disable-next-line prefer-const
39
- export let minimaxTracker = null;
40
- export let buttonHandler = null;
41
- export let nsCommands = null;
42
- // Active session registry for callback routing: sessionId → { pipeline, queue, name }
43
- export const activeSessions = new Map();
44
- // Finished-session grace cache — keeps a session discoverable for button
45
- // callbacks (Continue / Transcript / Verbose / Model) that arrive AFTER
46
- // the turn ends. Expires entries after FINISHED_SESSION_TTL_MS.
47
- export const recentlyFinishedSessions = new Map();
48
- export const FINISHED_SESSION_TTL_MS = 5 * 60 * 1000;
49
- // Tier 6: Delegation chain store — tracks Savvy card IDs for CC session linking/cleanup
50
- export const delegatedCardStore = new Map();
51
- // F3 — Module-level mirror of the most recent quota fetch.
52
- export let latestQuotaState = null;
53
- // F3 — Auto-pause threshold.
54
- const QUOTA_PAUSE_PCT = getQuotaPausePct();
55
- // Per-chat cooldown on pause notifications
56
- const _pauseNotifiedAt = new Map(); // chatId → timestamp
57
- // TelegramMessageQueue, _sendMessageDedup, _hashPayload, DEDUP_WINDOW_MS,
58
- // markDispatchedToTelegram, wasDispatchedToTelegram, _inputFingerprint were
59
- // extracted to throttle-controller.ts in Step 3 of v0.11.0 decomposition.
60
- // Re-exported below for backward compatibility with sibling modules that
61
- // import them from live-card.
62
- export { markDispatchedToTelegram, wasDispatchedToTelegram } from './throttle-controller.js';
63
- const PAUSE_NOTIFY_COOLDOWN_MS = 60 * 1000;
64
- // ── M1 helper — wraps options.onThinking so the live card receives a
65
- // rolling 80-char preview alongside any pre-existing consumer (e.g. the
66
- // streaming-handler SSE forwarder). Exported for unit tests; not part of
67
- // the public API surface — callers go through patchedSendMessage.
68
- export function wrapOnThinking(options, pipeline) {
69
- const originalOnThinking = options.onThinking;
70
- options.onThinking = (text) => {
71
- if (text && typeof pipeline.setThinkingPreview === 'function') {
72
- try {
73
- pipeline.setThinkingPreview(text.slice(-80));
74
- }
75
- catch { /* ignore */ }
76
- }
77
- if (originalOnThinking) {
78
- try {
79
- originalOnThinking(text);
80
- }
81
- catch { /* ignore */ }
82
- }
83
- };
84
- }
85
- // ── v0.22.0 M1 helper — lifts v0.20.2 D2 deviation (settle-only refresh).
86
- // Wraps options.callbacks.onText so per-delta assistant text reaches the
87
- // pipeline's appendAssistantTextDelta sink (workspace forwards to
88
- // savvy-card-state.setAssistantText(text,'streaming') — buffered in
89
- // _pendingAssistantText until messageStop). Preserves any pre-existing
90
- // onText consumer (SSE forwarder, streaming-handler) — same discipline as
91
- // wrapOnThinking. Failure-open: if pipeline.appendAssistantTextDelta is
92
- // absent (older workspace), this is a silent no-op aside from delegating
93
- // to the original onText. Exported for unit tests.
94
- export function wrapOnText(options, pipeline) {
95
- if (!options.callbacks)
96
- options.callbacks = {};
97
- const originalOnText = options.callbacks.onText;
98
- options.callbacks.onText = (text) => {
99
- if (text && typeof pipeline.appendAssistantTextDelta === 'function') {
100
- try {
101
- pipeline.appendAssistantTextDelta(text);
102
- }
103
- catch { /* ignore */ }
104
- }
105
- if (originalOnText) {
106
- try {
107
- originalOnText(text);
108
- }
109
- catch { /* ignore */ }
110
- }
111
- };
112
- }
113
- // ── v0.22.0 M5 — dual-bubble layout-mode env gate ────────────────────────
114
- //
115
- // CC_OPENCLAW_LIVE_CARD_LAYOUT controls whether bubble #2 (terminal mirror)
116
- // is emitted alongside the chrome card. Default `chrome_only` preserves
117
- // exact v0.20.2 behavior with zero regression. Set to `dual_bubble` to
118
- // enable the terminal mirror — a fenced code-block second message that
119
- // streams tool-event log lines + rolling assistant text tail.
120
- //
121
- // Read once at module load (not per call) so the value is stable across
122
- // the session — matches the discipline used by RICH_RENDER_ENABLED.
123
- const DUAL_BUBBLE_LAYOUT_ENABLED = (process.env.CC_OPENCLAW_LIVE_CARD_LAYOUT || 'chrome_only').toLowerCase() === 'dual_bubble';
124
- /** v0.22.0 M5 — testable getter for the layout-mode resolution.
125
- * Returns the active layout: 'chrome_only' | 'dual_bubble'. Reads the
126
- * env at call time (NOT cached) so test harnesses can flip the env and
127
- * observe the change. The hot-path uses DUAL_BUBBLE_LAYOUT_ENABLED for
128
- * one-time resolution; this getter is for tests + diagnostics. */
129
- export function resolveLiveCardLayout() {
130
- return (process.env.CC_OPENCLAW_LIVE_CARD_LAYOUT || 'chrome_only').toLowerCase() === 'dual_bubble'
131
- ? 'dual_bubble'
132
- : 'chrome_only';
133
- }
134
- let _terminalRenderer = null;
135
- let _terminalRendererLoaded = false;
136
- function _loadTerminalRenderer() {
137
- if (_terminalRendererLoaded)
138
- return _terminalRenderer;
139
- _terminalRendererLoaded = true;
140
- try {
141
- const mod = __require('/home/a1xai/.openclaw/workspace/lib/telegram-ux/telegram-renderer.js');
142
- if (typeof mod._renderTerminalBubble === 'function') {
143
- _terminalRenderer = mod._renderTerminalBubble;
144
- }
145
- }
146
- catch { /* fail open — bubble #2 stays off if workspace lacks renderer */ }
147
- return _terminalRenderer;
148
- }
149
- /** v0.22.0 M5 — emit bubble #2 if the layout flag is set and the renderer
150
- * is available. Fail-open: env unset / `chrome_only` / renderer missing
151
- * all silently no-op, preserving zero-regression for the default path.
152
- * Callers wire this AFTER updateCard within the same tick so the queue's
153
- * shared _cardChain enforces the bubble-ordering invariant. */
154
- export function maybeEmitDualBubble(state, queue) {
155
- if (!DUAL_BUBBLE_LAYOUT_ENABLED)
156
- return;
157
- if (!queue || typeof queue.updateTerminalBubble !== 'function')
158
- return;
159
- const renderer = _loadTerminalRenderer();
160
- if (!renderer)
161
- return;
162
- try {
163
- const body = renderer(state, {});
164
- if (body && body.trim())
165
- queue.updateTerminalBubble(body);
166
- }
167
- catch { /* ignore — bubble #2 must never break bubble #1 */ }
168
- }
169
- // ── Telegram Bot API — re-exported from card-renderer.ts for caller compat ─
170
- export { telegramApi, sendTg, editTg } from './card-renderer.js';
171
- // ── Per-session Telegram message queue ────────────────────────────────────
172
- // TelegramMessageQueue moved to throttle-controller.ts in Step 3 of v0.11.0
173
- // decomposition. Re-exported for callers that import it from live-card.
174
- export { TelegramMessageQueue } from './throttle-controller.js';
175
- // ── Event bridge — re-exported from card-renderer.ts ─────────────────────
176
- export { bridgeEvent } from './card-renderer.js';
177
- // ── Module-level logger (set at register() time) ──────────────────────────
178
- // Re-exported from shared logger.ts for backward-compat with siblings that import _logger from here.
179
- export { _logger, setLogger } from './logger.js';
180
- // ── UX module + patch state ───────────────────────────────────────────────
181
- let uxModule = null;
182
- let patchApplied = false;
183
- const PATCH_MARKER = Symbol.for('telegram-ux-bridge:patched');
184
- export function loadUxModule() {
185
- if (!uxModule) {
186
- uxModule = __require(UX_MODULE_PATH);
187
- }
188
- if (!buttonHandler) {
189
- try {
190
- const { ButtonHandler, NS_COMMANDS } = __require(`${UX_MODULE_PATH}/button-handler`);
191
- buttonHandler = new ButtonHandler();
192
- nsCommands = NS_COMMANDS || null;
193
- }
194
- catch { /* button-handler not available — buttons disabled */ }
195
- }
196
- return uxModule;
197
- }
198
- // ── input dedup fingerprint ───────────────────────────────────────────────
199
- // _inputFingerprint moved to throttle-controller.ts. Imported above for use
200
- // in applyPatch's tool-call dedup.
201
- // ── applyPatch ────────────────────────────────────────────────────────────
202
- export async function applyPatch() {
203
- if (patchApplied)
204
- return;
205
- patchApplied = true;
206
- let SessionManager;
207
- try {
208
- const mod = await import(CC_PLUGIN_PATH);
209
- const Cls = (mod.SessionManager || mod.default?.SessionManager);
210
- SessionManager = Cls;
211
- }
212
- catch (err) {
213
- _logger.error(`${PLUGIN_TAG} Cannot import SessionManager: ${err.message}`);
214
- return;
215
- }
216
- if (!SessionManager) {
217
- _logger.error(`${PLUGIN_TAG} SessionManager class not found in module`);
218
- return;
219
- }
220
- try {
221
- loadUxModule();
222
- }
223
- catch (err) {
224
- _logger.error(`${PLUGIN_TAG} Cannot load telegram-ux module: ${err.message}`);
225
- return;
226
- }
227
- const original = SessionManager.prototype.sendMessage;
228
- if (!original) {
229
- _logger.error(`${PLUGIN_TAG} sendMessage not found on SessionManager.prototype`);
230
- return;
231
- }
232
- if (original[PATCH_MARKER]) {
233
- _logger.warn(`${PLUGIN_TAG} sendMessage already patched — skipping to prevent message duplication`);
234
- return;
235
- }
236
- // TODO(P2): `this` context is the SessionManager instance at runtime — complex shape
237
- SessionManager.prototype.sendMessage = async function patchedSendMessage(name, message, options = {}) {
238
- const __PERF_KEY = Symbol.for('claude-local:perf-timing');
239
- const __perfSendStart = performance.now();
240
- let __perfFirstEventAbsMs = null;
241
- const __perfStore = globalThis[__PERF_KEY]
242
- = globalThis[__PERF_KEY] || new Map();
243
- const __perfBareKey = name.startsWith('openai-') ? name.slice(7) : name;
244
- {
245
- const prev = __perfStore.get(name) || __perfStore.get(__perfBareKey) || {};
246
- __perfStore.set(name, { ...prev, sendMessageStartAbsMs: __perfSendStart });
247
- }
248
- let chatId = options.telegramChatId || '';
249
- let threadId = options.telegramThreadId || undefined;
250
- if (!chatId) {
251
- const UX_META = Symbol.for('telegram-ux-bridge:metadata');
252
- const shared = globalThis[UX_META]?.get(name);
253
- if (shared) {
254
- chatId = shared.chatId || '';
255
- threadId = shared.threadId || undefined;
256
- globalThis[UX_META].delete(name);
257
- if (chatId) {
258
- _logger.info(`${PLUGIN_TAG} Resolved telegram metadata from global store for session "${name}": chat=${chatId} thread=${threadId || 'none'}`);
259
- }
260
- }
261
- }
262
- if (!BOT_TOKEN || !chatId) {
263
- return original.call(this, name, message, options);
264
- }
265
- // ── In-flight dedup ─────────────────────────────────────────────────────
266
- // Doubled-greeting defensive guard: if patchedSendMessage is invoked twice
267
- // within DEDUP_WINDOW_MS for the same (chatId, payload), short-circuit the
268
- // duplicate so it doesn't reach Telegram. Keyed on chatId because the
269
- // upstream double-call uses two different session names for the same
270
- // chat-bound output — sessionName is unstable, chatId is invariant.
271
- // Logs the first duplicate at WARN to surface the upstream double-call.
272
- {
273
- const _payloadHash = _hashPayload(message);
274
- const _existing = _sendMessageDedup.get(chatId);
275
- const _now = Date.now();
276
- if (_existing && _existing.hash === _payloadHash && _existing.expiresAt > _now) {
277
- _logger.warn(`${PLUGIN_TAG} Duplicate patchedSendMessage detected within ${DEDUP_WINDOW_MS}ms for chat=${chatId} session=${name} payloadHash=${_payloadHash} — short-circuiting (upstream double-call evidence)`);
278
- return; // no queue, no telegramApi call
279
- }
280
- _sendMessageDedup.set(chatId, { hash: _payloadHash, expiresAt: _now + DEDUP_WINDOW_MS });
281
- // Cheap GC: prune entries whose window has elapsed (keeps map small).
282
- if (_sendMessageDedup.size > 64) {
283
- for (const [k, v] of _sendMessageDedup) {
284
- if (v.expiresAt <= _now)
285
- _sendMessageDedup.delete(k);
286
- }
287
- }
288
- }
289
- // Mark this (chatId, message) so the state-machine's message_sending
290
- // hook can cancel the native ACP dispatcher when it also fires for
291
- // the same payload — that's the doubled-greeting cross-path bug.
292
- markDispatchedToTelegram(chatId, message);
293
- // F3 — Quota auto-pause
294
- if (QUOTA_PAUSE_PCT > 0 && QUOTA_PAUSE_PCT <= 100) {
295
- const pct7d = latestQuotaState?.sevenDay?.usedPercent;
296
- if (typeof pct7d === 'number' && pct7d >= QUOTA_PAUSE_PCT) {
297
- const lastNotif = _pauseNotifiedAt.get(chatId) || 0;
298
- if (Date.now() - lastNotif > PAUSE_NOTIFY_COOLDOWN_MS) {
299
- _pauseNotifiedAt.set(chatId, Date.now());
300
- const note = `⏸ Weekly plan quota at ${pct7d}% — dispatch paused (threshold ${QUOTA_PAUSE_PCT}%). Set OPENCLAW_QUOTA_PAUSE_PCT=100 to disable.`;
301
- telegramApi('sendMessage', {
302
- chat_id: chatId,
303
- text: note,
304
- ...(threadId ? { message_thread_id: Number(threadId) } : {}),
305
- }).catch(() => { });
306
- }
307
- _logger.warn(`${PLUGIN_TAG} Quota pause: 7d=${pct7d}% threshold=${QUOTA_PAUSE_PCT}% name=${name}`);
308
- const err = new Error(`quota-paused: 7d ${pct7d}% ≥ ${QUOTA_PAUSE_PCT}%`);
309
- err.code = 'QUOTA_PAUSED';
310
- throw err;
311
- }
312
- }
313
- const { TelegramUXPipeline } = loadUxModule();
314
- const ackMessageId = options.telegramAckMessageId || null;
315
- const queue = new TelegramMessageQueue(chatId, threadId, ackMessageId);
316
- const delegatedInfo = delegatedCardStore.get(name);
317
- if (delegatedInfo && !ackMessageId) {
318
- queue._replyToMessageId = delegatedInfo.cardMessageId;
319
- }
320
- let model = 'claude';
321
- let permissionMode = null;
322
- try {
323
- const managed = this._getSession?.(name);
324
- model = (managed?.config?.model || managed?.session?.options?.model || 'claude');
325
- permissionMode = managed?.config?.permissionMode || null;
326
- }
327
- catch { /* ignore */ }
328
- const sessionType = name.startsWith('cc-') ? 'cc'
329
- : name.startsWith('openai-') ? 'savvy'
330
- : 'delegated';
331
- let sessionRef = null;
332
- try {
333
- sessionRef = this._getSession?.(name)?.session || null;
334
- }
335
- catch { /* session may not exist yet */ }
336
- const pipeline = new TelegramUXPipeline({
337
- sessionName: name,
338
- model,
339
- chatKey: `telegram:${chatId}`,
340
- verbosityStorePath: VERBOSITY_STORE,
341
- editIntervalMs: 5000,
342
- onCardUpdate: (text, state) => {
343
- const markup = buttonHandler ? buttonHandler.buildButtons(state, name) : undefined;
344
- queue.updateCard(text, markup);
345
- // v0.22.0 M5 — emit bubble #2 (terminal mirror) in lockstep when
346
- // CC_OPENCLAW_LIVE_CARD_LAYOUT=dual_bubble. No-op when env unset
347
- // / 'chrome_only' / renderer module didn't load — preserves the
348
- // v0.20.2 zero-regression default-path contract.
349
- maybeEmitDualBubble(state, queue);
350
- },
351
- onNewMessage: (text) => {
352
- // 2026-05-07: For cc-* sessions, cc-handler delivers the answer directly
353
- // via sendDirectReply (see cc-handler.ts after sessionManager.sendMessage).
354
- // Skipping pipeline-driven delivery here prevents the doubled answer the
355
- // user observed (e.g. "15" appearing twice for /cc 7+8). The pipeline
356
- // still owns metadata-card updates (timing, quota, tool count) — only the
357
- // assistant-text delivery is suppressed for cc-* sessions.
358
- if (sessionType === 'cc')
359
- return;
360
- // v0.20.1: escape:true — raw assistant text must be MarkdownV2-escaped
361
- // before sending or content punctuation gets corrupted on fallback.
362
- // See throttle-controller.ts sendMessage doc + card-renderer.ts
363
- // fallback fix for the bug history.
364
- queue.sendMessage(text, { escape: true });
365
- },
366
- livenessCheck: () => {
367
- const pid = sessionRef?.pid || this._getSession?.(name)?.session?.pid;
368
- if (!pid)
369
- return true;
370
- try {
371
- process.kill(pid, 0);
372
- return true;
373
- }
374
- catch {
375
- return false;
376
- }
377
- },
378
- });
379
- pipeline.start();
380
- // Stall auto-kill
381
- // eslint-disable-next-line @typescript-eslint/no-this-alias
382
- const sessionMgr = this;
383
- let consecutiveStalls = 0;
384
- // v0.5.1: bumped 3 → 8. Long reasoning turns (54+ tools, 5+ min) accumulate
385
- // 3 stalls trivially because the stall detector treats per-tool-execution
386
- // gaps (60-100s while Bash runs) as model silence. Killing at 3 was killing
387
- // turns mid-execution. 8 stalls (~800s of cumulative model-silence) gives
388
- // multi-step plans time to complete; the pipeline's natural recovery on tool
389
- // output still resets the counter, so most turns won't reach 8.
390
- const MAX_STALLS_BEFORE_KILL = 8;
391
- const origHandleStall = pipeline._handleStall.bind(pipeline);
392
- const origHandleRecovery = pipeline._handleStallRecovery.bind(pipeline);
393
- pipeline._handleStall = (idleMs) => {
394
- consecutiveStalls++;
395
- origHandleStall(idleMs);
396
- const alive = pipeline._livenessCheck ? pipeline._livenessCheck() : true;
397
- if (!alive || consecutiveStalls >= MAX_STALLS_BEFORE_KILL) {
398
- _logger.warn(`${PLUGIN_TAG} Auto-killing stalled session "${name}" (alive=${alive}, stalls=${consecutiveStalls})`);
399
- queue.sendMessage(`⚠️ Session auto-stopped: ${!alive ? 'process exited' : `${consecutiveStalls} consecutive stalls with no activity`}`);
400
- try {
401
- sessionMgr.stopSession(name);
402
- }
403
- catch (e) {
404
- _logger.warn(`${PLUGIN_TAG} Auto-kill stopSession error: ${e.message}`);
405
- }
406
- }
407
- };
408
- pipeline._handleStallRecovery = () => {
409
- consecutiveStalls = 0;
410
- origHandleRecovery();
411
- };
412
- activeSessions.set(name, { pipeline, queue, name });
413
- if (permissionMode)
414
- pipeline.setPermissionMode(permissionMode);
415
- pipeline.setSessionType(sessionType);
416
- // M3 (v0.19.1): surface the original /<slash> on the card pill.
417
- // Savvy resolved-skill turns get it threaded via options.slashCommand
418
- // (extractor → handler → patched sendMessage). CC turns + unresolved
419
- // Savvy slashes fall back to detection on the raw message text.
420
- try {
421
- const optSlash = options.slashCommand;
422
- const fallbackSlash = optSlash ? null
423
- : (typeof message === 'string' ? detectSlashCommand(message) : null);
424
- const slash = optSlash || fallbackSlash;
425
- if (slash && typeof pipeline.setSlashCommand === 'function') {
426
- pipeline.setSlashCommand(slash);
427
- }
428
- }
429
- catch { /* ignore — pill is cosmetic */ }
430
- // Status file polling
431
- let statusPollTimer = null;
432
- let resolvedStatusPid = null;
433
- const _pollStatus = async () => {
434
- try {
435
- if (!sessionRef) {
436
- sessionRef = this._getSession?.(name)?.session || null;
437
- }
438
- const stats = sessionRef?.getStats?.() || sessionRef?.stats;
439
- if (stats) {
440
- if (typeof stats.tokensIn === 'number') {
441
- pipeline.setTokenUsage(stats.tokensIn, stats.tokensOut || 0);
442
- }
443
- if (typeof stats.contextPercent === 'number' && stats.contextPercent > 0) {
444
- pipeline.setContextPercent(Math.round(stats.contextPercent));
445
- }
446
- if (typeof stats.cachedTokens === 'number' && stats.cachedTokens > 0) {
447
- const totalIn = (stats.tokensIn || 0) + (stats.cachedTokens || 0);
448
- const pct = totalIn > 0 ? (stats.cachedTokens / totalIn) * 100 : null;
449
- pipeline.setCachedTokens(stats.cachedTokens, pct);
450
- }
451
- }
452
- const sessionModel = sessionRef?.options?.model;
453
- if (sessionModel)
454
- pipeline.setModel(sessionModel);
455
- if (minimaxTracker) {
456
- const mmUsage = minimaxTracker.getUsage();
457
- if (mmUsage.used > 0) {
458
- pipeline.setMiniMaxUsage(mmUsage);
459
- }
460
- }
461
- }
462
- catch { /* session not ready yet */ }
463
- try {
464
- if (!resolvedStatusPid) {
465
- resolvedStatusPid = sessionRef?.pid || this._getSession?.(name)?.session?.pid || null;
466
- }
467
- if (!resolvedStatusPid) {
468
- statusPollTimer = setTimeout(_pollStatus, STATUS_POLL_MS);
469
- return;
470
- }
471
- const statusFile = `${STATUS_TEE_DIR}/${resolvedStatusPid}.json`;
472
- const raw = await readFileAsync(statusFile, 'utf8');
473
- const data = JSON.parse(raw);
474
- const ctxPct = data?.context_window?.used_percentage;
475
- if (typeof ctxPct === 'number')
476
- pipeline.setContextPercent(Math.round(ctxPct));
477
- const rateLimits = data?.rate_limits;
478
- const quotaPct = rateLimits?.five_hour?.used_percentage;
479
- const quotaReset = rateLimits?.five_hour?.resets_at;
480
- if (typeof quotaPct === 'number')
481
- pipeline.setQuotaPercent(Math.round(quotaPct), quotaReset || null);
482
- const quotaPct7d = rateLimits?.seven_day?.used_percentage;
483
- const quotaReset7d = rateLimits?.seven_day?.resets_at;
484
- if (typeof quotaPct7d === 'number')
485
- pipeline.setQuota7d(Math.round(quotaPct7d), quotaReset7d || null);
486
- const modelData = data?.model;
487
- const modelName = modelData?.display_name || modelData?.model_id;
488
- if (modelName)
489
- pipeline.setModel(modelName);
490
- const ctxSize = data?.context_window?.context_window_size;
491
- if (typeof ctxSize === 'number' && ctxSize > 0)
492
- pipeline.setContextWindowSize(ctxSize);
493
- const usage = data?.context_window?.current_usage;
494
- const inTok = usage?.input_tokens;
495
- const outTok = usage?.output_tokens;
496
- if (typeof inTok === 'number' && typeof outTok === 'number')
497
- pipeline.setTokenUsage(inTok, outTok);
498
- }
499
- catch { /* status file doesn't exist or parse error — normal for pipe mode */ }
500
- statusPollTimer = setTimeout(_pollStatus, STATUS_POLL_MS);
501
- };
502
- statusPollTimer = setTimeout(_pollStatus, STATUS_POLL_MS);
503
- // GPT/Codex usage polling
504
- let gptPollTimer = null;
505
- try {
506
- const _ux = loadUxModule();
507
- const { getCodexUsage } = (_ux.getCodexUsage
508
- ? _ux
509
- : __require(`${UX_MODULE_PATH}/codex-usage`));
510
- const pollGpt = async () => {
511
- try {
512
- const usage = await getCodexUsage();
513
- if (usage)
514
- pipeline.setGptUsage(usage);
515
- }
516
- catch { /* ignore */ }
517
- };
518
- const initialUsage = await getCodexUsage().catch(() => null);
519
- if (initialUsage)
520
- pipeline.setGptUsage(initialUsage);
521
- const lastUsedMs = initialUsage?.lastUsed || 0;
522
- if (Date.now() - lastUsedMs < 24 * 60 * 60 * 1000) {
523
- gptPollTimer = setInterval(pollGpt, GPT_POLL_MS);
524
- }
525
- }
526
- catch { /* codex-usage module not available — skip */ }
527
- // Anthropic OAuth quota polling
528
- let quotaPollTimer = null;
529
- try {
530
- const { QuotaFetcher } = __require(`${UX_MODULE_PATH}/quota-fetcher`);
531
- const quotaFetcher = new QuotaFetcher();
532
- quotaFetcher.startPolling(QUOTA_POLL_MS, (quota) => {
533
- latestQuotaState = quota;
534
- if (quota.fiveHour && quota.fiveHour.usedPercent != null) {
535
- pipeline.setQuotaPercent(quota.fiveHour.usedPercent, quota.fiveHour.resetsAt);
536
- }
537
- if (quota.sevenDay && quota.sevenDay.usedPercent != null) {
538
- pipeline.setQuota7d(quota.sevenDay.usedPercent, quota.sevenDay.resetsAt);
539
- }
540
- });
541
- quotaPollTimer = quotaFetcher;
542
- }
543
- catch { /* quota-fetcher module not available — skip */ }
544
- let capturedResult = null;
545
- const resultListener = (event) => { capturedResult = event; };
546
- try {
547
- sessionRef = this._getSession?.(name)?.session || null;
548
- if (sessionRef?.on) {
549
- sessionRef.on('result', resultListener);
550
- // M4 (v0.19.1): mid-stream quota refresh. Engine re-emits the
551
- // CLI's `rate_limit_event` envelope; we forward 5h + 7d to the
552
- // pipeline immediately so the header `Max N%` updates within
553
- // the same tick (vs the existing 30s status-tee poll lag).
554
- sessionRef.on('rate_limit_event', (evt) => {
555
- try {
556
- const rli = (evt?.rateLimitInfo || {});
557
- if (rli.five_hour && typeof rli.five_hour.used_percentage === 'number') {
558
- pipeline.setQuotaPercent(rli.five_hour.used_percentage, rli.five_hour.resets_at);
559
- }
560
- if (rli.seven_day && typeof rli.seven_day.used_percentage === 'number') {
561
- pipeline.setQuota7d(rli.seven_day.used_percentage, rli.seven_day.resets_at);
562
- }
563
- }
564
- catch { /* ignore — quota refresh is best-effort */ }
565
- });
566
- }
567
- }
568
- catch { /* ignore */ }
569
- // Bridge engine thinking-delta stream into the live card. Wraps any
570
- // existing options.onThinking (e.g. streaming-handler's SSE forwarder)
571
- // so both consumers fire — the SSE thinking-surface must not regress.
572
- wrapOnThinking(options, pipeline);
573
- // v0.22.0 M1 — bridge engine text_delta stream into the per-delta
574
- // pipeline sink (workspace appendAssistantTextDelta → savvy-card-state
575
- // setAssistantText(text,'streaming')). Lifts the v0.20.2 D2 deviation
576
- // (settle-only refresh) so bubble #2 (terminal mirror, M3) can stream.
577
- // Preserves any pre-existing options.callbacks.onText consumer.
578
- wrapOnText(options, pipeline);
579
- const originalOnEvent = options.onEvent;
580
- const toolUseInputSize = new Map();
581
- options.onEvent = (event) => {
582
- if (event.type === 'tool_use') {
583
- const id = event.id || event.tool_use_id || '';
584
- if (id) {
585
- const curr = _inputFingerprint(event.tool?.input);
586
- const prev = toolUseInputSize.get(id);
587
- if (prev && curr.size <= prev.size && curr.sig === prev.sig) {
588
- if (originalOnEvent) {
589
- try {
590
- originalOnEvent(event);
591
- }
592
- catch { /* ignore */ }
593
- }
594
- return;
595
- }
596
- toolUseInputSize.set(id, curr);
597
- }
598
- }
599
- if (__perfFirstEventAbsMs == null) {
600
- __perfFirstEventAbsMs = performance.now();
601
- }
602
- const entry = bridgeEvent(event);
603
- if (entry) {
604
- pipeline.processTranscriptEntry(entry);
605
- }
606
- if (originalOnEvent) {
607
- try {
608
- originalOnEvent(event);
609
- }
610
- catch { /* ignore */ }
611
- }
612
- };
613
- try {
614
- const result = await original.call(this, name, message, options);
615
- try {
616
- const stats = sessionRef?.stats || {};
617
- const resultEntry = {
618
- kind: 'result',
619
- ts: new Date().toISOString(),
620
- // Fallback chain (extended 2026-05-06): handle bare-string results too.
621
- // session-manager.sendMessage() returns a STRING (the response text), not an
622
- // object with .output. The original chain (.output → captured) failed when
623
- // session-manager's post-stream coalesce path returns a plain string — so
624
- // resultEntry.text was always empty for fast-turn /cc Q&A and the live card
625
- // showed only metadata with no actual response text.
626
- text: (typeof result === 'string' && result) ||
627
- result?.output ||
628
- result?.text ||
629
- capturedResult?.result ||
630
- '',
631
- inputTokens: capturedResult?.usage?.input_tokens || stats.tokensIn || 0,
632
- outputTokens: capturedResult?.usage?.output_tokens || stats.tokensOut || 0,
633
- cachedTokens: capturedResult?.usage?.cache_read_input_tokens || stats.cachedTokens || 0,
634
- costUsd: stats.costUsd || 0,
635
- };
636
- // M2 (v0.19.1): also flow cost through the dedicated setter so
637
- // SessionCardState (CC) renders $X.XXXX in footer parity with Savvy.
638
- try {
639
- pipeline.setCostUsd?.(stats.costUsd || 0);
640
- }
641
- catch { /* ignore */ }
642
- // M5 (v0.19.1): split cache reads vs new entries so the footer
643
- // shows `12K cached · 3K new` instead of dropping cache_creation.
644
- try {
645
- const cacheRead = capturedResult?.usage?.cache_read_input_tokens
646
- ?? stats.cachedTokens
647
- ?? 0;
648
- const cacheWrite = capturedResult?.usage?.cache_creation_input_tokens ?? 0;
649
- if (cacheRead > 0 || cacheWrite > 0) {
650
- pipeline.setCacheBreakdown?.(cacheRead, cacheWrite);
651
- }
652
- }
653
- catch { /* ignore */ }
654
- pipeline.finish(resultEntry);
655
- // Fast-turn fallback: when the pipeline's gate suppresses card posting
656
- // (no tools, <20s thinking, no files/errors), pipeline.finish() returns
657
- // silently and the ack message is never edited. For plain Q&A turns
658
- // (/cc how r u), this would silently drop the reply. If the card was
659
- // never posted AND no message was sent through the queue AND we have
660
- // an ack to edit AND a text result, deliver the result directly via
661
- // queue.sendMessage() — which edits the ack in-place since
662
- // cardMessageId is set. Closes a real bug surfaced in production
663
- // 2026-04-27.
664
- //
665
- // Bug fix 2026-04-29: also gate on `queue.messageSent` to avoid
666
- // double-firing when the pipeline's `onNewMessage` callback already
667
- // delivered the result. Without this gate, fast turns like the
668
- // /new greeting were dispatched twice (pipeline+fallback) — observed
669
- // as two `[telegram] sendMessage ok` calls within ~350ms for one
670
- // model output.
671
- const _resultText = resultEntry.text || '';
672
- // 2026-05-07 fix: dropped `_cardNeverPosted` check from the gate.
673
- // The pipeline edits the card with METADATA (quota %, tool count, timing)
674
- // even when the assistant text was never delivered to Telegram —
675
- // _lastCardEditAt > 0 doesn't imply the answer reached the user.
676
- // The original "doubled-greeting" concern is already prevented by
677
- // `!queue.messageSent`: pipeline's onNewMessage callback (~line 482)
678
- // sets queue.messageSent=true when it delivers via the queue.
679
- // So:
680
- // - pipeline delivered text → queue.messageSent=true → skip fallback
681
- // - pipeline only posted metadata → queue.messageSent=false → deliver
682
- // Diagnosed 2026-05-07 via stderr instrumentation: gate showed
683
- // `cardNeverPosted=false, queueMessageSent=false, gateOpens=false`
684
- // while resultText="10" was correctly extracted — proof the gate
685
- // was the only blocker on /cc text delivery.
686
- // 2026-05-07: cc-* sessions are delivered by cc-handler.ts directly via
687
- // sendDirectReply. Fast-turn fallback here would double-fire — skip it
688
- // for cc-* and let cc-handler be the sole authoritative delivery path.
689
- // Other session types (openai-gw-*, delegated) keep the original path.
690
- if (sessionType !== 'cc' && !queue.messageSent && ackMessageId && _resultText) {
691
- // queue.sendMessage is fire-and-forget (returns void); errors are swallowed by the queue's own _msgChain.
692
- queue.sendMessage(_resultText);
693
- _logger.info(`${PLUGIN_TAG} fast-turn fallback: delivered result via queue.sendMessage (queue.messageSent gate, non-cc session) session=${name}`);
694
- }
695
- try {
696
- const state = pipeline._cardState?.getState?.() || {};
697
- const metricsDir = '/home/a1xai/.openclaw/workspace/memory';
698
- mkdirSync(metricsDir, { recursive: true });
699
- const __perfEnd = performance.now();
700
- const __perfEntry = __perfStore.get(name) || __perfStore.get(__perfBareKey) || {};
701
- const perfFields = {
702
- perfRoutePatchMs: __perfEntry.routePatchMs ?? null,
703
- perfRouteToSendMs: __perfEntry.routePatchEndAbsMs != null
704
- ? Math.round(__perfSendStart - __perfEntry.routePatchEndAbsMs)
705
- : null,
706
- perfTtftMs: __perfFirstEventAbsMs != null
707
- ? Math.round(__perfFirstEventAbsMs - __perfSendStart)
708
- : null,
709
- perfSendMessageMs: Math.round(__perfEnd - __perfSendStart),
710
- perfTurnTotalMs: __perfEntry.routePatchEndAbsMs != null
711
- ? Math.round(__perfEnd - (__perfEntry.routePatchEndAbsMs - (__perfEntry.routePatchMs || 0)))
712
- : null,
713
- };
714
- if (perfFields.perfRoutePatchMs != null) {
715
- perfFields.perfRoutePatchMs = Math.round(perfFields.perfRoutePatchMs);
716
- }
717
- __perfStore.delete(name);
718
- __perfStore.delete(__perfBareKey);
719
- const metricsLine = JSON.stringify({
720
- ts: new Date().toISOString(),
721
- sessionName: name,
722
- chatId: chatId || null,
723
- durationMs: state.elapsedMs || 0,
724
- toolCount: state.toolCount || 0,
725
- toolsByCategory: state.toolSummary || {},
726
- errorCount: state.errorCount || 0,
727
- stallCount: state.stallCount || 0,
728
- thinkingMs: state.thinkingMs || 0,
729
- filesModifiedCount: (state.filesModified || []).length,
730
- subagentCount: (state.subagents || []).length,
731
- inputTokens: resultEntry.inputTokens,
732
- outputTokens: resultEntry.outputTokens,
733
- cachedTokens: resultEntry.cachedTokens,
734
- status: state.status || 'done',
735
- ...perfFields,
736
- }) + '\n';
737
- setImmediate(() => {
738
- try {
739
- appendFileSync(`${metricsDir}/session-metrics.jsonl`, metricsLine);
740
- }
741
- catch { /* metrics advisory — non-fatal */ }
742
- });
743
- }
744
- catch { /* metrics are advisory — never block on failure */ }
745
- }
746
- catch {
747
- pipeline.finish(null);
748
- }
749
- return result;
750
- }
751
- catch (err) {
752
- pipeline.abort();
753
- throw err;
754
- }
755
- finally {
756
- if (statusPollTimer)
757
- clearTimeout(statusPollTimer);
758
- if (gptPollTimer)
759
- clearInterval(gptPollTimer);
760
- if (quotaPollTimer)
761
- quotaPollTimer.stopPolling();
762
- if (resolvedStatusPid) {
763
- try {
764
- unlinkSync(`${STATUS_TEE_DIR}/${resolvedStatusPid}.json`);
765
- }
766
- catch { /* ignore */ }
767
- }
768
- if (sessionRef?.removeListener) {
769
- sessionRef.removeListener('result', resultListener);
770
- }
771
- activeSessions.delete(name);
772
- recentlyFinishedSessions.set(name, { pipeline, queue, name, finishedAt: Date.now() });
773
- setTimeout(() => {
774
- const e = recentlyFinishedSessions.get(name);
775
- if (e && Date.now() - e.finishedAt >= FINISHED_SESSION_TTL_MS) {
776
- recentlyFinishedSessions.delete(name);
777
- }
778
- }, FINISHED_SESSION_TTL_MS + 100);
779
- const delegatedRef = delegatedCardStore.get(name);
780
- if (delegatedRef) {
781
- delegatedCardStore.delete(name);
782
- const collapsedText = '➡️ *Savvy* — delegated \\(complete\\)';
783
- editTg(delegatedRef.chatId, delegatedRef.cardMessageId, collapsedText, { inline_keyboard: [] })
784
- .catch(e => _logger.warn(`${PLUGIN_TAG} delegated card collapse failed: ${e.message}`));
785
- setTimeout(() => {
786
- telegramApi('deleteMessage', {
787
- chat_id: delegatedRef.chatId,
788
- message_id: delegatedRef.cardMessageId,
789
- }).catch(() => { });
790
- }, 5 * 60 * 1000);
791
- }
792
- }
793
- };
794
- SessionManager.prototype.sendMessage[PATCH_MARKER] = true;
795
- _logger.info(`${PLUGIN_TAG} SessionManager.sendMessage patched — UX pipeline active`);
796
- }
797
- // ── Stale status file cleanup ─────────────────────────────────────────────
798
- export function cleanStaleStatusFiles() {
799
- cleanStalePidFiles(STATUS_TEE_DIR, '.json');
800
- }
801
- // ── register() ────────────────────────────────────────────────────────────
802
- /**
803
- * Register the live-card plugin hooks.
804
- * Idempotent — subsequent calls are no-ops.
805
- */
806
- export function register(api) {
807
- setLogger(api.logger || console);
808
- defaultRegisterGuard.guard('channels/telegram/live-card', api, () => {
809
- // Read bot token from api.config first, then filesystem fallback
810
- try {
811
- const cfg = api.config || {};
812
- const tgChannels = cfg.channels?.telegram;
813
- if (tgChannels?.accounts) {
814
- const acctKey = tgChannels.defaultAccount || 'default';
815
- const acct = tgChannels.accounts[acctKey] || {};
816
- BOT_TOKEN = acct.botToken || '';
817
- }
818
- }
819
- catch { /* fall through to filesystem */ }
820
- if (!BOT_TOKEN) {
821
- try {
822
- const raw = readFileSync(OPENCLAW_CONFIG_PATH, 'utf8');
823
- const ocConfig = JSON.parse(raw);
824
- const tgChannels = ocConfig.channels?.telegram;
825
- if (tgChannels?.accounts) {
826
- const acctKey = tgChannels.defaultAccount || 'default';
827
- const acct = tgChannels.accounts[acctKey] || {};
828
- BOT_TOKEN = acct.botToken || '';
829
- }
830
- if (BOT_TOKEN) {
831
- _logger.info(`${PLUGIN_TAG} Telegram credentials loaded from ${OPENCLAW_CONFIG_PATH}`);
832
- }
833
- }
834
- catch (err) {
835
- _logger.warn(`${PLUGIN_TAG} Filesystem config fallback failed: ${err.message}`);
836
- }
837
- }
838
- if (!BOT_TOKEN) {
839
- _logger.warn(`${PLUGIN_TAG} No Telegram bot token found — plugin will be inactive`);
840
- }
841
- if (api.registerService) {
842
- api.registerService({
843
- id: 'telegram-ux-bridge',
844
- start: async () => {
845
- _logger.info(`${PLUGIN_TAG} Initialising via service lifecycle...`);
846
- await applyPatch();
847
- },
848
- stop: () => {
849
- _logger.info(`${PLUGIN_TAG} Stopped`);
850
- },
851
- });
852
- }
853
- if (BOT_TOKEN) {
854
- if (isTestMode()) {
855
- _logger.info(`${PLUGIN_TAG} TEST_MODE=1 — skipping eager SessionManager.sendMessage patch and stale status file cleanup`);
856
- }
857
- else {
858
- _logger.info(`${PLUGIN_TAG} Eagerly applying SessionManager patch...`);
859
- cleanStaleStatusFiles();
860
- applyPatch().catch((err) => {
861
- _logger.error(`${PLUGIN_TAG} Eager patch failed: ${err.message}`);
862
- });
863
- }
864
- }
865
- _logger.info(`${PLUGIN_TAG} live-card hooks registered`);
866
- }); // end defaultRegisterGuard.guard
867
- }
868
- //# sourceMappingURL=live-card.js.map