@openclaw-cloud/agent-controller 0.12.0 → 0.14.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 (47) hide show
  1. package/dist/handlers/board-handler.d.ts +1 -1
  2. package/dist/handlers/board-handler.js +54 -18
  3. package/dist/handlers/board-handler.js.map +1 -1
  4. package/dist/handlers/chat.js +4 -4
  5. package/dist/handlers/chat.js.map +1 -1
  6. package/dist/handlers/deploy.js +46 -42
  7. package/dist/handlers/deploy.js.map +1 -1
  8. package/dist/handlers/update-auth-profiles.js +10 -4
  9. package/dist/handlers/update-auth-profiles.js.map +1 -1
  10. package/dist/heartbeat.js +12 -15
  11. package/dist/heartbeat.js.map +1 -1
  12. package/dist/index.js +25 -10
  13. package/dist/index.js.map +1 -1
  14. package/dist/openclaw/gateway-adapter.d.ts +5 -23
  15. package/dist/openclaw/gateway-adapter.js +3 -178
  16. package/dist/openclaw/gateway-adapter.js.map +1 -1
  17. package/dist/openclaw/index.d.ts +10 -9
  18. package/dist/openclaw/index.js +19 -61
  19. package/dist/openclaw/index.js.map +1 -1
  20. package/dist/openclaw/types.d.ts +5 -37
  21. package/dist/providers/chat-types.d.ts +39 -0
  22. package/dist/providers/chat-types.js +6 -0
  23. package/dist/providers/chat-types.js.map +1 -0
  24. package/dist/providers/index.d.ts +11 -0
  25. package/dist/providers/index.js +26 -0
  26. package/dist/providers/index.js.map +1 -0
  27. package/dist/providers/mock/index.d.ts +25 -0
  28. package/dist/providers/mock/index.js +40 -0
  29. package/dist/providers/mock/index.js.map +1 -0
  30. package/dist/providers/openclaw/gateway-adapter.d.ts +24 -0
  31. package/dist/providers/openclaw/gateway-adapter.js +181 -0
  32. package/dist/providers/openclaw/gateway-adapter.js.map +1 -0
  33. package/dist/providers/openclaw/gateway-client.d.ts +21 -0
  34. package/dist/providers/openclaw/gateway-client.js +138 -0
  35. package/dist/providers/openclaw/gateway-client.js.map +1 -0
  36. package/dist/providers/openclaw/index.d.ts +21 -0
  37. package/dist/providers/openclaw/index.js +120 -0
  38. package/dist/providers/openclaw/index.js.map +1 -0
  39. package/dist/providers/types.d.ts +38 -0
  40. package/dist/providers/types.js +2 -0
  41. package/dist/providers/types.js.map +1 -0
  42. package/dist/skills/board-tools/scripts/board-result.sh +5 -1
  43. package/dist/types.d.ts +6 -0
  44. package/dist/utils/gateway-restart.d.ts +7 -4
  45. package/dist/utils/gateway-restart.js +15 -19
  46. package/dist/utils/gateway-restart.js.map +1 -1
  47. package/package.json +1 -1
@@ -0,0 +1,181 @@
1
+ import { GatewayClient } from './gateway-client.js';
2
+ import { toErrorMessage } from '../../utils/response.js';
3
+ const STREAM_TTL = 300_000; // 5 min
4
+ /**
5
+ * Extract plain text from gateway message payload.
6
+ * Supports:
7
+ * - string: "hello"
8
+ * - content array: [{type:"text", text:"hello"}]
9
+ * - message object: {role, content: [{type:"text", text:"hello"}], timestamp}
10
+ */
11
+ function extractText(msg) {
12
+ if (typeof msg === 'string')
13
+ return msg;
14
+ if (Array.isArray(msg)) {
15
+ return msg
16
+ .filter((c) => c.type === 'text')
17
+ .map((c) => c.text)
18
+ .join('');
19
+ }
20
+ if (typeof msg === 'object' && msg !== null) {
21
+ const obj = msg;
22
+ // {role, content: [...], timestamp} format
23
+ if (Array.isArray(obj['content'])) {
24
+ return obj['content']
25
+ .filter((c) => c.type === 'text')
26
+ .map((c) => c.text)
27
+ .join('');
28
+ }
29
+ // {text: "..."} shorthand
30
+ if (typeof obj['text'] === 'string')
31
+ return obj['text'];
32
+ }
33
+ return '';
34
+ }
35
+ export class OpenclawGatewayAdapter {
36
+ client;
37
+ streamCallbacks = new Map();
38
+ constructor(url, token) {
39
+ this.client = new GatewayClient(url, token);
40
+ this.client.setEventHandler(this.handleEvent.bind(this));
41
+ }
42
+ async connect() {
43
+ await this.client.connect();
44
+ }
45
+ disconnect() {
46
+ // Notify all in-flight streams before closing
47
+ for (const [, cb] of this.streamCallbacks) {
48
+ clearTimeout(cb.timer);
49
+ cb.onError?.('Connection closed');
50
+ }
51
+ this.streamCallbacks.clear();
52
+ this.client.disconnect();
53
+ }
54
+ isConnected() {
55
+ return this.client.isConnected();
56
+ }
57
+ async listSessions() {
58
+ const result = await this.client.request('sessions.list', {});
59
+ return (result?.sessions ?? []).map((s) => ({
60
+ key: s.key,
61
+ sessionId: s.sessionId ?? '',
62
+ kind: s.kind ?? 'direct',
63
+ label: s.key.split(':').pop() ?? s.key,
64
+ updatedAt: s.updatedAt ?? 0,
65
+ model: s.model,
66
+ }));
67
+ }
68
+ async getHistory(sessionKey, limit = 200) {
69
+ const result = await this.client.request('chat.history', { sessionKey, limit });
70
+ const messages = (result?.messages ?? [])
71
+ .filter((m) => m.role === 'user' || m.role === 'assistant')
72
+ .map((m) => {
73
+ const content = Array.isArray(m.content)
74
+ ? m.content.filter((c) => c.type === 'text').map((c) => c.text).join('')
75
+ : String(m.content ?? '');
76
+ return {
77
+ role: m.role,
78
+ content,
79
+ timestamp: typeof m.timestamp === 'number'
80
+ ? new Date(m.timestamp).toISOString()
81
+ : m.timestamp ?? new Date().toISOString(),
82
+ };
83
+ });
84
+ // Deduplicate consecutive assistant messages with same content
85
+ return messages.filter((msg, i) => {
86
+ if (i === 0)
87
+ return true;
88
+ const prev = messages[i - 1];
89
+ return !(msg.role === 'assistant' && prev.role === 'assistant' && msg.content === prev.content);
90
+ });
91
+ }
92
+ async sendMessage(params) {
93
+ const key = params.idempotencyKey;
94
+ // TTL timer: if no final/error event arrives within 5 min, clean up and error
95
+ const timer = setTimeout(() => {
96
+ const cb = this.streamCallbacks.get(key);
97
+ if (cb) {
98
+ this.streamCallbacks.delete(key);
99
+ cb.onError?.('Stream timeout');
100
+ }
101
+ }, STREAM_TTL);
102
+ // Register stream callbacks BEFORE sending
103
+ this.streamCallbacks.set(key, {
104
+ onDelta: params.onDelta,
105
+ onDone: params.onDone,
106
+ onError: params.onError,
107
+ lastText: '',
108
+ timer,
109
+ });
110
+ const payload = {
111
+ sessionKey: params.sessionKey,
112
+ message: params.text,
113
+ deliver: false,
114
+ idempotencyKey: key,
115
+ };
116
+ if (params.attachments?.length) {
117
+ payload['attachments'] = params.attachments;
118
+ }
119
+ try {
120
+ await this.client.request('chat.send', payload);
121
+ // Request accepted — response comes via events
122
+ }
123
+ catch (err) {
124
+ const cb = this.streamCallbacks.get(key);
125
+ if (cb) {
126
+ clearTimeout(cb.timer);
127
+ this.streamCallbacks.delete(key);
128
+ }
129
+ params.onError?.(toErrorMessage(err));
130
+ }
131
+ }
132
+ async abort(sessionKey, runId) {
133
+ await this.client.request('chat.abort', { sessionKey, runId }).catch(() => { });
134
+ }
135
+ deleteStream(runId) {
136
+ const cb = this.streamCallbacks.get(runId);
137
+ if (cb) {
138
+ clearTimeout(cb.timer);
139
+ this.streamCallbacks.delete(runId);
140
+ }
141
+ return cb;
142
+ }
143
+ handleEvent(event) {
144
+ console.log('[chat] Gateway event:', event.event, JSON.stringify(event.payload).slice(0, 500));
145
+ const data = event.payload;
146
+ if (!data || !data['sessionKey'])
147
+ return;
148
+ // Stream events have runId matching idempotencyKey
149
+ const runId = data['runId'];
150
+ const cb = runId ? this.streamCallbacks.get(runId) : null;
151
+ if (!cb)
152
+ return;
153
+ if (data['state'] === 'delta' && data['message'] != null) {
154
+ const msg = data['message'];
155
+ const text = extractText(msg);
156
+ console.log('[chat] delta extracted:', text.slice(0, 100));
157
+ cb.lastText = text;
158
+ cb.onDelta?.(text);
159
+ }
160
+ else if (data['state'] === 'final') {
161
+ const finalMsg = data['message'];
162
+ const finalText = finalMsg ? extractText(finalMsg) : cb.lastText;
163
+ console.log('[chat] final text:', finalText.slice(0, 100), 'lastText:', cb.lastText.slice(0, 100));
164
+ this.deleteStream(runId);
165
+ cb.onDone?.(finalText || cb.lastText);
166
+ }
167
+ else if (data['state'] === 'aborted') {
168
+ this.deleteStream(runId);
169
+ cb.onDone?.(cb.lastText); // still send whatever we have
170
+ }
171
+ else if (data['state'] === 'error') {
172
+ this.deleteStream(runId);
173
+ const errData = data['error'];
174
+ const errMsg = typeof errData === 'string'
175
+ ? errData
176
+ : errData?.message ?? 'Unknown error';
177
+ cb.onError?.(errMsg);
178
+ }
179
+ }
180
+ }
181
+ //# sourceMappingURL=gateway-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-adapter.js","sourceRoot":"","sources":["../../../src/providers/openclaw/gateway-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export type EventHandler = (event: {
2
+ event: string;
3
+ payload: unknown;
4
+ seq?: number;
5
+ }) => void;
6
+ export declare class GatewayClient {
7
+ private ws;
8
+ private pending;
9
+ private onEvent;
10
+ private connected;
11
+ private token;
12
+ private url;
13
+ constructor(url: string, token: string);
14
+ setEventHandler(handler: EventHandler): void;
15
+ connect(): Promise<void>;
16
+ disconnect(): void;
17
+ isConnected(): boolean;
18
+ request(method: string, params: unknown): Promise<unknown>;
19
+ private handleMessage;
20
+ private flushPending;
21
+ }
@@ -0,0 +1,138 @@
1
+ import WebSocket from 'ws';
2
+ import { randomUUID } from 'crypto';
3
+ export class GatewayClient {
4
+ ws = null;
5
+ pending = new Map();
6
+ onEvent = null;
7
+ connected = false;
8
+ token;
9
+ url;
10
+ constructor(url, token) {
11
+ this.url = url;
12
+ this.token = token;
13
+ }
14
+ setEventHandler(handler) {
15
+ this.onEvent = handler;
16
+ }
17
+ connect() {
18
+ // RACE-5: guard against double-call before the first handshake completes
19
+ if (this.ws !== null) {
20
+ return Promise.reject(new Error('Already connecting or connected'));
21
+ }
22
+ return new Promise((resolve, reject) => {
23
+ this.ws = new WebSocket(this.url);
24
+ this.ws.on('open', () => {
25
+ // Wait for connect.challenge event, then authenticate
26
+ });
27
+ this.ws.on('message', (raw) => {
28
+ try {
29
+ const msg = JSON.parse(raw.toString());
30
+ this.handleMessage(msg);
31
+ }
32
+ catch { }
33
+ });
34
+ this.ws.on('error', (e) => {
35
+ if (!this.connected)
36
+ reject(e);
37
+ });
38
+ this.ws.on('close', () => {
39
+ this.connected = false;
40
+ this.flushPending(new Error('Connection closed'));
41
+ });
42
+ // LEAK-3: store and clear the connect timeout after successful auth
43
+ const connectTimer = setTimeout(() => {
44
+ if (!this.connected)
45
+ reject(new Error('Connect timeout'));
46
+ }, 10_000);
47
+ // Wait for connect.challenge → authenticate → resolve
48
+ const origHandler = this.onEvent;
49
+ this.onEvent = async (ev) => {
50
+ if (ev.event === 'connect.challenge') {
51
+ try {
52
+ await this.request('connect', {
53
+ auth: { token: this.token },
54
+ scopes: ['operator.admin'],
55
+ caps: [],
56
+ client: {
57
+ id: 'gateway-client',
58
+ displayName: 'Agent Controller',
59
+ version: '1',
60
+ platform: process.platform,
61
+ mode: 'backend',
62
+ },
63
+ minProtocol: 3,
64
+ maxProtocol: 3,
65
+ });
66
+ this.connected = true;
67
+ clearTimeout(connectTimer);
68
+ this.onEvent = origHandler;
69
+ resolve();
70
+ }
71
+ catch (e) {
72
+ clearTimeout(connectTimer);
73
+ reject(e);
74
+ }
75
+ }
76
+ };
77
+ });
78
+ }
79
+ disconnect() {
80
+ this.ws?.close();
81
+ this.ws = null;
82
+ this.connected = false;
83
+ this.flushPending(new Error('Disconnected'));
84
+ }
85
+ isConnected() {
86
+ return this.connected && this.ws?.readyState === WebSocket.OPEN;
87
+ }
88
+ request(method, params) {
89
+ return new Promise((resolve, reject) => {
90
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
91
+ return reject(new Error('Not connected'));
92
+ }
93
+ const id = randomUUID();
94
+ // LEAK-2: store the per-request timeout so it can be cleared when the request resolves
95
+ const timer = setTimeout(() => {
96
+ if (this.pending.has(id)) {
97
+ this.pending.delete(id);
98
+ reject(new Error(`Request timeout: ${method}`));
99
+ }
100
+ }, 120_000);
101
+ this.pending.set(id, {
102
+ resolve: (payload) => { clearTimeout(timer); resolve(payload); },
103
+ reject: (err) => { clearTimeout(timer); reject(err); },
104
+ });
105
+ this.ws.send(JSON.stringify({ type: 'req', id, method, params }));
106
+ });
107
+ }
108
+ handleMessage(msg) {
109
+ if (typeof msg !== 'object' || msg === null)
110
+ return;
111
+ const m = msg;
112
+ if (m['type'] === 'event') {
113
+ this.onEvent?.(m);
114
+ return;
115
+ }
116
+ if (m['type'] === 'res') {
117
+ const id = m['id'];
118
+ const req = this.pending.get(id);
119
+ if (!req)
120
+ return;
121
+ this.pending.delete(id);
122
+ if (m['ok']) {
123
+ req.resolve(m['payload']);
124
+ }
125
+ else {
126
+ const errPayload = m['error'];
127
+ req.reject(new Error(errPayload?.message ?? 'Request failed'));
128
+ }
129
+ }
130
+ }
131
+ flushPending(err) {
132
+ for (const [, req] of this.pending) {
133
+ req.reject(err);
134
+ }
135
+ this.pending.clear();
136
+ }
137
+ }
138
+ //# sourceMappingURL=gateway-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-client.js","sourceRoot":"","sources":["../../../src/providers/openclaw/gateway-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { IAgentProvider, AgentHealthStatus, SendMessageParams } from '../types.js';
2
+ import type { ChatSession, ChatMessage } from '../chat-types.js';
3
+ export { OpenclawGatewayAdapter } from './gateway-adapter.js';
4
+ export declare class OpenclawProvider implements IAgentProvider {
5
+ readonly name = "openclaw";
6
+ private adapter;
7
+ private wsUrl;
8
+ private wsToken;
9
+ private _connecting;
10
+ constructor(wsUrl: string, wsToken: string);
11
+ connect(): Promise<void>;
12
+ disconnect(): void;
13
+ isConnected(): boolean;
14
+ sendMessage(params: SendMessageParams): Promise<void>;
15
+ listSessions(): Promise<ChatSession[]>;
16
+ getHistory(sessionKey: string, limit?: number): Promise<ChatMessage[]>;
17
+ abort(sessionKey: string, runId?: string): Promise<void>;
18
+ healthCheck(): Promise<AgentHealthStatus>;
19
+ restart(): Promise<void>;
20
+ install(currentVersion?: string): Promise<void>;
21
+ }
@@ -0,0 +1,120 @@
1
+ import { OpenclawGatewayAdapter } from './gateway-adapter.js';
2
+ import { execAsync } from '../../utils/exec.js';
3
+ export { OpenclawGatewayAdapter } from './gateway-adapter.js';
4
+ export class OpenclawProvider {
5
+ name = 'openclaw';
6
+ adapter = null;
7
+ wsUrl;
8
+ wsToken;
9
+ _connecting = null;
10
+ constructor(wsUrl, wsToken) {
11
+ this.wsUrl = wsUrl;
12
+ this.wsToken = wsToken;
13
+ }
14
+ async connect() {
15
+ if (this.adapter?.isConnected())
16
+ return;
17
+ // Guard against concurrent connect calls
18
+ if (this._connecting) {
19
+ await this._connecting;
20
+ return;
21
+ }
22
+ this._connecting = (async () => {
23
+ const maxRetries = 5;
24
+ const baseDelayMs = 2000;
25
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
26
+ try {
27
+ this.adapter = new OpenclawGatewayAdapter(this.wsUrl, this.wsToken);
28
+ await this.adapter.connect();
29
+ console.log(`OpenClaw Gateway WS connected (attempt ${attempt})`);
30
+ return;
31
+ }
32
+ catch (e) {
33
+ const msg = e instanceof Error ? e.message : String(e);
34
+ console.warn(`Chat provider connect failed (attempt ${attempt}/${maxRetries}): ${msg}`);
35
+ this.adapter?.disconnect();
36
+ this.adapter = null;
37
+ if (attempt < maxRetries) {
38
+ await new Promise((r) => setTimeout(r, baseDelayMs * Math.min(attempt, 5)));
39
+ }
40
+ }
41
+ }
42
+ throw new Error('OpenclawProvider: connect exhausted');
43
+ })();
44
+ try {
45
+ await this._connecting;
46
+ }
47
+ finally {
48
+ this._connecting = null;
49
+ }
50
+ }
51
+ disconnect() {
52
+ this.adapter?.disconnect();
53
+ this.adapter = null;
54
+ this._connecting = null;
55
+ }
56
+ isConnected() {
57
+ return this.adapter?.isConnected() ?? false;
58
+ }
59
+ // === Chat — delegate to gateway adapter ===
60
+ async sendMessage(params) {
61
+ if (!this.adapter) {
62
+ // Lazy connect
63
+ await this.connect();
64
+ }
65
+ if (!this.adapter)
66
+ throw new Error('Provider not connected');
67
+ await this.adapter.sendMessage(params);
68
+ }
69
+ async listSessions() {
70
+ if (!this.adapter)
71
+ return [];
72
+ return this.adapter.listSessions();
73
+ }
74
+ async getHistory(sessionKey, limit) {
75
+ if (!this.adapter)
76
+ return [];
77
+ return this.adapter.getHistory(sessionKey, limit);
78
+ }
79
+ async abort(sessionKey, runId) {
80
+ await this.adapter?.abort(sessionKey, runId);
81
+ }
82
+ // === Infrastructure ===
83
+ async healthCheck() {
84
+ try {
85
+ const output = await execAsync('openclaw health --json', 5000);
86
+ const parsed = JSON.parse(output);
87
+ const running = parsed.ok === true;
88
+ return { ok: running, rpcOk: running };
89
+ }
90
+ catch {
91
+ return { ok: false, rpcOk: false };
92
+ }
93
+ }
94
+ async restart() {
95
+ const { exec } = await import('node:child_process');
96
+ return new Promise((resolve) => {
97
+ exec('openclaw gateway restart', { timeout: 30_000 }, (error) => {
98
+ if (error)
99
+ console.error('Gateway restart failed:', error.message);
100
+ else
101
+ console.log('Gateway restarted');
102
+ resolve(); // always resolve — caller decides how to handle
103
+ });
104
+ });
105
+ }
106
+ async install(currentVersion) {
107
+ const { exec } = await import('node:child_process');
108
+ return new Promise((resolve, reject) => {
109
+ exec('npm i -g openclaw', { timeout: 120_000 }, (error, stdout, stderr) => {
110
+ if (error) {
111
+ reject(Object.assign(error, { stdout: stdout.toString(), stderr: stderr.toString() }));
112
+ }
113
+ else {
114
+ resolve();
115
+ }
116
+ });
117
+ });
118
+ }
119
+ }
120
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/providers/openclaw/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { ChatSession, ChatMessage, ChatAttachment } from './chat-types.js';
2
+ export type { ChatSession, ChatMessage, ChatAttachment };
3
+ export interface AgentHealthStatus {
4
+ ok: boolean;
5
+ rpcOk: boolean;
6
+ }
7
+ export interface SendMessageParams {
8
+ sessionKey: string;
9
+ text: string;
10
+ idempotencyKey: string;
11
+ attachments?: ChatAttachment[];
12
+ onDelta?: (accumulatedText: string) => void;
13
+ onDone?: (finalText: string) => void;
14
+ onError?: (error: string) => void;
15
+ }
16
+ export interface IAgentProvider {
17
+ readonly name: string;
18
+ /** Initialize/connect the provider */
19
+ connect(): Promise<void>;
20
+ /** Disconnect/cleanup */
21
+ disconnect(): void;
22
+ /** Is provider connected and ready? */
23
+ isConnected(): boolean;
24
+ /** Send a message to the agent (task prompt, chat message, etc.) */
25
+ sendMessage(params: SendMessageParams): Promise<void>;
26
+ /** List active chat sessions */
27
+ listSessions(): Promise<ChatSession[]>;
28
+ /** Get chat history for a session */
29
+ getHistory(sessionKey: string, limit?: number): Promise<ChatMessage[]>;
30
+ /** Abort an in-flight message */
31
+ abort(sessionKey: string, runId?: string): Promise<void>;
32
+ /** Check if the agent runtime is healthy */
33
+ healthCheck(): Promise<AgentHealthStatus>;
34
+ /** Restart the agent runtime */
35
+ restart(): Promise<void>;
36
+ /** Install/update the agent runtime */
37
+ install(currentVersion?: string): Promise<void>;
38
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/providers/types.ts"],"names":[],"mappings":""}
@@ -17,8 +17,12 @@ case "$STATUS" in
17
17
  ERROR_MSG="${1:-Agent reported failure}"
18
18
  BODY="{\"status\":\"failed\",\"error\":\"$ERROR_MSG\"}"
19
19
  ;;
20
+ needs-input|needs_input|blocked)
21
+ INPUT_MSG="${1:-Agent needs clarification}"
22
+ BODY="{\"status\":\"needs_input\",\"message\":\"$INPUT_MSG\"}"
23
+ ;;
20
24
  *)
21
- echo "Usage: board-result <complete|fail> [error message]" >&2
25
+ echo "Usage: board-result <complete|fail|needs-input> [message]" >&2
22
26
  exit 1
23
27
  ;;
24
28
  esac
package/dist/types.d.ts CHANGED
@@ -88,8 +88,14 @@ export interface CardDetail {
88
88
  assignedAgentId?: string | null;
89
89
  };
90
90
  }
91
+ export interface MockAction {
92
+ type: 'wait' | 'artifact' | 'comment' | 'result' | 'move';
93
+ ms?: number;
94
+ body?: Record<string, unknown>;
95
+ }
91
96
  export interface TaskInfo {
92
97
  cardProcessingId: string;
93
98
  prompt: string;
94
99
  workflowSteps: Array<Record<string, unknown>>;
100
+ mockActions?: MockAction[];
95
101
  }
@@ -3,8 +3,11 @@ export interface GatewayRestartResult {
3
3
  stderr: string;
4
4
  }
5
5
  /**
6
- * Runs `openclaw gateway restart` with a 30s timeout.
7
- * Resolves with { stdout, stderr } on success.
8
- * Rejects with an Error that also has stdout/stderr properties on failure.
6
+ * Restart the gateway via the configured agent provider.
7
+ * Returns { stdout: '', stderr: '' } for interface compatibility.
9
8
  */
10
- export declare function execGatewayRestart(): Promise<GatewayRestartResult>;
9
+ export declare function restartGateway(): Promise<GatewayRestartResult>;
10
+ /**
11
+ * @deprecated Use restartGateway() instead.
12
+ */
13
+ export declare const execGatewayRestart: typeof restartGateway;
@@ -1,23 +1,19 @@
1
- import { exec } from 'node:child_process';
1
+ import { getProvider } from '../providers/index.js';
2
2
  /**
3
- * Runs `openclaw gateway restart` with a 30s timeout.
4
- * Resolves with { stdout, stderr } on success.
5
- * Rejects with an Error that also has stdout/stderr properties on failure.
3
+ * Restart the gateway via the configured agent provider.
4
+ * Returns { stdout: '', stderr: '' } for interface compatibility.
6
5
  */
7
- export function execGatewayRestart() {
8
- return new Promise((resolve, reject) => {
9
- exec('openclaw gateway restart', { timeout: 30_000 }, (error, stdout, stderr) => {
10
- const result = {
11
- stdout: stdout.toString(),
12
- stderr: stderr.toString(),
13
- };
14
- if (error) {
15
- reject(Object.assign(error, result));
16
- }
17
- else {
18
- resolve(result);
19
- }
20
- });
21
- });
6
+ export async function restartGateway() {
7
+ const provider = getProvider();
8
+ if (!provider) {
9
+ console.warn('No provider configured, cannot restart gateway');
10
+ return { stdout: '', stderr: '' };
11
+ }
12
+ await provider.restart();
13
+ return { stdout: '', stderr: '' };
22
14
  }
15
+ /**
16
+ * @deprecated Use restartGateway() instead.
17
+ */
18
+ export const execGatewayRestart = restartGateway;
23
19
  //# sourceMappingURL=gateway-restart.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"gateway-restart.js","sourceRoot":"","sources":["../../src/utils/gateway-restart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAO1C;;;;GAIG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,CAAC,0BAA0B,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YAC9E,MAAM,MAAM,GAAyB;gBACnC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE;gBACzB,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE;aAC1B,CAAC;YACF,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;YACvC,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,MAAM,CAAC,CAAC;YAClB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"gateway-restart.js","sourceRoot":"","sources":["../../src/utils/gateway-restart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAOpD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAC/D,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACpC,CAAC;IACD,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;IACzB,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,cAAc,CAAC"}