@feelingmindful/thinking-graph 1.11.0 → 1.12.0

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.
@@ -3,7 +3,7 @@ import type { ThinkingGraph } from '../engine/graph.js';
3
3
  import { type VaultBridge } from '../vault/bridge.js';
4
4
  export declare const researchSchema: z.ZodObject<{
5
5
  query: z.ZodString;
6
- intent: z.ZodDefault<z.ZodEnum<["fact_check", "explore", "compare", "how_to", "current_state"]>>;
6
+ intent: z.ZodDefault<z.ZodEnum<["fact_check", "explore", "compare", "how_to", "current_state", "grounded_qa"]>>;
7
7
  context: z.ZodOptional<z.ZodString>;
8
8
  researchId: z.ZodOptional<z.ZodString>;
9
9
  findings: z.ZodOptional<z.ZodArray<z.ZodObject<{
@@ -23,9 +23,11 @@ export declare const researchSchema: z.ZodObject<{
23
23
  scrapeUrls: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
24
24
  recencyFilter: z.ZodOptional<z.ZodEnum<["hour", "day", "week", "month", "year"]>>;
25
25
  domainFilter: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
26
+ notebookId: z.ZodOptional<z.ZodString>;
27
+ skipGrounded: z.ZodOptional<z.ZodEffects<z.ZodBoolean, boolean, unknown>>;
26
28
  }, "strip", z.ZodTypeAny, {
27
29
  query: string;
28
- intent: "fact_check" | "explore" | "compare" | "how_to" | "current_state";
30
+ intent: "fact_check" | "explore" | "compare" | "how_to" | "current_state" | "grounded_qa";
29
31
  projectId?: string | undefined;
30
32
  context?: string | undefined;
31
33
  researchId?: string | undefined;
@@ -37,10 +39,12 @@ export declare const researchSchema: z.ZodObject<{
37
39
  scrapeUrls?: string[] | undefined;
38
40
  recencyFilter?: "hour" | "day" | "week" | "month" | "year" | undefined;
39
41
  domainFilter?: string[] | undefined;
42
+ notebookId?: string | undefined;
43
+ skipGrounded?: boolean | undefined;
40
44
  }, {
41
45
  query: string;
42
46
  projectId?: string | undefined;
43
- intent?: "fact_check" | "explore" | "compare" | "how_to" | "current_state" | undefined;
47
+ intent?: "fact_check" | "explore" | "compare" | "how_to" | "current_state" | "grounded_qa" | undefined;
44
48
  context?: string | undefined;
45
49
  researchId?: string | undefined;
46
50
  findings?: {
@@ -51,6 +55,8 @@ export declare const researchSchema: z.ZodObject<{
51
55
  scrapeUrls?: string[] | undefined;
52
56
  recencyFilter?: "hour" | "day" | "week" | "month" | "year" | undefined;
53
57
  domainFilter?: string[] | undefined;
58
+ notebookId?: string | undefined;
59
+ skipGrounded?: unknown;
54
60
  }>;
55
61
  export type ResearchInput = z.infer<typeof researchSchema>;
56
62
  export declare function researchHandler(graph: ThinkingGraph, input: ResearchInput, vault?: VaultBridge, projectSlug?: string): Promise<{
@@ -7,7 +7,11 @@ const RESEARCH_INTENTS = [
7
7
  'compare', // Compare options, libraries, approaches
8
8
  'how_to', // Find implementation guidance
9
9
  'current_state', // Get current state of something (version, status, etc.)
10
+ 'grounded_qa', // Query a curated knowledge base (NotebookLM notebook) — zero hallucinations
10
11
  ];
12
+ // Intents that should preferentially route through a NotebookLM notebook when available.
13
+ // These are the cases where a curated, citation-backed source is most valuable.
14
+ const GROUNDED_PREFERRED_INTENTS = new Set(['how_to', 'fact_check', 'current_state', 'grounded_qa']);
11
15
  const findingSchema = z.object({
12
16
  content: z.string().describe('What was found'),
13
17
  source: z.string().optional().describe('URL or citation'),
@@ -26,10 +30,51 @@ export const researchSchema = z.object({
26
30
  scrapeUrls: z.array(z.string()).optional().describe('Specific URLs to scrape with Firecrawl'),
27
31
  recencyFilter: z.enum(['hour', 'day', 'week', 'month', 'year']).optional().describe('How recent results should be'),
28
32
  domainFilter: z.array(z.string()).optional().describe('Restrict to these domains'),
33
+ notebookId: z.string().optional().describe('Specific NotebookLM notebook ID to query. If omitted, action plan will list notebooks first so the caller can pick the best match.'),
34
+ skipGrounded: coerceBool.optional().describe('Skip NotebookLM step even when it would normally auto-prepend'),
29
35
  });
36
+ function buildGroundedSteps(input) {
37
+ const steps = [];
38
+ const query = input.query;
39
+ // If caller specified a notebookId, select it then ask directly.
40
+ if (input.notebookId) {
41
+ steps.push({
42
+ tool: 'mcp__notebooklm__select_notebook',
43
+ description: 'Select the specified NotebookLM notebook',
44
+ args: { id: input.notebookId },
45
+ });
46
+ steps.push({
47
+ tool: 'mcp__notebooklm__ask_question',
48
+ description: 'Ask NotebookLM (grounded, citation-backed)',
49
+ args: { question: query },
50
+ });
51
+ return steps;
52
+ }
53
+ // Otherwise: search the library for the best match, then the agent picks one and asks.
54
+ steps.push({
55
+ tool: 'mcp__notebooklm__search_notebooks',
56
+ description: 'Find a NotebookLM notebook matching this query. Skip remaining NotebookLM steps if no match.',
57
+ args: { query },
58
+ });
59
+ steps.push({
60
+ tool: 'mcp__notebooklm__ask_question',
61
+ description: 'Ask the selected NotebookLM notebook. Only run after search_notebooks returns a match; fall back to the web-grounded steps below if the library has no relevant notebook.',
62
+ args: { question: query },
63
+ });
64
+ return steps;
65
+ }
30
66
  function buildActionPlan(input) {
31
67
  const steps = [];
32
68
  const query = input.query;
69
+ // Grounded NotebookLM path (preferred for how_to / fact_check / current_state / grounded_qa).
70
+ const shouldPrependGrounded = !input.skipGrounded && GROUNDED_PREFERRED_INTENTS.has(input.intent ?? 'explore');
71
+ if (shouldPrependGrounded) {
72
+ steps.push(...buildGroundedSteps(input));
73
+ }
74
+ // grounded_qa is NotebookLM-only — no web fallback steps.
75
+ if (input.intent === 'grounded_qa') {
76
+ return steps;
77
+ }
33
78
  // Choose Perplexity tool based on intent
34
79
  switch (input.intent) {
35
80
  case 'fact_check':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feelingmindful/thinking-graph",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "Persistent graph-based MCP thinking server for the feeling-mindful plugin marketplace",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",