@openagents-org/agent-launcher 0.2.181 → 0.2.182
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/icons/antigravity.svg +1 -0
- package/icons/mini-swe-agent.svg +7 -0
- package/package.json +3 -2
- package/registry.json +1137 -622
- package/src/adapters/aider.js +10 -3
- package/src/adapters/amp.js +11 -3
- package/src/adapters/antigravity.js +10 -2
- package/src/adapters/base.js +46 -0
- package/src/adapters/claude.js +6 -1
- package/src/adapters/cline.js +5 -1
- package/src/adapters/codebuddy.js +6 -1
- package/src/adapters/codex.js +10 -2
- package/src/adapters/commandcode.js +5 -1
- package/src/adapters/copilot.js +6 -1
- package/src/adapters/cursor.js +5 -1
- package/src/adapters/deepseek.js +5 -1
- package/src/adapters/gemini.js +10 -2
- package/src/adapters/goose.js +6 -2
- package/src/adapters/hermes.js +23 -53
- package/src/adapters/kimi.js +5 -1
- package/src/adapters/llm-direct.js +6 -0
- package/src/adapters/mini.js +10 -3
- package/src/adapters/openclaw.js +5 -1
- package/src/adapters/opencode.js +6 -1
- package/src/adapters/openworker.js +15 -1
- package/src/adapters/pi.js +6 -1
- package/src/adapters/workspace-prompt.js +23 -12
- package/src/daemon.js +5 -1
- package/src/installer.js +57 -16
- package/src/paths.js +98 -34
- package/src/probe.js +4 -1
- package/src/wsl.js +579 -0
package/src/adapters/aider.js
CHANGED
|
@@ -35,7 +35,11 @@
|
|
|
35
35
|
const fs = require('fs');
|
|
36
36
|
const os = require('os');
|
|
37
37
|
const path = require('path');
|
|
38
|
-
const { execSync
|
|
38
|
+
const { execSync } = require('child_process');
|
|
39
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
40
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
41
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
42
|
+
const { spawn, resolveWslBinary } = require('../wsl');
|
|
39
43
|
|
|
40
44
|
const BaseAdapter = require('./base');
|
|
41
45
|
const { whichBinary, getEnhancedEnv, aiderBinDirs } = require('../paths');
|
|
@@ -262,7 +266,7 @@ class AiderAdapter extends BaseAdapter {
|
|
|
262
266
|
// PATH (nvm/fnm/volta/homebrew + the Aider install dirs added to paths.js)
|
|
263
267
|
// — covers the GUI/daemon "not on PATH" case for uv-tool / pipx / pip-user
|
|
264
268
|
// installs.
|
|
265
|
-
const resolved = whichBinary('aider');
|
|
269
|
+
const resolved = whichBinary('aider', { allowWsl: false });
|
|
266
270
|
if (resolved) return resolved;
|
|
267
271
|
|
|
268
272
|
// Explicit fallback over every real install dir (XDG bin, XDG_DATA_HOME/../
|
|
@@ -274,7 +278,10 @@ class AiderAdapter extends BaseAdapter {
|
|
|
274
278
|
if (fs.existsSync(c)) return c;
|
|
275
279
|
}
|
|
276
280
|
}
|
|
277
|
-
|
|
281
|
+
// Nothing native anywhere. Last of all, look inside WSL: a CLI the user
|
|
282
|
+
// installed in their distro is a real install, and the marked path it comes
|
|
283
|
+
// back as is what the spawn bridge in ../wsl turns into a wsl.exe run.
|
|
284
|
+
return resolveWslBinary('aider');
|
|
278
285
|
}
|
|
279
286
|
|
|
280
287
|
// ------------------------------------------------------------------
|
package/src/adapters/amp.js
CHANGED
|
@@ -25,7 +25,11 @@
|
|
|
25
25
|
const fs = require('fs');
|
|
26
26
|
const os = require('os');
|
|
27
27
|
const path = require('path');
|
|
28
|
-
const { execSync
|
|
28
|
+
const { execSync } = require('child_process');
|
|
29
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
30
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
31
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
32
|
+
const { spawn, resolveWslBinary } = require('../wsl');
|
|
29
33
|
|
|
30
34
|
const BaseAdapter = require('./base');
|
|
31
35
|
const { buildOpenclawSystemPrompt } = require('./workspace-prompt');
|
|
@@ -123,7 +127,7 @@ class AmpAdapter extends BaseAdapter {
|
|
|
123
127
|
// the Amp installer's ~/.amp/bin. This is what makes detection work inside
|
|
124
128
|
// a GUI- or daemon-spawned process that did NOT inherit the user's
|
|
125
129
|
// interactive shell PATH (the common "installed but not found" case).
|
|
126
|
-
const resolved = whichBinary('amp');
|
|
130
|
+
const resolved = whichBinary('amp', { allowWsl: false });
|
|
127
131
|
if (resolved) return resolved;
|
|
128
132
|
|
|
129
133
|
// Tier 2: explicit known install dirs as a last resort. The official
|
|
@@ -145,7 +149,10 @@ class AmpAdapter extends BaseAdapter {
|
|
|
145
149
|
if (c && fs.existsSync(c)) return c;
|
|
146
150
|
}
|
|
147
151
|
|
|
148
|
-
|
|
152
|
+
// Nothing native anywhere. Last of all, look inside WSL: a CLI the user
|
|
153
|
+
// installed in their distro is a real install, and the marked path it comes
|
|
154
|
+
// back as is what the spawn bridge in ../wsl turns into a wsl.exe run.
|
|
155
|
+
return resolveWslBinary('amp');
|
|
149
156
|
}
|
|
150
157
|
|
|
151
158
|
/**
|
|
@@ -181,6 +188,7 @@ class AmpAdapter extends BaseAdapter {
|
|
|
181
188
|
endpoint: this.endpoint,
|
|
182
189
|
token: this.token,
|
|
183
190
|
mode: this._mode,
|
|
191
|
+
model: this.modelLabel(),
|
|
184
192
|
disabledModules: this.disabledModules,
|
|
185
193
|
browserEnabled,
|
|
186
194
|
...this.pinnedPromptOpts(channelName),
|
|
@@ -17,7 +17,11 @@
|
|
|
17
17
|
const fs = require('fs');
|
|
18
18
|
const os = require('os');
|
|
19
19
|
const path = require('path');
|
|
20
|
-
const { execSync
|
|
20
|
+
const { execSync } = require('child_process');
|
|
21
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
22
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
23
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
24
|
+
const { spawn, resolveWslBinary } = require('../wsl');
|
|
21
25
|
|
|
22
26
|
const BaseAdapter = require('./base');
|
|
23
27
|
const { whereBinary } = require('../paths');
|
|
@@ -131,7 +135,10 @@ class AntigravityAdapter extends BaseAdapter {
|
|
|
131
135
|
for (const c of candidates) {
|
|
132
136
|
if (fs.existsSync(c)) return c;
|
|
133
137
|
}
|
|
134
|
-
|
|
138
|
+
// Nothing native anywhere. Last of all, look inside WSL: a CLI the user
|
|
139
|
+
// installed in their distro is a real install, and the marked path it comes
|
|
140
|
+
// back as is what the spawn bridge in ../wsl turns into a wsl.exe run.
|
|
141
|
+
return resolveWslBinary('agy');
|
|
135
142
|
}
|
|
136
143
|
|
|
137
144
|
/**
|
|
@@ -178,6 +185,7 @@ class AntigravityAdapter extends BaseAdapter {
|
|
|
178
185
|
workspaceId: this.workspaceId,
|
|
179
186
|
channelName,
|
|
180
187
|
mode: this._mode,
|
|
188
|
+
model: this.modelLabel(),
|
|
181
189
|
decisionLog: pinned.decisionLog ? { ...pinned.decisionLog, writeAccess: false } : null,
|
|
182
190
|
glossary: pinned.glossary ? { ...pinned.glossary, writeAccess: false } : null,
|
|
183
191
|
});
|
package/src/adapters/base.js
CHANGED
|
@@ -60,6 +60,18 @@ const CURSOR_RESUME_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
|
60
60
|
// heartbeat_failed up to the daemon. A success resets the streak immediately.
|
|
61
61
|
const HEARTBEAT_ERROR_THRESHOLD = 2;
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Model variables whose name does not follow `<TYPE>_MODEL`. Only the ones an
|
|
65
|
+
* adapter really reads — see `modelLabel`, which tries `<TYPE>_MODEL` first
|
|
66
|
+
* and `LLM_MODEL` last, so nothing else needs an entry here.
|
|
67
|
+
*/
|
|
68
|
+
const MODEL_ENV_ALIASES = {
|
|
69
|
+
claude: ['ANTHROPIC_MODEL', 'CLAUDE_MODEL'],
|
|
70
|
+
gemini: ['GEMINI_MODEL', 'GOOGLE_GEMINI_MODEL'],
|
|
71
|
+
antigravity: ['ANTIGRAVITY_MODEL', 'AGY_MODEL'],
|
|
72
|
+
codex: ['CODEX_MODEL', 'OPENCLAW_MODEL'],
|
|
73
|
+
};
|
|
74
|
+
|
|
63
75
|
class BaseAdapter {
|
|
64
76
|
/**
|
|
65
77
|
* @param {object} opts
|
|
@@ -220,6 +232,40 @@ class BaseAdapter {
|
|
|
220
232
|
}
|
|
221
233
|
}
|
|
222
234
|
|
|
235
|
+
/**
|
|
236
|
+
* The model this agent is actually running on, for the workspace prompt.
|
|
237
|
+
*
|
|
238
|
+
* The one fact about itself an agent cannot look up. Asked "what model are
|
|
239
|
+
* you?", a CLI-driven agent answers from what its weights remember about
|
|
240
|
+
* their own training, which is a guess — and a user who had configured
|
|
241
|
+
* deepseek was told, confidently, "I am Claude, by Anthropic". We know the
|
|
242
|
+
* real answer: it is the id we hand the CLI.
|
|
243
|
+
*
|
|
244
|
+
* Resolution order is the same one the adapters spawn with: a model chosen
|
|
245
|
+
* in the workspace wins, then this agent type's own model variable, then the
|
|
246
|
+
* generic LLM_MODEL that the LLM-direct types and the daemon's model.set
|
|
247
|
+
* both write. Adapters that qualify the id further (OpenWorker prefixes it
|
|
248
|
+
* with the provider) override this and return exactly what they send.
|
|
249
|
+
*
|
|
250
|
+
* Null when nothing is configured — the CLI is then running its own default
|
|
251
|
+
* and we have nothing truthful to say about it. Better silent than wrong.
|
|
252
|
+
*/
|
|
253
|
+
modelLabel() {
|
|
254
|
+
const fromWorkspace = String(this.workspaceModel || '').trim();
|
|
255
|
+
if (fromWorkspace) return fromWorkspace;
|
|
256
|
+
const type = String(this.agentType || '').toUpperCase().replace(/[^A-Z0-9]+/g, '_');
|
|
257
|
+
const candidates = [
|
|
258
|
+
...(type ? [`${type}_MODEL`] : []),
|
|
259
|
+
...(MODEL_ENV_ALIASES[this.agentType] || []),
|
|
260
|
+
'LLM_MODEL',
|
|
261
|
+
];
|
|
262
|
+
for (const key of candidates) {
|
|
263
|
+
const value = String((this.agentEnv && this.agentEnv[key]) || '').trim();
|
|
264
|
+
if (value) return value;
|
|
265
|
+
}
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
|
|
223
269
|
async run() {
|
|
224
270
|
this._running = true;
|
|
225
271
|
|
package/src/adapters/claude.js
CHANGED
|
@@ -14,7 +14,11 @@
|
|
|
14
14
|
const fs = require('fs');
|
|
15
15
|
const os = require('os');
|
|
16
16
|
const path = require('path');
|
|
17
|
-
const { execSync
|
|
17
|
+
const { execSync } = require('child_process');
|
|
18
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
19
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
20
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
21
|
+
const { spawn } = require('../wsl');
|
|
18
22
|
|
|
19
23
|
const BaseAdapter = require('./base');
|
|
20
24
|
const { formatAttachmentsForPrompt, SESSION_DEFAULT_RE, generateSessionTitle, redactSecrets } = require('./utils');
|
|
@@ -462,6 +466,7 @@ class ClaudeAdapter extends BaseAdapter {
|
|
|
462
466
|
workspaceId: this.workspaceId,
|
|
463
467
|
channelName,
|
|
464
468
|
mode: this._mode,
|
|
469
|
+
model: this.modelLabel(),
|
|
465
470
|
browserEnabled,
|
|
466
471
|
toolMode: this.toolMode,
|
|
467
472
|
decisionLog,
|
package/src/adapters/cline.js
CHANGED
|
@@ -26,7 +26,11 @@
|
|
|
26
26
|
const fs = require('fs');
|
|
27
27
|
const os = require('os');
|
|
28
28
|
const path = require('path');
|
|
29
|
-
const { execSync, execFile
|
|
29
|
+
const { execSync, execFile } = require('child_process');
|
|
30
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
31
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
32
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
33
|
+
const { spawn } = require('../wsl');
|
|
30
34
|
|
|
31
35
|
const BaseAdapter = require('./base');
|
|
32
36
|
const { formatAttachmentsForPrompt, SESSION_DEFAULT_RE, generateSessionTitle } = require('./utils');
|
|
@@ -49,7 +49,11 @@
|
|
|
49
49
|
const fs = require('fs');
|
|
50
50
|
const os = require('os');
|
|
51
51
|
const path = require('path');
|
|
52
|
-
const { execFileSync
|
|
52
|
+
const { execFileSync } = require('child_process');
|
|
53
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
54
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
55
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
56
|
+
const { spawn } = require('../wsl');
|
|
53
57
|
|
|
54
58
|
const BaseAdapter = require('./base');
|
|
55
59
|
const { formatAttachmentsForPrompt, SESSION_DEFAULT_RE, generateSessionTitle } = require('./utils');
|
|
@@ -824,6 +828,7 @@ class CodeBuddyAdapter extends BaseAdapter {
|
|
|
824
828
|
workspaceId: this.workspaceId,
|
|
825
829
|
channelName: channel,
|
|
826
830
|
mode: this._mode,
|
|
831
|
+
model: this.modelLabel(),
|
|
827
832
|
browserEnabled: await this.getBrowserEnabled(),
|
|
828
833
|
toolMode: 'mcp',
|
|
829
834
|
});
|
package/src/adapters/codex.js
CHANGED
|
@@ -15,7 +15,11 @@
|
|
|
15
15
|
const fs = require('fs');
|
|
16
16
|
const os = require('os');
|
|
17
17
|
const path = require('path');
|
|
18
|
-
const { execSync
|
|
18
|
+
const { execSync } = require('child_process');
|
|
19
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
20
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
21
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
22
|
+
const { spawn, resolveWslBinary } = require('../wsl');
|
|
19
23
|
const http = require('http');
|
|
20
24
|
const https = require('https');
|
|
21
25
|
|
|
@@ -165,7 +169,10 @@ class CodexAdapter extends BaseAdapter {
|
|
|
165
169
|
if (fs.existsSync(c)) return c;
|
|
166
170
|
}
|
|
167
171
|
|
|
168
|
-
|
|
172
|
+
// Nothing native anywhere. Last of all, look inside WSL: a CLI the user
|
|
173
|
+
// installed in their distro is a real install, and the marked path it comes
|
|
174
|
+
// back as is what the spawn bridge in ../wsl turns into a wsl.exe run.
|
|
175
|
+
return resolveWslBinary('codex');
|
|
169
176
|
}
|
|
170
177
|
|
|
171
178
|
_buildSystemContext(channelName) {
|
|
@@ -176,6 +183,7 @@ class CodexAdapter extends BaseAdapter {
|
|
|
176
183
|
endpoint: this.endpoint,
|
|
177
184
|
token: this.token,
|
|
178
185
|
mode: this._mode,
|
|
186
|
+
model: this.modelLabel(),
|
|
179
187
|
disabledModules: this.disabledModules,
|
|
180
188
|
...this.pinnedPromptOpts(channelName),
|
|
181
189
|
});
|
|
@@ -45,7 +45,11 @@
|
|
|
45
45
|
const fs = require('fs');
|
|
46
46
|
const os = require('os');
|
|
47
47
|
const path = require('path');
|
|
48
|
-
const { execFileSync
|
|
48
|
+
const { execFileSync } = require('child_process');
|
|
49
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
50
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
51
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
52
|
+
const { spawn } = require('../wsl');
|
|
49
53
|
|
|
50
54
|
const BaseAdapter = require('./base');
|
|
51
55
|
const { formatAttachmentsForPrompt, SESSION_DEFAULT_RE, generateSessionTitle } = require('./utils');
|
package/src/adapters/copilot.js
CHANGED
|
@@ -38,7 +38,11 @@
|
|
|
38
38
|
const fs = require('fs');
|
|
39
39
|
const os = require('os');
|
|
40
40
|
const path = require('path');
|
|
41
|
-
const { execSync, execFileSync
|
|
41
|
+
const { execSync, execFileSync } = require('child_process');
|
|
42
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
43
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
44
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
45
|
+
const { spawn } = require('../wsl');
|
|
42
46
|
|
|
43
47
|
const BaseAdapter = require('./base');
|
|
44
48
|
const { buildOpenclawSystemPrompt } = require('./workspace-prompt');
|
|
@@ -326,6 +330,7 @@ class CopilotAdapter extends BaseAdapter {
|
|
|
326
330
|
endpoint: this.endpoint,
|
|
327
331
|
token: this.token,
|
|
328
332
|
mode: this._mode,
|
|
333
|
+
model: this.modelLabel(),
|
|
329
334
|
disabledModules: this.disabledModules,
|
|
330
335
|
...this.pinnedPromptOpts(channelName),
|
|
331
336
|
});
|
package/src/adapters/cursor.js
CHANGED
|
@@ -12,7 +12,11 @@
|
|
|
12
12
|
const fs = require('fs');
|
|
13
13
|
const os = require('os');
|
|
14
14
|
const path = require('path');
|
|
15
|
-
const { execSync
|
|
15
|
+
const { execSync } = require('child_process');
|
|
16
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
17
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
18
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
19
|
+
const { spawn } = require('../wsl');
|
|
16
20
|
|
|
17
21
|
const BaseAdapter = require('./base');
|
|
18
22
|
const { formatAttachmentsForPrompt, SESSION_DEFAULT_RE, generateSessionTitle } = require('./utils');
|
package/src/adapters/deepseek.js
CHANGED
|
@@ -47,7 +47,11 @@
|
|
|
47
47
|
const fs = require('fs');
|
|
48
48
|
const os = require('os');
|
|
49
49
|
const path = require('path');
|
|
50
|
-
const { execFileSync,
|
|
50
|
+
const { execFileSync, execSync } = require('child_process');
|
|
51
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
52
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
53
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
54
|
+
const { spawn } = require('../wsl');
|
|
51
55
|
|
|
52
56
|
const BaseAdapter = require('./base');
|
|
53
57
|
const { whichBinary, getEnhancedEnv } = require('../paths');
|
package/src/adapters/gemini.js
CHANGED
|
@@ -11,7 +11,11 @@
|
|
|
11
11
|
const fs = require('fs');
|
|
12
12
|
const os = require('os');
|
|
13
13
|
const path = require('path');
|
|
14
|
-
const { execSync
|
|
14
|
+
const { execSync } = require('child_process');
|
|
15
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
16
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
17
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
18
|
+
const { spawn, resolveWslBinary } = require('../wsl');
|
|
15
19
|
|
|
16
20
|
const BaseAdapter = require('./base');
|
|
17
21
|
const { whereBinary } = require('../paths');
|
|
@@ -183,7 +187,10 @@ class GeminiAdapter extends BaseAdapter {
|
|
|
183
187
|
if (fs.existsSync(c)) return c;
|
|
184
188
|
}
|
|
185
189
|
|
|
186
|
-
|
|
190
|
+
// Nothing native anywhere. Last of all, look inside WSL: a CLI the user
|
|
191
|
+
// installed in their distro is a real install, and the marked path it comes
|
|
192
|
+
// back as is what the spawn bridge in ../wsl turns into a wsl.exe run.
|
|
193
|
+
return resolveWslBinary('gemini');
|
|
187
194
|
}
|
|
188
195
|
|
|
189
196
|
// The Gemini CLI refuses to run non-interactively unless an auth method is
|
|
@@ -232,6 +239,7 @@ class GeminiAdapter extends BaseAdapter {
|
|
|
232
239
|
workspaceId: this.workspaceId,
|
|
233
240
|
channelName,
|
|
234
241
|
mode: this._mode,
|
|
242
|
+
model: this.modelLabel(),
|
|
235
243
|
decisionLog: pinned.decisionLog ? { ...pinned.decisionLog, writeAccess: false } : null,
|
|
236
244
|
glossary: pinned.glossary ? { ...pinned.glossary, writeAccess: false } : null,
|
|
237
245
|
});
|
package/src/adapters/goose.js
CHANGED
|
@@ -28,7 +28,11 @@ const fs = require('fs');
|
|
|
28
28
|
const path = require('path');
|
|
29
29
|
const os = require('os');
|
|
30
30
|
const crypto = require('crypto');
|
|
31
|
-
const {
|
|
31
|
+
const { execSync, execFileSync } = require('child_process');
|
|
32
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
33
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
34
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
35
|
+
const { spawn } = require('../wsl');
|
|
32
36
|
|
|
33
37
|
const BaseAdapter = require('./base');
|
|
34
38
|
const { GooseStreamParser, classifyGooseError, redactSecrets } = require('./goose-stream');
|
|
@@ -249,7 +253,7 @@ class GooseAdapter extends BaseAdapter {
|
|
|
249
253
|
|
|
250
254
|
_buildSystemPrompt(channelName) {
|
|
251
255
|
const pinned = this.pinnedPromptOpts(channelName);
|
|
252
|
-
let prompt = buildWorkspaceIdentity(this.agentName, this.workspaceId, channelName, this._mode)
|
|
256
|
+
let prompt = buildWorkspaceIdentity(this.agentName, this.workspaceId, channelName, this._mode, 'mcp', this.modelLabel())
|
|
253
257
|
+ buildCollaborationPrompt()
|
|
254
258
|
+ buildModePrompt(this._mode)
|
|
255
259
|
+ buildPinnedSections({
|
package/src/adapters/hermes.js
CHANGED
|
@@ -17,7 +17,11 @@
|
|
|
17
17
|
const fs = require('fs');
|
|
18
18
|
const os = require('os');
|
|
19
19
|
const path = require('path');
|
|
20
|
-
const { execSync
|
|
20
|
+
const { execSync } = require('child_process');
|
|
21
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
22
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
23
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
24
|
+
const { spawn, bridgeSpawn } = require('../wsl');
|
|
21
25
|
|
|
22
26
|
const BaseAdapter = require('./base');
|
|
23
27
|
const { buildOpenclawSystemPrompt } = require('./workspace-prompt');
|
|
@@ -71,9 +75,6 @@ class HermesAdapter extends BaseAdapter {
|
|
|
71
75
|
|
|
72
76
|
_findHermesBinary() {
|
|
73
77
|
const home = os.homedir();
|
|
74
|
-
// Reset each call. When set, this._hermesBin is a path INSIDE WSL and must
|
|
75
|
-
// be invoked as `wsl -e <path> …` rather than spawned natively.
|
|
76
|
-
this._hermesViaWsl = false;
|
|
77
78
|
|
|
78
79
|
// Tier 1: PATH (enriched env so we see the dirs the launcher adds; a fresh
|
|
79
80
|
// install updates the user PATH, which the running daemon won't pick up).
|
|
@@ -112,40 +113,13 @@ class HermesAdapter extends BaseAdapter {
|
|
|
112
113
|
if (fs.existsSync(c)) return c;
|
|
113
114
|
}
|
|
114
115
|
|
|
115
|
-
// Tier 3: Deep scan of every known bin dir
|
|
116
|
+
// Tier 3: Deep scan of every known bin dir — which ends inside WSL when
|
|
117
|
+
// nothing native turned up, so a hermes the user set up in their distro is
|
|
118
|
+
// found here and comes back marked for the ../wsl spawn bridge. Native
|
|
119
|
+
// Windows (Tiers 1-2) is still preferred.
|
|
116
120
|
const viaWhich = whichBinary('hermes');
|
|
117
121
|
if (viaWhich) return viaWhich;
|
|
118
122
|
|
|
119
|
-
// Tier 4 (Windows only): fall back to a WSL install if one exists. Native
|
|
120
|
-
// Windows (Tiers 1-3) is preferred, but a user who set hermes up inside
|
|
121
|
-
// WSL2 still works — resolve its absolute in-WSL path; _runHermes then
|
|
122
|
-
// invokes it as `wsl -e <path> …`.
|
|
123
|
-
if (IS_WINDOWS) {
|
|
124
|
-
const wslPath = this._resolveWslHermes();
|
|
125
|
-
if (wslPath) {
|
|
126
|
-
this._hermesViaWsl = true;
|
|
127
|
-
return wslPath;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Resolve hermes's absolute path inside the default WSL distro, or null.
|
|
136
|
-
* Uses a login shell (`bash -lc`) so the installer's PATH additions
|
|
137
|
-
* (~/.local/bin) are visible. Returns an absolute Linux path like
|
|
138
|
-
* /home/<user>/.local/bin/hermes.
|
|
139
|
-
*/
|
|
140
|
-
_resolveWslHermes() {
|
|
141
|
-
if (!IS_WINDOWS) return null;
|
|
142
|
-
try {
|
|
143
|
-
const out = execSync('wsl.exe -e bash -lc "command -v hermes"', {
|
|
144
|
-
encoding: 'utf-8', timeout: 8000, windowsHide: true,
|
|
145
|
-
}).trim();
|
|
146
|
-
const p = out.split(/\r?\n/).map((s) => s.trim()).find(Boolean);
|
|
147
|
-
if (p && p.startsWith('/')) return p;
|
|
148
|
-
} catch {}
|
|
149
123
|
return null;
|
|
150
124
|
}
|
|
151
125
|
|
|
@@ -240,6 +214,7 @@ class HermesAdapter extends BaseAdapter {
|
|
|
240
214
|
endpoint: this.endpoint,
|
|
241
215
|
token: this.token,
|
|
242
216
|
mode: this._mode,
|
|
217
|
+
model: this.modelLabel(),
|
|
243
218
|
disabledModules: this.disabledModules,
|
|
244
219
|
...this.pinnedPromptOpts(channelName),
|
|
245
220
|
}),
|
|
@@ -314,23 +289,17 @@ class HermesAdapter extends BaseAdapter {
|
|
|
314
289
|
|
|
315
290
|
const env = { ...(this.agentEnv || process.env) };
|
|
316
291
|
|
|
317
|
-
//
|
|
318
|
-
//
|
|
319
|
-
//
|
|
320
|
-
// hermes then uses its own config
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
if (this._hermesViaWsl) {
|
|
324
|
-
spawnBin = 'wsl.exe';
|
|
325
|
-
spawnArgs = ['-e', this._hermesBin, ...args];
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
const proc = spawn(spawnBin, spawnArgs, {
|
|
292
|
+
// A hermes that lives inside WSL is rewritten to `wsl.exe -e <path> …` by
|
|
293
|
+
// the bridge in ../wsl (which also forces detached off, there being no
|
|
294
|
+
// process group on the far side, and hands the distro the agent's env via
|
|
295
|
+
// WSLENV). hermes then uses its own config — ~/.hermes inside the distro —
|
|
296
|
+
// for model and keys. Nothing to special-case here.
|
|
297
|
+
const proc = spawn(this._hermesBin, args, {
|
|
329
298
|
env,
|
|
330
299
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
331
|
-
// No process group on Windows
|
|
332
|
-
//
|
|
333
|
-
detached: !IS_WINDOWS
|
|
300
|
+
// No process group on Windows (can't signal one); windowsHide keeps a
|
|
301
|
+
// console from flashing up.
|
|
302
|
+
detached: !IS_WINDOWS,
|
|
334
303
|
windowsHide: true,
|
|
335
304
|
});
|
|
336
305
|
this._channelProcesses[channelName] = proc;
|
|
@@ -469,9 +438,10 @@ class HermesAdapter extends BaseAdapter {
|
|
|
469
438
|
|
|
470
439
|
const { execFileSync } = require('child_process');
|
|
471
440
|
const run = (args) => {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
441
|
+
// Same rewrite the spawn bridge does, for the one call here that needs to
|
|
442
|
+
// be synchronous: an in-distro hermes is only reachable through wsl.exe.
|
|
443
|
+
const { file, args: argv } = bridgeSpawn(bin, args);
|
|
444
|
+
execFileSync(file, argv, {
|
|
475
445
|
stdio: 'ignore',
|
|
476
446
|
timeout: 20000,
|
|
477
447
|
windowsHide: true,
|
package/src/adapters/kimi.js
CHANGED
|
@@ -29,7 +29,11 @@
|
|
|
29
29
|
const fs = require('fs');
|
|
30
30
|
const os = require('os');
|
|
31
31
|
const path = require('path');
|
|
32
|
-
const { execSync
|
|
32
|
+
const { execSync } = require('child_process');
|
|
33
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
34
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
35
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
36
|
+
const { spawn } = require('../wsl');
|
|
33
37
|
|
|
34
38
|
const LlmDirectAdapter = require('./llm-direct');
|
|
35
39
|
const { formatAttachmentsForPrompt, SESSION_DEFAULT_RE, generateSessionTitle } = require('./utils');
|
|
@@ -71,6 +71,11 @@ class LlmDirectAdapter extends BaseAdapter {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
/** The model this runner actually calls with — see `_model` above. */
|
|
75
|
+
modelLabel() {
|
|
76
|
+
return String(this.workspaceModel || this._model || '').trim() || null;
|
|
77
|
+
}
|
|
78
|
+
|
|
74
79
|
_buildSystemPrompt(channelName) {
|
|
75
80
|
return buildOpenclawSystemPrompt({
|
|
76
81
|
agentName: this.agentName,
|
|
@@ -79,6 +84,7 @@ class LlmDirectAdapter extends BaseAdapter {
|
|
|
79
84
|
endpoint: this.endpoint,
|
|
80
85
|
token: this.token,
|
|
81
86
|
mode: this._mode,
|
|
87
|
+
model: this.modelLabel(),
|
|
82
88
|
disabledModules: this.disabledModules,
|
|
83
89
|
...this.pinnedPromptOpts(channelName),
|
|
84
90
|
});
|
package/src/adapters/mini.js
CHANGED
|
@@ -50,7 +50,11 @@
|
|
|
50
50
|
const fs = require('fs');
|
|
51
51
|
const os = require('os');
|
|
52
52
|
const path = require('path');
|
|
53
|
-
const { execSync
|
|
53
|
+
const { execSync } = require('child_process');
|
|
54
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
55
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
56
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
57
|
+
const { spawn, resolveWslBinary } = require('../wsl');
|
|
54
58
|
|
|
55
59
|
const BaseAdapter = require('./base');
|
|
56
60
|
const { whichBinary, getEnhancedEnv, aiderBinDirs } = require('../paths');
|
|
@@ -178,7 +182,7 @@ class MiniSweAgentAdapter extends BaseAdapter {
|
|
|
178
182
|
// Shared cross-platform resolver runs `which`/`where` against an ENHANCED
|
|
179
183
|
// PATH (nvm/fnm/volta/homebrew + pip/pipx/uv user-install dirs) — covers the
|
|
180
184
|
// GUI/daemon "installed but not on PATH" case for a `pip install`.
|
|
181
|
-
const resolved = whichBinary('mini');
|
|
185
|
+
const resolved = whichBinary('mini', { allowWsl: false });
|
|
182
186
|
if (resolved) return this._resolveExePreference(resolved, IS_WINDOWS);
|
|
183
187
|
|
|
184
188
|
// Explicit fallback over the pip/pipx/uv user-install bin dirs plus the uv
|
|
@@ -201,7 +205,10 @@ class MiniSweAgentAdapter extends BaseAdapter {
|
|
|
201
205
|
if (fs.existsSync(c)) return c;
|
|
202
206
|
}
|
|
203
207
|
}
|
|
204
|
-
|
|
208
|
+
// Nothing native anywhere. Last of all, look inside WSL: a CLI the user
|
|
209
|
+
// installed in their distro is a real install, and the marked path it comes
|
|
210
|
+
// back as is what the spawn bridge in ../wsl turns into a wsl.exe run.
|
|
211
|
+
return resolveWslBinary('mini');
|
|
205
212
|
}
|
|
206
213
|
|
|
207
214
|
/**
|
package/src/adapters/openclaw.js
CHANGED
|
@@ -14,7 +14,11 @@
|
|
|
14
14
|
const fs = require('fs');
|
|
15
15
|
const path = require('path');
|
|
16
16
|
const os = require('os');
|
|
17
|
-
const {
|
|
17
|
+
const { execSync } = require('child_process');
|
|
18
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
19
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
20
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
21
|
+
const { spawn } = require('../wsl');
|
|
18
22
|
|
|
19
23
|
const BaseAdapter = require('./base');
|
|
20
24
|
const { formatAttachmentsForPrompt } = require('./utils');
|
package/src/adapters/opencode.js
CHANGED
|
@@ -14,7 +14,11 @@ const fs = require('fs');
|
|
|
14
14
|
const path = require('path');
|
|
15
15
|
const os = require('os');
|
|
16
16
|
const crypto = require('crypto');
|
|
17
|
-
const { execSync
|
|
17
|
+
const { execSync } = require('child_process');
|
|
18
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
19
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
20
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
21
|
+
const { spawn } = require('../wsl');
|
|
18
22
|
|
|
19
23
|
const BaseAdapter = require('./base');
|
|
20
24
|
const { formatAttachmentsForPrompt, redactSecrets } = require('./utils');
|
|
@@ -250,6 +254,7 @@ class OpenCodeAdapter extends BaseAdapter {
|
|
|
250
254
|
endpoint: this.endpoint,
|
|
251
255
|
token: this.token,
|
|
252
256
|
mode: this._mode,
|
|
257
|
+
model: this.modelLabel(),
|
|
253
258
|
disabledModules: this.disabledModules,
|
|
254
259
|
...this.pinnedPromptOpts(channelName),
|
|
255
260
|
});
|
|
@@ -42,7 +42,11 @@ const net = require('net');
|
|
|
42
42
|
const os = require('os');
|
|
43
43
|
const path = require('path');
|
|
44
44
|
const crypto = require('crypto');
|
|
45
|
-
const {
|
|
45
|
+
const { execFileSync } = require('child_process');
|
|
46
|
+
// spawn() here is the WSL bridge from ../wsl: same signature as
|
|
47
|
+
// child_process.spawn, and a straight pass-through unless the resolved CLI
|
|
48
|
+
// lives on the other side of the Windows/WSL boundary.
|
|
49
|
+
const { spawn } = require('../wsl');
|
|
46
50
|
|
|
47
51
|
const BaseAdapter = require('./base');
|
|
48
52
|
const { formatAttachmentsForPrompt, SESSION_DEFAULT_RE, generateSessionTitle } = require('./utils');
|
|
@@ -203,6 +207,15 @@ class OpenWorkerAdapter extends BaseAdapter {
|
|
|
203
207
|
return String(this.agentEnv.OPENWORKER_API_KEY || '').trim();
|
|
204
208
|
}
|
|
205
209
|
|
|
210
|
+
/**
|
|
211
|
+
* What to tell the agent it is running on. `_model()` is the id we hand the
|
|
212
|
+
* server, provider prefix and all — the honest answer to "what model are
|
|
213
|
+
* you?", which OpenWorker's own weights cannot give.
|
|
214
|
+
*/
|
|
215
|
+
modelLabel() {
|
|
216
|
+
return this._model() || null;
|
|
217
|
+
}
|
|
218
|
+
|
|
206
219
|
/** The model for a turn: the workspace's selection wins over the saved env. */
|
|
207
220
|
_model() {
|
|
208
221
|
const raw = String(this.workspaceModel || this.agentEnv.OPENWORKER_MODEL || '').trim();
|
|
@@ -587,6 +600,7 @@ class OpenWorkerAdapter extends BaseAdapter {
|
|
|
587
600
|
endpoint: this.endpoint,
|
|
588
601
|
token: this.token,
|
|
589
602
|
mode: this._mode,
|
|
603
|
+
model: this.modelLabel(),
|
|
590
604
|
disabledModules: this.disabledModules,
|
|
591
605
|
browserEnabled,
|
|
592
606
|
});
|