@techwavedev/agi-agent-kit 1.1.7 → 1.2.7

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 (56) hide show
  1. package/CHANGELOG.md +142 -1
  2. package/README.md +195 -15
  3. package/bin/init.js +154 -5
  4. package/package.json +6 -3
  5. package/templates/base/AGENTS.md +54 -23
  6. package/templates/base/README.md +327 -0
  7. package/templates/base/directives/memory_integration.md +95 -0
  8. package/templates/base/execution/memory_manager.py +309 -0
  9. package/templates/base/execution/session_boot.py +218 -0
  10. package/templates/base/execution/session_init.py +320 -0
  11. package/templates/base/requirements.txt +45 -6
  12. package/templates/base/skill-creator/SKILL_skillcreator.md +3 -3
  13. package/templates/skills/knowledge/design-md/README.md +0 -0
  14. package/templates/skills/knowledge/design-md/SKILL.md +0 -0
  15. package/templates/skills/knowledge/design-md/examples/DESIGN.md +0 -0
  16. package/templates/skills/knowledge/intelligent-routing/SKILL.md +237 -164
  17. package/templates/skills/knowledge/notebooklm-rag/SKILL.md +216 -0
  18. package/templates/skills/knowledge/notebooklm-rag/requirements.txt +9 -0
  19. package/templates/skills/knowledge/notebooklm-rag/scripts/ask_question.py +237 -0
  20. package/templates/skills/knowledge/notebooklm-rag/scripts/auth_manager.py +307 -0
  21. package/templates/skills/knowledge/notebooklm-rag/scripts/browser_utils.py +101 -0
  22. package/templates/skills/knowledge/notebooklm-rag/scripts/cleanup_manager.py +87 -0
  23. package/templates/skills/knowledge/notebooklm-rag/scripts/config.py +45 -0
  24. package/templates/skills/knowledge/notebooklm-rag/scripts/notebook_manager.py +334 -0
  25. package/templates/skills/knowledge/notebooklm-rag/scripts/run.py +92 -0
  26. package/templates/skills/knowledge/notebooklm-rag/scripts/setup_environment.py +68 -0
  27. package/templates/skills/knowledge/parallel-agents/SKILL.md +345 -73
  28. package/templates/skills/knowledge/plugin-discovery/SKILL.md +581 -0
  29. package/templates/skills/knowledge/plugin-discovery/scripts/platform_setup.py +1083 -0
  30. package/templates/skills/knowledge/react-components/README.md +0 -0
  31. package/templates/skills/knowledge/react-components/SKILL.md +0 -0
  32. package/templates/skills/knowledge/react-components/examples/gold-standard-card.tsx +0 -0
  33. package/templates/skills/knowledge/react-components/package-lock.json +0 -0
  34. package/templates/skills/knowledge/react-components/package.json +0 -0
  35. package/templates/skills/knowledge/react-components/resources/architecture-checklist.md +0 -0
  36. package/templates/skills/knowledge/react-components/resources/component-template.tsx +0 -0
  37. package/templates/skills/knowledge/react-components/resources/stitch-api-reference.md +0 -0
  38. package/templates/skills/knowledge/react-components/resources/style-guide.json +0 -0
  39. package/templates/skills/knowledge/react-components/scripts/validate.js +0 -0
  40. package/templates/skills/knowledge/self-update/SKILL.md +0 -0
  41. package/templates/skills/knowledge/self-update/scripts/update_kit.py +0 -0
  42. package/templates/skills/knowledge/stitch-loop/README.md +0 -0
  43. package/templates/skills/knowledge/stitch-loop/SKILL.md +3 -3
  44. package/templates/skills/knowledge/stitch-loop/examples/SITE.md +0 -0
  45. package/templates/skills/knowledge/stitch-loop/examples/next-prompt.md +0 -0
  46. package/templates/skills/knowledge/stitch-loop/resources/baton-schema.md +0 -0
  47. package/templates/skills/knowledge/stitch-loop/resources/site-template.md +0 -0
  48. package/templates/skills/stitch-loop/SKILL.md +3 -3
  49. package/templates/skills/core/qdrant-memory/scripts/__pycache__/embedding_utils.cpython-314.pyc +0 -0
  50. package/templates/skills/core/qdrant-memory/scripts/__pycache__/init_collection.cpython-314.pyc +0 -0
  51. package/templates/skills/knowledge/SKILLS_CATALOG.md +0 -796
  52. package/templates/skills/knowledge/jira/scripts/__pycache__/jira_client.cpython-314.pyc +0 -0
  53. package/templates/skills/knowledge/notebooklm-mcp/SKILL.md +0 -71
  54. package/templates/skills/knowledge/notebooklm-mcp/assets/example_asset.txt +0 -24
  55. package/templates/skills/knowledge/notebooklm-mcp/references/api_reference.md +0 -34
  56. package/templates/skills/knowledge/notebooklm-mcp/scripts/example.py +0 -19
@@ -0,0 +1,216 @@
1
+ ---
2
+ name: notebooklm-rag
3
+ description: "Deep RAG layer powered by Google NotebookLM + Gemini. The agent autonomously manages notebooks via MCP tools — authentication, library management, querying, follow-ups, and caching. Opt-in for users with a Google account. Default RAG is qdrant-memory. Triggers on: '@notebooklm', 'research my docs', 'deep search', 'query my notebook', 'check my notebooks'."
4
+ ---
5
+
6
+ # NotebookLM Deep RAG
7
+
8
+ > **This is a Deep RAG tool.** The agent uses NotebookLM as an autonomous knowledge backend via MCP tools. It handles auth, notebooks, queries, follow-ups, and caching — fully hands-free.
9
+ >
10
+ > **Opt-in:** Requires a Google account with NotebookLM. Default RAG uses `qdrant-memory` (local, offline, no account needed).
11
+
12
+ ## Architecture
13
+
14
+ ```
15
+ User question
16
+
17
+ Agent checks Qdrant cache → hit? → return cached answer (0 cost)
18
+ ↓ miss
19
+ Agent checks NotebookLM auth → not authenticated? → setup_auth (opens browser)
20
+ ↓ authenticated
21
+ Agent resolves notebook → list_notebooks / search_notebooks / select_notebook
22
+
23
+ Agent asks question → ask_question (browser automation, Gemini-grounded answer)
24
+
25
+ Agent evaluates answer → gaps? → ask follow-up automatically
26
+ ↓ complete
27
+ Agent stores in Qdrant → cache for future use
28
+
29
+ Agent responds to user with synthesized answer
30
+ ```
31
+
32
+ ## MCP Tools Reference
33
+
34
+ The agent has direct access to these tools. Use them autonomously.
35
+
36
+ ### Authentication
37
+
38
+ | Tool | When |
39
+ | ------------ | --------------------------------------------- |
40
+ | `get_health` | First — always check auth status |
41
+ | `setup_auth` | One-time Google login (opens visible browser) |
42
+ | `re_auth` | Switch account or fix expired session |
43
+
44
+ ### Library Management
45
+
46
+ | Tool | When |
47
+ | ------------------- | ----------------------------------------------------------------- |
48
+ | `list_notebooks` | See all registered notebooks |
49
+ | `add_notebook` | Register a new notebook (url, name, description, topics required) |
50
+ | `remove_notebook` | Remove a notebook from library |
51
+ | `update_notebook` | Update notebook metadata |
52
+ | `search_notebooks` | Find notebooks by topic/keyword |
53
+ | `select_notebook` | Set active notebook (used as default for queries) |
54
+ | `get_notebook` | Get details of a specific notebook |
55
+ | `get_library_stats` | Library overview |
56
+
57
+ ### Querying
58
+
59
+ | Tool | When |
60
+ | --------------- | ------------------------------------- |
61
+ | `ask_question` | Query a notebook — core research tool |
62
+ | `list_sessions` | Check active browser sessions |
63
+ | `close_session` | Close a session when done |
64
+ | `reset_session` | Clear session history |
65
+
66
+ ### Maintenance
67
+
68
+ | Tool | When |
69
+ | -------------- | ------------------------------ |
70
+ | `cleanup_data` | Clean browser data, fix issues |
71
+
72
+ ## Autonomous Workflow
73
+
74
+ ### On Any Research Request:
75
+
76
+ 1. **Check Qdrant first** — `memory_manager.py auto --query "..."`. If cache hit, return immediately.
77
+
78
+ 2. **Check auth** — `get_health`. If not authenticated, run `setup_auth` and tell user a browser will open.
79
+
80
+ 3. **Resolve notebook** — `list_notebooks`. If user mentions a topic, `search_notebooks`. If no notebooks exist, ask user for a NotebookLM URL and `add_notebook`.
81
+
82
+ 4. **Ask the question** — `ask_question` with the resolved notebook. Can pass `notebook_id` (from library) or `notebook_url` (direct URL).
83
+
84
+ 5. **Follow up** — Every answer ends with "Is that ALL you need to know?" The agent MUST:
85
+ - Compare answer to original request
86
+ - Identify gaps
87
+ - Ask follow-up questions automatically (include full context — each question is a new browser session)
88
+ - Repeat until information is complete
89
+
90
+ 6. **Cache in Qdrant** — Store result with `memory_manager.py store` and `cache-store`.
91
+
92
+ 7. **Respond** — Synthesize all answers into a cohesive response.
93
+
94
+ ### On "Add a notebook":
95
+
96
+ **Smart Add** — If user provides a URL but no details:
97
+
98
+ 1. `ask_question` with `notebook_url` and question: "What is the content of this notebook? What topics are covered? Provide a brief overview."
99
+ 2. Use the answer to fill in `name`, `description`, `topics`
100
+ 3. `add_notebook` with discovered metadata
101
+
102
+ **Manual Add** — If user provides all details directly, just `add_notebook`.
103
+
104
+ ### On Notebook Management:
105
+
106
+ - "List my notebooks" → `list_notebooks`
107
+ - "Remove X" → Confirm with user → `remove_notebook`
108
+ - "Switch to X" → `select_notebook`
109
+ - "Update X description" → `update_notebook`
110
+ - "Search for X" → `search_notebooks`
111
+
112
+ ## Qdrant Integration (Context Keeping)
113
+
114
+ NotebookLM answers are cached in Qdrant. Prior research is recalled automatically.
115
+
116
+ ### Before Query
117
+
118
+ ```bash
119
+ python3 execution/memory_manager.py auto --query "<research question>"
120
+ ```
121
+
122
+ - `cache_hit: true` → Skip browser, return cached answer
123
+ - `source: memory` → Inject prior context into the question
124
+ - `source: none` → Proceed with NotebookLM query
125
+
126
+ ### After Query
127
+
128
+ ```bash
129
+ python3 execution/memory_manager.py store \
130
+ --content "Q: [question] A: [answer]" \
131
+ --type technical \
132
+ --project notebooklm-research \
133
+ --tags notebooklm [notebook-name] [topic]
134
+
135
+ python3 execution/memory_manager.py cache-store \
136
+ --query "[question]" \
137
+ --response "[synthesized answer]"
138
+ ```
139
+
140
+ ### Context Keeping
141
+
142
+ - Prior research on same topic is auto-recalled
143
+ - Previous findings enrich follow-up questions
144
+ - Each session builds compound knowledge
145
+
146
+ ## MCP Server Setup
147
+
148
+ The NotebookLM MCP server must be configured in the AI host:
149
+
150
+ ### Claude Desktop / Claude Code
151
+
152
+ ```json
153
+ {
154
+ "mcpServers": {
155
+ "notebooklm": {
156
+ "command": "npx",
157
+ "args": ["-y", "@anthropic/notebooklm-mcp"]
158
+ }
159
+ }
160
+ }
161
+ ```
162
+
163
+ ### Opencode
164
+
165
+ ```json
166
+ {
167
+ "mcpServers": {
168
+ "notebooklm": {
169
+ "command": "npx",
170
+ "args": ["-y", "@anthropic/notebooklm-mcp"]
171
+ }
172
+ }
173
+ }
174
+ ```
175
+
176
+ If MCP is not configured, fall back to the Python scripts in `scripts/` (see Fallback section below).
177
+
178
+ ## Fallback: Python Scripts
179
+
180
+ When MCP is not available, use the bundled scripts via `run.py`:
181
+
182
+ ```bash
183
+ python scripts/run.py auth_manager.py status # Check auth
184
+ python scripts/run.py auth_manager.py setup # Authenticate
185
+ python scripts/run.py notebook_manager.py list # List notebooks
186
+ python scripts/run.py notebook_manager.py add --url URL --name NAME --description DESC --topics TOPICS
187
+ python scripts/run.py ask_question.py --question "..." # Query
188
+ python scripts/run.py ask_question.py --question "..." --notebook-url "https://..."
189
+ python scripts/run.py cleanup_manager.py --confirm # Cleanup
190
+ ```
191
+
192
+ The `run.py` wrapper auto-creates `.venv`, installs dependencies (patchright, python-dotenv), and installs Chrome.
193
+
194
+ ## Troubleshooting
195
+
196
+ | Problem | Solution |
197
+ | ------------------------ | ------------------------------------------------------- |
198
+ | Not authenticated | `setup_auth` (browser opens for Google login) |
199
+ | Rate limit (50/day free) | Wait 24h or `re_auth` with different Google account |
200
+ | Browser crashes | `cleanup_data(preserve_library=true)` then `setup_auth` |
201
+ | Stale cached answer | Re-query or clear Qdrant cache |
202
+ | Notebook not found | `list_notebooks`, then `add_notebook` if missing |
203
+ | MCP not available | Use fallback Python scripts via `run.py` |
204
+
205
+ ## Limitations
206
+
207
+ - Rate limits: 50 queries/day (free), 250/day (Google AI Pro)
208
+ - Manual upload: User must add documents to NotebookLM first
209
+ - Browser overhead: Few seconds per query
210
+ - No live notebook discovery: User must provide URLs to register notebooks
211
+
212
+ ## Credits
213
+
214
+ MCP server: [PleasePrompto/notebooklm-mcp](https://github.com/PleasePrompto/notebooklm-mcp)
215
+ Browser automation: [PleasePrompto/notebooklm-skill](https://github.com/PleasePrompto/notebooklm-skill) (MIT License)
216
+ Adapted for the Agi Agent Framework with Qdrant memory integration.
@@ -0,0 +1,9 @@
1
+ # NotebookLM RAG Skill Dependencies
2
+ # These will be installed in the skill's local .venv
3
+
4
+ # Core browser automation with anti-detection
5
+ # Note: After installation, run: patchright install chrome
6
+ patchright==1.55.2
7
+
8
+ # Environment management
9
+ python-dotenv==1.0.0
@@ -0,0 +1,237 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Simple NotebookLM Question Interface
4
+ Adapted from PleasePrompto/notebooklm-skill (MIT License)
5
+
6
+ Implements hybrid auth approach:
7
+ - Persistent browser profile (user_data_dir) for fingerprint consistency
8
+ - Manual cookie injection from state.json for session cookies (Playwright bug workaround)
9
+ See: https://github.com/microsoft/playwright/issues/36139
10
+ """
11
+
12
+ import argparse
13
+ import sys
14
+ import time
15
+ import re
16
+ from pathlib import Path
17
+
18
+ from patchright.sync_api import sync_playwright
19
+
20
+ # Add parent directory to path
21
+ sys.path.insert(0, str(Path(__file__).parent))
22
+
23
+ from auth_manager import AuthManager
24
+ from notebook_manager import NotebookLibrary
25
+ from config import QUERY_INPUT_SELECTORS, RESPONSE_SELECTORS
26
+ from browser_utils import BrowserFactory, StealthUtils
27
+
28
+
29
+ # Since we don't have persistent sessions, we encourage comprehensive questions
30
+ FOLLOW_UP_REMINDER = (
31
+ "\n\nEXTREMELY IMPORTANT: Is that ALL you need to know? "
32
+ "You can always ask another question! Think about it carefully: "
33
+ "before you reply to the user, review their original request and this answer. "
34
+ "If anything is still unclear or missing, ask me another comprehensive question "
35
+ "that includes all necessary context (since each question opens a new browser session)."
36
+ )
37
+
38
+
39
+ def ask_notebooklm(question: str, notebook_url: str, headless: bool = True) -> str:
40
+ """
41
+ Ask a question to NotebookLM
42
+
43
+ Args:
44
+ question: Question to ask
45
+ notebook_url: NotebookLM notebook URL
46
+ headless: Run browser in headless mode
47
+
48
+ Returns:
49
+ Answer text from NotebookLM
50
+ """
51
+ auth = AuthManager()
52
+
53
+ if not auth.is_authenticated():
54
+ print("⚠️ Not authenticated. Run: python scripts/run.py auth_manager.py setup")
55
+ return None
56
+
57
+ print(f"💬 Asking: {question}")
58
+ print(f"📚 Notebook: {notebook_url}")
59
+
60
+ playwright = None
61
+ context = None
62
+
63
+ try:
64
+ playwright = sync_playwright().start()
65
+
66
+ context = BrowserFactory.launch_persistent_context(
67
+ playwright,
68
+ headless=headless
69
+ )
70
+
71
+ page = context.new_page()
72
+ print(" 🌐 Opening notebook...")
73
+ page.goto(notebook_url, wait_until="domcontentloaded")
74
+
75
+ page.wait_for_url(re.compile(r"^https://notebooklm\.google\.com/"), timeout=10000)
76
+
77
+ print(" ⏳ Waiting for query input...")
78
+ query_element = None
79
+
80
+ for selector in QUERY_INPUT_SELECTORS:
81
+ try:
82
+ query_element = page.wait_for_selector(
83
+ selector,
84
+ timeout=10000,
85
+ state="visible"
86
+ )
87
+ if query_element:
88
+ print(f" ✓ Found input: {selector}")
89
+ break
90
+ except:
91
+ continue
92
+
93
+ if not query_element:
94
+ print(" ❌ Could not find query input")
95
+ return None
96
+
97
+ print(" ⏳ Typing question...")
98
+
99
+ input_selector = QUERY_INPUT_SELECTORS[0]
100
+ StealthUtils.human_type(page, input_selector, question)
101
+
102
+ print(" 📤 Submitting...")
103
+ page.keyboard.press("Enter")
104
+
105
+ StealthUtils.random_delay(500, 1500)
106
+
107
+ print(" ⏳ Waiting for answer...")
108
+
109
+ answer = None
110
+ stable_count = 0
111
+ last_text = None
112
+ deadline = time.time() + 120 # 2 minutes timeout
113
+
114
+ while time.time() < deadline:
115
+ try:
116
+ thinking_element = page.query_selector('div.thinking-message')
117
+ if thinking_element and thinking_element.is_visible():
118
+ time.sleep(1)
119
+ continue
120
+ except:
121
+ pass
122
+
123
+ for selector in RESPONSE_SELECTORS:
124
+ try:
125
+ elements = page.query_selector_all(selector)
126
+ if elements:
127
+ latest = elements[-1]
128
+ text = latest.inner_text().strip()
129
+
130
+ if text:
131
+ if text == last_text:
132
+ stable_count += 1
133
+ if stable_count >= 3:
134
+ answer = text
135
+ break
136
+ else:
137
+ stable_count = 0
138
+ last_text = text
139
+ except:
140
+ continue
141
+
142
+ if answer:
143
+ break
144
+
145
+ time.sleep(1)
146
+
147
+ if not answer:
148
+ print(" ❌ Timeout waiting for answer")
149
+ return None
150
+
151
+ print(" ✅ Got answer!")
152
+ return answer + FOLLOW_UP_REMINDER
153
+
154
+ except Exception as e:
155
+ print(f" ❌ Error: {e}")
156
+ import traceback
157
+ traceback.print_exc()
158
+ return None
159
+
160
+ finally:
161
+ if context:
162
+ try:
163
+ context.close()
164
+ except:
165
+ pass
166
+
167
+ if playwright:
168
+ try:
169
+ playwright.stop()
170
+ except:
171
+ pass
172
+
173
+
174
+ def main():
175
+ parser = argparse.ArgumentParser(description='Ask NotebookLM a question')
176
+
177
+ parser.add_argument('--question', required=True, help='Question to ask')
178
+ parser.add_argument('--notebook-url', help='NotebookLM notebook URL')
179
+ parser.add_argument('--notebook-id', help='Notebook ID from library')
180
+ parser.add_argument('--show-browser', action='store_true', help='Show browser')
181
+
182
+ args = parser.parse_args()
183
+
184
+ # Resolve notebook URL
185
+ notebook_url = args.notebook_url
186
+
187
+ if not notebook_url and args.notebook_id:
188
+ library = NotebookLibrary()
189
+ notebook = library.get_notebook(args.notebook_id)
190
+ if notebook:
191
+ notebook_url = notebook['url']
192
+ else:
193
+ print(f"❌ Notebook '{args.notebook_id}' not found")
194
+ return 1
195
+
196
+ if not notebook_url:
197
+ library = NotebookLibrary()
198
+ active = library.get_active_notebook()
199
+ if active:
200
+ notebook_url = active['url']
201
+ print(f"📚 Using active notebook: {active['name']}")
202
+ else:
203
+ notebooks = library.list_notebooks()
204
+ if notebooks:
205
+ print("\n📚 Available notebooks:")
206
+ for nb in notebooks:
207
+ mark = " [ACTIVE]" if nb.get('id') == library.active_notebook_id else ""
208
+ print(f" {nb['id']}: {nb['name']}{mark}")
209
+ print("\nSpecify with --notebook-id or set active:")
210
+ print("python scripts/run.py notebook_manager.py activate --id ID")
211
+ else:
212
+ print("❌ No notebooks in library. Add one first:")
213
+ print("python scripts/run.py notebook_manager.py add --url URL --name NAME --description DESC --topics TOPICS")
214
+ return 1
215
+
216
+ answer = ask_notebooklm(
217
+ question=args.question,
218
+ notebook_url=notebook_url,
219
+ headless=not args.show_browser
220
+ )
221
+
222
+ if answer:
223
+ print("\n" + "=" * 60)
224
+ print(f"Question: {args.question}")
225
+ print("=" * 60)
226
+ print()
227
+ print(answer)
228
+ print()
229
+ print("=" * 60)
230
+ return 0
231
+ else:
232
+ print("\n❌ Failed to get answer")
233
+ return 1
234
+
235
+
236
+ if __name__ == "__main__":
237
+ sys.exit(main())