@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.
- package/dm +0 -0
- package/extensions/.dm-extensions.json +147 -218
- package/extensions/dm-9router-ext/package.json +0 -6
- package/extensions/dm-9router-ext/src/index.js +1 -1
- package/extensions/dm-ask-user/package.json +0 -4
- package/extensions/dm-caveman/LICENSE +21 -0
- package/extensions/dm-caveman/extensions/caveman.js +29 -0
- package/extensions/dm-caveman/package.json +20 -0
- package/extensions/dm-cli-anything/index.js +5 -5
- package/extensions/dm-cli-anything/package.json +0 -7
- package/extensions/dm-cli-anything/skills/cli-anything/SKILL.md +1 -3
- package/extensions/dm-context/package.json +0 -1
- package/extensions/dm-cua/package.json +0 -7
- package/extensions/dm-fff/package.json +0 -6
- package/extensions/dm-goal/package.json +0 -8
- package/extensions/dm-grill-me/index.js +2 -2
- package/extensions/dm-grill-me/package.json +0 -7
- package/extensions/dm-image2/package.json +0 -8
- package/extensions/dm-subagents/package.json +0 -11
- package/extensions/dm-tasks/package.json +0 -7
- package/extensions/dm-usage/package.json +0 -7
- package/extensions/greedysearch-dm/bin/cdp-greedy.mjs +1 -8
- package/extensions/greedysearch-dm/bin/gschrome.mjs +3 -3
- package/extensions/greedysearch-dm/bin/launch-visible.mjs +3 -3
- package/extensions/greedysearch-dm/bin/launch.mjs +4 -4
- package/extensions/greedysearch-dm/bin/search.mjs +103 -103
- package/extensions/greedysearch-dm/extractors/consensus.mjs +35 -35
- package/extensions/greedysearch-dm/extractors/gemini.mjs +38 -38
- package/extensions/greedysearch-dm/extractors/logically.mjs +35 -35
- package/extensions/greedysearch-dm/package.json +0 -10
- package/extensions/greedysearch-dm/src/search/chrome.mjs +23 -23
- package/extensions/greedysearch-dm/src/search/fetch-source.mjs +35 -35
- package/extensions/greedysearch-dm/src/search/research.mjs +61 -61
- package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +4 -4
- package/package.json +1 -1
- package/extensions/dm-9router-ext/README.md +0 -142
- package/extensions/dm-9router-ext/tsconfig.json +0 -17
- package/extensions/dm-ask-user/README.md +0 -226
- package/extensions/dm-cli-anything/README.md +0 -33
- package/extensions/dm-cli-anything/vendor/UPSTREAM.md +0 -14
- package/extensions/dm-context/AGENTS.md +0 -41
- package/extensions/dm-context/README.md +0 -18
- package/extensions/dm-context/tsconfig.json +0 -16
- package/extensions/dm-cua/README.md +0 -24
- package/extensions/dm-fff/README.md +0 -36
- package/extensions/dm-fff/tsconfig.json +0 -13
- package/extensions/dm-goal/CHANGELOG.md +0 -12
- package/extensions/dm-goal/README.md +0 -29
- package/extensions/dm-goal/tsconfig.json +0 -15
- package/extensions/dm-grill-me/DESIGN.md +0 -301
- package/extensions/dm-grill-me/README.md +0 -82
- package/extensions/dm-grill-me/tsconfig.json +0 -17
- package/extensions/dm-image2/README.md +0 -33
- package/extensions/dm-subagents/CHANGELOG.md +0 -1211
- package/extensions/dm-subagents/README.md +0 -29
- package/extensions/dm-subagents/biome.json +0 -26
- package/extensions/dm-subagents/tsconfig.json +0 -18
- package/extensions/dm-tasks/README.md +0 -30
- package/extensions/dm-tasks/biome.json +0 -26
- package/extensions/dm-tasks/tsconfig.json +0 -14
- package/extensions/dm-usage/README.md +0 -29
- package/extensions/greedysearch-dm/README.md +0 -222
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import{readFile as g,writeFile as r,mkdir as l}from"node:fs/promises";import{homedir as v}from"node:os";import{join as S}from"node:path";import{getSettingsListTheme as o}from"@duckmind/dm-coding-agent";import{Container as s,SettingsList as c,Text as G}from"@duckmind/dm-tui";var Y=["off","lite","full","ultra","wenyan-lite","wenyan","wenyan-ultra","micro"],m=new Set(["off","stop","quit"]),d=[{value:"lite",label:"lite",description:"Professional, no fluff"},{value:"full",label:"full",description:"Classic caveman"},{value:"ultra",label:"ultra",description:"Maximum compression"},{value:"wenyan-lite",label:"wenyan-lite",description:"Semi-classical Chinese"},{value:"wenyan",label:"wenyan",description:"Full 文言文"},{value:"wenyan-ultra",label:"wenyan-ultra",description:"Extreme 文言文"},{value:"micro",label:"micro",description:"Experimental prompt-minimized mode"},{value:"off",label:"off",description:"Disable caveman mode"},{value:"stop",label:"stop",description:"Disable caveman mode"},{value:"quit",label:"quit",description:"Disable caveman mode"},{value:"config",label:"config",description:"Open settings dialog"}],E=S(v(),".dm","agent","caveman.json"),O={defaultLevel:"full",showStatus:!0},_=Promise.resolve();async function n(){try{let $=await g(E,"utf8"),q=JSON.parse($);return{defaultLevel:Y.includes(q.defaultLevel)?q.defaultLevel:O.defaultLevel,showStatus:typeof q.showStatus==="boolean"?q.showStatus:O.showStatus}}catch{return{...O}}}async function a($){let q=JSON.stringify($,null,2)+`
|
|
2
|
+
`;return _=_.then(async()=>{await l(S(v(),".dm","agent"),{recursive:!0}),await r(E,q,"utf8")}),_}var M="\x1B[38;5;196m",N="\x1B[38;5;208m",p="\x1B[38;5;220m",L="\x1B[38;5;230m",F="\x1B[38;5;52m",j="\x1B[0m",k=[`${M}⠠${N}⠄${j}`,`${N}⠔${p}⠂${j}`,`${p}⠊${L}⠑${j}`,`${L}⠑${p}⠊${j}`,`${p}⠂${N}⠔${j}`,`${N}⠄${M}⠠${j}`,`${M}⠠${F}⠄${j}`,`${F}⠔${M}⠂${j}`],f={lite:{frames:k,label:"LITE",interval:300},full:{frames:k,label:"FULL",interval:200},ultra:{frames:k,label:"ULTRA",interval:100},"wenyan-lite":{frames:k,label:"文言",interval:300},wenyan:{frames:k,label:"文言文",interval:200},"wenyan-ultra":{frames:k,label:"文言文極",interval:100},micro:{frames:k,label:"MICRO",interval:120}},i=`IMPORTANT: You are in CAVEMAN MODE. Respond terse like smart caveman. All technical substance stay. Only fluff die.
|
|
3
|
+
|
|
4
|
+
Rules:
|
|
5
|
+
- Drop articles (a/an/the), filler (just/really/basically/actually/simply), pleasantries, hedging
|
|
6
|
+
- Fragments OK. Short synonyms preferred. Technical terms exact
|
|
7
|
+
- Code blocks unchanged. Errors quoted exact
|
|
8
|
+
- Pattern: [thing] [action] [reason]. [next step].
|
|
9
|
+
|
|
10
|
+
Bad: "Sure! I'd be happy to help you with that. The issue you're experiencing is likely caused by..."
|
|
11
|
+
Good: "Bug in auth middleware. Token expiry check use \`<\` not \`<=\`. Fix:"`,t=`# Token efficiency
|
|
12
|
+
Respond like smart caveman. Cut all filler, keep technical substance.
|
|
13
|
+
- Drop articles (a, an, the), filler (just, really, basically, actually).
|
|
14
|
+
- Drop pleasantries (sure, certainly, happy to).
|
|
15
|
+
- No hedging. Fragments fine. Short synonyms.
|
|
16
|
+
- Technical terms stay exact. Code blocks unchanged.
|
|
17
|
+
- Pattern: [thing] [action] [reason]. [next step].`,e={lite:'No filler/hedging. Keep articles + full sentences. Professional but tight.\nExample: "Your component re-renders because you create a new object reference each render. Wrap it in `useMemo`."',full:'Drop articles, fragments OK, short synonyms.\nExample: "New object ref each render. Inline object prop = new ref = re-render. Wrap in `useMemo`."',ultra:'Abbreviate (DB/auth/config/req/res/fn/impl), strip conjunctions, arrows for causality (X → Y).\nExample: "Inline obj prop → new ref → re-render. `useMemo`."',"wenyan-lite":`Semi-classical Chinese. Grammar intact, filler gone. Technical terms in English.
|
|
18
|
+
Example: "組件頻重繪,以每繪新生對象參照故。以 useMemo 包之。"`,wenyan:`Maximum classical terseness. 80-90% character reduction. Technical terms in English.
|
|
19
|
+
Example: "物出新參照,致重繪。useMemo Wrap之。"`,"wenyan-ultra":`Extreme classical compression. Technical terms in English.
|
|
20
|
+
Example: "新參照→重繪。useMemo Wrap。"`},bb=`Auto-clarity: drop caveman for security warnings, irreversible action confirmations, or when user is confused. Resume after.
|
|
21
|
+
Boundaries: write normal code. Only compress explanations. "stop caveman" or "normal mode" reverts.`;function qb($){let q="off",z={...O},X=null,V=0,P=!1,h=null,R=async()=>{if(!h)h=(async()=>{if(z=await n(),q==="off"&&z.defaultLevel!=="off")q=z.defaultLevel})();await h};function I(){if(X)clearInterval(X),X=null;V=0}function Q(Z){I();let J=Z.ui.theme;if(q==="off"||!z.showStatus){Z.ui.setStatus("caveman","");return}let b=f[q],B=(U)=>{Z.ui.setStatus("caveman",U+" "+J.fg("muted","caveman level: ")+J.fg("text",b.label))};if(!P){B(b.frames[0]);return}let w=()=>{B(b.frames[V%b.frames.length]),V++};w(),X=setInterval(w,b.interval)}$.on("session_start",async(Z,J)=>{await R();let b=null;for(let B of J.sessionManager.getEntries())if(B.type==="custom"&&B.customType==="caveman-level")b=B.data?.level??null;if(b!==null)q=b;else if(z.defaultLevel!=="off")q=z.defaultLevel,$.appendEntry("caveman-level",{level:q});Q(J)}),$.on("agent_start",async(Z,J)=>{P=!0,Q(J)}),$.on("agent_end",async(Z,J)=>{P=!1,Q(J)}),$.on("session_shutdown",async()=>{I(),P=!1}),$.registerCommand("caveman",{description:"Toggle caveman mode, set level, use stop/off/quit to disable, or 'config' to open settings",getArgumentCompletions:(Z)=>{let J=Z.trim().toLowerCase(),b=d.filter((B)=>B.value.startsWith(J));return b.length>0?b:null},handler:async(Z,J)=>{let b=Z?.trim().toLowerCase();if(b==="config"){await u(J);return}if(!b)q=q==="off"?"full":"off";else if(m.has(b))q="off";else if(Y.includes(b))q=b;else{J.ui.notify(`Unknown: "${b}". Use: ${Y.join(", ")}, stop, quit, or config`,"error");return}$.appendEntry("caveman-level",{level:q}),Q(J),J.ui.notify(q==="off"?"Caveman mode off.":`Caveman: ${f[q].label}`,"info")}});async function u(Z){await R(),await Z.ui.custom((J,b,B,w)=>{let U=[{id:"defaultLevel",label:"Default level for new sessions",currentValue:z.defaultLevel,values:[...Y]},{id:"showStatus",label:"Show animated status bar",currentValue:z.showStatus?"on":"off",values:["on","off"]}],W=new s;W.addChild(new G(b.fg("accent",b.bold(" Caveman Config")),0,0)),W.addChild(new G(b.fg("dim"," Saved to ~/.dm/agent/caveman.json"),0,0)),W.addChild(new G(b.fg("dim"," Default level applies to future sessions."),0,0)),W.addChild(new G("",0,0));let A=(K,D)=>{if(K==="defaultLevel"&&Y.includes(D))z.defaultLevel=D;else if(K==="showStatus")z.showStatus=D==="on";a(z),Q(Z)},y=new c(U,Math.min(U.length+2,10),o(),A,()=>w(void 0));W.addChild(y),W.addChild(new G(b.fg("dim"," ←→/hl/tab change • ↑↓/jk move • esc close"),0,0));let T=(K)=>{let D=y.selectedIndex,H=U[D];if(!H?.values?.length)return;let x=(H.values.indexOf(H.currentValue)+K+H.values.length)%H.values.length,C=H.values[x];H.currentValue=C,y.updateValue(H.id,C),A(H.id,C)};return{render:(K)=>W.render(K),invalidate:()=>W.invalidate(),handleInput:(K)=>{if(K==="j")K="\x1B[B";else if(K==="k")K="\x1B[A";else if(K==="h"){T(-1),J.requestRender();return}else if(K==="l"||K==="\x1B[C"||K==="\t"){T(1),J.requestRender();return}else if(K==="\x1B[D"){T(-1),J.requestRender();return}y.handleInput?.(K),J.requestRender()}}})}$.on("before_agent_start",async(Z)=>{if(await R(),q==="off")return;if(q==="micro")return{systemPrompt:`${Z.systemPrompt}
|
|
22
|
+
|
|
23
|
+
${t}`};return{systemPrompt:`${Z.systemPrompt}
|
|
24
|
+
|
|
25
|
+
${i}
|
|
26
|
+
|
|
27
|
+
${e[q]}
|
|
28
|
+
|
|
29
|
+
${bb}`}})}export{qb as default};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dm-caveman",
|
|
3
|
+
"version": "1.0.7",
|
|
4
|
+
"description": "DM extension for concise, token-efficient assistant responses",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"duckmind",
|
|
8
|
+
"dm",
|
|
9
|
+
"dm-extension",
|
|
10
|
+
"caveman",
|
|
11
|
+
"token-saving"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": "jonjonrankin",
|
|
15
|
+
"dm": {
|
|
16
|
+
"extensions": [
|
|
17
|
+
"./extensions/caveman.js"
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
`)}function
|
|
3
|
-
`)}function
|
|
4
|
-
`)}function
|
|
5
|
-
`)}],details:{status:"ok",action:n,entry:
|
|
1
|
+
import k from"node:fs";import g from"node:path";import{fileURLToPath as x}from"node:url";var L=g.dirname(x(import.meta.url)),w=g.join(L,"vendor"),S={type:"object",additionalProperties:!1,properties:{action:{type:"string",enum:["list","search","info","categories","install_command","launch_command"]},query:{type:"string",description:"Search query for CLI name, display name, description, or category."},name:{type:"string",description:"Exact CLI name or display name for info/install_command/launch_command."},category:{type:"string",description:"Optional category filter."},source:{type:"string",enum:["all","harness","public"],description:"Registry source filter. harness=CLI-Anything harnesses, public=public third-party CLIs."},limit:{type:"number",minimum:1,maximum:100,description:"Maximum items returned for list/search."}}};function q(e){return JSON.parse(k.readFileSync(e,"utf8"))}function A(e){return String(e??"").replace(/[\u0000-\u001f\u007f]/g," ").trim()}function a(e){return A(e).toLowerCase()}function f(e){return`'${String(e).replace(/'/g,"'\\''")}'`}function h(e,n){let o=q(g.join(w,n)),t=Array.isArray(o.clis)?o.clis:[];return{source:e,meta:o.meta||{},entries:t.map((s)=>({...s,_source:e}))}}function _(){let e=h("harness","registry.json"),n=h("public","public_registry.json"),o=[...e.entries,...n.entries].sort((t,s)=>a(t.name||t.display_name).localeCompare(a(s.name||s.display_name)));return{metas:{harness:e.meta,public:n.meta},counts:{harness:e.entries.length,public:n.entries.length,total:o.length},entries:o}}function E(e,n="all"){return!n||n==="all"||e._source===n}function N(e,n){return!n||a(e.category)===a(n)}function u(e,n={}){let o=n.source||"all";return e.filter((t)=>E(t,o)&&N(t,n.category))}function y(e,n,o={}){let t=a(n),s=u(e,o);if(!t)return s;return s.filter((i)=>{return[i.name,i.display_name,i.description,i.category,i.entry_point,i.homepage,i.source_url,i.package_manager,i.npm_package].map(a).join(" ").includes(t)})}function b(e,n,o={}){let t=a(n);if(!t)return null;let s=u(e,o);return s.find((i)=>a(i.name)===t)||s.find((i)=>a(i.display_name)===t)||s.find((i)=>a(i.entry_point)===t)||null}function d(e){let n=Number(e.limit??20);if(!Number.isFinite(n))return 20;return Math.max(1,Math.min(100,Math.trunc(n)))}function p(e){return{name:e.name,display_name:e.display_name,source:e._source,category:e.category,version:e.version,description:e.description,requires:e.requires,entry_point:e.entry_point,homepage:e.homepage,source_url:e.source_url,package_manager:e.package_manager,npm_package:e.npm_package,npx_cmd:e.npx_cmd,skill_md:e.skill_md}}function R(e){let n=[`${e.display_name||e.name} (${e.name}, ${e._source})`,`Category: ${e.category||"unknown"}; version: ${e.version||"unknown"}`,`Description: ${e.description||"n/a"}`];if(e.requires)n.push(`Requires: ${e.requires}`);if(e.entry_point)n.push(`Entry point: ${e.entry_point}`);if(e.homepage)n.push(`Homepage: ${e.homepage}`);if(e.source_url)n.push(`Source: ${e.source_url}`);if(e.skill_md)n.push(`Skill/guide: ${e.skill_md}`);if(e.npx_cmd)n.push(`npx: ${e.npx_cmd}`);return n.join(`
|
|
2
|
+
`)}function $(e,n,o){let t=e.length,s=e.slice(0,d(n)),i=[`source=${n.source||"all"}`];if(n.category)i.push(`category=${n.category}`);if(n.query)i.push(`query=${n.query}`);let r=[`Bundled DM CLI catalog: ${o.counts.total} CLIs (${o.counts.harness} harness, ${o.counts.public} public)`,`Matches: ${t}; showing ${s.length}; filters: ${i.join(", ")}`,"Note: install/launch actions return command suggestions only; they do not execute side effects.",""];for(let c of s)r.push(`- ${c.name} [${c._source}/${c.category||"unknown"}] — ${c.description||c.display_name||""}`);if(s.length<t)r.push(`... ${t-s.length} more; raise limit or narrow query/category.`);return r.join(`
|
|
3
|
+
`)}function v(e){let n=new Map;for(let t of e){let i=`${t.category||"unknown"} (${t._source})`;n.set(i,(n.get(i)||0)+1)}return["CLI-Anything categories:",...[...n.entries()].sort((t,s)=>t[0].localeCompare(s[0])).map(([t,s])=>`- ${t}: ${s}`)].join(`
|
|
4
|
+
`)}function C(e){let o=[{label:"cli-hub",command:`CLI_HUB_NO_ANALYTICS=1 cli-hub install ${f(e.name)}`,note:"Requires `pip install cli-anything-hub`; disables CLI-Hub analytics for the install command."}];if(e.install_cmd)o.push({label:"direct",command:e.install_cmd,note:"Direct upstream registry install command. Review before running because it can install global packages or execute shell commands."});if(e.npx_cmd)o.push({label:"npx",command:e.npx_cmd,note:"Runs through npx without preinstalling globally; still may download code."});return o}function I(e){let n=[];if(e.entry_point)n.push({label:"entry_point",command:e.entry_point});if(e.name)n.push({label:"cli-hub",command:`CLI_HUB_NO_ANALYTICS=1 cli-hub launch ${f(e.name)}`});return n}function M(e,n){let o=n==="install_command"?C(e):I(e);return{content:[{type:"text",text:[`${n==="install_command"?"Install":"Launch"} suggestions for ${e.name}:`,"These are suggestions only; dm-cli-anything does not execute install/update/uninstall/launch commands.","Ask the user before running commands with package installs, global writes, or shell side effects.","",...o.map((s)=>`- ${s.label}: ${s.command}${s.note?` (${s.note})`:""}`)].join(`
|
|
5
|
+
`)}],details:{status:"ok",action:n,entry:p(e),suggestions:o,side_effects_executed:!1},isError:!1}}function m(e,n){return{content:[{type:"text",text:e}],details:n,isError:!1}}function l(e,n={}){return{content:[{type:"text",text:`cli_anything_hub failed: ${e}`}],details:{status:"error",message:e,...n},isError:!0}}function j(e){e.registerTool({name:"cli_anything_hub",label:"CLI-Anything Hub",description:"Search and inspect the bundled DM CLI catalog. Install and launch actions return command suggestions only and never execute side effects.",promptSnippet:"Use cli_anything_hub to discover CLI-Anything harnesses and public CLIs by name, category, source, or query. Treat install_command and launch_command as suggestions only; ask before running global installs or shell commands.",promptGuidelines:["Use action=search for broad discovery, action=list with category/source filters for inventory, and action=info for a known CLI.","Do not execute install, update, uninstall, or launch commands from this tool without explicit user approval.","When suggesting CLI-Hub commands, prefer `CLI_HUB_NO_ANALYTICS=1` to avoid opt-out analytics side effects.","Mention that the catalog is a bundled snapshot and may need a DM update for newer entries."],parameters:S,async execute(n,o={}){let t=o.action||(o.query?"search":"list");try{let s=_();if(t==="categories"){let r=u(s.entries,o);return m(v(r),{status:"ok",action:t,categories_counted:r.length})}if(t==="list"||t==="search"){let r=t==="search"?y(s.entries,o.query||"",o):u(s.entries,o);return m($(r,o,s),{status:"ok",action:t,total_matches:r.length,shown:Math.min(r.length,d(o)),entries:r.slice(0,d(o)).map(p),counts:s.counts})}if(!o.name)return l(`${t} requires a name`,{action:t});let i=b(s.entries,o.name,o);if(!i)return l(`no CLI-Anything entry matched name=${o.name}`,{action:t,name:o.name,source:o.source||"all"});if(t==="info")return m(R(i),{status:"ok",action:t,entry:p(i)});if(t==="install_command"||t==="launch_command")return M(i,t);return l(`unsupported action=${t}`,{action:t})}catch(s){return l(s instanceof Error?s.message:String(s),{action:t})}}})}var O={loadRegistries:_,searchEntries:y,findEntry:b,installSuggestions:C,launchSuggestions:I,renderList:$};export{j as default,O as __test};
|
|
@@ -4,13 +4,6 @@
|
|
|
4
4
|
"description": "DuckMind extension for safe discovery of HKUDS CLI-Anything/CLI-Hub harnesses.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
7
|
-
"files": [
|
|
8
|
-
"index.js",
|
|
9
|
-
"vendor/",
|
|
10
|
-
"skills/",
|
|
11
|
-
"README.md",
|
|
12
|
-
"LICENSE"
|
|
13
|
-
],
|
|
14
7
|
"keywords": [
|
|
15
8
|
"duckmind",
|
|
16
9
|
"dm",
|
|
@@ -14,9 +14,7 @@ Core workflow:
|
|
|
14
14
|
|
|
15
15
|
Safety notes:
|
|
16
16
|
|
|
17
|
-
- The
|
|
18
|
-
`https://github.com/HKUDS/CLI-Anything` at
|
|
19
|
-
`7862c920c9950a0883326ba4ca9dd9ffdbcb5596`.
|
|
17
|
+
- The catalog is a bundled DM snapshot. Update DM to receive newer entries.
|
|
20
18
|
- CLI-Hub has optional analytics; prefer commands with
|
|
21
19
|
`CLI_HUB_NO_ANALYTICS=1`.
|
|
22
20
|
- Registry `install_cmd` values can install global packages or run shell
|
|
@@ -3,13 +3,6 @@
|
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"description": "First-class browser CUA extension for DM using a dedicated Chrome/CDP-compatible profile",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"files": [
|
|
7
|
-
"index.js",
|
|
8
|
-
"bin/",
|
|
9
|
-
"src/",
|
|
10
|
-
"skills/",
|
|
11
|
-
"README.md"
|
|
12
|
-
],
|
|
13
6
|
"keywords": [
|
|
14
7
|
"duckmind",
|
|
15
8
|
"dm",
|
|
@@ -101,14 +101,14 @@ Begin by updating the checkpoint if needed, seed or maintain the coverage checkl
|
|
|
101
101
|
- /grill output <one or more outputs> (preference only; approval still required)
|
|
102
102
|
- /grill research off|ask|auto
|
|
103
103
|
|
|
104
|
-
Grill Me uses one thorough default Socratic style. The assistant must use the hardcoded output-selection phase before ending the interview, producing outputs, or stopping without outputs.`,display:!0});return}if($==="stop"){j.active=!1,j.phase="interview",j.outputPhase=!1,j.outputSelection=void 0,j.approvedOutputPlan=void 0,j.currentQuestion=void 0,j.alternatives=[],j.lastChangeSummary="Stopped grill session",X(),z(Q),Q.ui.notify("Grill mode stopped.","info");return}if($==="status"){J.sendMessage({customType:"grill-me-status",content:jj(j),display:!0});return}if($==="checkpoint"){await q(Q,Z);return}if($==="intent"){let D=x(Z);if(!D){Q.ui.notify(`Usage: /grill intent ${p.join("|")}`,"warning");return}j.intent=D,j.lastChangeSummary=`Intent set to ${D}`,X(),z(Q),Q.ui.notify(`Grill intent: ${D}`,"info");return}if($==="output"){if(!Z){Q.ui.notify("Usage: /grill output <one or more outputs, e.g. design-doc,issues>","warning");return}j.outputPreference=Z,j.lastChangeSummary=`Output preference set to ${Z}`,X(),z(Q),Q.ui.notify(`Grill output preference: ${Z}. This is not approval; Grill Me will still ask/confirm before producing outputs.`,"info");return}if($==="research"){let D=u(Z);if(!D){Q.ui.notify(`Usage: /grill research ${l.join("|")}`,"warning");return}j.researchMode=D,j.lastChangeSummary=`Research mode set to ${D}`,X(),z(Q),Q.ui.notify(`Grill research mode: ${D}`,"info");return}let W=Xj(Y),R={},B=x(W.flags.intent),w=u(W.flags.research);if(B)R.intent=B;if(w)R.researchMode=w;if(typeof W.flags.output==="string")R.outputPreference=W.flags.output;let G=W.rest;if(!G){let D=h(Q);if(!Q.hasUI)G=D||"Current conversation";else{let L=await Q.ui.editor("What should I grill you about?",D||"");if(!L?.trim()){Q.ui.notify("Cancelled grill start.","info");return}G=L.trim()}}F(G,Q,R)}}),J.registerCommand("deep-interview",{description:"Start a DM Deep Interview session",handler:async(V,Q)=>{let Y=V.trim()||h(Q)||"Current conversation";F(Y,Q,{researchMode:"auto"},"DM Deep Interview")}}),J.registerTool({name:"grill_update_checkpoint",label:"Update Grill Checkpoint",description:"Replace the Grill Me shared-understanding checkpoint. Use before asking the next grill question whenever meaningful understanding changes.",promptSnippet:"Persist the evolving Grill Me shared-understanding Markdown checkpoint",promptGuidelines:["Use grill_update_checkpoint before asking the next question whenever an active Grill Me session reaches a meaningful new decision, clarification, assumption, risk, or open question."],parameters:H.Object({markdown:H.String({description:"The full replacement Markdown checkpoint."}),changeSummary:H.String({description:"Brief visible summary of what changed."})}),async execute(V,Q){if(!j.active)return{content:[{type:"text",text:"No active Grill Me session. Start one with /grill <topic>."}],details:{checkpoint:j.checkpoint,changeSummary:"No active session",updatedAt:j.updatedAt}};return j.checkpoint=Q.markdown,j.lastChangeSummary=Q.changeSummary,X(),{content:[{type:"text",text:`Recorded checkpoint update: ${Q.changeSummary}`}],details:{checkpoint:j.checkpoint,changeSummary:Q.changeSummary,updatedAt:j.updatedAt}}},renderCall(V,Q){return new k(Q.fg("toolTitle",Q.bold("grill_update_checkpoint "))+Q.fg("muted",V.changeSummary??""),0,0)},renderResult(V,Q,Y){let $=V.details?.changeSummary,Z=$?`✓ ${$}`:V.content[0]?.type==="text"?V.content[0].text:"Checkpoint updated";return new k(Y.fg("success",Z),0,0)}}),J.registerTool({name:"grill_set_alternatives",label:"Set Grill Alternatives",description:"Set the visible Grill Me answer alternatives offered to the user via Tab autocomplete for the next question or readiness choice.",promptSnippet:"Present answer alternatives through the Grill Me Tab autocomplete UX",promptGuidelines:["Before asking each grill question, call grill_set_alternatives with 2-5 concise, concrete alternatives the user can accept or edit with Tab autocomplete.","Include one recommended alternative and make it clear in the label or description.","Use alternatives that are useful defaults, not exhaustive menus; the user can still type a custom answer."],parameters:H.Object({question:H.String({description:"The question these alternatives answer."}),alternatives:H.Array(H.Object({value:H.String({description:"The exact reply inserted into the user's editor when selected."}),label:H.String({description:"Short visible label for the alternative."}),description:H.Optional(H.String({description:"Brief explanation or recommendation note."}))}),{description:"2-5 suggested replies. Include a recommended/default option."})}),async execute(V,Q,Y,$,Z){if(!j.active)return{content:[{type:"text",text:"No active Grill Me session. Start one with /grill <topic>."}],details:{alternatives:[]}};if(j.currentQuestion=Q.question,j.alternatives=T(Q.alternatives),j.lastChangeSummary=`Set ${j.alternatives.length} Tab alternatives`,X(),Z)z(Z);return{content:[{type:"text",text:`Tab alternatives updated: ${j.alternatives.map((W)=>W.label).join(", ")}`}],details:{question:j.currentQuestion,alternatives:j.alternatives}}},renderCall(V,Q){return new k(Q.fg("toolTitle",Q.bold("grill_set_alternatives "))+Q.fg("muted",V.question??""),0,0)},renderResult(V,Q,Y){let $=V.details?.alternatives??[],Z=$.length?`✓ Tab alternatives: ${$.map((W)=>W.label).join(" | ")}`:"No alternatives set";return new k(Y.fg($.length?"success":"warning",Z),0,0)}}),J.registerTool({name:"grill_enter_output_selection_phase",label:"Enter Grill Output Selection",description:`Enter the mandatory hardcoded output-selection phase at the end of the Grill Me interview before stopping or producing outputs. The phase must explicitly mention available output destinations: ${f()}.`,promptSnippet:"Start the mandatory Grill Me output-selection phase",promptGuidelines:["Use grill_enter_output_selection_phase after the final checkpoint update when the Grill Me interview is ready to end.","Do not stop a Grill Me interview, claim the work is complete, or enter output production until grill_enter_output_selection_phase has been called and the user has selected what happens next.",`In the output-selection chat response, explicitly list these output destination options before asking for a choice: ${f()}.`],parameters:H.Object({readinessRationale:H.String({description:"Why shared understanding is sufficient to leave interview mode."}),recommendedOutputs:H.String({description:`One or more recommended output destinations/formats from the explicit catalog (${f()}), or 'none' if no artifact is recommended.`}),recommendedStrategy:H.String({description:"Recommended output strategy, distinct from destination/format."}),question:H.String({description:"The explicit output-selection question to ask the user. It should name concrete output options rather than saying only 'outputs'."}),alternatives:H.Array(H.Object({value:H.String({description:"The exact reply inserted into the user's editor when selected."}),label:H.String({description:"Short visible label for the alternative."}),description:H.Optional(H.String({description:"Brief explanation or recommendation note."}))}),{description:"2-5 choices covering produce output(s), continue grilling, review checkpoint, or stop with no output as appropriate."})}),async execute(V,Q,Y,$,Z){if(!j.active)return{content:[{type:"text",text:"No active Grill Me session. Start one with /grill <topic>."}],details:{phase:A(j)}};if(j.phase="output-selection",j.outputPhase=!1,j.outputSelection={readinessRationale:Q.readinessRationale,recommendedOutputs:Q.recommendedOutputs,recommendedStrategy:Q.recommendedStrategy,question:Q.question},j.approvedOutputPlan=void 0,j.currentQuestion=Q.question,j.alternatives=T(Q.alternatives),j.lastChangeSummary="Entered mandatory output-selection phase",X(),Z)z(Z);return{content:[{type:"text",text:`Output-selection phase is active. In the chat response, explicitly show these output destination options:
|
|
104
|
+
Grill Me uses one thorough default Socratic style. The assistant must use the hardcoded output-selection phase before ending the interview, producing outputs, or stopping without outputs.`,display:!0});return}if($==="stop"){j.active=!1,j.phase="interview",j.outputPhase=!1,j.outputSelection=void 0,j.approvedOutputPlan=void 0,j.currentQuestion=void 0,j.alternatives=[],j.lastChangeSummary="Stopped grill session",X(),z(Q),Q.ui.notify("Grill mode stopped.","info");return}if($==="status"){J.sendMessage({customType:"grill-me-status",content:jj(j),display:!0});return}if($==="checkpoint"){await q(Q,Z);return}if($==="intent"){let D=x(Z);if(!D){Q.ui.notify(`Usage: /grill intent ${p.join("|")}`,"warning");return}j.intent=D,j.lastChangeSummary=`Intent set to ${D}`,X(),z(Q),Q.ui.notify(`Grill intent: ${D}`,"info");return}if($==="output"){if(!Z){Q.ui.notify("Usage: /grill output <one or more outputs, e.g. design-doc,issues>","warning");return}j.outputPreference=Z,j.lastChangeSummary=`Output preference set to ${Z}`,X(),z(Q),Q.ui.notify(`Grill output preference: ${Z}. This is not approval; Grill Me will still ask/confirm before producing outputs.`,"info");return}if($==="research"){let D=u(Z);if(!D){Q.ui.notify(`Usage: /grill research ${l.join("|")}`,"warning");return}j.researchMode=D,j.lastChangeSummary=`Research mode set to ${D}`,X(),z(Q),Q.ui.notify(`Grill research mode: ${D}`,"info");return}let W=Xj(Y),R={},B=x(W.flags.intent),w=u(W.flags.research);if(B)R.intent=B;if(w)R.researchMode=w;if(typeof W.flags.output==="string")R.outputPreference=W.flags.output;let G=W.rest;if(!G){let D=h(Q);if(!Q.hasUI)G=D||"Current conversation";else{let L=await Q.ui.editor("What should I grill you about?",D||"");if(!L?.trim()){Q.ui.notify("Cancelled grill start.","info");return}G=L.trim()}}F(G,Q,R)}}),J.registerCommand("deep-interview",{description:"Start a DM Deep Interview session",handler:async(V,Q)=>{let Y=V.trim()||h(Q)||"Current conversation";F(Y,Q,{researchMode:"auto"},"DM Deep Interview")}}),J.registerTool({name:"grill_update_checkpoint",label:"Update Grill Checkpoint",description:"Replace the Grill Me shared-understanding checkpoint. Use before asking the next grill question whenever meaningful understanding changes.",promptSnippet:"Persist the evolving Grill Me shared-understanding Markdown checkpoint",promptGuidelines:["Use grill_update_checkpoint before asking the next question whenever an active Grill Me session reaches a meaningful new decision, clarification, assumption, risk, or open question.","Maintain a clarity ledger for intent, outcome, scope, constraints, evidence, success criteria, decisions, and risks; use it to choose the next high-leverage question.","Route missing repo/docs facts to read-only inspection when available, and ask the user for judgments, priorities, tradeoffs, risk tolerance, taste, and decision boundaries.","Before closing the interview, run a light pressure pass over assumptions, counterexamples, failure modes, and unresolved branches."],parameters:H.Object({markdown:H.String({description:"The full replacement Markdown checkpoint."}),changeSummary:H.String({description:"Brief visible summary of what changed."})}),async execute(V,Q){if(!j.active)return{content:[{type:"text",text:"No active Grill Me session. Start one with /grill <topic>."}],details:{checkpoint:j.checkpoint,changeSummary:"No active session",updatedAt:j.updatedAt}};return j.checkpoint=Q.markdown,j.lastChangeSummary=Q.changeSummary,X(),{content:[{type:"text",text:`Recorded checkpoint update: ${Q.changeSummary}`}],details:{checkpoint:j.checkpoint,changeSummary:Q.changeSummary,updatedAt:j.updatedAt}}},renderCall(V,Q){return new k(Q.fg("toolTitle",Q.bold("grill_update_checkpoint "))+Q.fg("muted",V.changeSummary??""),0,0)},renderResult(V,Q,Y){let $=V.details?.changeSummary,Z=$?`✓ ${$}`:V.content[0]?.type==="text"?V.content[0].text:"Checkpoint updated";return new k(Y.fg("success",Z),0,0)}}),J.registerTool({name:"grill_set_alternatives",label:"Set Grill Alternatives",description:"Set the visible Grill Me answer alternatives offered to the user via Tab autocomplete for the next question or readiness choice.",promptSnippet:"Present answer alternatives through the Grill Me Tab autocomplete UX",promptGuidelines:["Before asking each grill question, call grill_set_alternatives with 2-5 concise, concrete alternatives the user can accept or edit with Tab autocomplete.","Include one recommended alternative and make it clear in the label or description.","Use alternatives that are useful defaults, not exhaustive menus; the user can still type a custom answer."],parameters:H.Object({question:H.String({description:"The question these alternatives answer."}),alternatives:H.Array(H.Object({value:H.String({description:"The exact reply inserted into the user's editor when selected."}),label:H.String({description:"Short visible label for the alternative."}),description:H.Optional(H.String({description:"Brief explanation or recommendation note."}))}),{description:"2-5 suggested replies. Include a recommended/default option."})}),async execute(V,Q,Y,$,Z){if(!j.active)return{content:[{type:"text",text:"No active Grill Me session. Start one with /grill <topic>."}],details:{alternatives:[]}};if(j.currentQuestion=Q.question,j.alternatives=T(Q.alternatives),j.lastChangeSummary=`Set ${j.alternatives.length} Tab alternatives`,X(),Z)z(Z);return{content:[{type:"text",text:`Tab alternatives updated: ${j.alternatives.map((W)=>W.label).join(", ")}`}],details:{question:j.currentQuestion,alternatives:j.alternatives}}},renderCall(V,Q){return new k(Q.fg("toolTitle",Q.bold("grill_set_alternatives "))+Q.fg("muted",V.question??""),0,0)},renderResult(V,Q,Y){let $=V.details?.alternatives??[],Z=$.length?`✓ Tab alternatives: ${$.map((W)=>W.label).join(" | ")}`:"No alternatives set";return new k(Y.fg($.length?"success":"warning",Z),0,0)}}),J.registerTool({name:"grill_enter_output_selection_phase",label:"Enter Grill Output Selection",description:`Enter the mandatory hardcoded output-selection phase at the end of the Grill Me interview before stopping or producing outputs. The phase must explicitly mention available output destinations: ${f()}.`,promptSnippet:"Start the mandatory Grill Me output-selection phase",promptGuidelines:["Use grill_enter_output_selection_phase after the final checkpoint update when the Grill Me interview is ready to end.","Do not stop a Grill Me interview, claim the work is complete, or enter output production until grill_enter_output_selection_phase has been called and the user has selected what happens next.",`In the output-selection chat response, explicitly list these output destination options before asking for a choice: ${f()}.`],parameters:H.Object({readinessRationale:H.String({description:"Why shared understanding is sufficient to leave interview mode."}),recommendedOutputs:H.String({description:`One or more recommended output destinations/formats from the explicit catalog (${f()}), or 'none' if no artifact is recommended.`}),recommendedStrategy:H.String({description:"Recommended output strategy, distinct from destination/format."}),question:H.String({description:"The explicit output-selection question to ask the user. It should name concrete output options rather than saying only 'outputs'."}),alternatives:H.Array(H.Object({value:H.String({description:"The exact reply inserted into the user's editor when selected."}),label:H.String({description:"Short visible label for the alternative."}),description:H.Optional(H.String({description:"Brief explanation or recommendation note."}))}),{description:"2-5 choices covering produce output(s), continue grilling, review checkpoint, or stop with no output as appropriate."})}),async execute(V,Q,Y,$,Z){if(!j.active)return{content:[{type:"text",text:"No active Grill Me session. Start one with /grill <topic>."}],details:{phase:A(j)}};if(j.phase="output-selection",j.outputPhase=!1,j.outputSelection={readinessRationale:Q.readinessRationale,recommendedOutputs:Q.recommendedOutputs,recommendedStrategy:Q.recommendedStrategy,question:Q.question},j.approvedOutputPlan=void 0,j.currentQuestion=Q.question,j.alternatives=T(Q.alternatives),j.lastChangeSummary="Entered mandatory output-selection phase",X(),Z)z(Z);return{content:[{type:"text",text:`Output-selection phase is active. In the chat response, explicitly show these output destination options:
|
|
105
105
|
${O()}
|
|
106
106
|
|
|
107
107
|
Then ask the user to choose one or more, customize the set, continue grilling, review the checkpoint, or stop without output. Alternatives: ${j.alternatives.map((W)=>W.label).join(", ")}`}],details:{phase:A(j),outputSelection:j.outputSelection,outputDestinationOptions:g,alternatives:j.alternatives}}},renderCall(V,Q){return new k(Q.fg("toolTitle",Q.bold("grill_enter_output_selection_phase "))+Q.fg("muted",V.question??""),0,0)},renderResult(V,Q,Y){let $=V.details?.outputSelection,Z=$?`✓ Output selection: ${$.recommendedOutputs}`:V.content[0]?.type==="text"?V.content[0].text:"Output selection phase updated";return new k(Y.fg($?"success":"warning",Z),0,0)}}),J.registerTool({name:"grill_finish_output_selection_phase",label:"Finish Grill Output Selection",description:"Resolve the mandatory output-selection phase without entering output production, either by continuing the interview or stopping with no outputs.",promptSnippet:"Resolve Grill Me output selection without output production",promptGuidelines:["Use grill_finish_output_selection_phase when the user responds to the mandatory output-selection phase by choosing to continue grilling or stop without producing outputs.","If the user approves concrete output production, use grill_enter_output_phase instead."],parameters:H.Object({outcome:H.String({description:"Either 'continue-grilling' or 'stop-without-output'."}),summary:H.Optional(H.String({description:"Brief summary of the user's output-selection decision."}))}),async execute(V,Q,Y,$,Z){if(!j.active)return{content:[{type:"text",text:"No active Grill Me session."}],details:{phase:A(j),active:j.active}};if(A(j)!=="output-selection")return{content:[{type:"text",text:"No active output-selection phase. Call grill_enter_output_selection_phase before resolving output selection."}],details:{phase:A(j),active:j.active}};let W=String(Q.outcome??"").trim().toLowerCase();if(W==="continue-grilling"||W==="continue"||W==="grill"){if(j.phase="interview",j.outputPhase=!1,j.outputSelection=void 0,j.currentQuestion=void 0,j.alternatives=[],j.lastChangeSummary=Q.summary?`Output selection resolved: ${Q.summary}`:"Output selection resolved: continue grilling",X(),Z)z(Z);return{content:[{type:"text",text:"Returned to Grill Me interview mode. Ask the next Socratic question with grill_set_alternatives."}],details:{phase:A(j),active:j.active,outcome:W}}}if(W==="stop-without-output"||W==="stop"||W==="no-output"||W==="none"){if(j.active=!1,j.phase="interview",j.outputPhase=!1,j.outputSelection=void 0,j.approvedOutputPlan=void 0,j.currentQuestion=void 0,j.alternatives=[],j.lastChangeSummary=Q.summary?`Stopped after output selection: ${Q.summary}`:"Stopped after output selection without outputs",X(),Z)z(Z);return{content:[{type:"text",text:j.lastChangeSummary}],details:{phase:A(j),active:j.active,outcome:W}}}return{content:[{type:"text",text:"Unsupported outcome. Use 'continue-grilling' or 'stop-without-output'. If outputs were approved, call grill_enter_output_phase instead."}],details:{phase:A(j),active:j.active,outcome:W}}}}),J.registerTool({name:"grill_enter_output_phase",label:"Enter Grill Output Phase",description:"Mark that the user approved output production after mandatory output selection, allowing the assistant to use tools required to create the approved artifacts.",promptSnippet:"Enter approved Grill Me output-production phase",promptGuidelines:["Use grill_enter_output_phase only after grill_enter_output_selection_phase has run and the user explicitly approves a concrete output plan or preview during an active Grill Me session.","During output phase, do not refuse approved mutating output work merely because it mutates state, such as creating GitHub issues. If a tool, CLI, platform, or DM permission/authentication gate blocks the mutation, stop and ask the user for the needed permission, confirmation, credentials, or plan change; do not bypass it or broaden scope.",b],parameters:H.Object({outputPlan:H.String({description:"The approved output plan, including one or more outputs/artifacts/files/issues and intended tool use."})}),async execute(V,Q,Y,$,Z){if(!j.active)return{content:[{type:"text",text:"No active Grill Me session."}],details:{phase:A(j),outputPhase:!1,outputPlan:Q.outputPlan}};if(A(j)!=="output-selection"&&!j.outputPhase)return{content:[{type:"text",text:"Output production requires the mandatory output-selection phase first. Call grill_enter_output_selection_phase, ask the user to choose/approve outputs, then call grill_enter_output_phase."}],details:{phase:A(j),outputPhase:!1,outputPlan:Q.outputPlan}};if(j.phase="output",j.outputPhase=!0,j.approvedOutputPlan=Q.outputPlan,j.lastChangeSummary="Entered approved output phase",X(),Z)z(Z);return{content:[{type:"text",text:`Output phase enabled for approved plan:
|
|
108
108
|
${Q.outputPlan}
|
|
109
109
|
|
|
110
110
|
${b}`}],details:{phase:A(j),outputPhase:!0,outputPlan:Q.outputPlan}}}}),J.registerTool({name:"grill_finish_output_phase",label:"Finish Grill Output Phase",description:"Return an active Grill Me session to read-only interview/planning enforcement after output production.",promptSnippet:"Return Grill Me to read-only interview mode after output production",parameters:H.Object({summary:H.Optional(H.String({description:"Brief summary of outputs created."}))}),async execute(V,Q,Y,$,Z){if(j.phase="interview",j.outputPhase=!1,j.outputSelection=void 0,j.approvedOutputPlan=void 0,j.lastChangeSummary=Q.summary?`Finished output phase: ${Q.summary}`:"Finished output phase",X(),Z)z(Z);return{content:[{type:"text",text:j.lastChangeSummary}],details:{phase:A(j),outputPhase:!1,summary:Q.summary}}}}),J.on("tool_call",async(V)=>{if(!j.active||j.outputPhase)return;if(V.toolName==="edit"||V.toolName==="write")return{block:!0,reason:"Grill Me is read-only until the mandatory output-selection phase runs and the user approves a concrete output plan. Call grill_enter_output_selection_phase first, then grill_enter_output_phase before writing artifacts."};if(V.toolName==="bash"){let Q=String(V.input?.command??"");if(!Yj(Q))return{block:!0,reason:`Grill Me read-only mode blocked a potentially mutating command. Run the mandatory output-selection phase with grill_enter_output_selection_phase, get output approval, then call grill_enter_output_phase first.
|
|
111
|
-
Command: ${Q}`}}}),J.on("before_agent_start",async(V)=>{if(!j.active)return;let Q=["Use one thorough default style throughout the interview.","Be relentlessly curious but collaborative: challenge vague answers, surface contradictions, and test assumptions without changing persona.","Ask enough follow-up questions to resolve the decision tree. Prefer one more high-value question over premature readiness.","Maintain a coverage checklist and decision-branch ledger in the checkpoint; mark branches resolved, deferred, or still open as understanding evolves.","
|
|
111
|
+
Command: ${Q}`}}}),J.on("before_agent_start",async(V)=>{if(!j.active)return;let Q=["Use one thorough default style throughout the interview.","Be relentlessly curious but collaborative: challenge vague answers, surface contradictions, and test assumptions without changing persona.","Ask enough follow-up questions to resolve the decision tree. Prefer one more high-value question over premature readiness.","Maintain a coverage checklist and decision-branch ledger in the checkpoint; mark branches resolved, deferred, or still open as understanding evolves.","Walk dependent branches one at a time. If an answer changes upstream assumptions, revisit affected downstream decisions before moving on.","Do not enter output selection until major objective, scope, constraints, dependencies, risks, validation, and output branches are resolved or explicitly deferred."].join(`
|
|
112
112
|
- `),Y={off:"Do not proactively inspect files or research. Ask the user instead unless they explicitly provide context.",ask:"If a question could be answered by inspecting files/code/research, ask permission before doing so.",auto:"For coding/project contexts, if a question can be answered by inspecting available files/code, inspect instead of asking. Use read-only tools during interview mode."},$=A(j),Z=$==="output"?`Approved output phase: produce only the approved outputs. If a required mutation is blocked by permissions, auth, or repo setup, ask the user instead of bypassing or faking success. ${b} When done, call grill_finish_output_phase.`:$==="output-selection"?"You are in the mandatory output-selection phase. Do not ask new interview questions unless the user chooses to continue grilling. Ask the user to choose outputs/continue/review/stop from the active output-selection alternatives. If they approve concrete output production, call grill_enter_output_phase. If they choose to continue or stop without output, call grill_finish_output_selection_phase.":"You are in read-only interview mode. Do not implement, write files, create issues, install packages, run mutating commands, or stop the Grill Me work. When ready to end the interview, first update the checkpoint if needed, then call grill_enter_output_selection_phase to enter the mandatory hardcoded output-selection phase before output production or stopping.",W=j.outputSelection?`
|
|
113
113
|
|
|
114
114
|
Active output selection:
|
|
@@ -3,14 +3,6 @@
|
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"description": "Dedicated imagen.py-based image generation extension for DM using active Ultradex/Codex accounts",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"files": [
|
|
7
|
-
"index.js",
|
|
8
|
-
"src/",
|
|
9
|
-
"vendor/",
|
|
10
|
-
"skills/",
|
|
11
|
-
"README.md",
|
|
12
|
-
"test/"
|
|
13
|
-
],
|
|
14
6
|
"keywords": [
|
|
15
7
|
"duckmind",
|
|
16
8
|
"dm",
|
|
@@ -13,17 +13,6 @@
|
|
|
13
13
|
"agents",
|
|
14
14
|
"cli"
|
|
15
15
|
],
|
|
16
|
-
"files": [
|
|
17
|
-
"src/",
|
|
18
|
-
"test/",
|
|
19
|
-
"agents/",
|
|
20
|
-
"prompts/",
|
|
21
|
-
"skills/",
|
|
22
|
-
"README.md",
|
|
23
|
-
"CHANGELOG.md",
|
|
24
|
-
"banner.png",
|
|
25
|
-
"install.mjs"
|
|
26
|
-
],
|
|
27
16
|
"dm": {
|
|
28
17
|
"extensions": [
|
|
29
18
|
"./src/extension/index.js"
|
|
@@ -1,9 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{spawn as
|
|
3
|
-
[greedysearch] Available engines: ${Object.keys(Y).join(", ")}
|
|
4
|
-
`);if(X.length>0)return X;process.stderr.write(`[greedysearch] Warning: no valid engines in ${$}, falling back to defaults: ${H.join(", ")}
|
|
5
|
-
`)}}}catch{}return H}function f(){try{if(!W(j))R(j,{recursive:!0});if(!W($))x($,JSON.stringify({engines:H,synthesizer:b},null,2)+`
|
|
6
|
-
`,"utf8")}catch{}}f();var k=["gemini","chatgpt"];function _(){try{if(W($)){let K=w($,"utf8"),Q=JSON.parse(K);if(typeof Q.synthesizer==="string"){let X=Q.synthesizer.toLowerCase();if(k.includes(X))return X;process.stderr.write(`[greedysearch] Warning: unknown synthesizer "${Q.synthesizer}" in ${$}
|
|
7
|
-
[greedysearch] Available synthesizers: ${k.join(", ")}
|
|
8
|
-
[greedysearch] Falling back to default: ${b}
|
|
9
|
-
`)}}}catch{}return b}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"},s=y();var d=_(),r=Math.max(1,Number.parseInt(process.env.GREEDY_FETCH_CONCURRENCY||"5",10)||5);process.env.CDP_PROFILE_DIR=Z;function O(K){return String(K||"").trim()==="existing"}var h=Z,C=G,D=g,B=process.argv.slice(2),J=null,A=B.indexOf("--mode");if(A!==-1)J=B[A+1]||null,B.splice(A,2);if(J&&!["visible","headless"].includes(J))console.error(`Invalid --mode ${J}. Use visible or headless.`),process.exit(2);if(!L(C))console.error(`GreedySearch Chrome is not running (missing ${C}). Launch with bin/visible.mjs or bin/launch.mjs.`),process.exit(1);if(J){let K=L(D)?P(D,"utf8").trim():"unknown";if(K!==J&&!(J==="visible"&&O(K)))console.error(`GreedySearch Chrome is ${K}, not ${J}. Refusing to attach.`),process.exit(1)}var I=new URL("./cdp.mjs",import.meta.url).pathname.replace(/^\/([A-Z]:)/,"$1"),m=S(U(),[I,...B],{stdio:"inherit",env:{...process.env,CDP_PROFILE_DIR:h}});m.on("close",(K)=>process.exit(K??0));
|
|
2
|
+
import{spawn as K}from"node:child_process";import{existsSync as J,readFileSync as N}from"node:fs";var Q=GREEDY_PROFILE_DIR,G=ACTIVE_PORT_FILE,H=CHROME_MODE_FILE,v=process.argv.slice(2),k=null,z=v.indexOf("--mode");if(z!==-1)k=v[z+1]||null,v.splice(z,2);if(k&&!["visible","headless"].includes(k))console.error(`Invalid --mode ${k}. Use visible or headless.`),process.exit(2);if(!J(G))console.error(`GreedySearch Chrome is not running (missing ${G}). Launch with bin/visible.mjs or bin/launch.mjs.`),process.exit(1);if(k){let q=J(H)?N(H,"utf8").trim():"unknown";if(q!==k&&!(k==="visible"&&isExistingBrowserMode(q)))console.error(`GreedySearch Chrome is ${q}, not ${k}. Refusing to attach.`),process.exit(1)}var U=new URL("./cdp.mjs",import.meta.url).pathname.replace(/^\/([A-Z]:)/,"$1"),W=K(nodeRuntimeCommand(),[U,...v],{stdio:"inherit",env:{...process.env,CDP_PROFILE_DIR:Q}});W.on("close",(q)=>process.exit(q??0));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{execSync as
|
|
3
|
-
`)[0]):null}catch{return null}}function
|
|
4
|
-
${
|
|
2
|
+
import{execSync as c,spawn as g}from"node:child_process";import{existsSync as u,mkdirSync as x,readFileSync as k,unlinkSync as Y,writeFileSync as B}from"node:fs";import{platform as _,tmpdir as w}from"node:os";import{join as O}from"node:path";var b=w().replaceAll("\\","/"),e=9222,p=O(w(),"greedysearch-chrome-profile"),h=`${b}/greedysearch-chrome.pid`,l=`${b}/greedysearch-chrome-mode`;function m(o){try{if(_()==="win32"){let C=c("netstat -ano -p TCP 2>nul",{encoding:"utf8"}),a=new RegExp(String.raw`TCP\s+\S+:${o}\s+\S+:0\s+LISTENING\s+(\d+)`,"i");return(C.match(a)||[])[1]?parseInt(C.match(a)[1]):null}let r=c(`lsof -i :${o} -t 2>/dev/null || ss -tlnp 2>/dev/null | grep :${o} | grep -oP 'pid=\\K\\d+'`,{encoding:"utf8"}).trim();return r?parseInt(r.split(`
|
|
3
|
+
`)[0]):null}catch{return null}}function f(){let o=m(e);if(!o)return!1;try{if(_()==="win32")c(`taskkill /F /PID ${o}`,{stdio:"ignore"});else process.kill(o,"SIGKILL");return!0}catch{return!1}}function H(){for(let o of[h,l])try{Y(o)}catch{}}async function U(){let{ok:o,body:r}=await probe();if(!o){console.log("Not running.");return}let C=u(l)?k(l,"utf8").trim():"unknown",a=u(h)?k(h,"utf8").trim():"none",n=m(e)||"unknown",{Browser:s}=JSON.parse(r);console.log(`Running: ${s}`),console.log(` Mode: ${C}`),console.log(` Port: ${e}`),console.log(` PID file: ${a}`),console.log(` PID actual:${n}`)}async function K(){let{ok:o}=await probe();if(!o){console.log("Not running — nothing to kill."),H();return}console.log("Killing browser on port 9222..."),f(),H(),await new Promise((C)=>setTimeout(C,1500));let{ok:r}=await probe();console.log(r?"FAILED — still running.":"Killed.")}async function R(o){let{ok:r}=await probe();if(r){let A=u(l)?k(l,"utf8").trim():"unknown";if(A===o){console.log(`Already running in ${o} mode.`);return}console.log(`${A} browser running — killing to switch to ${o}...`),f(),H(),await new Promise((i)=>setTimeout(i,1500))}if(!(process.env.CHROME_PATH||findChrome()))console.error("Chrome not found."),process.exit(1);let a=o==="headless",n=[`--remote-debugging-port=${e}`,"--disable-features=DevToolsPrivacyUI","--no-first-run","--no-default-browser-check","--disable-default-apps","--disable-blink-features=AutomationControlled","--window-size=1920,1080",`--user-data-dir=${p}`,"--profile-directory=Default"];if(a){if(n.push("--headless=new","--disable-gpu","--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"),_()==="win32")n.push("--disable-software-rasterizer")}n.push("about:blank"),x(p,{recursive:!0}),console.log(`Launching ${o} ${browser.label} on port ${e}...`);let s=g(browser.path,n,{detached:!0,stdio:"ignore"});s.unref(),B(h,String(s.pid)),B(l,o);for(let A=0;A<30;A++){await new Promise((t)=>setTimeout(t,500));let{ok:i}=await probe();if(i){try{let{body:t}=await probe(),{webSocketDebuggerUrl:W}=JSON.parse(t),G=new URL(W).pathname;B(`${p}/DevToolsActivePort`,`${e}
|
|
4
|
+
${G}`)}catch{}console.log("Ready.");return}}console.error("Timeout — Chrome did not become ready."),process.exit(1)}var T=process.argv[2];switch(T){case"launch-headless":await R("headless");break;case"launch-visible":await R("visible");break;case"kill":await K();break;case"status":await U();break;default:console.log(`Usage: node bin/gschrome.mjs <command>
|
|
5
5
|
|
|
6
6
|
Commands:
|
|
7
7
|
launch-headless Start headless Chrome on port 9222
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{execSync as c,spawn as YC}from"node:child_process";import{existsSync as EC,mkdirSync as GC,readFileSync as u,unlinkSync as
|
|
2
|
+
import{execSync as c,spawn as YC}from"node:child_process";import{existsSync as EC,mkdirSync as GC,readFileSync as u,unlinkSync as D,writeFileSync as $}from"node:fs";import MC from"node:http";import{platform as p,tmpdir as g}from"node:os";import{join as I}from"node:path";import{existsSync as N}from"node:fs";import{platform as V}from"node:os";function l(C=V()){if(C==="win32")return{cloak:["C:/Program Files/CloakBrowser/CloakBrowser.exe","C:/Program Files (x86)/CloakBrowser/CloakBrowser.exe"],chrome:["C:/Program Files/Google/Chrome/Application/chrome.exe","C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"]};if(C==="darwin")return{cloak:["/Applications/CloakBrowser.app/Contents/MacOS/CloakBrowser","/Applications/Cloak Browser.app/Contents/MacOS/CloakBrowser"],chrome:["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium"]};return{cloak:["/usr/bin/cloakbrowser","/usr/local/bin/cloakbrowser","/opt/CloakBrowser/CloakBrowser"],chrome:["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium-browser","/usr/bin/chromium","/snap/bin/chromium"]}}function L(C,A=N){return C.find((_)=>_&&A(_))||null}function a(C,A){for(let _ of A){let R=C[_]?.trim();if(R)return{key:_,path:R}}return null}function v(C,A){if(C==="chrome"||A==="CHROME_PATH")return"Chrome";if(C==="cloak"||A==="DM_CUA_CLOAK_PATH"||A==="CLOAKBROWSER_BINARY_PATH")return"CloakBrowser";return"browser"}function S({env:C=process.env,platformName:A=V(),exists:_=N}={}){let R=(C.GREEDY_SEARCH_BROWSER||C.DM_CUA_BROWSER||"auto").toLowerCase(),O=a(C,R==="chrome"?["GREEDY_SEARCH_BROWSER_PATH","DM_CUA_BROWSER_PATH","CHROME_PATH"]:["GREEDY_SEARCH_BROWSER_PATH","DM_CUA_BROWSER_PATH","DM_CUA_CLOAK_PATH","CLOAKBROWSER_BINARY_PATH","CHROME_PATH"]);if(O)return{path:O.path,label:v(R,O.key)};let W=l(A);if(R==="cloak")return{path:L(W.cloak,_),label:"CloakBrowser"};if(R==="chrome")return{path:L(W.chrome,_),label:"Chrome"};let K=L(W.cloak,_);return{path:K||L(W.chrome,_),label:K?"CloakBrowser":"Chrome"}}import{existsSync as h,mkdirSync as o,readFileSync as J,renameSync as r,unlinkSync as n,writeFileSync as U}from"node:fs";import i from"node:http";import{platform as m}from"node:os";import{dirname as s}from"node:path";var x=[9222,9223],d=/^(0|false|no|off)$/i;function t(C){return[...new Set(C.filter(Boolean))]}function w(C,A="localhost"){let _=String(C||"").trim().split(/\r?\n/).map((O)=>O.trim()).filter(Boolean);if(_.length===0)throw Error("empty DevToolsActivePort");let[R,B=""]=_;if(/^wss?:\/\//i.test(R))return R;if(R.includes(":"))return`ws://${R}${B}`;return`ws://${A}:${R}${B}`}function q(C,A="explicit"){let _=new URL(C),R=_.protocol==="wss:"?"wss:":"ws:",B=_.port?Number.parseInt(_.port,10):R==="wss:"?443:80;return{source:A,wsUrl:`${R}//${_.host}${_.pathname}${_.search}`,host:_.hostname,port:B,path:`${_.pathname}${_.search}`,httpUrl:`http://${_.hostname}:${B}`}}function y(C=process.env){return![C.GREEDY_SEARCH_REUSE_EXISTING_BROWSER,C.DM_CUA_REUSE_EXISTING_BROWSER].some((A)=>A!==void 0&&d.test(String(A)))}function Q(C){let A=Number.parseInt(String(C??""),10);return Number.isInteger(A)&&A>0&&A<65536?A:null}function e(C){if(!C)return null;let A=String(C).trim();if(!A)return null;let _=new URL(A.includes("://")?A:`http://${A}`),R=Q(_.port)||(_.protocol==="https:"?443:80);return{host:_.hostname,port:R,source:`env:${A}`}}function CC(C){if(!C)return[];return String(C).split(/[,\s]+/).map(Q).filter(Boolean)}function AC({env:C=process.env,platformName:A=m(),procVersionText:_=null}={}){if(A!=="linux")return!1;if(C.WSL_DISTRO_NAME||C.WSL_INTEROP)return!0;let R=_??(()=>{try{return J("/proc/version","utf8")}catch{return""}})();return/microsoft|wsl/i.test(R)}function _C({env:C=process.env,platformName:A=m(),procVersionText:_=null,resolvConfText:R=null}={}){let B=["localhost","127.0.0.1"];if(AC({env:C,platformName:A,procVersionText:_})){let W=(R??(()=>{try{return J("/etc/resolv.conf","utf8")}catch{return""}})()).match(/^\s*nameserver\s+([^\s#]+)/m);if(W)B.push(W[1]);B.push("host.docker.internal")}return t(B)}function RC({env:C=process.env,hosts:A=_C({env:C}),autoPorts:_=x,excludePorts:R=[]}={}){let B=[];for(let H of["GREEDY_SEARCH_CDP_WS_URL","DM_CUA_CDP_WS_URL","CDP_WS_URL"])if(C[H])B.push({wsUrl:C[H],source:`env:${H}`});for(let H of["GREEDY_SEARCH_CDP_URL","DM_CUA_CDP_URL","CDP_URL"])try{let Y=e(C[H]);if(Y)B.push(Y)}catch{}for(let H of["GREEDY_SEARCH_EXISTING_CDP_PORT","DM_CUA_EXISTING_CDP_PORT","GREEDY_SEARCH_CDP_PORT","DM_CUA_CDP_PORT"]){let Y=Q(C[H]);if(!Y)continue;for(let M of A)B.push({host:M,port:Y,source:`env:${H}`})}let O=CC(C.GREEDY_SEARCH_EXISTING_CDP_PORTS);for(let H of O)for(let Y of A)B.push({host:Y,port:H,source:"env:GREEDY_SEARCH_EXISTING_CDP_PORTS"});let W=new Set(R.filter(Boolean));if(y(C))for(let H of _){if(W.has(H))continue;for(let Y of A)B.push({host:Y,port:H,source:"auto"})}let K=new Set;return B.filter((H)=>{let Y=H.wsUrl||`${H.host}:${H.port}`;if(K.has(Y))return!1;return K.add(Y),!0})}async function BC(C,{timeoutMs:A=700}={}){if(C.wsUrl)return q(C.wsUrl,C.source);let _=C.host||"localhost",R=C.port;if(!R)return null;let B=await new Promise((O)=>{let W=i.get({host:_,port:R,path:"/json/version",timeout:A},(K)=>{let H="";K.setEncoding("utf8"),K.on("data",(Y)=>H+=Y),K.on("end",()=>O(K.statusCode===200?H:null))});W.on("error",()=>O(null)),W.setTimeout(A,()=>{W.destroy(),O(null)})});if(!B)return null;try{let O=JSON.parse(B);if(!O.webSocketDebuggerUrl)return null;let W=q(O.webSocketDebuggerUrl,C.source),K=W.path||new URL(O.webSocketDebuggerUrl).pathname;return{...W,host:_,port:R,httpUrl:`http://${_}:${R}`,wsUrl:`ws://${_}:${R}${K}`,path:K}}catch{return null}}async function OC(C={}){for(let A of RC(C)){let _=await BC(A,C);if(_)return _}return null}function HC(C){if(!C)throw Error("missing CDP endpoint");let A=new URL(C.wsUrl);return`${A.host}
|
|
3
3
|
${A.pathname}${A.search}
|
|
4
|
-
`}function
|
|
5
|
-
${
|
|
4
|
+
`}function KC(C,A){o(s(C),{recursive:!0});let _=`${C}.tmp-${process.pid}`;U(_,HC(A),"utf8");try{n(C)}catch{}r(_,C)}async function P({activePortFile:C,modeFile:A,env:_=process.env,excludePorts:R=[],autoPorts:B=x}={}){if(!y(_))return null;let O=await OC({env:_,excludePorts:R,autoPorts:B});if(!O)return null;if(KC(C,O),A)U(A,"existing","utf8");return O}function WC(C){return String(C||"").trim()==="existing"}function X(C,A){if(!A||!h(A))return!1;if(!WC(J(A,"utf8")))return!1;return!!C&&h(C)}var E=9222,f=I(g(),"greedysearch-chrome-profile"),G=I(f,"DevToolsActivePort"),z=I(g(),"greedysearch-chrome.pid"),b=I(g(),"greedysearch-chrome-mode");function j(){if(!EC(z))return!1;let C=Number.parseInt(u(z,"utf8").trim(),10);if(!C)return!1;try{return process.kill(C,0),C}catch{return!1}}function k(C){try{if(p()==="win32"){let _=c("netstat -ano -p TCP 2>nul",{encoding:"utf8"}),R=new RegExp(String.raw`TCP\s+[^\s]*:${C}\s+[^\s]*:0\s+LISTENING\s+(\d+)`,"i"),B=_.match(R);return B?Number.parseInt(B[1],10):null}}catch{return null}}function Z(C){try{if(p()==="win32")c(`taskkill /F /PID ${C} /T`,{stdio:"ignore"});else process.kill(C,"SIGKILL");return!0}catch{return!1}}function T(C,A=1000){return new Promise((_)=>{let R=MC.get(C,(B)=>{let O="";B.on("data",(W)=>O+=W),B.on("end",()=>_({ok:B.statusCode===200,body:O}))});R.on("error",()=>_({ok:!1})),R.setTimeout(A,()=>{R.destroy(),_({ok:!1})})})}async function bC(C){try{let A=await T(`http://localhost:${C}/json/version`).then((H)=>JSON.parse(H.body)),R=(await T(`http://localhost:${C}/json/list`).then((H)=>JSON.parse(H.body))).find((H)=>H.type==="page")?.id;if(!R)return;let B=A.webSocketDebuggerUrl;if(typeof B!=="string")return;let O=new URL(B);if(O.hostname!=="localhost"&&O.hostname!=="127.0.0.1")return;if(!/^ws:\/\/localhost:\d+/.test(`ws://${O.host}`))return;let W=O.pathname,K=new WebSocket(`ws://localhost:${C}${W}`);await new Promise((H)=>{K.onopen=()=>K.send(JSON.stringify({id:1,method:"Browser.getWindowForTarget",params:{targetId:R}})),K.onmessage=(Y)=>{let M=JSON.parse(Y.data);if(M.id===1&&M.result?.windowId)K.send(JSON.stringify({id:2,method:"Browser.setWindowBounds",params:{windowId:M.result.windowId,bounds:{windowState:"minimized"}}}));else if(M.id===2)K.close(),H()},K.onerror=()=>{K.close(),H()},setTimeout(()=>{try{K.close()}catch{}H()},5000)})}catch{}}async function DC(C=15000){let A=Date.now()+C;while(Date.now()<A){let{ok:_,body:R}=await T(`http://localhost:${E}/json/version`,1500);if(_)try{let{webSocketDebuggerUrl:B}=JSON.parse(R),O=new URL(B).pathname;return $(G,`${E}
|
|
5
|
+
${O}`,"utf8"),!0}catch{}await new Promise((B)=>setTimeout(B,400))}return!1}function F(){let C=j();if(C)Z(C);let A=k(E);if(A&&A!==C)Z(A);try{D(z)}catch{}try{D(G)}catch{}try{D(b)}catch{}return new Promise((_)=>{let R=Date.now(),B=()=>{let O=k(E);if(!O)return _(!0);if(Date.now()-R>5000)return _(!1);Z(O),setTimeout(B,500)};B()})}async function LC(){let C=process.argv[2];if(C==="--kill"){if(X(G,b)){try{D(G)}catch{}try{D(b)}catch{}console.log("Detached from existing browser CDP endpoint; no browser process was killed.");return}await F(),console.log("Browser stopped.");return}if(C==="--status"){if(X(G,b)){try{let H=w(u(G,"utf8"));console.log(`Reusing existing browser — ${H}`)}catch{console.log("Reusing existing browser.")}return}let K=j()||k(E);if(K)console.log(`Running — pid ${K}, port ${E}`);else console.log("Not running.");return}let A=await P({activePortFile:G,modeFile:b,excludePorts:j()?[E]:[],autoPorts:j()?[9223]:[E,9223]});if(A){console.log(`Reusing existing browser CDP endpoint ${A.httpUrl} (${A.source}).`);return}console.log("Stopping any existing browser on port 9222..."),await F();let _=S();if(!_.path)console.error("CloakBrowser/Chrome not found. Set GREEDY_SEARCH_BROWSER_PATH, DM_CUA_BROWSER_PATH, DM_CUA_CLOAK_PATH, CLOAKBROWSER_BINARY_PATH, or CHROME_PATH."),process.exit(1);GC(f,{recursive:!0});let R=[`--remote-debugging-port=${E}`,"--disable-features=DevToolsPrivacyUI","--no-first-run","--no-default-browser-check","--disable-default-apps",`--user-data-dir=${f}`,"--profile-directory=Default","--new-window","about:blank"];console.log("Launching visible Chrome...");let B=YC(_.path,R,{detached:!0,stdio:"ignore"});B.unref();let O=B.pid;if($(z,String(O)),$(b,"visible","utf8"),console.log(`Chrome PID: ${O}`),!await DC())console.error("Chrome did not become ready within 15s."),process.exit(1);await bC(E),console.log("Visible Chrome ready on port 9222."),console.log("Keep this terminal open to keep Chrome alive.")}LC();
|