@jmanuelcorral/openteam 0.24.0 → 0.25.0

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 (58) hide show
  1. package/README.es.md +20 -5
  2. package/README.md +14 -2
  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 +1251 -554
  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/console/assets.d.ts.map +1 -1
  15. package/dist/console/conversation.d.ts +5 -1
  16. package/dist/console/conversation.d.ts.map +1 -1
  17. package/dist/console/credentials.d.ts +4 -0
  18. package/dist/console/credentials.d.ts.map +1 -0
  19. package/dist/console/inspector.d.ts +1 -1
  20. package/dist/console/inspector.d.ts.map +1 -1
  21. package/dist/console/refresh.d.ts +1 -1
  22. package/dist/console/refresh.d.ts.map +1 -1
  23. package/dist/console/render.d.ts.map +1 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +999 -287
  26. package/dist/local/lemonade.d.ts.map +1 -1
  27. package/dist/local/lemonadeRequestGuard.d.ts +11 -0
  28. package/dist/local/lemonadeRequestGuard.d.ts.map +1 -0
  29. package/dist/local/lemonadeResidency.d.ts +22 -0
  30. package/dist/local/lemonadeResidency.d.ts.map +1 -0
  31. package/dist/local/modelResidency.d.ts +4 -0
  32. package/dist/local/modelResidency.d.ts.map +1 -0
  33. package/dist/local/slotPool.d.ts +13 -7
  34. package/dist/local/slotPool.d.ts.map +1 -1
  35. package/dist/messages/consoleDetail.d.ts +8 -5
  36. package/dist/messages/consoleDetail.d.ts.map +1 -1
  37. package/dist/messages/executionSetup.d.ts +19 -0
  38. package/dist/messages/executionSetup.d.ts.map +1 -1
  39. package/dist/messages/modelResidency.d.ts +19 -0
  40. package/dist/messages/modelResidency.d.ts.map +1 -0
  41. package/dist/orchestrator/coordinator.d.ts.map +1 -1
  42. package/dist/orchestrator/runtimeSelection.d.ts +4 -3
  43. package/dist/orchestrator/runtimeSelection.d.ts.map +1 -1
  44. package/dist/plugin/availability.d.ts +4 -1
  45. package/dist/plugin/availability.d.ts.map +1 -1
  46. package/dist/plugin/hooks.d.ts +2 -0
  47. package/dist/plugin/hooks.d.ts.map +1 -1
  48. package/dist/plugin/memoryTool.d.ts +9 -3
  49. package/dist/plugin/memoryTool.d.ts.map +1 -1
  50. package/dist/plugin/modelResidency.d.ts +47 -0
  51. package/dist/plugin/modelResidency.d.ts.map +1 -0
  52. package/dist/router/types.d.ts +2 -0
  53. package/dist/router/types.d.ts.map +1 -1
  54. package/dist/web/conversationRoute.d.ts +2 -2
  55. package/dist/web/conversationRoute.d.ts.map +1 -1
  56. package/dist/web/server.d.ts +1 -1
  57. package/dist/web/server.d.ts.map +1 -1
  58. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -786,6 +786,9 @@ function migrateConfig(raw) {
786
786
  var consoleDetailMessages = {
787
787
  follow: "Follow new activity",
788
788
  metadataOnly: "Lifecycle and telemetry stay metadata-only.",
789
+ logsDescription: "Current recorded conversations load automatically. Lifecycle and telemetry remain metadata-only; credentials are masked.",
790
+ credentialMasked: "[credential masked]",
791
+ offscreen: "Messages load automatically when this conversation is visible.",
789
792
  filter: "Filter sessions",
790
793
  incoming: "New activity available — show updates",
791
794
  refreshError: "Live updates unavailable; retrying.",
@@ -806,7 +809,7 @@ var consoleDetailMessages = {
806
809
  partialMetadata: "Some current session titles are unavailable or outside the bounded batch; fallback labels remain.",
807
810
  rootCurrent: "Current whole orchestrator session; may contain multiple batches. Not a historical or batch-only transcript.",
808
811
  recovered: "Read-only association verified from current opencode history; not an immutable lifecycle event.",
809
- rootUnlinked: "Orchestrator session not recorded. Reveal to try a bounded, read-only relationship search.",
812
+ rootUnlinked: "Orchestrator session not recorded. A bounded, read-only relationship search is attempted when visible.",
810
813
  rootUnavailable: "Orchestrator session unavailable: no unique, verifiable relationship was found in local history.",
811
814
  rootAmbiguous: "Orchestrator session unavailable: conflicting or copied relationships are ambiguous.",
812
815
  searchIncomplete: "Orchestrator association search incomplete or exceeded its bounded budget. No session was guessed.",
@@ -819,9 +822,9 @@ var consoleDetailMessages = {
819
822
  arguments: "Arguments",
820
823
  result: "Result",
821
824
  loading: "Loading local conversation…",
822
- current: "Present-day session, not a timeline reconstruction. May include later messages and tools. Refresh explicitly for updates.",
823
- historical: "Historical cursor: conversation content is hidden to avoid showing future mutable text. Return to live before revealing this operation.",
824
- disabled: "Content is disabled. Set console.sessionHistory.contentEnabled to true in .opencode/openteam.json and restart the Console. Then reveal content here.",
825
+ current: "Present-day whole session, not a timeline reconstruction or per-attempt transcript. Visible messages update automatically while live.",
826
+ historical: "Historical cursor: conversation content is hidden to avoid showing future mutable text. Return to live to read current messages.",
827
+ disabled: "Content is disabled by console.sessionHistory.contentEnabled: false. Lifecycle and telemetry remain metadata-only.",
825
828
  unavailable: "Conversation unavailable. Start an operator-owned local opencode serve against the same workspace and user history, configure console.sessionHistory.endpoint, then retry. No inference was requested.",
826
829
  empty: "No readable user messages, assistant output or tool calls remain in this session.",
827
830
  invalid: "This attempt has no recorded session in the selected run, or its history is incomplete.",
@@ -831,7 +834,7 @@ var consoleDetailMessages = {
831
834
  invalidEndpoint: "Expected a loopback HTTP origin without credentials, path, query or fragment.",
832
835
  readFailed: "Local session history could not be read.",
833
836
  oversized: "Conversation exceeds the local size limit (4 MiB). No content was loaded.",
834
- truncated: "Conversation display is truncated by local safety limits; omitted content is not empty history.",
837
+ truncated: "Conversation display is truncated by local safety limits. The newest bounded message window is shown; older messages or oversized fields may be omitted, not empty history.",
835
838
  truncatedMarker: `
836
839
  [truncated]`,
837
840
  terminalGap: "Live collection was interrupted; events during the gap are unavailable. This is not complete session history.",
@@ -908,7 +911,7 @@ var ConsoleConfigSchema = z3.object({
908
911
  openBrowser: z3.boolean().default(false),
909
912
  remoteStorage: z3.boolean().default(false),
910
913
  sessionHistory: z3.object({
911
- contentEnabled: z3.boolean().default(false),
914
+ contentEnabled: z3.boolean().default(true),
912
915
  endpoint: z3.string().refine(isLocalHistoryEndpoint, consoleDetailMessages.invalidEndpoint).optional()
913
916
  }).strict().optional(),
914
917
  terminal: z3.object({
@@ -5743,7 +5746,7 @@ import { z as z15 } from "zod";
5743
5746
  // package.json
5744
5747
  var package_default = {
5745
5748
  name: "@jmanuelcorral/openteam",
5746
- version: "0.24.0",
5749
+ version: "0.25.0",
5747
5750
  packageManager: "bun@1.3.14",
5748
5751
  description: "Cost-aware, local-first routing plugin for opencode with cheapest-capable frontier fallback and multi-agent orchestration.",
5749
5752
  license: "MIT",
@@ -6100,6 +6103,25 @@ var executionSetupMessages = {
6100
6103
  `),
6101
6104
  localOnlyTitle: "Local execution",
6102
6105
  localRequiredError: "local execution requires an enabled local runtime",
6106
+ lemonadeDetectedHint: (loaded, advertised) => `detected - ${loaded} confirmed loaded of ${advertised} advertised text model(s)`,
6107
+ 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.",
6108
+ 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.`,
6109
+ 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.",
6110
+ 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.",
6111
+ lemonadeEndpointMismatch: "Lemonade endpoint/provider mapping differs from the selected runtime. Reconcile the configured base URL and provider before rerunning setup; no model was substituted.",
6112
+ 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.`,
6113
+ lemonadeEffectiveConfigLabel: "effective setup configuration",
6114
+ lemonadeEffectiveConfigAmbiguous: "Cannot establish one effective openteam configuration from the configured plugin loaders. Reconcile their options before rerunning setup; no provider identity was guessed.",
6115
+ 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.`,
6116
+ 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.`,
6117
+ 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.",
6118
+ lemonadeV2Title: "Lemonade transport compatibility",
6119
+ 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.`,
6120
+ lemonadeInventory: (instanceID, providerID, models) => {
6121
+ const inventory = models.map((model) => `${model.modelID} (${model.loaded === true ? "loaded" : model.loaded === false ? "inactive" : "residency unknown"})`).join(", ");
6122
+ return `Lemonade inventory ${instanceID} (provider ${providerID}): ${inventory || "no advertised text models"}. Only confirmed loaded text models count as ready.`;
6123
+ },
6124
+ 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
6125
  mixedPrimaryQuestion: "Primary coordinator model",
6104
6126
  mixedPrimaryLocal: (model) => `Use local thinking model ${model}`,
6105
6127
  mixedPrimaryFrontier: "Choose a frontier model",
@@ -9931,6 +9953,243 @@ function ensureFoundryV1BaseURL(endpoint) {
9931
9953
  }
9932
9954
  }
9933
9955
 
9956
+ // src/local/lemonadeResidency.ts
9957
+ import { z as z19 } from "zod";
9958
+
9959
+ // src/messages/modelResidency.ts
9960
+ var reasons = {
9961
+ unknown: "fresh residency metadata is unavailable, malformed, or ambiguous",
9962
+ inactive: "the requested model is not verified as resident and serving",
9963
+ identity: "the requested model identity can be rewritten or is ambiguous",
9964
+ destination: "the request destination does not match its configured runtime",
9965
+ transport: "this provider execution path cannot enforce the residency guard",
9966
+ request: "this is not a supported, explicit model inference request",
9967
+ cancelled: "the request was cancelled before residency could be verified",
9968
+ timeout: "the residency metadata deadline expired",
9969
+ configuration: "the residency guard configuration is invalid"
9970
+ };
9971
+ var modelResidencyMessages = {
9972
+ blocked: (reason) => `[openteam] Lemonade model request blocked: ${reasons[reason]}.`,
9973
+ providerDisabled: (providerID) => `[openteam] Lemonade provider "${providerID}" is disabled because its configured transport or runtime mapping cannot enforce loaded-only requests.`,
9974
+ extractionRuntimeUnavailable: "[openteam] Memory extraction requires one enabled local runtime matching the configured extraction provider."
9975
+ };
9976
+
9977
+ // src/local/lemonadeResidency.ts
9978
+ class ModelResidencyError extends Error {
9979
+ code;
9980
+ statusCode = 400;
9981
+ isRetryable = false;
9982
+ constructor(code) {
9983
+ super(modelResidencyMessages.blocked(code));
9984
+ this.code = code;
9985
+ this.name = "ModelResidencyError";
9986
+ }
9987
+ }
9988
+ var modelName = z19.string().min(1).refine((name) => name === name.trim());
9989
+ var LoadedModelSchema = z19.object({
9990
+ model_name: modelName,
9991
+ loaded: z19.boolean().optional(),
9992
+ status: z19.string().optional(),
9993
+ backend_alive: z19.boolean().optional(),
9994
+ backend_health: z19.string().optional(),
9995
+ watchdog_reset: z19.boolean().optional(),
9996
+ watchdog_reset_reason: z19.string().optional(),
9997
+ residency_class: z19.string().optional(),
9998
+ slot_pool: z19.string().optional(),
9999
+ checkpoint: z19.string().optional(),
10000
+ type: z19.string().optional(),
10001
+ device: z19.string().optional(),
10002
+ backend_url: z19.string().optional(),
10003
+ pid: z19.number().int().optional(),
10004
+ launch_command: z19.unknown().optional(),
10005
+ pinned: z19.boolean().optional(),
10006
+ recipe: z19.string().optional(),
10007
+ recipe_options: z19.unknown().optional(),
10008
+ is_busy: z19.boolean().optional(),
10009
+ is_streaming: z19.boolean().optional(),
10010
+ max_context_window: z19.number().optional(),
10011
+ cost_input_per_million: z19.number().optional(),
10012
+ cost_output_per_million: z19.number().optional(),
10013
+ last_use: z19.number().optional()
10014
+ }).strict();
10015
+ var TelemetrySchema = z19.object({
10016
+ enabled: z19.boolean(),
10017
+ captures: z19.array(z19.string()).optional()
10018
+ }).strict();
10019
+ var HealthSchema = z19.object({
10020
+ status: z19.literal("ok"),
10021
+ all_models_loaded: z19.array(LoadedModelSchema),
10022
+ version: z19.string().optional(),
10023
+ model_loaded: z19.string().nullable().optional(),
10024
+ telemetry: TelemetrySchema.optional(),
10025
+ max_models: z19.record(z19.string(), z19.number().int()).optional(),
10026
+ pinned_models: z19.record(z19.string(), z19.number().int()).optional(),
10027
+ pinned_helper_models: z19.record(z19.string(), z19.number().int()).optional(),
10028
+ websocket_port: z19.number().int().optional(),
10029
+ update_check_done: z19.boolean().optional()
10030
+ }).strict();
10031
+ var AliasSchema = z19.object({
10032
+ alias: modelName,
10033
+ target: modelName,
10034
+ downloaded: z19.boolean().optional(),
10035
+ recipe: z19.string().optional()
10036
+ }).strict();
10037
+ var AliasesSchema = z19.object({
10038
+ aliases: z19.array(AliasSchema)
10039
+ }).strict();
10040
+ var MetadataRecordSchema = z19.record(z19.string(), z19.unknown());
10041
+ var inactiveStates = new Set([
10042
+ "loading",
10043
+ "downsizing",
10044
+ "downsized",
10045
+ "evicting",
10046
+ "unloaded"
10047
+ ]);
10048
+ var inactiveHealth = new Set(["stopped", "exited", "watchdog_reset"]);
10049
+ var standardPools = new Set([
10050
+ "standard/llm",
10051
+ "standard/embedding",
10052
+ "standard/reranking",
10053
+ "standard/transcription",
10054
+ "standard/image",
10055
+ "standard/tts",
10056
+ "standard/audio-generation",
10057
+ "standard/classification",
10058
+ "standard/mesh"
10059
+ ]);
10060
+ function usableState(entry) {
10061
+ 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/")) {
10062
+ return false;
10063
+ }
10064
+ 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))) {
10065
+ return;
10066
+ }
10067
+ return true;
10068
+ }
10069
+ function projectMetadataObject(payload, keys) {
10070
+ const record = MetadataRecordSchema.safeParse(payload);
10071
+ if (!record.success)
10072
+ throw new ModelResidencyError("unknown");
10073
+ return Object.fromEntries(keys.filter((key) => Object.hasOwn(record.data, key)).map((key) => [key, record.data[key]]));
10074
+ }
10075
+ function parseResidency(healthPayload, aliasPayload) {
10076
+ const healthFields = projectMetadataObject(healthPayload, Object.keys(HealthSchema.shape));
10077
+ if (Array.isArray(healthFields.all_models_loaded)) {
10078
+ healthFields.all_models_loaded = healthFields.all_models_loaded.map((entry) => projectMetadataObject(entry, Object.keys(LoadedModelSchema.shape)));
10079
+ }
10080
+ if (healthFields.telemetry !== undefined) {
10081
+ healthFields.telemetry = projectMetadataObject(healthFields.telemetry, Object.keys(TelemetrySchema.shape));
10082
+ }
10083
+ const aliasFields = projectMetadataObject(aliasPayload, Object.keys(AliasesSchema.shape));
10084
+ if (Array.isArray(aliasFields.aliases)) {
10085
+ aliasFields.aliases = aliasFields.aliases.map((entry) => projectMetadataObject(entry, Object.keys(AliasSchema.shape)));
10086
+ }
10087
+ const health = HealthSchema.safeParse(healthFields);
10088
+ const aliases = AliasesSchema.safeParse(aliasFields);
10089
+ if (!health.success || !aliases.success)
10090
+ throw new ModelResidencyError("unknown");
10091
+ const result = new Map;
10092
+ for (const entry of health.data.all_models_loaded) {
10093
+ if (result.has(entry.model_name))
10094
+ throw new ModelResidencyError("unknown");
10095
+ result.set(entry.model_name, {
10096
+ loaded: entry.model_name.endsWith(":latest") ? undefined : usableState(entry),
10097
+ metadata: entry
10098
+ });
10099
+ }
10100
+ const seenAliases = new Set;
10101
+ for (const entry of aliases.data.aliases) {
10102
+ if (seenAliases.has(entry.alias))
10103
+ throw new ModelResidencyError("unknown");
10104
+ seenAliases.add(entry.alias);
10105
+ result.set(entry.alias, {
10106
+ loaded: undefined,
10107
+ metadata: result.get(entry.alias)?.metadata ?? {}
10108
+ });
10109
+ }
10110
+ return result;
10111
+ }
10112
+ function lemonadeBaseURL(value) {
10113
+ let url;
10114
+ try {
10115
+ url = new URL(value);
10116
+ } catch {
10117
+ throw new ModelResidencyError("destination");
10118
+ }
10119
+ if (url.protocol !== "http:" && url.protocol !== "https:" || url.username !== "" || url.password !== "" || url.search !== "" || url.hash !== "" || !/^\/(?:api\/)?v[01]\/?$/.test(url.pathname)) {
10120
+ throw new ModelResidencyError("destination");
10121
+ }
10122
+ return `${url.origin}${url.pathname.replace(/\/$/, "")}`;
10123
+ }
10124
+ async function withResidencyDeadline(operation, options) {
10125
+ const timeoutMs = options.timeoutMs ?? 5000;
10126
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
10127
+ throw new ModelResidencyError("configuration");
10128
+ }
10129
+ const controller = new AbortController;
10130
+ const cancel = () => controller.abort(new ModelResidencyError("cancelled"));
10131
+ if (options.signal?.aborted)
10132
+ throw new ModelResidencyError("cancelled");
10133
+ options.signal?.addEventListener("abort", cancel, { once: true });
10134
+ const schedule = options.scheduleTimeout ?? ((callback, ms) => {
10135
+ const timer = setTimeout(callback, ms);
10136
+ return () => clearTimeout(timer);
10137
+ });
10138
+ let onAbort = () => {};
10139
+ const aborted = new Promise((_, reject) => {
10140
+ onAbort = () => reject(controller.signal.reason);
10141
+ controller.signal.addEventListener("abort", onAbort, { once: true });
10142
+ });
10143
+ const clearTimer = schedule(() => controller.abort(new ModelResidencyError("timeout")), timeoutMs);
10144
+ try {
10145
+ controller.signal.throwIfAborted();
10146
+ return await Promise.race([operation(controller.signal), aborted]);
10147
+ } finally {
10148
+ clearTimer();
10149
+ options.signal?.removeEventListener("abort", cancel);
10150
+ controller.signal.removeEventListener("abort", onAbort);
10151
+ controller.abort();
10152
+ }
10153
+ }
10154
+ async function metadata(url, fetch, signal, headers) {
10155
+ signal.throwIfAborted();
10156
+ let payload;
10157
+ try {
10158
+ const response = await fetch(url, {
10159
+ method: "GET",
10160
+ headers,
10161
+ signal,
10162
+ redirect: "error",
10163
+ cache: "no-store"
10164
+ });
10165
+ signal.throwIfAborted();
10166
+ if (!response.ok || response.redirected || response.url !== "" && response.url !== url) {
10167
+ throw new ModelResidencyError("unknown");
10168
+ }
10169
+ payload = await response.json();
10170
+ } catch {
10171
+ signal.throwIfAborted();
10172
+ throw new ModelResidencyError("unknown");
10173
+ }
10174
+ signal.throwIfAborted();
10175
+ return payload;
10176
+ }
10177
+ async function readLemonadeResidency(baseURL, fetch, options = {}) {
10178
+ const base = lemonadeBaseURL(baseURL);
10179
+ const headers = new Headers(options.headers);
10180
+ headers.delete("content-type");
10181
+ headers.delete("content-length");
10182
+ headers.set("accept", "application/json");
10183
+ headers.set("cache-control", "no-cache, no-store");
10184
+ headers.delete("if-none-match");
10185
+ headers.delete("if-modified-since");
10186
+ return withResidencyDeadline(async (signal) => {
10187
+ const aliases = await metadata(`${new URL(base).origin}/internal/aliases`, fetch, signal, headers);
10188
+ const health = await metadata(`${base}/health`, fetch, signal, headers);
10189
+ return parseResidency(health, aliases);
10190
+ }, options);
10191
+ }
10192
+
9934
10193
  // src/local/lemonade.ts
9935
10194
  var LEMONADE_DEFAULT_BASE_URL = "http://localhost:13305/api/v1";
9936
10195
  var NON_TEXT_LABELS = new Set([
@@ -10017,36 +10276,19 @@ function isNonTextModel(entry) {
10017
10276
  return entry.labels.some((label) => typeof label === "string" && NON_TEXT_LABELS.has(label));
10018
10277
  }
10019
10278
  async function readLoadedModels(baseURL, fetch) {
10020
- let payload;
10021
10279
  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();
10280
+ const residency = await readLemonadeResidency(baseURL, fetch);
10281
+ return new Map([...residency].map(([name, entry]) => [
10282
+ name,
10283
+ {
10284
+ loaded: entry.loaded,
10285
+ slots: entry.loaded === true ? readSlotCount(entry.metadata) : undefined,
10286
+ totalContextWindow: entry.loaded === true ? readLoadedContextWindow(entry.metadata) : undefined
10287
+ }
10288
+ ]));
10030
10289
  } catch {
10031
10290
  return;
10032
10291
  }
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
10292
  }
10051
10293
  function readSlotCount(entry) {
10052
10294
  return slotsFromLlamacppArgs(entry) ?? slotsFromLaunchCommand(entry);
@@ -10193,6 +10435,9 @@ function enrichWithLoadState(models, loaded) {
10193
10435
  if (hit === undefined) {
10194
10436
  return { ...base, loaded: false };
10195
10437
  }
10438
+ if (hit.loaded !== true) {
10439
+ return hit.loaded === false ? { ...base, loaded: false } : base;
10440
+ }
10196
10441
  const contextWindow = derivedConservativeContextWindow(model.contextWindow, hit);
10197
10442
  return {
10198
10443
  ...base,
@@ -10336,6 +10581,14 @@ function reportedModelSlotsByRuntime(snapshots) {
10336
10581
  }
10337
10582
 
10338
10583
  // src/local/slotPool.ts
10584
+ function localModelAliases(providerID, models) {
10585
+ const aliases = new Map;
10586
+ for (const model of models ?? []) {
10587
+ if (model.kind === "local" && model.providerID === providerID && model.runtimeModelID !== undefined && model.runtimeModelID !== model.modelID)
10588
+ aliases.set(model.modelID, model.runtimeModelID);
10589
+ }
10590
+ return aliases;
10591
+ }
10339
10592
  var POOL_SEPARATOR = "::";
10340
10593
  function slotPoolKey(runtime, modelID) {
10341
10594
  if (modelID === undefined) {
@@ -10365,13 +10618,20 @@ function slotPoolReservedInteractive(runtime, modelID) {
10365
10618
  function unknownPoolCapacity() {
10366
10619
  return DEFAULT_LOCAL_MAX_CONCURRENCY;
10367
10620
  }
10368
- function withReportedModelSlots(runtime, reported) {
10369
- if (reported === undefined || Object.keys(reported).length === 0) {
10621
+ function withReportedModelSlots(runtime, reported, aliases) {
10622
+ const configured = Object.entries(runtime.modelConcurrency ?? {});
10623
+ const hasAliasLimits = configured.some(([modelID]) => aliases?.has(modelID) === true);
10624
+ if (!hasAliasLimits && (reported === undefined || Object.keys(reported).length === 0)) {
10370
10625
  return runtime;
10371
10626
  }
10627
+ const explicit = new Map;
10628
+ for (const [modelID, limit] of configured) {
10629
+ const physicalID = aliases?.get(modelID) ?? modelID;
10630
+ explicit.set(physicalID, Math.min(explicit.get(physicalID) ?? limit, limit));
10631
+ }
10372
10632
  return {
10373
10633
  ...runtime,
10374
- modelConcurrency: { ...reported, ...runtime.modelConcurrency }
10634
+ modelConcurrency: { ...reported, ...Object.fromEntries(explicit) }
10375
10635
  };
10376
10636
  }
10377
10637
 
@@ -10468,14 +10728,14 @@ var readReportArtifact = async (reportPath) => {
10468
10728
  };
10469
10729
 
10470
10730
  // 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)
10731
+ import { z as z20 } from "zod";
10732
+ var RosterEntrySchema = z20.object({
10733
+ roleID: z20.string().min(1),
10734
+ agentName: z20.string().min(1)
10475
10735
  }).strict();
10476
- var RosterSchema = z19.object({
10477
- universe: z19.string().min(1),
10478
- entries: z19.array(RosterEntrySchema)
10736
+ var RosterSchema = z20.object({
10737
+ universe: z20.string().min(1),
10738
+ entries: z20.array(RosterEntrySchema)
10479
10739
  }).strict();
10480
10740
  var ROSTER_JSON_FENCE = /```json\s*([\s\S]*?)```/;
10481
10741
 
@@ -11120,10 +11380,21 @@ async function runSubsession(client, req, deps) {
11120
11380
  }
11121
11381
  }
11122
11382
 
11383
+ // src/local/modelResidency.ts
11384
+ function hasRequiredModelResidency(kind, model) {
11385
+ return kind !== "lemonade" || model?.loaded === true;
11386
+ }
11387
+
11123
11388
  // src/plugin/availability.ts
11124
11389
  function modelKey2(model) {
11125
11390
  return `${model.providerID}/${model.modelID}`;
11126
11391
  }
11392
+ function availabilityMetadata({
11393
+ apiModelID: _apiModelID,
11394
+ ...metadata2
11395
+ }) {
11396
+ return metadata2;
11397
+ }
11127
11398
  function compareAvailableModels(left, right) {
11128
11399
  const kindOrder = Number(left.kind === "frontier") - Number(right.kind === "frontier");
11129
11400
  if (kindOrder !== 0) {
@@ -11141,6 +11412,9 @@ function uniqueSelections(models) {
11141
11412
  function isConfiguredLocalModel(config, model) {
11142
11413
  return config.local.runtimes.some((runtime) => runtime.defaultModel.providerID === model.providerID);
11143
11414
  }
11415
+ function requiresModelResidency(config, model) {
11416
+ return config.local.runtimes.some((runtime) => runtime.defaultModel.providerID === model.providerID && !hasRequiredModelResidency(localRuntimeKind(runtime), undefined));
11417
+ }
11144
11418
  function configuredFrontierProviderIDs(config) {
11145
11419
  const providerIDs = new Set([config.baseline.hardDefault.providerID]);
11146
11420
  if (config.baseline.mode === "pinned" && config.baseline.pinnedModel !== null) {
@@ -11235,7 +11509,7 @@ function frontierAvailableModels(config, configuredModels) {
11235
11509
  for (const model of configuredModels ?? frontierBaselines(config)) {
11236
11510
  if (!isConfiguredLocalModel(config, model)) {
11237
11511
  frontierByKey.set(modelKey2(model), {
11238
- ...model,
11512
+ ...availabilityMetadata(model),
11239
11513
  kind: "frontier",
11240
11514
  available: true
11241
11515
  });
@@ -11251,7 +11525,7 @@ function defaultAvailableModels(config, configuredModels) {
11251
11525
  ...defaultLocalModels(config).map((model) => ({
11252
11526
  ...model,
11253
11527
  kind: "local",
11254
- available: true
11528
+ available: !requiresModelResidency(config, model)
11255
11529
  })),
11256
11530
  ...frontierAvailableModels(config, configuredModels)
11257
11531
  ].sort(compareAvailableModels);
@@ -11265,7 +11539,8 @@ function toAvailableModels(snapshots, config, configuredModels) {
11265
11539
  continue;
11266
11540
  }
11267
11541
  localByKey.set(modelKey2(model), {
11268
- ...model,
11542
+ ...availabilityMetadata(model),
11543
+ ...model.apiModelID !== undefined && model.apiModelID !== model.modelID ? { runtimeModelID: model.apiModelID } : {},
11269
11544
  kind: "local",
11270
11545
  available: false
11271
11546
  });
@@ -11276,27 +11551,25 @@ function toAvailableModels(snapshots, config, configuredModels) {
11276
11551
  continue;
11277
11552
  }
11278
11553
  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;
11554
+ const providerID = runtime.defaultModel.providerID;
11555
+ const refs = configuredModels === undefined ? [{ providerID, modelID: model.modelID }] : configuredModels.filter((registered) => registered.providerID === providerID && (registered.apiModelID ?? registered.modelID) === model.modelID);
11556
+ for (const ref of refs) {
11557
+ const existing = localByKey.get(modelKey2(ref));
11558
+ const availableModel = {
11559
+ ...existing,
11560
+ providerID: ref.providerID,
11561
+ modelID: ref.modelID,
11562
+ kind: "local",
11563
+ available: snapshot.reachable && hasRequiredModelResidency(localRuntimeKind(runtime), model) || existing?.available === true
11564
+ };
11565
+ if (model.supportsTools !== "unknown") {
11566
+ availableModel.supportsTools = model.supportsTools;
11567
+ }
11568
+ if (model.contextWindow !== undefined) {
11569
+ availableModel.contextWindow = model.contextWindow;
11570
+ }
11571
+ localByKey.set(modelKey2(ref), availableModel);
11298
11572
  }
11299
- localByKey.set(modelKey2(ref), availableModel);
11300
11573
  }
11301
11574
  }
11302
11575
  return [
@@ -11305,7 +11578,7 @@ function toAvailableModels(snapshots, config, configuredModels) {
11305
11578
  ].sort(compareAvailableModels);
11306
11579
  }
11307
11580
  function createAvailabilityCache(options) {
11308
- let configuredModels = options.initialConfiguredModels === undefined ? undefined : [...options.initialConfiguredModels];
11581
+ let configuredModels = options.initialConfiguredModels === undefined ? undefined : options.initialConfiguredModels.map((model) => ({ ...model }));
11309
11582
  let configuredProfiles = (options.initialConfiguredProfiles ?? []).map((profile) => profileForConfiguredDomain(options.config, profile));
11310
11583
  let cached = defaultAvailableModels(options.config, configuredModels);
11311
11584
  let inFlight;
@@ -11315,7 +11588,9 @@ function createAvailabilityCache(options) {
11315
11588
  if (options.listConfiguredInventory !== undefined) {
11316
11589
  const inventory = await options.listConfiguredInventory().then((value) => ({ kind: "models", value }), (error) => ({ kind: "error", error }));
11317
11590
  if (inventory.kind === "models") {
11318
- configuredModels = inventory.value.models;
11591
+ configuredModels = inventory.value.models.map((model) => ({
11592
+ ...model
11593
+ }));
11319
11594
  configuredProfiles = inventory.value.profiles.map((profile) => profileForConfiguredDomain(options.config, profile));
11320
11595
  } else {
11321
11596
  options.onRefreshError?.(inventory.error);
@@ -11328,15 +11603,22 @@ function createAvailabilityCache(options) {
11328
11603
  }
11329
11604
  return {
11330
11605
  get: () => cloneAvailableModels(cached),
11606
+ resolveApiModelID: (ref) => {
11607
+ const registered = configuredModels?.find((model) => model.providerID === ref.providerID && model.modelID === ref.modelID);
11608
+ return registered?.apiModelID ?? registered?.modelID;
11609
+ },
11331
11610
  getProfiles: () => configuredProfiles.map((profile) => ({
11332
11611
  ...profile,
11333
11612
  ref: { ...profile.ref },
11334
11613
  costPer1M: { ...profile.costPer1M }
11335
11614
  })),
11336
11615
  refresh: () => {
11337
- inFlight ??= refreshNow().finally(() => {
11338
- inFlight = undefined;
11339
- });
11616
+ if (inFlight === undefined) {
11617
+ cached = cached.map((model) => requiresModelResidency(options.config, model) ? { ...model, available: false } : model);
11618
+ inFlight = refreshNow().finally(() => {
11619
+ inFlight = undefined;
11620
+ });
11621
+ }
11340
11622
  return inFlight;
11341
11623
  }
11342
11624
  };
@@ -11504,7 +11786,7 @@ function planWorktreeReconciliation(input) {
11504
11786
  }
11505
11787
 
11506
11788
  // src/telemetry/otelConfig.ts
11507
- import { z as z20 } from "zod";
11789
+ import { z as z21 } from "zod";
11508
11790
 
11509
11791
  // src/telemetry/fanout.ts
11510
11792
  function createFanOutSink(deps) {
@@ -11582,10 +11864,10 @@ function createOtelSink(deps) {
11582
11864
  }
11583
11865
 
11584
11866
  // 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()
11867
+ var OtelBackendConfigSchema = z21.object({
11868
+ backend: z21.literal("opentelemetry"),
11869
+ connectionEnv: z21.string().min(1),
11870
+ serviceName: z21.string().min(1).optional()
11589
11871
  }).strict();
11590
11872
  function parseConnectionString(raw) {
11591
11873
  const pairs = new Map;
@@ -12010,7 +12292,7 @@ function parseOpencodeProviders(opencodeConfig) {
12010
12292
  function localRuntimeStates(config) {
12011
12293
  const map = new Map;
12012
12294
  for (const runtime of config.local.runtimes) {
12013
- map.set(runtime.id, { enabled: runtime.enabled });
12295
+ map.set(runtime.defaultModel.providerID, { enabled: runtime.enabled });
12014
12296
  }
12015
12297
  return map;
12016
12298
  }
@@ -12018,7 +12300,7 @@ function disabledLocalProviderIDs(config) {
12018
12300
  const ids = new Set;
12019
12301
  for (const runtime of config.local.runtimes) {
12020
12302
  if (!runtime.enabled) {
12021
- ids.add(runtime.id);
12303
+ ids.add(runtime.defaultModel.providerID);
12022
12304
  }
12023
12305
  }
12024
12306
  return ids;
@@ -12034,7 +12316,11 @@ function computeLive(model, isLocalProvider, liveModels) {
12034
12316
  if (!snapshot.reachable) {
12035
12317
  return "unreachable";
12036
12318
  }
12037
- return snapshot.modelIDs.has(model.modelID) ? "confirmed" : "not-advertised";
12319
+ if (snapshot.modelIDs.has(model.modelID))
12320
+ return "confirmed";
12321
+ if (snapshot.residency?.has(model.modelID))
12322
+ return snapshot.residency.get(model.modelID) === false ? "not-loaded" : "residency-unknown";
12323
+ return "not-advertised";
12038
12324
  }
12039
12325
  function resolveAgentModel(model, context) {
12040
12326
  const isLocalProvider = KNOWN_LOCAL_PROVIDER_IDS.has(model.providerID) || context.localRuntimes.has(model.providerID);
@@ -14365,12 +14651,19 @@ function defaultModelFromOpencode(opencodeConfig) {
14365
14651
  }
14366
14652
  return;
14367
14653
  }
14368
- function liveModelsFromSnapshots(snapshots) {
14654
+ function liveModelsFromSnapshots(snapshots, config) {
14369
14655
  const map = new Map;
14370
14656
  for (const snapshot of snapshots) {
14371
- map.set(snapshot.id, {
14657
+ const runtime = config.local.runtimes.find((runtime2) => runtime2.id === snapshot.id);
14658
+ if (runtime === undefined || !runtime.enabled)
14659
+ continue;
14660
+ const kind = localRuntimeKind(runtime);
14661
+ map.set(runtime.defaultModel.providerID, {
14372
14662
  reachable: snapshot.reachable,
14373
- modelIDs: new Set(snapshot.models.map((model) => model.modelID))
14663
+ modelIDs: new Set(snapshot.models.filter((model) => hasRequiredModelResidency(kind, model)).map((model) => model.modelID)),
14664
+ ...kind === "lemonade" ? {
14665
+ residency: new Map(snapshot.models.map((model) => [model.modelID, model.loaded]))
14666
+ } : {}
14374
14667
  });
14375
14668
  }
14376
14669
  return map;
@@ -14656,7 +14949,7 @@ async function runCli(argv, deps) {
14656
14949
  const agentModels = diagnoseAgentModels(agentFiles, {
14657
14950
  opencodeProviders: parseOpencodeProviders(opencodeConfig),
14658
14951
  localRuntimes: localRuntimeStates(config),
14659
- liveModels: liveModelsFromSnapshots(snapshots),
14952
+ liveModels: liveModelsFromSnapshots(snapshots, config),
14660
14953
  sourceDir: deps.agentDir,
14661
14954
  ...defaultModel !== undefined ? { defaultModel } : {}
14662
14955
  });
@@ -14695,29 +14988,53 @@ async function runCli(argv, deps) {
14695
14988
  const rosterMissing = deps.loadRosterForDoctor !== undefined && roster === undefined && rosterLoadError === undefined;
14696
14989
  const orchestratorAgentName = ORCHESTRATOR_AGENT_PATH.slice(ORCHESTRATOR_AGENT_PATH.lastIndexOf("/") + 1).replace(/\.md$/, "");
14697
14990
  const orchestratorAgentMissing = !agentFiles.some((file) => file.name === orchestratorAgentName);
14991
+ const inventoryNotes = [];
14992
+ const readySnapshots = snapshots.map((snapshot) => {
14993
+ const runtime = config.local.runtimes.find((runtime2) => runtime2.id === snapshot.id);
14994
+ if (runtime === undefined || localRuntimeKind(runtime) !== "lemonade")
14995
+ return snapshot;
14996
+ inventoryNotes.push(executionSetupMessages.lemonadeInventory(runtime.id, runtime.defaultModel.providerID, snapshot.models));
14997
+ return {
14998
+ ...snapshot,
14999
+ models: snapshot.models.filter((model) => hasRequiredModelResidency(localRuntimeKind(runtime), model))
15000
+ };
15001
+ });
15002
+ const residencyNotes = agentModels.flatMap((agent) => {
15003
+ const live = agent.resolution?.live;
15004
+ if (agent.model === undefined || live !== "not-loaded" && live !== "residency-unknown")
15005
+ return [];
15006
+ return [
15007
+ executionSetupMessages.lemonadeAgentResidency(agent.name, `${agent.model.providerID}/${agent.model.modelID}`, live)
15008
+ ];
15009
+ });
14698
15010
  return {
14699
15011
  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
- })
15012
+ stdout: [
15013
+ renderDoctor({
15014
+ config,
15015
+ snapshots: readySnapshots,
15016
+ telemetryPath,
15017
+ telemetryRecords: records.length,
15018
+ agentModels,
15019
+ opencodeConfigPaths,
15020
+ ...opencodeConfig !== undefined ? { opencodeConfig } : {},
15021
+ ...queueWait !== undefined ? { queueWait } : {},
15022
+ ...rosterAudit !== undefined ? { rosterAudit } : {},
15023
+ ...rosterRoleCount !== undefined ? { rosterRoleCount } : {},
15024
+ ...rosterLoadError !== undefined ? { rosterLoadError } : {},
15025
+ ...rosterMissing ? { rosterMissing } : {},
15026
+ ...orchestratorAgentMissing ? { orchestratorAgentMissing } : {},
15027
+ ...diagnostics !== undefined && diagnostics.length > 0 ? { diagnostics } : {},
15028
+ ...opencodeConfigError !== undefined ? { opencodeConfigError } : {},
15029
+ ...cacheEntries !== undefined ? { cacheEntries, cliVersion: deps.version } : {},
15030
+ ...legacyLayout !== undefined && legacyLayout.length > 0 ? { legacyLayout } : {},
15031
+ ...otelBackend !== undefined ? { otelBackend } : {},
15032
+ ...gitignoreCoverage !== undefined ? { gitignore: gitignoreCoverage } : {}
15033
+ }),
15034
+ ...inventoryNotes,
15035
+ ...residencyNotes
15036
+ ].join(`
15037
+ `)
14721
15038
  };
14722
15039
  }
14723
15040
  if (command === "migrate") {
@@ -14901,29 +15218,29 @@ import {
14901
15218
  writeFile as writeFile2
14902
15219
  } from "node:fs/promises";
14903
15220
  import { dirname as dirname5, join as join12, resolve as resolve7 } from "node:path";
14904
- import { z as z21 } from "zod";
15221
+ import { z as z22 } from "zod";
14905
15222
  var CONSOLE_RUNTIME_SCHEMA_VERSION = 1;
14906
15223
  var CONSOLE_RUNTIME_DIRECTORY = ".opencode/openteam-local/console";
14907
15224
  var CONSOLE_RUNTIME_FILE = "runtime.json";
14908
15225
  var CONSOLE_LAUNCH_LOCK_FILE = "launch.lock";
14909
15226
  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)
15227
+ var ConsoleRuntimeStateSchema = z22.object({
15228
+ schemaVersion: z22.literal(CONSOLE_RUNTIME_SCHEMA_VERSION),
15229
+ pid: z22.number().int().positive(),
15230
+ workspaceRoot: z22.string().min(1),
15231
+ host: z22.string().min(1),
15232
+ port: z22.number().int().min(1).max(65535),
15233
+ url: z22.url(),
15234
+ startedAt: z22.iso.datetime({ offset: true }),
15235
+ launchId: z22.uuid(),
15236
+ logPath: z22.string().min(1)
14920
15237
  }).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 })
15238
+ var ConsoleLaunchLockSchema = z22.object({
15239
+ schemaVersion: z22.literal(CONSOLE_RUNTIME_SCHEMA_VERSION),
15240
+ workspaceRoot: z22.string().min(1),
15241
+ launchId: z22.uuid(),
15242
+ ownerPid: z22.number().int().positive(),
15243
+ createdAt: z22.iso.datetime({ offset: true })
14927
15244
  }).strict();
14928
15245
 
14929
15246
  class ConsoleRuntimeStateFileError extends Error {
@@ -15622,36 +15939,36 @@ function formatResponse(response) {
15622
15939
  }
15623
15940
 
15624
15941
  // src/plugin/reportRunSchema.ts
15625
- import { z as z23 } from "zod";
15942
+ import { z as z24 } from "zod";
15626
15943
 
15627
15944
  // src/plugin/graphShadowIngress.ts
15628
- import { z as z22 } from "zod";
15945
+ import { z as z23 } from "zod";
15629
15946
  var LEGACY_EXECUTION_TRACE_VERSION = 1;
15630
- var LegacyExecutionStatusSchema = z22.enum([
15947
+ var LegacyExecutionStatusSchema = z23.enum([
15631
15948
  "completed",
15632
15949
  "failed",
15633
15950
  "cancelled"
15634
15951
  ]);
15635
- var LegacyReviewOutcomeSchema = z22.enum([
15952
+ var LegacyReviewOutcomeSchema = z23.enum([
15636
15953
  "approved",
15637
15954
  "rejected",
15638
15955
  "inconclusive"
15639
15956
  ]);
15640
- var LegacyTraceNodeV1Schema = z22.object({
15957
+ var LegacyTraceNodeV1Schema = z23.object({
15641
15958
  id: NodeIDSchema,
15642
15959
  role: NodeRoleSchema,
15643
- model: z22.string().min(1),
15644
- sessionRef: z22.string().min(1).optional(),
15960
+ model: z23.string().min(1),
15961
+ sessionRef: z23.string().min(1).optional(),
15645
15962
  errorClass: ErrorClassSchema.optional()
15646
15963
  }).strict();
15647
- var LegacyExecutionTraceV1Schema = z22.object({
15648
- version: z22.literal(LEGACY_EXECUTION_TRACE_VERSION),
15964
+ var LegacyExecutionTraceV1Schema = z23.object({
15965
+ version: z23.literal(LEGACY_EXECUTION_TRACE_VERSION),
15649
15966
  runID: NodeIDSchema,
15650
15967
  status: LegacyExecutionStatusSchema,
15651
15968
  outcome: LegacyReviewOutcomeSchema,
15652
- fixes: z22.number().int().nonnegative(),
15653
- nodes: z22.array(LegacyTraceNodeV1Schema).min(1),
15654
- parentSessionRef: z22.string().min(1).optional()
15969
+ fixes: z23.number().int().nonnegative(),
15970
+ nodes: z23.array(LegacyTraceNodeV1Schema).min(1),
15971
+ parentSessionRef: z23.string().min(1).optional()
15655
15972
  }).strict();
15656
15973
  function gateReason2(gate) {
15657
15974
  if (gate === undefined || gate.mode === "off") {
@@ -15722,20 +16039,20 @@ function parseLegacyExecutionTrace(input) {
15722
16039
  }
15723
16040
 
15724
16041
  // src/plugin/reportRunSchema.ts
15725
- var ReportRunNodeSchema = z23.object({
16042
+ var ReportRunNodeSchema = z24.object({
15726
16043
  id: NodeIDSchema,
15727
16044
  role: NodeRoleSchema,
15728
- model: z23.string().min(1),
15729
- ok: z23.boolean(),
15730
- sessionRef: z23.string().min(1).optional(),
16045
+ model: z24.string().min(1),
16046
+ ok: z24.boolean(),
16047
+ sessionRef: z24.string().min(1).optional(),
15731
16048
  errorClass: ErrorClassSchema.optional()
15732
16049
  }).strict();
15733
- var ReportRunPayloadSchema = z23.object({
16050
+ var ReportRunPayloadSchema = z24.object({
15734
16051
  runID: NodeIDSchema,
15735
16052
  status: LegacyExecutionStatusSchema,
15736
- fixes: z23.number().int().nonnegative(),
15737
- nodes: z23.array(ReportRunNodeSchema).min(1),
15738
- parentSessionRef: z23.string().min(1).optional()
16053
+ fixes: z24.number().int().nonnegative(),
16054
+ nodes: z24.array(ReportRunNodeSchema).min(1),
16055
+ parentSessionRef: z24.string().min(1).optional()
15739
16056
  }).strict();
15740
16057
 
15741
16058
  // src/orchestrator/graphShadow.ts
@@ -16839,6 +17156,309 @@ function hashPrompt(prompt) {
16839
17156
  return `fnv1a32:${(hash >>> 0).toString(16).padStart(8, "0")}`;
16840
17157
  }
16841
17158
 
17159
+ // src/plugin/modelResidency.ts
17160
+ import { z as z25 } from "zod";
17161
+
17162
+ // src/local/lemonadeRequestGuard.ts
17163
+ var inferencePaths = new Set([
17164
+ "/chat/completions",
17165
+ "/completions",
17166
+ "/embeddings",
17167
+ "/responses"
17168
+ ]);
17169
+ function modelID(payload) {
17170
+ if (typeof payload !== "object" || payload === null || !("model" in payload) || typeof payload.model !== "string" || payload.model.length === 0 || payload.model !== payload.model.trim()) {
17171
+ throw new ModelResidencyError("request");
17172
+ }
17173
+ if (payload.model.endsWith(":latest"))
17174
+ throw new ModelResidencyError("identity");
17175
+ return payload.model;
17176
+ }
17177
+ function createLemonadeGuardedFetch(options) {
17178
+ const base = lemonadeBaseURL(options.baseURL);
17179
+ const upstream = options.fetch;
17180
+ const healthFetch = options.healthFetch ?? upstream;
17181
+ return Object.assign(async (input, init) => {
17182
+ const request = new Request(input, init);
17183
+ const url = new URL(request.url);
17184
+ if (url.username !== "" || url.password !== "" || url.search !== "" || url.hash !== "" || !request.url.startsWith(`${base}/`)) {
17185
+ throw new ModelResidencyError("destination");
17186
+ }
17187
+ const path4 = request.url.slice(base.length);
17188
+ const metadataOnly = request.method === "GET" && (path4 === "/health" || /^\/models(?:\/[^/]+)?$/.test(path4));
17189
+ if (!metadataOnly && (request.method !== "POST" || !inferencePaths.has(path4))) {
17190
+ throw new ModelResidencyError("request");
17191
+ }
17192
+ if (!metadataOnly) {
17193
+ await withResidencyDeadline(async (signal) => {
17194
+ signal.throwIfAborted();
17195
+ let payload;
17196
+ try {
17197
+ payload = await request.clone().json();
17198
+ } catch {
17199
+ signal.throwIfAborted();
17200
+ throw new ModelResidencyError("request");
17201
+ }
17202
+ signal.throwIfAborted();
17203
+ const model = modelID(payload);
17204
+ const modelIDs = typeof options.modelIDs === "function" ? await options.modelIDs() : options.modelIDs;
17205
+ signal.throwIfAborted();
17206
+ if (modelIDs !== undefined && !modelIDs.has(model)) {
17207
+ throw new ModelResidencyError("identity");
17208
+ }
17209
+ const residency = await readLemonadeResidency(base, healthFetch, {
17210
+ ...options,
17211
+ signal,
17212
+ headers: request.headers
17213
+ });
17214
+ signal.throwIfAborted();
17215
+ const entry = residency.get(model);
17216
+ if (entry?.loaded !== true) {
17217
+ throw new ModelResidencyError(entry?.loaded === undefined && entry !== undefined ? "unknown" : "inactive");
17218
+ }
17219
+ }, { ...options, signal: request.signal });
17220
+ }
17221
+ if (request.signal.aborted)
17222
+ throw new ModelResidencyError("cancelled");
17223
+ const {
17224
+ body: _body,
17225
+ headers: _headers,
17226
+ method: _method,
17227
+ signal: _signal,
17228
+ redirect: _redirect,
17229
+ ...transportOptions
17230
+ } = init ?? {};
17231
+ return upstream(request, { ...transportOptions, redirect: "error" });
17232
+ }, {
17233
+ preconnect: (...args) => upstream.preconnect?.(...args)
17234
+ });
17235
+ }
17236
+
17237
+ // src/plugin/modelResidency.ts
17238
+ function isFetch(value) {
17239
+ return typeof value === "function";
17240
+ }
17241
+ function origin(value) {
17242
+ return typeof value === "string" && URL.canParse(value) ? new URL(value).origin : undefined;
17243
+ }
17244
+ var TEMPLATE_REFERENCE = /\$\{[^}]+\}/;
17245
+ function resolveTemplateReferences(value, readEnv) {
17246
+ let unresolved = false;
17247
+ const resolved = value.replace(/\$\{([^}]+)\}/g, (match, key) => {
17248
+ const resolvedValue = readEnv(key);
17249
+ if (resolvedValue === undefined) {
17250
+ unresolved = true;
17251
+ return match;
17252
+ }
17253
+ return resolvedValue;
17254
+ });
17255
+ return unresolved ? undefined : resolved;
17256
+ }
17257
+ function endpointBinding(value, readEnv) {
17258
+ if (!TEMPLATE_REFERENCE.test(value))
17259
+ return { ambiguous: false, origin: origin(value) };
17260
+ const resolved = resolveTemplateReferences(value, readEnv);
17261
+ return resolved === undefined ? { ambiguous: true } : { ambiguous: false, origin: origin(resolved) };
17262
+ }
17263
+ function optionBaseURL(value) {
17264
+ return typeof value === "string" && value !== "" ? value : undefined;
17265
+ }
17266
+ function providerBase(provider, model) {
17267
+ return optionBaseURL(provider.options?.baseURL) ?? model?.provider?.api ?? provider.api;
17268
+ }
17269
+ function providerRoutes(provider) {
17270
+ const models = Object.values(provider.models ?? {});
17271
+ return (models.length === 0 ? [undefined] : models).map((model) => ({
17272
+ baseURL: providerBase(provider, model),
17273
+ npm: model?.provider?.npm ?? provider.npm
17274
+ }));
17275
+ }
17276
+ function wireID(key, model) {
17277
+ const id = model?.id ?? key;
17278
+ if (id.length === 0 || id !== id.trim())
17279
+ throw new ModelResidencyError("identity");
17280
+ return id;
17281
+ }
17282
+ function nativeEligibleID(id) {
17283
+ return id === "openai" || id === "anthropic" || id.startsWith("opencode");
17284
+ }
17285
+ function configuredRuntime(config, providerID) {
17286
+ const runtimes = config.local.runtimes.filter((runtime2) => runtime2.defaultModel.providerID === providerID);
17287
+ const runtime = runtimes[0];
17288
+ if (runtimes.length !== 1 || runtime === undefined || !runtime.enabled) {
17289
+ throw new ModelResidencyError("destination");
17290
+ }
17291
+ return runtime;
17292
+ }
17293
+ function createModelResidencyGuard(config, options) {
17294
+ const guarded = new Map;
17295
+ const blocked = new Set;
17296
+ let hostConfig;
17297
+ const readEnv = options.readEnv ?? ((name) => process.env[name]);
17298
+ const lemonadeRuntimes = () => config.local.runtimes.filter((runtime) => localRuntimeKind(runtime) === "lemonade");
17299
+ const protects = (providerID, baseURL) => lemonadeRuntimes().some((runtime) => {
17300
+ if (runtime.defaultModel.providerID === providerID)
17301
+ return true;
17302
+ if (baseURL === undefined)
17303
+ return false;
17304
+ const binding = endpointBinding(baseURL, readEnv);
17305
+ if (binding.ambiguous)
17306
+ return true;
17307
+ return binding.origin !== undefined && binding.origin === origin(runtime.baseURL ?? LEMONADE_DEFAULT_BASE_URL);
17308
+ });
17309
+ const resolvedWireID = (model, declaredID) => {
17310
+ const id = options.resolveApiModelID === undefined ? declaredID : options.resolveApiModelID(model);
17311
+ if (id === undefined)
17312
+ throw new ModelResidencyError("identity");
17313
+ return wireID(id, undefined);
17314
+ };
17315
+ const configHook = async (host) => {
17316
+ hostConfig = host;
17317
+ const previousGuards = new Map(guarded);
17318
+ guarded.clear();
17319
+ blocked.clear();
17320
+ for (const [providerID, provider] of Object.entries(host.provider ?? {})) {
17321
+ const routes = providerRoutes(provider);
17322
+ if (!routes.some((route) => protects(providerID, route.baseURL)))
17323
+ continue;
17324
+ const previous = previousGuards.get(providerID);
17325
+ const configuredFetch = provider.options?.fetch;
17326
+ const originalFetch = previous !== undefined && configuredFetch === previous.fetch ? previous.originalFetch : configuredFetch ?? options.fetch;
17327
+ blocked.add(providerID);
17328
+ const wasDisabled = host.disabled_providers?.includes(providerID) ?? false;
17329
+ host.disabled_providers = [
17330
+ ...new Set([...host.disabled_providers ?? [], providerID])
17331
+ ];
17332
+ const reject = Object.assign(async () => {
17333
+ throw new ModelResidencyError("transport");
17334
+ }, { preconnect: () => {} });
17335
+ provider.options = { ...provider.options, fetch: reject };
17336
+ try {
17337
+ const runtime = configuredRuntime(config, providerID);
17338
+ const baseURL = lemonadeBaseURL(runtime.baseURL ?? LEMONADE_DEFAULT_BASE_URL);
17339
+ if (localRuntimeKind(runtime) !== "lemonade" || routes.some((route) => route.baseURL === undefined || lemonadeBaseURL(route.baseURL) !== baseURL))
17340
+ throw new ModelResidencyError("destination");
17341
+ if (routes.some((route) => route.npm !== "@ai-sdk/openai-compatible") || nativeEligibleID(providerID) || !isFetch(originalFetch))
17342
+ throw new ModelResidencyError("transport");
17343
+ const modelKeys = new Map;
17344
+ for (const [key, model] of Object.entries(provider.models ?? {})) {
17345
+ if (model.options?.fetch !== undefined || model.options?.baseURL !== undefined && (typeof model.options.baseURL !== "string" || lemonadeBaseURL(model.options.baseURL) !== baseURL))
17346
+ throw new ModelResidencyError("transport");
17347
+ modelKeys.set(key, wireID(key, model));
17348
+ }
17349
+ if (!modelKeys.has(runtime.defaultModel.modelID))
17350
+ modelKeys.set(runtime.defaultModel.modelID, undefined);
17351
+ const modelIDs = () => {
17352
+ const ids = new Set;
17353
+ for (const [modelID2, declaredID] of modelKeys) {
17354
+ const id = options.resolveApiModelID === undefined ? declaredID : options.resolveApiModelID({ providerID, modelID: modelID2 });
17355
+ if (id !== undefined)
17356
+ ids.add(wireID(id, undefined));
17357
+ }
17358
+ return ids;
17359
+ };
17360
+ const fetch = createLemonadeGuardedFetch({
17361
+ ...options,
17362
+ baseURL,
17363
+ modelIDs: async () => {
17364
+ await options.modelInventoryReady?.();
17365
+ return modelIDs();
17366
+ },
17367
+ fetch: originalFetch,
17368
+ healthFetch: options.fetch
17369
+ });
17370
+ provider.options.fetch = fetch;
17371
+ guarded.set(providerID, {
17372
+ baseURL,
17373
+ fetch,
17374
+ originalFetch,
17375
+ modelIDs,
17376
+ modelKeys
17377
+ });
17378
+ blocked.delete(providerID);
17379
+ if (!wasDisabled) {
17380
+ host.disabled_providers = host.disabled_providers.filter((id) => id !== providerID);
17381
+ }
17382
+ } catch (error) {
17383
+ if (!(error instanceof ModelResidencyError))
17384
+ throw error;
17385
+ (options.warn ?? console.warn)(modelResidencyMessages.providerDisabled(providerID));
17386
+ }
17387
+ }
17388
+ };
17389
+ const beforeInference = async (input) => {
17390
+ const base = optionBaseURL(input.provider.options.baseURL) ?? input.model.api.url;
17391
+ if (!protects(input.model.providerID, base))
17392
+ return;
17393
+ const provider = guarded.get(input.model.providerID);
17394
+ 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))
17395
+ throw new ModelResidencyError("transport");
17396
+ if (lemonadeBaseURL(base) !== provider.baseURL) {
17397
+ throw new ModelResidencyError("destination");
17398
+ }
17399
+ const id = resolvedWireID({ providerID: input.model.providerID, modelID: input.model.id }, provider.modelKeys.get(input.model.id));
17400
+ if (id !== input.model.api.id)
17401
+ throw new ModelResidencyError("identity");
17402
+ if (!provider.modelKeys.has(input.model.id))
17403
+ provider.modelKeys.set(input.model.id, undefined);
17404
+ };
17405
+ const localTarget = (model) => {
17406
+ const runtime = configuredRuntime(config, model.providerID);
17407
+ if (hostConfig?.disabled_providers?.includes(model.providerID)) {
17408
+ throw new ModelResidencyError("transport");
17409
+ }
17410
+ if (runtime.baseURL === undefined)
17411
+ throw new ModelResidencyError("destination");
17412
+ const provider = hostConfig?.provider?.[model.providerID];
17413
+ const entry = Object.hasOwn(provider?.models ?? {}, model.modelID) ? provider?.models?.[model.modelID] : undefined;
17414
+ const configuredURL = provider === undefined ? undefined : providerBase(provider, entry);
17415
+ if (configuredURL !== undefined && new URL(configuredURL).href.replace(/\/$/, "") !== new URL(runtime.baseURL).href.replace(/\/$/, "")) {
17416
+ throw new ModelResidencyError("destination");
17417
+ }
17418
+ const modelID2 = resolvedWireID(model, entry === undefined && localRuntimeKind(runtime) === "lemonade" ? undefined : wireID(model.modelID, entry));
17419
+ let fetch = options.fetch;
17420
+ if (localRuntimeKind(runtime) === "lemonade") {
17421
+ const installed = guarded.get(model.providerID);
17422
+ if (installed === undefined || blocked.has(model.providerID)) {
17423
+ throw new ModelResidencyError("transport");
17424
+ }
17425
+ if (installed.baseURL !== lemonadeBaseURL(runtime.baseURL)) {
17426
+ throw new ModelResidencyError("destination");
17427
+ }
17428
+ if (!installed.modelKeys.has(model.modelID))
17429
+ installed.modelKeys.set(model.modelID, undefined);
17430
+ if (!installed.modelIDs().has(modelID2))
17431
+ throw new ModelResidencyError("identity");
17432
+ fetch = installed.fetch;
17433
+ }
17434
+ const configuredHeaders = z25.record(z25.string(), z25.string()).safeParse(provider?.options?.headers ?? {});
17435
+ if (!configuredHeaders.success)
17436
+ throw new ModelResidencyError("configuration");
17437
+ const headers = new Headers(configuredHeaders.data);
17438
+ if (typeof provider?.options?.apiKey === "string" && !headers.has("authorization")) {
17439
+ headers.set("authorization", `Bearer ${provider.options.apiKey}`);
17440
+ }
17441
+ for (const [name, value] of Object.entries(entry?.headers ?? {}))
17442
+ headers.set(name, value);
17443
+ const upstream = fetch;
17444
+ return {
17445
+ baseURL: runtime.baseURL,
17446
+ modelID: modelID2,
17447
+ fetch: [...headers].length === 0 ? fetch : Object.assign(async (input, init) => {
17448
+ const request = new Request(input, init);
17449
+ for (const [name, value] of headers) {
17450
+ if (!request.headers.has(name))
17451
+ request.headers.set(name, value);
17452
+ }
17453
+ return upstream(request);
17454
+ }, {
17455
+ preconnect: (...args) => upstream.preconnect?.(...args)
17456
+ })
17457
+ };
17458
+ };
17459
+ return { config: configHook, beforeInference, localTarget };
17460
+ }
17461
+
16842
17462
  // src/plugin/hooks.ts
16843
17463
  var codeSignals = [
16844
17464
  "```",
@@ -16982,7 +17602,10 @@ function createChatMessageHook(config, getAvailable, options = {}) {
16982
17602
  };
16983
17603
  }
16984
17604
  function createHooks(config, getAvailable, options = {}) {
17605
+ const residency = options.modelResidency ?? createModelResidencyGuard(config, { fetch: globalThis.fetch });
16985
17606
  return {
17607
+ config: residency.config,
17608
+ "chat.params": residency.beforeInference,
16986
17609
  "chat.message": createChatMessageHook(config, getAvailable, options)
16987
17610
  };
16988
17611
  }
@@ -17036,62 +17659,62 @@ ${lines.join(`
17036
17659
  }
17037
17660
 
17038
17661
  // src/memory/types.ts
17039
- import { z as z24 } from "zod";
17662
+ import { z as z26 } from "zod";
17040
17663
  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),
17664
+ var OwnerKeySchema = z26.string().min(1);
17665
+ var MemoryKindSchema = z26.enum(["fact", "preference", "entity"]);
17666
+ var MemoryBaseSchema = z26.object({
17667
+ id: z26.string().min(1),
17045
17668
  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)
17669
+ confidence: z26.number().min(0).max(1),
17670
+ validFrom: z26.number().finite(),
17671
+ validUntil: z26.number().finite().nullable().default(null),
17672
+ createdAt: z26.number().finite(),
17673
+ invalidatedAt: z26.number().finite().nullable().default(null),
17674
+ sourceHash: z26.string().min(1),
17675
+ supersededBy: z26.string().min(1).nullable().default(null)
17053
17676
  }).strict();
17054
17677
  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)
17678
+ kind: z26.literal("fact"),
17679
+ subject: z26.string().min(1),
17680
+ predicate: z26.string().min(1),
17681
+ object: z26.string().min(1),
17682
+ category: z26.string().min(1).nullable().default(null)
17060
17683
  });
17061
17684
  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)
17685
+ kind: z26.literal("preference"),
17686
+ category: z26.string().min(1),
17687
+ preference: z26.string().min(1),
17688
+ context: z26.string().min(1).nullable().default(null),
17689
+ lastAccessedAt: z26.number().finite().nullable().default(null),
17690
+ accessCount: z26.number().int().min(0).default(0)
17068
17691
  });
17069
17692
  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([])
17693
+ kind: z26.literal("entity"),
17694
+ canonicalName: z26.string().min(1),
17695
+ type: z26.string().min(1),
17696
+ aliases: z26.array(z26.string().min(1)).default([])
17074
17697
  });
17075
17698
  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)
17699
+ kind: z26.literal("relation"),
17700
+ from: z26.string().min(1),
17701
+ to: z26.string().min(1),
17702
+ predicate: z26.string().min(1),
17703
+ annotation: z26.string().min(1).nullable().default(null)
17081
17704
  });
17082
- var MemoryRecordSchema = z24.discriminatedUnion("kind", [
17705
+ var MemoryRecordSchema = z26.discriminatedUnion("kind", [
17083
17706
  FactSchema,
17084
17707
  PreferenceSchema,
17085
17708
  EntitySchema,
17086
17709
  RelationSchema
17087
17710
  ]);
17088
- var RecallQuerySchema = z24.object({
17711
+ var RecallQuerySchema = z26.object({
17089
17712
  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)
17713
+ kinds: z26.array(MemoryKindSchema).default(["fact", "preference", "entity"]),
17714
+ asOf: z26.number().finite().nullable().default(null),
17715
+ limit: z26.number().int().positive().default(8),
17716
+ minSimilarity: z26.number().min(0).max(1).default(0.2),
17717
+ includeShared: z26.boolean().default(true)
17095
17718
  }).strict();
17096
17719
 
17097
17720
  // src/memory/rank.ts
@@ -17662,42 +18285,42 @@ function buildMemoryInjector(deps, policy) {
17662
18285
 
17663
18286
  // src/plugin/memoryTool.ts
17664
18287
  import { tool as tool4 } from "@opencode-ai/plugin";
17665
- import { z as z26 } from "zod";
18288
+ import { z as z28 } from "zod";
17666
18289
 
17667
18290
  // src/memory/extract.ts
17668
- import { z as z25 } from "zod";
18291
+ import { z as z27 } from "zod";
17669
18292
  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()
18293
+ var RawFactSchema = z27.object({
18294
+ subject: z27.string().min(1),
18295
+ predicate: z27.string().min(1),
18296
+ object: z27.string().min(1),
18297
+ category: z27.string().min(1).nullable().optional(),
18298
+ confidence: z27.number().min(0).max(1).optional()
17676
18299
  });
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()
18300
+ var RawPreferenceSchema = z27.object({
18301
+ category: z27.string().min(1),
18302
+ preference: z27.string().min(1),
18303
+ context: z27.string().min(1).nullable().optional(),
18304
+ confidence: z27.number().min(0).max(1).optional()
17682
18305
  });
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()
18306
+ var RawEntitySchema = z27.object({
18307
+ canonicalName: z27.string().min(1),
18308
+ type: z27.string().min(1),
18309
+ aliases: z27.array(z27.string().min(1)).optional(),
18310
+ confidence: z27.number().min(0).max(1).optional()
17688
18311
  });
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()
18312
+ var RawRelationSchema = z27.object({
18313
+ from: z27.string().min(1),
18314
+ to: z27.string().min(1),
18315
+ predicate: z27.string().min(1),
18316
+ annotation: z27.string().min(1).nullable().optional(),
18317
+ confidence: z27.number().min(0).max(1).optional()
17695
18318
  }).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([])
18319
+ var RawExtractionSchema = z27.object({
18320
+ facts: z27.array(RawFactSchema).default([]),
18321
+ preferences: z27.array(RawPreferenceSchema).default([]),
18322
+ entities: z27.array(RawEntitySchema).default([]),
18323
+ relations: z27.array(RawRelationSchema).default([])
17701
18324
  });
17702
18325
  var DEFAULT_CONFIDENCE = 0.6;
17703
18326
  var SYSTEM_PROMPT = [
@@ -17951,13 +18574,13 @@ var memoryToolMessages = {
17951
18574
 
17952
18575
  // src/plugin/memoryTool.ts
17953
18576
  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)
18577
+ var MemoryMessageSchema = z28.object({
18578
+ role: z28.enum(["system", "user", "assistant"]).describe(memoryToolMessages.messageRoleDescription),
18579
+ content: z28.string().min(1).describe(memoryToolMessages.messageContentDescription)
17957
18580
  }).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)
18581
+ var MemoryWritePayloadSchema = z28.object({
18582
+ messages: z28.array(MemoryMessageSchema).min(1).describe(memoryToolMessages.messagesDescription),
18583
+ roleID: z28.string().min(1).default(SCRIBE_ROLE_ID).describe(memoryToolMessages.roleIDDescription)
17961
18584
  }).strict();
17962
18585
  function createMemoryTool(deps) {
17963
18586
  return tool4({
@@ -17969,7 +18592,7 @@ function createMemoryTool(deps) {
17969
18592
  })).describe(memoryToolMessages.messagesDescription),
17970
18593
  roleID: tool4.schema.string().optional().describe(memoryToolMessages.roleIDDescription)
17971
18594
  },
17972
- async execute(args) {
18595
+ async execute(args, toolContext) {
17973
18596
  const parsed = MemoryWritePayloadSchema.safeParse(args);
17974
18597
  if (!parsed.success) {
17975
18598
  return memoryToolMessages.validationError(parsed.error.message);
@@ -17990,33 +18613,83 @@ function createMemoryTool(deps) {
17990
18613
  if (executionMode2 === "frontier") {
17991
18614
  return memoryToolMessages.frontierDomainRefusal;
17992
18615
  }
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
18616
  let records;
18013
18617
  try {
18618
+ const signal = toolContext.abort;
18619
+ const throwIfAborted = () => {
18620
+ if (signal?.aborted)
18621
+ throw new ModelResidencyError("cancelled");
18622
+ };
18623
+ throwIfAborted();
18624
+ const configuredModel = semantic.extraction.model;
18625
+ let runtime;
18626
+ if (configuredModel != null) {
18627
+ const matches = deps.config.local.runtimes.filter((candidate) => candidate.defaultModel.providerID === configuredModel.providerID);
18628
+ runtime = matches[0];
18629
+ if (matches.length !== 1 || runtime === undefined || !runtime.enabled) {
18630
+ return modelResidencyMessages.extractionRuntimeUnavailable;
18631
+ }
18632
+ } else {
18633
+ runtime = deps.config.local.runtimes.find((candidate) => candidate.enabled && typeof candidate.baseURL === "string" && candidate.baseURL.length > 0);
18634
+ }
18635
+ if (runtime?.baseURL === undefined || runtime.baseURL.length === 0) {
18636
+ return memoryToolMessages.localRuntimeBaseURLMissing;
18637
+ }
18638
+ const baseURL = runtime.baseURL;
18639
+ const model = configuredModel ?? runtime.defaultModel;
18640
+ const selectedRuntime = runtime;
18641
+ const deadline = {
18642
+ ...deps.residencyOptions,
18643
+ ...signal === undefined ? {} : { signal }
18644
+ };
18645
+ const reachable = localRuntimeKind(runtime) === "lemonade" ? await withResidencyDeadline((signal2) => deps.localRuntimeReachable(selectedRuntime, signal2), deadline) : await deps.localRuntimeReachable(runtime);
18646
+ throwIfAborted();
18647
+ if (!reachable)
18648
+ return memoryToolMessages.localRuntimeUnavailable;
18649
+ const resolveTarget = deps.resolveExtractionTarget;
18650
+ const target = resolveTarget ? await withResidencyDeadline(async () => resolveTarget(model), deadline) : {
18651
+ baseURL,
18652
+ modelID: model.modelID,
18653
+ fetch: localRuntimeKind(runtime) === "lemonade" ? createLemonadeGuardedFetch({
18654
+ baseURL,
18655
+ fetch: deps.fetch,
18656
+ modelIDs: new Set([model.modelID]),
18657
+ ...deps.residencyOptions
18658
+ }) : deps.fetch
18659
+ };
18660
+ throwIfAborted();
18661
+ if (target === undefined || target.baseURL !== baseURL) {
18662
+ throw new ModelResidencyError("destination");
18663
+ }
18664
+ const fetch = signal === undefined ? target.fetch : Object.assign(async (input, init) => {
18665
+ throwIfAborted();
18666
+ const response = await target.fetch(input, {
18667
+ ...init,
18668
+ signal
18669
+ });
18670
+ throwIfAborted();
18671
+ return response;
18672
+ }, {
18673
+ preconnect: (...args2) => target.fetch.preconnect?.(...args2)
18674
+ });
18675
+ const transcript = messages.map((m) => `${m.role}: ${m.content}`).join(`
18676
+ `);
18677
+ const sourceHash = sha256Hex(transcript);
18678
+ const now = deps.now();
18679
+ const context = {
18680
+ ownerKey: semantic.scope === "user" ? "user" : "project",
18681
+ now,
18682
+ sourceHash,
18683
+ storeContent: semantic.storeContent,
18684
+ idPrefix: `${sourceHash.slice(0, 12)}:${now}`
18685
+ };
18014
18686
  records = await extractMemory({
18015
- baseURL: runtime.baseURL,
18016
- modelID,
18687
+ baseURL: target.baseURL,
18688
+ modelID: target.modelID,
18017
18689
  messages,
18018
18690
  context
18019
- }, { fetch: deps.fetch, ...deps.warn ? { warn: deps.warn } : {} });
18691
+ }, { fetch, ...deps.warn ? { warn: deps.warn } : {} });
18692
+ throwIfAborted();
18020
18693
  } catch (error) {
18021
18694
  const reason = error instanceof Error ? error.message : String(error);
18022
18695
  return memoryToolMessages.extractionFailure(reason);
@@ -18082,10 +18755,10 @@ function createOrchestratedModelOwnership() {
18082
18755
 
18083
18756
  // src/plugin/orchestrateTool.ts
18084
18757
  import { tool as tool5 } from "@opencode-ai/plugin";
18085
- import { z as z28 } from "zod";
18758
+ import { z as z30 } from "zod";
18086
18759
 
18087
18760
  // src/orchestrator/coordinator.ts
18088
- import { z as z27 } from "zod";
18761
+ import { z as z29 } from "zod";
18089
18762
 
18090
18763
  // src/orchestrator/nodeIteration.ts
18091
18764
  var DEFAULT_MAX_RETRIES = 2;
@@ -18295,12 +18968,15 @@ async function applyReportDurabilityGate(results, probe) {
18295
18968
  }
18296
18969
 
18297
18970
  // src/orchestrator/runtimeSelection.ts
18298
- function configuredRuntime(runtimeId, config) {
18971
+ function configuredRuntime2(runtimeId, config) {
18299
18972
  return config.local.runtimes.find((runtime) => runtime.id === runtimeId);
18300
18973
  }
18301
18974
  function runtimeIdOfModel(model, config) {
18302
18975
  return config.local.runtimes.find((runtime) => sameModel(runtime.defaultModel, model))?.id;
18303
18976
  }
18977
+ function enabledRuntimeForProvider(providerID, config) {
18978
+ return config.local.runtimes.find((runtime) => runtime.enabled && runtime.defaultModel.providerID === providerID)?.id;
18979
+ }
18304
18980
  function roleLocalModel(role, runtimeId, fallback, runtime) {
18305
18981
  const pinned = role.localModels?.[runtimeId];
18306
18982
  if (pinned !== undefined) {
@@ -18315,7 +18991,7 @@ function runtimeClassModel(modelClass, runtime) {
18315
18991
  }
18316
18992
  return modelClass === "thinking" ? runtime.thinkingModel : runtime.coderModel;
18317
18993
  }
18318
- function selectDispatchRuntime(role, decision2, reachable, config) {
18994
+ function selectDispatchRuntime(role, decision2, reachable, config, availableModels2) {
18319
18995
  if (decision2.routeKind !== "local") {
18320
18996
  return { runtimeId: undefined, decision: decision2 };
18321
18997
  }
@@ -18326,7 +19002,7 @@ function selectDispatchRuntime(role, decision2, reachable, config) {
18326
19002
  if (!reachable.has(runtimeId)) {
18327
19003
  continue;
18328
19004
  }
18329
- const runtime = configuredRuntime(runtimeId, config);
19005
+ const runtime = configuredRuntime2(runtimeId, config);
18330
19006
  if (runtime?.defaultModel.providerID === decision2.selected.providerID) {
18331
19007
  return { runtimeId, decision: decision2 };
18332
19008
  }
@@ -18336,15 +19012,17 @@ function selectDispatchRuntime(role, decision2, reachable, config) {
18336
19012
  if (exactRuntimeId !== undefined) {
18337
19013
  return { runtimeId: exactRuntimeId, decision: decision2 };
18338
19014
  }
18339
- const providerRuntime = config.local.runtimes.find((runtime) => runtime.enabled && runtime.defaultModel.providerID === decision2.selected.providerID);
18340
- return { runtimeId: providerRuntime?.id, decision: decision2 };
19015
+ return {
19016
+ runtimeId: enabledRuntimeForProvider(decision2.selected.providerID, config),
19017
+ decision: decision2
19018
+ };
18341
19019
  }
18342
19020
  if (listed !== undefined && listed.length > 0 && reachable !== undefined) {
18343
19021
  for (const runtimeId of listed) {
18344
19022
  if (!reachable.has(runtimeId)) {
18345
19023
  continue;
18346
19024
  }
18347
- const runtime = configuredRuntime(runtimeId, config);
19025
+ const runtime = configuredRuntime2(runtimeId, config);
18348
19026
  if (runtime === undefined) {
18349
19027
  continue;
18350
19028
  }
@@ -18357,7 +19035,7 @@ function selectDispatchRuntime(role, decision2, reachable, config) {
18357
19035
  }
18358
19036
  const resolvedRuntimeId = runtimeIdOfModel(decision2.selected, config);
18359
19037
  if (resolvedRuntimeId !== undefined) {
18360
- const pinned = roleLocalModel(role, resolvedRuntimeId, decision2.selected, configuredRuntime(resolvedRuntimeId, config));
19038
+ const pinned = roleLocalModel(role, resolvedRuntimeId, decision2.selected, configuredRuntime2(resolvedRuntimeId, config));
18361
19039
  if (pinned !== decision2.selected) {
18362
19040
  return {
18363
19041
  runtimeId: resolvedRuntimeId,
@@ -18365,8 +19043,9 @@ function selectDispatchRuntime(role, decision2, reachable, config) {
18365
19043
  };
18366
19044
  }
18367
19045
  }
19046
+ const knownAlias = localModelAliases(decision2.selected.providerID, availableModels2).has(decision2.selected.modelID);
18368
19047
  return {
18369
- runtimeId: resolvedRuntimeId,
19048
+ runtimeId: resolvedRuntimeId ?? (knownAlias ? enabledRuntimeForProvider(decision2.selected.providerID, config) : undefined),
18370
19049
  decision: decision2
18371
19050
  };
18372
19051
  }
@@ -18553,7 +19232,7 @@ function buildRecord(input, decision2, subsession, deps, decisionID, batchID) {
18553
19232
  }
18554
19233
  return record;
18555
19234
  }
18556
- var TelemetryFailureClassSchema = z27.enum([
19235
+ var TelemetryFailureClassSchema = z29.enum([
18557
19236
  "create-rejected",
18558
19237
  "create-no-id",
18559
19238
  "prompt-rejected",
@@ -18812,7 +19491,7 @@ async function runRoleTaskWithCorrelation(input, deps, correlation, batch, route
18812
19491
  if (routed.routeKind === "blocked") {
18813
19492
  throw new Error(coordinatorRoutingBlocked(input.roleID, routed.blockReason));
18814
19493
  }
18815
- const selection = selectDispatchRuntime(role, routed, batch.set, input.config);
19494
+ const selection = selectDispatchRuntime(role, routed, batch.set, input.config, input.availableModels);
18816
19495
  const decision2 = selection.decision;
18817
19496
  const composed = composeSubsessionPrompt({
18818
19497
  prompt: input.prompt,
@@ -18894,8 +19573,9 @@ async function runRoleTaskWithCorrelation(input, deps, correlation, batch, route
18894
19573
  if (runtimeId !== undefined && deps.runtimeLimiter !== undefined) {
18895
19574
  const limiter = deps.runtimeLimiter;
18896
19575
  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);
19576
+ const dispatchRuntime = configuredRuntime2(runtimeId, input.config) ?? { id: runtimeId };
19577
+ const aliases = localModelAliases(decision2.selected.providerID, input.availableModels);
19578
+ const poolKey = slotPoolKey(withReportedModelSlots(dispatchRuntime, deps.reportedModelSlots?.(runtimeId), aliases), aliases.get(decision2.selected.modelID) ?? decision2.selected.modelID);
18899
19579
  release = limiter.tryAcquire(poolKey, priority);
18900
19580
  let waitedMs = 0;
18901
19581
  if (release === undefined) {
@@ -19369,7 +20049,7 @@ async function runRoleTasks(inputs, deps, options = {}) {
19369
20049
  var _pluginWarnedRoles = new Set;
19370
20050
  var EMPTY_ROLE_ID_SET = new Set;
19371
20051
  var SAFE_ROLE_ID = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
19372
- var RoleIDSchema = z28.string().min(1).superRefine((roleID, ctx) => {
20052
+ var RoleIDSchema = z30.string().min(1).superRefine((roleID, ctx) => {
19373
20053
  if (!SAFE_ROLE_ID.test(roleID)) {
19374
20054
  ctx.addIssue({
19375
20055
  code: "custom",
@@ -19377,16 +20057,16 @@ var RoleIDSchema = z28.string().min(1).superRefine((roleID, ctx) => {
19377
20057
  });
19378
20058
  }
19379
20059
  });
19380
- var RoleAssignmentSchema = z28.object({
20060
+ var RoleAssignmentSchema = z30.object({
19381
20061
  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)")
20062
+ prompt: z30.string().min(1).describe("Work prompt for this role"),
20063
+ title: z30.string().min(1).optional().describe("Human-readable title"),
20064
+ dependsOn: z30.array(RoleIDSchema).optional().describe("Role IDs this assignment depends on (DAG edges)")
19385
20065
  }).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")
20066
+ var OrchestratePayloadSchema = z30.object({
20067
+ assignments: z30.array(RoleAssignmentSchema).min(1).describe("Role assignments to distribute"),
20068
+ parentSessionID: z30.string().min(1).optional().describe(PARENT_SESSION_DESCRIPTION),
20069
+ directory: z30.string().min(1).optional().describe("Working directory override")
19390
20070
  }).strict();
19391
20071
  function validateAssignmentDependencies(assignments) {
19392
20072
  const ids = new Set;
@@ -20122,7 +20802,7 @@ ${advisory}`;
20122
20802
 
20123
20803
  // src/plugin/registerCastTool.ts
20124
20804
  import { tool as tool6 } from "@opencode-ai/plugin";
20125
- import { z as z29 } from "zod";
20805
+ import { z as z31 } from "zod";
20126
20806
 
20127
20807
  // src/messages/rosterSummary.ts
20128
20808
  var ROSTER_SUMMARY_HEADING = "Registered team model policies";
@@ -20351,13 +21031,13 @@ async function persistPreparedTeam(storage, files) {
20351
21031
  }
20352
21032
 
20353
21033
  // 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")
21034
+ var CastEntrySchema = z31.object({
21035
+ roleID: z31.string().min(1).describe("Stable role identifier, e.g. scribe or guardian"),
21036
+ agentName: z31.string().min(1).describe("Themed character name assigned to the role")
20357
21037
  }).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")
21038
+ var RegisterCastPayloadSchema = z31.object({
21039
+ universe: z31.string().min(1).describe("Casting universe for this roster"),
21040
+ entries: z31.array(CastEntrySchema).min(1).describe("Role-to-name mappings")
20361
21041
  }).strict();
20362
21042
  function offendingFields(error) {
20363
21043
  const fields = error.issues.flatMap((issue) => {
@@ -20976,7 +21656,7 @@ async function buildMemoryRuntimeFromConfig(config, deps, options = {}) {
20976
21656
  if (runtime?.baseURL === undefined) {
20977
21657
  return;
20978
21658
  }
20979
- const modelID = semantic.embeddings.model?.modelID ?? runtime.defaultModel.modelID;
21659
+ const modelID2 = semantic.embeddings.model?.modelID ?? runtime.defaultModel.modelID;
20980
21660
  const openDatabase = deps.openDatabase ?? createBunSqliteDatabase;
20981
21661
  const makeEmbedder = deps.createEmbedder ?? createLocalEmbedder;
20982
21662
  const fetchImpl = deps.fetch ?? globalThis.fetch;
@@ -20989,8 +21669,8 @@ async function buildMemoryRuntimeFromConfig(config, deps, options = {}) {
20989
21669
  if (rebuildResult.rejectedLines > 0) {
20990
21670
  warn(`[openteam] memory log rejected ${rebuildResult.rejectedLines} line(s); semantic memory may be incomplete.`);
20991
21671
  }
20992
- const embedder = makeEmbedder({ baseURL: runtime.baseURL, modelID }, { fetch: fetchImpl });
20993
- await ensureMemoryEmbeddings({ index, embedder, model: modelID, warn });
21672
+ const embedder = makeEmbedder({ baseURL: runtime.baseURL, modelID: modelID2 }, { fetch: fetchImpl });
21673
+ await ensureMemoryEmbeddings({ index, embedder, model: modelID2, warn });
20994
21674
  return {
20995
21675
  index,
20996
21676
  embedder,
@@ -21018,18 +21698,18 @@ import { join as join15, resolve as resolve11 } from "node:path";
21018
21698
  import { ZodError } from "zod";
21019
21699
 
21020
21700
  // src/storage/lifecycle/codec.ts
21021
- import { z as z30 } from "zod";
21701
+ import { z as z32 } from "zod";
21022
21702
  var LIFECYCLE_CODEC_VERSION = 1;
21023
21703
  var LIFECYCLE_GENESIS_DIGEST = sha256Hex("openteam/lifecycle-journal/genesis/v1");
21024
21704
  var NUL5 = "\x00";
21025
21705
  var NEWLINE2 = `
21026
21706
  `;
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()
21707
+ var frameSchema = z32.object({
21708
+ v: z32.literal(LIFECYCLE_CODEC_VERSION),
21709
+ seq: z32.number().int().nonnegative(),
21710
+ prev: z32.string().min(1),
21711
+ sum: z32.string().min(1),
21712
+ event: z32.unknown()
21033
21713
  }).strict();
21034
21714
  function canonical2(value) {
21035
21715
  if (Array.isArray(value)) {
@@ -21369,8 +22049,8 @@ function readRun(runDir, runID) {
21369
22049
  if (metadataText === undefined || eventsText === undefined) {
21370
22050
  throw new LifecycleFsError("corrupt");
21371
22051
  }
21372
- const metadata = parseJson(metadataText, parseLifecycleRunMetadata);
21373
- if (metadata.runID !== runID) {
22052
+ const metadata2 = parseJson(metadataText, parseLifecycleRunMetadata);
22053
+ if (metadata2.runID !== runID) {
21374
22054
  throw new LifecycleFsError("corrupt");
21375
22055
  }
21376
22056
  let decoded;
@@ -21385,10 +22065,10 @@ function readRun(runDir, runID) {
21385
22065
  }
21386
22066
  }
21387
22067
  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) {
22068
+ 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
22069
  throw new LifecycleFsError("corrupt");
21390
22070
  }
21391
- return { metadata, decoded };
22071
+ return { metadata: metadata2, decoded };
21392
22072
  }
21393
22073
  function terminalOutcome(events) {
21394
22074
  const last = events.at(-1);
@@ -21466,7 +22146,7 @@ var createFsLifecycleJournal = (options) => {
21466
22146
  mkdirSync3(stagingPath);
21467
22147
  const writerToken = issueWriterToken();
21468
22148
  const eventAt = now();
21469
- const metadata = parseLifecycleRunMetadata({
22149
+ const metadata2 = parseLifecycleRunMetadata({
21470
22150
  ...parsedInput,
21471
22151
  version: 1,
21472
22152
  createdAt: eventAt
@@ -21482,7 +22162,7 @@ var createFsLifecycleJournal = (options) => {
21482
22162
  executionAuthority: parsedInput.executionAuthority,
21483
22163
  root: parsedInput.root
21484
22164
  });
21485
- writeDurable2(join15(stagingPath, METADATA_FILE), `${JSON.stringify(metadata)}
22165
+ writeDurable2(join15(stagingPath, METADATA_FILE), `${JSON.stringify(metadata2)}
21486
22166
  `);
21487
22167
  writeDurable2(join15(stagingPath, EVENTS_FILE), encodeLifecycleJournal([event]));
21488
22168
  writeDurable2(join15(stagingPath, OWNER_FILE2), `${JSON.stringify(lease)}
@@ -21498,7 +22178,7 @@ var createFsLifecycleJournal = (options) => {
21498
22178
  stagingPath = undefined;
21499
22179
  return ok({
21500
22180
  handle: { runID, writerToken },
21501
- metadata,
22181
+ metadata: metadata2,
21502
22182
  event,
21503
22183
  lease,
21504
22184
  head: 1
@@ -22359,6 +23039,9 @@ async function listConfiguredOpencodeInventory(ctx) {
22359
23039
  providerID: model.providerID,
22360
23040
  modelID: model.id
22361
23041
  };
23042
+ if (typeof model.api?.id === "string" && model.api.id.length > 0 && model.api.id === model.api.id.trim() && model.api.id !== model.id) {
23043
+ configuredModel.apiModelID = model.api.id;
23044
+ }
22362
23045
  if (typeof model.capabilities?.toolcall === "boolean") {
22363
23046
  configuredModel.supportsTools = model.capabilities.toolcall;
22364
23047
  }
@@ -22428,12 +23111,20 @@ var server = async (ctx, rawOptions) => {
22428
23111
  const injectMemory = await buildMemoryInjectorFromConfig(config, storage, diagnostics.warn("memory-runtime-warning", { toast: false }));
22429
23112
  const sessionTracker = createSessionTracker();
22430
23113
  const orchestratedModelOwnership = createOrchestratedModelOwnership();
23114
+ const modelResidency = createModelResidencyGuard(config, {
23115
+ fetch: globalThis.fetch,
23116
+ ...ctx.client.config?.providers === undefined ? {} : {
23117
+ resolveApiModelID: cache.resolveApiModelID,
23118
+ modelInventoryReady: ensureAvailability
23119
+ }
23120
+ });
22431
23121
  const resolveAgentRole = async (agentName) => {
22432
23122
  const entry = (await readRoutingRosterEntries(storage)).find((candidate) => candidate.agentName === agentName);
22433
23123
  return entry?.roleID;
22434
23124
  };
22435
23125
  const hooks = createHooks(config, cache.get, injectMemory === undefined ? {
22436
23126
  sink,
23127
+ modelResidency,
22437
23128
  beforeRoute: ensureAvailability,
22438
23129
  capabilityProfiles,
22439
23130
  orchestratedModelOwnership,
@@ -22441,6 +23132,7 @@ var server = async (ctx, rawOptions) => {
22441
23132
  onRoute: (sid, model) => sessionTracker.trackRoutedModel(sid, model)
22442
23133
  } : {
22443
23134
  sink,
23135
+ modelResidency,
22444
23136
  beforeRoute: ensureAvailability,
22445
23137
  capabilityProfiles,
22446
23138
  injectMemory,
@@ -22561,7 +23253,7 @@ var server = async (ctx, rawOptions) => {
22561
23253
  if (runtime === undefined) {
22562
23254
  return;
22563
23255
  }
22564
- return withReportedModelSlots(runtime, reportedSlotsByRuntime.get(runtimeId));
23256
+ return withReportedModelSlots(runtime, reportedSlotsByRuntime.get(runtimeId), localModelAliases(runtime.defaultModel.providerID, cache.get()));
22565
23257
  };
22566
23258
  const runtimeLimiter = createRuntimeConcurrencyLimiter({
22567
23259
  capacityFor: (key2) => {
@@ -22606,7 +23298,27 @@ var server = async (ctx, rawOptions) => {
22606
23298
  config,
22607
23299
  storage,
22608
23300
  now,
22609
- localRuntimeReachable,
23301
+ localRuntimeReachable: async (runtime, signal) => {
23302
+ if (localRuntimeKind(runtime) === "lemonade") {
23303
+ if (ctx.client.config?.providers !== undefined)
23304
+ await ensureAvailability();
23305
+ signal?.throwIfAborted();
23306
+ const target = modelResidency.localTarget(resolveMemorySemantic(config).extraction.model ?? runtime.defaultModel);
23307
+ const response = await target.fetch(`${target.baseURL}/health`, {
23308
+ method: "GET",
23309
+ ...signal === undefined ? {} : { signal }
23310
+ });
23311
+ return response.ok;
23312
+ }
23313
+ const snapshots = await registry.probe([runtime]);
23314
+ rememberReportedSlots(snapshots);
23315
+ return anyRuntimeReachable(snapshots);
23316
+ },
23317
+ resolveExtractionTarget: async (model) => {
23318
+ if (ctx.client.config?.providers !== undefined)
23319
+ await ensureAvailability();
23320
+ return modelResidency.localTarget(model);
23321
+ },
22610
23322
  fetch: globalThis.fetch,
22611
23323
  warn: diagnostics.warn("memory-extraction-warning", { toast: false })
22612
23324
  });