@browserbasehq/orca 3.2.0-preview.3 → 3.2.0-preview.4

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 (171) hide show
  1. package/dist/cjs/lib/utils.d.ts +1 -0
  2. package/dist/cjs/lib/utils.js +4 -0
  3. package/dist/cjs/lib/utils.js.map +1 -1
  4. package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js +5 -7
  5. package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
  6. package/dist/cjs/lib/v3/agent/GoogleCUAClient.js +5 -7
  7. package/dist/cjs/lib/v3/agent/GoogleCUAClient.js.map +1 -1
  8. package/dist/cjs/lib/v3/agent/OpenAICUAClient.js +5 -7
  9. package/dist/cjs/lib/v3/agent/OpenAICUAClient.js.map +1 -1
  10. package/dist/cjs/lib/v3/agent/tools/act.js +1 -10
  11. package/dist/cjs/lib/v3/agent/tools/act.js.map +1 -1
  12. package/dist/cjs/lib/v3/agent/tools/ariaTree.js +1 -12
  13. package/dist/cjs/lib/v3/agent/tools/ariaTree.js.map +1 -1
  14. package/dist/cjs/lib/v3/agent/tools/braveSearch.js.map +1 -1
  15. package/dist/cjs/lib/v3/agent/tools/browserbaseSearch.js.map +1 -1
  16. package/dist/cjs/lib/v3/agent/tools/click.js.map +1 -1
  17. package/dist/cjs/lib/v3/agent/tools/clickAndHold.js.map +1 -1
  18. package/dist/cjs/lib/v3/agent/tools/dragAndDrop.js.map +1 -1
  19. package/dist/cjs/lib/v3/agent/tools/extract.js +1 -10
  20. package/dist/cjs/lib/v3/agent/tools/extract.js.map +1 -1
  21. package/dist/cjs/lib/v3/agent/tools/fillFormVision.js.map +1 -1
  22. package/dist/cjs/lib/v3/agent/tools/fillform.js +1 -10
  23. package/dist/cjs/lib/v3/agent/tools/fillform.js.map +1 -1
  24. package/dist/cjs/lib/v3/agent/tools/index.d.ts +2 -2
  25. package/dist/cjs/lib/v3/agent/tools/index.js +53 -5
  26. package/dist/cjs/lib/v3/agent/tools/index.js.map +1 -1
  27. package/dist/cjs/lib/v3/agent/tools/keys.d.ts +1 -1
  28. package/dist/cjs/lib/v3/agent/tools/keys.js.map +1 -1
  29. package/dist/cjs/lib/v3/agent/tools/type.js.map +1 -1
  30. package/dist/cjs/lib/v3/api.js +9 -2
  31. package/dist/cjs/lib/v3/api.js.map +1 -1
  32. package/dist/cjs/lib/v3/flowlogger/EventEmitter.d.ts +7 -0
  33. package/dist/cjs/lib/v3/flowlogger/EventEmitter.js +30 -0
  34. package/dist/cjs/lib/v3/flowlogger/EventEmitter.js.map +1 -0
  35. package/dist/cjs/lib/v3/flowlogger/EventSink.d.ts +44 -0
  36. package/dist/cjs/lib/v3/flowlogger/EventSink.js +217 -0
  37. package/dist/cjs/lib/v3/flowlogger/EventSink.js.map +1 -0
  38. package/dist/cjs/lib/v3/flowlogger/EventStore.d.ts +26 -0
  39. package/dist/cjs/lib/v3/flowlogger/EventStore.js +135 -0
  40. package/dist/cjs/lib/v3/flowlogger/EventStore.js.map +1 -0
  41. package/dist/cjs/lib/v3/flowlogger/FlowLogger.d.ts +99 -0
  42. package/dist/cjs/lib/v3/flowlogger/FlowLogger.js +591 -0
  43. package/dist/cjs/lib/v3/flowlogger/FlowLogger.js.map +1 -0
  44. package/dist/cjs/lib/v3/flowlogger/prettify.d.ts +6 -0
  45. package/dist/cjs/lib/v3/flowlogger/prettify.js +395 -0
  46. package/dist/cjs/lib/v3/flowlogger/prettify.js.map +1 -0
  47. package/dist/cjs/lib/v3/handlers/handlerUtils/actHandlerUtils.js +43 -57
  48. package/dist/cjs/lib/v3/handlers/handlerUtils/actHandlerUtils.js.map +1 -1
  49. package/dist/cjs/lib/v3/handlers/v3AgentHandler.d.ts +0 -4
  50. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +2 -32
  51. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  52. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js +9 -13
  53. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
  54. package/dist/cjs/lib/v3/llm/aisdk.js +11 -17
  55. package/dist/cjs/lib/v3/llm/aisdk.js.map +1 -1
  56. package/dist/cjs/lib/v3/types/public/options.d.ts +7 -0
  57. package/dist/cjs/lib/v3/types/public/options.js.map +1 -1
  58. package/dist/cjs/lib/v3/understudy/cdp.d.ts +3 -12
  59. package/dist/cjs/lib/v3/understudy/cdp.js +134 -21
  60. package/dist/cjs/lib/v3/understudy/cdp.js.map +1 -1
  61. package/dist/cjs/lib/v3/understudy/page.js +28 -18
  62. package/dist/cjs/lib/v3/understudy/page.js.map +1 -1
  63. package/dist/cjs/lib/v3/v3.d.ts +7 -2
  64. package/dist/cjs/lib/v3/v3.js +178 -159
  65. package/dist/cjs/lib/v3/v3.js.map +1 -1
  66. package/dist/cjs/tests/integration/flowLogger.spec.d.ts +1 -0
  67. package/dist/cjs/tests/integration/flowLogger.spec.js +714 -0
  68. package/dist/cjs/tests/integration/flowLogger.spec.js.map +1 -0
  69. package/dist/cjs/tests/integration/testUtils.d.ts +33 -0
  70. package/dist/cjs/tests/integration/testUtils.js +144 -0
  71. package/dist/cjs/tests/integration/testUtils.js.map +1 -1
  72. package/dist/cjs/tests/integration/timeouts.spec.js +112 -2
  73. package/dist/cjs/tests/integration/timeouts.spec.js.map +1 -1
  74. package/dist/cjs/tests/unit/flowlogger-capturing-cdp.test.d.ts +1 -0
  75. package/dist/cjs/tests/unit/flowlogger-capturing-cdp.test.js +95 -0
  76. package/dist/cjs/tests/unit/flowlogger-capturing-cdp.test.js.map +1 -0
  77. package/dist/cjs/tests/unit/flowlogger-capturing-llm.test.d.ts +1 -0
  78. package/dist/cjs/tests/unit/flowlogger-capturing-llm.test.js +43 -0
  79. package/dist/cjs/tests/unit/flowlogger-capturing-llm.test.js.map +1 -0
  80. package/dist/cjs/tests/unit/flowlogger-eventstore.test.d.ts +1 -0
  81. package/dist/cjs/tests/unit/flowlogger-eventstore.test.js +250 -0
  82. package/dist/cjs/tests/unit/flowlogger-eventstore.test.js.map +1 -0
  83. package/dist/esm/lib/utils.d.ts +1 -0
  84. package/dist/esm/lib/utils.js +3 -0
  85. package/dist/esm/lib/utils.js.map +1 -1
  86. package/dist/esm/lib/v3/agent/AnthropicCUAClient.js +5 -7
  87. package/dist/esm/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
  88. package/dist/esm/lib/v3/agent/GoogleCUAClient.js +5 -7
  89. package/dist/esm/lib/v3/agent/GoogleCUAClient.js.map +1 -1
  90. package/dist/esm/lib/v3/agent/OpenAICUAClient.js +5 -7
  91. package/dist/esm/lib/v3/agent/OpenAICUAClient.js.map +1 -1
  92. package/dist/esm/lib/v3/agent/tools/act.js +1 -10
  93. package/dist/esm/lib/v3/agent/tools/act.js.map +1 -1
  94. package/dist/esm/lib/v3/agent/tools/ariaTree.js +1 -12
  95. package/dist/esm/lib/v3/agent/tools/ariaTree.js.map +1 -1
  96. package/dist/esm/lib/v3/agent/tools/braveSearch.js.map +1 -1
  97. package/dist/esm/lib/v3/agent/tools/browserbaseSearch.js.map +1 -1
  98. package/dist/esm/lib/v3/agent/tools/click.js.map +1 -1
  99. package/dist/esm/lib/v3/agent/tools/clickAndHold.js.map +1 -1
  100. package/dist/esm/lib/v3/agent/tools/dragAndDrop.js.map +1 -1
  101. package/dist/esm/lib/v3/agent/tools/extract.js +1 -10
  102. package/dist/esm/lib/v3/agent/tools/extract.js.map +1 -1
  103. package/dist/esm/lib/v3/agent/tools/fillFormVision.js.map +1 -1
  104. package/dist/esm/lib/v3/agent/tools/fillform.js +1 -10
  105. package/dist/esm/lib/v3/agent/tools/fillform.js.map +1 -1
  106. package/dist/esm/lib/v3/agent/tools/index.d.ts +2 -2
  107. package/dist/esm/lib/v3/agent/tools/index.js +53 -5
  108. package/dist/esm/lib/v3/agent/tools/index.js.map +1 -1
  109. package/dist/esm/lib/v3/agent/tools/keys.d.ts +1 -1
  110. package/dist/esm/lib/v3/agent/tools/keys.js.map +1 -1
  111. package/dist/esm/lib/v3/agent/tools/type.js.map +1 -1
  112. package/dist/esm/lib/v3/api.js +9 -2
  113. package/dist/esm/lib/v3/api.js.map +1 -1
  114. package/dist/esm/lib/v3/flowlogger/EventEmitter.d.ts +7 -0
  115. package/dist/esm/lib/v3/flowlogger/EventEmitter.js +26 -0
  116. package/dist/esm/lib/v3/flowlogger/EventEmitter.js.map +1 -0
  117. package/dist/esm/lib/v3/flowlogger/EventSink.d.ts +44 -0
  118. package/dist/esm/lib/v3/flowlogger/EventSink.js +206 -0
  119. package/dist/esm/lib/v3/flowlogger/EventSink.js.map +1 -0
  120. package/dist/esm/lib/v3/flowlogger/EventStore.d.ts +26 -0
  121. package/dist/esm/lib/v3/flowlogger/EventStore.js +127 -0
  122. package/dist/esm/lib/v3/flowlogger/EventStore.js.map +1 -0
  123. package/dist/esm/lib/v3/flowlogger/FlowLogger.d.ts +99 -0
  124. package/dist/esm/lib/v3/flowlogger/FlowLogger.js +583 -0
  125. package/dist/esm/lib/v3/flowlogger/FlowLogger.js.map +1 -0
  126. package/dist/esm/lib/v3/flowlogger/prettify.d.ts +6 -0
  127. package/dist/esm/lib/v3/flowlogger/prettify.js +389 -0
  128. package/dist/esm/lib/v3/flowlogger/prettify.js.map +1 -0
  129. package/dist/esm/lib/v3/handlers/handlerUtils/actHandlerUtils.js +43 -57
  130. package/dist/esm/lib/v3/handlers/handlerUtils/actHandlerUtils.js.map +1 -1
  131. package/dist/esm/lib/v3/handlers/v3AgentHandler.d.ts +0 -4
  132. package/dist/esm/lib/v3/handlers/v3AgentHandler.js +2 -32
  133. package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  134. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js +9 -13
  135. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
  136. package/dist/esm/lib/v3/llm/aisdk.js +11 -17
  137. package/dist/esm/lib/v3/llm/aisdk.js.map +1 -1
  138. package/dist/esm/lib/v3/types/public/options.d.ts +7 -0
  139. package/dist/esm/lib/v3/types/public/options.js.map +1 -1
  140. package/dist/esm/lib/v3/understudy/cdp.d.ts +3 -12
  141. package/dist/esm/lib/v3/understudy/cdp.js +134 -21
  142. package/dist/esm/lib/v3/understudy/cdp.js.map +1 -1
  143. package/dist/esm/lib/v3/understudy/page.js +28 -18
  144. package/dist/esm/lib/v3/understudy/page.js.map +1 -1
  145. package/dist/esm/lib/v3/v3.d.ts +7 -2
  146. package/dist/esm/lib/v3/v3.js +178 -159
  147. package/dist/esm/lib/v3/v3.js.map +1 -1
  148. package/dist/esm/tests/integration/flowLogger.spec.d.ts +1 -0
  149. package/dist/esm/tests/integration/flowLogger.spec.js +712 -0
  150. package/dist/esm/tests/integration/flowLogger.spec.js.map +1 -0
  151. package/dist/esm/tests/integration/testUtils.d.ts +33 -0
  152. package/dist/esm/tests/integration/testUtils.js +138 -0
  153. package/dist/esm/tests/integration/testUtils.js.map +1 -1
  154. package/dist/esm/tests/integration/timeouts.spec.js +112 -2
  155. package/dist/esm/tests/integration/timeouts.spec.js.map +1 -1
  156. package/dist/esm/tests/unit/flowlogger-capturing-cdp.test.d.ts +1 -0
  157. package/dist/esm/tests/unit/flowlogger-capturing-cdp.test.js +93 -0
  158. package/dist/esm/tests/unit/flowlogger-capturing-cdp.test.js.map +1 -0
  159. package/dist/esm/tests/unit/flowlogger-capturing-llm.test.d.ts +1 -0
  160. package/dist/esm/tests/unit/flowlogger-capturing-llm.test.js +41 -0
  161. package/dist/esm/tests/unit/flowlogger-capturing-llm.test.js.map +1 -0
  162. package/dist/esm/tests/unit/flowlogger-eventstore.test.d.ts +1 -0
  163. package/dist/esm/tests/unit/flowlogger-eventstore.test.js +248 -0
  164. package/dist/esm/tests/unit/flowlogger-eventstore.test.js.map +1 -0
  165. package/package.json +3 -1
  166. package/dist/cjs/lib/v3/flowLogger.d.ts +0 -139
  167. package/dist/cjs/lib/v3/flowLogger.js +0 -881
  168. package/dist/cjs/lib/v3/flowLogger.js.map +0 -1
  169. package/dist/esm/lib/v3/flowLogger.d.ts +0 -139
  170. package/dist/esm/lib/v3/flowLogger.js +0 -868
  171. package/dist/esm/lib/v3/flowLogger.js.map +0 -1
@@ -0,0 +1,127 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { JsonlFileEventSink, PrettyLogFileEventSink, PrettyStderrEventSink, ShallowInMemoryEventSink, } from "./EventSink.js";
4
+ import { FlowEvent } from "./FlowLogger.js";
5
+ const DEFAULT_IN_MEMORY_EVENT_LIMIT = 500; // Per-session ancestry window retained by the default shallow query sink.
6
+ const CONFIG_DIR = process.env.BROWSERBASE_CONFIG_DIR || ""; // Base directory for session metadata + file-backed flow logs.
7
+ const FLOW_LOGS_ENABLED = process.env.BROWSERBASE_FLOW_LOGS === "1"; // Force-enables the pretty stderr flow sink even when `verbose !== 2`.
8
+ const SENSITIVE_KEYS = /key|secret|token|api-key|apikey|api_key|password|passwd|pwd|credential|auth/i; // Redacts obvious secrets before session options are written to disk.
9
+ // =============================================================================
10
+ // Filesystem Helpers
11
+ // =============================================================================
12
+ // Redacts secrets before session options are written to `session.json` inside a config-dir-backed session directory.
13
+ function sanitizeOptions(options) {
14
+ const sanitize = (value) => {
15
+ if (typeof value !== "object" || value === null)
16
+ return value;
17
+ if (Array.isArray(value))
18
+ return value.map(sanitize);
19
+ const result = {};
20
+ for (const [key, entry] of Object.entries(value)) {
21
+ result[key] = SENSITIVE_KEYS.test(key) ? "******" : sanitize(entry);
22
+ }
23
+ return result;
24
+ };
25
+ return sanitize({ ...options });
26
+ }
27
+ // Resolves the configured Browserbase config directory used by file sinks.
28
+ export function getConfigDir() {
29
+ return CONFIG_DIR ? path.resolve(CONFIG_DIR) : "";
30
+ }
31
+ // Creates the per-session directory used by file sinks and writes best-effort metadata such as the sanitized `session.json` file and `latest` symlink.
32
+ async function createSessionDir(sessionId, options) {
33
+ const configDir = getConfigDir();
34
+ if (!configDir) {
35
+ return null;
36
+ }
37
+ const sessionDir = path.join(configDir, "sessions", sessionId);
38
+ await fs.promises.mkdir(sessionDir, { recursive: true });
39
+ if (options) {
40
+ await fs.promises.writeFile(path.join(sessionDir, "session.json"), JSON.stringify(sanitizeOptions(options), null, 2), "utf-8");
41
+ }
42
+ const latestLink = path.join(configDir, "sessions", "latest");
43
+ try {
44
+ try {
45
+ await fs.promises.unlink(latestLink);
46
+ }
47
+ catch {
48
+ // ignore missing link
49
+ }
50
+ await fs.promises.symlink(sessionId, latestLink, "dir");
51
+ }
52
+ catch {
53
+ // symlink best effort only
54
+ }
55
+ return sessionDir;
56
+ }
57
+ // =============================================================================
58
+ // Event Store
59
+ // =============================================================================
60
+ // Per-session flow event sink manager.
61
+ // This is not an event bus. V3 forwards already-emitted FlowEvents into it so
62
+ // the store can fan them out to configured sinks, answer `query()` calls from
63
+ // its one query sink, and tear down its sinks when the session closes.
64
+ // We keep this as a separate object instead of wiring sinks directly with
65
+ // `v3.bus.on("*", sink.emit)` because pretty sinks need access to a shared
66
+ // query interface while rendering. Prettified lines often need to look up
67
+ // related parent/child events to recover the readable ancestry tags and labels.
68
+ // Passing sinks into each other to share that state gets messy quickly, so the
69
+ // EventStore contains the circular dependency: all sinks live here, and any
70
+ // sink that needs historical context can call the one `EventStore.query()`
71
+ // entrypoint backed by the main query sink for this session.
72
+ export class EventStore {
73
+ sessionId;
74
+ sinks = new Set(); // All sinks attached for this session; constructor registers them here and `destroy()` tears them down.
75
+ destroyed = false; // Flipped by `destroy()` so later emits and teardown calls become no-ops.
76
+ query; // Always reads from the one query sink chosen at construction time.
77
+ // Creates the per-instance store owned by a single V3 session. This store is intentionally single-session; it ignores events for other session ids.
78
+ constructor(
79
+ // Usually matches `browserbaseSessionId` today, but it is the store's own Stagehand session identifier and may diverge in the future.
80
+ sessionId, options, querySink = new ShallowInMemoryEventSink(DEFAULT_IN_MEMORY_EVENT_LIMIT)) {
81
+ this.sessionId = sessionId;
82
+ const sessionDirPromise = createSessionDir(sessionId, options);
83
+ this.registerSink(querySink);
84
+ this.query = async (query) => {
85
+ if (query.sessionId && query.sessionId !== this.sessionId) {
86
+ return [];
87
+ }
88
+ return querySink.query({
89
+ ...query,
90
+ sessionId: this.sessionId,
91
+ });
92
+ };
93
+ if (getConfigDir()) {
94
+ this.registerSink(new JsonlFileEventSink(sessionDirPromise));
95
+ this.registerSink(new PrettyLogFileEventSink(sessionDirPromise, this));
96
+ }
97
+ if (options?.verbose === 2 || FLOW_LOGS_ENABLED) {
98
+ this.registerSink(new PrettyStderrEventSink(this));
99
+ }
100
+ }
101
+ // Adds a sink to the direct fanout list used by `emit()`.
102
+ registerSink(sink) {
103
+ this.sinks.add(sink);
104
+ }
105
+ // Emits an event to all attached sinks when it belongs to this store's single session.
106
+ emit = async (event) => {
107
+ if (!(event instanceof FlowEvent)) {
108
+ return;
109
+ }
110
+ if (this.destroyed || event.sessionId !== this.sessionId) {
111
+ return;
112
+ }
113
+ await Promise.allSettled([...this.sinks].map((sink) => sink.emit(event)));
114
+ };
115
+ // Tears down all sinks when the V3 instance is closed.
116
+ async destroy() {
117
+ if (this.destroyed) {
118
+ return;
119
+ }
120
+ this.destroyed = true;
121
+ await Promise.all([...this.sinks].map((sink) => sink.destroy().catch(() => {
122
+ // best effort cleanup
123
+ })));
124
+ this.sinks.clear();
125
+ }
126
+ }
127
+ //# sourceMappingURL=EventStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventStore.js","sourceRoot":"","sources":["../../../../../lib/v3/flowlogger/EventStore.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { V3Options } from \"../types/public/index.js\";\nimport {\n EventSink,\n JsonlFileEventSink,\n PrettyLogFileEventSink,\n PrettyStderrEventSink,\n ShallowInMemoryEventSink,\n} from \"./EventSink.js\";\nimport { FlowEvent } from \"./FlowLogger.js\";\n\nconst DEFAULT_IN_MEMORY_EVENT_LIMIT = 500; // Per-session ancestry window retained by the default shallow query sink.\nconst CONFIG_DIR = process.env.BROWSERBASE_CONFIG_DIR || \"\"; // Base directory for session metadata + file-backed flow logs.\nconst FLOW_LOGS_ENABLED = process.env.BROWSERBASE_FLOW_LOGS === \"1\"; // Force-enables the pretty stderr flow sink even when `verbose !== 2`.\nconst SENSITIVE_KEYS =\n /key|secret|token|api-key|apikey|api_key|password|passwd|pwd|credential|auth/i; // Redacts obvious secrets before session options are written to disk.\n\n// =============================================================================\n// Public Contracts\n// =============================================================================\n\nexport interface EventStoreQuery {\n sessionId?: string;\n eventId?: string;\n eventType?: string;\n limit?: number;\n}\n\nexport interface EventStoreApi {\n readonly sessionId: string;\n emit(event: FlowEvent): Promise<void>;\n query(query: EventStoreQuery): Promise<FlowEvent[]>;\n destroy(): Promise<void>;\n}\n\n// =============================================================================\n// Filesystem Helpers\n// =============================================================================\n\n// Redacts secrets before session options are written to `session.json` inside a config-dir-backed session directory.\nfunction sanitizeOptions(options: V3Options): Record<string, unknown> {\n const sanitize = (value: unknown): unknown => {\n if (typeof value !== \"object\" || value === null) return value;\n if (Array.isArray(value)) return value.map(sanitize);\n\n const result: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(value)) {\n result[key] = SENSITIVE_KEYS.test(key) ? \"******\" : sanitize(entry);\n }\n return result;\n };\n\n return sanitize({ ...options }) as Record<string, unknown>;\n}\n\n// Resolves the configured Browserbase config directory used by file sinks.\nexport function getConfigDir(): string {\n return CONFIG_DIR ? path.resolve(CONFIG_DIR) : \"\";\n}\n\n// Creates the per-session directory used by file sinks and writes best-effort metadata such as the sanitized `session.json` file and `latest` symlink.\nasync function createSessionDir(\n sessionId: string,\n options?: V3Options,\n): Promise<string | null> {\n const configDir = getConfigDir();\n if (!configDir) {\n return null;\n }\n\n const sessionDir = path.join(configDir, \"sessions\", sessionId);\n await fs.promises.mkdir(sessionDir, { recursive: true });\n\n if (options) {\n await fs.promises.writeFile(\n path.join(sessionDir, \"session.json\"),\n JSON.stringify(sanitizeOptions(options), null, 2),\n \"utf-8\",\n );\n }\n\n const latestLink = path.join(configDir, \"sessions\", \"latest\");\n try {\n try {\n await fs.promises.unlink(latestLink);\n } catch {\n // ignore missing link\n }\n await fs.promises.symlink(sessionId, latestLink, \"dir\");\n } catch {\n // symlink best effort only\n }\n\n return sessionDir;\n}\n\n// =============================================================================\n// Event Store\n// =============================================================================\n\n// Per-session flow event sink manager.\n// This is not an event bus. V3 forwards already-emitted FlowEvents into it so\n// the store can fan them out to configured sinks, answer `query()` calls from\n// its one query sink, and tear down its sinks when the session closes.\n// We keep this as a separate object instead of wiring sinks directly with\n// `v3.bus.on(\"*\", sink.emit)` because pretty sinks need access to a shared\n// query interface while rendering. Prettified lines often need to look up\n// related parent/child events to recover the readable ancestry tags and labels.\n// Passing sinks into each other to share that state gets messy quickly, so the\n// EventStore contains the circular dependency: all sinks live here, and any\n// sink that needs historical context can call the one `EventStore.query()`\n// entrypoint backed by the main query sink for this session.\nexport class EventStore implements EventStoreApi {\n private readonly sinks = new Set<EventSink>(); // All sinks attached for this session; constructor registers them here and `destroy()` tears them down.\n private destroyed = false; // Flipped by `destroy()` so later emits and teardown calls become no-ops.\n public query: (query: EventStoreQuery) => Promise<FlowEvent[]>; // Always reads from the one query sink chosen at construction time.\n\n // Creates the per-instance store owned by a single V3 session. This store is intentionally single-session; it ignores events for other session ids.\n constructor(\n // Usually matches `browserbaseSessionId` today, but it is the store's own Stagehand session identifier and may diverge in the future.\n public readonly sessionId: string,\n options?: V3Options,\n querySink: EventSink = new ShallowInMemoryEventSink(\n DEFAULT_IN_MEMORY_EVENT_LIMIT,\n ),\n ) {\n const sessionDirPromise = createSessionDir(sessionId, options);\n\n this.registerSink(querySink);\n this.query = async (query) => {\n if (query.sessionId && query.sessionId !== this.sessionId) {\n return [];\n }\n\n return querySink.query({\n ...query,\n sessionId: this.sessionId,\n });\n };\n\n if (getConfigDir()) {\n this.registerSink(new JsonlFileEventSink(sessionDirPromise));\n this.registerSink(new PrettyLogFileEventSink(sessionDirPromise, this));\n }\n\n if (options?.verbose === 2 || FLOW_LOGS_ENABLED) {\n this.registerSink(new PrettyStderrEventSink(this));\n }\n }\n\n // Adds a sink to the direct fanout list used by `emit()`.\n private registerSink(sink: EventSink): void {\n this.sinks.add(sink);\n }\n\n // Emits an event to all attached sinks when it belongs to this store's single session.\n emit = async (event: FlowEvent): Promise<void> => {\n if (!(event instanceof FlowEvent)) {\n return;\n }\n\n if (this.destroyed || event.sessionId !== this.sessionId) {\n return;\n }\n\n await Promise.allSettled([...this.sinks].map((sink) => sink.emit(event)));\n };\n\n // Tears down all sinks when the V3 instance is closed.\n async destroy(): Promise<void> {\n if (this.destroyed) {\n return;\n }\n\n this.destroyed = true;\n await Promise.all(\n [...this.sinks].map((sink) =>\n sink.destroy().catch(() => {\n // best effort cleanup\n }),\n ),\n );\n this.sinks.clear();\n }\n}\n"]}
@@ -0,0 +1,99 @@
1
+ import type { LanguageModelMiddleware } from "ai";
2
+ import { z } from "zod";
3
+ import { EventEmitterWithWildcardSupport } from "./EventEmitter.js";
4
+ export declare const FlowEventDataSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
5
+ export declare const FlowEventInputSchema: z.ZodObject<{
6
+ eventType: z.ZodString;
7
+ eventId: z.ZodOptional<z.ZodString>;
8
+ eventParentIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
9
+ eventCreatedAt: z.ZodOptional<z.ZodString>;
10
+ sessionId: z.ZodOptional<z.ZodString>;
11
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
12
+ }, z.core.$strip>;
13
+ export type FlowEventData = z.infer<typeof FlowEventDataSchema>;
14
+ export type FlowEventInput = z.input<typeof FlowEventInputSchema>;
15
+ type FlowEventFields = Omit<FlowEventInput, "eventId" | "eventParentIds" | "eventCreatedAt" | "sessionId" | "data"> & {
16
+ eventId: string;
17
+ eventParentIds: string[];
18
+ eventCreatedAt: string;
19
+ sessionId: string;
20
+ data: FlowEventData;
21
+ };
22
+ export declare class FlowEvent implements FlowEventFields {
23
+ private static deriveEventIdSuffix;
24
+ static createEventId(eventType: string): string;
25
+ eventType: string;
26
+ eventId: string;
27
+ eventParentIds: string[];
28
+ eventCreatedAt: string;
29
+ sessionId: string;
30
+ data: FlowEventData;
31
+ constructor(input: FlowEventInput);
32
+ }
33
+ export interface FlowLoggerContext {
34
+ sessionId: string;
35
+ eventBus: EventEmitterWithWildcardSupport;
36
+ parentEvents: FlowEvent[];
37
+ }
38
+ type AsyncOriginalMethod<TArgs extends unknown[] = unknown[], TResult = unknown, TThis = unknown> = (this: TThis, ...args: TArgs) => Promise<TResult>;
39
+ type FlowLoggerLogOptions = FlowEventInput & {
40
+ context?: FlowLoggerContext;
41
+ };
42
+ export declare class FlowLogger {
43
+ private static cloneContext;
44
+ private static resolveReentryContext;
45
+ private static emit;
46
+ private static runWithAutoStatusEventLogging;
47
+ private static logCdpEvent;
48
+ private static emitLlmEvent;
49
+ private static buildMiddlewarePromptSummary;
50
+ private static buildMiddlewareOutputSummary;
51
+ static init(sessionId: string, eventBus: EventEmitterWithWildcardSupport): FlowLoggerContext;
52
+ static close(context?: FlowLoggerContext | null): Promise<void>;
53
+ static get currentContext(): FlowLoggerContext;
54
+ static resolveContext(fallbackContext?: FlowLoggerContext | null): FlowLoggerContext | null;
55
+ static wrapWithLogging<TMethod extends AsyncOriginalMethod>(options: FlowLoggerLogOptions): <TWrappedMethod extends AsyncOriginalMethod<Parameters<TMethod>, Awaited<ReturnType<TMethod>>, ThisParameterType<TMethod>>>(originalMethod: TWrappedMethod) => TWrappedMethod;
56
+ static runWithLogging<TMethod extends AsyncOriginalMethod>(options: FlowLoggerLogOptions, originalMethod: TMethod, params: Readonly<Parameters<TMethod>>): Promise<Awaited<ReturnType<TMethod>>>;
57
+ static runWithLogging<TResult>(options: FlowLoggerLogOptions, originalMethod: AsyncOriginalMethod<[], TResult>, params: ReadonlyArray<unknown>): Promise<Awaited<TResult>>;
58
+ static withContext<T>(context: FlowLoggerContext, fn: () => T): T;
59
+ private static readonly NOISY_CDP_EVENTS;
60
+ static logCdpCallEvent(context: FlowLoggerContext, data: {
61
+ method: string;
62
+ params?: object;
63
+ targetId?: string | null;
64
+ }): FlowEvent | null;
65
+ static logCdpResponseEvent(context: FlowLoggerContext, parentEvent: Pick<FlowEvent, "eventId" | "eventParentIds">, data: {
66
+ method: string;
67
+ result?: unknown;
68
+ error?: string;
69
+ targetId?: string | null;
70
+ }): void;
71
+ static logCdpMessageEvent(context: FlowLoggerContext, parentEvent: Pick<FlowEvent, "eventId" | "eventParentIds">, data: {
72
+ method: string;
73
+ params?: unknown;
74
+ targetId?: string | null;
75
+ }): void;
76
+ static logLlmRequest({ requestId, model, prompt, }: {
77
+ requestId: string;
78
+ model: string;
79
+ prompt?: string;
80
+ }): void;
81
+ static logLlmResponse({ requestId, model, output, inputTokens, outputTokens, }: {
82
+ requestId: string;
83
+ model: string;
84
+ output?: string;
85
+ inputTokens?: number;
86
+ outputTokens?: number;
87
+ }): void;
88
+ static createLlmLoggingMiddleware(modelId: string): Pick<LanguageModelMiddleware, "wrapGenerate">;
89
+ }
90
+ export declare function extractLlmPromptSummary(messages: Array<{
91
+ role: string;
92
+ content: unknown;
93
+ }>, options?: {
94
+ toolCount?: number;
95
+ hasSchema?: boolean;
96
+ }): string | undefined;
97
+ export declare function extractLlmCuaPromptSummary(messages: unknown[]): string | undefined;
98
+ export declare function extractLlmCuaResponseSummary(output: unknown): string;
99
+ export {};