agentsw 0.12.0 → 0.12.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 +3 -1
- package/dist/commands.js +5 -4
- package/dist/targets/codex.js +13 -11
- package/dist/targets/dsh.js +4 -2
- package/dist/targets/hermes.js +5 -3
- package/dist/targets/opencode.js +11 -9
- package/dist/targets/pistyle.js +1 -1
- package/dist/targets/workbuddy.js +3 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -325,7 +325,9 @@ Import still skips already configured accounts.
|
|
|
325
325
|
written once rather than once per provider: it gets the active provider when it can accept it, or the single
|
|
326
326
|
provider in the run that it can (Claude Code takes anthropic endpoints only, so an openai active provider does not
|
|
327
327
|
starve it). With several candidates and the active provider not among them the choice is yours, so the app keeps
|
|
328
|
-
pointing where it already does: syncing is not switching.
|
|
328
|
+
pointing where it already does: syncing is not switching. The same holds for an app that keeps a pointer of its
|
|
329
|
+
own — only the store's active provider may move it, so `sync -p other` writes that provider's block and models and
|
|
330
|
+
leaves the app's current model alone (`use` and `add` are what switch). A provider whose endpoint cannot be reached is reported
|
|
329
331
|
and skipped, the rest still sync, and the run exits non-zero.
|
|
330
332
|
- **Automatic lookup is not an automatic push:** enrichment updates saved metadata during add/quick/discover/import/refresh
|
|
331
333
|
and never writes agent configs by itself. `sync` is the push, and it refreshes first: it fetches the provider's model
|
package/dist/commands.js
CHANGED
|
@@ -801,9 +801,10 @@ function resolveProviderIds(store, opts, fallback) {
|
|
|
801
801
|
return ids;
|
|
802
802
|
}
|
|
803
803
|
/**
|
|
804
|
-
* Apps that name a single provider are written once (see `RunTargetsOptions.oneSlot`);
|
|
805
|
-
* the
|
|
806
|
-
* on the active provider and
|
|
804
|
+
* Apps that name a single provider are written once (see `RunTargetsOptions.oneSlot`); every other
|
|
805
|
+
* app only lets the store's active provider move its "current" pointer (see `ApplyOptions.keepSelection`),
|
|
806
|
+
* so a multi-provider sync finishes on the active provider and a run that does not include it leaves
|
|
807
|
+
* the pointer where the app already had it.
|
|
807
808
|
*/
|
|
808
809
|
function activeLast(store, ids) {
|
|
809
810
|
const active = store.active;
|
|
@@ -895,7 +896,7 @@ async function syncProviders(opts, sourceStore) {
|
|
|
895
896
|
}
|
|
896
897
|
}
|
|
897
898
|
out(`${t(opts.keepDefault ? "sync.syncingKeepDefault" : "sync.syncing", { id: pc.bold(id), model: provider.defaultModel })}\n`);
|
|
898
|
-
const outcome = await runWithOptionalDryRun("apply", provider, opts.apps, opts.dryRun, oneSlot, { keepDefault: opts.keepDefault });
|
|
899
|
+
const outcome = await runWithOptionalDryRun("apply", provider, opts.apps, opts.dryRun, oneSlot, { keepDefault: opts.keepDefault, keepSelection: provider.id !== store.active });
|
|
899
900
|
if (outcome.failed?.length)
|
|
900
901
|
failed.push(id);
|
|
901
902
|
if (refresh?.missing.length) {
|
package/dist/targets/codex.js
CHANGED
|
@@ -29,7 +29,7 @@ export const codex = transactionalTarget({
|
|
|
29
29
|
return [codexConfigFile(), codexAuthFile()];
|
|
30
30
|
},
|
|
31
31
|
detect: () => fs.existsSync(codexDir()),
|
|
32
|
-
async apply(provider) {
|
|
32
|
+
async apply(provider, options = {}) {
|
|
33
33
|
const configFile = codexConfigFile();
|
|
34
34
|
const authFile = codexAuthFile();
|
|
35
35
|
const notes = [];
|
|
@@ -42,16 +42,18 @@ export const codex = transactionalTarget({
|
|
|
42
42
|
if (config.model_providers !== undefined && !isJsonObject(config.model_providers)) {
|
|
43
43
|
throw new Error(`${configFile}: expected model_providers to be a table`);
|
|
44
44
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
45
|
+
if (!options.keepSelection) {
|
|
46
|
+
config.model_provider = provider.id;
|
|
47
|
+
config.model = provider.defaultModel;
|
|
48
|
+
const model = provider.models.find((m) => m.id === provider.defaultModel);
|
|
49
|
+
if (provider.reasoningEffort && model?.reasoning !== false) {
|
|
50
|
+
config.model_reasoning_effort = provider.reasoningEffort;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// The effort belongs to the active model: switching providers must not
|
|
54
|
+
// inherit the previous provider's level (prune treats it as owned too).
|
|
55
|
+
delete config.model_reasoning_effort;
|
|
56
|
+
}
|
|
55
57
|
}
|
|
56
58
|
// Codex only speaks the OpenAI Responses API (wire_api = "chat" was removed Feb 2026).
|
|
57
59
|
// requires_openai_auth = true makes Codex take the key from auth.json instead of an env var.
|
package/dist/targets/dsh.js
CHANGED
|
@@ -68,7 +68,7 @@ export const dsh = transactionalTarget({
|
|
|
68
68
|
return [dshSettingsFile(), dshCredentialsFile()];
|
|
69
69
|
},
|
|
70
70
|
detect: () => fs.existsSync(dshDir()),
|
|
71
|
-
async apply(provider) {
|
|
71
|
+
async apply(provider, options = {}) {
|
|
72
72
|
const notes = [];
|
|
73
73
|
const file = dshSettingsFile();
|
|
74
74
|
const doc = parseSettings(file);
|
|
@@ -117,7 +117,9 @@ export const dsh = transactionalTarget({
|
|
|
117
117
|
notes.push("dropped modelOverrides (llm-pi-ai refuses it beside an explicit models list)");
|
|
118
118
|
}
|
|
119
119
|
// The picker writes this section whole; a partial write would keep a stale reasoningEffort.
|
|
120
|
-
|
|
120
|
+
if (!options.keepSelection) {
|
|
121
|
+
doc.set("agent-default-model", doc.createNode({ provider: provider.id, model: provider.defaultModel }));
|
|
122
|
+
}
|
|
121
123
|
const referenced = credentialReferences(doc, provider.id);
|
|
122
124
|
const oldRef = typeof prev?.apiKeyEnv === "string" && isManagedCredentialRef(prev.apiKeyEnv, provider.id) && !referenced.has(prev.apiKeyEnv)
|
|
123
125
|
? prev.apiKeyEnv : undefined;
|
package/dist/targets/hermes.js
CHANGED
|
@@ -54,7 +54,7 @@ export const hermes = transactionalTarget({
|
|
|
54
54
|
protocols: ["openai", "anthropic"],
|
|
55
55
|
configPaths: [hermesConfigFile(), hermesEnvFile()],
|
|
56
56
|
detect: () => fs.existsSync(hermesHome()),
|
|
57
|
-
async apply(provider) {
|
|
57
|
+
async apply(provider, options = {}) {
|
|
58
58
|
const configFile = hermesConfigFile();
|
|
59
59
|
const envFile = hermesEnvFile();
|
|
60
60
|
const notes = [];
|
|
@@ -101,8 +101,10 @@ export const hermes = transactionalTarget({
|
|
|
101
101
|
else
|
|
102
102
|
doc.deleteIn([...modelAt, "context_length"]);
|
|
103
103
|
}
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
if (!options.keepSelection) {
|
|
105
|
+
doc.setIn(["model", "provider"], provider.id);
|
|
106
|
+
doc.setIn(["model", "default"], provider.defaultModel);
|
|
107
|
+
}
|
|
106
108
|
const envText = readTextIfExists(envFile) ?? "";
|
|
107
109
|
const assignments = envAssignments(envFile, envText);
|
|
108
110
|
const referenced = credentialReferences(doc, provider.id);
|
package/dist/targets/opencode.js
CHANGED
|
@@ -19,7 +19,7 @@ export const opencode = transactionalTarget({
|
|
|
19
19
|
},
|
|
20
20
|
detect: () => opencodeConfigFiles().some((file) => fs.existsSync(file)) ||
|
|
21
21
|
opencodeConfigDirs().some((dir) => fs.existsSync(dir)),
|
|
22
|
-
async apply(provider) {
|
|
22
|
+
async apply(provider, options = {}) {
|
|
23
23
|
const configFile = opencodePrimaryConfigFile();
|
|
24
24
|
const notes = [];
|
|
25
25
|
const existed = readTextIfExists(configFile) !== undefined;
|
|
@@ -94,14 +94,16 @@ export const opencode = transactionalTarget({
|
|
|
94
94
|
models,
|
|
95
95
|
};
|
|
96
96
|
config.provider = providerMap;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
97
|
+
if (!options.keepSelection) {
|
|
98
|
+
config.model = `${provider.id}/${provider.defaultModel}`;
|
|
99
|
+
if (provider.smallModel) {
|
|
100
|
+
config.small_model = `${provider.id}/${provider.smallModel}`;
|
|
101
|
+
}
|
|
102
|
+
else if (typeof config.small_model === "string" && config.small_model.startsWith(`${provider.id}/`)) {
|
|
103
|
+
// This provider's own previous small model is obsolete; another provider's
|
|
104
|
+
// entry stays untouched, exactly as prune scopes its cleanup.
|
|
105
|
+
delete config.small_model;
|
|
106
|
+
}
|
|
105
107
|
}
|
|
106
108
|
const backup = backupFile(configFile);
|
|
107
109
|
if (backup)
|
package/dist/targets/pistyle.js
CHANGED
|
@@ -106,7 +106,7 @@ export function piStyleTarget(opts) {
|
|
|
106
106
|
};
|
|
107
107
|
modelsConfig.providers = providers;
|
|
108
108
|
const modelsText = editJsoncObject(modelsDocument, modelsConfig);
|
|
109
|
-
const settingsText = options.keepDefault ? undefined : editJsoncObject(settingsDocument, {
|
|
109
|
+
const settingsText = options.keepDefault || options.keepSelection ? undefined : editJsoncObject(settingsDocument, {
|
|
110
110
|
...settingsDocument.value,
|
|
111
111
|
defaultProvider: provider.id,
|
|
112
112
|
defaultModel: provider.defaultModel,
|
|
@@ -79,7 +79,7 @@ export const workbuddy = transactionalTarget({
|
|
|
79
79
|
return [path.join(configDir(), "models.json"), path.join(configDir(), "settings.json")];
|
|
80
80
|
},
|
|
81
81
|
detect: () => fs.existsSync(configDir()),
|
|
82
|
-
async apply(provider) {
|
|
82
|
+
async apply(provider, options = {}) {
|
|
83
83
|
const dir = configDir();
|
|
84
84
|
const modelsFile = path.join(dir, "models.json");
|
|
85
85
|
const settingsFile = path.join(dir, "settings.json");
|
|
@@ -127,7 +127,8 @@ export const workbuddy = transactionalTarget({
|
|
|
127
127
|
const availableModels = [...new Set([
|
|
128
128
|
...existingAvailable.filter((id) => !removedIds.has(id) || keptIds.has(id)), ...ourIds,
|
|
129
129
|
])];
|
|
130
|
-
|
|
130
|
+
if (!options.keepSelection)
|
|
131
|
+
settings.model = provider.defaultModel;
|
|
131
132
|
const modelsBackup = backupFile(modelsFile);
|
|
132
133
|
if (modelsBackup)
|
|
133
134
|
notes.push(`backup: ${modelsBackup}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentsw",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "CLI provider switcher for coding agents: manage OpenAI/Anthropic-protocol providers in one place and sync them, with models.dev metadata, into Claude Code, Codex, omp, pi, prime-agent, opencode, Hermes, WorkBuddy and DeepSeek Harness",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|