@hasna/knowledge 0.2.25 → 0.2.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -122,6 +122,21 @@ knowledge "How do we cite handbook policy?" --scope project --json
122
122
  HASNA_KNOWLEDGE_WEB_SEARCH=1 open-knowledge web search "latest AI SDK web search" --provider openai --json
123
123
  ```
124
124
 
125
+ ## Guides
126
+
127
+ - [Company wiki workflow](docs/examples/company-wiki-workflow.md): an end-to-end
128
+ local workflow for open-files manifests, search, prompt runs, cited wiki
129
+ pages, linting, reindexing, MCP, and optional hosted/S3 mode.
130
+ - [JSON to SQLite migration](docs/migration/json-to-sqlite.md): how legacy
131
+ JSON notes coexist with the `.hasna/apps/knowledge` workspace and the
132
+ versioned SQLite catalog.
133
+ - [AI-native architecture](docs/architecture/ai-native-knowledge-base.md):
134
+ source boundaries, wiki model, search model, provider registry, and non-goals.
135
+ - [Hybrid semantic search](docs/architecture/hybrid-semantic-search.md):
136
+ keyword/vector/search-context contracts and hosted index options.
137
+ - [Hosted wrapper responsibilities](docs/architecture/hosted-wrapper-responsibilities.md):
138
+ what a future SaaS layer owns outside the OSS package.
139
+
125
140
  ## Commands
126
141
 
127
142
  ### add
@@ -13660,7 +13660,7 @@ import { existsSync as existsSync8, readFileSync as readFileSync8, writeFileSync
13660
13660
  // package.json
13661
13661
  var package_default = {
13662
13662
  name: "@hasna/knowledge",
13663
- version: "0.2.25",
13663
+ version: "0.2.26",
13664
13664
  description: "Agent-friendly local knowledge CLI with JSON output, pagination, and safe destructive actions",
13665
13665
  type: "module",
13666
13666
  bin: {
@@ -622,7 +622,7 @@ Pages should be concise, cited, and organized for both humans and agents.
622
622
  content_hash = excluded.content_hash,
623
623
  status = excluded.status,
624
624
  metadata_json = excluded.metadata_json,
625
- updated_at = excluded.updated_at`,[u,"wiki/README.md","Wiki",s.uri,s.hash??null,"active",JSON.stringify({artifact_key:s.key,provenance:Et(s)}),r,r]),lo(e,u,"Wiki",s,Jn(),r)}}function _o(e){if(!e)return;let t=e.trim().toLowerCase();if(t==="local"||t==="offline")return"local";if(t==="hosted"||t==="remote"||t==="knowledge.hasna.xyz")return"hosted";throw Error("Invalid setup mode. Use hosted or local.")}class Yn{options;ensuredWorkspace;cachedConfig;constructor(e={}){this.options=e}get scope(){return this.options.scope??"global"}get workspace(){return this.ensuredWorkspace??wt(this.options.scope,this.options.cwd)}ensureWorkspace(){if(!this.ensuredWorkspace)this.ensuredWorkspace=bt(this.workspace.home);return this.ensuredWorkspace}jsonStorePath(){return this.ensureWorkspace().jsonStorePath}config(){if(!this.cachedConfig){let e=this.ensureWorkspace();this.cachedConfig=vt(e.configPath)}return this.cachedConfig}safetyPolicy(){return pn(this.config(),this.ensureWorkspace())}artifactStore(){return Lt(this.config(),this.ensureWorkspace())}storageContract(){return Kn(this.config(),this.ensureWorkspace(),this.scope)}validateStorage(){return gt(this.config(),this.ensureWorkspace())}setup(e={}){let t=this.ensureWorkspace(),n=this.config(),r=_o(e.mode)??n.mode,i=e.apiUrl?$(e.apiUrl):n.hosted?.api_url?$(n.hosted.api_url):null,s={...n,mode:r,hosted:{...n.hosted??{},...i?{api_url:i}:{}}};return St(t.configPath,s),this.cachedConfig=s,{ok:!0,mode:r,api_url:s.hosted?.api_url??null,config_path:t.configPath,next:r==="hosted"?["open-knowledge auth login --api-key <key>","open-knowledge remote contracts --json"]:["open-knowledge search <query>","knowledge <prompt>"],message:`Set knowledge mode to ${r}`}}authStatus(e=process.env){return Kt(this.config(),e)}saveAuth(e,t=process.env){let n=e.apiUrl??this.config().hosted?.api_url;return Dt({api_key:e.apiKey,email:e.email,org_id:e.orgId,org_slug:e.orgSlug,user_id:e.userId,api_url:n},t)}clearAuth(e=process.env){return Ut(e)}remoteContract(){let e=this.storageContract();return An({mode:this.config().mode,sourceSchemes:this.config().sources.allowed_schemes,storageType:e.artifact_store.type,artifactUriPrefix:e.artifact_store.uri_prefix})}remoteClient(e=process.env){return We.fromConfig(this.config(),e)}paths(){let e=this.ensureWorkspace();return{ok:!0,scope:this.scope,home:e.home,config_path:e.configPath,json_store_path:e.jsonStorePath,knowledge_db_path:e.knowledgeDbPath,artifacts_dir:e.artifactsDir,indexes_dir:e.indexesDir,logs_dir:e.logsDir,runs_dir:e.runsDir,schemas_dir:e.schemasDir,wiki_dir:e.wikiDir,config:this.config(),message:e.home}}initDb(){return x(this.ensureWorkspace().knowledgeDbPath)}dbStats(){let e=this.ensureWorkspace();return x(e.knowledgeDbPath),Ot(e.knowledgeDbPath)}async initWiki(){let e=this.ensureWorkspace();x(e.knowledgeDbPath);let t=await zn(this.artifactStore()),n=b(e.knowledgeDbPath);try{ge(n,t.artifacts),Gn(n,t.artifacts)}finally{n.close()}return t}async compileWiki(e={}){let t=this.ensureWorkspace();return qn({...e,dbPath:t.knowledgeDbPath,store:this.artifactStore()})}async fileAnswer(e){let t=this.ensureWorkspace(),n=await this.retrieveContext({query:e.prompt,limit:e.limit,semantic:e.semantic,modelRef:e.modelRef,dimensions:e.dimensions,fake:e.fake});return Hn({dbPath:t.knowledgeDbPath,store:this.artifactStore(),prompt:e.prompt,answer:e.answer,context:n,approveWrite:e.approveWrite})}lintWiki(){let e=this.ensureWorkspace();return Bn({dbPath:e.knowledgeDbPath})}async ingestManifest(e){let t=this.ensureWorkspace();return yn({dbPath:t.knowledgeDbPath,input:e,config:this.config(),safetyPolicy:this.safetyPolicy()})}async ingestSource(e,t){let n=this.ensureWorkspace();return vn({dbPath:n.knowledgeDbPath,sourceRef:e,purpose:t,config:this.config(),safetyPolicy:this.safetyPolicy()})}async resolveSource(e,t={}){let n=this.ensureWorkspace();return Ke({dbPath:n.knowledgeDbPath,sourceRef:e,purpose:t.purpose,limit:t.limit,safetyPolicy:this.safetyPolicy()})}async consumeOutbox(e){let t=this.ensureWorkspace();return kn({dbPath:t.knowledgeDbPath,input:e,config:this.config(),safetyPolicy:this.safetyPolicy()})}reindexHealth(e={}){let t=this.ensureWorkspace();return Rn({...e,dbPath:t.knowledgeDbPath,config:this.config()})}enqueueReindex(e={}){let t=this.ensureWorkspace();return ft({...e,dbPath:t.knowledgeDbPath,config:this.config()})}async refreshEmbeddings(e={}){let t=this.ensureWorkspace();return xn({...e,dbPath:t.knowledgeDbPath,config:this.config()})}providerStatus(e=process.env){return $t(this.config(),e)}modelRegistry(){return rt(this.config())}embeddingStatus(){let e=this.ensureWorkspace();return Yt(e.knowledgeDbPath)}async indexEmbeddings(e={}){let t=this.ensureWorkspace();return Te({...e,dbPath:t.knowledgeDbPath,config:this.config()})}async semanticSearch(e){let t=this.ensureWorkspace();return Re({...e,dbPath:t.knowledgeDbPath,config:this.config()})}async search(e){let t=this.ensureWorkspace();return Ae({...e,dbPath:t.knowledgeDbPath,config:this.config()})}async retrieveContext(e){let t=this.ensureWorkspace();return Le({...e,dbPath:t.knowledgeDbPath,config:this.config()})}async runPrompt(e){let t=this.ensureWorkspace();return un({...e,dbPath:t.knowledgeDbPath,config:this.config()})}async webSearch(e){let t=this.ensureWorkspace();return Pn({...e,dbPath:t.knowledgeDbPath,config:this.config(),safetyPolicy:this.safetyPolicy()})}}function Vn(e={}){return new Yn(e)}import{basename as go}from"path";var pe={name:"@hasna/knowledge",version:"0.2.25",description:"Agent-friendly local knowledge CLI with JSON output, pagination, and safe destructive actions",type:"module",bin:{knowledge:"bin/open-knowledge.js","open-knowledge":"bin/open-knowledge.js","open-knowledge-mcp":"bin/open-knowledge-mcp.js"},files:["bin","src","docs","LICENSE","README.md"],scripts:{test:"bun test","test:cli":"bun test tests/cli.test.ts",build:"bun build --target=bun --outfile=bin/open-knowledge.js --minify --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/open-knowledge-mcp.js --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",prepublishOnly:"bun run build",postinstall:"bun run build"},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:{"@aws-sdk/client-s3":"^3.1063.0","@aws-sdk/credential-providers":"^3.1063.0","@ai-sdk/anthropic":"^3.0.81","@ai-sdk/deepseek":"^2.0.35","@ai-sdk/openai":"^3.0.68","@modelcontextprotocol/sdk":"^1.29.0",ai:"^6.0.197",zod:"^4.3.6"},devDependencies:{"@types/bun":"^1.3.14"}};var Qn={debug:0,info:1,warn:2,error:3},po=()=>{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 ee(e,t,n){if(Qn[e]<Qn[po()])return;let r={debug:"[DEBUG]",info:"[INFO]",warn:"[WARN]",error:"[ERROR]"}[e],i=n?`${r} ${t} ${JSON.stringify(n)}`:`${r} ${t}`;if(e==="error")console.error(i);else console.error(i)}var Zn=["add","list","get","delete","update","archive","restore","upsert","untag","export","prune","dedupe","stats","paths","setup","auth","remote","storage","db","wiki","source","ingest","reindex","search","web","ask","build","embeddings","providers","safety","help"],er={ls:"list",rm:"delete",edit:"update",unarchive:"restore",knowledge:"ask"};function mo(e){let t=[],n={};for(let r=0;r<e.length;r+=1){let i=e[r];if(!i.startsWith("-")){t.push(i);continue}switch(i){case"--json":n.json=!0;break;case"--yes":case"-y":n.yes=!0;break;case"--help":case"-h":n.help=!0;break;case"--version":case"-v":n.version=!0;break;case"--desc":n.desc=!0;break;case"--page":case"-p":n.page=Number(e[r+1]),r+=1;break;case"--limit":case"-l":n.limit=Number(e[r+1]),r+=1;break;case"--search":case"-s":n.search=e[r+1],r+=1;break;case"--sort":n.sort=e[r+1],r+=1;break;case"--id":n.id=e[r+1],r+=1;break;case"--store":n.store=e[r+1],r+=1;break;case"--title":n.title=e[r+1],r+=1;break;case"--content":n.content=e[r+1],r+=1;break;case"--url":n.url=e[r+1],r+=1;break;case"--tag":case"-t":n.tag=e[r+1],r+=1;break;case"--format":n.format=e[r+1],r+=1;break;case"--completions":n.completions=e[r+1],r+=1;break;case"--purpose":n.purpose=e[r+1],r+=1;break;case"--model":n.model=e[r+1],r+=1;break;case"--dimensions":n.dimensions=Number(e[r+1]),r+=1;break;case"--semantic":n.semantic=!0;break;case"--context":n.context=!0;break;case"--generate":n.generate=!0;break;case"--approve-write":n.approveWrite=!0;break;case"--provider":n.provider=e[r+1],r+=1;break;case"--mode":n.mode=e[r+1],r+=1;break;case"--api-url":n.apiUrl=e[r+1],r+=1;break;case"--api-key":n.apiKey=e[r+1],r+=1;break;case"--email":n.email=e[r+1],r+=1;break;case"--org":n.org=e[r+1],r+=1;break;case"--org-id":n.orgId=e[r+1],r+=1;break;case"--user-id":n.userId=e[r+1],r+=1;break;case"--domain":n.domain=[...n.domain??[],e[r+1]],r+=1;break;case"--file-results":n.fileResults=!0;break;case"--full":n.full=!0;break;case"--fake":n.fake=!0;break;case"--no-color":n.noColor=!0;break;case"--scope":n.scope=e[r+1],r+=1;break;case"--older-than":n.olderThan=Number(e[r+1]),r+=1;break;case"--empty":n.empty=!0;break;case"--archived":n.archived=!0;break;case"--include-archived":n.includeArchived=!0;break;default:throw Error(`Unknown flag: ${i}. Run 'open-knowledge --help' for valid options.`)}}return{positional:t,flags:n}}function ho(e){if(!e)return"";return er[e]??e}function Eo(e,t){let n=Array.from({length:e.length+1},()=>Array(t.length+1).fill(0));for(let r=0;r<=e.length;r+=1)n[r][0]=r;for(let r=0;r<=t.length;r+=1)n[0][r]=r;for(let r=1;r<=e.length;r+=1)for(let i=1;i<=t.length;i+=1){let s=e[r-1]===t[i-1]?0:1;n[r][i]=Math.min(n[r-1][i]+1,n[r][i-1]+1,n[r-1][i-1]+s)}return n[e.length][t.length]}function ko(e){if(!e)return"";let t=[...Zn,...Object.keys(er)],n="",r=Number.POSITIVE_INFINITY;for(let i of t){let s=Eo(e,i);if(s<r)r=s,n=i}return r<=3?n:""}function yo(){return go(process.argv[1]??"")==="knowledge"}function bo(){console.log(`open-knowledge - local agent knowledge store
625
+ updated_at = excluded.updated_at`,[u,"wiki/README.md","Wiki",s.uri,s.hash??null,"active",JSON.stringify({artifact_key:s.key,provenance:Et(s)}),r,r]),lo(e,u,"Wiki",s,Jn(),r)}}function _o(e){if(!e)return;let t=e.trim().toLowerCase();if(t==="local"||t==="offline")return"local";if(t==="hosted"||t==="remote"||t==="knowledge.hasna.xyz")return"hosted";throw Error("Invalid setup mode. Use hosted or local.")}class Yn{options;ensuredWorkspace;cachedConfig;constructor(e={}){this.options=e}get scope(){return this.options.scope??"global"}get workspace(){return this.ensuredWorkspace??wt(this.options.scope,this.options.cwd)}ensureWorkspace(){if(!this.ensuredWorkspace)this.ensuredWorkspace=bt(this.workspace.home);return this.ensuredWorkspace}jsonStorePath(){return this.ensureWorkspace().jsonStorePath}config(){if(!this.cachedConfig){let e=this.ensureWorkspace();this.cachedConfig=vt(e.configPath)}return this.cachedConfig}safetyPolicy(){return pn(this.config(),this.ensureWorkspace())}artifactStore(){return Lt(this.config(),this.ensureWorkspace())}storageContract(){return Kn(this.config(),this.ensureWorkspace(),this.scope)}validateStorage(){return gt(this.config(),this.ensureWorkspace())}setup(e={}){let t=this.ensureWorkspace(),n=this.config(),r=_o(e.mode)??n.mode,i=e.apiUrl?$(e.apiUrl):n.hosted?.api_url?$(n.hosted.api_url):null,s={...n,mode:r,hosted:{...n.hosted??{},...i?{api_url:i}:{}}};return St(t.configPath,s),this.cachedConfig=s,{ok:!0,mode:r,api_url:s.hosted?.api_url??null,config_path:t.configPath,next:r==="hosted"?["open-knowledge auth login --api-key <key>","open-knowledge remote contracts --json"]:["open-knowledge search <query>","knowledge <prompt>"],message:`Set knowledge mode to ${r}`}}authStatus(e=process.env){return Kt(this.config(),e)}saveAuth(e,t=process.env){let n=e.apiUrl??this.config().hosted?.api_url;return Dt({api_key:e.apiKey,email:e.email,org_id:e.orgId,org_slug:e.orgSlug,user_id:e.userId,api_url:n},t)}clearAuth(e=process.env){return Ut(e)}remoteContract(){let e=this.storageContract();return An({mode:this.config().mode,sourceSchemes:this.config().sources.allowed_schemes,storageType:e.artifact_store.type,artifactUriPrefix:e.artifact_store.uri_prefix})}remoteClient(e=process.env){return We.fromConfig(this.config(),e)}paths(){let e=this.ensureWorkspace();return{ok:!0,scope:this.scope,home:e.home,config_path:e.configPath,json_store_path:e.jsonStorePath,knowledge_db_path:e.knowledgeDbPath,artifacts_dir:e.artifactsDir,indexes_dir:e.indexesDir,logs_dir:e.logsDir,runs_dir:e.runsDir,schemas_dir:e.schemasDir,wiki_dir:e.wikiDir,config:this.config(),message:e.home}}initDb(){return x(this.ensureWorkspace().knowledgeDbPath)}dbStats(){let e=this.ensureWorkspace();return x(e.knowledgeDbPath),Ot(e.knowledgeDbPath)}async initWiki(){let e=this.ensureWorkspace();x(e.knowledgeDbPath);let t=await zn(this.artifactStore()),n=b(e.knowledgeDbPath);try{ge(n,t.artifacts),Gn(n,t.artifacts)}finally{n.close()}return t}async compileWiki(e={}){let t=this.ensureWorkspace();return qn({...e,dbPath:t.knowledgeDbPath,store:this.artifactStore()})}async fileAnswer(e){let t=this.ensureWorkspace(),n=await this.retrieveContext({query:e.prompt,limit:e.limit,semantic:e.semantic,modelRef:e.modelRef,dimensions:e.dimensions,fake:e.fake});return Hn({dbPath:t.knowledgeDbPath,store:this.artifactStore(),prompt:e.prompt,answer:e.answer,context:n,approveWrite:e.approveWrite})}lintWiki(){let e=this.ensureWorkspace();return Bn({dbPath:e.knowledgeDbPath})}async ingestManifest(e){let t=this.ensureWorkspace();return yn({dbPath:t.knowledgeDbPath,input:e,config:this.config(),safetyPolicy:this.safetyPolicy()})}async ingestSource(e,t){let n=this.ensureWorkspace();return vn({dbPath:n.knowledgeDbPath,sourceRef:e,purpose:t,config:this.config(),safetyPolicy:this.safetyPolicy()})}async resolveSource(e,t={}){let n=this.ensureWorkspace();return Ke({dbPath:n.knowledgeDbPath,sourceRef:e,purpose:t.purpose,limit:t.limit,safetyPolicy:this.safetyPolicy()})}async consumeOutbox(e){let t=this.ensureWorkspace();return kn({dbPath:t.knowledgeDbPath,input:e,config:this.config(),safetyPolicy:this.safetyPolicy()})}reindexHealth(e={}){let t=this.ensureWorkspace();return Rn({...e,dbPath:t.knowledgeDbPath,config:this.config()})}enqueueReindex(e={}){let t=this.ensureWorkspace();return ft({...e,dbPath:t.knowledgeDbPath,config:this.config()})}async refreshEmbeddings(e={}){let t=this.ensureWorkspace();return xn({...e,dbPath:t.knowledgeDbPath,config:this.config()})}providerStatus(e=process.env){return $t(this.config(),e)}modelRegistry(){return rt(this.config())}embeddingStatus(){let e=this.ensureWorkspace();return Yt(e.knowledgeDbPath)}async indexEmbeddings(e={}){let t=this.ensureWorkspace();return Te({...e,dbPath:t.knowledgeDbPath,config:this.config()})}async semanticSearch(e){let t=this.ensureWorkspace();return Re({...e,dbPath:t.knowledgeDbPath,config:this.config()})}async search(e){let t=this.ensureWorkspace();return Ae({...e,dbPath:t.knowledgeDbPath,config:this.config()})}async retrieveContext(e){let t=this.ensureWorkspace();return Le({...e,dbPath:t.knowledgeDbPath,config:this.config()})}async runPrompt(e){let t=this.ensureWorkspace();return un({...e,dbPath:t.knowledgeDbPath,config:this.config()})}async webSearch(e){let t=this.ensureWorkspace();return Pn({...e,dbPath:t.knowledgeDbPath,config:this.config(),safetyPolicy:this.safetyPolicy()})}}function Vn(e={}){return new Yn(e)}import{basename as go}from"path";var pe={name:"@hasna/knowledge",version:"0.2.26",description:"Agent-friendly local knowledge CLI with JSON output, pagination, and safe destructive actions",type:"module",bin:{knowledge:"bin/open-knowledge.js","open-knowledge":"bin/open-knowledge.js","open-knowledge-mcp":"bin/open-knowledge-mcp.js"},files:["bin","src","docs","LICENSE","README.md"],scripts:{test:"bun test","test:cli":"bun test tests/cli.test.ts",build:"bun build --target=bun --outfile=bin/open-knowledge.js --minify --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/open-knowledge-mcp.js --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",prepublishOnly:"bun run build",postinstall:"bun run build"},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:{"@aws-sdk/client-s3":"^3.1063.0","@aws-sdk/credential-providers":"^3.1063.0","@ai-sdk/anthropic":"^3.0.81","@ai-sdk/deepseek":"^2.0.35","@ai-sdk/openai":"^3.0.68","@modelcontextprotocol/sdk":"^1.29.0",ai:"^6.0.197",zod:"^4.3.6"},devDependencies:{"@types/bun":"^1.3.14"}};var Qn={debug:0,info:1,warn:2,error:3},po=()=>{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 ee(e,t,n){if(Qn[e]<Qn[po()])return;let r={debug:"[DEBUG]",info:"[INFO]",warn:"[WARN]",error:"[ERROR]"}[e],i=n?`${r} ${t} ${JSON.stringify(n)}`:`${r} ${t}`;if(e==="error")console.error(i);else console.error(i)}var Zn=["add","list","get","delete","update","archive","restore","upsert","untag","export","prune","dedupe","stats","paths","setup","auth","remote","storage","db","wiki","source","ingest","reindex","search","web","ask","build","embeddings","providers","safety","help"],er={ls:"list",rm:"delete",edit:"update",unarchive:"restore",knowledge:"ask"};function mo(e){let t=[],n={};for(let r=0;r<e.length;r+=1){let i=e[r];if(!i.startsWith("-")){t.push(i);continue}switch(i){case"--json":n.json=!0;break;case"--yes":case"-y":n.yes=!0;break;case"--help":case"-h":n.help=!0;break;case"--version":case"-v":n.version=!0;break;case"--desc":n.desc=!0;break;case"--page":case"-p":n.page=Number(e[r+1]),r+=1;break;case"--limit":case"-l":n.limit=Number(e[r+1]),r+=1;break;case"--search":case"-s":n.search=e[r+1],r+=1;break;case"--sort":n.sort=e[r+1],r+=1;break;case"--id":n.id=e[r+1],r+=1;break;case"--store":n.store=e[r+1],r+=1;break;case"--title":n.title=e[r+1],r+=1;break;case"--content":n.content=e[r+1],r+=1;break;case"--url":n.url=e[r+1],r+=1;break;case"--tag":case"-t":n.tag=e[r+1],r+=1;break;case"--format":n.format=e[r+1],r+=1;break;case"--completions":n.completions=e[r+1],r+=1;break;case"--purpose":n.purpose=e[r+1],r+=1;break;case"--model":n.model=e[r+1],r+=1;break;case"--dimensions":n.dimensions=Number(e[r+1]),r+=1;break;case"--semantic":n.semantic=!0;break;case"--context":n.context=!0;break;case"--generate":n.generate=!0;break;case"--approve-write":n.approveWrite=!0;break;case"--provider":n.provider=e[r+1],r+=1;break;case"--mode":n.mode=e[r+1],r+=1;break;case"--api-url":n.apiUrl=e[r+1],r+=1;break;case"--api-key":n.apiKey=e[r+1],r+=1;break;case"--email":n.email=e[r+1],r+=1;break;case"--org":n.org=e[r+1],r+=1;break;case"--org-id":n.orgId=e[r+1],r+=1;break;case"--user-id":n.userId=e[r+1],r+=1;break;case"--domain":n.domain=[...n.domain??[],e[r+1]],r+=1;break;case"--file-results":n.fileResults=!0;break;case"--full":n.full=!0;break;case"--fake":n.fake=!0;break;case"--no-color":n.noColor=!0;break;case"--scope":n.scope=e[r+1],r+=1;break;case"--older-than":n.olderThan=Number(e[r+1]),r+=1;break;case"--empty":n.empty=!0;break;case"--archived":n.archived=!0;break;case"--include-archived":n.includeArchived=!0;break;default:throw Error(`Unknown flag: ${i}. Run 'open-knowledge --help' for valid options.`)}}return{positional:t,flags:n}}function ho(e){if(!e)return"";return er[e]??e}function Eo(e,t){let n=Array.from({length:e.length+1},()=>Array(t.length+1).fill(0));for(let r=0;r<=e.length;r+=1)n[r][0]=r;for(let r=0;r<=t.length;r+=1)n[0][r]=r;for(let r=1;r<=e.length;r+=1)for(let i=1;i<=t.length;i+=1){let s=e[r-1]===t[i-1]?0:1;n[r][i]=Math.min(n[r-1][i]+1,n[r][i-1]+1,n[r-1][i-1]+s)}return n[e.length][t.length]}function ko(e){if(!e)return"";let t=[...Zn,...Object.keys(er)],n="",r=Number.POSITIVE_INFINITY;for(let i of t){let s=Eo(e,i);if(s<r)r=s,n=i}return r<=3?n:""}function yo(){return go(process.argv[1]??"")==="knowledge"}function bo(){console.log(`open-knowledge - local agent knowledge store
626
626
 
627
627
  Usage:
628
628
  open-knowledge <command> [options]
@@ -0,0 +1,176 @@
1
+ # Company Wiki Workflow
2
+
3
+ This workflow shows how to use `open-knowledge` as an AI-native company wiki
4
+ layer over source files owned by `open-files`.
5
+
6
+ ## 1. Initialize The Project Workspace
7
+
8
+ ```bash
9
+ open-knowledge paths --scope project --json
10
+ open-knowledge db init --scope project --json
11
+ open-knowledge wiki init --scope project --json
12
+ ```
13
+
14
+ Project state is created under:
15
+
16
+ ```text
17
+ .hasna/apps/knowledge/
18
+ config.json
19
+ knowledge.db
20
+ artifacts/
21
+ indexes/
22
+ logs/
23
+ runs/
24
+ schemas/
25
+ wiki/
26
+ ```
27
+
28
+ ## 2. Import Source Metadata From Open-Files
29
+
30
+ Use an `open-files` manifest with source refs, revisions, permissions, hashes,
31
+ and extracted text:
32
+
33
+ ```json
34
+ {
35
+ "source_ref": "open-files://file/file_handbook/revision/rev_20260608",
36
+ "file_id": "file_handbook",
37
+ "path": "Handbook/Policy.md",
38
+ "name": "Policy.md",
39
+ "mime": "text/markdown",
40
+ "hash": "sha256:...",
41
+ "status": "active",
42
+ "permissions": {
43
+ "mode": "read_only",
44
+ "allowed_purposes": ["knowledge_answer", "knowledge_index"]
45
+ },
46
+ "extracted_text": "Policy text..."
47
+ }
48
+ ```
49
+
50
+ Then ingest it:
51
+
52
+ ```bash
53
+ open-knowledge ingest manifest ./open-files-manifest.jsonl --scope project --json
54
+ ```
55
+
56
+ The knowledge app stores source refs, revisions, redacted chunks, offsets, and
57
+ citations. It does not store raw source bytes or connector credentials.
58
+
59
+ ## 3. Search And Build Context
60
+
61
+ Run local keyword/catalog search first:
62
+
63
+ ```bash
64
+ open-knowledge search "expense policy" --scope project --json
65
+ ```
66
+
67
+ Add deterministic local semantic indexing for a smoke test:
68
+
69
+ ```bash
70
+ open-knowledge embeddings index --scope project --fake --dimensions 8 --json
71
+ open-knowledge search "expense policy" --scope project --semantic --fake --dimensions 8 --json
72
+ ```
73
+
74
+ Ask for an agent-ready context pack:
75
+
76
+ ```bash
77
+ open-knowledge search "expense policy" --scope project --context --json
78
+ ```
79
+
80
+ ## 4. Answer With Citations
81
+
82
+ Create a local citation draft:
83
+
84
+ ```bash
85
+ knowledge "How do we approve expenses?" --scope project --json
86
+ ```
87
+
88
+ Use provider generation explicitly:
89
+
90
+ ```bash
91
+ OPENAI_API_KEY=... \
92
+ knowledge "How do we approve expenses?" \
93
+ --scope project \
94
+ --generate \
95
+ --model openai:gpt-5-mini \
96
+ --json
97
+ ```
98
+
99
+ Every prompt run records `runs`, `run_events`, provider/model metadata, usage,
100
+ citations, and proposed wiki updates.
101
+
102
+ ## 5. Compile Durable Wiki Pages
103
+
104
+ Compile a cited page from indexed chunks:
105
+
106
+ ```bash
107
+ open-knowledge wiki compile "expense policy" \
108
+ --title "Expense Policy" \
109
+ --scope project \
110
+ --json
111
+ ```
112
+
113
+ File an approved answer note:
114
+
115
+ ```bash
116
+ open-knowledge wiki file-answer "How do we approve expenses?" \
117
+ --content "Use manager approval and cite the policy source." \
118
+ --approve-write \
119
+ --scope project \
120
+ --json
121
+ ```
122
+
123
+ Lint the generated wiki:
124
+
125
+ ```bash
126
+ open-knowledge wiki lint --scope project --json
127
+ ```
128
+
129
+ Generated pages are written through the artifact store and cataloged in
130
+ `knowledge.db`; index rows and logs are sharded rather than stored in one large
131
+ Markdown file.
132
+
133
+ ## 6. Keep Sources Fresh
134
+
135
+ Consume open-files outbox events after source changes:
136
+
137
+ ```bash
138
+ open-knowledge reindex outbox ./open-files-outbox.jsonl --scope project --json
139
+ open-knowledge reindex enqueue --scope project --json
140
+ open-knowledge reindex embeddings --scope project --fake --dimensions 8 --json
141
+ ```
142
+
143
+ This invalidates stale source chunks and refreshes embeddings without losing the
144
+ source refs and citation provenance.
145
+
146
+ ## 7. Expose The Wiki To Agents Through MCP
147
+
148
+ Run MCP over stdio:
149
+
150
+ ```bash
151
+ open-knowledge-mcp
152
+ ```
153
+
154
+ Or run local Streamable HTTP:
155
+
156
+ ```bash
157
+ open-knowledge-mcp --http --port 8819
158
+ ```
159
+
160
+ Agents should prefer stable tools such as `knowledge_search`, `knowledge_ask`,
161
+ `knowledge_build`, `knowledge_get`, `knowledge_lint`, and
162
+ `knowledge_run_status`. They can inspect project resources such as
163
+ `knowledge://project/wiki/pages`, `knowledge://project/runs`, and
164
+ `knowledge://project/open-files`.
165
+
166
+ ## 8. Optional Hosted And S3 Mode
167
+
168
+ Hosted mode is only a remote client boundary:
169
+
170
+ ```bash
171
+ open-knowledge setup --mode hosted --api-url https://knowledge.hasna.xyz --scope project --json
172
+ open-knowledge remote contracts --scope project --json
173
+ ```
174
+
175
+ Generated artifacts may use S3 when configured, but raw source files still stay
176
+ in `open-files`.
@@ -0,0 +1,151 @@
1
+ # JSON To SQLite Migration
2
+
3
+ `open-knowledge` began as a simple JSON note store. Current project mode uses a
4
+ Hasna app workspace and a versioned SQLite catalog:
5
+
6
+ ```text
7
+ .hasna/apps/knowledge/
8
+ db.json
9
+ knowledge.db
10
+ artifacts/
11
+ indexes/
12
+ logs/
13
+ runs/
14
+ schemas/
15
+ wiki/
16
+ ```
17
+
18
+ The JSON store remains available for compatibility with note commands such as
19
+ `add`, `list`, `get`, `update`, `delete`, and `export`. The SQLite catalog is
20
+ used for source refs, source revisions, chunks, citations, embeddings, wiki
21
+ pages, generated artifacts, runs, audit events, and reindex jobs.
22
+
23
+ ## What Migrates Automatically
24
+
25
+ Global legacy notes are migrated on first use:
26
+
27
+ ```text
28
+ ~/.open-knowledge/db.json
29
+ ```
30
+
31
+ to:
32
+
33
+ ```text
34
+ ~/.hasna/apps/knowledge/db.json
35
+ ```
36
+
37
+ This happens only when the new Hasna JSON store does not already exist. The
38
+ legacy file is not deleted.
39
+
40
+ Project mode writes directly to:
41
+
42
+ ```text
43
+ <project>/.hasna/apps/knowledge/db.json
44
+ ```
45
+
46
+ when compatibility note commands are used with `--scope project`.
47
+
48
+ ## What Requires Explicit Ingestion
49
+
50
+ SQLite knowledge records are not inferred from old JSON notes automatically.
51
+ Use explicit commands so provenance, permissions, citations, and redaction are
52
+ recorded correctly.
53
+
54
+ Initialize the project catalog:
55
+
56
+ ```bash
57
+ open-knowledge db init --scope project --json
58
+ open-knowledge wiki init --scope project --json
59
+ ```
60
+
61
+ Import open-files manifests:
62
+
63
+ ```bash
64
+ open-knowledge ingest manifest ./open-files-manifest.jsonl --scope project --json
65
+ ```
66
+
67
+ Import one allowed source ref:
68
+
69
+ ```bash
70
+ open-knowledge ingest source file:///absolute/path/to/handbook.md \
71
+ --purpose knowledge_index \
72
+ --scope project \
73
+ --json
74
+ ```
75
+
76
+ Resolve indexed source evidence:
77
+
78
+ ```bash
79
+ open-knowledge source resolve open-files://file/file_123/revision/rev_456 \
80
+ --purpose knowledge_answer \
81
+ --scope project \
82
+ --json
83
+ ```
84
+
85
+ ## Recommended Migration Path
86
+
87
+ 1. Keep the legacy JSON note store as an exportable compatibility layer.
88
+ 2. Run `open-knowledge paths --scope project --json` and confirm the project
89
+ workspace is `.hasna/apps/knowledge`.
90
+ 3. Initialize `knowledge.db` with `open-knowledge db init --scope project`.
91
+ 4. Ingest source manifests from `open-files` rather than copying raw files into
92
+ `open-knowledge`.
93
+ 5. Run `open-knowledge search --scope project --json` to verify source chunks.
94
+ 6. Run `open-knowledge wiki compile` for durable cited pages.
95
+ 7. Run `open-knowledge wiki lint --scope project --json` before treating pages
96
+ as company knowledge.
97
+ 8. Use `open-knowledge export --format jsonl` if legacy notes need to be
98
+ archived or transformed outside the app.
99
+
100
+ ## JSON Output Contracts
101
+
102
+ Use `--json` during migration. Commands return stable objects with `ok: true`
103
+ when successful and command-specific fields such as:
104
+
105
+ - `paths`: workspace paths and config.
106
+ - `db stats`: schema version and table counts.
107
+ - `ingest manifest`: sources, revisions, chunks, redactions, and skipped rows.
108
+ - `source resolve`: read-only source metadata, chunks, citations, and evidence.
109
+ - `search --context`: excerpts, citations, graph evidence, and warnings.
110
+ - `ask|build`: run id, answer, context, citations, proposed wiki updates, write
111
+ policy, usage, and warnings.
112
+ - `wiki compile`: page id, artifact URI, citations written, index updates, and
113
+ log shard key.
114
+
115
+ ## Safety Rules During Migration
116
+
117
+ - Prefer `open-files://` refs for durable company sources.
118
+ - Keep raw source bytes in `open-files`; do not import them as generated wiki
119
+ artifacts.
120
+ - Enable S3 reads only for allowed buckets:
121
+
122
+ ```bash
123
+ HASNA_KNOWLEDGE_ALLOW_S3_READS=1 \
124
+ HASNA_KNOWLEDGE_ALLOWED_S3_BUCKETS=my-bucket \
125
+ open-knowledge ingest manifest s3://my-bucket/path/manifest.jsonl \
126
+ --scope project \
127
+ --json
128
+ ```
129
+
130
+ - Enable web search only when current external context is required:
131
+
132
+ ```bash
133
+ HASNA_KNOWLEDGE_WEB_SEARCH=1 \
134
+ open-knowledge web search "current policy source" --provider openai --json
135
+ ```
136
+
137
+ - Use `--approve-write` only when a generated wiki artifact should be durable.
138
+
139
+ ## Hosted Migration
140
+
141
+ Hosted mode should not change local migration semantics. It only records a
142
+ remote API boundary:
143
+
144
+ ```bash
145
+ open-knowledge setup --mode hosted --api-url https://knowledge.hasna.xyz --scope project --json
146
+ open-knowledge remote contracts --scope project --json
147
+ ```
148
+
149
+ A SaaS wrapper can later sync generated artifacts, run jobs, enforce tenant ACLs,
150
+ and store artifacts in S3, but the local package remains usable without a hosted
151
+ account.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/knowledge",
3
- "version": "0.2.25",
3
+ "version": "0.2.26",
4
4
  "description": "Agent-friendly local knowledge CLI with JSON output, pagination, and safe destructive actions",
5
5
  "type": "module",
6
6
  "bin": {