summaryrefslogtreecommitdiffhomepage
path: root/packages/core/src/models
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-05-21 19:06:15 +0900
committerAdam Malczewski <[email protected]>2026-05-21 19:06:15 +0900
commit55633c90c0d96e62153a4b6655f3f833a3b46ad4 (patch)
treea75f97b48071eb1ba9e8366d8053a376dde69af5 /packages/core/src/models
parentd6b208342edf97bafa5b1dcc986b782f9879d141 (diff)
downloaddispatch-55633c90c0d96e62153a4b6655f3f833a3b46ad4.tar.gz
dispatch-55633c90c0d96e62153a4b6655f3f833a3b46ad4.zip
refactor: gut model/tag/fallback/agent-template system, fix Docker setup
- Remove ModelResolver, model definitions, model tags, fallback order, agent templates - Remove all [[models]], [agents], and fallback from dispatch.toml and config schema - ModelRegistry is now a pure key-state manager - dispatch.toml reduced to keys + permissions only - Docker: fix entrypoint for existing UID, skip bun install in frontend container - Docker: scoped build cache prune in bin/clean
Diffstat (limited to 'packages/core/src/models')
-rw-r--r--packages/core/src/models/index.ts1
-rw-r--r--packages/core/src/models/registry.ts64
-rw-r--r--packages/core/src/models/resolver.ts88
3 files changed, 10 insertions, 143 deletions
diff --git a/packages/core/src/models/index.ts b/packages/core/src/models/index.ts
index e5efcc8..cf59749 100644
--- a/packages/core/src/models/index.ts
+++ b/packages/core/src/models/index.ts
@@ -1,2 +1 @@
export { ModelRegistry } from "./registry.js";
-export { ModelResolver } from "./resolver.js";
diff --git a/packages/core/src/models/registry.ts b/packages/core/src/models/registry.ts
index f78fe0e..9ea0b32 100644
--- a/packages/core/src/models/registry.ts
+++ b/packages/core/src/models/registry.ts
@@ -1,25 +1,20 @@
-import type { KeyDefinition, KeyState, ModelDefinition } from "../types/index.js";
+import type { KeyDefinition, KeyState } from "../types/index.js";
export class ModelRegistry {
- private models: ModelDefinition[];
private keyStates: Map<string, KeyState>;
- private fallbackOrder: string[];
+ private keyOrder: string[];
- constructor(models: ModelDefinition[], keys: KeyDefinition[], fallbackOrder: string[]) {
- this.models = [];
+ constructor(keys: KeyDefinition[]) {
this.keyStates = new Map();
- this.fallbackOrder = [];
- this._initConfig(models, keys, fallbackOrder, new Map());
+ this.keyOrder = [];
+ this._initConfig(keys, new Map());
}
private _initConfig(
- models: ModelDefinition[],
keys: KeyDefinition[],
- fallbackOrder: string[],
existingStates: Map<string, KeyState>,
): void {
- this.models = [...models];
- this.fallbackOrder = this._buildFallbackOrder(keys, fallbackOrder);
+ this.keyOrder = keys.map((k) => k.id);
const newStates = new Map<string, KeyState>();
for (const key of keys) {
@@ -34,51 +29,12 @@ export class ModelRegistry {
this.keyStates = newStates;
}
- private _buildFallbackOrder(keys: KeyDefinition[], fallbackOrder: string[]): string[] {
- const ordered: string[] = [];
- const keyIds = new Set(keys.map((k) => k.id));
-
- // Add keys from fallbackOrder first (if they exist)
- for (const id of fallbackOrder) {
- if (keyIds.has(id) && !ordered.includes(id)) {
- ordered.push(id);
- }
- }
-
- // Append remaining keys not in fallbackOrder
- for (const key of keys) {
- if (!ordered.includes(key.id)) {
- ordered.push(key.id);
- }
- }
-
- return ordered;
- }
-
- getModels(): ModelDefinition[] {
- return [...this.models];
- }
-
getKeys(): KeyState[] {
- return this.fallbackOrder
+ return this.keyOrder
.map((id) => this.keyStates.get(id))
.filter((state): state is KeyState => state !== undefined);
}
- getModelsByTag(tag: string): ModelDefinition[] {
- return this.models.filter((m) => m.tags.includes(tag));
- }
-
- getAllTags(): string[] {
- const tags = new Set<string>();
- for (const model of this.models) {
- for (const tag of model.tags) {
- tags.add(tag);
- }
- }
- return [...tags];
- }
-
markKeyExhausted(keyId: string, error?: string): void {
const state = this.keyStates.get(keyId);
if (!state) return;
@@ -118,13 +74,13 @@ export class ModelRegistry {
return true;
}
- updateConfig(models: ModelDefinition[], keys: KeyDefinition[], fallbackOrder: string[]): void {
- this._initConfig(models, keys, fallbackOrder, this.keyStates);
+ updateConfig(keys: KeyDefinition[]): void {
+ this._initConfig(keys, this.keyStates);
}
// Internal: get ordered key states for a specific provider
getOrderedKeysForProvider(provider: string): KeyState[] {
- return this.fallbackOrder
+ return this.keyOrder
.map((id) => this.keyStates.get(id))
.filter(
(state): state is KeyState =>
diff --git a/packages/core/src/models/resolver.ts b/packages/core/src/models/resolver.ts
deleted file mode 100644
index 3ada713..0000000
--- a/packages/core/src/models/resolver.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import type { ResolvedModel } from "../types/index.js";
-import type { ModelRegistry } from "./registry.js";
-
-export class ModelResolver {
- private registry: ModelRegistry;
-
- constructor(registry: ModelRegistry) {
- this.registry = registry;
- }
-
- resolve(tag: string): ResolvedModel | null {
- const models = this.registry.getModelsByTag(tag);
- const keys = this.registry.getKeys();
-
- for (const keyState of keys) {
- if (keyState.status !== "active") continue;
- const model = models.find((m) => m.provider === keyState.definition.provider);
- if (model) {
- return { model, key: keyState.definition };
- }
- }
-
- return null;
- }
-
- async waitForKey(
- tag: string,
- options?: {
- pollIntervalMs?: number;
- signal?: AbortSignal;
- onWaiting?: () => void;
- onResume?: () => void;
- },
- ): Promise<ResolvedModel | null> {
- const pollIntervalMs = options?.pollIntervalMs ?? 60000;
- const signal = options?.signal;
-
- // Try immediately first
- const immediate = this.resolve(tag);
- if (immediate) return immediate;
-
- // Check if aborted before entering wait state
- if (signal?.aborted) return null;
-
- options?.onWaiting?.();
-
- return new Promise<ResolvedModel | null>((resolve) => {
- let timer: ReturnType<typeof setTimeout> | null = null;
-
- const cleanup = () => {
- if (timer !== null) {
- clearTimeout(timer);
- timer = null;
- }
- };
-
- const onAbort = () => {
- cleanup();
- resolve(null);
- };
-
- if (signal) {
- signal.addEventListener("abort", onAbort, { once: true });
- }
-
- const poll = () => {
- if (signal?.aborted) {
- resolve(null);
- return;
- }
-
- const result = this.resolve(tag);
- if (result) {
- if (signal) {
- signal.removeEventListener("abort", onAbort);
- }
- options?.onResume?.();
- resolve(result);
- return;
- }
-
- timer = setTimeout(poll, pollIntervalMs);
- };
-
- timer = setTimeout(poll, pollIntervalMs);
- });
- }
-}