@ddwang/magnitude-core 0.3.1-ddwang.1

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 (142) hide show
  1. package/dist/actions/desktopActions.d.ts +58 -0
  2. package/dist/actions/desktopActions.js +154 -0
  3. package/dist/actions/index.d.ts +26 -0
  4. package/dist/actions/index.js +11 -0
  5. package/dist/actions/taskActions.d.ts +8 -0
  6. package/dist/actions/taskActions.js +27 -0
  7. package/dist/actions/types.d.ts +31 -0
  8. package/dist/actions/types.js +5 -0
  9. package/dist/actions/util.d.ts +20 -0
  10. package/dist/actions/util.js +297 -0
  11. package/dist/actions/webActions.d.ts +79 -0
  12. package/dist/actions/webActions.js +190 -0
  13. package/dist/agent/browserAgent.d.ts +29 -0
  14. package/dist/agent/browserAgent.js +122 -0
  15. package/dist/agent/errors.d.ts +8 -0
  16. package/dist/agent/errors.js +68 -0
  17. package/dist/agent/index.d.ts +53 -0
  18. package/dist/agent/index.js +377 -0
  19. package/dist/agent/narrator.d.ts +4 -0
  20. package/dist/agent/narrator.js +63 -0
  21. package/dist/agent/pause.test.d.ts +1 -0
  22. package/dist/agent/pause.test.js +194 -0
  23. package/dist/ai/baml_client/async_client.d.ts +73 -0
  24. package/dist/ai/baml_client/async_client.js +152 -0
  25. package/dist/ai/baml_client/async_request.d.ts +35 -0
  26. package/dist/ai/baml_client/async_request.js +98 -0
  27. package/dist/ai/baml_client/config.d.ts +11 -0
  28. package/dist/ai/baml_client/config.js +20 -0
  29. package/dist/ai/baml_client/globals.d.ts +16 -0
  30. package/dist/ai/baml_client/globals.js +37 -0
  31. package/dist/ai/baml_client/index.d.ts +16 -0
  32. package/dist/ai/baml_client/index.js +41 -0
  33. package/dist/ai/baml_client/inlinedbaml.d.ts +19 -0
  34. package/dist/ai/baml_client/inlinedbaml.js +31 -0
  35. package/dist/ai/baml_client/parser.d.ts +53 -0
  36. package/dist/ai/baml_client/parser.js +86 -0
  37. package/dist/ai/baml_client/partial_types.d.ts +61 -0
  38. package/dist/ai/baml_client/partial_types.js +10 -0
  39. package/dist/ai/baml_client/sync_client.d.ts +50 -0
  40. package/dist/ai/baml_client/sync_client.js +100 -0
  41. package/dist/ai/baml_client/sync_request.d.ts +35 -0
  42. package/dist/ai/baml_client/sync_request.js +98 -0
  43. package/dist/ai/baml_client/tracing.d.ts +16 -0
  44. package/dist/ai/baml_client/tracing.js +18 -0
  45. package/dist/ai/baml_client/type_builder.d.ts +38 -0
  46. package/dist/ai/baml_client/type_builder.js +96 -0
  47. package/dist/ai/baml_client/types.d.ts +69 -0
  48. package/dist/ai/baml_client/types.js +15 -0
  49. package/dist/ai/claudeCode.d.ts +1 -0
  50. package/dist/ai/claudeCode.js +186 -0
  51. package/dist/ai/modelHarness.d.ts +39 -0
  52. package/dist/ai/modelHarness.js +189 -0
  53. package/dist/ai/multiModelHarness.d.ts +27 -0
  54. package/dist/ai/multiModelHarness.js +52 -0
  55. package/dist/ai/types.d.ts +90 -0
  56. package/dist/ai/types.js +5 -0
  57. package/dist/ai/util.d.ts +13 -0
  58. package/dist/ai/util.js +165 -0
  59. package/dist/cli.d.ts +0 -0
  60. package/dist/cli.js +3 -0
  61. package/dist/common/actions.d.ts +0 -0
  62. package/dist/common/actions.js +14 -0
  63. package/dist/common/events.d.ts +15 -0
  64. package/dist/common/events.js +3 -0
  65. package/dist/common/failure.d.ts +68 -0
  66. package/dist/common/failure.js +1 -0
  67. package/dist/common/index.d.ts +3 -0
  68. package/dist/common/index.js +3 -0
  69. package/dist/common/retry.d.ts +16 -0
  70. package/dist/common/retry.js +30 -0
  71. package/dist/common/util.d.ts +23 -0
  72. package/dist/common/util.js +132 -0
  73. package/dist/connectors/browserConnector.d.ts +40 -0
  74. package/dist/connectors/browserConnector.js +127 -0
  75. package/dist/connectors/desktopConnector.d.ts +58 -0
  76. package/dist/connectors/desktopConnector.js +68 -0
  77. package/dist/connectors/index.d.ts +10 -0
  78. package/dist/connectors/index.js +2 -0
  79. package/dist/index.cjs +6143 -0
  80. package/dist/index.d.cts +825 -0
  81. package/dist/index.d.ts +20 -0
  82. package/dist/index.js +26 -0
  83. package/dist/index.mjs +6097 -0
  84. package/dist/logger.d.ts +3 -0
  85. package/dist/logger.js +15 -0
  86. package/dist/memory/agentMemory.d.ts +37 -0
  87. package/dist/memory/agentMemory.js +121 -0
  88. package/dist/memory/image.d.ts +26 -0
  89. package/dist/memory/image.js +106 -0
  90. package/dist/memory/index.d.ts +3 -0
  91. package/dist/memory/index.js +3 -0
  92. package/dist/memory/masking.d.ts +7 -0
  93. package/dist/memory/masking.js +141 -0
  94. package/dist/memory/masking.test.d.ts +1 -0
  95. package/dist/memory/masking.test.js +117 -0
  96. package/dist/memory/observation.d.ts +38 -0
  97. package/dist/memory/observation.js +79 -0
  98. package/dist/memory/rendering/index.d.ts +10 -0
  99. package/dist/memory/rendering/index.js +13 -0
  100. package/dist/memory/rendering/renderJsonParts.d.ts +3 -0
  101. package/dist/memory/rendering/renderJsonParts.js +115 -0
  102. package/dist/memory/rendering/renderJsonParts.test.d.ts +1 -0
  103. package/dist/memory/rendering/renderJsonParts.test.js +217 -0
  104. package/dist/memory/rendering/renderXmlParts.d.ts +7 -0
  105. package/dist/memory/rendering/renderXmlParts.js +127 -0
  106. package/dist/memory/serde.d.ts +20 -0
  107. package/dist/memory/serde.js +81 -0
  108. package/dist/memory/util.d.ts +2 -0
  109. package/dist/memory/util.js +17 -0
  110. package/dist/telemetry/events.d.ts +9 -0
  111. package/dist/telemetry/events.js +80 -0
  112. package/dist/telemetry/index.d.ts +6 -0
  113. package/dist/telemetry/index.js +91 -0
  114. package/dist/types.d.ts +30 -0
  115. package/dist/types.js +1 -0
  116. package/dist/util.d.ts +1 -0
  117. package/dist/util.js +12 -0
  118. package/dist/version.d.ts +1 -0
  119. package/dist/version.js +3 -0
  120. package/dist/web/browserProvider.d.ts +23 -0
  121. package/dist/web/browserProvider.js +153 -0
  122. package/dist/web/harness.d.ts +102 -0
  123. package/dist/web/harness.js +340 -0
  124. package/dist/web/stability.d.ts +57 -0
  125. package/dist/web/stability.js +316 -0
  126. package/dist/web/tabs.d.ts +58 -0
  127. package/dist/web/tabs.js +293 -0
  128. package/dist/web/transformer.d.ts +7 -0
  129. package/dist/web/transformer.js +41 -0
  130. package/dist/web/types.d.ts +32 -0
  131. package/dist/web/types.js +2 -0
  132. package/dist/web/util.d.ts +3 -0
  133. package/dist/web/util.js +81 -0
  134. package/dist/web/visualizer/cursor.d.ts +16 -0
  135. package/dist/web/visualizer/cursor.js +152 -0
  136. package/dist/web/visualizer/index.d.ts +22 -0
  137. package/dist/web/visualizer/index.js +47 -0
  138. package/dist/web/visualizer/mouseEffects.d.ts +18 -0
  139. package/dist/web/visualizer/mouseEffects.js +287 -0
  140. package/dist/web/visualizer/typeEffects.d.ts +10 -0
  141. package/dist/web/visualizer/typeEffects.js +190 -0
  142. package/package.json +71 -0
@@ -0,0 +1,90 @@
1
+ export type BrowserAgentRole = 'act' | 'extract' | 'query';
2
+ export declare const allBrowserAgentRoles: BrowserAgentRole[];
3
+ export type LLMClient = (AnthropicClient | ClaudeCodeClient | BedrockClient | GoogleAIClient | GoogleVertexClient | OpenAIClient | OpenAIGenericClient | AzureOpenAIClient) & {
4
+ roles?: BrowserAgentRole[];
5
+ };
6
+ export interface AnthropicClient {
7
+ provider: 'anthropic';
8
+ options: {
9
+ model: string;
10
+ apiKey?: string;
11
+ temperature?: number;
12
+ promptCaching?: boolean;
13
+ };
14
+ }
15
+ export interface ClaudeCodeClient {
16
+ provider: 'claude-code';
17
+ options: {
18
+ model: string;
19
+ temperature?: number;
20
+ promptCaching?: boolean;
21
+ };
22
+ }
23
+ export interface BedrockClient {
24
+ provider: 'aws-bedrock';
25
+ options: {
26
+ model: string;
27
+ temperature?: number;
28
+ };
29
+ }
30
+ export interface GoogleAIClient {
31
+ provider: 'google-ai';
32
+ options: {
33
+ model: string;
34
+ apiKey?: string;
35
+ temperature?: number;
36
+ baseUrl?: string;
37
+ };
38
+ }
39
+ export interface GoogleVertexClient {
40
+ provider: 'vertex-ai';
41
+ options: {
42
+ model: string;
43
+ location?: string;
44
+ baseUrl?: string;
45
+ projectId?: string;
46
+ credentials?: string | object;
47
+ anthropicVersion?: string;
48
+ temperature?: number;
49
+ };
50
+ }
51
+ export interface OpenAIClient {
52
+ provider: 'openai';
53
+ options: {
54
+ model: string;
55
+ apiKey?: string;
56
+ temperature?: number;
57
+ };
58
+ }
59
+ export interface AzureOpenAIClient {
60
+ provider: 'azure-openai';
61
+ options: {
62
+ resourceName: string;
63
+ deploymentId: string;
64
+ apiVersion: string;
65
+ apiKey: string;
66
+ };
67
+ }
68
+ export interface OpenAIGenericClient {
69
+ provider: 'openai-generic';
70
+ options: {
71
+ model: string;
72
+ baseUrl: string;
73
+ apiKey?: string;
74
+ temperature?: number;
75
+ headers?: Record<string, string>;
76
+ };
77
+ }
78
+ export interface LLMClientIdentifier {
79
+ provider: string;
80
+ model: string;
81
+ }
82
+ export interface ModelUsage {
83
+ llm: LLMClientIdentifier;
84
+ inputTokens: number;
85
+ outputTokens: number;
86
+ cacheWriteInputTokens?: number;
87
+ cacheReadInputTokens?: number;
88
+ inputCost?: number;
89
+ outputCost?: number;
90
+ }
@@ -0,0 +1,5 @@
1
+ // export interface CheckResult {
2
+ // passed: boolean,
3
+ // confidence: number
4
+ // }
5
+ export const allBrowserAgentRoles = ['act', 'extract', 'query'];
@@ -0,0 +1,13 @@
1
+ import { type LLMClient } from '@/ai/types';
2
+ import { AgentOptions } from "@/agent";
3
+ import { BrowserConnectorOptions } from "@/connectors/browserConnector";
4
+ export declare function convertToBamlClientOptions(client: LLMClient): Promise<Record<string, any>>;
5
+ export declare function tryDeriveUIGroundedClient(): LLMClient | null;
6
+ export declare function isClaude(llm: LLMClient): boolean;
7
+ export declare function buildDefaultBrowserAgentOptions({ agentOptions, browserOptions }: {
8
+ agentOptions: AgentOptions;
9
+ browserOptions: BrowserConnectorOptions;
10
+ }): {
11
+ agentOptions: AgentOptions;
12
+ browserOptions: BrowserConnectorOptions;
13
+ };
@@ -0,0 +1,165 @@
1
+ import { completeClaudeCodeAuthFlow } from './claudeCode';
2
+ function cleanNestedObject(obj) {
3
+ // Remove null/undefined key values entirely
4
+ return Object.fromEntries(Object.entries(obj)
5
+ // Filter out null/undefined values
6
+ .filter(([_, value]) => value !== null && value !== undefined)
7
+ // Process nested objects recursively
8
+ .map(([key, value]) => [
9
+ key,
10
+ typeof value === 'object' ? cleanNestedObject(value) : value
11
+ ]));
12
+ }
13
+ export async function convertToBamlClientOptions(client) {
14
+ // extract options compatible with https://docs.boundaryml.com/ref/llm-client-providers/overview
15
+ // Default to temperature 0.0
16
+ // Some client options (e.g. azure) do not have a temperature setting
17
+ const temp = 'temperature' in client.options ?
18
+ (client.options.temperature ?? 0.0) : 0.0;
19
+ let options;
20
+ if (client.provider === 'claude-code') {
21
+ // Special case - oauth with claude code max anthropic account
22
+ const oauthToken = await completeClaudeCodeAuthFlow();
23
+ options = {
24
+ model: client.options.model,
25
+ temperature: temp,
26
+ headers: {
27
+ 'Authorization': `Bearer ${oauthToken}`,
28
+ 'anthropic-beta': 'oauth-2025-04-20' + (client.options.promptCaching ? ',prompt-caching-2024-07-31' : ''),
29
+ // Overrides this header from being automatically derived from ANTHROPIC_API_KEY
30
+ 'X-API-Key': ''
31
+ },
32
+ ...(client.options.promptCaching ? { allowed_role_metadata: "all" } : {}),
33
+ };
34
+ }
35
+ else if (client.provider === 'anthropic') {
36
+ options = {
37
+ api_key: client.options.apiKey,
38
+ model: client.options.model,
39
+ temperature: temp,
40
+ ...(client.options.promptCaching ? {
41
+ allowed_role_metadata: "all",
42
+ headers: { 'anthropic-beta': 'prompt-caching-2024-07-31' }
43
+ } : {}),
44
+ };
45
+ }
46
+ else if (client.provider === 'aws-bedrock') {
47
+ options = {
48
+ model_id: client.options.model,
49
+ inference_configuration: {
50
+ temperature: temp,
51
+ }
52
+ };
53
+ }
54
+ else if (client.provider === 'google-ai') {
55
+ options = {
56
+ base_url: client.options.baseUrl,
57
+ model: client.options.model,
58
+ api_key: client.options.apiKey,
59
+ generationConfig: {
60
+ temperature: temp,
61
+ //thinking_budget: 0
62
+ }
63
+ };
64
+ }
65
+ else if (client.provider === 'vertex-ai') {
66
+ options = {
67
+ location: client.options.location,
68
+ base_url: client.options.baseUrl,
69
+ project_id: client.options.projectId,
70
+ credentials: client.options.credentials,
71
+ anthropic_version: client.options.anthropicVersion,
72
+ model: client.options.model,
73
+ // generationConfig: {
74
+ // temperature: temp,
75
+ // }
76
+ };
77
+ }
78
+ else if (client.provider === 'openai') {
79
+ options = {
80
+ api_key: client.options.apiKey,
81
+ model: client.options.model,
82
+ temperature: temp,
83
+ };
84
+ }
85
+ else if (client.provider === 'openai-generic') {
86
+ options = {
87
+ base_url: client.options.baseUrl,
88
+ api_key: client.options.apiKey,
89
+ model: client.options.model,
90
+ temperature: temp,
91
+ headers: {
92
+ "HTTP-Referer": "https://magnitude.run",
93
+ "X-Title": "Magnitude",
94
+ ...client.options.headers
95
+ }
96
+ };
97
+ }
98
+ else if (client.provider === 'azure-openai') {
99
+ options = {
100
+ resource_name: client.options.resourceName,
101
+ deployment_id: client.options.deploymentId,
102
+ api_version: client.options.apiVersion,
103
+ api_key: client.options.apiKey
104
+ };
105
+ }
106
+ else {
107
+ throw new Error(`Invalid provider: ${client.provider}`);
108
+ }
109
+ return cleanNestedObject(options);
110
+ }
111
+ export function tryDeriveUIGroundedClient() {
112
+ if (process.env.ANTHROPIC_API_KEY) {
113
+ return {
114
+ provider: 'anthropic',
115
+ options: {
116
+ // TODO: do more testing on best claude model for visuals
117
+ // model: 'claude-3-5-sonnet-20240620', // <- definitely not, pre computer use
118
+ // model: 'claude-3-5-sonnet-20241022', // <- not great on rescaling res
119
+ //model: 'claude-3-7-sonnet-latest', // <- underplans
120
+ // model: 'claude-sonnet-4-20250514', // <- underplans, also supposedly worse at visual reasoning
121
+ model: 'claude-haiku-4-5-20251001', // <- fast, cost-effective, good performance
122
+ apiKey: process.env.ANTHROPIC_API_KEY
123
+ }
124
+ };
125
+ }
126
+ else {
127
+ return null;
128
+ }
129
+ }
130
+ export function isClaude(llm) {
131
+ if ('model' in llm.options) { //if (llm.provider === 'anthropic' || llm.provider === 'aws-bedrock' || llm.provider === 'vertex-ai') {
132
+ const model = llm.options.model;
133
+ if (model.includes('claude'))
134
+ return true;
135
+ }
136
+ return false;
137
+ }
138
+ const DEFAULT_BROWSER_AGENT_TEMP = 0.2;
139
+ export function buildDefaultBrowserAgentOptions({ agentOptions, browserOptions }) {
140
+ /**
141
+ * Given any provided options for agent or browser connector, fill out additional key fields using environment,
142
+ * or any model-specific constraints (e.g. Claude needing 1024x768 virtual screen space)
143
+ */
144
+ const envLlm = tryDeriveUIGroundedClient();
145
+ let llms = agentOptions.llm ? (Array.isArray(agentOptions.llm) ? agentOptions.llm : [agentOptions.llm]) : (envLlm ? [envLlm] : []);
146
+ if (llms.length == 0) {
147
+ throw new Error("No LLM configured or available from environment. Set environment variable ANTHROPIC_API_KEY and try again. See https://docs.magnitude.run/customizing/llm-configuration for details");
148
+ }
149
+ // Set reasonable temp if not provided
150
+ let virtualScreenDimensions = null;
151
+ for (const llm of llms) {
152
+ let llmOptions = { temperature: DEFAULT_BROWSER_AGENT_TEMP, ...(llm?.options ?? {}) };
153
+ //let modifiedLlm = {...llm, options: llmOptions as any }
154
+ llm.options = llmOptions;
155
+ if (isClaude(llm)) {
156
+ // Claude only really works on 1024x768 screenshots
157
+ // if any model is claude, use virtual screen dimensions
158
+ virtualScreenDimensions = { width: 1024, height: 768 };
159
+ }
160
+ }
161
+ return {
162
+ agentOptions: { ...agentOptions, llm: llms },
163
+ browserOptions: { ...browserOptions, virtualScreenDimensions: virtualScreenDimensions ?? undefined }
164
+ };
165
+ }
package/dist/cli.d.ts ADDED
File without changes
package/dist/cli.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
File without changes
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ // import { ClickWebAction, NavigateWebAction, ScrollWebAction, SwitchTabWebAction, TypeWebAction } from "@/web/types";
3
+ // import { ClickIntent, TypeIntent, ScrollIntent, SwitchTabIntent, Action } from "@/actions/types";
4
+ // //'load' | 'click' | 'hover' | 'type' | 'scroll' | 'wait' | 'back';
5
+ // // move somewhere else, to action types, why is this here
6
+ // export type ActionDescriptor = Action & { screenshot: string };
7
+ // // export type ActionDescriptor = NavigateActionDescriptor | ClickActionDescriptor | TypeActionDescriptor | ScrollActionDescriptor | SwitchTabDescriptor;
8
+ // // export type ActionVariant = ActionDescriptor['variant'];
9
+ // // export type NavigateActionDescriptor = NavigateWebAction & { screenshot: string };
10
+ // // export type ClickActionDescriptor = ClickIntent & ClickWebAction & { screenshot: string };
11
+ // // export type TypeActionDescriptor = TypeIntent & TypeWebAction & { screenshot: string };
12
+ // // export type ScrollActionDescriptor = ScrollIntent & ScrollWebAction & { screenshot: string };
13
+ // // export type SwitchTabDescriptor = SwitchTabIntent & SwitchTabWebAction & { screenshot: string };
14
+ // //const a: ClickActionDescriptor = { variant: 'click', x: 1, y: 2, target: ''}
@@ -0,0 +1,15 @@
1
+ import { Action } from "@/actions/types";
2
+ import { ActOptions } from "@/agent";
3
+ import { ModelUsage } from "@/ai/types";
4
+ export interface AgentEvents {
5
+ 'start': () => void;
6
+ 'stop': () => void;
7
+ 'thought': (thought: string) => void;
8
+ 'actStarted': (task: string, options: ActOptions) => void;
9
+ 'actDone': (task: string, options: ActOptions) => void;
10
+ 'actionStarted': (action: Action) => void;
11
+ 'actionDone': (action: Action) => void;
12
+ 'pause': () => void;
13
+ 'resume': () => void;
14
+ 'tokensUsed': (usage: ModelUsage) => void;
15
+ }
@@ -0,0 +1,3 @@
1
+ // Common interfaces that can be used anywhere
2
+ // Goal is not to expose internals but provide all necessary info in events
3
+ export {};
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Represents any reason why a test case could have failed, for example:
3
+ * - Step could not be completed
4
+ * - Check did not pass
5
+ * - Could not navigate to starting URL
6
+ * - Time or action based timeout
7
+ * - Operation cancelled by signal
8
+ * - ...
9
+ */
10
+ export type FailureDescriptor = BugDetectedFailure | MisalignmentFailure | NetworkFailure | BrowserFailure | RateLimitFailure | ApiKeyFailure | UnknownFailure | CancelledFailure;
11
+ export type BugSeverity = 'critical' | 'high' | 'medium' | 'low';
12
+ /**
13
+ * Step and check failures are classified into one of:
14
+ * BugDetectedFailure: seems to be something wrong with the application itself
15
+ * MisalignmentFailure: seems to be a discrepency between the test case and the interface
16
+ * OR the agent did not properly recognize the relationship between test case and interface
17
+ */
18
+ export interface BugDetectedFailure {
19
+ variant: 'bug';
20
+ title: string;
21
+ expectedResult: string;
22
+ actualResult: string;
23
+ severity: BugSeverity;
24
+ }
25
+ export interface MisalignmentFailure {
26
+ /**
27
+ * Major misalignment: when a step/check fails due to:
28
+ * 1. Poorly written step/check that is completely unrelated to the interface
29
+ * 2. Or interface has changed so much that step/check no longer applicable
30
+ * 3. Planner did not do good enough job adjusting recipe for minor misalignment
31
+ * Misalignment could be due to a poorly written test case OR bad agent behavior.
32
+ */
33
+ variant: 'misalignment';
34
+ message: string;
35
+ }
36
+ export interface NetworkFailure {
37
+ /**
38
+ * For example, failure to connect to starting URL, or any other network errors
39
+ * that would completely prevent the test from executing.
40
+ */
41
+ variant: 'network';
42
+ message: string;
43
+ }
44
+ export interface BrowserFailure {
45
+ /**
46
+ * E.g. something goes wrong with playwright interactions, any DOM manipulation, etc.
47
+ */
48
+ variant: 'browser';
49
+ message: string;
50
+ }
51
+ export interface RateLimitFailure {
52
+ variant: 'rate_limit';
53
+ message: string;
54
+ }
55
+ export interface ApiKeyFailure {
56
+ variant: 'api_key';
57
+ message: string;
58
+ }
59
+ export interface UnknownFailure {
60
+ variant: 'unknown';
61
+ message: string;
62
+ }
63
+ export interface CancelledFailure {
64
+ /**
65
+ * Operation was cancelled, typically by an AbortSignal from a controlling process (e.g., test runner pool).
66
+ */
67
+ variant: 'cancelled';
68
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export * from './events';
2
+ export * from './failure';
3
+ export * from './util';
@@ -0,0 +1,3 @@
1
+ export * from './events';
2
+ export * from './failure';
3
+ export * from './util';
@@ -0,0 +1,16 @@
1
+ type RetryOptions = {
2
+ retries?: number;
3
+ delay?: number;
4
+ maxDelay?: number;
5
+ exponential?: boolean | number;
6
+ throwOnExhaustion?: boolean;
7
+ retryIf?: (error: Error) => boolean;
8
+ onRetry?: (error: Error, attempt: number) => void;
9
+ };
10
+ export declare function retry<T>(fn: () => Promise<T>, options: RetryOptions & {
11
+ throwOnExhaustion: false;
12
+ }): Promise<T | null>;
13
+ export declare function retry<T>(fn: () => Promise<T>, options?: RetryOptions & {
14
+ throwOnExhaustion?: true;
15
+ }): Promise<T>;
16
+ export {};
@@ -0,0 +1,30 @@
1
+ export async function retry(fn, options = {}) {
2
+ const { retries = 3, delay = 0, maxDelay = Infinity, exponential = false, throwOnExhaustion = true, // Now defaults to true
3
+ retryIf = () => true, onRetry } = options;
4
+ const multiplier = exponential === true ? 2 : exponential || 1;
5
+ for (let attempt = 0; attempt <= retries; attempt++) {
6
+ try {
7
+ return await fn();
8
+ }
9
+ catch (error) {
10
+ if (!(error instanceof Error)) {
11
+ throw new Error(`Non-Error thrown: ${String(error)}`);
12
+ }
13
+ if (attempt === retries || !retryIf(error)) {
14
+ if (throwOnExhaustion) {
15
+ throw error;
16
+ }
17
+ return null;
18
+ }
19
+ if (onRetry) {
20
+ onRetry(error, attempt + 1);
21
+ }
22
+ if (delay > 0) {
23
+ const currentDelay = Math.min(delay * Math.pow(multiplier, attempt), maxDelay);
24
+ await new Promise(resolve => setTimeout(resolve, currentDelay));
25
+ }
26
+ }
27
+ }
28
+ // Unreachable
29
+ return null;
30
+ }
@@ -0,0 +1,23 @@
1
+ export type RetryMode = {
2
+ mode: 'retry_on_partial_message';
3
+ errorSubstrings: string[];
4
+ } | {
5
+ mode: 'retry_all';
6
+ };
7
+ export type RetryParams = {
8
+ retryLimit: number;
9
+ delayMs: number;
10
+ showWarnOnRetry: boolean;
11
+ };
12
+ export type RetryOptions = RetryMode & RetryParams;
13
+ export declare function retryOnErrorIsSuccess<T>(fnToRetry: () => Promise<T>, retryOptions: RetryMode & Partial<RetryParams>): Promise<boolean>;
14
+ export declare function retryOnError<T>(fnToRetry: () => Promise<T>, retryOptions: RetryMode & Partial<RetryParams>): Promise<T>;
15
+ /**
16
+ * Performs a deep comparison between two values to determine if they are equivalent.
17
+ *
18
+ * @param a The first value to compare.
19
+ * @param b The second value to compare.
20
+ * @param cache A WeakMap to handle circular references. Should not be provided by the caller.
21
+ * @returns `true` if the values are deeply equal, `false` otherwise.
22
+ */
23
+ export declare function deepEquals(a: any, b: any, cache?: WeakMap<object, WeakSet<object>>): boolean;
@@ -0,0 +1,132 @@
1
+ import logger from "@/logger";
2
+ export async function retryOnErrorIsSuccess(fnToRetry, retryOptions) {
3
+ try {
4
+ await retryOnError(fnToRetry, retryOptions);
5
+ return true;
6
+ }
7
+ catch (error) {
8
+ return false;
9
+ }
10
+ }
11
+ export async function retryOnError(fnToRetry, retryOptions) {
12
+ let lastError;
13
+ const options = {
14
+ ...retryOptions,
15
+ retryLimit: retryOptions.retryLimit ?? 3,
16
+ delayMs: retryOptions.delayMs ?? 200,
17
+ showWarnOnRetry: retryOptions.showWarnOnRetry ?? false,
18
+ //throw: retryOptions.throw ?? true
19
+ };
20
+ if (options.retryLimit < 0) {
21
+ options.retryLimit = 0;
22
+ }
23
+ for (let attempt = 0; attempt <= options.retryLimit; attempt++) {
24
+ try {
25
+ return await fnToRetry();
26
+ }
27
+ catch (error) {
28
+ lastError = error;
29
+ const errorMessage = String(error?.message ?? error);
30
+ if (options.mode === 'retry_all') {
31
+ if (options.showWarnOnRetry) {
32
+ logger.warn(`Retrying on: ${errorMessage}`);
33
+ }
34
+ }
35
+ else if (options.mode === 'retry_on_partial_message') {
36
+ const includesSubstring = options.errorSubstrings.some((substring) => errorMessage.includes(substring));
37
+ if (includesSubstring) {
38
+ if (options.showWarnOnRetry) {
39
+ logger.warn(`Retrying on: ${errorMessage}`);
40
+ }
41
+ }
42
+ else {
43
+ // Error message does NOT contain the target substring. This error is not retryable.
44
+ throw lastError; // Throw this current error immediately.
45
+ }
46
+ }
47
+ }
48
+ await new Promise((resolve) => setTimeout(resolve, options.delayMs));
49
+ }
50
+ throw lastError;
51
+ //if (options.throw) throw lastError;
52
+ }
53
+ /**
54
+ * Performs a deep comparison between two values to determine if they are equivalent.
55
+ *
56
+ * @param a The first value to compare.
57
+ * @param b The second value to compare.
58
+ * @param cache A WeakMap to handle circular references. Should not be provided by the caller.
59
+ * @returns `true` if the values are deeply equal, `false` otherwise.
60
+ */
61
+ export function deepEquals(a, b, cache = new WeakMap()) {
62
+ // 1. Strict equality check (handles primitives, same object references, null, undefined)
63
+ if (a === b) {
64
+ return true;
65
+ }
66
+ // 2. If a or b is null or not an object, and they weren't ===, they are not equal.
67
+ // (This covers cases like comparing a primitive to an object, or one null and one object)
68
+ if (a == null || typeof a !== 'object' || b == null || typeof b !== 'object') {
69
+ return false;
70
+ }
71
+ // 3. Handle circular references:
72
+ // If we've already started comparing 'a' and 'b' in the current path,
73
+ // assume they are equal to break the cycle.
74
+ if (cache.has(a) && cache.get(a).has(b)) {
75
+ return true;
76
+ }
77
+ // Add to cache before recursive calls
78
+ if (!cache.has(a)) {
79
+ cache.set(a, new WeakSet());
80
+ }
81
+ cache.get(a).add(b);
82
+ // Symmetrically for b -> a to catch cycles like a.c = b; b.c = a;
83
+ if (!cache.has(b)) {
84
+ cache.set(b, new WeakSet());
85
+ }
86
+ cache.get(b).add(a);
87
+ // 4. Handle Dates
88
+ if (a instanceof Date && b instanceof Date) {
89
+ return a.getTime() === b.getTime();
90
+ }
91
+ // 5. Handle Regular Expressions
92
+ if (a instanceof RegExp && b instanceof RegExp) {
93
+ return a.source === b.source && a.flags === b.flags;
94
+ }
95
+ // 6. Handle Arrays
96
+ if (Array.isArray(a) && Array.isArray(b)) {
97
+ if (a.length !== b.length) {
98
+ return false;
99
+ }
100
+ for (let i = 0; i < a.length; i++) {
101
+ if (!deepEquals(a[i], b[i], cache)) {
102
+ return false;
103
+ }
104
+ }
105
+ return true;
106
+ }
107
+ // 7. Handle plain Objects
108
+ // At this point, 'a' and 'b' are objects but not arrays, dates, or regexps.
109
+ // If one is an array and the other an object, they are not equal.
110
+ if (Array.isArray(a) || Array.isArray(b)) {
111
+ return false;
112
+ }
113
+ const keysA = Object.keys(a);
114
+ const keysB = Object.keys(b);
115
+ if (keysA.length !== keysB.length) {
116
+ return false;
117
+ }
118
+ for (const key of keysA) {
119
+ // Check if key exists in B. `Object.keys` only returns own enumerable properties.
120
+ // `hasOwnProperty` is a more robust check if b might have non-enumerable properties from its prototype with the same name.
121
+ // However, since we compare keysA.length and keysB.length, if key is in keysA but not in keysB,
122
+ // lengths would mismatch or the loop over keysB (if we did that) would find a key in B not in A.
123
+ // The most crucial part is `Object.prototype.hasOwnProperty.call(b, key)`
124
+ if (!Object.prototype.hasOwnProperty.call(b, key)) {
125
+ return false;
126
+ }
127
+ if (!deepEquals(a[key], b[key], cache)) {
128
+ return false;
129
+ }
130
+ }
131
+ return true;
132
+ }
@@ -0,0 +1,40 @@
1
+ import { AgentConnector } from ".";
2
+ import { WebHarness } from "@/web/harness";
3
+ import { ActionDefinition } from '@/actions';
4
+ import { BrowserOptions } from "@/web/browserProvider";
5
+ import { TabState } from '@/web/tabs';
6
+ import { Observation } from "@/memory/observation";
7
+ import { Image } from "@/memory/image";
8
+ import { ActionVisualizerOptions } from "@/web/visualizer";
9
+ export interface BrowserConnectorOptions {
10
+ browser?: BrowserOptions;
11
+ url?: string;
12
+ virtualScreenDimensions?: {
13
+ width: number;
14
+ height: number;
15
+ };
16
+ minScreenshots?: number;
17
+ visuals?: ActionVisualizerOptions;
18
+ }
19
+ export interface BrowserConnectorStateData {
20
+ screenshot: Image;
21
+ tabs: TabState;
22
+ }
23
+ export declare class BrowserConnector implements AgentConnector {
24
+ readonly id: string;
25
+ private harness;
26
+ private options;
27
+ private browser?;
28
+ private context;
29
+ private logger;
30
+ constructor(options?: BrowserConnectorOptions);
31
+ onStart(): Promise<void>;
32
+ onStop(): Promise<void>;
33
+ getActionSpace(): ActionDefinition<any>[];
34
+ getHarness(): WebHarness;
35
+ private captureCurrentState;
36
+ transformScreenshot(screenshot: Image): Promise<Image>;
37
+ getLastScreenshot(): Promise<Image>;
38
+ collectObservations(): Promise<Observation[]>;
39
+ getInstructions(): Promise<void | string>;
40
+ }