first commit
This commit is contained in:
185
文档润色流和知识库构建流/claude-scholar/hooks/session-start.js
Normal file
185
文档润色流和知识库构建流/claude-scholar/hooks/session-start.js
Normal file
@@ -0,0 +1,185 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* SessionStart Hook: Display project status (cross-platform version)
|
||||
*
|
||||
* Event: SessionStart
|
||||
* Function: Display project status, Git info, todos, plugins, and commands at session start
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const fs = require('fs');
|
||||
|
||||
// Import shared utility library
|
||||
const common = require('./hook-common');
|
||||
|
||||
// Import package manager detection
|
||||
const { getPackageManager, getSelectionPrompt } = require('../scripts/lib/package-manager');
|
||||
|
||||
// Read stdin input
|
||||
let input = {};
|
||||
try {
|
||||
const stdinData = require('fs').readFileSync(0, 'utf8');
|
||||
if (stdinData.trim()) {
|
||||
input = JSON.parse(stdinData);
|
||||
}
|
||||
} catch {
|
||||
// Use default empty object
|
||||
}
|
||||
|
||||
const cwd = input.cwd || process.cwd();
|
||||
const projectName = path.basename(cwd);
|
||||
const homeDir = os.homedir();
|
||||
const binding = common.getProjectMemoryBinding(cwd);
|
||||
const researchCandidate = common.detectResearchProject(cwd);
|
||||
|
||||
// Build output
|
||||
let output = '';
|
||||
|
||||
// Session start info
|
||||
output += `🚀 ${projectName} Session started\n`;
|
||||
output += `▸ Time: ${common.formatDateTime()}\n`;
|
||||
output += `▸ Directory: ${cwd}\n\n`;
|
||||
|
||||
// Git status
|
||||
const gitInfo = common.getGitInfo(cwd);
|
||||
|
||||
if (gitInfo.is_repo) {
|
||||
output += `▸ Git branch: ${gitInfo.branch}\n\n`;
|
||||
|
||||
if (gitInfo.has_changes) {
|
||||
output += `⚠️ Uncommitted changes (${gitInfo.changes_count} files):\n`;
|
||||
|
||||
// Show change list (up to 5)
|
||||
const statusIcons = {
|
||||
'M': '📝', // Modified
|
||||
'A': '➕', // Added
|
||||
'D': '❌', // Deleted
|
||||
'R': '🔄', // Renamed
|
||||
'??': '❓' // Untracked
|
||||
};
|
||||
|
||||
for (let i = 0; i < Math.min(gitInfo.changes.length, 5); i++) {
|
||||
const change = gitInfo.changes[i];
|
||||
const status = change.substring(0, 2).trim();
|
||||
const file = change.substring(3).trim();
|
||||
|
||||
const icon = statusIcons[status] || '•';
|
||||
output += ` ${icon} ${file}\n`;
|
||||
}
|
||||
|
||||
if (gitInfo.changes_count > 5) {
|
||||
output += ` ... (${gitInfo.changes_count - 5} more files)\n`;
|
||||
}
|
||||
} else {
|
||||
output += `✅ Working directory clean\n`;
|
||||
}
|
||||
output += '\n';
|
||||
} else {
|
||||
output += `▸ Git: Not a repository\n\n`;
|
||||
}
|
||||
|
||||
if (binding.bound) {
|
||||
output += '🧠 Obsidian project KB: bound\n';
|
||||
output += ` - Project: ${binding.projectId || 'unknown'}\n`;
|
||||
output += ` - Status: ${binding.status || 'unknown'}\n`;
|
||||
output += ` - Auto-sync: ${binding.autoSync ? 'on' : 'off'}\n`;
|
||||
if (binding.vaultRoot) {
|
||||
output += ` - Vault root: ${binding.vaultRoot}\n`;
|
||||
}
|
||||
output += ' - Suggested commands: /kb-status, /kb-sync, /kb-lint\n\n';
|
||||
} else if (researchCandidate.candidate) {
|
||||
output += '🧠 Obsidian project KB: research repo candidate\n';
|
||||
output += ` - Detected markers: ${researchCandidate.markers.join(', ')}\n`;
|
||||
output += ' - Suggested command: /kb-init\n\n';
|
||||
}
|
||||
|
||||
// Package manager detection
|
||||
try {
|
||||
const pm = getPackageManager();
|
||||
output += `📦 Package manager: ${pm.name} (${pm.source})\n`;
|
||||
|
||||
// If detected via fallback, suggest setup
|
||||
if (pm.source === 'fallback' || pm.source === 'default') {
|
||||
output += `💡 Run /setup-pm to configure preferred package manager\n`;
|
||||
}
|
||||
} catch (err) {
|
||||
// Package manager detection failed, silently ignore
|
||||
}
|
||||
|
||||
output += '\n';
|
||||
|
||||
// Todos
|
||||
output += `📋 Todos:\n`;
|
||||
const todoInfo = common.getTodoInfo(cwd);
|
||||
|
||||
if (todoInfo.found) {
|
||||
output += ` - ${todoInfo.pending} pending / ${todoInfo.done} completed\n`;
|
||||
|
||||
// Show top 5 pending items
|
||||
if (fs.existsSync(todoInfo.path)) {
|
||||
try {
|
||||
const content = fs.readFileSync(todoInfo.path, 'utf8');
|
||||
const pendingItems = content.match(/^[\-\*] \[ \].+$/gm) || [];
|
||||
|
||||
if (pendingItems.length > 0) {
|
||||
output += `\n Recent todos:\n`;
|
||||
for (let i = 0; i < Math.min(5, pendingItems.length); i++) {
|
||||
const item = pendingItems[i].replace(/^[\-\*] \[ \]\s*/, '').substring(0, 60);
|
||||
output += ` - ${item}\n`;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Ignore errors
|
||||
}
|
||||
}
|
||||
} else {
|
||||
output += ` No todo file found (TODO.md, docs/todo.md etc)\n`;
|
||||
}
|
||||
|
||||
output += '\n';
|
||||
|
||||
// Enabled plugins
|
||||
output += `🔌 Enabled plugins:\n`;
|
||||
const enabledPlugins = common.getEnabledPlugins(homeDir);
|
||||
|
||||
if (enabledPlugins.length > 0) {
|
||||
for (let i = 0; i < Math.min(5, enabledPlugins.length); i++) {
|
||||
output += ` - ${enabledPlugins[i].name}\n`;
|
||||
}
|
||||
if (enabledPlugins.length > 5) {
|
||||
output += ` ... and ${enabledPlugins.length - 5} more plugins\n`;
|
||||
}
|
||||
} else {
|
||||
output += ` None\n`;
|
||||
}
|
||||
|
||||
output += '\n';
|
||||
|
||||
// Available commands
|
||||
output += `💡 Available commands:\n`;
|
||||
const availableCommands = common.getAvailableCommands(homeDir);
|
||||
|
||||
if (availableCommands.length > 0) {
|
||||
for (const cmd of availableCommands.slice(0, 5)) {
|
||||
const description = common.getCommandDescription(cmd.path) || `${cmd.plugin} command`;
|
||||
const truncatedDesc = description.length > 40 ? description.substring(0, 40) + '...' : description;
|
||||
output += ` /${cmd.name.padEnd(20)} ${truncatedDesc}\n`;
|
||||
}
|
||||
|
||||
if (availableCommands.length > 5) {
|
||||
output += ` ... and ${availableCommands.length - 5} more commands, use /help to list all\n`;
|
||||
}
|
||||
} else {
|
||||
output += ` No commands found\n`;
|
||||
}
|
||||
|
||||
// Output JSON
|
||||
const result = {
|
||||
continue: true,
|
||||
systemMessage: output
|
||||
};
|
||||
|
||||
console.log(JSON.stringify(result));
|
||||
|
||||
process.exit(0);
|
||||
Reference in New Issue
Block a user