@elizaos/ui 2.0.0-alpha.197 → 2.0.0-alpha.201

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 (46) hide show
  1. package/apps/app-lifeops/src/actions/calendar.d.ts.map +1 -1
  2. package/apps/app-lifeops/src/actions/calendar.js +99 -6
  3. package/apps/app-lifeops/src/actions/device-bus.d.ts.map +1 -1
  4. package/apps/app-lifeops/src/actions/device-bus.js +49 -8
  5. package/apps/app-lifeops/src/actions/health.d.ts.map +1 -1
  6. package/apps/app-lifeops/src/actions/health.js +23 -4
  7. package/apps/app-lifeops/src/actions/life.d.ts.map +1 -1
  8. package/apps/app-lifeops/src/actions/life.js +9 -2
  9. package/apps/app-lifeops/src/actions/password-manager.d.ts.map +1 -1
  10. package/apps/app-lifeops/src/actions/password-manager.js +44 -2
  11. package/apps/app-lifeops/src/actions/remote-desktop.d.ts.map +1 -1
  12. package/apps/app-lifeops/src/actions/remote-desktop.js +41 -2
  13. package/apps/app-lifeops/src/actions/scheduling.d.ts.map +1 -1
  14. package/apps/app-lifeops/src/actions/scheduling.js +13 -5
  15. package/apps/app-lifeops/src/actions/website-blocker.d.ts.map +1 -1
  16. package/apps/app-lifeops/src/actions/website-blocker.js +53 -4
  17. package/apps/app-lifeops/src/website-blocker/chat-integration/block-rule-service.d.ts.map +1 -1
  18. package/apps/app-lifeops/src/website-blocker/chat-integration/block-rule-service.js +44 -3
  19. package/package.json +1 -1
  20. package/packages/agent/src/types/trajectory.d.ts +2 -2
  21. package/packages/agent/src/types/trajectory.d.ts.map +1 -1
  22. package/packages/app-core/src/api/client-local-inference.d.ts +17 -1
  23. package/packages/app-core/src/api/client-local-inference.d.ts.map +1 -1
  24. package/packages/app-core/src/api/client-local-inference.js +18 -0
  25. package/packages/app-core/src/components/chat/widgets/plugins/agent-orchestrator.d.ts.map +1 -1
  26. package/packages/app-core/src/components/chat/widgets/plugins/agent-orchestrator.js +11 -12
  27. package/packages/app-core/src/components/local-inference/LocalInferencePanel.d.ts.map +1 -1
  28. package/packages/app-core/src/components/local-inference/LocalInferencePanel.js +3 -1
  29. package/packages/app-core/src/components/local-inference/ProvidersList.d.ts +15 -0
  30. package/packages/app-core/src/components/local-inference/ProvidersList.d.ts.map +1 -0
  31. package/packages/app-core/src/components/local-inference/ProvidersList.js +62 -0
  32. package/packages/app-core/src/components/local-inference/RoutingMatrix.d.ts +13 -0
  33. package/packages/app-core/src/components/local-inference/RoutingMatrix.d.ts.map +1 -0
  34. package/packages/app-core/src/components/local-inference/RoutingMatrix.js +105 -0
  35. package/packages/app-core/src/services/local-inference/handler-registry.d.ts +42 -0
  36. package/packages/app-core/src/services/local-inference/handler-registry.d.ts.map +1 -0
  37. package/packages/app-core/src/services/local-inference/handler-registry.js +127 -0
  38. package/packages/app-core/src/services/local-inference/providers.d.ts +61 -0
  39. package/packages/app-core/src/services/local-inference/providers.d.ts.map +1 -0
  40. package/packages/app-core/src/services/local-inference/providers.js +231 -0
  41. package/packages/app-core/src/services/local-inference/routing-preferences.d.ts +29 -0
  42. package/packages/app-core/src/services/local-inference/routing-preferences.d.ts.map +1 -0
  43. package/packages/app-core/src/services/local-inference/routing-preferences.js +71 -0
  44. package/packages/typescript/src/services/message.d.ts +2 -1
  45. package/packages/typescript/src/services/message.d.ts.map +1 -1
  46. package/packages/typescript/src/services/message.js +105 -22
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Side-registry of model handlers registered on an AgentRuntime.
3
+ *
4
+ * The elizaOS core exposes `runtime.registerModel(type, handler, provider,
5
+ * priority)` but no way to list who registered what. This module patches
6
+ * `AgentRuntime.prototype.registerModel` at import time so every call —
7
+ * from every plugin, on every runtime instance — records into a
8
+ * process-wide Map keyed by model type. The router-handler uses the raw
9
+ * handler references to dispatch by policy without re-entering
10
+ * `runtime.useModel`.
11
+ */
12
+ import { AgentRuntime } from "@elizaos/core";
13
+ export function toPublicRegistration(reg) {
14
+ return {
15
+ modelType: reg.modelType,
16
+ provider: reg.provider,
17
+ priority: reg.priority,
18
+ registeredAt: reg.registeredAt,
19
+ };
20
+ }
21
+ class HandlerRegistry {
22
+ registrations = new Map();
23
+ listeners = new Set();
24
+ installedOn = new WeakSet();
25
+ getAll() {
26
+ const out = [];
27
+ for (const list of this.registrations.values()) {
28
+ out.push(...list);
29
+ }
30
+ return out;
31
+ }
32
+ getForType(modelType) {
33
+ const list = this.registrations.get(modelType);
34
+ return list ? [...list] : [];
35
+ }
36
+ getForTypeExcluding(modelType, excludeProvider) {
37
+ return this.getForType(modelType).filter((r) => r.provider !== excludeProvider);
38
+ }
39
+ subscribe(listener) {
40
+ this.listeners.add(listener);
41
+ return () => {
42
+ this.listeners.delete(listener);
43
+ };
44
+ }
45
+ emit() {
46
+ const snapshot = this.getAll();
47
+ for (const listener of this.listeners) {
48
+ try {
49
+ listener(snapshot);
50
+ }
51
+ catch {
52
+ this.listeners.delete(listener);
53
+ }
54
+ }
55
+ }
56
+ record(reg) {
57
+ const existing = this.registrations.get(reg.modelType) ?? [];
58
+ // Last-write-wins per (type, provider) pair; matches core's semantics.
59
+ const filtered = existing.filter((r) => r.provider !== reg.provider);
60
+ filtered.push(reg);
61
+ filtered.sort((a, b) => b.priority - a.priority);
62
+ this.registrations.set(reg.modelType, filtered);
63
+ this.emit();
64
+ }
65
+ installOn(runtime) {
66
+ installPrototypePatch();
67
+ const rt = runtime;
68
+ if (typeof rt.registerModel !== "function")
69
+ return;
70
+ if (this.installedOn.has(rt))
71
+ return;
72
+ this.installedOn.add(rt);
73
+ // If the runtime inherited the prototype patch we're done.
74
+ const proto = Object.getPrototypeOf(rt);
75
+ if (proto?.registerModel?.[PATCH_MARK])
76
+ return;
77
+ // Per-instance wrap as a fallback for runtimes constructed before the
78
+ // prototype was patched (shouldn't happen in practice but defensive).
79
+ const original = rt.registerModel.bind(runtime);
80
+ rt.registerModel = ((modelType, handler, provider, priority) => {
81
+ this.record({
82
+ modelType: String(modelType),
83
+ provider: String(provider),
84
+ priority: typeof priority === "number" ? priority : 0,
85
+ registeredAt: new Date().toISOString(),
86
+ handler,
87
+ });
88
+ return original(modelType, handler, provider, priority);
89
+ });
90
+ }
91
+ }
92
+ export const handlerRegistry = new HandlerRegistry();
93
+ const PATCH_MARK = Symbol.for("milady.local-inference.registerModel.patched");
94
+ let prototypePatched = false;
95
+ function installPrototypePatch() {
96
+ if (prototypePatched)
97
+ return;
98
+ const proto = AgentRuntime.prototype;
99
+ const original = proto.registerModel;
100
+ if (typeof original !== "function")
101
+ return;
102
+ if (original[PATCH_MARK]) {
103
+ prototypePatched = true;
104
+ return;
105
+ }
106
+ const patched = function patchedRegisterModel(modelType, handler, provider, priority) {
107
+ try {
108
+ handlerRegistry.record({
109
+ modelType: String(modelType),
110
+ provider: String(provider),
111
+ priority: typeof priority === "number" ? priority : 0,
112
+ registeredAt: new Date().toISOString(),
113
+ handler,
114
+ });
115
+ }
116
+ catch {
117
+ // Registry bookkeeping must never break registration.
118
+ }
119
+ original.call(this, modelType, handler, provider, priority);
120
+ };
121
+ patched[PATCH_MARK] = true;
122
+ proto.registerModel = patched;
123
+ prototypePatched = true;
124
+ }
125
+ // Install at module-import time. Idempotent and benign — forwards to the
126
+ // original `registerModel` so core semantics are unchanged.
127
+ installPrototypePatch();
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Unified provider registry.
3
+ *
4
+ * Treats every inference source the same way — cloud subscription, cloud
5
+ * API, local llama.cpp engine, paired-device bridge, Capacitor on-device
6
+ * — each is a `ProviderDefinition` with an `id`, a human label, a set of
7
+ * supported model slots, and a pluggable `getEnableState()` that inspects
8
+ * whatever underlying gate controls it (API key presence, subscription
9
+ * status, env flag, file on disk).
10
+ *
11
+ * The cloud-provider status readers are intentionally permissive: they
12
+ * report what they can introspect without depending on the specific
13
+ * cloud-plugin internals, and hand off to the existing ProviderSwitcher
14
+ * UI for actual enable/disable via `configureHref`. That avoids the
15
+ * "unified enable matrix is an architectural project" problem by making
16
+ * configuration navigable rather than centralised.
17
+ */
18
+ import type { AgentModelSlot } from "./types";
19
+ export type ProviderId = "milady-local-inference" | "milady-device-bridge" | "capacitor-llama" | "anthropic" | "openai" | "grok" | "elizacloud" | "google" | "mistral";
20
+ export interface ProviderEnableState {
21
+ enabled: boolean;
22
+ /** Short reason, e.g. "API key set", "Device connected", "No API key". */
23
+ reason: string;
24
+ }
25
+ export interface ProviderDefinition {
26
+ id: ProviderId;
27
+ label: string;
28
+ kind: "cloud-api" | "cloud-subscription" | "local" | "device-bridge";
29
+ /** Short blurb shown in the UI. */
30
+ description: string;
31
+ /** Agent slots this provider can plausibly serve. */
32
+ supportedSlots: AgentModelSlot[];
33
+ /**
34
+ * Read the current enable state. For cloud providers we inspect env
35
+ * vars or config fragments; for local we check file presence; for
36
+ * device-bridge we check connected-device count.
37
+ */
38
+ getEnableState(): Promise<ProviderEnableState>;
39
+ /**
40
+ * Link to the settings UI where enable/configure actually happens.
41
+ * UI sends the user here via anchor-scroll when they click "Configure".
42
+ * `null` means the provider has no separate config surface.
43
+ */
44
+ configureHref: string | null;
45
+ }
46
+ /** Resolve which slots have at least one registered handler from this provider. */
47
+ export declare function getRegisteredSlotsForProvider(providerId: string): string[];
48
+ export declare const BUILT_IN_PROVIDERS: readonly ProviderDefinition[];
49
+ export interface ProviderStatus {
50
+ id: ProviderId;
51
+ label: string;
52
+ kind: ProviderDefinition["kind"];
53
+ description: string;
54
+ supportedSlots: AgentModelSlot[];
55
+ configureHref: string | null;
56
+ enableState: ProviderEnableState;
57
+ /** Registered model types this provider has handlers for, right now. */
58
+ registeredSlots: string[];
59
+ }
60
+ export declare function snapshotProviders(): Promise<ProviderStatus[]>;
61
+ //# sourceMappingURL=providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../../../../../../app-core/src/services/local-inference/providers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,UAAU,GAClB,wBAAwB,GACxB,sBAAsB,GACtB,iBAAiB,GACjB,WAAW,GACX,QAAQ,GACR,MAAM,GACN,YAAY,GACZ,QAAQ,GACR,SAAS,CAAC;AAEd,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,UAAU,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,WAAW,GAAG,oBAAoB,GAAG,OAAO,GAAG,eAAe,CAAC;IACrE,mCAAmC;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,cAAc,EAAE,cAAc,EAAE,CAAC;IACjC;;;;OAIG;IACH,cAAc,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC/C;;;;OAIG;IACH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,mFAAmF;AACnF,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAO1E;AAoMD,eAAO,MAAM,kBAAkB,EAAE,SAAS,kBAAkB,EAU3D,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,UAAU,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,cAAc,EAAE,CAAC;IACjC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,mBAAmB,CAAC;IACjC,wEAAwE;IACxE,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAiBnE"}
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Unified provider registry.
3
+ *
4
+ * Treats every inference source the same way — cloud subscription, cloud
5
+ * API, local llama.cpp engine, paired-device bridge, Capacitor on-device
6
+ * — each is a `ProviderDefinition` with an `id`, a human label, a set of
7
+ * supported model slots, and a pluggable `getEnableState()` that inspects
8
+ * whatever underlying gate controls it (API key presence, subscription
9
+ * status, env flag, file on disk).
10
+ *
11
+ * The cloud-provider status readers are intentionally permissive: they
12
+ * report what they can introspect without depending on the specific
13
+ * cloud-plugin internals, and hand off to the existing ProviderSwitcher
14
+ * UI for actual enable/disable via `configureHref`. That avoids the
15
+ * "unified enable matrix is an architectural project" problem by making
16
+ * configuration navigable rather than centralised.
17
+ */
18
+ import fs from "node:fs/promises";
19
+ import { deviceBridge } from "./device-bridge";
20
+ import { handlerRegistry } from "./handler-registry";
21
+ import { localInferenceRoot } from "./paths";
22
+ /** Resolve which slots have at least one registered handler from this provider. */
23
+ export function getRegisteredSlotsForProvider(providerId) {
24
+ const regs = handlerRegistry.getAll();
25
+ const slots = new Set();
26
+ for (const r of regs) {
27
+ if (r.provider === providerId)
28
+ slots.add(r.modelType);
29
+ }
30
+ return [...slots];
31
+ }
32
+ // ── Built-in provider definitions ────────────────────────────────────
33
+ const LOCAL_PROVIDER = {
34
+ id: "milady-local-inference",
35
+ label: "Local llama.cpp",
36
+ kind: "local",
37
+ description: "On-device inference using node-llama-cpp. Free, private, runs on your machine's CPU/GPU.",
38
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
39
+ async getEnableState() {
40
+ // Enabled when at least one model file lives under our root and the
41
+ // binding is loadable. We don't force-load node-llama-cpp here — that
42
+ // would tie up GPU memory just for a status probe.
43
+ try {
44
+ const entries = await fs.readdir(`${localInferenceRoot()}/models`, {
45
+ withFileTypes: true,
46
+ });
47
+ const hasModel = entries.some((e) => e.isFile() && e.name.toLowerCase().endsWith(".gguf"));
48
+ return hasModel
49
+ ? { enabled: true, reason: "GGUF model installed" }
50
+ : { enabled: false, reason: "No local model installed" };
51
+ }
52
+ catch {
53
+ return { enabled: false, reason: "No local model installed" };
54
+ }
55
+ },
56
+ configureHref: "#local-inference-panel",
57
+ };
58
+ const DEVICE_BRIDGE_PROVIDER = {
59
+ id: "milady-device-bridge",
60
+ label: "Paired device bridge",
61
+ kind: "device-bridge",
62
+ description: "Inference on a paired mobile or desktop device over WebSocket. Useful when the agent runs in a container but the model lives on your phone or laptop.",
63
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
64
+ async getEnableState() {
65
+ const bridgeEnabled = process.env.ELIZA_DEVICE_BRIDGE_ENABLED?.trim() === "1";
66
+ if (!bridgeEnabled) {
67
+ return {
68
+ enabled: false,
69
+ reason: "Set ELIZA_DEVICE_BRIDGE_ENABLED=1 to enable",
70
+ };
71
+ }
72
+ const status = deviceBridge.status();
73
+ if (status.connected) {
74
+ return {
75
+ enabled: true,
76
+ reason: `${status.devices.length} device(s) connected`,
77
+ };
78
+ }
79
+ return {
80
+ enabled: true,
81
+ reason: "Waiting for a device to connect",
82
+ };
83
+ },
84
+ configureHref: "#device-bridge-status",
85
+ };
86
+ const CAPACITOR_LLAMA_PROVIDER = {
87
+ id: "capacitor-llama",
88
+ label: "On-device llama.cpp (mobile)",
89
+ kind: "local",
90
+ description: "Runs llama.cpp natively on iOS or Android via Capacitor. Only available in mobile builds.",
91
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
92
+ async getEnableState() {
93
+ const cap = globalThis.Capacitor;
94
+ if (cap?.isNativePlatform?.()) {
95
+ return {
96
+ enabled: true,
97
+ reason: "Native Capacitor runtime detected",
98
+ };
99
+ }
100
+ return {
101
+ enabled: false,
102
+ reason: "Only available in iOS/Android builds",
103
+ };
104
+ },
105
+ configureHref: null,
106
+ };
107
+ const ANTHROPIC_PROVIDER = {
108
+ id: "anthropic",
109
+ label: "Anthropic API",
110
+ kind: "cloud-api",
111
+ description: "Claude models via the Anthropic API. Requires an API key.",
112
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE", "OBJECT_SMALL", "OBJECT_LARGE"],
113
+ async getEnableState() {
114
+ const key = process.env.ANTHROPIC_API_KEY?.trim();
115
+ return key
116
+ ? { enabled: true, reason: "API key set" }
117
+ : { enabled: false, reason: "No API key" };
118
+ },
119
+ configureHref: "#ai-model",
120
+ };
121
+ const OPENAI_PROVIDER = {
122
+ id: "openai",
123
+ label: "OpenAI API",
124
+ kind: "cloud-api",
125
+ description: "GPT models via the OpenAI API. Requires an API key.",
126
+ supportedSlots: [
127
+ "TEXT_SMALL",
128
+ "TEXT_LARGE",
129
+ "TEXT_EMBEDDING",
130
+ "OBJECT_SMALL",
131
+ "OBJECT_LARGE",
132
+ ],
133
+ async getEnableState() {
134
+ const key = process.env.OPENAI_API_KEY?.trim();
135
+ return key
136
+ ? { enabled: true, reason: "API key set" }
137
+ : { enabled: false, reason: "No API key" };
138
+ },
139
+ configureHref: "#ai-model",
140
+ };
141
+ const GROK_PROVIDER = {
142
+ id: "grok",
143
+ label: "Grok API",
144
+ kind: "cloud-api",
145
+ description: "xAI Grok models. Requires an API key.",
146
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
147
+ async getEnableState() {
148
+ const key = process.env.GROK_API_KEY?.trim() ?? process.env.XAI_API_KEY?.trim();
149
+ return key
150
+ ? { enabled: true, reason: "API key set" }
151
+ : { enabled: false, reason: "No API key" };
152
+ },
153
+ configureHref: "#ai-model",
154
+ };
155
+ const ELIZACLOUD_PROVIDER = {
156
+ id: "elizacloud",
157
+ label: "Eliza Cloud",
158
+ kind: "cloud-subscription",
159
+ description: "Milady-hosted inference routed through your subscription. No API key to manage.",
160
+ supportedSlots: [
161
+ "TEXT_SMALL",
162
+ "TEXT_LARGE",
163
+ "TEXT_EMBEDDING",
164
+ "OBJECT_SMALL",
165
+ "OBJECT_LARGE",
166
+ ],
167
+ async getEnableState() {
168
+ const token = process.env.ELIZA_CLOUD_TOKEN?.trim() ??
169
+ process.env.ELIZACLOUD_TOKEN?.trim() ??
170
+ process.env.ELIZAOS_API_KEY?.trim();
171
+ return token
172
+ ? { enabled: true, reason: "Cloud token set" }
173
+ : { enabled: false, reason: "Not signed in" };
174
+ },
175
+ configureHref: "#ai-model",
176
+ };
177
+ const GOOGLE_PROVIDER = {
178
+ id: "google",
179
+ label: "Google (Gemini)",
180
+ kind: "cloud-api",
181
+ description: "Gemini models via Google Generative AI. Requires an API key.",
182
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE", "OBJECT_SMALL", "OBJECT_LARGE"],
183
+ async getEnableState() {
184
+ const key = process.env.GOOGLE_API_KEY?.trim() ?? process.env.GEMINI_API_KEY?.trim();
185
+ return key
186
+ ? { enabled: true, reason: "API key set" }
187
+ : { enabled: false, reason: "No API key" };
188
+ },
189
+ configureHref: "#ai-model",
190
+ };
191
+ const MISTRAL_PROVIDER = {
192
+ id: "mistral",
193
+ label: "Mistral API",
194
+ kind: "cloud-api",
195
+ description: "Mistral models via la Plateforme. Requires an API key.",
196
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
197
+ async getEnableState() {
198
+ const key = process.env.MISTRAL_API_KEY?.trim();
199
+ return key
200
+ ? { enabled: true, reason: "API key set" }
201
+ : { enabled: false, reason: "No API key" };
202
+ },
203
+ configureHref: "#ai-model",
204
+ };
205
+ export const BUILT_IN_PROVIDERS = [
206
+ LOCAL_PROVIDER,
207
+ DEVICE_BRIDGE_PROVIDER,
208
+ CAPACITOR_LLAMA_PROVIDER,
209
+ ELIZACLOUD_PROVIDER,
210
+ ANTHROPIC_PROVIDER,
211
+ OPENAI_PROVIDER,
212
+ GOOGLE_PROVIDER,
213
+ GROK_PROVIDER,
214
+ MISTRAL_PROVIDER,
215
+ ];
216
+ export async function snapshotProviders() {
217
+ const entries = await Promise.all(BUILT_IN_PROVIDERS.map(async (def) => {
218
+ const state = await def.getEnableState();
219
+ return {
220
+ id: def.id,
221
+ label: def.label,
222
+ kind: def.kind,
223
+ description: def.description,
224
+ supportedSlots: def.supportedSlots,
225
+ configureHref: def.configureHref,
226
+ enableState: state,
227
+ registeredSlots: getRegisteredSlotsForProvider(def.id),
228
+ };
229
+ }));
230
+ return entries;
231
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Per-model-type user overrides: preferred provider + routing policy.
3
+ *
4
+ * Persisted to `$STATE_DIR/local-inference/routing.json` and read by the
5
+ * router-handler at dispatch time. When a slot has no override the
6
+ * router falls back to the runtime's native priority order — i.e. this
7
+ * file is layered over existing registration priority rather than
8
+ * replacing it.
9
+ */
10
+ import type { AgentModelSlot } from "./types";
11
+ export type RoutingPolicy = "manual" | "cheapest" | "fastest" | "prefer-local" | "round-robin";
12
+ export interface RoutingPreferences {
13
+ /**
14
+ * Explicit provider override per agent slot. Empty record = no overrides,
15
+ * runtime picks the highest-priority registered handler.
16
+ */
17
+ preferredProvider: Partial<Record<AgentModelSlot, string>>;
18
+ /**
19
+ * Per-slot policy. "manual" honours `preferredProvider` verbatim;
20
+ * anything else lets the router compute a winner from the policy rule
21
+ * set. Absent = "manual" (matches legacy behaviour).
22
+ */
23
+ policy: Partial<Record<AgentModelSlot, RoutingPolicy>>;
24
+ }
25
+ export declare function readRoutingPreferences(): Promise<RoutingPreferences>;
26
+ export declare function writeRoutingPreferences(prefs: RoutingPreferences): Promise<void>;
27
+ export declare function setPreferredProvider(slot: AgentModelSlot, provider: string | null): Promise<RoutingPreferences>;
28
+ export declare function setPolicy(slot: AgentModelSlot, policy: RoutingPolicy | null): Promise<RoutingPreferences>;
29
+ //# sourceMappingURL=routing-preferences.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing-preferences.d.ts","sourceRoot":"","sources":["../../../../../../../app-core/src/services/local-inference/routing-preferences.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,aAAa,GACrB,QAAQ,GACR,UAAU,GACV,SAAS,GACT,cAAc,GACd,aAAa,CAAC;AAElB,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3D;;;;OAIG;IACH,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC,CAAC;CACxD;AAiBD,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAY1E;AAED,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,IAAI,CAAC,CAMf;AAED,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,GACtB,OAAO,CAAC,kBAAkB,CAAC,CAa7B;AAED,wBAAsB,SAAS,CAC7B,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,aAAa,GAAG,IAAI,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CAa7B"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Per-model-type user overrides: preferred provider + routing policy.
3
+ *
4
+ * Persisted to `$STATE_DIR/local-inference/routing.json` and read by the
5
+ * router-handler at dispatch time. When a slot has no override the
6
+ * router falls back to the runtime's native priority order — i.e. this
7
+ * file is layered over existing registration priority rather than
8
+ * replacing it.
9
+ */
10
+ import fs from "node:fs/promises";
11
+ import path from "node:path";
12
+ import { localInferenceRoot } from "./paths";
13
+ const EMPTY = { preferredProvider: {}, policy: {} };
14
+ function routingPath() {
15
+ return path.join(localInferenceRoot(), "routing.json");
16
+ }
17
+ async function ensureRoot() {
18
+ await fs.mkdir(localInferenceRoot(), { recursive: true });
19
+ }
20
+ export async function readRoutingPreferences() {
21
+ try {
22
+ const raw = await fs.readFile(routingPath(), "utf8");
23
+ const parsed = JSON.parse(raw);
24
+ if (!parsed || parsed.version !== 1 || !parsed.preferences)
25
+ return EMPTY;
26
+ return {
27
+ preferredProvider: parsed.preferences.preferredProvider ?? {},
28
+ policy: parsed.preferences.policy ?? {},
29
+ };
30
+ }
31
+ catch {
32
+ return EMPTY;
33
+ }
34
+ }
35
+ export async function writeRoutingPreferences(prefs) {
36
+ await ensureRoot();
37
+ const payload = { version: 1, preferences: prefs };
38
+ const tmp = `${routingPath()}.tmp`;
39
+ await fs.writeFile(tmp, JSON.stringify(payload, null, 2), "utf8");
40
+ await fs.rename(tmp, routingPath());
41
+ }
42
+ export async function setPreferredProvider(slot, provider) {
43
+ const current = await readRoutingPreferences();
44
+ const next = {
45
+ preferredProvider: { ...current.preferredProvider },
46
+ policy: { ...current.policy },
47
+ };
48
+ if (provider) {
49
+ next.preferredProvider[slot] = provider;
50
+ }
51
+ else {
52
+ delete next.preferredProvider[slot];
53
+ }
54
+ await writeRoutingPreferences(next);
55
+ return next;
56
+ }
57
+ export async function setPolicy(slot, policy) {
58
+ const current = await readRoutingPreferences();
59
+ const next = {
60
+ preferredProvider: { ...current.preferredProvider },
61
+ policy: { ...current.policy },
62
+ };
63
+ if (policy) {
64
+ next.policy[slot] = policy;
65
+ }
66
+ else {
67
+ delete next.policy[slot];
68
+ }
69
+ await writeRoutingPreferences(next);
70
+ return next;
71
+ }
@@ -21,6 +21,7 @@ export declare const RESERVED_XML_KEYS: Set<string>;
21
21
  * Returns the assembled params string, or empty string if none found.
22
22
  */
23
23
  export declare function extractStandaloneActionParams(actionNames: string[], parsedXml: Record<string, unknown>): string;
24
+ export declare function extractPlannerActionNames(parsedXml: Record<string, unknown>): string[];
24
25
  export declare function isSimpleReplyResponse(responseContent: Pick<Content, "actions"> | null | undefined): boolean;
25
26
  /**
26
27
  * True when the planner's `text` field should be surfaced to the user as a
@@ -32,7 +33,7 @@ export declare function isSimpleReplyResponse(responseContent: Pick<Content, "ac
32
33
  * text), IGNORE (no user-visible response), or STOP (terminal). Also skipped
33
34
  * when `text` is empty.
34
35
  */
35
- export declare function shouldEmitPlannerPreamble(responseContent: Pick<Content, "text" | "actions"> | null | undefined): boolean;
36
+ export declare function shouldEmitPlannerPreamble(runtime: Pick<IAgentRuntime, "actions">, responseContent: Pick<Content, "text" | "actions"> | null | undefined): boolean;
36
37
  /**
37
38
  * Default implementation of the MessageService interface.
38
39
  * This service handles the complete message processing pipeline including:
@@ -1 +1 @@
1
- {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../../../../typescript/src/services/message.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAGX,eAAe,EAEf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAGjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EACX,6BAA6B,EAE7B,eAAe,EACf,wBAAwB,EACxB,uBAAuB,EAEvB,MAAM,0BAA0B,CAAC;AAclC,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAEhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAkCtD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,aAM5B,CAAC;AAsIH;;;;;;;;;;GAUG;AACH,wBAAgB,6BAA6B,CAC5C,WAAW,EAAE,MAAM,EAAE,EACrB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,CAiBR;AAohBD,wBAAgB,qBAAqB,CACpC,eAAe,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,GAC1D,OAAO,CAOT;AAuVD;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACxC,eAAe,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,GACnE,OAAO,CAiBT;AA0cD;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAsB,YAAW,eAAe;IAC5D;;OAEG;IACG,aAAa,CAClB,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,eAAe,EAC1B,OAAO,CAAC,EAAE,wBAAwB,GAChC,OAAO,CAAC,uBAAuB,CAAC;IAwmBnC;;OAEG;YACW,cAAc;YAu5Bd,qCAAqC;IA2NnD;;;OAGG;IACH,aAAa,CACZ,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,IAAI,EACX,cAAc,CAAC,EAAE,cAAc,GAC7B,6BAA6B;IA+HhC;;OAEG;IACG,kBAAkB,CACvB,OAAO,EAAE,aAAa,EACtB,WAAW,EAAE,KAAK,EAAE,GAClB,OAAO,CAAC,KAAK,EAAE,CAAC;YA4SL,yBAAyB;YAsMzB,6BAA6B;IAkM3C;;;OAGG;YACW,iBAAiB;YAuajB,wBAAwB;YA6ExB,2BAA2B;IA2IzC;;OAEG;YACW,gBAAgB;IA6f9B;;OAEG;YACW,YAAY;YAqBZ,eAAe;IAY7B;;;;;;;OAOG;IACG,aAAa,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB3E;;;;;;;;OAQG;IACG,YAAY,CACjB,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,IAAI,EACZ,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;CA4ChB"}
1
+ {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../../../../typescript/src/services/message.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAGX,eAAe,EAEf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAGjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EACX,6BAA6B,EAE7B,eAAe,EACf,wBAAwB,EACxB,uBAAuB,EAEvB,MAAM,0BAA0B,CAAC;AAclC,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAEhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAkCtD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,aAM5B,CAAC;AAsIH;;;;;;;;;;GAUG;AACH,wBAAgB,6BAA6B,CAC5C,WAAW,EAAE,MAAM,EAAE,EACrB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,CAiBR;AA+BD,wBAAgB,yBAAyB,CACxC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,EAAE,CAqEV;AA6eD,wBAAgB,qBAAqB,CACpC,eAAe,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,GAC1D,OAAO,CAOT;AA4XD;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACxC,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,EACvC,eAAe,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,GACnE,OAAO,CA0BT;AA0cD;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAsB,YAAW,eAAe;IAC5D;;OAEG;IACG,aAAa,CAClB,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,eAAe,EAC1B,OAAO,CAAC,EAAE,wBAAwB,GAChC,OAAO,CAAC,uBAAuB,CAAC;IAwmBnC;;OAEG;YACW,cAAc;YA25Bd,qCAAqC;IA2NnD;;;OAGG;IACH,aAAa,CACZ,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,IAAI,EACX,cAAc,CAAC,EAAE,cAAc,GAC7B,6BAA6B;IA+HhC;;OAEG;IACG,kBAAkB,CACvB,OAAO,EAAE,aAAa,EACtB,WAAW,EAAE,KAAK,EAAE,GAClB,OAAO,CAAC,KAAK,EAAE,CAAC;YA4SL,yBAAyB;YAsMzB,6BAA6B;IAkM3C;;;OAGG;YACW,iBAAiB;YAuajB,wBAAwB;YA6ExB,2BAA2B;IA2IzC;;OAEG;YACW,gBAAgB;IA6f9B;;OAEG;YACW,YAAY;YAqBZ,eAAe;IAY7B;;;;;;;OAOG;IACG,aAAa,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB3E;;;;;;;;OAQG;IACG,YAAY,CACjB,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,IAAI,EACZ,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;CA4ChB"}