metame-cli 1.5.10 → 1.5.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -6
- package/index.js +266 -72
- package/package.json +7 -3
- package/scripts/daemon-admin-commands.js +34 -0
- package/scripts/daemon-agent-commands.js +6 -2
- package/scripts/daemon-bridges.js +41 -10
- package/scripts/daemon-claude-engine.js +128 -29
- package/scripts/daemon-command-router.js +16 -0
- package/scripts/daemon-command-session-route.js +3 -1
- package/scripts/daemon-default.yaml +3 -1
- package/scripts/daemon-engine-runtime.js +1 -5
- package/scripts/daemon-message-pipeline.js +113 -44
- package/scripts/daemon-ops-commands.js +25 -11
- package/scripts/daemon-reactive-lifecycle.js +757 -76
- package/scripts/daemon-session-commands.js +3 -2
- package/scripts/daemon-session-store.js +82 -27
- package/scripts/daemon-team-dispatch.js +21 -5
- package/scripts/daemon-utils.js +3 -1
- package/scripts/daemon.js +80 -2
- package/scripts/distill.js +1 -1
- package/scripts/docs/file-transfer.md +1 -0
- package/scripts/docs/maintenance-manual.md +55 -2
- package/scripts/docs/pointer-map.md +34 -0
- package/scripts/feishu-adapter.js +25 -0
- package/scripts/hooks/intent-file-transfer.js +2 -1
- package/scripts/hooks/intent-perpetual.js +109 -0
- package/scripts/hooks/intent-research.js +112 -0
- package/scripts/intent-registry.js +4 -0
- package/scripts/memory-extract.js +29 -1
- package/scripts/memory-nightly-reflect.js +104 -0
- package/scripts/ops-mission-queue.js +258 -0
- package/scripts/ops-verifier.js +197 -0
- package/scripts/signal-capture.js +3 -3
- package/scripts/skill-evolution.js +11 -2
- package/skills/agent-browser/SKILL.md +153 -0
- package/skills/agent-reach/SKILL.md +66 -0
- package/skills/agent-reach/evolution.json +13 -0
- package/skills/deep-research/SKILL.md +77 -0
- package/skills/find-skills/SKILL.md +133 -0
- package/skills/heartbeat-task-manager/SKILL.md +63 -0
- package/skills/macos-local-orchestrator/SKILL.md +192 -0
- package/skills/macos-local-orchestrator/agents/openai.yaml +4 -0
- package/skills/macos-local-orchestrator/references/tooling-landscape.md +70 -0
- package/skills/macos-mail-calendar/SKILL.md +394 -0
- package/skills/mcp-installer/SKILL.md +138 -0
- package/skills/skill-creator/LICENSE.txt +202 -0
- package/skills/skill-creator/README.md +72 -0
- package/skills/skill-creator/SKILL.md +96 -0
- package/skills/skill-creator/evolution.json +6 -0
- package/skills/skill-creator/references/creation-guide.md +116 -0
- package/skills/skill-creator/references/evolution-guide.md +74 -0
- package/skills/skill-creator/references/output-patterns.md +82 -0
- package/skills/skill-creator/references/workflows.md +28 -0
- package/skills/skill-creator/scripts/align_all.py +32 -0
- package/skills/skill-creator/scripts/auto_evolve_hook.js +247 -0
- package/skills/skill-creator/scripts/init_skill.py +303 -0
- package/skills/skill-creator/scripts/merge_evolution.py +70 -0
- package/skills/skill-creator/scripts/package_skill.py +110 -0
- package/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/skills/skill-creator/scripts/setup.py +141 -0
- package/skills/skill-creator/scripts/smart_stitch.py +82 -0
- package/skills/skill-manager/SKILL.md +112 -0
- package/skills/skill-manager/scripts/delete_skill.py +31 -0
- package/skills/skill-manager/scripts/list_skills.py +61 -0
- package/skills/skill-manager/scripts/scan_and_check.py +125 -0
- package/skills/skill-manager/scripts/sync_index.py +144 -0
- package/skills/skill-manager/scripts/update_helper.py +39 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { execSync } = require('child_process');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* MetaMe Ops verifier — hard gate based on syntax + test results.
|
|
9
|
+
*
|
|
10
|
+
* Phases:
|
|
11
|
+
* diagnose — workspace/ops/diagnosis.md must exist
|
|
12
|
+
* plan — workspace/ops/fix-plan.md must exist
|
|
13
|
+
* fix — all .js files pass syntax check + all tests pass
|
|
14
|
+
* test — same as fix (double-check after implementation)
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// ── Protected files: changes to these BLOCK the gate ─────────
|
|
18
|
+
// These are load-bearing files. If broken, the entire system dies.
|
|
19
|
+
// Agent can diagnose issues in these files, but fixes require human approval.
|
|
20
|
+
|
|
21
|
+
// Scripts that must not be modified (basename match)
|
|
22
|
+
const PROTECTED_SCRIPTS = [
|
|
23
|
+
'daemon.js', // main daemon process
|
|
24
|
+
'daemon-reactive-lifecycle.js', // perpetual loop engine
|
|
25
|
+
'daemon-team-dispatch.js', // dispatch + prompt enrichment
|
|
26
|
+
'daemon-claude-engine.js', // Claude API bridge
|
|
27
|
+
'daemon-bridges.js', // Feishu/Telegram bridges
|
|
28
|
+
'daemon-remote-dispatch.js', // cross-device dispatch
|
|
29
|
+
'ops-verifier.js', // this file — agent must not weaken its own gate
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
// Repo-root files that must not be modified (relative path match)
|
|
33
|
+
const PROTECTED_ROOT_FILES = [
|
|
34
|
+
'perpetual.yaml', // manifest — controls which verifier runs
|
|
35
|
+
'perpetual.yml',
|
|
36
|
+
'CLAUDE.md', // agent identity — weakening it weakens all safety
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Check if any protected file was modified (repo-internal only).
|
|
41
|
+
* daemon.yaml lives outside repo and has its own backup mechanism — not our concern.
|
|
42
|
+
* FAIL-CLOSED: if git is unavailable, returns ['__GIT_UNAVAILABLE__'].
|
|
43
|
+
*/
|
|
44
|
+
function checkProtectedFiles(cwd) {
|
|
45
|
+
try {
|
|
46
|
+
const diff = execSync('git diff --name-only HEAD', { cwd, timeout: 5000, encoding: 'utf8', stdio: 'pipe' }).trim();
|
|
47
|
+
const staged = execSync('git diff --cached --name-only', { cwd, timeout: 5000, encoding: 'utf8', stdio: 'pipe' }).trim();
|
|
48
|
+
const changed = [...new Set([...diff.split('\n'), ...staged.split('\n')])].filter(Boolean);
|
|
49
|
+
|
|
50
|
+
const violations = [];
|
|
51
|
+
for (const f of changed) {
|
|
52
|
+
if (PROTECTED_SCRIPTS.includes(path.basename(f))) violations.push(path.basename(f));
|
|
53
|
+
}
|
|
54
|
+
for (const f of changed) {
|
|
55
|
+
if (PROTECTED_ROOT_FILES.includes(f)) violations.push(f);
|
|
56
|
+
}
|
|
57
|
+
return violations;
|
|
58
|
+
} catch {
|
|
59
|
+
return ['__GIT_UNAVAILABLE__'];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const GATES = {
|
|
64
|
+
diagnose: {
|
|
65
|
+
check: (cwd) => fileExists(cwd, 'workspace/ops/diagnosis.md'),
|
|
66
|
+
failDetail: 'workspace/ops/diagnosis.md not found',
|
|
67
|
+
hints: ['Scan logs and produce a diagnosis report at workspace/ops/diagnosis.md'],
|
|
68
|
+
},
|
|
69
|
+
plan: {
|
|
70
|
+
check: (cwd) => fileExists(cwd, 'workspace/ops/fix-plan.md'),
|
|
71
|
+
failDetail: 'workspace/ops/fix-plan.md not found',
|
|
72
|
+
hints: ['Write a fix plan at workspace/ops/fix-plan.md before implementing'],
|
|
73
|
+
},
|
|
74
|
+
fix: {
|
|
75
|
+
check: (cwd) => syntaxAndTests(cwd),
|
|
76
|
+
failDetail: 'syntax check or tests failed',
|
|
77
|
+
hints: ['Ensure all scripts pass `node -c` and `node --test`'],
|
|
78
|
+
},
|
|
79
|
+
test: {
|
|
80
|
+
check: (cwd) => syntaxAndTests(cwd),
|
|
81
|
+
failDetail: 'tests failed on verification pass',
|
|
82
|
+
hints: ['All tests must pass before marking mission complete'],
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
function fileExists(cwd, relPath) {
|
|
87
|
+
try { return fs.statSync(path.join(cwd, relPath)).isFile(); } catch { return false; }
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function syntaxAndTests(cwd) {
|
|
91
|
+
try {
|
|
92
|
+
// Find changed .js files (staged + unstaged) — only verify what was touched
|
|
93
|
+
let changedFiles = [];
|
|
94
|
+
try {
|
|
95
|
+
const diff = execSync('git diff --name-only HEAD -- scripts/', { cwd, timeout: 5000, encoding: 'utf8', stdio: 'pipe' }).trim();
|
|
96
|
+
const staged = execSync('git diff --cached --name-only -- scripts/', { cwd, timeout: 5000, encoding: 'utf8', stdio: 'pipe' }).trim();
|
|
97
|
+
changedFiles = [...new Set([...diff.split('\n'), ...staged.split('\n')])]
|
|
98
|
+
.filter(f => f.endsWith('.js'))
|
|
99
|
+
.map(f => path.basename(f));
|
|
100
|
+
} catch { /* git not available or not a repo — check all */ }
|
|
101
|
+
|
|
102
|
+
// Syntax check changed .js files (or all if git unavailable)
|
|
103
|
+
const srcFiles = changedFiles.length > 0
|
|
104
|
+
? changedFiles.filter(f => !f.endsWith('.test.js'))
|
|
105
|
+
: fs.readdirSync(path.join(cwd, 'scripts')).filter(f => f.endsWith('.js') && !f.endsWith('.test.js'));
|
|
106
|
+
|
|
107
|
+
for (const f of srcFiles) {
|
|
108
|
+
execSync(`node -c scripts/${f}`, { cwd, timeout: 5000, stdio: 'pipe' });
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Run associated test files
|
|
112
|
+
const testFiles = changedFiles.length > 0
|
|
113
|
+
? changedFiles.filter(f => f.endsWith('.test.js'))
|
|
114
|
+
: [];
|
|
115
|
+
// Also run tests for changed source files (e.g., foo.js → foo.test.js)
|
|
116
|
+
for (const f of srcFiles) {
|
|
117
|
+
const testName = f.replace('.js', '.test.js');
|
|
118
|
+
if (!testFiles.includes(testName)) {
|
|
119
|
+
const testPath = path.join(cwd, 'scripts', testName);
|
|
120
|
+
if (fs.existsSync(testPath)) testFiles.push(testName);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// If no specific tests identified, run the core lifecycle test as baseline
|
|
125
|
+
if (testFiles.length === 0) {
|
|
126
|
+
testFiles.push('daemon-reactive-lifecycle.test.js');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
for (const f of [...new Set(testFiles)]) {
|
|
130
|
+
const testPath = path.join(cwd, 'scripts', f);
|
|
131
|
+
if (!fs.existsSync(testPath)) continue;
|
|
132
|
+
const out = execSync(`node --test scripts/${f}`, { cwd, timeout: 60000, encoding: 'utf8', stdio: 'pipe' });
|
|
133
|
+
if (out.includes('# fail') && !out.includes('# fail 0')) return false;
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
} catch {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function verify(cwd, phase) {
|
|
142
|
+
const gate = GATES[phase];
|
|
143
|
+
if (!gate) {
|
|
144
|
+
return {
|
|
145
|
+
passed: false, phase: phase || '',
|
|
146
|
+
details: `unknown phase: "${phase || ''}"`,
|
|
147
|
+
artifacts: [], hints: ['Valid phases: diagnose, plan, fix, test'],
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Safety gate: block if protected files were touched
|
|
152
|
+
if (phase === 'fix' || phase === 'test') {
|
|
153
|
+
const violated = checkProtectedFiles(cwd);
|
|
154
|
+
if (violated.length > 0) {
|
|
155
|
+
return {
|
|
156
|
+
passed: false, phase,
|
|
157
|
+
details: `PROTECTED_FILE_VIOLATION: ${violated.join(', ')}`,
|
|
158
|
+
artifacts: [],
|
|
159
|
+
hints: [
|
|
160
|
+
`These files are daemon-critical and cannot be auto-merged: ${violated.join(', ')}`,
|
|
161
|
+
'Revert changes to protected files. Write the fix plan to workspace/ops/ and notify the user for manual review.',
|
|
162
|
+
],
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const passed = gate.check(cwd);
|
|
169
|
+
|
|
170
|
+
// Collect artifacts
|
|
171
|
+
const opsDir = path.join(cwd, 'workspace', 'ops');
|
|
172
|
+
let artifacts = [];
|
|
173
|
+
try {
|
|
174
|
+
if (fs.existsSync(opsDir)) {
|
|
175
|
+
artifacts = fs.readdirSync(opsDir)
|
|
176
|
+
.filter(f => f.endsWith('.md'))
|
|
177
|
+
.map(f => `workspace/ops/${f}`);
|
|
178
|
+
}
|
|
179
|
+
} catch { /* ok */ }
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
passed, phase,
|
|
183
|
+
details: passed ? `phase "${phase}" gate passed` : gate.failDetail,
|
|
184
|
+
artifacts,
|
|
185
|
+
hints: passed ? [] : gate.hints,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// CLI entry
|
|
190
|
+
if (require.main === module) {
|
|
191
|
+
const cwd = process.env.VERIFIER_CWD || process.cwd();
|
|
192
|
+
const phase = process.env.VERIFIER_PHASE || 'unknown';
|
|
193
|
+
const result = verify(cwd, phase);
|
|
194
|
+
process.stdout.write(JSON.stringify(result));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
module.exports = { verify };
|
|
@@ -97,7 +97,7 @@ function withBufferLock(fn) {
|
|
|
97
97
|
acquired = true;
|
|
98
98
|
break;
|
|
99
99
|
} catch (e) {
|
|
100
|
-
if (e.code !== 'EEXIST')
|
|
100
|
+
if (e.code !== 'EEXIST') return false; // non-EEXIST errors (EMFILE, EACCES) → skip lock gracefully
|
|
101
101
|
try {
|
|
102
102
|
const age = Date.now() - fs.statSync(LOCK_FILE).mtimeMs;
|
|
103
103
|
if (age > LOCK_STALE_MS) {
|
|
@@ -159,12 +159,12 @@ process.stdin.on('end', () => {
|
|
|
159
159
|
// Skip empty or very short messages
|
|
160
160
|
// Chinese chars carry more info per char, so use weighted length
|
|
161
161
|
const weightedLen = [...prompt].reduce((sum, ch) => sum + (ch.charCodeAt(0) > 0x2e80 ? 3 : 1), 0);
|
|
162
|
-
if (weightedLen < 15) {
|
|
162
|
+
if (!isMeta && weightedLen < 15) {
|
|
163
163
|
process.exit(0);
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
// Hard cap to prevent giant prompt pastes from poisoning distill budget.
|
|
167
|
-
if (prompt.length > ABSOLUTE_MAX_CAPTURE_CHARS) {
|
|
167
|
+
if (!isMeta && prompt.length > ABSOLUTE_MAX_CAPTURE_CHARS) {
|
|
168
168
|
process.exit(0);
|
|
169
169
|
}
|
|
170
170
|
if (prompt.length > MAX_CAPTURE_CHARS) {
|
|
@@ -75,6 +75,7 @@ const DEFAULT_POLICY = {
|
|
|
75
75
|
min_evidence_for_gap: 3,
|
|
76
76
|
max_updates_per_analysis: 3,
|
|
77
77
|
max_gaps_per_analysis: 2,
|
|
78
|
+
max_signals_per_analysis: 30, // cap signals sent to Haiku per run
|
|
78
79
|
|
|
79
80
|
// Workflow discovery
|
|
80
81
|
workflow_discovery_interval: 2, // every N cold-path cycles
|
|
@@ -200,6 +201,7 @@ function sanitizePolicy(input) {
|
|
|
200
201
|
min_evidence_for_gap: clampInt(merged.min_evidence_for_gap, DEFAULT_POLICY.min_evidence_for_gap, 1, 20),
|
|
201
202
|
max_updates_per_analysis: clampInt(merged.max_updates_per_analysis, DEFAULT_POLICY.max_updates_per_analysis, 1, 20),
|
|
202
203
|
max_gaps_per_analysis: clampInt(merged.max_gaps_per_analysis, DEFAULT_POLICY.max_gaps_per_analysis, 1, 20),
|
|
204
|
+
max_signals_per_analysis: clampInt(merged.max_signals_per_analysis, DEFAULT_POLICY.max_signals_per_analysis, 5, 100),
|
|
203
205
|
workflow_discovery_interval: clampInt(merged.workflow_discovery_interval, DEFAULT_POLICY.workflow_discovery_interval, 1, 100),
|
|
204
206
|
min_signals_for_workflow: clampInt(merged.min_signals_for_workflow, DEFAULT_POLICY.min_signals_for_workflow, 1, 100),
|
|
205
207
|
workflow_proposal_threshold: clampInt(merged.workflow_proposal_threshold, DEFAULT_POLICY.workflow_proposal_threshold, 2, 50),
|
|
@@ -610,8 +612,15 @@ async function distillSkills() {
|
|
|
610
612
|
if (!content) return null;
|
|
611
613
|
|
|
612
614
|
const lines = content.split('\n');
|
|
613
|
-
const
|
|
614
|
-
if (
|
|
615
|
+
const allSignals = lines.map(l => { try { return JSON.parse(l); } catch { return null; } }).filter(Boolean);
|
|
616
|
+
if (allSignals.length < policy.min_signals_for_distill) return null;
|
|
617
|
+
|
|
618
|
+
// Cap signals sent to Haiku to avoid prompt bloat / timeout.
|
|
619
|
+
// Keep most recent signals (higher relevance); overflow is still cleared.
|
|
620
|
+
const maxSignals = policy.max_signals_per_analysis || 30;
|
|
621
|
+
const signals = allSignals.length > maxSignals
|
|
622
|
+
? allSignals.slice(-maxSignals)
|
|
623
|
+
: allSignals;
|
|
615
624
|
|
|
616
625
|
// Get installed skills list
|
|
617
626
|
const installedSkills = listInstalledSkills();
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-browser
|
|
3
|
+
description: AI Agent 专属无头浏览器 CLI(省 token 80%)。触发:网页自动化、打开网页、点击填表、截图抓快照、agent-browser。
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
tool: agent-browser
|
|
6
|
+
install: npm install -g agent-browser && agent-browser install
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# agent-browser — AI Agent 专属浏览器
|
|
10
|
+
|
|
11
|
+
## 核心优势
|
|
12
|
+
|
|
13
|
+
| 特性 | agent-browser | MCP playwright |
|
|
14
|
+
|------|--------------|----------------|
|
|
15
|
+
| 快照 token 消耗 | ~80% 更少 | 较多 |
|
|
16
|
+
| 安装方式 | 全局 CLI | MCP Server |
|
|
17
|
+
| 调用方式 | Bash 工具 | 专用 MCP 工具 |
|
|
18
|
+
| 底层引擎 | Playwright | Playwright |
|
|
19
|
+
| 状态持久化 | session 文件 | MCP 进程生命周期 |
|
|
20
|
+
| Electron 桌面 App | ✅ 支持 | ❌ 不支持 |
|
|
21
|
+
|
|
22
|
+
## 安装验证
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
agent-browser --version # 应输出版本号(当前 0.15.2)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
若未安装:
|
|
29
|
+
```bash
|
|
30
|
+
npm install -g agent-browser
|
|
31
|
+
agent-browser install # 安装 Chromium
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 核心工作流
|
|
35
|
+
|
|
36
|
+
### 1. 打开页面 + 抓快照(核心循环)
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
agent-browser open <url>
|
|
40
|
+
agent-browser snapshot # 输出带 @ref 的可交互元素树
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
快照格式示例:
|
|
44
|
+
```
|
|
45
|
+
- heading "Example Domain" [ref=e1] [level=1]
|
|
46
|
+
- link "Learn more" [ref=e2]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
AI 直接用 `@e1`、`@e2` 引用元素,无需 CSS/XPath 选择器。
|
|
50
|
+
|
|
51
|
+
### 2. 常用操作命令
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# 导航
|
|
55
|
+
agent-browser open <url>
|
|
56
|
+
agent-browser back / forward / reload
|
|
57
|
+
|
|
58
|
+
# 交互
|
|
59
|
+
agent-browser click @e3
|
|
60
|
+
agent-browser fill @e5 "搜索内容"
|
|
61
|
+
agent-browser press Enter
|
|
62
|
+
agent-browser hover @e7
|
|
63
|
+
agent-browser select @e4 "选项值"
|
|
64
|
+
agent-browser upload @e6 /path/to/file
|
|
65
|
+
|
|
66
|
+
# 信息获取
|
|
67
|
+
agent-browser get text @e2
|
|
68
|
+
agent-browser get title
|
|
69
|
+
agent-browser get url
|
|
70
|
+
agent-browser is visible @e1
|
|
71
|
+
agent-browser is enabled @e2
|
|
72
|
+
|
|
73
|
+
# 视觉工具
|
|
74
|
+
agent-browser screenshot /tmp/debug.png
|
|
75
|
+
agent-browser screenshot --annotate /tmp/annotated.png # 带元素标注
|
|
76
|
+
|
|
77
|
+
# 等待
|
|
78
|
+
agent-browser wait @e1 # 等元素出现
|
|
79
|
+
agent-browser wait 2000 # 等 2 秒
|
|
80
|
+
|
|
81
|
+
# 执行 JS
|
|
82
|
+
agent-browser eval "document.title"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 3. 语义查找(不用 @ref)
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
agent-browser find role button "提交" # 按 ARIA role 找
|
|
89
|
+
agent-browser find text "登录" # 按文本找
|
|
90
|
+
agent-browser find label "用户名" # 按 label 找
|
|
91
|
+
agent-browser find placeholder "请输入" # 按 placeholder 找
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 4. 状态管理
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# 保存登录状态
|
|
98
|
+
agent-browser set session ~/.agent-sessions/github.json
|
|
99
|
+
|
|
100
|
+
# 后续会话复用
|
|
101
|
+
agent-browser open github.com --session ~/.agent-sessions/github.json
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## 标准 Agent 任务模板
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Step 1: 打开目标页面
|
|
108
|
+
agent-browser open <url>
|
|
109
|
+
|
|
110
|
+
# Step 2: 抓快照,识别元素
|
|
111
|
+
agent-browser snapshot
|
|
112
|
+
# AI 分析快照,找到目标 @ref
|
|
113
|
+
|
|
114
|
+
# Step 3: 执行操作
|
|
115
|
+
agent-browser click @eN
|
|
116
|
+
agent-browser fill @eM "内容"
|
|
117
|
+
agent-browser press Enter
|
|
118
|
+
|
|
119
|
+
# Step 4: 等待并验证结果
|
|
120
|
+
agent-browser wait ".success-msg"
|
|
121
|
+
agent-browser get text ".result"
|
|
122
|
+
|
|
123
|
+
# Step 5: 截图留档(可选)
|
|
124
|
+
agent-browser screenshot /tmp/result.png
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## 与 MCP Playwright 协作策略
|
|
128
|
+
|
|
129
|
+
**用 agent-browser 的场景:**
|
|
130
|
+
- token 预算紧张的长流程任务
|
|
131
|
+
- 需要控制 Electron 桌面 App(Discord、Figma、Notion 等)
|
|
132
|
+
- 简单的网页自动化脚本
|
|
133
|
+
|
|
134
|
+
**继续用 MCP playwright 的场景:**
|
|
135
|
+
- 已有 playwright MCP 连接且不想切换
|
|
136
|
+
- 需要精细的 Playwright API(network mock、tracing)
|
|
137
|
+
- 现有工作流已稳定
|
|
138
|
+
|
|
139
|
+
## 常见错误处理
|
|
140
|
+
|
|
141
|
+
| 错误 | 处理 |
|
|
142
|
+
|------|------|
|
|
143
|
+
| `command not found` | 运行 `npm install -g agent-browser` |
|
|
144
|
+
| 浏览器未安装 | 运行 `agent-browser install` |
|
|
145
|
+
| 元素点击失败 | 先 `snapshot` 确认 @ref,改用 `find` 语义查找 |
|
|
146
|
+
| 页面未加载完 | 在操作前加 `agent-browser wait 1500` 或等待特定元素 |
|
|
147
|
+
|
|
148
|
+
## 进阶:连接现有浏览器
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# 连接 CDP 调试端口(可复用已登录的 Chrome)
|
|
152
|
+
agent-browser connect 9222
|
|
153
|
+
```
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-reach
|
|
3
|
+
description: 免费多平台信息采集CLI(Twitter/YouTube/B站/小红书/抖音/Reddit/LinkedIn/GitHub/RSS/网页)。触发:agent reach、爬取、读网页、搜推特、搜B站。**WebFetch 失败时优先用此 skill**:凡遇到 JS 渲染页面(Twitter/X、Instagram、LinkedIn 等)或 WebFetch 返回空内容/JavaScript错误,无需重试 WebFetch,直接调用此 skill。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Agent Reach
|
|
7
|
+
|
|
8
|
+
免费开源的多平台信息采集 CLI,安装后直接调用上游工具。
|
|
9
|
+
|
|
10
|
+
## 首次使用 / 诊断
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
agent-reach doctor # 查看各平台状态
|
|
14
|
+
agent-reach install --env=auto # 自动安装依赖
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 详细命令参考
|
|
18
|
+
|
|
19
|
+
完整的平台命令和配置指南在上游 SKILL.md:
|
|
20
|
+
```bash
|
|
21
|
+
cat /tmp/Agent-Reach/agent_reach/skill/SKILL.md
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
如果 /tmp 已清理,重新获取:
|
|
25
|
+
```bash
|
|
26
|
+
pip show agent-reach | grep Location
|
|
27
|
+
# 然后读取 <location>/agent_reach/skill/SKILL.md
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
或直接查看:https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/skill/SKILL.md
|
|
31
|
+
|
|
32
|
+
## 快速速查
|
|
33
|
+
|
|
34
|
+
| 平台 | 工具 | 示例 |
|
|
35
|
+
|------|------|------|
|
|
36
|
+
| 任意网页 | Jina | `curl -s "https://r.jina.ai/URL"` |
|
|
37
|
+
| Twitter | xreach | `xreach search "query" --json -n 10` |
|
|
38
|
+
| YouTube | yt-dlp | `yt-dlp --dump-json "URL"` |
|
|
39
|
+
| B站 | yt-dlp | `yt-dlp --dump-json "bilibili URL"` |
|
|
40
|
+
| Reddit | curl | `curl -s "https://reddit.com/r/xxx/hot.json?limit=10"` |
|
|
41
|
+
| GitHub | gh | `gh search repos "query" --sort stars` |
|
|
42
|
+
| 小红书 | mcporter | `mcporter call 'xiaohongshu.search_feeds(...)'` |
|
|
43
|
+
| 抖音 | mcporter | `mcporter call 'douyin.parse_douyin_video_info(...)'` |
|
|
44
|
+
| LinkedIn | mcporter | `mcporter call 'linkedin.get_person_profile(...)'` |
|
|
45
|
+
| RSS | feedparser | Python `feedparser.parse(url)` |
|
|
46
|
+
|
|
47
|
+
## Cookie 配置(需登录的平台)
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
agent-reach configure --from-browser chrome # 自动提取
|
|
51
|
+
agent-reach configure twitter-cookies "auth_token=xxx; ct0=yyy" # 手动
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
> 提醒用户使用专用小号,Cookie 登录有封号风险。
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
<!-- METAME-EVOLUTION:START -->
|
|
58
|
+
|
|
59
|
+
## User-Learned Best Practices & Constraints
|
|
60
|
+
|
|
61
|
+
> **Auto-Generated Section**: Maintained by skill-evolution-manager. Do not edit manually.
|
|
62
|
+
|
|
63
|
+
### Known Fixes & Workarounds
|
|
64
|
+
- Repeatedly failing on Twitter/X links (signals #7, #15, #30 all tool_failure); improve X.com social media parsing robustness or add fallback extraction method for social platforms
|
|
65
|
+
|
|
66
|
+
<!-- METAME-EVOLUTION:END -->
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"last_updated": "2026-03-17T13:41:59.591Z",
|
|
3
|
+
"fixes": [
|
|
4
|
+
"Repeatedly failing on Twitter/X links (signals #7, #15, #30 all tool_failure); improve X.com social media parsing robustness or add fallback extraction method for social platforms"
|
|
5
|
+
],
|
|
6
|
+
"insights_stats": {
|
|
7
|
+
"Repeatedly failing on Twitter/X links (signals #7, #15, #30 all tool_failure); improve X.com social media parsing robustness or add fallback extraction method for social platforms": {
|
|
8
|
+
"success_count": 3,
|
|
9
|
+
"fail_count": 0,
|
|
10
|
+
"last_applied_at": "2026-03-20T00:11:44.684Z"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deep-research
|
|
3
|
+
description: AI深度研究助手。对任何主题进行迭代式深度研究,结合搜索引擎、网页抓取和大语言模型生成详细研究报告。触发词:深度研究、调研、research。
|
|
4
|
+
version: 2.0.0
|
|
5
|
+
created_at: 2026-01-29
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Deep Research 深度研究
|
|
9
|
+
|
|
10
|
+
基于 [dzhng/deep-research](https://github.com/dzhng/deep-research) 思路,用 Claude Code 原生能力实现。
|
|
11
|
+
|
|
12
|
+
## 研究流程
|
|
13
|
+
|
|
14
|
+
收到研究请求后,按以下步骤执行:
|
|
15
|
+
|
|
16
|
+
### 1. 分解查询(广度)
|
|
17
|
+
根据主题生成 3-5 个不同角度的搜索查询:
|
|
18
|
+
- 基础概念/定义
|
|
19
|
+
- 最新进展/动态
|
|
20
|
+
- 技术实现/原理
|
|
21
|
+
- 应用场景/案例
|
|
22
|
+
- 对比/竞品
|
|
23
|
+
|
|
24
|
+
### 2. 迭代搜索(深度)
|
|
25
|
+
对每个查询:
|
|
26
|
+
1. `WebSearch` 获取搜索结果
|
|
27
|
+
2. `WebFetch` 抓取 2-3 个高质量页面详情
|
|
28
|
+
3. 提取关键信息,发现新问题
|
|
29
|
+
4. 对新问题继续搜索(迭代 1-2 轮)
|
|
30
|
+
|
|
31
|
+
### 2.5 NotebookLM 补充查询(可选)
|
|
32
|
+
|
|
33
|
+
如果用户的 NotebookLM 中有与主题相关的笔记本,可作为**私有知识源**补充公开搜索的盲区:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# 搜索是否有相关笔记本
|
|
37
|
+
python ~/.claude/skills/notebooklm-skill/scripts/run.py notebook_manager.py search --query "关键词"
|
|
38
|
+
|
|
39
|
+
# 查询笔记本获取有引用的回答
|
|
40
|
+
python ~/.claude/skills/notebooklm-skill/scripts/run.py ask_question.py --question "具体问题" --notebook-id ID
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**使用时机**:
|
|
44
|
+
- 话题涉及用户个人积累的领域知识(已上传到 NotebookLM)
|
|
45
|
+
- 公开搜索结果不够深入,需要私有资料补充
|
|
46
|
+
- 用户主动要求"查一下我的 NotebookLM"
|
|
47
|
+
|
|
48
|
+
**不要**每次调研都自动查 NotebookLM,只在相关时使用。
|
|
49
|
+
|
|
50
|
+
### 3. 综合报告
|
|
51
|
+
整合所有信息,输出结构化报告:
|
|
52
|
+
|
|
53
|
+
```markdown
|
|
54
|
+
# [主题] 深度研究报告
|
|
55
|
+
|
|
56
|
+
## 摘要
|
|
57
|
+
[3-5 句核心发现]
|
|
58
|
+
|
|
59
|
+
## 背景与定义
|
|
60
|
+
## 技术原理/核心机制
|
|
61
|
+
## 最新进展
|
|
62
|
+
## 应用场景
|
|
63
|
+
## 竞品对比(如适用)
|
|
64
|
+
## 未来展望
|
|
65
|
+
## 参考来源
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## 使用示例
|
|
69
|
+
|
|
70
|
+
用户说:
|
|
71
|
+
- "深度研究一下 AI Agent"
|
|
72
|
+
- "调研 MCP 协议的最新进展"
|
|
73
|
+
- "research Claude Code 的竞品"
|
|
74
|
+
|
|
75
|
+
## 输出位置
|
|
76
|
+
|
|
77
|
+
报告写入:`/tmp/research_report.md`
|