@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.
- package/.turbo/turbo-build.log +5 -5
- package/CHANGELOG.md +8 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +77 -0
- package/package.json +1 -1
- package/src/session.ts +68 -0
- package/src/tools.ts +24 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @poncho-ai/browser@0.6.
|
|
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
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
[34mCLI[39m tsup v8.5.1
|
|
8
8
|
[34mCLI[39m Target: es2022
|
|
9
9
|
[34mESM[39m Build start
|
|
10
|
-
[32mESM[39m [1mdist/index.js [22m[
|
|
11
|
-
[32mESM[39m ⚡️ Build success in
|
|
10
|
+
[32mESM[39m [1mdist/index.js [22m[32m44.07 KB[39m
|
|
11
|
+
[32mESM[39m ⚡️ Build success in 79ms
|
|
12
12
|
[34mDTS[39m Build start
|
|
13
|
-
[32mDTS[39m ⚡️ Build success in
|
|
14
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m13.
|
|
13
|
+
[32mDTS[39m ⚡️ Build success in 4573ms
|
|
14
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m13.72 KB[39m
|
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
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:
|