@duckmind/dm-darwin-x64 0.48.5 → 0.49.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.
Files changed (62) hide show
  1. package/dm +0 -0
  2. package/extensions/.dm-extensions.json +147 -218
  3. package/extensions/dm-9router-ext/package.json +0 -6
  4. package/extensions/dm-9router-ext/src/index.js +1 -1
  5. package/extensions/dm-ask-user/package.json +0 -4
  6. package/extensions/dm-caveman/LICENSE +21 -0
  7. package/extensions/dm-caveman/extensions/caveman.js +29 -0
  8. package/extensions/dm-caveman/package.json +20 -0
  9. package/extensions/dm-cli-anything/index.js +5 -5
  10. package/extensions/dm-cli-anything/package.json +0 -7
  11. package/extensions/dm-cli-anything/skills/cli-anything/SKILL.md +1 -3
  12. package/extensions/dm-context/package.json +0 -1
  13. package/extensions/dm-cua/package.json +0 -7
  14. package/extensions/dm-fff/package.json +0 -6
  15. package/extensions/dm-goal/package.json +0 -8
  16. package/extensions/dm-grill-me/index.js +2 -2
  17. package/extensions/dm-grill-me/package.json +0 -7
  18. package/extensions/dm-image2/package.json +0 -8
  19. package/extensions/dm-subagents/package.json +0 -11
  20. package/extensions/dm-tasks/package.json +0 -7
  21. package/extensions/dm-usage/package.json +0 -7
  22. package/extensions/greedysearch-dm/bin/cdp-greedy.mjs +1 -8
  23. package/extensions/greedysearch-dm/bin/gschrome.mjs +3 -3
  24. package/extensions/greedysearch-dm/bin/launch-visible.mjs +3 -3
  25. package/extensions/greedysearch-dm/bin/launch.mjs +4 -4
  26. package/extensions/greedysearch-dm/bin/search.mjs +103 -103
  27. package/extensions/greedysearch-dm/extractors/consensus.mjs +35 -35
  28. package/extensions/greedysearch-dm/extractors/gemini.mjs +38 -38
  29. package/extensions/greedysearch-dm/extractors/logically.mjs +35 -35
  30. package/extensions/greedysearch-dm/package.json +0 -10
  31. package/extensions/greedysearch-dm/src/search/chrome.mjs +23 -23
  32. package/extensions/greedysearch-dm/src/search/fetch-source.mjs +35 -35
  33. package/extensions/greedysearch-dm/src/search/research.mjs +61 -61
  34. package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +4 -4
  35. package/package.json +1 -1
  36. package/extensions/dm-9router-ext/README.md +0 -142
  37. package/extensions/dm-9router-ext/tsconfig.json +0 -17
  38. package/extensions/dm-ask-user/README.md +0 -226
  39. package/extensions/dm-cli-anything/README.md +0 -33
  40. package/extensions/dm-cli-anything/vendor/UPSTREAM.md +0 -14
  41. package/extensions/dm-context/AGENTS.md +0 -41
  42. package/extensions/dm-context/README.md +0 -18
  43. package/extensions/dm-context/tsconfig.json +0 -16
  44. package/extensions/dm-cua/README.md +0 -24
  45. package/extensions/dm-fff/README.md +0 -36
  46. package/extensions/dm-fff/tsconfig.json +0 -13
  47. package/extensions/dm-goal/CHANGELOG.md +0 -12
  48. package/extensions/dm-goal/README.md +0 -29
  49. package/extensions/dm-goal/tsconfig.json +0 -15
  50. package/extensions/dm-grill-me/DESIGN.md +0 -301
  51. package/extensions/dm-grill-me/README.md +0 -82
  52. package/extensions/dm-grill-me/tsconfig.json +0 -17
  53. package/extensions/dm-image2/README.md +0 -33
  54. package/extensions/dm-subagents/CHANGELOG.md +0 -1211
  55. package/extensions/dm-subagents/README.md +0 -29
  56. package/extensions/dm-subagents/biome.json +0 -26
  57. package/extensions/dm-subagents/tsconfig.json +0 -18
  58. package/extensions/dm-tasks/README.md +0 -30
  59. package/extensions/dm-tasks/biome.json +0 -26
  60. package/extensions/dm-tasks/tsconfig.json +0 -14
  61. package/extensions/dm-usage/README.md +0 -29
  62. package/extensions/greedysearch-dm/README.md +0 -222
@@ -1,12 +1,12 @@
1
- import{spawn as ve}from"node:child_process";import{basename as B}from"node:path";function H(t=process.env,e=process.execPath){let i=t.GREEDY_SEARCH_NODE||t.NODE_BINARY||t.NODE;if(i?.trim())return i.trim();let o=B(e||"").toLowerCase();if(o==="node"||o==="node.exe")return e;return"node"}import{existsSync as O,mkdirSync as V,readFileSync as k,writeFileSync as F}from"node:fs";import{homedir as z}from"node:os";import{join as M}from"node:path";import{tmpdir as T}from"node:os";var N=`${T().replaceAll("\\","/")}/greedysearch-chrome-profile`,we=`${N}/DevToolsActivePort`,Ue=`${T().replaceAll("\\","/")}/cdp-pages.json`,We=`${T().replaceAll("\\","/")}/greedysearch-chrome-mode`,De=`${T().replaceAll("\\","/")}/greedysearch-visible-recovery.jsonl`,w=M(z(),".dm"),E=M(w,"greedyconfig"),U=["perplexity","google","chatgpt"],W="gemini";function ee(){try{if(O(E)){let t=k(E,"utf8"),e=JSON.parse(t);if(Array.isArray(e.engines)&&e.engines.length>0&&e.engines.every((i)=>typeof i==="string")){let i=e.engines.filter((s)=>y[s]),o=e.engines.filter((s)=>!y[s]);if(o.length>0)process.stderr.write(`[greedysearch] Warning: ignoring unknown engine(s) in ${E}: ${o.join(", ")}
1
+ import{spawn as ve}from"node:child_process";import{basename as B}from"node:path";function H(t=process.env,e=process.execPath){let i=t.GREEDY_SEARCH_NODE||t.NODE_BINARY||t.NODE;if(i?.trim())return i.trim();let n=B(e||"").toLowerCase();if(n==="node"||n==="node.exe")return e;return"node"}import{existsSync as O,mkdirSync as V,readFileSync as k,writeFileSync as F}from"node:fs";import{homedir as z}from"node:os";import{join as M}from"node:path";import{tmpdir as T}from"node:os";var N=`${T().replaceAll("\\","/")}/greedysearch-chrome-profile`,we=`${N}/DevToolsActivePort`,Ue=`${T().replaceAll("\\","/")}/cdp-pages.json`,We=`${T().replaceAll("\\","/")}/greedysearch-chrome-mode`,De=`${T().replaceAll("\\","/")}/greedysearch-visible-recovery.jsonl`,w=M(z(),".dm"),E=M(w,"greedyconfig"),U=["perplexity","google","chatgpt"],W="gemini";function ee(){try{if(O(E)){let t=k(E,"utf8"),e=JSON.parse(t);if(Array.isArray(e.engines)&&e.engines.length>0&&e.engines.every((i)=>typeof i==="string")){let i=e.engines.filter((s)=>y[s]),n=e.engines.filter((s)=>!y[s]);if(n.length>0)process.stderr.write(`[greedysearch] Warning: ignoring unknown engine(s) in ${E}: ${n.join(", ")}
2
2
  [greedysearch] Available engines: ${Object.keys(y).join(", ")}
3
3
  `);if(i.length>0)return i;process.stderr.write(`[greedysearch] Warning: no valid engines in ${E}, falling back to defaults: ${U.join(", ")}
4
4
  `)}}}catch{}return U}function ie(){try{if(!O(w))V(w,{recursive:!0});if(!O(E))F(E,JSON.stringify({engines:U,synthesizer:W},null,2)+`
5
5
  `,"utf8")}catch{}}ie();var C=["gemini","chatgpt"];function te(){try{if(O(E)){let t=k(E,"utf8"),e=JSON.parse(t);if(typeof e.synthesizer==="string"){let i=e.synthesizer.toLowerCase();if(C.includes(i))return i;process.stderr.write(`[greedysearch] Warning: unknown synthesizer "${e.synthesizer}" in ${E}
6
6
  [greedysearch] Available synthesizers: ${C.join(", ")}
7
7
  [greedysearch] Falling back to default: ${W}
8
- `)}}}catch{}return W}var y={perplexity:"perplexity.mjs",p:"perplexity.mjs",bing:"bing-copilot.mjs",b:"bing-copilot.mjs",google:"google-ai.mjs",g:"google-ai.mjs",gemini:"gemini.mjs",gem:"gemini.mjs",chatgpt:"chatgpt.mjs",gpt:"chatgpt.mjs","semantic-scholar":"semantic-scholar.mjs",semanticscholar:"semantic-scholar.mjs",s2:"semantic-scholar.mjs",logically:"logically.mjs",log:"logically.mjs"},ne=ee();var Le=te(),He=Math.max(1,Number.parseInt(process.env.GREEDY_FETCH_CONCURRENCY||"5",10)||5);process.env.CDP_PROFILE_DIR=N;var oe=["fbclid","gclid","ref","ref_src","ref_url","source","utm_campaign","utm_content","utm_medium","utm_source","utm_term"],se=["dev.to","hashnode.com","medium.com","reddit.com","stackoverflow.com","stackexchange.com","substack.com"],le=["arstechnica.com","techcrunch.com","theverge.com","venturebeat.com","wired.com","zdnet.com"],J=["facebook.com","instagram.com","linkedin.com","pinterest.com","tiktok.com","twitter.com","x.com"];function v(t="",e=240){let i=String(t).replaceAll(/\s+/g," ").trim();if(i.length<=e)return i;let o=i.slice(0,e),s=o.lastIndexOf(" ");return s>0?`${o.slice(0,s)}...`:`${o}...`}function D(t=""){let e=v(t,180);if(!e)return"";if(/^https?:\/\//i.test(e))return"";let i=e.split(/\s+/).filter(Boolean).length,o=/[A-Z]/.test(e),s=/\d/.test(e);return e===e.toLowerCase()&&i<=4&&!o&&!s?"":e}function G(t="",e=""){let i=D(t),o=D(e);if(!o)return i;if(!i)return o;let s=/^https?:\/\//i.test(i),r=/^https?:\/\//i.test(o);if(s&&!r)return o;if(!s&&r)return i;return o.length>i.length?o:i}function ce(t){if(!t)return null;try{let e=new URL(t);if(!["http:","https:"].includes(e.protocol))return null;if(e.hash="",e.hostname=e.hostname.toLowerCase(),e.protocol==="https:"&&e.port==="443"||e.protocol==="http:"&&e.port==="80")e.port="";for(let s of[...e.searchParams.keys()]){let r=s.toLowerCase();if(oe.includes(r)||r.startsWith("utm_"))e.searchParams.delete(s)}e.searchParams.sort();let i=e.pathname.replace(/\/{1,10}$/,"")||"/";e.pathname=i;let o=e.toString();return i==="/"?o.replace(/\/$/,""):o}catch{return null}}function re(t){try{return new URL(t).hostname.toLowerCase().replace(/^www\./,"")}catch{return""}}function _(t,e){return e.some((i)=>t===i||t.endsWith(`.${i}`))}function ae(t,e="",i=""){let o=e.toLowerCase(),s=i.toLowerCase();if(t==="github.com"||t==="gitlab.com")return"repo";if(t==="arxiv.org"||t==="doi.org"||t==="semanticscholar.org"||t.endsWith(".semanticscholar.org")||s.includes("/paper/")||s.includes("/pdf/"))return"academic";if(_(t,J))return"social";if(_(t,se))return"community";if(_(t,le))return"news";if(t.startsWith("docs.")||t.startsWith("developer.")||t.startsWith("developers.")||t.startsWith("api.")||o.includes("documentation")||o.includes("docs")||o.includes("reference")||s.includes("/docs/")||s.includes("/reference/")||s.includes("/api/"))return"official-docs";if(t.startsWith("blog.")||s.includes("/blog/"))return"maintainer-blog";return"website"}function fe(t){switch(t){case"official-docs":return 5;case"repo":return 4;case"academic":return 4;case"maintainer-blog":return 3;case"website":return 2;case"community":return 1;case"news":return 0;case"social":return-6;default:return 0}}function ge(t){let e=Object.values(t.perEngine||{}).map((i)=>i?.rank||99);return e.length?Math.min(...e):99}var pe=["reddit.com","news.ycombinator.com","lobste.rs"];function R(t){return t.smartScore*3+t.engineCount*5+fe(t.sourceType)*2+Math.max(0,7-ge(t))}function ue(t){let e=t.toLowerCase(),i=[];if(e.includes("openai")||e.includes("gpt")||e.includes("chatgpt"))i.push("openai.com","platform.openai.com","help.openai.com");if(e.includes("anthropic")||e.includes("claude"))i.push("anthropic.com","docs.anthropic.com");if(e.includes("bun"))i.push("bun.sh","bun.com");if(e.includes("next.js")||e.includes("nextjs"))i.push("nextjs.org","vercel.com");if(e.includes("playwright"))i.push("playwright.dev");if(e.includes("supabase"))i.push("supabase.com","supabase.io");if(e.includes("prisma"))i.push("prisma.io");if(e.includes("tailwind"))i.push("tailwindcss.com");if(e.includes("vite"))i.push("vitejs.dev","vite.dev");if(e.includes("astro"))i.push("astro.build");if(e.includes("svelte"))i.push("svelte.dev");if(e.includes("solid"))i.push("solidjs.com");if(e.includes("vue")||e.includes("nuxt"))i.push("vuejs.org","nuxt.com");if(e.includes("react")||e.includes("react native"))i.push("react.dev","reactnative.dev");if(e.includes("angular"))i.push("angular.io","angular.dev");if(e.includes("node.js")||e.includes("nodejs"))i.push("nodejs.org","nodejs.dev","npmjs.com");if(/\bgo\b/.test(e)||e.includes("golang"))i.push("go.dev","golang.org","pkg.go.dev");if(e.includes("deno"))i.push("deno.land","deno.com");if(e.includes("fresh"))i.push("fresh.deno.dev");if(e.includes("typescript")||e.includes("ts"))i.push("typescriptlang.org");if(e.includes("python"))i.push("python.org","docs.python.org");if(e.includes("rust"))i.push("rust-lang.org","docs.rs","crates.io");if(e.includes("zig"))i.push("ziglang.org");if(e.includes("docker"))i.push("docker.com","docs.docker.com","hub.docker.com");if(e.includes("kubernetes")||e.includes("k8s"))i.push("kubernetes.io","k8s.io");if(e.includes("postgres")||e.includes("postgresql"))i.push("postgresql.org","neon.tech","supabase.com");if(e.includes("redis"))i.push("redis.io");if(e.includes("sqlite"))i.push("sqlite.org");if(e.includes("cloudflare"))i.push("developers.cloudflare.com","cloudflare.com");if(e.includes("vercel"))i.push("vercel.com","nextjs.org");if(e.includes("netlify"))i.push("netlify.com","docs.netlify.com");if(e.includes("stripe"))i.push("stripe.com","docs.stripe.com");if(e.includes("github"))i.push("github.com","docs.github.com");if(e.includes("gitlab"))i.push("gitlab.com","docs.gitlab.com");if(e.includes("aws"))i.push("aws.amazon.com","docs.aws.amazon.com");if(e.includes("azure"))i.push("azure.microsoft.com","learn.microsoft.com");if(e.includes("gcp")||e.includes("google cloud"))i.push("cloud.google.com","developers.google.com");if(e.includes("gemini")||e.includes("google ai"))i.push("ai.google.dev","developers.google.com");for(let o of J){let s=o.replace(/\.com$/,"");if(e.includes(s))i.push(o)}return[...new Set(i)]}function I(t,e){return t===e||t.endsWith(`.${e}`)}function Y(t,e=""){let i=new Map,o=Object.keys(t||{}).filter((n)=>!n.startsWith("_")),s=ue(e);for(let n of o){let c=t[n];if(!c?.sources)continue;for(let a=0;a<c.sources.length;a++){let h=c.sources[a],g=ce(h.url);if(!g||g.length<10)continue;let j=D(h.title||""),u=re(g),d=ae(u,j,g),m=0;if(s.some(($)=>I(u,$)))m+=10;if(d==="official-docs")m+=3;let Q=g.toLowerCase();if(/\/docs\/|\/documentation\/|\.dev\/|\/api\/|\/reference\//.test(Q))m+=2;let q=s.some(($)=>I(u,$));if(d==="social"&&!q)m-=20;if(s.length>0){if(_(u,pe))m-=3;else if(d==="community"&&!_(u,["stackoverflow.com","stackexchange.com"]))m-=1}let p=i.get(g)||{id:"",canonicalUrl:g,displayUrl:h.url||g,domain:u,title:"",engines:[],engineCount:0,perEngine:{},sourceType:d,isOfficial:d==="official-docs",smartScore:0};if(p.title=G(p.title,j),p.displayUrl=p.displayUrl||h.url||g,p.sourceType=p.sourceType||d,p.isOfficial=p.isOfficial||d==="official-docs",p.smartScore=Math.max(p.smartScore,m),!p.engines.includes(n))p.engines.push(n);p.perEngine[n]={rank:a+1,title:G(p.perEngine[n]?.title||"",j)},i.set(g,p)}}let r=Array.from(i.values()).map((n)=>({...n,engineCount:n.engines.length})),f=r.filter((n)=>n.sourceType!=="social"),l=r.filter((n)=>n.sourceType==="social");return f.sort((n,c)=>{let a=R(c)-R(n);if(a!==0)return a;return n.domain.localeCompare(c.domain)}),l.sort((n,c)=>{let a=R(c)-R(n);if(a!==0)return a;return n.domain.localeCompare(c.domain)}),[...f,...l].slice(0,12).map((n,c)=>({...n,id:`S${c+1}`,title:n.title||n.domain||n.canonicalUrl}))}function me(t){let e="",i=!1,o=!1;for(let s of String(t)){if(o){e+=s,o=!1;continue}if(s==="\\"){e+=s,o=!0;continue}if(s==='"'){i=!i,e+=s;continue}if(i&&s===`
9
- `)e+="\\n";else if(i&&s==="\r")e+="\\r";else if(i&&s==="\t")e+="\\t";else e+=s}return e}function Z(t){if(!t)return null;let e=String(t).trim(),i=e.indexOf("BEGIN_JSON"),o=e.indexOf("END_JSON");if(i!==-1&&o!==-1&&i<o)e=e.slice(i+10,o).trim();else{let l=e.indexOf("{");if(l>0)e=e.slice(l)}let s=[e,e.replace(/^```json\s*/i,"").replace(/^```\s*/i,"").replace(/```$/i,"").trim()],r=e.indexOf("{"),f=e.lastIndexOf("}");if(r!==-1&&f!==-1&&r<f)s.push(e.slice(r,f+1));for(let l of[...s]){let n=me(l);if(n!==l)s.push(n)}for(let l of s)try{return JSON.parse(l)}catch{}return null}function x(t,e,i=""){let o=new Set(e.map((n)=>n.id)),s=["high","medium","low","mixed","conflicting"].includes(t?.agreement?.level)?t.agreement.level:"mixed",r=Array.isArray(t?.claims)?t.claims.map((n)=>({claim:v(n?.claim||"",260),support:["strong","moderate","weak","conflicting"].includes(n?.support)?n.support:"moderate",sourceIds:Array.isArray(n?.sourceIds)?n.sourceIds.filter((c)=>o.has(c)):[]})).filter((n)=>n.claim):[],f=Array.isArray(t?.recommendedSources)?t.recommendedSources.filter((n)=>o.has(n)).slice(0,6):[],l="";if(i){let n=i.indexOf("{"),c=i.lastIndexOf("}");if(n!==-1&&c!==-1&&n<c)l=i.slice(n,c+1);else l=i}return{answer:v(t?.answer||l||i,4000),agreement:{level:s,summary:v(t?.agreement?.summary||"",280)},differences:Array.isArray(t?.differences)?t.differences.map((n)=>v(n,220)).filter(Boolean).slice(0,5):[],caveats:Array.isArray(t?.caveats)?t.caveats.map((n)=>v(n,220)).filter(Boolean).slice(0,5):[],claims:r,recommendedSources:f}}function A(t,e,i,{grounded:o=!1}={}){let s={};for(let l of["perplexity","bing","google"]){let n=e[l];if(!n)continue;if(n.error){s[l]={status:"error",error:String(n.error)};continue}s[l]={status:"ok",answer:v(n.answer||"",o?4500:2200),sourceIds:i.filter((c)=>c.engines.includes(l)).sort((c,a)=>(c.perEngine[l]?.rank||99)-(a.perEngine[l]?.rank||99)).map((c)=>c.id).slice(0,6)}}let r=o?700:300,f=i.slice(0,o?10:8).map((l)=>({id:l.id,title:l.title,domain:l.domain,canonicalUrl:l.canonicalUrl,sourceType:l.sourceType,isOfficial:l.isOfficial,engines:l.engines,engineCount:l.engineCount,fetch:l.fetch?.attempted?{ok:l.fetch.ok,publishedTime:l.fetch.publishedTime||"",byline:l.fetch.byline||"",snippet:v(l.fetch.snippet||"",r)}:void 0}));return["You are a research synthesizer. Combine these search engine results into a single authoritative answer.","",`Query: ${t}`,"",`Engine summaries:
8
+ `)}}}catch{}return W}var y={perplexity:"perplexity.mjs",p:"perplexity.mjs",bing:"bing-copilot.mjs",b:"bing-copilot.mjs",google:"google-ai.mjs",g:"google-ai.mjs",gemini:"gemini.mjs",gem:"gemini.mjs",chatgpt:"chatgpt.mjs",gpt:"chatgpt.mjs","semantic-scholar":"semantic-scholar.mjs",semanticscholar:"semantic-scholar.mjs",s2:"semantic-scholar.mjs",logically:"logically.mjs",log:"logically.mjs"},ne=ee();var Le=te(),He=Math.max(1,Number.parseInt(process.env.GREEDY_FETCH_CONCURRENCY||"5",10)||5);process.env.CDP_PROFILE_DIR=N;var oe=["fbclid","gclid","ref","ref_src","ref_url","source","utm_campaign","utm_content","utm_medium","utm_source","utm_term"],se=["dev.to","hashnode.com","medium.com","reddit.com","stackoverflow.com","stackexchange.com","substack.com"],le=["arstechnica.com","techcrunch.com","theverge.com","venturebeat.com","wired.com","zdnet.com"],J=["facebook.com","instagram.com","linkedin.com","pinterest.com","tiktok.com","twitter.com","x.com"];function v(t="",e=240){let i=String(t).replaceAll(/\s+/g," ").trim();if(i.length<=e)return i;let n=i.slice(0,e),s=n.lastIndexOf(" ");return s>0?`${n.slice(0,s)}...`:`${n}...`}function D(t=""){let e=v(t,180);if(!e)return"";if(/^https?:\/\//i.test(e))return"";let i=e.split(/\s+/).filter(Boolean).length,n=/[A-Z]/.test(e),s=/\d/.test(e);return e===e.toLowerCase()&&i<=4&&!n&&!s?"":e}function G(t="",e=""){let i=D(t),n=D(e);if(!n)return i;if(!i)return n;let s=/^https?:\/\//i.test(i),r=/^https?:\/\//i.test(n);if(s&&!r)return n;if(!s&&r)return i;return n.length>i.length?n:i}function ce(t){if(!t)return null;try{let e=new URL(t);if(!["http:","https:"].includes(e.protocol))return null;if(e.hash="",e.hostname=e.hostname.toLowerCase(),e.protocol==="https:"&&e.port==="443"||e.protocol==="http:"&&e.port==="80")e.port="";for(let s of[...e.searchParams.keys()]){let r=s.toLowerCase();if(oe.includes(r)||r.startsWith("utm_"))e.searchParams.delete(s)}e.searchParams.sort();let i=e.pathname.replace(/\/{1,10}$/,"")||"/";e.pathname=i;let n=e.toString();return i==="/"?n.replace(/\/$/,""):n}catch{return null}}function re(t){try{return new URL(t).hostname.toLowerCase().replace(/^www\./,"")}catch{return""}}function _(t,e){return e.some((i)=>t===i||t.endsWith(`.${i}`))}function ae(t,e="",i=""){let n=e.toLowerCase(),s=i.toLowerCase();if(t==="github.com"||t==="gitlab.com")return"repo";if(t==="arxiv.org"||t==="doi.org"||t==="semanticscholar.org"||t.endsWith(".semanticscholar.org")||s.includes("/paper/")||s.includes("/pdf/"))return"academic";if(_(t,J))return"social";if(_(t,se))return"community";if(_(t,le))return"news";if(t.startsWith("docs.")||t.startsWith("developer.")||t.startsWith("developers.")||t.startsWith("api.")||n.includes("documentation")||n.includes("docs")||n.includes("reference")||s.includes("/docs/")||s.includes("/reference/")||s.includes("/api/"))return"official-docs";if(t.startsWith("blog.")||s.includes("/blog/"))return"maintainer-blog";return"website"}function fe(t){switch(t){case"official-docs":return 5;case"repo":return 4;case"academic":return 4;case"maintainer-blog":return 3;case"website":return 2;case"community":return 1;case"news":return 0;case"social":return-6;default:return 0}}function ge(t){let e=Object.values(t.perEngine||{}).map((i)=>i?.rank||99);return e.length?Math.min(...e):99}var pe=["reddit.com","news.ycombinator.com","lobste.rs"];function R(t){return t.smartScore*3+t.engineCount*5+fe(t.sourceType)*2+Math.max(0,7-ge(t))}function ue(t){let e=t.toLowerCase(),i=[];if(e.includes("openai")||e.includes("gpt")||e.includes("chatgpt"))i.push("openai.com","platform.openai.com","help.openai.com");if(e.includes("anthropic")||e.includes("claude"))i.push("anthropic.com","docs.anthropic.com");if(e.includes("bun"))i.push("bun.sh","bun.com");if(e.includes("next.js")||e.includes("nextjs"))i.push("nextjs.org","vercel.com");if(e.includes("playwright"))i.push("playwright.dev");if(e.includes("supabase"))i.push("supabase.com","supabase.io");if(e.includes("prisma"))i.push("prisma.io");if(e.includes("tailwind"))i.push("tailwindcss.com");if(e.includes("vite"))i.push("vitejs.dev","vite.dev");if(e.includes("astro"))i.push("astro.build");if(e.includes("svelte"))i.push("svelte.dev");if(e.includes("solid"))i.push("solidjs.com");if(e.includes("vue")||e.includes("nuxt"))i.push("vuejs.org","nuxt.com");if(e.includes("react")||e.includes("react native"))i.push("react.dev","reactnative.dev");if(e.includes("angular"))i.push("angular.io","angular.dev");if(e.includes("node.js")||e.includes("nodejs"))i.push("nodejs.org","nodejs.dev","npmjs.com");if(/\bgo\b/.test(e)||e.includes("golang"))i.push("go.dev","golang.org","pkg.go.dev");if(e.includes("deno"))i.push("deno.land","deno.com");if(e.includes("fresh"))i.push("fresh.deno.dev");if(e.includes("typescript")||e.includes("ts"))i.push("typescriptlang.org");if(e.includes("python"))i.push("python.org","docs.python.org");if(e.includes("rust"))i.push("rust-lang.org","docs.rs","crates.io");if(e.includes("zig"))i.push("ziglang.org");if(e.includes("docker"))i.push("docker.com","docs.docker.com","hub.docker.com");if(e.includes("kubernetes")||e.includes("k8s"))i.push("kubernetes.io","k8s.io");if(e.includes("postgres")||e.includes("postgresql"))i.push("postgresql.org","neon.tech","supabase.com");if(e.includes("redis"))i.push("redis.io");if(e.includes("sqlite"))i.push("sqlite.org");if(e.includes("cloudflare"))i.push("developers.cloudflare.com","cloudflare.com");if(e.includes("vercel"))i.push("vercel.com","nextjs.org");if(e.includes("netlify"))i.push("netlify.com","docs.netlify.com");if(e.includes("stripe"))i.push("stripe.com","docs.stripe.com");if(e.includes("github"))i.push("github.com","docs.github.com");if(e.includes("gitlab"))i.push("gitlab.com","docs.gitlab.com");if(e.includes("aws"))i.push("aws.amazon.com","docs.aws.amazon.com");if(e.includes("azure"))i.push("azure.microsoft.com","learn.microsoft.com");if(e.includes("gcp")||e.includes("google cloud"))i.push("cloud.google.com","developers.google.com");if(e.includes("gemini")||e.includes("google ai"))i.push("ai.google.dev","developers.google.com");for(let n of J){let s=n.replace(/\.com$/,"");if(e.includes(s))i.push(n)}return[...new Set(i)]}function I(t,e){return t===e||t.endsWith(`.${e}`)}function Y(t,e=""){let i=new Map,n=Object.keys(t||{}).filter((o)=>!o.startsWith("_")),s=ue(e);for(let o of n){let c=t[o];if(!c?.sources)continue;for(let a=0;a<c.sources.length;a++){let h=c.sources[a],g=ce(h.url);if(!g||g.length<10)continue;let j=D(h.title||""),u=re(g),d=ae(u,j,g),m=0;if(s.some(($)=>I(u,$)))m+=10;if(d==="official-docs")m+=3;let Q=g.toLowerCase();if(/\/docs\/|\/documentation\/|\.dev\/|\/api\/|\/reference\//.test(Q))m+=2;let q=s.some(($)=>I(u,$));if(d==="social"&&!q)m-=20;if(s.length>0){if(_(u,pe))m-=3;else if(d==="community"&&!_(u,["stackoverflow.com","stackexchange.com"]))m-=1}let p=i.get(g)||{id:"",canonicalUrl:g,displayUrl:h.url||g,domain:u,title:"",engines:[],engineCount:0,perEngine:{},sourceType:d,isOfficial:d==="official-docs",smartScore:0};if(p.title=G(p.title,j),p.displayUrl=p.displayUrl||h.url||g,p.sourceType=p.sourceType||d,p.isOfficial=p.isOfficial||d==="official-docs",p.smartScore=Math.max(p.smartScore,m),!p.engines.includes(o))p.engines.push(o);p.perEngine[o]={rank:a+1,title:G(p.perEngine[o]?.title||"",j)},i.set(g,p)}}let r=Array.from(i.values()).map((o)=>({...o,engineCount:o.engines.length})),f=r.filter((o)=>o.sourceType!=="social"),l=r.filter((o)=>o.sourceType==="social");return f.sort((o,c)=>{let a=R(c)-R(o);if(a!==0)return a;return o.domain.localeCompare(c.domain)}),l.sort((o,c)=>{let a=R(c)-R(o);if(a!==0)return a;return o.domain.localeCompare(c.domain)}),[...f,...l].slice(0,12).map((o,c)=>({...o,id:`S${c+1}`,title:o.title||o.domain||o.canonicalUrl}))}function me(t){let e="",i=!1,n=!1;for(let s of String(t)){if(n){e+=s,n=!1;continue}if(s==="\\"){e+=s,n=!0;continue}if(s==='"'){i=!i,e+=s;continue}if(i&&s===`
9
+ `)e+="\\n";else if(i&&s==="\r")e+="\\r";else if(i&&s==="\t")e+="\\t";else e+=s}return e}function Z(t){if(!t)return null;let e=String(t).trim(),i=e.indexOf("BEGIN_JSON"),n=e.indexOf("END_JSON");if(i!==-1&&n!==-1&&i<n)e=e.slice(i+10,n).trim();else{let l=e.indexOf("{");if(l>0)e=e.slice(l)}let s=[e,e.replace(/^```json\s*/i,"").replace(/^```\s*/i,"").replace(/```$/i,"").trim()],r=e.indexOf("{"),f=e.lastIndexOf("}");if(r!==-1&&f!==-1&&r<f)s.push(e.slice(r,f+1));for(let l of[...s]){let o=me(l);if(o!==l)s.push(o)}for(let l of s)try{return JSON.parse(l)}catch{}return null}function x(t,e,i=""){let n=new Set(e.map((o)=>o.id)),s=["high","medium","low","mixed","conflicting"].includes(t?.agreement?.level)?t.agreement.level:"mixed",r=Array.isArray(t?.claims)?t.claims.map((o)=>({claim:v(o?.claim||"",260),support:["strong","moderate","weak","conflicting"].includes(o?.support)?o.support:"moderate",sourceIds:Array.isArray(o?.sourceIds)?o.sourceIds.filter((c)=>n.has(c)):[]})).filter((o)=>o.claim):[],f=Array.isArray(t?.recommendedSources)?t.recommendedSources.filter((o)=>n.has(o)).slice(0,6):[],l="";if(i){let o=i.indexOf("{"),c=i.lastIndexOf("}");if(o!==-1&&c!==-1&&o<c)l=i.slice(o,c+1);else l=i}return{answer:v(t?.answer||l||i,4000),agreement:{level:s,summary:v(t?.agreement?.summary||"",280)},differences:Array.isArray(t?.differences)?t.differences.map((o)=>v(o,220)).filter(Boolean).slice(0,5):[],caveats:Array.isArray(t?.caveats)?t.caveats.map((o)=>v(o,220)).filter(Boolean).slice(0,5):[],claims:r,recommendedSources:f}}function A(t,e,i,{grounded:n=!1}={}){let s={};for(let l of["perplexity","bing","google"]){let o=e[l];if(!o)continue;if(o.error){s[l]={status:"error",error:String(o.error)};continue}s[l]={status:"ok",answer:v(o.answer||"",n?4500:2200),sourceIds:i.filter((c)=>c.engines.includes(l)).sort((c,a)=>(c.perEngine[l]?.rank||99)-(a.perEngine[l]?.rank||99)).map((c)=>c.id).slice(0,6)}}let r=n?700:300,f=i.slice(0,n?10:8).map((l)=>({id:l.id,title:l.title,domain:l.domain,canonicalUrl:l.canonicalUrl,sourceType:l.sourceType,isOfficial:l.isOfficial,engines:l.engines,engineCount:l.engineCount,fetch:l.fetch?.attempted?{ok:l.fetch.ok,publishedTime:l.fetch.publishedTime||"",byline:l.fetch.byline||"",snippet:v(l.fetch.snippet||"",r)}:void 0}));return["You are a research synthesizer. Combine these search engine results into a single authoritative answer.","",`Query: ${t}`,"",`Engine summaries:
10
10
  ${JSON.stringify(s,null,2)}`,"",`Source registry:
11
11
  ${JSON.stringify(f,null,2)}`,"","Instructions:","- Write a clear, direct answer in markdown (use headers/bullets where they help readability)","- Cite sources inline as [S1], [S2] etc. when making specific claims","- Prefer sources with content (fetch.ok=true and non-empty snippet) for citations","- Note where the engines agree or meaningfully disagree","- List any important caveats or limitations","- recommendedSources: the 2-4 source IDs most worth reading for this query","","Respond ONLY with a JSON object wrapped in BEGIN_JSON / END_JSON markers:","","BEGIN_JSON",JSON.stringify({answer:"<your markdown answer here>",agreement:{level:"high|medium|mixed|conflicting",summary:"<one sentence>"},differences:["<notable difference between engines, if any>"],caveats:["<important caveat or limitation>"],recommendedSources:["S1","S2"]},null,2),"END_JSON"].join(`
12
- `)}import{existsSync as S}from"node:fs";import{dirname as he,join as b}from"node:path";import{fileURLToPath as de}from"node:url";function P(t){return de(new URL(".",t)).replace(/^\/([A-Z]:)/,"$1")}function Ee(t,e=S){let i=new Set;for(let o of t.filter(Boolean)){if(i.has(o))continue;if(i.add(o),e(o))return o}return t.filter(Boolean).at(-1)}function K(t,{moduleDir:e,entrypoint:i=process.argv[1],env:o=process.env,exists:s=S}={}){let r=i?he(i):null,f=o.GREEDY_SEARCH_EXTENSION_DIR?.trim()||null,l=[e?b(e,"..","..","extractors",t):null,e?b(e,"..","extractors",t):null,f?b(f,"extractors",t):null,r?b(r,"..","extractors",t):null];return Ee(l,s)}var je=P(import.meta.url),Ce={gemini:"gemini.mjs",chatgpt:"chatgpt.mjs"},_e={gemini:"https://gemini.google.com/app",chatgpt:"https://chatgpt.com/"};function L(t="gemini"){let e=String(t||"gemini").toLowerCase();if(e==="gem")return"gemini";if(e==="gpt")return"chatgpt";return e}function Be(t="gemini"){return _e[L(t)]||"about:blank"}async function X(t,e,{tabPrefix:i=null,timeoutMs:o=180000,visible:s=null}={}){let r=L(t),f=Ce[r];if(!f||!C.includes(r))throw Error(`Unsupported synthesizer "${t}". Supported: ${C.join(", ")}`);return new Promise((l,n)=>{let c=i?["--tab",String(i)]:[],a=K(f,{moduleDir:je}),h={...process.env,CDP_PROFILE_DIR:N};if(s!==!0)delete h.GREEDY_SEARCH_VISIBLE,delete h.GREEDY_SEARCH_ALWAYS_VISIBLE;else h.GREEDY_SEARCH_VISIBLE="1",h.GREEDY_SEARCH_ALWAYS_VISIBLE="1";let g=ve(H(),[a,"--stdin",...c],{stdio:["pipe","pipe","pipe"],env:h});g.stdin.write(e),g.stdin.end();let j="",u="";g.stdout.on("data",(m)=>j+=m),g.stderr.on("data",(m)=>u+=m);let d=setTimeout(()=>{g.kill(),n(Error(`${r} prompt timed out after ${o/1000}s`))},o);g.on("close",(m)=>{if(clearTimeout(d),m!==0){n(Error(u.trim()||`${r} extractor failed`));return}try{l(JSON.parse(j.trim()))}catch{n(Error(`bad JSON from ${r}: ${j.slice(0,100)}`))}})})}async function Ve(t,e={}){return X("gemini",t,e)}async function Oe(t,e,{grounded:i=!1,tabPrefix:o=null,visible:s=null,synthesizer:r="gemini"}={}){let f=L(r),l=Array.isArray(e._sources)?e._sources:Y(e),n=A(t,e,l,{grounded:i}),c=await X(f,n,{tabPrefix:o,timeoutMs:180000,visible:s}),a=Z(c.answer||""),g=a&&["answer","agreement","claims","differences","caveats"].some((u)=>(u in a));if(a&&["perplexity","bing","google","chatgpt","gemini"].some((u)=>(u in a))&&!g)a=null;return{...x(a,l,c.answer||""),rawAnswer:c.answer||"",synthesizedBy:f,synthesizerSources:c.sources||[],geminiSources:f==="gemini"?c.sources||[]:[]}}async function Fe(t,e,i={}){return Oe(t,e,{...i,synthesizer:"gemini"})}export{Fe as synthesizeWithGemini,Oe as synthesizeResults,X as runSynthesisPrompt,Ve as runGeminiPrompt,L as normalizeSynthesizer,Be as getSynthesisStartUrl};
12
+ `)}import{existsSync as S}from"node:fs";import{dirname as he,join as b}from"node:path";import{fileURLToPath as de}from"node:url";function P(t){return de(new URL(".",t)).replace(/^\/([A-Z]:)/,"$1")}function Ee(t,e=S){let i=new Set;for(let n of t.filter(Boolean)){if(i.has(n))continue;if(i.add(n),e(n))return n}return t.filter(Boolean).at(-1)}function K(t,{moduleDir:e,entrypoint:i=process.argv[1],env:n=process.env,exists:s=S}={}){let r=i?he(i):null,f=n.GREEDY_SEARCH_EXTENSION_DIR?.trim()||null,l=[e?b(e,"..","..","extractors",t):null,e?b(e,"..","extractors",t):null,f?b(f,"extractors",t):null,r?b(r,"..","extractors",t):null];return Ee(l,s)}var je=P(import.meta.url),Ce={gemini:"gemini.mjs",chatgpt:"chatgpt.mjs"},_e={gemini:"https://gemini.google.com/app",chatgpt:"https://chatgpt.com/"};function L(t="gemini"){let e=String(t||"gemini").toLowerCase();if(e==="gem")return"gemini";if(e==="gpt")return"chatgpt";return e}function Be(t="gemini"){return _e[L(t)]||"about:blank"}async function X(t,e,{tabPrefix:i=null,timeoutMs:n=180000,visible:s=null}={}){let r=L(t),f=Ce[r];if(!f||!C.includes(r))throw Error(`Unsupported synthesizer "${t}". Supported: ${C.join(", ")}`);let l=K(f,{moduleDir:je});return new Promise((o,c)=>{let a=i?["--tab",String(i)]:[],h={...process.env,CDP_PROFILE_DIR:N};if(s!==!0)delete h.GREEDY_SEARCH_VISIBLE,delete h.GREEDY_SEARCH_ALWAYS_VISIBLE;else h.GREEDY_SEARCH_VISIBLE="1",h.GREEDY_SEARCH_ALWAYS_VISIBLE="1";let g=ve(H(),[l,"--stdin",...a],{stdio:["pipe","pipe","pipe"],env:h});g.stdin.write(e),g.stdin.end();let j="",u="";g.stdout.on("data",(m)=>j+=m),g.stderr.on("data",(m)=>u+=m);let d=setTimeout(()=>{g.kill(),c(Error(`${r} prompt timed out after ${n/1000}s`))},n);g.on("close",(m)=>{if(clearTimeout(d),m!==0){c(Error(u.trim()||`${r} extractor failed`));return}try{o(JSON.parse(j.trim()))}catch{c(Error(`bad JSON from ${r}: ${j.slice(0,100)}`))}})})}async function Ve(t,e={}){return X("gemini",t,e)}async function Oe(t,e,{grounded:i=!1,tabPrefix:n=null,visible:s=null,synthesizer:r="gemini"}={}){let f=L(r),l=Array.isArray(e._sources)?e._sources:Y(e),o=A(t,e,l,{grounded:i}),c=await X(f,o,{tabPrefix:n,timeoutMs:180000,visible:s}),a=Z(c.answer||""),g=a&&["answer","agreement","claims","differences","caveats"].some((u)=>(u in a));if(a&&["perplexity","bing","google","chatgpt","gemini"].some((u)=>(u in a))&&!g)a=null;return{...x(a,l,c.answer||""),rawAnswer:c.answer||"",synthesizedBy:f,synthesizerSources:c.sources||[],geminiSources:f==="gemini"?c.sources||[]:[]}}async function Fe(t,e,i={}){return Oe(t,e,{...i,synthesizer:"gemini"})}export{Fe as synthesizeWithGemini,Oe as synthesizeResults,X as runSynthesisPrompt,Ve as runGeminiPrompt,L as normalizeSynthesizer,Be as getSynthesisStartUrl};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duckmind/dm-darwin-x64",
3
- "version": "0.48.5",
3
+ "version": "0.49.0",
4
4
  "description": "DuckMind (dm) binary payload for darwin x64",
5
5
  "license": "MIT",
6
6
  "os": [
@@ -1,142 +0,0 @@
1
- # dm-9router-ext
2
-
3
- [![npm](https://img.shields.io/npm/v/dm-9router-ext?color=blue)](https://www.npmjs.com/package/dm-9router-ext)
4
-
5
- DM extension for [9router](https://github.com/decolua/9router) — an open-source AI routing proxy.
6
-
7
- **Install:** `dm install npm:dm-9router-ext`
8
-
9
- Connects DM to your 9router instance via its OpenAI-compatible API, with dynamic model discovery and interactive configuration.
10
-
11
- ## Features
12
-
13
- - **Auto-discovery** — Fetches available models and combos from 9router on startup
14
- - **Dynamic provider** — Registers 9router as a DM provider with live model list
15
- - **DM-native streaming** — Uses DM's built-in OpenAI completions provider without overriding other providers
16
- - **Status commands** — `/9router-status`, `/9router-models`, `/9router-config`, `/9router-reload`
17
- - **User-wide persistence** — Configuration survives new DM instances via `~/.dm/agent/9router-config.json`
18
- - **Routing detection** — Captures upstream model info from response headers when available
19
-
20
- ## Installation
21
-
22
- ### npm (Recommended)
23
-
24
- ```bash
25
- dm install npm:dm-9router-ext
26
- ```
27
-
28
- ### Via local path
29
-
30
- ```bash
31
- # Clone or download the DM repo
32
- git clone https://github.com/que-nguyen/dm.git
33
-
34
- # Install locally
35
- dm install /path/to/dm-9router-ext
36
-
37
- # Or try without installing
38
- dm -e /path/to/dm-9router-ext
39
- ```
40
-
41
- ### Manual (copy to extensions)
42
-
43
- ```bash
44
- cp -r dm-9router-ext/src/index.ts ~/.dm/agent/extensions/dm-9router-ext.ts
45
- ```
46
-
47
- ## Configuration
48
-
49
- ### Environment Variables
50
-
51
- | Variable | Default | Description |
52
- |----------|---------|-------------|
53
- | `NINE_ROUTER_BASE_URL` | `http://localhost:20128` | Your 9router instance URL |
54
- | `NINE_ROUTER_API_KEY` | — | API key if 9router has `REQUIRE_API_KEY=true` |
55
-
56
- Set them in your shell profile or prefix your `dm` command:
57
-
58
- ```bash
59
- NINE_ROUTER_BASE_URL=http://my-vps:20128 NINE_ROUTER_API_KEY=nr-... dm
60
- ```
61
-
62
- ### Interactive Configuration
63
-
64
- Use the `/9router-config` command inside DM to set base URL and API key interactively. This is saved to `~/.dm/agent/9router-config.json` and is shared by new DM instances. Environment variables still take precedence when set.
65
-
66
- ```
67
- /9router-config
68
- ```
69
-
70
- ## Usage
71
-
72
- ### Selecting a 9router Model
73
-
74
- After the extension loads, 9router models are available in DM's model picker under the dedicated `9router/` provider namespace:
75
-
76
- ```
77
- /model 9router/cc/claude-opus-4-7
78
- ```
79
-
80
- Built-in providers remain separate. To use Ollama Cloud, OpenRouter, opencode-go, etc., select their normal provider/model entries (for example `ollama-cloud/...`), not a `9router/...` model.
81
-
82
- Or browse interactively:
83
-
84
- ```
85
- /9router-models
86
- ```
87
-
88
- ### Available Commands
89
-
90
- | Command | Description |
91
- |---------|-------------|
92
- | `/9router-status` | Show connection status, model count, and config |
93
- | `/9router-models` | Browse and select from available 9router models |
94
- | `/9router-config` | Interactively configure base URL and API key |
95
- | `/9router-reload` | Refresh model list from 9router |
96
-
97
- ### Available Tool
98
-
99
- The LLM can call `ninerouter_status` to check connection status and list models programmatically.
100
-
101
- ## How It Works
102
-
103
- ```
104
- ┌─────────┐ OpenAI-compatible ┌──────────┐ ┌─────────────┐
105
- │ DM │ ──────────────────────────▶│ 9router │ ──▶ │ Providers │
106
- │ │ /v1/chat/completions │ (proxy) │ │ (40+) │
107
- └─────────┘ └──────────┘ └─────────────┘
108
-
109
- │ 1. Fetches /v1/models on startup
110
- │ 2. Registers as provider "9router"
111
- │ 3. Uses DM AI's OpenAI-compatible implementation for only 9router models
112
- │ 4. Leaves built-in/non-9router model switching untouched
113
- ```
114
-
115
- ## Troubleshooting
116
-
117
- **"Failed to discover models from 9router"**
118
- - Check that 9router is running: `curl http://localhost:20128/v1/models`
119
- - Verify `NINE_ROUTER_BASE_URL` points to the correct host/port
120
- - If `REQUIRE_API_KEY=true`, set `NINE_ROUTER_API_KEY`
121
-
122
- **"No 9router models discovered"**
123
- - 9router may have no active providers. Open the dashboard and connect a provider.
124
- - Use `/9router-reload` to retry discovery.
125
-
126
- **Models not showing in `/model` selector**
127
- - Ensure the extension loaded: check for "9router connected" notification on startup
128
- - Run `/9router-reload` to retry discovery
129
- - Run `/reload` to refresh extensions
130
-
131
- **Built-in provider returns 401 after installing this extension**
132
- - Make sure the active model is the built-in provider (`ollama-cloud/...`, `openrouter/...`, etc.), not a `9router/...` route.
133
- - Re-run `/login` for the built-in provider if its subscription token expired.
134
- - This extension only registers provider id `9router`; it does not override built-in providers. If 9router is unreachable, the extension unregisters the `9router` provider instead of leaving an empty/broken provider around.
135
-
136
- ## Similar Projects
137
-
138
- - [omniroute-pi-extension](https://www.npmjs.com/package/omniroute-pi-extension) — DM extension for OmniRoute (a fork of 9router with additional features)
139
-
140
- ## License
141
-
142
- MIT
@@ -1,17 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "strict": true,
7
- "noEmit": true,
8
- "allowImportingTsExtensions": true,
9
- "skipLibCheck": true,
10
- "types": [
11
- "node"
12
- ]
13
- },
14
- "include": [
15
- "src/**/*.ts"
16
- ]
17
- }
@@ -1,226 +0,0 @@
1
- # dm-ask-user — Interactive Form Tool for DM
2
-
3
- A DM extension that registers a tool the LLM can call to ask the user structured questions using rich form controls: **radio buttons**, **checkboxes**, and **text inputs**.
4
-
5
- Instead of the LLM asking questions in plain text and waiting for a freeform response, this tool presents an interactive TUI form where each question is typed, validated, and returned as structured data.
6
-
7
- ## How It Works
8
-
9
- 1. **LLM calls the tool** — Passes a JSON schema of questions with types, options, and metadata.
10
- 2. **Form renders** — An interactive panel appears in the terminal with typed controls for each question.
11
- 3. **User answers** — Navigate between questions, select options, type text, toggle checkboxes.
12
- 4. **Structured return** — Answers are returned to the LLM in a clean, structured format.
13
-
14
- ## Question Types
15
-
16
- ### Radio (single-select)
17
-
18
- ```
19
- ❯ ◉ PostgreSQL
20
- ○ MySQL
21
- ○ SQLite
22
- ○ Other...
23
- ```
24
-
25
- Pick exactly one option. Press Enter to select. The "Other..." option opens a text editor for a custom answer.
26
-
27
- ### Checkbox (multi-select)
28
-
29
- ```
30
- ❯ ☑ Unit tests
31
- ☑ Integration tests
32
- ☐ E2E tests
33
- ☐ Other...
34
- ```
35
-
36
- Toggle multiple options with Space. The "Other..." option opens a text editor. Press Enter to advance.
37
-
38
- ### Text (free input)
39
-
40
- ```
41
- ┌─────────────────────────────────┐
42
- │ Describe the migration strategy │
43
- └─────────────────────────────────┘
44
- ```
45
-
46
- A full multi-line editor. Shift+Enter for newlines, Enter to submit.
47
-
48
- ## Tool Schema
49
-
50
- ```json
51
- {
52
- "title": "Project Setup",
53
- "description": "Let me configure the project based on your preferences",
54
- "questions": [
55
- {
56
- "id": "database",
57
- "type": "radio",
58
- "prompt": "Which database should we use?",
59
- "label": "Database",
60
- "options": [
61
- { "value": "postgres", "label": "PostgreSQL", "description": "Best for complex queries" },
62
- { "value": "mysql", "label": "MySQL", "description": "Widely supported" },
63
- { "value": "sqlite", "label": "SQLite", "description": "Lightweight, file-based" }
64
- ],
65
- "allowOther": true
66
- },
67
- {
68
- "id": "testing",
69
- "type": "checkbox",
70
- "prompt": "Which test types should we set up?",
71
- "label": "Testing",
72
- "options": [
73
- { "value": "unit", "label": "Unit tests" },
74
- { "value": "integration", "label": "Integration tests" },
75
- { "value": "e2e", "label": "E2E tests" }
76
- ],
77
- "allowOther": true
78
- },
79
- {
80
- "id": "notes",
81
- "type": "text",
82
- "prompt": "Any additional notes or requirements?",
83
- "label": "Notes",
84
- "required": false,
85
- "placeholder": "Type any extra context here..."
86
- }
87
- ]
88
- }
89
- ```
90
-
91
- ### Question Fields
92
-
93
- | Field | Type | Default | Description |
94
- | ------------- | --------------------------------- | ---------------------- | ----------------------------------------------------- |
95
- | `id` | `string` | _required_ | Unique identifier |
96
- | `type` | `"radio"` \| `"checkbox"` \| `"text"` | _required_ | Control type |
97
- | `prompt` | `string` | _required_ | The question text |
98
- | `label` | `string` | `Q1`, `Q2`... | Short label for tab bar |
99
- | `options` | `Option[]` | `[]` | Choices for radio/checkbox |
100
- | `allowOther` | `boolean` | `true` (radio/checkbox) | Show "Other..." option with text input |
101
- | `required` | `boolean` | `true` | Must be answered before submit |
102
- | `placeholder` | `string` | — | Placeholder text for text inputs |
103
- | `default` | `string` \| `string[]` | — | Default value(s) |
104
-
105
- ### Option Fields
106
-
107
- | Field | Type | Description |
108
- | ------------- | -------- | ---------------------------------- |
109
- | `value` | `string` | Value returned to the LLM |
110
- | `label` | `string` | Display label |
111
- | `description` | `string` | Help text shown below the label |
112
-
113
- ## Panel Interface
114
-
115
- ### Single Question
116
-
117
- ```
118
- ──────────────────────────────────────────────────────
119
- Which database should we use? [single-select]
120
- *required
121
-
122
- ❯ ◉ PostgreSQL
123
- Best for complex queries
124
- ○ MySQL
125
- Widely supported
126
- ○ SQLite
127
- Lightweight, file-based
128
- ○ Other...
129
-
130
- ↑↓ navigate • Enter select • Esc cancel
131
- ──────────────────────────────────────────────────────
132
- ```
133
-
134
- ### Multiple Questions (tab bar)
135
-
136
- ```
137
- ──────────────────────────────────────────────────────
138
- Project Setup
139
- Let me configure the project based on your preferences
140
-
141
- ✓ Database │· Testing │· Notes │✓ Submit
142
-
143
- Which test types should we set up? [multi-select]
144
- *required
145
-
146
- ❯ ☑ Unit tests
147
- ☑ Integration tests
148
- ☐ E2E tests
149
- ☐ Other...
150
-
151
- ↑↓ navigate • Space toggle • Tab/←→ navigate • Enter next • Esc cancel
152
- ──────────────────────────────────────────────────────
153
- ```
154
-
155
- ### Submit Tab (review)
156
-
157
- ```
158
- ──────────────────────────────────────────────────────
159
- ✓ Database │✓ Testing │✓ Notes │✓ Submit
160
-
161
- Review & Submit
162
-
163
- Database: PostgreSQL
164
- Testing: unit, integration
165
- Notes: Focus on API layer first
166
-
167
- Press Enter to submit
168
-
169
- Tab/←→ navigate questions • Enter submit • Esc cancel
170
- ──────────────────────────────────────────────────────
171
- ```
172
-
173
- ## Keyboard Reference
174
-
175
- ### Navigation
176
-
177
- | Key | Action |
178
- | ----------------- | ------------------------------------- |
179
- | `Tab` / `→` | Next question (multi-question mode) |
180
- | `Shift+Tab` / `←` | Previous question |
181
- | `↑` / `↓` | Navigate options within a question |
182
-
183
- ### Selection
184
-
185
- | Key | Action |
186
- | ----------------- | ------------------------------------- |
187
- | `Enter` | Select radio option / advance / submit |
188
- | `Space` | Toggle checkbox option |
189
- | `Enter` (text) | Submit text answer |
190
- | `Shift+Enter` | Newline in text/other editor |
191
-
192
- ### Other
193
-
194
- | Key | Action |
195
- | ----------------- | ------------------------------------- |
196
- | `Esc` | Cancel (in "Other" mode: go back) |
197
-
198
- ## Output Format
199
-
200
- The tool returns structured text to the LLM:
201
-
202
- ```
203
- Database: PostgreSQL
204
- Testing: unit, integration, (wrote) GraphQL tests
205
- Notes: Focus on API layer first
206
- ```
207
-
208
- Custom "Other" answers are prefixed with `(wrote)` so the LLM knows they were user-typed.
209
-
210
- ## System Prompt Integration
211
-
212
- The tool includes `promptSnippet` and `promptGuidelines` so the LLM knows when and how to use it:
213
-
214
- - Prefers `ask_user_question` over plain-text questions
215
- - Uses radio for single-choice, checkbox for multi-choice, text for open-ended
216
- - Groups related questions in a single call
217
- - Includes "Other" escape hatches by default
218
-
219
- ## Dependencies
220
-
221
- | Package | Role |
222
- | ------------------------------- | ------------------------------------------------- |
223
- | `@duckmind/dm-coding-agent` | Extension API, theme types |
224
- | `@duckmind/dm-tui` | TUI primitives: Editor, Key, matchesKey, etc. |
225
- | `@duckmind/dm-ai` | `StringEnum` for Google-compatible enum schemas |
226
- | `@sinclair/typebox` | JSON Schema definitions for tool parameters |
@@ -1,33 +0,0 @@
1
- # dm-cli-anything
2
-
3
- `dm-cli-anything` bundles a snapshot of the HKUDS
4
- [CLI-Anything](https://github.com/HKUDS/CLI-Anything) CLI-Hub registries and exposes
5
- them to DuckMind as the `cli_anything_hub` tool.
6
-
7
- The extension is intentionally discovery-first:
8
-
9
- - `list`, `search`, `categories`, and `info` read only the bundled registry files.
10
- - `install_command` and `launch_command` return commands for the user to review.
11
- - The extension does **not** run install, update, uninstall, or launch commands.
12
- - Suggested CLI-Hub install/launch commands include `CLI_HUB_NO_ANALYTICS=1`.
13
-
14
- ## Snapshot
15
-
16
- - Upstream: `https://github.com/HKUDS/CLI-Anything`
17
- - Revision: `7862c920c9950a0883326ba4ca9dd9ffdbcb5596`
18
- - Bundled files:
19
- - `vendor/registry.json` (`64` CLI-Anything harness entries, updated `2026-04-16`)
20
- - `vendor/public_registry.json` (`16` public CLI entries, updated `2026-04-18`)
21
- - Root upstream license copied to `LICENSE` (Apache-2.0). The upstream `cli-hub`
22
- Python package metadata says MIT; this extension only bundles registry data and
23
- the root license file.
24
-
25
- ## Example tool calls
26
-
27
- - Search image-related harnesses: `action=search`, `query=image`
28
- - List public CLIs: `action=list`, `source=public`
29
- - Inspect one entry: `action=info`, `name=wiremock`
30
- - Get a safe install suggestion: `action=install_command`, `name=wiremock`
31
-
32
- Always ask before running commands that install packages, write global state, or
33
- start external tools.
@@ -1,14 +0,0 @@
1
- # CLI-Anything snapshot
2
-
3
- - Source repository: `https://github.com/HKUDS/CLI-Anything`
4
- - Source revision: `7862c920c9950a0883326ba4ca9dd9ffdbcb5596`
5
- - Snapshot source path: `/tmp/dm-cli-anything-inventory`
6
- - Files copied:
7
- - `registry.json` → `vendor/registry.json`
8
- - `public_registry.json` → `vendor/public_registry.json`
9
- - `LICENSE` → `../LICENSE`
10
-
11
- The full upstream repository is not vendored because it contains assets,
12
- plugins, examples, and `.git` history that are not needed for the DuckMind
13
- runtime package. This extension reads the bundled registry snapshot only and
14
- returns install/launch commands as suggestions, not executed side effects.
@@ -1,41 +0,0 @@
1
- # PROJECT KNOWLEDGE BASE
2
-
3
- **Generated:** 2026-03-04
4
-
5
- ## OVERVIEW
6
- Project: **dm-context**
7
- Stack: Node.js, TypeScript (ES2022 / Node16), `@mariozechner/dm` API, `@sinclair/typebox`.
8
-
9
- Description: A Git-like context management extension for the `dm` coding agent. It allows AI agents to proactively structure, monitor, and compress their context (history) using tools modeled after Git (`tag`, `log`, `checkout`).
10
-
11
- ## STRUCTURE
12
- * `src/`: TypeScript source code for the extension.
13
- * `index.ts`: Tool and command registrations (`acm`, `context_tag`, `context_log`, `context_checkout`).
14
- * `context.ts`: CLI command registrations (e.g., `/context` for TUI visualization).
15
- * `utils.ts`: Shared utility functions and type definitions.
16
- * `skills/`: DM skills documentation, containing `context-management/SKILL.md` which instructs the LLM on how to use the context tools.
17
- * `test/`: Markdown test scenarios.
18
- * `dist/`: Output directory for compiled code (generated by `tsc`).
19
-
20
- ## COMMANDS
21
- | Action | Command |
22
- |--------|---------|
23
- | Install| `npm install` |
24
- | Build | `npx tsc` |
25
- | Test | See `test/test.md` |
26
- | Run | The extension is loaded natively by `dm`. In a `dm` environment, run `dm -e ./src/index.ts -e ./src/context.ts --skill ./skills` to test locally. |
27
-
28
- ## CODING STANDARDS
29
- * **Language**: TypeScript with ESM (`"type": "module"`).
30
- * **Style**: Standard TypeScript. Interfaces and functions are exported as ES modules. Types are defined using `@sinclair/typebox` for tool parameter schemas.
31
- * **Rules**: Strict mode is enabled (`"strict": true`). Missing types from the main SDK entry point are defined locally (e.g., `SessionTreeNode` in `utils.ts`).
32
-
33
- ## WHERE TO LOOK
34
- * **Source**: `src/`
35
- * **Tests**: `test/`
36
- * **Skill Docs**: `skills/context-management/SKILL.md` (Crucial for understanding the agent workflow, tagging strategies, and the "Build, Perceive, Navigate" philosophy).
37
-
38
- ## NOTES
39
- * **Architecture**: `dm-context` hooks directly into the `SessionManager` from the `dm` SDK, leveraging its underlying tree structure to implement lossless time travel (squashing noise without deleting the nodes from disk).
40
- * **Missing Entry File**: The `package.json` defines `"main": "dist/index.js"`. The extension relies on the DM extension manifest config (`src/index.ts`, `src/context.ts`).
41
- * **Test Script Issues**: `test/test.md` outlines the testing steps.
@@ -1,18 +0,0 @@
1
- # dm-context
2
-
3
- Bundled DM extension for agentic context management.
4
-
5
- ## Included commands
6
-
7
- - `/acm` — enable agentic context management for the current session.
8
- - `/context` — inspect context-window usage and the current session graph.
9
-
10
- ## Included tools
11
-
12
- - `context_tag`
13
- - `context_log`
14
- - `context_checkout`
15
-
16
- ## Bundled with dm
17
-
18
- No separate install step is required. Once `dm` is installed, this extension is loaded from DM's bundled extension catalog.
@@ -1,16 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "Node16",
5
- "moduleResolution": "Node16",
6
- "outDir": "./dist",
7
- "rootDir": "./src",
8
- "strict": true,
9
- "esModuleInterop": true,
10
- "skipLibCheck": true,
11
- "forceConsistentCasingInFileNames": true,
12
- "declaration": true
13
- },
14
- "include": ["src/**/*"],
15
- "exclude": ["node_modules", "dist"]
16
- }
@@ -1,24 +0,0 @@
1
- # dm-cua
2
-
3
- Browser-first Computer Use extension for DM.
4
-
5
- What it does:
6
-
7
- - launches or reuses a dedicated browser profile via the bundled `greedysearch-dm` CDP helpers
8
- - bootstraps a blank tab on fresh empty profiles so browser automation does not fail on the first run
9
- - exposes one tool, `browser_cua`, for list / navigate / snapshot / screenshot / click / type / evaluate / stop
10
- - stores browser screenshots under `~/.dm/agent/cua/screenshots/` by default
11
-
12
- Browser selection:
13
-
14
- - default: Chrome/Chromium auto-detected by `greedysearch-dm`
15
- - opt-in CloakBrowser trial: set `DM_CUA_BROWSER=cloak` and one of `DM_CUA_BROWSER_PATH`, `DM_CUA_CLOAK_PATH`, `CLOAKBROWSER_BINARY_PATH`, or `CHROME_PATH` to the CloakBrowser Chromium executable
16
- - DM does not bundle or auto-download the compiled CloakBrowser binary; install/pre-download it outside DM first because upstream permits use but not redistribution
17
- - Current `browser_cua` actions still use CDP commands through `greedysearch-dm`; full CloakBrowser stealth parity would require a future Playwright-backed CUA lane.
18
-
19
- What it does **not** do yet:
20
-
21
- - it does not replace the macOS `computer-use` Codex plugin lane
22
- - it does not replace Android `adbridge`
23
-
24
- Those broader lanes are still tracked separately. This extension closes the most actionable CUA gap from the current DM snapshot: a first-class browser lane that works from a fresh dedicated browser profile instead of overloading `coding_task`.