@inline-chat/hermes-agent-adapter 0.0.5-alpha.0 → 0.0.5-alpha.2

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 CHANGED
@@ -58,11 +58,11 @@ hermes plugins enable inline-platform
58
58
  hermes gateway setup
59
59
  ```
60
60
 
61
- Select Inline in the messaging-platform picker. The guided setup can sign you
62
- in with the Inline CLI, create a dedicated Hermes bot, securely save its token,
63
- and restrict access to your Inline account. You can also paste an existing bot
64
- token. Manual setup remains documented in the
65
- [Inline bot creation guide](https://inline.chat/docs/creating-a-bot).
61
+ Select Inline in the messaging-platform picker. The default path is: go to
62
+ **Inline Settings Bots Create a new bot**, then paste its token. See the
63
+ [Inline bot creation guide](https://inline.chat/docs/creating-a-bot). The
64
+ optional CLI path can install/sign in to the Inline CLI and create the bot from
65
+ the terminal. Both paths securely save the token and configure access.
66
66
 
67
67
  ## Coding Agent Setup Prompt
68
68
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inline-chat/hermes-agent-adapter",
3
- "version": "0.0.5-alpha.0",
3
+ "version": "0.0.5-alpha.2",
4
4
  "description": "Hermes Agent platform adapter for Inline, with a native Python plugin and bundled Inline realtime sidecar.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -3001,7 +3001,6 @@ class InlineAdapter(BasePlatformAdapter):
3001
3001
  ) -> SendResult:
3002
3002
  target = self._target_for(chat_id, metadata)
3003
3003
  reply_to = self._reply_to_for_target(reply_to, target)
3004
- parse_markdown = self._parse_markdown and not self._expects_edits(metadata)
3005
3004
  chunks = self.truncate_message(self.format_message(content), self.MAX_MESSAGE_LENGTH)
3006
3005
  message_ids: List[str] = []
3007
3006
  raw_responses: List[Any] = []
@@ -3011,7 +3010,7 @@ class InlineAdapter(BasePlatformAdapter):
3011
3010
  body: Dict[str, Any] = {
3012
3011
  "target": target,
3013
3012
  "text": chunk,
3014
- "parseMarkdown": parse_markdown,
3013
+ "parseMarkdown": self._parse_markdown,
3015
3014
  }
3016
3015
  if reply_to and index == 0:
3017
3016
  body["replyToMsgId"] = str(reply_to)
@@ -3052,7 +3051,6 @@ class InlineAdapter(BasePlatformAdapter):
3052
3051
  metadata: Optional[Dict[str, Any]] = None,
3053
3052
  ) -> SendResult:
3054
3053
  text = self.format_message(content)
3055
- parse_markdown = self._parse_markdown if finalize else False
3056
3054
  if len(text) > self.MAX_MESSAGE_LENGTH:
3057
3055
  if finalize:
3058
3056
  return await self._edit_overflow_split(chat_id, message_id, content, metadata=metadata)
@@ -3062,7 +3060,7 @@ class InlineAdapter(BasePlatformAdapter):
3062
3060
  "target": target,
3063
3061
  "messageId": str(message_id),
3064
3062
  "text": text,
3065
- "parseMarkdown": parse_markdown,
3063
+ "parseMarkdown": self._parse_markdown,
3066
3064
  }
3067
3065
  result = await self._send_sidecar("/edit", body)
3068
3066
  if result.success:
@@ -3480,10 +3478,6 @@ class InlineAdapter(BasePlatformAdapter):
3480
3478
  def format_message(self, content: str) -> str:
3481
3479
  return content if self._parse_markdown else strip_markdown(content)
3482
3480
 
3483
- @staticmethod
3484
- def _expects_edits(metadata: Optional[Dict[str, Any]]) -> bool:
3485
- return bool((metadata or {}).get("expect_edits"))
3486
-
3487
3481
  def _target_for(self, chat_id: str, metadata: Optional[Dict[str, Any]] = None) -> Dict[str, str]:
3488
3482
  thread_id = (metadata or {}).get("thread_id")
3489
3483
  if thread_id:
@@ -12,12 +12,14 @@ import os
12
12
  import re
13
13
  import shutil
14
14
  import subprocess
15
+ import sys
15
16
 
16
17
  from pathlib import Path
17
18
 
18
19
  _SIDECAR_ENTRY = Path(__file__).parent / "sidecar" / "index.mjs"
19
20
  _MIN_NODE_MAJOR = 20
20
21
  _BOT_USERNAME_RE = re.compile(r"^[A-Za-z0-9_]+bot$", re.IGNORECASE)
22
+ _CLI_INSTALL_URL = "https://inline.chat/cli/install.sh"
21
23
 
22
24
 
23
25
  def gateway_setup() -> None:
@@ -42,17 +44,18 @@ def gateway_setup() -> None:
42
44
 
43
45
  hermes_setup.print_info("How would you like to connect Hermes to Inline?")
44
46
  print()
45
- hermes_setup.print_info(" [1] Create a dedicated Hermes bot (recommended)")
46
- hermes_setup.print_info(" Sign in with the Inline CLI, name the bot, and you're done.")
47
+ hermes_setup.print_info(" [1] Create a bot in Inline and paste its token")
48
+ hermes_setup.print_info(" Go to Settings Bots Create a new bot.")
49
+ hermes_setup.print_info(" https://inline.chat/docs/creating-a-bot")
47
50
  print()
48
- hermes_setup.print_info(" [2] Use an existing bot token")
49
- hermes_setup.print_info(" Paste a token you created in Inline Settings Bots.")
51
+ hermes_setup.print_info(" [2] Create a bot with the Inline CLI")
52
+ hermes_setup.print_info(" Install or sign in to the CLI, then create the bot here.")
50
53
  print()
51
54
 
52
55
  choice = hermes_setup.prompt("Choice [1/2]", default="1").strip()
53
56
  owner_user_id: str | None = None
54
57
  token: str | None = None
55
- if choice == "1":
58
+ if choice == "2":
56
59
  token, owner_user_id = _create_bot_with_inline_cli(hermes_setup)
57
60
  if not token:
58
61
  print()
@@ -70,6 +73,7 @@ def gateway_setup() -> None:
70
73
  if not owner_user_id:
71
74
  owner_user_id = _inline_cli_user_id(shutil.which("inline"))
72
75
  _configure_access(hermes_gateway, hermes_setup, owner_user_id)
76
+ hermes_gateway.write_platform_config_field("inline", "enabled", True, raw=True)
73
77
 
74
78
  print()
75
79
  hermes_setup.print_success("💬 Inline is configured!")
@@ -78,11 +82,13 @@ def gateway_setup() -> None:
78
82
 
79
83
 
80
84
  def _create_bot_with_inline_cli(hermes_setup) -> tuple[str | None, str | None]:
81
- inline_bin = shutil.which("inline")
85
+ inline_bin = _find_inline_cli()
82
86
  if not inline_bin:
83
- hermes_setup.print_warning("The Inline CLI is not installed, so automatic bot creation is unavailable.")
84
- hermes_setup.print_info("Install it from https://inline.chat/docs/cli, or use an existing bot token.")
85
- return None, None
87
+ inline_bin = _install_inline_cli(hermes_setup)
88
+ if not inline_bin:
89
+ hermes_setup.print_warning("Automatic bot creation is unavailable because the Inline CLI could not be installed.")
90
+ hermes_setup.print_info("Install it from https://inline.chat/docs/cli, or use an existing bot token.")
91
+ return None, None
86
92
 
87
93
  owner_user_id = _inline_cli_user_id(inline_bin)
88
94
  if not owner_user_id:
@@ -126,9 +132,96 @@ def _create_bot_with_inline_cli(hermes_setup) -> tuple[str | None, str | None]:
126
132
  return None, owner_user_id
127
133
 
128
134
 
135
+ def _install_inline_cli(hermes_setup) -> str | None:
136
+ print()
137
+ hermes_setup.print_info("The Inline CLI is needed to create your bot automatically.")
138
+ if not hermes_setup.prompt_yes_no("Install the Inline CLI now?", True):
139
+ hermes_setup.print_info("Inline CLI installation skipped.")
140
+ return None
141
+
142
+ brew_bin = shutil.which("brew") if sys.platform == "darwin" else None
143
+ if brew_bin:
144
+ hermes_setup.print_info("Installing the Inline CLI with Homebrew...")
145
+ result = subprocess.run(
146
+ [brew_bin, "install", "--cask", "inline"],
147
+ check=False,
148
+ )
149
+ else:
150
+ curl_bin = shutil.which("curl")
151
+ shell_bin = shutil.which("sh") or "/bin/sh"
152
+ if not curl_bin:
153
+ hermes_setup.print_warning("Automatic installation requires curl.")
154
+ return None
155
+ hermes_setup.print_info("Downloading the official Inline CLI installer...")
156
+ try:
157
+ download = subprocess.run(
158
+ [curl_bin, "-fsSL", _CLI_INSTALL_URL],
159
+ stdout=subprocess.PIPE,
160
+ stderr=subprocess.PIPE,
161
+ timeout=60,
162
+ check=False,
163
+ )
164
+ except (OSError, subprocess.TimeoutExpired) as exc:
165
+ hermes_setup.print_warning(f"Could not download the Inline CLI installer: {exc}")
166
+ return None
167
+ if download.returncode != 0 or not download.stdout:
168
+ hermes_setup.print_warning("Could not download the Inline CLI installer.")
169
+ return None
170
+ try:
171
+ result = subprocess.run(
172
+ [shell_bin, "-s"],
173
+ input=download.stdout,
174
+ timeout=180,
175
+ check=False,
176
+ )
177
+ except (OSError, subprocess.TimeoutExpired) as exc:
178
+ hermes_setup.print_warning(f"Inline CLI installation failed: {exc}")
179
+ return None
180
+
181
+ if result.returncode != 0:
182
+ hermes_setup.print_warning("The Inline CLI installer exited unsuccessfully.")
183
+ return None
184
+
185
+ inline_bin = _find_inline_cli()
186
+ if not inline_bin:
187
+ hermes_setup.print_warning("The Inline CLI was installed but could not be found on PATH.")
188
+ return None
189
+ try:
190
+ verified = subprocess.run(
191
+ [inline_bin, "--version"],
192
+ stdout=subprocess.PIPE,
193
+ stderr=subprocess.PIPE,
194
+ timeout=10,
195
+ check=False,
196
+ )
197
+ except (OSError, subprocess.TimeoutExpired):
198
+ verified = None
199
+ if verified is None or verified.returncode != 0:
200
+ hermes_setup.print_warning("The installed Inline CLI could not be verified.")
201
+ return None
202
+
203
+ hermes_setup.print_success("Inline CLI installed successfully.")
204
+ return inline_bin
205
+
206
+
207
+ def _find_inline_cli() -> str | None:
208
+ discovered = shutil.which("inline")
209
+ if discovered:
210
+ return discovered
211
+ candidates = [
212
+ Path("/opt/homebrew/bin/inline"),
213
+ Path("/usr/local/bin/inline"),
214
+ Path.home() / ".local" / "bin" / "inline",
215
+ ]
216
+ for candidate in candidates:
217
+ if candidate.is_file() and os.access(candidate, os.X_OK):
218
+ return str(candidate)
219
+ return None
220
+
221
+
129
222
  def _prompt_existing_token(hermes_setup) -> str | None:
130
223
  print()
131
- hermes_setup.print_info("Create or reveal a bot token in Inline Settings Bots.")
224
+ hermes_setup.print_info("Go to Inline Settings BotsCreate a new bot, then copy its token.")
132
225
  hermes_setup.print_info("Guide: https://inline.chat/docs/creating-a-bot")
133
226
  token = hermes_setup.prompt("Inline bot token", password=True).strip()
134
227
  return token or None
@@ -1,7 +1,7 @@
1
1
  name: inline-platform
2
2
  label: Inline
3
3
  kind: platform
4
- version: 0.0.5-alpha.0
4
+ version: 0.0.5-alpha.2
5
5
  description: >
6
6
  Inline platform adapter for Hermes Agent. The adapter runs as a native
7
7
  Hermes Python platform plugin and supervises a local Node sidecar that uses