bare-agent 0.42.0 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/bareagent.context.md +1 -1
  2. package/package.json +8 -3
  3. package/primitives.json +447 -0
  4. package/src/bareguard-adapter.d.ts +6 -0
  5. package/src/bareguard-adapter.js +6 -0
  6. package/src/checkpoint.d.ts +5 -0
  7. package/src/checkpoint.js +5 -0
  8. package/src/circuit-breaker.d.ts +5 -0
  9. package/src/circuit-breaker.js +5 -0
  10. package/src/complexity.d.ts +9 -0
  11. package/src/complexity.js +9 -0
  12. package/src/context-units.d.ts +12 -0
  13. package/src/context-units.js +12 -0
  14. package/src/evaluator.d.ts +9 -1
  15. package/src/evaluator.js +9 -1
  16. package/src/judge-calibration.d.ts +5 -0
  17. package/src/judge-calibration.js +5 -0
  18. package/src/judge.d.ts +5 -0
  19. package/src/judge.js +5 -0
  20. package/src/loop.d.ts +16 -2
  21. package/src/loop.js +29 -12
  22. package/src/mcp-bridge.d.ts +13 -0
  23. package/src/mcp-bridge.js +13 -0
  24. package/src/memory.d.ts +5 -0
  25. package/src/memory.js +5 -0
  26. package/src/planner.d.ts +6 -0
  27. package/src/planner.js +6 -0
  28. package/src/provider-anthropic.d.ts +4 -0
  29. package/src/provider-anthropic.js +4 -0
  30. package/src/provider-clipipe.d.ts +4 -0
  31. package/src/provider-clipipe.js +4 -0
  32. package/src/provider-fallback.d.ts +4 -0
  33. package/src/provider-fallback.js +4 -0
  34. package/src/provider-gemini.d.ts +7 -1
  35. package/src/provider-gemini.js +7 -1
  36. package/src/provider-ollama.d.ts +4 -0
  37. package/src/provider-ollama.js +11 -2
  38. package/src/provider-openai.d.ts +4 -0
  39. package/src/provider-openai.js +31 -3
  40. package/src/provider-toolcalls.d.ts +29 -0
  41. package/src/provider-toolcalls.js +45 -0
  42. package/src/recurse-retrieval.d.ts +22 -0
  43. package/src/recurse-retrieval.js +22 -0
  44. package/src/recurse.d.ts +6 -0
  45. package/src/recurse.js +6 -0
  46. package/src/refine.d.ts +5 -0
  47. package/src/refine.js +5 -0
  48. package/src/remember.d.ts +5 -0
  49. package/src/remember.js +5 -0
  50. package/src/retry.d.ts +8 -1
  51. package/src/retry.js +8 -1
  52. package/src/run-plan.d.ts +5 -0
  53. package/src/run-plan.js +5 -0
  54. package/src/scheduler.d.ts +8 -1
  55. package/src/scheduler.js +8 -1
  56. package/src/skills.d.ts +6 -0
  57. package/src/skills.js +6 -0
  58. package/src/stash.d.ts +5 -0
  59. package/src/stash.js +5 -0
  60. package/src/state.d.ts +8 -1
  61. package/src/state.js +8 -1
  62. package/src/store-jsonfile.d.ts +5 -0
  63. package/src/store-jsonfile.js +5 -0
  64. package/src/store-sqlite.d.ts +5 -0
  65. package/src/store-sqlite.js +5 -0
  66. package/src/stream.d.ts +5 -0
  67. package/src/stream.js +5 -0
  68. package/src/transport-jsonl.d.ts +4 -0
  69. package/src/transport-jsonl.js +4 -0
  70. package/tools/browse.d.ts +5 -0
  71. package/tools/browse.js +5 -0
  72. package/tools/defer.d.ts +13 -1
  73. package/tools/defer.js +13 -1
  74. package/tools/litectx-mcp.d.ts +6 -0
  75. package/tools/litectx-mcp.js +6 -0
  76. package/tools/mobile.d.ts +5 -0
  77. package/tools/mobile.js +5 -0
  78. package/tools/shell.d.ts +5 -0
  79. package/tools/shell.js +5 -0
  80. package/tools/spawn.d.ts +10 -0
  81. package/tools/spawn.js +10 -0
  82. package/types/index.d.ts +10 -0
package/src/stream.js CHANGED
@@ -36,6 +36,11 @@
36
36
  class Stream {
37
37
  /**
38
38
  * @param {StreamOptions} [options={}]
39
+ * @when you want a structured event emitter for loop/tool/governance events, optionally piped to a transport sink
40
+ * @fails never throws on emit; a transport write error is isolated and does not interrupt the run.
41
+ * @example
42
+ * const stream = new Stream({ transport });
43
+ * stream.emit('loop:round', { n: 1 });
39
44
  */
40
45
  constructor(options = {}) {
41
46
  /** @type {Transport|null} */
@@ -17,6 +17,10 @@ export type JsonlTransportOptions = {
17
17
  export class JsonlTransport {
18
18
  /**
19
19
  * @param {JsonlTransportOptions} [options={}]
20
+ * @when you want to pipe structured Stream events as JSONL to a writable stream — pipe-friendly observability
21
+ * @fails never throws on write; defaults to process.stdout when no output stream is given.
22
+ * @example
23
+ * const stream = new Stream({ transport: new JsonlTransport() });
20
24
  */
21
25
  constructor(options?: JsonlTransportOptions);
22
26
  _output: NodeJS.WritableStream | (NodeJS.WriteStream & {
@@ -15,6 +15,10 @@
15
15
  class JsonlTransport {
16
16
  /**
17
17
  * @param {JsonlTransportOptions} [options={}]
18
+ * @when you want to pipe structured Stream events as JSONL to a writable stream — pipe-friendly observability
19
+ * @fails never throws on write; defaults to process.stdout when no output stream is given.
20
+ * @example
21
+ * const stream = new Stream({ transport: new JsonlTransport() });
18
22
  */
19
23
  constructor(options = {}) {
20
24
  this._output = options.output || process.stdout;
package/tools/browse.d.ts CHANGED
@@ -3,6 +3,11 @@
3
3
  * Returns { tools, close } or null if barebrowse is not installed.
4
4
  * @param {object} [opts] - Options passed to barebrowse createBrowseTools
5
5
  * @returns {Promise<{tools: Array, close: Function}|null>}
6
+ * @when you want to give an agent browser tools (navigate, click, read) via barebrowse for inline snapshots
7
+ * @fails returns null if barebrowse (optional dep) is not installed; otherwise returns {tools, close} — call close() to release the browser.
8
+ * @example
9
+ * const b = await createBrowsingTools();
10
+ * const loop = new Loop({ provider, tools: b.tools });
6
11
  */
7
12
  export function createBrowsingTools(opts?: object): Promise<{
8
13
  tools: any[];
package/tools/browse.js CHANGED
@@ -5,6 +5,11 @@
5
5
  * Returns { tools, close } or null if barebrowse is not installed.
6
6
  * @param {object} [opts] - Options passed to barebrowse createBrowseTools
7
7
  * @returns {Promise<{tools: Array, close: Function}|null>}
8
+ * @when you want to give an agent browser tools (navigate, click, read) via barebrowse for inline snapshots
9
+ * @fails returns null if barebrowse (optional dep) is not installed; otherwise returns {tools, close} — call close() to release the browser.
10
+ * @example
11
+ * const b = await createBrowsingTools();
12
+ * const loop = new Loop({ provider, tools: b.tools });
8
13
  */
9
14
  async function createBrowsingTools(opts = {}) {
10
15
  try {
package/tools/defer.d.ts CHANGED
@@ -2,6 +2,11 @@
2
2
  * @param {object} [options]
3
3
  * @param {string} [options.queuePath] - Override queue file path.
4
4
  * @returns {{tool: import('../types').ToolDef, readQueue: () => Promise<Record<string, any>[]>, queuePath: string}}
5
+ * @when you want a tool that queues an action to a JSONL file for an external waker (cron) to fire later — two-phase governance (emit-time + fire-time)
6
+ * @fails returns {tool, readQueue, queuePath}; the inner action is re-gated at fire time when the waker runs. bareguard caps via defer.ratePerMinute.
7
+ * @example
8
+ * const { tool } = createDeferTool();
9
+ * const loop = new Loop({ provider, tools: [tool] });
5
10
  */
6
11
  export function createDeferTool(options?: {
7
12
  queuePath?: string | undefined;
@@ -15,7 +20,14 @@ export function createDeferTool(options?: {
15
20
  * append-only status lines (latest wins). Exposed for tests + library
16
21
  * users; the wake script does its own jq-based fold.
17
22
  */
18
- /** @param {string} [queuePath] */
23
+ /**
24
+ * @param {string} [queuePath]
25
+ * @name readDeferQueue
26
+ * @when you want to read the deferred-action queue and reconstruct each id's live status (an external waker or a status check)
27
+ * @fails never throws on a missing/empty queue; folds append-only status lines (latest wins) and returns the reconstructed records.
28
+ * @example
29
+ * const queue = await readDeferQueue();
30
+ */
19
31
  export function readQueue(queuePath?: string): Promise<Record<string, any>[]>;
20
32
  /**
21
33
  * Generate a sortable, unique id. 9-char base36 timestamp + 20-char hex
package/tools/defer.js CHANGED
@@ -128,7 +128,14 @@ async function appendRecord(queuePath, record) {
128
128
  * append-only status lines (latest wins). Exposed for tests + library
129
129
  * users; the wake script does its own jq-based fold.
130
130
  */
131
- /** @param {string} [queuePath] */
131
+ /**
132
+ * @param {string} [queuePath]
133
+ * @name readDeferQueue
134
+ * @when you want to read the deferred-action queue and reconstruct each id's live status (an external waker or a status check)
135
+ * @fails never throws on a missing/empty queue; folds append-only status lines (latest wins) and returns the reconstructed records.
136
+ * @example
137
+ * const queue = await readDeferQueue();
138
+ */
132
139
  async function readQueue(queuePath) {
133
140
  const path = resolveQueuePath(queuePath);
134
141
  try {
@@ -156,6 +163,11 @@ async function readQueue(queuePath) {
156
163
  * @param {object} [options]
157
164
  * @param {string} [options.queuePath] - Override queue file path.
158
165
  * @returns {{tool: import('../types').ToolDef, readQueue: () => Promise<Record<string, any>[]>, queuePath: string}}
166
+ * @when you want a tool that queues an action to a JSONL file for an external waker (cron) to fire later — two-phase governance (emit-time + fire-time)
167
+ * @fails returns {tool, readQueue, queuePath}; the inner action is re-gated at fire time when the waker runs. bareguard caps via defer.ratePerMinute.
168
+ * @example
169
+ * const { tool } = createDeferTool();
170
+ * const loop = new Loop({ provider, tools: [tool] });
159
171
  */
160
172
  function createDeferTool(options = {}) {
161
173
  const queuePath = resolveQueuePath(options.queuePath);
@@ -10,6 +10,12 @@
10
10
  * @param {string} [opts.now] - ISO timestamp for `discovered` (default: now). Pre-seed fresh so
11
11
  * `createMCPBridge` skips IDE discovery and connects straight to this curated server.
12
12
  * @returns {import('../src/mcp-bridge').BridgeConfig}
13
+ * @category integration
14
+ * @when you want to connect a litectx instance to a bareagent runner over the MCP bridge — a curated, child-db-local litectx server
15
+ * @fails read-only by default (opt-in `writable` allows remember/forget); pre-seeding `now` makes createMCPBridge skip IDE discovery and connect straight to this server.
16
+ * @example
17
+ * const cfg = liteCtxMcpBridgeConfig({ root: './child.db' });
18
+ * const { tools } = await createMCPBridge({ config: cfg });
13
19
  */
14
20
  export function liteCtxMcpBridgeConfig(opts: {
15
21
  root: string;
@@ -36,6 +36,12 @@ const ADMIN_VERBS = ['index', 'promotions'];
36
36
  * @param {string} [opts.now] - ISO timestamp for `discovered` (default: now). Pre-seed fresh so
37
37
  * `createMCPBridge` skips IDE discovery and connects straight to this curated server.
38
38
  * @returns {import('../src/mcp-bridge').BridgeConfig}
39
+ * @category integration
40
+ * @when you want to connect a litectx instance to a bareagent runner over the MCP bridge — a curated, child-db-local litectx server
41
+ * @fails read-only by default (opt-in `writable` allows remember/forget); pre-seeding `now` makes createMCPBridge skip IDE discovery and connect straight to this server.
42
+ * @example
43
+ * const cfg = liteCtxMcpBridgeConfig({ root: './child.db' });
44
+ * const { tools } = await createMCPBridge({ config: cfg });
39
45
  */
40
46
  function liteCtxMcpBridgeConfig(opts) {
41
47
  if (!opts || typeof opts.root !== 'string' || !opts.root) {
package/tools/mobile.d.ts CHANGED
@@ -23,6 +23,11 @@ export type MobilePage = any;
23
23
  * @param {string} [opts.device] - Device serial or 'auto'
24
24
  * @param {boolean} [opts.termux] - Use Termux ADB on-device mode
25
25
  * @returns {Promise<{tools: ToolDef[], close: Function}|null>}
26
+ * @when you want to give an agent Android/iOS device control (tap, type, snapshot) via baremobile
27
+ * @fails returns null if baremobile (optional dep) is not installed; otherwise returns {tools, close} — call close() to disconnect.
28
+ * @example
29
+ * const m = await createMobileTools({ platform: 'android' });
30
+ * const loop = new Loop({ provider, tools: m.tools });
26
31
  */
27
32
  export function createMobileTools(opts?: {
28
33
  platform?: string | undefined;
package/tools/mobile.js CHANGED
@@ -21,6 +21,11 @@
21
21
  * @param {string} [opts.device] - Device serial or 'auto'
22
22
  * @param {boolean} [opts.termux] - Use Termux ADB on-device mode
23
23
  * @returns {Promise<{tools: ToolDef[], close: Function}|null>}
24
+ * @when you want to give an agent Android/iOS device control (tap, type, snapshot) via baremobile
25
+ * @fails returns null if baremobile (optional dep) is not installed; otherwise returns {tools, close} — call close() to disconnect.
26
+ * @example
27
+ * const m = await createMobileTools({ platform: 'android' });
28
+ * const loop = new Loop({ provider, tools: m.tools });
24
29
  */
25
30
  async function createMobileTools(opts = {}) {
26
31
  const platform = opts.platform || 'android';
package/tools/shell.d.ts CHANGED
@@ -41,6 +41,11 @@ type ToolDef = import("../types").ToolDef;
41
41
  * gating is the caller's responsibility via `new Loop({ policy })`.
42
42
  *
43
43
  * @returns {{tools: ToolDef[]}}
44
+ * @when you want to give an agent shell/file tools (read, grep, write, edit, run, exec) — cross-platform, pure Node, zero deps
45
+ * @fails never throws at creation; gating is the caller's via Loop({ policy }) and fs.writeScope, and shell_edit refuses a non-unique anchor as a tool result (file untouched).
46
+ * @example
47
+ * const { tools } = createShellTools();
48
+ * const loop = new Loop({ provider, tools, policy });
44
49
  */
45
50
  declare function createShellTools(): {
46
51
  tools: ToolDef[];
package/tools/shell.js CHANGED
@@ -499,6 +499,11 @@ function execCommand({ command, cwd, timeout, maxBuffer, env }) {
499
499
  * gating is the caller's responsibility via `new Loop({ policy })`.
500
500
  *
501
501
  * @returns {{tools: ToolDef[]}}
502
+ * @when you want to give an agent shell/file tools (read, grep, write, edit, run, exec) — cross-platform, pure Node, zero deps
503
+ * @fails never throws at creation; gating is the caller's via Loop({ policy }) and fs.writeScope, and shell_edit refuses a non-unique anchor as a tool result (file untouched).
504
+ * @example
505
+ * const { tools } = createShellTools();
506
+ * const loop = new Loop({ provider, tools, policy });
502
507
  */
503
508
  function createShellTools() {
504
509
  /** @type {ToolDef[]} */
package/tools/spawn.d.ts CHANGED
@@ -68,6 +68,11 @@ export type Stream = import("../src/stream").Stream;
68
68
  * (heartbeat watchdog; default off). Resets on every line, so slow-but-working children survive.
69
69
  * @param {Stream} [options.stream] - bareagent Stream instance — child:stderr events get re-emitted here.
70
70
  * @returns {{tool: import('../types').ToolDef, spawnChild: typeof spawnChild}}
71
+ * @when you want an LLM-callable spawn tool so a model can fork child bareagents itself — governed per-family by bareguard
72
+ * @fails returns {tool, spawnChild}; the tool blocks per child and child stderr is re-emitted as child:stderr on the wired Stream.
73
+ * @example
74
+ * const { tool } = createSpawnTool();
75
+ * const loop = new Loop({ provider, tools: [tool] });
71
76
  */
72
77
  export function createSpawnTool(options?: {
73
78
  cliPath?: string | undefined;
@@ -104,6 +109,11 @@ export function createSpawnTool(options?: {
104
109
  * @property {Stream} [stream] - bareagent Stream — child:stderr events get re-emitted here.
105
110
  *
106
111
  * @param {SpawnChildOptions} [opts]
112
+ * @when you want to fork a child bareagent process programmatically and get a handle — heavyweight delegation, not the in-process recurse default
113
+ * @fails bounded by timeoutMs (wall-clock) and opt-in idleTimeoutMs (heartbeat); the result carries idleKilled if the watchdog fired. Threads BAREGUARD env vars to the child.
114
+ * @example
115
+ * const handle = spawnChild({ config, input });
116
+ * const result = await handle.wait();
107
117
  */
108
118
  export function spawnChild({ config, input, cliPath, timeoutMs, idleTimeoutMs, stream }?: SpawnChildOptions): {
109
119
  wait: () => Promise<{
package/tools/spawn.js CHANGED
@@ -74,6 +74,11 @@ function resolveCliPath() {
74
74
  * @property {Stream} [stream] - bareagent Stream — child:stderr events get re-emitted here.
75
75
  *
76
76
  * @param {SpawnChildOptions} [opts]
77
+ * @when you want to fork a child bareagent process programmatically and get a handle — heavyweight delegation, not the in-process recurse default
78
+ * @fails bounded by timeoutMs (wall-clock) and opt-in idleTimeoutMs (heartbeat); the result carries idleKilled if the watchdog fired. Threads BAREGUARD env vars to the child.
79
+ * @example
80
+ * const handle = spawnChild({ config, input });
81
+ * const result = await handle.wait();
77
82
  */
78
83
  function spawnChild({ config, input, cliPath, timeoutMs, idleTimeoutMs, stream } = {}) {
79
84
  if (typeof config !== 'string' || !config) {
@@ -257,6 +262,11 @@ function spawnChild({ config, input, cliPath, timeoutMs, idleTimeoutMs, stream }
257
262
  * (heartbeat watchdog; default off). Resets on every line, so slow-but-working children survive.
258
263
  * @param {Stream} [options.stream] - bareagent Stream instance — child:stderr events get re-emitted here.
259
264
  * @returns {{tool: import('../types').ToolDef, spawnChild: typeof spawnChild}}
265
+ * @when you want an LLM-callable spawn tool so a model can fork child bareagents itself — governed per-family by bareguard
266
+ * @fails returns {tool, spawnChild}; the tool blocks per child and child stderr is re-emitted as child:stderr on the wired Stream.
267
+ * @example
268
+ * const { tool } = createSpawnTool();
269
+ * const loop = new Loop({ provider, tools: [tool] });
260
270
  */
261
271
  function createSpawnTool(options = {}) {
262
272
  const tool = {
package/types/index.d.ts CHANGED
@@ -134,6 +134,16 @@ export interface GenerateResult {
134
134
  * temperature, not the one requested — callers reporting an effective temperature must honor this.
135
135
  */
136
136
  temperatureDropped?: boolean;
137
+ /**
138
+ * BA-27 — present ONLY when the model emitted a tool call whose `function.arguments` was
139
+ * syntactically-broken JSON (an extra brace, a truncated object). The billed round already
140
+ * succeeded, so rather than throw (which loses the round's usage and hangs metering), the provider
141
+ * returns NO usable tool calls (`toolCalls: []`) plus this marker. A caller treats it as "no usable
142
+ * tool call" and retries; `usage`/`model` still flow so the round is metered. The JSON is NEVER
143
+ * repaired. Absent on a clean round. OpenAI-compatible + Ollama string-arguments only; Anthropic
144
+ * arrives pre-parsed and cannot hit this.
145
+ */
146
+ malformedToolCall?: { name: string | undefined; error: string };
137
147
  /**
138
148
  * BA-7 — provider-native content blocks the normalized `{text, toolCalls}` shape cannot express
139
149
  * (Anthropic `thinking` / `redacted_thinking`), captured opaquely so the Loop can put them on the