neoagent 2.3.1-beta.99 → 2.4.1-beta.10
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/.env.example +6 -3
- package/LICENSE +619 -21
- package/README.md +1 -1
- package/extensions/chrome-browser/background.mjs +19 -7
- package/extensions/chrome-browser/icons/icon128.png +0 -0
- package/extensions/chrome-browser/icons/icon16.png +0 -0
- package/extensions/chrome-browser/icons/icon48.png +0 -0
- package/extensions/chrome-browser/icons/logo.svg +12 -0
- package/extensions/chrome-browser/manifest.json +13 -2
- package/extensions/chrome-browser/popup.css +5 -0
- package/extensions/chrome-browser/popup.html +7 -5
- package/extensions/chrome-browser/popup.js +16 -7
- package/flutter_app/lib/features/onboarding/onboarding_companion_step.dart +391 -0
- package/flutter_app/lib/features/onboarding/onboarding_shell.dart +6 -0
- package/flutter_app/lib/features/onboarding/onboarding_welcome_step.dart +1 -1
- package/flutter_app/lib/main.dart +2 -0
- package/flutter_app/lib/main_controller.dart +156 -3
- package/flutter_app/lib/main_devices.dart +485 -119
- package/flutter_app/lib/main_integrations.dart +21 -2
- package/flutter_app/lib/main_models.dart +60 -0
- package/flutter_app/lib/main_settings.dart +289 -30
- package/flutter_app/lib/main_theme.dart +31 -2
- package/flutter_app/lib/src/backend_client.dart +89 -0
- package/flutter_app/lib/src/desktop_companion_actions.dart +144 -0
- package/flutter_app/lib/src/desktop_companion_io.dart +145 -4
- package/flutter_app/lib/src/desktop_native_bridge.dart +13 -0
- package/flutter_app/lib/src/stream_renderer.dart +286 -0
- package/flutter_app/macos/Runner/AppDelegate.swift +67 -2
- package/flutter_app/macos/Runner/DebugProfile.entitlements +4 -0
- package/flutter_app/macos/Runner/Release.entitlements +4 -0
- package/flutter_app/pubspec.lock +5 -5
- package/lib/manager.js +164 -2
- package/package.json +2 -2
- package/server/db/database.js +85 -0
- package/server/guest_agent.js +19 -1
- package/server/http/routes.js +191 -0
- package/server/http/socket.js +1 -1
- package/server/index.js +4 -1
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/NOTICES +971 -1066
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/assets/shaders/ink_sparkle.frag +1 -1
- package/server/public/assets/shaders/stretch_effect.frag +1 -1
- package/server/public/canvaskit/canvaskit.js +2 -2
- package/server/public/canvaskit/canvaskit.js.symbols +11796 -11733
- package/server/public/canvaskit/canvaskit.wasm +0 -0
- package/server/public/canvaskit/chromium/canvaskit.js +2 -2
- package/server/public/canvaskit/chromium/canvaskit.js.symbols +10706 -10643
- package/server/public/canvaskit/chromium/canvaskit.wasm +0 -0
- package/server/public/canvaskit/experimental_webparagraph/canvaskit.js +171 -0
- package/server/public/canvaskit/experimental_webparagraph/canvaskit.js.symbols +9134 -0
- package/server/public/canvaskit/experimental_webparagraph/canvaskit.wasm +0 -0
- package/server/public/canvaskit/skwasm.js +14 -14
- package/server/public/canvaskit/skwasm.js.symbols +12787 -12676
- package/server/public/canvaskit/skwasm.wasm +0 -0
- package/server/public/canvaskit/skwasm_heavy.js +14 -14
- package/server/public/canvaskit/skwasm_heavy.js.symbols +14400 -14286
- package/server/public/canvaskit/skwasm_heavy.wasm +0 -0
- package/server/public/canvaskit/wimp.js +94 -95
- package/server/public/canvaskit/wimp.js.symbols +11325 -11177
- package/server/public/canvaskit/wimp.wasm +0 -0
- package/server/public/flutter_bootstrap.js +2 -2
- package/server/public/main.dart.js +86174 -83144
- package/server/routes/browser.js +14 -0
- package/server/routes/browser_extension.js +21 -4
- package/server/routes/desktop.js +10 -0
- package/server/routes/integrations.js +2 -2
- package/server/routes/memory.js +73 -0
- package/server/routes/settings.js +4 -0
- package/server/routes/stream.js +187 -0
- package/server/services/ai/engine.js +65 -26
- package/server/services/ai/models.js +21 -0
- package/server/services/ai/preModelCompaction.js +191 -0
- package/server/services/ai/providers/claudeCode.js +273 -0
- package/server/services/ai/providers/openaiCodex.js +212 -40
- package/server/services/ai/settings.js +12 -2
- package/server/services/ai/tools.js +40 -29
- package/server/services/android/controller.js +41 -2
- package/server/services/browser/controller.js +34 -0
- package/server/services/browser/extension/manifest.js +33 -0
- package/server/services/browser/extension/provider.js +12 -6
- package/server/services/browser/extension/registry.js +188 -18
- package/server/services/desktop/gateway.js +28 -3
- package/server/services/desktop/protocol.js +34 -0
- package/server/services/desktop/provider.js +25 -0
- package/server/services/desktop/registry.js +92 -10
- package/server/services/integrations/google/provider.js +78 -0
- package/server/services/integrations/manager.js +29 -13
- package/server/services/manager.js +44 -2
- package/server/services/memory/ingestion.js +486 -0
- package/server/services/memory/manager.js +422 -0
- package/server/services/memory/openhuman_uplift.test.js +98 -0
- package/server/services/runtime/backends/local-vm.js +6 -0
- package/server/services/runtime/docker-vm-manager.js +26 -3
- package/server/services/runtime/manager.js +36 -5
- package/server/services/runtime/settings.js +17 -0
- package/server/services/streaming/android-stream.js +298 -0
- package/server/services/streaming/browser-stream.js +87 -0
- package/server/services/streaming/stream-hub.js +231 -0
- package/server/services/websocket.js +73 -0
- package/server/services/widgets/focus_widget.js +45 -4
|
@@ -35,6 +35,8 @@ const EVENT_RATE_LIMITS = Object.freeze({
|
|
|
35
35
|
'integrations:status': { windowMs: 10 * 1000, max: 20 },
|
|
36
36
|
'memory:read': { windowMs: 10 * 1000, max: 20 },
|
|
37
37
|
'memory:search': { windowMs: 10 * 1000, max: 20 },
|
|
38
|
+
'stream:subscribe': { windowMs: 10 * 1000, max: 40 },
|
|
39
|
+
'stream:unsubscribe': { windowMs: 10 * 1000, max: 40 },
|
|
38
40
|
});
|
|
39
41
|
|
|
40
42
|
function asObject(value) {
|
|
@@ -54,6 +56,19 @@ function toBoundedInt(value, fallback, min, max) {
|
|
|
54
56
|
return Math.min(max, Math.max(min, Math.floor(parsed)));
|
|
55
57
|
}
|
|
56
58
|
|
|
59
|
+
function normalizeStreamPayload(raw) {
|
|
60
|
+
const data = asObject(raw);
|
|
61
|
+
const platform = toOptionalString(data?.platform, 32).toLowerCase() || 'desktop';
|
|
62
|
+
if (!['desktop', 'android', 'browser'].includes(platform)) {
|
|
63
|
+
throw new Error('platform must be desktop, android, or browser.');
|
|
64
|
+
}
|
|
65
|
+
const deviceId = toOptionalString(data?.deviceId || data?.device_id, 256);
|
|
66
|
+
return {
|
|
67
|
+
platform,
|
|
68
|
+
deviceId: deviceId || (platform === 'browser' ? 'browser' : ''),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
57
72
|
function resolveAgentFromPayload(userId, value) {
|
|
58
73
|
const data = asObject(value);
|
|
59
74
|
return resolveAgentId(userId, data?.agentId || data?.agent_id || null);
|
|
@@ -831,9 +846,67 @@ function setupWebSocket(io, services) {
|
|
|
831
846
|
}
|
|
832
847
|
});
|
|
833
848
|
|
|
849
|
+
// ── Remote Control Streams ──
|
|
850
|
+
|
|
851
|
+
socket.on('stream:subscribe', (raw) => {
|
|
852
|
+
const limit = allowEvent('stream:subscribe');
|
|
853
|
+
if (!limit.allowed) {
|
|
854
|
+
recordRateLimitHit(rateLimitObserver, userId, socket.id, 'stream:subscribe', limit.retryAfterMs);
|
|
855
|
+
return socket.emit('stream:error', {
|
|
856
|
+
error: `Rate limit exceeded for stream:subscribe. Retry in ${Math.ceil(limit.retryAfterMs / 1000)}s.`,
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
try {
|
|
860
|
+
const streamHub = services.streamHub || services.app?.locals?.streamHub;
|
|
861
|
+
if (!streamHub) throw new Error('Stream hub is unavailable.');
|
|
862
|
+
const data = normalizeStreamPayload(raw);
|
|
863
|
+
if (!data.deviceId) throw new Error('deviceId is required.');
|
|
864
|
+
const subscriberCount = streamHub.subscribe(userId, data.deviceId, data.platform, socket.id);
|
|
865
|
+
socket.emit('stream:subscribed', {
|
|
866
|
+
platform: data.platform,
|
|
867
|
+
deviceId: data.deviceId,
|
|
868
|
+
subscriberCount,
|
|
869
|
+
});
|
|
870
|
+
} catch (err) {
|
|
871
|
+
console.error(`[WS] stream:subscribe failed for user ${userId}:`, err);
|
|
872
|
+
socket.emit('stream:error', { error: sanitizeError(err) });
|
|
873
|
+
}
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
socket.on('stream:unsubscribe', async (raw) => {
|
|
877
|
+
const limit = allowEvent('stream:unsubscribe');
|
|
878
|
+
if (!limit.allowed) {
|
|
879
|
+
recordRateLimitHit(rateLimitObserver, userId, socket.id, 'stream:unsubscribe', limit.retryAfterMs);
|
|
880
|
+
return socket.emit('stream:error', {
|
|
881
|
+
error: `Rate limit exceeded for stream:unsubscribe. Retry in ${Math.ceil(limit.retryAfterMs / 1000)}s.`,
|
|
882
|
+
});
|
|
883
|
+
}
|
|
884
|
+
try {
|
|
885
|
+
const streamHub = services.streamHub || services.app?.locals?.streamHub;
|
|
886
|
+
if (!streamHub) throw new Error('Stream hub is unavailable.');
|
|
887
|
+
const data = normalizeStreamPayload(raw);
|
|
888
|
+
if (!data.deviceId) throw new Error('deviceId is required.');
|
|
889
|
+
const subscriberCount = await streamHub.unsubscribe(userId, data.platform, data.deviceId, socket.id);
|
|
890
|
+
socket.emit('stream:unsubscribed', {
|
|
891
|
+
platform: data.platform,
|
|
892
|
+
deviceId: data.deviceId,
|
|
893
|
+
subscriberCount,
|
|
894
|
+
});
|
|
895
|
+
} catch (err) {
|
|
896
|
+
console.error(`[WS] stream:unsubscribe failed for user ${userId}:`, err);
|
|
897
|
+
socket.emit('stream:error', { error: sanitizeError(err) });
|
|
898
|
+
}
|
|
899
|
+
});
|
|
900
|
+
|
|
834
901
|
// ── Disconnect ──
|
|
835
902
|
|
|
836
903
|
socket.on('disconnect', () => {
|
|
904
|
+
const streamHub = services.streamHub || services.app?.locals?.streamHub;
|
|
905
|
+
if (streamHub && typeof streamHub.unsubscribeAll === 'function') {
|
|
906
|
+
void streamHub.unsubscribeAll(socket.id).catch((err) => {
|
|
907
|
+
console.error(`[WS] Failed to unsubscribe streams for socket ${socket.id}:`, err);
|
|
908
|
+
});
|
|
909
|
+
}
|
|
837
910
|
if (!voiceRuntimeManager || typeof voiceRuntimeManager.closeSession !== 'function') {
|
|
838
911
|
socket.data.voiceSessionIds?.clear?.();
|
|
839
912
|
console.log(`[WS] User ${userId} disconnected (${socket.id})`);
|
|
@@ -52,6 +52,18 @@ function buildAssistantFocusSnapshot(memoryManager, userId, agentId) {
|
|
|
52
52
|
).all(userId, scopedAgentId);
|
|
53
53
|
const conversations = memoryManager?.getRecentConversations?.(userId, 4, { agentId: scopedAgentId }) || [];
|
|
54
54
|
const memories = memoryManager?.listMemories?.(userId, { limit: 6, agentId: scopedAgentId }) || [];
|
|
55
|
+
const recentKnowledgeChanges = memoryManager?.listRecentKnowledgeChanges?.(userId, {
|
|
56
|
+
agentId: scopedAgentId,
|
|
57
|
+
limit: 5,
|
|
58
|
+
}) || [];
|
|
59
|
+
const knowledgeViews = memoryManager?.listKnowledgeViews?.(userId, {
|
|
60
|
+
agentId: scopedAgentId,
|
|
61
|
+
limit: 4,
|
|
62
|
+
}) || [];
|
|
63
|
+
const ingestionOverview = memoryManager?.getIngestionOverview?.(userId, {
|
|
64
|
+
agentId: scopedAgentId,
|
|
65
|
+
limit: 8,
|
|
66
|
+
}) || [];
|
|
55
67
|
|
|
56
68
|
const activeThreads = conversations.slice(0, 3).map((conversation) => ({
|
|
57
69
|
title: safeTrim(conversation.title, 80),
|
|
@@ -75,6 +87,24 @@ function buildAssistantFocusSnapshot(memoryManager, userId, agentId) {
|
|
|
75
87
|
value: safeTrim(run.status || 'unknown', 32),
|
|
76
88
|
}));
|
|
77
89
|
const rememberedContext = memories.slice(0, 2).map((memory) => safeTrim(memory.content, 140));
|
|
90
|
+
const backgroundAwareness = {
|
|
91
|
+
summary: safeTrim(
|
|
92
|
+
recentKnowledgeChanges[0]?.summary
|
|
93
|
+
|| recentKnowledgeChanges[0]?.title
|
|
94
|
+
|| knowledgeViews[0]?.summary
|
|
95
|
+
|| '',
|
|
96
|
+
180,
|
|
97
|
+
),
|
|
98
|
+
changedCount: recentKnowledgeChanges.length,
|
|
99
|
+
lastChangedAt: recentKnowledgeChanges[0]?.updatedAt || null,
|
|
100
|
+
};
|
|
101
|
+
const syncHealth = ingestionOverview.slice(0, 3).map((source) => ({
|
|
102
|
+
label: safeTrim(source.providerKey || source.sourceTypes?.[0] || 'Background context', 80),
|
|
103
|
+
value: safeTrim(source.status || 'ready', 32),
|
|
104
|
+
lastRefreshAt: source.lastRefreshAt || null,
|
|
105
|
+
nextRefreshAt: source.nextRefreshAt || null,
|
|
106
|
+
documentCount: Number(source.documentCount || 0),
|
|
107
|
+
}));
|
|
78
108
|
|
|
79
109
|
const currentFocus = safeTrim(
|
|
80
110
|
selfState.focus?.currentFocus
|
|
@@ -90,6 +120,10 @@ function buildAssistantFocusSnapshot(memoryManager, userId, agentId) {
|
|
|
90
120
|
nearTermPriorities,
|
|
91
121
|
recentSignals,
|
|
92
122
|
rememberedContext,
|
|
123
|
+
recentKnowledgeChanges,
|
|
124
|
+
knowledgeViews,
|
|
125
|
+
backgroundAwareness,
|
|
126
|
+
syncHealth,
|
|
93
127
|
assistantIdentity: {
|
|
94
128
|
name: safeTrim(selfState.identity?.displayName, 80),
|
|
95
129
|
style: safeTrim(selfState.identity?.style, 120),
|
|
@@ -99,11 +133,15 @@ function buildAssistantFocusSnapshot(memoryManager, userId, agentId) {
|
|
|
99
133
|
}
|
|
100
134
|
|
|
101
135
|
function buildAssistantFocusWidgetPayload(snapshot) {
|
|
136
|
+
const knowledgeChangeCount = Number(snapshot.backgroundAwareness?.changedCount || 0);
|
|
137
|
+
const primaryMetric = knowledgeChangeCount > 0 ? knowledgeChangeCount : snapshot.activeThreads.length;
|
|
102
138
|
const rows = [
|
|
103
139
|
...snapshot.nearTermPriorities,
|
|
104
140
|
...snapshot.recentSignals,
|
|
141
|
+
...snapshot.syncHealth,
|
|
105
142
|
].slice(0, 3);
|
|
106
143
|
const chips = [
|
|
144
|
+
...snapshot.recentKnowledgeChanges.map((item) => item.title),
|
|
107
145
|
...snapshot.activeThreads.map((item) => item.title),
|
|
108
146
|
...snapshot.rememberedContext,
|
|
109
147
|
].filter(Boolean).slice(0, 3);
|
|
@@ -113,14 +151,17 @@ function buildAssistantFocusWidgetPayload(snapshot) {
|
|
|
113
151
|
kicker: 'Assistant state',
|
|
114
152
|
subtitle: snapshot.currentFocus,
|
|
115
153
|
body: snapshot.activeThreads[0]?.preview
|
|
154
|
+
|| snapshot.backgroundAwareness?.summary
|
|
116
155
|
|| snapshot.rememberedContext[0]
|
|
117
156
|
|| 'Watching recent conversations, tasks, and runs.',
|
|
118
|
-
metric: String(
|
|
119
|
-
metricLabel:
|
|
157
|
+
metric: String(primaryMetric),
|
|
158
|
+
metricLabel: knowledgeChangeCount > 0
|
|
159
|
+
? (knowledgeChangeCount === 1 ? 'knowledge change' : 'knowledge changes')
|
|
160
|
+
: (snapshot.activeThreads.length === 1 ? 'active thread' : 'active threads'),
|
|
120
161
|
secondaryMetric: String(snapshot.nearTermPriorities.length),
|
|
121
162
|
secondaryLabel: 'priorities',
|
|
122
|
-
tertiaryMetric: formatRelativeTimestamp(snapshot.generatedAt),
|
|
123
|
-
tertiaryLabel: 'updated',
|
|
163
|
+
tertiaryMetric: formatRelativeTimestamp(snapshot.backgroundAwareness?.lastChangedAt || snapshot.generatedAt),
|
|
164
|
+
tertiaryLabel: snapshot.backgroundAwareness?.lastChangedAt ? 'last change' : 'updated',
|
|
124
165
|
rows,
|
|
125
166
|
chips,
|
|
126
167
|
iconToken: 'focus',
|