@a1hvdy/cc-openclaw 0.30.0 → 0.32.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 (207) hide show
  1. package/dist/src/channels/telegram-mirror/card-renderer.js +9 -5
  2. package/dist/src/channels/telegram-mirror/commands.js +0 -8
  3. package/dist/src/channels/telegram-mirror/status-line.js +32 -2
  4. package/dist/src/constants.js +16 -2
  5. package/dist/src/engines/persistent-session.js +11 -0
  6. package/dist/src/lib/config.js +40 -0
  7. package/dist/src/openai-compat/non-streaming-handler.js +2 -2
  8. package/dist/src/openai-compat/streaming-handler.js +121 -9
  9. package/package.json +3 -2
  10. package/dist/src/channels/adapter.d.ts +0 -103
  11. package/dist/src/channels/telegram-mirror/askuser.d.ts +0 -107
  12. package/dist/src/channels/telegram-mirror/burst-accumulator.d.ts +0 -96
  13. package/dist/src/channels/telegram-mirror/callback-mapping.d.ts +0 -61
  14. package/dist/src/channels/telegram-mirror/card-renderer.d.ts +0 -68
  15. package/dist/src/channels/telegram-mirror/card-state.d.ts +0 -83
  16. package/dist/src/channels/telegram-mirror/commands.d.ts +0 -183
  17. package/dist/src/channels/telegram-mirror/compose-buffer.d.ts +0 -71
  18. package/dist/src/channels/telegram-mirror/cost-views.d.ts +0 -58
  19. package/dist/src/channels/telegram-mirror/failure/callback-data-overflow.d.ts +0 -21
  20. package/dist/src/channels/telegram-mirror/failure/gateway-down.d.ts +0 -15
  21. package/dist/src/channels/telegram-mirror/failure/in-flight-conflict.d.ts +0 -15
  22. package/dist/src/channels/telegram-mirror/failure/index.d.ts +0 -23
  23. package/dist/src/channels/telegram-mirror/failure/model-5xx.d.ts +0 -16
  24. package/dist/src/channels/telegram-mirror/failure/network-blip.d.ts +0 -17
  25. package/dist/src/channels/telegram-mirror/failure/pool-exhausted-fallback.d.ts +0 -15
  26. package/dist/src/channels/telegram-mirror/failure/rate-limit.d.ts +0 -16
  27. package/dist/src/channels/telegram-mirror/failure/returning-after-24h.d.ts +0 -14
  28. package/dist/src/channels/telegram-mirror/failure/types.d.ts +0 -30
  29. package/dist/src/channels/telegram-mirror/inbound-handler.d.ts +0 -73
  30. package/dist/src/channels/telegram-mirror/index.d.ts +0 -32
  31. package/dist/src/channels/telegram-mirror/plan-attachment.d.ts +0 -120
  32. package/dist/src/channels/telegram-mirror/quota-reader.d.ts +0 -42
  33. package/dist/src/channels/telegram-mirror/sessions-keyboard.d.ts +0 -84
  34. package/dist/src/channels/telegram-mirror/soak-log.d.ts +0 -99
  35. package/dist/src/channels/telegram-mirror/state-machine.d.ts +0 -113
  36. package/dist/src/channels/telegram-mirror/status-line.d.ts +0 -51
  37. package/dist/src/channels/telegram-mirror/sync-commands.d.ts +0 -100
  38. package/dist/src/channels/telegram-mirror/threshold-watcher.d.ts +0 -54
  39. package/dist/src/channels/telegram-mirror/turn-bridge.d.ts +0 -125
  40. package/dist/src/cli/checks/bridge-wiring.d.ts +0 -14
  41. package/dist/src/cli/checks/config-schema.d.ts +0 -11
  42. package/dist/src/cli/checks/critical-openclaw-json-keys.d.ts +0 -21
  43. package/dist/src/cli/checks/install-path.d.ts +0 -11
  44. package/dist/src/cli/checks/patch-scaffold.d.ts +0 -17
  45. package/dist/src/cli/doctor.d.ts +0 -20
  46. package/dist/src/cli/index.d.ts +0 -8
  47. package/dist/src/cli/migrate.d.ts +0 -29
  48. package/dist/src/command-router/cc-handler.d.ts +0 -67
  49. package/dist/src/command-router/index.d.ts +0 -2
  50. package/dist/src/command-router/launch-policy.d.ts +0 -92
  51. package/dist/src/command-router/resume-policy.d.ts +0 -18
  52. package/dist/src/command-router/turn-formatter.d.ts +0 -19
  53. package/dist/src/config/loader.d.ts +0 -8
  54. package/dist/src/config/schema.d.ts +0 -192
  55. package/dist/src/constants.d.ts +0 -191
  56. package/dist/src/council/build-agent-prompt.d.ts +0 -11
  57. package/dist/src/council/cleanup-worktrees.d.ts +0 -10
  58. package/dist/src/council/consensus.d.ts +0 -20
  59. package/dist/src/council/council.d.ts +0 -67
  60. package/dist/src/council/index.d.ts +0 -2
  61. package/dist/src/council/system-prompt.d.ts +0 -16
  62. package/dist/src/council/write-worktree-claude-md.d.ts +0 -10
  63. package/dist/src/engines/base-oneshot-session.d.ts +0 -87
  64. package/dist/src/engines/heartbeat-guard.d.ts +0 -93
  65. package/dist/src/engines/index.d.ts +0 -8
  66. package/dist/src/engines/persistent-codex-session.d.ts +0 -16
  67. package/dist/src/engines/persistent-cursor-session.d.ts +0 -21
  68. package/dist/src/engines/persistent-custom-session.d.ts +0 -78
  69. package/dist/src/engines/persistent-gemini-session.d.ts +0 -21
  70. package/dist/src/engines/persistent-session.d.ts +0 -95
  71. package/dist/src/engines/resolve-bin.d.ts +0 -14
  72. package/dist/src/engines/subprocess-pool.d.ts +0 -78
  73. package/dist/src/health/handler.d.ts +0 -39
  74. package/dist/src/health/index.d.ts +0 -1
  75. package/dist/src/health/metrics.d.ts +0 -52
  76. package/dist/src/index.d.ts +0 -57
  77. package/dist/src/lib/auto-recovery.d.ts +0 -43
  78. package/dist/src/lib/cache-parity-decide.d.ts +0 -64
  79. package/dist/src/lib/cache-parity.d.ts +0 -38
  80. package/dist/src/lib/cc-cli-scan.d.ts +0 -52
  81. package/dist/src/lib/circuit-breaker.d.ts +0 -21
  82. package/dist/src/lib/config-service.d.ts +0 -106
  83. package/dist/src/lib/config.d.ts +0 -136
  84. package/dist/src/lib/cost-rollup.d.ts +0 -36
  85. package/dist/src/lib/debounce.d.ts +0 -12
  86. package/dist/src/lib/debug-tap.d.ts +0 -13
  87. package/dist/src/lib/domain-error.d.ts +0 -59
  88. package/dist/src/lib/drift-detector.d.ts +0 -46
  89. package/dist/src/lib/env-overrides.d.ts +0 -47
  90. package/dist/src/lib/error-formatter.d.ts +0 -91
  91. package/dist/src/lib/error-renderer.d.ts +0 -20
  92. package/dist/src/lib/heartbeat-config.d.ts +0 -34
  93. package/dist/src/lib/heartbeat-workaround.d.ts +0 -44
  94. package/dist/src/lib/html-render.d.ts +0 -50
  95. package/dist/src/lib/http-agent.d.ts +0 -47
  96. package/dist/src/lib/index.d.ts +0 -7
  97. package/dist/src/lib/index.js +0 -10
  98. package/dist/src/lib/json-array.d.ts +0 -10
  99. package/dist/src/lib/markdown-to-mdv2.d.ts +0 -53
  100. package/dist/src/lib/markdown-v2.d.ts +0 -27
  101. package/dist/src/lib/perf/async-compact.d.ts +0 -26
  102. package/dist/src/lib/perf/direct-sdk.d.ts +0 -26
  103. package/dist/src/lib/perf/haiku-route.d.ts +0 -19
  104. package/dist/src/lib/perf/predictive-continuation.d.ts +0 -18
  105. package/dist/src/lib/perf/read-batch.d.ts +0 -33
  106. package/dist/src/lib/perf/skill-list-collapse.d.ts +0 -22
  107. package/dist/src/lib/perf/speculative-bubble.d.ts +0 -27
  108. package/dist/src/lib/perf/typing-prefetch.d.ts +0 -25
  109. package/dist/src/lib/probes.d.ts +0 -50
  110. package/dist/src/lib/register-guard.d.ts +0 -56
  111. package/dist/src/lib/req-shape-log.d.ts +0 -31
  112. package/dist/src/lib/safe-upstream-probes.d.ts +0 -25
  113. package/dist/src/lib/session-registry.d.ts +0 -66
  114. package/dist/src/lib/spawn-async.d.ts +0 -18
  115. package/dist/src/lib/status-tee-reader.d.ts +0 -29
  116. package/dist/src/lib/sysprompt-strip.d.ts +0 -53
  117. package/dist/src/lib/telegram-bot-api.d.ts +0 -146
  118. package/dist/src/lib/telemetry.d.ts +0 -38
  119. package/dist/src/lib/test-mode.d.ts +0 -26
  120. package/dist/src/lib/trajectory.d.ts +0 -44
  121. package/dist/src/lib/vendor-paths.d.ts +0 -12
  122. package/dist/src/lifecycle/boot.d.ts +0 -48
  123. package/dist/src/lifecycle/patch-manifest.d.ts +0 -82
  124. package/dist/src/lifecycle/phase-import-upstream.d.ts +0 -12
  125. package/dist/src/lifecycle/phase-install-patches.d.ts +0 -12
  126. package/dist/src/lifecycle/phase-schedule-jobs.d.ts +0 -12
  127. package/dist/src/lifecycle/phase-start-server.d.ts +0 -11
  128. package/dist/src/lifecycle/phase-validate-config.d.ts +0 -9
  129. package/dist/src/lifecycle/phase-validate-upstream.d.ts +0 -11
  130. package/dist/src/lifecycle/phase-wire-handlers.d.ts +0 -12
  131. package/dist/src/lifecycle/safe-restart.d.ts +0 -99
  132. package/dist/src/logger.d.ts +0 -14
  133. package/dist/src/mcp/bridge.d.ts +0 -21
  134. package/dist/src/mcp/index.d.ts +0 -2
  135. package/dist/src/models.d.ts +0 -68
  136. package/dist/src/observability/event-bus.d.ts +0 -86
  137. package/dist/src/observability/get-event-bus.d.ts +0 -25
  138. package/dist/src/observability/observability-service.d.ts +0 -19
  139. package/dist/src/observability/perf-telemetry.d.ts +0 -65
  140. package/dist/src/observability/subscribers/metrics.d.ts +0 -11
  141. package/dist/src/observability/subscribers/session-capture.d.ts +0 -15
  142. package/dist/src/openai-compat/autonomy-rule.d.ts +0 -26
  143. package/dist/src/openai-compat/bridges/allowlist.d.ts +0 -19
  144. package/dist/src/openai-compat/bridges/factory.d.ts +0 -30
  145. package/dist/src/openai-compat/bridges/media-bridge.d.ts +0 -34
  146. package/dist/src/openai-compat/bridges/openclaw-api-shim.d.ts +0 -54
  147. package/dist/src/openai-compat/bridges/openclaw-native-tools.d.ts +0 -61
  148. package/dist/src/openai-compat/bridges/openclaw-tool-registry.d.ts +0 -26
  149. package/dist/src/openai-compat/bridges/tts-media-bridge.d.ts +0 -19
  150. package/dist/src/openai-compat/chat-cwd.d.ts +0 -22
  151. package/dist/src/openai-compat/cli-stream-parser.d.ts +0 -134
  152. package/dist/src/openai-compat/index.d.ts +0 -1
  153. package/dist/src/openai-compat/message-extractor.d.ts +0 -84
  154. package/dist/src/openai-compat/mode-flags.d.ts +0 -34
  155. package/dist/src/openai-compat/non-streaming-handler.d.ts +0 -29
  156. package/dist/src/openai-compat/openai-chunk-types.d.ts +0 -35
  157. package/dist/src/openai-compat/openai-compat.d.ts +0 -49
  158. package/dist/src/openai-compat/openai-types.d.ts +0 -71
  159. package/dist/src/openai-compat/parse-route-body.d.ts +0 -24
  160. package/dist/src/openai-compat/prompts.d.ts +0 -47
  161. package/dist/src/openai-compat/request-coalescer.d.ts +0 -77
  162. package/dist/src/openai-compat/response-formatter.d.ts +0 -33
  163. package/dist/src/openai-compat/session-key-resolver.d.ts +0 -41
  164. package/dist/src/openai-compat/skill-resolver.d.ts +0 -59
  165. package/dist/src/openai-compat/sse-translator.d.ts +0 -51
  166. package/dist/src/openai-compat/status-reporter.d.ts +0 -30
  167. package/dist/src/openai-compat/streaming-handler.d.ts +0 -52
  168. package/dist/src/openai-compat/tool-calls-parser.d.ts +0 -34
  169. package/dist/src/openai-compat/tool-results-serializer.d.ts +0 -60
  170. package/dist/src/openai-compat/tts-rule.d.ts +0 -20
  171. package/dist/src/openai-compat/voice-recovery.d.ts +0 -56
  172. package/dist/src/patches/cache-parity-registry.d.ts +0 -103
  173. package/dist/src/patches/claude-md-injection.d.ts +0 -10
  174. package/dist/src/patches/cwd-redirect.d.ts +0 -10
  175. package/dist/src/patches/embedded-server-route.d.ts +0 -23
  176. package/dist/src/patches/pricing-overrides.d.ts +0 -10
  177. package/dist/src/patches/resume-registry-restore.d.ts +0 -11
  178. package/dist/src/patches/session-pid-tracking.d.ts +0 -10
  179. package/dist/src/patches/sysprompt-strip.d.ts +0 -46
  180. package/dist/src/patches/tools-restoration.d.ts +0 -12
  181. package/dist/src/persistence/migration-v0.d.ts +0 -24
  182. package/dist/src/persistence/session-registry.d.ts +0 -58
  183. package/dist/src/proxy/anthropic-adapter.d.ts +0 -136
  184. package/dist/src/proxy/handler.d.ts +0 -39
  185. package/dist/src/proxy/index.d.ts +0 -4
  186. package/dist/src/proxy/schema-cleaner.d.ts +0 -11
  187. package/dist/src/proxy/thought-cache.d.ts +0 -19
  188. package/dist/src/session/embedded-server.d.ts +0 -25
  189. package/dist/src/session/inbox-manager.d.ts +0 -38
  190. package/dist/src/session/index.d.ts +0 -3
  191. package/dist/src/session/persisted-sessions.d.ts +0 -50
  192. package/dist/src/session/session-manager.d.ts +0 -247
  193. package/dist/src/session/watchdogs.d.ts +0 -92
  194. package/dist/src/session-bootstrap/boot-self-heal.d.ts +0 -32
  195. package/dist/src/session-bootstrap/cwd-patch.d.ts +0 -50
  196. package/dist/src/session-bootstrap/index.d.ts +0 -3
  197. package/dist/src/session-bootstrap/resume-registry.d.ts +0 -27
  198. package/dist/src/session-bootstrap/session-hygiene.d.ts +0 -23
  199. package/dist/src/session-bootstrap/sysprompt-strip.d.ts +0 -24
  200. package/dist/src/session-bootstrap/think-conflict-resolver.d.ts +0 -32
  201. package/dist/src/types/route.d.ts +0 -11
  202. package/dist/src/types/runtime-config.d.ts +0 -208
  203. package/dist/src/types/sse.d.ts +0 -29
  204. package/dist/src/types/tool-bridge.d.ts +0 -82
  205. package/dist/src/types/upstream.d.ts +0 -580
  206. package/dist/src/types.d.ts +0 -498
  207. package/dist/src/validation.d.ts +0 -31
@@ -1,107 +0,0 @@
1
- /**
2
- * src/channels/telegram-mirror/askuser.ts — v0.26.3 M5.
3
- *
4
- * Renders Claude Code's AskUserQuestion tool as native Telegram inline
5
- * keyboards, "next-turn model" (Path A, chosen by A1 2026-05-20):
6
- *
7
- * agent calls AskUserQuestion → turn ends
8
- * → we send a keyboard message (single-select: one button per option +
9
- * "✍️ Write something else"; multi-select: checkbox toggles + Submit)
10
- * → user taps → api.registerInteractiveHandler fires
11
- * → we answer the callback, edit the message to show the choice, and
12
- * api.enqueueNextTurnInjection() queues the answer as context for the
13
- * agent's NEXT turn (it is acted on when the next message runs — the
14
- * documented primitive injects context, it does not start a turn).
15
- *
16
- * Feasibility proven 2026-05-20: the headless subprocess DOES emit an
17
- * AskUserQuestion tool_use (pushToolUse name=AskUserQuestion). The tool emits
18
- * twice (dual content_block_start + assistant-block), so capture dedups by
19
- * tool_use id.
20
- *
21
- * Telegram has no ANSI color — checkboxes use ☐/☑ glyphs.
22
- */
23
- /** Namespace prefix for callback_data so api.registerInteractiveHandler routes
24
- * taps here. Matched at the first ':' by the gateway (must be [A-Za-z0-9._-]+). */
25
- export declare const ASKUSER_NS = "ccmirror";
26
- interface QOption {
27
- label: string;
28
- description?: string;
29
- }
30
- interface ParsedQuestion {
31
- header: string;
32
- question: string;
33
- multiSelect: boolean;
34
- options: QOption[];
35
- }
36
- /**
37
- * v0.28.0 — build a single inline button that, when tapped, resumes a Claude
38
- * Code session. Reuses the proven askuser callback path: the payload is stashed
39
- * in the shared (globalThis-anchored) CallbackMap and the callback_data is
40
- * `ccmirror:<id>`, so taps route through the same before_dispatch interceptor.
41
- */
42
- export declare function buildResumeButton(uuid: string, label: string): {
43
- text: string;
44
- callback_data: string;
45
- };
46
- /** Minimal subset of the registerInteractiveHandler ctx we use. */
47
- export interface InteractiveCtx {
48
- callback: {
49
- id?: string;
50
- data?: string;
51
- namespace?: string;
52
- payload?: string;
53
- };
54
- chatId?: string | number;
55
- conversationId?: string;
56
- sessionKey?: string;
57
- threadId?: number;
58
- respond?: {
59
- editMessage?: (text: string) => Promise<unknown>;
60
- answer?: (text?: string) => Promise<unknown>;
61
- };
62
- }
63
- /** Minimal subset of the plugin api we use (next-turn injection). */
64
- export interface InjectApi {
65
- enqueueNextTurnInjection?: (injection: {
66
- sessionKey: string;
67
- text: string;
68
- placement?: 'prepend_context' | 'append_context';
69
- idempotencyKey?: string;
70
- }) => unknown;
71
- }
72
- /** Record the real agent session key for a chat (called from inbound before_dispatch). */
73
- export declare function rememberSessionKey(chatId: string, sessionKey: string | undefined): void;
74
- /** Parse the FIRST question from an AskUserQuestion tool input. Defensive —
75
- * returns undefined if the shape isn't usable (no fabrication). */
76
- export declare function parseFirstQuestion(input: Record<string, unknown> | undefined): ParsedQuestion | undefined;
77
- /**
78
- * Capture an AskUserQuestion tool_use and render the keyboard. Called from
79
- * turn-bridge when name === 'AskUserQuestion'. Dedups the dual-emission by
80
- * tool_use id. Best-effort: a send failure must not break the turn.
81
- */
82
- export declare function captureAskUserQuestion(chatId: string, threadId: number | undefined, input: Record<string, unknown> | undefined, toolUseId: string | undefined): Promise<void>;
83
- /**
84
- * Handle an inline-button tap routed from api.registerInteractiveHandler.
85
- * Resolves the callback payload, updates state, and on a terminal choice
86
- * (single-select option, multi-select Submit) injects the answer for the next
87
- * turn. "Write something else" just prompts the user to type — their typed
88
- * message becomes the next turn naturally, so no injection is needed.
89
- */
90
- export declare function handleTap(ctx: InteractiveCtx, api: InjectApi): Promise<void>;
91
- /** True if an inbound message text is actually an AskUserQuestion button tap.
92
- * The gateway delivers taps on plugin-sent keyboards as before_dispatch
93
- * messages with text = the callback_data (`ccmirror:<id>`), NOT as routed
94
- * interactive-handler callbacks — so we intercept them in before_dispatch. */
95
- export declare function isAskUserCallback(text: string): boolean;
96
- /**
97
- * Handle a tap that arrived as a before_dispatch message (text=`ccmirror:<id>`).
98
- * Builds a synthetic ctx (conversationId = chatId resolves the remembered
99
- * session key) and runs the normal tap logic. Caller MUST claim the event so
100
- * the literal callback_data never reaches the agent.
101
- */
102
- export declare function handleTapData(text: string, chatId: string, api: InjectApi): Promise<void>;
103
- /** Test-only — reset module state. */
104
- export declare function _resetAskUserForTests(): void;
105
- /** Test-only — peek pending question count. */
106
- export declare function _pendingCount(): number;
107
- export {};
@@ -1,96 +0,0 @@
1
- /**
2
- * src/channels/telegram-mirror/burst-accumulator.ts — v0.25.0 M8.
3
- *
4
- * Per-chat 5-second settle window for non-slash inbound messages. When
5
- * the user fires multiple message bubbles within 5s of each other, the
6
- * accumulator concatenates them into one user-message payload (joined by
7
- * "\n\n") before delivery to the engine. A gap > 5s flushes the prior
8
- * buffer immediately and starts a new one.
9
- *
10
- * Decision: ADR-007 — 5s is the empirical saddle point. <3s gaps are
11
- * almost always related thoughts; >8s gaps are almost always new turns.
12
- * 5s matches the WARMUP_COOLDOWN_MS in typing-prefetch.ts (consistency).
13
- *
14
- * Routing responsibility lives in the inbound dispatcher (later milestone):
15
- * • Slash messages bypass this class — dispatched immediately via
16
- * dispatchCommand (commands.ts).
17
- * • Compose-active chats bypass this class — drafts go to ComposeBuffer
18
- * (compose-buffer.ts). M7 takes priority over M8 per ADR-007.
19
- * • Everything else flows through submit() here.
20
- *
21
- * The flush flow has TWO triggers:
22
- * 1. A new submit() that arrives AFTER the settle window — that submit
23
- * returns the prior buffer in `flushed` and starts a fresh buffer.
24
- * 2. A periodic flushIfReady() check that runs on a timer when no new
25
- * inbound has arrived since the window opened.
26
- *
27
- * Tests inject a deterministic clock; production passes Date.now.
28
- */
29
- export interface BurstAccumulatorOptions {
30
- /** Settle window in milliseconds (default 5000 per ADR-007). */
31
- settleMs?: number;
32
- /** Injectable clock for tests; defaults to Date.now. */
33
- now?: () => number;
34
- /** Custom separator between concatenated drafts (default "\n\n"). */
35
- separator?: string;
36
- }
37
- export interface SubmitResult {
38
- /**
39
- * When the new submit() arrives AFTER the prior buffer's settle window,
40
- * the prior buffer is returned here for immediate delivery; the new
41
- * message starts a fresh buffer in its place. Undefined otherwise.
42
- */
43
- flushed?: string;
44
- }
45
- export declare class BurstAccumulator {
46
- private readonly sessions;
47
- private readonly settleMs;
48
- private readonly now;
49
- private readonly separator;
50
- constructor(opts?: BurstAccumulatorOptions);
51
- /**
52
- * Submit a non-slash inbound message. Returns `flushed` populated when
53
- * the prior buffer for the chat had timed out and this submit forced
54
- * its flush; in that case the new message starts a fresh buffer.
55
- *
56
- * The returned `flushed` payload is the only value the caller delivers
57
- * to the engine — the new message itself stays buffered for at least
58
- * `settleMs` more, so it gets a chance to coalesce with follow-ups.
59
- */
60
- submit(chatId: string, text: string): SubmitResult;
61
- /**
62
- * Periodic check — when the settle window has elapsed without any new
63
- * inbound, returns the buffered payload and clears the session. When
64
- * the window has NOT yet elapsed, returns undefined and leaves the
65
- * buffer intact. Returns undefined for chats without an active buffer.
66
- *
67
- * Production wiring: call from a 1Hz interval timer per known chatId
68
- * (or from the inbound dispatcher's idle-tick).
69
- */
70
- flushIfReady(chatId: string): string | undefined;
71
- /**
72
- * Force-flush the buffer for a chat regardless of timing. Used when an
73
- * explicit signal arrives that the current buffer must deliver now —
74
- * e.g. a slash command was typed (its dispatcher flushes burst first,
75
- * then routes the slash, so the bursted text reaches the engine before
76
- * the slash response).
77
- */
78
- flushNow(chatId: string): string | undefined;
79
- /**
80
- * True when a buffer exists for the chat (regardless of settle state).
81
- * Used by the inbound dispatcher to decide whether a slash arrival
82
- * should trigger flushNow before routing.
83
- */
84
- hasBuffer(chatId: string): boolean;
85
- /**
86
- * Number of drafts currently buffered for the chat. Useful for status
87
- * surfaces and for tests asserting the buffer state.
88
- */
89
- draftCount(chatId: string): number;
90
- /**
91
- * Clear all sessions. Test helper.
92
- */
93
- clear(): void;
94
- private fresh;
95
- private format;
96
- }
@@ -1,61 +0,0 @@
1
- /**
2
- * src/channels/telegram-mirror/callback-mapping.ts — v0.25.0 M3.
3
- *
4
- * ADR-004 — Telegram's callback_data is capped at 64 bytes UTF-8. For
5
- * payloads larger than that (most action+slug combinations are), the bot
6
- * writes a short opaque base36 id into callback_data and stashes the real
7
- * payload here. TTL prevents unbounded memory growth as users tap through
8
- * keyboards or never tap at all.
9
- *
10
- * Default TTL is 10 minutes per ADR-004 monitoring signal (callback miss
11
- * rate > 2% in soak → revisit TTL). The class accepts an injectable clock
12
- * so tests can fast-forward without setTimeout games.
13
- *
14
- * No I/O, no global state. Each subsystem that hands out callback_data
15
- * owns its own CallbackMap instance — keeps ownership boundaries clean
16
- * for M4 (per-command), M9 (plan keyboards), M11 (cost subview).
17
- */
18
- export interface CallbackMapOptions {
19
- /** TTL in milliseconds (default 10 minutes per ADR-004). */
20
- ttlMs?: number;
21
- /** Injectable clock for tests; defaults to Date.now. */
22
- now?: () => number;
23
- /** Length of the opaque id string (default 8 base36 chars ≈ 41 bits entropy). */
24
- idLength?: number;
25
- }
26
- export declare class CallbackMap {
27
- private readonly entries;
28
- private readonly ttlMs;
29
- private readonly now;
30
- private readonly idLength;
31
- constructor(opts?: CallbackMapOptions);
32
- /**
33
- * Allocate a fresh opaque id and stash the payload behind it. Returns the
34
- * id, which fits in a Telegram callback_data field with room to spare.
35
- * Idempotent only at the data-shape level — calling create() with the
36
- * same payload twice produces two distinct ids.
37
- */
38
- create(payload: unknown): string;
39
- /**
40
- * Resolve a callback id to its stashed payload. Returns undefined if the
41
- * id was never minted OR if it has expired since. Stale entries are
42
- * dropped lazily on access — no background timer needed.
43
- */
44
- get(id: string): unknown | undefined;
45
- /**
46
- * Manually evict an id (e.g., one-shot Approve/Reject buttons after the
47
- * user taps once). Returns true if an entry was deleted.
48
- */
49
- delete(id: string): boolean;
50
- /**
51
- * Current entry count (after pruning expired). Useful for monitoring
52
- * and the 2% callback-miss-rate signal in soak.
53
- */
54
- size(): number;
55
- /**
56
- * Drop everything. Test helper; production code never calls this.
57
- */
58
- clear(): void;
59
- private prune;
60
- private randomId;
61
- }
@@ -1,68 +0,0 @@
1
- /**
2
- * src/channels/telegram-mirror/card-renderer.ts — v0.25.0 M2.
3
- *
4
- * Pure-function renderer: Turn (from state-machine.ts) → message body string
5
- * suitable for sendMessage / editMessageText. Telegram-API HTTP wiring
6
- * (sendTg / editTg) lands in a later milestone alongside the dispatch path
7
- * — M2's exit criterion is just "render a single turn (working → done)",
8
- * which is satisfied by this pure function.
9
- *
10
- * Aesthetic: terminal-mimic per ADR-001. Header glyph ("▶" working,
11
- * "✓" done) + tool call list (each prefixed with status glyph) + assistant
12
- * text. Compact enough to fit in a single Telegram message bubble.
13
- *
14
- * Tests live at tests/channels/telegram-mirror/m2-render-pipeline.test.ts.
15
- */
16
- import type { Turn, ToolCallRecord } from './state-machine.js';
17
- import type { CardMeta } from './card-state.js';
18
- export declare function toolDiffBlock(tc: ToolCallRecord): string;
19
- /**
20
- * v0.27.5 — pick a syntax-highlight language for a tool's RESULT block so the
21
- * card colors output the way the terminal does. Bash/shell → 'bash'; file tools
22
- * → inferred from the `file_path` extension via EXT_LANG. Unknown → undefined
23
- * (renders classless, no regression — never guess a language we can't justify).
24
- */
25
- export declare function langForTool(tc: ToolCallRecord): string | undefined;
26
- /**
27
- * Format one tool-call line for inclusion in the rendered card body.
28
- * "✓ Bash · ls -la"
29
- * "… Read · src/index.ts"
30
- * "✗ Edit · …error glyph at left"
31
- */
32
- /**
33
- * Tool-type emoji icon (v0.26.4 styling). Pure unicode — renders in Telegram's
34
- * plain-text mode (the card currently sends as plain because unescaped
35
- * MarkdownV2 specials fail the parse; emoji/dividers work regardless). Unknown
36
- * tools get a neutral marker.
37
- */
38
- export declare function toolIcon(name: string): string;
39
- export declare function renderToolLine(tc: ToolCallRecord): string;
40
- /**
41
- * Render the thinking block (M6). Each line of the thinking text is
42
- * prefixed with "> " to read as a block quote in plain-text Telegram
43
- * bubbles — clearly visually distinct from the assistant text below it
44
- * without depending on MarkdownV2 escapes. Empty thinking returns ''.
45
- */
46
- export declare function renderThinkingBlock(thinkingText: string): string;
47
- export declare function renderTurn(turn: Turn, meta?: CardMeta): string;
48
- /**
49
- * A render action — abstraction the dispatch layer (added in a later
50
- * milestone) consumes. M2 doesn't dispatch; it just builds the action so
51
- * tests can assert against the planned message lifecycle.
52
- *
53
- * - 'send' on turn start (no prior messageId)
54
- * - 'edit' on every subsequent state mutation
55
- */
56
- export interface RenderAction {
57
- type: 'send' | 'edit';
58
- chatId: string;
59
- text: string;
60
- /** Defined only when type === 'edit'. */
61
- messageId?: number;
62
- }
63
- /**
64
- * Decide whether the current turn snapshot should be sent (first render)
65
- * or edited (subsequent renders). The dispatcher tracks the (chatId →
66
- * messageId) map; this function just produces the action shape.
67
- */
68
- export declare function planRenderAction(turn: Turn, knownMessageId: number | undefined): RenderAction;
@@ -1,83 +0,0 @@
1
- /**
2
- * src/channels/telegram-mirror/card-state.ts — v0.26.1.
3
- *
4
- * Module-scope shared state for the active Telegram mirror cards. Extracted
5
- * from inbound-handler.ts so the openai-compat handlers (which see the real
6
- * tool_use / text stream from the Claude subprocess) can push events into
7
- * the live card without a cross-channel event bus.
8
- *
9
- * Single source of truth: one Map<chatId, CardEntry>. Both inbound-handler
10
- * (writer on before_dispatch / reply_dispatch) and turn-bridge (writer from
11
- * streaming + non-streaming handlers) read+write here.
12
- *
13
- * ── v0.26.1 live-mirror fix: globalThis singleton ──────────────────────────
14
- * A plain `new Map()` at module scope is only a singleton if every importer
15
- * shares the same module INSTANCE. That assumption breaks here: the inbound
16
- * handler is loaded via the plugin's register() graph, but the openai-compat
17
- * handlers are loaded via cwd-patch's EAGER `await import(<abs path>)` of the
18
- * embedded server (session-bootstrap/cwd-patch.ts:906/336). When the same
19
- * file is reached through two different load roots, Node can hold TWO module
20
- * instances → two different Maps. The card the inbound handler registers
21
- * (so the user sees "▶ Working" and later "✓ Done") then lives in instance A,
22
- * while turn-bridge's pushToolUse/pushAssistantText run against instance B's
23
- * empty Map → every push silently no-ops. That is the exact "card frame
24
- * renders, body never fills" symptom that survived v0.25.7/0.25.9/0.26.0.
25
- *
26
- * Fix: anchor the Map on globalThis under a Symbol.for() key so ALL instances
27
- * resolve to ONE Map regardless of how the module was loaded. This mirrors
28
- * the codebase's existing cross-instance pattern (cwd-patch's
29
- * `Symbol.for('telegram-ux-bridge:metadata')` UX_META store). Harmless if the
30
- * single-instance assumption already held — it's the same one Map either way.
31
- */
32
- import type { TurnStateMachine } from './state-machine.js';
33
- /**
34
- * Per-card status metadata for the CC-CLI-style status line (v0.26.2). Every
35
- * field is OPTIONAL and rendered only when genuinely available (no-fake-data
36
- * rule). The inbound handler creates the card with empty meta; the openai-compat
37
- * handlers fill it in via turn-bridge.setCardMeta() once the model turn starts
38
- * (model, bypass) and completes (contextPercent). Quota is read at render time.
39
- */
40
- export interface CardMeta {
41
- /** Resolved model id, e.g. "claude-opus-4-7" (handler `model` param). */
42
- model?: string;
43
- /** True when the session runs permissionMode 'bypassPermissions'. */
44
- bypassPermissions?: boolean;
45
- /** Context-window usage % from getStatus().stats.contextPercent (M2). */
46
- contextPercent?: number;
47
- /** Plan/quota usage % (status-tee maxPercent) — set at render time (M2). */
48
- quotaPercent?: number;
49
- /** Quota window reset, Unix epoch seconds (status-tee resetsAt) (M2). */
50
- quotaResetsAt?: number;
51
- /**
52
- * Latest todo list captured from the agent's TodoWrite tool call (M4). Real
53
- * data — the only one of rules/hooks/todos reachable from the plugin (rules &
54
- * hooks live in the subprocess and are not exposed). Empty/absent → omitted.
55
- */
56
- todos?: Array<{
57
- content: string;
58
- status: string;
59
- }>;
60
- }
61
- export interface CardEntry {
62
- /** Telegram message_id of the editable card. */
63
- messageId: number;
64
- /** Per-turn state machine (one Turn per chat at a time). */
65
- sm: TurnStateMachine;
66
- /** Telegram message_thread_id when the chat is a forum/group topic. */
67
- threadId?: number;
68
- /** CC-CLI status-line metadata (v0.26.2). Filled progressively per turn. */
69
- meta?: CardMeta;
70
- }
71
- /**
72
- * chatId → active card. Cleared at model-turn end by
73
- * turn-bridge.finalizeActiveCards(). Process-global singleton (see header) so
74
- * the inbound handler and the openai-compat handlers share ONE Map even across
75
- * module-instance splits.
76
- */
77
- export declare const cardState: Map<string, CardEntry>;
78
- /**
79
- * Compact card-state summary for the turn-bridge push logs and the
80
- * openai-compat handler entry log — the permanent live-mirror success-gate
81
- * signal (cards>0 during a turn means events are reaching the active card).
82
- */
83
- export declare function cardStateDebug(): string;
@@ -1,183 +0,0 @@
1
- /**
2
- * src/channels/telegram-mirror/commands.ts — v0.25.0 M4.
3
- *
4
- * Top-7 phone-tier slash commands per PRP §5 M4:
5
- * /sessions /new <slug> /stop /status /compact /cost /rewind
6
- *
7
- * Each handler is a pure function returning a CommandResult — a list of
8
- * Telegram API actions the dispatch layer consumes. No I/O happens here
9
- * beyond reading session-registry (which itself isolates I/O behind an
10
- * env-overridable path for tests).
11
- *
12
- * G-2 resolution (2026-05-19): per-message inline keyboards + typed-form
13
- * — no persistent ReplyKeyboardMarkup. /sessions and /cost have an
14
- * inline-keyboard form; the rest are text-only.
15
- *
16
- * Decision refs:
17
- * • ADR-003 — slug registry is the canonical source for /sessions, /new,
18
- * /stop, /status.
19
- * • ADR-004 — callback_data slots come from the per-handler CallbackMap.
20
- * • ADR-008 — failure handlers (M12) consume CommandResult.actions[].
21
- *
22
- * Out of scope for M4 (per "no premature resolution"):
23
- * • Actually spawning / killing claude subprocesses (M5+ wiring).
24
- * • Real quota numbers in /cost — uses QuotaReader stub (M11 wires real).
25
- * • Threshold notifications / 95% pause button (M11).
26
- * • Plan attachment via sendDocument (M9).
27
- */
28
- import { CallbackMap } from './callback-mapping.js';
29
- import { type SessionState, type InlineButton } from './sessions-keyboard.js';
30
- import { type QuotaReader } from './quota-reader.js';
31
- import type { ComposeBuffer } from './compose-buffer.js';
32
- /**
33
- * Discriminated union of Telegram API actions a command may emit.
34
- * Maps 1:1 to the test mock layer at tests/.../__mocks__/telegram-api.ts.
35
- */
36
- export type TelegramAction = {
37
- type: 'sendMessage';
38
- chat_id: string | number;
39
- text: string;
40
- reply_markup?: {
41
- inline_keyboard: InlineButton[][];
42
- };
43
- parse_mode?: 'MarkdownV2';
44
- } | {
45
- type: 'editMessageText';
46
- chat_id: string | number;
47
- message_id: number;
48
- text: string;
49
- reply_markup?: {
50
- inline_keyboard: InlineButton[][];
51
- };
52
- parse_mode?: 'MarkdownV2';
53
- } | {
54
- type: 'sendDocument';
55
- chat_id: string | number;
56
- filename: string;
57
- content: string;
58
- caption?: string;
59
- reply_markup?: {
60
- inline_keyboard: InlineButton[][];
61
- };
62
- };
63
- export interface CommandContext {
64
- chatId: string | number;
65
- args: string[];
66
- callbackMap: CallbackMap;
67
- /** Optional state lookup for status-rich rows; defaults all entries to 'idle'. */
68
- stateLookup?: (slug: string) => SessionState;
69
- /** Optional quota reader for /cost; defaults to stubQuotaReader. */
70
- quotaReader?: QuotaReader;
71
- /** Optional clock for deterministic last-activity tests. */
72
- now?: number;
73
- /** Required for /compose and /send (M7); other handlers ignore. */
74
- composeBuffer?: ComposeBuffer;
75
- }
76
- export interface CommandResult {
77
- actions: TelegramAction[];
78
- /**
79
- * When the command produces user-message content destined for the
80
- * engine (currently only /send after /compose), the concatenated
81
- * payload appears here. M5+ engine bridging consumes this field to
82
- * feed openai-compat as a single user message. Absent when the command
83
- * is purely a UI surface (most handlers).
84
- */
85
- delivery?: {
86
- payload: string;
87
- };
88
- }
89
- /**
90
- * Tiny parser. Telegram slash messages look like "/cmd arg1 arg2" — split
91
- * on whitespace, drop the leading '/', strip any "@botname" suffix.
92
- * Returns undefined for non-slash input.
93
- */
94
- export interface ParsedSlash {
95
- cmd: string;
96
- args: string[];
97
- }
98
- export declare function parseSlash(text: string): ParsedSlash | undefined;
99
- /**
100
- * v0.28.0 — `/sessions` is now a `claude -r`-style picker over the REAL Claude
101
- * Code sessions. It mirrors `~/.claude/projects/**` (the store every `claude`
102
- * subprocess — terminal or cco-spawned — writes to), so one list spans both
103
- * surfaces. Each row shows the session's own ai-title (name) + last-prompt
104
- * (description); tapping resumes it immediately via the globalThis resume
105
- * bridge. Buttons use the proven `ccmirror:` callback path (buildResumeButton).
106
- *
107
- * The previous registry-backed keyboard (buildSessionsKeyboard / enrichRows)
108
- * is retired here: its "switch" callbacks were never wired (M4 stub), and the
109
- * slug registry only ever saw cco-Telegram sessions, not terminal ones.
110
- */
111
- export declare function handleSessions(ctx: CommandContext): CommandResult;
112
- export declare function handleNew(ctx: CommandContext): CommandResult;
113
- export declare function handleStop(ctx: CommandContext): CommandResult;
114
- export declare function handleStatus(ctx: CommandContext): CommandResult;
115
- export declare function handleCompact(ctx: CommandContext): CommandResult;
116
- export declare function handleCost(ctx: CommandContext): CommandResult;
117
- export declare function handleRewind(ctx: CommandContext): CommandResult;
118
- /**
119
- * v0.27.7 — /clear claims the command so it stops leaking to the LLM as plain
120
- * text (the bug: before this, /clear wasn't in COMMAND_HANDLERS, so the inbound
121
- * router forwarded it verbatim to Claude instead of handling it).
122
- *
123
- * It does NOT fake an in-place context reset. The running session's lifecycle +
124
- * resume linkage live in the command-router (activeSessions, meta.claudeSessionId)
125
- * and the engine — not this bookkeeping registry — so a pure mirror handler has
126
- * no honest lever to wipe context (the same D-6 constraint behind /compact and
127
- * /rewind being CLI-only). So /clear points to the paths that actually work: a
128
- * fresh session via /new <slug>, or an in-place wipe via /clear in the CLI.
129
- */
130
- export declare function handleClear(ctx: CommandContext): CommandResult;
131
- /**
132
- * Open a compose session for the chat. M7 — drafts append until /send.
133
- * Returns a force_reply prompt so Telegram nudges the user into reply mode.
134
- */
135
- export declare function handleCompose(ctx: CommandContext): CommandResult;
136
- /**
137
- * Commit the active compose buffer. Returns the concatenated payload via
138
- * CommandResult.delivery for the engine bridge to consume. If no session
139
- * is active, returns a friendly error message.
140
- */
141
- export declare function handleSend(ctx: CommandContext): CommandResult;
142
- /**
143
- * Cancel the active compose buffer without sending. Useful when the user
144
- * starts composing then changes their mind.
145
- */
146
- export declare function handleCancel(ctx: CommandContext): CommandResult;
147
- /**
148
- * Surface a Y/N inline keyboard so A1 records opened-laptop-today for
149
- * the soak instrumentation. Idempotency is enforced by SoakLogger
150
- * downstream — handler always emits the keyboard and lets the callback
151
- * resolver call recordLaptopCheck().
152
- */
153
- export declare function handleSoakCheck(ctx: CommandContext): CommandResult;
154
- /**
155
- * Full user-facing command catalogue, used by /help. The TOP_7 are the
156
- * phone-tier set synced to Telegram's command menu; the workflow extras
157
- * (compose/send/cancel) + help round out what the mirror actually claims.
158
- */
159
- export declare const ALL_COMMANDS: ReadonlyArray<{
160
- command: string;
161
- description: string;
162
- }>;
163
- /**
164
- * /help — list the mirror's commands. Discoverability close for gap #6: the 11
165
- * commands were previously invisible. Notes the passthrough so the user knows
166
- * any other slash (custom skills like /pregoal) or plain text reaches Claude.
167
- * HTML-safe content (only the intentional <b> tag); sendTg renders parse_mode:HTML.
168
- */
169
- export declare function handleHelp(ctx: CommandContext): CommandResult;
170
- export type CommandHandler = (ctx: CommandContext) => CommandResult;
171
- export declare const COMMAND_HANDLERS: Record<string, CommandHandler>;
172
- /**
173
- * Telegram bot commands list — declarative source for M5's setMyCommands sync.
174
- */
175
- export declare const TOP_7_COMMANDS: ReadonlyArray<{
176
- command: string;
177
- description: string;
178
- }>;
179
- /**
180
- * Route a parsed slash command to its handler. Returns undefined for
181
- * unknown commands so the caller can fall back to "unknown command" UX.
182
- */
183
- export declare function dispatchCommand(parsed: ParsedSlash, ctxBase: Omit<CommandContext, 'args'>): CommandResult | undefined;
@@ -1,71 +0,0 @@
1
- /**
2
- * src/channels/telegram-mirror/compose-buffer.ts — v0.25.0 M7.
3
- *
4
- * Per-chat buffer of draft messages between /compose and /send. The
5
- * dispatch layer feeds non-slash inbound messages here when a chat is in
6
- * compose mode; /send commits the buffer to one concatenated payload that
7
- * M5+ engine bridging delivers to openai-compat as a single user message.
8
- *
9
- * Decision: ADR-007 — the 5-second rapid-burst window (M8) is a SEPARATE
10
- * concatenation path. /compose is the explicit, user-controlled buffer
11
- * with no time limit (within reason); rapid-burst is the implicit window
12
- * for accidental double-taps. M7's compose buffer takes priority over
13
- * the M8 burst handler when a compose session is active.
14
- *
15
- * Timeout exists purely as a safety valve — a compose session that's
16
- * been idle for > timeoutMs is considered abandoned and silently cleared
17
- * on the next interaction. Default 30 minutes; tests inject shorter.
18
- */
19
- export interface ComposeBufferOptions {
20
- /** Injectable clock for tests; defaults to Date.now. */
21
- now?: () => number;
22
- /** Idle-session timeout in milliseconds (default 30 minutes). */
23
- timeoutMs?: number;
24
- }
25
- export declare class ComposeBuffer {
26
- private readonly sessions;
27
- private readonly now;
28
- private readonly timeoutMs;
29
- constructor(opts?: ComposeBufferOptions);
30
- /**
31
- * Open a compose session for the chat. If a session is already open it
32
- * is replaced — the user is restarting the buffer intentionally.
33
- */
34
- start(chatId: string): void;
35
- /**
36
- * Append a draft message to the active compose session. Returns true
37
- * when the message was buffered, false when no session was open (or the
38
- * session timed out and was discarded). Callers use the return to
39
- * decide whether to route the message through the regular inbound path
40
- * instead.
41
- */
42
- append(chatId: string, text: string): boolean;
43
- /**
44
- * Commit the active compose session. Returns the concatenated payload
45
- * (drafts joined by `separator`) and clears the session, or undefined
46
- * when no session was open / the session timed out. Default separator
47
- * is "\n\n" — produces natural paragraph breaks between drafts.
48
- */
49
- commit(chatId: string, separator?: string): string | undefined;
50
- /**
51
- * Drop the compose session without committing. Returns true iff a
52
- * session existed.
53
- */
54
- cancel(chatId: string): boolean;
55
- /**
56
- * Lazy-expiring isActive. Returns true only when a non-stale session
57
- * exists; stale sessions are dropped on the call.
58
- */
59
- isActive(chatId: string): boolean;
60
- /**
61
- * Number of drafts buffered (without committing). Useful for /compose
62
- * status surfaces.
63
- */
64
- draftCount(chatId: string): number;
65
- /**
66
- * Inspect drafts without committing — used for preview UX. Returns a
67
- * copy so callers can't mutate internal state.
68
- */
69
- peek(chatId: string): string[];
70
- private isExpired;
71
- }