Skip to content

Commit 7fbb380

Browse files
committed
log callback
1 parent e4a48d7 commit 7fbb380

File tree

7 files changed

+62
-44
lines changed

7 files changed

+62
-44
lines changed

bun.lock

Lines changed: 6 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/magnitude-core/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@isaacdyor/magnitude-core",
3-
"version": "0.2.36",
3+
"version": "0.2.38",
44
"description": "Magnitude e2e testing agent",
55
"publishConfig": {
66
"access": "public"
@@ -67,6 +67,6 @@
6767
"posthog-node": "^5.1.1",
6868
"sharp": "^0.33.5",
6969
"zod": "^4.0.0",
70-
"zod-to-json-schema": "^3.24.5"
70+
"@finom/zod-to-json-schema": "^3.24.11"
7171
}
7272
}

packages/magnitude-core/src/actions/util.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ActionDefinition } from ".";
2-
import { zodToJsonSchema } from "zod-to-json-schema";
2+
import { zodToJsonSchema } from "@finom/zod-to-json-schema";
33
import TypeBuilder from "@/ai/baml_client/type_builder";
44
import { FieldType, ClassBuilder, ClassPropertyBuilder, EnumBuilder, EnumValueBuilder } from "@boundaryml/baml/native";
55
import { z, ZodObject, ZodSchema } from "zod/v3";

packages/magnitude-core/src/agent/browserAgent.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import z, { ZodSchema } from "zod/v3";
77

88
type Schema = z.ZodSchema;
99
import { renderMinimalAccessibilityTree } from "@/web/util";
10-
import { narrateAgent, narrateBrowserAgent } from "./narrator";
10+
import { narrateAgent, narrateBrowserAgent, LogCallback } from "./narrator";
1111
import { PartitionOptions, partitionHtml, MarkdownSerializerOptions, serializeToMarkdown } from 'magnitude-extract';
1212
import EventEmitter from "eventemitter3";
1313
import { retry } from "@/common/retry";
@@ -21,7 +21,7 @@ const DEFAULT_BROWSER_AGENT_TEMP = 0.2;
2121

2222
// Helper function to start a web agent
2323
export async function startBrowserAgent(
24-
options?: AgentOptions & BrowserConnectorOptions & { narrate?: boolean }//StartAgentWithWebOptions = {}
24+
options?: AgentOptions & BrowserConnectorOptions & { onLog?: LogCallback }//StartAgentWithWebOptions = {}
2525
): Promise<BrowserAgent> {
2626
//console.log("sba options:", options);
2727
const { agentOptions, browserOptions } = buildDefaultBrowserAgentOptions({ agentOptions: options ?? {}, browserOptions: options ?? {} });
@@ -31,9 +31,8 @@ export async function startBrowserAgent(
3131
browserOptions: browserOptions,
3232
});
3333

34-
if (options?.narrate || process.env.MAGNITUDE_NARRATE) {
35-
narrateBrowserAgent(agent);
36-
//agent.events.on('actionStarted', (action: any) => { console.log(action) })
34+
if (options?.onLog) {
35+
narrateBrowserAgent(agent, options.onLog);
3736
}
3837

3938
//console.log('starting agent')
Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,31 @@
11
import { Action } from '@/actions/types';
22
import { ActOptions, Agent } from '@/agent';
3-
import { blueBright, bold, cyanBright, gray } from 'ansis';
43
import { BrowserAgent } from './browserAgent';
54
import { z } from 'zod/v3';
65

7-
export function narrateAgent(agent: Agent) {
6+
export type LogEntry =
7+
| { type: 'start'; message: string; timestamp: Date }
8+
| { type: 'stop'; message: string; timestamp: Date; data: {
9+
totalInputTokens: number;
10+
totalOutputTokens: number;
11+
totalCachedWriteInputTokens: number;
12+
totalCachedReadInputTokens: number;
13+
totalInputTokenCost: number;
14+
totalOutputTokenCost: number;
15+
numUniqueModels: number;
16+
modelDescription: string;
17+
}}
18+
| { type: 'thought'; message: string; timestamp: Date }
19+
| { type: 'act'; message: string; timestamp: Date; data: { task: string; options: ActOptions }}
20+
| { type: 'action'; message: string; timestamp: Date; data: { action: Action; actionDefinition: string }}
21+
| { type: 'nav'; message: string; timestamp: Date; data: { url: string }}
22+
| { type: 'extractStarted'; message: string; timestamp: Date; data: { instructions: string; schema: z.ZodSchema }}
23+
| { type: 'extractDone'; message: string; timestamp: Date; data: { instructions: string; result: any }};
24+
25+
export type LogCallback = (logEntry: LogEntry) => void;
26+
27+
28+
export function narrateAgent(agent: Agent, onLog: LogCallback) {
829
let totalInputTokens = 0;
930
let totalOutputTokens = 0;
1031
let totalCachedWriteInputTokens = 0;
@@ -22,56 +43,52 @@ export function narrateAgent(agent: Agent) {
2243
});
2344

2445
agent.events.on('start', () => {
25-
console.log(bold(blueBright(`▶ [start] agent started with ${agent.models.describe()}`)));
46+
const message = `agent started with ${agent.models.describe()}`;
47+
onLog({ type: 'start', message, timestamp: new Date() });
2648
});
2749

2850
agent.events.on('stop', () => {
29-
console.log(bold(blueBright(`■ [stop] agent stopped`)));
30-
31-
console.log(` Total usage: ` + bold`${totalInputTokens + totalCachedWriteInputTokens + totalCachedReadInputTokens}` + ` input tokens` + (totalCachedWriteInputTokens > 0 || totalCachedReadInputTokens > 0 ? ` (${totalCachedWriteInputTokens} cache write, ${totalCachedReadInputTokens} cache read)` : '') + ` / ` + bold`${totalOutputTokens}` + ` output tokens`);
32-
if (totalInputTokenCost > 0 || totalOutputTokenCost > 0) {
33-
if (agent.models.numUniqueModels === 1 && agent.models.describe().startsWith('claude-code')) {
34-
console.log(` Cost: ` + cyanBright`None - using Claude Pro or Max subscription`)
35-
} else {
36-
console.log(` Cost: $${(totalInputTokenCost + totalOutputTokenCost).toFixed(3)}`);
37-
}
38-
}
39-
// Show token usage and cost if available
40-
// if (totalInputTokenCost > 0 || totalOutputTokenCost > 0) {
41-
// console.log(` Total usage: ` + bold`${totalInputTokens}` + ` input tokens (` + `$${totalInputTokenCost.toFixed(3)}` + `)` + ` / ` + bold`${totalOutputTokens}` + ` output tokens (` + `$${totalOutputTokenCost.toFixed(3)}` + `)`);
42-
// } else {
43-
// console.log(` Total usage: ` + bold`${totalInputTokens}` + ` input tokens` + ` / ` + bold`${totalOutputTokens}` + ` output tokens`);
44-
// }
51+
const message = 'agent stopped';
52+
const tokenData = {
53+
totalInputTokens: totalInputTokens + totalCachedWriteInputTokens + totalCachedReadInputTokens,
54+
totalOutputTokens,
55+
totalCachedWriteInputTokens,
56+
totalCachedReadInputTokens,
57+
totalInputTokenCost,
58+
totalOutputTokenCost,
59+
numUniqueModels: agent.models.numUniqueModels,
60+
modelDescription: agent.models.describe()
61+
};
62+
onLog({ type: 'stop', message, data: tokenData, timestamp: new Date() });
4563
});
4664

4765
agent.events.on('thought', (thought: string) => {
48-
console.log(gray`${thought}`);
49-
//console.log(gray`⚙︎ ${thought}`);
66+
onLog({ type: 'thought', message: thought, timestamp: new Date() });
5067
});
5168

5269
agent.events.on('actStarted', (task: string, options: ActOptions) => {
53-
console.log(bold(cyanBright(`◆ [act] ${task}`)));
70+
onLog({ type: 'act', message: `act started: ${task}`, data: { task, options }, timestamp: new Date() });
5471
});
5572

5673
agent.events.on('actionStarted', (action: Action) => {
5774
const actionDefinition = agent.identifyAction(action);
58-
console.log(bold` ${actionDefinition.render(action)}`);
75+
const message = actionDefinition.render(action);
76+
onLog({ type: 'action', message: `action started: ${message}`, data: { action, actionDefinition: actionDefinition.name }, timestamp: new Date() });
5977
});
6078
}
6179

62-
export function narrateBrowserAgent(agent: BrowserAgent) {
63-
narrateAgent(agent);
80+
export function narrateBrowserAgent(agent: BrowserAgent, onLog: LogCallback) {
81+
narrateAgent(agent, onLog);
6482

6583
agent.browserAgentEvents.on('nav', (url: string) => {
66-
console.log(bold(cyanBright`⛓︎ [nav] ${url}`));
84+
onLog({ type: 'nav', message: `navigating to ${url}`, data: { url }, timestamp: new Date() });
6785
});
6886

6987
agent.browserAgentEvents.on('extractStarted', (instructions: string, schema: z.ZodSchema) => {
70-
console.log(bold(cyanBright`⛏ [extract] ${instructions}`));
88+
onLog({ type: 'extractStarted', message: `extract started: ${instructions}`, data: { instructions, schema }, timestamp: new Date() });
7189
});
90+
7291
agent.browserAgentEvents.on('extractDone', (instructions, data) => {
73-
// console.log has a decent default formatter for arbitrary data e.g. objects
74-
console.log(data);
75-
//console.log(blueBright`${JSON.stringify(data, null, 2)}`);
92+
onLog({ type: 'extractDone', message: `extract completed: ${instructions}`, data: { instructions, result: data }, timestamp: new Date() });
7693
});
7794
}

packages/magnitude-mcp/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"dependencies": {
1818
"@modelcontextprotocol/sdk": "^1.9.0",
1919
"zod": "^4.0.0",
20-
"zod-to-json-schema": "^3.24.5"
20+
"@finom/zod-to-json-schema": "^3.24.11"
2121
},
2222
"devDependencies": {
2323
"@types/node": "^20.17.30",

packages/magnitude-mcp/src/schemas.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { z } from 'zod/v3';
2-
import { zodToJsonSchema } from 'zod-to-json-schema';
2+
import { zodToJsonSchema } from '@finom/zod-to-json-schema';
33

44
/**
55
* Schema for initialize_project tool

0 commit comments

Comments
 (0)