@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/hooks/index.ts
CHANGED
|
@@ -2,6 +2,12 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { enqueueEvolutionTrigger, resolveEvolutionTriggerDecision } from "../evolution/index.ts";
|
|
5
|
+
import {
|
|
6
|
+
createScopedKnowledgeContextPack,
|
|
7
|
+
formatScopedKnowledgePromptBlock,
|
|
8
|
+
hasContextInjectionReceipt,
|
|
9
|
+
writeContextInjectionReceipt,
|
|
10
|
+
} from "../knowledge/index.ts";
|
|
5
11
|
import { resolveTraceTeamContext } from "../runtime-logs/index.ts";
|
|
6
12
|
import {
|
|
7
13
|
type TaskContract,
|
|
@@ -9,7 +15,15 @@ import {
|
|
|
9
15
|
routeTaskContract,
|
|
10
16
|
writeTaskContract,
|
|
11
17
|
} from "../task/index.ts";
|
|
12
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
type TeamMessageRecord,
|
|
20
|
+
createTeamRoleRuntimeContext,
|
|
21
|
+
markTeamMessagesDelivered,
|
|
22
|
+
readPendingTeamMessagesForRole,
|
|
23
|
+
recordTeamAgentNativeSession,
|
|
24
|
+
resolveTeamRunPaths,
|
|
25
|
+
updateTeamAgentHookState,
|
|
26
|
+
} from "../team/index.ts";
|
|
13
27
|
|
|
14
28
|
export const CANONICAL_HOOK_EVENT_TYPES = [
|
|
15
29
|
"SessionStart",
|
|
@@ -142,6 +156,7 @@ export interface HookRuntimeSessionBinding {
|
|
|
142
156
|
contractPath: string | null;
|
|
143
157
|
cwd: string | null;
|
|
144
158
|
route: TaskContract["route"] | null;
|
|
159
|
+
teamRuntimeContextDeliveredAt?: string | null;
|
|
145
160
|
updatedAt: string;
|
|
146
161
|
}
|
|
147
162
|
|
|
@@ -159,10 +174,12 @@ export interface HandleHookRuntimeInput {
|
|
|
159
174
|
target: CodeAgentHookTarget;
|
|
160
175
|
homeDir: string;
|
|
161
176
|
settings: HookSettings;
|
|
177
|
+
teamRuntimeDisplayMode?: "normal" | "development";
|
|
162
178
|
event: HookEventV1;
|
|
163
179
|
rawPayload: Record<string, unknown>;
|
|
164
180
|
receivedAt?: string;
|
|
165
181
|
environment?: Record<string, string | undefined>;
|
|
182
|
+
runtimeInjectionEnabled?: boolean;
|
|
166
183
|
}
|
|
167
184
|
|
|
168
185
|
const DEFAULT_EVENT_SETTINGS: Record<CanonicalHookEventType, boolean> = {
|
|
@@ -195,6 +212,20 @@ const DEFAULT_EVENT_SETTINGS: Record<CanonicalHookEventType, boolean> = {
|
|
|
195
212
|
const SENSITIVE_TEXT_PATTERN =
|
|
196
213
|
/https?:\/\/\S+|\b(secret|token|password|passwd|private|internal|api[_-]?key|apikey|credential|credentials|\.env)\b/i;
|
|
197
214
|
const SOURCE_LIKE_PATTERN = /\b(function|class|import|export|const|let|var)\b.*[{};]/s;
|
|
215
|
+
const TEAM_MESSAGE_DELIVERY_EVENTS = new Set<CanonicalHookEventType>([
|
|
216
|
+
"SessionStart",
|
|
217
|
+
"UserPromptSubmit",
|
|
218
|
+
"PostToolUse",
|
|
219
|
+
"PostToolUseFailure",
|
|
220
|
+
"Stop",
|
|
221
|
+
"TeammateIdle",
|
|
222
|
+
"SubagentStop",
|
|
223
|
+
"TaskCompleted",
|
|
224
|
+
]);
|
|
225
|
+
const CODEX_STOP_EVENTS_WITHOUT_ADDITIONAL_CONTEXT = new Set<CanonicalHookEventType>([
|
|
226
|
+
"Stop",
|
|
227
|
+
"SubagentStop",
|
|
228
|
+
]);
|
|
198
229
|
|
|
199
230
|
export function createDefaultHookSettings(): HookSettings {
|
|
200
231
|
return {
|
|
@@ -210,8 +241,8 @@ export function createDefaultHookSettings(): HookSettings {
|
|
|
210
241
|
},
|
|
211
242
|
},
|
|
212
243
|
observability: {
|
|
213
|
-
metadataOnly:
|
|
214
|
-
rawPayloadStorage:
|
|
244
|
+
metadataOnly: true,
|
|
245
|
+
rawPayloadStorage: false,
|
|
215
246
|
appendEvents: false,
|
|
216
247
|
},
|
|
217
248
|
learning: {
|
|
@@ -244,8 +275,8 @@ export function parseHookSettings(value: unknown): HookSettings {
|
|
|
244
275
|
codex: parseHookTargetSettings(value.targets, defaults.targets.codex, "codex"),
|
|
245
276
|
},
|
|
246
277
|
observability: {
|
|
247
|
-
metadataOnly:
|
|
248
|
-
rawPayloadStorage:
|
|
278
|
+
metadataOnly: true,
|
|
279
|
+
rawPayloadStorage: false,
|
|
249
280
|
appendEvents: optionalBoolean(
|
|
250
281
|
observability?.appendEvents,
|
|
251
282
|
defaults.observability.appendEvents,
|
|
@@ -277,7 +308,7 @@ export function normalizeHookEvent(input: NormalizeHookEventInput): HookEventV1
|
|
|
277
308
|
pluginId: sanitizeScalar(input.pluginId, redactions),
|
|
278
309
|
agent: sanitizeScalar(input.agent ?? "unknown", redactions),
|
|
279
310
|
sessionIdHash,
|
|
280
|
-
rawPayloadStored:
|
|
311
|
+
rawPayloadStored: false,
|
|
281
312
|
},
|
|
282
313
|
time: {
|
|
283
314
|
occurredAt: optionalSanitizedString(
|
|
@@ -289,7 +320,7 @@ export function normalizeHookEvent(input: NormalizeHookEventInput): HookEventV1
|
|
|
289
320
|
scope: {
|
|
290
321
|
taskId: optionalSanitizedString(input.payload.taskId, redactions),
|
|
291
322
|
projectId: optionalSanitizedString(input.payload.projectId, redactions),
|
|
292
|
-
cwdPolicy: "
|
|
323
|
+
cwdPolicy: "metadata-only",
|
|
293
324
|
projectContextOptedIn: false,
|
|
294
325
|
},
|
|
295
326
|
payload: {
|
|
@@ -297,7 +328,7 @@ export function normalizeHookEvent(input: NormalizeHookEventInput): HookEventV1
|
|
|
297
328
|
metadata,
|
|
298
329
|
redactions,
|
|
299
330
|
redactionCount: redactions.length,
|
|
300
|
-
rawContentIncluded:
|
|
331
|
+
rawContentIncluded: false,
|
|
301
332
|
},
|
|
302
333
|
policy: {
|
|
303
334
|
classification: "local-private",
|
|
@@ -338,8 +369,8 @@ export function formatHookInstallDryRun(plan: HookInstallDryRunPlan): string {
|
|
|
338
369
|
(eventType) => ` - ${eventType}: ${plan.settings.targets[plan.target].events[eventType]}`,
|
|
339
370
|
),
|
|
340
371
|
"Boundaries:",
|
|
341
|
-
" -
|
|
342
|
-
" -
|
|
372
|
+
" - execution events: metadata-only; raw payload/prompt/output/source storage=false",
|
|
373
|
+
" - historical raw trace files may remain for read-only migration compatibility",
|
|
343
374
|
" - learning: emitCandidates=false, writeMemory=false",
|
|
344
375
|
" - external upload: false",
|
|
345
376
|
" - protected project writes: .claude/.codex/CLAUDE.md/AGENTS.md not targeted",
|
|
@@ -438,9 +469,21 @@ export async function handleHookRuntime(input: HandleHookRuntimeInput): Promise<
|
|
|
438
469
|
result = await handleAdditionalContext(input, input.event.type);
|
|
439
470
|
}
|
|
440
471
|
const evolutionDiagnostics = await recordEvolutionTriggerFromHook(input);
|
|
472
|
+
const messageDiagnostics = await deliverPendingTeamMessagesFromHook(input, result);
|
|
473
|
+
const scopedContextDiagnostics = await injectScopedKnowledgeContextFromHook(input, result);
|
|
474
|
+
const teamStateDiagnostics = await recordTeamAgentHookStateFromHook(input);
|
|
441
475
|
return appendRuntimeDiagnostics(
|
|
442
|
-
appendRuntimeDiagnostics(
|
|
443
|
-
|
|
476
|
+
appendRuntimeDiagnostics(
|
|
477
|
+
appendRuntimeDiagnostics(
|
|
478
|
+
appendRuntimeDiagnostics(
|
|
479
|
+
appendRuntimeDiagnostics(result, diagnostics),
|
|
480
|
+
evolutionDiagnostics,
|
|
481
|
+
),
|
|
482
|
+
messageDiagnostics,
|
|
483
|
+
),
|
|
484
|
+
scopedContextDiagnostics,
|
|
485
|
+
),
|
|
486
|
+
teamStateDiagnostics,
|
|
444
487
|
);
|
|
445
488
|
}
|
|
446
489
|
|
|
@@ -568,6 +611,152 @@ async function recordEvolutionTriggerFromHook(
|
|
|
568
611
|
}
|
|
569
612
|
}
|
|
570
613
|
|
|
614
|
+
async function deliverPendingTeamMessagesFromHook(
|
|
615
|
+
input: HandleHookRuntimeInput,
|
|
616
|
+
result: HookRuntimeResult | undefined,
|
|
617
|
+
): Promise<HookRuntimeDiagnostics> {
|
|
618
|
+
if (result === undefined || !canDeliverTeamMessagesFromHook(input.target, input.event.type)) {
|
|
619
|
+
return { stateWrites: [], warnings: [] };
|
|
620
|
+
}
|
|
621
|
+
const team = resolveTraceTeamContext({
|
|
622
|
+
homeDir: input.homeDir,
|
|
623
|
+
environment: input.environment,
|
|
624
|
+
payload: input.rawPayload,
|
|
625
|
+
});
|
|
626
|
+
if (team === null) return { stateWrites: [], warnings: [] };
|
|
627
|
+
|
|
628
|
+
try {
|
|
629
|
+
const messages = await readPendingTeamMessagesForRole({
|
|
630
|
+
homeDir: input.homeDir,
|
|
631
|
+
runId: team.runId,
|
|
632
|
+
roleId: team.roleId,
|
|
633
|
+
limit: 5,
|
|
634
|
+
});
|
|
635
|
+
if (messages.length === 0) return { stateWrites: [], warnings: [] };
|
|
636
|
+
result.output = appendAdditionalContext(
|
|
637
|
+
result.output,
|
|
638
|
+
input.event.type,
|
|
639
|
+
formatTeamInboxContext(messages),
|
|
640
|
+
);
|
|
641
|
+
await markTeamMessagesDelivered({
|
|
642
|
+
homeDir: input.homeDir,
|
|
643
|
+
runId: team.runId,
|
|
644
|
+
roleId: team.roleId,
|
|
645
|
+
messageIds: messages.map((message) => message.messageId),
|
|
646
|
+
now:
|
|
647
|
+
input.receivedAt === undefined || input.receivedAt === "dry-run"
|
|
648
|
+
? undefined
|
|
649
|
+
: new Date(input.receivedAt),
|
|
650
|
+
});
|
|
651
|
+
const teamPaths = resolveTeamRunPaths(input.homeDir);
|
|
652
|
+
return {
|
|
653
|
+
stateWrites: [teamPaths.eventsPath(team.runId), teamPaths.messageListPath(team.runId)],
|
|
654
|
+
warnings: [],
|
|
655
|
+
};
|
|
656
|
+
} catch {
|
|
657
|
+
return {
|
|
658
|
+
stateWrites: [],
|
|
659
|
+
warnings: [
|
|
660
|
+
`Team inbox messages could not be delivered for role ${safeDiagnosticId(team.roleId)}.`,
|
|
661
|
+
],
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
async function injectScopedKnowledgeContextFromHook(
|
|
667
|
+
input: HandleHookRuntimeInput,
|
|
668
|
+
result: HookRuntimeResult | undefined,
|
|
669
|
+
): Promise<HookRuntimeDiagnostics> {
|
|
670
|
+
if (result === undefined || !canDeliverTeamMessagesFromHook(input.target, input.event.type)) {
|
|
671
|
+
return { stateWrites: [], warnings: [] };
|
|
672
|
+
}
|
|
673
|
+
const team = resolveTraceTeamContext({
|
|
674
|
+
homeDir: input.homeDir,
|
|
675
|
+
environment: input.environment,
|
|
676
|
+
payload: input.rawPayload,
|
|
677
|
+
});
|
|
678
|
+
if (team === null || team.roleId !== "main") return { stateWrites: [], warnings: [] };
|
|
679
|
+
|
|
680
|
+
try {
|
|
681
|
+
if (input.runtimeInjectionEnabled === false) return { stateWrites: [], warnings: [] };
|
|
682
|
+
const pack = await createScopedKnowledgeContextPack({
|
|
683
|
+
homeDir: input.homeDir,
|
|
684
|
+
projectKey: team.projectKey,
|
|
685
|
+
roleId: team.roleId,
|
|
686
|
+
});
|
|
687
|
+
if (pack === null) return { stateWrites: [], warnings: [] };
|
|
688
|
+
const sessionKey = resolveHookSessionKey(input.rawPayload);
|
|
689
|
+
if (
|
|
690
|
+
await hasContextInjectionReceipt({
|
|
691
|
+
homeDir: input.homeDir,
|
|
692
|
+
sessionKey,
|
|
693
|
+
contextPackId: pack.id,
|
|
694
|
+
})
|
|
695
|
+
) {
|
|
696
|
+
return { stateWrites: [], warnings: [] };
|
|
697
|
+
}
|
|
698
|
+
const receipt = await writeContextInjectionReceipt({
|
|
699
|
+
homeDir: input.homeDir,
|
|
700
|
+
sessionKey,
|
|
701
|
+
pack,
|
|
702
|
+
trigger: "hook-safe-point",
|
|
703
|
+
hookEventId: input.event.eventId,
|
|
704
|
+
injectedAt: input.receivedAt ?? new Date().toISOString(),
|
|
705
|
+
});
|
|
706
|
+
result.output = appendAdditionalContext(
|
|
707
|
+
result.output,
|
|
708
|
+
input.event.type,
|
|
709
|
+
formatScopedKnowledgePromptBlock(pack),
|
|
710
|
+
);
|
|
711
|
+
return { stateWrites: [receipt.path], warnings: [] };
|
|
712
|
+
} catch {
|
|
713
|
+
return {
|
|
714
|
+
stateWrites: [],
|
|
715
|
+
warnings: ["Scoped knowledge context could not be injected at this hook safe point."],
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
function canDeliverTeamMessagesFromHook(
|
|
721
|
+
target: CodeAgentHookTarget,
|
|
722
|
+
eventType: CanonicalHookEventType,
|
|
723
|
+
): boolean {
|
|
724
|
+
if (!TEAM_MESSAGE_DELIVERY_EVENTS.has(eventType)) return false;
|
|
725
|
+
return target !== "codex" || !CODEX_STOP_EVENTS_WITHOUT_ADDITIONAL_CONTEXT.has(eventType);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
async function recordTeamAgentHookStateFromHook(
|
|
729
|
+
input: HandleHookRuntimeInput,
|
|
730
|
+
): Promise<HookRuntimeDiagnostics> {
|
|
731
|
+
const team = resolveTraceTeamContext({
|
|
732
|
+
homeDir: input.homeDir,
|
|
733
|
+
environment: input.environment,
|
|
734
|
+
payload: input.rawPayload,
|
|
735
|
+
});
|
|
736
|
+
if (team === null) return { stateWrites: [], warnings: [] };
|
|
737
|
+
|
|
738
|
+
try {
|
|
739
|
+
const result = await updateTeamAgentHookState({
|
|
740
|
+
homeDir: input.homeDir,
|
|
741
|
+
runId: team.runId,
|
|
742
|
+
roleId: team.roleId,
|
|
743
|
+
hookEvent: input.event.type,
|
|
744
|
+
now:
|
|
745
|
+
input.receivedAt === undefined || input.receivedAt === "dry-run"
|
|
746
|
+
? undefined
|
|
747
|
+
: new Date(input.receivedAt),
|
|
748
|
+
});
|
|
749
|
+
return { stateWrites: [result.agentPath, result.statusPath], warnings: [] };
|
|
750
|
+
} catch {
|
|
751
|
+
return {
|
|
752
|
+
stateWrites: [],
|
|
753
|
+
warnings: [
|
|
754
|
+
`Team agent state could not be updated for hook role ${safeDiagnosticId(team.roleId)}.`,
|
|
755
|
+
],
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
571
760
|
function appendRuntimeDiagnostics(
|
|
572
761
|
result: HookRuntimeResult | undefined,
|
|
573
762
|
diagnostics: HookRuntimeDiagnostics,
|
|
@@ -583,15 +772,7 @@ function appendRuntimeDiagnostics(
|
|
|
583
772
|
}
|
|
584
773
|
|
|
585
774
|
async function handleSessionStart(input: HandleHookRuntimeInput): Promise<HookRuntimeResult> {
|
|
586
|
-
|
|
587
|
-
const context = [
|
|
588
|
-
"EvoDev session initialized.",
|
|
589
|
-
binding?.contractPath
|
|
590
|
-
? `Active Task Contract: ${binding.contractPath}`
|
|
591
|
-
: "No active Task Contract yet.",
|
|
592
|
-
"User prompts will be routed through EvoDev before execution.",
|
|
593
|
-
].join(" ");
|
|
594
|
-
return createRuntimeResult(input, hookOutput(input.event.type, { additionalContext: context }), {
|
|
775
|
+
return createRuntimeResult(input, null, {
|
|
595
776
|
summary: "Session context prepared.",
|
|
596
777
|
});
|
|
597
778
|
}
|
|
@@ -601,6 +782,17 @@ async function handleUserPromptSubmit(input: HandleHookRuntimeInput): Promise<Ho
|
|
|
601
782
|
const sessionKey = resolveHookSessionKey(input.rawPayload);
|
|
602
783
|
const paths = resolveHookRuntimeSessionPaths({ homeDir: input.homeDir, sessionKey });
|
|
603
784
|
const contract = routeTaskContract(createHookTaskContract(input, classification));
|
|
785
|
+
const previousBinding = await readSessionBinding(input.homeDir, input.rawPayload);
|
|
786
|
+
const teamRuntimeContext =
|
|
787
|
+
previousBinding?.teamRuntimeContextDeliveredAt === undefined ||
|
|
788
|
+
previousBinding.teamRuntimeContextDeliveredAt === null
|
|
789
|
+
? await createTeamRuntimeContextForUserPrompt(input)
|
|
790
|
+
: null;
|
|
791
|
+
const shouldShowDiagnostics = input.teamRuntimeDisplayMode === "development";
|
|
792
|
+
const teamRuntimeContextDeliveredAt =
|
|
793
|
+
teamRuntimeContext !== null && shouldShowDiagnostics
|
|
794
|
+
? (input.receivedAt ?? new Date().toISOString())
|
|
795
|
+
: (previousBinding?.teamRuntimeContextDeliveredAt ?? null);
|
|
604
796
|
const binding: HookRuntimeSessionBinding = {
|
|
605
797
|
version: 1,
|
|
606
798
|
target: input.target,
|
|
@@ -609,28 +801,55 @@ async function handleUserPromptSubmit(input: HandleHookRuntimeInput): Promise<Ho
|
|
|
609
801
|
contractPath: paths.contractPath,
|
|
610
802
|
cwd: optionalPayloadString(input.rawPayload.cwd),
|
|
611
803
|
route: contract.route,
|
|
804
|
+
teamRuntimeContextDeliveredAt,
|
|
612
805
|
updatedAt: input.receivedAt ?? new Date().toISOString(),
|
|
613
806
|
};
|
|
614
807
|
|
|
615
808
|
await writeTaskContract(paths.contractPath, contract, { overwrite: true });
|
|
616
809
|
await writeJsonFile(paths.bindingPath, binding);
|
|
617
810
|
|
|
618
|
-
const
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
811
|
+
const visibleContext = createUserPromptVisibleContext({
|
|
812
|
+
classification,
|
|
813
|
+
contract,
|
|
814
|
+
contractPath: paths.contractPath,
|
|
815
|
+
});
|
|
816
|
+
let output =
|
|
817
|
+
visibleContext === null || !shouldShowDiagnostics
|
|
818
|
+
? null
|
|
819
|
+
: hookOutput(input.event.type, {
|
|
820
|
+
additionalContext: visibleContext,
|
|
821
|
+
});
|
|
822
|
+
if (teamRuntimeContext !== null && shouldShowDiagnostics) {
|
|
823
|
+
output = appendAdditionalContext(output, input.event.type, teamRuntimeContext);
|
|
824
|
+
}
|
|
627
825
|
|
|
628
|
-
return createRuntimeResult(input,
|
|
629
|
-
summary: "User prompt observed
|
|
826
|
+
return createRuntimeResult(input, output, {
|
|
827
|
+
summary: "User prompt observed; Task Contract prepared.",
|
|
630
828
|
stateWrites: [paths.contractPath, paths.bindingPath],
|
|
631
829
|
});
|
|
632
830
|
}
|
|
633
831
|
|
|
832
|
+
async function createTeamRuntimeContextForUserPrompt(
|
|
833
|
+
input: HandleHookRuntimeInput,
|
|
834
|
+
): Promise<string | null> {
|
|
835
|
+
const team = resolveTraceTeamContext({
|
|
836
|
+
homeDir: input.homeDir,
|
|
837
|
+
environment: input.environment,
|
|
838
|
+
payload: input.rawPayload,
|
|
839
|
+
});
|
|
840
|
+
if (team === null || team.roleId !== "main") return null;
|
|
841
|
+
|
|
842
|
+
try {
|
|
843
|
+
return await createTeamRoleRuntimeContext({
|
|
844
|
+
homeDir: input.homeDir,
|
|
845
|
+
runId: team.runId,
|
|
846
|
+
roleId: team.roleId,
|
|
847
|
+
});
|
|
848
|
+
} catch {
|
|
849
|
+
return null;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
634
853
|
async function handlePreToolUse(input: HandleHookRuntimeInput): Promise<HookRuntimeResult> {
|
|
635
854
|
const commandClass =
|
|
636
855
|
typeof input.event.payload.metadata.commandClass === "string"
|
|
@@ -748,6 +967,68 @@ function hookOutput(
|
|
|
748
967
|
};
|
|
749
968
|
}
|
|
750
969
|
|
|
970
|
+
function appendAdditionalContext(
|
|
971
|
+
output: Record<string, unknown> | null,
|
|
972
|
+
eventName: CanonicalHookEventType,
|
|
973
|
+
context: string,
|
|
974
|
+
): Record<string, unknown> {
|
|
975
|
+
if (output === null) return hookOutput(eventName, { additionalContext: context });
|
|
976
|
+
const hookSpecificOutput = isRecord(output.hookSpecificOutput) ? output.hookSpecificOutput : {};
|
|
977
|
+
const previous =
|
|
978
|
+
typeof hookSpecificOutput.additionalContext === "string"
|
|
979
|
+
? hookSpecificOutput.additionalContext
|
|
980
|
+
: "";
|
|
981
|
+
return {
|
|
982
|
+
...output,
|
|
983
|
+
hookSpecificOutput: {
|
|
984
|
+
...hookSpecificOutput,
|
|
985
|
+
hookEventName:
|
|
986
|
+
typeof hookSpecificOutput.hookEventName === "string"
|
|
987
|
+
? hookSpecificOutput.hookEventName
|
|
988
|
+
: eventName,
|
|
989
|
+
additionalContext: previous === "" ? context : `${previous}\n\n${context}`,
|
|
990
|
+
},
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
function formatTeamInboxContext(messages: TeamMessageRecord[]): string {
|
|
995
|
+
const blocks = messages.map((message) =>
|
|
996
|
+
[
|
|
997
|
+
"[EvoDev team message]",
|
|
998
|
+
"Instruction: read this queued team message at this safe point; reply through Teams MCP only when a response is needed.",
|
|
999
|
+
`from: ${message.fromRoleId}`,
|
|
1000
|
+
`to: ${message.toRoleId}`,
|
|
1001
|
+
`type: ${message.type}`,
|
|
1002
|
+
`messageId: ${message.messageId}`,
|
|
1003
|
+
`cc: ${message.ccRoleIds.join(",") || "none"}`,
|
|
1004
|
+
"",
|
|
1005
|
+
truncateTeamMessageBody(message.body),
|
|
1006
|
+
"[/EvoDev team message]",
|
|
1007
|
+
].join("\n"),
|
|
1008
|
+
);
|
|
1009
|
+
return ["EvoDev team inbox:", ...blocks].join("\n\n");
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
function truncateTeamMessageBody(value: string): string {
|
|
1013
|
+
if (value.length <= 4000) return value;
|
|
1014
|
+
return `${value.slice(0, 4000)}...[truncated:${value.length - 4000}]`;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
function createUserPromptVisibleContext(input: {
|
|
1018
|
+
classification: ReturnType<typeof classifyUserPrompt>;
|
|
1019
|
+
contract: TaskContract;
|
|
1020
|
+
contractPath: string;
|
|
1021
|
+
}): string | null {
|
|
1022
|
+
if (!input.classification.needsClarification) return null;
|
|
1023
|
+
return [
|
|
1024
|
+
"EvoDev advisory: clarification may be needed before broad changes.",
|
|
1025
|
+
`Task Contract: ${input.contractPath}`,
|
|
1026
|
+
`Suggested mode: ${input.contract.route.mode ?? "unknown"}`,
|
|
1027
|
+
`Suggested workflow: ${input.contract.route.workflowId ?? "none"}`,
|
|
1028
|
+
`Reason: ${input.contract.route.rationale}`,
|
|
1029
|
+
].join(" ");
|
|
1030
|
+
}
|
|
1031
|
+
|
|
751
1032
|
function createHookTaskContract(
|
|
752
1033
|
input: HandleHookRuntimeInput,
|
|
753
1034
|
classification: ReturnType<typeof classifyUserPrompt>,
|
|
@@ -756,7 +1037,7 @@ function createHookTaskContract(
|
|
|
756
1037
|
const targetName = formatHookTargetName(input.target);
|
|
757
1038
|
const contract = createTaskContract({
|
|
758
1039
|
title: `${targetName} hook task ${sessionKey}`,
|
|
759
|
-
summary: `${targetName} prompt classified as ${classification.kind}; raw prompt is
|
|
1040
|
+
summary: `${targetName} prompt classified as ${classification.kind}; raw prompt is not stored by EvoDev.`,
|
|
760
1041
|
projectId: null,
|
|
761
1042
|
});
|
|
762
1043
|
|
|
@@ -927,9 +1208,7 @@ function extractMetadata(
|
|
|
927
1208
|
payload: Record<string, unknown>,
|
|
928
1209
|
redactions: string[],
|
|
929
1210
|
): Record<string, string | number | boolean | string[]> {
|
|
930
|
-
const metadata: Record<string, string | number | boolean | string[]> = {
|
|
931
|
-
rawContentIncluded: true,
|
|
932
|
-
};
|
|
1211
|
+
const metadata: Record<string, string | number | boolean | string[]> = {};
|
|
933
1212
|
const toolInput = isRecord(payload.tool_input)
|
|
934
1213
|
? payload.tool_input
|
|
935
1214
|
: isRecord(payload.toolInput)
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export * from "./agents/index.ts";
|
|
2
2
|
export * from "./assets/index.ts";
|
|
3
|
+
export * from "./code-agent-traces/index.ts";
|
|
3
4
|
export * from "./config/index.ts";
|
|
4
5
|
export * from "./daemon/index.ts";
|
|
5
6
|
export * from "./evolution/index.ts";
|
|
6
7
|
export * from "./hooks/index.ts";
|
|
8
|
+
export * from "./knowledge/index.ts";
|
|
7
9
|
export * from "./learning/index.ts";
|
|
8
10
|
export * from "./observability/index.ts";
|
|
9
11
|
export * from "./pack/index.ts";
|