@gabrywu/knowledge-bank 0.1.2-alpha.175 → 0.1.2-alpha.181

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/dist/index.js CHANGED
@@ -1 +1 @@
1
- import e,{dirname as t}from"path";import n from"os";import s,{readFileSync as o,existsSync as i,mkdirSync as r}from"fs";import{fileURLToPath as a}from"url";import{exec as d}from"child_process";import l from"better-sqlite3";import u from"simple-git";import{cwd as p}from"process";const c={logging:{level:"DEBUG"},db:{path:e.join(n.homedir(),".knowledge-bank","knowledge.db"),configs:["journal_mode = WAL","foreign_keys = ON"]},tmp:e.join(n.homedir(),".knowledge-bank","tmp")};let E=null;function _(){if(null===E){const t=process.env.KNOWLEDGE_CONF_DIR||e.join(n.homedir(),".knowledge-bank"),o=e.join(t,"config.json");E={...c,...s.existsSync(o)?JSON.parse(s.readFileSync(o,"utf-8")):{}}}return E}const h=_(),g={DEBUG:"DEBUG",INFO:"INFO",WARN:"WARN",ERROR:"ERROR"},R=Object.values(g);class m{constructor(t,o){this.loggerName=o;const i=h.logging.path||e.join(n.homedir(),".knowledge-bank","logs");s.mkdirSync(i,{recursive:!0}),this.loggerFile=e.join(i,`${t}.log`),this.logLevel=h.logging.level.toUpperCase()||g.INFO}formatMessage(e,t,n=null){const s=`${(new Date).toISOString().replace("T","-").split(".")[0]} ${this.loggerName} ${e}: ${t}`;return null===n?s:`${s} - ${JSON.stringify(n)}`}isLogLevelEnabled(e){const t=R.indexOf(this.logLevel);return R.indexOf(e)>=t}writeMessage(e,t,n){if(this.isLogLevelEnabled(e)){const o=this.formatMessage(e,t,n);s.appendFileSync(this.loggerFile,`${o}\n`,"utf8")}}logInfo(e,t=null){this.writeMessage(g.INFO,e,t)}logError(e,t=null){if(t instanceof Error){const n={message:t.message,stack:t.stack,name:t.name,...t.cause&&{cause:t.cause},...Object.getOwnPropertyNames(t).reduce((e,n)=>(["message","stack","name"].includes(n)||(e[n]=t[n]),e),{})};this.writeMessage(g.ERROR,e,n)}else this.writeMessage(g.ERROR,e,t)}logWarn(e,t=null){this.writeMessage(g.WARN,e,t)}logDebug(e,t=null){this.writeMessage(g.DEBUG,e,t)}}function T(e,t){return new m(e,t)}T("common","common");const y=a(import.meta.url),N=e.dirname(y),S=e.join(N,"..","claude-marketplace");function O(){return new Promise((e,t)=>{d("claude plugin marketplace list --json",(n,s,o)=>{if(n)t(n);else{o&&console.error(o);try{const t=s.trim()?JSON.parse(s):[];e(t)}catch(e){t(e)}}})})}!function(){const t=e.join(N,"package.json"),n=e.join(".","package.json");s.existsSync(t)?JSON.parse(o(t,"utf8")):JSON.parse(o(n,"utf8"))}(),e.join(n.homedir(),".claude","settings.local.json");const w=_();class f{constructor(){this.dbPath=w.db.path,this.db=null,this.transactionDepth=0}initialize(){const e=t(this.dbPath);return i(e)||r(e,{recursive:!0}),this.db=new l(this.dbPath),w.db.configs.forEach(e=>{this.db.pragma(e)}),this}getConnection(){return this.db||this.initialize(),this.db}beginTransaction(){return 0===this.transactionDepth&&this.getConnection().prepare("BEGIN").run(),this.transactionDepth++,this}commit(){return this.transactionDepth--,0===this.transactionDepth&&this.getConnection().prepare("COMMIT").run(),this}rollback(){return this.transactionDepth--,0===this.transactionDepth&&this.getConnection().prepare("ROLLBACK").run(),this}transaction(e){this.beginTransaction();try{const t=e(this.getConnection());return this.commit(),t}catch(e){throw this.rollback(),e}}close(){return this.db&&(this.db.close(),this.db=null),this}exists(){return i(this.dbPath)}getPath(){return this.dbPath}}let I=null;const k=["draft","suggested","verified"],b=["session_start","session_end","tool_use","user_prompt","pre_compact","notification","permission_request","stop","subagent_stop"],C={knowledge_item:`\n CREATE TABLE IF NOT EXISTS knowledge_item (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n\n -- Basic information\n title TEXT NOT NULL,\n summary TEXT NOT NULL,\n content TEXT NOT NULL,\n\n -- Classification dimensions\n scope TEXT NOT NULL CHECK(scope IN (${["personal","project","organization"].map(e=>`'${e}'`).join(", ")})),\n source_type TEXT NOT NULL CHECK(source_type IN (${["developer","architect","reviewer","ai"].map(e=>`'${e}'`).join(", ")})),\n knowledge_type TEXT NOT NULL CHECK(knowledge_type IN (${["code_pattern","tool_usage","architecture","config","pitfall","api_usage","exploration"].map(e=>`'${e}'`).join(", ")})),\n status TEXT NOT NULL DEFAULT 'draft' CHECK(status IN (${k.map(e=>`'${e}'`).join(", ")})),\n\n -- Association information\n repository_id INTEGER,\n session_id TEXT NOT NULL,\n\n -- Source tracking\n source_file TEXT,\n commit_hash TEXT,\n contributor TEXT,\n\n -- Timestamps\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n\n FOREIGN KEY (repository_id) REFERENCES repository(id)\n )\n `,repository:"\n CREATE TABLE IF NOT EXISTS repository (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n\n name TEXT NOT NULL,\n remote_url TEXT UNIQUE NOT NULL,\n local_path TEXT,\n\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n )\n ",session:"\n CREATE TABLE IF NOT EXISTS session (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n\n session_id TEXT UNIQUE NOT NULL,\n repository_id INTEGER,\n\n -- Session basic information\n working_directory TEXT NOT NULL,\n branch TEXT,\n username TEXT,\n\n -- Environment information (stored as JSON)\n env TEXT,\n\n -- Configuration information (stored as JSON)\n config TEXT,\n\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n\n FOREIGN KEY (repository_id) REFERENCES repository(id)\n )\n ",hook_event:"\n CREATE TABLE IF NOT EXISTS hook_event (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n\n session_id TEXT NOT NULL,\n\n -- Hook information\n name TEXT NOT NULL,\n input TEXT NOT NULL,\n output TEXT,\n\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n\n FOREIGN KEY (session_id) REFERENCES session(session_id)\n )\n ",sync_status:`\n CREATE TABLE IF NOT EXISTS sync_status (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n\n repository_id INTEGER,\n\n last_sync_at INTEGER,\n last_pull_at INTEGER,\n last_push_at INTEGER,\n\n remote_url TEXT,\n sync_protocol TEXT CHECK(sync_protocol IN (${["http","ftp","sftp"].map(e=>`'${e}'`).join(", ")})),\n\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n\n FOREIGN KEY (repository_id) REFERENCES repository(id)\n )\n `,knowledge_item_fts:"\n CREATE VIRTUAL TABLE IF NOT EXISTS knowledge_item_fts USING fts5(\n title, summary, content,\n content='knowledge_item',\n content_rowid='id',\n tokenize='trigram'\n )\n "},L={knowledge_item_fts_insert:"\n CREATE TRIGGER IF NOT EXISTS knowledge_item_fts_insert AFTER INSERT ON knowledge_item BEGIN\n INSERT INTO knowledge_item_fts(rowid, title, summary, content)\n VALUES (new.id, new.title, new.summary, new.content);\n END\n ",knowledge_item_fts_delete:"\n CREATE TRIGGER IF NOT EXISTS knowledge_item_fts_delete AFTER DELETE ON knowledge_item BEGIN\n INSERT INTO knowledge_item_fts(knowledge_item_fts, rowid, title, summary, content)\n VALUES('delete', old.id, old.title, old.summary, old.content);\n END\n ",knowledge_item_fts_update:"\n CREATE TRIGGER IF NOT EXISTS knowledge_item_fts_update AFTER UPDATE ON knowledge_item BEGIN\n INSERT INTO knowledge_item_fts(knowledge_item_fts, rowid, title, summary, content)\n VALUES('delete', old.id, old.title, old.summary, old.content);\n INSERT INTO knowledge_item_fts(rowid, title, summary, content)\n VALUES (new.id, new.title, new.summary, new.content);\n END\n "},D={idx_knowledge_scope:"CREATE INDEX IF NOT EXISTS idx_knowledge_scope ON knowledge_item(scope)",idx_knowledge_type:"CREATE INDEX IF NOT EXISTS idx_knowledge_type ON knowledge_item(knowledge_type)",idx_knowledge_status:"CREATE INDEX IF NOT EXISTS idx_knowledge_status ON knowledge_item(status)",idx_knowledge_repo:"CREATE INDEX IF NOT EXISTS idx_knowledge_repo ON knowledge_item(repository_id)",idx_knowledge_session:"CREATE INDEX IF NOT EXISTS idx_knowledge_session ON knowledge_item(session_id)",idx_session_repo:"CREATE INDEX IF NOT EXISTS idx_session_repo ON session(repository_id)",idx_session_id:"CREATE INDEX IF NOT EXISTS idx_session_id ON session(session_id)",idx_hook_event_session:"CREATE INDEX IF NOT EXISTS idx_hook_event_session ON hook_event(session_id)",idx_hook_event_type:"CREATE INDEX IF NOT EXISTS idx_hook_event_type ON hook_event(name)",idx_sync_repo:"CREATE INDEX IF NOT EXISTS idx_sync_repo ON sync_status(repository_id)"},F=T("knowledge-repository","knowledge-repository");class U{constructor(e){this.database=e,this.db=e.getConnection()}create(e){const t=Date.now(),n=this.db.prepare("\n INSERT INTO knowledge_item (\n title, summary, content,\n scope, source_type, knowledge_type, status,\n repository_id, session_id,\n source_file, commit_hash, contributor,\n created_at, updated_at\n ) VALUES (\n @title, @summary, @content,\n @scope, @source_type, @knowledge_type, @status,\n @repository_id, @session_id,\n @source_file, @commit_hash, @contributor,\n @created_at, @updated_at\n )\n ").run({...e,status:e.status||k.DRAFT,created_at:t,updated_at:t});return this.findById(n.lastInsertRowid)}findById(e){return this.db.prepare("SELECT * FROM knowledge_item WHERE id = ?").get(e)}findByRepository(e,t=null){return t?this.db.prepare("SELECT * FROM knowledge_item WHERE repository_id = ? AND scope = ? ORDER BY updated_at DESC").all(e,t):this.db.prepare("SELECT * FROM knowledge_item WHERE repository_id = ? ORDER BY updated_at DESC").all(e)}findByScope(e){return this.db.prepare("SELECT * FROM knowledge_item WHERE scope = ? ORDER BY updated_at DESC").all(e)}findByStatus(e){return this.db.prepare("SELECT * FROM knowledge_item WHERE status = ? ORDER BY updated_at DESC").all(e)}findByKnowledgeType(e){return this.db.prepare("SELECT * FROM knowledge_item WHERE knowledge_type = ? ORDER BY updated_at DESC").all(e)}findBySession(e){return this.db.prepare("SELECT * FROM knowledge_item WHERE session_id = ?").all(e)}findRelevant(e,t=5){return this.db.prepare("\n SELECT * FROM knowledge_item\n WHERE repository_id = ? OR scope = 'organization'\n ORDER BY\n CASE status\n WHEN 'verified' THEN 3\n WHEN 'suggested' THEN 2\n WHEN 'draft' THEN 1\n END DESC,\n updated_at DESC\n LIMIT ?\n ").all(e,t)}update(e,t){const n=Date.now(),s=Object.keys(t).map(e=>`${e} = @${e}`).join(", ");return this.db.prepare(`\n UPDATE knowledge_item\n SET ${s}, updated_at = @updated_at\n WHERE id = @id\n `).run({...t,id:e,updated_at:n}),this.findById(e)}updateStatus(e,t){return this.update(e,{status:t})}delete(e){return this.db.prepare("DELETE FROM knowledge_item WHERE id = ?").run(e)}count(e={}){let t="SELECT COUNT(*) as count FROM knowledge_item";const n=[],s=[];return e.scope&&(n.push("scope = ?"),s.push(e.scope)),e.status&&(n.push("status = ?"),s.push(e.status)),e.knowledge_type&&(n.push("knowledge_type = ?"),s.push(e.knowledge_type)),e.repository_id&&(n.push("repository_id = ?"),s.push(e.repository_id)),n.length>0&&(t+=` WHERE ${n.join(" AND ")}`),this.db.prepare(t).get(...s).count}findAll(e=100,t=0){return this.db.prepare("SELECT * FROM knowledge_item ORDER BY updated_at DESC LIMIT ? OFFSET ?").all(e,t)}search(e,t=10){const n=Array.isArray(e)?e.map(e=>`"${e}"`).join(" OR "):`"${e}"`;return F.logDebug("Searching knowledge items with query: ",n),this.db.prepare("\n SELECT ki.*\n FROM knowledge_item ki\n JOIN knowledge_item_fts fts ON fts.rowid = ki.id\n WHERE knowledge_item_fts MATCH ?\n ORDER BY rank\n LIMIT ?\n ").all(n,t)}}class B{constructor(e){this.database=e,this.db=e.getConnection()}create(e){const t=Date.now(),n=this.db.prepare("\n INSERT INTO repository (\n name, remote_url, local_path,\n created_at, updated_at\n ) VALUES (\n @name, @remote_url, @local_path,\n @created_at, @updated_at\n )\n ").run({...e,created_at:t,updated_at:t});return this.findById(n.lastInsertRowid)}findById(e){return this.db.prepare("SELECT * FROM repository WHERE id = ?").get(e)}findByRemoteUrl(e){return this.db.prepare("SELECT * FROM repository WHERE remote_url = ?").get(e)}findByPath(e){return this.db.prepare("SELECT * FROM repository WHERE local_path = ?").get(e)}findByName(e){return this.db.prepare("SELECT * FROM repository WHERE name = ?").get(e)}getOrCreate(e,t,n=null){let s=this.findByRemoteUrl(e);return s?n&&s.local_path!==n&&(s=this.update(s.id,{local_path:n})):s=this.create({name:t,remote_url:e,local_path:n}),s}update(e,t){const n=Date.now(),s=Object.keys(t).map(e=>`${e} = @${e}`).join(", ");return this.db.prepare(`\n UPDATE repository\n SET ${s}, updated_at = @updated_at\n WHERE id = @id\n `).run({...t,id:e,updated_at:n}),this.findById(e)}delete(e){return this.db.prepare("DELETE FROM repository WHERE id = ?").run(e)}findAll(){return this.db.prepare("SELECT * FROM repository ORDER BY updated_at DESC").all()}count(){return this.db.prepare("SELECT COUNT(*) as count FROM repository").get().count}}class v{constructor(e){this.database=e,this.db=e.getConnection()}create(e){const t=Date.now(),n=this.db.prepare("\n INSERT INTO sync_status (\n repository_id,\n last_sync_at, last_pull_at, last_push_at,\n remote_url, sync_protocol,\n created_at, updated_at\n ) VALUES (\n @repository_id,\n @last_sync_at, @last_pull_at, @last_push_at,\n @remote_url, @sync_protocol,\n @created_at, @updated_at\n )\n ").run({repository_id:e.repository_id||null,last_sync_at:e.last_sync_at||null,last_pull_at:e.last_pull_at||null,last_push_at:e.last_push_at||null,remote_url:e.remote_url||null,sync_protocol:e.sync_protocol||null,created_at:t,updated_at:t});return this.findById(n.lastInsertRowid)}findById(e){return this.db.prepare("SELECT * FROM sync_status WHERE id = ?").get(e)}findByRepository(e){return this.db.prepare("SELECT * FROM sync_status WHERE repository_id = ?").get(e)}findGlobal(){return this.db.prepare("SELECT * FROM sync_status WHERE repository_id IS NULL").get()}getOrCreate(e,t={}){let n=e?this.findByRepository(e):this.findGlobal();return n||(n=this.create({repository_id:e,...t})),n}update(e,t){const n=Date.now(),s=Object.keys(t).map(e=>`${e} = @${e}`).join(", ");return this.db.prepare(`\n UPDATE sync_status\n SET ${s}, updated_at = @updated_at\n WHERE id = @id\n `).run({...t,id:e,updated_at:n}),this.findById(e)}recordPull(e){const t=this.getOrCreate(e),n=Date.now();return this.update(t.id,{last_pull_at:n,last_sync_at:n})}recordPush(e){const t=this.getOrCreate(e),n=Date.now();return this.update(t.id,{last_push_at:n,last_sync_at:n})}recordSync(e){const t=this.getOrCreate(e),n=Date.now();return this.update(t.id,{last_pull_at:n,last_push_at:n,last_sync_at:n})}updateConfig(e,t){const n=this.getOrCreate(e);return this.update(n.id,{remote_url:t.remote_url,sync_protocol:t.sync_protocol})}delete(e){return this.db.prepare("DELETE FROM sync_status WHERE id = ?").run(e)}findAll(){return this.db.prepare("SELECT * FROM sync_status ORDER BY updated_at DESC").all()}needsSync(e,t=36e5){const n=e?this.findByRepository(e):this.findGlobal();return!n||!n.last_sync_at||Date.now()-n.last_sync_at>t}getStats(){return{total:this.db.prepare("SELECT COUNT(*) as count FROM sync_status").get().count,with_remote:this.db.prepare("SELECT COUNT(*) as count FROM sync_status WHERE remote_url IS NOT NULL").get().count,recent_syncs_24h:this.db.prepare("\n SELECT COUNT(*) as count FROM sync_status\n WHERE last_sync_at > ?\n ").get(Date.now()-864e5).count}}}class A{constructor(e){this.database=e,this.db=e.getConnection()}createSession(e){const t=this.findSessionBySessionId(e.session_id);if(t)return t;const n=Date.now(),s=e.config||_();return this.db.prepare("\n INSERT INTO session (\n session_id, repository_id, working_directory, branch, username, env, config,\n created_at, updated_at\n ) VALUES (\n @session_id, @repository_id, @working_directory, @branch, @username, @env, @config,\n @created_at, @updated_at\n )\n ").run({session_id:e.session_id,repository_id:e.repository_id||null,working_directory:e.working_directory,branch:e.branch||null,username:e.username||null,env:e.env?JSON.stringify(e.env):null,config:JSON.stringify(s),created_at:n,updated_at:n}),this.findSessionBySessionId(e.session_id)}findSessionBySessionId(e){const t=this.db.prepare("SELECT * FROM session WHERE session_id = ?").get(e);return this._parseSessionData(t)}_parseSessionData(e){return e?{...e,env:e.env?JSON.parse(e.env):null,config:e.config?JSON.parse(e.config):null}:null}updateSessionConfig(e,t){const n=Date.now();return this.db.prepare("\n UPDATE session\n SET config = ?, updated_at = ?\n WHERE session_id = ?\n ").run(JSON.stringify(t),n,e),this.findSessionBySessionId(e)}create(e){const t=Date.now(),n=this.db.prepare("\n INSERT INTO hook_event (\n session_id,\n name, input, output,\n created_at, updated_at\n ) VALUES (\n @session_id,\n @name, @input, @output,\n @created_at, @updated_at\n )\n ").run({session_id:e.session_id,name:e.name,input:"string"==typeof e.input?e.input:JSON.stringify(e.input),output:void 0===e.output||null===e.output?null:"string"==typeof e.output?e.output:JSON.stringify(e.output),created_at:t,updated_at:t});return this.findById(n.lastInsertRowid)}updateOutput(e,t){const n=Date.now(),s=this.db.prepare("\n UPDATE hook_event\n SET output = ?, updated_at = ?\n WHERE id = ?\n "),o="string"==typeof t?t:JSON.stringify(t);return s.run(o,n,e),this.findById(e)}findById(e){const t=this.db.prepare("SELECT * FROM hook_event WHERE id = ?").get(e);return t&&(t.input&&(t.input=JSON.parse(t.input)),t.output&&(t.output=JSON.parse(t.output))),t}findBySession(e){return this.db.prepare("SELECT * FROM hook_event WHERE session_id = ? ORDER BY created_at ASC").all(e).map(e=>({...e,input:e.input?JSON.parse(e.input):null,output:e.output?JSON.parse(e.output):null}))}findBySessionAndType(e,t){return this.db.prepare("SELECT * FROM hook_event WHERE session_id = ? AND name = ? ORDER BY created_at ASC").all(e,t).map(e=>({...e,input:e.input?JSON.parse(e.input):null,output:e.output?JSON.parse(e.output):null}))}findByRepository(e,t=100){return this.db.prepare("\n SELECT he.* FROM hook_event he\n JOIN session s ON he.session_id = s.session_id\n WHERE s.repository_id = ?\n ORDER BY he.created_at DESC\n LIMIT ?\n ").all(e,t).map(e=>({...e,input:e.input?JSON.parse(e.input):null,output:e.output?JSON.parse(e.output):null}))}findByHookType(e,t=100){return this.db.prepare("SELECT * FROM hook_event WHERE name = ? ORDER BY created_at DESC LIMIT ?").all(e,t).map(e=>({...e,input:e.input?JSON.parse(e.input):null,output:e.output?JSON.parse(e.output):null}))}findLatestSessionStart(e){const t=this.db.prepare("\n SELECT * FROM hook_event\n WHERE session_id = ? AND name = ?\n ORDER BY created_at DESC\n LIMIT 1\n ").get(e,b.SESSION_START);return t&&(t.input&&(t.input=JSON.parse(t.input)),t.output&&(t.output=JSON.parse(t.output))),t}hasSessionEnded(e){return this.db.prepare("\n SELECT COUNT(*) as count FROM hook_event\n WHERE session_id = ? AND name = ?\n ").get(e,b.SESSION_END).count>0}getSessionSummary(e){const t=this.findBySession(e),n=this._parseSessionData(this.db.prepare("SELECT * FROM session WHERE session_id = ?").get(e)),s={session_id:e,total_events:t.length,hook_types:{},start_time:null,end_time:null,duration:null,repository_id:n?.repository_id||null,branch:n?.branch||null,config:n?.config||null,created_at:n?.created_at||null,updated_at:n?.updated_at||null};return t.forEach(e=>{s.hook_types[e.name]=(s.hook_types[e.name]||0)+1,e.name!==b.SESSION_START||s.start_time||(s.start_time=e.created_at),e.name!==b.SESSION_END||s.end_time||(s.end_time=e.created_at)}),s.start_time&&s.end_time&&(s.duration=s.end_time-s.start_time),s}delete(e){return this.db.prepare("DELETE FROM hook_event WHERE id = ?").run(e)}deleteBySession(e){return this.db.prepare("DELETE FROM hook_event WHERE session_id = ?").run(e)}getRecentSessions(e=10){return this.db.prepare("\n SELECT DISTINCT session_id, MAX(created_at) as last_activity\n FROM hook_event\n GROUP BY session_id\n ORDER BY last_activity DESC\n LIMIT ?\n ").all(e)}count(e={}){let t="SELECT COUNT(*) as count FROM hook_event";const n=[],s=[];return e.session_id&&(n.push("session_id = ?"),s.push(e.session_id)),e.name&&(n.push("name = ?"),s.push(e.name)),n.length>0&&(t+=` WHERE ${n.join(" AND ")}`),this.db.prepare(t).get(...s).count}}class M{constructor(e=null){this.repoPath=e||p(),this.git=u(this.repoPath)}getCurrentBranch(){return this.git.branchLocal().then(e=>e.current).catch(e=>{throw new Error(`Failed to get current branch: ${e.message}`)})}getRemoteUrl(e="origin"){return this.git.getRemotes(!0).then(t=>{const n=t.find(t=>t.name===e);if(!n)throw new Error(`Remote '${e}' not found`);return n.refs.fetch||n.refs.push}).catch(e=>{throw new Error(`Failed to get remote URL: ${e.message}`)})}getMainBranch(){return this.git.branchLocal().then(e=>{const t=e.all;return t.includes("main")?"main":t.includes("master")?"master":t[0]||"main"}).catch(()=>"main")}isOnMainBranch(){return this.getCurrentBranch().then(e=>this.getMainBranch().then(t=>e===t))}getCurrentCommitHash(){return this.git.revparse(["HEAD"]).then(e=>e.trim()).catch(e=>{throw new Error(`Failed to get commit hash: ${e.message}`)})}getCommitAuthor(e="HEAD"){return this.git.show(["-s","--format=%an <%ae>",e]).then(e=>e.trim()).catch(e=>{throw new Error(`Failed to get commit author: ${e.message}`)})}isBranchMergedToMain(e){return this.getMainBranch().then(t=>this.git.branch(["--merged",t]).then(t=>t.all.map(e=>e.replace("*","").trim()).includes(e))).catch(e=>(console.error(`Failed to check merge status: ${e.message}`),!1))}getRepoRoot(){return this.git.revparse(["--show-toplevel"]).then(e=>e.trim()).catch(e=>{throw new Error(`Failed to get repo root: ${e.message}`)})}isGitRepository(){return this.git.checkIsRepo().catch(()=>!1)}getStatus(){return this.git.status().catch(e=>{throw new Error(`Failed to get git status: ${e.message}`)})}getAllBranches(){return this.git.branchLocal().then(e=>e.all).catch(e=>{throw new Error(`Failed to get branches: ${e.message}`)})}getRepositoryName(){return this.getRemoteUrl().then(e=>{const t=e.match(/([^/:]+?)(?:\.git)?$/);return t?t[1]:"unknown"}).catch(()=>"unknown")}getUserName(){return this.git.getConfig("user.name").then(e=>e.value||process.env.USER||process.env.USERNAME||"unknown_user").catch(()=>"unknown")}getUserInfo(){return Promise.all([this.git.getConfig("user.name").catch(()=>({value:null})),this.git.getConfig("user.email").catch(()=>({value:null}))]).then(([e,t])=>({name:e.value||"unknown",email:t.value||"unknown"}))}}class ${constructor(e,t){this.gitUtils=e,this.repositoryRepo=t}getCurrentRepository(){return Promise.all([this.gitUtils.getRemoteUrl(),this.gitUtils.getRepositoryName(),this.gitUtils.getRepoRoot()]).then(([e,t,n])=>this.getOrCreateRepository(e,t,n)).catch(e=>{throw new Error(`Failed to get current repository: ${e.message}`)})}getOrCreateRepository(e,t,n=null){return Promise.resolve(this.repositoryRepo.getOrCreate(e,t,n))}getRepository(e){return Promise.resolve(this.repositoryRepo.findById(e))}getRepositoryByUrl(e){return Promise.resolve(this.repositoryRepo.findByRemoteUrl(e))}getAllRepositories(){return Promise.resolve(this.repositoryRepo.findAll())}updateRepository(e,t){return Promise.resolve(this.repositoryRepo.update(e,t))}deleteRepository(e){return Promise.resolve(this.repositoryRepo.delete(e))}getRepositoryStats(e){return Promise.resolve({total_repositories:this.repositoryRepo.count()})}}class H{constructor(e){this.gitUtils=e}validateBranchForSession(){return this.gitUtils.getCurrentBranch().then(e=>this.gitUtils.getMainBranch().then(t=>e===t?{valid:!1,branch:e,message:`Cannot start session on main branch '${e}'. Please create a feature branch first.\n\nExample:\n git checkout -b feature/my-feature\n claude "your prompt here"`}:{valid:!0,branch:e,message:`Session validated on branch '${e}'`})).catch(e=>(console.warn(`Branch validation warning: ${e.message}`),{valid:!0,branch:"unknown",message:`Branch validation skipped: ${e.message}`}))}isMainBranch(){return this.gitUtils.isOnMainBranch().catch(()=>!1)}}const X=new class{constructor(){this.database=(I||(I=new f),I),this.initialized=!1}initialize(){this.initialized||(this.database.initialize(),this.initialized=!0)}async prepare(){this.initialize(),function(e){Object.values(C).forEach(t=>{e.prepare(t).run()}),Object.values(D).forEach(t=>{e.prepare(t).run()}),Object.values(L).forEach(t=>{e.prepare(t).run()});const t=e.prepare("SELECT COUNT(*) as count FROM knowledge_item_fts").get(),n=e.prepare("SELECT COUNT(*) as count FROM knowledge_item").get();n.count>0&&0===t.count&&(console.log("Populating FTS index from existing data..."),e.prepare("\n INSERT INTO knowledge_item_fts(rowid, title, summary, content)\n SELECT id, title, summary, content FROM knowledge_item\n ").run(),console.log(`FTS index populated with ${n.count} items`))}(this.database.getConnection())}getConnection(){return this.initialize(),this.database.getConnection()}close(){this.database&&(this.database.close(),this.initialized=!1)}},G=new class{constructor(e){this.dbService=e,this._repositoryRepo=null,this._syncRepo=null}get repositoryRepo(){return this._repositoryRepo||(this._repositoryRepo=new B(this.dbService.database)),this._repositoryRepo}get syncRepo(){return this._syncRepo||(this._syncRepo=new v(this.dbService.database)),this._syncRepo}}(X),W=new class{constructor(e){this.dbService=e,this._knowledgeRepo=null}get knowledgeRepo(){return this._knowledgeRepo||(this._knowledgeRepo=new U(this.dbService.database)),this._knowledgeRepo}}(X),P=new class{constructor(e){this.dbService=e,this._sessionRepo=null}get sessionRepo(){return this._sessionRepo||(this._sessionRepo=new A(this.dbService.database)),this._sessionRepo}}(X),j=new class{constructor(e){this.gitUtils=new M,this.repositoryManager=new $(this.gitUtils,e),this.branchValidator=new H(this.gitUtils)}}(G.repositoryRepo);async function x(){O().then(e=>e.find(e=>"knowledge-bank"===e.name)).then(async e=>{e||await new Promise((e,t)=>{d(`claude plugin marketplace add ${S}`,(n,s,o)=>{n?t(n):(o&&console.error(o),console.log(s),e())})}),await new Promise((e,t)=>{d("claude plugin install core@knowledge-bank",(n,s,o)=>{n?t(n):(o&&console.error(o),console.log(s),e())})})}).then(async()=>{await async function(){await X.prepare(),X.initialize()}()}).catch(e=>{console.error("Error during installation:",e)})}async function Y(){O().then(e=>e.find(e=>"knowledge-bank"===e.name)).then(async e=>{e?(await new Promise((e,t)=>{d("claude plugin uninstall core@knowledge-bank",(n,s,o)=>{n?t(n):(o&&console.error(o),console.log(s),e())})}),await new Promise((e,t)=>{d("claude plugin marketplace remove knowledge-bank",(n,s,o)=>{n?t(n):(o&&console.error(o),console.log(s),e())})})):console.log("knowledge-bank plugin is not installed.")}).catch(e=>{console.error("Error during uninstallation:",e)})}async function J(){console.log("📚 Knowledge Bank Status\n");const e=X.database.getPath(),t=X.database.exists();if(console.log(`Database: ${e}`),console.log(`Status: ${t?"✓ Connected":"✗ Not found"}\n`),await j.gitUtils.isGitRepository()){const e=await j.repositoryManager.getCurrentRepository(),t=await j.gitUtils.getCurrentBranch();console.log("Current Repository:"),console.log(` Name: ${e.name}`),console.log(` Branch: ${t}`),console.log(` Remote: ${e.remote_url}\n`);const n={total:W.knowledgeRepo.count({repository_id:e.id}),by_status:{draft:W.knowledgeRepo.count({repository_id:e.id,status:"draft"}),suggested:W.knowledgeRepo.count({repository_id:e.id,status:"suggested"}),verified:W.knowledgeRepo.count({repository_id:e.id,status:"verified"})},by_scope:{personal:W.knowledgeRepo.count({repository_id:e.id,scope:"personal"}),project:W.knowledgeRepo.count({repository_id:e.id,scope:"project"}),organization:W.knowledgeRepo.count({repository_id:e.id,scope:"organization"})}};console.log("Knowledge Statistics:"),console.log(` Total: ${n.total}`),console.log(" By Status:"),console.log(` - Draft: ${n.by_status.draft}`),console.log(` - Suggested: ${n.by_status.suggested}`),console.log(` - Verified: ${n.by_status.verified}`),console.log(" By Scope:"),console.log(` - Personal: ${n.by_scope.personal}`),console.log(` - Project: ${n.by_scope.project}`),console.log(` - Organization: ${n.by_scope.organization}\n`);const s=P.sessionRepo.getRecentSessions(5);console.log(`Recent Sessions: ${s.length}`),s.length>0&&s.forEach((e,t)=>{const n=new Date(e.updated_at).toLocaleString();console.log(` ${t+1}. ${e.session_id.substring(0,8)}... (${n})`)})}else{console.log("Not in a Git repository\n");const e=W.knowledgeRepo.count({});console.log("Global Knowledge Statistics:"),console.log(` Total: ${e}`)}}G.gitService=j;const z=T("knowledge-sync");async function K(e){const t=e?.force||!1;z.logInfo(`Starting knowledge synchronization${t?" (forced)":""}...`),z.logInfo("✓ Synchronization complete")}class V extends Error{constructor(e,t=1){super(e),this.name="CLIError",this.exitCode=t}}export{V as CLIError,x as install,J as knowledgeStatus,K as knowledgeSync,Y as uninstall};
1
+ import e,{dirname as t}from"path";import n from"os";import o,{readFileSync as s,existsSync as i,mkdirSync as r}from"fs";import{fileURLToPath as a}from"url";import{exec as d}from"child_process";import l from"better-sqlite3";import p from"simple-git";import{cwd as u}from"process";const c={logging:{level:"DEBUG"},db:{path:e.join(n.homedir(),".knowledge-bank","knowledge.db"),configs:["journal_mode = WAL","foreign_keys = ON"]},tmp:e.join(n.homedir(),".knowledge-bank","tmp")};let E=null;function h(){if(null===E){const t=process.env.KNOWLEDGE_CONF_DIR||e.join(n.homedir(),".knowledge-bank"),s=e.join(t,"config.json");E={...c,...o.existsSync(s)?JSON.parse(o.readFileSync(s,"utf-8")):{}}}return E}const g=h(),_={DEBUG:"DEBUG",INFO:"INFO",WARN:"WARN",ERROR:"ERROR"},m=Object.values(_);class R{constructor(t,s){this.loggerName=s;const i=g.logging.path||e.join(n.homedir(),".knowledge-bank","logs");o.mkdirSync(i,{recursive:!0}),this.loggerFile=e.join(i,`${t}.log`),this.logLevel=g.logging.level.toUpperCase()||_.INFO}formatMessage(e,t,n=null){const o=`${(new Date).toISOString().replace("T","-").split(".")[0]} ${this.loggerName} ${e}: ${t}`;return null===n?o:`${o} - ${JSON.stringify(n)}`}isLogLevelEnabled(e){const t=m.indexOf(this.logLevel);return m.indexOf(e)>=t}writeMessage(e,t,n){if(this.isLogLevelEnabled(e)){const s=this.formatMessage(e,t,n);o.appendFileSync(this.loggerFile,`${s}\n`,"utf8")}}logInfo(e,t=null){this.writeMessage(_.INFO,e,t)}logError(e,t=null){if(t instanceof Error){const n={message:t.message,stack:t.stack,name:t.name,...t.cause&&{cause:t.cause},...Object.getOwnPropertyNames(t).reduce((e,n)=>(["message","stack","name"].includes(n)||(e[n]=t[n]),e),{})};this.writeMessage(_.ERROR,e,n)}else this.writeMessage(_.ERROR,e,t)}logWarn(e,t=null){this.writeMessage(_.WARN,e,t)}logDebug(e,t=null){this.writeMessage(_.DEBUG,e,t)}}function T(e,t){return new R(e,t)}T("common","common");const N=a(import.meta.url),S=e.dirname(N),y=e.join(S,"..","claude-marketplace");function w(){return new Promise((e,t)=>{d("claude plugin marketplace list --json",(n,o,s)=>{if(n)t(n);else{s&&console.error(s);try{const t=o.trim()?JSON.parse(o):[];e(t)}catch(e){t(e)}}})})}!function(){const t=e.join(S,"package.json"),n=e.join(".","package.json");o.existsSync(t)?JSON.parse(s(t,"utf8")):JSON.parse(s(n,"utf8"))}(),e.join(n.homedir(),".claude","settings.local.json");const O=h();class f{constructor(){this.dbPath=O.db.path,this.db=null,this.transactionDepth=0}initialize(){const e=t(this.dbPath);return i(e)||r(e,{recursive:!0}),this.db=new l(this.dbPath),O.db.configs.forEach(e=>{this.db.pragma(e)}),this}getConnection(){return this.db||this.initialize(),this.db}beginTransaction(){return 0===this.transactionDepth&&this.getConnection().prepare("BEGIN").run(),this.transactionDepth++,this}commit(){return this.transactionDepth--,0===this.transactionDepth&&this.getConnection().prepare("COMMIT").run(),this}rollback(){return this.transactionDepth--,0===this.transactionDepth&&this.getConnection().prepare("ROLLBACK").run(),this}transaction(e){this.beginTransaction();try{const t=e(this.getConnection());return this.commit(),t}catch(e){throw this.rollback(),e}}close(){return this.db&&(this.db.close(),this.db=null),this}exists(){return i(this.dbPath)}getPath(){return this.dbPath}}let k=null;const I=["draft","suggested","verified"],b=["session_start","session_end","tool_use","user_prompt","pre_compact","notification","permission_request","stop","subagent_stop"],C={knowledge_item:`\n CREATE TABLE IF NOT EXISTS knowledge_item (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n\n -- Basic information\n title TEXT NOT NULL,\n summary TEXT NOT NULL,\n content TEXT NOT NULL,\n\n -- Classification dimensions\n scope TEXT NOT NULL CHECK(scope IN (${["personal","project","organization"].map(e=>`'${e}'`).join(", ")})),\n source_type TEXT NOT NULL CHECK(source_type IN (${["developer","architect","reviewer","ai"].map(e=>`'${e}'`).join(", ")})),\n knowledge_type TEXT NOT NULL CHECK(knowledge_type IN (${["code_pattern","tool_usage","architecture","config","pitfall","api_usage","exploration"].map(e=>`'${e}'`).join(", ")})),\n status TEXT NOT NULL DEFAULT 'draft' CHECK(status IN (${I.map(e=>`'${e}'`).join(", ")})),\n\n -- Association information\n repository_id INTEGER,\n session_id TEXT NOT NULL,\n\n -- Source tracking\n source_file TEXT,\n commit_hash TEXT,\n contributor TEXT,\n\n -- Timestamps\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n\n FOREIGN KEY (repository_id) REFERENCES repository(id)\n )\n `,repository:"\n CREATE TABLE IF NOT EXISTS repository (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n\n name TEXT NOT NULL,\n remote_url TEXT UNIQUE NOT NULL,\n local_path TEXT,\n\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n )\n ",session:"\n CREATE TABLE IF NOT EXISTS session (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n\n session_id TEXT UNIQUE NOT NULL,\n repository_id INTEGER,\n\n -- Session basic information\n working_directory TEXT NOT NULL,\n branch TEXT,\n username TEXT,\n\n -- Environment information (stored as JSON)\n env TEXT,\n\n -- Configuration information (stored as JSON)\n config TEXT,\n\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n\n FOREIGN KEY (repository_id) REFERENCES repository(id)\n )\n ",hook_event:"\n CREATE TABLE IF NOT EXISTS hook_event (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n\n session_id TEXT NOT NULL,\n\n -- Hook information\n name TEXT NOT NULL,\n input TEXT NOT NULL,\n output TEXT,\n\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n\n FOREIGN KEY (session_id) REFERENCES session(session_id)\n )\n ",knowledge_item_fts:"\n CREATE VIRTUAL TABLE IF NOT EXISTS knowledge_item_fts USING fts5(\n title, summary, content,\n content='knowledge_item',\n content_rowid='id',\n tokenize='trigram'\n )\n "},L={knowledge_item_fts_insert:"\n CREATE TRIGGER IF NOT EXISTS knowledge_item_fts_insert AFTER INSERT ON knowledge_item BEGIN\n INSERT INTO knowledge_item_fts(rowid, title, summary, content)\n VALUES (new.id, new.title, new.summary, new.content);\n END\n ",knowledge_item_fts_delete:"\n CREATE TRIGGER IF NOT EXISTS knowledge_item_fts_delete AFTER DELETE ON knowledge_item BEGIN\n INSERT INTO knowledge_item_fts(knowledge_item_fts, rowid, title, summary, content)\n VALUES('delete', old.id, old.title, old.summary, old.content);\n END\n ",knowledge_item_fts_update:"\n CREATE TRIGGER IF NOT EXISTS knowledge_item_fts_update AFTER UPDATE ON knowledge_item BEGIN\n INSERT INTO knowledge_item_fts(knowledge_item_fts, rowid, title, summary, content)\n VALUES('delete', old.id, old.title, old.summary, old.content);\n INSERT INTO knowledge_item_fts(rowid, title, summary, content)\n VALUES (new.id, new.title, new.summary, new.content);\n END\n "},D={idx_knowledge_scope:"CREATE INDEX IF NOT EXISTS idx_knowledge_scope ON knowledge_item(scope)",idx_knowledge_type:"CREATE INDEX IF NOT EXISTS idx_knowledge_type ON knowledge_item(knowledge_type)",idx_knowledge_status:"CREATE INDEX IF NOT EXISTS idx_knowledge_status ON knowledge_item(status)",idx_knowledge_repo:"CREATE INDEX IF NOT EXISTS idx_knowledge_repo ON knowledge_item(repository_id)",idx_knowledge_session:"CREATE INDEX IF NOT EXISTS idx_knowledge_session ON knowledge_item(session_id)",idx_session_repo:"CREATE INDEX IF NOT EXISTS idx_session_repo ON session(repository_id)",idx_session_id:"CREATE INDEX IF NOT EXISTS idx_session_id ON session(session_id)",idx_hook_event_session:"CREATE INDEX IF NOT EXISTS idx_hook_event_session ON hook_event(session_id)",idx_hook_event_type:"CREATE INDEX IF NOT EXISTS idx_hook_event_type ON hook_event(name)"},v=T("knowledge-repository","knowledge-repository");class F{constructor(e){this.database=e,this.db=e.getConnection()}create(e){const t=Date.now(),n=this.db.prepare("\n INSERT INTO knowledge_item (\n title, summary, content,\n scope, source_type, knowledge_type, status,\n repository_id, session_id,\n source_file, commit_hash, contributor,\n created_at, updated_at\n ) VALUES (\n @title, @summary, @content,\n @scope, @source_type, @knowledge_type, @status,\n @repository_id, @session_id,\n @source_file, @commit_hash, @contributor,\n @created_at, @updated_at\n )\n ").run({...e,status:e.status||I.DRAFT,created_at:t,updated_at:t});return this.findById(n.lastInsertRowid)}findById(e){return this.db.prepare("SELECT * FROM knowledge_item WHERE id = ?").get(e)}findByRepository(e,t=null){return t?this.db.prepare("SELECT * FROM knowledge_item WHERE repository_id = ? AND scope = ? ORDER BY updated_at DESC").all(e,t):this.db.prepare("SELECT * FROM knowledge_item WHERE repository_id = ? ORDER BY updated_at DESC").all(e)}findByScope(e){return this.db.prepare("SELECT * FROM knowledge_item WHERE scope = ? ORDER BY updated_at DESC").all(e)}findByStatus(e){return this.db.prepare("SELECT * FROM knowledge_item WHERE status = ? ORDER BY updated_at DESC").all(e)}findByKnowledgeType(e){return this.db.prepare("SELECT * FROM knowledge_item WHERE knowledge_type = ? ORDER BY updated_at DESC").all(e)}findBySession(e){return this.db.prepare("SELECT * FROM knowledge_item WHERE session_id = ?").all(e)}findRelevant(e,t=5){return this.db.prepare("\n SELECT * FROM knowledge_item\n WHERE repository_id = ? OR scope = 'organization'\n ORDER BY\n CASE status\n WHEN 'verified' THEN 3\n WHEN 'suggested' THEN 2\n WHEN 'draft' THEN 1\n END DESC,\n updated_at DESC\n LIMIT ?\n ").all(e,t)}update(e,t){const n=Date.now(),o=Object.keys(t).map(e=>`${e} = @${e}`).join(", ");return this.db.prepare(`\n UPDATE knowledge_item\n SET ${o}, updated_at = @updated_at\n WHERE id = @id\n `).run({...t,id:e,updated_at:n}),this.findById(e)}updateStatus(e,t){return this.update(e,{status:t})}delete(e){return this.db.prepare("DELETE FROM knowledge_item WHERE id = ?").run(e)}count(e={}){let t="SELECT COUNT(*) as count FROM knowledge_item";const n=[],o=[];return e.scope&&(n.push("scope = ?"),o.push(e.scope)),e.status&&(n.push("status = ?"),o.push(e.status)),e.knowledge_type&&(n.push("knowledge_type = ?"),o.push(e.knowledge_type)),e.repository_id&&(n.push("repository_id = ?"),o.push(e.repository_id)),n.length>0&&(t+=` WHERE ${n.join(" AND ")}`),this.db.prepare(t).get(...o).count}findAll(e=100,t=0){return this.db.prepare("SELECT * FROM knowledge_item ORDER BY updated_at DESC LIMIT ? OFFSET ?").all(e,t)}search(e,t=10){const n=Array.isArray(e)?e.map(e=>`"${e}"`).join(" OR "):`"${e}"`;return v.logDebug("Searching knowledge items with query: ",n),this.db.prepare("\n SELECT ki.*\n FROM knowledge_item ki\n JOIN knowledge_item_fts fts ON fts.rowid = ki.id\n WHERE knowledge_item_fts MATCH ?\n ORDER BY rank\n LIMIT ?\n ").all(n,t)}}class U{constructor(e){this.database=e,this.db=e.getConnection()}create(e){const t=Date.now(),n=this.db.prepare("\n INSERT INTO repository (\n name, remote_url, local_path,\n created_at, updated_at\n ) VALUES (\n @name, @remote_url, @local_path,\n @created_at, @updated_at\n )\n ").run({...e,created_at:t,updated_at:t});return this.findById(n.lastInsertRowid)}findById(e){return this.db.prepare("SELECT * FROM repository WHERE id = ?").get(e)}findByRemoteUrl(e){return this.db.prepare("SELECT * FROM repository WHERE remote_url = ?").get(e)}findByPath(e){return this.db.prepare("SELECT * FROM repository WHERE local_path = ?").get(e)}findByName(e){return this.db.prepare("SELECT * FROM repository WHERE name = ?").get(e)}getOrCreate(e,t,n=null){let o=this.findByRemoteUrl(e);return o?n&&o.local_path!==n&&(o=this.update(o.id,{local_path:n})):o=this.create({name:t,remote_url:e,local_path:n}),o}update(e,t){const n=Date.now(),o=Object.keys(t).map(e=>`${e} = @${e}`).join(", ");return this.db.prepare(`\n UPDATE repository\n SET ${o}, updated_at = @updated_at\n WHERE id = @id\n `).run({...t,id:e,updated_at:n}),this.findById(e)}delete(e){return this.db.prepare("DELETE FROM repository WHERE id = ?").run(e)}findAll(){return this.db.prepare("SELECT * FROM repository ORDER BY updated_at DESC").all()}count(){return this.db.prepare("SELECT COUNT(*) as count FROM repository").get().count}}class B{constructor(e){this.database=e,this.db=e.getConnection()}createSession(e){const t=this.findSessionBySessionId(e.session_id);if(t)return t;const n=Date.now(),o=e.config||h();return this.db.prepare("\n INSERT INTO session (\n session_id, repository_id, working_directory, branch, username, env, config,\n created_at, updated_at\n ) VALUES (\n @session_id, @repository_id, @working_directory, @branch, @username, @env, @config,\n @created_at, @updated_at\n )\n ").run({session_id:e.session_id,repository_id:e.repository_id||null,working_directory:e.working_directory,branch:e.branch||null,username:e.username||null,env:e.env?JSON.stringify(e.env):null,config:JSON.stringify(o),created_at:n,updated_at:n}),this.findSessionBySessionId(e.session_id)}findSessionBySessionId(e){const t=this.db.prepare("SELECT * FROM session WHERE session_id = ?").get(e);return this._parseSessionData(t)}_parseSessionData(e){return e?{...e,env:e.env?JSON.parse(e.env):null,config:e.config?JSON.parse(e.config):null}:null}updateSessionConfig(e,t){const n=Date.now();return this.db.prepare("\n UPDATE session\n SET config = ?, updated_at = ?\n WHERE session_id = ?\n ").run(JSON.stringify(t),n,e),this.findSessionBySessionId(e)}create(e){const t=Date.now(),n=this.db.prepare("\n INSERT INTO hook_event (\n session_id,\n name, input, output,\n created_at, updated_at\n ) VALUES (\n @session_id,\n @name, @input, @output,\n @created_at, @updated_at\n )\n ").run({session_id:e.session_id,name:e.name,input:"string"==typeof e.input?e.input:JSON.stringify(e.input),output:void 0===e.output||null===e.output?null:"string"==typeof e.output?e.output:JSON.stringify(e.output),created_at:t,updated_at:t});return this.findById(n.lastInsertRowid)}updateOutput(e,t){const n=Date.now(),o=this.db.prepare("\n UPDATE hook_event\n SET output = ?, updated_at = ?\n WHERE id = ?\n "),s="string"==typeof t?t:JSON.stringify(t);return o.run(s,n,e),this.findById(e)}findById(e){const t=this.db.prepare("SELECT * FROM hook_event WHERE id = ?").get(e);return t&&(t.input&&(t.input=JSON.parse(t.input)),t.output&&(t.output=JSON.parse(t.output))),t}findBySession(e){return this.db.prepare("SELECT * FROM hook_event WHERE session_id = ? ORDER BY created_at ASC").all(e).map(e=>({...e,input:e.input?JSON.parse(e.input):null,output:e.output?JSON.parse(e.output):null}))}findBySessionAndType(e,t){return this.db.prepare("SELECT * FROM hook_event WHERE session_id = ? AND name = ? ORDER BY created_at ASC").all(e,t).map(e=>({...e,input:e.input?JSON.parse(e.input):null,output:e.output?JSON.parse(e.output):null}))}findByRepository(e,t=100){return this.db.prepare("\n SELECT he.* FROM hook_event he\n JOIN session s ON he.session_id = s.session_id\n WHERE s.repository_id = ?\n ORDER BY he.created_at DESC\n LIMIT ?\n ").all(e,t).map(e=>({...e,input:e.input?JSON.parse(e.input):null,output:e.output?JSON.parse(e.output):null}))}findByHookType(e,t=100){return this.db.prepare("SELECT * FROM hook_event WHERE name = ? ORDER BY created_at DESC LIMIT ?").all(e,t).map(e=>({...e,input:e.input?JSON.parse(e.input):null,output:e.output?JSON.parse(e.output):null}))}findLatestSessionStart(e){const t=this.db.prepare("\n SELECT * FROM hook_event\n WHERE session_id = ? AND name = ?\n ORDER BY created_at DESC\n LIMIT 1\n ").get(e,b.SESSION_START);return t&&(t.input&&(t.input=JSON.parse(t.input)),t.output&&(t.output=JSON.parse(t.output))),t}hasSessionEnded(e){return this.db.prepare("\n SELECT COUNT(*) as count FROM hook_event\n WHERE session_id = ? AND name = ?\n ").get(e,b.SESSION_END).count>0}getSessionSummary(e){const t=this.findBySession(e),n=this._parseSessionData(this.db.prepare("SELECT * FROM session WHERE session_id = ?").get(e)),o={session_id:e,total_events:t.length,hook_types:{},start_time:null,end_time:null,duration:null,repository_id:n?.repository_id||null,branch:n?.branch||null,config:n?.config||null,created_at:n?.created_at||null,updated_at:n?.updated_at||null};return t.forEach(e=>{o.hook_types[e.name]=(o.hook_types[e.name]||0)+1,e.name!==b.SESSION_START||o.start_time||(o.start_time=e.created_at),e.name!==b.SESSION_END||o.end_time||(o.end_time=e.created_at)}),o.start_time&&o.end_time&&(o.duration=o.end_time-o.start_time),o}delete(e){return this.db.prepare("DELETE FROM hook_event WHERE id = ?").run(e)}deleteBySession(e){return this.db.prepare("DELETE FROM hook_event WHERE session_id = ?").run(e)}getRecentSessions(e=10){return this.db.prepare("\n SELECT DISTINCT session_id, MAX(created_at) as last_activity\n FROM hook_event\n GROUP BY session_id\n ORDER BY last_activity DESC\n LIMIT ?\n ").all(e)}count(e={}){let t="SELECT COUNT(*) as count FROM hook_event";const n=[],o=[];return e.session_id&&(n.push("session_id = ?"),o.push(e.session_id)),e.name&&(n.push("name = ?"),o.push(e.name)),n.length>0&&(t+=` WHERE ${n.join(" AND ")}`),this.db.prepare(t).get(...o).count}}class A{constructor(e=null){this.repoPath=e||u(),this.git=p(this.repoPath)}getCurrentBranch(){return this.git.branchLocal().then(e=>e.current).catch(e=>{throw new Error(`Failed to get current branch: ${e.message}`)})}getRemoteUrl(e="origin"){return this.git.getRemotes(!0).then(t=>{const n=t.find(t=>t.name===e);if(!n)throw new Error(`Remote '${e}' not found`);return n.refs.fetch||n.refs.push}).catch(e=>{throw new Error(`Failed to get remote URL: ${e.message}`)})}getMainBranch(){return this.git.branchLocal().then(e=>{const t=e.all;return t.includes("main")?"main":t.includes("master")?"master":t[0]||"main"}).catch(()=>"main")}isOnMainBranch(){return this.getCurrentBranch().then(e=>this.getMainBranch().then(t=>e===t))}getCurrentCommitHash(){return this.git.revparse(["HEAD"]).then(e=>e.trim()).catch(e=>{throw new Error(`Failed to get commit hash: ${e.message}`)})}getCommitAuthor(e="HEAD"){return this.git.show(["-s","--format=%an <%ae>",e]).then(e=>e.trim()).catch(e=>{throw new Error(`Failed to get commit author: ${e.message}`)})}isBranchMergedToMain(e){return this.getMainBranch().then(t=>this.git.branch(["--merged",t]).then(t=>t.all.map(e=>e.replace("*","").trim()).includes(e))).catch(e=>(console.error(`Failed to check merge status: ${e.message}`),!1))}getRepoRoot(){return this.git.revparse(["--show-toplevel"]).then(e=>e.trim()).catch(e=>{throw new Error(`Failed to get repo root: ${e.message}`)})}isGitRepository(){return this.git.checkIsRepo().catch(()=>!1)}getStatus(){return this.git.status().catch(e=>{throw new Error(`Failed to get git status: ${e.message}`)})}getAllBranches(){return this.git.branchLocal().then(e=>e.all).catch(e=>{throw new Error(`Failed to get branches: ${e.message}`)})}getRepositoryName(){return this.getRemoteUrl().then(e=>{const t=e.match(/([^/:]+?)(?:\.git)?$/);return t?t[1]:"unknown"}).catch(()=>"unknown")}getUserName(){return this.git.getConfig("user.name").then(e=>e.value||process.env.USER||process.env.USERNAME||"unknown_user").catch(()=>"unknown")}getUserInfo(){return Promise.all([this.git.getConfig("user.name").catch(()=>({value:null})),this.git.getConfig("user.email").catch(()=>({value:null}))]).then(([e,t])=>({name:e.value||"unknown",email:t.value||"unknown"}))}}class M{constructor(e,t){this.gitUtils=e,this.repositoryRepo=t}getCurrentRepository(){return Promise.all([this.gitUtils.getRemoteUrl(),this.gitUtils.getRepositoryName(),this.gitUtils.getRepoRoot()]).then(([e,t,n])=>this.getOrCreateRepository(e,t,n)).catch(e=>{throw new Error(`Failed to get current repository: ${e.message}`)})}getOrCreateRepository(e,t,n=null){return Promise.resolve(this.repositoryRepo.getOrCreate(e,t,n))}getRepository(e){return Promise.resolve(this.repositoryRepo.findById(e))}getRepositoryByUrl(e){return Promise.resolve(this.repositoryRepo.findByRemoteUrl(e))}getAllRepositories(){return Promise.resolve(this.repositoryRepo.findAll())}updateRepository(e,t){return Promise.resolve(this.repositoryRepo.update(e,t))}deleteRepository(e){return Promise.resolve(this.repositoryRepo.delete(e))}getRepositoryStats(e){return Promise.resolve({total_repositories:this.repositoryRepo.count()})}}class ${constructor(e){this.gitUtils=e}validateBranchForSession(){return this.gitUtils.getCurrentBranch().then(e=>this.gitUtils.getMainBranch().then(t=>e===t?{valid:!1,branch:e,message:`Cannot start session on main branch '${e}'. Please create a feature branch first.\n\nExample:\n git checkout -b feature/my-feature\n claude "your prompt here"`}:{valid:!0,branch:e,message:`Session validated on branch '${e}'`})).catch(e=>(console.warn(`Branch validation warning: ${e.message}`),{valid:!0,branch:"unknown",message:`Branch validation skipped: ${e.message}`}))}isMainBranch(){return this.gitUtils.isOnMainBranch().catch(()=>!1)}}const X=new class{constructor(){this.database=(k||(k=new f),k),this.initialized=!1}initialize(){this.initialized||(this.database.initialize(),this.initialized=!0)}async prepare(){this.initialize(),function(e){Object.values(C).forEach(t=>{e.prepare(t).run()}),Object.values(D).forEach(t=>{e.prepare(t).run()}),Object.values(L).forEach(t=>{e.prepare(t).run()});const t=e.prepare("SELECT COUNT(*) as count FROM knowledge_item_fts").get(),n=e.prepare("SELECT COUNT(*) as count FROM knowledge_item").get();n.count>0&&0===t.count&&(console.log("Populating FTS index from existing data..."),e.prepare("\n INSERT INTO knowledge_item_fts(rowid, title, summary, content)\n SELECT id, title, summary, content FROM knowledge_item\n ").run(),console.log(`FTS index populated with ${n.count} items`))}(this.database.getConnection())}getConnection(){return this.initialize(),this.database.getConnection()}close(){this.database&&(this.database.close(),this.initialized=!1)}},H=new class{constructor(e){this.dbService=e,this._repositoryRepo=null}get repositoryRepo(){return this._repositoryRepo||(this._repositoryRepo=new U(this.dbService.database)),this._repositoryRepo}}(X),W=new class{constructor(e){this.dbService=e,this._knowledgeRepo=null}get knowledgeRepo(){return this._knowledgeRepo||(this._knowledgeRepo=new F(this.dbService.database)),this._knowledgeRepo}}(X),P=new class{constructor(e){this.dbService=e,this._sessionRepo=null}get sessionRepo(){return this._sessionRepo||(this._sessionRepo=new B(this.dbService.database)),this._sessionRepo}}(X),G=new class{constructor(e){this.gitUtils=new A,this.repositoryManager=new M(this.gitUtils,e),this.branchValidator=new $(this.gitUtils)}}(H.repositoryRepo);async function j(){w().then(e=>e.find(e=>"knowledge-bank"===e.name)).then(async e=>{e||await new Promise((e,t)=>{d(`claude plugin marketplace add ${y}`,(n,o,s)=>{n?t(n):(s&&console.error(s),console.log(o),e())})}),await new Promise((e,t)=>{d("claude plugin install core@knowledge-bank",(n,o,s)=>{n?t(n):(s&&console.error(s),console.log(o),e())})})}).then(async()=>{await async function(){await X.prepare(),X.initialize()}()}).catch(e=>{console.error("Error during installation:",e)})}async function x(){w().then(e=>e.find(e=>"knowledge-bank"===e.name)).then(async e=>{e?(await new Promise((e,t)=>{d("claude plugin uninstall core@knowledge-bank",(n,o,s)=>{n?t(n):(s&&console.error(s),console.log(o),e())})}),await new Promise((e,t)=>{d("claude plugin marketplace remove knowledge-bank",(n,o,s)=>{n?t(n):(s&&console.error(s),console.log(o),e())})})):console.log("knowledge-bank plugin is not installed.")}).catch(e=>{console.error("Error during uninstallation:",e)})}async function J(){console.log("📚 Knowledge Bank Status\n");const e=X.database.getPath(),t=X.database.exists();if(console.log(`Database: ${e}`),console.log(`Status: ${t?"✓ Connected":"✗ Not found"}\n`),await G.gitUtils.isGitRepository()){const e=await G.repositoryManager.getCurrentRepository(),t=await G.gitUtils.getCurrentBranch();console.log("Current Repository:"),console.log(` Name: ${e.name}`),console.log(` Branch: ${t}`),console.log(` Remote: ${e.remote_url}\n`);const n={total:W.knowledgeRepo.count({repository_id:e.id}),by_status:{draft:W.knowledgeRepo.count({repository_id:e.id,status:"draft"}),suggested:W.knowledgeRepo.count({repository_id:e.id,status:"suggested"}),verified:W.knowledgeRepo.count({repository_id:e.id,status:"verified"})},by_scope:{personal:W.knowledgeRepo.count({repository_id:e.id,scope:"personal"}),project:W.knowledgeRepo.count({repository_id:e.id,scope:"project"}),organization:W.knowledgeRepo.count({repository_id:e.id,scope:"organization"})}};console.log("Knowledge Statistics:"),console.log(` Total: ${n.total}`),console.log(" By Status:"),console.log(` - Draft: ${n.by_status.draft}`),console.log(` - Suggested: ${n.by_status.suggested}`),console.log(` - Verified: ${n.by_status.verified}`),console.log(" By Scope:"),console.log(` - Personal: ${n.by_scope.personal}`),console.log(` - Project: ${n.by_scope.project}`),console.log(` - Organization: ${n.by_scope.organization}\n`);const o=P.sessionRepo.getRecentSessions(5);console.log(`Recent Sessions: ${o.length}`),o.length>0&&o.forEach((e,t)=>{const n=new Date(e.updated_at).toLocaleString();console.log(` ${t+1}. ${e.session_id.substring(0,8)}... (${n})`)})}else{console.log("Not in a Git repository\n");const e=W.knowledgeRepo.count({});console.log("Global Knowledge Statistics:"),console.log(` Total: ${e}`)}}H.gitService=G;class Y extends Error{constructor(e,t=1){super(e),this.name="CLIError",this.exitCode=t}}export{Y as CLIError,j as install,J as knowledgeStatus,x as uninstall};