From 0a5266aa1d611c9ebb4f1804dca6bc9139582934 Mon Sep 17 00:00:00 2001 From: Andrei Hasna Date: Sat, 8 Aug 2026 12:16:14 +0300 Subject: [PATCH] chore(release): knowledge 0.2.97 Release @hasna/knowledge 0.2.97 with the guarded-writer env binding fix from PR #76. Refs KNO-00018; refs #76. Agent: cassianus --- CHANGELOG.md | 2 +- bin/knowledge-mcp.js | 2 +- bin/knowledge.js | 2 +- package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b98090..f201cc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 0.2.97 - Fix the FCAME-1 guarded writer so `createKnowledgeGuardedWriter({ env })` authenticates guarded HTTP requests with the API endpoint and credential from diff --git a/bin/knowledge-mcp.js b/bin/knowledge-mcp.js index fcd3dd9..bd884f0 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.96", + version: "0.2.97", 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 7724fbe..b882050 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 Y8=UY(G8(),1),{program:Jm,createCommand:Pm,createArgument:zm,createOption:Sm,CommanderError:Wm,InvalidArgumentError:Xm,InvalidOptionArgumentError:Rm,Command:Q8,Argument:Gm,Option:Ym,Help:Qm}=Y8.default;import{chmod as Uz,mkdir as Kv,readFile as Fv,rename as Mv,writeFile as V8}from"fs/promises";import{Buffer as C8}from"buffer";import{existsSync as r8}from"fs";import{homedir as bv}from"os";import{join as MU}from"path";import{createHmac as vv,timingSafeEqual as bm}from"crypto";import{randomUUID as uv}from"crypto";import{spawn as xv}from"child_process";import{randomUUID as mv}from"crypto";function Rv(_,$){return $.split(".").reduce((D,U)=>{if(D&&typeof D==="object"&&U in D)return D[U];return},_)}function Gv(_,$){let D=[],U=(I)=>{if(!D.some((j)=>Object.is(j,I)))D.push(I)};if($.includes(".")&&$ in _)U(_[$]);let g=Rv(_,$);if(g!==void 0||!$.includes("."))U(g);return D}function Yv(_,$={}){let D="";for(let U=0;U<_.length;U+=1){let g=_[U];if(g==="*")if(_[U+1]==="*")D+=".*",U+=1;else D+=$.segmentSafe?"[^/]*":".*";else D+=g.replace(/[|\\{}()[\]^$+?.]/g,"\\$&")}return new RegExp(`^${D}$`)}function KU(_,$,D={}){if($===void 0)return!0;if(_===void 0)return!1;return(Array.isArray($)?$:[$]).some((g)=>Yv(g,D).test(_))}function T8(_,$){if(!$)return!0;return Object.entries($).every(([D,U])=>{let g=Gv(_,D);return Qv(g,U,D)})}function Qv(_,$,D){if(Bv($))return!_.some((U)=>q8(U,$.not,D));return _.some((U)=>q8(U,$,D))}function q8(_,$,D){if(typeof $==="string"||Array.isArray($))return Tv(_).some((U)=>KU(U,$,{segmentSafe:D.endsWith("_path")||D.endsWith(".path")}));if(Array.isArray(_))return _.some((U)=>U===$);return _===$}function Tv(_){if(_===void 0)return[];if(Array.isArray(_))return _.flatMap(($)=>qv($)?[String($)]:[]);return[String(_)]}function qv(_){return _===null||typeof _==="string"||typeof _==="number"||typeof _==="boolean"}function Bv(_){return Boolean(_&&typeof _==="object"&&!Array.isArray(_)&&"not"in _)}function Vv(_,$){return KU(_.source,$.source)&&KU(_.type,$.type)&&KU(_.subject,$.subject)&&KU(_.severity,$.severity)&&T8(_.data,$.data)&&T8(_.metadata,$.metadata)}function B8(_,$){if(!_.enabled)return!1;if(!_.filters||_.filters.length===0)return!0;return _.filters.some((D)=>Vv($,D))}var RN="HASNA_EVENTS_DIR",GN="HASNA_EVENTS_HOME",Ez="local-json-v1:",Zv=100,Hv=1000;function v8(_){return _||process.env[RN]||process.env[GN]||MU(bv(),".hasna","events")}function kv(){if(process.env[RN])return RN;if(process.env[GN])return GN;return null}class YN{dataDir;runtime;channelsPath;eventsPath;deliveriesPath;constructor(_=v8()){this.dataDir=_,this.runtime=Cv(_),this.channelsPath=MU(_,"channels.json"),this.eventsPath=MU(_,"events.json"),this.deliveriesPath=MU(_,"deliveries.json")}async init(){await Kv(this.dataDir,{recursive:!0,mode:448}),await Uz(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,[]),D=$.findIndex((U)=>U.id===_.id);if(D>=0)$[D]={..._,createdAt:$[D].createdAt,updatedAt:new Date().toISOString()};else $.push(_);return await this.writeJson(this.channelsPath,$),D>=0?$[D]:_}async listChannels(){return await this.init(),this.readJson(this.channelsPath,[])}async getChannel(_){return(await this.listChannels()).find((D)=>D.id===_)}async removeChannel(_){await this.init();let $=await this.readJson(this.channelsPath,[]),D=$.filter((U)=>U.id!==_);return await this.writeJson(this.channelsPath,D),D.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 D=await this.readJson(this.eventsPath,[]);if($.dedupe!==!1){let g=F8(D,{id:_.id,dedupeKey:_.dedupeKey});if(g)return{event:g,stored:!1,deduped:!0,identity:{id:g.id,dedupeKey:g.dedupeKey}}}return D.push(_),await this.writeJson(this.eventsPath,D),{event:_,stored:!0,deduped:!1,identity:{id:_.id,dedupeKey:_.dedupeKey}}}async listEvents(_={}){await this.init();let $=await this.readJson(this.eventsPath,[]);return K8($,_)}async listEventsPage(_={}){await this.init();let $=await this.readJson(this.eventsPath,[]),D=K8($,{eventId:_.eventId,source:_.source,type:_.type}),U=QN(_.cursor,_),g=TN(_.limit),I=D.slice(U,U+g),j=U+I.length,N=j{return})}async readJson(_,$){try{let D=await Fv(_,"utf-8");if(!D.trim())return $;return JSON.parse(D)}catch(D){if(D.code==="ENOENT")return $;throw D}}async writeJson(_,$){let D=`${_}.${process.pid}.${Date.now()}.tmp`;await V8(D,`${JSON.stringify($,null,2)} -`,{encoding:"utf-8",mode:384}),await Mv(D,_),await Uz(_,384).catch(()=>{return})}}function Cv(_=v8()){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 f8(_,$={}){if(!Number.isInteger(_)||_<0)throw Error(`Invalid event cursor offset: ${_}`);let D={offset:_,eventId:$.eventId,source:$.source,type:$.type};return`${Ez}${C8.from(JSON.stringify(D),"utf-8").toString("base64url")}`}function QN(_,$={}){if(!_)return 0;if(!_.startsWith(Ez))throw Error(`Invalid local JSON event cursor: ${_}`);let D=_.slice(Ez.length),U;try{U=JSON.parse(C8.from(D,"base64url").toString("utf-8"))}catch{throw Error(`Invalid local JSON event cursor: ${_}`)}let g=U.offset;if(!Number.isInteger(g)||g<0)throw Error(`Invalid local JSON event cursor: ${_}`);return Iz("eventId",U.eventId,$.eventId),Iz("source",U.source,$.source),Iz("type",U.type,$.type),g}function TN(_){if(_===void 0)return Zv;if(!Number.isInteger(_)||_<1)throw Error(`Event page limit must be a positive integer, got ${_}`);return Math.min(_,Hv)}function K8(_,$){let D=_;if($.eventId)D=D.filter((U)=>U.id===$.eventId);if($.source)D=D.filter((U)=>U.source===$.source);if($.type)D=D.filter((U)=>U.type===$.type);if($.cursor){let U=QN($.cursor,$);D=D.slice(U)}if($.limit!==void 0)D=D.slice(0,TN($.limit));return D}function Iz(_,$,D){if($!==D)throw Error(`Local JSON event cursor ${_} filter mismatch`)}function F8(_,$){return _.find((D)=>$.id!==void 0&&D.id===$.id||$.dedupeKey!==void 0&&D.dedupeKey===$.dedupeKey)}async function rv(_){let $=new YN(_);await $.init();let[D,U,g]=await Promise.all([$.listChannels(),$.listEvents(),$.listDeliveries()]),I=D.reduce((j,N)=>{return j[N.transport]=(j[N.transport]??0)+1,j},{});return{service:"events",schemaVersion:"1.0",dataDir:$.dataDir,storage:$.runtime,env:{primary:RN,fallback:GN,active:kv()},files:{channels:jz($.dataDir,"channels.json",D.length),events:jz($.dataDir,"events.json",U.length),deliveries:jz($.dataDir,"deliveries.json",g.length)},counts:{channels:D.length,enabledChannels:D.filter((j)=>j.enabled).length,disabledChannels:D.filter((j)=>!j.enabled).length,events:U.length,deliveries:g.length},transports:I,safety:{includesEventPayloads:!1,includesWebhookSecrets:!1,listOutputsRedactSecrets:!0,statusOutputIsMetadataOnly:!0}}}function jz(_,$,D){let U=MU(_,$);return{path:U,exists:r8(U),records:D}}function fv(_,$){return`${_}.${$}`}function wv(_,$,D){return`sha256=${vv("sha256",_).update(fv($,D)).digest("hex")}`}function i$(){return new Date().toISOString()}function FU(_,$=4096){return _.length>$?`${_.slice(0,$)}...`:_}function yv(_,$){if(!$.webhook)throw Error(`Channel ${$.id} has no webhook config`);let D=JSON.stringify(_),U=_.time,g={"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)g["X-Hasna-Signature"]=wv($.webhook.secret,U,D);return{body:D,headers:g}}async function hv(_,$,D={}){if(!$.webhook)throw Error(`Channel ${$.id} has no webhook config`);let U=i$(),{body:g,headers:I}=yv(_,$),j=new AbortController,N=setTimeout(()=>j.abort(),$.webhook.timeoutMs??15000);try{let O=await(D.fetchImpl??fetch)($.webhook.url,{method:"POST",headers:I,body:g,signal:j.signal}),A=FU(await O.text());return{attempt:1,status:O.ok?"success":"failed",startedAt:U,completedAt:i$(),responseStatus:O.status,responseBody:A,error:O.ok?void 0:`Webhook returned HTTP ${O.status}`}}catch(O){return{attempt:1,status:"failed",startedAt:U,completedAt:i$(),error:O instanceof Error?O.message:String(O)}}finally{clearTimeout(N)}}async function cv(_,$){if(!$.command)throw Error(`Channel ${$.id} has no command config`);let D=i$(),U=JSON.stringify(_),g={...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=xv($.command.command,$.command.args??[],{cwd:$.command.cwd,env:g,stdio:["pipe","pipe","pipe"]}),N="",O="",A=setTimeout(()=>j.kill("SIGTERM"),$.command.timeoutMs??15000);j.stdin.end(U),j.stdout.on("data",(L)=>{N+=L.toString()}),j.stderr.on("data",(L)=>{O+=L.toString()}),j.on("error",(L)=>{clearTimeout(A),I({attempt:1,status:"failed",startedAt:D,completedAt:i$(),stdout:FU(N),stderr:FU(O),error:L.message})}),j.on("close",(L,z)=>{clearTimeout(A);let W=L===0;I({attempt:1,status:W?"success":"failed",startedAt:D,completedAt:i$(),stdout:FU(N),stderr:FU(O),error:W?void 0:`Command exited with ${z?`signal ${z}`:`code ${L}`}`})})})}async function nv(_,$,D={}){if($.transport==="webhook")return hv(_,$,D);if($.transport==="command")return cv(_,$);return{attempt:1,status:"skipped",startedAt:i$(),completedAt:i$(),error:`Unsupported transport: ${$.transport}`}}function M8(_,$,D){let U=D.some((g)=>g.status==="success")?"success":D.every((g)=>g.status==="skipped")?"skipped":"failed";return{id:uv(),eventId:_.id,channelId:$.id,transport:$.transport,status:U,attempts:D,createdAt:D[0]?.startedAt??i$(),completedAt:D.at(-1)?.completedAt??i$()}}class w8 extends Error{eventType;issues;constructor(_,$){let D=$.map((U)=>`${U.path||""}: ${U.message}`).join("; ");super(`Event validation failed for type "${_}": ${D}`);this.name="EventValidationError",this.eventType=_,this.issues=$}}class u8{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 w8(_.type,$.issues)}}var dv=new u8;function Nz(_){return{id:_.id??mv(),source:_.source,type:_.type,time:pv(_.time),subject:_.subject,severity:_.severity??"info",data:_.data??{},message:_.message,dedupeKey:_.dedupeKey,schemaVersion:_.schemaVersion??"1.0",metadata:_.metadata??{}}}class x8{store;redactors;transportOptions;catalog;validateCatalogTypes;constructor(_={}){this.store=_.store??new YN(_.dataDir),this.redactors=_.redactors??[],this.transportOptions={fetchImpl:_.fetchImpl},this.catalog=_.catalog??dv,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 D=$.redactSensitiveData===!1?Nz(_):tv(Nz(_));if($.validate??this.validateCatalogTypes)this.catalog.assertEventValid(D);let U=await this.appendEvent(D,{dedupe:$.dedupe!==!1});if(U.deduped)return{event:U.event,deliveries:[],deduped:!0};let g=$.deliver===!1?[]:await this.deliver(U.event);return{event:U.event,deliveries:g,deduped:!1}}async listEvents(_={}){if(Object.keys(_).length===0)return this.store.listEvents();return b8(await this.store.listEvents(),_)}async listEventsPage(_={}){if(this.store.listEventsPage)return this.store.listEventsPage(_);let $=b8(await this.store.listEvents(),{eventId:_.eventId,source:_.source,type:_.type}),D=QN(_.cursor,_),U=TN(_.limit),g=$.slice(D,D+U),I=D+g.length,j=I<$.length;return{events:g,cursor:_.cursor,nextCursor:j?f8(I,_):void 0,hasMore:j}}async listDeliveries(){return this.store.listDeliveries()}async deliver(_){let D=(await this.store.listChannels()).filter((g)=>B8(g,_)),U=[];for(let g of D){let I=await this.applyRedaction(_,g),j=await this.deliverWithRetry(I,g);await this.store.appendDelivery(j),U.push(j)}return U}async matchChannel(_,$={}){let D=await this.store.getChannel(_);if(!D)throw Error(`Channel not found: ${_}`);let U=Nz({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}),g=B8(D,U);return{channelId:D.id,matched:g,event:U,filters:D.filters,reason:g?void 0:D.enabled?"event did not match channel filters":"channel is disabled"}}async testChannel(_,$={},D={}){let U=await this.store.getChannel(_);if(!U)throw Error(`Channel not found: ${_}`);let g=await this.matchChannel(_,$),I=g.event;if(D.honorFilters&&!g.matched){let O=new Date().toISOString(),A=M8(I,U,[{attempt:1,status:"skipped",startedAt:O,completedAt:O,error:g.reason}]);return A.metadata={reason:"filter_mismatch"},await this.store.appendDelivery(A),A}let j=await this.applyRedaction(I,U),N=await this.deliverWithRetry(j,U);return await this.store.appendDelivery(N),N}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 D=[];for(let U of $.events)D.push(...await this.deliver(U));return{events:$.events,deliveries:D,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 D=await this.store.appendEvent(_);return{event:D,stored:!0,deduped:!1,identity:{id:D.id,dedupeKey:D.dedupeKey}}}async applyRedaction(_,$){let D=iv(_,$.redact?.paths??[],$.redact?.replacement??"[REDACTED]");for(let U of this.redactors)D=await U(D,$);return D}async deliverWithRetry(_,$){let D=ev($.retry),U=[];for(let g=0;g[D,h8(D)?"[REDACTED]":U]));return $}function lv(_){return _.map(y8)}function tv(_,$="[REDACTED]"){return Oz(_,$)}function h8(_){return/secret|token|password|api[_-]?key|authorization/i.test(_)}function Oz(_,$){if(Array.isArray(_))return _.map((D)=>Oz(D,$));if(!_||typeof _!=="object")return _;return Object.fromEntries(Object.entries(_).map(([D,U])=>[D,h8(D)?$:Oz(U,$)]))}function ov(_,$,D){let U=$.split("."),g=_;for(let j of U.slice(0,-1)){let N=g[j];if(!N||typeof N!=="object")return;g=N}let I=U.at(-1);if(I&&I in g)g[I]=D}function b8(_,$){let D=_;if($.eventId)D=D.filter((U)=>U.id===$.eventId);if($.source)D=D.filter((U)=>U.source===$.source);if($.type)D=D.filter((U)=>U.type===$.type);if($.cursor)D=D.slice(QN($.cursor,$));if($.limit!==void 0)D=D.slice(0,TN($.limit));return D}function pv(_){if(!_)return new Date().toISOString();return _ instanceof Date?_.toISOString():_}function ev(_){return{maxAttempts:Math.max(1,_?.maxAttempts??1),backoffMs:Math.max(0,_?.backoffMs??250),multiplier:Math.max(1,_?.multiplier??2)}}function XN(_,$,D=!1){if(!_?.length)return;let U={};for(let g of _){let I=_f(g,$),j=I.path;if(j in U)throw Error(`Duplicate ${$} filter path: ${j}`);let N=D?sv(I.rawValue,$):I.rawValue;U[j]=I.negated?{not:N}:N}return U}function av(_){let $={};if(_.source)$.source=_.source;if(_.type)$.type=_.type;if(_.subject)$.subject=_.subject;if(_.severity)$.severity=_.severity;let D=Z8(XN(_.data,"data"),XN(_.dataJson,"data-json",!0)),U=Z8(XN(_.metadata,"metadata"),XN(_.metadataJson,"metadata-json",!0));if(Object.keys(D).length>0)$.data=D;if(Object.keys(U).length>0)$.metadata=U;return Object.keys($).length>0?[$]:void 0}function Z8(..._){let $={};for(let D of _){if(!D)continue;for(let[U,g]of Object.entries(D)){if(U in $)throw Error(`Duplicate filter path: ${U}`);$[U]=g}}return $}function sv(_,$){let D=JSON.parse(_);if(D===null||typeof D==="string"||typeof D==="number"||typeof D==="boolean"||Array.isArray(D)&&D.every((U)=>typeof U==="string"))return D;throw Error(`${$} filter JSON values must be string, string[], number, boolean, or null`)}function _f(_,$){let D=_.indexOf("!=");if(D>0)return{path:_.slice(0,D),rawValue:_.slice(D+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 $f=100;function VD(_,$){if(!_)return $;let D=JSON.parse(_);if(!D||typeof D!=="object"||Array.isArray(D))throw Error("Expected a JSON object");return D}function Df(_){if(!_?.length)return;let $={};for(let D of _){let U=D.indexOf("=");if(U===-1)throw Error(`Invalid header, expected name=value: ${D}`);$[D.slice(0,U)]=D.slice(U+1)}return $}function p6(_){if(_.createClient)return _.createClient();return new x8({store:new YN(_.dataDir)})}function s4(_,$,D){if($)console.log(JSON.stringify(_,null,2));else console.log(D)}function H8(_,$){let D=_ instanceof Error?_.message:String(_);if($)console.log(JSON.stringify({error:D},null,2));else console.error(D);process.exitCode=1}function k8(_){return Boolean(_?.json||_?.opts?.().json||_?.optsWithGlobals?.().json||_?.parent?.opts?.().json||_?.parent?.optsWithGlobals?.().json)}function W6(_,$){return k8(_)||k8($)}function gf(_,$){let D=_.command($.channelsCommandName??"channels").description("Manage Hasna event channels");return D.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",a4,[]).option("--metadata ","Event metadata field filter; string values, path!=value negatives, array-member matching, dot paths, * segment wildcard, ** recursive wildcard",a4,[]).option("--data-json ","Event data field filter with typed JSON value; path!=json negatives supported",a4,[]).option("--metadata-json ","Event metadata field filter with typed JSON value; path!=json negatives supported",a4,[]).option("--secret ","Webhook HMAC secret").option("--header ","Webhook header",a4,[]).option("--arg ","Command argument",a4,[]).option("--timeout-ms ","Transport timeout in milliseconds",bU).option("--retry-attempts ","Maximum delivery attempts",bU).option("--retry-backoff-ms ","Initial retry backoff in milliseconds",bU).option("--redact ","Event field path to redact before delivery",a4,[]).option("--disabled","Create channel disabled",!1).option("-j, --json","Print JSON output",!1).action(async(U,g,I)=>{let j=new Date().toISOString(),N={id:g.id,name:g.name,enabled:!g.disabled,transport:g.transport,filters:av(g),retry:g.retryAttempts||g.retryBackoffMs?{maxAttempts:g.retryAttempts,backoffMs:g.retryBackoffMs}:void 0,redact:g.redact?.length?{paths:g.redact}:void 0,createdAt:j,updatedAt:j};if(g.transport==="webhook")N.webhook={url:U,secret:g.secret,headers:Df(g.header),timeoutMs:g.timeoutMs};else if(g.transport==="command")N.command={command:U,args:g.arg??[],timeoutMs:g.timeoutMs};else throw Error(`Transport ${g.transport} is reserved for future use and cannot be added yet`);let O=await p6($).addChannel(N);s4(y8(O),W6(g,I),`Added ${O.transport} channel ${O.id}`)}),D.command("list").description("List configured channels").option("-j, --json","Print JSON output",!1).action(async(U,g)=>{let I=await p6($).listChannels();if(W6(U,g)){console.log(JSON.stringify(lv(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}`)}),D.command("status").description("Show events channel storage status").option("-j, --json","Print JSON output",!1).action(async(U,g)=>{let I=await rv($.dataDir);s4(I,W6(U,g),`events dataDir: ${I.dataDir}`)}),D.command("remove").description("Remove a channel").argument("","Channel identifier").option("-j, --json","Print JSON output",!1).action(async(U,g,I)=>{let j=await p6($).removeChannel(U);s4({removed:j},W6(g,I),j?`Removed ${U}`:`Channel not found: ${U}`)}),D.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,g,I)=>{let j=W6(g,I);try{let N=await p6($).testChannel(U,{source:g.source??$.source,type:g.type,subject:g.subject??U,message:g.message,data:VD(g.data,{test:!0}),metadata:VD(g.metadata,{})},{honorFilters:g.honorFilters});s4(N,j,`${N.status}: ${N.channelId}`)}catch(N){H8(N,j)}}),D.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,g,I)=>{let j=W6(g,I);try{let N=await p6($).matchChannel(U,{source:g.source??$.source,type:g.type,subject:g.subject??U,message:g.message,data:VD(g.data,{test:!0}),metadata:VD(g.metadata,{})});s4(N,j,`${N.matched?"matched":"skipped"}: ${N.channelId}`)}catch(N){H8(N,j)}}),D}function Uf(_,$){let D=_.command($.eventsCommandName??"events").description("Emit, list, and replay Hasna events");D.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(g,I,j)=>{let N=await p6($).emit({source:I.source??$.source,type:g,subject:I.subject,severity:I.severity,message:I.message,dedupeKey:I.dedupeKey,data:VD(I.data,{}),metadata:VD(I.metadata,{})},{deliver:I.deliver,dedupe:I.dedupe});s4(N,W6(I,j),`${N.deduped?"Deduped":"Emitted"} ${N.event.id} to ${N.deliveries.length} channel(s)`)});let U=$.defaultEventListLimit??$f;return D.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)`,bU,U).option("-j, --json","Print JSON output",!1).action(async(g,I)=>{let j=await p6($).listEvents();if(g.source)j=j.filter((N)=>N.source===g.source);if(g.type)j=j.filter((N)=>N.type===g.type);if(g.limit)j=j.slice(-g.limit);if(W6(g,I)){console.log(JSON.stringify(j,null,2));return}if(!j.length){console.log("No events recorded.");return}for(let N of j)console.log(`${N.time} ${N.id} ${N.source} ${N.type} ${N.severity}`)}),D.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",bU).option("--dry-run","Preview without delivery",!1).option("-j, --json","Print JSON output",!1).action(async(g,I)=>{let j=await p6($).replay({eventId:g.id,source:g.source,type:g.type,cursor:g.cursor,limit:g.limit,dryRun:g.dryRun});s4(j,W6(g,I),If(j.events.length,j.deliveries.length,j.nextCursor))}),D}function c8(_,$){gf(_,$),Uf(_,$)}function bU(_){let $=Number(_);if(!Number.isFinite($))throw Error(`Expected a number, got ${_}`);return $}function a4(_,$){return $.push(_),$}function If(_,$,D){let U=D?`, next cursor: ${D}`:"";return`Replayed ${_} event(s), ${$} delivery result(s)${U}`}import{basename as Nf}from"path";var C$={name:"@hasna/knowledge",version:"0.2.96",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/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",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 n8={debug:0,info:1,warn:2,error:3},Ef=()=>{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 $0(_,$,D){if(n8[_]U.toLowerCase()));return $.filter((U)=>!D.has(U.toLowerCase()))}function Az(_,$,D){if(D===void 0)return{..._,message:$};return{..._,added:D.length,message:`${$} (added ${D.length} tag${D.length===1?"":"s"})`}}function Af(_,$){if($===void 0)throw Error("Missing value for --tag. Example: knowledge add <content> -t <tag> -t <tag>");let D=$.split(",").map((U)=>U.trim()).filter((U)=>U.length>0);if(D.length===0)throw Error(`Invalid --tag value ${JSON.stringify($)}: no tag name found. Example: knowledge add <title> <content> -t <tag> -t <tag>`);return Of([..._??[],...D])}function Lf(_){let $=[],D={},U=!1;for(let g=0;g<_.length;g+=1){let I=_[g];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":D.json=!0;break;case"--verbose":D.verbose=!0;break;case"--yes":case"-y":D.yes=!0;break;case"--help":case"-h":D.help=!0;break;case"--version":case"-v":D.version=!0;break;case"--desc":D.desc=!0;break;case"--page":case"-p":D.page=Number(_[g+1]),g+=1;break;case"--limit":case"-l":D.limit=Number(_[g+1]),g+=1;break;case"--search":case"-s":D.search=_[g+1],g+=1;break;case"--sort":D.sort=_[g+1],g+=1;break;case"--id":D.id=_[g+1],g+=1;break;case"--store":D.store=_[g+1],g+=1;break;case"--title":D.title=_[g+1],g+=1;break;case"--content":D.content=_[g+1],g+=1;break;case"--url":D.url=_[g+1],g+=1;break;case"--tag":case"-t":D.tag=Af(D.tag,_[g+1]),D.tagRaw=[...D.tagRaw??[],_[g+1]],g+=1;break;case"--format":D.format=_[g+1],g+=1;break;case"--completions":D.completions=_[g+1],g+=1;break;case"--purpose":D.purpose=_[g+1],g+=1;break;case"--model":D.model=_[g+1],g+=1;break;case"--strategy":D.strategy=_[g+1],g+=1;break;case"--dimensions":D.dimensions=Number(_[g+1]),g+=1;break;case"--semantic":D.semantic=!0;break;case"--context":D.context=!0;break;case"--max-tokens":D.maxTokens=Number(_[g+1]),g+=1;break;case"--max-items":D.maxItems=Number(_[g+1]),g+=1;break;case"--from":D.from=_[g+1],g+=1;break;case"--to":D.to=_[g+1],g+=1;break;case"--rev":D.rev=Number(_[g+1]),g+=1;break;case"--if-version":D.ifVersion=Number(_[g+1]),g+=1;break;case"--since":D.since=_[g+1],g+=1;break;case"--topic":D.topic=_[g+1],g+=1;break;case"--dedupe":D.dedupe=!0;break;case"--generate":D.generate=!0;break;case"--approve-write":D.approveWrite=!0;break;case"--provider":D.provider=_[g+1],g+=1;break;case"--mode":D.mode=_[g+1],g+=1;break;case"--machine":D.machine=_[g+1],g+=1;break;case"--workspace":D.workspace=_[g+1],g+=1;break;case"--api-url":D.apiUrl=_[g+1],g+=1;break;case"--canonical-example":D.canonicalExample=!0;break;case"--api-key":D.apiKey=_[g+1],g+=1;break;case"--email":D.email=_[g+1],g+=1;break;case"--org":D.org=_[g+1],g+=1;break;case"--org-id":D.orgId=_[g+1],g+=1;break;case"--user-id":D.userId=_[g+1],g+=1;break;case"--owner":D.owner=_[g+1],g+=1;break;case"--approved-by":D.approvedBy=_[g+1],g+=1;break;case"--patch-uri":D.patchUri=_[g+1],g+=1;break;case"--domain":D.domain=[...D.domain??[],_[g+1]],g+=1;break;case"--file-results":D.fileResults=!0;break;case"--full":D.full=!0;break;case"--dry-run":D.dryRun=!0;break;case"--fake":D.fake=!0;break;case"--no-tailscale":D.tailscale=!1;break;case"--no-artifact-content":D.artifactContent=!1;break;case"--no-color":D.noColor=!0;break;case"--scope":D.scope=_[g+1],g+=1;break;case"--tables":D.tables=_[g+1],g+=1;break;case"--peer-workspace":D.peerWorkspace=_[g+1],g+=1;break;case"--older-than":D.olderThan=Number(_[g+1]),g+=1;break;case"--empty":D.empty=!0;break;case"--archived":D.archived=!0;break;case"--include-archived":D.includeArchived=!0;break;case"--project":D.project=_[g+1],g+=1;break;case"--contract":D.contract=!0;break;case"--source-ref":D.sourceRef=[...D.sourceRef??[],_[g+1]],g+=1;break;case"--allow-global":D.allowGlobal=!0;break;default:throw Error(`Unknown flag: ${I}. Run 'knowledge --help' for valid options.`)}}return{positional:$,flags:D}}function Jf(_){if(!_)return"";return p8[_]??_}function Pf(_,$){let D=Array.from({length:_.length+1},()=>Array($.length+1).fill(0));for(let U=0;U<=_.length;U+=1)D[U][0]=U;for(let U=0;U<=$.length;U+=1)D[0][U]=U;for(let U=1;U<=_.length;U+=1)for(let g=1;g<=$.length;g+=1){let I=_[U-1]===$[g-1]?0:1;D[U][g]=Math.min(D[U-1][g]+1,D[U][g-1]+1,D[U-1][g-1]+I)}return D[_.length][$.length]}function zf(_){if(!_)return"";let $=[...o8,...Object.keys(p8)],D="",U=Number.POSITIVE_INFINITY;for(let g of $){let I=Pf(_,g);if(I<U)U=I,D=g}return U<=3?D:""}function Sf(){return Nf(process.argv[1]??"").replace(/\.(?:js|ts|mjs|cjs)$/,"")==="knowledge"}async function Wf(_){if(!t8.includes(_[0]??""))return!1;let $=new Q8;return $.name("knowledge").description("Agent-friendly local knowledge CLI with JSON output, pagination, and safe destructive actions"),c8($,{source:"knowledge"}),await $.parseAsync(_,{from:"user"}),!0}function Xf(){console.log(`knowledge - local agent knowledge store +`,{encoding:"utf-8",mode:384}),await Mv(D,_),await Uz(_,384).catch(()=>{return})}}function Cv(_=v8()){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 f8(_,$={}){if(!Number.isInteger(_)||_<0)throw Error(`Invalid event cursor offset: ${_}`);let D={offset:_,eventId:$.eventId,source:$.source,type:$.type};return`${Ez}${C8.from(JSON.stringify(D),"utf-8").toString("base64url")}`}function QN(_,$={}){if(!_)return 0;if(!_.startsWith(Ez))throw Error(`Invalid local JSON event cursor: ${_}`);let D=_.slice(Ez.length),U;try{U=JSON.parse(C8.from(D,"base64url").toString("utf-8"))}catch{throw Error(`Invalid local JSON event cursor: ${_}`)}let g=U.offset;if(!Number.isInteger(g)||g<0)throw Error(`Invalid local JSON event cursor: ${_}`);return Iz("eventId",U.eventId,$.eventId),Iz("source",U.source,$.source),Iz("type",U.type,$.type),g}function TN(_){if(_===void 0)return Zv;if(!Number.isInteger(_)||_<1)throw Error(`Event page limit must be a positive integer, got ${_}`);return Math.min(_,Hv)}function K8(_,$){let D=_;if($.eventId)D=D.filter((U)=>U.id===$.eventId);if($.source)D=D.filter((U)=>U.source===$.source);if($.type)D=D.filter((U)=>U.type===$.type);if($.cursor){let U=QN($.cursor,$);D=D.slice(U)}if($.limit!==void 0)D=D.slice(0,TN($.limit));return D}function Iz(_,$,D){if($!==D)throw Error(`Local JSON event cursor ${_} filter mismatch`)}function F8(_,$){return _.find((D)=>$.id!==void 0&&D.id===$.id||$.dedupeKey!==void 0&&D.dedupeKey===$.dedupeKey)}async function rv(_){let $=new YN(_);await $.init();let[D,U,g]=await Promise.all([$.listChannels(),$.listEvents(),$.listDeliveries()]),I=D.reduce((j,N)=>{return j[N.transport]=(j[N.transport]??0)+1,j},{});return{service:"events",schemaVersion:"1.0",dataDir:$.dataDir,storage:$.runtime,env:{primary:RN,fallback:GN,active:kv()},files:{channels:jz($.dataDir,"channels.json",D.length),events:jz($.dataDir,"events.json",U.length),deliveries:jz($.dataDir,"deliveries.json",g.length)},counts:{channels:D.length,enabledChannels:D.filter((j)=>j.enabled).length,disabledChannels:D.filter((j)=>!j.enabled).length,events:U.length,deliveries:g.length},transports:I,safety:{includesEventPayloads:!1,includesWebhookSecrets:!1,listOutputsRedactSecrets:!0,statusOutputIsMetadataOnly:!0}}}function jz(_,$,D){let U=MU(_,$);return{path:U,exists:r8(U),records:D}}function fv(_,$){return`${_}.${$}`}function wv(_,$,D){return`sha256=${vv("sha256",_).update(fv($,D)).digest("hex")}`}function i$(){return new Date().toISOString()}function FU(_,$=4096){return _.length>$?`${_.slice(0,$)}...`:_}function yv(_,$){if(!$.webhook)throw Error(`Channel ${$.id} has no webhook config`);let D=JSON.stringify(_),U=_.time,g={"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)g["X-Hasna-Signature"]=wv($.webhook.secret,U,D);return{body:D,headers:g}}async function hv(_,$,D={}){if(!$.webhook)throw Error(`Channel ${$.id} has no webhook config`);let U=i$(),{body:g,headers:I}=yv(_,$),j=new AbortController,N=setTimeout(()=>j.abort(),$.webhook.timeoutMs??15000);try{let O=await(D.fetchImpl??fetch)($.webhook.url,{method:"POST",headers:I,body:g,signal:j.signal}),A=FU(await O.text());return{attempt:1,status:O.ok?"success":"failed",startedAt:U,completedAt:i$(),responseStatus:O.status,responseBody:A,error:O.ok?void 0:`Webhook returned HTTP ${O.status}`}}catch(O){return{attempt:1,status:"failed",startedAt:U,completedAt:i$(),error:O instanceof Error?O.message:String(O)}}finally{clearTimeout(N)}}async function cv(_,$){if(!$.command)throw Error(`Channel ${$.id} has no command config`);let D=i$(),U=JSON.stringify(_),g={...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=xv($.command.command,$.command.args??[],{cwd:$.command.cwd,env:g,stdio:["pipe","pipe","pipe"]}),N="",O="",A=setTimeout(()=>j.kill("SIGTERM"),$.command.timeoutMs??15000);j.stdin.end(U),j.stdout.on("data",(L)=>{N+=L.toString()}),j.stderr.on("data",(L)=>{O+=L.toString()}),j.on("error",(L)=>{clearTimeout(A),I({attempt:1,status:"failed",startedAt:D,completedAt:i$(),stdout:FU(N),stderr:FU(O),error:L.message})}),j.on("close",(L,z)=>{clearTimeout(A);let W=L===0;I({attempt:1,status:W?"success":"failed",startedAt:D,completedAt:i$(),stdout:FU(N),stderr:FU(O),error:W?void 0:`Command exited with ${z?`signal ${z}`:`code ${L}`}`})})})}async function nv(_,$,D={}){if($.transport==="webhook")return hv(_,$,D);if($.transport==="command")return cv(_,$);return{attempt:1,status:"skipped",startedAt:i$(),completedAt:i$(),error:`Unsupported transport: ${$.transport}`}}function M8(_,$,D){let U=D.some((g)=>g.status==="success")?"success":D.every((g)=>g.status==="skipped")?"skipped":"failed";return{id:uv(),eventId:_.id,channelId:$.id,transport:$.transport,status:U,attempts:D,createdAt:D[0]?.startedAt??i$(),completedAt:D.at(-1)?.completedAt??i$()}}class w8 extends Error{eventType;issues;constructor(_,$){let D=$.map((U)=>`${U.path||"<root>"}: ${U.message}`).join("; ");super(`Event validation failed for type "${_}": ${D}`);this.name="EventValidationError",this.eventType=_,this.issues=$}}class u8{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 w8(_.type,$.issues)}}var dv=new u8;function Nz(_){return{id:_.id??mv(),source:_.source,type:_.type,time:pv(_.time),subject:_.subject,severity:_.severity??"info",data:_.data??{},message:_.message,dedupeKey:_.dedupeKey,schemaVersion:_.schemaVersion??"1.0",metadata:_.metadata??{}}}class x8{store;redactors;transportOptions;catalog;validateCatalogTypes;constructor(_={}){this.store=_.store??new YN(_.dataDir),this.redactors=_.redactors??[],this.transportOptions={fetchImpl:_.fetchImpl},this.catalog=_.catalog??dv,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 D=$.redactSensitiveData===!1?Nz(_):tv(Nz(_));if($.validate??this.validateCatalogTypes)this.catalog.assertEventValid(D);let U=await this.appendEvent(D,{dedupe:$.dedupe!==!1});if(U.deduped)return{event:U.event,deliveries:[],deduped:!0};let g=$.deliver===!1?[]:await this.deliver(U.event);return{event:U.event,deliveries:g,deduped:!1}}async listEvents(_={}){if(Object.keys(_).length===0)return this.store.listEvents();return b8(await this.store.listEvents(),_)}async listEventsPage(_={}){if(this.store.listEventsPage)return this.store.listEventsPage(_);let $=b8(await this.store.listEvents(),{eventId:_.eventId,source:_.source,type:_.type}),D=QN(_.cursor,_),U=TN(_.limit),g=$.slice(D,D+U),I=D+g.length,j=I<$.length;return{events:g,cursor:_.cursor,nextCursor:j?f8(I,_):void 0,hasMore:j}}async listDeliveries(){return this.store.listDeliveries()}async deliver(_){let D=(await this.store.listChannels()).filter((g)=>B8(g,_)),U=[];for(let g of D){let I=await this.applyRedaction(_,g),j=await this.deliverWithRetry(I,g);await this.store.appendDelivery(j),U.push(j)}return U}async matchChannel(_,$={}){let D=await this.store.getChannel(_);if(!D)throw Error(`Channel not found: ${_}`);let U=Nz({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}),g=B8(D,U);return{channelId:D.id,matched:g,event:U,filters:D.filters,reason:g?void 0:D.enabled?"event did not match channel filters":"channel is disabled"}}async testChannel(_,$={},D={}){let U=await this.store.getChannel(_);if(!U)throw Error(`Channel not found: ${_}`);let g=await this.matchChannel(_,$),I=g.event;if(D.honorFilters&&!g.matched){let O=new Date().toISOString(),A=M8(I,U,[{attempt:1,status:"skipped",startedAt:O,completedAt:O,error:g.reason}]);return A.metadata={reason:"filter_mismatch"},await this.store.appendDelivery(A),A}let j=await this.applyRedaction(I,U),N=await this.deliverWithRetry(j,U);return await this.store.appendDelivery(N),N}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 D=[];for(let U of $.events)D.push(...await this.deliver(U));return{events:$.events,deliveries:D,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 D=await this.store.appendEvent(_);return{event:D,stored:!0,deduped:!1,identity:{id:D.id,dedupeKey:D.dedupeKey}}}async applyRedaction(_,$){let D=iv(_,$.redact?.paths??[],$.redact?.replacement??"[REDACTED]");for(let U of this.redactors)D=await U(D,$);return D}async deliverWithRetry(_,$){let D=ev($.retry),U=[];for(let g=0;g<D.maxAttempts;g+=1){let I=await nv(_,$,this.transportOptions);if(I.attempt=g+1,I.status==="failed"&&g+1<D.maxAttempts)I.nextBackoffMs=Math.round(D.backoffMs*D.multiplier**g);if(U.push(I),I.status!=="failed")break;if(I.nextBackoffMs)await Bun.sleep(I.nextBackoffMs)}return M8(_,$,U)}}function iv(_,$,D="[REDACTED]"){if($.length===0)return _;let U=structuredClone(_);for(let g of $)ov(U,g,D);return U}function y8(_){let $=structuredClone(_);if($.webhook?.secret)$.webhook.secret="[REDACTED]";if($.command?.env)$.command.env=Object.fromEntries(Object.entries($.command.env).map(([D,U])=>[D,h8(D)?"[REDACTED]":U]));return $}function lv(_){return _.map(y8)}function tv(_,$="[REDACTED]"){return Oz(_,$)}function h8(_){return/secret|token|password|api[_-]?key|authorization/i.test(_)}function Oz(_,$){if(Array.isArray(_))return _.map((D)=>Oz(D,$));if(!_||typeof _!=="object")return _;return Object.fromEntries(Object.entries(_).map(([D,U])=>[D,h8(D)?$:Oz(U,$)]))}function ov(_,$,D){let U=$.split("."),g=_;for(let j of U.slice(0,-1)){let N=g[j];if(!N||typeof N!=="object")return;g=N}let I=U.at(-1);if(I&&I in g)g[I]=D}function b8(_,$){let D=_;if($.eventId)D=D.filter((U)=>U.id===$.eventId);if($.source)D=D.filter((U)=>U.source===$.source);if($.type)D=D.filter((U)=>U.type===$.type);if($.cursor)D=D.slice(QN($.cursor,$));if($.limit!==void 0)D=D.slice(0,TN($.limit));return D}function pv(_){if(!_)return new Date().toISOString();return _ instanceof Date?_.toISOString():_}function ev(_){return{maxAttempts:Math.max(1,_?.maxAttempts??1),backoffMs:Math.max(0,_?.backoffMs??250),multiplier:Math.max(1,_?.multiplier??2)}}function XN(_,$,D=!1){if(!_?.length)return;let U={};for(let g of _){let I=_f(g,$),j=I.path;if(j in U)throw Error(`Duplicate ${$} filter path: ${j}`);let N=D?sv(I.rawValue,$):I.rawValue;U[j]=I.negated?{not:N}:N}return U}function av(_){let $={};if(_.source)$.source=_.source;if(_.type)$.type=_.type;if(_.subject)$.subject=_.subject;if(_.severity)$.severity=_.severity;let D=Z8(XN(_.data,"data"),XN(_.dataJson,"data-json",!0)),U=Z8(XN(_.metadata,"metadata"),XN(_.metadataJson,"metadata-json",!0));if(Object.keys(D).length>0)$.data=D;if(Object.keys(U).length>0)$.metadata=U;return Object.keys($).length>0?[$]:void 0}function Z8(..._){let $={};for(let D of _){if(!D)continue;for(let[U,g]of Object.entries(D)){if(U in $)throw Error(`Duplicate filter path: ${U}`);$[U]=g}}return $}function sv(_,$){let D=JSON.parse(_);if(D===null||typeof D==="string"||typeof D==="number"||typeof D==="boolean"||Array.isArray(D)&&D.every((U)=>typeof U==="string"))return D;throw Error(`${$} filter JSON values must be string, string[], number, boolean, or null`)}function _f(_,$){let D=_.indexOf("!=");if(D>0)return{path:_.slice(0,D),rawValue:_.slice(D+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 $f=100;function VD(_,$){if(!_)return $;let D=JSON.parse(_);if(!D||typeof D!=="object"||Array.isArray(D))throw Error("Expected a JSON object");return D}function Df(_){if(!_?.length)return;let $={};for(let D of _){let U=D.indexOf("=");if(U===-1)throw Error(`Invalid header, expected name=value: ${D}`);$[D.slice(0,U)]=D.slice(U+1)}return $}function p6(_){if(_.createClient)return _.createClient();return new x8({store:new YN(_.dataDir)})}function s4(_,$,D){if($)console.log(JSON.stringify(_,null,2));else console.log(D)}function H8(_,$){let D=_ instanceof Error?_.message:String(_);if($)console.log(JSON.stringify({error:D},null,2));else console.error(D);process.exitCode=1}function k8(_){return Boolean(_?.json||_?.opts?.().json||_?.optsWithGlobals?.().json||_?.parent?.opts?.().json||_?.parent?.optsWithGlobals?.().json)}function W6(_,$){return k8(_)||k8($)}function gf(_,$){let D=_.command($.channelsCommandName??"channels").description("Manage Hasna event channels");return D.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",a4,[]).option("--metadata <path=value...>","Event metadata field filter; string values, path!=value negatives, array-member matching, dot paths, * segment wildcard, ** recursive wildcard",a4,[]).option("--data-json <path=json...>","Event data field filter with typed JSON value; path!=json negatives supported",a4,[]).option("--metadata-json <path=json...>","Event metadata field filter with typed JSON value; path!=json negatives supported",a4,[]).option("--secret <secret>","Webhook HMAC secret").option("--header <name=value...>","Webhook header",a4,[]).option("--arg <arg...>","Command argument",a4,[]).option("--timeout-ms <ms>","Transport timeout in milliseconds",bU).option("--retry-attempts <n>","Maximum delivery attempts",bU).option("--retry-backoff-ms <ms>","Initial retry backoff in milliseconds",bU).option("--redact <path...>","Event field path to redact before delivery",a4,[]).option("--disabled","Create channel disabled",!1).option("-j, --json","Print JSON output",!1).action(async(U,g,I)=>{let j=new Date().toISOString(),N={id:g.id,name:g.name,enabled:!g.disabled,transport:g.transport,filters:av(g),retry:g.retryAttempts||g.retryBackoffMs?{maxAttempts:g.retryAttempts,backoffMs:g.retryBackoffMs}:void 0,redact:g.redact?.length?{paths:g.redact}:void 0,createdAt:j,updatedAt:j};if(g.transport==="webhook")N.webhook={url:U,secret:g.secret,headers:Df(g.header),timeoutMs:g.timeoutMs};else if(g.transport==="command")N.command={command:U,args:g.arg??[],timeoutMs:g.timeoutMs};else throw Error(`Transport ${g.transport} is reserved for future use and cannot be added yet`);let O=await p6($).addChannel(N);s4(y8(O),W6(g,I),`Added ${O.transport} channel ${O.id}`)}),D.command("list").description("List configured channels").option("-j, --json","Print JSON output",!1).action(async(U,g)=>{let I=await p6($).listChannels();if(W6(U,g)){console.log(JSON.stringify(lv(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}`)}),D.command("status").description("Show events channel storage status").option("-j, --json","Print JSON output",!1).action(async(U,g)=>{let I=await rv($.dataDir);s4(I,W6(U,g),`events dataDir: ${I.dataDir}`)}),D.command("remove").description("Remove a channel").argument("<id>","Channel identifier").option("-j, --json","Print JSON output",!1).action(async(U,g,I)=>{let j=await p6($).removeChannel(U);s4({removed:j},W6(g,I),j?`Removed ${U}`:`Channel not found: ${U}`)}),D.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,g,I)=>{let j=W6(g,I);try{let N=await p6($).testChannel(U,{source:g.source??$.source,type:g.type,subject:g.subject??U,message:g.message,data:VD(g.data,{test:!0}),metadata:VD(g.metadata,{})},{honorFilters:g.honorFilters});s4(N,j,`${N.status}: ${N.channelId}`)}catch(N){H8(N,j)}}),D.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,g,I)=>{let j=W6(g,I);try{let N=await p6($).matchChannel(U,{source:g.source??$.source,type:g.type,subject:g.subject??U,message:g.message,data:VD(g.data,{test:!0}),metadata:VD(g.metadata,{})});s4(N,j,`${N.matched?"matched":"skipped"}: ${N.channelId}`)}catch(N){H8(N,j)}}),D}function Uf(_,$){let D=_.command($.eventsCommandName??"events").description("Emit, list, and replay Hasna events");D.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(g,I,j)=>{let N=await p6($).emit({source:I.source??$.source,type:g,subject:I.subject,severity:I.severity,message:I.message,dedupeKey:I.dedupeKey,data:VD(I.data,{}),metadata:VD(I.metadata,{})},{deliver:I.deliver,dedupe:I.dedupe});s4(N,W6(I,j),`${N.deduped?"Deduped":"Emitted"} ${N.event.id} to ${N.deliveries.length} channel(s)`)});let U=$.defaultEventListLimit??$f;return D.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)`,bU,U).option("-j, --json","Print JSON output",!1).action(async(g,I)=>{let j=await p6($).listEvents();if(g.source)j=j.filter((N)=>N.source===g.source);if(g.type)j=j.filter((N)=>N.type===g.type);if(g.limit)j=j.slice(-g.limit);if(W6(g,I)){console.log(JSON.stringify(j,null,2));return}if(!j.length){console.log("No events recorded.");return}for(let N of j)console.log(`${N.time} ${N.id} ${N.source} ${N.type} ${N.severity}`)}),D.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",bU).option("--dry-run","Preview without delivery",!1).option("-j, --json","Print JSON output",!1).action(async(g,I)=>{let j=await p6($).replay({eventId:g.id,source:g.source,type:g.type,cursor:g.cursor,limit:g.limit,dryRun:g.dryRun});s4(j,W6(g,I),If(j.events.length,j.deliveries.length,j.nextCursor))}),D}function c8(_,$){gf(_,$),Uf(_,$)}function bU(_){let $=Number(_);if(!Number.isFinite($))throw Error(`Expected a number, got ${_}`);return $}function a4(_,$){return $.push(_),$}function If(_,$,D){let U=D?`, next cursor: ${D}`:"";return`Replayed ${_} event(s), ${$} delivery result(s)${U}`}import{basename as Nf}from"path";var C$={name:"@hasna/knowledge",version:"0.2.97",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/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",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 n8={debug:0,info:1,warn:2,error:3},Ef=()=>{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 $0(_,$,D){if(n8[_]<n8[Ef()])return;let U={debug:"[DEBUG]",info:"[INFO]",warn:"[WARN]",error:"[ERROR]"}[_],g=D?`${U} ${$} ${JSON.stringify(D)}`:`${U} ${$}`;if(_==="error")console.error(g);else console.error(g)}var t8=["events","webhooks"],o8=["add","list","get","delete","update","archive","restore","upsert","untag","versions","diff","export","prune","dedupe","stats","inventory","project-panel","paths","mode","setup","auth","storage","machines","sync","db","wiki","app-wiki","source","ingest","reindex","search","context","proposals","web","ask","build","embeddings","providers","safety","help",...t8],p8={ls:"list",rm:"delete",edit:"update",unarchive:"restore"};function Of(_){let $=new Set,D=[];for(let U of _){let g=U.toLowerCase();if($.has(g))continue;$.add(g),D.push(U)}return D}function d8(_,$){let D=new Set((_??[]).map((U)=>U.toLowerCase()));return $.filter((U)=>!D.has(U.toLowerCase()))}function Az(_,$,D){if(D===void 0)return{..._,message:$};return{..._,added:D.length,message:`${$} (added ${D.length} tag${D.length===1?"":"s"})`}}function Af(_,$){if($===void 0)throw Error("Missing value for --tag. Example: knowledge add <title> <content> -t <tag> -t <tag>");let D=$.split(",").map((U)=>U.trim()).filter((U)=>U.length>0);if(D.length===0)throw Error(`Invalid --tag value ${JSON.stringify($)}: no tag name found. Example: knowledge add <title> <content> -t <tag> -t <tag>`);return Of([..._??[],...D])}function Lf(_){let $=[],D={},U=!1;for(let g=0;g<_.length;g+=1){let I=_[g];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":D.json=!0;break;case"--verbose":D.verbose=!0;break;case"--yes":case"-y":D.yes=!0;break;case"--help":case"-h":D.help=!0;break;case"--version":case"-v":D.version=!0;break;case"--desc":D.desc=!0;break;case"--page":case"-p":D.page=Number(_[g+1]),g+=1;break;case"--limit":case"-l":D.limit=Number(_[g+1]),g+=1;break;case"--search":case"-s":D.search=_[g+1],g+=1;break;case"--sort":D.sort=_[g+1],g+=1;break;case"--id":D.id=_[g+1],g+=1;break;case"--store":D.store=_[g+1],g+=1;break;case"--title":D.title=_[g+1],g+=1;break;case"--content":D.content=_[g+1],g+=1;break;case"--url":D.url=_[g+1],g+=1;break;case"--tag":case"-t":D.tag=Af(D.tag,_[g+1]),D.tagRaw=[...D.tagRaw??[],_[g+1]],g+=1;break;case"--format":D.format=_[g+1],g+=1;break;case"--completions":D.completions=_[g+1],g+=1;break;case"--purpose":D.purpose=_[g+1],g+=1;break;case"--model":D.model=_[g+1],g+=1;break;case"--strategy":D.strategy=_[g+1],g+=1;break;case"--dimensions":D.dimensions=Number(_[g+1]),g+=1;break;case"--semantic":D.semantic=!0;break;case"--context":D.context=!0;break;case"--max-tokens":D.maxTokens=Number(_[g+1]),g+=1;break;case"--max-items":D.maxItems=Number(_[g+1]),g+=1;break;case"--from":D.from=_[g+1],g+=1;break;case"--to":D.to=_[g+1],g+=1;break;case"--rev":D.rev=Number(_[g+1]),g+=1;break;case"--if-version":D.ifVersion=Number(_[g+1]),g+=1;break;case"--since":D.since=_[g+1],g+=1;break;case"--topic":D.topic=_[g+1],g+=1;break;case"--dedupe":D.dedupe=!0;break;case"--generate":D.generate=!0;break;case"--approve-write":D.approveWrite=!0;break;case"--provider":D.provider=_[g+1],g+=1;break;case"--mode":D.mode=_[g+1],g+=1;break;case"--machine":D.machine=_[g+1],g+=1;break;case"--workspace":D.workspace=_[g+1],g+=1;break;case"--api-url":D.apiUrl=_[g+1],g+=1;break;case"--canonical-example":D.canonicalExample=!0;break;case"--api-key":D.apiKey=_[g+1],g+=1;break;case"--email":D.email=_[g+1],g+=1;break;case"--org":D.org=_[g+1],g+=1;break;case"--org-id":D.orgId=_[g+1],g+=1;break;case"--user-id":D.userId=_[g+1],g+=1;break;case"--owner":D.owner=_[g+1],g+=1;break;case"--approved-by":D.approvedBy=_[g+1],g+=1;break;case"--patch-uri":D.patchUri=_[g+1],g+=1;break;case"--domain":D.domain=[...D.domain??[],_[g+1]],g+=1;break;case"--file-results":D.fileResults=!0;break;case"--full":D.full=!0;break;case"--dry-run":D.dryRun=!0;break;case"--fake":D.fake=!0;break;case"--no-tailscale":D.tailscale=!1;break;case"--no-artifact-content":D.artifactContent=!1;break;case"--no-color":D.noColor=!0;break;case"--scope":D.scope=_[g+1],g+=1;break;case"--tables":D.tables=_[g+1],g+=1;break;case"--peer-workspace":D.peerWorkspace=_[g+1],g+=1;break;case"--older-than":D.olderThan=Number(_[g+1]),g+=1;break;case"--empty":D.empty=!0;break;case"--archived":D.archived=!0;break;case"--include-archived":D.includeArchived=!0;break;case"--project":D.project=_[g+1],g+=1;break;case"--contract":D.contract=!0;break;case"--source-ref":D.sourceRef=[...D.sourceRef??[],_[g+1]],g+=1;break;case"--allow-global":D.allowGlobal=!0;break;default:throw Error(`Unknown flag: ${I}. Run 'knowledge --help' for valid options.`)}}return{positional:$,flags:D}}function Jf(_){if(!_)return"";return p8[_]??_}function Pf(_,$){let D=Array.from({length:_.length+1},()=>Array($.length+1).fill(0));for(let U=0;U<=_.length;U+=1)D[U][0]=U;for(let U=0;U<=$.length;U+=1)D[0][U]=U;for(let U=1;U<=_.length;U+=1)for(let g=1;g<=$.length;g+=1){let I=_[U-1]===$[g-1]?0:1;D[U][g]=Math.min(D[U-1][g]+1,D[U][g-1]+1,D[U-1][g-1]+I)}return D[_.length][$.length]}function zf(_){if(!_)return"";let $=[...o8,...Object.keys(p8)],D="",U=Number.POSITIVE_INFINITY;for(let g of $){let I=Pf(_,g);if(I<U)U=I,D=g}return U<=3?D:""}function Sf(){return Nf(process.argv[1]??"").replace(/\.(?:js|ts|mjs|cjs)$/,"")==="knowledge"}async function Wf(_){if(!t8.includes(_[0]??""))return!1;let $=new Q8;return $.name("knowledge").description("Agent-friendly local knowledge CLI with JSON output, pagination, and safe destructive actions"),c8($,{source:"knowledge"}),await $.parseAsync(_,{from:"user"}),!0}function Xf(){console.log(`knowledge - local agent knowledge store Usage: knowledge <command> [options] diff --git a/package.json b/package.json index 4c353ac..8c1f76d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hasna/knowledge", - "version": "0.2.96", + "version": "0.2.97", "description": "Agent-friendly local knowledge CLI with JSON output, pagination, and safe destructive actions", "type": "module", "exports": {