dsh-interconnect 0.7.0 → 0.9.0
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 +60 -24
- package/lib/index.js +268 -285
- package/lib/interconnect/index.js +268 -285
- package/lib/interconnect/index.js.map +3 -3
- package/lib/tool-interconnect/index.js +13 -14
- package/lib/tool-interconnect/index.js.map +2 -2
- package/lib/types/interconnect/index.d.ts +57 -33
- package/lib/types/interconnect/index.d.ts.map +1 -1
- package/lib/types/interconnect/types.d.ts +86 -32
- package/lib/types/interconnect/types.d.ts.map +1 -1
- package/lib/types/tool-interconnect/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -7,10 +7,10 @@ function apply(ctx) {
|
|
|
7
7
|
name: "interconnect_send",
|
|
8
8
|
description: 'Deliver one text message to a live session on another DSH instance (same machine, another machine, or another session), over a shared-secret-authenticated channel. Returns whether the peer instance received it and which instance answered. Only a session with a running agent can receive a message; when none is running the result reports reason "session-not-live", and interconnect_list shows which sessions are live there.',
|
|
9
9
|
parameters: {
|
|
10
|
-
|
|
10
|
+
instanceId: {
|
|
11
11
|
type: "string",
|
|
12
12
|
required: true,
|
|
13
|
-
description: "
|
|
13
|
+
description: "The peer instance id to deliver to, as configured under this instance's interconnect peers map. Deliveries go over the persistent link to that instance."
|
|
14
14
|
},
|
|
15
15
|
sessionId: {
|
|
16
16
|
type: "string",
|
|
@@ -69,15 +69,14 @@ function apply(ctx) {
|
|
|
69
69
|
},
|
|
70
70
|
async execute(args, exec) {
|
|
71
71
|
const sessionId = exec.agent?.session.id;
|
|
72
|
-
const self = sessionId === void 0 ?
|
|
72
|
+
const self = interconnect.selfSender(sessionId === void 0 ? "" : String(sessionId));
|
|
73
73
|
const result = await interconnect.send({
|
|
74
|
-
|
|
74
|
+
instanceId: args.instanceId,
|
|
75
75
|
sessionId: args.sessionId,
|
|
76
76
|
text: args.text,
|
|
77
|
-
// Attribute this instance as the sender
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
...self === void 0 ? {} : { sender: self },
|
|
77
|
+
// Attribute this instance as the sender so the peer can reply back. The
|
|
78
|
+
// calling session id comes from the executing agent (the session sending).
|
|
79
|
+
sender: self,
|
|
81
80
|
...args.delivery === void 0 ? {} : { delivery: args.delivery },
|
|
82
81
|
...args.resume === void 0 ? {} : { resume: args.resume }
|
|
83
82
|
});
|
|
@@ -93,10 +92,10 @@ function apply(ctx) {
|
|
|
93
92
|
name: "interconnect_ping",
|
|
94
93
|
description: "Probe a peer DSH instance for liveness and identity over the shared-secret channel. Returns the peer instance id when reachable, or null on transport/auth failure.",
|
|
95
94
|
parameters: {
|
|
96
|
-
|
|
95
|
+
instanceId: {
|
|
97
96
|
type: "string",
|
|
98
97
|
required: true,
|
|
99
|
-
description: "
|
|
98
|
+
description: "The peer instance id to probe, as configured under this instance's interconnect peers map."
|
|
100
99
|
}
|
|
101
100
|
},
|
|
102
101
|
output: {
|
|
@@ -114,7 +113,7 @@ function apply(ctx) {
|
|
|
114
113
|
}]
|
|
115
114
|
},
|
|
116
115
|
async execute(args) {
|
|
117
|
-
const result = await interconnect.ping(args.
|
|
116
|
+
const result = await interconnect.ping(args.instanceId);
|
|
118
117
|
if (result === void 0) return { reachable: false };
|
|
119
118
|
return { reachable: true, instance: result.instance };
|
|
120
119
|
}
|
|
@@ -123,10 +122,10 @@ function apply(ctx) {
|
|
|
123
122
|
name: "interconnect_list",
|
|
124
123
|
description: "List the live sessions on a peer DSH instance, so a message can be addressed without knowing a session id in advance. Every returned sessionId is a valid interconnect_send target at the time of the call. Only live sessions appear: a session that exists on the peer but has no running agent is not listed and cannot receive a message.",
|
|
125
124
|
parameters: {
|
|
126
|
-
|
|
125
|
+
instanceId: {
|
|
127
126
|
type: "string",
|
|
128
127
|
required: true,
|
|
129
|
-
description: "
|
|
128
|
+
description: "The peer instance id to list, as configured under this instance's interconnect peers map."
|
|
130
129
|
}
|
|
131
130
|
},
|
|
132
131
|
output: {
|
|
@@ -165,7 +164,7 @@ function apply(ctx) {
|
|
|
165
164
|
}
|
|
166
165
|
},
|
|
167
166
|
async execute(args) {
|
|
168
|
-
const result = await interconnect.list(args.
|
|
167
|
+
const result = await interconnect.list(args.instanceId);
|
|
169
168
|
if (result === void 0) return { reachable: false };
|
|
170
169
|
return {
|
|
171
170
|
reachable: true,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/tool-interconnect/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Model-facing tools for cross-instance message handoff: `interconnect_send`\n * delivers one text message to a live session on a peer DSH instance, and\n * `interconnect_ping` probes a peer's liveness and identity.\n *\n * The tools consume the host-plane `interconnect` service and publish nothing\n * themselves, so this row sits as an ordinary tool plugin in a preset while\n * the service it reaches stays host-side (the same split `tool-goal` uses\n * against `goals`).\n * @module @deepseek-ai/dsh-tool-interconnect\n */\n\nimport { Context } from '@deepseek-ai/cordis'\nimport { defineTool } from '@deepseek-ai/dsh-tools'\n// Activates the `Context.interconnect` merge declared by the interconnect service plugin.\nimport type {} from '../interconnect/index.ts'\n\n/** Services required before the tools can register. */\nexport const inject = ['interconnect', 'tools']\n\n/**\n * Register the two tool surfaces. Registration is idempotent per fiber; the\n * tools unregister with the owning fiber.\n * @param ctx - connection context carrying the interconnect service and the tool registry.\n */\nexport function apply(ctx: Context): void {\n const interconnect = ctx.interconnect\n\n ctx.tools.register(defineTool({\n name: 'interconnect_send',\n description: 'Deliver one text message to a live session on another DSH instance (same machine, '\n + 'another machine, or another session), over a shared-secret-authenticated channel. '\n + 'Returns whether the peer instance received it and which instance answered. '\n + 'Only a session with a running agent can receive a message; when none is running the result '\n + 'reports reason \"session-not-live\", and interconnect_list shows which sessions are live there.',\n parameters: {\n baseUrl: {\n type: 'string',\n required: true,\n description: 'Receiver instance origin, e.g. http://127.0.0.1:3080 or http://peer-host:9001.',\n },\n sessionId: {\n type: 'string',\n required: true,\n description: 'Target session id on the receiving instance to deliver the message to.',\n },\n text: {\n type: 'string',\n required: true,\n description: 'Message text delivered to the peer session.',\n },\n delivery: {\n type: 'string',\n enum: ['followup', 'steer', 'inject'],\n description: 'How the message reaches the target agent. `followup` queues it as its own turn '\n + 'behind whatever that agent is doing now. `steer` cuts into the nearest step boundary of a '\n + 'running turn, so an urgent message does not wait for that turn to end. `inject` seeds '\n + 'context without waking an idle agent, so it may sit unread. Omit to use the receiver\\'s '\n + 'configured default.',\n },\n resume: {\n type: 'boolean',\n description: 'Wake the target session if it is persisted but has no running agent. Off by '\n + 'default because delivery to a woken session starts a real agent turn \u2014 a billed model call '\n + 'with that session\\'s full toolset \u2014 in a conversation nobody is watching. Prefer '\n + 'interconnect_list and an already-live target; set this only when that specific session must '\n + 'be reached. The receiver may refuse, answering reason \"resume-refused\".',\n },\n },\n output: {\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n delivered: { type: 'boolean', required: true },\n instance: { type: 'string', required: true },\n delivery: { type: 'string' },\n reason: { type: 'string' },\n },\n },\n render: (_args, value) => {\n if (value.delivered) {\n return [{\n type: 'text',\n text: `delivered to ${value.instance}${value.delivery === undefined ? '' : ` via ${value.delivery}`}`,\n }]\n }\n // Each failure gets the response it actually needs: a not-live target is\n // the caller's to re-choose, while an unreachable peer may just be worth\n // retrying. The old single line claimed \"no live session\" even when the\n // peer never answered, which pointed at the wrong thing entirely.\n const text = ((): string => {\n switch (value.reason) {\n case 'unreachable':\n return `not delivered: ${value.instance} did not answer (unreachable or unauthorized)`\n case 'resume-refused':\n return `not delivered: ${value.instance} does not allow waking persisted sessions`\n case 'resume-failed':\n return `not delivered: could not wake \"${_args.sessionId}\" on ${value.instance}`\n + ' (no such persisted session, or another owner holds it)'\n case 'session-owned-by-subagent':\n return `not delivered: \"${_args.sessionId}\" is a subagent's session on ${value.instance}`\n + ' \u2014 its parent agent owns delivery, so reach it through that parent'\n default:\n return `not delivered: no live session \"${_args.sessionId}\" on ${value.instance}`\n + ' \u2014 use interconnect_list to see which sessions are live there,'\n + ' or set resume to wake this one'\n }\n })()\n return [{ type: 'text', text }]\n },\n },\n async execute(args, exec) {\n const sessionId = exec.agent?.session.id\n const self = sessionId === undefined ? undefined : interconnect.selfSender(String(sessionId))\n const result = await interconnect.send({\n baseUrl: args.baseUrl,\n sessionId: args.sessionId,\n text: args.text,\n // Attribute this instance as the sender when configured, so the peer\n // can reply back. The calling session id comes from the executing\n // agent (the session that is sending).\n ...(self === undefined ? {} : { sender: self }),\n ...(args.delivery === undefined ? {} : { delivery: args.delivery }),\n ...(args.resume === undefined ? {} : { resume: args.resume }),\n })\n return {\n delivered: result.delivered,\n instance: result.instance,\n ...(result.delivery === undefined ? {} : { delivery: result.delivery }),\n ...(result.reason === undefined ? {} : { reason: result.reason }),\n }\n },\n }))\n\n ctx.tools.register(defineTool({\n name: 'interconnect_ping',\n description: 'Probe a peer DSH instance for liveness and identity over the shared-secret channel. '\n + 'Returns the peer instance id when reachable, or null on transport/auth failure.',\n parameters: {\n baseUrl: {\n type: 'string',\n required: true,\n description: 'Peer instance origin, e.g. http://127.0.0.1:3080.',\n },\n },\n output: {\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n reachable: { type: 'boolean', required: true },\n instance: { type: 'string' },\n },\n },\n render: (_args, value) => [{\n type: 'text',\n text: value.reachable\n ? `reachable: ${value.instance ?? '(unknown instance)'}`\n : 'unreachable or unauthorized',\n }],\n },\n async execute(args) {\n const result = await interconnect.ping(args.baseUrl)\n if (result === undefined) return { reachable: false }\n return { reachable: true, instance: result.instance }\n },\n }))\n\n ctx.tools.register(defineTool({\n name: 'interconnect_list',\n description: 'List the live sessions on a peer DSH instance, so a message can be addressed without '\n + 'knowing a session id in advance. Every returned sessionId is a valid interconnect_send target at '\n + 'the time of the call. Only live sessions appear: a session that exists on the peer but has no '\n + 'running agent is not listed and cannot receive a message.',\n parameters: {\n baseUrl: {\n type: 'string',\n required: true,\n description: 'Peer instance origin, e.g. http://127.0.0.1:3080.',\n },\n },\n output: {\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n reachable: { type: 'boolean', required: true },\n instance: { type: 'string' },\n sessions: {\n type: 'array',\n items: {\n type: 'object',\n additionalProperties: false,\n properties: {\n sessionId: { type: 'string', required: true },\n title: { type: 'string' },\n status: { type: 'string' },\n },\n },\n },\n },\n },\n render: (_args, value) => {\n if (!value.reachable) return [{ type: 'text', text: 'unreachable or unauthorized' }]\n const sessions = value.sessions ?? []\n if (sessions.length === 0) {\n return [{ type: 'text', text: `no live sessions on ${value.instance ?? '(unknown instance)'}` }]\n }\n const lines = sessions.map((session) => {\n const title = session.title === undefined ? '' : ` ${session.title}`\n const status = session.status === undefined ? '' : ` [${session.status}]`\n return `${session.sessionId}${title}${status}`\n })\n return [{ type: 'text', text: lines.join('\\n') }]\n },\n },\n async execute(args) {\n const result = await interconnect.list(args.baseUrl)\n if (result === undefined) return { reachable: false }\n return {\n reachable: true,\n instance: result.instance,\n // Rebuild each row so an optional key stays absent rather than\n // becoming an explicit undefined the wire schema would reject.\n sessions: result.sessions.map(session => ({\n sessionId: session.sessionId,\n ...(session.title === undefined ? {} : { title: session.title }),\n ...(session.status === undefined ? {} : { status: session.status }),\n })),\n }\n },\n }))\n\n ctx.tools.register(defineTool({\n name: 'interconnect_reply',\n description: 'Deliver one text message back to the peer that this session last received an '\n + 'interconnect message from. Only the LOCAL session id and the reply text are needed: the '\n + 'outbound target (the peer origin and its session id) is recalled from the message this '\n + 'session received, so you do not ask for an address twice. A session that never received a '\n + 'message through interconnect \u2014 or received one without a sender identity \u2014 reports reason '\n + '\"no-sender-known\".',\n parameters: {\n sessionId: {\n type: 'string',\n required: true,\n description: 'The LOCAL session id that received the message being replied to.',\n },\n text: {\n type: 'string',\n required: true,\n description: 'Message text delivered back to the recorded sender session.',\n },\n delivery: {\n type: 'string',\n enum: ['followup', 'steer', 'inject'],\n description: 'How the reply reaches the target agent, as in interconnect_send. Omit to use '\n + \"the receiver's configured default.\",\n },\n resume: {\n type: 'boolean',\n description: 'Wake the target session if it is persisted but has no running agent, as in '\n + 'interconnect_send. Off by default; the receiver may refuse.',\n },\n },\n output: {\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n delivered: { type: 'boolean', required: true },\n instance: { type: 'string', required: true },\n delivery: { type: 'string' },\n reason: { type: 'string' },\n },\n },\n render: (_args, value) => {\n if (value.delivered) {\n return [{\n type: 'text',\n text: `replied to ${value.instance}${value.delivery === undefined ? '' : ` via ${value.delivery}`}`,\n }]\n }\n const text = ((): string => {\n if (value.reason === 'no-sender-known') {\n return `not delivered: no sender recorded for \"${_args.sessionId}\"`\n + ' \u2014 this session never received an interconnect message with a sender identity'\n }\n if (value.reason === 'session-owned-by-subagent') {\n return `not delivered: \"${_args.sessionId}\" is a subagent's session \u2014 its parent agent owns delivery`\n }\n if (value.reason === 'unreachable') {\n return `not delivered: the recorded sender did not answer (unreachable or unauthorized)`\n }\n if (value.reason === 'resume-refused') {\n return `not delivered: the recorded sender does not allow waking persisted sessions`\n }\n if (value.reason === 'resume-failed') {\n return `not delivered: could not wake the recorded sender's session`\n }\n return `not delivered: the recorded sender's session is not live`\n })()\n return [{ type: 'text', text }]\n },\n },\n async execute(args) {\n const result = await interconnect.reply({\n sessionId: args.sessionId,\n text: args.text,\n ...(args.delivery === undefined ? {} : { delivery: args.delivery }),\n ...(args.resume === undefined ? {} : { resume: args.resume }),\n })\n return {\n delivered: result.delivered,\n instance: result.instance,\n ...(result.delivery === undefined ? {} : { delivery: result.delivery }),\n ...(result.reason === undefined ? {} : { reason: result.reason }),\n }\n },\n }))\n}\n"],
|
|
5
|
-
"mappings": ";AAaA,SAAS,kBAAkB;AAKpB,IAAM,SAAS,CAAC,gBAAgB,OAAO;AAOvC,SAAS,MAAM,KAAoB;AACxC,QAAM,eAAe,IAAI;AAEzB,MAAI,MAAM,SAAS,WAAW;AAAA,IAC5B,MAAM;AAAA,IACN,aAAa;AAAA,IAKb,YAAY;AAAA,MACV,
|
|
4
|
+
"sourcesContent": ["/**\n * Model-facing tools for cross-instance message handoff: `interconnect_send`\n * delivers one text message to a live session on a peer DSH instance, and\n * `interconnect_ping` probes a peer's liveness and identity.\n *\n * The tools consume the host-plane `interconnect` service and publish nothing\n * themselves, so this row sits as an ordinary tool plugin in a preset while\n * the service it reaches stays host-side (the same split `tool-goal` uses\n * against `goals`).\n * @module @deepseek-ai/dsh-tool-interconnect\n */\n\nimport { Context } from '@deepseek-ai/cordis'\nimport { defineTool } from '@deepseek-ai/dsh-tools'\n// Activates the `Context.interconnect` merge declared by the interconnect service plugin.\nimport type {} from '../interconnect/index.ts'\n\n/** Services required before the tools can register. */\nexport const inject = ['interconnect', 'tools']\n\n/**\n * Register the two tool surfaces. Registration is idempotent per fiber; the\n * tools unregister with the owning fiber.\n * @param ctx - connection context carrying the interconnect service and the tool registry.\n */\nexport function apply(ctx: Context): void {\n const interconnect = ctx.interconnect\n\n ctx.tools.register(defineTool({\n name: 'interconnect_send',\n description: 'Deliver one text message to a live session on another DSH instance (same machine, '\n + 'another machine, or another session), over a shared-secret-authenticated channel. '\n + 'Returns whether the peer instance received it and which instance answered. '\n + 'Only a session with a running agent can receive a message; when none is running the result '\n + 'reports reason \"session-not-live\", and interconnect_list shows which sessions are live there.',\n parameters: {\n instanceId: {\n type: 'string',\n required: true,\n description: 'The peer instance id to deliver to, as configured under this instance\\'s '\n + 'interconnect peers map. Deliveries go over the persistent link to that instance.',\n },\n sessionId: {\n type: 'string',\n required: true,\n description: 'Target session id on the receiving instance to deliver the message to.',\n },\n text: {\n type: 'string',\n required: true,\n description: 'Message text delivered to the peer session.',\n },\n delivery: {\n type: 'string',\n enum: ['followup', 'steer', 'inject'],\n description: 'How the message reaches the target agent. `followup` queues it as its own turn '\n + 'behind whatever that agent is doing now. `steer` cuts into the nearest step boundary of a '\n + 'running turn, so an urgent message does not wait for that turn to end. `inject` seeds '\n + 'context without waking an idle agent, so it may sit unread. Omit to use the receiver\\'s '\n + 'configured default.',\n },\n resume: {\n type: 'boolean',\n description: 'Wake the target session if it is persisted but has no running agent. Off by '\n + 'default because delivery to a woken session starts a real agent turn \u2014 a billed model call '\n + 'with that session\\'s full toolset \u2014 in a conversation nobody is watching. Prefer '\n + 'interconnect_list and an already-live target; set this only when that specific session must '\n + 'be reached. The receiver may refuse, answering reason \"resume-refused\".',\n },\n },\n output: {\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n delivered: { type: 'boolean', required: true },\n instance: { type: 'string', required: true },\n delivery: { type: 'string' },\n reason: { type: 'string' },\n },\n },\n render: (_args, value) => {\n if (value.delivered) {\n return [{\n type: 'text',\n text: `delivered to ${value.instance}${value.delivery === undefined ? '' : ` via ${value.delivery}`}`,\n }]\n }\n // Each failure gets the response it actually needs: a not-live target is\n // the caller's to re-choose, while an unreachable peer may just be worth\n // retrying. The old single line claimed \"no live session\" even when the\n // peer never answered, which pointed at the wrong thing entirely.\n const text = ((): string => {\n switch (value.reason) {\n case 'unreachable':\n return `not delivered: ${value.instance} did not answer (unreachable or unauthorized)`\n case 'resume-refused':\n return `not delivered: ${value.instance} does not allow waking persisted sessions`\n case 'resume-failed':\n return `not delivered: could not wake \"${_args.sessionId}\" on ${value.instance}`\n + ' (no such persisted session, or another owner holds it)'\n case 'session-owned-by-subagent':\n return `not delivered: \"${_args.sessionId}\" is a subagent's session on ${value.instance}`\n + ' \u2014 its parent agent owns delivery, so reach it through that parent'\n default:\n return `not delivered: no live session \"${_args.sessionId}\" on ${value.instance}`\n + ' \u2014 use interconnect_list to see which sessions are live there,'\n + ' or set resume to wake this one'\n }\n })()\n return [{ type: 'text', text }]\n },\n },\n async execute(args, exec) {\n const sessionId = exec.agent?.session.id\n const self = interconnect.selfSender(sessionId === undefined ? '' : String(sessionId))\n const result = await interconnect.send({\n instanceId: args.instanceId,\n sessionId: args.sessionId,\n text: args.text,\n // Attribute this instance as the sender so the peer can reply back. The\n // calling session id comes from the executing agent (the session sending).\n sender: self,\n ...(args.delivery === undefined ? {} : { delivery: args.delivery }),\n ...(args.resume === undefined ? {} : { resume: args.resume }),\n })\n return {\n delivered: result.delivered,\n instance: result.instance,\n ...(result.delivery === undefined ? {} : { delivery: result.delivery }),\n ...(result.reason === undefined ? {} : { reason: result.reason }),\n }\n },\n }))\n\n ctx.tools.register(defineTool({\n name: 'interconnect_ping',\n description: 'Probe a peer DSH instance for liveness and identity over the shared-secret channel. '\n + 'Returns the peer instance id when reachable, or null on transport/auth failure.',\n parameters: {\n instanceId: {\n type: 'string',\n required: true,\n description: 'The peer instance id to probe, as configured under this instance\\'s '\n + 'interconnect peers map.',\n },\n },\n output: {\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n reachable: { type: 'boolean', required: true },\n instance: { type: 'string' },\n },\n },\n render: (_args, value) => [{\n type: 'text',\n text: value.reachable\n ? `reachable: ${value.instance ?? '(unknown instance)'}`\n : 'unreachable or unauthorized',\n }],\n },\n async execute(args) {\n const result = await interconnect.ping(args.instanceId)\n if (result === undefined) return { reachable: false }\n return { reachable: true, instance: result.instance }\n },\n }))\n\n ctx.tools.register(defineTool({\n name: 'interconnect_list',\n description: 'List the live sessions on a peer DSH instance, so a message can be addressed without '\n + 'knowing a session id in advance. Every returned sessionId is a valid interconnect_send target at '\n + 'the time of the call. Only live sessions appear: a session that exists on the peer but has no '\n + 'running agent is not listed and cannot receive a message.',\n parameters: {\n instanceId: {\n type: 'string',\n required: true,\n description: 'The peer instance id to list, as configured under this instance\\'s '\n + 'interconnect peers map.',\n },\n },\n output: {\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n reachable: { type: 'boolean', required: true },\n instance: { type: 'string' },\n sessions: {\n type: 'array',\n items: {\n type: 'object',\n additionalProperties: false,\n properties: {\n sessionId: { type: 'string', required: true },\n title: { type: 'string' },\n status: { type: 'string' },\n },\n },\n },\n },\n },\n render: (_args, value) => {\n if (!value.reachable) return [{ type: 'text', text: 'unreachable or unauthorized' }]\n const sessions = value.sessions ?? []\n if (sessions.length === 0) {\n return [{ type: 'text', text: `no live sessions on ${value.instance ?? '(unknown instance)'}` }]\n }\n const lines = sessions.map((session) => {\n const title = session.title === undefined ? '' : ` ${session.title}`\n const status = session.status === undefined ? '' : ` [${session.status}]`\n return `${session.sessionId}${title}${status}`\n })\n return [{ type: 'text', text: lines.join('\\n') }]\n },\n },\n async execute(args) {\n const result = await interconnect.list(args.instanceId)\n if (result === undefined) return { reachable: false }\n return {\n reachable: true,\n instance: result.instance,\n // Rebuild each row so an optional key stays absent rather than\n // becoming an explicit undefined the wire schema would reject.\n sessions: result.sessions.map(session => ({\n sessionId: session.sessionId,\n ...(session.title === undefined ? {} : { title: session.title }),\n ...(session.status === undefined ? {} : { status: session.status }),\n })),\n }\n },\n }))\n\n ctx.tools.register(defineTool({\n name: 'interconnect_reply',\n description: 'Deliver one text message back to the peer that this session last received an '\n + 'interconnect message from. Only the LOCAL session id and the reply text are needed: the '\n + 'outbound target (the peer origin and its session id) is recalled from the message this '\n + 'session received, so you do not ask for an address twice. A session that never received a '\n + 'message through interconnect \u2014 or received one without a sender identity \u2014 reports reason '\n + '\"no-sender-known\".',\n parameters: {\n sessionId: {\n type: 'string',\n required: true,\n description: 'The LOCAL session id that received the message being replied to.',\n },\n text: {\n type: 'string',\n required: true,\n description: 'Message text delivered back to the recorded sender session.',\n },\n delivery: {\n type: 'string',\n enum: ['followup', 'steer', 'inject'],\n description: 'How the reply reaches the target agent, as in interconnect_send. Omit to use '\n + \"the receiver's configured default.\",\n },\n resume: {\n type: 'boolean',\n description: 'Wake the target session if it is persisted but has no running agent, as in '\n + 'interconnect_send. Off by default; the receiver may refuse.',\n },\n },\n output: {\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n delivered: { type: 'boolean', required: true },\n instance: { type: 'string', required: true },\n delivery: { type: 'string' },\n reason: { type: 'string' },\n },\n },\n render: (_args, value) => {\n if (value.delivered) {\n return [{\n type: 'text',\n text: `replied to ${value.instance}${value.delivery === undefined ? '' : ` via ${value.delivery}`}`,\n }]\n }\n const text = ((): string => {\n if (value.reason === 'no-sender-known') {\n return `not delivered: no sender recorded for \"${_args.sessionId}\"`\n + ' \u2014 this session never received an interconnect message with a sender identity'\n }\n if (value.reason === 'session-owned-by-subagent') {\n return `not delivered: \"${_args.sessionId}\" is a subagent's session \u2014 its parent agent owns delivery`\n }\n if (value.reason === 'unreachable') {\n return `not delivered: the recorded sender did not answer (unreachable or unauthorized)`\n }\n if (value.reason === 'resume-refused') {\n return `not delivered: the recorded sender does not allow waking persisted sessions`\n }\n if (value.reason === 'resume-failed') {\n return `not delivered: could not wake the recorded sender's session`\n }\n return `not delivered: the recorded sender's session is not live`\n })()\n return [{ type: 'text', text }]\n },\n },\n async execute(args) {\n const result = await interconnect.reply({\n sessionId: args.sessionId,\n text: args.text,\n ...(args.delivery === undefined ? {} : { delivery: args.delivery }),\n ...(args.resume === undefined ? {} : { resume: args.resume }),\n })\n return {\n delivered: result.delivered,\n instance: result.instance,\n ...(result.delivery === undefined ? {} : { delivery: result.delivery }),\n ...(result.reason === undefined ? {} : { reason: result.reason }),\n }\n },\n }))\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -16,7 +16,7 @@ import z from '@deepseek-ai/schemastery';
|
|
|
16
16
|
import WebSocket from 'ws';
|
|
17
17
|
import { type Config, type EventNotification, type ListResult, type PingResult, type ReplyRequest, type SendResult, type SendRequest, type SenderIdentity, type WebSocketLinkHandle } from './types.ts';
|
|
18
18
|
export type * from './types.ts';
|
|
19
|
-
export {
|
|
19
|
+
export { INTERCONNECT_TOKEN_REF } from './types.ts';
|
|
20
20
|
declare module '@deepseek-ai/cordis' {
|
|
21
21
|
interface Context {
|
|
22
22
|
interconnect: InterconnectService;
|
|
@@ -39,72 +39,95 @@ export declare class InterconnectService extends Service {
|
|
|
39
39
|
static inject: string[];
|
|
40
40
|
static Config: z<Config>;
|
|
41
41
|
private readonly instanceId;
|
|
42
|
-
private readonly selfBaseUrl;
|
|
43
42
|
private readonly requestTimeoutMs;
|
|
44
43
|
private readonly delivery;
|
|
45
44
|
private readonly allowResume;
|
|
46
|
-
private readonly peers;
|
|
47
45
|
private readonly subscriptions;
|
|
48
46
|
private readonly server;
|
|
49
47
|
private readonly sockets;
|
|
48
|
+
/** Outbound peer links keyed by the peer's `instanceId`. */
|
|
50
49
|
private readonly linkStates;
|
|
51
50
|
private heartbeatTimer;
|
|
52
51
|
/** Peer identity each live socket announced via its `hello` frame, if any. */
|
|
53
52
|
private readonly peerOf;
|
|
54
53
|
/** Sender each local session last received a send from, keyed by local session id. */
|
|
55
54
|
private readonly senders;
|
|
55
|
+
/** In-flight frames sent over a peer link, keyed by `reqId`, awaiting a correlated result. */
|
|
56
|
+
private readonly pendingMessages;
|
|
57
|
+
private reqIdCounter;
|
|
56
58
|
constructor(ctx: Context, config: Config);
|
|
57
59
|
/**
|
|
58
|
-
* This instance's identity to attach to outbound messages
|
|
59
|
-
*
|
|
60
|
-
* peer cannot reply to them.
|
|
60
|
+
* This instance's identity to attach to outbound messages. Always present:
|
|
61
|
+
* it needs no address, only this instance's id and the calling session.
|
|
61
62
|
* @param sessionId - the local session that is sending, used as the reply target.
|
|
62
63
|
*/
|
|
63
|
-
selfSender(sessionId: string): SenderIdentity
|
|
64
|
+
selfSender(sessionId: string): SenderIdentity;
|
|
64
65
|
send(request: SendRequest): Promise<SendResult>;
|
|
65
66
|
/**
|
|
66
67
|
* Deliver one text message back to the peer that a local session last
|
|
67
68
|
* received a send from. `sessionId` names the LOCAL replying session; the
|
|
68
|
-
* outbound target is the `sender` that session recorded,
|
|
69
|
-
*
|
|
69
|
+
* outbound target is the `sender` that session recorded, addressed through
|
|
70
|
+
* this instance's own link to the sender's instance.
|
|
70
71
|
*/
|
|
71
72
|
reply(request: ReplyRequest): Promise<SendResult>;
|
|
72
|
-
ping(baseUrl: string): Promise<PingResult | undefined>;
|
|
73
73
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
74
|
+
* Probe a peer instance for liveness and identity over its persistent link.
|
|
75
|
+
* Returns the peer identity when reachable, or undefined when the link is
|
|
76
|
+
* not up or no answer arrives.
|
|
76
77
|
*/
|
|
77
|
-
|
|
78
|
+
ping(instanceId: string): Promise<PingResult | undefined>;
|
|
78
79
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* @param peer - receiver origin, e.g. `http://127.0.0.1:3080`.
|
|
82
|
-
* @returns disposer removing the peer from the fan-out set.
|
|
80
|
+
* List a peer instance's live sessions over its persistent link. Undefined on
|
|
81
|
+
* transport failure, matching `ping`.
|
|
83
82
|
*/
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
|
|
83
|
+
list(instanceId: string): Promise<ListResult | undefined>;
|
|
84
|
+
/** The origin this instance dials to reach a configured peer, or undefined. */
|
|
85
|
+
private originOf;
|
|
86
|
+
/**
|
|
87
|
+
* Send a `msg` frame over the live link to a peer and resolve with its
|
|
88
|
+
* correlated `msg-result`. Undefined when the peer has no live link here
|
|
89
|
+
* (not configured, or the link is down) — sends can only address configured+
|
|
90
|
+
* connected peers by design.
|
|
91
|
+
*/
|
|
92
|
+
private msgRequest;
|
|
93
|
+
/** Send a `query` frame over the live link to a peer and resolve its result. */
|
|
94
|
+
private queryRequest;
|
|
95
|
+
/** Settle a `reqId` frame against its `*-result`, timing out at `requestTimeoutMs`. */
|
|
96
|
+
private waitForResult;
|
|
97
|
+
/**
|
|
98
|
+
* Add a peer route at runtime. Returns a disposer that removes it. Re-adding
|
|
99
|
+
* an existing instanceId re-routes it to the new origin.
|
|
100
|
+
* @param instanceId - the peer's `instanceId`.
|
|
101
|
+
* @param origin - origin this instance dials to reach that peer.
|
|
102
|
+
* @returns disposer removing the peer route.
|
|
103
|
+
*/
|
|
104
|
+
subscribe(instanceId: string, origin: string): () => void;
|
|
105
|
+
/** Remove a peer route, closing its outbound link. */
|
|
106
|
+
unsubscribe(instanceId: string): void;
|
|
87
107
|
/**
|
|
88
108
|
* Open (and, on drop, re-open) a persistent WebSocket link to a peer. Local
|
|
89
109
|
* events stream over the link in real time, and events the peer pushes are
|
|
90
|
-
* surfaced as `interconnect/event`. Repeating for the same
|
|
91
|
-
*
|
|
92
|
-
* @param
|
|
110
|
+
* surfaced as `interconnect/event`. Repeating for the same instanceId
|
|
111
|
+
* re-routes the link to the new origin.
|
|
112
|
+
* @param instanceId - the peer's `instanceId`.
|
|
113
|
+
* @param origin - receiver origin this instance dials, e.g. `http://127.0.0.1:13080`.
|
|
93
114
|
* @returns a handle closing the link and cancelling reconnection.
|
|
94
115
|
*/
|
|
95
|
-
link(
|
|
116
|
+
link(instanceId: string, origin: string): WebSocketLinkHandle;
|
|
96
117
|
/** Remove a closed outbound link's state so a later `link` re-dials fresh. */
|
|
97
|
-
forgetLink(
|
|
98
|
-
/**
|
|
118
|
+
forgetLink(instanceId: string): void;
|
|
119
|
+
/** Push one serialized lifecycle fact out to every linked peer over WS. */
|
|
99
120
|
private fanout;
|
|
100
121
|
/** Push one fact over every live WebSocket link, dropping closed sockets. */
|
|
101
122
|
private broadcast;
|
|
102
|
-
/**
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
private
|
|
123
|
+
/**
|
|
124
|
+
* Dispatch one inbound `msg` frame: deliver a `send`/`reply` and answer the
|
|
125
|
+
* correlated `msg-result` on the same socket. Errors are surfaced as the
|
|
126
|
+
* result so a throwing handler cannot escape the socket's message callback.
|
|
127
|
+
*/
|
|
128
|
+
private handleMsgFrame;
|
|
129
|
+
/** Dispatch one inbound `query` frame (ping/list/event) and answer on the socket. */
|
|
130
|
+
private handleQueryFrame;
|
|
108
131
|
/** Surface one remote notification to local listeners and the log. */
|
|
109
132
|
private receiveEvent;
|
|
110
133
|
/**
|
|
@@ -143,7 +166,6 @@ export declare class InterconnectService extends Service {
|
|
|
143
166
|
* deliver} so the two wire endpoints stay distinct in the request pipeline.
|
|
144
167
|
*/
|
|
145
168
|
private replyForSession;
|
|
146
|
-
private post;
|
|
147
169
|
private resolveToken;
|
|
148
170
|
/** Resolve the shared token for an outbound dial (same source as inbound). */
|
|
149
171
|
resolveTokenForDial(): Promise<string | undefined>;
|
|
@@ -157,6 +179,8 @@ export declare class InterconnectService extends Service {
|
|
|
157
179
|
attachSocket(websocket: WebSocket): void;
|
|
158
180
|
/** Parse and route one inbound link frame, attributing events to the socket's announced peer. */
|
|
159
181
|
private handleFrame;
|
|
182
|
+
/** Write one frame to a socket, returning false when the socket cannot take it. */
|
|
183
|
+
private sendFrame;
|
|
160
184
|
}
|
|
161
185
|
export default InterconnectService;
|
|
162
186
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/interconnect/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/interconnect/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,18 +31,15 @@ export declare const INTERCONNECT_TOKEN_REF = "DSH_INTERCONNECT_TOKEN";
|
|
|
31
31
|
export type DeliveryMode = 'followup' | 'steer' | 'inject';
|
|
32
32
|
/**
|
|
33
33
|
* Self-reported identity of the peer that sent a message, carried for reply
|
|
34
|
-
* attribution and echoed `sessionId` of the sending instance.
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
34
|
+
* attribution and echoed `sessionId` of the sending instance. Address-free on
|
|
35
|
+
* purpose: every delivery goes over an already-established WebSocket link, so
|
|
36
|
+
* the receiver addresses a `reply` by recalling the sender's `instanceId` and
|
|
37
|
+
* using its OWN outbound link to that instance — no origin crosses the wire.
|
|
38
|
+
* Both fields are sender-supplied and self-reported; the receiver stores them
|
|
39
|
+
* only to address a `reply`, never as an auth or routing authority (the shared
|
|
40
|
+
* secret still authenticates the connection itself).
|
|
38
41
|
*/
|
|
39
42
|
export interface SenderIdentity {
|
|
40
|
-
/**
|
|
41
|
-
* Origin the receiver can reach the sender's instance at when replying, e.g.
|
|
42
|
-
* `http://peer-host:9001`. This must be addressable FROM the receiver; a
|
|
43
|
-
* loopback address only makes sense when both sides share the same machine.
|
|
44
|
-
*/
|
|
45
|
-
readonly baseUrl: string;
|
|
46
43
|
/** The sender's self-reported instance id (diagnostic, as in `ping`). */
|
|
47
44
|
readonly instanceId: string;
|
|
48
45
|
/** Session id on the sender's instance to which a `reply` is addressed. */
|
|
@@ -152,21 +149,23 @@ export interface ListResult {
|
|
|
152
149
|
/** Echoed receiver instance id (diagnostic; never trusted for routing). */
|
|
153
150
|
readonly instance: string;
|
|
154
151
|
}
|
|
155
|
-
/** Outbound listing request:
|
|
152
|
+
/** Outbound listing request: which peer instance to list. */
|
|
156
153
|
export interface ListRequest {
|
|
157
|
-
/**
|
|
158
|
-
readonly
|
|
154
|
+
/** Peers' `instanceId` as configured under {@link Config.peers}. */
|
|
155
|
+
readonly instanceId: string;
|
|
159
156
|
}
|
|
160
|
-
/** Outbound delivery request:
|
|
157
|
+
/** Outbound delivery request: which peer instance plus a `send` business payload. */
|
|
161
158
|
export interface SendRequest {
|
|
162
|
-
/**
|
|
163
|
-
|
|
159
|
+
/**
|
|
160
|
+
* The peer instance to deliver to, as configured under {@link Config.peers}.
|
|
161
|
+
* The origin used to reach it comes from that instance's own link.
|
|
162
|
+
*/
|
|
163
|
+
readonly instanceId: string;
|
|
164
164
|
readonly sessionId: string;
|
|
165
165
|
readonly text: string;
|
|
166
166
|
/**
|
|
167
167
|
* This sender's identity, forwarded so the receiver can attribute the
|
|
168
|
-
* message and address a reply back.
|
|
169
|
-
* own addressable origin (see {@link Config.selfBaseUrl}).
|
|
168
|
+
* message and address a reply back.
|
|
170
169
|
*/
|
|
171
170
|
readonly sender?: SenderIdentity;
|
|
172
171
|
/** Per-message delivery override forwarded to the receiver. */
|
|
@@ -242,8 +241,10 @@ export interface EventPayload {
|
|
|
242
241
|
/**
|
|
243
242
|
* One text frame exchanged over a persistent WebSocket peer link. `hello`
|
|
244
243
|
* opens a link with the dialing side's identity; `event` pushes one
|
|
245
|
-
* notification in either direction
|
|
246
|
-
*
|
|
244
|
+
* notification in either direction; `msg`/`msg-result` carry a
|
|
245
|
+
* request/response message delivery over the same long-lived link (correlated
|
|
246
|
+
* by `reqId`). Native ws ping/pong carries the heartbeat, so no application
|
|
247
|
+
* keepalive frame exists.
|
|
247
248
|
*/
|
|
248
249
|
export type LinkFrame = {
|
|
249
250
|
readonly type: 'hello';
|
|
@@ -251,6 +252,59 @@ export type LinkFrame = {
|
|
|
251
252
|
} | {
|
|
252
253
|
readonly type: 'event';
|
|
253
254
|
readonly notification: EventNotification;
|
|
255
|
+
} | {
|
|
256
|
+
readonly type: 'msg';
|
|
257
|
+
readonly reqId: string;
|
|
258
|
+
readonly message: LinkMessage;
|
|
259
|
+
} | {
|
|
260
|
+
readonly type: 'msg-result';
|
|
261
|
+
readonly reqId: string;
|
|
262
|
+
readonly result: SendResult;
|
|
263
|
+
} | {
|
|
264
|
+
readonly type: 'query';
|
|
265
|
+
readonly reqId: string;
|
|
266
|
+
readonly query: QueryMessage;
|
|
267
|
+
} | {
|
|
268
|
+
readonly type: 'query-result';
|
|
269
|
+
readonly reqId: string;
|
|
270
|
+
readonly result: unknown;
|
|
271
|
+
};
|
|
272
|
+
/**
|
|
273
|
+
* A request/response query carried by `query`/`query-result` frames, used for
|
|
274
|
+
* the discovery endpoints (`ping`, `list`) over the persistent link. `ping`
|
|
275
|
+
* answers the peer's identity; `list` answers the peer's live session rows.
|
|
276
|
+
*/
|
|
277
|
+
export type QueryMessage = {
|
|
278
|
+
readonly kind: 'ping';
|
|
279
|
+
} | {
|
|
280
|
+
readonly kind: 'list';
|
|
281
|
+
} | {
|
|
282
|
+
readonly kind: 'event';
|
|
283
|
+
readonly notification: EventNotification;
|
|
284
|
+
};
|
|
285
|
+
/**
|
|
286
|
+
* The message-shaped business payload carried by a `msg` link frame. `kind`
|
|
287
|
+
* picks the delivery semantics: `send` targets the named remote session,
|
|
288
|
+
* `reply` targets the sender a local session recorded. One tagged union keeps
|
|
289
|
+
* the frame count down while the receiver dispatches on `kind`.
|
|
290
|
+
*/
|
|
291
|
+
export type LinkMessage = {
|
|
292
|
+
readonly kind: 'send';
|
|
293
|
+
readonly sessionId: string;
|
|
294
|
+
readonly text: string;
|
|
295
|
+
/** Delivered and attributed upstream exactly as in `SendPayload`. */
|
|
296
|
+
readonly sender?: SenderIdentity;
|
|
297
|
+
readonly delivery?: DeliveryMode;
|
|
298
|
+
readonly resume?: boolean;
|
|
299
|
+
} | {
|
|
300
|
+
readonly kind: 'reply';
|
|
301
|
+
/** LOCAL session id that received the message being replied to. */
|
|
302
|
+
readonly sessionId: string;
|
|
303
|
+
readonly text: string;
|
|
304
|
+
/** Attribution for the replying instance, so the peer can reply back. */
|
|
305
|
+
readonly sender?: SenderIdentity;
|
|
306
|
+
readonly delivery?: DeliveryMode;
|
|
307
|
+
readonly resume?: boolean;
|
|
254
308
|
};
|
|
255
309
|
/**
|
|
256
310
|
* Handle to one established outbound WebSocket peer link. `close` tears the
|
|
@@ -266,22 +320,22 @@ export interface WebSocketLinkHandle {
|
|
|
266
320
|
export interface Config {
|
|
267
321
|
/** Self-reported id of this instance, echoed in ping/send results for diagnostics. */
|
|
268
322
|
readonly instanceId: string;
|
|
269
|
-
/**
|
|
270
|
-
* Origin this instance is reachable at from peers, e.g. `http://my-box:3080`.
|
|
271
|
-
* When set, outbound `send` calls attach this instance's identity as the
|
|
272
|
-
* `sender` so the peer can reply back (chainable). Absent, outbound messages
|
|
273
|
-
* are not attributable and a peer `reply` reports `no-sender-known`. Must be
|
|
274
|
-
* addressable FROM peers — a loopback address only fits a same-machine link.
|
|
275
|
-
*/
|
|
276
|
-
readonly selfBaseUrl?: string;
|
|
277
323
|
/** Request timeout for outbound deliveries, in milliseconds. */
|
|
278
324
|
readonly requestTimeoutMs: number;
|
|
279
325
|
/**
|
|
280
|
-
* Peer instance
|
|
281
|
-
*
|
|
282
|
-
*
|
|
326
|
+
* Peer instance routes, keyed by the peer's `instanceId`, valued by the
|
|
327
|
+
* origin this instance dials to reach that peer (e.g. a tunnel endpoint
|
|
328
|
+
* `http://127.0.0.1:13080`). At activation each peer is linked over a
|
|
329
|
+
* persistent WebSocket (heartbeat + reconnect), and every outbound
|
|
330
|
+
* `send`/`reply`/`ping`/`list` is addressed by `instanceId` through that
|
|
331
|
+
* instance's own link. An origin is the ONLY routing authority — `instanceId`
|
|
332
|
+
* is never used to derive an address.
|
|
333
|
+
*
|
|
334
|
+
* Fan-out of local lifecycle events also goes to every peer in this map.
|
|
335
|
+
* A runtime `subscribe(instanceId, origin)` can extend the map without
|
|
336
|
+
* restart; retuning the origin of an existing peer re-routes it.
|
|
283
337
|
*/
|
|
284
|
-
readonly peers?: string
|
|
338
|
+
readonly peers?: Record<string, string>;
|
|
285
339
|
/**
|
|
286
340
|
* Default mode for inbound `send` messages that carry no per-message
|
|
287
341
|
* override. See {@link DeliveryMode} for what each mode does.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/interconnect/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,eAAO,MAAM,oBAAoB,kBAAkB,CAAA;AAEnD;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,2BAA2B,CAAA;AAE9D;;;;;;;;;;GAUG;AACH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAA;AAE1D
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/interconnect/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tool-interconnect/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAK7C,uDAAuD;AACvD,eAAO,MAAM,MAAM,UAA4B,CAAA;AAE/C;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tool-interconnect/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAK7C,uDAAuD;AACvD,eAAO,MAAM,MAAM,UAA4B,CAAA;AAE/C;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAySxC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-interconnect",
|
|
3
3
|
"description": "Cross-instance message/event handoff plugins for DeepSeek Harness (DSH): interconnect service + model-facing tools",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.9.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "lib/index.js",
|