@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prices.js","sourceRoot":"","sources":["../../../src/routing/pricing/prices.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { PriceSnapshot } from "./prices.js";
|
|
2
|
+
export interface RefreshSource {
|
|
3
|
+
/** Self-hosted price endpoint URL, e.g. "https://internal/prices.json". */
|
|
4
|
+
endpoint: string;
|
|
5
|
+
/** Polling interval in hours. 0 disables periodic refresh. */
|
|
6
|
+
refreshIntervalHours: number;
|
|
7
|
+
}
|
|
8
|
+
export interface RefreshState {
|
|
9
|
+
snapshot: PriceSnapshot;
|
|
10
|
+
/** Last successful refresh (epoch ms), undefined if never refreshed. */
|
|
11
|
+
lastRefreshedAt?: number;
|
|
12
|
+
/** Last refresh error, undefined if none. */
|
|
13
|
+
lastError?: string;
|
|
14
|
+
source?: RefreshSource;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Fetch a price list from a self-hosted endpoint and reconcile it over the
|
|
18
|
+
* built-in snapshot. Unknown models are added; known ones are overridden if
|
|
19
|
+
* the remote supplies a value. Failures leave the snapshot untouched, so
|
|
20
|
+
* estimates keep working offline.
|
|
21
|
+
*/
|
|
22
|
+
export declare function refreshPrices(snapshot: PriceSnapshot, source: RefreshSource, fetchImpl?: typeof fetch): Promise<RefreshState>;
|
|
23
|
+
export declare function createPriceRefresher(initial?: PriceSnapshot, source?: RefreshSource): {
|
|
24
|
+
start: () => void;
|
|
25
|
+
stop: () => void;
|
|
26
|
+
sync: () => Promise<void>;
|
|
27
|
+
readonly snapshot: PriceSnapshot;
|
|
28
|
+
readonly lastRefreshedAt: number | undefined;
|
|
29
|
+
readonly lastError: string | undefined;
|
|
30
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { emptyPriceSnapshot } from "./prices.js";
|
|
2
|
+
function isValidPrice(value) {
|
|
3
|
+
if (typeof value !== "object" || value === null)
|
|
4
|
+
return false;
|
|
5
|
+
const candidate = value;
|
|
6
|
+
return (typeof candidate.input === "number" &&
|
|
7
|
+
Number.isFinite(candidate.input) &&
|
|
8
|
+
candidate.input >= 0 &&
|
|
9
|
+
typeof candidate.output === "number" &&
|
|
10
|
+
Number.isFinite(candidate.output) &&
|
|
11
|
+
candidate.output >= 0);
|
|
12
|
+
}
|
|
13
|
+
function parseRemote(text) {
|
|
14
|
+
const payload = JSON.parse(text);
|
|
15
|
+
if (!payload || typeof payload.prices !== "object" || payload.prices === null)
|
|
16
|
+
return undefined;
|
|
17
|
+
const prices = {};
|
|
18
|
+
for (const [key, value] of Object.entries(payload.prices)) {
|
|
19
|
+
if (!isValidPrice(value))
|
|
20
|
+
continue;
|
|
21
|
+
prices[key.toLowerCase()] = { input: value.input, output: value.output };
|
|
22
|
+
}
|
|
23
|
+
if (Object.keys(prices).length === 0)
|
|
24
|
+
return undefined;
|
|
25
|
+
return { updatedAt: payload.updatedAt ?? new Date().toISOString(), prices };
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Fetch a price list from a self-hosted endpoint and reconcile it over the
|
|
29
|
+
* built-in snapshot. Unknown models are added; known ones are overridden if
|
|
30
|
+
* the remote supplies a value. Failures leave the snapshot untouched, so
|
|
31
|
+
* estimates keep working offline.
|
|
32
|
+
*/
|
|
33
|
+
export async function refreshPrices(snapshot, source, fetchImpl = fetch) {
|
|
34
|
+
const startedAt = Date.now();
|
|
35
|
+
if (!source?.endpoint || source.refreshIntervalHours <= 0) {
|
|
36
|
+
return { snapshot: { ...snapshot }, source };
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const response = await fetchImpl(source.endpoint);
|
|
40
|
+
if (!response.ok)
|
|
41
|
+
throw new Error(`price endpoint ${response.status}`);
|
|
42
|
+
const text = await response.text();
|
|
43
|
+
const remote = parseRemote(text);
|
|
44
|
+
if (!remote)
|
|
45
|
+
throw new Error("price endpoint returned no valid prices");
|
|
46
|
+
const merged = { ...snapshot.prices, ...remote.prices };
|
|
47
|
+
return {
|
|
48
|
+
snapshot: { updatedAt: remote.updatedAt, prices: merged },
|
|
49
|
+
lastRefreshedAt: startedAt,
|
|
50
|
+
source,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
return {
|
|
55
|
+
snapshot: { ...snapshot },
|
|
56
|
+
lastError: error instanceof Error ? error.message : String(error),
|
|
57
|
+
source,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export function createPriceRefresher(initial = emptyPriceSnapshot(), source) {
|
|
62
|
+
let state = { snapshot: initial, ...(source ? { source } : {}) };
|
|
63
|
+
let timer;
|
|
64
|
+
let inFlight;
|
|
65
|
+
const sync = () => {
|
|
66
|
+
if (!source?.endpoint || source.refreshIntervalHours <= 0)
|
|
67
|
+
return Promise.resolve();
|
|
68
|
+
if (inFlight)
|
|
69
|
+
return inFlight;
|
|
70
|
+
inFlight = refreshPrices(state.snapshot, source)
|
|
71
|
+
.then((next) => { state = next; })
|
|
72
|
+
.finally(() => { inFlight = undefined; });
|
|
73
|
+
return inFlight;
|
|
74
|
+
};
|
|
75
|
+
const start = () => {
|
|
76
|
+
if (!source?.endpoint || source.refreshIntervalHours <= 0)
|
|
77
|
+
return;
|
|
78
|
+
if (timer)
|
|
79
|
+
return;
|
|
80
|
+
void sync();
|
|
81
|
+
timer = setInterval(() => void sync(), source.refreshIntervalHours * 3_600_000);
|
|
82
|
+
// Do not keep the event loop alive solely for price polling.
|
|
83
|
+
timer.unref?.();
|
|
84
|
+
};
|
|
85
|
+
const stop = () => {
|
|
86
|
+
if (timer)
|
|
87
|
+
clearInterval(timer);
|
|
88
|
+
timer = undefined;
|
|
89
|
+
};
|
|
90
|
+
return {
|
|
91
|
+
start,
|
|
92
|
+
stop,
|
|
93
|
+
sync,
|
|
94
|
+
get snapshot() {
|
|
95
|
+
return state.snapshot;
|
|
96
|
+
},
|
|
97
|
+
get lastRefreshedAt() {
|
|
98
|
+
return state.lastRefreshedAt;
|
|
99
|
+
},
|
|
100
|
+
get lastError() {
|
|
101
|
+
return state.lastError;
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=refresh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../../src/routing/pricing/refresh.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure spend analytics derived from the per-day cost series the dashboard
|
|
3
|
+
* already aggregates. No I/O; deterministic given the same inputs so the
|
|
4
|
+
* results are straightforward to unit test.
|
|
5
|
+
*/
|
|
6
|
+
export interface DailyPoint {
|
|
7
|
+
date: string;
|
|
8
|
+
cost: number;
|
|
9
|
+
input: number;
|
|
10
|
+
output: number;
|
|
11
|
+
reasoning: number;
|
|
12
|
+
}
|
|
13
|
+
export interface DailyAnomaly {
|
|
14
|
+
date: string;
|
|
15
|
+
cost: number;
|
|
16
|
+
baselineMean: number;
|
|
17
|
+
threshold: number;
|
|
18
|
+
/** Signatures of the spike over the baseline (cost / stdev). */
|
|
19
|
+
z: number;
|
|
20
|
+
}
|
|
21
|
+
export interface MonthProjection {
|
|
22
|
+
/** Full calendar-month projection from month-to-date spend. */
|
|
23
|
+
projected: number;
|
|
24
|
+
monthToDate: number;
|
|
25
|
+
elapsedDays: number;
|
|
26
|
+
daysInMonth: number;
|
|
27
|
+
isAheadOfPace: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Flag days whose spend exceeds the trailing baseline (mean + SIGMA×stdev of
|
|
31
|
+
* the *prior* ordered days). A spike is only detected once enough history
|
|
32
|
+
* exists to form a stable baseline; the first days are therefore never
|
|
33
|
+
* flagged, and a single outlier does not poison the baseline.
|
|
34
|
+
*/
|
|
35
|
+
export declare function detectAnomalies(daily: DailyPoint[], sigma?: number): DailyAnomaly[];
|
|
36
|
+
/**
|
|
37
|
+
* Linear extrapolation of month-to-date spend to the full calendar month.
|
|
38
|
+
* `now` defaults to the real clock and exists only for deterministic tests.
|
|
39
|
+
*/
|
|
40
|
+
export declare function projectMonth(daily: DailyPoint[], now?: Date): MonthProjection;
|
|
41
|
+
/** Convenience: run both analyses and expose a combined result. */
|
|
42
|
+
export declare function analyzeDaily(daily: DailyPoint[], now?: Date): {
|
|
43
|
+
anomalies: DailyAnomaly[];
|
|
44
|
+
projection: MonthProjection;
|
|
45
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure spend analytics derived from the per-day cost series the dashboard
|
|
3
|
+
* already aggregates. No I/O; deterministic given the same inputs so the
|
|
4
|
+
* results are straightforward to unit test.
|
|
5
|
+
*/
|
|
6
|
+
const SIGMA = 2;
|
|
7
|
+
function mean(values) {
|
|
8
|
+
if (values.length === 0)
|
|
9
|
+
return 0;
|
|
10
|
+
return values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
11
|
+
}
|
|
12
|
+
function stdev(values) {
|
|
13
|
+
if (values.length < 2)
|
|
14
|
+
return 0;
|
|
15
|
+
const center = mean(values);
|
|
16
|
+
const variance = values.reduce((sum, value) => sum + (value - center) ** 2, 0) / (values.length - 1);
|
|
17
|
+
return Math.sqrt(variance);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Flag days whose spend exceeds the trailing baseline (mean + SIGMA×stdev of
|
|
21
|
+
* the *prior* ordered days). A spike is only detected once enough history
|
|
22
|
+
* exists to form a stable baseline; the first days are therefore never
|
|
23
|
+
* flagged, and a single outlier does not poison the baseline.
|
|
24
|
+
*/
|
|
25
|
+
export function detectAnomalies(daily, sigma = SIGMA) {
|
|
26
|
+
const ordered = [...daily].sort((a, b) => a.date.localeCompare(b.date));
|
|
27
|
+
const anomalies = [];
|
|
28
|
+
const history = [];
|
|
29
|
+
for (const point of ordered) {
|
|
30
|
+
if (history.length >= 3) {
|
|
31
|
+
const baselineMean = mean(history);
|
|
32
|
+
const deviation = stdev(history);
|
|
33
|
+
const threshold = baselineMean + sigma * Math.max(deviation, 0.0001);
|
|
34
|
+
if (point.cost > threshold) {
|
|
35
|
+
anomalies.push({
|
|
36
|
+
date: point.date,
|
|
37
|
+
cost: point.cost,
|
|
38
|
+
baselineMean,
|
|
39
|
+
threshold,
|
|
40
|
+
z: deviation > 0 ? (point.cost - baselineMean) / deviation : 0,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
history.push(point.cost);
|
|
45
|
+
}
|
|
46
|
+
return anomalies;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Linear extrapolation of month-to-date spend to the full calendar month.
|
|
50
|
+
* `now` defaults to the real clock and exists only for deterministic tests.
|
|
51
|
+
*/
|
|
52
|
+
export function projectMonth(daily, now = new Date()) {
|
|
53
|
+
const year = now.getFullYear();
|
|
54
|
+
const month = now.getMonth();
|
|
55
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
56
|
+
const elapsedDays = now.getDate();
|
|
57
|
+
const prefix = now.toISOString().slice(0, 7);
|
|
58
|
+
const monthToDate = daily
|
|
59
|
+
.filter((point) => point.date.startsWith(prefix))
|
|
60
|
+
.reduce((sum, point) => sum + point.cost, 0);
|
|
61
|
+
const elapsed = Math.max(1, elapsedDays);
|
|
62
|
+
const projected = (monthToDate / elapsed) * daysInMonth;
|
|
63
|
+
// Compare the current projection with the average of prior calendar months.
|
|
64
|
+
// Current-month points are deliberately excluded so the baseline and the
|
|
65
|
+
// projection do not measure the same period.
|
|
66
|
+
const prior = daily.filter((point) => !point.date.startsWith(prefix) && point.date < `${prefix}-01`);
|
|
67
|
+
const priorDailyAverage = prior.length > 0 ? prior.reduce((sum, point) => sum + point.cost, 0) / prior.length : 0;
|
|
68
|
+
const isAheadOfPace = prior.length > 0 && projected > priorDailyAverage * daysInMonth;
|
|
69
|
+
return { projected, monthToDate, elapsedDays, daysInMonth, isAheadOfPace };
|
|
70
|
+
}
|
|
71
|
+
/** Convenience: run both analyses and expose a combined result. */
|
|
72
|
+
export function analyzeDaily(daily, now = new Date()) {
|
|
73
|
+
return {
|
|
74
|
+
anomalies: detectAnomalies(daily),
|
|
75
|
+
projection: projectMonth(daily, now),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=analytics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../src/telemetry/analytics.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,9 @@ export interface MessageUsage {
|
|
|
17
17
|
completedAt?: number;
|
|
18
18
|
finish?: string;
|
|
19
19
|
tokens: TokenUsage;
|
|
20
|
+
/** Opt-in debug text: only recorded when telemetry.storeTexts is enabled. */
|
|
21
|
+
prompt?: string;
|
|
22
|
+
reply?: string;
|
|
20
23
|
}
|
|
21
24
|
export interface SessionLedger {
|
|
22
25
|
profile?: ProfileName;
|
|
@@ -52,16 +55,25 @@ export declare function readLedgerState(file: string): Promise<LedgerState>;
|
|
|
52
55
|
export declare class Ledger {
|
|
53
56
|
readonly enabled: boolean;
|
|
54
57
|
readonly stateFile: string;
|
|
58
|
+
private readonly storeTexts;
|
|
55
59
|
private readonly modelCosts;
|
|
56
60
|
private state?;
|
|
57
61
|
private queue;
|
|
58
|
-
constructor(directory: string, telemetryDirectory: string, enabled: boolean, pools: ModelCandidateInput[][]);
|
|
62
|
+
constructor(directory: string, telemetryDirectory: string, enabled: boolean, pools: ModelCandidateInput[][], storeTexts?: boolean);
|
|
59
63
|
private load;
|
|
60
64
|
private save;
|
|
61
65
|
private mutate;
|
|
62
66
|
setProfile(sessionID: string, profile: ProfileName): Promise<void>;
|
|
63
67
|
setConsensus(sessionID: string, consensus: number): Promise<void>;
|
|
64
68
|
recordAssistant(info: AssistantInfo): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Opt-in debug text. No-op unless the ledger was constructed with
|
|
71
|
+
* `storeTexts`, so prompts and replies are never persisted by default.
|
|
72
|
+
*/
|
|
73
|
+
recordText(sessionID: string, messageID: string, text: {
|
|
74
|
+
prompt?: string;
|
|
75
|
+
reply?: string;
|
|
76
|
+
}): Promise<void>;
|
|
65
77
|
getSession(sessionID: string): Promise<SessionLedger>;
|
|
66
78
|
formatStatus(sessionID: string): Promise<string>;
|
|
67
79
|
}
|
package/dist/telemetry/ledger.js
CHANGED
|
@@ -33,6 +33,10 @@ function upgradeState(input) {
|
|
|
33
33
|
const sessions = candidate.sessions ?? {};
|
|
34
34
|
for (const session of Object.values(sessions)) {
|
|
35
35
|
session.messages ??= {};
|
|
36
|
+
session.agents ??= {};
|
|
37
|
+
session.premiumEscalations ??= 0;
|
|
38
|
+
session.estimatedPaidUsage ??= 0;
|
|
39
|
+
session.freeWorkerCalls ??= 0;
|
|
36
40
|
for (const [id, message] of Object.entries(session.messages)) {
|
|
37
41
|
session.messages[id] = {
|
|
38
42
|
...message,
|
|
@@ -58,11 +62,13 @@ export async function readLedgerState(file) {
|
|
|
58
62
|
export class Ledger {
|
|
59
63
|
enabled;
|
|
60
64
|
stateFile;
|
|
65
|
+
storeTexts;
|
|
61
66
|
modelCosts;
|
|
62
67
|
state;
|
|
63
68
|
queue = Promise.resolve();
|
|
64
|
-
constructor(directory, telemetryDirectory, enabled, pools) {
|
|
69
|
+
constructor(directory, telemetryDirectory, enabled, pools, storeTexts = false) {
|
|
65
70
|
this.enabled = enabled;
|
|
71
|
+
this.storeTexts = storeTexts;
|
|
66
72
|
this.stateFile = path.resolve(directory, telemetryDirectory, "state.json");
|
|
67
73
|
this.modelCosts = new Map(pools.flat().map((candidate) => {
|
|
68
74
|
const normalized = normalizeCandidate(candidate);
|
|
@@ -145,9 +151,31 @@ export class Ledger {
|
|
|
145
151
|
...(info.time?.completed ? { completedAt: info.time.completed } : {}),
|
|
146
152
|
...(info.finish ? { finish: info.finish } : {}),
|
|
147
153
|
tokens: normalizeTokens(info.tokens),
|
|
154
|
+
...(previous?.prompt !== undefined ? { prompt: previous.prompt } : {}),
|
|
155
|
+
...(previous?.reply !== undefined ? { reply: previous.reply } : {}),
|
|
148
156
|
};
|
|
149
157
|
});
|
|
150
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Opt-in debug text. No-op unless the ledger was constructed with
|
|
161
|
+
* `storeTexts`, so prompts and replies are never persisted by default.
|
|
162
|
+
*/
|
|
163
|
+
async recordText(sessionID, messageID, text) {
|
|
164
|
+
if (!this.storeTexts)
|
|
165
|
+
return;
|
|
166
|
+
await this.mutate((state) => {
|
|
167
|
+
const session = (state.sessions[sessionID] ??= emptySession());
|
|
168
|
+
const message = (session.messages[messageID] ??= {
|
|
169
|
+
cost: 0,
|
|
170
|
+
agent: "default",
|
|
171
|
+
tokens: normalizeTokens(undefined),
|
|
172
|
+
});
|
|
173
|
+
if (text.prompt !== undefined)
|
|
174
|
+
message.prompt = text.prompt;
|
|
175
|
+
if (text.reply !== undefined)
|
|
176
|
+
message.reply = text.reply;
|
|
177
|
+
});
|
|
178
|
+
}
|
|
151
179
|
async getSession(sessionID) {
|
|
152
180
|
await this.queue;
|
|
153
181
|
const state = await this.load();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../src/telemetry/ledger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACrE,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;
|
|
1
|
+
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../src/telemetry/ledger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACrE,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AA0DjE,SAAS,YAAY;IACnB,OAAO;QACL,MAAM,EAAE,EAAE;QACV,kBAAkB,EAAE,CAAC;QACrB,kBAAkB,EAAE,CAAC;QACrB,eAAe,EAAE,CAAC;QAClB,QAAQ,EAAE,EAAE;KACb,CAAA;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;AAC3E,CAAC;AAED,SAAS,eAAe,CAAC,MAA4B;IACnD,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,CAAC;QACtC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC;QACxC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,IAAI,CAAC,CAAC;QAC9C,KAAK,EAAE;YACL,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC,CAAC;YAC3C,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC,CAAC;SAC9C;KACF,CAAA;AACH,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,gBAAgB,EAAE,CAAA;IAC1E,MAAM,SAAS,GAAG,KAA2F,CAAA;IAC7G,IAAI,SAAS,CAAC,OAAO,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,KAAK,CAAC;QAAE,OAAO,gBAAgB,EAAE,CAAA;IACjF,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,IAAI,EAAE,CAAA;IACzC,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9C,OAAO,CAAC,QAAQ,KAAK,EAAE,CAAA;QACvB,OAAO,CAAC,MAAM,KAAK,EAAE,CAAA;QACrB,OAAO,CAAC,kBAAkB,KAAK,CAAC,CAAA;QAChC,OAAO,CAAC,kBAAkB,KAAK,CAAC,CAAA;QAChC,OAAO,CAAC,eAAe,KAAK,CAAC,CAAA;QAC7B,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7D,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG;gBACrB,GAAG,OAAO;gBACV,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;gBACpC,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC;aACxC,CAAA;QACH,CAAC;IACH,CAAC;IACD,OAAO;QACL,OAAO,EAAE,CAAC;QACV,SAAS,EAAE,SAAS,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;QAC3D,QAAQ;KACT,CAAA;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY;IAChD,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,gBAAgB,EAAE,CAAA;IAC3B,CAAC;AACH,CAAC;AAED,MAAM,OAAO,MAAM;IACR,OAAO,CAAS;IAChB,SAAS,CAAQ;IACT,UAAU,CAAS;IACnB,UAAU,CAAwB;IAC3C,KAAK,CAAc;IACnB,KAAK,GAAG,OAAO,CAAC,OAAO,EAAE,CAAA;IAEjC,YACE,SAAiB,EACjB,kBAA0B,EAC1B,OAAgB,EAChB,KAA8B,EAC9B,UAAU,GAAG,KAAK;QAElB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,kBAAkB,EAAE,YAAY,CAAC,CAAA;QAC1E,IAAI,CAAC,UAAU,GAAG,IAAI,GAAG,CACvB,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;YAC7B,MAAM,UAAU,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAA;YAChD,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,CAAC,CAAA;QACzC,CAAC,CAAC,CACH,CAAA;IACH,CAAC;IAEO,KAAK,CAAC,IAAI;QAChB,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC,KAAK,CAAA;QACjC,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;QAC/E,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,KAAK,GAAG,gBAAgB,EAAE,CAAA;QACjC,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,KAAkB;QACnC,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAM;QACzB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAC9C,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAA;QACrD,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,UAAU,EAAE,kBAAkB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QACjE,CAAC;QAAC,MAAM,CAAC;YACP,2EAA2E;QAC7E,CAAC;QACD,KAAK,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;QAC1C,MAAM,SAAS,GAAG,GAAG,IAAI,CAAC,SAAS,MAAM,CAAA;QACzC,MAAM,SAAS,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACzE,MAAM,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;IACzC,CAAC;IAEO,MAAM,CAAC,SAAuC;QACpD,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;QAC3C,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;YACtC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA;YAC/B,SAAS,CAAC,KAAK,CAAC,CAAA;YAChB,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACxB,CAAC,CAAC,CAAA;QACF,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,SAAiB,EAAE,OAAoB;QACtD,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YAC1B,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,YAAY,EAAE,CAAC,CAAA;YAC9D,OAAO,CAAC,OAAO,GAAG,OAAO,CAAA;QAC3B,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,SAAiB,EAAE,SAAiB;QACrD,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YAC1B,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,YAAY,EAAE,CAAC,CAAA;YAC9D,OAAO,CAAC,SAAS,GAAG,SAAS,CAAA;QAC/B,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,IAAmB;QACvC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,IAAI,SAAS,CAAA;QACpC,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YAC1B,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,YAAY,EAAE,CAAC,CAAA;YACnE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAA;YAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAA;YAC9D,OAAO,CAAC,kBAAkB,IAAI,KAAK,CAAA;YAEnC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;gBACxD,IAAI,KAAK,KAAK,YAAY;oBAAE,OAAO,CAAC,kBAAkB,IAAI,CAAC,CAAA;gBAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;gBAChG,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,YAAY,IAAI,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,MAAM,EAAE,CAAC;oBACnI,OAAO,CAAC,eAAe,IAAI,CAAC,CAAA;gBAC9B,CAAC;YACH,CAAC;YAED,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG;gBAC1B,IAAI,EAAE,WAAW;gBACjB,KAAK;gBACL,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChD,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzD,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/D,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/C,MAAM,EAAE,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;gBACpC,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtE,GAAG,CAAC,QAAQ,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACpE,CAAA;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,CACd,SAAiB,EACjB,SAAiB,EACjB,IAAyC;QAEzC,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAM;QAC5B,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YAC1B,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,YAAY,EAAE,CAAC,CAAA;YAC9D,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK;gBAC/C,IAAI,EAAE,CAAC;gBACP,KAAK,EAAE,SAAS;gBAChB,MAAM,EAAE,eAAe,CAAC,SAAS,CAAC;aACnC,CAAC,CAAA;YACF,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;gBAAE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;YAC3D,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;gBAAE,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;QAC1D,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,SAAiB;QAChC,MAAM,IAAI,CAAC,KAAK,CAAA;QAChB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA;QAC/B,OAAO,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,YAAY,EAAE,CAAA;IACpD,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,SAAiB;QAClC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;QAChD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;aAC1C,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;aACtC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;aACvD,IAAI,CAAC,IAAI,CAAC,CAAA;QACb,OAAO;YACL,2BAA2B;YAC3B,EAAE;YACF,YAAY,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,gBAAgB,EAAE;YAChE,EAAE;YACF,SAAS;YACT,MAAM,IAAI,qBAAqB;YAC/B,EAAE;YACF,wBAAwB,OAAO,CAAC,kBAAkB,EAAE;YACpD,0BAA0B,OAAO,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YACjE,sBAAsB,OAAO,CAAC,eAAe,EAAE;YAC/C,cAAc,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,GAAG,GAAG,CAAC,GAAG,EAAE;SAC7G,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACd,CAAC;CACF"}
|
package/dist/tools.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { type ToolDefinition } from "@opencode-ai/plugin";
|
|
2
2
|
import type { OrchestraConfig } from "./config/schema.js";
|
|
3
|
+
import type { PriceSnapshot } from "./routing/pricing/prices.js";
|
|
3
4
|
import type { Ledger } from "./telemetry/ledger.js";
|
|
4
|
-
|
|
5
|
+
import { type PluginStatus } from "./plugin-status.js";
|
|
6
|
+
export interface PricingContext {
|
|
7
|
+
snapshot: PriceSnapshot;
|
|
8
|
+
}
|
|
9
|
+
export declare function createOrchestraTools(config: OrchestraConfig, ledger: Ledger, pluginStatus?: PluginStatus, pricing?: PricingContext): Record<string, ToolDefinition>;
|
package/dist/tools.js
CHANGED
|
@@ -2,8 +2,15 @@ import { tool } from "@opencode-ai/plugin";
|
|
|
2
2
|
import { profileNameSchema } from "./config/schema.js";
|
|
3
3
|
import { PROFILE_CATALOG } from "./profiles/catalog.js";
|
|
4
4
|
import { classifyTask } from "./routing/classifier.js";
|
|
5
|
+
import { createClassifierCache } from "./routing/classifier-cache.js";
|
|
5
6
|
import { decideEscalation } from "./routing/escalation.js";
|
|
6
|
-
|
|
7
|
+
import { planTask } from "./routing/planner.js";
|
|
8
|
+
import { createBudgetGuard, paidBudgetFor } from "./routing/budget-guard.js";
|
|
9
|
+
import { estimateCost, formatEstimateWarning } from "./routing/pricing/estimate.js";
|
|
10
|
+
import { workerCapability, workerPoolKey } from "./agents/workers.js";
|
|
11
|
+
import { formatPluginStatus } from "./plugin-status.js";
|
|
12
|
+
const classificationCache = createClassifierCache();
|
|
13
|
+
export function createOrchestraTools(config, ledger, pluginStatus, pricing) {
|
|
7
14
|
return {
|
|
8
15
|
orchestra_route: tool({
|
|
9
16
|
description: "Classify a complex task and return the recommended OpenCode Orchestra worker team for the active budget mode. This does not execute the team.",
|
|
@@ -13,11 +20,28 @@ export function createOrchestraTools(config, ledger) {
|
|
|
13
20
|
},
|
|
14
21
|
async execute(args, context) {
|
|
15
22
|
const requested = args.profile ? profileNameSchema.safeParse(args.profile) : undefined;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
let cached = false;
|
|
24
|
+
let classification;
|
|
25
|
+
if (requested?.success) {
|
|
26
|
+
classification = {
|
|
27
|
+
...classifyTask(args.task, config.orchestration.profiles),
|
|
28
|
+
profile: requested.data,
|
|
29
|
+
confidence: 1,
|
|
30
|
+
matchedSignals: ["explicit profile"],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
const hit = classificationCache.get(args.task);
|
|
35
|
+
if (hit) {
|
|
36
|
+
classification = hit;
|
|
37
|
+
cached = true;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
classification = classifyTask(args.task, config.orchestration.profiles);
|
|
41
|
+
classificationCache.set(args.task, classification);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const profile = classification.profile;
|
|
21
45
|
const definition = PROFILE_CATALOG[profile];
|
|
22
46
|
const enabledWorkers = Object.values(PROFILE_CATALOG)
|
|
23
47
|
.filter((candidate) => config.orchestration.profiles[candidate.name] !== false)
|
|
@@ -26,19 +50,56 @@ export function createOrchestraTools(config, ledger) {
|
|
|
26
50
|
? Array.from(new Set(enabledWorkers))
|
|
27
51
|
: definition.workers;
|
|
28
52
|
const workers = workerPool.slice(0, config.orchestration.maxWorkers);
|
|
53
|
+
const planOptions = {
|
|
54
|
+
maxNodes: config.orchestration.maxWorkers,
|
|
55
|
+
dependencyAware: config.budget !== "ebobo",
|
|
56
|
+
...(config.budget === "ebobo" ? { secondaryWorkers: Array.from(new Set(enabledWorkers)) } : {}),
|
|
57
|
+
};
|
|
58
|
+
const plan = planTask(profile, classification.secondaryProfiles, planOptions);
|
|
59
|
+
const paidBudget = paidBudgetFor(config.budget, {
|
|
60
|
+
maxPaidCalls: config.orchestration.maxPremiumCallsPerTask,
|
|
61
|
+
});
|
|
62
|
+
const guard = createBudgetGuard(paidBudget);
|
|
29
63
|
const escalation = decideEscalation(config, { classification });
|
|
30
64
|
const sessionID = context.sessionID;
|
|
31
65
|
if (sessionID)
|
|
32
66
|
await ledger.setProfile(sessionID, profile);
|
|
67
|
+
// Pre-run cost estimate (informational; does not block execution).
|
|
68
|
+
let estimate;
|
|
69
|
+
if (config.pricing.estimate && pricing?.snapshot) {
|
|
70
|
+
estimate = estimateCost({
|
|
71
|
+
budget: config.budget,
|
|
72
|
+
plan,
|
|
73
|
+
workerPools: config.models.worker,
|
|
74
|
+
leadPool: config.models.lead,
|
|
75
|
+
judgePool: config.models.judge,
|
|
76
|
+
workerPoolOf: workerPoolKey,
|
|
77
|
+
workerCapabilityOf: workerCapability,
|
|
78
|
+
snapshot: pricing.snapshot,
|
|
79
|
+
tokens: { workerTokens: 4000, leadTokens: 6000, judgeTokens: 4000 },
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const eboboHint = config.budget === "ebobo"
|
|
83
|
+
? " EBOBO MODE: run all level-0 branches concurrently and always consult orch-judge for frontier arbitration."
|
|
84
|
+
: "";
|
|
33
85
|
return JSON.stringify({
|
|
34
86
|
profile,
|
|
35
87
|
secondaryProfiles: classification.secondaryProfiles,
|
|
36
88
|
confidence: classification.confidence,
|
|
37
89
|
critical: classification.critical,
|
|
90
|
+
cached,
|
|
38
91
|
workers,
|
|
39
92
|
parallelWorkers: Math.min(config.orchestration.parallelWorkers, workers.length),
|
|
93
|
+
plan,
|
|
94
|
+
paidBudget: {
|
|
95
|
+
maxPaidCalls: paidBudget.maxPaidCalls,
|
|
96
|
+
remaining: guard.remaining(),
|
|
97
|
+
enabled: paidBudget.enabled,
|
|
98
|
+
},
|
|
40
99
|
escalation,
|
|
41
|
-
|
|
100
|
+
...(estimate ? { estimate } : {}),
|
|
101
|
+
...(estimate ? { warning: formatEstimateWarning(estimate, config.pricing.warnThresholdUSD) ?? null } : { warning: null }),
|
|
102
|
+
next: "Delegate the full task once to orch-lead with profile=" + profile + ". Let orch-lead dispatch workers per the plan levels: level 0 branches in parallel, then level 1 synthesis." + eboboHint,
|
|
42
103
|
}, null, 2);
|
|
43
104
|
},
|
|
44
105
|
}),
|
|
@@ -52,6 +113,15 @@ export function createOrchestraTools(config, ledger) {
|
|
|
52
113
|
return ledger.formatStatus(sessionID);
|
|
53
114
|
},
|
|
54
115
|
}),
|
|
116
|
+
orchestra_plugin_status: tool({
|
|
117
|
+
description: "Show the OpenCode Orchestra plugin's own runtime status: loaded version, budget mode, model strategy, config source, model counts, and companion MCP status (Context7, Codebase Memory, MemoryGraph, Supermemory).",
|
|
118
|
+
args: {},
|
|
119
|
+
async execute() {
|
|
120
|
+
if (!pluginStatus)
|
|
121
|
+
return "OpenCode Orchestra plugin status is unavailable — no plugin status snapshot was captured.";
|
|
122
|
+
return formatPluginStatus(pluginStatus);
|
|
123
|
+
},
|
|
124
|
+
}),
|
|
55
125
|
};
|
|
56
126
|
}
|
|
57
127
|
//# sourceMappingURL=tools.js.map
|
package/dist/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAuB,MAAM,qBAAqB,CAAA;AAE/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oeronteros-1/opencode-orchestra",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Production-ready model routing, specialist agents, diagnostics, telemetry, and dashboard for OpenCode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/Oeronteros/opencode-orchestra.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/Oeronteros/opencode-orchestra#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Oeronteros/opencode-orchestra/issues"
|
|
14
|
+
},
|
|
7
15
|
"publishConfig": {
|
|
8
16
|
"access": "public"
|
|
9
17
|
},
|
|
@@ -11,7 +19,10 @@
|
|
|
11
19
|
"opencode",
|
|
12
20
|
"plugin",
|
|
13
21
|
"agents",
|
|
14
|
-
"orchestration"
|
|
22
|
+
"orchestration",
|
|
23
|
+
"model-routing",
|
|
24
|
+
"mcp",
|
|
25
|
+
"telemetry"
|
|
15
26
|
],
|
|
16
27
|
"files": [
|
|
17
28
|
"dist",
|
|
@@ -19,6 +30,7 @@
|
|
|
19
30
|
"prompts",
|
|
20
31
|
"schema",
|
|
21
32
|
"CHANGELOG.md",
|
|
33
|
+
"GITHUB_RELEASE_1.0.0.md",
|
|
22
34
|
"README.md",
|
|
23
35
|
"LICENSE"
|
|
24
36
|
],
|
|
@@ -34,9 +46,10 @@
|
|
|
34
46
|
"build:dashboard": "vite build --config dashboard/vite.config.ts",
|
|
35
47
|
"build:plugin": "tsc -p tsconfig.build.json",
|
|
36
48
|
"dev:dashboard": "vite --config dashboard/vite.config.ts",
|
|
49
|
+
"prepublishOnly": "npm run check",
|
|
37
50
|
"prepack": "npm run build",
|
|
38
51
|
"typecheck": "tsc --noEmit && tsc -p dashboard/tsconfig.json",
|
|
39
|
-
"test": "tsc -p tsconfig.test.json && node --test dist-test/test/classifier.test.js dist-test/test/model-resolver.test.js dist-test/test/model-discovery.test.js dist-test/test/budget.test.js dist-test/test/agents.test.js dist-test/test/plugin.test.js dist-test/test/cli.test.js dist-test/test/dashboard.test.js dist-test/test/ledger.test.js",
|
|
52
|
+
"test": "tsc -p tsconfig.test.json && node --test dist-test/test/classifier.test.js dist-test/test/model-resolver.test.js dist-test/test/model-discovery.test.js dist-test/test/budget.test.js dist-test/test/agents.test.js dist-test/test/plugin.test.js dist-test/test/plugin-status.test.js dist-test/test/cli.test.js dist-test/test/dashboard.test.js dist-test/test/ledger.test.js dist-test/test/analytics.test.js dist-test/test/routing-features.test.js dist-test/test/pricing.test.js dist-test/test/fallback.test.js dist-test/test/integration.test.js dist-test/test/doctor.test.js",
|
|
40
53
|
"check": "npm run typecheck && npm test"
|
|
41
54
|
},
|
|
42
55
|
"dependencies": {
|