@ordewell/core 0.10.3 → 0.10.4
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/{IFileSystem-DCd-rkeH.d.ts → IFileSystem-_effm8-b.d.ts} +1 -1
- package/dist/{IFileSystem-B8Nkgg4e.d.mts → IFileSystem-vyqMdL-x.d.mts} +1 -1
- package/dist/{IRunner-CXdYyIZo.d.mts → IRunner-D_UkkMbJ.d.ts} +1 -1
- package/dist/{IRunner-QBdYcatb.d.ts → IRunner-NtTHQgLR.d.mts} +1 -1
- package/dist/{ModeResolver-BOU90Nn-.d.ts → ModeResolver-Dy3Ef6p-.d.ts} +1 -1
- package/dist/{ModeResolver-geqjKkLY.d.mts → ModeResolver-wnTFsDnF.d.mts} +1 -1
- package/dist/{Task-CRVIqSfy.d.mts → Task-DZs9eKgg.d.mts} +1 -1
- package/dist/{Task-CRVIqSfy.d.ts → Task-DZs9eKgg.d.ts} +1 -1
- package/dist/index.d.mts +21 -12
- package/dist/index.d.ts +21 -12
- package/dist/index.js +113 -27
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +113 -27
- package/dist/index.mjs.map +1 -1
- package/dist/parsing.d.mts +2 -2
- package/dist/parsing.d.ts +2 -2
- package/dist/{plan-utils-KU1Rse82.d.mts → plan-utils-CtKceSsQ.d.mts} +3 -3
- package/dist/{plan-utils-oC8bO4pN.d.ts → plan-utils-POIz5d8z.d.ts} +3 -3
- package/dist/plan-utils.d.mts +4 -4
- package/dist/plan-utils.d.ts +4 -4
- package/dist/testing.d.mts +3 -3
- package/dist/testing.d.ts +3 -3
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -6406,7 +6406,7 @@ var CODEX_MANIFEST = {
|
|
|
6406
6406
|
}
|
|
6407
6407
|
},
|
|
6408
6408
|
modelDiscovery: {
|
|
6409
|
-
// Codex has no `codex models` subcommand (see
|
|
6409
|
+
// Codex has no `codex models` subcommand (see ADR-0004). Discovery
|
|
6410
6410
|
// tries three sources in order, each falling through to the next:
|
|
6411
6411
|
//
|
|
6412
6412
|
// 1. `codex app-server` stdio JSON-RPC (`initialize` → `model/list`) —
|
|
@@ -6508,9 +6508,11 @@ function parseOpenCodeModelsVerbose(stdout, manifest) {
|
|
|
6508
6508
|
variants: variantIds.map((id) => ({ id, label: id.charAt(0).toUpperCase() + id.slice(1) }))
|
|
6509
6509
|
});
|
|
6510
6510
|
}
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6511
|
+
return preferredFirst(models, manifest);
|
|
6512
|
+
}
|
|
6513
|
+
function preferredFirst(models, manifest) {
|
|
6514
|
+
const prefOrder = manifest.modelDiscovery.preferredPatterns?.map((p) => p.id) ?? [];
|
|
6515
|
+
return [...models].sort((a, b) => {
|
|
6514
6516
|
const ai = prefOrder.indexOf(a.modelId);
|
|
6515
6517
|
const bi = prefOrder.indexOf(b.modelId);
|
|
6516
6518
|
if (ai >= 0 && bi >= 0) return ai - bi;
|
|
@@ -6518,7 +6520,36 @@ function parseOpenCodeModelsVerbose(stdout, manifest) {
|
|
|
6518
6520
|
if (bi >= 0) return 1;
|
|
6519
6521
|
return a.modelId.localeCompare(b.modelId);
|
|
6520
6522
|
});
|
|
6521
|
-
|
|
6523
|
+
}
|
|
6524
|
+
function parseOpenCodeModelsApi(stdout, manifest) {
|
|
6525
|
+
let data;
|
|
6526
|
+
try {
|
|
6527
|
+
data = JSON.parse(stdout)?.data;
|
|
6528
|
+
} catch {
|
|
6529
|
+
return [];
|
|
6530
|
+
}
|
|
6531
|
+
if (!Array.isArray(data)) return [];
|
|
6532
|
+
const prefLabels = new Map((manifest.modelDiscovery.preferredPatterns ?? []).map((p) => [p.id, p.label]));
|
|
6533
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6534
|
+
const models = [];
|
|
6535
|
+
for (const entry of data) {
|
|
6536
|
+
if (!entry || typeof entry.providerID !== "string" || typeof entry.modelID !== "string") continue;
|
|
6537
|
+
if (entry.enabled === false) continue;
|
|
6538
|
+
const fullId = `${entry.providerID}/${entry.modelID}`;
|
|
6539
|
+
if (seen.has(fullId)) continue;
|
|
6540
|
+
seen.add(fullId);
|
|
6541
|
+
const variantIds = Array.isArray(entry.variants) ? entry.variants.flatMap((v) => {
|
|
6542
|
+
const id = v?.id;
|
|
6543
|
+
return typeof id === "string" && id ? [id] : [];
|
|
6544
|
+
}) : [];
|
|
6545
|
+
models.push({
|
|
6546
|
+
modelId: fullId,
|
|
6547
|
+
modelLabel: prefLabels.get(fullId) || typeof entry.name === "string" && entry.name || entry.modelID,
|
|
6548
|
+
runnerProvider: entry.providerID,
|
|
6549
|
+
variants: variantIds.map((id) => ({ id, label: id.charAt(0).toUpperCase() + id.slice(1) }))
|
|
6550
|
+
});
|
|
6551
|
+
}
|
|
6552
|
+
return preferredFirst(models, manifest);
|
|
6522
6553
|
}
|
|
6523
6554
|
|
|
6524
6555
|
// src/plugins/builtin/opencode.manifest.ts
|
|
@@ -6534,13 +6565,17 @@ var OPENCODE_MANIFEST = {
|
|
|
6534
6565
|
modelDiscovery: {
|
|
6535
6566
|
method: "command",
|
|
6536
6567
|
discoveryCommands: [
|
|
6568
|
+
// v1 prints per-model variants under --verbose; v2 rejects the flag (a
|
|
6569
|
+
// fast non-zero exit) and serves the same catalog, variants included, over
|
|
6570
|
+
// `api model.list`. v1 is asked first so it never reaches the `api` form.
|
|
6537
6571
|
{ command: "opencode", args: ["models", "--verbose"], parser: parseOpenCodeModelsVerbose },
|
|
6572
|
+
{ command: "opencode", args: ["api", "model.list"], parser: parseOpenCodeModelsApi },
|
|
6538
6573
|
{ command: "opencode", args: ["models"], parser: parseOpenCodeModels }
|
|
6539
6574
|
],
|
|
6540
6575
|
// No fallbackModels: the list must always reflect what `opencode models`
|
|
6541
6576
|
// actually reports for THIS user (their configured providers only). A
|
|
6542
6577
|
// hardcoded fallback previously leaked models the user didn't have.
|
|
6543
|
-
// No static variants — per-model variants
|
|
6578
|
+
// No static variants — per-model variants come from the first two commands above
|
|
6544
6579
|
providerQualifiedIds: true
|
|
6545
6580
|
},
|
|
6546
6581
|
contextFile: "AGENTS.md",
|
|
@@ -14059,6 +14094,7 @@ function parseCodexModelsCache(content) {
|
|
|
14059
14094
|
}
|
|
14060
14095
|
}
|
|
14061
14096
|
var GEMINI_MODELS_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
14097
|
+
var NEGATIVE_TTL_MS = 6e4;
|
|
14062
14098
|
function geminiDiscoveryCacheKey(apiKey) {
|
|
14063
14099
|
const dir = globalDataDir();
|
|
14064
14100
|
const hash = apiKey.slice(-8);
|
|
@@ -14188,26 +14224,33 @@ async function discoverFromApi(manifest, config, fetchImpl) {
|
|
|
14188
14224
|
return null;
|
|
14189
14225
|
}
|
|
14190
14226
|
}
|
|
14227
|
+
function wasKilled(err) {
|
|
14228
|
+
return !!err && typeof err === "object" && err.killed === true;
|
|
14229
|
+
}
|
|
14191
14230
|
async function discoverFromCommand(manifest, execImpl) {
|
|
14192
14231
|
const discovery = manifest.modelDiscovery;
|
|
14193
14232
|
const commands = discovery.discoveryCommands ?? [
|
|
14194
14233
|
{ command: discovery.command, args: discovery.args || [], parser: discovery.parser }
|
|
14195
14234
|
];
|
|
14196
14235
|
const runCommands = async () => {
|
|
14236
|
+
let timedOut2 = false;
|
|
14197
14237
|
for (const cmd of commands) {
|
|
14198
14238
|
try {
|
|
14199
14239
|
const { stdout } = await execImpl(`${cmd.command} ${cmd.args.join(" ")}`, { timeout: 45e3 });
|
|
14200
14240
|
const models = parseModelOutput(stdout, cmd.parser, manifest);
|
|
14201
|
-
if (models.length > 0) return applyVariants(mergeCanonicalAliases(models, manifest), manifest);
|
|
14202
|
-
} catch {
|
|
14241
|
+
if (models.length > 0) return { models: applyVariants(mergeCanonicalAliases(models, manifest), manifest), timedOut: timedOut2 };
|
|
14242
|
+
} catch (err) {
|
|
14243
|
+
if (wasKilled(err)) timedOut2 = true;
|
|
14203
14244
|
}
|
|
14204
14245
|
}
|
|
14205
|
-
return null;
|
|
14246
|
+
return { models: null, timedOut: timedOut2 };
|
|
14206
14247
|
};
|
|
14207
14248
|
const first = await runCommands();
|
|
14208
|
-
if (first) return { models: first, fromFallback: false };
|
|
14209
|
-
|
|
14210
|
-
|
|
14249
|
+
if (first.models) return { models: first.models, fromFallback: false };
|
|
14250
|
+
if (first.timedOut) {
|
|
14251
|
+
const second = await runCommands();
|
|
14252
|
+
if (second.models) return { models: second.models, fromFallback: false };
|
|
14253
|
+
}
|
|
14211
14254
|
return { models: applyVariants(buildFallbackModels(manifest), manifest), fromFallback: true };
|
|
14212
14255
|
}
|
|
14213
14256
|
function mergeCanonicalAliases(discovered, manifest) {
|
|
@@ -14244,16 +14287,33 @@ function parseLineByLine(stdout) {
|
|
|
14244
14287
|
}
|
|
14245
14288
|
var ModelDiscovery = class {
|
|
14246
14289
|
cache = /* @__PURE__ */ new Map();
|
|
14290
|
+
/**
|
|
14291
|
+
* Degraded results (a fallback list, or empty) remembered for
|
|
14292
|
+
* {@link NEGATIVE_TTL_MS}. They are deliberately not cached — a transient
|
|
14293
|
+
* failure must heal — but re-running a failing CLI on every lookup is the
|
|
14294
|
+
* other extreme.
|
|
14295
|
+
*/
|
|
14296
|
+
misses = /* @__PURE__ */ new Map();
|
|
14297
|
+
/**
|
|
14298
|
+
* Discoveries still running, so a second lookup of the same runner joins the
|
|
14299
|
+
* first instead of spawning the CLI again. A slow CLI is the case this
|
|
14300
|
+
* exists for: a planner switch and a runner-list refresh land inside one
|
|
14301
|
+
* another's wait, and two `opencode models` calls race each other for the
|
|
14302
|
+
* same background service.
|
|
14303
|
+
*/
|
|
14304
|
+
inflight = /* @__PURE__ */ new Map();
|
|
14247
14305
|
registry;
|
|
14248
14306
|
execImpl;
|
|
14249
14307
|
fetchImpl;
|
|
14250
14308
|
appServerClient;
|
|
14251
14309
|
readFileImpl;
|
|
14252
|
-
|
|
14310
|
+
now;
|
|
14311
|
+
constructor(registry, execImpl = defaultExec2, fetchImpl, appServerClient = defaultAppServerClient, readFileImpl, now = Date.now) {
|
|
14253
14312
|
this.registry = registry;
|
|
14254
14313
|
this.execImpl = execImpl;
|
|
14255
14314
|
this.fetchImpl = fetchImpl;
|
|
14256
14315
|
this.appServerClient = appServerClient;
|
|
14316
|
+
this.now = now;
|
|
14257
14317
|
this.readFileImpl = readFileImpl ?? ((filePath) => {
|
|
14258
14318
|
try {
|
|
14259
14319
|
return fsSync3.readFileSync(filePath.replace(/^~/, osMod.homedir()), "utf8");
|
|
@@ -14297,10 +14357,20 @@ var ModelDiscovery = class {
|
|
|
14297
14357
|
const runnerLabel = manifest.displayName || runner;
|
|
14298
14358
|
return models.map((m) => ({ ...m, runnerId: runner, runnerLabel }));
|
|
14299
14359
|
}
|
|
14300
|
-
|
|
14301
|
-
|
|
14302
|
-
|
|
14303
|
-
|
|
14360
|
+
discoverRaw(runner) {
|
|
14361
|
+
const cached2 = this.cache.get(runner);
|
|
14362
|
+
if (cached2) return Promise.resolve(cached2);
|
|
14363
|
+
const remembered = this.misses.get(runner);
|
|
14364
|
+
if (remembered && this.now() - remembered.at < NEGATIVE_TTL_MS) return Promise.resolve(remembered.models);
|
|
14365
|
+
const running = this.inflight.get(runner);
|
|
14366
|
+
if (running) return running;
|
|
14367
|
+
const started = this.discoverUncached(runner).finally(() => {
|
|
14368
|
+
if (this.inflight.get(runner) === started) this.inflight.delete(runner);
|
|
14369
|
+
});
|
|
14370
|
+
this.inflight.set(runner, started);
|
|
14371
|
+
return started;
|
|
14372
|
+
}
|
|
14373
|
+
async discoverUncached(runner) {
|
|
14304
14374
|
const manifest = this.registry.getManifest(runner);
|
|
14305
14375
|
if (!manifest) {
|
|
14306
14376
|
return [];
|
|
@@ -14332,10 +14402,13 @@ var ModelDiscovery = class {
|
|
|
14332
14402
|
models = buildFallbackModels(manifest);
|
|
14333
14403
|
}
|
|
14334
14404
|
if (cacheable && models.length > 0) this.cache.set(runner, models);
|
|
14405
|
+
else this.misses.set(runner, { models, at: this.now() });
|
|
14335
14406
|
return models;
|
|
14336
14407
|
}
|
|
14337
14408
|
clear() {
|
|
14338
14409
|
this.cache.clear();
|
|
14410
|
+
this.misses.clear();
|
|
14411
|
+
this.inflight.clear();
|
|
14339
14412
|
}
|
|
14340
14413
|
/** Whatever `discover()` has already cached for `runner` — never triggers discovery. */
|
|
14341
14414
|
getCached(runner) {
|
|
@@ -25021,15 +25094,15 @@ var ModelResolver = class {
|
|
|
25021
25094
|
return toOrchestratorOptions({}, ORCHESTRATOR_SHORTCUTS);
|
|
25022
25095
|
}
|
|
25023
25096
|
async modelsForRunners(runners) {
|
|
25024
|
-
const
|
|
25025
|
-
|
|
25097
|
+
const unique = [...new Set(runners)];
|
|
25098
|
+
const discovered = await Promise.all(unique.map(async (runner) => {
|
|
25026
25099
|
try {
|
|
25027
|
-
|
|
25100
|
+
return [runner, await this.discovery.discover(runner)];
|
|
25028
25101
|
} catch {
|
|
25029
|
-
|
|
25102
|
+
return [runner, []];
|
|
25030
25103
|
}
|
|
25031
|
-
}
|
|
25032
|
-
return
|
|
25104
|
+
}));
|
|
25105
|
+
return Object.fromEntries(discovered);
|
|
25033
25106
|
}
|
|
25034
25107
|
async pickerOptions() {
|
|
25035
25108
|
if (this.cachedPickerOptions) return this.cachedPickerOptions;
|
|
@@ -25116,24 +25189,28 @@ var defaultExec3 = async (command, options) => {
|
|
|
25116
25189
|
return { stdout: String(stdout) };
|
|
25117
25190
|
};
|
|
25118
25191
|
var CHECK_TIMEOUT_MS = 8e3;
|
|
25192
|
+
var NEGATIVE_TTL_MS2 = 6e4;
|
|
25119
25193
|
var RunnerInstallation = class {
|
|
25120
25194
|
cache = /* @__PURE__ */ new Map();
|
|
25121
25195
|
inflight = /* @__PURE__ */ new Map();
|
|
25122
25196
|
registry;
|
|
25123
25197
|
execImpl;
|
|
25124
|
-
|
|
25198
|
+
now;
|
|
25199
|
+
constructor(registry, execImpl = defaultExec3, now = Date.now) {
|
|
25125
25200
|
this.registry = registry;
|
|
25126
25201
|
this.execImpl = execImpl;
|
|
25202
|
+
this.now = now;
|
|
25127
25203
|
}
|
|
25128
25204
|
/** True if the runner's CLI responds to `--version`. Cached per process. */
|
|
25129
25205
|
async isInstalled(runner) {
|
|
25130
|
-
|
|
25206
|
+
const cached2 = this.cache.get(runner);
|
|
25207
|
+
if (cached2 && (cached2.installed || this.now() - cached2.at < NEGATIVE_TTL_MS2)) return cached2.installed;
|
|
25131
25208
|
const existing = this.inflight.get(runner);
|
|
25132
25209
|
if (existing) return existing;
|
|
25133
25210
|
const manifest = this.registry.getManifest(runner);
|
|
25134
25211
|
const command = manifest?.runner.command;
|
|
25135
25212
|
if (!command) {
|
|
25136
|
-
this.cache.set(runner, false);
|
|
25213
|
+
this.cache.set(runner, { installed: false, at: this.now() });
|
|
25137
25214
|
return false;
|
|
25138
25215
|
}
|
|
25139
25216
|
const probe = (async () => {
|
|
@@ -25144,13 +25221,22 @@ var RunnerInstallation = class {
|
|
|
25144
25221
|
return false;
|
|
25145
25222
|
}
|
|
25146
25223
|
})().then((installed) => {
|
|
25147
|
-
this.cache.set(runner, installed);
|
|
25224
|
+
this.cache.set(runner, { installed, at: this.now() });
|
|
25148
25225
|
this.inflight.delete(runner);
|
|
25149
25226
|
return installed;
|
|
25150
25227
|
});
|
|
25151
25228
|
this.inflight.set(runner, probe);
|
|
25152
25229
|
return probe;
|
|
25153
25230
|
}
|
|
25231
|
+
/**
|
|
25232
|
+
* Forget cached "not installed" verdicts so the next probe re-runs them. A
|
|
25233
|
+
* runner-list refresh calls this, so a CLI installed while the host runs is
|
|
25234
|
+
* offered without a restart. An installed verdict stays: it cannot have
|
|
25235
|
+
* changed without the binary going away, and re-probing one costs a spawn.
|
|
25236
|
+
*/
|
|
25237
|
+
refresh() {
|
|
25238
|
+
for (const [runner, probe] of this.cache) if (!probe.installed) this.cache.delete(runner);
|
|
25239
|
+
}
|
|
25154
25240
|
/**
|
|
25155
25241
|
* Whether this runner can serve as a harness planner (ADR-0009, T9), and why
|
|
25156
25242
|
* not when it cannot. Surfaces call this to grey out an unusable agent in the
|