@stevederico/dotbot 0.27.0 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/README.md +64 -12
- package/bin/dotbot.js +389 -99
- package/core/agent.js +1 -1
- package/core/cdp.js +5 -58
- package/dotbot.db +0 -0
- package/index.js +0 -7
- package/package.json +1 -1
- package/storage/SQLiteCronAdapter.js +8 -92
- package/storage/index.js +0 -3
- package/tools/appgen.js +1 -10
- package/tools/browser.js +0 -15
- package/tools/code.js +0 -28
- package/tools/images.js +0 -10
- package/tools/index.js +2 -4
- package/tools/jobs.js +0 -2
- package/tools/tasks.js +0 -2
- package/tools/web.js +0 -36
- package/examples/sqlite-session-example.js +0 -69
- package/observer/index.js +0 -164
package/observer/index.js
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Browser Observer — in-memory snapshot store and agent tool.
|
|
3
|
-
*
|
|
4
|
-
* The frontend pushes structured browser-state snapshots via POST /api/agent/observer.
|
|
5
|
-
* The agent reads the latest snapshot via the `browser_observe` tool to understand
|
|
6
|
-
* what the user is currently doing in the browser.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const SNAPSHOT_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
10
|
-
|
|
11
|
-
/** @type {Map<string, Object>} userID → { ...snapshot, receivedAt } */
|
|
12
|
-
const snapshots = new Map();
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Store the latest browser snapshot for a user.
|
|
16
|
-
*
|
|
17
|
-
* @param {string} userID - Authenticated user ID
|
|
18
|
-
* @param {Object} snapshot - Structured browser state from the frontend
|
|
19
|
-
*/
|
|
20
|
-
export function storeSnapshot(userID, snapshot) {
|
|
21
|
-
snapshots.set(userID, { ...snapshot, receivedAt: Date.now() });
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Retrieve the latest snapshot for a user, or null if stale/missing.
|
|
26
|
-
*
|
|
27
|
-
* @param {string} userID - Authenticated user ID
|
|
28
|
-
* @returns {Object|null} Snapshot with receivedAt, or null
|
|
29
|
-
*/
|
|
30
|
-
export function getSnapshot(userID) {
|
|
31
|
-
const entry = snapshots.get(userID);
|
|
32
|
-
if (!entry) return null;
|
|
33
|
-
if (Date.now() - entry.receivedAt > SNAPSHOT_TTL_MS) {
|
|
34
|
-
snapshots.delete(userID);
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
return entry;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Remove a user's snapshot (cleanup on logout, etc.).
|
|
42
|
-
*
|
|
43
|
-
* @param {string} userID - Authenticated user ID
|
|
44
|
-
*/
|
|
45
|
-
export function clearSnapshot(userID) {
|
|
46
|
-
snapshots.delete(userID);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Format a snapshot into plain-text for LLM consumption.
|
|
51
|
-
*
|
|
52
|
-
* @param {Object} snap - Snapshot object from the store
|
|
53
|
-
* @param {boolean} includeActions - Whether to include recent actions
|
|
54
|
-
* @returns {string} Human-readable state description
|
|
55
|
-
*/
|
|
56
|
-
function formatSnapshot(snap, includeActions = true) {
|
|
57
|
-
const ageSec = Math.round((Date.now() - snap.timestamp) / 1000);
|
|
58
|
-
const lines = [];
|
|
59
|
-
|
|
60
|
-
lines.push(`Browser state (${ageSec}s ago):`);
|
|
61
|
-
lines.push('');
|
|
62
|
-
|
|
63
|
-
// Windows
|
|
64
|
-
if (snap.windows && snap.windows.length > 0) {
|
|
65
|
-
lines.push(`Open apps (${snap.windowCount || snap.windows.length}):`);
|
|
66
|
-
for (const w of snap.windows) {
|
|
67
|
-
const focus = w.isFocused ? ' [focused]' : '';
|
|
68
|
-
lines.push(` - ${w.app}${w.title ? ': ' + w.title : ''}${focus}`);
|
|
69
|
-
}
|
|
70
|
-
} else {
|
|
71
|
-
lines.push('No apps open.');
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (snap.focusedApp) {
|
|
75
|
-
lines.push(`Focused: ${snap.focusedApp}`);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Docked panel
|
|
79
|
-
if (snap.isDottieDocked) {
|
|
80
|
-
lines.push('DotBot panel: docked (sidebar)');
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Input bar
|
|
84
|
-
if (snap.isInputElevated) {
|
|
85
|
-
lines.push(`Input bar: elevated${snap.inputValue ? ' — "' + snap.inputValue + '"' : ''}`);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Voice
|
|
89
|
-
if (snap.voiceState && snap.voiceState !== 'idle') {
|
|
90
|
-
lines.push(`Voice: ${snap.voiceState}`);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Streaming
|
|
94
|
-
if (snap.isStreaming) {
|
|
95
|
-
lines.push('Agent: streaming response');
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Last tool call
|
|
99
|
-
if (snap.lastToolCall) {
|
|
100
|
-
const tc = snap.lastToolCall;
|
|
101
|
-
const tcAge = Math.round((Date.now() - tc.timestamp) / 1000);
|
|
102
|
-
lines.push(`Last tool: ${tc.name} (${tc.status}, ${tcAge}s ago)`);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Messages
|
|
106
|
-
if (snap.messageCount > 0) {
|
|
107
|
-
lines.push(`Messages in session: ${snap.messageCount}`);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Provider/model
|
|
111
|
-
if (snap.currentProvider || snap.currentModel) {
|
|
112
|
-
lines.push(`Model: ${snap.currentProvider || '?'}/${snap.currentModel || '?'}`);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Layout + dock
|
|
116
|
-
lines.push(`Layout: ${snap.layoutMode || 'desktop'}`);
|
|
117
|
-
if (snap.dockApps && snap.dockApps.length > 0) {
|
|
118
|
-
lines.push(`Dock: ${snap.dockApps.join(', ')}`);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Viewport
|
|
122
|
-
if (snap.viewport) {
|
|
123
|
-
lines.push(`Viewport: ${snap.viewport.width}x${snap.viewport.height}`);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Recent actions
|
|
127
|
-
if (includeActions && snap.recentActions && snap.recentActions.length > 0) {
|
|
128
|
-
lines.push('');
|
|
129
|
-
lines.push('Recent actions:');
|
|
130
|
-
for (const a of snap.recentActions) {
|
|
131
|
-
const aAge = Math.round((Date.now() - a.timestamp) / 1000);
|
|
132
|
-
const detail = a.app ? ` (${a.app})` : a.tool ? ` (${a.tool})` : '';
|
|
133
|
-
lines.push(` - ${a.action}${detail} — ${aAge}s ago`);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return lines.join('\n');
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/** Agent tool definitions for the browser observer. */
|
|
141
|
-
export const observerTools = [
|
|
142
|
-
{
|
|
143
|
-
name: 'browser_observe',
|
|
144
|
-
description:
|
|
145
|
-
"See what the user is currently doing in Dottie OS — open apps, focused window, voice state, recent actions. " +
|
|
146
|
-
"Call this when you need context about the user's current activity, or when they reference 'this', 'what I'm looking at', or 'current'.",
|
|
147
|
-
parameters: {
|
|
148
|
-
type: 'object',
|
|
149
|
-
properties: {
|
|
150
|
-
include_actions: {
|
|
151
|
-
type: 'boolean',
|
|
152
|
-
description: 'Include recent user actions (default true)',
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
execute: async (input, signal, context) => {
|
|
157
|
-
if (!context?.userID) return 'Error: user context not available';
|
|
158
|
-
const snap = getSnapshot(context.userID);
|
|
159
|
-
if (!snap) return 'No browser state available. The user may have the tab in the background or just opened the page.';
|
|
160
|
-
const includeActions = input.include_actions !== false;
|
|
161
|
-
return formatSnapshot(snap, includeActions);
|
|
162
|
-
},
|
|
163
|
-
},
|
|
164
|
-
];
|