@evo-dev/core 0.0.1-alpha.12 → 0.0.1-alpha.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/dist/config/index.js +400 -47
- package/dist/index.js +6424 -5987
- package/package.json +1 -1
- package/src/evolution/knowledge/index.ts +93 -18
- package/src/projects/index.ts +490 -9
- package/src/runtime-logs/index.ts +96 -1
package/package.json
CHANGED
|
@@ -3,6 +3,11 @@ import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
|
3
3
|
import { mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
4
4
|
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
5
5
|
import { resolveEvoDevPaths } from "../../config/paths.ts";
|
|
6
|
+
import {
|
|
7
|
+
canonicalizeProjectKey,
|
|
8
|
+
listEquivalentProjectKeys,
|
|
9
|
+
listProjectAliases,
|
|
10
|
+
} from "../../projects/index.ts";
|
|
6
11
|
import { createStableId, normalizeTimestamp } from "../../utils/index.ts";
|
|
7
12
|
import { listEvolutionEvosCases } from "../candidates/index.ts";
|
|
8
13
|
import {
|
|
@@ -377,6 +382,7 @@ interface OkfPaths {
|
|
|
377
382
|
|
|
378
383
|
interface KnowledgeQueryScope {
|
|
379
384
|
projectKey?: string;
|
|
385
|
+
projectKeys?: string[];
|
|
380
386
|
roleId?: string;
|
|
381
387
|
workflowId?: string;
|
|
382
388
|
paths: string[];
|
|
@@ -2367,6 +2373,13 @@ export async function listOkfKnowledgeConcepts(input: {
|
|
|
2367
2373
|
}): Promise<OkfKnowledgeConcept[]> {
|
|
2368
2374
|
const okfDir = resolveOkfKnowledgePaths(input.homeDir).okfDir;
|
|
2369
2375
|
if (!(await pathExists(okfDir))) return [];
|
|
2376
|
+
const equivalentProjectKeys =
|
|
2377
|
+
input.projectKey === undefined
|
|
2378
|
+
? undefined
|
|
2379
|
+
: await listEquivalentProjectKeys({
|
|
2380
|
+
homeDir: input.homeDir,
|
|
2381
|
+
projectKey: input.projectKey,
|
|
2382
|
+
});
|
|
2370
2383
|
const files = await listMarkdownFiles(okfDir);
|
|
2371
2384
|
const concepts: OkfKnowledgeConcept[] = [];
|
|
2372
2385
|
for (const file of files) {
|
|
@@ -2376,7 +2389,7 @@ export async function listOkfKnowledgeConcepts(input: {
|
|
|
2376
2389
|
if (parsed !== null) concepts.push(parsed);
|
|
2377
2390
|
}
|
|
2378
2391
|
return concepts
|
|
2379
|
-
.filter((concept) => matchesConceptFilters(concept, input))
|
|
2392
|
+
.filter((concept) => matchesConceptFilters(concept, input, equivalentProjectKeys))
|
|
2380
2393
|
.sort((left, right) => left.id.localeCompare(right.id));
|
|
2381
2394
|
}
|
|
2382
2395
|
|
|
@@ -2406,7 +2419,7 @@ export async function queryOkfKnowledge(input: {
|
|
|
2406
2419
|
now?: string | Date;
|
|
2407
2420
|
}): Promise<OkfKnowledgeQueryResult> {
|
|
2408
2421
|
const okfDir = resolveOkfKnowledgePaths(input.homeDir).okfDir;
|
|
2409
|
-
const scope = normalizeKnowledgeQueryScope(input);
|
|
2422
|
+
const scope = await normalizeKnowledgeQueryScope(input);
|
|
2410
2423
|
const queryText = normalizeKnowledgeQueryText(input.queryText);
|
|
2411
2424
|
const now = normalizeQueryNow(input.now);
|
|
2412
2425
|
const warnings: string[] = [];
|
|
@@ -2705,17 +2718,39 @@ export async function queryScopedOkfKnowledgeContext(input: {
|
|
|
2705
2718
|
now?: string | Date;
|
|
2706
2719
|
}): Promise<OkfKnowledgeQueryResult> {
|
|
2707
2720
|
const result = await queryOkfKnowledge(input);
|
|
2708
|
-
const
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2721
|
+
const equivalentProjectKeys =
|
|
2722
|
+
result.projectKey === undefined
|
|
2723
|
+
? [undefined]
|
|
2724
|
+
: await listEquivalentProjectKeys({
|
|
2725
|
+
homeDir: input.homeDir,
|
|
2726
|
+
projectKey: result.projectKey,
|
|
2727
|
+
});
|
|
2728
|
+
const evosResults = await Promise.all(
|
|
2729
|
+
equivalentProjectKeys.map((projectKey) =>
|
|
2730
|
+
listEvolutionEvosCases({
|
|
2731
|
+
homeDir: input.homeDir,
|
|
2732
|
+
...(projectKey === undefined ? {} : { projectKey }),
|
|
2733
|
+
roleId: input.roleId,
|
|
2734
|
+
reviewStates: ["accepted", "auto-accepted"],
|
|
2735
|
+
}),
|
|
2736
|
+
),
|
|
2737
|
+
);
|
|
2738
|
+
const evosCases = {
|
|
2739
|
+
cases: [
|
|
2740
|
+
...new Map(
|
|
2741
|
+
evosResults
|
|
2742
|
+
.flatMap((entry) => entry.cases)
|
|
2743
|
+
.map((evosCase) => [`${evosCase.projectKey}\0${evosCase.id}`, evosCase]),
|
|
2744
|
+
).values(),
|
|
2745
|
+
],
|
|
2746
|
+
warnings: [...new Set(evosResults.flatMap((entry) => entry.warnings))],
|
|
2747
|
+
};
|
|
2714
2748
|
return mergeAcceptedEvosCasesIntoKnowledgeQuery(
|
|
2715
2749
|
result,
|
|
2716
2750
|
evosCases.cases,
|
|
2717
2751
|
evosCases.warnings,
|
|
2718
2752
|
input.limit,
|
|
2753
|
+
equivalentProjectKeys.flatMap((projectKey) => (projectKey === undefined ? [] : [projectKey])),
|
|
2719
2754
|
);
|
|
2720
2755
|
}
|
|
2721
2756
|
|
|
@@ -2724,6 +2759,7 @@ export function mergeAcceptedEvosCasesIntoKnowledgeQuery(
|
|
|
2724
2759
|
cases: EvolutionEvosCase[],
|
|
2725
2760
|
warnings: string[] = [],
|
|
2726
2761
|
limit?: number,
|
|
2762
|
+
equivalentProjectKeys: string[] = [],
|
|
2727
2763
|
): OkfKnowledgeQueryResult {
|
|
2728
2764
|
const startRank = result.items.length + 1;
|
|
2729
2765
|
const evosItems = cases.flatMap<OkfKnowledgeContextItem>((evosCase, index) => {
|
|
@@ -2738,8 +2774,10 @@ export function mergeAcceptedEvosCasesIntoKnowledgeQuery(
|
|
|
2738
2774
|
: []),
|
|
2739
2775
|
];
|
|
2740
2776
|
const structuredScore =
|
|
2741
|
-
(result.projectKey !== undefined &&
|
|
2742
|
-
|
|
2777
|
+
(result.projectKey !== undefined &&
|
|
2778
|
+
[result.projectKey, ...equivalentProjectKeys].includes(evosCase.projectKey)
|
|
2779
|
+
? 100
|
|
2780
|
+
: 0) + (result.roleId !== undefined && evosCase.roleTags.includes(result.roleId) ? 100 : 0);
|
|
2743
2781
|
return [
|
|
2744
2782
|
{
|
|
2745
2783
|
id: evosCase.id,
|
|
@@ -4107,12 +4145,16 @@ function parseOkfConceptFile(
|
|
|
4107
4145
|
function matchesConceptFilters(
|
|
4108
4146
|
concept: OkfKnowledgeConcept,
|
|
4109
4147
|
input: { projectKey?: string; roleId?: string; workflowId?: string; paths?: string[] },
|
|
4148
|
+
equivalentProjectKeys?: string[],
|
|
4110
4149
|
): boolean {
|
|
4150
|
+
const projectKeys = (equivalentProjectKeys ?? []).map(sanitizeSlug);
|
|
4111
4151
|
if (
|
|
4112
4152
|
input.projectKey !== undefined &&
|
|
4113
4153
|
concept.repoTags.length > 0 &&
|
|
4114
|
-
!
|
|
4115
|
-
|
|
4154
|
+
![sanitizeSlug(input.projectKey), ...projectKeys].some(
|
|
4155
|
+
(projectKey) =>
|
|
4156
|
+
concept.repoTags.includes(projectKey) || concept.tags.includes(`repo:${projectKey}`),
|
|
4157
|
+
)
|
|
4116
4158
|
) {
|
|
4117
4159
|
return false;
|
|
4118
4160
|
}
|
|
@@ -4140,14 +4182,40 @@ function matchesConceptFilters(
|
|
|
4140
4182
|
return true;
|
|
4141
4183
|
}
|
|
4142
4184
|
|
|
4143
|
-
function normalizeKnowledgeQueryScope(input: {
|
|
4185
|
+
async function normalizeKnowledgeQueryScope(input: {
|
|
4186
|
+
homeDir: string;
|
|
4144
4187
|
projectKey?: string;
|
|
4145
4188
|
roleId?: string;
|
|
4146
4189
|
workflowId?: string;
|
|
4147
4190
|
paths?: string[];
|
|
4148
|
-
}): KnowledgeQueryScope {
|
|
4191
|
+
}): Promise<KnowledgeQueryScope> {
|
|
4192
|
+
const aliases =
|
|
4193
|
+
input.projectKey === undefined
|
|
4194
|
+
? {}
|
|
4195
|
+
: await listProjectAliases({
|
|
4196
|
+
homeDir: input.homeDir,
|
|
4197
|
+
});
|
|
4198
|
+
const requestedProjectKey =
|
|
4199
|
+
input.projectKey === undefined ? undefined : sanitizeSlug(input.projectKey);
|
|
4200
|
+
const projectKey =
|
|
4201
|
+
requestedProjectKey === undefined
|
|
4202
|
+
? undefined
|
|
4203
|
+
: canonicalizeProjectKey(requestedProjectKey, aliases);
|
|
4204
|
+
const projectKeys =
|
|
4205
|
+
projectKey === undefined
|
|
4206
|
+
? undefined
|
|
4207
|
+
: [
|
|
4208
|
+
...new Set([
|
|
4209
|
+
projectKey,
|
|
4210
|
+
requestedProjectKey ?? projectKey,
|
|
4211
|
+
...Object.keys(aliases).filter(
|
|
4212
|
+
(alias) => canonicalizeProjectKey(alias, aliases) === projectKey,
|
|
4213
|
+
),
|
|
4214
|
+
]),
|
|
4215
|
+
].map(sanitizeSlug);
|
|
4149
4216
|
return {
|
|
4150
|
-
projectKey
|
|
4217
|
+
projectKey,
|
|
4218
|
+
projectKeys,
|
|
4151
4219
|
roleId: input.roleId === undefined ? undefined : sanitizeSlug(input.roleId),
|
|
4152
4220
|
workflowId: input.workflowId === undefined ? undefined : sanitizeSlug(input.workflowId),
|
|
4153
4221
|
paths: (input.paths ?? []).flatMap((path) => {
|
|
@@ -4368,8 +4436,10 @@ function matchOkfConceptForContext(
|
|
|
4368
4436
|
|
|
4369
4437
|
const repoTags = collectScopedTags(concept, "repo");
|
|
4370
4438
|
if (scope.projectKey !== undefined) {
|
|
4371
|
-
|
|
4372
|
-
|
|
4439
|
+
const projectKeys = scope.projectKeys ?? [scope.projectKey];
|
|
4440
|
+
const matchedProjectKey = projectKeys.find((projectKey) => repoTags.includes(projectKey));
|
|
4441
|
+
if (repoTags.length > 0 && matchedProjectKey === undefined) return null;
|
|
4442
|
+
if (matchedProjectKey !== undefined) {
|
|
4373
4443
|
reasons.push(`repo:${scope.projectKey}`);
|
|
4374
4444
|
exactMatches += 1;
|
|
4375
4445
|
}
|
|
@@ -4441,7 +4511,12 @@ function matchOverlayScope(
|
|
|
4441
4511
|
): "repo" | "role" | "workflow" | "none" | null {
|
|
4442
4512
|
const [root, id] = conceptId.split("/");
|
|
4443
4513
|
if (root === "repos") {
|
|
4444
|
-
if (
|
|
4514
|
+
if (
|
|
4515
|
+
scope.projectKey !== undefined &&
|
|
4516
|
+
!(scope.projectKeys ?? [scope.projectKey]).includes(id ?? "")
|
|
4517
|
+
) {
|
|
4518
|
+
return null;
|
|
4519
|
+
}
|
|
4445
4520
|
return scope.projectKey === undefined ? "none" : "repo";
|
|
4446
4521
|
}
|
|
4447
4522
|
if (root === "roles") {
|