@openclaw-cloud/agent-controller 2.0.0 → 2.1.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 (38) hide show
  1. package/bin/agent-controller.js +11 -2
  2. package/dist/commands/channel-server.d.ts +17 -0
  3. package/dist/commands/channel-server.js +71 -0
  4. package/dist/commands/channel-server.js.map +1 -0
  5. package/dist/config-file.js +6 -0
  6. package/dist/config-file.js.map +1 -1
  7. package/dist/config.d.ts +10 -0
  8. package/dist/config.js +20 -0
  9. package/dist/config.js.map +1 -1
  10. package/dist/handlers/board-handler.js +56 -20
  11. package/dist/handlers/board-handler.js.map +1 -1
  12. package/dist/handlers/chat.d.ts +17 -0
  13. package/dist/handlers/chat.js +93 -0
  14. package/dist/handlers/chat.js.map +1 -1
  15. package/dist/index.js +24 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/providers/claude-code/channel-server.d.ts +60 -0
  18. package/dist/providers/claude-code/channel-server.js +155 -0
  19. package/dist/providers/claude-code/channel-server.js.map +1 -0
  20. package/dist/providers/claude-code/index.d.ts +68 -0
  21. package/dist/providers/claude-code/index.js +276 -0
  22. package/dist/providers/claude-code/index.js.map +1 -0
  23. package/dist/providers/claude-code/login-flow.d.ts +26 -0
  24. package/dist/providers/claude-code/login-flow.js +129 -0
  25. package/dist/providers/claude-code/login-flow.js.map +1 -0
  26. package/dist/providers/claude-code/settings-writer.d.ts +29 -0
  27. package/dist/providers/claude-code/settings-writer.js +79 -0
  28. package/dist/providers/claude-code/settings-writer.js.map +1 -0
  29. package/dist/providers/claude-code/socket-bridge.d.ts +88 -0
  30. package/dist/providers/claude-code/socket-bridge.js +302 -0
  31. package/dist/providers/claude-code/socket-bridge.js.map +1 -0
  32. package/dist/providers/claude-code/spawn-claude.d.ts +44 -0
  33. package/dist/providers/claude-code/spawn-claude.js +108 -0
  34. package/dist/providers/claude-code/spawn-claude.js.map +1 -0
  35. package/dist/providers/index.d.ts +3 -1
  36. package/dist/providers/index.js +12 -0
  37. package/dist/providers/index.js.map +1 -1
  38. package/package.json +1 -1
@@ -0,0 +1,44 @@
1
+ import { spawn, type ChildProcess } from 'node:child_process';
2
+ import { EventEmitter } from 'node:events';
3
+ export interface SpawnClaudeDeps {
4
+ /** Working directory for the claude process (workspace). */
5
+ workspaceDir: string;
6
+ /** Channels plugin flag argument (defaults to `plugin:agent-controller`). */
7
+ channelsFlag?: string;
8
+ /** Extra CLI flags to append. */
9
+ extraArgs?: string[];
10
+ /** Environment variables to merge on top of process.env. */
11
+ env?: Record<string, string | undefined>;
12
+ /** Allow `--dangerously-load-development-channels` (default true). */
13
+ danglyDev?: boolean;
14
+ /** Override spawn (tests). */
15
+ spawnFn?: typeof spawn;
16
+ /** Max retries on crash (default 5). */
17
+ maxRetries?: number;
18
+ }
19
+ /**
20
+ * Supervise a `claude` subprocess. Emits:
21
+ * - `stderr` (Buffer)
22
+ * - `stdout` (Buffer)
23
+ * - `spawn` (ChildProcess)
24
+ * - `exit` (code|null, signal|null)
25
+ * - `gaveup` — too many crashes, no more restarts.
26
+ *
27
+ * Restart on crash with capped exponential backoff.
28
+ */
29
+ export declare class ClaudeProcess extends EventEmitter {
30
+ private readonly deps;
31
+ private child;
32
+ private retries;
33
+ private shuttingDown;
34
+ private lastSpawnAt;
35
+ constructor(deps: SpawnClaudeDeps);
36
+ start(): void;
37
+ private spawnOnce;
38
+ private buildArgs;
39
+ /** Send SIGINT to interrupt the current turn. */
40
+ interrupt(): void;
41
+ stop(): void;
42
+ isRunning(): boolean;
43
+ getChild(): ChildProcess | null;
44
+ }
@@ -0,0 +1,108 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { EventEmitter } from 'node:events';
3
+ import { logCollector } from '../../connection.js';
4
+ /**
5
+ * Supervise a `claude` subprocess. Emits:
6
+ * - `stderr` (Buffer)
7
+ * - `stdout` (Buffer)
8
+ * - `spawn` (ChildProcess)
9
+ * - `exit` (code|null, signal|null)
10
+ * - `gaveup` — too many crashes, no more restarts.
11
+ *
12
+ * Restart on crash with capped exponential backoff.
13
+ */
14
+ export class ClaudeProcess extends EventEmitter {
15
+ deps;
16
+ child = null;
17
+ retries = 0;
18
+ shuttingDown = false;
19
+ lastSpawnAt = 0;
20
+ constructor(deps) {
21
+ super();
22
+ this.deps = deps;
23
+ }
24
+ start() {
25
+ if (this.child)
26
+ return;
27
+ this.shuttingDown = false;
28
+ this.spawnOnce();
29
+ }
30
+ spawnOnce() {
31
+ const spawnFn = this.deps.spawnFn ?? spawn;
32
+ const args = this.buildArgs();
33
+ this.lastSpawnAt = Date.now();
34
+ const child = spawnFn('claude', args, {
35
+ cwd: this.deps.workspaceDir,
36
+ env: { ...process.env, ...(this.deps.env ?? {}) },
37
+ stdio: ['pipe', 'pipe', 'pipe'],
38
+ });
39
+ this.child = child;
40
+ child.stdout?.on('data', (data) => this.emit('stdout', data));
41
+ child.stderr?.on('data', (data) => {
42
+ this.emit('stderr', data);
43
+ logCollector?.push('claude_stderr', 'debug', data.toString().slice(0, 500));
44
+ });
45
+ child.on('error', (err) => {
46
+ logCollector?.push('claude_spawn_error', 'error', err.message);
47
+ this.emit('error', err);
48
+ });
49
+ child.on('exit', (code, signal) => {
50
+ this.emit('exit', code, signal);
51
+ this.child = null;
52
+ if (this.shuttingDown)
53
+ return;
54
+ // Reset retries on a healthy long run
55
+ if (Date.now() - this.lastSpawnAt > 60_000)
56
+ this.retries = 0;
57
+ const maxRetries = this.deps.maxRetries ?? 5;
58
+ // Semantics: maxRetries is the number of RESTART attempts allowed.
59
+ // Increment first, then check — so maxRetries=5 yields exactly 5 restarts
60
+ // (retry counts 1..5) before giving up on the 6th crash.
61
+ this.retries += 1;
62
+ if (this.retries > maxRetries) {
63
+ logCollector?.push('claude_giveup', 'error', `claude crashed too many times (${this.retries - 1}/${maxRetries}), giving up`);
64
+ this.emit('gaveup');
65
+ return;
66
+ }
67
+ const backoff = Math.min(30_000, 500 * 2 ** (this.retries - 1));
68
+ logCollector?.push('claude_restart_scheduled', 'warn', `claude exited code=${code ?? 'null'} sig=${signal ?? 'null'}; retry ${this.retries}/${maxRetries} in ${backoff}ms`);
69
+ setTimeout(() => {
70
+ if (!this.shuttingDown)
71
+ this.spawnOnce();
72
+ }, backoff).unref();
73
+ });
74
+ this.emit('spawn', child);
75
+ logCollector?.push('claude_spawned', 'info', `claude spawned (pid=${child.pid})`);
76
+ }
77
+ buildArgs() {
78
+ const args = ['--channels', this.deps.channelsFlag ?? 'plugin:agent-controller'];
79
+ if (this.deps.danglyDev !== false)
80
+ args.push('--dangerously-load-development-channels');
81
+ if (this.deps.extraArgs)
82
+ args.push(...this.deps.extraArgs);
83
+ return args;
84
+ }
85
+ /** Send SIGINT to interrupt the current turn. */
86
+ interrupt() {
87
+ this.child?.kill('SIGINT');
88
+ }
89
+ stop() {
90
+ this.shuttingDown = true;
91
+ if (this.child) {
92
+ try {
93
+ this.child.kill('SIGTERM');
94
+ }
95
+ catch {
96
+ /* ignore */
97
+ }
98
+ }
99
+ this.child = null;
100
+ }
101
+ isRunning() {
102
+ return !!this.child && this.child.exitCode === null;
103
+ }
104
+ getChild() {
105
+ return this.child;
106
+ }
107
+ }
108
+ //# sourceMappingURL=spawn-claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-claude.js","sourceRoot":"","sources":["../../../src/providers/claude-code/spawn-claude.ts"],"names":[],"mappings":"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"}
@@ -4,8 +4,10 @@ export type { ChatSession, ChatMessage, ChatAttachment, ChatContentBlock, IChatP
4
4
  export { OpenclawProvider } from './openclaw/index.js';
5
5
  export { MockProvider } from './mock/index.js';
6
6
  export type { MockAction } from './mock/index.js';
7
+ export { ClaudeCodeProvider } from './claude-code/index.js';
8
+ export type { ClaudeCodeProviderConfig } from './claude-code/index.js';
7
9
  export declare function configureProvider(provider: IAgentProvider): void;
8
10
  export declare function getProvider(): IAgentProvider | null;
9
11
  /** For testing only — reset the global provider */
10
12
  export declare function resetProvider(): void;
11
- export declare function createProvider(type: string, config: Record<string, string>): IAgentProvider;
13
+ export declare function createProvider(type: string, config: Record<string, string | undefined>): IAgentProvider;
@@ -1,7 +1,9 @@
1
1
  import { OpenclawProvider } from './openclaw/index.js';
2
2
  import { MockProvider } from './mock/index.js';
3
+ import { ClaudeCodeProvider } from './claude-code/index.js';
3
4
  export { OpenclawProvider } from './openclaw/index.js';
4
5
  export { MockProvider } from './mock/index.js';
6
+ export { ClaudeCodeProvider } from './claude-code/index.js';
5
7
  let _provider = null;
6
8
  export function configureProvider(provider) {
7
9
  _provider = provider;
@@ -19,6 +21,16 @@ export function createProvider(type, config) {
19
21
  return new OpenclawProvider(config.wsUrl ?? 'ws://localhost:18789', config.wsToken ?? '');
20
22
  case 'mock':
21
23
  return new MockProvider();
24
+ case 'claude-code':
25
+ return new ClaudeCodeProvider({
26
+ workspaceDir: config.workspaceDir ?? '/home/ubuntu/.claude/workspace',
27
+ anthropicApiKey: config.anthropicApiKey,
28
+ anthropicAuthToken: config.anthropicAuthToken,
29
+ claudeCodeOauthToken: config.claudeCodeOauthToken,
30
+ backendUrl: config.backendUrl,
31
+ agentToken: config.agentToken,
32
+ claudeMdContent: config.claudeMdContent,
33
+ });
22
34
  default:
23
35
  throw new Error(`Unknown provider type: ${type}`);
24
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAU/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,IAAI,SAAS,GAA0B,IAAI,CAAC;AAE5C,MAAM,UAAU,iBAAiB,CAAC,QAAwB;IACxD,SAAS,GAAG,QAAQ,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,aAAa;IAC3B,SAAS,GAAG,IAAI,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,MAA8B;IACzE,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,UAAU;YACb,OAAO,IAAI,gBAAgB,CAAC,MAAM,CAAC,KAAK,IAAI,sBAAsB,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QAC5F,KAAK,MAAM;YACT,OAAO,IAAI,YAAY,EAAE,CAAC;QAC5B;YACE,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAU5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAG5D,IAAI,SAAS,GAA0B,IAAI,CAAC;AAE5C,MAAM,UAAU,iBAAiB,CAAC,QAAwB;IACxD,SAAS,GAAG,QAAQ,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,aAAa;IAC3B,SAAS,GAAG,IAAI,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,MAA0C;IAE1C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,UAAU;YACb,OAAO,IAAI,gBAAgB,CAAC,MAAM,CAAC,KAAK,IAAI,sBAAsB,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QAC5F,KAAK,MAAM;YACT,OAAO,IAAI,YAAY,EAAE,CAAC;QAC5B,KAAK,aAAa;YAChB,OAAO,IAAI,kBAAkB,CAAC;gBAC5B,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,gCAAgC;gBACrE,eAAe,EAAE,MAAM,CAAC,eAAe;gBACvC,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;gBAC7C,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;gBACjD,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,eAAe,EAAE,MAAM,CAAC,eAAe;aACxC,CAAC,CAAC;QACL;YACE,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw-cloud/agent-controller",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {