keywordgraph-mcp-server 1.7.4 → 1.8.5
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/README.md +73 -8
- package/dist/api/client.d.ts +3 -1
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +2 -1
- package/dist/api/client.js.map +1 -1
- package/dist/api/config-store.d.ts +11 -0
- package/dist/api/config-store.d.ts.map +1 -1
- package/dist/api/config-store.js +7 -0
- package/dist/api/config-store.js.map +1 -1
- package/dist/config/brand.d.ts.map +1 -1
- package/dist/config/brand.js +11 -0
- package/dist/config/brand.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +83 -6
- package/dist/index.js.map +1 -1
- package/dist/instructions.d.ts.map +1 -1
- package/dist/instructions.js +10 -3
- package/dist/instructions.js.map +1 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +32 -0
- package/dist/prompts/index.js.map +1 -1
- package/dist/resources/about.d.ts.map +1 -1
- package/dist/resources/about.js +9 -1
- package/dist/resources/about.js.map +1 -1
- package/dist/schemas/index.d.ts +466 -63
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +435 -34
- package/dist/schemas/index.js.map +1 -1
- package/dist/tools/addMemory.d.ts +1 -0
- package/dist/tools/addMemory.d.ts.map +1 -1
- package/dist/tools/addProjectLearnings.d.ts +30 -0
- package/dist/tools/addProjectLearnings.d.ts.map +1 -0
- package/dist/tools/addProjectLearnings.js +197 -0
- package/dist/tools/addProjectLearnings.js.map +1 -0
- package/dist/tools/analyzeLlmResults.d.ts +1 -1
- package/dist/tools/analyzeLlmResults.d.ts.map +1 -1
- package/dist/tools/analyzeLlmResults.js +5 -2
- package/dist/tools/analyzeLlmResults.js.map +1 -1
- package/dist/tools/analyzeText.d.ts +1 -0
- package/dist/tools/analyzeText.d.ts.map +1 -1
- package/dist/tools/analyzeTextSignature.d.ts +38 -0
- package/dist/tools/analyzeTextSignature.d.ts.map +1 -0
- package/dist/tools/analyzeTextSignature.js +82 -0
- package/dist/tools/analyzeTextSignature.js.map +1 -0
- package/dist/tools/createKnowledgeGraph.d.ts +1 -0
- package/dist/tools/createKnowledgeGraph.d.ts.map +1 -1
- package/dist/tools/deleteGraph.d.ts +43 -0
- package/dist/tools/deleteGraph.d.ts.map +1 -0
- package/dist/tools/deleteGraph.js +145 -0
- package/dist/tools/deleteGraph.js.map +1 -0
- package/dist/tools/deleteStatements.d.ts +106 -0
- package/dist/tools/deleteStatements.d.ts.map +1 -0
- package/dist/tools/deleteStatements.js +288 -0
- package/dist/tools/deleteStatements.js.map +1 -0
- package/dist/tools/developConceptualBridges.d.ts +2 -1
- package/dist/tools/developConceptualBridges.d.ts.map +1 -1
- package/dist/tools/developLatentTopics.d.ts +2 -1
- package/dist/tools/developLatentTopics.d.ts.map +1 -1
- package/dist/tools/developTextTool.d.ts +2 -1
- package/dist/tools/developTextTool.d.ts.map +1 -1
- package/dist/tools/enableProjectLearnings.d.ts +27 -0
- package/dist/tools/enableProjectLearnings.d.ts.map +1 -0
- package/dist/tools/enableProjectLearnings.js +68 -0
- package/dist/tools/enableProjectLearnings.js.map +1 -0
- package/dist/tools/generateContentGaps.d.ts +1 -0
- package/dist/tools/generateContentGaps.d.ts.map +1 -1
- package/dist/tools/generateContextualHint.d.ts +1 -0
- package/dist/tools/generateContextualHint.d.ts.map +1 -1
- package/dist/tools/generateDifferenceGraphFromTexts.d.ts +1 -0
- package/dist/tools/generateDifferenceGraphFromTexts.d.ts.map +1 -1
- package/dist/tools/generateDifferenceGraphFromTexts.js +1 -1
- package/dist/tools/generateDifferenceGraphFromTexts.js.map +1 -1
- package/dist/tools/generateKnowledgeGraph.d.ts +1 -0
- package/dist/tools/generateKnowledgeGraph.d.ts.map +1 -1
- package/dist/tools/generateMergedGraphFromTexts.d.ts +1 -0
- package/dist/tools/generateMergedGraphFromTexts.d.ts.map +1 -1
- package/dist/tools/generateMergedGraphFromTexts.js +1 -1
- package/dist/tools/generateMergedGraphFromTexts.js.map +1 -1
- package/dist/tools/generateOntologyGraph.d.ts +10 -3
- package/dist/tools/generateOntologyGraph.d.ts.map +1 -1
- package/dist/tools/generateOntologyGraph.js +142 -34
- package/dist/tools/generateOntologyGraph.js.map +1 -1
- package/dist/tools/generateOverlapGraphFromTexts.d.ts +1 -0
- package/dist/tools/generateOverlapGraphFromTexts.d.ts.map +1 -1
- package/dist/tools/generateOverlapGraphFromTexts.js +1 -1
- package/dist/tools/generateOverlapGraphFromTexts.js.map +1 -1
- package/dist/tools/generateResearchIdeas.d.ts +2 -1
- package/dist/tools/generateResearchIdeas.d.ts.map +1 -1
- package/dist/tools/generateResearchQuestions.d.ts +2 -1
- package/dist/tools/generateResearchQuestions.d.ts.map +1 -1
- package/dist/tools/generateResponses.d.ts +2 -1
- package/dist/tools/generateResponses.d.ts.map +1 -1
- package/dist/tools/generateSEOGraphTool.d.ts +1 -0
- package/dist/tools/generateSEOGraphTool.d.ts.map +1 -1
- package/dist/tools/generateSEOGraphTool.js +1 -1
- package/dist/tools/generateSEOGraphTool.js.map +1 -1
- package/dist/tools/generateTopicalClusters.d.ts +1 -0
- package/dist/tools/generateTopicalClusters.d.ts.map +1 -1
- package/dist/tools/getProjectLearnings.d.ts +30 -0
- package/dist/tools/getProjectLearnings.d.ts.map +1 -0
- package/dist/tools/getProjectLearnings.js +151 -0
- package/dist/tools/getProjectLearnings.js.map +1 -0
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +8 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/optimizeKnowledgeBase.d.ts +41 -0
- package/dist/tools/optimizeKnowledgeBase.d.ts.map +1 -0
- package/dist/tools/optimizeKnowledgeBase.js +230 -0
- package/dist/tools/optimizeKnowledgeBase.js.map +1 -0
- package/dist/tools/optimizeReasoning.d.ts +2 -1
- package/dist/tools/optimizeReasoning.d.ts.map +1 -1
- package/dist/tools/optimizeTextStructure.d.ts +2 -1
- package/dist/tools/optimizeTextStructure.d.ts.map +1 -1
- package/dist/tools/submitWorkflowFeedback.d.ts +35 -0
- package/dist/tools/submitWorkflowFeedback.d.ts.map +1 -0
- package/dist/tools/submitWorkflowFeedback.js +62 -0
- package/dist/tools/submitWorkflowFeedback.js.map +1 -0
- package/dist/tools/updateStatements.d.ts +134 -0
- package/dist/tools/updateStatements.d.ts.map +1 -0
- package/dist/tools/updateStatements.js +378 -0
- package/dist/tools/updateStatements.js.map +1 -0
- package/dist/types/index.d.ts +30 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/callTracking.d.ts +29 -0
- package/dist/utils/callTracking.d.ts.map +1 -0
- package/dist/utils/callTracking.js +88 -0
- package/dist/utils/callTracking.js.map +1 -0
- package/dist/utils/feedback.d.ts +63 -0
- package/dist/utils/feedback.d.ts.map +1 -0
- package/dist/utils/feedback.js +115 -0
- package/dist/utils/feedback.js.map +1 -0
- package/dist/utils/graphInput.d.ts +6 -1
- package/dist/utils/graphInput.d.ts.map +1 -1
- package/dist/utils/graphInput.js +5 -4
- package/dist/utils/graphInput.js.map +1 -1
- package/dist/utils/graphLookup.d.ts +29 -0
- package/dist/utils/graphLookup.d.ts.map +1 -0
- package/dist/utils/graphLookup.js +57 -0
- package/dist/utils/graphLookup.js.map +1 -0
- package/dist/utils/knowledgeBase.d.ts +21 -0
- package/dist/utils/knowledgeBase.d.ts.map +1 -0
- package/dist/utils/knowledgeBase.js +110 -0
- package/dist/utils/knowledgeBase.js.map +1 -0
- package/dist/utils/learnings.d.ts +121 -0
- package/dist/utils/learnings.d.ts.map +1 -0
- package/dist/utils/learnings.js +339 -0
- package/dist/utils/learnings.js.map +1 -0
- package/dist/utils/textSignature.d.ts +231 -0
- package/dist/utils/textSignature.d.ts.map +1 -0
- package/dist/utils/textSignature.js +738 -0
- package/dist/utils/textSignature.js.map +1 -0
- package/dist/utils/wikilinksMode.d.ts +12 -2
- package/dist/utils/wikilinksMode.d.ts.map +1 -1
- package/dist/utils/wikilinksMode.js +18 -5
- package/dist/utils/wikilinksMode.js.map +1 -1
- package/llms-full.infranodus.txt +39 -1
- package/llms-full.txt +39 -1
- package/llms.infranodus.txt +2 -0
- package/llms.txt +2 -0
- package/package.json +4 -2
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helpers for `optimize_knowledge_base`: turn the graph engine's
|
|
3
|
+
* diversity diagnosis into a reading that makes sense for a code base, a
|
|
4
|
+
* document vault, or a body of procedural knowledge (rules, frameworks,
|
|
5
|
+
* principles). The engine's numbers are the same for any text; what differs
|
|
6
|
+
* is what a "gap" or a "dominant cluster" means for the thing being studied.
|
|
7
|
+
*/
|
|
8
|
+
export const FOCUSES = ["general", "codebase", "vault", "procedural"];
|
|
9
|
+
export const STATES = ["biased", "focused", "diversified", "dispersed"];
|
|
10
|
+
const READINGS = {
|
|
11
|
+
general: {
|
|
12
|
+
biased: {
|
|
13
|
+
meaning: "One cluster of ideas dominates; the rest orbit it.",
|
|
14
|
+
action: "Develop the under-represented clusters before adding more to the dominant one.",
|
|
15
|
+
},
|
|
16
|
+
focused: {
|
|
17
|
+
meaning: "Coherent and centred, but narrow.",
|
|
18
|
+
action: "Develop the content gaps: the topics listed as under-developed are the cheapest way to widen it.",
|
|
19
|
+
},
|
|
20
|
+
diversified: {
|
|
21
|
+
meaning: "Several strong clusters that barely connect.",
|
|
22
|
+
action: "Bridge the gaps between clusters — the missing links are where the most original ideas sit.",
|
|
23
|
+
},
|
|
24
|
+
dispersed: {
|
|
25
|
+
meaning: "Many small clusters with no shared backbone.",
|
|
26
|
+
action: "Consolidate: pick the most common gap topics and connect the fragments through them.",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
codebase: {
|
|
30
|
+
biased: {
|
|
31
|
+
meaning: "One module or feature area dominates the project: everything depends on it or describes it (a god module, or a product that is really one feature with satellites).",
|
|
32
|
+
action: "Decide whether the dominance is intended. If not, develop the thin areas and cut dependencies on the dominant one; the under-developed list shows which parts of the code base nobody has built out.",
|
|
33
|
+
},
|
|
34
|
+
focused: {
|
|
35
|
+
meaning: "The code base is coherent and centred on a clear purpose, but narrow: little exists beyond the main path.",
|
|
36
|
+
action: "The gaps are the features and integrations that are implied but not built; the under-developed topics are the ones to build next.",
|
|
37
|
+
},
|
|
38
|
+
diversified: {
|
|
39
|
+
meaning: "Several substantial subsystems that hardly talk to each other.",
|
|
40
|
+
action: "The gaps between clusters are missing integrations or glue code — the most actionable state for a product: each gap is a feature that connects two things users already have.",
|
|
41
|
+
},
|
|
42
|
+
dispersed: {
|
|
43
|
+
meaning: "Fragmented: many small parts sharing no entities — features that do not compose, or several projects in one repo.",
|
|
44
|
+
action: "Consolidate around the most common gap topics; consider extracting or removing fragments that connect to nothing.",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
vault: {
|
|
48
|
+
biased: {
|
|
49
|
+
meaning: "The vault keeps returning to one theme; other notes are satellites of it.",
|
|
50
|
+
action: "Grow the satellite themes into their own clusters, or accept the vault as single-topic and prune what does not serve it.",
|
|
51
|
+
},
|
|
52
|
+
focused: {
|
|
53
|
+
meaning: "A coherent vault around one line of thought, not yet exploring its edges.",
|
|
54
|
+
action: "Write into the gaps: the under-developed topics are notes the vault is already pointing at but has not written.",
|
|
55
|
+
},
|
|
56
|
+
diversified: {
|
|
57
|
+
meaning: "Several well-developed themes with few notes linking them.",
|
|
58
|
+
action: "The gaps are the bridge notes waiting to be written — the places where two of your themes would produce a new idea if connected.",
|
|
59
|
+
},
|
|
60
|
+
dispersed: {
|
|
61
|
+
meaning: "Many unconnected notes; no theme is developed enough to organise the others.",
|
|
62
|
+
action: "Pick the most common gap topics as hub notes and link the fragments through them (maps of content).",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
procedural: {
|
|
66
|
+
biased: {
|
|
67
|
+
meaning: "One framework or rule set dominates the procedural knowledge; the others are footnotes to it.",
|
|
68
|
+
action: "Check whether the dominant framework really covers the other situations; develop the thin rule sets or make the dominance explicit.",
|
|
69
|
+
},
|
|
70
|
+
focused: {
|
|
71
|
+
meaning: "A coherent set of rules and frameworks around one way of working, with little guidance beyond it.",
|
|
72
|
+
action: "The gaps are situations the rules do not address; the under-developed topics are frameworks mentioned but not spelled out.",
|
|
73
|
+
},
|
|
74
|
+
diversified: {
|
|
75
|
+
meaning: "Several independent frameworks or rule sets that never reference each other.",
|
|
76
|
+
action: "The gaps are where two frameworks should hand off to each other — write the rules for those transitions, or you have contradictions waiting to happen.",
|
|
77
|
+
},
|
|
78
|
+
dispersed: {
|
|
79
|
+
meaning: "Fragmented procedural knowledge: many rules, no organising principles.",
|
|
80
|
+
action: "Consolidate the rules under the most common gap topics as principles; rules that connect to no principle are candidates for removal.",
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
export function normalizeState(raw) {
|
|
85
|
+
if (typeof raw !== "string")
|
|
86
|
+
return undefined;
|
|
87
|
+
const value = raw.toLowerCase();
|
|
88
|
+
return STATES.find((state) => value.includes(state));
|
|
89
|
+
}
|
|
90
|
+
export function readState(focus, state) {
|
|
91
|
+
return READINGS[focus][state];
|
|
92
|
+
}
|
|
93
|
+
/** Bounded, de-duplicated list helper for report fields. */
|
|
94
|
+
export function dedupeList(items, limit) {
|
|
95
|
+
const seen = new Set();
|
|
96
|
+
const out = [];
|
|
97
|
+
for (const item of items) {
|
|
98
|
+
if (!item)
|
|
99
|
+
continue;
|
|
100
|
+
const key = item.trim();
|
|
101
|
+
if (!key || seen.has(key.toLowerCase()))
|
|
102
|
+
continue;
|
|
103
|
+
seen.add(key.toLowerCase());
|
|
104
|
+
out.push(key);
|
|
105
|
+
if (out.length >= limit)
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=knowledgeBase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knowledgeBase.js","sourceRoot":"","sources":["../../src/utils/knowledgeBase.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { GraphResponse, Statement } from "../types/index.js";
|
|
2
|
+
import { READ_ATTEMPTS, errorText } from "./graphLookup.js";
|
|
3
|
+
export declare const GRAPH_PREFIX = "learn-";
|
|
4
|
+
export declare const MAX_GRAPH_NAME_LENGTH = 28;
|
|
5
|
+
export declare const MARKER_CATEGORY = "learnings-enabled";
|
|
6
|
+
export declare const LEARNING_TYPES: readonly ["location", "trap", "convention", "decision", "workflow", "question", "approach"];
|
|
7
|
+
export type LearningType = (typeof LEARNING_TYPES)[number];
|
|
8
|
+
export declare const TYPE_CATEGORY_PREFIX = "type-";
|
|
9
|
+
export declare const SOURCE_CATEGORY_PREFIX = "source-";
|
|
10
|
+
/** Near-duplicate threshold on word-set Jaccard similarity. */
|
|
11
|
+
export declare const DEDUPE_THRESHOLD = 0.6;
|
|
12
|
+
export declare const MAX_STATEMENT_LENGTH = 400;
|
|
13
|
+
export declare function slugify(input: string): string;
|
|
14
|
+
export declare function learningsGraphName(project: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Not attached to statements any more: a per-client label links every
|
|
17
|
+
* statement of that client and became the most central node of the graph in
|
|
18
|
+
* testing. Kept so `toStoredLearning` can still read graphs written before
|
|
19
|
+
* that change.
|
|
20
|
+
*/
|
|
21
|
+
export declare function sourceCategory(clientName?: string): string;
|
|
22
|
+
export declare function typeCategory(type: LearningType): string;
|
|
23
|
+
export interface RedactionIssue {
|
|
24
|
+
index: number;
|
|
25
|
+
reason: "secret-like" | "too-long" | "empty";
|
|
26
|
+
}
|
|
27
|
+
/** Returns the indices (never the content) of statements that must not be stored. */
|
|
28
|
+
export declare function redactionIssues(statements: string[]): RedactionIssue[];
|
|
29
|
+
export declare function tokenize(statement: string): Set<string>;
|
|
30
|
+
export declare function jaccard(a: Set<string>, b: Set<string>): number;
|
|
31
|
+
export interface DedupeResult {
|
|
32
|
+
statement: string;
|
|
33
|
+
status: "new" | "reinforced";
|
|
34
|
+
/** The existing statement this one reinforces (when status is "reinforced"). */
|
|
35
|
+
matches?: string;
|
|
36
|
+
similarity?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Compare candidates against what the graph already holds. A near-duplicate
|
|
40
|
+
* is not dropped — it is rewritten as a short "Confirmed again" statement so
|
|
41
|
+
* the repeat still raises the weight of the same entity links (that is how
|
|
42
|
+
* frequently re-learned things become central) without duplicating the text.
|
|
43
|
+
*/
|
|
44
|
+
export declare function dedupeAgainstExisting(candidates: string[], existing: string[], threshold?: number): DedupeResult[];
|
|
45
|
+
export interface LearningsGraphInfo {
|
|
46
|
+
exists: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* True for graphs created before 2026-08-28 with `categoriesAsMentions`
|
|
49
|
+
* on (labels are nodes there). Informational only; consent is the marker
|
|
50
|
+
* statement.
|
|
51
|
+
*/
|
|
52
|
+
categoriesOn: boolean;
|
|
53
|
+
id?: number;
|
|
54
|
+
url?: string;
|
|
55
|
+
createdAt?: string;
|
|
56
|
+
}
|
|
57
|
+
export { READ_ATTEMPTS, errorText };
|
|
58
|
+
/** Exact-name lookup through /listGraphs (read-only; never creates anything). */
|
|
59
|
+
export declare function findLearningsGraph(graphName: string): Promise<LearningsGraphInfo>;
|
|
60
|
+
export interface StoredLearning {
|
|
61
|
+
content: string;
|
|
62
|
+
types: string[];
|
|
63
|
+
source?: string;
|
|
64
|
+
categories: string[];
|
|
65
|
+
createdAt?: string;
|
|
66
|
+
}
|
|
67
|
+
export declare function toStoredLearning(statement: Statement): StoredLearning | null;
|
|
68
|
+
export declare function isMarkerStatement(statement: Statement): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Read every statement of the graph (doNotSave; the graph must already exist —
|
|
71
|
+
* a missing name errors and is never created). "Select an existing graph
|
|
72
|
+
* context" on a graph that does exist means the request hit an instance
|
|
73
|
+
* with a stale contexts list (see firstPositive), not a parameter problem.
|
|
74
|
+
*/
|
|
75
|
+
export declare function fetchLearningsGraph(graphName: string): Promise<{
|
|
76
|
+
statements: Statement[];
|
|
77
|
+
response: GraphResponse;
|
|
78
|
+
}>;
|
|
79
|
+
/**
|
|
80
|
+
* Resolve whether learnings are enabled for a graph name: the graph exists
|
|
81
|
+
* and holds the marker statement written by `createLearningsGraph`. The
|
|
82
|
+
* listing supplies url/createdAt; reading by name is authoritative for
|
|
83
|
+
* existence (a missing graph errors and is never created) and is also what
|
|
84
|
+
* catches a graph the listing does not show yet (see firstPositive).
|
|
85
|
+
*/
|
|
86
|
+
export declare function checkEnabled(graphName: string): Promise<{
|
|
87
|
+
enabled: boolean;
|
|
88
|
+
info: LearningsGraphInfo;
|
|
89
|
+
reason?: "missing" | "not-a-learnings-graph";
|
|
90
|
+
}>;
|
|
91
|
+
export interface AppendResult {
|
|
92
|
+
graphName?: string;
|
|
93
|
+
graphUrl?: string;
|
|
94
|
+
response: GraphResponse;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Append statements (with parallel categories/timestamps) to an existing
|
|
98
|
+
* graph. Sent as a plain statements payload, without contextSettings: the
|
|
99
|
+
* `type` labels stay metadata and never become nodes (the same as
|
|
100
|
+
* prepareStatementsPayload with categoriesAsNodes off), and an append must
|
|
101
|
+
* not carry settings anyway — the graph already has its own.
|
|
102
|
+
*/
|
|
103
|
+
export declare function appendLearnings(params: {
|
|
104
|
+
graphName: string;
|
|
105
|
+
statements: string[];
|
|
106
|
+
categories: string[][];
|
|
107
|
+
timestamps: string[];
|
|
108
|
+
}): Promise<AppendResult>;
|
|
109
|
+
/**
|
|
110
|
+
* Create the learnings graph. The marker statement (and its
|
|
111
|
+
* `learnings-enabled` category) is what `checkEnabled` looks for.
|
|
112
|
+
*/
|
|
113
|
+
export declare function createLearningsGraph(params: {
|
|
114
|
+
graphName: string;
|
|
115
|
+
slug: string;
|
|
116
|
+
clientName?: string;
|
|
117
|
+
}): Promise<AppendResult>;
|
|
118
|
+
export declare function newestFirst<T extends {
|
|
119
|
+
createdAt?: string;
|
|
120
|
+
}>(items: T[]): T[];
|
|
121
|
+
//# sourceMappingURL=learnings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"learnings.d.ts","sourceRoot":"","sources":["../../src/utils/learnings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project learnings: an append-only, per-project graph (`learn-<slug>`) where
|
|
3
|
+
* the calling LLM saves what it learned about operating in a project, so the
|
|
4
|
+
* next session — on any client — can retrieve it.
|
|
5
|
+
*
|
|
6
|
+
* Consent model (see docs/drafts/project-learnings-graph.md): the graph only
|
|
7
|
+
* exists if the user explicitly asked for it via `enable_project_learnings`.
|
|
8
|
+
* `add_project_learnings` refuses when the graph is missing and never creates
|
|
9
|
+
* one. Statements carry their `type-*` label as plain per-statement metadata
|
|
10
|
+
* (`categories`), deliberately WITHOUT `categoriesAsMentions`: with that
|
|
11
|
+
* flag each label becomes a [[label]] mention node linked to every statement
|
|
12
|
+
* of that type, which in testing made the labels the most central nodes of
|
|
13
|
+
* the graph. As metadata the labels are returned with each statement and
|
|
14
|
+
* filterable, while the graph's nodes stay the real entities.
|
|
15
|
+
*/
|
|
16
|
+
import { makeInfraNodusRequest } from "../api/client.js";
|
|
17
|
+
import { READ_ATTEMPTS, errorText, findGraphByName, firstPositive, } from "./graphLookup.js";
|
|
18
|
+
export const GRAPH_PREFIX = "learn-";
|
|
19
|
+
export const MAX_GRAPH_NAME_LENGTH = 28;
|
|
20
|
+
export const MARKER_CATEGORY = "learnings-enabled";
|
|
21
|
+
export const LEARNING_TYPES = [
|
|
22
|
+
"location",
|
|
23
|
+
"trap",
|
|
24
|
+
"convention",
|
|
25
|
+
"decision",
|
|
26
|
+
"workflow",
|
|
27
|
+
"question",
|
|
28
|
+
"approach",
|
|
29
|
+
];
|
|
30
|
+
export const TYPE_CATEGORY_PREFIX = "type-";
|
|
31
|
+
export const SOURCE_CATEGORY_PREFIX = "source-";
|
|
32
|
+
/** Near-duplicate threshold on word-set Jaccard similarity. */
|
|
33
|
+
export const DEDUPE_THRESHOLD = 0.6;
|
|
34
|
+
export const MAX_STATEMENT_LENGTH = 400;
|
|
35
|
+
export function slugify(input) {
|
|
36
|
+
return input
|
|
37
|
+
.toLowerCase()
|
|
38
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
39
|
+
.replace(/^-+|-+$/g, "")
|
|
40
|
+
.replace(/-{2,}/g, "-");
|
|
41
|
+
}
|
|
42
|
+
export function learningsGraphName(project) {
|
|
43
|
+
const slug = slugify(project) || "project";
|
|
44
|
+
const room = MAX_GRAPH_NAME_LENGTH - GRAPH_PREFIX.length;
|
|
45
|
+
return GRAPH_PREFIX + slug.slice(0, room).replace(/-+$/g, "");
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Not attached to statements any more: a per-client label links every
|
|
49
|
+
* statement of that client and became the most central node of the graph in
|
|
50
|
+
* testing. Kept so `toStoredLearning` can still read graphs written before
|
|
51
|
+
* that change.
|
|
52
|
+
*/
|
|
53
|
+
export function sourceCategory(clientName) {
|
|
54
|
+
return SOURCE_CATEGORY_PREFIX + (slugify(clientName ?? "") || "unknown");
|
|
55
|
+
}
|
|
56
|
+
export function typeCategory(type) {
|
|
57
|
+
return TYPE_CATEGORY_PREFIX + type;
|
|
58
|
+
}
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// Redaction lint
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
const SECRET_PATTERNS = [
|
|
63
|
+
/\bsk-[A-Za-z0-9_-]{8,}/, // OpenAI/Anthropic-style keys
|
|
64
|
+
/\bAKIA[0-9A-Z]{16}\b/, // AWS access key id
|
|
65
|
+
/\bbearer\s+[A-Za-z0-9._~+/=-]{12,}/i,
|
|
66
|
+
/\bapi[_-]?key\s*[:=]\s*['"]?[A-Za-z0-9._-]{8,}/i,
|
|
67
|
+
/\b(?:password|passwd|secret|token)\s*[:=]\s*['"]?\S{6,}/i,
|
|
68
|
+
/-----BEGIN [A-Z ]*PRIVATE KEY-----/,
|
|
69
|
+
/:\/\/[^\s/@]+:[^\s/@]+@/, // user:pass@host in a URL
|
|
70
|
+
/\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/, // JWT
|
|
71
|
+
];
|
|
72
|
+
/** Returns the indices (never the content) of statements that must not be stored. */
|
|
73
|
+
export function redactionIssues(statements) {
|
|
74
|
+
const issues = [];
|
|
75
|
+
statements.forEach((statement, index) => {
|
|
76
|
+
if (!statement || !statement.trim()) {
|
|
77
|
+
issues.push({ index, reason: "empty" });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (statement.length > MAX_STATEMENT_LENGTH) {
|
|
81
|
+
issues.push({ index, reason: "too-long" });
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (SECRET_PATTERNS.some((pattern) => pattern.test(statement))) {
|
|
85
|
+
issues.push({ index, reason: "secret-like" });
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return issues;
|
|
89
|
+
}
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Dedupe
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
const STOPWORDS = new Set([
|
|
94
|
+
"the", "and", "for", "that", "this", "with", "from", "are", "was", "were",
|
|
95
|
+
"has", "have", "not", "but", "its", "into", "when", "which", "also", "than",
|
|
96
|
+
"then", "there", "their", "they", "them", "been", "being", "use", "used",
|
|
97
|
+
"confirmed", "again",
|
|
98
|
+
]);
|
|
99
|
+
export function tokenize(statement) {
|
|
100
|
+
const words = statement
|
|
101
|
+
.toLowerCase()
|
|
102
|
+
.replace(/\[\[|\]\]/g, " ")
|
|
103
|
+
.split(/[^a-z0-9._/-]+/)
|
|
104
|
+
.map((word) => word.replace(/^[._/-]+|[._/-]+$/g, ""))
|
|
105
|
+
.filter((word) => word.length >= 3 && !STOPWORDS.has(word));
|
|
106
|
+
return new Set(words);
|
|
107
|
+
}
|
|
108
|
+
export function jaccard(a, b) {
|
|
109
|
+
if (a.size === 0 || b.size === 0)
|
|
110
|
+
return 0;
|
|
111
|
+
let intersection = 0;
|
|
112
|
+
for (const word of a)
|
|
113
|
+
if (b.has(word))
|
|
114
|
+
intersection += 1;
|
|
115
|
+
const union = a.size + b.size - intersection;
|
|
116
|
+
return union === 0 ? 0 : intersection / union;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Compare candidates against what the graph already holds. A near-duplicate
|
|
120
|
+
* is not dropped — it is rewritten as a short "Confirmed again" statement so
|
|
121
|
+
* the repeat still raises the weight of the same entity links (that is how
|
|
122
|
+
* frequently re-learned things become central) without duplicating the text.
|
|
123
|
+
*/
|
|
124
|
+
export function dedupeAgainstExisting(candidates, existing, threshold = DEDUPE_THRESHOLD) {
|
|
125
|
+
const existingTokens = existing.map((statement) => ({
|
|
126
|
+
statement,
|
|
127
|
+
tokens: tokenize(statement),
|
|
128
|
+
}));
|
|
129
|
+
const accepted = [];
|
|
130
|
+
return candidates.map((candidate) => {
|
|
131
|
+
const tokens = tokenize(candidate);
|
|
132
|
+
let best = null;
|
|
133
|
+
for (const entry of existingTokens) {
|
|
134
|
+
const similarity = jaccard(tokens, entry.tokens);
|
|
135
|
+
if (similarity >= threshold && (!best || similarity > best.similarity)) {
|
|
136
|
+
best = { statement: entry.statement, similarity };
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Also collapse duplicates within the same batch.
|
|
140
|
+
if (!best) {
|
|
141
|
+
for (const prior of accepted) {
|
|
142
|
+
if (jaccard(tokens, prior) >= threshold) {
|
|
143
|
+
best = { statement: "(earlier statement in this batch)", similarity: 1 };
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
accepted.push(tokens);
|
|
149
|
+
if (best) {
|
|
150
|
+
return {
|
|
151
|
+
statement: best.statement.startsWith("(")
|
|
152
|
+
? candidate
|
|
153
|
+
: `Confirmed again: ${stripConfirmedPrefix(best.statement)}`,
|
|
154
|
+
status: "reinforced",
|
|
155
|
+
matches: best.statement,
|
|
156
|
+
similarity: Number(best.similarity.toFixed(2)),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
return { statement: candidate, status: "new" };
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
function stripConfirmedPrefix(statement) {
|
|
163
|
+
return statement.replace(/^(?:confirmed again:\s*)+/i, "");
|
|
164
|
+
}
|
|
165
|
+
// The retrying lookup and the error-envelope normaliser live in
|
|
166
|
+
// graphLookup.ts (shared with delete_statements); re-exported here so the
|
|
167
|
+
// existing imports and tests keep working.
|
|
168
|
+
export { READ_ATTEMPTS, errorText };
|
|
169
|
+
/** Exact-name lookup through /listGraphs (read-only; never creates anything). */
|
|
170
|
+
export async function findLearningsGraph(graphName) {
|
|
171
|
+
const found = await findGraphByName(graphName);
|
|
172
|
+
if (!found)
|
|
173
|
+
return { exists: false, categoriesOn: false };
|
|
174
|
+
return {
|
|
175
|
+
exists: true,
|
|
176
|
+
categoriesOn: found.textProcessingSettings?.categoriesAsMentions === true,
|
|
177
|
+
id: found.id,
|
|
178
|
+
url: found.defaultRevisionUrl ?? undefined,
|
|
179
|
+
createdAt: found.createdAt,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
export function toStoredLearning(statement) {
|
|
183
|
+
if (!statement.content)
|
|
184
|
+
return null;
|
|
185
|
+
const categories = statement.categories ?? [];
|
|
186
|
+
return {
|
|
187
|
+
content: statement.content,
|
|
188
|
+
types: categories
|
|
189
|
+
.filter((category) => category.startsWith(TYPE_CATEGORY_PREFIX))
|
|
190
|
+
.map((category) => category.slice(TYPE_CATEGORY_PREFIX.length)),
|
|
191
|
+
source: categories
|
|
192
|
+
.find((category) => category.startsWith(SOURCE_CATEGORY_PREFIX))
|
|
193
|
+
?.slice(SOURCE_CATEGORY_PREFIX.length),
|
|
194
|
+
categories,
|
|
195
|
+
createdAt: statement.createdAt,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
export function isMarkerStatement(statement) {
|
|
199
|
+
return ((statement.categories ?? []).includes(MARKER_CATEGORY) ||
|
|
200
|
+
(statement.content ?? "").includes(`[[${MARKER_CATEGORY}]]`));
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Read every statement of the graph (doNotSave; the graph must already exist —
|
|
204
|
+
* a missing name errors and is never created). "Select an existing graph
|
|
205
|
+
* context" on a graph that does exist means the request hit an instance
|
|
206
|
+
* with a stale contexts list (see firstPositive), not a parameter problem.
|
|
207
|
+
*/
|
|
208
|
+
export async function fetchLearningsGraph(graphName) {
|
|
209
|
+
const queryParams = new URLSearchParams({
|
|
210
|
+
doNotSave: "true",
|
|
211
|
+
addStats: "true",
|
|
212
|
+
includeStatements: "true",
|
|
213
|
+
includeGraphSummary: "false",
|
|
214
|
+
extendedGraphSummary: "true",
|
|
215
|
+
includeGraph: "false",
|
|
216
|
+
compactGraph: "true",
|
|
217
|
+
compactStatements: "false",
|
|
218
|
+
aiTopics: "false",
|
|
219
|
+
});
|
|
220
|
+
let lastError = "Graph not found";
|
|
221
|
+
const response = await firstPositive(async (n) => {
|
|
222
|
+
try {
|
|
223
|
+
const result = await makeInfraNodusRequest(`/graphAndStatements?${queryParams.toString()}`, { name: graphName, aiTopics: "false", attempt: n });
|
|
224
|
+
if (result.error) {
|
|
225
|
+
lastError = errorText(result.error);
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
lastError = error instanceof Error ? error.message : String(error);
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
if (!response)
|
|
236
|
+
throw new Error(lastError);
|
|
237
|
+
return { statements: response.statements ?? [], response };
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Resolve whether learnings are enabled for a graph name: the graph exists
|
|
241
|
+
* and holds the marker statement written by `createLearningsGraph`. The
|
|
242
|
+
* listing supplies url/createdAt; reading by name is authoritative for
|
|
243
|
+
* existence (a missing graph errors and is never created) and is also what
|
|
244
|
+
* catches a graph the listing does not show yet (see firstPositive).
|
|
245
|
+
*/
|
|
246
|
+
export async function checkEnabled(graphName) {
|
|
247
|
+
const info = await findLearningsGraph(graphName);
|
|
248
|
+
let statements;
|
|
249
|
+
try {
|
|
250
|
+
({ statements } = await fetchLearningsGraph(graphName));
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
return { enabled: false, info, reason: "missing" };
|
|
254
|
+
}
|
|
255
|
+
if (statements.some(isMarkerStatement)) {
|
|
256
|
+
return { enabled: true, info: { ...info, exists: true } };
|
|
257
|
+
}
|
|
258
|
+
return {
|
|
259
|
+
enabled: false,
|
|
260
|
+
info: { ...info, exists: true },
|
|
261
|
+
reason: "not-a-learnings-graph",
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Append statements (with parallel categories/timestamps) to an existing
|
|
266
|
+
* graph. Sent as a plain statements payload, without contextSettings: the
|
|
267
|
+
* `type` labels stay metadata and never become nodes (the same as
|
|
268
|
+
* prepareStatementsPayload with categoriesAsNodes off), and an append must
|
|
269
|
+
* not carry settings anyway — the graph already has its own.
|
|
270
|
+
*/
|
|
271
|
+
export async function appendLearnings(params) {
|
|
272
|
+
const payload = {
|
|
273
|
+
text: "",
|
|
274
|
+
statements: params.statements,
|
|
275
|
+
categories: params.categories,
|
|
276
|
+
timestamps: params.timestamps,
|
|
277
|
+
};
|
|
278
|
+
const queryParams = new URLSearchParams({
|
|
279
|
+
doNotSave: "false",
|
|
280
|
+
addStats: "false",
|
|
281
|
+
includeStatements: "false",
|
|
282
|
+
includeGraphSummary: "false",
|
|
283
|
+
extendedGraphSummary: "false",
|
|
284
|
+
includeGraph: "false",
|
|
285
|
+
compactGraph: "true",
|
|
286
|
+
compactStatements: "true",
|
|
287
|
+
aiTopics: "false",
|
|
288
|
+
});
|
|
289
|
+
// An instance with a stale contexts list (see firstPositive) treats an
|
|
290
|
+
// append to an existing graph as a create and the engine rejects it with
|
|
291
|
+
// "Context with this name already exists". That error is the only one
|
|
292
|
+
// worth retrying: it means the graph exists and another instance will
|
|
293
|
+
// append correctly.
|
|
294
|
+
let lastError = "Append failed";
|
|
295
|
+
for (let n = 0; n < READ_ATTEMPTS; n++) {
|
|
296
|
+
const response = await makeInfraNodusRequest(`/graphAndStatements?${queryParams.toString()}`, {
|
|
297
|
+
name: params.graphName,
|
|
298
|
+
aiTopics: "false",
|
|
299
|
+
contextType: "memory",
|
|
300
|
+
...payload,
|
|
301
|
+
...(n > 0 ? { attempt: n } : {}),
|
|
302
|
+
});
|
|
303
|
+
if (!response.error) {
|
|
304
|
+
return {
|
|
305
|
+
graphName: response.graphName ?? params.graphName,
|
|
306
|
+
graphUrl: response.graphUrl,
|
|
307
|
+
response,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
lastError = errorText(response.error);
|
|
311
|
+
if (!/already exists/i.test(lastError))
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
throw new Error(lastError);
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Create the learnings graph. The marker statement (and its
|
|
318
|
+
* `learnings-enabled` category) is what `checkEnabled` looks for.
|
|
319
|
+
*/
|
|
320
|
+
export async function createLearningsGraph(params) {
|
|
321
|
+
const now = new Date().toISOString();
|
|
322
|
+
const client = params.clientName?.trim() || "unknown client";
|
|
323
|
+
return appendLearnings({
|
|
324
|
+
graphName: params.graphName,
|
|
325
|
+
statements: [
|
|
326
|
+
`[[${MARKER_CATEGORY}]] Project [[${params.slug}]] learnings enabled on ${now.slice(0, 10)} from ${client}. Append-only graph of what agents learned about operating in this project.`,
|
|
327
|
+
],
|
|
328
|
+
categories: [[MARKER_CATEGORY]],
|
|
329
|
+
timestamps: [now],
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
export function newestFirst(items) {
|
|
333
|
+
return [...items].sort((a, b) => {
|
|
334
|
+
const ta = a.createdAt ? Date.parse(a.createdAt) : 0;
|
|
335
|
+
const tb = b.createdAt ? Date.parse(b.createdAt) : 0;
|
|
336
|
+
return tb - ta;
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=learnings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"learnings.js","sourceRoot":"","sources":["../../src/utils/learnings.ts"],"names":[],"mappings":"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"}
|