@poncho-ai/browser 0.6.4 → 0.6.5

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @poncho-ai/browser@0.6.4 build /Users/cesar/Dev/latitude/poncho-ai/packages/browser
2
+ > @poncho-ai/browser@0.6.5 build /home/runner/work/poncho-ai/poncho-ai/packages/browser
3
3
  > tsup src/index.ts --format esm --dts
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -7,8 +7,8 @@
7
7
  CLI tsup v8.5.1
8
8
  CLI Target: es2022
9
9
  ESM Build start
10
- ESM dist/index.js 45.65 KB
11
- ESM ⚡️ Build success in 112ms
10
+ ESM dist/index.js 45.97 KB
11
+ ESM ⚡️ Build success in 73ms
12
12
  DTS Build start
13
- DTS ⚡️ Build success in 1828ms
14
- DTS dist/index.d.ts 13.72 KB
13
+ DTS ⚡️ Build success in 4746ms
14
+ DTS dist/index.d.ts 13.69 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @poncho-ai/browser
2
2
 
3
+ ## 0.6.5
4
+
5
+ ### Patch Changes
6
+
7
+ - [#42](https://github.com/cesr/poncho-ai/pull/42) [`e58a984`](https://github.com/cesr/poncho-ai/commit/e58a984efaa673b649318102bbf735fb4c2f9172) Thanks [@cesr](https://github.com/cesr)! - Add continuation model and fire-and-forget subagents
8
+
9
+ **Continuation model**: Agents no longer send a synthetic `"Continue"` user message between steps. Instead, the harness injects a transient signal when needed, and the full internal message chain is preserved across continuations so the LLM never loses context. `RunInput` gains `disableSoftDeadline` and `RunResult` gains `continuationMessages`.
10
+
11
+ **Fire-and-forget subagents**: Subagents now run asynchronously in the background. `spawn_subagent` returns immediately with a subagent ID; results are delivered back to the parent conversation as a callback once the subagent completes. Subagents cannot spawn their own subagents. The web UI shows results in a collapsible disclosure and reconnects the live event stream automatically when the parent agent resumes.
12
+
13
+ **Bug fixes**:
14
+ - Fixed a race condition where concurrent runs on the same harness instance could assign a subagent or browser tab to the wrong parent conversation (shared `_currentRunConversationId` field replaced with per-run `ToolContext.conversationId`).
15
+ - Fixed Upstash KV store silently dropping large values by switching from URL-path encoding to request body format for `SET`/`SETEX` commands.
16
+ - Fixed empty assistant content blocks causing Anthropic `text content blocks must be non-empty` errors.
17
+
18
+ **Client**: Added `getConversationStatus()` and `waitForSubagents` option on `sendMessage()`.
19
+
20
+ - Updated dependencies [[`e58a984`](https://github.com/cesr/poncho-ai/commit/e58a984efaa673b649318102bbf735fb4c2f9172)]:
21
+ - @poncho-ai/sdk@1.6.0
22
+
3
23
  ## 0.6.4
4
24
 
5
25
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -166,7 +166,7 @@ declare class BrowserSession {
166
166
  private emitStatus;
167
167
  }
168
168
 
169
- declare function createBrowserTools(getSession: () => BrowserSession, getConversationId: () => string): ToolDefinition[];
169
+ declare function createBrowserTools(getSession: () => BrowserSession): ToolDefinition[];
170
170
 
171
171
  /**
172
172
  * Returns a realistic Chrome user-agent string for the host OS.
package/dist/index.js CHANGED
@@ -1075,7 +1075,7 @@ var BrowserSession = class {
1075
1075
  };
1076
1076
 
1077
1077
  // src/tools.ts
1078
- function createBrowserTools(getSession, getConversationId) {
1078
+ function createBrowserTools(getSession) {
1079
1079
  return [
1080
1080
  {
1081
1081
  name: "browser_open",
@@ -1090,9 +1090,9 @@ function createBrowserTools(getSession, getConversationId) {
1090
1090
  },
1091
1091
  required: ["url"]
1092
1092
  },
1093
- handler: async (input) => {
1093
+ handler: async (input, context) => {
1094
1094
  const session = getSession();
1095
- const cid = getConversationId();
1095
+ const cid = context.conversationId ?? "__default__";
1096
1096
  const url = String(input.url ?? "");
1097
1097
  if (!url) throw new Error("url is required");
1098
1098
  const result = await session.open(cid, url);
@@ -1109,9 +1109,9 @@ function createBrowserTools(getSession, getConversationId) {
1109
1109
  type: "object",
1110
1110
  properties: {}
1111
1111
  },
1112
- handler: async () => {
1112
+ handler: async (_input, context) => {
1113
1113
  const session = getSession();
1114
- const snapshot = await session.snapshot(getConversationId());
1114
+ const snapshot = await session.snapshot(context.conversationId ?? "__default__");
1115
1115
  return { snapshot };
1116
1116
  }
1117
1117
  },
@@ -1128,11 +1128,11 @@ function createBrowserTools(getSession, getConversationId) {
1128
1128
  },
1129
1129
  required: ["ref"]
1130
1130
  },
1131
- handler: async (input) => {
1131
+ handler: async (input, context) => {
1132
1132
  const session = getSession();
1133
1133
  const ref = String(input.ref ?? "");
1134
1134
  if (!ref) throw new Error("ref is required");
1135
- await session.click(getConversationId(), ref);
1135
+ await session.click(context.conversationId ?? "__default__", ref);
1136
1136
  return { clicked: ref };
1137
1137
  }
1138
1138
  },
@@ -1153,12 +1153,12 @@ function createBrowserTools(getSession, getConversationId) {
1153
1153
  },
1154
1154
  required: ["text"]
1155
1155
  },
1156
- handler: async (input) => {
1156
+ handler: async (input, context) => {
1157
1157
  const session = getSession();
1158
1158
  const text = String(input.text ?? "");
1159
1159
  if (!text) throw new Error("text is required");
1160
1160
  const exact = input.exact === true;
1161
- await session.clickText(getConversationId(), text, exact);
1161
+ await session.clickText(context.conversationId ?? "__default__", text, exact);
1162
1162
  return { clicked: text, exact };
1163
1163
  }
1164
1164
  },
@@ -1175,11 +1175,11 @@ function createBrowserTools(getSession, getConversationId) {
1175
1175
  },
1176
1176
  required: ["script"]
1177
1177
  },
1178
- handler: async (input) => {
1178
+ handler: async (input, context) => {
1179
1179
  const session = getSession();
1180
1180
  const script = String(input.script ?? "");
1181
1181
  if (!script) throw new Error("script is required");
1182
- const result = await session.executeJs(getConversationId(), script);
1182
+ const result = await session.executeJs(context.conversationId ?? "__default__", script);
1183
1183
  return { result: result ?? null };
1184
1184
  }
1185
1185
  },
@@ -1200,12 +1200,12 @@ function createBrowserTools(getSession, getConversationId) {
1200
1200
  },
1201
1201
  required: ["ref", "text"]
1202
1202
  },
1203
- handler: async (input) => {
1203
+ handler: async (input, context) => {
1204
1204
  const session = getSession();
1205
1205
  const ref = String(input.ref ?? "");
1206
1206
  const text = String(input.text ?? "");
1207
1207
  if (!ref) throw new Error("ref is required");
1208
- await session.type(getConversationId(), ref, text);
1208
+ await session.type(context.conversationId ?? "__default__", ref, text);
1209
1209
  return { typed: text, into: ref };
1210
1210
  }
1211
1211
  },
@@ -1216,9 +1216,9 @@ function createBrowserTools(getSession, getConversationId) {
1216
1216
  type: "object",
1217
1217
  properties: {}
1218
1218
  },
1219
- handler: async () => {
1219
+ handler: async (_input, context) => {
1220
1220
  const session = getSession();
1221
- const result = await session.content(getConversationId());
1221
+ const result = await session.content(context.conversationId ?? "__default__");
1222
1222
  return { url: result.url, title: result.title, text: result.text };
1223
1223
  }
1224
1224
  },
@@ -1229,9 +1229,9 @@ function createBrowserTools(getSession, getConversationId) {
1229
1229
  type: "object",
1230
1230
  properties: {}
1231
1231
  },
1232
- handler: async () => {
1232
+ handler: async (_input, context) => {
1233
1233
  const session = getSession();
1234
- const base64 = await session.screenshot(getConversationId());
1234
+ const base64 = await session.screenshot(context.conversationId ?? "__default__");
1235
1235
  const filePart = {
1236
1236
  type: "file",
1237
1237
  data: base64,
@@ -1259,11 +1259,11 @@ function createBrowserTools(getSession, getConversationId) {
1259
1259
  },
1260
1260
  required: ["direction"]
1261
1261
  },
1262
- handler: async (input) => {
1262
+ handler: async (input, context) => {
1263
1263
  const session = getSession();
1264
1264
  const direction = String(input.direction ?? "down");
1265
1265
  const amount = typeof input.amount === "number" ? input.amount : void 0;
1266
- await session.scroll(getConversationId(), direction, amount);
1266
+ await session.scroll(context.conversationId ?? "__default__", direction, amount);
1267
1267
  return { scrolled: direction, amount: amount ?? "viewport" };
1268
1268
  }
1269
1269
  },
@@ -1279,10 +1279,10 @@ function createBrowserTools(getSession, getConversationId) {
1279
1279
  }
1280
1280
  }
1281
1281
  },
1282
- handler: async (input) => {
1282
+ handler: async (input, context) => {
1283
1283
  const session = getSession();
1284
1284
  const url = input.url ? String(input.url) : void 0;
1285
- const { cleared } = await session.clearCookies(getConversationId(), url);
1285
+ const { cleared } = await session.clearCookies(context.conversationId ?? "__default__", url);
1286
1286
  return { cleared, scope: url ?? "all" };
1287
1287
  }
1288
1288
  },
@@ -1293,9 +1293,9 @@ function createBrowserTools(getSession, getConversationId) {
1293
1293
  type: "object",
1294
1294
  properties: {}
1295
1295
  },
1296
- handler: async () => {
1296
+ handler: async (_input, context) => {
1297
1297
  const session = getSession();
1298
- await session.closeTab(getConversationId());
1298
+ await session.closeTab(context.conversationId ?? "__default__");
1299
1299
  return { closed: true };
1300
1300
  }
1301
1301
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poncho-ai/browser",
3
- "version": "0.6.4",
3
+ "version": "0.6.5",
4
4
  "description": "Browser automation for Poncho agents, powered by agent-browser",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "agent-browser": "^0.15.1",
24
- "@poncho-ai/sdk": "1.5.0"
24
+ "@poncho-ai/sdk": "1.6.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "tsup": "^8.0.0",
package/src/tools.ts CHANGED
@@ -1,11 +1,10 @@
1
- import type { ToolDefinition, FileContentPart } from "@poncho-ai/sdk";
1
+ import type { ToolContext, ToolDefinition, FileContentPart } from "@poncho-ai/sdk";
2
2
  import type { BrowserSession } from "./session.js";
3
3
 
4
4
  type BrowserToolInput = Record<string, unknown>;
5
5
 
6
6
  export function createBrowserTools(
7
7
  getSession: () => BrowserSession,
8
- getConversationId: () => string,
9
8
  ): ToolDefinition[] {
10
9
  return [
11
10
  {
@@ -22,9 +21,9 @@ export function createBrowserTools(
22
21
  },
23
22
  required: ["url"],
24
23
  },
25
- handler: async (input: BrowserToolInput) => {
24
+ handler: async (input: BrowserToolInput, context: ToolContext) => {
26
25
  const session = getSession();
27
- const cid = getConversationId();
26
+ const cid = context.conversationId ?? "__default__";
28
27
  const url = String(input.url ?? "");
29
28
  if (!url) throw new Error("url is required");
30
29
  const result = await session.open(cid, url);
@@ -44,9 +43,9 @@ export function createBrowserTools(
44
43
  type: "object",
45
44
  properties: {},
46
45
  },
47
- handler: async () => {
46
+ handler: async (_input: BrowserToolInput, context: ToolContext) => {
48
47
  const session = getSession();
49
- const snapshot = await session.snapshot(getConversationId());
48
+ const snapshot = await session.snapshot(context.conversationId ?? "__default__");
50
49
  return { snapshot };
51
50
  },
52
51
  },
@@ -65,11 +64,11 @@ export function createBrowserTools(
65
64
  },
66
65
  required: ["ref"],
67
66
  },
68
- handler: async (input: BrowserToolInput) => {
67
+ handler: async (input: BrowserToolInput, context: ToolContext) => {
69
68
  const session = getSession();
70
69
  const ref = String(input.ref ?? "");
71
70
  if (!ref) throw new Error("ref is required");
72
- await session.click(getConversationId(), ref);
71
+ await session.click(context.conversationId ?? "__default__", ref);
73
72
  return { clicked: ref };
74
73
  },
75
74
  },
@@ -94,12 +93,12 @@ export function createBrowserTools(
94
93
  },
95
94
  required: ["text"],
96
95
  },
97
- handler: async (input: BrowserToolInput) => {
96
+ handler: async (input: BrowserToolInput, context: ToolContext) => {
98
97
  const session = getSession();
99
98
  const text = String(input.text ?? "");
100
99
  if (!text) throw new Error("text is required");
101
100
  const exact = input.exact === true;
102
- await session.clickText(getConversationId(), text, exact);
101
+ await session.clickText(context.conversationId ?? "__default__", text, exact);
103
102
  return { clicked: text, exact };
104
103
  },
105
104
  },
@@ -121,11 +120,11 @@ export function createBrowserTools(
121
120
  },
122
121
  required: ["script"],
123
122
  },
124
- handler: async (input: BrowserToolInput) => {
123
+ handler: async (input: BrowserToolInput, context: ToolContext) => {
125
124
  const session = getSession();
126
125
  const script = String(input.script ?? "");
127
126
  if (!script) throw new Error("script is required");
128
- const result = await session.executeJs(getConversationId(), script);
127
+ const result = await session.executeJs(context.conversationId ?? "__default__", script);
129
128
  return { result: result ?? null };
130
129
  },
131
130
  },
@@ -148,12 +147,12 @@ export function createBrowserTools(
148
147
  },
149
148
  required: ["ref", "text"],
150
149
  },
151
- handler: async (input: BrowserToolInput) => {
150
+ handler: async (input: BrowserToolInput, context: ToolContext) => {
152
151
  const session = getSession();
153
152
  const ref = String(input.ref ?? "");
154
153
  const text = String(input.text ?? "");
155
154
  if (!ref) throw new Error("ref is required");
156
- await session.type(getConversationId(), ref, text);
155
+ await session.type(context.conversationId ?? "__default__", ref, text);
157
156
  return { typed: text, into: ref };
158
157
  },
159
158
  },
@@ -167,9 +166,9 @@ export function createBrowserTools(
167
166
  type: "object",
168
167
  properties: {},
169
168
  },
170
- handler: async () => {
169
+ handler: async (_input: BrowserToolInput, context: ToolContext) => {
171
170
  const session = getSession();
172
- const result = await session.content(getConversationId());
171
+ const result = await session.content(context.conversationId ?? "__default__");
173
172
  return { url: result.url, title: result.title, text: result.text };
174
173
  },
175
174
  },
@@ -182,9 +181,9 @@ export function createBrowserTools(
182
181
  type: "object",
183
182
  properties: {},
184
183
  },
185
- handler: async () => {
184
+ handler: async (_input: BrowserToolInput, context: ToolContext) => {
186
185
  const session = getSession();
187
- const base64 = await session.screenshot(getConversationId());
186
+ const base64 = await session.screenshot(context.conversationId ?? "__default__");
188
187
  const filePart: FileContentPart = {
189
188
  type: "file",
190
189
  data: base64,
@@ -213,11 +212,11 @@ export function createBrowserTools(
213
212
  },
214
213
  required: ["direction"],
215
214
  },
216
- handler: async (input: BrowserToolInput) => {
215
+ handler: async (input: BrowserToolInput, context: ToolContext) => {
217
216
  const session = getSession();
218
217
  const direction = String(input.direction ?? "down") as "up" | "down";
219
218
  const amount = typeof input.amount === "number" ? input.amount : undefined;
220
- await session.scroll(getConversationId(), direction, amount);
219
+ await session.scroll(context.conversationId ?? "__default__", direction, amount);
221
220
  return { scrolled: direction, amount: amount ?? "viewport" };
222
221
  },
223
222
  },
@@ -238,10 +237,10 @@ export function createBrowserTools(
238
237
  },
239
238
  },
240
239
  },
241
- handler: async (input: BrowserToolInput) => {
240
+ handler: async (input: BrowserToolInput, context: ToolContext) => {
242
241
  const session = getSession();
243
242
  const url = input.url ? String(input.url) : undefined;
244
- const { cleared } = await session.clearCookies(getConversationId(), url);
243
+ const { cleared } = await session.clearCookies(context.conversationId ?? "__default__", url);
245
244
  return { cleared, scope: url ?? "all" };
246
245
  },
247
246
  },
@@ -253,9 +252,9 @@ export function createBrowserTools(
253
252
  type: "object",
254
253
  properties: {},
255
254
  },
256
- handler: async () => {
255
+ handler: async (_input: BrowserToolInput, context: ToolContext) => {
257
256
  const session = getSession();
258
- await session.closeTab(getConversationId());
257
+ await session.closeTab(context.conversationId ?? "__default__");
259
258
  return { closed: true };
260
259
  },
261
260
  },
@@ -1,12 +0,0 @@
1
-
2
- > @poncho-ai/browser@0.6.2 test /Users/cesar/Dev/latitude/poncho-ai/packages/browser
3
- > vitest --passWithNoTests
4
-
5
-
6
-  RUN  v1.6.1 /Users/cesar/Dev/latitude/poncho-ai/packages/browser
7
-
8
- No test files found, exiting with code 0
9
- include: **/*.{test,spec}.?(c|m)[jt]s?(x)
10
-
11
- exclude: **/node_modules/**, **/dist/**, **/cypress/**, **/.{idea,git,cache,output,temp}/**, **/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*
12
- watch exclude: **/node_modules/**, **/dist/**