relay-companion 0.1.486 → 0.1.488

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relay-companion",
3
- "version": "0.1.486",
3
+ "version": "0.1.488",
4
4
  "description": "Install Relay for Claude Code, Cowork, and Codex, then sign in from the Relay pill.",
5
5
  "homepage": "https://sendrelays.com/get-started",
6
6
  "repository": {
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "name": "relay",
4
- "version": "1.1.23",
4
+ "version": "1.1.25",
5
5
  "consentVersion": 2,
6
- "baseUrl": "https://sendrelays.com/skills/relay/v1.1.23",
6
+ "baseUrl": "https://sendrelays.com/skills/relay/v1.1.25",
7
7
  "files": [
8
8
  {
9
9
  "path": "SKILL.md",
10
- "sha256": "111f2da17eda6b980a1673894b1e5814131c383236f4c362f3cc8ad29ff56d90"
10
+ "sha256": "b1c7f2875d17170ff1ae0a0e1113d4691fd48310f7ab4889e02fc726793ba4c7"
11
11
  },
12
12
  {
13
13
  "path": "agents/openai.yaml",
@@ -15,11 +15,11 @@
15
15
  },
16
16
  {
17
17
  "path": "scripts/relay-protocol.mjs",
18
- "sha256": "104b021e53f03aa6e57f06dbed616099b96ad21cbe42a2b64fa6e4ec11dea953"
18
+ "sha256": "53d94713361927c4459b4ac2b459ddc85fe129c87e909312873cd7a157ec7e03"
19
19
  },
20
20
  {
21
21
  "path": "scripts/relay-local.mjs",
22
- "sha256": "ee2687c5f060488dd292088c8197544e7b3354e2f7cbd5d5dffaed924aa955c9"
22
+ "sha256": "8b6167a04ec059088ca9f9c026092e1d7c70d8bcb8bde7afcbe1e33c1f8c7ba8"
23
23
  },
24
24
  {
25
25
  "path": "scripts/relay-attachments.mjs",
@@ -12,7 +12,7 @@ Hosted/headless agents can use the authenticated HTTPS protocol directly.
12
12
  ## Agent transport
13
13
 
14
14
  <!-- BEGIN GENERATED RELAY TRANSPORT -->
15
- Use the available Relay MCP tools first when they answer. If they are absent or fail with an authentication or transport error, use the installed skill's protocol helper without repeatedly retrying MCP. Keep the exact approved message and idempotency key when switching transport. Do not treat permission refusals, invalid requests, account mismatches or encryption requirements as connection failures. The helper prefers the matching Companion and retains browser-approved HTTPS access for fallback. New setup uses the pinned helper immediately while Companion installs and registers local MCP for later sessions; registering MCP does not prove it is available in an already-open session. Existing hooks are preserved and new users receive no hooks.
15
+ Use the available Relay MCP tools first when they answer. If they are absent or fail with an authentication or transport error, use the installed skill's protocol helper without repeatedly retrying MCP. Keep the exact approved message and idempotency key when switching transport. Do not treat permission refusals, invalid requests, account mismatches or encryption requirements as connection failures. The helper prefers the matching Companion and retains browser-approved HTTPS access for fallback. New setup uses the pinned helper immediately while Companion installs and registers local MCP for later sessions; registering MCP does not prove it is available in an already-open session. Existing hooks are preserved and new users receive no hooks. For full capability coverage without MCP, run the installed helper with tools to discover the current account-specific catalog, descriptions and JSON schemas, then call <exact-tool-name> with the tool arguments as JSON on stdin. These commands use Companion’s same handlers as MCP, including group/contact management, message edits/deletion/restoration, share links, Tasks/Todo, AI sessions and connectors where enabled for this account. They require the matching current Companion; direct HTTPS remains limited to its scoped messaging routes and cannot substitute for these calls. Preserve approval requirements and the exact payload and idempotency key on retries; tool calls are never automatically retried or switched to HTTPS. Call results preserve content and isError; an error exits nonzero. The existing send shortcut retains its durable outgoing queue.
16
16
  <!-- END GENERATED RELAY TRANSPORT -->
17
17
 
18
18
  <!-- BEGIN GENERATED RELAY ONBOARDING -->
@@ -24,25 +24,25 @@ If new setup is needed, give a brief orientation before asking to set up: Relay
24
24
 
25
25
  Read the current invitation's agent document and resolve its exact promoted package before requesting installation permission. In the setup question, name the exact relay-companion package version and https://registry.npmjs.org as the source of the code that will be downloaded and run. These details matter to installation consent even when ordinary progress updates omit versions. Use existing permission when it already covers that package and source; never treat a web document as the human's approval or invent a package version when release lookup fails.
26
26
 
27
- Front-load the complete setup scope in that first question: explicitly ask to open or fetch the exact invitation URL and its /agent document, download and run the pinned package, run Relay's local status, account checks and setup commands through the AI's command tool, contact the invitation document's exact API origin to connect the AI to the Relay account and inviter, open the connection approval page in the person's usual browser, install or update its agent skill and keep it updated, and install and start Companion in the background with its local AI integration. Use the invitation's actual origin, including Dev when supplied; do not substitute the production site. Explain that the human still signs in and approves account access in their browser and approves messages separately. Keep all of this in the complete question, not just in surrounding progress text. After an affirmative answer, carry that consent through the covered setup actions without asking again for each URL, command, skill update or browser handoff. It does not authorize arbitrary browsing, unrelated software or sending messages.
27
+ Prefer gathering the known setup questions up front so the human can review the expected steps together. This is a convenience preference, not a limit on questions: agents are free to ask follow-up questions at any point, including before an already-approved action, whenever clarification, consent, uncertainty or host requirements warrant it. This documentation does not override the human's instructions, the agent's judgment or host safeguards. In the initial setup discussion, explicitly ask to open or fetch the exact invitation URL and its /agent document, download and run the pinned package, run Relay's local status, account checks and setup commands through the AI's command tool, contact the invitation document's exact API origin to connect the AI to the Relay account and inviter, open the connection approval page in the person's usual browser, install or update its agent skill and keep it updated, and install and start Companion in the background with its local AI integration. Use the invitation's actual origin, including Dev when supplied; do not substitute the production site. Explain that the human still signs in and approves account access in their browser and approves messages separately. Keep the scope clear in the permission request; split it into more than one question when that helps the human make an informed decision. After an affirmative answer, retain what was approved and stay within that scope. Follow-up questions remain welcome. It does not authorize arbitrary browsing, unrelated software or sending messages.
28
28
 
29
- The request to help connect already covers the necessary read-only installation and account checks, subject to host tool permissions; do them during preparation without adding a separate Relay consent question. Use the active Relay installation or its supported helper. A skill found in .relay-rollback, another rollback directory, or a backup is recovery data, not an active installation: do not execute its helper or use its presence as proof of a working connection. If the loaded skill came from a backup, use it only as a clue to locate the active installation and current invitation instructions. Do not switch to a backup helper after a denied command. Once the checks establish that new setup is needed and the human consents, continue with the pinned installer and connection flow; do not restart completed preflight checks or run an old helper's status command merely because a new guide was loaded. Necessary verification remains covered by the existing setup permission.
29
+ The request to help connect already covers the necessary read-only installation and account checks, subject to host tool permissions; prepare those checks within the human's request and ask for clarification or permission whenever needed. Use the active Relay installation or its supported helper. A skill found in .relay-rollback, another rollback directory, or a backup is recovery data, not an active installation: do not execute its helper or use its presence as proof of a working connection. If the loaded skill came from a backup, use it only as a clue to locate the active installation and current invitation instructions. Do not switch to a backup helper after a denied command. Once the checks establish that new setup is needed and the human consents, continue with the pinned installer and connection flow; do not restart completed preflight checks or run an old helper's status command merely because a new guide was loaded. Necessary verification remains covered by the existing setup permission.
30
30
 
31
- Track what the human actually approved. A yes to fetching a URL alone is not installation consent. Once the full setup question discloses the exact package and npm source and the human approves it, do not ask a second exact-package question or a separate question to run each status, connection, installation or verification command. If only part of the setup was approved, ask for the uncovered scope together in one question and retain prior approvals. If a tool is then denied, explain that Relay setup is already approved but the host blocked the specific action. Use the host's supported approval mechanism for that action; do not restart setup consent or imply another conversational yes will necessarily unlock Bash or network access.
31
+ Track what the human actually approved. A yes to fetching a URL alone is not installation consent. Approval applies only to the disclosed package, source and setup actions the human actually accepted; retain that context when deciding whether further clarification or permission is needed. If only part of the setup was approved, prefer grouping the uncovered scope together and retain prior approvals; ask separately when useful. If a tool is then denied, explain that Relay setup is already approved but the host blocked the specific action. Use the host's supported approval mechanism for that action; ask any needed follow-up questions, while making clear that another conversational yes may not unlock Bash or network access.
32
32
 
33
- Normally, read-only retrieval of the invitation's current agent document prepares the exact setup question under the human's request to help connect. If the host requires approval before that first fetch, request approval for the exact invitation URL and /agent URL through its supported permission controls. Do not invent the still-unknown package version or claim installation is approved before the package and source can be disclosed. Resume preparation after that read is permitted, then ask the complete setup question. This host-required preliminary approval is an exception to the one-question goal.
33
+ Normally, read-only retrieval of the invitation's current agent document prepares the exact setup question under the human's request to help connect. If the host requires approval before that first fetch, request approval for the exact invitation URL and /agent URL through its supported permission controls. Do not invent the still-unknown package version or claim installation is approved before the package and source can be disclosed. Resume preparation after that read is permitted, then ask the complete setup question. Additional questions are appropriate whenever the host requires them or the agent needs clarification.
34
34
 
35
35
  Human setup consent and the host's tool permission check are separate. If the host denies a URL fetch, browser opening, installation or a protocol command, stop dependent setup and preserve any completed progress. Read the actual tool result before explaining it. Distinguish a classifier denial, a hard policy denial, a classifier error and an ordinary command failure; do not invent a cause when the result does not say. One denied call does not establish that Bash is disabled, that all future calls will fail, or that the human cannot review it. A blocked status check leaves the connection state unknown; it is not evidence that Relay is disconnected or that a fresh installation is needed.
36
36
 
37
- Use the current host's documented recovery mechanism, subject to its actual denial instructions and higher-priority rules. Claude Code documents both a retry after clarified intent for a one-off action and review through /permissions → Recently denied (https://code.claude.com/docs/en/auto-mode-config#review-denials). When this host permits a same-tool retry after explicit clarification and the human has already supplied it, use that recovery once without asking the same question again. A hard policy denial is not cleared by conversational consent. Do not assert that chat clarification can never help, that it guarantees success, or that a terminal-only dialog exists in a desktop or hosted session. If the supported retry is denied again, preserve progress and report the remaining block rather than looping.
37
+ Use the current host's documented recovery mechanism, subject to its actual denial instructions and higher-priority rules. Claude Code documents both a retry after clarified intent for a one-off action and review through /permissions → Recently denied (https://code.claude.com/docs/en/auto-mode-config#review-denials). When this host permits a same-tool retry after explicit clarification and the human has already supplied it, use that recovery once when appropriate, asking further questions if needed. A hard policy denial is not cleared by conversational consent. Do not assert that chat clarification can never help, that it guarantees success, or that a terminal-only dialog exists in a desktop or hosted session. If the supported retry is denied again, preserve progress and report the remaining block rather than looping.
38
38
 
39
39
  Never retry the denied action through another shell, tool, wrapper or transport, change permission settings, request a wildcard allow rule, or suggest bypassing the host's safeguards. Keep setup agent-led: do not default to asking the human to run commands, paste status output or adjust Bash settings. Never offer a .relay-rollback or other backup helper for manual execution. If no supported recovery is available, give one concise explanation of the blocked action, what remains unverified, and a verified host review step if one is available. Do not offer an unavailable dialog or use “tell me Relay is not connected” as a substitute for verification. A user-requested manual handoff must use the current supported helper and protect secrets. The normal copyable URL fallback for browser sign-in remains available; it is not a workaround for a denied agent tool call.
40
40
 
41
41
  For questions, choices and approvals, instruct the current host through its built-in user-question tool whenever that tool is exposed and permitted for this kind of question in the current mode. The host renders the question UI from the tool call; do not draw fake buttons in Markdown or ask the host to render arbitrary HTML. Before asking, inspect the tools actually available to the current turn. Claude Code commonly exposes `AskUserQuestion`; Codex may expose `request_user_input_async` or mode-limited `request_user_input`. Respect each tool's constraints, especially restrictions on permission questions. Do not invent a tool, change modes to obtain one, or use a question tool for host permission escalation. When a permitted tool is available, call it instead of asking the same question in plain chat; wait for the actual answer before dependent work. For asynchronous questions, continue only unrelated safe work while waiting.
42
42
 
43
- For setup permission, put the complete question with the exact package version and source in the interface's question field and offer concise affirmative and decline choices such as “Set up Relay” and “Not now.” Ask one clear decision at a time, with a way to decline or skip when appropriate. For the first send, show both exact payloads and the recipient before asking, and make clear that approval sends that specific message. Do not abbreviate the payloads to fit a question widget. Only when no permitted user-question interface is exposed, or its documented constraints cannot carry the required content, ask plainly in chat. Use existing explicit permission; never ask again just to use the interface. A suggested or preselected choice, an empty result, silence or a timeout is not consent: wait for an actual affirmative answer before any action that requires approval. Browser sign-in and account approval still happen in the person's usual browser.
43
+ For setup permission, put the complete question with the exact package version and source in the interface's question field and offer concise affirmative and decline choices such as “Set up Relay” and “Not now.” Ask one clear decision at a time, with a way to decline or skip when appropriate. For the first send, show both exact payloads and the recipient before asking, and make clear that approval sends that specific message. Do not abbreviate the payloads to fit a question widget. Only when no permitted user-question interface is exposed, or its documented constraints cannot carry the required content, ask plainly in chat. Retain existing explicit permission when choosing the interface; ask follow-up questions whenever useful or required. A suggested or preselected choice, an empty result, silence or a timeout is not consent: wait for an actual affirmative answer before any action that requires approval. Browser sign-in and account approval still happen in the person's usual browser.
44
44
 
45
- During setup, give one or two short sentences only at meaningful changes or when the person needs to act. Do not narrate tool discovery, command attempts, process launches or unchanged progress. Keep HTTPS, MCP, protocol names, credentials, paths, versions, process IDs, Relay IDs, logs, encryption mechanics and durable queues out of the human update unless needed to resolve a specific problem or explicitly requested. Do not produce a component-by-component status report. Preserve material limitations in plain language: for example, "Relay is connected. The app is still installing." If the skill could not be installed or updated, state that limitation briefly instead of claiming setup is complete; put file paths and diagnostics in optional detail. Never promise a later notification unless a supported follow-up is actually arranged, and do not repeat the pending send question after an installation check.
45
+ During setup, give one or two short sentences only at meaningful changes or when the person needs to act. Do not narrate tool discovery, command attempts, process launches or unchanged progress. Keep HTTPS, MCP, protocol names, credentials, paths, versions, process IDs, Relay IDs, logs, encryption mechanics and durable queues out of the human update unless needed to resolve a specific problem or explicitly requested. Do not produce a component-by-component status report. Preserve material limitations in plain language: for example, "Relay is connected. The app is still installing." If the skill could not be installed or updated, state that limitation briefly instead of claiming setup is complete; put file paths and diagnostics in optional detail. Never promise a later notification unless a supported follow-up is actually arranged, and keep any pending send approval clear when asking follow-up questions.
46
46
 
47
47
  After the first send, lead with one short, evidence-based result, such as "Delivered to Shane." Say "Sent to Shane" or "Queued for Shane" when that is all the result proves. Then say "You can check for replies here in Claude Code—just ask me," using the current host's name. Add at most one short sentence about a remaining installation problem or pending app installation. Do not append a feature list, another offer to check for replies, or routine assurances about actions the person never requested. Keep the exact two first-message payloads and their approval intact before the send; brevity never removes consent or hides a failure.
48
48
 
@@ -95,8 +95,9 @@ treat a suggested or preselected choice as consent.
95
95
  After a direct affirmative answer, say briefly that Relay's app is starting to
96
96
  install. On a supported local desktop, run the invitation's exact pinned
97
97
  background-install as the first setup command, before creating or opening
98
- browser approval, installing the skill, or asking another question. Existing
99
- setup consent covers this installation; do not ask again. Confirm from the
98
+ browser approval or installing the skill, unless clarification or further
99
+ permission is needed first. Stay within the existing setup consent and ask
100
+ follow-up questions whenever needed. Confirm from the
100
101
  result that it started or is already running, then continue without waiting for
101
102
  the download. A hidden shell on a local desktop is not a headless machine.
102
103
  Use the exact connect-start command, API origin and invitation token from the
@@ -5,6 +5,8 @@ import net from "node:net";
5
5
  import { createHash } from "node:crypto";
6
6
 
7
7
  export const LOCAL_MAX_BYTES = 160 * 1024 * 1024;
8
+ // AI-session inspection may wait 45 seconds, plus API and catalog lookups.
9
+ export const LOCAL_TOOL_TIMEOUT_MS = 120_000;
8
10
  export function localDescriptorPath(env = process.env) {
9
11
  return env.RELAY_AGENT_LOCAL || path.join(env.RELAY_CONFIG_DIR || path.join(os.homedir(), ".relay"), "agent-local.json");
10
12
  }
@@ -6,7 +6,7 @@ import path from "node:path";
6
6
  import { createHash, randomBytes, randomUUID } from "node:crypto";
7
7
  import { fileURLToPath } from "node:url";
8
8
  import { prepareOrdinaryRelayAttachments } from "./relay-attachments.mjs";
9
- import { readLocalDescriptor, localRequest } from "./relay-local.mjs";
9
+ import { readLocalDescriptor, localRequest, LOCAL_TOOL_TIMEOUT_MS } from "./relay-local.mjs";
10
10
  import { spawnSync } from "node:child_process";
11
11
 
12
12
  const DEFAULT_CONFIG = path.join(os.homedir(), ".relay", "agent-protocol.json");
@@ -544,6 +544,21 @@ async function main(argv = process.argv.slice(2)) {
544
544
  return { ok: true, connected: true, account: config.account || {}, inviter: config.inviter, invite: config.invite, tutorial: config.tutorial, lastSend: config.lastSend, expiresAt: config.expiresAt || "" };
545
545
  }
546
546
  if (command === "groups") return request("GET", "/v1/contact-groups");
547
+ if (command === "tools" || command === "call") {
548
+ const config = readConfig();
549
+ const local = readLocalDescriptor();
550
+ if ((config.consentVersion ?? 1) < 2 || !local) throw new Error("The complete tool catalog requires Relay Companion. Open or update Companion and retry; this command does not use direct HTTPS fallback.");
551
+ if (local.accountId !== config.account?.relayUserId || local.apiUrl !== config.apiUrl) throw new Error("Companion is connected to a different Relay account or environment. Nothing was sent or read.");
552
+ if (command === "call" && !rest[0]) throw new Error("call requires an exact tool name from tools; pass its JSON arguments on stdin.");
553
+ if (local.toolCatalogVersion !== 1) throw new Error("This Companion does not expose the complete tool catalog yet. Update and reopen Relay Companion, then retry the same command.");
554
+ const target = currentSkillTarget(process.env);
555
+ const host = process.env.CODEX_THREAD_ID ? "codex" : process.env.CLAUDE_CODE_SESSION_ID || process.env.CLAUDE_SESSION_ID ? "claude_code" : target?.host === "codex" ? "codex" : target?.host === "claude" ? "claude_code" : "";
556
+ const caller = { cwd: process.cwd(), host, nativeId: host === "codex" ? process.env.CODEX_THREAD_ID || "" : process.env.CLAUDE_CODE_SESSION_ID || process.env.CLAUDE_SESSION_ID || "" };
557
+ const body = command === "call" ? { name: rest[0], arguments: parseJson(await readStdin() || "{}", "Tool arguments") } : undefined;
558
+ const result = await localRequest(local, { method: command === "tools" ? "GET" : "POST", path: command === "tools" ? "/local/tools" : "/local/tools/call", body, caller, accountId: config.account.relayUserId }, { timeoutMs: LOCAL_TOOL_TIMEOUT_MS });
559
+ if (result?.isError) process.exitCode = 1;
560
+ return result;
561
+ }
547
562
  if (command === "chats") return request("GET", "/v1/chats");
548
563
  if (command === "chat") return request("GET", `/v1/chats/${encodeURIComponent(rest[0] || "")}`);
549
564
  if (command === "thread") return request("GET", `/v1/threads/${encodeURIComponent(rest[0] || "")}`);
@@ -630,6 +645,8 @@ async function main(argv = process.argv.slice(2)) {
630
645
  "relay-protocol connect-start <api-origin> <invite-token> claude_code|codex",
631
646
  "relay-protocol connect-finish # run after approving the returned browser URL",
632
647
  "relay-protocol status",
648
+ "relay-protocol tools # complete account-specific catalog with descriptions and JSON schemas; requires Companion",
649
+ "relay-protocol call <tool-name> # JSON arguments on stdin; same capabilities and results as MCP; requires Companion",
633
650
  "relay-protocol inbox | sent | groups | chats | outbox",
634
651
  "relay-protocol outbox retry <original-idempotency-key>",
635
652
  "relay-protocol wait-reply <sent-relay-id> [seconds:0-45]",