@relaymessenger/cli 0.4.4 → 0.5.0-staging.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.
- package/README.md +108 -118
- package/dist/cli.js +2 -172
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +8 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +13 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +39 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +206 -0
- package/dist/config.js.map +1 -0
- package/dist/doctor.d.ts +20 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +73 -112
- package/dist/doctor.js.map +1 -1
- package/dist/event-listen.d.ts +11 -0
- package/dist/event-listen.d.ts.map +1 -0
- package/dist/event-listen.js +37 -0
- package/dist/event-listen.js.map +1 -0
- package/dist/output.d.ts +4 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +26 -0
- package/dist/output.js.map +1 -0
- package/dist/program.d.ts +14 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +655 -0
- package/dist/program.js.map +1 -0
- package/package.json +31 -37
- package/claude-plugin/marketplace/.claude-plugin/marketplace.json +0 -14
- package/claude-plugin/marketplace/plugins/relay/.claude-plugin/plugin.json +0 -27
- package/claude-plugin/marketplace/plugins/relay/LICENSE +0 -21
- package/claude-plugin/marketplace/plugins/relay/README.md +0 -173
- package/claude-plugin/marketplace/plugins/relay/commands/configure.md +0 -71
- package/claude-plugin/marketplace/plugins/relay/runtime/server.mjs +0 -26197
- package/dist/api.d.ts +0 -114
- package/dist/api.d.ts.map +0 -1
- package/dist/api.js +0 -162
- package/dist/api.js.map +0 -1
- package/dist/claude-settings.d.ts +0 -14
- package/dist/claude-settings.d.ts.map +0 -1
- package/dist/claude-settings.js +0 -47
- package/dist/claude-settings.js.map +0 -1
- package/dist/codex.d.ts +0 -25
- package/dist/codex.d.ts.map +0 -1
- package/dist/codex.js +0 -237
- package/dist/codex.js.map +0 -1
- package/dist/engine/acp.d.ts +0 -74
- package/dist/engine/acp.d.ts.map +0 -1
- package/dist/engine/acp.js +0 -413
- package/dist/engine/acp.js.map +0 -1
- package/dist/engine/catalog.d.ts +0 -26
- package/dist/engine/catalog.d.ts.map +0 -1
- package/dist/engine/catalog.js +0 -41
- package/dist/engine/catalog.js.map +0 -1
- package/dist/engine/process.d.ts +0 -12
- package/dist/engine/process.d.ts.map +0 -1
- package/dist/engine/process.js +0 -54
- package/dist/engine/process.js.map +0 -1
- package/dist/engine/types.d.ts +0 -57
- package/dist/engine/types.d.ts.map +0 -1
- package/dist/engine/types.js +0 -8
- package/dist/engine/types.js.map +0 -1
- package/dist/flags.d.ts +0 -9
- package/dist/flags.d.ts.map +0 -1
- package/dist/flags.js +0 -34
- package/dist/flags.js.map +0 -1
- package/dist/install.d.ts +0 -69
- package/dist/install.d.ts.map +0 -1
- package/dist/install.js +0 -513
- package/dist/install.js.map +0 -1
- package/dist/mcp.d.ts +0 -16
- package/dist/mcp.d.ts.map +0 -1
- package/dist/mcp.js +0 -127
- package/dist/mcp.js.map +0 -1
- package/dist/pair.d.ts +0 -20
- package/dist/pair.d.ts.map +0 -1
- package/dist/pair.js +0 -135
- package/dist/pair.js.map +0 -1
- package/dist/permissions.d.ts +0 -90
- package/dist/permissions.d.ts.map +0 -1
- package/dist/permissions.js +0 -361
- package/dist/permissions.js.map +0 -1
- package/dist/receive.d.ts +0 -113
- package/dist/receive.d.ts.map +0 -1
- package/dist/receive.js +0 -596
- package/dist/receive.js.map +0 -1
- package/dist/store.d.ts +0 -301
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -551
- package/dist/store.js.map +0 -1
- package/openclaw-plugin/relaymessenger-openclaw-plugin-0.3.3.tgz +0 -0
package/README.md
CHANGED
|
@@ -1,139 +1,129 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Relay CLI
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
Texts become prompts, replies come back as messages, and tool approvals arrive
|
|
7
|
-
as Allow/Deny cards you answer with a tap.
|
|
3
|
+
`@relaymessenger/cli` is the official terminal client for the current Relay
|
|
4
|
+
v1 Agent API. It delegates all Relay calls and response types to
|
|
5
|
+
`@relaymessenger/sdk`.
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
https://docs.relayapp.im.
|
|
7
|
+
## Install
|
|
11
8
|
|
|
12
|
-
|
|
9
|
+
```sh
|
|
10
|
+
npm install --global @relaymessenger/cli
|
|
11
|
+
relay --version
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Node.js 22.22.3 or newer is required. `relaymessenger` remains an executable
|
|
15
|
+
alias for existing installs.
|
|
16
|
+
|
|
17
|
+
## Authenticate
|
|
18
|
+
|
|
19
|
+
Create Agent Tokens in Relay Console. Tokens are accepted only from stdin,
|
|
20
|
+
the `RELAY_AGENT_TOKEN` environment variable, or an owner-only local profile;
|
|
21
|
+
there is deliberately no token command-line option.
|
|
13
22
|
|
|
14
23
|
```sh
|
|
15
|
-
|
|
24
|
+
printf '%s' "$RELAY_AGENT_TOKEN" | relay auth login --token-stdin
|
|
25
|
+
relay auth status
|
|
26
|
+
relay doctor
|
|
27
|
+
```
|
|
16
28
|
|
|
17
|
-
|
|
18
|
-
|
|
29
|
+
Profiles live in `${XDG_CONFIG_HOME:-~/.config}/relay/config.json`. The
|
|
30
|
+
directory is mode `0700` and the file is mode `0600` on POSIX systems.
|
|
19
31
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
32
|
+
```sh
|
|
33
|
+
relay profiles add staging --api-url https://api.staging.relayapp.im
|
|
34
|
+
relay profiles use staging
|
|
35
|
+
printf '%s' "$STAGING_RELAY_AGENT_TOKEN" |
|
|
36
|
+
relay auth login --profile staging --token-stdin
|
|
37
|
+
relay profiles list
|
|
23
38
|
```
|
|
24
39
|
|
|
25
|
-
|
|
26
|
-
messages) becomes one engine turn; the bridge shows a typing indicator while
|
|
27
|
-
the engine works and posts one finalized reply per turn.
|
|
40
|
+
Resolution order is:
|
|
28
41
|
|
|
29
|
-
|
|
42
|
+
1. `RELAY_AGENT_TOKEN`, `RELAY_API_URL`, and `RELAY_PROFILE`;
|
|
43
|
+
2. the selected local profile;
|
|
44
|
+
3. `https://api.relayapp.im` as the API URL.
|
|
30
45
|
|
|
31
|
-
|
|
32
|
-
| --- | --- |
|
|
33
|
-
| `relaymessenger pair` | `POST /v1/pairings`, shows a terminal QR + code, long-polls until you claim it in the app, stores the Agent Token in `~/.relaymessenger/config.json` (chmod 600) and pins your user id as the bridge owner (from `GET /v1/agents/me`; override with `RELAY_OWNER_USER_ID`). If owner lookup is interrupted after the token is saved, running the command again resumes that saved token without creating another agent. The token never appears on the phone. |
|
|
34
|
-
| `relaymessenger start` | Receive loop: long-polls `GET /v1/events`, drives the engine over ACP, replies via `POST /v1/messages` with an `Idempotency-Key`. Flags: `--engine claude\|codex\|hermes`, `--dir <path>`. Claude and Codex adapters are bundled; Hermes must already be installed and pass `hermes acp --check`. |
|
|
35
|
-
| `relaymessenger install-codex` | Run from a project root to opt in that project only. Merges, never clobbers, `[mcp_servers.relay]` + `notify` into `~/.codex/config.toml` (comments preserved; a `.bak` of the original is kept) and a `PermissionRequest` hook into `~/.codex/hooks.json`. Other projects are suppressed until installed separately. Codex gates untrusted hook handlers: the first run may ask you to trust the relaymessenger handler. |
|
|
36
|
-
| `relaymessenger install-claude` | After pairing, strictly validates the Claude plugin bundled in the installed npm package, persists its local marketplace under the paired account's private runtime directory, installs `relay@relaymessenger-bundled`, and writes the token/API origin/owner pin to `~/.claude/channels/relay/.env` with mode 600 without printing the token. It refuses to overwrite a different configured identity. |
|
|
37
|
-
| `relaymessenger install-openclaw` | After pairing, persists the OpenClaw plugin archive bundled in the npm package and installs it through OpenClaw's managed `npm-pack:` path, adds only Relay's plugin/channel fields to `~/.openclaw/openclaw.json`, and writes the paired token to an owner-only file. Existing unrelated config is preserved and a different configured identity is refused. |
|
|
38
|
-
| `relaymessenger doctor` | Checks Node, pairing, token file permissions, API reachability, installed adapter pins, and durable-state health. |
|
|
46
|
+
Plain HTTP API URLs are rejected except for loopback development origins.
|
|
39
47
|
|
|
40
|
-
##
|
|
48
|
+
## Resource commands
|
|
41
49
|
|
|
42
|
-
|
|
43
|
-
with curl:
|
|
50
|
+
Every command prints JSON.
|
|
44
51
|
|
|
45
52
|
```sh
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
relay chats list --limit 20
|
|
54
|
+
relay chats get "$CHAT_ID"
|
|
55
|
+
relay chats messages list "$CHAT_ID" --limit 50
|
|
56
|
+
relay chats messages send "$CHAT_ID" --text "Hello" \
|
|
57
|
+
--idempotency-key "$(uuidgen)"
|
|
58
|
+
relay messages send --to advait --text "Hello" \
|
|
59
|
+
--idempotency-key "$(uuidgen)"
|
|
60
|
+
relay messages react "$MESSAGE_ID" --operation add --type love
|
|
61
|
+
relay chats typing start "$CHAT_ID"
|
|
62
|
+
relay chats read "$CHAT_ID"
|
|
63
|
+
|
|
64
|
+
relay contact-card get
|
|
65
|
+
relay contact-card setup --handle weather.acme --first-name Weather
|
|
66
|
+
relay contact-card share "$CHAT_ID"
|
|
67
|
+
relay contact-requests create advait
|
|
68
|
+
|
|
69
|
+
relay attachments upload ./report.pdf --content-type application/pdf
|
|
70
|
+
relay blocked-handles list
|
|
71
|
+
relay webhooks events
|
|
72
|
+
relay webhooks subscriptions list
|
|
56
73
|
```
|
|
57
74
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
engine/provider variables, not the complete parent environment. Hermes is
|
|
64
|
-
launched shell-free through its installed `hermes acp` stdio server and is
|
|
65
|
-
checked with `hermes acp --check`. Conversation → session bindings persist
|
|
66
|
-
in the paired account's runtime directory, so a conversation keeps its
|
|
67
|
-
engine context. OpenClaw is deliberately separate: `install-openclaw`
|
|
68
|
-
installs a native channel plugin into OpenClaw rather than pretending it is
|
|
69
|
-
an ACP coding-engine preset.
|
|
70
|
-
- **Approvals**: an engine `session/request_permission` becomes a Relay
|
|
71
|
-
message with a text part plus an `agent_permission_request` data part
|
|
72
|
-
(origin-tagged Allow/Deny options). Tap an option or text
|
|
73
|
-
`yes <id>` / `no <id>`. The full security-relevant tool input and affected
|
|
74
|
-
paths must fit in the card; an operation that cannot be represented in full
|
|
75
|
-
is denied instead of shown partially. No answer within 10 minutes → deny.
|
|
76
|
-
- **Owner gate**: only the user pinned at pair time can prompt the engine or
|
|
77
|
-
answer an approval card; messages from anyone else are ignored before their
|
|
78
|
-
content is interpreted.
|
|
79
|
-
- **Reliability**: the receive cursor advances only in the same atomic
|
|
80
|
-
(fsync + rename) write that persists the event queue
|
|
81
|
-
(`~/.relaymessenger/accounts/<origin-agent-hash>/state.json`), event ids are deduped, rapid messages debounce
|
|
82
|
-
~800 ms into one turn, and the poll loop restarts with capped exponential
|
|
83
|
-
backoff + jitter. Each pending approval is its own create-once file under
|
|
84
|
-
that account's `approvals/`, so a bridge restart cannot lose one and no two
|
|
85
|
-
processes ever rewrite a shared snapshot. Engine/tool turns are at-most-once:
|
|
86
|
-
an attempt marker is durable before execution, so a crash never silently
|
|
87
|
-
repeats a deploy, deletion, command, or external send. Completed replies use
|
|
88
|
-
a durable outbox and stable idempotency key, so delivery can retry without
|
|
89
|
-
rerunning those tools. An interrupted turn is reported and must be retried
|
|
90
|
-
explicitly by the owner.
|
|
91
|
-
- Long-poll is exclusive: an enabled webhook endpoint or a second poller gets
|
|
92
|
-
`409` (Telegram semantics). One consumer per token. A `401` stops the loop
|
|
93
|
-
with re-pair guidance instead of retrying.
|
|
94
|
-
- **Codex notification privacy**: `install-codex` stores an explicit local
|
|
95
|
-
allowlist entry for the current project root in
|
|
96
|
-
`~/.relaymessenger/codex-notify.json`. A completed turn from any other project is
|
|
97
|
-
suppressed. For an allowed project, Relay receives the project directory's
|
|
98
|
-
basename plus Codex's complete `last-assistant-message`; input messages and
|
|
99
|
-
the absolute working-directory path are not sent. That text is retained in
|
|
100
|
-
Relay message history. There is no global-all-projects opt-in; run
|
|
101
|
-
`install-codex` in each
|
|
102
|
-
project you choose to disclose.
|
|
103
|
-
- **Codex MCP sends**: `relay_send_message` requires a caller-chosen stable
|
|
104
|
-
`send_id`. Reuse the same `send_id`, conversation, and text only after an
|
|
105
|
-
unknown outcome; a changed payload is rejected. The mapping and
|
|
106
|
-
idempotency key live in the paired account's private runtime directory, so
|
|
107
|
-
a process restart cannot turn one logical send into two messages.
|
|
108
|
-
|
|
109
|
-
## Development and testing
|
|
110
|
-
|
|
111
|
-
- `RELAY_API_ORIGIN` points `pair`, `start`, and `doctor` at a
|
|
112
|
-
non-production Relay API origin, e.g. a local dev server:
|
|
113
|
-
`RELAY_API_ORIGIN=http://127.0.0.1:8787 relaymessenger pair`. This is a
|
|
114
|
-
development/testing mechanism only, production
|
|
115
|
-
(`https://api.relayapp.im`) stays the default, the value must be an
|
|
116
|
-
origin with no path/query/credentials, and plain HTTP is accepted only
|
|
117
|
-
for loopback hosts (same rule as every other origin the bridge uses).
|
|
118
|
-
Durable bridge state is scoped per effective origin, so an override
|
|
119
|
-
never replays or advances production cursors and ledgers.
|
|
120
|
-
- With `--engine claude`, the bundled adapter inherits your Claude Code
|
|
121
|
-
settings. If the resolved `permissions.defaultMode` is
|
|
122
|
-
`bypassPermissions`, the engine never asks for approval, so phone
|
|
123
|
-
Allow/Deny cards will not appear; `relaymessenger start` and `relaymessenger doctor`
|
|
124
|
-
print a warning when they detect this.
|
|
125
|
-
|
|
126
|
-
## Files
|
|
75
|
+
Run `relay --help` and each command group's `--help` for the full current
|
|
76
|
+
surface: Chats, Messages, Attachments, blocked Handles, webhook events and
|
|
77
|
+
subscriptions, Contact Cards, and Contact requests.
|
|
78
|
+
|
|
79
|
+
## Local event forwarding
|
|
127
80
|
|
|
81
|
+
`relay events listen` is a development convenience backed only by the SDK's
|
|
82
|
+
source-backed Agent WebSocket. It refuses Relay's production API, requires an
|
|
83
|
+
explicit profile, and requires confirmation that the profile belongs to a
|
|
84
|
+
dedicated non-production Agent whose durable checkpoint may advance:
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
relay --profile staging events listen --acknowledge-events
|
|
88
|
+
relay --profile staging events listen --acknowledge-events \
|
|
89
|
+
--forward-to http://127.0.0.1:3000/relay-events
|
|
128
90
|
```
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
91
|
+
|
|
92
|
+
Forward destinations must be loopback HTTP(S). Forwarded bodies are the
|
|
93
|
+
original Relay event envelopes but are **unsigned** and carry
|
|
94
|
+
`x-relay-dev-forwarded: 1`; this is not a substitute for testing Standard
|
|
95
|
+
Webhooks signature verification. A non-2xx local response is not acknowledged,
|
|
96
|
+
so Relay can redeliver it. Local receivers must deduplicate by `event_id`.
|
|
97
|
+
|
|
98
|
+
The listener refuses a FULL-sync request rather than falsely claiming it
|
|
99
|
+
rebuilt durable state. It also cannot run while the Agent has webhook
|
|
100
|
+
subscriptions because Relay makes those delivery modes exclusive. Never point
|
|
101
|
+
it at an Agent whose checkpoint is owned by another consumer.
|
|
102
|
+
|
|
103
|
+
## Doctor
|
|
104
|
+
|
|
105
|
+
`relay doctor` checks the Node runtime, API URL, token resolution, local file
|
|
106
|
+
permissions, SDK contract availability, and a read-only API request.
|
|
107
|
+
`relay doctor --offline` skips only the network request and is suitable for
|
|
108
|
+
package-install checks.
|
|
109
|
+
|
|
110
|
+
## Security
|
|
111
|
+
|
|
112
|
+
- Keep Agent Tokens out of source, URLs, shell arguments, and logs.
|
|
113
|
+
- Prefer secret-manager injection through `RELAY_AGENT_TOKEN` in automation.
|
|
114
|
+
- Output and error paths redact every locally resolvable token.
|
|
115
|
+
- This package has no coding-agent runtime, pairing flow, or hidden private
|
|
116
|
+
API client.
|
|
117
|
+
|
|
118
|
+
## Development
|
|
119
|
+
|
|
120
|
+
All Linux execution happens in a fresh Daytona sandbox:
|
|
121
|
+
|
|
122
|
+
```sh
|
|
123
|
+
npm ci
|
|
124
|
+
npm run validate
|
|
137
125
|
```
|
|
138
126
|
|
|
139
|
-
|
|
127
|
+
`validate` performs type checking, unit and negative tests, the pinned SDK
|
|
128
|
+
operation-hash check, boundary checks, package packing, isolated tarball
|
|
129
|
+
installation, and installed-bin doctor smoke tests.
|
package/dist/cli.js
CHANGED
|
@@ -1,174 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*
|
|
5
|
-
* relaymessenger pair [--engine <preset>] [--name <device-name>]
|
|
6
|
-
* relaymessenger start [--engine <preset>] [--dir <path>]
|
|
7
|
-
* relaymessenger install-codex
|
|
8
|
-
* relaymessenger install-claude
|
|
9
|
-
* relaymessenger install-openclaw
|
|
10
|
-
* relaymessenger doctor
|
|
11
|
-
*
|
|
12
|
-
* Internal entrypoints (wired by install-codex): notify, mcp,
|
|
13
|
-
* hook permission-request.
|
|
14
|
-
*/
|
|
15
|
-
import { resolveApiOrigin, RelayClient } from "./api.js";
|
|
16
|
-
import { claudeBypassWarning } from "./claude-settings.js";
|
|
17
|
-
import { notifyCommand, permissionRequestHook } from "./codex.js";
|
|
18
|
-
import { doctor } from "./doctor.js";
|
|
19
|
-
import { AcpEngine } from "./engine/acp.js";
|
|
20
|
-
import { ENGINE_HELP, enginePermissionTimeoutMs } from "./engine/catalog.js";
|
|
21
|
-
import { installClaude, installCodex, installOpenClaw } from "./install.js";
|
|
22
|
-
import { parseFlags } from "./flags.js";
|
|
23
|
-
import { mcpServe } from "./mcp.js";
|
|
24
|
-
import { pair } from "./pair.js";
|
|
25
|
-
import { PermissionBroker } from "./permissions.js";
|
|
26
|
-
import { ReceiveLoop } from "./receive.js";
|
|
27
|
-
import { ApprovalStore, ConfigStore, resolveOwnerUserId, RuntimeLock, runtimeHomeForConfig, SessionStore, StateStore, } from "./store.js";
|
|
28
|
-
const USAGE = `relaymessenger — bridge your local coding agent to Relay (https://relayapp.im)
|
|
29
|
-
|
|
30
|
-
relaymessenger pair pair this machine with the Relay app (QR + code)
|
|
31
|
-
relaymessenger start receive messages and drive the engine
|
|
32
|
-
--engine <preset> (default claude)
|
|
33
|
-
presets: ${ENGINE_HELP}
|
|
34
|
-
--dir <path> working directory for engine sessions
|
|
35
|
-
relaymessenger install-codex wire Codex notify + phone approvals + MCP server
|
|
36
|
-
relaymessenger install-claude point at the Claude Code channel plugin
|
|
37
|
-
relaymessenger install-openclaw install and configure the bundled OpenClaw plugin
|
|
38
|
-
relaymessenger doctor health checks
|
|
39
|
-
relaymessenger version print the installed version
|
|
40
|
-
|
|
41
|
-
Docs: https://docs.relayapp.im/quickstart`;
|
|
42
|
-
async function main() {
|
|
43
|
-
const [command, ...restArgv] = process.argv.slice(2);
|
|
44
|
-
const flags = parseFlags(restArgv);
|
|
45
|
-
const log = (line) => console.error(`[relaymessenger] ${line}`);
|
|
46
|
-
switch (command) {
|
|
47
|
-
case "pair": {
|
|
48
|
-
// RELAY_API_ORIGIN is a development/testing override; production default.
|
|
49
|
-
const origin = resolveApiOrigin();
|
|
50
|
-
await pair({ origin, engine: flags.engine, deviceName: flags.name });
|
|
51
|
-
return 0;
|
|
52
|
-
}
|
|
53
|
-
case "start": {
|
|
54
|
-
const config = new ConfigStore().load();
|
|
55
|
-
if (!config?.agent_token) {
|
|
56
|
-
console.error("Not paired. Run `relaymessenger pair` first.");
|
|
57
|
-
return 1;
|
|
58
|
-
}
|
|
59
|
-
const ownerUserId = resolveOwnerUserId(config); // fail closed without a pinned owner
|
|
60
|
-
// RELAY_API_ORIGIN (development/testing) overrides the paired origin.
|
|
61
|
-
const origin = resolveApiOrigin(config.api_origin);
|
|
62
|
-
const client = new RelayClient(origin, config.agent_token);
|
|
63
|
-
// Scope durable state to the effective origin so an override never
|
|
64
|
-
// replays or advances the paired production cursor/ledgers.
|
|
65
|
-
const runtimeHome = runtimeHomeForConfig({ ...config, api_origin: origin });
|
|
66
|
-
if (flags.engine === "claude") {
|
|
67
|
-
const bypass = claudeBypassWarning(flags.dir ?? process.cwd());
|
|
68
|
-
if (bypass)
|
|
69
|
-
log(`warning: ${bypass}`);
|
|
70
|
-
}
|
|
71
|
-
const runtimeLock = new RuntimeLock(runtimeHome);
|
|
72
|
-
// Acquire before any state/session/approval object can read or rewrite
|
|
73
|
-
// whole-file ledgers for this paired identity.
|
|
74
|
-
runtimeLock.acquire();
|
|
75
|
-
try {
|
|
76
|
-
const state = new StateStore(runtimeHome);
|
|
77
|
-
const sessions = new SessionStore(runtimeHome);
|
|
78
|
-
const approvals = new ApprovalStore(runtimeHome);
|
|
79
|
-
const engine = new AcpEngine(flags.engine, sessions, log);
|
|
80
|
-
const broker = new PermissionBroker(client, approvals, enginePermissionTimeoutMs(flags.engine), log);
|
|
81
|
-
const loop = new ReceiveLoop(client, state, engine, broker, {
|
|
82
|
-
ownerUserId,
|
|
83
|
-
cwd: flags.dir ?? process.cwd(),
|
|
84
|
-
log,
|
|
85
|
-
});
|
|
86
|
-
let shuttingDown;
|
|
87
|
-
const shutdown = () => {
|
|
88
|
-
if (shuttingDown)
|
|
89
|
-
return shuttingDown;
|
|
90
|
-
shuttingDown = (async () => {
|
|
91
|
-
log("shutting down…");
|
|
92
|
-
loop.stop();
|
|
93
|
-
// Dispose first: this rejects/aborts any live engine turn so settle()
|
|
94
|
-
// cannot wait forever on a child process we intend to terminate.
|
|
95
|
-
await engine.dispose();
|
|
96
|
-
await loop.settle();
|
|
97
|
-
runtimeLock.release();
|
|
98
|
-
process.exit(0);
|
|
99
|
-
})();
|
|
100
|
-
return shuttingDown;
|
|
101
|
-
};
|
|
102
|
-
process.on("SIGINT", shutdown);
|
|
103
|
-
process.on("SIGTERM", shutdown);
|
|
104
|
-
log(`bridge running: engine=${flags.engine} dir=${flags.dir ?? process.cwd()} api=${origin}`);
|
|
105
|
-
try {
|
|
106
|
-
await loop.run();
|
|
107
|
-
}
|
|
108
|
-
finally {
|
|
109
|
-
// Fatal loop exits (409/401 throws) must not leave a detached engine
|
|
110
|
-
// process group running without its bridge.
|
|
111
|
-
loop.stop();
|
|
112
|
-
await engine.dispose().catch(() => { });
|
|
113
|
-
}
|
|
114
|
-
return 0;
|
|
115
|
-
}
|
|
116
|
-
finally {
|
|
117
|
-
runtimeLock.release();
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
case "install-codex":
|
|
121
|
-
installCodex();
|
|
122
|
-
return 0;
|
|
123
|
-
case "install-claude":
|
|
124
|
-
installClaude();
|
|
125
|
-
return 0;
|
|
126
|
-
case "install-openclaw":
|
|
127
|
-
installOpenClaw();
|
|
128
|
-
return 0;
|
|
129
|
-
case "doctor":
|
|
130
|
-
return (await doctor()) ? 0 : 1;
|
|
131
|
-
case "notify":
|
|
132
|
-
await notifyCommand(restArgv);
|
|
133
|
-
return 0;
|
|
134
|
-
case "mcp":
|
|
135
|
-
await mcpServe();
|
|
136
|
-
return 0;
|
|
137
|
-
case "hook": {
|
|
138
|
-
if (flags.rest[0] !== "permission-request") {
|
|
139
|
-
console.error(`unknown hook: ${flags.rest[0] ?? "(none)"}`);
|
|
140
|
-
return 1;
|
|
141
|
-
}
|
|
142
|
-
return await permissionRequestHook();
|
|
143
|
-
}
|
|
144
|
-
case "version":
|
|
145
|
-
case "--version":
|
|
146
|
-
case "-v": {
|
|
147
|
-
// A published CLI that cannot state its own version leaves a bug report
|
|
148
|
-
// with nothing to anchor on. Read the manifest rather than a constant, so
|
|
149
|
-
// it cannot drift from what npm actually installed.
|
|
150
|
-
const { createRequire } = await import("node:module");
|
|
151
|
-
const manifest = createRequire(import.meta.url)("../package.json");
|
|
152
|
-
console.log(manifest.version);
|
|
153
|
-
return 0;
|
|
154
|
-
}
|
|
155
|
-
case undefined:
|
|
156
|
-
case "help":
|
|
157
|
-
case "--help":
|
|
158
|
-
case "-h":
|
|
159
|
-
console.log(USAGE);
|
|
160
|
-
return 0;
|
|
161
|
-
default:
|
|
162
|
-
console.error(`unknown command: ${command}\n`);
|
|
163
|
-
console.log(USAGE);
|
|
164
|
-
return 1;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
main().then((code) => {
|
|
168
|
-
if (code !== 0)
|
|
169
|
-
process.exitCode = code;
|
|
170
|
-
}, (error) => {
|
|
171
|
-
console.error(`relaymessenger: ${error?.message ?? error}`);
|
|
172
|
-
process.exitCode = 1;
|
|
173
|
-
});
|
|
2
|
+
import { runCLI } from "./program.js";
|
|
3
|
+
process.exitCode = await runCLI(process.argv.slice(2));
|
|
174
4
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,CAAC,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import Relay from "@relaymessenger/sdk";
|
|
2
|
+
import type { ConfigContext, ResolvedAuth } from "./config.js";
|
|
3
|
+
export interface ClientContext {
|
|
4
|
+
client: Relay;
|
|
5
|
+
auth: ResolvedAuth;
|
|
6
|
+
}
|
|
7
|
+
export declare const createClientContext: (profile?: string, configContext?: ConfigContext) => Promise<ClientContext>;
|
|
8
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,qBAAqB,CAAC;AACxC,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG/D,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,KAAK,CAAC;IACd,IAAI,EAAE,YAAY,CAAC;CACpB;AAED,eAAO,MAAM,mBAAmB,GAC9B,UAAU,MAAM,EAChB,gBAAe,aAAkB,KAChC,OAAO,CAAC,aAAa,CASvB,CAAC"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import Relay from "@relaymessenger/sdk";
|
|
2
|
+
import { resolveAuth } from "./config.js";
|
|
3
|
+
export const createClientContext = async (profile, configContext = {}) => {
|
|
4
|
+
const auth = await resolveAuth(profile, configContext);
|
|
5
|
+
return {
|
|
6
|
+
auth,
|
|
7
|
+
client: new Relay({
|
|
8
|
+
apiKey: auth.token,
|
|
9
|
+
baseURL: auth.apiURL,
|
|
10
|
+
}),
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,qBAAqB,CAAC;AAExC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EACtC,OAAgB,EAChB,gBAA+B,EAAE,EACT,EAAE;IAC1B,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IACvD,OAAO;QACL,IAAI;QACJ,MAAM,EAAE,IAAI,KAAK,CAAC;YAChB,MAAM,EAAE,IAAI,CAAC,KAAK;YAClB,OAAO,EAAE,IAAI,CAAC,MAAM;SACrB,CAAC;KACH,CAAC;AACJ,CAAC,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export declare const DEFAULT_API_URL = "https://api.relayapp.im";
|
|
2
|
+
export declare const DEFAULT_PROFILE = "default";
|
|
3
|
+
export interface RelayProfile {
|
|
4
|
+
api_url?: string;
|
|
5
|
+
agent_token?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface RelayConfig {
|
|
8
|
+
version: 1;
|
|
9
|
+
current_profile: string;
|
|
10
|
+
profiles: Record<string, RelayProfile>;
|
|
11
|
+
}
|
|
12
|
+
export interface ConfigContext {
|
|
13
|
+
env?: NodeJS.ProcessEnv;
|
|
14
|
+
home?: string;
|
|
15
|
+
platform?: NodeJS.Platform;
|
|
16
|
+
}
|
|
17
|
+
export interface ResolvedAuth {
|
|
18
|
+
profile: string;
|
|
19
|
+
apiURL: string;
|
|
20
|
+
token: string;
|
|
21
|
+
tokenSource: "environment" | "profile";
|
|
22
|
+
configPath: string;
|
|
23
|
+
}
|
|
24
|
+
export declare const configPath: (context?: ConfigContext) => string;
|
|
25
|
+
export declare const emptyConfig: () => RelayConfig;
|
|
26
|
+
export declare const readConfig: (context?: ConfigContext) => Promise<RelayConfig>;
|
|
27
|
+
export declare const writeConfig: (config: RelayConfig, context?: ConfigContext) => Promise<void>;
|
|
28
|
+
export declare const validateProfileName: (name: string) => string;
|
|
29
|
+
export declare const validateApiURL: (input: string) => string;
|
|
30
|
+
export declare const validateForwardURL: (input: string) => string;
|
|
31
|
+
export declare const validateToken: (value: string) => string;
|
|
32
|
+
export declare const resolveAuth: (requestedProfile?: string, context?: ConfigContext) => Promise<ResolvedAuth>;
|
|
33
|
+
export declare const inspectConfigPermissions: (context?: ConfigContext) => Promise<{
|
|
34
|
+
exists: boolean;
|
|
35
|
+
secure: boolean;
|
|
36
|
+
mode?: number;
|
|
37
|
+
}>;
|
|
38
|
+
export declare const collectConfiguredTokens: (context?: ConfigContext) => Promise<string[]>;
|
|
39
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,eAAe,4BAA4B,CAAC;AACzD,eAAO,MAAM,eAAe,YAAY,CAAC;AAEzC,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,CAAC,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,aAAa,GAAG,SAAS,CAAC;IACvC,UAAU,EAAE,MAAM,CAAC;CACpB;AAKD,eAAO,MAAM,UAAU,GAAI,UAAS,aAAkB,KAAG,MAYxD,CAAC;AAEF,eAAO,MAAM,WAAW,QAAO,WAM7B,CAAC;AA0CH,eAAO,MAAM,UAAU,GACrB,UAAS,aAAkB,KAC1B,OAAO,CAAC,WAAW,CAiBrB,CAAC;AAEF,eAAO,MAAM,WAAW,GACtB,QAAQ,WAAW,EACnB,UAAS,aAAkB,KAC1B,OAAO,CAAC,IAAI,CAuBd,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,KAAG,MAOlD,CAAC;AAQF,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MAoB9C,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,KAAG,MAgBlD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,KAAG,MAM7C,CAAC;AAEF,eAAO,MAAM,WAAW,GACtB,mBAAmB,MAAM,EACzB,UAAS,aAAkB,KAC1B,OAAO,CAAC,YAAY,CA2BtB,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,UAAS,aAAkB,KAC1B,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAkB7D,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,UAAS,aAAkB,KAC1B,OAAO,CAAC,MAAM,EAAE,CAQlB,CAAC"}
|