@openclaw-cloud/agent-controller 0.19.0-beta.2 → 0.19.0-beta.20
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/commands/install-deps.js +1 -7
- package/dist/commands/install-deps.js.map +1 -1
- package/dist/commands/self-update.js +29 -18
- package/dist/commands/self-update.js.map +1 -1
- package/dist/config-file.js +1 -1
- package/dist/config-file.js.map +1 -1
- package/dist/connection.d.ts +3 -0
- package/dist/connection.js +21 -7
- package/dist/connection.js.map +1 -1
- package/dist/handlers/backup.js +2 -0
- package/dist/handlers/backup.js.map +1 -1
- package/dist/handlers/file-delete.js +2 -0
- package/dist/handlers/file-delete.js.map +1 -1
- package/dist/handlers/file-write.js +2 -0
- package/dist/handlers/file-write.js.map +1 -1
- package/dist/handlers/package-install.js +2 -0
- package/dist/handlers/package-install.js.map +1 -1
- package/dist/handlers/restart.js +3 -1
- package/dist/handlers/restart.js.map +1 -1
- package/dist/handlers/self-update.js +2 -0
- package/dist/handlers/self-update.js.map +1 -1
- package/dist/handlers/update-config.d.ts +3 -0
- package/dist/handlers/update-config.js +22 -0
- package/dist/handlers/update-config.js.map +1 -0
- package/dist/handlers/update-skills.js +2 -0
- package/dist/handlers/update-skills.js.map +1 -1
- package/dist/heartbeat.js +62 -2
- package/dist/heartbeat.js.map +1 -1
- package/dist/index.js +17 -16
- package/dist/index.js.map +1 -1
- package/dist/lockfile.js +12 -3
- package/dist/lockfile.js.map +1 -1
- package/dist/openclaw/gateway-client.d.ts +5 -0
- package/dist/openclaw/gateway-client.js +31 -1
- package/dist/openclaw/gateway-client.js.map +1 -1
- package/dist/openclaw/index.d.ts +1 -1
- package/dist/openclaw/types.d.ts +1 -1
- package/dist/providers/chat-types.d.ts +19 -2
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/openclaw/device-identity.d.ts +20 -0
- package/dist/providers/openclaw/device-identity.js +76 -0
- package/dist/providers/openclaw/device-identity.js.map +1 -0
- package/dist/providers/openclaw/gateway-adapter.d.ts +7 -1
- package/dist/providers/openclaw/gateway-adapter.js +140 -8
- package/dist/providers/openclaw/gateway-adapter.js.map +1 -1
- package/dist/providers/openclaw/gateway-client.d.ts +5 -0
- package/dist/providers/openclaw/gateway-client.js +59 -2
- package/dist/providers/openclaw/gateway-client.js.map +1 -1
- package/dist/providers/types.d.ts +2 -2
- package/dist/types.d.ts +1 -1
- package/dist/utils/apply-config.d.ts +9 -0
- package/dist/utils/apply-config.js +62 -0
- package/dist/utils/apply-config.js.map +1 -0
- package/dist/utils/claude-env.js +35 -17
- package/dist/utils/claude-env.js.map +1 -1
- package/dist/utils/log-collector.d.ts +23 -0
- package/dist/utils/log-collector.js +56 -0
- package/dist/utils/log-collector.js.map +1 -0
- package/dist/utils/release-channel.d.ts +1 -1
- package/dist/utils/release-channel.js +1 -1
- package/dist/utils/release-channel.js.map +1 -1
- package/package.json +1 -1
- package/dist/handlers/config.d.ts +0 -2
- package/dist/handlers/config.js +0 -50
- package/dist/handlers/config.js.map +0 -1
- package/dist/handlers/update-auth-profiles.d.ts +0 -2
- package/dist/handlers/update-auth-profiles.js +0 -67
- package/dist/handlers/update-auth-profiles.js.map +0 -1
- package/dist/handlers/update-env.d.ts +0 -2
- package/dist/handlers/update-env.js +0 -54
- package/dist/handlers/update-env.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
import { dirname, join } from 'node:path';
|
|
4
|
-
import {
|
|
5
|
-
import { homedir } from 'node:os';
|
|
6
|
-
import { createConnection, subscribeToChannel } from './connection.js';
|
|
4
|
+
import { createConnection, subscribeToChannel, logCollector } from './connection.js';
|
|
7
5
|
import { startHeartbeat } from './heartbeat.js';
|
|
8
6
|
import { createAgentApi } from './api.js';
|
|
9
7
|
import { BoardHandler } from './handlers/board-handler.js';
|
|
@@ -11,29 +9,31 @@ import { configureProvider, createProvider, getProvider } from './providers/inde
|
|
|
11
9
|
import { DEBUG } from './debug.js';
|
|
12
10
|
import { requireEnv, getBackendUrl } from './utils/env.js';
|
|
13
11
|
import { createLockFile } from './lockfile.js';
|
|
12
|
+
import { applyBootstrapConfig } from './utils/apply-config.js';
|
|
14
13
|
const _require = createRequire(import.meta.url);
|
|
15
14
|
const { version: CONTROLLER_VERSION } = _require(join(dirname(fileURLToPath(import.meta.url)), '../package.json'));
|
|
16
|
-
/**
|
|
17
|
-
function
|
|
18
|
-
const
|
|
19
|
-
|
|
15
|
+
/** On startup, fetch latest config from bootstrap API and apply */
|
|
16
|
+
async function refreshConfigFromBootstrap() {
|
|
17
|
+
const backendUrl = getBackendUrl();
|
|
18
|
+
const agentToken = process.env.AGENT_TOKEN;
|
|
19
|
+
const agentId = process.env.AGENT_ID;
|
|
20
|
+
if (!backendUrl || !agentToken || !agentId)
|
|
20
21
|
return;
|
|
21
|
-
const agentDir = join(process.env.OPENCLAW_STATE_DIR?.trim() || join(homedir(), '.openclaw'), 'agents', 'main', 'agent');
|
|
22
|
-
const filePath = join(agentDir, 'auth-profiles.json');
|
|
23
|
-
if (existsSync(filePath))
|
|
24
|
-
return; // already written (restart)
|
|
25
22
|
try {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
const api = createAgentApi(backendUrl, agentToken);
|
|
24
|
+
const data = await api.agentBootstrap(agentId);
|
|
25
|
+
await applyBootstrapConfig(data);
|
|
26
|
+
console.log('[startup] Config refreshed from bootstrap API');
|
|
29
27
|
}
|
|
30
28
|
catch (err) {
|
|
31
|
-
console.error('[
|
|
29
|
+
console.error('[startup] Failed to refresh config from bootstrap:', err instanceof Error ? err.message : err);
|
|
32
30
|
}
|
|
33
31
|
}
|
|
34
32
|
export function main() {
|
|
35
33
|
createLockFile();
|
|
36
|
-
|
|
34
|
+
refreshConfigFromBootstrap().catch((err) => {
|
|
35
|
+
console.error('[startup] refreshConfigFromBootstrap failed:', err);
|
|
36
|
+
});
|
|
37
37
|
const url = requireEnv('CENTRIFUGO_URL');
|
|
38
38
|
const token = requireEnv('AGENT_TOKEN');
|
|
39
39
|
const agentId = requireEnv('AGENT_ID');
|
|
@@ -108,6 +108,7 @@ export function main() {
|
|
|
108
108
|
heartbeatHandle.stop();
|
|
109
109
|
boardSub?.unsubscribe();
|
|
110
110
|
getProvider()?.disconnect();
|
|
111
|
+
logCollector?.shutdown().catch(() => { });
|
|
111
112
|
client.disconnect();
|
|
112
113
|
// SHUT-4: In-flight commands that are still executing when SIGTERM arrives will not
|
|
113
114
|
// have their responses delivered. This is acceptable — the backend times out and
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/lockfile.js
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
|
|
3
|
+
import os from 'node:os';
|
|
4
4
|
const LOCK_FILE = 'agent-controller.lock';
|
|
5
|
+
function getLockDir() {
|
|
6
|
+
// VM/K8s: /opt/openclaw-cloud/agent-controller
|
|
7
|
+
// Standalone: ~/.openclaw/agent-controller
|
|
8
|
+
if (fs.existsSync('/opt/openclaw-cloud/agent-controller')) {
|
|
9
|
+
return '/opt/openclaw-cloud/agent-controller';
|
|
10
|
+
}
|
|
11
|
+
return path.join(os.homedir(), '.openclaw', 'agent-controller');
|
|
12
|
+
}
|
|
5
13
|
function getLockPath() {
|
|
6
|
-
return path.join(
|
|
14
|
+
return path.join(getLockDir(), LOCK_FILE);
|
|
7
15
|
}
|
|
8
16
|
/** Create lock file on startup */
|
|
9
17
|
export function createLockFile() {
|
|
10
18
|
try {
|
|
11
|
-
|
|
19
|
+
const lockDir = getLockDir();
|
|
20
|
+
fs.mkdirSync(lockDir, { recursive: true });
|
|
12
21
|
fs.writeFileSync(getLockPath(), String(process.pid), { mode: 0o644 });
|
|
13
22
|
console.log(`[lock] Created lock file: ${getLockPath()}`);
|
|
14
23
|
}
|
package/dist/lockfile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,SAAS,GAAG,uBAAuB,CAAC;AAE1C,SAAS,UAAU;IACjB,+CAA+C;IAC/C,2CAA2C;IAC3C,IAAI,EAAE,CAAC,UAAU,CAAC,sCAAsC,CAAC,EAAE,CAAC;QAC1D,OAAO,sCAAsC,CAAC;IAChD,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,kBAAkB,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,WAAW;IAClB,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,CAAC,CAAC;AAC5C,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;QAC7B,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,6BAA6B,WAAW,EAAE,EAAE,CAAC,CAAC;IAC5D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAChG,CAAC;AACH,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,6BAA6B,WAAW,EAAE,EAAE,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,8BAA8B;IAChC,CAAC;AACH,CAAC;AAED,gCAAgC;AAChC,MAAM,UAAU,iBAAiB;IAC/B,OAAO,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -10,10 +10,15 @@ export declare class GatewayClient {
|
|
|
10
10
|
private connected;
|
|
11
11
|
private token;
|
|
12
12
|
private url;
|
|
13
|
+
private reconnecting;
|
|
14
|
+
private destroyed;
|
|
15
|
+
private reconnectAttempts;
|
|
16
|
+
private static MAX_RECONNECT_DELAY;
|
|
13
17
|
constructor(url: string, token: string);
|
|
14
18
|
setEventHandler(handler: EventHandler): void;
|
|
15
19
|
connect(): Promise<void>;
|
|
16
20
|
disconnect(): void;
|
|
21
|
+
private scheduleReconnect;
|
|
17
22
|
isConnected(): boolean;
|
|
18
23
|
request(method: string, params: unknown): Promise<unknown>;
|
|
19
24
|
private handleMessage;
|
|
@@ -7,6 +7,10 @@ export class GatewayClient {
|
|
|
7
7
|
connected = false;
|
|
8
8
|
token;
|
|
9
9
|
url;
|
|
10
|
+
reconnecting = false;
|
|
11
|
+
destroyed = false;
|
|
12
|
+
reconnectAttempts = 0;
|
|
13
|
+
static MAX_RECONNECT_DELAY = 60_000;
|
|
10
14
|
constructor(url, token) {
|
|
11
15
|
this.url = url;
|
|
12
16
|
this.token = token;
|
|
@@ -16,9 +20,10 @@ export class GatewayClient {
|
|
|
16
20
|
}
|
|
17
21
|
connect() {
|
|
18
22
|
// RACE-5: guard against double-call before the first handshake completes
|
|
19
|
-
if (this.ws !== null) {
|
|
23
|
+
if (this.ws !== null && this.ws.readyState !== WebSocket.CLOSED) {
|
|
20
24
|
return Promise.reject(new Error('Already connecting or connected'));
|
|
21
25
|
}
|
|
26
|
+
this.ws = null;
|
|
22
27
|
return new Promise((resolve, reject) => {
|
|
23
28
|
this.ws = new WebSocket(this.url);
|
|
24
29
|
this.ws.on('open', () => {
|
|
@@ -37,7 +42,9 @@ export class GatewayClient {
|
|
|
37
42
|
});
|
|
38
43
|
this.ws.on('close', () => {
|
|
39
44
|
this.connected = false;
|
|
45
|
+
this.ws = null;
|
|
40
46
|
this.flushPending(new Error('Connection closed'));
|
|
47
|
+
this.scheduleReconnect();
|
|
41
48
|
});
|
|
42
49
|
// LEAK-3: store and clear the connect timeout after successful auth
|
|
43
50
|
const connectTimer = setTimeout(() => {
|
|
@@ -77,11 +84,34 @@ export class GatewayClient {
|
|
|
77
84
|
});
|
|
78
85
|
}
|
|
79
86
|
disconnect() {
|
|
87
|
+
this.destroyed = true;
|
|
80
88
|
this.ws?.close();
|
|
81
89
|
this.ws = null;
|
|
82
90
|
this.connected = false;
|
|
83
91
|
this.flushPending(new Error('Disconnected'));
|
|
84
92
|
}
|
|
93
|
+
scheduleReconnect() {
|
|
94
|
+
if (this.destroyed || this.reconnecting)
|
|
95
|
+
return;
|
|
96
|
+
this.reconnecting = true;
|
|
97
|
+
const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), GatewayClient.MAX_RECONNECT_DELAY);
|
|
98
|
+
this.reconnectAttempts++;
|
|
99
|
+
console.log(`[gateway-client] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})...`);
|
|
100
|
+
setTimeout(async () => {
|
|
101
|
+
this.reconnecting = false;
|
|
102
|
+
if (this.destroyed)
|
|
103
|
+
return;
|
|
104
|
+
try {
|
|
105
|
+
await this.connect();
|
|
106
|
+
this.reconnectAttempts = 0;
|
|
107
|
+
console.log('[gateway-client] Reconnected to gateway');
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
console.error('[gateway-client] Reconnect failed:', err instanceof Error ? err.message : err);
|
|
111
|
+
// on('close') will fire again → scheduleReconnect
|
|
112
|
+
}
|
|
113
|
+
}, delay);
|
|
114
|
+
}
|
|
85
115
|
isConnected() {
|
|
86
116
|
return this.connected && this.ws?.readyState === WebSocket.OPEN;
|
|
87
117
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-client.js","sourceRoot":"","sources":["../../src/openclaw/gateway-client.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,IAAI,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AASpC,MAAM,OAAO,aAAa;IAChB,EAAE,GAAqB,IAAI,CAAC;IAC5B,OAAO,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC5C,OAAO,GAAwB,IAAI,CAAC;IACpC,SAAS,GAAG,KAAK,CAAC;IAClB,KAAK,CAAS;IACd,GAAG,CAAS;
|
|
1
|
+
{"version":3,"file":"gateway-client.js","sourceRoot":"","sources":["../../src/openclaw/gateway-client.ts"],"names":[],"mappings":"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"}
|
package/dist/openclaw/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Kept for backward compatibility.
|
|
4
4
|
*/
|
|
5
5
|
export { OpenclawGatewayAdapter } from '../providers/openclaw/gateway-adapter.js';
|
|
6
|
-
export type { IChatProvider, ChatSession, ChatMessage, ChatAttachment } from '../providers/chat-types.js';
|
|
6
|
+
export type { IChatProvider, ChatSession, ChatMessage, ChatAttachment, ChatContentBlock } from '../providers/chat-types.js';
|
|
7
7
|
import type { IChatProvider } from '../providers/chat-types.js';
|
|
8
8
|
/** @deprecated Use configureProvider() from providers/index.ts */
|
|
9
9
|
export declare function configureChatProvider(url: string, token: string): void;
|
package/dist/openclaw/types.d.ts
CHANGED
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
* @deprecated — moved to src/providers/chat-types.ts
|
|
3
3
|
* This file is kept for backward compatibility.
|
|
4
4
|
*/
|
|
5
|
-
export type { ChatSession, ChatMessage, ChatAttachment, IChatProvider } from '../providers/chat-types.js';
|
|
5
|
+
export type { ChatSession, ChatMessage, ChatAttachment, ChatContentBlock, IChatProvider } from '../providers/chat-types.js';
|
|
@@ -10,9 +10,26 @@ export interface ChatSession {
|
|
|
10
10
|
updatedAt: number;
|
|
11
11
|
model?: string;
|
|
12
12
|
}
|
|
13
|
+
export interface ChatContentBlock {
|
|
14
|
+
type: string;
|
|
15
|
+
text?: string;
|
|
16
|
+
omitted?: boolean;
|
|
17
|
+
bytes?: number;
|
|
18
|
+
media_type?: string;
|
|
19
|
+
source?: {
|
|
20
|
+
type: string;
|
|
21
|
+
media_type: string;
|
|
22
|
+
data: string;
|
|
23
|
+
};
|
|
24
|
+
name?: string;
|
|
25
|
+
id?: string;
|
|
26
|
+
input?: unknown;
|
|
27
|
+
content?: string | ChatContentBlock[];
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
13
30
|
export interface ChatMessage {
|
|
14
|
-
role: 'user' | 'assistant';
|
|
15
|
-
content: string;
|
|
31
|
+
role: 'user' | 'assistant' | 'toolResult';
|
|
32
|
+
content: string | ChatContentBlock[];
|
|
16
33
|
timestamp: string;
|
|
17
34
|
}
|
|
18
35
|
export interface ChatAttachment {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { IAgentProvider } from './types.js';
|
|
2
2
|
export type { IAgentProvider, AgentHealthStatus, SendMessageParams } from './types.js';
|
|
3
|
-
export type { ChatSession, ChatMessage, ChatAttachment, IChatProvider } from './chat-types.js';
|
|
3
|
+
export type { ChatSession, ChatMessage, ChatAttachment, ChatContentBlock, IChatProvider } from './chat-types.js';
|
|
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';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface DeviceIdentity {
|
|
2
|
+
deviceId: string;
|
|
3
|
+
publicKeyPem: string;
|
|
4
|
+
privateKeyPem: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function publicKeyRawBase64Url(publicKeyPem: string): string;
|
|
7
|
+
export declare function signPayload(privateKeyPem: string, payload: string): string;
|
|
8
|
+
export declare function buildDeviceAuthPayloadV3(params: {
|
|
9
|
+
deviceId: string;
|
|
10
|
+
clientId: string;
|
|
11
|
+
clientMode: string;
|
|
12
|
+
role: string;
|
|
13
|
+
scopes: string[];
|
|
14
|
+
signedAtMs: number;
|
|
15
|
+
token: string;
|
|
16
|
+
nonce: string;
|
|
17
|
+
platform: string;
|
|
18
|
+
deviceFamily: string;
|
|
19
|
+
}): string;
|
|
20
|
+
export declare function loadOrCreateDeviceIdentity(): DeviceIdentity;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
const ED25519_SPKI_PREFIX = Buffer.from('302a300506032b6570032100', 'hex');
|
|
6
|
+
function base64UrlEncode(buf) {
|
|
7
|
+
return buf.toString('base64').replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/g, '');
|
|
8
|
+
}
|
|
9
|
+
function derivePublicKeyRaw(publicKeyPem) {
|
|
10
|
+
const key = crypto.createPublicKey(publicKeyPem);
|
|
11
|
+
const spki = key.export({ type: 'spki', format: 'der' });
|
|
12
|
+
if (spki.length === ED25519_SPKI_PREFIX.length + 32 &&
|
|
13
|
+
spki.subarray(0, ED25519_SPKI_PREFIX.length).equals(ED25519_SPKI_PREFIX)) {
|
|
14
|
+
return spki.subarray(ED25519_SPKI_PREFIX.length);
|
|
15
|
+
}
|
|
16
|
+
return spki;
|
|
17
|
+
}
|
|
18
|
+
function fingerprintPublicKey(publicKeyPem) {
|
|
19
|
+
const raw = derivePublicKeyRaw(publicKeyPem);
|
|
20
|
+
return crypto.createHash('sha256').update(raw).digest('hex');
|
|
21
|
+
}
|
|
22
|
+
export function publicKeyRawBase64Url(publicKeyPem) {
|
|
23
|
+
return base64UrlEncode(derivePublicKeyRaw(publicKeyPem));
|
|
24
|
+
}
|
|
25
|
+
export function signPayload(privateKeyPem, payload) {
|
|
26
|
+
const key = crypto.createPrivateKey(privateKeyPem);
|
|
27
|
+
const sig = crypto.sign(null, Buffer.from(payload, 'utf8'), key);
|
|
28
|
+
return base64UrlEncode(sig);
|
|
29
|
+
}
|
|
30
|
+
export function buildDeviceAuthPayloadV3(params) {
|
|
31
|
+
return [
|
|
32
|
+
'v3',
|
|
33
|
+
params.deviceId,
|
|
34
|
+
params.clientId,
|
|
35
|
+
params.clientMode,
|
|
36
|
+
params.role,
|
|
37
|
+
params.scopes.join(','),
|
|
38
|
+
String(params.signedAtMs),
|
|
39
|
+
params.token,
|
|
40
|
+
params.nonce,
|
|
41
|
+
params.platform,
|
|
42
|
+
params.deviceFamily,
|
|
43
|
+
].join('|');
|
|
44
|
+
}
|
|
45
|
+
function getIdentityPath() {
|
|
46
|
+
const stateDir = process.env.OPENCLAW_STATE_DIR?.trim() || path.join(os.homedir(), '.openclaw');
|
|
47
|
+
return path.join(stateDir, 'identity', 'device.json');
|
|
48
|
+
}
|
|
49
|
+
export function loadOrCreateDeviceIdentity() {
|
|
50
|
+
const filePath = getIdentityPath();
|
|
51
|
+
try {
|
|
52
|
+
if (fs.existsSync(filePath)) {
|
|
53
|
+
const raw = fs.readFileSync(filePath, 'utf8');
|
|
54
|
+
const parsed = JSON.parse(raw);
|
|
55
|
+
if (parsed?.version === 1 && parsed.deviceId && parsed.publicKeyPem && parsed.privateKeyPem) {
|
|
56
|
+
return {
|
|
57
|
+
deviceId: fingerprintPublicKey(parsed.publicKeyPem),
|
|
58
|
+
publicKeyPem: parsed.publicKeyPem,
|
|
59
|
+
privateKeyPem: parsed.privateKeyPem,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// regenerate
|
|
66
|
+
}
|
|
67
|
+
const { publicKey, privateKey } = crypto.generateKeyPairSync('ed25519');
|
|
68
|
+
const publicKeyPem = publicKey.export({ type: 'spki', format: 'pem' }).toString();
|
|
69
|
+
const privateKeyPem = privateKey.export({ type: 'pkcs8', format: 'pem' }).toString();
|
|
70
|
+
const deviceId = fingerprintPublicKey(publicKeyPem);
|
|
71
|
+
const identity = { deviceId, publicKeyPem, privateKeyPem };
|
|
72
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
73
|
+
fs.writeFileSync(filePath, JSON.stringify({ version: 1, ...identity, createdAtMs: Date.now() }, null, 2) + '\n', { mode: 0o600 });
|
|
74
|
+
return identity;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=device-identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-identity.js","sourceRoot":"","sources":["../../../src/providers/openclaw/device-identity.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { IChatProvider } from '../chat-types.js';
|
|
2
|
-
import type { ChatSession, ChatMessage, ChatAttachment } from '../chat-types.js';
|
|
2
|
+
import type { ChatSession, ChatMessage, ChatAttachment, ChatContentBlock } from '../chat-types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Process content blocks: resolve MEDIA: text references to inline base64 blocks.
|
|
5
|
+
* - Text block with "MEDIA:/path/to/file.png" → replaced with image/file block
|
|
6
|
+
* - Text block with "MEDIA:/path" mixed with other text → MEDIA part extracted, rest stays as text
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveMediaBlocks(blocks: ChatContentBlock[]): ChatContentBlock[];
|
|
3
9
|
export declare class OpenclawGatewayAdapter implements IChatProvider {
|
|
4
10
|
private client;
|
|
5
11
|
private streamCallbacks;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
1
3
|
import { GatewayClient } from './gateway-client.js';
|
|
2
4
|
import { toErrorMessage } from '../../utils/response.js';
|
|
3
5
|
const STREAM_TTL = 300_000; // 5 min
|
|
@@ -13,7 +15,7 @@ function extractText(msg) {
|
|
|
13
15
|
return msg;
|
|
14
16
|
if (Array.isArray(msg)) {
|
|
15
17
|
return msg
|
|
16
|
-
.filter((c) => c.type === 'text')
|
|
18
|
+
.filter((c) => c.type === 'text' && c.text)
|
|
17
19
|
.map((c) => c.text)
|
|
18
20
|
.join('');
|
|
19
21
|
}
|
|
@@ -22,7 +24,7 @@ function extractText(msg) {
|
|
|
22
24
|
// {role, content: [...], timestamp} format
|
|
23
25
|
if (Array.isArray(obj['content'])) {
|
|
24
26
|
return obj['content']
|
|
25
|
-
.filter((c) => c.type === 'text')
|
|
27
|
+
.filter((c) => c.type === 'text' && c.text)
|
|
26
28
|
.map((c) => c.text)
|
|
27
29
|
.join('');
|
|
28
30
|
}
|
|
@@ -32,6 +34,120 @@ function extractText(msg) {
|
|
|
32
34
|
}
|
|
33
35
|
return '';
|
|
34
36
|
}
|
|
37
|
+
// --- MEDIA: inline resolution ---
|
|
38
|
+
const MEDIA_PREFIX = 'MEDIA:';
|
|
39
|
+
const MAX_INLINE_SIZE = 10 * 1024 * 1024; // 10 MB
|
|
40
|
+
const IMAGE_EXTENSIONS = new Set(['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg']);
|
|
41
|
+
function mimeFromExt(ext) {
|
|
42
|
+
const map = {
|
|
43
|
+
'.png': 'image/png',
|
|
44
|
+
'.jpg': 'image/jpeg',
|
|
45
|
+
'.jpeg': 'image/jpeg',
|
|
46
|
+
'.gif': 'image/gif',
|
|
47
|
+
'.webp': 'image/webp',
|
|
48
|
+
'.svg': 'image/svg+xml',
|
|
49
|
+
'.pdf': 'application/pdf',
|
|
50
|
+
'.txt': 'text/plain',
|
|
51
|
+
'.json': 'application/json',
|
|
52
|
+
'.csv': 'text/csv',
|
|
53
|
+
};
|
|
54
|
+
return map[ext.toLowerCase()] ?? 'application/octet-stream';
|
|
55
|
+
}
|
|
56
|
+
function isImageExt(ext) {
|
|
57
|
+
return IMAGE_EXTENSIONS.has(ext.toLowerCase());
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Try to read a local file and return an inline content block (image or file).
|
|
61
|
+
* Returns null if the file doesn't exist, is too large, or is empty.
|
|
62
|
+
*/
|
|
63
|
+
function tryInlineFile(filePath) {
|
|
64
|
+
try {
|
|
65
|
+
if (!fs.existsSync(filePath))
|
|
66
|
+
return null;
|
|
67
|
+
const stat = fs.statSync(filePath);
|
|
68
|
+
if (stat.size > MAX_INLINE_SIZE || stat.size === 0)
|
|
69
|
+
return null;
|
|
70
|
+
const ext = path.extname(filePath);
|
|
71
|
+
const mimeType = mimeFromExt(ext);
|
|
72
|
+
const data = fs.readFileSync(filePath);
|
|
73
|
+
const base64 = data.toString('base64');
|
|
74
|
+
if (isImageExt(ext)) {
|
|
75
|
+
return {
|
|
76
|
+
type: 'image',
|
|
77
|
+
source: {
|
|
78
|
+
type: 'base64',
|
|
79
|
+
media_type: mimeType,
|
|
80
|
+
data: base64,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// Non-image files: return as a downloadable file block
|
|
85
|
+
return {
|
|
86
|
+
type: 'file',
|
|
87
|
+
name: path.basename(filePath),
|
|
88
|
+
mimeType,
|
|
89
|
+
data: base64,
|
|
90
|
+
size: stat.size,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Process content blocks: resolve MEDIA: text references to inline base64 blocks.
|
|
99
|
+
* - Text block with "MEDIA:/path/to/file.png" → replaced with image/file block
|
|
100
|
+
* - Text block with "MEDIA:/path" mixed with other text → MEDIA part extracted, rest stays as text
|
|
101
|
+
*/
|
|
102
|
+
export function resolveMediaBlocks(blocks) {
|
|
103
|
+
const resolved = [];
|
|
104
|
+
for (const block of blocks) {
|
|
105
|
+
if (block.type === 'text' && typeof block.text === 'string') {
|
|
106
|
+
const text = block.text.trim();
|
|
107
|
+
// Entire text block is a single MEDIA reference
|
|
108
|
+
if (text.startsWith(MEDIA_PREFIX) && !text.includes('\n')) {
|
|
109
|
+
const filePath = text.slice(MEDIA_PREFIX.length).trim();
|
|
110
|
+
const inlined = tryInlineFile(filePath);
|
|
111
|
+
if (inlined) {
|
|
112
|
+
resolved.push(inlined);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Check for MEDIA: references within multi-line text
|
|
117
|
+
if (text.includes(MEDIA_PREFIX)) {
|
|
118
|
+
const lines = text.split('\n');
|
|
119
|
+
const textLines = [];
|
|
120
|
+
for (const line of lines) {
|
|
121
|
+
const trimmed = line.trim();
|
|
122
|
+
if (trimmed.startsWith(MEDIA_PREFIX)) {
|
|
123
|
+
// Flush accumulated text
|
|
124
|
+
if (textLines.length > 0) {
|
|
125
|
+
resolved.push({ type: 'text', text: textLines.join('\n') });
|
|
126
|
+
textLines.length = 0;
|
|
127
|
+
}
|
|
128
|
+
const filePath = trimmed.slice(MEDIA_PREFIX.length).trim();
|
|
129
|
+
const inlined = tryInlineFile(filePath);
|
|
130
|
+
if (inlined) {
|
|
131
|
+
resolved.push(inlined);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
textLines.push(line); // Keep original if can't inline
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
textLines.push(line);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (textLines.length > 0) {
|
|
142
|
+
resolved.push({ type: 'text', text: textLines.join('\n') });
|
|
143
|
+
}
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
resolved.push(block);
|
|
148
|
+
}
|
|
149
|
+
return resolved;
|
|
150
|
+
}
|
|
35
151
|
export class OpenclawGatewayAdapter {
|
|
36
152
|
client;
|
|
37
153
|
streamCallbacks = new Map();
|
|
@@ -68,11 +184,23 @@ export class OpenclawGatewayAdapter {
|
|
|
68
184
|
async getHistory(sessionKey, limit = 200) {
|
|
69
185
|
const result = await this.client.request('chat.history', { sessionKey, limit });
|
|
70
186
|
const messages = (result?.messages ?? [])
|
|
71
|
-
.filter((m) => m.role === 'user' || m.role === 'assistant')
|
|
187
|
+
.filter((m) => m.role === 'user' || m.role === 'assistant' || m.role === 'toolResult')
|
|
72
188
|
.map((m) => {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
189
|
+
// Preserve content as-is: string or array of content blocks
|
|
190
|
+
let content;
|
|
191
|
+
if (typeof m.content === 'string') {
|
|
192
|
+
content = m.content;
|
|
193
|
+
}
|
|
194
|
+
else if (Array.isArray(m.content)) {
|
|
195
|
+
content = m.content;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
content = '';
|
|
199
|
+
}
|
|
200
|
+
// Resolve MEDIA: file references to inline base64
|
|
201
|
+
if (Array.isArray(content)) {
|
|
202
|
+
content = resolveMediaBlocks(content);
|
|
203
|
+
}
|
|
76
204
|
return {
|
|
77
205
|
role: m.role,
|
|
78
206
|
content,
|
|
@@ -81,12 +209,16 @@ export class OpenclawGatewayAdapter {
|
|
|
81
209
|
: m.timestamp ?? new Date().toISOString(),
|
|
82
210
|
};
|
|
83
211
|
});
|
|
84
|
-
// Deduplicate consecutive assistant messages with same content
|
|
212
|
+
// Deduplicate consecutive assistant messages with same text content
|
|
85
213
|
return messages.filter((msg, i) => {
|
|
86
214
|
if (i === 0)
|
|
87
215
|
return true;
|
|
88
216
|
const prev = messages[i - 1];
|
|
89
|
-
|
|
217
|
+
const prevText = typeof prev.content === 'string' ? prev.content
|
|
218
|
+
: prev.content.filter(b => b.type === 'text').map(b => b.text).join('');
|
|
219
|
+
const curText = typeof msg.content === 'string' ? msg.content
|
|
220
|
+
: msg.content.filter(b => b.type === 'text').map(b => b.text).join('');
|
|
221
|
+
return !(msg.role === 'assistant' && prev.role === 'assistant' && curText === prevText);
|
|
90
222
|
});
|
|
91
223
|
}
|
|
92
224
|
async sendMessage(params) {
|