@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.
- package/dist/actions/desktopActions.d.ts +58 -0
- package/dist/actions/desktopActions.js +154 -0
- package/dist/actions/index.d.ts +26 -0
- package/dist/actions/index.js +11 -0
- package/dist/actions/taskActions.d.ts +8 -0
- package/dist/actions/taskActions.js +27 -0
- package/dist/actions/types.d.ts +31 -0
- package/dist/actions/types.js +5 -0
- package/dist/actions/util.d.ts +20 -0
- package/dist/actions/util.js +297 -0
- package/dist/actions/webActions.d.ts +79 -0
- package/dist/actions/webActions.js +190 -0
- package/dist/agent/browserAgent.d.ts +29 -0
- package/dist/agent/browserAgent.js +122 -0
- package/dist/agent/errors.d.ts +8 -0
- package/dist/agent/errors.js +68 -0
- package/dist/agent/index.d.ts +53 -0
- package/dist/agent/index.js +377 -0
- package/dist/agent/narrator.d.ts +4 -0
- package/dist/agent/narrator.js +63 -0
- package/dist/agent/pause.test.d.ts +1 -0
- package/dist/agent/pause.test.js +194 -0
- package/dist/ai/baml_client/async_client.d.ts +73 -0
- package/dist/ai/baml_client/async_client.js +152 -0
- package/dist/ai/baml_client/async_request.d.ts +35 -0
- package/dist/ai/baml_client/async_request.js +98 -0
- package/dist/ai/baml_client/config.d.ts +11 -0
- package/dist/ai/baml_client/config.js +20 -0
- package/dist/ai/baml_client/globals.d.ts +16 -0
- package/dist/ai/baml_client/globals.js +37 -0
- package/dist/ai/baml_client/index.d.ts +16 -0
- package/dist/ai/baml_client/index.js +41 -0
- package/dist/ai/baml_client/inlinedbaml.d.ts +19 -0
- package/dist/ai/baml_client/inlinedbaml.js +31 -0
- package/dist/ai/baml_client/parser.d.ts +53 -0
- package/dist/ai/baml_client/parser.js +86 -0
- package/dist/ai/baml_client/partial_types.d.ts +61 -0
- package/dist/ai/baml_client/partial_types.js +10 -0
- package/dist/ai/baml_client/sync_client.d.ts +50 -0
- package/dist/ai/baml_client/sync_client.js +100 -0
- package/dist/ai/baml_client/sync_request.d.ts +35 -0
- package/dist/ai/baml_client/sync_request.js +98 -0
- package/dist/ai/baml_client/tracing.d.ts +16 -0
- package/dist/ai/baml_client/tracing.js +18 -0
- package/dist/ai/baml_client/type_builder.d.ts +38 -0
- package/dist/ai/baml_client/type_builder.js +96 -0
- package/dist/ai/baml_client/types.d.ts +69 -0
- package/dist/ai/baml_client/types.js +15 -0
- package/dist/ai/claudeCode.d.ts +1 -0
- package/dist/ai/claudeCode.js +186 -0
- package/dist/ai/modelHarness.d.ts +39 -0
- package/dist/ai/modelHarness.js +189 -0
- package/dist/ai/multiModelHarness.d.ts +27 -0
- package/dist/ai/multiModelHarness.js +52 -0
- package/dist/ai/types.d.ts +90 -0
- package/dist/ai/types.js +5 -0
- package/dist/ai/util.d.ts +13 -0
- package/dist/ai/util.js +165 -0
- package/dist/cli.d.ts +0 -0
- package/dist/cli.js +3 -0
- package/dist/common/actions.d.ts +0 -0
- package/dist/common/actions.js +14 -0
- package/dist/common/events.d.ts +15 -0
- package/dist/common/events.js +3 -0
- package/dist/common/failure.d.ts +68 -0
- package/dist/common/failure.js +1 -0
- package/dist/common/index.d.ts +3 -0
- package/dist/common/index.js +3 -0
- package/dist/common/retry.d.ts +16 -0
- package/dist/common/retry.js +30 -0
- package/dist/common/util.d.ts +23 -0
- package/dist/common/util.js +132 -0
- package/dist/connectors/browserConnector.d.ts +40 -0
- package/dist/connectors/browserConnector.js +127 -0
- package/dist/connectors/desktopConnector.d.ts +58 -0
- package/dist/connectors/desktopConnector.js +68 -0
- package/dist/connectors/index.d.ts +10 -0
- package/dist/connectors/index.js +2 -0
- package/dist/index.cjs +6143 -0
- package/dist/index.d.cts +825 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +26 -0
- package/dist/index.mjs +6097 -0
- package/dist/logger.d.ts +3 -0
- package/dist/logger.js +15 -0
- package/dist/memory/agentMemory.d.ts +37 -0
- package/dist/memory/agentMemory.js +121 -0
- package/dist/memory/image.d.ts +26 -0
- package/dist/memory/image.js +106 -0
- package/dist/memory/index.d.ts +3 -0
- package/dist/memory/index.js +3 -0
- package/dist/memory/masking.d.ts +7 -0
- package/dist/memory/masking.js +141 -0
- package/dist/memory/masking.test.d.ts +1 -0
- package/dist/memory/masking.test.js +117 -0
- package/dist/memory/observation.d.ts +38 -0
- package/dist/memory/observation.js +79 -0
- package/dist/memory/rendering/index.d.ts +10 -0
- package/dist/memory/rendering/index.js +13 -0
- package/dist/memory/rendering/renderJsonParts.d.ts +3 -0
- package/dist/memory/rendering/renderJsonParts.js +115 -0
- package/dist/memory/rendering/renderJsonParts.test.d.ts +1 -0
- package/dist/memory/rendering/renderJsonParts.test.js +217 -0
- package/dist/memory/rendering/renderXmlParts.d.ts +7 -0
- package/dist/memory/rendering/renderXmlParts.js +127 -0
- package/dist/memory/serde.d.ts +20 -0
- package/dist/memory/serde.js +81 -0
- package/dist/memory/util.d.ts +2 -0
- package/dist/memory/util.js +17 -0
- package/dist/telemetry/events.d.ts +9 -0
- package/dist/telemetry/events.js +80 -0
- package/dist/telemetry/index.d.ts +6 -0
- package/dist/telemetry/index.js +91 -0
- package/dist/types.d.ts +30 -0
- package/dist/types.js +1 -0
- package/dist/util.d.ts +1 -0
- package/dist/util.js +12 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +3 -0
- package/dist/web/browserProvider.d.ts +23 -0
- package/dist/web/browserProvider.js +153 -0
- package/dist/web/harness.d.ts +102 -0
- package/dist/web/harness.js +340 -0
- package/dist/web/stability.d.ts +57 -0
- package/dist/web/stability.js +316 -0
- package/dist/web/tabs.d.ts +58 -0
- package/dist/web/tabs.js +293 -0
- package/dist/web/transformer.d.ts +7 -0
- package/dist/web/transformer.js +41 -0
- package/dist/web/types.d.ts +32 -0
- package/dist/web/types.js +2 -0
- package/dist/web/util.d.ts +3 -0
- package/dist/web/util.js +81 -0
- package/dist/web/visualizer/cursor.d.ts +16 -0
- package/dist/web/visualizer/cursor.js +152 -0
- package/dist/web/visualizer/index.d.ts +22 -0
- package/dist/web/visualizer/index.js +47 -0
- package/dist/web/visualizer/mouseEffects.d.ts +18 -0
- package/dist/web/visualizer/mouseEffects.js +287 -0
- package/dist/web/visualizer/typeEffects.d.ts +10 -0
- package/dist/web/visualizer/typeEffects.js +190 -0
- package/package.json +71 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export declare const desktopClickAction: import(".").ActionDefinition<{
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
}>;
|
|
5
|
+
export declare const desktopRightClickAction: import(".").ActionDefinition<{
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
}>;
|
|
9
|
+
export declare const desktopDoubleClickAction: import(".").ActionDefinition<{
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
}>;
|
|
13
|
+
export declare const desktopDragAction: import(".").ActionDefinition<{
|
|
14
|
+
fromX: number;
|
|
15
|
+
fromY: number;
|
|
16
|
+
toX: number;
|
|
17
|
+
toY: number;
|
|
18
|
+
}>;
|
|
19
|
+
export declare const desktopScrollAction: import(".").ActionDefinition<{
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
deltaX: number;
|
|
23
|
+
deltaY: number;
|
|
24
|
+
}>;
|
|
25
|
+
export declare const desktopTypeAction: import(".").ActionDefinition<{
|
|
26
|
+
text: string;
|
|
27
|
+
}>;
|
|
28
|
+
export declare const desktopKeyAction: import(".").ActionDefinition<{
|
|
29
|
+
key: string;
|
|
30
|
+
}>;
|
|
31
|
+
export declare const desktopNavigateAction: import(".").ActionDefinition<{
|
|
32
|
+
url: string;
|
|
33
|
+
}>;
|
|
34
|
+
export declare const desktopWaitAction: import(".").ActionDefinition<{
|
|
35
|
+
seconds: number;
|
|
36
|
+
}>;
|
|
37
|
+
export declare const desktopActions: (import(".").ActionDefinition<{
|
|
38
|
+
x: number;
|
|
39
|
+
y: number;
|
|
40
|
+
}> | import(".").ActionDefinition<{
|
|
41
|
+
fromX: number;
|
|
42
|
+
fromY: number;
|
|
43
|
+
toX: number;
|
|
44
|
+
toY: number;
|
|
45
|
+
}> | import(".").ActionDefinition<{
|
|
46
|
+
x: number;
|
|
47
|
+
y: number;
|
|
48
|
+
deltaX: number;
|
|
49
|
+
deltaY: number;
|
|
50
|
+
}> | import(".").ActionDefinition<{
|
|
51
|
+
text: string;
|
|
52
|
+
}> | import(".").ActionDefinition<{
|
|
53
|
+
key: string;
|
|
54
|
+
}> | import(".").ActionDefinition<{
|
|
55
|
+
url: string;
|
|
56
|
+
}> | import(".").ActionDefinition<{
|
|
57
|
+
seconds: number;
|
|
58
|
+
}>)[];
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { createAction } from ".";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { DesktopConnector } from "@/connectors/desktopConnector";
|
|
4
|
+
// Mouse actions
|
|
5
|
+
export const desktopClickAction = createAction({
|
|
6
|
+
name: 'desktop:click',
|
|
7
|
+
description: "Click at screen coordinates",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
x: z.number().int().describe("X coordinate"),
|
|
10
|
+
y: z.number().int().describe("Y coordinate"),
|
|
11
|
+
}),
|
|
12
|
+
resolver: async ({ input: { x, y }, agent }) => {
|
|
13
|
+
const desktop = agent.require(DesktopConnector);
|
|
14
|
+
await desktop.getInterface().click(x, y);
|
|
15
|
+
},
|
|
16
|
+
render: ({ x, y }) => `⊙ click (${x}, ${y})`
|
|
17
|
+
});
|
|
18
|
+
export const desktopRightClickAction = createAction({
|
|
19
|
+
name: 'desktop:right_click',
|
|
20
|
+
description: "Right-click at screen coordinates",
|
|
21
|
+
schema: z.object({
|
|
22
|
+
x: z.number().int(),
|
|
23
|
+
y: z.number().int(),
|
|
24
|
+
}),
|
|
25
|
+
resolver: async ({ input: { x, y }, agent }) => {
|
|
26
|
+
const desktop = agent.require(DesktopConnector);
|
|
27
|
+
await desktop.getInterface().rightClick(x, y);
|
|
28
|
+
},
|
|
29
|
+
render: ({ x, y }) => `⊙ right-click (${x}, ${y})`
|
|
30
|
+
});
|
|
31
|
+
export const desktopDoubleClickAction = createAction({
|
|
32
|
+
name: 'desktop:double_click',
|
|
33
|
+
description: "Double-click at screen coordinates",
|
|
34
|
+
schema: z.object({
|
|
35
|
+
x: z.number().int(),
|
|
36
|
+
y: z.number().int(),
|
|
37
|
+
}),
|
|
38
|
+
resolver: async ({ input: { x, y }, agent }) => {
|
|
39
|
+
const desktop = agent.require(DesktopConnector);
|
|
40
|
+
await desktop.getInterface().doubleClick(x, y);
|
|
41
|
+
},
|
|
42
|
+
render: ({ x, y }) => `⊙ double-click (${x}, ${y})`
|
|
43
|
+
});
|
|
44
|
+
export const desktopDragAction = createAction({
|
|
45
|
+
name: 'desktop:drag',
|
|
46
|
+
description: "Drag from one position to another",
|
|
47
|
+
schema: z.object({
|
|
48
|
+
fromX: z.number().int(),
|
|
49
|
+
fromY: z.number().int(),
|
|
50
|
+
toX: z.number().int(),
|
|
51
|
+
toY: z.number().int(),
|
|
52
|
+
}),
|
|
53
|
+
resolver: async ({ input: { fromX, fromY, toX, toY }, agent }) => {
|
|
54
|
+
const desktop = agent.require(DesktopConnector);
|
|
55
|
+
await desktop.getInterface().drag(fromX, fromY, toX, toY);
|
|
56
|
+
},
|
|
57
|
+
render: ({ fromX, fromY, toX, toY }) => `⊙ drag from (${fromX}, ${fromY}) to (${toX}, ${toY})`
|
|
58
|
+
});
|
|
59
|
+
export const desktopScrollAction = createAction({
|
|
60
|
+
name: 'desktop:scroll',
|
|
61
|
+
description: "Hover mouse over target and scroll",
|
|
62
|
+
schema: z.object({
|
|
63
|
+
x: z.number().int(),
|
|
64
|
+
y: z.number().int(),
|
|
65
|
+
deltaX: z.number().int().describe("Pixels to scroll horizontally"),
|
|
66
|
+
deltaY: z.number().int().describe("Pixels to scroll vertically"),
|
|
67
|
+
}),
|
|
68
|
+
resolver: async ({ input: { x, y, deltaX, deltaY }, agent }) => {
|
|
69
|
+
const desktop = agent.require(DesktopConnector);
|
|
70
|
+
await desktop.getInterface().scroll(x, y, deltaX, deltaY);
|
|
71
|
+
},
|
|
72
|
+
render: ({ x, y, deltaX, deltaY }) => `↕ scroll (${deltaX}px, ${deltaY}px)`
|
|
73
|
+
});
|
|
74
|
+
// Keyboard actions
|
|
75
|
+
export const desktopTypeAction = createAction({
|
|
76
|
+
name: 'desktop:type',
|
|
77
|
+
description: "Type text at current cursor position",
|
|
78
|
+
schema: z.object({
|
|
79
|
+
text: z.string().describe("Text to type"),
|
|
80
|
+
}),
|
|
81
|
+
resolver: async ({ input: { text }, agent }) => {
|
|
82
|
+
const desktop = agent.require(DesktopConnector);
|
|
83
|
+
await desktop.getInterface().type(text);
|
|
84
|
+
},
|
|
85
|
+
render: ({ text }) => `⌨ type "${text}"`
|
|
86
|
+
});
|
|
87
|
+
export const desktopKeyAction = createAction({
|
|
88
|
+
name: 'desktop:key',
|
|
89
|
+
description: "Press a key or key combination. Use '+' to combine keys (e.g., 'cmd+c', 'ctrl+shift+t')",
|
|
90
|
+
schema: z.object({
|
|
91
|
+
key: z.string().describe("Key to press (e.g., 'enter', 'tab', 'esc') or combination (e.g., 'cmd+c', 'ctrl+a', 'ctrl+shift+t')"),
|
|
92
|
+
}),
|
|
93
|
+
resolver: async ({ input: { key }, agent }) => {
|
|
94
|
+
const desktop = agent.require(DesktopConnector);
|
|
95
|
+
// Check if it's a key combination (contains +)
|
|
96
|
+
if (key.includes('+')) {
|
|
97
|
+
// Parse the combination and use hotkey
|
|
98
|
+
const keys = key.split('+').map(k => k.trim());
|
|
99
|
+
await desktop.getInterface().hotkey(keys);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
// Single key press
|
|
103
|
+
await desktop.getInterface().key(key);
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
render: ({ key }) => {
|
|
107
|
+
// Show differently based on whether it's a combination
|
|
108
|
+
if (key.includes('+')) {
|
|
109
|
+
return `⌨ hotkey ${key}`;
|
|
110
|
+
}
|
|
111
|
+
return `⌨ key '${key}'`;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
// Navigation
|
|
115
|
+
export const desktopNavigateAction = createAction({
|
|
116
|
+
name: 'desktop:navigate',
|
|
117
|
+
description: "Open a new browser window/tab with the specified URL. For navigating within an existing browser window, interact with the address bar instead.",
|
|
118
|
+
schema: z.object({
|
|
119
|
+
url: z.string().describe("URL to open in a new browser window/tab"),
|
|
120
|
+
}),
|
|
121
|
+
resolver: async ({ input: { url }, agent }) => {
|
|
122
|
+
const desktop = agent.require(DesktopConnector);
|
|
123
|
+
const interface_ = desktop.getInterface();
|
|
124
|
+
if (!interface_.navigate) {
|
|
125
|
+
throw new Error("Desktop interface does not support navigation");
|
|
126
|
+
}
|
|
127
|
+
await interface_.navigate(url);
|
|
128
|
+
},
|
|
129
|
+
render: ({ url }) => `⛓ open browser with ${url}`
|
|
130
|
+
});
|
|
131
|
+
// Utility
|
|
132
|
+
export const desktopWaitAction = createAction({
|
|
133
|
+
name: 'desktop:wait',
|
|
134
|
+
description: "Actions include smart waiting automatically - so only use this when a significant additional wait is clearly required.",
|
|
135
|
+
schema: z.object({
|
|
136
|
+
seconds: z.number().describe("Seconds to wait"),
|
|
137
|
+
}),
|
|
138
|
+
resolver: async ({ input: { seconds }, agent }) => {
|
|
139
|
+
await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
|
|
140
|
+
},
|
|
141
|
+
render: ({ seconds }) => `◴ wait ${seconds}s`
|
|
142
|
+
});
|
|
143
|
+
// Export all desktop actions
|
|
144
|
+
export const desktopActions = [
|
|
145
|
+
desktopClickAction,
|
|
146
|
+
desktopRightClickAction,
|
|
147
|
+
desktopDoubleClickAction,
|
|
148
|
+
desktopDragAction,
|
|
149
|
+
desktopScrollAction,
|
|
150
|
+
desktopTypeAction,
|
|
151
|
+
desktopKeyAction,
|
|
152
|
+
desktopNavigateAction,
|
|
153
|
+
desktopWaitAction,
|
|
154
|
+
];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Agent } from "@/agent";
|
|
2
|
+
import { RenderableContent } from "@/memory/observation";
|
|
3
|
+
import { z, Schema, ZodTypeAny } from "zod";
|
|
4
|
+
export interface ActionDefinition<T> {
|
|
5
|
+
name: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
schema: Schema<T>;
|
|
8
|
+
resolver: ({ input, agent }: {
|
|
9
|
+
input: T;
|
|
10
|
+
agent: Agent;
|
|
11
|
+
}) => Promise<void | RenderableContent>;
|
|
12
|
+
render: (action: T) => string;
|
|
13
|
+
}
|
|
14
|
+
export declare function createAction<S extends ZodTypeAny>(action: {
|
|
15
|
+
name: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
schema?: S;
|
|
18
|
+
resolver: ({ input, agent }: {
|
|
19
|
+
input: z.infer<S>;
|
|
20
|
+
agent: Agent;
|
|
21
|
+
}) => Promise<void | RenderableContent>;
|
|
22
|
+
render?: (action: z.infer<S>) => string;
|
|
23
|
+
}): ActionDefinition<z.infer<S>>;
|
|
24
|
+
export type ActionPayload<A extends ActionDefinition<any>> = {
|
|
25
|
+
name: A['name'];
|
|
26
|
+
} & z.infer<A['schema']>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function createAction(action) {
|
|
3
|
+
// Just a helper for automatic schema typing
|
|
4
|
+
return {
|
|
5
|
+
name: action.name,
|
|
6
|
+
description: action.description,
|
|
7
|
+
schema: action.schema ?? z.object({}),
|
|
8
|
+
resolver: action.resolver,
|
|
9
|
+
render: action.render ?? ((action) => JSON.stringify(action))
|
|
10
|
+
};
|
|
11
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ActionDefinition } from ".";
|
|
2
|
+
export declare const doneAction: ActionDefinition<{
|
|
3
|
+
evidence: string;
|
|
4
|
+
}>;
|
|
5
|
+
export declare const failAction: ActionDefinition<{}>;
|
|
6
|
+
export declare const taskActions: readonly [ActionDefinition<{
|
|
7
|
+
evidence: string;
|
|
8
|
+
}>, ActionDefinition<{}>];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { AgentError } from "@/agent/errors";
|
|
2
|
+
import { createAction } from ".";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
export const doneAction = createAction({
|
|
5
|
+
name: 'task:done',
|
|
6
|
+
description: "ONLY once you have seen sufficient evidence of the task's completion, mark it as done", //Use once sure that task is finished',//'Designate current task as finished',// Do not use until you can verify the task is completed.
|
|
7
|
+
schema: z.object({
|
|
8
|
+
evidence: z.string().describe(`Specific observed evidence that verifies the task's completion. Do NOT predict this evidence.`)
|
|
9
|
+
}),
|
|
10
|
+
resolver: async ({ agent }) => {
|
|
11
|
+
agent.queueDone();
|
|
12
|
+
},
|
|
13
|
+
render: () => `✓ done`
|
|
14
|
+
});
|
|
15
|
+
export const failAction = createAction({
|
|
16
|
+
name: 'task:fail',
|
|
17
|
+
description: 'Use if task was attempted but does not seem possible. Use common sense', //'Designate current task as infeasible',
|
|
18
|
+
schema: z.object({}),
|
|
19
|
+
resolver: async ({ agent }) => {
|
|
20
|
+
throw new AgentError(`Task failed: ${agent.memory.getLastThoughtMessage() ?? "No thought recorded"}`);
|
|
21
|
+
},
|
|
22
|
+
render: () => `✕ fail`
|
|
23
|
+
});
|
|
24
|
+
export const taskActions = [
|
|
25
|
+
doneAction,
|
|
26
|
+
failAction
|
|
27
|
+
];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Intents" are natural language descriptors that align 1:1 with executable web actions.
|
|
3
|
+
* Micro converts intents into web actions.
|
|
4
|
+
*/
|
|
5
|
+
import { SwitchTabWebAction } from "@/web/types";
|
|
6
|
+
export interface Action {
|
|
7
|
+
variant: string;
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}
|
|
10
|
+
export type ActionIntent = ClickIntent | TypeIntent | ScrollIntent | SwitchTabIntent;
|
|
11
|
+
export type Intent = ActionIntent | CheckIntent;
|
|
12
|
+
export interface ClickIntent {
|
|
13
|
+
variant: 'click';
|
|
14
|
+
target: string;
|
|
15
|
+
}
|
|
16
|
+
export interface TypeIntent {
|
|
17
|
+
variant: 'type';
|
|
18
|
+
target: string;
|
|
19
|
+
content: string;
|
|
20
|
+
}
|
|
21
|
+
export interface ScrollIntent {
|
|
22
|
+
variant: 'scroll';
|
|
23
|
+
target: string;
|
|
24
|
+
deltaX: number;
|
|
25
|
+
deltaY: number;
|
|
26
|
+
}
|
|
27
|
+
export type SwitchTabIntent = SwitchTabWebAction;
|
|
28
|
+
export interface CheckIntent {
|
|
29
|
+
variant: 'check';
|
|
30
|
+
checks: string[];
|
|
31
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ActionDefinition } from ".";
|
|
2
|
+
import TypeBuilder from "@/ai/baml_client/type_builder";
|
|
3
|
+
import { FieldType } from "@boundaryml/baml/native";
|
|
4
|
+
import { Schema } from "zod";
|
|
5
|
+
export interface JsonSchema {
|
|
6
|
+
type?: string;
|
|
7
|
+
title?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
default?: any;
|
|
10
|
+
properties?: Record<string, JsonSchema>;
|
|
11
|
+
required?: string[];
|
|
12
|
+
additionalProperties?: boolean | JsonSchema;
|
|
13
|
+
items?: JsonSchema;
|
|
14
|
+
enum?: any[];
|
|
15
|
+
$ref?: string;
|
|
16
|
+
anyOf?: JsonSchema[];
|
|
17
|
+
[key: string]: any;
|
|
18
|
+
}
|
|
19
|
+
export declare function convertZodToBaml(tb: TypeBuilder, schema: Schema): FieldType;
|
|
20
|
+
export declare function convertActionDefinitionsToBaml<T>(tb: TypeBuilder, actionVocabulary: ActionDefinition<T>[]): FieldType;
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
2
|
+
import { z, ZodObject } from "zod";
|
|
3
|
+
function randomName() {
|
|
4
|
+
const chars = 'abcdefghijklmnopqrstuvwxyz';
|
|
5
|
+
let result = '';
|
|
6
|
+
for (let i = 0; i < 12; i++) {
|
|
7
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
8
|
+
}
|
|
9
|
+
return result;
|
|
10
|
+
}
|
|
11
|
+
class SchemaAdder {
|
|
12
|
+
tb;
|
|
13
|
+
rootSchema;
|
|
14
|
+
refCache = {};
|
|
15
|
+
constructor(tb, rootSchema) {
|
|
16
|
+
this.tb = tb;
|
|
17
|
+
this.rootSchema = rootSchema;
|
|
18
|
+
}
|
|
19
|
+
_parseObject(jsonSchema) {
|
|
20
|
+
if (jsonSchema.type !== "object") {
|
|
21
|
+
throw new Error(`_parseObject called with non-object type: ${jsonSchema.type}`);
|
|
22
|
+
}
|
|
23
|
+
let name = jsonSchema.title;
|
|
24
|
+
if (name === undefined || typeof name !== 'string') {
|
|
25
|
+
// Name doesn't actually affect much if field used as return value anyway, just needs to be unique
|
|
26
|
+
name = randomName();
|
|
27
|
+
//throw new Error("Title (string) is required in JSON schema for object type that becomes a BAML class.");
|
|
28
|
+
}
|
|
29
|
+
const newCls = this.tb.addClass(name);
|
|
30
|
+
const requiredFields = jsonSchema.required || [];
|
|
31
|
+
if (!Array.isArray(requiredFields) || !requiredFields.every(rf => typeof rf === 'string')) {
|
|
32
|
+
throw new Error(`'required' property in object '${name}' must be an array of strings.`);
|
|
33
|
+
}
|
|
34
|
+
const properties = jsonSchema.properties;
|
|
35
|
+
if (properties && typeof properties === 'object') {
|
|
36
|
+
for (const [fieldName, fieldSchemaUntyped] of Object.entries(properties)) {
|
|
37
|
+
if (typeof fieldSchemaUntyped !== 'object' || fieldSchemaUntyped === null) {
|
|
38
|
+
console.warn(`Property schema for '${fieldName}' in class '${name}' is not a valid object/schema. Skipping.`);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const fieldSchema = fieldSchemaUntyped;
|
|
42
|
+
const defaultValue = fieldSchema.default;
|
|
43
|
+
let fieldType;
|
|
44
|
+
if (fieldSchema.properties === undefined && fieldSchema.type === "object") {
|
|
45
|
+
console.warn(`Field '${fieldName}' in class '${name}' uses generic dict type (object without properties) ` +
|
|
46
|
+
`which defaults to map<string, string>. ` +
|
|
47
|
+
"If a more specific type is needed, please provide a specific schema with properties.");
|
|
48
|
+
fieldType = this.tb.map(this.tb.string(), this.tb.string());
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
fieldType = this.parse(fieldSchema);
|
|
52
|
+
}
|
|
53
|
+
if (!requiredFields.includes(fieldName)) {
|
|
54
|
+
if (defaultValue === undefined) {
|
|
55
|
+
fieldType = fieldType.optional();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const propertyBuilder = newCls.addProperty(fieldName, fieldType);
|
|
59
|
+
let fieldDescription = fieldSchema.description;
|
|
60
|
+
if (typeof fieldDescription === 'string') {
|
|
61
|
+
let finalDescription = fieldDescription.trim();
|
|
62
|
+
if (defaultValue !== undefined) {
|
|
63
|
+
finalDescription = `${finalDescription}\nDefault: ${JSON.stringify(defaultValue)}`;
|
|
64
|
+
finalDescription = finalDescription.trim();
|
|
65
|
+
}
|
|
66
|
+
if (finalDescription.length > 0) {
|
|
67
|
+
propertyBuilder.description(finalDescription);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else if (defaultValue !== undefined) {
|
|
71
|
+
const defaultDesc = `Default: ${JSON.stringify(defaultValue)}`;
|
|
72
|
+
propertyBuilder.description(defaultDesc.trim());
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return newCls.type();
|
|
77
|
+
}
|
|
78
|
+
_parseString(jsonSchema) {
|
|
79
|
+
if (jsonSchema.type !== "string") {
|
|
80
|
+
throw new Error(`_parseString called with non-string type: ${jsonSchema.type}`);
|
|
81
|
+
}
|
|
82
|
+
const title = jsonSchema.title;
|
|
83
|
+
const enumValues = jsonSchema.enum;
|
|
84
|
+
if (enumValues) {
|
|
85
|
+
if (!Array.isArray(enumValues)) {
|
|
86
|
+
throw new Error(`'enum' property for string type '${title || "anonymous"}' must be an array.`);
|
|
87
|
+
}
|
|
88
|
+
const stringEnumValues = [];
|
|
89
|
+
for (const val of enumValues) {
|
|
90
|
+
stringEnumValues.push(String(val));
|
|
91
|
+
}
|
|
92
|
+
if (title === undefined || typeof title !== 'string') {
|
|
93
|
+
if (stringEnumValues.length === 0) {
|
|
94
|
+
console.warn(`Anonymous enum (string type with 'enum' but no 'title') has no values. Defaulting to plain string type.`);
|
|
95
|
+
return this.tb.string();
|
|
96
|
+
}
|
|
97
|
+
return this.tb.union(stringEnumValues.map(value => this.tb.literalString(value)));
|
|
98
|
+
}
|
|
99
|
+
const newEnum = this.tb.addEnum(title);
|
|
100
|
+
if (stringEnumValues.length === 0) {
|
|
101
|
+
console.warn(`Enum '${title}' has no values. An empty enum was created.`);
|
|
102
|
+
}
|
|
103
|
+
for (const value of stringEnumValues) {
|
|
104
|
+
newEnum.addValue(value);
|
|
105
|
+
}
|
|
106
|
+
return newEnum.type();
|
|
107
|
+
}
|
|
108
|
+
return this.tb.string();
|
|
109
|
+
}
|
|
110
|
+
_parseArray(jsonSchema) {
|
|
111
|
+
if (jsonSchema.type !== "array") {
|
|
112
|
+
throw new Error(`_parseArray called with non-array type: ${jsonSchema.type}`);
|
|
113
|
+
}
|
|
114
|
+
const itemsSchema = jsonSchema.items;
|
|
115
|
+
if (itemsSchema === undefined) {
|
|
116
|
+
throw new Error(`Array field '${jsonSchema.title || "untitled array"}' is missing 'items' definition.`);
|
|
117
|
+
}
|
|
118
|
+
if (Array.isArray(itemsSchema) || typeof itemsSchema !== 'object' || itemsSchema === null) {
|
|
119
|
+
throw new Error(`'items' property for array '${jsonSchema.title || "untitled array"}' must be a single schema object. Tuple/array types for 'items' are not supported by this converter (matching Python script's direct parsing of items).`);
|
|
120
|
+
}
|
|
121
|
+
return this.parse(itemsSchema).list();
|
|
122
|
+
}
|
|
123
|
+
_loadRef(ref) {
|
|
124
|
+
if (!ref.startsWith("#/")) {
|
|
125
|
+
throw new Error(`Only local references are supported: ${ref}`);
|
|
126
|
+
}
|
|
127
|
+
if (this.refCache[ref]) {
|
|
128
|
+
return this.refCache[ref];
|
|
129
|
+
}
|
|
130
|
+
const pathParts = ref.substring(2).split('/');
|
|
131
|
+
if (pathParts.length !== 2 || !pathParts[0] || !pathParts[1]) {
|
|
132
|
+
throw new Error(`Unsupported $ref format: '${ref}'. Expected format like '#/collectionKey/definitionKey' matching Python logic.`);
|
|
133
|
+
}
|
|
134
|
+
const collectionKey = pathParts[0];
|
|
135
|
+
const definitionKey = pathParts[1];
|
|
136
|
+
const collection = this.rootSchema[collectionKey];
|
|
137
|
+
if (typeof collection !== 'object' || collection === null) {
|
|
138
|
+
throw new Error(`Reference collection '${collectionKey}' for $ref '${ref}' not found or not an object in the root schema.`);
|
|
139
|
+
}
|
|
140
|
+
if (!collection.hasOwnProperty(definitionKey)) {
|
|
141
|
+
throw new Error(`Reference item '${definitionKey}' for $ref '${ref}' not found in collection '${collectionKey}'.`);
|
|
142
|
+
}
|
|
143
|
+
const targetSchema = collection[definitionKey];
|
|
144
|
+
if (typeof targetSchema !== 'object' || targetSchema === null) {
|
|
145
|
+
throw new Error(`Resolved $ref '${ref}' points to a non-object schema.`);
|
|
146
|
+
}
|
|
147
|
+
const fieldType = this.parse(targetSchema);
|
|
148
|
+
this.refCache[ref] = fieldType;
|
|
149
|
+
return fieldType;
|
|
150
|
+
}
|
|
151
|
+
parse(jsonSchema) {
|
|
152
|
+
if (jsonSchema.$ref) {
|
|
153
|
+
if (typeof jsonSchema.$ref !== 'string') {
|
|
154
|
+
throw new Error("'$ref' property must be a string.");
|
|
155
|
+
}
|
|
156
|
+
return this._loadRef(jsonSchema.$ref);
|
|
157
|
+
}
|
|
158
|
+
// Handle 'const' next, as it's a very specific assertion
|
|
159
|
+
if (jsonSchema.const !== undefined) {
|
|
160
|
+
const constValue = jsonSchema.const;
|
|
161
|
+
if (typeof constValue === 'string') {
|
|
162
|
+
return this.tb.literalString(constValue);
|
|
163
|
+
}
|
|
164
|
+
else if (typeof constValue === 'number') {
|
|
165
|
+
if (Number.isInteger(constValue)) {
|
|
166
|
+
return this.tb.literalInt(constValue);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
// BAML does not appear to have a literalFloat, based on available information.
|
|
170
|
+
// The 'const' value itself isn't captured as a literal in the BAML type for floats.
|
|
171
|
+
console.warn(`JSON Schema 'const' with float value '${constValue}' encountered. ` +
|
|
172
|
+
`BAML will use base type (float) as literalFloat is not available. Title: '${jsonSchema.title || "anonymous"}'`);
|
|
173
|
+
return this.tb.float();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else if (typeof constValue === 'boolean') {
|
|
177
|
+
return this.tb.literalBool(constValue);
|
|
178
|
+
}
|
|
179
|
+
else if (constValue === null) {
|
|
180
|
+
return this.tb.null();
|
|
181
|
+
}
|
|
182
|
+
if (typeof constValue === 'object' && (jsonSchema.type !== 'object' && jsonSchema.type !== 'array')) {
|
|
183
|
+
console.warn(`JSON Schema 'const' with complex value '${JSON.stringify(constValue)}' ` +
|
|
184
|
+
`encountered. Title: '${jsonSchema.title || "anonymous"}'. ` +
|
|
185
|
+
`Expected 'type: "object"' or 'type: "array"' if this const is to be further processed as such. ` +
|
|
186
|
+
`Falling back to standard type parsing based on 'jsonSchema.type' (if present).`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (jsonSchema.anyOf) {
|
|
190
|
+
if (!Array.isArray(jsonSchema.anyOf)) {
|
|
191
|
+
throw new Error("'anyOf' property must be an array of schema objects.");
|
|
192
|
+
}
|
|
193
|
+
if (!jsonSchema.anyOf.every(s => typeof s === 'object' && s !== null)) {
|
|
194
|
+
throw new Error("'anyOf' array must contain valid schema objects.");
|
|
195
|
+
}
|
|
196
|
+
if (jsonSchema.anyOf.length === 0) {
|
|
197
|
+
console.warn("'anyOf' is an empty array. Defaulting to string (Python script has no specific handling).");
|
|
198
|
+
return this.tb.string();
|
|
199
|
+
}
|
|
200
|
+
return this.tb.union(jsonSchema.anyOf.map(subSchema => this.parse(subSchema)));
|
|
201
|
+
}
|
|
202
|
+
const additionalProperties = jsonSchema.additionalProperties;
|
|
203
|
+
if (additionalProperties && typeof additionalProperties === 'object' && additionalProperties.anyOf) {
|
|
204
|
+
const apSchema = additionalProperties;
|
|
205
|
+
const anyOfInAp = apSchema.anyOf;
|
|
206
|
+
if (!Array.isArray(anyOfInAp)) {
|
|
207
|
+
throw new Error("'anyOf' in 'additionalProperties' must be an array of schema objects.");
|
|
208
|
+
}
|
|
209
|
+
if (!anyOfInAp.every(s => typeof s === 'object' && s !== null)) {
|
|
210
|
+
throw new Error("'anyOf' in 'additionalProperties' must contain valid schema objects.");
|
|
211
|
+
}
|
|
212
|
+
if (anyOfInAp.length === 0) {
|
|
213
|
+
console.warn("'anyOf' in 'additionalProperties' is empty. Defaulting map value to string.");
|
|
214
|
+
return this.tb.map(this.tb.string(), this.tb.string());
|
|
215
|
+
}
|
|
216
|
+
const valueType = this.tb.union(anyOfInAp.map(subSchema => this.parse(subSchema)));
|
|
217
|
+
return this.tb.map(this.tb.string(), valueType);
|
|
218
|
+
}
|
|
219
|
+
const type = jsonSchema.type;
|
|
220
|
+
if (type === undefined) {
|
|
221
|
+
console.warn("Type field is missing in JSON schema, defaulting to string (Python script behavior).");
|
|
222
|
+
return this.tb.string();
|
|
223
|
+
}
|
|
224
|
+
if (typeof type !== 'string') {
|
|
225
|
+
throw new Error(`Unsupported 'type' format: Expected a string, got ${typeof type} (${JSON.stringify(type)}). Python script would raise ValueError.`);
|
|
226
|
+
}
|
|
227
|
+
let fieldType;
|
|
228
|
+
switch (type) {
|
|
229
|
+
case "string":
|
|
230
|
+
fieldType = this._parseString(jsonSchema);
|
|
231
|
+
break;
|
|
232
|
+
case "number":
|
|
233
|
+
fieldType = this.tb.float();
|
|
234
|
+
break;
|
|
235
|
+
case "integer":
|
|
236
|
+
fieldType = this.tb.int();
|
|
237
|
+
break;
|
|
238
|
+
case "object":
|
|
239
|
+
fieldType = this._parseObject(jsonSchema);
|
|
240
|
+
break;
|
|
241
|
+
case "array":
|
|
242
|
+
fieldType = this._parseArray(jsonSchema);
|
|
243
|
+
break;
|
|
244
|
+
case "boolean":
|
|
245
|
+
fieldType = this.tb.bool();
|
|
246
|
+
break;
|
|
247
|
+
case "null":
|
|
248
|
+
fieldType = this.tb.null();
|
|
249
|
+
break;
|
|
250
|
+
default:
|
|
251
|
+
throw new Error(`Unsupported JSON Schema type: '${type}'`);
|
|
252
|
+
}
|
|
253
|
+
return fieldType;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function convertJsonSchemaToBaml(tb, jsonSchema) {
|
|
257
|
+
if (typeof jsonSchema !== 'object' || jsonSchema === null) {
|
|
258
|
+
throw new Error("Invalid JSON schema provided. Must be an object.");
|
|
259
|
+
}
|
|
260
|
+
const parser = new SchemaAdder(tb, jsonSchema);
|
|
261
|
+
return parser.parse(jsonSchema);
|
|
262
|
+
}
|
|
263
|
+
export function convertZodToBaml(tb, schema) {
|
|
264
|
+
const jsonSchema = zodToJsonSchema(schema);
|
|
265
|
+
return convertJsonSchemaToBaml(tb, jsonSchema);
|
|
266
|
+
}
|
|
267
|
+
export function convertActionDefinitionsToBaml(tb, actionVocabulary) {
|
|
268
|
+
/**
|
|
269
|
+
* Convert action definitions to BAML TypeBuilder union representing any one of the actions
|
|
270
|
+
*/
|
|
271
|
+
const actionTypes = [];
|
|
272
|
+
for (const { name, description, schema } of actionVocabulary) {
|
|
273
|
+
// Need to augment the schema a bit:
|
|
274
|
+
// (1) if object, unpack and include variant as literal { variant: name, ...others }
|
|
275
|
+
// (2) if primitive, add as name input { variant: name, input: <primitive> }
|
|
276
|
+
let wrapperSchema;
|
|
277
|
+
const baseWrapperSchema = z.object({
|
|
278
|
+
variant: description ? z.literal(name).describe(description) : z.literal(name)
|
|
279
|
+
});
|
|
280
|
+
if (schema instanceof ZodObject) {
|
|
281
|
+
// Merge the variant field with the existing object schema
|
|
282
|
+
// The original schema's fields will be at the top level alongside 'variant'.
|
|
283
|
+
wrapperSchema = baseWrapperSchema.merge(schema);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
wrapperSchema = baseWrapperSchema.extend({
|
|
287
|
+
input: schema,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
//if (description) wrapperSchema = wrapperSchema.describe(description);
|
|
291
|
+
actionTypes.push(convertZodToBaml(tb, wrapperSchema));
|
|
292
|
+
}
|
|
293
|
+
return tb.union(actionTypes);
|
|
294
|
+
}
|
|
295
|
+
//const tb = new TypeBuilder();
|
|
296
|
+
//console.log(convertZodToBaml(tb, z.string()))
|
|
297
|
+
//console.log(zodToJsonSchema(z.string()))
|