@chrysb/alphaclaw 0.9.20 → 0.9.22
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/lib/public/dist/app.bundle.js +1179 -1179
- package/lib/public/js/components/models-tab/index.js +21 -23
- package/lib/public/js/components/models-tab/model-picker.js +24 -1
- package/lib/public/js/components/models-tab/use-models.js +11 -2
- package/lib/public/js/lib/model-config.js +22 -2
- package/lib/server/constants.js +4 -4
- package/lib/server/init/register-server-routes.js +2 -1
- package/lib/server/routes/codex.js +4 -0
- package/lib/server/routes/models.js +2 -0
- package/package.json +1 -1
|
@@ -13,13 +13,15 @@ import {
|
|
|
13
13
|
buildSyntheticModelEntry,
|
|
14
14
|
getModelCatalogProvider,
|
|
15
15
|
getModelsTabAuthProvider,
|
|
16
|
+
getModelsTabRequiredAuthProviders,
|
|
17
|
+
getProviderAuthDisplayOrder,
|
|
16
18
|
getProviderSortIndex,
|
|
17
19
|
SearchableModelPicker,
|
|
18
20
|
} from "./model-picker.js";
|
|
19
21
|
import { ProviderAuthCard } from "./provider-auth-card.js";
|
|
20
22
|
import {
|
|
21
23
|
getFeaturedModels,
|
|
22
|
-
|
|
24
|
+
withAlwaysAvailableModels,
|
|
23
25
|
} from "../../lib/model-config.js";
|
|
24
26
|
|
|
25
27
|
const html = htm.bind(h);
|
|
@@ -27,19 +29,13 @@ const html = htm.bind(h);
|
|
|
27
29
|
const deriveRequiredProviders = (configuredModels) => {
|
|
28
30
|
const providers = new Set();
|
|
29
31
|
for (const modelKey of Object.keys(configuredModels)) {
|
|
30
|
-
const provider
|
|
31
|
-
|
|
32
|
+
for (const provider of getModelsTabRequiredAuthProviders(modelKey)) {
|
|
33
|
+
providers.add(provider);
|
|
34
|
+
}
|
|
32
35
|
}
|
|
33
36
|
return [...providers];
|
|
34
37
|
};
|
|
35
38
|
|
|
36
|
-
const kProviderDisplayOrder = [
|
|
37
|
-
"anthropic",
|
|
38
|
-
"openai",
|
|
39
|
-
"openai-codex",
|
|
40
|
-
...kProviderOrder.filter((provider) => !["anthropic", "openai"].includes(provider)),
|
|
41
|
-
];
|
|
42
|
-
|
|
43
39
|
export const Models = ({ onRestartRequired = () => {}, agentId, embedded = false }) => {
|
|
44
40
|
const {
|
|
45
41
|
catalog,
|
|
@@ -70,14 +66,22 @@ export const Models = ({ onRestartRequired = () => {}, agentId, embedded = false
|
|
|
70
66
|
[configuredModels],
|
|
71
67
|
);
|
|
72
68
|
|
|
73
|
-
const
|
|
69
|
+
const selectableCatalog = useMemo(
|
|
70
|
+
() => withAlwaysAvailableModels(catalog),
|
|
71
|
+
[catalog],
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const featuredModels = useMemo(
|
|
75
|
+
() => getFeaturedModels(selectableCatalog),
|
|
76
|
+
[selectableCatalog],
|
|
77
|
+
);
|
|
74
78
|
const popularPickerModels = useMemo(
|
|
75
79
|
() => featuredModels.filter((model) => !configuredKeys.has(model.key)),
|
|
76
80
|
[featuredModels, configuredKeys],
|
|
77
81
|
);
|
|
78
82
|
|
|
79
83
|
const pickerModels = useMemo(() => {
|
|
80
|
-
return [...
|
|
84
|
+
return [...selectableCatalog]
|
|
81
85
|
.filter((model) => !configuredKeys.has(model.key))
|
|
82
86
|
.sort((a, b) => {
|
|
83
87
|
const providerCompare =
|
|
@@ -86,7 +90,7 @@ export const Models = ({ onRestartRequired = () => {}, agentId, embedded = false
|
|
|
86
90
|
if (providerCompare !== 0) return providerCompare;
|
|
87
91
|
return String(a.label || a.key).localeCompare(String(b.label || b.key));
|
|
88
92
|
});
|
|
89
|
-
}, [
|
|
93
|
+
}, [selectableCatalog, configuredKeys]);
|
|
90
94
|
|
|
91
95
|
const requiredProviders = useMemo(
|
|
92
96
|
() => deriveRequiredProviders(configuredModels),
|
|
@@ -94,14 +98,7 @@ export const Models = ({ onRestartRequired = () => {}, agentId, embedded = false
|
|
|
94
98
|
);
|
|
95
99
|
|
|
96
100
|
const sortedProviders = useMemo(() => {
|
|
97
|
-
|
|
98
|
-
for (const p of kProviderDisplayOrder) {
|
|
99
|
-
if (requiredProviders.includes(p)) ordered.push(p);
|
|
100
|
-
}
|
|
101
|
-
for (const p of requiredProviders) {
|
|
102
|
-
if (!ordered.includes(p)) ordered.push(p);
|
|
103
|
-
}
|
|
104
|
-
return ordered;
|
|
101
|
+
return getProviderAuthDisplayOrder(requiredProviders);
|
|
105
102
|
}, [requiredProviders]);
|
|
106
103
|
|
|
107
104
|
const providerHasAuth = useMemo(
|
|
@@ -113,7 +110,8 @@ export const Models = ({ onRestartRequired = () => {}, agentId, embedded = false
|
|
|
113
110
|
() =>
|
|
114
111
|
Object.keys(configuredModels).map((key) => {
|
|
115
112
|
const catalogEntry =
|
|
116
|
-
|
|
113
|
+
selectableCatalog.find((m) => m.key === key) ||
|
|
114
|
+
buildSyntheticModelEntry(key);
|
|
117
115
|
const provider = getModelsTabAuthProvider(key);
|
|
118
116
|
const hasAuth = !!providerHasAuth[provider];
|
|
119
117
|
return {
|
|
@@ -124,7 +122,7 @@ export const Models = ({ onRestartRequired = () => {}, agentId, embedded = false
|
|
|
124
122
|
hasAuth,
|
|
125
123
|
};
|
|
126
124
|
}),
|
|
127
|
-
[configuredModels,
|
|
125
|
+
[configuredModels, selectableCatalog, primary, providerHasAuth],
|
|
128
126
|
);
|
|
129
127
|
|
|
130
128
|
const headerActions = html`
|
|
@@ -19,10 +19,30 @@ const kProviderDisplayOrder = [
|
|
|
19
19
|
|
|
20
20
|
export const getModelsTabAuthProvider = (modelKey) => {
|
|
21
21
|
const provider = getModelProvider(modelKey);
|
|
22
|
-
if (provider === "openai
|
|
22
|
+
if (provider === "openai" || provider === "openai-codex") {
|
|
23
|
+
return "openai-codex";
|
|
24
|
+
}
|
|
23
25
|
return getAuthProviderFromModelProvider(provider);
|
|
24
26
|
};
|
|
25
27
|
|
|
28
|
+
export const getModelsTabRequiredAuthProviders = (modelKey) => {
|
|
29
|
+
const provider = getModelProvider(modelKey);
|
|
30
|
+
if (provider === "openai" || provider === "openai-codex") {
|
|
31
|
+
return ["openai", "openai-codex"];
|
|
32
|
+
}
|
|
33
|
+
const authProvider = getAuthProviderFromModelProvider(provider);
|
|
34
|
+
return authProvider ? [authProvider] : [];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const getProviderAuthDisplayOrder = (requiredProviders = []) => {
|
|
38
|
+
const required = new Set(["openai-codex", ...requiredProviders]);
|
|
39
|
+
const ordered = kProviderDisplayOrder.filter((provider) => required.has(provider));
|
|
40
|
+
for (const provider of required) {
|
|
41
|
+
if (!ordered.includes(provider)) ordered.push(provider);
|
|
42
|
+
}
|
|
43
|
+
return ordered;
|
|
44
|
+
};
|
|
45
|
+
|
|
26
46
|
export const getModelCatalogProvider = (model) =>
|
|
27
47
|
String(model?.provider || getModelProvider(model?.key)).trim();
|
|
28
48
|
|
|
@@ -88,6 +108,9 @@ export const buildProviderHasAuth = ({
|
|
|
88
108
|
if (codexStatus?.connected) {
|
|
89
109
|
result["openai-codex"] = true;
|
|
90
110
|
}
|
|
111
|
+
if (result.openai) {
|
|
112
|
+
result["openai-codex"] = true;
|
|
113
|
+
}
|
|
91
114
|
return result;
|
|
92
115
|
};
|
|
93
116
|
|
|
@@ -343,15 +343,24 @@ export const useModels = (agentId) => {
|
|
|
343
343
|
]);
|
|
344
344
|
|
|
345
345
|
const refreshCodexStatus = useCallback(async () => {
|
|
346
|
+
let codex;
|
|
346
347
|
try {
|
|
347
|
-
|
|
348
|
+
codex = await fetchCodexStatus();
|
|
348
349
|
setCodexStatus(codex || { connected: false });
|
|
349
350
|
updateCache({ codexStatus: codex || { connected: false } });
|
|
350
351
|
} catch {
|
|
351
352
|
setCodexStatus({ connected: false });
|
|
352
353
|
updateCache({ codexStatus: { connected: false } });
|
|
354
|
+
return;
|
|
353
355
|
}
|
|
354
|
-
|
|
356
|
+
try {
|
|
357
|
+
invalidateCache(kModelCatalogCacheKey);
|
|
358
|
+
const catalogResult = await catalogFetchState.refresh({ force: true });
|
|
359
|
+
applyCatalogResult(catalogResult);
|
|
360
|
+
} catch {
|
|
361
|
+
// Keep the successful auth status; catalog polling will retry discovery.
|
|
362
|
+
}
|
|
363
|
+
}, [applyCatalogResult, catalogFetchState, updateCache]);
|
|
355
364
|
|
|
356
365
|
return {
|
|
357
366
|
catalog,
|
|
@@ -27,11 +27,14 @@ export const kFeaturedModelDefs = [
|
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
label: "Codex 5.3",
|
|
30
|
-
preferredKeys: [
|
|
30
|
+
preferredKeys: [
|
|
31
|
+
"openai/gpt-5.3-codex",
|
|
32
|
+
"openai-codex/gpt-5.3-codex",
|
|
33
|
+
],
|
|
31
34
|
},
|
|
32
35
|
{
|
|
33
36
|
label: "GPT-5.5",
|
|
34
|
-
preferredKeys: ["openai-codex/gpt-5.5"],
|
|
37
|
+
preferredKeys: ["openai/gpt-5.5", "openai-codex/gpt-5.5"],
|
|
35
38
|
},
|
|
36
39
|
{
|
|
37
40
|
label: "Gemini 3.1 Pro",
|
|
@@ -39,6 +42,23 @@ export const kFeaturedModelDefs = [
|
|
|
39
42
|
},
|
|
40
43
|
];
|
|
41
44
|
|
|
45
|
+
export const kAlwaysAvailableModelDefs = [
|
|
46
|
+
{
|
|
47
|
+
key: "openai/gpt-5.5",
|
|
48
|
+
provider: "openai",
|
|
49
|
+
label: "GPT-5.5",
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
export const withAlwaysAvailableModels = (models = []) => {
|
|
54
|
+
const merged = [...models];
|
|
55
|
+
const keys = new Set(merged.map((model) => model?.key));
|
|
56
|
+
for (const model of kAlwaysAvailableModelDefs) {
|
|
57
|
+
if (!keys.has(model.key)) merged.push(model);
|
|
58
|
+
}
|
|
59
|
+
return merged;
|
|
60
|
+
};
|
|
61
|
+
|
|
42
62
|
export const getFeaturedModels = (allModels) => {
|
|
43
63
|
const picked = [];
|
|
44
64
|
const used = new Set();
|
package/lib/server/constants.js
CHANGED
|
@@ -173,13 +173,13 @@ const kMinimalFallbackOnboardingModels = [
|
|
|
173
173
|
label: "Claude Haiku 4.6",
|
|
174
174
|
},
|
|
175
175
|
{
|
|
176
|
-
key: "openai
|
|
177
|
-
provider: "openai
|
|
176
|
+
key: "openai/gpt-5.5",
|
|
177
|
+
provider: "openai",
|
|
178
178
|
label: "GPT-5.5",
|
|
179
179
|
},
|
|
180
180
|
{
|
|
181
|
-
key: "openai
|
|
182
|
-
provider: "openai
|
|
181
|
+
key: "openai/gpt-5.3-codex",
|
|
182
|
+
provider: "openai",
|
|
183
183
|
label: "Codex GPT-5.3",
|
|
184
184
|
},
|
|
185
185
|
{
|
|
@@ -97,7 +97,7 @@ const registerServerRoutes = ({
|
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
registerPageRoutes({ app, requireAuth, isGatewayRunning });
|
|
100
|
-
registerModelRoutes({
|
|
100
|
+
const modelCatalogCache = registerModelRoutes({
|
|
101
101
|
app,
|
|
102
102
|
shellCmd,
|
|
103
103
|
gatewayEnv,
|
|
@@ -150,6 +150,7 @@ const registerServerRoutes = ({
|
|
|
150
150
|
parseCodexAuthorizationInput,
|
|
151
151
|
getCodexAccountId,
|
|
152
152
|
authProfiles,
|
|
153
|
+
onAuthChanged: () => modelCatalogCache.markStale(),
|
|
153
154
|
});
|
|
154
155
|
registerGoogleRoutes({
|
|
155
156
|
app,
|
|
@@ -29,6 +29,7 @@ const registerCodexRoutes = ({
|
|
|
29
29
|
parseCodexAuthorizationInput,
|
|
30
30
|
getCodexAccountId,
|
|
31
31
|
authProfiles,
|
|
32
|
+
onAuthChanged = () => {},
|
|
32
33
|
}) => {
|
|
33
34
|
const { kCodexOauthStates, cleanupCodexOauthStates } = createCodexOauthState();
|
|
34
35
|
|
|
@@ -123,6 +124,7 @@ const registerCodexRoutes = ({
|
|
|
123
124
|
const accountId = getCodexAccountId(access);
|
|
124
125
|
|
|
125
126
|
authProfiles.upsertCodexProfile({ access, refresh, expires, accountId });
|
|
127
|
+
onAuthChanged();
|
|
126
128
|
|
|
127
129
|
return res.send(`<!DOCTYPE html><html><body><script>
|
|
128
130
|
window.opener?.postMessage({ codex: 'success' }, '*');
|
|
@@ -186,6 +188,7 @@ const registerCodexRoutes = ({
|
|
|
186
188
|
const expires = Date.now() + Number(json.expires_in) * 1000;
|
|
187
189
|
const accountId = getCodexAccountId(access);
|
|
188
190
|
authProfiles.upsertCodexProfile({ access, refresh, expires, accountId });
|
|
191
|
+
onAuthChanged();
|
|
189
192
|
return res.json({ ok: true });
|
|
190
193
|
} catch (err) {
|
|
191
194
|
console.error("[codex] Manual exchange error:", err);
|
|
@@ -197,6 +200,7 @@ const registerCodexRoutes = ({
|
|
|
197
200
|
|
|
198
201
|
app.post("/api/codex/disconnect", (req, res) => {
|
|
199
202
|
const changed = authProfiles.removeCodexProfiles();
|
|
203
|
+
if (changed) onAuthChanged();
|
|
200
204
|
res.json({ ok: true, changed });
|
|
201
205
|
});
|
|
202
206
|
};
|