@mindmakr/reins 0.0.0-stage → 0.1.0
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 +21 -0
- package/README.md +6 -2
- package/dist/adapters.d.ts +25 -0
- package/dist/adapters.js +24 -0
- package/dist/bridge/args.d.ts +15 -0
- package/dist/bridge/args.js +59 -0
- package/dist/bridge/audit.d.ts +13 -0
- package/dist/bridge/audit.js +13 -0
- package/dist/bridge/clipboard.d.ts +2 -0
- package/dist/bridge/clipboard.js +31 -0
- package/dist/bridge/hub.d.ts +56 -0
- package/dist/bridge/hub.js +162 -0
- package/dist/bridge/index.d.ts +11 -0
- package/dist/bridge/index.js +11 -0
- package/dist/bridge/mcp.d.ts +5 -0
- package/dist/bridge/mcp.js +22 -0
- package/dist/bridge/origin.d.ts +7 -0
- package/dist/bridge/origin.js +23 -0
- package/dist/bridge/report-cli.d.ts +13 -0
- package/dist/bridge/report-cli.js +82 -0
- package/dist/bridge/session.d.ts +24 -0
- package/dist/bridge/session.js +116 -0
- package/dist/bridge/snap.d.ts +28 -0
- package/dist/bridge/snap.js +65 -0
- package/dist/bridge/token.d.ts +10 -0
- package/dist/bridge/token.js +35 -0
- package/dist/bridge/tools.d.ts +18 -0
- package/dist/bridge/tools.js +174 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +67 -0
- package/dist/dom.d.ts +2 -0
- package/dist/dom.js +48 -0
- package/dist/env.d.ts +1 -0
- package/dist/env.js +6 -0
- package/dist/expo.d.ts +27 -0
- package/dist/expo.js +48 -0
- package/dist/index.d.ts +70 -0
- package/dist/index.js +267 -0
- package/dist/metro.d.ts +16 -0
- package/dist/metro.js +45 -0
- package/dist/network.d.ts +14 -0
- package/dist/network.js +50 -0
- package/dist/next-token-route.d.ts +9 -0
- package/dist/next-token-route.js +17 -0
- package/dist/next.d.ts +13 -0
- package/dist/next.js +27 -0
- package/dist/node.d.ts +80 -0
- package/dist/node.js +414 -0
- package/dist/react.d.ts +281 -0
- package/dist/react.js +33 -0
- package/dist/record-stub.d.ts +18 -0
- package/dist/record-stub.js +6 -0
- package/dist/record.d.ts +28 -0
- package/dist/record.js +104 -0
- package/dist/redact.d.ts +7 -0
- package/dist/redact.js +30 -0
- package/dist/report.d.ts +121 -0
- package/dist/report.js +353 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.js +27 -0
- package/dist/stub.d.ts +88 -0
- package/dist/stub.js +38 -0
- package/dist/types.d.ts +248 -0
- package/dist/types.js +1 -0
- package/dist/verify-cli.d.ts +2 -0
- package/dist/verify-cli.js +3 -0
- package/dist/verify.d.ts +17 -0
- package/dist/verify.js +60 -0
- package/dist/vite.d.ts +32 -0
- package/dist/vite.js +33 -0
- package/dist/webmcp.d.ts +3 -0
- package/dist/webmcp.js +20 -0
- package/package.json +59 -4
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/** A JSON Schema object. reins passes it through untouched. */
|
|
2
|
+
export type JSONSchema = Record<string, unknown>;
|
|
3
|
+
export interface Action<I = any, O = any> {
|
|
4
|
+
/** Letters, digits, `.`, `_` and `-`, up to 64 characters. */
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
/** JSON Schema for the input. Use an object schema. */
|
|
8
|
+
input?: JSONSchema;
|
|
9
|
+
/** Changes real data or sends something. Callers must pass `confirm: true`. */
|
|
10
|
+
consequential?: boolean;
|
|
11
|
+
/** Reads only. Passed to WebMCP as `readOnlyHint`. */
|
|
12
|
+
readOnly?: boolean;
|
|
13
|
+
run: (input: I) => O | Promise<O>;
|
|
14
|
+
}
|
|
15
|
+
export interface ActionInfo {
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
input: JSONSchema;
|
|
19
|
+
consequential: boolean;
|
|
20
|
+
readOnly: boolean;
|
|
21
|
+
}
|
|
22
|
+
/** Keys that are shown as they are. Everything else sensitive is redacted. */
|
|
23
|
+
export interface Allow {
|
|
24
|
+
headers?: string[];
|
|
25
|
+
bodyKeys?: string[];
|
|
26
|
+
storageKeys?: string[];
|
|
27
|
+
cookies?: string[];
|
|
28
|
+
queryKeys?: string[];
|
|
29
|
+
stateKeys?: string[];
|
|
30
|
+
}
|
|
31
|
+
export interface Box {
|
|
32
|
+
id: string;
|
|
33
|
+
/** CSS pixels, relative to the viewport. */
|
|
34
|
+
x: number;
|
|
35
|
+
y: number;
|
|
36
|
+
width: number;
|
|
37
|
+
height: number;
|
|
38
|
+
scrollX: number;
|
|
39
|
+
scrollY: number;
|
|
40
|
+
devicePixelRatio: number;
|
|
41
|
+
viewportWidth?: number;
|
|
42
|
+
viewportHeight?: number;
|
|
43
|
+
}
|
|
44
|
+
export type Measure = () => Box | null | Promise<Box | null>;
|
|
45
|
+
export interface NetEntry {
|
|
46
|
+
method: string;
|
|
47
|
+
url: string;
|
|
48
|
+
status: number;
|
|
49
|
+
ms: number;
|
|
50
|
+
startMs?: number;
|
|
51
|
+
at: number;
|
|
52
|
+
requestHeaders?: Record<string, string>;
|
|
53
|
+
responseHeaders?: Record<string, string>;
|
|
54
|
+
requestBody?: unknown;
|
|
55
|
+
responseBody?: unknown;
|
|
56
|
+
error?: string;
|
|
57
|
+
/** Sent as `x-reins-trace` on same-origin calls while paired, so `@mindmakr/reins/node` can join the server half. */
|
|
58
|
+
traceId?: string;
|
|
59
|
+
}
|
|
60
|
+
export interface ErrEntry {
|
|
61
|
+
kind: 'console' | 'error' | 'rejection';
|
|
62
|
+
message: string;
|
|
63
|
+
at: number;
|
|
64
|
+
stack?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface ComponentPerf {
|
|
67
|
+
id: string;
|
|
68
|
+
mountedAtMs: number;
|
|
69
|
+
lastRenderMs: number;
|
|
70
|
+
renders: number;
|
|
71
|
+
}
|
|
72
|
+
export interface PerfTimelineEntry {
|
|
73
|
+
kind: 'lifecycle' | 'component-mount' | 'api' | 'action' | 'server';
|
|
74
|
+
name: string;
|
|
75
|
+
atMs: number;
|
|
76
|
+
durationMs?: number;
|
|
77
|
+
status?: number;
|
|
78
|
+
/** Server entries (joined by the bridge from `@mindmakr/reins/node`): the trace id, time in `db.*` spans, and the spans. */
|
|
79
|
+
traceId?: string;
|
|
80
|
+
dbMs?: number;
|
|
81
|
+
spans?: Array<{
|
|
82
|
+
name: string;
|
|
83
|
+
atMs: number;
|
|
84
|
+
durationMs: number;
|
|
85
|
+
error?: string;
|
|
86
|
+
}>;
|
|
87
|
+
}
|
|
88
|
+
export interface ApiCall {
|
|
89
|
+
method: string;
|
|
90
|
+
url: string;
|
|
91
|
+
status: number;
|
|
92
|
+
startMs?: number;
|
|
93
|
+
ms: number;
|
|
94
|
+
traceId?: string;
|
|
95
|
+
}
|
|
96
|
+
export interface PerfReport {
|
|
97
|
+
lifecycle: {
|
|
98
|
+
ttfbMs: number | null;
|
|
99
|
+
domInteractiveMs: number | null;
|
|
100
|
+
domContentLoadedMs: number | null;
|
|
101
|
+
loadMs: number | null;
|
|
102
|
+
firstPaintMs: number | null;
|
|
103
|
+
firstContentfulPaintMs: number | null;
|
|
104
|
+
domNodes: number;
|
|
105
|
+
nowMs: number;
|
|
106
|
+
};
|
|
107
|
+
components: ComponentPerf[];
|
|
108
|
+
api: {
|
|
109
|
+
totalCalls: number;
|
|
110
|
+
failedCalls: number;
|
|
111
|
+
avgMs: number;
|
|
112
|
+
maxMs: number;
|
|
113
|
+
slowest: ApiCall | null;
|
|
114
|
+
/** In the page these are the full (redacted) network entries; the bridge trims them to these fields. */
|
|
115
|
+
calls: ApiCall[];
|
|
116
|
+
};
|
|
117
|
+
actions: Array<{
|
|
118
|
+
name: string;
|
|
119
|
+
startMs: number;
|
|
120
|
+
durationMs: number;
|
|
121
|
+
}>;
|
|
122
|
+
/** Built from the parts above by `withTimeline` in `@mindmakr/reins/report`. The bridge's `reins_perf` and record mode always include it. */
|
|
123
|
+
timeline?: PerfTimelineEntry[];
|
|
124
|
+
/** Added by the bridge when a `@mindmakr/reins/node` server is paired. */
|
|
125
|
+
server?: {
|
|
126
|
+
requests: number;
|
|
127
|
+
slowest: RouteStat[];
|
|
128
|
+
runtime: ServerRuntime | null;
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/** One timed piece of server work: a `reinsNode.span()` call. */
|
|
132
|
+
export interface ServerSpan {
|
|
133
|
+
name: string;
|
|
134
|
+
/** Milliseconds from the start of the request (or of the process, for top-level spans). */
|
|
135
|
+
startMs: number;
|
|
136
|
+
ms: number;
|
|
137
|
+
error?: string;
|
|
138
|
+
}
|
|
139
|
+
/** One outbound `fetch` the server made (seen through `node:diagnostics_channel`). */
|
|
140
|
+
export interface ServerOutbound {
|
|
141
|
+
method: string;
|
|
142
|
+
url: string;
|
|
143
|
+
status: number;
|
|
144
|
+
startMs: number;
|
|
145
|
+
ms: number;
|
|
146
|
+
error?: string;
|
|
147
|
+
}
|
|
148
|
+
/** One inbound HTTP request handled by a server that uses `@mindmakr/reins/node`. */
|
|
149
|
+
export interface ServerRequest {
|
|
150
|
+
method: string;
|
|
151
|
+
route: string;
|
|
152
|
+
url: string;
|
|
153
|
+
status: number;
|
|
154
|
+
ms: number;
|
|
155
|
+
/** `performance.now()` of the server process when the request started. */
|
|
156
|
+
startMs: number;
|
|
157
|
+
at: number;
|
|
158
|
+
traceId?: string;
|
|
159
|
+
/** Total time in spans whose name starts with `db.`. */
|
|
160
|
+
dbMs: number;
|
|
161
|
+
spans: ServerSpan[];
|
|
162
|
+
outbound: ServerOutbound[];
|
|
163
|
+
requestHeaders?: Record<string, string>;
|
|
164
|
+
}
|
|
165
|
+
export interface ServerRuntime {
|
|
166
|
+
node: string;
|
|
167
|
+
pid: number;
|
|
168
|
+
uptimeS: number;
|
|
169
|
+
rssMb: number;
|
|
170
|
+
heapUsedMb: number;
|
|
171
|
+
eventLoop: {
|
|
172
|
+
p50Ms: number;
|
|
173
|
+
p99Ms: number;
|
|
174
|
+
maxMs: number;
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
export interface RouteStat {
|
|
178
|
+
method: string;
|
|
179
|
+
route: string;
|
|
180
|
+
count: number;
|
|
181
|
+
avgMs: number;
|
|
182
|
+
maxMs: number;
|
|
183
|
+
avgDbMs: number;
|
|
184
|
+
}
|
|
185
|
+
/** What `reins_server` returns for one server. */
|
|
186
|
+
export interface ServerReport {
|
|
187
|
+
runtime: ServerRuntime | null;
|
|
188
|
+
requests: ServerRequest[];
|
|
189
|
+
slowest: RouteStat[];
|
|
190
|
+
spans: ServerSpan[];
|
|
191
|
+
outbound: ServerOutbound[];
|
|
192
|
+
actions?: ActionInfo[];
|
|
193
|
+
}
|
|
194
|
+
export interface DomOptions {
|
|
195
|
+
panel?: string;
|
|
196
|
+
selector?: string;
|
|
197
|
+
depth?: number;
|
|
198
|
+
maxNodes?: number;
|
|
199
|
+
}
|
|
200
|
+
export type DomIssue = 'horizontal-clip' | 'vertical-clip' | 'zero-size';
|
|
201
|
+
export interface DomNode {
|
|
202
|
+
tag: string;
|
|
203
|
+
id?: string;
|
|
204
|
+
classes?: string[];
|
|
205
|
+
panel?: string;
|
|
206
|
+
role?: string;
|
|
207
|
+
text?: string;
|
|
208
|
+
box: {
|
|
209
|
+
x: number;
|
|
210
|
+
y: number;
|
|
211
|
+
width: number;
|
|
212
|
+
height: number;
|
|
213
|
+
};
|
|
214
|
+
styles: Record<string, string>;
|
|
215
|
+
issues: DomIssue[];
|
|
216
|
+
children: DomNode[];
|
|
217
|
+
}
|
|
218
|
+
export interface SocketLike {
|
|
219
|
+
send(data: string): void;
|
|
220
|
+
close(): void;
|
|
221
|
+
onopen: ((ev?: unknown) => void) | null;
|
|
222
|
+
onmessage: ((ev: {
|
|
223
|
+
data: unknown;
|
|
224
|
+
}) => void) | null;
|
|
225
|
+
onclose: ((ev?: unknown) => void) | null;
|
|
226
|
+
onerror: ((ev?: unknown) => void) | null;
|
|
227
|
+
}
|
|
228
|
+
export interface ConnectOptions {
|
|
229
|
+
/** Bridge WebSocket URL. Default `ws://127.0.0.1:7357`. */
|
|
230
|
+
url?: string;
|
|
231
|
+
/** Pairing token. If missing, reins fetches it from `tokenUrl`. */
|
|
232
|
+
token?: string;
|
|
233
|
+
/** Where to fetch the token. Default `/__reins/token` (served by the Vite plugin). */
|
|
234
|
+
tokenUrl?: string;
|
|
235
|
+
allow?: Allow;
|
|
236
|
+
/** Size of the network and error buffers. Default 100. */
|
|
237
|
+
bufferSize?: number;
|
|
238
|
+
/** Register actions as WebMCP tools when the browser supports it. Default true. */
|
|
239
|
+
webmcp?: boolean;
|
|
240
|
+
/** Wait for `load` and an idle moment before connecting. Default true. */
|
|
241
|
+
lazy?: boolean;
|
|
242
|
+
/** Retry when the bridge is not there or goes away. Default true. */
|
|
243
|
+
reconnect?: boolean;
|
|
244
|
+
/** Extra facts sent with the handshake, such as `{ platform: 'android' }`. */
|
|
245
|
+
meta?: Record<string, string>;
|
|
246
|
+
/** For tests and React Native. Default `globalThis.WebSocket`. */
|
|
247
|
+
WebSocket?: new (url: string) => SocketLike;
|
|
248
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/verify.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** The string the reins core carries. It must never reach a production bundle. */
|
|
2
|
+
export declare const MARKER = "__REINS_DEV_ONLY__";
|
|
3
|
+
/** Every file under `dir`, skipping node_modules and .git. */
|
|
4
|
+
export declare function listFiles(dir: string): string[];
|
|
5
|
+
/**
|
|
6
|
+
* Files under `dir` (relative paths, forward slashes) that contain the marker.
|
|
7
|
+
* Reads bytes, so it also finds the marker in Hermes bytecode and source maps.
|
|
8
|
+
*/
|
|
9
|
+
export declare function findMarker(dir: string, marker?: string): string[];
|
|
10
|
+
/** Runs the check and returns the exit code: 0 clean, 1 marker found, 2 bad usage. */
|
|
11
|
+
export declare function main(args: string[], out?: {
|
|
12
|
+
(...data: any[]): void;
|
|
13
|
+
(message?: any, ...optionalParams: any[]): void;
|
|
14
|
+
}, err?: {
|
|
15
|
+
(...data: any[]): void;
|
|
16
|
+
(message?: any, ...optionalParams: any[]): void;
|
|
17
|
+
}): number;
|
package/dist/verify.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { join, relative } from 'node:path';
|
|
3
|
+
/** The string the reins core carries. It must never reach a production bundle. */
|
|
4
|
+
export const MARKER = '__REINS_DEV_ONLY__';
|
|
5
|
+
const SKIP = new Set(['node_modules', '.git']);
|
|
6
|
+
/** Every file under `dir`, skipping node_modules and .git. */
|
|
7
|
+
export function listFiles(dir) {
|
|
8
|
+
const out = [];
|
|
9
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
10
|
+
if (SKIP.has(entry.name))
|
|
11
|
+
continue;
|
|
12
|
+
const full = join(dir, entry.name);
|
|
13
|
+
if (entry.isDirectory())
|
|
14
|
+
out.push(...listFiles(full));
|
|
15
|
+
else if (entry.isFile())
|
|
16
|
+
out.push(full);
|
|
17
|
+
}
|
|
18
|
+
return out;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Files under `dir` (relative paths, forward slashes) that contain the marker.
|
|
22
|
+
* Reads bytes, so it also finds the marker in Hermes bytecode and source maps.
|
|
23
|
+
*/
|
|
24
|
+
export function findMarker(dir, marker = MARKER) {
|
|
25
|
+
if (!statSync(dir).isDirectory())
|
|
26
|
+
throw new Error(`${dir} is not a directory`);
|
|
27
|
+
const needle = Buffer.from(marker);
|
|
28
|
+
return listFiles(dir)
|
|
29
|
+
.filter((file) => readFileSync(file).includes(needle))
|
|
30
|
+
.map((file) => relative(dir, file).split('\\').join('/'));
|
|
31
|
+
}
|
|
32
|
+
/** Runs the check and returns the exit code: 0 clean, 1 marker found, 2 bad usage. */
|
|
33
|
+
export function main(args, out = console.log, err = console.error) {
|
|
34
|
+
const dirs = args.filter((a) => !a.startsWith('-'));
|
|
35
|
+
if (dirs.length === 0 || args.includes('--help') || args.includes('-h')) {
|
|
36
|
+
err('usage: reins-verify-bundle <dir> [<dir>...]');
|
|
37
|
+
err(`Exits 1 if any file contains ${MARKER}, which means reins dev code is in a production build.`);
|
|
38
|
+
return 2;
|
|
39
|
+
}
|
|
40
|
+
let found = 0;
|
|
41
|
+
for (const dir of dirs) {
|
|
42
|
+
let hits;
|
|
43
|
+
try {
|
|
44
|
+
hits = findMarker(dir);
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
err(`reins-verify-bundle: ${e.message}`);
|
|
48
|
+
return 2;
|
|
49
|
+
}
|
|
50
|
+
for (const hit of hits)
|
|
51
|
+
err(`reins dev code found: ${dir}/${hit}`);
|
|
52
|
+
found += hits.length;
|
|
53
|
+
}
|
|
54
|
+
if (found > 0) {
|
|
55
|
+
err(`reins-verify-bundle: ${found} file(s) contain reins dev code. Use the @mindmakr/reins/vite, @mindmakr/reins/next or @mindmakr/reins/metro plugin, or check REINS_ENABLE.`);
|
|
56
|
+
return 1;
|
|
57
|
+
}
|
|
58
|
+
out(`reins-verify-bundle: clean (${dirs.join(', ')})`);
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
package/dist/vite.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** The parts of the Vite plugin API this plugin uses, so it needs no Vite types. */
|
|
2
|
+
interface ResolvedConfig {
|
|
3
|
+
root: string;
|
|
4
|
+
command: 'build' | 'serve';
|
|
5
|
+
mode: string;
|
|
6
|
+
}
|
|
7
|
+
interface Server {
|
|
8
|
+
config: {
|
|
9
|
+
root: string;
|
|
10
|
+
};
|
|
11
|
+
middlewares: {
|
|
12
|
+
use(fn: (req: any, res: any, next: () => void) => void): void;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/** Entries that carry the dev marker, and the stubs that replace them in production builds. */
|
|
16
|
+
export declare const STUBS: Record<string, string>;
|
|
17
|
+
export interface ReinsViteOptions {
|
|
18
|
+
/** Keep reins in production builds. Prefer the REINS_ENABLE=1 env var, and only for staging. */
|
|
19
|
+
keep?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Dev: serves the pairing token at /__reins/token from `.reins/token`.
|
|
23
|
+
* Build (not development mode): resolves `@mindmakr/reins` to `@mindmakr/reins/stub` and `@mindmakr/reins/record` to `@mindmakr/reins/record-stub`, so no reins code ships.
|
|
24
|
+
*/
|
|
25
|
+
export declare function reinsPlugin(options?: ReinsViteOptions): {
|
|
26
|
+
name: string;
|
|
27
|
+
enforce: "pre";
|
|
28
|
+
configResolved(config: ResolvedConfig): void;
|
|
29
|
+
resolveId(this: any, id: string, importer?: string): Promise<any>;
|
|
30
|
+
configureServer(server: Server): void;
|
|
31
|
+
};
|
|
32
|
+
export default reinsPlugin;
|
package/dist/vite.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { keepInBuild, TOKEN_ROUTE, tokenResponse } from '@mindmakr/reins/server';
|
|
2
|
+
/** Entries that carry the dev marker, and the stubs that replace them in production builds. */
|
|
3
|
+
export const STUBS = { '@mindmakr/reins': '@mindmakr/reins/stub', '@mindmakr/reins/record': '@mindmakr/reins/record-stub' };
|
|
4
|
+
/**
|
|
5
|
+
* Dev: serves the pairing token at /__reins/token from `.reins/token`.
|
|
6
|
+
* Build (not development mode): resolves `@mindmakr/reins` to `@mindmakr/reins/stub` and `@mindmakr/reins/record` to `@mindmakr/reins/record-stub`, so no reins code ships.
|
|
7
|
+
*/
|
|
8
|
+
export function reinsPlugin(options = {}) {
|
|
9
|
+
let stub = false;
|
|
10
|
+
return {
|
|
11
|
+
name: 'reins',
|
|
12
|
+
enforce: 'pre',
|
|
13
|
+
configResolved(config) {
|
|
14
|
+
stub = config.command === 'build' && config.mode !== 'development' && !options.keep && !keepInBuild();
|
|
15
|
+
},
|
|
16
|
+
async resolveId(id, importer) {
|
|
17
|
+
const to = stub && Object.prototype.hasOwnProperty.call(STUBS, id) ? STUBS[id] : null;
|
|
18
|
+
return to ? this.resolve(to, importer, { skipSelf: true }) : null;
|
|
19
|
+
},
|
|
20
|
+
configureServer(server) {
|
|
21
|
+
server.middlewares.use((req, res, next) => {
|
|
22
|
+
if (req.url !== TOKEN_ROUTE)
|
|
23
|
+
return next();
|
|
24
|
+
const { status, body } = tokenResponse(server.config.root, req.headers);
|
|
25
|
+
res.statusCode = status;
|
|
26
|
+
res.setHeader('Content-Type', 'text/plain');
|
|
27
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
28
|
+
res.end(body);
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export default reinsPlugin;
|
package/dist/webmcp.d.ts
ADDED
package/dist/webmcp.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const findModelContext = (g) => {
|
|
2
|
+
const m = g.document?.modelContext || g.navigator?.modelContext;
|
|
3
|
+
return m?.registerTool && m;
|
|
4
|
+
};
|
|
5
|
+
export function registerTool(mc, a, run) {
|
|
6
|
+
const s = a.input || { type: 'object', properties: {} }, c = !!a.consequential, reg = mc.registerTool({
|
|
7
|
+
...a,
|
|
8
|
+
inputSchema: c ? { ...s, properties: { ...s.properties, confirm: { type: 'boolean' } }, required: [...(s.required || []), 'confirm'] } : s,
|
|
9
|
+
annotations: { readOnlyHint: !!a.readOnly && !c, destructiveHint: c },
|
|
10
|
+
execute: async ({ confirm, ...rest } = {}) => ({
|
|
11
|
+
content: [{ type: 'text', text: JSON.stringify((await run(a.name, c ? rest : { confirm, ...rest }, confirm === true)) ?? null) }],
|
|
12
|
+
}),
|
|
13
|
+
});
|
|
14
|
+
return () => {
|
|
15
|
+
try {
|
|
16
|
+
reg?.unregister ? reg.unregister() : mc.unregisterTool?.(a.name);
|
|
17
|
+
}
|
|
18
|
+
catch { }
|
|
19
|
+
};
|
|
20
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,61 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mindmakr/reins",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Give coding agents the reins: a tiny dev-only library to drive, inspect and debug your web and Expo apps",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "mindmakr",
|
|
7
|
+
"homepage": "https://mindmakr.github.io/reins/",
|
|
8
|
+
"bugs": "https://github.com/mindmakr/reins/issues",
|
|
9
|
+
"publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" },
|
|
10
|
+
"repository": { "type": "git", "url": "git+https://github.com/mindmakr/reins.git", "directory": "packages/reins" },
|
|
11
|
+
"type": "module",
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": { "types": "./dist/index.d.ts", "default": "./dist/index.js" },
|
|
17
|
+
"./stub": { "types": "./dist/stub.d.ts", "default": "./dist/stub.js" },
|
|
18
|
+
"./adapters": { "types": "./dist/adapters.d.ts", "default": "./dist/adapters.js" },
|
|
19
|
+
"./server": { "types": "./dist/server.d.ts", "default": "./dist/server.js" },
|
|
20
|
+
"./react": { "types": "./dist/react.d.ts", "default": "./dist/react.js" },
|
|
21
|
+
"./expo": { "types": "./dist/expo.d.ts", "default": "./dist/expo.js" },
|
|
22
|
+
"./expo/metro": { "types": "./dist/metro.d.ts", "default": "./dist/metro.js" },
|
|
23
|
+
"./metro": { "types": "./dist/metro.d.ts", "default": "./dist/metro.js" },
|
|
24
|
+
"./vite": { "types": "./dist/vite.d.ts", "default": "./dist/vite.js" },
|
|
25
|
+
"./next": { "types": "./dist/next.d.ts", "default": "./dist/next.js" },
|
|
26
|
+
"./next/token-route": { "types": "./dist/next-token-route.d.ts", "default": "./dist/next-token-route.js" },
|
|
27
|
+
"./verify": { "types": "./dist/verify.d.ts", "default": "./dist/verify.js" },
|
|
28
|
+
"./bridge": { "types": "./dist/bridge/index.d.ts", "default": "./dist/bridge/index.js" },
|
|
29
|
+
"./report": { "types": "./dist/report.d.ts", "default": "./dist/report.js" },
|
|
30
|
+
"./node": { "types": "./dist/node.d.ts", "default": "./dist/node.js" },
|
|
31
|
+
"./record": { "types": "./dist/record.d.ts", "default": "./dist/record.js" },
|
|
32
|
+
"./record-stub": { "types": "./dist/record-stub.d.ts", "default": "./dist/record-stub.js" }
|
|
33
|
+
},
|
|
34
|
+
"bin": {
|
|
35
|
+
"reins": "dist/cli.js",
|
|
36
|
+
"reins-verify-bundle": "dist/verify-cli.js"
|
|
37
|
+
},
|
|
38
|
+
"files": ["dist"],
|
|
39
|
+
"engines": { "node": ">=18" },
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc -p tsconfig.json",
|
|
42
|
+
"prepublishOnly": "npm run build"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@modelcontextprotocol/sdk": "^1.32.0",
|
|
46
|
+
"ws": "^8.18.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"next": ">=13",
|
|
50
|
+
"playwright": ">=1.40",
|
|
51
|
+
"react": ">=17",
|
|
52
|
+
"react-native": ">=0.70"
|
|
53
|
+
},
|
|
54
|
+
"peerDependenciesMeta": {
|
|
55
|
+
"next": { "optional": true },
|
|
56
|
+
"playwright": { "optional": true },
|
|
57
|
+
"react": { "optional": true },
|
|
58
|
+
"react-native": { "optional": true }
|
|
59
|
+
},
|
|
60
|
+
"keywords": ["ai-agents", "testing", "mcp", "webmcp", "devtools", "lucid-coding"]
|
|
61
|
+
}
|