aquaman-plugin 0.6.0 → 0.7.1
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/README.md +16 -12
- package/index.ts +44 -84
- package/openclaw.plugin.json +0 -11
- package/package.json +6 -3
- package/src/commands.ts +26 -198
- package/src/config-schema.ts +0 -31
- package/src/http-interceptor.ts +30 -59
- package/src/index.ts +1 -13
- package/src/plugin.ts +16 -143
- package/src/proxy-health.ts +43 -38
- package/src/proxy-manager.ts +9 -32
- package/src/embedded.ts +0 -182
package/src/proxy-manager.ts
CHANGED
|
@@ -2,22 +2,20 @@
|
|
|
2
2
|
* Proxy process lifecycle manager
|
|
3
3
|
*
|
|
4
4
|
* Spawns and manages the aquaman proxy daemon as a separate process
|
|
5
|
-
* for maximum credential isolation.
|
|
5
|
+
* for maximum credential isolation. Communicates via Unix domain socket.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { spawn, type ChildProcess } from 'node:child_process';
|
|
9
9
|
import * as path from 'node:path';
|
|
10
10
|
import * as fs from 'node:fs';
|
|
11
|
+
import * as os from 'node:os';
|
|
11
12
|
import type { PluginConfig } from './config-schema.js';
|
|
12
13
|
|
|
13
14
|
export interface ProxyConnectionInfo {
|
|
14
15
|
ready: boolean;
|
|
15
|
-
|
|
16
|
-
protocol: 'http' | 'https';
|
|
17
|
-
baseUrl: string;
|
|
16
|
+
socketPath: string;
|
|
18
17
|
services: string[];
|
|
19
18
|
backend: string;
|
|
20
|
-
token?: string;
|
|
21
19
|
hostMap?: Record<string, string>;
|
|
22
20
|
}
|
|
23
21
|
|
|
@@ -79,11 +77,8 @@ export class ProxyManager {
|
|
|
79
77
|
return;
|
|
80
78
|
}
|
|
81
79
|
|
|
82
|
-
// Build arguments
|
|
83
|
-
const args = [
|
|
84
|
-
'plugin-mode',
|
|
85
|
-
'--port', String(config.proxyPort || 8081)
|
|
86
|
-
];
|
|
80
|
+
// Build arguments — UDS is the default, no --port needed
|
|
81
|
+
const args = ['plugin-mode'];
|
|
87
82
|
|
|
88
83
|
// Spawn proxy process
|
|
89
84
|
this.process = spawn(binaryPath, args, {
|
|
@@ -140,15 +135,7 @@ export class ProxyManager {
|
|
|
140
135
|
|
|
141
136
|
if (!this.connectionInfo) {
|
|
142
137
|
const stderrText = stderr || stdout;
|
|
143
|
-
|
|
144
|
-
if (stderrText.includes('EADDRINUSE') || stderrText.includes('already in use')) {
|
|
145
|
-
const port = config.proxyPort || 8081;
|
|
146
|
-
error = new Error(
|
|
147
|
-
`Proxy port ${port} is in use. Stop the existing instance: aquaman stop`
|
|
148
|
-
);
|
|
149
|
-
} else {
|
|
150
|
-
error = new Error(`Proxy exited with code ${code}: ${stderrText}`);
|
|
151
|
-
}
|
|
138
|
+
const error = new Error(`Proxy exited with code ${code}: ${stderrText}`);
|
|
152
139
|
reject(error);
|
|
153
140
|
}
|
|
154
141
|
});
|
|
@@ -205,20 +192,10 @@ export class ProxyManager {
|
|
|
205
192
|
}
|
|
206
193
|
|
|
207
194
|
/**
|
|
208
|
-
* Get
|
|
209
|
-
*/
|
|
210
|
-
getClientToken(): string | null {
|
|
211
|
-
return this.connectionInfo?.token || null;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Get base URL for a service
|
|
195
|
+
* Get socket path
|
|
216
196
|
*/
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
return null;
|
|
220
|
-
}
|
|
221
|
-
return `${this.connectionInfo.baseUrl}/${service}`;
|
|
197
|
+
getSocketPath(): string | null {
|
|
198
|
+
return this.connectionInfo?.socketPath || null;
|
|
222
199
|
}
|
|
223
200
|
|
|
224
201
|
/**
|
package/src/embedded.ts
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Embedded mode - Direct vault access within OpenClaw process
|
|
3
|
-
*
|
|
4
|
-
* This mode provides simpler setup but credentials DO enter the Gateway process memory.
|
|
5
|
-
* Use proxy mode for maximum isolation.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
createCredentialStore,
|
|
10
|
-
createAuditLogger,
|
|
11
|
-
type CredentialStore,
|
|
12
|
-
type AuditLogger,
|
|
13
|
-
type CredentialBackend
|
|
14
|
-
} from 'aquaman-core';
|
|
15
|
-
import type { PluginConfig } from './config-schema.js';
|
|
16
|
-
|
|
17
|
-
export interface EmbeddedModeOptions {
|
|
18
|
-
config: PluginConfig;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export class EmbeddedMode {
|
|
22
|
-
private config: PluginConfig;
|
|
23
|
-
private store: CredentialStore | null = null;
|
|
24
|
-
private auditLogger: AuditLogger | null = null;
|
|
25
|
-
private initialized = false;
|
|
26
|
-
|
|
27
|
-
constructor(options: EmbeddedModeOptions) {
|
|
28
|
-
this.config = options.config;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Initialize the embedded mode
|
|
33
|
-
*/
|
|
34
|
-
async initialize(): Promise<void> {
|
|
35
|
-
if (this.initialized) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Initialize credential store
|
|
40
|
-
this.store = createCredentialStore({
|
|
41
|
-
backend: (this.config.backend || 'keychain') as CredentialBackend,
|
|
42
|
-
vaultAddress: this.config.vaultAddress,
|
|
43
|
-
vaultToken: this.config.vaultToken,
|
|
44
|
-
vaultNamespace: this.config.vaultNamespace,
|
|
45
|
-
vaultMountPath: this.config.vaultMountPath,
|
|
46
|
-
onePasswordVault: this.config.onePasswordVault,
|
|
47
|
-
onePasswordAccount: this.config.onePasswordAccount,
|
|
48
|
-
encryptionPassword: process.env['AQUAMAN_ENCRYPTION_PASSWORD']
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
// Initialize audit logger
|
|
52
|
-
if (this.config.auditEnabled !== false) {
|
|
53
|
-
this.auditLogger = createAuditLogger({
|
|
54
|
-
logDir: this.config.auditLogDir || '~/.aquaman/audit',
|
|
55
|
-
enabled: true
|
|
56
|
-
});
|
|
57
|
-
await this.auditLogger.initialize();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
this.initialized = true;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Get a credential for a service
|
|
65
|
-
* WARNING: This retrieves the credential into process memory
|
|
66
|
-
*/
|
|
67
|
-
async getCredential(service: string, key: string): Promise<string | null> {
|
|
68
|
-
if (!this.store) {
|
|
69
|
-
throw new Error('Embedded mode not initialized');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const credential = await this.store.get(service, key);
|
|
73
|
-
|
|
74
|
-
// Log access
|
|
75
|
-
if (this.auditLogger) {
|
|
76
|
-
await this.auditLogger.logCredentialAccess('embedded', 'openclaw', {
|
|
77
|
-
service,
|
|
78
|
-
operation: 'read',
|
|
79
|
-
success: credential !== null
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return credential;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Set a credential
|
|
88
|
-
*/
|
|
89
|
-
async setCredential(service: string, key: string, value: string): Promise<void> {
|
|
90
|
-
if (!this.store) {
|
|
91
|
-
throw new Error('Embedded mode not initialized');
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
await this.store.set(service, key, value);
|
|
95
|
-
|
|
96
|
-
// Log access
|
|
97
|
-
if (this.auditLogger) {
|
|
98
|
-
await this.auditLogger.logCredentialAccess('embedded', 'openclaw', {
|
|
99
|
-
service,
|
|
100
|
-
operation: 'use',
|
|
101
|
-
success: true
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Delete a credential
|
|
108
|
-
*/
|
|
109
|
-
async deleteCredential(service: string, key: string): Promise<boolean> {
|
|
110
|
-
if (!this.store) {
|
|
111
|
-
throw new Error('Embedded mode not initialized');
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return this.store.delete(service, key);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* List credentials
|
|
119
|
-
*/
|
|
120
|
-
async listCredentials(service?: string): Promise<Array<{ service: string; key: string }>> {
|
|
121
|
-
if (!this.store) {
|
|
122
|
-
throw new Error('Embedded mode not initialized');
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return this.store.list(service);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Check if a credential exists
|
|
130
|
-
*/
|
|
131
|
-
async hasCredential(service: string, key: string): Promise<boolean> {
|
|
132
|
-
if (!this.store) {
|
|
133
|
-
throw new Error('Embedded mode not initialized');
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return this.store.exists(service, key);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Get the audit logger
|
|
141
|
-
*/
|
|
142
|
-
getAuditLogger(): AuditLogger | null {
|
|
143
|
-
return this.auditLogger;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Get status info
|
|
148
|
-
*/
|
|
149
|
-
getStatus(): { initialized: boolean; backend: string; auditEnabled: boolean } {
|
|
150
|
-
return {
|
|
151
|
-
initialized: this.initialized,
|
|
152
|
-
backend: this.config.backend || 'keychain',
|
|
153
|
-
auditEnabled: this.config.auditEnabled !== false
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Verify audit log integrity
|
|
159
|
-
*/
|
|
160
|
-
async verifyAuditIntegrity(): Promise<{ valid: boolean; errors: string[] }> {
|
|
161
|
-
if (!this.auditLogger) {
|
|
162
|
-
return { valid: true, errors: [] };
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return this.auditLogger.verifyIntegrity();
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Get recent audit entries
|
|
170
|
-
*/
|
|
171
|
-
async getRecentAuditEntries(count: number = 10): Promise<any[]> {
|
|
172
|
-
if (!this.auditLogger) {
|
|
173
|
-
return [];
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return this.auditLogger.tail(count);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
export function createEmbeddedMode(options: EmbeddedModeOptions): EmbeddedMode {
|
|
181
|
-
return new EmbeddedMode(options);
|
|
182
|
-
}
|