@yeaft/webchat-agent 1.0.417 → 1.0.418
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/browser-runtime/browser-install.js +39 -0
- package/browser-runtime/messages.js +52 -2
- package/browser-runtime/service.js +221 -5
- package/index.js +12 -1
- package/local-runtime/server/browser-runtime-routes.js +22 -3
- package/local-runtime/server/client-protocol.js +4 -0
- package/local-runtime/server/handlers/agent-browser.js +88 -3
- package/local-runtime/server/handlers/agent-sync.js +14 -0
- package/local-runtime/server/handlers/client-browser.js +50 -3
- package/local-runtime/server/ws-agent.js +1 -0
- package/local-runtime/server/ws-client.js +9 -1
- package/local-runtime/version.json +1 -1
- package/local-runtime/web/app.bundle.js +155 -90
- package/local-runtime/web/app.bundle.js.gz +0 -0
- package/local-runtime/web/index.html +2 -2
- package/local-runtime/web/style.bundle.css +1 -1
- package/local-runtime/web/style.bundle.css.gz +0 -0
- package/package.json +1 -1
|
@@ -74,6 +74,20 @@ export async function handleAgentSync(agentId, agent, msg) {
|
|
|
74
74
|
break;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
case 'agent_capabilities_updated': {
|
|
78
|
+
const capabilities = Array.isArray(msg.capabilities)
|
|
79
|
+
? [...new Set(msg.capabilities.filter(value => (
|
|
80
|
+
typeof value === 'string' && value.length > 0 && value.length <= 128
|
|
81
|
+
)).slice(0, 128))]
|
|
82
|
+
: null;
|
|
83
|
+
if (!capabilities || capabilities.length === 0) break;
|
|
84
|
+
agent.capabilities = capabilities;
|
|
85
|
+
// Transport encryption negotiation is connection-scoped and immutable.
|
|
86
|
+
// A runtime capability refresh must never flip framing mid-connection.
|
|
87
|
+
await broadcastAgentList();
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
|
|
77
91
|
case 'agent_metrics': {
|
|
78
92
|
agent.metrics = normalizeAgentMetrics(msg.metrics || {});
|
|
79
93
|
agent.metricsUpdatedAt = Date.now();
|
|
@@ -15,6 +15,9 @@ import {
|
|
|
15
15
|
} from '../browser-runtime-routes.js';
|
|
16
16
|
|
|
17
17
|
const CLIENT_BROWSER_TYPES = new Set([
|
|
18
|
+
'browser_runtime_status',
|
|
19
|
+
'browser_runtime_install',
|
|
20
|
+
'browser_runtime_enable',
|
|
18
21
|
'browser_session_create',
|
|
19
22
|
'browser_session_get',
|
|
20
23
|
'browser_session_list',
|
|
@@ -34,8 +37,11 @@ function digest(value) {
|
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
async function fail(client, msg, code, safeError = code) {
|
|
40
|
+
const type = String(msg.type || '');
|
|
37
41
|
await sendToWebClient(client, {
|
|
38
|
-
type:
|
|
42
|
+
type: type.startsWith('browser_peer_') ? 'browser_peer_error'
|
|
43
|
+
: type.startsWith('browser_runtime_') ? 'browser_runtime_error'
|
|
44
|
+
: 'browser_session_error',
|
|
39
45
|
requestId: clean(msg.requestId) || null,
|
|
40
46
|
browserSessionId: clean(msg.browserSessionId) || null,
|
|
41
47
|
peerId: clean(msg.peerId) || null,
|
|
@@ -46,6 +52,10 @@ async function fail(client, msg, code, safeError = code) {
|
|
|
46
52
|
return true;
|
|
47
53
|
}
|
|
48
54
|
|
|
55
|
+
function agentSupportsBrowserSetup(agent) {
|
|
56
|
+
return new Set(agent?.capabilities || []).has('browser_runtime_setup');
|
|
57
|
+
}
|
|
58
|
+
|
|
49
59
|
function agentSupportsBrowser(agent) {
|
|
50
60
|
const capabilities = new Set(agent?.capabilities || []);
|
|
51
61
|
return capabilities.has('browser_runtime')
|
|
@@ -98,17 +108,54 @@ function ownerRoute(client, msg) {
|
|
|
98
108
|
export async function handleClientBrowser(client, msg, checkAgentAccess) {
|
|
99
109
|
if (!CLIENT_BROWSER_TYPES.has(msg?.type)) return false;
|
|
100
110
|
if (!CONFIG.browserRuntime.enabled) return fail(client, msg, 'browser_runtime_disabled');
|
|
101
|
-
|
|
111
|
+
const setupRequest = String(msg.type || '').startsWith('browser_runtime_');
|
|
112
|
+
if (setupRequest) {
|
|
113
|
+
if (client.browserRuntimeSetupProtocol !== 1) {
|
|
114
|
+
return fail(client, msg, 'browser_setup_protocol_required');
|
|
115
|
+
}
|
|
116
|
+
} else if (client.browserRuntimeProtocol !== 1) {
|
|
117
|
+
return fail(client, msg, 'browser_protocol_required');
|
|
118
|
+
}
|
|
102
119
|
const agentId = clean(msg.agentId);
|
|
103
120
|
if (!await checkAgentAccess(agentId)) return true;
|
|
104
121
|
const agent = agents.get(agentId);
|
|
105
|
-
if (!
|
|
122
|
+
if (setupRequest ? !agentSupportsBrowserSetup(agent) : !agentSupportsBrowser(agent)) {
|
|
123
|
+
return fail(client, msg, 'browser_runtime_unavailable');
|
|
124
|
+
}
|
|
106
125
|
const requestId = clean(msg.requestId);
|
|
107
126
|
const requestRequired = msg.type !== 'browser_peer_answer'
|
|
108
127
|
&& msg.type !== 'browser_peer_ice_candidate';
|
|
109
128
|
if (requestRequired && !requestId) return fail(client, msg, 'browser_request_id_required');
|
|
110
129
|
const identity = browserServerIdentity(client);
|
|
111
130
|
|
|
131
|
+
if (setupRequest) {
|
|
132
|
+
const canonical = msg.type === 'browser_runtime_install' ? {
|
|
133
|
+
confirmedBuildId: clean(msg.confirmedBuildId, 128),
|
|
134
|
+
confirmedDownloadBytes: Number(msg.confirmedDownloadBytes) || 0,
|
|
135
|
+
} : {};
|
|
136
|
+
const registration = registerBrowserCreateRequest({
|
|
137
|
+
agentId,
|
|
138
|
+
client,
|
|
139
|
+
requestId,
|
|
140
|
+
digest: digest({ type: msg.type, ...canonical }),
|
|
141
|
+
kind: msg.type,
|
|
142
|
+
});
|
|
143
|
+
if (registration.conflict) return fail(client, msg, 'browser_request_conflict');
|
|
144
|
+
if (registration.capacity) return fail(client, msg, 'browser_request_capacity');
|
|
145
|
+
if (registration.duplicate) {
|
|
146
|
+
if (registration.request.response) await sendToWebClient(client, registration.request.response);
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
await sendToAgent(agent, {
|
|
150
|
+
type: msg.type,
|
|
151
|
+
agentId,
|
|
152
|
+
requestId: registration.request.serverRequestId,
|
|
153
|
+
...canonical,
|
|
154
|
+
serverIdentity: identity,
|
|
155
|
+
});
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
|
|
112
159
|
if (msg.type === 'browser_session_create') {
|
|
113
160
|
const canonical = canonicalCreate(msg);
|
|
114
161
|
if (!canonical) return fail(client, msg, 'browser_url_invalid');
|
|
@@ -352,6 +352,7 @@ async function handleAgentMessage(agentId, msg, ws) {
|
|
|
352
352
|
'file_content', 'file_saved', 'file_op_result', 'file_search_result',
|
|
353
353
|
'git_status_result', 'git_diff_result', 'git_op_result',
|
|
354
354
|
'terminal_created', 'terminal_output', 'terminal_closed', 'terminal_error',
|
|
355
|
+
'agent_capabilities_updated', 'browser_runtime_status_result', 'browser_runtime_install_progress', 'browser_runtime_error',
|
|
355
356
|
'browser_session_created', 'browser_session_error', 'browser_session_snapshot', 'browser_session_list_result',
|
|
356
357
|
'browser_peer_prepared', 'browser_peer_offer', 'browser_peer_ice_candidate', 'browser_peer_state', 'browser_peer_error'
|
|
357
358
|
]);
|
|
@@ -6,7 +6,12 @@ import { authenticateRequest } from './auth/request-auth.js';
|
|
|
6
6
|
import { encodeKey } from './encryption.js';
|
|
7
7
|
import { userDb } from './database.js';
|
|
8
8
|
import { agents, clearYeaftDebugRequestsForClient, webClients, isHeartbeatMessageType, trackRequest } from './context.js';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
applyClientHello,
|
|
11
|
+
BROWSER_RUNTIME_PROTOCOL,
|
|
12
|
+
BROWSER_RUNTIME_SETUP_PROTOCOL,
|
|
13
|
+
WORKBENCH_ROUTE_PROTOCOL,
|
|
14
|
+
} from './client-protocol.js';
|
|
10
15
|
import { clearWorkbenchCorrelationsForClient } from './workbench-correlation.js';
|
|
11
16
|
import { clearBrowserRuntimeForClient } from './browser-runtime-routes.js';
|
|
12
17
|
import {
|
|
@@ -88,6 +93,7 @@ export function handleWebConnection(ws, url, req = {}) {
|
|
|
88
93
|
// Explicit protocols have no omission-based downgrade for security fields.
|
|
89
94
|
workbenchRouteProtocol: 0,
|
|
90
95
|
browserRuntimeProtocol: 0,
|
|
96
|
+
browserRuntimeSetupProtocol: 0,
|
|
91
97
|
});
|
|
92
98
|
|
|
93
99
|
// 心跳响应处理
|
|
@@ -116,6 +122,7 @@ export function handleWebConnection(ws, url, req = {}) {
|
|
|
116
122
|
yeaftSessionInventoryComplete: true,
|
|
117
123
|
workbenchRouteProtocol: WORKBENCH_ROUTE_PROTOCOL,
|
|
118
124
|
browserRuntimeProtocol: BROWSER_RUNTIME_PROTOCOL,
|
|
125
|
+
browserRuntimeSetupProtocol: BROWSER_RUNTIME_SETUP_PROTOCOL,
|
|
119
126
|
browserRuntimeEnabled: CONFIG.browserRuntime.enabled,
|
|
120
127
|
}));
|
|
121
128
|
setTimeout(() => broadcastAgentList(), 100);
|
|
@@ -249,6 +256,7 @@ async function handleWebMessage(clientId, msg) {
|
|
|
249
256
|
type: 'client_hello_ack',
|
|
250
257
|
workbenchRouteProtocol: client.workbenchRouteProtocol,
|
|
251
258
|
browserRuntimeProtocol: client.browserRuntimeProtocol,
|
|
259
|
+
browserRuntimeSetupProtocol: client.browserRuntimeSetupProtocol,
|
|
252
260
|
browserRuntimeEnabled: CONFIG.browserRuntime.enabled,
|
|
253
261
|
});
|
|
254
262
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"1.0.
|
|
1
|
+
{"version":"1.0.418"}
|