@a1hvdy/cc-openclaw 0.10.4 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (275) hide show
  1. package/dist/src/channels/telegram/card-renderer.d.ts +63 -0
  2. package/dist/src/channels/telegram/card-renderer.js +149 -0
  3. package/dist/src/channels/telegram/card-renderer.js.map +1 -0
  4. package/dist/src/channels/telegram/insight-formatter.d.ts +36 -0
  5. package/dist/src/channels/telegram/insight-formatter.js +36 -0
  6. package/dist/src/channels/telegram/insight-formatter.js.map +1 -0
  7. package/dist/src/channels/telegram/live-card.d.ts +7 -90
  8. package/dist/src/channels/telegram/live-card.js +22 -265
  9. package/dist/src/channels/telegram/live-card.js.map +1 -1
  10. package/dist/src/channels/telegram/logger.d.ts +10 -0
  11. package/dist/src/channels/telegram/logger.js +13 -0
  12. package/dist/src/channels/telegram/logger.js.map +1 -0
  13. package/dist/src/channels/telegram/throttle-controller.d.ts +54 -0
  14. package/dist/src/channels/telegram/throttle-controller.js +132 -0
  15. package/dist/src/channels/telegram/throttle-controller.js.map +1 -0
  16. package/dist/src/channels/telegram/tool-tracker.js +3 -14
  17. package/dist/src/channels/telegram/tool-tracker.js.map +1 -1
  18. package/dist/src/cli/doctor.d.ts +24 -0
  19. package/dist/src/cli/doctor.js +194 -0
  20. package/dist/src/cli/doctor.js.map +1 -0
  21. package/dist/src/cli/index.d.ts +8 -0
  22. package/dist/src/cli/index.js +39 -0
  23. package/dist/src/cli/index.js.map +1 -0
  24. package/dist/src/command-router/cc-handler.js +35 -709
  25. package/dist/src/command-router/cc-handler.js.map +1 -1
  26. package/dist/src/command-router/launch-policy.d.ts +93 -0
  27. package/dist/src/command-router/launch-policy.js +323 -0
  28. package/dist/src/command-router/launch-policy.js.map +1 -0
  29. package/dist/src/command-router/resume-policy.d.ts +18 -0
  30. package/dist/src/command-router/resume-policy.js +236 -0
  31. package/dist/src/command-router/resume-policy.js.map +1 -0
  32. package/dist/src/command-router/turn-formatter.d.ts +19 -0
  33. package/dist/src/command-router/turn-formatter.js +144 -0
  34. package/dist/src/command-router/turn-formatter.js.map +1 -0
  35. package/dist/src/openai-compat/bridges/allowlist.d.ts +10 -0
  36. package/dist/src/openai-compat/bridges/allowlist.js +17 -0
  37. package/dist/src/openai-compat/bridges/allowlist.js.map +1 -0
  38. package/dist/src/openai-compat/bridges/factory.d.ts +30 -0
  39. package/dist/src/openai-compat/bridges/factory.js +84 -0
  40. package/dist/src/openai-compat/bridges/factory.js.map +1 -0
  41. package/dist/src/openai-compat/bridges/media-bridge.d.ts +34 -0
  42. package/dist/src/openai-compat/bridges/media-bridge.js +20 -0
  43. package/dist/src/openai-compat/bridges/media-bridge.js.map +1 -0
  44. package/dist/src/openai-compat/bridges/openclaw-native-tools.d.ts +61 -0
  45. package/dist/src/openai-compat/bridges/openclaw-native-tools.js +171 -0
  46. package/dist/src/openai-compat/bridges/openclaw-native-tools.js.map +1 -0
  47. package/dist/src/openai-compat/bridges/openclaw-tool-registry.d.ts +26 -0
  48. package/dist/src/openai-compat/bridges/openclaw-tool-registry.js +38 -0
  49. package/dist/src/openai-compat/bridges/openclaw-tool-registry.js.map +1 -0
  50. package/dist/src/openai-compat/bridges/tts-media-bridge.d.ts +19 -0
  51. package/dist/src/openai-compat/bridges/tts-media-bridge.js +59 -0
  52. package/dist/src/openai-compat/bridges/tts-media-bridge.js.map +1 -0
  53. package/dist/src/openai-compat/openai-compat.js.map +1 -1
  54. package/dist/src/types/tool-bridge.d.ts +2 -1
  55. package/dist/src/types/tool-bridge.js +1 -0
  56. package/dist/src/types/tool-bridge.js.map +1 -1
  57. package/package.json +1 -1
  58. package/dist/scripts/bench/ab-harness.d.ts +0 -58
  59. package/dist/scripts/bench/ab-harness.d.ts.map +0 -1
  60. package/dist/scripts/bench/ab-harness.js +0 -78
  61. package/dist/scripts/bench/ab-harness.js.map +0 -1
  62. package/dist/src/channels/adapter.d.ts.map +0 -1
  63. package/dist/src/channels/telegram/completion-summary.d.ts.map +0 -1
  64. package/dist/src/channels/telegram/error-renderer.d.ts.map +0 -1
  65. package/dist/src/channels/telegram/event-reducer.d.ts.map +0 -1
  66. package/dist/src/channels/telegram/index.d.ts.map +0 -1
  67. package/dist/src/channels/telegram/injector.d.ts.map +0 -1
  68. package/dist/src/channels/telegram/live-card.d.ts.map +0 -1
  69. package/dist/src/channels/telegram/state-machine.d.ts.map +0 -1
  70. package/dist/src/channels/telegram/tool-tracker.d.ts.map +0 -1
  71. package/dist/src/command-router/cc-handler.d.ts.map +0 -1
  72. package/dist/src/command-router/index.d.ts.map +0 -1
  73. package/dist/src/constants.d.ts.map +0 -1
  74. package/dist/src/council/consensus.d.ts.map +0 -1
  75. package/dist/src/council/council.d.ts.map +0 -1
  76. package/dist/src/council/index.d.ts.map +0 -1
  77. package/dist/src/engines/base-oneshot-session.d.ts.map +0 -1
  78. package/dist/src/engines/index.d.ts.map +0 -1
  79. package/dist/src/engines/persistent-codex-session.d.ts.map +0 -1
  80. package/dist/src/engines/persistent-cursor-session.d.ts.map +0 -1
  81. package/dist/src/engines/persistent-custom-session.d.ts.map +0 -1
  82. package/dist/src/engines/persistent-gemini-session.d.ts.map +0 -1
  83. package/dist/src/engines/persistent-session.d.ts.map +0 -1
  84. package/dist/src/health/handler.d.ts.map +0 -1
  85. package/dist/src/health/index.d.ts.map +0 -1
  86. package/dist/src/index.d.ts.map +0 -1
  87. package/dist/src/lib/auto-recovery.d.ts.map +0 -1
  88. package/dist/src/lib/cache-parity.d.ts.map +0 -1
  89. package/dist/src/lib/circuit-breaker.d.ts.map +0 -1
  90. package/dist/src/lib/config.d.ts.map +0 -1
  91. package/dist/src/lib/drift-detector.d.ts.map +0 -1
  92. package/dist/src/lib/error-formatter.d.ts.map +0 -1
  93. package/dist/src/lib/heartbeat-workaround.d.ts.map +0 -1
  94. package/dist/src/lib/index.d.ts.map +0 -1
  95. package/dist/src/lib/register-guard.d.ts.map +0 -1
  96. package/dist/src/lib/route-flag.d.ts +0 -49
  97. package/dist/src/lib/route-flag.d.ts.map +0 -1
  98. package/dist/src/lib/route-flag.js +0 -52
  99. package/dist/src/lib/route-flag.js.map +0 -1
  100. package/dist/src/lib/sysprompt-strip.d.ts.map +0 -1
  101. package/dist/src/lib/telemetry.d.ts.map +0 -1
  102. package/dist/src/lib/test-mode.d.ts.map +0 -1
  103. package/dist/src/lib/vendor-paths.d.ts.map +0 -1
  104. package/dist/src/logger.d.ts.map +0 -1
  105. package/dist/src/mcp/bridge.d.ts.map +0 -1
  106. package/dist/src/mcp/index.d.ts.map +0 -1
  107. package/dist/src/models.d.ts.map +0 -1
  108. package/dist/src/openai-compat/cli-stream-parser.d.ts.map +0 -1
  109. package/dist/src/openai-compat/index.d.ts.map +0 -1
  110. package/dist/src/openai-compat/openai-compat.d.ts.map +0 -1
  111. package/dist/src/openai-compat/skill-resolver.d.ts.map +0 -1
  112. package/dist/src/openai-compat/sse-translator.d.ts.map +0 -1
  113. package/dist/src/proxy/anthropic-adapter.d.ts.map +0 -1
  114. package/dist/src/proxy/handler.d.ts.map +0 -1
  115. package/dist/src/proxy/index.d.ts.map +0 -1
  116. package/dist/src/proxy/schema-cleaner.d.ts.map +0 -1
  117. package/dist/src/proxy/thought-cache.d.ts.map +0 -1
  118. package/dist/src/session/embedded-server.d.ts.map +0 -1
  119. package/dist/src/session/inbox-manager.d.ts.map +0 -1
  120. package/dist/src/session/index.d.ts.map +0 -1
  121. package/dist/src/session/session-manager.d.ts.map +0 -1
  122. package/dist/src/session-bootstrap/cwd-patch.d.ts.map +0 -1
  123. package/dist/src/session-bootstrap/index.d.ts.map +0 -1
  124. package/dist/src/session-bootstrap/sysprompt-strip.d.ts.map +0 -1
  125. package/dist/src/session-bootstrap/think-conflict-resolver.d.ts.map +0 -1
  126. package/dist/src/types.d.ts.map +0 -1
  127. package/dist/src/validation.d.ts.map +0 -1
  128. package/dist/tests/_helpers/subprocess-mock.d.ts +0 -35
  129. package/dist/tests/_helpers/subprocess-mock.d.ts.map +0 -1
  130. package/dist/tests/_helpers/subprocess-mock.js +0 -136
  131. package/dist/tests/_helpers/subprocess-mock.js.map +0 -1
  132. package/dist/tests/auto-recovery.test.d.ts +0 -2
  133. package/dist/tests/auto-recovery.test.d.ts.map +0 -1
  134. package/dist/tests/auto-recovery.test.js +0 -185
  135. package/dist/tests/auto-recovery.test.js.map +0 -1
  136. package/dist/tests/bench-harness.test.d.ts +0 -2
  137. package/dist/tests/bench-harness.test.d.ts.map +0 -1
  138. package/dist/tests/bench-harness.test.js +0 -21
  139. package/dist/tests/bench-harness.test.js.map +0 -1
  140. package/dist/tests/cache-parity.test.d.ts +0 -2
  141. package/dist/tests/cache-parity.test.d.ts.map +0 -1
  142. package/dist/tests/cache-parity.test.js +0 -401
  143. package/dist/tests/cache-parity.test.js.map +0 -1
  144. package/dist/tests/command-router.test.d.ts +0 -2
  145. package/dist/tests/command-router.test.d.ts.map +0 -1
  146. package/dist/tests/command-router.test.js +0 -60
  147. package/dist/tests/command-router.test.js.map +0 -1
  148. package/dist/tests/council.test.d.ts +0 -2
  149. package/dist/tests/council.test.d.ts.map +0 -1
  150. package/dist/tests/council.test.js +0 -20
  151. package/dist/tests/council.test.js.map +0 -1
  152. package/dist/tests/drift-detector.test.d.ts +0 -2
  153. package/dist/tests/drift-detector.test.d.ts.map +0 -1
  154. package/dist/tests/drift-detector.test.js +0 -268
  155. package/dist/tests/drift-detector.test.js.map +0 -1
  156. package/dist/tests/eager-bootstrap-gating.test.d.ts +0 -9
  157. package/dist/tests/eager-bootstrap-gating.test.d.ts.map +0 -1
  158. package/dist/tests/eager-bootstrap-gating.test.js +0 -97
  159. package/dist/tests/eager-bootstrap-gating.test.js.map +0 -1
  160. package/dist/tests/engines.test.d.ts +0 -2
  161. package/dist/tests/engines.test.d.ts.map +0 -1
  162. package/dist/tests/engines.test.js +0 -8
  163. package/dist/tests/engines.test.js.map +0 -1
  164. package/dist/tests/error-formatter.test.d.ts +0 -2
  165. package/dist/tests/error-formatter.test.d.ts.map +0 -1
  166. package/dist/tests/error-formatter.test.js +0 -220
  167. package/dist/tests/error-formatter.test.js.map +0 -1
  168. package/dist/tests/health.test.d.ts +0 -2
  169. package/dist/tests/health.test.d.ts.map +0 -1
  170. package/dist/tests/health.test.js +0 -110
  171. package/dist/tests/health.test.js.map +0 -1
  172. package/dist/tests/heartbeat-workaround.test.d.ts +0 -2
  173. package/dist/tests/heartbeat-workaround.test.d.ts.map +0 -1
  174. package/dist/tests/heartbeat-workaround.test.js +0 -90
  175. package/dist/tests/heartbeat-workaround.test.js.map +0 -1
  176. package/dist/tests/index.test.d.ts +0 -2
  177. package/dist/tests/index.test.d.ts.map +0 -1
  178. package/dist/tests/index.test.js +0 -7
  179. package/dist/tests/index.test.js.map +0 -1
  180. package/dist/tests/lib-sysprompt-strip.test.d.ts +0 -2
  181. package/dist/tests/lib-sysprompt-strip.test.d.ts.map +0 -1
  182. package/dist/tests/lib-sysprompt-strip.test.js +0 -145
  183. package/dist/tests/lib-sysprompt-strip.test.js.map +0 -1
  184. package/dist/tests/listener-activation.test.d.ts +0 -2
  185. package/dist/tests/listener-activation.test.d.ts.map +0 -1
  186. package/dist/tests/listener-activation.test.js +0 -87
  187. package/dist/tests/listener-activation.test.js.map +0 -1
  188. package/dist/tests/mcp-bridge.test.d.ts +0 -2
  189. package/dist/tests/mcp-bridge.test.d.ts.map +0 -1
  190. package/dist/tests/mcp-bridge.test.js +0 -137
  191. package/dist/tests/mcp-bridge.test.js.map +0 -1
  192. package/dist/tests/openai-compat.test.d.ts +0 -2
  193. package/dist/tests/openai-compat.test.d.ts.map +0 -1
  194. package/dist/tests/openai-compat.test.js +0 -8
  195. package/dist/tests/openai-compat.test.js.map +0 -1
  196. package/dist/tests/proxy-heartbeat-integration.test.d.ts +0 -15
  197. package/dist/tests/proxy-heartbeat-integration.test.d.ts.map +0 -1
  198. package/dist/tests/proxy-heartbeat-integration.test.js +0 -122
  199. package/dist/tests/proxy-heartbeat-integration.test.js.map +0 -1
  200. package/dist/tests/proxy.test.d.ts +0 -2
  201. package/dist/tests/proxy.test.d.ts.map +0 -1
  202. package/dist/tests/proxy.test.js +0 -8
  203. package/dist/tests/proxy.test.js.map +0 -1
  204. package/dist/tests/register-guard-stacking.test.d.ts +0 -2
  205. package/dist/tests/register-guard-stacking.test.d.ts.map +0 -1
  206. package/dist/tests/register-guard-stacking.test.js +0 -61
  207. package/dist/tests/register-guard-stacking.test.js.map +0 -1
  208. package/dist/tests/register-guard.test.d.ts +0 -2
  209. package/dist/tests/register-guard.test.d.ts.map +0 -1
  210. package/dist/tests/register-guard.test.js +0 -129
  211. package/dist/tests/register-guard.test.js.map +0 -1
  212. package/dist/tests/route-flag-rollback.test.d.ts +0 -2
  213. package/dist/tests/route-flag-rollback.test.d.ts.map +0 -1
  214. package/dist/tests/route-flag-rollback.test.js +0 -70
  215. package/dist/tests/route-flag-rollback.test.js.map +0 -1
  216. package/dist/tests/route-flag.test.d.ts +0 -2
  217. package/dist/tests/route-flag.test.d.ts.map +0 -1
  218. package/dist/tests/route-flag.test.js +0 -101
  219. package/dist/tests/route-flag.test.js.map +0 -1
  220. package/dist/tests/session-bootstrap.test.d.ts +0 -2
  221. package/dist/tests/session-bootstrap.test.d.ts.map +0 -1
  222. package/dist/tests/session-bootstrap.test.js +0 -183
  223. package/dist/tests/session-bootstrap.test.js.map +0 -1
  224. package/dist/tests/session.test.d.ts +0 -2
  225. package/dist/tests/session.test.d.ts.map +0 -1
  226. package/dist/tests/session.test.js +0 -17
  227. package/dist/tests/session.test.js.map +0 -1
  228. package/dist/tests/state-machine.test.d.ts +0 -2
  229. package/dist/tests/state-machine.test.d.ts.map +0 -1
  230. package/dist/tests/state-machine.test.js +0 -133
  231. package/dist/tests/state-machine.test.js.map +0 -1
  232. package/dist/tests/streaming/cli-stream-parser.test.d.ts +0 -2
  233. package/dist/tests/streaming/cli-stream-parser.test.d.ts.map +0 -1
  234. package/dist/tests/streaming/cli-stream-parser.test.js +0 -233
  235. package/dist/tests/streaming/cli-stream-parser.test.js.map +0 -1
  236. package/dist/tests/streaming/feature-flag.test.d.ts +0 -14
  237. package/dist/tests/streaming/feature-flag.test.d.ts.map +0 -1
  238. package/dist/tests/streaming/feature-flag.test.js +0 -163
  239. package/dist/tests/streaming/feature-flag.test.js.map +0 -1
  240. package/dist/tests/streaming/no-tools-prompt.test.d.ts +0 -17
  241. package/dist/tests/streaming/no-tools-prompt.test.d.ts.map +0 -1
  242. package/dist/tests/streaming/no-tools-prompt.test.js +0 -229
  243. package/dist/tests/streaming/no-tools-prompt.test.js.map +0 -1
  244. package/dist/tests/streaming/skill-plus-tools.test.d.ts +0 -14
  245. package/dist/tests/streaming/skill-plus-tools.test.d.ts.map +0 -1
  246. package/dist/tests/streaming/skill-plus-tools.test.js +0 -234
  247. package/dist/tests/streaming/skill-plus-tools.test.js.map +0 -1
  248. package/dist/tests/streaming/sse-translator.test.d.ts +0 -2
  249. package/dist/tests/streaming/sse-translator.test.d.ts.map +0 -1
  250. package/dist/tests/streaming/sse-translator.test.js +0 -227
  251. package/dist/tests/streaming/sse-translator.test.js.map +0 -1
  252. package/dist/tests/streaming/tool-result-roundtrip.test.d.ts +0 -11
  253. package/dist/tests/streaming/tool-result-roundtrip.test.d.ts.map +0 -1
  254. package/dist/tests/streaming/tool-result-roundtrip.test.js +0 -215
  255. package/dist/tests/streaming/tool-result-roundtrip.test.js.map +0 -1
  256. package/dist/tests/streaming/tool-use-translation.test.d.ts +0 -10
  257. package/dist/tests/streaming/tool-use-translation.test.d.ts.map +0 -1
  258. package/dist/tests/streaming/tool-use-translation.test.js +0 -251
  259. package/dist/tests/streaming/tool-use-translation.test.js.map +0 -1
  260. package/dist/tests/telegram-bridge.test.d.ts +0 -2
  261. package/dist/tests/telegram-bridge.test.d.ts.map +0 -1
  262. package/dist/tests/telegram-bridge.test.js +0 -17
  263. package/dist/tests/telegram-bridge.test.js.map +0 -1
  264. package/dist/tests/telegram-injector.test.d.ts +0 -2
  265. package/dist/tests/telegram-injector.test.d.ts.map +0 -1
  266. package/dist/tests/telegram-injector.test.js +0 -74
  267. package/dist/tests/telegram-injector.test.js.map +0 -1
  268. package/dist/tests/telemetry.test.d.ts +0 -2
  269. package/dist/tests/telemetry.test.d.ts.map +0 -1
  270. package/dist/tests/telemetry.test.js +0 -405
  271. package/dist/tests/telemetry.test.js.map +0 -1
  272. package/dist/tests/test-mode.test.d.ts +0 -2
  273. package/dist/tests/test-mode.test.d.ts.map +0 -1
  274. package/dist/tests/test-mode.test.js +0 -39
  275. package/dist/tests/test-mode.test.js.map +0 -1
@@ -0,0 +1,236 @@
1
+ /**
2
+ * resume-policy — /cc+ continuation, /cc resume, rehydrate, and turn-extension logic.
3
+ *
4
+ * Extracted from cc-handler.ts (Step 4 of Phase 5 v0.11.0 decomposition).
5
+ * Each public function takes PolicyDeps as its first argument per PRP §7 Q3.
6
+ * cc-handler.ts retains ownership of the sessionManager/activeSessions/logger
7
+ * singletons and threads them in via `_deps()` on every call.
8
+ *
9
+ * Callers MUST verify `sessionManager !== null` before constructing deps:
10
+ * PolicyDeps.sessionManager is typed non-null and these handlers assume it.
11
+ * The "Claude Code handler not ready — try again in a few seconds." response
12
+ * is now produced at the dispatcher in cc-handler.ts.
13
+ */
14
+ import { DEFAULT_CWD, sessionMapKey, saveSession, loadSession, loadSessionById, scanAllSessions, IDLE_TIMEOUT_MS, ACK_TIMEOUT_MS, scheduleIdle, _postTurnContextCheck, } from './launch-policy.js';
15
+ import { sendDirectReply } from './turn-formatter.js';
16
+ const PLUGIN_TAG = '[cc-openclaw/resume-policy]';
17
+ // ── Continuation Handler ──────────────────────────────────────────────────
18
+ export function handleContinuation(deps, prompt, chatId, threadId) {
19
+ const { sessionManager, activeSessions, logger } = deps;
20
+ const key = sessionMapKey(chatId, threadId);
21
+ const active = activeSessions.get(key);
22
+ if (!active) {
23
+ return {
24
+ handled: true,
25
+ text: 'No active session to continue. Start one with /cc <prompt> or /cc resume',
26
+ };
27
+ }
28
+ if (active.needsRehydration) {
29
+ if (!active.meta.claudeSessionId) {
30
+ activeSessions.delete(key);
31
+ return {
32
+ handled: true,
33
+ text: 'Recovered session has no Claude ID — start fresh with /cc <prompt>',
34
+ };
35
+ }
36
+ logger.info(`${PLUGIN_TAG} /cc+ rehydrating recovered session: slug=${active.slug} chat=${chatId} thread=${threadId || 'none'}`);
37
+ let resolveAckId;
38
+ const ackIdPromise = new Promise((r) => {
39
+ resolveAckId = r;
40
+ });
41
+ (async () => {
42
+ try {
43
+ await rehydrateSession(deps, active.meta, chatId, threadId);
44
+ active.needsRehydration = false;
45
+ await continueTurn(deps, active, prompt, chatId, threadId, ackIdPromise);
46
+ }
47
+ catch (err) {
48
+ logger.error(`${PLUGIN_TAG} Rehydrate+continue ${active.slug} failed: ${err instanceof Error ? err.message : String(err)}`);
49
+ scheduleIdle(deps, key, active);
50
+ }
51
+ })();
52
+ return {
53
+ handled: true,
54
+ text: `⏳ [${active.meta.id || '?'}] Resuming & continuing ${active.slug}...`,
55
+ _resolveAckId: resolveAckId,
56
+ };
57
+ }
58
+ try {
59
+ sessionManager.getStatus(active.sessionName);
60
+ }
61
+ catch {
62
+ activeSessions.delete(key);
63
+ return {
64
+ handled: true,
65
+ text: 'Previous session expired. Use /cc resume or start fresh with /cc <prompt>',
66
+ };
67
+ }
68
+ if (active.idleTimer)
69
+ clearTimeout(active.idleTimer);
70
+ logger.info(`${PLUGIN_TAG} /cc+ continuation: slug=${active.slug} chat=${chatId} thread=${threadId || 'none'}`);
71
+ let resolveAckId;
72
+ const ackIdPromise = new Promise((r) => {
73
+ resolveAckId = r;
74
+ });
75
+ continueTurn(deps, active, prompt, chatId, threadId, ackIdPromise).catch((err) => {
76
+ logger.error(`${PLUGIN_TAG} Continuation ${active.slug} failed: ${err instanceof Error ? err.message : String(err)}`);
77
+ scheduleIdle(deps, key, active);
78
+ });
79
+ return {
80
+ handled: true,
81
+ text: `⏳ [${active.meta.id || '?'}] Continuing ${active.slug}...`,
82
+ _resolveAckId: resolveAckId,
83
+ };
84
+ }
85
+ // ── Resume Handler ────────────────────────────────────────────────────────
86
+ export function handleResume(deps, chatId, threadId, targetSlug) {
87
+ const { activeSessions, logger } = deps;
88
+ const key = sessionMapKey(chatId, threadId);
89
+ const currentActive = activeSessions.get(key);
90
+ if (currentActive) {
91
+ return {
92
+ handled: true,
93
+ text: `Already have active session: ${currentActive.slug}\nUse /cc stop first, or /cc+ to continue it.`,
94
+ };
95
+ }
96
+ let meta = null;
97
+ if (targetSlug) {
98
+ const isSessionId = /^[0-9a-f]{8}$/i.test(targetSlug);
99
+ if (isSessionId) {
100
+ meta = loadSessionById(targetSlug.toLowerCase());
101
+ }
102
+ if (!meta) {
103
+ meta = loadSession(targetSlug);
104
+ }
105
+ if (!meta) {
106
+ return { handled: true, text: `Session "${targetSlug}" not found.` };
107
+ }
108
+ if (meta.chatId !== chatId) {
109
+ return {
110
+ handled: true,
111
+ text: `Session "${targetSlug}" belongs to a different chat.`,
112
+ };
113
+ }
114
+ }
115
+ else {
116
+ const candidates = scanAllSessions()
117
+ .filter((s) => s.chatId === chatId &&
118
+ (s.threadId || undefined) === (threadId || undefined) &&
119
+ !!s.claudeSessionId)
120
+ .sort((a, b) => {
121
+ const timeA = new Date(a.lastContinuedAt || a.completedAt || a.startedAt).getTime();
122
+ const timeB = new Date(b.lastContinuedAt || b.completedAt || b.startedAt).getTime();
123
+ return timeB - timeA;
124
+ });
125
+ if (candidates.length === 0) {
126
+ return {
127
+ handled: true,
128
+ text: 'No resumable session found. Start fresh with /cc <prompt>',
129
+ };
130
+ }
131
+ meta = candidates[0];
132
+ }
133
+ if (!meta.claudeSessionId) {
134
+ return {
135
+ handled: true,
136
+ text: `Session ${meta.slug} has no Claude session ID — cannot resume.\nStart fresh with /cc <prompt>`,
137
+ };
138
+ }
139
+ const { slug, id: resumeId } = meta;
140
+ logger.info(`${PLUGIN_TAG} /cc resume: id=${resumeId} slug=${slug} claudeId=${meta.claudeSessionId} chat=${chatId} thread=${threadId || 'none'}`);
141
+ rehydrateSession(deps, meta, chatId, threadId).catch((err) => {
142
+ logger.error(`${PLUGIN_TAG} Resume ${slug} failed: ${err instanceof Error ? err.message : String(err)}`);
143
+ meta.state = 'failed';
144
+ meta.error = `Resume failed: ${err instanceof Error ? err.message : String(err)}`;
145
+ try {
146
+ saveSession(meta);
147
+ }
148
+ catch { /* best effort */ }
149
+ const active = activeSessions.get(key);
150
+ if (active?.slug === slug) {
151
+ if (active.idleTimer)
152
+ clearTimeout(active.idleTimer);
153
+ activeSessions.delete(key);
154
+ }
155
+ });
156
+ return { handled: true, text: `⏳ [${resumeId || '?'}] Resuming ${slug}...` };
157
+ }
158
+ // ── Rehydrate Session ─────────────────────────────────────────────────────
159
+ export async function rehydrateSession(deps, meta, chatId, threadId) {
160
+ const { sessionManager, activeSessions, logger } = deps;
161
+ const { slug, sessionName, claudeSessionId } = meta;
162
+ const key = sessionMapKey(chatId, threadId);
163
+ logger.info(`${PLUGIN_TAG} Rehydrating ${sessionName} with claudeSessionId=${claudeSessionId}...`);
164
+ await sessionManager.startSession({
165
+ name: sessionName,
166
+ cwd: meta.cwd || DEFAULT_CWD,
167
+ engine: 'claude',
168
+ permissionMode: 'bypassPermissions',
169
+ effort: 'high',
170
+ resumeSessionId: claudeSessionId,
171
+ });
172
+ const prevActive = activeSessions.get(key);
173
+ if (prevActive && prevActive.sessionName !== sessionName) {
174
+ if (prevActive.idleTimer)
175
+ clearTimeout(prevActive.idleTimer);
176
+ try {
177
+ await sessionManager.stopSession(prevActive.sessionName);
178
+ }
179
+ catch { /* ignore */ }
180
+ }
181
+ meta.state = 'idle';
182
+ meta.threadId = threadId;
183
+ meta.lastContinuedAt = new Date().toISOString();
184
+ try {
185
+ saveSession(meta);
186
+ }
187
+ catch { /* best effort */ }
188
+ const activeEntry = { sessionName, slug, meta, idleTimer: null };
189
+ activeSessions.set(key, activeEntry);
190
+ logger.info(`${PLUGIN_TAG} Session ${sessionName} resumed — idle for ${IDLE_TIMEOUT_MS / 1000}s`);
191
+ scheduleIdle(deps, key, activeEntry);
192
+ }
193
+ // ── Continuation Turn ─────────────────────────────────────────────────────
194
+ export async function continueTurn(deps, active, prompt, chatId, threadId, ackIdPromise) {
195
+ const { sessionManager, logger } = deps;
196
+ const { sessionName, meta } = active;
197
+ const key = sessionMapKey(chatId, threadId);
198
+ meta.state = 'running';
199
+ try {
200
+ saveSession(meta);
201
+ }
202
+ catch { /* best effort */ }
203
+ const opts = { telegramChatId: chatId };
204
+ if (threadId)
205
+ opts.telegramThreadId = threadId;
206
+ const ackMsgId = await Promise.race([
207
+ ackIdPromise,
208
+ new Promise((r) => setTimeout(() => r(null), ACK_TIMEOUT_MS)),
209
+ ]);
210
+ if (ackMsgId)
211
+ opts.telegramAckMessageId = ackMsgId;
212
+ const result = await sessionManager.sendMessage(sessionName, prompt, opts);
213
+ meta.state = 'idle';
214
+ meta.turns = (meta.turns || 1) + 1;
215
+ meta.lastContinuedAt = new Date().toISOString();
216
+ meta.output = (result?.output || '').slice(0, 2000);
217
+ meta.claudeSessionId = result?.sessionId ?? meta.claudeSessionId;
218
+ try {
219
+ saveSession(meta);
220
+ }
221
+ catch { /* best effort */ }
222
+ // v0.6.0: post-turn context-pressure check (continuation turn).
223
+ void _postTurnContextCheck(deps, sessionName, chatId, threadId);
224
+ // 2026-05-07 FIX — direct answer delivery (continuation turn).
225
+ if (result?.output && chatId) {
226
+ try {
227
+ await sendDirectReply(chatId, threadId, result.output, logger);
228
+ }
229
+ catch (e) {
230
+ logger.warn(`${PLUGIN_TAG} Direct answer delivery failed for ${sessionName} (continuation): ${e instanceof Error ? e.message : String(e)}`);
231
+ }
232
+ }
233
+ logger.info(`${PLUGIN_TAG} Session ${sessionName} turn ${meta.turns} complete`);
234
+ scheduleIdle(deps, key, active);
235
+ }
236
+ //# sourceMappingURL=resume-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume-policy.js","sourceRoot":"","sources":["../../../src/command-router/resume-policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * turn-formatter — Telegram direct-send + observability formatting helpers.
3
+ *
4
+ * Extracted from cc-handler.ts (Step 1 of Phase 5 v0.11.0 decomposition).
5
+ * Contains: loadBotToken, telegramApiDirect, sendDirectReply,
6
+ * buildPhase2FlagsLine, buildObservabilityLines.
7
+ */
8
+ export declare function loadBotToken(logger?: Console): void;
9
+ export declare function sendDirectReply(chatId: string, threadId: string | undefined, text: string, logger?: Console): Promise<number | null>;
10
+ /** Returns the current BOT_TOKEN (for callers that need to check if it's set). */
11
+ export declare function hasBotToken(): boolean;
12
+ export declare function buildPhase2FlagsLine(): string;
13
+ /**
14
+ * Pillar C v0.4.0 — compose observability lines for /cc status panel.
15
+ * Reads from Pillar A metrics, Pillar B trajectory tail, and status-tee
16
+ * quota snapshot. Each source is independently fault-tolerant: if one
17
+ * fails, the line shows "?" rather than crashing the panel.
18
+ */
19
+ export declare function buildObservabilityLines(): string;
@@ -0,0 +1,144 @@
1
+ /**
2
+ * turn-formatter — Telegram direct-send + observability formatting helpers.
3
+ *
4
+ * Extracted from cc-handler.ts (Step 1 of Phase 5 v0.11.0 decomposition).
5
+ * Contains: loadBotToken, telegramApiDirect, sendDirectReply,
6
+ * buildPhase2FlagsLine, buildObservabilityLines.
7
+ */
8
+ import * as fs from 'node:fs';
9
+ import { request as httpsRequest } from 'node:https';
10
+ const PLUGIN_TAG = '[cc-openclaw/command-router]';
11
+ const OPENCLAW_CONFIG_PATH = '/home/a1xai/.openclaw/openclaw.json';
12
+ // ── Telegram Direct Send ──────────────────────────────────────────────────
13
+ let BOT_TOKEN = '';
14
+ export function loadBotToken(logger = console) {
15
+ if (BOT_TOKEN)
16
+ return;
17
+ try {
18
+ const raw = fs.readFileSync(OPENCLAW_CONFIG_PATH, 'utf8');
19
+ const cfg = JSON.parse(raw);
20
+ const tg = cfg.channels?.telegram;
21
+ if (tg?.accounts) {
22
+ const acctKey = tg.defaultAccount || 'default';
23
+ const acct = tg.accounts[acctKey] || {};
24
+ BOT_TOKEN = acct.botToken || '';
25
+ }
26
+ if (BOT_TOKEN)
27
+ logger.info(`${PLUGIN_TAG} Bot token loaded for direct replies`);
28
+ }
29
+ catch (err) {
30
+ logger.warn(`${PLUGIN_TAG} Failed to load bot token: ${err instanceof Error ? err.message : String(err)}`);
31
+ }
32
+ }
33
+ function telegramApiDirect(method, params) {
34
+ return new Promise((resolve, reject) => {
35
+ const body = JSON.stringify(params);
36
+ const options = {
37
+ hostname: 'api.telegram.org',
38
+ path: `/bot${BOT_TOKEN}/${method}`,
39
+ method: 'POST',
40
+ headers: {
41
+ 'Content-Type': 'application/json',
42
+ 'Content-Length': Buffer.byteLength(body),
43
+ },
44
+ };
45
+ const req = httpsRequest(options, (res) => {
46
+ let data = '';
47
+ res.on('data', (chunk) => (data += chunk));
48
+ res.on('end', () => {
49
+ try {
50
+ resolve(JSON.parse(data));
51
+ }
52
+ catch {
53
+ resolve({ ok: false });
54
+ }
55
+ });
56
+ });
57
+ req.on('error', reject);
58
+ req.setTimeout(10_000, () => req.destroy(new Error('Telegram API timeout')));
59
+ req.write(body);
60
+ req.end();
61
+ });
62
+ }
63
+ export async function sendDirectReply(chatId, threadId, text, logger = console) {
64
+ if (!BOT_TOKEN || !chatId)
65
+ return null;
66
+ try {
67
+ const params = {
68
+ chat_id: chatId,
69
+ text,
70
+ disable_web_page_preview: true,
71
+ };
72
+ if (threadId)
73
+ params.message_thread_id = Number(threadId);
74
+ const res = await telegramApiDirect('sendMessage', params);
75
+ if (!res.ok) {
76
+ logger.warn(`${PLUGIN_TAG} Direct reply failed: ${JSON.stringify(res.description || res)}`);
77
+ return null;
78
+ }
79
+ return res.result?.message_id ?? null;
80
+ }
81
+ catch (err) {
82
+ logger.warn(`${PLUGIN_TAG} Direct reply error: ${err instanceof Error ? err.message : String(err)}`);
83
+ return null;
84
+ }
85
+ }
86
+ /** Returns the current BOT_TOKEN (for callers that need to check if it's set). */
87
+ export function hasBotToken() {
88
+ return BOT_TOKEN !== '';
89
+ }
90
+ // ── Phase 2 Flags ─────────────────────────────────────────────────────────
91
+ export function buildPhase2FlagsLine() {
92
+ const allowBuiltins = process.env.CC_OPENCLAW_ALLOW_BUILTINS === '1';
93
+ const toolStream = process.env.CC_OPENCLAW_TOOL_STREAM === '1';
94
+ return `Flags: builtins=${allowBuiltins ? 'on' : 'off'} | toolstream=${toolStream ? 'on' : 'off'}`;
95
+ }
96
+ // ── Observability Lines ───────────────────────────────────────────────────
97
+ /**
98
+ * Pillar C v0.4.0 — compose observability lines for /cc status panel.
99
+ * Reads from Pillar A metrics, Pillar B trajectory tail, and status-tee
100
+ * quota snapshot. Each source is independently fault-tolerant: if one
101
+ * fails, the line shows "?" rather than crashing the panel.
102
+ */
103
+ export function buildObservabilityLines() {
104
+ const lines = [];
105
+ // Plan quota (status-tee)
106
+ try {
107
+ // Lazy require so this file remains testable without status-tee
108
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
109
+ const { readQuotaSnapshot, formatQuotaLine } = require('../lib/status-tee-reader.js');
110
+ lines.push(formatQuotaLine(readQuotaSnapshot()));
111
+ }
112
+ catch {
113
+ lines.push('Plan: ?%');
114
+ }
115
+ // Workers + uptime + last error (Pillar A metrics)
116
+ try {
117
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
118
+ const { metricsRegistry } = require('../health/metrics.js');
119
+ const out = metricsRegistry.serializePrometheus();
120
+ const workersMatch = /cc_openclaw_workers (\d+)/.exec(out);
121
+ const uptimeMatch = /cc_openclaw_uptime_seconds (\d+)/.exec(out);
122
+ const lastErrMatch = /cc_openclaw_last_error_seconds (\d+)/.exec(out);
123
+ const errorsMatch = /cc_openclaw_errors_total (\d+)/.exec(out);
124
+ const workers = workersMatch ? workersMatch[1] : '?';
125
+ const uptime = uptimeMatch ? Math.floor(parseInt(uptimeMatch[1], 10) / 60) : '?';
126
+ lines.push(`Workers: ${workers} | Uptime: ${uptime}m`);
127
+ const errCount = errorsMatch ? parseInt(errorsMatch[1], 10) : 0;
128
+ const lastErrTs = lastErrMatch ? parseInt(lastErrMatch[1], 10) : 0;
129
+ if (errCount === 0 || lastErrTs === 0) {
130
+ lines.push('Last error: none');
131
+ }
132
+ else {
133
+ const agoSec = Math.floor(Date.now() / 1000) - lastErrTs;
134
+ const agoLabel = agoSec < 60 ? `${agoSec}s` : agoSec < 3600 ? `${Math.floor(agoSec / 60)}m` : `${Math.floor(agoSec / 3600)}h`;
135
+ lines.push(`Last error: ${agoLabel} ago (${errCount} total)`);
136
+ }
137
+ }
138
+ catch {
139
+ lines.push('Workers: ? | Uptime: ?');
140
+ lines.push('Last error: ?');
141
+ }
142
+ return lines.join('\n');
143
+ }
144
+ //# sourceMappingURL=turn-formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turn-formatter.js","sourceRoot":"","sources":["../../../src/command-router/turn-formatter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * v0.11.0 — OpenClaw native tool allowlist.
3
+ *
4
+ * Hard-coded for v0.11.0 soak. `image.send` and `file.upload` are reserved
5
+ * but NOT active until v0.12.0. Flip will happen in allowlist.ts only — no
6
+ * other file needs to change.
7
+ */
8
+ export declare const OPENCLAW_TOOL_ALLOWLIST: ReadonlySet<string>;
9
+ /** Return true when `toolName` is in the v0.11.0 allowlist. */
10
+ export declare function isAllowedTool(toolName: string): boolean;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * v0.11.0 — OpenClaw native tool allowlist.
3
+ *
4
+ * Hard-coded for v0.11.0 soak. `image.send` and `file.upload` are reserved
5
+ * but NOT active until v0.12.0. Flip will happen in allowlist.ts only — no
6
+ * other file needs to change.
7
+ */
8
+ export const OPENCLAW_TOOL_ALLOWLIST = new Set([
9
+ 'message.voice',
10
+ // 'image.send', // reserved — v0.12.0
11
+ // 'file.upload', // reserved — v0.12.0
12
+ ]);
13
+ /** Return true when `toolName` is in the v0.11.0 allowlist. */
14
+ export function isAllowedTool(toolName) {
15
+ return OPENCLAW_TOOL_ALLOWLIST.has(toolName);
16
+ }
17
+ //# sourceMappingURL=allowlist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowlist.js","sourceRoot":"","sources":["../../../../src/openai-compat/bridges/allowlist.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,uBAAuB,GAAwB,IAAI,GAAG,CAAC;IAClE,eAAe;IACf,wCAAwC;IACxC,wCAAwC;CACzC,CAAC,CAAC;AAEH,+DAA+D;AAC/D,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,uBAAuB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * factory.ts — Bridge factory: reads env flags and returns the active IToolBridge.
3
+ *
4
+ * Mode precedence (highest wins):
5
+ * CC_OPENCLAW_NATIVE_TOOLS=1 → OpenClawNative (v0.11.0, default OFF)
6
+ * CC_OPENCLAW_TOOL_STREAM=1 → NativeStream
7
+ * OPENAI_COMPAT_TOOLS_PER_MESSAGE=1 → PerMessage
8
+ * (default) → Embedded
9
+ *
10
+ * The three existing modes (Embedded, PerMessage, NativeStream) are NOT
11
+ * implemented as full IToolBridge classes in this PR — their logic lives
12
+ * inside openai-compat.ts. The factory stubs them as thin wrappers that
13
+ * satisfy IToolBridge so callers can type-check against the interface.
14
+ * Only OpenClawNativeBridge is a real implementation here.
15
+ *
16
+ * Coexistence rule: existing flag readers (`isToolsPerMessageModeEnabled`,
17
+ * `isToolStreamMode`) are not touched — factory reads them via the same
18
+ * env vars, not via those helpers, to avoid coupling factory → mode-flags.
19
+ */
20
+ import type { IToolBridge } from '../../types/tool-bridge.js';
21
+ import { ToolMode } from '../../types/tool-bridge.js';
22
+ /**
23
+ * Return the active IToolBridge based on env flags.
24
+ *
25
+ * Call once per request — bridges are lightweight and stateless (except
26
+ * OpenClawNativeToolsBridge which caches the gateway config read).
27
+ */
28
+ export declare function makeToolBridge(): IToolBridge;
29
+ /** Read the active mode without constructing a bridge. Useful for logging. */
30
+ export declare function activeToolMode(): ToolMode;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * factory.ts — Bridge factory: reads env flags and returns the active IToolBridge.
3
+ *
4
+ * Mode precedence (highest wins):
5
+ * CC_OPENCLAW_NATIVE_TOOLS=1 → OpenClawNative (v0.11.0, default OFF)
6
+ * CC_OPENCLAW_TOOL_STREAM=1 → NativeStream
7
+ * OPENAI_COMPAT_TOOLS_PER_MESSAGE=1 → PerMessage
8
+ * (default) → Embedded
9
+ *
10
+ * The three existing modes (Embedded, PerMessage, NativeStream) are NOT
11
+ * implemented as full IToolBridge classes in this PR — their logic lives
12
+ * inside openai-compat.ts. The factory stubs them as thin wrappers that
13
+ * satisfy IToolBridge so callers can type-check against the interface.
14
+ * Only OpenClawNativeBridge is a real implementation here.
15
+ *
16
+ * Coexistence rule: existing flag readers (`isToolsPerMessageModeEnabled`,
17
+ * `isToolStreamMode`) are not touched — factory reads them via the same
18
+ * env vars, not via those helpers, to avoid coupling factory → mode-flags.
19
+ */
20
+ import { ToolMode } from '../../types/tool-bridge.js';
21
+ import { OpenClawNativeToolsBridge } from './openclaw-native-tools.js';
22
+ // ── Stub bridges for legacy modes ─────────────────────────────────────────
23
+ // These stubs let the factory return typed IToolBridge values for the existing
24
+ // modes. They are NOT functional implementations — the real logic lives in
25
+ // openai-compat.ts / streaming-handler.ts. Their presence here is purely for
26
+ // the mode-selection interface.
27
+ class EmbeddedToolsBridgeStub {
28
+ mode = ToolMode.Embedded;
29
+ buildToolPreamble(_tools) { return ''; }
30
+ translateToolUse(_event) { return null; }
31
+ serializeToolResult(call, result) {
32
+ return `<tool_result tool_use_id="${call.id}" name="${call.function.name}">${result}</tool_result>`;
33
+ }
34
+ }
35
+ class PerMessageToolsBridgeStub {
36
+ mode = ToolMode.PerMessage;
37
+ buildToolPreamble(_tools) { return ''; }
38
+ translateToolUse(_event) { return null; }
39
+ serializeToolResult(call, result) {
40
+ return `<tool_result tool_use_id="${call.id}" name="${call.function.name}">${result}</tool_result>`;
41
+ }
42
+ }
43
+ class NativeStreamToolsBridgeStub {
44
+ mode = ToolMode.NativeStream;
45
+ buildToolPreamble(_tools) { return ''; }
46
+ translateToolUse(_event) { return null; }
47
+ serializeToolResult(call, result) {
48
+ return `<tool_result tool_use_id="${call.id}" name="${call.function.name}">${result}</tool_result>`;
49
+ }
50
+ }
51
+ // ── Factory ────────────────────────────────────────────────────────────────
52
+ /**
53
+ * Return the active IToolBridge based on env flags.
54
+ *
55
+ * Call once per request — bridges are lightweight and stateless (except
56
+ * OpenClawNativeToolsBridge which caches the gateway config read).
57
+ */
58
+ export function makeToolBridge() {
59
+ // OpenClawNative: highest precedence, default OFF for v0.11.0 soak
60
+ if (process.env.CC_OPENCLAW_NATIVE_TOOLS === '1') {
61
+ return new OpenClawNativeToolsBridge();
62
+ }
63
+ // NativeStream
64
+ if (process.env.CC_OPENCLAW_TOOL_STREAM === '1') {
65
+ return new NativeStreamToolsBridgeStub();
66
+ }
67
+ // PerMessage (legacy)
68
+ if (process.env.OPENAI_COMPAT_TOOLS_PER_MESSAGE === '1') {
69
+ return new PerMessageToolsBridgeStub();
70
+ }
71
+ // Default: Embedded
72
+ return new EmbeddedToolsBridgeStub();
73
+ }
74
+ /** Read the active mode without constructing a bridge. Useful for logging. */
75
+ export function activeToolMode() {
76
+ if (process.env.CC_OPENCLAW_NATIVE_TOOLS === '1')
77
+ return ToolMode.OpenClawNative;
78
+ if (process.env.CC_OPENCLAW_TOOL_STREAM === '1')
79
+ return ToolMode.NativeStream;
80
+ if (process.env.OPENAI_COMPAT_TOOLS_PER_MESSAGE === '1')
81
+ return ToolMode.PerMessage;
82
+ return ToolMode.Embedded;
83
+ }
84
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../../src/openai-compat/bridges/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAEtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAEvE,6EAA6E;AAC7E,+EAA+E;AAC/E,2EAA2E;AAC3E,6EAA6E;AAC7E,gCAAgC;AAEhC,MAAM,uBAAuB;IAClB,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC;IAClC,iBAAiB,CAAC,MAAiD,IAAY,OAAO,EAAE,CAAC,CAAC,CAAC;IAC3F,gBAAgB,CAAC,MAAe,IAA4B,OAAO,IAAI,CAAC,CAAC,CAAC;IAC1E,mBAAmB,CAAC,IAAoB,EAAE,MAAc;QACtD,OAAO,6BAA6B,IAAI,CAAC,EAAE,WAAW,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,MAAM,gBAAgB,CAAC;IACtG,CAAC;CACF;AAED,MAAM,yBAAyB;IACpB,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC;IACpC,iBAAiB,CAAC,MAAiD,IAAY,OAAO,EAAE,CAAC,CAAC,CAAC;IAC3F,gBAAgB,CAAC,MAAe,IAA4B,OAAO,IAAI,CAAC,CAAC,CAAC;IAC1E,mBAAmB,CAAC,IAAoB,EAAE,MAAc;QACtD,OAAO,6BAA6B,IAAI,CAAC,EAAE,WAAW,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,MAAM,gBAAgB,CAAC;IACtG,CAAC;CACF;AAED,MAAM,2BAA2B;IACtB,IAAI,GAAG,QAAQ,CAAC,YAAY,CAAC;IACtC,iBAAiB,CAAC,MAAiD,IAAY,OAAO,EAAE,CAAC,CAAC,CAAC;IAC3F,gBAAgB,CAAC,MAAe,IAA4B,OAAO,IAAI,CAAC,CAAC,CAAC;IAC1E,mBAAmB,CAAC,IAAoB,EAAE,MAAc;QACtD,OAAO,6BAA6B,IAAI,CAAC,EAAE,WAAW,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,MAAM,gBAAgB,CAAC;IACtG,CAAC;CACF;AAED,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,cAAc;IAC5B,mEAAmE;IACnE,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,KAAK,GAAG,EAAE,CAAC;QACjD,OAAO,IAAI,yBAAyB,EAAE,CAAC;IACzC,CAAC;IACD,eAAe;IACf,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,GAAG,EAAE,CAAC;QAChD,OAAO,IAAI,2BAA2B,EAAE,CAAC;IAC3C,CAAC;IACD,sBAAsB;IACtB,IAAI,OAAO,CAAC,GAAG,CAAC,+BAA+B,KAAK,GAAG,EAAE,CAAC;QACxD,OAAO,IAAI,yBAAyB,EAAE,CAAC;IACzC,CAAC;IACD,oBAAoB;IACpB,OAAO,IAAI,uBAAuB,EAAE,CAAC;AACvC,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,cAAc;IAC5B,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,KAAK,GAAG;QAAE,OAAO,QAAQ,CAAC,cAAc,CAAC;IACjF,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,GAAG;QAAE,OAAO,QAAQ,CAAC,YAAY,CAAC;IAC9E,IAAI,OAAO,CAAC,GAAG,CAAC,+BAA+B,KAAK,GAAG;QAAE,OAAO,QAAQ,CAAC,UAAU,CAAC;IACpF,OAAO,QAAQ,CAAC,QAAQ,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * media-bridge.ts — Shared contract for media delivery bridges.
3
+ *
4
+ * `MediaBridge` is the interface all media-type sub-bridges implement.
5
+ * `TtsMediaBridge` (tts-media-bridge.ts) is the v0.11.0 concrete impl.
6
+ * Future: `ImageMediaBridge`, `FileMediaBridge` for v0.12.0.
7
+ */
8
+ /** Structured result from a media bridge execution. */
9
+ export interface MediaBridgeResult {
10
+ /** Text to inject into the SSE stream in place of the tool_call. */
11
+ readonly text: string;
12
+ /** Whether the bridge produced output via the native channel. */
13
+ readonly delivered: boolean;
14
+ /** Delivery channel used. Informational — not load-bearing. */
15
+ readonly via: string;
16
+ }
17
+ /** Every media sub-bridge must satisfy this contract. */
18
+ export interface MediaBridge {
19
+ /** Canonical tool name this bridge handles (e.g. `message.voice`). */
20
+ readonly toolName: string;
21
+ /**
22
+ * Execute the media delivery. `args` is the raw JSON-parsed tool arguments
23
+ * from the model's tool_call. Returns a `MediaBridgeResult` — never throws;
24
+ * fallback text is always produced on error.
25
+ */
26
+ execute(args: Record<string, unknown>): Promise<MediaBridgeResult>;
27
+ }
28
+ /** Thrown by bridge internals for structured error propagation.
29
+ * Caught at the `OpenClawNativeToolsBridge` boundary — never escapes to callers. */
30
+ export declare class MediaBridgeError extends Error {
31
+ readonly toolName: string;
32
+ readonly cause?: unknown | undefined;
33
+ constructor(message: string, toolName: string, cause?: unknown | undefined);
34
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * media-bridge.ts — Shared contract for media delivery bridges.
3
+ *
4
+ * `MediaBridge` is the interface all media-type sub-bridges implement.
5
+ * `TtsMediaBridge` (tts-media-bridge.ts) is the v0.11.0 concrete impl.
6
+ * Future: `ImageMediaBridge`, `FileMediaBridge` for v0.12.0.
7
+ */
8
+ /** Thrown by bridge internals for structured error propagation.
9
+ * Caught at the `OpenClawNativeToolsBridge` boundary — never escapes to callers. */
10
+ export class MediaBridgeError extends Error {
11
+ toolName;
12
+ cause;
13
+ constructor(message, toolName, cause) {
14
+ super(message);
15
+ this.toolName = toolName;
16
+ this.cause = cause;
17
+ this.name = 'MediaBridgeError';
18
+ }
19
+ }
20
+ //# sourceMappingURL=media-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-bridge.js","sourceRoot":"","sources":["../../../../src/openai-compat/bridges/media-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAyBH;qFACqF;AACrF,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAGvB;IACA;IAHlB,YACE,OAAe,EACC,QAAgB,EAChB,KAAe;QAE/B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,aAAQ,GAAR,QAAQ,CAAQ;QAChB,UAAK,GAAL,KAAK,CAAU;QAG/B,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF"}