@devframes/plugin-inspect 0.7.16 → 0.8.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/README.md CHANGED
@@ -7,7 +7,9 @@
7
7
  A devframe plugin that inspects *its own* connection (and, when mounted in a
8
8
  host, the host's): browse every registered RPC function with its metadata,
9
9
  invoke read-only `query`/`static` functions and inspect the results, watch
10
- shared-state keys update live, and explore the agent-exposed surface.
10
+ shared-state keys update live, explore the agent-exposed surface, and — while
11
+ running against a live backend — list the other devframe dev servers running
12
+ alongside it.
11
13
 
12
14
  Ported in spirit from the RPC & State panels of
13
15
  [`vitejs/devtools`](https://github.com/vitejs/devtools); rebuilt on devframe's
@@ -54,7 +56,10 @@ All functions are namespaced `devframes:plugin:inspect:*`:
54
56
  | `invoke` | `action` | Invokes a read-only `query`/`static` function by name and returns a result envelope. Refuses `action`/`event` functions. |
55
57
  | `list-state-keys` | `query` (snapshot) | The keys of every shared-state entry on the connection. |
56
58
  | `describe-agent` | `query` (snapshot) | The agent manifest — tools and readable resources. |
59
+ | `list-instances` | `query` (live) | Every devframe dev server currently running on the machine, discovered through the shared instance registry. Powers the read-only Instances tab. |
57
60
 
58
- The three `query` functions are agent-exposed (read-only) and bake into the
59
- static dump, so the inspector still lists functions, state keys, and the agent
60
- surface when deployed as a static SPA.
61
+ The three snapshot `query` functions are agent-exposed (read-only) and bake into
62
+ the static dump, so the inspector still lists functions, state keys, and the
63
+ agent surface when deployed as a static SPA. `list-instances` is live rather
64
+ than baked (the set of running processes is meaningless in a static dump), so
65
+ the Instances tab appears only against a live backend.
package/dist/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as inspectDevframe } from "./src-B0I3jZUe.mjs";
1
+ import { n as inspectDevframe } from "./src-DE4XzhQt.mjs";
2
2
  import { createCac } from "devframe/adapters/cac";
3
3
  //#region src/cli.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { a as RpcFunctionInfo, i as RpcFunctionAgentInfo, n as DevframeInspectCommandInfo, r as InvokeResult, t as AgentManifest } from "../types-C1KvyFRp.mjs";
1
+ import { a as RpcFunctionAgentInfo, i as InvokeResult, n as DevframeInspectCommandInfo, o as RpcFunctionInfo, r as DevframeInspectInstanceInfo, t as AgentManifest } from "../types-_vo7QhmS.mjs";
2
2
  import { DevframeConnectionStatus, DevframeRpcClient, DevframeRpcClientOptions } from "devframe/client";
3
3
  //#region src/client/index.d.ts
4
4
  /**
@@ -8,4 +8,4 @@ import { DevframeConnectionStatus, DevframeRpcClient, DevframeRpcClientOptions }
8
8
  */
9
9
  declare function connectInspect(options?: DevframeRpcClientOptions): Promise<DevframeRpcClient>;
10
10
  //#endregion
11
- export { type AgentManifest, type DevframeConnectionStatus, type DevframeInspectCommandInfo, type DevframeRpcClient, type InvokeResult, type RpcFunctionAgentInfo, type RpcFunctionInfo, connectInspect };
11
+ export { type AgentManifest, type DevframeConnectionStatus, type DevframeInspectCommandInfo, type DevframeInspectInstanceInfo, type DevframeRpcClient, type InvokeResult, type RpcFunctionAgentInfo, type RpcFunctionInfo, connectInspect };
@@ -1,4 +1,4 @@
1
- import "./types-C1KvyFRp.mjs";
1
+ import "./types-_vo7QhmS.mjs";
2
2
  import { DevframeDefinition } from "devframe/types";
3
3
  //#region src/index.d.ts
4
4
  interface InspectDevframeOptions {
package/dist/index.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import { a as RpcFunctionInfo, r as InvokeResult } from "./types-C1KvyFRp.mjs";
2
- import { n as createInspectDevframe, r as inspectDevframe, t as InspectDevframeOptions } from "./index-HaJd7k1e.mjs";
1
+ import { i as InvokeResult, o as RpcFunctionInfo } from "./types-_vo7QhmS.mjs";
2
+ import { n as createInspectDevframe, r as inspectDevframe, t as InspectDevframeOptions } from "./index-B7KBbd3U.mjs";
3
3
  export { InspectDevframeOptions, type InvokeResult, type RpcFunctionInfo, createInspectDevframe, inspectDevframe as default };
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as inspectDevframe, t as createInspectDevframe } from "./src-B0I3jZUe.mjs";
1
+ import { n as inspectDevframe, t as createInspectDevframe } from "./src-DE4XzhQt.mjs";
2
2
  export { createInspectDevframe, inspectDevframe as default };
@@ -1,4 +1,4 @@
1
- import { t as serverFunctions } from "../rpc-Blq-HUIF.mjs";
1
+ import { t as serverFunctions } from "../rpc-BCuMcHnd.mjs";
2
2
  //#region src/node/index.ts
3
3
  /**
4
4
  * Register the inspector's introspection RPC functions on a devframe
@@ -1,5 +1,5 @@
1
- import { a as RpcFunctionInfo, n as DevframeInspectCommandInfo, r as InvokeResult } from "../types-C1KvyFRp.mjs";
2
- import "../index-HaJd7k1e.mjs";
1
+ import { i as InvokeResult, n as DevframeInspectCommandInfo, o as RpcFunctionInfo, r as DevframeInspectInstanceInfo } from "../types-_vo7QhmS.mjs";
2
+ import "../index-B7KBbd3U.mjs";
3
3
  import { RpcDefinitionsToFunctions } from "devframe/rpc";
4
4
  //#region src/rpc/index.d.ts
5
5
  /**
@@ -118,6 +118,20 @@ declare const serverFunctions: readonly [{
118
118
  snapshot?: boolean;
119
119
  __cache?: WeakMap<object, import("devframe/rpc").Thenable<import("devframe/rpc").RpcFunctionSetupResult<[id: string, args?: unknown[] | undefined], Promise<InvokeResult>>>> | undefined;
120
120
  __promise?: import("devframe/rpc").Thenable<import("devframe/rpc").RpcFunctionSetupResult<[id: string, args?: unknown[] | undefined], Promise<InvokeResult>>> | undefined;
121
+ }, {
122
+ name: "devframes:plugin:inspect:list-instances";
123
+ type?: "query" | undefined;
124
+ cacheable?: boolean;
125
+ args?: undefined;
126
+ returns?: undefined;
127
+ jsonSerializable?: boolean;
128
+ agent?: import("devframe").RpcFunctionAgentOptions;
129
+ setup?: ((context: import("devframe").DevframeNodeContext) => import("devframe/rpc").Thenable<import("devframe/rpc").RpcFunctionSetupResult<[], Promise<DevframeInspectInstanceInfo[]>>>) | undefined;
130
+ handler?: (() => Promise<DevframeInspectInstanceInfo[]>) | undefined;
131
+ dump?: import("devframe/rpc").RpcDump<[], Promise<DevframeInspectInstanceInfo[]>, import("devframe").DevframeNodeContext> | undefined;
132
+ snapshot?: boolean;
133
+ __cache?: WeakMap<object, import("devframe/rpc").Thenable<import("devframe/rpc").RpcFunctionSetupResult<[], Promise<DevframeInspectInstanceInfo[]>>>> | undefined;
134
+ __promise?: import("devframe/rpc").Thenable<import("devframe/rpc").RpcFunctionSetupResult<[], Promise<DevframeInspectInstanceInfo[]>>> | undefined;
121
135
  }];
122
136
  declare module 'devframe' {
123
137
  interface DevframeRpcServerFunctions extends RpcDefinitionsToFunctions<typeof serverFunctions> {}
@@ -1,2 +1,2 @@
1
- import { t as serverFunctions } from "../rpc-Blq-HUIF.mjs";
1
+ import { t as serverFunctions } from "../rpc-BCuMcHnd.mjs";
2
2
  export { serverFunctions };
@@ -1,6 +1,8 @@
1
1
  import { createDefineWrapperWithContext } from "devframe/rpc";
2
2
  import { defineDiagnostics } from "nostics";
3
3
  import { toJsonSchema } from "@valibot/to-json-schema";
4
+ import process from "node:process";
5
+ import { listLiveDevframeInstances } from "devframe/node";
4
6
  //#region src/rpc/functions/_define.ts
5
7
  /**
6
8
  * `defineRpcFunction` pre-bound to the framework-neutral
@@ -236,39 +238,128 @@ const FALLBACK_SCHEMA = Object.freeze({
236
238
  additionalProperties: true
237
239
  });
238
240
  /**
239
- * Convert a valibot return schema to JSON Schema, swallowing
240
- * conversion failures (unsupported valibot actions) into a permissive
241
- * fallback so introspection never throws.
241
+ * Convert a schema to JSON Schema for the inspector, vendor-neutrally.
242
+ *
243
+ * Prefers the schema's own Standard JSON Schema converter
244
+ * (`~standard.jsonSchema`, implemented by e.g. zod 4), then falls back to
245
+ * valibot's converter, then to a permissive object — so introspection never
246
+ * throws regardless of which validator produced the schema.
242
247
  */
243
- function returnSchemaToJson(schema) {
244
- if (!schema) return void 0;
248
+ function convert(schema) {
249
+ const standard = schema["~standard"];
245
250
  try {
251
+ if (standard.jsonSchema) return standard.jsonSchema.input({ target: "draft-2020-12" });
246
252
  return toJsonSchema(schema);
247
253
  } catch {
248
254
  return FALLBACK_SCHEMA;
249
255
  }
250
256
  }
251
257
  /**
252
- * Convert the positional args valibot schemas to a single JSON Schema
253
- * tuple (`type: 'array'` + `prefixItems`). Returns `undefined` when the
254
- * function declares no args.
258
+ * Convert an RPC return schema to JSON Schema, swallowing conversion
259
+ * failures into a permissive fallback so introspection never throws.
260
+ */
261
+ function returnSchemaToJson(schema) {
262
+ if (!schema) return void 0;
263
+ return convert(schema);
264
+ }
265
+ /**
266
+ * Convert positional args schemas to a single JSON Schema tuple
267
+ * (`type: 'array'` + `prefixItems`). Returns `undefined` when the function
268
+ * declares no args.
255
269
  */
256
270
  function argsSchemaToJson(args) {
257
271
  if (!args || args.length === 0) return void 0;
258
272
  return {
259
273
  type: "array",
260
- prefixItems: args.map((arg) => {
261
- try {
262
- return toJsonSchema(arg);
263
- } catch {
264
- return FALLBACK_SCHEMA;
265
- }
266
- })
274
+ prefixItems: args.map((arg) => convert(arg))
267
275
  };
268
276
  }
269
277
  //#endregion
270
278
  //#region src/rpc/functions/list-functions.ts
271
279
  const INVOKABLE_TYPES = /* @__PURE__ */ new Set(["query", "static"]);
280
+ /**
281
+ * Enumerate every RPC function registered on the connection, projecting
282
+ * each definition's metadata into a JSON-safe {@link RpcFunctionInfo}.
283
+ * `snapshot: true` bakes the registry into the static dump so the
284
+ * inspector still lists functions in `build`/`spa` mode.
285
+ */
286
+ const listFunctions = defineInspectRpc({
287
+ name: "devframes:plugin:inspect:list-functions",
288
+ type: "query",
289
+ jsonSerializable: true,
290
+ snapshot: true,
291
+ agent: {
292
+ description: "List every RPC function registered on this devframe connection, with metadata (name, type, JSON-serializable/snapshot flags, args/return schema, agent exposure). Read-only — the canonical way to discover what the running devframe can do.",
293
+ title: "List RPC functions"
294
+ },
295
+ setup: (ctx) => ({ handler: async () => {
296
+ const out = [];
297
+ for (const [name, fn] of ctx.rpc.definitions) {
298
+ const type = fn.type ?? "query";
299
+ let agent;
300
+ if (fn.agent) agent = {
301
+ description: fn.agent.description,
302
+ title: fn.agent.title,
303
+ safety: fn.agent.safety,
304
+ tags: fn.agent.tags
305
+ };
306
+ out.push({
307
+ name,
308
+ type,
309
+ jsonSerializable: fn.jsonSerializable === true,
310
+ snapshot: fn.snapshot === true,
311
+ cacheable: fn.cacheable === true,
312
+ hasArgs: !!fn.args,
313
+ hasReturns: !!fn.returns,
314
+ hasDump: !!fn.dump,
315
+ hasSetup: !!fn.setup,
316
+ hasHandler: !!fn.handler,
317
+ invokable: INVOKABLE_TYPES.has(type),
318
+ agent,
319
+ argsSchema: argsSchemaToJson(fn.args),
320
+ returnsSchema: returnSchemaToJson(fn.returns)
321
+ });
322
+ }
323
+ out.sort((a, b) => a.name.localeCompare(b.name));
324
+ return out;
325
+ } })
326
+ });
327
+ //#endregion
328
+ //#region src/rpc/functions/list-instances.ts
329
+ /**
330
+ * Enumerate every devframe dev server currently running on this machine,
331
+ * discovered through the shared instance registry (`~/.devframe/instances/`)
332
+ * with a `__connection.json` liveness probe — the same discovery that backs
333
+ * the `devframe connect` bin. Powers the inspector's read-only Instances tab.
334
+ *
335
+ * Deliberately **not** `snapshot` (the set of live processes is meaningless
336
+ * baked into a static dump — the Instances tab is hidden in `build`/`spa`
337
+ * mode) and **not** agent-exposed (the `devframe connect` bin already offers
338
+ * instance discovery to agents over MCP, so exposing it here would duplicate
339
+ * that surface).
340
+ */
341
+ const listInstances = defineInspectRpc({
342
+ name: "devframes:plugin:inspect:list-instances",
343
+ type: "query",
344
+ jsonSerializable: true,
345
+ setup: () => ({ handler: async () => {
346
+ const { live } = await listLiveDevframeInstances();
347
+ const currentPid = process.pid;
348
+ return live.map((record) => ({
349
+ id: record.id,
350
+ name: record.name,
351
+ port: record.port,
352
+ origin: record.origin,
353
+ basePath: record.basePath,
354
+ url: `${record.origin}${record.basePath}`,
355
+ pid: record.pid,
356
+ rootDir: record.rootDir,
357
+ startedAt: record.startedAt,
358
+ hasMcp: record.mcp != null,
359
+ isCurrent: record.pid === currentPid
360
+ }));
361
+ } })
362
+ });
272
363
  //#endregion
273
364
  //#region src/rpc/index.ts
274
365
  /**
@@ -276,47 +367,7 @@ const INVOKABLE_TYPES = /* @__PURE__ */ new Set(["query", "static"]);
276
367
  * Namespaced `devframes:plugin:inspect:*` per the plugin convention.
277
368
  */
278
369
  const serverFunctions = [
279
- defineInspectRpc({
280
- name: "devframes:plugin:inspect:list-functions",
281
- type: "query",
282
- jsonSerializable: true,
283
- snapshot: true,
284
- agent: {
285
- description: "List every RPC function registered on this devframe connection, with metadata (name, type, JSON-serializable/snapshot flags, args/return schema, agent exposure). Read-only — the canonical way to discover what the running devframe can do.",
286
- title: "List RPC functions"
287
- },
288
- setup: (ctx) => ({ handler: async () => {
289
- const out = [];
290
- for (const [name, fn] of ctx.rpc.definitions) {
291
- const type = fn.type ?? "query";
292
- let agent;
293
- if (fn.agent) agent = {
294
- description: fn.agent.description,
295
- title: fn.agent.title,
296
- safety: fn.agent.safety,
297
- tags: fn.agent.tags
298
- };
299
- out.push({
300
- name,
301
- type,
302
- jsonSerializable: fn.jsonSerializable === true,
303
- snapshot: fn.snapshot === true,
304
- cacheable: fn.cacheable === true,
305
- hasArgs: !!fn.args,
306
- hasReturns: !!fn.returns,
307
- hasDump: !!fn.dump,
308
- hasSetup: !!fn.setup,
309
- hasHandler: !!fn.handler,
310
- invokable: INVOKABLE_TYPES.has(type),
311
- agent,
312
- argsSchema: argsSchemaToJson(fn.args),
313
- returnsSchema: returnSchemaToJson(fn.returns)
314
- });
315
- }
316
- out.sort((a, b) => a.name.localeCompare(b.name));
317
- return out;
318
- } })
319
- }),
370
+ listFunctions,
320
371
  invoke,
321
372
  defineInspectRpc({
322
373
  name: "devframes:plugin:inspect:list-state-keys",
@@ -359,7 +410,8 @@ const serverFunctions = [
359
410
  } })
360
411
  }),
361
412
  listCommands,
362
- executeCommand
413
+ executeCommand,
414
+ listInstances
363
415
  ];
364
416
  //#endregion
365
417
  export { serverFunctions as t };