obsidian-tc 1.17.1 → 1.18.0
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 +1 -1
- package/dist/cli.js +5 -5
- package/dist/cli.js.map +1 -1
- package/dist/plugin/manifest.json +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ See the [repo root README](../../README.md) for project overview and the
|
|
|
9
9
|
|
|
10
10
|
## Status
|
|
11
11
|
|
|
12
|
-
✅ **Shipped — v1.
|
|
12
|
+
✅ **Shipped — v1.18.0.** The full tool surface (157 tools across 31 domains, milestones
|
|
13
13
|
M0–M7) is implemented and released. Built on Bun + Hono with Zod 4 schemas; runs under
|
|
14
14
|
Node `>=24` (the test suite runs vitest under Node for `node:sqlite`).
|
|
15
15
|
|
package/dist/cli.js
CHANGED
|
@@ -642,7 +642,7 @@ Usage:
|
|
|
642
642
|
If no path is given, OBSIDIAN_TC_CONFIG is used. A vault folder boots a single
|
|
643
643
|
vault with id "main" and all defaults; pass a config file for multi-vault, auth,
|
|
644
644
|
ACLs, transports, and embeddings.
|
|
645
|
-
`;class I$ extends Error{cli=!0}function Z6($){return $.find((X)=>!X.startsWith("-"))}function c0($,X){let J=$.indexOf(X);if(J<0)return;let W=$[J+1];if(W===void 0||W.startsWith("-"))throw new I$(`${X} requires a value`);return W}function Nx($){try{let[X,...J]=$;if(X===void 0)return{kind:"serve"};if(X==="version"||X==="--version"||X==="-v")return{kind:"version"};if(X==="help"||X==="--help"||X==="-h")return{kind:"help"};if(X==="serve")return{kind:"serve",input:c0(J,"--config")??Z6(J)};if(X==="token"){let W=J[0];if(W!=="mint")throw new I$(`unknown token subcommand: ${W??"(none)"}`);let Q=J.slice(1),G=["--sub","--aud","--vault","--scopes","--ttl","--config"],Y=Q.filter((B,F)=>{if(B==="--json"||G.includes(B))return!1;let L=Q[F-1];return!(F>0&&L!==void 0&&G.includes(L))}),Z=c0(Q,"--ttl"),U=Z===void 0?void 0:Number(Z);if(U!==void 0&&!Number.isFinite(U))throw new I$(`--ttl must be a number of seconds, got: ${Z}`);if(c0(Q,"--sub")===void 0)throw new I$("token mint requires --sub (the caller identity)");let K=c0(Q,"--config")??Z6(Y);return{kind:"token-mint",...K!==void 0?{configPath:K}:{},...c0(Q,"--sub")!==void 0?{sub:c0(Q,"--sub")}:{},...c0(Q,"--aud")!==void 0?{aud:c0(Q,"--aud")}:{},...c0(Q,"--vault")!==void 0?{vault:c0(Q,"--vault")}:{},...Q.includes("--scopes")?{scopes:Q[Q.indexOf("--scopes")+1]??""}:{},...U!==void 0?{ttl:U}:{},json:Q.includes("--json")}}if(X==="config"){let W=J[0],Q=c0(J,"--config")??Z6(J.slice(1));if(W==="show")return{kind:"config-show",configPath:Q};if(W==="validate")return{kind:"config-validate",configPath:Q};if(W==="explain"){let G=J.slice(1);for(let U of["--source","--config"]){let K=G.indexOf(U);if(K>=0)G.splice(K,2)}let Y=c0(J,"--source"),Z=["env","file","profile","default","derived"];if(Y!==void 0&&!Z.includes(Y))return{kind:"error",message:`--source must be one of ${Z.join("|")}`};return{kind:"config-explain",configPath:c0(J,"--config")??Z6(G.filter((U)=>U!=="--json")),json:J.includes("--json"),...Y!==void 0?{source:Y}:{}}}return{kind:"error",message:`unknown config subcommand: ${W??"(none)"}`}}if(X==="doctor"){let W=J.includes("--json"),Q=c0(J,"--token"),G=J.includes("--probe"),Y=J.filter((U,K)=>{if(U==="--json")return!1;if(U==="--probe")return!1;if(U==="--token")return!1;if(K>0&&J[K-1]==="--token")return!1;return!0}),Z=c0(Y,"--config")??Z6(Y);return{kind:"doctor",...Z!==void 0?{configPath:Z}:{},json:W,probe:G,...Q!==void 0?{token:Q}:{}}}if(X==="plugin"){let W=J[0];if(W==="install"){let Q=c0(J,"--vault")??Z6(J.slice(1));if(!Q)throw new I$("plugin install requires a vault: --vault <path> (or a positional path)");return{kind:"plugin-install",vaultPath:Q}}return{kind:"error",message:`unknown plugin subcommand: ${W??"(none)"}`}}if(X==="cluster"){let W,Q=J,G=J.indexOf("--k");if(G>=0){let Y=J[G+1];if(Y===void 0||Y.startsWith("-"))throw new I$("--k requires a value");if(W=Number.parseInt(Y,10),!Number.isFinite(W)||W<1)return{kind:"error",message:"--k must be a positive integer"};Q=J.filter((Z,U)=>U!==G&&U!==G+1)}return{kind:"cluster",input:c0(Q,"--config")??Z6(Q),k:W}}if(X==="activation-recompute")return{kind:"activation-recompute",input:c0(J,"--config")??Z6(J)};if(X==="index"){let W=[...J];for(let Z of["--vault","--folder","--config"]){let U=W.indexOf(Z);if(U>=0)W.splice(U,2)}let Q=c0(J,"--config")??Z6(W),G=c0(J,"--vault"),Y=c0(J,"--folder");return{kind:"index",...Q!==void 0?{input:Q}:{},...G!==void 0?{vault:G}:{},...Y!==void 0?{folder:Y}:{}}}if(X==="densify-llm"){let W=[...J];for(let G of["--vault","--config","--batch-size","--confidence-floor"]){let Y=W.indexOf(G);if(Y>=0)W.splice(Y,2)}let Q=c0(J,"--vault");return{kind:"densify-llm",input:c0(J,"--config")??Z6(W),...Q!==void 0?{vault:Q}:{}}}if(X==="citation-infer"){let W=(L)=>{let A=c0(J,L);if(A===void 0)return;let N=Number(A);if(!Number.isFinite(N))throw new I$(`${L} must be a number`);return N},Q=[...J];for(let L of["--session","--since","--until","--transcript","--max-judged","--config"]){let A=Q.indexOf(L);if(A>=0)Q.splice(A,2)}let G=c0(J,"--session"),Y=W("--since"),Z=W("--until"),U=c0(J,"--transcript"),K=c0(J,"--max-judged"),B;if(K!==void 0){if(B=Number.parseInt(K,10),!Number.isFinite(B)||B<0)return{kind:"error",message:"--max-judged must be a non-negative integer"}}let F=J.includes("--allow-uncertain");return{kind:"citation-infer",input:c0(J,"--config")??Z6(Q),...G!==void 0?{session:G}:{},...Y!==void 0?{since:Y}:{},...Z!==void 0?{until:Z}:{},...U!==void 0?{transcript:U}:{},...F?{allowUncertain:F}:{},...B!==void 0?{maxJudged:B}:{}}}if(X==="contribution-report"){let W=(U)=>{let K=c0(J,U);if(K===void 0)return;let B=Number(K);if(!Number.isFinite(B))throw new I$(`${U} must be a number`);return B},Q=[...J];for(let U of["--since","--until","--json","--config"]){let K=Q.indexOf(U);if(K>=0)Q.splice(K,2)}let G=W("--since"),Y=W("--until"),Z=c0(J,"--json");return{kind:"contribution-report",input:c0(J,"--config")??Z6(Q),...G!==void 0?{since:G}:{},...Y!==void 0?{until:Y}:{},...Z!==void 0?{json:Z}:{}}}if(X==="note-quality"){let W=[...J];for(let K of["--vault","--flags","--limit","--config"]){let B=W.indexOf(K);if(B>=0)W.splice(B,2)}let Q=c0(J,"--limit"),G=Q===void 0?void 0:Number(Q);if(G!==void 0&&(!Number.isFinite(G)||G<=0))throw new I$("--limit must be a positive number");let Z=c0(J,"--flags")?.split(",").map((K)=>K.trim()).filter(Boolean),U=c0(J,"--vault");return{kind:"note-quality",input:c0(J,"--config")??Z6(W),...U!==void 0?{vault:U}:{},...Z&&Z.length>0?{flags:Z}:{},...G!==void 0?{limit:G}:{}}}if(X==="forget"){let W=[...J].filter((Z)=>Z!=="--erase"&&Z!=="--verify");for(let Z of["--episode","--note","--vault","--config"]){let U=W.indexOf(Z);if(U>=0)W.splice(U,2)}let Q=c0(J,"--episode"),G=c0(J,"--note"),Y=c0(J,"--vault");return{kind:"forget",input:c0(J,"--config")??Z6(W),...Q!==void 0?{episode:Q}:{},...G!==void 0?{note:G}:{},...Y!==void 0?{vault:Y}:{},...J.includes("--erase")?{erase:!0}:{},...J.includes("--verify")?{verify:!0}:{}}}if(X==="gaps"){let W=(F)=>{let L=c0(J,F);if(L===void 0)return;let A=Number(L);if(!Number.isFinite(A))throw new I$(`${F} must be a number`);return A},Q=[...J];for(let F of["--vault","--queries","--threshold","--min-results","--json","--calibrate","--config"]){let L=Q.indexOf(F);if(L>=0)Q.splice(L,2)}let G=c0(J,"--vault"),Y=c0(J,"--queries"),Z=W("--threshold"),U=W("--min-results"),K=c0(J,"--json"),B=c0(J,"--calibrate");return{kind:"gaps",input:c0(J,"--config")??Z6(Q),...G!==void 0?{vault:G}:{},...Y!==void 0?{queries:Y}:{},...Z!==void 0?{threshold:Z}:{},...U!==void 0?{minResults:U}:{},...K!==void 0?{json:K}:{},...B!==void 0?{calibrate:B}:{}}}if(X==="metrics"){let W=(B)=>{let F=c0(J,B);if(F===void 0)return;let L=Number(F);if(!Number.isFinite(L))throw new I$(`${B} must be a number`);return L},Q=[...J];for(let B of["--vault","--since","--until","--stale-days","--json","--config"]){let F=Q.indexOf(B);if(F>=0)Q.splice(F,2)}let G=c0(J,"--vault"),Y=W("--since"),Z=W("--until"),U=W("--stale-days"),K=c0(J,"--json");return{kind:"metrics",input:c0(J,"--config")??Z6(Q),...G!==void 0?{vault:G}:{},...Y!==void 0?{since:Y}:{},...Z!==void 0?{until:Z}:{},...U!==void 0?{staleDays:U}:{},...K!==void 0?{json:K}:{}}}if(X==="reflect"){let W=[...J];for(let Y of["--max-judged","--config"]){let Z=W.indexOf(Y);if(Z>=0)W.splice(Z,2)}let Q=c0(J,"--max-judged"),G;if(Q!==void 0){if(G=Number.parseInt(Q,10),!Number.isFinite(G)||G<0)return{kind:"error",message:"--max-judged must be a non-negative integer"}}return{kind:"reflect",input:c0(J,"--config")??Z6(W),...G!==void 0?{maxJudged:G}:{}}}if(X==="prefetch"){let W=[...J];for(let Z of["--vault","--ttl-hours","--config"]){let U=W.indexOf(Z);if(U>=0)W.splice(U,2)}let Q=c0(J,"--vault"),G=c0(J,"--ttl-hours"),Y;if(G!==void 0){if(Y=Number(G),!Number.isFinite(Y)||Y<=0)return{kind:"error",message:"--ttl-hours must be a positive number"}}return{kind:"prefetch",input:c0(J,"--config")??Z6(W),...Q!==void 0?{vault:Q}:{},...Y!==void 0?{ttlHours:Y}:{}}}if(X.startsWith("-"))return{kind:"error",message:`unknown option: ${X}`};return{kind:"serve",input:X}}catch(X){if(X instanceof I$)return{kind:"error",message:X.message};throw X}}function hj0($){return FW({vaults:[{id:"main",path:gj0($)}]})}function Vx($){let X=$??process.env.OBSIDIAN_TC_CONFIG;if(!X)throw new I$("no vault or config given: pass a vault folder or a config.json (or set OBSIDIAN_TC_CONFIG).");let J;try{J=vj0(X)}catch{throw new I$(`no such vault folder or config file: ${X}`)}return J.isDirectory()?hj0(X):pK(X)}var mj0=/(secret|token|password|key)$/i,uj0=/^(authorization|proxy-authorization|cookie|set-cookie|x-api-key|x-auth-token|api-key)$/i;function nK($){if(Array.isArray($))return $.map(nK);if($&&typeof $==="object"){let X={};for(let[J,W]of Object.entries($))X[J]=typeof W==="string"&&W.length>0&&(mj0.test(J)||uj0.test(J))?"<redacted>":nK(W);return X}return $}import{mkdirSync as YO0}from"node:fs";var M$="1.
|
|
645
|
+
`;class I$ extends Error{cli=!0}function Z6($){return $.find((X)=>!X.startsWith("-"))}function c0($,X){let J=$.indexOf(X);if(J<0)return;let W=$[J+1];if(W===void 0||W.startsWith("-"))throw new I$(`${X} requires a value`);return W}function Nx($){try{let[X,...J]=$;if(X===void 0)return{kind:"serve"};if(X==="version"||X==="--version"||X==="-v")return{kind:"version"};if(X==="help"||X==="--help"||X==="-h")return{kind:"help"};if(X==="serve")return{kind:"serve",input:c0(J,"--config")??Z6(J)};if(X==="token"){let W=J[0];if(W!=="mint")throw new I$(`unknown token subcommand: ${W??"(none)"}`);let Q=J.slice(1),G=["--sub","--aud","--vault","--scopes","--ttl","--config"],Y=Q.filter((B,F)=>{if(B==="--json"||G.includes(B))return!1;let L=Q[F-1];return!(F>0&&L!==void 0&&G.includes(L))}),Z=c0(Q,"--ttl"),U=Z===void 0?void 0:Number(Z);if(U!==void 0&&!Number.isFinite(U))throw new I$(`--ttl must be a number of seconds, got: ${Z}`);if(c0(Q,"--sub")===void 0)throw new I$("token mint requires --sub (the caller identity)");let K=c0(Q,"--config")??Z6(Y);return{kind:"token-mint",...K!==void 0?{configPath:K}:{},...c0(Q,"--sub")!==void 0?{sub:c0(Q,"--sub")}:{},...c0(Q,"--aud")!==void 0?{aud:c0(Q,"--aud")}:{},...c0(Q,"--vault")!==void 0?{vault:c0(Q,"--vault")}:{},...Q.includes("--scopes")?{scopes:Q[Q.indexOf("--scopes")+1]??""}:{},...U!==void 0?{ttl:U}:{},json:Q.includes("--json")}}if(X==="config"){let W=J[0],Q=c0(J,"--config")??Z6(J.slice(1));if(W==="show")return{kind:"config-show",configPath:Q};if(W==="validate")return{kind:"config-validate",configPath:Q};if(W==="explain"){let G=J.slice(1);for(let U of["--source","--config"]){let K=G.indexOf(U);if(K>=0)G.splice(K,2)}let Y=c0(J,"--source"),Z=["env","file","profile","default","derived"];if(Y!==void 0&&!Z.includes(Y))return{kind:"error",message:`--source must be one of ${Z.join("|")}`};return{kind:"config-explain",configPath:c0(J,"--config")??Z6(G.filter((U)=>U!=="--json")),json:J.includes("--json"),...Y!==void 0?{source:Y}:{}}}return{kind:"error",message:`unknown config subcommand: ${W??"(none)"}`}}if(X==="doctor"){let W=J.includes("--json"),Q=c0(J,"--token"),G=J.includes("--probe"),Y=J.filter((U,K)=>{if(U==="--json")return!1;if(U==="--probe")return!1;if(U==="--token")return!1;if(K>0&&J[K-1]==="--token")return!1;return!0}),Z=c0(Y,"--config")??Z6(Y);return{kind:"doctor",...Z!==void 0?{configPath:Z}:{},json:W,probe:G,...Q!==void 0?{token:Q}:{}}}if(X==="plugin"){let W=J[0];if(W==="install"){let Q=c0(J,"--vault")??Z6(J.slice(1));if(!Q)throw new I$("plugin install requires a vault: --vault <path> (or a positional path)");return{kind:"plugin-install",vaultPath:Q}}return{kind:"error",message:`unknown plugin subcommand: ${W??"(none)"}`}}if(X==="cluster"){let W,Q=J,G=J.indexOf("--k");if(G>=0){let Y=J[G+1];if(Y===void 0||Y.startsWith("-"))throw new I$("--k requires a value");if(W=Number.parseInt(Y,10),!Number.isFinite(W)||W<1)return{kind:"error",message:"--k must be a positive integer"};Q=J.filter((Z,U)=>U!==G&&U!==G+1)}return{kind:"cluster",input:c0(Q,"--config")??Z6(Q),k:W}}if(X==="activation-recompute")return{kind:"activation-recompute",input:c0(J,"--config")??Z6(J)};if(X==="index"){let W=[...J];for(let Z of["--vault","--folder","--config"]){let U=W.indexOf(Z);if(U>=0)W.splice(U,2)}let Q=c0(J,"--config")??Z6(W),G=c0(J,"--vault"),Y=c0(J,"--folder");return{kind:"index",...Q!==void 0?{input:Q}:{},...G!==void 0?{vault:G}:{},...Y!==void 0?{folder:Y}:{}}}if(X==="densify-llm"){let W=[...J];for(let G of["--vault","--config","--batch-size","--confidence-floor"]){let Y=W.indexOf(G);if(Y>=0)W.splice(Y,2)}let Q=c0(J,"--vault");return{kind:"densify-llm",input:c0(J,"--config")??Z6(W),...Q!==void 0?{vault:Q}:{}}}if(X==="citation-infer"){let W=(L)=>{let A=c0(J,L);if(A===void 0)return;let N=Number(A);if(!Number.isFinite(N))throw new I$(`${L} must be a number`);return N},Q=[...J];for(let L of["--session","--since","--until","--transcript","--max-judged","--config"]){let A=Q.indexOf(L);if(A>=0)Q.splice(A,2)}let G=c0(J,"--session"),Y=W("--since"),Z=W("--until"),U=c0(J,"--transcript"),K=c0(J,"--max-judged"),B;if(K!==void 0){if(B=Number.parseInt(K,10),!Number.isFinite(B)||B<0)return{kind:"error",message:"--max-judged must be a non-negative integer"}}let F=J.includes("--allow-uncertain");return{kind:"citation-infer",input:c0(J,"--config")??Z6(Q),...G!==void 0?{session:G}:{},...Y!==void 0?{since:Y}:{},...Z!==void 0?{until:Z}:{},...U!==void 0?{transcript:U}:{},...F?{allowUncertain:F}:{},...B!==void 0?{maxJudged:B}:{}}}if(X==="contribution-report"){let W=(U)=>{let K=c0(J,U);if(K===void 0)return;let B=Number(K);if(!Number.isFinite(B))throw new I$(`${U} must be a number`);return B},Q=[...J];for(let U of["--since","--until","--json","--config"]){let K=Q.indexOf(U);if(K>=0)Q.splice(K,2)}let G=W("--since"),Y=W("--until"),Z=c0(J,"--json");return{kind:"contribution-report",input:c0(J,"--config")??Z6(Q),...G!==void 0?{since:G}:{},...Y!==void 0?{until:Y}:{},...Z!==void 0?{json:Z}:{}}}if(X==="note-quality"){let W=[...J];for(let K of["--vault","--flags","--limit","--config"]){let B=W.indexOf(K);if(B>=0)W.splice(B,2)}let Q=c0(J,"--limit"),G=Q===void 0?void 0:Number(Q);if(G!==void 0&&(!Number.isFinite(G)||G<=0))throw new I$("--limit must be a positive number");let Z=c0(J,"--flags")?.split(",").map((K)=>K.trim()).filter(Boolean),U=c0(J,"--vault");return{kind:"note-quality",input:c0(J,"--config")??Z6(W),...U!==void 0?{vault:U}:{},...Z&&Z.length>0?{flags:Z}:{},...G!==void 0?{limit:G}:{}}}if(X==="forget"){let W=[...J].filter((Z)=>Z!=="--erase"&&Z!=="--verify");for(let Z of["--episode","--note","--vault","--config"]){let U=W.indexOf(Z);if(U>=0)W.splice(U,2)}let Q=c0(J,"--episode"),G=c0(J,"--note"),Y=c0(J,"--vault");return{kind:"forget",input:c0(J,"--config")??Z6(W),...Q!==void 0?{episode:Q}:{},...G!==void 0?{note:G}:{},...Y!==void 0?{vault:Y}:{},...J.includes("--erase")?{erase:!0}:{},...J.includes("--verify")?{verify:!0}:{}}}if(X==="gaps"){let W=(F)=>{let L=c0(J,F);if(L===void 0)return;let A=Number(L);if(!Number.isFinite(A))throw new I$(`${F} must be a number`);return A},Q=[...J];for(let F of["--vault","--queries","--threshold","--min-results","--json","--calibrate","--config"]){let L=Q.indexOf(F);if(L>=0)Q.splice(L,2)}let G=c0(J,"--vault"),Y=c0(J,"--queries"),Z=W("--threshold"),U=W("--min-results"),K=c0(J,"--json"),B=c0(J,"--calibrate");return{kind:"gaps",input:c0(J,"--config")??Z6(Q),...G!==void 0?{vault:G}:{},...Y!==void 0?{queries:Y}:{},...Z!==void 0?{threshold:Z}:{},...U!==void 0?{minResults:U}:{},...K!==void 0?{json:K}:{},...B!==void 0?{calibrate:B}:{}}}if(X==="metrics"){let W=(B)=>{let F=c0(J,B);if(F===void 0)return;let L=Number(F);if(!Number.isFinite(L))throw new I$(`${B} must be a number`);return L},Q=[...J];for(let B of["--vault","--since","--until","--stale-days","--json","--config"]){let F=Q.indexOf(B);if(F>=0)Q.splice(F,2)}let G=c0(J,"--vault"),Y=W("--since"),Z=W("--until"),U=W("--stale-days"),K=c0(J,"--json");return{kind:"metrics",input:c0(J,"--config")??Z6(Q),...G!==void 0?{vault:G}:{},...Y!==void 0?{since:Y}:{},...Z!==void 0?{until:Z}:{},...U!==void 0?{staleDays:U}:{},...K!==void 0?{json:K}:{}}}if(X==="reflect"){let W=[...J];for(let Y of["--max-judged","--config"]){let Z=W.indexOf(Y);if(Z>=0)W.splice(Z,2)}let Q=c0(J,"--max-judged"),G;if(Q!==void 0){if(G=Number.parseInt(Q,10),!Number.isFinite(G)||G<0)return{kind:"error",message:"--max-judged must be a non-negative integer"}}return{kind:"reflect",input:c0(J,"--config")??Z6(W),...G!==void 0?{maxJudged:G}:{}}}if(X==="prefetch"){let W=[...J];for(let Z of["--vault","--ttl-hours","--config"]){let U=W.indexOf(Z);if(U>=0)W.splice(U,2)}let Q=c0(J,"--vault"),G=c0(J,"--ttl-hours"),Y;if(G!==void 0){if(Y=Number(G),!Number.isFinite(Y)||Y<=0)return{kind:"error",message:"--ttl-hours must be a positive number"}}return{kind:"prefetch",input:c0(J,"--config")??Z6(W),...Q!==void 0?{vault:Q}:{},...Y!==void 0?{ttlHours:Y}:{}}}if(X.startsWith("-"))return{kind:"error",message:`unknown option: ${X}`};return{kind:"serve",input:X}}catch(X){if(X instanceof I$)return{kind:"error",message:X.message};throw X}}function hj0($){return FW({vaults:[{id:"main",path:gj0($)}]})}function Vx($){let X=$??process.env.OBSIDIAN_TC_CONFIG;if(!X)throw new I$("no vault or config given: pass a vault folder or a config.json (or set OBSIDIAN_TC_CONFIG).");let J;try{J=vj0(X)}catch{throw new I$(`no such vault folder or config file: ${X}`)}return J.isDirectory()?hj0(X):pK(X)}var mj0=/(secret|token|password|key)$/i,uj0=/^(authorization|proxy-authorization|cookie|set-cookie|x-api-key|x-auth-token|api-key)$/i;function nK($){if(Array.isArray($))return $.map(nK);if($&&typeof $==="object"){let X={};for(let[J,W]of Object.entries($))X[J]=typeof W==="string"&&W.length>0&&(mj0.test(J)||uj0.test(J))?"<redacted>":nK(W);return X}return $}import{mkdirSync as YO0}from"node:fs";var M$="1.18.0";import{join as XO0}from"node:path";import{createHash as cj0}from"node:crypto";function pj0($){return cj0("sha256").update($,"utf8").digest("hex")}function nj0($){$.exec(`CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
646
646
|
version TEXT PRIMARY KEY,
|
|
647
647
|
applied_at INTEGER NOT NULL,
|
|
648
648
|
obsidian_tc_version TEXT NOT NULL,
|
|
@@ -2197,7 +2197,7 @@ OPEN CONTRADICTIONS:
|
|
|
2197
2197
|
OPEN CONTRADICTIONS:`,K.length===0?"(none)":K.join(`
|
|
2198
2198
|
|
|
2199
2199
|
`)].join(`
|
|
2200
|
-
`),chunksUsed:L,chunksDropped:$.length-L,contradictionsUsed:B,contradictionsDropped:X.length-B}}async function dB0($){let X=$.roles;if(!X)return{ok:!1,detail:{skipped:"no gateway roles"}};let J=$.db.prepare("SELECT DISTINCT vault_id FROM chunks").all().map((Y)=>Y.vault_id);if(J.length===0)return{ok:!0,detail:{skipped:"no chunks"}};let W=$.db.prepare("SELECT 1 AS x FROM sqlite_master WHERE type = 'table' AND name = 'contradictions'").get()!==void 0,Q=uJ(new Date($.now())),G=[];for(let Y of J){let Z=$.db.prepare("SELECT path, chunk_index, headings, content FROM chunks WHERE vault_id = ? ORDER BY updated_at DESC LIMIT ?").all(Y,MF$);if(Z.length===0)continue;let U=W?$.db.prepare("SELECT id, source_path, conflict_path, judge_verdict, judge_rationale FROM contradictions WHERE status = 'open' AND vault_id = ? ORDER BY detected_at DESC LIMIT ?").all(Y,EF$):[],K=SF$(Z,U,$.maxPromptChars??RF$,uB0.length);if(K.chunksDropped>0||K.contradictionsDropped>0)$.log?.(`synthesis: prompt budget dropped ${K.chunksDropped} chunk(s) and ${K.contradictionsDropped} contradiction(s) for vault ${Y} — raise plane.maxPromptChars if the synthesize role has a larger context`);let B=await X.synthesize(q4(uB0,K.message)),F;try{F=CF$(B.text)}catch(L){return{ok:!1,detail:{vault_id:Y,error:L.message}}}$.db.prepare("INSERT INTO syntheses (vault_id, iso_year, iso_week, generated_at, cluster_count, pattern_count, clusters, patterns, judge_model) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(vault_id, iso_year, iso_week) DO UPDATE SET generated_at = excluded.generated_at, cluster_count = excluded.cluster_count, pattern_count = excluded.pattern_count, clusters = excluded.clusters, patterns = excluded.patterns, judge_model = excluded.judge_model").run(Y,Q.year,Q.week,$.now(),F.clusters.length,F.patterns.length,JSON.stringify(F.clusters),JSON.stringify(F.patterns),B.model),G.push({vault_id:Y,patterns:F.patterns.length,clusters:F.clusters.length,chunks_used:K.chunksUsed,chunks_dropped:K.chunksDropped,contradictions_used:K.contradictionsUsed,contradictions_dropped:K.contradictionsDropped})}if(G.length===0)return{ok:!0,detail:{skipped:"no chunks"}};return{ok:!0,detail:{iso_year:Q.year,iso_week:Q.week,vaults:G}}}function RD($,X,J){return async()=>{let W=J.now(),Q;try{Q=await X()}catch(G){throw cB0(J,$,W,{ok:!1,detail:{error:G.message}}),G}if(cB0(J,$,W,Q),!Q.ok)throw Error(`${$} job failed: ${JSON.stringify(Q.detail??{})}`)}}function cB0($,X,J,W){if(!K$($.db,"job_runs"))return;try{$.db.prepare("INSERT INTO job_runs (job, started_at, finished_at, ok, detail) VALUES (?, ?, ?, ?, ?)").run(X,J,$.now(),W.ok?1:0,W.detail?JSON.stringify(W.detail):null)}catch{}}import{randomUUID as zF$}from"node:crypto";function wF$($){if(typeof $!=="string"||$.length===0)return null;try{let X=JSON.parse($);if(X!==null&&typeof X==="object"&&typeof X.ok==="boolean")return X}catch{}return null}function CD($){return{id:$.id,type:$.type,class:$.class,state:$.state,attempt:$.attempt,maxAttempts:$.max_attempts,nextAttemptAt:$.next_attempt_at,leaseOwner:$.lease_owner,leaseExpiresAt:$.lease_expires_at,cancelRequested:$.cancel_requested!==0,checkpoint:$.checkpoint==null?void 0:JSON.parse($.checkpoint),payload:$.payload==null?void 0:JSON.parse($.payload),idempotencyKey:$.idempotency_key,lastError:$.last_error,createdAt:$.created_at,updatedAt:$.updated_at,vaultId:$.vault_id??null,caller:$.caller??null,outcome:wF$($.outcome)}}var kF$=30000,_F$=5,yF$=1000,fF$=300000,xF$=50;class dk{taskListeners=new Set;db;now;leaseMsValue;maxAttempts;backoffBaseMs;maxBackoffMs;sql;constructor($,X={}){this.sql=X.sql,this.db=$,this.now=X.now??Date.now,this.leaseMsValue=X.leaseMs??kF$,this.maxAttempts=X.maxAttempts??_F$,this.backoffBaseMs=X.backoffBaseMs??yF$,this.maxBackoffMs=X.maxBackoffMs??fF$}get leaseMs(){return this.leaseMsValue}backoff($){return Math.min(this.backoffBaseMs*2**Math.max(0,$-1),this.maxBackoffMs)}enqueue($,X={}){let J=this.now();if(X.idempotencyKey){let G=this.db.prepare("SELECT * FROM jobs WHERE idempotency_key = ?").get(X.idempotencyKey);if(G){let Y=G.state==="complete"||G.state==="failed";if(X.replaceIfTerminal&&Y)this.db.prepare("DELETE FROM jobs WHERE id = ?").run(G.id);else return CD(G)}}let W=zF$(),Q={id:W,type:$,class:X.class??$,max_attempts:X.maxAttempts??this.maxAttempts,payload:X.payload===void 0?null:JSON.stringify(X.payload),idempotency_key:X.idempotencyKey??null,created_at:J,updated_at:J,vault_id:X.owner?.vaultId??null,caller:X.owner?.caller??null};try{this.db.prepare(`INSERT INTO jobs (id, type, class, state, attempt, max_attempts, next_attempt_at, payload, idempotency_key, created_at, updated_at, vault_id, caller)
|
|
2200
|
+
`),chunksUsed:L,chunksDropped:$.length-L,contradictionsUsed:B,contradictionsDropped:X.length-B}}async function dB0($){let X=$.roles;if(!X)return{ok:!1,detail:{skipped:"no gateway roles"}};let J=$.db.prepare("SELECT DISTINCT vault_id FROM chunks").all().map((Y)=>Y.vault_id);if(J.length===0)return{ok:!0,detail:{skipped:"no chunks"}};let W=$.db.prepare("SELECT 1 AS x FROM sqlite_master WHERE type = 'table' AND name = 'contradictions'").get()!==void 0,Q=uJ(new Date($.now())),G=[];for(let Y of J){let Z=$.db.prepare("SELECT path, chunk_index, headings, content FROM chunks WHERE vault_id = ? ORDER BY updated_at DESC LIMIT ?").all(Y,MF$);if(Z.length===0)continue;let U=W?$.db.prepare("SELECT id, source_path, conflict_path, judge_verdict, judge_rationale FROM contradictions WHERE status = 'open' AND vault_id = ? ORDER BY detected_at DESC LIMIT ?").all(Y,EF$):[],K=SF$(Z,U,$.maxPromptChars??RF$,uB0.length);if(K.chunksDropped>0||K.contradictionsDropped>0)$.log?.(`synthesis: prompt budget dropped ${K.chunksDropped} chunk(s) and ${K.contradictionsDropped} contradiction(s) for vault ${Y} — raise plane.maxPromptChars if the synthesize role has a larger context`);let B=await X.synthesize(q4(uB0,K.message)),F;try{F=CF$(B.text)}catch(L){return{ok:!1,detail:{vault_id:Y,error:L.message}}}$.db.prepare("INSERT INTO syntheses (vault_id, iso_year, iso_week, generated_at, cluster_count, pattern_count, clusters, patterns, judge_model) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(vault_id, iso_year, iso_week) DO UPDATE SET generated_at = excluded.generated_at, cluster_count = excluded.cluster_count, pattern_count = excluded.pattern_count, clusters = excluded.clusters, patterns = excluded.patterns, judge_model = excluded.judge_model").run(Y,Q.year,Q.week,$.now(),F.clusters.length,F.patterns.length,JSON.stringify(F.clusters),JSON.stringify(F.patterns),B.model),G.push({vault_id:Y,patterns:F.patterns.length,clusters:F.clusters.length,chunks_used:K.chunksUsed,chunks_dropped:K.chunksDropped,contradictions_used:K.contradictionsUsed,contradictions_dropped:K.contradictionsDropped})}if(G.length===0)return{ok:!0,detail:{skipped:"no chunks"}};return{ok:!0,detail:{iso_year:Q.year,iso_week:Q.week,vaults:G}}}function RD($,X,J){return async()=>{let W=J.now(),Q;try{Q=await X()}catch(G){throw cB0(J,$,W,{ok:!1,detail:{error:G.message}}),G}if(cB0(J,$,W,Q),!Q.ok)throw Error(`${$} job failed: ${JSON.stringify(Q.detail??{})}`)}}function cB0($,X,J,W){if(!K$($.db,"job_runs"))return;try{$.db.prepare("INSERT INTO job_runs (job, started_at, finished_at, ok, detail) VALUES (?, ?, ?, ?, ?)").run(X,J,$.now(),W.ok?1:0,W.detail?JSON.stringify(W.detail):null)}catch{}}import{randomUUID as zF$}from"node:crypto";function wF$($){if(typeof $!=="string"||$.length===0)return null;try{let X=JSON.parse($);if(X!==null&&typeof X==="object"&&typeof X.ok==="boolean")return X}catch{}return null}function CD($){return{id:$.id,type:$.type,class:$.class,state:$.state,attempt:$.attempt,maxAttempts:$.max_attempts,nextAttemptAt:$.next_attempt_at,leaseOwner:$.lease_owner,leaseExpiresAt:$.lease_expires_at,cancelRequested:$.cancel_requested!==0,checkpoint:$.checkpoint==null?void 0:JSON.parse($.checkpoint),payload:$.payload==null?void 0:JSON.parse($.payload),idempotencyKey:$.idempotency_key,lastError:$.last_error,createdAt:$.created_at,updatedAt:$.updated_at,vaultId:$.vault_id??null,caller:$.caller??null,outcome:wF$($.outcome)}}var kF$=30000,_F$=5,yF$=1000,fF$=300000,xF$=50;class dk{taskListeners=new Set;db;now;leaseMsValue;maxAttempts;backoffBaseMs;maxBackoffMs;sql;constructor($,X={}){this.sql=X.sql,this.db=$,this.now=X.now??Date.now,this.leaseMsValue=X.leaseMs??kF$,this.maxAttempts=X.maxAttempts??_F$,this.backoffBaseMs=X.backoffBaseMs??yF$,this.maxBackoffMs=X.maxBackoffMs??fF$}get leaseMs(){return this.leaseMsValue}backoff($){return Math.min(this.backoffBaseMs*2**Math.max(0,$-1),this.maxBackoffMs)}enqueue($,X={}){let J=this.now();if(X.idempotencyKey){let G=this.db.prepare("SELECT * FROM jobs WHERE idempotency_key = ?").get(X.idempotencyKey);if(G){let Y=G.state==="complete"||G.state==="failed";if(X.replaceIfTerminal&&Y||X.replaceIfFailed&&G.state==="failed")this.db.prepare("DELETE FROM jobs WHERE id = ?").run(G.id);else return CD(G)}}let W=zF$(),Q={id:W,type:$,class:X.class??$,max_attempts:X.maxAttempts??this.maxAttempts,payload:X.payload===void 0?null:JSON.stringify(X.payload),idempotency_key:X.idempotencyKey??null,created_at:J,updated_at:J,vault_id:X.owner?.vaultId??null,caller:X.owner?.caller??null};try{this.db.prepare(`INSERT INTO jobs (id, type, class, state, attempt, max_attempts, next_attempt_at, payload, idempotency_key, created_at, updated_at, vault_id, caller)
|
|
2201
2201
|
VALUES (?, ?, ?, 'queued', 0, ?, ?, ?, ?, ?, ?, ?, ?)`).run(Q.id,Q.type,Q.class,Q.max_attempts,Q.created_at,Q.payload,Q.idempotency_key,Q.created_at,Q.updated_at,Q.vault_id,Q.caller)}catch(G){if(X.idempotencyKey){let Y=this.db.prepare("SELECT * FROM jobs WHERE idempotency_key = ?").get(X.idempotencyKey);if(Y)return CD(Y)}throw G}return this.get(W)}get($){let X=this.db.prepare("SELECT * FROM jobs WHERE id = ?").get($);return X?CD(X):null}listByState($){return this.db.prepare("SELECT * FROM jobs WHERE state = ? ORDER BY created_at ASC").all($).map(CD)}claim($){let X=this.now(),J=$.leaseMs??this.leaseMsValue;return f4(this.db,"job_claim",()=>{let W=$.types?.length?`AND type IN (${$.types.map(()=>"?").join(",")})`:"",Q=this.db.prepare(`SELECT * FROM jobs
|
|
2202
2202
|
WHERE (
|
|
2203
2203
|
state = 'queued'
|
|
@@ -2294,8 +2294,8 @@ parentPort.on("message", (job) => {
|
|
|
2294
2294
|
error_code, duration_ms, result_size, summary, tags, trust, eligibility,
|
|
2295
2295
|
blocked, prev_id
|
|
2296
2296
|
FROM agent_episodes WHERE ${Q.join(" AND ")}`),Y=(L)=>{let A=[L,X()];if(!J.any_caller)A.push(W.caller??null);return G.get(...A)},Z=[],U=new Set,K=J.id;while(K!==null&&Z.length<J.k&&!U.has(K)){U.add(K);let L=Y(K);if(!L)break;Z.push(L),K=L.prev_id}let B=Z.length===J.k&&Z[Z.length-1]?.prev_id!==null,F=k_($.edb,Z);return{available:!0,chain:Z.map((L)=>__(L,F)),truncated:B}}}),g({name:"episode_stats",domain:"knowledge",description:"Aggregate activity counts over the experiential episode log WITHOUT returning any episode content. work_search/work_episodes are all-or-nothing: seeing activity patterns otherwise requires admin:workspace, which also grants full row content. This returns counts only, so an operator can answer 'what is this agent doing' without reading what it did. Grouping by caller is not offered — the group_by enum excludes it deliberately. Buckets smaller than min_bucket are withheld and summed into `suppressed`, because a count of 1 in a narrow bucket is equivalent to reading the row.",inputSchema:H.object({group_by:H.enum(["tool","status","eligibility"]).default("tool"),...y_,min_bucket:H.number().int().min(2).max(1000).default(5),limit:H.number().int().positive().max(200).default(50)}).strict(),outputSchema:F4({group_by:H.string(),min_bucket:H.number(),buckets:H.array(H.object({key:H.string().nullable(),count:H.number()})),suppressed:H.number(),suppressed_buckets:H.number(),total:H.number()}),requiredScopes:["read:workspace"],tags:["experiential"],handler:(J,W)=>{if(!$.edb)return B4;let Q=["blocked = 0","(valid_until IS NULL OR valid_until > ?)"],G=[X()];if(J.since!==void 0)Q.push("ts >= ?"),G.push(J.since);if(J.until!==void 0)Q.push("ts <= ?"),G.push(J.until);let Y=J.group_by,Z=$.edb.prepare(`SELECT ${Y} AS key, COUNT(*) AS n FROM agent_episodes
|
|
2297
|
-
WHERE ${Q.join(" AND ")} GROUP BY ${Y} ORDER BY n DESC`).all(...G),U=Z.filter((B)=>B.n>=J.min_bucket),K=Z.filter((B)=>B.n<J.min_bucket);return{available:!0,group_by:J.group_by,min_bucket:J.min_bucket,buckets:U.slice(0,J.limit).map((B)=>({key:B.key,count:B.n})),suppressed:K.reduce((B,F)=>B+F.n,0),suppressed_buckets:K.length,total:Z.reduce((B,F)=>B+F.n,0)}}}),g({name:"work_forget",domain:"knowledge",description:"Tombstone an experiential episode (the THE-238 control-1 blocklist, surfaced as the first-party forget verb). A forgotten episode never surfaces in work_search again; each successful forget appends a THE-239 hash-chained forget_log row for forensics. Idempotent: a repeat call, foreign, or unknown episode id is a silent no-op (forgotten:false) that appends NO additional log row. P1.7: only your OWN episodes unless you hold admin:workspace — a foreign or unknown id is a silent no-op, not an error.",inputSchema:H.object({episode_id:H.string().min(1)}).strict(),outputSchema:F4({episode_id:H.string(),forgotten:H.boolean()}),requiredScopes:["write:workspace"],tags:["experiential"],handler:(J,W)=>{if(!$.edb)return B4;let Q=0;$.edb.exec("BEGIN");try{if(Q=(Y7(W)?$.edb.prepare("UPDATE agent_episodes SET blocked = 1 WHERE id = ? AND blocked = 0").run(J.episode_id):$.edb.prepare("UPDATE agent_episodes SET blocked = 1 WHERE id = ? AND blocked = 0 AND caller IS ?").run(J.episode_id,W.caller??null)).changes,Q>0)hB($.edb,{ts:X(),kind:"episode",target:J.episode_id,mode:"tombstone",details:{actor:W.caller??null,source:"work_forget"}});$.edb.exec("COMMIT")}catch(G){throw $.edb.exec("ROLLBACK"),G}return{available:!0,episode_id:J.episode_id,forgotten:Q>0}}}),g({name:"record_retrieval_feedback",domain:"knowledge",description:"Report which retrieved chunks actually helped. CALL THIS after you act on a search result: outcome (-1|0|+1) = did acting on it lead somewhere good, feedback (-1|0|+1) = was it the right chunk. Stamp the chunks you genuinely used, not every hit, and stamp -1 when a confidently-returned chunk was wrong — a negative is worth more than silence. This is the only signal separating a chunk that gets RETRIEVED from one that gets USED: it feeds the ACT-R activation recompute, so stamping is what makes later retrieval better, and not stamping leaves ranking blind. Targets your most recent retrieval event(s) for that chunk (last_n, default 1). Returns `updated`; when that is 0 it also returns `reason` — `session_scope` (you own retrievals for this chunk, none in the current scope) or `no_owned_retrievals` (nothing of yours matches), so a no-op is never silent. You may only stamp retrievals your own caller produced (THE-568); an unidentified caller cannot stamp, and admin:workspace crosses both that and the session scope.",inputSchema:H.object({chunk_id:H.string().min(1),feedback:H.number().int().min(-1).max(1).optional(),outcome:H.number().int().min(-1).max(1).optional(),session_id:H.string().optional(),last_n:H.number().int().positive().max(50).default(1)}).strict().refine((J)=>J.feedback!==void 0||J.outcome!==void 0,{message:"provide feedback and/or outcome"}),outputSchema:F4({chunk_id:H.string(),updated:H.number().int(),reason:H.enum(["session_scope","no_owned_retrievals"]).optional()}),requiredScopes:["write:workspace"],tags:["experiential"],handler:(J,W)=>$.edb?gA0($.edb,J,W):B4}),g({name:"note_quality_report",domain:"knowledge",description:"Read-only note-health report from the note_quality rollup (THE-537): which notes are duplicated, orphaned, stale by edit or by access, contradicted, or tombstoned — with the raw components behind each verdict. quality_score is NULL when there is no usage evidence yet, which means UNMEASURED, not bad. Populated by the offline `obsidian-tc note-quality` pass; computed_at tells you how fresh it is. Never used for ranking.",inputSchema:H.object({vault:m,flags:H.array(H.enum(["duplicate","orphan","stale_edit","stale_access","contradicted","tombstoned"])).optional(),limit:H.number().int().positive().max(500).default(50)}).strict(),outputSchema:F4({vault:H.string(),count:H.number().int(),computed_at:H.number().nullable(),notes:H.array(H.object({path:H.string(),quality_score:H.number().nullable(),score_version:H.number(),flags:H.array(H.string()),chunk_count:H.number(),dup_chunk_count:H.number(),dup_ratio:H.number().nullable(),age_days:H.number().nullable(),last_retrieved_at:H.number().nullable(),retrievals:H.number(),citations:H.number(),outcome_balance:H.number(),in_degree:H.number(),out_degree:H.number(),contradictions_open:H.number(),tombstoned:H.boolean()}))}),requiredScopes:["read:notes"],tags:["experiential","knowledge"],handler:(J)=>{if(!$.edb)return B4;let W=EF($.edb,{vaultId:J.vault,...J.flags?{flags:J.flags}:{},limit:J.limit});return{available:!0,vault:J.vault,count:W.length,computed_at:W[0]?.computed_at??null,notes:W.map((Q)=>({path:Q.path,quality_score:Q.quality_score,score_version:Q.score_version,flags:JSON.parse(Q.flags),chunk_count:Q.chunk_count,dup_chunk_count:Q.dup_chunk_count,dup_ratio:Q.dup_ratio,age_days:Q.age_days,last_retrieved_at:Q.last_retrieved_at,retrievals:Q.retrievals,citations:Q.citations,outcome_balance:Q.outcome_balance,in_degree:Q.in_degree,out_degree:Q.out_degree,contradictions_open:Q.contradictions_open,tombstoned:Q.tombstoned===1}))}}}),g({name:"gap_report",domain:"knowledge",description:"Read-only view of the latest gap-detector pass (THE-48/THE-616/THE-644): which of the pass's queries scored below the calibrated coverage floor, with their nearest-hit context. Populated by the offline `obsidian-tc gaps` pass; computed_at tells you how fresh it is, and null means no pass has ever been persisted for this vault. Never recomputes — a fresh reading requires re-running the CLI pass. Nearest-hit paths are filtered to the caller's read ACL (THE-563/564) before being returned.",inputSchema:H.object({vault:m,gaps_only:H.boolean().default(!1),limit:H.number().int().positive().max(500).default(50)}).strict(),outputSchema:F4({vault:H.string(),computed_at:H.number().nullable(),threshold:H.number(),min_results:H.number().int(),total:H.number().int(),gaps:H.number().int(),gap_rate:H.number(),returned:H.number().int(),items:H.array(H.object({id:H.string(),query:H.string(),top_score:H.number().nullable(),results:H.number().int(),gap:H.boolean(),nearest:H.array(H.object({path:H.string(),score:H.number()}))}))}),requiredScopes:["read:notes"],tags:["experiential","knowledge"],handler:(J,W)=>{if(!$.edb)return B4;let Q=tu($.edb,J.vault),G=Q?.items??[],Z=(J.gaps_only?G.filter((U)=>U.gap):G).slice(0,J.limit).map((U)=>({...U,nearest:U.nearest.filter((K)=>M0(W.acl,K.path))}));return{available:!0,vault:Q?.vault_id??J.vault,computed_at:Q?.computed_at??null,threshold:Q?.threshold??VG,min_results:Q?.min_results??VC,total:Q?.total??0,gaps:Q?.gaps??0,gap_rate:Q?.gap_rate??0,returned:Z.length,items:Z}}})]}function uA0($,X){for(let J of mA0(X))$.register(J)}function dA0($){$.registry.register(tB0({version:$.version,vaults:$.vaults.map((X)=>X.id),startedAt:$.startedAt,nativeLoaded:$3,vecEnabled:$.hasVec,ftsEnabled:$.hasFts,getIndexHealth:(X)=>({reconcile:$.indexHealth.reconcile,reconcile_at:$.indexHealth.reconcileAt,write_failures:$.indexHealth.writeFailures,notes_ready:$.indexHealth.notesReady,...X?{detail:{reconcile_errors:$.indexHealth.reconcileErrors,audit_write_failures:$.indexHealth.auditWriteFailures,index_queue_depth:$.getIndexCoordinatorStats().queued,index_queue_active:$.getIndexCoordinatorStats().active,index_queue_backpressures:$.indexHealth.indexQueueBackpressures,...$.indexHealth.lastWriteError!==void 0?{last_write_error:$.indexHealth.lastWriteError}:{}}}:{}}),getJobQueueStats:$.getJobQueueStats})),$.registry.register(sB0({vecEnabled:$.hasVec,ftsEnabled:$.hasFts,getIndexHealth:()=>({reconcile:$.indexHealth.reconcile,reconcile_at:$.indexHealth.reconcileAt,write_failures:$.indexHealth.writeFailures,notes_ready:$.indexHealth.notesReady}),getLastChunksUpserted:()=>$.indexHealth.lastChunksUpserted}))}async function BN$($,X){let J=await ex($,X);if(J)return J;let W=dH($.provider,X?.embeddings,{baseUrl:$.baseUrl,gatewayUrlEnv:process.env.OBSIDIAN_TC_GATEWAY_URL});if(W)throw w.invalidInput(W.reason,{provider:$.provider,hint:W.hint});throw w.invalidInput(`reranker.provider "${$.provider}" resolved to no reranker`,{provider:$.provider,hint:"this provider's registry entry returned null instead of a reranker (or throwing) for a declared reranker block; that is a bug in the registry entry."})}async function cA0($,X,J,W){let Q=null;try{Q=O4({})}catch{Q=null}let G=Q,Y=G?(K,B,F)=>G.rerank({query:K,documents:B,topN:F}).then((L)=>L.results):null,Z=X?await BN$(X,{embeddings:$,configDir:J,securityProfile:W}):DW($)??Y,U=G?pA0(G):null;return{gateway:Q,reranker:Z,roles:U}}function pA0($){return{extract:(X)=>$.extract(X).then((J)=>({text:J.text,model:J.model})),synthesize:(X)=>$.synthesize(X).then((J)=>({text:J.text,model:J.model})),judge:(X)=>$.judge(X).then((J)=>({text:J.text,model:J.model}))}}function nA0($,X){try{return pA0(O4({maxAttempts:$,...X!==void 0?{timeoutMs:X}:{}}))}catch{return null}}function lA0($){let{config:X}=$;JL0($.registry,{vaultRegistry:$.vaultRegistry,version:$.version,startedAt:$.startedAt,embeddings:{provider:X.embeddings.provider,model:X.embeddings.model},configPath:$.configPath,snapshots:{enabled:X.snapshots.enabled,retention:X.snapshots.retention},onSnapshotSkipped:$.onSnapshotSkipped,metadataIndex:{hasFts:$.hasFts,ready:()=>$.indexHealth.notesReady},requireCas:X.writes.requireCas,reindex:$.reindex,deindex:$.deindex,indexVault:async(J)=>{return{notes_seen:(await $.indexVaultRecorded({db:$.db,provider:$.embeddingProvider,embed:$.embedConfig,chunkContext:X.embeddings.chunkContext,representation:$.representation,densify:X.retrieval.densify,vaultId:J,root:$.vaultRegistry.resolve(J).root,isReadable:$.indexReadableFor(J),now:Date.now,sql:$.sqlHooksFor(J),onVecRebuild:$.onVecRebuild,onIndexed:$.makeOnIndexed(J),onNotesPass:()=>{$.indexHealth.notesReady=!0},walk:{streaming:X.indexing.streamingWalk}})).notes_seen}}})}function iA0($){let{config:X,registry:J}=$,W=(Z)=>$.memoryFolderByVault.get(Z)??V4,Q=(Z)=>$.traceFolderByVault.get(Z)??nJ;DL0(J,{vaultRegistry:$.vaultRegistry,embeddingProvider:$.embeddingProvider,...$.retrievalLog?{retrievalLog:$.retrievalLog}:{},chunkContext:X.embeddings.chunkContext,representation:$.representation,densify:X.retrieval.densify,streamingWalk:X.indexing.streamingWalk,dataviewBridge:(Z)=>({client:H$($.m4Deps,Z,"dataview").client,timeoutMs:e0($.m4Deps,Z).timeoutMs}),regexTimeoutMs:X.governor.regexTimeoutMs,metadataIndex:{hasFts:$.hasFts,ready:()=>$.indexHealth.notesReady},onIndexVaultComplete:(Z,U)=>{$.indexHealth.lastChunksUpserted=U.chunks_upserted,$.recordIngestStatsFor(Z,U)}}),GA0(J,{vaultRegistry:$.vaultRegistry,reindex:$.reindex,templaterBridge:(Z)=>({client:H$($.m4Deps,Z,"templater").client,timeoutMs:e0($.m4Deps,Z).templaterTimeoutMs})}),jB0(J,$.m4Deps);let G=aB0(X.plur);wA0(J,{vaultRegistry:$.vaultRegistry,activeSessions:$.activeSessions,reindex:$.reindex,plur:G,bootstrap:X.bootstrap,memoryFolder:W,traceFolder:Q});let Y={vaultRegistry:$.vaultRegistry,rateLimiter:$.rateLimiter,version:$.version,startedAt:$.startedAt,authMode:X.auth.mode,throttle:X.throttle,observability:{otel:!!X.observability.otel.endpoint,prometheus:X.observability.prometheus.enabled,morgiana:X.observability.morgiana.spool||!!X.observability.morgiana.httpEndpoint},embeddingsProvider:X.embeddings.provider,governorMaxResponseBytes:X.governor.maxResponseBytes,capabilities:(Z)=>$.capabilities.get(Z),registeredTools:()=>J.list().length};vA0(J,{...Y,reindex:$.reindex,deindex:$.deindex}),sA(J,{vaultRegistry:$.vaultRegistry,embeddingProvider:$.embeddingProvider,reranker:$.reranker,roles:$.roles,retrieval:X.retrieval,ranking:X.ranking,...$.retrievalLog?{retrievalLog:$.retrievalLog}:{},onVecFallback:$.onVecFallback,onStageMetric:$.onStageMetric,...$.onRerankOutcome?{onRerankOutcome:$.onRerankOutcome}:{},...$.activationFor?{activationFor:$.activationFor}:{},classRouter:X.retrieval.classRouter,...$.experientialOpen?{edb:$.experientialDb}:{},memoryFolder:W,prewarmDir:X.cacheDir,snapshots:{enabled:X.snapshots.enabled,retention:X.snapshots.retention},reindex:$.reindex,...X.retrieval.cache.enabled?{retrievalCaches:$.retrievalCaches}:{}}),uA0(J,{...$.experientialOpen?{edb:$.experientialDb}:{}})}var FN$=3,oA0=15000;function rA0($,X){return new dk($,{now:Date.now,sql:X("scheduler")})}function aA0($){return(X)=>$.roles?(J)=>{for(let W of J)$.jobQueue.enqueue("contradiction",{class:"contradiction",payload:{vaultId:X,chunkId:W.id},idempotencyKey:`${X}:${W.id}:${p0(W.content)}`,maxAttempts:FN$,replaceIfTerminal:!0})}:void 0}function sA0($){let X=new Map;if(X.set(K2,lB0({registry:$.registry,db:$.db,acl:$.acl,queue:$.jobQueue})),$.roles){let W=$.roles;X.set("contradiction",async(U)=>{let{vaultId:K,chunkId:B}=U.payload,F=gB0($.db,K,B);if(!F)return;let L={db:$.db,roles:W,now:Date.now,model:$.embeddingProvider.id},A=await hB0(L,K,[F]);if(A.unjudged>0)throw Error(`contradiction: ${A.unjudged}/${A.checked} unjudged`)});let Q=($.gatewayMaxAttempts!==void 0?nA0($.gatewayMaxAttempts,$.gatewayTimeoutMs):null)??W,G={db:$.db,roles:Q,now:Date.now,...$.maxPromptChars!==void 0?{maxPromptChars:$.maxPromptChars}:{}},Y=RD("synthesis",()=>dB0(G),G),Z=RD("audit",()=>vB0.run(G),G);X.set("synthesis",Y),X.set("audit",Z)}if($.experientialOpen){let W=$.vaults.map((G)=>G.id),Q=RD("note-quality",async()=>({ok:!0,detail:{per_vault:li($.db,$.experientialDb,W,Date.now())}}),{db:$.db,now:Date.now});X.set("note-quality",Q)}let J=nB0({queue:$.jobQueue,leaseOwner:`serve:${process.pid}`,handlers:X,classLimits:{contradiction:4,plane:1}});return{jobHandlers:X,jobRunner:J}}function tA0($){return async()=>{await Promise.all($.vaults.map((X)=>$.indexVaultRecorded({db:$.db,provider:$.embeddingProvider,embed:$.embedConfig,chunkContext:$.chunkContext,representation:$.representation,densify:$.densify,vaultId:X.id,root:$.vaultRegistry.resolve(X.id).root,isReadable:$.indexReadableFor(X.id),now:Date.now,sql:$.sqlHooksFor(X.id),onVecRebuild:$.onVecRebuild,onIndexed:$.makeOnIndexed(X.id),onNotesPass:()=>{$.indexHealth.notesReady=!0},walk:{streaming:$.streamingWalk}}).then((J)=>({vault:X.id,error:J.notes_embed_failed>0?`${J.notes_embed_failed} note(s) skipped: embed provider rejected their chunks (HTTP 400)`:null}),(J)=>({vault:X.id,error:M3(J)})))).then(async(X)=>{if(iB0(X,$.indexHealth,{now:Date.now,write:(J)=>process.stderr.write(J)}),!$.roles)return;await $.jobRunner.drainOnce(new AbortController().signal)})}}function eA0($,X){if(!(X.plane.enabled&&X.roles))return;$.register({name:"plane-enqueue",intervalMs:X.plane.intervalMinutes*60000,run:()=>{let J=uJ(new Date);X.jobQueue.enqueue("synthesis",{class:"plane",idempotencyKey:`synthesis:${J.year}-${J.week}`,maxAttempts:1,replaceIfTerminal:!0});let W=new Date().toISOString().slice(0,10);X.jobQueue.enqueue("audit",{class:"plane",idempotencyKey:`audit:${W}`,maxAttempts:1,replaceIfTerminal:!0})},onError:(J)=>process.stderr.write(`[plane-enqueue] enqueue failed: ${M3(J)}
|
|
2298
|
-
`)})}function $20($,X){if(!X.experientialOpen)return;_B0($,X.observability,{edb:X.experientialDb,intervalMs:X.intervalMs}),Kh($,{edb:X.experientialDb,intervalMs:X.intervalMs,onError:_1("episode-evaluation")}),$.register({name:"note-quality-enqueue",intervalMs:X.intervalMs,run:()=>{X.jobQueue.enqueue("note-quality",{class:"plane",idempotencyKey:`note-quality:${new Date().toISOString().slice(0,10)}`,maxAttempts:1})},onError:_1("note-quality-enqueue")}),$.register({name:"goal-expiry",intervalMs:X.intervalMs,run:()=>{bB0(X.experientialDb,Date.now())},onError:_1("goal-expiry")})}import{monitorEventLoopDelay as LN$}from"node:perf_hooks";var AN$=300000,DN$=5000,NN$=250;function VN$($){return typeof $?.then==="function"}class f_{jobs=new Map;stats(){return[...this.jobs.entries()].map(([$,X])=>({job:$,skipped:X.skipped,consecutiveFailures:X.consecutiveFailures,deferred:X.deferred}))}now;db;eventLoopDeferMs;maxBackoffMs;random;shutdownDeadlineMs;deferralRecheckMs;loopDelay;loopMonitor;onPersistError;persistErrorSeen=new Set;timer=null;virtualNow=0;started=!1;stopped=!1;abort=new AbortController;constructor($={}){if(this.now=$.now??Date.now,this.db=$.db,this.eventLoopDeferMs=$.eventLoopDeferMs,this.maxBackoffMs=$.maxBackoffMs??AN$,this.random=$.random??Math.random,this.shutdownDeadlineMs=$.shutdownDeadlineMs??DN$,this.deferralRecheckMs=$.deferralRecheckMs??NN$,this.onPersistError=$.onPersistError,this.eventLoopDeferMs!==void 0)if($.loopDelayMs)this.loopDelay=$.loopDelayMs;else try{let X=LN$({resolution:20});X.enable(),this.loopMonitor=X,this.loopDelay=()=>X.percentile(99)/1e6}catch{}else if($.loopDelayMs)this.loopDelay=$.loopDelayMs;if(this.db)this.ensureTable(this.db)}register($){if(this.jobs.has($.name))throw Error(`scheduler: duplicate job '${$.name}'`);return this.jobs.set($.name,{spec:$,nextRunAt:0,inFlight:null,consecutiveFailures:0,skipped:0,deferred:0}),this}start(){if(this.started)return;this.started=!0;for(let $ of this.jobs.values()){let X=this.seedNextRun($);$.nextRunAt=X??this.virtualNow+this.effInterval($)}this.arm()}async stop(){if(this.stopped)return;if(this.stopped=!0,this.timer)clearTimeout(this.timer),this.timer=null;this.abort.abort();let $=[...this.jobs.values()].map((X)=>X.inFlight).filter((X)=>!!X);if($.length>0)await Promise.race([Promise.allSettled($),new Promise((X)=>{setTimeout(X,this.shutdownDeadlineMs).unref?.()})]);this.loopMonitor?.disable()}reportPersistError($,X,J){let W=`${$}:${X??""}`;if(this.persistErrorSeen.has(W))return;this.persistErrorSeen.add(W);try{this.onPersistError?.({op:$,job:X,error:J})}catch{}}clearPersistError($,X){this.persistErrorSeen.delete(`${$}:${X}`)}ensureTable($){try{$.exec("CREATE TABLE IF NOT EXISTS job_schedule (name TEXT PRIMARY KEY, last_run_at INTEGER, last_success_at INTEGER, next_run_at INTEGER, consecutive_failures INTEGER NOT NULL DEFAULT 0)")}catch(X){this.reportPersistError("ensureTable",void 0,X)}}seedNextRun($){if(!this.db)return null;try{let X=this.db.prepare("SELECT next_run_at, consecutive_failures FROM job_schedule WHERE name = ?").get($.spec.name);if(!X)return null;if(X.consecutive_failures!=null)$.consecutiveFailures=X.consecutive_failures;if(X.next_run_at==null)return null;let J=Math.max(0,X.next_run_at-this.now());return this.virtualNow+J}catch(X){return this.reportPersistError("seedNextRun",$.spec.name,X),null}}effInterval($){let X=Math.min($.spec.intervalMs*2**$.consecutiveFailures,this.maxBackoffMs),J=$.spec.jitterRatio??0;if(
|
|
2297
|
+
WHERE ${Q.join(" AND ")} GROUP BY ${Y} ORDER BY n DESC`).all(...G),U=Z.filter((B)=>B.n>=J.min_bucket),K=Z.filter((B)=>B.n<J.min_bucket);return{available:!0,group_by:J.group_by,min_bucket:J.min_bucket,buckets:U.slice(0,J.limit).map((B)=>({key:B.key,count:B.n})),suppressed:K.reduce((B,F)=>B+F.n,0),suppressed_buckets:K.length,total:Z.reduce((B,F)=>B+F.n,0)}}}),g({name:"work_forget",domain:"knowledge",description:"Tombstone an experiential episode (the THE-238 control-1 blocklist, surfaced as the first-party forget verb). A forgotten episode never surfaces in work_search again; each successful forget appends a THE-239 hash-chained forget_log row for forensics. Idempotent: a repeat call, foreign, or unknown episode id is a silent no-op (forgotten:false) that appends NO additional log row. P1.7: only your OWN episodes unless you hold admin:workspace — a foreign or unknown id is a silent no-op, not an error.",inputSchema:H.object({episode_id:H.string().min(1)}).strict(),outputSchema:F4({episode_id:H.string(),forgotten:H.boolean()}),requiredScopes:["write:workspace"],tags:["experiential"],handler:(J,W)=>{if(!$.edb)return B4;let Q=0;$.edb.exec("BEGIN");try{if(Q=(Y7(W)?$.edb.prepare("UPDATE agent_episodes SET blocked = 1 WHERE id = ? AND blocked = 0").run(J.episode_id):$.edb.prepare("UPDATE agent_episodes SET blocked = 1 WHERE id = ? AND blocked = 0 AND caller IS ?").run(J.episode_id,W.caller??null)).changes,Q>0)hB($.edb,{ts:X(),kind:"episode",target:J.episode_id,mode:"tombstone",details:{actor:W.caller??null,source:"work_forget"}});$.edb.exec("COMMIT")}catch(G){throw $.edb.exec("ROLLBACK"),G}return{available:!0,episode_id:J.episode_id,forgotten:Q>0}}}),g({name:"record_retrieval_feedback",domain:"knowledge",description:"Report which retrieved chunks actually helped. CALL THIS after you act on a search result: outcome (-1|0|+1) = did acting on it lead somewhere good, feedback (-1|0|+1) = was it the right chunk. Stamp the chunks you genuinely used, not every hit, and stamp -1 when a confidently-returned chunk was wrong — a negative is worth more than silence. This is the only signal separating a chunk that gets RETRIEVED from one that gets USED: it feeds the ACT-R activation recompute, so stamping is what makes later retrieval better, and not stamping leaves ranking blind. Targets your most recent retrieval event(s) for that chunk (last_n, default 1). Returns `updated`; when that is 0 it also returns `reason` — `session_scope` (you own retrievals for this chunk, none in the current scope) or `no_owned_retrievals` (nothing of yours matches), so a no-op is never silent. You may only stamp retrievals your own caller produced (THE-568); an unidentified caller cannot stamp, and admin:workspace crosses both that and the session scope.",inputSchema:H.object({chunk_id:H.string().min(1),feedback:H.number().int().min(-1).max(1).optional(),outcome:H.number().int().min(-1).max(1).optional(),session_id:H.string().optional(),last_n:H.number().int().positive().max(50).default(1)}).strict().refine((J)=>J.feedback!==void 0||J.outcome!==void 0,{message:"provide feedback and/or outcome"}),outputSchema:F4({chunk_id:H.string(),updated:H.number().int(),reason:H.enum(["session_scope","no_owned_retrievals"]).optional()}),requiredScopes:["write:workspace"],tags:["experiential"],handler:(J,W)=>$.edb?gA0($.edb,J,W):B4}),g({name:"note_quality_report",domain:"knowledge",description:"Read-only note-health report from the note_quality rollup (THE-537): which notes are duplicated, orphaned, stale by edit or by access, contradicted, or tombstoned — with the raw components behind each verdict. quality_score is NULL when there is no usage evidence yet, which means UNMEASURED, not bad. Populated by the offline `obsidian-tc note-quality` pass; computed_at tells you how fresh it is. Never used for ranking.",inputSchema:H.object({vault:m,flags:H.array(H.enum(["duplicate","orphan","stale_edit","stale_access","contradicted","tombstoned"])).optional(),limit:H.number().int().positive().max(500).default(50)}).strict(),outputSchema:F4({vault:H.string(),count:H.number().int(),computed_at:H.number().nullable(),notes:H.array(H.object({path:H.string(),quality_score:H.number().nullable(),score_version:H.number(),flags:H.array(H.string()),chunk_count:H.number(),dup_chunk_count:H.number(),dup_ratio:H.number().nullable(),age_days:H.number().nullable(),last_retrieved_at:H.number().nullable(),retrievals:H.number(),citations:H.number(),outcome_balance:H.number(),in_degree:H.number(),out_degree:H.number(),contradictions_open:H.number(),tombstoned:H.boolean()}))}),requiredScopes:["read:notes"],tags:["experiential","knowledge"],handler:(J)=>{if(!$.edb)return B4;let W=EF($.edb,{vaultId:J.vault,...J.flags?{flags:J.flags}:{},limit:J.limit});return{available:!0,vault:J.vault,count:W.length,computed_at:W[0]?.computed_at??null,notes:W.map((Q)=>({path:Q.path,quality_score:Q.quality_score,score_version:Q.score_version,flags:JSON.parse(Q.flags),chunk_count:Q.chunk_count,dup_chunk_count:Q.dup_chunk_count,dup_ratio:Q.dup_ratio,age_days:Q.age_days,last_retrieved_at:Q.last_retrieved_at,retrievals:Q.retrievals,citations:Q.citations,outcome_balance:Q.outcome_balance,in_degree:Q.in_degree,out_degree:Q.out_degree,contradictions_open:Q.contradictions_open,tombstoned:Q.tombstoned===1}))}}}),g({name:"gap_report",domain:"knowledge",description:"Read-only view of the latest gap-detector pass (THE-48/THE-616/THE-644): which of the pass's queries scored below the calibrated coverage floor, with their nearest-hit context. Populated by the offline `obsidian-tc gaps` pass; computed_at tells you how fresh it is, and null means no pass has ever been persisted for this vault. Never recomputes — a fresh reading requires re-running the CLI pass. Nearest-hit paths are filtered to the caller's read ACL (THE-563/564) before being returned.",inputSchema:H.object({vault:m,gaps_only:H.boolean().default(!1),limit:H.number().int().positive().max(500).default(50)}).strict(),outputSchema:F4({vault:H.string(),computed_at:H.number().nullable(),threshold:H.number(),min_results:H.number().int(),total:H.number().int(),gaps:H.number().int(),gap_rate:H.number(),returned:H.number().int(),items:H.array(H.object({id:H.string(),query:H.string(),top_score:H.number().nullable(),results:H.number().int(),gap:H.boolean(),nearest:H.array(H.object({path:H.string(),score:H.number()}))}))}),requiredScopes:["read:notes"],tags:["experiential","knowledge"],handler:(J,W)=>{if(!$.edb)return B4;let Q=tu($.edb,J.vault),G=Q?.items??[],Z=(J.gaps_only?G.filter((U)=>U.gap):G).slice(0,J.limit).map((U)=>({...U,nearest:U.nearest.filter((K)=>M0(W.acl,K.path))}));return{available:!0,vault:Q?.vault_id??J.vault,computed_at:Q?.computed_at??null,threshold:Q?.threshold??VG,min_results:Q?.min_results??VC,total:Q?.total??0,gaps:Q?.gaps??0,gap_rate:Q?.gap_rate??0,returned:Z.length,items:Z}}})]}function uA0($,X){for(let J of mA0(X))$.register(J)}function dA0($){$.registry.register(tB0({version:$.version,vaults:$.vaults.map((X)=>X.id),startedAt:$.startedAt,nativeLoaded:$3,vecEnabled:$.hasVec,ftsEnabled:$.hasFts,getIndexHealth:(X)=>({reconcile:$.indexHealth.reconcile,reconcile_at:$.indexHealth.reconcileAt,write_failures:$.indexHealth.writeFailures,notes_ready:$.indexHealth.notesReady,...X?{detail:{reconcile_errors:$.indexHealth.reconcileErrors,audit_write_failures:$.indexHealth.auditWriteFailures,index_queue_depth:$.getIndexCoordinatorStats().queued,index_queue_active:$.getIndexCoordinatorStats().active,index_queue_backpressures:$.indexHealth.indexQueueBackpressures,...$.indexHealth.lastWriteError!==void 0?{last_write_error:$.indexHealth.lastWriteError}:{}}}:{}}),getJobQueueStats:$.getJobQueueStats})),$.registry.register(sB0({vecEnabled:$.hasVec,ftsEnabled:$.hasFts,getIndexHealth:()=>({reconcile:$.indexHealth.reconcile,reconcile_at:$.indexHealth.reconcileAt,write_failures:$.indexHealth.writeFailures,notes_ready:$.indexHealth.notesReady}),getLastChunksUpserted:()=>$.indexHealth.lastChunksUpserted}))}async function BN$($,X){let J=await ex($,X);if(J)return J;let W=dH($.provider,X?.embeddings,{baseUrl:$.baseUrl,gatewayUrlEnv:process.env.OBSIDIAN_TC_GATEWAY_URL});if(W)throw w.invalidInput(W.reason,{provider:$.provider,hint:W.hint});throw w.invalidInput(`reranker.provider "${$.provider}" resolved to no reranker`,{provider:$.provider,hint:"this provider's registry entry returned null instead of a reranker (or throwing) for a declared reranker block; that is a bug in the registry entry."})}async function cA0($,X,J,W){let Q=null;try{Q=O4({})}catch{Q=null}let G=Q,Y=G?(K,B,F)=>G.rerank({query:K,documents:B,topN:F}).then((L)=>L.results):null,Z=X?await BN$(X,{embeddings:$,configDir:J,securityProfile:W}):DW($)??Y,U=G?pA0(G):null;return{gateway:Q,reranker:Z,roles:U}}function pA0($){return{extract:(X)=>$.extract(X).then((J)=>({text:J.text,model:J.model})),synthesize:(X)=>$.synthesize(X).then((J)=>({text:J.text,model:J.model})),judge:(X)=>$.judge(X).then((J)=>({text:J.text,model:J.model}))}}function nA0($,X){try{return pA0(O4({maxAttempts:$,...X!==void 0?{timeoutMs:X}:{}}))}catch{return null}}function lA0($){let{config:X}=$;JL0($.registry,{vaultRegistry:$.vaultRegistry,version:$.version,startedAt:$.startedAt,embeddings:{provider:X.embeddings.provider,model:X.embeddings.model},configPath:$.configPath,snapshots:{enabled:X.snapshots.enabled,retention:X.snapshots.retention},onSnapshotSkipped:$.onSnapshotSkipped,metadataIndex:{hasFts:$.hasFts,ready:()=>$.indexHealth.notesReady},requireCas:X.writes.requireCas,reindex:$.reindex,deindex:$.deindex,indexVault:async(J)=>{return{notes_seen:(await $.indexVaultRecorded({db:$.db,provider:$.embeddingProvider,embed:$.embedConfig,chunkContext:X.embeddings.chunkContext,representation:$.representation,densify:X.retrieval.densify,vaultId:J,root:$.vaultRegistry.resolve(J).root,isReadable:$.indexReadableFor(J),now:Date.now,sql:$.sqlHooksFor(J),onVecRebuild:$.onVecRebuild,onIndexed:$.makeOnIndexed(J),onNotesPass:()=>{$.indexHealth.notesReady=!0},walk:{streaming:X.indexing.streamingWalk}})).notes_seen}}})}function iA0($){let{config:X,registry:J}=$,W=(Z)=>$.memoryFolderByVault.get(Z)??V4,Q=(Z)=>$.traceFolderByVault.get(Z)??nJ;DL0(J,{vaultRegistry:$.vaultRegistry,embeddingProvider:$.embeddingProvider,...$.retrievalLog?{retrievalLog:$.retrievalLog}:{},chunkContext:X.embeddings.chunkContext,representation:$.representation,densify:X.retrieval.densify,streamingWalk:X.indexing.streamingWalk,dataviewBridge:(Z)=>({client:H$($.m4Deps,Z,"dataview").client,timeoutMs:e0($.m4Deps,Z).timeoutMs}),regexTimeoutMs:X.governor.regexTimeoutMs,metadataIndex:{hasFts:$.hasFts,ready:()=>$.indexHealth.notesReady},onIndexVaultComplete:(Z,U)=>{$.indexHealth.lastChunksUpserted=U.chunks_upserted,$.recordIngestStatsFor(Z,U)}}),GA0(J,{vaultRegistry:$.vaultRegistry,reindex:$.reindex,templaterBridge:(Z)=>({client:H$($.m4Deps,Z,"templater").client,timeoutMs:e0($.m4Deps,Z).templaterTimeoutMs})}),jB0(J,$.m4Deps);let G=aB0(X.plur);wA0(J,{vaultRegistry:$.vaultRegistry,activeSessions:$.activeSessions,reindex:$.reindex,plur:G,bootstrap:X.bootstrap,memoryFolder:W,traceFolder:Q});let Y={vaultRegistry:$.vaultRegistry,rateLimiter:$.rateLimiter,version:$.version,startedAt:$.startedAt,authMode:X.auth.mode,throttle:X.throttle,observability:{otel:!!X.observability.otel.endpoint,prometheus:X.observability.prometheus.enabled,morgiana:X.observability.morgiana.spool||!!X.observability.morgiana.httpEndpoint},embeddingsProvider:X.embeddings.provider,governorMaxResponseBytes:X.governor.maxResponseBytes,capabilities:(Z)=>$.capabilities.get(Z),registeredTools:()=>J.list().length};vA0(J,{...Y,reindex:$.reindex,deindex:$.deindex}),sA(J,{vaultRegistry:$.vaultRegistry,embeddingProvider:$.embeddingProvider,reranker:$.reranker,roles:$.roles,retrieval:X.retrieval,ranking:X.ranking,...$.retrievalLog?{retrievalLog:$.retrievalLog}:{},onVecFallback:$.onVecFallback,onStageMetric:$.onStageMetric,...$.onRerankOutcome?{onRerankOutcome:$.onRerankOutcome}:{},...$.activationFor?{activationFor:$.activationFor}:{},classRouter:X.retrieval.classRouter,...$.experientialOpen?{edb:$.experientialDb}:{},memoryFolder:W,prewarmDir:X.cacheDir,snapshots:{enabled:X.snapshots.enabled,retention:X.snapshots.retention},reindex:$.reindex,...X.retrieval.cache.enabled?{retrievalCaches:$.retrievalCaches}:{}}),uA0(J,{...$.experientialOpen?{edb:$.experientialDb}:{}})}var FN$=3,oA0=15000;function rA0($,X){return new dk($,{now:Date.now,sql:X("scheduler")})}function aA0($){return(X)=>$.roles?(J)=>{for(let W of J)$.jobQueue.enqueue("contradiction",{class:"contradiction",payload:{vaultId:X,chunkId:W.id},idempotencyKey:`${X}:${W.id}:${p0(W.content)}`,maxAttempts:FN$,replaceIfTerminal:!0})}:void 0}function sA0($){let X=new Map;if(X.set(K2,lB0({registry:$.registry,db:$.db,acl:$.acl,queue:$.jobQueue})),$.roles){let W=$.roles;X.set("contradiction",async(U)=>{let{vaultId:K,chunkId:B}=U.payload,F=gB0($.db,K,B);if(!F)return;let L={db:$.db,roles:W,now:Date.now,model:$.embeddingProvider.id},A=await hB0(L,K,[F]);if(A.unjudged>0)throw Error(`contradiction: ${A.unjudged}/${A.checked} unjudged`)});let Q=($.gatewayMaxAttempts!==void 0?nA0($.gatewayMaxAttempts,$.gatewayTimeoutMs):null)??W,G={db:$.db,roles:Q,now:Date.now,...$.maxPromptChars!==void 0?{maxPromptChars:$.maxPromptChars}:{}},Y=RD("synthesis",()=>dB0(G),G),Z=RD("audit",()=>vB0.run(G),G);X.set("synthesis",Y),X.set("audit",Z)}if($.experientialOpen){let W=$.vaults.map((G)=>G.id),Q=RD("note-quality",async()=>({ok:!0,detail:{per_vault:li($.db,$.experientialDb,W,Date.now())}}),{db:$.db,now:Date.now});X.set("note-quality",Q)}let J=nB0({queue:$.jobQueue,leaseOwner:`serve:${process.pid}`,handlers:X,classLimits:{contradiction:4,plane:1}});return{jobHandlers:X,jobRunner:J}}function tA0($){return async()=>{await Promise.all($.vaults.map((X)=>$.indexVaultRecorded({db:$.db,provider:$.embeddingProvider,embed:$.embedConfig,chunkContext:$.chunkContext,representation:$.representation,densify:$.densify,vaultId:X.id,root:$.vaultRegistry.resolve(X.id).root,isReadable:$.indexReadableFor(X.id),now:Date.now,sql:$.sqlHooksFor(X.id),onVecRebuild:$.onVecRebuild,onIndexed:$.makeOnIndexed(X.id),onNotesPass:()=>{$.indexHealth.notesReady=!0},walk:{streaming:$.streamingWalk}}).then((J)=>({vault:X.id,error:J.notes_embed_failed>0?`${J.notes_embed_failed} note(s) skipped: embed provider rejected their chunks (HTTP 400)`:null}),(J)=>({vault:X.id,error:M3(J)})))).then(async(X)=>{if(iB0(X,$.indexHealth,{now:Date.now,write:(J)=>process.stderr.write(J)}),!$.roles)return;await $.jobRunner.drainOnce(new AbortController().signal)})}}function eA0($,X){if(!(X.plane.enabled&&X.roles))return;$.register({name:"plane-enqueue",intervalMs:X.plane.intervalMinutes*60000,run:()=>{let J=uJ(new Date);X.jobQueue.enqueue("synthesis",{class:"plane",idempotencyKey:`synthesis:${J.year}-${J.week}`,maxAttempts:1,replaceIfFailed:!0});let W=new Date().toISOString().slice(0,10);X.jobQueue.enqueue("audit",{class:"plane",idempotencyKey:`audit:${W}`,maxAttempts:1,replaceIfFailed:!0})},onError:(J)=>process.stderr.write(`[plane-enqueue] enqueue failed: ${M3(J)}
|
|
2298
|
+
`)})}function $20($,X){if(!X.experientialOpen)return;_B0($,X.observability,{edb:X.experientialDb,intervalMs:X.intervalMs}),Kh($,{edb:X.experientialDb,intervalMs:X.intervalMs,onError:_1("episode-evaluation")}),$.register({name:"note-quality-enqueue",intervalMs:X.intervalMs,run:()=>{X.jobQueue.enqueue("note-quality",{class:"plane",idempotencyKey:`note-quality:${new Date().toISOString().slice(0,10)}`,maxAttempts:1})},onError:_1("note-quality-enqueue")}),$.register({name:"goal-expiry",intervalMs:X.intervalMs,run:()=>{bB0(X.experientialDb,Date.now())},onError:_1("goal-expiry")})}import{monitorEventLoopDelay as LN$}from"node:perf_hooks";var AN$=300000,DN$=5000,NN$=250;function VN$($){return typeof $?.then==="function"}class f_{jobs=new Map;stats(){return[...this.jobs.entries()].map(([$,X])=>({job:$,skipped:X.skipped,consecutiveFailures:X.consecutiveFailures,deferred:X.deferred}))}now;db;eventLoopDeferMs;maxBackoffMs;random;shutdownDeadlineMs;deferralRecheckMs;loopDelay;loopMonitor;onPersistError;persistErrorSeen=new Set;timer=null;virtualNow=0;started=!1;stopped=!1;abort=new AbortController;constructor($={}){if(this.now=$.now??Date.now,this.db=$.db,this.eventLoopDeferMs=$.eventLoopDeferMs,this.maxBackoffMs=$.maxBackoffMs??AN$,this.random=$.random??Math.random,this.shutdownDeadlineMs=$.shutdownDeadlineMs??DN$,this.deferralRecheckMs=$.deferralRecheckMs??NN$,this.onPersistError=$.onPersistError,this.eventLoopDeferMs!==void 0)if($.loopDelayMs)this.loopDelay=$.loopDelayMs;else try{let X=LN$({resolution:20});X.enable(),this.loopMonitor=X,this.loopDelay=()=>X.percentile(99)/1e6}catch{}else if($.loopDelayMs)this.loopDelay=$.loopDelayMs;if(this.db)this.ensureTable(this.db)}register($){if(this.jobs.has($.name))throw Error(`scheduler: duplicate job '${$.name}'`);return this.jobs.set($.name,{spec:$,nextRunAt:0,inFlight:null,consecutiveFailures:0,skipped:0,deferred:0}),this}start(){if(this.started)return;this.started=!0;for(let $ of this.jobs.values()){let X=this.seedNextRun($);$.nextRunAt=X??this.virtualNow+this.effInterval($)}this.arm()}async stop(){if(this.stopped)return;if(this.stopped=!0,this.timer)clearTimeout(this.timer),this.timer=null;this.abort.abort();let $=[...this.jobs.values()].map((X)=>X.inFlight).filter((X)=>!!X);if($.length>0)await Promise.race([Promise.allSettled($),new Promise((X)=>{setTimeout(X,this.shutdownDeadlineMs).unref?.()})]);this.loopMonitor?.disable()}reportPersistError($,X,J){let W=`${$}:${X??""}`;if(this.persistErrorSeen.has(W))return;this.persistErrorSeen.add(W);try{this.onPersistError?.({op:$,job:X,error:J})}catch{}}clearPersistError($,X){this.persistErrorSeen.delete(`${$}:${X}`)}ensureTable($){try{$.exec("CREATE TABLE IF NOT EXISTS job_schedule (name TEXT PRIMARY KEY, last_run_at INTEGER, last_success_at INTEGER, next_run_at INTEGER, consecutive_failures INTEGER NOT NULL DEFAULT 0)")}catch(X){this.reportPersistError("ensureTable",void 0,X)}}seedNextRun($){if(!this.db)return null;try{let X=this.db.prepare("SELECT next_run_at, consecutive_failures FROM job_schedule WHERE name = ?").get($.spec.name);if(!X)return null;if(X.consecutive_failures!=null)$.consecutiveFailures=X.consecutive_failures;if(X.next_run_at==null)return null;let J=Math.max(0,X.next_run_at-this.now());return this.virtualNow+J}catch(X){return this.reportPersistError("seedNextRun",$.spec.name,X),null}}effInterval($){let X=Math.min($.spec.intervalMs*2**$.consecutiveFailures,this.maxBackoffMs),J=Math.max(X,$.spec.intervalMs),W=$.spec.jitterRatio??0;if(W<=0)return J;let Q=J+J*W*(2*this.random()-1);return Math.max(1,Math.round(Q))}arm(){if(this.timer)clearTimeout(this.timer),this.timer=null;if(this.stopped||this.jobs.size===0)return;let $=Number.POSITIVE_INFINITY;for(let J of this.jobs.values())$=Math.min($,J.nextRunAt);if(!Number.isFinite($))return;let X=Math.max(0,$-this.virtualNow);this.timer=setTimeout(()=>this.tick(X),X),this.timer.unref?.()}tick($){if(this.stopped)return;this.virtualNow+=$;let X=this.selectDue();if(this.eventLoopDeferMs!==void 0&&this.loopDelay&&X.length>0){if(this.loopDelay()>this.eventLoopDeferMs){for(let J of X)J.nextRunAt=this.virtualNow+this.deferralRecheckMs,J.deferred+=1;this.arm();return}}for(let J of X){if(J.inFlight){J.skipped+=1,this.safeSkip(J),J.nextRunAt=this.virtualNow+this.effInterval(J);continue}J.nextRunAt=this.virtualNow+this.effInterval(J),this.runJob(J)}this.arm()}selectDue(){let $=[];for(let X of this.jobs.values())if(X.nextRunAt<=this.virtualNow)$.push(X);return $.sort((X,J)=>(J.spec.priority??0)-(X.spec.priority??0)),$}runJob($){this.safeRun($),this.persistRunStart($);let X;try{X=$.spec.run(this.abort.signal)}catch(J){this.onFailure($,J);return}if(VN$(X))$.inFlight=X.then(()=>this.onSuccess($),(J)=>this.onFailure($,J)),$.inFlight=$.inFlight.finally(()=>{$.inFlight=null});else this.onSuccess($)}onSuccess($){if($.consecutiveFailures=0,$.nextRunAt=this.virtualNow+this.effInterval($),this.arm(),!this.db)return;let X=this.now();this.persist($,{last_success_at:X,next_run_at:X+this.effInterval($),consecutive_failures:0})}onFailure($,X){if($.consecutiveFailures+=1,$.nextRunAt=this.virtualNow+this.effInterval($),this.arm(),this.db){let J=this.now();this.persist($,{next_run_at:J+this.effInterval($),consecutive_failures:$.consecutiveFailures})}this.safeError($,X)}persistRunStart($){if(!this.db)return;let X=this.now();try{this.db.prepare(`INSERT INTO job_schedule (name, last_run_at, next_run_at)
|
|
2299
2299
|
VALUES (?, ?, ?)
|
|
2300
2300
|
ON CONFLICT(name) DO UPDATE SET
|
|
2301
2301
|
last_run_at = excluded.last_run_at,
|
|
@@ -2330,5 +2330,5 @@ ${W.join(`\r
|
|
|
2330
2330
|
`)}).finally(()=>{process.exit(0)})}},W=J("SIGTERM"),Q=J("SIGINT");return process.on("SIGTERM",W),process.on("SIGINT",Q),()=>{process.off("SIGTERM",W),process.off("SIGINT",Q)}}async function Qj$($){let X=R$($.input),J=$.input??process.env.OBSIDIAN_TC_CONFIG,W=await jD0(X,J);OD0(W),await W.start()}async function Wj$(){let $=Nx(process.argv.slice(2));switch($.kind){case"token-mint":return cs($);case"version":return ps($);case"help":return bd($);case"error":return vu($);case"plugin-install":return si($);case"config-show":case"config-validate":return Vb($);case"config-explain":return Nb($);case"doctor":return bu($);case"cluster":return Lb($);case"activation-recompute":return zx($);case"densify-llm":return bb($);case"citation-infer":return Wb($);case"contribution-report":return qb($);case"note-quality":return ii($);case"forget":return ou($);case"gaps":return xd($);case"index":return hi($);case"metrics":return ui($);case"reflect":return Ns($);case"prefetch":return Ds($);default:return Qj$($)}}Wj$().catch(($)=>{process.stderr.write(`fatal: ${$.message}
|
|
2331
2331
|
`),process.exit(1)});
|
|
2332
2332
|
|
|
2333
|
-
//# debugId=
|
|
2333
|
+
//# debugId=22991361EB451D6064756E2164756E21
|
|
2334
2334
|
//# sourceMappingURL=cli.js.map
|