@a1hvdy/cc-openclaw 0.27.2 → 0.27.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/src/channels/telegram-mirror/card-renderer.d.ts +8 -22
  2. package/dist/src/channels/telegram-mirror/card-renderer.js +227 -22
  3. package/dist/src/channels/telegram-mirror/commands.d.ts +16 -0
  4. package/dist/src/channels/telegram-mirror/commands.js +34 -0
  5. package/dist/src/channels/telegram-mirror/inbound-handler.js +1 -1
  6. package/dist/src/channels/telegram-mirror/turn-bridge.d.ts +12 -1
  7. package/dist/src/channels/telegram-mirror/turn-bridge.js +41 -2
  8. package/dist/src/constants.d.ts +27 -0
  9. package/dist/src/constants.js +28 -0
  10. package/dist/src/engines/persistent-session.d.ts +5 -0
  11. package/dist/src/engines/persistent-session.js +27 -0
  12. package/dist/src/lib/error-formatter.d.ts +14 -2
  13. package/dist/src/lib/error-formatter.js +23 -11
  14. package/dist/src/lib/error-renderer.js +3 -1
  15. package/dist/src/lib/html-render.d.ts +23 -16
  16. package/dist/src/lib/html-render.js +127 -1
  17. package/dist/src/lib/markdown-to-mdv2.js +2 -1
  18. package/dist/src/lib/telegram-bot-api.d.ts +22 -6
  19. package/dist/src/lib/telegram-bot-api.js +94 -14
  20. package/dist/src/openai-compat/non-streaming-handler.js +18 -1
  21. package/dist/src/openai-compat/openai-compat.js +61 -2
  22. package/dist/src/openai-compat/request-coalescer.d.ts +77 -0
  23. package/dist/src/openai-compat/request-coalescer.js +157 -0
  24. package/dist/src/openai-compat/streaming-handler.d.ts +9 -1
  25. package/dist/src/openai-compat/streaming-handler.js +40 -5
  26. package/dist/src/session/persisted-sessions.d.ts +11 -0
  27. package/dist/src/session/persisted-sessions.js +17 -0
  28. package/dist/src/session/session-manager.js +22 -6
  29. package/dist/src/session/watchdogs.d.ts +3 -0
  30. package/dist/src/session/watchdogs.js +6 -0
  31. package/dist/src/session-bootstrap/cwd-patch.js +1 -2
  32. package/dist/src/types.d.ts +11 -0
  33. package/package.json +1 -1
  34. package/dist/src/config/drift-detector.d.ts +0 -28
  35. package/dist/src/config/drift-detector.js +0 -74
  36. package/dist/src/lib/stale-pid-files.d.ts +0 -17
  37. package/dist/src/lib/stale-pid-files.js +0 -39
  38. package/dist/src/persistence/snapshot.d.ts +0 -18
  39. package/dist/src/persistence/snapshot.js +0 -31
  40. package/dist/src/persistence/wal.d.ts +0 -17
  41. package/dist/src/persistence/wal.js +0 -31
  42. package/dist/src/types/index.d.ts +0 -15
  43. package/dist/src/types/index.js +0 -15
  44. package/dist/src/types/session.d.ts +0 -48
  45. package/dist/src/types/session.js +0 -19
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a1hvdy/cc-openclaw",
3
- "version": "0.27.2",
3
+ "version": "0.27.6",
4
4
  "description": "A1xAI's Anthropic CLI bridge plugin for OpenClaw",
5
5
  "author": "@a1cy",
6
6
  "license": "MIT",
@@ -1,28 +0,0 @@
1
- /**
2
- * drift-detector — snapshots the parsed Config to disk on a healthy boot;
3
- * compares on subsequent boots and returns a delta list.
4
- *
5
- * Primary purpose: detect keys pruned by `openclaw doctor --fix`
6
- * (OF5 — feedback_cc_openclaw_provider_timeout.md).
7
- *
8
- * Snapshot path: ~/.openclaw/workspace/memory/cc-openclaw-config-snapshot.json
9
- * The file is written atomically (write-then-rename is not available in pure
10
- * Node ESM without extra deps; we write directly since the worst case is a
11
- * corrupted snapshot — non-fatal; falls back to empty baseline).
12
- */
13
- import type { Config } from './schema.js';
14
- export interface ConfigDelta {
15
- path: string;
16
- previous: unknown;
17
- current: unknown;
18
- }
19
- /**
20
- * Compare current config against the on-disk snapshot.
21
- * Returns an array of changed paths (empty = no drift).
22
- */
23
- export declare function detectDrift(current: Config): ConfigDelta[];
24
- /**
25
- * Persist current config as the baseline snapshot for future drift detection.
26
- * Called at the end of a successful boot (after phase 7 / ready state).
27
- */
28
- export declare function saveSnapshot(current: Config): void;
@@ -1,74 +0,0 @@
1
- /**
2
- * drift-detector — snapshots the parsed Config to disk on a healthy boot;
3
- * compares on subsequent boots and returns a delta list.
4
- *
5
- * Primary purpose: detect keys pruned by `openclaw doctor --fix`
6
- * (OF5 — feedback_cc_openclaw_provider_timeout.md).
7
- *
8
- * Snapshot path: ~/.openclaw/workspace/memory/cc-openclaw-config-snapshot.json
9
- * The file is written atomically (write-then-rename is not available in pure
10
- * Node ESM without extra deps; we write directly since the worst case is a
11
- * corrupted snapshot — non-fatal; falls back to empty baseline).
12
- */
13
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
14
- import { homedir } from 'os';
15
- import { join, dirname } from 'path';
16
- const SNAPSHOT_PATH = join(homedir(), '.openclaw', 'workspace', 'memory', 'cc-openclaw-config-snapshot.json');
17
- // ── Internal helpers ──────────────────────────────────────────────────────────
18
- function flattenConfig(obj, prefix = '') {
19
- if (obj === null || typeof obj !== 'object') {
20
- return { [prefix]: obj };
21
- }
22
- const result = {};
23
- for (const [k, v] of Object.entries(obj)) {
24
- const key = prefix ? `${prefix}.${k}` : k;
25
- if (v !== null && typeof v === 'object' && !Array.isArray(v)) {
26
- Object.assign(result, flattenConfig(v, key));
27
- }
28
- else {
29
- result[key] = v;
30
- }
31
- }
32
- return result;
33
- }
34
- function readSnapshot() {
35
- if (!existsSync(SNAPSHOT_PATH))
36
- return {};
37
- try {
38
- const raw = readFileSync(SNAPSHOT_PATH, 'utf8');
39
- return JSON.parse(raw);
40
- }
41
- catch {
42
- return {};
43
- }
44
- }
45
- // ── Public API ────────────────────────────────────────────────────────────────
46
- /**
47
- * Compare current config against the on-disk snapshot.
48
- * Returns an array of changed paths (empty = no drift).
49
- */
50
- export function detectDrift(current) {
51
- const previous = readSnapshot();
52
- const flat = flattenConfig(current);
53
- const deltas = [];
54
- for (const [path, value] of Object.entries(flat)) {
55
- if (path in previous && JSON.stringify(previous[path]) !== JSON.stringify(value)) {
56
- deltas.push({ path, previous: previous[path], current: value });
57
- }
58
- }
59
- return deltas;
60
- }
61
- /**
62
- * Persist current config as the baseline snapshot for future drift detection.
63
- * Called at the end of a successful boot (after phase 7 / ready state).
64
- */
65
- export function saveSnapshot(current) {
66
- try {
67
- mkdirSync(dirname(SNAPSHOT_PATH), { recursive: true });
68
- const flat = flattenConfig(current);
69
- writeFileSync(SNAPSHOT_PATH, JSON.stringify(flat, null, 2), 'utf8');
70
- }
71
- catch {
72
- // Non-fatal: drift detection degrades to "no baseline" on next boot.
73
- }
74
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * Stale PID-keyed file cleanup — for status/sentinel files named `<pid>.json`
3
- * in a tee directory, removes entries whose PID is no longer alive.
4
- *
5
- * Extracted from `live-card.ts` 2026-05-14. Pure-function utility with a
6
- * dir-parameter shape so future callers (other PID-keyed sentinel patterns)
7
- * can reuse without duplicating the kill(pid, 0) liveness probe.
8
- *
9
- * The original file-extension was `.json`; expose it as a parameter so this
10
- * is forward-compatible with `.sock`, `.lock`, etc.
11
- */
12
- /**
13
- * Remove `<pid><ext>` files in `dir` whose PID no longer exists.
14
- * Silent on missing directory. Per-file errors are swallowed — this is
15
- * best-effort cleanup, not a correctness guarantee.
16
- */
17
- export declare function cleanStalePidFiles(dir: string, ext?: string): void;
@@ -1,39 +0,0 @@
1
- /**
2
- * Stale PID-keyed file cleanup — for status/sentinel files named `<pid>.json`
3
- * in a tee directory, removes entries whose PID is no longer alive.
4
- *
5
- * Extracted from `live-card.ts` 2026-05-14. Pure-function utility with a
6
- * dir-parameter shape so future callers (other PID-keyed sentinel patterns)
7
- * can reuse without duplicating the kill(pid, 0) liveness probe.
8
- *
9
- * The original file-extension was `.json`; expose it as a parameter so this
10
- * is forward-compatible with `.sock`, `.lock`, etc.
11
- */
12
- import { readdirSync, unlinkSync } from 'node:fs';
13
- /**
14
- * Remove `<pid><ext>` files in `dir` whose PID no longer exists.
15
- * Silent on missing directory. Per-file errors are swallowed — this is
16
- * best-effort cleanup, not a correctness guarantee.
17
- */
18
- export function cleanStalePidFiles(dir, ext = '.json') {
19
- try {
20
- const files = readdirSync(dir);
21
- for (const file of files) {
22
- if (!file.endsWith(ext))
23
- continue;
24
- const pid = parseInt(file.replace(ext, ''), 10);
25
- if (isNaN(pid))
26
- continue;
27
- try {
28
- process.kill(pid, 0);
29
- }
30
- catch {
31
- try {
32
- unlinkSync(`${dir}/${file}`);
33
- }
34
- catch { /* ignore */ }
35
- }
36
- }
37
- }
38
- catch { /* directory doesn't exist — nothing to clean */ }
39
- }
@@ -1,18 +0,0 @@
1
- /**
2
- * SnapshotWriter — periodic full-state snapshot of the SessionRegistry.
3
- *
4
- * Snapshot file: ~/.openclaw/workspace/memory/cc-openclaw-session-snapshot.json
5
- * Written every N minutes from phase 7 (schedule-jobs).
6
- * Phase E wires SessionRegistry.snapshot() → SnapshotWriter.write().
7
- * Stub body in Phase D.
8
- */
9
- import type { SessionState } from './session-registry.js';
10
- export declare class SnapshotWriter {
11
- private readonly path;
12
- constructor(path?: string);
13
- /**
14
- * Write the full session state array as a JSON file.
15
- * Phase E: write to a temp file then rename for atomicity.
16
- */
17
- write(states: SessionState[]): Promise<void>;
18
- }
@@ -1,31 +0,0 @@
1
- /**
2
- * SnapshotWriter — periodic full-state snapshot of the SessionRegistry.
3
- *
4
- * Snapshot file: ~/.openclaw/workspace/memory/cc-openclaw-session-snapshot.json
5
- * Written every N minutes from phase 7 (schedule-jobs).
6
- * Phase E wires SessionRegistry.snapshot() → SnapshotWriter.write().
7
- * Stub body in Phase D.
8
- */
9
- import { mkdirSync, writeFileSync } from 'fs';
10
- import { homedir } from 'os';
11
- import { join, dirname } from 'path';
12
- const SNAPSHOT_PATH = join(homedir(), '.openclaw', 'workspace', 'memory', 'cc-openclaw-session-snapshot.json');
13
- export class SnapshotWriter {
14
- path;
15
- constructor(path = SNAPSHOT_PATH) {
16
- this.path = path;
17
- }
18
- /**
19
- * Write the full session state array as a JSON file.
20
- * Phase E: write to a temp file then rename for atomicity.
21
- */
22
- async write(states) {
23
- try {
24
- mkdirSync(dirname(this.path), { recursive: true });
25
- writeFileSync(this.path, JSON.stringify(states, null, 2), 'utf8');
26
- }
27
- catch {
28
- // Non-fatal stub; Phase E promotes to logged error.
29
- }
30
- }
31
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * WalWriter — append-only JSONL writer for the session registry WAL.
3
- *
4
- * WAL file location: ~/.openclaw/workspace/memory/cc-openclaw-session-wal.jsonl
5
- * Phase E wires this into SessionRegistry.set() / delete().
6
- * Stub body in Phase D — compiles and exports the class with the correct interface.
7
- */
8
- export declare class WalWriter {
9
- private readonly path;
10
- constructor(path?: string);
11
- /**
12
- * Append a JSON-serializable record as a single JSONL line.
13
- * Creates parent directories if absent. Non-atomic in Phase D stub;
14
- * Phase E adds write-then-rename for crash safety.
15
- */
16
- append(record: Record<string, unknown>): void;
17
- }
@@ -1,31 +0,0 @@
1
- /**
2
- * WalWriter — append-only JSONL writer for the session registry WAL.
3
- *
4
- * WAL file location: ~/.openclaw/workspace/memory/cc-openclaw-session-wal.jsonl
5
- * Phase E wires this into SessionRegistry.set() / delete().
6
- * Stub body in Phase D — compiles and exports the class with the correct interface.
7
- */
8
- import { mkdirSync, appendFileSync } from 'fs';
9
- import { homedir } from 'os';
10
- import { join, dirname } from 'path';
11
- const WAL_PATH = join(homedir(), '.openclaw', 'workspace', 'memory', 'cc-openclaw-session-wal.jsonl');
12
- export class WalWriter {
13
- path;
14
- constructor(path = WAL_PATH) {
15
- this.path = path;
16
- }
17
- /**
18
- * Append a JSON-serializable record as a single JSONL line.
19
- * Creates parent directories if absent. Non-atomic in Phase D stub;
20
- * Phase E adds write-then-rename for crash safety.
21
- */
22
- append(record) {
23
- try {
24
- mkdirSync(dirname(this.path), { recursive: true });
25
- appendFileSync(this.path, JSON.stringify(record) + '\n', 'utf8');
26
- }
27
- catch {
28
- // Non-fatal in Phase D; Phase E promotes to logged error.
29
- }
30
- }
31
- }
@@ -1,15 +0,0 @@
1
- /**
2
- * Cluster A — Type-seams barrel.
3
- *
4
- * Single import surface for all typed boundaries introduced in Cluster A.
5
- * Subsequent clusters import from `cc-openclaw/types` (this barrel)
6
- * rather than reaching into individual modules.
7
- *
8
- * This file is intentionally pure re-exports — no logic, no side effects.
9
- */
10
- export * from './runtime-config.js';
11
- export * from './route.js';
12
- export * from './sse.js';
13
- export * from './session.js';
14
- export * from './upstream.js';
15
- export * from './tool-bridge.js';
@@ -1,15 +0,0 @@
1
- /**
2
- * Cluster A — Type-seams barrel.
3
- *
4
- * Single import surface for all typed boundaries introduced in Cluster A.
5
- * Subsequent clusters import from `cc-openclaw/types` (this barrel)
6
- * rather than reaching into individual modules.
7
- *
8
- * This file is intentionally pure re-exports — no logic, no side effects.
9
- */
10
- export * from './runtime-config.js';
11
- export * from './route.js';
12
- export * from './sse.js';
13
- export * from './session.js';
14
- export * from './upstream.js';
15
- export * from './tool-bridge.js';
@@ -1,48 +0,0 @@
1
- /**
2
- * Cluster A — Session boundary types.
3
- *
4
- * Re-exports the session vocabulary already established in the root
5
- * `src/types.ts` module. New aliases (`SessionStartConfig`, `SessionMeta`)
6
- * preview Cluster B's `SessionService` boundary without yet introducing
7
- * a new shape — they're typed wrappers over today's `SessionConfig` /
8
- * `ActiveSession`.
9
- *
10
- * `SessionName` is the branded type that Cluster D's `SessionRegistry`
11
- * will use to enforce the `'openai-'` prefix routing discriminant
12
- * (cwd-patch.ts:489 gates CWD redirect, tools restoration, CLAUDE.md
13
- * injection on this prefix).
14
- *
15
- * NOT consumed yet — Cluster A first commit establishes the vocabulary.
16
- */
17
- export type { SessionConfig as SessionStartConfig, SessionStats, ActiveSession, SessionInfo, SessionSendOptions, StreamCallbacks, StreamEvent, SendResult, SendOptions, TurnResult, CostBreakdown, ISession, EngineType, PermissionMode, EffortLevel, PluginConfig, HookConfig, CustomEngineConfig, } from '../types.js';
18
- /**
19
- * Branded session-name type. Prevents raw string from being passed where
20
- * the `'openai-'` prefix is load-bearing. Use the constructors below to
21
- * mint or strip the prefix — never construct directly.
22
- */
23
- export type SessionName = string & {
24
- readonly __brand: 'SessionName';
25
- };
26
- export declare const sessionNameFromKey: (key: string) => SessionName;
27
- export declare const isOpenAiBridgeName: (name: SessionName) => boolean;
28
- export declare const stripOpenAiPrefix: (name: SessionName) => string;
29
- /**
30
- * Cluster B/D will fold this into `SessionRegistry.SessionEntry`. For
31
- * Cluster A it's a typed preview — the shape Cluster D will persist,
32
- * declared here so other clusters can compile against the contract.
33
- */
34
- export interface SessionMeta {
35
- readonly name: SessionName;
36
- readonly claudeSessionId: string | null;
37
- readonly pid: number | null;
38
- readonly cachedSysPromptHash: string;
39
- readonly skipPersistence: boolean;
40
- readonly createdAt: number;
41
- readonly updatedAt: number;
42
- }
43
- /**
44
- * Input shape Cluster B's `SessionService.send()` accepts.
45
- * Today's call sites pass either a string or an array of content blocks;
46
- * this interface preserves both without yet committing to a tighter shape.
47
- */
48
- export type SendInput = string | ReadonlyArray<unknown>;
@@ -1,19 +0,0 @@
1
- /**
2
- * Cluster A — Session boundary types.
3
- *
4
- * Re-exports the session vocabulary already established in the root
5
- * `src/types.ts` module. New aliases (`SessionStartConfig`, `SessionMeta`)
6
- * preview Cluster B's `SessionService` boundary without yet introducing
7
- * a new shape — they're typed wrappers over today's `SessionConfig` /
8
- * `ActiveSession`.
9
- *
10
- * `SessionName` is the branded type that Cluster D's `SessionRegistry`
11
- * will use to enforce the `'openai-'` prefix routing discriminant
12
- * (cwd-patch.ts:489 gates CWD redirect, tools restoration, CLAUDE.md
13
- * injection on this prefix).
14
- *
15
- * NOT consumed yet — Cluster A first commit establishes the vocabulary.
16
- */
17
- export const sessionNameFromKey = (key) => `openai-${key}`;
18
- export const isOpenAiBridgeName = (name) => name.startsWith('openai-');
19
- export const stripOpenAiPrefix = (name) => name.replace(/^openai-/, '');