@fugui200/llmwiki 0.1.2-beta.0 → 0.1.2-beta.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/README.md +3 -3
- package/package.json +1 -1
- package/scripts/codex-hook.js +1 -0
- package/scripts/init-project.js +97 -7
- package/skill/llmwiki-connector/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -51,9 +51,9 @@ llmwiki push "archive: update project notes"
|
|
|
51
51
|
|
|
52
52
|
## Agents
|
|
53
53
|
|
|
54
|
-
- `codex`: writes `.llmwiki.json
|
|
55
|
-
- `claude-code`: writes `.claude/settings.json` plus a lightweight `CLAUDE.md` block
|
|
56
|
-
- `gemini`: writes a lightweight `GEMINI.md` block
|
|
54
|
+
- `codex`: writes `.llmwiki.json`, installs a global Codex hook, and installs `llmwiki-connector` to `$HOME/.codex/skills/`.
|
|
55
|
+
- `claude-code`: writes `.claude/settings.json` plus a lightweight `CLAUDE.md` block, and installs `llmwiki-connector` to `$HOME/.claude/skills/`.
|
|
56
|
+
- `gemini`: writes a lightweight `GEMINI.md` block, and installs `llmwiki-connector` to `$HOME/.gemini/skills/`.
|
|
57
57
|
- `all`: configures all supported agents.
|
|
58
58
|
|
|
59
59
|
Agent integrations only inject routing metadata and recall rules. They do not
|
package/package.json
CHANGED
package/scripts/codex-hook.js
CHANGED
|
@@ -77,6 +77,7 @@ function buildAdditionalContext(cwd) {
|
|
|
77
77
|
'Use this as routing metadata only. Do not read or load global LLM Wiki pages at startup, after /clear, or for ordinary prompts.',
|
|
78
78
|
'Search/read wiki pages only when the user asks to recall/archive knowledge, or when the current task clearly needs prior project context.',
|
|
79
79
|
'When recall is needed, prefer current archiveProjects first; use shared patterns/tools/concepts only after keyword matching.',
|
|
80
|
+
'When the user asks to archive to llmwiki or 沉淀到 llmwiki, use the llmwiki-connector skill and the configured wikiRoot; do not route that task to OMX wiki.',
|
|
80
81
|
];
|
|
81
82
|
|
|
82
83
|
if (legacyTargets.length) {
|
package/scripts/init-project.js
CHANGED
|
@@ -16,10 +16,11 @@
|
|
|
16
16
|
const fs = require('fs');
|
|
17
17
|
const os = require('os');
|
|
18
18
|
const path = require('path');
|
|
19
|
-
const { writeProjectConfig, writeWorkspaceConfig } = require('./classify-project');
|
|
19
|
+
const { resolveWikiRoot, writeProjectConfig, writeWorkspaceConfig } = require('./classify-project');
|
|
20
20
|
|
|
21
21
|
const LLMWIKI_CONTEXT_BLOCK_START = '<!-- LLMWIKI:START -->';
|
|
22
22
|
const LLMWIKI_CONTEXT_BLOCK_END = '<!-- LLMWIKI:END -->';
|
|
23
|
+
const CONNECTOR_SKILL_NAME = 'llmwiki-connector';
|
|
23
24
|
const STOP_HOOK_COMMAND = [
|
|
24
25
|
'if [ -d ~/.llmwiki/.git ]; then',
|
|
25
26
|
'echo \'[LLM Wiki] 如果本次工作产出了新知识',
|
|
@@ -99,9 +100,9 @@ function showInitHelp() {
|
|
|
99
100
|
console.log(' 为当前项目导入指定 Agent 的 LLM Wiki 接入配置。');
|
|
100
101
|
console.log('');
|
|
101
102
|
console.log('Agent:');
|
|
102
|
-
console.log(' claude-code 写入 .claude/settings.json hooks');
|
|
103
|
-
console.log(' codex 写入 .llmwiki.json
|
|
104
|
-
console.log(' gemini 写入 GEMINI.md
|
|
103
|
+
console.log(' claude-code 写入 .claude/settings.json hooks,并安装 $HOME/.claude/skills/llmwiki-connector');
|
|
104
|
+
console.log(' codex 写入 .llmwiki.json、全局 hook,并安装 $HOME/.codex/skills/llmwiki-connector');
|
|
105
|
+
console.log(' gemini 写入 GEMINI.md,并安装 $HOME/.gemini/skills/llmwiki-connector');
|
|
105
106
|
console.log(' all 同时导入 claude-code、codex、gemini');
|
|
106
107
|
console.log('');
|
|
107
108
|
console.log('选项:');
|
|
@@ -348,6 +349,14 @@ function defaultWikiRootForProfile(profile) {
|
|
|
348
349
|
return '~/.llmwiki';
|
|
349
350
|
}
|
|
350
351
|
|
|
352
|
+
function ensureTeamWikiRoot(config, configDir) {
|
|
353
|
+
if (config.profile !== 'team') return null;
|
|
354
|
+
|
|
355
|
+
const wikiRoot = resolveWikiRoot(config, configDir);
|
|
356
|
+
fs.mkdirSync(wikiRoot, { recursive: true });
|
|
357
|
+
return wikiRoot;
|
|
358
|
+
}
|
|
359
|
+
|
|
351
360
|
async function promptInteractiveConfig(args, input = process.stdin, output = process.stdout) {
|
|
352
361
|
if (!input.isTTY || !output.isTTY) return args;
|
|
353
362
|
|
|
@@ -470,6 +479,7 @@ function installClaudeCode(projectRoot) {
|
|
|
470
479
|
const claudeDir = path.join(projectRoot, '.claude');
|
|
471
480
|
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
472
481
|
const claudePath = path.join(projectRoot, 'CLAUDE.md');
|
|
482
|
+
const skillResult = installConnectorSkill(path.join(resolveClaudeHome(), 'skills'));
|
|
473
483
|
fs.mkdirSync(claudeDir, { recursive: true });
|
|
474
484
|
|
|
475
485
|
let settings = {};
|
|
@@ -486,10 +496,12 @@ function installClaudeCode(projectRoot) {
|
|
|
486
496
|
|
|
487
497
|
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, '\t') + '\n');
|
|
488
498
|
console.log(`✓ Claude Code hook/context 已${stopStatus === 'updated' ? '更新' : '导入'}: .claude/settings.json, CLAUDE.md`);
|
|
499
|
+
logSkillResult('Claude Code', skillResult);
|
|
489
500
|
}
|
|
490
501
|
|
|
491
502
|
function installCodex(projectRoot) {
|
|
492
503
|
const result = installCodexGlobalHooks();
|
|
504
|
+
const skillResult = installCodexSkill();
|
|
493
505
|
console.log('✓ Codex 接入已标记: .llmwiki.json');
|
|
494
506
|
if (result.status === 'installed') {
|
|
495
507
|
console.log(`✓ Codex 全局 hook 已写入: ${result.hooksPath}`);
|
|
@@ -500,13 +512,85 @@ function installCodex(projectRoot) {
|
|
|
500
512
|
} else {
|
|
501
513
|
console.log(`⚠ Codex 全局 hook 未写入: ${result.reason}`);
|
|
502
514
|
}
|
|
515
|
+
if (skillResult.status === 'installed') {
|
|
516
|
+
console.log(`✓ Codex skill 已安装: ${skillResult.skillPath}`);
|
|
517
|
+
} else if (skillResult.status === 'updated') {
|
|
518
|
+
console.log(`✓ Codex skill 已更新: ${skillResult.skillPath}`);
|
|
519
|
+
} else {
|
|
520
|
+
console.log(`⚠ Codex skill 未安装: ${skillResult.reason}`);
|
|
521
|
+
}
|
|
503
522
|
console.log(' Codex hook 只注入项目归属元数据;需要召回时再按需读取 wiki。');
|
|
504
523
|
}
|
|
505
524
|
|
|
506
525
|
function resolveCodexHome() {
|
|
507
|
-
return
|
|
508
|
-
|
|
509
|
-
|
|
526
|
+
return path.join(resolveUserHome(), '.codex');
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function resolveClaudeHome() {
|
|
530
|
+
return path.join(resolveUserHome(), '.claude');
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function resolveGeminiHome() {
|
|
534
|
+
return path.join(resolveUserHome(), '.gemini');
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
function resolveUserHome() {
|
|
538
|
+
return process.env.HOME ? path.resolve(process.env.HOME) : os.homedir();
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
function copyDirectory(src, dest) {
|
|
542
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
543
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
544
|
+
const from = path.join(src, entry.name);
|
|
545
|
+
const to = path.join(dest, entry.name);
|
|
546
|
+
if (entry.isDirectory()) {
|
|
547
|
+
copyDirectory(from, to);
|
|
548
|
+
} else if (entry.isFile()) {
|
|
549
|
+
fs.copyFileSync(from, to);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
function installConnectorSkill(skillsRoot) {
|
|
555
|
+
const skillSource = path.join(__dirname, '..', 'skill', CONNECTOR_SKILL_NAME);
|
|
556
|
+
const skillPath = path.join(skillsRoot, CONNECTOR_SKILL_NAME);
|
|
557
|
+
|
|
558
|
+
try {
|
|
559
|
+
if (!fs.existsSync(skillSource)) {
|
|
560
|
+
return {
|
|
561
|
+
status: 'failed',
|
|
562
|
+
skillPath,
|
|
563
|
+
reason: `skill 源目录不存在: ${skillSource}`,
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
const existed = fs.existsSync(skillPath);
|
|
568
|
+
copyDirectory(skillSource, skillPath);
|
|
569
|
+
return {
|
|
570
|
+
status: existed ? 'updated' : 'installed',
|
|
571
|
+
skillPath,
|
|
572
|
+
};
|
|
573
|
+
} catch (error) {
|
|
574
|
+
return {
|
|
575
|
+
status: 'failed',
|
|
576
|
+
skillPath,
|
|
577
|
+
reason: error.message,
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
function installCodexSkill() {
|
|
583
|
+
return installConnectorSkill(path.join(resolveCodexHome(), 'skills'));
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
function logSkillResult(agentName, result) {
|
|
587
|
+
if (result.status === 'installed') {
|
|
588
|
+
console.log(`✓ ${agentName} skill 已安装: ${result.skillPath}`);
|
|
589
|
+
} else if (result.status === 'updated') {
|
|
590
|
+
console.log(`✓ ${agentName} skill 已更新: ${result.skillPath}`);
|
|
591
|
+
} else {
|
|
592
|
+
console.log(`⚠ ${agentName} skill 未安装: ${result.reason}`);
|
|
593
|
+
}
|
|
510
594
|
}
|
|
511
595
|
|
|
512
596
|
function buildCodexHookCommand() {
|
|
@@ -585,8 +669,10 @@ function installCodexGlobalHooks() {
|
|
|
585
669
|
|
|
586
670
|
function installGemini(projectRoot) {
|
|
587
671
|
const geminiPath = path.join(projectRoot, 'GEMINI.md');
|
|
672
|
+
const skillResult = installConnectorSkill(path.join(resolveGeminiHome(), 'skills'));
|
|
588
673
|
upsertContextBlock(geminiPath);
|
|
589
674
|
console.log('✓ Gemini context 已导入: GEMINI.md');
|
|
675
|
+
logSkillResult('Gemini', skillResult);
|
|
590
676
|
}
|
|
591
677
|
|
|
592
678
|
function expandAgent(agent) {
|
|
@@ -634,22 +720,26 @@ async function main() {
|
|
|
634
720
|
|
|
635
721
|
if (args.workspace) {
|
|
636
722
|
const { configPath, config } = writeWorkspaceConfig(projectRoot, configOptions);
|
|
723
|
+
const createdWikiRoot = ensureTeamWikiRoot(config, projectRoot);
|
|
637
724
|
console.log(`✓ workspace 配置已写入 ${path.relative(projectRoot, configPath)}`);
|
|
638
725
|
console.log(` - workspace: ${config.name}`);
|
|
639
726
|
console.log(` - profile: ${config.profile}`);
|
|
640
727
|
console.log(` - wikiRoot: ${config.wikiRoot}`);
|
|
641
728
|
console.log(` - sync: ${config.sync.type}${config.sync.branch ? ` ${config.sync.branch}` : ''}`);
|
|
642
729
|
console.log(` - projects: ${Object.keys(config.projectRoots).join(', ') || '(none detected)'}`);
|
|
730
|
+
if (createdWikiRoot) console.log(`✓ team wikiRoot 已创建: ${createdWikiRoot}`);
|
|
643
731
|
wikiConfigWritten = true;
|
|
644
732
|
return;
|
|
645
733
|
}
|
|
646
734
|
|
|
647
735
|
const { configPath, config } = writeProjectConfig(projectRoot, configOptions);
|
|
736
|
+
const createdWikiRoot = ensureTeamWikiRoot(config, projectRoot);
|
|
648
737
|
console.log(`✓ project 配置已写入 ${path.relative(projectRoot, configPath)}`);
|
|
649
738
|
console.log(` - project: ${config.name}`);
|
|
650
739
|
console.log(` - profile: ${config.profile}`);
|
|
651
740
|
console.log(` - wikiRoot: ${config.wikiRoot}`);
|
|
652
741
|
console.log(` - sync: ${config.sync.type}${config.sync.branch ? ` ${config.sync.branch}` : ''}`);
|
|
742
|
+
if (createdWikiRoot) console.log(`✓ team wikiRoot 已创建: ${createdWikiRoot}`);
|
|
653
743
|
wikiConfigWritten = true;
|
|
654
744
|
};
|
|
655
745
|
|
|
@@ -113,7 +113,7 @@ llmwiki init --agent gemini
|
|
|
113
113
|
llmwiki init --agent all
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
-
`llmwiki init` 在交互终端中会依次询问 agent、是否 workspace、profile(personal/team/local)和 wikiRoot;非交互环境必须显式传参。`claude-code` 写入 `.claude/settings.json` 归档提醒 hook
|
|
116
|
+
`llmwiki init` 在交互终端中会依次询问 agent、是否 workspace、profile(personal/team/local)和 wikiRoot;非交互环境必须显式传参。`claude-code` 写入 `.claude/settings.json` 归档提醒 hook、`CLAUDE.md` 按需召回规则,并安装 `$HOME/.claude/skills/llmwiki-connector`;`codex` 写入 `.llmwiki.json` 项目标记、全局 Codex hooks,并安装 `$HOME/.codex/skills/llmwiki-connector`;`gemini` 写入 `GEMINI.md` 项目上下文入口,并安装 `$HOME/.gemini/skills/llmwiki-connector`;`all` 同时导入三者。三种接入默认只使用项目归属元数据和按需召回规则,不在启动、`/clear` 或普通提问时自动加载全局 wiki 页面。
|
|
117
117
|
|
|
118
118
|
## 注意事项
|
|
119
119
|
|