agents 0.20.1 → 0.21.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 (76) hide show
  1. package/README.md +50 -12
  2. package/dist/{agent-tool-types-BC-WFlsz.d.ts → agent-tool-types-CzGGB-20.d.ts} +375 -72
  3. package/dist/agent-tool-types.d.ts +1 -1
  4. package/dist/{agent-tools-DeHe9Xov.d.ts → agent-tools-zR2d5uij.d.ts} +2 -2
  5. package/dist/agent-tools.d.ts +24 -8
  6. package/dist/agent-tools.js +14 -6
  7. package/dist/agent-tools.js.map +1 -1
  8. package/dist/browser/ai.d.ts +5 -3
  9. package/dist/browser/ai.js +86 -7
  10. package/dist/browser/ai.js.map +1 -1
  11. package/dist/browser/index.d.ts +1 -1
  12. package/dist/browser/index.js +1 -1
  13. package/dist/browser/tanstack-ai.js +13 -1
  14. package/dist/browser/tanstack-ai.js.map +1 -1
  15. package/dist/chat/index.d.ts +31 -2
  16. package/dist/chat/index.js +57 -2
  17. package/dist/chat/index.js.map +1 -1
  18. package/dist/chat/react.d.ts +5 -179
  19. package/dist/chat/react.js +18 -555
  20. package/dist/chat/react.js.map +1 -1
  21. package/dist/chat/transport.d.ts +10 -0
  22. package/dist/chat/transport.js +2 -0
  23. package/dist/chat-sdk/index.d.ts +1 -1
  24. package/dist/client.d.ts +1 -1
  25. package/dist/{connector-v2M1zlZp.d.ts → connector-CkQD4MK3.d.ts} +20 -3
  26. package/dist/{connector-KEJnl6e5.js → connector-CptFKzRh.js} +158 -40
  27. package/dist/connector-CptFKzRh.js.map +1 -0
  28. package/dist/index.d.ts +20 -12
  29. package/dist/index.js +5 -4
  30. package/dist/index.js.map +1 -1
  31. package/dist/mcp/client.d.ts +20 -20
  32. package/dist/mcp/index.d.ts +35 -35
  33. package/dist/observability/ai/index.d.ts +1 -130
  34. package/dist/observability/ai/index.js +39 -399
  35. package/dist/observability/ai/index.js.map +1 -1
  36. package/dist/{wire-types-CU9rLoeS.js → protocol-Dqc2MQxo.js} +2 -46
  37. package/dist/protocol-Dqc2MQxo.js.map +1 -0
  38. package/dist/react.d.ts +1 -1
  39. package/dist/react.js +5 -8
  40. package/dist/react.js.map +1 -1
  41. package/dist/serializable.d.ts +1 -1
  42. package/dist/sub-routing.d.ts +18 -6
  43. package/dist/sub-routing.js +92 -2
  44. package/dist/sub-routing.js.map +1 -1
  45. package/dist/wire-types-CnMt6_HR.js +47 -0
  46. package/dist/wire-types-CnMt6_HR.js.map +1 -0
  47. package/dist/workflow-types.d.ts +25 -25
  48. package/dist/workflow-types.js.map +1 -1
  49. package/dist/workflows.d.ts +22 -22
  50. package/dist/ws-chat-transport-CIoOBbO7.js +561 -0
  51. package/dist/ws-chat-transport-CIoOBbO7.js.map +1 -0
  52. package/dist/ws-chat-transport-UNRIS2xl.d.ts +184 -0
  53. package/docs/adding-to-existing-project.md +4 -2
  54. package/docs/agent-class.md +1 -1
  55. package/docs/agent-tools.md +29 -0
  56. package/docs/browse-the-web.md +16 -1
  57. package/docs/chat-agents.md +3 -1
  58. package/docs/client-sdk.md +12 -8
  59. package/docs/configuration.md +7 -1
  60. package/docs/cross-domain-authentication.md +7 -35
  61. package/docs/email.md +2 -13
  62. package/docs/human-in-the-loop.md +15 -12
  63. package/docs/long-running-agents.md +11 -11
  64. package/docs/mcp-servers.md +6 -0
  65. package/docs/mcp-transports.md +18 -12
  66. package/docs/migration-to-ai-sdk-v5.md +2 -2
  67. package/docs/migration-to-ai-sdk-v6.md +5 -1
  68. package/docs/observability.md +22 -66
  69. package/docs/routing.md +27 -0
  70. package/docs/sub-agents.md +47 -2
  71. package/docs/webhooks.md +109 -136
  72. package/docs/workflows.md +9 -1
  73. package/package.json +13 -4
  74. package/dist/connector-KEJnl6e5.js.map +0 -1
  75. package/dist/wire-types-CU9rLoeS.js.map +0 -1
  76. package/dist/workflow-types-Baz_PO5v.d.ts +0 -280
@@ -0,0 +1,10 @@
1
+ import {
2
+ n as WebSocketChatTransport,
3
+ r as WebSocketChatTransportOptions,
4
+ t as AgentConnection
5
+ } from "../ws-chat-transport-UNRIS2xl.js";
6
+ export {
7
+ type AgentConnection,
8
+ WebSocketChatTransport,
9
+ type WebSocketChatTransportOptions
10
+ };
@@ -0,0 +1,2 @@
1
+ import { t as WebSocketChatTransport } from "../ws-chat-transport-CIoOBbO7.js";
2
+ export { WebSocketChatTransport };
@@ -2,7 +2,7 @@ import {
2
2
  O as Agent,
3
3
  ct as SubAgentClass,
4
4
  lt as SubAgentStub
5
- } from "../agent-tool-types-BC-WFlsz.js";
5
+ } from "../agent-tool-types-CzGGB-20.js";
6
6
  import { Lock, QueueEntry, StateAdapter } from "chat";
7
7
 
8
8
  //#region src/chat-sdk/agent.d.ts
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { O as Agent } from "./agent-tool-types-BC-WFlsz.js";
1
+ import { O as Agent } from "./agent-tool-types-CzGGB-20.js";
2
2
  import {
3
3
  ClientParameters,
4
4
  Method,
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  CodemodeConnector,
3
+ ConnectorTool,
3
4
  ConnectorTools,
4
5
  ExecutionEndStatus,
5
6
  PassEndStatus
@@ -95,6 +96,11 @@ interface ConnectBrowserOptions {
95
96
  * {@link getBrowserRecording}.
96
97
  */
97
98
  recording?: boolean;
99
+ /**
100
+ * Select the browser engine. Defaults to Chromium. Use `"kitesurf"` for
101
+ * Cloudflare's connection-scoped, agent-first browser engine.
102
+ */
103
+ browser?: "kitesurf";
98
104
  }
99
105
  /** An rrweb session recording for a closed Browser Run session. */
100
106
  interface BrowserRecording {
@@ -228,7 +234,7 @@ type QuickActionExtractInput = QuickActionPage & {
228
234
  /** Natural-language instruction for what to extract. */ prompt?: string /** A JSON Schema describing the desired output shape. */;
229
235
  response_format?: {
230
236
  type: "json_schema";
231
- schema: unknown;
237
+ json_schema: unknown;
232
238
  } /** Bring-your-own model(s), tried in order, for extraction. */;
233
239
  custom_ai?: {
234
240
  model: string;
@@ -432,6 +438,12 @@ interface BrowserConnectorSessionOptions {
432
438
  * {@link BrowserConnector.liveView}/`sessionInfo()`.
433
439
  */
434
440
  recording?: boolean;
441
+ /**
442
+ * Select the browser engine. Defaults to Chromium. Kitesurf is scoped to
443
+ * one CDP WebSocket, so it supports only one-shot execution without
444
+ * pause/resume, Live View, recording, or keep-alive.
445
+ */
446
+ browser?: "kitesurf";
435
447
  }
436
448
  type BrowserConnectorOptions = (
437
449
  | {
@@ -554,13 +566,14 @@ declare class BrowserConnector extends CodemodeConnector {
554
566
  );
555
567
  name(): string;
556
568
  protected instructions(): string;
569
+ protected tool(name: string, tool: ConnectorTool): ConnectorTool;
557
570
  protected tools(): ConnectorTools;
558
571
  /**
559
572
  * A pass is over (completed, errored, or paused awaiting approval) — drop
560
573
  * the CDP socket. The Browser Run session itself stays alive; a resume
561
574
  * reconnects from the durably stored session id.
562
575
  */
563
- onPassEnd(executionId: string, _status: PassEndStatus): Promise<void>;
576
+ onPassEnd(executionId: string, status: PassEndStatus): Promise<void>;
564
577
  /**
565
578
  * The execution is terminal — delete its Browser Run session unless it was
566
579
  * promoted to the shared slot via `cdp.startSession()`.
@@ -597,6 +610,10 @@ declare class BrowserConnector extends CodemodeConnector {
597
610
  * deleted, so a later resume fails with a clear "session expired" error
598
611
  * instead of silently continuing in a fresh browser; tombstones are
599
612
  * deleted once they age past the threshold again.
613
+ *
614
+ * Kitesurf entries are reclaimed the same way, minus the Browser Run
615
+ * delete: their stored id is a synthetic per-execution marker, not a
616
+ * session, and the connection died with the execution.
600
617
  */
601
618
  sweep(
602
619
  options?: BrowserConnectorSweepOptions
@@ -656,4 +673,4 @@ export {
656
673
  QuickActionCommonOptions as y,
657
674
  BrowserSessionInfo as z
658
675
  };
659
- //# sourceMappingURL=connector-v2M1zlZp.d.ts.map
676
+ //# sourceMappingURL=connector-CkQD4MK3.d.ts.map
@@ -1,6 +1,7 @@
1
1
  import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-DZBYAB34.js";
2
2
  import { t as _classPrivateMethodInitSpec } from "./classPrivateMethodInitSpec-qMjJ6sHQ.js";
3
3
  import { CodemodeConnector } from "@cloudflare/codemode";
4
+ import { Validator } from "@cfworker/json-schema";
4
5
  //#region src/browser/cdp-session.ts
5
6
  const DEFAULT_TIMEOUT_MS = 1e4;
6
7
  const MAX_DEBUG_ENTRIES = 400;
@@ -207,6 +208,7 @@ function browserSessionEndpoint(sessionId, options) {
207
208
  if (options?.keepAliveMs !== void 0) url.searchParams.set("keep_alive", String(options.keepAliveMs));
208
209
  if (options?.includeTargets) url.searchParams.set("targets", "true");
209
210
  if (options?.recording) url.searchParams.set("recording", "true");
211
+ if (options?.browser) url.searchParams.set("browser", options.browser);
210
212
  return url.toString();
211
213
  }
212
214
  async function parseBrowserSessionInfo(response) {
@@ -239,13 +241,20 @@ async function deleteBrowserSession(browser, sessionId) {
239
241
  */
240
242
  async function connectBrowser(browser, options) {
241
243
  const normalizedOptions = typeof options === "number" ? { timeoutMs: options } : options ?? {};
244
+ const isKitesurf = normalizedOptions.browser === "kitesurf";
245
+ if (isKitesurf && (normalizedOptions.keepAliveMs || normalizedOptions.includeTargets || normalizedOptions.recording)) throw new Error("Kitesurf does not support keepAliveMs, includeTargets, or recording");
242
246
  const response = await browser.fetch(browserSessionEndpoint(void 0, {
243
- keepAliveMs: normalizedOptions.keepAliveMs,
247
+ keepAliveMs: isKitesurf ? void 0 : normalizedOptions.keepAliveMs,
244
248
  includeTargets: normalizedOptions.includeTargets,
245
- recording: normalizedOptions.recording
249
+ recording: normalizedOptions.recording,
250
+ browser: normalizedOptions.browser
246
251
  }), { headers: { Upgrade: "websocket" } });
247
252
  const ws = response.webSocket;
248
253
  if (!ws) throw new Error("Browser Rendering binding did not return a WebSocket. Ensure the 'browser' binding is configured in wrangler.jsonc.");
254
+ if (normalizedOptions.browser === "kitesurf") {
255
+ ws.accept();
256
+ return new CdpSession(ws, normalizedOptions.timeoutMs);
257
+ }
249
258
  const sessionId = response.headers.get("cf-browser-session-id");
250
259
  if (!sessionId) throw new Error("Browser Rendering binding did not include a session ID when opening the CDP WebSocket");
251
260
  ws.accept();
@@ -495,6 +504,12 @@ const DEFAULT_SWEEP_IDLE_MS = 600 * 1e3;
495
504
  //#endregion
496
505
  //#region src/browser/connector.ts
497
506
  const EXEC_KEY_PREFIX = "cdp:exec:";
507
+ /**
508
+ * Prefix of the synthetic session id stored for a Kitesurf execution: the
509
+ * connection is scoped to its execution, so the entry is a marker rather than
510
+ * a Browser Run session that can be reconnected to or deleted.
511
+ */
512
+ const KITESURF_SESSION_PREFIX = "kitesurf:";
498
513
  const REUSE_KEY_PREFIX = "cdp:reuse:";
499
514
  /**
500
515
  * Default idle window before {@link BrowserConnector.sweep} reclaims a
@@ -518,6 +533,13 @@ const LIVE_VIEW_URL_TTL_MS = 300 * 1e3;
518
533
  function isMissingBrowserSession(error) {
519
534
  return error instanceof BrowserRenderingError && (error.status === 404 || error.status === 410);
520
535
  }
536
+ function formatToolValidationError(connector, tool, errors) {
537
+ const specific = errors.filter((error) => error.keyword !== "properties");
538
+ return `Invalid arguments for ${connector}.${tool}${(specific.length > 0 ? specific : errors).map((error) => {
539
+ const location = error.instanceLocation.replace(/^#\/?/, "").replaceAll("~1", "/").replaceAll("~0", "~").replaceAll("/", ".");
540
+ return `${location ? ` at ${location}` : ""}: ${error.error}`;
541
+ }).join(";")}`;
542
+ }
521
543
  /**
522
544
  * Rewrite the hosted Live View UI's `mode` query param (`tab` | `devtools`).
523
545
  * The raw `devtoolsFrontendUrl` is returned unchanged when no mode is asked
@@ -575,6 +597,11 @@ var BrowserConnector = class extends CodemodeConnector {
575
597
  _classPrivateFieldInitSpec(this, _connecting, /* @__PURE__ */ new Map());
576
598
  if (!options.cdpUrl && !options.browser) throw new Error("BrowserConnector requires either 'browser' (Fetcher binding) or 'cdpUrl'");
577
599
  if (options.browser && !options.store) throw new Error("BrowserConnector requires 'store' when using the Browser Rendering binding");
600
+ if (options.session?.browser === "kitesurf") {
601
+ if (options.session.mode !== void 0 && options.session.mode !== "one-shot") throw new Error("Kitesurf only supports session mode \"one-shot\"");
602
+ if (options.session.keepAliveMs) throw new Error("Kitesurf does not support keepAliveMs");
603
+ if (options.session.recording) throw new Error("Kitesurf does not support session recording");
604
+ }
578
605
  _classPrivateFieldSet2(_options, this, options);
579
606
  }
580
607
  name() {
@@ -584,21 +611,36 @@ var BrowserConnector = class extends CodemodeConnector {
584
611
  const mode = _assertClassBrand(_BrowserConnector_brand, this, _mode).call(this);
585
612
  const lines = [
586
613
  "Issue CDP calls sequentially — never in parallel (no Promise.all): call order is recorded for durable replay.",
587
- "Browser-/Target-scoped commands (Target.createTarget, Target.getTargets) need no sessionId. Page-scoped commands (Page.navigate, Runtime.evaluate) require one: `const { sessionId } = await cdp.attachToTarget({ targetId });` then pass it to every page-scoped send.",
588
- "Write large outputs (screenshots, page dumps) to a file or workspace immediately and pass around small references large return values fail to record.",
589
- "Use cdp.spec() to discover commands, events, and types when unsure.",
590
- "If a command fails or times out, check cdp.getDebugLog() for recent protocol traffic.",
591
- "When a step needs a human (login, MFA, CAPTCHA, sensitive input), call cdp.getLiveViewUrl() to get a link they can open to control the browser live — surface it, then make an approval-gated call so the run pauses until they're done."
614
+ "cdp.send returns the CDP method result directly, not the outer JSON-RPC envelope: Target.createTarget returns { targetId }, Runtime.evaluate returns { result: { value } }, and Page.captureScreenshot returns { data }.",
615
+ "Browser-/Target-scoped commands (Target.createTarget, Target.getTargets) need no sessionId. Page-scoped commands (Page.navigate, Runtime.evaluate) require one: `const { sessionId } = await cdp.attachToTarget({ targetId });` then pass it to every page-scoped send. Use this helper instead of sending Target.attachToTarget manually.",
616
+ "Write large textual outputs such as page dumps to a file or workspace and pass around small references. For screenshots, follow the host tool's documented screenshot result format.",
617
+ "If a command fails or times out, check cdp.getDebugLog() for recent protocol traffic."
592
618
  ];
619
+ if (_assertClassBrand(_BrowserConnector_brand, this, _isKitesurf).call(this)) lines.push("Kitesurf implements a subset of CDP and does not expose protocol discovery.", "Kitesurf is scoped to this connection. Complete the whole browser task in one execution and do not pause for approval: the browser cannot reconnect when execution resumes.", "Kitesurf Page.navigate may resolve before layout and paint. Before a screenshot: call Page.enable; navigate; poll Runtime.evaluate with returnByValue: true until result.value reports document.readyState === 'complete' and non-empty body text; then wait 1000ms before Page.captureScreenshot. Do not capture if readiness fails.");
620
+ else lines.push("Use cdp.spec() to discover commands, events, and types when unsure.", "When a step needs a human (login, MFA, CAPTCHA, sensitive input), call cdp.getLiveViewUrl() to get a link they can open to control the browser live — surface it, then make an approval-gated call so the run pauses until they're done.");
593
621
  if (mode === "one-shot") lines.push("The browser session lasts for this execution only and is closed when it ends.");
594
622
  else if (mode === "reuse") lines.push("The browser session is shared and persists across executions — tabs and state you leave behind will still be there next time.");
595
623
  else lines.push("The browser session is one-shot by default. If browser state must persist after this execution (e.g. a logged-in page), call cdp.startSession() to keep it alive for later executions.");
596
624
  return lines.join("\n");
597
625
  }
626
+ tool(name, tool) {
627
+ if (!tool.inputSchema) return tool;
628
+ const schema = tool.inputSchema;
629
+ const validator = new Validator(schema, "7", false);
630
+ return {
631
+ ...tool,
632
+ execute: async (args, ctx) => {
633
+ const input = args === void 0 ? {} : args;
634
+ const result = validator.validate(input);
635
+ if (!result.valid) throw new Error(formatToolValidationError(this.name(), name, result.errors));
636
+ return await tool.execute(input, ctx);
637
+ }
638
+ };
639
+ }
598
640
  tools() {
599
641
  const tools = {
600
642
  send: {
601
- description: "Send a CDP command and return its result. Page-scoped commands require a sessionId — pass the handle returned by attachToTarget.",
643
+ description: "Send a CDP command and return its method result directly (the outer JSON-RPC envelope is removed). Page-scoped commands require a sessionId — pass the handle returned by attachToTarget.",
602
644
  inputSchema: {
603
645
  type: "object",
604
646
  properties: {
@@ -641,7 +683,7 @@ var BrowserConnector = class extends CodemodeConnector {
641
683
  }
642
684
  },
643
685
  attachToTarget: {
644
- description: "Attach to a target (tab) and return { sessionId } — a stable session handle to pass as sessionId in page-scoped send calls. The handle stays valid across pauses/resumes.",
686
+ description: _assertClassBrand(_BrowserConnector_brand, this, _isKitesurf).call(this) ? "Attach to a target (tab) and return { sessionId } to pass to page-scoped send calls for this connection." : "Attach to a target (tab) and return { sessionId } — a stable session handle to pass as sessionId in page-scoped send calls. The handle stays valid across pauses/resumes.",
645
687
  inputSchema: {
646
688
  type: "object",
647
689
  properties: {
@@ -657,7 +699,7 @@ var BrowserConnector = class extends CodemodeConnector {
657
699
  type: "object",
658
700
  properties: { sessionId: {
659
701
  type: "string",
660
- description: "Stable session handle for page-scoped send calls (valid across pauses/resumes)"
702
+ description: _assertClassBrand(_BrowserConnector_brand, this, _isKitesurf).call(this) ? "Session handle for page-scoped send calls on this connection" : "Stable session handle for page-scoped send calls (valid across pauses/resumes)"
661
703
  } },
662
704
  required: ["sessionId"]
663
705
  },
@@ -675,7 +717,10 @@ var BrowserConnector = class extends CodemodeConnector {
675
717
  type: "object",
676
718
  properties: {}
677
719
  },
678
- execute: async () => loadCdpSpec(_classPrivateFieldGet2(_options, this))
720
+ execute: async () => {
721
+ if (_assertClassBrand(_BrowserConnector_brand, this, _isKitesurf).call(this)) throw new Error("Kitesurf does not expose a CDP protocol specification");
722
+ return loadCdpSpec(_classPrivateFieldGet2(_options, this));
723
+ }
679
724
  },
680
725
  getDebugLog: {
681
726
  description: "Return recent CDP protocol traffic (sends, receives, warnings) for this execution's connection — useful to diagnose failures and timeouts.",
@@ -702,31 +747,32 @@ var BrowserConnector = class extends CodemodeConnector {
702
747
  (await _assertClassBrand(_BrowserConnector_brand, this, _socket).call(this, _assertClassBrand(_BrowserConnector_brand, this, _executionId).call(this, ctx))).clearDebugLog();
703
748
  return null;
704
749
  }
705
- },
706
- getLiveViewUrl: {
707
- description: "Return a Live View URL for a tab — a link a human can open in a browser to watch and control this session in real time. Use it for human-in-the-loop steps (login, MFA, CAPTCHA, sensitive input): get the URL, surface it to the user, then make a call that pauses for approval so they can act before the run continues. The URL is valid for ~5 minutes.",
708
- replay: "reexecute",
709
- inputSchema: {
710
- type: "object",
711
- properties: {
712
- targetId: {
713
- type: "string",
714
- description: "Target (tab) id to view; defaults to the first open page"
715
- },
716
- mode: {
717
- type: "string",
718
- enum: ["tab", "devtools"],
719
- description: "tab = standalone interactive page view (best for handoff); devtools = full DevTools inspector panel"
720
- }
750
+ }
751
+ };
752
+ if (_assertClassBrand(_BrowserConnector_brand, this, _isKitesurf).call(this)) delete tools.spec;
753
+ else tools.getLiveViewUrl = {
754
+ description: "Return a Live View URL for a tab — a link a human can open in a browser to watch and control this session in real time. Use it for human-in-the-loop steps (login, MFA, CAPTCHA, sensitive input): get the URL, surface it to the user, then make a call that pauses for approval so they can act before the run continues. The URL is valid for ~5 minutes.",
755
+ replay: "reexecute",
756
+ inputSchema: {
757
+ type: "object",
758
+ properties: {
759
+ targetId: {
760
+ type: "string",
761
+ description: "Target (tab) id to view; defaults to the first open page"
762
+ },
763
+ mode: {
764
+ type: "string",
765
+ enum: ["tab", "devtools"],
766
+ description: "tab = standalone interactive page view (best for handoff); devtools = full DevTools inspector panel"
721
767
  }
722
- },
723
- execute: async (args, ctx) => {
724
- const { targetId, mode } = args ?? {};
725
- return _assertClassBrand(_BrowserConnector_brand, this, _liveViewUrl).call(this, _assertClassBrand(_BrowserConnector_brand, this, _executionId).call(this, ctx), {
726
- targetId,
727
- mode
728
- });
729
768
  }
769
+ },
770
+ execute: async (args, ctx) => {
771
+ const { targetId, mode } = args ?? {};
772
+ return _assertClassBrand(_BrowserConnector_brand, this, _liveViewUrl).call(this, _assertClassBrand(_BrowserConnector_brand, this, _executionId).call(this, ctx), {
773
+ targetId,
774
+ mode
775
+ });
730
776
  }
731
777
  };
732
778
  const mode = _assertClassBrand(_BrowserConnector_brand, this, _mode).call(this);
@@ -775,8 +821,20 @@ var BrowserConnector = class extends CodemodeConnector {
775
821
  * the CDP socket. The Browser Run session itself stays alive; a resume
776
822
  * reconnects from the durably stored session id.
777
823
  */
778
- async onPassEnd(executionId, _status) {
824
+ async onPassEnd(executionId, status) {
779
825
  _assertClassBrand(_BrowserConnector_brand, this, _dropSocket).call(this, executionId);
826
+ if (!_assertClassBrand(_BrowserConnector_brand, this, _isKitesurf).call(this) || status !== "paused") return;
827
+ const key = _assertClassBrand(_BrowserConnector_brand, this, _execKey).call(this, executionId);
828
+ const lock = await _get_store.call(_assertClassBrand(_BrowserConnector_brand, this)).acquireLock(key);
829
+ try {
830
+ const stored = await _get_store.call(_assertClassBrand(_BrowserConnector_brand, this)).get(key);
831
+ if (stored?.sessionId.startsWith(KITESURF_SESSION_PREFIX)) await _get_store.call(_assertClassBrand(_BrowserConnector_brand, this)).set(key, {
832
+ ...stored,
833
+ closedAt: Date.now()
834
+ });
835
+ } finally {
836
+ await lock.release();
837
+ }
780
838
  }
781
839
  /**
782
840
  * The execution is terminal — delete its Browser Run session unless it was
@@ -785,6 +843,24 @@ var BrowserConnector = class extends CodemodeConnector {
785
843
  async disposeExecution(executionId, _status) {
786
844
  _assertClassBrand(_BrowserConnector_brand, this, _dropSocket).call(this, executionId);
787
845
  if (!_classPrivateFieldGet2(_options, this).browser) return;
846
+ if (_assertClassBrand(_BrowserConnector_brand, this, _isKitesurf).call(this)) {
847
+ const key = _assertClassBrand(_BrowserConnector_brand, this, _execKey).call(this, executionId);
848
+ const lock = await _get_store.call(_assertClassBrand(_BrowserConnector_brand, this)).acquireLock(key);
849
+ let stale;
850
+ try {
851
+ const stored = await _get_store.call(_assertClassBrand(_BrowserConnector_brand, this)).get(key);
852
+ if (stored && stored.closedAt === void 0 && !stored.sessionId.startsWith(KITESURF_SESSION_PREFIX)) stale = stored;
853
+ await _get_store.call(_assertClassBrand(_BrowserConnector_brand, this)).delete(key);
854
+ } finally {
855
+ await lock.release();
856
+ }
857
+ if (stale) try {
858
+ await deleteBrowserSession(_classPrivateFieldGet2(_options, this).browser, stale.sessionId);
859
+ } catch (error) {
860
+ console.warn(`[agents/browser] Failed to delete Browser Run session ${stale.sessionId} for execution ${executionId}`, error);
861
+ }
862
+ return;
863
+ }
788
864
  const store = _classPrivateFieldGet2(_options, this).store;
789
865
  const execKey = _assertClassBrand(_BrowserConnector_brand, this, _execKey).call(this, executionId);
790
866
  const lock = await store.acquireLock(execKey);
@@ -807,7 +883,7 @@ var BrowserConnector = class extends CodemodeConnector {
807
883
  }
808
884
  /** Info about the shared (reuse/promoted) session, if one exists. */
809
885
  async sessionInfo() {
810
- if (!_classPrivateFieldGet2(_options, this).browser) return void 0;
886
+ if (!_classPrivateFieldGet2(_options, this).browser || _assertClassBrand(_BrowserConnector_brand, this, _isKitesurf).call(this)) return void 0;
811
887
  const store = _classPrivateFieldGet2(_options, this).store;
812
888
  const key = _assertClassBrand(_BrowserConnector_brand, this, _reuseKey).call(this);
813
889
  const lock = await store.acquireLock(key);
@@ -858,7 +934,7 @@ var BrowserConnector = class extends CodemodeConnector {
858
934
  }
859
935
  /** Close the shared (reuse/promoted) session, if one exists. */
860
936
  async closeSession() {
861
- if (!_classPrivateFieldGet2(_options, this).browser) return;
937
+ if (!_classPrivateFieldGet2(_options, this).browser || _assertClassBrand(_BrowserConnector_brand, this, _isKitesurf).call(this)) return;
862
938
  await _assertClassBrand(_BrowserConnector_brand, this, _closeStoredSession).call(this, _assertClassBrand(_BrowserConnector_brand, this, _reuseKey).call(this));
863
939
  }
864
940
  /**
@@ -873,9 +949,14 @@ var BrowserConnector = class extends CodemodeConnector {
873
949
  * deleted, so a later resume fails with a clear "session expired" error
874
950
  * instead of silently continuing in a fresh browser; tombstones are
875
951
  * deleted once they age past the threshold again.
952
+ *
953
+ * Kitesurf entries are reclaimed the same way, minus the Browser Run
954
+ * delete: their stored id is a synthetic per-execution marker, not a
955
+ * session, and the connection died with the execution.
876
956
  */
877
957
  async sweep(options) {
878
958
  if (!_classPrivateFieldGet2(_options, this).browser) return { swept: [] };
959
+ const browser = _classPrivateFieldGet2(_options, this).browser;
879
960
  const store = _classPrivateFieldGet2(_options, this).store;
880
961
  const maxIdleMs = options?.maxIdleMs ?? _classPrivateFieldGet2(_options, this).session?.keepAliveMs ?? 6e5;
881
962
  const maxExecIdleMs = options?.maxExecIdleMs ?? 864e5;
@@ -905,8 +986,8 @@ var BrowserConnector = class extends CodemodeConnector {
905
986
  } finally {
906
987
  await lock.release();
907
988
  }
908
- try {
909
- await deleteBrowserSession(_classPrivateFieldGet2(_options, this).browser, toClose.sessionId);
989
+ if (!toClose.sessionId.startsWith(KITESURF_SESSION_PREFIX)) try {
990
+ await deleteBrowserSession(browser, toClose.sessionId);
910
991
  } catch (error) {
911
992
  console.warn(`[agents/browser] Sweep failed to delete Browser Run session ${toClose.sessionId}`, error);
912
993
  }
@@ -918,6 +999,9 @@ var BrowserConnector = class extends CodemodeConnector {
918
999
  return { swept };
919
1000
  }
920
1001
  };
1002
+ function _isKitesurf() {
1003
+ return _classPrivateFieldGet2(_options, this).session?.browser === "kitesurf";
1004
+ }
921
1005
  function _mode() {
922
1006
  return _classPrivateFieldGet2(_options, this).session?.mode ?? "one-shot";
923
1007
  }
@@ -964,6 +1048,7 @@ async function _liveTargets(executionId) {
964
1048
  }
965
1049
  const browser = _classPrivateFieldGet2(_options, this).browser;
966
1050
  if (!browser) throw new Error("BrowserConnector has no browser binding");
1051
+ if (_assertClassBrand(_BrowserConnector_brand, this, _isKitesurf).call(this)) throw new Error("Kitesurf does not support Browser Run Live View");
967
1052
  await _assertClassBrand(_BrowserConnector_brand, this, _socket).call(this, executionId);
968
1053
  const sessionId = _classPrivateFieldGet2(_sockets, this).get(executionId)?.browserSessionId;
969
1054
  if (!sessionId) return [];
@@ -993,6 +1078,7 @@ async function _liveViewUrl(executionId, options) {
993
1078
  */
994
1079
  async function _isSpecEvent(method) {
995
1080
  try {
1081
+ if (_assertClassBrand(_BrowserConnector_brand, this, _isKitesurf).call(this)) return false;
996
1082
  const spec = await loadCdpSpec(_classPrivateFieldGet2(_options, this));
997
1083
  const domain = method.split(".")[0];
998
1084
  return spec.domains.some((d) => d.name === domain && d.events.some((e) => e.event === method));
@@ -1036,6 +1122,38 @@ async function _socketInner(executionId) {
1036
1122
  }
1037
1123
  const browser = _classPrivateFieldGet2(_options, this).browser;
1038
1124
  if (!browser) throw new Error("BrowserConnector has no browser binding");
1125
+ if (_assertClassBrand(_BrowserConnector_brand, this, _isKitesurf).call(this)) {
1126
+ const cached = _classPrivateFieldGet2(_sockets, this).get(executionId);
1127
+ if (cached) return cached.session;
1128
+ const key = _assertClassBrand(_BrowserConnector_brand, this, _execKey).call(this, executionId);
1129
+ const lock = await _get_store.call(_assertClassBrand(_BrowserConnector_brand, this)).acquireLock(key);
1130
+ try {
1131
+ if (await _get_store.call(_assertClassBrand(_BrowserConnector_brand, this)).get(key)) throw new Error("Kitesurf's connection was closed and cannot be resumed; start a new execution");
1132
+ const now = Date.now();
1133
+ await _get_store.call(_assertClassBrand(_BrowserConnector_brand, this)).set(key, {
1134
+ sessionId: `${KITESURF_SESSION_PREFIX}${crypto.randomUUID()}`,
1135
+ createdAt: now,
1136
+ updatedAt: now
1137
+ });
1138
+ } finally {
1139
+ await lock.release();
1140
+ }
1141
+ try {
1142
+ const session = await connectBrowser(browser, {
1143
+ browser: "kitesurf",
1144
+ timeoutMs: _classPrivateFieldGet2(_options, this).timeout
1145
+ });
1146
+ _classPrivateFieldGet2(_sockets, this).set(executionId, {
1147
+ session,
1148
+ attached: /* @__PURE__ */ new Map()
1149
+ });
1150
+ return session;
1151
+ } catch (error) {
1152
+ const failed = await _assertClassBrand(_BrowserConnector_brand, this, _readStored).call(this, key);
1153
+ if (failed) await _assertClassBrand(_BrowserConnector_brand, this, _deleteStoredEntry).call(this, key, failed.sessionId);
1154
+ throw error;
1155
+ }
1156
+ }
1039
1157
  const stored = await _assertClassBrand(_BrowserConnector_brand, this, _resolveSession).call(this, executionId);
1040
1158
  const cached = _classPrivateFieldGet2(_sockets, this).get(executionId);
1041
1159
  if (cached?.browserSessionId === stored.sessionId) return cached.session;
@@ -1288,4 +1406,4 @@ async function _closeStoredSession(key) {
1288
1406
  //#endregion
1289
1407
  export { connectUrl as C, CdpSession as S, connectBrowserSession as _, loadCdpSpec as a, getBrowserRecording as b, browserLinks as c, browserScrape as d, browserScreenshot as f, connectBrowser as g, BrowserRenderingError as h, DurableBrowserSessionStore as i, browserMarkdown as l, runQuickAction as m, DEFAULT_EXEC_SWEEP_IDLE_MS as n, browserContent as o, browserSnapshot as p, DEFAULT_SWEEP_IDLE_MS as r, browserExtract as s, BrowserConnector as t, browserPdf as u, createBrowserSession as v, listBrowserTargets as x, deleteBrowserSession as y };
1290
1408
 
1291
- //# sourceMappingURL=connector-KEJnl6e5.js.map
1409
+ //# sourceMappingURL=connector-CptFKzRh.js.map