@musashishao/agent-kit 1.9.0 → 1.9.1
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/.agent/agents/ai-asset-factory.md +700 -0
- package/.agent/agents/ai-audio-factory.md +503 -0
- package/.agent/agents/game-developer.md +4 -4
- package/.agent/agents/orchestrator.md +113 -3
- package/.agent/agents/project-planner.md +67 -0
- package/.agent/agents/unity-mobile-master.md +949 -0
- package/.agent/mcp/config/registry.json +65 -51
- package/.agent/mcp/servers/notebooklm/README.md +114 -0
- package/.agent/mcp/servers/notebooklm/package.json +35 -0
- package/.agent/mcp/servers/notebooklm/src/auth/chrome.ts +225 -0
- package/.agent/mcp/servers/notebooklm/src/auth/index.ts +1 -0
- package/.agent/mcp/servers/notebooklm/src/index.ts +516 -0
- package/.agent/mcp/servers/notebooklm/src/services/index.ts +3 -0
- package/.agent/mcp/servers/notebooklm/src/services/library.ts +217 -0
- package/.agent/mcp/servers/notebooklm/src/services/notebooklm.ts +380 -0
- package/.agent/mcp/servers/notebooklm/tsconfig.json +15 -0
- package/.agent/mcp-gateway/README.md +169 -20
- package/.agent/mcp-gateway/package.json +22 -7
- package/.agent/mcp-gateway/src/auth/index.ts +55 -0
- package/.agent/mcp-gateway/src/auth/middleware.ts +242 -0
- package/.agent/mcp-gateway/src/auth/oauth.ts +462 -0
- package/.agent/mcp-gateway/src/auth/scopes.ts +227 -0
- package/.agent/mcp-gateway/src/index.ts +252 -105
- package/.agent/mcp-gateway/src/observability/index.ts +5 -0
- package/.agent/mcp-gateway/src/observability/otel.ts +405 -0
- package/.agent/mcp-gateway/src/transports/index.ts +5 -0
- package/.agent/mcp-gateway/src/transports/streamableHttp.ts +235 -0
- package/.agent/rules/CODEX.md +89 -0
- package/.agent/rules/CODE_RULES.md +73 -0
- package/.agent/rules/GEMINI.md +25 -0
- package/.agent/rules/MEMORY_STATE.md +110 -0
- package/.agent/rules/REFERENCE.md +33 -141
- package/.agent/rules/REF_SKILLS.md +116 -0
- package/.agent/rules/REF_WORKFLOWS.md +81 -0
- package/.agent/scripts/ak_cli.py +106 -5
- package/.agent/scripts/memory_manager.py +48 -9
- package/.agent/skills/anti-hallucination/SKILL.md +295 -0
- package/.agent/skills/anti-hallucination/scripts/check_hallucination.py +299 -0
- package/.agent/skills/bifurcation-analysis/SKILL.md +56 -0
- package/.agent/skills/brainstorming/SKILL.md +80 -6
- package/.agent/skills/decision-memory/SKILL.md +317 -0
- package/.agent/skills/emergence-detector/SKILL.md +230 -0
- package/.agent/skills/emergence-detector/scripts/check_emergence.py +265 -0
- package/.agent/skills/explained-qa/SKILL.md +142 -0
- package/.agent/skills/explained-qa/game-terminology.md +214 -0
- package/.agent/skills/game-development/ai-dialogue-engine/SKILL.md +442 -0
- package/.agent/skills/game-development/ai-graphics-generator/SKILL.md +463 -0
- package/.agent/skills/game-development/ai-playtest-framework/SKILL.md +570 -0
- package/.agent/skills/game-development/camera-systems/SKILL.md +607 -0
- package/.agent/skills/game-development/card-battle-engine/SKILL.md +618 -0
- package/.agent/skills/game-development/character-controller-3d/SKILL.md +908 -0
- package/.agent/skills/game-development/cloud-save-sync/SKILL.md +527 -0
- package/.agent/skills/game-development/combat-system/SKILL.md +748 -0
- package/.agent/skills/game-development/compliance-rating/SKILL.md +277 -0
- package/.agent/skills/game-development/crossplatform-build/SKILL.md +386 -0
- package/.agent/skills/game-development/cultivation-progression/SKILL.md +520 -0
- package/.agent/skills/game-development/data-driven-balance/SKILL.md +535 -0
- package/.agent/skills/game-development/game-analytics-integrator/SKILL.md +410 -0
- package/.agent/skills/game-development/game-audio-advanced/SKILL.md +646 -0
- package/.agent/skills/game-development/game-economy-designer/SKILL.md +375 -0
- package/.agent/skills/game-development/game-marketing/SKILL.md +85 -0
- package/.agent/skills/game-development/game-state-manager/SKILL.md +883 -0
- package/.agent/skills/game-development/hybrid-game-spec/SKILL.md +220 -0
- package/.agent/skills/game-development/inventory-quest/SKILL.md +747 -0
- package/.agent/skills/game-development/liveops/SKILL.md +308 -0
- package/.agent/skills/game-development/localization/SKILL.md +286 -0
- package/.agent/skills/game-development/mobile-input-patterns/SKILL.md +343 -0
- package/.agent/skills/game-development/monetization-strategy/SKILL.md +94 -0
- package/.agent/skills/game-development/multiplayer-master/SKILL.md +727 -0
- package/.agent/skills/game-development/narrative-branching/SKILL.md +593 -0
- package/.agent/skills/game-development/procedural-level-ai/SKILL.md +367 -0
- package/.agent/skills/game-development/prototyping-rapid/SKILL.md +205 -0
- package/.agent/skills/game-development/spec-ecosystem/SKILL.md +155 -0
- package/.agent/skills/game-development/spec-ecosystem/decision-log-format.md +129 -0
- package/.agent/skills/game-development/spec-ecosystem/templates/PLAN-template.md +178 -0
- package/.agent/skills/game-development/spec-ecosystem/templates/SPEC-template.md +110 -0
- package/.agent/skills/game-development/spec-ecosystem/templates/TASKS-template.md +156 -0
- package/.agent/skills/game-development/survival-systems/SKILL.md +493 -0
- package/.agent/skills/game-development/testing-qa/SKILL.md +270 -0
- package/.agent/skills/game-development/unity-mobile-optimization/SKILL.md +271 -0
- package/.agent/skills/intent-capture/SKILL.md +65 -0
- package/.agent/skills/mcp-composition/SKILL.md +362 -0
- package/.agent/skills/mcp-observability/SKILL.md +323 -0
- package/.agent/skills/mcp-security/SKILL.md +314 -0
- package/.agent/skills/trust-spectrum/SKILL.md +291 -0
- package/.agent/skills/vibe-coding-guard/SKILL.md +328 -0
- package/.agent/templates/AGENTS.game.md +63 -0
- package/.agent/templates/docs/WORKFLOW_GUIDE.en.md +100 -0
- package/.agent/templates/docs/WORKFLOW_GUIDE.vi.md +100 -0
- package/.agent/workflows/ai-agent.md +2 -0
- package/.agent/workflows/autofix.md +1 -0
- package/.agent/workflows/brainstorm.md +1 -0
- package/.agent/workflows/context.md +1 -0
- package/.agent/workflows/create.md +39 -8
- package/.agent/workflows/dashboard.md +1 -0
- package/.agent/workflows/debug.md +14 -0
- package/.agent/workflows/deploy.md +14 -0
- package/.agent/workflows/enhance.md +44 -0
- package/.agent/workflows/gamekit-init.md +177 -0
- package/.agent/workflows/gamekit-launch.md +338 -0
- package/.agent/workflows/gamekit-plan.md +204 -0
- package/.agent/workflows/gamekit-qa.md +153 -0
- package/.agent/workflows/gamekit-spec.md +243 -0
- package/.agent/workflows/gamekit-tasks.md +208 -0
- package/.agent/workflows/marketing.md +2 -0
- package/.agent/workflows/next.md +1 -0
- package/.agent/workflows/orchestrate.md +12 -0
- package/.agent/workflows/pentest.md +2 -0
- package/.agent/workflows/plan.md +42 -0
- package/.agent/workflows/preview.md +1 -0
- package/.agent/workflows/quality.md +1 -0
- package/.agent/workflows/saas.md +2 -0
- package/.agent/workflows/spec.md +42 -0
- package/.agent/workflows/status.md +1 -0
- package/.agent/workflows/test.md +14 -0
- package/.agent/workflows/ui-ux-pro-max.md +1 -0
- package/bin/cli.js +411 -111
- package/package.json +1 -2
- package/.agent/agents/game-asset-curator.md +0 -317
- package/.agent/agents/game-narrative-designer.md +0 -310
- package/.agent/agents/game-qa-agent.md +0 -441
- package/.agent/workflows/game-prototype.md +0 -154
- package/docs/AI_DATA_INFRASTRUCTURE.md +0 -288
- package/docs/CHANGELOG_AI_INFRA.md +0 -141
- package/docs/MIGRATION_GUIDE_V1.9.md +0 -55
|
@@ -1,54 +1,68 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
},
|
|
8
|
-
"awesome": {
|
|
9
|
-
"name": "Awesome MCP Servers",
|
|
10
|
-
"url": "https://github.com/punkpeye/awesome-mcp-servers",
|
|
11
|
-
"categories": [
|
|
12
|
-
"browser-automation",
|
|
13
|
-
"databases",
|
|
14
|
-
"developer-tools",
|
|
15
|
-
"file-systems",
|
|
16
|
-
"version-control",
|
|
17
|
-
"cloud-platforms"
|
|
18
|
-
]
|
|
19
|
-
}
|
|
2
|
+
"registries": {
|
|
3
|
+
"npm": {
|
|
4
|
+
"name": "NPM Registry",
|
|
5
|
+
"searchUrl": "https://registry.npmjs.org/-/v1/search?text=mcp-server",
|
|
6
|
+
"pattern": "mcp-server-*"
|
|
20
7
|
},
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
8
|
+
"awesome": {
|
|
9
|
+
"name": "Awesome MCP Servers",
|
|
10
|
+
"url": "https://github.com/punkpeye/awesome-mcp-servers",
|
|
11
|
+
"categories": [
|
|
12
|
+
"browser-automation",
|
|
13
|
+
"databases",
|
|
14
|
+
"developer-tools",
|
|
15
|
+
"file-systems",
|
|
16
|
+
"version-control",
|
|
17
|
+
"cloud-platforms"
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"featured": [
|
|
22
|
+
{
|
|
23
|
+
"name": "@anthropic/mcp-server-filesystem",
|
|
24
|
+
"description": "Secure file system access",
|
|
25
|
+
"source": "npm"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "@anthropic/mcp-server-sqlite",
|
|
29
|
+
"description": "SQLite database integration",
|
|
30
|
+
"source": "npm"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "@anthropic/mcp-server-github",
|
|
34
|
+
"description": "GitHub API integration",
|
|
35
|
+
"source": "npm"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "@anthropic/mcp-server-memory",
|
|
39
|
+
"description": "Persistent memory for AI",
|
|
40
|
+
"source": "npm"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "playwright-mcp",
|
|
44
|
+
"description": "Browser automation with Playwright",
|
|
45
|
+
"source": "npm"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "mcp-server-fetch",
|
|
49
|
+
"description": "HTTP fetch capabilities",
|
|
50
|
+
"source": "npm"
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"installed": [
|
|
54
|
+
{
|
|
55
|
+
"name": "notebooklm-mcp",
|
|
56
|
+
"serverName": "notebooklm",
|
|
57
|
+
"config": {
|
|
58
|
+
"command": "node",
|
|
59
|
+
"args": [
|
|
60
|
+
".agent/mcp/servers/notebooklm/dist/index.js"
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
"installedAt": "2026-01-30T16:50:20.478Z",
|
|
64
|
+
"claudeConfigured": false,
|
|
65
|
+
"cursorConfigured": true
|
|
66
|
+
}
|
|
67
|
+
]
|
|
54
68
|
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# NotebookLM MCP Server - Agent Kit Custom
|
|
2
|
+
|
|
3
|
+
> 🎓 Custom NotebookLM MCP server với Chrome OAuth, skill-linking, và Agent Kit native integration.
|
|
4
|
+
|
|
5
|
+
## ✨ Tính năng
|
|
6
|
+
|
|
7
|
+
| Feature | Community | Agent Kit Custom |
|
|
8
|
+
|---------|-----------|------------------|
|
|
9
|
+
| Chrome OAuth | ✅ | ✅ Persistent sessions |
|
|
10
|
+
| Query Notebook | ✅ | ✅ + markAsUsed tracking |
|
|
11
|
+
| Library | Tags only | ✅ **Skill-linking** |
|
|
12
|
+
| Agent Integration | ❌ | ✅ Native |
|
|
13
|
+
|
|
14
|
+
## 🛠️ Tools (12)
|
|
15
|
+
|
|
16
|
+
### Authentication
|
|
17
|
+
| Tool | Description |
|
|
18
|
+
|------|-------------|
|
|
19
|
+
| `notebooklm_login` | Đăng nhập via Chrome OAuth |
|
|
20
|
+
| `notebooklm_status` | Kiểm tra trạng thái |
|
|
21
|
+
| `notebooklm_logout` | Đăng xuất + xóa data |
|
|
22
|
+
|
|
23
|
+
### Notebook Operations
|
|
24
|
+
| Tool | Description |
|
|
25
|
+
|------|-------------|
|
|
26
|
+
| `notebooklm_list_notebooks` | Liệt kê tất cả notebooks |
|
|
27
|
+
| `notebooklm_query` | Hỏi đáp với citations |
|
|
28
|
+
| `notebooklm_create_notebook` | Tạo notebook mới |
|
|
29
|
+
| `notebooklm_add_source` | Thêm URL/text |
|
|
30
|
+
| `notebooklm_get_sources` | List sources |
|
|
31
|
+
|
|
32
|
+
### Library (Unique)
|
|
33
|
+
| Tool | Description |
|
|
34
|
+
|------|-------------|
|
|
35
|
+
| `notebooklm_library_add` | Lưu vào library local |
|
|
36
|
+
| `notebooklm_library_search` | Tìm theo tags/skills |
|
|
37
|
+
| `notebooklm_library_recent` | Notebooks dùng gần đây |
|
|
38
|
+
| `notebooklm_skill_link` | **Link notebook ↔ Agent Kit skill** |
|
|
39
|
+
|
|
40
|
+
## 🚀 Cài đặt
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
cd .agent/mcp/servers/notebooklm
|
|
44
|
+
npm install
|
|
45
|
+
npm run build
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## ⚙️ Cấu hình
|
|
49
|
+
|
|
50
|
+
### Cursor (`.cursor/mcp.json`)
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"mcpServers": {
|
|
54
|
+
"notebooklm": {
|
|
55
|
+
"command": "node",
|
|
56
|
+
"args": [".agent/mcp/servers/notebooklm/dist/index.js"]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Claude Desktop
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"mcpServers": {
|
|
66
|
+
"notebooklm": {
|
|
67
|
+
"command": "node",
|
|
68
|
+
"args": ["/path/to/.agent/mcp/servers/notebooklm/dist/index.js"]
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## 📖 Sử dụng
|
|
75
|
+
|
|
76
|
+
### 1. Đăng nhập
|
|
77
|
+
```
|
|
78
|
+
User: "Log me in to NotebookLM"
|
|
79
|
+
→ Chrome opens → Login Google → Done
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 2. Query notebook
|
|
83
|
+
```
|
|
84
|
+
User: "Query notebook abc123: How to implement auth?"
|
|
85
|
+
→ Returns answer with citations
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 3. Skill-linking (Unique feature)
|
|
89
|
+
```
|
|
90
|
+
User: "Add my React docs notebook to library, link to react-patterns skill"
|
|
91
|
+
|
|
92
|
+
# Sau đó
|
|
93
|
+
User: "I'm working on React, find relevant notebooks"
|
|
94
|
+
→ Auto-suggests notebooks linked to react-patterns
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## 📁 Data Locations
|
|
98
|
+
|
|
99
|
+
| Data | Path |
|
|
100
|
+
|------|------|
|
|
101
|
+
| Chrome Profile | `~/.agent-kit/notebooklm/chrome-profile/` |
|
|
102
|
+
| Library | `~/.agent-kit/notebooklm/library/notebooks.json` |
|
|
103
|
+
|
|
104
|
+
## 🔧 Environment Variables
|
|
105
|
+
|
|
106
|
+
| Variable | Description |
|
|
107
|
+
|----------|-------------|
|
|
108
|
+
| `NOTEBOOKLM_USER_DATA` | Chrome profile path |
|
|
109
|
+
| `NOTEBOOKLM_LIBRARY_DIR` | Library storage path |
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
**Version:** 1.0.0
|
|
114
|
+
**Made for:** Agent Kit
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agent-kit/mcp-notebooklm",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Custom NotebookLM MCP server for Agent Kit - Chrome OAuth, skill-aware research, codebase context",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mcp-notebooklm": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsx src/index.ts",
|
|
13
|
+
"start": "node dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mcp",
|
|
17
|
+
"notebooklm",
|
|
18
|
+
"agent-kit",
|
|
19
|
+
"ai",
|
|
20
|
+
"research"
|
|
21
|
+
],
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
24
|
+
"playwright": "^1.50.0",
|
|
25
|
+
"zod": "^3.23.8"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^22.0.0",
|
|
29
|
+
"tsx": "^4.19.0",
|
|
30
|
+
"typescript": "^5.6.0"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=20.0.0"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chrome Authentication Module
|
|
3
|
+
*
|
|
4
|
+
* Handles Google OAuth via Chrome browser.
|
|
5
|
+
* Uses Playwright for browser automation with persistent context.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { chromium, BrowserContext, Page } from "playwright";
|
|
9
|
+
import * as fs from "fs";
|
|
10
|
+
import * as path from "path";
|
|
11
|
+
import * as os from "os";
|
|
12
|
+
|
|
13
|
+
const USER_DATA_DIR = process.env.NOTEBOOKLM_USER_DATA ||
|
|
14
|
+
path.join(os.homedir(), ".agent-kit", "notebooklm", "chrome-profile");
|
|
15
|
+
|
|
16
|
+
const COOKIES_FILE = path.join(USER_DATA_DIR, "cookies.json");
|
|
17
|
+
const AUTH_STATE_FILE = path.join(USER_DATA_DIR, "auth-state.json");
|
|
18
|
+
|
|
19
|
+
export interface AuthState {
|
|
20
|
+
isAuthenticated: boolean;
|
|
21
|
+
email?: string;
|
|
22
|
+
lastChecked: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Ensure user data directory exists
|
|
27
|
+
*/
|
|
28
|
+
function ensureDataDir(): void {
|
|
29
|
+
if (!fs.existsSync(USER_DATA_DIR)) {
|
|
30
|
+
fs.mkdirSync(USER_DATA_DIR, { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Load saved authentication state
|
|
36
|
+
*/
|
|
37
|
+
export function loadAuthState(): AuthState {
|
|
38
|
+
ensureDataDir();
|
|
39
|
+
|
|
40
|
+
if (fs.existsSync(AUTH_STATE_FILE)) {
|
|
41
|
+
try {
|
|
42
|
+
return JSON.parse(fs.readFileSync(AUTH_STATE_FILE, "utf-8"));
|
|
43
|
+
} catch {
|
|
44
|
+
return { isAuthenticated: false, lastChecked: new Date().toISOString() };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return { isAuthenticated: false, lastChecked: new Date().toISOString() };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Save authentication state
|
|
53
|
+
*/
|
|
54
|
+
export function saveAuthState(state: AuthState): void {
|
|
55
|
+
ensureDataDir();
|
|
56
|
+
fs.writeFileSync(AUTH_STATE_FILE, JSON.stringify(state, null, 2));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Launch browser with persistent context
|
|
61
|
+
*/
|
|
62
|
+
export async function launchBrowser(): Promise<BrowserContext> {
|
|
63
|
+
ensureDataDir();
|
|
64
|
+
|
|
65
|
+
const context = await chromium.launchPersistentContext(USER_DATA_DIR, {
|
|
66
|
+
headless: false,
|
|
67
|
+
args: [
|
|
68
|
+
"--disable-blink-features=AutomationControlled",
|
|
69
|
+
"--no-first-run",
|
|
70
|
+
"--no-default-browser-check",
|
|
71
|
+
],
|
|
72
|
+
viewport: { width: 1280, height: 800 },
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return context;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Check if user is logged in to NotebookLM
|
|
80
|
+
*/
|
|
81
|
+
export async function checkLogin(page: Page): Promise<{ loggedIn: boolean; email?: string }> {
|
|
82
|
+
try {
|
|
83
|
+
await page.goto("https://notebooklm.google.com", {
|
|
84
|
+
waitUntil: "networkidle",
|
|
85
|
+
timeout: 30000,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Check for sign-in prompt
|
|
89
|
+
const signInButton = await page.$('text="Sign in"');
|
|
90
|
+
if (signInButton) {
|
|
91
|
+
return { loggedIn: false };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Check for account menu (indicates logged in)
|
|
95
|
+
const accountButton = await page.$('[aria-label*="Account"], [data-ogsr-up]');
|
|
96
|
+
if (accountButton) {
|
|
97
|
+
// Try to get email
|
|
98
|
+
const email = await page.$eval(
|
|
99
|
+
'[data-email], [aria-label*="@"]',
|
|
100
|
+
(el) => el.getAttribute("data-email") || el.getAttribute("aria-label")?.match(/[\w.-]+@[\w.-]+/)?.[0]
|
|
101
|
+
).catch(() => undefined);
|
|
102
|
+
|
|
103
|
+
return { loggedIn: true, email };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// If we see notebooks list, we're logged in
|
|
107
|
+
const notebooksList = await page.$('[role="listbox"], [class*="notebook"]');
|
|
108
|
+
if (notebooksList) {
|
|
109
|
+
return { loggedIn: true };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return { loggedIn: false };
|
|
113
|
+
} catch (error) {
|
|
114
|
+
return { loggedIn: false };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Perform login flow
|
|
120
|
+
* Opens browser and waits for user to complete Google OAuth
|
|
121
|
+
*/
|
|
122
|
+
export async function login(): Promise<AuthState> {
|
|
123
|
+
const context = await launchBrowser();
|
|
124
|
+
const page = await context.newPage();
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
// Navigate to NotebookLM
|
|
128
|
+
await page.goto("https://notebooklm.google.com", { waitUntil: "networkidle" });
|
|
129
|
+
|
|
130
|
+
// Check if already logged in
|
|
131
|
+
const status = await checkLogin(page);
|
|
132
|
+
|
|
133
|
+
if (status.loggedIn) {
|
|
134
|
+
const state: AuthState = {
|
|
135
|
+
isAuthenticated: true,
|
|
136
|
+
email: status.email,
|
|
137
|
+
lastChecked: new Date().toISOString(),
|
|
138
|
+
};
|
|
139
|
+
saveAuthState(state);
|
|
140
|
+
await context.close();
|
|
141
|
+
return state;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Wait for user to complete login (max 5 minutes)
|
|
145
|
+
console.error("🔐 Waiting for you to complete Google login...");
|
|
146
|
+
console.error(" Please log in to your Google account in the browser window.");
|
|
147
|
+
|
|
148
|
+
// Poll for login completion
|
|
149
|
+
let attempts = 0;
|
|
150
|
+
const maxAttempts = 60; // 5 minutes with 5 second intervals
|
|
151
|
+
|
|
152
|
+
while (attempts < maxAttempts) {
|
|
153
|
+
await page.waitForTimeout(5000);
|
|
154
|
+
const loginStatus = await checkLogin(page);
|
|
155
|
+
|
|
156
|
+
if (loginStatus.loggedIn) {
|
|
157
|
+
const state: AuthState = {
|
|
158
|
+
isAuthenticated: true,
|
|
159
|
+
email: loginStatus.email,
|
|
160
|
+
lastChecked: new Date().toISOString(),
|
|
161
|
+
};
|
|
162
|
+
saveAuthState(state);
|
|
163
|
+
|
|
164
|
+
// Save cookies for future sessions
|
|
165
|
+
const cookies = await context.cookies();
|
|
166
|
+
fs.writeFileSync(COOKIES_FILE, JSON.stringify(cookies, null, 2));
|
|
167
|
+
|
|
168
|
+
console.error(`✅ Login successful! ${loginStatus.email || ""}`);
|
|
169
|
+
await context.close();
|
|
170
|
+
return state;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
attempts++;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Timeout
|
|
177
|
+
await context.close();
|
|
178
|
+
throw new Error("Login timeout - please try again");
|
|
179
|
+
|
|
180
|
+
} catch (error) {
|
|
181
|
+
await context.close();
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Get authenticated browser context
|
|
188
|
+
* Returns existing session or throws if not authenticated
|
|
189
|
+
*/
|
|
190
|
+
export async function getAuthenticatedContext(): Promise<BrowserContext> {
|
|
191
|
+
const state = loadAuthState();
|
|
192
|
+
|
|
193
|
+
if (!state.isAuthenticated) {
|
|
194
|
+
throw new Error("Not authenticated. Please run notebooklm_login first.");
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const context = await launchBrowser();
|
|
198
|
+
|
|
199
|
+
// Load saved cookies if available
|
|
200
|
+
if (fs.existsSync(COOKIES_FILE)) {
|
|
201
|
+
try {
|
|
202
|
+
const cookies = JSON.parse(fs.readFileSync(COOKIES_FILE, "utf-8"));
|
|
203
|
+
await context.addCookies(cookies);
|
|
204
|
+
} catch {
|
|
205
|
+
// Ignore cookie errors
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return context;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Logout and clear saved credentials
|
|
214
|
+
*/
|
|
215
|
+
export function logout(): void {
|
|
216
|
+
if (fs.existsSync(COOKIES_FILE)) fs.unlinkSync(COOKIES_FILE);
|
|
217
|
+
if (fs.existsSync(AUTH_STATE_FILE)) fs.unlinkSync(AUTH_STATE_FILE);
|
|
218
|
+
|
|
219
|
+
// Clear Chrome profile data
|
|
220
|
+
if (fs.existsSync(USER_DATA_DIR)) {
|
|
221
|
+
fs.rmSync(USER_DATA_DIR, { recursive: true, force: true });
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export { USER_DATA_DIR };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./chrome.js";
|