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.
Files changed (161) hide show
  1. package/README.md +73 -8
  2. package/dist/api/client.d.ts +3 -1
  3. package/dist/api/client.d.ts.map +1 -1
  4. package/dist/api/client.js +2 -1
  5. package/dist/api/client.js.map +1 -1
  6. package/dist/api/config-store.d.ts +11 -0
  7. package/dist/api/config-store.d.ts.map +1 -1
  8. package/dist/api/config-store.js +7 -0
  9. package/dist/api/config-store.js.map +1 -1
  10. package/dist/config/brand.d.ts.map +1 -1
  11. package/dist/config/brand.js +11 -0
  12. package/dist/config/brand.js.map +1 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +83 -6
  15. package/dist/index.js.map +1 -1
  16. package/dist/instructions.d.ts.map +1 -1
  17. package/dist/instructions.js +10 -3
  18. package/dist/instructions.js.map +1 -1
  19. package/dist/prompts/index.d.ts.map +1 -1
  20. package/dist/prompts/index.js +32 -0
  21. package/dist/prompts/index.js.map +1 -1
  22. package/dist/resources/about.d.ts.map +1 -1
  23. package/dist/resources/about.js +9 -1
  24. package/dist/resources/about.js.map +1 -1
  25. package/dist/schemas/index.d.ts +466 -63
  26. package/dist/schemas/index.d.ts.map +1 -1
  27. package/dist/schemas/index.js +435 -34
  28. package/dist/schemas/index.js.map +1 -1
  29. package/dist/tools/addMemory.d.ts +1 -0
  30. package/dist/tools/addMemory.d.ts.map +1 -1
  31. package/dist/tools/addProjectLearnings.d.ts +30 -0
  32. package/dist/tools/addProjectLearnings.d.ts.map +1 -0
  33. package/dist/tools/addProjectLearnings.js +197 -0
  34. package/dist/tools/addProjectLearnings.js.map +1 -0
  35. package/dist/tools/analyzeLlmResults.d.ts +1 -1
  36. package/dist/tools/analyzeLlmResults.d.ts.map +1 -1
  37. package/dist/tools/analyzeLlmResults.js +5 -2
  38. package/dist/tools/analyzeLlmResults.js.map +1 -1
  39. package/dist/tools/analyzeText.d.ts +1 -0
  40. package/dist/tools/analyzeText.d.ts.map +1 -1
  41. package/dist/tools/analyzeTextSignature.d.ts +38 -0
  42. package/dist/tools/analyzeTextSignature.d.ts.map +1 -0
  43. package/dist/tools/analyzeTextSignature.js +82 -0
  44. package/dist/tools/analyzeTextSignature.js.map +1 -0
  45. package/dist/tools/createKnowledgeGraph.d.ts +1 -0
  46. package/dist/tools/createKnowledgeGraph.d.ts.map +1 -1
  47. package/dist/tools/deleteGraph.d.ts +43 -0
  48. package/dist/tools/deleteGraph.d.ts.map +1 -0
  49. package/dist/tools/deleteGraph.js +145 -0
  50. package/dist/tools/deleteGraph.js.map +1 -0
  51. package/dist/tools/deleteStatements.d.ts +106 -0
  52. package/dist/tools/deleteStatements.d.ts.map +1 -0
  53. package/dist/tools/deleteStatements.js +288 -0
  54. package/dist/tools/deleteStatements.js.map +1 -0
  55. package/dist/tools/developConceptualBridges.d.ts +2 -1
  56. package/dist/tools/developConceptualBridges.d.ts.map +1 -1
  57. package/dist/tools/developLatentTopics.d.ts +2 -1
  58. package/dist/tools/developLatentTopics.d.ts.map +1 -1
  59. package/dist/tools/developTextTool.d.ts +2 -1
  60. package/dist/tools/developTextTool.d.ts.map +1 -1
  61. package/dist/tools/enableProjectLearnings.d.ts +27 -0
  62. package/dist/tools/enableProjectLearnings.d.ts.map +1 -0
  63. package/dist/tools/enableProjectLearnings.js +68 -0
  64. package/dist/tools/enableProjectLearnings.js.map +1 -0
  65. package/dist/tools/generateContentGaps.d.ts +1 -0
  66. package/dist/tools/generateContentGaps.d.ts.map +1 -1
  67. package/dist/tools/generateContextualHint.d.ts +1 -0
  68. package/dist/tools/generateContextualHint.d.ts.map +1 -1
  69. package/dist/tools/generateDifferenceGraphFromTexts.d.ts +1 -0
  70. package/dist/tools/generateDifferenceGraphFromTexts.d.ts.map +1 -1
  71. package/dist/tools/generateDifferenceGraphFromTexts.js +1 -1
  72. package/dist/tools/generateDifferenceGraphFromTexts.js.map +1 -1
  73. package/dist/tools/generateKnowledgeGraph.d.ts +1 -0
  74. package/dist/tools/generateKnowledgeGraph.d.ts.map +1 -1
  75. package/dist/tools/generateMergedGraphFromTexts.d.ts +1 -0
  76. package/dist/tools/generateMergedGraphFromTexts.d.ts.map +1 -1
  77. package/dist/tools/generateMergedGraphFromTexts.js +1 -1
  78. package/dist/tools/generateMergedGraphFromTexts.js.map +1 -1
  79. package/dist/tools/generateOntologyGraph.d.ts +10 -3
  80. package/dist/tools/generateOntologyGraph.d.ts.map +1 -1
  81. package/dist/tools/generateOntologyGraph.js +142 -34
  82. package/dist/tools/generateOntologyGraph.js.map +1 -1
  83. package/dist/tools/generateOverlapGraphFromTexts.d.ts +1 -0
  84. package/dist/tools/generateOverlapGraphFromTexts.d.ts.map +1 -1
  85. package/dist/tools/generateOverlapGraphFromTexts.js +1 -1
  86. package/dist/tools/generateOverlapGraphFromTexts.js.map +1 -1
  87. package/dist/tools/generateResearchIdeas.d.ts +2 -1
  88. package/dist/tools/generateResearchIdeas.d.ts.map +1 -1
  89. package/dist/tools/generateResearchQuestions.d.ts +2 -1
  90. package/dist/tools/generateResearchQuestions.d.ts.map +1 -1
  91. package/dist/tools/generateResponses.d.ts +2 -1
  92. package/dist/tools/generateResponses.d.ts.map +1 -1
  93. package/dist/tools/generateSEOGraphTool.d.ts +1 -0
  94. package/dist/tools/generateSEOGraphTool.d.ts.map +1 -1
  95. package/dist/tools/generateSEOGraphTool.js +1 -1
  96. package/dist/tools/generateSEOGraphTool.js.map +1 -1
  97. package/dist/tools/generateTopicalClusters.d.ts +1 -0
  98. package/dist/tools/generateTopicalClusters.d.ts.map +1 -1
  99. package/dist/tools/getProjectLearnings.d.ts +30 -0
  100. package/dist/tools/getProjectLearnings.d.ts.map +1 -0
  101. package/dist/tools/getProjectLearnings.js +151 -0
  102. package/dist/tools/getProjectLearnings.js.map +1 -0
  103. package/dist/tools/index.d.ts +8 -0
  104. package/dist/tools/index.d.ts.map +1 -1
  105. package/dist/tools/index.js +8 -0
  106. package/dist/tools/index.js.map +1 -1
  107. package/dist/tools/optimizeKnowledgeBase.d.ts +41 -0
  108. package/dist/tools/optimizeKnowledgeBase.d.ts.map +1 -0
  109. package/dist/tools/optimizeKnowledgeBase.js +230 -0
  110. package/dist/tools/optimizeKnowledgeBase.js.map +1 -0
  111. package/dist/tools/optimizeReasoning.d.ts +2 -1
  112. package/dist/tools/optimizeReasoning.d.ts.map +1 -1
  113. package/dist/tools/optimizeTextStructure.d.ts +2 -1
  114. package/dist/tools/optimizeTextStructure.d.ts.map +1 -1
  115. package/dist/tools/submitWorkflowFeedback.d.ts +35 -0
  116. package/dist/tools/submitWorkflowFeedback.d.ts.map +1 -0
  117. package/dist/tools/submitWorkflowFeedback.js +62 -0
  118. package/dist/tools/submitWorkflowFeedback.js.map +1 -0
  119. package/dist/tools/updateStatements.d.ts +134 -0
  120. package/dist/tools/updateStatements.d.ts.map +1 -0
  121. package/dist/tools/updateStatements.js +378 -0
  122. package/dist/tools/updateStatements.js.map +1 -0
  123. package/dist/types/index.d.ts +30 -0
  124. package/dist/types/index.d.ts.map +1 -1
  125. package/dist/utils/callTracking.d.ts +29 -0
  126. package/dist/utils/callTracking.d.ts.map +1 -0
  127. package/dist/utils/callTracking.js +88 -0
  128. package/dist/utils/callTracking.js.map +1 -0
  129. package/dist/utils/feedback.d.ts +63 -0
  130. package/dist/utils/feedback.d.ts.map +1 -0
  131. package/dist/utils/feedback.js +115 -0
  132. package/dist/utils/feedback.js.map +1 -0
  133. package/dist/utils/graphInput.d.ts +6 -1
  134. package/dist/utils/graphInput.d.ts.map +1 -1
  135. package/dist/utils/graphInput.js +5 -4
  136. package/dist/utils/graphInput.js.map +1 -1
  137. package/dist/utils/graphLookup.d.ts +29 -0
  138. package/dist/utils/graphLookup.d.ts.map +1 -0
  139. package/dist/utils/graphLookup.js +57 -0
  140. package/dist/utils/graphLookup.js.map +1 -0
  141. package/dist/utils/knowledgeBase.d.ts +21 -0
  142. package/dist/utils/knowledgeBase.d.ts.map +1 -0
  143. package/dist/utils/knowledgeBase.js +110 -0
  144. package/dist/utils/knowledgeBase.js.map +1 -0
  145. package/dist/utils/learnings.d.ts +121 -0
  146. package/dist/utils/learnings.d.ts.map +1 -0
  147. package/dist/utils/learnings.js +339 -0
  148. package/dist/utils/learnings.js.map +1 -0
  149. package/dist/utils/textSignature.d.ts +231 -0
  150. package/dist/utils/textSignature.d.ts.map +1 -0
  151. package/dist/utils/textSignature.js +738 -0
  152. package/dist/utils/textSignature.js.map +1 -0
  153. package/dist/utils/wikilinksMode.d.ts +12 -2
  154. package/dist/utils/wikilinksMode.d.ts.map +1 -1
  155. package/dist/utils/wikilinksMode.js +18 -5
  156. package/dist/utils/wikilinksMode.js.map +1 -1
  157. package/llms-full.infranodus.txt +39 -1
  158. package/llms-full.txt +39 -1
  159. package/llms.infranodus.txt +2 -0
  160. package/llms.txt +2 -0
  161. package/package.json +4 -2
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { brand } from "../config/brand.js";
3
- import { WikilinksModeEnum, wikilinksModeDescription, } from "../utils/wikilinksMode.js";
3
+ import { WikilinksModeEnum, categoriesAsNodesDescription, wikilinksModeDescription, } from "../utils/wikilinksMode.js";
4
4
  /**
5
5
  * Optional alternative to `text` / `url`, shared by every tool that builds a
6
6
  * graph from content: discrete statements with optional per-statement
@@ -14,11 +14,18 @@ const statementsField = z
14
14
  const categoriesField = z
15
15
  .array(z.array(z.string()))
16
16
  .optional()
17
- .describe("Per-statement metadata labels, one entry per statement (empty array for none, length must match `statements`). Each label becomes a [[label]] node linked to that statement's concepts only, so author / source / tag / section can be filtered and grouped in the graph. Requires `statements`; omit when there is no metadata.");
17
+ .describe("Per-statement metadata labels, one entry per statement (empty array for none, length must match `statements`). Each label is stored on its statement as metadata, so author / source / tag / section can be filtered and grouped in the app and targeted by delete_statements / update_statements; labels become [[label]] nodes only when `categoriesAsNodes` is true. Requires `statements`; omit when there is no metadata.");
18
+ /** Companion of `categories`: off by default so the labels stay metadata;
19
+ * on only when the connections between pages/files (the labels) are the
20
+ * point, as in large knowledge bases and Obsidian vaults. */
21
+ const categoriesAsNodesField = z
22
+ .boolean()
23
+ .default(false)
24
+ .describe(categoriesAsNodesDescription);
18
25
  /** Saved graphs freeze their processing settings at creation (lib/context.js
19
26
  * applies contextSettings only when the context does not already exist), so
20
27
  * categories on a later upload to the same graph produce no label nodes. */
21
- const SAVED_GRAPH_CATEGORIES_NOTE = "Per-statement metadata labels, one entry per statement (empty array for none, length must match `statements`). Each label becomes a [[label]] node linked to that statement's concepts only, so author / source / tag / section can be filtered and grouped in the graph. Takes effect only when the graph is FIRST created — uploads to an existing graphName keep its original settings and the labels are ignored. Requires `statements`; omit when there is no metadata.";
28
+ const SAVED_GRAPH_CATEGORIES_NOTE = "Per-statement metadata labels, one entry per statement (empty array for none, length must match `statements`). Each label is stored on its statement as metadata, so author / source / tag / section can be filtered and grouped in the app and targeted by delete_statements / update_statements; labels become [[label]] nodes only when `categoriesAsNodes` is true. Takes effect only when the graph is FIRST created — uploads to an existing graphName keep its original settings and the labels are ignored. Requires `statements`; omit when there is no metadata.";
22
29
  const timestampsField = z
23
30
  .array(z.string())
24
31
  .optional()
@@ -35,6 +42,7 @@ export const GenerateGraphSchema = z.object({
35
42
  .describe("URL to fetch content from or YouTube video URL to fetch transcript. Provide either this or text, not both."),
36
43
  statements: statementsField,
37
44
  categories: categoriesField,
45
+ categoriesAsNodes: categoriesAsNodesField,
38
46
  timestamps: timestampsField,
39
47
  includeStatements: z
40
48
  .boolean()
@@ -81,6 +89,7 @@ export const CreateGraphSchema = z.object({
81
89
  .describe("URL to fetch content from or YouTube video URL to fetch transcript. Provide either this or text, not both."),
82
90
  statements: statementsField,
83
91
  categories: categoriesField.describe(`${SAVED_GRAPH_CATEGORIES_NOTE}`),
92
+ categoriesAsNodes: categoriesAsNodesField,
84
93
  timestamps: timestampsField,
85
94
  includeStatements: z
86
95
  .boolean()
@@ -124,6 +133,7 @@ export const AddMemorySchema = z.object({
124
133
  .describe("Text that you'd like to analyze. Use new lines to separate separate statements, relations, and paragraphs in each text (but not the sentences). Detect the entities in every statement and use [[wikilinks]] syntax to mark them, unless the user explicitly requests automatic entity detection. Every statement should have at least two entities marked. Provide either this or statements."),
125
134
  statements: statementsField,
126
135
  categories: categoriesField.describe(SAVED_GRAPH_CATEGORIES_NOTE),
136
+ categoriesAsNodes: categoriesAsNodesField,
127
137
  timestamps: timestampsField,
128
138
  includeStatements: z
129
139
  .boolean()
@@ -154,6 +164,7 @@ export const AnalyzeTextSchemaBase = z.object({
154
164
  .describe("URL to fetch content from (e.g. webpage or YouTube video transcript). Provide either this or text."),
155
165
  statements: statementsField,
156
166
  categories: categoriesField,
167
+ categoriesAsNodes: categoriesAsNodesField,
157
168
  timestamps: timestampsField,
158
169
  includeStatements: z
159
170
  .boolean()
@@ -261,6 +272,7 @@ export const GenerateContentGapsSchemaBase = z.object({
261
272
  .describe("URL to fetch content from or YouTube video URL to fetch transcript. Provide one of: text, url, statements, or graphName."),
262
273
  statements: statementsField,
263
274
  categories: categoriesField,
275
+ categoriesAsNodes: categoriesAsNodesField,
264
276
  timestamps: timestampsField,
265
277
  graphName: z
266
278
  .string()
@@ -283,6 +295,7 @@ export const generateContextualHintSchemaBase = z.object({
283
295
  .describe("URL to fetch content from or YouTube video URL to fetch transcript. Provide one of: text, url, statements, or graphName."),
284
296
  statements: statementsField,
285
297
  categories: categoriesField,
298
+ categoriesAsNodes: categoriesAsNodesField,
286
299
  timestamps: timestampsField,
287
300
  graphName: z
288
301
  .string()
@@ -301,16 +314,36 @@ export const generateContextualHintSchema = generateContextualHintSchemaBase.ref
301
314
  export const GenerateOntologyGraphSchema = z.object({
302
315
  prompt: z
303
316
  .string()
304
- .min(1, "Provide a topic, prompt, or text to generate an ontology for")
305
- .describe("The topic, prompt, or text to generate a reasoning ontology graph for. For example: 'build an ontology on AI attention mechanisms' or 'the main principles of Ray Dalio applied to investment'. The AI generates entities and the relations between them."),
317
+ .optional()
318
+ .describe("A topic or short prompt to generate a reasoning ontology for, e.g. 'build an ontology on AI attention mechanisms' or 'the main principles of Ray Dalio applied to investment'. Sent to the AI as-is in one call. Provide exactly one of: prompt, text, sourceGraphName."),
319
+ text: z
320
+ .string()
321
+ .optional()
322
+ .describe("A long text, document, or structure map of a project (file tree, imports, exports, docstring headlines) to EXTRACT an ontology from. Chunked server-side (see chunkSize); every chunk's ontology is appended to the same graph. Provide exactly one of: prompt, text, sourceGraphName."),
323
+ sourceGraphName: z
324
+ .string()
325
+ .optional()
326
+ .describe(`Name of an existing ${brand.name} graph whose statements are the source: they are read back, chunked, and an ontology is generated from each chunk into the graph named by graphName. Use it to condense a fully ingested repo, vault, or corpus graph (e.g. repo-<project>-docs or repo-<project>-structure) into an ontology, or — with ontologyMode 'procedural' — into a digest of how the project works. Provide exactly one of: prompt, text, sourceGraphName.`),
327
+ ontologyMode: z
328
+ .enum(["general", "codebase", "procedural"])
329
+ .default("general")
330
+ .describe("'general' (default): entities and relations of any domain. 'codebase': the source is a software project's structure map or code documentation — entities are modules/files, functions, classes, data stores, external services, configuration, and the domain concepts they implement; relations favour dependsOn / partOf / exposes / calls / stores / implements. 'procedural': instead of an ontology, write a DIGEST of how the project works — one prose statement per line with [[wikilinks]] on the modules, concepts, and files involved, each ending with its type in [brackets] — [principles], [rules], [procedures], [handoffs], [main_ideas], [gaps] — which is saved as the statement's category; save it as repo-<project>-digest or vault-<project>-digest and feed it to optimize_knowledge_base. Use it when the content already lives in a graph (docs, structure, notes) and nobody can or should re-read the files. Applies to text and sourceGraphName inputs."),
331
+ chunkSize: z
332
+ .number()
333
+ .int()
334
+ .min(2000)
335
+ .max(40000)
336
+ .default(12000)
337
+ .describe("Characters per chunk for text / sourceGraphName inputs (split on line boundaries). Smaller chunks give more detailed, more expensive ontologies. Default 12000."),
306
338
  graphName: z
307
339
  .string()
308
340
  .optional()
309
341
  .describe(`Name of the ${brand.name} graph to save the ontology to. Only used when saveGraph is true. If omitted, a name is auto-generated from the prompt. Note: saving to a name that already exists appends the new statements to that graph rather than replacing it.`),
310
342
  modelToUse: z
311
343
  .enum([
312
- "claude-opus-4.6",
313
- "claude-sonnet-4.6",
344
+ "claude-opus-5",
345
+ "claude-sonnet-5",
346
+ "claude-fable-5",
314
347
  "gemini-2.5-pro",
315
348
  "gemini-2.5-flash",
316
349
  "gemini-2.5-flash-lite",
@@ -320,9 +353,11 @@ export const GenerateOntologyGraphSchema = z.object({
320
353
  "gpt-4o-mini",
321
354
  "gpt-5.4",
322
355
  "gpt-5.4-mini",
356
+ "gpt-5.6-terra",
357
+ "gpt-5.6-sol",
323
358
  ])
324
- .default("claude-opus-4.6")
325
- .describe("AI model used to generate the ontology. More capable models (claude-opus-4.6, gpt-5.4) produce richer, more accurate ontologies; the -mini and -lite variants are faster and cheaper. Default: claude-opus-4.6."),
359
+ .default("claude-opus-5")
360
+ .describe("AI model used to generate the ontology. More capable models (claude-opus-5, claude-fable-5, gpt-5.6-terra) produce richer, more accurate ontologies; the -mini and -lite variants are faster and cheaper. Default: claude-opus-5."),
326
361
  saveGraph: z
327
362
  .boolean()
328
363
  .default(true)
@@ -362,8 +397,9 @@ export const AnalyzeLlmResultsSchema = z.object({
362
397
  .describe(`Name of the ${brand.name} graph to save the LLM overview to. Only used when saveGraph is true. If omitted, a name is auto-generated from the prompt. Note: saving to a name that already exists appends the new statements to that graph rather than replacing it.`),
363
398
  modelToUse: z
364
399
  .enum([
365
- "claude-opus-4.6",
366
- "claude-sonnet-4.6",
400
+ "claude-opus-5",
401
+ "claude-sonnet-5",
402
+ "claude-fable-5",
367
403
  "gemini-2.5-pro",
368
404
  "gemini-2.5-flash",
369
405
  "gemini-2.5-flash-lite",
@@ -373,9 +409,11 @@ export const AnalyzeLlmResultsSchema = z.object({
373
409
  "gpt-4o-mini",
374
410
  "gpt-5.4",
375
411
  "gpt-5.4-mini",
412
+ "gpt-5.6-terra",
413
+ "gpt-5.6-sol",
376
414
  ])
377
- .default("claude-opus-4.6")
378
- .describe("AI model whose view of the topic is being analyzed. Pick the model the user is curious about — different models surface different framings. Default: claude-opus-4.6."),
415
+ .default("claude-opus-5")
416
+ .describe("AI model whose view of the topic is being analyzed. Pick the model the user is curious about — different models surface different framings. Default: claude-opus-5."),
379
417
  modifyAnalyzedText: z
380
418
  .enum(["none", "detectEntities", "extractEntitiesOnly"])
381
419
  .default("none")
@@ -409,6 +447,7 @@ export const GenerateTopicalClustersSchemaBase = z.object({
409
447
  .describe("URL to fetch content from or YouTube video URL to fetch transcript. Provide one of: text, url, statements, or graphName."),
410
448
  statements: statementsField,
411
449
  categories: categoriesField,
450
+ categoriesAsNodes: categoriesAsNodesField,
412
451
  timestamps: timestampsField,
413
452
  graphName: z
414
453
  .string()
@@ -441,6 +480,7 @@ export const GenerateResearchQuestionsSchemaBase = z.object({
441
480
  .describe("URL to fetch content from or YouTube video URL to fetch transcript. Provide one of: text, url, statements, or graphName."),
442
481
  statements: statementsField,
443
482
  categories: categoriesField,
483
+ categoriesAsNodes: categoriesAsNodesField,
444
484
  timestamps: timestampsField,
445
485
  graphName: z
446
486
  .string()
@@ -465,8 +505,9 @@ export const GenerateResearchQuestionsSchemaBase = z.object({
465
505
  .describe("Include graph summary string in the response to provide additional information about the text knowledge graph structure"),
466
506
  modelToUse: z
467
507
  .enum([
468
- "claude-opus-4.6",
469
- "claude-sonnet-4.6",
508
+ "claude-opus-5",
509
+ "claude-sonnet-5",
510
+ "claude-fable-5",
470
511
  "gemini-2.5-pro",
471
512
  "gemini-2.5-flash",
472
513
  "gemini-2.5-flash-lite",
@@ -476,9 +517,11 @@ export const GenerateResearchQuestionsSchemaBase = z.object({
476
517
  "gpt-4o-mini",
477
518
  "gpt-5.4",
478
519
  "gpt-5.4-mini",
520
+ "gpt-5.6-terra",
521
+ "gpt-5.6-sol",
479
522
  ])
480
523
  .default("gpt-5.4")
481
- .describe("AI model to use for generating research questions: claude-opus-4.6, claude-sonnet-4.6, gemini-2.5-flash, gemini-2.5-flash-lite, gpt-4o, gpt-4o-mini, gpt-5.4, gpt-5.4-mini"),
524
+ .describe("AI model to use for generating research questions: claude-opus-5, claude-sonnet-5, claude-fable-5, gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite, grok-4.1-fast-non-reasoning, grok-4.1-fast-reasoning, gpt-4o, gpt-4o-mini, gpt-5.4, gpt-5.4-mini, gpt-5.6-terra, gpt-5.6-sol"),
482
525
  });
483
526
  export const GenerateResearchQuestionsSchema = GenerateResearchQuestionsSchemaBase.refine((data) => (data.text !== undefined && data.text.trim().length > 0) ||
484
527
  (data.url !== undefined && data.url.length > 0) ||
@@ -496,6 +539,7 @@ export const GenerateResearchIdeasSchemaBase = z.object({
496
539
  .describe("URL to fetch content from or YouTube video URL to fetch transcript. Provide one of: text, url, statements, or graphName."),
497
540
  statements: statementsField,
498
541
  categories: categoriesField,
542
+ categoriesAsNodes: categoriesAsNodesField,
499
543
  timestamps: timestampsField,
500
544
  graphName: z
501
545
  .string()
@@ -528,8 +572,9 @@ export const GenerateResearchIdeasSchemaBase = z.object({
528
572
  .describe("Include graph summary string in the response to provide additional information about the text knowledge graph structure"),
529
573
  modelToUse: z
530
574
  .enum([
531
- "claude-opus-4.6",
532
- "claude-sonnet-4.6",
575
+ "claude-opus-5",
576
+ "claude-sonnet-5",
577
+ "claude-fable-5",
533
578
  "gemini-2.5-pro",
534
579
  "gemini-2.5-flash",
535
580
  "gemini-2.5-flash-lite",
@@ -539,9 +584,11 @@ export const GenerateResearchIdeasSchemaBase = z.object({
539
584
  "gpt-4o-mini",
540
585
  "gpt-5.4",
541
586
  "gpt-5.4-mini",
587
+ "gpt-5.6-terra",
588
+ "gpt-5.6-sol",
542
589
  ])
543
590
  .default("gpt-5.4")
544
- .describe("AI model to use for generating research questions: claude-opus-4.6, claude-sonnet-4.6, gemini-2.5-flash, gemini-2.5-flash-lite, gpt-4o, gpt-4o-mini, gpt-5.4, gpt-5.4-mini"),
591
+ .describe("AI model to use for generating research questions: claude-opus-5, claude-sonnet-5, claude-fable-5, gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite, grok-4.1-fast-non-reasoning, grok-4.1-fast-reasoning, gpt-4o, gpt-4o-mini, gpt-5.4, gpt-5.4-mini, gpt-5.6-terra, gpt-5.6-sol"),
545
592
  });
546
593
  export const GenerateResearchIdeasSchema = GenerateResearchIdeasSchemaBase.refine((data) => (data.text !== undefined && data.text.trim().length > 0) ||
547
594
  (data.url !== undefined && data.url.length > 0) ||
@@ -559,6 +606,7 @@ export const OptimizeTextStructureSchemaBase = z.object({
559
606
  .describe("URL to fetch content from or YouTube video URL to fetch transcript. Provide one of: text, url, statements, or graphName."),
560
607
  statements: statementsField,
561
608
  categories: categoriesField,
609
+ categoriesAsNodes: categoriesAsNodesField,
562
610
  timestamps: timestampsField,
563
611
  graphName: z
564
612
  .string()
@@ -571,8 +619,9 @@ export const OptimizeTextStructureSchemaBase = z.object({
571
619
  .describe("Type of response to generate: 'response' — generates a response based on the gaps identified; 'idea' — generate a business idea that bridges the gap; 'question' — generate questions that focus on this context; 'transcend' — generate responses that go beyond the text and relate to a broader discourse."),
572
620
  modelToUse: z
573
621
  .enum([
574
- "claude-opus-4.6",
575
- "claude-sonnet-4.6",
622
+ "claude-opus-5",
623
+ "claude-sonnet-5",
624
+ "claude-fable-5",
576
625
  "gemini-2.5-pro",
577
626
  "gemini-2.5-flash",
578
627
  "gemini-2.5-flash-lite",
@@ -582,9 +631,11 @@ export const OptimizeTextStructureSchemaBase = z.object({
582
631
  "gpt-4o-mini",
583
632
  "gpt-5.4",
584
633
  "gpt-5.4-mini",
634
+ "gpt-5.6-terra",
635
+ "gpt-5.6-sol",
585
636
  ])
586
637
  .default("gpt-5.4")
587
- .describe("AI model to use for generating optimization suggestions: claude-opus-4.6, claude-sonnet-4.6, gemini-2.5-flash, gemini-2.5-flash-lite, gpt-4o, gpt-4o-mini, gpt-5.4, gpt-5.4-mini"),
638
+ .describe("AI model to use for generating optimization suggestions: claude-opus-5, claude-sonnet-5, claude-fable-5, gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite, grok-4.1-fast-non-reasoning, grok-4.1-fast-reasoning, gpt-4o, gpt-4o-mini, gpt-5.4, gpt-5.4-mini, gpt-5.6-terra, gpt-5.6-sol"),
588
639
  });
589
640
  export const OptimizeTextStructureSchema = OptimizeTextStructureSchemaBase.refine((data) => (data.text !== undefined && data.text.trim().length > 0) ||
590
641
  (data.url !== undefined && data.url.length > 0) ||
@@ -597,11 +648,13 @@ export const OptimizeReasoningSchemaBase = z.object({
597
648
  .describe("The current reasoning trace or chat conversation to analyze structurally. Paste the model's own chain-of-thought / reasoning output, the running dialogue with the user, or both concatenated. Use new lines to separate distinct reasoning steps, turns, or paragraphs (but not individual sentences). Provide either this or statements."),
598
649
  statements: statementsField,
599
650
  categories: categoriesField,
651
+ categoriesAsNodes: categoriesAsNodesField,
600
652
  timestamps: timestampsField,
601
653
  modelToUse: z
602
654
  .enum([
603
- "claude-opus-4.6",
604
- "claude-sonnet-4.6",
655
+ "claude-opus-5",
656
+ "claude-sonnet-5",
657
+ "claude-fable-5",
605
658
  "gemini-2.5-pro",
606
659
  "gemini-2.5-flash",
607
660
  "gemini-2.5-flash-lite",
@@ -611,9 +664,11 @@ export const OptimizeReasoningSchemaBase = z.object({
611
664
  "gpt-4o-mini",
612
665
  "gpt-5.4",
613
666
  "gpt-5.4-mini",
667
+ "gpt-5.6-terra",
668
+ "gpt-5.6-sol",
614
669
  ])
615
670
  .default("gpt-5.4")
616
- .describe("AI model to use for generating the reasoning-optimization suggestions: claude-opus-4.6, claude-sonnet-4.6, gemini-2.5-flash, gemini-2.5-flash-lite, gpt-4o, gpt-4o-mini, gpt-5.4, gpt-5.4-mini"),
671
+ .describe("AI model to use for generating the reasoning-optimization suggestions: claude-opus-5, claude-sonnet-5, claude-fable-5, gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite, grok-4.1-fast-non-reasoning, grok-4.1-fast-reasoning, gpt-4o, gpt-4o-mini, gpt-5.4, gpt-5.4-mini, gpt-5.6-terra, gpt-5.6-sol"),
617
672
  });
618
673
  export const OptimizeReasoningSchema = OptimizeReasoningSchemaBase;
619
674
  export const DevelopLatentConceptsSchemaBase = z.object({
@@ -628,6 +683,7 @@ export const DevelopLatentConceptsSchemaBase = z.object({
628
683
  .describe("URL to fetch content from or YouTube video URL to fetch transcript. Provide one of: text, url, statements, or graphName."),
629
684
  statements: statementsField,
630
685
  categories: categoriesField,
686
+ categoriesAsNodes: categoriesAsNodesField,
631
687
  timestamps: timestampsField,
632
688
  graphName: z
633
689
  .string()
@@ -640,8 +696,9 @@ export const DevelopLatentConceptsSchemaBase = z.object({
640
696
  .describe("Request mode: 'question' — generate questions that focus on this context; 'transcend' — generate responses that transcend and go beyond the content of the text and relate to a broader discourse."),
641
697
  modelToUse: z
642
698
  .enum([
643
- "claude-opus-4.6",
644
- "claude-sonnet-4.6",
699
+ "claude-opus-5",
700
+ "claude-sonnet-5",
701
+ "claude-fable-5",
645
702
  "gemini-2.5-pro",
646
703
  "gemini-2.5-flash",
647
704
  "gemini-2.5-flash-lite",
@@ -651,9 +708,11 @@ export const DevelopLatentConceptsSchemaBase = z.object({
651
708
  "gpt-4o-mini",
652
709
  "gpt-5.4",
653
710
  "gpt-5.4-mini",
711
+ "gpt-5.6-terra",
712
+ "gpt-5.6-sol",
654
713
  ])
655
714
  .default("gpt-5.4")
656
- .describe("AI model to use for generating research questions: claude-opus-4.6, claude-sonnet-4.6, gemini-2.5-flash, gemini-2.5-flash-lite, gpt-4o, gpt-4o-mini, gpt-5.4, gpt-5.4-mini"),
715
+ .describe("AI model to use for generating research questions: claude-opus-5, claude-sonnet-5, claude-fable-5, gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite, grok-4.1-fast-non-reasoning, grok-4.1-fast-reasoning, gpt-4o, gpt-4o-mini, gpt-5.4, gpt-5.4-mini, gpt-5.6-terra, gpt-5.6-sol"),
657
716
  });
658
717
  export const DevelopLatentConceptsSchema = DevelopLatentConceptsSchemaBase.refine((data) => (data.text !== undefined && data.text.trim().length > 0) ||
659
718
  (data.url !== undefined && data.url.length > 0) ||
@@ -710,6 +769,7 @@ export const GenerateResponsesFromGraphSchemaBase = z.object({
710
769
  .describe("URL to fetch content from or YouTube video URL to fetch transcript. Provide one of: text, url, statements, or graphName."),
711
770
  statements: statementsField,
712
771
  categories: categoriesField,
772
+ categoriesAsNodes: categoriesAsNodesField,
713
773
  timestamps: timestampsField,
714
774
  prompt: z
715
775
  .string()
@@ -717,8 +777,9 @@ export const GenerateResponsesFromGraphSchemaBase = z.object({
717
777
  .describe("Prompt to generate responses to from the graph"),
718
778
  modelToUse: z
719
779
  .enum([
720
- "claude-opus-4.6",
721
- "claude-sonnet-4.6",
780
+ "claude-opus-5",
781
+ "claude-sonnet-5",
782
+ "claude-fable-5",
722
783
  "gemini-2.5-pro",
723
784
  "gemini-2.5-flash",
724
785
  "gemini-2.5-flash-lite",
@@ -728,9 +789,11 @@ export const GenerateResponsesFromGraphSchemaBase = z.object({
728
789
  "gpt-4o-mini",
729
790
  "gpt-5.4",
730
791
  "gpt-5.4-mini",
792
+ "gpt-5.6-terra",
793
+ "gpt-5.6-sol",
731
794
  ])
732
795
  .default("gpt-5.4")
733
- .describe("AI model to use for generating research questions: claude-opus-4.6, claude-sonnet-4.6, gemini-2.5-flash, gemini-2.5-flash-lite, gpt-4o, gpt-4o-mini, gpt-5.4, gpt-5.4-mini"),
796
+ .describe("AI model to use for generating research questions: claude-opus-5, claude-sonnet-5, claude-fable-5, gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite, grok-4.1-fast-non-reasoning, grok-4.1-fast-reasoning, gpt-4o, gpt-4o-mini, gpt-5.4, gpt-5.4-mini, gpt-5.6-terra, gpt-5.6-sol"),
734
797
  });
735
798
  export const GenerateResponsesFromGraphSchema = GenerateResponsesFromGraphSchemaBase.refine((data) => (data.text !== undefined && data.text.trim().length > 0) ||
736
799
  (data.url !== undefined && data.url.length > 0) ||
@@ -823,6 +886,7 @@ const GenerateOverlapGraphFromTextsSchemaBase = z.object({
823
886
  .array(contextItemTextUrlOrGraphSchema)
824
887
  .min(2, "At least two contexts are required for overlap")
825
888
  .describe("Array of sources to analyze and find content overlaps for. Each item is an object with exactly one of: { text: string }, { statements: string[] } (optionally with categories / timestamps), { url: string }, or { graphName: string }. Example: [{ text: '...' }, { url: 'https://...' }, { graphName: 'my-graph' }]."),
889
+ categoriesAsNodes: categoriesAsNodesField,
826
890
  modifyAnalyzedText: z
827
891
  .enum(["none", "detectEntities", "extractEntitiesOnly"])
828
892
  .default("none")
@@ -847,6 +911,7 @@ const GenerateDifferenceGraphFromTextsSchemaBase = z.object({
847
911
  .array(contextItemTextUrlOrGraphSchema)
848
912
  .min(2, "At least two contexts (target + one reference) are required")
849
913
  .describe("Array where the FIRST item is the target to analyze for missing parts; REMAINING items are reference sources. Each item is an object with exactly one of: { text: string }, { statements: string[] } (optionally with categories / timestamps), { url: string }, or { graphName: string }. Example: [{ text: '...' }, { url: 'https://...' }, { graphName: 'my-graph' }]."),
914
+ categoriesAsNodes: categoriesAsNodesField,
850
915
  modifyAnalyzedText: z
851
916
  .enum(["none", "detectEntities", "extractEntitiesOnly"])
852
917
  .default("none")
@@ -1196,6 +1261,7 @@ export const GenerateSEOGraphSchema = z.object({
1196
1261
  .describe("URL to fetch content from for SEO analysis. Provide either this or text, not both."),
1197
1262
  statements: statementsField,
1198
1263
  categories: categoriesField,
1264
+ categoriesAsNodes: categoriesAsNodesField,
1199
1265
  contentToExtract: z
1200
1266
  .enum(["all", "header tags", "link tags"])
1201
1267
  .default("all")
@@ -1281,6 +1347,7 @@ export const DevelopTextToolSchemaBase = z.object({
1281
1347
  .describe("URL to fetch content from or YouTube video URL to fetch transcript. Provide one of: text, url, statements, or graphName."),
1282
1348
  statements: statementsField,
1283
1349
  categories: categoriesField,
1350
+ categoriesAsNodes: categoriesAsNodesField,
1284
1351
  timestamps: timestampsField,
1285
1352
  graphName: z
1286
1353
  .string()
@@ -1301,8 +1368,9 @@ export const DevelopTextToolSchemaBase = z.object({
1301
1368
  .describe("Shall we transcend and go beyond this text to relate to a broader discourse? If false, the focus is on this text only."),
1302
1369
  modelToUse: z
1303
1370
  .enum([
1304
- "claude-opus-4.6",
1305
- "claude-sonnet-4.6",
1371
+ "claude-opus-5",
1372
+ "claude-sonnet-5",
1373
+ "claude-fable-5",
1306
1374
  "gemini-2.5-pro",
1307
1375
  "gemini-2.5-flash",
1308
1376
  "gemini-2.5-flash-lite",
@@ -1312,9 +1380,11 @@ export const DevelopTextToolSchemaBase = z.object({
1312
1380
  "gpt-4o-mini",
1313
1381
  "gpt-5.4",
1314
1382
  "gpt-5.4-mini",
1383
+ "gpt-5.6-terra",
1384
+ "gpt-5.6-sol",
1315
1385
  ])
1316
1386
  .default("gpt-5.4")
1317
- .describe("AI model to use for generating insights: claude-opus-4.6, claude-sonnet-4.6, gemini-2.5-flash, gemini-2.5-flash-lite, gpt-4o, gpt-4o-mini, gpt-5.4, gpt-5.4-mini"),
1387
+ .describe("AI model to use for generating insights: claude-opus-5, claude-sonnet-5, claude-fable-5, gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite, grok-4.1-fast-non-reasoning, grok-4.1-fast-reasoning, gpt-4o, gpt-4o-mini, gpt-5.4, gpt-5.4-mini, gpt-5.6-terra, gpt-5.6-sol"),
1318
1388
  });
1319
1389
  export const DevelopTextToolSchema = DevelopTextToolSchemaBase.refine((data) => (data.text !== undefined && data.text.trim().length > 0) ||
1320
1390
  (data.url !== undefined && data.url.length > 0) ||
@@ -1347,4 +1417,335 @@ export const ListGraphsSchema = z.object({
1347
1417
  .describe("Filter by language code (e.g., 'EN', 'AUTO', 'DE', 'FR', 'ES', etc.)"),
1348
1418
  favorite: z.boolean().optional().describe("Filter by favorite status"),
1349
1419
  });
1420
+ // ---------------------------------------------------------------------------
1421
+ // Project learnings (see docs/drafts/project-learnings-graph.md)
1422
+ // ---------------------------------------------------------------------------
1423
+ const projectField = z
1424
+ .string()
1425
+ .min(1, "Project name is required")
1426
+ .describe("Name of the project the learnings belong to — the repo or folder name, git remote basename, or whatever the user calls it. Use the same name every time for the same project (call get_project_learnings without a project to list the names already in use). Becomes the graph name learn-<slug>.");
1427
+ export const EnableProjectLearningsSchema = z.object({
1428
+ project: projectField,
1429
+ });
1430
+ // Length parity between `types` and `statements` is checked in the handler
1431
+ // (a .refine() would hide `.shape`, which tool registration needs).
1432
+ export const AddProjectLearningsSchema = z.object({
1433
+ project: projectField,
1434
+ statements: z
1435
+ .array(z.string().min(1))
1436
+ .min(1)
1437
+ .max(10)
1438
+ .describe("One learning per statement, at most 2 sentences each, with at least two [[wikilinked]] entities (file paths, modules, concepts, tools). Only project knowledge that is not derivable from the code in a few reads, would have saved time up front, survived verification, and ideally connects things that are not obviously connected. Include a self-assessment of how the work went: what approach worked well in this project and should be repeated, and what should be done differently next time (type 'approach'). Never anything about the user; never secrets, hostnames, env values, or verbatim error output."),
1439
+ types: z
1440
+ .array(z.enum([
1441
+ "location",
1442
+ "trap",
1443
+ "convention",
1444
+ "decision",
1445
+ "workflow",
1446
+ "question",
1447
+ "approach",
1448
+ ]))
1449
+ .min(1)
1450
+ .max(10)
1451
+ .describe("One type per statement, parallel to `statements`: location (where X lives), trap (what went wrong first), convention (how things are done here), decision (what was chosen and why), workflow (how to run/test/build/deploy), question (open, unresolved), approach (self-assessment: what worked well and should be repeated, or what should be done differently next time in this project)."),
1452
+ confirm: z
1453
+ .boolean()
1454
+ .default(false)
1455
+ .describe("false (default) = dry run: returns what would be written (new vs reinforced duplicates) and writes nothing — show it to the user and ask whether to save. true = write. Pass true directly only when the user has said they don't want to be asked each time."),
1456
+ });
1457
+ export const GetProjectLearningsSchema = z.object({
1458
+ project: z
1459
+ .string()
1460
+ .optional()
1461
+ .describe("Project name (same as used when enabling). Omit to list the projects that have learnings enabled in this account."),
1462
+ prompt: z
1463
+ .string()
1464
+ .optional()
1465
+ .describe("The task or question at hand. Retrieves the most relevant learnings for it (GraphRAG) plus a structural overview of what is known. Use at the start of a substantive task."),
1466
+ entity: z
1467
+ .string()
1468
+ .optional()
1469
+ .describe("A file path, module, or concept. Returns every learning that mentions it. Use before working on an unfamiliar area."),
1470
+ type: z
1471
+ .enum(["location", "trap", "convention", "decision", "workflow", "question", "approach"])
1472
+ .optional()
1473
+ .describe("Only return learnings of this type (e.g. 'trap' for the fragile areas of the project, 'approach' for what worked well or should be done differently). Applies to the overview and prompt modes."),
1474
+ limit: z
1475
+ .number()
1476
+ .int()
1477
+ .min(1)
1478
+ .max(50)
1479
+ .default(15)
1480
+ .describe("Maximum number of learnings to return."),
1481
+ });
1482
+ // ---------------------------------------------------------------------------
1483
+ // Workflow feedback (see docs/drafts/workflow-feedback-tool.md)
1484
+ // ---------------------------------------------------------------------------
1485
+ export const SubmitWorkflowFeedbackSchema = z.object({
1486
+ workflow: z
1487
+ .string()
1488
+ .min(1)
1489
+ .describe("One sentence: what the user was trying to accomplish."),
1490
+ toolsUsed: z
1491
+ .array(z.string().min(1))
1492
+ .min(1)
1493
+ .describe(`Names of the ${brand.name} tools called in this workflow, in order.`),
1494
+ consumption: z
1495
+ .enum(["none", "some", "most"])
1496
+ .describe("How much of the tool output you carried into your reply to the user."),
1497
+ usedExample: z
1498
+ .string()
1499
+ .optional()
1500
+ .describe("Quote ONE specific item from the output that you used (a gap, a question, a cluster name, a bridge). Required when consumption is not 'none'. Never invent one."),
1501
+ novelty: z
1502
+ .enum(["nothing_new", "some_new", "mostly_new"])
1503
+ .describe("Did the output contain things you would NOT have produced from the source text on your own?"),
1504
+ taskFit: z
1505
+ .enum(["right_tool", "needed_another", "wrong_tool"])
1506
+ .describe("Was this the right tool for the request, or did you have to call another tool / do the work yourself to compensate?"),
1507
+ callsNeeded: z
1508
+ .number()
1509
+ .int()
1510
+ .min(1)
1511
+ .describe("How many InfraNodus calls it took to get a usable result (including retries with changed parameters)."),
1512
+ defects: z
1513
+ .array(z.enum([
1514
+ "too_generic",
1515
+ "off_topic",
1516
+ "wrong_language",
1517
+ "truncated",
1518
+ "duplicates",
1519
+ "too_long_to_read",
1520
+ "error",
1521
+ "empty",
1522
+ ]))
1523
+ .default([])
1524
+ .describe("Concrete problems observed in the output. Empty array if none."),
1525
+ userNext: z
1526
+ .enum(["built_on_it", "asked_followup", "ignored", "redirected", "unknown"])
1527
+ .default("unknown")
1528
+ .describe("Only if you can observe it: what the user did after your reply. Leave 'unknown' when reporting before the user has responded."),
1529
+ reason: z
1530
+ .string()
1531
+ .min(1)
1532
+ .describe("One line justifying the observations above."),
1533
+ });
1534
+ // ---------------------------------------------------------------------------
1535
+ // optimize_knowledge_base — structural feedback on a code base / vault / rule set
1536
+ // ---------------------------------------------------------------------------
1537
+ export const OptimizeKnowledgeBaseSchema = z.object({
1538
+ graphName: z
1539
+ .string()
1540
+ .optional()
1541
+ .describe(`Name of the saved ${brand.name} graph that represents the project: e.g. repo-<project>-digest or vault-<project>-digest (the LLM-written digest of how it works), repo-<project>-structure (the deterministic map of files, imports, exports), repo-<project>-docs, vault-<project>-links, or learn-<project>. Provide this or statements/text.`),
1542
+ statements: statementsField,
1543
+ categories: categoriesField,
1544
+ categoriesAsNodes: categoriesAsNodesField,
1545
+ text: z
1546
+ .string()
1547
+ .optional()
1548
+ .describe("Alternative to graphName: a digest of the project as text that YOU write after reading its files — one statement per line describing how it works (principles, rules, procedures, hand-offs, main ideas, gaps), in your own words, with [[wikilinks]] on the modules, concepts, tools, and files each statement is about, grouped under `## [[Topic]]` heading lines; no tags; 100–300 lines. Analyzed without saving unless saveAs is given."),
1549
+ saveAs: z
1550
+ .string()
1551
+ .optional()
1552
+ .describe("With statements/text: save the submitted digest as this graph first (e.g. repo-<project>-digest, vault-<project>-digest), then analyse the saved graph. `## [[Topic]]` heading lines become the parent of the statements under them. Makes compareWith available in the same call and keeps the digest for later questions. Use a name no other producer writes to: a graph created here is in parent mode, and appending generate_ontology_graph 'procedural' output (whose [type] tags are categories) to it would turn those tags into central nodes. Ignored when graphName is given."),
1553
+ focus: z
1554
+ .enum(["general", "codebase", "vault", "procedural"])
1555
+ .default("general")
1556
+ .describe("How to read the structure: 'codebase' (modules, features, integrations), 'vault' (notes, themes, bridge notes), 'procedural' (rules, frameworks, hand-offs between them), or 'general'. Changes the interpretation of the diagnosis, not the analysis."),
1557
+ compareWith: z
1558
+ .array(z.string().min(1))
1559
+ .max(2)
1560
+ .optional()
1561
+ .describe("Up to two other saved graphs of the same project to compare against (e.g. repo-<project>-structure when the primary is the digest, or docs when the primary is code). Each comparison reports what the other layer covers that the primary lacks, and the reverse — rules without code, code without documentation, features described but not built. Requires the primary to be a saved graph: graphName, or statements/text with saveAs."),
1562
+ includeLatent: z
1563
+ .boolean()
1564
+ .default(true)
1565
+ .describe("Also run the latent-topics pass (one extra AI call) to list under-developed areas with ideas on how to develop them. Default true."),
1566
+ modelToUse: z
1567
+ .enum([
1568
+ "claude-opus-5",
1569
+ "claude-sonnet-5",
1570
+ "claude-fable-5",
1571
+ "gemini-2.5-pro",
1572
+ "gemini-2.5-flash",
1573
+ "gemini-2.5-flash-lite",
1574
+ "grok-4.1-fast-non-reasoning",
1575
+ "grok-4.1-fast-reasoning",
1576
+ "gpt-4o",
1577
+ "gpt-4o-mini",
1578
+ "gpt-5.4",
1579
+ "gpt-5.4-mini",
1580
+ "gpt-5.6-terra",
1581
+ "gpt-5.6-sol",
1582
+ ])
1583
+ .default("gpt-5.4")
1584
+ .describe("AI model for the development suggestions and latent-topic ideas."),
1585
+ });
1586
+ // ---------------------------------------------------------------------------
1587
+ // delete_statements (see docs/drafts/delete-statements-tool.md)
1588
+ // ---------------------------------------------------------------------------
1589
+ // "Exactly one selector" is checked in the handler (a .refine() would hide
1590
+ // `.shape`, which tool registration needs). There is deliberately no
1591
+ // `userName`: the tool only ever addresses graphs in the caller's own account.
1592
+ export const DeleteStatementsSchema = z.object({
1593
+ graphName: z
1594
+ .string()
1595
+ .min(1, "graphName is required")
1596
+ .describe(`Name of the graph in your own ${brand.name} account to delete from. It must already exist (use list_graphs to check the exact name); other users' graphs cannot be targeted and this tool never creates a graph.`),
1597
+ categories: z
1598
+ .array(z.string().min(1))
1599
+ .optional()
1600
+ .describe("Delete every statement that carries any of these category labels (exact match). Categories are the source labels statements were uploaded with — a file path, a page name, the [[label]] parent from a '## [[Topic]]' heading — so this is how you remove everything that came from one source before re-uploading its new version with create_knowledge_graph to the same graphName."),
1601
+ statements: z
1602
+ .array(z.string().min(1))
1603
+ .optional()
1604
+ .describe("Delete statements whose text equals one of these exactly (whitespace-normalised)."),
1605
+ query: z
1606
+ .string()
1607
+ .optional()
1608
+ .describe("Delete statements containing this text (case-insensitive substring), or matching a regular expression written as /pattern/flags."),
1609
+ before: z
1610
+ .string()
1611
+ .optional()
1612
+ .describe("Delete statements dated before this ISO 8601 date or datetime (e.g. 2026-08-01 or 2026-08-01T12:00:00Z). Combine with after for a window; the two together count as one selector."),
1613
+ after: z
1614
+ .string()
1615
+ .optional()
1616
+ .describe("Delete statements dated after this ISO 8601 date or datetime. Combine with before for a window."),
1617
+ deleteAll: z
1618
+ .boolean()
1619
+ .optional()
1620
+ .describe("Delete every statement but keep the graph: its name, URL, and settings (e.g. wikilinksMode) stay valid, so it can be rebuilt in place with create_knowledge_graph."),
1621
+ statementIds: z
1622
+ .array(z.number().int())
1623
+ .optional()
1624
+ .describe("Advanced: delete by statement id (ids come from an earlier dry run of this tool or from retrieve_from_knowledge_base). Ids that do not belong to this graph are ignored and reported as ignoredIds."),
1625
+ confirm: z
1626
+ .boolean()
1627
+ .default(false)
1628
+ .describe("Without this (the default) the call is a DRY RUN that only reports what would be deleted. Set true, with the same filter, only after the user has agreed to delete what the dry run showed. The deletion is irreversible."),
1629
+ });
1630
+ // ---------------------------------------------------------------------------
1631
+ // delete_graph
1632
+ // ---------------------------------------------------------------------------
1633
+ export const DeleteGraphSchema = z.object({
1634
+ graphName: z
1635
+ .string()
1636
+ .min(1, "graphName is required")
1637
+ .describe(`Exact name of the graph in your own ${brand.name} account to delete (use list_graphs to check it). Other users' graphs cannot be targeted.`),
1638
+ confirm: z
1639
+ .boolean()
1640
+ .default(false)
1641
+ .describe("Without this (the default) the call is a DRY RUN that only confirms the graph exists and reports what would be removed. Set true, with the same graphName, only after the user has agreed to delete that graph. The deletion is irreversible."),
1642
+ });
1643
+ // ---------------------------------------------------------------------------
1644
+ // update_statements (see docs/drafts/update-statements-tool.md)
1645
+ // ---------------------------------------------------------------------------
1646
+ /** One targeted edit for update_statements (Mode A). */
1647
+ export const UpdateStatementEditSchema = z.object({
1648
+ match: z
1649
+ .string()
1650
+ .min(1)
1651
+ .optional()
1652
+ .describe("The exact current text of the statement to edit (whitespace-normalised), e.g. as returned by analyze_existing_graph_by_name with includeStatements, retrieve_from_knowledge_base, or an earlier dry run. Give exactly one of match or statementId."),
1653
+ statementId: z
1654
+ .number()
1655
+ .int()
1656
+ .optional()
1657
+ .describe("Advanced: the id of the statement to edit (ids come from a dry run of this tool, of delete_statements, or from retrieve_from_knowledge_base). Give exactly one of match or statementId."),
1658
+ content: z
1659
+ .string()
1660
+ .min(1)
1661
+ .optional()
1662
+ .describe("The new text of the statement (at most 1000 characters). [[wikilinks]] are honoured as in create_knowledge_graph. Omit to keep the current text."),
1663
+ categories: z
1664
+ .array(z.string().min(1))
1665
+ .optional()
1666
+ .describe("The new full list of category labels for this statement (replaces the current list). Omit to keep the current categories."),
1667
+ timestamp: z
1668
+ .string()
1669
+ .optional()
1670
+ .describe("The new ISO 8601 date or datetime for this statement (e.g. 2026-08-01 or 2026-08-01T12:00:00Z). Omit to keep the current one."),
1671
+ });
1672
+ // Cross-field rules (Mode A xor Mode B, exactly one selector, at least one
1673
+ // operation, one of match/statementId per edit) are checked in the handler
1674
+ // (a .refine() would hide `.shape`, which tool registration needs). No
1675
+ // `userName`: the tool only ever addresses graphs in the caller's own account.
1676
+ export const UpdateStatementsSchema = z.object({
1677
+ graphName: z
1678
+ .string()
1679
+ .min(1, "graphName is required")
1680
+ .describe(`Name of the graph in your own ${brand.name} account to edit. It must already exist (use list_graphs to check the exact name); other users' graphs cannot be targeted and this tool never creates a graph.`),
1681
+ edits: z
1682
+ .array(UpdateStatementEditSchema)
1683
+ .optional()
1684
+ .describe("Mode A — rewrite specific statements. Each item names one statement (exactly one of match — its exact current text — or statementId) and at least one field to change (content, categories, timestamp). Cannot be combined with the Mode B fields below. Items that match no statement are reported as unmatched, not errors."),
1685
+ categories: z
1686
+ .array(z.string().min(1))
1687
+ .optional()
1688
+ .describe("Mode B selector: every statement carrying any of these category labels (exact match) — everything uploaded under one source (a file path, a page name, the [[label]] parent of a '## [[Topic]]' heading)."),
1689
+ statements: z
1690
+ .array(z.string().min(1))
1691
+ .optional()
1692
+ .describe("Mode B selector: statements whose text equals one of these exactly (whitespace-normalised)."),
1693
+ query: z
1694
+ .string()
1695
+ .optional()
1696
+ .describe("Mode B selector: statements containing this text (case-insensitive substring), or matching a regular expression written as /pattern/flags."),
1697
+ before: z
1698
+ .string()
1699
+ .optional()
1700
+ .describe("Mode B selector: statements dated before this ISO 8601 date or datetime (e.g. 2026-08-01 or 2026-08-01T12:00:00Z). Combine with after for a window; the two together count as one selector."),
1701
+ after: z
1702
+ .string()
1703
+ .optional()
1704
+ .describe("Mode B selector: statements dated after this ISO 8601 date or datetime. Combine with before for a window."),
1705
+ all: z
1706
+ .boolean()
1707
+ .optional()
1708
+ .describe("Mode B selector: every statement in the graph (e.g. to rename a [[concept]] or a source path everywhere with replace)."),
1709
+ statementIds: z
1710
+ .array(z.number().int())
1711
+ .optional()
1712
+ .describe("Mode B selector (advanced): statements by id (ids come from an earlier dry run of this tool or of delete_statements, or from retrieve_from_knowledge_base). Ids that do not belong to this graph are reported as unmatched."),
1713
+ set: z
1714
+ .object({
1715
+ addCategories: z
1716
+ .array(z.string().min(1))
1717
+ .optional()
1718
+ .describe("Category labels to add to every selected statement (existing ones are kept)."),
1719
+ removeCategories: z
1720
+ .array(z.string().min(1))
1721
+ .optional()
1722
+ .describe("Category labels to remove from every selected statement."),
1723
+ categories: z
1724
+ .array(z.string().min(1))
1725
+ .optional()
1726
+ .describe("The new full list of category labels for every selected statement (replaces the current list). Cannot be combined with addCategories or removeCategories."),
1727
+ timestamp: z
1728
+ .string()
1729
+ .optional()
1730
+ .describe("The new ISO 8601 date or datetime for every selected statement."),
1731
+ })
1732
+ .optional()
1733
+ .describe("Mode B operation: change the metadata of every selected statement — addCategories, removeCategories, categories (full replacement; exclusive with add/remove), timestamp. At least one of set or replace is required in Mode B."),
1734
+ replace: z
1735
+ .object({
1736
+ pattern: z
1737
+ .string()
1738
+ .min(1)
1739
+ .describe("What to find in the text of every selected statement: a plain substring (every occurrence, case-sensitive) or a regular expression written as /pattern/flags (e.g. /\\[\\[Old Name\\]\\]/g)."),
1740
+ with: z
1741
+ .string()
1742
+ .describe("The replacement text ($1-style backreferences work with a regex pattern). An empty string removes the match. The resulting statement must stay at most 1000 characters."),
1743
+ })
1744
+ .optional()
1745
+ .describe("Mode B operation: find-and-replace in the text of every selected statement, e.g. to rename a [[concept]] or a source path across the graph. At least one of set or replace is required in Mode B."),
1746
+ confirm: z
1747
+ .boolean()
1748
+ .default(false)
1749
+ .describe("Without this (the default) the call is a DRY RUN that only reports what would change (before → after for each statement). Set true, with the same arguments, only after the user has agreed to the changes the dry run showed. The edit is irreversible: the previous text survives only in the dry-run output."),
1750
+ });
1350
1751
  //# sourceMappingURL=index.js.map