@evo-dev/core 0.0.1-alpha.1 → 0.0.1-alpha.2
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/assets/skills/coding/knowledge-distillation/SKILL.md +112 -111
- package/assets/skills/coding/knowledge-distillation/references/knowledge-distillation-methods.md +11 -7
- package/dist/config/index.js +757 -34
- package/dist/index.js +6862 -1535
- package/package.json +5 -1
- package/src/agents/index.ts +56 -0
- package/src/code-agent-traces/index.ts +521 -0
- package/src/config/index.ts +3 -0
- package/src/config/paths.ts +1 -1
- package/src/config/settings.ts +78 -0
- package/src/config/store.ts +2 -0
- package/src/daemon/index.ts +98 -9
- package/src/evolution/index.ts +494 -23
- package/src/hooks/index.ts +315 -36
- package/src/index.ts +2 -0
- package/src/knowledge/index.ts +4784 -0
- package/src/runtime-logs/index.ts +490 -16
- package/src/team/index.ts +847 -176
- package/src/team/mcp.ts +9 -5
- package/src/team/prompts.ts +141 -0
package/src/config/settings.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
1
2
|
import { type HookSettings, createDefaultHookSettings, parseHookSettings } from "../hooks/index.ts";
|
|
2
3
|
import { EvoDevConfigError, describeType } from "./errors.ts";
|
|
4
|
+
import { resolveEvoDevPaths } from "./paths.ts";
|
|
3
5
|
|
|
4
6
|
export interface PluginSettings {
|
|
5
7
|
enabled: boolean;
|
|
@@ -7,6 +9,13 @@ export interface PluginSettings {
|
|
|
7
9
|
autoSyncAgents?: boolean;
|
|
8
10
|
}
|
|
9
11
|
|
|
12
|
+
export interface MemorySettings {
|
|
13
|
+
autoAccept: boolean;
|
|
14
|
+
runtimeInjection: boolean;
|
|
15
|
+
staleReview: boolean;
|
|
16
|
+
lexicalIndex: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
10
19
|
export interface EvoDevSettings {
|
|
11
20
|
version: 1;
|
|
12
21
|
platform: {
|
|
@@ -29,6 +38,7 @@ export interface EvoDevSettings {
|
|
|
29
38
|
};
|
|
30
39
|
hooks: HookSettings;
|
|
31
40
|
teamRuntime: TeamRuntimeSettings;
|
|
41
|
+
memory: MemorySettings;
|
|
32
42
|
}
|
|
33
43
|
|
|
34
44
|
export type SettingsInput = Partial<{
|
|
@@ -45,6 +55,7 @@ export type SettingsInput = Partial<{
|
|
|
45
55
|
doctor: Partial<EvoDevSettings["doctor"]>;
|
|
46
56
|
hooks: unknown;
|
|
47
57
|
teamRuntime: Partial<TeamRuntimeSettings>;
|
|
58
|
+
memory: Partial<MemorySettings>;
|
|
48
59
|
}>;
|
|
49
60
|
|
|
50
61
|
export interface TeamRuntimeSettings {
|
|
@@ -52,6 +63,7 @@ export interface TeamRuntimeSettings {
|
|
|
52
63
|
defaultModel: string | null;
|
|
53
64
|
defaultThinkingLevel: string | null;
|
|
54
65
|
recordTranscript: boolean;
|
|
66
|
+
displayMode: "normal" | "development";
|
|
55
67
|
}
|
|
56
68
|
|
|
57
69
|
export function createDefaultSettings(os: string = process.platform): EvoDevSettings {
|
|
@@ -83,6 +95,7 @@ export function createDefaultSettings(os: string = process.platform): EvoDevSett
|
|
|
83
95
|
},
|
|
84
96
|
hooks: createDefaultHookSettings(),
|
|
85
97
|
teamRuntime: createDefaultTeamRuntimeSettings(),
|
|
98
|
+
memory: createDefaultMemorySettings(),
|
|
86
99
|
};
|
|
87
100
|
}
|
|
88
101
|
|
|
@@ -92,6 +105,16 @@ export function createDefaultTeamRuntimeSettings(): TeamRuntimeSettings {
|
|
|
92
105
|
defaultModel: null,
|
|
93
106
|
defaultThinkingLevel: null,
|
|
94
107
|
recordTranscript: false,
|
|
108
|
+
displayMode: "normal",
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function createDefaultMemorySettings(): MemorySettings {
|
|
113
|
+
return {
|
|
114
|
+
autoAccept: true,
|
|
115
|
+
runtimeInjection: true,
|
|
116
|
+
staleReview: true,
|
|
117
|
+
lexicalIndex: true,
|
|
95
118
|
};
|
|
96
119
|
}
|
|
97
120
|
|
|
@@ -135,11 +158,25 @@ export function mergeSettings(
|
|
|
135
158
|
...defaults.teamRuntime,
|
|
136
159
|
...existing.teamRuntime,
|
|
137
160
|
},
|
|
161
|
+
memory: {
|
|
162
|
+
...defaults.memory,
|
|
163
|
+
...existing.memory,
|
|
164
|
+
},
|
|
138
165
|
};
|
|
139
166
|
|
|
140
167
|
return parseSettings(merged);
|
|
141
168
|
}
|
|
142
169
|
|
|
170
|
+
export async function readRuntimeInjectionSettings(homeDir?: string): Promise<MemorySettings> {
|
|
171
|
+
const paths = resolveEvoDevPaths(homeDir);
|
|
172
|
+
try {
|
|
173
|
+
return parseSettings(JSON.parse(await readFile(paths.settingsPath, "utf8"))).memory;
|
|
174
|
+
} catch (error) {
|
|
175
|
+
if (isNotFoundError(error)) return createDefaultMemorySettings();
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
143
180
|
export function parseSettings(value: unknown): EvoDevSettings {
|
|
144
181
|
const root = expectRecord(value, "settings");
|
|
145
182
|
const version = root.version;
|
|
@@ -184,11 +221,35 @@ export function parseSettings(value: unknown): EvoDevSettings {
|
|
|
184
221
|
root.teamRuntime ?? createDefaultTeamRuntimeSettings(),
|
|
185
222
|
"settings.teamRuntime",
|
|
186
223
|
),
|
|
224
|
+
memory: parseMemorySettings(root.memory ?? createDefaultMemorySettings(), "settings.memory"),
|
|
187
225
|
};
|
|
188
226
|
|
|
189
227
|
return parsed;
|
|
190
228
|
}
|
|
191
229
|
|
|
230
|
+
function parseMemorySettings(value: unknown, path: string): MemorySettings {
|
|
231
|
+
const input = expectRecord(value, path);
|
|
232
|
+
const defaults = createDefaultMemorySettings();
|
|
233
|
+
return {
|
|
234
|
+
autoAccept:
|
|
235
|
+
input.autoAccept === undefined
|
|
236
|
+
? defaults.autoAccept
|
|
237
|
+
: expectBoolean(input.autoAccept, `${path}.autoAccept`),
|
|
238
|
+
runtimeInjection:
|
|
239
|
+
input.runtimeInjection === undefined
|
|
240
|
+
? defaults.runtimeInjection
|
|
241
|
+
: expectBoolean(input.runtimeInjection, `${path}.runtimeInjection`),
|
|
242
|
+
staleReview:
|
|
243
|
+
input.staleReview === undefined
|
|
244
|
+
? defaults.staleReview
|
|
245
|
+
: expectBoolean(input.staleReview, `${path}.staleReview`),
|
|
246
|
+
lexicalIndex:
|
|
247
|
+
input.lexicalIndex === undefined
|
|
248
|
+
? defaults.lexicalIndex
|
|
249
|
+
: expectBoolean(input.lexicalIndex, `${path}.lexicalIndex`),
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
192
253
|
function parseTeamRuntimeSettings(value: unknown, path: string): TeamRuntimeSettings {
|
|
193
254
|
const input = expectRecord(value, path);
|
|
194
255
|
const defaults = createDefaultTeamRuntimeSettings();
|
|
@@ -211,9 +272,20 @@ function parseTeamRuntimeSettings(value: unknown, path: string): TeamRuntimeSett
|
|
|
211
272
|
input.recordTranscript === undefined
|
|
212
273
|
? defaults.recordTranscript
|
|
213
274
|
: expectBoolean(input.recordTranscript, `${path}.recordTranscript`),
|
|
275
|
+
displayMode: parseTeamRuntimeDisplayMode(input.displayMode, defaults.displayMode, path),
|
|
214
276
|
};
|
|
215
277
|
}
|
|
216
278
|
|
|
279
|
+
function parseTeamRuntimeDisplayMode(
|
|
280
|
+
value: unknown,
|
|
281
|
+
fallback: TeamRuntimeSettings["displayMode"],
|
|
282
|
+
path: string,
|
|
283
|
+
): TeamRuntimeSettings["displayMode"] {
|
|
284
|
+
if (value === undefined) return fallback;
|
|
285
|
+
if (value === "normal" || value === "development") return value;
|
|
286
|
+
throw new EvoDevConfigError(`Invalid ${path}.displayMode; expected normal or development`);
|
|
287
|
+
}
|
|
288
|
+
|
|
217
289
|
function parsePluginSettings(value: unknown, path: string): PluginSettings {
|
|
218
290
|
const input = expectRecord(value, path);
|
|
219
291
|
const parsed: PluginSettings = {
|
|
@@ -239,6 +311,12 @@ function expectRecord(value: unknown, path: string): Record<string, unknown> {
|
|
|
239
311
|
return value as Record<string, unknown>;
|
|
240
312
|
}
|
|
241
313
|
|
|
314
|
+
function isNotFoundError(error: unknown): boolean {
|
|
315
|
+
return (
|
|
316
|
+
error instanceof Error && "code" in error && (error as NodeJS.ErrnoException).code === "ENOENT"
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
|
|
242
320
|
function expectString(value: unknown, path: string): string {
|
|
243
321
|
if (typeof value !== "string" || value.length === 0) {
|
|
244
322
|
throw new EvoDevConfigError(`Invalid ${path}; expected non-empty string`);
|
package/src/config/store.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
|
+
import { ensureOkfKnowledgeBase } from "../knowledge/index.ts";
|
|
3
4
|
import { EvoDevConfigError } from "./errors.ts";
|
|
4
5
|
import { type EvoDevPaths, resolveEvoDevPaths } from "./paths.ts";
|
|
5
6
|
import { type EvoDevRegistry, createDefaultRegistry, parseRegistry } from "./registry.ts";
|
|
@@ -102,6 +103,7 @@ export async function initializeCoreConfig(homeDir?: string): Promise<CoreConfig
|
|
|
102
103
|
export async function ensureKnowledgeBaseFiles(paths: EvoDevPaths): Promise<void> {
|
|
103
104
|
await mkdir(paths.knowledgeDir, { recursive: true });
|
|
104
105
|
await mkdir(paths.evosCasesDir, { recursive: true });
|
|
106
|
+
await ensureOkfKnowledgeBase(paths.homeDir);
|
|
105
107
|
await writeTextIfMissing(
|
|
106
108
|
`${paths.knowledgeDir}/README.md`,
|
|
107
109
|
[
|
package/src/daemon/index.ts
CHANGED
|
@@ -6,12 +6,19 @@ import { listEvolutionTriggers, processEvolutionTriggers } from "../evolution/in
|
|
|
6
6
|
import { listObservabilityEvents } from "../observability/index.ts";
|
|
7
7
|
import {
|
|
8
8
|
type TeamRuntimeAdapter,
|
|
9
|
+
isActiveTeamAgentStatus,
|
|
10
|
+
isIdleTeamAgentStatus,
|
|
11
|
+
isMidTurnTeamAgentStatus,
|
|
9
12
|
listTeamRuns,
|
|
13
|
+
markTeamMessagesDelivered,
|
|
14
|
+
readPendingTeamMessagesForRole,
|
|
10
15
|
reconcileTeamRun,
|
|
11
16
|
resumeTeamRun,
|
|
17
|
+
schedulePendingTeamMessageDelivery,
|
|
12
18
|
sendTeamMessage,
|
|
13
19
|
spawnTeamRole,
|
|
14
20
|
stopTeamRole,
|
|
21
|
+
updateTeamAgentHookState,
|
|
15
22
|
} from "../team/index.ts";
|
|
16
23
|
|
|
17
24
|
export interface DaemonPaths {
|
|
@@ -182,12 +189,42 @@ export async function handleDaemonRequest(
|
|
|
182
189
|
const removed = await cleanupDaemonState(input.homeDir, input.token ?? "");
|
|
183
190
|
return ok({ stopped: true, removed }, warnings);
|
|
184
191
|
}
|
|
185
|
-
if (
|
|
192
|
+
if (
|
|
193
|
+
(input.path === "/team/message/enqueue" || input.path === "/teams/send") &&
|
|
194
|
+
input.method === "POST"
|
|
195
|
+
) {
|
|
186
196
|
return dashboardMutation(
|
|
187
197
|
await sendDashboardTeamMessage(input.homeDir, input.body, input.runtimeAdapter),
|
|
188
198
|
warnings,
|
|
189
199
|
);
|
|
190
200
|
}
|
|
201
|
+
if (input.path === "/team/agent/state" && input.method === "POST") {
|
|
202
|
+
return dashboardMutation(
|
|
203
|
+
await updateDashboardTeamAgentState(input.homeDir, input.body),
|
|
204
|
+
warnings,
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
if (input.path === "/team/message/claim" && input.method === "POST") {
|
|
208
|
+
return ok(await claimDashboardTeamMessages(input.homeDir, input.body), warnings);
|
|
209
|
+
}
|
|
210
|
+
if (input.path === "/team/message/delivered" && input.method === "POST") {
|
|
211
|
+
return dashboardMutation(
|
|
212
|
+
await markDashboardTeamMessagesDelivered(input.homeDir, input.body),
|
|
213
|
+
warnings,
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
if (
|
|
217
|
+
(input.path === "/team/reconcile" || input.path === "/teams/reconcile") &&
|
|
218
|
+
input.method === "POST"
|
|
219
|
+
) {
|
|
220
|
+
await schedulePendingTeamMessageDelivery({
|
|
221
|
+
homeDir: input.homeDir,
|
|
222
|
+
runtimeAdapter: input.runtimeAdapter,
|
|
223
|
+
}).catch((error) =>
|
|
224
|
+
warnings.push(`Team delivery scheduling unavailable: ${describeError(error)}`),
|
|
225
|
+
);
|
|
226
|
+
return ok(await collectTeamStatus(input.homeDir, warnings, input.runtimeAdapter), warnings);
|
|
227
|
+
}
|
|
191
228
|
if (input.path === "/teams/spawn" && input.method === "POST") {
|
|
192
229
|
return dashboardMutation(
|
|
193
230
|
await spawnDashboardTeamRole(input.homeDir, input.body, input.runtimeAdapter),
|
|
@@ -206,9 +243,6 @@ export async function handleDaemonRequest(
|
|
|
206
243
|
warnings,
|
|
207
244
|
);
|
|
208
245
|
}
|
|
209
|
-
if (input.path === "/teams/reconcile" && input.method === "POST") {
|
|
210
|
-
return ok(await collectTeamStatus(input.homeDir, warnings, input.runtimeAdapter), warnings);
|
|
211
|
-
}
|
|
212
246
|
if (input.path === "/evolution/process" && input.method === "POST") {
|
|
213
247
|
return dashboardMutation(
|
|
214
248
|
await processDashboardEvolutionTriggers(input.homeDir, input.body),
|
|
@@ -541,10 +575,9 @@ async function collectTeamStatus(
|
|
|
541
575
|
thinkingLevel: agent.thinkingLevel,
|
|
542
576
|
status: agent.status,
|
|
543
577
|
paneId: agent.tmux.paneId,
|
|
544
|
-
canReceiveMessages:
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
agent.status === "recreated",
|
|
578
|
+
canReceiveMessages: isActiveTeamAgentStatus(agent.status),
|
|
579
|
+
isIdle: isIdleTeamAgentStatus(agent.status),
|
|
580
|
+
isMidTurn: isMidTurnTeamAgentStatus(agent.status),
|
|
548
581
|
nativeSessionRecorded: agent.nativeSession.sessionId !== null,
|
|
549
582
|
updatedAt: agent.updatedAt,
|
|
550
583
|
})),
|
|
@@ -552,7 +585,8 @@ async function collectTeamStatus(
|
|
|
552
585
|
notifications: status.notifications.map((notification) => ({
|
|
553
586
|
ok: notification.ok,
|
|
554
587
|
error: notification.error ?? null,
|
|
555
|
-
|
|
588
|
+
delivery: notification.delivery ?? null,
|
|
589
|
+
queuedFor: notification.queuedFor ?? null,
|
|
556
590
|
})),
|
|
557
591
|
}) as DaemonTeamStatusSummary;
|
|
558
592
|
} catch (error) {
|
|
@@ -577,6 +611,61 @@ async function sendDashboardTeamMessage(
|
|
|
577
611
|
});
|
|
578
612
|
}
|
|
579
613
|
|
|
614
|
+
async function updateDashboardTeamAgentState(homeDir: string, body: unknown): Promise<unknown> {
|
|
615
|
+
const input = expectRequestBody(body);
|
|
616
|
+
const result = await updateTeamAgentHookState({
|
|
617
|
+
homeDir,
|
|
618
|
+
runId: expectBodyString(input, "runId"),
|
|
619
|
+
roleId: expectBodyString(input, "roleId"),
|
|
620
|
+
hookEvent: expectBodyString(input, "hookEvent"),
|
|
621
|
+
});
|
|
622
|
+
return {
|
|
623
|
+
ok: true,
|
|
624
|
+
roleId: result.agent.roleId,
|
|
625
|
+
status: result.agent.status,
|
|
626
|
+
statusPath: result.statusPath,
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
async function claimDashboardTeamMessages(homeDir: string, body: unknown): Promise<unknown> {
|
|
631
|
+
const input = expectRequestBody(body);
|
|
632
|
+
const runId = expectBodyString(input, "runId");
|
|
633
|
+
const roleId = expectBodyString(input, "roleId");
|
|
634
|
+
const messages = await readPendingTeamMessagesForRole({
|
|
635
|
+
homeDir,
|
|
636
|
+
runId,
|
|
637
|
+
roleId,
|
|
638
|
+
limit: optionalBodyNumber(input.limit),
|
|
639
|
+
});
|
|
640
|
+
return {
|
|
641
|
+
runId,
|
|
642
|
+
roleId,
|
|
643
|
+
messages,
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
async function markDashboardTeamMessagesDelivered(
|
|
648
|
+
homeDir: string,
|
|
649
|
+
body: unknown,
|
|
650
|
+
): Promise<unknown> {
|
|
651
|
+
const input = expectRequestBody(body);
|
|
652
|
+
const messageIdsValue = input.messageIds;
|
|
653
|
+
if (!Array.isArray(messageIdsValue)) throw new Error("Expected body.messageIds array.");
|
|
654
|
+
const messageIds = messageIdsValue.map((value) => {
|
|
655
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
656
|
+
throw new Error("Expected body.messageIds to contain non-empty strings.");
|
|
657
|
+
}
|
|
658
|
+
return value;
|
|
659
|
+
});
|
|
660
|
+
await markTeamMessagesDelivered({
|
|
661
|
+
homeDir,
|
|
662
|
+
runId: expectBodyString(input, "runId"),
|
|
663
|
+
roleId: expectBodyString(input, "roleId"),
|
|
664
|
+
messageIds,
|
|
665
|
+
});
|
|
666
|
+
return { ok: true, delivered: messageIds };
|
|
667
|
+
}
|
|
668
|
+
|
|
580
669
|
async function spawnDashboardTeamRole(
|
|
581
670
|
homeDir: string,
|
|
582
671
|
body: unknown,
|