@a1hvdy/cc-openclaw 0.8.0 → 0.9.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 (72) hide show
  1. package/dist/src/index.d.ts +10 -1
  2. package/dist/src/index.js +47 -7
  3. package/dist/src/index.js.map +1 -1
  4. package/dist/src/lib/config-service.d.ts +106 -0
  5. package/dist/src/lib/config-service.js +217 -0
  6. package/dist/src/lib/config-service.js.map +1 -0
  7. package/dist/src/lib/config.d.ts +33 -14
  8. package/dist/src/lib/config.js +147 -34
  9. package/dist/src/lib/config.js.map +1 -1
  10. package/dist/src/lib/index.d.ts +1 -1
  11. package/dist/src/lib/index.js +4 -1
  12. package/dist/src/lib/index.js.map +1 -1
  13. package/dist/src/openai-compat/message-extractor.d.ts +79 -0
  14. package/dist/src/openai-compat/message-extractor.js +134 -0
  15. package/dist/src/openai-compat/message-extractor.js.map +1 -0
  16. package/dist/src/openai-compat/mode-flags.d.ts +34 -0
  17. package/dist/src/openai-compat/mode-flags.js +44 -0
  18. package/dist/src/openai-compat/mode-flags.js.map +1 -0
  19. package/dist/src/openai-compat/non-streaming-handler.d.ts +26 -0
  20. package/dist/src/openai-compat/non-streaming-handler.js +108 -0
  21. package/dist/src/openai-compat/non-streaming-handler.js.map +1 -0
  22. package/dist/src/openai-compat/openai-compat.d.ts +15 -166
  23. package/dist/src/openai-compat/openai-compat.js +59 -849
  24. package/dist/src/openai-compat/openai-compat.js.map +1 -1
  25. package/dist/src/openai-compat/prompts.d.ts +47 -0
  26. package/dist/src/openai-compat/prompts.js +119 -0
  27. package/dist/src/openai-compat/prompts.js.map +1 -0
  28. package/dist/src/openai-compat/response-formatter.d.ts +33 -0
  29. package/dist/src/openai-compat/response-formatter.js +74 -0
  30. package/dist/src/openai-compat/response-formatter.js.map +1 -0
  31. package/dist/src/openai-compat/session-key-resolver.d.ts +41 -0
  32. package/dist/src/openai-compat/session-key-resolver.js +78 -0
  33. package/dist/src/openai-compat/session-key-resolver.js.map +1 -0
  34. package/dist/src/openai-compat/status-reporter.d.ts +30 -0
  35. package/dist/src/openai-compat/status-reporter.js +81 -0
  36. package/dist/src/openai-compat/status-reporter.js.map +1 -0
  37. package/dist/src/openai-compat/streaming-handler.d.ts +41 -0
  38. package/dist/src/openai-compat/streaming-handler.js +294 -0
  39. package/dist/src/openai-compat/streaming-handler.js.map +1 -0
  40. package/dist/src/openai-compat/tool-calls-parser.d.ts +34 -0
  41. package/dist/src/openai-compat/tool-calls-parser.js +93 -0
  42. package/dist/src/openai-compat/tool-calls-parser.js.map +1 -0
  43. package/dist/src/openai-compat/tool-results-serializer.d.ts +60 -0
  44. package/dist/src/openai-compat/tool-results-serializer.js +56 -0
  45. package/dist/src/openai-compat/tool-results-serializer.js.map +1 -0
  46. package/dist/src/session-bootstrap/cwd-patch.js +20 -13
  47. package/dist/src/session-bootstrap/cwd-patch.js.map +1 -1
  48. package/dist/src/types/index.d.ts +15 -0
  49. package/dist/src/types/index.js +16 -0
  50. package/dist/src/types/index.js.map +1 -0
  51. package/dist/src/types/route.d.ts +41 -0
  52. package/dist/src/types/route.js +12 -0
  53. package/dist/src/types/route.js.map +1 -0
  54. package/dist/src/types/runtime-config.d.ts +161 -0
  55. package/dist/src/types/runtime-config.js +118 -0
  56. package/dist/src/types/runtime-config.js.map +1 -0
  57. package/dist/src/types/session.d.ts +48 -0
  58. package/dist/src/types/session.js +20 -0
  59. package/dist/src/types/session.js.map +1 -0
  60. package/dist/src/types/sse.d.ts +38 -0
  61. package/dist/src/types/sse.js +12 -0
  62. package/dist/src/types/sse.js.map +1 -0
  63. package/dist/src/types/tool-bridge.d.ts +81 -0
  64. package/dist/src/types/tool-bridge.js +34 -0
  65. package/dist/src/types/tool-bridge.js.map +1 -0
  66. package/dist/src/types/upstream.d.ts +652 -0
  67. package/dist/src/types/upstream.js +145 -0
  68. package/dist/src/types/upstream.js.map +1 -0
  69. package/package.json +3 -2
  70. package/dist/src/lib/route-flag.d.ts +0 -49
  71. package/dist/src/lib/route-flag.js +0 -52
  72. package/dist/src/lib/route-flag.js.map +0 -1
@@ -10,6 +10,7 @@
10
10
  * injection must run BEFORE any session start so the cwd is already
11
11
  * adjusted by the time engines spawn. All others are order-independent.
12
12
  */
13
+ import { getConfigService } from './lib/config-service.js';
13
14
  export declare const PLUGIN_ID = "cc-openclaw";
14
15
  export declare const VERSION = "0.1.0";
15
16
  /**
@@ -36,6 +37,7 @@ export interface PluginApi {
36
37
  stop: () => Promise<void> | void;
37
38
  }): void;
38
39
  }
40
+ export { getConfigService };
39
41
  /**
40
42
  * Top-level plugin entry. Idempotent — re-calls are no-op.
41
43
  * Guard centralized via defaultRegisterGuard (P2 cco-hardening).
@@ -43,6 +45,13 @@ export interface PluginApi {
43
45
  export declare function register(api: PluginApi): void;
44
46
  /** Test-only helper to reset top-level registration state. */
45
47
  export declare function _resetRegisteredForTests(): void;
48
+ /**
49
+ * Test-only helper to reset the ConfigService singleton. Each test that
50
+ * mutates `process.env` and re-invokes `register()` should call this first
51
+ * so the config is re-parsed with the test's env, not the cached value
52
+ * from a prior test. Also exported from `lib/config-service.ts` directly.
53
+ */
54
+ export declare function _resetConfigServiceForTests(): void;
46
55
  export type { ChannelAdapter, ChannelMessage, ChannelInbound, ChannelButton } from './channels/adapter.js';
47
56
  export { registerChannelAdapter } from './channels/adapter.js';
48
- export { selectEngine, captureSessionRoute, type Engine, type SessionRoute } from './lib/route-flag.js';
57
+ export { selectEngine, captureSessionRoute, type Engine, type SessionRoute } from './lib/config-service.js';
package/dist/src/index.js CHANGED
@@ -11,7 +11,8 @@
11
11
  * adjusted by the time engines spawn. All others are order-independent.
12
12
  */
13
13
  import { defaultRegisterGuard } from './lib/register-guard.js';
14
- import { selectEngine } from './lib/route-flag.js';
14
+ import { ConfigService, setConfigService, getConfigService, selectEngine, _resetConfigServiceForTests as _resetConfigSingleton, } from './lib/config-service.js';
15
+ import { ConfigError, RuntimeMode } from './types/runtime-config.js';
15
16
  import { wrapApiWithDebugTap } from './lib/debug-tap.js';
16
17
  import { register as registerCommandRouter } from './command-router/index.js';
17
18
  import { registerCwdPatch, registerSyspromptStrip, registerThinkConflictResolver, } from './session-bootstrap/index.js';
@@ -32,9 +33,11 @@ export const VERSION = '0.1.0';
32
33
  * To activate: set OPENCLAW_CC_OPENCLAW_LISTENERS=1 AND remove
33
34
  * savvy-claude-code from openclaw.json plugins.allow (mutual exclusion).
34
35
  *
35
- * This is separate from OPENCLAW_USE_CC_OPENCLAW (the route-flag),
36
- * which decides per-session engine routing at session-create time.
37
- * LISTENERS controls whether cc-openclaw wires its handlers at all.
36
+ * This is separate from OPENCLAW_CC_OPENCLAW_ACTIVE (or its deprecated
37
+ * alias OPENCLAW_USE_CC_OPENCLAW), which decides per-session engine
38
+ * routing see `selectEngine()` in `lib/config-service.ts`. LISTENERS
39
+ * controls whether cc-openclaw wires its handlers at all; the two are
40
+ * orthogonal contracts (ARCHITECTURE.md §3).
38
41
  */
39
42
  function listenersEnabled() {
40
43
  const v = process.env.OPENCLAW_CC_OPENCLAW_LISTENERS;
@@ -43,14 +46,41 @@ function listenersEnabled() {
43
46
  const norm = v.toLowerCase();
44
47
  return norm === '1' || norm === 'true' || norm === 'on';
45
48
  }
49
+ // Re-export getConfigService from config-service.ts for callers that import
50
+ // from the plugin entry point. The actual singleton lives in config-service.ts
51
+ // to avoid a circular import with src/lib/config.ts (which now reads from it).
52
+ export { getConfigService };
46
53
  /**
47
54
  * Top-level plugin entry. Idempotent — re-calls are no-op.
48
55
  * Guard centralized via defaultRegisterGuard (P2 cco-hardening).
49
56
  */
50
57
  export function register(api) {
51
58
  defaultRegisterGuard.guard('cc-openclaw/index', api, () => {
52
- const initialEngine = selectEngine();
53
59
  const logger = api.logger || console;
60
+ // ── Cluster A step 3+7: ConfigService boot wiring ─────────────────────
61
+ // Parse env into typed RuntimeConfig + install as the module-level
62
+ // singleton consumed by src/lib/config.ts getters (compat shim).
63
+ // Soft-fail during v0.9.x compat window — existing env readers still
64
+ // work when ConfigService is undefined. Hard-fail deferred until v1.0.
65
+ try {
66
+ const svc = ConfigService.fromEnv(process.env);
67
+ setConfigService(svc);
68
+ const cfg = svc.config;
69
+ logger.info(`[cc-openclaw] config: mode=${cfg.mode} cacheParity={module:${cfg.cacheParityModuleEnabled},trackB:${cfg.cacheParityTrackB}} tokenTelemetry={routeGate:${cfg.tokenTelemetryRouteGate},writer:${cfg.tokenTelemetryWriter}} testMode=${cfg.testMode}`);
70
+ if (cfg.usedDeprecatedAlias) {
71
+ logger.warn('[cc-openclaw] DEPRECATION: OPENCLAW_USE_CC_OPENCLAW is the legacy activation flag. Set OPENCLAW_CC_OPENCLAW_ACTIVE=1 instead. The alias is retained through v0.9.x and removed at v1.0.0.');
72
+ }
73
+ if (cfg.mode === RuntimeMode.PASSIVE) {
74
+ // No-op — passive mode is the default and announced by the
75
+ // existing passive-load message below. Avoids double-logging.
76
+ }
77
+ }
78
+ catch (err) {
79
+ const e = err instanceof ConfigError ? err.message : String(err);
80
+ logger.warn(`[cc-openclaw] ConfigService.fromEnv() failed during boot — continuing with legacy env readers (compat shim window): ${e}`);
81
+ setConfigService(undefined);
82
+ }
83
+ const initialEngine = selectEngine();
54
84
  logger.info(`[cc-openclaw] plugin loaded; route flag selects: ${initialEngine}`);
55
85
  if (!listenersEnabled()) {
56
86
  logger.info('[cc-openclaw] passive load — listeners gated. To activate: set OPENCLAW_CC_OPENCLAW_LISTENERS=1 AND remove savvy-claude-code from openclaw.json plugins.allow (else handlers collide).');
@@ -82,7 +112,17 @@ export function register(api) {
82
112
  export function _resetRegisteredForTests() {
83
113
  defaultRegisterGuard._resetForTests();
84
114
  }
115
+ /**
116
+ * Test-only helper to reset the ConfigService singleton. Each test that
117
+ * mutates `process.env` and re-invokes `register()` should call this first
118
+ * so the config is re-parsed with the test's env, not the cached value
119
+ * from a prior test. Also exported from `lib/config-service.ts` directly.
120
+ */
121
+ export function _resetConfigServiceForTests() {
122
+ _resetConfigSingleton();
123
+ }
85
124
  export { registerChannelAdapter } from './channels/adapter.js';
86
- // Re-export route-flag types so callers can compose engine routing without a circular import.
87
- export { selectEngine, captureSessionRoute } from './lib/route-flag.js';
125
+ // Re-export engine routing primitives. Originally lived in lib/route-flag.ts;
126
+ // collapsed into config-service.ts at Cluster A step 8 (route-flag.ts deleted).
127
+ export { selectEngine, captureSessionRoute } from './lib/config-service.js';
88
128
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,QAAQ,IAAI,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,6BAA6B,GAC9B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,yBAAyB,EACzB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAE/D,MAAM,CAAC,MAAM,SAAS,GAAG,aAAa,CAAC;AACvC,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAyB/B;;;;;;;;;;;;;;;;GAgBG;AACH,SAAS,gBAAgB;IACvB,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC;IACrD,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACrB,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC7B,OAAO,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,IAAI,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAc;IACrC,oBAAoB,CAAC,KAAK,CAAC,mBAAmB,EAAE,GAAG,EAAE,GAAG,EAAE;QACxD,MAAM,aAAa,GAAG,YAAY,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,oDAAoD,aAAa,EAAE,CAAC,CAAC;QAEjF,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CACT,wLAAwL,CACzL,CAAC;YACF,OAAO;QACT,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,kIAAkI,CAAC,CAAC;QAEhJ,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,GAAG,EAAE,CAAC;YAC1C,MAAM,CAAC,IAAI,CAAC,iJAAiJ,CAAC,CAAC;QACjK,CAAC;QAED,kEAAkE;QAClE,gBAAgB,CAAC,mBAAmB,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC;QACxD,sBAAsB,CAAC,mBAAmB,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC,CAAC;QACpE,6BAA6B,CAAC,mBAAmB,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAE1E,4BAA4B;QAC5B,qBAAqB,CAAC,mBAAmB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC;QAE9D,yEAAyE;QACzE,gBAAgB,CAAC,mBAAmB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;QACvD,gBAAgB,CAAC,mBAAmB,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC;QACxD,mBAAmB,CAAC,mBAAmB,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC;QAC9D,yBAAyB,CAAC,mBAAmB,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC,CAAC;QAC1E,oBAAoB,CAAC,mBAAmB,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC;QAChE,oBAAoB,CAAC,mBAAmB,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC;QAEhE,6FAA6F;QAC7F,iBAAiB,CAAC,mBAAmB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,8DAA8D;AAC9D,sGAAsG;AACtG,MAAM,UAAU,wBAAwB;IACtC,oBAAoB,CAAC,cAAc,EAAE,CAAC;AACxC,CAAC;AAKD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,8FAA8F;AAC9F,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAkC,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Cluster A — ConfigService.
3
+ *
4
+ * The single source of truth for runtime configuration. Parses
5
+ * `process.env` into a frozen `RuntimeConfig` at boot, exposes two
6
+ * narrow escape hatches that preserve the live-read vs frozen-snapshot
7
+ * asymmetry currently encoded in `src/lib/route-flag.ts:48,63`.
8
+ *
9
+ * Compat-shim window (v0.9.x): existing `src/lib/config.ts` getters
10
+ * delegate here once Cluster A migration step 6 lands. Direct `process.env`
11
+ * reads are removed in step 7 (the final Cluster A commit) when
12
+ * `src/lib/route-flag.ts` collapses into `selectEngine()` /
13
+ * `captureSessionRoute()` below.
14
+ *
15
+ * NOT yet wired into `src/index.ts` — that's Cluster A migration step 3.
16
+ */
17
+ import { type RuntimeConfig, type ParseEnvResult } from '../types/runtime-config.js';
18
+ /**
19
+ * Parse `process.env` into a `RuntimeConfig`. Total function — never
20
+ * throws. Use the discriminated `ParseEnvResult` to handle failure.
21
+ *
22
+ * Behavior preservation contract: every `process.env.X` read here MUST
23
+ * match the semantic of the corresponding getter in `src/lib/config.ts`.
24
+ * The two dual-default flags (`OPENCLAW_TOKEN_TELEMETRY`,
25
+ * `OPENCLAW_CACHE_PARITY`) are split into two fields each — see
26
+ * `src/types/runtime-config.ts` schema comments.
27
+ */
28
+ export declare function parseEnv(env: NodeJS.ProcessEnv): ParseEnvResult;
29
+ export type Engine = 'cc-openclaw' | 'claude-local';
30
+ export interface SessionRoute {
31
+ readonly engine: Engine;
32
+ readonly capturedAt: string;
33
+ }
34
+ /** Primary activation env var (PRP_v3 §10). */
35
+ export declare const ACTIVE_FLAG_ENV = "OPENCLAW_CC_OPENCLAW_ACTIVE";
36
+ /**
37
+ * @deprecated Use `ACTIVE_FLAG_ENV`. Read for fallback when the new name
38
+ * is unset. Removed in v1.0.0.
39
+ */
40
+ export declare const ROUTE_FLAG_ENV = "OPENCLAW_USE_CC_OPENCLAW";
41
+ /**
42
+ * Read env at call time and report whether cc-openclaw engine routing is
43
+ * active. **Independent of `LISTENERS`** — per ARCHITECTURE.md §3, engine
44
+ * selection (per-session) and handler wiring (process-wide) are orthogonal:
45
+ * a session can pick the cc-openclaw engine even when LISTENERS is off.
46
+ *
47
+ * Honors deprecated `OPENCLAW_USE_CC_OPENCLAW` fallback when the new
48
+ * ACTIVE_FLAG_ENV is unset.
49
+ *
50
+ * Free-function variant — works without a ConfigService instance.
51
+ */
52
+ export declare function isCcOpenclawEnabled(env?: NodeJS.ProcessEnv): boolean;
53
+ /**
54
+ * Free-function variant of `ConfigService.prototype.selectEngine()`.
55
+ * Re-reads env at call time. Use when you don't have a ConfigService instance
56
+ * (i.e. early boot, or in tests) — semantics match the instance method exactly.
57
+ *
58
+ * **Only reads `ACTIVE_FLAG_ENV` / deprecated alias.** Does NOT consider
59
+ * `LISTENERS` — that flag controls handler wiring, not engine selection.
60
+ * The higher-level `RuntimeMode` enum (which classifies the whole-process
61
+ * activation state) is computed separately by `deriveMode`.
62
+ */
63
+ export declare function selectEngine(env?: NodeJS.ProcessEnv): Engine;
64
+ /**
65
+ * Free-function variant of `ConfigService.prototype.captureSessionRoute()`.
66
+ * Returns a frozen snapshot — subsequent env mutations do NOT affect the
67
+ * captured route. This is what makes "in-flight sessions stay on original
68
+ * engine" architecturally true at the routing layer.
69
+ */
70
+ export declare function captureSessionRoute(env?: NodeJS.ProcessEnv): SessionRoute;
71
+ /**
72
+ * ConfigService wraps the parsed config with the live-read escape hatches
73
+ * that preserve `route-flag.ts:48,63` semantics.
74
+ *
75
+ * - `config`: frozen at construction; reads return boot-time values.
76
+ * - `selectEngine()`: re-reads `process.env` on every call. Use when picking
77
+ * an engine for a NEW session — lets a rollback flip take effect mid-process
78
+ * without restart.
79
+ * - `captureSessionRoute()`: snapshots the current engine into a frozen
80
+ * object. Use at session-start to lock the engine for that session's
81
+ * lifetime — lets in-flight sessions ride out a rollback unaffected.
82
+ */
83
+ export declare class ConfigService {
84
+ readonly config: Readonly<RuntimeConfig>;
85
+ constructor(config: Readonly<RuntimeConfig>);
86
+ /**
87
+ * Re-reads env at call time. Use for new-session engine selection.
88
+ * Asymmetric with `config.activeRouting` (frozen at boot) BY DESIGN —
89
+ * see PRP §5 Cluster A "Frozen + escape-hatch contract".
90
+ *
91
+ * Delegates to the module-level `selectEngine` free function so that
92
+ * the class API and free-function API share one implementation.
93
+ */
94
+ selectEngine(env?: NodeJS.ProcessEnv): Engine;
95
+ /**
96
+ * Snapshot the current engine for a new session. Frozen — subsequent
97
+ * env mutations do NOT affect the captured route. Delegates to the
98
+ * free function for the same single-source-of-truth reason.
99
+ */
100
+ captureSessionRoute(env?: NodeJS.ProcessEnv): Readonly<SessionRoute>;
101
+ /** Convenience constructor for boot path. */
102
+ static fromEnv(env?: NodeJS.ProcessEnv): ConfigService;
103
+ }
104
+ export declare function getConfigService(): ConfigService | undefined;
105
+ export declare function setConfigService(svc: ConfigService | undefined): void;
106
+ export declare function _resetConfigServiceForTests(): void;
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Cluster A — ConfigService.
3
+ *
4
+ * The single source of truth for runtime configuration. Parses
5
+ * `process.env` into a frozen `RuntimeConfig` at boot, exposes two
6
+ * narrow escape hatches that preserve the live-read vs frozen-snapshot
7
+ * asymmetry currently encoded in `src/lib/route-flag.ts:48,63`.
8
+ *
9
+ * Compat-shim window (v0.9.x): existing `src/lib/config.ts` getters
10
+ * delegate here once Cluster A migration step 6 lands. Direct `process.env`
11
+ * reads are removed in step 7 (the final Cluster A commit) when
12
+ * `src/lib/route-flag.ts` collapses into `selectEngine()` /
13
+ * `captureSessionRoute()` below.
14
+ *
15
+ * NOT yet wired into `src/index.ts` — that's Cluster A migration step 3.
16
+ */
17
+ import { RuntimeConfigSchema, RuntimeMode, ConfigError, deriveMode, } from '../types/runtime-config.js';
18
+ const TRUTHY = (v) => v === '1' || v?.toLowerCase() === 'true' || v?.toLowerCase() === 'on';
19
+ const FALSEY = (v) => v === '0' || v?.toLowerCase() === 'false' || v?.toLowerCase() === 'off';
20
+ /**
21
+ * Parse `process.env` into a `RuntimeConfig`. Total function — never
22
+ * throws. Use the discriminated `ParseEnvResult` to handle failure.
23
+ *
24
+ * Behavior preservation contract: every `process.env.X` read here MUST
25
+ * match the semantic of the corresponding getter in `src/lib/config.ts`.
26
+ * The two dual-default flags (`OPENCLAW_TOKEN_TELEMETRY`,
27
+ * `OPENCLAW_CACHE_PARITY`) are split into two fields each — see
28
+ * `src/types/runtime-config.ts` schema comments.
29
+ */
30
+ export function parseEnv(env) {
31
+ const mode = deriveMode(env);
32
+ const usedDeprecatedAlias = env.OPENCLAW_CC_OPENCLAW_ACTIVE === undefined &&
33
+ env.OPENCLAW_USE_CC_OPENCLAW !== undefined;
34
+ const raw = {
35
+ mode,
36
+ listenersEnabled: TRUTHY(env.OPENCLAW_CC_OPENCLAW_LISTENERS),
37
+ activeRouting: mode === RuntimeMode.ACTIVE_ROUTING,
38
+ toolStream: TRUTHY(env.CC_OPENCLAW_TOOL_STREAM),
39
+ allowBuiltins: TRUTHY(env.CC_OPENCLAW_ALLOW_BUILTINS),
40
+ toolsPerMessage: TRUTHY(env.OPENAI_COMPAT_TOOLS_PER_MESSAGE),
41
+ // Dual-default split (see schema comments).
42
+ cacheParityModuleEnabled: !FALSEY(env.OPENCLAW_CACHE_PARITY),
43
+ cacheParityTrackB: env.OPENCLAW_CACHE_PARITY === '1',
44
+ newConvoHeuristic: env.OPENAI_COMPAT_NEW_CONVO_HEURISTIC === '1',
45
+ aggressiveStripEnabled: !FALSEY(env.OPENCLAW_AGGRESSIVE_STRIP),
46
+ debug: TRUTHY(env.CC_OPENCLAW_DEBUG),
47
+ registerDebug: env.OPENCLAW_REGISTER_DEBUG === '1',
48
+ // Dual-default split (see schema comments).
49
+ tokenTelemetryRouteGate: env.OPENCLAW_TOKEN_TELEMETRY === '1',
50
+ tokenTelemetryWriter: env.OPENCLAW_TOKEN_TELEMETRY !== '0',
51
+ syspromptDump: env.OPENCLAW_SYSPROMPT_DUMP === '1',
52
+ trajectoryEnabled: env.CC_OPENCLAW_TRAJECTORY === '1',
53
+ statusUrl: env.OPENAI_COMPAT_STATUS_URL && env.OPENAI_COMPAT_STATUS_URL !== ''
54
+ ? env.OPENAI_COMPAT_STATUS_URL
55
+ : undefined,
56
+ surfaceThinking: env.CC_OPENCLAW_SURFACE_THINKING === '1',
57
+ thinkingExcerpt: env.CC_OPENCLAW_THINKING_EXCERPT === '1',
58
+ maxConcurrentSessions: parseInt(env.CLAUDE_CODE_MAX_SESSIONS ?? '', 10) || 32,
59
+ sessionTtlMinutes: parseInt(env.CLAUDE_CODE_SESSION_TTL ?? '', 10) || 1440,
60
+ serverHost: env.OPENCLAW_SERVER_HOST || '127.0.0.1',
61
+ rateLimit: parseInt(env.OPENCLAW_RATE_LIMIT ?? '', 10) || 100,
62
+ serverToken: env.OPENCLAW_SERVER_TOKEN && env.OPENCLAW_SERVER_TOKEN !== '' ? env.OPENCLAW_SERVER_TOKEN : undefined,
63
+ corsAllowAll: env.OPENCLAW_CORS_ORIGINS === '*',
64
+ claudeBin: env.CLAUDE_BIN && env.CLAUDE_BIN !== '' ? env.CLAUDE_BIN : undefined,
65
+ geminiBin: env.GEMINI_BIN && env.GEMINI_BIN !== '' ? env.GEMINI_BIN : undefined,
66
+ codexBin: env.CODEX_BIN && env.CODEX_BIN !== '' ? env.CODEX_BIN : undefined,
67
+ cursorBin: env.CURSOR_BIN && env.CURSOR_BIN !== '' ? env.CURSOR_BIN : undefined,
68
+ driftAlertsEnabled: env.OPENCLAW_CC_OPENCLAW_DRIFT_ALERTS !== '0',
69
+ autoRecoveryEnabled: env.OPENCLAW_CC_OPENCLAW_AUTO_RECOVERY !== '0',
70
+ quotaPausePct: Number(env.OPENCLAW_QUOTA_PAUSE_PCT) || 95,
71
+ testMode: env.OPENCLAW_PLUGIN_TEST_MODE === '1',
72
+ heartbeatWorkaroundDisabled: env.CC_OPENCLAW_DISABLE_HEARTBEAT_WORKAROUND === '1',
73
+ savvyLiveCardEnabled: TRUTHY(env.SAVVY_LIVE_CARD),
74
+ usedDeprecatedAlias,
75
+ };
76
+ const result = RuntimeConfigSchema.safeParse(raw);
77
+ if (!result.success) {
78
+ return { ok: false, error: new ConfigError(result.error.issues) };
79
+ }
80
+ return { ok: true, config: Object.freeze(result.data) };
81
+ }
82
+ // ── Free-function compat shims (Cluster A step 8: collapses route-flag.ts) ──
83
+ //
84
+ // The old `src/lib/route-flag.ts` exported `selectEngine`,
85
+ // `isCcOpenclawEnabled`, `captureSessionRoute`, `ACTIVE_FLAG_ENV`, and
86
+ // `ROUTE_FLAG_ENV` as free top-level symbols. Step 8 collapsed that file
87
+ // into ConfigService: the exports below re-implement the same API as
88
+ // pure functions that read env at call time (no caching, no
89
+ // ConfigService instance required) so existing call sites + tests work
90
+ // unchanged after a one-line import-path swap.
91
+ //
92
+ // `ConfigService.prototype.selectEngine()` and `captureSessionRoute()`
93
+ // delegate to these free functions, so the semantics are bit-identical
94
+ // regardless of which API a caller uses.
95
+ //
96
+ // **Deprecation alias `ROUTE_FLAG_ENV`** is preserved through v0.9.x and
97
+ // removed at v1.0.0. The activation derivation in `deriveMode` already
98
+ // honors it as a fallback.
99
+ /** Primary activation env var (PRP_v3 §10). */
100
+ export const ACTIVE_FLAG_ENV = 'OPENCLAW_CC_OPENCLAW_ACTIVE';
101
+ /**
102
+ * @deprecated Use `ACTIVE_FLAG_ENV`. Read for fallback when the new name
103
+ * is unset. Removed in v1.0.0.
104
+ */
105
+ export const ROUTE_FLAG_ENV = 'OPENCLAW_USE_CC_OPENCLAW';
106
+ /**
107
+ * Read env at call time and report whether cc-openclaw engine routing is
108
+ * active. **Independent of `LISTENERS`** — per ARCHITECTURE.md §3, engine
109
+ * selection (per-session) and handler wiring (process-wide) are orthogonal:
110
+ * a session can pick the cc-openclaw engine even when LISTENERS is off.
111
+ *
112
+ * Honors deprecated `OPENCLAW_USE_CC_OPENCLAW` fallback when the new
113
+ * ACTIVE_FLAG_ENV is unset.
114
+ *
115
+ * Free-function variant — works without a ConfigService instance.
116
+ */
117
+ export function isCcOpenclawEnabled(env = process.env) {
118
+ const v = env[ACTIVE_FLAG_ENV] ?? env[ROUTE_FLAG_ENV];
119
+ if (!v)
120
+ return false;
121
+ const norm = v.toLowerCase();
122
+ return norm === '1' || norm === 'true' || norm === 'on';
123
+ }
124
+ /**
125
+ * Free-function variant of `ConfigService.prototype.selectEngine()`.
126
+ * Re-reads env at call time. Use when you don't have a ConfigService instance
127
+ * (i.e. early boot, or in tests) — semantics match the instance method exactly.
128
+ *
129
+ * **Only reads `ACTIVE_FLAG_ENV` / deprecated alias.** Does NOT consider
130
+ * `LISTENERS` — that flag controls handler wiring, not engine selection.
131
+ * The higher-level `RuntimeMode` enum (which classifies the whole-process
132
+ * activation state) is computed separately by `deriveMode`.
133
+ */
134
+ export function selectEngine(env = process.env) {
135
+ return isCcOpenclawEnabled(env) ? 'cc-openclaw' : 'claude-local';
136
+ }
137
+ /**
138
+ * Free-function variant of `ConfigService.prototype.captureSessionRoute()`.
139
+ * Returns a frozen snapshot — subsequent env mutations do NOT affect the
140
+ * captured route. This is what makes "in-flight sessions stay on original
141
+ * engine" architecturally true at the routing layer.
142
+ */
143
+ export function captureSessionRoute(env = process.env) {
144
+ return Object.freeze({
145
+ engine: selectEngine(env),
146
+ capturedAt: new Date().toISOString(),
147
+ });
148
+ }
149
+ /**
150
+ * ConfigService wraps the parsed config with the live-read escape hatches
151
+ * that preserve `route-flag.ts:48,63` semantics.
152
+ *
153
+ * - `config`: frozen at construction; reads return boot-time values.
154
+ * - `selectEngine()`: re-reads `process.env` on every call. Use when picking
155
+ * an engine for a NEW session — lets a rollback flip take effect mid-process
156
+ * without restart.
157
+ * - `captureSessionRoute()`: snapshots the current engine into a frozen
158
+ * object. Use at session-start to lock the engine for that session's
159
+ * lifetime — lets in-flight sessions ride out a rollback unaffected.
160
+ */
161
+ export class ConfigService {
162
+ config;
163
+ constructor(config) {
164
+ this.config = config;
165
+ }
166
+ /**
167
+ * Re-reads env at call time. Use for new-session engine selection.
168
+ * Asymmetric with `config.activeRouting` (frozen at boot) BY DESIGN —
169
+ * see PRP §5 Cluster A "Frozen + escape-hatch contract".
170
+ *
171
+ * Delegates to the module-level `selectEngine` free function so that
172
+ * the class API and free-function API share one implementation.
173
+ */
174
+ selectEngine(env = process.env) {
175
+ return selectEngine(env);
176
+ }
177
+ /**
178
+ * Snapshot the current engine for a new session. Frozen — subsequent
179
+ * env mutations do NOT affect the captured route. Delegates to the
180
+ * free function for the same single-source-of-truth reason.
181
+ */
182
+ captureSessionRoute(env = process.env) {
183
+ return captureSessionRoute(env);
184
+ }
185
+ /** Convenience constructor for boot path. */
186
+ static fromEnv(env = process.env) {
187
+ const result = parseEnv(env);
188
+ if (!result.ok)
189
+ throw result.error;
190
+ return new ConfigService(result.config);
191
+ }
192
+ }
193
+ // ── Module-level singleton (Cluster A step 7) ────────────────────────────────
194
+ //
195
+ // The singleton lives here (NOT in src/index.ts) so that src/lib/config.ts
196
+ // can import it without creating a circular import (index.ts imports from
197
+ // many lib modules; if config.ts imported from index.ts, the cycle would
198
+ // surface at boot).
199
+ //
200
+ // `setConfigService` is called once by `register()` at boot. `getConfigService`
201
+ // returns `undefined` before that call OR if parseEnv failed. Compat-shim
202
+ // callers should pattern-match: `getConfigService()?.config.X ?? legacy`.
203
+ //
204
+ // Tests can clear via `_resetConfigServiceForTests()`. Tests that mutate env
205
+ // and depend on getters reading the new value should not call `register()`
206
+ // at all, OR should reset the singleton first.
207
+ let _singleton;
208
+ export function getConfigService() {
209
+ return _singleton;
210
+ }
211
+ export function setConfigService(svc) {
212
+ _singleton = svc;
213
+ }
214
+ export function _resetConfigServiceForTests() {
215
+ _singleton = undefined;
216
+ }
217
+ //# sourceMappingURL=config-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-service.js","sourceRoot":"","sources":["../../../src/lib/config-service.ts"],"names":[],"mappings":"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"}
@@ -1,19 +1,27 @@
1
1
  /**
2
- * config — single env-reader source of truth (PRP_v3 §5 hard rule).
2
+ * config — env-reader source of truth.
3
3
  *
4
- * v3 §5 mandates: `process.env` reads only in `src/index.ts`,
5
- * `src/lib/route-flag.ts`, and this module. Every other source file imports
6
- * its config from here via the typed getter functions.
4
+ * Originally PRP_v3 §5: `process.env` reads only in `src/index.ts`,
5
+ * `src/lib/route-flag.ts`, and this module. Cluster A step 7 layered a
6
+ * compat shim on top: getters now delegate to `ConfigService.config.X`
7
+ * (the typed Cluster A boot config) when available, falling back to
8
+ * the original `process.env.X` read otherwise.
7
9
  *
8
- * Why getters (not cached constants): tests flip env vars at runtime via
9
- * `process.env.X = 'y'` and expect immediate effect. Cached-at-import
10
- * constants would freeze the value at first load, breaking every existing
11
- * test that toggles env mid-run. Getters preserve test flippability while
12
- * still centralizing env-coupling to one module.
10
+ * Why the shim instead of pure delegation: tests flip env vars at
11
+ * runtime via `process.env.X = 'y'` and expect immediate effect. When
12
+ * `ConfigService` is unset (most tests), getters fall through to env
13
+ * preserving test flippability bit-for-bit. When `ConfigService` is
14
+ * set (live gateway boot), the typed config wins, providing single-
15
+ * source-of-truth observability via `/health` and the boot log.
13
16
  *
14
- * Adding a new env var: add a getter here, import it from the consumer.
15
- * Do NOT add `process.env.X` reads in any other file under src/ except
16
- * the two pre-authorized exceptions noted above.
17
+ * Adding a new env var: add a getter here AND a field to
18
+ * `RuntimeConfigSchema` in `src/types/runtime-config.ts`. The shim line
19
+ * pattern is `getConfigService()?.config.X ?? legacyEnvRead`.
20
+ *
21
+ * Cluster A step 8 will collapse the activation getters (selectEngine,
22
+ * route-flag) into ConfigService escape hatches and delete
23
+ * `src/lib/route-flag.ts`. Cluster F (v1.0.0) will remove the legacy
24
+ * env-read fallback and hard-fail when ConfigService is missing.
17
25
  */
18
26
  export declare function getAggressiveStripEnabled(): boolean;
19
27
  export declare function getCacheParityEnabled(): boolean;
@@ -50,6 +58,9 @@ export declare function getClaudeBin(): string | undefined;
50
58
  * PATH passed to spawned engine subprocesses. Falls back to the standard
51
59
  * Unix path so binaries resolve even when the parent's PATH is unset
52
60
  * (preserved from persistent-session.ts:257 + persistent-custom-session.ts:240).
61
+ *
62
+ * NOT in RuntimeConfig — PATH is process-environment, not plugin
63
+ * configuration. Kept as a direct env reader.
53
64
  */
54
65
  export declare function getProcessPath(): string;
55
66
  export declare function isTokenTelemetryWriterEnabled(): boolean;
@@ -57,7 +68,11 @@ export declare function isTokenTelemetryWriterEnabled(): boolean;
57
68
  export declare function isRegisterDebugEnabled(): boolean;
58
69
  export declare function isHeartbeatWorkaroundDisabled(): boolean;
59
70
  export declare function getQuotaPausePct(): number;
60
- /** Raw value for `isToolsPerMessageModeEnabled()` parsing. */
71
+ /**
72
+ * Raw value for `isToolsPerMessageModeEnabled()` parsing.
73
+ * NOT delegated — the consumer parses the raw string itself; the typed
74
+ * `toolsPerMessage` boolean field is for boot-time observability only.
75
+ */
61
76
  export declare function getOpenaiCompatToolsPerMessage(): string | undefined;
62
77
  /** Strict opt-in — legacy new-conversation heuristic via env=1. */
63
78
  export declare function isOpenaiCompatNewConvoHeuristic(): boolean;
@@ -68,7 +83,11 @@ export declare function isSavvyLiveCardEnabled(): boolean;
68
83
  export declare function getHomeOrTmp(): string;
69
84
  export declare function getHealthPortEnv(): string | undefined;
70
85
  export declare function isDriftAlertsEnabled(): boolean;
71
- /** Dedup window for repeated drift Telegram alerts. Default 1h. */
86
+ /**
87
+ * Dedup window for repeated drift Telegram alerts. Default 1h.
88
+ * NOT in RuntimeConfig — niche tunable not surfaced through the activation
89
+ * matrix. Kept as a direct env reader.
90
+ */
72
91
  export declare function getDriftDedupeWindowMs(): number;
73
92
  export declare function isAutoRecoveryEnabled(): boolean;
74
93
  export declare function getSurfaceThinkingEnabled(): boolean;