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.
- package/dist/agent.js +3 -3
- package/dist/cli.js +1 -1
- package/dist/index.js +458 -440
- package/dist/orchestration.js +1 -1
- package/dist/skills/mcp/astraclaw-native-mcp-server.js +6 -6
- package/dist/types/cli/handlers/community-handler.d.ts +1 -2
- package/dist/types/cli/handlers/memory-handler.d.ts +7 -0
- package/dist/types/protocol/methods.d.ts +0 -26
- package/dist/types/protocol/wire/agent-methods.d.ts +0 -11
- package/dist/types/protocol/wire/gateway-rpc.d.ts +1 -0
- package/dist/types/runtime/community/community-consent-client.d.ts +0 -21
- package/dist/types/runtime/hooks/memory-hooks.d.ts +6 -0
- package/dist/types/runtime/infra/agent-paths.d.ts +9 -7
- package/dist/types/runtime/infra/astraclaw-capabilities.d.ts +0 -6
- package/dist/types/runtime/infra/checkpoint-backend.d.ts +1 -1
- package/dist/types/runtime/infra/migrate-device-scope.d.ts +49 -0
- package/dist/types/runtime/infra/project-data-paths.d.ts +4 -3
- package/dist/types/runtime/infra/project-skill-manifest.d.ts +3 -2
- package/dist/types/runtime/ports/memory-provider.d.ts +21 -0
- package/dist/types/skills/memory/fts-segment.d.ts +20 -0
- package/dist/types/skills/memory/local-memory-provider.d.ts +52 -4
- package/dist/types/skills/memory/local-store-records.d.ts +6 -1
- package/dist/types/skills/memory/local-store.d.ts +61 -10
- package/dist/types/skills/memory/memdir.d.ts +10 -5
- package/dist/types/skills/memory/memory-consolidation.d.ts +7 -0
- package/dist/types/skills/memory/proposal-consumer.d.ts +51 -0
- package/dist/types/skills/memory/sqlite-memory-mappers.d.ts +2 -1
- package/dist/types/skills/memory/sqlite-memory-schema.d.ts +9 -1
- package/package.json +3 -2
- package/dist/types/cli/tool-bootstrap-community-registration.d.ts +0 -9
- package/dist/types/runtime/community/community-discovery-cache.d.ts +0 -24
- package/dist/types/runtime/community/community-discovery-coordinator.d.ts +0 -33
- package/dist/types/runtime/hooks/community-discovery-hook.d.ts +0 -18
- package/dist/types/skills/tools/community-seek-tool.d.ts +0 -49
package/dist/orchestration.js
CHANGED
|
@@ -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
|
|
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:
|
|
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
|
|
8
|
-
`);if(
|
|
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
|
|
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,
|
|
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;
|
|
@@ -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
|
|
29
|
+
/** Root of the projectData tree on this device (`~/.qlogicagent/projectData/`). */
|
|
30
30
|
export declare function getProjectDataRoot(): string;
|
|
31
|
-
/**
|
|
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/
|
|
41
|
+
/** `~/.qlogicagent/plugins/` — device-scoped. */
|
|
42
42
|
export declare function getUserPluginsDir(): string;
|
|
43
|
-
/** `~/.qlogicagent/
|
|
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/
|
|
51
|
+
/** `~/.qlogicagent/plugin-cache/` — device-scoped (download cache for installs). */
|
|
52
52
|
export declare function getUserPluginCacheDir(): string;
|
|
53
|
-
/** `~/.qlogicagent/
|
|
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/
|
|
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/
|
|
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
|
|
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/
|
|
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/
|
|
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
|
-
* -
|
|
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;
|