@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.
|
|
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: {
|
package/bin/open-knowledge.js
CHANGED
|
@@ -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.
|