@oeronteros-1/opencode-orchestra 0.5.3 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +63 -9
- package/GITHUB_RELEASE_1.0.0.md +84 -0
- package/README.md +95 -7
- package/dashboard-dist/assets/index-CN3CG5oG.js +124 -0
- package/dashboard-dist/assets/{index-89Gs8jun.css → index-j0b0ZK2D.css} +1 -1
- package/dashboard-dist/index.html +2 -2
- package/dist/agents/workers.d.ts +14 -1
- package/dist/agents/workers.js +10 -0
- package/dist/agents/workers.js.map +1 -1
- package/dist/cli.js +63 -3
- package/dist/cli.js.map +1 -1
- package/dist/config/schema.d.ts +23 -0
- package/dist/config/schema.js +18 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/dashboard/server.d.ts +11 -0
- package/dist/dashboard/server.js +152 -33
- package/dist/dashboard/server.js.map +1 -1
- package/dist/diagnostics/completion.d.ts +5 -0
- package/dist/diagnostics/completion.js +145 -0
- package/dist/diagnostics/completion.js.map +1 -0
- package/dist/diagnostics/doctor.d.ts +58 -0
- package/dist/diagnostics/doctor.js +354 -0
- package/dist/diagnostics/doctor.js.map +1 -0
- package/dist/diagnostics/update.d.ts +17 -0
- package/dist/diagnostics/update.js +89 -0
- package/dist/diagnostics/update.js.map +1 -0
- package/dist/index.js +141 -2
- package/dist/index.js.map +1 -1
- package/dist/plugin-status.d.ts +34 -0
- package/dist/plugin-status.js +90 -0
- package/dist/plugin-status.js.map +1 -0
- package/dist/routing/budget-guard.d.ts +36 -0
- package/dist/routing/budget-guard.js +52 -0
- package/dist/routing/budget-guard.js.map +1 -0
- package/dist/routing/classifier-cache.d.ts +25 -0
- package/dist/routing/classifier-cache.js +46 -0
- package/dist/routing/classifier-cache.js.map +1 -0
- package/dist/routing/fallback.d.ts +41 -0
- package/dist/routing/fallback.js +81 -0
- package/dist/routing/fallback.js.map +1 -0
- package/dist/routing/model-discovery.js +3 -1
- package/dist/routing/model-discovery.js.map +1 -1
- package/dist/routing/model-resolver.d.ts +11 -0
- package/dist/routing/model-resolver.js +27 -7
- package/dist/routing/model-resolver.js.map +1 -1
- package/dist/routing/observer.d.ts +22 -0
- package/dist/routing/observer.js +64 -0
- package/dist/routing/observer.js.map +1 -0
- package/dist/routing/planner.d.ts +24 -0
- package/dist/routing/planner.js +106 -0
- package/dist/routing/planner.js.map +1 -0
- package/dist/routing/pricing/estimate.d.ts +60 -0
- package/dist/routing/pricing/estimate.js +81 -0
- package/dist/routing/pricing/estimate.js.map +1 -0
- package/dist/routing/pricing/prices.d.ts +19 -0
- package/dist/routing/pricing/prices.js +74 -0
- package/dist/routing/pricing/prices.js.map +1 -0
- package/dist/routing/pricing/refresh.d.ts +30 -0
- package/dist/routing/pricing/refresh.js +105 -0
- package/dist/routing/pricing/refresh.js.map +1 -0
- package/dist/telemetry/analytics.d.ts +45 -0
- package/dist/telemetry/analytics.js +78 -0
- package/dist/telemetry/analytics.js.map +1 -0
- package/dist/telemetry/ledger.d.ts +13 -1
- package/dist/telemetry/ledger.js +29 -1
- package/dist/telemetry/ledger.js.map +1 -1
- package/dist/tools.d.ts +6 -1
- package/dist/tools.js +77 -7
- package/dist/tools.js.map +1 -1
- package/package.json +17 -4
- package/schema/opencode-orchestra.schema.json +15 -2
- package/dashboard-dist/assets/index-Bhe8OPZD.js +0 -124
|
@@ -39,13 +39,15 @@ function candidate(providerID, model) {
|
|
|
39
39
|
for (const capability of caps)
|
|
40
40
|
scores[capability] = model.reasoning && capability === "reasoning" ? 9 : 7;
|
|
41
41
|
return {
|
|
42
|
-
id:
|
|
42
|
+
id: providerID + "/" + model.id,
|
|
43
43
|
cost: paid ? "paid" : "free",
|
|
44
44
|
tier: model.reasoning ? ((model.limit?.context ?? 0) >= 200_000 ? "frontier" : "lead") : "worker",
|
|
45
45
|
priority,
|
|
46
46
|
capabilities: caps,
|
|
47
47
|
scores,
|
|
48
48
|
...(contextClass(model.limit?.context) ? { context: contextClass(model.limit?.context) } : {}),
|
|
49
|
+
...(model.cost?.input !== undefined ? { priceInput: model.cost.input } : {}),
|
|
50
|
+
...(model.cost?.output !== undefined ? { priceOutput: model.cost.output } : {}),
|
|
49
51
|
};
|
|
50
52
|
}
|
|
51
53
|
export async function discoverConnectedModels(client) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-discovery.js","sourceRoot":"","sources":["../../src/routing/model-discovery.ts"],"names":[],"mappings":"AA8BA,SAAS,YAAY,CAAC,MAA0B;IAC9C,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAA;IAC7B,IAAI,MAAM,IAAI,OAAO;QAAE,OAAO,QAAQ,CAAA;IACtC,IAAI,MAAM,IAAI,OAAO;QAAE,OAAO,OAAO,CAAA;IACrC,IAAI,MAAM,IAAI,MAAM;QAAE,OAAO,QAAQ,CAAA;IACrC,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,KAAmB;IACvC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAA;IACxC,IAAI,KAAK,CAAC,SAAS,KAAK,KAAK,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAClB,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACxB,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACpB,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACvB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACpB,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QACtB,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;IAC3B,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACvF,IAAI,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACnE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,IAAI,CAAC,CAAC,IAAI,OAAO;QAAE,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;IACvE,OAAO,CAAC,GAAG,MAAM,CAAC,CAAA;AACpB,CAAC;AAED,SAAS,SAAS,CAAC,UAAkB,EAAE,KAAmB;IACxD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;IACnF,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;IAChC,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,CAAC,CAAA;IAClE,MAAM,gBAAgB,GAAG,KAAK,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IACrH,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAA;IAC7F,MAAM,MAAM,GAA2B,EAAE,CAAA;IACzC,KAAK,MAAM,UAAU,IAAI,IAAI;QAAE,MAAM,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC,SAAS,IAAI,UAAU,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAEzG,OAAO;QACL,EAAE,EAAE,GAAG,
|
|
1
|
+
{"version":3,"file":"model-discovery.js","sourceRoot":"","sources":["../../src/routing/model-discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,10 @@ export interface ModelCandidate {
|
|
|
7
7
|
capabilities: CapabilityName[];
|
|
8
8
|
scores: Record<string, number>;
|
|
9
9
|
context?: "small" | "medium" | "large" | "xlarge";
|
|
10
|
+
/** Explicit USD price per 1M input tokens, when configured. */
|
|
11
|
+
priceInput?: number;
|
|
12
|
+
/** Explicit USD price per 1M output tokens, when configured. */
|
|
13
|
+
priceOutput?: number;
|
|
10
14
|
}
|
|
11
15
|
export interface ResolveModelRequest {
|
|
12
16
|
pool: ModelCandidateInput[];
|
|
@@ -20,7 +24,14 @@ export interface ResolvedModel {
|
|
|
20
24
|
id: string;
|
|
21
25
|
score: number;
|
|
22
26
|
cost: ModelCost;
|
|
27
|
+
priceInput?: number;
|
|
28
|
+
priceOutput?: number;
|
|
23
29
|
reason: string[];
|
|
30
|
+
/**
|
|
31
|
+
* Ordered failover alternatives (cheaper first). When the primary fails
|
|
32
|
+
* with a retryable error, step down this list instead of re-hitting it.
|
|
33
|
+
*/
|
|
34
|
+
fallback: string[];
|
|
24
35
|
}
|
|
25
36
|
export declare function normalizeCandidate(input: ModelCandidateInput): ModelCandidate;
|
|
26
37
|
export declare function resolveModel(request: ResolveModelRequest): ResolvedModel | undefined;
|
|
@@ -18,8 +18,19 @@ export function normalizeCandidate(input) {
|
|
|
18
18
|
capabilities: input.capabilities,
|
|
19
19
|
scores: input.scores,
|
|
20
20
|
...(input.context ? { context: input.context } : {}),
|
|
21
|
+
...(input.priceInput !== undefined ? { priceInput: input.priceInput } : {}),
|
|
22
|
+
...(input.priceOutput !== undefined ? { priceOutput: input.priceOutput } : {}),
|
|
21
23
|
};
|
|
22
24
|
}
|
|
25
|
+
const COST_ORDER = { paid: 2, subscription: 1, free: 0 };
|
|
26
|
+
function priceAdjustment(candidate) {
|
|
27
|
+
// A monetary price is a separate ranking signal from the coarse cost class:
|
|
28
|
+
// all else equal, cheaper models win. Log-scale so differences are gentle.
|
|
29
|
+
const price = (candidate.priceInput ?? 0) + (candidate.priceOutput ?? 0);
|
|
30
|
+
if (price <= 0)
|
|
31
|
+
return 0;
|
|
32
|
+
return -Math.round(Math.log10(1 + price) * 6);
|
|
33
|
+
}
|
|
23
34
|
export function resolveModel(request) {
|
|
24
35
|
const policy = getBudgetPolicy(request.budget);
|
|
25
36
|
const ranked = request.pool
|
|
@@ -40,15 +51,17 @@ export function resolveModel(request) {
|
|
|
40
51
|
const preferredTierIndex = request.preferredTiers?.indexOf(candidate.tier) ?? -1;
|
|
41
52
|
const preferredCostBonus = preferredCostIndex >= 0 ? Math.max(30, 100 - preferredCostIndex * 30) : 0;
|
|
42
53
|
const preferredTierBonus = preferredTierIndex >= 0 ? Math.max(30, 100 - preferredTierIndex * 30) : 0;
|
|
54
|
+
const priceAdj = priceAdjustment(candidate);
|
|
43
55
|
const score = candidate.priority + explicit * 8 + declared + contextBonus + frontierBonus
|
|
44
|
-
+ preferredCostBonus + preferredTierBonus + costAdjustment(candidate.cost, policy);
|
|
56
|
+
+ preferredCostBonus + preferredTierBonus + costAdjustment(candidate.cost, policy) + priceAdj;
|
|
45
57
|
const reason = [
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
...(frontierBonus ? [
|
|
50
|
-
...(preferredCostBonus ? [
|
|
51
|
-
...(preferredTierBonus ? [
|
|
58
|
+
"priority=" + candidate.priority,
|
|
59
|
+
"capability=" + (explicit || (declared ? "declared" : "unspecified")),
|
|
60
|
+
"cost=" + candidate.cost,
|
|
61
|
+
...(frontierBonus ? ["frontier=" + frontierBonus] : []),
|
|
62
|
+
...(preferredCostBonus ? ["preferred-cost=" + preferredCostBonus] : []),
|
|
63
|
+
...(preferredTierBonus ? ["preferred-tier=" + preferredTierBonus] : []),
|
|
64
|
+
...(priceAdj !== 0 ? ["price=" + priceAdj] : []),
|
|
52
65
|
];
|
|
53
66
|
return { candidate, score, reason };
|
|
54
67
|
})
|
|
@@ -56,11 +69,18 @@ export function resolveModel(request) {
|
|
|
56
69
|
const winner = ranked[0];
|
|
57
70
|
if (!winner)
|
|
58
71
|
return undefined;
|
|
72
|
+
const fallback = ranked
|
|
73
|
+
.slice(1)
|
|
74
|
+
.sort((a, b) => COST_ORDER[a.candidate.cost] - COST_ORDER[b.candidate.cost] || a.score - b.score || a.candidate.id.localeCompare(b.candidate.id))
|
|
75
|
+
.map((item) => item.candidate.id);
|
|
59
76
|
return {
|
|
60
77
|
id: winner.candidate.id,
|
|
61
78
|
score: winner.score,
|
|
62
79
|
cost: winner.candidate.cost,
|
|
80
|
+
...(winner.candidate.priceInput !== undefined ? { priceInput: winner.candidate.priceInput } : {}),
|
|
81
|
+
...(winner.candidate.priceOutput !== undefined ? { priceOutput: winner.candidate.priceOutput } : {}),
|
|
63
82
|
reason: winner.reason,
|
|
83
|
+
fallback,
|
|
64
84
|
};
|
|
65
85
|
}
|
|
66
86
|
//# sourceMappingURL=model-resolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-resolver.js","sourceRoot":"","sources":["../../src/routing/model-resolver.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"model-resolver.js","sourceRoot":"","sources":["../../src/routing/model-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stream observer ("Obestor"). Watches the token stream and flags rising
|
|
3
|
+
* uncertainty mid-generation rather than judging only a finalized answer.
|
|
4
|
+
*/
|
|
5
|
+
export interface StreamObservation {
|
|
6
|
+
confidence: number;
|
|
7
|
+
lowConfidence: boolean;
|
|
8
|
+
flags: string[];
|
|
9
|
+
length: number;
|
|
10
|
+
}
|
|
11
|
+
export interface StreamObserverOptions {
|
|
12
|
+
threshold?: number;
|
|
13
|
+
minLength?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function createStreamObserver(options?: StreamObserverOptions): {
|
|
16
|
+
push(delta: string): StreamObservation;
|
|
17
|
+
observe: () => StreamObservation;
|
|
18
|
+
text: () => string;
|
|
19
|
+
reset(): void;
|
|
20
|
+
};
|
|
21
|
+
export type StreamObserver = ReturnType<typeof createStreamObserver>;
|
|
22
|
+
export declare function scoreFinalText(text: string, options?: StreamObserverOptions): StreamObservation;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stream observer ("Obestor"). Watches the token stream and flags rising
|
|
3
|
+
* uncertainty mid-generation rather than judging only a finalized answer.
|
|
4
|
+
*/
|
|
5
|
+
const HEDGES = [
|
|
6
|
+
"i think", "perhaps", "maybe", "might be", "possibly", "not sure",
|
|
7
|
+
"uncertain", "unclear", "ambiguous", "it seems", "i believe", "likely",
|
|
8
|
+
"assum", "probably", "похоже", "возможно", "вероятно", "не уверен",
|
|
9
|
+
"кажется", "неясно", "предполож", "скорее всего",
|
|
10
|
+
];
|
|
11
|
+
const DISAGREEMENT = [
|
|
12
|
+
"disagree", "conflict", "contradict", "inconsistent", "diverg",
|
|
13
|
+
"however", "on the other hand", "but note",
|
|
14
|
+
"противореч", "не соглас", "однако", "с другой стороны", "расхожд",
|
|
15
|
+
];
|
|
16
|
+
const CORRECTIONS = [
|
|
17
|
+
"actually", "wait", "correction", "let me reconsider", "i mean", "rather",
|
|
18
|
+
"точнее", "на самом деле", "погоди", "точнее говоря",
|
|
19
|
+
];
|
|
20
|
+
export function createStreamObserver(options = {}) {
|
|
21
|
+
const threshold = options.threshold ?? 0.6;
|
|
22
|
+
const minLength = options.minLength ?? 40;
|
|
23
|
+
let text = "";
|
|
24
|
+
function count(list) {
|
|
25
|
+
const lower = text.toLowerCase();
|
|
26
|
+
return list.reduce((acc, phrase) => acc + (lower.includes(phrase) ? 1 : 0), 0);
|
|
27
|
+
}
|
|
28
|
+
function observe() {
|
|
29
|
+
const flags = [];
|
|
30
|
+
const hedgeHits = count(HEDGES);
|
|
31
|
+
const disagreeHits = count(DISAGREEMENT);
|
|
32
|
+
const correctionHits = count(CORRECTIONS);
|
|
33
|
+
let penalties = 0.04 * Math.min(4, hedgeHits);
|
|
34
|
+
penalties += 0.12 * Math.min(3, disagreeHits);
|
|
35
|
+
penalties += 0.08 * Math.min(3, correctionHits);
|
|
36
|
+
if (disagreeHits > 0)
|
|
37
|
+
flags.push("disagreement markers detected");
|
|
38
|
+
if (correctionHits > 0)
|
|
39
|
+
flags.push("self-correction or retraction detected");
|
|
40
|
+
if (hedgeHits >= 2)
|
|
41
|
+
flags.push("persistent hedging language");
|
|
42
|
+
const settled = text.length >= minLength;
|
|
43
|
+
const confidence = Math.max(0.15, Math.min(0.98, 0.92 - penalties));
|
|
44
|
+
const lowConfidence = settled && confidence < threshold;
|
|
45
|
+
return { confidence, lowConfidence, flags, length: text.length };
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
push(delta) {
|
|
49
|
+
text += delta;
|
|
50
|
+
return observe();
|
|
51
|
+
},
|
|
52
|
+
observe,
|
|
53
|
+
text: () => text,
|
|
54
|
+
reset() {
|
|
55
|
+
text = "";
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export function scoreFinalText(text, options = {}) {
|
|
60
|
+
const observer = createStreamObserver(options);
|
|
61
|
+
observer.push(text);
|
|
62
|
+
return observer.observe();
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=observer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observer.js","sourceRoot":"","sources":["../../src/routing/observer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ProfileName } from "../config/schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* A single node in a task's execution DAG. Each node is a self-contained
|
|
4
|
+
* subtask that maps onto one specialist worker. Dependencies are expressed as
|
|
5
|
+
* ids of the nodes that must complete (or at least be dispatched) first.
|
|
6
|
+
*/
|
|
7
|
+
export interface PlanNode {
|
|
8
|
+
id: string;
|
|
9
|
+
description: string;
|
|
10
|
+
worker: string;
|
|
11
|
+
dependsOn: string[];
|
|
12
|
+
}
|
|
13
|
+
export interface TaskPlan {
|
|
14
|
+
nodes: PlanNode[];
|
|
15
|
+
levels: string[][];
|
|
16
|
+
maxParallel: number;
|
|
17
|
+
}
|
|
18
|
+
export interface PlanOptions {
|
|
19
|
+
secondaryWorkers?: string[];
|
|
20
|
+
maxNodes?: number;
|
|
21
|
+
dependencyAware?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function planTask(profile: ProfileName, secondaryProfiles?: ProfileName[], options?: PlanOptions): TaskPlan;
|
|
24
|
+
export declare function validatePlan(plan: TaskPlan): string[];
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const PROFILE_WORKERS = {
|
|
2
|
+
architecture: ["orch-repo", "orch-research", "orch-critic"],
|
|
3
|
+
debug: ["orch-repo", "orch-tests", "orch-critic"],
|
|
4
|
+
ui: ["orch-visual-reference", "orch-visual-review", "orch-repo"],
|
|
5
|
+
research: ["orch-research", "orch-docs", "orch-critic"],
|
|
6
|
+
review: ["orch-critic", "orch-repo", "orch-tests"],
|
|
7
|
+
security: ["orch-security", "orch-repo", "orch-critic"],
|
|
8
|
+
performance: ["orch-tests", "orch-repo", "orch-critic"],
|
|
9
|
+
migration: ["orch-repo", "orch-tests", "orch-research"],
|
|
10
|
+
ops: ["orch-repo", "orch-research", "orch-tests"],
|
|
11
|
+
};
|
|
12
|
+
const ANALYSTS = new Set(["orch-critic", "orch-security", "orch-visual-review"]);
|
|
13
|
+
export function planTask(profile, secondaryProfiles = [], options = {}) {
|
|
14
|
+
const maxNodes = options.maxNodes ?? 6;
|
|
15
|
+
const dependencyAware = options.dependencyAware ?? true;
|
|
16
|
+
const own = PROFILE_WORKERS[profile] ?? [];
|
|
17
|
+
const level0 = [];
|
|
18
|
+
const level1 = [];
|
|
19
|
+
const seen = new Set();
|
|
20
|
+
for (const worker of own) {
|
|
21
|
+
seen.add(worker);
|
|
22
|
+
(ANALYSTS.has(worker) ? level1 : level0).push(worker);
|
|
23
|
+
}
|
|
24
|
+
for (const secondary of secondaryProfiles) {
|
|
25
|
+
for (const worker of PROFILE_WORKERS[secondary] ?? []) {
|
|
26
|
+
if (seen.has(worker))
|
|
27
|
+
continue;
|
|
28
|
+
seen.add(worker);
|
|
29
|
+
(ANALYSTS.has(worker) ? level1 : level0).push(worker);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
for (const worker of options.secondaryWorkers ?? []) {
|
|
33
|
+
if (seen.has(worker))
|
|
34
|
+
continue;
|
|
35
|
+
seen.add(worker);
|
|
36
|
+
(ANALYSTS.has(worker) ? level1 : level0).push(worker);
|
|
37
|
+
}
|
|
38
|
+
const trimmedLevel0 = level0.slice(0, Math.max(1, maxNodes));
|
|
39
|
+
const remaining = maxNodes - trimmedLevel0.length;
|
|
40
|
+
const trimmedLevel1 = level1.slice(0, Math.max(0, remaining));
|
|
41
|
+
const nodes = [];
|
|
42
|
+
const levels = [];
|
|
43
|
+
if (dependencyAware && trimmedLevel1.length > 0) {
|
|
44
|
+
const l0 = trimmedLevel0.map((worker, i) => {
|
|
45
|
+
const node = {
|
|
46
|
+
id: "n0-" + i,
|
|
47
|
+
description: "Gather primary evidence for the " + profile + " task using " + worker + ".",
|
|
48
|
+
worker,
|
|
49
|
+
dependsOn: [],
|
|
50
|
+
};
|
|
51
|
+
nodes.push(node);
|
|
52
|
+
return node.id;
|
|
53
|
+
});
|
|
54
|
+
levels.push(l0);
|
|
55
|
+
const l1 = trimmedLevel1.map((worker, i) => {
|
|
56
|
+
const node = {
|
|
57
|
+
id: "n1-" + i,
|
|
58
|
+
description: "Cross-check the gathered evidence using " + worker + ".",
|
|
59
|
+
worker,
|
|
60
|
+
dependsOn: l0,
|
|
61
|
+
};
|
|
62
|
+
nodes.push(node);
|
|
63
|
+
return node.id;
|
|
64
|
+
});
|
|
65
|
+
levels.push(l1);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const flat = [...trimmedLevel0, ...trimmedLevel1].slice(0, maxNodes);
|
|
69
|
+
const l0 = flat.map((worker, i) => {
|
|
70
|
+
const node = {
|
|
71
|
+
id: "n0-" + i,
|
|
72
|
+
description: "Contribute an independent branch for the " + profile + " task using " + worker + ".",
|
|
73
|
+
worker,
|
|
74
|
+
dependsOn: [],
|
|
75
|
+
};
|
|
76
|
+
nodes.push(node);
|
|
77
|
+
return node.id;
|
|
78
|
+
});
|
|
79
|
+
levels.push(l0);
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
nodes,
|
|
83
|
+
levels,
|
|
84
|
+
maxParallel: levels.reduce((max, level) => Math.max(max, level.length), 0),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export function validatePlan(plan) {
|
|
88
|
+
const byId = new Map(plan.nodes.map((n) => [n.id, n]));
|
|
89
|
+
const position = new Map(plan.nodes.map((n, i) => [n.id, i]));
|
|
90
|
+
const problems = [];
|
|
91
|
+
for (const node of plan.nodes) {
|
|
92
|
+
if (!byId.has(node.id))
|
|
93
|
+
problems.push("missing node " + node.id);
|
|
94
|
+
for (const dep of node.dependsOn) {
|
|
95
|
+
if (!byId.has(dep))
|
|
96
|
+
problems.push("node " + node.id + " references unknown dependency " + dep);
|
|
97
|
+
else if (dep === node.id)
|
|
98
|
+
problems.push("node " + node.id + " depends on itself");
|
|
99
|
+
else if ((position.get(dep) ?? -1) >= (position.get(node.id) ?? 0)) {
|
|
100
|
+
problems.push("node " + node.id + " has a forward/cyclic dependency on " + dep);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return problems;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=planner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planner.js","sourceRoot":"","sources":["../../src/routing/planner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { BudgetMode, ModelCandidateInput } from "../../config/schema.js";
|
|
2
|
+
import { resolveModel } from "../model-resolver.js";
|
|
3
|
+
import type { PriceSnapshot } from "./prices.js";
|
|
4
|
+
import type { TaskPlan } from "../planner.js";
|
|
5
|
+
export interface PriceResolution {
|
|
6
|
+
/** Price source used for the estimate (where a paid price was found). */
|
|
7
|
+
source: "snapshot" | "remote";
|
|
8
|
+
/** Price (USD per 1M tokens) resolved for a model id, if paid and known. */
|
|
9
|
+
price: ModelPriceLike | undefined;
|
|
10
|
+
}
|
|
11
|
+
type ModelPriceLike = {
|
|
12
|
+
input: number;
|
|
13
|
+
output: number;
|
|
14
|
+
};
|
|
15
|
+
export interface TokenEstimates {
|
|
16
|
+
/** Input+output tokens for one worker call. */
|
|
17
|
+
workerTokens: number;
|
|
18
|
+
/** Input+output tokens for one lead synthesis. */
|
|
19
|
+
leadTokens: number;
|
|
20
|
+
/** Input+output tokens for one judge arbitration. */
|
|
21
|
+
judgeTokens: number;
|
|
22
|
+
}
|
|
23
|
+
export declare const DEFAULT_TOKEN_ESTIMATES: TokenEstimates;
|
|
24
|
+
export interface CostEstimateInput {
|
|
25
|
+
budget: BudgetMode;
|
|
26
|
+
plan: TaskPlan;
|
|
27
|
+
/** Worker slots for each capability pool (same shape as config.models.worker). */
|
|
28
|
+
workerPools: Record<"code" | "reasoning" | "research" | "vision" | "image", ModelCandidateInput[]>;
|
|
29
|
+
leadPool: ModelCandidateInput[];
|
|
30
|
+
judgePool: ModelCandidateInput[];
|
|
31
|
+
/** Worker-name -> capability-pool key (from workers.ts WORKERS spec). */
|
|
32
|
+
workerPoolOf: (worker: string) => keyof CostEstimateInput["workerPools"];
|
|
33
|
+
/** Worker-name -> actual capability; review/security share reasoning pools. */
|
|
34
|
+
workerCapabilityOf?: (worker: string) => Parameters<typeof resolveModel>[0]["capability"];
|
|
35
|
+
snapshot: PriceSnapshot;
|
|
36
|
+
tokens?: TokenEstimates;
|
|
37
|
+
}
|
|
38
|
+
export interface CostBreakdown {
|
|
39
|
+
workers: number;
|
|
40
|
+
workersCost: number;
|
|
41
|
+
leadCost: number;
|
|
42
|
+
judgeCost: number;
|
|
43
|
+
subtotal: number;
|
|
44
|
+
/** Conservative +20% buffer for retries / cache misses / reasoning tokens. */
|
|
45
|
+
total: number;
|
|
46
|
+
}
|
|
47
|
+
export interface CostEstimate {
|
|
48
|
+
budget: BudgetMode;
|
|
49
|
+
/** Estimated USD for this task under the given budget mode. */
|
|
50
|
+
total: number;
|
|
51
|
+
breakdown: CostBreakdown;
|
|
52
|
+
/** Human-readable summary line for pre-run confirmation. */
|
|
53
|
+
summary: string;
|
|
54
|
+
}
|
|
55
|
+
export declare function estimateCost(input: CostEstimateInput): CostEstimate;
|
|
56
|
+
/** Compare an estimate against a warning threshold; returns a pre-run message. */
|
|
57
|
+
export declare function formatEstimateWarning(estimate: CostEstimate, thresholdUSD?: number): string | undefined;
|
|
58
|
+
/** Total combined price for a model id or 0 when unknown/free. */
|
|
59
|
+
export declare function priceOfModel(snapshot: PriceSnapshot, modelId: string): number;
|
|
60
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { normalizeCandidate, resolveModel } from "../model-resolver.js";
|
|
2
|
+
import { lookupPrice, combinedPrice } from "./prices.js";
|
|
3
|
+
export const DEFAULT_TOKEN_ESTIMATES = {
|
|
4
|
+
workerTokens: 4_000,
|
|
5
|
+
leadTokens: 6_000,
|
|
6
|
+
judgeTokens: 4_000,
|
|
7
|
+
};
|
|
8
|
+
function costOfTokens(price, tokens) {
|
|
9
|
+
if (!price)
|
|
10
|
+
return 0;
|
|
11
|
+
// Assume a 3:1 input:output split within the token budget.
|
|
12
|
+
const output = tokens * 0.25;
|
|
13
|
+
const input = tokens * 0.75;
|
|
14
|
+
return (input * price.input + output * price.output) / 1_000_000;
|
|
15
|
+
}
|
|
16
|
+
function resolvePoolPriceId(pool, budget, capability, snapshot) {
|
|
17
|
+
const resolved = resolveModel({
|
|
18
|
+
pool,
|
|
19
|
+
capability,
|
|
20
|
+
budget,
|
|
21
|
+
allowPaid: budget === "quality" || budget === "ebobo",
|
|
22
|
+
preferredCosts: budget === "eco" || budget === "balanced" ? ["free"] : [],
|
|
23
|
+
preferredTiers: budget === "ebobo"
|
|
24
|
+
? ["frontier", "lead"]
|
|
25
|
+
: budget === "quality"
|
|
26
|
+
? ["lead", "frontier"]
|
|
27
|
+
: ["worker"],
|
|
28
|
+
});
|
|
29
|
+
if (!resolved)
|
|
30
|
+
return {};
|
|
31
|
+
const configuredPrice = resolved.priceInput !== undefined && resolved.priceOutput !== undefined
|
|
32
|
+
? { input: resolved.priceInput, output: resolved.priceOutput }
|
|
33
|
+
: undefined;
|
|
34
|
+
const price = configuredPrice ?? lookupPrice(snapshot, resolved.id);
|
|
35
|
+
// Only paid models carry a dollar estimate; free/subscription resolve to 0.
|
|
36
|
+
const resolvedPrice = resolved.cost === "paid" ? price : undefined;
|
|
37
|
+
return { id: resolved.id, ...(resolvedPrice ? { price: resolvedPrice } : {}) };
|
|
38
|
+
}
|
|
39
|
+
export function estimateCost(input) {
|
|
40
|
+
const tokens = input.tokens ?? DEFAULT_TOKEN_ESTIMATES;
|
|
41
|
+
const lead = resolvePoolPriceId(input.leadPool, input.budget, "reasoning", input.snapshot);
|
|
42
|
+
const judge = resolvePoolPriceId(input.judgePool, input.budget, "review", input.snapshot);
|
|
43
|
+
const workersCost = input.plan.nodes.reduce((sum, node) => {
|
|
44
|
+
const poolKey = input.workerPoolOf(node.worker);
|
|
45
|
+
const pool = input.workerPools[poolKey] ?? [];
|
|
46
|
+
const capability = input.workerCapabilityOf?.(node.worker)
|
|
47
|
+
?? (poolKey === "image" ? "image" : poolKey === "vision" ? "vision" : poolKey === "research" ? "research" : poolKey === "reasoning" ? "reasoning" : "code");
|
|
48
|
+
const { price } = resolvePoolPriceId(pool, input.budget, capability, input.snapshot);
|
|
49
|
+
return sum + costOfTokens(price, tokens.workerTokens);
|
|
50
|
+
}, 0);
|
|
51
|
+
const leadCost = costOfTokens(lead.price, tokens.leadTokens);
|
|
52
|
+
const judgeCost = costOfTokens(judge.price, tokens.judgeTokens);
|
|
53
|
+
const subtotal = workersCost + leadCost + judgeCost;
|
|
54
|
+
const total = subtotal * 1.2;
|
|
55
|
+
const breakdown = {
|
|
56
|
+
workers: input.plan.nodes.length,
|
|
57
|
+
workersCost,
|
|
58
|
+
leadCost,
|
|
59
|
+
judgeCost,
|
|
60
|
+
subtotal,
|
|
61
|
+
total,
|
|
62
|
+
};
|
|
63
|
+
return {
|
|
64
|
+
budget: input.budget,
|
|
65
|
+
total,
|
|
66
|
+
breakdown,
|
|
67
|
+
summary: `This task in ${input.budget} mode will cost roughly $${total.toFixed(2)} (${breakdown.workers} worker calls, lead, ${judge.price ? "plus judge" : "no judge"} arbitration).`,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/** Compare an estimate against a warning threshold; returns a pre-run message. */
|
|
71
|
+
export function formatEstimateWarning(estimate, thresholdUSD = 0.5) {
|
|
72
|
+
if (estimate.total >= thresholdUSD) {
|
|
73
|
+
return `Heads up: this task in ${estimate.budget} mode is estimated at approximately $${estimate.total.toFixed(2)}. Proceed only if that is acceptable.`;
|
|
74
|
+
}
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
/** Total combined price for a model id or 0 when unknown/free. */
|
|
78
|
+
export function priceOfModel(snapshot, modelId) {
|
|
79
|
+
return combinedPrice(lookupPrice(snapshot, modelId));
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=estimate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"estimate.js","sourceRoot":"","sources":["../../../src/routing/pricing/estimate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ModelPrice {
|
|
2
|
+
input: number;
|
|
3
|
+
output: number;
|
|
4
|
+
}
|
|
5
|
+
export interface PriceSnapshot {
|
|
6
|
+
/** ISO timestamp the snapshot represents (bumped by refresh). */
|
|
7
|
+
updatedAt: string;
|
|
8
|
+
/** Price per provider/model id (e.g. "anthropic/claude-sonnet-4-5"). */
|
|
9
|
+
prices: Record<string, ModelPrice>;
|
|
10
|
+
}
|
|
11
|
+
export declare const SNAPSHOT_VERSION = "2026-01";
|
|
12
|
+
export declare const DEFAULT_PRICES: Record<string, ModelPrice>;
|
|
13
|
+
export declare function emptyPriceSnapshot(): PriceSnapshot;
|
|
14
|
+
/** Normalize an arbitrary provider/model id (case, optional provider) for lookup. */
|
|
15
|
+
export declare function modelPriceKey(providerID: string, modelID: string): string;
|
|
16
|
+
/** Look up a price, tolerating provider/ and bare model ids and case. */
|
|
17
|
+
export declare function lookupPrice(snapshot: PriceSnapshot, id: string): ModelPrice | undefined;
|
|
18
|
+
/** Combined input+output price per 1M tokens, for ordering heuristics. */
|
|
19
|
+
export declare function combinedPrice(price: ModelPrice | undefined): number;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Built-in model price snapshot (USD per 1M tokens, input/output).
|
|
2
|
+
// Prices are a *ranking signal* and the basis for pre-run cost estimates.
|
|
3
|
+
// They can be refreshed from a self-hosted endpoint (see refresh.ts); this
|
|
4
|
+
// snapshot is the offline fallback so estimates never depend on network.
|
|
5
|
+
export const SNAPSHOT_VERSION = "2026-01";
|
|
6
|
+
// Rough public list prices at time of snapshot. Values are per-million-token
|
|
7
|
+
// USD, input/output. They are deliberately approximate: they drive ordering,
|
|
8
|
+
// not accounting — the ledger remains the source of truth for actual spend.
|
|
9
|
+
export const DEFAULT_PRICES = {
|
|
10
|
+
// OpenAI
|
|
11
|
+
"openai/gpt-5.3": { input: 1.25, output: 10 },
|
|
12
|
+
"openai/gpt-5.2": { input: 1.25, output: 10 },
|
|
13
|
+
"openai/gpt-5": { input: 1.25, output: 10 },
|
|
14
|
+
"openai/gpt-5-mini": { input: 0.25, output: 2 },
|
|
15
|
+
"openai/gpt-5-nano": { input: 0.05, output: 0.4 },
|
|
16
|
+
"openai/gpt-4.1": { input: 2, output: 8 },
|
|
17
|
+
"openai/gpt-4.1-mini": { input: 0.4, output: 1.6 },
|
|
18
|
+
"openai/o3": { input: 2, output: 8 },
|
|
19
|
+
"openai/o4-mini": { input: 1.1, output: 4.4 },
|
|
20
|
+
// Anthropic
|
|
21
|
+
"anthropic/claude-sonnet-4-5": { input: 3, output: 15 },
|
|
22
|
+
"anthropic/claude-sonnet-4": { input: 3, output: 15 },
|
|
23
|
+
"anthropic/claude-opus-4": { input: 15, output: 75 },
|
|
24
|
+
"anthropic/claude-opus-4-5": { input: 15, output: 75 },
|
|
25
|
+
"anthropic/claude-haiku-4-5": { input: 1, output: 5 },
|
|
26
|
+
"anthropic/claude-haiku-4": { input: 0.8, output: 4 },
|
|
27
|
+
// Google
|
|
28
|
+
"google/gemini-3-pro": { input: 2, output: 12 },
|
|
29
|
+
"google/gemini-3-flash": { input: 0.1, output: 0.4 },
|
|
30
|
+
"google/gemini-2.5-pro": { input: 1.25, output: 10 },
|
|
31
|
+
"google/gemini-2.5-flash": { input: 0.3, output: 2.5 },
|
|
32
|
+
"google/gemini-2.5-flash-lite": { input: 0.1, output: 0.4 },
|
|
33
|
+
// DeepSeek
|
|
34
|
+
"deepseek/deepseek-chat": { input: 0.27, output: 1.1 },
|
|
35
|
+
"deepseek/deepseek-reasoner": { input: 0.55, output: 2.19 },
|
|
36
|
+
// Meta / Llama (hosted)
|
|
37
|
+
"meta-llama/llama-4-maverick": { input: 0.2, output: 0.6 },
|
|
38
|
+
"meta-llama/llama-4-scout": { input: 0.1, output: 0.35 },
|
|
39
|
+
"meta-llama/llama-3.3-70b": { input: 0.12, output: 0.3 },
|
|
40
|
+
// Mistral
|
|
41
|
+
"mistral/mistral-large": { input: 2, output: 6 },
|
|
42
|
+
"mistral/mistral-medium": { input: 0.9, output: 2.7 },
|
|
43
|
+
"mistral/mistral-small": { input: 0.2, output: 0.6 },
|
|
44
|
+
// xAI
|
|
45
|
+
"x-ai/grok-4": { input: 3, output: 15 },
|
|
46
|
+
"x-ai/grok-3": { input: 3, output: 15 },
|
|
47
|
+
"x-ai/grok-3-mini": { input: 0.3, output: 0.5 },
|
|
48
|
+
};
|
|
49
|
+
export function emptyPriceSnapshot() {
|
|
50
|
+
return { updatedAt: SNAPSHOT_VERSION, prices: { ...DEFAULT_PRICES } };
|
|
51
|
+
}
|
|
52
|
+
/** Normalize an arbitrary provider/model id (case, optional provider) for lookup. */
|
|
53
|
+
export function modelPriceKey(providerID, modelID) {
|
|
54
|
+
return `${providerID.toLowerCase()}/${modelID.toLowerCase()}`;
|
|
55
|
+
}
|
|
56
|
+
/** Look up a price, tolerating provider/ and bare model ids and case. */
|
|
57
|
+
export function lookupPrice(snapshot, id) {
|
|
58
|
+
const normalized = id.toLowerCase();
|
|
59
|
+
const direct = snapshot.prices[normalized];
|
|
60
|
+
if (direct)
|
|
61
|
+
return direct;
|
|
62
|
+
// Fall through bare-model form: map the final path segment across providers.
|
|
63
|
+
const bare = normalized.split("/").pop();
|
|
64
|
+
if (!bare)
|
|
65
|
+
return undefined;
|
|
66
|
+
const entries = Object.entries(snapshot.prices);
|
|
67
|
+
const exact = entries.find(([key]) => key.endsWith(`/${bare}`));
|
|
68
|
+
return exact?.[1];
|
|
69
|
+
}
|
|
70
|
+
/** Combined input+output price per 1M tokens, for ordering heuristics. */
|
|
71
|
+
export function combinedPrice(price) {
|
|
72
|
+
return price ? price.input + price.output : 0;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=prices.js.map
|