@animalabs/portal-client 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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GAAG,UAAU,EACzB,IAAI,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACpD,YAAY,CAOd"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Build an `OutgoingFile` from in-memory bytes (the portable way to attach a
3
+ * file — works from any client/host, no relay-side filesystem access).
4
+ */
5
+ export function fileFromBytes(name, data, opts) {
6
+ return {
7
+ name,
8
+ bytes: Buffer.from(data).toString('base64'),
9
+ ...(opts?.contentType ? { contentType: opts.contentType } : {}),
10
+ ...(opts?.description ? { description: opts.description } : {}),
11
+ };
12
+ }
13
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/files.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAY,EACZ,IAAyB,EACzB,IAAqD;IAErD,OAAO;QACL,IAAI;QACJ,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC3C,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @animalabs/portal-client
3
+ *
4
+ * General-purpose client for the portal relay: WS transport, client-side cache,
5
+ * typed RPC, and transport-level reconnect/resume. No agent semantics — that's
6
+ * portal-mcpl's job.
7
+ */
8
+ export { PortalClient } from './client.js';
9
+ export type { PortalClientOptions, PortalClientEvents } from './client.js';
10
+ export { ClientCache } from './cache.js';
11
+ export { TypedEmitter } from './emitter.js';
12
+ export { enroll, loadOrEnrollCreds } from './enroll.js';
13
+ export type { EnrollOptions, PortalCredentials } from './enroll.js';
14
+ export { fileFromBytes } from './files.js';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @animalabs/portal-client
3
+ *
4
+ * General-purpose client for the portal relay: WS transport, client-side cache,
5
+ * typed RPC, and transport-level reconnect/resume. No agent semantics — that's
6
+ * portal-mcpl's job.
7
+ */
8
+ export { PortalClient } from './client.js';
9
+ export { ClientCache } from './cache.js';
10
+ export { TypedEmitter } from './emitter.js';
11
+ export { enroll, loadOrEnrollCreds } from './enroll.js';
12
+ export { fileFromBytes } from './files.js';
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=enroll.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enroll.test.d.ts","sourceRoot":"","sources":["../../test/enroll.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,75 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { WebSocketServer } from 'ws';
4
+ import { mkdtempSync, existsSync, readFileSync, rmSync } from 'node:fs';
5
+ import { tmpdir } from 'node:os';
6
+ import { join } from 'node:path';
7
+ import { enroll, loadOrEnrollCreds } from '../src/enroll.js';
8
+ const PORT = 8795;
9
+ /** Minimal relay stand-in: sends `hello`, answers `register` with `registered`
10
+ * (or `invalid_session` for invite "bad"). Counts how many registers it saw. */
11
+ function fakeRelay(port) {
12
+ let registers = 0;
13
+ const wss = new WebSocketServer({ port, host: '127.0.0.1' });
14
+ wss.on('connection', (ws) => {
15
+ ws.send(JSON.stringify({ op: 'hello', d: { protocolVersion: 1, heartbeatIntervalMs: 30000 } }));
16
+ ws.on('message', (data) => {
17
+ const frame = JSON.parse(data.toString());
18
+ if (frame.op !== 'register')
19
+ return;
20
+ registers++;
21
+ if (frame.d.invite === 'bad') {
22
+ ws.send(JSON.stringify({ op: 'invalid_session', d: { resumable: false, reason: 'invite unknown' } }));
23
+ return;
24
+ }
25
+ ws.send(JSON.stringify({
26
+ op: 'registered',
27
+ d: {
28
+ personaId: `minted-${registers}`,
29
+ token: `tok-${registers}`,
30
+ persona: { id: `minted-${registers}`, displayName: frame.d.desiredName, avatarUrl: '' },
31
+ },
32
+ }));
33
+ });
34
+ });
35
+ return {
36
+ url: `ws://127.0.0.1:${port}`,
37
+ registers: () => registers,
38
+ close: () => new Promise((r) => wss.close(() => r())),
39
+ };
40
+ }
41
+ test('enroll: returns minted creds; rejects bad invite', async () => {
42
+ const relay = fakeRelay(PORT);
43
+ try {
44
+ const creds = await enroll({ url: relay.url, invite: 'good', desiredName: 'Claude Code' });
45
+ assert.equal(creds.personaId, 'minted-1');
46
+ assert.equal(creds.token, 'tok-1');
47
+ await assert.rejects(() => enroll({ url: relay.url, invite: 'bad', desiredName: 'x' }), /invite unknown/);
48
+ }
49
+ finally {
50
+ await relay.close();
51
+ }
52
+ });
53
+ test('loadOrEnrollCreds: enrolls once then reuses the cached file', async () => {
54
+ const relay = fakeRelay(PORT + 1);
55
+ const dir = mkdtempSync(join(tmpdir(), 'portal-creds-'));
56
+ const credsPath = join(dir, 'nested', 'creds.json');
57
+ try {
58
+ const a = await loadOrEnrollCreds({ url: relay.url, credsPath, invite: 'good', desiredName: 'cc' });
59
+ assert.equal(relay.registers(), 1);
60
+ assert.ok(existsSync(credsPath));
61
+ // second call: no new register, returns the same persisted creds
62
+ const b = await loadOrEnrollCreds({ url: relay.url, credsPath, invite: 'good', desiredName: 'cc' });
63
+ assert.equal(relay.registers(), 1);
64
+ assert.deepEqual(a, b);
65
+ const onDisk = JSON.parse(readFileSync(credsPath, 'utf8'));
66
+ assert.equal(onDisk.personaId, a.personaId);
67
+ // without saved creds and without an invite → error
68
+ await assert.rejects(() => loadOrEnrollCreds({ url: relay.url, credsPath: join(dir, 'absent.json') }), /no saved credentials/);
69
+ }
70
+ finally {
71
+ rmSync(dir, { recursive: true, force: true });
72
+ await relay.close();
73
+ }
74
+ });
75
+ //# sourceMappingURL=enroll.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enroll.test.js","sourceRoot":"","sources":["../../test/enroll.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"fileNames":["../node_modules/typescript/lib/lib.es5.d.ts","../node_modules/typescript/lib/lib.es2015.d.ts","../node_modules/typescript/lib/lib.es2016.d.ts","../node_modules/typescript/lib/lib.es2017.d.ts","../node_modules/typescript/lib/lib.es2018.d.ts","../node_modules/typescript/lib/lib.es2019.d.ts","../node_modules/typescript/lib/lib.es2020.d.ts","../node_modules/typescript/lib/lib.es2021.d.ts","../node_modules/typescript/lib/lib.es2022.d.ts","../node_modules/typescript/lib/lib.es2015.core.d.ts","../node_modules/typescript/lib/lib.es2015.collection.d.ts","../node_modules/typescript/lib/lib.es2015.generator.d.ts","../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../node_modules/typescript/lib/lib.es2015.promise.d.ts","../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../node_modules/typescript/lib/lib.es2016.intl.d.ts","../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../node_modules/typescript/lib/lib.es2017.date.d.ts","../node_modules/typescript/lib/lib.es2017.object.d.ts","../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2017.string.d.ts","../node_modules/typescript/lib/lib.es2017.intl.d.ts","../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../node_modules/typescript/lib/lib.es2018.intl.d.ts","../node_modules/typescript/lib/lib.es2018.promise.d.ts","../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../node_modules/typescript/lib/lib.es2019.array.d.ts","../node_modules/typescript/lib/lib.es2019.object.d.ts","../node_modules/typescript/lib/lib.es2019.string.d.ts","../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../node_modules/typescript/lib/lib.es2019.intl.d.ts","../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../node_modules/typescript/lib/lib.es2020.date.d.ts","../node_modules/typescript/lib/lib.es2020.promise.d.ts","../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2020.string.d.ts","../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2020.intl.d.ts","../node_modules/typescript/lib/lib.es2020.number.d.ts","../node_modules/typescript/lib/lib.es2021.promise.d.ts","../node_modules/typescript/lib/lib.es2021.string.d.ts","../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../node_modules/typescript/lib/lib.es2021.intl.d.ts","../node_modules/typescript/lib/lib.es2022.array.d.ts","../node_modules/typescript/lib/lib.es2022.error.d.ts","../node_modules/typescript/lib/lib.es2022.intl.d.ts","../node_modules/typescript/lib/lib.es2022.object.d.ts","../node_modules/typescript/lib/lib.es2022.string.d.ts","../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../node_modules/typescript/lib/lib.decorators.d.ts","../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../portal-protocol/dist/src/version.d.ts","../../portal-protocol/dist/src/ids.d.ts","../../portal-protocol/dist/src/persona.d.ts","../../portal-protocol/dist/src/channel.d.ts","../../portal-protocol/dist/src/message.d.ts","../../portal-protocol/dist/src/members.d.ts","../../portal-protocol/dist/src/events.d.ts","../../portal-protocol/dist/src/rpc.d.ts","../../portal-protocol/dist/src/frames.d.ts","../../portal-protocol/dist/src/guards.d.ts","../../portal-protocol/dist/src/index.d.ts","../src/cache.ts","../node_modules/@types/node/compatibility/disposable.d.ts","../node_modules/@types/node/compatibility/indexable.d.ts","../node_modules/@types/node/compatibility/iterators.d.ts","../node_modules/@types/node/compatibility/index.d.ts","../node_modules/@types/node/globals.typedarray.d.ts","../node_modules/@types/node/buffer.buffer.d.ts","../node_modules/@types/node/globals.d.ts","../node_modules/@types/node/web-globals/abortcontroller.d.ts","../node_modules/@types/node/web-globals/domexception.d.ts","../node_modules/@types/node/web-globals/events.d.ts","../node_modules/undici-types/header.d.ts","../node_modules/undici-types/readable.d.ts","../node_modules/undici-types/file.d.ts","../node_modules/undici-types/fetch.d.ts","../node_modules/undici-types/formdata.d.ts","../node_modules/undici-types/connector.d.ts","../node_modules/undici-types/client.d.ts","../node_modules/undici-types/errors.d.ts","../node_modules/undici-types/dispatcher.d.ts","../node_modules/undici-types/global-dispatcher.d.ts","../node_modules/undici-types/global-origin.d.ts","../node_modules/undici-types/pool-stats.d.ts","../node_modules/undici-types/pool.d.ts","../node_modules/undici-types/handlers.d.ts","../node_modules/undici-types/balanced-pool.d.ts","../node_modules/undici-types/agent.d.ts","../node_modules/undici-types/mock-interceptor.d.ts","../node_modules/undici-types/mock-agent.d.ts","../node_modules/undici-types/mock-client.d.ts","../node_modules/undici-types/mock-pool.d.ts","../node_modules/undici-types/mock-errors.d.ts","../node_modules/undici-types/proxy-agent.d.ts","../node_modules/undici-types/env-http-proxy-agent.d.ts","../node_modules/undici-types/retry-handler.d.ts","../node_modules/undici-types/retry-agent.d.ts","../node_modules/undici-types/api.d.ts","../node_modules/undici-types/interceptors.d.ts","../node_modules/undici-types/util.d.ts","../node_modules/undici-types/cookies.d.ts","../node_modules/undici-types/patch.d.ts","../node_modules/undici-types/websocket.d.ts","../node_modules/undici-types/eventsource.d.ts","../node_modules/undici-types/filereader.d.ts","../node_modules/undici-types/diagnostics-channel.d.ts","../node_modules/undici-types/content-type.d.ts","../node_modules/undici-types/cache.d.ts","../node_modules/undici-types/index.d.ts","../node_modules/@types/node/web-globals/fetch.d.ts","../node_modules/@types/node/assert.d.ts","../node_modules/@types/node/assert/strict.d.ts","../node_modules/@types/node/async_hooks.d.ts","../node_modules/@types/node/buffer.d.ts","../node_modules/@types/node/child_process.d.ts","../node_modules/@types/node/cluster.d.ts","../node_modules/@types/node/console.d.ts","../node_modules/@types/node/constants.d.ts","../node_modules/@types/node/crypto.d.ts","../node_modules/@types/node/dgram.d.ts","../node_modules/@types/node/diagnostics_channel.d.ts","../node_modules/@types/node/dns.d.ts","../node_modules/@types/node/dns/promises.d.ts","../node_modules/@types/node/domain.d.ts","../node_modules/@types/node/events.d.ts","../node_modules/@types/node/fs.d.ts","../node_modules/@types/node/fs/promises.d.ts","../node_modules/@types/node/http.d.ts","../node_modules/@types/node/http2.d.ts","../node_modules/@types/node/https.d.ts","../node_modules/@types/node/inspector.generated.d.ts","../node_modules/@types/node/module.d.ts","../node_modules/@types/node/net.d.ts","../node_modules/@types/node/os.d.ts","../node_modules/@types/node/path.d.ts","../node_modules/@types/node/perf_hooks.d.ts","../node_modules/@types/node/process.d.ts","../node_modules/@types/node/punycode.d.ts","../node_modules/@types/node/querystring.d.ts","../node_modules/@types/node/readline.d.ts","../node_modules/@types/node/readline/promises.d.ts","../node_modules/@types/node/repl.d.ts","../node_modules/@types/node/sea.d.ts","../node_modules/@types/node/stream.d.ts","../node_modules/@types/node/stream/promises.d.ts","../node_modules/@types/node/stream/consumers.d.ts","../node_modules/@types/node/stream/web.d.ts","../node_modules/@types/node/string_decoder.d.ts","../node_modules/@types/node/test.d.ts","../node_modules/@types/node/timers.d.ts","../node_modules/@types/node/timers/promises.d.ts","../node_modules/@types/node/tls.d.ts","../node_modules/@types/node/trace_events.d.ts","../node_modules/@types/node/tty.d.ts","../node_modules/@types/node/url.d.ts","../node_modules/@types/node/util.d.ts","../node_modules/@types/node/v8.d.ts","../node_modules/@types/node/vm.d.ts","../node_modules/@types/node/wasi.d.ts","../node_modules/@types/node/worker_threads.d.ts","../node_modules/@types/node/zlib.d.ts","../node_modules/@types/node/index.d.ts","../node_modules/@types/ws/index.d.mts","../src/emitter.ts","../src/client.ts","../src/enroll.ts","../src/files.ts","../src/index.ts","../test/enroll.test.ts","../node_modules/@types/ws/index.d.ts"],"fileIdsList":[[75,118,121],[75,120,121],[121],[75,121,126,154],[75,121,122,127,132,140,151,162],[75,121,122,123,132,140],[75,121],[70,71,72,75,121],[75,121,124,163],[75,121,125,126,133,141],[75,121,126,151,159],[75,121,127,129,132,140],[75,120,121,128],[75,121,129,130],[75,121,131,132],[75,120,121,132],[75,121,132,133,134,151,162],[75,121,132,133,134,147,151,154],[75,121,129,132,135,140,151,162],[75,121,132,133,135,136,140,151,159,162],[75,121,135,137,151,159,162],[73,74,75,76,77,78,79,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168],[75,121,132,138],[75,121,139,162,167],[75,121,129,132,140,151],[75,121,141],[75,121,142],[75,120,121,143],[75,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168],[75,121,145],[75,121,146],[75,121,132,147,148],[75,121,147,149,163,165],[75,121,132,151,152,154],[75,121,153,154],[75,121,151,152],[75,121,154],[75,121,155],[75,118,121,151,156],[75,121,132,157,158],[75,121,157,158],[75,121,126,140,151,159],[75,121,160],[75,121,140,161],[75,121,135,146,162],[75,121,126,163],[75,121,151,164],[75,121,139,165],[75,121,166],[75,116,121],[75,116,121,132,134,143,151,154,162,165,167],[75,121,151,168],[75,121,132,135,137,140,151,159,162,168,169],[75,88,92,121,162],[75,88,121,151,162],[75,83,121],[75,85,88,121,159,162],[75,121,140,159],[75,121,169],[75,83,121,169],[75,85,88,121,140,162],[75,80,81,84,87,121,132,151,162],[75,88,95,121],[75,80,86,121],[75,88,109,110,121],[75,84,88,121,154,162,169],[75,109,121,169],[75,82,83,121,169],[75,88,121],[75,82,83,84,85,86,87,88,89,90,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,110,111,112,113,114,115,121],[75,88,103,121],[75,88,95,96,121],[75,86,88,96,97,121],[75,87,121],[75,80,83,88,121],[75,88,92,96,97,121],[75,92,121],[75,86,88,91,121,162],[75,80,85,88,95,121],[75,121,151],[75,83,88,109,121,167,169],[68,75,121],[68,69,75,121,126,170,171],[68,75,121,133,142,170],[69,75,121,171,172,173,174],[75,119,121,133,141,142,156,170,173],[59,75,121],[59,60,61,62,75,121],[58,59,60,61,64,65,75,121],[59,64,65,66,75,121],[58,59,60,61,62,63,64,65,66,67,75,121],[59,61,62,63,75,121]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"8cdf8847677ac7d20486e54dd3fcf09eda95812ac8ace44b4418da1bbbab6eb8","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"883e357cb209919c0e20d34677f0deda2eeb8ba12c7fd8ae0fa42b0910864bae","impliedFormat":99},{"version":"435e1a15cf0ac4d15f500f2174e3830d9bc7edbb1d2fa11bcadfb3f3a4186b91","impliedFormat":99},{"version":"0952fa52b26f5d4996c796c6774bf6afdd85db3e50641b473245f27af1a5c5dd","impliedFormat":99},{"version":"6a16560639eb98f9f2cb913f4ab41f28d981a0713d130ad5f741d71f02242c6a","impliedFormat":99},{"version":"005f7e311cc3dd252699ede82a80bd794fc7f4499b1ea6298158d994d4b9ccf3","impliedFormat":99},{"version":"eff94c3b1a920b7fa97e8cfe8a9ddf89f962905128522f9f359fc093604315bc","impliedFormat":99},{"version":"80055ae5fe3d3176fec0fe87196545799440efd26b932f8bb80da16bd2398aab","impliedFormat":99},{"version":"f526a9140547a1c3851846ff3f8cb17285208b920cca0608d47242957b9ba882","impliedFormat":99},{"version":"9cab1da85553c2806ab5784d29f6a097e3dc40b58650e142cb8ee1ff99c475be","impliedFormat":99},{"version":"abe8d15f5c76d4b50ae18db579148562538424b857ebbce7988c30df9991e3db","impliedFormat":99},{"version":"160c18798ef047992ba50e02bcb6f05ca2a46967e6cd1fde7bfbf18f5fa03b73","impliedFormat":99},{"version":"53397aaa0627c48fe37323e0e763c3162c59153c01a83ff82c7cdbb9881c3b1c","signature":"cd0b17a3a263140e1335d75f31d8749592e19e3e2331b10f664e6fc5a8f76f91","impliedFormat":99},{"version":"70521b6ab0dcba37539e5303104f29b721bfb2940b2776da4cc818c07e1fefc1","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"98cffbf06d6bab333473c70a893770dbe990783904002c4f1a960447b4b53dca","affectsGlobalScope":true,"impliedFormat":1},{"version":"ba481bca06f37d3f2c137ce343c7d5937029b2468f8e26111f3c9d9963d6568d","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d9ef24f9a22a88e3e9b3b3d8c40ab1ddb0853f1bfbd5c843c37800138437b61","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"b52476feb4a0cbcb25e5931b930fc73cb6643fb1a5060bf8a3dda0eeae5b4b68","affectsGlobalScope":true,"impliedFormat":1},{"version":"e2677634fe27e87348825bb041651e22d50a613e2fdf6a4a3ade971d71bac37e","impliedFormat":1},{"version":"7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","impliedFormat":1},{"version":"8c0bcd6c6b67b4b503c11e91a1fb91522ed585900eab2ab1f61bba7d7caa9d6f","impliedFormat":1},{"version":"8cd19276b6590b3ebbeeb030ac271871b9ed0afc3074ac88a94ed2449174b776","affectsGlobalScope":true,"impliedFormat":1},{"version":"696eb8d28f5949b87d894b26dc97318ef944c794a9a4e4f62360cd1d1958014b","impliedFormat":1},{"version":"3f8fa3061bd7402970b399300880d55257953ee6d3cd408722cb9ac20126460c","impliedFormat":1},{"version":"35ec8b6760fd7138bbf5809b84551e31028fb2ba7b6dc91d95d098bf212ca8b4","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"68bd56c92c2bd7d2339457eb84d63e7de3bd56a69b25f3576e1568d21a162398","affectsGlobalScope":true,"impliedFormat":1},{"version":"3e93b123f7c2944969d291b35fed2af79a6e9e27fdd5faa99748a51c07c02d28","impliedFormat":1},{"version":"9d19808c8c291a9010a6c788e8532a2da70f811adb431c97520803e0ec649991","impliedFormat":1},{"version":"87aad3dd9752067dc875cfaa466fc44246451c0c560b820796bdd528e29bef40","impliedFormat":1},{"version":"4aacb0dd020eeaef65426153686cc639a78ec2885dc72ad220be1d25f1a439df","impliedFormat":1},{"version":"f0bd7e6d931657b59605c44112eaf8b980ba7f957a5051ed21cb93d978cf2f45","impliedFormat":1},{"version":"8db0ae9cb14d9955b14c214f34dae1b9ef2baee2fe4ce794a4cd3ac2531e3255","affectsGlobalScope":true,"impliedFormat":1},{"version":"15fc6f7512c86810273af28f224251a5a879e4261b4d4c7e532abfbfc3983134","impliedFormat":1},{"version":"58adba1a8ab2d10b54dc1dced4e41f4e7c9772cbbac40939c0dc8ce2cdb1d442","impliedFormat":1},{"version":"641942a78f9063caa5d6b777c99304b7d1dc7328076038c6d94d8a0b81fc95c1","impliedFormat":1},{"version":"1123a83f35cf56c97de746f0a7250012153c61a167e4a61668bf50e558162d14","impliedFormat":1},{"version":"855cd5f7eb396f5f1ab1bc0f8580339bff77b68a770f84c6b254e319bbfd1ac7","impliedFormat":1},{"version":"5650cf3dace09e7c25d384e3e6b818b938f68f4e8de96f52d9c5a1b3db068e86","impliedFormat":1},{"version":"1354ca5c38bd3fd3836a68e0f7c9f91f172582ba30ab15bb8c075891b91502b7","affectsGlobalScope":true,"impliedFormat":1},{"version":"7e20d899c28ca26a2a7afc98beaa69e63ff7fba0a8bc47b4e3bf3ede5e09e424","impliedFormat":1},{"version":"2d2fcaab481b31a5882065c7951255703ddbe1c0e507af56ea42d79ac3911201","impliedFormat":1},{"version":"a192fe8ec33f75edbc8d8f3ed79f768dfae11ff5735e7fe52bfa69956e46d78d","impliedFormat":1},{"version":"ca867399f7db82df981d6915bcbb2d81131d7d1ef683bc782b59f71dda59bc85","affectsGlobalScope":true,"impliedFormat":1},{"version":"372413016d17d804e1d139418aca0c68e47a83fb6669490857f4b318de8cccb3","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e043a1bc8fbf2a255bccf9bf27e0f1caf916c3b0518ea34aa72357c0afd42ec","impliedFormat":1},{"version":"b4f70ec656a11d570e1a9edce07d118cd58d9760239e2ece99306ee9dfe61d02","impliedFormat":1},{"version":"3bc2f1e2c95c04048212c569ed38e338873f6a8593930cf5a7ef24ffb38fc3b6","impliedFormat":1},{"version":"6e70e9570e98aae2b825b533aa6292b6abd542e8d9f6e9475e88e1d7ba17c866","impliedFormat":1},{"version":"f9d9d753d430ed050dc1bf2667a1bab711ccbb1c1507183d794cc195a5b085cc","impliedFormat":1},{"version":"9eece5e586312581ccd106d4853e861aaaa1a39f8e3ea672b8c3847eedd12f6e","impliedFormat":1},{"version":"085f552d005479e2e6a7311cdbbe5d8c55c497b4d19274285df161ee9684cd9c","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"007faacc9268357caa21d24169f3f3f2497af3e9241308df2d89f6e6d9bb3f2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"74cf591a0f63db318651e0e04cb55f8791385f86e987a67fd4d2eaab8191f730","impliedFormat":1},{"version":"5eab9b3dc9b34f185417342436ec3f106898da5f4801992d8ff38ab3aff346b5","impliedFormat":1},{"version":"12ed4559eba17cd977aa0db658d25c4047067444b51acfdcbf38470630642b23","affectsGlobalScope":true,"impliedFormat":1},{"version":"f3ffabc95802521e1e4bcba4c88d8615176dc6e09111d920c7a213bdda6e1d65","impliedFormat":1},{"version":"809821b8a065e3234a55b3a9d7846231ed18d66dd749f2494c66288d890daf7f","impliedFormat":1},{"version":"ae56f65caf3be91108707bd8dfbccc2a57a91feb5daabf7165a06a945545ed26","impliedFormat":1},{"version":"a136d5de521da20f31631a0a96bf712370779d1c05b7015d7019a9b2a0446ca9","impliedFormat":1},{"version":"c3b41e74b9a84b88b1dca61ec39eee25c0dbc8e7d519ba11bb070918cfacf656","affectsGlobalScope":true,"impliedFormat":1},{"version":"4737a9dc24d0e68b734e6cfbcea0c15a2cfafeb493485e27905f7856988c6b29","affectsGlobalScope":true,"impliedFormat":1},{"version":"36d8d3e7506b631c9582c251a2c0b8a28855af3f76719b12b534c6edf952748d","impliedFormat":1},{"version":"1ca69210cc42729e7ca97d3a9ad48f2e9cb0042bada4075b588ae5387debd318","impliedFormat":1},{"version":"f5ebe66baaf7c552cfa59d75f2bfba679f329204847db3cec385acda245e574e","impliedFormat":1},{"version":"ed59add13139f84da271cafd32e2171876b0a0af2f798d0c663e8eeb867732cf","affectsGlobalScope":true,"impliedFormat":1},{"version":"b7c5e2ea4a9749097c347454805e933844ed207b6eefec6b7cfd418b5f5f7b28","impliedFormat":1},{"version":"b1810689b76fd473bd12cc9ee219f8e62f54a7d08019a235d07424afbf074d25","impliedFormat":1},{"version":"316f1486e15cbf7896425f0a16dfe12d447dd57cfb3244b8b119c77df870858f","impliedFormat":99},{"version":"673062ba46dbcc11204daef95f914a4223c48d2a1334d5c7f53a54154d298816","signature":"034715a35a88aa11cdc6be599286e2fcce847dcd223a75a8ac24c4a194826f5c","impliedFormat":99},{"version":"5a12c87777c2ad3de9f0759c92ce5b3b18af2cfc278337b56db5efec95b9f046","signature":"4991236277793ed51f44f2a14534d9c9b9f6e60cb89a31d5b7f32986e9730faf","impliedFormat":99},{"version":"d233e47b9b072c01097c790cb78272271c24b15c8d20c4d800f616b010d959d9","signature":"4009dcf376db8e84976fa75ecebf3061e2674ece0b0b861e05071f7db0c6f3f4","impliedFormat":99},{"version":"e822003de8cd74d5b345a72fc9d722277cefd1927f85ebdbf2f954f224d808b7","signature":"6b380ad1a0c4d73ce004b96871d34d0a9607ebac0daccda3c8c591d9cee25435","impliedFormat":99},{"version":"2bc63c2ed61daa67907ee06748bc0f36f51ba24ad33ef162ccb03fdacdadf5e7","impliedFormat":99},{"version":"a3d3c09047b82886e9fe8c0430d33bf49ee024f886ee7e3fe159dd0ae8d6a264","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","impliedFormat":99},{"version":"1ba59c8bbeed2cb75b239bb12041582fa3e8ef32f8d0bd0ec802e38442d3f317","impliedFormat":1}],"root":[69,[171,176]],"options":{"composite":true,"declaration":true,"declarationMap":true,"esModuleInterop":true,"module":199,"outDir":"./","rootDir":"..","skipLibCheck":true,"sourceMap":true,"strict":true,"target":9},"referencedMap":[[118,1],[119,1],[120,2],[75,3],[121,4],[122,5],[123,6],[70,7],[73,8],[71,7],[72,7],[124,9],[125,10],[126,11],[127,12],[128,13],[129,14],[130,14],[131,15],[132,16],[133,17],[134,18],[76,7],[74,7],[135,19],[136,20],[137,21],[169,22],[138,23],[139,24],[140,25],[141,26],[142,27],[143,28],[144,29],[145,30],[146,31],[147,32],[148,32],[149,33],[150,7],[151,34],[153,35],[152,36],[154,37],[155,38],[156,39],[157,40],[158,41],[159,42],[160,43],[161,44],[162,45],[163,46],[164,47],[165,48],[166,49],[77,7],[78,7],[79,7],[117,50],[167,51],[168,52],[170,53],[177,53],[56,7],[57,7],[11,7],[10,7],[2,7],[12,7],[13,7],[14,7],[15,7],[16,7],[17,7],[18,7],[19,7],[3,7],[20,7],[21,7],[4,7],[22,7],[26,7],[23,7],[24,7],[25,7],[27,7],[28,7],[29,7],[5,7],[30,7],[31,7],[32,7],[33,7],[6,7],[37,7],[34,7],[35,7],[36,7],[38,7],[7,7],[39,7],[44,7],[45,7],[40,7],[41,7],[42,7],[43,7],[8,7],[49,7],[46,7],[47,7],[48,7],[50,7],[9,7],[51,7],[52,7],[53,7],[55,7],[54,7],[1,7],[95,54],[105,55],[94,54],[115,56],[86,57],[85,58],[114,59],[108,60],[113,61],[88,62],[102,63],[87,64],[111,65],[83,66],[82,59],[112,67],[84,68],[89,69],[90,7],[93,69],[80,7],[116,70],[106,71],[97,72],[98,73],[100,74],[96,75],[99,76],[109,59],[91,77],[92,78],[101,79],[81,80],[104,71],[103,69],[107,7],[110,81],[69,82],[172,83],[171,7],[173,84],[174,82],[175,85],[176,86],[61,87],[64,88],[66,89],[67,90],[59,7],[68,91],[63,87],[62,87],[60,87],[65,92],[58,7]],"latestChangedDtsFile":"./src/files.d.ts","version":"5.9.3"}
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@animalabs/portal-client",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/src/index.js",
6
+ "types": "./dist/src/index.d.ts",
7
+ "description": "General-purpose portal client: WS transport, client-side cache, typed RPC, reconnect/resume.",
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "typecheck": "tsc --noEmit",
11
+ "test": "node --import tsx --test test/*.test.ts",
12
+ "clean": "rm -rf dist"
13
+ },
14
+ "dependencies": {
15
+ "@animalabs/portal-protocol": "^0.1.0",
16
+ "ws": "^8.18.0"
17
+ },
18
+ "devDependencies": {
19
+ "tsx": "^4.7.0",
20
+ "typescript": "^5.5.0",
21
+ "@types/node": "^20.0.0",
22
+ "@types/ws": "^8.5.0"
23
+ },
24
+ "engines": {
25
+ "node": ">=20.0.0"
26
+ }
27
+ }
package/src/cache.ts ADDED
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Client-side cache, hydrated from `ready` and kept fresh by dispatch events.
3
+ * Provides synchronous getters so callers (and the MCPL layer) can resolve
4
+ * names/ids and capabilities without a round-trip.
5
+ */
6
+ import type {
7
+ PortalChannel,
8
+ PortalEvent,
9
+ PortalGuild,
10
+ Persona,
11
+ ReadyData,
12
+ } from '@animalabs/portal-protocol';
13
+
14
+ export class ClientCache {
15
+ persona?: Persona;
16
+ private guilds = new Map<string, PortalGuild>();
17
+ private channels = new Map<string, PortalChannel>();
18
+
19
+ hydrate(ready: ReadyData): void {
20
+ this.persona = ready.persona;
21
+ this.guilds.clear();
22
+ this.channels.clear();
23
+ for (const g of ready.guilds) this.guilds.set(g.id, g);
24
+ for (const c of ready.channels) this.channels.set(c.id, c);
25
+ }
26
+
27
+ /** Apply structural events; returns true if the cache changed. */
28
+ apply(event: PortalEvent): boolean {
29
+ switch (event.type) {
30
+ case 'channel_create':
31
+ case 'channel_update':
32
+ case 'thread_create':
33
+ case 'thread_update':
34
+ this.channels.set(event.channel.id, event.channel);
35
+ return true;
36
+ case 'channel_delete':
37
+ return this.channels.delete(event.channelId);
38
+ case 'thread_delete':
39
+ return this.channels.delete(event.channelId);
40
+ case 'guild_create':
41
+ this.guilds.set(event.guild.id, event.guild);
42
+ for (const c of event.channels) this.channels.set(c.id, c);
43
+ return true;
44
+ case 'guild_delete':
45
+ return this.guilds.delete(event.guildId);
46
+ case 'persona_update':
47
+ this.persona = event.persona;
48
+ return true;
49
+ case 'capabilities_update': {
50
+ const ch = this.channels.get(event.channelId);
51
+ if (ch) {
52
+ this.channels.set(event.channelId, { ...ch, capabilities: event.capabilities });
53
+ return true;
54
+ }
55
+ return false;
56
+ }
57
+ default:
58
+ return false;
59
+ }
60
+ }
61
+
62
+ getGuild(id: string): PortalGuild | undefined {
63
+ return this.guilds.get(id);
64
+ }
65
+ getChannel(id: string): PortalChannel | undefined {
66
+ return this.channels.get(id);
67
+ }
68
+ allGuilds(): PortalGuild[] {
69
+ return [...this.guilds.values()];
70
+ }
71
+ allChannels(): PortalChannel[] {
72
+ return [...this.channels.values()];
73
+ }
74
+ /** Threads + channels under a parent. */
75
+ childrenOf(parentId: string): PortalChannel[] {
76
+ return [...this.channels.values()].filter((c) => c.parentId === parentId);
77
+ }
78
+ findChannelByName(name: string, guildId?: string): PortalChannel | undefined {
79
+ return [...this.channels.values()].find(
80
+ (c) => c.name === name && (!guildId || c.guildId === guildId),
81
+ );
82
+ }
83
+ }
package/src/client.ts ADDED
@@ -0,0 +1,281 @@
1
+ /**
2
+ * PortalClient — WS transport + cache + typed RPC + reconnect/resume.
3
+ *
4
+ * Lifecycle: connect → hello → identify → ready. On an unexpected close it
5
+ * reconnects and `resume`s from the last seq; a non-resumable rejection falls
6
+ * back to a fresh identify. The agent-facing read watermark is NOT here — that
7
+ * lives in portal-mcpl; this layer only does transport-level resume.
8
+ */
9
+ import { WebSocket } from 'ws';
10
+ import { randomUUID } from 'node:crypto';
11
+ import {
12
+ PORTAL_PROTOCOL_VERSION,
13
+ isServerFrame,
14
+ type AddressReason,
15
+ type PortalChannel,
16
+ type PortalEvent,
17
+ type PortalMessage,
18
+ type ReadyData,
19
+ type RpcMethod,
20
+ type RpcParams,
21
+ type RpcResult,
22
+ type ServerFrame,
23
+ } from '@animalabs/portal-protocol';
24
+ import { ClientCache } from './cache.js';
25
+ import { TypedEmitter } from './emitter.js';
26
+
27
+ export interface PortalClientOptions {
28
+ url: string;
29
+ token: string;
30
+ personaId: string;
31
+ /** Ambient channel subscriptions to request on connect. */
32
+ subscriptions?: string[];
33
+ /** RPC timeout in ms (default 15000). */
34
+ rpcTimeoutMs?: number;
35
+ /** Max reconnect backoff in ms (default 30000). */
36
+ maxBackoffMs?: number;
37
+ /** Provide a WebSocket impl (tests). Defaults to ws. */
38
+ wsFactory?: (url: string) => WebSocket;
39
+ }
40
+
41
+ type MessageEvent = { message: PortalMessage; addressedToMe: boolean; reasons: AddressReason[] };
42
+
43
+ export interface PortalClientEvents extends Record<string, (...args: never[]) => void> {
44
+ ready: (data: ReadyData) => void;
45
+ resumed: (replayed: number) => void;
46
+ message: (e: MessageEvent) => void;
47
+ messageUpdate: (e: MessageEvent) => void;
48
+ messageDelete: (e: { channelId: string; threadId?: string; messageId: string }) => void;
49
+ /** Any dispatch event, after the cache has been updated. */
50
+ event: (e: PortalEvent) => void;
51
+ channelChange: (channel: PortalChannel) => void;
52
+ close: (info: { code: number; willReconnect: boolean }) => void;
53
+ error: (err: Error) => void;
54
+ }
55
+
56
+ interface Pending {
57
+ resolve: (v: unknown) => void;
58
+ reject: (e: Error) => void;
59
+ timer: ReturnType<typeof setTimeout>;
60
+ }
61
+
62
+ export class PortalClient extends TypedEmitter<PortalClientEvents> {
63
+ readonly cache = new ClientCache();
64
+ private ws?: WebSocket;
65
+ private opts: Required<Omit<PortalClientOptions, 'subscriptions' | 'wsFactory'>> &
66
+ Pick<PortalClientOptions, 'subscriptions' | 'wsFactory'>;
67
+ private pending = new Map<string, Pending>();
68
+ private sessionId?: string;
69
+ private lastSeq = 0;
70
+ private heartbeat?: ReturnType<typeof setInterval>;
71
+ private backoff = 1000;
72
+ private closedByUser = false;
73
+ private ready = false;
74
+
75
+ constructor(options: PortalClientOptions) {
76
+ super();
77
+ this.opts = {
78
+ url: options.url,
79
+ token: options.token,
80
+ personaId: options.personaId,
81
+ rpcTimeoutMs: options.rpcTimeoutMs ?? 15_000,
82
+ maxBackoffMs: options.maxBackoffMs ?? 30_000,
83
+ // Kept as a mutable set so subscribe/unsubscribe stay durable across
84
+ // reconnects (identify replays this list).
85
+ subscriptions: options.subscriptions ? [...options.subscriptions] : [],
86
+ wsFactory: options.wsFactory,
87
+ };
88
+ }
89
+
90
+ /** Connect and resolve once `ready` (or `resumed`) is received. */
91
+ connect(): Promise<ReadyData> {
92
+ this.closedByUser = false;
93
+ return new Promise<ReadyData>((resolve, reject) => {
94
+ const onReady = this.on('ready', (d) => {
95
+ onReady();
96
+ onErr();
97
+ resolve(d);
98
+ });
99
+ const onErr = this.on('error', (e) => {
100
+ if (!this.ready) {
101
+ onReady();
102
+ onErr();
103
+ reject(e);
104
+ }
105
+ });
106
+ this.open();
107
+ });
108
+ }
109
+
110
+ close(): void {
111
+ this.closedByUser = true;
112
+ if (this.heartbeat) clearInterval(this.heartbeat);
113
+ this.ws?.close(1000, 'client closing');
114
+ }
115
+
116
+ /** Typed RPC call. */
117
+ call<M extends RpcMethod>(method: M, params: RpcParams<M>): Promise<RpcResult<M>> {
118
+ const id = `rpc_${randomUUID()}`;
119
+ return new Promise<RpcResult<M>>((resolve, reject) => {
120
+ const timer = setTimeout(() => {
121
+ this.pending.delete(id);
122
+ reject(new Error(`RPC ${method} timed out`));
123
+ }, this.opts.rpcTimeoutMs);
124
+ this.pending.set(id, { resolve: resolve as (v: unknown) => void, reject, timer });
125
+ this.sendFrame({ op: 'rpc', d: { id, method, params } });
126
+ });
127
+ }
128
+
129
+ // Convenience wrappers
130
+ sendMessage(params: RpcParams<'send_message'>) {
131
+ return this.call('send_message', params);
132
+ }
133
+ editMessage(messageId: string, content: string) {
134
+ return this.call('edit_message', { messageId, content });
135
+ }
136
+ deleteMessage(messageId: string) {
137
+ return this.call('delete_message', { messageId });
138
+ }
139
+ react(messageId: string, emoji: string, visible = false) {
140
+ return this.call('react', { messageId, emoji, visible });
141
+ }
142
+ fetchHistory(params: RpcParams<'fetch_history'>) {
143
+ return this.call('fetch_history', params);
144
+ }
145
+ subscribe(channelId: string) {
146
+ const subs = (this.opts.subscriptions ??= []);
147
+ if (!subs.includes(channelId)) subs.push(channelId);
148
+ return this.call('subscribe_channel', { channelId });
149
+ }
150
+ unsubscribe(channelId: string) {
151
+ this.opts.subscriptions = (this.opts.subscriptions ?? []).filter((c) => c !== channelId);
152
+ return this.call('unsubscribe_channel', { channelId });
153
+ }
154
+
155
+ // ── Internals ──
156
+
157
+ private open(): void {
158
+ const ws = this.opts.wsFactory ? this.opts.wsFactory(this.opts.url) : new WebSocket(this.opts.url);
159
+ this.ws = ws;
160
+ ws.on('message', (data: Buffer | string) => this.onMessage(data.toString()));
161
+ ws.on('close', (code: number) => this.onClose(code));
162
+ ws.on('error', (err: Error) => this.emit('error', err));
163
+ }
164
+
165
+ private onMessage(raw: string): void {
166
+ const parsed: unknown = safeParse(raw);
167
+ if (!isServerFrame(parsed)) return;
168
+ const frame = parsed as ServerFrame;
169
+ switch (frame.op) {
170
+ case 'hello':
171
+ this.startHeartbeat(frame.d.heartbeatIntervalMs);
172
+ if (this.sessionId && this.lastSeq >= 0) {
173
+ this.sendFrame({ op: 'resume', d: { sessionId: this.sessionId, seq: this.lastSeq } });
174
+ } else {
175
+ this.identify();
176
+ }
177
+ return;
178
+ case 'ready':
179
+ this.ready = true;
180
+ this.backoff = 1000;
181
+ this.sessionId = frame.d.sessionId;
182
+ this.lastSeq = frame.d.seq;
183
+ this.cache.hydrate(frame.d);
184
+ this.emit('ready', frame.d);
185
+ return;
186
+ case 'resumed':
187
+ this.ready = true;
188
+ this.backoff = 1000;
189
+ this.emit('resumed', frame.d.replayedEvents);
190
+ return;
191
+ case 'invalid_session':
192
+ // Can't resume — start fresh.
193
+ this.sessionId = undefined;
194
+ this.lastSeq = 0;
195
+ if (frame.d.resumable) {
196
+ /* relay said retry resume, but we lack state → identify */
197
+ }
198
+ this.identify();
199
+ return;
200
+ case 'heartbeat_ack':
201
+ return;
202
+ case 'dispatch':
203
+ this.lastSeq = frame.seq;
204
+ this.onEvent(frame.d);
205
+ return;
206
+ case 'rpc_result': {
207
+ const p = this.pending.get(frame.d.id);
208
+ if (!p) return;
209
+ this.pending.delete(frame.d.id);
210
+ clearTimeout(p.timer);
211
+ if (frame.d.ok) p.resolve(frame.d.result);
212
+ else p.reject(Object.assign(new Error(frame.d.error.message), { code: frame.d.error.code }));
213
+ return;
214
+ }
215
+ }
216
+ }
217
+
218
+ private onEvent(event: PortalEvent): void {
219
+ this.cache.apply(event);
220
+ this.emit('event', event);
221
+ switch (event.type) {
222
+ case 'message_create':
223
+ this.emit('message', { message: event.message, addressedToMe: event.addressedToMe, reasons: event.reasons });
224
+ break;
225
+ case 'message_update':
226
+ this.emit('messageUpdate', { message: event.message, addressedToMe: event.addressedToMe, reasons: event.reasons });
227
+ break;
228
+ case 'message_delete':
229
+ this.emit('messageDelete', { channelId: event.channelId, threadId: event.threadId, messageId: event.messageId });
230
+ break;
231
+ case 'channel_create':
232
+ case 'channel_update':
233
+ case 'thread_create':
234
+ case 'thread_update':
235
+ this.emit('channelChange', event.channel);
236
+ break;
237
+ }
238
+ }
239
+
240
+ private identify(): void {
241
+ this.sendFrame({
242
+ op: 'identify',
243
+ d: {
244
+ protocolVersion: PORTAL_PROTOCOL_VERSION,
245
+ token: this.opts.token,
246
+ personaId: this.opts.personaId,
247
+ subscriptions: this.opts.subscriptions,
248
+ },
249
+ });
250
+ }
251
+
252
+ private startHeartbeat(intervalMs: number): void {
253
+ if (this.heartbeat) clearInterval(this.heartbeat);
254
+ this.heartbeat = setInterval(() => this.sendFrame({ op: 'heartbeat', d: { seq: this.lastSeq } }), intervalMs);
255
+ }
256
+
257
+ private onClose(code: number): void {
258
+ if (this.heartbeat) clearInterval(this.heartbeat);
259
+ this.ready = false;
260
+ const willReconnect = !this.closedByUser;
261
+ this.emit('close', { code, willReconnect });
262
+ if (!willReconnect) return;
263
+ const delay = Math.min(this.backoff, this.opts.maxBackoffMs);
264
+ this.backoff = Math.min(this.backoff * 2, this.opts.maxBackoffMs);
265
+ setTimeout(() => this.open(), delay);
266
+ }
267
+
268
+ private sendFrame(frame: unknown): void {
269
+ if (this.ws && this.ws.readyState === this.ws.OPEN) {
270
+ this.ws.send(JSON.stringify(frame));
271
+ }
272
+ }
273
+ }
274
+
275
+ function safeParse(raw: string): unknown {
276
+ try {
277
+ return JSON.parse(raw);
278
+ } catch {
279
+ return null;
280
+ }
281
+ }