@devframes/plugin-inspect 0.0.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/LICENSE.md +21 -0
- package/README.md +60 -0
- package/bin.mjs +13 -0
- package/dist/cli.d.mts +12 -0
- package/dist/cli.mjs +14 -0
- package/dist/client/index.d.mts +12 -0
- package/dist/client/index.mjs +12 -0
- package/dist/index-E4zIjo1K.d.mts +37 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +2 -0
- package/dist/node/index.d.mts +12 -0
- package/dist/node/index.mjs +12 -0
- package/dist/rpc/index.d.mts +100 -0
- package/dist/rpc/index.mjs +2 -0
- package/dist/rpc-Cb6r6pvt.mjs +256 -0
- package/dist/spa/assets/index-B6EgVPCn.js +4 -0
- package/dist/spa/assets/index-MP7zS7Ea.css +1 -0
- package/dist/spa/index.html +14 -0
- package/dist/src-9kAqdLdh.mjs +49 -0
- package/dist/types-Cz7H8Eh1.d.mts +72 -0
- package/dist/vite.d.mts +12 -0
- package/dist/vite.mjs +14 -0
- package/package.json +82 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-PRESENT Anthony Fu <https://github.com/antfu>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# @devframes/plugin-inspect
|
|
2
|
+
|
|
3
|
+
> [!WARNING] Experimental
|
|
4
|
+
> This plugin is experimental and may change without a major version bump until
|
|
5
|
+
> it stabilizes.
|
|
6
|
+
|
|
7
|
+
A devframe plugin that inspects *its own* connection (and, when mounted in a
|
|
8
|
+
host, the host's): browse every registered RPC function with its metadata,
|
|
9
|
+
invoke read-only `query`/`static` functions and inspect the results, watch
|
|
10
|
+
shared-state keys update live, and explore the agent-exposed surface.
|
|
11
|
+
|
|
12
|
+
Ported in spirit from the RPC & State panels of
|
|
13
|
+
[`vitejs/devtools`](https://github.com/vitejs/devtools); rebuilt on devframe's
|
|
14
|
+
framework-neutral client (`connectDevframe`, `rpc.sharedState`) with a Vue + Vite SPA.
|
|
15
|
+
|
|
16
|
+
## Use it standalone
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx @devframes/plugin-inspect
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Opens the inspector against a fresh standalone devframe connection — useful as a
|
|
23
|
+
reference and for poking at the introspection RPCs themselves.
|
|
24
|
+
|
|
25
|
+
## Mount into a Vite host
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
// vite.config.ts
|
|
29
|
+
import { inspectVitePlugin } from '@devframes/plugin-inspect/vite'
|
|
30
|
+
import { defineConfig } from 'vite'
|
|
31
|
+
|
|
32
|
+
export default defineConfig({
|
|
33
|
+
plugins: [
|
|
34
|
+
inspectVitePlugin(),
|
|
35
|
+
],
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Programmatic
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { createInspectDevframe } from '@devframes/plugin-inspect'
|
|
43
|
+
|
|
44
|
+
const devframe = createInspectDevframe({ port: 9100 })
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## RPC surface
|
|
48
|
+
|
|
49
|
+
All functions are namespaced `devframes-plugin-inspect:*`:
|
|
50
|
+
|
|
51
|
+
| Function | Type | What it returns |
|
|
52
|
+
|----------|------|-----------------|
|
|
53
|
+
| `list-functions` | `query` (snapshot) | Every registered RPC function with metadata (type, JSON-serializable/snapshot flags, args/return JSON Schema, agent exposure). |
|
|
54
|
+
| `invoke` | `action` | Invokes a read-only `query`/`static` function by name and returns a result envelope. Refuses `action`/`event` functions. |
|
|
55
|
+
| `list-state-keys` | `query` (snapshot) | The keys of every shared-state entry on the connection. |
|
|
56
|
+
| `describe-agent` | `query` (snapshot) | The agent manifest — tools and readable resources. |
|
|
57
|
+
|
|
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.
|
package/bin.mjs
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import process from 'node:process'
|
|
3
|
+
import { createInspectCli } from './dist/cli.mjs'
|
|
4
|
+
|
|
5
|
+
async function main() {
|
|
6
|
+
const cli = createInspectCli()
|
|
7
|
+
await cli.parse()
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
main().catch((error) => {
|
|
11
|
+
console.error(error)
|
|
12
|
+
process.exit(1)
|
|
13
|
+
})
|
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CliHandle } from "devframe/adapters/cli";
|
|
2
|
+
|
|
3
|
+
//#region src/cli.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Build the standalone CLI for the inspector — backs the package `bin`
|
|
6
|
+
* (`devframe-inspect`) and `npx @devframes/plugin-inspect`. Wraps the
|
|
7
|
+
* default {@link createInspectDevframe} definition with devframe's
|
|
8
|
+
* `dev` / `build` / `spa` / `mcp` command shell.
|
|
9
|
+
*/
|
|
10
|
+
declare function createInspectCli(): CliHandle;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { createInspectCli };
|
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { n as inspectDevframe } from "./src-9kAqdLdh.mjs";
|
|
2
|
+
import { createCli } from "devframe/adapters/cli";
|
|
3
|
+
//#region src/cli.ts
|
|
4
|
+
/**
|
|
5
|
+
* Build the standalone CLI for the inspector — backs the package `bin`
|
|
6
|
+
* (`devframe-inspect`) and `npx @devframes/plugin-inspect`. Wraps the
|
|
7
|
+
* default {@link createInspectDevframe} definition with devframe's
|
|
8
|
+
* `dev` / `build` / `spa` / `mcp` command shell.
|
|
9
|
+
*/
|
|
10
|
+
function createInspectCli() {
|
|
11
|
+
return createCli(inspectDevframe);
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { createInspectCli };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { i as RpcFunctionInfo, n as InvokeResult, r as RpcFunctionAgentInfo, t as AgentManifest } from "../types-Cz7H8Eh1.mjs";
|
|
2
|
+
import { DevframeRpcClient, DevframeRpcClientOptions } from "devframe/client";
|
|
3
|
+
|
|
4
|
+
//#region src/client/index.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Connect to the inspector's devframe backend. A thin, typed wrapper
|
|
7
|
+
* around devframe's {@link connectDevframe}; the SPA derives its base
|
|
8
|
+
* from `document.baseURI`, so no options are required in the common case.
|
|
9
|
+
*/
|
|
10
|
+
declare function connectInspect(options?: DevframeRpcClientOptions): Promise<DevframeRpcClient>;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { type AgentManifest, type DevframeRpcClient, type InvokeResult, type RpcFunctionAgentInfo, type RpcFunctionInfo, connectInspect };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { connectDevframe } from "devframe/client";
|
|
2
|
+
//#region src/client/index.ts
|
|
3
|
+
/**
|
|
4
|
+
* Connect to the inspector's devframe backend. A thin, typed wrapper
|
|
5
|
+
* around devframe's {@link connectDevframe}; the SPA derives its base
|
|
6
|
+
* from `document.baseURI`, so no options are required in the common case.
|
|
7
|
+
*/
|
|
8
|
+
function connectInspect(options) {
|
|
9
|
+
return connectDevframe(options);
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { connectInspect };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { DevframeDefinition } from "devframe/types";
|
|
2
|
+
|
|
3
|
+
//#region src/index.d.ts
|
|
4
|
+
interface InspectDevframeOptions {
|
|
5
|
+
/** Override the devframe id (and default CLI command / mount path). */
|
|
6
|
+
id?: string;
|
|
7
|
+
/** Override the display name shown in a host dock. */
|
|
8
|
+
name?: string;
|
|
9
|
+
/** Override the dock icon. */
|
|
10
|
+
icon?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Override the mount path. Left unset, the SPA mounts at `/` standalone
|
|
13
|
+
* and `/__<id>/` when hosted (Vite/embedded).
|
|
14
|
+
*/
|
|
15
|
+
basePath?: string;
|
|
16
|
+
/** Preferred standalone CLI port. */
|
|
17
|
+
port?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Require the trust handshake on the standalone server. Defaults to
|
|
20
|
+
* `false` (auto-trust) since the inspector is a single-user localhost
|
|
21
|
+
* tool. Hosted adapters manage their own auth.
|
|
22
|
+
*/
|
|
23
|
+
auth?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Build a {@link DevframeDefinition} for the Devframe Inspector. The
|
|
27
|
+
* same definition runs standalone (`/cli`, `/spa`, `/build`) and mounts
|
|
28
|
+
* into a host (`/vite`, hub).
|
|
29
|
+
*
|
|
30
|
+
* @experimental This plugin is experimental and may change without a major
|
|
31
|
+
* version bump until it stabilizes.
|
|
32
|
+
*/
|
|
33
|
+
declare function createInspectDevframe(options?: InspectDevframeOptions): DevframeDefinition;
|
|
34
|
+
/** The default inspector devframe definition. */
|
|
35
|
+
declare const inspectDevframe: DevframeDefinition;
|
|
36
|
+
//#endregion
|
|
37
|
+
export { createInspectDevframe as n, inspectDevframe as r, InspectDevframeOptions as t };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { i as RpcFunctionInfo, n as InvokeResult } from "./types-Cz7H8Eh1.mjs";
|
|
2
|
+
import { n as createInspectDevframe, r as inspectDevframe, t as InspectDevframeOptions } from "./index-E4zIjo1K.mjs";
|
|
3
|
+
export { InspectDevframeOptions, InvokeResult, RpcFunctionInfo, createInspectDevframe, inspectDevframe as default };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { serverFunctions } from "../rpc/index.mjs";
|
|
2
|
+
import { DevframeNodeContext } from "devframe/types";
|
|
3
|
+
|
|
4
|
+
//#region src/node/index.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Register the inspector's introspection RPC functions on a devframe
|
|
7
|
+
* node context. Called from the definition's `setup(ctx)` and reusable
|
|
8
|
+
* by host adapters that wire their own context.
|
|
9
|
+
*/
|
|
10
|
+
declare function setupInspect(ctx: DevframeNodeContext): void;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { serverFunctions, setupInspect };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { t as serverFunctions } from "../rpc-Cb6r6pvt.mjs";
|
|
2
|
+
//#region src/node/index.ts
|
|
3
|
+
/**
|
|
4
|
+
* Register the inspector's introspection RPC functions on a devframe
|
|
5
|
+
* node context. Called from the definition's `setup(ctx)` and reusable
|
|
6
|
+
* by host adapters that wire their own context.
|
|
7
|
+
*/
|
|
8
|
+
function setupInspect(ctx) {
|
|
9
|
+
for (const fn of serverFunctions) ctx.rpc.register(fn);
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { serverFunctions, setupInspect };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { i as RpcFunctionInfo, n as InvokeResult } from "../types-Cz7H8Eh1.mjs";
|
|
2
|
+
import * as _$devframe from "devframe";
|
|
3
|
+
import * as _$devframe_rpc0 from "devframe/rpc";
|
|
4
|
+
import { RpcDefinitionsToFunctions } from "devframe/rpc";
|
|
5
|
+
|
|
6
|
+
//#region src/rpc/index.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* The introspection RPC functions registered by the inspector plugin.
|
|
9
|
+
* Namespaced `devframes-plugin-inspect:*` per the plugin convention.
|
|
10
|
+
*/
|
|
11
|
+
declare const serverFunctions: readonly [{
|
|
12
|
+
name: "devframes-plugin-inspect:list-functions";
|
|
13
|
+
type?: "query" | undefined;
|
|
14
|
+
cacheable?: boolean;
|
|
15
|
+
args?: undefined;
|
|
16
|
+
returns?: undefined;
|
|
17
|
+
jsonSerializable?: boolean;
|
|
18
|
+
agent?: _$devframe.RpcFunctionAgentOptions;
|
|
19
|
+
setup?: ((context: _$devframe.DevframeNodeContext) => _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[], Promise<RpcFunctionInfo[]>>>) | undefined;
|
|
20
|
+
handler?: (() => Promise<RpcFunctionInfo[]>) | undefined;
|
|
21
|
+
dump?: _$devframe_rpc0.RpcDump<[], Promise<RpcFunctionInfo[]>, _$devframe.DevframeNodeContext> | undefined;
|
|
22
|
+
snapshot?: boolean;
|
|
23
|
+
__cache?: WeakMap<object, _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[], Promise<RpcFunctionInfo[]>>>> | undefined;
|
|
24
|
+
__promise?: _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[], Promise<RpcFunctionInfo[]>>> | undefined;
|
|
25
|
+
}, {
|
|
26
|
+
name: "devframes-plugin-inspect:invoke";
|
|
27
|
+
type?: "action" | undefined;
|
|
28
|
+
cacheable?: boolean;
|
|
29
|
+
args?: undefined;
|
|
30
|
+
returns?: undefined;
|
|
31
|
+
jsonSerializable?: boolean;
|
|
32
|
+
agent?: _$devframe.RpcFunctionAgentOptions;
|
|
33
|
+
setup?: ((context: _$devframe.DevframeNodeContext) => _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[name: string, args?: unknown[] | undefined], Promise<InvokeResult>>>) | undefined;
|
|
34
|
+
handler?: ((name: string, args?: unknown[] | undefined) => Promise<InvokeResult>) | undefined;
|
|
35
|
+
dump?: _$devframe_rpc0.RpcDump<[name: string, args?: unknown[] | undefined], Promise<InvokeResult>, _$devframe.DevframeNodeContext> | undefined;
|
|
36
|
+
snapshot?: boolean;
|
|
37
|
+
__cache?: WeakMap<object, _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[name: string, args?: unknown[] | undefined], Promise<InvokeResult>>>> | undefined;
|
|
38
|
+
__promise?: _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[name: string, args?: unknown[] | undefined], Promise<InvokeResult>>> | undefined;
|
|
39
|
+
}, {
|
|
40
|
+
name: "devframes-plugin-inspect:list-state-keys";
|
|
41
|
+
type?: "query" | undefined;
|
|
42
|
+
cacheable?: boolean;
|
|
43
|
+
args?: undefined;
|
|
44
|
+
returns?: undefined;
|
|
45
|
+
jsonSerializable?: boolean;
|
|
46
|
+
agent?: _$devframe.RpcFunctionAgentOptions;
|
|
47
|
+
setup?: ((context: _$devframe.DevframeNodeContext) => _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[], Promise<string[]>>>) | undefined;
|
|
48
|
+
handler?: (() => Promise<string[]>) | undefined;
|
|
49
|
+
dump?: _$devframe_rpc0.RpcDump<[], Promise<string[]>, _$devframe.DevframeNodeContext> | undefined;
|
|
50
|
+
snapshot?: boolean;
|
|
51
|
+
__cache?: WeakMap<object, _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[], Promise<string[]>>>> | undefined;
|
|
52
|
+
__promise?: _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[], Promise<string[]>>> | undefined;
|
|
53
|
+
}, {
|
|
54
|
+
name: "devframes-plugin-inspect:describe-agent";
|
|
55
|
+
type?: "query" | undefined;
|
|
56
|
+
cacheable?: boolean;
|
|
57
|
+
args?: undefined;
|
|
58
|
+
returns?: undefined;
|
|
59
|
+
jsonSerializable?: boolean;
|
|
60
|
+
agent?: _$devframe.RpcFunctionAgentOptions;
|
|
61
|
+
setup?: ((context: _$devframe.DevframeNodeContext) => _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[], Promise<_$devframe.AgentManifest>>>) | undefined;
|
|
62
|
+
handler?: (() => Promise<_$devframe.AgentManifest>) | undefined;
|
|
63
|
+
dump?: _$devframe_rpc0.RpcDump<[], Promise<_$devframe.AgentManifest>, _$devframe.DevframeNodeContext> | undefined;
|
|
64
|
+
snapshot?: boolean;
|
|
65
|
+
__cache?: WeakMap<object, _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[], Promise<_$devframe.AgentManifest>>>> | undefined;
|
|
66
|
+
__promise?: _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[], Promise<_$devframe.AgentManifest>>> | undefined;
|
|
67
|
+
}, {
|
|
68
|
+
name: "devframes-plugin-inspect:invoke-agent-tool";
|
|
69
|
+
type?: "action" | undefined;
|
|
70
|
+
cacheable?: boolean;
|
|
71
|
+
args?: undefined;
|
|
72
|
+
returns?: undefined;
|
|
73
|
+
jsonSerializable?: boolean;
|
|
74
|
+
agent?: _$devframe.RpcFunctionAgentOptions;
|
|
75
|
+
setup?: ((context: _$devframe.DevframeNodeContext) => _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[id: string, args: unknown], Promise<InvokeResult>>>) | undefined;
|
|
76
|
+
handler?: ((id: string, args: unknown) => Promise<InvokeResult>) | undefined;
|
|
77
|
+
dump?: _$devframe_rpc0.RpcDump<[id: string, args: unknown], Promise<InvokeResult>, _$devframe.DevframeNodeContext> | undefined;
|
|
78
|
+
snapshot?: boolean;
|
|
79
|
+
__cache?: WeakMap<object, _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[id: string, args: unknown], Promise<InvokeResult>>>> | undefined;
|
|
80
|
+
__promise?: _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[id: string, args: unknown], Promise<InvokeResult>>> | undefined;
|
|
81
|
+
}, {
|
|
82
|
+
name: "devframes-plugin-inspect:read-agent-resource";
|
|
83
|
+
type?: "action" | undefined;
|
|
84
|
+
cacheable?: boolean;
|
|
85
|
+
args?: undefined;
|
|
86
|
+
returns?: undefined;
|
|
87
|
+
jsonSerializable?: boolean;
|
|
88
|
+
agent?: _$devframe.RpcFunctionAgentOptions;
|
|
89
|
+
setup?: ((context: _$devframe.DevframeNodeContext) => _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[id: string], Promise<InvokeResult>>>) | undefined;
|
|
90
|
+
handler?: ((id: string) => Promise<InvokeResult>) | undefined;
|
|
91
|
+
dump?: _$devframe_rpc0.RpcDump<[id: string], Promise<InvokeResult>, _$devframe.DevframeNodeContext> | undefined;
|
|
92
|
+
snapshot?: boolean;
|
|
93
|
+
__cache?: WeakMap<object, _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[id: string], Promise<InvokeResult>>>> | undefined;
|
|
94
|
+
__promise?: _$devframe_rpc0.Thenable<_$devframe_rpc0.RpcFunctionSetupResult<[id: string], Promise<InvokeResult>>> | undefined;
|
|
95
|
+
}];
|
|
96
|
+
declare module 'devframe' {
|
|
97
|
+
interface DevframeRpcServerFunctions extends RpcDefinitionsToFunctions<typeof serverFunctions> {}
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
export { serverFunctions };
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { createDefineWrapperWithContext } from "devframe/rpc";
|
|
2
|
+
import { defineDiagnostics } from "nostics";
|
|
3
|
+
import { toJsonSchema } from "@valibot/to-json-schema";
|
|
4
|
+
//#region src/rpc/functions/_define.ts
|
|
5
|
+
/**
|
|
6
|
+
* `defineRpcFunction` pre-bound to the framework-neutral
|
|
7
|
+
* {@link DevframeNodeContext}, so each inspector function's `setup(ctx)`
|
|
8
|
+
* receives the typed node context (`ctx.rpc`, `ctx.agent`, …) instead of
|
|
9
|
+
* the default `undefined` context.
|
|
10
|
+
*/
|
|
11
|
+
const defineInspectRpc = createDefineWrapperWithContext();
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/rpc/functions/describe-agent.ts
|
|
14
|
+
/**
|
|
15
|
+
* Surface the agent-exposed surface of the connection: the unified
|
|
16
|
+
* manifest of tools (RPC functions flagged with `agent`, plus
|
|
17
|
+
* host-registered tools) and readable resources. `snapshot: true` bakes
|
|
18
|
+
* the manifest into the static dump for `build`/`spa` mode.
|
|
19
|
+
*/
|
|
20
|
+
const describeAgent = defineInspectRpc({
|
|
21
|
+
name: "devframes-plugin-inspect:describe-agent",
|
|
22
|
+
type: "query",
|
|
23
|
+
jsonSerializable: true,
|
|
24
|
+
snapshot: true,
|
|
25
|
+
agent: {
|
|
26
|
+
description: "Describe the agent-exposed surface of this devframe: the list of tools (agent-flagged RPC functions and host-registered tools) and readable resources, with their titles, descriptions, safety hints, and schemas. Read-only.",
|
|
27
|
+
title: "Describe agent surface"
|
|
28
|
+
},
|
|
29
|
+
setup: (ctx) => ({ handler: async () => {
|
|
30
|
+
return ctx.agent.list();
|
|
31
|
+
} })
|
|
32
|
+
});
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/diagnostics.ts
|
|
35
|
+
/**
|
|
36
|
+
* Structured diagnostics for `@devframes/plugin-inspect`. Node-side only.
|
|
37
|
+
* Codes use the plugin-private `DP_INSPECT_` band (see the built-in
|
|
38
|
+
* plugins planning index) so they never collide with devframe core
|
|
39
|
+
* (`DF00xx`) or `@devframes/hub` (`DF80xx`).
|
|
40
|
+
*/
|
|
41
|
+
const diagnostics = defineDiagnostics({
|
|
42
|
+
docsBase: "https://devfra.me/errors",
|
|
43
|
+
codes: {
|
|
44
|
+
DP_INSPECT_0001: {
|
|
45
|
+
why: (p) => `Cannot invoke "${p.name}" — no RPC function with that name is registered on this connection.`,
|
|
46
|
+
fix: "Call `devframes-plugin-inspect:list-functions` to see the registered names, or check for a typo."
|
|
47
|
+
},
|
|
48
|
+
DP_INSPECT_0002: {
|
|
49
|
+
why: (p) => `Refusing to invoke "${p.name}" — only read-only "query" and "static" functions are invokable from the inspector, but this one is "${p.type}".`,
|
|
50
|
+
fix: "The inspector deliberately blocks `action`/`event` functions to avoid triggering side effects. Invoke those through their own UI instead."
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/rpc/functions/invoke.ts
|
|
56
|
+
const INVOKABLE_TYPES$1 = new Set(["query", "static"]);
|
|
57
|
+
/**
|
|
58
|
+
* Invoke a read-only RPC function by name and return a result envelope.
|
|
59
|
+
*
|
|
60
|
+
* Deliberately gated to `query` / `static` functions — `action` and
|
|
61
|
+
* `event` functions may carry side effects, so the inspector refuses to
|
|
62
|
+
* fire them (`DP_INSPECT_0002`). Uses structured-clone serialization
|
|
63
|
+
* (default) so arbitrary return values round-trip without the strict-JSON
|
|
64
|
+
* constraints that `jsonSerializable: true` would impose.
|
|
65
|
+
*/
|
|
66
|
+
const invoke = defineInspectRpc({
|
|
67
|
+
name: "devframes-plugin-inspect:invoke",
|
|
68
|
+
type: "action",
|
|
69
|
+
setup: (ctx) => ({ handler: async (name, args = []) => {
|
|
70
|
+
const def = ctx.rpc.definitions.get(name);
|
|
71
|
+
if (!def) throw diagnostics.DP_INSPECT_0001({ name });
|
|
72
|
+
const type = def.type ?? "query";
|
|
73
|
+
if (!INVOKABLE_TYPES$1.has(type)) throw diagnostics.DP_INSPECT_0002({
|
|
74
|
+
name,
|
|
75
|
+
type
|
|
76
|
+
});
|
|
77
|
+
const start = Date.now();
|
|
78
|
+
try {
|
|
79
|
+
return {
|
|
80
|
+
ok: true,
|
|
81
|
+
result: await ctx.rpc.invokeLocal(name, ...args),
|
|
82
|
+
durationMs: Date.now() - start
|
|
83
|
+
};
|
|
84
|
+
} catch (error) {
|
|
85
|
+
const e = error;
|
|
86
|
+
return {
|
|
87
|
+
ok: false,
|
|
88
|
+
error: {
|
|
89
|
+
name: e?.name ?? "Error",
|
|
90
|
+
message: e?.message ?? String(error),
|
|
91
|
+
stack: e?.stack
|
|
92
|
+
},
|
|
93
|
+
durationMs: Date.now() - start
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
} })
|
|
97
|
+
});
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region src/rpc/functions/invoke-agent-tool.ts
|
|
100
|
+
const invokeAgentTool = defineInspectRpc({
|
|
101
|
+
name: "devframes-plugin-inspect:invoke-agent-tool",
|
|
102
|
+
type: "action",
|
|
103
|
+
setup: (ctx) => ({ handler: async (id, args) => {
|
|
104
|
+
const start = Date.now();
|
|
105
|
+
try {
|
|
106
|
+
return {
|
|
107
|
+
ok: true,
|
|
108
|
+
result: await ctx.agent.invoke(id, args),
|
|
109
|
+
durationMs: Date.now() - start
|
|
110
|
+
};
|
|
111
|
+
} catch (error) {
|
|
112
|
+
const e = error;
|
|
113
|
+
return {
|
|
114
|
+
ok: false,
|
|
115
|
+
error: {
|
|
116
|
+
name: e?.name ?? "Error",
|
|
117
|
+
message: e?.message ?? String(error),
|
|
118
|
+
stack: e?.stack
|
|
119
|
+
},
|
|
120
|
+
durationMs: Date.now() - start
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
} })
|
|
124
|
+
});
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region src/rpc/functions/_schema.ts
|
|
127
|
+
const FALLBACK_SCHEMA = Object.freeze({
|
|
128
|
+
type: "object",
|
|
129
|
+
additionalProperties: true
|
|
130
|
+
});
|
|
131
|
+
/**
|
|
132
|
+
* Convert a valibot return schema to JSON Schema, swallowing
|
|
133
|
+
* conversion failures (unsupported valibot actions) into a permissive
|
|
134
|
+
* fallback so introspection never throws.
|
|
135
|
+
*/
|
|
136
|
+
function returnSchemaToJson(schema) {
|
|
137
|
+
if (!schema) return void 0;
|
|
138
|
+
try {
|
|
139
|
+
return toJsonSchema(schema);
|
|
140
|
+
} catch {
|
|
141
|
+
return FALLBACK_SCHEMA;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Convert the positional args valibot schemas to a single JSON Schema
|
|
146
|
+
* tuple (`type: 'array'` + `prefixItems`). Returns `undefined` when the
|
|
147
|
+
* function declares no args.
|
|
148
|
+
*/
|
|
149
|
+
function argsSchemaToJson(args) {
|
|
150
|
+
if (!args || args.length === 0) return void 0;
|
|
151
|
+
return {
|
|
152
|
+
type: "array",
|
|
153
|
+
prefixItems: args.map((arg) => {
|
|
154
|
+
try {
|
|
155
|
+
return toJsonSchema(arg);
|
|
156
|
+
} catch {
|
|
157
|
+
return FALLBACK_SCHEMA;
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
//#endregion
|
|
163
|
+
//#region src/rpc/functions/list-functions.ts
|
|
164
|
+
const INVOKABLE_TYPES = new Set(["query", "static"]);
|
|
165
|
+
//#endregion
|
|
166
|
+
//#region src/rpc/index.ts
|
|
167
|
+
/**
|
|
168
|
+
* The introspection RPC functions registered by the inspector plugin.
|
|
169
|
+
* Namespaced `devframes-plugin-inspect:*` per the plugin convention.
|
|
170
|
+
*/
|
|
171
|
+
const serverFunctions = [
|
|
172
|
+
defineInspectRpc({
|
|
173
|
+
name: "devframes-plugin-inspect:list-functions",
|
|
174
|
+
type: "query",
|
|
175
|
+
jsonSerializable: true,
|
|
176
|
+
snapshot: true,
|
|
177
|
+
agent: {
|
|
178
|
+
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.",
|
|
179
|
+
title: "List RPC functions"
|
|
180
|
+
},
|
|
181
|
+
setup: (ctx) => ({ handler: async () => {
|
|
182
|
+
const out = [];
|
|
183
|
+
for (const [name, fn] of ctx.rpc.definitions) {
|
|
184
|
+
const type = fn.type ?? "query";
|
|
185
|
+
let agent;
|
|
186
|
+
if (fn.agent) agent = {
|
|
187
|
+
description: fn.agent.description,
|
|
188
|
+
title: fn.agent.title,
|
|
189
|
+
safety: fn.agent.safety,
|
|
190
|
+
tags: fn.agent.tags
|
|
191
|
+
};
|
|
192
|
+
out.push({
|
|
193
|
+
name,
|
|
194
|
+
type,
|
|
195
|
+
jsonSerializable: fn.jsonSerializable === true,
|
|
196
|
+
snapshot: fn.snapshot === true,
|
|
197
|
+
cacheable: fn.cacheable === true,
|
|
198
|
+
hasArgs: !!fn.args,
|
|
199
|
+
hasReturns: !!fn.returns,
|
|
200
|
+
hasDump: !!fn.dump,
|
|
201
|
+
hasSetup: !!fn.setup,
|
|
202
|
+
hasHandler: !!fn.handler,
|
|
203
|
+
invokable: INVOKABLE_TYPES.has(type),
|
|
204
|
+
agent,
|
|
205
|
+
argsSchema: argsSchemaToJson(fn.args),
|
|
206
|
+
returnsSchema: returnSchemaToJson(fn.returns)
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
out.sort((a, b) => a.name.localeCompare(b.name));
|
|
210
|
+
return out;
|
|
211
|
+
} })
|
|
212
|
+
}),
|
|
213
|
+
invoke,
|
|
214
|
+
defineInspectRpc({
|
|
215
|
+
name: "devframes-plugin-inspect:list-state-keys",
|
|
216
|
+
type: "query",
|
|
217
|
+
jsonSerializable: true,
|
|
218
|
+
snapshot: true,
|
|
219
|
+
agent: {
|
|
220
|
+
description: "List the keys of all shared-state entries published by this devframe connection. Read-only. Pair with the built-in shared-state reads to inspect individual values.",
|
|
221
|
+
title: "List shared-state keys"
|
|
222
|
+
},
|
|
223
|
+
setup: (ctx) => ({ handler: async () => {
|
|
224
|
+
return [...ctx.rpc.sharedState.keys()].sort();
|
|
225
|
+
} })
|
|
226
|
+
}),
|
|
227
|
+
describeAgent,
|
|
228
|
+
invokeAgentTool,
|
|
229
|
+
defineInspectRpc({
|
|
230
|
+
name: "devframes-plugin-inspect:read-agent-resource",
|
|
231
|
+
type: "action",
|
|
232
|
+
setup: (ctx) => ({ handler: async (id) => {
|
|
233
|
+
const start = Date.now();
|
|
234
|
+
try {
|
|
235
|
+
return {
|
|
236
|
+
ok: true,
|
|
237
|
+
result: await ctx.agent.read(id),
|
|
238
|
+
durationMs: Date.now() - start
|
|
239
|
+
};
|
|
240
|
+
} catch (error) {
|
|
241
|
+
const e = error;
|
|
242
|
+
return {
|
|
243
|
+
ok: false,
|
|
244
|
+
error: {
|
|
245
|
+
name: e?.name ?? "Error",
|
|
246
|
+
message: e?.message ?? String(error),
|
|
247
|
+
stack: e?.stack
|
|
248
|
+
},
|
|
249
|
+
durationMs: Date.now() - start
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
} })
|
|
253
|
+
})
|
|
254
|
+
];
|
|
255
|
+
//#endregion
|
|
256
|
+
export { serverFunctions as t };
|