@oeronteros-1/opencode-orchestra 1.0.13 → 1.0.14
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/README.md +53 -3
- package/dist/agents/build.js +2 -0
- package/dist/agents/build.js.map +1 -1
- package/dist/agents/lead.js +2 -1
- package/dist/agents/lead.js.map +1 -1
- package/dist/agents/merge.d.ts +4 -0
- package/dist/agents/merge.js +22 -0
- package/dist/agents/merge.js.map +1 -0
- package/dist/dashboard/server.js +80 -1
- package/dist/dashboard/server.js.map +1 -1
- package/dist/index.js +71 -3
- package/dist/index.js.map +1 -1
- package/dist/routing/planner.d.ts +5 -5
- package/dist/routing/planner.js +73 -75
- package/dist/routing/planner.js.map +1 -1
- package/dist/telemetry/live.d.ts +154 -0
- package/dist/telemetry/live.js +248 -0
- package/dist/telemetry/live.js.map +1 -0
- package/dist/tools.js +3 -2
- package/dist/tools.js.map +1 -1
- package/package.json +1 -1
- package/prompts/lead.md +5 -4
- package/CHANGELOG.md +0 -86
- package/GITHUB_RELEASE_1.0.0.md +0 -84
- package/GITHUB_RELEASE_1.0.7.md +0 -21
package/dist/routing/planner.js
CHANGED
|
@@ -9,98 +9,96 @@ const PROFILE_WORKERS = {
|
|
|
9
9
|
migration: ["orch-repo", "orch-tests", "orch-research"],
|
|
10
10
|
ops: ["orch-repo", "orch-research", "orch-tests"],
|
|
11
11
|
};
|
|
12
|
-
const
|
|
12
|
+
const REVIEWERS = new Set(["orch-critic", "orch-security", "orch-visual-review"]);
|
|
13
13
|
export function planTask(profile, secondaryProfiles = [], options = {}) {
|
|
14
|
-
const maxNodes = options.maxNodes ?? 6;
|
|
14
|
+
const maxNodes = Math.max(1, options.maxNodes ?? 6);
|
|
15
15
|
const dependencyAware = options.dependencyAware ?? true;
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
16
|
+
const includeMerger = options.includeMerger ?? dependencyAware;
|
|
17
|
+
const workerLimit = Math.max(0, maxNodes - (includeMerger ? 1 : 0));
|
|
18
|
+
const primary = [];
|
|
19
|
+
const reviewers = [];
|
|
19
20
|
const seen = new Set();
|
|
20
|
-
|
|
21
|
+
const add = (worker) => {
|
|
22
|
+
if (seen.has(worker) || worker === "orch-merge")
|
|
23
|
+
return;
|
|
21
24
|
seen.add(worker);
|
|
22
|
-
(
|
|
23
|
-
}
|
|
24
|
-
for (const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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));
|
|
25
|
+
(REVIEWERS.has(worker) ? reviewers : primary).push(worker);
|
|
26
|
+
};
|
|
27
|
+
for (const worker of PROFILE_WORKERS[profile] ?? [])
|
|
28
|
+
add(worker);
|
|
29
|
+
for (const secondary of secondaryProfiles)
|
|
30
|
+
for (const worker of PROFILE_WORKERS[secondary] ?? [])
|
|
31
|
+
add(worker);
|
|
32
|
+
for (const worker of options.secondaryWorkers ?? [])
|
|
33
|
+
add(worker);
|
|
34
|
+
const selectedPrimary = primary.slice(0, workerLimit);
|
|
35
|
+
const selectedReviewers = reviewers.slice(0, Math.max(0, workerLimit - selectedPrimary.length));
|
|
41
36
|
const nodes = [];
|
|
42
37
|
const levels = [];
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
};
|
|
38
|
+
const first = selectedPrimary.map((worker, i) => {
|
|
39
|
+
const node = { id: "n0-" + i, description: "Investigate an independent " + profile + " branch using " + worker + ".", worker, dependsOn: [], role: "specialist" };
|
|
40
|
+
nodes.push(node);
|
|
41
|
+
return node.id;
|
|
42
|
+
});
|
|
43
|
+
if (first.length)
|
|
44
|
+
levels.push(first);
|
|
45
|
+
let evidence = first;
|
|
46
|
+
if (selectedReviewers.length) {
|
|
47
|
+
const review = selectedReviewers.map((worker, i) => {
|
|
48
|
+
const deps = dependencyAware ? first : [];
|
|
49
|
+
const node = { id: "n1-" + i, description: "Cross-check specialist evidence using " + worker + ".", worker, dependsOn: deps, role: "reviewer" };
|
|
62
50
|
nodes.push(node);
|
|
63
51
|
return node.id;
|
|
64
52
|
});
|
|
65
|
-
|
|
53
|
+
if (dependencyAware)
|
|
54
|
+
levels.push(review);
|
|
55
|
+
else if (levels[0])
|
|
56
|
+
levels[0].push(...review);
|
|
57
|
+
else
|
|
58
|
+
levels.push(review);
|
|
59
|
+
evidence = [...first, ...review];
|
|
66
60
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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);
|
|
61
|
+
let mergerNodeId;
|
|
62
|
+
if (includeMerger) {
|
|
63
|
+
mergerNodeId = "merge";
|
|
64
|
+
nodes.push({ id: mergerNodeId, description: "Merge all completed specialist outputs into one evidence-backed handoff, preserving conflicts and provenance.", worker: "orch-merge", dependsOn: evidence, role: "merger" });
|
|
65
|
+
levels.push([mergerNodeId]);
|
|
80
66
|
}
|
|
81
|
-
return {
|
|
82
|
-
nodes,
|
|
83
|
-
levels,
|
|
84
|
-
maxParallel: levels.reduce((max, level) => Math.max(max, level.length), 0),
|
|
85
|
-
};
|
|
67
|
+
return { nodes, levels, maxParallel: levels.reduce((max, level) => Math.max(max, level.length), 0), ...(mergerNodeId ? { mergerNodeId } : {}) };
|
|
86
68
|
}
|
|
87
69
|
export function validatePlan(plan) {
|
|
88
|
-
const byId = new Map(
|
|
89
|
-
const position = new Map(plan.nodes.map((n, i) => [n.id, i]));
|
|
70
|
+
const byId = new Map();
|
|
90
71
|
const problems = [];
|
|
91
72
|
for (const node of plan.nodes) {
|
|
92
|
-
if (
|
|
93
|
-
problems.push("
|
|
73
|
+
if (byId.has(node.id))
|
|
74
|
+
problems.push("duplicate node " + node.id);
|
|
75
|
+
byId.set(node.id, node);
|
|
76
|
+
}
|
|
77
|
+
const visiting = new Set(), visited = new Set();
|
|
78
|
+
const visit = (id) => {
|
|
79
|
+
if (visiting.has(id)) {
|
|
80
|
+
problems.push("cycle includes " + id);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (visited.has(id))
|
|
84
|
+
return;
|
|
85
|
+
const node = byId.get(id);
|
|
86
|
+
if (!node)
|
|
87
|
+
return;
|
|
88
|
+
visiting.add(id);
|
|
94
89
|
for (const dep of node.dependsOn) {
|
|
95
90
|
if (!byId.has(dep))
|
|
96
|
-
problems.push("node " +
|
|
97
|
-
else if (dep ===
|
|
98
|
-
problems.push("node " +
|
|
99
|
-
else
|
|
100
|
-
|
|
101
|
-
}
|
|
91
|
+
problems.push("node " + id + " references unknown dependency " + dep);
|
|
92
|
+
else if (dep === id)
|
|
93
|
+
problems.push("node " + id + " depends on itself");
|
|
94
|
+
else
|
|
95
|
+
visit(dep);
|
|
102
96
|
}
|
|
103
|
-
|
|
104
|
-
|
|
97
|
+
visiting.delete(id);
|
|
98
|
+
visited.add(id);
|
|
99
|
+
};
|
|
100
|
+
for (const node of plan.nodes)
|
|
101
|
+
visit(node.id);
|
|
102
|
+
return [...new Set(problems)];
|
|
105
103
|
}
|
|
106
104
|
//# sourceMappingURL=planner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planner.js","sourceRoot":"","sources":["../../src/routing/planner.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"planner.js","sourceRoot":"","sources":["../../src/routing/planner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live orchestration activity feed.
|
|
3
|
+
*
|
|
4
|
+
* The OpenCode plugin and the standalone dashboard server run in separate
|
|
5
|
+
* processes, so live state is bridged over the filesystem exactly like the
|
|
6
|
+
* usage ledger. The plugin feeds this stream while agents generate (start /
|
|
7
|
+
* delta / finish) and the dashboard's SSE endpoint re-reads the small snapshot
|
|
8
|
+
* file on a poll, diffing it by a monotonic sequence number.
|
|
9
|
+
*
|
|
10
|
+
* The persisted file is intentionally a full snapshot (active agents + a short
|
|
11
|
+
* ring of recent events) rather than an unbounded log, so a freshly connected
|
|
12
|
+
* dashboard client can read the whole thing with no tailing/trimming logic.
|
|
13
|
+
* The `active` array is authoritative for what is running right now; `recent`
|
|
14
|
+
* is a rolling event log used to animate the UI. Flushes to disk are throttled,
|
|
15
|
+
* and start/finish flush immediately so state changes appear promptly.
|
|
16
|
+
*/
|
|
17
|
+
/** Per-million-token USD prices for a resolved model. */
|
|
18
|
+
export interface LiveTokenPrice {
|
|
19
|
+
input: number;
|
|
20
|
+
output: number;
|
|
21
|
+
}
|
|
22
|
+
/** An event appended to the stream (start / delta / finish). */
|
|
23
|
+
export type LiveEventKind = "start" | "delta" | "finish";
|
|
24
|
+
export interface LiveEvent {
|
|
25
|
+
/** Monotonic sequence; used by the dashboard as its diffing cursor. */
|
|
26
|
+
seq: number;
|
|
27
|
+
e: LiveEventKind;
|
|
28
|
+
/** Epoch ms the event was produced. */
|
|
29
|
+
ts: number;
|
|
30
|
+
/** Orchestration message id the activity belongs to. */
|
|
31
|
+
k: string;
|
|
32
|
+
sessionID?: string | undefined;
|
|
33
|
+
agent?: string | undefined;
|
|
34
|
+
model?: string | undefined;
|
|
35
|
+
provider?: string | undefined;
|
|
36
|
+
/** Current snippet of what the agent produced (what it is "doing"). */
|
|
37
|
+
text?: string | undefined;
|
|
38
|
+
/** USD cost-so-far (delta carries the running estimate; finish the actual). */
|
|
39
|
+
cost?: number | undefined;
|
|
40
|
+
/** Tokens-so-far (delta estimate) or finalized tokens (finish). */
|
|
41
|
+
tokens?: {
|
|
42
|
+
input: number;
|
|
43
|
+
output: number;
|
|
44
|
+
reasoning: number;
|
|
45
|
+
} | undefined;
|
|
46
|
+
/** Finalization reason, present on finish events. */
|
|
47
|
+
finish?: string | undefined;
|
|
48
|
+
/** Stream-observer confidence + flags, present on flagged deltas. */
|
|
49
|
+
confidence?: number | undefined;
|
|
50
|
+
flags?: string[] | undefined;
|
|
51
|
+
}
|
|
52
|
+
/** An agent currently generating. */
|
|
53
|
+
export interface LiveActiveAgent {
|
|
54
|
+
key: string;
|
|
55
|
+
sessionID?: string | undefined;
|
|
56
|
+
agent?: string | undefined;
|
|
57
|
+
model?: string | undefined;
|
|
58
|
+
provider?: string | undefined;
|
|
59
|
+
/** Epoch ms the agent started responding. */
|
|
60
|
+
startedAt: number;
|
|
61
|
+
/** Last-seen snippet of the in-progress output. */
|
|
62
|
+
text: string;
|
|
63
|
+
/** Estimated USD accrued while still generating. */
|
|
64
|
+
cost: number;
|
|
65
|
+
tokens: {
|
|
66
|
+
input: number;
|
|
67
|
+
output: number;
|
|
68
|
+
reasoning: number;
|
|
69
|
+
};
|
|
70
|
+
confidence?: number | undefined;
|
|
71
|
+
flags?: string[] | undefined;
|
|
72
|
+
}
|
|
73
|
+
export interface LiveSnapshot {
|
|
74
|
+
version: 1;
|
|
75
|
+
/** Epoch ms the snapshot was last written. */
|
|
76
|
+
updatedAt: number;
|
|
77
|
+
/** Maximum sequence emitted so far. */
|
|
78
|
+
seq: number;
|
|
79
|
+
/** Agents currently generating. */
|
|
80
|
+
active: LiveActiveAgent[];
|
|
81
|
+
/** Rolling event log (newest last). */
|
|
82
|
+
recent: LiveEvent[];
|
|
83
|
+
}
|
|
84
|
+
export declare function emptyLiveSnapshot(): LiveSnapshot;
|
|
85
|
+
/** Parse the persisted live snapshot; returns an empty snapshot on failure. */
|
|
86
|
+
export declare function parseLiveSnapshot(text: string): LiveSnapshot;
|
|
87
|
+
/** Estimate output tokens from character count (≈4 chars/token). */
|
|
88
|
+
export declare function estimateOutputTokens(chars: number): number;
|
|
89
|
+
/** Estimate live USD accrued from accumulated text + assumed input volume. */
|
|
90
|
+
export declare function estimateLiveCost(chars: number, price: LiveTokenPrice | undefined, assumedInput?: number): {
|
|
91
|
+
cost: number;
|
|
92
|
+
input: number;
|
|
93
|
+
output: number;
|
|
94
|
+
};
|
|
95
|
+
export declare class LiveStream {
|
|
96
|
+
readonly liveFile: string;
|
|
97
|
+
private readonly maxRecent;
|
|
98
|
+
private readonly throttleMs;
|
|
99
|
+
private readonly estimatePrice;
|
|
100
|
+
private active;
|
|
101
|
+
private recent;
|
|
102
|
+
private seq;
|
|
103
|
+
private queue;
|
|
104
|
+
private timer;
|
|
105
|
+
private lastWrite;
|
|
106
|
+
private dirty;
|
|
107
|
+
private enabled;
|
|
108
|
+
constructor(directory: string, telemetryDirectory: string, enabled: boolean, estimatePrice?: (provider: string | undefined, model: string | undefined) => LiveTokenPrice | undefined, maxRecent?: number, throttleMs?: number);
|
|
109
|
+
private makeEvent;
|
|
110
|
+
/** Mark an agent message as started generating. */
|
|
111
|
+
start(input: {
|
|
112
|
+
key: string;
|
|
113
|
+
sessionID?: string | undefined;
|
|
114
|
+
agent?: string | undefined;
|
|
115
|
+
provider?: string | undefined;
|
|
116
|
+
model?: string | undefined;
|
|
117
|
+
startedAt?: number;
|
|
118
|
+
}): void;
|
|
119
|
+
/**
|
|
120
|
+
* Append generated text for an in-flight agent. Each delta updates the
|
|
121
|
+
* in-memory state immediately and is appended to the rolling log; the disk
|
|
122
|
+
* flush is throttled by the class so the dashboard poll stays cheap.
|
|
123
|
+
*/
|
|
124
|
+
delta(input: {
|
|
125
|
+
key: string;
|
|
126
|
+
text: string;
|
|
127
|
+
sessionID?: string | undefined;
|
|
128
|
+
agent?: string | undefined;
|
|
129
|
+
provider?: string | undefined;
|
|
130
|
+
model?: string | undefined;
|
|
131
|
+
confidence?: number | undefined;
|
|
132
|
+
flags?: string[] | undefined;
|
|
133
|
+
}): void;
|
|
134
|
+
/** Mark an agent message as finished and remove it from the active set. */
|
|
135
|
+
finish(input: {
|
|
136
|
+
key: string;
|
|
137
|
+
cost: number;
|
|
138
|
+
tokens?: {
|
|
139
|
+
input: number;
|
|
140
|
+
output: number;
|
|
141
|
+
reasoning: number;
|
|
142
|
+
} | undefined;
|
|
143
|
+
finish?: string | undefined;
|
|
144
|
+
sessionID?: string | undefined;
|
|
145
|
+
agent?: string | undefined;
|
|
146
|
+
}): void;
|
|
147
|
+
/** The current snapshot (before the next disk flush). */
|
|
148
|
+
current(): LiveSnapshot;
|
|
149
|
+
private record;
|
|
150
|
+
private serialize;
|
|
151
|
+
private scheduleFlush;
|
|
152
|
+
private flush;
|
|
153
|
+
dispose(): Promise<void>;
|
|
154
|
+
}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { mkdir, rename, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const MAX_RECENT = 200;
|
|
4
|
+
const THROTTLE_MS = 450;
|
|
5
|
+
function emptySnapshot() {
|
|
6
|
+
return { version: 1, updatedAt: 0, seq: 0, active: [], recent: [] };
|
|
7
|
+
}
|
|
8
|
+
export function emptyLiveSnapshot() {
|
|
9
|
+
return emptySnapshot();
|
|
10
|
+
}
|
|
11
|
+
/** Parse the persisted live snapshot; returns an empty snapshot on failure. */
|
|
12
|
+
export function parseLiveSnapshot(text) {
|
|
13
|
+
try {
|
|
14
|
+
const parsed = JSON.parse(text);
|
|
15
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
16
|
+
return emptySnapshot();
|
|
17
|
+
const candidate = parsed;
|
|
18
|
+
if (candidate.version !== 1)
|
|
19
|
+
return emptySnapshot();
|
|
20
|
+
return {
|
|
21
|
+
version: 1,
|
|
22
|
+
updatedAt: typeof candidate.updatedAt === "number" ? candidate.updatedAt : 0,
|
|
23
|
+
seq: typeof candidate.seq === "number" ? candidate.seq : 0,
|
|
24
|
+
active: Array.isArray(candidate.active) ? candidate.active : [],
|
|
25
|
+
recent: Array.isArray(candidate.recent) ? candidate.recent : [],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return emptySnapshot();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** Estimate output tokens from character count (≈4 chars/token). */
|
|
33
|
+
export function estimateOutputTokens(chars) {
|
|
34
|
+
return Math.max(0, Math.floor(chars / 4));
|
|
35
|
+
}
|
|
36
|
+
/** Estimate live USD accrued from accumulated text + assumed input volume. */
|
|
37
|
+
export function estimateLiveCost(chars, price, assumedInput = 1500) {
|
|
38
|
+
const output = estimateOutputTokens(chars);
|
|
39
|
+
const input = assumedInput;
|
|
40
|
+
let cost = 0;
|
|
41
|
+
if (price) {
|
|
42
|
+
cost = (input * price.input + output * price.output) / 1_000_000;
|
|
43
|
+
}
|
|
44
|
+
return { cost, input, output };
|
|
45
|
+
}
|
|
46
|
+
export class LiveStream {
|
|
47
|
+
liveFile;
|
|
48
|
+
maxRecent;
|
|
49
|
+
throttleMs;
|
|
50
|
+
estimatePrice;
|
|
51
|
+
active = new Map();
|
|
52
|
+
recent = [];
|
|
53
|
+
seq = 0;
|
|
54
|
+
queue = Promise.resolve();
|
|
55
|
+
timer;
|
|
56
|
+
lastWrite = 0;
|
|
57
|
+
dirty = false;
|
|
58
|
+
enabled;
|
|
59
|
+
constructor(directory, telemetryDirectory, enabled, estimatePrice = () => undefined, maxRecent = MAX_RECENT, throttleMs = THROTTLE_MS) {
|
|
60
|
+
this.liveFile = path.resolve(directory, telemetryDirectory, "live.ndjson");
|
|
61
|
+
this.enabled = enabled;
|
|
62
|
+
this.maxRecent = maxRecent;
|
|
63
|
+
this.throttleMs = throttleMs;
|
|
64
|
+
this.estimatePrice = estimatePrice;
|
|
65
|
+
}
|
|
66
|
+
makeEvent(input) {
|
|
67
|
+
const event = { seq: ++this.seq, ts: Date.now(), ...input };
|
|
68
|
+
this.recent.push(event);
|
|
69
|
+
if (this.recent.length > this.maxRecent)
|
|
70
|
+
this.recent.splice(0, this.recent.length - this.maxRecent);
|
|
71
|
+
return event;
|
|
72
|
+
}
|
|
73
|
+
/** Mark an agent message as started generating. */
|
|
74
|
+
start(input) {
|
|
75
|
+
if (!this.enabled)
|
|
76
|
+
return;
|
|
77
|
+
if (this.active.has(input.key)) {
|
|
78
|
+
this.scheduleFlush(true);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const price = this.estimatePrice(input.provider, input.model);
|
|
82
|
+
const est = estimateLiveCost(0, price);
|
|
83
|
+
this.active.set(input.key, {
|
|
84
|
+
key: input.key,
|
|
85
|
+
sessionID: input.sessionID,
|
|
86
|
+
agent: input.agent,
|
|
87
|
+
model: input.model,
|
|
88
|
+
provider: input.provider,
|
|
89
|
+
startedAt: input.startedAt ?? Date.now(),
|
|
90
|
+
text: "",
|
|
91
|
+
cost: est.cost,
|
|
92
|
+
tokens: { input: est.input, output: 0, reasoning: 0 },
|
|
93
|
+
lastSeq: this.seq,
|
|
94
|
+
});
|
|
95
|
+
this.makeEvent({
|
|
96
|
+
e: "start",
|
|
97
|
+
k: input.key,
|
|
98
|
+
sessionID: input.sessionID,
|
|
99
|
+
agent: input.agent,
|
|
100
|
+
model: input.model,
|
|
101
|
+
provider: input.provider,
|
|
102
|
+
text: "",
|
|
103
|
+
cost: 0,
|
|
104
|
+
tokens: undefined,
|
|
105
|
+
});
|
|
106
|
+
this.scheduleFlush(true);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Append generated text for an in-flight agent. Each delta updates the
|
|
110
|
+
* in-memory state immediately and is appended to the rolling log; the disk
|
|
111
|
+
* flush is throttled by the class so the dashboard poll stays cheap.
|
|
112
|
+
*/
|
|
113
|
+
delta(input) {
|
|
114
|
+
if (!this.enabled)
|
|
115
|
+
return;
|
|
116
|
+
const existing = this.active.get(input.key);
|
|
117
|
+
if (!existing) {
|
|
118
|
+
// No prior start for this key: synthesize one so the row is visible.
|
|
119
|
+
this.start({
|
|
120
|
+
key: input.key,
|
|
121
|
+
sessionID: input.sessionID,
|
|
122
|
+
agent: input.agent,
|
|
123
|
+
provider: input.provider,
|
|
124
|
+
model: input.model,
|
|
125
|
+
});
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (input.sessionID)
|
|
129
|
+
existing.sessionID = input.sessionID;
|
|
130
|
+
if (input.agent)
|
|
131
|
+
existing.agent = input.agent;
|
|
132
|
+
if (input.model)
|
|
133
|
+
existing.model = input.model;
|
|
134
|
+
if (input.provider)
|
|
135
|
+
existing.provider = input.provider;
|
|
136
|
+
const snippet = input.text.length > 240 ? `${input.text.slice(-240)}…` : input.text;
|
|
137
|
+
existing.text = snippet;
|
|
138
|
+
existing.confidence = input.confidence;
|
|
139
|
+
existing.flags = input.flags;
|
|
140
|
+
existing.lastSeq = this.seq;
|
|
141
|
+
const price = this.estimatePrice(input.provider ?? existing.provider, input.model ?? existing.model);
|
|
142
|
+
const est = estimateLiveCost(snippet.length, price);
|
|
143
|
+
existing.cost = est.cost;
|
|
144
|
+
existing.tokens = { input: est.input, output: est.output, reasoning: 0 };
|
|
145
|
+
this.record({
|
|
146
|
+
e: "delta",
|
|
147
|
+
k: input.key,
|
|
148
|
+
sessionID: existing.sessionID,
|
|
149
|
+
agent: existing.agent,
|
|
150
|
+
model: input.model ?? existing.model,
|
|
151
|
+
provider: input.provider ?? existing.provider,
|
|
152
|
+
text: snippet,
|
|
153
|
+
cost: existing.cost,
|
|
154
|
+
tokens: { input: existing.tokens.input, output: existing.tokens.output, reasoning: existing.tokens.reasoning },
|
|
155
|
+
confidence: input.confidence,
|
|
156
|
+
flags: input.flags,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
/** Mark an agent message as finished and remove it from the active set. */
|
|
160
|
+
finish(input) {
|
|
161
|
+
if (!this.enabled)
|
|
162
|
+
return;
|
|
163
|
+
const existing = this.active.get(input.key);
|
|
164
|
+
this.active.delete(input.key);
|
|
165
|
+
const tokens = input.tokens ?? existing?.tokens ?? { input: 0, output: 0, reasoning: 0 };
|
|
166
|
+
this.record({
|
|
167
|
+
e: "finish",
|
|
168
|
+
k: input.key,
|
|
169
|
+
sessionID: input.sessionID ?? existing?.sessionID,
|
|
170
|
+
agent: input.agent ?? existing?.agent,
|
|
171
|
+
model: existing?.model,
|
|
172
|
+
provider: existing?.provider,
|
|
173
|
+
cost: input.cost,
|
|
174
|
+
tokens,
|
|
175
|
+
finish: input.finish,
|
|
176
|
+
});
|
|
177
|
+
this.scheduleFlush(true);
|
|
178
|
+
}
|
|
179
|
+
/** The current snapshot (before the next disk flush). */
|
|
180
|
+
current() {
|
|
181
|
+
return this.serialize();
|
|
182
|
+
}
|
|
183
|
+
record(input) {
|
|
184
|
+
this.makeEvent(input);
|
|
185
|
+
this.scheduleFlush(false);
|
|
186
|
+
}
|
|
187
|
+
serialize() {
|
|
188
|
+
const active = [...this.active.values()]
|
|
189
|
+
.map(({ lastSeq: _lastSeq, ...rest }) => rest)
|
|
190
|
+
.sort((a, b) => a.startedAt - b.startedAt);
|
|
191
|
+
return {
|
|
192
|
+
version: 1,
|
|
193
|
+
updatedAt: this.lastWrite || Date.now(),
|
|
194
|
+
seq: this.seq,
|
|
195
|
+
active,
|
|
196
|
+
recent: [...this.recent],
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
scheduleFlush(immediate) {
|
|
200
|
+
if (!this.enabled)
|
|
201
|
+
return;
|
|
202
|
+
this.dirty = true;
|
|
203
|
+
if (immediate) {
|
|
204
|
+
if (this.timer) {
|
|
205
|
+
clearTimeout(this.timer);
|
|
206
|
+
this.timer = undefined;
|
|
207
|
+
}
|
|
208
|
+
void this.flush();
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (this.timer)
|
|
212
|
+
return;
|
|
213
|
+
const remaining = this.throttleMs - (Date.now() - this.lastWrite);
|
|
214
|
+
this.timer = setTimeout(() => {
|
|
215
|
+
this.timer = undefined;
|
|
216
|
+
void this.flush();
|
|
217
|
+
}, Math.max(20, remaining));
|
|
218
|
+
}
|
|
219
|
+
flush() {
|
|
220
|
+
this.dirty = false;
|
|
221
|
+
this.lastWrite = Date.now();
|
|
222
|
+
const snapshot = this.serialize();
|
|
223
|
+
this.queue = this.queue.then(async () => {
|
|
224
|
+
try {
|
|
225
|
+
const directory = path.dirname(this.liveFile);
|
|
226
|
+
await mkdir(directory, { recursive: true });
|
|
227
|
+
const temporary = `${this.liveFile}.tmp`;
|
|
228
|
+
await writeFile(temporary, JSON.stringify(snapshot) + "\n", "utf8");
|
|
229
|
+
await rename(temporary, this.liveFile);
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
// Live telemetry is best-effort; a failure must never break orchestration.
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
return this.queue;
|
|
236
|
+
}
|
|
237
|
+
async dispose() {
|
|
238
|
+
if (this.timer) {
|
|
239
|
+
clearTimeout(this.timer);
|
|
240
|
+
this.timer = undefined;
|
|
241
|
+
}
|
|
242
|
+
if (this.dirty)
|
|
243
|
+
await this.flush();
|
|
244
|
+
else
|
|
245
|
+
await this.queue;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=live.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/telemetry/live.ts"],"names":[],"mappings":"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"}
|
package/dist/tools.js
CHANGED
|
@@ -52,7 +52,8 @@ export function createOrchestraTools(config, ledger, pluginStatus, pricing) {
|
|
|
52
52
|
const workers = workerPool.slice(0, config.orchestration.maxWorkers);
|
|
53
53
|
const planOptions = {
|
|
54
54
|
maxNodes: config.orchestration.maxWorkers,
|
|
55
|
-
dependencyAware:
|
|
55
|
+
dependencyAware: true,
|
|
56
|
+
includeMerger: true,
|
|
56
57
|
...(config.budget === "ebobo" ? { secondaryWorkers: Array.from(new Set(enabledWorkers)) } : {}),
|
|
57
58
|
};
|
|
58
59
|
const plan = planTask(profile, classification.secondaryProfiles, planOptions);
|
|
@@ -99,7 +100,7 @@ export function createOrchestraTools(config, ledger, pluginStatus, pricing) {
|
|
|
99
100
|
escalation,
|
|
100
101
|
...(estimate ? { estimate } : {}),
|
|
101
102
|
...(estimate ? { warning: formatEstimateWarning(estimate, config.pricing.warnThresholdUSD) ?? null } : { warning: null }),
|
|
102
|
-
next: "Delegate the full task once to orch-lead with profile=" + profile + ".
|
|
103
|
+
next: "Delegate the full task and returned plan once to orch-lead with profile=" + profile + ". Execute ready nodes level-by-level, concurrently within parallelWorkers, then call orch-merge exactly once." + eboboHint,
|
|
103
104
|
}, null, 2);
|
|
104
105
|
},
|
|
105
106
|
}),
|