brass-runtime 1.16.0 → 1.16.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/CHANGELOG.md +17 -0
- package/README.md +283 -18
- package/dist/agent/cli/main.cjs +38 -38
- package/dist/agent/cli/main.js +6 -6
- package/dist/agent/cli/main.mjs +6 -6
- package/dist/agent/index.cjs +7 -7
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.js +6 -6
- package/dist/agent/index.mjs +6 -6
- package/dist/chunk-2HQTDLHF.mjs +683 -0
- package/dist/chunk-36I3M4UC.mjs +370 -0
- package/dist/{chunk-QY5FKYEQ.js → chunk-3AYM6WPJ.js} +570 -51
- package/dist/chunk-3LOYJFRR.cjs +300 -0
- package/dist/chunk-3Y2RIUMM.js +300 -0
- package/dist/{chunk-N6VHMOWB.cjs → chunk-4ROBZFL6.cjs} +128 -128
- package/dist/{chunk-NC5SDRYE.js → chunk-52OB2ROS.js} +4 -4
- package/dist/{chunk-JX3LZQJH.cjs → chunk-52PPNNI4.cjs} +82 -20
- package/dist/{chunk-5YOQOXEQ.cjs → chunk-5EC274J5.cjs} +676 -293
- package/dist/chunk-5QC7LRZ3.js +229 -0
- package/dist/{chunk-7TL2LHQJ.js → chunk-5VRJNBLZ.mjs} +524 -141
- package/dist/chunk-62AZW6UT.cjs +313 -0
- package/dist/chunk-6IXXWIUM.js +683 -0
- package/dist/chunk-74ZTY6CP.js +2871 -0
- package/dist/chunk-76YMRMH2.cjs +777 -0
- package/dist/chunk-7CMJS3QE.mjs +2871 -0
- package/dist/{chunk-2WC63LJK.mjs → chunk-7JIJOVCT.js} +20 -10
- package/dist/{chunk-FM4W4QPL.js → chunk-A2OM6NEH.mjs} +5 -4
- package/dist/chunk-AGR5B2BC.cjs +683 -0
- package/dist/chunk-AVNQLJ5V.js +777 -0
- package/dist/chunk-B33ICAKP.js +313 -0
- package/dist/{chunk-J3H54ZRV.mjs → chunk-B5JD23U7.mjs} +1 -1
- package/dist/chunk-BABBZK4Y.js +2024 -0
- package/dist/{chunk-U5KWK3PX.mjs → chunk-C3MDXTRZ.js} +11 -0
- package/dist/{chunk-F5EUMJL7.mjs → chunk-CIZFIMK5.js} +55 -5
- package/dist/{chunk-SPUEME2B.cjs → chunk-CZIVE6NT.cjs} +12 -1
- package/dist/{chunk-TDVMADDN.js → chunk-DNFJLJMW.mjs} +11 -0
- package/dist/chunk-DNFO2EIZ.mjs +777 -0
- package/dist/{chunk-XDZOO4L5.js → chunk-EJ6BPYVR.mjs} +79 -17
- package/dist/{chunk-JNFRRJYH.cjs → chunk-ENKODRU3.cjs} +242 -192
- package/dist/chunk-EOC4UHBS.mjs +229 -0
- package/dist/{chunk-7LVI2GIN.js → chunk-FH2X7BVP.js} +507 -72
- package/dist/{chunk-OOGJ73B6.js → chunk-FHQGHPMO.mjs} +20 -10
- package/dist/{chunk-WQ5QNU5R.cjs → chunk-GLE2WY7Z.cjs} +652 -217
- package/dist/{chunk-G6IQOE4P.mjs → chunk-GYM3LLGS.mjs} +507 -72
- package/dist/chunk-HLWLMW2F.mjs +2024 -0
- package/dist/{chunk-TVN5I4U6.cjs → chunk-JF5WGYJJ.cjs} +25 -24
- package/dist/{chunk-CY33PGEX.mjs → chunk-KH4SYAOS.mjs} +570 -51
- package/dist/chunk-KN32XNTH.mjs +313 -0
- package/dist/chunk-KQLYONSE.cjs +2871 -0
- package/dist/{chunk-7HUOJA4W.cjs → chunk-KZJQ723N.cjs} +90 -80
- package/dist/{chunk-CCKHV5BT.mjs → chunk-L2SYFEBS.js} +5 -4
- package/dist/{chunk-IJT6RRQ5.cjs → chunk-L6VB5N7Q.cjs} +20 -9
- package/dist/{chunk-ZGLD4TVZ.mjs → chunk-MBEJI5HF.mjs} +4 -4
- package/dist/{chunk-PRWCB3QL.mjs → chunk-MIIYDLGM.js} +524 -141
- package/dist/{chunk-H55LI6WY.js → chunk-MOO4L7F4.mjs} +15 -4
- package/dist/{chunk-7XOPAB5Q.js → chunk-MT3OWDPC.mjs} +55 -5
- package/dist/chunk-MVGUEJ5Z.cjs +370 -0
- package/dist/chunk-PD4EJTQC.cjs +229 -0
- package/dist/chunk-PWC3RBQE.mjs +300 -0
- package/dist/{chunk-MWXMNYJS.cjs → chunk-Q2I37RP3.cjs} +643 -124
- package/dist/{chunk-VFIUZG7J.mjs → chunk-RKGKFN2A.js} +79 -17
- package/dist/{chunk-NYL4D7SK.cjs → chunk-SA6HUJVI.cjs} +5 -5
- package/dist/{chunk-K2T3DV26.mjs → chunk-TRM4JUZQ.js} +15 -4
- package/dist/chunk-UB4B6OFY.js +370 -0
- package/dist/{chunk-G3XGCZDQ.js → chunk-UCUBNWM2.js} +1 -1
- package/dist/chunk-VN44DYYT.cjs +2024 -0
- package/dist/{client-CtFmoDvM.d.ts → client-CZHU674n.d.ts} +211 -36
- package/dist/core/index.cjs +135 -9
- package/dist/core/index.d.ts +238 -33
- package/dist/core/index.js +155 -29
- package/dist/core/index.mjs +155 -29
- package/dist/{effect-CGNl5Rqp.d.ts → effect-DIUHZ9IN.d.ts} +89 -1
- package/dist/effectRunner-CFLC32IK.cjs +8 -0
- package/dist/{effectRunner-A4CHJXJI.js → effectRunner-L4S7IPT3.js} +2 -2
- package/dist/{effectRunner-OPUF6QRN.mjs → effectRunner-NNGG75QA.mjs} +2 -2
- package/dist/http/index.cjs +324 -2986
- package/dist/http/index.d.ts +54 -68
- package/dist/http/index.js +238 -2900
- package/dist/http/index.mjs +238 -2900
- package/dist/http/testing.cjs +14 -12
- package/dist/http/testing.d.ts +5 -4
- package/dist/http/testing.js +10 -8
- package/dist/http/testing.mjs +10 -8
- package/dist/index.cjs +423 -255
- package/dist/index.d.ts +87 -69
- package/dist/index.js +301 -133
- package/dist/index.mjs +301 -133
- package/dist/observability/index.cjs +16 -531
- package/dist/observability/index.d.ts +81 -8
- package/dist/observability/index.js +23 -538
- package/dist/observability/index.mjs +23 -538
- package/dist/perf/cli.cjs +401 -0
- package/dist/perf/cli.d.ts +1 -0
- package/dist/perf/cli.js +401 -0
- package/dist/perf/cli.mjs +401 -0
- package/dist/perf/index.cjs +141 -0
- package/dist/perf/index.d.ts +483 -0
- package/dist/perf/index.js +141 -0
- package/dist/perf/index.mjs +141 -0
- package/dist/schedule-CK3Ml_7p.d.ts +259 -0
- package/dist/schema/index.cjs +6 -2
- package/dist/schema/index.d.ts +3 -1
- package/dist/schema/index.js +5 -1
- package/dist/schema/index.mjs +5 -1
- package/dist/{server-C8hDXA74.d.ts → server-GJPg8ZSG.d.ts} +4 -3
- package/dist/{stream-dvSs0QS5.d.ts → stream-B4oK9JFP.d.ts} +1 -1
- package/dist/{tracer-B5tRH9H7.d.ts → tracer-Hwt1cl7h.d.ts} +13 -54
- package/dist/{tracing-Dt9S_6V8.d.ts → tracing-DqbTKGcf.d.ts} +1 -1
- package/docs/ARCHITECTURE.md +292 -0
- package/docs/README.md +63 -0
- package/docs/adr/0001-ai-context-pack.md +32 -0
- package/docs/agent-apply-mode.md +104 -0
- package/docs/agent-approvals.md +110 -0
- package/docs/agent-batch.md +185 -0
- package/docs/agent-boundaries.md +112 -0
- package/docs/agent-chat-sessions.md +160 -0
- package/docs/agent-ci.md +17 -0
- package/docs/agent-cli.md +405 -0
- package/docs/agent-config.md +480 -0
- package/docs/agent-context-discovery.md +159 -0
- package/docs/agent-copilot-like-dx.md +126 -0
- package/docs/agent-declarative-optimized-planning.md +138 -0
- package/docs/agent-dx.md +224 -0
- package/docs/agent-env-files.md +126 -0
- package/docs/agent-follow-up-context.md +43 -0
- package/docs/agent-global-usage.md +180 -0
- package/docs/agent-init.md +109 -0
- package/docs/agent-install-and-configure.md +516 -0
- package/docs/agent-language-workspace-ux.md +99 -0
- package/docs/agent-llm-adapters.md +123 -0
- package/docs/agent-local-install.md +190 -0
- package/docs/agent-local-tests.md +51 -0
- package/docs/agent-observability.md +155 -0
- package/docs/agent-patch-quality-loop.md +162 -0
- package/docs/agent-presets.md +22 -0
- package/docs/agent-project-commands.md +237 -0
- package/docs/agent-project-intelligence.md +156 -0
- package/docs/agent-redaction.md +18 -0
- package/docs/agent-release-readiness.md +76 -0
- package/docs/agent-rollback-safety.md +162 -0
- package/docs/agent-rollback.md +23 -0
- package/docs/agent-run-artifacts.md +16 -0
- package/docs/agent-vscode-auto-discovery.md +137 -0
- package/docs/agent-vscode-batch-runner.md +100 -0
- package/docs/agent-vscode-chat-layout.md +90 -0
- package/docs/agent-vscode-clean-install.md +147 -0
- package/docs/agent-vscode-code-actions.md +70 -0
- package/docs/agent-vscode-diff-preview.md +45 -0
- package/docs/agent-vscode-inline-assist.md +56 -0
- package/docs/agent-vscode-install.md +186 -0
- package/docs/agent-vscode-model-setup.md +97 -0
- package/docs/agent-vscode-patch-preview.md +92 -0
- package/docs/agent-vscode-problems.md +79 -0
- package/docs/agent-vscode-project-dashboard.md +106 -0
- package/docs/agent-vscode-run-history.md +92 -0
- package/docs/agent-vscode-ux.md +73 -0
- package/docs/ai/INVARIANTS.md +84 -0
- package/docs/ai/PROJECT_MAP.md +338 -0
- package/docs/ai/PUBLIC_API.md +336 -0
- package/docs/ai/VALIDATION_MATRIX.md +67 -0
- package/docs/api-polish.md +37 -0
- package/docs/cancellation.md +162 -0
- package/docs/coverage.md +46 -0
- package/docs/getting-started.md +159 -0
- package/docs/guides/README.md +40 -0
- package/docs/guides/circuit-breaker.md +89 -0
- package/docs/guides/error-handling.md +91 -0
- package/docs/guides/getting-started.md +107 -0
- package/docs/guides/layers.md +189 -0
- package/docs/guides/metrics.md +101 -0
- package/docs/guides/resource-management.md +141 -0
- package/docs/guides/retry.md +215 -0
- package/docs/guides/semaphore.md +66 -0
- package/docs/guides/streams.md +117 -0
- package/docs/guides/supervisors.md +98 -0
- package/docs/guides/testing.md +162 -0
- package/docs/guides/tracing.md +71 -0
- package/docs/http-recipes.md +399 -0
- package/docs/http.md +749 -0
- package/docs/modules.md +285 -0
- package/docs/observability-collector-smoke.md +31 -0
- package/docs/observability-framework-examples.md +98 -0
- package/docs/observability.md +542 -0
- package/docs/otel-collector-smoke.yaml +27 -0
- package/docs/performance-profiler.md +199 -0
- package/docs/production-readiness.md +73 -0
- package/docs/recipes/README.md +12 -0
- package/docs/recipes/http-server.md +45 -0
- package/docs/recipes/layers.md +44 -0
- package/docs/recipes/performance.md +47 -0
- package/docs/recipes/runtime.md +41 -0
- package/docs/recipes/testing.md +41 -0
- package/docs/release.md +53 -0
- package/docs/wasm-bounded-queues.md +44 -0
- package/docs/wasm-engine-observability-benchmarks.md +85 -0
- package/docs/wasm-fiber-engine.md +117 -0
- package/docs/wasm-scheduler-state-machine.md +122 -0
- package/docs/wasm-stream-chunks.md +54 -0
- package/package.json +22 -2
- package/dist/chunk-45F7OKGT.cjs +0 -104
- package/dist/chunk-7V4KY4RL.mjs +0 -104
- package/dist/chunk-DJQ7OMMB.cjs +0 -144
- package/dist/chunk-GOV47PPB.mjs +0 -552
- package/dist/chunk-JF4XXPZ5.cjs +0 -552
- package/dist/chunk-KCPT2D6G.js +0 -552
- package/dist/chunk-NOYZIMUJ.mjs +0 -144
- package/dist/chunk-PNVFW245.js +0 -144
- package/dist/chunk-ROJC3NBJ.js +0 -104
- package/dist/effectRunner-3ZHAD3LE.cjs +0 -8
- package/dist/schedule-Fque9Abz.d.ts +0 -70
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Agent LLM adapters
|
|
2
|
+
|
|
3
|
+
`src/agent` keeps LLM providers behind the small `LLM` capability:
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
export type LLM = {
|
|
7
|
+
readonly complete: (request: LLMRequest) => Async<unknown, AgentError, LLMResponse>;
|
|
8
|
+
};
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Adapters must return `Async` and must be cancelable. They should not leak provider-specific request or response shapes into the agent loop.
|
|
12
|
+
|
|
13
|
+
## Provider selection in the CLI
|
|
14
|
+
|
|
15
|
+
The local CLI chooses a provider from environment variables:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
BRASS_LLM_PROVIDER=google # or gemini
|
|
19
|
+
BRASS_LLM_PROVIDER=openai-compatible
|
|
20
|
+
BRASS_LLM_PROVIDER=fake
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
If `BRASS_LLM_PROVIDER` is omitted, the CLI auto-detects providers in this order:
|
|
24
|
+
|
|
25
|
+
1. Google Gemini, when `BRASS_GOOGLE_API_KEY`, `GOOGLE_API_KEY`, or `GEMINI_API_KEY` exists.
|
|
26
|
+
2. OpenAI-compatible, when both `BRASS_LLM_ENDPOINT` and `BRASS_LLM_API_KEY` exist.
|
|
27
|
+
3. Fake LLM, as a no-network fallback.
|
|
28
|
+
|
|
29
|
+
## Google Gemini / Generative Language API
|
|
30
|
+
|
|
31
|
+
Use the native Google adapter:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { makeGoogleGenerativeAILLM } from "brass-runtime/agent";
|
|
35
|
+
|
|
36
|
+
const llm = makeGoogleGenerativeAILLM({
|
|
37
|
+
apiKey: process.env.GEMINI_API_KEY!,
|
|
38
|
+
model: "gemini-2.5-flash",
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
CLI example:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
export BRASS_LLM_PROVIDER=google
|
|
46
|
+
export GEMINI_API_KEY="..."
|
|
47
|
+
export BRASS_GOOGLE_MODEL="gemini-2.5-flash"
|
|
48
|
+
|
|
49
|
+
npx tsx src/agent/cli/main.ts "fix the failing tests"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The same keys can live in `.env` or `.brass-agent.env` in the workspace; the
|
|
53
|
+
CLI auto-loads supported agent env keys before choosing the provider.
|
|
54
|
+
|
|
55
|
+
Supported Google-specific variables:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
BRASS_GOOGLE_API_KEY # preferred explicit key for brass-agent
|
|
59
|
+
GOOGLE_API_KEY # supported by Google SDKs; also accepted here
|
|
60
|
+
GEMINI_API_KEY # supported by Google SDKs; also accepted here
|
|
61
|
+
BRASS_GOOGLE_MODEL # defaults to gemini-2.5-flash
|
|
62
|
+
BRASS_GOOGLE_API_VERSION # defaults to v1beta
|
|
63
|
+
BRASS_GOOGLE_BASE_URL # defaults to https://generativelanguage.googleapis.com
|
|
64
|
+
BRASS_GOOGLE_ENDPOINT # full generateContent endpoint override
|
|
65
|
+
BRASS_GOOGLE_SYSTEM_INSTRUCTION
|
|
66
|
+
BRASS_GOOGLE_TEMPERATURE
|
|
67
|
+
BRASS_GOOGLE_TOP_P
|
|
68
|
+
BRASS_GOOGLE_TOP_K
|
|
69
|
+
BRASS_GOOGLE_MAX_OUTPUT_TOKENS
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The adapter uses `models.generateContent` with the `x-goog-api-key` header and maps Gemini `candidates[].content.parts[].text` into `LLMResponse.content`.
|
|
73
|
+
|
|
74
|
+
## OpenAI-compatible
|
|
75
|
+
|
|
76
|
+
Use the existing adapter:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
export BRASS_LLM_PROVIDER=openai-compatible
|
|
80
|
+
export BRASS_LLM_ENDPOINT="https://.../chat/completions"
|
|
81
|
+
export BRASS_LLM_API_KEY="..."
|
|
82
|
+
export BRASS_LLM_MODEL="..."
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Fake
|
|
86
|
+
|
|
87
|
+
Use this for offline smoke tests:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
export BRASS_LLM_PROVIDER=fake
|
|
91
|
+
npx tsx src/agent/cli/main.ts "fix the failing tests"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
You can also force a deterministic fake response, including a fenced diff block:
|
|
95
|
+
|
|
96
|
+
~~~bash
|
|
97
|
+
export BRASS_LLM_PROVIDER=fake
|
|
98
|
+
export BRASS_FAKE_LLM_RESPONSE='```diff
|
|
99
|
+
--- a/hello.txt
|
|
100
|
+
+++ b/hello.txt
|
|
101
|
+
@@ -1 +1 @@
|
|
102
|
+
-old
|
|
103
|
+
+new
|
|
104
|
+
```'
|
|
105
|
+
~~~
|
|
106
|
+
|
|
107
|
+
## Config-file selection
|
|
108
|
+
|
|
109
|
+
P7 also lets the CLI select an adapter through `.brass-agent.json`:
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"llm": {
|
|
114
|
+
"provider": "google",
|
|
115
|
+
"model": "gemini-2.5-flash",
|
|
116
|
+
"apiKeyEnv": "GEMINI_API_KEY"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Environment variables still override config values. Secrets should stay in the
|
|
122
|
+
environment; the config loader rejects `llm.apiKey` and expects `llm.apiKeyEnv`
|
|
123
|
+
instead.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Brass Agent local install and doctor
|
|
2
|
+
|
|
3
|
+
> For the end-to-end setup flow, see [Brass Agent install and configure](./agent-install-and-configure.md).
|
|
4
|
+
|
|
5
|
+
P23 intentionally avoids CI/release automation. It focuses on making local DX
|
|
6
|
+
boring: build the CLI, package/install the VS Code extension, point the extension
|
|
7
|
+
at the local CLI, and diagnose the setup.
|
|
8
|
+
|
|
9
|
+
## One-command local VS Code install
|
|
10
|
+
|
|
11
|
+
From the repository root:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm run agent:vscode:install
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
That script performs the local install flow:
|
|
18
|
+
|
|
19
|
+
```txt
|
|
20
|
+
npm install # only if root node_modules is missing
|
|
21
|
+
npm run build # builds dist/agent/cli/main.cjs
|
|
22
|
+
npm install # inside extensions/vscode-brass-agent, if needed
|
|
23
|
+
npm run compile # extension TypeScript
|
|
24
|
+
npm run package:vsix # creates vscode-brass-agent-*.vsix
|
|
25
|
+
code --install-extension # installs the VSIX locally
|
|
26
|
+
write .vscode/settings.json # points brassAgent.command at the built local CLI
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The setting it writes is:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"brassAgent.command": "/absolute/path/to/brass-runtime/dist/agent/cli/main.cjs"
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
That means the extension can run the exact local CLI build without requiring a
|
|
38
|
+
global npm install.
|
|
39
|
+
|
|
40
|
+
## Global CLI for many projects
|
|
41
|
+
|
|
42
|
+
To use `brass-agent` outside the `brass-runtime` checkout:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm run agent:link
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Then from any project:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
brass-agent --where
|
|
52
|
+
brass-agent --doctor
|
|
53
|
+
brass-agent --preset inspect
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
To make VS Code work through that global command instead of an absolute local path:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm run agent:vscode:install:global
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
That command runs the global link flow and installs the VS Code extension with `brassAgent.command = "brass-agent"`.
|
|
63
|
+
|
|
64
|
+
To remove only the global CLI link/install:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npm run agent:unlink
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
To remove the VS Code extension, workspace settings/storage, generated VSIX files, and the global CLI link/install:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npm run agent:vscode:uninstall:global
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
To do a clean global reinstall:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npm run agent:vscode:reinstall:global
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Package only
|
|
83
|
+
|
|
84
|
+
To build/package the extension without installing it into VS Code:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npm run agent:vscode:package
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
This is useful when you want to manually install from VS Code via:
|
|
91
|
+
|
|
92
|
+
```txt
|
|
93
|
+
Extensions view
|
|
94
|
+
-> Views and More Actions...
|
|
95
|
+
-> Install from VSIX...
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Install script options
|
|
99
|
+
|
|
100
|
+
The underlying script is:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
node scripts/install-vscode-extension.mjs
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Useful options:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
node scripts/install-vscode-extension.mjs --dry-run
|
|
110
|
+
node scripts/install-vscode-extension.mjs --no-code-install
|
|
111
|
+
node scripts/install-vscode-extension.mjs --no-settings
|
|
112
|
+
node scripts/install-vscode-extension.mjs --workspace ../some-project
|
|
113
|
+
node scripts/install-vscode-extension.mjs --use-global-command
|
|
114
|
+
node scripts/install-vscode-extension.mjs --command brass-agent
|
|
115
|
+
node scripts/install-vscode-extension.mjs --code "code-insiders"
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Use `--workspace` when you want the script to write `.vscode/settings.json` into
|
|
119
|
+
a different project than the `brass-runtime` checkout. Use `--use-global-command`
|
|
120
|
+
when `brass-agent` is available on PATH and you do not want workspace settings to
|
|
121
|
+
point at an absolute `dist/agent/cli/main.cjs` path.
|
|
122
|
+
|
|
123
|
+
## Doctor
|
|
124
|
+
|
|
125
|
+
Run:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npm run agent:doctor
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
or after building/installing:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
brass-agent --doctor
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The doctor checks:
|
|
138
|
+
|
|
139
|
+
```txt
|
|
140
|
+
Node.js / npm
|
|
141
|
+
git
|
|
142
|
+
ripgrep / rg
|
|
143
|
+
workspace package.json and scripts
|
|
144
|
+
inferred package manager
|
|
145
|
+
LLM provider environment
|
|
146
|
+
.brass-agent.json / brass-agent.config.json discovery
|
|
147
|
+
VS Code `code` CLI
|
|
148
|
+
VS Code workspace setting brassAgent.command
|
|
149
|
+
local CLI build artifact
|
|
150
|
+
VS Code extension build / VSIX package
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
JSON output is available for scripts:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
brass-agent --doctor --json
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Why this is not CI
|
|
160
|
+
|
|
161
|
+
This is deliberately local-first. It gives us repeatable commands that a person
|
|
162
|
+
can run before we add workflows:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
npm run agent:vscode:install
|
|
166
|
+
npm run agent:doctor
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Later, CI can reuse the same install/build/doctor concepts, but P23 does not add
|
|
170
|
+
GitHub Actions or release automation.
|
|
171
|
+
|
|
172
|
+
## Initialize a workspace first
|
|
173
|
+
|
|
174
|
+
For a new project, bootstrap local config before deeper DX setup:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
brass-agent --init
|
|
178
|
+
brass-agent --doctor
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The VS Code extension also contributes `Brass Agent: Initialize Workspace`, which runs the same init flow from the command palette.
|
|
182
|
+
|
|
183
|
+
## Env files
|
|
184
|
+
|
|
185
|
+
`brass-agent --doctor` auto-loads supported agent keys from `.brass-agent.env`, `.env.local`, and `.env` in the workspace. Use `--env-file PATH` to choose a file or `--no-env-file` to disable this behavior. See [Agent env files](./agent-env-files.md).
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
## VS Code auto-discovery
|
|
189
|
+
|
|
190
|
+
The VS Code extension can now use `brassAgent.command = "auto"` and prefer its bundled CLI, so you can open any repo and use Brass Agent without linking the CLI globally. See [VS Code auto-discovery](./agent-vscode-auto-discovery.md).
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Brass Agent local tests
|
|
2
|
+
|
|
3
|
+
P36 adds local smoke-test scripts for dogfooding without CI.
|
|
4
|
+
|
|
5
|
+
These tests are intentionally local-first. They do not publish artifacts, do not require a real LLM provider, and do not need GitHub Actions.
|
|
6
|
+
|
|
7
|
+
## Smoke test
|
|
8
|
+
|
|
9
|
+
Build first, then run:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm run agent:test:smoke
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Or run the full local flow:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm run agent:test:local
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`agent:test:local` runs:
|
|
22
|
+
|
|
23
|
+
```txt
|
|
24
|
+
npm run build
|
|
25
|
+
node scripts/agent-local-smoke.mjs
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## What the smoke test validates
|
|
29
|
+
|
|
30
|
+
The smoke test creates a temporary project and checks:
|
|
31
|
+
|
|
32
|
+
```txt
|
|
33
|
+
- the built CLI exists
|
|
34
|
+
- read-only inspect can finish with fake LLM
|
|
35
|
+
- apply mode can use fake LLM diff output
|
|
36
|
+
- patch preview/apply plumbing can update a file through the CLI
|
|
37
|
+
- validation can pass after the patch
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
It uses:
|
|
41
|
+
|
|
42
|
+
```txt
|
|
43
|
+
BRASS_LLM_PROVIDER=fake
|
|
44
|
+
BRASS_FAKE_LLM_RESPONSE=<controlled unified diff>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
No real API key is required.
|
|
48
|
+
|
|
49
|
+
## Why no CI yet
|
|
50
|
+
|
|
51
|
+
This is a local stabilization step only. CI and release automation remain intentionally deferred until the agent UX has been dogfooded more heavily.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Brass Agent observability
|
|
2
|
+
|
|
3
|
+
`brass-agent` emits a typed event stream while the agent loop runs.
|
|
4
|
+
|
|
5
|
+
The event stream is intentionally modeled as a capability of the agent environment:
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
type AgentEnv = {
|
|
9
|
+
fs: FileSystem;
|
|
10
|
+
shell: Shell;
|
|
11
|
+
llm: LLM;
|
|
12
|
+
patch: PatchService;
|
|
13
|
+
permissions: PermissionService;
|
|
14
|
+
approvals?: ApprovalService;
|
|
15
|
+
events?: AgentEventSink;
|
|
16
|
+
};
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The core runtime does not know about the agent. The agent depends on the runtime and exposes its own higher-level observability events.
|
|
20
|
+
|
|
21
|
+
## Invariant
|
|
22
|
+
|
|
23
|
+
Observability must never change agent semantics.
|
|
24
|
+
|
|
25
|
+
If an event sink throws, the agent ignores the sink failure and continues. Event sinks are best-effort and should not be used for control flow.
|
|
26
|
+
|
|
27
|
+
## Event lifecycle
|
|
28
|
+
|
|
29
|
+
A normal run emits events in this order:
|
|
30
|
+
|
|
31
|
+
```txt
|
|
32
|
+
agent.run.started
|
|
33
|
+
agent.action.started
|
|
34
|
+
agent.action.completed
|
|
35
|
+
agent.observation.recorded
|
|
36
|
+
...
|
|
37
|
+
agent.run.completed
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
If a tool fails, the action emits:
|
|
41
|
+
|
|
42
|
+
```txt
|
|
43
|
+
agent.action.started
|
|
44
|
+
agent.action.failed
|
|
45
|
+
agent.observation.recorded
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Some important failures also emit specialized events:
|
|
49
|
+
|
|
50
|
+
```txt
|
|
51
|
+
agent.tool.timeout
|
|
52
|
+
agent.permission.denied
|
|
53
|
+
agent.approval.requested
|
|
54
|
+
agent.approval.resolved
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Approval events are emitted around `ApprovalService.request(...)`. They report
|
|
58
|
+
that an action asked for human or policy approval and whether that approval was
|
|
59
|
+
granted or rejected.
|
|
60
|
+
|
|
61
|
+
When a patch is applied, the stream also emits:
|
|
62
|
+
|
|
63
|
+
```txt
|
|
64
|
+
agent.patch.applied
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## CLI output
|
|
68
|
+
|
|
69
|
+
Human output now uses the live event stream by default:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
brass-agent "fix the failing tests"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Example shape:
|
|
76
|
+
|
|
77
|
+
```txt
|
|
78
|
+
brass-agent propose
|
|
79
|
+
workspace: /repo
|
|
80
|
+
goal: fix the failing tests
|
|
81
|
+
|
|
82
|
+
→ read package.json
|
|
83
|
+
✓ read package.json 3ms
|
|
84
|
+
→ check pnpm-lock.yaml
|
|
85
|
+
✓ found pnpm-lock.yaml 2ms
|
|
86
|
+
→ pnpm test
|
|
87
|
+
! pnpm test exited 1 1234ms
|
|
88
|
+
→ llm.plan
|
|
89
|
+
✓ llm.plan responded 2400ms
|
|
90
|
+
→ propose patch
|
|
91
|
+
✓ patch proposed 1ms
|
|
92
|
+
→ finish
|
|
93
|
+
✓ done 1ms
|
|
94
|
+
|
|
95
|
+
phase: done
|
|
96
|
+
steps: 5
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The old full-state debug output is still available:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
brass-agent --json "fix the failing tests"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
For quick machine-readable streaming, use event-only JSON Lines:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
brass-agent --events-json "fix the failing tests"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
This prints one compact `AgentEvent` per line.
|
|
112
|
+
|
|
113
|
+
For editor integrations and other clients, prefer the protocol stream:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
brass-agent --protocol-json "fix the failing tests"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
This prints newline-delimited messages with `protocol: "brass-agent"`, `version: 1`, event messages, and a final-state message. See [Agent DX surfaces](./agent-dx.md).
|
|
120
|
+
|
|
121
|
+
## Programmatic usage
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import {
|
|
125
|
+
runAgent,
|
|
126
|
+
type AgentEnv,
|
|
127
|
+
type AgentEventSink,
|
|
128
|
+
} from "brass-runtime/agent";
|
|
129
|
+
|
|
130
|
+
const events: AgentEventSink = {
|
|
131
|
+
emit(event) {
|
|
132
|
+
console.log(event.type, event);
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const env: AgentEnv = {
|
|
137
|
+
fs,
|
|
138
|
+
shell,
|
|
139
|
+
patch,
|
|
140
|
+
llm,
|
|
141
|
+
permissions,
|
|
142
|
+
approvals,
|
|
143
|
+
events,
|
|
144
|
+
};
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Privacy and output size
|
|
148
|
+
|
|
149
|
+
The CLI compacts large payloads in `--events-json` mode, including file contents, LLM prompts, LLM responses, shell output, and patches.
|
|
150
|
+
|
|
151
|
+
Programmatic event sinks receive the typed event values directly. If you forward them to logs, apply your own redaction policy.
|
|
152
|
+
|
|
153
|
+
## Boundary rule
|
|
154
|
+
|
|
155
|
+
`src/core` must not import agent events. Agent observability lives in `src/agent` and is built on top of runtime semantics.
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Agent patch quality loop
|
|
2
|
+
|
|
3
|
+
P13 adds a bounded repair loop for generated patches.
|
|
4
|
+
|
|
5
|
+
The previous apply flow was one-shot:
|
|
6
|
+
|
|
7
|
+
```txt
|
|
8
|
+
llm.plan
|
|
9
|
+
-> patch.apply
|
|
10
|
+
-> validation commands
|
|
11
|
+
-> finish
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The new flow can perform one or more repair attempts when the generated patch
|
|
15
|
+
fails to apply or when validation still fails after apply:
|
|
16
|
+
|
|
17
|
+
```txt
|
|
18
|
+
llm.plan
|
|
19
|
+
-> patch.apply
|
|
20
|
+
-> validation commands
|
|
21
|
+
-> if validation fails: llm.patch
|
|
22
|
+
-> patch.apply
|
|
23
|
+
-> validation commands
|
|
24
|
+
-> finish
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The loop is intentionally small and bounded. It is a quality pass, not an
|
|
28
|
+
unbounded autonomous edit loop.
|
|
29
|
+
|
|
30
|
+
## Exact patch safety
|
|
31
|
+
|
|
32
|
+
Runs started with an explicit patch file stay exact:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
brass-agent --apply-patch-file ./approved.diff --yes "apply approved patch"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
For these runs, repair is disabled. That preserves the VS Code patch preview
|
|
39
|
+
invariant:
|
|
40
|
+
|
|
41
|
+
```txt
|
|
42
|
+
preview patch A
|
|
43
|
+
-> approve patch A
|
|
44
|
+
-> apply exactly patch A
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The agent must not silently generate and apply patch B after the user approved
|
|
48
|
+
patch A. To allow the agent to repair its own generated patches, use normal
|
|
49
|
+
write mode instead:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
brass-agent --apply "fix the failing tests"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Configuration
|
|
56
|
+
|
|
57
|
+
Configure the loop in `.brass-agent.json`:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"patchQuality": {
|
|
62
|
+
"enabled": true,
|
|
63
|
+
"maxRepairAttempts": 1
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Defaults:
|
|
69
|
+
|
|
70
|
+
```txt
|
|
71
|
+
enabled: true
|
|
72
|
+
maxRepairAttempts: 1
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Disable repairs entirely:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"patchQuality": {
|
|
80
|
+
"enabled": false
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Allow two repair calls after the initial generated patch:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"patchQuality": {
|
|
90
|
+
"maxRepairAttempts": 2
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
A value of `0` means “apply once, validate once, do not ask for repairs.”
|
|
96
|
+
|
|
97
|
+
## What counts as a repair attempt?
|
|
98
|
+
|
|
99
|
+
Only LLM calls with purpose `patch` count as repair attempts.
|
|
100
|
+
|
|
101
|
+
The initial planning call is still `llm.plan`:
|
|
102
|
+
|
|
103
|
+
```txt
|
|
104
|
+
llm.plan # initial diagnosis / patch proposal
|
|
105
|
+
llm.patch # repair attempt 1
|
|
106
|
+
llm.patch # repair attempt 2, if configured
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## What triggers a repair?
|
|
110
|
+
|
|
111
|
+
A repair can be requested when all of these are true:
|
|
112
|
+
|
|
113
|
+
1. the agent is in `write` or `autonomous` mode
|
|
114
|
+
2. the patch came from the agent, not from `--apply-patch-file`
|
|
115
|
+
3. `patchQuality.enabled` is not `false`
|
|
116
|
+
4. remaining repair budget is greater than zero
|
|
117
|
+
5. either:
|
|
118
|
+
- `patch.apply` failed, or
|
|
119
|
+
- validation commands ran after `patch.applied` and at least one failed
|
|
120
|
+
|
|
121
|
+
Permission denials, approval rejections, and non-patch tool failures do not
|
|
122
|
+
trigger patch repair.
|
|
123
|
+
|
|
124
|
+
## Boundaries
|
|
125
|
+
|
|
126
|
+
The repair loop does not change the core runtime boundary:
|
|
127
|
+
|
|
128
|
+
```txt
|
|
129
|
+
src/core
|
|
130
|
+
↑
|
|
131
|
+
src/agent decides llm.patch / patch.apply
|
|
132
|
+
↑
|
|
133
|
+
src/agent/cli configures patchQuality
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Repair is just more agent logic expressed as normal actions:
|
|
137
|
+
|
|
138
|
+
```txt
|
|
139
|
+
AgentAction(llm.complete purpose=patch)
|
|
140
|
+
-> LLM capability
|
|
141
|
+
-> Observation(llm.response purpose=patch)
|
|
142
|
+
-> AgentAction(patch.apply)
|
|
143
|
+
-> PermissionService / ApprovalService
|
|
144
|
+
-> PatchService
|
|
145
|
+
-> validation commands
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
No side effects are executed outside the `Async` tool pipeline.
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
## Relationship with rollback safety
|
|
152
|
+
|
|
153
|
+
P14 runs after the patch quality loop. If validation still fails and no repair
|
|
154
|
+
attempts remain, rollback safety can reverse generated patches through
|
|
155
|
+
`patch.rollback`. This keeps repair and restore as separate decisions:
|
|
156
|
+
|
|
157
|
+
```txt
|
|
158
|
+
repair budget remains -> llm.patch
|
|
159
|
+
repair budget exhausted -> optional patch.rollback
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
See [Agent automatic rollback safety](./agent-rollback-safety.md).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Brass Agent presets
|
|
2
|
+
|
|
3
|
+
P20 adds built-in DX presets for common developer workflows.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
brass-agent --preset fix-tests
|
|
7
|
+
brass-agent --preset inspect
|
|
8
|
+
brass-agent --preset typecheck
|
|
9
|
+
brass-agent --preset lint
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
A preset only supplies a default goal and, for `inspect`, defaults to `read-only` when no `--mode` was explicitly provided. Explicit goal text and flags still win.
|
|
13
|
+
|
|
14
|
+
VS Code also exposes preset commands:
|
|
15
|
+
|
|
16
|
+
```txt
|
|
17
|
+
Brass Agent: Fix Tests
|
|
18
|
+
Brass Agent: Typecheck
|
|
19
|
+
Brass Agent: Lint
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The VS Code commands still use the preview-first flow: generate patch proposal, show Webview, then apply the exact reviewed patch through `brass-agent`.
|