dsh-interconnect 0.11.16 → 0.11.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/dsh.plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-interconnect",
3
3
  "description": "Cross-instance message/event handoff for DeepSeek Harness (DSH): WebSocket link, model-facing tools, and companion skill.",
4
- "version": "0.11.16",
4
+ "version": "0.11.18",
5
5
  "entry": {
6
6
  "name": "dsh-interconnect/interconnect",
7
7
  "inject": ["agents", "credentials"]
package/lib/index.js CHANGED
@@ -835,6 +835,7 @@ var PLUGIN_SOURCE = "dsh-interconnect";
835
835
  var MAX_LINK_FRAME_BYTES = 1024 * 1024;
836
836
  var LINK_HANDSHAKE_TIMEOUT_MS = 1e4;
837
837
  var LINK_CHANNEL = "/interconnect/link";
838
+ var MAX_INSTANCE_ID_CHARS = 256;
838
839
  var MAX_REQUEST_ID_CHARS = 256;
839
840
  var MAX_LISTED_SESSIONS = 100;
840
841
  var frameFitsLink = (frame) => Buffer.byteLength(JSON.stringify(frame), "utf8") <= MAX_LINK_FRAME_BYTES;
@@ -928,7 +929,7 @@ var linkFrameSchema = Schema.union([
928
929
  var InterconnectService = class extends Service {
929
930
  static inject = ["agents", "credentials"];
930
931
  static Config = Schema.object({
931
- instanceId: Schema.string().default("dsh"),
932
+ instanceId: Schema.string().max(MAX_INSTANCE_ID_CHARS).default("dsh"),
932
933
  requestTimeoutMs: Schema.natural().max(6e4).default(1e4),
933
934
  peers: Schema.dict(Schema.string()).default({}),
934
935
  delivery: Schema.union([Schema.const("followup"), Schema.const("steer"), Schema.const("inject")]).default("followup"),
@@ -938,7 +939,6 @@ var InterconnectService = class extends Service {
938
939
  requestTimeoutMs;
939
940
  delivery;
940
941
  allowResume;
941
- subscriptions = [];
942
942
  server = new WebSocketServer({ noServer: true, maxPayload: MAX_LINK_FRAME_BYTES });
943
943
  sockets = /* @__PURE__ */ new Set();
944
944
  /** Outbound peer links keyed by the peer's `instanceId`. */
@@ -948,6 +948,8 @@ var InterconnectService = class extends Service {
948
948
  peerOf = /* @__PURE__ */ new WeakMap();
949
949
  /** Configured peer an outbound dial owns a socket for; absent on inbound sockets. */
950
950
  dialedPeerOf = /* @__PURE__ */ new WeakMap();
951
+ /** Dialed sockets already reported as announcing an id other than their configured key. */
952
+ mismatchWarned = /* @__PURE__ */ new WeakSet();
951
953
  /** Sender each local session last received a send from, keyed by local session id. */
952
954
  senders = /* @__PURE__ */ new Map();
953
955
  /** In-flight frames sent over a peer link, keyed by `reqId`, awaiting a correlated result. */
@@ -995,28 +997,28 @@ var InterconnectService = class extends Service {
995
997
  socket.ping();
996
998
  }
997
999
  }, 3e4);
998
- this.subscriptions.push(ctx.on("agent/status", ({ agent, status }) => {
1000
+ ctx.on("agent/status", ({ agent, status }) => {
999
1001
  this.fanout({ kind: "agent/status", sessionId: String(agent.session.id), status });
1000
- }));
1001
- this.subscriptions.push(ctx.on("agent/created", ({ agent }) => {
1002
+ });
1003
+ ctx.on("agent/created", ({ agent }) => {
1002
1004
  this.fanout({ kind: "agent/created", sessionId: String(agent.session.id) });
1003
- }));
1004
- this.subscriptions.push(ctx.on("agent/disposed", ({ agent }) => {
1005
+ });
1006
+ ctx.on("agent/disposed", ({ agent }) => {
1005
1007
  this.fanout({ kind: "agent/disposed", sessionId: String(agent.session.id) });
1006
- }));
1007
- this.subscriptions.push(ctx.on("session/created", (session) => {
1008
+ });
1009
+ ctx.on("session/created", (session) => {
1008
1010
  const parentSessionId = session.header.parentSession === void 0 ? void 0 : String(session.header.parentSession);
1009
1011
  this.fanout({
1010
1012
  kind: "session/created",
1011
1013
  sessionId: String(session.id),
1012
1014
  ...parentSessionId === void 0 ? {} : { parentSessionId }
1013
1015
  });
1014
- }));
1015
- this.subscriptions.push(ctx.on("session/disposed", (session) => {
1016
+ });
1017
+ ctx.on("session/disposed", (session) => {
1016
1018
  this.senders.delete(String(session.id));
1017
1019
  this.fanout({ kind: "session/disposed", sessionId: String(session.id) });
1018
- }));
1019
- this.subscriptions.push(ctx.on("subagent/end", (info) => {
1020
+ });
1021
+ ctx.on("subagent/end", (info) => {
1020
1022
  if (!info.local) return;
1021
1023
  this.fanout({
1022
1024
  kind: "subagent/end",
@@ -1024,10 +1026,7 @@ var InterconnectService = class extends Service {
1024
1026
  childSessionId: String(info.id),
1025
1027
  stopReason: info.stopReason
1026
1028
  });
1027
- }));
1028
- ctx.effect(() => () => {
1029
- for (const dispose of this.subscriptions.splice(0)) dispose();
1030
- }, "interconnect: event subscriptions");
1029
+ });
1031
1030
  ctx.effect(() => () => {
1032
1031
  if (this.heartbeatTimer !== void 0) clearInterval(this.heartbeatTimer);
1033
1032
  for (const state of this.linkStates.values()) state.close();
@@ -1217,10 +1216,12 @@ var InterconnectService = class extends Service {
1217
1216
  * dialed link plus the peer's inbound one), so one event must leave over one
1218
1217
  * of them. Which one is decided by local ownership, not by the peer: a dialed
1219
1218
  * socket is a configured peer's link and always sends. An inbound socket is
1220
- * skipped only when a dialed link to the id that socket itself announced is
1221
- * open, so an announcement can suppress nothing but a duplicate the
1222
- * controlled link already carries — an impostor cannot drop an event for a
1223
- * peer, and without a dialed link every inbound socket receives it.
1219
+ * skipped only when this instance has an open dialed link configured under
1220
+ * the id that socket itself announced, so a self-reported announcement can
1221
+ * never silence another peer's link; with no such dialed link every inbound
1222
+ * socket receives the event. A peer listed under a key other than the id it
1223
+ * announces is warned about once per link, because then its own inbound
1224
+ * socket is not attributable and the peer receives each event twice.
1224
1225
  *
1225
1226
  * That holds once a peer's announcement has been seen. Between this
1226
1227
  * instance's dialed link opening and the peer's `hello` arriving on its
@@ -1271,12 +1272,7 @@ var InterconnectService = class extends Service {
1271
1272
  if (query.kind === "ping") {
1272
1273
  result = { pong: true, instance: this.instanceId };
1273
1274
  } else if (query.kind === "list") {
1274
- const rowBudget = this.listRowsBudgetBytes(reqId);
1275
- if (rowBudget < 0) {
1276
- this.ctx.logger.warn("interconnect: list answer cannot fit the link frame cap; not answering");
1277
- return;
1278
- }
1279
- result = this.listSessions(rowBudget);
1275
+ result = this.listSessions(this.listRowsBudgetBytes(reqId));
1280
1276
  } else {
1281
1277
  const payload = {
1282
1278
  sender: this.peerOf.get(socket) ?? "unknown-peer",
@@ -1308,10 +1304,11 @@ var InterconnectService = class extends Service {
1308
1304
  * Bytes one `list` answer may spend on its `sessions` rows: the frame cap
1309
1305
  * minus the serialized envelope that answer will carry. The envelope holds
1310
1306
  * the peer-supplied `reqId` and this instance's own id, so it is measured per
1311
- * answer instead of reserved with a fixed constant.
1307
+ * answer instead of reserved with a fixed constant. Both ids are bounded
1308
+ * ({@link MAX_REQUEST_ID_CHARS} and {@link MAX_INSTANCE_ID_CHARS} characters),
1309
+ * so the envelope always fits and the budget is always positive.
1312
1310
  * @param reqId - the request id the answer has to echo.
1313
- * @returns the byte budget for the rows, negative when even an empty answer
1314
- * exceeds the cap and so cannot be sent at all.
1311
+ * @returns the byte budget for the rows.
1315
1312
  */
1316
1313
  listRowsBudgetBytes(reqId) {
1317
1314
  const envelope = {
@@ -1576,6 +1573,13 @@ var InterconnectService = class extends Service {
1576
1573
  const frame = parsed;
1577
1574
  if (frame.type === "hello") {
1578
1575
  this.peerOf.set(socket, frame.sender);
1576
+ const dialedPeer = this.dialedPeerOf.get(socket);
1577
+ if (dialedPeer !== void 0 && dialedPeer !== frame.sender && !this.mismatchWarned.has(socket)) {
1578
+ this.mismatchWarned.add(socket);
1579
+ this.ctx.logger.warn(
1580
+ `interconnect: peer configured as ${dialedPeer} announces ${frame.sender}; list a peer under the instanceId it announces, or the duplicate inbound link is not recognised`
1581
+ );
1582
+ }
1579
1583
  return;
1580
1584
  }
1581
1585
  if (frame.type === "event") {
@@ -835,6 +835,7 @@ var PLUGIN_SOURCE = "dsh-interconnect";
835
835
  var MAX_LINK_FRAME_BYTES = 1024 * 1024;
836
836
  var LINK_HANDSHAKE_TIMEOUT_MS = 1e4;
837
837
  var LINK_CHANNEL = "/interconnect/link";
838
+ var MAX_INSTANCE_ID_CHARS = 256;
838
839
  var MAX_REQUEST_ID_CHARS = 256;
839
840
  var MAX_LISTED_SESSIONS = 100;
840
841
  var frameFitsLink = (frame) => Buffer.byteLength(JSON.stringify(frame), "utf8") <= MAX_LINK_FRAME_BYTES;
@@ -928,7 +929,7 @@ var linkFrameSchema = Schema.union([
928
929
  var InterconnectService = class extends Service {
929
930
  static inject = ["agents", "credentials"];
930
931
  static Config = Schema.object({
931
- instanceId: Schema.string().default("dsh"),
932
+ instanceId: Schema.string().max(MAX_INSTANCE_ID_CHARS).default("dsh"),
932
933
  requestTimeoutMs: Schema.natural().max(6e4).default(1e4),
933
934
  peers: Schema.dict(Schema.string()).default({}),
934
935
  delivery: Schema.union([Schema.const("followup"), Schema.const("steer"), Schema.const("inject")]).default("followup"),
@@ -938,7 +939,6 @@ var InterconnectService = class extends Service {
938
939
  requestTimeoutMs;
939
940
  delivery;
940
941
  allowResume;
941
- subscriptions = [];
942
942
  server = new WebSocketServer({ noServer: true, maxPayload: MAX_LINK_FRAME_BYTES });
943
943
  sockets = /* @__PURE__ */ new Set();
944
944
  /** Outbound peer links keyed by the peer's `instanceId`. */
@@ -948,6 +948,8 @@ var InterconnectService = class extends Service {
948
948
  peerOf = /* @__PURE__ */ new WeakMap();
949
949
  /** Configured peer an outbound dial owns a socket for; absent on inbound sockets. */
950
950
  dialedPeerOf = /* @__PURE__ */ new WeakMap();
951
+ /** Dialed sockets already reported as announcing an id other than their configured key. */
952
+ mismatchWarned = /* @__PURE__ */ new WeakSet();
951
953
  /** Sender each local session last received a send from, keyed by local session id. */
952
954
  senders = /* @__PURE__ */ new Map();
953
955
  /** In-flight frames sent over a peer link, keyed by `reqId`, awaiting a correlated result. */
@@ -995,28 +997,28 @@ var InterconnectService = class extends Service {
995
997
  socket.ping();
996
998
  }
997
999
  }, 3e4);
998
- this.subscriptions.push(ctx.on("agent/status", ({ agent, status }) => {
1000
+ ctx.on("agent/status", ({ agent, status }) => {
999
1001
  this.fanout({ kind: "agent/status", sessionId: String(agent.session.id), status });
1000
- }));
1001
- this.subscriptions.push(ctx.on("agent/created", ({ agent }) => {
1002
+ });
1003
+ ctx.on("agent/created", ({ agent }) => {
1002
1004
  this.fanout({ kind: "agent/created", sessionId: String(agent.session.id) });
1003
- }));
1004
- this.subscriptions.push(ctx.on("agent/disposed", ({ agent }) => {
1005
+ });
1006
+ ctx.on("agent/disposed", ({ agent }) => {
1005
1007
  this.fanout({ kind: "agent/disposed", sessionId: String(agent.session.id) });
1006
- }));
1007
- this.subscriptions.push(ctx.on("session/created", (session) => {
1008
+ });
1009
+ ctx.on("session/created", (session) => {
1008
1010
  const parentSessionId = session.header.parentSession === void 0 ? void 0 : String(session.header.parentSession);
1009
1011
  this.fanout({
1010
1012
  kind: "session/created",
1011
1013
  sessionId: String(session.id),
1012
1014
  ...parentSessionId === void 0 ? {} : { parentSessionId }
1013
1015
  });
1014
- }));
1015
- this.subscriptions.push(ctx.on("session/disposed", (session) => {
1016
+ });
1017
+ ctx.on("session/disposed", (session) => {
1016
1018
  this.senders.delete(String(session.id));
1017
1019
  this.fanout({ kind: "session/disposed", sessionId: String(session.id) });
1018
- }));
1019
- this.subscriptions.push(ctx.on("subagent/end", (info) => {
1020
+ });
1021
+ ctx.on("subagent/end", (info) => {
1020
1022
  if (!info.local) return;
1021
1023
  this.fanout({
1022
1024
  kind: "subagent/end",
@@ -1024,10 +1026,7 @@ var InterconnectService = class extends Service {
1024
1026
  childSessionId: String(info.id),
1025
1027
  stopReason: info.stopReason
1026
1028
  });
1027
- }));
1028
- ctx.effect(() => () => {
1029
- for (const dispose of this.subscriptions.splice(0)) dispose();
1030
- }, "interconnect: event subscriptions");
1029
+ });
1031
1030
  ctx.effect(() => () => {
1032
1031
  if (this.heartbeatTimer !== void 0) clearInterval(this.heartbeatTimer);
1033
1032
  for (const state of this.linkStates.values()) state.close();
@@ -1217,10 +1216,12 @@ var InterconnectService = class extends Service {
1217
1216
  * dialed link plus the peer's inbound one), so one event must leave over one
1218
1217
  * of them. Which one is decided by local ownership, not by the peer: a dialed
1219
1218
  * socket is a configured peer's link and always sends. An inbound socket is
1220
- * skipped only when a dialed link to the id that socket itself announced is
1221
- * open, so an announcement can suppress nothing but a duplicate the
1222
- * controlled link already carries — an impostor cannot drop an event for a
1223
- * peer, and without a dialed link every inbound socket receives it.
1219
+ * skipped only when this instance has an open dialed link configured under
1220
+ * the id that socket itself announced, so a self-reported announcement can
1221
+ * never silence another peer's link; with no such dialed link every inbound
1222
+ * socket receives the event. A peer listed under a key other than the id it
1223
+ * announces is warned about once per link, because then its own inbound
1224
+ * socket is not attributable and the peer receives each event twice.
1224
1225
  *
1225
1226
  * That holds once a peer's announcement has been seen. Between this
1226
1227
  * instance's dialed link opening and the peer's `hello` arriving on its
@@ -1271,12 +1272,7 @@ var InterconnectService = class extends Service {
1271
1272
  if (query.kind === "ping") {
1272
1273
  result = { pong: true, instance: this.instanceId };
1273
1274
  } else if (query.kind === "list") {
1274
- const rowBudget = this.listRowsBudgetBytes(reqId);
1275
- if (rowBudget < 0) {
1276
- this.ctx.logger.warn("interconnect: list answer cannot fit the link frame cap; not answering");
1277
- return;
1278
- }
1279
- result = this.listSessions(rowBudget);
1275
+ result = this.listSessions(this.listRowsBudgetBytes(reqId));
1280
1276
  } else {
1281
1277
  const payload = {
1282
1278
  sender: this.peerOf.get(socket) ?? "unknown-peer",
@@ -1308,10 +1304,11 @@ var InterconnectService = class extends Service {
1308
1304
  * Bytes one `list` answer may spend on its `sessions` rows: the frame cap
1309
1305
  * minus the serialized envelope that answer will carry. The envelope holds
1310
1306
  * the peer-supplied `reqId` and this instance's own id, so it is measured per
1311
- * answer instead of reserved with a fixed constant.
1307
+ * answer instead of reserved with a fixed constant. Both ids are bounded
1308
+ * ({@link MAX_REQUEST_ID_CHARS} and {@link MAX_INSTANCE_ID_CHARS} characters),
1309
+ * so the envelope always fits and the budget is always positive.
1312
1310
  * @param reqId - the request id the answer has to echo.
1313
- * @returns the byte budget for the rows, negative when even an empty answer
1314
- * exceeds the cap and so cannot be sent at all.
1311
+ * @returns the byte budget for the rows.
1315
1312
  */
1316
1313
  listRowsBudgetBytes(reqId) {
1317
1314
  const envelope = {
@@ -1576,6 +1573,13 @@ var InterconnectService = class extends Service {
1576
1573
  const frame = parsed;
1577
1574
  if (frame.type === "hello") {
1578
1575
  this.peerOf.set(socket, frame.sender);
1576
+ const dialedPeer = this.dialedPeerOf.get(socket);
1577
+ if (dialedPeer !== void 0 && dialedPeer !== frame.sender && !this.mismatchWarned.has(socket)) {
1578
+ this.mismatchWarned.add(socket);
1579
+ this.ctx.logger.warn(
1580
+ `interconnect: peer configured as ${dialedPeer} announces ${frame.sender}; list a peer under the instanceId it announces, or the duplicate inbound link is not recognised`
1581
+ );
1582
+ }
1579
1583
  return;
1580
1584
  }
1581
1585
  if (frame.type === "event") {