bare-agent 0.26.0 → 0.26.2
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/bareagent.context.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# bareagent — Integration Guide
|
|
2
2
|
|
|
3
3
|
> For AI assistants and developers wiring bareagent into a project.
|
|
4
|
-
> v0.26.
|
|
4
|
+
> v0.26.2 | Node.js >= 18 | zero required deps (`bareguard >=0.9.0 <0.13.0` optional peer for governance) | Apache 2.0
|
|
5
5
|
>
|
|
6
6
|
> Full human guide with composition examples, design philosophy, and recipes: [Usage Guide](docs/02-features/usage-guide.md)
|
|
7
7
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bare-agent",
|
|
3
|
-
"version": "0.26.
|
|
3
|
+
"version": "0.26.2",
|
|
4
4
|
"files": [
|
|
5
5
|
"index.js",
|
|
6
6
|
"index.d.ts",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"cron-parser": "^4.9.0"
|
|
81
81
|
},
|
|
82
82
|
"peerDependencies": {
|
|
83
|
-
"bareguard": "
|
|
83
|
+
"bareguard": ">=0.9.0 <0.13.0",
|
|
84
84
|
"better-sqlite3": ">=9.0.0"
|
|
85
85
|
},
|
|
86
86
|
"peerDependenciesMeta": {
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
},
|
|
102
102
|
"devDependencies": {
|
|
103
103
|
"@types/node": "^22.19.19",
|
|
104
|
-
"bareguard": "
|
|
104
|
+
"bareguard": ">=0.9.0 <0.13.0",
|
|
105
105
|
"litectx": "^0.26.0",
|
|
106
106
|
"typescript": "^5.7.0"
|
|
107
107
|
}
|
|
@@ -27,9 +27,9 @@ export type GateDecision = {
|
|
|
27
27
|
*/
|
|
28
28
|
rule?: string | undefined;
|
|
29
29
|
/**
|
|
30
|
-
* - Human-readable reason.
|
|
30
|
+
* - Human-readable reason (bareguard's Decision emits null when absent).
|
|
31
31
|
*/
|
|
32
|
-
reason?: string | undefined;
|
|
32
|
+
reason?: string | null | undefined;
|
|
33
33
|
/**
|
|
34
34
|
* - Arbitrary structured context.
|
|
35
35
|
*/
|
package/src/bareguard-adapter.js
CHANGED
|
@@ -21,7 +21,7 @@ const { HaltError } = require('./errors');
|
|
|
21
21
|
* @property {string} [outcome] - 'allow' when permitted.
|
|
22
22
|
* @property {string} [severity] - 'halt' for halt-severity denials.
|
|
23
23
|
* @property {string} [rule] - The matched rule name.
|
|
24
|
-
* @property {string} [reason] - Human-readable reason.
|
|
24
|
+
* @property {string | null} [reason] - Human-readable reason (bareguard's Decision emits null when absent).
|
|
25
25
|
* @property {Record<string, any>} [context] - Arbitrary structured context.
|
|
26
26
|
*/
|
|
27
27
|
|
package/src/provider-clipipe.js
CHANGED
|
@@ -165,39 +165,65 @@ class CLIPipeProvider {
|
|
|
165
165
|
|
|
166
166
|
let stdout = '';
|
|
167
167
|
let stderr = '';
|
|
168
|
-
let killed = false;
|
|
169
168
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
169
|
+
// Settle exactly once, no matter which combination of events fires. 'close' can be
|
|
170
|
+
// withheld indefinitely when the CLI spawns a grandchild that inherits its stdio pipes
|
|
171
|
+
// (the child exits, but the pipes stay open) — observed live as a generate() promise
|
|
172
|
+
// that never settled. Every path below funnels through settle().
|
|
173
|
+
let settled = false;
|
|
174
|
+
/** @type {NodeJS.Timeout[]} */
|
|
175
|
+
const timers = [];
|
|
176
|
+
const later = (fn, ms) => { timers.push(setTimeout(fn, ms)); };
|
|
177
|
+
const settle = (/** @type {Error|null} */ err, text = '') => {
|
|
178
|
+
if (settled) return;
|
|
179
|
+
settled = true;
|
|
180
|
+
for (const t of timers) clearTimeout(t);
|
|
181
|
+
if (err) reject(err); else resolve(text);
|
|
182
|
+
};
|
|
176
183
|
|
|
177
|
-
|
|
178
|
-
if (killed) return; // timeout already rejected
|
|
184
|
+
const finish = (/** @type {number|null} */ code) => {
|
|
179
185
|
if (code !== 0) {
|
|
180
|
-
|
|
186
|
+
// The claude CLI reports errors on STDOUT (a JSON envelope) with stderr often
|
|
187
|
+
// empty — fall back to a stdout tail so the operator never sees a blank reason.
|
|
188
|
+
const detail = stderr.trim() || (stdout.trim() ? `(stderr empty) stdout: ${stdout.trim().slice(-400)}` : '');
|
|
189
|
+
return settle(new ProviderError(`[CLIPipeProvider] process exited with code ${code}: ${detail}`, /** @type {any} */ ({ status: code })));
|
|
181
190
|
}
|
|
182
191
|
const text = stdout.trim();
|
|
183
192
|
if (!text) {
|
|
184
|
-
return
|
|
193
|
+
return settle(new ProviderError('[CLIPipeProvider] process produced no output', /** @type {any} */ ({ status: 0 })));
|
|
194
|
+
}
|
|
195
|
+
settle(null, text);
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
child.stdout.on('data', d => {
|
|
199
|
+
stdout += d;
|
|
200
|
+
try {
|
|
201
|
+
this.onChunk?.(d.toString());
|
|
202
|
+
} catch (err) {
|
|
203
|
+
// an observer callback must fail the call loudly, never crash the host process
|
|
204
|
+
settle(new ProviderError(`[CLIPipeProvider] onChunk callback threw: ${/** @type {Error} */ (err).message}`, /** @type {any} */ ({ status: 0 })));
|
|
185
205
|
}
|
|
186
|
-
|
|
206
|
+
});
|
|
207
|
+
child.stderr.on('data', d => { stderr += d; });
|
|
208
|
+
|
|
209
|
+
child.on('error', err => {
|
|
210
|
+
settle(new ProviderError(`[CLIPipeProvider] failed to spawn "${this.command}": ${err.message}`, /** @type {any} */ ({ status: 0 })));
|
|
187
211
|
});
|
|
188
212
|
|
|
189
|
-
//
|
|
190
|
-
|
|
191
|
-
|
|
213
|
+
// Primary completion path: all stdio drained.
|
|
214
|
+
child.on('close', code => finish(code));
|
|
215
|
+
|
|
216
|
+
// Fallback: the process exited but 'close' is being held open by inherited pipes.
|
|
217
|
+
// Give real drainage a short grace, then finish with what has arrived — a bounded
|
|
218
|
+
// wait, never a hang.
|
|
219
|
+
child.on('exit', code => later(() => finish(code), 2000));
|
|
220
|
+
|
|
221
|
+
later(() => {
|
|
192
222
|
child.kill('SIGTERM');
|
|
193
|
-
setTimeout(() => {
|
|
194
|
-
|
|
195
|
-
}, 1000);
|
|
196
|
-
reject(new ProviderError(`[CLIPipeProvider] timed out after ${this.timeout}ms`, /** @type {any} */ ({ status: 0 })));
|
|
223
|
+
setTimeout(() => { try { child.kill('SIGKILL'); } catch (_) {} }, 1000).unref?.();
|
|
224
|
+
settle(new ProviderError(`[CLIPipeProvider] timed out after ${this.timeout}ms`, /** @type {any} */ ({ status: 0 })));
|
|
197
225
|
}, this.timeout);
|
|
198
226
|
|
|
199
|
-
child.on('close', () => clearTimeout(timer));
|
|
200
|
-
|
|
201
227
|
// Write prompt to stdin — catch errors silently (process may exit early)
|
|
202
228
|
child.stdin.on('error', () => {});
|
|
203
229
|
child.stdin.end(prompt);
|