diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f33a9a..78f6147 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.2.102 + +- Republish the same reviewed bounded-query product code through the isolated + exact-clone provenance path so the registry can record the landed commit. + ## 0.2.101 - Reject command-shaped unknown lookups before they can fall through to the diff --git a/bin/knowledge-mcp.js b/bin/knowledge-mcp.js index 22cff29..31c569f 100755 --- a/bin/knowledge-mcp.js +++ b/bin/knowledge-mcp.js @@ -14997,7 +14997,7 @@ import { existsSync as existsSync15, readFileSync as readFileSync14, writeFileSy // package.json var package_default = { name: "@hasna/knowledge", - version: "0.2.101", + version: "0.2.102", description: "Agent-friendly local knowledge CLI with JSON output, pagination, and safe destructive actions", type: "module", exports: { diff --git a/bin/knowledge.js b/bin/knowledge.js index 1b0da80..b3d3f59 100755 --- a/bin/knowledge.js +++ b/bin/knowledge.js @@ -1356,7 +1356,7 @@ Pages should be concise, cited, and organized for both humans and agents. ) `)}var B8=AY(q8(),1),{program:Fm,createCommand:rm,createArgument:bm,createOption:Mm,CommanderError:Zm,InvalidArgumentError:Hm,InvalidOptionArgumentError:km,Command:V8,Argument:Cm,Option:vm,Help:wm}=B8.default;import{chmod as AJ,mkdir as wv,readFile as uv,rename as fv,writeFile as M8}from"fs/promises";import{Buffer as f8}from"buffer";import{existsSync as x8}from"fs";import{homedir as xv}from"os";import{join as FU}from"path";import{createHmac as mv,timingSafeEqual as dm}from"crypto";import{randomUUID as tv}from"crypto";import{spawn as ov}from"child_process";import{randomUUID as $w}from"crypto";function rv(_,$){return $.split(".").reduce((g,U)=>{if(g&&typeof g==="object"&&U in g)return g[U];return},_)}function bv(_,$){let g=[],U=(I)=>{if(!g.some((j)=>Object.is(j,I)))g.push(I)};if($.includes(".")&&$ in _)U(_[$]);let D=rv(_,$);if(D!==void 0||!$.includes("."))U(D);return g}function Mv(_,$={}){let g="";for(let U=0;U<_.length;U+=1){let D=_[U];if(D==="*")if(_[U+1]==="*")g+=".*",U+=1;else g+=$.segmentSafe?"[^/]*":".*";else g+=D.replace(/[|\\{}()[\]^$+?.]/g,"\\$&")}return new RegExp(`^${g}$`)}function BU(_,$,g={}){if($===void 0)return!0;if(_===void 0)return!1;return(Array.isArray($)?$:[$]).some((D)=>Mv(D,g).test(_))}function F8(_,$){if(!$)return!0;return Object.entries($).every(([g,U])=>{let D=bv(_,g);return Zv(D,U,g)})}function Zv(_,$,g){if(Cv($))return!_.some((U)=>r8(U,$.not,g));return _.some((U)=>r8(U,$,g))}function r8(_,$,g){if(typeof $==="string"||Array.isArray($))return Hv(_).some((U)=>BU(U,$,{segmentSafe:g.endsWith("_path")||g.endsWith(".path")}));if(Array.isArray(_))return _.some((U)=>U===$);return _===$}function Hv(_){if(_===void 0)return[];if(Array.isArray(_))return _.flatMap(($)=>kv($)?[String($)]:[]);return[String(_)]}function kv(_){return _===null||typeof _==="string"||typeof _==="number"||typeof _==="boolean"}function Cv(_){return Boolean(_&&typeof _==="object"&&!Array.isArray(_)&&"not"in _)}function vv(_,$){return BU(_.source,$.source)&&BU(_.type,$.type)&&BU(_.subject,$.subject)&&BU(_.severity,$.severity)&&F8(_.data,$.data)&&F8(_.metadata,$.metadata)}function b8(_,$){if(!_.enabled)return!1;if(!_.filters||_.filters.length===0)return!0;return _.filters.some((g)=>vv($,g))}var GE="HASNA_EVENTS_DIR",XE="HASNA_EVENTS_HOME",LJ="local-json-v1:",yv=100,cv=1000;function y8(_){return _||process.env[GE]||process.env[XE]||FU(xv(),".hasna","events")}function hv(){if(process.env[GE])return GE;if(process.env[XE])return XE;return null}class YE{dataDir;runtime;channelsPath;eventsPath;deliveriesPath;constructor(_=y8()){this.dataDir=_,this.runtime=nv(_),this.channelsPath=FU(_,"channels.json"),this.eventsPath=FU(_,"events.json"),this.deliveriesPath=FU(_,"deliveries.json")}async init(){await wv(this.dataDir,{recursive:!0,mode:448}),await AJ(this.dataDir,448).catch(()=>{return}),await this.ensureArrayFile(this.channelsPath),await this.ensureArrayFile(this.eventsPath),await this.ensureArrayFile(this.deliveriesPath)}async addChannel(_){await this.init();let $=await this.readJson(this.channelsPath,[]),g=$.findIndex((U)=>U.id===_.id);if(g>=0)$[g]={..._,createdAt:$[g].createdAt,updatedAt:new Date().toISOString()};else $.push(_);return await this.writeJson(this.channelsPath,$),g>=0?$[g]:_}async listChannels(){return await this.init(),this.readJson(this.channelsPath,[])}async getChannel(_){return(await this.listChannels()).find((g)=>g.id===_)}async removeChannel(_){await this.init();let $=await this.readJson(this.channelsPath,[]),g=$.filter((U)=>U.id!==_);return await this.writeJson(this.channelsPath,g),g.length!==$.length}async appendEvent(_){await this.init();let $=await this.readJson(this.eventsPath,[]);return $.push(_),await this.writeJson(this.eventsPath,$),_}async appendEventOnce(_,$={}){await this.init();let g=await this.readJson(this.eventsPath,[]);if($.dedupe!==!1){let D=H8(g,{id:_.id,dedupeKey:_.dedupeKey});if(D)return{event:D,stored:!1,deduped:!0,identity:{id:D.id,dedupeKey:D.dedupeKey}}}return g.push(_),await this.writeJson(this.eventsPath,g),{event:_,stored:!0,deduped:!1,identity:{id:_.id,dedupeKey:_.dedupeKey}}}async listEvents(_={}){await this.init();let $=await this.readJson(this.eventsPath,[]);return Z8($,_)}async listEventsPage(_={}){await this.init();let $=await this.readJson(this.eventsPath,[]),g=Z8($,{eventId:_.eventId,source:_.source,type:_.type}),U=QE(_.cursor,_),D=TE(_.limit),I=g.slice(U,U+D),j=U+I.length,E=j{return})}async readJson(_,$){try{let g=await uv(_,"utf-8");if(!g.trim())return $;return JSON.parse(g)}catch(g){if(g.code==="ENOENT")return $;throw g}}async writeJson(_,$){let g=`${_}.${process.pid}.${Date.now()}.tmp`;await M8(g,`${JSON.stringify($,null,2)} -`,{encoding:"utf-8",mode:384}),await fv(g,_),await AJ(_,384).catch(()=>{return})}}function nv(_=y8()){return{mode:"local-files",name:"json-events-store",remote:!1,localFiles:!0,localSqlite:!1,postgres:!1,s3:!1,aws:!1,durable:!0,idempotency:"best-effort-local",replayCursors:!0,description:`Local JSON files in ${_}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`}}function c8(_,$={}){if(!Number.isInteger(_)||_<0)throw Error(`Invalid event cursor offset: ${_}`);let g={offset:_,eventId:$.eventId,source:$.source,type:$.type};return`${LJ}${f8.from(JSON.stringify(g),"utf-8").toString("base64url")}`}function QE(_,$={}){if(!_)return 0;if(!_.startsWith(LJ))throw Error(`Invalid local JSON event cursor: ${_}`);let g=_.slice(LJ.length),U;try{U=JSON.parse(f8.from(g,"base64url").toString("utf-8"))}catch{throw Error(`Invalid local JSON event cursor: ${_}`)}let D=U.offset;if(!Number.isInteger(D)||D<0)throw Error(`Invalid local JSON event cursor: ${_}`);return OJ("eventId",U.eventId,$.eventId),OJ("source",U.source,$.source),OJ("type",U.type,$.type),D}function TE(_){if(_===void 0)return yv;if(!Number.isInteger(_)||_<1)throw Error(`Event page limit must be a positive integer, got ${_}`);return Math.min(_,cv)}function Z8(_,$){let g=_;if($.eventId)g=g.filter((U)=>U.id===$.eventId);if($.source)g=g.filter((U)=>U.source===$.source);if($.type)g=g.filter((U)=>U.type===$.type);if($.cursor){let U=QE($.cursor,$);g=g.slice(U)}if($.limit!==void 0)g=g.slice(0,TE($.limit));return g}function OJ(_,$,g){if($!==g)throw Error(`Local JSON event cursor ${_} filter mismatch`)}function H8(_,$){return _.find((g)=>$.id!==void 0&&g.id===$.id||$.dedupeKey!==void 0&&g.dedupeKey===$.dedupeKey)}async function dv(_){let $=new YE(_);await $.init();let[g,U,D]=await Promise.all([$.listChannels(),$.listEvents(),$.listDeliveries()]),I=g.reduce((j,E)=>{return j[E.transport]=(j[E.transport]??0)+1,j},{});return{service:"events",schemaVersion:"1.0",dataDir:$.dataDir,storage:$.runtime,env:{primary:GE,fallback:XE,active:hv()},files:{channels:PJ($.dataDir,"channels.json",g.length),events:PJ($.dataDir,"events.json",U.length),deliveries:PJ($.dataDir,"deliveries.json",D.length)},counts:{channels:g.length,enabledChannels:g.filter((j)=>j.enabled).length,disabledChannels:g.filter((j)=>!j.enabled).length,events:U.length,deliveries:D.length},transports:I,safety:{includesEventPayloads:!1,includesWebhookSecrets:!1,listOutputsRedactSecrets:!0,statusOutputIsMetadataOnly:!0}}}function PJ(_,$,g){let U=FU(_,$);return{path:U,exists:x8(U),records:g}}function iv(_,$){return`${_}.${$}`}function lv(_,$,g){return`sha256=${mv("sha256",_).update(iv($,g)).digest("hex")}`}function m$(){return new Date().toISOString()}function VU(_,$=4096){return _.length>$?`${_.slice(0,$)}...`:_}function pv(_,$){if(!$.webhook)throw Error(`Channel ${$.id} has no webhook config`);let g=JSON.stringify(_),U=_.time,D={"Content-Type":"application/json","User-Agent":"@hasna/events","X-Hasna-Event-Id":_.id,"X-Hasna-Event-Type":_.type,"X-Hasna-Timestamp":U,...$.webhook.headers};if($.webhook.secret)D["X-Hasna-Signature"]=lv($.webhook.secret,U,g);return{body:g,headers:D}}async function ev(_,$,g={}){if(!$.webhook)throw Error(`Channel ${$.id} has no webhook config`);let U=m$(),{body:D,headers:I}=pv(_,$),j=new AbortController,E=setTimeout(()=>j.abort(),$.webhook.timeoutMs??15000);try{let A=await(g.fetchImpl??fetch)($.webhook.url,{method:"POST",headers:I,body:D,signal:j.signal}),O=VU(await A.text());return{attempt:1,status:A.ok?"success":"failed",startedAt:U,completedAt:m$(),responseStatus:A.status,responseBody:O,error:A.ok?void 0:`Webhook returned HTTP ${A.status}`}}catch(A){return{attempt:1,status:"failed",startedAt:U,completedAt:m$(),error:A instanceof Error?A.message:String(A)}}finally{clearTimeout(E)}}async function av(_,$){if(!$.command)throw Error(`Channel ${$.id} has no command config`);let g=m$(),U=JSON.stringify(_),D={...process.env,...$.command.env,HASNA_CHANNEL_ID:$.id,HASNA_EVENT_ID:_.id,HASNA_EVENT_TYPE:_.type,HASNA_EVENT_SOURCE:_.source,HASNA_EVENT_SUBJECT:_.subject??"",HASNA_EVENT_SEVERITY:_.severity,HASNA_EVENT_TIME:_.time,HASNA_EVENT_DEDUPE_KEY:_.dedupeKey??"",HASNA_EVENT_SCHEMA_VERSION:_.schemaVersion,HASNA_EVENT_JSON:U};return new Promise((I)=>{let j=ov($.command.command,$.command.args??[],{cwd:$.command.cwd,env:D,stdio:["pipe","pipe","pipe"]}),E="",A="",O=setTimeout(()=>j.kill("SIGTERM"),$.command.timeoutMs??15000);j.stdin.end(U),j.stdout.on("data",(P)=>{E+=P.toString()}),j.stderr.on("data",(P)=>{A+=P.toString()}),j.on("error",(P)=>{clearTimeout(O),I({attempt:1,status:"failed",startedAt:g,completedAt:m$(),stdout:VU(E),stderr:VU(A),error:P.message})}),j.on("close",(P,W)=>{clearTimeout(O);let z=P===0;I({attempt:1,status:z?"success":"failed",startedAt:g,completedAt:m$(),stdout:VU(E),stderr:VU(A),error:z?void 0:`Command exited with ${W?`signal ${W}`:`code ${P}`}`})})})}async function sv(_,$,g={}){if($.transport==="webhook")return ev(_,$,g);if($.transport==="command")return av(_,$);return{attempt:1,status:"skipped",startedAt:m$(),completedAt:m$(),error:`Unsupported transport: ${$.transport}`}}function k8(_,$,g){let U=g.some((D)=>D.status==="success")?"success":g.every((D)=>D.status==="skipped")?"skipped":"failed";return{id:tv(),eventId:_.id,channelId:$.id,transport:$.transport,status:U,attempts:g,createdAt:g[0]?.startedAt??m$(),completedAt:g.at(-1)?.completedAt??m$()}}class h8 extends Error{eventType;issues;constructor(_,$){let g=$.map((U)=>`${U.path||""}: ${U.message}`).join("; ");super(`Event validation failed for type "${_}": ${g}`);this.name="EventValidationError",this.eventType=_,this.issues=$}}class n8{definitions=new Map;register(_){return this.definitions.set(_.type,_),this}unregister(_){return this.definitions.delete(_)}has(_){return this.definitions.has(_)}get(_){return this.definitions.get(_)}list(){return[...this.definitions.values()]}validateEvent(_){let $=this.definitions.get(_.type);if(!$)return{ok:!0};return $.validate(_.data,_)}assertEventValid(_){let $=this.validateEvent(_);if(!$.ok)throw new h8(_.type,$.issues)}}var _w=new n8;function SJ(_){return{id:_.id??$w(),source:_.source,type:_.type,time:jw(_.time),subject:_.subject,severity:_.severity??"info",data:_.data??{},message:_.message,dedupeKey:_.dedupeKey,schemaVersion:_.schemaVersion??"1.0",metadata:_.metadata??{}}}class d8{store;redactors;transportOptions;catalog;validateCatalogTypes;constructor(_={}){this.store=_.store??new YE(_.dataDir),this.redactors=_.redactors??[],this.transportOptions={fetchImpl:_.fetchImpl},this.catalog=_.catalog??_w,this.validateCatalogTypes=_.validateCatalogTypes??!1}async addChannel(_){let $=new Date().toISOString();return this.store.addChannel({..._,createdAt:_.createdAt??$,updatedAt:_.updatedAt??$})}async listChannels(){return this.store.listChannels()}async removeChannel(_){return this.store.removeChannel(_)}async emit(_,$={}){let g=$.redactSensitiveData===!1?SJ(_):Uw(SJ(_));if($.validate??this.validateCatalogTypes)this.catalog.assertEventValid(g);let U=await this.appendEvent(g,{dedupe:$.dedupe!==!1});if(U.deduped)return{event:U.event,deliveries:[],deduped:!0};let D=$.deliver===!1?[]:await this.deliver(U.event);return{event:U.event,deliveries:D,deduped:!1}}async listEvents(_={}){if(Object.keys(_).length===0)return this.store.listEvents();return C8(await this.store.listEvents(),_)}async listEventsPage(_={}){if(this.store.listEventsPage)return this.store.listEventsPage(_);let $=C8(await this.store.listEvents(),{eventId:_.eventId,source:_.source,type:_.type}),g=QE(_.cursor,_),U=TE(_.limit),D=$.slice(g,g+U),I=g+D.length,j=I<$.length;return{events:D,cursor:_.cursor,nextCursor:j?c8(I,_):void 0,hasMore:j}}async listDeliveries(){return this.store.listDeliveries()}async deliver(_){let g=(await this.store.listChannels()).filter((D)=>b8(D,_)),U=[];for(let D of g){let I=await this.applyRedaction(_,D),j=await this.deliverWithRetry(I,D);await this.store.appendDelivery(j),U.push(j)}return U}async matchChannel(_,$={}){let g=await this.store.getChannel(_);if(!g)throw Error(`Channel not found: ${_}`);let U=SJ({source:$.source??"hasna.events",type:$.type??"events.test",subject:$.subject??_,severity:$.severity??"info",data:$.data??{test:!0},message:$.message??"Hasna events test delivery",dedupeKey:$.dedupeKey,schemaVersion:$.schemaVersion,metadata:$.metadata,time:$.time,id:$.id}),D=b8(g,U);return{channelId:g.id,matched:D,event:U,filters:g.filters,reason:D?void 0:g.enabled?"event did not match channel filters":"channel is disabled"}}async testChannel(_,$={},g={}){let U=await this.store.getChannel(_);if(!U)throw Error(`Channel not found: ${_}`);let D=await this.matchChannel(_,$),I=D.event;if(g.honorFilters&&!D.matched){let A=new Date().toISOString(),O=k8(I,U,[{attempt:1,status:"skipped",startedAt:A,completedAt:A,error:D.reason}]);return O.metadata={reason:"filter_mismatch"},await this.store.appendDelivery(O),O}let j=await this.applyRedaction(I,U),E=await this.deliverWithRetry(j,U);return await this.store.appendDelivery(E),E}async replay(_={}){let $=_.cursor||_.limit!==void 0?await this.listEventsPage(_):{events:await this.listEvents(_),hasMore:!1};if(_.dryRun)return{events:$.events,deliveries:[],cursor:$.cursor,nextCursor:$.nextCursor,hasMore:$.hasMore};let g=[];for(let U of $.events)g.push(...await this.deliver(U));return{events:$.events,deliveries:g,cursor:$.cursor,nextCursor:$.nextCursor,hasMore:$.hasMore}}async appendEvent(_,$){if(this.store.appendEventOnce)return this.store.appendEventOnce(_,{dedupe:$.dedupe});if($.dedupe){let U=await this.store.findEventByIdentity({id:_.id,dedupeKey:_.dedupeKey});if(U)return{event:U,stored:!1,deduped:!0,identity:{id:U.id,dedupeKey:U.dedupeKey}}}let g=await this.store.appendEvent(_);return{event:g,stored:!0,deduped:!1,identity:{id:g.id,dedupeKey:g.dedupeKey}}}async applyRedaction(_,$){let g=gw(_,$.redact?.paths??[],$.redact?.replacement??"[REDACTED]");for(let U of this.redactors)g=await U(g,$);return g}async deliverWithRetry(_,$){let g=Ew($.retry),U=[];for(let D=0;D[g,i8(g)?"[REDACTED]":U]));return $}function Dw(_){return _.map(m8)}function Uw(_,$="[REDACTED]"){return WJ(_,$)}function i8(_){return/secret|token|password|api[_-]?key|authorization/i.test(_)}function WJ(_,$){if(Array.isArray(_))return _.map((g)=>WJ(g,$));if(!_||typeof _!=="object")return _;return Object.fromEntries(Object.entries(_).map(([g,U])=>[g,i8(g)?$:WJ(U,$)]))}function Iw(_,$,g){let U=$.split("."),D=_;for(let j of U.slice(0,-1)){let E=D[j];if(!E||typeof E!=="object")return;D=E}let I=U.at(-1);if(I&&I in D)D[I]=g}function C8(_,$){let g=_;if($.eventId)g=g.filter((U)=>U.id===$.eventId);if($.source)g=g.filter((U)=>U.source===$.source);if($.type)g=g.filter((U)=>U.type===$.type);if($.cursor)g=g.slice(QE($.cursor,$));if($.limit!==void 0)g=g.slice(0,TE($.limit));return g}function jw(_){if(!_)return new Date().toISOString();return _ instanceof Date?_.toISOString():_}function Ew(_){return{maxAttempts:Math.max(1,_?.maxAttempts??1),backoffMs:Math.max(0,_?.backoffMs??250),multiplier:Math.max(1,_?.multiplier??2)}}function RE(_,$,g=!1){if(!_?.length)return;let U={};for(let D of _){let I=Ow(D,$),j=I.path;if(j in U)throw Error(`Duplicate ${$} filter path: ${j}`);let E=g?Aw(I.rawValue,$):I.rawValue;U[j]=I.negated?{not:E}:E}return U}function Nw(_){let $={};if(_.source)$.source=_.source;if(_.type)$.type=_.type;if(_.subject)$.subject=_.subject;if(_.severity)$.severity=_.severity;let g=v8(RE(_.data,"data"),RE(_.dataJson,"data-json",!0)),U=v8(RE(_.metadata,"metadata"),RE(_.metadataJson,"metadata-json",!0));if(Object.keys(g).length>0)$.data=g;if(Object.keys(U).length>0)$.metadata=U;return Object.keys($).length>0?[$]:void 0}function v8(..._){let $={};for(let g of _){if(!g)continue;for(let[U,D]of Object.entries(g)){if(U in $)throw Error(`Duplicate filter path: ${U}`);$[U]=D}}return $}function Aw(_,$){let g=JSON.parse(_);if(g===null||typeof g==="string"||typeof g==="number"||typeof g==="boolean"||Array.isArray(g)&&g.every((U)=>typeof U==="string"))return g;throw Error(`${$} filter JSON values must be string, string[], number, boolean, or null`)}function Ow(_,$){let g=_.indexOf("!=");if(g>0)return{path:_.slice(0,g),rawValue:_.slice(g+2),negated:!0};let U=_.indexOf("=");if(U<=0)throw Error(`Invalid ${$} filter, expected path=value or path!=value: ${_}`);return{path:_.slice(0,U),rawValue:_.slice(U+1),negated:!1}}var Pw=100;function q0(_,$){if(!_)return $;let g=JSON.parse(_);if(!g||typeof g!=="object"||Array.isArray(g))throw Error("Expected a JSON object");return g}function Sw(_){if(!_?.length)return;let $={};for(let g of _){let U=g.indexOf("=");if(U===-1)throw Error(`Invalid header, expected name=value: ${g}`);$[g.slice(0,U)]=g.slice(U+1)}return $}function e6(_){if(_.createClient)return _.createClient();return new d8({store:new YE(_.dataDir)})}function _4(_,$,g){if($)console.log(JSON.stringify(_,null,2));else console.log(g)}function w8(_,$){let g=_ instanceof Error?_.message:String(_);if($)console.log(JSON.stringify({error:g},null,2));else console.error(g);process.exitCode=1}function u8(_){return Boolean(_?.json||_?.opts?.().json||_?.optsWithGlobals?.().json||_?.parent?.opts?.().json||_?.parent?.optsWithGlobals?.().json)}function G6(_,$){return u8(_)||u8($)}function Lw(_,$){let g=_.command($.channelsCommandName??"channels").description("Manage Hasna event channels");return g.command("add").description("Add or replace a channel").argument("","Webhook URL or command binary").requiredOption("--id ","Channel identifier").option("--transport ","Transport kind: webhook or command","webhook").option("--name ","Display name").option("--type ","Event type filter, e.g. todos.task.*").option("--source ","Event source filter").option("--subject ","Event subject filter").option("--severity ","Event severity filter").option("--data ","Event data field filter; string values, path!=value negatives, array-member matching, dot paths, * segment wildcard, ** recursive wildcard",sg,[]).option("--metadata ","Event metadata field filter; string values, path!=value negatives, array-member matching, dot paths, * segment wildcard, ** recursive wildcard",sg,[]).option("--data-json ","Event data field filter with typed JSON value; path!=json negatives supported",sg,[]).option("--metadata-json ","Event metadata field filter with typed JSON value; path!=json negatives supported",sg,[]).option("--secret ","Webhook HMAC secret").option("--header ","Webhook header",sg,[]).option("--arg ","Command argument",sg,[]).option("--timeout-ms ","Transport timeout in milliseconds",rU).option("--retry-attempts ","Maximum delivery attempts",rU).option("--retry-backoff-ms ","Initial retry backoff in milliseconds",rU).option("--redact ","Event field path to redact before delivery",sg,[]).option("--disabled","Create channel disabled",!1).option("-j, --json","Print JSON output",!1).action(async(U,D,I)=>{let j=new Date().toISOString(),E={id:D.id,name:D.name,enabled:!D.disabled,transport:D.transport,filters:Nw(D),retry:D.retryAttempts||D.retryBackoffMs?{maxAttempts:D.retryAttempts,backoffMs:D.retryBackoffMs}:void 0,redact:D.redact?.length?{paths:D.redact}:void 0,createdAt:j,updatedAt:j};if(D.transport==="webhook")E.webhook={url:U,secret:D.secret,headers:Sw(D.header),timeoutMs:D.timeoutMs};else if(D.transport==="command")E.command={command:U,args:D.arg??[],timeoutMs:D.timeoutMs};else throw Error(`Transport ${D.transport} is reserved for future use and cannot be added yet`);let A=await e6($).addChannel(E);_4(m8(A),G6(D,I),`Added ${A.transport} channel ${A.id}`)}),g.command("list").description("List configured channels").option("-j, --json","Print JSON output",!1).action(async(U,D)=>{let I=await e6($).listChannels();if(G6(U,D)){console.log(JSON.stringify(Dw(I),null,2));return}if(!I.length){console.log("No channels configured.");return}for(let j of I)console.log(`${j.id} ${j.enabled?"enabled":"disabled"} ${j.transport} ${j.webhook?.url??j.command?.command??j.transport}`)}),g.command("status").description("Show events channel storage status").option("-j, --json","Print JSON output",!1).action(async(U,D)=>{let I=await dv($.dataDir);_4(I,G6(U,D),`events dataDir: ${I.dataDir}`)}),g.command("remove").description("Remove a channel").argument("","Channel identifier").option("-j, --json","Print JSON output",!1).action(async(U,D,I)=>{let j=await e6($).removeChannel(U);_4({removed:j},G6(D,I),j?`Removed ${U}`:`Channel not found: ${U}`)}),g.command("test").description("Send a test event to one channel").argument("","Channel identifier").option("--source ","Event source override").option("--type ","Event type","events.test").option("--subject ","Event subject").option("--message ","Event message","Hasna events test delivery").option("--data ","Event data JSON object").option("--metadata ","Event metadata JSON object").option("--honor-filters","Skip delivery when the sample event does not match channel filters",!1).option("-j, --json","Print JSON output",!1).action(async(U,D,I)=>{let j=G6(D,I);try{let E=await e6($).testChannel(U,{source:D.source??$.source,type:D.type,subject:D.subject??U,message:D.message,data:q0(D.data,{test:!0}),metadata:q0(D.metadata,{})},{honorFilters:D.honorFilters});_4(E,j,`${E.status}: ${E.channelId}`)}catch(E){w8(E,j)}}),g.command("match").description("Check whether a sample event matches one channel without delivering").argument("","Channel identifier").option("--source ","Event source override").option("--type ","Event type","events.test").option("--subject ","Event subject").option("--message ","Event message","Hasna events match preview").option("--data ","Event data JSON object").option("--metadata ","Event metadata JSON object").option("-j, --json","Print JSON output",!1).action(async(U,D,I)=>{let j=G6(D,I);try{let E=await e6($).matchChannel(U,{source:D.source??$.source,type:D.type,subject:D.subject??U,message:D.message,data:q0(D.data,{test:!0}),metadata:q0(D.metadata,{})});_4(E,j,`${E.matched?"matched":"skipped"}: ${E.channelId}`)}catch(E){w8(E,j)}}),g}function Ww(_,$){let g=_.command($.eventsCommandName??"events").description("Emit, list, and replay Hasna events");g.command("emit").description("Emit an event from this app").argument("","Event type").option("--source ","Event source override").option("--subject ","Event subject").option("--severity ","Event severity","info").option("--message ","Event message").option("--dedupe-key ","Dedupe key").option("--data ","Event data JSON object").option("--metadata ","Event metadata JSON object").option("--no-deliver","Record without delivering").option("--no-dedupe","Allow duplicate id/dedupeKey events").option("-j, --json","Print JSON output",!1).action(async(D,I,j)=>{let E=await e6($).emit({source:I.source??$.source,type:D,subject:I.subject,severity:I.severity,message:I.message,dedupeKey:I.dedupeKey,data:q0(I.data,{}),metadata:q0(I.metadata,{})},{deliver:I.deliver,dedupe:I.dedupe});_4(E,G6(I,j),`${E.deduped?"Deduped":"Emitted"} ${E.event.id} to ${E.deliveries.length} channel(s)`)});let U=$.defaultEventListLimit??Pw;return g.command("list").description("List recorded events").option("--source ","Filter by source").option("--type ","Filter by type").option("--limit ",`Limit to the most recent events (default ${U}; use 0 for all)`,rU,U).option("-j, --json","Print JSON output",!1).action(async(D,I)=>{let j=await e6($).listEvents();if(D.source)j=j.filter((E)=>E.source===D.source);if(D.type)j=j.filter((E)=>E.type===D.type);if(D.limit)j=j.slice(-D.limit);if(G6(D,I)){console.log(JSON.stringify(j,null,2));return}if(!j.length){console.log("No events recorded.");return}for(let E of j)console.log(`${E.time} ${E.id} ${E.source} ${E.type} ${E.severity}`)}),g.command("replay").description("Replay recorded events").option("--id ","Replay one event id").option("--source ","Filter by source").option("--type ","Filter by type").option("--cursor ","Opaque replay cursor from a previous page").option("--limit ","Maximum events to replay",rU).option("--dry-run","Preview without delivery",!1).option("-j, --json","Print JSON output",!1).action(async(D,I)=>{let j=await e6($).replay({eventId:D.id,source:D.source,type:D.type,cursor:D.cursor,limit:D.limit,dryRun:D.dryRun});_4(j,G6(D,I),Jw(j.events.length,j.deliveries.length,j.nextCursor))}),g}function l8(_,$){Lw(_,$),Ww(_,$)}function rU(_){let $=Number(_);if(!Number.isFinite($))throw Error(`Expected a number, got ${_}`);return $}function sg(_,$){return $.push(_),$}function Jw(_,$,g){let U=g?`, next cursor: ${g}`:"";return`Replayed ${_} event(s), ${$} delivery result(s)${U}`}import{basename as Rw}from"path";var H$={name:"@hasna/knowledge",version:"0.2.101",description:"Agent-friendly local knowledge CLI with JSON output, pagination, and safe destructive actions",type:"module",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"},"./storage":{import:"./dist/storage.js",types:"./dist/storage.d.ts"},"./serve":{import:"./dist/serve.js",types:"./dist/serve.d.ts"}},main:"./dist/index.js",types:"./dist/index.d.ts",bin:{knowledge:"bin/knowledge.js","knowledge-mcp":"bin/knowledge-mcp.js","knowledge-serve":"bin/knowledge-serve.js"},files:["bin","dist","scripts/apply-cloud-migrations.mjs","scripts/live-private-query.mjs","scripts/lib/remote-temp-dir.mjs","scripts/smoke-machine-sync-release.mjs","scripts/smoke-machines-adapter.mjs","scripts/smoke-open-files-installed-boundary.mjs","scripts/strip-generated-trailing-whitespace.mjs","scripts/verify-generated-artifacts.mjs","docs/architecture/ai-native-knowledge-base.md","docs/architecture/hosted-wrapper-responsibilities.md","docs/architecture/hybrid-semantic-search.md","docs/architecture/machine-sync-schema.md","docs/examples/app-project-wiki-standard.md","docs/examples/company-wiki-workflow.md","docs/migration/global-rules-provenance-import.md","docs/migration/json-to-sqlite.md","LICENSE","README.md"],scripts:{test:"bun test","test:cli":"bun test tests/cli.test.ts","test:package":"bun test tests/package-release.test.ts","release:pack:check":"node scripts/validate-public-package.mjs","smoke:machines-adapter":"bun scripts/smoke-machines-adapter.mjs","smoke:machine-sync-release":"bun scripts/smoke-machine-sync-release.mjs","smoke:open-files-installed-boundary":"bun scripts/smoke-open-files-installed-boundary.mjs","migrate:cloud":"bun scripts/apply-cloud-migrations.mjs","live:private-query":"bun scripts/live-private-query.mjs",serve:"bun src/serve-entry.ts","verify:generated":"bun scripts/verify-generated-artifacts.mjs","contracts:conformance":"contracts conformance fixtures",build:"rm -rf dist && bun build --target=bun --outfile=bin/knowledge.js --minify --external pg --external @hasna/machines --external @hasna/machines/consumer --external @aws-sdk/client-s3 --external @aws-sdk/credential-providers --external ai --external @ai-sdk/openai --external @ai-sdk/anthropic --external @ai-sdk/deepseek src/cli.ts && bun build --target=bun --outfile=bin/knowledge-mcp.js --external pg --external @hasna/machines --external @hasna/machines/consumer --external @modelcontextprotocol/sdk --external @aws-sdk/client-s3 --external @aws-sdk/credential-providers --external ai --external @ai-sdk/openai --external @ai-sdk/anthropic --external @ai-sdk/deepseek src/mcp.js && bun build --target=bun --outfile=bin/knowledge-serve.js --external pg --external @hasna/machines --external @hasna/machines/consumer --external @aws-sdk/client-s3 --external @aws-sdk/credential-providers --external ai --external @ai-sdk/openai --external @ai-sdk/anthropic --external @ai-sdk/deepseek src/serve-entry.ts && bun build ./src/index.ts ./src/storage.ts ./src/serve.ts --outdir ./dist --target bun --external pg --external @hasna/machines --external @hasna/machines/consumer --external @aws-sdk/client-s3 --external @aws-sdk/credential-providers --external ai --external @ai-sdk/openai --external @ai-sdk/anthropic --external @ai-sdk/deepseek && bun scripts/strip-generated-trailing-whitespace.mjs && bunx tsc -p tsconfig.build.json",prepublishOnly:"bun run contracts:conformance && contracts no-cloud-scan . && bun run build && node scripts/validate-public-package.mjs"},keywords:["knowledge","cli","agents","json","notes","local","store"],license:"Apache-2.0",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},repository:{type:"git",url:"git+https://github.com/hasna/knowledge.git"},bugs:{url:"https://github.com/hasna/knowledge/issues"},author:"Hasna Inc. ",engines:{bun:">=1.0",node:">=18"},dependencies:{"@ai-sdk/anthropic":"^3.0.81","@ai-sdk/deepseek":"^2.0.35","@ai-sdk/openai":"^3.0.68","@aws-sdk/client-s3":"^3.1063.0","@aws-sdk/credential-providers":"^3.1063.0","@hasna/events":"^0.1.3","@modelcontextprotocol/sdk":"^1.29.0","@types/json-schema":"^7.0.15",ai:"^6.0.197",commander:"^13.1.0",pg:"^8.16.3",zod:"^4.3.6"},devDependencies:{"@electric-sql/pglite":"^0.5.4","@hasna/contracts":"0.8.5","@types/bun":"^1.3.14","@types/pg":"^8.15.6"}};var t8={debug:0,info:1,warn:2,error:3},Gw=()=>{if(process.env.DEBUG)return"debug";if(process.env.LOG_LEVEL==="debug")return"debug";if(process.env.LOG_LEVEL==="warn")return"warn";if(process.env.LOG_LEVEL==="error")return"error";return"info"};function g4(_,$,g){if(t8[_]U.toLowerCase()));return $.filter((U)=>!g.has(U.toLowerCase()))}function JJ(_,$,g){if(g===void 0)return{..._,message:$};return{..._,added:g.length,message:`${$} (added ${g.length} tag${g.length===1?"":"s"})`}}function Tw(_,$){if($===void 0)throw Error("Missing value for --tag. Example: knowledge add <content> -t <tag> -t <tag>");let g=$.split(",").map((U)=>U.trim()).filter((U)=>U.length>0);if(g.length===0)throw Error(`Invalid --tag value ${JSON.stringify($)}: no tag name found. Example: knowledge add <title> <content> -t <tag> -t <tag>`);return Qw([..._??[],...g])}function Kw(_){let $=[],g={},U=!1;for(let D=0;D<_.length;D+=1){let I=_[D];if(U){$.push(I);continue}if(I==="--"){U=!0;continue}if(!I.startsWith("-")||$[0]==="add"&&$.length===2&&I.startsWith("---")){$.push(I);continue}switch(I){case"--json":g.json=!0;break;case"--verbose":g.verbose=!0;break;case"--yes":case"-y":g.yes=!0;break;case"--help":case"-h":g.help=!0;break;case"--version":case"-v":g.version=!0;break;case"--desc":g.desc=!0;break;case"--page":case"-p":g.page=Number(_[D+1]),D+=1;break;case"--limit":case"-l":g.limit=Number(_[D+1]),D+=1;break;case"--search":case"-s":g.search=_[D+1],D+=1;break;case"--sort":g.sort=_[D+1],D+=1;break;case"--id":g.id=_[D+1],D+=1;break;case"--store":g.store=_[D+1],D+=1;break;case"--title":g.title=_[D+1],D+=1;break;case"--content":g.content=_[D+1],D+=1;break;case"--url":g.url=_[D+1],D+=1;break;case"--tag":case"-t":g.tag=Tw(g.tag,_[D+1]),g.tagRaw=[...g.tagRaw??[],_[D+1]],D+=1;break;case"--format":g.format=_[D+1],D+=1;break;case"--completions":g.completions=_[D+1],D+=1;break;case"--purpose":g.purpose=_[D+1],D+=1;break;case"--model":g.model=_[D+1],D+=1;break;case"--strategy":g.strategy=_[D+1],D+=1;break;case"--dimensions":g.dimensions=Number(_[D+1]),D+=1;break;case"--semantic":g.semantic=!0;break;case"--context":g.context=!0;break;case"--max-tokens":g.maxTokens=Number(_[D+1]),D+=1;break;case"--max-items":g.maxItems=Number(_[D+1]),D+=1;break;case"--from":g.from=_[D+1],D+=1;break;case"--to":g.to=_[D+1],D+=1;break;case"--rev":g.rev=Number(_[D+1]),D+=1;break;case"--if-version":g.ifVersion=Number(_[D+1]),D+=1;break;case"--since":g.since=_[D+1],D+=1;break;case"--topic":g.topic=_[D+1],D+=1;break;case"--dedupe":g.dedupe=!0;break;case"--generate":g.generate=!0;break;case"--approve-write":g.approveWrite=!0;break;case"--provider":g.provider=_[D+1],D+=1;break;case"--mode":g.mode=_[D+1],D+=1;break;case"--machine":g.machine=_[D+1],D+=1;break;case"--workspace":g.workspace=_[D+1],D+=1;break;case"--api-url":g.apiUrl=_[D+1],D+=1;break;case"--canonical-example":g.canonicalExample=!0;break;case"--api-key":g.apiKey=_[D+1],D+=1;break;case"--email":g.email=_[D+1],D+=1;break;case"--org":g.org=_[D+1],D+=1;break;case"--org-id":g.orgId=_[D+1],D+=1;break;case"--user-id":g.userId=_[D+1],D+=1;break;case"--owner":g.owner=_[D+1],D+=1;break;case"--approved-by":g.approvedBy=_[D+1],D+=1;break;case"--patch-uri":g.patchUri=_[D+1],D+=1;break;case"--domain":g.domain=[...g.domain??[],_[D+1]],D+=1;break;case"--file-results":g.fileResults=!0;break;case"--full":g.full=!0;break;case"--dry-run":g.dryRun=!0;break;case"--fake":g.fake=!0;break;case"--no-tailscale":g.tailscale=!1;break;case"--no-artifact-content":g.artifactContent=!1;break;case"--no-color":g.noColor=!0;break;case"--scope":g.scope=_[D+1],D+=1;break;case"--tables":g.tables=_[D+1],D+=1;break;case"--peer-workspace":g.peerWorkspace=_[D+1],D+=1;break;case"--older-than":g.olderThan=Number(_[D+1]),D+=1;break;case"--empty":g.empty=!0;break;case"--archived":g.archived=!0;break;case"--include-archived":g.includeArchived=!0;break;case"--project":g.project=_[D+1],D+=1;break;case"--contract":g.contract=!0;break;case"--source-ref":g.sourceRef=[...g.sourceRef??[],_[D+1]],D+=1;break;case"--allow-global":g.allowGlobal=!0;break;default:throw Error(`Unknown flag: ${I}. Run 'knowledge --help' for valid options.`)}}return{positional:$,flags:g}}function qw(_){if(!_)return"";return $Y[_]??_}function Bw(_,$){let g=Array.from({length:_.length+1},()=>Array($.length+1).fill(0));for(let U=0;U<=_.length;U+=1)g[U][0]=U;for(let U=0;U<=$.length;U+=1)g[0][U]=U;for(let U=1;U<=_.length;U+=1)for(let D=1;D<=$.length;D+=1){let I=_[U-1]===$[D-1]?0:1;g[U][D]=Math.min(g[U-1][D]+1,g[U][D-1]+1,g[U-1][D-1]+I)}return g[_.length][$.length]}function Vw(_){if(!_)return"";let $=[..._Y,...Object.keys($Y)],g="",U=Number.POSITIVE_INFINITY;for(let D of $){let I=Bw(_,D);if(I<U)U=I,g=D}return U<=3?g:""}function Fw(){return Rw(process.argv[1]??"").replace(/\.(?:js|ts|mjs|cjs)$/,"")==="knowledge"}async function rw(_){if(!s8.includes(_[0]??""))return!1;let $=new V8;return $.name("knowledge").description("Agent-friendly local knowledge CLI with JSON output, pagination, and safe destructive actions"),l8($,{source:"knowledge"}),await $.parseAsync(_,{from:"user"}),!0}function bw(){console.log(`knowledge - local agent knowledge store +`,{encoding:"utf-8",mode:384}),await fv(g,_),await AJ(_,384).catch(()=>{return})}}function nv(_=y8()){return{mode:"local-files",name:"json-events-store",remote:!1,localFiles:!0,localSqlite:!1,postgres:!1,s3:!1,aws:!1,durable:!0,idempotency:"best-effort-local",replayCursors:!0,description:`Local JSON files in ${_}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`}}function c8(_,$={}){if(!Number.isInteger(_)||_<0)throw Error(`Invalid event cursor offset: ${_}`);let g={offset:_,eventId:$.eventId,source:$.source,type:$.type};return`${LJ}${f8.from(JSON.stringify(g),"utf-8").toString("base64url")}`}function QE(_,$={}){if(!_)return 0;if(!_.startsWith(LJ))throw Error(`Invalid local JSON event cursor: ${_}`);let g=_.slice(LJ.length),U;try{U=JSON.parse(f8.from(g,"base64url").toString("utf-8"))}catch{throw Error(`Invalid local JSON event cursor: ${_}`)}let D=U.offset;if(!Number.isInteger(D)||D<0)throw Error(`Invalid local JSON event cursor: ${_}`);return OJ("eventId",U.eventId,$.eventId),OJ("source",U.source,$.source),OJ("type",U.type,$.type),D}function TE(_){if(_===void 0)return yv;if(!Number.isInteger(_)||_<1)throw Error(`Event page limit must be a positive integer, got ${_}`);return Math.min(_,cv)}function Z8(_,$){let g=_;if($.eventId)g=g.filter((U)=>U.id===$.eventId);if($.source)g=g.filter((U)=>U.source===$.source);if($.type)g=g.filter((U)=>U.type===$.type);if($.cursor){let U=QE($.cursor,$);g=g.slice(U)}if($.limit!==void 0)g=g.slice(0,TE($.limit));return g}function OJ(_,$,g){if($!==g)throw Error(`Local JSON event cursor ${_} filter mismatch`)}function H8(_,$){return _.find((g)=>$.id!==void 0&&g.id===$.id||$.dedupeKey!==void 0&&g.dedupeKey===$.dedupeKey)}async function dv(_){let $=new YE(_);await $.init();let[g,U,D]=await Promise.all([$.listChannels(),$.listEvents(),$.listDeliveries()]),I=g.reduce((j,E)=>{return j[E.transport]=(j[E.transport]??0)+1,j},{});return{service:"events",schemaVersion:"1.0",dataDir:$.dataDir,storage:$.runtime,env:{primary:GE,fallback:XE,active:hv()},files:{channels:PJ($.dataDir,"channels.json",g.length),events:PJ($.dataDir,"events.json",U.length),deliveries:PJ($.dataDir,"deliveries.json",D.length)},counts:{channels:g.length,enabledChannels:g.filter((j)=>j.enabled).length,disabledChannels:g.filter((j)=>!j.enabled).length,events:U.length,deliveries:D.length},transports:I,safety:{includesEventPayloads:!1,includesWebhookSecrets:!1,listOutputsRedactSecrets:!0,statusOutputIsMetadataOnly:!0}}}function PJ(_,$,g){let U=FU(_,$);return{path:U,exists:x8(U),records:g}}function iv(_,$){return`${_}.${$}`}function lv(_,$,g){return`sha256=${mv("sha256",_).update(iv($,g)).digest("hex")}`}function m$(){return new Date().toISOString()}function VU(_,$=4096){return _.length>$?`${_.slice(0,$)}...`:_}function pv(_,$){if(!$.webhook)throw Error(`Channel ${$.id} has no webhook config`);let g=JSON.stringify(_),U=_.time,D={"Content-Type":"application/json","User-Agent":"@hasna/events","X-Hasna-Event-Id":_.id,"X-Hasna-Event-Type":_.type,"X-Hasna-Timestamp":U,...$.webhook.headers};if($.webhook.secret)D["X-Hasna-Signature"]=lv($.webhook.secret,U,g);return{body:g,headers:D}}async function ev(_,$,g={}){if(!$.webhook)throw Error(`Channel ${$.id} has no webhook config`);let U=m$(),{body:D,headers:I}=pv(_,$),j=new AbortController,E=setTimeout(()=>j.abort(),$.webhook.timeoutMs??15000);try{let A=await(g.fetchImpl??fetch)($.webhook.url,{method:"POST",headers:I,body:D,signal:j.signal}),O=VU(await A.text());return{attempt:1,status:A.ok?"success":"failed",startedAt:U,completedAt:m$(),responseStatus:A.status,responseBody:O,error:A.ok?void 0:`Webhook returned HTTP ${A.status}`}}catch(A){return{attempt:1,status:"failed",startedAt:U,completedAt:m$(),error:A instanceof Error?A.message:String(A)}}finally{clearTimeout(E)}}async function av(_,$){if(!$.command)throw Error(`Channel ${$.id} has no command config`);let g=m$(),U=JSON.stringify(_),D={...process.env,...$.command.env,HASNA_CHANNEL_ID:$.id,HASNA_EVENT_ID:_.id,HASNA_EVENT_TYPE:_.type,HASNA_EVENT_SOURCE:_.source,HASNA_EVENT_SUBJECT:_.subject??"",HASNA_EVENT_SEVERITY:_.severity,HASNA_EVENT_TIME:_.time,HASNA_EVENT_DEDUPE_KEY:_.dedupeKey??"",HASNA_EVENT_SCHEMA_VERSION:_.schemaVersion,HASNA_EVENT_JSON:U};return new Promise((I)=>{let j=ov($.command.command,$.command.args??[],{cwd:$.command.cwd,env:D,stdio:["pipe","pipe","pipe"]}),E="",A="",O=setTimeout(()=>j.kill("SIGTERM"),$.command.timeoutMs??15000);j.stdin.end(U),j.stdout.on("data",(P)=>{E+=P.toString()}),j.stderr.on("data",(P)=>{A+=P.toString()}),j.on("error",(P)=>{clearTimeout(O),I({attempt:1,status:"failed",startedAt:g,completedAt:m$(),stdout:VU(E),stderr:VU(A),error:P.message})}),j.on("close",(P,W)=>{clearTimeout(O);let z=P===0;I({attempt:1,status:z?"success":"failed",startedAt:g,completedAt:m$(),stdout:VU(E),stderr:VU(A),error:z?void 0:`Command exited with ${W?`signal ${W}`:`code ${P}`}`})})})}async function sv(_,$,g={}){if($.transport==="webhook")return ev(_,$,g);if($.transport==="command")return av(_,$);return{attempt:1,status:"skipped",startedAt:m$(),completedAt:m$(),error:`Unsupported transport: ${$.transport}`}}function k8(_,$,g){let U=g.some((D)=>D.status==="success")?"success":g.every((D)=>D.status==="skipped")?"skipped":"failed";return{id:tv(),eventId:_.id,channelId:$.id,transport:$.transport,status:U,attempts:g,createdAt:g[0]?.startedAt??m$(),completedAt:g.at(-1)?.completedAt??m$()}}class h8 extends Error{eventType;issues;constructor(_,$){let g=$.map((U)=>`${U.path||"<root>"}: ${U.message}`).join("; ");super(`Event validation failed for type "${_}": ${g}`);this.name="EventValidationError",this.eventType=_,this.issues=$}}class n8{definitions=new Map;register(_){return this.definitions.set(_.type,_),this}unregister(_){return this.definitions.delete(_)}has(_){return this.definitions.has(_)}get(_){return this.definitions.get(_)}list(){return[...this.definitions.values()]}validateEvent(_){let $=this.definitions.get(_.type);if(!$)return{ok:!0};return $.validate(_.data,_)}assertEventValid(_){let $=this.validateEvent(_);if(!$.ok)throw new h8(_.type,$.issues)}}var _w=new n8;function SJ(_){return{id:_.id??$w(),source:_.source,type:_.type,time:jw(_.time),subject:_.subject,severity:_.severity??"info",data:_.data??{},message:_.message,dedupeKey:_.dedupeKey,schemaVersion:_.schemaVersion??"1.0",metadata:_.metadata??{}}}class d8{store;redactors;transportOptions;catalog;validateCatalogTypes;constructor(_={}){this.store=_.store??new YE(_.dataDir),this.redactors=_.redactors??[],this.transportOptions={fetchImpl:_.fetchImpl},this.catalog=_.catalog??_w,this.validateCatalogTypes=_.validateCatalogTypes??!1}async addChannel(_){let $=new Date().toISOString();return this.store.addChannel({..._,createdAt:_.createdAt??$,updatedAt:_.updatedAt??$})}async listChannels(){return this.store.listChannels()}async removeChannel(_){return this.store.removeChannel(_)}async emit(_,$={}){let g=$.redactSensitiveData===!1?SJ(_):Uw(SJ(_));if($.validate??this.validateCatalogTypes)this.catalog.assertEventValid(g);let U=await this.appendEvent(g,{dedupe:$.dedupe!==!1});if(U.deduped)return{event:U.event,deliveries:[],deduped:!0};let D=$.deliver===!1?[]:await this.deliver(U.event);return{event:U.event,deliveries:D,deduped:!1}}async listEvents(_={}){if(Object.keys(_).length===0)return this.store.listEvents();return C8(await this.store.listEvents(),_)}async listEventsPage(_={}){if(this.store.listEventsPage)return this.store.listEventsPage(_);let $=C8(await this.store.listEvents(),{eventId:_.eventId,source:_.source,type:_.type}),g=QE(_.cursor,_),U=TE(_.limit),D=$.slice(g,g+U),I=g+D.length,j=I<$.length;return{events:D,cursor:_.cursor,nextCursor:j?c8(I,_):void 0,hasMore:j}}async listDeliveries(){return this.store.listDeliveries()}async deliver(_){let g=(await this.store.listChannels()).filter((D)=>b8(D,_)),U=[];for(let D of g){let I=await this.applyRedaction(_,D),j=await this.deliverWithRetry(I,D);await this.store.appendDelivery(j),U.push(j)}return U}async matchChannel(_,$={}){let g=await this.store.getChannel(_);if(!g)throw Error(`Channel not found: ${_}`);let U=SJ({source:$.source??"hasna.events",type:$.type??"events.test",subject:$.subject??_,severity:$.severity??"info",data:$.data??{test:!0},message:$.message??"Hasna events test delivery",dedupeKey:$.dedupeKey,schemaVersion:$.schemaVersion,metadata:$.metadata,time:$.time,id:$.id}),D=b8(g,U);return{channelId:g.id,matched:D,event:U,filters:g.filters,reason:D?void 0:g.enabled?"event did not match channel filters":"channel is disabled"}}async testChannel(_,$={},g={}){let U=await this.store.getChannel(_);if(!U)throw Error(`Channel not found: ${_}`);let D=await this.matchChannel(_,$),I=D.event;if(g.honorFilters&&!D.matched){let A=new Date().toISOString(),O=k8(I,U,[{attempt:1,status:"skipped",startedAt:A,completedAt:A,error:D.reason}]);return O.metadata={reason:"filter_mismatch"},await this.store.appendDelivery(O),O}let j=await this.applyRedaction(I,U),E=await this.deliverWithRetry(j,U);return await this.store.appendDelivery(E),E}async replay(_={}){let $=_.cursor||_.limit!==void 0?await this.listEventsPage(_):{events:await this.listEvents(_),hasMore:!1};if(_.dryRun)return{events:$.events,deliveries:[],cursor:$.cursor,nextCursor:$.nextCursor,hasMore:$.hasMore};let g=[];for(let U of $.events)g.push(...await this.deliver(U));return{events:$.events,deliveries:g,cursor:$.cursor,nextCursor:$.nextCursor,hasMore:$.hasMore}}async appendEvent(_,$){if(this.store.appendEventOnce)return this.store.appendEventOnce(_,{dedupe:$.dedupe});if($.dedupe){let U=await this.store.findEventByIdentity({id:_.id,dedupeKey:_.dedupeKey});if(U)return{event:U,stored:!1,deduped:!0,identity:{id:U.id,dedupeKey:U.dedupeKey}}}let g=await this.store.appendEvent(_);return{event:g,stored:!0,deduped:!1,identity:{id:g.id,dedupeKey:g.dedupeKey}}}async applyRedaction(_,$){let g=gw(_,$.redact?.paths??[],$.redact?.replacement??"[REDACTED]");for(let U of this.redactors)g=await U(g,$);return g}async deliverWithRetry(_,$){let g=Ew($.retry),U=[];for(let D=0;D<g.maxAttempts;D+=1){let I=await sv(_,$,this.transportOptions);if(I.attempt=D+1,I.status==="failed"&&D+1<g.maxAttempts)I.nextBackoffMs=Math.round(g.backoffMs*g.multiplier**D);if(U.push(I),I.status!=="failed")break;if(I.nextBackoffMs)await Bun.sleep(I.nextBackoffMs)}return k8(_,$,U)}}function gw(_,$,g="[REDACTED]"){if($.length===0)return _;let U=structuredClone(_);for(let D of $)Iw(U,D,g);return U}function m8(_){let $=structuredClone(_);if($.webhook?.secret)$.webhook.secret="[REDACTED]";if($.command?.env)$.command.env=Object.fromEntries(Object.entries($.command.env).map(([g,U])=>[g,i8(g)?"[REDACTED]":U]));return $}function Dw(_){return _.map(m8)}function Uw(_,$="[REDACTED]"){return WJ(_,$)}function i8(_){return/secret|token|password|api[_-]?key|authorization/i.test(_)}function WJ(_,$){if(Array.isArray(_))return _.map((g)=>WJ(g,$));if(!_||typeof _!=="object")return _;return Object.fromEntries(Object.entries(_).map(([g,U])=>[g,i8(g)?$:WJ(U,$)]))}function Iw(_,$,g){let U=$.split("."),D=_;for(let j of U.slice(0,-1)){let E=D[j];if(!E||typeof E!=="object")return;D=E}let I=U.at(-1);if(I&&I in D)D[I]=g}function C8(_,$){let g=_;if($.eventId)g=g.filter((U)=>U.id===$.eventId);if($.source)g=g.filter((U)=>U.source===$.source);if($.type)g=g.filter((U)=>U.type===$.type);if($.cursor)g=g.slice(QE($.cursor,$));if($.limit!==void 0)g=g.slice(0,TE($.limit));return g}function jw(_){if(!_)return new Date().toISOString();return _ instanceof Date?_.toISOString():_}function Ew(_){return{maxAttempts:Math.max(1,_?.maxAttempts??1),backoffMs:Math.max(0,_?.backoffMs??250),multiplier:Math.max(1,_?.multiplier??2)}}function RE(_,$,g=!1){if(!_?.length)return;let U={};for(let D of _){let I=Ow(D,$),j=I.path;if(j in U)throw Error(`Duplicate ${$} filter path: ${j}`);let E=g?Aw(I.rawValue,$):I.rawValue;U[j]=I.negated?{not:E}:E}return U}function Nw(_){let $={};if(_.source)$.source=_.source;if(_.type)$.type=_.type;if(_.subject)$.subject=_.subject;if(_.severity)$.severity=_.severity;let g=v8(RE(_.data,"data"),RE(_.dataJson,"data-json",!0)),U=v8(RE(_.metadata,"metadata"),RE(_.metadataJson,"metadata-json",!0));if(Object.keys(g).length>0)$.data=g;if(Object.keys(U).length>0)$.metadata=U;return Object.keys($).length>0?[$]:void 0}function v8(..._){let $={};for(let g of _){if(!g)continue;for(let[U,D]of Object.entries(g)){if(U in $)throw Error(`Duplicate filter path: ${U}`);$[U]=D}}return $}function Aw(_,$){let g=JSON.parse(_);if(g===null||typeof g==="string"||typeof g==="number"||typeof g==="boolean"||Array.isArray(g)&&g.every((U)=>typeof U==="string"))return g;throw Error(`${$} filter JSON values must be string, string[], number, boolean, or null`)}function Ow(_,$){let g=_.indexOf("!=");if(g>0)return{path:_.slice(0,g),rawValue:_.slice(g+2),negated:!0};let U=_.indexOf("=");if(U<=0)throw Error(`Invalid ${$} filter, expected path=value or path!=value: ${_}`);return{path:_.slice(0,U),rawValue:_.slice(U+1),negated:!1}}var Pw=100;function q0(_,$){if(!_)return $;let g=JSON.parse(_);if(!g||typeof g!=="object"||Array.isArray(g))throw Error("Expected a JSON object");return g}function Sw(_){if(!_?.length)return;let $={};for(let g of _){let U=g.indexOf("=");if(U===-1)throw Error(`Invalid header, expected name=value: ${g}`);$[g.slice(0,U)]=g.slice(U+1)}return $}function e6(_){if(_.createClient)return _.createClient();return new d8({store:new YE(_.dataDir)})}function _4(_,$,g){if($)console.log(JSON.stringify(_,null,2));else console.log(g)}function w8(_,$){let g=_ instanceof Error?_.message:String(_);if($)console.log(JSON.stringify({error:g},null,2));else console.error(g);process.exitCode=1}function u8(_){return Boolean(_?.json||_?.opts?.().json||_?.optsWithGlobals?.().json||_?.parent?.opts?.().json||_?.parent?.optsWithGlobals?.().json)}function G6(_,$){return u8(_)||u8($)}function Lw(_,$){let g=_.command($.channelsCommandName??"channels").description("Manage Hasna event channels");return g.command("add").description("Add or replace a channel").argument("<target>","Webhook URL or command binary").requiredOption("--id <id>","Channel identifier").option("--transport <kind>","Transport kind: webhook or command","webhook").option("--name <name>","Display name").option("--type <pattern>","Event type filter, e.g. todos.task.*").option("--source <pattern>","Event source filter").option("--subject <pattern>","Event subject filter").option("--severity <pattern>","Event severity filter").option("--data <path=value...>","Event data field filter; string values, path!=value negatives, array-member matching, dot paths, * segment wildcard, ** recursive wildcard",sg,[]).option("--metadata <path=value...>","Event metadata field filter; string values, path!=value negatives, array-member matching, dot paths, * segment wildcard, ** recursive wildcard",sg,[]).option("--data-json <path=json...>","Event data field filter with typed JSON value; path!=json negatives supported",sg,[]).option("--metadata-json <path=json...>","Event metadata field filter with typed JSON value; path!=json negatives supported",sg,[]).option("--secret <secret>","Webhook HMAC secret").option("--header <name=value...>","Webhook header",sg,[]).option("--arg <arg...>","Command argument",sg,[]).option("--timeout-ms <ms>","Transport timeout in milliseconds",rU).option("--retry-attempts <n>","Maximum delivery attempts",rU).option("--retry-backoff-ms <ms>","Initial retry backoff in milliseconds",rU).option("--redact <path...>","Event field path to redact before delivery",sg,[]).option("--disabled","Create channel disabled",!1).option("-j, --json","Print JSON output",!1).action(async(U,D,I)=>{let j=new Date().toISOString(),E={id:D.id,name:D.name,enabled:!D.disabled,transport:D.transport,filters:Nw(D),retry:D.retryAttempts||D.retryBackoffMs?{maxAttempts:D.retryAttempts,backoffMs:D.retryBackoffMs}:void 0,redact:D.redact?.length?{paths:D.redact}:void 0,createdAt:j,updatedAt:j};if(D.transport==="webhook")E.webhook={url:U,secret:D.secret,headers:Sw(D.header),timeoutMs:D.timeoutMs};else if(D.transport==="command")E.command={command:U,args:D.arg??[],timeoutMs:D.timeoutMs};else throw Error(`Transport ${D.transport} is reserved for future use and cannot be added yet`);let A=await e6($).addChannel(E);_4(m8(A),G6(D,I),`Added ${A.transport} channel ${A.id}`)}),g.command("list").description("List configured channels").option("-j, --json","Print JSON output",!1).action(async(U,D)=>{let I=await e6($).listChannels();if(G6(U,D)){console.log(JSON.stringify(Dw(I),null,2));return}if(!I.length){console.log("No channels configured.");return}for(let j of I)console.log(`${j.id} ${j.enabled?"enabled":"disabled"} ${j.transport} ${j.webhook?.url??j.command?.command??j.transport}`)}),g.command("status").description("Show events channel storage status").option("-j, --json","Print JSON output",!1).action(async(U,D)=>{let I=await dv($.dataDir);_4(I,G6(U,D),`events dataDir: ${I.dataDir}`)}),g.command("remove").description("Remove a channel").argument("<id>","Channel identifier").option("-j, --json","Print JSON output",!1).action(async(U,D,I)=>{let j=await e6($).removeChannel(U);_4({removed:j},G6(D,I),j?`Removed ${U}`:`Channel not found: ${U}`)}),g.command("test").description("Send a test event to one channel").argument("<id>","Channel identifier").option("--source <source>","Event source override").option("--type <type>","Event type","events.test").option("--subject <subject>","Event subject").option("--message <message>","Event message","Hasna events test delivery").option("--data <json>","Event data JSON object").option("--metadata <json>","Event metadata JSON object").option("--honor-filters","Skip delivery when the sample event does not match channel filters",!1).option("-j, --json","Print JSON output",!1).action(async(U,D,I)=>{let j=G6(D,I);try{let E=await e6($).testChannel(U,{source:D.source??$.source,type:D.type,subject:D.subject??U,message:D.message,data:q0(D.data,{test:!0}),metadata:q0(D.metadata,{})},{honorFilters:D.honorFilters});_4(E,j,`${E.status}: ${E.channelId}`)}catch(E){w8(E,j)}}),g.command("match").description("Check whether a sample event matches one channel without delivering").argument("<id>","Channel identifier").option("--source <source>","Event source override").option("--type <type>","Event type","events.test").option("--subject <subject>","Event subject").option("--message <message>","Event message","Hasna events match preview").option("--data <json>","Event data JSON object").option("--metadata <json>","Event metadata JSON object").option("-j, --json","Print JSON output",!1).action(async(U,D,I)=>{let j=G6(D,I);try{let E=await e6($).matchChannel(U,{source:D.source??$.source,type:D.type,subject:D.subject??U,message:D.message,data:q0(D.data,{test:!0}),metadata:q0(D.metadata,{})});_4(E,j,`${E.matched?"matched":"skipped"}: ${E.channelId}`)}catch(E){w8(E,j)}}),g}function Ww(_,$){let g=_.command($.eventsCommandName??"events").description("Emit, list, and replay Hasna events");g.command("emit").description("Emit an event from this app").argument("<type>","Event type").option("--source <source>","Event source override").option("--subject <subject>","Event subject").option("--severity <severity>","Event severity","info").option("--message <message>","Event message").option("--dedupe-key <key>","Dedupe key").option("--data <json>","Event data JSON object").option("--metadata <json>","Event metadata JSON object").option("--no-deliver","Record without delivering").option("--no-dedupe","Allow duplicate id/dedupeKey events").option("-j, --json","Print JSON output",!1).action(async(D,I,j)=>{let E=await e6($).emit({source:I.source??$.source,type:D,subject:I.subject,severity:I.severity,message:I.message,dedupeKey:I.dedupeKey,data:q0(I.data,{}),metadata:q0(I.metadata,{})},{deliver:I.deliver,dedupe:I.dedupe});_4(E,G6(I,j),`${E.deduped?"Deduped":"Emitted"} ${E.event.id} to ${E.deliveries.length} channel(s)`)});let U=$.defaultEventListLimit??Pw;return g.command("list").description("List recorded events").option("--source <source>","Filter by source").option("--type <type>","Filter by type").option("--limit <n>",`Limit to the most recent <n> events (default ${U}; use 0 for all)`,rU,U).option("-j, --json","Print JSON output",!1).action(async(D,I)=>{let j=await e6($).listEvents();if(D.source)j=j.filter((E)=>E.source===D.source);if(D.type)j=j.filter((E)=>E.type===D.type);if(D.limit)j=j.slice(-D.limit);if(G6(D,I)){console.log(JSON.stringify(j,null,2));return}if(!j.length){console.log("No events recorded.");return}for(let E of j)console.log(`${E.time} ${E.id} ${E.source} ${E.type} ${E.severity}`)}),g.command("replay").description("Replay recorded events").option("--id <id>","Replay one event id").option("--source <source>","Filter by source").option("--type <type>","Filter by type").option("--cursor <cursor>","Opaque replay cursor from a previous page").option("--limit <n>","Maximum events to replay",rU).option("--dry-run","Preview without delivery",!1).option("-j, --json","Print JSON output",!1).action(async(D,I)=>{let j=await e6($).replay({eventId:D.id,source:D.source,type:D.type,cursor:D.cursor,limit:D.limit,dryRun:D.dryRun});_4(j,G6(D,I),Jw(j.events.length,j.deliveries.length,j.nextCursor))}),g}function l8(_,$){Lw(_,$),Ww(_,$)}function rU(_){let $=Number(_);if(!Number.isFinite($))throw Error(`Expected a number, got ${_}`);return $}function sg(_,$){return $.push(_),$}function Jw(_,$,g){let U=g?`, next cursor: ${g}`:"";return`Replayed ${_} event(s), ${$} delivery result(s)${U}`}import{basename as Rw}from"path";var H$={name:"@hasna/knowledge",version:"0.2.102",description:"Agent-friendly local knowledge CLI with JSON output, pagination, and safe destructive actions",type:"module",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"},"./storage":{import:"./dist/storage.js",types:"./dist/storage.d.ts"},"./serve":{import:"./dist/serve.js",types:"./dist/serve.d.ts"}},main:"./dist/index.js",types:"./dist/index.d.ts",bin:{knowledge:"bin/knowledge.js","knowledge-mcp":"bin/knowledge-mcp.js","knowledge-serve":"bin/knowledge-serve.js"},files:["bin","dist","scripts/apply-cloud-migrations.mjs","scripts/live-private-query.mjs","scripts/lib/remote-temp-dir.mjs","scripts/smoke-machine-sync-release.mjs","scripts/smoke-machines-adapter.mjs","scripts/smoke-open-files-installed-boundary.mjs","scripts/strip-generated-trailing-whitespace.mjs","scripts/verify-generated-artifacts.mjs","docs/architecture/ai-native-knowledge-base.md","docs/architecture/hosted-wrapper-responsibilities.md","docs/architecture/hybrid-semantic-search.md","docs/architecture/machine-sync-schema.md","docs/examples/app-project-wiki-standard.md","docs/examples/company-wiki-workflow.md","docs/migration/global-rules-provenance-import.md","docs/migration/json-to-sqlite.md","LICENSE","README.md"],scripts:{test:"bun test","test:cli":"bun test tests/cli.test.ts","test:package":"bun test tests/package-release.test.ts","release:pack:check":"node scripts/validate-public-package.mjs","smoke:machines-adapter":"bun scripts/smoke-machines-adapter.mjs","smoke:machine-sync-release":"bun scripts/smoke-machine-sync-release.mjs","smoke:open-files-installed-boundary":"bun scripts/smoke-open-files-installed-boundary.mjs","migrate:cloud":"bun scripts/apply-cloud-migrations.mjs","live:private-query":"bun scripts/live-private-query.mjs",serve:"bun src/serve-entry.ts","verify:generated":"bun scripts/verify-generated-artifacts.mjs","contracts:conformance":"contracts conformance fixtures",build:"rm -rf dist && bun build --target=bun --outfile=bin/knowledge.js --minify --external pg --external @hasna/machines --external @hasna/machines/consumer --external @aws-sdk/client-s3 --external @aws-sdk/credential-providers --external ai --external @ai-sdk/openai --external @ai-sdk/anthropic --external @ai-sdk/deepseek src/cli.ts && bun build --target=bun --outfile=bin/knowledge-mcp.js --external pg --external @hasna/machines --external @hasna/machines/consumer --external @modelcontextprotocol/sdk --external @aws-sdk/client-s3 --external @aws-sdk/credential-providers --external ai --external @ai-sdk/openai --external @ai-sdk/anthropic --external @ai-sdk/deepseek src/mcp.js && bun build --target=bun --outfile=bin/knowledge-serve.js --external pg --external @hasna/machines --external @hasna/machines/consumer --external @aws-sdk/client-s3 --external @aws-sdk/credential-providers --external ai --external @ai-sdk/openai --external @ai-sdk/anthropic --external @ai-sdk/deepseek src/serve-entry.ts && bun build ./src/index.ts ./src/storage.ts ./src/serve.ts --outdir ./dist --target bun --external pg --external @hasna/machines --external @hasna/machines/consumer --external @aws-sdk/client-s3 --external @aws-sdk/credential-providers --external ai --external @ai-sdk/openai --external @ai-sdk/anthropic --external @ai-sdk/deepseek && bun scripts/strip-generated-trailing-whitespace.mjs && bunx tsc -p tsconfig.build.json",prepublishOnly:"bun run contracts:conformance && contracts no-cloud-scan . && bun run build && node scripts/validate-public-package.mjs"},keywords:["knowledge","cli","agents","json","notes","local","store"],license:"Apache-2.0",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},repository:{type:"git",url:"git+https://github.com/hasna/knowledge.git"},bugs:{url:"https://github.com/hasna/knowledge/issues"},author:"Hasna Inc. <hasna@example.com>",engines:{bun:">=1.0",node:">=18"},dependencies:{"@ai-sdk/anthropic":"^3.0.81","@ai-sdk/deepseek":"^2.0.35","@ai-sdk/openai":"^3.0.68","@aws-sdk/client-s3":"^3.1063.0","@aws-sdk/credential-providers":"^3.1063.0","@hasna/events":"^0.1.3","@modelcontextprotocol/sdk":"^1.29.0","@types/json-schema":"^7.0.15",ai:"^6.0.197",commander:"^13.1.0",pg:"^8.16.3",zod:"^4.3.6"},devDependencies:{"@electric-sql/pglite":"^0.5.4","@hasna/contracts":"0.8.5","@types/bun":"^1.3.14","@types/pg":"^8.15.6"}};var t8={debug:0,info:1,warn:2,error:3},Gw=()=>{if(process.env.DEBUG)return"debug";if(process.env.LOG_LEVEL==="debug")return"debug";if(process.env.LOG_LEVEL==="warn")return"warn";if(process.env.LOG_LEVEL==="error")return"error";return"info"};function g4(_,$,g){if(t8[_]<t8[Gw()])return;let U={debug:"[DEBUG]",info:"[INFO]",warn:"[WARN]",error:"[ERROR]"}[_],D=g?`${U} ${$} ${JSON.stringify(g)}`:`${U} ${$}`;if(_==="error")console.error(D);else console.error(D)}var s8=["events","webhooks"],_Y=["add","list","get","delete","update","archive","restore","upsert","untag","versions","diff","export","prune","dedupe","stats","inventory","project-panel","paths","mode","guarded","setup","auth","storage","machines","sync","db","wiki","app-wiki","source","ingest","reindex","search","context","proposals","web","ask","build","embeddings","providers","safety","help",...s8],$Y={ls:"list",rm:"delete",edit:"update",unarchive:"restore"},Xw=/^k_[A-Za-z0-9][A-Za-z0-9_-]*$/;async function Yw(_,$,g){if(/\s/.test($))return!0;if(_.length<=1)return!1;let U=_[1]??"";if(Xw.test(U))return!1;return await g.get(U)===null}function Qw(_){let $=new Set,g=[];for(let U of _){let D=U.toLowerCase();if($.has(D))continue;$.add(D),g.push(U)}return g}function o8(_,$){let g=new Set((_??[]).map((U)=>U.toLowerCase()));return $.filter((U)=>!g.has(U.toLowerCase()))}function JJ(_,$,g){if(g===void 0)return{..._,message:$};return{..._,added:g.length,message:`${$} (added ${g.length} tag${g.length===1?"":"s"})`}}function Tw(_,$){if($===void 0)throw Error("Missing value for --tag. Example: knowledge add <title> <content> -t <tag> -t <tag>");let g=$.split(",").map((U)=>U.trim()).filter((U)=>U.length>0);if(g.length===0)throw Error(`Invalid --tag value ${JSON.stringify($)}: no tag name found. Example: knowledge add <title> <content> -t <tag> -t <tag>`);return Qw([..._??[],...g])}function Kw(_){let $=[],g={},U=!1;for(let D=0;D<_.length;D+=1){let I=_[D];if(U){$.push(I);continue}if(I==="--"){U=!0;continue}if(!I.startsWith("-")||$[0]==="add"&&$.length===2&&I.startsWith("---")){$.push(I);continue}switch(I){case"--json":g.json=!0;break;case"--verbose":g.verbose=!0;break;case"--yes":case"-y":g.yes=!0;break;case"--help":case"-h":g.help=!0;break;case"--version":case"-v":g.version=!0;break;case"--desc":g.desc=!0;break;case"--page":case"-p":g.page=Number(_[D+1]),D+=1;break;case"--limit":case"-l":g.limit=Number(_[D+1]),D+=1;break;case"--search":case"-s":g.search=_[D+1],D+=1;break;case"--sort":g.sort=_[D+1],D+=1;break;case"--id":g.id=_[D+1],D+=1;break;case"--store":g.store=_[D+1],D+=1;break;case"--title":g.title=_[D+1],D+=1;break;case"--content":g.content=_[D+1],D+=1;break;case"--url":g.url=_[D+1],D+=1;break;case"--tag":case"-t":g.tag=Tw(g.tag,_[D+1]),g.tagRaw=[...g.tagRaw??[],_[D+1]],D+=1;break;case"--format":g.format=_[D+1],D+=1;break;case"--completions":g.completions=_[D+1],D+=1;break;case"--purpose":g.purpose=_[D+1],D+=1;break;case"--model":g.model=_[D+1],D+=1;break;case"--strategy":g.strategy=_[D+1],D+=1;break;case"--dimensions":g.dimensions=Number(_[D+1]),D+=1;break;case"--semantic":g.semantic=!0;break;case"--context":g.context=!0;break;case"--max-tokens":g.maxTokens=Number(_[D+1]),D+=1;break;case"--max-items":g.maxItems=Number(_[D+1]),D+=1;break;case"--from":g.from=_[D+1],D+=1;break;case"--to":g.to=_[D+1],D+=1;break;case"--rev":g.rev=Number(_[D+1]),D+=1;break;case"--if-version":g.ifVersion=Number(_[D+1]),D+=1;break;case"--since":g.since=_[D+1],D+=1;break;case"--topic":g.topic=_[D+1],D+=1;break;case"--dedupe":g.dedupe=!0;break;case"--generate":g.generate=!0;break;case"--approve-write":g.approveWrite=!0;break;case"--provider":g.provider=_[D+1],D+=1;break;case"--mode":g.mode=_[D+1],D+=1;break;case"--machine":g.machine=_[D+1],D+=1;break;case"--workspace":g.workspace=_[D+1],D+=1;break;case"--api-url":g.apiUrl=_[D+1],D+=1;break;case"--canonical-example":g.canonicalExample=!0;break;case"--api-key":g.apiKey=_[D+1],D+=1;break;case"--email":g.email=_[D+1],D+=1;break;case"--org":g.org=_[D+1],D+=1;break;case"--org-id":g.orgId=_[D+1],D+=1;break;case"--user-id":g.userId=_[D+1],D+=1;break;case"--owner":g.owner=_[D+1],D+=1;break;case"--approved-by":g.approvedBy=_[D+1],D+=1;break;case"--patch-uri":g.patchUri=_[D+1],D+=1;break;case"--domain":g.domain=[...g.domain??[],_[D+1]],D+=1;break;case"--file-results":g.fileResults=!0;break;case"--full":g.full=!0;break;case"--dry-run":g.dryRun=!0;break;case"--fake":g.fake=!0;break;case"--no-tailscale":g.tailscale=!1;break;case"--no-artifact-content":g.artifactContent=!1;break;case"--no-color":g.noColor=!0;break;case"--scope":g.scope=_[D+1],D+=1;break;case"--tables":g.tables=_[D+1],D+=1;break;case"--peer-workspace":g.peerWorkspace=_[D+1],D+=1;break;case"--older-than":g.olderThan=Number(_[D+1]),D+=1;break;case"--empty":g.empty=!0;break;case"--archived":g.archived=!0;break;case"--include-archived":g.includeArchived=!0;break;case"--project":g.project=_[D+1],D+=1;break;case"--contract":g.contract=!0;break;case"--source-ref":g.sourceRef=[...g.sourceRef??[],_[D+1]],D+=1;break;case"--allow-global":g.allowGlobal=!0;break;default:throw Error(`Unknown flag: ${I}. Run 'knowledge --help' for valid options.`)}}return{positional:$,flags:g}}function qw(_){if(!_)return"";return $Y[_]??_}function Bw(_,$){let g=Array.from({length:_.length+1},()=>Array($.length+1).fill(0));for(let U=0;U<=_.length;U+=1)g[U][0]=U;for(let U=0;U<=$.length;U+=1)g[0][U]=U;for(let U=1;U<=_.length;U+=1)for(let D=1;D<=$.length;D+=1){let I=_[U-1]===$[D-1]?0:1;g[U][D]=Math.min(g[U-1][D]+1,g[U][D-1]+1,g[U-1][D-1]+I)}return g[_.length][$.length]}function Vw(_){if(!_)return"";let $=[..._Y,...Object.keys($Y)],g="",U=Number.POSITIVE_INFINITY;for(let D of $){let I=Bw(_,D);if(I<U)U=I,g=D}return U<=3?g:""}function Fw(){return Rw(process.argv[1]??"").replace(/\.(?:js|ts|mjs|cjs)$/,"")==="knowledge"}async function rw(_){if(!s8.includes(_[0]??""))return!1;let $=new V8;return $.name("knowledge").description("Agent-friendly local knowledge CLI with JSON output, pagination, and safe destructive actions"),l8($,{source:"knowledge"}),await $.parseAsync(_,{from:"user"}),!0}function bw(){console.log(`knowledge - local agent knowledge store Usage: knowledge <command> [options] diff --git a/package.json b/package.json index ab9e0b5..819880f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hasna/knowledge", - "version": "0.2.101", + "version": "0.2.102", "description": "Agent-friendly local knowledge CLI with JSON output, pagination, and safe destructive actions", "type": "module", "exports": {