@a1hvdy/cc-openclaw 0.9.2 → 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.
- package/dist/src/channels/telegram/card-renderer.d.ts +63 -0
- package/dist/src/channels/telegram/card-renderer.js +149 -0
- package/dist/src/channels/telegram/card-renderer.js.map +1 -0
- package/dist/src/channels/telegram/completion-summary.js +20 -1
- package/dist/src/channels/telegram/completion-summary.js.map +1 -1
- package/dist/src/channels/telegram/insight-formatter.d.ts +36 -0
- package/dist/src/channels/telegram/insight-formatter.js +36 -0
- package/dist/src/channels/telegram/insight-formatter.js.map +1 -0
- package/dist/src/channels/telegram/live-card.d.ts +7 -90
- package/dist/src/channels/telegram/live-card.js +22 -265
- package/dist/src/channels/telegram/live-card.js.map +1 -1
- package/dist/src/channels/telegram/logger.d.ts +10 -0
- package/dist/src/channels/telegram/logger.js +13 -0
- package/dist/src/channels/telegram/logger.js.map +1 -0
- package/dist/src/channels/telegram/throttle-controller.d.ts +54 -0
- package/dist/src/channels/telegram/throttle-controller.js +132 -0
- package/dist/src/channels/telegram/throttle-controller.js.map +1 -0
- package/dist/src/channels/telegram/tool-tracker.js +3 -14
- package/dist/src/channels/telegram/tool-tracker.js.map +1 -1
- package/dist/src/cli/doctor.d.ts +24 -0
- package/dist/src/cli/doctor.js +194 -0
- package/dist/src/cli/doctor.js.map +1 -0
- package/dist/src/cli/index.d.ts +8 -0
- package/dist/src/cli/index.js +39 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/command-router/cc-handler.js +35 -709
- package/dist/src/command-router/cc-handler.js.map +1 -1
- package/dist/src/command-router/launch-policy.d.ts +93 -0
- package/dist/src/command-router/launch-policy.js +323 -0
- package/dist/src/command-router/launch-policy.js.map +1 -0
- package/dist/src/command-router/resume-policy.d.ts +18 -0
- package/dist/src/command-router/resume-policy.js +236 -0
- package/dist/src/command-router/resume-policy.js.map +1 -0
- package/dist/src/command-router/turn-formatter.d.ts +19 -0
- package/dist/src/command-router/turn-formatter.js +144 -0
- package/dist/src/command-router/turn-formatter.js.map +1 -0
- package/dist/src/constants.d.ts +33 -2
- package/dist/src/constants.js +33 -2
- package/dist/src/constants.js.map +1 -1
- package/dist/src/lib/config.d.ts +3 -0
- package/dist/src/lib/config.js +46 -0
- package/dist/src/lib/config.js.map +1 -1
- package/dist/src/lib/trajectory.d.ts +1 -1
- package/dist/src/lib/trajectory.js.map +1 -1
- package/dist/src/openai-compat/bridges/allowlist.d.ts +10 -0
- package/dist/src/openai-compat/bridges/allowlist.js +17 -0
- package/dist/src/openai-compat/bridges/allowlist.js.map +1 -0
- package/dist/src/openai-compat/bridges/factory.d.ts +30 -0
- package/dist/src/openai-compat/bridges/factory.js +84 -0
- package/dist/src/openai-compat/bridges/factory.js.map +1 -0
- package/dist/src/openai-compat/bridges/media-bridge.d.ts +34 -0
- package/dist/src/openai-compat/bridges/media-bridge.js +20 -0
- package/dist/src/openai-compat/bridges/media-bridge.js.map +1 -0
- package/dist/src/openai-compat/bridges/openclaw-native-tools.d.ts +61 -0
- package/dist/src/openai-compat/bridges/openclaw-native-tools.js +171 -0
- package/dist/src/openai-compat/bridges/openclaw-native-tools.js.map +1 -0
- package/dist/src/openai-compat/bridges/openclaw-tool-registry.d.ts +26 -0
- package/dist/src/openai-compat/bridges/openclaw-tool-registry.js +38 -0
- package/dist/src/openai-compat/bridges/openclaw-tool-registry.js.map +1 -0
- package/dist/src/openai-compat/bridges/tts-media-bridge.d.ts +19 -0
- package/dist/src/openai-compat/bridges/tts-media-bridge.js +59 -0
- package/dist/src/openai-compat/bridges/tts-media-bridge.js.map +1 -0
- package/dist/src/openai-compat/non-streaming-handler.js +52 -3
- package/dist/src/openai-compat/non-streaming-handler.js.map +1 -1
- package/dist/src/openai-compat/openai-compat.js +64 -2
- package/dist/src/openai-compat/openai-compat.js.map +1 -1
- package/dist/src/openai-compat/streaming-handler.js +107 -1
- package/dist/src/openai-compat/streaming-handler.js.map +1 -1
- package/dist/src/openai-compat/voice-recovery.d.ts +56 -0
- package/dist/src/openai-compat/voice-recovery.js +231 -0
- package/dist/src/openai-compat/voice-recovery.js.map +1 -0
- package/dist/src/session/session-manager.d.ts +51 -0
- package/dist/src/session/session-manager.js +165 -1
- package/dist/src/session/session-manager.js.map +1 -1
- package/dist/src/types/tool-bridge.d.ts +2 -1
- package/dist/src/types/tool-bridge.js +1 -0
- package/dist/src/types/tool-bridge.js.map +1 -1
- package/package.json +1 -1
- package/dist/scripts/bench/ab-harness.d.ts +0 -58
- package/dist/scripts/bench/ab-harness.d.ts.map +0 -1
- package/dist/scripts/bench/ab-harness.js +0 -78
- package/dist/scripts/bench/ab-harness.js.map +0 -1
- package/dist/src/channels/adapter.d.ts.map +0 -1
- package/dist/src/channels/telegram/completion-summary.d.ts.map +0 -1
- package/dist/src/channels/telegram/error-renderer.d.ts.map +0 -1
- package/dist/src/channels/telegram/event-reducer.d.ts.map +0 -1
- package/dist/src/channels/telegram/index.d.ts.map +0 -1
- package/dist/src/channels/telegram/injector.d.ts.map +0 -1
- package/dist/src/channels/telegram/live-card.d.ts.map +0 -1
- package/dist/src/channels/telegram/state-machine.d.ts.map +0 -1
- package/dist/src/channels/telegram/tool-tracker.d.ts.map +0 -1
- package/dist/src/command-router/cc-handler.d.ts.map +0 -1
- package/dist/src/command-router/index.d.ts.map +0 -1
- package/dist/src/constants.d.ts.map +0 -1
- package/dist/src/council/consensus.d.ts.map +0 -1
- package/dist/src/council/council.d.ts.map +0 -1
- package/dist/src/council/index.d.ts.map +0 -1
- package/dist/src/engines/base-oneshot-session.d.ts.map +0 -1
- package/dist/src/engines/index.d.ts.map +0 -1
- package/dist/src/engines/persistent-codex-session.d.ts.map +0 -1
- package/dist/src/engines/persistent-cursor-session.d.ts.map +0 -1
- package/dist/src/engines/persistent-custom-session.d.ts.map +0 -1
- package/dist/src/engines/persistent-gemini-session.d.ts.map +0 -1
- package/dist/src/engines/persistent-session.d.ts.map +0 -1
- package/dist/src/health/handler.d.ts.map +0 -1
- package/dist/src/health/index.d.ts.map +0 -1
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/lib/auto-recovery.d.ts.map +0 -1
- package/dist/src/lib/cache-parity.d.ts.map +0 -1
- package/dist/src/lib/circuit-breaker.d.ts.map +0 -1
- package/dist/src/lib/config.d.ts.map +0 -1
- package/dist/src/lib/debug-tap.d.ts.map +0 -1
- package/dist/src/lib/drift-detector.d.ts.map +0 -1
- package/dist/src/lib/error-formatter.d.ts.map +0 -1
- package/dist/src/lib/heartbeat-workaround.d.ts.map +0 -1
- package/dist/src/lib/index.d.ts.map +0 -1
- package/dist/src/lib/register-guard.d.ts.map +0 -1
- package/dist/src/lib/route-flag.d.ts +0 -49
- package/dist/src/lib/route-flag.d.ts.map +0 -1
- package/dist/src/lib/route-flag.js +0 -52
- package/dist/src/lib/route-flag.js.map +0 -1
- package/dist/src/lib/sysprompt-strip.d.ts.map +0 -1
- package/dist/src/lib/telemetry.d.ts.map +0 -1
- package/dist/src/lib/test-mode.d.ts.map +0 -1
- package/dist/src/lib/vendor-paths.d.ts.map +0 -1
- package/dist/src/logger.d.ts.map +0 -1
- package/dist/src/mcp/bridge.d.ts.map +0 -1
- package/dist/src/mcp/index.d.ts.map +0 -1
- package/dist/src/models.d.ts.map +0 -1
- package/dist/src/openai-compat/cli-stream-parser.d.ts.map +0 -1
- package/dist/src/openai-compat/index.d.ts.map +0 -1
- package/dist/src/openai-compat/openai-compat.d.ts.map +0 -1
- package/dist/src/openai-compat/skill-resolver.d.ts.map +0 -1
- package/dist/src/openai-compat/sse-translator.d.ts.map +0 -1
- package/dist/src/proxy/anthropic-adapter.d.ts.map +0 -1
- package/dist/src/proxy/handler.d.ts.map +0 -1
- package/dist/src/proxy/index.d.ts.map +0 -1
- package/dist/src/proxy/schema-cleaner.d.ts.map +0 -1
- package/dist/src/proxy/thought-cache.d.ts.map +0 -1
- package/dist/src/session/embedded-server.d.ts.map +0 -1
- package/dist/src/session/inbox-manager.d.ts.map +0 -1
- package/dist/src/session/index.d.ts.map +0 -1
- package/dist/src/session/session-manager.d.ts.map +0 -1
- package/dist/src/session-bootstrap/cwd-patch.d.ts.map +0 -1
- package/dist/src/session-bootstrap/index.d.ts.map +0 -1
- package/dist/src/session-bootstrap/sysprompt-strip.d.ts.map +0 -1
- package/dist/src/session-bootstrap/think-conflict-resolver.d.ts.map +0 -1
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/validation.d.ts.map +0 -1
- package/dist/tests/_helpers/subprocess-mock.d.ts +0 -35
- package/dist/tests/_helpers/subprocess-mock.d.ts.map +0 -1
- package/dist/tests/_helpers/subprocess-mock.js +0 -136
- package/dist/tests/_helpers/subprocess-mock.js.map +0 -1
- package/dist/tests/auto-recovery.test.d.ts +0 -2
- package/dist/tests/auto-recovery.test.d.ts.map +0 -1
- package/dist/tests/auto-recovery.test.js +0 -189
- package/dist/tests/auto-recovery.test.js.map +0 -1
- package/dist/tests/bench-harness.test.d.ts +0 -2
- package/dist/tests/bench-harness.test.d.ts.map +0 -1
- package/dist/tests/bench-harness.test.js +0 -21
- package/dist/tests/bench-harness.test.js.map +0 -1
- package/dist/tests/cache-parity.test.d.ts +0 -2
- package/dist/tests/cache-parity.test.d.ts.map +0 -1
- package/dist/tests/cache-parity.test.js +0 -401
- package/dist/tests/cache-parity.test.js.map +0 -1
- package/dist/tests/command-router.test.d.ts +0 -2
- package/dist/tests/command-router.test.d.ts.map +0 -1
- package/dist/tests/command-router.test.js +0 -60
- package/dist/tests/command-router.test.js.map +0 -1
- package/dist/tests/council.test.d.ts +0 -2
- package/dist/tests/council.test.d.ts.map +0 -1
- package/dist/tests/council.test.js +0 -20
- package/dist/tests/council.test.js.map +0 -1
- package/dist/tests/drift-detector.test.d.ts +0 -2
- package/dist/tests/drift-detector.test.d.ts.map +0 -1
- package/dist/tests/drift-detector.test.js +0 -268
- package/dist/tests/drift-detector.test.js.map +0 -1
- package/dist/tests/eager-bootstrap-gating.test.d.ts +0 -9
- package/dist/tests/eager-bootstrap-gating.test.d.ts.map +0 -1
- package/dist/tests/eager-bootstrap-gating.test.js +0 -97
- package/dist/tests/eager-bootstrap-gating.test.js.map +0 -1
- package/dist/tests/engines.test.d.ts +0 -2
- package/dist/tests/engines.test.d.ts.map +0 -1
- package/dist/tests/engines.test.js +0 -8
- package/dist/tests/engines.test.js.map +0 -1
- package/dist/tests/error-formatter.test.d.ts +0 -2
- package/dist/tests/error-formatter.test.d.ts.map +0 -1
- package/dist/tests/error-formatter.test.js +0 -220
- package/dist/tests/error-formatter.test.js.map +0 -1
- package/dist/tests/health.test.d.ts +0 -2
- package/dist/tests/health.test.d.ts.map +0 -1
- package/dist/tests/health.test.js +0 -110
- package/dist/tests/health.test.js.map +0 -1
- package/dist/tests/heartbeat-workaround.test.d.ts +0 -2
- package/dist/tests/heartbeat-workaround.test.d.ts.map +0 -1
- package/dist/tests/heartbeat-workaround.test.js +0 -90
- package/dist/tests/heartbeat-workaround.test.js.map +0 -1
- package/dist/tests/index.test.d.ts +0 -2
- package/dist/tests/index.test.d.ts.map +0 -1
- package/dist/tests/index.test.js +0 -7
- package/dist/tests/index.test.js.map +0 -1
- package/dist/tests/lib-sysprompt-strip.test.d.ts +0 -2
- package/dist/tests/lib-sysprompt-strip.test.d.ts.map +0 -1
- package/dist/tests/lib-sysprompt-strip.test.js +0 -145
- package/dist/tests/lib-sysprompt-strip.test.js.map +0 -1
- package/dist/tests/listener-activation.test.d.ts +0 -2
- package/dist/tests/listener-activation.test.d.ts.map +0 -1
- package/dist/tests/listener-activation.test.js +0 -87
- package/dist/tests/listener-activation.test.js.map +0 -1
- package/dist/tests/mcp-bridge.test.d.ts +0 -2
- package/dist/tests/mcp-bridge.test.d.ts.map +0 -1
- package/dist/tests/mcp-bridge.test.js +0 -137
- package/dist/tests/mcp-bridge.test.js.map +0 -1
- package/dist/tests/openai-compat.test.d.ts +0 -2
- package/dist/tests/openai-compat.test.d.ts.map +0 -1
- package/dist/tests/openai-compat.test.js +0 -8
- package/dist/tests/openai-compat.test.js.map +0 -1
- package/dist/tests/proxy-heartbeat-integration.test.d.ts +0 -15
- package/dist/tests/proxy-heartbeat-integration.test.d.ts.map +0 -1
- package/dist/tests/proxy-heartbeat-integration.test.js +0 -122
- package/dist/tests/proxy-heartbeat-integration.test.js.map +0 -1
- package/dist/tests/proxy.test.d.ts +0 -2
- package/dist/tests/proxy.test.d.ts.map +0 -1
- package/dist/tests/proxy.test.js +0 -8
- package/dist/tests/proxy.test.js.map +0 -1
- package/dist/tests/register-guard-stacking.test.d.ts +0 -2
- package/dist/tests/register-guard-stacking.test.d.ts.map +0 -1
- package/dist/tests/register-guard-stacking.test.js +0 -61
- package/dist/tests/register-guard-stacking.test.js.map +0 -1
- package/dist/tests/register-guard.test.d.ts +0 -2
- package/dist/tests/register-guard.test.d.ts.map +0 -1
- package/dist/tests/register-guard.test.js +0 -129
- package/dist/tests/register-guard.test.js.map +0 -1
- package/dist/tests/route-flag-rollback.test.d.ts +0 -2
- package/dist/tests/route-flag-rollback.test.d.ts.map +0 -1
- package/dist/tests/route-flag-rollback.test.js +0 -70
- package/dist/tests/route-flag-rollback.test.js.map +0 -1
- package/dist/tests/route-flag.test.d.ts +0 -2
- package/dist/tests/route-flag.test.d.ts.map +0 -1
- package/dist/tests/route-flag.test.js +0 -101
- package/dist/tests/route-flag.test.js.map +0 -1
- package/dist/tests/session-bootstrap.test.d.ts +0 -2
- package/dist/tests/session-bootstrap.test.d.ts.map +0 -1
- package/dist/tests/session-bootstrap.test.js +0 -183
- package/dist/tests/session-bootstrap.test.js.map +0 -1
- package/dist/tests/session.test.d.ts +0 -2
- package/dist/tests/session.test.d.ts.map +0 -1
- package/dist/tests/session.test.js +0 -17
- package/dist/tests/session.test.js.map +0 -1
- package/dist/tests/state-machine.test.d.ts +0 -2
- package/dist/tests/state-machine.test.d.ts.map +0 -1
- package/dist/tests/state-machine.test.js +0 -133
- package/dist/tests/state-machine.test.js.map +0 -1
- package/dist/tests/streaming/cli-stream-parser.test.d.ts +0 -2
- package/dist/tests/streaming/cli-stream-parser.test.d.ts.map +0 -1
- package/dist/tests/streaming/cli-stream-parser.test.js +0 -233
- package/dist/tests/streaming/cli-stream-parser.test.js.map +0 -1
- package/dist/tests/streaming/feature-flag.test.d.ts +0 -14
- package/dist/tests/streaming/feature-flag.test.d.ts.map +0 -1
- package/dist/tests/streaming/feature-flag.test.js +0 -163
- package/dist/tests/streaming/feature-flag.test.js.map +0 -1
- package/dist/tests/streaming/no-tools-prompt.test.d.ts +0 -17
- package/dist/tests/streaming/no-tools-prompt.test.d.ts.map +0 -1
- package/dist/tests/streaming/no-tools-prompt.test.js +0 -229
- package/dist/tests/streaming/no-tools-prompt.test.js.map +0 -1
- package/dist/tests/streaming/skill-plus-tools.test.d.ts +0 -14
- package/dist/tests/streaming/skill-plus-tools.test.d.ts.map +0 -1
- package/dist/tests/streaming/skill-plus-tools.test.js +0 -234
- package/dist/tests/streaming/skill-plus-tools.test.js.map +0 -1
- package/dist/tests/streaming/sse-translator.test.d.ts +0 -2
- package/dist/tests/streaming/sse-translator.test.d.ts.map +0 -1
- package/dist/tests/streaming/sse-translator.test.js +0 -227
- package/dist/tests/streaming/sse-translator.test.js.map +0 -1
- package/dist/tests/streaming/tool-result-roundtrip.test.d.ts +0 -11
- package/dist/tests/streaming/tool-result-roundtrip.test.d.ts.map +0 -1
- package/dist/tests/streaming/tool-result-roundtrip.test.js +0 -215
- package/dist/tests/streaming/tool-result-roundtrip.test.js.map +0 -1
- package/dist/tests/streaming/tool-use-translation.test.d.ts +0 -10
- package/dist/tests/streaming/tool-use-translation.test.d.ts.map +0 -1
- package/dist/tests/streaming/tool-use-translation.test.js +0 -251
- package/dist/tests/streaming/tool-use-translation.test.js.map +0 -1
- package/dist/tests/telegram-bridge.test.d.ts +0 -2
- package/dist/tests/telegram-bridge.test.d.ts.map +0 -1
- package/dist/tests/telegram-bridge.test.js +0 -17
- package/dist/tests/telegram-bridge.test.js.map +0 -1
- package/dist/tests/telegram-injector.test.d.ts +0 -2
- package/dist/tests/telegram-injector.test.d.ts.map +0 -1
- package/dist/tests/telegram-injector.test.js +0 -74
- package/dist/tests/telegram-injector.test.js.map +0 -1
- package/dist/tests/telemetry.test.d.ts +0 -2
- package/dist/tests/telemetry.test.d.ts.map +0 -1
- package/dist/tests/telemetry.test.js +0 -405
- package/dist/tests/telemetry.test.js.map +0 -1
- package/dist/tests/test-mode.test.d.ts +0 -2
- package/dist/tests/test-mode.test.d.ts.map +0 -1
- package/dist/tests/test-mode.test.js +0 -39
- 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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"}
|
package/dist/src/constants.d.ts
CHANGED
|
@@ -15,8 +15,39 @@ export declare const GREP_HISTORY_FETCH = 500;
|
|
|
15
15
|
export declare const SESSION_READY_TIMEOUT_MS = 30000;
|
|
16
16
|
/** Fallback delay before checking if proc is alive (resume path) */
|
|
17
17
|
export declare const SESSION_READY_FALLBACK_MS = 2000;
|
|
18
|
-
/** Default timeout for a send() / turn completion
|
|
19
|
-
|
|
18
|
+
/** Default timeout for a send() / turn completion.
|
|
19
|
+
* v0.10.0: bumped 300_000 → 900_000 to align with the
|
|
20
|
+
* `models.providers.cc-openclaw.timeoutSeconds` outer envelope. The
|
|
21
|
+
* runtime stalled-session watchdog (STALLED_SESSION_KILL_MS) is the real
|
|
22
|
+
* ceiling for stuck subprocesses; this constant just prevents an internal
|
|
23
|
+
* per-turn timeout from firing before the outer wall and silently masking
|
|
24
|
+
* the stall as a "timeout" rather than a watchdog kill. */
|
|
25
|
+
export declare const TURN_TIMEOUT_MS = 900000;
|
|
26
|
+
/** Runtime watchdog threshold for "stuck" sessions. If a session is
|
|
27
|
+
* `isBusy === true` AND its stats.lastActivity hasn't moved in this many
|
|
28
|
+
* ms, the SessionManager watchdog aborts + disposes the session. Mirrors
|
|
29
|
+
* the boot-time orphan reaper in gateway-pm2-wrapper.sh:53-60, but runs
|
|
30
|
+
* continuously on a setInterval. Env-overridable via
|
|
31
|
+
* CC_OPENCLAW_STALLED_KILL_MS. v0.10.0. */
|
|
32
|
+
export declare const STALLED_SESSION_KILL_MS = 180000;
|
|
33
|
+
/** How often the stalled-session watchdog scans the sessions Map. */
|
|
34
|
+
export declare const STALLED_WATCH_INTERVAL_MS = 30000;
|
|
35
|
+
/** Runaway-loop watchdog: max new cc-openclaw subprocess spawns within
|
|
36
|
+
* RUNAWAY_LOOP_WINDOW_MS before the next spawn is refused.
|
|
37
|
+
*
|
|
38
|
+
* Rationale: when OpenClaw's agent-runner re-fires `before_model_resolve`
|
|
39
|
+
* multiple times for one user turn (the 2026-05-11 17:42 incident
|
|
40
|
+
* spawned 4 subprocesses in 60s on session 7be69d1b), the cc-openclaw
|
|
41
|
+
* side has no signal that it's the same conversation — each request
|
|
42
|
+
* carries a fresh runId in the X-Session-Id header, so the existing
|
|
43
|
+
* stalled-session watchdog never fires. This second-dimension
|
|
44
|
+
* watchdog catches runaway loops by spawn rate across the SessionManager.
|
|
45
|
+
*
|
|
46
|
+
* Env override: CC_OPENCLAW_LOOP_MAX_SUBPROCS. Min 2, max 20.
|
|
47
|
+
* v0.10.1. */
|
|
48
|
+
export declare const RUNAWAY_LOOP_MAX_SUBPROCS = 3;
|
|
49
|
+
/** Sliding window for the runaway-loop spawn-rate counter. */
|
|
50
|
+
export declare const RUNAWAY_LOOP_WINDOW_MS = 60000;
|
|
20
51
|
/** Timeout for compact / context summary operations */
|
|
21
52
|
export declare const COMPACT_TIMEOUT_MS = 60000;
|
|
22
53
|
/** Delay before SIGKILL after initial SIGTERM on stop() */
|
package/dist/src/constants.js
CHANGED
|
@@ -18,8 +18,39 @@ export const GREP_HISTORY_FETCH = 500;
|
|
|
18
18
|
export const SESSION_READY_TIMEOUT_MS = 30_000;
|
|
19
19
|
/** Fallback delay before checking if proc is alive (resume path) */
|
|
20
20
|
export const SESSION_READY_FALLBACK_MS = 2_000;
|
|
21
|
-
/** Default timeout for a send() / turn completion
|
|
22
|
-
|
|
21
|
+
/** Default timeout for a send() / turn completion.
|
|
22
|
+
* v0.10.0: bumped 300_000 → 900_000 to align with the
|
|
23
|
+
* `models.providers.cc-openclaw.timeoutSeconds` outer envelope. The
|
|
24
|
+
* runtime stalled-session watchdog (STALLED_SESSION_KILL_MS) is the real
|
|
25
|
+
* ceiling for stuck subprocesses; this constant just prevents an internal
|
|
26
|
+
* per-turn timeout from firing before the outer wall and silently masking
|
|
27
|
+
* the stall as a "timeout" rather than a watchdog kill. */
|
|
28
|
+
export const TURN_TIMEOUT_MS = 900_000;
|
|
29
|
+
/** Runtime watchdog threshold for "stuck" sessions. If a session is
|
|
30
|
+
* `isBusy === true` AND its stats.lastActivity hasn't moved in this many
|
|
31
|
+
* ms, the SessionManager watchdog aborts + disposes the session. Mirrors
|
|
32
|
+
* the boot-time orphan reaper in gateway-pm2-wrapper.sh:53-60, but runs
|
|
33
|
+
* continuously on a setInterval. Env-overridable via
|
|
34
|
+
* CC_OPENCLAW_STALLED_KILL_MS. v0.10.0. */
|
|
35
|
+
export const STALLED_SESSION_KILL_MS = 180_000;
|
|
36
|
+
/** How often the stalled-session watchdog scans the sessions Map. */
|
|
37
|
+
export const STALLED_WATCH_INTERVAL_MS = 30_000;
|
|
38
|
+
/** Runaway-loop watchdog: max new cc-openclaw subprocess spawns within
|
|
39
|
+
* RUNAWAY_LOOP_WINDOW_MS before the next spawn is refused.
|
|
40
|
+
*
|
|
41
|
+
* Rationale: when OpenClaw's agent-runner re-fires `before_model_resolve`
|
|
42
|
+
* multiple times for one user turn (the 2026-05-11 17:42 incident
|
|
43
|
+
* spawned 4 subprocesses in 60s on session 7be69d1b), the cc-openclaw
|
|
44
|
+
* side has no signal that it's the same conversation — each request
|
|
45
|
+
* carries a fresh runId in the X-Session-Id header, so the existing
|
|
46
|
+
* stalled-session watchdog never fires. This second-dimension
|
|
47
|
+
* watchdog catches runaway loops by spawn rate across the SessionManager.
|
|
48
|
+
*
|
|
49
|
+
* Env override: CC_OPENCLAW_LOOP_MAX_SUBPROCS. Min 2, max 20.
|
|
50
|
+
* v0.10.1. */
|
|
51
|
+
export const RUNAWAY_LOOP_MAX_SUBPROCS = 3;
|
|
52
|
+
/** Sliding window for the runaway-loop spawn-rate counter. */
|
|
53
|
+
export const RUNAWAY_LOOP_WINDOW_MS = 60_000;
|
|
23
54
|
/** Timeout for compact / context summary operations */
|
|
24
55
|
export const COMPACT_TIMEOUT_MS = 60_000;
|
|
25
56
|
/** Delay before SIGKILL after initial SIGTERM on stop() */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,8EAA8E;AAE9E,2DAA2D;AAC3D,MAAM,CAAC,MAAM,sBAAsB,GAAG,OAAO,CAAC;AAE9C,+EAA+E;AAE/E,gFAAgF;AAChF,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AACrC,iEAAiE;AACjE,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC;AACxC,4DAA4D;AAC5D,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAEtC,+EAA+E;AAE/E,oDAAoD;AACpD,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC;AAC/C,oEAAoE;AACpE,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,CAAC;AAC/C
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"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"}
|
package/dist/src/lib/config.d.ts
CHANGED
|
@@ -53,6 +53,9 @@ export declare function getGeminiApiKey(): string | undefined;
|
|
|
53
53
|
export declare function getGeminiBin(): string | undefined;
|
|
54
54
|
export declare function getCodexBin(): string | undefined;
|
|
55
55
|
export declare function getCursorBin(): string | undefined;
|
|
56
|
+
export declare function getTtsAutoMode(): 'off' | 'always' | 'inbound' | 'tagged';
|
|
57
|
+
/** Test-only: reset the TTS auto-mode cache so the next call re-reads. */
|
|
58
|
+
export declare function _resetTtsAutoModeCacheForTests(): void;
|
|
56
59
|
export declare function getClaudeBin(): string | undefined;
|
|
57
60
|
/**
|
|
58
61
|
* PATH passed to spawned engine subprocesses. Falls back to the standard
|
package/dist/src/lib/config.js
CHANGED
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
* `src/lib/route-flag.ts`. Cluster F (v1.0.0) will remove the legacy
|
|
24
24
|
* env-read fallback and hard-fail when ConfigService is missing.
|
|
25
25
|
*/
|
|
26
|
+
import { readFileSync } from 'node:fs';
|
|
27
|
+
import { join } from 'node:path';
|
|
28
|
+
import { homedir } from 'node:os';
|
|
26
29
|
import { RATE_LIMIT_MAX_REQUESTS } from '../constants.js';
|
|
27
30
|
import { getConfigService } from './config-service.js';
|
|
28
31
|
// ── Sysprompt strip (PRP_v3 §10) ─────────────────────────────────────────
|
|
@@ -202,6 +205,49 @@ export function getCursorBin() {
|
|
|
202
205
|
const v = process.env.CURSOR_BIN;
|
|
203
206
|
return v === undefined || v === '' ? undefined : v;
|
|
204
207
|
}
|
|
208
|
+
// ── TTS auto-mode (v0.10.2) ─────────────────────────────────────────────────
|
|
209
|
+
// Reads `messages.tts.auto` from `~/.openclaw/openclaw.json` once and caches
|
|
210
|
+
// the result. Used by openai-compat to gate the auto-prepended TTS-syntax
|
|
211
|
+
// rule on `appendSystemPrompt`. Valid values match OpenClaw's TTS_AUTO_MODES
|
|
212
|
+
// enum: 'off' | 'always' | 'inbound' | 'tagged'. Unknown values / missing
|
|
213
|
+
// file → 'off' (safe default — rule is gated off).
|
|
214
|
+
//
|
|
215
|
+
// Why a custom file reader instead of ConfigService: cc-openclaw is loaded
|
|
216
|
+
// into OpenClaw's gateway process but exposes its own
|
|
217
|
+
// `~/.openclaw/openclaw.json` parsing for plugin-side decisions that
|
|
218
|
+
// shouldn't reach back through OpenClaw's typed runtime. Tests that need
|
|
219
|
+
// to override should set OPENCLAW_TTS_AUTO_MODE env var.
|
|
220
|
+
let _ttsAutoModeCache = null;
|
|
221
|
+
let _ttsAutoModeCacheChecked = false;
|
|
222
|
+
export function getTtsAutoMode() {
|
|
223
|
+
// Test-time override takes precedence
|
|
224
|
+
const envOverride = process.env.OPENCLAW_TTS_AUTO_MODE?.trim().toLowerCase();
|
|
225
|
+
if (envOverride === 'off' || envOverride === 'always' || envOverride === 'inbound' || envOverride === 'tagged') {
|
|
226
|
+
return envOverride;
|
|
227
|
+
}
|
|
228
|
+
if (!_ttsAutoModeCacheChecked) {
|
|
229
|
+
_ttsAutoModeCacheChecked = true;
|
|
230
|
+
try {
|
|
231
|
+
const configPath = process.env.OPENCLAW_CONFIG_PATH || join(homedir(), '.openclaw', 'openclaw.json');
|
|
232
|
+
const raw = readFileSync(configPath, 'utf8');
|
|
233
|
+
const parsed = JSON.parse(raw);
|
|
234
|
+
_ttsAutoModeCache = parsed.messages?.tts?.auto ?? null;
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
// File missing / unreadable / invalid JSON — fall through to 'off'
|
|
238
|
+
_ttsAutoModeCache = null;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const value = (_ttsAutoModeCache ?? 'off').toLowerCase();
|
|
242
|
+
if (value === 'always' || value === 'inbound' || value === 'tagged')
|
|
243
|
+
return value;
|
|
244
|
+
return 'off';
|
|
245
|
+
}
|
|
246
|
+
/** Test-only: reset the TTS auto-mode cache so the next call re-reads. */
|
|
247
|
+
export function _resetTtsAutoModeCacheForTests() {
|
|
248
|
+
_ttsAutoModeCache = null;
|
|
249
|
+
_ttsAutoModeCacheChecked = false;
|
|
250
|
+
}
|
|
205
251
|
export function getClaudeBin() {
|
|
206
252
|
const cfg = getConfigService();
|
|
207
253
|
if (cfg)
|