@owloops/browserbird 1.8.5 → 1.8.7

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
@@ -276,7 +276,10 @@ Store API keys and secrets in the web UI (Settings, Keys tab) and bind them to s
276
276
  - **Encrypted at rest** with AES-256-GCM. The encryption key is auto-generated on first start and stored in `.env` as `BROWSERBIRD_VAULT_KEY`.
277
277
  - **Redacted from output.** If the agent prints a vault key value, it appears as `[redacted]` in Slack and logs.
278
278
  - **Bound to targets.** A key bound to channel `*` applies to all channels. A key bound to a specific bird applies only when that bird runs. Bird-level keys override channel-level keys on name conflict.
279
- - **Name restrictions.** Dangerous env var names (`PATH`, `NODE_OPTIONS`, `LD_PRELOAD`, etc.) are blocked to prevent subprocess hijacking.
279
+
280
+ **Example: GitHub integration.** Store a GitHub personal access token as `GITHUB_TOKEN` in the vault and bind it to a channel or bird. The agent can then create issues, open PRs, push code, review changes, and manage repositories using the GitHub API or CLI.
281
+
282
+ **Example: authenticated browsing.** For birds that need to browse logged-in sites (X, LinkedIn, etc.), export cookies from your local browser using [Cookie-Editor](https://github.com/moustachauve/cookie-editor), store the JSON as a vault key (e.g. `X_COOKIES`), and bind it to the bird. In the bird's prompt, instruct it to read the cookies from the env var and inject them via `addCookies` before browsing. Pre-injecting cookies ensures the agent starts in a logged-in state, making scheduled tasks more reliable.
280
283
 
281
284
  ## CLI
282
285
 
package/dist/index.mjs CHANGED
@@ -193,8 +193,8 @@ function unknownSubcommand(subcommand, command, validCommands) {
193
193
  /** @fileoverview ASCII banner displayed on daemon startup and in help text. */
194
194
  const pkg = createRequire(import.meta.url)("../package.json");
195
195
  const buildInfo = [];
196
- buildInfo.push(`commit: ${"258f644d7838a281ab32e4095dd9a9fc43e603d4".substring(0, 7)}`);
197
- buildInfo.push(`built: 2026-03-22T17:47:18+04:00`);
196
+ buildInfo.push(`commit: ${"637d56da365a934b93c6e1a80c98ef7bc60967bb".substring(0, 7)}`);
197
+ buildInfo.push(`built: 2026-03-22T22:44:02+04:00`);
198
198
  const buildString = buildInfo.length > 0 ? ` (${buildInfo.join(", ")})` : "";
199
199
  const VERSION = `browserbird ${pkg.version}${buildString}`;
200
200
  const BIRD = [
@@ -4498,14 +4498,18 @@ function createHandler(client, getConfig, signal, getTeamId, getChannelNameToId)
4498
4498
  const msg = err instanceof Error ? err.message : String(err);
4499
4499
  return msg.includes("not_in_streaming_state") || msg.includes("streaming") || msg.includes("msg_too_long");
4500
4500
  }
4501
+ let streamToolCount = 0;
4501
4502
  async function resetStream() {
4502
4503
  try {
4503
4504
  await streamer.stop();
4504
4505
  } catch {}
4505
4506
  streamer = client.startStream(streamOpts);
4506
4507
  streamedChars = 0;
4508
+ streamToolCount = 0;
4509
+ needsPlanHeader = true;
4507
4510
  logger.debug("stream reset: started new streaming message");
4508
4511
  }
4512
+ let needsPlanHeader = true;
4509
4513
  async function safeAppend(content) {
4510
4514
  if (streamDead) {
4511
4515
  if (content.markdown_text) await client.postMessage(channelId, threadTs, content.markdown_text).catch(() => {});
@@ -4566,13 +4570,17 @@ function createHandler(client, getConfig, signal, getTeamId, getChannelNameToId)
4566
4570
  client.setStatus?.(channelId, threadTs, lastStatus).catch(() => {});
4567
4571
  if (event.toolCallId !== void 0) {
4568
4572
  toolCount++;
4573
+ streamToolCount++;
4569
4574
  activeTasks.set(event.toolCallId, event.toolName);
4570
4575
  const title = toolTaskTitle(event.toolName);
4571
4576
  const chunks = [];
4572
- if (toolCount === 1) chunks.push({
4573
- type: "plan_update",
4574
- title: "Working on it"
4575
- });
4577
+ if (needsPlanHeader) {
4578
+ chunks.push({
4579
+ type: "plan_update",
4580
+ title: "Working on it"
4581
+ });
4582
+ needsPlanHeader = false;
4583
+ }
4576
4584
  chunks.push({
4577
4585
  type: "task_update",
4578
4586
  id: event.toolCallId,
@@ -4598,7 +4606,7 @@ function createHandler(client, getConfig, signal, getTeamId, getChannelNameToId)
4598
4606
  ...event.output ? { output: redact(event.output) } : {}
4599
4607
  }];
4600
4608
  if (activeTasks.size === 0) {
4601
- const label = toolErrors === 0 ? `Completed (${toolCount} ${toolCount === 1 ? "step" : "steps"})` : `${toolSuccesses} passed, ${toolErrors} failed`;
4609
+ const label = toolErrors === 0 ? `Completed (${streamToolCount} ${streamToolCount === 1 ? "step" : "steps"})` : `${toolSuccesses} passed, ${toolErrors} failed`;
4602
4610
  chunks.push({
4603
4611
  type: "plan_update",
4604
4612
  title: label
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owloops/browserbird",
3
- "version": "1.8.5",
3
+ "version": "1.8.7",
4
4
  "description": "AI agent orchestrator with a real browser, a cron scheduler, and a web dashboard",
5
5
  "type": "module",
6
6
  "bin": {