@source-repo/rpc-cli 3.0.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.
Files changed (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1131 -0
  3. package/dist/bench.d.ts +66 -0
  4. package/dist/bench.d.ts.map +1 -0
  5. package/dist/bench.js +109 -0
  6. package/dist/bench.js.map +1 -0
  7. package/dist/broker.d.ts +61 -0
  8. package/dist/broker.d.ts.map +1 -0
  9. package/dist/broker.js +56 -0
  10. package/dist/broker.js.map +1 -0
  11. package/dist/bus.d.ts +142 -0
  12. package/dist/bus.d.ts.map +1 -0
  13. package/dist/bus.js +272 -0
  14. package/dist/bus.js.map +1 -0
  15. package/dist/bus.types.json +269 -0
  16. package/dist/conform.d.ts +75 -0
  17. package/dist/conform.d.ts.map +1 -0
  18. package/dist/conform.js +152 -0
  19. package/dist/conform.js.map +1 -0
  20. package/dist/console.d.ts +285 -0
  21. package/dist/console.d.ts.map +1 -0
  22. package/dist/console.js +686 -0
  23. package/dist/console.js.map +1 -0
  24. package/dist/console.types.json +1730 -0
  25. package/dist/extract.d.ts +37 -0
  26. package/dist/extract.d.ts.map +1 -0
  27. package/dist/extract.js +272 -0
  28. package/dist/extract.js.map +1 -0
  29. package/dist/fake.d.ts +58 -0
  30. package/dist/fake.d.ts.map +1 -0
  31. package/dist/fake.js +164 -0
  32. package/dist/fake.js.map +1 -0
  33. package/dist/index.d.ts +3 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +905 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/mcp.d.ts +15 -0
  38. package/dist/mcp.d.ts.map +1 -0
  39. package/dist/mcp.js +507 -0
  40. package/dist/mcp.js.map +1 -0
  41. package/dist/network.d.ts +58 -0
  42. package/dist/network.d.ts.map +1 -0
  43. package/dist/network.js +64 -0
  44. package/dist/network.js.map +1 -0
  45. package/dist/record.d.ts +74 -0
  46. package/dist/record.d.ts.map +1 -0
  47. package/dist/record.js +221 -0
  48. package/dist/record.js.map +1 -0
  49. package/dist/tapping.d.ts +11 -0
  50. package/dist/tapping.d.ts.map +1 -0
  51. package/dist/tapping.js +71 -0
  52. package/dist/tapping.js.map +1 -0
  53. package/dist/verbs.d.ts +59 -0
  54. package/dist/verbs.d.ts.map +1 -0
  55. package/dist/verbs.js +324 -0
  56. package/dist/verbs.js.map +1 -0
  57. package/dist/web/app.css +1 -0
  58. package/dist/web/app.js +2063 -0
  59. package/dist/web/app.js.map +1 -0
  60. package/dist/web/index.html +13 -0
  61. package/package.json +65 -0
@@ -0,0 +1,59 @@
1
+ import type { DescribedMethod, ServerDescription, TypeNode } from '@source-repo/rpc';
2
+ import { type NetworkOptions } from './network.js';
3
+ /**
4
+ * The console's verbs without the browser: `peers`, `describe`, `call` and `watch`, one shot each,
5
+ * with an exit code.
6
+ *
7
+ * Everything the network could be asked was reachable only through the console (which needs a
8
+ * browser) or the MCP server (which needs a model), so a shell script and a CI job had nothing.
9
+ * These are the same five verbs `ConsoleService` exposes, minus the HTTP server, plus the two
10
+ * things a command line needs and an RPC service does not: an exit status, and output that survives
11
+ * a pipe.
12
+ *
13
+ * `--json` on every verb, because the human rendering is for reading and the JSON is for `jq`, and
14
+ * guessing which one is wanted from whether stdout is a tty is the kind of cleverness that breaks
15
+ * in CI.
16
+ */
17
+ /** Where a verb writes. Injected so tests can read what a command printed. */
18
+ export interface Output {
19
+ out: (text: string) => void;
20
+ err: (text: string) => void;
21
+ }
22
+ export declare const processOutput: Output;
23
+ export interface VerbOptions extends NetworkOptions {
24
+ json: boolean;
25
+ /** How long to wait for a peer to appear before giving up on it. */
26
+ wait: number;
27
+ }
28
+ /** How a type reads when written out, which is what a signature line should show. */
29
+ export declare const typeText: (type: TypeNode | undefined) => string;
30
+ export declare const signatureOf: (method: DescribedMethod) => string;
31
+ /**
32
+ * Turns one command-line word into the value the contract asks for.
33
+ *
34
+ * A shell has only strings, so without this `source-rpc call plant plant.writeSetpoint 1200` sends
35
+ * "1200" and comes back `InvalidParams: expected number, got string` - technically correct and
36
+ * useless. The peer's own contract says what argument 0 is, so it decides.
37
+ *
38
+ * Where there is no contract the rule is JSON-if-it-parses, else the literal text: `42` is a
39
+ * number, `{"a":1}` is an object, and `hello` is a string rather than a syntax error.
40
+ */
41
+ export declare const coerceArgument: (text: string, declared: TypeNode | undefined, types: ServerDescription['types']) => unknown;
42
+ /** Coerces a whole argument list, naming the argument that would not convert. */
43
+ export declare const coerceArguments: (texts: string[], method: DescribedMethod | undefined, types: ServerDescription['types']) => unknown[];
44
+ export declare const runPeers: (options: VerbOptions, io?: Output) => Promise<number>;
45
+ export declare const runDescribe: (peer: string, options: VerbOptions, io?: Output) => Promise<number>;
46
+ export declare const runCall: (peer: string, target: string, argumentTexts: string[], options: VerbOptions & {
47
+ rawArgs?: string;
48
+ idempotencyKey?: string;
49
+ }, io?: Output) => Promise<number>;
50
+ /**
51
+ * Streams one event as one line of JSON until the caller stops it.
52
+ *
53
+ * jsonl rather than the human rendering the other verbs get: this is the verb whose output is most
54
+ * likely to be piped somewhere, and a stream that is pleasant to read is a stream nothing can parse.
55
+ */
56
+ export declare const runWatch: (peer: string, target: string, options: VerbOptions, io?: Output,
57
+ /** Resolves to stop watching. Ctrl-C on a command line; a promise the test controls in a test. */
58
+ until?: Promise<void>) => Promise<number>;
59
+ //# sourceMappingURL=verbs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verbs.d.ts","sourceRoot":"","sources":["../src/verbs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AACpF,OAAO,EAAoD,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AAEpG;;;;;;;;;;;;;GAaG;AAEH,8EAA8E;AAC9E,MAAM,WAAW,MAAM;IACnB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3B,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAC9B;AAED,eAAO,MAAM,aAAa,EAAE,MAG3B,CAAA;AAED,MAAM,WAAW,WAAY,SAAQ,cAAc;IAC/C,IAAI,EAAE,OAAO,CAAA;IACb,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAA;CACf;AAsBD,qFAAqF;AACrF,eAAO,MAAM,QAAQ,SAAU,QAAQ,GAAG,SAAS,KAAG,MAwBrD,CAAA;AAED,eAAO,MAAM,WAAW,WAAY,eAAe,WAKlD,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,SAAU,MAAM,YAAY,QAAQ,GAAG,SAAS,SAAS,iBAAiB,CAAC,OAAO,CAAC,KAAG,OA6ChH,CAAA;AAUD,iFAAiF;AACjF,eAAO,MAAM,eAAe,UAAW,MAAM,EAAE,UAAU,eAAe,GAAG,SAAS,SAAS,iBAAiB,CAAC,OAAO,CAAC,cAStH,CAAA;AA4CD,eAAO,MAAM,QAAQ,YAAa,WAAW,OAAM,MAAM,oBAWnD,CAAA;AAEN,eAAO,MAAM,WAAW,SAAU,MAAM,WAAW,WAAW,OAAM,MAAM,oBA4BpE,CAAA;AAEN,eAAO,MAAM,OAAO,SACV,MAAM,UACJ,MAAM,iBACC,MAAM,EAAE,WACd,WAAW,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,OAChE,MAAM,oBA8DR,CAAA;AAEN;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,SACX,MAAM,UACJ,MAAM,WACL,WAAW,OAChB,MAAM;AACV,kGAAkG;QAC3F,OAAO,CAAC,IAAI,CAAC,oBA0BlB,CAAA"}
package/dist/verbs.js ADDED
@@ -0,0 +1,324 @@
1
+ import { awaitPeer, connectNetwork } from './network.js';
2
+ export const processOutput = {
3
+ out: (text) => void process.stdout.write(text),
4
+ err: (text) => void process.stderr.write(text)
5
+ };
6
+ const failureText = (e) => {
7
+ const error = e;
8
+ return error?.code ? `${error.code}: ${error.message ?? ''}`.trim() : e instanceof Error ? e.message : String(e);
9
+ };
10
+ /** Resolves a `ref` so a caller does not have to care whether a type was named. */
11
+ const resolveType = (type, types) => type?.kind === 'ref' ? resolveType(types?.[type.name], types) : type;
12
+ /** A parameter is optional when its type admits null, which is how the extractor writes `mode?`. */
13
+ const isOptional = (type) => type?.kind === 'any' || (type?.kind === 'union' && type.options.some((option) => option.kind === 'literal' && option.value === null));
14
+ /** The type to convert against, with the optional-ness stripped off. */
15
+ const requiredPart = (type) => {
16
+ if (type?.kind !== 'union')
17
+ return type;
18
+ const options = type.options.filter((option) => !(option.kind === 'literal' && option.value === null));
19
+ return options.length === 1 ? options[0] : { ...type, options };
20
+ };
21
+ /** How a type reads when written out, which is what a signature line should show. */
22
+ export const typeText = (type) => {
23
+ if (!type)
24
+ return 'unknown';
25
+ switch (type.kind) {
26
+ case 'literal':
27
+ return JSON.stringify(type.value);
28
+ case 'array':
29
+ return `${typeText(type.items)}[]`;
30
+ case 'tuple':
31
+ return `[${type.items.map(typeText).join(', ')}]`;
32
+ case 'union':
33
+ return type.options.map(typeText).join(' | ');
34
+ case 'ref':
35
+ return type.name;
36
+ case 'object':
37
+ return `{ ${Object.entries(type.fields)
38
+ .map(([name, field]) => `${name}${field.optional ? '?' : ''}: ${typeText(field.type)}`)
39
+ .join(', ')} }`;
40
+ case 'record':
41
+ return `{ [key: string]: ${typeText(type.values)} }`;
42
+ case 'number':
43
+ return type.min !== undefined || type.max !== undefined ? `number(${type.min ?? ''}..${type.max ?? ''})` : 'number';
44
+ default:
45
+ return type.kind;
46
+ }
47
+ };
48
+ export const signatureOf = (method) => {
49
+ if (!method.params)
50
+ return `${method.name}(…)`;
51
+ const names = method.paramNames ?? method.params.map((_, index) => `argument ${index}`);
52
+ const parameters = method.params.map((type, index) => `${names[index]}${isOptional(type) ? '?' : ''}: ${typeText(requiredPart(type))}`);
53
+ return `${method.name}(${parameters.join(', ')})${method.returns ? `: ${typeText(method.returns)}` : ''}`;
54
+ };
55
+ /**
56
+ * Turns one command-line word into the value the contract asks for.
57
+ *
58
+ * A shell has only strings, so without this `source-rpc call plant plant.writeSetpoint 1200` sends
59
+ * "1200" and comes back `InvalidParams: expected number, got string` - technically correct and
60
+ * useless. The peer's own contract says what argument 0 is, so it decides.
61
+ *
62
+ * Where there is no contract the rule is JSON-if-it-parses, else the literal text: `42` is a
63
+ * number, `{"a":1}` is an object, and `hello` is a string rather than a syntax error.
64
+ */
65
+ export const coerceArgument = (text, declared, types) => {
66
+ const type = resolveType(requiredPart(declared), types);
67
+ if (!type)
68
+ return looseValue(text);
69
+ switch (type.kind) {
70
+ case 'string':
71
+ return text;
72
+ case 'number': {
73
+ const value = Number(text);
74
+ if (!Number.isFinite(value))
75
+ throw new Error(`expected a number, got '${text}'`);
76
+ return value;
77
+ }
78
+ case 'boolean':
79
+ if (text === 'true' || text === '1')
80
+ return true;
81
+ if (text === 'false' || text === '0')
82
+ return false;
83
+ throw new Error(`expected true or false, got '${text}'`);
84
+ case 'date': {
85
+ const value = new Date(text);
86
+ if (Number.isNaN(value.getTime()))
87
+ throw new Error(`expected a date, got '${text}'`);
88
+ return value;
89
+ }
90
+ case 'bytes': {
91
+ const hex = text.startsWith('0x') ? text.slice(2) : text;
92
+ if (hex.length % 2 || /[^0-9a-fA-F]/.test(hex))
93
+ throw new Error(`expected hex bytes, got '${text}'`);
94
+ return Uint8Array.from(hex.match(/../g) ?? [], (pair) => parseInt(pair, 16));
95
+ }
96
+ case 'literal':
97
+ // A union of literals is a fixed set of words, so matching the text against them beats
98
+ // JSON-parsing it: 'auto' is the value, not a string that happens to look like one.
99
+ return typeof type.value === 'string' && text === type.value ? type.value : looseValue(text);
100
+ case 'union': {
101
+ const literal = type.options.find((option) => option.kind === 'literal' && String(option.value) === text);
102
+ if (literal)
103
+ return literal.value;
104
+ return looseValue(text);
105
+ }
106
+ case 'any':
107
+ return looseValue(text);
108
+ default:
109
+ // object, array, tuple, record: nothing but JSON will do, and a failure here is worth
110
+ // naming, since the alternative is sending the brace-laden text as a string.
111
+ try {
112
+ return JSON.parse(text);
113
+ }
114
+ catch {
115
+ throw new Error(`expected ${typeText(type)} as JSON, got '${text}'`);
116
+ }
117
+ }
118
+ };
119
+ const looseValue = (text) => {
120
+ try {
121
+ return JSON.parse(text);
122
+ }
123
+ catch {
124
+ return text;
125
+ }
126
+ };
127
+ /** Coerces a whole argument list, naming the argument that would not convert. */
128
+ export const coerceArguments = (texts, method, types) => {
129
+ const names = method?.paramNames;
130
+ return texts.map((text, index) => {
131
+ try {
132
+ return coerceArgument(text, method?.params?.[index], types);
133
+ }
134
+ catch (e) {
135
+ throw new Error(`argument ${index}${names?.[index] ? ` (${names[index]})` : ''}: ${e.message}`, { cause: e });
136
+ }
137
+ });
138
+ };
139
+ /** `plant.writeSetpoint` - one word, because two positional arguments here read as one thing. */
140
+ const splitTarget = (target) => {
141
+ const dot = target.lastIndexOf('.');
142
+ if (dot <= 0 || dot === target.length - 1)
143
+ return undefined;
144
+ return { namespace: target.slice(0, dot), member: target.slice(dot + 1) };
145
+ };
146
+ const describePeer = async (connected, peer) => {
147
+ const proxy = await connected.network.proxy('msgrpc', peer);
148
+ return await proxy.remote.describe();
149
+ };
150
+ /**
151
+ * Runs a verb against a network and closes it again, whatever happened.
152
+ *
153
+ * Every verb is one shot, so the link is opened for the length of one answer. The exception is
154
+ * `watch`, which hands back a promise that settles on Ctrl-C.
155
+ */
156
+ const withNetwork = async (options, io, body) => {
157
+ let connected;
158
+ try {
159
+ connected = await connectNetwork(options);
160
+ }
161
+ catch (e) {
162
+ io.err(`source-rpc: cannot join the network: ${failureText(e)}\n`);
163
+ return 1;
164
+ }
165
+ try {
166
+ return await body(connected);
167
+ }
168
+ catch (e) {
169
+ io.err(`source-rpc: ${failureText(e)}\n`);
170
+ return 1;
171
+ }
172
+ finally {
173
+ await connected.close().catch(() => undefined);
174
+ }
175
+ };
176
+ /** A peer that never appeared, said once and the same way everywhere. */
177
+ const missing = (peer, options, io) => {
178
+ io.err(`source-rpc: ${peer} did not appear within ${options.wait} ms. Run 'source-rpc peers' to see who is there.\n`);
179
+ return 1;
180
+ };
181
+ export const runPeers = (options, io = processOutput) => withNetwork(options, io, async (connected) => {
182
+ // Presence is retained, so most of the list is already here - but it arrives just after the
183
+ // subscription does, and a command that read the set immediately would sometimes print
184
+ // nothing on a network that was plainly up.
185
+ await new Promise((resolve) => setTimeout(resolve, Math.min(options.wait, 1000)));
186
+ const peers = [...connected.online].sort();
187
+ if (options.json)
188
+ io.out(JSON.stringify({ peers }, null, 2) + '\n');
189
+ else if (peers.length === 0)
190
+ io.err('source-rpc: no peers announced themselves.\n');
191
+ else
192
+ io.out(peers.map((peer) => peer + '\n').join(''));
193
+ return 0;
194
+ });
195
+ export const runDescribe = (peer, options, io = processOutput) => withNetwork(options, io, async (connected) => {
196
+ if (!(await awaitPeer(connected, peer, options.wait)))
197
+ return missing(peer, options, io);
198
+ let description;
199
+ try {
200
+ description = await describePeer(connected, peer);
201
+ }
202
+ catch (e) {
203
+ // An answer about the peer, not a broken command: a server started without
204
+ // exposeIntrospection is a fact worth reporting plainly.
205
+ io.err(`source-rpc: ${peer} could not be described: ${failureText(e)}\n`);
206
+ return 1;
207
+ }
208
+ if (options.json) {
209
+ io.out(JSON.stringify(description, null, 2) + '\n');
210
+ return 0;
211
+ }
212
+ io.out(`${description.name}${description.version ? ` (contract ${description.version})` : ''} — arguments ${description.validating ? 'checked' : 'not checked'}\n`);
213
+ for (const namespace of description.namespaces) {
214
+ io.out(`\n${namespace.name}${namespace.version ? `@${namespace.version}` : ''}${namespace.className ? ` ${namespace.className}` : ''}${namespace.created ? ' (created at runtime)' : ''}${namespace.serialised ? ' (one call at a time)' : ''}\n`);
215
+ // What a repeat costs is the thing worth knowing before calling something on a plant,
216
+ // so it goes on the line with the signature rather than behind --json.
217
+ for (const method of namespace.methods)
218
+ io.out(` ${signatureOf(method)}${method.semantics ? ` [${method.semantics}]` : ''}\n`);
219
+ for (const event of namespace.events)
220
+ io.out(` event ${event.name}(${event.params ? event.params.map(typeText).join(', ') : '…'}) ${event.subscribers} subscriber${event.subscribers === 1 ? '' : 's'}\n`);
221
+ }
222
+ return 0;
223
+ });
224
+ export const runCall = (peer, target, argumentTexts, options, io = processOutput) => withNetwork(options, io, async (connected) => {
225
+ const split = splitTarget(target);
226
+ if (!split) {
227
+ io.err(`source-rpc: '${target}' should be <namespace>.<method>, e.g. plant.writeSetpoint\n`);
228
+ return 1;
229
+ }
230
+ if (!(await awaitPeer(connected, peer, options.wait)))
231
+ return missing(peer, options, io);
232
+ let args;
233
+ if (options.rawArgs !== undefined) {
234
+ // The escape hatch, for a call the contract cannot describe or a value the shell would
235
+ // mangle. Whatever is in here is sent as it parses.
236
+ let parsed;
237
+ try {
238
+ parsed = JSON.parse(options.rawArgs);
239
+ }
240
+ catch (e) {
241
+ io.err(`source-rpc: --args is not JSON: ${e.message}\n`);
242
+ return 1;
243
+ }
244
+ if (!Array.isArray(parsed)) {
245
+ io.err('source-rpc: --args must be a JSON array of positional arguments\n');
246
+ return 1;
247
+ }
248
+ args = parsed;
249
+ }
250
+ else {
251
+ // Described first, so the contract decides what each word means. A peer with no
252
+ // introspection is not an error here - it just means the loose rule applies.
253
+ const description = await describePeer(connected, peer).catch(() => undefined);
254
+ const method = description?.namespaces.find((namespace) => namespace.name === split.namespace)?.methods.find((entry) => entry.name === split.member);
255
+ try {
256
+ args = coerceArguments(argumentTexts, method, description?.types);
257
+ }
258
+ catch (e) {
259
+ io.err(`source-rpc: ${e.message}\n`);
260
+ return 1;
261
+ }
262
+ }
263
+ const started = Date.now();
264
+ try {
265
+ const proxy = await connected.network.proxy(split.namespace, peer);
266
+ // With a key, two runs of this command are two attempts at one command - which is how a
267
+ // durable idempotency store is checked from a shell: call it twice, see it run once.
268
+ const remote = options.idempotencyKey ? proxy.remote.$with({ idempotencyKey: options.idempotencyKey }) : proxy.remote;
269
+ const result = await remote[split.member](...args);
270
+ const ms = Date.now() - started;
271
+ if (options.json)
272
+ io.out(JSON.stringify({ result, ms }, null, 2) + '\n');
273
+ else {
274
+ // The result on stdout and the timing on stderr, so piping into jq gets the value
275
+ // and nothing else while a person still sees what it cost.
276
+ io.out((result === undefined ? '' : JSON.stringify(result, null, 2)) + '\n');
277
+ io.err(`${ms} ms\n`);
278
+ }
279
+ return 0;
280
+ }
281
+ catch (e) {
282
+ const failure = e;
283
+ if (options.json)
284
+ io.out(JSON.stringify({ error: failure.message ?? String(e), code: failure.code, ms: Date.now() - started }, null, 2) + '\n');
285
+ else
286
+ io.err(`source-rpc: ${peer}.${target} failed: ${failureText(e)}\n`);
287
+ // A refused call is a failed command. That is the whole point of running this in CI.
288
+ return 1;
289
+ }
290
+ });
291
+ /**
292
+ * Streams one event as one line of JSON until the caller stops it.
293
+ *
294
+ * jsonl rather than the human rendering the other verbs get: this is the verb whose output is most
295
+ * likely to be piped somewhere, and a stream that is pleasant to read is a stream nothing can parse.
296
+ */
297
+ export const runWatch = (peer, target, options, io = processOutput,
298
+ /** Resolves to stop watching. Ctrl-C on a command line; a promise the test controls in a test. */
299
+ until = new Promise(() => { })) => withNetwork(options, io, async (connected) => {
300
+ const split = splitTarget(target);
301
+ if (!split) {
302
+ io.err(`source-rpc: '${target}' should be <namespace>.<event>, e.g. plant.alarm\n`);
303
+ return 1;
304
+ }
305
+ if (!(await awaitPeer(connected, peer, options.wait)))
306
+ return missing(peer, options, io);
307
+ const handler = (...args) => io.out(JSON.stringify({ at: Date.now(), peer, namespace: split.namespace, event: split.member, args }) + '\n');
308
+ let proxy;
309
+ try {
310
+ proxy = await connected.network.proxy(split.namespace, peer);
311
+ await proxy.remote.on(split.member, handler);
312
+ }
313
+ catch (e) {
314
+ io.err(`source-rpc: cannot watch ${peer}.${target}: ${failureText(e)}\n`);
315
+ return 1;
316
+ }
317
+ io.err(`source-rpc: watching ${peer}.${target}. Ctrl-C to stop.\n`);
318
+ await until;
319
+ // Drops the server's subscription too, rather than only walking away from it: a debugging
320
+ // session should not leave listeners behind on a device that outlives it.
321
+ await proxy.remote.off(split.member, handler).catch(() => undefined);
322
+ return 0;
323
+ });
324
+ //# sourceMappingURL=verbs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verbs.js","sourceRoot":"","sources":["../src/verbs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ :root{--bg: #0e1116;--panel: #151a21;--panel-2: #1b212a;--line: #262e3a;--text: #d6dde7;--muted: #7d8899;--accent: #4ea1ff;--accent-dim: #1d3a5c;--ok: #37d18a;--bad: #ff6b6b;--warn: #f0b429;--mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;color-scheme:dark}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--text);font:14px/1.5 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;-webkit-font-smoothing:antialiased}button{font:inherit;color:inherit;background:none;border:none;cursor:pointer}.mono,code,pre,time{font-family:var(--mono)}.muted{color:var(--muted);font-size:12px}.app{display:grid;grid-template-columns:240px minmax(0,1fr) 340px;height:100vh}aside{background:var(--panel);overflow-y:auto;padding:14px}.stream{flex:1 1 auto;min-height:0;overflow-y:auto;padding:14px}aside{border-right:1px solid var(--line)}.side{display:flex;flex-direction:column;min-height:0;border-left:1px solid var(--line);background:var(--panel)}.chat{display:flex;flex-direction:column;min-height:0;flex:1 1 auto;padding:14px;border-bottom:1px solid var(--line)}.chat-log{flex:1;min-height:0;overflow-y:auto;margin-bottom:10px}.said{margin-bottom:6px;font-size:13px}.said .text{display:inline-block;padding:5px 9px;border-radius:8px;background:var(--panel-2);word-break:break-word}.said.mine{text-align:right}.said.mine .text{background:var(--accent-dim);color:#eaf3ff;text-align:left}.chat-send{display:flex;gap:6px}.chat-send .control{flex:1}.bad{color:var(--bad)}main{overflow-y:auto;padding:22px 26px 60px}aside header,.stream header{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-bottom:12px}h1{margin:0;font-size:12px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;color:var(--muted)}.peer-head{display:flex;align-items:baseline;gap:12px;padding-bottom:14px;margin-bottom:18px;border-bottom:1px solid var(--line)}.peer-head h1{font-size:20px;letter-spacing:0;text-transform:none;color:var(--text);font-family:var(--mono)}.identity{display:flex;flex-direction:column;gap:1px;padding:8px 10px 9px;margin-bottom:14px;border:1px solid var(--line);border-left:3px solid var(--accent);border-radius:6px;background:var(--panel-2)}.identity .name{font-size:13px;color:var(--text);word-break:break-word}.you{margin-left:auto;padding:0 6px;border-radius:999px;background:var(--line);font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}.status{font-size:11px;font-family:var(--mono)}.status.ok{color:var(--ok)}.status.warn{color:var(--warn)}.peer{display:flex;align-items:center;gap:8px;width:100%;padding:7px 10px;margin-bottom:3px;border-radius:6px;font-family:var(--mono);font-size:13px;text-align:left;transition:background .12s}.peer:hover{background:var(--panel-2)}.peer.selected{background:var(--accent-dim);color:#fff}.dot{width:7px;height:7px;border-radius:50%;background:var(--ok);flex:none;box-shadow:0 0 6px #37d18a99}.dot.off{background:var(--muted);box-shadow:none}.namespace{margin-bottom:28px}.namespace h2{display:flex;align-items:baseline;gap:10px;margin:0 0 10px;font-size:15px;font-weight:600;font-family:var(--mono)}.badge{padding:1px 6px;border:1px solid var(--line);border-radius:999px;font-size:11px;font-family:var(--mono);color:var(--muted)}.method{border:1px solid var(--line);border-radius:8px;margin-bottom:6px;background:var(--panel);overflow:hidden}.method.open{border-color:var(--accent-dim);background:var(--panel-2)}.method-head{display:flex;align-items:baseline;gap:8px;width:100%;padding:9px 12px;text-align:left}.method-head:hover{background:#4ea1ff0f}.method-head code{font-size:13px;word-break:break-word}.chevron{color:var(--muted);font-size:11px;flex:none}.method-body{padding:4px 14px 14px;border-top:1px solid var(--line)}.field{padding:10px 0;border-bottom:1px dashed rgba(38,46,58,.7)}.field:last-of-type{border-bottom:none}.field.off .control,.field.off .checkbox{opacity:.35}.field-label{display:flex;align-items:center;gap:8px;margin-bottom:5px}.field-label .name{font-family:var(--mono);font-size:13px}.field-label .type{font-family:var(--mono);font-size:11px;color:var(--muted)}.include{accent-color:var(--accent)}.control{width:100%;padding:7px 10px;background:#0b0f14;border:1px solid var(--line);border-radius:6px;color:var(--text);font:inherit;font-size:13px}textarea.control{resize:vertical}.control:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 2px #4ea1ff2e}.checkbox{display:inline-flex;align-items:center;gap:8px;font-family:var(--mono);font-size:13px;cursor:pointer}.checkbox input{accent-color:var(--accent);width:16px;height:16px}.actions{margin-top:12px}.primary{padding:7px 18px;border-radius:6px;background:var(--accent);color:#06121f;font-weight:600;font-size:13px}.primary:hover:not(:disabled){background:#6fb4ff}.primary:disabled{opacity:.5;cursor:default}.result{margin:12px 0 0;padding:10px 12px;border-radius:6px;background:#0b0f14;border-left:3px solid var(--ok);font-size:12.5px;white-space:pre-wrap;word-break:break-word;max-height:320px;overflow:auto}.result.bad{border-left-color:var(--bad);color:#ffb1b1}.events{margin-top:10px;padding:10px 12px;border:1px solid var(--line);border-radius:8px}.events h3{margin:0 0 6px;font-size:11px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;color:var(--muted)}.event-row{display:flex;align-items:center;gap:10px;padding:4px 0;font-size:13px}.event-row code{flex:1;min-width:0;word-break:break-word}.toggle{padding:3px 10px;border:1px solid var(--line);border-radius:999px;font-size:11px;font-family:var(--mono);color:var(--muted)}.toggle:hover{border-color:var(--accent);color:var(--text)}.toggle.on{background:var(--accent-dim);border-color:var(--accent);color:#cfe6ff}.streamed{padding:7px 0;border-bottom:1px solid rgba(38,46,58,.6);font-size:12px}.streamed time{color:var(--muted);font-size:11px;margin-right:8px;white-space:nowrap}.streamed code{color:var(--accent);font-size:12px}.streamed pre{margin:3px 0 0;color:var(--text);font-size:12px;white-space:pre-wrap;word-break:break-word}.notice{padding:14px 16px;border:1px solid var(--line);border-left:3px solid var(--warn);border-radius:6px;background:var(--panel)}.notice p{margin:6px 0 0}@media(max-width:1100px){.app{grid-template-columns:200px minmax(0,1fr);grid-template-rows:minmax(0,1fr) 220px}.stream{grid-column:1 / -1;border-left:none;border-top:1px solid var(--line)}}.tabs{display:flex;flex:0 0 auto;border-bottom:1px solid var(--line);background:var(--panel-2)}.tab{flex:1 1 0;padding:9px 6px;font-size:11px;font-family:var(--mono);letter-spacing:.06em;text-transform:uppercase;color:var(--muted);border-bottom:2px solid transparent}.tab:hover{color:var(--text)}.tab.on{color:#cfe6ff;border-bottom-color:var(--accent)}.tab .count{margin-left:6px;padding:1px 6px;border-radius:999px;background:var(--accent-dim);color:#cfe6ff;font-size:10px}.traffic{flex:1 1 auto;min-height:0;overflow-y:auto;padding:14px}.traffic header{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-bottom:12px}.traffic-actions{display:flex;gap:6px}.tap-setup{display:flex;flex-direction:column;gap:9px;padding-bottom:10px}.kinds{display:flex;flex-wrap:wrap;align-items:center;gap:6px}.tap-where{margin:0 0 10px;font-size:11px}.traffic .control{margin-bottom:10px}.frame{padding:6px 0 6px 8px;border-left:2px solid var(--line);border-bottom:1px solid rgba(38,46,58,.6);font-size:12px}.frame.post{border-left-color:var(--accent)}.frame.success{border-left-color:var(--ok)}.frame.error{border-left-color:var(--bad)}.frame.event{border-left-color:var(--warn)}.frame-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px}.frame-head time{color:var(--muted);font-size:11px;white-space:nowrap}.frame .arrow{color:var(--muted)}.frame .peers{color:var(--muted);font-size:11px}.frame code{color:var(--accent);font-size:12px}.frame .ms{font-size:11px}.frame .code{color:var(--bad);font-family:var(--mono);font-size:11px}.frame-error{margin:3px 0 0;color:var(--bad);font-size:11px}.frame-payload{margin:3px 0 0;color:var(--text);font-size:11px;font-family:var(--mono);cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.frame-payload.open{white-space:pre-wrap;word-break:break-word}.traffic.hidden{display:none}.problems{flex:1 1 auto;min-height:0;overflow-y:auto;padding:14px}.problems header{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-bottom:12px}.problem{padding:7px 0 7px 8px;border-left:2px solid var(--line);border-bottom:1px solid rgba(38,46,58,.6);font-size:12px}.problem.rejected{border-left-color:var(--bad)}.problem.unroutable{border-left-color:var(--warn)}.problem.peerDisplaced{border-left-color:var(--accent)}.problem.transportError{border-left-color:var(--bad)}.problem-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px}.problem-head time{color:var(--muted);font-size:11px;white-space:nowrap}.problem .kind{font-family:var(--mono);font-size:11px;color:var(--text)}.problem .link{font-size:11px}.problem-body code{color:var(--accent);font-size:11px}.problem-body p{margin:2px 0 0;color:var(--muted);font-size:11px}.tab .count.bad{background:#ff6b6b2e;color:#ffb3b3}.peer .link{margin-left:auto;padding-left:8px;color:var(--muted);font-size:10px;font-family:var(--mono);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:45%}.actions{flex-wrap:wrap}.actions .timing{font-size:11px;font-family:var(--mono);margin-left:auto}.events h3{display:flex;align-items:baseline;gap:8px}.stream .control{margin-bottom:10px}.presence{flex:1 1 auto;min-height:0;overflow-y:auto;padding:14px}.presence header{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-bottom:12px}.flapping{margin-bottom:12px;padding:8px 10px;border:1px solid var(--line);border-left:3px solid var(--warn);border-radius:6px}.flapping p{margin:2px 0;font-size:12px;color:var(--text)}.coming{display:flex;align-items:baseline;gap:8px;padding:5px 0;border-bottom:1px solid rgba(38,46,58,.6);font-size:12px}.coming time{color:var(--muted);font-size:11px;white-space:nowrap}.coming .mark{font-family:var(--mono);width:10px}.coming.online .mark{color:var(--ok)}.coming.offline .mark{color:var(--bad)}.coming .link{margin-left:auto;font-size:10px;font-family:var(--mono)}.peer .role{margin-left:8px;padding:1px 6px;border-radius:999px;font-size:10px;font-family:var(--mono);background:var(--panel-2);color:var(--muted)}.peer .role.broker{color:#cfe6ff;background:var(--accent-dim)}.peer .role.undescribed{color:var(--warn)}.presets{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:10px 0 4px}.preset{display:inline-flex;align-items:center}.preset .toggle{border-top-right-radius:0;border-bottom-right-radius:0;max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.forget{padding:3px 7px;border:1px solid var(--line);border-left:none;border-radius:0 999px 999px 0;font-size:11px;color:var(--muted)}.forget:hover{color:var(--bad);border-color:var(--bad)}