@xera-ai/core 0.11.0 → 0.11.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/dist/bin/internal.js +11 -8
- package/package.json +3 -3
- package/src/graph/enrich.ts +25 -10
package/dist/bin/internal.js
CHANGED
|
@@ -10910,7 +10910,7 @@ init_graph_backfill();
|
|
|
10910
10910
|
// src/graph/enrich.ts
|
|
10911
10911
|
init_store();
|
|
10912
10912
|
init_ulid();
|
|
10913
|
-
import { existsSync as existsSync22, readFileSync as readFileSync19 } from "fs";
|
|
10913
|
+
import { existsSync as existsSync22, readFileSync as readFileSync19, unlinkSync as unlinkSync2 } from "fs";
|
|
10914
10914
|
import { join as join21 } from "path";
|
|
10915
10915
|
import { z as z8 } from "zod";
|
|
10916
10916
|
var MAX_SIMILAR_EDGES = 10;
|
|
@@ -10933,6 +10933,13 @@ var mk2 = (actor, type, payload) => ({
|
|
|
10933
10933
|
payload
|
|
10934
10934
|
});
|
|
10935
10935
|
async function enrichTicket(repoRoot, ticketId, opts) {
|
|
10936
|
+
const snapshot = deriveSnapshot(loadAllEvents(repoRoot));
|
|
10937
|
+
if (!snapshot.tickets[ticketId]) {
|
|
10938
|
+
throw new Error(`ticket ${ticketId} not in graph; fetch it first with \`/xera-fetch ${ticketId}\``);
|
|
10939
|
+
}
|
|
10940
|
+
if (snapshot.tickets[ticketId].enrichedAt && !opts.force) {
|
|
10941
|
+
return { ticketId, similarCount: 0, enrichedAt: snapshot.tickets[ticketId].enrichedAt };
|
|
10942
|
+
}
|
|
10936
10943
|
const inputPath = join21(repoRoot, ".xera", ticketId, "enrichment-input.json");
|
|
10937
10944
|
if (!existsSync22(inputPath)) {
|
|
10938
10945
|
throw new Error(`enrichment-input.json not found at ${inputPath}`);
|
|
@@ -10942,13 +10949,6 @@ async function enrichTicket(repoRoot, ticketId, opts) {
|
|
|
10942
10949
|
if (!parsed.success) {
|
|
10943
10950
|
throw new Error(`invalid enrichment-input.json: ${parsed.error.message}`);
|
|
10944
10951
|
}
|
|
10945
|
-
const snapshot = deriveSnapshot(loadAllEvents(repoRoot));
|
|
10946
|
-
if (!snapshot.tickets[ticketId]) {
|
|
10947
|
-
throw new Error(`ticket ${ticketId} not in graph; run /xera-fetch first`);
|
|
10948
|
-
}
|
|
10949
|
-
if (snapshot.tickets[ticketId].enrichedAt && !opts.force) {
|
|
10950
|
-
return { ticketId, similarCount: 0, enrichedAt: snapshot.tickets[ticketId].enrichedAt };
|
|
10951
|
-
}
|
|
10952
10952
|
const validated = parsed.data.similar.map((s) => ({ ...s, confidence: Math.max(0, Math.min(1, s.confidence)) })).filter((s) => s.confidence >= MIN_CONFIDENCE).filter((s) => snapshot.tickets[s.ticketId] !== undefined).filter((s) => s.ticketId !== ticketId).slice(0, MAX_SIMILAR_EDGES);
|
|
10953
10953
|
const events = [];
|
|
10954
10954
|
for (const s of validated) {
|
|
@@ -10969,6 +10969,9 @@ async function enrichTicket(repoRoot, ticketId, opts) {
|
|
|
10969
10969
|
};
|
|
10970
10970
|
events.push(mk2("graph-enrich", "ticket.enriched", enrichedPayload));
|
|
10971
10971
|
appendEvents(repoRoot, events, { skill: "graph-enrich", ticketId });
|
|
10972
|
+
try {
|
|
10973
|
+
unlinkSync2(inputPath);
|
|
10974
|
+
} catch {}
|
|
10972
10975
|
return { ticketId, similarCount: validated.length, enrichedAt };
|
|
10973
10976
|
}
|
|
10974
10977
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xera-ai/core",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"zod": "4.4.3",
|
|
34
|
-
"@xera-ai/web": "^0.11.
|
|
35
|
-
"@xera-ai/http": "^0.11.
|
|
34
|
+
"@xera-ai/web": "^0.11.2",
|
|
35
|
+
"@xera-ai/http": "^0.11.2",
|
|
36
36
|
"@playwright/test": "1.60.0",
|
|
37
37
|
"dotenv": "^16.0.0",
|
|
38
38
|
"fflate": "0.8.3",
|
package/src/graph/enrich.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
1
|
+
import { existsSync, readFileSync, unlinkSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { appendEvents, deriveSnapshot, loadAllEvents } from './store';
|
|
@@ -50,6 +50,22 @@ export async function enrichTicket(
|
|
|
50
50
|
ticketId: string,
|
|
51
51
|
opts: EnrichOptions,
|
|
52
52
|
): Promise<EnrichResult> {
|
|
53
|
+
// Check the graph snapshot first so a missing ticket surfaces as the
|
|
54
|
+
// actionable "fetch it first" error instead of a confusing
|
|
55
|
+
// "enrichment-input.json not found" — the input file may live under
|
|
56
|
+
// .xera/<CANDIDATE>/, a directory that doesn't exist until the
|
|
57
|
+
// candidate has been fetched.
|
|
58
|
+
const snapshot = deriveSnapshot(loadAllEvents(repoRoot));
|
|
59
|
+
if (!snapshot.tickets[ticketId]) {
|
|
60
|
+
throw new Error(
|
|
61
|
+
`ticket ${ticketId} not in graph; fetch it first with \`/xera-fetch ${ticketId}\``,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (snapshot.tickets[ticketId]!.enrichedAt && !opts.force) {
|
|
66
|
+
return { ticketId, similarCount: 0, enrichedAt: snapshot.tickets[ticketId]!.enrichedAt! };
|
|
67
|
+
}
|
|
68
|
+
|
|
53
69
|
const inputPath = join(repoRoot, '.xera', ticketId, 'enrichment-input.json');
|
|
54
70
|
if (!existsSync(inputPath)) {
|
|
55
71
|
throw new Error(`enrichment-input.json not found at ${inputPath}`);
|
|
@@ -61,15 +77,6 @@ export async function enrichTicket(
|
|
|
61
77
|
throw new Error(`invalid enrichment-input.json: ${parsed.error.message}`);
|
|
62
78
|
}
|
|
63
79
|
|
|
64
|
-
const snapshot = deriveSnapshot(loadAllEvents(repoRoot));
|
|
65
|
-
if (!snapshot.tickets[ticketId]) {
|
|
66
|
-
throw new Error(`ticket ${ticketId} not in graph; run /xera-fetch first`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (snapshot.tickets[ticketId]!.enrichedAt && !opts.force) {
|
|
70
|
-
return { ticketId, similarCount: 0, enrichedAt: snapshot.tickets[ticketId]!.enrichedAt! };
|
|
71
|
-
}
|
|
72
|
-
|
|
73
80
|
const validated = parsed.data.similar
|
|
74
81
|
.map((s) => ({ ...s, confidence: Math.max(0, Math.min(1, s.confidence)) }))
|
|
75
82
|
.filter((s) => s.confidence >= MIN_CONFIDENCE)
|
|
@@ -99,5 +106,13 @@ export async function enrichTicket(
|
|
|
99
106
|
|
|
100
107
|
appendEvents(repoRoot, events, { skill: 'graph-enrich', ticketId });
|
|
101
108
|
|
|
109
|
+
// Consumed — remove so a stale file can't accidentally re-drive enrich
|
|
110
|
+
// on a later invocation outside the /xera-report skill flow.
|
|
111
|
+
try {
|
|
112
|
+
unlinkSync(inputPath);
|
|
113
|
+
} catch {
|
|
114
|
+
// Best-effort cleanup; ignore if already gone.
|
|
115
|
+
}
|
|
116
|
+
|
|
102
117
|
return { ticketId, similarCount: validated.length, enrichedAt };
|
|
103
118
|
}
|