@inline-chat/hermes-agent-adapter 0.0.18-alpha.0 → 0.0.18
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 +9 -5
- package/dist/install.js +25 -7
- package/package.json +5 -5
- package/plugin/inline/adapter.py +12 -14
- package/plugin/inline/cli.py +48 -3
- package/plugin/inline/plugin.yaml +4 -1
- package/plugin/inline/sidecar/index.mjs +84 -1325
package/README.md
CHANGED
|
@@ -157,7 +157,7 @@ uv run ./hermes plugins list --plain --no-bundled
|
|
|
157
157
|
Expected local output includes:
|
|
158
158
|
|
|
159
159
|
```text
|
|
160
|
-
enabled user 0.0.18
|
|
160
|
+
enabled user 0.0.18 inline-platform
|
|
161
161
|
```
|
|
162
162
|
|
|
163
163
|
## Update Or Reinstall
|
|
@@ -179,13 +179,17 @@ mismatch, rerun the same command after rebuilding or upgrading the package.
|
|
|
179
179
|
## Compatibility
|
|
180
180
|
|
|
181
181
|
- Hermes Agent: requires the external user plugin registry and native platform
|
|
182
|
-
plugin loader available in Hermes Agent `>=0.
|
|
183
|
-
against Hermes Agent `0.21.
|
|
184
|
-
`v2026.
|
|
182
|
+
plugin loader available in Hermes Agent `>=0.21.4`. This package was validated
|
|
183
|
+
against Hermes Agent `0.21.5` from source commit `f97608f178d1ffeca59860195ab7da295f7c8e5f` (tag
|
|
184
|
+
`v2026.9.24`).
|
|
185
|
+
- CI checks the minimum supported Hermes release, newest stable source, and upstream
|
|
186
|
+
`main`. A six-hour scheduled check also tests the published npm `latest` adapter.
|
|
187
|
+
`inline-hermes doctor` requires successful host loading and compatibility validation;
|
|
188
|
+
unavailable Hermes diagnostics no longer count as healthy.
|
|
185
189
|
- Node.js: `>=20` is required for the bundled sidecar. Hermes-managed Node 22,
|
|
186
190
|
system Node, or an explicit `INLINE_NODE_BIN` path all work.
|
|
187
191
|
- Inbound recovery retries without waiting for another message or reconnect. Independent chats are consumed concurrently; same-chat order and delivery acknowledgements are preserved. Sender provenance lookups start with a short timeout and expand up to the existing SDK ceiling after timeouts; deferred inputs stay recoverable. Stream replacement wakes pending backpressure writes.
|
|
188
|
-
- Inline transport: the sidecar uses `@inline-chat/realtime-sdk@0.0.
|
|
192
|
+
- Inline transport: the sidecar uses `@inline-chat/realtime-sdk@0.0.18` and is
|
|
189
193
|
bundled into the npm package, so Hermes startup does not run `npm install`.
|
|
190
194
|
- Live sends require a valid Inline user or bot token in `INLINE_TOKEN`,
|
|
191
195
|
`INLINE_BOT_TOKEN`, `platforms.inline.token`, or `inline.token`.
|
package/dist/install.js
CHANGED
|
@@ -7174,6 +7174,12 @@ async function inspectInstall(params) {
|
|
|
7174
7174
|
if (!node.ok) {
|
|
7175
7175
|
issues.push(node.error || `${node.source} is not usable: ${node.path}`);
|
|
7176
7176
|
}
|
|
7177
|
+
if (params.opts.command === "doctor" && !activation.hermesCompatibilityVerified) {
|
|
7178
|
+
issues.push("Hermes could not validate the installed plugin compatibility; check `hermes inline status --json --check-compatibility` and update or repair the plugin");
|
|
7179
|
+
}
|
|
7180
|
+
if (params.opts.command === "doctor" && !activation.hermesCredentialStoreChecked) {
|
|
7181
|
+
issues.push("Hermes credential verification is unavailable; doctor cannot confirm runtime readiness");
|
|
7182
|
+
}
|
|
7177
7183
|
if (params.opts.command === "doctor" && !activation.pluginEnabled) {
|
|
7178
7184
|
issues.push(`Hermes plugin '${pluginEnableKey}' is not enabled. Run: hermes plugins enable ${pluginEnableKey}`);
|
|
7179
7185
|
}
|
|
@@ -7579,7 +7585,7 @@ async function inspectActivation(hermesHome, target, probeCredential) {
|
|
|
7579
7585
|
}
|
|
7580
7586
|
const tokenPresent = Boolean(process.env.INLINE_TOKEN || process.env.INLINE_BOT_TOKEN);
|
|
7581
7587
|
const configTokenConfigured = configTokenIsConfigured(config, ["platforms", defaultPluginId, "token"]) || configTokenIsConfigured(config, [defaultPluginId, "token"]);
|
|
7582
|
-
const machineCredential = inspectHermesCredential(hermesHome, probeCredential);
|
|
7588
|
+
const machineCredential = inspectHermesCredential(hermesHome, probeCredential, target);
|
|
7583
7589
|
const fallbackConfigured = tokenPresent || configTokenConfigured;
|
|
7584
7590
|
const credentialState = (machineCredential.state === "unknown" || machineCredential.state === "not_configured") && fallbackConfigured ? "configured_unverified" : machineCredential.state;
|
|
7585
7591
|
const installOwnershipAligned = await inspectInstallOwnership(hermesHome, target);
|
|
@@ -7589,6 +7595,7 @@ async function inspectActivation(hermesHome, target, probeCredential) {
|
|
|
7589
7595
|
pluginEnabled: readConfigList(config, ["plugins", "enabled"]).includes(pluginEnableKey),
|
|
7590
7596
|
platformConfigured: readConfigBoolean(config, ["platforms", defaultPluginId, "enabled"]) || readConfigBoolean(config, [defaultPluginId, "enabled"]),
|
|
7591
7597
|
configTokenConfigured,
|
|
7598
|
+
hermesCompatibilityVerified: machineCredential.compatible === true,
|
|
7592
7599
|
hermesCredentialStoreChecked: machineCredential.checked,
|
|
7593
7600
|
hermesCredentialStoreTokenConfigured: machineCredential.configured === true,
|
|
7594
7601
|
credentialState,
|
|
@@ -7649,9 +7656,9 @@ async function chownTree(target, uid, gid) {
|
|
|
7649
7656
|
}
|
|
7650
7657
|
await chown(target, uid, gid);
|
|
7651
7658
|
}
|
|
7652
|
-
function inspectHermesCredential(hermesHome, probe) {
|
|
7659
|
+
function inspectHermesCredential(hermesHome, probe, target) {
|
|
7653
7660
|
const executable = normalizeToken(process.env.INLINE_HERMES_BIN) || "hermes";
|
|
7654
|
-
const args = ["inline", "status", "--json", ...probe ? ["--probe"] : []];
|
|
7661
|
+
const args = ["inline", "status", "--json", ...probe ? ["--probe", "--check-compatibility"] : []];
|
|
7655
7662
|
const result = spawnSync(executable, args, {
|
|
7656
7663
|
encoding: "utf8",
|
|
7657
7664
|
timeout: hermesMachineTimeoutMs,
|
|
@@ -7675,11 +7682,13 @@ function inspectHermesCredential(hermesHome, probe) {
|
|
|
7675
7682
|
if (record.action !== "inline.status" || typeof record.setupProtocolVersion !== "number" || record.setupProtocolVersion < 1 || typeof record.configured !== "boolean") {
|
|
7676
7683
|
return { checked: false, configured: null, state: "unknown" };
|
|
7677
7684
|
}
|
|
7685
|
+
const compatibility = record.compatibility;
|
|
7686
|
+
const compatible = result.status === 0 && compatibility?.ok === true && compatibility.pluginPath === safeRealpathSync(target);
|
|
7678
7687
|
if (!record.configured) {
|
|
7679
|
-
return { checked: true, configured: false, state: "not_configured" };
|
|
7688
|
+
return { compatible, checked: true, configured: false, state: "not_configured" };
|
|
7680
7689
|
}
|
|
7681
7690
|
if (!probe) {
|
|
7682
|
-
return { checked: true, configured: true, state: "configured_unverified" };
|
|
7691
|
+
return { compatible, checked: true, configured: true, state: "configured_unverified" };
|
|
7683
7692
|
}
|
|
7684
7693
|
const probeResult = record.probe && typeof record.probe === "object" && !Array.isArray(record.probe) ? record.probe : null;
|
|
7685
7694
|
if (probeResult?.ok === true) {
|
|
@@ -7688,6 +7697,7 @@ function inspectHermesCredential(hermesHome, probe) {
|
|
|
7688
7697
|
return { checked: false, configured: true, state: "unknown" };
|
|
7689
7698
|
const botUsername = typeof probeResult.botUsername === "string" && probeResult.botUsername.trim() ? probeResult.botUsername.trim() : undefined;
|
|
7690
7699
|
return {
|
|
7700
|
+
compatible,
|
|
7691
7701
|
checked: true,
|
|
7692
7702
|
configured: true,
|
|
7693
7703
|
state: "verified",
|
|
@@ -7696,9 +7706,16 @@ function inspectHermesCredential(hermesHome, probe) {
|
|
|
7696
7706
|
};
|
|
7697
7707
|
}
|
|
7698
7708
|
if (probeResult?.errorKind === "invalid_credential") {
|
|
7699
|
-
return { checked: true, configured: true, state: "invalid" };
|
|
7709
|
+
return { compatible, checked: true, configured: true, state: "invalid" };
|
|
7710
|
+
}
|
|
7711
|
+
return { compatible, checked: true, configured: true, state: "unknown" };
|
|
7712
|
+
}
|
|
7713
|
+
function safeRealpathSync(target) {
|
|
7714
|
+
try {
|
|
7715
|
+
return realpathSync(target);
|
|
7716
|
+
} catch {
|
|
7717
|
+
return null;
|
|
7700
7718
|
}
|
|
7701
|
-
return { checked: true, configured: true, state: "unknown" };
|
|
7702
7719
|
}
|
|
7703
7720
|
function readConfigList(config, pathParts) {
|
|
7704
7721
|
const value = readConfigValue(config, pathParts);
|
|
@@ -8118,6 +8135,7 @@ Options:
|
|
|
8118
8135
|
console.log(`Usage: inline-hermes ${topic} [options]
|
|
8119
8136
|
|
|
8120
8137
|
${topic === "doctor" ? "Diagnose" : "Inspect"} the installed Inline plugin, sidecar integrity, and Node runtime.
|
|
8138
|
+
${topic === "doctor" ? "Doctor also requires a successful Hermes loader compatibility check and credential probe." : ""}
|
|
8121
8139
|
|
|
8122
8140
|
Options:
|
|
8123
8141
|
--hermes-home <path> Hermes home directory. Defaults to HERMES_HOME or ~/.hermes.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inline-chat/hermes-agent-adapter",
|
|
3
|
-
"version": "0.0.18
|
|
3
|
+
"version": "0.0.18",
|
|
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",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"check": "bun run typecheck && bun run lint && bun run test"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@inline-chat/realtime-sdk": "0.0.
|
|
65
|
+
"@inline-chat/realtime-sdk": "0.0.18",
|
|
66
66
|
"yaml": "2.9.0"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
@@ -81,8 +81,8 @@
|
|
|
81
81
|
"npmSpec": "@inline-chat/hermes-agent-adapter"
|
|
82
82
|
},
|
|
83
83
|
"machineSetupProtocol": 1,
|
|
84
|
-
"minHermesVersion": "0.
|
|
85
|
-
"testedHermesVersion": "0.21.
|
|
86
|
-
"testedHermesCommit": "
|
|
84
|
+
"minHermesVersion": "0.21.4",
|
|
85
|
+
"testedHermesVersion": "0.21.5",
|
|
86
|
+
"testedHermesCommit": "f97608f178d1ffeca59860195ab7da295f7c8e5f"
|
|
87
87
|
}
|
|
88
88
|
}
|
package/plugin/inline/adapter.py
CHANGED
|
@@ -45,6 +45,7 @@ from gateway.platforms.base import (
|
|
|
45
45
|
SendResult,
|
|
46
46
|
cache_audio_from_url,
|
|
47
47
|
cache_image_from_url,
|
|
48
|
+
safe_url_for_log,
|
|
48
49
|
)
|
|
49
50
|
from gateway.platforms.helpers import strip_markdown
|
|
50
51
|
|
|
@@ -575,7 +576,7 @@ def _normalize_inline_command_description(raw: str) -> str:
|
|
|
575
576
|
|
|
576
577
|
|
|
577
578
|
def _inline_menu_commands(max_commands: int = _INLINE_COMMAND_LIMIT) -> tuple[List[Dict[str, Any]], int]:
|
|
578
|
-
from hermes_cli.
|
|
579
|
+
from hermes_cli.commands_platforms import telegram_menu_commands
|
|
579
580
|
|
|
580
581
|
command_specs = _inline_command_specs()
|
|
581
582
|
local_commands = [
|
|
@@ -1209,7 +1210,7 @@ class InlineAdapter(BasePlatformAdapter):
|
|
|
1209
1210
|
|
|
1210
1211
|
try:
|
|
1211
1212
|
from gateway.run import _load_gateway_config
|
|
1212
|
-
from hermes_cli.
|
|
1213
|
+
from hermes_cli.model_switch_providers import list_picker_providers
|
|
1213
1214
|
|
|
1214
1215
|
cfg = _load_gateway_config() or {}
|
|
1215
1216
|
model_cfg = cfg.get("model") if isinstance(cfg, dict) else {}
|
|
@@ -3001,16 +3002,15 @@ class InlineAdapter(BasePlatformAdapter):
|
|
|
3001
3002
|
return await cache_audio_from_url(url, ext=_extension_for_media(mime, file_name, ".ogg"))
|
|
3002
3003
|
return await self._download_inline_media_url(url, mime=mime, file_name=file_name)
|
|
3003
3004
|
except Exception as exc:
|
|
3004
|
-
logger.warning("[inline] failed to cache %s attachment
|
|
3005
|
-
|
|
3005
|
+
logger.warning("[inline] failed to cache %s attachment (%s)", kind, type(exc).__name__)
|
|
3006
|
+
# Never pass an unvalidated URL on to Hermes for another fetch.
|
|
3007
|
+
return None
|
|
3006
3008
|
|
|
3007
3009
|
async def _download_inline_media_url(self, url: str, *, mime: str, file_name: Optional[str]) -> str:
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
except ImportError:
|
|
3013
|
-
pass
|
|
3010
|
+
# A missing host safety helper must stop the download, never bypass it.
|
|
3011
|
+
from tools.url_safety import is_safe_url
|
|
3012
|
+
if not is_safe_url(url):
|
|
3013
|
+
raise ValueError(f"blocked unsafe media URL: {safe_url_for_log(url)}")
|
|
3014
3014
|
_MEDIA_CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
|
3015
3015
|
name = _safe_media_file_name(url=url, mime=mime, file_name=file_name)
|
|
3016
3016
|
path = _MEDIA_CACHE_DIR / name
|
|
@@ -4230,7 +4230,7 @@ class InlineAdapter(BasePlatformAdapter):
|
|
|
4230
4230
|
label = group_id
|
|
4231
4231
|
member_slugs: list[str] = []
|
|
4232
4232
|
try:
|
|
4233
|
-
from hermes_cli.
|
|
4233
|
+
from hermes_cli.models_catalog_static import PROVIDER_GROUPS
|
|
4234
4234
|
label, _desc, members = PROVIDER_GROUPS.get(group_id, (group_id, "", []))
|
|
4235
4235
|
member_slugs = [str(member) for member in members]
|
|
4236
4236
|
except Exception:
|
|
@@ -4686,7 +4686,6 @@ class InlineAdapter(BasePlatformAdapter):
|
|
|
4686
4686
|
|
|
4687
4687
|
async def send_image(self, chat_id: str, image_url: str, caption: Optional[str] = None, reply_to: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None) -> SendResult:
|
|
4688
4688
|
try:
|
|
4689
|
-
from gateway.platforms.base import cache_image_from_url
|
|
4690
4689
|
local_path = await cache_image_from_url(image_url)
|
|
4691
4690
|
return await self.send_image_file(chat_id, local_path, caption, reply_to, metadata)
|
|
4692
4691
|
except Exception:
|
|
@@ -4694,7 +4693,6 @@ class InlineAdapter(BasePlatformAdapter):
|
|
|
4694
4693
|
|
|
4695
4694
|
async def send_animation(self, chat_id: str, animation_url: str, caption: Optional[str] = None, reply_to: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None) -> SendResult:
|
|
4696
4695
|
try:
|
|
4697
|
-
from gateway.platforms.base import cache_image_from_url
|
|
4698
4696
|
local_path = await cache_image_from_url(animation_url, ext=".gif")
|
|
4699
4697
|
return await self.send_document(chat_id, local_path, caption, file_name=Path(local_path).name, reply_to=reply_to, metadata=metadata)
|
|
4700
4698
|
except Exception:
|
|
@@ -4982,7 +4980,7 @@ class InlineAdapter(BasePlatformAdapter):
|
|
|
4982
4980
|
}
|
|
4983
4981
|
actions: list[Dict[str, str]] = []
|
|
4984
4982
|
try:
|
|
4985
|
-
from hermes_cli.
|
|
4983
|
+
from hermes_cli.models_catalog_static import group_providers
|
|
4986
4984
|
grouped = group_providers(list(by_slug.keys()))
|
|
4987
4985
|
except Exception:
|
|
4988
4986
|
grouped = [{"kind": "single", "slug": slug} for slug in by_slug.keys()]
|
package/plugin/inline/cli.py
CHANGED
|
@@ -27,7 +27,7 @@ _CLI_INSTALL_URL = "https://inline.chat/cli/install.sh"
|
|
|
27
27
|
_MAX_TOKEN_BYTES = 16 * 1024
|
|
28
28
|
_MAX_PROBE_RESPONSE_BYTES = 64 * 1024
|
|
29
29
|
_MACHINE_SETUP_PROTOCOL_VERSION = 1
|
|
30
|
-
_PROBE_USER_AGENT = "inline-hermes-agent-adapter/0.0.18
|
|
30
|
+
_PROBE_USER_AGENT = "inline-hermes-agent-adapter/0.0.18"
|
|
31
31
|
_ENV_REFERENCE_RE = re.compile(r"^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$")
|
|
32
32
|
|
|
33
33
|
|
|
@@ -362,6 +362,7 @@ def register_cli(parser: argparse.ArgumentParser) -> None:
|
|
|
362
362
|
setup.add_argument("--json", action="store_true", help="Print compact machine-readable setup output.")
|
|
363
363
|
status = subs.add_parser("status", help="Show Inline adapter status", description="Check Inline configuration, sidecar, Node runtime, and optional credential identity.")
|
|
364
364
|
status.add_argument("--json", action="store_true", help="Print compact machine-readable status output.")
|
|
365
|
+
status.add_argument("--check-compatibility", action="store_true", help="Validate the installed plugin with the Hermes loader.")
|
|
365
366
|
status.add_argument("--probe", action="store_true", help="Verify the configured Inline credential and bot identity.")
|
|
366
367
|
parser.set_defaults(func=dispatch)
|
|
367
368
|
|
|
@@ -453,7 +454,9 @@ def _status(args) -> int:
|
|
|
453
454
|
and sidecar["size"] > 0
|
|
454
455
|
)
|
|
455
456
|
runtime_usable = bool(sidecar["ok"] and node["ok"])
|
|
456
|
-
|
|
457
|
+
compatibility = _compatibility_status() if getattr(args, "check_compatibility", False) else None
|
|
458
|
+
compatible = compatibility is None or compatibility["ok"]
|
|
459
|
+
ready = compatible and runtime_usable and configured and (not probe_requested or bool(probe and probe.get("ok")))
|
|
457
460
|
result = {
|
|
458
461
|
"ok": ready,
|
|
459
462
|
"ready": ready,
|
|
@@ -467,11 +470,14 @@ def _status(args) -> int:
|
|
|
467
470
|
"node": node,
|
|
468
471
|
"probeRequested": probe_requested,
|
|
469
472
|
"gateway": _gateway_status(),
|
|
473
|
+
**({"compatibility": compatibility} if compatibility is not None else {}),
|
|
470
474
|
**({"probe": probe} if probe is not None else {}),
|
|
471
475
|
}
|
|
472
476
|
if getattr(args, "json", False):
|
|
473
477
|
print(json.dumps(result, separators=(",", ":")))
|
|
474
478
|
else:
|
|
479
|
+
if compatibility is not None:
|
|
480
|
+
print(f"Hermes plugin compatible: {'yes' if compatibility['ok'] else 'no'} ({compatibility['reason']})")
|
|
475
481
|
print(f"Inline configured: {'yes' if configured else 'no'}")
|
|
476
482
|
print(f"Inline sidecar usable: {'yes' if sidecar['ok'] else 'no'}")
|
|
477
483
|
print(f"Node available: {_node_status_text(node)}")
|
|
@@ -481,7 +487,46 @@ def _status(args) -> int:
|
|
|
481
487
|
elif probe_requested:
|
|
482
488
|
print(f"Inline credential probe: {'ready' if ready else 'failed'}")
|
|
483
489
|
print("Advanced diagnostics: inline-hermes doctor --json")
|
|
484
|
-
return 0 if runtime_usable and (not probe_requested or ready) else 1
|
|
490
|
+
return 0 if compatible and runtime_usable and (not probe_requested or ready) else 1
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
def _compatibility_status() -> dict:
|
|
494
|
+
"""Attest only a successful host load of this exact installed plugin.
|
|
495
|
+
|
|
496
|
+
Never return host exception text: configuration or import errors may contain
|
|
497
|
+
credentials. A missing diagnostic API is an inconclusive check, not success.
|
|
498
|
+
"""
|
|
499
|
+
unavailable = {"ok": False, "reason": "loader_unavailable"}
|
|
500
|
+
try:
|
|
501
|
+
from hermes_cli.plugins import get_plugin_manager
|
|
502
|
+
|
|
503
|
+
manager = get_plugin_manager()
|
|
504
|
+
manager.discover_and_load()
|
|
505
|
+
plugin_dir = Path(__file__).resolve().parent
|
|
506
|
+
loaded = next((
|
|
507
|
+
item for item in manager._plugins.values()
|
|
508
|
+
if item.manifest.name == "inline-platform"
|
|
509
|
+
and Path(item.manifest.path).resolve() == plugin_dir
|
|
510
|
+
), None)
|
|
511
|
+
if loaded is None:
|
|
512
|
+
return {"ok": False, "reason": "plugin_not_loaded"}
|
|
513
|
+
if not loaded.enabled or loaded.error or loaded.module is None:
|
|
514
|
+
return {"ok": False, "reason": "plugin_load_failed"}
|
|
515
|
+
if "inline" not in loaded.tools_registered:
|
|
516
|
+
return {"ok": False, "reason": "tool_not_registered"}
|
|
517
|
+
# Older supported Hermes releases predate the moved-import scanner.
|
|
518
|
+
# Their loader still checks real imports and plugin registration above.
|
|
519
|
+
try:
|
|
520
|
+
from hermes_cli.plugin_compat import plugin_hits
|
|
521
|
+
except ModuleNotFoundError as error:
|
|
522
|
+
if error.name != "hermes_cli.plugin_compat":
|
|
523
|
+
raise
|
|
524
|
+
else:
|
|
525
|
+
if plugin_hits(loaded.manifest):
|
|
526
|
+
return {"ok": False, "reason": "deprecated_imports"}
|
|
527
|
+
return {"ok": True, "reason": "loaded", "pluginPath": str(plugin_dir)}
|
|
528
|
+
except Exception:
|
|
529
|
+
return unavailable
|
|
485
530
|
|
|
486
531
|
|
|
487
532
|
def _gateway_status() -> dict:
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
name: inline-platform
|
|
2
2
|
label: Inline
|
|
3
3
|
kind: platform
|
|
4
|
-
|
|
4
|
+
provides_tools:
|
|
5
|
+
- inline
|
|
6
|
+
version: 0.0.18
|
|
7
|
+
requires_hermes: ">=0.21.4"
|
|
5
8
|
description: >
|
|
6
9
|
Inline platform adapter for Hermes Agent. The adapter runs as a native
|
|
7
10
|
Hermes Python platform plugin and supervises a local Node sidecar that uses
|