@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.
- package/dist/claude.js +4 -15
- package/dist/cli.js +5 -3
- package/dist/hold.js +1 -2
- package/dist/runtime-install.js +4 -5
- package/dist/runtime.js +1 -4
- package/dist/serve.js +4 -5
- package/dist/service.js +82 -21
- package/dist/update.js +1 -1
- package/package.json +2 -2
- package/runtime/marketplace/plugin/.claude-plugin/plugin.json +1 -1
- package/runtime/node_modules/@metro-labs/core/src/events.ts +4 -2
- package/runtime/node_modules/@metro-labs/core/src/lines.ts +12 -25
- package/runtime/node_modules/@metro-labs/core/src/stations/account-store.ts +45 -22
- package/runtime/node_modules/@metro-labs/core/src/stations/attachments.ts +0 -1
- package/runtime/node_modules/@metro-labs/core/src/stations/messaging-normalize.ts +8 -80
- package/runtime/node_modules/@metro-labs/core/src/stations/station-runtime.ts +3 -5
- package/runtime/node_modules/@metro-labs/core/src/stations/train-events.ts +4 -9
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/files.ts +9 -39
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/job-env.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/provision.ts +9 -28
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/schedule-detail.ts +0 -1
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/schedules-api.ts +3 -3
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/schedules.ts +8 -116
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/unit-files.ts +11 -35
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/user.ts +7 -9
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/view.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/agents/account-lookups.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/agents/accounts-api.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/agents/allowlist.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/agents/bundle.ts +3 -3
- package/runtime/node_modules/@metro-labs/daemon/src/agents/file-admin.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/agents/files.ts +3 -29
- package/runtime/node_modules/@metro-labs/daemon/src/approvals/pending.ts +5 -8
- package/runtime/node_modules/@metro-labs/daemon/src/approvals/preview.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/boot/boot.ts +5 -8
- package/runtime/node_modules/@metro-labs/daemon/src/boot/connect-hint.ts +3 -6
- package/runtime/node_modules/@metro-labs/daemon/src/channels/inbound.ts +25 -3
- package/runtime/node_modules/@metro-labs/daemon/src/channels/media-note.ts +2 -3
- package/runtime/node_modules/@metro-labs/daemon/src/claude/files.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/claude/login.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/claude/memory.ts +6 -56
- package/runtime/node_modules/@metro-labs/daemon/src/claude/plugin-install.ts +3 -3
- package/runtime/node_modules/@metro-labs/daemon/src/claude/session-files.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/claude/session.ts +7 -6
- package/runtime/node_modules/@metro-labs/daemon/src/claude/settings.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/claude/setup.ts +7 -7
- package/runtime/node_modules/@metro-labs/daemon/src/claude/skills.ts +4 -4
- package/runtime/node_modules/@metro-labs/daemon/src/claude/version.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/api.ts +2 -4
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/config.ts +19 -22
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/gates.ts +1 -2
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth-discovery.ts +6 -8
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth-routes.ts +3 -6
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/plugin-sync.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/relay.ts +2 -3
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/store.ts +28 -1
- package/runtime/node_modules/@metro-labs/daemon/src/files/attach-serve.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/bedrock.ts +4 -4
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-auth.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-device.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-stream.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-translate.ts +3 -2
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/effort.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/eventstream.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/forward.ts +3 -3
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/frames.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/gateway.ts +3 -3
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-auth.ts +6 -6
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-client.ts +7 -7
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-stream.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-translate.ts +3 -2
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-config.ts +10 -31
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-signin.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-store.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/openrouter.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/provider-models.ts +3 -3
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/text.ts +1 -2
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/usage.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/policy-gate.ts +5 -6
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/policy-snapshot.ts +3 -3
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/profile-lookup.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/read-tool.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/metro-user/helper-script.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/metro-user/install.ts +37 -0
- package/runtime/node_modules/@metro-labs/daemon/src/net/tunnel.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/policy/policy.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/routes/local-mode.ts +1 -4
- package/runtime/node_modules/@metro-labs/daemon/src/routes/session-apis.ts +3 -8
- package/runtime/node_modules/@metro-labs/daemon/src/server/machine.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/server/update.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-session.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-xmtp.ts +6 -7
- package/runtime/node_modules/@metro-labs/daemon/src/stations/supervisor-io.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/stations/supervisor.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/terminal/api.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/terminal/socket.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/vault/firewall.ts +5 -44
- package/runtime/node_modules/@metro-labs/daemon/src/vault/index.ts +4 -4
- package/runtime/node_modules/@metro-labs/daemon/src/vault/proxy.ts +6 -7
- package/runtime/node_modules/@metro-labs/daemon/src/vault/store.ts +12 -13
- package/runtime/node_modules/@metro-labs/daemon/src/vault/trust.ts +5 -22
- package/runtime/node_modules/@metro-labs/discord-bot/src/accounts.ts +1 -19
- package/runtime/node_modules/@metro-labs/discord-bot/src/actions.ts +7 -35
- package/runtime/node_modules/@metro-labs/discord-bot/src/format.ts +5 -10
- package/runtime/node_modules/@metro-labs/discord-bot/src/group-actions.ts +1 -1
- package/runtime/node_modules/@metro-labs/discord-bot/src/index.ts +1 -2
- package/runtime/node_modules/@metro-labs/discord-bot/src/profile.ts +1 -1
- package/runtime/node_modules/@metro-labs/discord-bot/src/send-files.ts +11 -12
- package/runtime/node_modules/@metro-labs/http/src/api-http.ts +2 -5
- package/runtime/node_modules/@metro-labs/http/src/mode-api.ts +0 -1
- package/runtime/node_modules/@metro-labs/outlook/src/accounts.ts +1 -15
- package/runtime/node_modules/@metro-labs/outlook/src/actions.ts +0 -6
- package/runtime/node_modules/@metro-labs/outlook/src/format.ts +0 -1
- package/runtime/node_modules/@metro-labs/outlook/src/state.ts +1 -1
- package/runtime/node_modules/@metro-labs/telegram/src/accounts.ts +4 -22
- package/runtime/node_modules/@metro-labs/telegram/src/actions.ts +2 -2
- package/runtime/node_modules/@metro-labs/telegram/src/format.ts +1 -3
- package/runtime/node_modules/@metro-labs/telegram/src/inbound.ts +1 -1
- package/runtime/node_modules/@metro-labs/telegram/src/media-actions.ts +1 -2
- package/runtime/node_modules/@metro-labs/telegram/src/reactions.ts +1 -1
- package/runtime/node_modules/@metro-labs/telegram-bot/src/accounts.ts +4 -37
- package/runtime/node_modules/@metro-labs/telegram-bot/src/actions.ts +7 -23
- package/runtime/node_modules/@metro-labs/telegram-bot/src/format.ts +1 -4
- package/runtime/node_modules/@metro-labs/telegram-bot/src/media-actions.ts +4 -9
- package/runtime/node_modules/@metro-labs/telegram-bot/src/profile.ts +3 -3
- package/runtime/node_modules/@metro-labs/threema/src/accounts.ts +0 -11
- package/runtime/node_modules/@metro-labs/threema/src/actions.ts +2 -12
- package/runtime/node_modules/@metro-labs/threema/src/files.ts +4 -15
- package/runtime/node_modules/@metro-labs/threema/src/format.ts +2 -7
- package/runtime/node_modules/@metro-labs/whatsapp/package.json +1 -2
- package/runtime/node_modules/@metro-labs/whatsapp/src/accounts.ts +5 -26
- package/runtime/node_modules/@metro-labs/whatsapp/src/actions.ts +5 -6
- package/runtime/node_modules/@metro-labs/whatsapp/src/format.ts +1 -3
- package/runtime/node_modules/@metro-labs/whatsapp/src/inbound.ts +1 -1
- package/runtime/node_modules/@metro-labs/xmtp/src/accounts.ts +1 -12
- package/runtime/node_modules/@metro-labs/xmtp/src/actions-close.ts +1 -1
- package/runtime/node_modules/@metro-labs/xmtp/src/actions-conv.ts +14 -5
- package/runtime/node_modules/@metro-labs/xmtp/src/actions-meta.ts +1 -1
- package/runtime/node_modules/@metro-labs/xmtp/src/actions.ts +31 -78
- package/runtime/node_modules/@metro-labs/xmtp/src/emit.ts +3 -4
- package/runtime/node_modules/@metro-labs/xmtp/src/index.ts +1 -6
- package/runtime/node_modules/@metro-labs/xmtp/src/profile.ts +1 -1
- package/runtime/node_modules/@metro-labs/xmtp/src/sender.ts +1 -1
- package/runtime/node_modules/@metro-labs/xmtp/src/tools-handlers.ts +1 -1
- package/runtime/node_modules/@metro-labs/xmtp/src/transcribe.ts +2 -2
- package/runtime/node_modules/@metro-labs/xmtp/src/wire.ts +0 -2
- package/runtime/runtime.json +1 -1
- package/runtime/node_modules/@metro-labs/core/src/identity.ts +0 -7
- package/runtime/node_modules/@metro-labs/daemon/src/approvals/needs.ts +0 -2
- package/runtime/node_modules/@metro-labs/daemon/src/channels/dedupe.ts +0 -12
- package/runtime/node_modules/@metro-labs/daemon/src/channels/react-note.ts +0 -13
- package/runtime/node_modules/@metro-labs/daemon/src/channels/reply-id.ts +0 -1
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/relay-target.ts +0 -29
- package/runtime/node_modules/@metro-labs/daemon/src/metro-user/api.ts +0 -43
- package/runtime/node_modules/@metro-labs/daemon/src/metro-user/move.ts +0 -165
- package/runtime/node_modules/@metro-labs/discord-bot/src/wire.ts +0 -1
- package/runtime/node_modules/@metro-labs/telegram/src/normalize.ts +0 -22
- package/runtime/node_modules/@metro-labs/telegram/src/wire.ts +0 -1
- package/runtime/node_modules/@metro-labs/telegram-bot/src/wire.ts +0 -1
- package/runtime/node_modules/@metro-labs/whatsapp/src/normalize.ts +0 -22
- 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';
|