@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 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.9 inline-platform
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.0` from source commit `3c27eb6`.
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.9",
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.0",
85
- "testedHermesCommit": "3c27eb6"
84
+ "testedHermesVersion": "0.20.6",
85
+ "testedHermesCommit": "31e41eed"
86
86
  }
87
87
  }
@@ -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
- _BOT_SETTINGS_MODEL_CATALOG_CACHE_SECONDS = 60
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
- info = await self._get_chat_info(chat_id)
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
- {"id": "runtime", "items": runtime_items},
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
- {"id": "replies", "items": [{
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": 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"])
@@ -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.9"
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
 
@@ -1,7 +1,7 @@
1
1
  name: inline-platform
2
2
  label: Inline
3
3
  kind: platform
4
- version: 0.0.9
4
+ version: 0.0.11
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
@@ -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
- const requestId = readRequiredInlineId(record2, "requestId");
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: {} });