@poncho-ai/browser 0.6.2 → 0.6.3

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.2 build /home/runner/work/poncho-ai/poncho-ai/packages/browser
2
+ > @poncho-ai/browser@0.6.3 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 41.37 KB
11
- ESM ⚡️ Build success in 75ms
10
+ ESM dist/index.js 44.07 KB
11
+ ESM ⚡️ Build success in 79ms
12
12
  DTS Build start
13
- DTS ⚡️ Build success in 4983ms
14
- DTS dist/index.d.ts 13.59 KB
13
+ DTS ⚡️ Build success in 4573ms
14
+ DTS dist/index.d.ts 13.72 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @poncho-ai/browser
2
2
 
3
+ ## 0.6.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [`35f3f54`](https://github.com/cesr/poncho-ai/commit/35f3f54b17ff50253ab01dbcfe19c643dd6c7e00) Thanks [@cesr](https://github.com/cesr)! - Add `browser_clear_cookies` tool for deleting browser cookies
8
+
9
+ Agents with `browser: true` can now call `browser_clear_cookies` to delete cookies from the live browser and persisted storage. Accepts an optional `url` parameter to scope deletion to a specific site (e.g. "https://example.com"); omit to clear all cookies.
10
+
3
11
  ## 0.6.2
4
12
 
5
13
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -147,6 +147,9 @@ declare class BrowserSession {
147
147
  executeJs(conversationId: string, script: string): Promise<unknown>;
148
148
  closeTab(conversationId: string): Promise<void>;
149
149
  navigate(conversationId: string, action: string): Promise<void>;
150
+ clearCookies(conversationId: string, url?: string): Promise<{
151
+ cleared: number;
152
+ }>;
150
153
  startScreencast(conversationId: string, options?: ScreencastOptions): Promise<void>;
151
154
  stopScreencast(): Promise<void>;
152
155
  onFrame(conversationId: string, listener: FrameListener): () => void;
@@ -158,6 +161,7 @@ declare class BrowserSession {
158
161
  saveState(storagePath: string): Promise<void>;
159
162
  private persistStorageState;
160
163
  private restoreStorageState;
164
+ private clearPersistedCookies;
161
165
  close(): Promise<void>;
162
166
  private emitStatus;
163
167
  }
package/dist/index.js CHANGED
@@ -739,6 +739,34 @@ var BrowserSession = class {
739
739
  this.unlock();
740
740
  }
741
741
  }
742
+ async clearCookies(conversationId, url) {
743
+ await this.lock();
744
+ try {
745
+ const mgr = await this.ensureManager();
746
+ await this.switchToConversation(mgr, conversationId);
747
+ const cdp = await mgr.getCDPSession();
748
+ let cleared = 0;
749
+ if (url) {
750
+ const { cookies } = await cdp.send("Network.getCookies", { urls: [url] });
751
+ cleared = cookies.length;
752
+ for (const cookie of cookies) {
753
+ await cdp.send("Network.deleteCookies", {
754
+ name: cookie.name,
755
+ domain: cookie.domain,
756
+ path: cookie.path
757
+ });
758
+ }
759
+ } else {
760
+ const { cookies } = await cdp.send("Network.getCookies");
761
+ cleared = cookies.length;
762
+ await cdp.send("Network.clearBrowserCookies");
763
+ }
764
+ await this.clearPersistedCookies(url);
765
+ return { cleared };
766
+ } finally {
767
+ this.unlock();
768
+ }
769
+ }
742
770
  // -----------------------------------------------------------------------
743
771
  // Screencast (one active at a time, tied to the viewed conversation)
744
772
  // -----------------------------------------------------------------------
@@ -933,6 +961,36 @@ var BrowserSession = class {
933
961
  console.warn("[poncho][browser] Failed to restore storage state:", err?.message ?? err);
934
962
  }
935
963
  }
964
+ async clearPersistedCookies(url) {
965
+ const persistence = this.config.storagePersistence;
966
+ if (!persistence) return;
967
+ try {
968
+ const json = await persistence.load();
969
+ if (!json) return;
970
+ const state = JSON.parse(json);
971
+ if (!state.cookies?.length) return;
972
+ if (url) {
973
+ let host;
974
+ try {
975
+ host = new URL(url).hostname.toLowerCase();
976
+ } catch {
977
+ return;
978
+ }
979
+ state.cookies = state.cookies.filter((c) => {
980
+ const raw = String(c.domain ?? "").toLowerCase();
981
+ const bare = raw.replace(/^\./, "");
982
+ if (host === bare) return false;
983
+ if (raw.startsWith(".") && host.endsWith("." + bare)) return false;
984
+ return true;
985
+ });
986
+ } else {
987
+ state.cookies = [];
988
+ }
989
+ await persistence.save(JSON.stringify(state));
990
+ } catch (err) {
991
+ console.warn("[poncho][browser] Failed to clear persisted cookies:", err?.message ?? err);
992
+ }
993
+ }
936
994
  async close() {
937
995
  try {
938
996
  await this.stopScreencast();
@@ -1167,6 +1225,25 @@ function createBrowserTools(getSession, getConversationId) {
1167
1225
  return { scrolled: direction, amount: amount ?? "viewport" };
1168
1226
  }
1169
1227
  },
1228
+ {
1229
+ name: "browser_clear_cookies",
1230
+ description: `Delete browser cookies. By default clears all cookies. Pass a url to only delete cookies that would be sent to that URL (e.g. "https://example.com" removes cookies for example.com and its subdomains). Also removes them from persisted storage so they won't be restored on next launch.`,
1231
+ inputSchema: {
1232
+ type: "object",
1233
+ properties: {
1234
+ url: {
1235
+ type: "string",
1236
+ description: 'Optional URL to scope deletion to (e.g. "https://example.com"). Omit to clear all cookies.'
1237
+ }
1238
+ }
1239
+ },
1240
+ handler: async (input) => {
1241
+ const session = getSession();
1242
+ const url = input.url ? String(input.url) : void 0;
1243
+ const { cleared } = await session.clearCookies(getConversationId(), url);
1244
+ return { cleared, scope: url ?? "all" };
1245
+ }
1246
+ },
1170
1247
  {
1171
1248
  name: "browser_close",
1172
1249
  description: "Close the browser tab for this conversation. Call this when you're done with browser tasks to free resources.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poncho-ai/browser",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "description": "Browser automation for Poncho agents, powered by agent-browser",
5
5
  "repository": {
6
6
  "type": "git",
package/src/session.ts CHANGED
@@ -676,6 +676,42 @@ export class BrowserSession {
676
676
  }
677
677
  }
678
678
 
679
+ async clearCookies(conversationId: string, url?: string): Promise<{ cleared: number }> {
680
+ await this.lock();
681
+ try {
682
+ const mgr = await this.ensureManager();
683
+ await this.switchToConversation(mgr, conversationId);
684
+ const cdp = await mgr.getCDPSession();
685
+
686
+ let cleared = 0;
687
+
688
+ if (url) {
689
+ const { cookies } = (await cdp.send("Network.getCookies", { urls: [url] })) as {
690
+ cookies: Array<{ name: string; domain: string; path: string }>;
691
+ };
692
+ cleared = cookies.length;
693
+ for (const cookie of cookies) {
694
+ await cdp.send("Network.deleteCookies", {
695
+ name: cookie.name,
696
+ domain: cookie.domain,
697
+ path: cookie.path,
698
+ });
699
+ }
700
+ } else {
701
+ const { cookies } = (await cdp.send("Network.getCookies")) as {
702
+ cookies: Array<unknown>;
703
+ };
704
+ cleared = cookies.length;
705
+ await cdp.send("Network.clearBrowserCookies");
706
+ }
707
+
708
+ await this.clearPersistedCookies(url);
709
+ return { cleared };
710
+ } finally {
711
+ this.unlock();
712
+ }
713
+ }
714
+
679
715
  // -----------------------------------------------------------------------
680
716
  // Screencast (one active at a time, tied to the viewed conversation)
681
717
  // -----------------------------------------------------------------------
@@ -881,6 +917,38 @@ export class BrowserSession {
881
917
  }
882
918
  }
883
919
 
920
+ private async clearPersistedCookies(url?: string): Promise<void> {
921
+ const persistence = this.config.storagePersistence;
922
+ if (!persistence) return;
923
+ try {
924
+ const json = await persistence.load();
925
+ if (!json) return;
926
+ const state = JSON.parse(json) as {
927
+ cookies?: Array<Record<string, unknown>>;
928
+ origins?: Array<{ origin: string; localStorage: Array<{ name: string; value: string }> }>;
929
+ };
930
+ if (!state.cookies?.length) return;
931
+
932
+ if (url) {
933
+ let host: string;
934
+ try { host = new URL(url).hostname.toLowerCase(); } catch { return; }
935
+ state.cookies = state.cookies.filter((c) => {
936
+ const raw = String(c.domain ?? "").toLowerCase();
937
+ const bare = raw.replace(/^\./, "");
938
+ if (host === bare) return false;
939
+ if (raw.startsWith(".") && host.endsWith("." + bare)) return false;
940
+ return true;
941
+ });
942
+ } else {
943
+ state.cookies = [];
944
+ }
945
+
946
+ await persistence.save(JSON.stringify(state));
947
+ } catch (err) {
948
+ console.warn("[poncho][browser] Failed to clear persisted cookies:", (err as Error)?.message ?? err);
949
+ }
950
+ }
951
+
884
952
  async close(): Promise<void> {
885
953
  try { await this.stopScreencast(); } catch { /* */ }
886
954
  await this.persistStorageState();
package/src/tools.ts CHANGED
@@ -221,6 +221,30 @@ export function createBrowserTools(
221
221
  return { scrolled: direction, amount: amount ?? "viewport" };
222
222
  },
223
223
  },
224
+ {
225
+ name: "browser_clear_cookies",
226
+ description:
227
+ "Delete browser cookies. By default clears all cookies. " +
228
+ "Pass a url to only delete cookies that would be sent to that URL " +
229
+ "(e.g. \"https://example.com\" removes cookies for example.com and its subdomains). " +
230
+ "Also removes them from persisted storage so they won't be restored on next launch.",
231
+ inputSchema: {
232
+ type: "object",
233
+ properties: {
234
+ url: {
235
+ type: "string",
236
+ description:
237
+ "Optional URL to scope deletion to (e.g. \"https://example.com\"). Omit to clear all cookies.",
238
+ },
239
+ },
240
+ },
241
+ handler: async (input: BrowserToolInput) => {
242
+ const session = getSession();
243
+ const url = input.url ? String(input.url) : undefined;
244
+ const { cleared } = await session.clearCookies(getConversationId(), url);
245
+ return { cleared, scope: url ?? "all" };
246
+ },
247
+ },
224
248
  {
225
249
  name: "browser_close",
226
250
  description: