From a63562661a0276f1358e8213a8065d137038ca28 Mon Sep 17 00:00:00 2001 From: Windsander Date: Mon, 14 Sep 2026 21:17:12 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat(skill):=20G6.4=20=E8=A1=8C=E7=82=BA?= =?UTF-8?q?=E5=B1=A4=E5=8C=85=E8=88=87=20CLI=EF=BC=88init/keygen/print-con?= =?UTF-8?q?fig/status=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - feat(skill): 新增 packages/skill(@mebular/skill):SKILL.md(frontmatter name=mebular-memory+whenToUse)、MEMORY_POLICY.md、mcp/{opencode,claude,cursor,dsh.cordis,generic}、scripts/install.mjs - feat(skill): install.mjs 探測 .agents/skills / .dsh/skills / .opencode/skills / ~/.agents/skills,支援 --target/--global - feat(cli): init(config.json + 主密鑰,不覆蓋既有)、keygen、print-config --client、status - test(skill): scripts/verify-mcp-skill.mjs(E1:包內容/CLI/install);agent 實機對話為 E2 - ci: build-test-lint job 增 Skill/CLI 步驟 對應 goal-v0.1.md G6.4 與 project-status.md D43。 --- .github/workflows/ci.yml | 3 + package.json | 3 +- packages/mcp/bin/mebular.mjs | 99 +++++++++++++++++++++++++- packages/skill/MEMORY_POLICY.md | 38 ++++++++++ packages/skill/SKILL.md | 44 ++++++++++++ packages/skill/mcp/claude.json | 8 +++ packages/skill/mcp/cursor.json | 8 +++ packages/skill/mcp/dsh.cordis.yml | 13 ++++ packages/skill/mcp/generic.json | 8 +++ packages/skill/mcp/opencode.json | 9 +++ packages/skill/package.json | 20 ++++++ packages/skill/scripts/install.mjs | 61 ++++++++++++++++ scripts/verify-mcp-skill.mjs | 110 +++++++++++++++++++++++++++++ 13 files changed, 421 insertions(+), 3 deletions(-) create mode 100644 packages/skill/MEMORY_POLICY.md create mode 100644 packages/skill/SKILL.md create mode 100644 packages/skill/mcp/claude.json create mode 100644 packages/skill/mcp/cursor.json create mode 100644 packages/skill/mcp/dsh.cordis.yml create mode 100644 packages/skill/mcp/generic.json create mode 100644 packages/skill/mcp/opencode.json create mode 100644 packages/skill/package.json create mode 100644 packages/skill/scripts/install.mjs create mode 100644 scripts/verify-mcp-skill.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d149b09..9f020aa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,6 +47,9 @@ jobs: - name: HTTP MCP (auth / PKCE / lock / fail-closed) run: npm run verify:mcp:http + - name: Skill package + CLI (init/keygen/print-config/status) + run: npm run verify:mcp:skill + semantic-real: name: semantic recall (real model) runs-on: ubuntu-latest diff --git a/package.json b/package.json index 8adadef..2b369f2 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js", "test:coverage": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage", "test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch", - "lint": "eslint src tests tests-semantic scripts packages/mcp --ext .ts,.mjs", + "lint": "eslint src tests tests-semantic scripts packages --ext .ts,.mjs", "verify": "node scripts/verify.mjs", "verify:at-rest": "node scripts/scan-at-rest.mjs", "verify:semantic": "node scripts/verify-semantic.mjs", @@ -62,6 +62,7 @@ "bench:snapshot": "node scripts/bench-snapshot.mjs", "verify:mcp:stdio": "node scripts/verify-mcp-stdio.mjs", "verify:mcp:http": "node scripts/verify-mcp-http.mjs", + "verify:mcp:skill": "node scripts/verify-mcp-skill.mjs", "dev": "node --loader ts-node/esm src/index.ts" }, "dependencies": { diff --git a/packages/mcp/bin/mebular.mjs b/packages/mcp/bin/mebular.mjs index dc3d8e9..5ed0722 100755 --- a/packages/mcp/bin/mebular.mjs +++ b/packages/mcp/bin/mebular.mjs @@ -80,6 +80,96 @@ async function runToken(action, flags) { process.exit(2); } +async function runKeygen(flags) { + const { IdentityManager } = await import('@mebular/core'); + const out = typeof flags.out === 'string' ? flags.out : join(homeDir(), 'user-master-key.json'); + const master = await new IdentityManager().generateUserMasterKey(); + const record = { + publicKey: Buffer.from(master.publicKey).toString('base64'), + privateKeyPkcs8: await IdentityManager.exportPrivateKey(master.privateKey), + createdAt: new Date().toISOString(), + }; + await mkdir(dirname(out), { recursive: true }); + await writeFile(out, JSON.stringify(record, null, 2), 'utf-8'); + await chmod(out, 0o600); + console.log(JSON.stringify({ keyFile: out, publicKey: record.publicKey }, null, 2)); + console.error('(主私钥是信任根,请妥善保管;权限 0600)'); +} + +async function runInit(flags) { + const home = homeDir(); + const configFile = join(home, 'config.json'); + const keyFile = join(home, 'user-master-key.json'); + await mkdir(home, { recursive: true }); + + if (!existsSync(keyFile)) await runKeygen({ out: keyFile }); + + if (existsSync(configFile)) { + console.log(`配置已存在,未覆盖:${configFile}`); + } else { + const config = { + storagePath: typeof flags['storage'] === 'string' ? flags['storage'] : join(home, 'store.jsonl'), + storageAdapter: 'json', + deviceId: typeof flags['device-id'] === 'string' ? flags['device-id'] : `device-${process.env.HOSTNAME ?? 'local'}`, + encryption: { level: 'none', keyFile }, + network: { enabled: false, libp2p: { listen: [], relayServers: [], relayUnlimited: false } }, + sync: { autoSync: true }, + semantic: { enabled: false, minScore: 0.2 }, + mcp: { http: { host: '127.0.0.1', port: 7331, auth: 'none', tls: false, tokensFile: join(home, 'auth', 'tokens.json') } }, + }; + await writeFile(configFile, JSON.stringify(config, null, 2), 'utf-8'); + console.log(`已写入配置:${configFile}`); + } + console.log( + [ + '', + '下一步:', + ' node packages/mcp/bin/mebular.mjs mcp # stdio 接入(各 MCP client)', + ' node packages/mcp/bin/mebular.mjs serve # Streamable HTTP', + ' node packages/mcp/bin/mebular.mjs status # 查看状态', + ' node packages/skill/scripts/install.mjs # 安装行为层 Skill', + ].join('\n'), + ); +} + +function runPrintConfig(flags) { + const client = typeof flags.client === 'string' ? flags.client : 'generic'; + const url = typeof flags.url === 'string' ? flags.url : null; + const local = { command: 'mebular', args: ['mcp'] }; + + const snippets = { + opencode: JSON.stringify( + { $schema: 'https://opencode.ai/config.json', mcp: { mebular: url ? { type: 'remote', url } : { type: 'local', command: ['mebular', 'mcp'] } } }, + null, + 2, + ), + claude: JSON.stringify({ mcpServers: { mebular: url ? { url } : local } }, null, 2), + cursor: JSON.stringify({ mcpServers: { mebular: url ? { url } : local } }, null, 2), + generic: JSON.stringify({ mcpServers: { mebular: url ? { url } : local } }, null, 2), + dsh: url + ? `plugins:\n - name: '@deepseek-ai/dsh-mcp-client'\n config:\n serverName: mebular\n transport: streamable-http\n url: ${url}` + : "plugins:\n - name: '@deepseek-ai/dsh-mcp-client'\n config:\n serverName: mebular\n transport: stdio\n command: mebular\n args: ['mcp']", + }; + const output = snippets[client]; + if (!output) { + console.error(`未知 client:${client}(opencode/claude/cursor/dsh/generic)`); + process.exit(2); + } + console.log(output); +} + +async function runStatus() { + const { createMebular } = await import('../src/config.mjs'); + const { MemoryService } = await import('@mebular/core'); + const { app, home, storagePath } = await createMebular(); + try { + const status = await new MemoryService(app).status(); + console.log(JSON.stringify({ ...status, home, storagePath }, null, 2)); + } finally { + await app.shutdown().catch(() => undefined); + } +} + async function main() { const flags = parseFlags(argv.slice(1)); switch (command) { @@ -127,11 +217,16 @@ async function main() { process.exit(0); return; case 'init': + await runInit(flags); + return; case 'keygen': + await runKeygen(flags); + return; case 'print-config': + runPrintConfig(flags); + return; case 'status': - console.error(`mebular ${command}:尚未实现(按 G6 计划补齐)`); - process.exit(2); + await runStatus(); return; default: console.error(`未知命令:${command ?? '(空)'}`); diff --git a/packages/skill/MEMORY_POLICY.md b/packages/skill/MEMORY_POLICY.md new file mode 100644 index 0000000..a865abc --- /dev/null +++ b/packages/skill/MEMORY_POLICY.md @@ -0,0 +1,38 @@ +# Mebular 记忆使用规约(MEMORY_POLICY) + +本文件是 Agent 使用 Mebular 记忆时的行为规约;与 `SKILL.md` 配套分发。 + +## 1. 先查后写 + +写入前先用 `memory_query` / `memory_search` 查重;已有等价记忆则不重复写入,必要时用更新语义。避免记忆库被重复条目稀释。 + +## 2. 类型选择 + +| 内容 | 类型 | +|------|------| +| 稳定事实(人、物、关系、客观陈述) | `fact` | +| 用户偏好(可随时间变化的取向) | `preference` | +| 会话 / 任务 / 决策 / 报错过程 | `episode` | +| 可复用的步骤、命令、流程 | `skill` | +| 对用户或环境的观察 | `observation` | + +## 3. 时效 + +- 有有效期的记忆用 `metadata.expiresAt` 标注。 +- 过期事实不要当作现状;需要现状时重新确认。 +- 事实冲突时以更新的 `validFrom` 为准。 + +## 4. 隐私 + +- 不要写入密钥、口令、令牌、完整证件号等高敏感信息。 +- 只记录完成任务所必需的最小信息。 +- 用户明确要求删除时,尊重删除语义(墓碑)。 + +## 5. 关系 + +- 相关对象用 `metadata.relatedTo` 关联**已存在**的节点,不要制造悬空引用。 +- 需要结构化关系时优先用既有实体作为端点。 + +## 6. 无结果别编 + +召回为空就如实说明「没有相关记忆」,不要凭推测填充。宁可承认缺失,也不写入或返回未经验证的内容。 diff --git a/packages/skill/SKILL.md b/packages/skill/SKILL.md new file mode 100644 index 0000000..b1b8dc8 --- /dev/null +++ b/packages/skill/SKILL.md @@ -0,0 +1,44 @@ +--- +name: mebular-memory +description: 通过 Mebular MCP 使用跨设备、离线可用的图式长期记忆:先查后写、类型化节点、时效与关系、隐私红线。 +whenToUse: 需要记住或复用用户偏好/事实/会话/技能,跨会话或跨设备共享 Agent 记忆,或按语义/关系检索既有记忆时。 +--- + +# Mebular Memory + +Mebular 是一个本地优先的分布式图记忆层。通过 MCP 工具读写记忆,行为规约见 `MEMORY_POLICY.md`。 + +## 何时使用 + +- 用户透露稳定偏好、事实或约束,且未来会复用时。 +- 需要回顾历史会话、任务过程或既有技能时。 +- 需要按语义(同义不同词)或关系检索既有记忆时。 + +## 工具(11 个) + +| 工具 | 用途 | +|------|------| +| `memory_write` / `memory_write_batch` | 写入一/多条记忆(fact / preference / episode / observation / skill) | +| `memory_query` | 语义(配置向量索引)/关键词召回,可按类型与过滤 | +| `memory_search` | 关键词检索,可选一跳关系 | +| `memory_profile` | 用户偏好与属性画像 | +| `memory_skills` | 技能列表(按分类/关键词/标签) | +| `memory_history` | 会话历史 | +| `memory_graph` | 从某节点遍历关系图 | +| `memory_import` | 经适配器导入异构来源(kv / markdown / …) | +| `memory_status` | 设备/网络/计数/状态哈希/开关 | +| `memory_sync` | 连接对端并等待一次同步(需 network.enabled) | + +## 工作流 + +1. **先查后写**:写入前用 `memory_query`/`memory_search` 查重。 +2. **选对类型**:稳定事实→`fact`;用户偏好→`preference`;会话/任务过程→`episode`;可复用步骤→`skill`;观察→`observation`。 +3. **标注时效**:有有效期的用 `metadata.expiresAt`;过期事实不当现状。 +4. **表达关系**:`metadata.relatedTo` 精确关联已存在节点。 +5. **诚实回答**:召回为空就如实说明,不要臆造记忆。 + +完整行为规约见 `MEMORY_POLICY.md`。 + +## 接入 + +本 Skill 目录附各客户端 MCP 接入片段(见 `mcp/`);`scripts/install.mjs` 可将本 Skill 安装到常见 Skill 目录。 diff --git a/packages/skill/mcp/claude.json b/packages/skill/mcp/claude.json new file mode 100644 index 0000000..c6931bc --- /dev/null +++ b/packages/skill/mcp/claude.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "mebular": { + "command": "mebular", + "args": ["mcp"] + } + } +} diff --git a/packages/skill/mcp/cursor.json b/packages/skill/mcp/cursor.json new file mode 100644 index 0000000..c6931bc --- /dev/null +++ b/packages/skill/mcp/cursor.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "mebular": { + "command": "mebular", + "args": ["mcp"] + } + } +} diff --git a/packages/skill/mcp/dsh.cordis.yml b/packages/skill/mcp/dsh.cordis.yml new file mode 100644 index 0000000..a6a38c7 --- /dev/null +++ b/packages/skill/mcp/dsh.cordis.yml @@ -0,0 +1,13 @@ +# DeepSeek Harness(Cordis)— 只桥接 Tools(不桥接 prompts) +# 行为规约以 SKILL.md + MEMORY_POLICY.md 为主通道。 +plugins: + - name: '@deepseek-ai/dsh-mcp-client' + config: + serverName: mebular + transport: stdio + command: mebular + args: ['mcp'] + +# 远程(Streamable HTTP)用: +# transport: streamable-http +# url: http://127.0.0.1:7331/mcp diff --git a/packages/skill/mcp/generic.json b/packages/skill/mcp/generic.json new file mode 100644 index 0000000..c6931bc --- /dev/null +++ b/packages/skill/mcp/generic.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "mebular": { + "command": "mebular", + "args": ["mcp"] + } + } +} diff --git a/packages/skill/mcp/opencode.json b/packages/skill/mcp/opencode.json new file mode 100644 index 0000000..31a5a5d --- /dev/null +++ b/packages/skill/mcp/opencode.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "mebular": { + "type": "local", + "command": ["mebular", "mcp"] + } + } +} diff --git a/packages/skill/package.json b/packages/skill/package.json new file mode 100644 index 0000000..eb1cb47 --- /dev/null +++ b/packages/skill/package.json @@ -0,0 +1,20 @@ +{ + "name": "@mebular/skill", + "version": "0.1.0", + "description": "Mebular 行为层:可移植的 SKILL.md + MEMORY_POLICY.md 与各 MCP client 接入片段", + "license": "MIT", + "private": false, + "type": "module", + "files": [ + "SKILL.md", + "MEMORY_POLICY.md", + "mcp", + "scripts" + ], + "engines": { + "node": ">=20" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/skill/scripts/install.mjs b/packages/skill/scripts/install.mjs new file mode 100644 index 0000000..216dc08 --- /dev/null +++ b/packages/skill/scripts/install.mjs @@ -0,0 +1,61 @@ +#!/usr/bin/env node +// 安装 Mebular Skill 到常见 Skill 目录(G6.4)。 +// +// 用法: +// node scripts/install.mjs # 探测并安装到 cwd 的 .agents/skills、.dsh/skills(及存在的 .opencode/skills) +// node scripts/install.mjs --global # 另装到 ~/.agents/skills +// node scripts/install.mjs --target # 只装到指定目录(/mebular-memory,测试/自定义用) + +import { existsSync } from 'node:fs'; +import { cp, mkdir } from 'node:fs/promises'; +import { homedir } from 'node:os'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const pkgRoot = join(dirname(fileURLToPath(import.meta.url)), '..'); +const SKILL_NAME = 'mebular-memory'; + +function parseFlags(argv) { + const flags = {}; + for (let i = 0; i < argv.length; i++) { + const token = argv[i]; + if (token.startsWith('--')) { + const key = token.slice(2); + const next = argv[i + 1]; + if (next === undefined || next.startsWith('--')) flags[key] = true; + else { + flags[key] = next; + i++; + } + } + } + return flags; +} + +const flags = parseFlags(process.argv.slice(2)); +const cwd = process.cwd(); +const targets = []; +if (typeof flags.target === 'string') { + targets.push(flags.target); +} else { + targets.push(join(cwd, '.agents', 'skills')); + targets.push(join(cwd, '.dsh', 'skills')); + if (existsSync(join(cwd, '.opencode'))) targets.push(join(cwd, '.opencode', 'skills')); + if (flags.global === true) targets.push(join(homedir(), '.agents', 'skills')); +} + +const installed = []; +for (const target of targets) { + const dest = join(target, SKILL_NAME); + await mkdir(dest, { recursive: true }); + await cp(join(pkgRoot, 'SKILL.md'), join(dest, 'SKILL.md')); + await cp(join(pkgRoot, 'MEMORY_POLICY.md'), join(dest, 'MEMORY_POLICY.md')); + installed.push(dest); + console.log(`installed ${dest}`); +} + +if (installed.length === 0) { + console.error('没有可安装的目标目录'); + process.exit(1); +} +console.log(JSON.stringify({ skill: SKILL_NAME, installed }, null, 2)); diff --git a/scripts/verify-mcp-skill.mjs b/scripts/verify-mcp-skill.mjs new file mode 100644 index 0000000..597c9b0 --- /dev/null +++ b/scripts/verify-mcp-skill.mjs @@ -0,0 +1,110 @@ +#!/usr/bin/env node +// G6.4 行为层 + CLI 验证(E1;agent 实机为 E2,见文末标注) +// +// 覆盖:@mebular/skill 包内容(SKILL.md frontmatter / MEMORY_POLICY.md / mcp 片段 / +// install.mjs)+ CLI init/keygen/print-config/status。 +// 干净环境退出码 0。前置:npm run build。 + +import { execFileSync } from 'node:child_process'; +import { existsSync } from 'node:fs'; +import { mkdtemp, readFile, rm } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const rootDir = join(__dirname, '..'); +const bin = join(rootDir, 'packages', 'mcp', 'bin', 'mebular.mjs'); +const skillDir = join(rootDir, 'packages', 'skill'); + +let passed = true; +const check = (label, ok, detail = '') => { + console.log(` ${ok ? '✓' : '✗'} ${label}${detail ? `(${detail})` : ''}`); + if (!ok) passed = false; +}; + +function run(args, env = {}) { + return execFileSync(process.execPath, args, { + cwd: rootDir, + encoding: 'utf-8', + env: { ...process.env, ...env }, + }); +} + +console.log('Mebular G6.4 行为层 + CLI 验证'); +console.log('=============================='); + +const dir = await mkdtemp(join(tmpdir(), 'mebular-skill-')); +const home = join(dir, 'home'); +const installTarget = join(dir, 'skills'); + +try { + // ---------- Skill 包内容 ---------- + check('SKILL.md 存在', existsSync(join(skillDir, 'SKILL.md'))); + check('MEMORY_POLICY.md 存在', existsSync(join(skillDir, 'MEMORY_POLICY.md'))); + const skill = await readFile(join(skillDir, 'SKILL.md'), 'utf-8'); + check('SKILL.md frontmatter name=mebular-memory', /^---[\s\S]*?name:\s*mebular-memory[\s\S]*?---/.test(skill)); + check('SKILL.md 含 whenToUse', /whenToUse:/.test(skill)); + for (const f of ['opencode.json', 'claude.json', 'cursor.json', 'dsh.cordis.yml', 'generic.json']) { + check(`mcp 片段 ${f}`, existsSync(join(skillDir, 'mcp', f))); + } + const policy = await readFile(join(skillDir, 'MEMORY_POLICY.md'), 'utf-8'); + check('MEMORY_POLICY 含「先查后写」「无结果别编」', policy.includes('先查后写') && policy.includes('无结果别编')); + + // ---------- CLI keygen ---------- + const keyOut = join(dir, 'k.json'); + const keygenOut = JSON.parse(run([bin, 'keygen', '--out', keyOut])); + check('keygen 生成主密钥文件', existsSync(keyOut) && typeof keygenOut.publicKey === 'string', keyOut); + + // ---------- CLI init ---------- + const initOut = run([bin, 'init'], { MEBULAR_HOME: home }); + const configPath = join(home, 'config.json'); + check('init 写入 config.json', existsSync(configPath)); + check('init 生成 user-master-key.json', existsSync(join(home, 'user-master-key.json'))); + const config = JSON.parse(await readFile(configPath, 'utf-8')); + check('config 含 mcp.http + storagePath', config.mcp?.http?.host === '127.0.0.1' && typeof config.storagePath === 'string'); + check('init 打印下一步', initOut.includes('install.mjs')); + + // ---------- CLI print-config ---------- + for (const client of ['opencode', 'claude', 'cursor', 'generic']) { + const out = run([bin, 'print-config', '--client', client]); + let ok = false; + try { + const parsed = JSON.parse(out); + ok = JSON.stringify(parsed).includes('mebular'); + } catch { + ok = false; + } + check(`print-config ${client}(JSON 含 mebular)`, ok); + } + const dsh = run([bin, 'print-config', '--client', 'dsh']); + check('print-config dsh(只桥接 Tools)', dsh.includes('@deepseek-ai/dsh-mcp-client') && dsh.includes('transport: stdio')); + const remote = run([bin, 'print-config', '--client', 'claude', '--url', 'https://example/mcp']); + check('print-config 远程 url 形态', JSON.parse(remote).mcpServers.mebular.url === 'https://example/mcp'); + + // ---------- CLI status ---------- + const status = JSON.parse(run([bin, 'status'], { MEBULAR_HOME: home })); + check('status 出 deviceId/stateHash', typeof status.deviceId === 'string' && /^[0-9a-f]{64}$/.test(status.stateHash)); + check('status 含 home/storagePath', typeof status.home === 'string' && typeof status.storagePath === 'string'); + + // ---------- install.mjs ---------- + const installOut = run([join(skillDir, 'scripts', 'install.mjs'), '--target', installTarget]); + const installedSkill = join(installTarget, 'mebular-memory', 'SKILL.md'); + check('install.mjs 安装 SKILL.md', existsSync(installedSkill), installOut.trim().split('\n')[0]); + check('install.mjs 安装 MEMORY_POLICY.md', existsSync(join(installTarget, 'mebular-memory', 'MEMORY_POLICY.md'))); +} catch (error) { + check('G6.4 验证', false, String(error?.message ?? error).substring(0, 400)); +} finally { + await rm(dir, { recursive: true, force: true }).catch(() => undefined); +} + +console.log('=============================='); +console.log('E2(人工,不影响上述 E1):opencode / Claude Code+Desktop / Cursor / DeepSeek Harness'); +console.log(' 按 packages/skill/mcp/* 片段接入后,走通「提问→召回→写入」。'); +if (passed) { + console.log('✓ G6.4 行为层 + CLI 验证通过(E1)'); + process.exit(0); +} else { + console.log('✗ G6.4 行为层 + CLI 验证失败'); + process.exit(1); +} From 46685beb7b76621e5cba2bb7fb3dd243e0b47685 Mon Sep 17 00:00:00 2001 From: Windsander Date: Mon, 14 Sep 2026 21:19:18 +0800 Subject: [PATCH 2/2] =?UTF-8?q?chore(skill):=20=E6=9B=B4=E6=96=B0=20lockfi?= =?UTF-8?q?le=20=E7=B4=8D=E5=85=A5=20@mebular/skill=20workspace?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/package-lock.json b/package-lock.json index 074acf3..40c9ba9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1796,6 +1796,10 @@ "resolved": "packages/mcp", "link": true }, + "node_modules/@mebular/skill": { + "resolved": "packages/skill", + "link": true + }, "node_modules/@modelcontextprotocol/client": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@modelcontextprotocol/client/-/client-2.0.0.tgz", @@ -7337,6 +7341,14 @@ "engines": { "node": ">=20" } + }, + "packages/skill": { + "name": "@mebular/skill", + "version": "0.1.0", + "license": "MIT", + "engines": { + "node": ">=20" + } } } }