@elizaos/app-core 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 (57) 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/apps/app-training/src/optimizers/bootstrap-fewshot.js +2 -3
  20. package/package.json +5 -5
  21. package/packages/agent/src/types/trajectory.d.ts +2 -2
  22. package/packages/agent/src/types/trajectory.d.ts.map +1 -1
  23. package/packages/app-core/src/api/client-local-inference.d.ts +17 -1
  24. package/packages/app-core/src/api/client-local-inference.d.ts.map +1 -1
  25. package/packages/app-core/src/api/client-local-inference.js +18 -0
  26. package/packages/app-core/src/api/local-inference-compat-routes.d.ts.map +1 -1
  27. package/packages/app-core/src/api/local-inference-compat-routes.js +99 -0
  28. package/packages/app-core/src/components/chat/widgets/plugins/agent-orchestrator.d.ts.map +1 -1
  29. package/packages/app-core/src/components/chat/widgets/plugins/agent-orchestrator.js +11 -12
  30. package/packages/app-core/src/components/local-inference/LocalInferencePanel.d.ts.map +1 -1
  31. package/packages/app-core/src/components/local-inference/LocalInferencePanel.js +3 -1
  32. package/packages/app-core/src/components/local-inference/ProvidersList.d.ts +15 -0
  33. package/packages/app-core/src/components/local-inference/ProvidersList.d.ts.map +1 -0
  34. package/packages/app-core/src/components/local-inference/ProvidersList.js +62 -0
  35. package/packages/app-core/src/components/local-inference/RoutingMatrix.d.ts +13 -0
  36. package/packages/app-core/src/components/local-inference/RoutingMatrix.d.ts.map +1 -0
  37. package/packages/app-core/src/components/local-inference/RoutingMatrix.js +105 -0
  38. package/packages/app-core/src/runtime/ensure-local-inference-handler.d.ts.map +1 -1
  39. package/packages/app-core/src/runtime/ensure-local-inference-handler.js +13 -0
  40. package/packages/app-core/src/services/local-inference/handler-registry.d.ts +42 -0
  41. package/packages/app-core/src/services/local-inference/handler-registry.d.ts.map +1 -0
  42. package/packages/app-core/src/services/local-inference/handler-registry.js +127 -0
  43. package/packages/app-core/src/services/local-inference/providers.d.ts +61 -0
  44. package/packages/app-core/src/services/local-inference/providers.d.ts.map +1 -0
  45. package/packages/app-core/src/services/local-inference/providers.js +231 -0
  46. package/packages/app-core/src/services/local-inference/router-handler.d.ts +48 -0
  47. package/packages/app-core/src/services/local-inference/router-handler.d.ts.map +1 -0
  48. package/packages/app-core/src/services/local-inference/router-handler.js +130 -0
  49. package/packages/app-core/src/services/local-inference/routing-policy.d.ts +55 -0
  50. package/packages/app-core/src/services/local-inference/routing-policy.d.ts.map +1 -0
  51. package/packages/app-core/src/services/local-inference/routing-policy.js +187 -0
  52. package/packages/app-core/src/services/local-inference/routing-preferences.d.ts +29 -0
  53. package/packages/app-core/src/services/local-inference/routing-preferences.d.ts.map +1 -0
  54. package/packages/app-core/src/services/local-inference/routing-preferences.js +71 -0
  55. package/packages/typescript/src/services/message.d.ts +2 -1
  56. package/packages/typescript/src/services/message.d.ts.map +1 -1
  57. package/packages/typescript/src/services/message.js +105 -22
@@ -1 +1 @@
1
- {"version":3,"file":"block-rule-service.d.ts","sourceRoot":"","sources":["../../../../../../../../apps/app-lifeops/src/website-blocker/chat-integration/block-rule-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,aAAa,EAGd,MAAM,eAAe,CAAC;AAIvB,OAAO,EAEL,KAAK,SAAS,EAEd,KAAK,oBAAoB,EAE1B,MAAM,wBAAwB,CAAC;AAuHhC,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,aAAa;IAE7C,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC;IA8D7D,gBAAgB,CACpB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAC/C,OAAO,CAAC,IAAI,CAAC;IA4CV,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAarE;AAED,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,aAAa;IAE7C,gBAAgB,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAYxC,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAa3D,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAahD,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;CAa9D"}
1
+ {"version":3,"file":"block-rule-service.d.ts","sourceRoot":"","sources":["../../../../../../../../apps/app-lifeops/src/website-blocker/chat-integration/block-rule-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,aAAa,EAGd,MAAM,eAAe,CAAC;AAIvB,OAAO,EAEL,KAAK,SAAS,EAEd,KAAK,oBAAoB,EAE1B,MAAM,wBAAwB,CAAC;AAsKhC,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,aAAa;IAE7C,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC;IA+D7D,gBAAgB,CACpB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAC/C,OAAO,CAAC,IAAI,CAAC;IA4CV,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAarE;AAED,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,aAAa;IAE7C,gBAAgB,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAYxC,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAa3D,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAahD,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;CAa9D"}
@@ -1,5 +1,5 @@
1
1
  import crypto from "node:crypto";
2
- import { createUniqueUuid, logger, stringToUuid } from "@elizaos/core";
2
+ import { ChannelType, createUniqueUuid, logger, stringToUuid } from "@elizaos/core";
3
3
  import { executeRawSql, sqlQuote, sqlText } from "../../lifeops/sql.js";
4
4
  import { blockWebsitesAction } from "../../actions/website-blocker.js";
5
5
  import { BLOCK_RULES_TABLE, rowToBlockRule, } from "./block-rule-schema.js";
@@ -58,18 +58,58 @@ function assertCreateInput(input) {
58
58
  }
59
59
  }
60
60
  function makeSyntheticMessage(runtime, websites) {
61
+ const worldId = stringToUuid(`block-rule-service-world-${String(runtime.agentId)}`);
61
62
  const roomId = stringToUuid(`block-rule-service-${String(runtime.agentId)}`);
62
- const entityId = stringToUuid(`block-rule-service-entity-${String(runtime.agentId)}`);
63
63
  return {
64
64
  id: createUniqueUuid(runtime, `block-rule-${Date.now()}`),
65
- entityId,
65
+ entityId: runtime.agentId,
66
66
  agentId: runtime.agentId,
67
67
  roomId,
68
+ worldId,
68
69
  content: {
69
70
  text: `Block ${websites.join(", ")}.`,
71
+ source: "agent",
70
72
  },
71
73
  };
72
74
  }
75
+ async function ensureSyntheticMessageContext(runtime, message) {
76
+ const worldId = message.worldId ?? stringToUuid(`block-rule-service-world-${String(runtime.agentId)}`);
77
+ const roomId = message.roomId;
78
+ const worldMetadata = {
79
+ ownerId: runtime.agentId,
80
+ adminIds: [runtime.agentId],
81
+ roles: {
82
+ [runtime.agentId]: "OWNER",
83
+ },
84
+ };
85
+ if (typeof runtime.ensureWorldExists === "function") {
86
+ await runtime.ensureWorldExists({
87
+ id: worldId,
88
+ name: "Block Rule Service",
89
+ agentId: runtime.agentId,
90
+ messageServerId: runtime.agentId,
91
+ metadata: worldMetadata,
92
+ });
93
+ }
94
+ if (typeof runtime.ensureConnection === "function") {
95
+ await runtime.ensureConnection({
96
+ entityId: runtime.agentId,
97
+ roomId,
98
+ worldId,
99
+ worldName: "Block Rule Service",
100
+ userName: "Block Rule Service",
101
+ name: "Block Rule Service",
102
+ source: "agent",
103
+ channelId: String(roomId),
104
+ type: ChannelType.DM,
105
+ messageServerId: runtime.agentId,
106
+ metadata: worldMetadata,
107
+ });
108
+ }
109
+ if (typeof runtime.ensureParticipantInRoom === "function") {
110
+ await runtime.ensureParticipantInRoom(runtime.agentId, roomId);
111
+ }
112
+ }
73
113
  function computeHandlerOptionsForCreate(input) {
74
114
  const durationMinutes = (() => {
75
115
  if (input.gateType === "fixed_duration") {
@@ -121,6 +161,7 @@ export class BlockRuleWriter {
121
161
  NULL
122
162
  )`);
123
163
  const message = makeSyntheticMessage(this.runtime, input.websites);
164
+ await ensureSyntheticMessageContext(this.runtime, message);
124
165
  const handlerOptions = computeHandlerOptionsForCreate(input);
125
166
  const result = await blockWebsitesAction.handler(this.runtime, message, undefined, handlerOptions);
126
167
  if (result && typeof result === "object" && "success" in result) {
@@ -45,7 +45,7 @@ export async function runBootstrapFewshot(input) {
45
45
  const lineage = [];
46
46
  const baselineScore = await input.scorer(input.baselinePrompt, input.dataset);
47
47
  lineage.push({ round: 0, variant: 0, score: baselineScore, notes: "baseline" });
48
- const ranked = await rankExamples(input, baselineScore);
48
+ const ranked = await rankExamples(input);
49
49
  const fewShot = ranked.slice(0, Math.min(k, ranked.length));
50
50
  const optimizedPrompt = withDemonstrations(input.baselinePrompt, fewShot);
51
51
  const optimizedScore = await input.scorer(optimizedPrompt, input.dataset);
@@ -63,7 +63,7 @@ export async function runBootstrapFewshot(input) {
63
63
  fewShotExamples: fewShot,
64
64
  };
65
65
  }
66
- async function rankExamples(input, baselineScore) {
66
+ async function rankExamples(input) {
67
67
  if (input.options?.rankByScorer) {
68
68
  const scored = [];
69
69
  for (const example of input.dataset) {
@@ -75,7 +75,6 @@ async function rankExamples(input, baselineScore) {
75
75
  // reward when the scorer is uninformative.
76
76
  scored.sort((a, b) => b.score - a.score ||
77
77
  (b.example.reward ?? 0) - (a.example.reward ?? 0));
78
- void baselineScore;
79
78
  return scored.map((entry) => entry.example);
80
79
  }
81
80
  // Reward-first ranking. Examples without a recorded reward fall through
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elizaos/app-core",
3
- "version": "2.0.0-alpha.197",
3
+ "version": "2.0.0-alpha.201",
4
4
  "description": "Shared application core for elizaOS white-label agent apps.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -477,7 +477,7 @@
477
477
  "@capacitor/keyboard": "8.0.3",
478
478
  "@capacitor/preferences": "^8.0.1",
479
479
  "@clack/prompts": "^1.0.0",
480
- "@elizaos/agent": "^2.0.0-alpha.197",
480
+ "@elizaos/agent": "^2.0.0-alpha.201",
481
481
  "@elizaos/app-companion": "^0.0.0",
482
482
  "@elizaos/app-elizamaker": "^0.0.0",
483
483
  "@elizaos/app-lifeops": "^0.0.0",
@@ -486,9 +486,9 @@
486
486
  "@elizaos/app-task-coordinator": "^0.0.0",
487
487
  "@elizaos/app-training": "^0.0.1",
488
488
  "@elizaos/app-vincent": "^0.0.0",
489
- "@elizaos/core": "^2.0.0-alpha.197",
490
- "@elizaos/shared": "^2.0.0-alpha.197",
491
- "@elizaos/ui": "^2.0.0-alpha.197",
489
+ "@elizaos/core": "^2.0.0-alpha.201",
490
+ "@elizaos/shared": "^2.0.0-alpha.201",
491
+ "@elizaos/ui": "^2.0.0-alpha.201",
492
492
  "@radix-ui/react-checkbox": "^1.3.3",
493
493
  "@radix-ui/react-dialog": "^1.1.15",
494
494
  "@radix-ui/react-dropdown-menu": "^2.1.16",
@@ -25,9 +25,9 @@ export interface TrajectoryListItem {
25
25
  startTime: number;
26
26
  endTime: number | null;
27
27
  durationMs: number | null;
28
- stepCount?: number;
28
+ stepCount: number;
29
29
  llmCallCount: number;
30
- providerAccessCount?: number;
30
+ providerAccessCount: number;
31
31
  totalPromptTokens: number;
32
32
  totalCompletionTokens: number;
33
33
  scenarioId?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"trajectory.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/types/trajectory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"trajectory.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/types/trajectory.ts"],"names":[],"mappings":"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"}
@@ -5,9 +5,12 @@
5
5
  * raw `fetch` from UI code.
6
6
  */
7
7
  import type { DeviceBridgeStatus } from "../services/local-inference/device-bridge";
8
+ import type { PublicRegistration } from "../services/local-inference/handler-registry";
9
+ import type { ProviderStatus } from "../services/local-inference/providers";
10
+ import type { RoutingPolicy, RoutingPreferences } from "../services/local-inference/routing-preferences";
8
11
  import type { ActiveModelState, AgentModelSlot, CatalogModel, DownloadJob, HardwareProbe, InstalledModel, ModelAssignments, ModelBucket, ModelHubSnapshot } from "../services/local-inference/types";
9
12
  import type { VerifyResult } from "../services/local-inference/verify";
10
- export type { ActiveModelState, AgentModelSlot, CatalogModel, DeviceBridgeStatus, DownloadJob, HardwareProbe, InstalledModel, ModelAssignments, ModelBucket, ModelHubSnapshot, VerifyResult, };
13
+ export type { ActiveModelState, AgentModelSlot, CatalogModel, DeviceBridgeStatus, DownloadJob, HardwareProbe, InstalledModel, ModelAssignments, ModelBucket, ModelHubSnapshot, ProviderStatus, PublicRegistration, RoutingPolicy, RoutingPreferences, VerifyResult, };
11
14
  declare module "./client-base" {
12
15
  interface ElizaClient {
13
16
  getLocalInferenceHub(): Promise<ModelHubSnapshot>;
@@ -41,6 +44,19 @@ declare module "./client-base" {
41
44
  assignments: ModelAssignments;
42
45
  }>;
43
46
  verifyLocalInferenceModel(id: string): Promise<VerifyResult>;
47
+ getLocalInferenceRouting(): Promise<{
48
+ registrations: PublicRegistration[];
49
+ preferences: RoutingPreferences;
50
+ }>;
51
+ setLocalInferencePreferredProvider(slot: AgentModelSlot, provider: string | null): Promise<{
52
+ preferences: RoutingPreferences;
53
+ }>;
54
+ setLocalInferencePolicy(slot: AgentModelSlot, policy: RoutingPolicy | null): Promise<{
55
+ preferences: RoutingPreferences;
56
+ }>;
57
+ getLocalInferenceProviders(): Promise<{
58
+ providers: ProviderStatus[];
59
+ }>;
44
60
  }
45
61
  }
46
62
  //# sourceMappingURL=client-local-inference.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client-local-inference.d.ts","sourceRoot":"","sources":["../../../../../src/api/client-local-inference.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AACpF,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,WAAW,EACX,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EACjB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAGvE,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,YAAY,GACb,CAAC;AAEF,OAAO,QAAQ,eAAe,CAAC;IAC7B,UAAU,WAAW;QACnB,oBAAoB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAClD,yBAAyB,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;QACpD,wBAAwB,IAAI,OAAO,CAAC;YAAE,MAAM,EAAE,YAAY,EAAE,CAAA;SAAE,CAAC,CAAC;QAChE,0BAA0B,IAAI,OAAO,CAAC;YAAE,MAAM,EAAE,cAAc,EAAE,CAAA;SAAE,CAAC,CAAC;QACpE,2BAA2B,CACzB,aAAa,EAAE,MAAM,GAAG,YAAY,GACnC,OAAO,CAAC;YAAE,GAAG,EAAE,WAAW,CAAA;SAAE,CAAC,CAAC;QACjC,qBAAqB,CACnB,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC;YAAE,MAAM,EAAE,YAAY,EAAE,CAAA;SAAE,CAAC,CAAC;QACvC,4BAA4B,CAC1B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;YAAE,SAAS,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;QACnC,uBAAuB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACrD,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACpE,yBAAyB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACvD,4BAA4B,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;YAAE,OAAO,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;QACxE,6BAA6B,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAAC;QAC7D,4BAA4B,IAAI,OAAO,CAAC;YACtC,WAAW,EAAE,gBAAgB,CAAC;SAC/B,CAAC,CAAC;QACH,2BAA2B,CACzB,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC;YAAE,WAAW,EAAE,gBAAgB,CAAA;SAAE,CAAC,CAAC;QAC9C,yBAAyB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;KAC9D;CACF"}
1
+ {"version":3,"file":"client-local-inference.d.ts","sourceRoot":"","sources":["../../../../../src/api/client-local-inference.ts"],"names":[],"mappings":"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"}
@@ -67,3 +67,21 @@ ElizaClient.prototype.setLocalInferenceAssignment = async function (slot, modelI
67
67
  ElizaClient.prototype.verifyLocalInferenceModel = async function (id) {
68
68
  return this.fetch(`/api/local-inference/installed/${encodeURIComponent(id)}/verify`, { method: "POST" });
69
69
  };
70
+ ElizaClient.prototype.getLocalInferenceRouting = async function () {
71
+ return this.fetch("/api/local-inference/routing");
72
+ };
73
+ ElizaClient.prototype.setLocalInferencePreferredProvider = async function (slot, provider) {
74
+ return this.fetch("/api/local-inference/routing/preferred", {
75
+ method: "POST",
76
+ body: JSON.stringify({ slot, provider }),
77
+ });
78
+ };
79
+ ElizaClient.prototype.setLocalInferencePolicy = async function (slot, policy) {
80
+ return this.fetch("/api/local-inference/routing/policy", {
81
+ method: "POST",
82
+ body: JSON.stringify({ slot, policy }),
83
+ });
84
+ };
85
+ ElizaClient.prototype.getLocalInferenceProviders = async function () {
86
+ return this.fetch("/api/local-inference/providers");
87
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"local-inference-compat-routes.d.ts","sourceRoot":"","sources":["../../../../../src/api/local-inference-compat-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAelC,OAAO,EACL,KAAK,kBAAkB,EAExB,MAAM,uBAAuB,CAAC;AAqD/B,wBAAsB,gCAAgC,CACpD,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,OAAO,CAAC,CA2XlB"}
1
+ {"version":3,"file":"local-inference-compat-routes.d.ts","sourceRoot":"","sources":["../../../../../src/api/local-inference-compat-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AA0BlC,OAAO,EACL,KAAK,kBAAkB,EAExB,MAAM,uBAAuB,CAAC;AAqD/B,wBAAsB,gCAAgC,CACpD,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,OAAO,CAAC,CAqflB"}
@@ -11,6 +11,9 @@
11
11
  * `isStreamAuthorized`.
12
12
  */
13
13
  import { deviceBridge } from "../services/local-inference/device-bridge";
14
+ import { handlerRegistry, toPublicRegistration, } from "../services/local-inference/handler-registry";
15
+ import { snapshotProviders } from "../services/local-inference/providers";
16
+ import { readRoutingPreferences, setPolicy, setPreferredProvider, } from "../services/local-inference/routing-preferences";
14
17
  import { localInferenceService } from "../services/local-inference/service";
15
18
  import { AGENT_MODEL_SLOTS } from "../services/local-inference/types";
16
19
  import { ensureCompatApiAuthorized, ensureCompatSensitiveRouteAuthorized, getCompatApiToken, getProvidedApiToken, tokenMatches, } from "./auth";
@@ -176,6 +179,102 @@ export async function handleLocalInferenceCompatRoutes(req, res, state) {
176
179
  }
177
180
  return true;
178
181
  }
182
+ // ── GET: provider snapshot (enable state + supported slots) ────────
183
+ if (method === "GET" && pathname === "/api/local-inference/providers") {
184
+ if (!ensureCompatApiAuthorized(req, res))
185
+ return true;
186
+ try {
187
+ const providers = await snapshotProviders();
188
+ sendJsonResponse(res, 200, { providers });
189
+ }
190
+ catch (err) {
191
+ sendJsonErrorResponse(res, 500, err instanceof Error ? err.message : "Failed to snapshot providers");
192
+ }
193
+ return true;
194
+ }
195
+ // ── GET: registered model handlers across all providers ────────────
196
+ if (method === "GET" && pathname === "/api/local-inference/routing") {
197
+ if (!ensureCompatApiAuthorized(req, res))
198
+ return true;
199
+ try {
200
+ const prefs = await readRoutingPreferences();
201
+ const registrations = handlerRegistry.getAll().map(toPublicRegistration);
202
+ sendJsonResponse(res, 200, { registrations, preferences: prefs });
203
+ }
204
+ catch (err) {
205
+ sendJsonErrorResponse(res, 500, err instanceof Error ? err.message : "Failed to read routing state");
206
+ }
207
+ return true;
208
+ }
209
+ // ── POST: set preferred provider for a slot (manual override) ──────
210
+ if (method === "POST" &&
211
+ pathname === "/api/local-inference/routing/preferred") {
212
+ if (!ensureCompatSensitiveRouteAuthorized(req, res))
213
+ return true;
214
+ const body = await readCompatJsonBody(req, res);
215
+ if (!body)
216
+ return true;
217
+ const slot = stringBody(body, "slot");
218
+ if (!slot || !AGENT_MODEL_SLOTS.includes(slot)) {
219
+ sendJsonErrorResponse(res, 400, "slot is required and must be a valid AgentModelSlot");
220
+ return true;
221
+ }
222
+ const raw = body.provider;
223
+ const provider = raw === null
224
+ ? null
225
+ : typeof raw === "string" && raw.trim().length > 0
226
+ ? raw.trim()
227
+ : null;
228
+ try {
229
+ const prefs = await setPreferredProvider(slot, provider);
230
+ sendJsonResponse(res, 200, { preferences: prefs });
231
+ }
232
+ catch (err) {
233
+ sendJsonErrorResponse(res, 500, err instanceof Error
234
+ ? err.message
235
+ : "Failed to write preferred provider");
236
+ }
237
+ return true;
238
+ }
239
+ // ── POST: set routing policy for a slot ─────────────────────────────
240
+ if (method === "POST" && pathname === "/api/local-inference/routing/policy") {
241
+ if (!ensureCompatSensitiveRouteAuthorized(req, res))
242
+ return true;
243
+ const body = await readCompatJsonBody(req, res);
244
+ if (!body)
245
+ return true;
246
+ const slot = stringBody(body, "slot");
247
+ if (!slot || !AGENT_MODEL_SLOTS.includes(slot)) {
248
+ sendJsonErrorResponse(res, 400, "slot is required and must be a valid AgentModelSlot");
249
+ return true;
250
+ }
251
+ const validPolicies = [
252
+ "manual",
253
+ "cheapest",
254
+ "fastest",
255
+ "prefer-local",
256
+ "round-robin",
257
+ ];
258
+ const raw = body.policy;
259
+ const policy = raw === null
260
+ ? null
261
+ : typeof raw === "string" &&
262
+ validPolicies.includes(raw)
263
+ ? raw
264
+ : null;
265
+ if (raw !== null && policy === null) {
266
+ sendJsonErrorResponse(res, 400, `policy must be one of ${validPolicies.join(", ")} or null`);
267
+ return true;
268
+ }
269
+ try {
270
+ const prefs = await setPolicy(slot, policy);
271
+ sendJsonResponse(res, 200, { preferences: prefs });
272
+ }
273
+ catch (err) {
274
+ sendJsonErrorResponse(res, 500, err instanceof Error ? err.message : "Failed to write routing policy");
275
+ }
276
+ return true;
277
+ }
179
278
  // ── GET: model-type assignments ─────────────────────────────────────
180
279
  if (method === "GET" && pathname === "/api/local-inference/assignments") {
181
280
  if (!ensureCompatApiAuthorized(req, res))
@@ -1 +1 @@
1
- {"version":3,"file":"agent-orchestrator.d.ts","sourceRoot":"","sources":["../../../../../../../../src/components/chat/widgets/plugins/agent-orchestrator.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,2BAA2B,EAE5B,MAAM,UAAU,CAAC;AA8VlB,eAAO,MAAM,iCAAiC,EAAE,2BAA2B,EAuBxE,CAAC"}
1
+ {"version":3,"file":"agent-orchestrator.d.ts","sourceRoot":"","sources":["../../../../../../../../src/components/chat/widgets/plugins/agent-orchestrator.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EACV,2BAA2B,EAE5B,MAAM,UAAU,CAAC;AAqWlB,eAAO,MAAM,iCAAiC,EAAE,2BAA2B,EAuBxE,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { CodingAgentTasksPanel as AppCodingAgentTasksPanel } from "@elizaos/app-task-coordinator";
3
3
  import { Badge, Button } from "@elizaos/ui";
4
- import { Activity } from "lucide-react";
4
+ import { Activity, AlertTriangle, Eye, EyeOff, Play, SquareArrowOutUpRight, Trash2, } from "lucide-react";
5
5
  import { startTransition, useEffect, useMemo, useState } from "react";
6
6
  import { client } from "../../../../api";
7
7
  import { useApp } from "../../../../state";
@@ -53,12 +53,13 @@ function getClientErrorMessage(error, fallback) {
53
53
  return error instanceof Error ? error.message : fallback;
54
54
  }
55
55
  function AppRunCard({ run, attentionReasons, }) {
56
- const healthTone = run.health.state === "healthy"
57
- ? "bg-ok/20 text-ok"
56
+ const healthDot = run.health.state === "healthy"
57
+ ? "bg-ok"
58
58
  : run.health.state === "degraded"
59
- ? "bg-warn/20 text-warn"
60
- : "bg-danger/20 text-danger";
61
- return (_jsxs("div", { className: "rounded-lg border border-border/50 bg-bg-accent/30 p-3", children: [_jsx("div", { className: "flex items-start gap-2", children: _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-xs font-semibold text-txt", children: run.displayName }), _jsxs("div", { className: "mt-1 flex flex-wrap items-center gap-1.5 text-2xs text-muted", children: [_jsx(Badge, { variant: "secondary", className: `px-1.5 py-0 ${healthTone}`, children: run.health.state }), _jsx("span", { children: run.status }), _jsx("span", { children: run.viewerAttachment }), _jsx("span", { children: formatIsoTime(run.lastHeartbeatAt ?? run.updatedAt) })] })] }) }), _jsx("div", { className: "mt-2 line-clamp-2 text-xs-tight text-muted", children: run.summary || run.health.message || "Run active." }), attentionReasons.length > 0 ? (_jsxs("div", { className: "mt-2 flex flex-wrap gap-1.5", children: [_jsx(Badge, { variant: "secondary", className: "bg-warn/15 px-1.5 py-0 text-3xs text-warn", children: "Needs attention" }), _jsx("span", { className: "inline-flex max-w-full items-center rounded-full border border-border/30 bg-bg-hover/70 px-2 py-0.5 text-2xs text-muted-strong", children: _jsx("span", { className: "truncate", children: attentionReasons[0] }) })] })) : null] }));
59
+ ? "bg-warn"
60
+ : "bg-danger";
61
+ const ViewerIcon = run.viewerAttachment === "attached" ? Eye : EyeOff;
62
+ return (_jsxs("div", { className: "rounded-lg border border-border/50 bg-bg-accent/30 p-2", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-2xs font-semibold text-txt", children: run.displayName }), _jsxs("div", { className: "mt-1 flex flex-wrap items-center gap-1.5 text-3xs text-muted", children: [_jsx("span", { className: `inline-block h-1.5 w-1.5 rounded-full ${healthDot}`, "aria-label": run.health.state, title: run.health.state }), _jsx(ViewerIcon, { className: "h-3 w-3", "aria-label": run.viewerAttachment }), _jsx("span", { children: formatIsoTime(run.lastHeartbeatAt ?? run.updatedAt) })] })] }), _jsx("div", { className: "mt-1 line-clamp-2 text-3xs text-muted", children: run.summary || run.health.message || "Run active." }), attentionReasons.length > 0 ? (_jsxs("div", { className: "mt-1.5 flex items-center gap-1.5 text-3xs text-warn", children: [_jsx(AlertTriangle, { className: "h-3 w-3 shrink-0", "aria-label": "Needs attention" }), _jsx("span", { className: "truncate", children: attentionReasons[0] })] })) : null] }));
62
63
  }
63
64
  function AppRunsWidget(_props) {
64
65
  const app = useApp();
@@ -114,18 +115,16 @@ function AppRunsWidget(_props) {
114
115
  if (shouldHideWidget) {
115
116
  return null;
116
117
  }
117
- return (_jsxs(WidgetSection, { title: t("appsview.Running", { defaultValue: "Apps" }), icon: _jsx(Activity, { className: "h-4 w-4" }), action: _jsxs("div", { className: "flex items-center gap-1.5", children: [currentRun ? (_jsx(Button, { variant: "ghost", size: "sm", className: "h-6 px-2 text-2xs", onClick: () => {
118
+ return (_jsxs(WidgetSection, { title: t("appsview.Running", { defaultValue: "Apps" }), icon: _jsx(Activity, { className: "h-4 w-4" }), action: _jsxs("div", { className: "flex items-center gap-1", children: [currentRun ? (_jsx(Button, { variant: "ghost", size: "sm", className: "h-6 w-6 p-0", "aria-label": "Resume viewer", onClick: () => {
118
119
  setState("appRuns", runs);
119
120
  setState("activeGameRunId", currentRun.runId);
120
121
  setState("tab", "apps");
121
122
  setState("appsSubTab", "games");
122
- }, children: "Resume Viewer" })) : null, _jsx(Button, { variant: "ghost", size: "sm", className: "h-6 px-2 text-2xs", onClick: () => {
123
+ }, children: _jsx(Play, { className: "h-3.5 w-3.5" }) })) : null, _jsx(Button, { variant: "ghost", size: "sm", className: "h-6 w-6 p-0", "aria-label": "Open apps", onClick: () => {
123
124
  setState("appRuns", runs);
124
125
  setState("tab", "apps");
125
126
  setState("appsSubTab", "running");
126
- }, children: "Open Apps" })] }), testId: "chat-widget-app-runs", children: [error ? (_jsx("div", { className: "mb-2 rounded-md border border-danger/30 bg-danger/10 px-2 py-1.5 text-xs-tight text-danger", children: error })) : null, runs.length === 0 ? (loading ? (_jsx("div", { className: "text-xs-tight text-muted", children: "Loading app runs..." })) : (_jsx(EmptyWidgetState, { icon: _jsx(Activity, { className: "h-8 w-8" }), title: "No games are running" }))) : (_jsxs("div", { className: "flex flex-col gap-2.5", children: [_jsxs("div", { className: "flex flex-wrap gap-2 text-2xs text-muted", children: [_jsxs(Badge, { variant: "secondary", className: "bg-bg-hover/70 text-muted", children: ["Currently playing: ", attachedCount] }), _jsxs(Badge, { variant: "secondary", className: "bg-bg-hover/70 text-muted", children: ["Background: ", backgroundCount] }), _jsxs(Badge, { variant: "secondary", className: needsAttentionCount > 0
127
- ? "bg-warn/15 text-warn"
128
- : "bg-ok/15 text-ok", children: ["Needs attention: ", needsAttentionCount] })] }), attentionRuns.length > 0 ? (_jsxs("div", { className: "rounded-lg border border-warn/30 bg-warn/10 p-2.5", children: [_jsx("div", { className: "mb-2 text-2xs font-semibold uppercase tracking-[0.08em] text-warn", children: "Recovery queue" }), _jsx("div", { className: "flex flex-col gap-2", children: attentionRuns.slice(0, 3).map((run) => {
127
+ }, children: _jsx(SquareArrowOutUpRight, { className: "h-3.5 w-3.5" }) })] }), testId: "chat-widget-app-runs", children: [error ? (_jsx("div", { className: "mb-2 rounded-md border border-danger/30 bg-danger/10 px-2 py-1.5 text-xs-tight text-danger", children: error })) : null, runs.length === 0 ? (loading ? (_jsx("div", { className: "text-xs-tight text-muted", children: "Loading app runs..." })) : (_jsx(EmptyWidgetState, { icon: _jsx(Activity, { className: "h-8 w-8" }), title: "No games are running" }))) : (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-3 text-3xs text-muted", children: [_jsxs("span", { className: "inline-flex items-center gap-1", title: "Currently playing", children: [_jsx(Eye, { className: "h-3 w-3" }), attachedCount] }), _jsxs("span", { className: "inline-flex items-center gap-1", title: "Background", children: [_jsx(EyeOff, { className: "h-3 w-3" }), backgroundCount] }), _jsxs("span", { className: `inline-flex items-center gap-1 ${needsAttentionCount > 0 ? "text-warn" : "text-ok"}`, title: "Needs attention", children: [_jsx(AlertTriangle, { className: "h-3 w-3" }), needsAttentionCount] })] }), attentionRuns.length > 0 ? (_jsxs("div", { className: "rounded-lg border border-warn/30 bg-warn/10 p-2", children: [_jsxs("div", { className: "mb-1.5 flex items-center gap-1.5 text-3xs font-semibold uppercase tracking-[0.08em] text-warn", children: [_jsx(AlertTriangle, { className: "h-3 w-3" }), "Recovery"] }), _jsx("div", { className: "flex flex-col gap-2", children: attentionRuns.slice(0, 3).map((run) => {
129
128
  const reasons = attentionMap.get(run.runId) ?? [];
130
129
  return (_jsx(AppRunCard, { run: run, attentionReasons: reasons }, run.runId));
131
130
  }) })] })) : null, _jsx("div", { className: "flex flex-col gap-2", children: runs.slice(0, 4).map((run) => (_jsx(AppRunCard, { run: run, attentionReasons: attentionMap.get(run.runId) ?? [] }, run.runId))) })] }))] }));
@@ -139,7 +138,7 @@ function OrchestratorActivityWidget({ events, clearEvents, }) {
139
138
  if (events.length === 0) {
140
139
  return null;
141
140
  }
142
- return (_jsx(WidgetSection, { title: t("taskseventspanel.Activity", { defaultValue: "Activity" }), icon: _jsx(Activity, { className: "h-4 w-4" }), action: _jsx(Button, { variant: "ghost", size: "sm", onClick: clearEvents, className: "h-6 px-2 text-xs text-muted", children: "Clear" }), testId: "chat-widget-events", children: _jsx(ActivityItemsContent, { events: events }) }));
141
+ return (_jsx(WidgetSection, { title: t("taskseventspanel.Activity", { defaultValue: "Activity" }), icon: _jsx(Activity, { className: "h-4 w-4" }), action: _jsx(Button, { variant: "ghost", size: "sm", onClick: clearEvents, "aria-label": "Clear activity", className: "h-6 w-6 p-0 text-muted", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }), testId: "chat-widget-events", children: _jsx(ActivityItemsContent, { events: events }) }));
143
142
  }
144
143
  export const AGENT_ORCHESTRATOR_PLUGIN_WIDGETS = [
145
144
  {
@@ -1 +1 @@
1
- {"version":3,"file":"LocalInferencePanel.d.ts","sourceRoot":"","sources":["../../../../../../src/components/local-inference/LocalInferencePanel.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,YAAY,EAEZ,aAAa,EACb,cAAc,EAEf,MAAM,kCAAkC,CAAC;AAsB1C,wBAAgB,mBAAmB,4CA4XlC;AAqFD;;GAEG;AACH,eAAe,mBAAmB,CAAC;AAGnC,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"LocalInferencePanel.d.ts","sourceRoot":"","sources":["../../../../../../src/components/local-inference/LocalInferencePanel.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,YAAY,EAEZ,aAAa,EACb,cAAc,EAEf,MAAM,kCAAkC,CAAC;AAwB1C,wBAAgB,mBAAmB,4CA8XlC;AAqFD;;GAEG;AACH,eAAe,mBAAmB,CAAC;AAGnC,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC"}
@@ -14,6 +14,8 @@ import { FirstRunOffer } from "./FirstRunOffer";
14
14
  import { HardwareBadge } from "./HardwareBadge";
15
15
  import { HuggingFaceSearch } from "./HuggingFaceSearch";
16
16
  import { ModelHubView } from "./ModelHubView";
17
+ import { ProvidersList } from "./ProvidersList";
18
+ import { RoutingMatrix } from "./RoutingMatrix";
17
19
  import { SlotAssignments } from "./SlotAssignments";
18
20
  export function LocalInferencePanel() {
19
21
  const { setActionNotice } = useApp();
@@ -208,7 +210,7 @@ export function LocalInferencePanel() {
208
210
  return (_jsx("button", { type: "button", onClick: () => setTab(id), className: `-mb-px border-b-2 px-1 pb-2 text-sm font-medium transition-colors ${active
209
211
  ? "border-accent text-txt"
210
212
  : "border-transparent text-muted hover:text-txt"}`, children: label }, id));
211
- }) }), tab === "curated" && (_jsx(ModelHubView, { catalog: catalog, installed: hub.installed, downloads: hub.downloads, active: hub.active, hardware: hub.hardware, onDownload: handleDownload, onCancel: handleCancel, onActivate: handleActivate, onUninstall: handleUninstall, onVerify: handleVerify, onRedownload: handleRedownload, busy: busy })), tab === "search" && !mobile && (_jsx(HuggingFaceSearch, { installed: hub.installed, downloads: hub.downloads, active: hub.active, hardware: hub.hardware, onDownload: handleDownloadSpec, onCancel: handleCancel, onActivate: handleActivate, onUninstall: handleUninstall, busy: busy })), tab === "search" && mobile && (_jsx("p", { className: "text-sm text-muted", children: "HuggingFace search is desktop-only for now \u2014 most results would be too large for a phone." })), tab === "downloads" && (_jsx(DownloadQueue, { downloads: hub.downloads, catalog: hub.catalog, onCancel: handleCancel })), _jsx(SlotAssignments, { installed: hub.installed, assignments: hub.assignments, onChange: handleAssignmentsChange }), _jsx(DevicesPanel, {}), _jsx(ExternalInstalledSummary, { installed: hub.installed, onActivate: handleActivate, onUninstall: handleUninstall, active: hub.active, busy: busy })] }));
213
+ }) }), tab === "curated" && (_jsx(ModelHubView, { catalog: catalog, installed: hub.installed, downloads: hub.downloads, active: hub.active, hardware: hub.hardware, onDownload: handleDownload, onCancel: handleCancel, onActivate: handleActivate, onUninstall: handleUninstall, onVerify: handleVerify, onRedownload: handleRedownload, busy: busy })), tab === "search" && !mobile && (_jsx(HuggingFaceSearch, { installed: hub.installed, downloads: hub.downloads, active: hub.active, hardware: hub.hardware, onDownload: handleDownloadSpec, onCancel: handleCancel, onActivate: handleActivate, onUninstall: handleUninstall, busy: busy })), tab === "search" && mobile && (_jsx("p", { className: "text-sm text-muted", children: "HuggingFace search is desktop-only for now \u2014 most results would be too large for a phone." })), tab === "downloads" && (_jsx(DownloadQueue, { downloads: hub.downloads, catalog: hub.catalog, onCancel: handleCancel })), _jsx(ProvidersList, {}), _jsx(RoutingMatrix, {}), _jsx(SlotAssignments, { installed: hub.installed, assignments: hub.assignments, onChange: handleAssignmentsChange }), _jsx(DevicesPanel, {}), _jsx(ExternalInstalledSummary, { installed: hub.installed, onActivate: handleActivate, onUninstall: handleUninstall, active: hub.active, busy: busy })] }));
212
214
  }
213
215
  function ExternalInstalledSummary({ installed, onActivate, active, busy, }) {
214
216
  const external = installed.filter((m) => m.source === "external-scan");
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Single pane listing every provider Milady knows about, cloud + local.
3
+ * Each card shows:
4
+ * - current enable state (green/grey dot + short reason)
5
+ * - supported model slots
6
+ * - which slots it has registered handlers for right now
7
+ * - a "Configure" link back to wherever the actual enable happens
8
+ *
9
+ * The key insight: we don't centralise enable/disable here. Each provider
10
+ * points at the surface that controls it (ProviderSwitcher for cloud,
11
+ * download hub for local, etc). This turns the fragmented multi-provider
12
+ * enable story into a single observable list without forcing a migration.
13
+ */
14
+ export declare function ProvidersList(): import("react/jsx-runtime").JSX.Element;
15
+ //# sourceMappingURL=ProvidersList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProvidersList.d.ts","sourceRoot":"","sources":["../../../../../../src/components/local-inference/ProvidersList.tsx"],"names":[],"mappings":"AAWA;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,4CA8G5B"}
@@ -0,0 +1,62 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useState } from "react";
3
+ import { client } from "../../api";
4
+ const KIND_LABEL = {
5
+ "cloud-api": "Cloud API",
6
+ "cloud-subscription": "Subscription",
7
+ local: "Local",
8
+ "device-bridge": "Device bridge",
9
+ };
10
+ /**
11
+ * Single pane listing every provider Milady knows about, cloud + local.
12
+ * Each card shows:
13
+ * - current enable state (green/grey dot + short reason)
14
+ * - supported model slots
15
+ * - which slots it has registered handlers for right now
16
+ * - a "Configure" link back to wherever the actual enable happens
17
+ *
18
+ * The key insight: we don't centralise enable/disable here. Each provider
19
+ * points at the surface that controls it (ProviderSwitcher for cloud,
20
+ * download hub for local, etc). This turns the fragmented multi-provider
21
+ * enable story into a single observable list without forcing a migration.
22
+ */
23
+ export function ProvidersList() {
24
+ const [providers, setProviders] = useState(null);
25
+ const [error, setError] = useState(null);
26
+ const refresh = useCallback(async () => {
27
+ try {
28
+ const { providers: ps } = await client.getLocalInferenceProviders();
29
+ setProviders(ps);
30
+ setError(null);
31
+ }
32
+ catch (err) {
33
+ setError(err instanceof Error ? err.message : "Failed to load providers");
34
+ }
35
+ }, []);
36
+ useEffect(() => {
37
+ void refresh();
38
+ // Re-poll every 10s so provider state follows env-var / config-file
39
+ // changes without the user having to reload.
40
+ const interval = setInterval(() => void refresh(), 10_000);
41
+ return () => clearInterval(interval);
42
+ }, [refresh]);
43
+ if (error && !providers) {
44
+ return (_jsx("div", { className: "rounded-xl border border-rose-500/40 bg-rose-500/10 p-4 text-sm", children: error }));
45
+ }
46
+ if (!providers) {
47
+ return _jsx("p", { className: "text-sm text-muted-foreground", children: "Loading providers\u2026" });
48
+ }
49
+ return (_jsxs("section", { className: "flex flex-col gap-3", children: [_jsxs("header", { className: "flex flex-col gap-1", children: [_jsx("h3", { className: "text-sm font-semibold uppercase tracking-wide text-muted-foreground", children: "All providers" }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Every inference source Milady knows about \u2014 cloud subscription, cloud API, local llama.cpp, paired device, on-device Capacitor. Enable as many as you want." })] }), _jsx("div", { className: "grid grid-cols-1 gap-3 md:grid-cols-2", children: providers.map((p) => {
50
+ const dot = p.enableState.enabled
51
+ ? "bg-emerald-500"
52
+ : "bg-muted-foreground/40";
53
+ return (_jsxs("div", { className: "rounded-xl border border-border bg-card p-3 flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: `inline-flex h-2 w-2 rounded-full ${dot}`, "aria-hidden": true }), _jsx("span", { className: "font-medium truncate", children: p.label }), _jsx("span", { className: "ml-auto text-[10px] uppercase tracking-wide text-muted-foreground", children: KIND_LABEL[p.kind] })] }), _jsx("p", { className: "text-xs text-muted-foreground line-clamp-2", children: p.description }), _jsx("div", { className: "flex flex-wrap gap-1", children: p.supportedSlots.map((slot) => {
54
+ const active = p.registeredSlots.includes(slot);
55
+ return (_jsx("span", { className: `rounded-full border px-1.5 py-0.5 text-[10px] ${active
56
+ ? "border-primary/50 bg-primary/10 text-primary"
57
+ : "border-border text-muted-foreground"}`, title: active
58
+ ? "Handler currently registered"
59
+ : "Supported but not currently registered", children: slot }, slot));
60
+ }) }), _jsxs("div", { className: "flex items-center justify-between gap-2 text-xs", children: [_jsx("span", { className: "text-muted-foreground truncate", children: p.enableState.reason }), p.configureHref && (_jsx("a", { href: p.configureHref, className: "text-primary underline-offset-2 hover:underline", children: "Configure" }))] })] }, p.id));
61
+ }) })] }));
62
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Cross-provider routing matrix.
3
+ *
4
+ * Shows every `AgentModelSlot` as a row with:
5
+ * - a policy dropdown (manual / cheapest / fastest / prefer-local / round-robin)
6
+ * - a preferred-provider dropdown (only editable when policy === "manual")
7
+ * - a live view of which providers have a registered handler for that slot
8
+ *
9
+ * Both settings persist to `$STATE_DIR/local-inference/routing.json` and
10
+ * take effect on the next request via the router-handler.
11
+ */
12
+ export declare function RoutingMatrix(): import("react/jsx-runtime").JSX.Element;
13
+ //# sourceMappingURL=RoutingMatrix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RoutingMatrix.d.ts","sourceRoot":"","sources":["../../../../../../src/components/local-inference/RoutingMatrix.tsx"],"names":[],"mappings":"AAmDA;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,4CAuJ5B"}