theclawbay 0.3.66 → 0.3.68
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/dist/commands/logout.js +2 -2
- package/dist/commands/setup.js +8 -5
- package/dist/lib/codex-auth-seeding.js +7 -6
- package/dist/lib/codex-desktop-model-picker.js +2 -2
- package/dist/lib/codex-model-cache-migration.js +105 -174
- package/dist/lib/codex-model-catalog.d.ts +5 -0
- package/dist/lib/codex-model-catalog.js +46 -0
- package/package.json +2 -1
- package/theclawbay-codex-model-catalog.json +644 -0
package/dist/commands/logout.js
CHANGED
|
@@ -1548,10 +1548,10 @@ class LogoutCommand extends base_command_1.BaseCommand {
|
|
|
1548
1548
|
this.log("- Codex login state: no cleanup needed.");
|
|
1549
1549
|
}
|
|
1550
1550
|
if (modelCacheCleanup.action === "removed") {
|
|
1551
|
-
this.log("- Codex model cache: removed the Claw Bay
|
|
1551
|
+
this.log("- Codex model cache: removed the Claw Bay managed model catalog.");
|
|
1552
1552
|
}
|
|
1553
1553
|
else if (modelCacheCleanup.action === "preserved") {
|
|
1554
|
-
this.log("- Codex model cache: preserved an existing
|
|
1554
|
+
this.log("- Codex model cache: preserved an existing model catalog entry.");
|
|
1555
1555
|
}
|
|
1556
1556
|
else if (modelCacheCleanup.warning) {
|
|
1557
1557
|
this.log(`- Codex model cache: ${modelCacheCleanup.warning}`);
|
package/dist/commands/setup.js
CHANGED
|
@@ -3240,11 +3240,14 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3240
3240
|
summaryNotes.add(authSeedResult.warning);
|
|
3241
3241
|
if (authSeedResult &&
|
|
3242
3242
|
["seeded", "updated", "already_seeded"].includes(authSeedResult.action)) {
|
|
3243
|
-
summaryNotes.add("Codex desktop clients were pinned to
|
|
3243
|
+
summaryNotes.add("Codex desktop clients were pinned to the local The Claw Bay API-key auth path while the desktop picker compatibility patches keep current VS Code and Codex app builds on the The Claw Bay model catalog.");
|
|
3244
3244
|
}
|
|
3245
3245
|
if (desktopModelPickerMigration?.action === "patched") {
|
|
3246
3246
|
summaryNotes.add("Desktop model pickers were refreshed so current VS Code and Codex app builds stop labeling supported The Claw Bay models like GPT-5.5 as Custom.");
|
|
3247
3247
|
}
|
|
3248
|
+
if (selectedSetupClients.has("codex")) {
|
|
3249
|
+
summaryNotes.add("If Codex updates later, rerun `theclawbay setup` once to refresh its local model catalog.");
|
|
3250
|
+
}
|
|
3248
3251
|
if (selectedSetupClients.has("codex") && !migrateCodexConversations) {
|
|
3249
3252
|
summaryNotes.add("Left existing Codex conversations untouched.");
|
|
3250
3253
|
}
|
|
@@ -3357,14 +3360,14 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3357
3360
|
}
|
|
3358
3361
|
if (authSeedResult?.action === "seeded") {
|
|
3359
3362
|
this.log(authSeedResult.replacedExistingAuth
|
|
3360
|
-
? "- Codex login state: backed up the existing Codex auth and switched local desktop auth to the Claw Bay
|
|
3361
|
-
: "- Codex login state: seeded local desktop auth in the Claw Bay
|
|
3363
|
+
? "- Codex login state: backed up the existing Codex auth and switched local desktop auth back to the Claw Bay API-key mode."
|
|
3364
|
+
: "- Codex login state: seeded local desktop auth in the Claw Bay API-key mode.");
|
|
3362
3365
|
}
|
|
3363
3366
|
else if (authSeedResult?.action === "updated") {
|
|
3364
|
-
this.log("- Codex login state: refreshed the local The Claw Bay
|
|
3367
|
+
this.log("- Codex login state: refreshed the local The Claw Bay API-key auth seed.");
|
|
3365
3368
|
}
|
|
3366
3369
|
else if (authSeedResult?.action === "already_seeded") {
|
|
3367
|
-
this.log("- Codex login state: local desktop auth was already pinned to the Claw Bay
|
|
3370
|
+
this.log("- Codex login state: local desktop auth was already pinned to the Claw Bay API-key mode.");
|
|
3368
3371
|
}
|
|
3369
3372
|
else if (authSeedResult?.warning) {
|
|
3370
3373
|
this.log(`- Codex login state: ${authSeedResult.warning}`);
|
|
@@ -244,12 +244,13 @@ async function ensureCodexApiKeyAuth(params) {
|
|
|
244
244
|
});
|
|
245
245
|
}
|
|
246
246
|
async function ensureCodexUsageLimitAuth(params) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
247
|
+
// Current desktop Codex builds treat chatgptAuthTokens as real ChatGPT web
|
|
248
|
+
// auth and can trigger upstream plugin sync calls against chatgpt.com. With
|
|
249
|
+
// The Claw Bay, that can wedge the desktop startup path behind Cloudflare
|
|
250
|
+
// challenges and leave Codex / VS Code stuck on splash. Keep desktop auth on
|
|
251
|
+
// the local API-key path and rely on the managed config + picker patches for
|
|
252
|
+
// model catalog compatibility instead.
|
|
253
|
+
return ensureCodexApiKeyAuth(params);
|
|
253
254
|
}
|
|
254
255
|
async function cleanupSeededCodexAuth(params) {
|
|
255
256
|
const authPath = node_path_1.default.join(params.codexHome, AUTH_FILE);
|
|
@@ -9,8 +9,8 @@ const promises_1 = __importDefault(require("node:fs/promises"));
|
|
|
9
9
|
const node_os_1 = __importDefault(require("node:os"));
|
|
10
10
|
const node_path_1 = __importDefault(require("node:path"));
|
|
11
11
|
const paths_1 = require("./config/paths");
|
|
12
|
-
const
|
|
13
|
-
const DESKTOP_MODEL_IDS = Array.from(new Set((0,
|
|
12
|
+
const codex_model_catalog_1 = require("./codex-model-catalog");
|
|
13
|
+
const DESKTOP_MODEL_IDS = Array.from(new Set((0, codex_model_catalog_1.getVisibleHardcodedCodexModelIds)()));
|
|
14
14
|
const STATSIG_MODEL_PICKER_CONFIG_ID = "107580212";
|
|
15
15
|
function uniqueStrings(values) {
|
|
16
16
|
return Array.from(new Set(values.filter((value) => Boolean(value))));
|
|
@@ -10,36 +10,22 @@ const promises_1 = __importDefault(require("node:fs/promises"));
|
|
|
10
10
|
const node_path_1 = __importDefault(require("node:path"));
|
|
11
11
|
const node_child_process_1 = require("node:child_process");
|
|
12
12
|
const node_os_1 = __importDefault(require("node:os"));
|
|
13
|
+
const codex_model_catalog_1 = require("./codex-model-catalog");
|
|
13
14
|
const supported_models_1 = require("./supported-models");
|
|
14
15
|
const MODELS_CACHE_FILE = "models_cache.json";
|
|
15
16
|
const MODELS_CACHE_STATE_FILE = "theclawbay.models-cache.json";
|
|
16
17
|
const STATE_DB_FILE_PATTERN = /^state_\d+\.sqlite$/;
|
|
17
|
-
const
|
|
18
|
+
const CATALOG_MODELS = (0, codex_model_catalog_1.getHardcodedCodexModelCatalog)();
|
|
19
|
+
const CATALOG_MODEL_IDS = (0, codex_model_catalog_1.getHardcodedCodexModelIds)();
|
|
18
20
|
const LEGACY_REMOVED_MODEL_IDS = (0, supported_models_1.getLegacyRemovedModelIds)();
|
|
19
|
-
const
|
|
20
|
-
const TRACKED_MODEL_ID_SET = new Set([...
|
|
21
|
+
const CATALOG_MODEL_ID_SET = new Set(CATALOG_MODEL_IDS);
|
|
22
|
+
const TRACKED_MODEL_ID_SET = new Set([...CATALOG_MODEL_IDS, ...LEGACY_REMOVED_MODEL_IDS]);
|
|
21
23
|
const LEGACY_REMOVED_MODEL_ID_SET = new Set(LEGACY_REMOVED_MODEL_IDS);
|
|
22
24
|
const SEED_MARKER_KEY = "_theclawbay_seeded";
|
|
23
25
|
// Older releases stored the model id as the marker value; accept those so cleanup still works.
|
|
24
26
|
const SEED_MARKER_VALUE = "theclawbay";
|
|
25
27
|
const LEGACY_SEED_MARKER_VALUES = new Set([...TRACKED_MODEL_ID_SET, SEED_MARKER_VALUE, true]);
|
|
26
|
-
const
|
|
27
|
-
const SUPPORTED_MODEL_CONFIG = new Map(SUPPORTED_MODELS.map((model) => [model.id, model]));
|
|
28
|
-
const TEMPLATE_MODEL_IDS = TARGET_MODEL_IDS;
|
|
29
|
-
const DEFAULT_REASONING_LEVELS = [
|
|
30
|
-
{ effort: "low", description: "Fast responses with lighter reasoning" },
|
|
31
|
-
{ effort: "medium", description: "Balances speed and reasoning depth for everyday tasks" },
|
|
32
|
-
{ effort: "high", description: "Greater reasoning depth for complex problems" },
|
|
33
|
-
{ effort: "xhigh", description: "Extra high reasoning depth for complex problems" },
|
|
34
|
-
];
|
|
35
|
-
const FALLBACK_BASE_INSTRUCTIONS = `You are Codex, a coding agent based on GPT-5. You and the user share the same workspace and collaborate to achieve the user's goals.
|
|
36
|
-
|
|
37
|
-
## General
|
|
38
|
-
|
|
39
|
-
- Prefer rg or rg --files for search when available.
|
|
40
|
-
- Make safe, minimal code changes that preserve user work.
|
|
41
|
-
- Explain what changed and any remaining risk clearly.`;
|
|
42
|
-
const SEEDED_CACHE_FRESHNESS_YEARS = 10;
|
|
28
|
+
const SEEDED_CACHE_FRESHNESS_ISO = "2099-12-31T23:59:59.000Z";
|
|
43
29
|
function objectRecordOr(value) {
|
|
44
30
|
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
45
31
|
return value;
|
|
@@ -148,7 +134,7 @@ async function readPatchState(statePath) {
|
|
|
148
134
|
}
|
|
149
135
|
async function writePatchState(statePath, fingerprints) {
|
|
150
136
|
await promises_1.default.mkdir(node_path_1.default.dirname(statePath), { recursive: true });
|
|
151
|
-
const models =
|
|
137
|
+
const models = CATALOG_MODEL_IDS.flatMap((modelId) => {
|
|
152
138
|
const fingerprint = fingerprints[modelId];
|
|
153
139
|
if (!fingerprint)
|
|
154
140
|
return [];
|
|
@@ -166,93 +152,43 @@ function findModel(models, slug) {
|
|
|
166
152
|
function hasSeedMarker(model) {
|
|
167
153
|
return LEGACY_SEED_MARKER_VALUES.has(model[SEED_MARKER_KEY]);
|
|
168
154
|
}
|
|
169
|
-
function
|
|
155
|
+
function stripSeedMarker(model) {
|
|
156
|
+
if (!(SEED_MARKER_KEY in model))
|
|
157
|
+
return cloneJson(model);
|
|
170
158
|
const next = cloneJson(model);
|
|
171
|
-
next[SEED_MARKER_KEY]
|
|
159
|
+
delete next[SEED_MARKER_KEY];
|
|
172
160
|
return next;
|
|
173
161
|
}
|
|
174
|
-
function
|
|
175
|
-
return
|
|
162
|
+
function buildCatalogModels() {
|
|
163
|
+
return cloneJson(CATALOG_MODELS).map((model) => stripSeedMarker(model));
|
|
176
164
|
}
|
|
177
|
-
function
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
seed.description = seedDescription(modelId);
|
|
183
|
-
if (typeof seed.default_reasoning_level !== "string") {
|
|
184
|
-
seed.default_reasoning_level = "medium";
|
|
185
|
-
}
|
|
186
|
-
if (!Array.isArray(seed.supported_reasoning_levels) || seed.supported_reasoning_levels.length === 0) {
|
|
187
|
-
seed.supported_reasoning_levels = cloneJson(DEFAULT_REASONING_LEVELS);
|
|
188
|
-
}
|
|
189
|
-
if (typeof seed.shell_type !== "string") {
|
|
190
|
-
seed.shell_type = "shell_command";
|
|
191
|
-
}
|
|
192
|
-
seed.visibility = "list";
|
|
193
|
-
seed.supported_in_api = true;
|
|
194
|
-
seed.priority = 0;
|
|
195
|
-
seed.upgrade = null;
|
|
196
|
-
if (typeof seed.base_instructions !== "string" || !seed.base_instructions.trim()) {
|
|
197
|
-
seed.base_instructions = FALLBACK_BASE_INSTRUCTIONS;
|
|
198
|
-
}
|
|
199
|
-
if (typeof seed.supports_reasoning_summaries !== "boolean") {
|
|
200
|
-
seed.supports_reasoning_summaries = true;
|
|
201
|
-
}
|
|
202
|
-
if (typeof seed.support_verbosity !== "boolean") {
|
|
203
|
-
seed.support_verbosity = true;
|
|
204
|
-
}
|
|
205
|
-
if (seed.default_verbosity === undefined) {
|
|
206
|
-
seed.default_verbosity = "low";
|
|
207
|
-
}
|
|
208
|
-
if (seed.apply_patch_tool_type === undefined) {
|
|
209
|
-
seed.apply_patch_tool_type = "freeform";
|
|
210
|
-
}
|
|
211
|
-
const truncationPolicy = objectRecordOr(seed.truncation_policy);
|
|
212
|
-
if (!truncationPolicy || typeof truncationPolicy.mode !== "string" || typeof truncationPolicy.limit !== "number") {
|
|
213
|
-
seed.truncation_policy = { mode: "tokens", limit: 10000 };
|
|
214
|
-
}
|
|
215
|
-
if (typeof seed.supports_parallel_tool_calls !== "boolean") {
|
|
216
|
-
seed.supports_parallel_tool_calls = true;
|
|
217
|
-
}
|
|
218
|
-
if (typeof seed.context_window !== "number") {
|
|
219
|
-
seed.context_window = 272000;
|
|
220
|
-
}
|
|
221
|
-
if (typeof seed.effective_context_window_percent !== "number") {
|
|
222
|
-
seed.effective_context_window_percent = 95;
|
|
223
|
-
}
|
|
224
|
-
if (!Array.isArray(seed.experimental_supported_tools)) {
|
|
225
|
-
seed.experimental_supported_tools = [];
|
|
226
|
-
}
|
|
227
|
-
if (!Array.isArray(seed.input_modalities) || seed.input_modalities.length === 0) {
|
|
228
|
-
seed.input_modalities = ["text", "image"];
|
|
229
|
-
}
|
|
230
|
-
if (typeof seed.prefer_websockets !== "boolean") {
|
|
231
|
-
seed.prefer_websockets = true;
|
|
232
|
-
}
|
|
233
|
-
return seed;
|
|
165
|
+
function buildCatalogModelMap() {
|
|
166
|
+
return new Map(buildCatalogModels().flatMap((model) => {
|
|
167
|
+
const slug = typeof model.slug === "string" ? model.slug : "";
|
|
168
|
+
return slug ? [[slug, model]] : [];
|
|
169
|
+
}));
|
|
234
170
|
}
|
|
235
|
-
function
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
return normalizeSeedModel(null, modelId);
|
|
171
|
+
function sameFingerprintMaps(left, right) {
|
|
172
|
+
const leftKeys = Object.keys(left).sort();
|
|
173
|
+
const rightKeys = Object.keys(right).sort();
|
|
174
|
+
if (leftKeys.length !== rightKeys.length)
|
|
175
|
+
return false;
|
|
176
|
+
return leftKeys.every((key, index) => key === rightKeys[index] && left[key] === right[key]);
|
|
242
177
|
}
|
|
243
|
-
function
|
|
244
|
-
return models.some((model) =>
|
|
178
|
+
function hasCatalogModels(models) {
|
|
179
|
+
return models.some((model) => {
|
|
180
|
+
const slug = typeof model.slug === "string" ? model.slug : "";
|
|
181
|
+
return Boolean(slug) && CATALOG_MODEL_ID_SET.has(slug);
|
|
182
|
+
});
|
|
245
183
|
}
|
|
246
184
|
function nextFetchedAtIsoForDocument(doc) {
|
|
247
|
-
if (!
|
|
185
|
+
if (!hasCatalogModels(doc.models)) {
|
|
248
186
|
return new Date().toISOString();
|
|
249
187
|
}
|
|
250
|
-
// Current
|
|
251
|
-
// catalogs in API-key mode
|
|
252
|
-
//
|
|
253
|
-
|
|
254
|
-
next.setUTCFullYear(next.getUTCFullYear() + SEEDED_CACHE_FRESHNESS_YEARS);
|
|
255
|
-
return next.toISOString();
|
|
188
|
+
// Current Codex builds only consult models_cache.json for custom-provider
|
|
189
|
+
// catalogs in API-key mode. Pin the cache freshness far into the future so
|
|
190
|
+
// setup can refresh the catalog on demand without the five-minute TTL.
|
|
191
|
+
return SEEDED_CACHE_FRESHNESS_ISO;
|
|
256
192
|
}
|
|
257
193
|
function setCacheFreshnessMetadata(doc, clientVersion) {
|
|
258
194
|
let changed = false;
|
|
@@ -562,22 +498,22 @@ async function ensureCodexModelCacheHasGpt54(params) {
|
|
|
562
498
|
try {
|
|
563
499
|
const existingState = await readPatchState(statePath);
|
|
564
500
|
const parsed = await readJsonIfExists(cachePath);
|
|
501
|
+
const catalogModels = buildCatalogModels();
|
|
502
|
+
const catalogModelMap = buildCatalogModelMap();
|
|
565
503
|
if (parsed === null) {
|
|
566
504
|
const clientVersion = await inferCodexClientVersion(params.codexHome);
|
|
567
505
|
if (!clientVersion) {
|
|
568
506
|
await removeFileIfExists(statePath);
|
|
569
507
|
return {
|
|
570
508
|
action: "skipped",
|
|
571
|
-
warning: "Codex models cache was not found, and Codex version could not be inferred for a safe The Claw Bay model
|
|
509
|
+
warning: "Codex models cache was not found, and Codex version could not be inferred for a safe The Claw Bay model catalog refresh.",
|
|
572
510
|
};
|
|
573
511
|
}
|
|
574
|
-
const docModels =
|
|
575
|
-
const nextState = {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
nextState[modelId] = fingerprintModel(seed);
|
|
580
|
-
}
|
|
512
|
+
const docModels = cloneJson(catalogModels);
|
|
513
|
+
const nextState = Object.fromEntries(docModels.flatMap((model) => {
|
|
514
|
+
const slug = typeof model.slug === "string" ? model.slug : "";
|
|
515
|
+
return slug ? [[slug, fingerprintModel(model)]] : [];
|
|
516
|
+
}));
|
|
581
517
|
const doc = {
|
|
582
518
|
fetched_at: nextFetchedAtIsoForDocument({ models: docModels }),
|
|
583
519
|
client_version: clientVersion,
|
|
@@ -592,105 +528,92 @@ async function ensureCodexModelCacheHasGpt54(params) {
|
|
|
592
528
|
if (!doc) {
|
|
593
529
|
return {
|
|
594
530
|
action: "skipped",
|
|
595
|
-
warning: "Codex models cache exists but is not valid JSON in the expected format; skipped The Claw Bay model
|
|
531
|
+
warning: "Codex models cache exists but is not valid JSON in the expected format; skipped The Claw Bay model catalog refresh.",
|
|
596
532
|
};
|
|
597
533
|
}
|
|
598
534
|
const clientVersion = (await inferCodexClientVersion(params.codexHome)) ??
|
|
599
535
|
(typeof doc.client_version === "string" && doc.client_version ? doc.client_version : null);
|
|
600
536
|
let changed = false;
|
|
601
537
|
let seeded = false;
|
|
602
|
-
|
|
603
|
-
const
|
|
604
|
-
const
|
|
605
|
-
doc.models = doc.models.filter((entry) => {
|
|
538
|
+
const currentCatalogEntries = new Map();
|
|
539
|
+
const rest = [];
|
|
540
|
+
for (const entry of doc.models) {
|
|
606
541
|
const slug = typeof entry.slug === "string" ? entry.slug : "";
|
|
607
|
-
if (!slug
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
for (const modelId of TARGET_MODEL_IDS) {
|
|
619
|
-
const existingModel = findModel(doc.models, modelId);
|
|
620
|
-
const trackedFingerprint = existingState[modelId];
|
|
621
|
-
if (existingModel) {
|
|
622
|
-
const currentFingerprint = fingerprintModel(existingModel);
|
|
623
|
-
if (hasSeedMarker(existingModel)) {
|
|
624
|
-
if (!trackedFingerprint || trackedFingerprint !== currentFingerprint) {
|
|
625
|
-
nextState[modelId] = currentFingerprint;
|
|
626
|
-
stateChanged = true;
|
|
627
|
-
}
|
|
628
|
-
continue;
|
|
542
|
+
if (!slug) {
|
|
543
|
+
rest.push(entry);
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
if (LEGACY_REMOVED_MODEL_ID_SET.has(slug) && hasSeedMarker(entry)) {
|
|
547
|
+
changed = true;
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
if (CATALOG_MODEL_ID_SET.has(slug)) {
|
|
551
|
+
if (!currentCatalogEntries.has(slug)) {
|
|
552
|
+
currentCatalogEntries.set(slug, entry);
|
|
629
553
|
}
|
|
630
|
-
|
|
631
|
-
const seededModel = applySeedMarker(existingModel);
|
|
632
|
-
doc.models = doc.models.map((entry) => (entry.slug === modelId ? seededModel : entry));
|
|
633
|
-
nextState[modelId] = fingerprintModel(seededModel);
|
|
634
|
-
seeded = true;
|
|
554
|
+
else {
|
|
635
555
|
changed = true;
|
|
636
|
-
stateChanged = true;
|
|
637
|
-
continue;
|
|
638
|
-
}
|
|
639
|
-
if (trackedFingerprint && trackedFingerprint !== currentFingerprint) {
|
|
640
|
-
delete nextState[modelId];
|
|
641
|
-
stateChanged = true;
|
|
642
556
|
}
|
|
643
557
|
continue;
|
|
644
558
|
}
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
stateChanged = true;
|
|
559
|
+
const normalized = stripSeedMarker(entry);
|
|
560
|
+
if (fingerprintModel(normalized) !== fingerprintModel(entry)) {
|
|
561
|
+
changed = true;
|
|
562
|
+
}
|
|
563
|
+
rest.push(normalized);
|
|
651
564
|
}
|
|
652
|
-
|
|
653
|
-
const
|
|
654
|
-
const
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
565
|
+
const orderedCatalog = [];
|
|
566
|
+
const nextState = {};
|
|
567
|
+
for (const modelId of CATALOG_MODEL_IDS) {
|
|
568
|
+
const desiredModel = catalogModelMap.get(modelId);
|
|
569
|
+
if (!desiredModel)
|
|
570
|
+
continue;
|
|
571
|
+
const desiredFingerprint = fingerprintModel(desiredModel);
|
|
572
|
+
const trackedFingerprint = existingState[modelId];
|
|
573
|
+
const existingModel = currentCatalogEntries.get(modelId);
|
|
574
|
+
if (!existingModel) {
|
|
575
|
+
orderedCatalog.push(cloneJson(desiredModel));
|
|
576
|
+
nextState[modelId] = desiredFingerprint;
|
|
577
|
+
changed = true;
|
|
578
|
+
seeded = true;
|
|
659
579
|
continue;
|
|
660
580
|
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
581
|
+
const normalizedExisting = stripSeedMarker(existingModel);
|
|
582
|
+
const existingFingerprint = fingerprintModel(normalizedExisting);
|
|
583
|
+
if (existingFingerprint === desiredFingerprint && !hasSeedMarker(existingModel)) {
|
|
584
|
+
orderedCatalog.push(normalizedExisting);
|
|
585
|
+
if (trackedFingerprint === desiredFingerprint) {
|
|
586
|
+
nextState[modelId] = trackedFingerprint;
|
|
587
|
+
}
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
orderedCatalog.push(cloneJson(desiredModel));
|
|
591
|
+
nextState[modelId] = desiredFingerprint;
|
|
592
|
+
changed = true;
|
|
593
|
+
seeded = true;
|
|
668
594
|
}
|
|
669
|
-
doc.models = [...
|
|
595
|
+
doc.models = [...orderedCatalog, ...rest];
|
|
670
596
|
if (setCacheFreshnessMetadata(doc, clientVersion)) {
|
|
671
597
|
changed = true;
|
|
672
598
|
}
|
|
599
|
+
const stateChanged = !sameFingerprintMaps(existingState, nextState);
|
|
673
600
|
if (changed) {
|
|
674
601
|
await promises_1.default.writeFile(cachePath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
|
|
675
602
|
}
|
|
676
|
-
const hasAnyTracked =
|
|
603
|
+
const hasAnyTracked = CATALOG_MODEL_IDS.some((id) => Boolean(nextState[id]));
|
|
677
604
|
if (!hasAnyTracked) {
|
|
678
605
|
if (Object.keys(existingState).length > 0) {
|
|
679
606
|
await removeFileIfExists(statePath);
|
|
680
607
|
}
|
|
681
608
|
}
|
|
682
|
-
else if (stateChanged
|
|
609
|
+
else if (stateChanged) {
|
|
683
610
|
await writePatchState(statePath, nextState);
|
|
684
611
|
}
|
|
685
612
|
if (seeded)
|
|
686
613
|
return { action: "seeded" };
|
|
687
614
|
if (changed || stateChanged)
|
|
688
615
|
return { action: "refreshed" };
|
|
689
|
-
|
|
690
|
-
const model = findModel(doc.models, id);
|
|
691
|
-
return Boolean(model && hasSeedMarker(model));
|
|
692
|
-
});
|
|
693
|
-
return { action: allSeeded ? "already_seeded" : "already_present" };
|
|
616
|
+
return { action: hasAnyTracked ? "already_seeded" : "already_present" };
|
|
694
617
|
}
|
|
695
618
|
catch (error) {
|
|
696
619
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -724,9 +647,17 @@ async function cleanupSeededCodexModelCache(params) {
|
|
|
724
647
|
let preserved = 0;
|
|
725
648
|
doc.models = doc.models.filter((entry) => {
|
|
726
649
|
const slug = typeof entry.slug === "string" ? entry.slug : "";
|
|
727
|
-
if (!slug
|
|
650
|
+
if (!slug)
|
|
651
|
+
return true;
|
|
652
|
+
if (LEGACY_REMOVED_MODEL_ID_SET.has(slug) && hasSeedMarker(entry)) {
|
|
653
|
+
removed += 1;
|
|
654
|
+
return false;
|
|
655
|
+
}
|
|
656
|
+
const trackedFingerprint = state[slug];
|
|
657
|
+
if (!trackedFingerprint)
|
|
728
658
|
return true;
|
|
729
|
-
|
|
659
|
+
const normalized = stripSeedMarker(entry);
|
|
660
|
+
if (fingerprintModel(normalized) !== trackedFingerprint) {
|
|
730
661
|
preserved += 1;
|
|
731
662
|
return true;
|
|
732
663
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getHardcodedCodexModelCatalog = getHardcodedCodexModelCatalog;
|
|
7
|
+
exports.getHardcodedCodexModelIds = getHardcodedCodexModelIds;
|
|
8
|
+
exports.getVisibleHardcodedCodexModelIds = getVisibleHardcodedCodexModelIds;
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const node_fs_1 = require("node:fs");
|
|
11
|
+
function configPath() {
|
|
12
|
+
return node_path_1.default.resolve(__dirname, "..", "..", "theclawbay-codex-model-catalog.json");
|
|
13
|
+
}
|
|
14
|
+
function parseCodexModelCatalog(raw) {
|
|
15
|
+
const parsed = JSON.parse(raw);
|
|
16
|
+
if (!Array.isArray(parsed)) {
|
|
17
|
+
throw new Error("codex model catalog must be an array");
|
|
18
|
+
}
|
|
19
|
+
return parsed.map((entry) => {
|
|
20
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
21
|
+
throw new Error("codex model catalog contains an invalid entry");
|
|
22
|
+
}
|
|
23
|
+
return entry;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function cloneJson(value) {
|
|
27
|
+
return JSON.parse(JSON.stringify(value));
|
|
28
|
+
}
|
|
29
|
+
let cachedCatalog = null;
|
|
30
|
+
function getHardcodedCodexModelCatalog() {
|
|
31
|
+
if (!cachedCatalog) {
|
|
32
|
+
cachedCatalog = parseCodexModelCatalog((0, node_fs_1.readFileSync)(configPath(), "utf8"));
|
|
33
|
+
}
|
|
34
|
+
return cloneJson(cachedCatalog);
|
|
35
|
+
}
|
|
36
|
+
function getHardcodedCodexModelIds() {
|
|
37
|
+
return getHardcodedCodexModelCatalog()
|
|
38
|
+
.map((model) => (typeof model.slug === "string" ? model.slug.trim() : ""))
|
|
39
|
+
.filter(Boolean);
|
|
40
|
+
}
|
|
41
|
+
function getVisibleHardcodedCodexModelIds() {
|
|
42
|
+
return getHardcodedCodexModelCatalog()
|
|
43
|
+
.filter((model) => model.visibility === "list")
|
|
44
|
+
.map((model) => (typeof model.slug === "string" ? model.slug.trim() : ""))
|
|
45
|
+
.filter(Boolean);
|
|
46
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "theclawbay",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.68",
|
|
4
4
|
"description": "CLI for connecting Codex, Continue, Cline, GSD, OpenClaw, OpenCode, Kilo, Roo Code, Aider, experimental Trae, and experimental Zo to The Claw Bay.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"dist",
|
|
30
|
+
"theclawbay-codex-model-catalog.json",
|
|
30
31
|
"theclawbay-supported-models.json",
|
|
31
32
|
"README.md",
|
|
32
33
|
"LICENSE"
|