indieclaw-agent 2.2.0 → 2.4.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.
- package/index.js +75 -54
- package/install.sh +14 -4
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -143,64 +143,79 @@ try {
|
|
|
143
143
|
// qrcode-terminal not installed, skip QR display
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
// --- OpenClaw Detection ---
|
|
147
|
-
const
|
|
146
|
+
// --- OpenClaw Detection & Config ---
|
|
147
|
+
const OPENCLAW_CONFIG_PATHS = [
|
|
148
|
+
path.join(os.homedir(), '.openclaw', 'openclaw.json'),
|
|
149
|
+
path.join(os.homedir(), '.openclaw', 'openclaw.json5'),
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
// Read OpenClaw gateway config (port + auth token) from local config file
|
|
153
|
+
function readOpenClawConfig() {
|
|
154
|
+
for (const configPath of OPENCLAW_CONFIG_PATHS) {
|
|
155
|
+
try {
|
|
156
|
+
if (!fs.existsSync(configPath)) continue;
|
|
157
|
+
let raw = fs.readFileSync(configPath, 'utf-8');
|
|
158
|
+
// Strip JSON5 comments (// and /* */) for safe JSON.parse
|
|
159
|
+
raw = raw.replace(/\/\/.*$/gm, '').replace(/\/\*[\s\S]*?\*\//g, '');
|
|
160
|
+
// Strip trailing commas before } or ]
|
|
161
|
+
raw = raw.replace(/,\s*([\]}])/g, '$1');
|
|
162
|
+
const config = JSON.parse(raw);
|
|
163
|
+
const gw = config.gateway || {};
|
|
164
|
+
return {
|
|
165
|
+
port: gw.port || 18789,
|
|
166
|
+
token: gw.auth?.token || gw.auth?.password || null,
|
|
167
|
+
host: gw.bind || '127.0.0.1',
|
|
168
|
+
};
|
|
169
|
+
} catch {}
|
|
170
|
+
}
|
|
171
|
+
return { port: 18789, token: null, host: '127.0.0.1' };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Cache the config on startup
|
|
175
|
+
let openClawConfig = readOpenClawConfig();
|
|
148
176
|
|
|
149
|
-
function
|
|
177
|
+
function detectOpenClaw() {
|
|
150
178
|
return new Promise((resolve) => {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
} catch {
|
|
172
|
-
resolve({ available: false, models: [], port });
|
|
179
|
+
// Refresh config each detection
|
|
180
|
+
openClawConfig = readOpenClawConfig();
|
|
181
|
+
|
|
182
|
+
// Method 1: Use `openclaw gateway status` CLI (most reliable)
|
|
183
|
+
exec('openclaw gateway status 2>&1', { timeout: 5000 }, (err, stdout) => {
|
|
184
|
+
const output = (stdout || '').toLowerCase();
|
|
185
|
+
if (!err && (output.includes('running') || output.includes('active'))) {
|
|
186
|
+
return resolve({ available: true, models: ['openclaw'], port: openClawConfig.port });
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Method 2: Check if openclaw-gateway process is running
|
|
190
|
+
exec('pgrep -f "openclaw.gateway\\|openclaw-gateway" 2>/dev/null', { timeout: 2000 }, (err3, pid) => {
|
|
191
|
+
if (!err3 && pid?.trim()) {
|
|
192
|
+
return resolve({ available: true, models: ['openclaw'], port: openClawConfig.port });
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Method 3: Check if openclaw binary exists + health check
|
|
196
|
+
exec('command -v openclaw 2>/dev/null', { timeout: 2000 }, (err2, binPath) => {
|
|
197
|
+
if (err2 || !binPath?.trim()) {
|
|
198
|
+
return resolve({ available: false, models: [], port: null });
|
|
173
199
|
}
|
|
200
|
+
exec(`openclaw gateway health --url ws://127.0.0.1:${openClawConfig.port} 2>&1`, { timeout: 5000 }, (err4, healthOut) => {
|
|
201
|
+
const hOutput = (healthOut || '').toLowerCase();
|
|
202
|
+
if (!err4 && (hOutput.includes('ok') || hOutput.includes('healthy') || hOutput.includes('reachable'))) {
|
|
203
|
+
return resolve({ available: true, models: ['openclaw'], port: openClawConfig.port });
|
|
204
|
+
}
|
|
205
|
+
return resolve({ available: false, models: [], port: null });
|
|
206
|
+
});
|
|
174
207
|
});
|
|
175
|
-
}
|
|
176
|
-
);
|
|
177
|
-
req.on('timeout', () => {
|
|
178
|
-
req.destroy();
|
|
179
|
-
resolve({ available: false, models: [], port });
|
|
180
|
-
});
|
|
181
|
-
req.on('error', () => {
|
|
182
|
-
resolve({ available: false, models: [], port });
|
|
208
|
+
});
|
|
183
209
|
});
|
|
184
|
-
req.end();
|
|
185
210
|
});
|
|
186
211
|
}
|
|
187
212
|
|
|
188
|
-
async function detectOpenClaw() {
|
|
189
|
-
// Try all common ports in parallel
|
|
190
|
-
const results = await Promise.all(OPENCLAW_PORTS.map(tryOpenClawPort));
|
|
191
|
-
const found = results.find((r) => r.available);
|
|
192
|
-
if (found) {
|
|
193
|
-
return { available: true, models: found.models, port: found.port };
|
|
194
|
-
}
|
|
195
|
-
return { available: false, models: [], port: null };
|
|
196
|
-
}
|
|
197
|
-
|
|
198
213
|
// Run detection on startup
|
|
199
214
|
detectOpenClaw().then((oc) => {
|
|
200
215
|
if (oc.available) {
|
|
201
|
-
console.log(` [OpenClaw] Detected on port ${oc.port}
|
|
216
|
+
console.log(` [OpenClaw] Detected (gateway on port ${oc.port})`);
|
|
202
217
|
} else {
|
|
203
|
-
console.log(
|
|
218
|
+
console.log(' [OpenClaw] Not detected');
|
|
204
219
|
}
|
|
205
220
|
});
|
|
206
221
|
|
|
@@ -963,9 +978,11 @@ function handleTerminalStop(ws, { id }) {
|
|
|
963
978
|
}
|
|
964
979
|
|
|
965
980
|
// --- Chat (OpenClaw Proxy) ---
|
|
966
|
-
function handleChatSend(ws, { id, messages
|
|
967
|
-
|
|
968
|
-
const
|
|
981
|
+
function handleChatSend(ws, { id, messages }) {
|
|
982
|
+
// Use locally-detected OpenClaw config — no need for app to send credentials
|
|
983
|
+
const port = openClawConfig.port || 18789;
|
|
984
|
+
const host = openClawConfig.host || '127.0.0.1';
|
|
985
|
+
const token = openClawConfig.token;
|
|
969
986
|
|
|
970
987
|
const body = JSON.stringify({
|
|
971
988
|
model: 'openclaw:main',
|
|
@@ -973,17 +990,21 @@ function handleChatSend(ws, { id, messages, openclawToken, openclawPort, opencla
|
|
|
973
990
|
stream: true,
|
|
974
991
|
});
|
|
975
992
|
|
|
993
|
+
const headers = {
|
|
994
|
+
'Content-Type': 'application/json',
|
|
995
|
+
'x-openclaw-agent-id': 'main',
|
|
996
|
+
};
|
|
997
|
+
if (token) {
|
|
998
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
999
|
+
}
|
|
1000
|
+
|
|
976
1001
|
const req = http.request(
|
|
977
1002
|
{
|
|
978
1003
|
hostname: host,
|
|
979
1004
|
port,
|
|
980
1005
|
path: '/v1/chat/completions',
|
|
981
1006
|
method: 'POST',
|
|
982
|
-
headers
|
|
983
|
-
'Content-Type': 'application/json',
|
|
984
|
-
Authorization: `Bearer ${openclawToken}`,
|
|
985
|
-
'x-openclaw-agent-id': 'main',
|
|
986
|
-
},
|
|
1007
|
+
headers,
|
|
987
1008
|
},
|
|
988
1009
|
(res) => {
|
|
989
1010
|
if (res.statusCode !== 200) {
|
package/install.sh
CHANGED
|
@@ -110,11 +110,21 @@ echo -e " ${GREEN}✓${NC} IP: ${MACHINE_IP}"
|
|
|
110
110
|
# Step 5: Check OpenClaw
|
|
111
111
|
echo -e "${YELLOW}[5/5]${NC} Checking OpenClaw..."
|
|
112
112
|
OPENCLAW_STATUS="not detected"
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
# Check via CLI (gateway status), then via process, then via binary existence
|
|
114
|
+
if command -v openclaw &> /dev/null; then
|
|
115
|
+
OC_STATUS=$(openclaw gateway status 2>&1 || true)
|
|
116
|
+
if echo "$OC_STATUS" | grep -qi "running\|active"; then
|
|
117
|
+
OPENCLAW_STATUS="running"
|
|
118
|
+
echo -e " ${GREEN}✓${NC} OpenClaw gateway is running"
|
|
119
|
+
elif pgrep -f "openclaw.gateway\|openclaw-gateway" > /dev/null 2>&1; then
|
|
120
|
+
OPENCLAW_STATUS="running"
|
|
121
|
+
echo -e " ${GREEN}✓${NC} OpenClaw gateway process detected"
|
|
122
|
+
else
|
|
123
|
+
OPENCLAW_STATUS="installed (gateway not running)"
|
|
124
|
+
echo -e " ${YELLOW}—${NC} OpenClaw installed but gateway not running. Start with: openclaw gateway run"
|
|
125
|
+
fi
|
|
116
126
|
else
|
|
117
|
-
echo -e " ${YELLOW}—${NC} OpenClaw not
|
|
127
|
+
echo -e " ${YELLOW}—${NC} OpenClaw not installed (optional, for AI features)"
|
|
118
128
|
fi
|
|
119
129
|
|
|
120
130
|
# Build deep link
|