wyrm-mcp 9.2.2 → 9.2.3
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/activation.js +1 -1
- package/dist/agent-loop.js +2 -2
- package/dist/audit.js +2 -2
- package/dist/autoconfig.js +6 -6
- package/dist/backup-cli.js +6 -0
- package/dist/backup.js +1 -0
- package/dist/bridge.js +1 -1
- package/dist/buddy-runner.js +1 -1
- package/dist/buddy.js +4 -4
- package/dist/capabilities.js +1 -1
- package/dist/causality.js +3 -3
- package/dist/cloud/cli.js +3 -3
- package/dist/cloud/sync-daemon-entrypoint.js +1 -1
- package/dist/cloud/sync-engine.js +8 -7
- package/dist/cloud-backup.js +4 -4
- package/dist/cloud-sync-entrypoint.js +1 -1
- package/dist/cloud-sync.js +1 -1
- package/dist/connectors/ingest.js +2 -2
- package/dist/constellation.js +1 -1
- package/dist/context-build-budgeted.js +4 -4
- package/dist/context-ranking.js +1 -1
- package/dist/daemon-writer.js +1 -1
- package/dist/database.js +41 -23
- package/dist/design.js +1 -1
- package/dist/erasure-cli.js +3 -0
- package/dist/erasure-log.js +8 -0
- package/dist/erasure.js +1 -0
- package/dist/event-replication.js +1 -1
- package/dist/events.js +11 -11
- package/dist/failure-patterns.js +67 -44
- package/dist/federation.js +11 -10
- package/dist/governance.js +1 -0
- package/dist/handlers/agent.js +4 -4
- package/dist/handlers/alias-adapters.js +1 -1
- package/dist/handlers/audit.js +1 -1
- package/dist/handlers/boundary.js +1 -1
- package/dist/handlers/capture.js +54 -52
- package/dist/handlers/causality.js +2 -2
- package/dist/handlers/cloud.js +9 -9
- package/dist/handlers/companion.js +4 -4
- package/dist/handlers/entity.js +6 -6
- package/dist/handlers/events.js +4 -4
- package/dist/handlers/failure.js +15 -12
- package/dist/handlers/goals.js +2 -2
- package/dist/handlers/intelligence.js +81 -74
- package/dist/handlers/mcpclient.js +3 -3
- package/dist/handlers/presence.js +1 -1
- package/dist/handlers/prompts.js +2 -2
- package/dist/handlers/quest.js +11 -4
- package/dist/handlers/recall.js +10 -10
- package/dist/handlers/resources.js +1 -1
- package/dist/handlers/review.js +3 -3
- package/dist/handlers/run.js +3 -3
- package/dist/handlers/search.js +1 -1
- package/dist/handlers/session.js +27 -25
- package/dist/handlers/share.js +3 -3
- package/dist/handlers/skill.js +2 -2
- package/dist/handlers/symbols.js +5 -5
- package/dist/handlers/syncops.js +2 -2
- package/dist/harvest.js +5 -5
- package/dist/hours.js +1 -1
- package/dist/http-auth.js +2 -2
- package/dist/http-fast.js +17 -17
- package/dist/http-projects.js +4 -0
- package/dist/http-rate-limit.js +1 -0
- package/dist/index-health.js +52 -0
- package/dist/index.js +2 -2
- package/dist/indexer.js +4 -4
- package/dist/intelligence.js +36 -29
- package/dist/lane-provenance.js +39 -0
- package/dist/license.js +1 -1
- package/dist/lineage.js +15 -0
- package/dist/live-embedding-state.js +2 -2
- package/dist/maintenance.js +2 -2
- package/dist/mcp-integrity.js +2 -2
- package/dist/memory-artifacts.js +39 -37
- package/dist/metabolize.js +9 -7
- package/dist/metrics.js +1 -1
- package/dist/migrate-prompt.js +1 -1
- package/dist/migrations.js +236 -45
- package/dist/priority-embed.js +1 -1
- package/dist/providers/embedding-provider.js +1 -1
- package/dist/readonly-gate.js +1 -1
- package/dist/redact-backfill.js +1 -0
- package/dist/rehydration.js +30 -20
- package/dist/reindex.js +1 -1
- package/dist/render-target.js +6 -6
- package/dist/repl-guard.js +1 -1
- package/dist/replication-daemon-entrypoint.js +1 -1
- package/dist/replication-daemon.js +1 -1
- package/dist/retention.js +1 -0
- package/dist/reverse-bridge.js +6 -6
- package/dist/review-sample.js +31 -0
- package/dist/security.js +1 -1
- package/dist/self-maintenance.js +4 -4
- package/dist/served-records.js +8 -2
- package/dist/setup-wizard.js +1 -1
- package/dist/setup.js +1 -1
- package/dist/skill-author.js +2 -2
- package/dist/store-open.js +1 -0
- package/dist/store-readonly.js +1 -0
- package/dist/sub-agent.js +2 -2
- package/dist/tool-manifest-v2.json +1 -1
- package/dist/tool-manifest.json +1 -1
- package/dist/truth-freshness.js +8 -0
- package/dist/ui-dashboard.js +4 -4
- package/dist/vault.js +1 -1
- package/dist/vector-init.js +1 -1
- package/dist/vectors.js +4 -3
- package/dist/visibility.js +12 -12
- package/dist/write-guard.js +1 -0
- package/dist/wyrm-cli.js +108 -92
- package/dist/wyrm-guard.js +13 -12
- package/dist/wyrm-loop.js +3 -3
- package/dist/wyrm-manifest.json +1 -1
- package/dist/wyrm-memo.js +5 -5
- package/package.json +1 -1
- package/scripts/hooks/wyrm-session-capture.mjs +3 -0
package/dist/http-fast.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
2
|
+
import re from"http";import{WyrmDB as x}from"./database.js";import{cache as h,estimateTokens as ne,truncateToTokens as se,timed as $}from"./performance.js";import{authMiddleware as oe,getAuthStatus as w,getSecurityHeaders as P,getUiNonce as ae,siteContextFor as ie}from"./http-auth.js";import{refuseWrite as ce}from"./write-guard.js";import{WyrmLogger as le}from"./logger.js";import{SecurityError as ue,sanitizeFtsQuery as q,validateProjectPath as de}from"./security.js";import{listProjectsPage as pe,parseProjectListQuery as me,registerProjectAt as fe}from"./http-projects.js";import{readFileSync as L,existsSync as T,readdirSync as Ee,realpathSync as Y}from"fs";import{homedir as he}from"os";import{dirname as B,join as y}from"path";import{fileURLToPath as _e}from"url";let b=null;function Se(){if(b!==null)return b;b="unknown";try{const e=B(_e(import.meta.url));for(const t of[y(e,"..","package.json"),y(e,"..","..","package.json")]){if(!T(t))continue;const r=JSON.parse(L(t,"utf-8")).version;if(typeof r=="string"){b=r;break}}}catch{}return b}import{getUIDashboardHTML as ye}from"./ui-dashboard.js";import{resolveBranding as F}from"./branding.js";import{verifyLicense as J,getLicenseInfo as ge}from"./license.js";import{loadRevocations as Te,refreshRevocations as Oe}from"./revocations.js";import{rerankConfigured as Re,rerankEgressHost as ve}from"./rerank.js";import{MemoryArtifacts as Ce}from"./memory-artifacts.js";import{createVectorStore as Le}from"./vectors.js";import{scheduleMaintenanceSweep as be}from"./self-maintenance.js";import{GroundTruths as je,computeStaleness as Ne}from"./intelligence.js";import{Causality as Me}from"./causality.js";import{wireTruthAutoCascade as Ae}from"./truth-cascade.js";import{FailurePatterns as De}from"./failure-patterns.js";import{handleDaemonWrite as Ie}from"./daemon-write-endpoint.js";import{retryableWriteCause as K,busyErrorBody as Q}from"./sqlite-busy.js";import{sseFrame as ke,resolveStartCursor as V,SSE_KEEPALIVE as we}from"./events-sse.js";import{readonlyBlocks as Pe}from"./readonly-gate.js";import{resolveActorEnvelope as Fe,runWithActor as He,setDefaultWriter as We}from"./handlers/boundary.js";import{setGovernanceSurface as Ge}from"./governance.js";import{asNewerStoreError as Ue,NEWER_STORE_CODE as xe}from"./store-readonly.js";Ge("http");function X(e,t,r){const n=Ue(r);return n?(E(e,t,{e:n.message,code:xe,readonly:1,store_schema:n.store,binary_schema:n.binary},503),!0):!1}function $e(e=process.env){for(const t of[e.WYRM_PORT,e.WYRM_HTTP_PORT]){if(t===void 0||t.trim()==="")continue;const r=Number(t);if(Number.isInteger(r)&&r>=1&&r<=65535)return r}return 3333}const qe=/^(?:(?:0+\.){3}0+|::)$/;function Ye(e,t){const r=e===""||qe.test(e)?"127.0.0.1":e;return`http://${r.includes(":")?`[${r}]`:r}:${t}/ui`}const j=$e(),O=process.env.WYRM_UI_READONLY==="1",Be=512*1024,D=500,Je=parseInt(process.env.WYRM_MAX_SSE_STREAMS||"64",10)||64,Ke=parseInt(process.env.WYRM_MAX_SSE_PER_IP||"8",10)||8;let H=0;const R=new Map;let N=!1;const W=new Set;let v=null,M=null,A=null,I=null;function a(){return v||(v=new x(process.env.WYRM_DB_PATH)),v}function g(){if(!M){M=new Ce(a().getDatabase());try{const e=process.env.WYRM_VECTOR_PROVIDER||"auto";e!=="none"&&M.setVectorStore(Le({provider:e},a().getDatabase()))}catch{}}return M}function Qe(){return A||(A=new je(a().getDatabase()),Ae(A,new Me(a().getDatabase()))),A}function Ve(){return I||(I=new De(a().getDatabase())),I}function Xe(e){const t=v;v=e,M=null,A=null,I=null;try{t?.close()}catch{}}async function ze(e={}){Te(e.publicKeyPem),await Oe(e).catch(()=>{})}function z(){const e=[],t=he(),r=new Set;let n=[];try{n=Ee(t)}catch{return e}n.sort((s,o)=>o.localeCompare(s));for(const s of n){if(s!==".wyrm"&&!s.startsWith(".wyrm-"))continue;let o;try{o=Y(y(t,s))}catch{continue}if(r.has(o))continue;const l=y(o,"wyrm.db");if(!T(l))continue;r.add(o);let i="Local",u="free";try{const c=y(o,"license.json");if(T(c)){const m=JSON.parse(L(c,"utf-8")),p=J(m);i=m.license&&m.license.issued_to||i,u=p.valid?p.tier:"free"}else{const m=y(o,"cloud.json");T(m)&&(i=JSON.parse(L(m,"utf-8")).email||i)}}catch{}const d=s.replace(/^\.wyrm-?/,"")||"default";e.push({name:d,dbPath:l,account:i,tier:u})}return e}const k=new le({level:"info"});function _(e,t,r){const n=Number.parseInt(String(e??""),10);return!Number.isFinite(n)||n<1?t:Math.min(n,r)}function G(e){const t=e==null?"":String(e);if(t)return a().getProject(t)||a().getProjectByName(t)}function E(e,t,r,n=200){const s=JSON.stringify(r),o=P(t);e.writeHead(n,{"Content-Type":"application/json","Content-Length":Buffer.byteLength(s),"X-Tokens":String(ne(r)),...o,...N?{Connection:"close"}:{}}),e.end(s)}function Ze(e,t,r){const n=P(t);e.writeHead(200,{...n,"Content-Type":"text/html; charset=utf-8","Content-Length":Buffer.byteLength(r),"Cache-Control":"no-store",...N?{Connection:"close"}:{}}),e.end(r)}function et(e){return new Promise((t,r)=>{if(e.method==="GET"){t({});return}let n="",s=0;e.on("data",o=>{if(s+=o.length,s>Be){e.destroy(),r(new Error("Request body too large"));return}n+=o}),e.on("end",()=>{try{t(n?JSON.parse(n):{})}catch{r(new Error("Invalid JSON"))}}),e.on("error",r)})}const Z={"GET /c":e=>{const t=`ctx:${e.p||"global"}`,r=h.get(t);if(r)return r;const n=e.p;let s;if(n){const o=a().getProject(n);if(!o)return{e:"not found"};const l=a().getPendingQuests(o.id),i=a().getRecentSessions(o.id,3);s={n:o.name,s:o.stack,q:l.length,qt:l.slice(0,5).map(u=>u.title),r:i[0]?.summary||i[0]?.notes?.slice(0,200)||null}}else{const o=a().getAllProjects(20),l=a().getAllPendingQuests();s={p:o.map(i=>({n:i.name,s:i.stack,q:a().getPendingQuests(i.id).length})),tq:l.length}}return h.set(t,s),s},"GET /p":e=>{const t=me(e);if(t)return pe(a(),t);const r=h.get("projects");if(r)return r;const s=a().getAllProjects(50).map(o=>({i:o.id,n:o.name,p:o.path,s:o.stack}));return h.set("projects",s),s},"POST /scan":e=>{const t=e.d||e.directory||process.env.HOME+"/Git Projects";let r;try{r=de(t)}catch{return{e:"path not allowed"}}return h.invalidate(),{found:a().scanForProjects(r,!0).length}},"POST /pa":e=>{const t=fe(a(),e);return"e"in t||(h.invalidate("projects"),h.invalidate("ctx")),t},"GET /q":e=>{const t=e.p;if(t){const r=a().getProject(t);return r?a().getPendingQuests(r.id).map(n=>({i:n.id,t:n.title,p:n.priority[0]})):{e:"not found"}}return a().getAllPendingQuests().slice(0,20).map(r=>({i:r.id,t:r.title,p:r.priority[0]}))},"POST /q":e=>{const t=e.p,r=a().getProject(t);return r?(h.invalidate("ctx"),{i:a().addQuest(r.id,e.t,e.d,e.pr||"medium").id}):{e:"not found"}},"POST /qc":e=>{const t=typeof e.i=="number"?e.i:parseInt(String(e.i),10);return!t||t<1?{e:"id required"}:(h.invalidate("ctx"),a().updateQuest(t,"completed"),{ok:1})},"POST /s":e=>{const t=e.p;let r=a().getProject(t);if(!r){try{a().scanForProjects(t,!1)}catch(s){if(s instanceof ue)return{e:"path not allowed"};throw s}r=a().getProject(t)}if(!r)return{e:"not found"};let n=a().getTodaySession(r.id);return n||(n=a().createSession(r.id,{objectives:e.o||"",notes:""})),h.invalidate("ctx"),{i:n.id,d:n.date}},"POST /su":e=>{const t=e.i;return h.invalidate("ctx"),a().updateSession(t,{notes:e.n,summary:e.s,completed:e.c}),{ok:1}},"POST /x":e=>{const t=e.p,r=a().getProject(t);return r?(a().setContext(r.id,e.k,e.v),h.invalidate("ctx"),{ok:1}):{e:"not found"}},"GET /x":e=>{const t=e.p,r=a().getProject(t);return r?a().getAllContext(r.id):{e:"not found"}},"POST /g":e=>{const t=e.k,r=e.v;return!t||typeof t!="string"?{e:"k (key) required"}:r==null?{e:"v (value) required"}:(a().setGlobalContext(t,String(r)),h.invalidate(),{ok:1})},"GET /g":()=>a().getAllGlobalContext(),"GET /s":e=>{const t=e.q;if(!t)return{e:"query required"};const r=q(t);return{q:a().searchQuests(r).slice(0,5).map(s=>({i:s.id,t:s.title})),s:a().searchSessions(r).slice(0,3).map(s=>({i:s.id,d:s.date})),p:a().searchProjects(r).slice(0,3).map(s=>({n:s.name,p:s.path}))}},"POST /d":e=>{const t=e.p,r=a().getProject(t);return r?{i:a().insertData(r.id,e.c,e.k,e.v,e.m).id}:{e:"not found"}},"GET /d":e=>{const t=e.p,r=a().getProject(t);if(!r)return{e:"not found"};const n=_(e.l,20,100);return a().queryData(r.id,e.c,n).map(s=>({k:s.key,v:se(s.value,100)}))},"GET /d/search":e=>{const t=e.p,r=a().getProject(t);if(!r)return{e:"not found"};const n=e.q;if(!n)return{e:"q (query) required"};const s=e.c,o=_(e.l,10,100);let l=a().searchData(n,r.id);return s&&(l=l.filter(i=>i.category===s)),l.slice(0,o).map(i=>({k:i.key,v:i.value,c:i.category,m:i.metadata}))},"GET /d/agg":e=>{const t=e.p,r=a().getProject(t);if(!r)return{e:"not found"};const n=e.c;if(!n)return{e:"c (category) required"};const s=e.stack_key,o=e.scanner,l=_(e.l,1e3,1e4),i={};for(const u of a().queryData(r.id,n,l)){let d;try{d=JSON.parse(u.value)}catch{continue}if(s&&d.stack_key!==s||o&&d.scanner!==o)continue;const c=String(d.scanner??""),m=String(d.payload_hash??"");if(!c||!m)continue;const p=`${c}:${m}`,f=i[p]??{s:c,ph:m,sk:String(d.stack_key??""),h:0,t:0};f.t+=1,d.hit&&(f.h+=1),i[p]=f}return Object.values(i).map(u=>({...u,r:u.t>0?u.h/u.t:0})).sort((u,d)=>d.r-u.r||d.h-u.h)},"POST /batch":e=>{const t=e.ops;if(!t||!Array.isArray(t))return{e:"ops required"};if(t.length>D)return{e:`max ${D} ops per batch`};const r=performance.now();return{r:t.map(s=>{const o=`${s.m} ${s.r}`,l=Z[o];if(!l)return{e:"unknown"};try{return{d:l(s.a||{})}}catch{return{e:"op failed"}}}),ms:Math.round(performance.now()-r)}},"POST /write":e=>Ie({db:a(),artifacts:g(),truths:Qe(),failures:Ve()},e),"GET /syms":e=>{const t=String(e.q??"").slice(0,200);if(!t)return[];const r=_(e.limit,20,200),n=a().getDatabase();try{return n.prepare(`
|
|
3
3
|
SELECT symbol, kind, language, file_path, line, signature, project_id
|
|
4
4
|
FROM symbol_index
|
|
5
5
|
WHERE symbol LIKE ?
|
|
@@ -19,63 +19,63 @@ import V from"http";import{WyrmDB as W}from"./database.js";import{cache as h,est
|
|
|
19
19
|
AND (key LIKE ? OR value LIKE ? OR rationale LIKE ?)
|
|
20
20
|
ORDER BY confidence DESC
|
|
21
21
|
LIMIT ?
|
|
22
|
-
`).all(`%${t}%`,`%${t}%`,`%${t}%`,r)}catch{return[]}},"GET /routing":e=>{const t=String(e.task_type??e.t??"").slice(0,200).trim();if(!t)return{e:"task_type required"};const r=_(e.limit,10,100);let n;const s=e.p;if(s){const i=a().getProject(s);if(!i)return{e:"not found"};n=i.id}const o=e.since_days!=null?Number(e.since_days):void 0;return a().recallRouting(t,{projectId:n,limit:r,sinceDays:Number.isFinite(o)?o:void 0}).map(i=>({m:i.model_id,tools:i.tool_names,runs:i.runs,ok:i.successes,fail:i.failures,rate:Math.round(i.success_rate*1e3)/1e3,ms:i.avg_latency_ms,last:i.last_ts}))},"POST /routing":e=>{const t=String(e.task_type??"").slice(0,200).trim(),r=String(e.model_id??"").slice(0,200).trim();if(!t)return{e:"task_type required"};if(!r)return{e:"model_id required"};if(e.success===void 0||e.success===null)return{e:"success required"};let n;const s=e.p;if(s){const
|
|
22
|
+
`).all(`%${t}%`,`%${t}%`,`%${t}%`,r)}catch{return[]}},"GET /routing":e=>{const t=String(e.task_type??e.t??"").slice(0,200).trim();if(!t)return{e:"task_type required"};const r=_(e.limit,10,100);let n;const s=e.p;if(s){const i=a().getProject(s);if(!i)return{e:"not found"};n=i.id}const o=e.since_days!=null?Number(e.since_days):void 0;return a().recallRouting(t,{projectId:n,limit:r,sinceDays:Number.isFinite(o)?o:void 0}).map(i=>({m:i.model_id,tools:i.tool_names,runs:i.runs,ok:i.successes,fail:i.failures,rate:Math.round(i.success_rate*1e3)/1e3,ms:i.avg_latency_ms,last:i.last_ts}))},"POST /routing":e=>{const t=String(e.task_type??"").slice(0,200).trim(),r=String(e.model_id??"").slice(0,200).trim();if(!t)return{e:"task_type required"};if(!r)return{e:"model_id required"};if(e.success===void 0||e.success===null)return{e:"success required"};let n;const s=e.p;if(s){const u=a().getProject(s);u&&(n=u.id)}const o=Array.isArray(e.tool_names)?e.tool_names.map(u=>String(u)):e.tool_names!=null?String(e.tool_names):null,l=e.latency_ms!=null?Number(e.latency_ms):null,i=e.success===!0||e.success===1||e.success==="1"||e.success==="true";try{return{i:a().recordRouting({projectId:n,taskType:t,modelId:r,toolNames:o,success:i,latencyMs:Number.isFinite(l)?l:null})}}catch(u){return{e:u.message}}},"GET /audit":e=>{const t=_(e.limit,50,500),r=e.kind,n=a().getDatabase();try{return r?n.prepare("SELECT * FROM audit_log WHERE event_kind = ? ORDER BY id DESC LIMIT ?").all(r,t):n.prepare("SELECT * FROM audit_log ORDER BY id DESC LIMIT ?").all(t)}catch{return[]}},"GET /sync/push":e=>{const t=e.since,r=_(e.limit,500,5e3),n=a().getDatabase(),s=[],o=t??"1970-01-01",l=[["session","sessions","created_at"],["quest","quests","created_at"],["truth","ground_truths","updated_at"],["artifact","memory_artifacts","last_accessed_at"],["edge","decision_edges","created_at"]],i=(()=>{try{return n.prepare("PRAGMA table_info(projects)").all().some(d=>d.name==="sync_policy")?"AND (project_id IS NULL OR project_id IN (SELECT id FROM projects WHERE sync_policy = 'team'))":""}catch{return""}})();for(const[u,d,c]of l){if(s.length>=r)break;try{const m=n.prepare(`SELECT * FROM ${d}
|
|
23
23
|
WHERE is_shared = 1 ${i} AND ${c} > ?
|
|
24
24
|
ORDER BY ${c} ASC
|
|
25
|
-
LIMIT ?`).all(o,Math.max(1,r-s.length));for(const
|
|
25
|
+
LIMIT ?`).all(o,Math.max(1,r-s.length));for(const p of m)s.push({kind:u,id:p.id,project_id:p.project_id??null,updated_at:p[c]??null,payload:p})}catch{}}return{rows:s,count:s.length,cursor:new Date().toISOString()}},"GET /events":e=>{if(!a().liveMemoryEnabled())return{e:"live memory disabled",disabled:1};const t=G(e.project??e.p);if(!t)return{e:"not found"};const r=V(void 0,e.since),n=_(e.limit??e.l,100,1e3),o=e.shared==="1"||e.shared==="true"?a().eventsForPush(t.id,r,n):a().eventsSince(t.id,r,n),l=o.length?o[o.length-1].cursor:r;return{project:t.name,cursor:l,count:o.length,events:o}},"POST /events":e=>{if(!a().liveMemoryEnabled())return{e:"live memory disabled",disabled:1};const t=G(e.project??e.p);if(!t)return{e:"not found"};const r=Array.isArray(e.events)?e.events:e.event?[e.event]:[];if(r.length===0)return{e:"events[] required"};if(r.length>D)return{e:`max ${D} events per request`};let n=0,s=0,o=0;for(const l of r){const i=a().ingestRemoteEvent(t.id,l);i==="inserted"?n++:i==="echo"?o++:s++}return n>0&&h.invalidate("ctx"),{project:t.name,inserted:n,duplicate:s,echo:o}},"GET /stats":()=>{const{result:e,ms:t}=$(()=>a().getStats());return{...e,ms:t,cache:h.stats()}},"GET /health":async e=>{const t={ok:1,ts:Date.now()};if(!/^(1|true|yes)$/i.test(String(e.check_dependencies??"")))return t;const r={...t};try{const s=a().getDatabase().prepare("SELECT MAX(version) v FROM schema_versions").get().v;r.db={ok:1,migration:s}}catch{r.ok=0,r.db={ok:0}}try{const n=g().getVectorStore();if(n){const s=n.getProvider(),o=n.indexCoverage();r.vectors={provider:s.name,model:s.model,ready:await s.isReady(),indexed:o.activeCount,stale:o.stale?1:0,...o.stale?{indexed_under:Object.keys(o.otherModels),hint:"run wyrm_reindex"}:{},egress:s.remoteHost??"none"}}else r.vectors={provider:"none",ready:!1}}catch{r.vectors={ok:0}}return r.rerank={configured:Re()?1:0,provider:(process.env.WYRM_RERANK_PROVIDER||"llamacpp").trim()||"llamacpp",egress:ve()??"none"},r},"GET /auth/status":()=>{const e=w();return{auth:e.requireAuth?1:0,origins:e.allowedOrigins.length}},"GET /ui/stats":()=>{const e=a().getDatabase(),t=e.prepare("SELECT COUNT(*) as c FROM projects").get().c,r=e.prepare("SELECT COUNT(*) as c FROM sessions").get().c,n=e.prepare("SELECT COUNT(*) as c FROM quests WHERE status IN ('pending','in_progress')").get().c,s=e.prepare("SELECT COUNT(*) as c FROM data_lake").get().c,o=e.prepare("SELECT COUNT(*) as c FROM memory_artifacts WHERE needs_review = 0").get().c,l=e.prepare("SELECT COUNT(*) as c FROM memory_artifacts WHERE needs_review = 1").get().c,i=e.prepare("SELECT COUNT(*) as c FROM ground_truths WHERE is_current = 1").get().c,u=e.prepare(`
|
|
26
26
|
SELECT date, summary, objectives FROM sessions
|
|
27
27
|
ORDER BY created_at DESC LIMIT 8
|
|
28
|
-
`).all();return{projects:t,sessions:r,active_quests:n,data_points:s,artifacts:o,review_queue:
|
|
28
|
+
`).all();return{projects:t,sessions:r,active_quests:n,data_points:s,artifacts:o,review_queue:l,truths:i,recent_sessions:u}},"GET /ui/memories":e=>{const t=a().getDatabase(),r=Math.max(1,parseInt(String(e.page||"1"),10)),n=Math.min(100,Math.max(1,parseInt(String(e.limit||"20"),10))),s=e.kind?String(e.kind):"",o=e.search?String(e.search):"",l=(r-1)*n;let i,u,d,c;if(o){const f=q(o);s?(i=`
|
|
29
29
|
SELECT ma.*, p.name AS project_name
|
|
30
30
|
FROM memory_artifacts ma
|
|
31
31
|
JOIN memory_artifacts_fts fts ON fts.rowid = ma.id
|
|
32
32
|
LEFT JOIN projects p ON ma.project_id = p.id
|
|
33
33
|
WHERE memory_artifacts_fts MATCH ? AND ma.kind = ?
|
|
34
34
|
AND ma.supersedes_id IS NULL
|
|
35
|
-
ORDER BY ma.confidence DESC LIMIT ? OFFSET ?`,
|
|
35
|
+
ORDER BY ma.confidence DESC LIMIT ? OFFSET ?`,u=`
|
|
36
36
|
SELECT COUNT(*) as c FROM memory_artifacts ma
|
|
37
37
|
JOIN memory_artifacts_fts fts ON fts.rowid = ma.id
|
|
38
38
|
WHERE memory_artifacts_fts MATCH ? AND ma.kind = ?
|
|
39
|
-
AND ma.supersedes_id IS NULL`,
|
|
39
|
+
AND ma.supersedes_id IS NULL`,d=[f,s,n,l],c=[f,s]):(i=`
|
|
40
40
|
SELECT ma.*, p.name AS project_name
|
|
41
41
|
FROM memory_artifacts ma
|
|
42
42
|
JOIN memory_artifacts_fts fts ON fts.rowid = ma.id
|
|
43
43
|
LEFT JOIN projects p ON ma.project_id = p.id
|
|
44
44
|
WHERE memory_artifacts_fts MATCH ? AND ma.supersedes_id IS NULL
|
|
45
|
-
ORDER BY ma.confidence DESC LIMIT ? OFFSET ?`,
|
|
45
|
+
ORDER BY ma.confidence DESC LIMIT ? OFFSET ?`,u=`
|
|
46
46
|
SELECT COUNT(*) as c FROM memory_artifacts ma
|
|
47
47
|
JOIN memory_artifacts_fts fts ON fts.rowid = ma.id
|
|
48
|
-
WHERE memory_artifacts_fts MATCH ? AND ma.supersedes_id IS NULL`,
|
|
48
|
+
WHERE memory_artifacts_fts MATCH ? AND ma.supersedes_id IS NULL`,d=[f,n,l],c=[f])}else s?(i=`
|
|
49
49
|
SELECT ma.*, p.name AS project_name
|
|
50
50
|
FROM memory_artifacts ma
|
|
51
51
|
LEFT JOIN projects p ON ma.project_id = p.id
|
|
52
52
|
WHERE ma.kind = ? AND ma.supersedes_id IS NULL
|
|
53
|
-
ORDER BY ma.confidence DESC LIMIT ? OFFSET ?`,
|
|
53
|
+
ORDER BY ma.confidence DESC LIMIT ? OFFSET ?`,u="SELECT COUNT(*) as c FROM memory_artifacts WHERE kind = ? AND supersedes_id IS NULL",d=[s,n,l],c=[s]):(i=`
|
|
54
54
|
SELECT ma.*, p.name AS project_name
|
|
55
55
|
FROM memory_artifacts ma
|
|
56
56
|
LEFT JOIN projects p ON ma.project_id = p.id
|
|
57
57
|
WHERE ma.supersedes_id IS NULL
|
|
58
|
-
ORDER BY ma.confidence DESC LIMIT ? OFFSET ?`,
|
|
58
|
+
ORDER BY ma.confidence DESC LIMIT ? OFFSET ?`,u="SELECT COUNT(*) as c FROM memory_artifacts WHERE supersedes_id IS NULL",d=[n,l],c=[]);const m=t.prepare(i).all(...d),p=t.prepare(u).get(...c).c;return{items:m,total:p,page:r,limit:n}},"GET /ui/quests":()=>{const t=a().getDatabase().prepare(`
|
|
59
59
|
SELECT q.id, q.title, q.status, q.priority, p.name AS project_name
|
|
60
60
|
FROM quests q
|
|
61
61
|
LEFT JOIN projects p ON q.project_id = p.id
|
|
62
62
|
ORDER BY q.created_at DESC
|
|
63
|
-
`).all(),r={pending:[],in_progress:[],completed:[],abandoned:[]};for(const n of t)r[n.status]&&r[n.status].push(n);return r},"GET /ui/warroom":()=>{const e=a().getDatabase(),t=(c,...
|
|
63
|
+
`).all(),r={pending:[],in_progress:[],completed:[],abandoned:[]};for(const n of t)r[n.status]&&r[n.status].push(n);return r},"GET /ui/warroom":()=>{const e=a().getDatabase(),t=(c,...m)=>{try{const p=e.prepare(c).get(...m);return p?Object.values(p)[0]??0:0}catch{return 0}},r=(c,...m)=>{try{return e.prepare(c).all(...m)}catch{return[]}},n=F(!1).fleetGrove,o=(()=>{try{return e.prepare("SELECT id FROM projects WHERE name = ? LIMIT 1").get(n)}catch{return}})()?.id??-1,l=r("SELECT agent_id, agent_kind, last_heartbeat, ttl_seconds, role FROM agent_presence ORDER BY last_heartbeat DESC LIMIT 24").map(c=>({agent:c.agent_id,kind:c.agent_kind,role:c.role,last:c.last_heartbeat,alive:(()=>{try{const m=(Date.now()-new Date(c.last_heartbeat.replace(" ","T")+"Z").getTime())/1e3;return m>=0&&m<(c.ttl_seconds||300)}catch{return!1}})()})),i={findings:t("SELECT COUNT(*) n FROM quests WHERE project_id = ? AND status = ?",o,"pending")+t("SELECT COUNT(*) n FROM failure_patterns WHERE project_id = ? AND resolved = 0",o),claimed:t("SELECT COUNT(*) n FROM quests WHERE project_id = ? AND agent_id IS NOT NULL AND status IN ('pending','in_progress')",o),fixed:t("SELECT COUNT(*) n FROM quests WHERE project_id = ? AND status = 'completed'",o)+t("SELECT COUNT(*) n FROM memory_artifacts WHERE project_id = ? AND needs_review = 0 AND tags LIKE '%receipt%'",o),verified:t("SELECT COUNT(*) n FROM memory_artifacts WHERE project_id = ? AND needs_review = 0 AND tags LIKE '%verdict%'",o)},u=[];for(const c of r("SELECT id, title, status, agent_id, COALESCE(updated_at, created_at) AS ts, COALESCE(description, '') AS description FROM quests WHERE project_id = ?",o))u.push({type:"request",id:c.id,title:c.title,status:c.status,agent:c.agent_id,ts:c.ts,detail:String(c.description).slice(0,240)});for(const c of r("SELECT id, COALESCE(problem,'') AS problem, COALESCE(validated_fix,'') AS validated_fix, COALESCE(tags,'') AS tags, created_at FROM memory_artifacts WHERE project_id = ? AND needs_review = 0 AND tags LIKE '%warroom%'",o)){const m=String(c.tags).includes("verdict")?"verdict":String(c.tags).includes("receipt")?"receipt":"note";u.push({type:m,id:c.id,title:String(c.problem).slice(0,120),status:"",agent:null,ts:c.created_at,detail:String(c.validated_fix).slice(0,240)})}for(const c of r("SELECT id, scope, target, COALESCE(description,'') AS description, last_seen, resolved FROM failure_patterns WHERE project_id = ?",o))u.push({type:"finding",id:c.id,title:`[${c.scope}] ${c.target}`,status:c.resolved?"resolved":"open",agent:null,ts:c.last_seen,detail:String(c.description).slice(0,240)});u.sort((c,m)=>String(m.ts).localeCompare(String(c.ts)));const d={failure_blocks:t("SELECT COUNT(*) n FROM failure_blocks"),tokens_saved:t("SELECT COALESCE(SUM(estimated_tokens),0) n FROM token_savings_log"),rows_shared:t("SELECT COUNT(*) n FROM memory_artifacts WHERE project_id = ? AND is_shared = 1",o)+t("SELECT COUNT(*) n FROM quests WHERE project_id = ? AND is_shared = 1",o)};return{grove:n,found:o!==-1,presence:l,loop:i,metrics:d,feed:u.slice(0,40)}},"GET /ui/truths":e=>{const t=a().getDatabase(),r=Math.max(1,parseInt(String(e.page||"1"),10)),n=Math.min(100,Math.max(1,parseInt(String(e.limit||"20"),10))),s=(r-1)*n,o=t.prepare(`
|
|
64
64
|
SELECT gt.*, p.name AS project_name
|
|
65
65
|
FROM ground_truths gt
|
|
66
66
|
LEFT JOIN projects p ON gt.project_id = p.id
|
|
67
67
|
WHERE gt.is_current = 1
|
|
68
68
|
ORDER BY gt.updated_at DESC LIMIT ? OFFSET ?
|
|
69
|
-
`).all(n,s),
|
|
69
|
+
`).all(n,s),l=t.prepare("SELECT COUNT(*) as c FROM ground_truths WHERE is_current = 1").get().c;return{items:o.map(u=>({...u,staleness:Ne(u)})),total:l,page:r,limit:n}},"GET /ui/review":()=>({items:a().getDatabase().prepare(`
|
|
70
70
|
SELECT ma.*, p.name AS project_name
|
|
71
71
|
FROM memory_artifacts ma
|
|
72
72
|
LEFT JOIN projects p ON ma.project_id = p.id
|
|
73
73
|
WHERE ma.needs_review = 1
|
|
74
74
|
ORDER BY ma.created_at DESC
|
|
75
|
-
`).all()}),"GET /ui/account":()=>{const e=
|
|
75
|
+
`).all()}),"GET /ui/account":()=>{const e=B(a().getDatabasePath());try{const t=y(e,"license.json");if(T(t)){const r=JSON.parse(L(t,"utf-8")),n=J(r);return{account:r.license&&r.license.issued_to||"unknown",tier:n.valid?n.tier:"free",valid:!!n.valid,expires:n.expiresAt||null,readonly:O}}}catch{}try{const t=y(e,"cloud.json");if(T(t))return{account:JSON.parse(L(t,"utf-8")).email||"Local",tier:"free",valid:!1,expires:null,readonly:O}}catch{}return{account:"Local",tier:"free",valid:!1,expires:null,readonly:O}},"GET /ui/impact":()=>{const e=a().getDatabase(),t=r=>{try{return e.prepare(r).get()?.n||0}catch{return 0}};return{failures_blocked:t("SELECT COALESCE(SUM(occurrences),0) AS n FROM failure_patterns"),tokens_saved:t("SELECT COALESCE(SUM(estimated_tokens),0) AS n FROM token_savings_log"),memories:t("SELECT COUNT(*) AS n FROM memory_artifacts WHERE supersedes_id IS NULL"),memories_week:t("SELECT COUNT(*) AS n FROM memory_artifacts WHERE created_at >= datetime('now','-7 days')"),truths:t("SELECT COUNT(*) AS n FROM ground_truths WHERE is_current = 1"),sessions:t("SELECT COUNT(*) AS n FROM sessions"),quests_completed:t("SELECT COUNT(*) AS n FROM quests WHERE status = 'completed'"),skills:t("SELECT COUNT(*) AS n FROM skills"),projects:t("SELECT COUNT(*) AS n FROM projects")}},"GET /ui/memory":e=>{const t=a().getDatabase(),r=parseInt(String(e&&e.id||"0"),10);if(!r)return{item:null};try{return{item:t.prepare(`SELECT ma.*, p.name AS project_name
|
|
76
76
|
FROM memory_artifacts ma LEFT JOIN projects p ON ma.project_id = p.id
|
|
77
|
-
WHERE ma.id = ?`).get(r)||null}}catch{return{item:null}}},"GET /ui/recall":async e=>{const t=e.search?String(e.search):e.q?String(e.q):"";if(!t)return{items:[],total:0};const r=_(e.limit,6,25),n=e.kind?String(e.kind):void 0,o=(await
|
|
78
|
-
`),tokens:i,items:
|
|
79
|
-
FROM skills ORDER BY category COLLATE NOCASE, name COLLATE NOCASE`).all();return{items:t,total:t.length}}catch{return{items:[],total:0}}},"GET /ui/homes":()=>{const e=
|
|
77
|
+
WHERE ma.id = ?`).get(r)||null}}catch{return{item:null}}},"GET /ui/recall":async e=>{const t=e.search?String(e.search):e.q?String(e.q):"";if(!t)return{items:[],total:0};const r=_(e.limit,6,25),n=e.kind?String(e.kind):void 0,o=(await g().recallHybridGlobal(t,{limit:r,kind:n})).map(l=>({...l.artifact,relevance:Math.round(l.relevance_score*1e3)/1e3,match_type:l.match_type}));return{items:o,total:o.length}},"GET /ui/context":async e=>{const t=e.search?String(e.search):e.q?String(e.q):"";if(!t)return{context:"",items:[],total:0,tokens:0};const r=_(e.limit,10,25),n=_(e.budget,900,2400),s=await g().recallHybridGlobal(t,{limit:r}),o=[],l=[];let i=0;for(const u of s){const d=u.artifact,c=String(d.problem??d.title??d.summary??d.key??d.kind??"").trim(),m=String(d.validated_fix??d.content??d.body??d.value??d.problem??"").replace(/\s+/g," ").trim(),p=`- ${c}${m?": "+m.slice(0,320):""}`,f=Math.ceil(p.length/4);i+f<=n?(o.push(p),i+=f):o.push(`- ${c.slice(0,64)} \u2026 (recall for detail)`),l.push({...d,relevance:Math.round(u.relevance_score*1e3)/1e3,match_type:u.match_type})}return{context:o.join(`
|
|
78
|
+
`),tokens:i,items:l,total:l.length}},"GET /ui/skills":()=>{const e=a().getDatabase();try{const t=e.prepare(`SELECT name, description, category, tier, usage_count, is_active
|
|
79
|
+
FROM skills ORDER BY category COLLATE NOCASE, name COLLATE NOCASE`).all();return{items:t,total:t.length}}catch{return{items:[],total:0}}},"GET /ui/homes":()=>{const e=z();let t=a().getDatabasePath();try{t=Y(t)}catch{}return{homes:e.map(r=>({...r,active:r.dbPath===t}))}},"POST /ui/switch":e=>{const t=String(e&&e.path||""),r=z().find(n=>n.dbPath===t);if(!r)return{ok:!1,error:"unknown home"};try{return Xe(new x(r.dbPath)),{ok:!0,account:r.account,tier:r.tier}}catch(n){return{ok:!1,error:n instanceof Error?n.message:String(n)}}}};function tt(e,t,r){if(!a().liveMemoryEnabled()){E(t,e,{e:"live memory disabled",disabled:1},503);return}const n=G(r.project??r.p);if(!n){E(t,e,{e:"not found"},404);return}const s=e.socket.remoteAddress||"unknown";if(H>=Je){E(t,e,{e:"too many concurrent streams",retry_after:5},503);return}if((R.get(s)??0)>=Ke){E(t,e,{e:"too many concurrent streams from this client",retry_after:5},503);return}H++,R.set(s,(R.get(s)??0)+1);let o=V(e.headers["last-event-id"],r.since);const i=!(s==="127.0.0.1"||s==="::1"||s==="::ffff:127.0.0.1")||r.shared==="1"||r.shared==="true";t.writeHead(200,{...P(e),"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),t.write(`retry: 3000
|
|
80
80
|
|
|
81
|
-
`);let
|
|
81
|
+
`),W.add(t);let u,d,c=!1;const m=()=>{if(c)return;c=!0,W.delete(t),u&&clearInterval(u),d&&clearInterval(d),H--;const f=(R.get(s)??1)-1;f<=0?R.delete(s):R.set(s,f)},p=()=>{if(t.writableEnded){m();return}try{const f=i?a().eventsForPush(n.id,o,200):a().eventsSince(n.id,o,200);for(const C of f)o=C.cursor,t.write(ke(C))}catch{}};p(),u=setInterval(p,1e3),d=setInterval(()=>{try{t.write(we)}catch{}},25e3),e.on("close",m),t.on("close",m),t.on("error",m)}const S=re.createServer(async(e,t)=>{if(N){E(t,e,{e:"shutting down"},503);return}const r=ce(e.method||"GET",e.headers,ie(e));if(r){E(t,e,{e:r.e},r.status);return}if(!oe(e,t).error)try{const s=new URL(e.url||"/",`http://localhost:${j}`);if(O&&Pe(e.method||"GET",s.pathname)){E(t,e,{e:"read-only mode",readonly:1},403);return}let o;try{o=await et(e)}catch(p){if(p.message==="Invalid JSON"){E(t,e,{e:"Invalid JSON body"},400);return}throw p}if(s.searchParams.forEach((p,f)=>o[f]=p),e.method==="GET"&&s.pathname==="/ui"){{const p=F(!1);let f=!1;try{f=!!a().getDatabase().prepare("SELECT 1 FROM projects WHERE name = ? LIMIT 1").get(p.fleetGrove)}catch{}Ze(t,e,ye(F(f),ae()))}return}if(e.method==="GET"&&s.pathname==="/events/stream"){tt(e,t,o);return}const l=s.pathname.match(/^\/ui\/review\/(\d+)\/(approve|reject)$/);if(e.method==="POST"&&l){const p=parseInt(l[1],10);l[2]==="approve"?g().approve(p):g().reject(p),E(t,e,{ok:!0});return}const i=`${e.method} ${s.pathname}`,u=Z[i];if(!u){if(s.pathname==="/"){E(t,e,{wyrm:Se(),ui:"/ui",auth:w().requireAuth?"required":"disabled",tip:"GET /c for quick context"});return}E(t,e,{e:"not found"},404);return}const d=Fe({header:e.headers["wyrm-actor"],transport:"http"}),{result:c,ms:m}=$(()=>He(d,()=>u(o)));t.setHeader("X-Time-Ms",String(m)),c instanceof Promise?c.then(p=>E(t,e,p)).catch(p=>{if(X(t,e,p))return;const f=K(p);if(f!==null){const C=Q("http",f);t.setHeader("Retry-After",String(Math.ceil(C.error.retry_after_ms/1e3))),E(t,e,C,503);return}k.error("Fast API request failed",{path:e.url,error:p.message}),E(t,e,{e:"Internal server error"},500)}):E(t,e,c)}catch(s){if(X(t,e,s))return;const o=K(s);if(o!==null){const l=Q("http",o);t.setHeader("Retry-After",String(Math.ceil(l.error.retry_after_ms/1e3))),E(t,e,l,503);return}k.error("Fast API request failed",{path:e.url,error:s.message}),E(t,e,{e:"Internal server error"},500)}});S.once("listening",()=>{be(()=>a(),process.env,{vectors:()=>g().getVectorStore()??null})});const rt=4e3;let ee=!1;const U=()=>{if(!ee){ee=!0;try{v?.close()}catch{}process.exit(0)}},te=()=>{if(N){S.closeAllConnections(),U();return}N=!0,S.close(()=>U());for(const e of W)try{e.end()}catch{}S.closeIdleConnections(),setInterval(()=>S.closeIdleConnections(),100).unref(),setTimeout(()=>{S.closeAllConnections(),U()},rt).unref()};process.on("SIGINT",te),process.on("SIGTERM",te);import{fileURLToPath as nt}from"url";const st=nt(import.meta.url);if(process.argv[1]===st){ge().key&&!/^(0|false|no|off)$/i.test(process.env.WYRM_LICENSE_REFRESH??"")&&ze();const e=process.env.WYRM_BIND_HOST||"127.0.0.1";S.listen(j,e,()=>{const t=Ye(e,j);k.info("Wyrm Fast API started",{port:j,host:e,ui:t}),console.log(`\u{F115D} Wyrm Fast API on ${e}:${j}`),console.log(` Dashboard: ${t}`),console.log(` Auth: ${w().requireAuth?"required":"disabled"}`),O&&console.log(" Read-only: writes + off-box egress blocked (safe to expose)"),e!=="127.0.0.1"&&e!=="::1"&&e!=="localhost"&&(k.warn("Wyrm Fast API bound to a NON-loopback host, reachable beyond localhost; ensure auth is required",{host:e}),console.log(` \u26A0 bound to ${e}: reachable beyond localhost; make sure auth is required`),O||console.log(" \u26A0 not in read-only mode; set WYRM_UI_READONLY=1 for a public bind"))})}S.on("listening",()=>We("http"));export{rt as SHUTDOWN_GRACE_MS,Ye as dashboardUrl,ze as primeLicenseRevocations,$e as resolveHttpPort,S as server};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{realpathSync as f}from"fs";import{basename as u,resolve as E}from"path";import{SecurityError as h,validateProjectPath as m}from"./security.js";const d=50,S=500,L=1e9,l=200,P=["limit","offset","q","path"];function s(e){return{i:e.id,n:e.name,p:e.path,s:e.stack??null}}function N(e){if(!P.some(a=>e[a]!==void 0&&e[a]!==null))return null;const t=Number.parseInt(String(e.limit??""),10),r=Number.parseInt(String(e.offset??""),10),i=e.q==null?"":String(e.q).trim(),n=e.path==null?"":String(e.path).trim();return{limit:Number.isFinite(t)&&t>=1?Math.min(t,S):d,offset:Number.isFinite(r)&&r>0?Math.min(r,L):0,q:i?i.slice(0,l):null,path:n&&!n.includes("\0")?E(n):null}}function A(e){return e.replace(/[\\%_]/g,t=>`\\${t}`)}function _(e,t){const r=t.q===null?null:`%${A(t.q)}%`,i=[t.path,t.path,r,r,r],n=e.getDatabase(),a=n.prepare(`SELECT COUNT(*) AS c FROM projects
|
|
2
|
+
WHERE (? IS NULL OR path = ?) AND (? IS NULL OR name LIKE ? ESCAPE '\\' OR path LIKE ? ESCAPE '\\')`).get(...i).c,c=n.prepare(`SELECT id, name, path, stack FROM projects
|
|
3
|
+
WHERE (? IS NULL OR path = ?) AND (? IS NULL OR name LIKE ? ESCAPE '\\' OR path LIKE ? ESCAPE '\\')
|
|
4
|
+
ORDER BY updated_at DESC, id DESC LIMIT ? OFFSET ?`).all(...i,t.limit,t.offset),o=t.offset+c.length,p=c.length>0&&o<a;return{items:c.map(s),total:a,limit:t.limit,offset:t.offset,more:p?1:0,next:p?o:null}}function C(e,t){const r=typeof t.path=="string"?t.path.trim():"";if(!r)return{e:"path required"};if(r.includes("\0"))return{e:"path not allowed"};let i;if(t.name!==void 0&&t.name!==null&&t.name!==""){const o=typeof t.name=="string"?t.name.trim():"";if(!o||o.length>l)return{e:`name must be 1 to ${l} characters`};if(/[\u0000-\u001f\u007f]/.test(o))return{e:"name must not contain control characters"};i=o}let n;try{n=m(r),m(f(n))}catch(o){return o instanceof h&&o.code==="INVALID_DIRECTORY"?{e:"not a directory"}:{e:"path not allowed"}}const a=e.getProject(n);if(a)return{...s(a),created:0};const c=e.registerProject(i??u(n),n);return{...s(c),created:1}}export{d as PROJECT_PAGE_DEFAULT,S as PROJECT_PAGE_MAX,s as compactProject,A as escapeLike,_ as listProjectsPage,N as parseProjectListQuery,C as registerProjectAt};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const u=Object.freeze({enabled:!0,requests:100,windowMs:6e4,loopbackRequests:6e3,authFailures:20,loopbackAuthFailures:300});function i(e,t){const s=typeof e=="number"?e:typeof e=="string"&&e.trim()!==""?Number(e):Number.NaN;return Number.isFinite(s)&&s>=0?Math.floor(s):t}function l(e){const t=e&&typeof e=="object"&&!Array.isArray(e)?e:{},s=i(t.windowMs,u.windowMs);return{enabled:typeof t.enabled=="boolean"?t.enabled:u.enabled,requests:i(t.requests,u.requests),windowMs:s>=1e3?s:u.windowMs,loopbackRequests:i(t.loopbackRequests,u.loopbackRequests),authFailures:i(t.authFailures,u.authFailures),loopbackAuthFailures:i(t.loopbackAuthFailures,u.loopbackAuthFailures)}}function c(e){return e==="127.0.0.1"||e==="::1"||e==="::ffff:127.0.0.1"}function h(e,t){const s=c(t);return e?.kind==="token"?`token:${e.tokenHash.slice(0,16)}:${s?"loopback":"remote"}`:e?.kind==="ui"||e?.kind==="dev"?e.kind:`${e?"open":"public"}:${t||"unknown"}`}function b(e,t){return c(t)?e.loopbackRequests:e.requests}function f(e,t){return c(t)?e.loopbackAuthFailures:e.authFailures}class k{maxEntries;entries=new Map;constructor(t=1e4){this.maxEntries=t}get size(){return this.entries.size}hit(t,s,n,r){const o=this.live(t,n,r);return o.count++,{allowed:s===0||o.count<=s,limit:s,remaining:s===0?Number.POSITIVE_INFINITY:Math.max(0,s-o.count),resetAt:o.resetAt}}peek(t,s,n,r){const o=this.entries.get(t),a=o&&o.resetAt>r?o:{count:0,resetAt:r+n};return{allowed:s===0||a.count<s,limit:s,remaining:s===0?Number.POSITIVE_INFINITY:Math.max(0,s-a.count),resetAt:a.resetAt}}live(t,s,n){let r=this.entries.get(t);return(!r||r.resetAt<=n)&&(this.entries.delete(t),this.makeRoom(n),r={count:0,resetAt:n+s},this.entries.set(t,r)),r}makeRoom(t){if(!(this.entries.size<this.maxEntries)){for(const[s,n]of this.entries)n.resetAt<=t&&this.entries.delete(s);for(;this.entries.size>=this.maxEntries;){const s=this.entries.keys().next().value;if(s===void 0)break;this.entries.delete(s)}}}}export{u as DEFAULT_RATE_LIMIT,k as WindowCounter,h as budgetKey,f as failureLimit,c as isLoopbackAddress,l as normalizeRateLimit,b as requestLimit};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import{NON_EMBED_MODELS as O}from"./vectors.js";import{getMeta as m}from"./events.js";import{RETIRED_NIM_EMBED_MODELS as v}from"./providers/embedding-provider.js";import{QUEUE_MAX_RETRIES as f}from"./indexer.js";const K="idx_vectors_model_type_project",L=["artifact","quest","session"],A=200;function I(e){return`${e.problem}${e.validated_fix?" "+e.validated_fix:""}`.slice(0,2e3)}const _={artifact:{from:"memory_artifacts r",where:"r.needs_review = 0 AND r.supersedes_id IS NULL"},quest:{from:"quests r",where:"(COALESCE(r.title, '') <> '' OR COALESCE(r.description, '') <> '')"},session:{from:"sessions r",where:"(COALESCE(r.objectives, '') <> '' OR COALESCE(r.completed, '') <> '' OR COALESCE(r.notes, '') <> '' OR COALESCE(r.summary, '') <> '')"}};function D(e,n,r){const o=_[e];return`SELECT ${n} FROM ${o.from}
|
|
2
|
+
WHERE ${o.where}${r?" AND r.project_id = @project":""}
|
|
3
|
+
AND NOT EXISTS (SELECT 1 FROM vectors v
|
|
4
|
+
WHERE v.content_type = '${e}' AND v.content_id = r.id AND v.model = @model)`}function F(e,n,r={}){const o={artifact:0,quest:0,session:0,total:0},t=r.projectId!=null;for(const s of L){const a={model:n};t&&(a.project=r.projectId);const E=e.prepare(D(s,"COUNT(*) AS n",t)).get(a).n;o[s]=E,o.total+=E}return o}function g(e,n,r={}){const o=[],t=r.projectId!=null,s=r.limit!=null&&r.limit>0;for(const a of L){const E=s?r.limit-o.length:-1;if(E===0)break;const u={model:n,limit:E};t&&(u.project=r.projectId);const i=`${D(a,`'${a}' AS content_type, r.id AS content_id, r.project_id AS project_id`,t)}
|
|
5
|
+
ORDER BY r.id DESC LIMIT @limit`;o.push(...e.prepare(i).all(u))}return o}function b(e,n,r){let o=null;if(n==="artifact"){const t=e.prepare("SELECT problem, validated_fix, needs_review, supersedes_id FROM memory_artifacts WHERE id = ?").get(r);t&&t.needs_review===0&&t.supersedes_id==null&&(o=I(t))}else if(n==="quest"){const t=e.prepare("SELECT title, description FROM quests WHERE id = ?").get(r);t&&(o=[t.title,t.description].filter(Boolean).join(" "))}else{const t=e.prepare("SELECT objectives, completed, notes, summary FROM sessions WHERE id = ?").get(r);t&&(o=[t.objectives,t.completed,t.notes,t.summary].filter(Boolean).join(" "))}return!o||o.startsWith("ENCRYPTED:")?null:o}async function h(e,n,r={}){const o=n.getProvider().model,t=F(e,o,{projectId:r.projectId}),s={model:o,dryRun:r.dryRun===!0,eligible:t.total,byType:{artifact:t.artifact,quest:t.quest,session:t.session},attempted:0,embedded:0,failed:0,aborted:!1};if(s.dryRun||t.total===0)return s;const a=r.maxConsecutiveFailures??3;let E=0,u=null;try{u=e.prepare("DELETE FROM indexing_queue WHERE content_type = ? AND content_id = ? AND retry_count >= ?")}catch{u=null}for(const i of g(e,o,{limit:r.limit,projectId:r.projectId})){const c=b(e,i.content_type,i.content_id);if(c===null)continue;s.attempted++;let d=null;try{d=await n.addVector(c,i.content_type,i.content_id,i.project_id)}catch{d=null}if(d){s.embedded++,E=0;try{u?.run(i.content_type,i.content_id,f)}catch{}continue}if(s.failed++,++E>=a){s.aborted=!0;break}}return s}function H(e,n){const r=n.getProvider();return r.name==="none"?!1:W(e,r.model)!==null}function x(e){const n=m(e,"embed_last_ok_at"),r=m(e,"embed_last_error_at");return!!r&&(!n||Date.parse(r)>Date.parse(n))}function W(e,n){return!n||O.has(n)||v[n]||x(e)?null:n}async function Y(e,n,r=process.env){const o=Number(r.WYRM_BACKFILL_LIMIT??A),t=Number.isFinite(o)&&o>=0?Math.floor(o):A;return t===0||!H(e,n)?null:h(e,n,{limit:t})}const C=[["artifact","memory_artifacts"],["session","sessions"],["quest","quests"],["note","data_lake"]],S="(v.content_type = 'context')",N=`(v.content_type = 'context'
|
|
6
|
+
AND EXISTS (SELECT 1 FROM quests p WHERE p.id = v.content_id)
|
|
7
|
+
AND NOT EXISTS (SELECT 1 FROM vectors w WHERE w.content_type = 'quest' AND w.content_id = v.content_id AND w.model = v.model))`,q=`(${C.map(([e,n])=>`(v.content_type = '${e}' AND NOT EXISTS (SELECT 1 FROM ${n} p WHERE p.id = v.content_id))`).join(" OR ")})`,$=`(v.content_type = 'artifact'
|
|
8
|
+
AND EXISTS (SELECT 1 FROM memory_artifacts p WHERE p.id = v.content_id AND p.supersedes_id IS NOT NULL))`,j=`(${C.map(([e,n])=>`(v.content_type = '${e}' AND EXISTS (SELECT 1 FROM ${n} p WHERE p.id = v.content_id${e==="artifact"?" AND p.supersedes_id IS NULL":""}))`).join(" OR ")})`,U=`(v.model <> @active
|
|
9
|
+
AND v.model NOT IN (SELECT value FROM json_each(@protected))
|
|
10
|
+
AND ${j}
|
|
11
|
+
AND EXISTS (SELECT 1 FROM vectors w WHERE w.content_type = v.content_type AND w.content_id = v.content_id AND w.model = @active))`;function w(e,n={}){const r=n.dryRun===!0,o=n.activeModel&&!O.has(n.activeModel)?n.activeModel:null,t={dryRun:r,activeModel:o,orphans:0,superseded:0,mislabelled:0,relabelled:0,oldModel:0,bytes:0,deleted:0};if(!e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'vectors'").get())return t;const a={active:o??"",protected:JSON.stringify([...n.protectedModels??[]])},E=(c,d={})=>e.prepare(`SELECT COUNT(*) AS n, COALESCE(SUM(length(v.embedding)), 0) AS b FROM vectors v WHERE ${c}`).get(d),u=(c,d={})=>e.prepare(`DELETE FROM vectors WHERE id IN (SELECT v.id FROM vectors v WHERE ${c})`).run(d).changes,i=[{key:"orphans",pred:q},{key:"superseded",pred:$}];if(o&&i.push({key:"oldModel",pred:U,params:a}),r){const c=E(N).n,d=E(`${S} AND NOT ${N}`);t.relabelled=c,t.mislabelled=c+d.n,t.bytes+=d.b;for(const l of i){const p=E(l.pred,l.params);t[l.key]=p.n,t.bytes+=p.b}return t}return e.transaction(()=>{t.relabelled=e.prepare(`UPDATE OR IGNORE vectors SET content_type = 'quest' WHERE id IN (SELECT v.id FROM vectors v WHERE ${N})`).run().changes;const c=E(S);t.bytes+=c.b;const d=u(S);t.mislabelled=t.relabelled+d,t.deleted+=d;for(const l of i){t.bytes+=E(l.pred,l.params).b;const p=u(l.pred,l.params);t[l.key]=p,t.deleted+=p}})(),t}const R=`(
|
|
12
|
+
(q.content_type = 'artifact' AND NOT EXISTS (SELECT 1 FROM memory_artifacts p WHERE p.id = q.content_id))
|
|
13
|
+
OR (q.content_type IN ('quest', 'context') AND NOT EXISTS (SELECT 1 FROM quests p WHERE p.id = q.content_id))
|
|
14
|
+
OR (q.content_type = 'session' AND NOT EXISTS (SELECT 1 FROM sessions p WHERE p.id = q.content_id))
|
|
15
|
+
OR (q.content_type = 'note' AND NOT EXISTS (SELECT 1 FROM data_lake p WHERE p.id = q.content_id)))`,T=`(NOT ${R} AND (
|
|
16
|
+
q.content_type = 'context'
|
|
17
|
+
OR (q.content_type = 'artifact' AND EXISTS (SELECT 1 FROM memory_artifacts r WHERE r.id = q.content_id AND NOT (${_.artifact.where})))
|
|
18
|
+
OR (q.content_type = 'quest' AND EXISTS (SELECT 1 FROM quests r WHERE r.id = q.content_id AND NOT ${_.quest.where}))
|
|
19
|
+
OR (q.content_type = 'session' AND EXISTS (SELECT 1 FROM sessions r WHERE r.id = q.content_id AND NOT ${_.session.where}))))`,M=`(NOT ${R} AND NOT ${T}
|
|
20
|
+
AND EXISTS (SELECT 1 FROM vectors v WHERE v.content_type = q.content_type AND v.content_id = q.content_id AND v.model = @active))`,X=`
|
|
21
|
+
SELECT COUNT(*) AS stuck,
|
|
22
|
+
COALESCE(SUM(CASE WHEN ${R} THEN 1 ELSE 0 END), 0) AS gone,
|
|
23
|
+
COALESCE(SUM(CASE WHEN ${T} THEN 1 ELSE 0 END), 0) AS notNeeded,
|
|
24
|
+
COALESCE(SUM(CASE WHEN ${M} THEN 1 ELSE 0 END), 0) AS embedded
|
|
25
|
+
FROM indexing_queue q WHERE q.retry_count >= @max`,k=`
|
|
26
|
+
DELETE FROM indexing_queue WHERE id IN (
|
|
27
|
+
SELECT q.id FROM indexing_queue q
|
|
28
|
+
WHERE q.retry_count >= @max AND (${R} OR ${T} OR ${M}))`;function G(e,n={}){const r=n.dryRun===!0,o={active:n.activeModel??"",max:n.maxRetries??f};if(!e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'indexing_queue'").get())return{stuck:0,gone:0,notNeeded:0,embedded:0,cleared:0,remaining:0,dryRun:r};const s=e.prepare(X).get(o),a=s.gone+s.notNeeded+s.embedded,E=r||a===0?0:e.prepare(k).run(o).changes;return{stuck:s.stuck,gone:s.gone,notNeeded:s.notNeeded,embedded:s.embedded,cleared:E,remaining:s.stuck-a,dryRun:r}}const y=90;function J(e=process.env){const n=Number(e.WYRM_RUN_RETAIN_DAYS??y);return Number.isFinite(n)&&n>=0?Math.floor(n):y}function z(e,n){const r=n.dryRun===!0,o=e.prepare(`
|
|
29
|
+
SELECT r.run_id FROM runs r
|
|
30
|
+
WHERE r.status IN ('completed', 'failed', 'abandoned')
|
|
31
|
+
AND r.updated_at < datetime('now', ?)
|
|
32
|
+
AND NOT EXISTS (SELECT 1 FROM failure_patterns fp
|
|
33
|
+
WHERE fp.run_id = r.run_id AND fp.resolved = 0 AND fp.quarantine_scope = 'run')
|
|
34
|
+
AND NOT EXISTS (SELECT 1 FROM runs c WHERE c.parent_run_id = r.run_id AND c.status = 'running')
|
|
35
|
+
`).all(`-${Math.max(0,n.olderThanDays)} days`).map(a=>a.run_id),t=JSON.stringify(o),s=e.prepare("SELECT COUNT(*) AS n FROM run_agents WHERE run_id IN (SELECT value FROM json_each(?))").get(t).n;return r||o.length===0?{runs:o.length,runAgents:s,dryRun:r}:(e.transaction(()=>{e.prepare("DELETE FROM run_agents WHERE run_id IN (SELECT value FROM json_each(?))").run(t),e.prepare("DELETE FROM runs WHERE run_id IN (SELECT value FROM json_each(?))").run(t)})(),{runs:o.length,runAgents:s,dryRun:r})}function Z(e,n={}){const r=n.dryRun===!0,o=e.prepare(`
|
|
36
|
+
SELECT r.id FROM relationships r
|
|
37
|
+
WHERE NOT EXISTS (SELECT 1 FROM entities e WHERE e.id = r.source_entity_id)
|
|
38
|
+
OR NOT EXISTS (SELECT 1 FROM entities e WHERE e.id = r.target_entity_id)
|
|
39
|
+
OR (r.extraction_method = 'auto-extract'
|
|
40
|
+
AND r.weight <= 0.3000001
|
|
41
|
+
AND r.source_memory LIKE 'mem:%'
|
|
42
|
+
AND NOT EXISTS (SELECT 1 FROM memory_artifacts a
|
|
43
|
+
WHERE a.id = CAST(substr(r.source_memory, 5) AS INTEGER) AND a.supersedes_id IS NULL))
|
|
44
|
+
`).all().map(i=>i.id),t=JSON.stringify(o),s=e.prepare(`
|
|
45
|
+
SELECT e.id, e.project_id, e.name FROM entities e
|
|
46
|
+
WHERE e.created_by = 'auto-extract'
|
|
47
|
+
AND NOT EXISTS (SELECT 1 FROM entity_aliases x WHERE x.entity_id = e.id)
|
|
48
|
+
AND NOT EXISTS (SELECT 1 FROM relationships r
|
|
49
|
+
WHERE r.source_entity_id = e.id AND r.id NOT IN (SELECT value FROM json_each(@edges)))
|
|
50
|
+
AND NOT EXISTS (SELECT 1 FROM relationships r
|
|
51
|
+
WHERE r.target_entity_id = e.id AND r.id NOT IN (SELECT value FROM json_each(@edges)))
|
|
52
|
+
`).all({edges:t}),a=new Map,E=i=>{let c=a.get(i);return c||(c=e.prepare("SELECT problem, validated_fix FROM memory_artifacts WHERE project_id = ? AND needs_review = 0 AND supersedes_id IS NULL").all(i).map(d=>`${d.problem} ${d.validated_fix??""}`.toLowerCase()),a.set(i,c)),c},u=s.filter(i=>{const c=i.name.toLowerCase();return!E(i.project_id).some(d=>d.includes(c))}).map(i=>i.id);return!r&&(o.length>0||u.length>0)&&e.transaction(()=>{e.prepare("DELETE FROM relationships WHERE id IN (SELECT value FROM json_each(?))").run(t),e.prepare("DELETE FROM entities WHERE id IN (SELECT value FROM json_each(?))").run(JSON.stringify(u))})(),{relationships:o.length,entities:u.length,dryRun:r}}function ee(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}export{A as DEFAULT_BACKFILL_LIMIT,y as DEFAULT_RUN_RETAIN_DAYS,K as VECTOR_INDEX_NAME,I as artifactVectorText,b as backfillContent,h as backfillVectors,Z as compactGraph,F as countUnembedded,H as embeddingHealthy,g as findUnembedded,ee as formatBytes,Y as maybeBackfill,z as pruneEndedRuns,W as pruneReferenceModel,G as pruneStuckQueue,w as pruneVectors,J as runRetainDays};
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Server as we}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Se}from"@modelcontextprotocol/sdk/server/stdio.js";import{scheduleMaintenanceSweep as Re}from"./self-maintenance.js";import{watchForOrphaning as ve,makeShutdown as ke,trackInFlight as be,resolveDrainMs as Ee}from"./stdio-lifecycle.js";import{CallToolRequestSchema as De,GetPromptRequestSchema as Ce,ListPromptsRequestSchema as Te,ListResourcesRequestSchema as Oe,ListResourceTemplatesRequestSchema as xe,ListToolsRequestSchema as Me,ReadResourceRequestSchema as We}from"@modelcontextprotocol/sdk/types.js";import{WyrmDB as Pe,resolveDbPath as Ae}from"./database.js";import{ValidationError as V}from"./validate.js";import{validationErrorResponse as $,cacheKeyFor as
|
|
3
|
-
`).map(
|
|
2
|
+
import{Server as we}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Se}from"@modelcontextprotocol/sdk/server/stdio.js";import{scheduleMaintenanceSweep as Re}from"./self-maintenance.js";import{watchForOrphaning as ve,makeShutdown as ke,trackInFlight as be,resolveDrainMs as Ee}from"./stdio-lifecycle.js";import{CallToolRequestSchema as De,GetPromptRequestSchema as Ce,ListPromptsRequestSchema as Te,ListResourcesRequestSchema as Oe,ListResourceTemplatesRequestSchema as xe,ListToolsRequestSchema as Me,ReadResourceRequestSchema as We}from"@modelcontextprotocol/sdk/types.js";import{WyrmDB as Pe,resolveDbPath as Ae,describeStoreError as Ie}from"./database.js";import{ValidationError as V}from"./validate.js";import{validationErrorResponse as $,cacheKeyFor as Ne}from"./render.js";import{handlerRegistry as h,registryToolDefs as W,applyDeclaredOutputSchemas as Le,buildStableToolList as Ye}from"./handlers/registry.js";import{resolveActorEnvelope as J,runWithActor as z,getActor as je,runWithReadCacheKey as Fe}from"./handlers/boundary.js";import{resolveAliasCall as Be}from"./handlers/aliases.js";import{rejectUnknownArgs as Ke}from"./handlers/arg-keys.js";import{resolveShimCall as Ue,shimToolDefs as P}from"./handlers/shims.js";import{getPromptResult as Ge,wyrmPromptList as He}from"./handlers/prompts.js";import{listWyrmResources as qe,listWyrmResourceTemplates as Ve,readWyrmResource as $e,ResourceNotFoundError as Je}from"./handlers/resources.js";import{TaskStore as ze,resolveTaskGate as Qe,runLongOp as Xe}from"./tasks.js";import{registerTaskHandlers as Ze,finalizeEarly as et,unwrapOutcome as tt,applyAdminGate as rt}from"./tasks-dispatch.js";import{ReplicationManager as ot}from"./replication-daemon.js";import{WYRM_SERVER_INSTRUCTIONS as st}from"./priority-embed.js";import{WyrmSync as nt}from"./sync.js";import{cache as w,estimateTokens as A}from"./performance.js";import{readFileSync as Q,unlinkSync as at,existsSync as X}from"fs";import{join as it}from"path";import{initializeOrchestrator as ct}from"./auto-orchestrator.js";import{getCrypto as mt,initializeCrypto as lt}from"./crypto.js";import{initVectorSearch as pt}from"./vector-init.js";import{KnowledgeGraph as ut}from"./knowledge-graph.js";import{MemoryArtifacts as _t}from"./memory-artifacts.js";import{GroundTruths as ft,ReasoningScaffolds as yt}from"./intelligence.js";import{classifyCapture as ns}from"./capture.js";import{initializeLicense as dt,getLicenseInfo as gt}from"./license.js";import{refreshRevocations as Z}from"./revocations.js";import{refreshLicenseIfNeeded as ee}from"./license-refresh.js";import{activationSatisfied as ht,activationGateResult as wt}from"./activation.js";import{WyrmAnalytics as St}from"./analytics.js";import{WyrmCloudBackup as Rt}from"./cloud-backup.js";import{CloudSyncManager as vt}from"./cloud-sync.js";import{FailurePatterns as kt}from"./failure-patterns.js";import{AgentPresence as bt}from"./presence.js";import{Causality as Et}from"./causality.js";import{wireTruthAutoCascade as Dt}from"./truth-cascade.js";import{SymbolGraph as Ct}from"./symbols.js";import{HourLedger as Tt}from"./hours.js";import{ToolAnalytics as Ot}from"./tool-analytics.js";import{Rehydration as xt}from"./rehydration.js";import{AuditLog as Mt,loadAuditSignerFromEnv as Wt}from"./audit.js";import{retryableWriteCause as Pt,busyErrorResponse as At}from"./sqlite-busy.js";import{SubAgent as It}from"./sub-agent.js";import{Federation as Nt}from"./federation.js";import{Goals as Lt}from"./goals.js";import{OutboundMcpClient as Yt}from"./mcp-client.js";import{AgentLoop as jt}from"./agent-loop.js";import{makeInternalDispatch as Ft}from"./internal-dispatch.js";import{createUsageTracker as Bt}from"./usage-tracker.js";import{AgentDaemon as Kt}from"./agent-daemon.js";import{emitStartupVersionBanner as Ut}from"./version-check.js";import{resolveProfile as te,filterByProfile as re}from"./tool-profiles.js";import{annotateTools as Gt,elideDefaultAnnotations as Ht}from"./tool-annotations.js";import{applyDeprecationNotices as qt,noteDeprecatedToolInvocation as Vt,isHardCliExile as $t,cliExileRedirectResponse as Jt}from"./deprecations.js";import{goldenCapture as y}from"./golden.js";import{makeEstimator as zt}from"./token-budget.js";import{makeRunBudgetedContextBuild as Qt}from"./context-build-budgeted.js";import{assembleThread as Xt}from"./thread-assemble.js";import{getThread as Zt}from"./thread-store.js";import{renderThreadForContext as oe}from"./handlers/thread.js";import{makeRunCompanionBuddy as er}from"./buddy-runner.js";import{loadWeightsFromEnv as tr}from"./context-ranking.js";import{SessionSeen as rr}from"./session-seen.js";import{recordServed as or}from"./served-records.js";import{DesignSystem as sr}from"./design.js";import{fileURLToPath as nr}from"url";import{dirname as ar,join as se}from"path";import{readFileSync as ir,existsSync as cr}from"fs";const mr=137;let I=null;function lr(){return I||(I=new sr(r.getDatabase())),I}const pr=zt(),ur=tr();let N=null;function ne(){return N||(N=new rr(r.getDatabase())),N}const T=(()=>{try{const e=ar(nr(import.meta.url));for(const t of[se(e,"..","package.json"),se(e,"..","..","package.json")])if(cr(t)){const o=JSON.parse(ir(t,"utf-8")).version;if(typeof o=="string")return o}}catch{}return"unknown"})(),r=new Pe(Ae()),_r=new nt(r),ae=new ut(r.getDatabase()),R=new _t(r.getDatabase()),v=new ft(r.getDatabase()),L=new yt(r.getDatabase()),Y=new kt(r.getDatabase()),j=new bt(r.getDatabase()),F=new Et(r.getDatabase());Dt(v,F);const B=new Ct(r.getDatabase()),fr=new Tt(r.getDatabase()),k=new Ot(r.getDatabase()),yr=Qt({groundTruths:v,scaffoldLib:L,memory:R,toolAnalytics:k,sessionSeen:ne,tokenEstimator:pr,rankWeights:ur,threadText:e=>{try{return oe(Xt(r.getDatabase(),e))}catch{try{const t=Zt(r.getDatabase(),e);return t?oe(t):""}catch{return""}}}}),ie=new xt(r.getDatabase()),dr=new Mt(r.getDatabase(),Wt()),gr=new It(r.getDatabase()),ce=new Nt(r.getDatabase()),me=new Lt(r.getDatabase()),le={projects:r,goals:me,getActor:je,store:r,raw:()=>r.getDatabase(),memory:R,truths:v,scaffolds:L,failures:Y,presence:j,rehydration:ie,graph:ae,symbols:B,vectors:()=>b,indexing:()=>G,cache:w,decrypt:e=>U.maybeDecrypt(e),clientSupportsResources:()=>{const e=c.getClientCapabilities()?.experimental;return!!e&&"resources"in e}},K=new Yt(r.getDatabase()),hr=er({db:r,mcpClient:K,version:T}),wr=new Kt(r.getDatabase()),Sr=Ft({db:r,failures:Y,symbols:B,rehydration:ie,causality:F,presence:j,federation:ce,memory:R,groundTruths:v}),Rr=new jt(r.getDatabase(),K,Sr);if(process.env.WYRM_ENCRYPTION_KEY)try{lt(process.env.WYRM_ENCRYPTION_KEY)}catch(e){console.error("Wyrm: Failed to initialize encryption:",e)}const U=mt();let b=null,G=null;{const e=pt(r,R,U);b=e.vectorStore,G=e.indexingPipeline}const vr=ct({autoOrchestrateEnabled:!0,minConfidenceThreshold:65,maxParallelAgents:6,defaultHaikuBoosting:!0,trackMetrics:!0});dt();const O=gt();O.tier!=="free"&&console.error(`Wyrm: Licensed, ${O.tier} tier (expires: ${O.expiresAt||"never"})`);const kr=!!O.key&&!/^(0|false|no|off)$/i.test(process.env.WYRM_LICENSE_REFRESH??"");kr&&(Promise.all([Z(),ee()]).catch(()=>{}),setInterval(()=>{Promise.all([Z(),ee()]).catch(()=>{})},1440*60*1e3).unref?.());try{const e=process.env.HOME||process.env.USERPROFILE||"",t=it(e,".wyrm","bundled-skills.json");if(e&&X(t)){const o=JSON.parse(Q(t,"utf-8"));let l=0;for(const i of o.skills)try{if(!X(i.path))continue;const m=Q(i.path,"utf-8").match(/^---\s*\n([\s\S]*?)\n---/);let a=i.name,_;if(m){const g=m[1].match(/description:\s*\|?\s*\n([\s\S]*?)(?:\nname:|\nmetadata:|\ncategory:|\ntype:|$)/);g&&(a=g[1].split(`
|
|
3
|
+
`).map(D=>D.trim()).filter(Boolean).join(" ").slice(0,500));const S=m[1].match(/category:\s*([^\n]+)/);S&&(_=S[1].trim())}r.registerSkill(i.name,a,i.path,_,"Ghost Protocol",void 0,"bundled"),l++}catch{}l>0&&console.error(`Wyrm: Registered ${l} bundled skill(s) on first start.`);try{at(t)}catch{}}}catch{}const H=new St(r.getDatabase()),pe=new Rt;process.env.WYRM_R2_ENDPOINT&&process.env.WYRM_R2_ACCESS_KEY&&process.env.WYRM_R2_SECRET_KEY&&pe.configure({endpoint:process.env.WYRM_R2_ENDPOINT,bucket:process.env.WYRM_R2_BUCKET||"wyrm-backups",accessKeyId:process.env.WYRM_R2_ACCESS_KEY,secretAccessKey:process.env.WYRM_R2_SECRET_KEY},process.env.WYRM_ENCRYPTION_KEY);import{fileURLToPath as br}from"url";import{dirname as Er,join as ue}from"path";const Dr=br(import.meta.url),_e=Er(Dr),Cr=new vt(ue(_e,"cloud-sync-entrypoint.js")),Tr=new ot(ue(_e,"replication-daemon-entrypoint.js")),{trackUsage:d,getUsageStats:Or,usageLog:xr}=Bt(H),Mr=new Map;function Wr(e,t=!1){return{content:[{type:"text",text:e}]}}const Pr=new Set(["wyrm_list_projects","wyrm_project_context","wyrm_global_context","wyrm_all_quests","wyrm_data_query","wyrm_data_categories","wyrm_search","wyrm_stats","wyrm_skill_list","wyrm_skill_get","wyrm_skill_search","wyrm_skill_stats","wyrm_orchestration_config","wyrm_orchestration_stats","wyrm_license","wyrm_analytics_dashboard","wyrm_cost_report","wyrm_entity_search","wyrm_entity_graph","wyrm_entity_path","wyrm_truth_get","wyrm_scaffold_get","wyrm_session_prime"]);function Ar(e,t){return!(!Pr.has(e)||e==="wyrm_session_prime"&&(t?.run_id===void 0||t?.run_id===null))}const fe=new Set(["wyrm_session_start","wyrm_session_update","wyrm_quest_add","wyrm_quest_complete","wyrm_data_insert","wyrm_data_batch_insert","wyrm_set_global","wyrm_scan_projects","wyrm_sync","wyrm_maintenance","wyrm_vector_setup","wyrm_reindex","wyrm_skill_register","wyrm_skill_delete","wyrm_skill_activate","wyrm_skill_deactivate","wyrm_spec_register","wyrm_activate","wyrm_cloud_backup","wyrm_cloud_sync","wyrm_encrypt_setup","wyrm_entity_add","wyrm_entity_link","wyrm_entity_merge","wyrm_remember","wyrm_recall","wyrm_feedback","wyrm_truth_set","wyrm_scaffold_save","wyrm_distill","wyrm_review","wyrm_capture","wyrm_import_git","wyrm_import_pr","wyrm_import_rules","wyrm_inject_prompt","wyrm_prune","wyrm_sync_export","wyrm_sync_import"]),E=new ze,c=new we({name:"wyrm",version:T},{capabilities:{tools:{},prompts:{},resources:{},tasks:{list:{},cancel:{},requests:{tools:{call:{}}}}},instructions:st}),ye={...le,db:r,sync:_r,graph:ae,memory:R,groundTruths:v,scaffoldLib:L,failures:Y,presence:j,causality:F,symbols:B,hours:fr,toolAnalytics:k,auditLog:dr,subAgent:gr,federation:ce,goals:me,mcpClient:K,agentDaemon:wr,agentLoop:Rr,analytics:H,cloudBackup:pe,cloudSyncManager:Cr,replicationManager:Tr,orchestrator:vr,server:c,wyrmCrypto:U,get vectorStore(){return b},get indexingPipeline(){return G},setVectorStore:e=>{b=e},WYRM_PACKAGE_VERSION:T,WYRM_TOOL_COUNT:mr,toolCounts:()=>({active:re([...W(),...P()],te()).length,full:W().length+P().length}),WRITE_TOOLS:fe,usageLog:xr,responseFingerprints:Mr,designSystem:lr,sessionSeen:ne,cachedResponse:Wr,getUsageStats:Or,runCompanionBuddy:hr,runBudgetedContextBuild:yr};c.setRequestHandler(Me,async()=>{const e=[...W(),...P()],t=te();return{tools:Ye(Le(qt(Ht(Gt(re(e,t))))))}}),c.setRequestHandler(Te,async()=>({prompts:[...He()]})),c.setRequestHandler(Ce,async e=>{const t=e.params.arguments??{},o=J({transport:"mcp",args:t,meta:e.params._meta,clientName:c.getClientVersion()?.name});return z(o,()=>Ge(e.params.name,t,le))}),c.setRequestHandler(Oe,async()=>({resources:qe()})),c.setRequestHandler(xe,async()=>({resourceTemplates:Ve()})),c.setRequestHandler(We,async e=>{const t=e.params.uri;try{const o=$e(t,ye),{nextCursor:l,...i}=o;return l?{contents:[i],_meta:{"wyrm/nextCursor":l}}:{contents:[i]}}catch(o){throw o instanceof Je?new Error(o.message):o}}),Ze(c,E),c.setRequestHandler(De,async e=>{const{name:t,arguments:o}=e.params;if(!ht())return wt();const l=J({transport:"mcp",args:o??{},meta:e.params._meta,clientName:c.getClientVersion()?.name});Vt(t);const i=performance.now(),x=JSON.stringify(o||{}),m=A(x);let a,_,g=null;try{const s=Be(t,o??{});s.via?.kind==="cli-exile"&&(g=s.via),{tool:a,args:_}=Ue(s.tool,s.args),Ke(t,o??{},a)}catch(s){if(s instanceof V){const n=Math.round(performance.now()-i);d({tool:t,tokens_in:m,tokens_out:0,cached:!1,ms:n,timestamp:new Date().toISOString()});const p=$(t,s.field,s.message);return y({tool:t,args:o,meta:e.params._meta,response:p,outcome:"validation_error",ms:n,dispatch:"switch"}),p}throw s}if(g&&$t(g.name)){const s=Math.round(performance.now()-i);d({tool:t,tokens_in:m,tokens_out:0,cached:!1,ms:s,timestamp:new Date().toISOString()});const n=Jt(g.name);return y({tool:t,args:o,meta:e.params._meta,response:n,outcome:"soft_error",ms:s,dispatch:"switch"}),n}const S=Qe(c.getClientCapabilities()?.tasks,e.params),D=rt(E,S,a,s=>{const n=Math.round(performance.now()-i);d({tool:t,tokens_in:m,tokens_out:0,cached:!1,ms:n,timestamp:new Date().toISOString()}),y({tool:t,args:o,meta:e.params._meta,response:s,outcome:"soft_error",ms:n,dispatch:h.has(a)?"registry":"switch"})});if(D!==null)return D;const de=a===t?x:JSON.stringify(_),M=Ar(a,_??{})?Ne(a,de):null;if(M){const s=w.get(M);if(s){const n=Math.round(performance.now()-i),p=A(JSON.stringify(s));d({tool:t,tokens_in:m,tokens_out:p,cached:!0,ms:n,timestamp:new Date().toISOString()});const u={...s};return y({tool:t,args:o,meta:e.params._meta,response:u,cached:!0,ms:n,dispatch:h.has(a)?"registry":"switch"}),et(E,S,a,u)}}if(fe.has(a)){const s=_?.projectPath;s&&w.invalidate(s),w.invalidate("wyrm_list_projects"),w.invalidate("wyrm_global_context"),w.invalidate("wyrm_all_quests"),w.invalidate("wyrm_stats")}let C;const ge=_||{};try{const s=await z(l,async()=>{const q=h.get(a);return q?await Xe(a,S,E,()=>Fe(M,()=>q(ge,ye))):{kind:"inline",result:{content:[{type:"text",text:`Unknown tool: ${a}`}],isError:!0}}}),{wireValue:n,payload:p}=tt(E,s);C=p;const u=Math.round(performance.now()-i),f=JSON.stringify(C),he=A(f);return or(r.getDatabase(),f),d({tool:t,tokens_in:m,tokens_out:he,cached:!1,ms:u,timestamp:new Date().toISOString()}),k.log({tool_name:t,args:o,success:!C?.isError,latency_ms:u}),y({tool:t,args:o,meta:e.params._meta,response:C,ms:u,dispatch:h.has(a)?"registry":"switch"}),n}catch(s){const n=Math.round(performance.now()-i);if(s instanceof V){d({tool:t,tokens_in:m,tokens_out:0,cached:!1,ms:n,timestamp:new Date().toISOString()});const f=$(t,s.field,s.message);return y({tool:t,args:o,meta:e.params._meta,response:f,outcome:"validation_error",ms:n,dispatch:h.has(a)?"registry":"switch"}),f}const p=Pt(s);if(p!==null){d({tool:t,tokens_in:m,tokens_out:0,cached:!1,ms:n,timestamp:new Date().toISOString()}),k.log({tool_name:t,args:o,success:!1,error_message:`WYRM_BUSY[${p}]: ${String(s).slice(0,400)}`,latency_ms:n});const f=At(t,p);return y({tool:t,args:o,meta:e.params._meta,response:f,outcome:"error",ms:n,dispatch:h.has(a)?"registry":"switch"}),f}d({tool:t,tokens_in:m,tokens_out:0,cached:!1,ms:n,timestamp:new Date().toISOString()}),k.log({tool_name:t,args:o,success:!1,error_message:String(s).slice(0,500),latency_ms:n});const u={content:[{type:"text",text:`Error: ${Ie(s)}`}],isError:!0};return y({tool:t,args:o,meta:e.params._meta,response:u,outcome:"error",ms:n,dispatch:h.has(a)?"registry":"switch"}),u}}),process.on("uncaughtException",e=>{try{console.error("Wyrm[uncaughtException]:",e instanceof Error?e.stack:e)}catch{}}),process.on("unhandledRejection",e=>{try{console.error("Wyrm[unhandledRejection]:",e instanceof Error?e.stack:e)}catch{}});async function Ir(){const e=ke([()=>H.shutdown(),()=>r.close()]);process.on("SIGINT",()=>e()),process.on("SIGTERM",()=>e());const{transport:t,inFlight:o}=be(new Se);ve({inFlight:o,drainMs:Ee(),onOrphan:l=>e(`client gone (${l})`)}),await c.connect(t),Re(r,process.env,{vectors:()=>b}),Ut(r.getDatabase(),T).catch(()=>{})}Ir().catch(console.error);export{ns as classifyCapture};
|
package/dist/indexer.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
const u=3,a=`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS indexing_queue (
|
|
3
3
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
4
4
|
content_type TEXT NOT NULL,
|
|
@@ -13,7 +13,7 @@ class a{db;vectorStore;timer=null;processing=!1;batchSize;maxRetries;intervalMs;
|
|
|
13
13
|
);
|
|
14
14
|
CREATE INDEX IF NOT EXISTS idx_iq_status ON indexing_queue(status);
|
|
15
15
|
CREATE INDEX IF NOT EXISTS idx_iq_content ON indexing_queue(content_type, content_id);
|
|
16
|
-
|
|
16
|
+
`,c=`
|
|
17
17
|
INSERT INTO indexing_queue (content_type, content_id, project_id, status, retry_count)
|
|
18
18
|
VALUES (?, ?, ?, 'pending', 0)
|
|
19
19
|
ON CONFLICT(content_type, content_id) DO UPDATE SET
|
|
@@ -21,9 +21,9 @@ class a{db;vectorStore;timer=null;processing=!1;batchSize;maxRetries;intervalMs;
|
|
|
21
21
|
retry_count = 0,
|
|
22
22
|
error_message = NULL,
|
|
23
23
|
processed_at = NULL
|
|
24
|
-
|
|
24
|
+
`;function E(i,e){i.exec(a);const s=i.prepare(c);return i.transaction(()=>{for(const n of e)s.run(n.contentType,n.contentId,n.projectId)})(),e.length}class d{db;vectorStore;timer=null;processing=!1;batchSize;maxRetries;intervalMs;contentResolver;constructor(e,s,n,t){this.db=e,this.vectorStore=s,this.contentResolver=n,this.batchSize=t?.batchSize??10,this.maxRetries=t?.maxRetries??3,this.intervalMs=t?.intervalMs??5e3,this.ensureTable()}updateStore(e){this.vectorStore=e}ensureTable(){this.db.exec(a)}enqueue(e,s,n){this.db.prepare(c).run(e,s,n)}async processBatch(){if(this.processing)return 0;this.processing=!0;try{this.db.prepare("UPDATE indexing_queue SET status = 'pending' WHERE status = 'processing'").run();const e=this.db.prepare(`
|
|
25
25
|
SELECT * FROM indexing_queue
|
|
26
26
|
WHERE status = 'pending' AND retry_count < ?
|
|
27
27
|
ORDER BY created_at ASC
|
|
28
28
|
LIMIT ?
|
|
29
|
-
`).all(this.maxRetries,this.batchSize);if(
|
|
29
|
+
`).all(this.maxRetries,this.batchSize);if(e.length===0)return 0;const s=e.map(t=>t.id);this.db.prepare(`UPDATE indexing_queue SET status = 'processing' WHERE id IN (${s.map(()=>"?").join(",")})`).run(...s);let n=0;for(const t of e)try{const r=this.contentResolver(t.content_type,t.content_id);if(r===null){this.db.prepare("UPDATE indexing_queue SET status = 'skipped', processed_at = datetime('now'), error_message = 'Content not found or encrypted' WHERE id = ?").run(t.id);continue}await this.vectorStore.addVector(r,t.content_type,t.content_id,t.project_id)?this.db.prepare("UPDATE indexing_queue SET status = 'done', processed_at = datetime('now') WHERE id = ?").run(t.id):this.db.prepare("UPDATE indexing_queue SET status = 'failed', retry_count = retry_count + 1, error_message = 'Provider returned null' WHERE id = ?").run(t.id),n++}catch(r){const o=r instanceof Error?r.message:String(r);this.db.prepare("UPDATE indexing_queue SET status = 'failed', retry_count = retry_count + 1, error_message = ? WHERE id = ?").run(o,t.id)}return this.db.prepare("UPDATE indexing_queue SET status = 'pending' WHERE status = 'failed' AND retry_count < ?").run(this.maxRetries),n}finally{this.processing=!1}}start(){this.timer||(this.timer=setInterval(()=>{this.processBatch().catch(()=>{})},this.intervalMs))}stop(){this.timer&&(clearInterval(this.timer),this.timer=null)}getStats(){const e=this.db.prepare("SELECT status, COUNT(*) as cnt FROM indexing_queue GROUP BY status").all(),s={pending:0,processing:0,done:0,failed:0,skipped:0,total:0};for(const n of e)s[n.status]=n.cnt,s.total+=n.cnt;return s}clearCompleted(){return this.db.prepare("DELETE FROM indexing_queue WHERE status IN ('done', 'skipped')").run().changes}isProcessing(){return this.processing}isRunning(){return this.timer!==null}}export{d as IndexingPipeline,u as QUEUE_MAX_RETRIES,E as enqueueForIndexing};
|