@inline-chat/hermes-agent-adapter 0.0.9 → 0.0.11
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 +2 -2
- package/dist/install.js +4 -0
- package/package.json +3 -3
- package/plugin/inline/adapter.py +23 -16
- package/plugin/inline/cli.py +1 -1
- package/plugin/inline/plugin.yaml +1 -1
- package/plugin/inline/sidecar/index.mjs +32 -2
package/README.md
CHANGED
|
@@ -147,7 +147,7 @@ uv run ./hermes plugins list --plain --no-bundled
|
|
|
147
147
|
Expected local output includes:
|
|
148
148
|
|
|
149
149
|
```text
|
|
150
|
-
enabled user 0.0.
|
|
150
|
+
enabled user 0.0.11 inline-platform
|
|
151
151
|
```
|
|
152
152
|
|
|
153
153
|
## Update Or Reinstall
|
|
@@ -170,7 +170,7 @@ mismatch, rerun the same command after rebuilding or upgrading the package.
|
|
|
170
170
|
|
|
171
171
|
- Hermes Agent: requires the external user plugin registry and native platform
|
|
172
172
|
plugin loader available in Hermes Agent `0.17.x`. This package was validated
|
|
173
|
-
against Hermes Agent `0.20.
|
|
173
|
+
against Hermes Agent `0.20.6` from source commit `31e41eed`.
|
|
174
174
|
- Node.js: `>=20` is required for the bundled sidecar. Hermes-managed Node 22,
|
|
175
175
|
system Node, or an explicit `INLINE_NODE_BIN` path all work.
|
|
176
176
|
- Inline transport: the sidecar uses `@inline-chat/realtime-sdk@0.0.16` and is
|
package/dist/install.js
CHANGED
|
@@ -7009,6 +7009,10 @@ var sensitiveUrlParams = new Set([
|
|
|
7009
7009
|
"key",
|
|
7010
7010
|
"token"
|
|
7011
7011
|
]);
|
|
7012
|
+
var botSettingsEventKinds = new Set([
|
|
7013
|
+
"bot.chatSettings.request",
|
|
7014
|
+
"bot.chatSettings.item.invoke"
|
|
7015
|
+
]);
|
|
7012
7016
|
function redactText(value, secrets) {
|
|
7013
7017
|
let text = value instanceof Error ? value.message : String(value);
|
|
7014
7018
|
for (const secret of secrets) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inline-chat/hermes-agent-adapter",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
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",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
},
|
|
82
82
|
"machineSetupProtocol": 1,
|
|
83
83
|
"minHermesVersion": "0.17.0",
|
|
84
|
-
"testedHermesVersion": "0.20.
|
|
85
|
-
"testedHermesCommit": "
|
|
84
|
+
"testedHermesVersion": "0.20.6",
|
|
85
|
+
"testedHermesCommit": "31e41eed"
|
|
86
86
|
}
|
|
87
87
|
}
|
package/plugin/inline/adapter.py
CHANGED
|
@@ -66,7 +66,11 @@ _DEDUP_MAX_SIZE = 5000
|
|
|
66
66
|
_DEDUP_WINDOW_SECONDS = 48 * 3600
|
|
67
67
|
_CHAT_INFO_CACHE_SECONDS = 10 * 60
|
|
68
68
|
_CHAT_INFO_CACHE_MAX_SIZE = 512
|
|
69
|
-
|
|
69
|
+
_BOT_SETTINGS_CHAT_INFO_TIMEOUT_SECONDS = 2.0
|
|
70
|
+
# Provider discovery may invoke host CLIs. Keep repeated panel opens and
|
|
71
|
+
# unrelated mutations off that slow path while always injecting the live
|
|
72
|
+
# current/default model into the document below.
|
|
73
|
+
_BOT_SETTINGS_MODEL_CATALOG_CACHE_SECONDS = 5 * 60
|
|
70
74
|
_DEFAULT_CONTEXT_BACKFILL = "selective"
|
|
71
75
|
_CONTEXT_BACKFILL_MODES = {"off", "selective", "always"}
|
|
72
76
|
_DEFAULT_THREAD_CONTEXT_LIMIT = 30
|
|
@@ -1013,7 +1017,14 @@ class InlineAdapter(BasePlatformAdapter):
|
|
|
1013
1017
|
if not chat_id or not actor_id:
|
|
1014
1018
|
return {"access": "guideOnly", "scope_id": chat_id or "unknown", "reply_threads": "auto"}
|
|
1015
1019
|
|
|
1016
|
-
|
|
1020
|
+
try:
|
|
1021
|
+
info = await asyncio.wait_for(
|
|
1022
|
+
self._get_chat_info(chat_id),
|
|
1023
|
+
timeout=_BOT_SETTINGS_CHAT_INFO_TIMEOUT_SECONDS,
|
|
1024
|
+
)
|
|
1025
|
+
except asyncio.TimeoutError:
|
|
1026
|
+
logger.warning("[inline] agent settings chat metadata timed out")
|
|
1027
|
+
info = {}
|
|
1017
1028
|
if not info:
|
|
1018
1029
|
return {
|
|
1019
1030
|
"access": "guideOnly",
|
|
@@ -1050,7 +1061,7 @@ class InlineAdapter(BasePlatformAdapter):
|
|
|
1050
1061
|
"actor_id": actor_id,
|
|
1051
1062
|
"chat_type": chat_type,
|
|
1052
1063
|
"is_reply_thread": is_reply_thread,
|
|
1053
|
-
"following": self._chat_follow_mode_following(info),
|
|
1064
|
+
"following": None if chat_type == "dm" else self._chat_follow_mode_following(info),
|
|
1054
1065
|
"reply_threads": self._reply_thread_mode_for_chat(scope_chat_id),
|
|
1055
1066
|
"can_set_default_model": can_modify,
|
|
1056
1067
|
"source": source,
|
|
@@ -1242,13 +1253,13 @@ class InlineAdapter(BasePlatformAdapter):
|
|
|
1242
1253
|
}},
|
|
1243
1254
|
})
|
|
1244
1255
|
|
|
1245
|
-
sections: List[Dict[str, Any]] = [
|
|
1246
|
-
|
|
1247
|
-
{"id": "attention", "items": [{
|
|
1256
|
+
sections: List[Dict[str, Any]] = [{"id": "runtime", "items": runtime_items}]
|
|
1257
|
+
if context.get("following") is not None:
|
|
1258
|
+
sections.append({"id": "attention", "items": [{
|
|
1248
1259
|
"id": "following", "label": "Following", "description": "Wake on eligible activity.", **common,
|
|
1249
1260
|
"control": {"oneofKind": "toggle", "toggle": {"value": bool(context.get("following"))}},
|
|
1250
|
-
}]}
|
|
1251
|
-
|
|
1261
|
+
}]})
|
|
1262
|
+
sections.append({"id": "replies", "items": [{
|
|
1252
1263
|
"id": "reply-threads", "label": "Reply in threads", **common,
|
|
1253
1264
|
"control": {"oneofKind": "select", "select": {
|
|
1254
1265
|
"value": context.get("reply_threads") or "auto",
|
|
@@ -1258,8 +1269,7 @@ class InlineAdapter(BasePlatformAdapter):
|
|
|
1258
1269
|
{"value": "off", "label": "Off", "description": "Stay in chat.", "disabled": False},
|
|
1259
1270
|
],
|
|
1260
1271
|
}},
|
|
1261
|
-
}]}
|
|
1262
|
-
]
|
|
1272
|
+
}]})
|
|
1263
1273
|
if disabled:
|
|
1264
1274
|
sections.append({"id": "access", "items": [{
|
|
1265
1275
|
"id": "read-only", "label": "Read-only", "disabled": False,
|
|
@@ -1343,14 +1353,11 @@ class InlineAdapter(BasePlatformAdapter):
|
|
|
1343
1353
|
runner = context.get("runner")
|
|
1344
1354
|
source = context.get("source")
|
|
1345
1355
|
if item_id == "following" and value_body.get("oneofKind") == "boolValue":
|
|
1356
|
+
if context.get("following") is None:
|
|
1357
|
+
raise ValueError("following unavailable")
|
|
1346
1358
|
enabled = bool(value_body.get("boolValue"))
|
|
1347
|
-
target = (
|
|
1348
|
-
{"userId": context["actor_id"]}
|
|
1349
|
-
if context.get("chat_type") == "dm"
|
|
1350
|
-
else {"chatId": context["chat_id"]}
|
|
1351
|
-
)
|
|
1352
1359
|
await self._sidecar_call("/follow-mode", {
|
|
1353
|
-
"target":
|
|
1360
|
+
"target": {"chatId": context["chat_id"]},
|
|
1354
1361
|
"mode": "following" if enabled else "unfollowed",
|
|
1355
1362
|
})
|
|
1356
1363
|
self._invalidate_chat_info(context["chat_id"])
|
package/plugin/inline/cli.py
CHANGED
|
@@ -26,7 +26,7 @@ _CLI_INSTALL_URL = "https://inline.chat/cli/install.sh"
|
|
|
26
26
|
_MAX_TOKEN_BYTES = 16 * 1024
|
|
27
27
|
_MAX_PROBE_RESPONSE_BYTES = 64 * 1024
|
|
28
28
|
_MACHINE_SETUP_PROTOCOL_VERSION = 1
|
|
29
|
-
_PROBE_USER_AGENT = "inline-hermes-agent-adapter/0.0.
|
|
29
|
+
_PROBE_USER_AGENT = "inline-hermes-agent-adapter/0.0.11"
|
|
30
30
|
_ENV_REFERENCE_RE = re.compile(r"^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$")
|
|
31
31
|
|
|
32
32
|
|
|
@@ -45251,6 +45251,7 @@ var portableCoreV1Vector = {
|
|
|
45251
45251
|
};
|
|
45252
45252
|
// src/sidecar/contract.ts
|
|
45253
45253
|
var MAX_INLINE_ID = 9223372036854775807n;
|
|
45254
|
+
var MAX_UINT64 = 18446744073709551615n;
|
|
45254
45255
|
var sensitiveUrlParams = new Set([
|
|
45255
45256
|
"access_token",
|
|
45256
45257
|
"auth",
|
|
@@ -45258,6 +45259,13 @@ var sensitiveUrlParams = new Set([
|
|
|
45258
45259
|
"key",
|
|
45259
45260
|
"token"
|
|
45260
45261
|
]);
|
|
45262
|
+
var botSettingsEventKinds = new Set([
|
|
45263
|
+
"bot.chatSettings.request",
|
|
45264
|
+
"bot.chatSettings.item.invoke"
|
|
45265
|
+
]);
|
|
45266
|
+
function inboundEventNeedsSenderResolution(event) {
|
|
45267
|
+
return !botSettingsEventKinds.has(event.kind ?? "");
|
|
45268
|
+
}
|
|
45261
45269
|
|
|
45262
45270
|
class SidecarError extends Error {
|
|
45263
45271
|
errorKind;
|
|
@@ -45546,6 +45554,25 @@ function parseInlineId(value, field) {
|
|
|
45546
45554
|
throw new SidecarError(`${field} must be a positive signed 64-bit integer`, "bad_format");
|
|
45547
45555
|
}
|
|
45548
45556
|
}
|
|
45557
|
+
function parseUnsigned64Id(value, field) {
|
|
45558
|
+
try {
|
|
45559
|
+
if (typeof value === "number" && (!Number.isSafeInteger(value) || value <= 0)) {
|
|
45560
|
+
throw new Error("unsafe number");
|
|
45561
|
+
}
|
|
45562
|
+
const raw = typeof value === "string" ? value.trim() : value;
|
|
45563
|
+
if (typeof raw === "string" && !/^[1-9][0-9]*$/.test(raw))
|
|
45564
|
+
throw new Error("invalid digits");
|
|
45565
|
+
if (typeof raw !== "string" && typeof raw !== "bigint" && typeof raw !== "number") {
|
|
45566
|
+
throw new Error("invalid type");
|
|
45567
|
+
}
|
|
45568
|
+
const parsed = BigInt(raw);
|
|
45569
|
+
if (parsed <= 0n || parsed > MAX_UINT64)
|
|
45570
|
+
throw new Error("out of range");
|
|
45571
|
+
return parsed;
|
|
45572
|
+
} catch {
|
|
45573
|
+
throw new SidecarError(`${field} must be a positive unsigned 64-bit integer`, "bad_format");
|
|
45574
|
+
}
|
|
45575
|
+
}
|
|
45549
45576
|
function defaultErrorText(error) {
|
|
45550
45577
|
return error instanceof Error ? error.message : String(error);
|
|
45551
45578
|
}
|
|
@@ -45828,7 +45855,7 @@ async function connectClientLoop() {
|
|
|
45828
45855
|
async function consumeEvents() {
|
|
45829
45856
|
try {
|
|
45830
45857
|
for await (const event of client.events()) {
|
|
45831
|
-
const senderResolution = await resolveInboundSender(event);
|
|
45858
|
+
const senderResolution = inboundEventNeedsSenderResolution(event) ? await resolveInboundSender(event) : { provenanceVerified: true };
|
|
45832
45859
|
const normalized = normalizeInboundEvent(event, meId, senderResolution.profile, meUsername);
|
|
45833
45860
|
await deliver(senderResolution.provenanceVerified ? normalized : { ...asRecord(normalized), _inlineSenderProvenanceVerified: false });
|
|
45834
45861
|
}
|
|
@@ -46572,7 +46599,10 @@ async function endpointAnswerAction(res, body) {
|
|
|
46572
46599
|
}
|
|
46573
46600
|
async function endpointAnswerBotSettings(res, body) {
|
|
46574
46601
|
const record2 = asRecord(body);
|
|
46575
|
-
|
|
46602
|
+
if (record2.requestId == null || record2.requestId === "") {
|
|
46603
|
+
throw new SidecarError("missing requestId", "bad_format");
|
|
46604
|
+
}
|
|
46605
|
+
const requestId = parseUnsigned64Id(record2.requestId, "requestId");
|
|
46576
46606
|
const response = asRecord(record2.response);
|
|
46577
46607
|
await client.answerBotChatSettings({ requestId, response });
|
|
46578
46608
|
writeJson(res, 200, { ok: true, result: {} });
|