prjct-cli 2.2.7 → 2.2.8
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/CHANGELOG.md +7 -0
- package/dist/bin/prjct-core.mjs +188 -188
- package/dist/daemon/entry.mjs +149 -149
- package/dist/mcp/server.mjs +26 -26
- package/package.json +1 -1
package/dist/mcp/server.mjs
CHANGED
|
@@ -5,13 +5,13 @@ import { dirname as __pathDirname } from 'path';
|
|
|
5
5
|
var require = __createRequire(import.meta.url);
|
|
6
6
|
var __filename = __fileURLToPath(import.meta.url);
|
|
7
7
|
var __dirname = __pathDirname(__filename);
|
|
8
|
-
var
|
|
9
|
-
`;await X.writeFile(n,s,"utf-8")}async function _(n){try{return await X.access(n),!0}catch(t){if(P(t))return!1;throw t}}async function
|
|
10
|
-
`)[0];if(s?.startsWith("worktree "))return s.replace("worktree ","").trim()}catch{}let{stdout:e}=await k("git rev-parse --show-toplevel",{cwd:t});return e.trim()}async setup(t,e){let r=I.join(e,".env");await _(r)&&await
|
|
8
|
+
var ot=Object.defineProperty;var Xr=Object.getOwnPropertyDescriptor;var $r=Object.getOwnPropertyNames;var Wr=Object.prototype.hasOwnProperty;var c=(n,t)=>ot(n,"name",{value:t,configurable:!0}),pe=(n=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(n,{get:(t,e)=>(typeof require<"u"?require:t)[e]}):n)(function(n){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+n+'" is not supported')});var A=(n,t)=>()=>(n&&(t=n(n=0)),t);var me=(n,t)=>{for(var e in t)ot(n,e,{get:t[e],enumerable:!0})},Gr=(n,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of $r(t))!Wr.call(n,s)&&s!==e&&ot(n,s,{get:()=>t[s],enumerable:!(r=Xr(t,s))||r.enumerable});return n};var vt=n=>Gr(ot({},"__esModule",{value:!0}),n);var ge,fe,he,_t=A(()=>{"use strict";ge=new Set(["node_modules",".git","dist","build","out",".next",".nuxt","coverage",".cache",".turbo",".vercel",".parcel-cache","__pycache__",".pytest_cache","target","vendor",".venv","venv","eggs","*.egg-info",".prjct",".worktrees"]),fe=["",".ts",".tsx",".js",".jsx","/index.ts","/index.js"],he=/(?:import|from)\s+['"]([^'"]+)['"]/g});function Hr(n){return n instanceof Error&&"code"in n}function P(n){return Hr(n)&&n.code==="ENOENT"}function Ee(n){return n instanceof Error?n.message:typeof n=="string"?n:"Unknown error"}var U=A(()=>{"use strict";c(Hr,"isNodeError");c(P,"isNotFoundError");c(Ee,"getErrorMessage")});import be from"node:fs/promises";async function Se(n,t){let e;try{e=await be.readFile(n,"utf-8")}catch(i){if(P(i))return null;throw i}let r;try{r=JSON.parse(e)}catch{return await ke(n,e),we(n,"Malformed JSON"),null}let s=t.safeParse(r);return s.success?r:(await ke(n,e),we(n,qr(s.error)),null)}async function ke(n,t){let e=`${n}.backup`;try{await be.writeFile(e,t,"utf-8")}catch{}}function we(n,t){console.error(`[prjct] Warning: Corrupted storage file: ${n}`),console.error(`[prjct] Reason: ${t}`),console.error("[prjct] A .backup file has been created. Returning defaults.")}function qr(n){return n.issues.slice(0,3).map(t=>`${t.path.join(".")}: ${t.message}`).join("; ")}var ve=A(()=>{"use strict";U();c(Se,"safeRead");c(ke,"createBackup");c(we,"logCorruption");c(qr,"formatZodError")});import X from"node:fs/promises";import xt from"node:path";async function _e(n,t={}){let e=[],r=t.maxFiles??1/0,s=t.dotfileAllowlist?new Set(t.dotfileAllowlist):null;async function i(o){if(e.length>=r)return;let a=await X.readdir(o,{withFileTypes:!0}).catch(()=>[]);for(let u of a){if(e.length>=r)break;let d=String(u.name);if(ge.has(d)||t.skipDotfiles&&d.startsWith(".")&&(!s||!s.has(d)))continue;let m=xt.join(o,d);u.isDirectory()?await i(m):u.isFile()&&e.push(xt.relative(n,m))}}return c(i,"walk"),await i(n),e}async function xe(n,t,e){let r=[];for(let s=0;s<n.length;s+=t){let i=await Promise.all(n.slice(s,s+t).map(e));for(let o of i)o!==null&&r.push(o)}return r}async function at(n,t=null,e){if(e)return await Se(n,e)??t;try{let r=await X.readFile(n,"utf-8");return JSON.parse(r)}catch(r){if(P(r))return t;throw r}}async function L(n,t,e=2){let r=xt.dirname(n);await X.mkdir(r,{recursive:!0});let s=`${JSON.stringify(t,null,e)}
|
|
9
|
+
`;await X.writeFile(n,s,"utf-8")}async function _(n){try{return await X.access(n),!0}catch(t){if(P(t))return!1;throw t}}async function Rt(n){try{return(await X.stat(n)).isDirectory()}catch(t){if(P(t))return!1;throw t}}async function O(n){await X.mkdir(n,{recursive:!0})}var M=A(()=>{"use strict";_t();ve();U();c(_e,"walkDir");c(xe,"batchProcess");c(at,"readJson");c(L,"writeJson");c(_,"fileExists");c(Rt,"dirExists");c(O,"ensureDir")});var Pe=A(()=>{"use strict"});import{z as Q}from"zod";function Ae(n,t){let e=n.split(".").map(Number),r=t.split(".").map(Number);for(let s=0;s<3;s++){let i=e[s]??0,o=r[s]??0;if(i<o)return-1;if(i>o)return 1}return 0}var Pt,At=A(()=>{"use strict";Pt=Q.object({provider:Q.string(),model:Q.string(),cliVersion:Q.string().optional(),recordedAt:Q.string()});c(Ae,"compareSemver")});import{exec as Yr,execFile as zr}from"node:child_process";import{promisify as Ne}from"node:util";var k,Hn,B=A(()=>{"use strict";k=Ne(Yr),Hn=Ne(zr)});function Ce(n,t){let e=typeof n=="string"?new Date(n).getTime():n;return Date.now()-e>t}var ct,Nt=A(()=>{"use strict";c(Ce,"isExpired");ct=class{static{c(this,"TTLCache")}cache=new Map;ttl;maxSize;constructor(t={}){this.ttl=t.ttl??5e3,this.maxSize=t.maxSize??50}isValid(t){let e=this.cache.get(t);return e?Date.now()-e.timestamp<this.ttl:!1}get(t){let e=this.cache.get(t);return e?this.isValid(t)?e.data:(this.cache.delete(t),null):null}set(t,e){this.cache.set(t,{data:e,timestamp:Date.now()}),this.evictOldEntries()}delete(t){this.cache.delete(t)}clear(){this.cache.clear()}has(t){return this.cache.has(t)}get size(){return this.cache.size}evictOldEntries(){if(this.cache.size<=this.maxSize)return;let e=Array.from(this.cache.entries()).sort((r,s)=>r[1].timestamp-s[1].timestamp).slice(0,this.cache.size-this.maxSize);for(let[r]of e)this.cache.delete(r)}stats(){return{size:this.cache.size,maxSize:this.maxSize,ttl:this.ttl}}prune(){let t=0;for(let e of this.cache.keys())this.isValid(e)||(this.cache.delete(e),t++);return t}}});import Jr from"node:fs/promises";import Kr from"node:os";import Ie from"node:path";async function Le(){try{let n=await Jr.readFile(De,"utf-8"),t=JSON.parse(n);return!t.timestamp||!t.detection||!t.detection.claude||!t.detection.gemini||!t.detection.codex||Ce(t.timestamp,Qr)?null:t.detection}catch{return null}}async function Oe(n){let t={timestamp:new Date().toISOString(),detection:n};await L(De,t)}var Vr,De,Qr,Me=A(()=>{"use strict";Nt();M();Vr=Ie.join(Kr.homedir(),".prjct-cli","cache"),De=Ie.join(Vr,"providers.json"),Qr=10*60*1e3;c(Le,"readProviderCache");c(Oe,"writeProviderCache")});var lt={};me(lt,{ClaudeProvider:()=>ut,CursorProvider:()=>Ue,GeminiProvider:()=>It,Providers:()=>Z,detectAllProviders:()=>Dt,detectAntigravity:()=>ss,detectCodex:()=>Ge,detectProvider:()=>Ct,getActiveProvider:()=>es,getProviderBranding:()=>rs,selectProvider:()=>ns,validateCliVersion:()=>We});import j from"node:os";import N from"node:path";async function $e(n){try{let{stdout:t}=await k(`which ${n}`,{timeout:2e3});return t.trim()}catch{return null}}async function ts(n){try{let{stdout:t}=await k(`${n} --version`,{timeout:2e3}),e=t.match(/\d+\.\d+\.\d+/);return e?e[0]:t.trim()}catch{return null}}async function Ct(n){let t=Z[n];if(!t.cliCommand)return{installed:!1};let e=await $e(t.cliCommand);if(!e)return{installed:!1};let r=await ts(t.cliCommand),s=We(n,r||void 0);return{installed:!0,version:r||void 0,path:e,versionWarning:s||void 0}}function We(n,t){let e=Z[n];return!e.minCliVersion||!t?null:Ae(t,e.minCliVersion)<0?`\u26A0\uFE0F ${e.displayName} v${t} is below minimum v${e.minCliVersion}. Some features may not work correctly.`:null}async function Dt(n=!1){if(!n){let o=await Le();if(o)return o}let[t,e,r]=await Promise.all([Ct("claude"),Ct("gemini"),Ge()]),s={installed:r.installed},i={claude:t,gemini:e,codex:s};return await Oe(i).catch(()=>{}),i}async function es(n){if(n&&Z[n])return Z[n];let t=await Dt();return t.claude.installed&&!t.gemini.installed?ut:t.gemini.installed&&!t.claude.installed?It:ut}function rs(n){return{commitFooter:"Generated with [p/](https://www.prjct.app/)",signature:{claude:"\u26A1 prjct + Claude",gemini:"\u26A1 prjct + Gemini",cursor:"\u26A1 prjct + Cursor",antigravity:"\u26A1 prjct + Antigravity",windsurf:"\u26A1 prjct + Windsurf",codex:"\u26A1 prjct + Codex"}[n]||"\u26A1 prjct"}}async function ss(){let n=Fe.configDir;if(!n)return{installed:!1,skillInstalled:!1};let t=N.join(n,"skills","prjct","SKILL.md"),[e,r]=await Promise.all([_(n),_(t)]);return{installed:e,skillInstalled:r,configPath:e?n:void 0}}async function Ge(){let n=Xe.configDir;if(!n)return{installed:!1,skillInstalled:!1};let t=await $e("codex"),e=N.join(n,"skills","prjct","SKILL.md"),r=await _(e),s=!!t;return{installed:s,skillInstalled:r,configPath:s?n:void 0}}async function ns(){let n=await Dt(),t=n.claude.installed,e=n.gemini.installed;return!t&&!e?{provider:"claude",userSelected:!1,detection:n}:t&&!e?{provider:"claude",userSelected:!1,detection:n}:e&&!t?{provider:"gemini",userSelected:!1,detection:n}:{provider:"claude",userSelected:!0,detection:n}}var ut,It,Fe,Ue,Zr,Xe,Z,dt=A(()=>{"use strict";Pe();At();B();M();Me();ut={name:"claude",displayName:"Claude Code",cliCommand:"claude",configDir:N.join(j.homedir(),".claude"),contextFile:"CLAUDE.md",skillsDir:N.join(j.homedir(),".claude","skills"),commandsDir:".claude/commands",commandFormat:"md",settingsFile:"settings.json",projectSettingsFile:"settings.local.json",ignoreFile:".claudeignore",websiteUrl:"https://www.anthropic.com/claude",docsUrl:"https://docs.anthropic.com/claude-code",defaultModel:"sonnet",supportedModels:["opus","sonnet","haiku"],minCliVersion:"1.0.0",capabilityTier:"full"},It={name:"gemini",displayName:"Gemini CLI",cliCommand:"gemini",configDir:N.join(j.homedir(),".gemini"),contextFile:"GEMINI.md",skillsDir:N.join(j.homedir(),".gemini","skills"),commandsDir:".gemini/commands",commandFormat:"toml",settingsFile:"settings.json",projectSettingsFile:"settings.json",ignoreFile:".geminiignore",websiteUrl:"https://geminicli.com",docsUrl:"https://geminicli.com/docs",defaultModel:"2.5-flash",supportedModels:["2.5-pro","2.5-flash","2.0-flash"],minCliVersion:"1.0.0",capabilityTier:"standard"},Fe={name:"antigravity",displayName:"Google Antigravity",cliCommand:null,configDir:N.join(j.homedir(),".gemini","antigravity"),contextFile:"ANTIGRAVITY.md",skillsDir:N.join(j.homedir(),".gemini","antigravity","global_skills"),commandsDir:".agent/skills",commandFormat:"md",settingsFile:"mcp_config.json",projectSettingsFile:null,ignoreFile:".agentignore",websiteUrl:"https://gemini.google.com/app/antigravity",docsUrl:"https://gemini.google.com/app/antigravity",defaultModel:null,supportedModels:[],minCliVersion:null,capabilityTier:"basic"},Ue={name:"cursor",displayName:"Cursor IDE",cliCommand:null,configDir:null,contextFile:"prjct.mdc",skillsDir:null,commandsDir:".cursor/commands",rulesDir:".cursor/rules",commandFormat:"md",settingsFile:null,projectSettingsFile:null,ignoreFile:".cursorignore",isProjectLevel:!0,websiteUrl:"https://cursor.com",docsUrl:"https://cursor.com/docs",defaultModel:null,supportedModels:[],minCliVersion:null,capabilityTier:"basic"},Zr={name:"windsurf",displayName:"Windsurf IDE",cliCommand:null,configDir:null,contextFile:"prjct.md",skillsDir:null,commandsDir:".windsurf/workflows",rulesDir:".windsurf/rules",commandFormat:"md",settingsFile:null,projectSettingsFile:null,ignoreFile:".windsurfignore",isProjectLevel:!0,websiteUrl:"https://windsurf.com",docsUrl:"https://docs.windsurf.com",defaultModel:null,supportedModels:[],minCliVersion:null,capabilityTier:"basic"},Xe={name:"codex",displayName:"OpenAI Codex",cliCommand:"codex",configDir:N.join(j.homedir(),".codex"),contextFile:"AGENTS.md",skillsDir:N.join(j.homedir(),".codex","skills"),commandsDir:".agents/skills",commandFormat:"md",settingsFile:null,projectSettingsFile:null,ignoreFile:".codexignore",websiteUrl:"https://openai.com/codex",docsUrl:"https://github.com/openai/codex",defaultModel:null,supportedModels:[],minCliVersion:null,capabilityTier:"basic"},Z={claude:ut,gemini:It,cursor:Ue,antigravity:Fe,windsurf:Zr,codex:Xe};c($e,"whichCommand");c(ts,"getCliVersion");c(Ct,"detectProvider");c(We,"validateCliVersion");c(Dt,"detectAllProviders");c(es,"getActiveProvider");c(rs,"getProviderBranding");c(ss,"detectAntigravity");c(Ge,"detectCodex");c(ns,"selectProvider")});var nr={};me(nr,{default:()=>Ps,worktreeService:()=>sr});import Ht from"node:fs/promises";import I from"node:path";var rr,qt,sr,Ps,ir=A(()=>{"use strict";B();M();rr=".worktrees",qt=class{static{c(this,"WorktreeService")}async create(t,e,r={}){let s=await this.getMainWorktree(t),i=I.join(s,rr,e),o=r.branch||`feat/${e}`;await Ht.mkdir(I.join(s,rr),{recursive:!0});let a=r.baseBranch?` ${r.baseBranch}`:"";await k(`git worktree add "${i}" -b "${o}"${a}`,{cwd:s});let{stdout:u}=await k("git rev-parse HEAD",{cwd:i});return{path:i,branch:o,commit:u.trim(),isMain:!1,slug:e}}async remove(t,e=!1){let r=await this.getMainWorktree(t),s;if(e)try{let{stdout:i}=await k("git rev-parse --abbrev-ref HEAD",{cwd:t});s=i.trim()}catch{}if(await k(`git worktree remove "${t}" --force`,{cwd:r}),e&&s&&s!=="main"&&s!=="master")try{await k(`git branch -D "${s}"`,{cwd:r})}catch{}}async list(t){let e=await this.getMainWorktree(t),{stdout:r}=await k("git worktree list --porcelain",{cwd:e});return this.parsePorcelainOutput(r,e)}async detect(t){try{let{stdout:e}=await k("git rev-parse --git-common-dir",{cwd:t}),{stdout:r}=await k("git rev-parse --git-dir",{cwd:t}),s=I.resolve(t,e.trim()),i=I.resolve(t,r.trim());if(s!==i){let{stdout:o}=await k("git rev-parse --abbrev-ref HEAD",{cwd:t}),{stdout:a}=await k("git rev-parse HEAD",{cwd:t}),{stdout:u}=await k("git rev-parse --show-toplevel",{cwd:t}),d=u.trim(),m=I.basename(d);return{path:d,branch:o.trim(),commit:a.trim(),isMain:!1,slug:m}}return null}catch{return null}}async getMainWorktree(t){try{let{stdout:r}=await k("git worktree list --porcelain",{cwd:t}),s=r.split(`
|
|
10
|
+
`)[0];if(s?.startsWith("worktree "))return s.replace("worktree ","").trim()}catch{}let{stdout:e}=await k("git rev-parse --show-toplevel",{cwd:t});return e.trim()}async setup(t,e){let r=I.join(e,".env");await _(r)&&await Ht.copyFile(r,I.join(t,".env"));let s=I.join(e,".prjct"),i=I.join(t,".prjct");await _(s)&&!await _(i)&&await Ht.symlink(s,i,"dir")}async teardown(t){}async clean(t){let e=await this.list(t),r=[],s=await this.getMainWorktree(t);await k("git worktree prune",{cwd:s});for(let i of e)i.isMain||await _(i.path)||r.push(i.slug);return r}parsePorcelainOutput(t,e){let r=[],s=t.trim().split(`
|
|
11
11
|
|
|
12
12
|
`);for(let i of s){if(!i.trim())continue;let o=i.trim().split(`
|
|
13
|
-
`),a="",u="",d="",m=!1;for(let p of o)p.startsWith("worktree ")?a=p.replace("worktree ","").trim():p.startsWith("HEAD ")?u=p.replace("HEAD ","").trim():p.startsWith("branch ")?d=p.replace("branch refs/heads/","").trim():p==="bare"?m=!0:p==="detached"&&(d="(detached)");if(a){let p=a===e||m;r.push({path:a,branch:d,commit:u,isMain:p,slug:p?"main":I.basename(a)})}}return r}},sr=new
|
|
14
|
-
`).map(a=>a.replace(/^\s*-\s*['"]?|['"]?\s*$/g,"")).filter(Boolean))}else if(e==="npm"||e==="lerna"){let i=h.join(t,"package.json"),o=await C.readFile(i,"utf-8"),a=JSON.parse(o);if(Array.isArray(a.workspaces)?s=a.workspaces:a.workspaces?.packages&&(s=a.workspaces.packages),e==="lerna"){let u=h.join(t,"lerna.json");if(await _(u)){let d=await C.readFile(u,"utf-8"),m=JSON.parse(d);m.packages&&(s=m.packages)}}}else if(e==="nx")s=["apps/*","libs/*","packages/*"];else if(e==="turborepo"){let i=h.join(t,"package.json"),o=await C.readFile(i,"utf-8"),a=JSON.parse(o);Array.isArray(a.workspaces)&&(s=a.workspaces)}s.length===0&&(s=["packages/*","apps/*","libs/*"]);for(let i of s){if(i.startsWith("!"))continue;let o=
|
|
13
|
+
`),a="",u="",d="",m=!1;for(let p of o)p.startsWith("worktree ")?a=p.replace("worktree ","").trim():p.startsWith("HEAD ")?u=p.replace("HEAD ","").trim():p.startsWith("branch ")?d=p.replace("branch refs/heads/","").trim():p==="bare"?m=!0:p==="detached"&&(d="(detached)");if(a){let p=a===e||m;r.push({path:a,branch:d,commit:u,isMain:p,slug:p?"main":I.basename(a)})}}return r}},sr=new qt,Ps=sr});import{StdioServerTransport as En}from"@modelcontextprotocol/sdk/server/stdio.js";import{McpServer as Tn}from"@modelcontextprotocol/sdk/server/mcp.js";import{z as R}from"zod";_t();import qe from"node:fs/promises";import q from"node:path";import Ot from"node:fs";import He from"node:path";import is from"node:crypto";import C from"node:fs/promises";import H from"node:os";import h from"node:path";import{globSync as os}from"glob";import{formatDistanceToNowStrict as _n}from"date-fns";function Te(n){return{year:n.getFullYear().toString(),month:(n.getMonth()+1).toString().padStart(2,"0"),day:n.getDate().toString().padStart(2,"0")}}c(Te,"getYearMonthDay");function f(){return new Date().toISOString()}c(f,"getTimestamp");function ye(n){let t=new Date;return t.setDate(t.getDate()-n),t}c(ye,"getDaysAgo");M();var Lt=class{static{c(this,"PathManager")}globalBaseDir;globalProjectsDir;globalConfigDir;constructor(){let t=process.env.PRJCT_CLI_HOME?.trim();this.globalBaseDir=t?h.resolve(t):h.join(H.homedir(),".prjct-cli"),this.globalProjectsDir=h.join(this.globalBaseDir,"projects"),this.globalConfigDir=h.join(this.globalBaseDir,"config")}setGlobalBaseDir(t){this.globalBaseDir=h.resolve(t),this.globalProjectsDir=h.join(this.globalBaseDir,"projects"),this.globalConfigDir=h.join(this.globalBaseDir,"config")}generateProjectId(t){return is.randomUUID()}getGlobalBasePath(){return this.globalBaseDir}getGlobalProjectPath(t){return h.join(this.globalProjectsDir,t)}getLocalConfigPath(t){return h.join(t,".prjct","prjct.config.json")}getGlobalProjectConfigPath(t){return h.join(this.getGlobalProjectPath(t),"project.json")}getLegacyPrjctPath(t){return h.join(t,".prjct")}async hasLegacyStructure(t){let e=this.getLegacyPrjctPath(t);return await Rt(e)}async hasConfig(t){let e=this.getLocalConfigPath(t);return await _(e)}async ensureGlobalStructure(){await O(this.globalBaseDir),await O(this.globalProjectsDir),await O(this.globalConfigDir)}async ensureProjectStructure(t){await this.ensureGlobalStructure();let e=this.getGlobalProjectPath(t),r=["core","progress","planning","analysis","memory"];for(let s of r)await O(h.join(e,s));return await O(h.join(e,"planning","tasks")),await O(h.join(e,"sessions")),e}getSessionPath(t,e=new Date){let{year:r,month:s,day:i}=Te(e);return h.join(this.getGlobalProjectPath(t),"sessions",r,s,i)}getCurrentSessionPath(t){return this.getSessionPath(t,new Date)}async ensureSessionPath(t,e=new Date){let r=this.getSessionPath(t,e);return await O(r),r}async listSessions(t,e=null,r=null){let s=h.join(this.getGlobalProjectPath(t),"sessions"),i=[];try{let o=await C.readdir(s,{withFileTypes:!0});for(let a of o){if(!a.isDirectory()||e&&a.name!==e.toString())continue;let u=h.join(s,a.name),d=await C.readdir(u,{withFileTypes:!0});for(let m of d){if(!m.isDirectory()||r&&m.name!==r.toString().padStart(2,"0"))continue;let p=h.join(u,m.name),g=await C.readdir(p,{withFileTypes:!0});for(let T of g)T.isDirectory()&&i.push({year:a.name,month:m.name,day:T.name,path:h.join(p,T.name),date:new Date(`${a.name}-${m.name}-${T.name}`)})}}return i.sort((a,u)=>u.date.getTime()-a.date.getTime()),i}catch{return[]}}async getSessionsInRange(t,e,r=new Date){return(await this.listSessions(t)).filter(i=>i.date>=e&&i.date<=r)}getFilePath(t,e,r){return h.join(this.getGlobalProjectPath(t),e,r)}async listProjects(){try{return await this.ensureGlobalStructure(),(await C.readdir(this.globalProjectsDir,{withFileTypes:!0})).filter(e=>e.isDirectory()).map(e=>e.name)}catch{return[]}}async projectExists(t){let e=this.getGlobalProjectPath(t);return await Rt(e)}getDisplayPath(t){let e=H.homedir();return t.startsWith(e)?t.replace(e,"~"):t}getAuthConfigPath(){return h.join(this.globalConfigDir,"auth.json")}getSyncPendingPath(t){return h.join(this.getGlobalProjectPath(t),"sync","pending.json")}getLastSyncPath(t){return h.join(this.getGlobalProjectPath(t),"sync","last-sync.json")}getRunningStatusPath(){return h.join(this.globalBaseDir,".running")}getDocsPath(){return h.join(this.globalBaseDir,"docs")}async getAgentDir(){return(await(dt(),vt(lt)).getActiveProvider()).configDir}async getAgentSettingsPath(){let t=await(dt(),vt(lt)).getActiveProvider();return(dt(),vt(lt)).getGlobalSettingsPath(t.name)}getClaudeDir(){return h.join(H.homedir(),".claude")}getClaudeSettingsPath(){return h.join(this.getClaudeDir(),"settings.json")}getStoragePath(t,e){return h.join(this.getGlobalProjectPath(t),"storage",e)}getContextPath(t){return h.join(this.getGlobalProjectPath(t),"context")}getWikiPath(t,e){if(e&&e.trim().length>0)return this.resolveVaultOverride(t,e);let s=h.basename(h.resolve(t)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"project";return h.join(H.homedir(),"Documents","prjct",s)}getWikiPathWithProjectHash(t,e){let s=h.basename(h.resolve(t)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"project",i=e.replace(/-/g,"").slice(0,8);return h.join(H.homedir(),"Documents","prjct",`${s}-${i}`)}getLegacyWikiPath(t){return h.join(t,".prjct","wiki")}resolveVaultOverride(t,e){let r=e.trim();return(r.startsWith("~/")||r==="~")&&(r=h.join(H.homedir(),r.slice(1))),h.isAbsolute(r)||(r=h.resolve(t,r)),r}async detectMonorepo(t){let e={isMonorepo:!1,type:null,rootPath:t,packages:[]},r=[{file:"pnpm-workspace.yaml",type:"pnpm"},{file:"lerna.json",type:"lerna"},{file:"nx.json",type:"nx"},{file:"rush.json",type:"rush"},{file:"turbo.json",type:"turborepo"}];for(let s of r){let i=h.join(t,s.file);if(await _(i)){e.isMonorepo=!0,e.type=s.type;break}}if(!e.isMonorepo){let s=h.join(t,"package.json");if(await _(s))try{let i=await C.readFile(s,"utf-8");JSON.parse(i).workspaces&&(e.isMonorepo=!0,e.type="npm")}catch{}}return e.isMonorepo&&(e.packages=await this.discoverMonorepoPackages(t,e.type)),e}async discoverMonorepoPackages(t,e){let r=[],s=[];try{if(e==="pnpm"){let o=(await C.readFile(h.join(t,"pnpm-workspace.yaml"),"utf-8")).match(/packages:\s*\n((?:\s*-\s*.+\n?)+)/);o&&(s=o[1].split(`
|
|
14
|
+
`).map(a=>a.replace(/^\s*-\s*['"]?|['"]?\s*$/g,"")).filter(Boolean))}else if(e==="npm"||e==="lerna"){let i=h.join(t,"package.json"),o=await C.readFile(i,"utf-8"),a=JSON.parse(o);if(Array.isArray(a.workspaces)?s=a.workspaces:a.workspaces?.packages&&(s=a.workspaces.packages),e==="lerna"){let u=h.join(t,"lerna.json");if(await _(u)){let d=await C.readFile(u,"utf-8"),m=JSON.parse(d);m.packages&&(s=m.packages)}}}else if(e==="nx")s=["apps/*","libs/*","packages/*"];else if(e==="turborepo"){let i=h.join(t,"package.json"),o=await C.readFile(i,"utf-8"),a=JSON.parse(o);Array.isArray(a.workspaces)&&(s=a.workspaces)}s.length===0&&(s=["packages/*","apps/*","libs/*"]);for(let i of s){if(i.startsWith("!"))continue;let o=os(i,{cwd:t,absolute:!1});for(let a of o){let u=h.join(t,a),d=h.join(u,"package.json");if(await _(d))try{let m=await C.readFile(d,"utf-8"),p=JSON.parse(m),g=h.join(u,"PRJCT.md");r.push({name:p.name||h.basename(a),path:u,relativePath:a,hasPrjctMd:await _(g)})}catch{}}}}catch{}return r}async findContainingPackage(t,e){if(!e.isMonorepo)return null;let r=h.resolve(t);for(let s of e.packages){let i=h.resolve(s.path);if(r.startsWith(i))return s}return null}async findMonorepoRoot(t){let e=h.resolve(t),r=h.parse(e).root;for(;e!==r;){if((await this.detectMonorepo(e)).isMonorepo)return e;e=h.dirname(e)}return null}},as=new Lt,w=as;function cs(){return typeof globalThis<"u"&&"Bun"in globalThis?"bun":"node"}c(cs,"detectRuntime");function Be(){return cs()==="bun"}c(Be,"isBun");function us(n){if(Be()){let{Database:s}=pe("bun:sqlite");return new s(n,{create:!0})}let t=pe("better-sqlite3"),e=new t(n),r=e.exec.bind(e);return e.run=s=>r(s),e}c(us,"openDatabase");var ls=[{version:1,name:"initial-schema",up:c(n=>{n.run(`
|
|
15
15
|
-- =======================================================================
|
|
16
16
|
-- Document storage (backward-compatible with JSON file pattern)
|
|
17
17
|
-- =======================================================================
|
|
@@ -482,35 +482,35 @@ var it=Object.defineProperty;var Xr=Object.getOwnPropertyDescriptor;var $r=Objec
|
|
|
482
482
|
);
|
|
483
483
|
|
|
484
484
|
CREATE INDEX IF NOT EXISTS idx_wrc_rule ON workflow_rule_cache(rule_id);
|
|
485
|
-
`)},"up")},{version:14,name:"workflow-rules-trust-source",up:c(n=>{try{n.run("ALTER TABLE workflow_rules ADD COLUMN trust_source TEXT NOT NULL DEFAULT 'local'")}catch{}},"up")},{version:15,name:"disable-orphan-workflow-rules",up:c(n=>{let e=["pause","resume","reopen","next","dash","bug","idea","linear","jira","tokens","velocity","plan"].map(r=>`'${r}'`).join(",");n.run(`UPDATE workflow_rules SET enabled = 0 WHERE command IN (${e}) AND enabled = 1`)},"up")}],
|
|
485
|
+
`)},"up")},{version:14,name:"workflow-rules-trust-source",up:c(n=>{try{n.run("ALTER TABLE workflow_rules ADD COLUMN trust_source TEXT NOT NULL DEFAULT 'local'")}catch{}},"up")},{version:15,name:"disable-orphan-workflow-rules",up:c(n=>{let e=["pause","resume","reopen","next","dash","bug","idea","linear","jira","tokens","velocity","plan"].map(r=>`'${r}'`).join(",");n.run(`UPDATE workflow_rules SET enabled = 0 WHERE command IN (${e}) AND enabled = 1`)},"up")}],ds=3,Mt=class{static{c(this,"PrjctDatabase")}connections=new Map;accessOrder=[];getDbPath(t){return He.join(w.getGlobalProjectPath(t),"prjct.db")}getDb(t){let e=this.connections.get(t);if(e)return this.touchAccessOrder(t),e;this.connections.size>=ds&&this.evictLru();let r=this.getDbPath(t),s=He.dirname(r);Ot.existsSync(s)||Ot.mkdirSync(s,{recursive:!0});let i=us(r);return i.run("PRAGMA journal_mode = WAL"),i.run("PRAGMA synchronous = NORMAL"),i.run("PRAGMA cache_size = -2000"),i.run("PRAGMA temp_store = MEMORY"),i.run("PRAGMA mmap_size = 33554432"),this.runMigrations(i),this.connections.set(t,i),this.touchAccessOrder(t),i}close(t){if(t){let e=this.connections.get(t);e&&(e.close(),this.connections.delete(t),this.accessOrder=this.accessOrder.filter(r=>r!==t))}else this.connections.forEach(e=>{e.close()}),this.connections.clear(),this.accessOrder=[]}touchAccessOrder(t){this.accessOrder=this.accessOrder.filter(e=>e!==t),this.accessOrder.push(t)}evictLru(){if(this.accessOrder.length===0)return;let t=this.accessOrder.shift(),e=this.connections.get(t);e&&(e.close(),this.connections.delete(t))}checkpointAll(){for(let[t,e]of this.connections)try{e.run("PRAGMA wal_checkpoint(TRUNCATE)")}catch{}}exists(t){return Ot.existsSync(this.getDbPath(t))}getDoc(t,e){let s=this.getDb(t).prepare("SELECT data FROM kv_store WHERE key = ?").get(e);return s?JSON.parse(s.data):null}setDoc(t,e,r){let s=this.getDb(t),i=JSON.stringify(r),o=new Date().toISOString();s.prepare("INSERT OR REPLACE INTO kv_store (key, data, updated_at) VALUES (?, ?, ?)").run(e,i,o)}deleteDoc(t,e){this.getDb(t).prepare("DELETE FROM kv_store WHERE key = ?").run(e)}hasDoc(t,e){return this.getDb(t).prepare("SELECT 1 FROM kv_store WHERE key = ?").get(e)!==null}appendEvent(t,e,r,s){let i=this.getDb(t),o=new Date().toISOString();i.prepare("INSERT INTO events (type, task_id, data, timestamp) VALUES (?, ?, ?, ?)").run(e,s??null,JSON.stringify(r),o)}getEvents(t,e,r=100){let s=this.getDb(t);return e?s.prepare("SELECT * FROM events WHERE type = ? ORDER BY id DESC LIMIT ?").all(e,r):s.prepare("SELECT * FROM events ORDER BY id DESC LIMIT ?").all(r)}query(t,e,...r){return this.getDb(t).prepare(e).all(...r)}run(t,e,...r){this.getDb(t).prepare(e).run(...r)}get(t,e,...r){return this.getDb(t).prepare(e).get(...r)??null}transaction(t,e){let r=this.getDb(t);return r.transaction(e)(r)}runMigrations(t){t.run(`
|
|
486
486
|
CREATE TABLE IF NOT EXISTS _migrations (
|
|
487
487
|
version INTEGER PRIMARY KEY,
|
|
488
488
|
name TEXT NOT NULL,
|
|
489
489
|
applied_at TEXT NOT NULL
|
|
490
490
|
)
|
|
491
|
-
`);let e=new Set(t.prepare("SELECT version FROM _migrations").all().map(r=>r.version));for(let r of
|
|
492
|
-
`)){let o=i.trim();o==="---COMMIT---"?(s&&s.size>0&&s.size<=30&&r.push(s),s=new Set):o&&s&&
|
|
491
|
+
`);let e=new Set(t.prepare("SELECT version FROM _migrations").all().map(r=>r.version));for(let r of ls)e.has(r.version)||t.transaction(()=>{r.up(t),t.prepare("INSERT INTO _migrations (version, name, applied_at) VALUES (?, ?, ?)").run(r.version,r.name,new Date().toISOString())})()}getMigrations(t){return this.getDb(t).prepare("SELECT * FROM _migrations ORDER BY version").all()}getSchemaVersion(t){return this.getDb(t).prepare("SELECT MAX(version) as version FROM _migrations").get()?.version??0}},y=new Mt,E=y;M();function ps(n){let t=[],e,r=new RegExp(he.source,"g");for(;(e=r.exec(n))!==null;){let s=e[1];(s.startsWith(".")||s.startsWith("@/"))&&t.push(s)}return t}c(ps,"extractImportSources");async function ms(n,t,e){let r;if(n.startsWith("@/"))r=q.join(e,"src",n.slice(2));else{let s=q.dirname(q.join(e,t));r=q.resolve(s,n)}for(let s of fe){let i=r+s;try{if((await qe.stat(i)).isFile())return q.relative(e,i)}catch{}}return null}c(ms,"resolveImport");async function gs(n){let t=await _e(n),e={},r={},s=0,i=await xe(t,50,async o=>{try{let a=await qe.readFile(q.join(n,o),"utf-8"),u=ps(a),d=[];for(let m of u){let p=await ms(m,o,n);p&&p!==o&&d.push(p)}return d.length>0?{filePath:o,imports:d}:null}catch{return null}});for(let{filePath:o,imports:a}of i){e[o]=a,s+=a.length;for(let u of a)r[u]||(r[u]=[]),r[u].push(o)}return{forward:e,reverse:r,fileCount:t.length,edgeCount:s,builtAt:new Date().toISOString()}}c(gs,"buildGraph");function Ye(n,t,e=2){let r=new Set(n),s=new Map,i=[];for(let o of n){let a=t.forward[o]||[],u=t.reverse[o]||[];for(let d of[...a,...u])r.has(d)||i.push({file:d,depth:1})}for(;i.length>0;){let{file:o,depth:a}=i.shift();if(a>e)continue;let u=1/(a+1),d=s.get(o);if(d){u>d.score&&s.set(o,{score:u,depth:a});continue}if(s.set(o,{score:u,depth:a}),a<e){let m=t.forward[o]||[],p=t.reverse[o]||[];for(let g of[...m,...p])!r.has(g)&&!s.has(g)&&i.push({file:g,depth:a+1})}}return Array.from(s.entries()).map(([o,{score:a,depth:u}])=>({path:o,score:a,depth:u})).sort((o,a)=>a.score-o.score)}c(Ye,"scoreFromSeeds");var jt="import-graph",pt=new Map;function fs(n,t){E.setDoc(n,jt,t),pt.delete(n)}c(fs,"saveGraph");function tt(n){let t=E.get(n,"SELECT updated_at FROM kv_store WHERE key = ?",jt);if(!t)return pt.delete(n),null;let e=pt.get(n);if(e&&e.updatedAt===t.updated_at)return e.graph;let r=E.getDoc(n,jt);return r&&pt.set(n,{graph:r,updatedAt:t.updated_at}),r}c(tt,"loadGraph");async function ze(n,t){let e=await gs(n);return fs(t,e),e}c(ze,"indexImports");function Je(n,t){let e=[...n.added,...n.modified],r=new Set(e),s=new Set,i=tt(t);if(i)for(let u of e){let d=i.reverse[u];if(d)for(let m of d)r.has(m)||s.add(m)}let o=Array.from(s),a=[...e,...o];return{directlyChanged:e,affectedByImports:o,deleted:n.deleted,allAffected:a}}c(Je,"propagateChanges");function Ke(n){let t=new Set;for(let e of n){let r=e.toLowerCase();(r.endsWith(".tsx")||r.endsWith(".jsx")||r.endsWith(".css")||r.endsWith(".scss")||r.endsWith(".vue")||r.endsWith(".svelte")||r.includes("/components/")||r.includes("/pages/")||r.includes("/app/"))&&(t.add("frontend"),t.add("uxui")),(r.includes(".test.")||r.includes(".spec.")||r.includes("__tests__")||r.includes("/test/"))&&t.add("testing"),(r.includes("dockerfile")||r.includes("docker-compose")||r.includes(".dockerignore")||r.includes(".github/")||r.includes("ci/")||r.includes("cd/"))&&t.add("devops"),(r.endsWith(".sql")||r.includes("prisma")||r.includes("drizzle")||r.includes("migration")||r.includes("/db/"))&&t.add("database"),(r.endsWith(".ts")||r.endsWith(".js"))&&!r.includes(".test.")&&!r.includes(".spec.")&&!r.endsWith(".d.ts")&&t.add("backend")}return t}c(Ke,"affectedDomains");B();async function Ts(n,t=100){try{let{stdout:e}=await k(`git log --name-only --pretty=format:'---COMMIT---' -${t}`,{cwd:n,maxBuffer:10485760}),r=[],s=null;for(let i of e.split(`
|
|
492
|
+
`)){let o=i.trim();o==="---COMMIT---"?(s&&s.size>0&&s.size<=30&&r.push(s),s=new Set):o&&s&&ys(o)&&s.add(o)}return s&&s.size>0&&s.size<=30&&r.push(s),r}catch{return[]}}c(Ts,"parseGitLog");function ys(n){return/\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|cs|rb|php|vue|svelte)$/i.test(n)&&!n.includes("node_modules/")}c(ys,"isSourceFile");async function Es(n,t=100){let e=await Ts(n,t),r=new Map,s=new Map;for(let o of e){let a=Array.from(o);for(let u of a)r.set(u,(r.get(u)||0)+1);for(let u=0;u<a.length;u++)for(let d=u+1;d<a.length;d++){let m=ks(a[u],a[d]);s.set(m,(s.get(m)||0)+1)}}let i={};for(let[o,a]of s){let[u,d]=o.split("\0"),m=r.get(u)||0,p=r.get(d)||0;if(m<2||p<2)continue;let g=m+p-a,T=g>0?a/g:0;T<.1||(i[u]||(i[u]={}),i[d]||(i[d]={}),i[u][d]=T,i[d][u]=T)}return{matrix:i,commitsAnalyzed:e.length,filesAnalyzed:r.size,builtAt:new Date().toISOString()}}c(Es,"buildMatrix");function ks(n,t){return n<t?`${n}\0${t}`:`${t}\0${n}`}c(ks,"pairKey");function Ut(n,t){let e=new Set(n),r=new Map;for(let s of n){let i=t.matrix[s];if(i)for(let[o,a]of Object.entries(i)){if(e.has(o))continue;let u=r.get(o)||0;a>u&&r.set(o,a)}}return Array.from(r.entries()).map(([s,i])=>({path:s,score:i})).sort((s,i)=>i.score-s.score)}c(Ut,"scoreFromSeeds");var Ft="cochange-index",mt=new Map;function ws(n,t){E.setDoc(n,Ft,t),mt.delete(n)}c(ws,"saveMatrix");function Xt(n){let t=E.get(n,"SELECT updated_at FROM kv_store WHERE key = ?",Ft);if(!t)return mt.delete(n),null;let e=mt.get(n);if(e&&e.updatedAt===t.updated_at)return e.matrix;let r=E.getDoc(n,Ft);return r&&mt.set(n,{matrix:r,updatedAt:t.updated_at}),r}c(Xt,"loadMatrix");async function Ze(n,t,e=100){let r=await Es(n,e);return ws(t,r),r}c(Ze,"indexCoChanges");import Yt from"node:fs/promises";import As from"node:path";import*as Tt from"jsonc-parser";var $t=class extends Error{static{c(this,"PrjctError")}code;isOperational;constructor(t,e="PRJCT_ERROR"){super(t),this.name="PrjctError",this.code=e,this.isOperational=!0,Error.captureStackTrace?.(this,this.constructor)}};function bs(n){return n instanceof $t}c(bs,"isPrjctError");function Wt(n){return bs(n)||n instanceof Error?n.message:typeof n=="string"?n:"Unknown error"}c(Wt,"getErrorMessage");U();M();U();import Gt from"node:fs";import ft from"node:path";var gt=null,et=null;function tr(){if(et)return et;let n=__dirname;for(let t=0;t<5;t++){let e=ft.join(n,"package.json");if(Gt.existsSync(e))try{if(JSON.parse(Gt.readFileSync(e,"utf-8")).name==="prjct-cli")return et=n,n}catch{}n=ft.dirname(n)}return et=ft.join(__dirname,"..","..",".."),et}c(tr,"getPackageRoot");function Ss(){if(gt)return gt;try{let n=ft.join(tr(),"package.json");return gt=JSON.parse(Gt.readFileSync(n,"utf-8")).version,gt}catch(n){return console.error("Failed to read version from package.json:",Ee(n)),"0.0.0"}}c(Ss,"getVersion");var Bt=Ss(),qi=tr();B();async function ht(n){try{let{stdout:t}=await k(n,{timeout:5e3});return{success:!0,output:t.trim()}}catch{return{success:!1,output:""}}}c(ht,"execCommand");async function vs(){let n=await ht("gh api user --jq .login");return n.success&&n.output||(n=await ht("git config --global github.user"),n.success&&n.output)?n.output:null}c(vs,"detectGitHubUsername");async function _s(){let n=await ht("git config user.name");return n.success&&n.output?n.output:null}c(_s,"detectGitName");async function xs(){let n=await ht("git config user.email");return n.success&&n.output?n.output:null}c(xs,"detectGitEmail");async function er(){let[n,t,e]=await Promise.all([vs(),_s(),xs()]);return{github:n,email:e,name:t||n||"Unknown"}}c(er,"detect");function or(n){let t=[],e=Tt.parse(n,t,{allowTrailingComma:!0,disallowComments:!1});if(t.length>0){let r=t[0];throw new SyntaxError(`JSON parse error at offset ${r.offset}: ${Tt.printParseErrorCode(r.error)}`)}return e}c(or,"parseJsonc");var zt=class{static{c(this,"ConfigManager")}async readConfig(t){try{let e=w.getLocalConfigPath(t),r=await Yt.readFile(e,"utf-8");return or(r)}catch(e){return P(e)||console.warn(`Warning: Could not read config at ${t}: ${Wt(e)}`),null}}async writeConfig(t,e){let r=w.getLocalConfigPath(t);await L(r,e)}async readGlobalConfig(t){try{let e=w.getGlobalProjectConfigPath(t),r=await Yt.readFile(e,"utf-8");return or(r)}catch(e){return P(e)||console.warn(`Warning: Could not read global config for ${t}: ${Wt(e)}`),null}}async writeGlobalConfig(t,e){let r=w.getGlobalProjectConfigPath(t);await L(r,e)}async ensureGlobalConfig(t){let e=await this.readGlobalConfig(t);if(!e){let r=f();e={projectId:t,authors:[],version:Bt,lastSync:r},await this.writeGlobalConfig(t,e)}return e}async createConfig(t,e){let r=w.generateProjectId(t),s=w.getGlobalProjectPath(r),i=w.getDisplayPath(s),o=f(),a={projectId:r,dataPath:i,showMetrics:!0};await this.writeConfig(t,a);let u={projectId:r,authors:[{name:e.name||"Unknown",email:e.email||"",github:e.github||"",firstContribution:o,lastActivity:o}],version:Bt,created:o,lastSync:o};return await this.writeGlobalConfig(r,u),a}async updateLastSync(t){let e=await this.getProjectId(t),r=await this.readGlobalConfig(e);r&&(r.lastSync=f(),await this.writeGlobalConfig(e,r))}validateConfig(t){return!(!t||!t.projectId||!t.dataPath)}async needsMigration(t){if(!await w.hasLegacyStructure(t))return!1;if(!await w.hasConfig(t))return!0;let s=await this.readConfig(t);if(!s||!s.projectId)return!0;let i=w.getGlobalProjectPath(s.projectId);try{return(await Yt.readdir(As.join(i,"core"))).length===0}catch(o){return P(o),!0}}async getProjectId(t){let e=await this.readConfig(t);if(e?.projectId)return e.projectId;try{let{worktreeService:r}=await Promise.resolve().then(()=>(ir(),nr));if(await r.detect(t)){let i=await r.getMainWorktree(t);if(i!==t){let o=await this.readConfig(i);if(o?.projectId)return o.projectId}}}catch{}return w.generateProjectId(t)}async findAuthor(t,e){let r=await this.readGlobalConfig(t);return!r||!r.authors?null:r.authors.find(s=>s.github===e)||null}async addAuthor(t,e){let r=await this.ensureGlobalConfig(t);if(r.authors.some(o=>o.github===e.github))return;let i=f();r.authors.push({name:e.name||"Unknown",email:e.email||"",github:e.github||"",firstContribution:i,lastActivity:i}),r.lastSync=i,await this.writeGlobalConfig(t,r)}async updateAuthorActivity(t,e){let r=await this.readGlobalConfig(t);if(!r||!r.authors)return;let s=r.authors.find(i=>i.github===e);s&&(s.lastActivity=f(),r.lastSync=s.lastActivity,await this.writeGlobalConfig(t,r))}async getCurrentAuthor(t){let e=await er(),r=await this.getProjectId(t);return await this.addAuthor(r,{name:e.name??void 0,email:e.email??void 0,github:e.github??void 0}),e.github||e.name||"Unknown"}async isConfigured(t){let e=await this.readConfig(t);return this.validateConfig(e)}async getShowMetrics(t){return(await this.readConfig(t))?.showMetrics??!0}async setShowMetrics(t,e){let r=await this.readConfig(t);r&&(r.showMetrics=e,await this.writeConfig(t,r))}async getConfigWithDefaults(t){let e=await this.readConfig(t);if(e)return e;let r=w.generateProjectId(t);return{projectId:r,dataPath:w.getDisplayPath(w.getGlobalProjectPath(r))}}},Ns=new zt,$=Ns;async function v(n){return $.getProjectId(n)}c(v,"resolveProjectId");function b(n,t){return async e=>{try{return await t(e)}catch(r){return Cs(r,n)}}}c(b,"safeMcpCall");function Cs(n,t){let e=n instanceof Error?n.message:String(n);return{content:[{type:"text",text:`[${t}] Error: ${e}`}],isError:!0}}c(Cs,"mcpError");function ar(n){let t=n;t.tool("prjct_impact_analysis","Given changed files, find affected files via import graph + affected domains",{projectPath:R.string().describe("Project directory path"),changedFiles:R.array(R.string()).describe("List of changed file paths (relative to project root)")},b("prjct_impact_analysis",async e=>{let r=await v(e.projectPath),s={added:[],modified:e.changedFiles,deleted:[],unchanged:[]},i=Je(s,r),o=Ke(i.allAffected),a=["## Impact Analysis"];a.push(`
|
|
493
493
|
### Directly Changed (${i.directlyChanged.length})`);for(let u of i.directlyChanged)a.push(`- ${u}`);if(i.affectedByImports.length>0){a.push(`
|
|
494
494
|
### Affected via Imports (${i.affectedByImports.length})`);for(let u of i.affectedByImports)a.push(`- ${u}`)}return a.push(`
|
|
495
495
|
### Affected Domains`),a.push(o.size>0?Array.from(o).join(", "):"none detected"),a.push(`
|
|
496
496
|
Total affected: ${i.allAffected.length} files`),{content:[{type:"text",text:a.join(`
|
|
497
|
-
`)}]}})),t.tool("prjct_import_graph","Import graph stats + file neighbors (imports/importers). Pass a file for its neighbors, omit for graph stats.",{projectPath:R.string().describe("Project directory path"),file:R.string().optional().describe("File path to get neighbors for (omit for graph stats)"),rebuild:R.boolean().optional().default(!1).describe("Force rebuild the import graph")},b("prjct_import_graph",async e=>{let r=await v(e.projectPath),s=e.rebuild?null:
|
|
497
|
+
`)}]}})),t.tool("prjct_import_graph","Import graph stats + file neighbors (imports/importers). Pass a file for its neighbors, omit for graph stats.",{projectPath:R.string().describe("Project directory path"),file:R.string().optional().describe("File path to get neighbors for (omit for graph stats)"),rebuild:R.boolean().optional().default(!1).describe("Force rebuild the import graph")},b("prjct_import_graph",async e=>{let r=await v(e.projectPath),s=e.rebuild?null:tt(r);if(s||(s=await ze(e.projectPath,r)),e.file){let o=s.forward[e.file]||[],a=s.reverse[e.file]||[];return{content:[{type:"text",text:[`## Import Neighbors: ${e.file}`,`
|
|
498
498
|
### Imports (${o.length})`,...o.map(d=>`- ${d}`),`
|
|
499
499
|
### Imported By (${a.length})`,...a.map(d=>`- ${d}`)].join(`
|
|
500
500
|
`)}]}}return{content:[{type:"text",text:["## Import Graph Stats",`Files: ${s.fileCount}`,`Edges: ${s.edgeCount}`,`Built: ${s.builtAt}`].join(`
|
|
501
|
-
`)}]}})),t.tool("prjct_cochange","Files that historically change together (Jaccard similarity from git history)",{projectPath:R.string().describe("Project directory path"),seedFiles:R.array(R.string()).describe("Seed files to find co-change partners for"),rebuild:R.boolean().optional().default(!1).describe("Force rebuild the co-change matrix"),maxResults:R.number().optional().default(10).describe("Max results (default 10)")},b("prjct_cochange",async e=>{let r=await v(e.projectPath),s=e.rebuild?null:
|
|
502
|
-
`)}]}})),t.tool("prjct_related_context","Combined: import neighbors + co-change partners for seed files",{projectPath:R.string().describe("Project directory path"),seedFiles:R.array(R.string()).describe("Seed files to find related context for"),maxResults:R.number().optional().default(15).describe("Max results (default 15)")},b("prjct_related_context",async e=>{let r=await v(e.projectPath),s=
|
|
503
|
-
`)}]}}))}c(ar,"registerCodeIntelTools");import{z as W}from"zod";import Cs from"node:crypto";function F(){return Cs.randomUUID()}c(F,"generateUUID");Rt();import{z as l}from"zod";var Is=l.enum(["low","medium","high","critical"]),ht=l.enum(["feature","bug","improvement","chore"]),Ds=l.enum(["active","backlog","previously_active"]),Ls=l.enum(["pending","in_progress","completed","blocked","paused","failed","skipped"]),qt=l.object({title:l.string(),description:l.string(),filesChanged:l.array(l.object({path:l.string(),action:l.enum(["created","modified","deleted"])})),whatWasDone:l.array(l.string()).min(1),outputForNextAgent:l.string().min(1),notes:l.string().optional()}),ur=l.object({output:l.string().min(1,"Subtask output is required"),summary:qt}),lr=l.object({id:l.string(),description:l.string(),domain:l.string(),agent:l.string(),status:Ls,dependsOn:l.array(l.string()),startedAt:l.string().optional(),completedAt:l.string().optional(),output:l.string().optional(),summary:qt.optional(),skipReason:l.string().optional(),blockReason:l.string().optional(),estimatedPoints:l.number().optional(),estimatedMinutes:l.number().optional()}),dr=l.object({completed:l.number(),total:l.number(),percentage:l.number()}),pr=l.object({id:l.string(),description:l.string(),type:ht.optional(),startedAt:l.string(),sessionId:l.string(),featureId:l.string().optional(),subtasks:l.array(lr).optional(),currentSubtaskIndex:l.number().optional(),subtaskProgress:dr.optional(),linearId:l.string().optional(),linearUuid:l.string().optional(),estimatedPoints:l.number().optional(),estimatedMinutes:l.number().optional(),modelMetadata:xt.optional(),tokensIn:l.number().optional(),tokensOut:l.number().optional(),parentDescription:l.string().optional(),branch:l.string().optional(),prUrl:l.string().optional()}),cr=l.object({id:l.string(),description:l.string(),status:l.literal("paused"),startedAt:l.string(),pausedAt:l.string(),pauseReason:l.string().optional(),type:ht.optional(),sessionId:l.string().optional(),featureId:l.string().optional(),subtasks:l.array(lr).optional(),currentSubtaskIndex:l.number().optional(),subtaskProgress:dr.optional(),linearId:l.string().optional(),linearUuid:l.string().optional(),estimatedPoints:l.number().optional(),estimatedMinutes:l.number().optional(),modelMetadata:xt.optional(),tokensIn:l.number().optional(),tokensOut:l.number().optional()}),Os=l.object({stackConfirmed:l.array(l.string()).optional(),patternsDiscovered:l.array(l.string()).optional(),agentAccuracy:l.array(l.object({agent:l.string(),rating:l.enum(["helpful","neutral","inaccurate"]),note:l.string().optional()})).optional(),issuesEncountered:l.array(l.string()).optional()}),Ms=l.object({taskId:l.string(),title:l.string(),classification:ht,startedAt:l.string(),completedAt:l.string(),subtaskCount:l.number(),subtaskSummaries:l.array(qt),outcome:l.string(),branchName:l.string(),linearId:l.string().optional(),linearUuid:l.string().optional(),prUrl:l.string().optional(),feedback:Os.optional(),tokensIn:l.number().optional(),tokensOut:l.number().optional()}),js=pr.extend({workspaceId:l.string(),worktreePath:l.string().optional(),agentSessionId:l.string().optional(),jiraId:l.string().optional(),jiraUuid:l.string().optional(),dispatchedFrom:l.string().optional()}),mr=l.object({currentTask:pr.nullable(),previousTask:cr.nullable().optional(),pausedTasks:l.array(cr).optional(),taskHistory:l.array(Ms).optional(),activeTasks:l.array(js).optional(),lastUpdated:l.string()}),Fs=l.object({id:l.string(),description:l.string(),body:l.string().optional(),priority:Is,type:ht,featureId:l.string().optional(),originFeature:l.string().optional(),completed:l.boolean(),completedAt:l.string().optional(),createdAt:l.string(),section:Ds,agent:l.string().optional(),groupName:l.string().optional(),groupId:l.string().optional()}),gr=l.object({tasks:l.array(Fs),lastUpdated:l.string()});var et={idle:{transitions:["task"],prompt:"prjct task <description> Start working",description:"No active task"},working:{transitions:["done","pause"],prompt:"prjct status done Complete task | prjct status paused Switch context",description:"Task in progress"},paused:{transitions:["resume","task","ship"],prompt:"prjct status active Continue | prjct task <new> Start different | prjct ship Ship directly",description:"Task paused"},completed:{transitions:["ship","task","pause","reopen"],prompt:"prjct ship Ship it | prjct task <next> Start next | prjct status active Reopen",description:"Task completed"},shipped:{transitions:["task"],prompt:"prjct task <description> Start new task",description:"Feature shipped"}},Yt=class{static{c(this,"WorkflowStateMachine")}getCurrentState(t,e){let r=null;if(e&&t?.activeTasks?.length&&(r=t.activeTasks.find(i=>i.workspaceId===e)),r||(r=t?.currentTask),!r)return(t?.pausedTasks?.length||0)>0||t?.previousTask?.status==="paused"?"paused":"idle";switch((typeof r.status=="string"?r.status:"").toLowerCase()){case"in_progress":case"working":return"working";case"paused":return"paused";case"completed":case"done":return"completed";case"shipped":return"shipped";default:return r?"working":"idle"}}canTransition(t,e){if(et[t].transitions.includes(e))return{valid:!0};let s=this.formatNextSteps(t).join(" | ");return{valid:!1,error:`Cannot transition to '${e}' from '${t}' state`,suggestion:`Valid next steps: ${s}`}}getNextState(t,e){switch(e){case"task":return"working";case"done":return"completed";case"pause":return"paused";case"resume":return"working";case"ship":return"shipped";case"reopen":return"working";default:return t}}getStateInfo(t){return et[t]}getPrompt(t){return et[t].prompt}getValidCommands(t){return et[t].transitions}formatNextSteps(t){return et[t].transitions.map(r=>{switch(r){case"task":return"prjct task <desc> Start new task";case"done":return"prjct status done Complete current task";case"pause":return"prjct status paused Pause and switch context";case"resume":return"prjct status active Continue paused task";case"ship":return"prjct ship Ship the feature";case"reopen":return"prjct status active Reopen completed task";default:return`prjct ${r}`}})}},zt=new Yt;var rt={SHIPPED_RETENTION_DAYS:90,IDEA_DORMANT_DAYS:180,QUEUE_COMPLETED_DAYS:7,PAUSED_TASK_DAYS:30,MEMORY_MAX_ENTRIES:500},Jt=class{static{c(this,"ArchiveStorage")}archive(t,e){let r=F(),s=f();return y.run(t,"INSERT INTO archives (id, entity_type, entity_id, entity_data, summary, archived_at, reason) VALUES (?, ?, ?, ?, ?, ?, ?)",r,e.entityType,e.entityId,JSON.stringify(e.entityData),e.summary??null,s,e.reason),r}archiveMany(t,e){if(e.length===0)return 0;let r=f();return y.transaction(t,s=>{let i=s.prepare("INSERT INTO archives (id, entity_type, entity_id, entity_data, summary, archived_at, reason) VALUES (?, ?, ?, ?, ?, ?, ?)");for(let o of e)i.run(F(),o.entityType,o.entityId,JSON.stringify(o.entityData),o.summary??null,r,o.reason)}),e.length}getArchived(t,e,r=50){return e?y.query(t,"SELECT * FROM archives WHERE entity_type = ? ORDER BY archived_at DESC LIMIT ?",e,r):y.query(t,"SELECT * FROM archives ORDER BY archived_at DESC LIMIT ?",r)}getStats(t){let e=y.query(t,"SELECT entity_type, COUNT(*) as count FROM archives GROUP BY entity_type"),r={shipped:0,idea:0,queue_task:0,paused_task:0,memory_entry:0,total:0};for(let s of e){let i=s.entity_type;i in r&&(r[i]=s.count),r.total+=s.count}return r}restore(t,e){let r=y.get(t,"SELECT * FROM archives WHERE id = ?",e);return r?(y.run(t,"DELETE FROM archives WHERE id = ?",e),JSON.parse(r.entity_data)):null}pruneOldArchives(t,e){let r=new Date(Date.now()-e*24*60*60*1e3).toISOString(),s=this.getTotalCount(t);y.run(t,"DELETE FROM archives WHERE archived_at < ?",r);let i=this.getTotalCount(t);return s-i}getTotalCount(t){return y.get(t,"SELECT COUNT(*) as count FROM archives")?.count??0}},Y=new Jt;M();var Kt=class{static{c(this,"SyncEventBus")}async publish(t){let e=w.getSyncPendingPath(t.projectId),r=await ot(e,[])??[],s=Array.isArray(r)?r:[];s.push(t),await L(e,s)}async getPending(t){let e=w.getSyncPendingPath(t),r=await ot(e,[])??[];return Array.isArray(r)?r:[]}async clearPending(t){let e=w.getSyncPendingPath(t);await L(e,[])}async updateLastSync(t){let e=w.getLastSyncPath(t),r={timestamp:f(),success:!0};await L(e,r)}async getLastSync(t){let e=w.getLastSyncPath(t);return await ot(e,null)}},fr=new Kt;Pt();var z=class{static{c(this,"StorageManager")}filename;cache;constructor(t,e){this.filename=t,this.cache=new at({ttl:5e3,maxSize:50})}getStoreKey(){return this.filename.replace(".json","")}async read(t){let e=this.cache.get(t);if(e!==null)return e;try{let r=y.getDoc(t,this.getStoreKey());if(r!==null)return this.cache.set(t,r),r}catch{}return this.getDefault()}async write(t,e){y.setDoc(t,this.getStoreKey(),e),this.cache.set(t,e)}async update(t,e){let r=await this.read(t),s=e(r);return await this.write(t,s),s}async publishEvent(t,e,r){let s={type:e,path:[this.filename.replace(".json","")],data:r,timestamp:f(),projectId:t};await fr.publish(s)}async publishEntityEvent(t,e,r,s){let i=`${e}.${r}`,o={...s,timestamp:f()};await this.publishEvent(t,i,o)}async exists(t){try{return y.hasDoc(t,this.getStoreKey())}catch{return!1}}clearCache(t){t?this.cache.delete(t):this.cache.clear()}getCacheStats(){return this.cache.stats()}};var Vt=class extends z{static{c(this,"StateStorage")}constructor(){super("state.json",mr)}getDefault(){return{currentTask:null,previousTask:null,pausedTasks:[],taskHistory:[],activeTasks:[],lastUpdated:""}}getEventType(t){return`state.${t}d`}validateTransition(t,e){let r=zt.getCurrentState(t),s=zt.canTransition(r,e);if(!s.valid)throw new Error(`${s.error}. ${s.suggestion||""}`.trim())}async getCurrentTask(t){return(await this.read(t)).currentTask}async getPausedTasks(t){let e=await this.read(t);return this.getPausedTasksFromState(e)}async startTask(t,e){let r=await this.read(t);this.validateTransition(r,"task");let s={...e,startedAt:f()};return await this.update(t,i=>({...i,currentTask:s,lastUpdated:f()})),await this.publishEvent(t,"task.started",{taskId:s.id,description:s.description,startedAt:s.startedAt,sessionId:s.sessionId}),s}async updateCurrentTask(t,e){let r=await this.read(t);if(!r.currentTask)return null;let s={...r.currentTask,...e};return await this.update(t,i=>({...i,currentTask:s,lastUpdated:f()})),s}async completeTask(t,e){let r=await this.read(t),s=r.currentTask;if(!s)return null;this.validateTransition(r,"done");let i=f(),o=this.createTaskHistoryEntry(s,i,e),a=this.getTaskHistoryFromState(r),u=[o,...a].slice(0,this.maxTaskHistory);return await this.update(t,d=>({...d,currentTask:null,previousTask:null,taskHistory:u,lastUpdated:i})),await this.publishEvent(t,"task.completed",{taskId:s.id,description:s.description,startedAt:s.startedAt,completedAt:i}),s}createTaskHistoryEntry(t,e,r){let s=(t.subtasks||[]).filter(a=>a.status==="completed"&&a.summary).map(a=>a.summary),i=s.length>0?s.map(a=>a.title).join(", "):"Task completed",o={taskId:t.id,title:t.parentDescription||t.description,classification:t.type||"improvement",startedAt:t.startedAt,completedAt:e,subtaskCount:t.subtasks?.length||0,subtaskSummaries:s,outcome:i,branchName:t.branch||"unknown",linearId:t.linearId,linearUuid:t.linearUuid,prUrl:t.prUrl};return r&&(o.feedback=r),t.tokensIn&&(o.tokensIn=t.tokensIn),t.tokensOut&&(o.tokensOut=t.tokensOut),o}maxPausedTasks=5;maxTaskHistory=20;stalenessThresholdDays=30;async pauseTask(t,e){let r=await this.read(t);if(!r.currentTask)return null;this.validateTransition(r,"pause");let s={...r.currentTask,status:"paused",pausedAt:f(),pauseReason:e},i=this.getPausedTasksFromState(r),o=[s,...i].slice(0,this.maxPausedTasks);return await this.update(t,a=>({...a,currentTask:null,previousTask:null,pausedTasks:o,lastUpdated:f()})),await this.publishEvent(t,"task.paused",{taskId:s.id,description:s.description,pausedAt:s.pausedAt,reason:e,pausedCount:o.length}),s}async resumeTask(t,e){let r=await this.read(t),s=this.getPausedTasksFromState(r);if(s.length===0)return null;this.validateTransition(r,"resume");let i=0;if(e&&(i=s.findIndex(T=>T.id===e),i===-1))return null;let o=s[i],a=s.filter((T,D)=>D!==i),{status:u,pausedAt:d,pauseReason:m,...p}=o,g={...p,startedAt:f(),sessionId:o.sessionId??F()};return await this.update(t,T=>({...T,currentTask:g,previousTask:null,pausedTasks:a,lastUpdated:f()})),await this.publishEvent(t,"task.resumed",{taskId:g.id,description:g.description,resumedAt:g.startedAt,remainingPaused:a.length}),g}getPausedTasksFromState(t){return Array.isArray(t.pausedTasks)&&t.pausedTasks.length>0?t.pausedTasks:t.previousTask?[t.previousTask]:[]}getTaskHistoryFromState(t){return t.taskHistory||[]}async getStalePausedTasks(t){let e=await this.read(t),r=this.getPausedTasksFromState(e),s=Date.now()-this.stalenessThresholdDays*24*60*60*1e3;return r.filter(i=>new Date(i.pausedAt).getTime()<s)}async archiveStalePausedTasks(t){let e=await this.read(t),r=this.getPausedTasksFromState(e),s=Date.now()-this.stalenessThresholdDays*24*60*60*1e3,i=r.filter(a=>new Date(a.pausedAt).getTime()<s),o=r.filter(a=>new Date(a.pausedAt).getTime()>=s);if(i.length===0)return[];Y.archiveMany(t,i.map(a=>({entityType:"paused_task",entityId:a.id,entityData:a,summary:a.description,reason:"staleness"}))),await this.update(t,a=>({...a,pausedTasks:o,previousTask:null,lastUpdated:f()}));for(let a of i)await this.publishEvent(t,"task.archived",{taskId:a.id,description:a.description,pausedAt:a.pausedAt,reason:"staleness"});return i}async clearTask(t){await this.update(t,()=>({currentTask:null,previousTask:null,pausedTasks:[],activeTasks:[],lastUpdated:f()}))}async hasTask(t){let e=await this.read(t),r=this.getPausedTasksFromState(e);return e.currentTask!==null||r.length>0}async getPausedTask(t){let e=await this.read(t);return this.getPausedTasksFromState(e)[0]||null}async getAllPausedTasks(t){let e=await this.read(t);return this.getPausedTasksFromState(e)}async getTaskHistory(t){let e=await this.read(t);return this.getTaskHistoryFromState(e)}async getMostRecentTask(t){let e=await this.read(t);return this.getTaskHistoryFromState(e)[0]||null}async getTaskHistoryByType(t,e){let r=await this.read(t);return this.getTaskHistoryFromState(r).filter(i=>i.classification===e)}async getAggregatedFeedback(t){let r=(await this.getTaskHistory(t)).filter(g=>g.feedback),s=[],i=[],o=[],a=[];for(let g of r){let T=g.feedback;Array.isArray(T.stackConfirmed)&&s.push(...T.stackConfirmed),Array.isArray(T.patternsDiscovered)&&i.push(...T.patternsDiscovered),Array.isArray(T.agentAccuracy)&&o.push(...T.agentAccuracy),Array.isArray(T.issuesEncountered)&&a.push(...T.issuesEncountered)}let u=[...new Set(s)],d=[...new Set(i)],m=new Map;for(let g of a)m.set(g,(m.get(g)||0)+1);let p=[...m.entries()].filter(([g,T])=>T>=2).map(([g])=>g);return{stackConfirmed:u,patternsDiscovered:d,agentAccuracy:o,issuesEncountered:[...new Set(a)],knownGotchas:p}}async startTaskInWorkspace(t,e,r){let s={...e,workspaceId:r,startedAt:f()};return await this.update(t,i=>({...i,activeTasks:[...i.activeTasks||[],s],lastUpdated:f()})),await this.publishEvent(t,"task.started",{taskId:s.id,description:s.description,startedAt:s.startedAt,sessionId:s.sessionId,workspaceId:r}),s}async getCurrentTaskForWorkspace(t,e){return((await this.read(t)).activeTasks||[]).find(s=>s.workspaceId===e)??null}async completeTaskInWorkspace(t,e,r){let s=await this.read(t),o=(s.activeTasks||[]).find(p=>p.workspaceId===e);if(!o)return null;let a=f(),u=this.createTaskHistoryEntry(o,a,r),d=this.getTaskHistoryFromState(s),m=[u,...d].slice(0,this.maxTaskHistory);return await this.update(t,p=>({...p,activeTasks:(p.activeTasks||[]).filter(g=>g.workspaceId!==e),taskHistory:m,lastUpdated:a})),await this.publishEvent(t,"task.completed",{taskId:o.id,description:o.description,startedAt:o.startedAt,completedAt:a,workspaceId:e}),o}async getActiveTasks(t){return(await this.read(t)).activeTasks||[]}async getActiveTaskCount(t){return((await this.read(t)).activeTasks||[]).length}async updateWorkspaceTask(t,e,r){let i=(await this.read(t)).activeTasks||[],o=i.findIndex(u=>u.workspaceId===e);if(o===-1)return null;let a={...i[o],...r,workspaceId:e};return await this.update(t,u=>{let d=[...u.activeTasks||[]];return d[o]=a,{...u,activeTasks:d,lastUpdated:f()}}),a}async addTokens(t,e,r){let s=await this.read(t);if(!s.currentTask)return null;let i=(s.currentTask.tokensIn||0)+e,o=(s.currentTask.tokensOut||0)+r;return await this.update(t,a=>({...a,currentTask:{...a.currentTask,tokensIn:i,tokensOut:o},lastUpdated:f()})),{tokensIn:i,tokensOut:o}}async createSubtasks(t,e){let r=await this.read(t);if(!r.currentTask)return;let s=e.map((i,o)=>({...i,status:o===0?"in_progress":"pending",startedAt:o===0?f():void 0,dependsOn:i.dependsOn||[]}));await this.update(t,i=>({...i,currentTask:{...i.currentTask,subtasks:s,currentSubtaskIndex:0,subtaskProgress:{completed:0,total:s.length,percentage:0}},lastUpdated:f()})),await this.publishEvent(t,"subtasks.created",{taskId:r.currentTask.id,subtaskCount:s.length,subtasks:s.map(i=>({id:i.id,description:i.description,domain:i.domain}))})}async completeSubtask(t,e){let r=ur.safeParse(e);if(!r.success){let D=r.error.issues.map(nt=>`${nt.path.join(".")}: ${nt.message}`);throw new Error(`Subtask completion requires handoff data:
|
|
501
|
+
`)}]}})),t.tool("prjct_cochange","Files that historically change together (Jaccard similarity from git history)",{projectPath:R.string().describe("Project directory path"),seedFiles:R.array(R.string()).describe("Seed files to find co-change partners for"),rebuild:R.boolean().optional().default(!1).describe("Force rebuild the co-change matrix"),maxResults:R.number().optional().default(10).describe("Max results (default 10)")},b("prjct_cochange",async e=>{let r=await v(e.projectPath),s=e.rebuild?null:Xt(r);s||(s=await Ze(e.projectPath,r));let i=Ut(e.seedFiles,s).slice(0,e.maxResults);if(i.length===0)return{content:[{type:"text",text:"No co-change partners found."}]};let o=["## Co-Change Partners",`Seeds: ${e.seedFiles.join(", ")}`,`Commits analyzed: ${s.commitsAnalyzed}`,""];for(let a of i)o.push(`- ${a.path} (similarity: ${Math.round(a.score*100)}%)`);return{content:[{type:"text",text:o.join(`
|
|
502
|
+
`)}]}})),t.tool("prjct_related_context","Combined: import neighbors + co-change partners for seed files",{projectPath:R.string().describe("Project directory path"),seedFiles:R.array(R.string()).describe("Seed files to find related context for"),maxResults:R.number().optional().default(15).describe("Max results (default 15)")},b("prjct_related_context",async e=>{let r=await v(e.projectPath),s=tt(r),i=s?Ye(e.seedFiles,s):[],o=Xt(r),a=o?Ut(e.seedFiles,o):[],u=new Map;for(let p of i)u.set(p.path,{importScore:p.score,cochangeScore:0});for(let p of a){let g=u.get(p.path);g?g.cochangeScore=p.score:u.set(p.path,{importScore:0,cochangeScore:p.score})}let d=Array.from(u.entries()).map(([p,g])=>({path:p,combined:g.importScore*.6+g.cochangeScore*.4,importScore:g.importScore,cochangeScore:g.cochangeScore})).sort((p,g)=>g.combined-p.combined).slice(0,e.maxResults);if(d.length===0)return{content:[{type:"text",text:"No related files found. Run `prjct sync` to build indexes."}]};let m=["## Related Context",`Seeds: ${e.seedFiles.join(", ")}`,""];for(let p of d){let g=[];p.importScore>0&&g.push(`import: ${p.importScore.toFixed(2)}`),p.cochangeScore>0&&g.push(`cochange: ${Math.round(p.cochangeScore*100)}%`),m.push(`- ${p.path} (${g.join(", ")})`)}return{content:[{type:"text",text:m.join(`
|
|
503
|
+
`)}]}}))}c(ar,"registerCodeIntelTools");import{z as W}from"zod";import Is from"node:crypto";function F(){return Is.randomUUID()}c(F,"generateUUID");At();import{z as l}from"zod";var Ds=l.enum(["low","medium","high","critical"]),yt=l.enum(["feature","bug","improvement","chore"]),Ls=l.enum(["active","backlog","previously_active"]),Os=l.enum(["pending","in_progress","completed","blocked","paused","failed","skipped"]),Jt=l.object({title:l.string(),description:l.string(),filesChanged:l.array(l.object({path:l.string(),action:l.enum(["created","modified","deleted"])})),whatWasDone:l.array(l.string()).min(1),outputForNextAgent:l.string().min(1),notes:l.string().optional()}),ur=l.object({output:l.string().min(1,"Subtask output is required"),summary:Jt}),lr=l.object({id:l.string(),description:l.string(),domain:l.string(),agent:l.string(),status:Os,dependsOn:l.array(l.string()),startedAt:l.string().optional(),completedAt:l.string().optional(),output:l.string().optional(),summary:Jt.optional(),skipReason:l.string().optional(),blockReason:l.string().optional(),estimatedPoints:l.number().optional(),estimatedMinutes:l.number().optional()}),dr=l.object({completed:l.number(),total:l.number(),percentage:l.number()}),pr=l.object({id:l.string(),description:l.string(),type:yt.optional(),startedAt:l.string(),sessionId:l.string(),featureId:l.string().optional(),subtasks:l.array(lr).optional(),currentSubtaskIndex:l.number().optional(),subtaskProgress:dr.optional(),linearId:l.string().optional(),linearUuid:l.string().optional(),estimatedPoints:l.number().optional(),estimatedMinutes:l.number().optional(),modelMetadata:Pt.optional(),tokensIn:l.number().optional(),tokensOut:l.number().optional(),parentDescription:l.string().optional(),branch:l.string().optional(),prUrl:l.string().optional()}),cr=l.object({id:l.string(),description:l.string(),status:l.literal("paused"),startedAt:l.string(),pausedAt:l.string(),pauseReason:l.string().optional(),type:yt.optional(),sessionId:l.string().optional(),featureId:l.string().optional(),subtasks:l.array(lr).optional(),currentSubtaskIndex:l.number().optional(),subtaskProgress:dr.optional(),linearId:l.string().optional(),linearUuid:l.string().optional(),estimatedPoints:l.number().optional(),estimatedMinutes:l.number().optional(),modelMetadata:Pt.optional(),tokensIn:l.number().optional(),tokensOut:l.number().optional()}),Ms=l.object({stackConfirmed:l.array(l.string()).optional(),patternsDiscovered:l.array(l.string()).optional(),agentAccuracy:l.array(l.object({agent:l.string(),rating:l.enum(["helpful","neutral","inaccurate"]),note:l.string().optional()})).optional(),issuesEncountered:l.array(l.string()).optional()}),js=l.object({taskId:l.string(),title:l.string(),classification:yt,startedAt:l.string(),completedAt:l.string(),subtaskCount:l.number(),subtaskSummaries:l.array(Jt),outcome:l.string(),branchName:l.string(),linearId:l.string().optional(),linearUuid:l.string().optional(),prUrl:l.string().optional(),feedback:Ms.optional(),tokensIn:l.number().optional(),tokensOut:l.number().optional()}),Fs=pr.extend({workspaceId:l.string(),worktreePath:l.string().optional(),agentSessionId:l.string().optional(),jiraId:l.string().optional(),jiraUuid:l.string().optional(),dispatchedFrom:l.string().optional()}),mr=l.object({currentTask:pr.nullable(),previousTask:cr.nullable().optional(),pausedTasks:l.array(cr).optional(),taskHistory:l.array(js).optional(),activeTasks:l.array(Fs).optional(),lastUpdated:l.string()}),Us=l.object({id:l.string(),description:l.string(),body:l.string().optional(),priority:Ds,type:yt,featureId:l.string().optional(),originFeature:l.string().optional(),completed:l.boolean(),completedAt:l.string().optional(),createdAt:l.string(),section:Ls,agent:l.string().optional(),groupName:l.string().optional(),groupId:l.string().optional()}),gr=l.object({tasks:l.array(Us),lastUpdated:l.string()});var rt={idle:{transitions:["task"],prompt:"prjct task <description> Start working",description:"No active task"},working:{transitions:["done","pause"],prompt:"prjct status done Complete task | prjct status paused Switch context",description:"Task in progress"},paused:{transitions:["resume","task","ship"],prompt:"prjct status active Continue | prjct task <new> Start different | prjct ship Ship directly",description:"Task paused"},completed:{transitions:["ship","task","pause","reopen"],prompt:"prjct ship Ship it | prjct task <next> Start next | prjct status active Reopen",description:"Task completed"},shipped:{transitions:["task"],prompt:"prjct task <description> Start new task",description:"Feature shipped"}},Kt=class{static{c(this,"WorkflowStateMachine")}getCurrentState(t,e){let r=null;if(e&&t?.activeTasks?.length&&(r=t.activeTasks.find(i=>i.workspaceId===e)),r||(r=t?.currentTask),!r)return(t?.pausedTasks?.length||0)>0||t?.previousTask?.status==="paused"?"paused":"idle";switch((typeof r.status=="string"?r.status:"").toLowerCase()){case"in_progress":case"working":return"working";case"paused":return"paused";case"completed":case"done":return"completed";case"shipped":return"shipped";default:return r?"working":"idle"}}canTransition(t,e){if(rt[t].transitions.includes(e))return{valid:!0};let s=this.formatNextSteps(t).join(" | ");return{valid:!1,error:`Cannot transition to '${e}' from '${t}' state`,suggestion:`Valid next steps: ${s}`}}getNextState(t,e){switch(e){case"task":return"working";case"done":return"completed";case"pause":return"paused";case"resume":return"working";case"ship":return"shipped";case"reopen":return"working";default:return t}}getStateInfo(t){return rt[t]}getPrompt(t){return rt[t].prompt}getValidCommands(t){return rt[t].transitions}formatNextSteps(t){return rt[t].transitions.map(r=>{switch(r){case"task":return"prjct task <desc> Start new task";case"done":return"prjct status done Complete current task";case"pause":return"prjct status paused Pause and switch context";case"resume":return"prjct status active Continue paused task";case"ship":return"prjct ship Ship the feature";case"reopen":return"prjct status active Reopen completed task";default:return`prjct ${r}`}})}},Vt=new Kt;var st={SHIPPED_RETENTION_DAYS:90,IDEA_DORMANT_DAYS:180,QUEUE_COMPLETED_DAYS:7,PAUSED_TASK_DAYS:30,MEMORY_MAX_ENTRIES:500},Qt=class{static{c(this,"ArchiveStorage")}archive(t,e){let r=F(),s=f();return y.run(t,"INSERT INTO archives (id, entity_type, entity_id, entity_data, summary, archived_at, reason) VALUES (?, ?, ?, ?, ?, ?, ?)",r,e.entityType,e.entityId,JSON.stringify(e.entityData),e.summary??null,s,e.reason),r}archiveMany(t,e){if(e.length===0)return 0;let r=f();return y.transaction(t,s=>{let i=s.prepare("INSERT INTO archives (id, entity_type, entity_id, entity_data, summary, archived_at, reason) VALUES (?, ?, ?, ?, ?, ?, ?)");for(let o of e)i.run(F(),o.entityType,o.entityId,JSON.stringify(o.entityData),o.summary??null,r,o.reason)}),e.length}getArchived(t,e,r=50){return e?y.query(t,"SELECT * FROM archives WHERE entity_type = ? ORDER BY archived_at DESC LIMIT ?",e,r):y.query(t,"SELECT * FROM archives ORDER BY archived_at DESC LIMIT ?",r)}getStats(t){let e=y.query(t,"SELECT entity_type, COUNT(*) as count FROM archives GROUP BY entity_type"),r={shipped:0,idea:0,queue_task:0,paused_task:0,memory_entry:0,total:0};for(let s of e){let i=s.entity_type;i in r&&(r[i]=s.count),r.total+=s.count}return r}restore(t,e){let r=y.get(t,"SELECT * FROM archives WHERE id = ?",e);return r?(y.run(t,"DELETE FROM archives WHERE id = ?",e),JSON.parse(r.entity_data)):null}pruneOldArchives(t,e){let r=new Date(Date.now()-e*24*60*60*1e3).toISOString(),s=this.getTotalCount(t);y.run(t,"DELETE FROM archives WHERE archived_at < ?",r);let i=this.getTotalCount(t);return s-i}getTotalCount(t){return y.get(t,"SELECT COUNT(*) as count FROM archives")?.count??0}},Y=new Qt;M();var Zt=class{static{c(this,"SyncEventBus")}async publish(t){let e=w.getSyncPendingPath(t.projectId),r=await at(e,[])??[],s=Array.isArray(r)?r:[];s.push(t),await L(e,s)}async getPending(t){let e=w.getSyncPendingPath(t),r=await at(e,[])??[];return Array.isArray(r)?r:[]}async clearPending(t){let e=w.getSyncPendingPath(t);await L(e,[])}async updateLastSync(t){let e=w.getLastSyncPath(t),r={timestamp:f(),success:!0};await L(e,r)}async getLastSync(t){let e=w.getLastSyncPath(t);return await at(e,null)}},fr=new Zt;Nt();var z=class{static{c(this,"StorageManager")}filename;cache;constructor(t,e){this.filename=t,this.cache=new ct({ttl:5e3,maxSize:50})}getStoreKey(){return this.filename.replace(".json","")}async read(t){let e=this.cache.get(t);if(e!==null)return e;try{let r=y.getDoc(t,this.getStoreKey());if(r!==null)return this.cache.set(t,r),r}catch{}return this.getDefault()}async write(t,e){y.setDoc(t,this.getStoreKey(),e),this.cache.set(t,e)}async update(t,e){let r=await this.read(t),s=e(r);return await this.write(t,s),s}async publishEvent(t,e,r){let s={type:e,path:[this.filename.replace(".json","")],data:r,timestamp:f(),projectId:t};await fr.publish(s)}async publishEntityEvent(t,e,r,s){let i=`${e}.${r}`,o={...s,timestamp:f()};await this.publishEvent(t,i,o)}async exists(t){try{return y.hasDoc(t,this.getStoreKey())}catch{return!1}}clearCache(t){t?this.cache.delete(t):this.cache.clear()}getCacheStats(){return this.cache.stats()}};var te=class extends z{static{c(this,"StateStorage")}constructor(){super("state.json",mr)}getDefault(){return{currentTask:null,previousTask:null,pausedTasks:[],taskHistory:[],activeTasks:[],lastUpdated:""}}getEventType(t){return`state.${t}d`}validateTransition(t,e){let r=Vt.getCurrentState(t),s=Vt.canTransition(r,e);if(!s.valid)throw new Error(`${s.error}. ${s.suggestion||""}`.trim())}async getCurrentTask(t){return(await this.read(t)).currentTask}async getPausedTasks(t){let e=await this.read(t);return this.getPausedTasksFromState(e)}async startTask(t,e){let r=await this.read(t);this.validateTransition(r,"task");let s={...e,startedAt:f()};return await this.update(t,i=>({...i,currentTask:s,lastUpdated:f()})),await this.publishEvent(t,"task.started",{taskId:s.id,description:s.description,startedAt:s.startedAt,sessionId:s.sessionId}),s}async updateCurrentTask(t,e){let r=await this.read(t);if(!r.currentTask)return null;let s={...r.currentTask,...e};return await this.update(t,i=>({...i,currentTask:s,lastUpdated:f()})),s}async completeTask(t,e){let r=await this.read(t),s=r.currentTask;if(!s)return null;this.validateTransition(r,"done");let i=f(),o=this.createTaskHistoryEntry(s,i,e),a=this.getTaskHistoryFromState(r),u=[o,...a].slice(0,this.maxTaskHistory);return await this.update(t,d=>({...d,currentTask:null,previousTask:null,taskHistory:u,lastUpdated:i})),await this.publishEvent(t,"task.completed",{taskId:s.id,description:s.description,startedAt:s.startedAt,completedAt:i}),s}createTaskHistoryEntry(t,e,r){let s=(t.subtasks||[]).filter(a=>a.status==="completed"&&a.summary).map(a=>a.summary),i=s.length>0?s.map(a=>a.title).join(", "):"Task completed",o={taskId:t.id,title:t.parentDescription||t.description,classification:t.type||"improvement",startedAt:t.startedAt,completedAt:e,subtaskCount:t.subtasks?.length||0,subtaskSummaries:s,outcome:i,branchName:t.branch||"unknown",linearId:t.linearId,linearUuid:t.linearUuid,prUrl:t.prUrl};return r&&(o.feedback=r),t.tokensIn&&(o.tokensIn=t.tokensIn),t.tokensOut&&(o.tokensOut=t.tokensOut),o}maxPausedTasks=5;maxTaskHistory=20;stalenessThresholdDays=30;async pauseTask(t,e){let r=await this.read(t);if(!r.currentTask)return null;this.validateTransition(r,"pause");let s={...r.currentTask,status:"paused",pausedAt:f(),pauseReason:e},i=this.getPausedTasksFromState(r),o=[s,...i].slice(0,this.maxPausedTasks);return await this.update(t,a=>({...a,currentTask:null,previousTask:null,pausedTasks:o,lastUpdated:f()})),await this.publishEvent(t,"task.paused",{taskId:s.id,description:s.description,pausedAt:s.pausedAt,reason:e,pausedCount:o.length}),s}async resumeTask(t,e){let r=await this.read(t),s=this.getPausedTasksFromState(r);if(s.length===0)return null;this.validateTransition(r,"resume");let i=0;if(e&&(i=s.findIndex(T=>T.id===e),i===-1))return null;let o=s[i],a=s.filter((T,D)=>D!==i),{status:u,pausedAt:d,pauseReason:m,...p}=o,g={...p,startedAt:f(),sessionId:o.sessionId??F()};return await this.update(t,T=>({...T,currentTask:g,previousTask:null,pausedTasks:a,lastUpdated:f()})),await this.publishEvent(t,"task.resumed",{taskId:g.id,description:g.description,resumedAt:g.startedAt,remainingPaused:a.length}),g}getPausedTasksFromState(t){return Array.isArray(t.pausedTasks)&&t.pausedTasks.length>0?t.pausedTasks:t.previousTask?[t.previousTask]:[]}getTaskHistoryFromState(t){return t.taskHistory||[]}async getStalePausedTasks(t){let e=await this.read(t),r=this.getPausedTasksFromState(e),s=Date.now()-this.stalenessThresholdDays*24*60*60*1e3;return r.filter(i=>new Date(i.pausedAt).getTime()<s)}async archiveStalePausedTasks(t){let e=await this.read(t),r=this.getPausedTasksFromState(e),s=Date.now()-this.stalenessThresholdDays*24*60*60*1e3,i=r.filter(a=>new Date(a.pausedAt).getTime()<s),o=r.filter(a=>new Date(a.pausedAt).getTime()>=s);if(i.length===0)return[];Y.archiveMany(t,i.map(a=>({entityType:"paused_task",entityId:a.id,entityData:a,summary:a.description,reason:"staleness"}))),await this.update(t,a=>({...a,pausedTasks:o,previousTask:null,lastUpdated:f()}));for(let a of i)await this.publishEvent(t,"task.archived",{taskId:a.id,description:a.description,pausedAt:a.pausedAt,reason:"staleness"});return i}async clearTask(t){await this.update(t,()=>({currentTask:null,previousTask:null,pausedTasks:[],activeTasks:[],lastUpdated:f()}))}async hasTask(t){let e=await this.read(t),r=this.getPausedTasksFromState(e);return e.currentTask!==null||r.length>0}async getPausedTask(t){let e=await this.read(t);return this.getPausedTasksFromState(e)[0]||null}async getAllPausedTasks(t){let e=await this.read(t);return this.getPausedTasksFromState(e)}async getTaskHistory(t){let e=await this.read(t);return this.getTaskHistoryFromState(e)}async getMostRecentTask(t){let e=await this.read(t);return this.getTaskHistoryFromState(e)[0]||null}async getTaskHistoryByType(t,e){let r=await this.read(t);return this.getTaskHistoryFromState(r).filter(i=>i.classification===e)}async getAggregatedFeedback(t){let r=(await this.getTaskHistory(t)).filter(g=>g.feedback),s=[],i=[],o=[],a=[];for(let g of r){let T=g.feedback;Array.isArray(T.stackConfirmed)&&s.push(...T.stackConfirmed),Array.isArray(T.patternsDiscovered)&&i.push(...T.patternsDiscovered),Array.isArray(T.agentAccuracy)&&o.push(...T.agentAccuracy),Array.isArray(T.issuesEncountered)&&a.push(...T.issuesEncountered)}let u=[...new Set(s)],d=[...new Set(i)],m=new Map;for(let g of a)m.set(g,(m.get(g)||0)+1);let p=[...m.entries()].filter(([g,T])=>T>=2).map(([g])=>g);return{stackConfirmed:u,patternsDiscovered:d,agentAccuracy:o,issuesEncountered:[...new Set(a)],knownGotchas:p}}async startTaskInWorkspace(t,e,r){let s={...e,workspaceId:r,startedAt:f()};return await this.update(t,i=>({...i,activeTasks:[...i.activeTasks||[],s],lastUpdated:f()})),await this.publishEvent(t,"task.started",{taskId:s.id,description:s.description,startedAt:s.startedAt,sessionId:s.sessionId,workspaceId:r}),s}async getCurrentTaskForWorkspace(t,e){return((await this.read(t)).activeTasks||[]).find(s=>s.workspaceId===e)??null}async completeTaskInWorkspace(t,e,r){let s=await this.read(t),o=(s.activeTasks||[]).find(p=>p.workspaceId===e);if(!o)return null;let a=f(),u=this.createTaskHistoryEntry(o,a,r),d=this.getTaskHistoryFromState(s),m=[u,...d].slice(0,this.maxTaskHistory);return await this.update(t,p=>({...p,activeTasks:(p.activeTasks||[]).filter(g=>g.workspaceId!==e),taskHistory:m,lastUpdated:a})),await this.publishEvent(t,"task.completed",{taskId:o.id,description:o.description,startedAt:o.startedAt,completedAt:a,workspaceId:e}),o}async getActiveTasks(t){return(await this.read(t)).activeTasks||[]}async getActiveTaskCount(t){return((await this.read(t)).activeTasks||[]).length}async updateWorkspaceTask(t,e,r){let i=(await this.read(t)).activeTasks||[],o=i.findIndex(u=>u.workspaceId===e);if(o===-1)return null;let a={...i[o],...r,workspaceId:e};return await this.update(t,u=>{let d=[...u.activeTasks||[]];return d[o]=a,{...u,activeTasks:d,lastUpdated:f()}}),a}async addTokens(t,e,r){let s=await this.read(t);if(!s.currentTask)return null;let i=(s.currentTask.tokensIn||0)+e,o=(s.currentTask.tokensOut||0)+r;return await this.update(t,a=>({...a,currentTask:{...a.currentTask,tokensIn:i,tokensOut:o},lastUpdated:f()})),{tokensIn:i,tokensOut:o}}async createSubtasks(t,e){let r=await this.read(t);if(!r.currentTask)return;let s=e.map((i,o)=>({...i,status:o===0?"in_progress":"pending",startedAt:o===0?f():void 0,dependsOn:i.dependsOn||[]}));await this.update(t,i=>({...i,currentTask:{...i.currentTask,subtasks:s,currentSubtaskIndex:0,subtaskProgress:{completed:0,total:s.length,percentage:0}},lastUpdated:f()})),await this.publishEvent(t,"subtasks.created",{taskId:r.currentTask.id,subtaskCount:s.length,subtasks:s.map(i=>({id:i.id,description:i.description,domain:i.domain}))})}async completeSubtask(t,e){let r=ur.safeParse(e);if(!r.success){let D=r.error.issues.map(it=>`${it.path.join(".")}: ${it.message}`);throw new Error(`Subtask completion requires handoff data:
|
|
504
504
|
${D.join(`
|
|
505
|
-
`)}`)}let{output:s,summary:i}=r.data,o=await this.read(t);if(!o.currentTask?.subtasks)return null;let a=o.currentTask.currentSubtaskIndex||0,u=o.currentTask.subtasks[a];if(!u)return null;let d=[...o.currentTask.subtasks];d[a]={...u,status:"completed",completedAt:f(),output:s,summary:i};let m=d.filter(D=>D.status==="completed").length,p=d.length,g=Math.round(m/p*100),T=a+1;return T<d.length&&(d[T]={...d[T],status:"in_progress",startedAt:f()}),await this.update(t,D=>({...D,currentTask:{...D.currentTask,subtasks:d,currentSubtaskIndex:T<p?T:a,subtaskProgress:{completed:m,total:p,percentage:g}},lastUpdated:f()})),await this.publishEvent(t,"subtask.completed",{taskId:o.currentTask.id,subtaskId:u.id,description:u.description,output:s,handoff:i.outputForNextAgent,filesChanged:i.filesChanged.length,progress:{completed:m,total:p,percentage:g}}),T<p?d[T]:null}async getCurrentSubtask(t){let e=await this.read(t);if(!e.currentTask?.subtasks)return null;let r=e.currentTask.currentSubtaskIndex||0;return e.currentTask.subtasks[r]||null}async getNextSubtask(t){let e=await this.read(t);if(!e.currentTask?.subtasks)return null;let r=(e.currentTask.currentSubtaskIndex||0)+1;return e.currentTask.subtasks[r]||null}async getPreviousSubtask(t){let e=await this.read(t);if(!e.currentTask?.subtasks)return null;let r=(e.currentTask.currentSubtaskIndex||0)-1;return r<0?null:e.currentTask.subtasks[r]||null}async getPreviousHandoff(t){let e=await this.getPreviousSubtask(t);return e?.summary?.outputForNextAgent?{fromSubtask:e.description,outputForNextAgent:e.summary.outputForNextAgent,filesChanged:e.summary.filesChanged,whatWasDone:e.summary.whatWasDone}:null}async getSubtasks(t){return(await this.read(t)).currentTask?.subtasks||[]}async getSubtaskProgress(t){return(await this.read(t)).currentTask?.subtaskProgress||null}async hasSubtasks(t){return((await this.read(t)).currentTask?.subtasks?.length||0)>0}async areAllSubtasksComplete(t){let e=await this.read(t);return e.currentTask?.subtasks?e.currentTask.subtasks.every(r=>r.status==="completed"||r.status==="failed"||r.status==="skipped"):!0}async failSubtask(t,e){let r=await this.read(t);if(!r.currentTask?.subtasks)return null;let s=r.currentTask.currentSubtaskIndex||0,i=r.currentTask.subtasks[s];if(!i)return null;let o=[...r.currentTask.subtasks];o[s]={...i,status:"failed",completedAt:f(),output:`Failed: ${e}`};let a=s+1,u=o.length;a<u&&(o[a]={...o[a],status:"in_progress",startedAt:f()});let d=o.filter(p=>p.status==="completed"||p.status==="failed"||p.status==="skipped").length,m=Math.round(d/u*100);return await this.update(t,p=>({...p,currentTask:{...p.currentTask,subtasks:o,currentSubtaskIndex:a<u?a:s,subtaskProgress:{completed:d,total:u,percentage:m}},lastUpdated:f()})),await this.publishEvent(t,"subtask.failed",{taskId:r.currentTask.id,subtaskId:i.id,description:i.description,error:e}),a<u?o[a]:null}async skipSubtask(t,e){let r=await this.read(t);if(!r.currentTask?.subtasks)return null;let s=r.currentTask.currentSubtaskIndex||0,i=r.currentTask.subtasks[s];if(!i)return null;let o=[...r.currentTask.subtasks];o[s]={...i,status:"skipped",completedAt:f(),output:`Skipped: ${e}`,skipReason:e};let a=s+1,u=o.length;a<u&&(o[a]={...o[a],status:"in_progress",startedAt:f()});let d=o.filter(p=>p.status==="completed"||p.status==="failed"||p.status==="skipped").length,m=Math.round(d/u*100);return await this.update(t,p=>({...p,currentTask:{...p.currentTask,subtasks:o,currentSubtaskIndex:a<u?a:s,subtaskProgress:{completed:d,total:u,percentage:m}},lastUpdated:f()})),await this.publishEvent(t,"subtask.skipped",{taskId:r.currentTask.id,subtaskId:i.id,description:i.description,reason:e}),a<u?o[a]:null}async blockSubtask(t,e){let r=await this.read(t);if(!r.currentTask?.subtasks)return null;let s=r.currentTask.currentSubtaskIndex||0,i=r.currentTask.subtasks[s];if(!i)return null;let o=[...r.currentTask.subtasks];o[s]={...i,status:"blocked",output:`Blocked: ${e}`,blockReason:e};let a=s+1,u=o.length;return a<u&&(o[a]={...o[a],status:"in_progress",startedAt:f()}),await this.update(t,d=>({...d,currentTask:{...d.currentTask,subtasks:o,currentSubtaskIndex:a<u?a:s},lastUpdated:f()})),await this.publishEvent(t,"subtask.blocked",{taskId:r.currentTask.id,subtaskId:i.id,description:i.description,blocker:e}),a<u?o[a]:null}},J=new
|
|
505
|
+
`)}`)}let{output:s,summary:i}=r.data,o=await this.read(t);if(!o.currentTask?.subtasks)return null;let a=o.currentTask.currentSubtaskIndex||0,u=o.currentTask.subtasks[a];if(!u)return null;let d=[...o.currentTask.subtasks];d[a]={...u,status:"completed",completedAt:f(),output:s,summary:i};let m=d.filter(D=>D.status==="completed").length,p=d.length,g=Math.round(m/p*100),T=a+1;return T<d.length&&(d[T]={...d[T],status:"in_progress",startedAt:f()}),await this.update(t,D=>({...D,currentTask:{...D.currentTask,subtasks:d,currentSubtaskIndex:T<p?T:a,subtaskProgress:{completed:m,total:p,percentage:g}},lastUpdated:f()})),await this.publishEvent(t,"subtask.completed",{taskId:o.currentTask.id,subtaskId:u.id,description:u.description,output:s,handoff:i.outputForNextAgent,filesChanged:i.filesChanged.length,progress:{completed:m,total:p,percentage:g}}),T<p?d[T]:null}async getCurrentSubtask(t){let e=await this.read(t);if(!e.currentTask?.subtasks)return null;let r=e.currentTask.currentSubtaskIndex||0;return e.currentTask.subtasks[r]||null}async getNextSubtask(t){let e=await this.read(t);if(!e.currentTask?.subtasks)return null;let r=(e.currentTask.currentSubtaskIndex||0)+1;return e.currentTask.subtasks[r]||null}async getPreviousSubtask(t){let e=await this.read(t);if(!e.currentTask?.subtasks)return null;let r=(e.currentTask.currentSubtaskIndex||0)-1;return r<0?null:e.currentTask.subtasks[r]||null}async getPreviousHandoff(t){let e=await this.getPreviousSubtask(t);return e?.summary?.outputForNextAgent?{fromSubtask:e.description,outputForNextAgent:e.summary.outputForNextAgent,filesChanged:e.summary.filesChanged,whatWasDone:e.summary.whatWasDone}:null}async getSubtasks(t){return(await this.read(t)).currentTask?.subtasks||[]}async getSubtaskProgress(t){return(await this.read(t)).currentTask?.subtaskProgress||null}async hasSubtasks(t){return((await this.read(t)).currentTask?.subtasks?.length||0)>0}async areAllSubtasksComplete(t){let e=await this.read(t);return e.currentTask?.subtasks?e.currentTask.subtasks.every(r=>r.status==="completed"||r.status==="failed"||r.status==="skipped"):!0}async failSubtask(t,e){let r=await this.read(t);if(!r.currentTask?.subtasks)return null;let s=r.currentTask.currentSubtaskIndex||0,i=r.currentTask.subtasks[s];if(!i)return null;let o=[...r.currentTask.subtasks];o[s]={...i,status:"failed",completedAt:f(),output:`Failed: ${e}`};let a=s+1,u=o.length;a<u&&(o[a]={...o[a],status:"in_progress",startedAt:f()});let d=o.filter(p=>p.status==="completed"||p.status==="failed"||p.status==="skipped").length,m=Math.round(d/u*100);return await this.update(t,p=>({...p,currentTask:{...p.currentTask,subtasks:o,currentSubtaskIndex:a<u?a:s,subtaskProgress:{completed:d,total:u,percentage:m}},lastUpdated:f()})),await this.publishEvent(t,"subtask.failed",{taskId:r.currentTask.id,subtaskId:i.id,description:i.description,error:e}),a<u?o[a]:null}async skipSubtask(t,e){let r=await this.read(t);if(!r.currentTask?.subtasks)return null;let s=r.currentTask.currentSubtaskIndex||0,i=r.currentTask.subtasks[s];if(!i)return null;let o=[...r.currentTask.subtasks];o[s]={...i,status:"skipped",completedAt:f(),output:`Skipped: ${e}`,skipReason:e};let a=s+1,u=o.length;a<u&&(o[a]={...o[a],status:"in_progress",startedAt:f()});let d=o.filter(p=>p.status==="completed"||p.status==="failed"||p.status==="skipped").length,m=Math.round(d/u*100);return await this.update(t,p=>({...p,currentTask:{...p.currentTask,subtasks:o,currentSubtaskIndex:a<u?a:s,subtaskProgress:{completed:d,total:u,percentage:m}},lastUpdated:f()})),await this.publishEvent(t,"subtask.skipped",{taskId:r.currentTask.id,subtaskId:i.id,description:i.description,reason:e}),a<u?o[a]:null}async blockSubtask(t,e){let r=await this.read(t);if(!r.currentTask?.subtasks)return null;let s=r.currentTask.currentSubtaskIndex||0,i=r.currentTask.subtasks[s];if(!i)return null;let o=[...r.currentTask.subtasks];o[s]={...i,status:"blocked",output:`Blocked: ${e}`,blockReason:e};let a=s+1,u=o.length;return a<u&&(o[a]={...o[a],status:"in_progress",startedAt:f()}),await this.update(t,d=>({...d,currentTask:{...d.currentTask,subtasks:o,currentSubtaskIndex:a<u?a:s},lastUpdated:f()})),await this.publishEvent(t,"subtask.blocked",{taskId:r.currentTask.id,subtaskId:i.id,description:i.description,blocker:e}),a<u?o[a]:null}},J=new te;U();B();import Xs from"node:fs/promises";import Et from"node:path";var $s={frontend:["component","page","view","ui","layout","style","css","scss","sass","hook","context","store","redux","zustand","react","vue","svelte","angular","next","nuxt","app","client"],backend:["api","route","controller","service","middleware","handler","resolver","schema","model","entity","repository","server","socket","graphql","rest","trpc"],database:["migration","seed","schema","model","entity","repository","prisma","drizzle","sequelize","typeorm","mongoose","knex","sql","db"],auth:["auth","login","logout","session","token","jwt","oauth","passport","credential","permission","role","user","account"],testing:["test","spec","e2e","integration","unit","mock","fixture","stub","jest","vitest","cypress","playwright"],config:["config","env","setting","constant","option","tsconfig","eslint","prettier","vite","webpack","rollup"],infra:["docker","compose","kubernetes","k8s","ci","cd","github","gitlab","jenkins","terraform","ansible","deploy"],util:["util","helper","lib","common","shared","core","base","abstract"]},Ws=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".go",".rs",".java",".kt",".swift",".rb",".php",".c",".cpp",".h",".hpp",".cs",".vue",".svelte"]),Gs=new Set(["node_modules",".git","dist","build",".next",".nuxt",".output","coverage",".cache","__pycache__",".pytest_cache","vendor","target",".turbo",".vercel"]);async function hr(n,t,e={}){let r=Date.now(),s=e.maxFiles??30,i=e.minScore??.1,o=e.includeTests??!1,a=Bs(n),u=await Hs(t),d=await qs(t),m=[];for(let g of u){if(!o&&zs(g))continue;let T=Ys(g,a,d,e.historicalBoosts);T.score>=i&&m.push(T)}m.sort((g,T)=>T.score-g.score);let p=m.slice(0,s);return{files:p,metrics:{filesScanned:u.length,filesReturned:p.length,scanDuration:Date.now()-r}}}c(hr,"findRelevantFiles");function Bs(n){let t=n.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean),e=new Set(["a","an","the","and","or","but","is","are","was","were","be","been","being","have","has","had","do","does","did","will","would","could","should","may","might","must","shall","can","need","to","of","in","for","on","with","at","by","from","as","into","through","during","before","after","above","below","between","under","again","further","then","once","here","there","when","where","why","how","all","each","few","more","most","other","some","such","no","nor","not","only","own","same","so","than","too","very","just","add","create","make","implement","fix","update","change","modify","remove","delete","new"]);return t.filter(r=>!e.has(r)&&r.length>2)}c(Bs,"extractKeywords");async function Hs(n){let t=[];async function e(r,s=""){try{let i=await Xs.readdir(r,{withFileTypes:!0});for(let o of i){let a=Et.join(r,o.name),u=Et.join(s,o.name);if(o.isDirectory()){if(Gs.has(o.name)||o.name.startsWith("."))continue;await e(a,u)}else if(o.isFile()){let d=Et.extname(o.name).toLowerCase();Ws.has(d)&&t.push(u)}}}catch(i){P(i)}}return c(e,"walk"),await e(n),t}c(Hs,"getAllCodeFiles");async function qs(n){let t=new Map;try{let{stdout:e}=await k(`git log -30 --pretty=format:"%H %ct" --name-only | awk '
|
|
506
506
|
/^[a-f0-9]{40}/ { commit=$1; timestamp=$2; next }
|
|
507
507
|
NF { files[$0]++; if (!lastmod[$0]) lastmod[$0]=timestamp }
|
|
508
508
|
END { for (f in files) print files[f], lastmod[f], f }
|
|
509
509
|
'`,{cwd:n,maxBuffer:10485760}),r=Math.floor(Date.now()/1e3),s=e.trim().split(`
|
|
510
|
-
`).filter(Boolean);for(let i of s){let o=i.match(/^(\d+)\s+(\d+)\s+(.+)$/);if(o){let a=parseInt(o[1],10),u=parseInt(o[2],10),d=o[3],m=Math.floor((r-u)/86400);t.set(d,{commits:a,daysAgo:m})}}}catch{}return t}c(
|
|
511
|
-
`);return{file:n,language:a,signatures:d,fallback:!1,metrics:Er(i,m)}}c(br,"extractSignatures");function
|
|
510
|
+
`).filter(Boolean);for(let i of s){let o=i.match(/^(\d+)\s+(\d+)\s+(.+)$/);if(o){let a=parseInt(o[1],10),u=parseInt(o[2],10),d=o[3],m=Math.floor((r-u)/86400);t.set(d,{commits:a,daysAgo:m})}}}catch{}return t}c(qs,"getGitRecency");function Ys(n,t,e,r){let s=[],i=0,o=0,a=0,u=0,d=0,m=n.toLowerCase(),p=m.split("/").join(" ").split(/[^a-z0-9]+/);for(let x of t){m.includes(x)&&(i+=.3,s.push(`keyword:${x}`));for(let V of p)if(V.includes(x)||x.includes(V)){i+=.15;break}}i=Math.min(1,i);for(let[x,V]of Object.entries($s))for(let Ur of V)if(m.includes(Ur)&&t.some(St=>V.includes(St)||St.includes(x)||x.includes(St))){o+=.4,s.push(`domain:${x}`);break}o=Math.min(1,o);let g=e.get(n);g&&(g.daysAgo<=1?(a=1,s.push("recent:1d")):g.daysAgo<=3?(a=.8,s.push("recent:3d")):g.daysAgo<=7?(a=.6,s.push("recent:1w")):g.daysAgo<=30&&(a=.3,s.push("recent:1m")),g.commits>=5&&(a=Math.min(1,a+.2)));let T=Et.basename(n).toLowerCase();if((T.includes("index")||T.includes("main")||T.includes("app")||T.includes("entry"))&&(u=.5,s.push("import:0")),(m.includes("/core/")||m.includes("/shared/")||m.includes("/lib/"))&&(u=Math.max(u,.3),s.some(x=>x.startsWith("import:"))||s.push("import:1")),r){let x=r.get(n);x!==void 0&&(d=(x+1)/2,x>0?s.push("history:boosted"):x<0&&s.push("history:penalized"))}let it=r&&r.size>0?i*.54+o*.18+a*.13+u*.05+d*.1:i*.6+o*.2+a*.15+u*.05;return{path:n,score:Math.min(1,it),reasons:[...new Set(s)]}}c(Ys,"scoreFile");function zs(n){let t=n.toLowerCase();return t.includes(".test.")||t.includes(".spec.")||t.includes("__tests__")||t.includes("__mocks__")||t.includes("/tests/")||t.includes("/test/")||t.endsWith("_test.go")||t.endsWith("_test.py")}c(zs,"isTestFile");U();import Zs from"node:fs/promises";import K from"node:path";var Ks={"claude-opus-4.5":{input:.005,output:.025},"claude-sonnet-4.5":{input:.003,output:.015},"claude-haiku-4.5":{input:.001,output:.005},"claude-opus-4":{input:.015,output:.075},"claude-opus-4-6":{input:.015,output:.075},"gpt-4o":{input:.0025,output:.01},"gpt-4-turbo":{input:.01,output:.03},"gpt-4o-mini":{input:15e-5,output:6e-4},"gemini-1.5-pro":{input:.00125,output:.005},"gemini-1.5-flash":{input:75e-6,output:3e-4}},Vs="claude-sonnet-4.5";function ee(n){return!n||n.length===0?0:Math.ceil(n.length/4)}c(ee,"countTokens");var yr=["claude-sonnet-4.5","claude-opus-4.5","claude-opus-4-6","gpt-4o","gemini-1.5-pro"];function Tr(n,t){let e=Ks[t],r=n/1e3*e.input,s=n/1e3*e.output*.3;return{inputSaved:r,outputPotential:s,total:r+s}}c(Tr,"calculateModelCost");function Qs(n){return n<.001?"<$0.01":n<.01?`$${n.toFixed(3)}`:`$${n.toFixed(2)}`}c(Qs,"formatCostSaved");function Er(n,t){let e=ee(n),r=ee(t),s=Math.max(0,e-r),i=e>0?(e-r)/e:0,o=Tr(s,Vs),a=yr.map(u=>({model:u,...Tr(s,u)}));return{tokens:{original:e,filtered:r,saved:s},compression:Math.max(0,Math.min(1,i)),cost:{saved:o.total,formatted:Qs(o.total),byModel:a}}}c(Er,"measureCompression");function kt(n){let t=ee(n);return{tokens:{original:t,filtered:t,saved:0},compression:0,cost:{saved:0,formatted:"$0.00",byModel:yr.map(e=>({model:e,inputSaved:0,outputPotential:0,total:0}))}}}c(kt,"noCompression");var tn={".ts":"typescript",".tsx":"typescript",".js":"javascript",".jsx":"javascript",".mjs":"javascript",".cjs":"javascript",".py":"python",".go":"go",".rs":"rust",".java":"java",".cs":"csharp",".php":"php",".rb":"ruby"},kr=[{type:"function",pattern:/^export\s+(?:async\s+)?function\s+(\w+)\s*(<[^>]*>)?\s*\(([^)]*)\)\s*(?::\s*([^{;]+))?/gm,nameIndex:1,exported:!0},{type:"function",pattern:/^export\s+const\s+(\w+)\s*(?::\s*[^=]+)?\s*=\s*(?:async\s+)?\([^)]*\)\s*(?::\s*[^=]+)?\s*=>/gm,nameIndex:1,exported:!0},{type:"function",pattern:/^(?:async\s+)?function\s+(\w+)\s*(<[^>]*>)?\s*\(([^)]*)\)\s*(?::\s*([^{;]+))?/gm,nameIndex:1},{type:"function",pattern:/^const\s+(\w+)\s*(?::\s*[^=]+)?\s*=\s*(?:async\s+)?\([^)]*\)\s*(?::\s*[^=]+)?\s*=>/gm,nameIndex:1},{type:"interface",pattern:/^export\s+interface\s+(\w+)(?:<[^>]+>)?\s*(?:extends\s+[^{]+)?\s*\{/gm,nameIndex:1,exported:!0},{type:"interface",pattern:/^interface\s+(\w+)(?:<[^>]+>)?\s*(?:extends\s+[^{]+)?\s*\{/gm,nameIndex:1},{type:"type",pattern:/^export\s+type\s+(\w+)(?:<[^>]+>)?\s*=/gm,nameIndex:1,exported:!0},{type:"type",pattern:/^type\s+(\w+)(?:<[^>]+>)?\s*=/gm,nameIndex:1},{type:"class",pattern:/^export\s+(?:abstract\s+)?class\s+(\w+)(?:<[^>]+>)?(?:\s+extends\s+[^{]+)?(?:\s+implements\s+[^{]+)?\s*\{/gm,nameIndex:1,exported:!0},{type:"class",pattern:/^(?:abstract\s+)?class\s+(\w+)(?:<[^>]+>)?(?:\s+extends\s+[^{]+)?(?:\s+implements\s+[^{]+)?\s*\{/gm,nameIndex:1},{type:"enum",pattern:/^export\s+enum\s+(\w+)\s*\{/gm,nameIndex:1,exported:!0},{type:"enum",pattern:/^enum\s+(\w+)\s*\{/gm,nameIndex:1},{type:"const",pattern:/^export\s+const\s+(\w+)\s*(?::\s*([^=]+))?\s*=/gm,nameIndex:1,exported:!0}],en=[{type:"function",pattern:/^def\s+(\w+)\s*\(([^)]*)\)\s*(?:->\s*([^:]+))?\s*:/gm,nameIndex:1},{type:"function",pattern:/^async\s+def\s+(\w+)\s*\(([^)]*)\)\s*(?:->\s*([^:]+))?\s*:/gm,nameIndex:1},{type:"class",pattern:/^class\s+(\w+)(?:\(([^)]*)\))?\s*:/gm,nameIndex:1}],rn=[{type:"function",pattern:/^func\s+(\w+)\s*\(([^)]*)\)\s*(?:\(([^)]*)\)|([^\s{]+))?\s*\{/gm,nameIndex:1},{type:"method",pattern:/^func\s+\([^)]+\)\s+(\w+)\s*\(([^)]*)\)\s*(?:\(([^)]*)\)|([^\s{]+))?\s*\{/gm,nameIndex:1},{type:"type",pattern:/^type\s+(\w+)\s+(?:struct|interface)\s*\{/gm,nameIndex:1}],sn=[{type:"function",pattern:/^pub\s+(?:async\s+)?fn\s+(\w+)(?:<[^>]+>)?\s*\(([^)]*)\)\s*(?:->\s*([^{]+))?\s*\{/gm,nameIndex:1,exported:!0},{type:"function",pattern:/^(?:async\s+)?fn\s+(\w+)(?:<[^>]+>)?\s*\(([^)]*)\)\s*(?:->\s*([^{]+))?\s*\{/gm,nameIndex:1},{type:"class",pattern:/^pub\s+struct\s+(\w+)(?:<[^>]+>)?\s*(?:\{|;)/gm,nameIndex:1,exported:!0},{type:"class",pattern:/^struct\s+(\w+)(?:<[^>]+>)?\s*(?:\{|;)/gm,nameIndex:1},{type:"interface",pattern:/^pub\s+trait\s+(\w+)(?:<[^>]+>)?\s*(?:\{|:)/gm,nameIndex:1,exported:!0},{type:"interface",pattern:/^trait\s+(\w+)(?:<[^>]+>)?\s*(?:\{|:)/gm,nameIndex:1},{type:"enum",pattern:/^pub\s+enum\s+(\w+)(?:<[^>]+>)?\s*\{/gm,nameIndex:1,exported:!0},{type:"enum",pattern:/^enum\s+(\w+)(?:<[^>]+>)?\s*\{/gm,nameIndex:1}],wr=[{type:"class",pattern:/^(?:public\s+)?(?:abstract\s+)?(?:final\s+)?class\s+(\w+)(?:<[^>]+>)?(?:\s+extends\s+\w+)?(?:\s+implements\s+[^{]+)?\s*\{/gm,nameIndex:1,exported:!0},{type:"interface",pattern:/^(?:public\s+)?interface\s+(\w+)(?:<[^>]+>)?(?:\s+extends\s+[^{]+)?\s*\{/gm,nameIndex:1,exported:!0},{type:"method",pattern:/^\s+(?:public|private|protected)?\s*(?:static\s+)?(?:final\s+)?(?:synchronized\s+)?(?:<[^>]+>\s+)?(\w+(?:<[^>]+>)?)\s+(\w+)\s*\([^)]*\)\s*(?:throws\s+[^{]+)?\s*\{/gm,nameIndex:2}],nn={typescript:kr,javascript:kr,python:en,go:rn,rust:sn,java:wr,csharp:wr,php:[],ruby:[],unknown:[]};async function br(n,t=process.cwd()){let e=K.isAbsolute(n)?n:K.join(t,n),r=K.resolve(t),s=K.resolve(e);if(!s.startsWith(r+K.sep)&&s!==r)return{file:n,language:"unknown",signatures:[],fallback:!0,fallbackReason:"Path traversal denied: file is outside project directory",metrics:kt("")};let i;try{i=await Zs.readFile(e,"utf-8")}catch(p){if(P(p))return{file:n,language:"unknown",signatures:[],fallback:!0,fallbackReason:"File not found",metrics:kt("")};throw p}let o=K.extname(n).toLowerCase(),a=tn[o]||"unknown",u=nn[a];if(!u||u.length===0)return{file:n,language:a,signatures:[],fallback:!0,fallbackReason:`No extraction patterns for ${a}`,metrics:kt(i)};let d=on(i,u),m=d.map(p=>`${p.exported?"export ":""}${p.type} ${p.name}: ${p.signature}`).join(`
|
|
511
|
+
`);return{file:n,language:a,signatures:d,fallback:!1,metrics:Er(i,m)}}c(br,"extractSignatures");function on(n,t){let e=[],r=n.split(`
|
|
512
512
|
`),s=new Set;for(let i of t){i.pattern.lastIndex=0;let o;for(;(o=i.pattern.exec(n))!==null;){let a=o[i.nameIndex];if(!a)continue;let u=`${i.type}:${a}`;if(s.has(u))continue;s.add(u);let d=o.index,m=n.substring(0,d).split(`
|
|
513
|
-
`).length,p=o[0].trim(),g;if(m>1){let T=r[m-2]?.trim();(T?.startsWith("/**")||T?.startsWith("///")||T?.startsWith("#"))&&(g=T)}e.push({type:i.type,name:a,signature:
|
|
513
|
+
`).length,p=o[0].trim(),g;if(m>1){let T=r[m-2]?.trim();(T?.startsWith("/**")||T?.startsWith("///")||T?.startsWith("#"))&&(g=T)}e.push({type:i.type,name:a,signature:an(p),exported:i.exported||!1,line:m,docstring:g})}}return e.sort((i,o)=>i.line-o.line)}c(on,"extractFromContent");function an(n){return n.replace(/\{$/,"").replace(/\s+/g," ").trim()}c(an,"cleanSignature");function Sr(n){let t=n;t.tool("prjct_relevant_files","BM25-ranked files relevant to a query",{projectPath:W.string().describe("Project directory path"),query:W.string().describe("Task or query to find relevant files for"),maxFiles:W.number().optional().default(10).describe("Max files to return")},b("prjct_relevant_files",async e=>{let r=await hr(e.query,e.projectPath,{maxFiles:e.maxFiles,minScore:.1});if(r.files.length===0)return{content:[{type:"text",text:"No relevant files found."}]};let s=r.files.map(o=>`- \`${o.path}\` (score: ${Math.round(o.score*100)}%) \u2014 ${o.reasons.join(", ")}`);return{content:[{type:"text",text:`## Relevant Files (${r.files.length}/${r.metrics.filesScanned} scanned)
|
|
514
514
|
|
|
515
515
|
${s.join(`
|
|
516
516
|
`)}`}]}})),t.tool("prjct_signatures","Code signatures from a file (90% token reduction vs full content)",{projectPath:W.string().describe("Project directory path"),filePath:W.string().describe("Relative file path to extract signatures from")},b("prjct_signatures",async e=>{let r=await br(e.filePath,e.projectPath);if(r.signatures.length===0)return{content:[{type:"text",text:r.fallback?`No signatures extracted: ${r.fallbackReason}`:"No signatures found."}]};let s=r.signatures.map(a=>`${a.exported?"export ":""}${a.type} ${a.name}: ${a.signature}${a.docstring?` // ${a.docstring}`:""}`),i=r.metrics?.compression?` (${Math.round(r.metrics.compression*100)}% reduction)`:"";return{content:[{type:"text",text:`## ${r.file} (${r.language})
|
|
@@ -520,28 +520,28 @@ ${s.join(`
|
|
|
520
520
|
\`\`\`${i}`}]}})),t.tool("prjct_history","Recent completed tasks with outcomes",{projectPath:W.string().describe("Project directory path"),limit:W.number().optional().default(10).describe("Max results")},b("prjct_history",async e=>{let r=await v(e.projectPath),s=await J.getTaskHistory(r);if(s.length===0)return{content:[{type:"text",text:"No task history."}]};let o=s.slice(-e.limit).reverse().map(u=>{let d=[`- **${u.title}**`];return u.completedAt&&d.push(`completed: ${u.completedAt}`),u.classification&&d.push(`type: ${u.classification}`),d.join(" | ")});return{content:[{type:"text",text:`## Task History (${s.length} total)
|
|
521
521
|
|
|
522
522
|
${o.join(`
|
|
523
|
-
`)}`}]}}))}c(Sr,"registerFileTools");import{z as S}from"zod";var
|
|
524
|
-
`).trim()}c(
|
|
523
|
+
`)}`}]}}))}c(Sr,"registerFileTools");import{z as S}from"zod";var re=class{static{c(this,"MemoryService")}async log(t,e,r,s){try{let i=await $.getProjectId(t);if(!i)return;E.appendEvent(i,`memory.${e}`,{...r,author:s})}catch(i){console.error(`Memory log error: ${i instanceof Error?i.message:String(i)}`)}}async getRecent(t,e=100){try{let r=await $.getProjectId(t);return r?E.query(r,"SELECT type, data, timestamp FROM events WHERE type LIKE 'memory.%' ORDER BY id DESC LIMIT ?",e).reverse().map(i=>{let o=JSON.parse(i.data),{author:a,...u}=o;return{timestamp:i.timestamp,action:i.type.replace("memory.",""),data:u,author:a}}):[]}catch(r){return console.error(`Memory read error: ${r instanceof Error?r.message:String(r)}`),[]}}async search(t,e,r=50){let s=await this.getRecent(t,1e3),i=e.toLowerCase();return s.filter(o=>{let a=o.action.toLowerCase().includes(i),u=JSON.stringify(o.data).toLowerCase().includes(i);return a||u}).slice(-r)}async getByAction(t,e,r=50){try{let s=await $.getProjectId(t);return s?E.query(s,"SELECT type, data, timestamp FROM events WHERE type = ? ORDER BY id DESC LIMIT ?",`memory.${e}`,r).reverse().map(o=>{let a=JSON.parse(o.data),{author:u,...d}=a;return{timestamp:o.timestamp,action:o.type.replace("memory.",""),data:d,author:u}}):[]}catch(s){return console.error(`Memory read error: ${s instanceof Error?s.message:String(s)}`),[]}}async clear(t){try{let e=await $.getProjectId(t);if(!e)return;E.run(e,"DELETE FROM events WHERE type LIKE 'memory.%'")}catch(e){console.error(`Memory clear error: ${e instanceof Error?e.message:String(e)}`)}}async getRecentEvents(t,e=100){try{return E.query(t,"SELECT type, data, timestamp FROM events WHERE type LIKE 'memory.%' ORDER BY id DESC LIMIT ?",e).reverse().map(s=>{let i=JSON.parse(s.data);return{timestamp:s.timestamp,action:s.type.replace("memory.",""),...i}})}catch(r){return console.error(`Memory read error: ${r instanceof Error?r.message:String(r)}`),[]}}async capEntries(t){try{let r=E.get(t,"SELECT COUNT(*) as cnt FROM events WHERE type LIKE 'memory.%'")?.cnt??0;if(r<=st.MEMORY_MAX_ENTRIES)return 0;let s=r-st.MEMORY_MAX_ENTRIES,i=E.query(t,"SELECT id, type, data, timestamp FROM events WHERE type LIKE 'memory.%' ORDER BY id ASC LIMIT ?",s);Y.archiveMany(t,i.map((a,u)=>({entityType:"memory_entry",entityId:`memory-${a.timestamp||u}`,entityData:{type:a.type,data:JSON.parse(a.data),timestamp:a.timestamp},summary:a.type.replace("memory.",""),reason:"overflow"})));let o=i[i.length-1]?.id;return o!==void 0&&E.run(t,"DELETE FROM events WHERE type LIKE 'memory.%' AND id <= ?",o),s}catch(e){return console.error(`Memory cap error: ${e instanceof Error?e.message:String(e)}`),0}}},vr=new re;var _r="memory.",se="remember.",ne=`${_r}${se}`,Da=`${_r}task.tagged`;var xr=["fact","decision","learning","gotcha","pattern","anti-pattern","shipped","inbox","todo","idea","insight","question","source","person"];var cn=25,un=4,ln=100;function Rr(n,t){try{return JSON.parse(n)}catch{return t}}c(Rr,"safeJson");function dn(n){let t=n.type.slice(ne.length),e=Rr(n.data,{});return{id:`mem_${n.id}`,type:t,content:e.content??"",tags:e.tags??{},rememberedAt:n.timestamp,source:e.source,provenance:e.provenance??"declared"}}c(dn,"rowToEntry");function pn(n){let t=n.data?Rr(n.data,{}):{},e=t.tags??{};return n.type&&(e.type=n.type),{id:`ship_${n.id}`,type:"shipped",content:n.name,tags:e,rememberedAt:n.shipped_at,source:t.taskId,provenance:"extracted"}}c(pn,"shippedRowToEntry");function mn(n,t){let e=t.toLowerCase();if(n.content.toLowerCase().includes(e))return!0;for(let r of Object.values(n.tags))if(r.toLowerCase().includes(e))return!0;return!1}c(mn,"matchesTopic");function gn(n,t){for(let[e,r]of Object.entries(t))if(n.tags[e]!==r)return!1;return!0}c(gn,"matchesTags");var G={async remember(n,t){await vr.log(n,`${se}${t.type}`,{content:t.content,tags:t.tags??{},source:t.source,provenance:t.provenance??"declared"})},recall(n,t={}){let e=t.limit??cn,r=Math.max(e*un,ln),s=E.query(n,"SELECT id, type, data, timestamp FROM events WHERE type LIKE ? ORDER BY id DESC LIMIT ?",`${ne}%`,r),i=E.query(n,"SELECT id, name, type, shipped_at, data FROM shipped_features ORDER BY shipped_at DESC LIMIT ?",r),o=[...s.map(dn),...i.map(pn)];if(t.types&&t.types.length>0){let a=new Set(t.types);o=o.filter(u=>a.has(u.type))}return t.tags&&(o=o.filter(a=>gn(a,t.tags??{}))),t.topic&&(o=o.filter(a=>mn(a,t.topic))),o.sort((a,u)=>u.rememberedAt.localeCompare(a.rememberedAt)),o.slice(0,e)},similar(n,t,e=10){let r=t.toLowerCase().split(/[^a-z0-9]+/).filter(o=>o.length>3);return r.length===0?[]:G.recall(n,{limit:200}).map(o=>{let a=`${o.content} ${Object.values(o.tags).join(" ")}`.toLowerCase(),u=r.reduce((d,m)=>a.includes(m)?d+1:d,0);return{entry:o,hits:u}}).filter(o=>o.hits>0).sort((o,a)=>a.hits-o.hits).slice(0,e).map(o=>o.entry)}};function nt(n){if(n.length===0)return"> No matching memory entries.";let t=new Map;for(let i of n){let o=t.get(i.type)??[];o.push(i),t.set(i.type,o)}let e=["decision","learning","anti-pattern","gotcha","pattern","fact","shipped"],r=[],s={declared:"DECL",extracted:"EXTR",inferred:"INFR",ambiguous:"AMBG"};for(let i of e){let o=t.get(i);if(!(!o||o.length===0)){r.push(`### ${i.toUpperCase()}`);for(let a of o){let u=Object.entries(a.tags).map(([p,g])=>`${p}=${g}`).join(" "),d=u?` _(${u})_`:"",m=s[a.provenance];r.push(`- \`${m}\` [${a.id}] ${a.content}${d}`)}r.push("")}}return r.join(`
|
|
524
|
+
`).trim()}c(nt,"formatMemoryMd");var fn=[{name:"sk-\u2026 token",re:/\bsk-[A-Za-z0-9_-]{16,}/},{name:"GitHub PAT",re:/\bghp_[A-Za-z0-9]{30,}/},{name:"GitHub server PAT",re:/\bghs_[A-Za-z0-9]{30,}/},{name:"AWS access key",re:/\bAKIA[0-9A-Z]{16}\b/},{name:"Slack token",re:/\bxox[abps]-[A-Za-z0-9-]{10,}/},{name:"bearer JWT-ish",re:/\beyJ[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\b/}];function Pr(n){let t=[];for(let{name:e,re:r}of fn)r.test(n)&&t.push(e);return t}c(Pr,"scanForSecrets");var Ar=`Base types: ${xr.join(", ")}. Any lowercase identifier is accepted (e.g. "recipe", "okr").`;function Nr(n){let t=n;t.tool("prjct_mem_save",`Save a memory entry. ${Ar} Secret-like content is refused unless force=true.`,{projectPath:S.string().describe("Project directory path"),type:S.string().describe("Memory type (fact/decision/learning/... or user-defined)"),content:S.string().describe("The memory content. Freeform text."),tags:S.record(S.string(),S.string()).optional().describe('Key:value tags (e.g. {domain: "auth"})'),source:S.string().optional().describe("Task id this memory came from, if any"),force:S.boolean().optional().describe("Bypass the secret-like-content refusal. Default false.")},b("prjct_mem_save",async e=>{await v(e.projectPath);let r=e.type.toLowerCase().trim();if(!r||!/^[a-z][a-z0-9-]*$/.test(r))return{content:[{type:"text",text:`Invalid type '${e.type}'. Lowercase letters + dashes only. ${Ar}`}]};let s=Pr(e.content);return s.length>0&&!e.force?{content:[{type:"text",text:`Refused \u2014 content looks like a secret (${s.join(", ")}). Re-call with force=true if intentional.`}]}:(await G.remember(e.projectPath,{type:r,content:e.content,tags:e.tags??{},source:e.source}),{content:[{type:"text",text:`Saved ${r}: ${e.content.slice(0,80)}`}]})})),t.tool("prjct_mem_list","Recall memory entries. Optional filters: topic (keyword across content + tag values), types, tags, limit.",{projectPath:S.string().describe("Project directory path"),topic:S.string().optional().describe("Keyword to match over content + tag values"),types:S.array(S.string()).optional().describe("Restrict to these types"),tags:S.record(S.string(),S.string()).optional().describe("Require exact match on these k:v pairs"),limit:S.number().optional().default(25).describe("Max entries (default 25)")},b("prjct_mem_list",async e=>{let r=await v(e.projectPath),s=G.recall(r,{topic:e.topic,types:e.types,tags:e.tags,limit:e.limit});return{content:[{type:"text",text:nt(s)}]}})),t.tool("prjct_mem_similar","Find memory entries similar to a free-text description. Keyword-based, best-effort.",{projectPath:S.string().describe("Project directory path"),description:S.string().describe("Free-text description to find similar memories for"),limit:S.number().optional().default(10).describe("Max results (default 10)")},b("prjct_mem_similar",async e=>{let r=await v(e.projectPath),s=G.similar(r,e.description,e.limit);return s.length===0?{content:[{type:"text",text:"No similar memories found."}]}:{content:[{type:"text",text:nt(s)}]}})),t.tool("prjct_mem_forget","Remove a memory entry by id. Ids are stable \u2014 pull them from `prjct_mem_list`.",{projectPath:S.string().describe("Project directory path"),id:S.string().describe('Memory id (e.g. "mem_42" or "ship_7")')},b("prjct_mem_forget",async e=>({content:[{type:"text",text:"Forget is not implemented in the projectMemory API yet. Entries persist event-sourced \u2014 filter them out client-side, or drop the underlying event manually."}]})))}c(Nr,"registerMemoryTools");import{z as ae}from"zod";var ie=class{static{c(this,"LLMAnalysisStorage")}save(t,e){let r=y.getDb(t),s=f();r.transaction(()=>{r.prepare("UPDATE llm_analysis SET status = 'superseded', superseded_at = ? WHERE status = 'active'").run(s),r.prepare("INSERT INTO llm_analysis (commit_hash, status, analysis, analyzed_at) VALUES (?, ?, ?, ?)").run(e.commitHash??null,"active",JSON.stringify(e),e.analyzedAt)})()}getActive(t){let e=y.get(t,"SELECT analysis FROM llm_analysis WHERE status = 'active' LIMIT 1");return e?JSON.parse(e.analysis):null}getActiveSummary(t){let e=this.getActive(t);return e?{commitHash:e.commitHash,architectureStyle:e.architecture.style,patternCount:e.patterns.length,antiPatternCount:e.antiPatterns.length,analyzedAt:e.analyzedAt}:null}isCurrent(t,e){return e?y.get(t,"SELECT commit_hash FROM llm_analysis WHERE status = 'active' LIMIT 1")?.commit_hash===e:!1}getAllFull(t){return y.query(t,"SELECT id, commit_hash, status, analyzed_at, superseded_at, analysis FROM llm_analysis ORDER BY id DESC").map(r=>({id:r.id,status:r.status,commitHash:r.commit_hash,analyzedAt:r.analyzed_at,supersededAt:r.superseded_at,analysis:JSON.parse(r.analysis)}))}getHistory(t,e=10){return y.query(t,"SELECT id, commit_hash, status, analyzed_at, analysis FROM llm_analysis ORDER BY id DESC LIMIT ?",e).map(s=>{let i=JSON.parse(s.analysis);return{id:s.id,commitHash:s.commit_hash,status:s.status,analyzedAt:s.analyzed_at,patternCount:i.patterns.length}})}},hn=new ie,Cr=hn;var Ir={critical:0,high:1,medium:2,low:3},Dr={active:0,previously_active:1,backlog:2};function Lr(n){return[...n].sort((t,e)=>{let r=Dr[t.section]-Dr[e.section];return r!==0?r:Ir[t.priority]-Ir[e.priority]})}c(Lr,"sortBySectionAndPriority");var oe=class extends z{static{c(this,"QueueStorage")}constructor(){super("queue.json",gr)}getDefault(){return{tasks:[],lastUpdated:""}}getEventType(t){return`queue.${t}d`}async getTasks(t){return(await this.read(t)).tasks}async getActiveTasks(t){return(await this.read(t)).tasks.filter(r=>r.section==="active"&&!r.completed)}async getBacklog(t){return(await this.read(t)).tasks.filter(r=>r.section==="backlog"&&!r.completed)}async getNextTask(t){let e=await this.getActiveTasks(t);return Lr(e)[0]||null}async addTask(t,e){let r={...e,id:F(),createdAt:f(),completed:!1};return await this.update(t,s=>({tasks:[...s.tasks,r],lastUpdated:f()})),await this.publishEvent(t,"queue.task_added",{taskId:r.id,description:r.description,priority:r.priority,section:r.section}),r}async addTasks(t,e){let r=f(),s=e.map(i=>({...i,id:F(),createdAt:r,completed:!1}));return await this.update(t,i=>({tasks:[...i.tasks,...s],lastUpdated:r})),await this.publishEvent(t,"queue.tasks_added",{count:s.length,tasks:s.map(i=>({id:i.id,description:i.description}))}),s}async removeTask(t,e){await this.update(t,r=>({tasks:r.tasks.filter(s=>s.id!==e),lastUpdated:f()})),await this.publishEvent(t,"queue.task_removed",{taskId:e})}async completeTask(t,e){let r=null;if(await this.update(t,s=>({tasks:s.tasks.map(o=>o.id===e?(r={...o,completed:!0,completedAt:f()},r):o),lastUpdated:f()})),r){let s=r;await this.publishEvent(t,"queue.task_completed",{taskId:e,description:s.description,completedAt:s.completedAt})}return r}async moveToSection(t,e,r){await this.update(t,s=>({tasks:s.tasks.map(i=>i.id===e?{...i,section:r}:i),lastUpdated:f()}))}async setPriority(t,e,r){await this.update(t,s=>({tasks:s.tasks.map(i=>i.id===e?{...i,priority:r}:i),lastUpdated:f()}))}async getTask(t,e){return(await this.read(t)).tasks.find(s=>s.id===e)||null}async updateTask(t,e,r){let s=null;return await this.update(t,i=>({tasks:i.tasks.map(o=>o.id===e?(s={...o,...r},s):o),lastUpdated:f()})),s&&await this.publishEvent(t,"queue.task_updated",{taskId:e}),s}async clearCompleted(t){let r=(await this.read(t)).tasks.filter(s=>s.completed).length;return await this.update(t,s=>({tasks:s.tasks.filter(i=>!i.completed),lastUpdated:f()})),r}async removeStaleCompleted(t){let e=await this.read(t),r=ye(st.QUEUE_COMPLETED_DAYS),s=e.tasks.filter(o=>o.completed&&o.completedAt&&new Date(o.completedAt)<r);if(s.length===0)return 0;Y.archiveMany(t,s.map(o=>({entityType:"queue_task",entityId:o.id,entityData:o,summary:o.description,reason:"age"})));let i=new Set(s.map(o=>o.id));return await this.update(t,o=>({tasks:o.tasks.filter(a=>!i.has(a.id)),lastUpdated:f()})),await this.publishEvent(t,"queue.stale_removed",{count:s.length}),s.length}},Or=new oe;function Mr(n){let t=n;t.tool("prjct_task_status","Current task, duration, subtasks, and queue",{projectPath:ae.string().describe("Project directory path")},b("prjct_task_status",async e=>{let r=await v(e.projectPath),s=await J.getCurrentTask(r),i=await Or.getActiveTasks(r),o=[];if(s?(o.push(`## Active Task
|
|
525
525
|
**${s.description}**`),s.branch&&o.push(`Branch: ${s.branch}`),o.push(`Started: ${s.startedAt}`)):o.push("No active task."),i.length>0){o.push(`
|
|
526
526
|
## Queue (${i.length} tasks)`);for(let a of i.slice(0,10))o.push(`- ${a.description} [${a.priority||"medium"}]`)}return{content:[{type:"text",text:o.join(`
|
|
527
|
-
`)}]}})),t.tool("prjct_analysis","LLM analysis: stack, patterns, anti-patterns, conventions",{projectPath:
|
|
527
|
+
`)}]}})),t.tool("prjct_analysis","LLM analysis: stack, patterns, anti-patterns, conventions",{projectPath:ae.string().describe("Project directory path")},b("prjct_analysis",async e=>{let r=await v(e.projectPath),s=Cr.getActive(r);if(!s)return{content:[{type:"text",text:"No analysis available. Run `prjct sync`."}]};let i=["## Project Analysis"];if(s.stack&&(i.push(`
|
|
528
528
|
### Stack`),s.stack.languages?.length&&i.push(`Languages: ${s.stack.languages.join(", ")}`),s.stack.frameworks?.length&&i.push(`Frameworks: ${s.stack.frameworks.join(", ")}`),s.stack.packageManager&&i.push(`Package Manager: ${s.stack.packageManager}`)),s.patterns?.length){i.push(`
|
|
529
529
|
### Patterns (${s.patterns.length})`);for(let o of s.patterns)i.push(`- **${o.name}**: ${o.description}`)}if(s.antiPatterns?.length){i.push(`
|
|
530
530
|
### Anti-Patterns (${s.antiPatterns.length})`);for(let o of s.antiPatterns)i.push(`- **${o.issue}**: ${o.suggestion}`)}if(s.conventions?.length){i.push(`
|
|
531
531
|
### Conventions (${s.conventions.length})`);for(let o of s.conventions)i.push(`- [${o.category}] ${o.rule}`)}return{content:[{type:"text",text:i.join(`
|
|
532
|
-
`)}]}})),t.tool("prjct_patterns","Project memory grouped by type (decision / pattern / anti-pattern / gotcha). Powered by projectMemory \u2014 same source the CLI memory verbs read.",{projectPath:
|
|
533
|
-
VALUES (?, ?, ?, ?, 0, 1, ?)`,e.name,e.description??null,r,r,e.metadata?JSON.stringify(e.metadata):null);let s=E.get(t,"SELECT id FROM custom_workflows WHERE name = ?",e.name);if(!s)throw new Error(`Failed to create workflow: ${e.name}`);return s.id}getWorkflow(t,e){let r=E.get(t,"SELECT * FROM custom_workflows WHERE name = ?",e);return r?this.rowToWorkflow(r):null}getAllWorkflows(t,e=!1){let r=e?"SELECT * FROM custom_workflows ORDER BY is_builtin DESC, name ASC":"SELECT * FROM custom_workflows WHERE enabled = 1 ORDER BY is_builtin DESC, name ASC";return E.query(t,r).map(i=>this.rowToWorkflow(i))}updateWorkflow(t,e,r){if(!this.getWorkflow(t,e))return!1;let i=new Date().toISOString(),o=[],a=[];return r.description!==void 0&&(o.push("description = ?"),a.push(r.description)),r.enabled!==void 0&&(o.push("enabled = ?"),a.push(r.enabled?1:0)),r.metadata!==void 0&&(o.push("metadata = ?"),a.push(JSON.stringify(r.metadata))),o.length===0?!1:(o.push("updated_at = ?"),a.push(i),a.push(e),E.run(t,`UPDATE custom_workflows SET ${o.join(", ")} WHERE name = ?`,...a),!0)}deleteWorkflow(t,e){let r=this.getWorkflow(t,e);if(!r)return!1;if(r.isBuiltin)throw new Error(`Cannot delete built-in workflow: ${e}`);return E.run(t,"UPDATE custom_workflows SET enabled = 0 WHERE name = ?",e),!0}isBuiltin(t,e){return this.getWorkflow(t,e)?.isBuiltin??!1}isReservedName(t){let e=["task","done","ship","sync"],r=["add","rm","gate","list","create","delete","run","help","reset","init"];return e.includes(t)||r.includes(t)}isValidName(t){return/^[a-z0-9-]+$/.test(t)}rowToWorkflow(t){return{id:t.id,name:t.name,description:t.description,createdAt:t.created_at,updatedAt:t.updated_at,isBuiltin:t.is_builtin===1,enabled:t.enabled===1,metadata:t.metadata?JSON.parse(t.metadata):null}}},
|
|
534
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,e.type,e.command,e.position,e.action,e.description??null,e.enabled?1:0,e.timeoutMs,e.createdAt,s,e.whenExpr??null,e.parallel===!1?0:1,e.trustSource??"local"),y.get(t,"SELECT last_insert_rowid() as id")?.id??0}removeRule(t,e){return y.get(t,"SELECT id FROM workflow_rules WHERE id = ?",e)?(y.run(t,"DELETE FROM workflow_rules WHERE id = ?",e),!0):!1}updateRule(t,e,r){if(!y.get(t,"SELECT id FROM workflow_rules WHERE id = ?",e))return!1;let i={type:{column:"type"},command:{column:"command"},position:{column:"position"},action:{column:"action"},description:{column:"description"},enabled:{column:"enabled",transform:c(u=>u?1:0,"transform")},timeoutMs:{column:"timeout_ms"},createdAt:{column:"created_at"},sortOrder:{column:"sort_order"},whenExpr:{column:"when_expr"},parallel:{column:"parallel",transform:c(u=>u===!1?0:1,"transform")},trustSource:{column:"trust_source"}},o=[],a=[];for(let[u,d]of Object.entries(r)){let m=i[u];if(!m)continue;o.push(`${m.column} = ?`);let p=d;a.push(m.transform?m.transform(p):p)}return o.length===0||(a.push(e),y.run(t,`UPDATE workflow_rules SET ${o.join(", ")} WHERE id = ?`,...a)),!0}getRuleById(t,e){let r=y.get(t,"SELECT * FROM workflow_rules WHERE id = ?",e);return r?
|
|
532
|
+
`)}]}})),t.tool("prjct_patterns","Project memory grouped by type (decision / pattern / anti-pattern / gotcha). Powered by projectMemory \u2014 same source the CLI memory verbs read.",{projectPath:ae.string().describe("Project directory path")},b("prjct_patterns",async e=>{let r=await v(e.projectPath),s=G.recall(r,{types:["decision","pattern","anti-pattern","gotcha"],limit:50});return s.length===0?{content:[{type:"text",text:"No decisions or patterns captured yet."}]}:{content:[{type:"text",text:nt(s)}]}}))}c(Mr,"registerProjectTools");import{z as bt}from"zod";var ce=class{static{c(this,"CustomWorkflowStorage")}createWorkflow(t,e){let r=new Date().toISOString();E.run(t,`INSERT INTO custom_workflows (name, description, created_at, updated_at, is_builtin, enabled, metadata)
|
|
533
|
+
VALUES (?, ?, ?, ?, 0, 1, ?)`,e.name,e.description??null,r,r,e.metadata?JSON.stringify(e.metadata):null);let s=E.get(t,"SELECT id FROM custom_workflows WHERE name = ?",e.name);if(!s)throw new Error(`Failed to create workflow: ${e.name}`);return s.id}getWorkflow(t,e){let r=E.get(t,"SELECT * FROM custom_workflows WHERE name = ?",e);return r?this.rowToWorkflow(r):null}getAllWorkflows(t,e=!1){let r=e?"SELECT * FROM custom_workflows ORDER BY is_builtin DESC, name ASC":"SELECT * FROM custom_workflows WHERE enabled = 1 ORDER BY is_builtin DESC, name ASC";return E.query(t,r).map(i=>this.rowToWorkflow(i))}updateWorkflow(t,e,r){if(!this.getWorkflow(t,e))return!1;let i=new Date().toISOString(),o=[],a=[];return r.description!==void 0&&(o.push("description = ?"),a.push(r.description)),r.enabled!==void 0&&(o.push("enabled = ?"),a.push(r.enabled?1:0)),r.metadata!==void 0&&(o.push("metadata = ?"),a.push(JSON.stringify(r.metadata))),o.length===0?!1:(o.push("updated_at = ?"),a.push(i),a.push(e),E.run(t,`UPDATE custom_workflows SET ${o.join(", ")} WHERE name = ?`,...a),!0)}deleteWorkflow(t,e){let r=this.getWorkflow(t,e);if(!r)return!1;if(r.isBuiltin)throw new Error(`Cannot delete built-in workflow: ${e}`);return E.run(t,"UPDATE custom_workflows SET enabled = 0 WHERE name = ?",e),!0}isBuiltin(t,e){return this.getWorkflow(t,e)?.isBuiltin??!1}isReservedName(t){let e=["task","done","ship","sync"],r=["add","rm","gate","list","create","delete","run","help","reset","init"];return e.includes(t)||r.includes(t)}isValidName(t){return/^[a-z0-9-]+$/.test(t)}rowToWorkflow(t){return{id:t.id,name:t.name,description:t.description,createdAt:t.created_at,updatedAt:t.updated_at,isBuiltin:t.is_builtin===1,enabled:t.enabled===1,metadata:t.metadata?JSON.parse(t.metadata):null}}},wt=new ce;function ue(n){let t=n.trust_source==="imported"?"imported":"local";return{id:n.id,type:n.type,command:n.command,position:n.position,action:n.action,description:n.description,enabled:n.enabled===1,timeoutMs:n.timeout_ms,createdAt:n.created_at,sortOrder:n.sort_order,whenExpr:n.when_expr??null,parallel:n.parallel===null?!0:n.parallel===1,trustSource:t}}c(ue,"rowToRule");var le=class{static{c(this,"WorkflowRuleStorage")}addRule(t,e){let r=y.get(t,"SELECT MAX(sort_order) as m FROM workflow_rules WHERE command = ?",e.command),s=e.sortOrder||(r?.m??-1)+1;return y.run(t,`INSERT INTO workflow_rules (type, command, position, action, description, enabled, timeout_ms, created_at, sort_order, when_expr, parallel, trust_source)
|
|
534
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,e.type,e.command,e.position,e.action,e.description??null,e.enabled?1:0,e.timeoutMs,e.createdAt,s,e.whenExpr??null,e.parallel===!1?0:1,e.trustSource??"local"),y.get(t,"SELECT last_insert_rowid() as id")?.id??0}removeRule(t,e){return y.get(t,"SELECT id FROM workflow_rules WHERE id = ?",e)?(y.run(t,"DELETE FROM workflow_rules WHERE id = ?",e),!0):!1}updateRule(t,e,r){if(!y.get(t,"SELECT id FROM workflow_rules WHERE id = ?",e))return!1;let i={type:{column:"type"},command:{column:"command"},position:{column:"position"},action:{column:"action"},description:{column:"description"},enabled:{column:"enabled",transform:c(u=>u?1:0,"transform")},timeoutMs:{column:"timeout_ms"},createdAt:{column:"created_at"},sortOrder:{column:"sort_order"},whenExpr:{column:"when_expr"},parallel:{column:"parallel",transform:c(u=>u===!1?0:1,"transform")},trustSource:{column:"trust_source"}},o=[],a=[];for(let[u,d]of Object.entries(r)){let m=i[u];if(!m)continue;o.push(`${m.column} = ?`);let p=d;a.push(m.transform?m.transform(p):p)}return o.length===0||(a.push(e),y.run(t,`UPDATE workflow_rules SET ${o.join(", ")} WHERE id = ?`,...a)),!0}getRuleById(t,e){let r=y.get(t,"SELECT * FROM workflow_rules WHERE id = ?",e);return r?ue(r):null}getRulesForCommand(t,e){let r=wt.getWorkflow(t,e);return!r||!r.enabled?[]:y.query(t,"SELECT * FROM workflow_rules WHERE command = ? AND enabled = 1 ORDER BY sort_order ASC",e).map(ue)}getAllRules(t){return y.query(t,"SELECT * FROM workflow_rules ORDER BY command ASC, sort_order ASC").map(ue)}resetRules(t){let e=y.get(t,"SELECT COUNT(*) as c FROM workflow_rules");return y.run(t,"DELETE FROM workflow_rules"),e?.c??0}},de=new le;function jr(n){let t=n;t.tool("prjct_workflow_rules","Get workflow rules for a command (gates, hooks, steps, instructions)",{projectPath:bt.string().describe("Project directory path"),command:bt.string().describe("Command name (task, done, ship, sync, etc.)")},b("prjct_workflow_rules",async e=>{let r=await v(e.projectPath),s=de.getRulesForCommand(r,e.command);if(s.length===0)return{content:[{type:"text",text:`No workflow rules for \`${e.command}\`.`}]};let i={};for(let a of s){let u=`${a.type}:${a.position}`;i[u]||(i[u]=[]),i[u].push(a)}let o=[`## Workflow Rules for \`${e.command}\``];for(let[a,u]of Object.entries(i)){o.push(`
|
|
535
535
|
### ${a}`);for(let d of u){let m=d.enabled?"":" (disabled)";o.push(`- ${d.action}${d.description?` \u2014 ${d.description}`:""}${m}`)}}return{content:[{type:"text",text:o.join(`
|
|
536
|
-
`)}]}})),t.tool("prjct_workflow_list","List all workflows for this project (built-in + custom)",{projectPath:
|
|
536
|
+
`)}]}})),t.tool("prjct_workflow_list","List all workflows for this project (built-in + custom)",{projectPath:bt.string().describe("Project directory path")},b("prjct_workflow_list",async e=>{let r=await v(e.projectPath),s=wt.getAllWorkflows(r);if(s.length===0)return{content:[{type:"text",text:"No workflows configured."}]};let i=s.map(o=>{let a=o.isBuiltin?"(built-in)":"(custom)",u=o.enabled?"":" [disabled]";return`- **${o.name}** ${a}${u}${o.description?`: ${o.description}`:""}`});return{content:[{type:"text",text:`## Workflows (${s.length})
|
|
537
537
|
|
|
538
538
|
${i.join(`
|
|
539
|
-
`)}`}]}})),t.tool("prjct_workflow_status","Current workflow execution state + active rules",{projectPath:
|
|
539
|
+
`)}`}]}})),t.tool("prjct_workflow_status","Current workflow execution state + active rules",{projectPath:bt.string().describe("Project directory path")},b("prjct_workflow_status",async e=>{let r=await v(e.projectPath),s=await J.getCurrentTask(r),i=de.getAllRules(r),o=["## Workflow Status"];s?(o.push(`
|
|
540
540
|
Active task: **${s.description}**`),o.push(`Started: ${s.startedAt}`)):o.push(`
|
|
541
541
|
No active task.`);let a=i.filter(u=>u.enabled);if(a.length>0){o.push(`
|
|
542
542
|
### Active Rules (${a.length})`);for(let u of a)o.push(`- [${u.type}] ${u.command}:${u.position} \u2192 ${u.action}`)}else o.push(`
|
|
543
543
|
No active workflow rules.`);return{content:[{type:"text",text:o.join(`
|
|
544
|
-
`)}]}}))}c(jr,"registerWorkflowTools");var
|
|
544
|
+
`)}]}}))}c(jr,"registerWorkflowTools");var yn=`# prjct \u2014 persona-aware context broker
|
|
545
545
|
|
|
546
546
|
Use when you want prior project memory, state, or a registered workflow. You decide whether any of it is relevant to the current turn.
|
|
547
547
|
|
|
@@ -556,4 +556,4 @@ Use when you want prior project memory, state, or a registered workflow. You dec
|
|
|
556
556
|
- Memory is best-effort \u2014 never assume recall returned everything; it's a query, not a lookup.
|
|
557
557
|
- Topic keys are free-form strings; don't invent new vocabularies when existing ones fit.
|
|
558
558
|
- Not every project defines every memory type \u2014 if one is empty, that's fine.
|
|
559
|
-
- Saving a secret-looking string is refused by default. Re-save with a scrubbed version.`;function Fr(){let n=new
|
|
559
|
+
- Saving a secret-looking string is refused by default. Re-save with a scrubbed version.`;function Fr(){let n=new Tn({name:"prjct",version:"1.0.0"},{instructions:yn});return Nr(n),Mr(n),Sr(n),jr(n),ar(n),n}c(Fr,"createServer");async function kn(){let n=Fr(),t=new En;await n.connect(t)}c(kn,"main");kn().catch(n=>{console.error("prjct MCP server failed:",n),process.exit(1)});
|