devframe 0.1.19 → 0.1.21
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/README.md +2 -2
- package/dist/{_shared-BcPXmcjq.mjs → _shared-iZy45oG3.mjs} +2 -2
- package/dist/adapters/build.d.mts +3 -3
- package/dist/adapters/build.mjs +12 -9
- package/dist/adapters/cli.d.mts +1 -1
- package/dist/adapters/cli.mjs +2 -2
- package/dist/adapters/dev.d.mts +2 -2
- package/dist/adapters/dev.mjs +1 -1
- package/dist/adapters/embedded.d.mts +2 -2
- package/dist/adapters/embedded.mjs +1 -1
- package/dist/adapters/mcp.d.mts +1 -1
- package/dist/adapters/mcp.mjs +6 -2
- package/dist/adapters/vite.d.mts +5 -4
- package/dist/adapters/vite.mjs +4 -3
- package/dist/client/index.d.mts +51 -145
- package/dist/client/index.mjs +1664 -2
- package/dist/constants.d.mts +12 -15
- package/dist/constants.mjs +12 -29
- package/dist/context-BJ4r2SmR.mjs +1051 -0
- package/dist/context-internal-Dx_NoSv1.mjs +199 -0
- package/dist/context-internal-saIAfNVw.d.mts +51 -0
- package/dist/{dev-Djy5hbgs.mjs → dev-CdAy400a.mjs} +7 -6
- package/dist/{devtool-CIqONpYU.d.mts → devtool-CNvLs2_Y.d.mts} +367 -530
- package/dist/diagnostics-DxPnRoXO.mjs +51 -0
- package/dist/host-h3-9jeHcltx.mjs +24 -0
- package/dist/{human-id-CHS0s28X.mjs → human-id-BLoGo_e5.mjs} +0 -1
- package/dist/{index-BwrLhNmz.d.mts → index-CuLRIMto.d.mts} +1 -1
- package/dist/index.d.mts +4 -5
- package/dist/index.mjs +1 -4
- package/dist/internal/index.d.mts +16 -0
- package/dist/internal/index.mjs +3 -0
- package/dist/node/index.d.mts +45 -140
- package/dist/node/index.mjs +7 -6
- package/dist/recipes/open-helpers.d.mts +1 -1
- package/dist/recipes/open-helpers.mjs +3 -1
- package/dist/rpc/index.d.mts +2 -2
- package/dist/rpc/index.mjs +2 -2
- package/dist/rpc/transports/ws-client.d.mts +1 -1
- package/dist/rpc/transports/ws-client.mjs +1 -1
- package/dist/rpc/transports/ws-server.d.mts +1 -1
- package/dist/rpc/transports/ws-server.mjs +1 -1
- package/dist/{rpc-D7LxIh8t.mjs → rpc-INbWfHoX.mjs} +1 -1
- package/dist/{serialization-BN2ZQEE9.mjs → serialization-DwKi05Pn.mjs} +1 -1
- package/dist/{server-CaUeMcAh.d.mts → server-BAqOajx_.d.mts} +1 -1
- package/dist/{server-DrBxa6ZV.mjs → server-CBsxXIH5.mjs} +27 -2
- package/dist/{static-dump-cyGfMmRf.mjs → static-dump-D5VH8Iqk.mjs} +1 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/human-id.mjs +1 -1
- package/dist/utils/shared-state.d.mts +2 -2
- package/dist/utils/shared-state.mjs +1 -1
- package/dist/utils/state.d.mts +2 -1
- package/dist/utils/state.mjs +1 -1
- package/dist/utils/streaming-channel.d.mts +2 -0
- package/dist/utils/streaming-channel.mjs +255 -0
- package/dist/utils/when.d.mts +401 -2
- package/dist/{ws-client-DOYwYluO.d.mts → ws-client-CjPuPFbA.d.mts} +1 -1
- package/dist/{ws-server-DHMeNOY_.d.mts → ws-server-C7LnhOHi.d.mts} +13 -1
- package/package.json +10 -21
- package/skills/devframe/README.md +13 -0
- package/skills/devframe/SKILL.md +406 -0
- package/skills/devframe/templates/counter-devtool.ts +24 -0
- package/skills/devframe/templates/spa-devtool.ts +28 -0
- package/skills/devframe/templates/vite-client.ts +11 -0
- package/dist/adapters/kit.d.mts +0 -23
- package/dist/adapters/kit.mjs +0 -16
- package/dist/client-C6w_NshP.mjs +0 -1569
- package/dist/context-BsNZMCnr.mjs +0 -6827
- package/dist/helpers/nuxt/index.d.mts +0 -46
- package/dist/helpers/nuxt/index.mjs +0 -58
- package/dist/helpers/nuxt/runtime/plugin.client.d.mts +0 -8
- package/dist/helpers/nuxt/runtime/plugin.client.mjs +0 -12
- package/dist/host-h3-w3c0t8ZO.mjs +0 -18
- package/dist/immer-HjMAm3b6.mjs +0 -894
- package/dist/main-CuGOfqoX.mjs +0 -601
- package/dist/when-BAE663Hv.d.mts +0 -401
- package/dist/{open-JfacLHs0.mjs → open-Dede_w9r.mjs} +4 -4
- /package/dist/{types-gWbe-b2R.d.mts → types-C5OVe4AC.d.mts} +0 -0
|
@@ -0,0 +1,1051 @@
|
|
|
1
|
+
import { o as RpcFunctionsCollectorBase } from "./rpc-INbWfHoX.mjs";
|
|
2
|
+
import { s as diagnostics } from "./serialization-DwKi05Pn.mjs";
|
|
3
|
+
import { defineRpcFunction } from "./index.mjs";
|
|
4
|
+
import { n as logger, t as diagnostics$1 } from "./diagnostics-DxPnRoXO.mjs";
|
|
5
|
+
import { createEventEmitter } from "./utils/events.mjs";
|
|
6
|
+
import { createSharedState } from "./utils/shared-state.mjs";
|
|
7
|
+
import { createStreamReader, createStreamSink } from "./utils/streaming-channel.mjs";
|
|
8
|
+
import { consoleReporter, createLogger, defineDiagnostics } from "logs-sdk";
|
|
9
|
+
import c from "ansis";
|
|
10
|
+
import { ansiFormatter } from "logs-sdk/formatters/ansi";
|
|
11
|
+
import { isatty } from "node:tty";
|
|
12
|
+
import { formatWithOptions, inspect } from "node:util";
|
|
13
|
+
import { existsSync } from "node:fs";
|
|
14
|
+
//#region src/node/host-agent.ts
|
|
15
|
+
/**
|
|
16
|
+
* Framework-neutral host aggregating the agent-exposed surface of a
|
|
17
|
+
* devtool. Auto-discovers RPC functions with an `agent` field from
|
|
18
|
+
* `ctx.rpc.definitions`, and accepts plugin-registered tools /
|
|
19
|
+
* resources via `registerTool` / `registerResource`.
|
|
20
|
+
*
|
|
21
|
+
* @experimental
|
|
22
|
+
*/
|
|
23
|
+
var DevToolsAgentHost = class {
|
|
24
|
+
events = createEventEmitter();
|
|
25
|
+
tools = /* @__PURE__ */ new Map();
|
|
26
|
+
resources = /* @__PURE__ */ new Map();
|
|
27
|
+
_rpcUnsubscribe;
|
|
28
|
+
constructor(context) {
|
|
29
|
+
this.context = context;
|
|
30
|
+
this._rpcUnsubscribe = context.rpc.onChanged(() => {
|
|
31
|
+
this.events.emit("agent:manifest:changed");
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
registerTool(input) {
|
|
35
|
+
this._validateToolId(input.id);
|
|
36
|
+
const tool = this._projectTool(input);
|
|
37
|
+
this.tools.set(tool.id, {
|
|
38
|
+
tool,
|
|
39
|
+
handler: input.handler
|
|
40
|
+
});
|
|
41
|
+
this.events.emit("agent:tool:registered", tool);
|
|
42
|
+
this.events.emit("agent:manifest:changed");
|
|
43
|
+
return { unregister: () => this.unregisterTool(tool.id) };
|
|
44
|
+
}
|
|
45
|
+
unregisterTool(id) {
|
|
46
|
+
const existed = this.tools.delete(id);
|
|
47
|
+
if (existed) {
|
|
48
|
+
this.events.emit("agent:tool:unregistered", id);
|
|
49
|
+
this.events.emit("agent:manifest:changed");
|
|
50
|
+
}
|
|
51
|
+
return existed;
|
|
52
|
+
}
|
|
53
|
+
registerResource(input) {
|
|
54
|
+
if (this.resources.has(input.id)) throw logger.DF0016({ id: input.id }).throw();
|
|
55
|
+
const resource = {
|
|
56
|
+
id: input.id,
|
|
57
|
+
name: input.name,
|
|
58
|
+
description: input.description,
|
|
59
|
+
mimeType: input.mimeType ?? "application/json",
|
|
60
|
+
uri: input.uri ?? `devframe://resource/${encodeURIComponent(input.id)}`
|
|
61
|
+
};
|
|
62
|
+
this.resources.set(resource.id, {
|
|
63
|
+
resource,
|
|
64
|
+
read: input.read
|
|
65
|
+
});
|
|
66
|
+
this.events.emit("agent:resource:registered", resource);
|
|
67
|
+
this.events.emit("agent:manifest:changed");
|
|
68
|
+
return { unregister: () => this.unregisterResource(resource.id) };
|
|
69
|
+
}
|
|
70
|
+
unregisterResource(id) {
|
|
71
|
+
const existed = this.resources.delete(id);
|
|
72
|
+
if (existed) {
|
|
73
|
+
this.events.emit("agent:resource:unregistered", id);
|
|
74
|
+
this.events.emit("agent:manifest:changed");
|
|
75
|
+
}
|
|
76
|
+
return existed;
|
|
77
|
+
}
|
|
78
|
+
list() {
|
|
79
|
+
const rpcTools = this._collectRpcTools();
|
|
80
|
+
const plainTools = Array.from(this.tools.values()).map((t) => t.tool);
|
|
81
|
+
const resources = Array.from(this.resources.values()).map((r) => r.resource);
|
|
82
|
+
return {
|
|
83
|
+
tools: [...rpcTools, ...plainTools],
|
|
84
|
+
resources
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
getTool(id) {
|
|
88
|
+
const plain = this.tools.get(id);
|
|
89
|
+
if (plain) return plain.tool;
|
|
90
|
+
return this._collectRpcTools().find((t) => t.id === id);
|
|
91
|
+
}
|
|
92
|
+
getResource(id) {
|
|
93
|
+
return this.resources.get(id)?.resource;
|
|
94
|
+
}
|
|
95
|
+
async invoke(id, args) {
|
|
96
|
+
const plain = this.tools.get(id);
|
|
97
|
+
if (plain?.handler) return await plain.handler(args);
|
|
98
|
+
const rpcDef = this._findRpcDefinition(id);
|
|
99
|
+
if (rpcDef) {
|
|
100
|
+
const positional = this._coercePositionalArgs(args, rpcDef);
|
|
101
|
+
return await this.context.rpc.invokeLocal(id, ...positional);
|
|
102
|
+
}
|
|
103
|
+
throw new Error(`[devframe/agent] tool "${id}" not found`);
|
|
104
|
+
}
|
|
105
|
+
async read(id) {
|
|
106
|
+
const entry = this.resources.get(id);
|
|
107
|
+
if (!entry) throw new Error(`[devframe/agent] resource "${id}" not found`);
|
|
108
|
+
return await entry.read();
|
|
109
|
+
}
|
|
110
|
+
/** @internal */
|
|
111
|
+
_dispose() {
|
|
112
|
+
this._rpcUnsubscribe?.();
|
|
113
|
+
this._rpcUnsubscribe = void 0;
|
|
114
|
+
}
|
|
115
|
+
_validateToolId(id) {
|
|
116
|
+
if (this.tools.has(id)) throw logger.DF0015({ id }).throw();
|
|
117
|
+
if (this.context.rpc.definitions.get(id)?.agent) throw logger.DF0015({ id }).throw();
|
|
118
|
+
}
|
|
119
|
+
_projectTool(input) {
|
|
120
|
+
if (!input.description || typeof input.description !== "string") throw logger.DF0014({ name: input.id }).throw();
|
|
121
|
+
return {
|
|
122
|
+
id: input.id,
|
|
123
|
+
kind: "tool",
|
|
124
|
+
title: input.title ?? input.id,
|
|
125
|
+
description: input.description,
|
|
126
|
+
safety: input.safety ?? "action",
|
|
127
|
+
tags: input.tags,
|
|
128
|
+
inputSchema: input.inputSchema,
|
|
129
|
+
outputSchema: input.outputSchema,
|
|
130
|
+
examples: input.examples
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
_collectRpcTools() {
|
|
134
|
+
const out = [];
|
|
135
|
+
for (const [name, def] of this.context.rpc.definitions) {
|
|
136
|
+
const agent = def.agent;
|
|
137
|
+
if (!agent) continue;
|
|
138
|
+
if (!agent.description || typeof agent.description !== "string") throw logger.DF0014({ name }).throw();
|
|
139
|
+
const type = def.type ?? "query";
|
|
140
|
+
const safety = agent.safety ?? inferSafety(type);
|
|
141
|
+
out.push({
|
|
142
|
+
id: name,
|
|
143
|
+
kind: "rpc",
|
|
144
|
+
title: agent.title ?? name,
|
|
145
|
+
description: agent.description,
|
|
146
|
+
safety,
|
|
147
|
+
tags: agent.tags,
|
|
148
|
+
rpcName: name,
|
|
149
|
+
examples: agent.examples
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return out;
|
|
153
|
+
}
|
|
154
|
+
_findRpcDefinition(id) {
|
|
155
|
+
const def = this.context.rpc.definitions.get(id);
|
|
156
|
+
if (def?.agent) return def;
|
|
157
|
+
}
|
|
158
|
+
_coercePositionalArgs(args, def) {
|
|
159
|
+
if (Array.isArray(args)) return args;
|
|
160
|
+
if (args === void 0 || args === null) return [];
|
|
161
|
+
if (args && typeof args === "object") {
|
|
162
|
+
const obj = args;
|
|
163
|
+
const schemas = def.args;
|
|
164
|
+
if (schemas && schemas.length) return schemas.map((_, i) => obj[`arg${i}`]);
|
|
165
|
+
if (hasPositionalKeys(obj)) {
|
|
166
|
+
const out = [];
|
|
167
|
+
let i = 0;
|
|
168
|
+
while (`arg${i}` in obj) {
|
|
169
|
+
out.push(obj[`arg${i}`]);
|
|
170
|
+
i++;
|
|
171
|
+
}
|
|
172
|
+
return out;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return [args];
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
function inferSafety(type) {
|
|
179
|
+
if (type === "static" || type === "query") return "read";
|
|
180
|
+
return "action";
|
|
181
|
+
}
|
|
182
|
+
function hasPositionalKeys(obj) {
|
|
183
|
+
return "arg0" in obj;
|
|
184
|
+
}
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/node/host-diagnostics.ts
|
|
187
|
+
var DevToolsDiagnosticsHost = class {
|
|
188
|
+
_definitions = [];
|
|
189
|
+
_logger;
|
|
190
|
+
defineDiagnostics = defineDiagnostics;
|
|
191
|
+
createLogger = createLogger;
|
|
192
|
+
constructor(context, initialDefinitions = []) {
|
|
193
|
+
this.context = context;
|
|
194
|
+
this._definitions = [...initialDefinitions];
|
|
195
|
+
this._rebuild();
|
|
196
|
+
}
|
|
197
|
+
get logger() {
|
|
198
|
+
return this._logger;
|
|
199
|
+
}
|
|
200
|
+
register(definitions) {
|
|
201
|
+
this._definitions.push(definitions);
|
|
202
|
+
this._rebuild();
|
|
203
|
+
}
|
|
204
|
+
_rebuild() {
|
|
205
|
+
this._logger = createLogger({
|
|
206
|
+
diagnostics: this._definitions,
|
|
207
|
+
formatter: ansiFormatter(c),
|
|
208
|
+
reporters: consoleReporter
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
//#endregion
|
|
213
|
+
//#region ../../../node_modules/.pnpm/obug@2.1.1/node_modules/obug/dist/core.js
|
|
214
|
+
function coerce(value) {
|
|
215
|
+
if (value instanceof Error) return value.stack || value.message;
|
|
216
|
+
return value;
|
|
217
|
+
}
|
|
218
|
+
function selectColor(colors, namespace) {
|
|
219
|
+
let hash = 0;
|
|
220
|
+
for (let i = 0; i < namespace.length; i++) {
|
|
221
|
+
hash = (hash << 5) - hash + namespace.charCodeAt(i);
|
|
222
|
+
hash |= 0;
|
|
223
|
+
}
|
|
224
|
+
return colors[Math.abs(hash) % colors.length];
|
|
225
|
+
}
|
|
226
|
+
function matchesTemplate(search, template) {
|
|
227
|
+
let searchIndex = 0;
|
|
228
|
+
let templateIndex = 0;
|
|
229
|
+
let starIndex = -1;
|
|
230
|
+
let matchIndex = 0;
|
|
231
|
+
while (searchIndex < search.length) if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === "*")) if (template[templateIndex] === "*") {
|
|
232
|
+
starIndex = templateIndex;
|
|
233
|
+
matchIndex = searchIndex;
|
|
234
|
+
templateIndex++;
|
|
235
|
+
} else {
|
|
236
|
+
searchIndex++;
|
|
237
|
+
templateIndex++;
|
|
238
|
+
}
|
|
239
|
+
else if (starIndex !== -1) {
|
|
240
|
+
templateIndex = starIndex + 1;
|
|
241
|
+
matchIndex++;
|
|
242
|
+
searchIndex = matchIndex;
|
|
243
|
+
} else return false;
|
|
244
|
+
while (templateIndex < template.length && template[templateIndex] === "*") templateIndex++;
|
|
245
|
+
return templateIndex === template.length;
|
|
246
|
+
}
|
|
247
|
+
function humanize(value) {
|
|
248
|
+
if (value >= 1e3) return `${(value / 1e3).toFixed(1)}s`;
|
|
249
|
+
return `${value}ms`;
|
|
250
|
+
}
|
|
251
|
+
let globalNamespaces = "";
|
|
252
|
+
function createDebug$1(namespace, options) {
|
|
253
|
+
let prevTime;
|
|
254
|
+
let enableOverride;
|
|
255
|
+
let namespacesCache;
|
|
256
|
+
let enabledCache;
|
|
257
|
+
const debug = (...args) => {
|
|
258
|
+
if (!debug.enabled) return;
|
|
259
|
+
const curr = Date.now();
|
|
260
|
+
const diff = curr - (prevTime || curr);
|
|
261
|
+
prevTime = curr;
|
|
262
|
+
args[0] = coerce(args[0]);
|
|
263
|
+
if (typeof args[0] !== "string") args.unshift("%O");
|
|
264
|
+
let index = 0;
|
|
265
|
+
args[0] = args[0].replace(/%([a-z%])/gi, (match, format) => {
|
|
266
|
+
if (match === "%%") return "%";
|
|
267
|
+
index++;
|
|
268
|
+
const formatter = options.formatters[format];
|
|
269
|
+
if (typeof formatter === "function") {
|
|
270
|
+
const value = args[index];
|
|
271
|
+
match = formatter.call(debug, value);
|
|
272
|
+
args.splice(index, 1);
|
|
273
|
+
index--;
|
|
274
|
+
}
|
|
275
|
+
return match;
|
|
276
|
+
});
|
|
277
|
+
options.formatArgs.call(debug, diff, args);
|
|
278
|
+
debug.log(...args);
|
|
279
|
+
};
|
|
280
|
+
debug.extend = function(namespace$1, delimiter = ":") {
|
|
281
|
+
return createDebug$1(this.namespace + delimiter + namespace$1, {
|
|
282
|
+
useColors: this.useColors,
|
|
283
|
+
color: this.color,
|
|
284
|
+
formatArgs: this.formatArgs,
|
|
285
|
+
formatters: this.formatters,
|
|
286
|
+
inspectOpts: this.inspectOpts,
|
|
287
|
+
log: this.log,
|
|
288
|
+
humanize: this.humanize
|
|
289
|
+
});
|
|
290
|
+
};
|
|
291
|
+
Object.assign(debug, options);
|
|
292
|
+
debug.namespace = namespace;
|
|
293
|
+
Object.defineProperty(debug, "enabled", {
|
|
294
|
+
enumerable: true,
|
|
295
|
+
configurable: false,
|
|
296
|
+
get: () => {
|
|
297
|
+
if (enableOverride != null) return enableOverride;
|
|
298
|
+
if (namespacesCache !== globalNamespaces) {
|
|
299
|
+
namespacesCache = globalNamespaces;
|
|
300
|
+
enabledCache = enabled(namespace);
|
|
301
|
+
}
|
|
302
|
+
return enabledCache;
|
|
303
|
+
},
|
|
304
|
+
set: (v) => {
|
|
305
|
+
enableOverride = v;
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
return debug;
|
|
309
|
+
}
|
|
310
|
+
let names = [];
|
|
311
|
+
let skips = [];
|
|
312
|
+
function enable(namespaces$1) {
|
|
313
|
+
globalNamespaces = namespaces$1;
|
|
314
|
+
names = [];
|
|
315
|
+
skips = [];
|
|
316
|
+
const split = globalNamespaces.trim().replace(/\s+/g, ",").split(",").filter(Boolean);
|
|
317
|
+
for (const ns of split) if (ns[0] === "-") skips.push(ns.slice(1));
|
|
318
|
+
else names.push(ns);
|
|
319
|
+
}
|
|
320
|
+
function enabled(name) {
|
|
321
|
+
for (const skip of skips) if (matchesTemplate(name, skip)) return false;
|
|
322
|
+
for (const ns of names) if (matchesTemplate(name, ns)) return true;
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
//#endregion
|
|
326
|
+
//#region ../../../node_modules/.pnpm/obug@2.1.1/node_modules/obug/dist/node.js
|
|
327
|
+
const colors = process.stderr.getColorDepth && process.stderr.getColorDepth() > 2 ? [
|
|
328
|
+
20,
|
|
329
|
+
21,
|
|
330
|
+
26,
|
|
331
|
+
27,
|
|
332
|
+
32,
|
|
333
|
+
33,
|
|
334
|
+
38,
|
|
335
|
+
39,
|
|
336
|
+
40,
|
|
337
|
+
41,
|
|
338
|
+
42,
|
|
339
|
+
43,
|
|
340
|
+
44,
|
|
341
|
+
45,
|
|
342
|
+
56,
|
|
343
|
+
57,
|
|
344
|
+
62,
|
|
345
|
+
63,
|
|
346
|
+
68,
|
|
347
|
+
69,
|
|
348
|
+
74,
|
|
349
|
+
75,
|
|
350
|
+
76,
|
|
351
|
+
77,
|
|
352
|
+
78,
|
|
353
|
+
79,
|
|
354
|
+
80,
|
|
355
|
+
81,
|
|
356
|
+
92,
|
|
357
|
+
93,
|
|
358
|
+
98,
|
|
359
|
+
99,
|
|
360
|
+
112,
|
|
361
|
+
113,
|
|
362
|
+
128,
|
|
363
|
+
129,
|
|
364
|
+
134,
|
|
365
|
+
135,
|
|
366
|
+
148,
|
|
367
|
+
149,
|
|
368
|
+
160,
|
|
369
|
+
161,
|
|
370
|
+
162,
|
|
371
|
+
163,
|
|
372
|
+
164,
|
|
373
|
+
165,
|
|
374
|
+
166,
|
|
375
|
+
167,
|
|
376
|
+
168,
|
|
377
|
+
169,
|
|
378
|
+
170,
|
|
379
|
+
171,
|
|
380
|
+
172,
|
|
381
|
+
173,
|
|
382
|
+
178,
|
|
383
|
+
179,
|
|
384
|
+
184,
|
|
385
|
+
185,
|
|
386
|
+
196,
|
|
387
|
+
197,
|
|
388
|
+
198,
|
|
389
|
+
199,
|
|
390
|
+
200,
|
|
391
|
+
201,
|
|
392
|
+
202,
|
|
393
|
+
203,
|
|
394
|
+
204,
|
|
395
|
+
205,
|
|
396
|
+
206,
|
|
397
|
+
207,
|
|
398
|
+
208,
|
|
399
|
+
209,
|
|
400
|
+
214,
|
|
401
|
+
215,
|
|
402
|
+
220,
|
|
403
|
+
221
|
|
404
|
+
] : [
|
|
405
|
+
6,
|
|
406
|
+
2,
|
|
407
|
+
3,
|
|
408
|
+
4,
|
|
409
|
+
5,
|
|
410
|
+
1
|
|
411
|
+
];
|
|
412
|
+
const inspectOpts = Object.keys(process.env).filter((key) => /^debug_/i.test(key)).reduce((obj, key) => {
|
|
413
|
+
const prop = key.slice(6).toLowerCase().replace(/_([a-z])/g, (_, k) => k.toUpperCase());
|
|
414
|
+
let value = process.env[key];
|
|
415
|
+
const lowerCase = typeof value === "string" && value.toLowerCase();
|
|
416
|
+
if (value === "null") value = null;
|
|
417
|
+
else if (lowerCase === "yes" || lowerCase === "on" || lowerCase === "true" || lowerCase === "enabled") value = true;
|
|
418
|
+
else if (lowerCase === "no" || lowerCase === "off" || lowerCase === "false" || lowerCase === "disabled") value = false;
|
|
419
|
+
else value = Number(value);
|
|
420
|
+
obj[prop] = value;
|
|
421
|
+
return obj;
|
|
422
|
+
}, {});
|
|
423
|
+
function useColors() {
|
|
424
|
+
return "colors" in inspectOpts ? Boolean(inspectOpts.colors) : isatty(process.stderr.fd);
|
|
425
|
+
}
|
|
426
|
+
function getDate() {
|
|
427
|
+
if (inspectOpts.hideDate) return "";
|
|
428
|
+
return `${(/* @__PURE__ */ new Date()).toISOString()} `;
|
|
429
|
+
}
|
|
430
|
+
function formatArgs(diff, args) {
|
|
431
|
+
const { namespace: name, useColors: useColors$1 } = this;
|
|
432
|
+
if (useColors$1) {
|
|
433
|
+
const c = this.color;
|
|
434
|
+
const colorCode = `\u001B[3${c < 8 ? c : `8;5;${c}`}`;
|
|
435
|
+
const prefix = ` ${colorCode};1m${name} \u001B[0m`;
|
|
436
|
+
args[0] = prefix + args[0].split("\n").join(`\n${prefix}`);
|
|
437
|
+
args.push(`${colorCode}m+${this.humanize(diff)}\u001B[0m`);
|
|
438
|
+
} else args[0] = `${getDate()}${name} ${args[0]}`;
|
|
439
|
+
}
|
|
440
|
+
function log(...args) {
|
|
441
|
+
process.stderr.write(`${formatWithOptions(this.inspectOpts, ...args)}\n`);
|
|
442
|
+
}
|
|
443
|
+
const defaultOptions = {
|
|
444
|
+
useColors: useColors(),
|
|
445
|
+
formatArgs,
|
|
446
|
+
formatters: {
|
|
447
|
+
o(v) {
|
|
448
|
+
this.inspectOpts.colors = this.useColors;
|
|
449
|
+
return inspect(v, this.inspectOpts).split("\n").map((str) => str.trim()).join(" ");
|
|
450
|
+
},
|
|
451
|
+
O(v) {
|
|
452
|
+
this.inspectOpts.colors = this.useColors;
|
|
453
|
+
return inspect(v, this.inspectOpts);
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
inspectOpts,
|
|
457
|
+
log,
|
|
458
|
+
humanize
|
|
459
|
+
};
|
|
460
|
+
function createDebug(namespace, options) {
|
|
461
|
+
var _ref;
|
|
462
|
+
const color = (_ref = options && options.color) !== null && _ref !== void 0 ? _ref : selectColor(colors, namespace);
|
|
463
|
+
return createDebug$1(namespace, Object.assign(defaultOptions, { color }, options));
|
|
464
|
+
}
|
|
465
|
+
enable(process.env.DEBUG || "");
|
|
466
|
+
//#endregion
|
|
467
|
+
//#region src/node/rpc-shared-state.ts
|
|
468
|
+
const debug$1 = createDebug("vite:devtools:rpc:state:changed");
|
|
469
|
+
const debugSubscribe = createDebug("vite:devtools:rpc:state:subscribe");
|
|
470
|
+
function createRpcSharedStateServerHost(rpc) {
|
|
471
|
+
const sharedState = /* @__PURE__ */ new Map();
|
|
472
|
+
const keyAddedListeners = /* @__PURE__ */ new Set();
|
|
473
|
+
function registerSharedState(key, state) {
|
|
474
|
+
const offs = [];
|
|
475
|
+
offs.push(state.on("updated", (fullState, patches, syncId) => {
|
|
476
|
+
if (patches) {
|
|
477
|
+
debug$1("patch", {
|
|
478
|
+
key,
|
|
479
|
+
syncId
|
|
480
|
+
});
|
|
481
|
+
rpc.broadcast({
|
|
482
|
+
method: "devframe:rpc:client-state:patch",
|
|
483
|
+
args: [
|
|
484
|
+
key,
|
|
485
|
+
patches,
|
|
486
|
+
syncId
|
|
487
|
+
],
|
|
488
|
+
filter: (client) => client.$meta.subscribedStates.has(key)
|
|
489
|
+
});
|
|
490
|
+
} else {
|
|
491
|
+
debug$1("updated", {
|
|
492
|
+
key,
|
|
493
|
+
syncId
|
|
494
|
+
});
|
|
495
|
+
rpc.broadcast({
|
|
496
|
+
method: "devframe:rpc:client-state:updated",
|
|
497
|
+
args: [
|
|
498
|
+
key,
|
|
499
|
+
fullState,
|
|
500
|
+
syncId
|
|
501
|
+
],
|
|
502
|
+
filter: (client) => client.$meta.subscribedStates.has(key)
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
}));
|
|
506
|
+
return () => {
|
|
507
|
+
for (const off of offs) off();
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
const host = {
|
|
511
|
+
get: async (key, options) => {
|
|
512
|
+
if (sharedState.has(key)) return sharedState.get(key);
|
|
513
|
+
if (options?.initialValue === void 0 && options?.sharedState === void 0) throw logger.DF0013({ key }).throw();
|
|
514
|
+
debug$1("new-state", key);
|
|
515
|
+
const state = options.sharedState ?? createSharedState({
|
|
516
|
+
initialValue: options.initialValue,
|
|
517
|
+
enablePatches: false
|
|
518
|
+
});
|
|
519
|
+
registerSharedState(key, state);
|
|
520
|
+
sharedState.set(key, state);
|
|
521
|
+
for (const fn of keyAddedListeners) fn(key);
|
|
522
|
+
return state;
|
|
523
|
+
},
|
|
524
|
+
keys() {
|
|
525
|
+
return Array.from(sharedState.keys());
|
|
526
|
+
},
|
|
527
|
+
onKeyAdded(fn) {
|
|
528
|
+
keyAddedListeners.add(fn);
|
|
529
|
+
return () => {
|
|
530
|
+
keyAddedListeners.delete(fn);
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
rpc.register({
|
|
535
|
+
name: "devframe:rpc:server-state:subscribe",
|
|
536
|
+
type: "event",
|
|
537
|
+
handler(key) {
|
|
538
|
+
const session = rpc.getCurrentRpcSession();
|
|
539
|
+
if (!session) return;
|
|
540
|
+
debugSubscribe("subscribe", {
|
|
541
|
+
key,
|
|
542
|
+
session: session.meta.id
|
|
543
|
+
});
|
|
544
|
+
session.meta.subscribedStates.add(key);
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
rpc.register({
|
|
548
|
+
name: "devframe:rpc:server-state:get",
|
|
549
|
+
type: "query",
|
|
550
|
+
handler: async (key) => {
|
|
551
|
+
if (!sharedState.has(key)) return void 0;
|
|
552
|
+
return (await host.get(key)).value();
|
|
553
|
+
},
|
|
554
|
+
dump: () => ({ inputs: host.keys().map((key) => [key]) })
|
|
555
|
+
});
|
|
556
|
+
rpc.register({
|
|
557
|
+
name: "devframe:rpc:server-state:set",
|
|
558
|
+
type: "query",
|
|
559
|
+
handler: async (key, value, syncId) => {
|
|
560
|
+
(await host.get(key, { initialValue: value })).mutate(() => value, syncId);
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
rpc.register({
|
|
564
|
+
name: "devframe:rpc:server-state:patch",
|
|
565
|
+
type: "query",
|
|
566
|
+
handler: async (key, patches, syncId) => {
|
|
567
|
+
if (!sharedState.has(key)) return;
|
|
568
|
+
(await host.get(key)).patch(patches, syncId);
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
return host;
|
|
572
|
+
}
|
|
573
|
+
//#endregion
|
|
574
|
+
//#region src/node/rpc-streaming.ts
|
|
575
|
+
const debug = createDebug("vite:devtools:rpc:streaming");
|
|
576
|
+
const STREAM_KEY_SEPARATOR = "";
|
|
577
|
+
function streamKey(channel, id) {
|
|
578
|
+
return `${channel}${STREAM_KEY_SEPARATOR}${id}`;
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Build the server-side streaming host. Mirrors the layout of
|
|
582
|
+
* `createRpcSharedStateServerHost` — registers a fixed set of internal
|
|
583
|
+
* RPC methods (`subscribe` / `unsubscribe` / `cancel`) once, then per-channel
|
|
584
|
+
* state lives in a `Map<channelName, ChannelState>`.
|
|
585
|
+
*/
|
|
586
|
+
function createRpcStreamingServerHost(rpc) {
|
|
587
|
+
const channels = /* @__PURE__ */ new Map();
|
|
588
|
+
function findStream(channelName, id) {
|
|
589
|
+
return channels.get(channelName)?.streams.get(id);
|
|
590
|
+
}
|
|
591
|
+
function freeStreamNow(state, id) {
|
|
592
|
+
const record = state.streams.get(id);
|
|
593
|
+
if (!record) return;
|
|
594
|
+
if (record.retentionTimer) {
|
|
595
|
+
clearTimeout(record.retentionTimer);
|
|
596
|
+
record.retentionTimer = void 0;
|
|
597
|
+
}
|
|
598
|
+
for (const off of record.unbinders) off();
|
|
599
|
+
state.streams.delete(id);
|
|
600
|
+
debug("freed", state.name, id);
|
|
601
|
+
}
|
|
602
|
+
function maybeFreeStream(state, id) {
|
|
603
|
+
const record = state.streams.get(id);
|
|
604
|
+
if (!record) return;
|
|
605
|
+
if (!record.sink.closed || record.subscribers.size > 0) return;
|
|
606
|
+
const retention = state.options.closedStreamRetention;
|
|
607
|
+
if (retention <= 0) {
|
|
608
|
+
freeStreamNow(state, id);
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
if (record.retentionTimer) return;
|
|
612
|
+
record.retentionTimer = setTimeout(freeStreamNow, retention, state, id);
|
|
613
|
+
}
|
|
614
|
+
function cancelRetention(record) {
|
|
615
|
+
if (record.retentionTimer) {
|
|
616
|
+
clearTimeout(record.retentionTimer);
|
|
617
|
+
record.retentionTimer = void 0;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
rpc.register({
|
|
621
|
+
name: "devframe:streaming:subscribe",
|
|
622
|
+
type: "event",
|
|
623
|
+
handler(channelName, id, opts) {
|
|
624
|
+
const state = channels.get(channelName);
|
|
625
|
+
if (!state) {
|
|
626
|
+
logger.DF0030({
|
|
627
|
+
channel: channelName,
|
|
628
|
+
id
|
|
629
|
+
}).log();
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
const record = state.streams.get(id);
|
|
633
|
+
if (!record) {
|
|
634
|
+
logger.DF0030({
|
|
635
|
+
channel: channelName,
|
|
636
|
+
id
|
|
637
|
+
}).log();
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
const session = rpc.getCurrentRpcSession();
|
|
641
|
+
if (!session) return;
|
|
642
|
+
const key = streamKey(channelName, id);
|
|
643
|
+
session.meta.subscribedStreams ??= /* @__PURE__ */ new Set();
|
|
644
|
+
session.meta.subscribedStreams.add(key);
|
|
645
|
+
record.subscribers.add(session.meta);
|
|
646
|
+
cancelRetention(record);
|
|
647
|
+
const afterSeq = opts?.afterSeq ?? 0;
|
|
648
|
+
for (const buffered of record.sink.buffer) if (buffered.seq > afterSeq) rpc.broadcast({
|
|
649
|
+
method: "devframe:streaming:chunk",
|
|
650
|
+
args: [
|
|
651
|
+
channelName,
|
|
652
|
+
id,
|
|
653
|
+
buffered.seq,
|
|
654
|
+
buffered.chunk
|
|
655
|
+
],
|
|
656
|
+
event: true,
|
|
657
|
+
optional: true,
|
|
658
|
+
filter: (client) => client.$meta === session.meta
|
|
659
|
+
});
|
|
660
|
+
if (record.sink.closed) rpc.broadcast({
|
|
661
|
+
method: "devframe:streaming:end",
|
|
662
|
+
args: [
|
|
663
|
+
channelName,
|
|
664
|
+
id,
|
|
665
|
+
void 0
|
|
666
|
+
],
|
|
667
|
+
event: true,
|
|
668
|
+
optional: true,
|
|
669
|
+
filter: (client) => client.$meta === session.meta
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
});
|
|
673
|
+
rpc.register({
|
|
674
|
+
name: "devframe:streaming:unsubscribe",
|
|
675
|
+
type: "event",
|
|
676
|
+
handler(channelName, id) {
|
|
677
|
+
const state = channels.get(channelName);
|
|
678
|
+
const record = state?.streams.get(id);
|
|
679
|
+
const session = rpc.getCurrentRpcSession();
|
|
680
|
+
if (!session) return;
|
|
681
|
+
session.meta.subscribedStreams?.delete(streamKey(channelName, id));
|
|
682
|
+
if (state && record) {
|
|
683
|
+
record.subscribers.delete(session.meta);
|
|
684
|
+
maybeFreeStream(state, id);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
});
|
|
688
|
+
rpc.register({
|
|
689
|
+
name: "devframe:streaming:cancel",
|
|
690
|
+
type: "event",
|
|
691
|
+
handler(channelName, id) {
|
|
692
|
+
const record = findStream(channelName, id);
|
|
693
|
+
if (!record) return;
|
|
694
|
+
const session = rpc.getCurrentRpcSession();
|
|
695
|
+
if (!session) return;
|
|
696
|
+
record.subscribers.delete(session.meta);
|
|
697
|
+
session.meta.subscribedStreams?.delete(streamKey(channelName, id));
|
|
698
|
+
if (record.subscribers.size === 0) record.sink.abort("cancelled by client");
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
rpc.register({
|
|
702
|
+
name: "devframe:streaming:upload-chunk",
|
|
703
|
+
type: "event",
|
|
704
|
+
handler(channelName, id, seq, chunk) {
|
|
705
|
+
const record = channels.get(channelName)?.inbound.get(id);
|
|
706
|
+
if (!record) {
|
|
707
|
+
logger.DF0030({
|
|
708
|
+
channel: channelName,
|
|
709
|
+
id
|
|
710
|
+
}).log();
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
if (!record.uploaderMeta) {
|
|
714
|
+
const session = rpc.getCurrentRpcSession();
|
|
715
|
+
if (session) {
|
|
716
|
+
record.uploaderMeta = session.meta;
|
|
717
|
+
session.meta.uploadingStreams ??= /* @__PURE__ */ new Set();
|
|
718
|
+
session.meta.uploadingStreams.add(streamKey(channelName, id));
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
record.reader._push(seq, chunk);
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
rpc.register({
|
|
725
|
+
name: "devframe:streaming:upload-end",
|
|
726
|
+
type: "event",
|
|
727
|
+
handler(channelName, id, error) {
|
|
728
|
+
const state = channels.get(channelName);
|
|
729
|
+
const record = state?.inbound.get(id);
|
|
730
|
+
if (!record) return;
|
|
731
|
+
record.reader._end(error);
|
|
732
|
+
if (record.uploaderMeta) record.uploaderMeta.uploadingStreams?.delete(streamKey(channelName, id));
|
|
733
|
+
state?.inbound.delete(id);
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
function createChannel(name, opts = {}) {
|
|
737
|
+
if (channels.has(name)) throw logger.DF0032({ channel: name }).throw();
|
|
738
|
+
const replayWindow = opts.replayWindow ?? 0;
|
|
739
|
+
const state = {
|
|
740
|
+
name,
|
|
741
|
+
options: {
|
|
742
|
+
replayWindow,
|
|
743
|
+
closedStreamRetention: opts.closedStreamRetention ?? (replayWindow > 0 ? 3e4 : 0)
|
|
744
|
+
},
|
|
745
|
+
streams: /* @__PURE__ */ new Map(),
|
|
746
|
+
inbound: /* @__PURE__ */ new Map()
|
|
747
|
+
};
|
|
748
|
+
channels.set(name, state);
|
|
749
|
+
function start(startOpts = {}) {
|
|
750
|
+
const sink = createStreamSink({
|
|
751
|
+
id: startOpts.id,
|
|
752
|
+
replayWindow: state.options.replayWindow
|
|
753
|
+
});
|
|
754
|
+
const record = {
|
|
755
|
+
sink,
|
|
756
|
+
subscribers: /* @__PURE__ */ new Set(),
|
|
757
|
+
unbinders: []
|
|
758
|
+
};
|
|
759
|
+
state.streams.set(sink.id, record);
|
|
760
|
+
record.unbinders.push(sink.events.on("chunk", (seq, chunk) => {
|
|
761
|
+
rpc.broadcast({
|
|
762
|
+
method: "devframe:streaming:chunk",
|
|
763
|
+
args: [
|
|
764
|
+
name,
|
|
765
|
+
sink.id,
|
|
766
|
+
seq,
|
|
767
|
+
chunk
|
|
768
|
+
],
|
|
769
|
+
event: true,
|
|
770
|
+
optional: true,
|
|
771
|
+
filter: (client) => record.subscribers.has(client.$meta)
|
|
772
|
+
});
|
|
773
|
+
}));
|
|
774
|
+
record.unbinders.push(sink.events.on("end", (error) => {
|
|
775
|
+
rpc.broadcast({
|
|
776
|
+
method: "devframe:streaming:end",
|
|
777
|
+
args: [
|
|
778
|
+
name,
|
|
779
|
+
sink.id,
|
|
780
|
+
error
|
|
781
|
+
],
|
|
782
|
+
event: true,
|
|
783
|
+
optional: true,
|
|
784
|
+
filter: (client) => record.subscribers.has(client.$meta)
|
|
785
|
+
});
|
|
786
|
+
maybeFreeStream(state, sink.id);
|
|
787
|
+
}));
|
|
788
|
+
return sink;
|
|
789
|
+
}
|
|
790
|
+
async function pipeFrom(readable, startOpts = {}) {
|
|
791
|
+
const sink = start(startOpts);
|
|
792
|
+
readable.pipeTo(sink.writable, { signal: sink.signal }).catch(() => {});
|
|
793
|
+
return sink;
|
|
794
|
+
}
|
|
795
|
+
function get(id) {
|
|
796
|
+
return state.streams.get(id)?.sink;
|
|
797
|
+
}
|
|
798
|
+
function ids() {
|
|
799
|
+
return Array.from(state.streams.keys());
|
|
800
|
+
}
|
|
801
|
+
function openInbound(inboundOpts = {}) {
|
|
802
|
+
let inboundRecord;
|
|
803
|
+
const reader = createStreamReader({
|
|
804
|
+
id: inboundOpts.id,
|
|
805
|
+
onCancel() {
|
|
806
|
+
const targetMeta = inboundRecord?.uploaderMeta;
|
|
807
|
+
if (!targetMeta) return;
|
|
808
|
+
rpc.broadcast({
|
|
809
|
+
method: "devframe:streaming:upload-cancel",
|
|
810
|
+
args: [name, reader.id],
|
|
811
|
+
event: true,
|
|
812
|
+
optional: true,
|
|
813
|
+
filter: (client) => client.$meta === targetMeta
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
});
|
|
817
|
+
inboundRecord = { reader };
|
|
818
|
+
state.inbound.set(reader.id, inboundRecord);
|
|
819
|
+
debug("opened-inbound", name, reader.id);
|
|
820
|
+
return reader;
|
|
821
|
+
}
|
|
822
|
+
return {
|
|
823
|
+
name,
|
|
824
|
+
start,
|
|
825
|
+
pipeFrom,
|
|
826
|
+
get,
|
|
827
|
+
ids,
|
|
828
|
+
openInbound
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
function parseKey(key) {
|
|
832
|
+
const sepIdx = key.indexOf(STREAM_KEY_SEPARATOR);
|
|
833
|
+
if (sepIdx < 0) return void 0;
|
|
834
|
+
return {
|
|
835
|
+
channelName: key.slice(0, sepIdx),
|
|
836
|
+
id: key.slice(sepIdx + 1)
|
|
837
|
+
};
|
|
838
|
+
}
|
|
839
|
+
return {
|
|
840
|
+
create: createChannel,
|
|
841
|
+
_onSessionDisconnected(meta) {
|
|
842
|
+
if (meta.subscribedStreams) {
|
|
843
|
+
for (const key of meta.subscribedStreams) {
|
|
844
|
+
const parsed = parseKey(key);
|
|
845
|
+
if (!parsed) continue;
|
|
846
|
+
const state = channels.get(parsed.channelName);
|
|
847
|
+
const record = state?.streams.get(parsed.id);
|
|
848
|
+
if (!state || !record) continue;
|
|
849
|
+
record.subscribers.delete(meta);
|
|
850
|
+
if (record.subscribers.size === 0 && !record.sink.closed) record.sink.abort("all subscribers disconnected");
|
|
851
|
+
maybeFreeStream(state, parsed.id);
|
|
852
|
+
}
|
|
853
|
+
meta.subscribedStreams.clear();
|
|
854
|
+
}
|
|
855
|
+
if (meta.uploadingStreams) {
|
|
856
|
+
for (const key of meta.uploadingStreams) {
|
|
857
|
+
const parsed = parseKey(key);
|
|
858
|
+
if (!parsed) continue;
|
|
859
|
+
const state = channels.get(parsed.channelName);
|
|
860
|
+
const record = state?.inbound.get(parsed.id);
|
|
861
|
+
if (!state || !record) continue;
|
|
862
|
+
record.reader._end({
|
|
863
|
+
name: "UploadDisconnected",
|
|
864
|
+
message: "Uploader disconnected before completing the stream"
|
|
865
|
+
});
|
|
866
|
+
state.inbound.delete(parsed.id);
|
|
867
|
+
}
|
|
868
|
+
meta.uploadingStreams.clear();
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
//#endregion
|
|
874
|
+
//#region src/node/host-functions.ts
|
|
875
|
+
const debugBroadcast = createDebug("vite:devtools:rpc:broadcast");
|
|
876
|
+
var RpcFunctionsHost = class extends RpcFunctionsCollectorBase {
|
|
877
|
+
/**
|
|
878
|
+
* @internal
|
|
879
|
+
*/
|
|
880
|
+
_rpcGroup = void 0;
|
|
881
|
+
_asyncStorage = void 0;
|
|
882
|
+
constructor(context) {
|
|
883
|
+
super(context);
|
|
884
|
+
this.sharedState = createRpcSharedStateServerHost(this);
|
|
885
|
+
this.streaming = createRpcStreamingServerHost(this);
|
|
886
|
+
}
|
|
887
|
+
sharedState;
|
|
888
|
+
streaming;
|
|
889
|
+
/**
|
|
890
|
+
* Adapters call this from their WS `onDisconnected` hook so downstream
|
|
891
|
+
* hosts (streaming, …) can free per-session state. Public-ish because
|
|
892
|
+
* tests / custom adapters may want to mirror it.
|
|
893
|
+
*
|
|
894
|
+
* @internal
|
|
895
|
+
*/
|
|
896
|
+
_emitSessionDisconnected(meta) {
|
|
897
|
+
this.streaming._onSessionDisconnected(meta);
|
|
898
|
+
}
|
|
899
|
+
async invokeLocal(method, ...args) {
|
|
900
|
+
if (!this.definitions.has(method)) throw logger.DF0006({ name: String(method) }).throw();
|
|
901
|
+
const handler = await this.getHandler(method);
|
|
902
|
+
return await Promise.resolve(handler(...args));
|
|
903
|
+
}
|
|
904
|
+
async broadcast(options) {
|
|
905
|
+
if (!this._rpcGroup) return;
|
|
906
|
+
debugBroadcast(JSON.stringify(options.method));
|
|
907
|
+
await Promise.allSettled(this._rpcGroup.clients.map((client) => {
|
|
908
|
+
if (options.filter?.(client) === false) return void 0;
|
|
909
|
+
return client.$callRaw({
|
|
910
|
+
optional: true,
|
|
911
|
+
event: true,
|
|
912
|
+
...options
|
|
913
|
+
});
|
|
914
|
+
}));
|
|
915
|
+
}
|
|
916
|
+
getCurrentRpcSession() {
|
|
917
|
+
if (!this._asyncStorage) throw logger.DF0007().throw();
|
|
918
|
+
return this._asyncStorage.getStore();
|
|
919
|
+
}
|
|
920
|
+
};
|
|
921
|
+
//#endregion
|
|
922
|
+
//#region src/node/host-views.ts
|
|
923
|
+
var DevToolsViewHost = class {
|
|
924
|
+
/**
|
|
925
|
+
* @internal
|
|
926
|
+
*/
|
|
927
|
+
buildStaticDirs = [];
|
|
928
|
+
constructor(context) {
|
|
929
|
+
this.context = context;
|
|
930
|
+
}
|
|
931
|
+
hostStatic(baseUrl, distDir) {
|
|
932
|
+
if (!existsSync(distDir)) throw logger.DF0008({ distDir }).throw();
|
|
933
|
+
this.buildStaticDirs.push({
|
|
934
|
+
baseUrl,
|
|
935
|
+
distDir
|
|
936
|
+
});
|
|
937
|
+
this.context.host.mountStatic(baseUrl, distDir);
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
//#endregion
|
|
941
|
+
//#region src/node/rpc/agent-invoke-tool.ts
|
|
942
|
+
const agentInvokeTool = defineRpcFunction({
|
|
943
|
+
name: "devframe:agent:invoke-tool",
|
|
944
|
+
type: "action",
|
|
945
|
+
setup: (ctx) => {
|
|
946
|
+
return { async handler(id, args) {
|
|
947
|
+
return await ctx.agent.invoke(id, args);
|
|
948
|
+
} };
|
|
949
|
+
}
|
|
950
|
+
});
|
|
951
|
+
//#endregion
|
|
952
|
+
//#region src/node/rpc/agent-list-resources.ts
|
|
953
|
+
const agentListResources = defineRpcFunction({
|
|
954
|
+
name: "devframe:agent:list-resources",
|
|
955
|
+
type: "query",
|
|
956
|
+
jsonSerializable: true,
|
|
957
|
+
setup: (ctx) => {
|
|
958
|
+
return { async handler() {
|
|
959
|
+
return ctx.agent.list().resources;
|
|
960
|
+
} };
|
|
961
|
+
}
|
|
962
|
+
});
|
|
963
|
+
//#endregion
|
|
964
|
+
//#region src/node/rpc/index.ts
|
|
965
|
+
/**
|
|
966
|
+
* Built-in agent introspection RPC functions. Registered automatically
|
|
967
|
+
* by `createHostContext`. Not themselves agent-exposed (no `agent`
|
|
968
|
+
* field) — they power the MCP adapter and any future agent CLI.
|
|
969
|
+
*
|
|
970
|
+
* @experimental
|
|
971
|
+
*/
|
|
972
|
+
const BUILTIN_AGENT_RPC = [
|
|
973
|
+
defineRpcFunction({
|
|
974
|
+
name: "devframe:agent:list-tools",
|
|
975
|
+
type: "query",
|
|
976
|
+
jsonSerializable: true,
|
|
977
|
+
setup: (ctx) => {
|
|
978
|
+
return { async handler() {
|
|
979
|
+
return ctx.agent.list().tools;
|
|
980
|
+
} };
|
|
981
|
+
}
|
|
982
|
+
}),
|
|
983
|
+
agentInvokeTool,
|
|
984
|
+
agentListResources,
|
|
985
|
+
defineRpcFunction({
|
|
986
|
+
name: "devframe:agent:read-resource",
|
|
987
|
+
type: "query",
|
|
988
|
+
jsonSerializable: true,
|
|
989
|
+
setup: (ctx) => {
|
|
990
|
+
return { async handler(id) {
|
|
991
|
+
return await ctx.agent.read(id);
|
|
992
|
+
} };
|
|
993
|
+
}
|
|
994
|
+
})
|
|
995
|
+
];
|
|
996
|
+
//#endregion
|
|
997
|
+
//#region src/node/context.ts
|
|
998
|
+
/**
|
|
999
|
+
* Framework-neutral core of the DevTools node context. Wires the RPC
|
|
1000
|
+
* host, view (HTTP file-serving) host, diagnostics, and agent
|
|
1001
|
+
* subsystems plus the JSON-render factory. Hub-level subsystems
|
|
1002
|
+
* (`docks`, `terminals`, `messages`, `commands`) are owned by
|
|
1003
|
+
* `@vitejs/devtools-kit` — its `createKitContext` wraps this and
|
|
1004
|
+
* attaches them when the devtool is mounted into a multi-integration
|
|
1005
|
+
* hub.
|
|
1006
|
+
*/
|
|
1007
|
+
async function createHostContext(options) {
|
|
1008
|
+
const { cwd, workspaceRoot = cwd, mode, host, builtinRpcDeclarations = [] } = options;
|
|
1009
|
+
const context = {
|
|
1010
|
+
cwd,
|
|
1011
|
+
workspaceRoot,
|
|
1012
|
+
mode,
|
|
1013
|
+
host,
|
|
1014
|
+
rpc: void 0,
|
|
1015
|
+
views: void 0,
|
|
1016
|
+
diagnostics: void 0,
|
|
1017
|
+
agent: void 0,
|
|
1018
|
+
createJsonRenderer: void 0
|
|
1019
|
+
};
|
|
1020
|
+
const rpcHost = new RpcFunctionsHost(context);
|
|
1021
|
+
const viewsHost = new DevToolsViewHost(context);
|
|
1022
|
+
const diagnosticsHost = new DevToolsDiagnosticsHost(context, [diagnostics$1, diagnostics]);
|
|
1023
|
+
context.rpc = rpcHost;
|
|
1024
|
+
context.views = viewsHost;
|
|
1025
|
+
context.diagnostics = diagnosticsHost;
|
|
1026
|
+
context.agent = new DevToolsAgentHost(context);
|
|
1027
|
+
let jrCounter = 0;
|
|
1028
|
+
context.createJsonRenderer = (initialSpec) => {
|
|
1029
|
+
const stateKey = `devframe:json-render:${jrCounter++}`;
|
|
1030
|
+
const statePromise = rpcHost.sharedState.get(stateKey, { initialValue: initialSpec });
|
|
1031
|
+
return {
|
|
1032
|
+
_stateKey: stateKey,
|
|
1033
|
+
async updateSpec(spec) {
|
|
1034
|
+
(await statePromise).mutate(() => spec);
|
|
1035
|
+
},
|
|
1036
|
+
async updateState(newState) {
|
|
1037
|
+
(await statePromise).mutate((draft) => {
|
|
1038
|
+
draft.state = {
|
|
1039
|
+
...draft.state,
|
|
1040
|
+
...newState
|
|
1041
|
+
};
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
};
|
|
1045
|
+
};
|
|
1046
|
+
for (const fn of BUILTIN_AGENT_RPC) rpcHost.register(fn);
|
|
1047
|
+
for (const fn of builtinRpcDeclarations) rpcHost.register(fn);
|
|
1048
|
+
return context;
|
|
1049
|
+
}
|
|
1050
|
+
//#endregion
|
|
1051
|
+
export { createRpcSharedStateServerHost as a, createRpcStreamingServerHost as i, DevToolsViewHost as n, DevToolsDiagnosticsHost as o, RpcFunctionsHost as r, DevToolsAgentHost as s, createHostContext as t };
|