@stage-labs/metro 0.1.0-beta.201 → 0.1.0-beta.202

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 (163) hide show
  1. package/dist/claude.js +4 -15
  2. package/dist/cli.js +5 -3
  3. package/dist/hold.js +1 -2
  4. package/dist/runtime-install.js +4 -5
  5. package/dist/runtime.js +1 -4
  6. package/dist/serve.js +4 -5
  7. package/dist/service.js +82 -21
  8. package/dist/update.js +1 -1
  9. package/package.json +2 -2
  10. package/runtime/marketplace/plugin/.claude-plugin/plugin.json +1 -1
  11. package/runtime/node_modules/@metro-labs/core/src/events.ts +4 -2
  12. package/runtime/node_modules/@metro-labs/core/src/lines.ts +12 -25
  13. package/runtime/node_modules/@metro-labs/core/src/stations/account-store.ts +45 -22
  14. package/runtime/node_modules/@metro-labs/core/src/stations/attachments.ts +0 -1
  15. package/runtime/node_modules/@metro-labs/core/src/stations/messaging-normalize.ts +8 -80
  16. package/runtime/node_modules/@metro-labs/core/src/stations/station-runtime.ts +3 -5
  17. package/runtime/node_modules/@metro-labs/core/src/stations/train-events.ts +4 -9
  18. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/files.ts +9 -39
  19. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/job-env.ts +1 -1
  20. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/provision.ts +9 -28
  21. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/schedule-detail.ts +0 -1
  22. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/schedules-api.ts +3 -3
  23. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/schedules.ts +8 -116
  24. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/unit-files.ts +11 -35
  25. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/user.ts +7 -9
  26. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/view.ts +1 -1
  27. package/runtime/node_modules/@metro-labs/daemon/src/agents/account-lookups.ts +1 -1
  28. package/runtime/node_modules/@metro-labs/daemon/src/agents/accounts-api.ts +1 -1
  29. package/runtime/node_modules/@metro-labs/daemon/src/agents/allowlist.ts +1 -1
  30. package/runtime/node_modules/@metro-labs/daemon/src/agents/bundle.ts +3 -3
  31. package/runtime/node_modules/@metro-labs/daemon/src/agents/file-admin.ts +2 -2
  32. package/runtime/node_modules/@metro-labs/daemon/src/agents/files.ts +3 -29
  33. package/runtime/node_modules/@metro-labs/daemon/src/approvals/pending.ts +5 -8
  34. package/runtime/node_modules/@metro-labs/daemon/src/approvals/preview.ts +1 -1
  35. package/runtime/node_modules/@metro-labs/daemon/src/boot/boot.ts +5 -8
  36. package/runtime/node_modules/@metro-labs/daemon/src/boot/connect-hint.ts +3 -6
  37. package/runtime/node_modules/@metro-labs/daemon/src/channels/inbound.ts +25 -3
  38. package/runtime/node_modules/@metro-labs/daemon/src/channels/media-note.ts +2 -3
  39. package/runtime/node_modules/@metro-labs/daemon/src/claude/files.ts +2 -2
  40. package/runtime/node_modules/@metro-labs/daemon/src/claude/login.ts +1 -1
  41. package/runtime/node_modules/@metro-labs/daemon/src/claude/memory.ts +6 -56
  42. package/runtime/node_modules/@metro-labs/daemon/src/claude/plugin-install.ts +3 -3
  43. package/runtime/node_modules/@metro-labs/daemon/src/claude/session-files.ts +1 -1
  44. package/runtime/node_modules/@metro-labs/daemon/src/claude/session.ts +7 -6
  45. package/runtime/node_modules/@metro-labs/daemon/src/claude/settings.ts +1 -1
  46. package/runtime/node_modules/@metro-labs/daemon/src/claude/setup.ts +7 -7
  47. package/runtime/node_modules/@metro-labs/daemon/src/claude/skills.ts +4 -4
  48. package/runtime/node_modules/@metro-labs/daemon/src/claude/version.ts +1 -1
  49. package/runtime/node_modules/@metro-labs/daemon/src/connectors/api.ts +2 -4
  50. package/runtime/node_modules/@metro-labs/daemon/src/connectors/config.ts +19 -22
  51. package/runtime/node_modules/@metro-labs/daemon/src/connectors/gates.ts +1 -2
  52. package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth-discovery.ts +6 -8
  53. package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth-routes.ts +3 -6
  54. package/runtime/node_modules/@metro-labs/daemon/src/connectors/plugin-sync.ts +1 -1
  55. package/runtime/node_modules/@metro-labs/daemon/src/connectors/relay.ts +2 -3
  56. package/runtime/node_modules/@metro-labs/daemon/src/connectors/store.ts +28 -1
  57. package/runtime/node_modules/@metro-labs/daemon/src/files/attach-serve.ts +1 -1
  58. package/runtime/node_modules/@metro-labs/daemon/src/gateway/bedrock.ts +4 -4
  59. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-auth.ts +1 -1
  60. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-device.ts +1 -1
  61. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-stream.ts +1 -1
  62. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-translate.ts +3 -2
  63. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex.ts +1 -1
  64. package/runtime/node_modules/@metro-labs/daemon/src/gateway/effort.ts +2 -2
  65. package/runtime/node_modules/@metro-labs/daemon/src/gateway/eventstream.ts +1 -1
  66. package/runtime/node_modules/@metro-labs/daemon/src/gateway/forward.ts +3 -3
  67. package/runtime/node_modules/@metro-labs/daemon/src/gateway/frames.ts +1 -1
  68. package/runtime/node_modules/@metro-labs/daemon/src/gateway/gateway.ts +3 -3
  69. package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-auth.ts +6 -6
  70. package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-client.ts +7 -7
  71. package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-stream.ts +1 -1
  72. package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-translate.ts +3 -2
  73. package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini.ts +1 -1
  74. package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-config.ts +10 -31
  75. package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-signin.ts +1 -1
  76. package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-store.ts +1 -1
  77. package/runtime/node_modules/@metro-labs/daemon/src/gateway/openrouter.ts +2 -2
  78. package/runtime/node_modules/@metro-labs/daemon/src/gateway/provider-models.ts +3 -3
  79. package/runtime/node_modules/@metro-labs/daemon/src/gateway/text.ts +1 -2
  80. package/runtime/node_modules/@metro-labs/daemon/src/gateway/usage.ts +2 -2
  81. package/runtime/node_modules/@metro-labs/daemon/src/mcp/policy-gate.ts +5 -6
  82. package/runtime/node_modules/@metro-labs/daemon/src/mcp/policy-snapshot.ts +3 -3
  83. package/runtime/node_modules/@metro-labs/daemon/src/mcp/profile-lookup.ts +2 -2
  84. package/runtime/node_modules/@metro-labs/daemon/src/mcp/read-tool.ts +2 -2
  85. package/runtime/node_modules/@metro-labs/daemon/src/metro-user/helper-script.ts +2 -2
  86. package/runtime/node_modules/@metro-labs/daemon/src/metro-user/install.ts +37 -0
  87. package/runtime/node_modules/@metro-labs/daemon/src/net/tunnel.ts +2 -2
  88. package/runtime/node_modules/@metro-labs/daemon/src/policy/policy.ts +1 -1
  89. package/runtime/node_modules/@metro-labs/daemon/src/routes/local-mode.ts +1 -4
  90. package/runtime/node_modules/@metro-labs/daemon/src/routes/session-apis.ts +3 -8
  91. package/runtime/node_modules/@metro-labs/daemon/src/server/machine.ts +2 -2
  92. package/runtime/node_modules/@metro-labs/daemon/src/server/update.ts +2 -2
  93. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-session.ts +2 -2
  94. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-xmtp.ts +6 -7
  95. package/runtime/node_modules/@metro-labs/daemon/src/stations/supervisor-io.ts +1 -1
  96. package/runtime/node_modules/@metro-labs/daemon/src/stations/supervisor.ts +2 -2
  97. package/runtime/node_modules/@metro-labs/daemon/src/terminal/api.ts +2 -2
  98. package/runtime/node_modules/@metro-labs/daemon/src/terminal/socket.ts +1 -1
  99. package/runtime/node_modules/@metro-labs/daemon/src/vault/firewall.ts +5 -44
  100. package/runtime/node_modules/@metro-labs/daemon/src/vault/index.ts +4 -4
  101. package/runtime/node_modules/@metro-labs/daemon/src/vault/proxy.ts +6 -7
  102. package/runtime/node_modules/@metro-labs/daemon/src/vault/store.ts +12 -13
  103. package/runtime/node_modules/@metro-labs/daemon/src/vault/trust.ts +5 -22
  104. package/runtime/node_modules/@metro-labs/discord-bot/src/accounts.ts +1 -19
  105. package/runtime/node_modules/@metro-labs/discord-bot/src/actions.ts +7 -35
  106. package/runtime/node_modules/@metro-labs/discord-bot/src/format.ts +5 -10
  107. package/runtime/node_modules/@metro-labs/discord-bot/src/group-actions.ts +1 -1
  108. package/runtime/node_modules/@metro-labs/discord-bot/src/index.ts +1 -2
  109. package/runtime/node_modules/@metro-labs/discord-bot/src/profile.ts +1 -1
  110. package/runtime/node_modules/@metro-labs/discord-bot/src/send-files.ts +11 -12
  111. package/runtime/node_modules/@metro-labs/http/src/api-http.ts +2 -5
  112. package/runtime/node_modules/@metro-labs/http/src/mode-api.ts +0 -1
  113. package/runtime/node_modules/@metro-labs/outlook/src/accounts.ts +1 -15
  114. package/runtime/node_modules/@metro-labs/outlook/src/actions.ts +0 -6
  115. package/runtime/node_modules/@metro-labs/outlook/src/format.ts +0 -1
  116. package/runtime/node_modules/@metro-labs/outlook/src/state.ts +1 -1
  117. package/runtime/node_modules/@metro-labs/telegram/src/accounts.ts +4 -22
  118. package/runtime/node_modules/@metro-labs/telegram/src/actions.ts +2 -2
  119. package/runtime/node_modules/@metro-labs/telegram/src/format.ts +1 -3
  120. package/runtime/node_modules/@metro-labs/telegram/src/inbound.ts +1 -1
  121. package/runtime/node_modules/@metro-labs/telegram/src/media-actions.ts +1 -2
  122. package/runtime/node_modules/@metro-labs/telegram/src/reactions.ts +1 -1
  123. package/runtime/node_modules/@metro-labs/telegram-bot/src/accounts.ts +4 -37
  124. package/runtime/node_modules/@metro-labs/telegram-bot/src/actions.ts +7 -23
  125. package/runtime/node_modules/@metro-labs/telegram-bot/src/format.ts +1 -4
  126. package/runtime/node_modules/@metro-labs/telegram-bot/src/media-actions.ts +4 -9
  127. package/runtime/node_modules/@metro-labs/telegram-bot/src/profile.ts +3 -3
  128. package/runtime/node_modules/@metro-labs/threema/src/accounts.ts +0 -11
  129. package/runtime/node_modules/@metro-labs/threema/src/actions.ts +2 -12
  130. package/runtime/node_modules/@metro-labs/threema/src/files.ts +4 -15
  131. package/runtime/node_modules/@metro-labs/threema/src/format.ts +2 -7
  132. package/runtime/node_modules/@metro-labs/whatsapp/package.json +1 -2
  133. package/runtime/node_modules/@metro-labs/whatsapp/src/accounts.ts +5 -26
  134. package/runtime/node_modules/@metro-labs/whatsapp/src/actions.ts +5 -6
  135. package/runtime/node_modules/@metro-labs/whatsapp/src/format.ts +1 -3
  136. package/runtime/node_modules/@metro-labs/whatsapp/src/inbound.ts +1 -1
  137. package/runtime/node_modules/@metro-labs/xmtp/src/accounts.ts +1 -12
  138. package/runtime/node_modules/@metro-labs/xmtp/src/actions-close.ts +1 -1
  139. package/runtime/node_modules/@metro-labs/xmtp/src/actions-conv.ts +14 -5
  140. package/runtime/node_modules/@metro-labs/xmtp/src/actions-meta.ts +1 -1
  141. package/runtime/node_modules/@metro-labs/xmtp/src/actions.ts +31 -78
  142. package/runtime/node_modules/@metro-labs/xmtp/src/emit.ts +3 -4
  143. package/runtime/node_modules/@metro-labs/xmtp/src/index.ts +1 -6
  144. package/runtime/node_modules/@metro-labs/xmtp/src/profile.ts +1 -1
  145. package/runtime/node_modules/@metro-labs/xmtp/src/sender.ts +1 -1
  146. package/runtime/node_modules/@metro-labs/xmtp/src/tools-handlers.ts +1 -1
  147. package/runtime/node_modules/@metro-labs/xmtp/src/transcribe.ts +2 -2
  148. package/runtime/node_modules/@metro-labs/xmtp/src/wire.ts +0 -2
  149. package/runtime/runtime.json +1 -1
  150. package/runtime/node_modules/@metro-labs/core/src/identity.ts +0 -7
  151. package/runtime/node_modules/@metro-labs/daemon/src/approvals/needs.ts +0 -2
  152. package/runtime/node_modules/@metro-labs/daemon/src/channels/dedupe.ts +0 -12
  153. package/runtime/node_modules/@metro-labs/daemon/src/channels/react-note.ts +0 -13
  154. package/runtime/node_modules/@metro-labs/daemon/src/channels/reply-id.ts +0 -1
  155. package/runtime/node_modules/@metro-labs/daemon/src/connectors/relay-target.ts +0 -29
  156. package/runtime/node_modules/@metro-labs/daemon/src/metro-user/api.ts +0 -43
  157. package/runtime/node_modules/@metro-labs/daemon/src/metro-user/move.ts +0 -165
  158. package/runtime/node_modules/@metro-labs/discord-bot/src/wire.ts +0 -1
  159. package/runtime/node_modules/@metro-labs/telegram/src/normalize.ts +0 -22
  160. package/runtime/node_modules/@metro-labs/telegram/src/wire.ts +0 -1
  161. package/runtime/node_modules/@metro-labs/telegram-bot/src/wire.ts +0 -1
  162. package/runtime/node_modules/@metro-labs/whatsapp/src/normalize.ts +0 -22
  163. package/runtime/node_modules/@metro-labs/whatsapp/src/wire.ts +0 -1
@@ -1,165 +0,0 @@
1
- import { spawnSync } from 'node:child_process';
2
- import { chmodSync, existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from 'node:fs';
3
- import { homedir } from 'node:os';
4
- import { join } from 'node:path';
5
- import { ApiError } from '@metro-labs/http/api-error';
6
- import { METRO_VERSION } from '@metro-labs/core/version';
7
- import { AGENT_NAME } from '../agent-user/user.js';
8
- import { HELPER_PATH, helperScript, METRO_HOME, METRO_USER, SUDOERS_PATH, sudoersText } from './helper-script.js';
9
- import { runningAsRoot } from './privilege.js';
10
-
11
- export const UNIT_FILE = '/etc/systemd/system/metro.service';
12
- export const MOVE_DIR = '/var/lib/metro-move';
13
- export const MOVE_LOG = '/var/log/metro-move.log';
14
- const PREFIX = `${METRO_HOME}/.npm-global`;
15
- const CLI = `${PREFIX}/lib/node_modules/@stage-labs/metro/dist/cli.js`;
16
-
17
- const which = (bin: string): string | null => {
18
- const run = spawnSync('sh', ['-c', `command -v ${bin}`], { encoding: 'utf8' });
19
- const path = run.status === 0 ? run.stdout.trim() : '';
20
- if (path === '') return null;
21
- try {
22
- return realpathSync(path);
23
- } catch {
24
- return null;
25
- }
26
- };
27
-
28
- export interface UnitFacts {
29
- serveArgs: string[];
30
- env: string[];
31
- port: string;
32
- }
33
-
34
- export function unitFacts(unit: string): UnitFacts {
35
- const exec = /^ExecStart=(.*)$/m.exec(unit)?.[1] ?? '';
36
- const words = [...exec.matchAll(/"((?:[^"\\]|\\.)*)"|(\S+)/g)].map((m) => (m[1] ?? m[2] ?? '').replace(/\\(.)/g, '$1'));
37
- const at = words.indexOf('serve');
38
- if (at < 0) throw new ApiError('the metro service does not run `metro serve`; move it by hand', 409);
39
- const env = [...unit.matchAll(/^Environment=(.*)$/gm)].map((m) => m[1] ?? '').filter((e) => /^"?METRO_/.test(e) && !/^"?METRO_(AGENTS_DIR|RUNTIME_STORE)=/.test(e));
40
- const portArg = words[words.indexOf('--port') + 1];
41
- const envPort = /METRO_WEBHOOK_PORT=(\d+)/.exec(env.join(' '))?.[1];
42
- return { serveArgs: words.slice(at + 1), env, port: (words.includes('--port') ? portArg : envPort) ?? '8420' };
43
- }
44
-
45
- const ESCAPED_QUOTE = '\'\\\'\'';
46
- const shellWord = (w: string): string => `'${w.replace(/'/g, ESCAPED_QUOTE)}'`;
47
- const unitWord = (w: string): string => (/^[A-Za-z0-9_/.:=+@,-]+$/.test(w) ? w : `"${w.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`);
48
-
49
- export function metroUnit(node: string, facts: UnitFacts): string {
50
- return [
51
- '[Unit]',
52
- 'Description=Metro daemon (metro serve)',
53
- 'After=network-online.target tailscaled.service',
54
- 'Wants=network-online.target',
55
- '',
56
- '[Service]',
57
- `User=${METRO_USER}`,
58
- `Group=${METRO_USER}`,
59
- `ExecStart=${[node, CLI, 'serve', ...facts.serveArgs].map(unitWord).join(' ')}`,
60
- 'Restart=always',
61
- 'RestartSec=2',
62
- 'OOMPolicy=continue',
63
- 'WorkingDirectory=/',
64
- `Environment=HOME=${METRO_HOME}`,
65
- `Environment=PATH=${PREFIX}/bin:/usr/local/bin:/usr/bin:/bin`,
66
- `Environment=NPM_CONFIG_PREFIX=${PREFIX}`,
67
- ...facts.env.map((e) => `Environment=${e}`),
68
- '',
69
- '[Install]',
70
- 'WantedBy=multi-user.target',
71
- '',
72
- ].join('\n');
73
- }
74
-
75
- export function moveScript(port: string, spec: string, bun: string): string {
76
- return [
77
- '#!/bin/sh',
78
- 'set -u',
79
- `exec >> ${MOVE_LOG} 2>&1`,
80
- 'echo "--- metro move $(date -Is)"',
81
- `OLD=/root/.metro; NEW=${METRO_HOME}/.metro; DIR=${MOVE_DIR}`,
82
- 'fail() { echo "FAILED: $*"; echo failed > "$DIR/state"; exit 1; }',
83
- 'healthy() {',
84
- ' i=0; while [ $i -lt 60 ]; do',
85
- ` if curl -fsS -m 3 http://127.0.0.1:${port}/health >/dev/null 2>&1 && [ "$(ps -o user= -p "$(systemctl show metro -p MainPID --value)")" = "$1" ]; then return 0; fi`,
86
- ' i=$((i+1)); sleep 2; done; return 1; }',
87
- 'echo moving > "$DIR/state"',
88
- `id ${METRO_USER} >/dev/null 2>&1 || useradd --system --create-home --home-dir ${METRO_HOME} --shell /usr/sbin/nologin ${METRO_USER} || fail "useradd"`,
89
- `usermod -aG systemd-journal ${METRO_USER} || true`,
90
- `mkdir -p ${METRO_HOME} && chown ${METRO_USER}:${METRO_USER} ${METRO_HOME} && chmod 711 ${METRO_HOME}`,
91
- `B=${shellWord(bun)}; case "$B" in /root/*) install -m 755 "$B" /usr/local/bin/bun || fail "bun";; esac`,
92
- `su -s /bin/sh ${METRO_USER} -c ${shellWord(`cd / && npm install --global --prefix ${PREFIX} ${spec}`)} || fail "npm install for ${METRO_USER}"`,
93
- `for bin in node bun tailscale npm; do su -s /bin/sh ${METRO_USER} -c ${shellWord(`PATH=${PREFIX}/bin:/usr/local/bin:/usr/bin:/bin command -v "$1" >/dev/null`)} sh "$bin" || fail "${METRO_USER} cannot find $bin"; done`,
94
- `tailscale set --operator=${METRO_USER} || fail "tailscale operator"`,
95
- `cp ${UNIT_FILE} "$DIR/metro.service.root" || fail "unit backup"`,
96
- 'systemctl stop metro',
97
- 'if [ -e "$NEW" ]; then mv "$NEW" "$NEW.old-$(date +%s)"; fi',
98
- 'mv "$OLD" "$NEW" || { systemctl start metro; fail "move"; }',
99
- 'rm -f "$NEW/runtime/runtime.json"',
100
- `chown -R ${METRO_USER}:${METRO_USER} ${METRO_HOME} && chmod 711 ${METRO_HOME} && chmod 700 "$NEW"`,
101
- `install -m 644 "$DIR/metro.service.new" ${UNIT_FILE}`,
102
- 'systemctl daemon-reload && systemctl start metro',
103
- `if healthy ${METRO_USER}; then echo done > "$DIR/state"; echo "metro runs as ${METRO_USER}"; exit 0; fi`,
104
- 'echo "not healthy as metro, putting everything back"',
105
- 'systemctl stop metro',
106
- 'mv "$NEW" "$OLD" && chown -R root:root "$OLD"',
107
- `install -m 644 "$DIR/metro.service.root" ${UNIT_FILE}`,
108
- 'systemctl daemon-reload && systemctl start metro',
109
- 'healthy root && fail "Metro did not start as metro; it runs as root again" || fail "Metro did not start as metro, and the way back did not answer either"',
110
- '',
111
- ].join('\n');
112
- }
113
-
114
- function whichOrFail(bin: string): string {
115
- const found = which(bin);
116
- if (found === null) throw new ApiError(`${bin} is missing on this box`, 409);
117
- return found;
118
- }
119
-
120
- const requireTools = (): void => {
121
- for (const bin of ['sudo', 'visudo', 'tailscale', 'curl', 'npm']) whichOrFail(bin);
122
- };
123
-
124
- function preflight(): { node: string; bun: string; unit: string } {
125
- if (!runningAsRoot()) throw new ApiError('only a Metro running as root can move itself', 409);
126
- if (!existsSync(UNIT_FILE)) throw new ApiError('this box does not run Metro as the systemd service `metro`', 409);
127
- if (process.env.METRO_AGENTS_DIR !== undefined && process.env.METRO_AGENTS_DIR !== '') throw new ApiError('METRO_AGENTS_DIR is set; move this box by hand', 409);
128
- if (homedir() !== '/root') throw new ApiError(`Metro keeps its files in ${homedir()}, not /root; move this box by hand`, 409);
129
- const node = which('node');
130
- if (node === null || node.startsWith('/root/')) throw new ApiError('Node must be installed for every user (not under /root) before the move', 409);
131
- requireTools();
132
- return { node, bun: whichOrFail('bun'), unit: readFileSync(UNIT_FILE, 'utf8') };
133
- }
134
-
135
- function installHelper(): void {
136
- mkdirSync('/usr/local/lib/metro', { recursive: true, mode: 0o755 });
137
- writeFileSync(HELPER_PATH, helperScript(), { mode: 0o755 });
138
- chmodSync(HELPER_PATH, 0o755);
139
- const draft = join(MOVE_DIR, 'sudoers');
140
- writeFileSync(draft, sudoersText(AGENT_NAME), { mode: 0o440 });
141
- const check = spawnSync('visudo', ['-cf', draft], { encoding: 'utf8' });
142
- if (check.status !== 0) throw new ApiError(`the sudo rules did not validate: ${check.stdout}${check.stderr}`, 500);
143
- spawnSync('install', ['-m', '440', draft, SUDOERS_PATH]);
144
- }
145
-
146
- export function startMove(spec = `@stage-labs/metro@${METRO_VERSION}`): { log: string } {
147
- const { node, bun, unit } = preflight();
148
- const facts = unitFacts(unit);
149
- mkdirSync(MOVE_DIR, { recursive: true, mode: 0o700 });
150
- installHelper();
151
- writeFileSync(join(MOVE_DIR, 'metro.service.new'), metroUnit(node, facts), { mode: 0o600 });
152
- writeFileSync(join(MOVE_DIR, 'move.sh'), moveScript(facts.port, spec, bun), { mode: 0o700 });
153
- writeFileSync(join(MOVE_DIR, 'state'), 'starting\n');
154
- const run = spawnSync('systemd-run', ['--unit=metro-move', '--collect', '--quiet', 'sh', join(MOVE_DIR, 'move.sh')], { encoding: 'utf8' });
155
- if (run.status !== 0) throw new ApiError(`could not start the move: ${run.stderr.trim()}`, 500);
156
- return { log: MOVE_LOG };
157
- }
158
-
159
- export function moveState(): string | null {
160
- try {
161
- return readFileSync(join(MOVE_DIR, 'state'), 'utf8').trim();
162
- } catch {
163
- return null;
164
- }
165
- }
@@ -1 +0,0 @@
1
- export { emit, respond, mintId } from '@metro-labs/core/stations/station-runtime';
@@ -1,22 +0,0 @@
1
- import type { Normalized } from '@metro-labs/core/stations/messaging-normalize';
2
-
3
- type Args = Record<string, unknown>;
4
-
5
- export function normalizeTelegramUser(action: string, env: Args): Normalized {
6
- if (action === 'reply') {
7
- return {
8
- action: 'send',
9
- args: {
10
- line: env.line,
11
- text: env.text,
12
- replyTo: env.replyTo,
13
- account: env.account,
14
- attachments: env.attachments,
15
- },
16
- };
17
- }
18
- if (action === 'unreact') {
19
- return { action: 'react', args: { ...env, emoji: '' } };
20
- }
21
- return { action, args: env };
22
- }
@@ -1 +0,0 @@
1
- export { emit, mintId } from '@metro-labs/core/stations/station-runtime';
@@ -1 +0,0 @@
1
- export { emit, respond, mintId } from '@metro-labs/core/stations/station-runtime';
@@ -1,22 +0,0 @@
1
- import type { Normalized } from '@metro-labs/core/stations/messaging-normalize';
2
-
3
- type Args = Record<string, unknown>;
4
-
5
- export function normalizeWhatsApp(action: string, env: Args): Normalized {
6
- if (action === 'reply') {
7
- return {
8
- action: 'send',
9
- args: {
10
- line: env.line,
11
- text: env.text,
12
- replyTo: env.replyTo ?? env.messageId,
13
- account: env.account,
14
- attachments: env.attachments,
15
- },
16
- };
17
- }
18
- if (action === 'unreact') {
19
- return { action: 'react', args: { ...env, emoji: '' } };
20
- }
21
- return { action, args: env };
22
- }
@@ -1 +0,0 @@
1
- export { emit, mintId } from '@metro-labs/core/stations/station-runtime';