@evo-dev/core 0.0.1-alpha.19 → 0.0.1-alpha.20
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/dist/config/index.js +59 -8
- package/dist/index.js +803 -230
- package/package.json +1 -1
- package/src/evolution/evidence/session-memory/retention.ts +359 -78
- package/src/evolution/evidence/session-memory/segment.ts +15 -1
- package/src/evolution/evidence/session-memory/storage.ts +37 -6
- package/src/evolution/evidence/session-memory/types.ts +5 -2
- package/src/evolution/evidence/session-memory/updater.ts +23 -15
- package/src/evolution/knowledge/changes.ts +6 -0
- package/src/evolution/knowledge/freshness.ts +17 -57
- package/src/evolution/knowledge/index.ts +204 -12
- package/src/evolution/knowledge/support.ts +135 -0
- package/src/hooks/index.ts +124 -20
package/src/hooks/index.ts
CHANGED
|
@@ -8,13 +8,14 @@ import {
|
|
|
8
8
|
createScopedKnowledgeContextPack,
|
|
9
9
|
formatScopedKnowledgePromptBlock,
|
|
10
10
|
hasContextInjectionReceipt,
|
|
11
|
+
recordContextInjectionOutcome,
|
|
11
12
|
writeContextInjectionReceipt,
|
|
12
13
|
} from "../evolution/knowledge/index.ts";
|
|
13
14
|
import {
|
|
14
15
|
enqueueEvolutionTrigger,
|
|
15
16
|
resolveEvolutionTriggerDecision,
|
|
16
17
|
} from "../evolution/triggers/index.ts";
|
|
17
|
-
import { recordDiscoveredProject } from "../projects/index.ts";
|
|
18
|
+
import { recordDiscoveredProject, resolveProjectWorkspaceFromCwd } from "../projects/index.ts";
|
|
18
19
|
import { resolveTraceSessionKey, resolveTraceTeamContext } from "../runtime-logs/index.ts";
|
|
19
20
|
import {
|
|
20
21
|
type TeamMessageRecord,
|
|
@@ -156,6 +157,7 @@ export interface HookRuntimeSessionBinding {
|
|
|
156
157
|
sessionKey: string;
|
|
157
158
|
cwd: string | null;
|
|
158
159
|
teamRuntimeContextDeliveredAt?: string | null;
|
|
160
|
+
knowledgeContextDeliveredAt?: string | null;
|
|
159
161
|
updatedAt: string;
|
|
160
162
|
}
|
|
161
163
|
|
|
@@ -488,26 +490,20 @@ export async function handleHookRuntime(input: HandleHookRuntimeInput): Promise<
|
|
|
488
490
|
: await recordEvolutionTriggerFromHook(input);
|
|
489
491
|
const messageDiagnostics = await deliverPendingTeamMessagesFromHook(input, result);
|
|
490
492
|
const scopedContextDiagnostics = await injectScopedKnowledgeContextFromHook(input, result);
|
|
493
|
+
const knowledgeOutcomeDiagnostics = await recordKnowledgeOutcomeFromHook(input);
|
|
491
494
|
const teamStateDiagnostics = await recordTeamAgentHookStateFromHook(input);
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
),
|
|
501
|
-
sessionMemoryDiagnostics,
|
|
502
|
-
),
|
|
503
|
-
evolutionDiagnostics,
|
|
504
|
-
),
|
|
505
|
-
messageDiagnostics,
|
|
506
|
-
),
|
|
507
|
-
scopedContextDiagnostics,
|
|
508
|
-
),
|
|
495
|
+
let completed = appendRuntimeDiagnostics(result, diagnostics);
|
|
496
|
+
for (const entry of [
|
|
497
|
+
projectDiagnostics,
|
|
498
|
+
sessionMemoryDiagnostics,
|
|
499
|
+
evolutionDiagnostics,
|
|
500
|
+
messageDiagnostics,
|
|
501
|
+
scopedContextDiagnostics,
|
|
502
|
+
knowledgeOutcomeDiagnostics,
|
|
509
503
|
teamStateDiagnostics,
|
|
510
|
-
)
|
|
504
|
+
]) {
|
|
505
|
+
completed = appendRuntimeDiagnostics(completed, entry);
|
|
506
|
+
}
|
|
511
507
|
return appendDevelopmentHookDiagnostics(input, completed);
|
|
512
508
|
}
|
|
513
509
|
|
|
@@ -765,7 +761,8 @@ async function injectScopedKnowledgeContextFromHook(
|
|
|
765
761
|
environment: input.environment,
|
|
766
762
|
payload: input.rawPayload,
|
|
767
763
|
});
|
|
768
|
-
if (team === null
|
|
764
|
+
if (team === null) return injectOrdinarySessionKnowledge(input, result);
|
|
765
|
+
if (team.roleId !== "main") return { stateWrites: [], warnings: [] };
|
|
769
766
|
|
|
770
767
|
try {
|
|
771
768
|
if (input.runtimeInjectionEnabled === false) return { stateWrites: [], warnings: [] };
|
|
@@ -807,6 +804,112 @@ async function injectScopedKnowledgeContextFromHook(
|
|
|
807
804
|
}
|
|
808
805
|
}
|
|
809
806
|
|
|
807
|
+
async function injectOrdinarySessionKnowledge(
|
|
808
|
+
input: HandleHookRuntimeInput,
|
|
809
|
+
result: HookRuntimeResult,
|
|
810
|
+
): Promise<HookRuntimeDiagnostics> {
|
|
811
|
+
if (input.event.type !== "UserPromptSubmit" || input.runtimeInjectionEnabled === false) {
|
|
812
|
+
return { stateWrites: [], warnings: [] };
|
|
813
|
+
}
|
|
814
|
+
const cwd = optionalPayloadString(input.rawPayload.cwd);
|
|
815
|
+
if (cwd === null) return { stateWrites: [], warnings: [] };
|
|
816
|
+
const sessionKey = resolveHookSessionKey(input.rawPayload);
|
|
817
|
+
const paths = resolveHookRuntimeSessionPaths({ homeDir: input.homeDir, sessionKey });
|
|
818
|
+
const binding = await readSessionBinding(input.homeDir, input.rawPayload);
|
|
819
|
+
if (
|
|
820
|
+
binding?.knowledgeContextDeliveredAt !== undefined &&
|
|
821
|
+
binding.knowledgeContextDeliveredAt !== null
|
|
822
|
+
) {
|
|
823
|
+
return { stateWrites: [], warnings: [] };
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
try {
|
|
827
|
+
const workspace = await resolveProjectWorkspaceFromCwd({ homeDir: input.homeDir, cwd });
|
|
828
|
+
if (workspace === null) return { stateWrites: [], warnings: [] };
|
|
829
|
+
const queryText = readKnowledgeQueryText(input.rawPayload);
|
|
830
|
+
const pack = await createScopedKnowledgeContextPack({
|
|
831
|
+
homeDir: input.homeDir,
|
|
832
|
+
projectKey: workspace.projectKey,
|
|
833
|
+
roleId: input.target,
|
|
834
|
+
...(queryText === null ? {} : { queryText }),
|
|
835
|
+
limit: 3,
|
|
836
|
+
inlineOnly: true,
|
|
837
|
+
});
|
|
838
|
+
const deliveredAt = input.receivedAt ?? new Date().toISOString();
|
|
839
|
+
const nextBinding: HookRuntimeSessionBinding = {
|
|
840
|
+
version: 1,
|
|
841
|
+
target: input.target,
|
|
842
|
+
sessionKey,
|
|
843
|
+
cwd,
|
|
844
|
+
teamRuntimeContextDeliveredAt: binding?.teamRuntimeContextDeliveredAt ?? null,
|
|
845
|
+
knowledgeContextDeliveredAt: deliveredAt,
|
|
846
|
+
updatedAt: deliveredAt,
|
|
847
|
+
};
|
|
848
|
+
await writeJsonFile(paths.bindingPath, nextBinding);
|
|
849
|
+
if (pack === null) return { stateWrites: [paths.bindingPath], warnings: [] };
|
|
850
|
+
const receipt = await writeContextInjectionReceipt({
|
|
851
|
+
homeDir: input.homeDir,
|
|
852
|
+
sessionKey,
|
|
853
|
+
pack,
|
|
854
|
+
trigger: "ordinary-session",
|
|
855
|
+
hookEventId: input.event.eventId,
|
|
856
|
+
injectedAt: deliveredAt,
|
|
857
|
+
});
|
|
858
|
+
result.output = appendAdditionalContext(
|
|
859
|
+
result.output,
|
|
860
|
+
input.event.type,
|
|
861
|
+
formatScopedKnowledgePromptBlock(pack),
|
|
862
|
+
);
|
|
863
|
+
return { stateWrites: [paths.bindingPath, receipt.path], warnings: [] };
|
|
864
|
+
} catch {
|
|
865
|
+
return {
|
|
866
|
+
stateWrites: [],
|
|
867
|
+
warnings: ["Ordinary-session knowledge context could not be injected."],
|
|
868
|
+
};
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
function readKnowledgeQueryText(payload: Record<string, unknown>): string | null {
|
|
873
|
+
for (const value of [
|
|
874
|
+
payload.prompt,
|
|
875
|
+
payload.user_prompt,
|
|
876
|
+
payload.userPrompt,
|
|
877
|
+
payload.query,
|
|
878
|
+
payload.message,
|
|
879
|
+
payload.text,
|
|
880
|
+
]) {
|
|
881
|
+
if (typeof value === "string" && value.trim() !== "") return value.trim().slice(0, 4_000);
|
|
882
|
+
}
|
|
883
|
+
return null;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
async function recordKnowledgeOutcomeFromHook(
|
|
887
|
+
input: HandleHookRuntimeInput,
|
|
888
|
+
): Promise<HookRuntimeDiagnostics> {
|
|
889
|
+
if (!isKnowledgeOutcomeSignal(input.event)) return { stateWrites: [], warnings: [] };
|
|
890
|
+
try {
|
|
891
|
+
const paths = await recordContextInjectionOutcome({
|
|
892
|
+
homeDir: input.homeDir,
|
|
893
|
+
sessionKey: resolveHookSessionKey(input.rawPayload),
|
|
894
|
+
eventId: input.event.eventId,
|
|
895
|
+
observedAt: input.receivedAt ?? input.event.time.receivedAt ?? new Date().toISOString(),
|
|
896
|
+
summary: input.event.payload.summary,
|
|
897
|
+
});
|
|
898
|
+
return { stateWrites: paths, warnings: [] };
|
|
899
|
+
} catch {
|
|
900
|
+
return {
|
|
901
|
+
stateWrites: [],
|
|
902
|
+
warnings: ["Knowledge delivery outcome metadata could not be recorded."],
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
function isKnowledgeOutcomeSignal(event: HookEventV1): boolean {
|
|
908
|
+
if (event.type !== "PostToolUse") return false;
|
|
909
|
+
if (event.payload.metadata.commandClass === "test-command") return true;
|
|
910
|
+
return /\b(?:test|lint|typecheck|build|verify|check)\b/iu.test(event.payload.summary);
|
|
911
|
+
}
|
|
912
|
+
|
|
810
913
|
function canDeliverTeamMessagesFromHook(
|
|
811
914
|
target: CodeAgentHookTarget,
|
|
812
915
|
eventType: CanonicalHookEventType,
|
|
@@ -886,6 +989,7 @@ async function handleUserPromptSubmit(input: HandleHookRuntimeInput): Promise<Ho
|
|
|
886
989
|
sessionKey,
|
|
887
990
|
cwd: optionalPayloadString(input.rawPayload.cwd),
|
|
888
991
|
teamRuntimeContextDeliveredAt,
|
|
992
|
+
knowledgeContextDeliveredAt: previousBinding?.knowledgeContextDeliveredAt ?? null,
|
|
889
993
|
updatedAt: input.receivedAt ?? new Date().toISOString(),
|
|
890
994
|
};
|
|
891
995
|
|