brass-runtime 1.11.1 → 1.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,8 +45,7 @@ npm i brass-runtime
45
45
  ### Run an effect
46
46
 
47
47
  ```ts
48
- import { succeed } from "brass-runtime";
49
- import { Runtime, toPromise } from "brass-runtime/runtime";
48
+ import { Runtime, succeed, toPromise } from "brass-runtime";
50
49
 
51
50
  const runtime = new Runtime({ env: {} });
52
51
 
@@ -57,8 +56,7 @@ console.log(value); // 123
57
56
  ### Structured concurrency with Scope
58
57
 
59
58
  ```ts
60
- import { withScope } from "brass-runtime/scope";
61
- import { Runtime } from "brass-runtime/runtime";
59
+ import { Runtime, withScope } from "brass-runtime";
62
60
 
63
61
  const runtime = new Runtime({ env: {} });
64
62
 
@@ -91,8 +89,8 @@ A ZIO-style HTTP client built on top of fibers and `Async`.
91
89
  Example:
92
90
 
93
91
  ```ts
92
+ import { Runtime, toPromise } from "brass-runtime";
94
93
  import { httpClientStream } from "brass-runtime/http";
95
- import { toPromise, Runtime } from "brass-runtime/runtime";
96
94
 
97
95
  type Post = { id: number; title: string; body: string };
98
96
 
@@ -106,6 +104,36 @@ console.log(res.status, res.value.title);
106
104
 
107
105
  ---
108
106
 
107
+ ### 🤖 Brass Agent (experimental)
108
+
109
+ A CLI-first coding agent built on top of the runtime. Brass Agent is currently experimental: it can inspect a workspace, discover validation commands, gather bounded context, ask an LLM for a patch, apply/rollback patches through explicit policies, and expose a thin VS Code extension over the CLI protocol.
110
+
111
+ Start here:
112
+
113
+ - [Install and configure Brass Agent](./docs/agent-install-and-configure.md)
114
+ - [Declarative optimized planning roadmap](./docs/agent-declarative-optimized-planning.md)
115
+ - [Brass Agent CLI](./docs/agent-cli.md)
116
+ - [Project intelligence](./docs/agent-project-intelligence.md)
117
+ - [Global usage and workspace discovery](./docs/agent-global-usage.md)
118
+ - [VS Code local install](./docs/agent-vscode-install.md)
119
+ - [VS Code auto-discovery](./docs/agent-vscode-auto-discovery.md)
120
+ - [VS Code model setup](./docs/agent-vscode-model-setup.md)
121
+ - [VS Code chat layout / focus mode](./docs/agent-vscode-chat-layout.md)
122
+
123
+ ```bash
124
+ npm run agent:vscode:install
125
+ # then open any repo in VS Code and use Brass Agent -> Chat
126
+
127
+ npm run build
128
+ npm run agent:link
129
+ brass-agent --where
130
+ brass-agent --doctor
131
+ brass-agent --init
132
+ brass-agent --preset inspect
133
+ ```
134
+
135
+ ---
136
+
109
137
  ### 🌊 Streams (ZStream-like)
110
138
 
111
139
  Pull-based, resource-aware streams with backpressure.
@@ -129,6 +157,8 @@ Examples:
129
157
  - [Observability: Hooks & Tracing](./docs/observability.md)
130
158
  - [HTTP module](./docs/http.md)
131
159
  - [Modules overview](./docs/modules.md)
160
+ - [Install and configure Brass Agent](./docs/agent-install-and-configure.md)
161
+ - [Declarative optimized planning roadmap](./docs/agent-declarative-optimized-planning.md)
132
162
 
133
163
  ---
134
164
 
@@ -186,3 +216,16 @@ Examples:
186
216
  ## License
187
217
 
188
218
  MIT License © 2025
219
+
220
+
221
+ ## Brass Agent local smoke tests
222
+
223
+ Run local smoke tests without CI or a real LLM provider:
224
+
225
+ ```bash
226
+ npm run agent:test:local
227
+ ```
228
+
229
+ This builds the project and runs a fake-LLM smoke test against the `brass-agent` CLI.
230
+
231
+ See also: [Agent language and workspace setup UX](docs/agent-language-workspace-ux.md).
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';var chunk63ODH5W4_cjs=require('../../chunk-63ODH5W4.cjs'),chunkT3QEEHK6_cjs=require('../../chunk-T3QEEHK6.cjs'),fs=require('fs'),promises=require('fs/promises'),path=require('path'),child_process=require('child_process');var Xe=new Function("specifier","return import(specifier)"),Ze=e=>["y","yes","approve","approved","si","s\xED","s"].includes(e),en=e=>["n","no","reject","rejected","deny","denied"].includes(e),nn=(e,n)=>{let t=e.trim().toLowerCase();return t?Ze(t)?{type:"approved"}:en(t)?{type:"rejected",reason:"Rejected by user."}:{type:"rejected",reason:`Unrecognized approval answer: ${e}`}:n.defaultAnswer==="approve"?{type:"approved"}:{type:"rejected",reason:"Rejected by default answer."}},Pe=(e={})=>({request:n=>chunkT3QEEHK6_cjs.j((t,o)=>{let r=false,a;return Xe("node:readline/promises").then(({createInterface:l})=>{if(r)return;let s=e.input??process.stdin,c=e.output??process.stderr??process.stdout,h=n.defaultAnswer==="approve"?"Y/n":"y/N";return a=l({input:s,output:c}),c?.write?.(`
3
+ Approval required (${n.risk})
4
+ `),c?.write?.(`Action: ${chunk63ODH5W4_cjs.T(n.action)}
5
+ `),c?.write?.(`Reason: ${n.reason}
6
+ `),a.question(`Approve? [${h}] `)}).then(l=>{l===void 0||r||(r=true,a?.close?.(),o(chunkT3QEEHK6_cjs.u.succeed(nn(l,n))));}).catch(l=>{r||(r=true,a?.close?.(),o(chunkT3QEEHK6_cjs.u.failCause(chunkT3QEEHK6_cjs.t.fail({_tag:"AgentLoopError",message:`Approval prompt failed: ${String(l)}`}))));}),()=>{r||(r=true,a?.close?.());}})});var _=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),N=e=>{try{return JSON.parse(fs.readFileSync(e,"utf8"))}catch{return}},Le=(e,n)=>{let t=path.resolve(e);for(;;){let o=path.join(t,"package.json"),r=N(o);if(_(r)&&r.name===n)return t;let a=path.resolve(t,"..");if(a===t)return;t=a;}},M=(e,n=["--version"],t)=>{let o=child_process.spawnSync(e,[...n],{cwd:t,encoding:"utf8",shell:false,timeout:1e4});if(!(o.error||(o.status??0)!==0))return `${o.stdout??""}${o.stderr??""}`.trim().split(/\r?\n/g)[0]},L=e=>!!(e&&process.env[e]),ln=()=>process.env.BRASS_AGENT_VSCODE_EXTENSION==="1",cn=e=>{let n=N(path.join(e,"package.json")),t=_(n)&&typeof n.packageManager=="string"?n.packageManager.split("@")[0]:void 0;return t?{manager:t,source:"package.json packageManager"}:fs.existsSync(path.join(e,"pnpm-lock.yaml"))?{manager:"pnpm",source:"pnpm-lock.yaml"}:fs.existsSync(path.join(e,"yarn.lock"))?{manager:"yarn",source:"yarn.lock"}:fs.existsSync(path.join(e,"bun.lockb"))||fs.existsSync(path.join(e,"bun.lock"))?{manager:"bun",source:"bun lockfile"}:fs.existsSync(path.join(e,"package-lock.json"))||fs.existsSync(path.join(e,"npm-shrinkwrap.json"))?{manager:"npm",source:"npm lockfile"}:{manager:"npm",source:"fallback"}},pn=e=>_(e)&&_(e.scripts)?Object.entries(e.scripts).filter(([,n])=>typeof n=="string").map(([n])=>n).sort():[],dn=(e,n)=>e.find(t=>n.some(o=>o.test(t))),un=(e,n)=>{let t=pn(n),o=["Cargo.toml","Cargo.lock","src-tauri/tauri.conf.json","apps/desktop/package.json","apps/desktop/src-tauri/tauri.conf.json","bridges/whatsmeow-bridge/Cargo.toml","apps","packages","bridges","turbo.json","nx.json","pnpm-workspace.yaml"].filter(s=>fs.existsSync(path.join(e,s))),r=[];_(n)&&r.push("node"),o.some(s=>s==="Cargo.toml"||s==="Cargo.lock"||s.endsWith("Cargo.toml"))&&r.push("rust"),(o.some(s=>s.includes("tauri"))||t.some(s=>s.includes("tauri")))&&r.push("tauri"),(o.some(s=>s.startsWith("apps"))||t.some(s=>s.includes("desktop")))&&r.push("desktop"),(o.some(s=>s.startsWith("bridges"))||t.some(s=>s.includes("bridge")))&&r.push("bridge"),o.some(s=>["apps","packages","bridges","turbo.json","nx.json","pnpm-workspace.yaml"].includes(s))&&r.push("monorepo");let a=dn(t,[/^repo:check$/,/^check$/,/(^|:)check($|:)/,/(^|:)doctor($|:)/,/(^|:)health($|:)/,/(^|:)verify($|:)/,/(^|:)validate($|:)/,/(^|:)ci($|:)/]),l=[`stacks: ${r.length>0?[...new Set(r)].join(", "):"none detected"}`,`markers: ${o.length>0?o.slice(0,8).join(", "):"none"}`,a?`likely validation: npm run ${a}`:"likely validation: none detected"];return {id:"workspace.projectProfile",label:"Workspace project profile",status:r.length>0?"ok":"skip",message:l.join(". ")}},gn=e=>{if(!e)return {id:"envFile",label:"Agent env file",status:"skip",message:"Env file loading did not run."};if(e.disabled)return {id:"envFile",label:"Agent env file",status:"skip",message:"Env file loading disabled by --no-env-file."};if(e.errors.length>0)return {id:"envFile",label:"Agent env file",status:"fail",message:e.errors.join("; ")};if(e.paths.length===0)return {id:"envFile",label:"Agent env file",status:"skip",message:"No .brass-agent.env, .env.local, or .env found in workspace; using exported shell environment only."};let n=[`Loaded ${e.paths.join(", ")}`];return e.loadedKeys.length>0&&n.push(`keys: ${e.loadedKeys.join(", ")}`),e.alreadySetKeys.length>0&&n.push(`already set by shell: ${e.alreadySetKeys.join(", ")}`),e.emptyKeys.length>0&&n.push(`empty keys skipped: ${e.emptyKeys.join(", ")}`),e.ignoredKeys.length>0&&n.push(`non-agent keys ignored: ${e.ignoredKeys.slice(0,8).join(", ")}${e.ignoredKeys.length>8?", ...":""}`),e.invalidLines.length>0&&n.push(`invalid lines: ${e.invalidLines.join(", ")}`),{id:"envFile",label:"Agent env file",status:e.loadedKeys.length>0||e.alreadySetKeys.length>0?"ok":"warn",message:n.join(". ")}},fn=e=>{let n=(process.env.BRASS_LLM_PROVIDER??e?.llm?.provider)?.trim().toLowerCase(),t=e?.llm?.apiKeyEnv;if(n==="fake")return {id:"llm",label:"LLM provider",status:"ok",message:"Fake LLM provider is selected."};if(n==="google"||n==="gemini"){let o=L(t)||L("BRASS_GOOGLE_API_KEY")||L("GOOGLE_API_KEY")||L("GEMINI_API_KEY");return {id:"llm",label:"LLM provider",status:o?"ok":"fail",message:o?`Google/Gemini provider is configured (${n}).`:"Google/Gemini provider is selected but no API key env var is set. Export GEMINI_API_KEY or put it in .env/.brass-agent.env."}}if(n==="openai"||n==="openai-compatible"){let o=!!(process.env.BRASS_LLM_ENDPOINT??e?.llm?.endpoint),r=L(t)||L("BRASS_LLM_API_KEY");return {id:"llm",label:"LLM provider",status:o&&r?"ok":"fail",message:o&&r?`OpenAI-compatible provider is configured (${n}).`:"OpenAI-compatible provider is selected but endpoint or API key env var is missing. Export BRASS_LLM_API_KEY or put it in .env/.brass-agent.env."}}return L("BRASS_GOOGLE_API_KEY")||L("GOOGLE_API_KEY")||L("GEMINI_API_KEY")?{id:"llm",label:"LLM provider",status:"ok",message:"Google/Gemini credentials are available and will be auto-detected."}:(process.env.BRASS_LLM_ENDPOINT??e?.llm?.endpoint)&&L("BRASS_LLM_API_KEY")?{id:"llm",label:"LLM provider",status:"ok",message:"OpenAI-compatible credentials are available and will be auto-detected."}:{id:"llm",label:"LLM provider",status:"warn",message:"No real LLM credentials found. The CLI will fall back to the fake provider unless config selects a real provider."}},mn=e=>{let n=N(path.join(e,".vscode","settings.json"));if(!_(n))return;let t=n["brassAgent.command"];return typeof t=="string"?t:void 0},yn=e=>{try{return fs.readdirSync(e).filter(n=>n.endsWith(".vsix")).sort().at(-1)}catch{return}},y=(e,n)=>{e.push(n);},_e=async e=>{let n=path.resolve(e.cwd),t=[],o=Le(n,"brass-runtime")??Le(process.cwd(),"brass-runtime"),r=Number(process.versions.node.split(".")[0]??"0");y(t,{id:"node",label:"Node.js",status:r>=18?"ok":"fail",message:`Node ${process.versions.node}${r>=18?"":" is too old; use Node 18 or newer."}`});let a=M("npm");y(t,{id:"npm",label:"npm",status:a?"ok":"fail",message:a?`npm ${a}`:"npm is not available on PATH."});let l=M("git");y(t,{id:"git",label:"git",status:l?"ok":"warn",message:l||"git is not available; patch apply/rollback uses git apply."});let s=M("rg");if(y(t,{id:"ripgrep",label:"ripgrep",status:s?"ok":"warn",message:s||"rg is not available; context discovery search will be limited."}),y(t,{id:"workspace",label:"Workspace",status:fs.existsSync(n)?"ok":"fail",message:fs.existsSync(n)?n:`Workspace does not exist: ${n}`}),e.workspaceDiscovery){let p=e.workspaceDiscovery;y(t,{id:"workspace.discovery",label:"Workspace discovery",status:p.disabled?"skip":p.marker?"ok":"warn",message:p.disabled?"Workspace discovery disabled by --no-discover-workspace.":p.marker?`${p.changed?`Resolved ${p.inputCwd} -> ${p.cwd}`:`Using ${p.cwd}`} via ${p.marker}.`:`No workspace marker found upward from ${p.inputCwd}; using input cwd.`});}let c=path.join(n,"package.json"),h=N(c);if(y(t,{id:"workspace.packageJson",label:"Workspace package.json",status:_(h)?"ok":"warn",message:_(h)?`Found ${c}`:"No package.json found in workspace; project command discovery may use fallbacks."}),_(h)){let p=_(h.scripts)?Object.keys(h.scripts):[];y(t,{id:"workspace.scripts",label:"Workspace scripts",status:p.length?"ok":"warn",message:p.length?`Scripts: ${p.slice(0,12).join(", ")}${p.length>12?", ...":""}`:"No package scripts found."});let g=cn(n),m=M(g.manager);y(t,{id:"workspace.packageManager",label:"Workspace package manager",status:m?"ok":"warn",message:m?`${g.manager} available (${g.source}): ${m}`:`${g.manager} inferred from ${g.source}, but command is not available on PATH.`});}if(y(t,un(n,h)),y(t,gn(e.envFileLoad)),y(t,fn(e.config)),y(t,{id:"config",label:"Agent config",status:e.configPath?"ok":"skip",message:e.configPath?`Loaded ${e.configPath}`:"No .brass-agent.json / brass-agent.config.json loaded; using built-in defaults and VS Code/CLI settings."}),e.includeVsCode!==false){let p=M(process.env.BRASS_CODE_CMD??"code");y(t,{id:"vscode.code",label:"VS Code CLI",status:p?"ok":"warn",message:p?`code ${p}`:"VS Code CLI `code` is not available on PATH; .vsix install needs it unless using the VS Code UI."});let g=mn(n),m=ln();y(t,{id:"vscode.settings",label:"VS Code extension setting",status:g?"ok":m?"skip":"warn",message:g?`brassAgent.command = ${g}`:m?`No workspace brassAgent.command needed; launched by the VS Code extension (${process.env.BRASS_AGENT_VSCODE_CLI_SOURCE??"auto"}).`:"No workspace .vscode/settings.json brassAgent.command found."});}if(o){let p=path.join(o,"src","agent","cli","main.ts"),g=path.join(o,"dist","agent","cli","main.cjs"),m=path.join(o,"extensions","vscode-brass-agent");y(t,{id:"repo.root",label:"brass-runtime repo",status:"ok",message:o}),y(t,{id:"repo.cliSource",label:"CLI source",status:fs.existsSync(p)?"ok":"fail",message:fs.existsSync(p)?`Found ${p}`:`Missing ${p}`}),y(t,{id:"repo.cliBuild",label:"CLI build",status:fs.existsSync(g)?"ok":"warn",message:fs.existsSync(g)?`Found ${g}`:"dist/agent/cli/main.cjs is missing; run npm run build."}),y(t,{id:"repo.extensionDir",label:"VS Code extension source",status:fs.existsSync(path.join(m,"package.json"))?"ok":"warn",message:fs.existsSync(path.join(m,"package.json"))?m:"extensions/vscode-brass-agent was not found."}),y(t,{id:"repo.extensionBuild",label:"VS Code extension build",status:fs.existsSync(path.join(m,"out","extension.js"))?"ok":"warn",message:fs.existsSync(path.join(m,"out","extension.js"))?"out/extension.js exists.":"Extension output missing; run npm run agent:vscode:package or compile the extension."});let S=yn(m);y(t,{id:"repo.extensionVsix",label:"VSIX package",status:S?"ok":"warn",message:S?`Found ${S}`:"No .vsix found in extensions/vscode-brass-agent."});let R=await promises.access(g,promises.constants.R_OK).then(()=>true).catch(()=>false);y(t,{id:"repo.cliReadable",label:"CLI artifact readable",status:R?"ok":"warn",message:R?"Built CLI artifact is readable.":"Built CLI artifact is not readable yet."});}else y(t,{id:"repo.root",label:"brass-runtime repo",status:"skip",message:"Not running inside a brass-runtime checkout; local source/build checks skipped."});let E=t.some(p=>p.status==="fail")?"fail":t.some(p=>p.status==="warn")?"warn":"ok";return {generatedAt:new Date().toISOString(),cwd:n,...e.configPath?{configPath:e.configPath}:{},...o?{repoRoot:o}:{},status:E,checks:t}},hn=e=>{switch(e){case "ok":return "\u2713";case "warn":return "!";case "fail":return "\u2717";case "skip":return "-"}},xe=e=>{console.log("brass-agent doctor"),console.log(`workspace: ${e.cwd}`),e.configPath&&console.log(`config: ${e.configPath}`),e.repoRoot&&console.log(`repo: ${e.repoRoot}`),console.log(`status: ${e.status}`),console.log("");for(let n of e.checks)console.log(`${hn(n.status)} ${n.label}: ${n.message}`);};var kn=[".brass-agent.env",".env.local",".env"],wn=new Set(["BRASS_LLM_PROVIDER","BRASS_FAKE_LLM_RESPONSE","BRASS_GOOGLE_API_KEY","GOOGLE_API_KEY","GEMINI_API_KEY","BRASS_GOOGLE_MODEL","BRASS_GOOGLE_API_VERSION","BRASS_GOOGLE_BASE_URL","BRASS_GOOGLE_ENDPOINT","BRASS_GOOGLE_SYSTEM_INSTRUCTION","BRASS_GOOGLE_TEMPERATURE","BRASS_GOOGLE_TOP_P","BRASS_GOOGLE_TOP_K","BRASS_GOOGLE_MAX_OUTPUT_TOKENS","BRASS_LLM_ENDPOINT","BRASS_LLM_API_KEY","BRASS_LLM_MODEL","BRASS_AGENT_APPROVAL","BRASS_AGENT_AUTO_APPROVE","BRASS_CODE_CMD"]),C=e=>Array.from(new Set(e)),Sn=e=>{if(e.length<2)return;let n=e[0];if(n!=='"'&&n!=="'"||e[e.length-1]!==n)return;let t=e.slice(1,-1);return n==="'"?t:t.replace(/\\n/g,`
7
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")},En=e=>{let n=e.trim();if(!n||n.startsWith("#"))return {type:"skip"};let t=n.startsWith("export ")?n.slice(7).trimStart():n,o=/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(t);if(!o)return {type:"invalid"};let r=o[1]??"",l=(o[2]??"").trim(),c=Sn(l)??l.replace(/\s+#.*$/u,"").trim();return {type:"assignment",key:r,value:c}},Rn=(e,n)=>n?[path.isAbsolute(n)?n:path.resolve(e,n)]:kn.map(t=>path.join(e,t)),Ce=e=>{let n=path.resolve(e.cwd),t=e.allowedExtraKeys?.filter(Boolean)??[],o=new Set([...wn,...t]),r=e.noEnvFile?[]:Rn(n,e.envFile),a=[],l=[],s=[],c=[],h=[],E=[],p=[];if(e.noEnvFile)return {cwd:n,disabled:true,filesChecked:[],paths:[],loadedKeys:[],alreadySetKeys:[],emptyKeys:[],ignoredKeys:[],invalidLines:[],errors:[]};for(let g of r){if(!fs.existsSync(g)){e.envFile&&p.push(`Env file does not exist: ${g}`);continue}a.push(g);let m;try{m=fs.readFileSync(g,"utf8").replace(/^\uFEFF/u,"");}catch(S){p.push(`Could not read env file ${g}: ${S instanceof Error?S.message:String(S)}`);continue}for(let[S,R]of m.split(/\r?\n/gu).entries()){let b=En(R);if(b.type!=="skip"){if(b.type==="invalid"){E.push(`${g}:${S+1}`);continue}if(!o.has(b.key)){h.push(b.key);continue}if(!b.value){c.push(b.key);continue}if(process.env[b.key]!==void 0){s.push(b.key);continue}process.env[b.key]=b.value,l.push(b.key);}}}return {cwd:n,disabled:false,...e.envFile?{explicitPath:path.isAbsolute(e.envFile)?e.envFile:path.resolve(n,e.envFile)}:{},filesChecked:r,paths:a,loadedKeys:C(l),alreadySetKeys:C(s),emptyKeys:C(c),ignoredKeys:C(h),invalidLines:C(E),errors:C(p)}};var Fe=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),On=e=>{try{return JSON.parse(fs.readFileSync(e,"utf8"))}catch{return}},Me=e=>{let n=On(path.join(e,"package.json"));return Fe(n)?n:void 0},$e=e=>{let n=e?.scripts;return Fe(n)?Object.entries(n).filter(([,t])=>typeof t=="string").map(([t])=>t).sort():[]},$=(e,n)=>n.some(t=>e.includes(t)),Cn=(e,n)=>{let t=typeof n?.packageManager=="string"?n.packageManager.split("@")[0]:void 0;return t==="npm"||t==="pnpm"||t==="yarn"||t==="bun"?t:fs.existsSync(path.join(e,"pnpm-lock.yaml"))?"pnpm":fs.existsSync(path.join(e,"yarn.lock"))?"yarn":fs.existsSync(path.join(e,"bun.lockb"))||fs.existsSync(path.join(e,"bun.lock"))?"bun":fs.existsSync(path.join(e,"package-lock.json"))||fs.existsSync(path.join(e,"npm-shrinkwrap.json"))?"npm":"auto"},In=e=>{switch(e){case "default":return;case "google":return {provider:"google",model:"gemini-2.5-flash",apiKeyEnv:"GEMINI_API_KEY",temperature:.2,maxOutputTokens:4096};case "openai-compatible":return {provider:"openai-compatible",endpoint:"https://api.openai.com/v1/chat/completions",model:"gpt-4.1",apiKeyEnv:"BRASS_LLM_API_KEY",temperature:.2};case "fake":return {provider:"fake",fakeResponse:"Fake plan from brass-agent init. Configure a real provider when ready."}}},Fn=(e,n)=>{let t=Me(e),o=$e(t),r=$(o,["typecheck","type-check","check-types","tsc","check"]),a=$(o,["lint","lint:ci"]),l=In(n);return {mode:"propose",approval:"auto",...l?{llm:l}:{},project:{packageManager:Cn(e,t),testScriptNames:["test","test:ci","test:unit"],includeTypecheck:r,includeLint:a,maxValidationCommands:2},context:{enabled:true,maxSearchQueries:3,maxFiles:4,maxSearchResults:40,globs:["*.ts","*.tsx","*.js","*.jsx","*.mjs","*.cjs","*.json","*.md","*.yml","*.yaml"],excludeGlobs:[".env*","**/.env*","**/node_modules/**","**/dist/**","**/build/**","**/.git/**","**/*.pem","**/*.key","**/secrets/**"]},patchQuality:{enabled:true,maxRepairAttempts:1},rollback:{enabled:true,onFinalValidationFailure:true,strategy:"all",maxRollbackDepth:8,runValidationAfterRollback:true,allowForSuppliedPatches:false},redaction:{enabled:true,additionalPatterns:[]},language:{response:"auto"},permissions:{shell:{inheritDefaults:true,ask:[{pattern:"npm run build",reason:"Build commands can be slow and may produce large outputs.",risk:"medium",defaultAnswer:"approve"},{pattern:"pnpm run build",reason:"Build commands can be slow and may produce large outputs.",risk:"medium",defaultAnswer:"approve"},{pattern:"yarn run build",reason:"Build commands can be slow and may produce large outputs.",risk:"medium",defaultAnswer:"approve"},{pattern:"bun run build",reason:"Build commands can be slow and may produce large outputs.",risk:"medium",defaultAnswer:"approve"}],deny:["rm *","git push *","git reset *","git clean *"]},patchApply:{decision:"ask",reason:"Apply the generated unified diff to the workspace.",risk:"high",defaultAnswer:"reject"}},tools:{"fs.readFile":{timeoutMs:1e4,retries:1},"fs.exists":{timeoutMs:5e3,retries:0},"fs.searchText":{timeoutMs:1e4,retries:1},"shell.exec":{timeoutMs:18e4,retries:0},"llm.complete":{timeoutMs:9e4,retries:2},"patch.apply":{timeoutMs:3e4,retries:0},"patch.rollback":{timeoutMs:3e4,retries:0}}}},Mn=e=>{let n=$e(Me(e)),t=[{preset:"inspect",mode:"read-only"}];return $(n,["typecheck","type-check","check-types","tsc","check"])&&t.push({preset:"typecheck",mode:"propose"}),$(n,["lint","lint:ci"])&&t.push({preset:"lint",mode:"propose"}),$(n,["test","test:ci","test:unit"])&&t.push({preset:"fix-tests",mode:"propose"}),t},$n=e=>`${JSON.stringify({stopOnFailure:false,goals:Mn(e)},null,2)}
8
+ `,jn=e=>{let n=["# Brass Agent environment variables","# Copy this file to .env or .brass-agent.env, or export the variables in your shell.","# brass-agent auto-loads supported agent env keys from --cwd.","# Do not commit real API keys.",""];return e==="fake"&&n.push("BRASS_LLM_PROVIDER=fake","BRASS_FAKE_LLM_RESPONSE=Fake plan from .env.example",""),n.push("# Google / Gemini","# Used when .brass-agent.json selects provider google, or when auto-detected.","GEMINI_API_KEY=","BRASS_GOOGLE_MODEL=gemini-2.5-flash","","# OpenAI-compatible providers","# BRASS_LLM_PROVIDER=openai-compatible","BRASS_LLM_ENDPOINT=https://api.openai.com/v1/chat/completions","BRASS_LLM_API_KEY=","BRASS_LLM_MODEL=gpt-4.1","","# Approval behavior: auto | interactive | approve | deny","# BRASS_AGENT_APPROVAL=auto",""),e==="google"?n.splice(4,0,"BRASS_LLM_PROVIDER=google",""):e==="openai-compatible"&&n.splice(4,0,"BRASS_LLM_PROVIDER=openai-compatible",""),`${n.join(`
9
+ `)}
10
+ `},Bn=()=>["# Brass Agent","","This workspace was initialized with `brass-agent --init`.","","Generated files:","","- `.brass-agent.json` \u2014 local policy/config for Brass Agent.","- `brass-agent.batch.json` \u2014 sample multi-goal batch workflow.","- `.env.example` \u2014 example environment variables. Copy to `.env` or `.brass-agent.env`; keep real secrets out of git.","","Recommended first commands:","","```bash","brass-agent --doctor","brass-agent --preset inspect","brass-agent --batch-file brass-agent.batch.json","```","","Apply mode is intentionally approval-gated:","","```bash",'brass-agent --apply "fix the failing tests"',"```",""].join(`
11
+ `),Dn=e=>{let n=["Review .brass-agent.json and adjust permissions/context budgets for this repo.","Run: brass-agent --doctor","Run: brass-agent --preset inspect","Run: brass-agent --batch-file brass-agent.batch.json"];return e==="google"?["Set GEMINI_API_KEY in your shell, `.env`, or `.brass-agent.env`.",...n]:e==="openai-compatible"?["Set BRASS_LLM_API_KEY and BRASS_LLM_ENDPOINT in your shell, `.env`, or `.brass-agent.env`.",...n]:e==="default"?["Set an LLM provider env var in your shell, `.env`, or `.brass-agent.env` when ready, or let the CLI fall back to fake mode.",...n]:n},T=async e=>{let n=path.resolve(e.cwd,e.relativePath),o=fs.existsSync(n)?e.force?"overwritten":"skipped":"created";return !e.dryRun&&o!=="skipped"&&(await promises.mkdir(path.dirname(n),{recursive:true}),await promises.writeFile(n,e.content,"utf8")),{path:n,relativePath:e.relativePath,status:o,bytes:Buffer.byteLength(e.content,"utf8")}},je=async e=>{let n=path.resolve(e.cwd),t=e.profile??"default",o=e.force??false,r=e.dryRun??false,a=Fn(n,t),l=await Promise.all([T({cwd:n,relativePath:".brass-agent.json",content:`${JSON.stringify(a,null,2)}
12
+ `,force:o,dryRun:r}),T({cwd:n,relativePath:"brass-agent.batch.json",content:$n(n),force:o,dryRun:r}),T({cwd:n,relativePath:".env.example",content:jn(t),force:o,dryRun:r}),T({cwd:n,relativePath:"BRASS_AGENT.md",content:Bn(),force:o,dryRun:r})]);return {cwd:n,profile:t,dryRun:r,files:l,nextSteps:Dn(t)}},Gn=e=>{switch(e){case "created":return "\u2713";case "overwritten":return "!";case "skipped":return "-"}},Be=e=>{console.log(`brass-agent init${e.dryRun?" (dry run)":""}`),console.log(`workspace: ${e.cwd}`),console.log(`profile: ${e.profile}`),console.log("");for(let n of e.files)console.log(`${Gn(n.status)} ${n.status} ${n.relativePath}`);console.log(""),console.log("next steps:");for(let n of e.nextSteps)console.log(`- ${n}`);};var F=new Function("specifier","return import(specifier)"),Nn=async(e,n)=>{let t=await F("node:path");return (await F("node:fs/promises")).readFile(t.resolve(e,n),"utf8")},K=e=>{if(e===void 0||e.trim()==="")return;let n=Number(e);return Number.isFinite(n)?n:void 0},Ye=e=>e==="read-only"||e==="propose"||e==="write"||e==="autonomous",Je=e=>e==="auto"||e==="interactive"||e==="approve"||e==="deny",De=e=>e==="default"||e==="google"||e==="openai-compatible"||e==="fake",Tn=e=>["auto","match-user","en","es","pt","fr","de","it","custom"].includes(e),k=(e,n,t)=>{let o=e[n],r=o.startsWith(`${t}=`)?o.slice(t.length+1):void 0;if(r!==void 0&&r!=="")return [r,n];let a=e[n+1];if(!a)throw new Error(`${t} requires a value`);return [a,n+1]},Kn=e=>{let n=process.cwd(),t=true,o=false,r="propose",a=false,l=false,s="human",c="auto",h=false,E,p=false,g,m=false,S=false,R,b="apply",V,re=false,se=false,W,Y,D,ae=false,ie=false,le=false,G="default",ce=false,J,U=[];for(let u=0;u<e.length;u+=1){let i=e[u];if(i==="--"){U.push(...e.slice(u+1));break}if(i==="--help"||i==="-h"){l=true;continue}if(i==="--doctor"){ae=true;continue}if(i==="--where"||i==="--print-workspace"){o=true;continue}if(i==="--no-discover-workspace"){t=false;continue}if(i==="--init"){ie=true;continue}if(i==="--force"||i==="--init-force"){le=true;continue}if(i==="--init-dry-run"){ce=true;continue}if(i==="--init-profile"||i.startsWith("--init-profile=")){let[d,f]=k(e,u,"--init-profile");if(!De(d))throw new Error("--init-profile requires one of: default, google, openai-compatible, fake");G=d,u=f;continue}if(i==="--init-provider"||i.startsWith("--init-provider=")){let[d,f]=k(e,u,"--init-provider");if(d==="auto")G="default";else if(De(d))G=d;else throw new Error("--init-provider requires one of: auto, fake, google, openai-compatible");u=f;continue}if(i==="--language"||i.startsWith("--language=")){let[d,f]=k(e,u,"--language");if(!Tn(d))throw new Error("--language requires one of: auto, match-user, en, es, pt, fr, de, it, custom");J=d,u=f;continue}if(i==="--json"){s="json";continue}if(i==="--events-json"){s="events-json";continue}if(i==="--protocol-json"){s="protocol-json";continue}if(i==="--protocol-full-patches"){S=true;continue}if(i==="--preset"||i.startsWith("--preset=")){let[d,f]=k(e,u,"--preset");if(!chunk63ODH5W4_cjs.ga(d))throw new Error("--preset requires one of: fix-tests, inspect, typecheck, lint");W=d,u=f;continue}if(i==="--batch-file"||i.startsWith("--batch-file=")){let[d,f]=k(e,u,"--batch-file");Y=d,u=f;continue}if(i==="--batch-stop-on-failure"){D=true;continue}if(i==="--batch-continue-on-failure"){D=false;continue}if(i==="--ci"){re=true;continue}if(i==="--fail-on-patch-proposed"){se=true;continue}if(i==="--yes"||i==="-y"){c="approve",h=true;continue}if(i==="--no-input"){c="deny",h=true;continue}if(i==="--approval"||i.startsWith("--approval=")){let[d,f]=k(e,u,"--approval");if(!Je(d))throw new Error("--approval requires one of: auto, interactive, approve, deny");c=d,h=true,u=f;continue}if(i==="--apply"){r="write",a=true;continue}if(i==="--patch-file"||i.startsWith("--patch-file=")){let[d,f]=k(e,u,"--patch-file");R=d,u=f;continue}if(i==="--apply-patch-file"||i.startsWith("--apply-patch-file=")){let[d,f]=k(e,u,"--apply-patch-file");R=d,b="apply",r="write",a=true,u=f;continue}if(i==="--rollback-patch-file"||i.startsWith("--rollback-patch-file=")){let[d,f]=k(e,u,"--rollback-patch-file");R=d,b="rollback",r="write",a=true,u=f;continue}if(i==="--mode"||i.startsWith("--mode=")){let[d,f]=k(e,u,"--mode");if(!Ye(d))throw new Error("--mode requires one of: read-only, propose, write, autonomous");r=d,a=true,u=f;continue}if(i==="--cwd"||i.startsWith("--cwd=")){let[d,f]=k(e,u,"--cwd");n=d,u=f;continue}if(i==="--save-run"||i.startsWith("--save-run=")){let[d,f]=k(e,u,"--save-run");V=d,u=f;continue}if(i==="--config"||i.startsWith("--config=")){let[d,f]=k(e,u,"--config");E=d,p=false,u=f;continue}if(i==="--no-config"){E=void 0,p=true;continue}if(i==="--env-file"||i.startsWith("--env-file=")){let[d,f]=k(e,u,"--env-file");g=d,m=false,u=f;continue}if(i==="--no-env-file"){g=void 0,m=true;continue}if(i.startsWith("--"))throw new Error(`Unknown option: ${i}`);U.push(i);}return {cwd:n,discoverWorkspace:t,where:o,goalText:U.join(" ").trim(),mode:r,modeSpecified:a,showHelp:l,output:s,approval:c,approvalSpecified:h,...E?{configPath:E}:{},noConfig:p,...g?{envFile:g}:{},noEnvFile:m,protocolFullPatches:S,patchFileMode:b,ci:re,failOnPatchProposed:se,...W?{preset:W}:{},...Y?{batchFile:Y}:{},...D!==void 0?{batchStopOnFailure:D}:{},doctor:ae,init:ie,initForce:le,initProfile:G,initDryRun:ce,...J?{language:J}:{},...V?{saveRunDir:V}:{},...R?{patchFile:R}:{}}},Ue=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),Vn=(e,n)=>{if(typeof e=="string")return e;if(!Ue(e))throw new Error(`${n} must be a string or object.`);let t=e.goal,o=e.preset,r=e.mode,a=e.cwd,l=e.patchFile,s=e.patchFileMode,c=e.saveRunDir;if(t!==void 0&&typeof t!="string")throw new Error(`${n}.goal must be a string.`);if(a!==void 0&&typeof a!="string")throw new Error(`${n}.cwd must be a string.`);if(l!==void 0&&typeof l!="string")throw new Error(`${n}.patchFile must be a string.`);if(c!==void 0&&typeof c!="string")throw new Error(`${n}.saveRunDir must be a string.`);if(o!==void 0&&(typeof o!="string"||!chunk63ODH5W4_cjs.ga(o)))throw new Error(`${n}.preset must be one of: fix-tests, inspect, typecheck, lint.`);if(r!==void 0&&(typeof r!="string"||!Ye(r)))throw new Error(`${n}.mode must be one of: read-only, propose, write, autonomous.`);if(s!==void 0&&s!=="apply"&&s!=="rollback")throw new Error(`${n}.patchFileMode must be apply or rollback.`);if(t===void 0&&o===void 0&&l===void 0)throw new Error(`${n} must include goal, preset, or patchFile.`);return {...t?{goal:t}:{},...o?{preset:o}:{},...r?{mode:r}:{},...a?{cwd:a}:{},...l?{patchFile:l}:{},...s?{patchFileMode:s}:{},...c?{saveRunDir:c}:{}}},Wn=e=>{let n=Array.isArray(e)?e:Ue(e)&&Array.isArray(e.goals)?e.goals:void 0;if(!n)throw new Error("Batch file must be a JSON array or an object with a goals array.");return n.map((t,o)=>Vn(t,`goals[${o}]`))},Yn=async(e,n)=>{let t=await F("node:path"),o=await F("node:fs/promises"),r=t.isAbsolute(n)?n:t.resolve(e,n),a=String(await o.readFile(r,"utf8")).replace(/^\uFEFF/,"");try{return Wn(JSON.parse(a))}catch(l){if(!(l instanceof SyntaxError))throw l;let s=a.split(/\r?\n/g).map(c=>c.trim()).filter(c=>c&&!c.startsWith("#"));if(s.length===0)throw new Error(`Batch file has no goals: ${r}`);return s}},Jn=(e,n)=>typeof e=="string"?e:e.goal?e.goal:e.preset?chunk63ODH5W4_cjs.ha(e.preset):e.patchFile??n?"apply supplied patch":"",Un=(e,n,t)=>typeof e!="string"&&e.mode?e.mode:typeof e!="string"&&e.preset==="inspect"&&!n.modeSpecified?"read-only":n.modeSpecified?n.mode:t.mode??n.mode,qn=(e,n,t)=>e.map((o,r)=>{let a=Jn(o,n.patchFile),l=typeof o=="string"?n.cwd:o.cwd??n.cwd,s=typeof o=="string"?n.patchFile:o.patchFile??n.patchFile,c=typeof o=="string"?n.patchFileMode:o.patchFileMode??n.patchFileMode,h=typeof o=="string"?n.saveRunDir:o.saveRunDir??n.saveRunDir;if(!a)throw new Error(`Batch goal ${r+1} resolved to an empty goal.`);return {index:r,cwd:l,goalText:a,mode:Un(o,n,t),patchFileMode:c,...s?{patchFile:s}:{},...h?{saveRunDir:h}:{}}}),Hn=async e=>{let n=chunk63ODH5W4_cjs.ta(e.cwd,{enabled:e.discoverWorkspace}),t=n.cwd,o={...e,cwd:t},r=await chunk63ODH5W4_cjs.pa({cwd:t,configPath:e.configPath,noConfig:e.noConfig}),a=Ce({cwd:t,envFile:e.envFile,noEnvFile:e.noEnvFile,allowedExtraKeys:r.config.llm?.apiKeyEnv?[r.config.llm.apiKeyEnv]:[]}),l=!e.goalText&&!e.preset&&!e.patchFile,s=e.batchFile?await Yn(t,e.batchFile):l?r.config.batch?.goals??[]:[],c=qn(s,o,r.config);return {...o,goalText:e.goalText||(e.preset?chunk63ODH5W4_cjs.ha(e.preset):e.patchFile?"apply supplied patch":e.goalText),mode:e.modeSpecified?e.mode:e.preset==="inspect"?"read-only":r.config.mode??e.mode,approval:e.approvalSpecified?e.approval:r.config.approval??e.approval,config:r.config,workspaceDiscovery:n,batchRuns:c,batchStopOnFailureResolved:e.batchStopOnFailure??r.config.batch?.stopOnFailure??e.ci,envFileLoad:a,...r.path?{resolvedConfigPath:r.path}:{}}},Ge=()=>{console.log(['Usage: brass-agent [options] "goal"',"","Options:"," --mode read-only|propose|write|autonomous"," Agent permission mode. Default: propose, or config.mode if present."," --preset fix-tests|inspect|typecheck|lint"," Use a built-in goal preset when no explicit goal text is provided."," --apply"," Alias for --mode write."," --cwd PATH"," Starting directory for workspace discovery. Default: current directory."," --no-discover-workspace"," Use --cwd exactly instead of searching upward for package.json, .brass-agent.json, or .git."," --where, --print-workspace"," Print the resolved workspace root and exit."," --config PATH"," Load a specific .brass-agent.json policy/config file."," --save-run DIR"," Write final run JSON and Markdown artifacts to DIR."," --batch-file PATH"," Run multiple goals sequentially from a JSON or line-based file."," --batch-stop-on-failure"," Stop a batch after the first failed run."," --batch-continue-on-failure"," Continue a batch even when a run fails."," --doctor"," Check local CLI, workspace, VS Code, package manager, and LLM setup."," --init"," Initialize this workspace with .brass-agent.json, brass-agent.batch.json, .env.example, and BRASS_AGENT.md."," --force, --init-force"," Overwrite files generated by --init when they already exist."," --init-profile default|google|openai-compatible|fake"," Initialization profile. Default: default, which leaves provider auto-detection enabled."," --init-provider auto|fake|google|openai-compatible"," Alias for choosing an LLM-oriented init profile. auto maps to default."," --init-dry-run"," Preview generated files without writing them."," --no-config"," Do not discover or load an agent config file."," --language auto|match-user|en|es|pt|fr|de|it"," Response language for LLM summaries. Default: config.language or auto-match the user goal."," --env-file PATH"," Load Brass Agent environment variables from a specific env file."," --no-env-file"," Do not auto-load .brass-agent.env, .env.local, or .env from --cwd."," --json"," Print the full final AgentState JSON. Suppresses live event output."," --ci"," Preserve output mode but set process exit codes from the final run status."," --fail-on-patch-proposed"," In --ci mode, exit 2 when a patch was proposed but not applied."," --events-json"," Stream AgentEvent objects as JSON Lines. Does not print the final AgentState."," --protocol-json"," Stream Brass Agent protocol JSON Lines, including events and a final-state message."," --protocol-full-patches"," Keep patch payloads untruncated in protocol/event JSON output for trusted local integrations."," --patch-file PATH"," Supply a precomputed unified diff to the agent. Respects --mode."," --apply-patch-file PATH"," Supply and apply a precomputed unified diff. Alias for --patch-file PATH --mode write."," --rollback-patch-file PATH"," Reverse-apply a precomputed unified diff through PatchService. Requires write mode approvals."," --yes, -y"," Auto-approve approval prompts. Useful for CI and smoke tests."," --no-input"," Do not prompt; reject any action that requires approval."," --approval auto|interactive|approve|deny"," Approval strategy. Default: auto, or config.approval if present."," --help, -h"," Show this help message.","","Config files:"," brass-agent first resolves a workspace root by searching upward from --cwd."," It looks for .brass-agent.json, brass-agent.config.json, package.json, workspace markers, or .git."," brass-agent then searches upward from that workspace root for .brass-agent.json or brass-agent.config.json."," config.batch.goals can define a default batch when --batch-file is not provided.","","Examples:",' brass-agent "fix the failing tests"'," brass-agent --preset fix-tests"," brass-agent --preset inspect"," brass-agent --batch-file ./brass-agent.batch.json --ci"," brass-agent --where"," brass-agent --doctor"," brass-agent --doctor --json"," brass-agent --env-file .env --doctor"," brass-agent --init"," brass-agent --init --init-profile google"," brass-agent --init --init-profile fake --init-dry-run",' brass-agent --config ./agent.policy.json "fix the failing tests"',' brass-agent --no-config "fix the failing tests"',' brass-agent --json "fix the failing tests"',' brass-agent --events-json "fix the failing tests"',' brass-agent --protocol-json "fix the failing tests"',' brass-agent --protocol-json --protocol-full-patches "fix the failing tests"',' brass-agent --apply-patch-file ./approved.diff --yes "apply approved patch"',' brass-agent --apply "fix the failing tests"',' brass-agent --apply --yes "fix the failing tests"',' brass-agent --mode read-only --cwd ./repo "inspect the test failure"',"","LLM providers:"," BRASS_LLM_PROVIDER=fake"," BRASS_LLM_PROVIDER=google GEMINI_API_KEY=..."," BRASS_LLM_PROVIDER=openai-compatible BRASS_LLM_ENDPOINT=... BRASS_LLM_API_KEY=..."].join(`
13
+ `));},qe=e=>e?process.env[e]:void 0,Ne=e=>{let n=qe(e?.apiKeyEnv)??process.env.BRASS_GOOGLE_API_KEY??process.env.GOOGLE_API_KEY??process.env.GEMINI_API_KEY;if(n)return chunk63ODH5W4_cjs.ra({apiKey:n,model:process.env.BRASS_GOOGLE_MODEL??process.env.BRASS_LLM_MODEL??e?.model??"gemini-2.5-flash",apiVersion:process.env.BRASS_GOOGLE_API_VERSION??e?.apiVersion??"v1beta",baseUrl:process.env.BRASS_GOOGLE_BASE_URL??e?.baseUrl,endpoint:process.env.BRASS_GOOGLE_ENDPOINT??e?.endpoint,systemInstruction:process.env.BRASS_GOOGLE_SYSTEM_INSTRUCTION??e?.systemInstruction,temperature:K(process.env.BRASS_GOOGLE_TEMPERATURE)??e?.temperature,topP:K(process.env.BRASS_GOOGLE_TOP_P)??e?.topP,topK:K(process.env.BRASS_GOOGLE_TOP_K)??e?.topK,maxOutputTokens:K(process.env.BRASS_GOOGLE_MAX_OUTPUT_TOKENS)??e?.maxOutputTokens})},Te=e=>{let n=process.env.BRASS_LLM_ENDPOINT??e?.endpoint,t=qe(e?.apiKeyEnv)??process.env.BRASS_LLM_API_KEY,o=process.env.BRASS_LLM_MODEL??e?.model??"gpt-4.1";if(!(!n||!t))return chunk63ODH5W4_cjs.qa({endpoint:n,apiKey:t,model:o})},zn=e=>{let n=(process.env.BRASS_LLM_PROVIDER??e?.provider)?.trim().toLowerCase(),t=process.env.BRASS_FAKE_LLM_RESPONSE??e?.fakeResponse;if(n==="fake")return chunk63ODH5W4_cjs.sa({content:t});if(n==="google"||n==="gemini"){let o=Ne(e);if(!o)throw new Error("Google LLM provider requires BRASS_GOOGLE_API_KEY, GOOGLE_API_KEY, GEMINI_API_KEY, or config.llm.apiKeyEnv.");return o}if(n==="openai"||n==="openai-compatible"){let o=Te(e);if(!o)throw new Error("OpenAI-compatible LLM provider requires BRASS_LLM_ENDPOINT/config.llm.endpoint and BRASS_LLM_API_KEY/config.llm.apiKeyEnv.");return o}if(n)throw new Error(`Unsupported LLM provider: ${n}`);return Ne(e)??Te(e)??chunk63ODH5W4_cjs.sa({content:t})},Qn=()=>{let e=process.env.BRASS_AGENT_APPROVAL?.trim().toLowerCase();if(e){if(Je(e))return e;throw new Error("BRASS_AGENT_APPROVAL must be one of: auto, interactive, approve, deny")}},Xn=e=>e==="1"||e?.toLowerCase()==="true"||e?.toLowerCase()==="yes",Zn=()=>!!(process.stdin?.isTTY&&(process.stderr?.isTTY??process.stdout?.isTTY)),et=e=>{if(e.approvalSpecified&&e.approval!=="auto")return e.approval;if(Xn(process.env.BRASS_AGENT_AUTO_APPROVE))return "approve";let n=Qn();return n&&n!=="auto"?n:e.approval!=="auto"?e.approval:e.output==="human"&&Zn()?"interactive":"deny"},nt=e=>{switch(et(e)){case "approve":return chunk63ODH5W4_cjs.ka;case "deny":return chunk63ODH5W4_cjs.la("Approval rejected because the CLI is running without interactive input. Use --yes to auto-approve.");case "interactive":return Pe()}},Ke=(e,n=2e3)=>e.length<=n?e:`${e.slice(0,n)}
14
+ \u2026 truncated ${e.length-n} chars`,I=(e,n=1e3)=>e.length<=n?e:`${e.slice(0,n)}\u2026 truncated ${e.length-n} chars`,B=(e,n)=>n.fullPatches?e:I(e),He=(e,n)=>({...e,...e.initialPatch?{initialPatch:B(e.initialPatch,n)}:{}}),j=(e,n={})=>{switch(e.type){case "llm.complete":return {...e,prompt:I(e.prompt)};case "patch.apply":case "patch.rollback":case "patch.propose":return {...e,patch:B(e.patch,n)};default:return e}},ne=(e,n={})=>{switch(e.type){case "fs.fileRead":return {...e,content:I(e.content)};case "llm.response":return {...e,content:I(e.content)};case "shell.result":return {...e,stdout:I(e.stdout),stderr:I(e.stderr)};case "fs.searchResult":return {...e,matches:e.matches.slice(0,30),omittedMatches:Math.max(0,e.matches.length-30)};case "patch.proposed":return {...e,patch:B(e.patch,n)};case "patch.applied":case "patch.rolledBack":return e.patch?{...e,patch:B(e.patch,n)}:e;default:return e}},ze=(e,n={})=>{switch(e.type){case "agent.run.started":case "agent.run.completed":return {...e,goal:He(e.goal,n)};case "agent.action.started":return {...e,action:j(e.action,n)};case "agent.action.completed":return {...e,action:j(e.action,n),observation:ne(e.observation,n)};case "agent.action.failed":return {...e,action:j(e.action,n)};case "agent.observation.recorded":return {...e,observation:ne(e.observation,n)};case "agent.tool.timeout":case "agent.permission.denied":case "agent.approval.requested":case "agent.approval.resolved":return {...e,action:j(e.action,n)};default:return e}},te=(e,n={})=>({...e,goal:He(e.goal,n),observations:e.observations.map(t=>ne(t,n)),errors:e.errors.map(t=>{switch(t._tag){case "PermissionDenied":case "ApprovalRejected":return {...t,action:j(t.action,n)};case "PatchError":return {...t,cause:String(t.cause),...t.patch?{patch:B(t.patch,n)}:{}};case "FsError":case "ShellError":case "LLMError":return {...t,cause:String(t.cause)};default:return t}})}),oe=e=>({protocol:"brass-agent",version:1,...e}),tt=e=>{switch(e){case "ok":return "\u2713";case "warn":return "!";case "fail":return "\u2717"}},Ve=e=>`${Math.max(0,e)}ms`,w=(e,n)=>[...e.observations].reverse().find(t=>t.type===n),ot=e=>({emit(n){switch(n.type){case "agent.run.started":console.log(`brass-agent ${n.goal.mode}`),console.log(`workspace: ${n.goal.cwd}`),e&&console.log(`config: ${e}`),console.log(`goal: ${n.goal.text}`),console.log("");break;case "agent.action.started":console.log(`\u2192 ${chunk63ODH5W4_cjs.T(n.action)}`);break;case "agent.action.completed":{let t=chunk63ODH5W4_cjs.V(n.observation);console.log(`${tt(t)} ${chunk63ODH5W4_cjs.U(n.observation)} ${Ve(n.durationMs)}`);break}case "agent.action.failed":n.error._tag!=="ToolTimeout"&&n.error._tag!=="PermissionDenied"&&n.error._tag!=="ApprovalRejected"&&console.log(`\u2717 ${chunk63ODH5W4_cjs.T(n.action)} failed with ${n.error._tag} ${Ve(n.durationMs)}`);break;case "agent.tool.timeout":console.log(`! ${chunk63ODH5W4_cjs.T(n.action)} timed out after ${n.timeoutMs}ms`);break;case "agent.permission.denied":console.log(`\u2717 ${chunk63ODH5W4_cjs.T(n.action)} denied: ${n.reason}`);break;case "agent.approval.requested":console.log(`? approval required for ${chunk63ODH5W4_cjs.T(n.action)} (${n.risk})`);break;case "agent.approval.resolved":n.approved?console.log(`\u2713 approval granted for ${chunk63ODH5W4_cjs.T(n.action)}`):console.log(`\u2717 approval rejected for ${chunk63ODH5W4_cjs.T(n.action)}${n.reason?`: ${n.reason}`:""}`);break;case "agent.patch.applied":break;case "agent.patch.rolledBack":n.automatic&&console.log(`\u2713 automatic rollback completed (${n.changedFiles.join(", ")||"no files reported"})`);break;}}}),rt=(e={})=>({emit(n){console.log(JSON.stringify(ze(n,e)));}}),st=(e={})=>({emit(n){console.log(JSON.stringify(oe({type:"event",event:ze(n,e)})));}}),We=e=>e.toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,80)||"run",ee=e=>e.replace(/\\/g,"\\\\").replace(/`/g,"\\`"),at=async(e,n,t)=>{let o=await F("node:path"),r=await F("node:fs/promises"),a=o.isAbsolute(n)?n:o.resolve(e.goal.cwd,n);await r.mkdir(a,{recursive:true});let s=`${We(e.goal.id)}-${We(e.goal.text)}`,c=o.join(a,`${s}.json`),h=o.join(a,`${s}.md`),E=w(e,"agent.done"),p=w(e,"agent.error"),g=w(e,"patch.applied"),m=w(e,"patch.rolledBack");await r.writeFile(c,`${JSON.stringify(te(e,t),null,2)}
15
+ `,"utf8"),await r.writeFile(h,[`# Brass Agent Run ${ee(e.goal.id)}`,"",`- Goal: ${ee(e.goal.text)}`,`- Workspace: ${ee(e.goal.cwd)}`,`- Mode: ${e.goal.mode}`,`- Phase: ${e.phase}`,`- Steps: ${e.steps}`,g?`- Changed files: ${g.changedFiles.join(", ")||"none reported"}`:void 0,m?`- Rolled back files: ${m.changedFiles.join(", ")||"none reported"}`:void 0,"","## Summary","",E?.summary?.trim()||(p?`Error: ${p.error._tag}`:"No summary recorded.")].filter(Boolean).join(`
16
+ `),"utf8"),process.stderr?.isTTY&&console.error(`saved run artifacts: ${c} ${h}`);},it=e=>w(e,"shell.result"),lt=(e,n)=>{if(w(e,"agent.error"))return 1;let t=it(e);return t&&t.exitCode!==0?1:n.failOnPatchProposed&&w(e,"patch.proposed")&&!w(e,"patch.applied")?2:0},ct=e=>{let n=w(e,"agent.done"),t=w(e,"agent.error"),o=w(e,"patch.proposed"),r=w(e,"patch.applied"),a=w(e,"patch.rolledBack"),l=w(e,"llm.response");console.log(""),console.log(`phase: ${e.phase}`),console.log(`steps: ${e.steps}`),a?console.log(`rolled back files: ${a.changedFiles.join(", ")||"(none reported)"}`):r?console.log(`changed files: ${r.changedFiles.join(", ")||"(none reported)"}`):o&&console.log("patch: proposed only; rerun with --apply to apply it"),n?(console.log(""),console.log("summary:"),console.log(Ke(n.summary.trim()||"Agent completed."))):t?(console.log(""),console.log("error:"),console.log(JSON.stringify(t.error,null,2))):l&&(console.log(""),console.log("llm response:"),console.log(Ke(l.content.trim())));},pt=(e,n)=>e.output==="human"?ot(e.resolvedConfigPath):e.output==="events-json"?rt(n):e.output==="protocol-json"?st(n):void 0,dt=(e,n)=>{let t=chunk63ODH5W4_cjs.ma;return {shell:t,fs:chunk63ODH5W4_cjs.na(t),patch:chunk63ODH5W4_cjs.oa(t),llm:zn(e.config.llm),permissions:chunk63ODH5W4_cjs.ia(e.config.permissions),approvals:nt(e),...n?{events:n}:{},...e.config.tools?{toolPolicies:e.config.tools}:{}}},ut=e=>({index:0,cwd:e.cwd,goalText:e.goalText,mode:e.mode,patchFileMode:e.patchFileMode,...e.patchFile?{patchFile:e.patchFile}:{},...e.saveRunDir?{saveRunDir:e.saveRunDir}:{}}),gt=async(e,n,t,o)=>{let r=dt(e,o),a=new chunkT3QEEHK6_cjs.M({env:r}),l=n.patchFile?await Nn(n.cwd,n.patchFile):void 0,s=await a.toPromise(chunk63ODH5W4_cjs.ba(a,{id:`agent-${Date.now()}-${n.index+1}`,cwd:n.cwd,text:n.goalText,mode:n.mode,...e.config.project?{project:e.config.project}:{},...e.config.context?{context:e.config.context}:{},...e.config.patchQuality?{patchQuality:e.config.patchQuality}:{},...e.config.rollback?{rollback:e.config.rollback}:{},...e.config.redaction?{redaction:e.config.redaction}:{},...e.language?{language:{response:e.language}}:e.config.language?{language:e.config.language}:{},...l?{initialPatch:l,initialPatchMode:n.patchFileMode}:{}}));return n.saveRunDir&&await at(s,n.saveRunDir,t),{run:n,state:s,exitCode:lt(s,{failOnPatchProposed:e.failOnPatchProposed})}},ft=e=>e.some(n=>n.exitCode===1)?1:e.some(n=>n.exitCode===2)?2:0,Qe=(e,n)=>({total:e.length,completed:n.length,failed:n.filter(t=>t.exitCode!==0).length,exitCode:ft(n),stoppedEarly:n.length<e.length}),mt=(e,n)=>{let t=Qe(e,n);console.log(""),console.log("batch summary:"),console.log(`completed: ${t.completed}/${t.total}`),console.log(`failed: ${t.failed}`),t.stoppedEarly&&console.log("stopped early: yes"),console.log(`exit code: ${t.exitCode}`);},yt=e=>{let n={cwd:e.cwd,inputCwd:e.workspaceDiscovery.inputCwd,changed:e.workspaceDiscovery.changed,disabled:!!e.workspaceDiscovery.disabled,marker:e.workspaceDiscovery.marker,markerPath:e.workspaceDiscovery.markerPath,configPath:e.resolvedConfigPath,envFiles:e.envFileLoad.paths};if(e.output==="json"||e.output==="protocol-json"){console.log(JSON.stringify(n,null,2));return}console.log("brass-agent workspace"),console.log(`input: ${n.inputCwd}`),console.log(`workspace: ${n.cwd}`),n.disabled?console.log("discovery: disabled"):n.marker?console.log(`marker: ${n.marker} (${n.markerPath})`):console.log("marker: none found; using input cwd"),n.configPath&&console.log(`config: ${n.configPath}`),n.envFiles.length>0&&console.log(`env: ${n.envFiles.join(", ")}`);},ht=async()=>{let e=await Hn(Kn(process.argv.slice(2))),n=e.batchRuns.length>0;if(e.showHelp&&(Ge(),process.exit(0)),e.where){yt(e);return}if(e.init){let s=await je({cwd:e.cwd,force:e.initForce,dryRun:e.initDryRun,profile:e.initProfile});e.output==="json"?console.log(JSON.stringify(s,null,2)):Be(s);return}if(e.doctor){let s=await _e({cwd:e.cwd,config:e.config,configPath:e.resolvedConfigPath,envFileLoad:e.envFileLoad,workspaceDiscovery:e.workspaceDiscovery});e.output==="json"?console.log(JSON.stringify(s,null,2)):xe(s),process.exitCode=s.status==="fail"?1:0;return}!e.goalText&&!n&&(Ge(),process.exit(1));let t={fullPatches:e.protocolFullPatches},o=pt(e,t),r=n?e.batchRuns:[ut(e)],a=[];for(let s of r){let c=await gt(e,s,t,o);if(a.push(c),e.output==="protocol-json"?console.log(JSON.stringify(oe({type:"final-state",state:te(c.state,t)}))):e.output==="human"&&ct(c.state),n&&e.batchStopOnFailureResolved&&c.exitCode!==0)break}if(n){let s=Qe(r,a);e.output==="json"?console.log(JSON.stringify({type:"batch",summary:s,results:a.map(c=>({index:c.run.index,goal:c.run.goalText,cwd:c.run.cwd,mode:c.run.mode,exitCode:c.exitCode,state:te(c.state,t)}))},null,2)):e.output==="protocol-json"?console.log(JSON.stringify(oe({type:"batch-summary",summary:s}))):e.output==="human"&&mt(r,a),e.ci&&(process.exitCode=s.exitCode);return}let l=a[0];if(!l)throw new Error("Agent run did not produce a result.");e.output==="json"&&console.log(JSON.stringify(l.state,null,2)),e.ci&&(process.exitCode=l.exitCode);};ht().catch(e=>{console.error(e),process.exit(1);});
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ import {ta,pa,ha,ga,ba,T as T$1,V,U,ma,ia,oa,na,la,ka,sa,ra,qa}from'../../chunk-P4IND5C3.js';import {M as M$1,j as j$1,u,t}from'../../chunk-63MXGA7P.js';import {existsSync,readFileSync,readdirSync}from'fs';import {access,constants,mkdir,writeFile}from'fs/promises';import {resolve,join,isAbsolute,dirname}from'path';import {spawnSync}from'child_process';var Xe=new Function("specifier","return import(specifier)"),Ze=e=>["y","yes","approve","approved","si","s\xED","s"].includes(e),en=e=>["n","no","reject","rejected","deny","denied"].includes(e),nn=(e,n)=>{let t=e.trim().toLowerCase();return t?Ze(t)?{type:"approved"}:en(t)?{type:"rejected",reason:"Rejected by user."}:{type:"rejected",reason:`Unrecognized approval answer: ${e}`}:n.defaultAnswer==="approve"?{type:"approved"}:{type:"rejected",reason:"Rejected by default answer."}},Pe=(e={})=>({request:n=>j$1((t$1,o)=>{let r=false,a;return Xe("node:readline/promises").then(({createInterface:l})=>{if(r)return;let s=e.input??process.stdin,c=e.output??process.stderr??process.stdout,h=n.defaultAnswer==="approve"?"Y/n":"y/N";return a=l({input:s,output:c}),c?.write?.(`
3
+ Approval required (${n.risk})
4
+ `),c?.write?.(`Action: ${T$1(n.action)}
5
+ `),c?.write?.(`Reason: ${n.reason}
6
+ `),a.question(`Approve? [${h}] `)}).then(l=>{l===void 0||r||(r=true,a?.close?.(),o(u.succeed(nn(l,n))));}).catch(l=>{r||(r=true,a?.close?.(),o(u.failCause(t.fail({_tag:"AgentLoopError",message:`Approval prompt failed: ${String(l)}`}))));}),()=>{r||(r=true,a?.close?.());}})});var _=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),N=e=>{try{return JSON.parse(readFileSync(e,"utf8"))}catch{return}},Le=(e,n)=>{let t=resolve(e);for(;;){let o=join(t,"package.json"),r=N(o);if(_(r)&&r.name===n)return t;let a=resolve(t,"..");if(a===t)return;t=a;}},M=(e,n=["--version"],t)=>{let o=spawnSync(e,[...n],{cwd:t,encoding:"utf8",shell:false,timeout:1e4});if(!(o.error||(o.status??0)!==0))return `${o.stdout??""}${o.stderr??""}`.trim().split(/\r?\n/g)[0]},L=e=>!!(e&&process.env[e]),ln=()=>process.env.BRASS_AGENT_VSCODE_EXTENSION==="1",cn=e=>{let n=N(join(e,"package.json")),t=_(n)&&typeof n.packageManager=="string"?n.packageManager.split("@")[0]:void 0;return t?{manager:t,source:"package.json packageManager"}:existsSync(join(e,"pnpm-lock.yaml"))?{manager:"pnpm",source:"pnpm-lock.yaml"}:existsSync(join(e,"yarn.lock"))?{manager:"yarn",source:"yarn.lock"}:existsSync(join(e,"bun.lockb"))||existsSync(join(e,"bun.lock"))?{manager:"bun",source:"bun lockfile"}:existsSync(join(e,"package-lock.json"))||existsSync(join(e,"npm-shrinkwrap.json"))?{manager:"npm",source:"npm lockfile"}:{manager:"npm",source:"fallback"}},pn=e=>_(e)&&_(e.scripts)?Object.entries(e.scripts).filter(([,n])=>typeof n=="string").map(([n])=>n).sort():[],dn=(e,n)=>e.find(t=>n.some(o=>o.test(t))),un=(e,n)=>{let t=pn(n),o=["Cargo.toml","Cargo.lock","src-tauri/tauri.conf.json","apps/desktop/package.json","apps/desktop/src-tauri/tauri.conf.json","bridges/whatsmeow-bridge/Cargo.toml","apps","packages","bridges","turbo.json","nx.json","pnpm-workspace.yaml"].filter(s=>existsSync(join(e,s))),r=[];_(n)&&r.push("node"),o.some(s=>s==="Cargo.toml"||s==="Cargo.lock"||s.endsWith("Cargo.toml"))&&r.push("rust"),(o.some(s=>s.includes("tauri"))||t.some(s=>s.includes("tauri")))&&r.push("tauri"),(o.some(s=>s.startsWith("apps"))||t.some(s=>s.includes("desktop")))&&r.push("desktop"),(o.some(s=>s.startsWith("bridges"))||t.some(s=>s.includes("bridge")))&&r.push("bridge"),o.some(s=>["apps","packages","bridges","turbo.json","nx.json","pnpm-workspace.yaml"].includes(s))&&r.push("monorepo");let a=dn(t,[/^repo:check$/,/^check$/,/(^|:)check($|:)/,/(^|:)doctor($|:)/,/(^|:)health($|:)/,/(^|:)verify($|:)/,/(^|:)validate($|:)/,/(^|:)ci($|:)/]),l=[`stacks: ${r.length>0?[...new Set(r)].join(", "):"none detected"}`,`markers: ${o.length>0?o.slice(0,8).join(", "):"none"}`,a?`likely validation: npm run ${a}`:"likely validation: none detected"];return {id:"workspace.projectProfile",label:"Workspace project profile",status:r.length>0?"ok":"skip",message:l.join(". ")}},gn=e=>{if(!e)return {id:"envFile",label:"Agent env file",status:"skip",message:"Env file loading did not run."};if(e.disabled)return {id:"envFile",label:"Agent env file",status:"skip",message:"Env file loading disabled by --no-env-file."};if(e.errors.length>0)return {id:"envFile",label:"Agent env file",status:"fail",message:e.errors.join("; ")};if(e.paths.length===0)return {id:"envFile",label:"Agent env file",status:"skip",message:"No .brass-agent.env, .env.local, or .env found in workspace; using exported shell environment only."};let n=[`Loaded ${e.paths.join(", ")}`];return e.loadedKeys.length>0&&n.push(`keys: ${e.loadedKeys.join(", ")}`),e.alreadySetKeys.length>0&&n.push(`already set by shell: ${e.alreadySetKeys.join(", ")}`),e.emptyKeys.length>0&&n.push(`empty keys skipped: ${e.emptyKeys.join(", ")}`),e.ignoredKeys.length>0&&n.push(`non-agent keys ignored: ${e.ignoredKeys.slice(0,8).join(", ")}${e.ignoredKeys.length>8?", ...":""}`),e.invalidLines.length>0&&n.push(`invalid lines: ${e.invalidLines.join(", ")}`),{id:"envFile",label:"Agent env file",status:e.loadedKeys.length>0||e.alreadySetKeys.length>0?"ok":"warn",message:n.join(". ")}},fn=e=>{let n=(process.env.BRASS_LLM_PROVIDER??e?.llm?.provider)?.trim().toLowerCase(),t=e?.llm?.apiKeyEnv;if(n==="fake")return {id:"llm",label:"LLM provider",status:"ok",message:"Fake LLM provider is selected."};if(n==="google"||n==="gemini"){let o=L(t)||L("BRASS_GOOGLE_API_KEY")||L("GOOGLE_API_KEY")||L("GEMINI_API_KEY");return {id:"llm",label:"LLM provider",status:o?"ok":"fail",message:o?`Google/Gemini provider is configured (${n}).`:"Google/Gemini provider is selected but no API key env var is set. Export GEMINI_API_KEY or put it in .env/.brass-agent.env."}}if(n==="openai"||n==="openai-compatible"){let o=!!(process.env.BRASS_LLM_ENDPOINT??e?.llm?.endpoint),r=L(t)||L("BRASS_LLM_API_KEY");return {id:"llm",label:"LLM provider",status:o&&r?"ok":"fail",message:o&&r?`OpenAI-compatible provider is configured (${n}).`:"OpenAI-compatible provider is selected but endpoint or API key env var is missing. Export BRASS_LLM_API_KEY or put it in .env/.brass-agent.env."}}return L("BRASS_GOOGLE_API_KEY")||L("GOOGLE_API_KEY")||L("GEMINI_API_KEY")?{id:"llm",label:"LLM provider",status:"ok",message:"Google/Gemini credentials are available and will be auto-detected."}:(process.env.BRASS_LLM_ENDPOINT??e?.llm?.endpoint)&&L("BRASS_LLM_API_KEY")?{id:"llm",label:"LLM provider",status:"ok",message:"OpenAI-compatible credentials are available and will be auto-detected."}:{id:"llm",label:"LLM provider",status:"warn",message:"No real LLM credentials found. The CLI will fall back to the fake provider unless config selects a real provider."}},mn=e=>{let n=N(join(e,".vscode","settings.json"));if(!_(n))return;let t=n["brassAgent.command"];return typeof t=="string"?t:void 0},yn=e=>{try{return readdirSync(e).filter(n=>n.endsWith(".vsix")).sort().at(-1)}catch{return}},y=(e,n)=>{e.push(n);},_e=async e=>{let n=resolve(e.cwd),t=[],o=Le(n,"brass-runtime")??Le(process.cwd(),"brass-runtime"),r=Number(process.versions.node.split(".")[0]??"0");y(t,{id:"node",label:"Node.js",status:r>=18?"ok":"fail",message:`Node ${process.versions.node}${r>=18?"":" is too old; use Node 18 or newer."}`});let a=M("npm");y(t,{id:"npm",label:"npm",status:a?"ok":"fail",message:a?`npm ${a}`:"npm is not available on PATH."});let l=M("git");y(t,{id:"git",label:"git",status:l?"ok":"warn",message:l||"git is not available; patch apply/rollback uses git apply."});let s=M("rg");if(y(t,{id:"ripgrep",label:"ripgrep",status:s?"ok":"warn",message:s||"rg is not available; context discovery search will be limited."}),y(t,{id:"workspace",label:"Workspace",status:existsSync(n)?"ok":"fail",message:existsSync(n)?n:`Workspace does not exist: ${n}`}),e.workspaceDiscovery){let p=e.workspaceDiscovery;y(t,{id:"workspace.discovery",label:"Workspace discovery",status:p.disabled?"skip":p.marker?"ok":"warn",message:p.disabled?"Workspace discovery disabled by --no-discover-workspace.":p.marker?`${p.changed?`Resolved ${p.inputCwd} -> ${p.cwd}`:`Using ${p.cwd}`} via ${p.marker}.`:`No workspace marker found upward from ${p.inputCwd}; using input cwd.`});}let c=join(n,"package.json"),h=N(c);if(y(t,{id:"workspace.packageJson",label:"Workspace package.json",status:_(h)?"ok":"warn",message:_(h)?`Found ${c}`:"No package.json found in workspace; project command discovery may use fallbacks."}),_(h)){let p=_(h.scripts)?Object.keys(h.scripts):[];y(t,{id:"workspace.scripts",label:"Workspace scripts",status:p.length?"ok":"warn",message:p.length?`Scripts: ${p.slice(0,12).join(", ")}${p.length>12?", ...":""}`:"No package scripts found."});let g=cn(n),m=M(g.manager);y(t,{id:"workspace.packageManager",label:"Workspace package manager",status:m?"ok":"warn",message:m?`${g.manager} available (${g.source}): ${m}`:`${g.manager} inferred from ${g.source}, but command is not available on PATH.`});}if(y(t,un(n,h)),y(t,gn(e.envFileLoad)),y(t,fn(e.config)),y(t,{id:"config",label:"Agent config",status:e.configPath?"ok":"skip",message:e.configPath?`Loaded ${e.configPath}`:"No .brass-agent.json / brass-agent.config.json loaded; using built-in defaults and VS Code/CLI settings."}),e.includeVsCode!==false){let p=M(process.env.BRASS_CODE_CMD??"code");y(t,{id:"vscode.code",label:"VS Code CLI",status:p?"ok":"warn",message:p?`code ${p}`:"VS Code CLI `code` is not available on PATH; .vsix install needs it unless using the VS Code UI."});let g=mn(n),m=ln();y(t,{id:"vscode.settings",label:"VS Code extension setting",status:g?"ok":m?"skip":"warn",message:g?`brassAgent.command = ${g}`:m?`No workspace brassAgent.command needed; launched by the VS Code extension (${process.env.BRASS_AGENT_VSCODE_CLI_SOURCE??"auto"}).`:"No workspace .vscode/settings.json brassAgent.command found."});}if(o){let p=join(o,"src","agent","cli","main.ts"),g=join(o,"dist","agent","cli","main.cjs"),m=join(o,"extensions","vscode-brass-agent");y(t,{id:"repo.root",label:"brass-runtime repo",status:"ok",message:o}),y(t,{id:"repo.cliSource",label:"CLI source",status:existsSync(p)?"ok":"fail",message:existsSync(p)?`Found ${p}`:`Missing ${p}`}),y(t,{id:"repo.cliBuild",label:"CLI build",status:existsSync(g)?"ok":"warn",message:existsSync(g)?`Found ${g}`:"dist/agent/cli/main.cjs is missing; run npm run build."}),y(t,{id:"repo.extensionDir",label:"VS Code extension source",status:existsSync(join(m,"package.json"))?"ok":"warn",message:existsSync(join(m,"package.json"))?m:"extensions/vscode-brass-agent was not found."}),y(t,{id:"repo.extensionBuild",label:"VS Code extension build",status:existsSync(join(m,"out","extension.js"))?"ok":"warn",message:existsSync(join(m,"out","extension.js"))?"out/extension.js exists.":"Extension output missing; run npm run agent:vscode:package or compile the extension."});let S=yn(m);y(t,{id:"repo.extensionVsix",label:"VSIX package",status:S?"ok":"warn",message:S?`Found ${S}`:"No .vsix found in extensions/vscode-brass-agent."});let R=await access(g,constants.R_OK).then(()=>true).catch(()=>false);y(t,{id:"repo.cliReadable",label:"CLI artifact readable",status:R?"ok":"warn",message:R?"Built CLI artifact is readable.":"Built CLI artifact is not readable yet."});}else y(t,{id:"repo.root",label:"brass-runtime repo",status:"skip",message:"Not running inside a brass-runtime checkout; local source/build checks skipped."});let E=t.some(p=>p.status==="fail")?"fail":t.some(p=>p.status==="warn")?"warn":"ok";return {generatedAt:new Date().toISOString(),cwd:n,...e.configPath?{configPath:e.configPath}:{},...o?{repoRoot:o}:{},status:E,checks:t}},hn=e=>{switch(e){case "ok":return "\u2713";case "warn":return "!";case "fail":return "\u2717";case "skip":return "-"}},xe=e=>{console.log("brass-agent doctor"),console.log(`workspace: ${e.cwd}`),e.configPath&&console.log(`config: ${e.configPath}`),e.repoRoot&&console.log(`repo: ${e.repoRoot}`),console.log(`status: ${e.status}`),console.log("");for(let n of e.checks)console.log(`${hn(n.status)} ${n.label}: ${n.message}`);};var kn=[".brass-agent.env",".env.local",".env"],wn=new Set(["BRASS_LLM_PROVIDER","BRASS_FAKE_LLM_RESPONSE","BRASS_GOOGLE_API_KEY","GOOGLE_API_KEY","GEMINI_API_KEY","BRASS_GOOGLE_MODEL","BRASS_GOOGLE_API_VERSION","BRASS_GOOGLE_BASE_URL","BRASS_GOOGLE_ENDPOINT","BRASS_GOOGLE_SYSTEM_INSTRUCTION","BRASS_GOOGLE_TEMPERATURE","BRASS_GOOGLE_TOP_P","BRASS_GOOGLE_TOP_K","BRASS_GOOGLE_MAX_OUTPUT_TOKENS","BRASS_LLM_ENDPOINT","BRASS_LLM_API_KEY","BRASS_LLM_MODEL","BRASS_AGENT_APPROVAL","BRASS_AGENT_AUTO_APPROVE","BRASS_CODE_CMD"]),C=e=>Array.from(new Set(e)),Sn=e=>{if(e.length<2)return;let n=e[0];if(n!=='"'&&n!=="'"||e[e.length-1]!==n)return;let t=e.slice(1,-1);return n==="'"?t:t.replace(/\\n/g,`
7
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")},En=e=>{let n=e.trim();if(!n||n.startsWith("#"))return {type:"skip"};let t=n.startsWith("export ")?n.slice(7).trimStart():n,o=/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(t);if(!o)return {type:"invalid"};let r=o[1]??"",l=(o[2]??"").trim(),c=Sn(l)??l.replace(/\s+#.*$/u,"").trim();return {type:"assignment",key:r,value:c}},Rn=(e,n)=>n?[isAbsolute(n)?n:resolve(e,n)]:kn.map(t=>join(e,t)),Ce=e=>{let n=resolve(e.cwd),t=e.allowedExtraKeys?.filter(Boolean)??[],o=new Set([...wn,...t]),r=e.noEnvFile?[]:Rn(n,e.envFile),a=[],l=[],s=[],c=[],h=[],E=[],p=[];if(e.noEnvFile)return {cwd:n,disabled:true,filesChecked:[],paths:[],loadedKeys:[],alreadySetKeys:[],emptyKeys:[],ignoredKeys:[],invalidLines:[],errors:[]};for(let g of r){if(!existsSync(g)){e.envFile&&p.push(`Env file does not exist: ${g}`);continue}a.push(g);let m;try{m=readFileSync(g,"utf8").replace(/^\uFEFF/u,"");}catch(S){p.push(`Could not read env file ${g}: ${S instanceof Error?S.message:String(S)}`);continue}for(let[S,R]of m.split(/\r?\n/gu).entries()){let b=En(R);if(b.type!=="skip"){if(b.type==="invalid"){E.push(`${g}:${S+1}`);continue}if(!o.has(b.key)){h.push(b.key);continue}if(!b.value){c.push(b.key);continue}if(process.env[b.key]!==void 0){s.push(b.key);continue}process.env[b.key]=b.value,l.push(b.key);}}}return {cwd:n,disabled:false,...e.envFile?{explicitPath:isAbsolute(e.envFile)?e.envFile:resolve(n,e.envFile)}:{},filesChecked:r,paths:a,loadedKeys:C(l),alreadySetKeys:C(s),emptyKeys:C(c),ignoredKeys:C(h),invalidLines:C(E),errors:C(p)}};var Fe=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),On=e=>{try{return JSON.parse(readFileSync(e,"utf8"))}catch{return}},Me=e=>{let n=On(join(e,"package.json"));return Fe(n)?n:void 0},$e=e=>{let n=e?.scripts;return Fe(n)?Object.entries(n).filter(([,t])=>typeof t=="string").map(([t])=>t).sort():[]},$=(e,n)=>n.some(t=>e.includes(t)),Cn=(e,n)=>{let t=typeof n?.packageManager=="string"?n.packageManager.split("@")[0]:void 0;return t==="npm"||t==="pnpm"||t==="yarn"||t==="bun"?t:existsSync(join(e,"pnpm-lock.yaml"))?"pnpm":existsSync(join(e,"yarn.lock"))?"yarn":existsSync(join(e,"bun.lockb"))||existsSync(join(e,"bun.lock"))?"bun":existsSync(join(e,"package-lock.json"))||existsSync(join(e,"npm-shrinkwrap.json"))?"npm":"auto"},In=e=>{switch(e){case "default":return;case "google":return {provider:"google",model:"gemini-2.5-flash",apiKeyEnv:"GEMINI_API_KEY",temperature:.2,maxOutputTokens:4096};case "openai-compatible":return {provider:"openai-compatible",endpoint:"https://api.openai.com/v1/chat/completions",model:"gpt-4.1",apiKeyEnv:"BRASS_LLM_API_KEY",temperature:.2};case "fake":return {provider:"fake",fakeResponse:"Fake plan from brass-agent init. Configure a real provider when ready."}}},Fn=(e,n)=>{let t=Me(e),o=$e(t),r=$(o,["typecheck","type-check","check-types","tsc","check"]),a=$(o,["lint","lint:ci"]),l=In(n);return {mode:"propose",approval:"auto",...l?{llm:l}:{},project:{packageManager:Cn(e,t),testScriptNames:["test","test:ci","test:unit"],includeTypecheck:r,includeLint:a,maxValidationCommands:2},context:{enabled:true,maxSearchQueries:3,maxFiles:4,maxSearchResults:40,globs:["*.ts","*.tsx","*.js","*.jsx","*.mjs","*.cjs","*.json","*.md","*.yml","*.yaml"],excludeGlobs:[".env*","**/.env*","**/node_modules/**","**/dist/**","**/build/**","**/.git/**","**/*.pem","**/*.key","**/secrets/**"]},patchQuality:{enabled:true,maxRepairAttempts:1},rollback:{enabled:true,onFinalValidationFailure:true,strategy:"all",maxRollbackDepth:8,runValidationAfterRollback:true,allowForSuppliedPatches:false},redaction:{enabled:true,additionalPatterns:[]},language:{response:"auto"},permissions:{shell:{inheritDefaults:true,ask:[{pattern:"npm run build",reason:"Build commands can be slow and may produce large outputs.",risk:"medium",defaultAnswer:"approve"},{pattern:"pnpm run build",reason:"Build commands can be slow and may produce large outputs.",risk:"medium",defaultAnswer:"approve"},{pattern:"yarn run build",reason:"Build commands can be slow and may produce large outputs.",risk:"medium",defaultAnswer:"approve"},{pattern:"bun run build",reason:"Build commands can be slow and may produce large outputs.",risk:"medium",defaultAnswer:"approve"}],deny:["rm *","git push *","git reset *","git clean *"]},patchApply:{decision:"ask",reason:"Apply the generated unified diff to the workspace.",risk:"high",defaultAnswer:"reject"}},tools:{"fs.readFile":{timeoutMs:1e4,retries:1},"fs.exists":{timeoutMs:5e3,retries:0},"fs.searchText":{timeoutMs:1e4,retries:1},"shell.exec":{timeoutMs:18e4,retries:0},"llm.complete":{timeoutMs:9e4,retries:2},"patch.apply":{timeoutMs:3e4,retries:0},"patch.rollback":{timeoutMs:3e4,retries:0}}}},Mn=e=>{let n=$e(Me(e)),t=[{preset:"inspect",mode:"read-only"}];return $(n,["typecheck","type-check","check-types","tsc","check"])&&t.push({preset:"typecheck",mode:"propose"}),$(n,["lint","lint:ci"])&&t.push({preset:"lint",mode:"propose"}),$(n,["test","test:ci","test:unit"])&&t.push({preset:"fix-tests",mode:"propose"}),t},$n=e=>`${JSON.stringify({stopOnFailure:false,goals:Mn(e)},null,2)}
8
+ `,jn=e=>{let n=["# Brass Agent environment variables","# Copy this file to .env or .brass-agent.env, or export the variables in your shell.","# brass-agent auto-loads supported agent env keys from --cwd.","# Do not commit real API keys.",""];return e==="fake"&&n.push("BRASS_LLM_PROVIDER=fake","BRASS_FAKE_LLM_RESPONSE=Fake plan from .env.example",""),n.push("# Google / Gemini","# Used when .brass-agent.json selects provider google, or when auto-detected.","GEMINI_API_KEY=","BRASS_GOOGLE_MODEL=gemini-2.5-flash","","# OpenAI-compatible providers","# BRASS_LLM_PROVIDER=openai-compatible","BRASS_LLM_ENDPOINT=https://api.openai.com/v1/chat/completions","BRASS_LLM_API_KEY=","BRASS_LLM_MODEL=gpt-4.1","","# Approval behavior: auto | interactive | approve | deny","# BRASS_AGENT_APPROVAL=auto",""),e==="google"?n.splice(4,0,"BRASS_LLM_PROVIDER=google",""):e==="openai-compatible"&&n.splice(4,0,"BRASS_LLM_PROVIDER=openai-compatible",""),`${n.join(`
9
+ `)}
10
+ `},Bn=()=>["# Brass Agent","","This workspace was initialized with `brass-agent --init`.","","Generated files:","","- `.brass-agent.json` \u2014 local policy/config for Brass Agent.","- `brass-agent.batch.json` \u2014 sample multi-goal batch workflow.","- `.env.example` \u2014 example environment variables. Copy to `.env` or `.brass-agent.env`; keep real secrets out of git.","","Recommended first commands:","","```bash","brass-agent --doctor","brass-agent --preset inspect","brass-agent --batch-file brass-agent.batch.json","```","","Apply mode is intentionally approval-gated:","","```bash",'brass-agent --apply "fix the failing tests"',"```",""].join(`
11
+ `),Dn=e=>{let n=["Review .brass-agent.json and adjust permissions/context budgets for this repo.","Run: brass-agent --doctor","Run: brass-agent --preset inspect","Run: brass-agent --batch-file brass-agent.batch.json"];return e==="google"?["Set GEMINI_API_KEY in your shell, `.env`, or `.brass-agent.env`.",...n]:e==="openai-compatible"?["Set BRASS_LLM_API_KEY and BRASS_LLM_ENDPOINT in your shell, `.env`, or `.brass-agent.env`.",...n]:e==="default"?["Set an LLM provider env var in your shell, `.env`, or `.brass-agent.env` when ready, or let the CLI fall back to fake mode.",...n]:n},T=async e=>{let n=resolve(e.cwd,e.relativePath),o=existsSync(n)?e.force?"overwritten":"skipped":"created";return !e.dryRun&&o!=="skipped"&&(await mkdir(dirname(n),{recursive:true}),await writeFile(n,e.content,"utf8")),{path:n,relativePath:e.relativePath,status:o,bytes:Buffer.byteLength(e.content,"utf8")}},je=async e=>{let n=resolve(e.cwd),t=e.profile??"default",o=e.force??false,r=e.dryRun??false,a=Fn(n,t),l=await Promise.all([T({cwd:n,relativePath:".brass-agent.json",content:`${JSON.stringify(a,null,2)}
12
+ `,force:o,dryRun:r}),T({cwd:n,relativePath:"brass-agent.batch.json",content:$n(n),force:o,dryRun:r}),T({cwd:n,relativePath:".env.example",content:jn(t),force:o,dryRun:r}),T({cwd:n,relativePath:"BRASS_AGENT.md",content:Bn(),force:o,dryRun:r})]);return {cwd:n,profile:t,dryRun:r,files:l,nextSteps:Dn(t)}},Gn=e=>{switch(e){case "created":return "\u2713";case "overwritten":return "!";case "skipped":return "-"}},Be=e=>{console.log(`brass-agent init${e.dryRun?" (dry run)":""}`),console.log(`workspace: ${e.cwd}`),console.log(`profile: ${e.profile}`),console.log("");for(let n of e.files)console.log(`${Gn(n.status)} ${n.status} ${n.relativePath}`);console.log(""),console.log("next steps:");for(let n of e.nextSteps)console.log(`- ${n}`);};var F=new Function("specifier","return import(specifier)"),Nn=async(e,n)=>{let t=await F("node:path");return (await F("node:fs/promises")).readFile(t.resolve(e,n),"utf8")},K=e=>{if(e===void 0||e.trim()==="")return;let n=Number(e);return Number.isFinite(n)?n:void 0},Ye=e=>e==="read-only"||e==="propose"||e==="write"||e==="autonomous",Je=e=>e==="auto"||e==="interactive"||e==="approve"||e==="deny",De=e=>e==="default"||e==="google"||e==="openai-compatible"||e==="fake",Tn=e=>["auto","match-user","en","es","pt","fr","de","it","custom"].includes(e),k=(e,n,t)=>{let o=e[n],r=o.startsWith(`${t}=`)?o.slice(t.length+1):void 0;if(r!==void 0&&r!=="")return [r,n];let a=e[n+1];if(!a)throw new Error(`${t} requires a value`);return [a,n+1]},Kn=e=>{let n=process.cwd(),t=true,o=false,r="propose",a=false,l=false,s="human",c="auto",h=false,E,p=false,g,m=false,S=false,R,b="apply",V,re=false,se=false,W,Y,D,ae=false,ie=false,le=false,G="default",ce=false,J,U=[];for(let u=0;u<e.length;u+=1){let i=e[u];if(i==="--"){U.push(...e.slice(u+1));break}if(i==="--help"||i==="-h"){l=true;continue}if(i==="--doctor"){ae=true;continue}if(i==="--where"||i==="--print-workspace"){o=true;continue}if(i==="--no-discover-workspace"){t=false;continue}if(i==="--init"){ie=true;continue}if(i==="--force"||i==="--init-force"){le=true;continue}if(i==="--init-dry-run"){ce=true;continue}if(i==="--init-profile"||i.startsWith("--init-profile=")){let[d,f]=k(e,u,"--init-profile");if(!De(d))throw new Error("--init-profile requires one of: default, google, openai-compatible, fake");G=d,u=f;continue}if(i==="--init-provider"||i.startsWith("--init-provider=")){let[d,f]=k(e,u,"--init-provider");if(d==="auto")G="default";else if(De(d))G=d;else throw new Error("--init-provider requires one of: auto, fake, google, openai-compatible");u=f;continue}if(i==="--language"||i.startsWith("--language=")){let[d,f]=k(e,u,"--language");if(!Tn(d))throw new Error("--language requires one of: auto, match-user, en, es, pt, fr, de, it, custom");J=d,u=f;continue}if(i==="--json"){s="json";continue}if(i==="--events-json"){s="events-json";continue}if(i==="--protocol-json"){s="protocol-json";continue}if(i==="--protocol-full-patches"){S=true;continue}if(i==="--preset"||i.startsWith("--preset=")){let[d,f]=k(e,u,"--preset");if(!ga(d))throw new Error("--preset requires one of: fix-tests, inspect, typecheck, lint");W=d,u=f;continue}if(i==="--batch-file"||i.startsWith("--batch-file=")){let[d,f]=k(e,u,"--batch-file");Y=d,u=f;continue}if(i==="--batch-stop-on-failure"){D=true;continue}if(i==="--batch-continue-on-failure"){D=false;continue}if(i==="--ci"){re=true;continue}if(i==="--fail-on-patch-proposed"){se=true;continue}if(i==="--yes"||i==="-y"){c="approve",h=true;continue}if(i==="--no-input"){c="deny",h=true;continue}if(i==="--approval"||i.startsWith("--approval=")){let[d,f]=k(e,u,"--approval");if(!Je(d))throw new Error("--approval requires one of: auto, interactive, approve, deny");c=d,h=true,u=f;continue}if(i==="--apply"){r="write",a=true;continue}if(i==="--patch-file"||i.startsWith("--patch-file=")){let[d,f]=k(e,u,"--patch-file");R=d,u=f;continue}if(i==="--apply-patch-file"||i.startsWith("--apply-patch-file=")){let[d,f]=k(e,u,"--apply-patch-file");R=d,b="apply",r="write",a=true,u=f;continue}if(i==="--rollback-patch-file"||i.startsWith("--rollback-patch-file=")){let[d,f]=k(e,u,"--rollback-patch-file");R=d,b="rollback",r="write",a=true,u=f;continue}if(i==="--mode"||i.startsWith("--mode=")){let[d,f]=k(e,u,"--mode");if(!Ye(d))throw new Error("--mode requires one of: read-only, propose, write, autonomous");r=d,a=true,u=f;continue}if(i==="--cwd"||i.startsWith("--cwd=")){let[d,f]=k(e,u,"--cwd");n=d,u=f;continue}if(i==="--save-run"||i.startsWith("--save-run=")){let[d,f]=k(e,u,"--save-run");V=d,u=f;continue}if(i==="--config"||i.startsWith("--config=")){let[d,f]=k(e,u,"--config");E=d,p=false,u=f;continue}if(i==="--no-config"){E=void 0,p=true;continue}if(i==="--env-file"||i.startsWith("--env-file=")){let[d,f]=k(e,u,"--env-file");g=d,m=false,u=f;continue}if(i==="--no-env-file"){g=void 0,m=true;continue}if(i.startsWith("--"))throw new Error(`Unknown option: ${i}`);U.push(i);}return {cwd:n,discoverWorkspace:t,where:o,goalText:U.join(" ").trim(),mode:r,modeSpecified:a,showHelp:l,output:s,approval:c,approvalSpecified:h,...E?{configPath:E}:{},noConfig:p,...g?{envFile:g}:{},noEnvFile:m,protocolFullPatches:S,patchFileMode:b,ci:re,failOnPatchProposed:se,...W?{preset:W}:{},...Y?{batchFile:Y}:{},...D!==void 0?{batchStopOnFailure:D}:{},doctor:ae,init:ie,initForce:le,initProfile:G,initDryRun:ce,...J?{language:J}:{},...V?{saveRunDir:V}:{},...R?{patchFile:R}:{}}},Ue=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),Vn=(e,n)=>{if(typeof e=="string")return e;if(!Ue(e))throw new Error(`${n} must be a string or object.`);let t=e.goal,o=e.preset,r=e.mode,a=e.cwd,l=e.patchFile,s=e.patchFileMode,c=e.saveRunDir;if(t!==void 0&&typeof t!="string")throw new Error(`${n}.goal must be a string.`);if(a!==void 0&&typeof a!="string")throw new Error(`${n}.cwd must be a string.`);if(l!==void 0&&typeof l!="string")throw new Error(`${n}.patchFile must be a string.`);if(c!==void 0&&typeof c!="string")throw new Error(`${n}.saveRunDir must be a string.`);if(o!==void 0&&(typeof o!="string"||!ga(o)))throw new Error(`${n}.preset must be one of: fix-tests, inspect, typecheck, lint.`);if(r!==void 0&&(typeof r!="string"||!Ye(r)))throw new Error(`${n}.mode must be one of: read-only, propose, write, autonomous.`);if(s!==void 0&&s!=="apply"&&s!=="rollback")throw new Error(`${n}.patchFileMode must be apply or rollback.`);if(t===void 0&&o===void 0&&l===void 0)throw new Error(`${n} must include goal, preset, or patchFile.`);return {...t?{goal:t}:{},...o?{preset:o}:{},...r?{mode:r}:{},...a?{cwd:a}:{},...l?{patchFile:l}:{},...s?{patchFileMode:s}:{},...c?{saveRunDir:c}:{}}},Wn=e=>{let n=Array.isArray(e)?e:Ue(e)&&Array.isArray(e.goals)?e.goals:void 0;if(!n)throw new Error("Batch file must be a JSON array or an object with a goals array.");return n.map((t,o)=>Vn(t,`goals[${o}]`))},Yn=async(e,n)=>{let t=await F("node:path"),o=await F("node:fs/promises"),r=t.isAbsolute(n)?n:t.resolve(e,n),a=String(await o.readFile(r,"utf8")).replace(/^\uFEFF/,"");try{return Wn(JSON.parse(a))}catch(l){if(!(l instanceof SyntaxError))throw l;let s=a.split(/\r?\n/g).map(c=>c.trim()).filter(c=>c&&!c.startsWith("#"));if(s.length===0)throw new Error(`Batch file has no goals: ${r}`);return s}},Jn=(e,n)=>typeof e=="string"?e:e.goal?e.goal:e.preset?ha(e.preset):e.patchFile??n?"apply supplied patch":"",Un=(e,n,t)=>typeof e!="string"&&e.mode?e.mode:typeof e!="string"&&e.preset==="inspect"&&!n.modeSpecified?"read-only":n.modeSpecified?n.mode:t.mode??n.mode,qn=(e,n,t)=>e.map((o,r)=>{let a=Jn(o,n.patchFile),l=typeof o=="string"?n.cwd:o.cwd??n.cwd,s=typeof o=="string"?n.patchFile:o.patchFile??n.patchFile,c=typeof o=="string"?n.patchFileMode:o.patchFileMode??n.patchFileMode,h=typeof o=="string"?n.saveRunDir:o.saveRunDir??n.saveRunDir;if(!a)throw new Error(`Batch goal ${r+1} resolved to an empty goal.`);return {index:r,cwd:l,goalText:a,mode:Un(o,n,t),patchFileMode:c,...s?{patchFile:s}:{},...h?{saveRunDir:h}:{}}}),Hn=async e=>{let n=ta(e.cwd,{enabled:e.discoverWorkspace}),t=n.cwd,o={...e,cwd:t},r=await pa({cwd:t,configPath:e.configPath,noConfig:e.noConfig}),a=Ce({cwd:t,envFile:e.envFile,noEnvFile:e.noEnvFile,allowedExtraKeys:r.config.llm?.apiKeyEnv?[r.config.llm.apiKeyEnv]:[]}),l=!e.goalText&&!e.preset&&!e.patchFile,s=e.batchFile?await Yn(t,e.batchFile):l?r.config.batch?.goals??[]:[],c=qn(s,o,r.config);return {...o,goalText:e.goalText||(e.preset?ha(e.preset):e.patchFile?"apply supplied patch":e.goalText),mode:e.modeSpecified?e.mode:e.preset==="inspect"?"read-only":r.config.mode??e.mode,approval:e.approvalSpecified?e.approval:r.config.approval??e.approval,config:r.config,workspaceDiscovery:n,batchRuns:c,batchStopOnFailureResolved:e.batchStopOnFailure??r.config.batch?.stopOnFailure??e.ci,envFileLoad:a,...r.path?{resolvedConfigPath:r.path}:{}}},Ge=()=>{console.log(['Usage: brass-agent [options] "goal"',"","Options:"," --mode read-only|propose|write|autonomous"," Agent permission mode. Default: propose, or config.mode if present."," --preset fix-tests|inspect|typecheck|lint"," Use a built-in goal preset when no explicit goal text is provided."," --apply"," Alias for --mode write."," --cwd PATH"," Starting directory for workspace discovery. Default: current directory."," --no-discover-workspace"," Use --cwd exactly instead of searching upward for package.json, .brass-agent.json, or .git."," --where, --print-workspace"," Print the resolved workspace root and exit."," --config PATH"," Load a specific .brass-agent.json policy/config file."," --save-run DIR"," Write final run JSON and Markdown artifacts to DIR."," --batch-file PATH"," Run multiple goals sequentially from a JSON or line-based file."," --batch-stop-on-failure"," Stop a batch after the first failed run."," --batch-continue-on-failure"," Continue a batch even when a run fails."," --doctor"," Check local CLI, workspace, VS Code, package manager, and LLM setup."," --init"," Initialize this workspace with .brass-agent.json, brass-agent.batch.json, .env.example, and BRASS_AGENT.md."," --force, --init-force"," Overwrite files generated by --init when they already exist."," --init-profile default|google|openai-compatible|fake"," Initialization profile. Default: default, which leaves provider auto-detection enabled."," --init-provider auto|fake|google|openai-compatible"," Alias for choosing an LLM-oriented init profile. auto maps to default."," --init-dry-run"," Preview generated files without writing them."," --no-config"," Do not discover or load an agent config file."," --language auto|match-user|en|es|pt|fr|de|it"," Response language for LLM summaries. Default: config.language or auto-match the user goal."," --env-file PATH"," Load Brass Agent environment variables from a specific env file."," --no-env-file"," Do not auto-load .brass-agent.env, .env.local, or .env from --cwd."," --json"," Print the full final AgentState JSON. Suppresses live event output."," --ci"," Preserve output mode but set process exit codes from the final run status."," --fail-on-patch-proposed"," In --ci mode, exit 2 when a patch was proposed but not applied."," --events-json"," Stream AgentEvent objects as JSON Lines. Does not print the final AgentState."," --protocol-json"," Stream Brass Agent protocol JSON Lines, including events and a final-state message."," --protocol-full-patches"," Keep patch payloads untruncated in protocol/event JSON output for trusted local integrations."," --patch-file PATH"," Supply a precomputed unified diff to the agent. Respects --mode."," --apply-patch-file PATH"," Supply and apply a precomputed unified diff. Alias for --patch-file PATH --mode write."," --rollback-patch-file PATH"," Reverse-apply a precomputed unified diff through PatchService. Requires write mode approvals."," --yes, -y"," Auto-approve approval prompts. Useful for CI and smoke tests."," --no-input"," Do not prompt; reject any action that requires approval."," --approval auto|interactive|approve|deny"," Approval strategy. Default: auto, or config.approval if present."," --help, -h"," Show this help message.","","Config files:"," brass-agent first resolves a workspace root by searching upward from --cwd."," It looks for .brass-agent.json, brass-agent.config.json, package.json, workspace markers, or .git."," brass-agent then searches upward from that workspace root for .brass-agent.json or brass-agent.config.json."," config.batch.goals can define a default batch when --batch-file is not provided.","","Examples:",' brass-agent "fix the failing tests"'," brass-agent --preset fix-tests"," brass-agent --preset inspect"," brass-agent --batch-file ./brass-agent.batch.json --ci"," brass-agent --where"," brass-agent --doctor"," brass-agent --doctor --json"," brass-agent --env-file .env --doctor"," brass-agent --init"," brass-agent --init --init-profile google"," brass-agent --init --init-profile fake --init-dry-run",' brass-agent --config ./agent.policy.json "fix the failing tests"',' brass-agent --no-config "fix the failing tests"',' brass-agent --json "fix the failing tests"',' brass-agent --events-json "fix the failing tests"',' brass-agent --protocol-json "fix the failing tests"',' brass-agent --protocol-json --protocol-full-patches "fix the failing tests"',' brass-agent --apply-patch-file ./approved.diff --yes "apply approved patch"',' brass-agent --apply "fix the failing tests"',' brass-agent --apply --yes "fix the failing tests"',' brass-agent --mode read-only --cwd ./repo "inspect the test failure"',"","LLM providers:"," BRASS_LLM_PROVIDER=fake"," BRASS_LLM_PROVIDER=google GEMINI_API_KEY=..."," BRASS_LLM_PROVIDER=openai-compatible BRASS_LLM_ENDPOINT=... BRASS_LLM_API_KEY=..."].join(`
13
+ `));},qe=e=>e?process.env[e]:void 0,Ne=e=>{let n=qe(e?.apiKeyEnv)??process.env.BRASS_GOOGLE_API_KEY??process.env.GOOGLE_API_KEY??process.env.GEMINI_API_KEY;if(n)return ra({apiKey:n,model:process.env.BRASS_GOOGLE_MODEL??process.env.BRASS_LLM_MODEL??e?.model??"gemini-2.5-flash",apiVersion:process.env.BRASS_GOOGLE_API_VERSION??e?.apiVersion??"v1beta",baseUrl:process.env.BRASS_GOOGLE_BASE_URL??e?.baseUrl,endpoint:process.env.BRASS_GOOGLE_ENDPOINT??e?.endpoint,systemInstruction:process.env.BRASS_GOOGLE_SYSTEM_INSTRUCTION??e?.systemInstruction,temperature:K(process.env.BRASS_GOOGLE_TEMPERATURE)??e?.temperature,topP:K(process.env.BRASS_GOOGLE_TOP_P)??e?.topP,topK:K(process.env.BRASS_GOOGLE_TOP_K)??e?.topK,maxOutputTokens:K(process.env.BRASS_GOOGLE_MAX_OUTPUT_TOKENS)??e?.maxOutputTokens})},Te=e=>{let n=process.env.BRASS_LLM_ENDPOINT??e?.endpoint,t=qe(e?.apiKeyEnv)??process.env.BRASS_LLM_API_KEY,o=process.env.BRASS_LLM_MODEL??e?.model??"gpt-4.1";if(!(!n||!t))return qa({endpoint:n,apiKey:t,model:o})},zn=e=>{let n=(process.env.BRASS_LLM_PROVIDER??e?.provider)?.trim().toLowerCase(),t=process.env.BRASS_FAKE_LLM_RESPONSE??e?.fakeResponse;if(n==="fake")return sa({content:t});if(n==="google"||n==="gemini"){let o=Ne(e);if(!o)throw new Error("Google LLM provider requires BRASS_GOOGLE_API_KEY, GOOGLE_API_KEY, GEMINI_API_KEY, or config.llm.apiKeyEnv.");return o}if(n==="openai"||n==="openai-compatible"){let o=Te(e);if(!o)throw new Error("OpenAI-compatible LLM provider requires BRASS_LLM_ENDPOINT/config.llm.endpoint and BRASS_LLM_API_KEY/config.llm.apiKeyEnv.");return o}if(n)throw new Error(`Unsupported LLM provider: ${n}`);return Ne(e)??Te(e)??sa({content:t})},Qn=()=>{let e=process.env.BRASS_AGENT_APPROVAL?.trim().toLowerCase();if(e){if(Je(e))return e;throw new Error("BRASS_AGENT_APPROVAL must be one of: auto, interactive, approve, deny")}},Xn=e=>e==="1"||e?.toLowerCase()==="true"||e?.toLowerCase()==="yes",Zn=()=>!!(process.stdin?.isTTY&&(process.stderr?.isTTY??process.stdout?.isTTY)),et=e=>{if(e.approvalSpecified&&e.approval!=="auto")return e.approval;if(Xn(process.env.BRASS_AGENT_AUTO_APPROVE))return "approve";let n=Qn();return n&&n!=="auto"?n:e.approval!=="auto"?e.approval:e.output==="human"&&Zn()?"interactive":"deny"},nt=e=>{switch(et(e)){case "approve":return ka;case "deny":return la("Approval rejected because the CLI is running without interactive input. Use --yes to auto-approve.");case "interactive":return Pe()}},Ke=(e,n=2e3)=>e.length<=n?e:`${e.slice(0,n)}
14
+ \u2026 truncated ${e.length-n} chars`,I=(e,n=1e3)=>e.length<=n?e:`${e.slice(0,n)}\u2026 truncated ${e.length-n} chars`,B=(e,n)=>n.fullPatches?e:I(e),He=(e,n)=>({...e,...e.initialPatch?{initialPatch:B(e.initialPatch,n)}:{}}),j=(e,n={})=>{switch(e.type){case "llm.complete":return {...e,prompt:I(e.prompt)};case "patch.apply":case "patch.rollback":case "patch.propose":return {...e,patch:B(e.patch,n)};default:return e}},ne=(e,n={})=>{switch(e.type){case "fs.fileRead":return {...e,content:I(e.content)};case "llm.response":return {...e,content:I(e.content)};case "shell.result":return {...e,stdout:I(e.stdout),stderr:I(e.stderr)};case "fs.searchResult":return {...e,matches:e.matches.slice(0,30),omittedMatches:Math.max(0,e.matches.length-30)};case "patch.proposed":return {...e,patch:B(e.patch,n)};case "patch.applied":case "patch.rolledBack":return e.patch?{...e,patch:B(e.patch,n)}:e;default:return e}},ze=(e,n={})=>{switch(e.type){case "agent.run.started":case "agent.run.completed":return {...e,goal:He(e.goal,n)};case "agent.action.started":return {...e,action:j(e.action,n)};case "agent.action.completed":return {...e,action:j(e.action,n),observation:ne(e.observation,n)};case "agent.action.failed":return {...e,action:j(e.action,n)};case "agent.observation.recorded":return {...e,observation:ne(e.observation,n)};case "agent.tool.timeout":case "agent.permission.denied":case "agent.approval.requested":case "agent.approval.resolved":return {...e,action:j(e.action,n)};default:return e}},te=(e,n={})=>({...e,goal:He(e.goal,n),observations:e.observations.map(t=>ne(t,n)),errors:e.errors.map(t=>{switch(t._tag){case "PermissionDenied":case "ApprovalRejected":return {...t,action:j(t.action,n)};case "PatchError":return {...t,cause:String(t.cause),...t.patch?{patch:B(t.patch,n)}:{}};case "FsError":case "ShellError":case "LLMError":return {...t,cause:String(t.cause)};default:return t}})}),oe=e=>({protocol:"brass-agent",version:1,...e}),tt=e=>{switch(e){case "ok":return "\u2713";case "warn":return "!";case "fail":return "\u2717"}},Ve=e=>`${Math.max(0,e)}ms`,w=(e,n)=>[...e.observations].reverse().find(t=>t.type===n),ot=e=>({emit(n){switch(n.type){case "agent.run.started":console.log(`brass-agent ${n.goal.mode}`),console.log(`workspace: ${n.goal.cwd}`),e&&console.log(`config: ${e}`),console.log(`goal: ${n.goal.text}`),console.log("");break;case "agent.action.started":console.log(`\u2192 ${T$1(n.action)}`);break;case "agent.action.completed":{let t=V(n.observation);console.log(`${tt(t)} ${U(n.observation)} ${Ve(n.durationMs)}`);break}case "agent.action.failed":n.error._tag!=="ToolTimeout"&&n.error._tag!=="PermissionDenied"&&n.error._tag!=="ApprovalRejected"&&console.log(`\u2717 ${T$1(n.action)} failed with ${n.error._tag} ${Ve(n.durationMs)}`);break;case "agent.tool.timeout":console.log(`! ${T$1(n.action)} timed out after ${n.timeoutMs}ms`);break;case "agent.permission.denied":console.log(`\u2717 ${T$1(n.action)} denied: ${n.reason}`);break;case "agent.approval.requested":console.log(`? approval required for ${T$1(n.action)} (${n.risk})`);break;case "agent.approval.resolved":n.approved?console.log(`\u2713 approval granted for ${T$1(n.action)}`):console.log(`\u2717 approval rejected for ${T$1(n.action)}${n.reason?`: ${n.reason}`:""}`);break;case "agent.patch.applied":break;case "agent.patch.rolledBack":n.automatic&&console.log(`\u2713 automatic rollback completed (${n.changedFiles.join(", ")||"no files reported"})`);break;}}}),rt=(e={})=>({emit(n){console.log(JSON.stringify(ze(n,e)));}}),st=(e={})=>({emit(n){console.log(JSON.stringify(oe({type:"event",event:ze(n,e)})));}}),We=e=>e.toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,80)||"run",ee=e=>e.replace(/\\/g,"\\\\").replace(/`/g,"\\`"),at=async(e,n,t)=>{let o=await F("node:path"),r=await F("node:fs/promises"),a=o.isAbsolute(n)?n:o.resolve(e.goal.cwd,n);await r.mkdir(a,{recursive:true});let s=`${We(e.goal.id)}-${We(e.goal.text)}`,c=o.join(a,`${s}.json`),h=o.join(a,`${s}.md`),E=w(e,"agent.done"),p=w(e,"agent.error"),g=w(e,"patch.applied"),m=w(e,"patch.rolledBack");await r.writeFile(c,`${JSON.stringify(te(e,t),null,2)}
15
+ `,"utf8"),await r.writeFile(h,[`# Brass Agent Run ${ee(e.goal.id)}`,"",`- Goal: ${ee(e.goal.text)}`,`- Workspace: ${ee(e.goal.cwd)}`,`- Mode: ${e.goal.mode}`,`- Phase: ${e.phase}`,`- Steps: ${e.steps}`,g?`- Changed files: ${g.changedFiles.join(", ")||"none reported"}`:void 0,m?`- Rolled back files: ${m.changedFiles.join(", ")||"none reported"}`:void 0,"","## Summary","",E?.summary?.trim()||(p?`Error: ${p.error._tag}`:"No summary recorded.")].filter(Boolean).join(`
16
+ `),"utf8"),process.stderr?.isTTY&&console.error(`saved run artifacts: ${c} ${h}`);},it=e=>w(e,"shell.result"),lt=(e,n)=>{if(w(e,"agent.error"))return 1;let t=it(e);return t&&t.exitCode!==0?1:n.failOnPatchProposed&&w(e,"patch.proposed")&&!w(e,"patch.applied")?2:0},ct=e=>{let n=w(e,"agent.done"),t=w(e,"agent.error"),o=w(e,"patch.proposed"),r=w(e,"patch.applied"),a=w(e,"patch.rolledBack"),l=w(e,"llm.response");console.log(""),console.log(`phase: ${e.phase}`),console.log(`steps: ${e.steps}`),a?console.log(`rolled back files: ${a.changedFiles.join(", ")||"(none reported)"}`):r?console.log(`changed files: ${r.changedFiles.join(", ")||"(none reported)"}`):o&&console.log("patch: proposed only; rerun with --apply to apply it"),n?(console.log(""),console.log("summary:"),console.log(Ke(n.summary.trim()||"Agent completed."))):t?(console.log(""),console.log("error:"),console.log(JSON.stringify(t.error,null,2))):l&&(console.log(""),console.log("llm response:"),console.log(Ke(l.content.trim())));},pt=(e,n)=>e.output==="human"?ot(e.resolvedConfigPath):e.output==="events-json"?rt(n):e.output==="protocol-json"?st(n):void 0,dt=(e,n)=>{let t=ma;return {shell:t,fs:na(t),patch:oa(t),llm:zn(e.config.llm),permissions:ia(e.config.permissions),approvals:nt(e),...n?{events:n}:{},...e.config.tools?{toolPolicies:e.config.tools}:{}}},ut=e=>({index:0,cwd:e.cwd,goalText:e.goalText,mode:e.mode,patchFileMode:e.patchFileMode,...e.patchFile?{patchFile:e.patchFile}:{},...e.saveRunDir?{saveRunDir:e.saveRunDir}:{}}),gt=async(e,n,t,o)=>{let r=dt(e,o),a=new M$1({env:r}),l=n.patchFile?await Nn(n.cwd,n.patchFile):void 0,s=await a.toPromise(ba(a,{id:`agent-${Date.now()}-${n.index+1}`,cwd:n.cwd,text:n.goalText,mode:n.mode,...e.config.project?{project:e.config.project}:{},...e.config.context?{context:e.config.context}:{},...e.config.patchQuality?{patchQuality:e.config.patchQuality}:{},...e.config.rollback?{rollback:e.config.rollback}:{},...e.config.redaction?{redaction:e.config.redaction}:{},...e.language?{language:{response:e.language}}:e.config.language?{language:e.config.language}:{},...l?{initialPatch:l,initialPatchMode:n.patchFileMode}:{}}));return n.saveRunDir&&await at(s,n.saveRunDir,t),{run:n,state:s,exitCode:lt(s,{failOnPatchProposed:e.failOnPatchProposed})}},ft=e=>e.some(n=>n.exitCode===1)?1:e.some(n=>n.exitCode===2)?2:0,Qe=(e,n)=>({total:e.length,completed:n.length,failed:n.filter(t=>t.exitCode!==0).length,exitCode:ft(n),stoppedEarly:n.length<e.length}),mt=(e,n)=>{let t=Qe(e,n);console.log(""),console.log("batch summary:"),console.log(`completed: ${t.completed}/${t.total}`),console.log(`failed: ${t.failed}`),t.stoppedEarly&&console.log("stopped early: yes"),console.log(`exit code: ${t.exitCode}`);},yt=e=>{let n={cwd:e.cwd,inputCwd:e.workspaceDiscovery.inputCwd,changed:e.workspaceDiscovery.changed,disabled:!!e.workspaceDiscovery.disabled,marker:e.workspaceDiscovery.marker,markerPath:e.workspaceDiscovery.markerPath,configPath:e.resolvedConfigPath,envFiles:e.envFileLoad.paths};if(e.output==="json"||e.output==="protocol-json"){console.log(JSON.stringify(n,null,2));return}console.log("brass-agent workspace"),console.log(`input: ${n.inputCwd}`),console.log(`workspace: ${n.cwd}`),n.disabled?console.log("discovery: disabled"):n.marker?console.log(`marker: ${n.marker} (${n.markerPath})`):console.log("marker: none found; using input cwd"),n.configPath&&console.log(`config: ${n.configPath}`),n.envFiles.length>0&&console.log(`env: ${n.envFiles.join(", ")}`);},ht=async()=>{let e=await Hn(Kn(process.argv.slice(2))),n=e.batchRuns.length>0;if(e.showHelp&&(Ge(),process.exit(0)),e.where){yt(e);return}if(e.init){let s=await je({cwd:e.cwd,force:e.initForce,dryRun:e.initDryRun,profile:e.initProfile});e.output==="json"?console.log(JSON.stringify(s,null,2)):Be(s);return}if(e.doctor){let s=await _e({cwd:e.cwd,config:e.config,configPath:e.resolvedConfigPath,envFileLoad:e.envFileLoad,workspaceDiscovery:e.workspaceDiscovery});e.output==="json"?console.log(JSON.stringify(s,null,2)):xe(s),process.exitCode=s.status==="fail"?1:0;return}!e.goalText&&!n&&(Ge(),process.exit(1));let t={fullPatches:e.protocolFullPatches},o=pt(e,t),r=n?e.batchRuns:[ut(e)],a=[];for(let s of r){let c=await gt(e,s,t,o);if(a.push(c),e.output==="protocol-json"?console.log(JSON.stringify(oe({type:"final-state",state:te(c.state,t)}))):e.output==="human"&&ct(c.state),n&&e.batchStopOnFailureResolved&&c.exitCode!==0)break}if(n){let s=Qe(r,a);e.output==="json"?console.log(JSON.stringify({type:"batch",summary:s,results:a.map(c=>({index:c.run.index,goal:c.run.goalText,cwd:c.run.cwd,mode:c.run.mode,exitCode:c.exitCode,state:te(c.state,t)}))},null,2)):e.output==="protocol-json"?console.log(JSON.stringify(oe({type:"batch-summary",summary:s}))):e.output==="human"&&mt(r,a),e.ci&&(process.exitCode=s.exitCode);return}let l=a[0];if(!l)throw new Error("Agent run did not produce a result.");e.output==="json"&&console.log(JSON.stringify(l.state,null,2)),e.ci&&(process.exitCode=l.exitCode);};ht().catch(e=>{console.error(e),process.exit(1);});
@@ -0,0 +1 @@
1
+ 'use strict';var chunk63ODH5W4_cjs=require('../chunk-63ODH5W4.cjs');require('../chunk-T3QEEHK6.cjs');Object.defineProperty(exports,"AGENT_CONFIG_FILE_NAMES",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.fa}});Object.defineProperty(exports,"NodeShell",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.ma}});Object.defineProperty(exports,"PROJECT_LOCKFILE_PROBES",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.m}});Object.defineProperty(exports,"PROJECT_PROFILE_PROBES",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.i}});Object.defineProperty(exports,"autoApproveApprovals",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.ka}});Object.defineProperty(exports,"canAutoRollback",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.D}});Object.defineProperty(exports,"canRequestPatchRepair",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.x}});Object.defineProperty(exports,"commandForScript",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.r}});Object.defineProperty(exports,"decideNextAction",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.P}});Object.defineProperty(exports,"defaultPermissions",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.ja}});Object.defineProperty(exports,"deriveContextSearchQueries",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.e}});Object.defineProperty(exports,"describeCommandDiscovery",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.u}});Object.defineProperty(exports,"describeContextDiscovery",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.f}});Object.defineProperty(exports,"describeLanguagePolicy",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.N}});Object.defineProperty(exports,"describePatchQuality",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.z}});Object.defineProperty(exports,"describeProjectProfile",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.l}});Object.defineProperty(exports,"describeRollbackSafety",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.G}});Object.defineProperty(exports,"discoverNodeWorkspaceRoot",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.ta}});Object.defineProperty(exports,"discoverPackageManager",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.p}});Object.defineProperty(exports,"discoverProjectProfile",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.k}});Object.defineProperty(exports,"discoverValidationCommands",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.s}});Object.defineProperty(exports,"emitAgentEvent",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.R}});Object.defineProperty(exports,"emitAgentEvents",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.S}});Object.defineProperty(exports,"errorEventFor",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.W}});Object.defineProperty(exports,"extractLikelyFilePaths",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.d}});Object.defineProperty(exports,"extractPatchPaths",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.I}});Object.defineProperty(exports,"extractUnifiedDiff",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.H}});Object.defineProperty(exports,"goalForAgentPreset",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.ha}});Object.defineProperty(exports,"inferUserLanguage",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.L}});Object.defineProperty(exports,"initialAgentState",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.a}});Object.defineProperty(exports,"invokeAction",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.aa}});Object.defineProperty(exports,"isAgentConfigApprovalMode",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.da}});Object.defineProperty(exports,"isAgentConfigLLMProvider",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.ea}});Object.defineProperty(exports,"isAgentConfigMode",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.ca}});Object.defineProperty(exports,"isAgentPreset",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.ga}});Object.defineProperty(exports,"isRedactionEnabled",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.J}});Object.defineProperty(exports,"isTerminal",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.c}});Object.defineProperty(exports,"latestUnappliedPatch",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.C}});Object.defineProperty(exports,"loadNodeAgentConfig",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.pa}});Object.defineProperty(exports,"makeAutoDenyApprovals",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.la}});Object.defineProperty(exports,"makeConfiguredPermissions",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.ia}});Object.defineProperty(exports,"makeFakeLLM",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.sa}});Object.defineProperty(exports,"makeGoogleGenerativeAILLM",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.ra}});Object.defineProperty(exports,"makeNodeFileSystem",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.na}});Object.defineProperty(exports,"makeNodePatchService",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.oa}});Object.defineProperty(exports,"makeOpenAICompatibleLLM",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.qa}});Object.defineProperty(exports,"nextContextDiscoveryAction",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.h}});Object.defineProperty(exports,"nextProjectProbeAction",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.o}});Object.defineProperty(exports,"nextUnrunValidationCommand",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.t}});Object.defineProperty(exports,"nowMillis",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.Q}});Object.defineProperty(exports,"observationEventFor",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.X}});Object.defineProperty(exports,"observationStatus",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.V}});Object.defineProperty(exports,"parseProjectPackageJson",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.n}});Object.defineProperty(exports,"patchQualitySummary",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.w}});Object.defineProperty(exports,"patchRepairAttemptsUsed",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.v}});Object.defineProperty(exports,"patchValidationStatus",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.y}});Object.defineProperty(exports,"projectProfileProbePending",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.j}});Object.defineProperty(exports,"redactText",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.K}});Object.defineProperty(exports,"reduceAgentState",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.b}});Object.defineProperty(exports,"responseLanguageName",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.M}});Object.defineProperty(exports,"retry",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.Z}});Object.defineProperty(exports,"rollbackSafetySummary",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.A}});Object.defineProperty(exports,"runAgent",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.ba}});Object.defineProperty(exports,"runStatusFor",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.Y}});Object.defineProperty(exports,"shouldContinueRollbackStack",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.E}});Object.defineProperty(exports,"sleep",{enumerable:true,get:function(){return chunk63ODH5W4_cjs._}});Object.defineProperty(exports,"spanishLike",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.O}});Object.defineProperty(exports,"splitCommand",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.q}});Object.defineProperty(exports,"summarizeAgentAction",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.T}});Object.defineProperty(exports,"summarizeAgentObservation",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.U}});Object.defineProperty(exports,"summarizeContextDiscovery",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.g}});Object.defineProperty(exports,"timeout",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.$}});Object.defineProperty(exports,"unappliedPatchStack",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.B}});Object.defineProperty(exports,"workspaceValidationStatus",{enumerable:true,get:function(){return chunk63ODH5W4_cjs.F}});