@commonlyai/cli 0.1.163 → 0.1.164
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/package.json +1 -1
- package/src/commands/agent.js +0 -26
- package/src/lib/adapters/claude.js +1 -4
- package/src/lib/adapters/codex.js +1 -4
- package/src/lib/adapters/dsh.js +1 -4
- package/src/lib/adapters/goose.js +2 -4
- package/src/lib/adapters/hermes.js +1 -4
- package/src/lib/adapters/opencode.js +1 -4
- package/src/lib/adapters/pi.js +2 -4
- package/src/lib/adapters/qwen.js +1 -4
- package/src/lib/adapters/seat-model.js +0 -12
package/package.json
CHANGED
package/src/commands/agent.js
CHANGED
|
@@ -17,7 +17,6 @@ import { homedir, tmpdir } from 'os';
|
|
|
17
17
|
import { fileURLToPath } from 'url';
|
|
18
18
|
import { createHash } from 'crypto';
|
|
19
19
|
|
|
20
|
-
import { requireSeatModel } from '../lib/adapters/seat-model.js';
|
|
21
20
|
import { createClient } from '../lib/api.js';
|
|
22
21
|
import { copyHandoffMemory } from '../lib/handoff-memory.js';
|
|
23
22
|
import {
|
|
@@ -1254,7 +1253,6 @@ export const performRun = ({
|
|
|
1254
1253
|
const effectiveTurnTimeoutMs = Number.isFinite(requestedTurnTimeout) && requestedTurnTimeout > 0
|
|
1255
1254
|
? Math.min(requestedTurnTimeout, 2_147_483_647) : 15 * 60 * 1000;
|
|
1256
1255
|
const client = createClient({ instance: instanceUrl, token });
|
|
1257
|
-
const missingModelNotices = new Set();
|
|
1258
1256
|
const handoffAgent = sanitizeHandoffAgent(refusalHandoff);
|
|
1259
1257
|
if (refusalHandoff && !handoffAgent) {
|
|
1260
1258
|
log(`--refusal-handoff ignored: '${String(refusalHandoff).slice(0, 64)}' is not an agent handle`);
|
|
@@ -1679,30 +1677,6 @@ export const performRun = ({
|
|
|
1679
1677
|
? `${recycleBriefing}\n\n${promptWithSkills}`
|
|
1680
1678
|
: promptWithSkills;
|
|
1681
1679
|
|
|
1682
|
-
if (adapter.requiresModel) {
|
|
1683
|
-
try {
|
|
1684
|
-
requireSeatModel(seatEnvironment, adapter.name);
|
|
1685
|
-
} catch (error) {
|
|
1686
|
-
if (error.code === 'seat_model_missing' && eventPodId && !missingModelNotices.has(eventPodId)) {
|
|
1687
|
-
try {
|
|
1688
|
-
const delivery = await deliverChatReply({
|
|
1689
|
-
client,
|
|
1690
|
-
podId: eventPodId,
|
|
1691
|
-
text: "This agent has no model set; add environment.model to its configuration.",
|
|
1692
|
-
limit: chatCharLimit,
|
|
1693
|
-
maxChunks: maxChatChunks,
|
|
1694
|
-
log,
|
|
1695
|
-
});
|
|
1696
|
-
if (!delivery.skipped && !delivery.refused) missingModelNotices.add(eventPodId);
|
|
1697
|
-
} catch (noticeError) {
|
|
1698
|
-
log(`missing model notice could not be posted: ${noticeError.message}`);
|
|
1699
|
-
}
|
|
1700
|
-
}
|
|
1701
|
-
// Configuration failure is retryable: never turn a notice into an ack.
|
|
1702
|
-
throw error;
|
|
1703
|
-
}
|
|
1704
|
-
}
|
|
1705
|
-
|
|
1706
1680
|
log(`[${event.type}] spawning ${adapter.name}`);
|
|
1707
1681
|
// TASK-102 part B. The CHILD gets a scoped credential; the wrapper keeps
|
|
1708
1682
|
// the seat token for its own polling, claiming and posting (`client` was
|
|
@@ -43,7 +43,6 @@
|
|
|
43
43
|
* SIGKILL escalation is a post-v1 concern (ADR-005 §Spawning semantics).
|
|
44
44
|
*/
|
|
45
45
|
|
|
46
|
-
import { requireSeatModel } from './seat-model.js';
|
|
47
46
|
import { spawn as childSpawn, spawnSync } from 'child_process';
|
|
48
47
|
import { createHash, randomUUID } from 'crypto';
|
|
49
48
|
import { accessSync, constants, realpathSync } from 'fs';
|
|
@@ -726,7 +725,6 @@ const prepareArgv = async (innerArgv, ctx) => {
|
|
|
726
725
|
};
|
|
727
726
|
|
|
728
727
|
export default {
|
|
729
|
-
requiresModel: true,
|
|
730
728
|
name: 'claude',
|
|
731
729
|
// Identity-bearing runtime tag written into AgentInstallation.config.runtime
|
|
732
730
|
// by `commonly agent attach`. The CLI command stays `commonly agent attach
|
|
@@ -761,7 +759,6 @@ export default {
|
|
|
761
759
|
},
|
|
762
760
|
|
|
763
761
|
async spawn(prompt, rawCtx = {}) {
|
|
764
|
-
const seatModel = requireSeatModel(rawCtx.environment, 'claude');
|
|
765
762
|
// `sandbox.trust: 'internal'` is refused for new declarations and read as
|
|
766
763
|
// `public` for a record that already carries it; such a seat is confined
|
|
767
764
|
// where it can be and refuses to derive where it cannot (Wren 69585).
|
|
@@ -812,7 +809,7 @@ export default {
|
|
|
812
809
|
// session-recovery retry, or a retry runs at a different effort than the
|
|
813
810
|
// turn it replaces.
|
|
814
811
|
const modelArgs = [
|
|
815
|
-
'--model',
|
|
812
|
+
...(ctx.environment?.model ? ['--model', String(ctx.environment.model)] : []),
|
|
816
813
|
...(ctx.environment?.effort ? ['--effort', String(ctx.environment.effort)] : []),
|
|
817
814
|
];
|
|
818
815
|
const baseArgs = ['-p', fullPrompt, '--output-format', 'text', sessionFlag, sessionId, ...modelArgs];
|
|
@@ -37,7 +37,6 @@
|
|
|
37
37
|
* SIGKILL escalation is a post-v1 concern (ADR-005 §Spawning semantics).
|
|
38
38
|
*/
|
|
39
39
|
|
|
40
|
-
import { requireSeatModel } from './seat-model.js';
|
|
41
40
|
import { spawn as childSpawn, spawnSync } from 'child_process';
|
|
42
41
|
import { createHash } from 'crypto';
|
|
43
42
|
import { accessSync, constants } from 'fs';
|
|
@@ -617,7 +616,6 @@ const runCodex = ({ args, cwd, env, timeoutMs, credentials = [], spawnImpl = chi
|
|
|
617
616
|
});
|
|
618
617
|
|
|
619
618
|
export default {
|
|
620
|
-
requiresModel: true,
|
|
621
619
|
name: 'codex',
|
|
622
620
|
// See claude.js for the rationale — identity-bearing runtime tag persisted
|
|
623
621
|
// to AgentInstallation.config.runtime (paired with host:'byo') so a CLI-
|
|
@@ -644,7 +642,6 @@ export default {
|
|
|
644
642
|
},
|
|
645
643
|
|
|
646
644
|
async spawn(prompt, ctx = {}) {
|
|
647
|
-
const seatModel = requireSeatModel(ctx.environment, 'codex');
|
|
648
645
|
// Passed through UNCOALESCED. `ctx.memoryLongTerm || ''` was here, and
|
|
649
646
|
// `null || ''` is `''` — which routed the unreadable case straight into
|
|
650
647
|
// the empty-memory branch and made the whole distinction unreachable from
|
|
@@ -701,7 +698,7 @@ export default {
|
|
|
701
698
|
mcpFlags: mcp.flags,
|
|
702
699
|
mcpReadDirectories: mcp.mcpReadDirectories,
|
|
703
700
|
publicSandboxMode,
|
|
704
|
-
model:
|
|
701
|
+
model: ctx.environment?.model,
|
|
705
702
|
effort: ctx.environment?.effort,
|
|
706
703
|
commitAttributionEnv: ctx.commitAttributionEnv,
|
|
707
704
|
});
|
package/src/lib/adapters/dsh.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/** DeepSeek Harness 0.2.1-rc.2, private seats only. Configuration is per spawn. */
|
|
2
|
-
import { requireSeatModel } from './seat-model.js';
|
|
3
2
|
import { spawn as childSpawn, spawnSync } from 'child_process';
|
|
4
3
|
import { createHash } from 'crypto';
|
|
5
4
|
import { existsSync } from 'fs';
|
|
@@ -219,7 +218,6 @@ export const runDsh = ({ binary, args, cwd, env, timeoutMs, credentials, spawnIm
|
|
|
219
218
|
});
|
|
220
219
|
|
|
221
220
|
export default {
|
|
222
|
-
requiresModel: true,
|
|
223
221
|
name: 'dsh', runtimeType: 'dsh', supportsProvider: true,
|
|
224
222
|
|
|
225
223
|
async validateEnvironment(environment, workspacePath) {
|
|
@@ -248,7 +246,6 @@ export default {
|
|
|
248
246
|
},
|
|
249
247
|
|
|
250
248
|
async spawn(prompt, ctx = {}) {
|
|
251
|
-
const seatModel = requireSeatModel(ctx.environment, 'dsh');
|
|
252
249
|
assertPrivateDsh(ctx.environment);
|
|
253
250
|
if (!ctx.environment?.provider || !ctx.environment?.model) {
|
|
254
251
|
throw new Error('dsh requires environment.provider and environment.model');
|
|
@@ -278,7 +275,7 @@ export default {
|
|
|
278
275
|
credentialFile: credential.path, instanceUrl: ctx.instanceUrl,
|
|
279
276
|
});
|
|
280
277
|
const patch = JSON.stringify(buildPatch({
|
|
281
|
-
proxyBaseURL: proxy.baseURL, model:
|
|
278
|
+
proxyBaseURL: proxy.baseURL, model: ctx.environment.model,
|
|
282
279
|
cwd: ctx.cwd, mcp, effort: ctx.environment.effort,
|
|
283
280
|
deepseekOfficial: new URL(ctx.environment.provider.baseURL).hostname === 'api.deepseek.com',
|
|
284
281
|
}), null, 2);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/** Goose 1.54.0 wrapper. Public seats wait for TASK-236's deny-by-default proof. */
|
|
2
|
-
import { requireSeatModel } from './seat-model.js';
|
|
3
2
|
import { spawn as childSpawn, spawnSync } from 'node:child_process';
|
|
4
3
|
import { mkdtemp, readFile, rm } from 'node:fs/promises';
|
|
5
4
|
import { tmpdir } from 'node:os';
|
|
@@ -17,6 +16,7 @@ import { adapterFailure, spawnCredentials } from '../upstream-refusal.js';
|
|
|
17
16
|
export const TESTED_GOOSE_VERSIONS = Object.freeze(['1.54.0']);
|
|
18
17
|
const DEFAULT_TIMEOUT_MS = 15 * 60 * 1000;
|
|
19
18
|
const TERMINATION_GRACE_MS = 5000;
|
|
19
|
+
const DEFAULT_MODEL = 'deepseek-v4-flash';
|
|
20
20
|
const DEFAULT_PROVIDER_HOST = 'https://litellm.commonly.me';
|
|
21
21
|
const DEFAULT_PROVIDER_KEY = 'COMMONLY_LITELLM_KEY';
|
|
22
22
|
const PLACEHOLDER_RE = /\$\{(COMMONLY_[A-Z_]+)\}/g;
|
|
@@ -174,7 +174,6 @@ const runGoose = ({ binary, args, cwd, env, timeoutMs, credentials, spawnImpl =
|
|
|
174
174
|
});
|
|
175
175
|
|
|
176
176
|
export default {
|
|
177
|
-
requiresModel: true,
|
|
178
177
|
name: 'goose',
|
|
179
178
|
providerKeyEnv: DEFAULT_PROVIDER_KEY,
|
|
180
179
|
supportsProvider: true,
|
|
@@ -194,7 +193,6 @@ export default {
|
|
|
194
193
|
},
|
|
195
194
|
|
|
196
195
|
async spawn(prompt, ctx = {}) {
|
|
197
|
-
const seatModel = requireSeatModel(ctx.environment, 'goose');
|
|
198
196
|
const keyFile = await this.validateEnvironment(ctx.environment, ctx.cwd);
|
|
199
197
|
const sourceEnv = ctx.env || process.env;
|
|
200
198
|
const configured = ctx.environment?.provider;
|
|
@@ -205,7 +203,7 @@ export default {
|
|
|
205
203
|
if (!/^https?:$/.test(baseUrl.protocol) || baseUrl.username || baseUrl.password || baseUrl.search || baseUrl.hash) {
|
|
206
204
|
throw new Error('goose adapter: provider.baseURL must be a plain HTTP(S) URL');
|
|
207
205
|
}
|
|
208
|
-
const model =
|
|
206
|
+
const model = ctx.environment?.model || DEFAULT_MODEL;
|
|
209
207
|
const binary = ctx._binaryPath || 'goose';
|
|
210
208
|
const version = ctx._version || versionOf(spawnSync(binary, ['--version'], { encoding: 'utf8', timeout: 5000 }).stdout);
|
|
211
209
|
if (!TESTED_GOOSE_VERSIONS.includes(version)) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/** Hermes 0.22.2 local CLI wrapper. Hermes owns provider I/O; this file only spawns it. */
|
|
2
|
-
import { requireSeatModel } from './seat-model.js';
|
|
3
2
|
import { spawn as childSpawn, spawnSync } from 'child_process';
|
|
4
3
|
import { createHash } from 'crypto';
|
|
5
4
|
import { mkdir } from 'fs/promises';
|
|
@@ -138,7 +137,6 @@ const runHermes = ({ args, prompt, cwd, env, timeoutMs, spawnImpl, credentials }
|
|
|
138
137
|
});
|
|
139
138
|
|
|
140
139
|
export default {
|
|
141
|
-
requiresModel: true,
|
|
142
140
|
name: 'hermes',
|
|
143
141
|
runtimeType: 'hermes',
|
|
144
142
|
supportsProvider: false,
|
|
@@ -163,7 +161,6 @@ export default {
|
|
|
163
161
|
},
|
|
164
162
|
|
|
165
163
|
async spawn(prompt, ctx = {}) {
|
|
166
|
-
const seatModel = requireSeatModel(ctx.environment, 'hermes');
|
|
167
164
|
await this.validateEnvironment(ctx.environment);
|
|
168
165
|
// Keep Hermes away from the operator's default profile, including any
|
|
169
166
|
// Nous Portal/Cloud credentials there. The wrapper provides the sole key.
|
|
@@ -180,7 +177,7 @@ export default {
|
|
|
180
177
|
}
|
|
181
178
|
const args = ['chat', '--oneshot', '--query-file', '-', '--format', 'stream-json',
|
|
182
179
|
'--provider', 'openrouter', '--source', 'tool', '--no-restore-cwd'];
|
|
183
|
-
args.push('--model',
|
|
180
|
+
if (ctx.environment?.model) args.push('--model', ctx.environment.model);
|
|
184
181
|
if (ctx.sessionId) args.push('--resume', ctx.sessionId);
|
|
185
182
|
const fullPrompt = buildMemoryPreamble(prompt, ctx.memoryLongTerm, {
|
|
186
183
|
freshSession: !ctx.sessionId,
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
* `text.part.text`, and token counts in `step_finish.part.tokens`.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import { requireSeatModel } from './seat-model.js';
|
|
23
22
|
import { spawn as childSpawn, spawnSync } from 'child_process';
|
|
24
23
|
import { createHash } from 'crypto';
|
|
25
24
|
import { realpathSync } from 'fs';
|
|
@@ -623,7 +622,6 @@ const describeOpenCodeVersionMismatch = (installedVersion) => {
|
|
|
623
622
|
};
|
|
624
623
|
|
|
625
624
|
export default {
|
|
626
|
-
requiresModel: true,
|
|
627
625
|
name: 'opencode',
|
|
628
626
|
runtimeType: 'opencode',
|
|
629
627
|
supportsProvider: true,
|
|
@@ -647,7 +645,6 @@ export default {
|
|
|
647
645
|
},
|
|
648
646
|
|
|
649
647
|
async spawn(prompt, rawCtx = {}) {
|
|
650
|
-
const seatModel = requireSeatModel(rawCtx.environment, 'opencode');
|
|
651
648
|
const sandbox = normalizeSandboxTrust(rawCtx.environment?.sandbox);
|
|
652
649
|
const ctx = rawCtx.environment
|
|
653
650
|
? { ...rawCtx, environment: { ...rawCtx.environment, sandbox } }
|
|
@@ -808,7 +805,7 @@ export default {
|
|
|
808
805
|
prompt: fullPrompt,
|
|
809
806
|
sessionId: ctx.sessionId,
|
|
810
807
|
cwd: ctx.cwd,
|
|
811
|
-
model: qualifiedProviderModel(provider,
|
|
808
|
+
model: qualifiedProviderModel(provider, ctx.environment?.model),
|
|
812
809
|
effort: ctx.environment?.effort,
|
|
813
810
|
title: ctx.agentName,
|
|
814
811
|
});
|
package/src/lib/adapters/pi.js
CHANGED
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
* Contract (see stub.js): detect() and spawn(prompt, ctx) → { text, newSessionId }.
|
|
33
33
|
*/
|
|
34
34
|
|
|
35
|
-
import { requireSeatModel } from './seat-model.js';
|
|
36
35
|
import { spawn as childSpawn, spawnSync } from 'child_process';
|
|
37
36
|
import { createHash, randomUUID } from 'crypto';
|
|
38
37
|
import { mkdir, readdir, writeFile } from 'fs/promises';
|
|
@@ -66,6 +65,7 @@ export const DEFAULT_PROVIDER = Object.freeze({
|
|
|
66
65
|
api: 'openai-completions',
|
|
67
66
|
apiKeyEnv: 'COMMONLY_LITELLM_KEY',
|
|
68
67
|
});
|
|
68
|
+
export const DEFAULT_MODEL = 'deepseek-v4-flash';
|
|
69
69
|
|
|
70
70
|
// ADR-008 `effort` → pi `--thinking`. pi's ladder is off/minimal/low/medium/high/xhigh/max.
|
|
71
71
|
const THINKING = { none: 'off', off: 'off', minimal: 'minimal', low: 'low', medium: 'medium', high: 'high', xhigh: 'xhigh', max: 'max' };
|
|
@@ -390,7 +390,6 @@ const runPi = ({ args, cwd, env, payload, timeoutMs, credentials = [], spawnImpl
|
|
|
390
390
|
});
|
|
391
391
|
|
|
392
392
|
export default {
|
|
393
|
-
requiresModel: true,
|
|
394
393
|
name: 'pi',
|
|
395
394
|
|
|
396
395
|
// TASK-049: the variable this adapter needs from the environment of whatever
|
|
@@ -410,13 +409,12 @@ export default {
|
|
|
410
409
|
},
|
|
411
410
|
|
|
412
411
|
async spawn(prompt, ctx = {}) {
|
|
413
|
-
const seatModel = requireSeatModel(ctx.environment, 'pi');
|
|
414
412
|
// pi has no enforced sandbox. claude.js and codex.js refuse a public-trust
|
|
415
413
|
// seat they cannot confine; so does this adapter, and it refuses any declared
|
|
416
414
|
// sandbox mode rather than run unconfined under a spec that promised one.
|
|
417
415
|
assertNoSandboxDeclared(ctx.environment);
|
|
418
416
|
const provider = resolveProvider(ctx.environment);
|
|
419
|
-
const model =
|
|
417
|
+
const model = ctx.environment?.model || DEFAULT_MODEL;
|
|
420
418
|
const thinking = thinkingFor(ctx.environment?.effort);
|
|
421
419
|
const baseEnv = ctx.env || process.env;
|
|
422
420
|
if (!baseEnv[provider.apiKeyEnv]) {
|
package/src/lib/adapters/qwen.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/** Qwen Code 0.25.1 wrapper. Public turns have fresh HOME, config and keys. */
|
|
2
|
-
import { requireSeatModel } from './seat-model.js';
|
|
3
2
|
import { spawn as childSpawn, spawnSync } from 'child_process';
|
|
4
3
|
import { lstatSync, realpathSync } from 'fs';
|
|
5
4
|
import { chmod, mkdtemp, readFile, rm, writeFile } from 'fs/promises';
|
|
@@ -209,7 +208,6 @@ const runQwen = ({ cmd, args, cwd, env, timeoutMs, spawnImpl, credentials }) =>
|
|
|
209
208
|
});
|
|
210
209
|
|
|
211
210
|
export default {
|
|
212
|
-
requiresModel: true,
|
|
213
211
|
name: 'qwen',
|
|
214
212
|
runtimeType: 'qwen',
|
|
215
213
|
supportsProvider: true,
|
|
@@ -232,7 +230,6 @@ export default {
|
|
|
232
230
|
},
|
|
233
231
|
|
|
234
232
|
async spawn(prompt, ctx = {}) {
|
|
235
|
-
const seatModel = requireSeatModel(ctx.environment, 'qwen');
|
|
236
233
|
const sandbox = normalizeSandboxTrust(ctx.environment?.sandbox);
|
|
237
234
|
const isPublic = sandbox?.trust === 'public';
|
|
238
235
|
const mode = isPublic ? resolvePublicSandboxMode(sandbox) : null;
|
|
@@ -307,7 +304,7 @@ export default {
|
|
|
307
304
|
freshSession: true,
|
|
308
305
|
});
|
|
309
306
|
const args = [
|
|
310
|
-
'--bare', '--safe-mode', '--auth-type', 'openai', '-m',
|
|
307
|
+
'--bare', '--safe-mode', '--auth-type', 'openai', '-m', ctx.environment.model,
|
|
311
308
|
'--mcp-config', mcpPath, '--exclude-tools', [
|
|
312
309
|
...EXCLUDED_TOOLS, ...(isPublic ? PUBLIC_READ_TOOLS : []),
|
|
313
310
|
].join(','),
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/** A seat must choose its model independently of the operator's CLI defaults. */
|
|
2
|
-
export const requireSeatModel = (environment, adapterName) => {
|
|
3
|
-
const model = environment?.model;
|
|
4
|
-
if (typeof model !== 'string' || !model.trim()) {
|
|
5
|
-
const error = new Error(
|
|
6
|
-
`${adapterName} requires environment.model; set the seat model with commonly agent config <name> --model <model> before running`,
|
|
7
|
-
);
|
|
8
|
-
error.code = 'seat_model_missing';
|
|
9
|
-
throw error;
|
|
10
|
-
}
|
|
11
|
-
return model.trim();
|
|
12
|
-
};
|