@antseed/cli 0.1.192 → 0.1.194

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 (137) hide show
  1. package/dist/cli/commands/buyer/start.d.ts.map +1 -1
  2. package/dist/cli/commands/buyer/start.js +9 -4
  3. package/dist/cli/commands/buyer/start.js.map +1 -1
  4. package/dist/cli/commands/gateway/index.d.ts.map +1 -1
  5. package/dist/cli/commands/gateway/index.js +6 -0
  6. package/dist/cli/commands/gateway/index.js.map +1 -1
  7. package/dist/cli/commands/gateway/settings.d.ts.map +1 -1
  8. package/dist/cli/commands/gateway/settings.js +14 -1
  9. package/dist/cli/commands/gateway/settings.js.map +1 -1
  10. package/dist/cli/commands/seller/start.d.ts.map +1 -1
  11. package/dist/cli/commands/seller/start.js +9 -0
  12. package/dist/cli/commands/seller/start.js.map +1 -1
  13. package/dist/cli/commands/tunnel/start.d.ts.map +1 -1
  14. package/dist/cli/commands/tunnel/start.js +8 -2
  15. package/dist/cli/commands/tunnel/start.js.map +1 -1
  16. package/dist/cli/commands/update.d.ts +19 -0
  17. package/dist/cli/commands/update.d.ts.map +1 -0
  18. package/dist/cli/commands/update.js +153 -0
  19. package/dist/cli/commands/update.js.map +1 -0
  20. package/dist/cli/index.js +11 -0
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/cli/program.d.ts.map +1 -1
  23. package/dist/cli/program.js +2 -0
  24. package/dist/cli/program.js.map +1 -1
  25. package/dist/gateway/buyer-process.d.ts +5 -0
  26. package/dist/gateway/buyer-process.d.ts.map +1 -1
  27. package/dist/gateway/buyer-process.js +7 -4
  28. package/dist/gateway/buyer-process.js.map +1 -1
  29. package/dist/gateway/buyer-process.test.js +28 -2
  30. package/dist/gateway/buyer-process.test.js.map +1 -1
  31. package/dist/gateway/console-api/deps.d.ts +3 -0
  32. package/dist/gateway/console-api/deps.d.ts.map +1 -1
  33. package/dist/gateway/console-api/handlers/index.d.ts.map +1 -1
  34. package/dist/gateway/console-api/handlers/index.js +2 -0
  35. package/dist/gateway/console-api/handlers/index.js.map +1 -1
  36. package/dist/gateway/console-api/handlers/network-mapping.d.ts +6 -0
  37. package/dist/gateway/console-api/handlers/network-mapping.d.ts.map +1 -1
  38. package/dist/gateway/console-api/handlers/network-mapping.js +18 -7
  39. package/dist/gateway/console-api/handlers/network-mapping.js.map +1 -1
  40. package/dist/gateway/console-api/handlers/network.test.js +16 -1
  41. package/dist/gateway/console-api/handlers/network.test.js.map +1 -1
  42. package/dist/gateway/console-api/handlers/staking.d.ts +28 -0
  43. package/dist/gateway/console-api/handlers/staking.d.ts.map +1 -0
  44. package/dist/gateway/console-api/handlers/staking.js +153 -0
  45. package/dist/gateway/console-api/handlers/staking.js.map +1 -0
  46. package/dist/gateway/console-api/handlers/staking.test.d.ts +2 -0
  47. package/dist/gateway/console-api/handlers/staking.test.d.ts.map +1 -0
  48. package/dist/gateway/console-api/handlers/staking.test.js +126 -0
  49. package/dist/gateway/console-api/handlers/staking.test.js.map +1 -0
  50. package/dist/gateway/console-api/handlers/update.d.ts +13 -0
  51. package/dist/gateway/console-api/handlers/update.d.ts.map +1 -0
  52. package/dist/gateway/console-api/handlers/update.js +65 -0
  53. package/dist/gateway/console-api/handlers/update.js.map +1 -0
  54. package/dist/gateway/console-api/router.d.ts +1 -1
  55. package/dist/gateway/console-api/router.d.ts.map +1 -1
  56. package/dist/gateway/console-api/router.js +8 -3
  57. package/dist/gateway/console-api/router.js.map +1 -1
  58. package/dist/gateway/console-api/types.d.ts +63 -0
  59. package/dist/gateway/console-api/types.d.ts.map +1 -1
  60. package/dist/gateway/console-api/types.js.map +1 -1
  61. package/dist/gateway/console-api/update.test.d.ts +2 -0
  62. package/dist/gateway/console-api/update.test.d.ts.map +1 -0
  63. package/dist/gateway/console-api/update.test.js +198 -0
  64. package/dist/gateway/console-api/update.test.js.map +1 -0
  65. package/dist/gateway/console.d.ts +3 -0
  66. package/dist/gateway/console.d.ts.map +1 -1
  67. package/dist/gateway/console.js +3 -0
  68. package/dist/gateway/console.js.map +1 -1
  69. package/dist/gateway/gateway-policy.test.js +66 -0
  70. package/dist/gateway/gateway-policy.test.js.map +1 -1
  71. package/dist/gateway/gateway.test.js +88 -0
  72. package/dist/gateway/gateway.test.js.map +1 -1
  73. package/dist/gateway/policy-resolver.test.js +11 -3
  74. package/dist/gateway/policy-resolver.test.js.map +1 -1
  75. package/dist/gateway/request-errors.test.js +147 -3
  76. package/dist/gateway/request-errors.test.js.map +1 -1
  77. package/dist/gateway/request-shaping.d.ts +4 -2
  78. package/dist/gateway/request-shaping.d.ts.map +1 -1
  79. package/dist/gateway/request-shaping.js +16 -10
  80. package/dist/gateway/request-shaping.js.map +1 -1
  81. package/dist/gateway/server.d.ts +6 -0
  82. package/dist/gateway/server.d.ts.map +1 -1
  83. package/dist/gateway/server.js +165 -66
  84. package/dist/gateway/server.js.map +1 -1
  85. package/dist/gateway/services/network.d.ts.map +1 -1
  86. package/dist/gateway/services/network.js +20 -1
  87. package/dist/gateway/services/network.js.map +1 -1
  88. package/dist/gateway/services/usage.d.ts.map +1 -1
  89. package/dist/gateway/services/usage.js +7 -0
  90. package/dist/gateway/services/usage.js.map +1 -1
  91. package/dist/gateway/store-data.test.js +1 -1
  92. package/dist/gateway/store-data.test.js.map +1 -1
  93. package/dist/gateway/store-migrations.d.ts.map +1 -1
  94. package/dist/gateway/store-migrations.js +7 -0
  95. package/dist/gateway/store-migrations.js.map +1 -1
  96. package/dist/gateway/store.d.ts +24 -1
  97. package/dist/gateway/store.d.ts.map +1 -1
  98. package/dist/gateway/store.js +29 -10
  99. package/dist/gateway/store.js.map +1 -1
  100. package/dist/gateway/updates.d.ts +34 -0
  101. package/dist/gateway/updates.d.ts.map +1 -0
  102. package/dist/gateway/updates.js +155 -0
  103. package/dist/gateway/updates.js.map +1 -0
  104. package/dist/proxy/buyer-proxy.d.ts +4 -0
  105. package/dist/proxy/buyer-proxy.d.ts.map +1 -1
  106. package/dist/proxy/buyer-proxy.js +9 -0
  107. package/dist/proxy/buyer-proxy.js.map +1 -1
  108. package/dist/proxy/router-execution.d.ts.map +1 -1
  109. package/dist/proxy/router-execution.js +14 -4
  110. package/dist/proxy/router-execution.js.map +1 -1
  111. package/dist/proxy/router-execution.test.js +35 -0
  112. package/dist/proxy/router-execution.test.js.map +1 -1
  113. package/dist/update/install-method.d.ts +25 -0
  114. package/dist/update/install-method.d.ts.map +1 -0
  115. package/dist/update/install-method.js +76 -0
  116. package/dist/update/install-method.js.map +1 -0
  117. package/dist/update/notifier.d.ts +30 -0
  118. package/dist/update/notifier.d.ts.map +1 -0
  119. package/dist/update/notifier.js +84 -0
  120. package/dist/update/notifier.js.map +1 -0
  121. package/dist/update/root-updater.d.ts +80 -0
  122. package/dist/update/root-updater.d.ts.map +1 -0
  123. package/dist/update/root-updater.js +104 -0
  124. package/dist/update/root-updater.js.map +1 -0
  125. package/dist/update/update.test.d.ts +2 -0
  126. package/dist/update/update.test.d.ts.map +1 -0
  127. package/dist/update/update.test.js +224 -0
  128. package/dist/update/update.test.js.map +1 -0
  129. package/dist/update/version.d.ts +29 -0
  130. package/dist/update/version.d.ts.map +1 -0
  131. package/dist/update/version.js +110 -0
  132. package/dist/update/version.js.map +1 -0
  133. package/dist/update/watch.d.ts +32 -0
  134. package/dist/update/watch.d.ts.map +1 -0
  135. package/dist/update/watch.js +59 -0
  136. package/dist/update/watch.js.map +1 -0
  137. package/package.json +9 -9
@@ -0,0 +1,153 @@
1
+ /**
2
+ * ANTS staking inside the console. The console renders the staking dashboard's
3
+ * own pages; this module serves the dashboard's API to them at
4
+ * `/console/api/workspaces/:id/ants/*`, behind the console's sign-in and roles.
5
+ *
6
+ * The dashboard API keeps per-session state (the connected wallet, the one
7
+ * pending wallet approval, the job journal), so each console session gets its
8
+ * own dashboard session per workspace, bound to the workspace's buyer account.
9
+ * Sessions close when idle. Every transaction is signed by the member's own
10
+ * wallet in the browser; the gateway never signs for staking.
11
+ */
12
+ import { createAntsServer, resolveAntsChain, AntsContext } from '@antseed/ants';
13
+ import { DEFAULT_BUYER_IDENTITY } from '@antseed/node';
14
+ import { ZeroAddress } from 'ethers';
15
+ import { errorMessage } from '../../errors.js';
16
+ import { audit, requireWorkspaceAccess } from '../access.js';
17
+ import { ConsoleError, respond } from '../router.js';
18
+ import { resolveIdentityAddress } from '../../services/wallet-address.js';
19
+ /** A session nobody has called for this long is closed (unless a transaction is still running). */
20
+ const IDLE_MS = 30 * 60_000;
21
+ /** More open sessions than this close the least recently used idle ones first. */
22
+ const MAX_SESSIONS = 64;
23
+ const SWEEP_MS = 60_000;
24
+ /** Dashboard actions that start a wallet transaction; recorded in the audit log. */
25
+ const ACTION_PATHS = new Set([
26
+ 'positions/stake', 'positions/move', 'positions/split', 'positions/merge', 'positions/extend', 'positions/max-lock', 'positions/withdraw',
27
+ 'rewards/claim', 'rewards/restake', 'rewards/stake-usage', 'rewards/compound',
28
+ 'verification/submit', 'seller/register', 'seller/claim-starter',
29
+ ]);
30
+ export function registerStakingRoutes(router, deps, overrides = {}) {
31
+ const access = overrides.requireWorkspaceAccess ?? requireWorkspaceAccess;
32
+ const createServer = overrides.createServer ?? createAntsServer;
33
+ const now = overrides.now ?? deps.now;
34
+ const addressBook = overrides.buyerAddresses ?? deps.buyerAddresses ?? null;
35
+ const sessions = new Map();
36
+ // Rank the chain's RPC endpoints once per process; every session reads in that order.
37
+ let ranked = null;
38
+ const chain = () => {
39
+ ranked ??= (async () => {
40
+ const resolved = await (overrides.resolveChain ?? (() => resolveAntsChain(deps.configPath)))();
41
+ const probe = new AntsContext({ chain: resolved, address: ZeroAddress });
42
+ await probe.selectRpc();
43
+ return probe.chain;
44
+ })();
45
+ ranked.catch(() => { ranked = null; });
46
+ return ranked;
47
+ };
48
+ const workspaceAddress = overrides.workspaceAddress ?? (async (buyerIdentity) => (await resolveIdentityAddress(deps.dataDir, addressBook, buyerIdentity).catch(() => null))?.address ?? null);
49
+ const close = (key, session) => {
50
+ sessions.delete(key);
51
+ void session.server.then((server) => server.close()).catch(() => { });
52
+ };
53
+ /** Close idle sessions, then the least recently used idle ones while over the cap. Busy sessions stay. */
54
+ const sweep = async () => {
55
+ const entries = [...sessions.entries()].sort((a, b) => a[1].lastUsed - b[1].lastUsed);
56
+ let open = entries.length;
57
+ for (const [key, session] of entries) {
58
+ const server = await session.server.catch(() => null);
59
+ if (!server) {
60
+ close(key, session);
61
+ open--;
62
+ continue;
63
+ }
64
+ if (server.busy)
65
+ continue;
66
+ if (now() - session.lastUsed > IDLE_MS || open > MAX_SESSIONS) {
67
+ close(key, session);
68
+ open--;
69
+ }
70
+ }
71
+ };
72
+ const timer = setInterval(() => { void sweep(); }, SWEEP_MS);
73
+ timer.unref?.();
74
+ const sessionFor = async (request) => {
75
+ const principal = request.principal;
76
+ if (principal?.kind !== 'member')
77
+ throw new ConsoleError(403, 'forbidden', 'Staking needs a signed-in member.');
78
+ const workspaceId = request.params['id'] ?? '';
79
+ // Staking reads the workspace's buyer rewards, which the Rewards page also limits to admins.
80
+ access(deps.store, principal, workspaceId, 'admin');
81
+ const workspace = deps.store.getWorkspace(workspaceId);
82
+ if (!workspace)
83
+ throw new ConsoleError(404, 'not_found', 'Workspace not found.');
84
+ const key = `${principal.sessionId}:${workspaceId}`;
85
+ let session = sessions.get(key);
86
+ if (!session) {
87
+ const buyerIdentity = workspace.buyerIdentity || DEFAULT_BUYER_IDENTITY;
88
+ const server = (async () => {
89
+ const address = await workspaceAddress(buyerIdentity);
90
+ if (!address)
91
+ throw new ConsoleError(409, 'wallet_unavailable', 'This workspace has no wallet address yet.');
92
+ return createServer({
93
+ port: 0,
94
+ browserWallet: true,
95
+ serveWeb: false,
96
+ selectRpc: false,
97
+ chain: await chain(),
98
+ address,
99
+ dataDir: deps.dataDir,
100
+ configPath: deps.configPath,
101
+ stateKey: `console-${principal.memberId}-${workspaceId}`,
102
+ });
103
+ })();
104
+ session = { server, lastUsed: now() };
105
+ sessions.set(key, session);
106
+ server.catch(() => { if (sessions.get(key) === session)
107
+ sessions.delete(key); });
108
+ if (sessions.size > MAX_SESSIONS)
109
+ void sweep();
110
+ }
111
+ session.lastUsed = now();
112
+ return session.server;
113
+ };
114
+ const forward = async (request) => {
115
+ const server = await sessionFor(request);
116
+ const rest = request.params['*'] ?? '';
117
+ const query = request.query.toString();
118
+ const response = await server.app.inject({
119
+ method: request.method === 'POST' ? 'POST' : 'GET',
120
+ url: `/api/${rest}${query ? `?${query}` : ''}`,
121
+ headers: { authorization: `Bearer ${server.token}`, ...(request.method === 'POST' ? { 'content-type': 'application/json' } : {}) },
122
+ ...(request.method === 'POST' ? { payload: JSON.stringify(request.body ?? {}) } : {}),
123
+ });
124
+ let body;
125
+ try {
126
+ body = response.json();
127
+ }
128
+ catch {
129
+ deps.log(`console staking: ${request.method} ${rest} answered ${response.statusCode} without JSON`);
130
+ throw new ConsoleError(502, 'staking_unavailable', 'The staking service did not answer.');
131
+ }
132
+ if (request.method === 'POST' && ACTION_PATHS.has(rest) && response.statusCode < 300) {
133
+ const job = body?.data;
134
+ audit(deps, request, `staking.${rest.replace('/', '.')}`, { kind: 'workspace', id: request.params['id'] ?? null, label: null }, { jobId: job?.id ?? null });
135
+ }
136
+ // The dashboard's own `{ ok, data | error | state }` envelope, unchanged.
137
+ return respond(response.statusCode, body);
138
+ };
139
+ const handle = async (request) => {
140
+ try {
141
+ return await forward(request);
142
+ }
143
+ catch (error) {
144
+ if (error instanceof ConsoleError)
145
+ throw error;
146
+ deps.log(`console staking: ${request.method} ${request.params['*'] ?? ''}: ${errorMessage(error)}`);
147
+ throw new ConsoleError(502, 'staking_unavailable', `Staking could not be loaded: ${errorMessage(error)}`);
148
+ }
149
+ };
150
+ router.add('GET', '/workspaces/:id/ants/*', handle, { allow: ['member'] });
151
+ router.add('POST', '/workspaces/:id/ants/*', handle, { allow: ['member'] });
152
+ }
153
+ //# sourceMappingURL=staking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staking.js","sourceRoot":"","sources":["../../../../src/gateway/console-api/handlers/staking.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=staking.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staking.test.d.ts","sourceRoot":"","sources":["../../../../src/gateway/console-api/handlers/staking.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,126 @@
1
+ import assert from 'node:assert/strict';
2
+ import { mkdtempSync, rmSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { test } from 'node:test';
6
+ import { createAntsServer } from '@antseed/ants';
7
+ import { ConsoleRouter } from '../router.js';
8
+ import { call, fakeDeps, fakeRequireWorkspaceAccess, memberPrincipal, rejectsWith } from './network-test-helpers.js';
9
+ import { registerStakingRoutes } from './staking.js';
10
+ // Obvious fakes only; no test reaches the chain.
11
+ const TEAM_WALLET = `0x${'0a'.repeat(20)}`;
12
+ const CHAIN = { chainId: 'base-local', evmChainId: 31337, rpcUrl: 'http://127.0.0.1:1' };
13
+ const owner = memberPrincipal('m_owner', {}, 'owner');
14
+ const ali = memberPrincipal('m_ali', { ws_team: 'admin' });
15
+ const sam = memberPrincipal('m_sam', { ws_team: 'member' });
16
+ function fixture(options = {}) {
17
+ const dataDir = mkdtempSync(join(tmpdir(), 'antseed-staking-'));
18
+ const audits = [];
19
+ const created = [];
20
+ let now = 1_700_000_000_000;
21
+ const store = {
22
+ getWorkspace: (id) => (id === 'ws_team' ? { id, buyerIdentity: 'team-a' } : null),
23
+ getMember: () => null,
24
+ getKey: () => null,
25
+ getAdminToken: () => null,
26
+ recordAudit: (entry) => { audits.push(entry); },
27
+ };
28
+ const router = new ConsoleRouter();
29
+ registerStakingRoutes(router, { ...fakeDeps(store, () => now), dataDir }, {
30
+ requireWorkspaceAccess: fakeRequireWorkspaceAccess,
31
+ resolveChain: async () => CHAIN,
32
+ workspaceAddress: async (identity) => (identity === 'team-a' && options.address !== null ? options.address ?? TEAM_WALLET : null),
33
+ createServer: (serverOptions) => {
34
+ created.push(serverOptions);
35
+ return createAntsServer(serverOptions);
36
+ },
37
+ });
38
+ return {
39
+ router,
40
+ audits,
41
+ created,
42
+ advance: (ms) => { now += ms; },
43
+ cleanup: () => rmSync(dataDir, { recursive: true, force: true }),
44
+ };
45
+ }
46
+ test('staking serves the dashboard API for the workspace buyer, unchanged', async () => {
47
+ const f = fixture();
48
+ try {
49
+ const config = await call(f.router, 'GET', '/workspaces/ws_team/ants/config', owner);
50
+ assert.equal(config.status, 200);
51
+ assert.equal(config.body.ok, true);
52
+ assert.equal(config.body.data['buyerAddress'], TEAM_WALLET);
53
+ assert.equal(config.body.data['browserWallet'], true);
54
+ assert.equal(config.body.data['readOnly'], true, 'no wallet is connected yet');
55
+ // The gateway's data directory stays on the gateway.
56
+ assert.equal(config.body.data['dataDir'], null);
57
+ const options = f.created[0];
58
+ assert.equal(options.serveWeb, false);
59
+ assert.equal(options.selectRpc, false);
60
+ assert.equal(options.stateKey, 'console-m_owner-ws_team');
61
+ }
62
+ finally {
63
+ f.cleanup();
64
+ }
65
+ });
66
+ test('staking keeps one dashboard session per console session and workspace', async () => {
67
+ const f = fixture();
68
+ try {
69
+ await call(f.router, 'GET', '/workspaces/ws_team/ants/config', owner);
70
+ await call(f.router, 'GET', '/workspaces/ws_team/ants/jobs', owner);
71
+ assert.equal(f.created.length, 1);
72
+ await call(f.router, 'GET', '/workspaces/ws_team/ants/config', ali);
73
+ assert.equal(f.created.length, 2, 'another member gets their own wallet session');
74
+ }
75
+ finally {
76
+ f.cleanup();
77
+ }
78
+ });
79
+ test('staking is for workspace admins, like the Rewards page', async () => {
80
+ const f = fixture();
81
+ try {
82
+ await rejectsWith(call(f.router, 'GET', '/workspaces/ws_team/ants/config', sam), 403);
83
+ await rejectsWith(call(f.router, 'GET', '/workspaces/ws_team/ants/config', { kind: 'token', tokenId: 't1', scope: 'admin' }), 403, 'forbidden');
84
+ await rejectsWith(call(f.router, 'GET', '/workspaces/ws_none/ants/config', owner), 404, 'not_found');
85
+ assert.equal(f.created.length, 0);
86
+ }
87
+ finally {
88
+ f.cleanup();
89
+ }
90
+ });
91
+ test('staking explains a workspace without a wallet, and retries on the next call', async () => {
92
+ const f = fixture({ address: null });
93
+ try {
94
+ await rejectsWith(call(f.router, 'GET', '/workspaces/ws_team/ants/config', owner), 409, 'wallet_unavailable');
95
+ await rejectsWith(call(f.router, 'GET', '/workspaces/ws_team/ants/config', owner), 409, 'wallet_unavailable');
96
+ }
97
+ finally {
98
+ f.cleanup();
99
+ }
100
+ });
101
+ test('staking passes dashboard errors through and audits only started actions', async () => {
102
+ const f = fixture();
103
+ try {
104
+ // No wallet connected: the dashboard refuses the action itself.
105
+ const refused = await call(f.router, 'POST', '/workspaces/ws_team/ants/positions/stake', owner, { agentId: 1, amount: '1' });
106
+ assert.equal(refused.status, 403);
107
+ assert.equal(refused.body.ok, false);
108
+ assert.match(refused.body.error, /read-only/);
109
+ // A wallet on another chain is rejected with the dashboard's message.
110
+ const wrongChain = await call(f.router, 'POST', '/workspaces/ws_team/ants/wallet', owner, { address: TEAM_WALLET, chainId: 1 });
111
+ assert.equal(wrongChain.status, 400);
112
+ assert.match(wrongChain.body.error, /Switch your wallet/);
113
+ assert.deepEqual(f.audits, []);
114
+ }
115
+ finally {
116
+ f.cleanup();
117
+ }
118
+ });
119
+ test('the console router matches a trailing wildcard on one or more segments', () => {
120
+ const router = new ConsoleRouter();
121
+ router.add('GET', '/workspaces/:id/ants/*', async () => null);
122
+ assert.deepEqual(router.match('GET', '/workspaces/ws_1/ants/verification/proofs/0xab')?.params, { id: 'ws_1', '*': 'verification/proofs/0xab' });
123
+ assert.equal(router.match('GET', '/workspaces/ws_1/ants'), null);
124
+ assert.equal(router.match('GET', '/workspaces/ws_1/other/x'), null);
125
+ });
126
+ //# sourceMappingURL=staking.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staking.test.js","sourceRoot":"","sources":["../../../../src/gateway/console-api/handlers/staking.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ConsoleDeps } from '../deps.js';
2
+ import { type ConsoleRouter } from '../router.js';
3
+ /**
4
+ * Antseed updates (org admins and admin tokens). The gateway asks npm for
5
+ * the latest @antseed/cli every 30 minutes. On a server set up by the
6
+ * gateway installer, or in the desktop app, updating takes two clicks like
7
+ * the desktop app's banner: `POST /update {"action":"download"}` fetches the
8
+ * new version without touching the running one, then `POST /update`
9
+ * (`install`) switches to it and restarts, so the console reconnects to the
10
+ * new version. Elsewhere the console shows the command to run.
11
+ */
12
+ export declare function registerUpdateRoutes(router: ConsoleRouter, deps: ConsoleDeps): void;
13
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../../src/gateway/console-api/handlers/update.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,EAAyB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAA;AAExE;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CAwCnF"}
@@ -0,0 +1,65 @@
1
+ import { recordAudit } from '../../services/context.js';
2
+ import { createGatewayUpdates } from '../../updates.js';
3
+ import { requestActor, requireOrgAdmin } from '../access.js';
4
+ import { ConsoleError, respond } from '../router.js';
5
+ /**
6
+ * Antseed updates (org admins and admin tokens). The gateway asks npm for
7
+ * the latest @antseed/cli every 30 minutes. On a server set up by the
8
+ * gateway installer, or in the desktop app, updating takes two clicks like
9
+ * the desktop app's banner: `POST /update {"action":"download"}` fetches the
10
+ * new version without touching the running one, then `POST /update`
11
+ * (`install`) switches to it and restarts, so the console reconnects to the
12
+ * new version. Elsewhere the console shows the command to run.
13
+ */
14
+ export function registerUpdateRoutes(router, deps) {
15
+ const { store } = deps;
16
+ const updates = deps.updates ?? createGatewayUpdates({ dataDir: deps.dataDir, current: deps.version, log: deps.log });
17
+ router.add('GET', '/update', async ({ principal }) => {
18
+ requireOrgAdmin(principal, store);
19
+ return updates.info();
20
+ });
21
+ router.add('POST', '/update/check', async ({ principal }) => {
22
+ requireOrgAdmin(principal, store);
23
+ return updates.check();
24
+ });
25
+ router.add('POST', '/update', async (request) => {
26
+ requireOrgAdmin(request.principal, store);
27
+ const action = readAction(request.body);
28
+ const before = updates.info();
29
+ if (before.apply !== 'console') {
30
+ throw new ConsoleError(409, 'update_unsupported', before.command
31
+ ? `This gateway cannot update itself from the console. On its host, run: ${before.command}`
32
+ : before.note);
33
+ }
34
+ if (!before.available && before.downloaded === null && !inFlight(before))
35
+ throw new ConsoleError(409, 'up_to_date', `Antseed ${before.current} is already the latest version`);
36
+ // Asking again for the step that is running is harmless; the other step waits for it.
37
+ if (inFlight(before) && before.progress?.action !== action) {
38
+ throw new ConsoleError(409, 'update_in_progress', before.progress?.action === 'download'
39
+ ? 'The download is still running; restart once it is ready'
40
+ : 'An update is installing; try again when it is done');
41
+ }
42
+ // Downloaded already: nothing to fetch until the next version is out.
43
+ if (action === 'download' && before.downloaded !== null && before.downloaded === before.latest)
44
+ return respond(202, before);
45
+ const actor = requestActor(deps, request);
46
+ const after = updates.apply(actor.actor.label ?? actor.actor.kind, action);
47
+ // Only the step that restarts the gateway is audited.
48
+ if (action === 'install' && !inFlight(before)) {
49
+ recordAudit(deps, actor, 'gateway.update', { kind: 'settings', id: 'update', label: 'Antseed version' }, { from: before.current, to: before.downloaded ?? before.latest });
50
+ }
51
+ return respond(202, after);
52
+ });
53
+ }
54
+ function readAction(body) {
55
+ const action = body && typeof body === 'object' ? body['action'] : undefined;
56
+ if (action === undefined || action === 'install')
57
+ return 'install';
58
+ if (action === 'download')
59
+ return 'download';
60
+ throw new ConsoleError(400, 'invalid_action', 'action must be "download" or "install"');
61
+ }
62
+ function inFlight(update) {
63
+ return update.progress?.state === 'requested' || update.progress?.state === 'running';
64
+ }
65
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../../../src/gateway/console-api/handlers/update.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,EAAE,oBAAoB,EAAuB,MAAM,kBAAkB,CAAA;AAC5E,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAE5D,OAAO,EAAE,YAAY,EAAE,OAAO,EAAsB,MAAM,cAAc,CAAA;AAExE;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAqB,EAAE,IAAiB;IAC3E,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAA;IACtB,MAAM,OAAO,GAAmB,IAAI,CAAC,OAAO,IAAI,oBAAoB,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;IAErI,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE;QACnD,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QACjC,OAAO,OAAO,CAAC,IAAI,EAAE,CAAA;IACvB,CAAC,CAAC,CAAA;IAEF,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE;QAC1D,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QACjC,OAAO,OAAO,CAAC,KAAK,EAAE,CAAA;IACxB,CAAC,CAAC,CAAA;IAEF,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAC9C,eAAe,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QACzC,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QACvC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAA;QAC7B,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,IAAI,YAAY,CAAC,GAAG,EAAE,oBAAoB,EAAE,MAAM,CAAC,OAAO;gBAC9D,CAAC,CAAC,yEAAyE,MAAM,CAAC,OAAO,EAAE;gBAC3F,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAClB,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,YAAY,CAAC,GAAG,EAAE,YAAY,EAAE,WAAW,MAAM,CAAC,OAAO,gCAAgC,CAAC,CAAA;QAC9K,sFAAsF;QACtF,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;YAC3D,MAAM,IAAI,YAAY,CAAC,GAAG,EAAE,oBAAoB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,KAAK,UAAU;gBACtF,CAAC,CAAC,yDAAyD;gBAC3D,CAAC,CAAC,oDAAoD,CAAC,CAAA;QAC3D,CAAC;QACD,sEAAsE;QACtE,IAAI,MAAM,KAAK,UAAU,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI,IAAI,MAAM,CAAC,UAAU,KAAK,MAAM,CAAC,MAAM;YAAE,OAAO,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;QAC3H,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QACzC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QAC1E,sDAAsD;QACtD,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9C,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,CAAA;QAC5K,CAAC;QACD,OAAO,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IAC5B,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,IAAa;IAC/B,MAAM,MAAM,GAAG,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAE,IAAgC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACzG,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IAClE,IAAI,MAAM,KAAK,UAAU;QAAE,OAAO,UAAU,CAAA;IAC5C,MAAM,IAAI,YAAY,CAAC,GAAG,EAAE,gBAAgB,EAAE,wCAAwC,CAAC,CAAA;AACzF,CAAC;AAED,SAAS,QAAQ,CAAC,MAAqB;IACrC,OAAO,MAAM,CAAC,QAAQ,EAAE,KAAK,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,EAAE,KAAK,KAAK,SAAS,CAAA;AACvF,CAAC"}
@@ -66,7 +66,7 @@ export interface Route {
66
66
  }
67
67
  /**
68
68
  * Minimal method + path router. Patterns use `:name` segments, e.g.
69
- * `/workspaces/:id/members/:memberId`. Feature modules export a
69
+ * `/workspaces/:id/members/:memberId`, and may end in `*` for the rest of the path. Feature modules export a
70
70
  * `register…Routes(router, deps)` function that calls `router.add`.
71
71
  */
72
72
  export declare class ConsoleRouter {
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../src/gateway/console-api/router.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../src/gateway/console-api/router.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,7 @@ export class ConsoleError extends Error {
14
14
  }
15
15
  /**
16
16
  * Minimal method + path router. Patterns use `:name` segments, e.g.
17
- * `/workspaces/:id/members/:memberId`. Feature modules export a
17
+ * `/workspaces/:id/members/:memberId`, and may end in `*` for the rest of the path. Feature modules export a
18
18
  * `register…Routes(router, deps)` function that calls `router.add`.
19
19
  */
20
20
  export class ConsoleRouter {
@@ -28,11 +28,16 @@ export class ConsoleRouter {
28
28
  if (route.method !== method.toUpperCase())
29
29
  continue;
30
30
  const pattern = route.pattern.split('/').filter(Boolean);
31
- if (pattern.length !== segments.length)
31
+ // A trailing `*` matches one or more further segments, kept as written in `params['*']`.
32
+ const rest = pattern[pattern.length - 1] === '*';
33
+ const fixed = rest ? pattern.length - 1 : pattern.length;
34
+ if (rest ? segments.length <= fixed : pattern.length !== segments.length)
32
35
  continue;
33
36
  const params = {};
37
+ if (rest)
38
+ params['*'] = segments.slice(fixed).join('/');
34
39
  let ok = true;
35
- for (let index = 0; index < pattern.length; index += 1) {
40
+ for (let index = 0; index < fixed; index += 1) {
36
41
  const part = pattern[index];
37
42
  const segment = segments[index];
38
43
  if (part.startsWith(':')) {
@@ -1 +1 @@
1
- {"version":3,"file":"router.js","sourceRoot":"","sources":["../../../src/gateway/console-api/router.ts"],"names":[],"mappings":"AAsCA,MAAM,UAAU,OAAO,CAAC,MAAc,EAAE,IAAc,EAAE,UAAsE,EAAE;IAC9H,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAA;AAC9D,CAAC;AAED,MAAM,OAAO,YAAa,SAAQ,KAAK;IAChB;IAAyB;IAAwC;IAAtF,YAAqB,MAAc,EAAW,IAAY,EAAE,OAAe,EAAW,OAAiC;QACrH,KAAK,CAAC,OAAO,CAAC,CAAA;QADK,WAAM,GAAN,MAAM,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAQ;QAA4B,YAAO,GAAP,OAAO,CAA0B;IAEvH,CAAC;CACF;AAgBD;;;;GAIG;AACH,MAAM,OAAO,aAAa;IACP,OAAO,GAAY,EAAE,CAAA;IAEtC,GAAG,CAAC,MAAc,EAAE,OAAe,EAAE,OAAuB,EAAE,UAAwB,EAAE;QACtF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;IAChF,CAAC;IAED,KAAK,CAAC,MAAc,EAAE,IAAY;QAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAChD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjC,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,WAAW,EAAE;gBAAE,SAAQ;YACnD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;YACxD,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;gBAAE,SAAQ;YAChD,MAAM,MAAM,GAA2B,EAAE,CAAA;YACzC,IAAI,EAAE,GAAG,IAAI,CAAA;YACb,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;gBACvD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAE,CAAA;gBAC5B,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAE,CAAA;gBAChC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACzB,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;oBACpC,4FAA4F;oBAC5F,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;wBACnB,EAAE,GAAG,KAAK,CAAA;wBACV,MAAK;oBACP,CAAC;oBACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAA;gBAC/B,CAAC;qBAAM,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;oBAC5B,EAAE,GAAG,KAAK,CAAA;oBACV,MAAK;gBACP,CAAC;YACH,CAAC;YACD,IAAI,EAAE;gBAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;QAClC,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;CACF;AAmBD,SAAS,aAAa,CAAC,OAAe;IACpC,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAA;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../../src/gateway/console-api/router.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,8 @@
11
11
  * HTTP status.
12
12
  */
13
13
  import type { RoutingPolicy } from '../../routing-policy/policy.js';
14
+ import type { InstallKind } from '../../update/install-method.js';
15
+ import type { RootUpdateProgress } from '../../update/root-updater.js';
14
16
  export type { RoutingPolicy, ModelRoute, RoutingSort } from '../../routing-policy/policy.js';
15
17
  export type { OperatorRelation, OperatorState, OperatorAuthorization, WorkspaceOperatorSummary } from './operator-types.js';
16
18
  export declare const CONSOLE_BASE_PATH = "/console";
@@ -277,6 +279,16 @@ export interface RequestLogEntry {
277
279
  * Token counts meanwhile come from the response's own usage.
278
280
  */
279
281
  costPending?: boolean;
282
+ /**
283
+ * A native video request. A job is charged once, on the retrieve that
284
+ * delivers its file (`delivery`); its create and status polls cost nothing.
285
+ * `charged` is a create's job charge, null until its video is delivered.
286
+ */
287
+ video?: {
288
+ action: 'create' | 'poll' | 'delivery';
289
+ jobId: string | null;
290
+ charged: Usdc | null;
291
+ };
280
292
  }
281
293
  /** GET /requests/:tag → one entry, with bodies when content logging was on for it. */
282
294
  export interface RequestDetail extends RequestLogEntry {
@@ -511,6 +523,8 @@ export interface PeerVerificationLink {
511
523
  /** `https://<domain>` or `https://github.com/<user>[/<repo>]`. */
512
524
  href: string;
513
525
  }
526
+ /** Mirrors `TeeScope` in `@antseed/node/tee-status`, which the console cannot import. */
527
+ export type PeerTeeScope = 'end-to-end' | 'seller-node';
514
528
  export interface Peer {
515
529
  peerId: string;
516
530
  displayName: string | null;
@@ -530,6 +544,12 @@ export interface Peer {
530
544
  /** Verified domain and GitHub claims; empty when none checked out. */
531
545
  verificationLinks: PeerVerificationLink[];
532
546
  tee: boolean;
547
+ /**
548
+ * How far a current TEE attestation reaches: 'end-to-end' (seller node and its model
549
+ * provider) or 'seller-node' (the provider behind it is not TEE-attested). Null when the
550
+ * seller is not TEE-capable or the buyer has not verified it yet.
551
+ */
552
+ teeScope: PeerTeeScope | null;
533
553
  stakeAnts: string | null;
534
554
  usageShareBps: number | null;
535
555
  washFlagged: boolean;
@@ -573,6 +593,12 @@ export interface NetworkModelOffer {
573
593
  /** The seller's verified domain and GitHub claims. */
574
594
  verificationLinks: PeerVerificationLink[];
575
595
  tee: boolean;
596
+ /**
597
+ * How far a current TEE attestation reaches: 'end-to-end' (seller node and its model
598
+ * provider) or 'seller-node' (the provider behind it is not TEE-attested). Null when the
599
+ * seller is not TEE-capable or the buyer has not verified it yet.
600
+ */
601
+ teeScope: PeerTeeScope | null;
576
602
  /** Medians over this gateway's recent requests: total time, time to first token, and output tokens per second. */
577
603
  latencyMsP50: number | null;
578
604
  firstTokenMsP50: number | null;
@@ -600,6 +626,8 @@ export interface NetworkModel {
600
626
  /** At least one offer is free. */
601
627
  free: boolean;
602
628
  teeSellers: number;
629
+ /** Sellers whose TEE attestation reaches end to end, through their model provider. */
630
+ fullTeeSellers: number;
603
631
  verifiedSellers: number;
604
632
  /** In the buyer's routing order. */
605
633
  offers: NetworkModelOffer[];
@@ -694,6 +722,41 @@ export interface GatewayStatus {
694
722
  */
695
723
  exposure?: GatewayExposure;
696
724
  }
725
+ export interface GatewayUpdate {
726
+ /**
727
+ * What updates: `cli` is @antseed/cli from npm; `desktop` is the desktop
728
+ * app running this gateway, whose own updater reports the versions below.
729
+ */
730
+ product: 'cli' | 'desktop';
731
+ /** The running version (of the CLI, or of the desktop app). */
732
+ current: string;
733
+ /** The newest version at the last check (npm's `latest`, or the app's newest release); null before the first answer. */
734
+ latest: string | null;
735
+ available: boolean;
736
+ /** When npm was last asked (ms); null when never. */
737
+ checkedAt: number | null;
738
+ /** Why the last check failed; null when it worked. */
739
+ checkError: string | null;
740
+ /** `NO_UPDATE_NOTIFIER`, `ANTSEED_NO_UPDATE_CHECK` or `CI` turned background checks off. */
741
+ checksDisabled: boolean;
742
+ /**
743
+ * `console`: `POST /update` downloads and installs it (servers set up by the gateway
744
+ * installer, and the desktop app); `command`: run `command` on the gateway
745
+ * host; `none`: it updates some other way.
746
+ */
747
+ apply: 'console' | 'command' | 'none';
748
+ install: InstallKind;
749
+ command: string | null;
750
+ /** One line on how this install updates. */
751
+ note: string;
752
+ /** The update service's pending request or last run; null when `apply` is not `console` or it never ran. */
753
+ progress: RootUpdateProgress | null;
754
+ /**
755
+ * A version downloaded and waiting for Restart & update: newer than
756
+ * `current`, whatever npm's `latest` has moved on to since. Null when none.
757
+ */
758
+ downloaded: string | null;
759
+ }
697
760
  /**
698
761
  * `local`: only this machine can reach the gateway (loopback, no public URL);
699
762
  * `lan`: it listens beyond loopback without a public URL; `public`: it has