qlogicagent 2.18.3 → 2.18.4

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.
Files changed (34) hide show
  1. package/dist/agent.js +3 -3
  2. package/dist/cli.js +1 -1
  3. package/dist/index.js +458 -440
  4. package/dist/orchestration.js +1 -1
  5. package/dist/skills/mcp/astraclaw-native-mcp-server.js +6 -6
  6. package/dist/types/cli/handlers/community-handler.d.ts +1 -2
  7. package/dist/types/cli/handlers/memory-handler.d.ts +7 -0
  8. package/dist/types/protocol/methods.d.ts +0 -26
  9. package/dist/types/protocol/wire/agent-methods.d.ts +0 -11
  10. package/dist/types/protocol/wire/gateway-rpc.d.ts +1 -0
  11. package/dist/types/runtime/community/community-consent-client.d.ts +0 -21
  12. package/dist/types/runtime/hooks/memory-hooks.d.ts +6 -0
  13. package/dist/types/runtime/infra/agent-paths.d.ts +9 -7
  14. package/dist/types/runtime/infra/astraclaw-capabilities.d.ts +0 -6
  15. package/dist/types/runtime/infra/checkpoint-backend.d.ts +1 -1
  16. package/dist/types/runtime/infra/migrate-device-scope.d.ts +49 -0
  17. package/dist/types/runtime/infra/project-data-paths.d.ts +4 -3
  18. package/dist/types/runtime/infra/project-skill-manifest.d.ts +3 -2
  19. package/dist/types/runtime/ports/memory-provider.d.ts +21 -0
  20. package/dist/types/skills/memory/fts-segment.d.ts +20 -0
  21. package/dist/types/skills/memory/local-memory-provider.d.ts +52 -4
  22. package/dist/types/skills/memory/local-store-records.d.ts +6 -1
  23. package/dist/types/skills/memory/local-store.d.ts +61 -10
  24. package/dist/types/skills/memory/memdir.d.ts +10 -5
  25. package/dist/types/skills/memory/memory-consolidation.d.ts +7 -0
  26. package/dist/types/skills/memory/proposal-consumer.d.ts +51 -0
  27. package/dist/types/skills/memory/sqlite-memory-mappers.d.ts +2 -1
  28. package/dist/types/skills/memory/sqlite-memory-schema.d.ts +9 -1
  29. package/package.json +3 -2
  30. package/dist/types/cli/tool-bootstrap-community-registration.d.ts +0 -9
  31. package/dist/types/runtime/community/community-discovery-cache.d.ts +0 -24
  32. package/dist/types/runtime/community/community-discovery-coordinator.d.ts +0 -33
  33. package/dist/types/runtime/hooks/community-discovery-hook.d.ts +0 -18
  34. package/dist/types/skills/tools/community-seek-tool.d.ts +0 -49
@@ -16,7 +16,7 @@ New messages to integrate:`:void 0,C=U(p,{taskContext:m}),k=await this.config.su
16
16
  ${k}`},_=[...l,A,...d],E=Date.now()-o,b=_.reduce((f,g)=>f+this.config.estimateTokens(g),0);return{messages:_,droppedCount:p.length,strategy:"incremental-compact",metrics:{tokensBefore:u,tokensAfter:b,compressionRatio:u>0?b/u:1,latencyMs:E,usedLlm:!0,cacheInvalidated:!0}}}},P=class{config;constructor(t){this.config=t}compress(t,n){let o=R(t),r=this.config.inner.compress(t,n),s=R(r.messages),i=o!==s&&r.droppedCount>0;return i&&this.config.onCacheInvalidated?.({droppedCount:r.droppedCount,strategy:r.strategy}),{...r,metrics:{...r.metrics??{tokensBefore:0,tokensAfter:0,compressionRatio:0,latencyMs:0,usedLlm:!1},cacheInvalidated:i}}}async compressAsync(t,n){let o=R(t),r=B(this.config.inner)?await this.config.inner.compressAsync(t,n):this.config.inner.compress(t,n),s=R(r.messages),i=o!==s&&r.droppedCount>0;return i&&this.config.onCacheInvalidated?.({droppedCount:r.droppedCount,strategy:r.strategy}),{...r,metrics:{...r.metrics??{tokensBefore:0,tokensAfter:0,compressionRatio:0,latencyMs:0,usedLlm:!1},cacheInvalidated:i}}}},ne={modelContextWindow:128e3,targetUsageRatio:.75,minBudget:16e3,maxBudget:12e4};function st(e={}){let t={...ne,...e},n=Math.floor(t.modelContextWindow*t.targetUsageRatio);return Math.max(t.minBudget,Math.min(n,t.maxBudget))}function it(e,t){let n=e/t;return n<=.8?"none":n<=1?"trim-only":n<=1.5?"sliding-window":"llm-summarize"}var N=class{events=[];maxEvents;constructor(t=100){this.maxEvents=t}record(t){this.events.push(t),this.events.length>this.maxEvents&&this.events.shift()}snapshot(){let t=this.events.length;if(t===0)return{totalCompressions:0,totalLlmCalls:0,totalCacheInvalidations:0,averageCompressionRatio:1,averageLatencyMs:0,totalTokensSaved:0,recentEvents:[]};let n=0,o=0,r=0,s=0,i=0;for(let a of this.events)n+=a.tokensBefore>0?a.tokensAfter/a.tokensBefore:1,o+=a.latencyMs,r+=Math.max(0,a.tokensBefore-a.tokensAfter),a.usedLlm&&s++,a.cacheInvalidated&&i++;return{totalCompressions:t,totalLlmCalls:s,totalCacheInvalidations:i,averageCompressionRatio:n/t,averageLatencyMs:o/t,totalTokensSaved:r,recentEvents:this.events.slice(-10)}}reset(){this.events.length=0}},D=class{engines=new Map;activeId;register(t){this.engines.set(t.id,t)}activate(t){return this.engines.has(t)?(this.activeId=t,!0):!1}getActive(){return this.activeId?this.engines.get(this.activeId):void 0}listEngines(){return Array.from(this.engines.values()).map(t=>({id:t.id,label:t.label,active:t.id===this.activeId}))}};function oe(e){let t=[],n=[];for(let o of e)o.role==="system"?t.push(o):n.push(o);return{system:t,nonSystem:n}}function S(e){let t=typeof e.content=="string"?e.content:e.content!=null?JSON.stringify(e.content):"";return Math.ceil(t.length/4)}function R(e){let t=Math.min(e.length,5),n=[];for(let o=0;o<t;o++){let r=e[o],s=typeof r.content=="string"?r.content.slice(0,200):"";n.push(`${r.role}:${s}`)}return n.join("|")}var at=new Set(["file_read","read","Read","bash","shell","Bash","grep","search","Grep","grep_search","glob","Glob","file_search","web_search","WebSearch","web_fetch","WebFetch","file_edit","edit","Edit","file_write","write","Write"]),F=class{constructor(t=20,n=S){this.preserveRecentCount=t;this.estimateTokens=n}preserveRecentCount;estimateTokens;compress(t,n){if(t.length<=this.preserveRecentCount)return{messages:t,droppedCount:0,strategy:"micro-compact"};let o=new Map;for(let l of t){let c=l.tool_calls;if(Array.isArray(c))for(let u of c)u?.id&&u.function?.name&&o.set(u.id,u.function.name)}let r=t.length-this.preserveRecentCount,s=0,i=0;return{messages:t.map((l,c)=>{if(c>=r||l.role!=="tool"||typeof l.content!="string")return l;let u=l.name??o.get(l.tool_call_id??"");if(!u||!at.has(u)||l.content.length<=200)return l;let p=this.estimateTokens(l);return i+=p,s++,{...l,content:`[result cleared \u2014 ${l.content.length} chars]`}}),droppedCount:s,strategy:"micro-compact",metrics:s>0?{tokensBefore:0,tokensAfter:0,compressionRatio:0,latencyMs:0,usedLlm:!1,cacheInvalidated:!1}:void 0}}};function lt(e){let t=new Map;for(let n=0;n<e.length;n++){let o=e[n];if(o.tool_calls&&Array.isArray(o.tool_calls))for(let r of o.tool_calls){let s=r.function?.name??"";if(/read|edit|write|file/i.test(s)&&r.function?.arguments)try{let i=JSON.parse(r.function.arguments),a=i.path??i.filePath??i.file_path??i.file;a&&typeof a=="string"&&t.set(a,n)}catch{}}o.role==="tool"&&o.name&&/read|edit|write|file/i.test(o.name)}return[...t.entries()].sort((n,o)=>o[1]-n[1]).map(([n])=>n)}async function ct(e,t,n){let o=n.estimateTokens??(d=>Math.ceil(d.length/4)),r=lt(t);if(r.length===0)return e;let s=e.map(d=>typeof d.content=="string"?d.content:"").join(`
17
17
  `),i=r.filter(d=>!s.includes(d));if(i.length===0)return e;let a=n.maxTokenBudget,l=[],c=0;for(let d of i){if(c>=n.maxFiles||a<=0)break;let m=await n.readFile(d);if(!m)continue;let C=o(m);C>a||(a-=C,c++,l.push({role:"system",content:`[Post-compact file recovery: ${d}]
18
18
 
19
- ${m}`}))}if(l.length===0)return e;let u=[...e],p=-1;for(let d=0;d<u.length;d++)u[d].role==="system"&&(p=d);return u.splice(p+1,0,...l),u}function ut(e,t,n=S){if(t.size===0)return{messages:e,tokensFreed:0,removedCount:0};let o=0,r=0,s=[];for(let a of e){let l=a.tool_call_id??"";if(l&&t.has(l)){o+=n(a),r++,t.delete(l);continue}s.push(a)}let i=r>0?{role:"system",content:`[${r} messages removed by snip]`}:void 0;return{messages:s,tokensFreed:o,removedCount:r,boundaryMessage:i}}function pt(){return{stages:[]}}function dt(e,t,n){let o=n?.thresholdMessages??40;if(e.filter(a=>a.role!=="system").length<=o)return{messages:e,stagedCount:0};let s=re(e,t),i=ft(s,t,o);if(i.length===0)return{messages:s,stagedCount:0};for(let a of i)t.stages.push(a);return s=re(e,t),{messages:s,stagedCount:i.length}}function mt(e,t){let n=0;for(let o of t.stages)o.committed||(o.committed=!0,n++);return n===0?{messages:e,committed:0}:{messages:se(e,t),committed:n}}function re(e,t){return t.stages.filter(o=>o.committed).length===0?e:se(e,t)}function se(e,t){let n=t.stages.filter(r=>r.committed).sort((r,s)=>s.range[0]-r.range[0]),o=[...e];for(let r of n){let[s,i]=r.range;if(s>=o.length)continue;let a=Math.min(i,o.length),l={role:"system",content:r.summary};o.splice(s,a-s,l)}return o}function ft(e,t,n){let o=Math.max(0,e.length-Math.floor(n/2)),r=[],s=new Set(t.stages.map(l=>`${l.range[0]}-${l.range[1]}`)),i=-1,a=0;for(let l=0;l<o;l++){let c=e[l];if(c.role==="tool"||c.role==="assistant"&&typeof c.content=="string"&&c.content==="")i<0&&(i=l),a++;else{if(a>=3){let p=`${i}-${i+a}`;s.has(p)||r.push({id:`collapse_${i}_${i+a}`,range:[i,i+a],summary:`[${a} tool results collapsed]`,committed:!1})}i=-1,a=0}}if(a>=3){let l=`${i}-${i+a}`;s.has(l)||r.push({id:`collapse_${i}_${i+a}`,range:[i,i+a],summary:`[${a} tool results collapsed]`,committed:!1})}return r}import{readFileSync as gt,writeFileSync as yt,mkdirSync as Tt}from"node:fs";import{join as ht,dirname as Ct}from"node:path";var Ln=Math.min(Math.max(1,Number(process.env.TOOL_LOOP_DEFAULT_BUDGET)||25),100),Pn=Math.max(1e3,Number(process.env.TOOL_LOOP_TOOL_TIMEOUT_MS)||24e4);var ie=3,ae=2,le=300*1e3,ce=3,ue=720*60*60*1e3,G=4;var Nn=3600*1e3;var Dn=50*1024,Fn=500*1024,Bn=500*1024*1024,Un=50*1024*1024;var Gn=60*1024;var de=0;var _t="skill-patterns.json";function me(e){return ht(e,".qlogicagent",_t)}function fe(e){let t=me(e);try{return JSON.parse(gt(t,"utf8"))}catch{return{version:1,patterns:{}}}}function pe(e,t){let n=me(e);Tt(Ct(n),{recursive:!0}),yt(n,JSON.stringify(t,null,2),"utf8")}function bt(e){let t=Date.now()-ue;for(let[n,o]of Object.entries(e.patterns))new Date(o.lastSeen).getTime()<t&&delete e.patterns[n]}function ge(e,t){if(t.length===0)return!1;let n=ye(t),o=fe(e);bt(o);let r=new Date().toISOString(),s=o.patterns[n];if(s||(s={signature:n,count:0,firstSeen:r,lastSeen:r,promoted:!1},o.patterns[n]=s),s.promoted)return pe(e,o),!1;s.count++,s.lastSeen=r;let i=s.count>=ce;return i&&(s.promoted=!0),pe(e,o),i}function Rt(e){let t=fe(e);return Object.values(t.patterns)}function ye(e){return[...e].sort().join("+")}function St(e,t){return!(!e.ok||e.existingSkillName||!e.multiStep||e.toolCallCount<ie||e.distinctToolCount<ae||Date.now()-de<le||t?.projectRoot&&t.tools.length>0&&!ge(t.projectRoot,t.tools))}function xt(e){return e.existingSkillName?e.feedback==="negative":!1}function kt(e,t){return xt(e)?{type:"skill.improve",skillName:e.existingSkillName,reason:"negative user feedback on existing skill execution"}:St(e,t)?(de=Date.now(),{type:"skill.create",suggestedName:t.suggestedName??`auto-skill-${t.tools.slice(0,3).join("-")}`,description:`Multi-step orchestration using ${t.tools.join(", ")}`,tools:t.tools,stepCount:e.toolCallCount}):null}function At(e){return[...new Set(e.map(x).filter(Boolean))].sort((t,n)=>t.localeCompare(n))}function Te(e){let t=At(e);return t.length===0?"":`Available tools for this round: ${t.join(", ")}. Do not invent or attempt any tool outside this list. If the request needs a capability none of these tools cover, do not silently refuse: consider exec-based scripts/OS commands, use community_seek (when listed) to find an installable capability, and otherwise state plainly which capability is missing.`}function Et(e){let t=[...new Set(e.map(x).filter(Boolean))].sort((i,a)=>i.localeCompare(a)),n=new Set(t),o=Te(e),r=n.has("exec"),s=["read","search","write","edit","patch"].some(i=>n.has(i));return!r||!s?"You must call one of the available tools before responding. "+o:"You must call one of the available tools before responding. "+o+' Tool selection is part of correctness. Use read/search/write/edit/patch for file paths and file maintenance. For search, always include `mode` and `pattern`; examples: {"mode":"filename","pattern":"**/*.md"} or {"mode":"content","pattern":"TODO","fileGlob":"*.ts"}. Use exec only for shell commands with the required `command` field; never pass `path`, `filePath`, or file content to exec.'}function x(e){return e.function&&typeof e.function=="object"&&typeof e.function.name=="string"?e.function.name.trim():typeof e.name=="string"?e.name.trim():""}function Mt(e){return e==="enabled-eligible"||e==="installed-awaiting-approval"}function vt(e){return new Map((e??[]).map(t=>[t.toolName,t]))}function It(e){if(!e.eligibility?.length)return[...e.tools];let t=vt(e.eligibility);return e.tools.filter(n=>{let o=x(n);if(!o)return!1;let r=t.get(o);return!r||Mt(r.status)})}function wt(e){let t=[],n=e.compatibility??{},o=e.toolChoice;if(e.thinkingEnabled&&n.requireAutoWhenThinking){let r=typeof o=="object"&&o&&!Array.isArray(o)?String(o.type??""):o;r&&r!=="auto"&&r!=="none"&&(t.push("tool_choice downgraded to auto because thinking mode requires auto/none compatibility."),o="auto")}if(o==="required"&&n.allowRequiredToolChoice===!1){let r=n.requiredFallback??"auto";t.push(`tool_choice=required is not supported by this provider; downgraded to ${r}.`),o=r}if(o&&typeof o=="object"&&!Array.isArray(o)&&o.type==="function"&&n.allowNamedToolChoice===!1){let r=n.namedFallback??"required";t.push(`named tool_choice is not supported by this provider; downgraded to ${r}.`),o=r}return{normalizedToolChoice:o,warnings:t}}function Ot(e){let t=wt({toolChoice:e.toolChoice,thinkingEnabled:e.thinkingEnabled,compatibility:e.compatibility}),n=t.normalizedToolChoice,o=[...t.warnings],r=It({tools:e.tools,eligibility:e.eligibility});if(!n||n==="auto")return{tools:r,normalizedToolChoice:n,...r.length>0?{extraSystemPrompt:Te(r)}:{},warnings:o};if(n==="none")return{tools:[],normalizedToolChoice:"none",warnings:o};if(n==="required"){if(r.length===0)throw new Error("tool_choice=required but no tools were provided");return{tools:r,normalizedToolChoice:"required",extraSystemPrompt:Et(r),warnings:o}}if(typeof n=="object"&&!Array.isArray(n)&&n.type==="function"){let s=n.function??void 0,i=typeof s?.name=="string"?s.name.trim():"";if(!i)throw new Error("tool_choice.function.name is required");let a=r.filter(l=>x(l)===i);if(a.length===0)throw new Error(`tool_choice requested unknown tool: ${i}`);return{tools:a,normalizedToolChoice:{type:"function",function:{name:i}},extraSystemPrompt:`You must call the ${i} tool before responding.`,warnings:o}}return{tools:r,normalizedToolChoice:n,warnings:o}}var Lt=["stop","aborted","timeout","cancelled","interrupted","error"],Pt=["tool_calls","toolCalls","function_call","functionCall","raw_tool_calls","rawToolCalls"];function he(e){return e==null?[]:typeof e=="string"?e.length>0?[{type:"text",text:e}]:[]:Array.isArray(e)?e:[{type:"text",text:String(e)}]}function Nt(e,t){return{...e,content:[...he(e.content),...he(t.content)]}}function Dt(e){let t=new Set;if(e.role!=="assistant"||!Array.isArray(e.tool_calls))return t;for(let n of e.tool_calls)typeof n.id=="string"&&n.id&&t.add(n.id);return t}function Ft(e){let t=new Set,n=[];for(let o=0;o<e.length;o+=1){if(t.has(o))continue;let r=e[o];if(!r)continue;n.push(r);let s=Dt(r);if(s.size!==0)for(let i=o+1;i<e.length;i+=1){if(t.has(i))continue;let a=e[i];a?.role==="tool"&&typeof a.tool_call_id=="string"&&s.has(a.tool_call_id)&&(n.push(a),t.add(i))}}return n}function Bt(e){if(!e||typeof e!="object")return!1;if(e.function&&typeof e.function=="object"){let t=e.function.name;if(typeof t=="string"&&t.length>0)return!0}return typeof e.name=="string"&&e.name.length>0}function Ut(e){return new Set((e??Lt).map(t=>t.trim().toLowerCase()))}function Ce(e,t){return e?Ut(t).has(e.trim().toLowerCase()):!1}function Gt(e){let t=e.indexOf("|");return t<=0||t>=e.length-1?{callId:e}:{callId:e.slice(0,t),itemId:e.slice(t+1)}}function j(e){if(!Array.isArray(e)||e.length===0)return[...e];let t=e.map(l=>{if(l.role==="assistant"&&Array.isArray(l.tool_calls)){let c=l.tool_calls.filter(u=>Bt(u));return{...l,...c.length>0?{tool_calls:c}:{tool_calls:void 0}}}return{...l}}),n=new Set;for(let l of t)if(!(l.role!=="assistant"||!Array.isArray(l.tool_calls)))for(let c of l.tool_calls)typeof c.id=="string"&&c.id&&n.add(c.id);let o=t.filter(l=>l.role!=="tool"?!0:!!(l.tool_call_id&&n.has(l.tool_call_id))),r=new Set;for(let l of o)l.role==="tool"&&typeof l.tool_call_id=="string"&&l.tool_call_id&&r.add(l.tool_call_id);let s=[];for(let l of o){if(l.role==="assistant"&&Array.isArray(l.tool_calls)&&l.tool_calls.length>0){let c=l.tool_calls.filter(u=>typeof u.id=="string"&&r.has(u.id));if(c.length===0){let{tool_calls:u,...p}=l;p.content!=null&&p.content!==""&&s.push(p);continue}if(c.length<l.tool_calls.length){s.push({...l,tool_calls:c});continue}}s.push(l)}let i=Ft(s),a=[];for(let l of i){let c=a.length>0?a[a.length-1]:void 0;if(l.role==="user"&&c?.role==="user"){a[a.length-1]=Nt(c,l);continue}a.push(l)}return a}function $(e,t){return Ce(t?.stopReason,t?.forcedStopReasons)?e.map(n=>{if(n.role!=="assistant")return{...n};let o={...n};for(let r of Pt)delete o[r];return o}):[...e]}function H(e,t){let n=t?.placeholderToolResult??"Error: Tool loop interrupted before the tool result was replayed.",o=new Set;for(let s of e)s.role==="tool"&&typeof s.tool_call_id=="string"&&s.tool_call_id&&o.add(s.tool_call_id);let r=[];for(let s of e)if(r.push({...s}),!(s.role!=="assistant"||!Array.isArray(s.tool_calls)||s.tool_calls.length===0))for(let i of s.tool_calls)typeof i.id!="string"||!i.id||o.has(i.id)||(o.add(i.id),r.push({role:"tool",tool_call_id:i.id,content:n}));return r}function jt(e,t){let n=j(e),o=$(n,t);return H(o,t)}function _e(e,t){let n=t?.placeholderFunctionCallOutput??"Error: Tool loop interrupted before function_call_output was provided.",o=Ce(t?.stopReason,t?.forcedStopReasons),r=[];for(let c=0;c<e.length;c+=1){let u=e[c];if(!u||typeof u!="object"){r.push(u);continue}if(u.type==="reasoning"&&typeof u.id=="string"&&u.id.startsWith("rs_")&&!e.slice(c+1).some(m=>m&&typeof m=="object"&&m.type!=="reasoning"))continue;if(u.type!=="function_call"){r.push({...u});continue}let p={...u};if(typeof p.id=="string"){let d=Gt(p.id);d.itemId?.startsWith("fc_")&&(p.id=d.callId)}r.push(p)}let s=new Set,i=new Map;for(let c of r){if(c.type!=="function_call")continue;let u=typeof c.call_id=="string"&&c.call_id?c.call_id:typeof c.id=="string"?c.id:void 0;u&&(s.add(u),i.set(u,c))}let a=new Set,l=[];for(let c of r)if(!(o&&c.type==="function_call")){if(c.type==="function_call_output"){let u=typeof c.call_id=="string"?c.call_id:"";if(!u||!s.has(u))continue;a.add(u)}l.push(c)}for(let[c]of i)a.has(c)||o||l.push({type:"function_call_output",call_id:c,output:n});return l}function $t(e){let t=new Set,n=new Set;for(let o of e){if(o.role==="assistant"&&Array.isArray(o.tool_calls))for(let r of o.tool_calls)typeof r.id=="string"&&r.id&&t.add(r.id);o.role==="tool"&&typeof o.tool_call_id=="string"&&o.tool_call_id&&n.add(o.tool_call_id)}return[...t].filter(o=>!n.has(o))}function Ht(e){let t=new Set;for(let n of e)n.role==="tool"&&typeof n.tool_call_id=="string"&&n.tool_call_id&&t.add(n.tool_call_id);return[...t]}function zt(e){let t=new Set,n=new Set;for(let o of e){if(o.type==="function_call"){let r=typeof o.call_id=="string"&&o.call_id?o.call_id:typeof o.id=="string"?o.id:"";r&&t.add(r)}o.type==="function_call_output"&&typeof o.call_id=="string"&&o.call_id&&n.add(o.call_id)}return[...t].filter(o=>!n.has(o))}function qt(e){let t=new Set;for(let n of e)n.type==="function_call_output"&&typeof n.call_id=="string"&&n.call_id&&t.add(n.call_id);return[...t]}function be(e){return{round:e.round??0,maxRounds:e.maxRounds,pendingToolCallIds:[...e.pendingToolCallIds??[]],completedToolCallIds:[...e.completedToolCallIds??[]],lastStopReason:e.lastStopReason,replayMessages:[...e.replayMessages??[]]}}function Yt(e,t){return{round:e.round+1,maxRounds:e.maxRounds,pendingToolCallIds:[...t.pendingToolCallIds??e.pendingToolCallIds],completedToolCallIds:[...t.completedToolCallIds??e.completedToolCallIds],lastStopReason:t.lastStopReason??e.lastStopReason,replayMessages:[...t.replayMessages??e.replayMessages]}}function Xt(e,t){return{round:e.round,maxRounds:e.maxRounds,pendingToolCallIds:[],completedToolCallIds:[...t.completedToolCallIds??e.completedToolCallIds],lastStopReason:t.lastStopReason??e.lastStopReason,replayMessages:[...t.replayMessages??e.replayMessages]}}function Kt(e){let t=[],n=j(e.replayMessages);n.length!==e.replayMessages.length&&t.push({kind:"drop-orphan-tool-result",detail:"Removed orphan tool results or invalid assistant tool calls."});let o=$(n,e.options);o.some((s,i)=>s!==n[i])&&t.push({kind:"strip-forced-stop-tool-metadata",detail:"Removed assistant tool-call metadata after forced stop."});let r=H(o,e.options);return r.length>o.length&&t.push({kind:"inject-placeholder-tool-result",detail:"Injected placeholder tool result for pending tool calls."}),{state:be({maxRounds:e.maxRounds,round:e.round,lastStopReason:e.lastStopReason,replayMessages:r,pendingToolCallIds:$t(r),completedToolCallIds:Ht(r)}),recoveryActions:t}}function Wt(e){let t=_e(e.replayItems,e.options),n=[];return t.length!==e.replayItems.length&&n.push({kind:"drop-trailing-reasoning",detail:"Dropped dangling reasoning blocks or injected missing function_call_output items."}),t.some((o,r)=>o!==e.replayItems[r]&&o.type==="function_call")&&n.push({kind:"rewrite-openai-function-call-pair",detail:"Rewrote OpenAI function_call pairing ids for replay compatibility."}),{state:be({maxRounds:e.maxRounds,round:e.round,lastStopReason:e.lastStopReason,replayMessages:t,pendingToolCallIds:zt(t),completedToolCallIds:qt(t)}),recoveryActions:n}}var Vt=new Set(["main","sdk","agent","compact","hook","verification","side_question"]);function Jt(e){return e?Vt.has(e):!0}function Zt(e){return e===429||e===529}function Qt(e,t=500,n=32e3){let o=Math.min(t*Math.pow(2,e-1),n);return o+Math.floor(Math.random()*o*.25)}var Zn={maxBackoffMs:300*1e3,resetCapMs:360*60*1e3,heartbeatIntervalMs:3e4};function en(){let e=process.env.QLOGICAGENT_PERSISTENT_RETRY;return e==="1"||e==="true"}var z=class extends Error{constructor(n,o){super(`Model fallback triggered: ${n} -> ${o}`);this.originalModel=n;this.fallbackModel=o;this.name="FallbackTriggeredError"}originalModel;fallbackModel};var q="<fork-child-context>",Re="Fork started \u2014 processing in background";function tn(e){return JSON.stringify(e).includes(q)}function nn(e){return e<G}function on(e,t){let n=[...e.parentMessages],o=e.worktreePath?`
19
+ ${m}`}))}if(l.length===0)return e;let u=[...e],p=-1;for(let d=0;d<u.length;d++)u[d].role==="system"&&(p=d);return u.splice(p+1,0,...l),u}function ut(e,t,n=S){if(t.size===0)return{messages:e,tokensFreed:0,removedCount:0};let o=0,r=0,s=[];for(let a of e){let l=a.tool_call_id??"";if(l&&t.has(l)){o+=n(a),r++,t.delete(l);continue}s.push(a)}let i=r>0?{role:"system",content:`[${r} messages removed by snip]`}:void 0;return{messages:s,tokensFreed:o,removedCount:r,boundaryMessage:i}}function pt(){return{stages:[]}}function dt(e,t,n){let o=n?.thresholdMessages??40;if(e.filter(a=>a.role!=="system").length<=o)return{messages:e,stagedCount:0};let s=re(e,t),i=ft(s,t,o);if(i.length===0)return{messages:s,stagedCount:0};for(let a of i)t.stages.push(a);return s=re(e,t),{messages:s,stagedCount:i.length}}function mt(e,t){let n=0;for(let o of t.stages)o.committed||(o.committed=!0,n++);return n===0?{messages:e,committed:0}:{messages:se(e,t),committed:n}}function re(e,t){return t.stages.filter(o=>o.committed).length===0?e:se(e,t)}function se(e,t){let n=t.stages.filter(r=>r.committed).sort((r,s)=>s.range[0]-r.range[0]),o=[...e];for(let r of n){let[s,i]=r.range;if(s>=o.length)continue;let a=Math.min(i,o.length),l={role:"system",content:r.summary};o.splice(s,a-s,l)}return o}function ft(e,t,n){let o=Math.max(0,e.length-Math.floor(n/2)),r=[],s=new Set(t.stages.map(l=>`${l.range[0]}-${l.range[1]}`)),i=-1,a=0;for(let l=0;l<o;l++){let c=e[l];if(c.role==="tool"||c.role==="assistant"&&typeof c.content=="string"&&c.content==="")i<0&&(i=l),a++;else{if(a>=3){let p=`${i}-${i+a}`;s.has(p)||r.push({id:`collapse_${i}_${i+a}`,range:[i,i+a],summary:`[${a} tool results collapsed]`,committed:!1})}i=-1,a=0}}if(a>=3){let l=`${i}-${i+a}`;s.has(l)||r.push({id:`collapse_${i}_${i+a}`,range:[i,i+a],summary:`[${a} tool results collapsed]`,committed:!1})}return r}import{readFileSync as gt,writeFileSync as yt,mkdirSync as Tt}from"node:fs";import{join as ht,dirname as Ct}from"node:path";var Ln=Math.min(Math.max(1,Number(process.env.TOOL_LOOP_DEFAULT_BUDGET)||25),100),Pn=Math.max(1e3,Number(process.env.TOOL_LOOP_TOOL_TIMEOUT_MS)||24e4);var ie=3,ae=2,le=300*1e3,ce=3,ue=720*60*60*1e3,G=4;var Nn=3600*1e3;var Dn=50*1024,Fn=500*1024,Bn=500*1024*1024,Un=50*1024*1024;var Gn=60*1024;var de=0;var _t="skill-patterns.json";function me(e){return ht(e,".qlogicagent",_t)}function fe(e){let t=me(e);try{return JSON.parse(gt(t,"utf8"))}catch{return{version:1,patterns:{}}}}function pe(e,t){let n=me(e);Tt(Ct(n),{recursive:!0}),yt(n,JSON.stringify(t,null,2),"utf8")}function bt(e){let t=Date.now()-ue;for(let[n,o]of Object.entries(e.patterns))new Date(o.lastSeen).getTime()<t&&delete e.patterns[n]}function ge(e,t){if(t.length===0)return!1;let n=ye(t),o=fe(e);bt(o);let r=new Date().toISOString(),s=o.patterns[n];if(s||(s={signature:n,count:0,firstSeen:r,lastSeen:r,promoted:!1},o.patterns[n]=s),s.promoted)return pe(e,o),!1;s.count++,s.lastSeen=r;let i=s.count>=ce;return i&&(s.promoted=!0),pe(e,o),i}function Rt(e){let t=fe(e);return Object.values(t.patterns)}function ye(e){return[...e].sort().join("+")}function St(e,t){return!(!e.ok||e.existingSkillName||!e.multiStep||e.toolCallCount<ie||e.distinctToolCount<ae||Date.now()-de<le||t?.projectRoot&&t.tools.length>0&&!ge(t.projectRoot,t.tools))}function xt(e){return e.existingSkillName?e.feedback==="negative":!1}function kt(e,t){return xt(e)?{type:"skill.improve",skillName:e.existingSkillName,reason:"negative user feedback on existing skill execution"}:St(e,t)?(de=Date.now(),{type:"skill.create",suggestedName:t.suggestedName??`auto-skill-${t.tools.slice(0,3).join("-")}`,description:`Multi-step orchestration using ${t.tools.join(", ")}`,tools:t.tools,stepCount:e.toolCallCount}):null}function At(e){return[...new Set(e.map(x).filter(Boolean))].sort((t,n)=>t.localeCompare(n))}function Te(e){let t=At(e);return t.length===0?"":`Available tools for this round: ${t.join(", ")}. Do not invent or attempt any tool outside this list. If the request needs a capability none of these tools cover, do not silently refuse: consider exec-based scripts/OS commands, and otherwise state plainly which capability is missing.`}function Et(e){let t=[...new Set(e.map(x).filter(Boolean))].sort((i,a)=>i.localeCompare(a)),n=new Set(t),o=Te(e),r=n.has("exec"),s=["read","search","write","edit","patch"].some(i=>n.has(i));return!r||!s?"You must call one of the available tools before responding. "+o:"You must call one of the available tools before responding. "+o+' Tool selection is part of correctness. Use read/search/write/edit/patch for file paths and file maintenance. For search, always include `mode` and `pattern`; examples: {"mode":"filename","pattern":"**/*.md"} or {"mode":"content","pattern":"TODO","fileGlob":"*.ts"}. Use exec only for shell commands with the required `command` field; never pass `path`, `filePath`, or file content to exec.'}function x(e){return e.function&&typeof e.function=="object"&&typeof e.function.name=="string"?e.function.name.trim():typeof e.name=="string"?e.name.trim():""}function Mt(e){return e==="enabled-eligible"||e==="installed-awaiting-approval"}function vt(e){return new Map((e??[]).map(t=>[t.toolName,t]))}function It(e){if(!e.eligibility?.length)return[...e.tools];let t=vt(e.eligibility);return e.tools.filter(n=>{let o=x(n);if(!o)return!1;let r=t.get(o);return!r||Mt(r.status)})}function wt(e){let t=[],n=e.compatibility??{},o=e.toolChoice;if(e.thinkingEnabled&&n.requireAutoWhenThinking){let r=typeof o=="object"&&o&&!Array.isArray(o)?String(o.type??""):o;r&&r!=="auto"&&r!=="none"&&(t.push("tool_choice downgraded to auto because thinking mode requires auto/none compatibility."),o="auto")}if(o==="required"&&n.allowRequiredToolChoice===!1){let r=n.requiredFallback??"auto";t.push(`tool_choice=required is not supported by this provider; downgraded to ${r}.`),o=r}if(o&&typeof o=="object"&&!Array.isArray(o)&&o.type==="function"&&n.allowNamedToolChoice===!1){let r=n.namedFallback??"required";t.push(`named tool_choice is not supported by this provider; downgraded to ${r}.`),o=r}return{normalizedToolChoice:o,warnings:t}}function Ot(e){let t=wt({toolChoice:e.toolChoice,thinkingEnabled:e.thinkingEnabled,compatibility:e.compatibility}),n=t.normalizedToolChoice,o=[...t.warnings],r=It({tools:e.tools,eligibility:e.eligibility});if(!n||n==="auto")return{tools:r,normalizedToolChoice:n,...r.length>0?{extraSystemPrompt:Te(r)}:{},warnings:o};if(n==="none")return{tools:[],normalizedToolChoice:"none",warnings:o};if(n==="required"){if(r.length===0)throw new Error("tool_choice=required but no tools were provided");return{tools:r,normalizedToolChoice:"required",extraSystemPrompt:Et(r),warnings:o}}if(typeof n=="object"&&!Array.isArray(n)&&n.type==="function"){let s=n.function??void 0,i=typeof s?.name=="string"?s.name.trim():"";if(!i)throw new Error("tool_choice.function.name is required");let a=r.filter(l=>x(l)===i);if(a.length===0)throw new Error(`tool_choice requested unknown tool: ${i}`);return{tools:a,normalizedToolChoice:{type:"function",function:{name:i}},extraSystemPrompt:`You must call the ${i} tool before responding.`,warnings:o}}return{tools:r,normalizedToolChoice:n,warnings:o}}var Lt=["stop","aborted","timeout","cancelled","interrupted","error"],Pt=["tool_calls","toolCalls","function_call","functionCall","raw_tool_calls","rawToolCalls"];function he(e){return e==null?[]:typeof e=="string"?e.length>0?[{type:"text",text:e}]:[]:Array.isArray(e)?e:[{type:"text",text:String(e)}]}function Nt(e,t){return{...e,content:[...he(e.content),...he(t.content)]}}function Dt(e){let t=new Set;if(e.role!=="assistant"||!Array.isArray(e.tool_calls))return t;for(let n of e.tool_calls)typeof n.id=="string"&&n.id&&t.add(n.id);return t}function Ft(e){let t=new Set,n=[];for(let o=0;o<e.length;o+=1){if(t.has(o))continue;let r=e[o];if(!r)continue;n.push(r);let s=Dt(r);if(s.size!==0)for(let i=o+1;i<e.length;i+=1){if(t.has(i))continue;let a=e[i];a?.role==="tool"&&typeof a.tool_call_id=="string"&&s.has(a.tool_call_id)&&(n.push(a),t.add(i))}}return n}function Bt(e){if(!e||typeof e!="object")return!1;if(e.function&&typeof e.function=="object"){let t=e.function.name;if(typeof t=="string"&&t.length>0)return!0}return typeof e.name=="string"&&e.name.length>0}function Ut(e){return new Set((e??Lt).map(t=>t.trim().toLowerCase()))}function Ce(e,t){return e?Ut(t).has(e.trim().toLowerCase()):!1}function Gt(e){let t=e.indexOf("|");return t<=0||t>=e.length-1?{callId:e}:{callId:e.slice(0,t),itemId:e.slice(t+1)}}function j(e){if(!Array.isArray(e)||e.length===0)return[...e];let t=e.map(l=>{if(l.role==="assistant"&&Array.isArray(l.tool_calls)){let c=l.tool_calls.filter(u=>Bt(u));return{...l,...c.length>0?{tool_calls:c}:{tool_calls:void 0}}}return{...l}}),n=new Set;for(let l of t)if(!(l.role!=="assistant"||!Array.isArray(l.tool_calls)))for(let c of l.tool_calls)typeof c.id=="string"&&c.id&&n.add(c.id);let o=t.filter(l=>l.role!=="tool"?!0:!!(l.tool_call_id&&n.has(l.tool_call_id))),r=new Set;for(let l of o)l.role==="tool"&&typeof l.tool_call_id=="string"&&l.tool_call_id&&r.add(l.tool_call_id);let s=[];for(let l of o){if(l.role==="assistant"&&Array.isArray(l.tool_calls)&&l.tool_calls.length>0){let c=l.tool_calls.filter(u=>typeof u.id=="string"&&r.has(u.id));if(c.length===0){let{tool_calls:u,...p}=l;p.content!=null&&p.content!==""&&s.push(p);continue}if(c.length<l.tool_calls.length){s.push({...l,tool_calls:c});continue}}s.push(l)}let i=Ft(s),a=[];for(let l of i){let c=a.length>0?a[a.length-1]:void 0;if(l.role==="user"&&c?.role==="user"){a[a.length-1]=Nt(c,l);continue}a.push(l)}return a}function $(e,t){return Ce(t?.stopReason,t?.forcedStopReasons)?e.map(n=>{if(n.role!=="assistant")return{...n};let o={...n};for(let r of Pt)delete o[r];return o}):[...e]}function H(e,t){let n=t?.placeholderToolResult??"Error: Tool loop interrupted before the tool result was replayed.",o=new Set;for(let s of e)s.role==="tool"&&typeof s.tool_call_id=="string"&&s.tool_call_id&&o.add(s.tool_call_id);let r=[];for(let s of e)if(r.push({...s}),!(s.role!=="assistant"||!Array.isArray(s.tool_calls)||s.tool_calls.length===0))for(let i of s.tool_calls)typeof i.id!="string"||!i.id||o.has(i.id)||(o.add(i.id),r.push({role:"tool",tool_call_id:i.id,content:n}));return r}function jt(e,t){let n=j(e),o=$(n,t);return H(o,t)}function _e(e,t){let n=t?.placeholderFunctionCallOutput??"Error: Tool loop interrupted before function_call_output was provided.",o=Ce(t?.stopReason,t?.forcedStopReasons),r=[];for(let c=0;c<e.length;c+=1){let u=e[c];if(!u||typeof u!="object"){r.push(u);continue}if(u.type==="reasoning"&&typeof u.id=="string"&&u.id.startsWith("rs_")&&!e.slice(c+1).some(m=>m&&typeof m=="object"&&m.type!=="reasoning"))continue;if(u.type!=="function_call"){r.push({...u});continue}let p={...u};if(typeof p.id=="string"){let d=Gt(p.id);d.itemId?.startsWith("fc_")&&(p.id=d.callId)}r.push(p)}let s=new Set,i=new Map;for(let c of r){if(c.type!=="function_call")continue;let u=typeof c.call_id=="string"&&c.call_id?c.call_id:typeof c.id=="string"?c.id:void 0;u&&(s.add(u),i.set(u,c))}let a=new Set,l=[];for(let c of r)if(!(o&&c.type==="function_call")){if(c.type==="function_call_output"){let u=typeof c.call_id=="string"?c.call_id:"";if(!u||!s.has(u))continue;a.add(u)}l.push(c)}for(let[c]of i)a.has(c)||o||l.push({type:"function_call_output",call_id:c,output:n});return l}function $t(e){let t=new Set,n=new Set;for(let o of e){if(o.role==="assistant"&&Array.isArray(o.tool_calls))for(let r of o.tool_calls)typeof r.id=="string"&&r.id&&t.add(r.id);o.role==="tool"&&typeof o.tool_call_id=="string"&&o.tool_call_id&&n.add(o.tool_call_id)}return[...t].filter(o=>!n.has(o))}function Ht(e){let t=new Set;for(let n of e)n.role==="tool"&&typeof n.tool_call_id=="string"&&n.tool_call_id&&t.add(n.tool_call_id);return[...t]}function zt(e){let t=new Set,n=new Set;for(let o of e){if(o.type==="function_call"){let r=typeof o.call_id=="string"&&o.call_id?o.call_id:typeof o.id=="string"?o.id:"";r&&t.add(r)}o.type==="function_call_output"&&typeof o.call_id=="string"&&o.call_id&&n.add(o.call_id)}return[...t].filter(o=>!n.has(o))}function qt(e){let t=new Set;for(let n of e)n.type==="function_call_output"&&typeof n.call_id=="string"&&n.call_id&&t.add(n.call_id);return[...t]}function be(e){return{round:e.round??0,maxRounds:e.maxRounds,pendingToolCallIds:[...e.pendingToolCallIds??[]],completedToolCallIds:[...e.completedToolCallIds??[]],lastStopReason:e.lastStopReason,replayMessages:[...e.replayMessages??[]]}}function Yt(e,t){return{round:e.round+1,maxRounds:e.maxRounds,pendingToolCallIds:[...t.pendingToolCallIds??e.pendingToolCallIds],completedToolCallIds:[...t.completedToolCallIds??e.completedToolCallIds],lastStopReason:t.lastStopReason??e.lastStopReason,replayMessages:[...t.replayMessages??e.replayMessages]}}function Xt(e,t){return{round:e.round,maxRounds:e.maxRounds,pendingToolCallIds:[],completedToolCallIds:[...t.completedToolCallIds??e.completedToolCallIds],lastStopReason:t.lastStopReason??e.lastStopReason,replayMessages:[...t.replayMessages??e.replayMessages]}}function Kt(e){let t=[],n=j(e.replayMessages);n.length!==e.replayMessages.length&&t.push({kind:"drop-orphan-tool-result",detail:"Removed orphan tool results or invalid assistant tool calls."});let o=$(n,e.options);o.some((s,i)=>s!==n[i])&&t.push({kind:"strip-forced-stop-tool-metadata",detail:"Removed assistant tool-call metadata after forced stop."});let r=H(o,e.options);return r.length>o.length&&t.push({kind:"inject-placeholder-tool-result",detail:"Injected placeholder tool result for pending tool calls."}),{state:be({maxRounds:e.maxRounds,round:e.round,lastStopReason:e.lastStopReason,replayMessages:r,pendingToolCallIds:$t(r),completedToolCallIds:Ht(r)}),recoveryActions:t}}function Wt(e){let t=_e(e.replayItems,e.options),n=[];return t.length!==e.replayItems.length&&n.push({kind:"drop-trailing-reasoning",detail:"Dropped dangling reasoning blocks or injected missing function_call_output items."}),t.some((o,r)=>o!==e.replayItems[r]&&o.type==="function_call")&&n.push({kind:"rewrite-openai-function-call-pair",detail:"Rewrote OpenAI function_call pairing ids for replay compatibility."}),{state:be({maxRounds:e.maxRounds,round:e.round,lastStopReason:e.lastStopReason,replayMessages:t,pendingToolCallIds:zt(t),completedToolCallIds:qt(t)}),recoveryActions:n}}var Vt=new Set(["main","sdk","agent","compact","hook","verification","side_question"]);function Jt(e){return e?Vt.has(e):!0}function Zt(e){return e===429||e===529}function Qt(e,t=500,n=32e3){let o=Math.min(t*Math.pow(2,e-1),n);return o+Math.floor(Math.random()*o*.25)}var Zn={maxBackoffMs:300*1e3,resetCapMs:360*60*1e3,heartbeatIntervalMs:3e4};function en(){let e=process.env.QLOGICAGENT_PERSISTENT_RETRY;return e==="1"||e==="true"}var z=class extends Error{constructor(n,o){super(`Model fallback triggered: ${n} -> ${o}`);this.originalModel=n;this.fallbackModel=o;this.name="FallbackTriggeredError"}originalModel;fallbackModel};var q="<fork-child-context>",Re="Fork started \u2014 processing in background";function tn(e){return JSON.stringify(e).includes(q)}function nn(e){return e<G}function on(e,t){let n=[...e.parentMessages],o=e.worktreePath?`
20
20
 
21
21
  Your working directory is: ${e.worktreePath}
22
22
  All file paths should be relative to this directory.`:"",r={role:"user",content:[{type:"text",text:`${q}
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import{createInterface as Ze}from"node:readline";import{existsSync as Xe,readFileSync as et}from"node:fs";import{readFileSync as Se}from"node:fs";import{randomUUID as we}from"node:crypto";import{readdirSync as _t,readFileSync as Ct,statSync as se,writeFileSync as xt}from"node:fs";import{readdir as ie,readFile as ae,stat as le,writeFile as ce}from"node:fs/promises";import{join as d}from"node:path";import{homedir as Q}from"node:os";import{join as c,resolve as ut}from"node:path";import{existsSync as pt}from"node:fs";import{createHash as ft}from"node:crypto";var P=".qlogicagent";function Y(){return process.env.QLOGICAGENT_HOME||c(Q(),P)}function Z(){let t=process.env.QLOGIC_LLMROUTER_USER_ID?.trim();if(t)return t;let e=process.env.QLOGIC_IMPLICIT_OWNER_ID?.trim();if(e)return e;let r=process.env.QLOGIC_DEVICE_ID?.trim();return r?`oc_${r}`:"oc_local"}function X(t){let e=t.trim();if(!e)throw new Error("ownerUserId is required for profile-scoped storage");return encodeURIComponent(e).replace(/\./g,"%2E")}function m(t=Z()){return c(Y(),"profiles",X(t))}function v(){return c(m(),"skills")}function _(){return c(m(),"mcp.json")}function ee(t){if(!t)throw new Error("getProjectAgentDir: cwd is required (must not fall back to process.cwd())");return c(t,P)}function C(t){return c(ee(t),"skills-disabled.json")}import{readFileSync as te,writeFileSync as yt,mkdirSync as vt,renameSync as bt}from"node:fs";import{dirname as wt,join as re}from"node:path";function f(){return{version:1,disabled:[]}}function oe(t){let e;try{e=te(t,"utf8")}catch(n){return n.code==="ENOENT"?{list:f(),corrupt:!1}:(console.error(`[project-skill-manifest] Cannot read skill mute list at ${t} (${n instanceof Error?n.message:String(n)}); treating it as empty for reads \u2014 muted skills may reactivate.`),{list:f(),corrupt:!0})}let r;try{r=JSON.parse(e)}catch(n){return console.error(`[project-skill-manifest] Skill mute list at ${t} is corrupted (${n instanceof Error?n.message:String(n)}); treating it as empty for reads \u2014 muted skills may reactivate.`),{list:f(),corrupt:!0}}return!r||typeof r!="object"||!Array.isArray(r.disabled)?(console.error(`[project-skill-manifest] Skill mute list at ${t} has an unexpected shape; treating it as empty for reads \u2014 muted skills may reactivate.`),{list:f(),corrupt:!0}):{list:{version:1,disabled:[...new Set(r.disabled.filter(n=>typeof n=="string"&&n.trim().length>0))]},corrupt:!1}}function x(t){return oe(t).list}function ne(){return re(m(),"skills-disabled.json")}function A(){return new Set(x(ne()).disabled)}function R(t){return new Set(x(C(t)).disabled)}var ue=["auto-skill-","test-skill-"],de=".skills_prompt_snapshot.json";function pe(t){return ue.some(e=>t.startsWith(e))}function me(t){let e=t.replace(/\r\n/g,`
3
- `),r=e.match(/^---\n[\s\S]*?^version:\s*(\S+)/m),o=e.match(/^---\n[\s\S]*?^category:\s*(.+)/m),n=e.match(/^---\n[\s\S]*?^author:\s*(.+)/m),i=e.match(/^---\n[\s\S]*?^requires:\s*(.+)/m),s=e.match(/^---\n[\s\S]*?^environments:\s*(.+)/m),a=e.match(/^---\n([\s\S]*?)\n---/)?.[1]??"";return{version:r?.[1],description:fe(a),category:o?.[1]?.trim()||void 0,author:n?.[1]?.trim()||void 0,requiredTools:M(i?.[1]),environments:M(s?.[1])}}function fe(t){let e=t.split(`
4
- `),r=e.findIndex(s=>/^description:/.test(s));if(r===-1)return;let o=e[r].replace(/^description:[ \t]*/,"").trim(),n=/^[>|][+-]?$/.test(o),i=[];!n&&o&&i.push(o);for(let s=r+1;s<e.length;s++){let a=e[s];if(!/^[ \t]/.test(a))break;let l=a.trim();l&&i.push(l)}if(i.length!==0)return i.join(" ").replace(/^["']|["']$/g,"").trim()||void 0}var E=new Map,b=new Map;function ge(t,e,r,o){let n=e.has(t.name),i=r.has(t.name),s=!ve(t.meta,o);return{name:t.name,filePath:t.filePath,baseDir:t.baseDir,globallyDisabled:n,projectDisabled:i,active:!n&&!i&&!s,systemGenerated:t.systemGenerated,description:t.meta.description,version:t.meta.version,category:t.meta.category,author:t.meta.author,requiredTools:t.meta.requiredTools,environments:t.meta.environments}}async function he(t){let e;try{e=await ie(t,{withFileTypes:!0})}catch{e=[]}let r=[];for(let s of e){if(!s.isDirectory()||s.name.startsWith("."))continue;let a=d(t,s.name),l=d(a,"SKILL.md");try{let y=await le(l);if(!y.isFile())continue;r.push({name:s.name,filePath:l,baseDir:a,mtimeMs:y.mtimeMs,size:y.size})}catch{continue}}r.sort((s,a)=>s.name.localeCompare(a.name));let o=r.map(s=>`${s.name}:${s.mtimeMs}:${s.size}`).join("|"),n=E.get(t);if(n&&n.fingerprint===o)return n.raw;let i=[];for(let s of r){let a;try{a=await ae(s.filePath,"utf8")}catch{continue}i.push({name:s.name,filePath:s.filePath,baseDir:s.baseDir,systemGenerated:pe(s.name),mtimeMs:s.mtimeMs,size:s.size,meta:me(a)})}return E.set(t,{fingerprint:o,raw:i}),be(t,i),i}async function ye(t,e){let r=v(),o=A(),n=t?R(t):new Set,i=b.get(r);return i||(i=he(r).finally(()=>b.delete(r)),b.set(r,i)),(await i).map(a=>ge(a,o,n,e))}async function D(t,e){return(await ye(t,e)).filter(r=>r.active)}function j(t){let e=v(),r=d(e,t),o=d(r,"SKILL.md");try{if(se(o).isFile())return{baseDir:r,filePath:o}}catch{}return null}function M(t){if(!t)return;let e=t.replace(/^\[|\]$/g,"").split(/[,\s]+/).map(r=>r.replace(/^["']|["']$/g,"").trim()).filter(Boolean);return e.length>0?e:void 0}function ve(t,e){if(t.environments&&e?.currentEnvironment&&!t.environments.includes(e.currentEnvironment))return!1;if(t.requiredTools){if(!e?.availableToolNames)return!1;let r=new Set(e.availableToolNames);return t.requiredTools.every(o=>r.has(o))}return!0}async function be(t,e){try{let o={version:1,entries:e.map(n=>({name:n.name,size:n.size,mtimeMs:n.mtimeMs,description:n.meta.description,version:n.meta.version,requiredTools:n.meta.requiredTools,environments:n.meta.environments}))};await ce(d(t,de),JSON.stringify(o,null,2),"utf8")}catch{}}var I="astraclaw_capabilities";async function L(t){if(t.tool==="skills_list")return{handled:!0,result:{skills:(await D(t.projectRoot,{availableToolNames:t.availableToolNames,currentEnvironment:t.currentEnvironment??process.platform})).map(Te)}};if(t.tool==="skill_view"){let e=typeof t.args.name=="string"?t.args.name.trim():"";if(!e)throw new Error("skill_view requires a skill name");let r=j(e);if(!r)throw new Error(`Skill not found: ${e}`);return{handled:!0,result:{name:e,content:Se(r.filePath,"utf8")}}}if(t.tool==="mcp_connectors_list"){let e=t.mcpServerFailures??[],r=e.length>0?{failedServers:e,note:`${e.length} configured MCP server(s) are unavailable this session; their tools are missing from this list.`}:{};if(!t.toolCatalog)return{handled:!0,result:{tools:[],note:"AstraClaw MCP connector catalog is not attached to this capability server instance.",...e.length>0?{failedServers:e}:{}}};let o=t.toolCatalog.getToolManifest().filter(n=>n.function.name.startsWith("mcp__")).map(n=>({toolName:n.function.name,server:Pe(n.function.name),name:_e(n.function.name),description:n.function.description,inputSchema:n.function.parameters}));return{handled:!0,result:{tools:o,count:o.length,...r}}}if(t.tool==="mcp_tool_call"){if(!t.toolCatalog)throw new Error("AstraClaw MCP connector catalog is not attached");let e=typeof t.args.toolName=="string"?t.args.toolName.trim():"";if(!e.startsWith("mcp__"))throw new Error("mcp_tool_call requires a connector toolName returned by mcp_connectors_list");let r=t.toolCatalog.findTool(e);if(!r?.execute)throw new Error(`MCP connector tool not found or not executable: ${e}`);let o=ke(t.args.args),n=`astraclaw_mcp_${we().slice(0,8)}`,i=await r.execute(n,o);return{handled:!0,result:{toolName:e,content:i.content,details:i.details,imageUrls:i.imageUrls}}}return{handled:!1}}function Te(t){return{name:t.name,description:t.description,version:t.version,category:t.category,requiredTools:t.requiredTools,environments:t.environments}}function ke(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)?t:{}}function Pe(t){let e=t.split("__");return e.length>=3?e[1]??"":""}function _e(t){let e=t.split("__");return e.length>=3?e.slice(2).join("__"):t}import p from"node:path";import{fileURLToPath as Ee}from"node:url";import{createRuntime as Me}from"mcporter";var O=new Set(["gateway","agents_list","session_status","sessions_send","sessions_list","sessions_history","sessions_spawn","cron","config","workflow"]),Ce=new Set([...O,"agent"]);function $(t){return t?.riskLevel?t.riskLevel:t?.isDangerous?"system":t?.isReadOnly?"read":t?.isEgress?"external_egress":"write"}var S=class{toolPool=new Map;setTools(e){this.toolPool.clear();for(let r of e)this.toolPool.set(r.name,r)}addTool(e){this.toolPool.set(e.name,e)}addTools(e){for(let r of e)this.addTool(r)}removeTool(e){return this.toolPool.delete(e)}findTool(e){return this.toolPool.get(e)}hasTool(e){return this.toolPool.has(e)}getToolNames(){return Array.from(this.toolPool.keys())}getToolCount(){return this.toolPool.size}async executeTool(e,r,o,n){let i=this.toolPool.get(e);if(!i)throw new Error(`Tool not found: ${e}`);return i.execute(r,o,n)}getTools(){return Array.from(this.toolPool.values()).filter(e=>e.isEnabled?.()!==!1)}getToolManifest(){let e=[];for(let r of this.toolPool.values()){if(r.isEnabled?.()===!1)continue;let o=$(r);e.push({type:"function",function:{name:r.name,description:r.description,parameters:r.parameters},meta:{category:r.category??"other",displayName:r.displayName??{key:`capability.tool.${r.name}.name`,fallback:r.label},displayDescription:r.displayDescription??{key:`capability.tool.${r.name}.description`,fallback:""},parallelSafe:r.isConcurrencySafe??!1,riskLevel:o,isReadOnly:o==="read",isDangerous:o==="system",isDelete:r.isDelete??!1,isEgress:r.isEgress??o==="external_egress",egressCarriesData:r.egressCarriesData??!1}})}return e}},N=new S;function F(t){N.addTools(t)}function q(t){return N.removeTool(t)}var xe=new Set(["describe","fetch","find","get","inspect","list","query","read","search","stat"]),Ae=new Set(["append","copy","create","delete","edit","move","patch","remove","rename","set","update","upload","write"]);function U(t){let e=t.annotations,r=Re(t.name),o=r.some(l=>Ae.has(l)),n=r.some(l=>xe.has(l)),i=e?.destructiveHint===!0||o,s=e?.readOnlyHint===!0||!i&&n,a=s||e?.idempotentHint===!0&&!i;return{isReadOnly:s,isConcurrencySafe:a,isDestructive:i}}function Re(t){return t.replace(/([a-z0-9])([A-Z])/g,"$1_$2").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean)}var De=12e4,g=3,je=1e3;async function Ie(t,e){let r=e.sleep??(i=>new Promise(s=>setTimeout(s,i))),o=Math.max(1,e.attempts),n;for(let i=1;i<=o;i++)try{return await t()}catch(s){n=s,i<o&&(e.onRetry?.(i,s),await r(e.baseDelayMs*i))}throw n}var h=class{runtime=null;definitions=[];toolsByServer=new Map;injectedNames=new Set;log;workspaceRoot;toolCatalog;serverToolFilters=new Map;serverOAuth=new Map;failedServers=new Map;constructor(e){this.log=e.log??{info:()=>{},warn:()=>{}},this.workspaceRoot=e.workspaceRoot?p.resolve(e.workspaceRoot):void 0,this.toolCatalog=e.toolCatalog,this.definitions=e.servers.filter(r=>!r.disabled).filter(r=>{let o=Ve(r);for(let n of o)this.log.warn(`[mcp] rejected server "${r.name}": ${n.message}`);return r.tools&&this.serverToolFilters.set(r.name,r.tools),r.oauth===!0&&this.serverOAuth.set(r.name,!0),o.length===0}).map(r=>this.toServerDefinition(r)).filter(r=>r!==null)}markServerFailed(e,r,o){this.failedServers.set(e,{name:e,phase:r,error:o}),console.error(`[mcp] server "${e}" unavailable this session (${r}): ${o}`)}toServerDefinition(e){if((e.type??(e.url?"http":"stdio"))==="http"){if(!e.url)return this.log.warn(`[mcp] server "${e.name}" is type "http" but has no url, skipping`),this.markServerFailed(e.name,"config",'type "http" but no url'),null;let o;try{o=new URL(e.url)}catch{return this.log.warn(`[mcp] server "${e.name}" has an invalid url "${e.url}", skipping`),this.markServerFailed(e.name,"config",`invalid url "${e.url}"`),null}return{name:e.name,command:{kind:"http",url:o,headers:e.headers}}}return e.command?{name:e.name,command:{kind:"stdio",command:e.command,args:e.args??[],cwd:e.cwd??this.workspaceRoot??process.cwd()},env:e.env}:(this.log.warn(`[mcp] server "${e.name}" is type "stdio" but has no command, skipping`),this.markServerFailed(e.name,"config",'type "stdio" but no command'),null)}async connectAll(){this.definitions.length!==0&&(this.runtime=await Me({servers:this.definitions,clientInfo:{name:"qlogicagent",version:"1.0.0"},logger:{info:e=>this.log.info(`[mcp] ${e}`),warn:e=>this.log.warn(`[mcp] ${e}`),error:(e,r)=>this.log.warn(`[mcp] ${e}${r?` (${r instanceof Error?r.message:String(r)})`:""}`),debug:()=>{}}}),await Promise.allSettled(this.definitions.map(async e=>{try{let r=await Ie(()=>this.runtime.listTools(e.name,{includeSchema:!0,disableOAuth:this.serverOAuth.get(e.name)!==!0}),{attempts:g,baseDelayMs:je,onRetry:(n,i)=>this.log.warn(`[mcp] connect attempt ${n}/${g} for ${e.name} failed, retrying: ${i instanceof Error?i.message:i}`)}),o=z(r,this.serverToolFilters.get(e.name));this.toolsByServer.set(e.name,o),this.failedServers.delete(e.name),this.log.info(`[mcp] connected to ${e.name} (${o.length}/${r.length} tools)`)}catch(r){this.log.warn(`[mcp] failed to connect to ${e.name} after ${g} attempts: ${r instanceof Error?r.message:r}`),this.markServerFailed(e.name,"connect",`${r instanceof Error?r.message:String(r)} (after ${g} attempts)`)}})))}injectTools(){for(let[e,r]of this.toolsByServer){let o=this.injectPortableTools(e,r);this.log.info(`[mcp] injected ${o.length} tools from ${e}`)}}async refreshServerTools(e){if(!this.runtime)throw new Error("MCP runtime is not connected");let r=await this.runtime.listTools(e,{includeSchema:!0,disableOAuth:this.serverOAuth.get(e)!==!0}),o=z(r,this.serverToolFilters.get(e));return this.toolsByServer.set(e,o),this.failedServers.delete(e),this.retractServerTools(e),this.injectPortableTools(e,o),o.length}getConnectedServers(){return Array.from(this.toolsByServer.keys())}getFailedServers(){return Array.from(this.failedServers.values())}getToolCount(){let e=0;for(let r of this.toolsByServer.values())e+=r.length;return e}async disconnectAll(){for(let r of this.injectedNames)this.removeRegisteredTool(r);this.injectedNames.clear(),this.toolsByServer.clear(),this.failedServers.clear();let e=this.runtime;if(this.runtime=null,e)try{await e.close()}catch{}}toPortableTool(e,r){let o=U({name:r.name,description:r.description});return{name:`mcp__${G(e)}__${r.name}`,label:`[${e}] ${r.name}`,category:"mcp",description:r.description??`MCP tool from ${e}`,parameters:r.inputSchema??{type:"object",properties:{}},isConcurrencySafe:o.isConcurrencySafe,isReadOnly:o.isReadOnly,isDestructive:o.isDestructive,searchHint:`mcp ${e} ${r.name.replace(/[_-]+/g," ")}`,execute:async(n,i)=>{let s=this.runtime;if(!s)return{content:[{type:"text",text:`MCP server "${e}" is not connected.`}],details:{error:"mcp_not_connected"}};try{let a=await s.callTool(e,r.name,{args:i,timeoutMs:De});return Le(a)}catch(a){let l=a instanceof Error?a.message:String(a);return{content:[{type:"text",text:`MCP tool error: ${l}`}],details:{error:l}}}}}}wrapToolsForWorkspaceBoundary(e){return this.workspaceRoot?e.map(r=>{if(!r.execute)return r;let o=r.execute;return{...r,execute:async(n,i,s)=>{let a=$e(r.name,i,this.workspaceRoot);return a?{content:[{type:"text",text:a}],details:{type:"mcp",error:"workspace_boundary"}}:o(n,i,s)}}}):e}injectPortableTools(e,r){let o=this.wrapToolsForWorkspaceBoundary(r.map(n=>this.toPortableTool(e,n)));this.registerTools(o);for(let n of o)this.injectedNames.add(n.name);return o}retractServerTools(e){let r=`mcp__${G(e)}__`;for(let o of[...this.injectedNames])o.startsWith(r)&&(this.removeRegisteredTool(o),this.injectedNames.delete(o))}registerTools(e){this.toolCatalog?this.toolCatalog.addTools(e):F(e)}removeRegisteredTool(e){return this.toolCatalog?.removeTool(e)??q(e)}};function Le(t){let e=t&&typeof t=="object"?t:{},o=(Array.isArray(e.content)?e.content:[]).filter(a=>!!a&&typeof a=="object"),n=o.filter(a=>a.type==="text"&&typeof a.text=="string").map(a=>a.text),i=o.filter(a=>!(a.type==="text"&&typeof a.text=="string")).map(a=>typeof a.type=="string"&&a.type?a.type:"unknown"),s=n.join(`
2
+ import{createInterface as Ke}from"node:readline";import{existsSync as Qe,readFileSync as Ye}from"node:fs";import{readFileSync as ye}from"node:fs";import{randomUUID as ve}from"node:crypto";import{readdirSync as Tt,readFileSync as kt,statSync as re,writeFileSync as Pt}from"node:fs";import{readdir as oe,readFile as ne,stat as se,writeFile as ie}from"node:fs/promises";import{join as d}from"node:path";import{homedir as Q}from"node:os";import{join as u,resolve as at}from"node:path";import{existsSync as ct}from"node:fs";import{createHash as dt}from"node:crypto";var P=".qlogicagent";function p(){return process.env.QLOGICAGENT_HOME||u(Q(),P)}function v(){return u(p(),"skills")}function _(){return u(p(),"mcp.json")}function Y(t){if(!t)throw new Error("getProjectAgentDir: cwd is required (must not fall back to process.cwd())");return u(t,P)}function C(t){return u(Y(t),"skills-disabled.json")}import{readFileSync as Z,writeFileSync as ft,mkdirSync as gt,renameSync as ht}from"node:fs";import{dirname as vt,join as X}from"node:path";function f(){return{version:1,disabled:[]}}function ee(t){let e;try{e=Z(t,"utf8")}catch(n){return n.code==="ENOENT"?{list:f(),corrupt:!1}:(console.error(`[project-skill-manifest] Cannot read skill mute list at ${t} (${n instanceof Error?n.message:String(n)}); treating it as empty for reads \u2014 muted skills may reactivate.`),{list:f(),corrupt:!0})}let r;try{r=JSON.parse(e)}catch(n){return console.error(`[project-skill-manifest] Skill mute list at ${t} is corrupted (${n instanceof Error?n.message:String(n)}); treating it as empty for reads \u2014 muted skills may reactivate.`),{list:f(),corrupt:!0}}return!r||typeof r!="object"||!Array.isArray(r.disabled)?(console.error(`[project-skill-manifest] Skill mute list at ${t} has an unexpected shape; treating it as empty for reads \u2014 muted skills may reactivate.`),{list:f(),corrupt:!0}):{list:{version:1,disabled:[...new Set(r.disabled.filter(n=>typeof n=="string"&&n.trim().length>0))]},corrupt:!1}}function x(t){return ee(t).list}function te(){return X(p(),"skills-disabled.json")}function A(){return new Set(x(te()).disabled)}function R(t){return new Set(x(C(t)).disabled)}var ae=["auto-skill-","test-skill-"],le=".skills_prompt_snapshot.json";function ce(t){return ae.some(e=>t.startsWith(e))}function ue(t){let e=t.replace(/\r\n/g,`
3
+ `),r=e.match(/^---\n[\s\S]*?^version:\s*(\S+)/m),o=e.match(/^---\n[\s\S]*?^category:\s*(.+)/m),n=e.match(/^---\n[\s\S]*?^author:\s*(.+)/m),i=e.match(/^---\n[\s\S]*?^requires:\s*(.+)/m),s=e.match(/^---\n[\s\S]*?^environments:\s*(.+)/m),a=e.match(/^---\n([\s\S]*?)\n---/)?.[1]??"";return{version:r?.[1],description:de(a),category:o?.[1]?.trim()||void 0,author:n?.[1]?.trim()||void 0,requiredTools:M(i?.[1]),environments:M(s?.[1])}}function de(t){let e=t.split(`
4
+ `),r=e.findIndex(s=>/^description:/.test(s));if(r===-1)return;let o=e[r].replace(/^description:[ \t]*/,"").trim(),n=/^[>|][+-]?$/.test(o),i=[];!n&&o&&i.push(o);for(let s=r+1;s<e.length;s++){let a=e[s];if(!/^[ \t]/.test(a))break;let l=a.trim();l&&i.push(l)}if(i.length!==0)return i.join(" ").replace(/^["']|["']$/g,"").trim()||void 0}var E=new Map,S=new Map;function me(t,e,r,o){let n=e.has(t.name),i=r.has(t.name),s=!ge(t.meta,o);return{name:t.name,filePath:t.filePath,baseDir:t.baseDir,globallyDisabled:n,projectDisabled:i,active:!n&&!i&&!s,systemGenerated:t.systemGenerated,description:t.meta.description,version:t.meta.version,category:t.meta.category,author:t.meta.author,requiredTools:t.meta.requiredTools,environments:t.meta.environments}}async function pe(t){let e;try{e=await oe(t,{withFileTypes:!0})}catch{e=[]}let r=[];for(let s of e){if(!s.isDirectory()||s.name.startsWith("."))continue;let a=d(t,s.name),l=d(a,"SKILL.md");try{let y=await se(l);if(!y.isFile())continue;r.push({name:s.name,filePath:l,baseDir:a,mtimeMs:y.mtimeMs,size:y.size})}catch{continue}}r.sort((s,a)=>s.name.localeCompare(a.name));let o=r.map(s=>`${s.name}:${s.mtimeMs}:${s.size}`).join("|"),n=E.get(t);if(n&&n.fingerprint===o)return n.raw;let i=[];for(let s of r){let a;try{a=await ne(s.filePath,"utf8")}catch{continue}i.push({name:s.name,filePath:s.filePath,baseDir:s.baseDir,systemGenerated:ce(s.name),mtimeMs:s.mtimeMs,size:s.size,meta:ue(a)})}return E.set(t,{fingerprint:o,raw:i}),he(t,i),i}async function fe(t,e){let r=v(),o=A(),n=t?R(t):new Set,i=S.get(r);return i||(i=pe(r).finally(()=>S.delete(r)),S.set(r,i)),(await i).map(a=>me(a,o,n,e))}async function D(t,e){return(await fe(t,e)).filter(r=>r.active)}function j(t){let e=v(),r=d(e,t),o=d(r,"SKILL.md");try{if(re(o).isFile())return{baseDir:r,filePath:o}}catch{}return null}function M(t){if(!t)return;let e=t.replace(/^\[|\]$/g,"").split(/[,\s]+/).map(r=>r.replace(/^["']|["']$/g,"").trim()).filter(Boolean);return e.length>0?e:void 0}function ge(t,e){if(t.environments&&e?.currentEnvironment&&!t.environments.includes(e.currentEnvironment))return!1;if(t.requiredTools){if(!e?.availableToolNames)return!1;let r=new Set(e.availableToolNames);return t.requiredTools.every(o=>r.has(o))}return!0}async function he(t,e){try{let o={version:1,entries:e.map(n=>({name:n.name,size:n.size,mtimeMs:n.mtimeMs,description:n.meta.description,version:n.meta.version,requiredTools:n.meta.requiredTools,environments:n.meta.environments}))};await ie(d(t,le),JSON.stringify(o,null,2),"utf8")}catch{}}var I="astraclaw_capabilities";async function L(t){if(t.tool==="skills_list")return{handled:!0,result:{skills:(await D(t.projectRoot,{availableToolNames:t.availableToolNames,currentEnvironment:t.currentEnvironment??process.platform})).map(Se)}};if(t.tool==="skill_view"){let e=typeof t.args.name=="string"?t.args.name.trim():"";if(!e)throw new Error("skill_view requires a skill name");let r=j(e);if(!r)throw new Error(`Skill not found: ${e}`);return{handled:!0,result:{name:e,content:ye(r.filePath,"utf8")}}}if(t.tool==="mcp_connectors_list"){let e=t.mcpServerFailures??[],r=e.length>0?{failedServers:e,note:`${e.length} configured MCP server(s) are unavailable this session; their tools are missing from this list.`}:{};if(!t.toolCatalog)return{handled:!0,result:{tools:[],note:"AstraClaw MCP connector catalog is not attached to this capability server instance.",...e.length>0?{failedServers:e}:{}}};let o=t.toolCatalog.getToolManifest().filter(n=>n.function.name.startsWith("mcp__")).map(n=>({toolName:n.function.name,server:we(n.function.name),name:Te(n.function.name),description:n.function.description,inputSchema:n.function.parameters}));return{handled:!0,result:{tools:o,count:o.length,...r}}}if(t.tool==="mcp_tool_call"){if(!t.toolCatalog)throw new Error("AstraClaw MCP connector catalog is not attached");let e=typeof t.args.toolName=="string"?t.args.toolName.trim():"";if(!e.startsWith("mcp__"))throw new Error("mcp_tool_call requires a connector toolName returned by mcp_connectors_list");let r=t.toolCatalog.findTool(e);if(!r?.execute)throw new Error(`MCP connector tool not found or not executable: ${e}`);let o=be(t.args.args),n=`astraclaw_mcp_${ve().slice(0,8)}`,i=await r.execute(n,o);return{handled:!0,result:{toolName:e,content:i.content,details:i.details,imageUrls:i.imageUrls}}}return{handled:!1}}function Se(t){return{name:t.name,description:t.description,version:t.version,category:t.category,requiredTools:t.requiredTools,environments:t.environments}}function be(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)?t:{}}function we(t){let e=t.split("__");return e.length>=3?e[1]??"":""}function Te(t){let e=t.split("__");return e.length>=3?e.slice(2).join("__"):t}import m from"node:path";import{fileURLToPath as xe}from"node:url";import{createRuntime as Ae}from"mcporter";var O=new Set(["gateway","agents_list","session_status","sessions_send","sessions_list","sessions_history","sessions_spawn","cron","config","workflow"]),ke=new Set([...O,"agent"]);function $(t){return t?.riskLevel?t.riskLevel:t?.isDangerous?"system":t?.isReadOnly?"read":t?.isEgress?"external_egress":"write"}var b=class{toolPool=new Map;setTools(e){this.toolPool.clear();for(let r of e)this.toolPool.set(r.name,r)}addTool(e){this.toolPool.set(e.name,e)}addTools(e){for(let r of e)this.addTool(r)}removeTool(e){return this.toolPool.delete(e)}findTool(e){return this.toolPool.get(e)}hasTool(e){return this.toolPool.has(e)}getToolNames(){return Array.from(this.toolPool.keys())}getToolCount(){return this.toolPool.size}async executeTool(e,r,o,n){let i=this.toolPool.get(e);if(!i)throw new Error(`Tool not found: ${e}`);return i.execute(r,o,n)}getTools(){return Array.from(this.toolPool.values()).filter(e=>e.isEnabled?.()!==!1)}getToolManifest(){let e=[];for(let r of this.toolPool.values()){if(r.isEnabled?.()===!1)continue;let o=$(r);e.push({type:"function",function:{name:r.name,description:r.description,parameters:r.parameters},meta:{category:r.category??"other",displayName:r.displayName??{key:`capability.tool.${r.name}.name`,fallback:r.label},displayDescription:r.displayDescription??{key:`capability.tool.${r.name}.description`,fallback:""},parallelSafe:r.isConcurrencySafe??!1,riskLevel:o,isReadOnly:o==="read",isDangerous:o==="system",isDelete:r.isDelete??!1,isEgress:r.isEgress??o==="external_egress",egressCarriesData:r.egressCarriesData??!1}})}return e}},N=new b;function F(t){N.addTools(t)}function U(t){return N.removeTool(t)}var Pe=new Set(["describe","fetch","find","get","inspect","list","query","read","search","stat"]),_e=new Set(["append","copy","create","delete","edit","move","patch","remove","rename","set","update","upload","write"]);function q(t){let e=t.annotations,r=Ce(t.name),o=r.some(l=>_e.has(l)),n=r.some(l=>Pe.has(l)),i=e?.destructiveHint===!0||o,s=e?.readOnlyHint===!0||!i&&n,a=s||e?.idempotentHint===!0&&!i;return{isReadOnly:s,isConcurrencySafe:a,isDestructive:i}}function Ce(t){return t.replace(/([a-z0-9])([A-Z])/g,"$1_$2").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean)}var Re=12e4,g=3,Ee=1e3;async function Me(t,e){let r=e.sleep??(i=>new Promise(s=>setTimeout(s,i))),o=Math.max(1,e.attempts),n;for(let i=1;i<=o;i++)try{return await t()}catch(s){n=s,i<o&&(e.onRetry?.(i,s),await r(e.baseDelayMs*i))}throw n}var h=class{runtime=null;definitions=[];toolsByServer=new Map;injectedNames=new Set;log;workspaceRoot;toolCatalog;serverToolFilters=new Map;serverOAuth=new Map;failedServers=new Map;constructor(e){this.log=e.log??{info:()=>{},warn:()=>{}},this.workspaceRoot=e.workspaceRoot?m.resolve(e.workspaceRoot):void 0,this.toolCatalog=e.toolCatalog,this.definitions=e.servers.filter(r=>!r.disabled).filter(r=>{let o=Be(r);for(let n of o)this.log.warn(`[mcp] rejected server "${r.name}": ${n.message}`);return r.tools&&this.serverToolFilters.set(r.name,r.tools),r.oauth===!0&&this.serverOAuth.set(r.name,!0),o.length===0}).map(r=>this.toServerDefinition(r)).filter(r=>r!==null)}markServerFailed(e,r,o){this.failedServers.set(e,{name:e,phase:r,error:o}),console.error(`[mcp] server "${e}" unavailable this session (${r}): ${o}`)}toServerDefinition(e){if((e.type??(e.url?"http":"stdio"))==="http"){if(!e.url)return this.log.warn(`[mcp] server "${e.name}" is type "http" but has no url, skipping`),this.markServerFailed(e.name,"config",'type "http" but no url'),null;let o;try{o=new URL(e.url)}catch{return this.log.warn(`[mcp] server "${e.name}" has an invalid url "${e.url}", skipping`),this.markServerFailed(e.name,"config",`invalid url "${e.url}"`),null}return{name:e.name,command:{kind:"http",url:o,headers:e.headers}}}return e.command?{name:e.name,command:{kind:"stdio",command:e.command,args:e.args??[],cwd:e.cwd??this.workspaceRoot??process.cwd()},env:e.env}:(this.log.warn(`[mcp] server "${e.name}" is type "stdio" but has no command, skipping`),this.markServerFailed(e.name,"config",'type "stdio" but no command'),null)}async connectAll(){this.definitions.length!==0&&(this.runtime=await Ae({servers:this.definitions,clientInfo:{name:"qlogicagent",version:"1.0.0"},logger:{info:e=>this.log.info(`[mcp] ${e}`),warn:e=>this.log.warn(`[mcp] ${e}`),error:(e,r)=>this.log.warn(`[mcp] ${e}${r?` (${r instanceof Error?r.message:String(r)})`:""}`),debug:()=>{}}}),await Promise.allSettled(this.definitions.map(async e=>{try{let r=await Me(()=>this.runtime.listTools(e.name,{includeSchema:!0,disableOAuth:this.serverOAuth.get(e.name)!==!0}),{attempts:g,baseDelayMs:Ee,onRetry:(n,i)=>this.log.warn(`[mcp] connect attempt ${n}/${g} for ${e.name} failed, retrying: ${i instanceof Error?i.message:i}`)}),o=z(r,this.serverToolFilters.get(e.name));this.toolsByServer.set(e.name,o),this.failedServers.delete(e.name),this.log.info(`[mcp] connected to ${e.name} (${o.length}/${r.length} tools)`)}catch(r){this.log.warn(`[mcp] failed to connect to ${e.name} after ${g} attempts: ${r instanceof Error?r.message:r}`),this.markServerFailed(e.name,"connect",`${r instanceof Error?r.message:String(r)} (after ${g} attempts)`)}})))}injectTools(){for(let[e,r]of this.toolsByServer){let o=this.injectPortableTools(e,r);this.log.info(`[mcp] injected ${o.length} tools from ${e}`)}}async refreshServerTools(e){if(!this.runtime)throw new Error("MCP runtime is not connected");let r=await this.runtime.listTools(e,{includeSchema:!0,disableOAuth:this.serverOAuth.get(e)!==!0}),o=z(r,this.serverToolFilters.get(e));return this.toolsByServer.set(e,o),this.failedServers.delete(e),this.retractServerTools(e),this.injectPortableTools(e,o),o.length}getConnectedServers(){return Array.from(this.toolsByServer.keys())}getFailedServers(){return Array.from(this.failedServers.values())}getToolCount(){let e=0;for(let r of this.toolsByServer.values())e+=r.length;return e}async disconnectAll(){for(let r of this.injectedNames)this.removeRegisteredTool(r);this.injectedNames.clear(),this.toolsByServer.clear(),this.failedServers.clear();let e=this.runtime;if(this.runtime=null,e)try{await e.close()}catch{}}toPortableTool(e,r){let o=q({name:r.name,description:r.description});return{name:`mcp__${G(e)}__${r.name}`,label:`[${e}] ${r.name}`,category:"mcp",description:r.description??`MCP tool from ${e}`,parameters:r.inputSchema??{type:"object",properties:{}},isConcurrencySafe:o.isConcurrencySafe,isReadOnly:o.isReadOnly,isDestructive:o.isDestructive,searchHint:`mcp ${e} ${r.name.replace(/[_-]+/g," ")}`,execute:async(n,i)=>{let s=this.runtime;if(!s)return{content:[{type:"text",text:`MCP server "${e}" is not connected.`}],details:{error:"mcp_not_connected"}};try{let a=await s.callTool(e,r.name,{args:i,timeoutMs:Re});return De(a)}catch(a){let l=a instanceof Error?a.message:String(a);return{content:[{type:"text",text:`MCP tool error: ${l}`}],details:{error:l}}}}}}wrapToolsForWorkspaceBoundary(e){return this.workspaceRoot?e.map(r=>{if(!r.execute)return r;let o=r.execute;return{...r,execute:async(n,i,s)=>{let a=Ie(r.name,i,this.workspaceRoot);return a?{content:[{type:"text",text:a}],details:{type:"mcp",error:"workspace_boundary"}}:o(n,i,s)}}}):e}injectPortableTools(e,r){let o=this.wrapToolsForWorkspaceBoundary(r.map(n=>this.toPortableTool(e,n)));this.registerTools(o);for(let n of o)this.injectedNames.add(n.name);return o}retractServerTools(e){let r=`mcp__${G(e)}__`;for(let o of[...this.injectedNames])o.startsWith(r)&&(this.removeRegisteredTool(o),this.injectedNames.delete(o))}registerTools(e){this.toolCatalog?this.toolCatalog.addTools(e):F(e)}removeRegisteredTool(e){return this.toolCatalog?.removeTool(e)??U(e)}};function De(t){let e=t&&typeof t=="object"?t:{},o=(Array.isArray(e.content)?e.content:[]).filter(a=>!!a&&typeof a=="object"),n=o.filter(a=>a.type==="text"&&typeof a.text=="string").map(a=>a.text),i=o.filter(a=>!(a.type==="text"&&typeof a.text=="string")).map(a=>typeof a.type=="string"&&a.type?a.type:"unknown"),s=n.join(`
5
5
  `);if(i.length>0){let a=[...new Set(i)].join(", ");s=s?`${s}
6
6
 
7
- [${i.length} non-text blocks omitted: ${a}]`:`[output contains only non-text blocks: ${a}]`}return{content:[{type:"text",text:s||"(no text output)"}],...e.isError?{details:{error:"mcp_tool_error"}}:{}}}function G(t){return t.replace(/[^a-zA-Z0-9_]/g,"_").toLowerCase()}var Oe=/(?:^|_)(path|paths|file|files|filename|filenames|dir|dirs|directory|directories|folder|folders|cwd|root|uri)(?:$|_)/i;function $e(t,e,r){if(!r)return null;for(let o of T(e)){let n=qe(o.value,r);if(n&&!Ue(n.candidate,n.root,n.pathApi))return`Blocked: MCP tool "${t}" path "${o.value}" is outside the workspace boundary "${n.root}"`}return null}function T(t,e="",r=0){if(r>8)return[];if(typeof t=="string")return Ne(e,t)?[{key:e,value:t}]:[];if(Array.isArray(t))return t.flatMap(n=>T(n,e,r+1));if(!t||typeof t!="object")return[];let o=[];for(let[n,i]of Object.entries(t))o.push(...T(i,n,r+1));return o}function Ne(t,e){if(!Oe.test(t))return!1;let r=e.trim();return!r||/^https?:\/\//i.test(r)?!1:Fe(r)}function Fe(t){return p.isAbsolute(t)||/^[A-Za-z]:[\\/]/.test(t)||/^\\\\/.test(t)||/^file:\/\//i.test(t)||t.includes("../")||t.includes("..\\")||t.startsWith(".\\")||t.startsWith("./")||t.includes("/")||t.includes("\\")}function qe(t,e){let r=t.trim();if(/^file:\/\//i.test(r))try{r=Ee(r)}catch{return null}let o=W(r)||W(e)?p.win32:p,n=o.resolve(e);return{candidate:o.isAbsolute(r)?o.resolve(r):o.resolve(n,r),root:n,pathApi:o}}function Ue(t,e,r){let o=r.relative(e,t);return o===""||!o.startsWith("..")&&!r.isAbsolute(o)}function W(t){return/^[A-Za-z]:[\\/]/.test(t)||/^\\\\/.test(t)}function J(t){if(!t||typeof t!="object")return[];let e=t,r=[],o=e.mcpServers??e.servers??e;for(let[n,i]of Object.entries(o)){if(!i||typeof i!="object")continue;let s=i;if(typeof s.url=="string"){r.push({name:n,type:"http",url:s.url,headers:s.headers&&typeof s.headers=="object"?s.headers:void 0,disabled:s.disabled===!0,oauth:s.oauth===!0,tools:B(s.tools)});continue}typeof s.command=="string"&&r.push({name:n,type:"stdio",command:s.command,args:Array.isArray(s.args)?s.args:void 0,env:s.env&&typeof s.env=="object"?s.env:void 0,cwd:typeof s.cwd=="string"?s.cwd:void 0,disabled:s.disabled===!0,oauth:s.oauth===!0,tools:B(s.tools)})}return r}function z(t,e){let r=new Set(e?.include??[]),o=new Set(e?.exclude??[]);return t.filter(n=>r.size>0&&!r.has(n.name)?!1:!o.has(n.name))}function B(t){if(!t||typeof t!="object")return;let e=t,r=H(e.include),o=H(e.exclude);if(!(!r&&!o))return{...r?{include:r}:{},...o?{exclude:o}:{}}}function H(t){if(!Array.isArray(t))return;let e=t.filter(r=>typeof r=="string"&&r.trim().length>0);return e.length>0?e:void 0}var Ge=new Set(["bash","sh","zsh","fish","cmd","cmd.exe","powershell","powershell.exe","pwsh","pwsh.exe"]),We=new Set(["-c","/c","-command","-encodedcommand","-e"]),ze=["curl","wget","invokewebrequest","invoke-restmethod","iwr","irm","nc","netcat"],Be=["env","processenv","apikey","api_key","token","secret","credential","credentials","awsaccesskey","awssecret"],He=["authorizedkeys","sshknownhosts","crontab","launchctl","schtasks","startup","runkey","runonce","bashrc","profile"],Je=/\bssh-(?:rsa|ed25519|ecdsa-[^\s]+)\s+[A-Za-z0-9+/=]{40,}/i;function Ve(t){let e=[],r=[t.command??"",...t.args??[],...Object.keys(t.env??{}),...Object.values(t.env??{})].join(`
8
- `);if(Je.test(r)&&e.push({code:"ioc_public_key",message:"configuration contains an inline SSH public key IOC"}),(t.type??(t.url?"http":"stdio"))!=="stdio"||!Ke(t.command))return e;let o=Qe(t.args??[]);if(!o)return e;let n=Ye(o);return w(n,He)&&e.push({code:"persistence",message:"stdio shell command attempts a persistence write"}),w(n,ze)&&w(n,Be)&&e.push({code:"dangerous_egress",message:"stdio shell command combines network egress with likely secret access"}),e}function Ke(t){if(!t)return!1;let e=p.basename(t).toLowerCase();return Ge.has(e)}function Qe(t){for(let e=0;e<t.length;e++){let r=t[e]?.toLowerCase();if(r&&We.has(r))return t.slice(e+1).join(" ")}return""}function Ye(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"")}function w(t,e){return e.some(r=>t.includes(r))}var tt=[{name:"skills_list",description:"List AstraClaw skills active for the current workspace.",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"skill_view",description:"Read the full SKILL.md instructions for one AstraClaw skill.",inputSchema:{type:"object",properties:{name:{type:"string",description:"Skill name from skills_list."}},required:["name"],additionalProperties:!1}},{name:"mcp_connectors_list",description:"List MCP connector tools installed in AstraClaw's Plugins page and shared with this external agent.",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"mcp_tool_call",description:"Call one AstraClaw shared MCP connector tool by toolName from mcp_connectors_list.",inputSchema:{type:"object",properties:{toolName:{type:"string",description:"Connector tool name, for example mcp__filesystem__read_text_file."},args:{type:"object",description:"Arguments for the connector tool."}},required:["toolName"],additionalProperties:!1}}],k=class{tools=new Map;findTool(e){return this.tools.get(e)}getToolManifest(){return Array.from(this.tools.values()).map(e=>({type:"function",function:{name:e.name,description:e.description,parameters:e.parameters}}))}getToolNames(){return Array.from(this.tools.keys())}setTools(e){this.tools.clear(),this.addTools(e)}addTool(e){this.tools.set(e.name,e)}addTools(e){for(let r of e)this.addTool(r)}removeTool(e){return this.tools.delete(e)}},u=null,rt=Ze({input:process.stdin,crlfDelay:Number.POSITIVE_INFINITY});rt.on("line",t=>{ot(t)});async function ot(t){let e=t.trim();if(!e)return;let r;try{r=JSON.parse(e)}catch{return}if(r.id===void 0||r.id===null)return r.method==="notifications/initialized",void 0;try{let o=await nt(r);K({jsonrpc:"2.0",id:r.id,result:o})}catch(o){K({jsonrpc:"2.0",id:r.id,error:{code:-32603,message:o instanceof Error?o.message:String(o)}})}}async function nt(t){switch(t.method){case"initialize":return{protocolVersion:"2024-11-05",capabilities:{tools:{}},serverInfo:{name:I,version:"1.0.0"}};case"tools/list":return{tools:tt};case"tools/call":{let e=V(t.params),r=typeof e.name=="string"?e.name:"",o=V(e.arguments),n=st(),i=r==="mcp_connectors_list"||r==="mcp_tool_call"?await it(n):void 0,s=await L({tool:r,args:o,projectRoot:n,toolCatalog:i,mcpServerFailures:i?u?.manager?.getFailedServers():void 0});if(!s.handled)throw new Error(`Unknown tool: ${r}`);return{content:[{type:"text",text:JSON.stringify(s.result)}]}}default:throw new Error(`Unknown method: ${t.method}`)}}function st(){return process.env.ASTRACLAW_PROJECT_ROOT||process.env.QLOGICAGENT_PROJECT_ROOT||process.cwd()}async function it(t){if(u?.projectRoot===t)return await u.ready,u.catalog;u?.manager?.disconnectAll().catch(()=>{});let e=new k,r=new h({servers:at(),workspaceRoot:t,toolCatalog:e,log:{info:n=>process.stderr.write(`${n}
7
+ [${i.length} non-text blocks omitted: ${a}]`:`[output contains only non-text blocks: ${a}]`}return{content:[{type:"text",text:s||"(no text output)"}],...e.isError?{details:{error:"mcp_tool_error"}}:{}}}function G(t){return t.replace(/[^a-zA-Z0-9_]/g,"_").toLowerCase()}var je=/(?:^|_)(path|paths|file|files|filename|filenames|dir|dirs|directory|directories|folder|folders|cwd|root|uri)(?:$|_)/i;function Ie(t,e,r){if(!r)return null;for(let o of T(e)){let n=$e(o.value,r);if(n&&!Ne(n.candidate,n.root,n.pathApi))return`Blocked: MCP tool "${t}" path "${o.value}" is outside the workspace boundary "${n.root}"`}return null}function T(t,e="",r=0){if(r>8)return[];if(typeof t=="string")return Le(e,t)?[{key:e,value:t}]:[];if(Array.isArray(t))return t.flatMap(n=>T(n,e,r+1));if(!t||typeof t!="object")return[];let o=[];for(let[n,i]of Object.entries(t))o.push(...T(i,n,r+1));return o}function Le(t,e){if(!je.test(t))return!1;let r=e.trim();return!r||/^https?:\/\//i.test(r)?!1:Oe(r)}function Oe(t){return m.isAbsolute(t)||/^[A-Za-z]:[\\/]/.test(t)||/^\\\\/.test(t)||/^file:\/\//i.test(t)||t.includes("../")||t.includes("..\\")||t.startsWith(".\\")||t.startsWith("./")||t.includes("/")||t.includes("\\")}function $e(t,e){let r=t.trim();if(/^file:\/\//i.test(r))try{r=xe(r)}catch{return null}let o=W(r)||W(e)?m.win32:m,n=o.resolve(e);return{candidate:o.isAbsolute(r)?o.resolve(r):o.resolve(n,r),root:n,pathApi:o}}function Ne(t,e,r){let o=r.relative(e,t);return o===""||!o.startsWith("..")&&!r.isAbsolute(o)}function W(t){return/^[A-Za-z]:[\\/]/.test(t)||/^\\\\/.test(t)}function J(t){if(!t||typeof t!="object")return[];let e=t,r=[],o=e.mcpServers??e.servers??e;for(let[n,i]of Object.entries(o)){if(!i||typeof i!="object")continue;let s=i;if(typeof s.url=="string"){r.push({name:n,type:"http",url:s.url,headers:s.headers&&typeof s.headers=="object"?s.headers:void 0,disabled:s.disabled===!0,oauth:s.oauth===!0,tools:B(s.tools)});continue}typeof s.command=="string"&&r.push({name:n,type:"stdio",command:s.command,args:Array.isArray(s.args)?s.args:void 0,env:s.env&&typeof s.env=="object"?s.env:void 0,cwd:typeof s.cwd=="string"?s.cwd:void 0,disabled:s.disabled===!0,oauth:s.oauth===!0,tools:B(s.tools)})}return r}function z(t,e){let r=new Set(e?.include??[]),o=new Set(e?.exclude??[]);return t.filter(n=>r.size>0&&!r.has(n.name)?!1:!o.has(n.name))}function B(t){if(!t||typeof t!="object")return;let e=t,r=H(e.include),o=H(e.exclude);if(!(!r&&!o))return{...r?{include:r}:{},...o?{exclude:o}:{}}}function H(t){if(!Array.isArray(t))return;let e=t.filter(r=>typeof r=="string"&&r.trim().length>0);return e.length>0?e:void 0}var Fe=new Set(["bash","sh","zsh","fish","cmd","cmd.exe","powershell","powershell.exe","pwsh","pwsh.exe"]),Ue=new Set(["-c","/c","-command","-encodedcommand","-e"]),qe=["curl","wget","invokewebrequest","invoke-restmethod","iwr","irm","nc","netcat"],Ge=["env","processenv","apikey","api_key","token","secret","credential","credentials","awsaccesskey","awssecret"],We=["authorizedkeys","sshknownhosts","crontab","launchctl","schtasks","startup","runkey","runonce","bashrc","profile"],ze=/\bssh-(?:rsa|ed25519|ecdsa-[^\s]+)\s+[A-Za-z0-9+/=]{40,}/i;function Be(t){let e=[],r=[t.command??"",...t.args??[],...Object.keys(t.env??{}),...Object.values(t.env??{})].join(`
8
+ `);if(ze.test(r)&&e.push({code:"ioc_public_key",message:"configuration contains an inline SSH public key IOC"}),(t.type??(t.url?"http":"stdio"))!=="stdio"||!He(t.command))return e;let o=Je(t.args??[]);if(!o)return e;let n=Ve(o);return w(n,We)&&e.push({code:"persistence",message:"stdio shell command attempts a persistence write"}),w(n,qe)&&w(n,Ge)&&e.push({code:"dangerous_egress",message:"stdio shell command combines network egress with likely secret access"}),e}function He(t){if(!t)return!1;let e=m.basename(t).toLowerCase();return Fe.has(e)}function Je(t){for(let e=0;e<t.length;e++){let r=t[e]?.toLowerCase();if(r&&Ue.has(r))return t.slice(e+1).join(" ")}return""}function Ve(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"")}function w(t,e){return e.some(r=>t.includes(r))}var Ze=[{name:"skills_list",description:"List AstraClaw skills active for the current workspace.",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"skill_view",description:"Read the full SKILL.md instructions for one AstraClaw skill.",inputSchema:{type:"object",properties:{name:{type:"string",description:"Skill name from skills_list."}},required:["name"],additionalProperties:!1}},{name:"mcp_connectors_list",description:"List MCP connector tools installed in AstraClaw's Plugins page and shared with this external agent.",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"mcp_tool_call",description:"Call one AstraClaw shared MCP connector tool by toolName from mcp_connectors_list.",inputSchema:{type:"object",properties:{toolName:{type:"string",description:"Connector tool name, for example mcp__filesystem__read_text_file."},args:{type:"object",description:"Arguments for the connector tool."}},required:["toolName"],additionalProperties:!1}}],k=class{tools=new Map;findTool(e){return this.tools.get(e)}getToolManifest(){return Array.from(this.tools.values()).map(e=>({type:"function",function:{name:e.name,description:e.description,parameters:e.parameters}}))}getToolNames(){return Array.from(this.tools.keys())}setTools(e){this.tools.clear(),this.addTools(e)}addTool(e){this.tools.set(e.name,e)}addTools(e){for(let r of e)this.addTool(r)}removeTool(e){return this.tools.delete(e)}},c=null,Xe=Ke({input:process.stdin,crlfDelay:Number.POSITIVE_INFINITY});Xe.on("line",t=>{et(t)});async function et(t){let e=t.trim();if(!e)return;let r;try{r=JSON.parse(e)}catch{return}if(r.id===void 0||r.id===null)return r.method==="notifications/initialized",void 0;try{let o=await tt(r);K({jsonrpc:"2.0",id:r.id,result:o})}catch(o){K({jsonrpc:"2.0",id:r.id,error:{code:-32603,message:o instanceof Error?o.message:String(o)}})}}async function tt(t){switch(t.method){case"initialize":return{protocolVersion:"2024-11-05",capabilities:{tools:{}},serverInfo:{name:I,version:"1.0.0"}};case"tools/list":return{tools:Ze};case"tools/call":{let e=V(t.params),r=typeof e.name=="string"?e.name:"",o=V(e.arguments),n=rt(),i=r==="mcp_connectors_list"||r==="mcp_tool_call"?await ot(n):void 0,s=await L({tool:r,args:o,projectRoot:n,toolCatalog:i,mcpServerFailures:i?c?.manager?.getFailedServers():void 0});if(!s.handled)throw new Error(`Unknown tool: ${r}`);return{content:[{type:"text",text:JSON.stringify(s.result)}]}}default:throw new Error(`Unknown method: ${t.method}`)}}function rt(){return process.env.ASTRACLAW_PROJECT_ROOT||process.env.QLOGICAGENT_PROJECT_ROOT||process.cwd()}async function ot(t){if(c?.projectRoot===t)return await c.ready,c.catalog;c?.manager?.disconnectAll().catch(()=>{});let e=new k,r=new h({servers:nt(),workspaceRoot:t,toolCatalog:e,log:{info:n=>process.stderr.write(`${n}
9
9
  `),warn:n=>process.stderr.write(`${n}
10
- `)}}),o=r.connectAll().then(()=>r.injectTools());return u={projectRoot:t,catalog:e,manager:r,ready:o},await o,e}function at(){let t=process.env.ASTRACLAW_MCP_CONFIG_PATH||_();if(!Xe(t))return[];try{let e=et(t,"utf8").replace(/^\uFEFF/,"");return J(JSON.parse(e))}catch(e){return process.stderr.write(`[astraclaw-native-mcp] failed to read MCP config: ${e instanceof Error?e.message:String(e)}
10
+ `)}}),o=r.connectAll().then(()=>r.injectTools());return c={projectRoot:t,catalog:e,manager:r,ready:o},await o,e}function nt(){let t=process.env.ASTRACLAW_MCP_CONFIG_PATH||_();if(!Qe(t))return[];try{let e=Ye(t,"utf8").replace(/^\uFEFF/,"");return J(JSON.parse(e))}catch(e){return process.stderr.write(`[astraclaw-native-mcp] failed to read MCP config: ${e instanceof Error?e.message:String(e)}
11
11
  `),[]}}function V(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)?t:{}}function K(t){process.stdout.write(`${JSON.stringify(t)}
12
12
  `)}
@@ -1,6 +1,6 @@
1
1
  import { type CommunityConsentClient } from "../../runtime/community/community-consent-client.js";
2
2
  import { type AgentRpcError, type AgentRpcRequest } from "../../protocol/wire/index.js";
3
- export type { CommunityConsentClient, CommunityInstallRiskTier, CommunityInstallResolution, CommunityRegistryMatchInput, } from "../../runtime/community/community-consent-client.js";
3
+ export type { CommunityConsentClient, CommunityInstallRiskTier, CommunityInstallResolution, } from "../../runtime/community/community-consent-client.js";
4
4
  export interface CommunityHandlerHost {
5
5
  resolveCommunityConsentClient?: () => CommunityConsentClient | null;
6
6
  sendResponse(id: string | number, result?: unknown, error?: AgentRpcError): void;
@@ -9,7 +9,6 @@ export interface CommunityHandlerHost {
9
9
  /** Active owner id, so community pet install/publish land in the same profile pet.status reads. */
10
10
  memoryUserId?: string;
11
11
  }
12
- export declare function handleCommunityMatchRegistry(this: CommunityHandlerHost, msg: AgentRpcRequest): Promise<void>;
13
12
  export declare function handleCommunityResolveInstall(this: CommunityHandlerHost, msg: AgentRpcRequest): Promise<void>;
14
13
  export declare function handleCommunityListResourceVersions(this: CommunityHandlerHost, msg: AgentRpcRequest): Promise<void>;
15
14
  export declare function handleCommunityInstallResource(this: CommunityHandlerHost, msg: AgentRpcRequest): Promise<void>;
@@ -32,6 +32,13 @@ export interface MemoryHandlerHost {
32
32
  export declare function handleMemoryList(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
33
33
  /** memory.list-files: returns actual topic files from memdir. */
34
34
  export declare function handleMemoryListFiles(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
35
+ /**
36
+ * memory.proposals: pending factual proposals (implicit-extract / feedback /
37
+ * dream) awaiting corroboration — the candidate surface of the proposal
38
+ * consumer. action=list (default) returns them; action=confirm/dismiss
39
+ * resolves one (confirm commits with manual authority; dismiss rejects).
40
+ */
41
+ export declare function handleMemoryProposals(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
35
42
  /**
36
43
  * memory.atlas: returns full L2 vector-memory records (wire-safe, no embedding
37
44
  * blob) plus category roll-ups, for the 3D memory atlas visualization.
@@ -342,28 +342,6 @@ export interface ConfigUpdateResult {
342
342
  reason: string;
343
343
  }>;
344
344
  }
345
- export interface CommunityMatchRegistryParams {
346
- intent: string;
347
- topK?: 1 | 2 | 3;
348
- preferOfficial?: boolean;
349
- }
350
- export interface CommunityRegistryMatchResult {
351
- id: string;
352
- type: string;
353
- title: string;
354
- summary: string;
355
- capabilityTags: string[];
356
- sourceTier: CommunityInstallSourceTier;
357
- trustStage: CommunityInstallTrustStage;
358
- resourceRiskTier: CommunityInstallRiskTier;
359
- effectiveRiskTier: CommunityInstallRiskTier;
360
- latestVersion: string | null;
361
- canonical: true;
362
- }
363
- export interface CommunityMatchRegistryResult {
364
- ok: boolean;
365
- matches: CommunityRegistryMatchResult[];
366
- }
367
345
  export type CommunityInstallRiskTier = "R0" | "R1" | "R2" | "R3";
368
346
  export type CommunityInstallSourceTier = "official" | "community";
369
347
  export type CommunityInstallTrustStage = "quarantine" | "trial" | "trusted";
@@ -660,10 +638,6 @@ export interface RpcMethodMap {
660
638
  params: ConfigUpdateParams;
661
639
  result: ConfigUpdateResult;
662
640
  };
663
- "community.matchRegistry": {
664
- params: CommunityMatchRegistryParams;
665
- result: CommunityMatchRegistryResult;
666
- };
667
641
  "community.resolveInstall": {
668
642
  params: CommunityResolveInstallParams;
669
643
  result: CommunityResolveInstallResult;
@@ -835,17 +835,6 @@ export interface AgentRpcMethodMap extends GatewayRpcMethodMap {
835
835
  value: unknown;
836
836
  };
837
837
  };
838
- "community.matchRegistry": {
839
- params: {
840
- intent: string;
841
- topK?: 1 | 2 | 3;
842
- preferOfficial?: boolean;
843
- };
844
- result: {
845
- ok: boolean;
846
- matches: Array<Record<string, unknown>>;
847
- };
848
- };
849
838
  "community.resolveInstall": {
850
839
  params: {
851
840
  resourceId: string;
@@ -115,6 +115,7 @@ export interface GatewayRpcMethodMap {
115
115
  limit?: number;
116
116
  projectId?: string;
117
117
  archived?: boolean;
118
+ agentId?: string;
118
119
  };
119
120
  result: {
120
121
  sessions: Array<{
@@ -7,26 +7,6 @@ export interface CommunityRuntimeResolution {
7
7
  checksum: string;
8
8
  sizeBytes: number;
9
9
  }
10
- export interface CommunityRegistryMatchInput {
11
- intent: string;
12
- topK?: number;
13
- preferOfficial?: boolean;
14
- }
15
- export interface CommunityRegistryMatchResult {
16
- id: string;
17
- type: string;
18
- title: string;
19
- summary: string;
20
- /** RESOURCE_CATEGORIES key(search 表演锚点;hub match 返回 ResourceView.category)。 */
21
- category: string | null;
22
- capabilityTags: string[];
23
- sourceTier: CommunityInstallSourceTier;
24
- trustStage: CommunityInstallTrustStage;
25
- resourceRiskTier: CommunityInstallRiskTier;
26
- effectiveRiskTier: CommunityInstallRiskTier;
27
- latestVersion: string | null;
28
- canonical: true;
29
- }
30
10
  export type CommunityInstallRiskTier = "R0" | "R1" | "R2" | "R3";
31
11
  export type CommunityInstallSourceTier = "official" | "community";
32
12
  export type CommunityInstallTrustStage = "quarantine" | "trial" | "trusted";
@@ -71,7 +51,6 @@ export interface CommunityConsentClientOptions {
71
51
  clientVersion?: string;
72
52
  }
73
53
  export interface CommunityConsentClient {
74
- matchRegistry(input: CommunityRegistryMatchInput): Promise<CommunityRegistryMatchResult[]>;
75
54
  resolveInstall(resourceId: string, version?: string): Promise<CommunityInstallResolution>;
76
55
  /** List a resource's published versions for the version/rollback menu (WS-B3). The
77
56
  * default client always implements it; optional so lightweight mocks may omit it. */
@@ -7,6 +7,12 @@ export declare const MEMORY_PREFETCH_CONFIG: {
7
7
  readonly LIMIT_PER_RECALL: 10;
8
8
  readonly MAX_SURFACED_ENTRIES: 100;
9
9
  };
10
+ /**
11
+ * Fallback for hosts that don't inject deps.procedureTag. MUST stay equal to
12
+ * skills/memory/task-distillation PROCEDURE_TAG (runtime cannot import skills
13
+ * per the architecture boundary; task-distillation.test.ts asserts equality).
14
+ */
15
+ export declare const PROCEDURE_TAG_FALLBACK = "distilled@v1";
10
16
  export interface MemoryHooksDeps {
11
17
  /** QMemory adapter (MemoryProvider with search/health). */
12
18
  memoryProvider?: MemoryProvider;
@@ -26,9 +26,9 @@ export declare function getOwnerProfileDir(ownerUserId?: string): string;
26
26
  export declare function getProfileMemoryDir(ownerUserId?: string): string;
27
27
  /** Dir name for our per-project companion data (sessions/checkpoints/uploads). */
28
28
  export declare const PROJECT_DATA_DIRNAME = "projectData";
29
- /** Root of the projectData tree for the current owner. */
29
+ /** Root of the projectData tree on this device (`~/.qlogicagent/projectData/`). */
30
30
  export declare function getProjectDataRoot(): string;
31
- /** `profiles/<owner>/projectData/<projectId>/` (projectId is the path-derived key). */
31
+ /** `~/.qlogicagent/projectData/<projectId>/` (projectId is the path-derived key). */
32
32
  export declare function getProjectDataDirById(projectId: string): string;
33
33
  /**
34
34
  * Ensure the user agent home directory exists and is writable.
@@ -38,9 +38,9 @@ export declare function getProjectDataDirById(projectId: string): string;
38
38
  export declare function ensureUserAgentHome(): string;
39
39
  /** `~/.qlogicagent/profiles/<owner>/.credentials.json` */
40
40
  export declare function getUserCredentialsPath(): string;
41
- /** `~/.qlogicagent/profiles/<owner>/plugins/` */
41
+ /** `~/.qlogicagent/plugins/` — device-scoped. */
42
42
  export declare function getUserPluginsDir(): string;
43
- /** `~/.qlogicagent/profiles/<owner>/skills/` */
43
+ /** `~/.qlogicagent/skills/` — device-scoped single global skill store. */
44
44
  export declare function getUserSkillsDir(): string;
45
45
  /** `~/.qlogicagent/profiles/<owner>/settings.json` */
46
46
  export declare function getUserSettingsPath(): string;
@@ -48,11 +48,13 @@ export declare function getUserSettingsPath(): string;
48
48
  export declare function getUserCacheDir(): string;
49
49
  /** `~/.qlogicagent/debug-logs/` */
50
50
  export declare function getUserDebugLogsDir(): string;
51
- /** `~/.qlogicagent/profiles/<owner>/plugin-cache/` */
51
+ /** `~/.qlogicagent/plugin-cache/` — device-scoped (download cache for installs). */
52
52
  export declare function getUserPluginCacheDir(): string;
53
- /** `~/.qlogicagent/profiles/<owner>/mcp.json` */
53
+ /** `~/.qlogicagent/mcp.json` — device-scoped installed MCP server definitions.
54
+ * The gateway's preinstall writes here too (its mcp-config.ts mirrors this path) — keeping both
55
+ * sides on the device level is what makes the preinstalled github MCP visible to every login. */
54
56
  export declare function getUserMcpConfigPath(): string;
55
- /** `~/.qlogicagent/profiles/<owner>/marketplace.json` */
57
+ /** `~/.qlogicagent/marketplace.json` — device-scoped marketplace sources. */
56
58
  export declare function getUserMarketplaceConfigPath(): string;
57
59
  /** `~/.qlogicagent/profiles/<owner>/workflows/` */
58
60
  export declare function getUserWorkflowsDir(): string;
@@ -30,10 +30,4 @@ export declare function buildAstraClawCapabilitiesSystemPrompt(input: {
30
30
  availableToolNames?: Iterable<string>;
31
31
  currentEnvironment?: string;
32
32
  }): Promise<string | undefined>;
33
- export declare function buildAstraClawCapabilitiesPromptPreamble(input: {
34
- projectRoot: string;
35
- mcpAvailable: boolean;
36
- availableToolNames?: Iterable<string>;
37
- currentEnvironment?: string;
38
- }): Promise<string | undefined>;
39
33
  export declare function handleAstraClawCapabilityToolCall(input: AstraClawCapabilityToolInput): Promise<AstraClawCapabilityToolResult>;
@@ -2,7 +2,7 @@
2
2
  * Local Checkpoint Backend — git-based shadow repo implementation.
3
3
  *
4
4
  * Creates and manages checkpoint snapshots in the centralized companion store
5
- * `~/.qlogicagent/profiles/<owner>/projectData/<projectId>/checkpoints/<sessionId>/`
5
+ * `~/.qlogicagent/projectData/<projectId>/checkpoints/<sessionId>/`
6
6
  * (NOT inside the user's workspace) using a shadow git repository independent of the user's .git.
7
7
  */
8
8
  import type { CheckpointBackend } from "../ports/checkpoint-contracts.js";
@@ -0,0 +1,49 @@
1
+ /**
2
+ * One-shot migration: fold legacy PER-PROFILE install assets into the device-level store.
3
+ *
4
+ * 设计裁定:安装的插件/技能/MCP 是【设备资产】,跟随机器;只有会话/记忆/设置/偏好随登录身份
5
+ * (owner profile)。历史版本把 skills/plugins/mcp.json/skill-lifecycle.json 挂在
6
+ * profiles/<owner>/ 下,登录切身份 → 引擎换 profile → 已装插件"消失"、预装跨身份失效。
7
+ *
8
+ * 折并规则(活跃 owner 的 profile 先处理,它的副本优先):
9
+ * - skills/<name>: 设备层缺 → 整目录 rename 进设备 store;同名且 SKILL.md 内容一致 → 丢弃
10
+ * profile 副本;同名不同内容 → 原地保留 + 大声告警(绝不静默覆盖)。
11
+ * - plugins/<name>: 设备层缺 → rename;同名 → 原地保留 + 告警(插件目录内容不可比对)。
12
+ * - skill-lifecycle.json: 按技能名合并进设备层 store(先到优先),消费掉的文件改名
13
+ * `*.migrated-to-device` 留痕。
14
+ * - mcp.json: 服务器按名合并(先到优先、绝不覆盖已有键),消费掉的文件同样改名留痕。
15
+ * - marketplace.json: 设备层缺 → rename 采用;已有 → 原地保留 + 告警。
16
+ * - skills-disabled.json(全局静音表): 与技能 store 同为设备资产 —— 各 profile 取【并集】合入
17
+ * 设备层(保守方向:任何身份下停放/静音过的技能绝不因迁移静默点亮;agent 自建技能的
18
+ * "默认停放"正是靠这张表,漏并会让它们在别的身份下全部亮起)。消费掉的文件改名留痕。
19
+ * - plugin-cache/、cache/community-installs/: 纯下载缓存,直接删除。
20
+ *
21
+ * 会话伴生数据(第二批裁定,对齐 codex/VS Code —— 会话也随设备):
22
+ * - projectData/<pid>/: 设备层缺该 pid → 整目录 rename;同 pid 跨 profile(同一 workspace 在
23
+ * 多身份下用过,path-derived id 相同)→ 结构化合并:sessions/、checkpoints/、uploads/ 的
24
+ * 子项按【uuid 名】跳已存在(同名=同一会话的陈旧副本,活跃身份先到先得);sessions/.deleted
25
+ * 墓碑按文件名并集;project.json back-ref 先到先得(输家副本可安全删除,注册表每次写都会重生成)。
26
+ * 未能并尽的残留原地保留 + 计入 conflicts(绝不静默销毁)。
27
+ * - projects.json(注册表): 按项目 id 合并(先到先得);activeProjectId 继承第一个有效值
28
+ * (活跃身份优先)。折并须在 rebuildIndexFromBackrefs 之前跑 —— 否则自愈会先用空注册表
29
+ * 重建、丢掉 active 指针等索引态。
30
+ *
31
+ * 幂等:按目录状态驱动(profile 里没有遗留 → 全程 no-op),每次启动同步段调用都安全。
32
+ */
33
+ export interface DeviceScopeMigrationResult {
34
+ movedSkills: string[];
35
+ movedPlugins: string[];
36
+ /** projectData/<pid> trees moved or merged into the device store. */
37
+ movedProjects: string[];
38
+ /** Same-name different-content entries left in place (loud warning emitted). */
39
+ conflicts: string[];
40
+ /** Profile files (lifecycle/mcp/marketplace/registry/mute) whose content was folded into the device store. */
41
+ mergedFiles: string[];
42
+ }
43
+ /**
44
+ * Fold every profile's legacy install assets into the device-level store. Bounded (rename-based),
45
+ * idempotent, best-effort with loud per-item diagnostics. Call from the SYNCHRONOUS bootstrap
46
+ * section BEFORE anything reads the skill store — on an upgraded machine every installed skill
47
+ * still lives under profiles/ until this runs.
48
+ */
49
+ export declare function migrateDeviceScopeInstalls(): DeviceScopeMigrationResult;
@@ -2,17 +2,18 @@
2
2
  * Project Data Paths — centralized location for our per-project COMPANION data (the "account
3
3
  * book"): session transcripts/metadata, checkpoint shadow repos, uploaded attachments, deletion
4
4
  * tombstones. Mirrors VS Code's workspaceStorage: this data is OURS and lives in a centralized,
5
- * per-project-id, physically-isolated dir under the owner profile — NEVER inside the user's
5
+ * per-project-id, physically-isolated dir at the DEVICE level — NEVER inside the user's
6
6
  * workspace folder. The workspace folder holds only user work product (code/docs/generated media).
7
+ * 设备级(用户裁定,对齐 codex/VS Code):会话数据跟随机器;登录身份只属于云同步/计费层。
7
8
  *
8
- * ~/.qlogicagent/profiles/<owner>/projectData/<projectId>/{sessions,checkpoints,uploads}/
9
+ * ~/.qlogicagent/projectData/<projectId>/{sessions,checkpoints,uploads}/
9
10
  *
10
11
  * projectId is the PATH-DERIVED key (deriveProjectId(workspaceDir), see agent-paths) — the
11
12
  * mainstream model (VS Code / cc-haha): same folder → same id, deterministic, recomputable, no
12
13
  * central-registry dependency for the storage key. Deleting a project = `rm` projectData/<id>/.
13
14
  */
14
15
  export { getProjectDataDirById, getProjectDataRoot } from "./agent-paths.js";
15
- /** `~/.qlogicagent/profiles/<owner>/projectData/<projectId>/` for a projectId or workspaceDir. */
16
+ /** `~/.qlogicagent/projectData/<projectId>/` for a projectId or workspaceDir. */
16
17
  export declare function getProjectDataDir(projectIdOrWorkspaceDir: string): string;
17
18
  /** `projectData/<id>/sessions/` */
18
19
  export declare function getProjectDataSessionsRoot(projectIdOrWorkspaceDir: string): string;
@@ -2,9 +2,10 @@
2
2
  * Skill mute registries — under the single-store model, EVERY skill is global. There is no
3
3
  * project-scoped / opt-in concept; instead there are two opt-OUT mute lists:
4
4
  *
5
- * - owner-level (~/.qlogicagent/profiles/<owner>/skills-disabled.json) — off in EVERY project
5
+ * - device-level (~/.qlogicagent/skills-disabled.json) — off in EVERY project
6
6
  * (the plugin card's on/off switch; also where agent-learned skills land, disabled, until the
7
- * user reviews and enables them).
7
+ * user reviews and enables them). 与技能 store 同域:插件及其开关都是设备资产,登录身份切换
8
+ * 不得改变哪些技能是开着的(此前 per-owner 键控会让 A 身份停放的技能在 B 身份下点亮)。
8
9
  * - per-project (<cwd>/.qlogicagent/skills-disabled.json) — off in THIS project only
9
10
  * (the "project skills" opt-out, to cut down which skills an agent sees in a given project).
10
11
  *
@@ -159,6 +159,27 @@ export interface MemoryHandlerProvider extends MemoryProvider {
159
159
  } | null>;
160
160
  /** Persist understood/extracted text on an attachment row. */
161
161
  setAttachmentText?(id: string, text: string): void;
162
+ /** Factual proposals for the candidate surface: pending (default) awaiting
163
+ * corroboration, or expired (read-only history of what timed out). */
164
+ listPendingProposals?(userId: string, limit?: number, status?: "pending" | "expired"): Array<{
165
+ id: string;
166
+ text: string;
167
+ category: string;
168
+ importance: number;
169
+ confidence: number;
170
+ source: string;
171
+ tags: string[];
172
+ createdAt: number;
173
+ }>;
174
+ /** UI resolution of one pending proposal: confirm commits it with manual authority; dismiss rejects it. */
175
+ resolveProposal?(userId: string, proposalId: string, action: "confirm" | "dismiss"): Promise<boolean>;
176
+ /** Evidence-laddered backlog consumption (corroborated commit / feedback solo / TTL expiry). */
177
+ consumePendingProposals?(userId: string): Promise<{
178
+ committed: number;
179
+ merged: number;
180
+ expiredIds: string[];
181
+ pendingLeft: number;
182
+ }>;
162
183
  }
163
184
  export interface MemoryDreamProvider {
164
185
  search(query: string, userId: string, options?: {
@@ -0,0 +1,20 @@
1
+ /**
2
+ * FTS pre-segmentation for CJK-aware keyword search.
3
+ *
4
+ * SQLite FTS5's unicode61 tokenizer does not segment CJK: a run of Chinese
5
+ * characters indexes as ONE token, so a query like 咖啡 can never match a
6
+ * memory containing 用户喜欢喝美式咖啡. Instead of switching tokenizers
7
+ * (trigram misses 2-char Chinese words, ICU is not bundled), we index a
8
+ * pre-segmented shadow column (`memories.text_seg`) and segment queries with
9
+ * the SAME function:
10
+ * - Latin/digit runs stay whole words ("docker", "v2")
11
+ * - CJK runs become character bigrams (咖啡, 啡因) + the single char for
12
+ * 1-char runs — the same scheme the near-duplicate gate already uses.
13
+ *
14
+ * Index side and query side MUST share this function; drift between them
15
+ * silently zeroes recall.
16
+ */
17
+ /** Segment text into FTS-friendly tokens (lowercased). */
18
+ export declare function segmentForFts(text: string): string[];
19
+ /** Render the segmented shadow text stored in memories.text_seg. */
20
+ export declare function segmentTextForFts(text: string): string;