agentix-cli 0.134.0 → 0.135.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/dist/{absorb-eval-WU7JR3BT.js → absorb-eval-WY3YMLS4.js} +2 -2
- package/dist/{agent-2GPJGHHG.js → agent-3R5NY7I3.js} +2 -2
- package/dist/{board-dashboard-PUQPL4AX.js → board-dashboard-U3ZSCO62.js} +2 -2
- package/dist/{chunk-AHO4CQRK.js → chunk-5NT44FKL.js} +2 -2
- package/dist/{chunk-RJOA7QBB.js → chunk-6WF56ME6.js} +2 -2
- package/dist/{chunk-MCBTVNPX.js → chunk-BQIWMQNU.js} +2 -2
- package/dist/{chunk-MM3F74K4.js → chunk-EEBK4F6E.js} +3 -3
- package/dist/chunk-EEBK4F6E.js.map +1 -0
- package/dist/{chunk-YSXE65O7.js → chunk-GSKJ57XY.js} +4 -4
- package/dist/{chunk-VQYVL72V.js → chunk-H6VWU2HN.js} +2 -2
- package/dist/chunk-JRS5QRZG.js +2 -0
- package/dist/chunk-JRS5QRZG.js.map +1 -0
- package/dist/{chunk-5BI2T3WD.js → chunk-JTDUTCUE.js} +3 -3
- package/dist/chunk-JTDUTCUE.js.map +1 -0
- package/dist/{chunk-4VVHGR7H.js → chunk-KEXBEUSU.js} +1 -1
- package/dist/{chunk-4VVHGR7H.js.map → chunk-KEXBEUSU.js.map} +1 -1
- package/dist/chunk-L5UGH4T4.js +160 -0
- package/dist/chunk-L5UGH4T4.js.map +1 -0
- package/dist/{chunk-RDEFA6Y6.js → chunk-LU7GDHGD.js} +2 -2
- package/dist/chunk-MI7WOGH6.js +4 -0
- package/dist/chunk-MI7WOGH6.js.map +1 -0
- package/dist/chunk-NY7NHGVT.js +105 -0
- package/dist/chunk-NY7NHGVT.js.map +1 -0
- package/dist/chunk-QAWKN2N4.js +3 -0
- package/dist/chunk-QAWKN2N4.js.map +1 -0
- package/dist/{chunk-FEEXOWK5.js → chunk-QDWEM4DG.js} +2 -2
- package/dist/{chunk-JP5OAMWQ.js → chunk-RGZARSHV.js} +1 -1
- package/dist/{chunk-JP5OAMWQ.js.map → chunk-RGZARSHV.js.map} +1 -1
- package/dist/{chunk-TDGDH4RA.js → chunk-RVEMX5MJ.js} +2 -2
- package/dist/{chunk-TDGDH4RA.js.map → chunk-RVEMX5MJ.js.map} +1 -1
- package/dist/{chunk-URN74FTP.js → chunk-WWDYDLY2.js} +2 -2
- package/dist/{chunk-G4HDRJVN.js → chunk-YA3P77LV.js} +2 -2
- package/dist/{chunk-XWO6ALJQ.js → chunk-ZFRXFUP7.js} +2 -2
- package/dist/{chunk-NXRSIWQA.js → chunk-ZGVVYJIK.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/{contributions-74M6YOCZ.js → contributions-KLRJ4ZXV.js} +2 -2
- package/dist/{enrich-NH3WHKD6.js → enrich-ZB5I7KHN.js} +2 -2
- package/dist/event-levels-CQWHSLMT.js +3 -0
- package/dist/event-levels-CQWHSLMT.js.map +1 -0
- package/dist/graph-ZVKV3JBD.js +2 -0
- package/dist/{hub-VTDFUAEH.js → hub-TILTOOSS.js} +2 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/dist/load-EOZUZK7U.js +2 -0
- package/dist/model-call-PKV5UAQ7.js +2 -0
- package/dist/{program-3URNCVEZ.js → program-U3HJY7E5.js} +272 -274
- package/dist/program-U3HJY7E5.js.map +1 -0
- package/dist/{promote-B2BADAEP.js → promote-RHVZB2QZ.js} +2 -2
- package/dist/push-bridge-325SXDGN.js +1 -1
- package/dist/{query-2VIIGGDS.js → query-OZXZVLO7.js} +2 -2
- package/dist/query-runs-7VX3YAC3.js +4 -0
- package/dist/query-runs-7VX3YAC3.js.map +1 -0
- package/dist/{query-settings-VJ3POZS3.js → query-settings-2MGUS6AY.js} +2 -2
- package/dist/registry-LZLIPP7N.js +2 -0
- package/dist/roster-BZGKG2ZA.js +2 -0
- package/dist/score-DZGPLHCL.js +3 -0
- package/dist/score-DZGPLHCL.js.map +1 -0
- package/dist/types-ARP27T6T.js +2 -0
- package/dist/types-LJZ2YY5W.js +2 -0
- package/dist/{wiki-SXWJ5NJQ.js → wiki-GCRRINW3.js} +2 -2
- package/dist/wiki-GCRRINW3.js.map +1 -0
- package/dist/wiki-enrich-P5TNWACZ.js +2 -0
- package/dist/wiki-enrich-P5TNWACZ.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-5BI2T3WD.js.map +0 -1
- package/dist/chunk-7VLLZQ3N.js +0 -2
- package/dist/chunk-7VLLZQ3N.js.map +0 -1
- package/dist/chunk-DDEDSYLF.js +0 -105
- package/dist/chunk-DDEDSYLF.js.map +0 -1
- package/dist/chunk-KFIJDLQ5.js +0 -3
- package/dist/chunk-KFIJDLQ5.js.map +0 -1
- package/dist/chunk-MM3F74K4.js.map +0 -1
- package/dist/chunk-SFVDQNTY.js +0 -156
- package/dist/chunk-SFVDQNTY.js.map +0 -1
- package/dist/graph-EXDH7EPZ.js +0 -2
- package/dist/load-5DNMGHFW.js +0 -2
- package/dist/model-call-BGTDPWZD.js +0 -2
- package/dist/program-3URNCVEZ.js.map +0 -1
- package/dist/registry-PRCISYBO.js +0 -2
- package/dist/roster-IRXP32XF.js +0 -2
- package/dist/score-KDNIUTNV.js +0 -3
- package/dist/score-KDNIUTNV.js.map +0 -1
- package/dist/types-ROL44T62.js +0 -2
- /package/dist/{absorb-eval-WU7JR3BT.js.map → absorb-eval-WY3YMLS4.js.map} +0 -0
- /package/dist/{agent-2GPJGHHG.js.map → agent-3R5NY7I3.js.map} +0 -0
- /package/dist/{board-dashboard-PUQPL4AX.js.map → board-dashboard-U3ZSCO62.js.map} +0 -0
- /package/dist/{chunk-AHO4CQRK.js.map → chunk-5NT44FKL.js.map} +0 -0
- /package/dist/{chunk-RJOA7QBB.js.map → chunk-6WF56ME6.js.map} +0 -0
- /package/dist/{chunk-MCBTVNPX.js.map → chunk-BQIWMQNU.js.map} +0 -0
- /package/dist/{chunk-YSXE65O7.js.map → chunk-GSKJ57XY.js.map} +0 -0
- /package/dist/{chunk-VQYVL72V.js.map → chunk-H6VWU2HN.js.map} +0 -0
- /package/dist/{chunk-RDEFA6Y6.js.map → chunk-LU7GDHGD.js.map} +0 -0
- /package/dist/{chunk-FEEXOWK5.js.map → chunk-QDWEM4DG.js.map} +0 -0
- /package/dist/{chunk-URN74FTP.js.map → chunk-WWDYDLY2.js.map} +0 -0
- /package/dist/{chunk-G4HDRJVN.js.map → chunk-YA3P77LV.js.map} +0 -0
- /package/dist/{chunk-XWO6ALJQ.js.map → chunk-ZFRXFUP7.js.map} +0 -0
- /package/dist/{chunk-NXRSIWQA.js.map → chunk-ZGVVYJIK.js.map} +0 -0
- /package/dist/{contributions-74M6YOCZ.js.map → contributions-KLRJ4ZXV.js.map} +0 -0
- /package/dist/{enrich-NH3WHKD6.js.map → enrich-ZB5I7KHN.js.map} +0 -0
- /package/dist/{graph-EXDH7EPZ.js.map → graph-ZVKV3JBD.js.map} +0 -0
- /package/dist/{hub-VTDFUAEH.js.map → hub-TILTOOSS.js.map} +0 -0
- /package/dist/{load-5DNMGHFW.js.map → load-EOZUZK7U.js.map} +0 -0
- /package/dist/{model-call-BGTDPWZD.js.map → model-call-PKV5UAQ7.js.map} +0 -0
- /package/dist/{promote-B2BADAEP.js.map → promote-RHVZB2QZ.js.map} +0 -0
- /package/dist/{query-2VIIGGDS.js.map → query-OZXZVLO7.js.map} +0 -0
- /package/dist/{query-settings-VJ3POZS3.js.map → query-settings-2MGUS6AY.js.map} +0 -0
- /package/dist/{registry-PRCISYBO.js.map → registry-LZLIPP7N.js.map} +0 -0
- /package/dist/{roster-IRXP32XF.js.map → roster-BZGKG2ZA.js.map} +0 -0
- /package/dist/{types-ROL44T62.js.map → types-ARP27T6T.js.map} +0 -0
- /package/dist/{wiki-SXWJ5NJQ.js.map → types-LJZ2YY5W.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as w}from"./chunk-
|
|
1
|
+
import{c as w}from"./chunk-ZFRXFUP7.js";function T(t){let r=1779033703^t.length;for(let s=0;s<t.length;s++)r=Math.imul(r^t.charCodeAt(s),3432918353),r=r<<13|r>>>19;let o=r>>>0;return()=>{o=o+1831565813>>>0;let s=o;return s=Math.imul(s^s>>>15,s|1),s^=s+Math.imul(s^s>>>7,s|61),((s^s>>>14)>>>0)/4294967296}}function _(t,r,o){let s=T(o),i=[...t].sort((e,u)=>e.path.localeCompare(u.path));for(let e=i.length-1;e>0;e--){let u=Math.floor(s()*(e+1));[i[e],i[u]]=[i[u],i[e]]}return i.slice(0,Math.max(0,r)).sort((e,u)=>e.path.localeCompare(u.path))}var R=new Set("about after again also because been before being between could does doing during each from have having here into just more most only other over same should some such than that their them then there these they this those through under until very were what when where which while will with would your yours user assistant agent message entry please thanks".split(" "));function k(t){let r=new Set;for(let o of t.toLowerCase().matchAll(/[\p{L}\p{N}][\p{L}\p{N}_-]{3,}/gu))R.has(o[0])||r.add(o[0]);return r}function E(t,r){let o=k(t);if(o.size===0)return 1;let s=k(r),i=0;for(let e of o)s.has(e)&&i++;return i/o.size}var W=.15;function $(t){let r=w(t);return{commits:r.commits,urls:r.urls,numbers:r.numbers}}function j(t,r,o){return t.includes(r)||o.some(s=>s.startsWith(r)||r.startsWith(s))}var y=t=>t.toLowerCase().replace(/\/+$/,"");function N(t,r,o){let s=t.sources.map(a=>r.get(a)).filter(a=>!!a),i=t.sources.filter(a=>!r.has(a)),e=s.filter(a=>k(a.content).size>=5&&E(a.content,t.content)<W).map(a=>a.id),u=[...s.map(a=>`${a.date??""}
|
|
2
2
|
${a.content}`),t.previous??""].join(`
|
|
3
3
|
`),l=u.toLowerCase(),d=$(u),p=new Set(d.urls.map(y)),g=new Set(d.numbers),n=$(t.content),c=[];for(let a of n.commits)j(l,a,d.commits)||c.push(`commit ${a}`);for(let a of n.urls)!p.has(y(a))&&!l.includes(y(a))&&c.push(`link ${a}`);for(let a of n.numbers)/^\d{1,2}$/.test(a)||!g.has(a)&&!l.includes(a)&&c.push(`number ${a}`);let h=[];for(let a of s){let m=$(a.content);if(m.commits.length===0&&m.urls.length===0)continue;let v=o(a.id),S=(v.length>0?v:[t.content]).join(`
|
|
4
4
|
`).toLowerCase(),x=$(S);for(let b of m.commits)j(S,b,x.commits)||h.push({entry:a.id,fact:`commit ${b}`});for(let b of m.urls)S.includes(y(b))||h.push({entry:a.id,fact:`link ${b}`})}return{path:t.path,title:t.title,type:t.type,sources:t.sources.length,missingSources:i,weakSources:e,ungrounded:c,lost:h}}function U(t,r){let o=r.toLowerCase(),s=w(r).commits,i=[];for(let e of t){let u=w(e.content),l=[...u.commits.filter(d=>!j(o,d,s)).map(d=>`commit ${d}`),...u.urls.filter(d=>!o.includes(y(d))).map(d=>`link ${d}`)];l.length>0&&i.push({entry:e.id,facts:l})}return i}var P=new Set("the and for with from into of on in at to by an a".split(" "));function L(t){return new Set((t||"").toLowerCase().split(/[^\p{L}\p{N}]+/u).filter(r=>(r.length>1||/\d/.test(r))&&!P.has(r)&&!R.has(r)))}function M(t,r){if(t.size===0||r.size===0)return 0;let o=0;for(let s of t)r.has(s)&&o++;return o/(t.size+r.size-o)}function D(t,r,o={}){let s=o.titleMin??.75,i=o.sourcesMin??.5,e=t.map(l=>({...l,tt:L(l.title),ss:new Set(l.sources??[])})),u=[];for(let l=0;l<e.length;l++)for(let d=l+1;d<e.length;d++){let p=e[l],g=e[d];if(r&&!r.has(p.path)&&!r.has(g.path))continue;let n=(p.type??"")===(g.type??"")?M(p.tt,g.tt):0;if(n>=s){u.push({a:p.path,b:g.path,reason:"title",score:n});continue}if(p.ss.size>=2&&g.ss.size>=2){let c=M(p.ss,g.ss);c>=i&&u.push({a:p.path,b:g.path,reason:"sources",score:c})}}return u.sort((l,d)=>d.score-l.score||l.a.localeCompare(d.a))}var A=4e3;function J(t,r){let o=r.map(i=>{let e=i.content.length>A?`${i.content.slice(0,A)}
|
|
@@ -33,4 +33,4 @@ Reply with JSON only, no fencing:
|
|
|
33
33
|
{"claims": 0, "supported": 0, "unsupported": [], "contradicted": [], "off_subject": [], "missing": [], "verdict": "good"}`}function z(t){if(!t||typeof t!="object"||Array.isArray(t))return null;let r=t,o=l=>Array.isArray(l)?l.map(d=>String(d)):[],s=l=>typeof l=="number"&&Number.isFinite(l)&&l>=0?Math.round(l):NaN,i=s(r.claims);if(Number.isNaN(i))return null;let e=Math.min(i,Number.isNaN(s(r.supported))?i-o(r.unsupported).length:s(r.supported)),u=r.verdict==="good"||r.verdict==="minor"||r.verdict==="major"?r.verdict:null;return u?{claims:i,supported:Math.max(0,e),unsupported:o(r.unsupported),contradicted:o(r.contradicted),offSubject:o(r.off_subject??r.offSubject),missing:o(r.missing),verdict:u}:null}function I(t,r,o,s=[],i=5,e){let u={};for(let n of t)u[n.type??"untyped"]=(u[n.type??"untyped"]??0)+1;let l=new Set,d=new Set;for(let n of t)for(let c of n.lost)l.add(c.entry),d.add(`${c.entry}|${c.fact}`);let p=new Set(r.flatMap(n=>[n.a,n.b]).filter(n=>t.some(c=>c.path===n))),g={sample:{articles:t.length,seed:o.seed,since:o.since,byType:u},citations:{withSources:t.filter(n=>n.sources>0).length,missingSources:t.reduce((n,c)=>n+c.missingSources.length,0),weakSources:t.reduce((n,c)=>n+c.weakSources.length,0),articlesWithWeak:t.filter(n=>n.weakSources.length>0).length},grounding:{articlesWithUngrounded:t.filter(n=>n.ungrounded.length>0).length,ungroundedFacts:t.reduce((n,c)=>n+c.ungrounded.length,0)},lost:{entriesWithLostFacts:l.size,lostFacts:d.size},duplicates:{pairs:r.length,articlesInPair:p.size},...e?{uncited:{entries:e.entries,withLostFacts:e.lost.length}}:{},examples:{ungrounded:t.filter(n=>n.ungrounded.length>0).slice(0,i).map(n=>({path:n.path,facts:n.ungrounded.slice(0,6)})),lost:t.flatMap(n=>n.lost.map(c=>({path:n.path,...c}))).slice(0,i),weak:t.filter(n=>n.weakSources.length>0).slice(0,i).map(n=>({path:n.path,entries:n.weakSources})),duplicates:r.slice(0,i),uncited:(e?.lost??[]).slice(0,i).map(n=>({entry:n.entry,facts:n.facts.slice(0,4)})),judged:s.filter(n=>n.verdict.verdict!=="good").slice(0,i).map(n=>({path:n.path,verdict:n.verdict.verdict,unsupported:n.verdict.unsupported.slice(0,4),contradicted:n.verdict.contradicted.slice(0,4),offSubject:n.verdict.offSubject,missing:n.verdict.missing.slice(0,4)}))}};if(s.length>0){let n=s.map(a=>a.verdict),c=n.reduce((a,m)=>a+m.claims,0),h=n.reduce((a,m)=>a+m.supported,0);g.judge={judged:n.length,claims:c,supported:h,supportRate:c>0?h/c:1,unsupported:n.reduce((a,m)=>a+m.unsupported.length,0),contradicted:n.reduce((a,m)=>a+m.contradicted.length,0),articlesWithWrongMerge:n.filter(a=>a.offSubject.length>0).length,missingFacts:n.reduce((a,m)=>a+m.missing.length,0),verdicts:{good:n.filter(a=>a.verdict==="good").length,minor:n.filter(a=>a.verdict==="minor").length,major:n.filter(a=>a.verdict==="major").length}}}return g}var f=(t,r)=>r>0?`${Math.round(t/r*100)}%`:"\u2013";function O(t){let r=t.sample.articles,o=["# Wiki absorb scorecard","",`Sample: ${r} articles (seed \`${t.sample.seed}\`${t.sample.since?`, changed since ${t.sample.since}`:""}). Types: ${Object.entries(t.sample.byType).map(([e,u])=>`${e} ${u}`).join(", ")||"\u2013"}.`,"","| Check | Result | Lower is better? |","|---|---|---|",`| Articles citing at least one entry | ${t.citations.withSources}/${r} (${f(t.citations.withSources,r)}) | no |`,`| Cited ids with no entry | ${t.citations.missingSources} | yes |`,`| Articles with a weak citation (entry shares <${Math.round(W*100)}% of its words) | ${t.citations.articlesWithWeak}/${r} (${f(t.citations.articlesWithWeak,r)}) | yes |`,`| Articles with an ungrounded commit, link or number | ${t.grounding.articlesWithUngrounded}/${r} (${f(t.grounding.articlesWithUngrounded,r)}) | yes |`,`| Ungrounded facts | ${t.grounding.ungroundedFacts} | yes |`,`| Commits or links lost from cited entries | ${t.lost.lostFacts} across ${t.lost.entriesWithLostFacts} entries | yes |`,`| Sampled articles in a likely duplicate pair | ${t.duplicates.articlesInPair}/${r} (${f(t.duplicates.articlesInPair,r)}) | yes |`];if(t.uncited&&o.push(`| Entries read in the window but cited by no article | ${t.uncited.entries} | \u2013 |`,`| \u2026of which carry a commit or link no article has | ${t.uncited.withLostFacts} | yes |`),t.judge){let e=t.judge;o.push(`| Judge: claims supported by the cited entries | ${e.supported}/${e.claims} (${f(e.supported,e.claims)}) | no |`,`| Judge: unsupported / contradicted claims | ${e.unsupported} / ${e.contradicted} | yes |`,`| Judge: articles with an off-subject source (wrong merge) | ${e.articlesWithWrongMerge}/${e.judged} (${f(e.articlesWithWrongMerge,e.judged)}) | yes |`,`| Judge: facts missing from the article | ${e.missingFacts} | yes |`,`| Judge verdicts good / minor / major | ${e.verdicts.good} / ${e.verdicts.minor} / ${e.verdicts.major} | \u2013 |`)}let s=t.examples,i=(e,u)=>{u.length!==0&&o.push("",`## ${e}`,"",...u)};return i("Examples: ungrounded facts",s.ungrounded.map(e=>`- \`${e.path}\`: ${e.facts.join("; ")}`)),i("Examples: lost facts",s.lost.map(e=>`- \`${e.path}\` \u2190 entry \`${e.entry}\`: ${e.fact}`)),i("Examples: weak citations",s.weak.map(e=>`- \`${e.path}\`: ${e.entries.map(u=>`\`${u}\``).join(", ")}`)),i("Examples: uncited entries with facts no article has",s.uncited.map(e=>`- \`${e.entry}\`: ${e.facts.join("; ")}`)),i("Examples: likely duplicates",s.duplicates.map(e=>`- \`${e.a}\` \u2194 \`${e.b}\` (${e.reason}, ${e.score.toFixed(2)})`)),i("Examples: judge findings",s.judged.map(e=>{let u=[e.unsupported.length?`unsupported: ${e.unsupported.join(" | ")}`:"",e.contradicted.length?`contradicted: ${e.contradicted.join(" | ")}`:"",e.offSubject.length?`off-subject: ${e.offSubject.join(", ")}`:"",e.missing.length?`missing: ${e.missing.join(" | ")}`:""].filter(Boolean);return`- \`${e.path}\` (${e.verdict}): ${u.join("; ")}`})),o.push("","## Method","","- The sample is drawn with a seeded shuffle from the articles changed in the window, so the same seed and window give the same articles.","- Ungrounded: a commit hash, link or number (three digits or more, or a date) in the article that no cited entry and no earlier version of the article contains.","- Lost: a commit hash or link in a cited entry that no article citing that entry contains.","- Uncited: entries the absorb ledger marks as read in the window that no article cites; those carrying a commit or link that no article on the node has are counted as lost, since absorb will not offer them again.","- Weak citation: a cited entry sharing fewer than 15% of its distinctive words with the article.","- Duplicate: two articles of the same type whose titles share at least 75% of their words, or which share at least half their sources.","- Judge (optional): one model call per article reads the article and its cited entries and lists unsupported, contradicted, off-subject and missing items."),o.join(`
|
|
34
34
|
`)+`
|
|
35
35
|
`}function V(t){if(!t||typeof t!="object")return{};let r=t,o=r.usage??{},s=i=>typeof i=="number"&&Number.isFinite(i)?i:void 0;return{costUsd:s(r.total_cost_usd)??s(r.cost_usd),apiMs:s(r.duration_api_ms),inputTokens:s(o.input_tokens),outputTokens:s(o.output_tokens),cacheReadTokens:s(o.cache_read_input_tokens),cacheWriteTokens:s(o.cache_creation_input_tokens)}}function C(t,r){return t.length===0?0:t[Math.min(t.length-1,Math.floor(r*t.length))]}function Y(t){let r=new Map,o=i=>{let e=i||"(none)",u=r.get(e);return u||r.set(e,u={calls:[],runs:[]}),u};for(let i of t)i.kind==="call"?o(i.label).calls.push(i):i.kind==="run"&&o(i.label).runs.push(i);let s=[];for(let[i,{calls:e,runs:u}]of r){if(e.length===0)continue;let l=e.map(n=>n.wallMs).sort((n,c)=>n-c),d;if(u.length>0)d=u.reduce((n,c)=>n+(Date.parse(c.endedAt)-Date.parse(c.startedAt)),0);else{let n=e.map(h=>Date.parse(h.at)-h.wallMs),c=e.map(h=>Date.parse(h.at));d=Math.max(...c)-Math.min(...n)}let p=e.reduce((n,c)=>n+c.entries,0),g=e.reduce((n,c)=>n+(c.costUsd??0),0);s.push({label:i,calls:e.length,failed:e.filter(n=>n.failed).length,entries:p,articles:e.reduce((n,c)=>n+c.articles,0),refused:e.reduce((n,c)=>n+c.refused,0),heldCited:e.reduce((n,c)=>n+(c.heldCited??0),0),wallMs:d,callMsP50:C(l,.5),callMsP95:C(l,.95),prepMs:e.reduce((n,c)=>n+(c.prepMs??0),0),costUsd:g,costPerEntry:p>0?g/p:0,entriesPerMinute:d>0?p/d*6e4:0,promptChars:e.reduce((n,c)=>n+c.promptChars,0)})}return s.sort((i,e)=>i.label.localeCompare(e.label))}export{T as a,_ as b,k as c,E as d,W as e,N as f,U as g,D as h,A as i,J as j,z as k,I as l,O as m,V as n,Y as o};
|
|
36
|
-
//# sourceMappingURL=chunk-
|
|
36
|
+
//# sourceMappingURL=chunk-RVEMX5MJ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/wiki/absorb-eval.ts"],"sourcesContent":["// Measuring what `agentx wiki absorb` writes (#808).\n//\n// Absorb turns raw entries into articles, and until now nothing checked\n// the result against the entries it came from. This module is the\n// scorecard: a fixed, seeded sample of articles, five checks per article,\n// and an optional model judge for the questions a string match cannot\n// answer (is this claim supported, does this source belong here).\n//\n// The deterministic checks are deliberately narrow. A commit hash or URL\n// in an article that no cited entry and no earlier version carries is\n// almost certainly made up or mis-attributed; a commit or URL in a cited\n// entry that no article carries was almost certainly lost. Prose claims\n// are left to the judge.\n\nimport { extractFacts } from \"./absorb-context\"\n\nexport interface EvalArticle {\n path: string\n title: string\n type?: string\n content: string\n sources: string[]\n lastUpdated?: string\n /** The article body before this absorb touched it, when one exists. */\n previous?: string\n}\n\nexport interface EvalEntry {\n id: string\n date?: string\n content: string\n}\n\n// --- Sample ---\n\n/** A small seeded PRNG, so a sample can be drawn again from the same seed. */\nexport function seededRandom(seed: string): () => number {\n let h = 1779033703 ^ seed.length\n for (let i = 0; i < seed.length; i++) {\n h = Math.imul(h ^ seed.charCodeAt(i), 3432918353)\n h = (h << 13) | (h >>> 19)\n }\n let a = h >>> 0\n return () => {\n a = (a + 0x6d2b79f5) >>> 0\n let t = a\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n\n/** `n` items picked without replacement. Same items and seed, same pick. */\nexport function pickSample<T extends { path: string }>(items: T[], n: number, seed: string): T[] {\n const rng = seededRandom(seed)\n const pool = [...items].sort((a, b) => a.path.localeCompare(b.path))\n for (let i = pool.length - 1; i > 0; i--) {\n const j = Math.floor(rng() * (i + 1))\n ;[pool[i], pool[j]] = [pool[j], pool[i]]\n }\n return pool.slice(0, Math.max(0, n)).sort((a, b) => a.path.localeCompare(b.path))\n}\n\n// --- Terms ---\n\nconst STOP = new Set(\n (\"about after again also because been before being between could does doing during each from have having here into \"\n + \"just more most only other over same should some such than that their them then there these they this those \"\n + \"through under until very were what when where which while will with would your yours user assistant agent \"\n + \"message entry please thanks\").split(\" \"),\n)\n\n/** Distinctive words: four letters or more, lower-cased, minus common ones. */\nexport function terms(text: string): Set<string> {\n const out = new Set<string>()\n for (const m of text.toLowerCase().matchAll(/[\\p{L}\\p{N}][\\p{L}\\p{N}_-]{3,}/gu)) {\n if (!STOP.has(m[0])) out.add(m[0])\n }\n return out\n}\n\n/** Share of `entry`'s distinctive words that appear in `article`. */\nexport function termOverlap(entry: string, article: string): number {\n const e = terms(entry)\n if (e.size === 0) return 1\n const a = terms(article)\n let hit = 0\n for (const t of e) if (a.has(t)) hit++\n return hit / e.size\n}\n\n// --- Per-article checks ---\n\n/** Below this share of shared words a cited entry is flagged as weak. */\nexport const WEAK_CITATION = 0.15\n\nexport interface ArticleCheck {\n path: string\n title: string\n type?: string\n sources: number\n /** Cited ids with no entry behind them. */\n missingSources: string[]\n /** Cited entries that share almost no words with the article. */\n weakSources: string[]\n /** Commits, links and numbers in the article that neither a cited entry\n * nor the earlier version carries. */\n ungrounded: string[]\n /** Commits and links in a cited entry that no article citing it carries. */\n lost: Array<{ entry: string; fact: string }>\n}\n\n/** What a fact looks like when matched against grounding text. */\nfunction factStrings(text: string): { commits: string[]; urls: string[]; numbers: string[] } {\n const f = extractFacts(text)\n return { commits: f.commits, urls: f.urls, numbers: f.numbers }\n}\n\nfunction hasCommit(haystack: string, commit: string, known: string[]): boolean {\n return haystack.includes(commit) || known.some((k) => k.startsWith(commit) || commit.startsWith(k))\n}\n\nconst urlKey = (u: string) => u.toLowerCase().replace(/\\/+$/, \"\")\n\n/**\n * Check one article against its cited entries.\n *\n * `citersOf` returns every article (in the whole wiki, not only the\n * sample) that cites an entry, so a fact moved to a sibling article is\n * not counted as lost.\n */\nexport function checkArticle(\n article: EvalArticle,\n entries: Map<string, EvalEntry>,\n citersOf: (entryId: string) => string[],\n): ArticleCheck {\n const cited = article.sources.map((id) => entries.get(id)).filter((e): e is EvalEntry => !!e)\n const missingSources = article.sources.filter((id) => !entries.has(id))\n\n const weakSources = cited\n .filter((e) => terms(e.content).size >= 5 && termOverlap(e.content, article.content) < WEAK_CITATION)\n .map((e) => e.id)\n\n // Grounding: entry text with its date (absorb is shown the date in the\n // entry header), plus the earlier version of the article.\n const grounding = [...cited.map((e) => `${e.date ?? \"\"}\\n${e.content}`), article.previous ?? \"\"].join(\"\\n\")\n const groundLower = grounding.toLowerCase()\n const g = factStrings(grounding)\n const groundUrls = new Set(g.urls.map(urlKey))\n const groundNumbers = new Set(g.numbers)\n const mine = factStrings(article.content)\n const ungrounded: string[] = []\n for (const c of mine.commits) if (!hasCommit(groundLower, c, g.commits)) ungrounded.push(`commit ${c}`)\n for (const u of mine.urls) if (!groundUrls.has(urlKey(u)) && !groundLower.includes(urlKey(u))) ungrounded.push(`link ${u}`)\n for (const n of mine.numbers) {\n // Bare small integers (\"2 tests\", \"3 people\") are too common to judge.\n if (/^\\d{1,2}$/.test(n)) continue\n if (!groundNumbers.has(n) && !groundLower.includes(n)) ungrounded.push(`number ${n}`)\n }\n\n const lost: Array<{ entry: string; fact: string }> = []\n for (const e of cited) {\n const facts = factStrings(e.content)\n if (facts.commits.length === 0 && facts.urls.length === 0) continue\n const carriers = citersOf(e.id)\n const text = (carriers.length > 0 ? carriers : [article.content]).join(\"\\n\").toLowerCase()\n const carrierFacts = factStrings(text)\n for (const c of facts.commits) if (!hasCommit(text, c, carrierFacts.commits)) lost.push({ entry: e.id, fact: `commit ${c}` })\n for (const u of facts.urls) if (!text.includes(urlKey(u))) lost.push({ entry: e.id, fact: `link ${u}` })\n }\n\n return {\n path: article.path,\n title: article.title,\n type: article.type,\n sources: article.sources.length,\n missingSources,\n weakSources,\n ungrounded,\n lost,\n }\n}\n\n// --- Uncited entries ---\n\n/**\n * Entries absorb read and cited nowhere that carry a commit or link no\n * article on the node has. A successful run marks every entry it read as\n * done (#762), so a fact in an entry the model passed over is gone from\n * the queue for good; the per-article \"lost\" check cannot see it because\n * no article points back at the entry.\n */\nexport function uncitedWithFacts(\n uncited: EvalEntry[],\n allArticles: string,\n): Array<{ entry: string; facts: string[] }> {\n const lower = allArticles.toLowerCase()\n const known = extractFacts(allArticles).commits\n const out: Array<{ entry: string; facts: string[] }> = []\n for (const e of uncited) {\n const f = extractFacts(e.content)\n const missing = [\n ...f.commits.filter((c) => !hasCommit(lower, c, known)).map((c) => `commit ${c}`),\n ...f.urls.filter((u) => !lower.includes(urlKey(u))).map((u) => `link ${u}`),\n ]\n if (missing.length > 0) out.push({ entry: e.id, facts: missing })\n }\n return out\n}\n\n// --- Duplicates ---\n\nexport interface DuplicatePair {\n a: string\n b: string\n reason: \"title\" | \"sources\"\n score: number\n}\n\nconst TITLE_STOP = new Set(\"the and for with from into of on in at to by an a\".split(\" \"))\n\nfunction titleTerms(title: string): Set<string> {\n return new Set(\n (title || \"\").toLowerCase().split(/[^\\p{L}\\p{N}]+/u).filter((w) => (w.length > 1 || /\\d/.test(w)) && !TITLE_STOP.has(w) && !STOP.has(w)),\n )\n}\n\nfunction jaccard<T>(a: Set<T>, b: Set<T>): number {\n if (a.size === 0 || b.size === 0) return 0\n let inter = 0\n for (const x of a) if (b.has(x)) inter++\n return inter / (a.size + b.size - inter)\n}\n\n/**\n * Pairs of articles that look like one subject filed twice: the same type\n * and near-identical title words, or most of their sources in common.\n * Only pairs touching `focus` are returned when it is given.\n */\nexport function findDuplicates(\n catalog: Array<{ path: string; title: string; type?: string; sources?: string[] }>,\n focus?: Set<string>,\n opts: { titleMin?: number; sourcesMin?: number } = {},\n): DuplicatePair[] {\n const titleMin = opts.titleMin ?? 0.75\n const sourcesMin = opts.sourcesMin ?? 0.5\n const rows = catalog.map((a) => ({ ...a, tt: titleTerms(a.title), ss: new Set(a.sources ?? []) }))\n const pairs: DuplicatePair[] = []\n for (let i = 0; i < rows.length; i++) {\n for (let j = i + 1; j < rows.length; j++) {\n const x = rows[i], y = rows[j]\n if (focus && !focus.has(x.path) && !focus.has(y.path)) continue\n const t = (x.type ?? \"\") === (y.type ?? \"\") ? jaccard(x.tt, y.tt) : 0\n if (t >= titleMin) { pairs.push({ a: x.path, b: y.path, reason: \"title\", score: t }); continue }\n if (x.ss.size >= 2 && y.ss.size >= 2) {\n const s = jaccard(x.ss, y.ss)\n if (s >= sourcesMin) pairs.push({ a: x.path, b: y.path, reason: \"sources\", score: s })\n }\n }\n }\n return pairs.sort((p, q) => q.score - p.score || p.a.localeCompare(q.a))\n}\n\n// --- Model judge ---\n\nexport interface JudgeVerdict {\n claims: number\n supported: number\n unsupported: string[]\n contradicted: string[]\n /** Cited entry ids that are about a different subject (a wrong merge). */\n offSubject: string[]\n /** Facts in the entries that belong in this article and are missing. */\n missing: string[]\n verdict: \"good\" | \"minor\" | \"major\"\n}\n\n/** Per-entry cap in the judge prompt, so one long transcript cannot crowd out the rest. */\nexport const JUDGE_ENTRY_CHARS = 4000\n\nexport function buildJudgePrompt(article: EvalArticle, entries: EvalEntry[]): string {\n const sourceBlock = entries\n .map((e) => {\n const body = e.content.length > JUDGE_ENTRY_CHARS ? `${e.content.slice(0, JUDGE_ENTRY_CHARS)}\\n[…cut]` : e.content\n return `--- ENTRY ${e.id} [${e.date ?? \"\"}] ---\\n${body}\\n--- END ENTRY ---`\n })\n .join(\"\\n\\n\")\n const earlier = article.previous\n ? `\\n## Earlier version of the article (facts here count as supported)\\n\\n${article.previous}\\n`\n : \"\"\n return `You are auditing one wiki article against the raw entries it cites. Do not use outside knowledge.\n\n## Article: ${article.title} (${article.type ?? \"untyped\"}, ${article.path})\n\n${article.content}\n${earlier}\n## Cited entries (${entries.length})\n\n${sourceBlock || \"(none)\"}\n\n## What to report\n\n1. Split the article into factual claims (one per sentence or bullet; skip headings and \"unknown\" placeholders). Count them.\n2. A claim is supported when a cited entry or the earlier version states it or plainly implies it. List each claim that is not supported, quoted briefly.\n3. List each claim an entry contradicts.\n4. List the cited entry ids that are about a different subject than the article (they were merged in by mistake).\n5. List facts from the entries that belong in this article and are missing (names, numbers, identifiers, decisions). Ignore small talk.\n6. Verdict: \"good\" (nothing wrong), \"minor\" (wording or a small omission), \"major\" (an unsupported or contradicted fact, a wrong merge, or a lost identifier).\n\nReply with JSON only, no fencing:\n{\"claims\": 0, \"supported\": 0, \"unsupported\": [], \"contradicted\": [], \"off_subject\": [], \"missing\": [], \"verdict\": \"good\"}`\n}\n\nexport function parseJudgeReply(value: unknown): JudgeVerdict | null {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return null\n const v = value as Record<string, unknown>\n const list = (x: unknown) => (Array.isArray(x) ? x.map((s) => String(s)) : [])\n const num = (x: unknown) => (typeof x === \"number\" && Number.isFinite(x) && x >= 0 ? Math.round(x) : NaN)\n const claims = num(v.claims)\n if (Number.isNaN(claims)) return null\n const supported = Math.min(claims, Number.isNaN(num(v.supported)) ? claims - list(v.unsupported).length : num(v.supported))\n const verdict = v.verdict === \"good\" || v.verdict === \"minor\" || v.verdict === \"major\" ? v.verdict : null\n if (!verdict) return null\n return {\n claims,\n supported: Math.max(0, supported),\n unsupported: list(v.unsupported),\n contradicted: list(v.contradicted),\n offSubject: list(v.off_subject ?? v.offSubject),\n missing: list(v.missing),\n verdict,\n }\n}\n\n// --- Scorecard ---\n\nexport interface Scorecard {\n sample: { articles: number; seed: string; since?: string; byType: Record<string, number> }\n citations: { withSources: number; missingSources: number; weakSources: number; articlesWithWeak: number }\n grounding: { articlesWithUngrounded: number; ungroundedFacts: number }\n lost: { entriesWithLostFacts: number; lostFacts: number }\n duplicates: { pairs: number; articlesInPair: number }\n /** Entries read in the window that no article cites. */\n uncited?: { entries: number; withLostFacts: number }\n judge?: {\n judged: number\n claims: number\n supported: number\n supportRate: number\n unsupported: number\n contradicted: number\n articlesWithWrongMerge: number\n missingFacts: number\n verdicts: Record<\"good\" | \"minor\" | \"major\", number>\n }\n examples: {\n ungrounded: Array<{ path: string; facts: string[] }>\n lost: Array<{ path: string; entry: string; fact: string }>\n weak: Array<{ path: string; entries: string[] }>\n duplicates: DuplicatePair[]\n uncited: Array<{ entry: string; facts: string[] }>\n judged: Array<{ path: string; verdict: string; unsupported: string[]; contradicted: string[]; offSubject: string[]; missing: string[] }>\n }\n}\n\nexport function buildScorecard(\n checks: ArticleCheck[],\n duplicates: DuplicatePair[],\n meta: { seed: string; since?: string },\n judged: Array<{ path: string; verdict: JudgeVerdict }> = [],\n maxExamples = 5,\n uncited?: { entries: number; lost: Array<{ entry: string; facts: string[] }> },\n): Scorecard {\n const byType: Record<string, number> = {}\n for (const c of checks) byType[c.type ?? \"untyped\"] = (byType[c.type ?? \"untyped\"] ?? 0) + 1\n const lostEntries = new Set<string>()\n const lostKeys = new Set<string>()\n for (const c of checks) for (const l of c.lost) { lostEntries.add(l.entry); lostKeys.add(`${l.entry}|${l.fact}`) }\n const inPair = new Set(duplicates.flatMap((d) => [d.a, d.b]).filter((p) => checks.some((c) => c.path === p)))\n\n const card: Scorecard = {\n sample: { articles: checks.length, seed: meta.seed, since: meta.since, byType },\n citations: {\n withSources: checks.filter((c) => c.sources > 0).length,\n missingSources: checks.reduce((s, c) => s + c.missingSources.length, 0),\n weakSources: checks.reduce((s, c) => s + c.weakSources.length, 0),\n articlesWithWeak: checks.filter((c) => c.weakSources.length > 0).length,\n },\n grounding: {\n articlesWithUngrounded: checks.filter((c) => c.ungrounded.length > 0).length,\n ungroundedFacts: checks.reduce((s, c) => s + c.ungrounded.length, 0),\n },\n lost: { entriesWithLostFacts: lostEntries.size, lostFacts: lostKeys.size },\n duplicates: { pairs: duplicates.length, articlesInPair: inPair.size },\n ...(uncited ? { uncited: { entries: uncited.entries, withLostFacts: uncited.lost.length } } : {}),\n examples: {\n ungrounded: checks.filter((c) => c.ungrounded.length > 0).slice(0, maxExamples).map((c) => ({ path: c.path, facts: c.ungrounded.slice(0, 6) })),\n lost: checks.flatMap((c) => c.lost.map((l) => ({ path: c.path, ...l }))).slice(0, maxExamples),\n weak: checks.filter((c) => c.weakSources.length > 0).slice(0, maxExamples).map((c) => ({ path: c.path, entries: c.weakSources })),\n duplicates: duplicates.slice(0, maxExamples),\n uncited: (uncited?.lost ?? []).slice(0, maxExamples).map((u) => ({ entry: u.entry, facts: u.facts.slice(0, 4) })),\n judged: judged\n .filter((j) => j.verdict.verdict !== \"good\")\n .slice(0, maxExamples)\n .map((j) => ({\n path: j.path,\n verdict: j.verdict.verdict,\n unsupported: j.verdict.unsupported.slice(0, 4),\n contradicted: j.verdict.contradicted.slice(0, 4),\n offSubject: j.verdict.offSubject,\n missing: j.verdict.missing.slice(0, 4),\n })),\n },\n }\n\n if (judged.length > 0) {\n const v = judged.map((j) => j.verdict)\n const claims = v.reduce((s, x) => s + x.claims, 0)\n const supported = v.reduce((s, x) => s + x.supported, 0)\n card.judge = {\n judged: v.length,\n claims,\n supported,\n supportRate: claims > 0 ? supported / claims : 1,\n unsupported: v.reduce((s, x) => s + x.unsupported.length, 0),\n contradicted: v.reduce((s, x) => s + x.contradicted.length, 0),\n articlesWithWrongMerge: v.filter((x) => x.offSubject.length > 0).length,\n missingFacts: v.reduce((s, x) => s + x.missing.length, 0),\n verdicts: {\n good: v.filter((x) => x.verdict === \"good\").length,\n minor: v.filter((x) => x.verdict === \"minor\").length,\n major: v.filter((x) => x.verdict === \"major\").length,\n },\n }\n }\n return card\n}\n\nconst pct = (n: number, d: number) => (d > 0 ? `${Math.round((n / d) * 100)}%` : \"–\")\n\n/** The scorecard as Markdown, for the issue or a PR comment. */\nexport function renderScorecard(card: Scorecard): string {\n const n = card.sample.articles\n const lines = [\n `# Wiki absorb scorecard`,\n \"\",\n `Sample: ${n} articles (seed \\`${card.sample.seed}\\`${card.sample.since ? `, changed since ${card.sample.since}` : \"\"}). `\n + `Types: ${Object.entries(card.sample.byType).map(([t, k]) => `${t} ${k}`).join(\", \") || \"–\"}.`,\n \"\",\n \"| Check | Result | Lower is better? |\",\n \"|---|---|---|\",\n `| Articles citing at least one entry | ${card.citations.withSources}/${n} (${pct(card.citations.withSources, n)}) | no |`,\n `| Cited ids with no entry | ${card.citations.missingSources} | yes |`,\n `| Articles with a weak citation (entry shares <${Math.round(WEAK_CITATION * 100)}% of its words) | ${card.citations.articlesWithWeak}/${n} (${pct(card.citations.articlesWithWeak, n)}) | yes |`,\n `| Articles with an ungrounded commit, link or number | ${card.grounding.articlesWithUngrounded}/${n} (${pct(card.grounding.articlesWithUngrounded, n)}) | yes |`,\n `| Ungrounded facts | ${card.grounding.ungroundedFacts} | yes |`,\n `| Commits or links lost from cited entries | ${card.lost.lostFacts} across ${card.lost.entriesWithLostFacts} entries | yes |`,\n `| Sampled articles in a likely duplicate pair | ${card.duplicates.articlesInPair}/${n} (${pct(card.duplicates.articlesInPair, n)}) | yes |`,\n ]\n if (card.uncited) {\n lines.push(\n `| Entries read in the window but cited by no article | ${card.uncited.entries} | – |`,\n `| …of which carry a commit or link no article has | ${card.uncited.withLostFacts} | yes |`,\n )\n }\n if (card.judge) {\n const j = card.judge\n lines.push(\n `| Judge: claims supported by the cited entries | ${j.supported}/${j.claims} (${pct(j.supported, j.claims)}) | no |`,\n `| Judge: unsupported / contradicted claims | ${j.unsupported} / ${j.contradicted} | yes |`,\n `| Judge: articles with an off-subject source (wrong merge) | ${j.articlesWithWrongMerge}/${j.judged} (${pct(j.articlesWithWrongMerge, j.judged)}) | yes |`,\n `| Judge: facts missing from the article | ${j.missingFacts} | yes |`,\n `| Judge verdicts good / minor / major | ${j.verdicts.good} / ${j.verdicts.minor} / ${j.verdicts.major} | – |`,\n )\n }\n const ex = card.examples\n const section = (title: string, rows: string[]) => {\n if (rows.length === 0) return\n lines.push(\"\", `## ${title}`, \"\", ...rows)\n }\n section(\"Examples: ungrounded facts\", ex.ungrounded.map((e) => `- \\`${e.path}\\`: ${e.facts.join(\"; \")}`))\n section(\"Examples: lost facts\", ex.lost.map((e) => `- \\`${e.path}\\` ← entry \\`${e.entry}\\`: ${e.fact}`))\n section(\"Examples: weak citations\", ex.weak.map((e) => `- \\`${e.path}\\`: ${e.entries.map((x) => `\\`${x}\\``).join(\", \")}`))\n section(\"Examples: uncited entries with facts no article has\", ex.uncited.map((u) => `- \\`${u.entry}\\`: ${u.facts.join(\"; \")}`))\n section(\"Examples: likely duplicates\", ex.duplicates.map((d) => `- \\`${d.a}\\` ↔ \\`${d.b}\\` (${d.reason}, ${d.score.toFixed(2)})`))\n section(\n \"Examples: judge findings\",\n ex.judged.map((e) => {\n const parts = [\n e.unsupported.length ? `unsupported: ${e.unsupported.join(\" | \")}` : \"\",\n e.contradicted.length ? `contradicted: ${e.contradicted.join(\" | \")}` : \"\",\n e.offSubject.length ? `off-subject: ${e.offSubject.join(\", \")}` : \"\",\n e.missing.length ? `missing: ${e.missing.join(\" | \")}` : \"\",\n ].filter(Boolean)\n return `- \\`${e.path}\\` (${e.verdict}): ${parts.join(\"; \")}`\n }),\n )\n lines.push(\n \"\",\n \"## Method\",\n \"\",\n \"- The sample is drawn with a seeded shuffle from the articles changed in the window, so the same seed and window give the same articles.\",\n \"- Ungrounded: a commit hash, link or number (three digits or more, or a date) in the article that no cited entry and no earlier version of the article contains.\",\n \"- Lost: a commit hash or link in a cited entry that no article citing that entry contains.\",\n \"- Uncited: entries the absorb ledger marks as read in the window that no article cites; those carrying a commit or link that no article on the node has are counted as lost, since absorb will not offer them again.\",\n \"- Weak citation: a cited entry sharing fewer than 15% of its distinctive words with the article.\",\n \"- Duplicate: two articles of the same type whose titles share at least 75% of their words, or which share at least half their sources.\",\n \"- Judge (optional): one model call per article reads the article and its cited entries and lists unsupported, contradicted, off-subject and missing items.\",\n )\n return lines.join(\"\\n\") + \"\\n\"\n}\n\n// --- Run telemetry ---\n\n/** One compile call, as appended to `_absorb-runs.jsonl`. */\nexport interface AbsorbCallRecord {\n kind: \"call\"\n at: string\n label?: string\n agent: string\n model: string\n entries: number\n articles: number\n refused: number\n /** Entries held by a refused save that another saved article cites:\n * they leave the queue, so the refused update is never retried. */\n heldCited?: number\n /** Wiki notes (#831) the call was given, patched, and recorded. */\n notes?: number\n notesPatched?: number\n notesRecorded?: number\n failed: boolean\n /** The model call alone. */\n wallMs: number\n /** Retrieval, fact lookups and prompt building before the call. */\n prepMs?: number\n promptChars: number\n promptParts?: Record<string, number>\n costUsd?: number\n apiMs?: number\n inputTokens?: number\n outputTokens?: number\n cacheReadTokens?: number\n cacheWriteTokens?: number\n}\n\n/** One whole `wiki absorb` invocation. */\nexport interface AbsorbRunRecord {\n kind: \"run\"\n label?: string\n startedAt: string\n endedAt: string\n max: number\n model: string\n}\n\n/** Cost and timing fields from the claude CLI's `--output-format json` envelope. */\nexport function envelopeUsage(envelope: unknown): Partial<AbsorbCallRecord> {\n if (!envelope || typeof envelope !== \"object\") return {}\n const e = envelope as Record<string, any>\n const u = (e.usage ?? {}) as Record<string, unknown>\n const n = (x: unknown) => (typeof x === \"number\" && Number.isFinite(x) ? x : undefined)\n return {\n costUsd: n(e.total_cost_usd) ?? n(e.cost_usd),\n apiMs: n(e.duration_api_ms),\n inputTokens: n(u.input_tokens),\n outputTokens: n(u.output_tokens),\n cacheReadTokens: n(u.cache_read_input_tokens),\n cacheWriteTokens: n(u.cache_creation_input_tokens),\n }\n}\n\nexport interface RunSummary {\n label: string\n calls: number\n failed: number\n entries: number\n articles: number\n refused: number\n heldCited: number\n /** First call start to last call end, or the run records' span when present. */\n wallMs: number\n callMsP50: number\n callMsP95: number\n /** Time spent before the model calls, summed. */\n prepMs: number\n costUsd: number\n costPerEntry: number\n entriesPerMinute: number\n promptChars: number\n}\n\nfunction percentile(sorted: number[], p: number): number {\n if (sorted.length === 0) return 0\n return sorted[Math.min(sorted.length - 1, Math.floor(p * sorted.length))]\n}\n\n/** Totals per run label from the telemetry lines. Calls without a label group under \"(none)\". */\nexport function summariseRuns(records: Array<AbsorbCallRecord | AbsorbRunRecord>): RunSummary[] {\n const groups = new Map<string, { calls: AbsorbCallRecord[]; runs: AbsorbRunRecord[] }>()\n const group = (label?: string) => {\n const key = label || \"(none)\"\n let g = groups.get(key)\n if (!g) groups.set(key, (g = { calls: [], runs: [] }))\n return g\n }\n for (const r of records) {\n if (r.kind === \"call\") group(r.label).calls.push(r)\n else if (r.kind === \"run\") group(r.label).runs.push(r)\n }\n const out: RunSummary[] = []\n for (const [label, { calls, runs }] of groups) {\n if (calls.length === 0) continue\n const ms = calls.map((c) => c.wallMs).sort((a, b) => a - b)\n let wallMs: number\n if (runs.length > 0) {\n wallMs = runs.reduce((s, r) => s + (Date.parse(r.endedAt) - Date.parse(r.startedAt)), 0)\n } else {\n const starts = calls.map((c) => Date.parse(c.at) - c.wallMs)\n const ends = calls.map((c) => Date.parse(c.at))\n wallMs = Math.max(...ends) - Math.min(...starts)\n }\n const entries = calls.reduce((s, c) => s + c.entries, 0)\n const costUsd = calls.reduce((s, c) => s + (c.costUsd ?? 0), 0)\n out.push({\n label,\n calls: calls.length,\n failed: calls.filter((c) => c.failed).length,\n entries,\n articles: calls.reduce((s, c) => s + c.articles, 0),\n refused: calls.reduce((s, c) => s + c.refused, 0),\n heldCited: calls.reduce((s, c) => s + (c.heldCited ?? 0), 0),\n wallMs,\n callMsP50: percentile(ms, 0.5),\n callMsP95: percentile(ms, 0.95),\n prepMs: calls.reduce((s, c) => s + (c.prepMs ?? 0), 0),\n costUsd,\n costPerEntry: entries > 0 ? costUsd / entries : 0,\n entriesPerMinute: wallMs > 0 ? (entries / wallMs) * 60_000 : 0,\n promptChars: calls.reduce((s, c) => s + c.promptChars, 0),\n })\n }\n return out.sort((a, b) => a.label.localeCompare(b.label))\n}\n"],"mappings":"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","names":["seededRandom","seed","h","i","a","t","pickSample","items","n","rng","pool","b","j","STOP","terms","text","out","m","termOverlap","entry","article","e","hit","WEAK_CITATION","factStrings","f","extractFacts","hasCommit","haystack","commit","known","k","urlKey","u","checkArticle","entries","citersOf","cited","id","missingSources","weakSources","grounding","groundLower","g","groundUrls","groundNumbers","mine","ungrounded","c","lost","facts","carriers","carrierFacts","uncitedWithFacts","uncited","allArticles","lower","missing","TITLE_STOP","titleTerms","title","w","jaccard","inter","x","findDuplicates","catalog","focus","opts","titleMin","sourcesMin","rows","pairs","y","s","p","q","JUDGE_ENTRY_CHARS","buildJudgePrompt","sourceBlock","body","earlier","parseJudgeReply","value","v","list","num","claims","supported","verdict","buildScorecard","checks","duplicates","meta","judged","maxExamples","byType","lostEntries","lostKeys","l","inPair","d","card","pct","renderScorecard","lines","ex","section","parts","envelopeUsage","envelope","percentile","sorted","summariseRuns","records","groups","group","label","key","r","calls","runs","ms","wallMs","starts","ends","costUsd"]}
|
|
1
|
+
{"version":3,"sources":["../src/wiki/absorb-eval.ts"],"sourcesContent":["// Measuring what `agentx wiki absorb` writes (#808).\n//\n// Absorb turns raw entries into articles, and until now nothing checked\n// the result against the entries it came from. This module is the\n// scorecard: a fixed, seeded sample of articles, five checks per article,\n// and an optional model judge for the questions a string match cannot\n// answer (is this claim supported, does this source belong here).\n//\n// The deterministic checks are deliberately narrow. A commit hash or URL\n// in an article that no cited entry and no earlier version carries is\n// almost certainly made up or mis-attributed; a commit or URL in a cited\n// entry that no article carries was almost certainly lost. Prose claims\n// are left to the judge.\n\nimport { extractFacts } from \"./absorb-context\"\n\nexport interface EvalArticle {\n path: string\n title: string\n type?: string\n content: string\n sources: string[]\n lastUpdated?: string\n /** The article body before this absorb touched it, when one exists. */\n previous?: string\n}\n\nexport interface EvalEntry {\n id: string\n date?: string\n content: string\n}\n\n// --- Sample ---\n\n/** A small seeded PRNG, so a sample can be drawn again from the same seed. */\nexport function seededRandom(seed: string): () => number {\n let h = 1779033703 ^ seed.length\n for (let i = 0; i < seed.length; i++) {\n h = Math.imul(h ^ seed.charCodeAt(i), 3432918353)\n h = (h << 13) | (h >>> 19)\n }\n let a = h >>> 0\n return () => {\n a = (a + 0x6d2b79f5) >>> 0\n let t = a\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n\n/** `n` items picked without replacement. Same items and seed, same pick. */\nexport function pickSample<T extends { path: string }>(items: T[], n: number, seed: string): T[] {\n const rng = seededRandom(seed)\n const pool = [...items].sort((a, b) => a.path.localeCompare(b.path))\n for (let i = pool.length - 1; i > 0; i--) {\n const j = Math.floor(rng() * (i + 1))\n ;[pool[i], pool[j]] = [pool[j], pool[i]]\n }\n return pool.slice(0, Math.max(0, n)).sort((a, b) => a.path.localeCompare(b.path))\n}\n\n// --- Terms ---\n\nconst STOP = new Set(\n (\"about after again also because been before being between could does doing during each from have having here into \"\n + \"just more most only other over same should some such than that their them then there these they this those \"\n + \"through under until very were what when where which while will with would your yours user assistant agent \"\n + \"message entry please thanks\").split(\" \"),\n)\n\n/** Distinctive words: four letters or more, lower-cased, minus common ones. */\nexport function terms(text: string): Set<string> {\n const out = new Set<string>()\n for (const m of text.toLowerCase().matchAll(/[\\p{L}\\p{N}][\\p{L}\\p{N}_-]{3,}/gu)) {\n if (!STOP.has(m[0])) out.add(m[0])\n }\n return out\n}\n\n/** Share of `entry`'s distinctive words that appear in `article`. */\nexport function termOverlap(entry: string, article: string): number {\n const e = terms(entry)\n if (e.size === 0) return 1\n const a = terms(article)\n let hit = 0\n for (const t of e) if (a.has(t)) hit++\n return hit / e.size\n}\n\n// --- Per-article checks ---\n\n/** Below this share of shared words a cited entry is flagged as weak. */\nexport const WEAK_CITATION = 0.15\n\nexport interface ArticleCheck {\n path: string\n title: string\n type?: string\n sources: number\n /** Cited ids with no entry behind them. */\n missingSources: string[]\n /** Cited entries that share almost no words with the article. */\n weakSources: string[]\n /** Commits, links and numbers in the article that neither a cited entry\n * nor the earlier version carries. */\n ungrounded: string[]\n /** Commits and links in a cited entry that no article citing it carries. */\n lost: Array<{ entry: string; fact: string }>\n}\n\n/** What a fact looks like when matched against grounding text. */\nfunction factStrings(text: string): { commits: string[]; urls: string[]; numbers: string[] } {\n const f = extractFacts(text)\n return { commits: f.commits, urls: f.urls, numbers: f.numbers }\n}\n\nfunction hasCommit(haystack: string, commit: string, known: string[]): boolean {\n return haystack.includes(commit) || known.some((k) => k.startsWith(commit) || commit.startsWith(k))\n}\n\nconst urlKey = (u: string) => u.toLowerCase().replace(/\\/+$/, \"\")\n\n/**\n * Check one article against its cited entries.\n *\n * `citersOf` returns every article (in the whole wiki, not only the\n * sample) that cites an entry, so a fact moved to a sibling article is\n * not counted as lost.\n */\nexport function checkArticle(\n article: EvalArticle,\n entries: Map<string, EvalEntry>,\n citersOf: (entryId: string) => string[],\n): ArticleCheck {\n const cited = article.sources.map((id) => entries.get(id)).filter((e): e is EvalEntry => !!e)\n const missingSources = article.sources.filter((id) => !entries.has(id))\n\n const weakSources = cited\n .filter((e) => terms(e.content).size >= 5 && termOverlap(e.content, article.content) < WEAK_CITATION)\n .map((e) => e.id)\n\n // Grounding: entry text with its date (absorb is shown the date in the\n // entry header), plus the earlier version of the article.\n const grounding = [...cited.map((e) => `${e.date ?? \"\"}\\n${e.content}`), article.previous ?? \"\"].join(\"\\n\")\n const groundLower = grounding.toLowerCase()\n const g = factStrings(grounding)\n const groundUrls = new Set(g.urls.map(urlKey))\n const groundNumbers = new Set(g.numbers)\n const mine = factStrings(article.content)\n const ungrounded: string[] = []\n for (const c of mine.commits) if (!hasCommit(groundLower, c, g.commits)) ungrounded.push(`commit ${c}`)\n for (const u of mine.urls) if (!groundUrls.has(urlKey(u)) && !groundLower.includes(urlKey(u))) ungrounded.push(`link ${u}`)\n for (const n of mine.numbers) {\n // Bare small integers (\"2 tests\", \"3 people\") are too common to judge.\n if (/^\\d{1,2}$/.test(n)) continue\n if (!groundNumbers.has(n) && !groundLower.includes(n)) ungrounded.push(`number ${n}`)\n }\n\n const lost: Array<{ entry: string; fact: string }> = []\n for (const e of cited) {\n const facts = factStrings(e.content)\n if (facts.commits.length === 0 && facts.urls.length === 0) continue\n const carriers = citersOf(e.id)\n const text = (carriers.length > 0 ? carriers : [article.content]).join(\"\\n\").toLowerCase()\n const carrierFacts = factStrings(text)\n for (const c of facts.commits) if (!hasCommit(text, c, carrierFacts.commits)) lost.push({ entry: e.id, fact: `commit ${c}` })\n for (const u of facts.urls) if (!text.includes(urlKey(u))) lost.push({ entry: e.id, fact: `link ${u}` })\n }\n\n return {\n path: article.path,\n title: article.title,\n type: article.type,\n sources: article.sources.length,\n missingSources,\n weakSources,\n ungrounded,\n lost,\n }\n}\n\n// --- Uncited entries ---\n\n/**\n * Entries absorb read and cited nowhere that carry a commit or link no\n * article on the node has. A successful run marks every entry it read as\n * done (#762), so a fact in an entry the model passed over is gone from\n * the queue for good; the per-article \"lost\" check cannot see it because\n * no article points back at the entry.\n */\nexport function uncitedWithFacts(\n uncited: EvalEntry[],\n allArticles: string,\n): Array<{ entry: string; facts: string[] }> {\n const lower = allArticles.toLowerCase()\n const known = extractFacts(allArticles).commits\n const out: Array<{ entry: string; facts: string[] }> = []\n for (const e of uncited) {\n const f = extractFacts(e.content)\n const missing = [\n ...f.commits.filter((c) => !hasCommit(lower, c, known)).map((c) => `commit ${c}`),\n ...f.urls.filter((u) => !lower.includes(urlKey(u))).map((u) => `link ${u}`),\n ]\n if (missing.length > 0) out.push({ entry: e.id, facts: missing })\n }\n return out\n}\n\n// --- Duplicates ---\n\nexport interface DuplicatePair {\n a: string\n b: string\n reason: \"title\" | \"sources\"\n score: number\n}\n\nconst TITLE_STOP = new Set(\"the and for with from into of on in at to by an a\".split(\" \"))\n\nfunction titleTerms(title: string): Set<string> {\n return new Set(\n (title || \"\").toLowerCase().split(/[^\\p{L}\\p{N}]+/u).filter((w) => (w.length > 1 || /\\d/.test(w)) && !TITLE_STOP.has(w) && !STOP.has(w)),\n )\n}\n\nfunction jaccard<T>(a: Set<T>, b: Set<T>): number {\n if (a.size === 0 || b.size === 0) return 0\n let inter = 0\n for (const x of a) if (b.has(x)) inter++\n return inter / (a.size + b.size - inter)\n}\n\n/**\n * Pairs of articles that look like one subject filed twice: the same type\n * and near-identical title words, or most of their sources in common.\n * Only pairs touching `focus` are returned when it is given.\n */\nexport function findDuplicates(\n catalog: Array<{ path: string; title: string; type?: string; sources?: string[] }>,\n focus?: Set<string>,\n opts: { titleMin?: number; sourcesMin?: number } = {},\n): DuplicatePair[] {\n const titleMin = opts.titleMin ?? 0.75\n const sourcesMin = opts.sourcesMin ?? 0.5\n const rows = catalog.map((a) => ({ ...a, tt: titleTerms(a.title), ss: new Set(a.sources ?? []) }))\n const pairs: DuplicatePair[] = []\n for (let i = 0; i < rows.length; i++) {\n for (let j = i + 1; j < rows.length; j++) {\n const x = rows[i], y = rows[j]\n if (focus && !focus.has(x.path) && !focus.has(y.path)) continue\n const t = (x.type ?? \"\") === (y.type ?? \"\") ? jaccard(x.tt, y.tt) : 0\n if (t >= titleMin) { pairs.push({ a: x.path, b: y.path, reason: \"title\", score: t }); continue }\n if (x.ss.size >= 2 && y.ss.size >= 2) {\n const s = jaccard(x.ss, y.ss)\n if (s >= sourcesMin) pairs.push({ a: x.path, b: y.path, reason: \"sources\", score: s })\n }\n }\n }\n return pairs.sort((p, q) => q.score - p.score || p.a.localeCompare(q.a))\n}\n\n// --- Model judge ---\n\nexport interface JudgeVerdict {\n claims: number\n supported: number\n unsupported: string[]\n contradicted: string[]\n /** Cited entry ids that are about a different subject (a wrong merge). */\n offSubject: string[]\n /** Facts in the entries that belong in this article and are missing. */\n missing: string[]\n verdict: \"good\" | \"minor\" | \"major\"\n}\n\n/** Per-entry cap in the judge prompt, so one long transcript cannot crowd out the rest. */\nexport const JUDGE_ENTRY_CHARS = 4000\n\nexport function buildJudgePrompt(article: EvalArticle, entries: EvalEntry[]): string {\n const sourceBlock = entries\n .map((e) => {\n const body = e.content.length > JUDGE_ENTRY_CHARS ? `${e.content.slice(0, JUDGE_ENTRY_CHARS)}\\n[…cut]` : e.content\n return `--- ENTRY ${e.id} [${e.date ?? \"\"}] ---\\n${body}\\n--- END ENTRY ---`\n })\n .join(\"\\n\\n\")\n const earlier = article.previous\n ? `\\n## Earlier version of the article (facts here count as supported)\\n\\n${article.previous}\\n`\n : \"\"\n return `You are auditing one wiki article against the raw entries it cites. Do not use outside knowledge.\n\n## Article: ${article.title} (${article.type ?? \"untyped\"}, ${article.path})\n\n${article.content}\n${earlier}\n## Cited entries (${entries.length})\n\n${sourceBlock || \"(none)\"}\n\n## What to report\n\n1. Split the article into factual claims (one per sentence or bullet; skip headings and \"unknown\" placeholders). Count them.\n2. A claim is supported when a cited entry or the earlier version states it or plainly implies it. List each claim that is not supported, quoted briefly.\n3. List each claim an entry contradicts.\n4. List the cited entry ids that are about a different subject than the article (they were merged in by mistake).\n5. List facts from the entries that belong in this article and are missing (names, numbers, identifiers, decisions). Ignore small talk.\n6. Verdict: \"good\" (nothing wrong), \"minor\" (wording or a small omission), \"major\" (an unsupported or contradicted fact, a wrong merge, or a lost identifier).\n\nReply with JSON only, no fencing:\n{\"claims\": 0, \"supported\": 0, \"unsupported\": [], \"contradicted\": [], \"off_subject\": [], \"missing\": [], \"verdict\": \"good\"}`\n}\n\nexport function parseJudgeReply(value: unknown): JudgeVerdict | null {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return null\n const v = value as Record<string, unknown>\n const list = (x: unknown) => (Array.isArray(x) ? x.map((s) => String(s)) : [])\n const num = (x: unknown) => (typeof x === \"number\" && Number.isFinite(x) && x >= 0 ? Math.round(x) : NaN)\n const claims = num(v.claims)\n if (Number.isNaN(claims)) return null\n const supported = Math.min(claims, Number.isNaN(num(v.supported)) ? claims - list(v.unsupported).length : num(v.supported))\n const verdict = v.verdict === \"good\" || v.verdict === \"minor\" || v.verdict === \"major\" ? v.verdict : null\n if (!verdict) return null\n return {\n claims,\n supported: Math.max(0, supported),\n unsupported: list(v.unsupported),\n contradicted: list(v.contradicted),\n offSubject: list(v.off_subject ?? v.offSubject),\n missing: list(v.missing),\n verdict,\n }\n}\n\n// --- Scorecard ---\n\nexport interface Scorecard {\n sample: { articles: number; seed: string; since?: string; byType: Record<string, number> }\n citations: { withSources: number; missingSources: number; weakSources: number; articlesWithWeak: number }\n grounding: { articlesWithUngrounded: number; ungroundedFacts: number }\n lost: { entriesWithLostFacts: number; lostFacts: number }\n duplicates: { pairs: number; articlesInPair: number }\n /** Entries read in the window that no article cites. */\n uncited?: { entries: number; withLostFacts: number }\n judge?: {\n judged: number\n claims: number\n supported: number\n supportRate: number\n unsupported: number\n contradicted: number\n articlesWithWrongMerge: number\n missingFacts: number\n verdicts: Record<\"good\" | \"minor\" | \"major\", number>\n }\n examples: {\n ungrounded: Array<{ path: string; facts: string[] }>\n lost: Array<{ path: string; entry: string; fact: string }>\n weak: Array<{ path: string; entries: string[] }>\n duplicates: DuplicatePair[]\n uncited: Array<{ entry: string; facts: string[] }>\n judged: Array<{ path: string; verdict: string; unsupported: string[]; contradicted: string[]; offSubject: string[]; missing: string[] }>\n }\n}\n\nexport function buildScorecard(\n checks: ArticleCheck[],\n duplicates: DuplicatePair[],\n meta: { seed: string; since?: string },\n judged: Array<{ path: string; verdict: JudgeVerdict }> = [],\n maxExamples = 5,\n uncited?: { entries: number; lost: Array<{ entry: string; facts: string[] }> },\n): Scorecard {\n const byType: Record<string, number> = {}\n for (const c of checks) byType[c.type ?? \"untyped\"] = (byType[c.type ?? \"untyped\"] ?? 0) + 1\n const lostEntries = new Set<string>()\n const lostKeys = new Set<string>()\n for (const c of checks) for (const l of c.lost) { lostEntries.add(l.entry); lostKeys.add(`${l.entry}|${l.fact}`) }\n const inPair = new Set(duplicates.flatMap((d) => [d.a, d.b]).filter((p) => checks.some((c) => c.path === p)))\n\n const card: Scorecard = {\n sample: { articles: checks.length, seed: meta.seed, since: meta.since, byType },\n citations: {\n withSources: checks.filter((c) => c.sources > 0).length,\n missingSources: checks.reduce((s, c) => s + c.missingSources.length, 0),\n weakSources: checks.reduce((s, c) => s + c.weakSources.length, 0),\n articlesWithWeak: checks.filter((c) => c.weakSources.length > 0).length,\n },\n grounding: {\n articlesWithUngrounded: checks.filter((c) => c.ungrounded.length > 0).length,\n ungroundedFacts: checks.reduce((s, c) => s + c.ungrounded.length, 0),\n },\n lost: { entriesWithLostFacts: lostEntries.size, lostFacts: lostKeys.size },\n duplicates: { pairs: duplicates.length, articlesInPair: inPair.size },\n ...(uncited ? { uncited: { entries: uncited.entries, withLostFacts: uncited.lost.length } } : {}),\n examples: {\n ungrounded: checks.filter((c) => c.ungrounded.length > 0).slice(0, maxExamples).map((c) => ({ path: c.path, facts: c.ungrounded.slice(0, 6) })),\n lost: checks.flatMap((c) => c.lost.map((l) => ({ path: c.path, ...l }))).slice(0, maxExamples),\n weak: checks.filter((c) => c.weakSources.length > 0).slice(0, maxExamples).map((c) => ({ path: c.path, entries: c.weakSources })),\n duplicates: duplicates.slice(0, maxExamples),\n uncited: (uncited?.lost ?? []).slice(0, maxExamples).map((u) => ({ entry: u.entry, facts: u.facts.slice(0, 4) })),\n judged: judged\n .filter((j) => j.verdict.verdict !== \"good\")\n .slice(0, maxExamples)\n .map((j) => ({\n path: j.path,\n verdict: j.verdict.verdict,\n unsupported: j.verdict.unsupported.slice(0, 4),\n contradicted: j.verdict.contradicted.slice(0, 4),\n offSubject: j.verdict.offSubject,\n missing: j.verdict.missing.slice(0, 4),\n })),\n },\n }\n\n if (judged.length > 0) {\n const v = judged.map((j) => j.verdict)\n const claims = v.reduce((s, x) => s + x.claims, 0)\n const supported = v.reduce((s, x) => s + x.supported, 0)\n card.judge = {\n judged: v.length,\n claims,\n supported,\n supportRate: claims > 0 ? supported / claims : 1,\n unsupported: v.reduce((s, x) => s + x.unsupported.length, 0),\n contradicted: v.reduce((s, x) => s + x.contradicted.length, 0),\n articlesWithWrongMerge: v.filter((x) => x.offSubject.length > 0).length,\n missingFacts: v.reduce((s, x) => s + x.missing.length, 0),\n verdicts: {\n good: v.filter((x) => x.verdict === \"good\").length,\n minor: v.filter((x) => x.verdict === \"minor\").length,\n major: v.filter((x) => x.verdict === \"major\").length,\n },\n }\n }\n return card\n}\n\nconst pct = (n: number, d: number) => (d > 0 ? `${Math.round((n / d) * 100)}%` : \"–\")\n\n/** The scorecard as Markdown, for the issue or a PR comment. */\nexport function renderScorecard(card: Scorecard): string {\n const n = card.sample.articles\n const lines = [\n `# Wiki absorb scorecard`,\n \"\",\n `Sample: ${n} articles (seed \\`${card.sample.seed}\\`${card.sample.since ? `, changed since ${card.sample.since}` : \"\"}). `\n + `Types: ${Object.entries(card.sample.byType).map(([t, k]) => `${t} ${k}`).join(\", \") || \"–\"}.`,\n \"\",\n \"| Check | Result | Lower is better? |\",\n \"|---|---|---|\",\n `| Articles citing at least one entry | ${card.citations.withSources}/${n} (${pct(card.citations.withSources, n)}) | no |`,\n `| Cited ids with no entry | ${card.citations.missingSources} | yes |`,\n `| Articles with a weak citation (entry shares <${Math.round(WEAK_CITATION * 100)}% of its words) | ${card.citations.articlesWithWeak}/${n} (${pct(card.citations.articlesWithWeak, n)}) | yes |`,\n `| Articles with an ungrounded commit, link or number | ${card.grounding.articlesWithUngrounded}/${n} (${pct(card.grounding.articlesWithUngrounded, n)}) | yes |`,\n `| Ungrounded facts | ${card.grounding.ungroundedFacts} | yes |`,\n `| Commits or links lost from cited entries | ${card.lost.lostFacts} across ${card.lost.entriesWithLostFacts} entries | yes |`,\n `| Sampled articles in a likely duplicate pair | ${card.duplicates.articlesInPair}/${n} (${pct(card.duplicates.articlesInPair, n)}) | yes |`,\n ]\n if (card.uncited) {\n lines.push(\n `| Entries read in the window but cited by no article | ${card.uncited.entries} | – |`,\n `| …of which carry a commit or link no article has | ${card.uncited.withLostFacts} | yes |`,\n )\n }\n if (card.judge) {\n const j = card.judge\n lines.push(\n `| Judge: claims supported by the cited entries | ${j.supported}/${j.claims} (${pct(j.supported, j.claims)}) | no |`,\n `| Judge: unsupported / contradicted claims | ${j.unsupported} / ${j.contradicted} | yes |`,\n `| Judge: articles with an off-subject source (wrong merge) | ${j.articlesWithWrongMerge}/${j.judged} (${pct(j.articlesWithWrongMerge, j.judged)}) | yes |`,\n `| Judge: facts missing from the article | ${j.missingFacts} | yes |`,\n `| Judge verdicts good / minor / major | ${j.verdicts.good} / ${j.verdicts.minor} / ${j.verdicts.major} | – |`,\n )\n }\n const ex = card.examples\n const section = (title: string, rows: string[]) => {\n if (rows.length === 0) return\n lines.push(\"\", `## ${title}`, \"\", ...rows)\n }\n section(\"Examples: ungrounded facts\", ex.ungrounded.map((e) => `- \\`${e.path}\\`: ${e.facts.join(\"; \")}`))\n section(\"Examples: lost facts\", ex.lost.map((e) => `- \\`${e.path}\\` ← entry \\`${e.entry}\\`: ${e.fact}`))\n section(\"Examples: weak citations\", ex.weak.map((e) => `- \\`${e.path}\\`: ${e.entries.map((x) => `\\`${x}\\``).join(\", \")}`))\n section(\"Examples: uncited entries with facts no article has\", ex.uncited.map((u) => `- \\`${u.entry}\\`: ${u.facts.join(\"; \")}`))\n section(\"Examples: likely duplicates\", ex.duplicates.map((d) => `- \\`${d.a}\\` ↔ \\`${d.b}\\` (${d.reason}, ${d.score.toFixed(2)})`))\n section(\n \"Examples: judge findings\",\n ex.judged.map((e) => {\n const parts = [\n e.unsupported.length ? `unsupported: ${e.unsupported.join(\" | \")}` : \"\",\n e.contradicted.length ? `contradicted: ${e.contradicted.join(\" | \")}` : \"\",\n e.offSubject.length ? `off-subject: ${e.offSubject.join(\", \")}` : \"\",\n e.missing.length ? `missing: ${e.missing.join(\" | \")}` : \"\",\n ].filter(Boolean)\n return `- \\`${e.path}\\` (${e.verdict}): ${parts.join(\"; \")}`\n }),\n )\n lines.push(\n \"\",\n \"## Method\",\n \"\",\n \"- The sample is drawn with a seeded shuffle from the articles changed in the window, so the same seed and window give the same articles.\",\n \"- Ungrounded: a commit hash, link or number (three digits or more, or a date) in the article that no cited entry and no earlier version of the article contains.\",\n \"- Lost: a commit hash or link in a cited entry that no article citing that entry contains.\",\n \"- Uncited: entries the absorb ledger marks as read in the window that no article cites; those carrying a commit or link that no article on the node has are counted as lost, since absorb will not offer them again.\",\n \"- Weak citation: a cited entry sharing fewer than 15% of its distinctive words with the article.\",\n \"- Duplicate: two articles of the same type whose titles share at least 75% of their words, or which share at least half their sources.\",\n \"- Judge (optional): one model call per article reads the article and its cited entries and lists unsupported, contradicted, off-subject and missing items.\",\n )\n return lines.join(\"\\n\") + \"\\n\"\n}\n\n// --- Run telemetry ---\n\n/** One compile call, as appended to `_absorb-runs.jsonl`. */\nexport interface AbsorbCallRecord {\n kind: \"call\"\n at: string\n label?: string\n agent: string\n model: string\n entries: number\n articles: number\n refused: number\n /** Entries held by a refused save that another saved article cites:\n * they leave the queue, so the refused update is never retried. */\n heldCited?: number\n /** Wiki notes (#831) the call was given, patched, and recorded. */\n notes?: number\n notesPatched?: number\n notesRecorded?: number\n failed: boolean\n /** The model call alone. */\n wallMs: number\n /** Retrieval, fact lookups and prompt building before the call. */\n prepMs?: number\n promptChars: number\n promptParts?: Record<string, number>\n costUsd?: number\n apiMs?: number\n inputTokens?: number\n outputTokens?: number\n cacheReadTokens?: number\n cacheWriteTokens?: number\n}\n\n/** One whole `wiki absorb` invocation. */\nexport interface AbsorbRunRecord {\n kind: \"run\"\n label?: string\n startedAt: string\n endedAt: string\n max: number\n model: string\n /** Compile calls in this run that failed. Absent on runs before #603. */\n failed?: number\n}\n\n/** Cost and timing fields from the claude CLI's `--output-format json` envelope. */\nexport function envelopeUsage(envelope: unknown): Partial<AbsorbCallRecord> {\n if (!envelope || typeof envelope !== \"object\") return {}\n const e = envelope as Record<string, any>\n const u = (e.usage ?? {}) as Record<string, unknown>\n const n = (x: unknown) => (typeof x === \"number\" && Number.isFinite(x) ? x : undefined)\n return {\n costUsd: n(e.total_cost_usd) ?? n(e.cost_usd),\n apiMs: n(e.duration_api_ms),\n inputTokens: n(u.input_tokens),\n outputTokens: n(u.output_tokens),\n cacheReadTokens: n(u.cache_read_input_tokens),\n cacheWriteTokens: n(u.cache_creation_input_tokens),\n }\n}\n\nexport interface RunSummary {\n label: string\n calls: number\n failed: number\n entries: number\n articles: number\n refused: number\n heldCited: number\n /** First call start to last call end, or the run records' span when present. */\n wallMs: number\n callMsP50: number\n callMsP95: number\n /** Time spent before the model calls, summed. */\n prepMs: number\n costUsd: number\n costPerEntry: number\n entriesPerMinute: number\n promptChars: number\n}\n\nfunction percentile(sorted: number[], p: number): number {\n if (sorted.length === 0) return 0\n return sorted[Math.min(sorted.length - 1, Math.floor(p * sorted.length))]\n}\n\n/** Totals per run label from the telemetry lines. Calls without a label group under \"(none)\". */\nexport function summariseRuns(records: Array<AbsorbCallRecord | AbsorbRunRecord>): RunSummary[] {\n const groups = new Map<string, { calls: AbsorbCallRecord[]; runs: AbsorbRunRecord[] }>()\n const group = (label?: string) => {\n const key = label || \"(none)\"\n let g = groups.get(key)\n if (!g) groups.set(key, (g = { calls: [], runs: [] }))\n return g\n }\n for (const r of records) {\n if (r.kind === \"call\") group(r.label).calls.push(r)\n else if (r.kind === \"run\") group(r.label).runs.push(r)\n }\n const out: RunSummary[] = []\n for (const [label, { calls, runs }] of groups) {\n if (calls.length === 0) continue\n const ms = calls.map((c) => c.wallMs).sort((a, b) => a - b)\n let wallMs: number\n if (runs.length > 0) {\n wallMs = runs.reduce((s, r) => s + (Date.parse(r.endedAt) - Date.parse(r.startedAt)), 0)\n } else {\n const starts = calls.map((c) => Date.parse(c.at) - c.wallMs)\n const ends = calls.map((c) => Date.parse(c.at))\n wallMs = Math.max(...ends) - Math.min(...starts)\n }\n const entries = calls.reduce((s, c) => s + c.entries, 0)\n const costUsd = calls.reduce((s, c) => s + (c.costUsd ?? 0), 0)\n out.push({\n label,\n calls: calls.length,\n failed: calls.filter((c) => c.failed).length,\n entries,\n articles: calls.reduce((s, c) => s + c.articles, 0),\n refused: calls.reduce((s, c) => s + c.refused, 0),\n heldCited: calls.reduce((s, c) => s + (c.heldCited ?? 0), 0),\n wallMs,\n callMsP50: percentile(ms, 0.5),\n callMsP95: percentile(ms, 0.95),\n prepMs: calls.reduce((s, c) => s + (c.prepMs ?? 0), 0),\n costUsd,\n costPerEntry: entries > 0 ? costUsd / entries : 0,\n entriesPerMinute: wallMs > 0 ? (entries / wallMs) * 60_000 : 0,\n promptChars: calls.reduce((s, c) => s + c.promptChars, 0),\n })\n }\n return out.sort((a, b) => a.label.localeCompare(b.label))\n}\n"],"mappings":"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","names":["seededRandom","seed","h","i","a","t","pickSample","items","n","rng","pool","b","j","STOP","terms","text","out","m","termOverlap","entry","article","e","hit","WEAK_CITATION","factStrings","f","extractFacts","hasCommit","haystack","commit","known","k","urlKey","u","checkArticle","entries","citersOf","cited","id","missingSources","weakSources","grounding","groundLower","g","groundUrls","groundNumbers","mine","ungrounded","c","lost","facts","carriers","carrierFacts","uncitedWithFacts","uncited","allArticles","lower","missing","TITLE_STOP","titleTerms","title","w","jaccard","inter","x","findDuplicates","catalog","focus","opts","titleMin","sourcesMin","rows","pairs","y","s","p","q","JUDGE_ENTRY_CHARS","buildJudgePrompt","sourceBlock","body","earlier","parseJudgeReply","value","v","list","num","claims","supported","verdict","buildScorecard","checks","duplicates","meta","judged","maxExamples","byType","lostEntries","lostKeys","l","inPair","d","card","pct","renderScorecard","lines","ex","section","parts","envelopeUsage","envelope","percentile","sorted","summariseRuns","records","groups","group","label","key","r","calls","runs","ms","wallMs","starts","ends","costUsd"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as R,b as G,c as K,d as z,e as J}from"./chunk-
|
|
1
|
+
import{a as R,b as G,c as K,d as z,e as J}from"./chunk-YA3P77LV.js";import{a as N,b as I,c as V,d as Y,e as B,j as F}from"./chunk-ERULJ2ZL.js";import{a as H}from"./chunk-JRS5QRZG.js";import{y as T,z as ot}from"./chunk-4XMALK7X.js";import{g as j}from"./chunk-6TURWSMN.js";import{b as E,c as L}from"./chunk-QOYAX2FT.js";import{readFileSync as lt,existsSync as X}from"fs";ot();import{resolve as _}from"path";import{execSync as ct}from"child_process";var ht=.8;function dt(e,r,o,t){if(t.size===0)return 0;let c=e.listArticles(r||"").map(l=>l.path).filter(l=>!l.includes("/_versions/"));return c.length===0&&(c=o.sharedPool.map(l=>l.path)),c.length===0?0:c.filter(l=>t.has(l)).length/c.length}async function Et(e,r,o,t={}){let c=t.selectorModel??"haiku",l=t.synthModel??"sonnet",m=t.maxCandidates??3,g=t.maxHops??2,d=t.maxArticles??8,i=t.timeoutMs??6e4,s=t.log??console.error.bind(console,"[wiki-query]"),h=t.messagePath?.length?t.messagePath:void 0,n=t.graphWeight??W,a=_(r.baseDir,"_index.md"),p=tt(r,o,t.shared),b=t.method??"catalog";if(b!=="catalog"){let u=z(r,t.shared);if(b==="summaries"||dt(r,o,p,u)>=ht){let f=t.summaries??K,P=t.notes&&o&&t.notes.owner===o?G(t.notes):void 0,y=await J(e,P?pt(p,P):p,P?new Map([...u,...P.summaries]):u,{...f,navigatorModel:t.selectorModel??f.navigatorModel,answerModel:t.synthModel??f.answerModel},{call:t.call??H,fetch:t.fetch,timeoutMs:i,log:s}),$=y.picked.map(w=>({title:w.meta.title,path:w.path,type:R(w.path)?"note":w.meta.type,hop:w.hop}));return{answer:y.answer,citations:y.status==="ok"?$.map(({hop:w,...v})=>v):[],candidates:$.filter(w=>w.hop===0).map(({title:w,path:v})=>({title:w,path:v})),walked:$,status:y.status,method:"summaries",basis:y.basis,live:y.live,liveAsked:y.liveAsked,trace:y.trace,...y.error?{error:y.error}:{}}}}if(!X(a)&&p.sharedPool.length===0)return M("no-catalog",e,"No _index.md found \u2014 run `agentx wiki status` to rebuild.");let it=(X(a)?lt(a,"utf-8"):"")+ut(e,p.sharedPool,h,n),U=Date.now(),A=[],S="";try{let u=await nt(e,p.pool,o,m,h,n);u?(A=u,S=`[wiki-rerank seat] ${u.map(f=>f.title).join(" | ")}`):(S=await Z(ft(e,it,m,h),c,i),A=wt(S))}catch(u){return s("selector failed:",u?.message),{...M("error",e,`Selector: ${u?.message||"unknown"}`),trace:{selectorMs:Date.now()-U,synthesisMs:0,selectorOutput:S}}}let x=Date.now()-U;if(A.length===0)return{...M("no-candidates",e,"Selector returned no candidates."),trace:{selectorMs:x,synthesisMs:0,selectorOutput:S}};let C=rt(A,p,g,d);if(C.length===0)return{...M("no-candidates",e,"Candidates did not resolve to readable articles."),candidates:A,trace:{selectorMs:x,synthesisMs:0,selectorOutput:S}};let D=Date.now(),Q="";try{Q=await Z(yt(e,C),l,i*2)}catch(u){return s("synthesis failed:",u?.message),{...M("error",e,`Synthesis: ${u?.message||"unknown"}`),candidates:A,walked:C.map(f=>({title:f.meta.title,path:f.path,type:f.meta.type,hop:f.hop??0})),trace:{selectorMs:x,synthesisMs:Date.now()-D,selectorOutput:S}}}let st=Date.now()-D;return{answer:Q.trim(),citations:C.map(u=>({title:u.meta.title,path:u.path,type:u.meta.type})),candidates:A,walked:C.map(u=>({title:u.meta.title,path:u.path,type:u.meta.type,hop:u.hop??0})),status:"ok",trace:{selectorMs:x,synthesisMs:st,selectorOutput:S}}}async function Lt(e,r,o,t={}){let c=t.maxCandidates??3,l=t.graphWeight??W,m=t.messagePath?.length?t.messagePath:void 0,g=t.pool??q(r);if(g.length===0||!e.trim())return[];let d=await nt(e,g,o,c,m,l,t.stage??"retrieve");if(!d){let i=new Set(L(e,E(g.map(at))).map(s=>s.docIndex));d=O(e,g,m,l).filter(s=>i.has(s)).slice(0,c).map(s=>({title:g[s].title,path:g[s].path}))}return d.length===0?[]:rt(d,tt(r,o),t.maxHops??1,t.maxArticles??6)}function q(e){try{return(e.rebuildIndex().articles??[]).filter(r=>r.path&&!r.path.includes("/_versions/"))}catch{return[]}}function M(e,r,o){return{answer:"",citations:[],candidates:[],walked:[],status:e,error:o}}function tt(e,r,o=[]){let t=new Map,c=[];for(let i of e.listArticles(r||""))t.set(i.meta.title.toLowerCase(),i.path),c.push({path:i.path,related:i.meta.related??[],lastUpdated:i.meta.lastUpdated??""});let l=[],m=new Map;for(let i of o)if(i.store.baseDir!==e.baseDir){m.set(i.id,i);for(let s of i.store.listArticles(r||"")){if(s.path.includes("/_versions/")||i.skip?.(s.path))continue;let h=`@${i.id}/${s.path}`;l.push(mt(s,h)),c.push({path:h,related:s.meta.related??[],lastUpdated:s.meta.lastUpdated??""});let n=s.meta.title.toLowerCase();t.has(n)||t.set(n,h)}}let g=new Map;if(m.size>0)for(let i of[...c].sort((s,h)=>h.lastUpdated.localeCompare(s.lastUpdated)))for(let s of i.related){let h=s.toLowerCase(),n=g.get(h)??[];n.includes(i.path)||n.push(i.path),g.set(h,n)}let d;return{backlinks:g,readable:new Set(c.map(i=>i.path)),get pool(){return d??=[...q(e),...l]},sharedPool:l,titleIndex:t,read(i){let s=i.match(/^@([^/]+)\/(.+)$/),h=s?m.get(s[1]):void 0;if(s&&!h)return null;let n=h?.store??e,a=s?s[2]:i,p=r?n.readArticleAs(a,r):n.readArticle(a);return p?{...p,path:i}:null},links(i){let s=(i.meta.related??[]).map(a=>t.get(a.toLowerCase())).filter(a=>!!a),h=[i.meta.title,...i.meta.aliases??[]].map(a=>a.toLowerCase()),n=[...new Set(h.flatMap(a=>g.get(a)??[]))].filter(a=>a!==i.path).slice(0,et);return[...new Set([...s,...n])].filter(a=>a!==i.path)}}}function pt(e,r){return{...e,pool:[...e.pool,...r.pool],readable:new Set([...e.readable,...r.pool.map(o=>o.path)]),read:o=>R(o)?r.read(o):e.read(o)}}function mt(e,r){return{path:r,title:e.meta.title,type:e.meta.type,related:e.meta.related,tags:e.meta.tags||[],owner:e.meta.owner,access:e.meta.access,sharedWith:e.meta.sharedWith,aliases:[e.meta.title.toLowerCase(),...(e.meta.aliases??[]).map(o=>o.toLowerCase())],backlinks:0,sources:e.meta.sources,lastUpdated:e.meta.lastUpdated,graphPath:e.meta.graphPath}}var gt=150;function ut(e,r,o,t){return r.length===0?"":`
|
|
2
2
|
|
|
3
3
|
## Shared wiki (other agents' articles)
|
|
4
4
|
|
|
@@ -52,4 +52,4 @@ ${o}
|
|
|
52
52
|
Answer the question in 2\u20136 sentences. Cite articles by their title in square brackets like [Article Title]. When two articles disagree, prefer the one updated more recently, and say which agent's page and date the answer comes from. If the articles do not answer the question, say so plainly (do not invent). Prefer concrete facts over hedging.
|
|
53
53
|
|
|
54
54
|
Output ONLY the answer \u2014 no preamble, no "here is my answer:", no markdown fencing.`}function wt(e){let r=e.match(/\[[\s\S]*?\]/);if(!r)return[];try{let o=JSON.parse(r[0]);return Array.isArray(o)?o.filter(t=>t&&typeof t.title=="string"&&typeof t.path=="string").map(t=>({title:t.title,path:t.path})):[]}catch{return[]}}async function Z(e,r,o){let{writeFileSync:t,mkdirSync:c,rmSync:l}=await import("fs"),{tmpdir:m}=await import("os"),g=_(m(),`agentx-wiki-query-${process.pid}`);c(g,{recursive:!0});let d=_(g,`prompt-${Date.now()}.txt`);t(d,e);try{let i=`cat '${d}' | claude -p - --output-format json --max-turns 1 --model ${r} --disallowedTools "Bash Read Write Edit Glob Grep Agent WebSearch WebFetch NotebookEdit"`,s=ct(i,{env:j(),encoding:"utf-8",timeout:o,maxBuffer:4*1024*1024});try{let h=JSON.parse(s);return String(h.result||h.content||"")}catch{return s}}finally{try{l(d,{force:!0})}catch{}}}async function Rt(e){try{let{loadDaemonConfig:r}=await import("./config-GHMRBRDL.js");return r(e).wiki.query.shared}catch{return!0}}export{ht as a,Et as b,Lt as c,q as d,gt as e,W as f,O as g,Rt as h};
|
|
55
|
-
//# sourceMappingURL=chunk-
|
|
55
|
+
//# sourceMappingURL=chunk-WWDYDLY2.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{c as L}from"./chunk-JRS5QRZG.js";import{a as H}from"./chunk-4LWFJ4MZ.js";import{c as N}from"./chunk-BIJHMWXK.js";import{b as J}from"./chunk-QD6IICK7.js";var X="note:",v=e=>e.startsWith(X);function Ne(e){let t=new Set(e.types),s=new Map;for(let o of H(e.dir).notes)!o.type||!t.has(o.type)||!o.description&&!o.body||J(`${o.description}
|
|
2
2
|
${o.body}`)||s.set(`${X}${o.file}`,o);let n=[],i=new Map;for(let[o,r]of s)n.push({path:o,title:r.name,type:"note",tags:[r.type],owner:e.owner,lastUpdated:r.checked}),i.set(o,r.description||r.body.split(`
|
|
3
3
|
`)[0]);return{pool:n,summaries:i,read(o){let r=s.get(o);return r?ie(o,r,e.owner):null}}}function ie(e,t,s){let n=t.checked?`Checked: ${t.checked}`:"Checked: not recorded",i=t.source?`Source: ${t.source}`:"Source: not recorded",o=t.checked??t.updated?.slice(0,10)??"";return{path:e,content:`${i}
|
|
4
4
|
${n}
|
|
@@ -84,4 +84,4 @@ Question: ${e}
|
|
|
84
84
|
${t.map(n=>`- ${n.line}`).join(`
|
|
85
85
|
`)}
|
|
86
86
|
`}async function Qe(e,t,s,n,i){let o={selectorMs:0,planMs:0,liveMs:0,synthesisMs:0,selectorOutput:""},r=(u,y)=>({status:u,basis:"pages",answer:"",picked:[],live:[],liveAsked:0,error:y,trace:o}),a=()=>`${(i.now?.()??new Date).toISOString().slice(0,16).replace("T"," ")} UTC`,c=async u=>{if(!ee(n.live))return r("no-candidates",u);let y=[],x=0;try{let w=Date.now(),C=await te(e,n.live,i.call,i.timeoutMs);if(o.planMs=Date.now()-w,x=C.length,C.length===0)return r("no-candidates",u);w=Date.now(),y=await q(C,n.live,i.fetch),o.liveMs=Date.now()-w}catch(w){return i.log("source search failed:",w?.message),r("no-candidates",u)}let P=y.filter(w=>!w.line.endsWith(W));if(P.length===0)return{...r("no-candidates",`${u} The source search found no issue.`),live:y,liveAsked:x};let B=Date.now();try{let w=await i.call(Me(e,P,a()),n.answerModel,i.timeoutMs*2);return o.synthesisMs=Date.now()-B,{status:"ok",basis:"search",answer:w.trim(),picked:[],live:P,liveAsked:x,trace:o}}catch(w){return o.synthesisMs=Date.now()-B,i.log("answer failed:",w?.message),{status:"error",basis:"search",answer:"",picked:[],live:P,liveAsked:x,error:`Synthesis: ${w?.message||"unknown"}`,trace:o}}},d=t.pool.filter(u=>t.readable.has(u.path)),g=d.filter(u=>!u.path.startsWith("@")&&!v(u.path)),m=d.filter(u=>u.path.startsWith("@")),l=d.filter(u=>v(u.path)),h=[...M(e,g,s,n.candidates).map(u=>g[u]),...M(e,l,s,n.noteCandidates).map(u=>l[u]),...M(e,m,s,n.sharedCandidates).map(u=>m[u])];if(h.length===0)return c("No page shares a word with the question.");let p=Date.now(),R;try{o.selectorOutput=await i.call(Le(e,h,s,n.maxPages),n.navigatorModel,i.timeoutMs),R=Ae(o.selectorOutput,h.length,n.maxPages)}catch(u){return i.log("navigator failed:",u?.message),r("error",`Selector: ${u?.message||"unknown"}`)}finally{o.selectorMs=Date.now()-p}let $=[];for(let u of R){let y=t.read(h[u].path);y&&$.push({...y,hop:0})}if($.length===0)return c("No page was picked for the question.");let V=xe(e,$,t,s,n),Y=Pe([...$,...V],s,n.pageChars);$.push(...V.map(({chars:u,...y})=>y));let A=[],E=0;if(U(n.live))try{p=Date.now();let u=await ne(e,Y,n.live,i.call,i.timeoutMs);o.planMs=Date.now()-p,E=u.length,p=Date.now(),A=await q(u,n.live,i.fetch),o.liveMs=Date.now()-p}catch(u){i.log("live read failed:",u?.message)}p=Date.now();try{let u=await i.call(_e(e,Y,A,a(),$.some(y=>v(y.path))),n.answerModel,i.timeoutMs*2);return o.synthesisMs=Date.now()-p,{status:"ok",basis:"pages",answer:u.trim(),picked:$,live:A,liveAsked:E,trace:o}}catch(u){return o.synthesisMs=Date.now()-p,i.log("answer failed:",u?.message),{status:"error",basis:"pages",answer:"",picked:$,live:A,liveAsked:E,error:`Synthesis: ${u?.message||"unknown"}`,trace:o}}}export{v as a,Ne as b,Ie as c,Fe as d,Qe as e};
|
|
87
|
-
//# sourceMappingURL=chunk-
|
|
87
|
+
//# sourceMappingURL=chunk-YA3P77LV.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as g}from"./chunk-
|
|
1
|
+
import{c as g}from"./chunk-WWDYDLY2.js";async function $(e,i,r,n,o={}){let a=o.retrieve??g,c=o.perEntry??2,s=o.maxArticles??8,f=o.queryChars??1500,h=new Map;for(let t of e){let l=[];try{l=await a(t.content.slice(0,f),i,r,{pool:n,maxCandidates:c,maxHops:1,maxArticles:c*2,stage:"absorb-covering"})}catch{}for(let u of l){let p=h.get(u.path);p?(p.hop=Math.min(p.hop,u.hop),p.entries.includes(t.id)||p.entries.push(t.id)):h.set(u.path,{...u,entries:[t.id]})}}return[...h.values()].sort((t,l)=>t.hop-l.hop||l.entries.length-t.entries.length||t.path.localeCompare(l.path)).slice(0,s)}function x(e){if(e.length===0)return"";let i=e.map(r=>{let n=`### ${r.meta.title} \u2014 ${r.meta.type||"untyped"} (${r.path})`,o=`Found for entries: ${r.entries.join(", ")}${r.hop>0?" (linked from a match)":""}`,a=r.meta.related?.length?`Related: ${r.meta.related.join(", ")}`:"";return[n,o,a,"",r.content].filter(c=>c!=="").join(`
|
|
2
2
|
`)}).join(`
|
|
3
3
|
|
|
4
4
|
---
|
|
@@ -14,4 +14,4 @@ These ${e.length} articles were found by searching the wiki for each entry below
|
|
|
14
14
|
|
|
15
15
|
${i}
|
|
16
16
|
`}var d=/\bhttps?:\/\/[^\s<>"'`)\]]+/gi,y=/\[\[([^\]|]+)(?:\|[^\]]*)?\]\]/g,w=/(?<![\w-])(?=[0-9a-f]*[0-9])(?=[0-9a-f]*[a-f])[0-9a-f]{7,40}(?![\w-])/gi,k=/(?<![\w.,:/-])\d+(?:[.,:\-/]\d+)*(?![\w])/g,C=/^\s*\d+[.)]\s/gm;function A(e){let i=[...e.matchAll(d)].map(s=>s[0].replace(/[.,;:!?'"]+$/,"")),r=[...e.matchAll(y)].map(s=>s[1].trim()),n=e.replace(d," ").replace(y," ").replace(C," "),o=[...n.matchAll(w)].map(s=>s[0].toLowerCase()),c=[...n.replace(w," ").matchAll(k)].map(s=>v(s[0]));return{commits:m(o),urls:m(i),wikilinks:m(r),numbers:m(c)}}function R(e,i){let r=A(e),n=A(i),o=i.toLowerCase(),a=[];for(let t of r.commits)!o.includes(t)&&!n.commits.some(l=>l.startsWith(t)||t.startsWith(l))&&a.push(`commit ${t}`);let c=t=>t.toLowerCase().replace(/\/+$/,""),s=new Set(n.urls.map(c));for(let t of r.urls)s.has(c(t))||a.push(`link ${t}`);let f=new Set(n.wikilinks.map(t=>t.toLowerCase()));for(let t of r.wikilinks)f.has(t.toLowerCase())||a.push(`link [[${t}]]`);let h=new Set(n.numbers);for(let t of r.numbers)h.has(t)||a.push(`number ${t}`);return a}function v(e){return/^\d{1,3}(,\d{3})+$/.test(e)?e.replace(/,/g,""):e}function m(e){return[...new Set(e)]}function L(e,i){if(i.some(n=>n.path===e.path))return e.path;let r=b(e.title);return r?i.find(n=>b(n.title)===r)?.path??e.path:e.path}function b(e){return(e||"").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").trim()}export{$ as a,x as b,A as c,R as d,L as e};
|
|
17
|
-
//# sourceMappingURL=chunk-
|
|
17
|
+
//# sourceMappingURL=chunk-ZFRXFUP7.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as Re}from"./chunk-GTJIKXDB.js";import{q as Kt}from"./chunk-S2GAEH2F.js";import{a as w}from"./chunk-7LN4VKDU.js";import{a as ne}from"./chunk-IMLAPB7G.js";import{b as Jt}from"./chunk-WCXXXAHV.js";import{f as Yt,g as Ae,i as V,j as q,l as Zt}from"./chunk-AKLZ4YO2.js";import{t as Xt,u as Gt}from"./chunk-
|
|
1
|
+
import{a as Re}from"./chunk-GTJIKXDB.js";import{q as Kt}from"./chunk-S2GAEH2F.js";import{a as w}from"./chunk-7LN4VKDU.js";import{a as ne}from"./chunk-IMLAPB7G.js";import{b as Jt}from"./chunk-WCXXXAHV.js";import{f as Yt,g as Ae,i as V,j as q,l as Zt}from"./chunk-AKLZ4YO2.js";import{t as Xt,u as Gt}from"./chunk-5NT44FKL.js";import{d as Ht,e as zt}from"./chunk-AQASR6KR.js";import{X as Nt,Z as te,_ as ve,aa as $e,b as Se}from"./chunk-QDWEM4DG.js";import{a as Vt,b as qt,d as Bt}from"./chunk-Y4CYQV7G.js";import{a as Lt,b as Ot}from"./chunk-SHEUCITK.js";import{g as Mt,h as jt,i as Wt,k as Ft,l as Ut}from"./chunk-FWDRBUMS.js";import{q as Pt}from"./chunk-SSQMFHSM.js";import{a as Ct,b as Dt}from"./chunk-LUYN6RAC.js";import{A as Rt,B as _t,ha as xe,n as ee,o as St,oa as It,p as vt,pa as Et,q as Jr,xa as Tt,y as $t,z as At}from"./chunk-DYGQF3MI.js";import{a as we,h as Yr}from"./chunk-BRK6M6LA.js";import{f as ke,n as Zr}from"./chunk-UIBUZ2N3.js";import{existsSync as Qr,readdirSync as ei,readFileSync as ti,statSync as ni}from"fs";import{resolve as ri}from"path";function Qt(t,e,n=Date.now(),i=7){let r=i*864e5,s=new Map;for(let o of e){let a=s.get(o.workflowId);a?a.push(o):s.set(o.workflowId,[o])}return t.map(o=>{let a=s.get(o.id)??[],l=a.filter(f=>n-f.at<=r),c=a.filter(f=>n-f.at>r&&n-f.at<=r*2),u=l.filter(f=>f.status==="failed").length,d=a.filter(f=>f.status==="paused").length,p=a.length?Math.max(...a.map(f=>f.at)):null,g=a.length?c.length>0&&l.length===0?"dormant":l.length>0&&u*2>=l.length?"failing":l.length>0?"active":"quiet":"never";return{id:o.id,name:o.name||o.id,state:g,lastRunAt:p,recent:l.length,prior:c.length,failed:u,paused:d}}).sort((o,a)=>{let l={dormant:0,failing:1,active:2,quiet:3,never:4};return l[o.state]-l[a.state]||(a.lastRunAt??0)-(o.lastRunAt??0)})}var re=new Map;function Ea(t,e=1e3){if(!Qr(t))return[];let n=ei(t).filter(s=>s.endsWith(".jsonl")).map(s=>{let o=ri(t,s);return{path:o,mtime:ni(o).mtimeMs}}).sort((s,o)=>o.mtime-s.mtime).slice(0,e),i=new Set(n.map(s=>s.path));for(let s of re.keys())i.has(s)||re.delete(s);let r=[];for(let{path:s,mtime:o}of n){let a=re.get(s);if(a&&a.mtime===o){a.summary&&r.push(a.summary);continue}let l=ii(s,o);re.set(s,{mtime:o,summary:l}),l&&r.push(l)}return r}function ii(t,e){try{let n=ti(t,"utf-8").split(`
|
|
2
2
|
`).filter(Boolean);if(!n.length)return null;let i=JSON.parse(n[0]),r=i.run?.workflowId;if(!r)return null;let s=i.run?.status??"unknown";for(let o=n.length-1;o>=0;o--){let a=JSON.parse(n[o]),l=a.status??a.run?.status;if(l){s=l;break}}return{workflowId:r,status:s,at:e}}catch{return null}}var si={failStreak:3,disabledDays:30,missedFires:2,graceMs:15*6e4},k={routines:200,summary:160,filters:6,filterValue:60,text:120},oi=(t,e,n)=>{try{return Pt(t,e,n)}catch{return null}},en=864e5;function Pa(t){let e=t.now??Date.now(),n={...si,...t.thresholds},i=t.nextFire??oi,r=[];for(let a of t.crons){let l=t.cronRuns.get(a.id)??[],c=a.timezone||"UTC",u=l.map(g=>({at:Date.parse(g.startedAt),status:g.status})),d=l[0],p={id:`cron:${a.id}`,source:"cron",kind:"schedule",name:$(a.id,k.text),trigger:{schedule:$(a.schedule,k.text),timezone:c},agent:a.agent||null,enabled:a.enabled,state:a.enabled?"enabled":"disabled",nextRunAt:a.enabled?_e(a.nextRun)??_e(i(a.schedule,new Date(e),c)):null,lastRun:d?{at:d.startedAt,status:d.status,summary:pi(d.status==="success"?void 0:d.errorSummary,k.summary)}:null,lastSuccessAt:l.find(g=>g.status==="success")?.startedAt??null,consecutiveFailures:tn(u),sampledRuns:l.length,flags:[],attention:null};p.flags=nn(p,u,a.schedule,c,null,e,n,i),r.push(rn(p))}let s=new Map(Qt(t.workflows.map(a=>({id:a.id,name:a.title})),t.workflowRuns,e).map(a=>[a.id,a])),o=new Map;for(let a of t.workflowRuns){let l=o.get(a.workflowId);l?l.push(a):o.set(a.workflowId,[a])}for(let a of t.workflows){let l=a.nodes.find(I=>I.type.startsWith("trigger."));if(!l||l.type!=="trigger.cron"&&l.type!=="trigger.hook")continue;let c=l.config??{},u=a.state||"active",d=u==="active",p=(o.get(a.id)??[]).slice().sort((I,ye)=>ye.at-I.at),g=p.map(I=>({at:I.at,status:ci(I.status)})),f=g[0],h=l.type==="trigger.cron",b=typeof c.spec=="string"?c.spec:"",C=typeof c.timezone=="string"?c.timezone:"UTC",M={id:`workflow:${a.id}`,source:"workflow",kind:h?"schedule":"event",name:$(a.title||a.id,k.text),trigger:h?{schedule:$(b,k.text),timezone:C}:{event:$(typeof c.event=="string"?c.event:"",k.text),filters:di(c.filter,a)},agent:ui(a),enabled:d,state:u,nextRunAt:h&&d&&b?_e(i(b,new Date(e),C)):null,lastRun:f?{at:new Date(f.at).toISOString(),status:f.status}:null,lastSuccessAt:(()=>{let I=g.find(ye=>ye.status==="success");return I?new Date(I.at).toISOString():null})(),consecutiveFailures:tn(g),sampledRuns:p.length,flags:[],attention:null},Q=Date.parse(a.updated||a.created||"");M.flags=h?nn(M,g,b,C,Number.isFinite(Q)?Q:null,e,n,i):ai(M,s.get(a.id)?.state==="dormant",Number.isFinite(Q)?Q:null,e,n),r.push(rn(M))}return r.sort(li).slice(0,k.routines)}function tn(t){let e=0;for(let n of t)if(!(n.status==="running"||n.status==="paused"||n.status==="unknown"))if(n.status==="failed"||n.status==="timeout")e++;else break;return e}function nn(t,e,n,i,r,s,o,a){let l=[],c=e.length?e[0].at:null;if(!t.enabled){let p=on(c,r,s,o);return p&&l.push(p),l}if(t.consecutiveFailures>=o.failStreak&&l.push({reason:"failing",detail:`${t.consecutiveFailures} failed attempts in a row`}),c===null)return l.push({reason:"never-ran",detail:"No persisted attempt"}),l;let u=new Date(c),d=null;for(let p=0;p<o.missedFires&&(d=a(n,u,i),!!d);p++)u=d;return d&&s>d.getTime()+o.graceMs&&l.push({reason:"overdue",detail:`No attempt since ${new Date(c).toISOString()}; ${o.missedFires} scheduled fires missed`}),l}function ai(t,e,n,i,r){let s=[],o=t.lastRun?Date.parse(t.lastRun.at):null;if(!t.enabled){let a=on(o,n,i,r);return a&&s.push(a),s}return t.consecutiveFailures>=r.failStreak&&s.push({reason:"failing",detail:`${t.consecutiveFailures} failed runs in a row`}),o===null?s.push({reason:"never-ran",detail:"No run recorded for this trigger"}):e&&s.push({reason:"dormant",detail:"Fired in the prior week, silent in the last one"}),s}function on(t,e,n,i){let r=Math.max(t??0,e??0);return r&&n-r<i.disabledDays*en?null:{reason:"disabled-long",detail:r?`Disabled; no activity for ${Math.floor((n-r)/en)} days`:"Disabled and never ran"}}function rn(t){let e=new Set(t.flags.map(n=>n.reason));return t.attention=e.has("failing")?"critical":e.has("overdue")||e.has("dormant")||e.has("never-ran")?"warning":e.has("disabled-long")?"info":null,t}var sn={critical:0,warning:1,info:2};function li(t,e){let n=t.attention?sn[t.attention]:3,i=e.attention?sn[e.attention]:3;return n-i||Number(e.enabled)-Number(t.enabled)||t.name.localeCompare(e.name)}function ci(t){switch(t){case"completed":case"ok":return"success";case"failed":return"failed";case"timeout":return"timeout";case"canceled":return"canceled";case"running":return"running";case"paused":return"paused";default:return"unknown"}}function ui(t){if(t.ownerAgent)return $(t.ownerAgent,k.text);let e=t.nodes.find(n=>n.type==="agent"&&typeof n.config?.agentId=="string"&&n.config.agentId);return e?$(String(e.config.agentId),k.text):null}function di(t,e){let n=[],i=e?.project;if(i&&n.push($(`project=${i}`,k.filterValue)),t&&typeof t=="object"&&!Array.isArray(t))for(let[r,s]of Object.entries(t)){let o=Array.isArray(s)?s.map(String):s==null?[]:[String(s)];o.length&&n.push($(`${r}=${o.join(",")}`,k.filterValue))}return n.slice(0,k.filters)}function _e(t){if(!t)return null;let e=t instanceof Date?t:new Date(t);return Number.isFinite(e.getTime())?e.toISOString():null}function $(t,e){return t.length<=e?t:t.slice(0,e-3)+"..."}function pi(t,e){return t===void 0?void 0:$(t,e)}import{existsSync as H,readdirSync as Pi,readFileSync as Ni}from"fs";import{resolve as R}from"path";import{randomBytes as cn}from"crypto";import{existsSync as fi,mkdirSync as mi,readdirSync as hi,readFileSync as bi,renameSync as un,unlinkSync as yi,writeFileSync as wi}from"fs";import{resolve as dn}from"path";function an(t){return[...t.account?["--account",t.account]:[],...t.store?["--store",t.store]:[]]}var gi=t=>t.trim().split(`
|
|
3
3
|
`).pop()?.slice(0,300)||"no output";async function ln(t,e,n,i=Re){let r=await i(t.bin,[...an(t),"send","text","--to",e,"--message",n,"--no-preview"],{timeoutMs:6e4});return r.code===0?{ok:!0}:{ok:!1,error:`wacli send failed: ${gi(r.stderr||r.stdout)}`}}async function Oa(t,e,n,i,r=Re){return(await r(t.bin,[...an(t),"--read-only","media","download","--chat",e,"--id",n,"--output",i],{timeoutMs:12e4})).code===0}var ki=2e3,xi=t=>ln(t.wacli,t.to,t.text);function Ie(t){return dn(t,".agentx","whatsapp-triage","drafts")}var Si=t=>/^[a-z0-9-]{8,64}$/.test(t),ie=(t,e)=>dn(Ie(t),`${e}.json`);function pn(t,e){mi(Ie(t),{recursive:!0});let n=ie(t,e.id),i=`${n}.${process.pid}.tmp`;wi(i,JSON.stringify(e,null,2)+`
|
|
4
4
|
`,{mode:384}),un(i,n)}function Va(t,e,n=Date.now()){let i=e.text.trim().slice(0,ki);if(!i)throw new Error("empty draft");let r={...e,text:i,id:`${n.toString(36)}-${cn(4).toString("hex")}`,status:"pending",created_at:new Date(n).toISOString()};return pn(t,r),r}function se(t,e){if(!Si(e))return null;try{return JSON.parse(bi(ie(t,e),"utf-8"))}catch{return null}}function gn(t,e){let n=Ie(t);return fi(n)?hi(n).filter(i=>i.endsWith(".json")).map(i=>se(t,i.slice(0,-5))).filter(i=>!!i&&(!e||i.status===e)).sort((i,r)=>i.created_at.localeCompare(r.created_at)):[]}async function fn(t,e,n,i={}){let r=se(t,e);if(!r||r.status!=="pending")return{ok:!1,error:`no reply draft "${e}" is waiting`};let s=`${ie(t,e)}.${process.pid}.${cn(3).toString("hex")}.claim`;try{un(ie(t,e),s)}catch{return{ok:!1,error:`reply draft "${e}" is already being decided`}}let o={...r,decided_by:i.by??"operator",decided_at:new Date(i.now??Date.now()).toISOString()};if(n==="no")o.status="rejected";else{let a=await(i.send??xi)(r).catch(l=>({ok:!1,error:String(l?.message??l)}));a.ok?o.status="sent":(o.status="failed",o.error=a.error)}pn(t,o);try{yi(s)}catch{}return o.status==="failed"?{ok:!1,error:o.error??"send failed"}:{ok:!0,draft:o}}import{mkdirSync as vi,readFileSync as $i,renameSync as Ai,writeFileSync as Ri}from"fs";import{resolve as _i}from"path";function mn(t){return _i(Ae(t),"_state.json")}function A(t){try{let e=JSON.parse($i(mn(t),"utf-8"));return{snoozed:e&&typeof e.snoozed=="object"&&e.snoozed?e.snoozed:{},...typeof e?.lastDigest=="string"?{lastDigest:e.lastDigest}:{},...e?.popped&&typeof e.popped=="object"?{popped:e.popped}:{},...typeof e?.passAt=="string"?{passAt:e.passAt}:{},...Array.isArray(e?.wanted)?{wanted:e.wanted.filter(n=>typeof n=="string")}:{}}}catch{return{snoozed:{}}}}function B(t,e){vi(Ae(t),{recursive:!0});let n=mn(t),i=`${n}.${process.pid}.tmp`;Ri(i,JSON.stringify(e,null,2)+`
|
|
@@ -529,4 +529,4 @@ Document the arguments, commands, or files the skill expects. Example:
|
|
|
529
529
|
claude-code ${xt(t)} --arg value
|
|
530
530
|
\`\`\`
|
|
531
531
|
`}Tt();var zr={maxPixels:12e5,timeoutMs:5e3,intervalMs:100,changeThreshold:.015,stableMs:400,regions:{},buffer:{enabled:!1,seconds:10,fps:2,region:"screen",maxPixels:3e5}};function Xr(t){return{...zr,...t??{},regions:{...t?.regions??{}},buffer:{...zr.buffer,...t?.buffer??{}}}}function td(t){try{return Xr(Et(t).screen)}catch{return Xr(void 0)}}var Ra=/^[a-z][\w-]*$/,Gr=["window","screen","menubar","notifications"];function Z(t,e,n,i){let r=Number(t);if(t===""||t===null||!Number.isFinite(r)||!n(r))throw new Error(`${e} must be ${i}`);return r}var be=(t,e)=>Z(t,e,n=>Number.isInteger(n)&&n>0,"a whole number above 0");function Kr(t){let e=typeof t=="string"?t.split(",").map(Number):[t?.x,t?.y,t?.width,t?.height].map(Number);if(e.length!==4||!e.every(Number.isFinite)||e[2]<=0||e[3]<=0)throw new Error("a region is x,y,width,height in screen points, with width and height above 0");return{x:e[0],y:e[1],width:e[2],height:e[3]}}function nd(t,e){let n={...t??{}};if("maxPixels"in e&&(n.maxPixels=be(e.maxPixels,"maxPixels")),"timeoutMs"in e&&(n.timeoutMs=be(e.timeoutMs,"timeoutMs")),"intervalMs"in e&&(n.intervalMs=be(e.intervalMs,"intervalMs")),"stableMs"in e&&(n.stableMs=Z(e.stableMs,"stableMs",r=>Number.isInteger(r)&&r>=0,"a whole number, 0 or more")),"changeThreshold"in e&&(n.changeThreshold=Z(e.changeThreshold,"changeThreshold",r=>r>=0&&r<=1,"between 0 and 1")),e.regions&&typeof e.regions=="object"){let r={...n.regions??{}};for(let[s,o]of Object.entries(e.regions)){if(!Ra.test(s))throw new Error(`region name "${s}" must be lowercase letters, digits, - or _`);o===null?delete r[s]:r[s]=Kr(o)}n.regions=r}if(e.buffer&&typeof e.buffer=="object"){let r=e.buffer,s={...n.buffer??{}};"enabled"in r&&(s.enabled=!!r.enabled),"seconds"in r&&(s.seconds=Z(r.seconds,"buffer.seconds",o=>o>0&&o<=120,"above 0 and at most 120")),"fps"in r&&(s.fps=Z(r.fps,"buffer.fps",o=>o>0&&o<=10,"above 0 and at most 10")),"maxPixels"in r&&(s.maxPixels=be(r.maxPixels,"buffer.maxPixels")),"region"in r&&(s.region=String(r.region).trim()),n.buffer=s}let i=n.buffer?.region;if(i!==void 0&&!Gr.includes(i)&&!n.regions?.[i])try{Kr(i)}catch{throw new Error(`buffer.region "${i}" is not a region \u2014 use ${[...Gr,...Object.keys(n.regions??{})].join(", ")}, or x,y,w,h`)}return n}export{Qt as a,Ea as b,tt as c,Ks as d,Js as e,mc as f,hc as g,bc as h,ar as i,wc as j,xc as k,D as l,lr as m,k as n,Pa as o,Oa as p,xi as q,Va as r,fn as s,A as t,Xa as u,Ga as v,Ya as w,oe as x,Za as y,xn as z,il as A,z as B,wl as C,kl as D,_n as E,cr as F,$c as G,_c as H,vr as I,eu as J,tu as K,au as L,qo as M,lu as N,Sl as O,vl as P,$l as Q,Al as R,Rl as S,_l as T,El as U,Tl as V,Wl as W,Me as X,Fl as Y,Ul as Z,X as _,G as $,Ko as aa,bu as ba,yu as ca,wu as da,ku as ea,ct as fa,xu as ga,Fe as ha,Ue as ia,pe as ja,ms as ka,bs as la,zl as ma,qe as na,Be as oa,ys as pa,ws as qa,Xn as ra,Yn as sa,Xl as ta,Ss as ua,Gl as va,Ts as wa,Ps as xa,He as ya,Ls as za,Zn as Aa,P as Ba,Lr as Ca,Or as Da,Mr as Ea,_u as Fa,ia as Ga,Wr as Ha,Fr as Ia,ju as Ja,Wu as Ka,ka as La,Fu as Ma,Vr as Na,ge as Oa,oc as Pa,ir as Qa,ze as Ra,Qe as Sa,gc as Ta,Bu as Ua,Hu as Va,zu as Wa,Xu as Xa,Gu as Ya,Ku as Za,Ju as _a,Yu as $a,Zu as ab,zr as bb,Xr as cb,td as db,Gr as eb,nd as fb};
|
|
532
|
-
//# sourceMappingURL=chunk-
|
|
532
|
+
//# sourceMappingURL=chunk-ZGVVYJIK.js.map
|
package/dist/cli.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{b as o}from"./chunk-JXF54PT7.js";import"./chunk-QIJLFPWE.js";var s=o(process.versions.node);s&&(console.error(s),process.exit(1));var{buildProgram:r}=await import("./program-
|
|
2
|
+
import{b as o}from"./chunk-JXF54PT7.js";import"./chunk-QIJLFPWE.js";var s=o(process.versions.node);s&&(console.error(s),process.exit(1));var{buildProgram:r}=await import("./program-U3HJY7E5.js"),{installCliSignalExit:i}=await import("./signal-exit-WL7G3EEZ.js");i();var e=await r();process.argv.slice(2).length===0?e.outputHelp():e.parse();
|
|
3
3
|
//# sourceMappingURL=cli.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as ee}from"./chunk-
|
|
1
|
+
import{a as ee}from"./chunk-LU7GDHGD.js";import"./chunk-ZFRXFUP7.js";import{f as Q,k as V}from"./chunk-QSKG754X.js";import{c as O}from"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import{b as X}from"./chunk-KEXBEUSU.js";import"./chunk-WWDYDLY2.js";import"./chunk-YA3P77LV.js";import"./chunk-ERULJ2ZL.js";import"./chunk-WPNRDEHW.js";import"./chunk-JRS5QRZG.js";import"./chunk-4LWFJ4MZ.js";import"./chunk-BIJHMWXK.js";import"./chunk-4XMALK7X.js";import"./chunk-72SZI2UW.js";import"./chunk-FCPTN6NF.js";import"./chunk-MCI3DIWW.js";import"./chunk-6TURWSMN.js";import"./chunk-QD6IICK7.js";import{b as N,c as H}from"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import"./chunk-DYGQF3MI.js";import"./chunk-BRK6M6LA.js";import"./chunk-UIBUZ2N3.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";import{createHash as le}from"crypto";import{existsSync as z,mkdirSync as ne,readdirSync as re,readFileSync as ge,renameSync as se,writeFileSync as pe}from"fs";import{resolve as w}from"path";var _={maxPatches:30,maxCostUsd:.5,maxItems:60},he=12,fe=2e3,me=1500,M=8,U=300,be=12,B="## Checked facts";function S(n){return w(n,"_contributions")}function E(n,r){if(!z(n))return r;try{return JSON.parse(ge(n,"utf-8"))}catch(t){throw new Error(`${n} is not valid JSON: ${t.message}`)}}function L(n,r){ne(w(n,".."),{recursive:!0});let t=`${n}.${process.pid}.tmp`;pe(t,`${JSON.stringify(r,null,2)}
|
|
2
2
|
`),se(t,n)}function ie(n){return{agents:E(w(S(n),"state.json"),{agents:{}}).agents??{}}}function ye(n){let r=w(S(n),"pending");return z(r)?re(r).filter(t=>t.endsWith(".json")).sort().map(t=>E(w(r,t),null)).filter(t=>!!t):[]}function G(n){return w(S(n),"held.json")}function K(n,r={}){let t=E(G(n),[]);return r.all?t:t.filter(a=>a.status==="held")}function _e(n){let r=w(S(n),"reports");if(!z(r))return null;let t=re(r).filter(a=>a.endsWith(".json")).sort().pop();return t?E(w(r,t),null):null}function ke(n,r,t,a={}){let o=ie(r).agents[t],c=a.now??Date.now(),e=a.since??o?.lastRunAt??new Date(c-864e5).toISOString(),d=e.slice(0,10),u=new Set(o?.processed??[]),s=[];for(let g of n.getAgentEntries(t))g.date<d||u.has(g.id)||s.push({id:g.id,at:g.date,kind:"chat",title:[g.source,g.sourceContext].filter(Boolean).join(" \xB7 "),text:g.content});if(a.db){let g=Date.parse(e);for(let l of V(a.db,{agentId:t,since:Number.isFinite(g)?g:void 0,limit:500})){if(l.status==="in-flight"||u.has(l.taskId))continue;let k=(Q(a.db,l.taskId)?.steps??[]).filter(b=>b.name==="tool_use"||b.action).slice(0,be).map(b=>`- ${b.action??b.name}${b.inputSummary?` ${x(b.inputSummary,160)}`:""}${b.outputSummary?` \u2192 ${x(b.outputSummary,240)}`:""}${b.error?` \u2717 ${x(b.error,120)}`:""}`),y=[`Request: ${x(l.originalMessage??l.messagePreview??"",600)}`,k.length?`Tool calls:
|
|
3
3
|
${k.join(`
|
|
4
4
|
`)}`:"",l.finalResponse?`Reply: ${x(l.finalResponse,800)}`:""].filter(Boolean).join(`
|
|
@@ -54,4 +54,4 @@ _Sources: ${t.sources.join("; ")}._`,a);return n.writeArticle(r,{title:t.title,.
|
|
|
54
54
|
`).replace(/\n{3,}/g,`
|
|
55
55
|
|
|
56
56
|
`).trim(),superseded:d}}function Ce(n){let r=n.previous?` (previously: ${n.previous})`:"";return`- **${n.attribute}:** ${n.value} \u2014 ${n.source}; checked ${n.checkedAt.slice(0,10)} by ${n.by}${r}`}function Re(n){let r=n.match(/^- \*\*.+?:\*\* (.*?) — .*?; checked (\S+) by \S+(?: \(previously: (.*)\))?$/);return r?{value:r[1],checkedAt:r[2],...r[3]?{previous:r[3]}:{}}:void 0}function J(n,r){return`contribution:${n}@${r.slice(0,10)}`}var Te={person:"people",project:"projects",place:"places",concept:"concepts",event:"events",decision:"decisions",pattern:"patterns"};function de(n,r,t){let a=r.toLowerCase().replace(/[^\p{L}\p{N}]+/gu,"-").replace(/^-+|-+$/g,"").slice(0,60)||"page",o=t?Te[t]:"contributions",c=`${o}/${a}.md`;for(let e=2;n.readArticle(c);e++)c=`${o}/${a}-${e}.md`;return c}export{_ as DEFAULT_CONTRIBUTION_LIMITS,B as FACTS_HEADING,ue as applyFactLines,De as approveHeld,xe as buildContributionPrompt,S as contributionsDir,_e as latestReport,K as listHeld,ye as listPendingBatches,Be as mergeContributions,W as pageKey,Ae as parseContributionPatches,ke as pendingWork,Se as possibleDuplicate,Fe as rejectHeld,ce as replaceOnce,Me as runContribution};
|
|
57
|
-
//# sourceMappingURL=contributions-
|
|
57
|
+
//# sourceMappingURL=contributions-KLRJ4ZXV.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as N,k as A,l as O,m as Y}from"./chunk-
|
|
1
|
+
import{a as N,k as A,l as O,m as Y}from"./chunk-BQIWMQNU.js";import{f as y}from"./chunk-QAWKN2N4.js";import{f as C,g as G}from"./chunk-JTDUTCUE.js";import"./chunk-IMLAPB7G.js";import{b as U}from"./chunk-KEXBEUSU.js";import"./chunk-RGZARSHV.js";import"./chunk-QIJLFPWE.js";import{createHash as L}from"crypto";import{existsSync as J,mkdirSync as V,readFileSync as B,writeFileSync as q}from"fs";import{resolve as x}from"path";var _="wiki-enrich",$e=["person","organization","project","place","device","server","app","domain","account"],K=new Set(["person","organization","project","place"]),z=3500,Q=700;function X(e,n){let i=e.ontology.types.find(r=>r.id===n)?.lens??[],t=new Map;for(let r of i)if(G(r)==="statements")for(let s of C(r)){if(s==="related"||t.has(s))continue;let l=e.ontology.properties.find(u=>u.id===s);l?.domain&&!l.domain.includes(n)||t.set(s,l?.label??s.replace(/_/g," "))}return t}function D(e,n,i){let t=y(n.title);return t.length<4?[]:[...e.entities.values()].filter(r=>r.type===i&&r.id!==n.id&&` ${y(r.title)} `.includes(` ${t} `))}function H(e){return e.access==="public"?null:new Set([e.owner,...e.access==="shared"?e.sharedWith??[]:[]])}function Z(e,n){let i=H(e);if(!i)return!0;let t=H(n);return!!t&&[...t].every(r=>i.has(r))}function ee(e,n,i,t){let r=o=>!t||Z(o.article.meta,t.article.meta),s=o=>o.pages.some(r),l=n.pages.filter(r),u=t?[...new Set(l.flatMap(o=>o.article.meta.sources??[]))]:n.sources,p=N(e,n,null).filter(s),f=o=>[...new Map(o.map(d=>[d.id,d])).values()],k=f([...p.filter(o=>o.type==="event"),...D(e,n,"event").filter(s)]).sort((o,d)=>(d.date||"").localeCompare(o.date||"")).slice(0,30),a=f([...p.filter(o=>o.type==="project"),...D(e,n,"project").filter(s)]).slice(0,12),g=p.filter(o=>o.type!=="event"&&o.type!=="project").filter(s).filter(o=>n.type!=="person"||K.has(o.type)).slice(0,40),v=i(u).sort((o,d)=>d.date.localeCompare(o.date)).slice(0,14),c=X(e,n.type),m=new Map;for(let o of c.keys()){let d=e.ontology.properties.find(h=>h.id===o)?.range;d?.length&&m.set(o,d)}return{entity:n,pages:l,properties:c,ranges:m,neighbours:g,events:k,projects:a,entries:v,sources:u,mentions:te(e,n,12,r)}}function te(e,n,i=12,t=()=>!0){let r=[n.title,...n.pages.flatMap(p=>p.article.meta.aliases??[])].filter(p=>p.trim().length>=3);if(r.length===0)return[];let s=r.map(p=>p.trim().replace(/[.*+?^${}()|[\]\\]/g,"\\$&")),l=new RegExp(`(^|[^\\p{L}\\p{N}])(${s.join("|")})(?=$|[^\\p{L}\\p{N}])`,"iu"),u=[];for(let p of e.entities.values())if(!(p.id===n.id||p.type==="event"))for(let f of p.pages){if(!t(f))continue;let k=A(f.article.content),a=l.exec(k);if(!a)continue;let g=Math.max(0,a.index-250);u.push({page:f,excerpt:k.slice(g,a.index+450).replace(/\s+/g," ").trim(),at:f.article.meta.lastUpdated||""});break}return u.sort((p,f)=>f.at.localeCompare(p.at)).slice(0,i).map(({page:p,excerpt:f})=>({page:p,excerpt:f}))}function ne(e){let n=[...e.pages.map(i=>`${i.agentId}/${i.article.path}`),...e.sources,...e.events.map(i=>i.id),...e.projects.map(i=>i.id),...e.mentions.map(i=>`${i.page.agentId}/${i.page.article.path}`)].sort();return L("sha1").update(n.join(`
|
|
2
2
|
`)).digest("hex").slice(0,16)}var R=(e,n)=>e.length>n?`${e.slice(0,n)}\u2026`:e;function se(e,n,i){let t=e.entity,r=[`You are bringing one wiki page up to date. Today is ${i}.`,`Subject: "${t.title}" (${n}).`,"","## What the agents' pages say"];for(let s of e.pages)r.push(`### page ${s.agentId}/${s.article.path} (updated ${s.article.meta.lastUpdated||"?"})`,R(A(s.article.content),z),"");if(e.mentions.length){r.push("## Other pages that name the subject");for(let s of e.mentions)r.push(`### page ${s.page.agentId}/${s.page.article.path}: "${s.page.article.meta.title}"`,s.excerpt,"")}r.push("## Source entries (newest first)");for(let s of e.entries)r.push(`### entry ${s.id} (${s.date}, ${s.agentId}, ${s.source})`,R(s.content.trim(),Q),"");return r.push("## Event pages",...e.events.map(s=>`- ${s.date||"?"} \xB7 ${s.title}`),""),r.push("## Project pages",...e.projects.map(s=>`- ${s.title}`),""),r.push("## Other pages it may name",...e.neighbours.map(s=>`- ${s.title} (${s.type})`),""),r.push(`## Properties you may use (the subject is always ${t.title})`,...[...e.properties].map(([s,l])=>`- ${s}: "${t.title} ${l} <value>"${e.ranges.get(s)?`, value is a ${e.ranges.get(s).join(" or ")}`:""}`),""),r.push("## Task","Return one JSON object and nothing else:",'{"overview": "\u2026", "statements": [{"property": "\u2026", "value": "\u2026", "role": "\u2026", "since": "YYYY-MM-DD", "until": "YYYY-MM-DD", "source": "\u2026"}], "history": ["event page title"], "projects": ["project page title"]}',"","Rules:",`- overview: 3 to 6 full sentences telling the story of the relationship: who ${t.title} is to us, how it started, what changed, and where it stands now, with dates. Plain prose. Link pages as [[Exact Title]] only when the title is listed above. Never stop mid-sentence.`,"- statements: only facts the pages or entries state. Use only the listed properties. value is a listed page title when it names one, else a short literal. role, since and until only when stated.","- source: the entry id, the page (agent/path) or the event title the fact comes from. A statement without one of these is dropped.","- Do not list an AI agent or bot as a person's relation.","- history: titles of the listed event pages that are about the subject. projects: listed project titles it takes part in.","- Leave out anything you could not verify. Do not write 'unknown' or 'not captured' as a fact.","- Write in the language the pages are written in."),r.join(`
|
|
3
3
|
`)}function ie(e){let n=e.match(/```(?:json)?\s*\n([\s\S]*?)\n```/),i=n?n[1]:e.slice(e.indexOf("{"),e.lastIndexOf("}")+1);try{let t=JSON.parse(i);return t&&typeof t=="object"&&!Array.isArray(t)?t:null}catch{return null}}var T=/^\d{4}-\d{2}(-\d{2})?$/,w=e=>typeof e=="string"?e.trim():"";function re(e,n,i){let t=[],r=n.entity,s=w(e.overview);if(s&&!/[.!?؟)»"']$/.test(s)){let a=Math.max(s.lastIndexOf(". "),s.lastIndexOf("? "),s.lastIndexOf("! "));s=a>0?s.slice(0,a+1):"",t.push("overview: unfinished last sentence removed")}let l=[...n.entries.map(a=>a.id),...n.pages.map(a=>`${a.agentId}/${a.article.path}`),...n.pages.map(a=>a.article.path),...n.mentions.map(a=>`${a.page.agentId}/${a.page.article.path}`),...n.mentions.map(a=>a.page.article.path),...n.events.map(a=>a.title)],u=[],p=new Set;for(let a of Array.isArray(e.statements)?e.statements:[]){let g=a??{},v=w(g.property),c=w(g.value),m=w(g.source),o=`${v} ${c}`;if(!n.properties.has(v)){t.push(`${o}: property not allowed`);continue}if(!c||/^(unknown|not (given|known|captured|recorded))\b/i.test(c)){t.push(`${o}: no value`);continue}if(!m||!l.some(E=>m.includes(E))){t.push(`${o}: source not among those given`);continue}let d=i.names.get(y(c)),h=d?i.entities.get(d):void 0;if(h?.id===r.id){t.push(`${o}: points at itself`);continue}if(r.type==="person"&&h?.type==="agent"){t.push(`${o}: an agent is not a person's relation`);continue}let S=n.ranges.get(v);if(S&&h&&!S.includes(h.type)){t.push(`${o}: value is a ${h.type}, expected ${S.join(" or ")}`);continue}let j=`${v}
|
|
4
4
|
${y(c)}`;if(p.has(j))continue;p.add(j);let $={property:v,value:h?.title??c,source:R(m,200)},W=w(g.role);W&&($.role=R(W,80)),T.test(w(g.since))&&($.since=w(g.since)),T.test(w(g.until))&&($.until=w(g.until)),u.push($)}let f=new Map([...n.events,...n.projects].map(a=>[y(a.title),a.title])),k=[];for(let a of[...Array.isArray(e.history)?e.history:[],...Array.isArray(e.projects)?e.projects:[]]){let g=f.get(y(w(a).replace(/^\d{4}-\d{2}-\d{2}\s*·\s*/,"")));g&&!k.includes(g)?k.push(g):!g&&w(a)&&t.push(`link ${w(a)}: no such page`)}return{overview:s,statements:u,links:k,dropped:t}}function oe(e,n){let i=`## Overview
|
|
@@ -13,4 +13,4 @@ ${e.trim()}
|
|
|
13
13
|
`}function ae(e,n,i){let t=p=>`${p.property}
|
|
14
14
|
${y(p.value)}`,r=(e.statements??[]).filter(p=>p.by!==_),s=new Set(r.map(t)),l=[...r,...n.statements.filter(p=>!s.has(t(p))).map(p=>({...p,checked_at:i,by:_}))],u=[...new Set([...e.related??[],...n.links])];return{...e,statements:l.length?l:void 0,related:u.length?u:void 0,lastUpdated:i}}function ce(e,n){return n.pages.filter(i=>!e.syncedFrom(i.agentId)).sort((i,t)=>(t.article.meta.sources?.length??0)-(i.article.meta.sources?.length??0)||t.article.content.length-i.article.content.length)[0]}var pe={person:"people",organization:"organizations",project:"projects",place:"places"};function ke(e,n,i,t,r){let s=n.replace(/\s+/g," ").trim(),l=e.getAgentWiki(t);if(l.listAllArticles().some(k=>y(k.meta.title)===y(s)))return null;let u=`${pe[i]??`${i}s`}/${y(s).replace(/ /g,"-").slice(0,80)||"page"}.md`,p=U(i)?i:void 0,f={title:s,type:p,class:i,tags:[],owner:t,access:"shared",created:r,lastUpdated:r,sources:[]};return l.writeArticle(u,f,`${s}.
|
|
15
15
|
`,t)?u:null}function Ee(e){let n=x(e,"_enrich","state.json");if(!J(n))return{entities:{}};try{let i=JSON.parse(B(n,"utf-8"));return i&&typeof i.entities=="object"?i:{entities:{}}}catch{return{entities:{}}}}function we(e,n){V(x(e,"_enrich"),{recursive:!0}),q(x(e,"_enrich","state.json"),JSON.stringify(n,null,2))}async function be(e,n,i,t,r){let s=new Set(t.types),l=new Set(t.only.map(y)),u=c=>c.sources.length+c.pages.length,p=c=>r.entities[c.id]?.failures??0,f=[...n.entities.values()].filter(c=>s.has(c.type)).filter(c=>l.size===0||l.has(y(c.id))||l.has(y(c.title))).sort((c,m)=>p(c)-p(m)||u(m)-u(c)),k=c=>e.getSharedStore().readEntries(c),a={outcomes:[],costUsd:0,capped:!1},g=0,v=(c,m,o,d=!1)=>{if(t.dryRun)return;let h=r.entities[c];r.entities[c]=d?{fingerprint:h?.fingerprint??"",at:new Date().toISOString(),costUsd:o,failures:(h?.failures??0)+1}:{fingerprint:m,at:new Date().toISOString(),costUsd:o},t.save?.(r)};for(let c of f){if(g>=t.max)break;let m={entity:c.id,title:c.title,statements:0,links:0,overview:!1,costUsd:0,dropped:[]},o=ce(e,c);if(!o){a.outcomes.push({...m,status:"no-page"});continue}let d=ee(n,c,k,o),h=ne(d);if(!t.force&&r.entities[c.id]?.fingerprint===h){l.size&&a.outcomes.push({...m,status:"unchanged"});continue}if(a.costUsd>=t.maxCostUsd){a.capped=!0;break}g++;let S=n.ontology.types.find(I=>I.id===c.type)?.label??c.type,j=`${o.agentId}/${o.article.path}`,$;try{$=await i(se(d,S,t.today))}catch(I){a.outcomes.push({...m,page:j,status:"failed",dropped:[I.message.slice(0,200)]}),v(c.id,h,0,!0);continue}a.costUsd+=$.costUsd;let W=ie($.text),E={...m,page:j,status:"no-reply",costUsd:$.costUsd};if(!W){a.outcomes.push(E),v(c.id,h,$.costUsd);continue}let b=re(W,d,n);if(Object.assign(E,{statements:b.statements.length,links:b.links.length,overview:!!b.overview,dropped:b.dropped}),!b.overview&&b.statements.length===0&&b.links.length===0){E.status="nothing-new",a.outcomes.push(E),v(c.id,h,$.costUsd);continue}let M=b.overview?oe(o.article.content,b.overview):o.article.content,F=ae(o.article.meta,b,t.today);if(t.dryRun){a.outcomes.push({...E,status:"dry-run",preview:M,facts:b.statements});continue}let P=e.getAgentWiki(o.agentId);if(!P.writeArticle(o.article.path,F,M,o.article.meta.owner||o.agentId)){E.status="failed",E.dropped.push("write refused"),a.outcomes.push(E),v(c.id,h,$.costUsd,!0);continue}P.rebuildIndex(),v(c.id,h,$.costUsd),E.status="written",a.outcomes.push(E)}return a}export{_ as ENRICH_BY,$e as ENRICH_TYPES,se as buildEnrichPrompt,re as checkEnrichment,ke as createEntityPage,ee as enrichContext,ne as fingerprint,X as lensProperties,Ee as loadEnrichState,te as mentionsOf,ae as mergedMeta,ie as parseEnrichReply,Z as readableAlongside,be as runEnrich,we as saveEnrichState,ce as targetPage,oe as withOverview};
|
|
16
|
-
//# sourceMappingURL=enrich-
|
|
16
|
+
//# sourceMappingURL=enrich-ZB5I7KHN.js.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{a as w,k as I}from"./chunk-BQIWMQNU.js";import{f as g}from"./chunk-QAWKN2N4.js";import"./chunk-JTDUTCUE.js";import"./chunk-IMLAPB7G.js";import{a as b}from"./chunk-RGZARSHV.js";import"./chunk-QIJLFPWE.js";var y="wiki-events",E="importance_set",A=new Set(["event","due_date","topic"]),$=10,W=320;function P(n,t,a){let o=new Set(a.map(r=>r.toLowerCase()));for(let r of n??[])if(!(!b.includes(r.level)||!r.title&&!r.tags?.length)){if(r.title){let c;try{c=new RegExp(r.title,"i")}catch{continue}if(!c.test(t))continue}if(!(r.tags?.length&&!r.tags.some(c=>o.has(c.toLowerCase()))))return r.level}}function x(n,t){let a=` ${g(t)} `,o=[];for(let r of n.entities.values()){if(A.has(r.type))continue;let c=g(r.title);c.length>=4&&a.includes(` ${c} `)&&o.push(r)}return o}function M(n,t){let a=w(n,t,null).filter(r=>!A.has(r.type)),o=x(n,t.title);return[...new Map([...o,...a].map(r=>[r.id,r])).values()].slice(0,$)}function R(n,t){return t.pages.find(a=>!n.syncedFrom(a.agentId))}function j(n){return n.pages.some(t=>t.article.meta.importance&&!(t.article.meta.statements??[]).some(a=>a.by===y&&a.property===E))}function _(n,t,a){let o=new Set;for(let i of a.about){let l=t.names.get(g(i))??(t.entities.has(i)?i:void 0);l&&o.add(l)}let r=[],c=[],s=[...t.entities.values()].filter(i=>i.type==="event").sort((i,l)=>(l.date||"").localeCompare(i.date||""));for(let i of s){if(i.pages.some(e=>e.article.meta.importance)&&(!a.force||j(i)))continue;let f=M(t,i);if(a.about.length&&!f.some(e=>o.has(e.id)))continue;let m=R(n,i);if(!m){c.push(i);continue}r.push({event:i,page:m,candidates:f})}return{items:r,noPage:c}}var S=(n,t)=>n.length>t?`${n.slice(0,t)}\u2026`:n;function L(n,t){let a=["You are sorting the event pages of a company wiki by importance, and saying what each event is about.","","Levels:","- minor: routine upkeep or a small incident with no lasting effect (a disk filled and was cleaned, a job was restarted, a reminder was sent).","- normal: something a person would want in the history of the thing it is about (a delivery, a payment, an outage that was noticed, a meeting with an outcome).","- major: a turning point (a client won or lost, a contract signed, a legal or financial deadline missed, data lost, a decision that changes how things are done).","When unsure between two levels, pick the lower one.","","## Events"];return n.forEach((o,r)=>{let c=S(I(o.page.article.content).replace(/\s+/g," ").trim(),W);a.push(`### ${r+1}. ${o.event.title} (${o.event.date||"no date"})`,c||"(no text)"),a.push(o.candidates.length?`May be about: ${o.candidates.map(s=>`"${s.title}" (${s.type})`).join(", ")}`:"May be about: nothing listed","")}),a.push("## Task","Return one JSON object and nothing else:",'{"events": [{"n": 1, "importance": "minor", "about": ["Exact Title"], "why": "one short reason"}]}',"","Rules:",`- One item per event, with its number. importance is one of ${b.join(", ")}.`,`- about: only titles from that event's own "May be about" list, copied exactly, and only the ones the event really concerns: the machine that failed, the client it was for, the person it happened to. Often one, at most three. Leave it empty when none fits.`,"- why: under 15 words, in English.",...t.importance.major_set_by==="owner"?["- major is only a suggestion here: the owner confirms it."]:[]),a.join(`
|
|
2
|
+
`)}function C(n){let t=n.match(/```(?:json)?\s*\n([\s\S]*?)\n```/),a=t?t[1]:n.slice(n.indexOf("{"),n.lastIndexOf("}")+1);try{let o=JSON.parse(a);return o&&typeof o=="object"&&!Array.isArray(o)?o:null}catch{return null}}function O(n,t){return n==="major"&&t.importance.major_set_by==="owner"?{importance:"normal",proposed:"major"}:{importance:n}}function U(n,t,a){let o=new Map,r=C(n);for(let c of Array.isArray(r?.events)?r.events:[]){let s=c??{},i=Number(s.n)-1,l=t[i];if(!Number.isInteger(i)||!l||o.has(i))continue;let f=String(s.importance??"").trim().toLowerCase();if(!b.includes(f))continue;let m=[],e=new Map(l.candidates.map(d=>[g(d.title),d.title])),p=[];for(let d of Array.isArray(s.about)?s.about:[]){let u=e.get(g(String(d??"")));u&&!p.includes(u)?p.push(u):!u&&String(d??"").trim()&&m.push(`about ${String(d).trim().slice(0,80)}: not in the list shown`)}p.length>3&&m.push(`about: kept the first 3 of ${p.length}`);let h=typeof s.why=="string"?S(s.why.trim(),160):void 0;o.set(i,{verdict:{...O(f,a),about:p.slice(0,3),why:h||void 0,by:"model"},dropped:m})}return o}function G(n,t,a){let o=(n.statements??[]).filter(s=>s.by!==y),r=new Set(o.filter(s=>s.property==="involves").map(s=>g(s.value))),c=t.about.filter(s=>!r.has(g(s))).map(s=>({property:"involves",value:s,checked_at:a,by:y}));return c.push({property:E,value:t.proposed??t.importance,checked_at:a,by:y,...t.why?{note:t.why}:{}}),{...n,importance:t.importance,importanceProposed:t.proposed,statements:[...o,...c],lastUpdated:a}}async function B(n,t,a,o){let r=t.ontology,{items:c,noPage:s}=_(n,t,o),i=c.slice(0,o.max),l={outcomes:[],costUsd:0,calls:0,capped:!1,left:c.length-i.length};for(let e of o.about.length?s:[])l.outcomes.push({event:e.id,title:e.title,date:e.date,status:"no-page",about:[],dropped:["its pages are copied from another node"]});let f=(e,p,h)=>{let d=`${e.page.agentId}/${e.page.article.path}`,u={event:e.event.id,title:e.event.title,date:e.event.date,page:d,status:"dry-run",importance:p.importance,proposed:p.proposed,about:p.about,by:p.by,why:p.why,dropped:h};if(o.dryRun){l.outcomes.push(u);return}let k=n.getAgentWiki(e.page.agentId).writeArticle(e.page.article.path,G(e.page.article.meta,p,o.today),e.page.article.content,e.page.article.meta.owner||e.page.agentId);l.outcomes.push({...u,status:k?"written":"failed",dropped:k?h:[...h,"write refused"]})},m=[];for(let e of i){let p=P(r.importance.rules,e.event.title,e.page.article.meta.tags??[]);if(!p){m.push(e);continue}let h=new Set(x(t,e.event.title).map(u=>u.id)),d=e.candidates.filter(u=>h.has(u.id)).slice(0,3).map(u=>u.title);f(e,{...O(p,r),about:d,why:"matched an importance rule",by:"rule"},[])}if(o.rulesOnly)return l.left+=m.length,l;for(let e=0;e<m.length;e+=o.batch){let p=m.slice(e,e+o.batch);if(l.costUsd>=o.maxCostUsd){l.capped=!0,l.left+=m.length-e;break}l.calls++;let h;try{let d=await a(L(p,r));l.costUsd+=d.costUsd,h=U(d.text,p,r)}catch(d){for(let u of p)l.outcomes.push({event:u.event.id,title:u.event.title,date:u.event.date,page:`${u.page.agentId}/${u.page.article.path}`,status:"failed",about:[],dropped:[d.message.slice(0,200)]});continue}p.forEach((d,u)=>{let v=h.get(u);v?f(d,v.verdict,v.dropped):l.outcomes.push({event:d.event.id,title:d.event.title,date:d.event.date,page:`${d.page.agentId}/${d.page.article.path}`,status:"no-answer",about:[],dropped:["the reply had no usable item for this event"]})})}if(!o.dryRun)for(let e of new Set(l.outcomes.filter(p=>p.status==="written").map(p=>p.page.split("/")[0])))n.getAgentWiki(e).rebuildIndex();return l}function D(n,t,a,o,r){let c=t.names.get(g(a))??(t.entities.has(a)?a:void 0),s=c?t.entities.get(c):void 0;if(!s)return{ok:!1,reason:`no page is titled "${a}"`};if(s.type!=="event")return{ok:!1,title:s.title,reason:`"${s.title}" is a ${s.type}, not an event`};let i=R(n,s);if(!i)return{ok:!1,title:s.title,reason:"its pages are copied from another node; set the level there"};let l=(i.article.meta.statements??[]).filter(p=>!(p.by===y&&p.property===E)),f={...i.article.meta,importance:o,importanceProposed:void 0,statements:l.length?l:void 0,lastUpdated:r},m=n.getAgentWiki(i.agentId),e=m.writeArticle(i.article.path,f,i.article.content,i.article.meta.owner||i.agentId);return e&&m.rebuildIndex(),{ok:e,title:s.title,page:`${i.agentId}/${i.article.path}`,reason:e?void 0:"write refused"}}function F(n,t,a){let o=[],r=new Map(t.outcomes.filter(c=>c.importance).map(c=>[c.event,c]));for(let c of a){let s=n.names.get(g(c))??(n.entities.has(c)?c:void 0),i=s?n.entities.get(s):void 0;if(!i)continue;let l=new Set(w(n,i,new Set(["event"])).map(e=>e.id)),f={minor:0,normal:0,major:0},m=new Set;for(let e of n.entities.values()){if(e.type!=="event")continue;let p=r.get(e.id);!(l.has(e.id)||p?.about.some(d=>g(d)===g(i.title)))||m.has(e.id)||(m.add(e.id),f[p?.importance??e.importance]++)}o.push({title:i.title,type:i.type,before:l.size,after:f})}return o}export{y as EVENTS_BY,L as buildEventsPrompt,U as checkEventsReply,M as eventCandidates,G as eventMeta,_ as pickEvents,P as ruleLevel,B as runEvents,D as setEventLevel,F as summariseAbout};
|
|
3
|
+
//# sourceMappingURL=event-levels-CQWHSLMT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/wiki/event-levels.ts"],"sourcesContent":["// --- Give each event an importance level and the pages it is about (#811) ---\n//\n// Event pages are half the wiki, and until a level is set they all show\n// as `normal` beside decisions and client events. This pass reads the\n// event pages (never the raw entries) and writes, per event:\n// - `importance`: minor, normal or major;\n// - `involves` statements: the people, organisations, assets or\n// projects the event is about, so it shows in their History.\n// The ontology's `importance.rules` decide first, for free. What they\n// leave is sent to a model in batches. Each answer is checked against\n// what the call was shown before a page is written through the store,\n// which keeps the old version. Where only the owner may set `major`, a\n// suggested `major` is stored as a proposal and the event stays `normal`.\n\nimport type { WikiHub } from \"./hub\"\nimport type { WikiArticleMeta } from \"./types\"\nimport { normName, type Entity, type GraphPage, type WikiGraph } from \"./ontology/graph\"\nimport { linkedEntities } from \"./ontology/lens\"\nimport { IMPORTANCE_LEVELS, type Importance, type ImportanceRule, type Ontology, type WikiStatement } from \"./ontology/types\"\nimport { bodyOf } from \"./ontology/view-entity\"\n\nexport const EVENTS_BY = \"wiki-events\"\n/** Statement that records this job set the level; the owner's `set` removes it. */\nconst LEVEL_MARK = \"importance_set\"\n\n/** Types an event can be about. Events, due dates and topics are not. */\nconst ABOUT_SKIP = new Set([\"event\", \"due_date\", \"topic\"])\nconst MAX_CANDIDATES = 10\nconst BODY_CHARS = 320\n\nexport interface EventItem {\n event: Entity\n /** The page the result is written to: one this node owns. */\n page: GraphPage\n /** Entities the event may be about: linked to it, or named in its title. */\n candidates: Entity[]\n}\n\nexport interface EventVerdict {\n importance: Importance\n /** Set when `major` was suggested but only the owner may set it. */\n proposed?: Importance\n /** Titles of the candidates the event is about. */\n about: string[]\n why?: string\n by: \"rule\" | \"model\"\n}\n\nexport interface EventOutcome {\n event: string\n title: string\n date: string\n page?: string\n status: \"written\" | \"dry-run\" | \"no-page\" | \"no-answer\" | \"failed\"\n importance?: Importance\n proposed?: Importance\n about: string[]\n by?: \"rule\" | \"model\"\n why?: string\n dropped: string[]\n}\n\nexport interface EventsRun {\n outcomes: EventOutcome[]\n costUsd: number\n calls: number\n /** Set when the run stopped at its spending cap. */\n capped: boolean\n /** Events without a level that this run did not reach. */\n left: number\n}\n\nexport interface EventsCall {\n (prompt: string): Promise<{ text: string; costUsd: number }>\n}\n\nexport interface EventsOptions {\n /** Entity ids or titles: only events linked to or naming them. */\n about: string[]\n /** Most events per run. */\n max: number\n /** Events per model call. */\n batch: number\n maxCostUsd: number\n dryRun: boolean\n /** Redo events that already have a level set by this job. */\n force: boolean\n /** Skip the model: only the ontology's rules decide. */\n rulesOnly: boolean\n today: string\n}\n\n/** The first rule that matches the event, if any. */\nexport function ruleLevel(rules: ImportanceRule[] | undefined, title: string, tags: string[]): Importance | undefined {\n const have = new Set(tags.map(t => t.toLowerCase()))\n for (const r of rules ?? []) {\n if (!IMPORTANCE_LEVELS.includes(r.level) || (!r.title && !r.tags?.length)) continue\n if (r.title) {\n let re: RegExp\n try { re = new RegExp(r.title, \"i\") } catch { continue } // reported by checkOntology\n if (!re.test(title)) continue\n }\n if (r.tags?.length && !r.tags.some(t => have.has(t.toLowerCase()))) continue\n return r.level\n }\n return undefined\n}\n\n/** Entities whose name appears as whole words in `text`. */\nfunction namedEntities(g: WikiGraph, text: string): Entity[] {\n const hay = ` ${normName(text)} `\n const out: Entity[] = []\n for (const e of g.entities.values()) {\n if (ABOUT_SKIP.has(e.type)) continue\n const name = normName(e.title)\n if (name.length >= 4 && hay.includes(` ${name} `)) out.push(e)\n }\n return out\n}\n\n/** What the event may be about: pages it links to or that link to it,\n * then pages its title names. Linked ones first. */\nexport function eventCandidates(g: WikiGraph, ev: Entity): Entity[] {\n const linked = linkedEntities(g, ev, null).filter(x => !ABOUT_SKIP.has(x.type))\n const named = namedEntities(g, ev.title)\n return [...new Map([...named, ...linked].map(x => [x.id, x])).values()].slice(0, MAX_CANDIDATES)\n}\n\nfunction localPage(hub: Pick<WikiHub, \"syncedFrom\">, e: Entity): GraphPage | undefined {\n return e.pages.find(p => !hub.syncedFrom(p.agentId))\n}\n\n/** True when the level on the event was set by a person or another job. */\nfunction setByOthers(ev: Entity): boolean {\n return ev.pages.some(p => p.article.meta.importance && !(p.article.meta.statements ?? []).some(s => s.by === EVENTS_BY && s.property === LEVEL_MARK))\n}\n\n/** Events this run should look at, newest first. */\nexport function pickEvents(hub: Pick<WikiHub, \"syncedFrom\">, g: WikiGraph, opts: Pick<EventsOptions, \"about\" | \"force\">): { items: EventItem[]; noPage: Entity[] } {\n const scope = new Set<string>()\n for (const name of opts.about) {\n const id = g.names.get(normName(name)) ?? (g.entities.has(name) ? name : undefined)\n if (id) scope.add(id)\n }\n const items: EventItem[] = []\n const noPage: Entity[] = []\n const events = [...g.entities.values()].filter(e => e.type === \"event\").sort((a, b) => (b.date || \"\").localeCompare(a.date || \"\"))\n for (const ev of events) {\n const hasLevel = ev.pages.some(p => p.article.meta.importance)\n // A level a person set is never redone; --force redoes only this job's.\n if (hasLevel && (!opts.force || setByOthers(ev))) continue\n const candidates = eventCandidates(g, ev)\n if (opts.about.length && !candidates.some(c => scope.has(c.id))) continue\n const page = localPage(hub, ev)\n if (!page) { noPage.push(ev); continue }\n items.push({ event: ev, page, candidates })\n }\n return { items, noPage }\n}\n\nconst clip = (s: string, n: number) => (s.length > n ? `${s.slice(0, n)}…` : s)\n\nexport function buildEventsPrompt(items: EventItem[], o: Ontology): string {\n const lines: string[] = [\n \"You are sorting the event pages of a company wiki by importance, and saying what each event is about.\",\n \"\",\n \"Levels:\",\n \"- minor: routine upkeep or a small incident with no lasting effect (a disk filled and was cleaned, a job was restarted, a reminder was sent).\",\n \"- normal: something a person would want in the history of the thing it is about (a delivery, a payment, an outage that was noticed, a meeting with an outcome).\",\n \"- major: a turning point (a client won or lost, a contract signed, a legal or financial deadline missed, data lost, a decision that changes how things are done).\",\n \"When unsure between two levels, pick the lower one.\",\n \"\",\n \"## Events\",\n ]\n items.forEach((it, i) => {\n const body = clip(bodyOf(it.page.article.content).replace(/\\s+/g, \" \").trim(), BODY_CHARS)\n lines.push(`### ${i + 1}. ${it.event.title} (${it.event.date || \"no date\"})`, body || \"(no text)\")\n lines.push(it.candidates.length ? `May be about: ${it.candidates.map(c => `\"${c.title}\" (${c.type})`).join(\", \")}` : \"May be about: nothing listed\", \"\")\n })\n lines.push(\n \"## Task\",\n \"Return one JSON object and nothing else:\",\n `{\"events\": [{\"n\": 1, \"importance\": \"minor\", \"about\": [\"Exact Title\"], \"why\": \"one short reason\"}]}`,\n \"\",\n \"Rules:\",\n `- One item per event, with its number. importance is one of ${IMPORTANCE_LEVELS.join(\", \")}.`,\n \"- about: only titles from that event's own \\\"May be about\\\" list, copied exactly, and only the ones the event really concerns: the machine that failed, the client it was for, the person it happened to. Often one, at most three. Leave it empty when none fits.\",\n \"- why: under 15 words, in English.\",\n ...(o.importance.major_set_by === \"owner\" ? [\"- major is only a suggestion here: the owner confirms it.\"] : []),\n )\n return lines.join(\"\\n\")\n}\n\n/** The JSON object in the reply, fenced or not. */\nfunction parseReply(text: string): Record<string, unknown> | null {\n const fenced = text.match(/```(?:json)?\\s*\\n([\\s\\S]*?)\\n```/)\n const raw = fenced ? fenced[1] : text.slice(text.indexOf(\"{\"), text.lastIndexOf(\"}\") + 1)\n try {\n const v = JSON.parse(raw)\n return v && typeof v === \"object\" && !Array.isArray(v) ? v as Record<string, unknown> : null\n } catch {\n return null\n }\n}\n\n/** Keep `major` for the owner where the ontology says so. */\nfunction withOwnerRule(level: Importance, o: Ontology): Pick<EventVerdict, \"importance\" | \"proposed\"> {\n if (level === \"major\" && o.importance.major_set_by === \"owner\") return { importance: \"normal\", proposed: \"major\" }\n return { importance: level }\n}\n\n/** Per-event verdicts from one reply, keeping only what the call was shown. */\nexport function checkEventsReply(text: string, items: EventItem[], o: Ontology): Map<number, { verdict: EventVerdict; dropped: string[] }> {\n const out = new Map<number, { verdict: EventVerdict; dropped: string[] }>()\n const parsed = parseReply(text)\n for (const raw of Array.isArray(parsed?.events) ? parsed!.events as unknown[] : []) {\n const r = (raw ?? {}) as Record<string, unknown>\n const at = Number(r.n) - 1\n const it = items[at]\n if (!Number.isInteger(at) || !it || out.has(at)) continue\n const level = String(r.importance ?? \"\").trim().toLowerCase() as Importance\n if (!IMPORTANCE_LEVELS.includes(level)) continue\n const dropped: string[] = []\n const allowed = new Map(it.candidates.map(c => [normName(c.title), c.title]))\n const about: string[] = []\n for (const t of Array.isArray(r.about) ? r.about : []) {\n const title = allowed.get(normName(String(t ?? \"\")))\n if (title && !about.includes(title)) about.push(title)\n else if (!title && String(t ?? \"\").trim()) dropped.push(`about ${String(t).trim().slice(0, 80)}: not in the list shown`)\n }\n if (about.length > 3) dropped.push(`about: kept the first 3 of ${about.length}`)\n const why = typeof r.why === \"string\" ? clip(r.why.trim(), 160) : undefined\n out.set(at, { verdict: { ...withOwnerRule(level, o), about: about.slice(0, 3), why: why || undefined, by: \"model\" }, dropped })\n }\n return out\n}\n\n/** Page meta with the level and this job's `involves` facts replaced. */\nexport function eventMeta(meta: WikiArticleMeta, v: EventVerdict, today: string): WikiArticleMeta {\n const kept = (meta.statements ?? []).filter(s => s.by !== EVENTS_BY)\n const taken = new Set(kept.filter(s => s.property === \"involves\").map(s => normName(s.value)))\n const added: WikiStatement[] = v.about\n .filter(t => !taken.has(normName(t)))\n .map(t => ({ property: \"involves\", value: t, checked_at: today, by: EVENTS_BY }))\n // The marker records that this job set the level, so --force may redo it.\n added.push({ property: LEVEL_MARK, value: v.proposed ?? v.importance, checked_at: today, by: EVENTS_BY, ...(v.why ? { note: v.why } : {}) })\n return { ...meta, importance: v.importance, importanceProposed: v.proposed, statements: [...kept, ...added], lastUpdated: today }\n}\n\nexport async function runEvents(hub: WikiHub, g: WikiGraph, call: EventsCall, opts: EventsOptions): Promise<EventsRun> {\n const o = g.ontology\n const { items: all, noPage } = pickEvents(hub, g, opts)\n const items = all.slice(0, opts.max)\n const run: EventsRun = { outcomes: [], costUsd: 0, calls: 0, capped: false, left: all.length - items.length }\n for (const ev of opts.about.length ? noPage : []) {\n run.outcomes.push({ event: ev.id, title: ev.title, date: ev.date, status: \"no-page\", about: [], dropped: [\"its pages are copied from another node\"] })\n }\n\n const write = (it: EventItem, v: EventVerdict, dropped: string[]): void => {\n const where = `${it.page.agentId}/${it.page.article.path}`\n const base: EventOutcome = { event: it.event.id, title: it.event.title, date: it.event.date, page: where, status: \"dry-run\", importance: v.importance, proposed: v.proposed, about: v.about, by: v.by, why: v.why, dropped }\n if (opts.dryRun) { run.outcomes.push(base); return }\n const store = hub.getAgentWiki(it.page.agentId)\n const ok = store.writeArticle(it.page.article.path, eventMeta(it.page.article.meta, v, opts.today), it.page.article.content, it.page.article.meta.owner || it.page.agentId)\n run.outcomes.push({ ...base, status: ok ? \"written\" : \"failed\", dropped: ok ? dropped : [...dropped, \"write refused\"] })\n }\n\n // Rules first: free, and the same answer every run.\n const forModel: EventItem[] = []\n for (const it of items) {\n const level = ruleLevel(o.importance.rules, it.event.title, it.page.article.meta.tags ?? [])\n if (!level) { forModel.push(it); continue }\n // A rule gives the level only; what the title names is what it is about.\n const named = new Set(namedEntities(g, it.event.title).map(e => e.id))\n const about = it.candidates.filter(c => named.has(c.id)).slice(0, 3).map(c => c.title)\n write(it, { ...withOwnerRule(level, o), about, why: \"matched an importance rule\", by: \"rule\" }, [])\n }\n if (opts.rulesOnly) {\n run.left += forModel.length\n return run\n }\n\n for (let i = 0; i < forModel.length; i += opts.batch) {\n const batch = forModel.slice(i, i + opts.batch)\n if (run.costUsd >= opts.maxCostUsd) {\n run.capped = true\n run.left += forModel.length - i\n break\n }\n run.calls++\n let verdicts: ReturnType<typeof checkEventsReply>\n try {\n const reply = await call(buildEventsPrompt(batch, o))\n run.costUsd += reply.costUsd\n verdicts = checkEventsReply(reply.text, batch, o)\n } catch (err) {\n for (const it of batch) {\n run.outcomes.push({ event: it.event.id, title: it.event.title, date: it.event.date, page: `${it.page.agentId}/${it.page.article.path}`, status: \"failed\", about: [], dropped: [(err as Error).message.slice(0, 200)] })\n }\n continue\n }\n batch.forEach((it, at) => {\n const v = verdicts.get(at)\n if (v) write(it, v.verdict, v.dropped)\n else run.outcomes.push({ event: it.event.id, title: it.event.title, date: it.event.date, page: `${it.page.agentId}/${it.page.article.path}`, status: \"no-answer\", about: [], dropped: [\"the reply had no usable item for this event\"] })\n })\n }\n if (!opts.dryRun) {\n for (const agentId of new Set(run.outcomes.filter(x => x.status === \"written\").map(x => x.page!.split(\"/\")[0]))) {\n hub.getAgentWiki(agentId).rebuildIndex()\n }\n }\n return run\n}\n\n/** The owner's own word: set a level on an event and clear any proposal. */\nexport function setEventLevel(hub: WikiHub, g: WikiGraph, name: string, level: Importance, today: string): { ok: boolean; title?: string; page?: string; reason?: string } {\n const id = g.names.get(normName(name)) ?? (g.entities.has(name) ? name : undefined)\n const ev = id ? g.entities.get(id) : undefined\n if (!ev) return { ok: false, reason: `no page is titled \"${name}\"` }\n if (ev.type !== \"event\") return { ok: false, title: ev.title, reason: `\"${ev.title}\" is a ${ev.type}, not an event` }\n const page = localPage(hub, ev)\n if (!page) return { ok: false, title: ev.title, reason: \"its pages are copied from another node; set the level there\" }\n // Dropping this job's marker makes the level the owner's: no run redoes it.\n const statements = (page.article.meta.statements ?? []).filter(s => !(s.by === EVENTS_BY && s.property === LEVEL_MARK))\n const meta: WikiArticleMeta = { ...page.article.meta, importance: level, importanceProposed: undefined, statements: statements.length ? statements : undefined, lastUpdated: today }\n const store = hub.getAgentWiki(page.agentId)\n const ok = store.writeArticle(page.article.path, meta, page.article.content, page.article.meta.owner || page.agentId)\n if (ok) store.rebuildIndex()\n return { ok, title: ev.title, page: `${page.agentId}/${page.article.path}`, reason: ok ? undefined : \"write refused\" }\n}\n\nexport interface AboutSummary {\n title: string\n type: string\n /** Events in its History before this run, and how they split after. */\n before: number\n after: Record<Importance, number>\n}\n\n/** For a pilot: what each named page's History looks like after the run. */\nexport function summariseAbout(g: WikiGraph, run: EventsRun, about: string[]): AboutSummary[] {\n const out: AboutSummary[] = []\n const byEvent = new Map(run.outcomes.filter(x => x.importance).map(x => [x.event, x]))\n for (const name of about) {\n const id = g.names.get(normName(name)) ?? (g.entities.has(name) ? name : undefined)\n const e = id ? g.entities.get(id) : undefined\n if (!e) continue\n const linkedBefore = new Set(linkedEntities(g, e, new Set([\"event\"])).map(x => x.id))\n const after: Record<Importance, number> = { minor: 0, normal: 0, major: 0 }\n const seen = new Set<string>()\n for (const ev of g.entities.values()) {\n if (ev.type !== \"event\") continue\n const o = byEvent.get(ev.id)\n const linkedAfter = linkedBefore.has(ev.id) || !!o?.about.some(t => normName(t) === normName(e.title))\n if (!linkedAfter || seen.has(ev.id)) continue\n seen.add(ev.id)\n after[o?.importance ?? ev.importance]++\n }\n out.push({ title: e.title, type: e.type, before: linkedBefore.size, after })\n }\n return out\n}\n"],"mappings":"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","names":["EVENTS_BY","LEVEL_MARK","ABOUT_SKIP","MAX_CANDIDATES","BODY_CHARS","ruleLevel","rules","title","tags","have","t","IMPORTANCE_LEVELS","re","namedEntities","g","text","hay","normName","out","e","name","eventCandidates","ev","linked","linkedEntities","x","named","localPage","hub","p","setByOthers","s","pickEvents","opts","scope","id","items","noPage","events","a","b","candidates","c","page","clip","n","buildEventsPrompt","o","lines","it","i","body","bodyOf","parseReply","fenced","raw","v","withOwnerRule","level","checkEventsReply","parsed","r","at","dropped","allowed","about","why","eventMeta","meta","today","kept","taken","added","runEvents","call","all","run","write","where","base","ok","forModel","batch","verdicts","reply","err","agentId","setEventLevel","statements","store","summariseAbout","byEvent","linkedBefore","after","seen"]}
|