@jmanuelcorral/openteam 0.24.0 → 0.24.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.
Files changed (42) hide show
  1. package/README.es.md +7 -1
  2. package/README.md +6 -1
  3. package/dist/certificates/graph-release-certificate.json +2 -2
  4. package/dist/certificates/graph-shadow-certificate.json +2 -2
  5. package/dist/cli/setupAdapters.d.ts +2 -2
  6. package/dist/cli/setupAdapters.d.ts.map +1 -1
  7. package/dist/cli.js +826 -298
  8. package/dist/commands/agents.d.ts +6 -4
  9. package/dist/commands/agents.d.ts.map +1 -1
  10. package/dist/commands/dispatch.d.ts +1 -1
  11. package/dist/commands/dispatch.d.ts.map +1 -1
  12. package/dist/commands/setup.d.ts +22 -14
  13. package/dist/commands/setup.d.ts.map +1 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +990 -281
  16. package/dist/local/lemonade.d.ts.map +1 -1
  17. package/dist/local/lemonadeRequestGuard.d.ts +11 -0
  18. package/dist/local/lemonadeRequestGuard.d.ts.map +1 -0
  19. package/dist/local/lemonadeResidency.d.ts +22 -0
  20. package/dist/local/lemonadeResidency.d.ts.map +1 -0
  21. package/dist/local/modelResidency.d.ts +4 -0
  22. package/dist/local/modelResidency.d.ts.map +1 -0
  23. package/dist/local/slotPool.d.ts +13 -7
  24. package/dist/local/slotPool.d.ts.map +1 -1
  25. package/dist/messages/executionSetup.d.ts +19 -0
  26. package/dist/messages/executionSetup.d.ts.map +1 -1
  27. package/dist/messages/modelResidency.d.ts +19 -0
  28. package/dist/messages/modelResidency.d.ts.map +1 -0
  29. package/dist/orchestrator/coordinator.d.ts.map +1 -1
  30. package/dist/orchestrator/runtimeSelection.d.ts +4 -3
  31. package/dist/orchestrator/runtimeSelection.d.ts.map +1 -1
  32. package/dist/plugin/availability.d.ts +4 -1
  33. package/dist/plugin/availability.d.ts.map +1 -1
  34. package/dist/plugin/hooks.d.ts +2 -0
  35. package/dist/plugin/hooks.d.ts.map +1 -1
  36. package/dist/plugin/memoryTool.d.ts +9 -3
  37. package/dist/plugin/memoryTool.d.ts.map +1 -1
  38. package/dist/plugin/modelResidency.d.ts +47 -0
  39. package/dist/plugin/modelResidency.d.ts.map +1 -0
  40. package/dist/router/types.d.ts +2 -0
  41. package/dist/router/types.d.ts.map +1 -1
  42. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5743,7 +5743,7 @@ import { z as z15 } from "zod";
5743
5743
  // package.json
5744
5744
  var package_default = {
5745
5745
  name: "@jmanuelcorral/openteam",
5746
- version: "0.24.0",
5746
+ version: "0.24.1",
5747
5747
  packageManager: "bun@1.3.14",
5748
5748
  description: "Cost-aware, local-first routing plugin for opencode with cheapest-capable frontier fallback and multi-agent orchestration.",
5749
5749
  license: "MIT",
@@ -6100,6 +6100,25 @@ var executionSetupMessages = {
6100
6100
  `),
6101
6101
  localOnlyTitle: "Local execution",
6102
6102
  localRequiredError: "local execution requires an enabled local runtime",
6103
+ lemonadeDetectedHint: (loaded, advertised) => `detected - ${loaded} confirmed loaded of ${advertised} advertised text model(s)`,
6104
+ lemonadeNoLoadedModels: "Lemonade has no text models verified as loaded and ready. Keep the intended model active in Lemonade and rerun setup; inactive or unknown models cannot be selected or entered manually.",
6105
+ lemonadeModelNotLoaded: (model) => `Lemonade model "${model}" is not positively verified as loaded and ready. Keep that exact text model active and rerun setup; no substitute was selected and no implicit loading is allowed.`,
6106
+ lemonadeProbeRequired: "Lemonade setup requires a fresh read-only residency probe before writing configuration. Use the CLI with its runtime probe enabled; manual model IDs cannot bypass this requirement.",
6107
+ lemonadeProbeFailed: "Lemonade residency could not be verified at the configured endpoint. Check connectivity and the read-only /models, /health, and /internal/aliases responses, then rerun setup with the intended text models already active.",
6108
+ lemonadeEndpointMismatch: "Lemonade endpoint/provider mapping differs from the selected runtime. Reconcile the configured base URL and provider before rerunning setup; no model was substituted.",
6109
+ lemonadeModelIdentityUnknown: (model) => `Lemonade model "${model}" has no usable registered wire identity in the effective opencode configuration. Fix its model declaration before rerunning setup; setup will not replace or guess an alias.`,
6110
+ lemonadeEffectiveConfigLabel: "effective setup configuration",
6111
+ lemonadeEffectiveConfigAmbiguous: "Cannot establish one effective openteam configuration from the configured plugin loaders. Reconcile their options before rerunning setup; no provider identity was guessed.",
6112
+ lemonadeRetainedProviderUnprotected: (providerID) => `Cannot safely keep retained Lemonade provider "${providerID}": the effective configuration must retain one matching Lemonade runtime, disabled when deselected. Reconcile the plugin options or machine overlay, or explicitly remove the provider registration before rerunning setup; no configuration was written.`,
6113
+ lemonadeV2InvalidProvider: (providerID) => `Lemonade provider ${JSON.stringify(providerID)} cannot be represented as an exact native V2 policy resource. Choose a non-empty provider ID without wildcards, slashes, backslashes, or whitespace; setup will not broaden a deny rule.`,
6114
+ lemonadeV2InvalidPolicies: "Cannot safely preserve experimental.policies: experimental must be an object and policies must be an array of provider.use statements with a string resource and allow/deny effect. Fix the project configuration before rerunning setup.",
6115
+ lemonadeV2Title: "Lemonade transport compatibility",
6116
+ lemonadeV2Restriction: (providers) => `Project policies disable native V2 Lemonade access for: ${providers.join(", ")}. Ordinary guarded V1 configuration remains supported; V2 is not an openteam-hook execution path. Higher-precedence or global policies can override this project restriction; it is not a server-atomic no-autoload guarantee.`,
6117
+ lemonadeInventory: (instanceID, providerID, models) => {
6118
+ const inventory = models.map((model) => `${model.modelID} (${model.loaded === true ? "loaded" : model.loaded === false ? "inactive" : "residency unknown"})`).join(", ");
6119
+ return `Lemonade inventory ${instanceID} (provider ${providerID}): ${inventory || "no advertised text models"}. Only confirmed loaded text models count as ready.`;
6120
+ },
6121
+ lemonadeAgentResidency: (agent, model, state) => `Lemonade readiness: ${agent} (${model}): ${state === "not-loaded" ? "inactive (not ready)" : "residency unknown"}; advertised inventory is not loaded readiness. Keep this exact model active and verify residency before use; requests without verified readiness are blocked.`,
6103
6122
  mixedPrimaryQuestion: "Primary coordinator model",
6104
6123
  mixedPrimaryLocal: (model) => `Use local thinking model ${model}`,
6105
6124
  mixedPrimaryFrontier: "Choose a frontier model",
@@ -9931,6 +9950,243 @@ function ensureFoundryV1BaseURL(endpoint) {
9931
9950
  }
9932
9951
  }
9933
9952
 
9953
+ // src/local/lemonadeResidency.ts
9954
+ import { z as z19 } from "zod";
9955
+
9956
+ // src/messages/modelResidency.ts
9957
+ var reasons = {
9958
+ unknown: "fresh residency metadata is unavailable, malformed, or ambiguous",
9959
+ inactive: "the requested model is not verified as resident and serving",
9960
+ identity: "the requested model identity can be rewritten or is ambiguous",
9961
+ destination: "the request destination does not match its configured runtime",
9962
+ transport: "this provider execution path cannot enforce the residency guard",
9963
+ request: "this is not a supported, explicit model inference request",
9964
+ cancelled: "the request was cancelled before residency could be verified",
9965
+ timeout: "the residency metadata deadline expired",
9966
+ configuration: "the residency guard configuration is invalid"
9967
+ };
9968
+ var modelResidencyMessages = {
9969
+ blocked: (reason) => `[openteam] Lemonade model request blocked: ${reasons[reason]}.`,
9970
+ providerDisabled: (providerID) => `[openteam] Lemonade provider "${providerID}" is disabled because its configured transport or runtime mapping cannot enforce loaded-only requests.`,
9971
+ extractionRuntimeUnavailable: "[openteam] Memory extraction requires one enabled local runtime matching the configured extraction provider."
9972
+ };
9973
+
9974
+ // src/local/lemonadeResidency.ts
9975
+ class ModelResidencyError extends Error {
9976
+ code;
9977
+ statusCode = 400;
9978
+ isRetryable = false;
9979
+ constructor(code) {
9980
+ super(modelResidencyMessages.blocked(code));
9981
+ this.code = code;
9982
+ this.name = "ModelResidencyError";
9983
+ }
9984
+ }
9985
+ var modelName = z19.string().min(1).refine((name) => name === name.trim());
9986
+ var LoadedModelSchema = z19.object({
9987
+ model_name: modelName,
9988
+ loaded: z19.boolean().optional(),
9989
+ status: z19.string().optional(),
9990
+ backend_alive: z19.boolean().optional(),
9991
+ backend_health: z19.string().optional(),
9992
+ watchdog_reset: z19.boolean().optional(),
9993
+ watchdog_reset_reason: z19.string().optional(),
9994
+ residency_class: z19.string().optional(),
9995
+ slot_pool: z19.string().optional(),
9996
+ checkpoint: z19.string().optional(),
9997
+ type: z19.string().optional(),
9998
+ device: z19.string().optional(),
9999
+ backend_url: z19.string().optional(),
10000
+ pid: z19.number().int().optional(),
10001
+ launch_command: z19.unknown().optional(),
10002
+ pinned: z19.boolean().optional(),
10003
+ recipe: z19.string().optional(),
10004
+ recipe_options: z19.unknown().optional(),
10005
+ is_busy: z19.boolean().optional(),
10006
+ is_streaming: z19.boolean().optional(),
10007
+ max_context_window: z19.number().optional(),
10008
+ cost_input_per_million: z19.number().optional(),
10009
+ cost_output_per_million: z19.number().optional(),
10010
+ last_use: z19.number().optional()
10011
+ }).strict();
10012
+ var TelemetrySchema = z19.object({
10013
+ enabled: z19.boolean(),
10014
+ captures: z19.array(z19.string()).optional()
10015
+ }).strict();
10016
+ var HealthSchema = z19.object({
10017
+ status: z19.literal("ok"),
10018
+ all_models_loaded: z19.array(LoadedModelSchema),
10019
+ version: z19.string().optional(),
10020
+ model_loaded: z19.string().nullable().optional(),
10021
+ telemetry: TelemetrySchema.optional(),
10022
+ max_models: z19.record(z19.string(), z19.number().int()).optional(),
10023
+ pinned_models: z19.record(z19.string(), z19.number().int()).optional(),
10024
+ pinned_helper_models: z19.record(z19.string(), z19.number().int()).optional(),
10025
+ websocket_port: z19.number().int().optional(),
10026
+ update_check_done: z19.boolean().optional()
10027
+ }).strict();
10028
+ var AliasSchema = z19.object({
10029
+ alias: modelName,
10030
+ target: modelName,
10031
+ downloaded: z19.boolean().optional(),
10032
+ recipe: z19.string().optional()
10033
+ }).strict();
10034
+ var AliasesSchema = z19.object({
10035
+ aliases: z19.array(AliasSchema)
10036
+ }).strict();
10037
+ var MetadataRecordSchema = z19.record(z19.string(), z19.unknown());
10038
+ var inactiveStates = new Set([
10039
+ "loading",
10040
+ "downsizing",
10041
+ "downsized",
10042
+ "evicting",
10043
+ "unloaded"
10044
+ ]);
10045
+ var inactiveHealth = new Set(["stopped", "exited", "watchdog_reset"]);
10046
+ var standardPools = new Set([
10047
+ "standard/llm",
10048
+ "standard/embedding",
10049
+ "standard/reranking",
10050
+ "standard/transcription",
10051
+ "standard/image",
10052
+ "standard/tts",
10053
+ "standard/audio-generation",
10054
+ "standard/classification",
10055
+ "standard/mesh"
10056
+ ]);
10057
+ function usableState(entry) {
10058
+ if (entry.loaded === false || entry.backend_alive === false || entry.watchdog_reset === true || typeof entry.status === "string" && inactiveStates.has(entry.status) || typeof entry.backend_health === "string" && inactiveHealth.has(entry.backend_health) || entry.residency_class === "routing_helper" || typeof entry.slot_pool === "string" && entry.slot_pool.startsWith("routing_helper/")) {
10059
+ return false;
10060
+ }
10061
+ if (entry.loaded !== true || entry.backend_alive !== true || entry.watchdog_reset !== false || entry.status !== "ready" && entry.status !== "in_use" || entry.backend_health !== "ready" && entry.backend_health !== "busy" || entry.watchdog_reset_reason !== undefined && entry.watchdog_reset_reason !== "" || entry.residency_class !== undefined && entry.residency_class !== "standard" || entry.slot_pool !== undefined && (typeof entry.slot_pool !== "string" || !standardPools.has(entry.slot_pool))) {
10062
+ return;
10063
+ }
10064
+ return true;
10065
+ }
10066
+ function projectMetadataObject(payload, keys) {
10067
+ const record = MetadataRecordSchema.safeParse(payload);
10068
+ if (!record.success)
10069
+ throw new ModelResidencyError("unknown");
10070
+ return Object.fromEntries(keys.filter((key) => Object.hasOwn(record.data, key)).map((key) => [key, record.data[key]]));
10071
+ }
10072
+ function parseResidency(healthPayload, aliasPayload) {
10073
+ const healthFields = projectMetadataObject(healthPayload, Object.keys(HealthSchema.shape));
10074
+ if (Array.isArray(healthFields.all_models_loaded)) {
10075
+ healthFields.all_models_loaded = healthFields.all_models_loaded.map((entry) => projectMetadataObject(entry, Object.keys(LoadedModelSchema.shape)));
10076
+ }
10077
+ if (healthFields.telemetry !== undefined) {
10078
+ healthFields.telemetry = projectMetadataObject(healthFields.telemetry, Object.keys(TelemetrySchema.shape));
10079
+ }
10080
+ const aliasFields = projectMetadataObject(aliasPayload, Object.keys(AliasesSchema.shape));
10081
+ if (Array.isArray(aliasFields.aliases)) {
10082
+ aliasFields.aliases = aliasFields.aliases.map((entry) => projectMetadataObject(entry, Object.keys(AliasSchema.shape)));
10083
+ }
10084
+ const health = HealthSchema.safeParse(healthFields);
10085
+ const aliases = AliasesSchema.safeParse(aliasFields);
10086
+ if (!health.success || !aliases.success)
10087
+ throw new ModelResidencyError("unknown");
10088
+ const result = new Map;
10089
+ for (const entry of health.data.all_models_loaded) {
10090
+ if (result.has(entry.model_name))
10091
+ throw new ModelResidencyError("unknown");
10092
+ result.set(entry.model_name, {
10093
+ loaded: entry.model_name.endsWith(":latest") ? undefined : usableState(entry),
10094
+ metadata: entry
10095
+ });
10096
+ }
10097
+ const seenAliases = new Set;
10098
+ for (const entry of aliases.data.aliases) {
10099
+ if (seenAliases.has(entry.alias))
10100
+ throw new ModelResidencyError("unknown");
10101
+ seenAliases.add(entry.alias);
10102
+ result.set(entry.alias, {
10103
+ loaded: undefined,
10104
+ metadata: result.get(entry.alias)?.metadata ?? {}
10105
+ });
10106
+ }
10107
+ return result;
10108
+ }
10109
+ function lemonadeBaseURL(value) {
10110
+ let url;
10111
+ try {
10112
+ url = new URL(value);
10113
+ } catch {
10114
+ throw new ModelResidencyError("destination");
10115
+ }
10116
+ if (url.protocol !== "http:" && url.protocol !== "https:" || url.username !== "" || url.password !== "" || url.search !== "" || url.hash !== "" || !/^\/(?:api\/)?v[01]\/?$/.test(url.pathname)) {
10117
+ throw new ModelResidencyError("destination");
10118
+ }
10119
+ return `${url.origin}${url.pathname.replace(/\/$/, "")}`;
10120
+ }
10121
+ async function withResidencyDeadline(operation, options) {
10122
+ const timeoutMs = options.timeoutMs ?? 5000;
10123
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
10124
+ throw new ModelResidencyError("configuration");
10125
+ }
10126
+ const controller = new AbortController;
10127
+ const cancel = () => controller.abort(new ModelResidencyError("cancelled"));
10128
+ if (options.signal?.aborted)
10129
+ throw new ModelResidencyError("cancelled");
10130
+ options.signal?.addEventListener("abort", cancel, { once: true });
10131
+ const schedule = options.scheduleTimeout ?? ((callback, ms) => {
10132
+ const timer = setTimeout(callback, ms);
10133
+ return () => clearTimeout(timer);
10134
+ });
10135
+ let onAbort = () => {};
10136
+ const aborted = new Promise((_, reject) => {
10137
+ onAbort = () => reject(controller.signal.reason);
10138
+ controller.signal.addEventListener("abort", onAbort, { once: true });
10139
+ });
10140
+ const clearTimer = schedule(() => controller.abort(new ModelResidencyError("timeout")), timeoutMs);
10141
+ try {
10142
+ controller.signal.throwIfAborted();
10143
+ return await Promise.race([operation(controller.signal), aborted]);
10144
+ } finally {
10145
+ clearTimer();
10146
+ options.signal?.removeEventListener("abort", cancel);
10147
+ controller.signal.removeEventListener("abort", onAbort);
10148
+ controller.abort();
10149
+ }
10150
+ }
10151
+ async function metadata(url, fetch, signal, headers) {
10152
+ signal.throwIfAborted();
10153
+ let payload;
10154
+ try {
10155
+ const response = await fetch(url, {
10156
+ method: "GET",
10157
+ headers,
10158
+ signal,
10159
+ redirect: "error",
10160
+ cache: "no-store"
10161
+ });
10162
+ signal.throwIfAborted();
10163
+ if (!response.ok || response.redirected || response.url !== "" && response.url !== url) {
10164
+ throw new ModelResidencyError("unknown");
10165
+ }
10166
+ payload = await response.json();
10167
+ } catch {
10168
+ signal.throwIfAborted();
10169
+ throw new ModelResidencyError("unknown");
10170
+ }
10171
+ signal.throwIfAborted();
10172
+ return payload;
10173
+ }
10174
+ async function readLemonadeResidency(baseURL, fetch, options = {}) {
10175
+ const base = lemonadeBaseURL(baseURL);
10176
+ const headers = new Headers(options.headers);
10177
+ headers.delete("content-type");
10178
+ headers.delete("content-length");
10179
+ headers.set("accept", "application/json");
10180
+ headers.set("cache-control", "no-cache, no-store");
10181
+ headers.delete("if-none-match");
10182
+ headers.delete("if-modified-since");
10183
+ return withResidencyDeadline(async (signal) => {
10184
+ const aliases = await metadata(`${new URL(base).origin}/internal/aliases`, fetch, signal, headers);
10185
+ const health = await metadata(`${base}/health`, fetch, signal, headers);
10186
+ return parseResidency(health, aliases);
10187
+ }, options);
10188
+ }
10189
+
9934
10190
  // src/local/lemonade.ts
9935
10191
  var LEMONADE_DEFAULT_BASE_URL = "http://localhost:13305/api/v1";
9936
10192
  var NON_TEXT_LABELS = new Set([
@@ -10017,36 +10273,19 @@ function isNonTextModel(entry) {
10017
10273
  return entry.labels.some((label) => typeof label === "string" && NON_TEXT_LABELS.has(label));
10018
10274
  }
10019
10275
  async function readLoadedModels(baseURL, fetch) {
10020
- let payload;
10021
10276
  try {
10022
- const response = await fetch(`${baseURL}/health`, {
10023
- method: "GET",
10024
- headers: { accept: "application/json" }
10025
- });
10026
- if (!response.ok) {
10027
- return;
10028
- }
10029
- payload = await response.json();
10277
+ const residency = await readLemonadeResidency(baseURL, fetch);
10278
+ return new Map([...residency].map(([name, entry]) => [
10279
+ name,
10280
+ {
10281
+ loaded: entry.loaded,
10282
+ slots: entry.loaded === true ? readSlotCount(entry.metadata) : undefined,
10283
+ totalContextWindow: entry.loaded === true ? readLoadedContextWindow(entry.metadata) : undefined
10284
+ }
10285
+ ]));
10030
10286
  } catch {
10031
10287
  return;
10032
10288
  }
10033
- if (!isObject2(payload) || !Array.isArray(payload.all_models_loaded)) {
10034
- return;
10035
- }
10036
- const loaded = new Map;
10037
- for (const entry of payload.all_models_loaded) {
10038
- if (!isObject2(entry) || typeof entry.model_name !== "string") {
10039
- continue;
10040
- }
10041
- if (entry.loaded === false) {
10042
- continue;
10043
- }
10044
- loaded.set(entry.model_name, {
10045
- slots: readSlotCount(entry),
10046
- totalContextWindow: readLoadedContextWindow(entry)
10047
- });
10048
- }
10049
- return loaded;
10050
10289
  }
10051
10290
  function readSlotCount(entry) {
10052
10291
  return slotsFromLlamacppArgs(entry) ?? slotsFromLaunchCommand(entry);
@@ -10193,6 +10432,9 @@ function enrichWithLoadState(models, loaded) {
10193
10432
  if (hit === undefined) {
10194
10433
  return { ...base, loaded: false };
10195
10434
  }
10435
+ if (hit.loaded !== true) {
10436
+ return hit.loaded === false ? { ...base, loaded: false } : base;
10437
+ }
10196
10438
  const contextWindow = derivedConservativeContextWindow(model.contextWindow, hit);
10197
10439
  return {
10198
10440
  ...base,
@@ -10336,6 +10578,14 @@ function reportedModelSlotsByRuntime(snapshots) {
10336
10578
  }
10337
10579
 
10338
10580
  // src/local/slotPool.ts
10581
+ function localModelAliases(providerID, models) {
10582
+ const aliases = new Map;
10583
+ for (const model of models ?? []) {
10584
+ if (model.kind === "local" && model.providerID === providerID && model.runtimeModelID !== undefined && model.runtimeModelID !== model.modelID)
10585
+ aliases.set(model.modelID, model.runtimeModelID);
10586
+ }
10587
+ return aliases;
10588
+ }
10339
10589
  var POOL_SEPARATOR = "::";
10340
10590
  function slotPoolKey(runtime, modelID) {
10341
10591
  if (modelID === undefined) {
@@ -10365,13 +10615,20 @@ function slotPoolReservedInteractive(runtime, modelID) {
10365
10615
  function unknownPoolCapacity() {
10366
10616
  return DEFAULT_LOCAL_MAX_CONCURRENCY;
10367
10617
  }
10368
- function withReportedModelSlots(runtime, reported) {
10369
- if (reported === undefined || Object.keys(reported).length === 0) {
10618
+ function withReportedModelSlots(runtime, reported, aliases) {
10619
+ const configured = Object.entries(runtime.modelConcurrency ?? {});
10620
+ const hasAliasLimits = configured.some(([modelID]) => aliases?.has(modelID) === true);
10621
+ if (!hasAliasLimits && (reported === undefined || Object.keys(reported).length === 0)) {
10370
10622
  return runtime;
10371
10623
  }
10624
+ const explicit = new Map;
10625
+ for (const [modelID, limit] of configured) {
10626
+ const physicalID = aliases?.get(modelID) ?? modelID;
10627
+ explicit.set(physicalID, Math.min(explicit.get(physicalID) ?? limit, limit));
10628
+ }
10372
10629
  return {
10373
10630
  ...runtime,
10374
- modelConcurrency: { ...reported, ...runtime.modelConcurrency }
10631
+ modelConcurrency: { ...reported, ...Object.fromEntries(explicit) }
10375
10632
  };
10376
10633
  }
10377
10634
 
@@ -10468,14 +10725,14 @@ var readReportArtifact = async (reportPath) => {
10468
10725
  };
10469
10726
 
10470
10727
  // src/orchestrator/roster.ts
10471
- import { z as z19 } from "zod";
10472
- var RosterEntrySchema = z19.object({
10473
- roleID: z19.string().min(1),
10474
- agentName: z19.string().min(1)
10728
+ import { z as z20 } from "zod";
10729
+ var RosterEntrySchema = z20.object({
10730
+ roleID: z20.string().min(1),
10731
+ agentName: z20.string().min(1)
10475
10732
  }).strict();
10476
- var RosterSchema = z19.object({
10477
- universe: z19.string().min(1),
10478
- entries: z19.array(RosterEntrySchema)
10733
+ var RosterSchema = z20.object({
10734
+ universe: z20.string().min(1),
10735
+ entries: z20.array(RosterEntrySchema)
10479
10736
  }).strict();
10480
10737
  var ROSTER_JSON_FENCE = /```json\s*([\s\S]*?)```/;
10481
10738
 
@@ -11120,10 +11377,21 @@ async function runSubsession(client, req, deps) {
11120
11377
  }
11121
11378
  }
11122
11379
 
11380
+ // src/local/modelResidency.ts
11381
+ function hasRequiredModelResidency(kind, model) {
11382
+ return kind !== "lemonade" || model?.loaded === true;
11383
+ }
11384
+
11123
11385
  // src/plugin/availability.ts
11124
11386
  function modelKey2(model) {
11125
11387
  return `${model.providerID}/${model.modelID}`;
11126
11388
  }
11389
+ function availabilityMetadata({
11390
+ apiModelID: _apiModelID,
11391
+ ...metadata2
11392
+ }) {
11393
+ return metadata2;
11394
+ }
11127
11395
  function compareAvailableModels(left, right) {
11128
11396
  const kindOrder = Number(left.kind === "frontier") - Number(right.kind === "frontier");
11129
11397
  if (kindOrder !== 0) {
@@ -11141,6 +11409,9 @@ function uniqueSelections(models) {
11141
11409
  function isConfiguredLocalModel(config, model) {
11142
11410
  return config.local.runtimes.some((runtime) => runtime.defaultModel.providerID === model.providerID);
11143
11411
  }
11412
+ function requiresModelResidency(config, model) {
11413
+ return config.local.runtimes.some((runtime) => runtime.defaultModel.providerID === model.providerID && !hasRequiredModelResidency(localRuntimeKind(runtime), undefined));
11414
+ }
11144
11415
  function configuredFrontierProviderIDs(config) {
11145
11416
  const providerIDs = new Set([config.baseline.hardDefault.providerID]);
11146
11417
  if (config.baseline.mode === "pinned" && config.baseline.pinnedModel !== null) {
@@ -11235,7 +11506,7 @@ function frontierAvailableModels(config, configuredModels) {
11235
11506
  for (const model of configuredModels ?? frontierBaselines(config)) {
11236
11507
  if (!isConfiguredLocalModel(config, model)) {
11237
11508
  frontierByKey.set(modelKey2(model), {
11238
- ...model,
11509
+ ...availabilityMetadata(model),
11239
11510
  kind: "frontier",
11240
11511
  available: true
11241
11512
  });
@@ -11251,7 +11522,7 @@ function defaultAvailableModels(config, configuredModels) {
11251
11522
  ...defaultLocalModels(config).map((model) => ({
11252
11523
  ...model,
11253
11524
  kind: "local",
11254
- available: true
11525
+ available: !requiresModelResidency(config, model)
11255
11526
  })),
11256
11527
  ...frontierAvailableModels(config, configuredModels)
11257
11528
  ].sort(compareAvailableModels);
@@ -11265,7 +11536,8 @@ function toAvailableModels(snapshots, config, configuredModels) {
11265
11536
  continue;
11266
11537
  }
11267
11538
  localByKey.set(modelKey2(model), {
11268
- ...model,
11539
+ ...availabilityMetadata(model),
11540
+ ...model.apiModelID !== undefined && model.apiModelID !== model.modelID ? { runtimeModelID: model.apiModelID } : {},
11269
11541
  kind: "local",
11270
11542
  available: false
11271
11543
  });
@@ -11276,27 +11548,25 @@ function toAvailableModels(snapshots, config, configuredModels) {
11276
11548
  continue;
11277
11549
  }
11278
11550
  for (const model of snapshot.models) {
11279
- const ref = {
11280
- providerID: runtime.defaultModel.providerID,
11281
- modelID: model.modelID
11282
- };
11283
- if (registeredKeys !== undefined && !registeredKeys.has(modelKey2(ref))) {
11284
- continue;
11285
- }
11286
- const existing = localByKey.get(modelKey2(ref));
11287
- const availableModel = {
11288
- ...existing,
11289
- ...ref,
11290
- kind: "local",
11291
- available: snapshot.reachable || existing?.available === true
11292
- };
11293
- if (model.supportsTools !== "unknown") {
11294
- availableModel.supportsTools = model.supportsTools;
11295
- }
11296
- if (model.contextWindow !== undefined) {
11297
- availableModel.contextWindow = model.contextWindow;
11551
+ const providerID = runtime.defaultModel.providerID;
11552
+ const refs = configuredModels === undefined ? [{ providerID, modelID: model.modelID }] : configuredModels.filter((registered) => registered.providerID === providerID && (registered.apiModelID ?? registered.modelID) === model.modelID);
11553
+ for (const ref of refs) {
11554
+ const existing = localByKey.get(modelKey2(ref));
11555
+ const availableModel = {
11556
+ ...existing,
11557
+ providerID: ref.providerID,
11558
+ modelID: ref.modelID,
11559
+ kind: "local",
11560
+ available: snapshot.reachable && hasRequiredModelResidency(localRuntimeKind(runtime), model) || existing?.available === true
11561
+ };
11562
+ if (model.supportsTools !== "unknown") {
11563
+ availableModel.supportsTools = model.supportsTools;
11564
+ }
11565
+ if (model.contextWindow !== undefined) {
11566
+ availableModel.contextWindow = model.contextWindow;
11567
+ }
11568
+ localByKey.set(modelKey2(ref), availableModel);
11298
11569
  }
11299
- localByKey.set(modelKey2(ref), availableModel);
11300
11570
  }
11301
11571
  }
11302
11572
  return [
@@ -11305,7 +11575,7 @@ function toAvailableModels(snapshots, config, configuredModels) {
11305
11575
  ].sort(compareAvailableModels);
11306
11576
  }
11307
11577
  function createAvailabilityCache(options) {
11308
- let configuredModels = options.initialConfiguredModels === undefined ? undefined : [...options.initialConfiguredModels];
11578
+ let configuredModels = options.initialConfiguredModels === undefined ? undefined : options.initialConfiguredModels.map((model) => ({ ...model }));
11309
11579
  let configuredProfiles = (options.initialConfiguredProfiles ?? []).map((profile) => profileForConfiguredDomain(options.config, profile));
11310
11580
  let cached = defaultAvailableModels(options.config, configuredModels);
11311
11581
  let inFlight;
@@ -11315,7 +11585,9 @@ function createAvailabilityCache(options) {
11315
11585
  if (options.listConfiguredInventory !== undefined) {
11316
11586
  const inventory = await options.listConfiguredInventory().then((value) => ({ kind: "models", value }), (error) => ({ kind: "error", error }));
11317
11587
  if (inventory.kind === "models") {
11318
- configuredModels = inventory.value.models;
11588
+ configuredModels = inventory.value.models.map((model) => ({
11589
+ ...model
11590
+ }));
11319
11591
  configuredProfiles = inventory.value.profiles.map((profile) => profileForConfiguredDomain(options.config, profile));
11320
11592
  } else {
11321
11593
  options.onRefreshError?.(inventory.error);
@@ -11328,15 +11600,22 @@ function createAvailabilityCache(options) {
11328
11600
  }
11329
11601
  return {
11330
11602
  get: () => cloneAvailableModels(cached),
11603
+ resolveApiModelID: (ref) => {
11604
+ const registered = configuredModels?.find((model) => model.providerID === ref.providerID && model.modelID === ref.modelID);
11605
+ return registered?.apiModelID ?? registered?.modelID;
11606
+ },
11331
11607
  getProfiles: () => configuredProfiles.map((profile) => ({
11332
11608
  ...profile,
11333
11609
  ref: { ...profile.ref },
11334
11610
  costPer1M: { ...profile.costPer1M }
11335
11611
  })),
11336
11612
  refresh: () => {
11337
- inFlight ??= refreshNow().finally(() => {
11338
- inFlight = undefined;
11339
- });
11613
+ if (inFlight === undefined) {
11614
+ cached = cached.map((model) => requiresModelResidency(options.config, model) ? { ...model, available: false } : model);
11615
+ inFlight = refreshNow().finally(() => {
11616
+ inFlight = undefined;
11617
+ });
11618
+ }
11340
11619
  return inFlight;
11341
11620
  }
11342
11621
  };
@@ -11504,7 +11783,7 @@ function planWorktreeReconciliation(input) {
11504
11783
  }
11505
11784
 
11506
11785
  // src/telemetry/otelConfig.ts
11507
- import { z as z20 } from "zod";
11786
+ import { z as z21 } from "zod";
11508
11787
 
11509
11788
  // src/telemetry/fanout.ts
11510
11789
  function createFanOutSink(deps) {
@@ -11582,10 +11861,10 @@ function createOtelSink(deps) {
11582
11861
  }
11583
11862
 
11584
11863
  // src/telemetry/otelConfig.ts
11585
- var OtelBackendConfigSchema = z20.object({
11586
- backend: z20.literal("opentelemetry"),
11587
- connectionEnv: z20.string().min(1),
11588
- serviceName: z20.string().min(1).optional()
11864
+ var OtelBackendConfigSchema = z21.object({
11865
+ backend: z21.literal("opentelemetry"),
11866
+ connectionEnv: z21.string().min(1),
11867
+ serviceName: z21.string().min(1).optional()
11589
11868
  }).strict();
11590
11869
  function parseConnectionString(raw) {
11591
11870
  const pairs = new Map;
@@ -12010,7 +12289,7 @@ function parseOpencodeProviders(opencodeConfig) {
12010
12289
  function localRuntimeStates(config) {
12011
12290
  const map = new Map;
12012
12291
  for (const runtime of config.local.runtimes) {
12013
- map.set(runtime.id, { enabled: runtime.enabled });
12292
+ map.set(runtime.defaultModel.providerID, { enabled: runtime.enabled });
12014
12293
  }
12015
12294
  return map;
12016
12295
  }
@@ -12018,7 +12297,7 @@ function disabledLocalProviderIDs(config) {
12018
12297
  const ids = new Set;
12019
12298
  for (const runtime of config.local.runtimes) {
12020
12299
  if (!runtime.enabled) {
12021
- ids.add(runtime.id);
12300
+ ids.add(runtime.defaultModel.providerID);
12022
12301
  }
12023
12302
  }
12024
12303
  return ids;
@@ -12034,7 +12313,11 @@ function computeLive(model, isLocalProvider, liveModels) {
12034
12313
  if (!snapshot.reachable) {
12035
12314
  return "unreachable";
12036
12315
  }
12037
- return snapshot.modelIDs.has(model.modelID) ? "confirmed" : "not-advertised";
12316
+ if (snapshot.modelIDs.has(model.modelID))
12317
+ return "confirmed";
12318
+ if (snapshot.residency?.has(model.modelID))
12319
+ return snapshot.residency.get(model.modelID) === false ? "not-loaded" : "residency-unknown";
12320
+ return "not-advertised";
12038
12321
  }
12039
12322
  function resolveAgentModel(model, context) {
12040
12323
  const isLocalProvider = KNOWN_LOCAL_PROVIDER_IDS.has(model.providerID) || context.localRuntimes.has(model.providerID);
@@ -14365,12 +14648,19 @@ function defaultModelFromOpencode(opencodeConfig) {
14365
14648
  }
14366
14649
  return;
14367
14650
  }
14368
- function liveModelsFromSnapshots(snapshots) {
14651
+ function liveModelsFromSnapshots(snapshots, config) {
14369
14652
  const map = new Map;
14370
14653
  for (const snapshot of snapshots) {
14371
- map.set(snapshot.id, {
14654
+ const runtime = config.local.runtimes.find((runtime2) => runtime2.id === snapshot.id);
14655
+ if (runtime === undefined || !runtime.enabled)
14656
+ continue;
14657
+ const kind = localRuntimeKind(runtime);
14658
+ map.set(runtime.defaultModel.providerID, {
14372
14659
  reachable: snapshot.reachable,
14373
- modelIDs: new Set(snapshot.models.map((model) => model.modelID))
14660
+ modelIDs: new Set(snapshot.models.filter((model) => hasRequiredModelResidency(kind, model)).map((model) => model.modelID)),
14661
+ ...kind === "lemonade" ? {
14662
+ residency: new Map(snapshot.models.map((model) => [model.modelID, model.loaded]))
14663
+ } : {}
14374
14664
  });
14375
14665
  }
14376
14666
  return map;
@@ -14656,7 +14946,7 @@ async function runCli(argv, deps) {
14656
14946
  const agentModels = diagnoseAgentModels(agentFiles, {
14657
14947
  opencodeProviders: parseOpencodeProviders(opencodeConfig),
14658
14948
  localRuntimes: localRuntimeStates(config),
14659
- liveModels: liveModelsFromSnapshots(snapshots),
14949
+ liveModels: liveModelsFromSnapshots(snapshots, config),
14660
14950
  sourceDir: deps.agentDir,
14661
14951
  ...defaultModel !== undefined ? { defaultModel } : {}
14662
14952
  });
@@ -14695,29 +14985,53 @@ async function runCli(argv, deps) {
14695
14985
  const rosterMissing = deps.loadRosterForDoctor !== undefined && roster === undefined && rosterLoadError === undefined;
14696
14986
  const orchestratorAgentName = ORCHESTRATOR_AGENT_PATH.slice(ORCHESTRATOR_AGENT_PATH.lastIndexOf("/") + 1).replace(/\.md$/, "");
14697
14987
  const orchestratorAgentMissing = !agentFiles.some((file) => file.name === orchestratorAgentName);
14988
+ const inventoryNotes = [];
14989
+ const readySnapshots = snapshots.map((snapshot) => {
14990
+ const runtime = config.local.runtimes.find((runtime2) => runtime2.id === snapshot.id);
14991
+ if (runtime === undefined || localRuntimeKind(runtime) !== "lemonade")
14992
+ return snapshot;
14993
+ inventoryNotes.push(executionSetupMessages.lemonadeInventory(runtime.id, runtime.defaultModel.providerID, snapshot.models));
14994
+ return {
14995
+ ...snapshot,
14996
+ models: snapshot.models.filter((model) => hasRequiredModelResidency(localRuntimeKind(runtime), model))
14997
+ };
14998
+ });
14999
+ const residencyNotes = agentModels.flatMap((agent) => {
15000
+ const live = agent.resolution?.live;
15001
+ if (agent.model === undefined || live !== "not-loaded" && live !== "residency-unknown")
15002
+ return [];
15003
+ return [
15004
+ executionSetupMessages.lemonadeAgentResidency(agent.name, `${agent.model.providerID}/${agent.model.modelID}`, live)
15005
+ ];
15006
+ });
14698
15007
  return {
14699
15008
  exitCode: 0,
14700
- stdout: renderDoctor({
14701
- config,
14702
- snapshots,
14703
- telemetryPath,
14704
- telemetryRecords: records.length,
14705
- agentModels,
14706
- opencodeConfigPaths,
14707
- ...opencodeConfig !== undefined ? { opencodeConfig } : {},
14708
- ...queueWait !== undefined ? { queueWait } : {},
14709
- ...rosterAudit !== undefined ? { rosterAudit } : {},
14710
- ...rosterRoleCount !== undefined ? { rosterRoleCount } : {},
14711
- ...rosterLoadError !== undefined ? { rosterLoadError } : {},
14712
- ...rosterMissing ? { rosterMissing } : {},
14713
- ...orchestratorAgentMissing ? { orchestratorAgentMissing } : {},
14714
- ...diagnostics !== undefined && diagnostics.length > 0 ? { diagnostics } : {},
14715
- ...opencodeConfigError !== undefined ? { opencodeConfigError } : {},
14716
- ...cacheEntries !== undefined ? { cacheEntries, cliVersion: deps.version } : {},
14717
- ...legacyLayout !== undefined && legacyLayout.length > 0 ? { legacyLayout } : {},
14718
- ...otelBackend !== undefined ? { otelBackend } : {},
14719
- ...gitignoreCoverage !== undefined ? { gitignore: gitignoreCoverage } : {}
14720
- })
15009
+ stdout: [
15010
+ renderDoctor({
15011
+ config,
15012
+ snapshots: readySnapshots,
15013
+ telemetryPath,
15014
+ telemetryRecords: records.length,
15015
+ agentModels,
15016
+ opencodeConfigPaths,
15017
+ ...opencodeConfig !== undefined ? { opencodeConfig } : {},
15018
+ ...queueWait !== undefined ? { queueWait } : {},
15019
+ ...rosterAudit !== undefined ? { rosterAudit } : {},
15020
+ ...rosterRoleCount !== undefined ? { rosterRoleCount } : {},
15021
+ ...rosterLoadError !== undefined ? { rosterLoadError } : {},
15022
+ ...rosterMissing ? { rosterMissing } : {},
15023
+ ...orchestratorAgentMissing ? { orchestratorAgentMissing } : {},
15024
+ ...diagnostics !== undefined && diagnostics.length > 0 ? { diagnostics } : {},
15025
+ ...opencodeConfigError !== undefined ? { opencodeConfigError } : {},
15026
+ ...cacheEntries !== undefined ? { cacheEntries, cliVersion: deps.version } : {},
15027
+ ...legacyLayout !== undefined && legacyLayout.length > 0 ? { legacyLayout } : {},
15028
+ ...otelBackend !== undefined ? { otelBackend } : {},
15029
+ ...gitignoreCoverage !== undefined ? { gitignore: gitignoreCoverage } : {}
15030
+ }),
15031
+ ...inventoryNotes,
15032
+ ...residencyNotes
15033
+ ].join(`
15034
+ `)
14721
15035
  };
14722
15036
  }
14723
15037
  if (command === "migrate") {
@@ -14901,29 +15215,29 @@ import {
14901
15215
  writeFile as writeFile2
14902
15216
  } from "node:fs/promises";
14903
15217
  import { dirname as dirname5, join as join12, resolve as resolve7 } from "node:path";
14904
- import { z as z21 } from "zod";
15218
+ import { z as z22 } from "zod";
14905
15219
  var CONSOLE_RUNTIME_SCHEMA_VERSION = 1;
14906
15220
  var CONSOLE_RUNTIME_DIRECTORY = ".opencode/openteam-local/console";
14907
15221
  var CONSOLE_RUNTIME_FILE = "runtime.json";
14908
15222
  var CONSOLE_LAUNCH_LOCK_FILE = "launch.lock";
14909
15223
  var CONSOLE_LOG_FILE = "console.log";
14910
- var ConsoleRuntimeStateSchema = z21.object({
14911
- schemaVersion: z21.literal(CONSOLE_RUNTIME_SCHEMA_VERSION),
14912
- pid: z21.number().int().positive(),
14913
- workspaceRoot: z21.string().min(1),
14914
- host: z21.string().min(1),
14915
- port: z21.number().int().min(1).max(65535),
14916
- url: z21.url(),
14917
- startedAt: z21.iso.datetime({ offset: true }),
14918
- launchId: z21.uuid(),
14919
- logPath: z21.string().min(1)
15224
+ var ConsoleRuntimeStateSchema = z22.object({
15225
+ schemaVersion: z22.literal(CONSOLE_RUNTIME_SCHEMA_VERSION),
15226
+ pid: z22.number().int().positive(),
15227
+ workspaceRoot: z22.string().min(1),
15228
+ host: z22.string().min(1),
15229
+ port: z22.number().int().min(1).max(65535),
15230
+ url: z22.url(),
15231
+ startedAt: z22.iso.datetime({ offset: true }),
15232
+ launchId: z22.uuid(),
15233
+ logPath: z22.string().min(1)
14920
15234
  }).strict();
14921
- var ConsoleLaunchLockSchema = z21.object({
14922
- schemaVersion: z21.literal(CONSOLE_RUNTIME_SCHEMA_VERSION),
14923
- workspaceRoot: z21.string().min(1),
14924
- launchId: z21.uuid(),
14925
- ownerPid: z21.number().int().positive(),
14926
- createdAt: z21.iso.datetime({ offset: true })
15235
+ var ConsoleLaunchLockSchema = z22.object({
15236
+ schemaVersion: z22.literal(CONSOLE_RUNTIME_SCHEMA_VERSION),
15237
+ workspaceRoot: z22.string().min(1),
15238
+ launchId: z22.uuid(),
15239
+ ownerPid: z22.number().int().positive(),
15240
+ createdAt: z22.iso.datetime({ offset: true })
14927
15241
  }).strict();
14928
15242
 
14929
15243
  class ConsoleRuntimeStateFileError extends Error {
@@ -15622,36 +15936,36 @@ function formatResponse(response) {
15622
15936
  }
15623
15937
 
15624
15938
  // src/plugin/reportRunSchema.ts
15625
- import { z as z23 } from "zod";
15939
+ import { z as z24 } from "zod";
15626
15940
 
15627
15941
  // src/plugin/graphShadowIngress.ts
15628
- import { z as z22 } from "zod";
15942
+ import { z as z23 } from "zod";
15629
15943
  var LEGACY_EXECUTION_TRACE_VERSION = 1;
15630
- var LegacyExecutionStatusSchema = z22.enum([
15944
+ var LegacyExecutionStatusSchema = z23.enum([
15631
15945
  "completed",
15632
15946
  "failed",
15633
15947
  "cancelled"
15634
15948
  ]);
15635
- var LegacyReviewOutcomeSchema = z22.enum([
15949
+ var LegacyReviewOutcomeSchema = z23.enum([
15636
15950
  "approved",
15637
15951
  "rejected",
15638
15952
  "inconclusive"
15639
15953
  ]);
15640
- var LegacyTraceNodeV1Schema = z22.object({
15954
+ var LegacyTraceNodeV1Schema = z23.object({
15641
15955
  id: NodeIDSchema,
15642
15956
  role: NodeRoleSchema,
15643
- model: z22.string().min(1),
15644
- sessionRef: z22.string().min(1).optional(),
15957
+ model: z23.string().min(1),
15958
+ sessionRef: z23.string().min(1).optional(),
15645
15959
  errorClass: ErrorClassSchema.optional()
15646
15960
  }).strict();
15647
- var LegacyExecutionTraceV1Schema = z22.object({
15648
- version: z22.literal(LEGACY_EXECUTION_TRACE_VERSION),
15961
+ var LegacyExecutionTraceV1Schema = z23.object({
15962
+ version: z23.literal(LEGACY_EXECUTION_TRACE_VERSION),
15649
15963
  runID: NodeIDSchema,
15650
15964
  status: LegacyExecutionStatusSchema,
15651
15965
  outcome: LegacyReviewOutcomeSchema,
15652
- fixes: z22.number().int().nonnegative(),
15653
- nodes: z22.array(LegacyTraceNodeV1Schema).min(1),
15654
- parentSessionRef: z22.string().min(1).optional()
15966
+ fixes: z23.number().int().nonnegative(),
15967
+ nodes: z23.array(LegacyTraceNodeV1Schema).min(1),
15968
+ parentSessionRef: z23.string().min(1).optional()
15655
15969
  }).strict();
15656
15970
  function gateReason2(gate) {
15657
15971
  if (gate === undefined || gate.mode === "off") {
@@ -15722,20 +16036,20 @@ function parseLegacyExecutionTrace(input) {
15722
16036
  }
15723
16037
 
15724
16038
  // src/plugin/reportRunSchema.ts
15725
- var ReportRunNodeSchema = z23.object({
16039
+ var ReportRunNodeSchema = z24.object({
15726
16040
  id: NodeIDSchema,
15727
16041
  role: NodeRoleSchema,
15728
- model: z23.string().min(1),
15729
- ok: z23.boolean(),
15730
- sessionRef: z23.string().min(1).optional(),
16042
+ model: z24.string().min(1),
16043
+ ok: z24.boolean(),
16044
+ sessionRef: z24.string().min(1).optional(),
15731
16045
  errorClass: ErrorClassSchema.optional()
15732
16046
  }).strict();
15733
- var ReportRunPayloadSchema = z23.object({
16047
+ var ReportRunPayloadSchema = z24.object({
15734
16048
  runID: NodeIDSchema,
15735
16049
  status: LegacyExecutionStatusSchema,
15736
- fixes: z23.number().int().nonnegative(),
15737
- nodes: z23.array(ReportRunNodeSchema).min(1),
15738
- parentSessionRef: z23.string().min(1).optional()
16050
+ fixes: z24.number().int().nonnegative(),
16051
+ nodes: z24.array(ReportRunNodeSchema).min(1),
16052
+ parentSessionRef: z24.string().min(1).optional()
15739
16053
  }).strict();
15740
16054
 
15741
16055
  // src/orchestrator/graphShadow.ts
@@ -16839,6 +17153,309 @@ function hashPrompt(prompt) {
16839
17153
  return `fnv1a32:${(hash >>> 0).toString(16).padStart(8, "0")}`;
16840
17154
  }
16841
17155
 
17156
+ // src/plugin/modelResidency.ts
17157
+ import { z as z25 } from "zod";
17158
+
17159
+ // src/local/lemonadeRequestGuard.ts
17160
+ var inferencePaths = new Set([
17161
+ "/chat/completions",
17162
+ "/completions",
17163
+ "/embeddings",
17164
+ "/responses"
17165
+ ]);
17166
+ function modelID(payload) {
17167
+ if (typeof payload !== "object" || payload === null || !("model" in payload) || typeof payload.model !== "string" || payload.model.length === 0 || payload.model !== payload.model.trim()) {
17168
+ throw new ModelResidencyError("request");
17169
+ }
17170
+ if (payload.model.endsWith(":latest"))
17171
+ throw new ModelResidencyError("identity");
17172
+ return payload.model;
17173
+ }
17174
+ function createLemonadeGuardedFetch(options) {
17175
+ const base = lemonadeBaseURL(options.baseURL);
17176
+ const upstream = options.fetch;
17177
+ const healthFetch = options.healthFetch ?? upstream;
17178
+ return Object.assign(async (input, init) => {
17179
+ const request = new Request(input, init);
17180
+ const url = new URL(request.url);
17181
+ if (url.username !== "" || url.password !== "" || url.search !== "" || url.hash !== "" || !request.url.startsWith(`${base}/`)) {
17182
+ throw new ModelResidencyError("destination");
17183
+ }
17184
+ const path4 = request.url.slice(base.length);
17185
+ const metadataOnly = request.method === "GET" && (path4 === "/health" || /^\/models(?:\/[^/]+)?$/.test(path4));
17186
+ if (!metadataOnly && (request.method !== "POST" || !inferencePaths.has(path4))) {
17187
+ throw new ModelResidencyError("request");
17188
+ }
17189
+ if (!metadataOnly) {
17190
+ await withResidencyDeadline(async (signal) => {
17191
+ signal.throwIfAborted();
17192
+ let payload;
17193
+ try {
17194
+ payload = await request.clone().json();
17195
+ } catch {
17196
+ signal.throwIfAborted();
17197
+ throw new ModelResidencyError("request");
17198
+ }
17199
+ signal.throwIfAborted();
17200
+ const model = modelID(payload);
17201
+ const modelIDs = typeof options.modelIDs === "function" ? await options.modelIDs() : options.modelIDs;
17202
+ signal.throwIfAborted();
17203
+ if (modelIDs !== undefined && !modelIDs.has(model)) {
17204
+ throw new ModelResidencyError("identity");
17205
+ }
17206
+ const residency = await readLemonadeResidency(base, healthFetch, {
17207
+ ...options,
17208
+ signal,
17209
+ headers: request.headers
17210
+ });
17211
+ signal.throwIfAborted();
17212
+ const entry = residency.get(model);
17213
+ if (entry?.loaded !== true) {
17214
+ throw new ModelResidencyError(entry?.loaded === undefined && entry !== undefined ? "unknown" : "inactive");
17215
+ }
17216
+ }, { ...options, signal: request.signal });
17217
+ }
17218
+ if (request.signal.aborted)
17219
+ throw new ModelResidencyError("cancelled");
17220
+ const {
17221
+ body: _body,
17222
+ headers: _headers,
17223
+ method: _method,
17224
+ signal: _signal,
17225
+ redirect: _redirect,
17226
+ ...transportOptions
17227
+ } = init ?? {};
17228
+ return upstream(request, { ...transportOptions, redirect: "error" });
17229
+ }, {
17230
+ preconnect: (...args) => upstream.preconnect?.(...args)
17231
+ });
17232
+ }
17233
+
17234
+ // src/plugin/modelResidency.ts
17235
+ function isFetch(value) {
17236
+ return typeof value === "function";
17237
+ }
17238
+ function origin(value) {
17239
+ return typeof value === "string" && URL.canParse(value) ? new URL(value).origin : undefined;
17240
+ }
17241
+ var TEMPLATE_REFERENCE = /\$\{[^}]+\}/;
17242
+ function resolveTemplateReferences(value, readEnv) {
17243
+ let unresolved = false;
17244
+ const resolved = value.replace(/\$\{([^}]+)\}/g, (match, key) => {
17245
+ const resolvedValue = readEnv(key);
17246
+ if (resolvedValue === undefined) {
17247
+ unresolved = true;
17248
+ return match;
17249
+ }
17250
+ return resolvedValue;
17251
+ });
17252
+ return unresolved ? undefined : resolved;
17253
+ }
17254
+ function endpointBinding(value, readEnv) {
17255
+ if (!TEMPLATE_REFERENCE.test(value))
17256
+ return { ambiguous: false, origin: origin(value) };
17257
+ const resolved = resolveTemplateReferences(value, readEnv);
17258
+ return resolved === undefined ? { ambiguous: true } : { ambiguous: false, origin: origin(resolved) };
17259
+ }
17260
+ function optionBaseURL(value) {
17261
+ return typeof value === "string" && value !== "" ? value : undefined;
17262
+ }
17263
+ function providerBase(provider, model) {
17264
+ return optionBaseURL(provider.options?.baseURL) ?? model?.provider?.api ?? provider.api;
17265
+ }
17266
+ function providerRoutes(provider) {
17267
+ const models = Object.values(provider.models ?? {});
17268
+ return (models.length === 0 ? [undefined] : models).map((model) => ({
17269
+ baseURL: providerBase(provider, model),
17270
+ npm: model?.provider?.npm ?? provider.npm
17271
+ }));
17272
+ }
17273
+ function wireID(key, model) {
17274
+ const id = model?.id ?? key;
17275
+ if (id.length === 0 || id !== id.trim())
17276
+ throw new ModelResidencyError("identity");
17277
+ return id;
17278
+ }
17279
+ function nativeEligibleID(id) {
17280
+ return id === "openai" || id === "anthropic" || id.startsWith("opencode");
17281
+ }
17282
+ function configuredRuntime(config, providerID) {
17283
+ const runtimes = config.local.runtimes.filter((runtime2) => runtime2.defaultModel.providerID === providerID);
17284
+ const runtime = runtimes[0];
17285
+ if (runtimes.length !== 1 || runtime === undefined || !runtime.enabled) {
17286
+ throw new ModelResidencyError("destination");
17287
+ }
17288
+ return runtime;
17289
+ }
17290
+ function createModelResidencyGuard(config, options) {
17291
+ const guarded = new Map;
17292
+ const blocked = new Set;
17293
+ let hostConfig;
17294
+ const readEnv = options.readEnv ?? ((name) => process.env[name]);
17295
+ const lemonadeRuntimes = () => config.local.runtimes.filter((runtime) => localRuntimeKind(runtime) === "lemonade");
17296
+ const protects = (providerID, baseURL) => lemonadeRuntimes().some((runtime) => {
17297
+ if (runtime.defaultModel.providerID === providerID)
17298
+ return true;
17299
+ if (baseURL === undefined)
17300
+ return false;
17301
+ const binding = endpointBinding(baseURL, readEnv);
17302
+ if (binding.ambiguous)
17303
+ return true;
17304
+ return binding.origin !== undefined && binding.origin === origin(runtime.baseURL ?? LEMONADE_DEFAULT_BASE_URL);
17305
+ });
17306
+ const resolvedWireID = (model, declaredID) => {
17307
+ const id = options.resolveApiModelID === undefined ? declaredID : options.resolveApiModelID(model);
17308
+ if (id === undefined)
17309
+ throw new ModelResidencyError("identity");
17310
+ return wireID(id, undefined);
17311
+ };
17312
+ const configHook = async (host) => {
17313
+ hostConfig = host;
17314
+ const previousGuards = new Map(guarded);
17315
+ guarded.clear();
17316
+ blocked.clear();
17317
+ for (const [providerID, provider] of Object.entries(host.provider ?? {})) {
17318
+ const routes = providerRoutes(provider);
17319
+ if (!routes.some((route) => protects(providerID, route.baseURL)))
17320
+ continue;
17321
+ const previous = previousGuards.get(providerID);
17322
+ const configuredFetch = provider.options?.fetch;
17323
+ const originalFetch = previous !== undefined && configuredFetch === previous.fetch ? previous.originalFetch : configuredFetch ?? options.fetch;
17324
+ blocked.add(providerID);
17325
+ const wasDisabled = host.disabled_providers?.includes(providerID) ?? false;
17326
+ host.disabled_providers = [
17327
+ ...new Set([...host.disabled_providers ?? [], providerID])
17328
+ ];
17329
+ const reject = Object.assign(async () => {
17330
+ throw new ModelResidencyError("transport");
17331
+ }, { preconnect: () => {} });
17332
+ provider.options = { ...provider.options, fetch: reject };
17333
+ try {
17334
+ const runtime = configuredRuntime(config, providerID);
17335
+ const baseURL = lemonadeBaseURL(runtime.baseURL ?? LEMONADE_DEFAULT_BASE_URL);
17336
+ if (localRuntimeKind(runtime) !== "lemonade" || routes.some((route) => route.baseURL === undefined || lemonadeBaseURL(route.baseURL) !== baseURL))
17337
+ throw new ModelResidencyError("destination");
17338
+ if (routes.some((route) => route.npm !== "@ai-sdk/openai-compatible") || nativeEligibleID(providerID) || !isFetch(originalFetch))
17339
+ throw new ModelResidencyError("transport");
17340
+ const modelKeys = new Map;
17341
+ for (const [key, model] of Object.entries(provider.models ?? {})) {
17342
+ if (model.options?.fetch !== undefined || model.options?.baseURL !== undefined && (typeof model.options.baseURL !== "string" || lemonadeBaseURL(model.options.baseURL) !== baseURL))
17343
+ throw new ModelResidencyError("transport");
17344
+ modelKeys.set(key, wireID(key, model));
17345
+ }
17346
+ if (!modelKeys.has(runtime.defaultModel.modelID))
17347
+ modelKeys.set(runtime.defaultModel.modelID, undefined);
17348
+ const modelIDs = () => {
17349
+ const ids = new Set;
17350
+ for (const [modelID2, declaredID] of modelKeys) {
17351
+ const id = options.resolveApiModelID === undefined ? declaredID : options.resolveApiModelID({ providerID, modelID: modelID2 });
17352
+ if (id !== undefined)
17353
+ ids.add(wireID(id, undefined));
17354
+ }
17355
+ return ids;
17356
+ };
17357
+ const fetch = createLemonadeGuardedFetch({
17358
+ ...options,
17359
+ baseURL,
17360
+ modelIDs: async () => {
17361
+ await options.modelInventoryReady?.();
17362
+ return modelIDs();
17363
+ },
17364
+ fetch: originalFetch,
17365
+ healthFetch: options.fetch
17366
+ });
17367
+ provider.options.fetch = fetch;
17368
+ guarded.set(providerID, {
17369
+ baseURL,
17370
+ fetch,
17371
+ originalFetch,
17372
+ modelIDs,
17373
+ modelKeys
17374
+ });
17375
+ blocked.delete(providerID);
17376
+ if (!wasDisabled) {
17377
+ host.disabled_providers = host.disabled_providers.filter((id) => id !== providerID);
17378
+ }
17379
+ } catch (error) {
17380
+ if (!(error instanceof ModelResidencyError))
17381
+ throw error;
17382
+ (options.warn ?? console.warn)(modelResidencyMessages.providerDisabled(providerID));
17383
+ }
17384
+ }
17385
+ };
17386
+ const beforeInference = async (input) => {
17387
+ const base = optionBaseURL(input.provider.options.baseURL) ?? input.model.api.url;
17388
+ if (!protects(input.model.providerID, base))
17389
+ return;
17390
+ const provider = guarded.get(input.model.providerID);
17391
+ if (provider === undefined || blocked.has(input.model.providerID) || input.provider.options.fetch !== provider.fetch || input.model.api.npm !== "@ai-sdk/openai-compatible" || nativeEligibleID(input.model.providerID))
17392
+ throw new ModelResidencyError("transport");
17393
+ if (lemonadeBaseURL(base) !== provider.baseURL) {
17394
+ throw new ModelResidencyError("destination");
17395
+ }
17396
+ const id = resolvedWireID({ providerID: input.model.providerID, modelID: input.model.id }, provider.modelKeys.get(input.model.id));
17397
+ if (id !== input.model.api.id)
17398
+ throw new ModelResidencyError("identity");
17399
+ if (!provider.modelKeys.has(input.model.id))
17400
+ provider.modelKeys.set(input.model.id, undefined);
17401
+ };
17402
+ const localTarget = (model) => {
17403
+ const runtime = configuredRuntime(config, model.providerID);
17404
+ if (hostConfig?.disabled_providers?.includes(model.providerID)) {
17405
+ throw new ModelResidencyError("transport");
17406
+ }
17407
+ if (runtime.baseURL === undefined)
17408
+ throw new ModelResidencyError("destination");
17409
+ const provider = hostConfig?.provider?.[model.providerID];
17410
+ const entry = Object.hasOwn(provider?.models ?? {}, model.modelID) ? provider?.models?.[model.modelID] : undefined;
17411
+ const configuredURL = provider === undefined ? undefined : providerBase(provider, entry);
17412
+ if (configuredURL !== undefined && new URL(configuredURL).href.replace(/\/$/, "") !== new URL(runtime.baseURL).href.replace(/\/$/, "")) {
17413
+ throw new ModelResidencyError("destination");
17414
+ }
17415
+ const modelID2 = resolvedWireID(model, entry === undefined && localRuntimeKind(runtime) === "lemonade" ? undefined : wireID(model.modelID, entry));
17416
+ let fetch = options.fetch;
17417
+ if (localRuntimeKind(runtime) === "lemonade") {
17418
+ const installed = guarded.get(model.providerID);
17419
+ if (installed === undefined || blocked.has(model.providerID)) {
17420
+ throw new ModelResidencyError("transport");
17421
+ }
17422
+ if (installed.baseURL !== lemonadeBaseURL(runtime.baseURL)) {
17423
+ throw new ModelResidencyError("destination");
17424
+ }
17425
+ if (!installed.modelKeys.has(model.modelID))
17426
+ installed.modelKeys.set(model.modelID, undefined);
17427
+ if (!installed.modelIDs().has(modelID2))
17428
+ throw new ModelResidencyError("identity");
17429
+ fetch = installed.fetch;
17430
+ }
17431
+ const configuredHeaders = z25.record(z25.string(), z25.string()).safeParse(provider?.options?.headers ?? {});
17432
+ if (!configuredHeaders.success)
17433
+ throw new ModelResidencyError("configuration");
17434
+ const headers = new Headers(configuredHeaders.data);
17435
+ if (typeof provider?.options?.apiKey === "string" && !headers.has("authorization")) {
17436
+ headers.set("authorization", `Bearer ${provider.options.apiKey}`);
17437
+ }
17438
+ for (const [name, value] of Object.entries(entry?.headers ?? {}))
17439
+ headers.set(name, value);
17440
+ const upstream = fetch;
17441
+ return {
17442
+ baseURL: runtime.baseURL,
17443
+ modelID: modelID2,
17444
+ fetch: [...headers].length === 0 ? fetch : Object.assign(async (input, init) => {
17445
+ const request = new Request(input, init);
17446
+ for (const [name, value] of headers) {
17447
+ if (!request.headers.has(name))
17448
+ request.headers.set(name, value);
17449
+ }
17450
+ return upstream(request);
17451
+ }, {
17452
+ preconnect: (...args) => upstream.preconnect?.(...args)
17453
+ })
17454
+ };
17455
+ };
17456
+ return { config: configHook, beforeInference, localTarget };
17457
+ }
17458
+
16842
17459
  // src/plugin/hooks.ts
16843
17460
  var codeSignals = [
16844
17461
  "```",
@@ -16982,7 +17599,10 @@ function createChatMessageHook(config, getAvailable, options = {}) {
16982
17599
  };
16983
17600
  }
16984
17601
  function createHooks(config, getAvailable, options = {}) {
17602
+ const residency = options.modelResidency ?? createModelResidencyGuard(config, { fetch: globalThis.fetch });
16985
17603
  return {
17604
+ config: residency.config,
17605
+ "chat.params": residency.beforeInference,
16986
17606
  "chat.message": createChatMessageHook(config, getAvailable, options)
16987
17607
  };
16988
17608
  }
@@ -17036,62 +17656,62 @@ ${lines.join(`
17036
17656
  }
17037
17657
 
17038
17658
  // src/memory/types.ts
17039
- import { z as z24 } from "zod";
17659
+ import { z as z26 } from "zod";
17040
17660
  var SHARED_OWNER_KEY = "*";
17041
- var OwnerKeySchema = z24.string().min(1);
17042
- var MemoryKindSchema = z24.enum(["fact", "preference", "entity"]);
17043
- var MemoryBaseSchema = z24.object({
17044
- id: z24.string().min(1),
17661
+ var OwnerKeySchema = z26.string().min(1);
17662
+ var MemoryKindSchema = z26.enum(["fact", "preference", "entity"]);
17663
+ var MemoryBaseSchema = z26.object({
17664
+ id: z26.string().min(1),
17045
17665
  ownerKey: OwnerKeySchema,
17046
- confidence: z24.number().min(0).max(1),
17047
- validFrom: z24.number().finite(),
17048
- validUntil: z24.number().finite().nullable().default(null),
17049
- createdAt: z24.number().finite(),
17050
- invalidatedAt: z24.number().finite().nullable().default(null),
17051
- sourceHash: z24.string().min(1),
17052
- supersededBy: z24.string().min(1).nullable().default(null)
17666
+ confidence: z26.number().min(0).max(1),
17667
+ validFrom: z26.number().finite(),
17668
+ validUntil: z26.number().finite().nullable().default(null),
17669
+ createdAt: z26.number().finite(),
17670
+ invalidatedAt: z26.number().finite().nullable().default(null),
17671
+ sourceHash: z26.string().min(1),
17672
+ supersededBy: z26.string().min(1).nullable().default(null)
17053
17673
  }).strict();
17054
17674
  var FactSchema = MemoryBaseSchema.extend({
17055
- kind: z24.literal("fact"),
17056
- subject: z24.string().min(1),
17057
- predicate: z24.string().min(1),
17058
- object: z24.string().min(1),
17059
- category: z24.string().min(1).nullable().default(null)
17675
+ kind: z26.literal("fact"),
17676
+ subject: z26.string().min(1),
17677
+ predicate: z26.string().min(1),
17678
+ object: z26.string().min(1),
17679
+ category: z26.string().min(1).nullable().default(null)
17060
17680
  });
17061
17681
  var PreferenceSchema = MemoryBaseSchema.extend({
17062
- kind: z24.literal("preference"),
17063
- category: z24.string().min(1),
17064
- preference: z24.string().min(1),
17065
- context: z24.string().min(1).nullable().default(null),
17066
- lastAccessedAt: z24.number().finite().nullable().default(null),
17067
- accessCount: z24.number().int().min(0).default(0)
17682
+ kind: z26.literal("preference"),
17683
+ category: z26.string().min(1),
17684
+ preference: z26.string().min(1),
17685
+ context: z26.string().min(1).nullable().default(null),
17686
+ lastAccessedAt: z26.number().finite().nullable().default(null),
17687
+ accessCount: z26.number().int().min(0).default(0)
17068
17688
  });
17069
17689
  var EntitySchema = MemoryBaseSchema.extend({
17070
- kind: z24.literal("entity"),
17071
- canonicalName: z24.string().min(1),
17072
- type: z24.string().min(1),
17073
- aliases: z24.array(z24.string().min(1)).default([])
17690
+ kind: z26.literal("entity"),
17691
+ canonicalName: z26.string().min(1),
17692
+ type: z26.string().min(1),
17693
+ aliases: z26.array(z26.string().min(1)).default([])
17074
17694
  });
17075
17695
  var RelationSchema = MemoryBaseSchema.extend({
17076
- kind: z24.literal("relation"),
17077
- from: z24.string().min(1),
17078
- to: z24.string().min(1),
17079
- predicate: z24.string().min(1),
17080
- annotation: z24.string().min(1).nullable().default(null)
17696
+ kind: z26.literal("relation"),
17697
+ from: z26.string().min(1),
17698
+ to: z26.string().min(1),
17699
+ predicate: z26.string().min(1),
17700
+ annotation: z26.string().min(1).nullable().default(null)
17081
17701
  });
17082
- var MemoryRecordSchema = z24.discriminatedUnion("kind", [
17702
+ var MemoryRecordSchema = z26.discriminatedUnion("kind", [
17083
17703
  FactSchema,
17084
17704
  PreferenceSchema,
17085
17705
  EntitySchema,
17086
17706
  RelationSchema
17087
17707
  ]);
17088
- var RecallQuerySchema = z24.object({
17708
+ var RecallQuerySchema = z26.object({
17089
17709
  ownerKey: OwnerKeySchema,
17090
- kinds: z24.array(MemoryKindSchema).default(["fact", "preference", "entity"]),
17091
- asOf: z24.number().finite().nullable().default(null),
17092
- limit: z24.number().int().positive().default(8),
17093
- minSimilarity: z24.number().min(0).max(1).default(0.2),
17094
- includeShared: z24.boolean().default(true)
17710
+ kinds: z26.array(MemoryKindSchema).default(["fact", "preference", "entity"]),
17711
+ asOf: z26.number().finite().nullable().default(null),
17712
+ limit: z26.number().int().positive().default(8),
17713
+ minSimilarity: z26.number().min(0).max(1).default(0.2),
17714
+ includeShared: z26.boolean().default(true)
17095
17715
  }).strict();
17096
17716
 
17097
17717
  // src/memory/rank.ts
@@ -17662,42 +18282,42 @@ function buildMemoryInjector(deps, policy) {
17662
18282
 
17663
18283
  // src/plugin/memoryTool.ts
17664
18284
  import { tool as tool4 } from "@opencode-ai/plugin";
17665
- import { z as z26 } from "zod";
18285
+ import { z as z28 } from "zod";
17666
18286
 
17667
18287
  // src/memory/extract.ts
17668
- import { z as z25 } from "zod";
18288
+ import { z as z27 } from "zod";
17669
18289
  var REDACTED = "[redacted]";
17670
- var RawFactSchema = z25.object({
17671
- subject: z25.string().min(1),
17672
- predicate: z25.string().min(1),
17673
- object: z25.string().min(1),
17674
- category: z25.string().min(1).nullable().optional(),
17675
- confidence: z25.number().min(0).max(1).optional()
18290
+ var RawFactSchema = z27.object({
18291
+ subject: z27.string().min(1),
18292
+ predicate: z27.string().min(1),
18293
+ object: z27.string().min(1),
18294
+ category: z27.string().min(1).nullable().optional(),
18295
+ confidence: z27.number().min(0).max(1).optional()
17676
18296
  });
17677
- var RawPreferenceSchema = z25.object({
17678
- category: z25.string().min(1),
17679
- preference: z25.string().min(1),
17680
- context: z25.string().min(1).nullable().optional(),
17681
- confidence: z25.number().min(0).max(1).optional()
18297
+ var RawPreferenceSchema = z27.object({
18298
+ category: z27.string().min(1),
18299
+ preference: z27.string().min(1),
18300
+ context: z27.string().min(1).nullable().optional(),
18301
+ confidence: z27.number().min(0).max(1).optional()
17682
18302
  });
17683
- var RawEntitySchema = z25.object({
17684
- canonicalName: z25.string().min(1),
17685
- type: z25.string().min(1),
17686
- aliases: z25.array(z25.string().min(1)).optional(),
17687
- confidence: z25.number().min(0).max(1).optional()
18303
+ var RawEntitySchema = z27.object({
18304
+ canonicalName: z27.string().min(1),
18305
+ type: z27.string().min(1),
18306
+ aliases: z27.array(z27.string().min(1)).optional(),
18307
+ confidence: z27.number().min(0).max(1).optional()
17688
18308
  });
17689
- var RawRelationSchema = z25.object({
17690
- from: z25.string().min(1),
17691
- to: z25.string().min(1),
17692
- predicate: z25.string().min(1),
17693
- annotation: z25.string().min(1).nullable().optional(),
17694
- confidence: z25.number().min(0).max(1).optional()
18309
+ var RawRelationSchema = z27.object({
18310
+ from: z27.string().min(1),
18311
+ to: z27.string().min(1),
18312
+ predicate: z27.string().min(1),
18313
+ annotation: z27.string().min(1).nullable().optional(),
18314
+ confidence: z27.number().min(0).max(1).optional()
17695
18315
  }).strict();
17696
- var RawExtractionSchema = z25.object({
17697
- facts: z25.array(RawFactSchema).default([]),
17698
- preferences: z25.array(RawPreferenceSchema).default([]),
17699
- entities: z25.array(RawEntitySchema).default([]),
17700
- relations: z25.array(RawRelationSchema).default([])
18316
+ var RawExtractionSchema = z27.object({
18317
+ facts: z27.array(RawFactSchema).default([]),
18318
+ preferences: z27.array(RawPreferenceSchema).default([]),
18319
+ entities: z27.array(RawEntitySchema).default([]),
18320
+ relations: z27.array(RawRelationSchema).default([])
17701
18321
  });
17702
18322
  var DEFAULT_CONFIDENCE = 0.6;
17703
18323
  var SYSTEM_PROMPT = [
@@ -17951,13 +18571,13 @@ var memoryToolMessages = {
17951
18571
 
17952
18572
  // src/plugin/memoryTool.ts
17953
18573
  var SCRIBE_ROLE_ID = "scribe";
17954
- var MemoryMessageSchema = z26.object({
17955
- role: z26.enum(["system", "user", "assistant"]).describe(memoryToolMessages.messageRoleDescription),
17956
- content: z26.string().min(1).describe(memoryToolMessages.messageContentDescription)
18574
+ var MemoryMessageSchema = z28.object({
18575
+ role: z28.enum(["system", "user", "assistant"]).describe(memoryToolMessages.messageRoleDescription),
18576
+ content: z28.string().min(1).describe(memoryToolMessages.messageContentDescription)
17957
18577
  }).strict();
17958
- var MemoryWritePayloadSchema = z26.object({
17959
- messages: z26.array(MemoryMessageSchema).min(1).describe(memoryToolMessages.messagesDescription),
17960
- roleID: z26.string().min(1).default(SCRIBE_ROLE_ID).describe(memoryToolMessages.roleIDDescription)
18578
+ var MemoryWritePayloadSchema = z28.object({
18579
+ messages: z28.array(MemoryMessageSchema).min(1).describe(memoryToolMessages.messagesDescription),
18580
+ roleID: z28.string().min(1).default(SCRIBE_ROLE_ID).describe(memoryToolMessages.roleIDDescription)
17961
18581
  }).strict();
17962
18582
  function createMemoryTool(deps) {
17963
18583
  return tool4({
@@ -17969,7 +18589,7 @@ function createMemoryTool(deps) {
17969
18589
  })).describe(memoryToolMessages.messagesDescription),
17970
18590
  roleID: tool4.schema.string().optional().describe(memoryToolMessages.roleIDDescription)
17971
18591
  },
17972
- async execute(args) {
18592
+ async execute(args, toolContext) {
17973
18593
  const parsed = MemoryWritePayloadSchema.safeParse(args);
17974
18594
  if (!parsed.success) {
17975
18595
  return memoryToolMessages.validationError(parsed.error.message);
@@ -17990,33 +18610,83 @@ function createMemoryTool(deps) {
17990
18610
  if (executionMode2 === "frontier") {
17991
18611
  return memoryToolMessages.frontierDomainRefusal;
17992
18612
  }
17993
- if (!await deps.localRuntimeReachable()) {
17994
- return memoryToolMessages.localRuntimeUnavailable;
17995
- }
17996
- const runtime = deps.config.local.runtimes.find((rt) => rt.enabled && typeof rt.baseURL === "string" && rt.baseURL.length > 0);
17997
- if (runtime?.baseURL === undefined) {
17998
- return memoryToolMessages.localRuntimeBaseURLMissing;
17999
- }
18000
- const modelID = semantic.extraction.model?.modelID ?? runtime.defaultModel.modelID;
18001
- const transcript = messages.map((m) => `${m.role}: ${m.content}`).join(`
18002
- `);
18003
- const sourceHash = sha256Hex(transcript);
18004
- const now = deps.now();
18005
- const context = {
18006
- ownerKey: semantic.scope === "user" ? "user" : "project",
18007
- now,
18008
- sourceHash,
18009
- storeContent: semantic.storeContent,
18010
- idPrefix: `${sourceHash.slice(0, 12)}:${now}`
18011
- };
18012
18613
  let records;
18013
18614
  try {
18615
+ const signal = toolContext.abort;
18616
+ const throwIfAborted = () => {
18617
+ if (signal?.aborted)
18618
+ throw new ModelResidencyError("cancelled");
18619
+ };
18620
+ throwIfAborted();
18621
+ const configuredModel = semantic.extraction.model;
18622
+ let runtime;
18623
+ if (configuredModel != null) {
18624
+ const matches = deps.config.local.runtimes.filter((candidate) => candidate.defaultModel.providerID === configuredModel.providerID);
18625
+ runtime = matches[0];
18626
+ if (matches.length !== 1 || runtime === undefined || !runtime.enabled) {
18627
+ return modelResidencyMessages.extractionRuntimeUnavailable;
18628
+ }
18629
+ } else {
18630
+ runtime = deps.config.local.runtimes.find((candidate) => candidate.enabled && typeof candidate.baseURL === "string" && candidate.baseURL.length > 0);
18631
+ }
18632
+ if (runtime?.baseURL === undefined || runtime.baseURL.length === 0) {
18633
+ return memoryToolMessages.localRuntimeBaseURLMissing;
18634
+ }
18635
+ const baseURL = runtime.baseURL;
18636
+ const model = configuredModel ?? runtime.defaultModel;
18637
+ const selectedRuntime = runtime;
18638
+ const deadline = {
18639
+ ...deps.residencyOptions,
18640
+ ...signal === undefined ? {} : { signal }
18641
+ };
18642
+ const reachable = localRuntimeKind(runtime) === "lemonade" ? await withResidencyDeadline((signal2) => deps.localRuntimeReachable(selectedRuntime, signal2), deadline) : await deps.localRuntimeReachable(runtime);
18643
+ throwIfAborted();
18644
+ if (!reachable)
18645
+ return memoryToolMessages.localRuntimeUnavailable;
18646
+ const resolveTarget = deps.resolveExtractionTarget;
18647
+ const target = resolveTarget ? await withResidencyDeadline(async () => resolveTarget(model), deadline) : {
18648
+ baseURL,
18649
+ modelID: model.modelID,
18650
+ fetch: localRuntimeKind(runtime) === "lemonade" ? createLemonadeGuardedFetch({
18651
+ baseURL,
18652
+ fetch: deps.fetch,
18653
+ modelIDs: new Set([model.modelID]),
18654
+ ...deps.residencyOptions
18655
+ }) : deps.fetch
18656
+ };
18657
+ throwIfAborted();
18658
+ if (target === undefined || target.baseURL !== baseURL) {
18659
+ throw new ModelResidencyError("destination");
18660
+ }
18661
+ const fetch = signal === undefined ? target.fetch : Object.assign(async (input, init) => {
18662
+ throwIfAborted();
18663
+ const response = await target.fetch(input, {
18664
+ ...init,
18665
+ signal
18666
+ });
18667
+ throwIfAborted();
18668
+ return response;
18669
+ }, {
18670
+ preconnect: (...args2) => target.fetch.preconnect?.(...args2)
18671
+ });
18672
+ const transcript = messages.map((m) => `${m.role}: ${m.content}`).join(`
18673
+ `);
18674
+ const sourceHash = sha256Hex(transcript);
18675
+ const now = deps.now();
18676
+ const context = {
18677
+ ownerKey: semantic.scope === "user" ? "user" : "project",
18678
+ now,
18679
+ sourceHash,
18680
+ storeContent: semantic.storeContent,
18681
+ idPrefix: `${sourceHash.slice(0, 12)}:${now}`
18682
+ };
18014
18683
  records = await extractMemory({
18015
- baseURL: runtime.baseURL,
18016
- modelID,
18684
+ baseURL: target.baseURL,
18685
+ modelID: target.modelID,
18017
18686
  messages,
18018
18687
  context
18019
- }, { fetch: deps.fetch, ...deps.warn ? { warn: deps.warn } : {} });
18688
+ }, { fetch, ...deps.warn ? { warn: deps.warn } : {} });
18689
+ throwIfAborted();
18020
18690
  } catch (error) {
18021
18691
  const reason = error instanceof Error ? error.message : String(error);
18022
18692
  return memoryToolMessages.extractionFailure(reason);
@@ -18082,10 +18752,10 @@ function createOrchestratedModelOwnership() {
18082
18752
 
18083
18753
  // src/plugin/orchestrateTool.ts
18084
18754
  import { tool as tool5 } from "@opencode-ai/plugin";
18085
- import { z as z28 } from "zod";
18755
+ import { z as z30 } from "zod";
18086
18756
 
18087
18757
  // src/orchestrator/coordinator.ts
18088
- import { z as z27 } from "zod";
18758
+ import { z as z29 } from "zod";
18089
18759
 
18090
18760
  // src/orchestrator/nodeIteration.ts
18091
18761
  var DEFAULT_MAX_RETRIES = 2;
@@ -18295,12 +18965,15 @@ async function applyReportDurabilityGate(results, probe) {
18295
18965
  }
18296
18966
 
18297
18967
  // src/orchestrator/runtimeSelection.ts
18298
- function configuredRuntime(runtimeId, config) {
18968
+ function configuredRuntime2(runtimeId, config) {
18299
18969
  return config.local.runtimes.find((runtime) => runtime.id === runtimeId);
18300
18970
  }
18301
18971
  function runtimeIdOfModel(model, config) {
18302
18972
  return config.local.runtimes.find((runtime) => sameModel(runtime.defaultModel, model))?.id;
18303
18973
  }
18974
+ function enabledRuntimeForProvider(providerID, config) {
18975
+ return config.local.runtimes.find((runtime) => runtime.enabled && runtime.defaultModel.providerID === providerID)?.id;
18976
+ }
18304
18977
  function roleLocalModel(role, runtimeId, fallback, runtime) {
18305
18978
  const pinned = role.localModels?.[runtimeId];
18306
18979
  if (pinned !== undefined) {
@@ -18315,7 +18988,7 @@ function runtimeClassModel(modelClass, runtime) {
18315
18988
  }
18316
18989
  return modelClass === "thinking" ? runtime.thinkingModel : runtime.coderModel;
18317
18990
  }
18318
- function selectDispatchRuntime(role, decision2, reachable, config) {
18991
+ function selectDispatchRuntime(role, decision2, reachable, config, availableModels2) {
18319
18992
  if (decision2.routeKind !== "local") {
18320
18993
  return { runtimeId: undefined, decision: decision2 };
18321
18994
  }
@@ -18326,7 +18999,7 @@ function selectDispatchRuntime(role, decision2, reachable, config) {
18326
18999
  if (!reachable.has(runtimeId)) {
18327
19000
  continue;
18328
19001
  }
18329
- const runtime = configuredRuntime(runtimeId, config);
19002
+ const runtime = configuredRuntime2(runtimeId, config);
18330
19003
  if (runtime?.defaultModel.providerID === decision2.selected.providerID) {
18331
19004
  return { runtimeId, decision: decision2 };
18332
19005
  }
@@ -18336,15 +19009,17 @@ function selectDispatchRuntime(role, decision2, reachable, config) {
18336
19009
  if (exactRuntimeId !== undefined) {
18337
19010
  return { runtimeId: exactRuntimeId, decision: decision2 };
18338
19011
  }
18339
- const providerRuntime = config.local.runtimes.find((runtime) => runtime.enabled && runtime.defaultModel.providerID === decision2.selected.providerID);
18340
- return { runtimeId: providerRuntime?.id, decision: decision2 };
19012
+ return {
19013
+ runtimeId: enabledRuntimeForProvider(decision2.selected.providerID, config),
19014
+ decision: decision2
19015
+ };
18341
19016
  }
18342
19017
  if (listed !== undefined && listed.length > 0 && reachable !== undefined) {
18343
19018
  for (const runtimeId of listed) {
18344
19019
  if (!reachable.has(runtimeId)) {
18345
19020
  continue;
18346
19021
  }
18347
- const runtime = configuredRuntime(runtimeId, config);
19022
+ const runtime = configuredRuntime2(runtimeId, config);
18348
19023
  if (runtime === undefined) {
18349
19024
  continue;
18350
19025
  }
@@ -18357,7 +19032,7 @@ function selectDispatchRuntime(role, decision2, reachable, config) {
18357
19032
  }
18358
19033
  const resolvedRuntimeId = runtimeIdOfModel(decision2.selected, config);
18359
19034
  if (resolvedRuntimeId !== undefined) {
18360
- const pinned = roleLocalModel(role, resolvedRuntimeId, decision2.selected, configuredRuntime(resolvedRuntimeId, config));
19035
+ const pinned = roleLocalModel(role, resolvedRuntimeId, decision2.selected, configuredRuntime2(resolvedRuntimeId, config));
18361
19036
  if (pinned !== decision2.selected) {
18362
19037
  return {
18363
19038
  runtimeId: resolvedRuntimeId,
@@ -18365,8 +19040,9 @@ function selectDispatchRuntime(role, decision2, reachable, config) {
18365
19040
  };
18366
19041
  }
18367
19042
  }
19043
+ const knownAlias = localModelAliases(decision2.selected.providerID, availableModels2).has(decision2.selected.modelID);
18368
19044
  return {
18369
- runtimeId: resolvedRuntimeId,
19045
+ runtimeId: resolvedRuntimeId ?? (knownAlias ? enabledRuntimeForProvider(decision2.selected.providerID, config) : undefined),
18370
19046
  decision: decision2
18371
19047
  };
18372
19048
  }
@@ -18553,7 +19229,7 @@ function buildRecord(input, decision2, subsession, deps, decisionID, batchID) {
18553
19229
  }
18554
19230
  return record;
18555
19231
  }
18556
- var TelemetryFailureClassSchema = z27.enum([
19232
+ var TelemetryFailureClassSchema = z29.enum([
18557
19233
  "create-rejected",
18558
19234
  "create-no-id",
18559
19235
  "prompt-rejected",
@@ -18812,7 +19488,7 @@ async function runRoleTaskWithCorrelation(input, deps, correlation, batch, route
18812
19488
  if (routed.routeKind === "blocked") {
18813
19489
  throw new Error(coordinatorRoutingBlocked(input.roleID, routed.blockReason));
18814
19490
  }
18815
- const selection = selectDispatchRuntime(role, routed, batch.set, input.config);
19491
+ const selection = selectDispatchRuntime(role, routed, batch.set, input.config, input.availableModels);
18816
19492
  const decision2 = selection.decision;
18817
19493
  const composed = composeSubsessionPrompt({
18818
19494
  prompt: input.prompt,
@@ -18894,8 +19570,9 @@ async function runRoleTaskWithCorrelation(input, deps, correlation, batch, route
18894
19570
  if (runtimeId !== undefined && deps.runtimeLimiter !== undefined) {
18895
19571
  const limiter = deps.runtimeLimiter;
18896
19572
  const priority = priorityForRole(role);
18897
- const dispatchRuntime = configuredRuntime(runtimeId, input.config) ?? { id: runtimeId };
18898
- const poolKey = slotPoolKey(withReportedModelSlots(dispatchRuntime, deps.reportedModelSlots?.(runtimeId)), decision2.selected.modelID);
19573
+ const dispatchRuntime = configuredRuntime2(runtimeId, input.config) ?? { id: runtimeId };
19574
+ const aliases = localModelAliases(decision2.selected.providerID, input.availableModels);
19575
+ const poolKey = slotPoolKey(withReportedModelSlots(dispatchRuntime, deps.reportedModelSlots?.(runtimeId), aliases), aliases.get(decision2.selected.modelID) ?? decision2.selected.modelID);
18899
19576
  release = limiter.tryAcquire(poolKey, priority);
18900
19577
  let waitedMs = 0;
18901
19578
  if (release === undefined) {
@@ -19369,7 +20046,7 @@ async function runRoleTasks(inputs, deps, options = {}) {
19369
20046
  var _pluginWarnedRoles = new Set;
19370
20047
  var EMPTY_ROLE_ID_SET = new Set;
19371
20048
  var SAFE_ROLE_ID = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
19372
- var RoleIDSchema = z28.string().min(1).superRefine((roleID, ctx) => {
20049
+ var RoleIDSchema = z30.string().min(1).superRefine((roleID, ctx) => {
19373
20050
  if (!SAFE_ROLE_ID.test(roleID)) {
19374
20051
  ctx.addIssue({
19375
20052
  code: "custom",
@@ -19377,16 +20054,16 @@ var RoleIDSchema = z28.string().min(1).superRefine((roleID, ctx) => {
19377
20054
  });
19378
20055
  }
19379
20056
  });
19380
- var RoleAssignmentSchema = z28.object({
20057
+ var RoleAssignmentSchema = z30.object({
19381
20058
  roleID: RoleIDSchema.describe("Role identifier from the roster"),
19382
- prompt: z28.string().min(1).describe("Work prompt for this role"),
19383
- title: z28.string().min(1).optional().describe("Human-readable title"),
19384
- dependsOn: z28.array(RoleIDSchema).optional().describe("Role IDs this assignment depends on (DAG edges)")
20059
+ prompt: z30.string().min(1).describe("Work prompt for this role"),
20060
+ title: z30.string().min(1).optional().describe("Human-readable title"),
20061
+ dependsOn: z30.array(RoleIDSchema).optional().describe("Role IDs this assignment depends on (DAG edges)")
19385
20062
  }).strict();
19386
- var OrchestratePayloadSchema = z28.object({
19387
- assignments: z28.array(RoleAssignmentSchema).min(1).describe("Role assignments to distribute"),
19388
- parentSessionID: z28.string().min(1).optional().describe(PARENT_SESSION_DESCRIPTION),
19389
- directory: z28.string().min(1).optional().describe("Working directory override")
20063
+ var OrchestratePayloadSchema = z30.object({
20064
+ assignments: z30.array(RoleAssignmentSchema).min(1).describe("Role assignments to distribute"),
20065
+ parentSessionID: z30.string().min(1).optional().describe(PARENT_SESSION_DESCRIPTION),
20066
+ directory: z30.string().min(1).optional().describe("Working directory override")
19390
20067
  }).strict();
19391
20068
  function validateAssignmentDependencies(assignments) {
19392
20069
  const ids = new Set;
@@ -20122,7 +20799,7 @@ ${advisory}`;
20122
20799
 
20123
20800
  // src/plugin/registerCastTool.ts
20124
20801
  import { tool as tool6 } from "@opencode-ai/plugin";
20125
- import { z as z29 } from "zod";
20802
+ import { z as z31 } from "zod";
20126
20803
 
20127
20804
  // src/messages/rosterSummary.ts
20128
20805
  var ROSTER_SUMMARY_HEADING = "Registered team model policies";
@@ -20351,13 +21028,13 @@ async function persistPreparedTeam(storage, files) {
20351
21028
  }
20352
21029
 
20353
21030
  // src/plugin/registerCastTool.ts
20354
- var CastEntrySchema = z29.object({
20355
- roleID: z29.string().min(1).describe("Stable role identifier, e.g. scribe or guardian"),
20356
- agentName: z29.string().min(1).describe("Themed character name assigned to the role")
21031
+ var CastEntrySchema = z31.object({
21032
+ roleID: z31.string().min(1).describe("Stable role identifier, e.g. scribe or guardian"),
21033
+ agentName: z31.string().min(1).describe("Themed character name assigned to the role")
20357
21034
  }).strict();
20358
- var RegisterCastPayloadSchema = z29.object({
20359
- universe: z29.string().min(1).describe("Casting universe for this roster"),
20360
- entries: z29.array(CastEntrySchema).min(1).describe("Role-to-name mappings")
21035
+ var RegisterCastPayloadSchema = z31.object({
21036
+ universe: z31.string().min(1).describe("Casting universe for this roster"),
21037
+ entries: z31.array(CastEntrySchema).min(1).describe("Role-to-name mappings")
20361
21038
  }).strict();
20362
21039
  function offendingFields(error) {
20363
21040
  const fields = error.issues.flatMap((issue) => {
@@ -20976,7 +21653,7 @@ async function buildMemoryRuntimeFromConfig(config, deps, options = {}) {
20976
21653
  if (runtime?.baseURL === undefined) {
20977
21654
  return;
20978
21655
  }
20979
- const modelID = semantic.embeddings.model?.modelID ?? runtime.defaultModel.modelID;
21656
+ const modelID2 = semantic.embeddings.model?.modelID ?? runtime.defaultModel.modelID;
20980
21657
  const openDatabase = deps.openDatabase ?? createBunSqliteDatabase;
20981
21658
  const makeEmbedder = deps.createEmbedder ?? createLocalEmbedder;
20982
21659
  const fetchImpl = deps.fetch ?? globalThis.fetch;
@@ -20989,8 +21666,8 @@ async function buildMemoryRuntimeFromConfig(config, deps, options = {}) {
20989
21666
  if (rebuildResult.rejectedLines > 0) {
20990
21667
  warn(`[openteam] memory log rejected ${rebuildResult.rejectedLines} line(s); semantic memory may be incomplete.`);
20991
21668
  }
20992
- const embedder = makeEmbedder({ baseURL: runtime.baseURL, modelID }, { fetch: fetchImpl });
20993
- await ensureMemoryEmbeddings({ index, embedder, model: modelID, warn });
21669
+ const embedder = makeEmbedder({ baseURL: runtime.baseURL, modelID: modelID2 }, { fetch: fetchImpl });
21670
+ await ensureMemoryEmbeddings({ index, embedder, model: modelID2, warn });
20994
21671
  return {
20995
21672
  index,
20996
21673
  embedder,
@@ -21018,18 +21695,18 @@ import { join as join15, resolve as resolve11 } from "node:path";
21018
21695
  import { ZodError } from "zod";
21019
21696
 
21020
21697
  // src/storage/lifecycle/codec.ts
21021
- import { z as z30 } from "zod";
21698
+ import { z as z32 } from "zod";
21022
21699
  var LIFECYCLE_CODEC_VERSION = 1;
21023
21700
  var LIFECYCLE_GENESIS_DIGEST = sha256Hex("openteam/lifecycle-journal/genesis/v1");
21024
21701
  var NUL5 = "\x00";
21025
21702
  var NEWLINE2 = `
21026
21703
  `;
21027
- var frameSchema = z30.object({
21028
- v: z30.literal(LIFECYCLE_CODEC_VERSION),
21029
- seq: z30.number().int().nonnegative(),
21030
- prev: z30.string().min(1),
21031
- sum: z30.string().min(1),
21032
- event: z30.unknown()
21704
+ var frameSchema = z32.object({
21705
+ v: z32.literal(LIFECYCLE_CODEC_VERSION),
21706
+ seq: z32.number().int().nonnegative(),
21707
+ prev: z32.string().min(1),
21708
+ sum: z32.string().min(1),
21709
+ event: z32.unknown()
21033
21710
  }).strict();
21034
21711
  function canonical2(value) {
21035
21712
  if (Array.isArray(value)) {
@@ -21369,8 +22046,8 @@ function readRun(runDir, runID) {
21369
22046
  if (metadataText === undefined || eventsText === undefined) {
21370
22047
  throw new LifecycleFsError("corrupt");
21371
22048
  }
21372
- const metadata = parseJson(metadataText, parseLifecycleRunMetadata);
21373
- if (metadata.runID !== runID) {
22049
+ const metadata2 = parseJson(metadataText, parseLifecycleRunMetadata);
22050
+ if (metadata2.runID !== runID) {
21374
22051
  throw new LifecycleFsError("corrupt");
21375
22052
  }
21376
22053
  let decoded;
@@ -21385,10 +22062,10 @@ function readRun(runDir, runID) {
21385
22062
  }
21386
22063
  }
21387
22064
  const first = decoded.events[0];
21388
- if (first === undefined || first.type !== "run.started" || first.source !== metadata.source || first.executionAuthority !== metadata.executionAuthority || first.root.operationID !== metadata.root.operationID || first.root.taskID !== metadata.root.taskID) {
22065
+ if (first === undefined || first.type !== "run.started" || first.source !== metadata2.source || first.executionAuthority !== metadata2.executionAuthority || first.root.operationID !== metadata2.root.operationID || first.root.taskID !== metadata2.root.taskID) {
21389
22066
  throw new LifecycleFsError("corrupt");
21390
22067
  }
21391
- return { metadata, decoded };
22068
+ return { metadata: metadata2, decoded };
21392
22069
  }
21393
22070
  function terminalOutcome(events) {
21394
22071
  const last = events.at(-1);
@@ -21466,7 +22143,7 @@ var createFsLifecycleJournal = (options) => {
21466
22143
  mkdirSync3(stagingPath);
21467
22144
  const writerToken = issueWriterToken();
21468
22145
  const eventAt = now();
21469
- const metadata = parseLifecycleRunMetadata({
22146
+ const metadata2 = parseLifecycleRunMetadata({
21470
22147
  ...parsedInput,
21471
22148
  version: 1,
21472
22149
  createdAt: eventAt
@@ -21482,7 +22159,7 @@ var createFsLifecycleJournal = (options) => {
21482
22159
  executionAuthority: parsedInput.executionAuthority,
21483
22160
  root: parsedInput.root
21484
22161
  });
21485
- writeDurable2(join15(stagingPath, METADATA_FILE), `${JSON.stringify(metadata)}
22162
+ writeDurable2(join15(stagingPath, METADATA_FILE), `${JSON.stringify(metadata2)}
21486
22163
  `);
21487
22164
  writeDurable2(join15(stagingPath, EVENTS_FILE), encodeLifecycleJournal([event]));
21488
22165
  writeDurable2(join15(stagingPath, OWNER_FILE2), `${JSON.stringify(lease)}
@@ -21498,7 +22175,7 @@ var createFsLifecycleJournal = (options) => {
21498
22175
  stagingPath = undefined;
21499
22176
  return ok({
21500
22177
  handle: { runID, writerToken },
21501
- metadata,
22178
+ metadata: metadata2,
21502
22179
  event,
21503
22180
  lease,
21504
22181
  head: 1
@@ -22359,6 +23036,9 @@ async function listConfiguredOpencodeInventory(ctx) {
22359
23036
  providerID: model.providerID,
22360
23037
  modelID: model.id
22361
23038
  };
23039
+ if (typeof model.api?.id === "string" && model.api.id.length > 0 && model.api.id === model.api.id.trim() && model.api.id !== model.id) {
23040
+ configuredModel.apiModelID = model.api.id;
23041
+ }
22362
23042
  if (typeof model.capabilities?.toolcall === "boolean") {
22363
23043
  configuredModel.supportsTools = model.capabilities.toolcall;
22364
23044
  }
@@ -22428,12 +23108,20 @@ var server = async (ctx, rawOptions) => {
22428
23108
  const injectMemory = await buildMemoryInjectorFromConfig(config, storage, diagnostics.warn("memory-runtime-warning", { toast: false }));
22429
23109
  const sessionTracker = createSessionTracker();
22430
23110
  const orchestratedModelOwnership = createOrchestratedModelOwnership();
23111
+ const modelResidency = createModelResidencyGuard(config, {
23112
+ fetch: globalThis.fetch,
23113
+ ...ctx.client.config?.providers === undefined ? {} : {
23114
+ resolveApiModelID: cache.resolveApiModelID,
23115
+ modelInventoryReady: ensureAvailability
23116
+ }
23117
+ });
22431
23118
  const resolveAgentRole = async (agentName) => {
22432
23119
  const entry = (await readRoutingRosterEntries(storage)).find((candidate) => candidate.agentName === agentName);
22433
23120
  return entry?.roleID;
22434
23121
  };
22435
23122
  const hooks = createHooks(config, cache.get, injectMemory === undefined ? {
22436
23123
  sink,
23124
+ modelResidency,
22437
23125
  beforeRoute: ensureAvailability,
22438
23126
  capabilityProfiles,
22439
23127
  orchestratedModelOwnership,
@@ -22441,6 +23129,7 @@ var server = async (ctx, rawOptions) => {
22441
23129
  onRoute: (sid, model) => sessionTracker.trackRoutedModel(sid, model)
22442
23130
  } : {
22443
23131
  sink,
23132
+ modelResidency,
22444
23133
  beforeRoute: ensureAvailability,
22445
23134
  capabilityProfiles,
22446
23135
  injectMemory,
@@ -22561,7 +23250,7 @@ var server = async (ctx, rawOptions) => {
22561
23250
  if (runtime === undefined) {
22562
23251
  return;
22563
23252
  }
22564
- return withReportedModelSlots(runtime, reportedSlotsByRuntime.get(runtimeId));
23253
+ return withReportedModelSlots(runtime, reportedSlotsByRuntime.get(runtimeId), localModelAliases(runtime.defaultModel.providerID, cache.get()));
22565
23254
  };
22566
23255
  const runtimeLimiter = createRuntimeConcurrencyLimiter({
22567
23256
  capacityFor: (key2) => {
@@ -22606,7 +23295,27 @@ var server = async (ctx, rawOptions) => {
22606
23295
  config,
22607
23296
  storage,
22608
23297
  now,
22609
- localRuntimeReachable,
23298
+ localRuntimeReachable: async (runtime, signal) => {
23299
+ if (localRuntimeKind(runtime) === "lemonade") {
23300
+ if (ctx.client.config?.providers !== undefined)
23301
+ await ensureAvailability();
23302
+ signal?.throwIfAborted();
23303
+ const target = modelResidency.localTarget(resolveMemorySemantic(config).extraction.model ?? runtime.defaultModel);
23304
+ const response = await target.fetch(`${target.baseURL}/health`, {
23305
+ method: "GET",
23306
+ ...signal === undefined ? {} : { signal }
23307
+ });
23308
+ return response.ok;
23309
+ }
23310
+ const snapshots = await registry.probe([runtime]);
23311
+ rememberReportedSlots(snapshots);
23312
+ return anyRuntimeReachable(snapshots);
23313
+ },
23314
+ resolveExtractionTarget: async (model) => {
23315
+ if (ctx.client.config?.providers !== undefined)
23316
+ await ensureAvailability();
23317
+ return modelResidency.localTarget(model);
23318
+ },
22610
23319
  fetch: globalThis.fetch,
22611
23320
  warn: diagnostics.warn("memory-extraction-warning", { toast: false })
22612
23321
  });