@meshagent/meshagent-agents 0.46.4 → 0.47.1
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/CHANGELOG.md +10 -2
- package/README.md +24 -0
- package/dist/browser/agent-messages.js +11 -21
- package/dist/browser/chat-client.d.ts +42 -3
- package/dist/browser/chat-client.js +209 -17
- package/dist/esm/agent-messages.js +11 -21
- package/dist/esm/chat-client.d.ts +42 -3
- package/dist/esm/chat-client.js +206 -17
- package/dist/node/agent-messages.js +11 -21
- package/dist/node/chat-client.d.ts +42 -3
- package/dist/node/chat-client.js +209 -17
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
## [0.
|
|
2
|
-
-
|
|
1
|
+
## [0.47.1]
|
|
2
|
+
- Added duplex messaging stream subscriptions and replay-state alignment in the TypeScript chat clients, bringing the NodeJS SDK in line with the new streaming model.
|
|
3
|
+
- Reworked messaging and room client flow control so dispatch ordering, close behavior, and presence updates stay consistent under streaming loads.
|
|
4
|
+
- Expanded stream and presence test coverage for the new messaging behavior.
|
|
5
|
+
|
|
6
|
+
## [0.47.0]
|
|
7
|
+
- Improved TypeScript messaging clients so room delivery order and startup/presence behavior stay consistent.
|
|
8
|
+
- Moved managed-agent client routing onto the Rust tunnel path and hardened agent chat-client event handling.
|
|
9
|
+
- Added a `test:rust-process-e2e` entry point for the agents-ts package and expanded live chat/process-agent coverage.
|
|
10
|
+
- Finished aligning CLI pagination behavior across feeds, rooms, mailboxes, scheduled tasks, and shared helpers.
|
|
3
11
|
|
|
4
12
|
## [0.46.3]
|
|
5
13
|
- `LivekitProtocolChannel.sendData` now clones outgoing `Uint8Array` payloads before publishing, avoiding shared-buffer mutation issues.
|
package/README.md
CHANGED
|
@@ -204,3 +204,27 @@ npm test
|
|
|
204
204
|
```
|
|
205
205
|
|
|
206
206
|
The build emits ESM, Node CommonJS, and browser CommonJS outputs under `dist/`.
|
|
207
|
+
|
|
208
|
+
An external E2E harness can validate interoperability with a Rust process agent by
|
|
209
|
+
starting that agent in a room, then supplying its room participant credentials:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
MESHAGENT_TOKEN=... \
|
|
213
|
+
MESHAGENT_ROOM=... \
|
|
214
|
+
TEST_AGENT_NAME=... \
|
|
215
|
+
MESHAGENT_API_URL=... \
|
|
216
|
+
npm run test:rust-process-e2e
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
The runner owns only the TypeScript client. The harness remains responsible for
|
|
220
|
+
starting and stopping the Rust process agent named by `TEST_AGENT_NAME`. It must
|
|
221
|
+
also supply either `MESHAGENT_API_URL` (preferred for the Rust harness) or
|
|
222
|
+
`MESHAGENT_ROOM_URL`, so the client does not silently connect to production.
|
|
223
|
+
|
|
224
|
+
From this repository, the preferred full interoperability check starts the
|
|
225
|
+
Rust server and process agent, runs both the Dart and TypeScript suites, and
|
|
226
|
+
stops the fixture automatically:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
rust/meshagent-server-e2e/run-cross-language-e2e.sh
|
|
230
|
+
```
|
|
@@ -747,26 +747,16 @@ function makeMessageClass({ type, base = "message", fields = [], }) {
|
|
|
747
747
|
params.model = stringOrNull(json.model);
|
|
748
748
|
}
|
|
749
749
|
for (const field of fields) {
|
|
750
|
-
if (field.
|
|
751
|
-
if (field.
|
|
752
|
-
|
|
750
|
+
if (!hasOwn(json, field.json)) {
|
|
751
|
+
if (field.required) {
|
|
752
|
+
if (field.from != null) {
|
|
753
|
+
field.from(undefined, json);
|
|
754
|
+
}
|
|
755
|
+
throw new TypeError(`missing required field '${field.json}'`);
|
|
753
756
|
}
|
|
754
|
-
|
|
755
|
-
params[field.prop] = requiredString(json, field.json);
|
|
756
|
-
}
|
|
757
|
-
else if (typeof json[field.json] === "number") {
|
|
758
|
-
params[field.prop] = json[field.json];
|
|
759
|
-
}
|
|
760
|
-
else {
|
|
761
|
-
params[field.prop] = requiredMap(json, field.json);
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
else if (hasOwn(json, field.json)) {
|
|
765
|
-
params[field.prop] = field.from != null ? field.from(json[field.json], json) : json[field.json];
|
|
766
|
-
}
|
|
767
|
-
else if (field.default != null) {
|
|
768
|
-
params[field.prop] = field.default(json);
|
|
757
|
+
continue;
|
|
769
758
|
}
|
|
759
|
+
params[field.prop] = json[field.json];
|
|
770
760
|
}
|
|
771
761
|
return new this(params);
|
|
772
762
|
}
|
|
@@ -990,10 +980,10 @@ exports.AgentToolCallLogDelta = makeMessageClass({ type: exports.agentToolCallLo
|
|
|
990
980
|
exports.AgentToolCallEnded = makeMessageClass({ type: exports.agentToolCallEndedType, base: "llm", fields: [...contentPart, { prop: "namespace", json: "namespace", from: (value) => stringOrNull(value) ?? "meshagent", default: () => "meshagent", always: true }, s("callId"), s("toolkit"), s("tool"), { prop: "result", json: "result", from: contentOrNull, to: contentHeader }, obj("error", "error", AgentError.fromJson)] });
|
|
991
981
|
exports.AgentToolCallApprovalRequested = makeMessageClass({ type: exports.agentToolCallApprovalRequestedType, base: "llm", fields: toolState.filter((field) => field.prop !== "argumentBytes") });
|
|
992
982
|
exports.AgentSecretRequested = makeMessageClass({ type: exports.agentSecretRequestedType, base: "llm", fields: [...contentPart, s("requestId", "request_id", true), s("name", "name", true), s("scope")] });
|
|
993
|
-
exports.AgentClientToolCallRequested = makeMessageClass({ type: exports.agentClientToolCallRequestedType, base: "llm", fields: [...contentPart, s("requestId", "request_id", true), s("toolkit", "toolkit", true), s("tool", "tool", true), m("arguments", "arguments", true)] });
|
|
994
|
-
exports.AgentClientToolCallCancelled = makeMessageClass({ type: exports.agentClientToolCallCancelledType, base: "llm", fields: [...contentPart, s("requestId", "request_id", true), s("reason")] });
|
|
983
|
+
exports.AgentClientToolCallRequested = makeMessageClass({ type: exports.agentClientToolCallRequestedType, base: "llm", fields: [...contentPart, s("requestId", "request_id", true), s("targetParticipantId"), s("toolkit", "toolkit", true), s("tool", "tool", true), m("arguments", "arguments", true)] });
|
|
984
|
+
exports.AgentClientToolCallCancelled = makeMessageClass({ type: exports.agentClientToolCallCancelledType, base: "llm", fields: [...contentPart, s("requestId", "request_id", true), s("targetParticipantId"), s("reason")] });
|
|
995
985
|
exports.AgentThreadStatus = makeMessageClass({ type: exports.agentThreadStatusType, base: "thread", fields: [s("status"), s("mode"), s("startedAt"), s("turnId"), s("pendingItemId"), i("totalBytes"), i("linesAdded"), i("linesRemoved")] });
|
|
996
|
-
exports.AgentConnectionStatus = makeMessageClass({ type: exports.agentConnectionStatusType, fields: [s("status", "status", true), s("message"), s("reason"), n("retryInSeconds")] });
|
|
986
|
+
exports.AgentConnectionStatus = makeMessageClass({ type: exports.agentConnectionStatusType, fields: [s("status", "status", true), s("message"), s("reason"), n("retryInSeconds"), s("participantId")] });
|
|
997
987
|
exports.AgentThreadEvent = makeMessageClass({ type: exports.agentThreadEventType, base: "llm", fields: [m("event", "event", true)] });
|
|
998
988
|
exports.AgentImageGenerationStarted = makeMessageClass({ type: exports.agentImageGenerationStartedType, base: "llm", fields: imageGeneration });
|
|
999
989
|
exports.AgentImageGenerationPartial = makeMessageClass({ type: exports.agentImageGenerationPartialType, base: "llm", fields: [...imageGeneration, obj("image", "image", AgentGeneratedImage.fromJson), i("partialIndex")] });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { RemoteParticipant } from "@meshagent/meshagent";
|
|
1
|
+
import { MessagingStream, RemoteParticipant } from "@meshagent/meshagent";
|
|
2
2
|
import type { RoomClient, Content } from "@meshagent/meshagent";
|
|
3
|
-
import { AgentMessage, AgentModelChanged, AgentThreadStatus, ModelsResponse, ToolChoice, AgentConnectionStatus } from "./agent-messages.js";
|
|
3
|
+
import { AgentMessage, AgentModelChanged, AgentThreadStatus, ModelsResponse, ToolChoice, AgentConnectionStatus, AgentClientToolCallRequested } from "./agent-messages.js";
|
|
4
4
|
import type { AgentPayload, JsonMap, ClientToolkitDescription } from "./agent-messages.js";
|
|
5
5
|
import { ChangeEmitter } from "./change-emitter.js";
|
|
6
6
|
export declare class AgentMessageEvent {
|
|
@@ -90,6 +90,8 @@ export declare abstract class BaseChatClient extends ChangeEmitter {
|
|
|
90
90
|
stop(): Promise<void>;
|
|
91
91
|
agentParticipant(): RemoteParticipant | null;
|
|
92
92
|
localParticipantName(): string | undefined;
|
|
93
|
+
localParticipantId(): string | undefined;
|
|
94
|
+
isClientToolCallForLocalParticipant(request: InstanceType<typeof AgentClientToolCallRequested>): boolean;
|
|
93
95
|
protected cleanParticipantName(value: string | undefined): string | undefined;
|
|
94
96
|
openThread(threadPath: string, { load, sinceTurn, reloadIfOpen, drainPendingEvents, }?: {
|
|
95
97
|
load?: boolean;
|
|
@@ -131,7 +133,30 @@ export declare abstract class BaseChatClient extends ChangeEmitter {
|
|
|
131
133
|
}): void;
|
|
132
134
|
removeThreadSession(threadPath: string): void;
|
|
133
135
|
}
|
|
134
|
-
export declare
|
|
136
|
+
export declare const messagingChatThreadSubscribeType = "meshagent.chat.thread.subscribe";
|
|
137
|
+
export declare const messagingChatThreadListSubscribeType = "meshagent.chat.thread_list.subscribe";
|
|
138
|
+
export declare class ThreadSubscribe {
|
|
139
|
+
readonly threadId: string;
|
|
140
|
+
readonly stream: MessagingStream;
|
|
141
|
+
constructor({ threadId, stream }: {
|
|
142
|
+
threadId: string;
|
|
143
|
+
stream: MessagingStream;
|
|
144
|
+
});
|
|
145
|
+
get closed(): boolean;
|
|
146
|
+
send(message: AgentMessage, { attachment }?: {
|
|
147
|
+
attachment?: Uint8Array;
|
|
148
|
+
}): Promise<void>;
|
|
149
|
+
close(): Promise<void>;
|
|
150
|
+
}
|
|
151
|
+
export declare class ThreadListSubscribe {
|
|
152
|
+
readonly stream: MessagingStream;
|
|
153
|
+
constructor({ stream }: {
|
|
154
|
+
stream: MessagingStream;
|
|
155
|
+
});
|
|
156
|
+
get closed(): boolean;
|
|
157
|
+
close(): Promise<void>;
|
|
158
|
+
}
|
|
159
|
+
export declare class BaseMessagingChatClient extends BaseChatClient {
|
|
135
160
|
readonly room: RoomClient;
|
|
136
161
|
readonly agentName?: string;
|
|
137
162
|
private readonly pendingParticipantWaits;
|
|
@@ -146,6 +171,7 @@ export declare class MessagingChatClient extends BaseChatClient {
|
|
|
146
171
|
agentName?: string;
|
|
147
172
|
});
|
|
148
173
|
localParticipantName(): string | undefined;
|
|
174
|
+
localParticipantId(): string | undefined;
|
|
149
175
|
start(): Promise<void>;
|
|
150
176
|
stop(): Promise<void>;
|
|
151
177
|
private attachMessagingListeners;
|
|
@@ -164,6 +190,17 @@ export declare class MessagingChatClient extends BaseChatClient {
|
|
|
164
190
|
private reopenOpenSessions;
|
|
165
191
|
private readonly onMessagingMessage;
|
|
166
192
|
}
|
|
193
|
+
export declare class MessagingChatClient extends BaseMessagingChatClient {
|
|
194
|
+
private readonly threadSubscriptions;
|
|
195
|
+
private threadListSubscription?;
|
|
196
|
+
private readonly streamTasks;
|
|
197
|
+
stop(): Promise<void>;
|
|
198
|
+
private supportsThreadSubscriptions;
|
|
199
|
+
private trackStream;
|
|
200
|
+
sendAgentMessage(message: AgentMessage, { attachment }?: {
|
|
201
|
+
attachment?: Uint8Array;
|
|
202
|
+
}): Promise<void>;
|
|
203
|
+
}
|
|
167
204
|
export declare class ChatThreadSession extends ChangeEmitter {
|
|
168
205
|
private readonly client;
|
|
169
206
|
readonly threadPath: string;
|
|
@@ -171,6 +208,8 @@ export declare class ChatThreadSession extends ChangeEmitter {
|
|
|
171
208
|
private readonly messageIndexes;
|
|
172
209
|
private readonly localAgentMessageIds;
|
|
173
210
|
private readonly pendingLocalInputMessageIds;
|
|
211
|
+
private readonly resolvedInputMessageIds;
|
|
212
|
+
private readonly completedTurnIds;
|
|
174
213
|
private readonly mergedDeltaMessageIds;
|
|
175
214
|
private readonly pendingInputsById;
|
|
176
215
|
private openState;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ChatThreadSession = exports.MessagingChatClient = exports.BaseChatClient = exports.ChatThreadStartResult = exports.ChatThreadSessionLoadState = exports.ChatThreadSessionLoadPhase = exports.PendingAgentInput = exports.AgentMessageEvent = void 0;
|
|
3
|
+
exports.ChatThreadSession = exports.MessagingChatClient = exports.BaseMessagingChatClient = exports.ThreadListSubscribe = exports.ThreadSubscribe = exports.messagingChatThreadListSubscribeType = exports.messagingChatThreadSubscribeType = exports.BaseChatClient = exports.ChatThreadStartResult = exports.ChatThreadSessionLoadState = exports.ChatThreadSessionLoadPhase = exports.PendingAgentInput = exports.AgentMessageEvent = void 0;
|
|
4
4
|
const meshagent_1 = require("@meshagent/meshagent");
|
|
5
5
|
const uuid_1 = require("uuid");
|
|
6
6
|
const agent_messages_js_1 = require("./agent-messages.js");
|
|
@@ -175,6 +175,13 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
|
|
|
175
175
|
localParticipantName() {
|
|
176
176
|
return undefined;
|
|
177
177
|
}
|
|
178
|
+
localParticipantId() {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
isClientToolCallForLocalParticipant(request) {
|
|
182
|
+
const targetParticipantId = request.targetParticipantId?.trim();
|
|
183
|
+
return targetParticipantId == null || targetParticipantId === "" || targetParticipantId === this.localParticipantId();
|
|
184
|
+
}
|
|
178
185
|
cleanParticipantName(value) {
|
|
179
186
|
return nonEmptyTrimmed(value);
|
|
180
187
|
}
|
|
@@ -280,6 +287,10 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
|
|
|
280
287
|
}
|
|
281
288
|
}
|
|
282
289
|
handleAgentMessage(message, { createdAt, attachment } = {}) {
|
|
290
|
+
if (message instanceof agent_messages_js_1.AgentClientToolCallRequested &&
|
|
291
|
+
!this.isClientToolCallForLocalParticipant(message)) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
283
294
|
if (message.type === agent_messages_js_1.agentConnectionStatusType) {
|
|
284
295
|
this._connectionStatus = message;
|
|
285
296
|
}
|
|
@@ -332,7 +343,41 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
|
|
|
332
343
|
}
|
|
333
344
|
}
|
|
334
345
|
exports.BaseChatClient = BaseChatClient;
|
|
335
|
-
|
|
346
|
+
exports.messagingChatThreadSubscribeType = "meshagent.chat.thread.subscribe";
|
|
347
|
+
exports.messagingChatThreadListSubscribeType = "meshagent.chat.thread_list.subscribe";
|
|
348
|
+
class ThreadSubscribe {
|
|
349
|
+
constructor({ threadId, stream }) {
|
|
350
|
+
this.threadId = threadId;
|
|
351
|
+
this.stream = stream;
|
|
352
|
+
}
|
|
353
|
+
get closed() {
|
|
354
|
+
return this.stream.closed;
|
|
355
|
+
}
|
|
356
|
+
async send(message, { attachment } = {}) {
|
|
357
|
+
await this.stream.sendMessage({
|
|
358
|
+
type: agent_messages_js_1.agentRoomMessageType,
|
|
359
|
+
message: message.toJson(),
|
|
360
|
+
attachment,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
async close() {
|
|
364
|
+
await this.stream.close();
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
exports.ThreadSubscribe = ThreadSubscribe;
|
|
368
|
+
class ThreadListSubscribe {
|
|
369
|
+
constructor({ stream }) {
|
|
370
|
+
this.stream = stream;
|
|
371
|
+
}
|
|
372
|
+
get closed() {
|
|
373
|
+
return this.stream.closed;
|
|
374
|
+
}
|
|
375
|
+
async close() {
|
|
376
|
+
await this.stream.close();
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
exports.ThreadListSubscribe = ThreadListSubscribe;
|
|
380
|
+
class BaseMessagingChatClient extends BaseChatClient {
|
|
336
381
|
constructor({ room, agentName }) {
|
|
337
382
|
super();
|
|
338
383
|
this.pendingParticipantWaits = new Map();
|
|
@@ -420,6 +465,9 @@ class MessagingChatClient extends BaseChatClient {
|
|
|
420
465
|
const name = this.room.localParticipant?.getAttribute("name");
|
|
421
466
|
return typeof name === "string" ? this.cleanParticipantName(name) : undefined;
|
|
422
467
|
}
|
|
468
|
+
localParticipantId() {
|
|
469
|
+
return this.room.localParticipant?.id;
|
|
470
|
+
}
|
|
423
471
|
async start() {
|
|
424
472
|
if (this.started) {
|
|
425
473
|
return;
|
|
@@ -546,6 +594,123 @@ class MessagingChatClient extends BaseChatClient {
|
|
|
546
594
|
}
|
|
547
595
|
}
|
|
548
596
|
}
|
|
597
|
+
exports.BaseMessagingChatClient = BaseMessagingChatClient;
|
|
598
|
+
class MessagingChatClient extends BaseMessagingChatClient {
|
|
599
|
+
constructor() {
|
|
600
|
+
super(...arguments);
|
|
601
|
+
this.threadSubscriptions = new Map();
|
|
602
|
+
this.streamTasks = new Set();
|
|
603
|
+
}
|
|
604
|
+
async stop() {
|
|
605
|
+
const subscriptions = [
|
|
606
|
+
...this.threadSubscriptions.values(),
|
|
607
|
+
];
|
|
608
|
+
if (this.threadListSubscription != null) {
|
|
609
|
+
subscriptions.push(this.threadListSubscription);
|
|
610
|
+
}
|
|
611
|
+
this.threadSubscriptions.clear();
|
|
612
|
+
this.threadListSubscription = undefined;
|
|
613
|
+
await Promise.all(subscriptions.map(async (subscription) => subscription.close()));
|
|
614
|
+
await Promise.all(this.streamTasks);
|
|
615
|
+
await super.stop();
|
|
616
|
+
}
|
|
617
|
+
supportsThreadSubscriptions(participant) {
|
|
618
|
+
return participant.getAttribute("supports_messaging_streams") === true;
|
|
619
|
+
}
|
|
620
|
+
trackStream(subscription) {
|
|
621
|
+
const task = (async () => {
|
|
622
|
+
try {
|
|
623
|
+
for await (const event of subscription.stream) {
|
|
624
|
+
if (event.kind !== "message" || event.message.type !== agent_messages_js_1.agentRoomMessageType) {
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
const raw = event.message.message;
|
|
628
|
+
if (typeof raw["type"] !== "string") {
|
|
629
|
+
continue;
|
|
630
|
+
}
|
|
631
|
+
this.handleAgentMessage(agent_messages_js_1.AgentMessage.fromJson(raw), {
|
|
632
|
+
createdAt: dateOrNull(raw["created_at"]),
|
|
633
|
+
attachment: event.message.attachment,
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
finally {
|
|
638
|
+
if (subscription instanceof ThreadSubscribe) {
|
|
639
|
+
if (this.threadSubscriptions.get(subscription.threadId) === subscription) {
|
|
640
|
+
this.threadSubscriptions.delete(subscription.threadId);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
else if (this.threadListSubscription === subscription) {
|
|
644
|
+
this.threadListSubscription = undefined;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
})();
|
|
648
|
+
this.streamTasks.add(task);
|
|
649
|
+
void task.finally(() => this.streamTasks.delete(task));
|
|
650
|
+
}
|
|
651
|
+
async sendAgentMessage(message, { attachment } = {}) {
|
|
652
|
+
await this.start();
|
|
653
|
+
const participant = this.agentParticipant();
|
|
654
|
+
if (participant == null) {
|
|
655
|
+
throw new Error("Agent messaging participant is not available.");
|
|
656
|
+
}
|
|
657
|
+
if (!this.supportsThreadSubscriptions(participant)) {
|
|
658
|
+
await super.sendAgentMessage(message, { attachment });
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
if (message.type === agent_messages_js_1.agentThreadOpenType) {
|
|
662
|
+
const previous = this.threadSubscriptions.get(message.threadId);
|
|
663
|
+
if (previous != null) {
|
|
664
|
+
await previous.close();
|
|
665
|
+
}
|
|
666
|
+
const stream = await this.room.messaging.stream({
|
|
667
|
+
to: participant,
|
|
668
|
+
type: exports.messagingChatThreadSubscribeType,
|
|
669
|
+
message: message.toJson(),
|
|
670
|
+
attachment,
|
|
671
|
+
});
|
|
672
|
+
const subscription = new ThreadSubscribe({ threadId: message.threadId, stream });
|
|
673
|
+
this.threadSubscriptions.set(message.threadId, subscription);
|
|
674
|
+
this.trackStream(subscription);
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
if (message.type === agent_messages_js_1.agentThreadCloseType) {
|
|
678
|
+
const subscription = this.threadSubscriptions.get(message.threadId);
|
|
679
|
+
if (subscription != null) {
|
|
680
|
+
this.threadSubscriptions.delete(message.threadId);
|
|
681
|
+
await subscription.close();
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
if (message.type === agent_messages_js_1.agentThreadWatchType) {
|
|
686
|
+
await this.threadListSubscription?.close();
|
|
687
|
+
const stream = await this.room.messaging.stream({
|
|
688
|
+
to: participant,
|
|
689
|
+
type: exports.messagingChatThreadListSubscribeType,
|
|
690
|
+
message: message.toJson(),
|
|
691
|
+
attachment,
|
|
692
|
+
});
|
|
693
|
+
const subscription = new ThreadListSubscribe({ stream });
|
|
694
|
+
this.threadListSubscription = subscription;
|
|
695
|
+
this.trackStream(subscription);
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
if (message.type === agent_messages_js_1.agentThreadUnwatchType && this.threadListSubscription != null) {
|
|
699
|
+
const subscription = this.threadListSubscription;
|
|
700
|
+
this.threadListSubscription = undefined;
|
|
701
|
+
await subscription.close();
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
if ("threadId" in message && typeof message.threadId === "string") {
|
|
705
|
+
const subscription = this.threadSubscriptions.get(message.threadId);
|
|
706
|
+
if (subscription != null) {
|
|
707
|
+
await subscription.send(message, { attachment });
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
await super.sendAgentMessage(message, { attachment });
|
|
712
|
+
}
|
|
713
|
+
}
|
|
549
714
|
exports.MessagingChatClient = MessagingChatClient;
|
|
550
715
|
function isThreadListMessage(message) {
|
|
551
716
|
return message.type === agent_messages_js_1.agentThreadListedType
|
|
@@ -560,6 +725,8 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
560
725
|
this.messageIndexes = new Map();
|
|
561
726
|
this.localAgentMessageIds = new Set();
|
|
562
727
|
this.pendingLocalInputMessageIds = new Set();
|
|
728
|
+
this.resolvedInputMessageIds = new Set();
|
|
729
|
+
this.completedTurnIds = new Set();
|
|
563
730
|
this.mergedDeltaMessageIds = new Set();
|
|
564
731
|
this.pendingInputsById = new Map();
|
|
565
732
|
this.openState = false;
|
|
@@ -638,6 +805,8 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
638
805
|
this.messageIndexes.clear();
|
|
639
806
|
this.localAgentMessageIds.clear();
|
|
640
807
|
this.pendingLocalInputMessageIds.clear();
|
|
808
|
+
this.resolvedInputMessageIds.clear();
|
|
809
|
+
this.completedTurnIds.clear();
|
|
641
810
|
this.mergedDeltaMessageIds.clear();
|
|
642
811
|
this.pendingInputsById.clear();
|
|
643
812
|
this.lastCompletedTurnIdValue = undefined;
|
|
@@ -789,15 +958,19 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
789
958
|
return;
|
|
790
959
|
}
|
|
791
960
|
if (message.type === agent_messages_js_1.agentThreadStatusType && message instanceof agent_messages_js_1.AgentThreadStatus) {
|
|
792
|
-
this.threadStatusValue = message;
|
|
793
961
|
const mode = normalizedString(message.mode);
|
|
794
962
|
const status = normalizedString(message.status);
|
|
795
963
|
const turnId = normalizedString(message.turnId);
|
|
796
|
-
if (status
|
|
797
|
-
this.
|
|
964
|
+
if (status == null) {
|
|
965
|
+
this.threadStatusValue = undefined;
|
|
966
|
+
if (turnId != null && this.activeTurnIdValue === turnId) {
|
|
967
|
+
this.activeTurnIdValue = undefined;
|
|
968
|
+
}
|
|
969
|
+
return;
|
|
798
970
|
}
|
|
799
|
-
|
|
800
|
-
|
|
971
|
+
this.threadStatusValue = message;
|
|
972
|
+
if (mode === "steerable" && turnId != null) {
|
|
973
|
+
this.activeTurnIdValue = turnId;
|
|
801
974
|
}
|
|
802
975
|
return;
|
|
803
976
|
}
|
|
@@ -825,21 +998,29 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
825
998
|
updatePendingInputsForMessage(message, createdAt) {
|
|
826
999
|
const type = message.type;
|
|
827
1000
|
const messageId = message.messageId;
|
|
828
|
-
const sourceMessageId = sourceMessageIdFor(message);
|
|
1001
|
+
const sourceMessageId = normalizedString(sourceMessageIdFor(message));
|
|
829
1002
|
if (type === agent_messages_js_1.agentThreadStartType || type === agent_messages_js_1.agentTurnStartType || type === agent_messages_js_1.agentTurnSteerType) {
|
|
830
1003
|
const normalizedMessageId = messageId.trim();
|
|
831
1004
|
if (normalizedMessageId !== "") {
|
|
1005
|
+
const wasPending = this.pendingInputsById.has(normalizedMessageId);
|
|
1006
|
+
const turnId = type === agent_messages_js_1.agentTurnStartType || type === agent_messages_js_1.agentTurnSteerType
|
|
1007
|
+
? normalizedString(threadMessageValue(message, "turnId"))
|
|
1008
|
+
: undefined;
|
|
1009
|
+
const wasAlreadyResolved = !wasPending && (this.resolvedInputMessageIds.has(normalizedMessageId) ||
|
|
1010
|
+
(turnId != null && this.completedTurnIds.has(turnId)));
|
|
832
1011
|
this.localAgentMessageIds.add(normalizedMessageId);
|
|
833
1012
|
this.pendingLocalInputMessageIds.add(normalizedMessageId);
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
1013
|
+
if (!wasAlreadyResolved) {
|
|
1014
|
+
this.markPending(new PendingAgentInput({
|
|
1015
|
+
messageId: normalizedMessageId,
|
|
1016
|
+
messageType: type,
|
|
1017
|
+
threadPath: this.threadPath,
|
|
1018
|
+
payload: message,
|
|
1019
|
+
createdAt,
|
|
1020
|
+
awaitingAcceptance: true,
|
|
1021
|
+
awaitingApplication: true,
|
|
1022
|
+
}));
|
|
1023
|
+
}
|
|
843
1024
|
}
|
|
844
1025
|
}
|
|
845
1026
|
else if (type === agent_messages_js_1.agentThreadStartRejectedType) {
|
|
@@ -852,12 +1033,14 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
852
1033
|
}
|
|
853
1034
|
else if (type === agent_messages_js_1.agentTurnStartedType || type === agent_messages_js_1.agentTurnSteeredType) {
|
|
854
1035
|
if (sourceMessageId != null) {
|
|
1036
|
+
this.resolvedInputMessageIds.add(sourceMessageId);
|
|
855
1037
|
this.pendingInputsById.delete(sourceMessageId);
|
|
856
1038
|
this.pendingLocalInputMessageIds.delete(sourceMessageId);
|
|
857
1039
|
}
|
|
858
1040
|
}
|
|
859
1041
|
else if (type === agent_messages_js_1.agentTurnStartRejectedType || type === agent_messages_js_1.agentTurnSteerRejectedType) {
|
|
860
1042
|
if (sourceMessageId != null) {
|
|
1043
|
+
this.resolvedInputMessageIds.add(sourceMessageId);
|
|
861
1044
|
this.pendingInputsById.delete(sourceMessageId);
|
|
862
1045
|
this.pendingLocalInputMessageIds.delete(sourceMessageId);
|
|
863
1046
|
}
|
|
@@ -865,6 +1048,15 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
865
1048
|
else if (type === agent_messages_js_1.agentTurnEndedType || type === agent_messages_js_1.agentThreadClearedType) {
|
|
866
1049
|
this.pendingInputsById.clear();
|
|
867
1050
|
this.pendingLocalInputMessageIds.clear();
|
|
1051
|
+
if (type === agent_messages_js_1.agentTurnEndedType) {
|
|
1052
|
+
const turnId = normalizedString(threadMessageValue(message, "turnId"));
|
|
1053
|
+
if (turnId != null)
|
|
1054
|
+
this.completedTurnIds.add(turnId);
|
|
1055
|
+
}
|
|
1056
|
+
else if (type === agent_messages_js_1.agentThreadClearedType) {
|
|
1057
|
+
this.resolvedInputMessageIds.clear();
|
|
1058
|
+
this.completedTurnIds.clear();
|
|
1059
|
+
}
|
|
868
1060
|
}
|
|
869
1061
|
}
|
|
870
1062
|
appendRenderableMessage(event) {
|
|
@@ -721,26 +721,16 @@ function makeMessageClass({ type, base = "message", fields = [], }) {
|
|
|
721
721
|
params.model = stringOrNull(json.model);
|
|
722
722
|
}
|
|
723
723
|
for (const field of fields) {
|
|
724
|
-
if (field.
|
|
725
|
-
if (field.
|
|
726
|
-
|
|
724
|
+
if (!hasOwn(json, field.json)) {
|
|
725
|
+
if (field.required) {
|
|
726
|
+
if (field.from != null) {
|
|
727
|
+
field.from(undefined, json);
|
|
728
|
+
}
|
|
729
|
+
throw new TypeError(`missing required field '${field.json}'`);
|
|
727
730
|
}
|
|
728
|
-
|
|
729
|
-
params[field.prop] = requiredString(json, field.json);
|
|
730
|
-
}
|
|
731
|
-
else if (typeof json[field.json] === "number") {
|
|
732
|
-
params[field.prop] = json[field.json];
|
|
733
|
-
}
|
|
734
|
-
else {
|
|
735
|
-
params[field.prop] = requiredMap(json, field.json);
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
else if (hasOwn(json, field.json)) {
|
|
739
|
-
params[field.prop] = field.from != null ? field.from(json[field.json], json) : json[field.json];
|
|
740
|
-
}
|
|
741
|
-
else if (field.default != null) {
|
|
742
|
-
params[field.prop] = field.default(json);
|
|
731
|
+
continue;
|
|
743
732
|
}
|
|
733
|
+
params[field.prop] = json[field.json];
|
|
744
734
|
}
|
|
745
735
|
return new this(params);
|
|
746
736
|
}
|
|
@@ -964,10 +954,10 @@ export const AgentToolCallLogDelta = makeMessageClass({ type: agentToolCallLogDe
|
|
|
964
954
|
export const AgentToolCallEnded = makeMessageClass({ type: agentToolCallEndedType, base: "llm", fields: [...contentPart, { prop: "namespace", json: "namespace", from: (value) => stringOrNull(value) ?? "meshagent", default: () => "meshagent", always: true }, s("callId"), s("toolkit"), s("tool"), { prop: "result", json: "result", from: contentOrNull, to: contentHeader }, obj("error", "error", AgentError.fromJson)] });
|
|
965
955
|
export const AgentToolCallApprovalRequested = makeMessageClass({ type: agentToolCallApprovalRequestedType, base: "llm", fields: toolState.filter((field) => field.prop !== "argumentBytes") });
|
|
966
956
|
export const AgentSecretRequested = makeMessageClass({ type: agentSecretRequestedType, base: "llm", fields: [...contentPart, s("requestId", "request_id", true), s("name", "name", true), s("scope")] });
|
|
967
|
-
export const AgentClientToolCallRequested = makeMessageClass({ type: agentClientToolCallRequestedType, base: "llm", fields: [...contentPart, s("requestId", "request_id", true), s("toolkit", "toolkit", true), s("tool", "tool", true), m("arguments", "arguments", true)] });
|
|
968
|
-
export const AgentClientToolCallCancelled = makeMessageClass({ type: agentClientToolCallCancelledType, base: "llm", fields: [...contentPart, s("requestId", "request_id", true), s("reason")] });
|
|
957
|
+
export const AgentClientToolCallRequested = makeMessageClass({ type: agentClientToolCallRequestedType, base: "llm", fields: [...contentPart, s("requestId", "request_id", true), s("targetParticipantId"), s("toolkit", "toolkit", true), s("tool", "tool", true), m("arguments", "arguments", true)] });
|
|
958
|
+
export const AgentClientToolCallCancelled = makeMessageClass({ type: agentClientToolCallCancelledType, base: "llm", fields: [...contentPart, s("requestId", "request_id", true), s("targetParticipantId"), s("reason")] });
|
|
969
959
|
export const AgentThreadStatus = makeMessageClass({ type: agentThreadStatusType, base: "thread", fields: [s("status"), s("mode"), s("startedAt"), s("turnId"), s("pendingItemId"), i("totalBytes"), i("linesAdded"), i("linesRemoved")] });
|
|
970
|
-
export const AgentConnectionStatus = makeMessageClass({ type: agentConnectionStatusType, fields: [s("status", "status", true), s("message"), s("reason"), n("retryInSeconds")] });
|
|
960
|
+
export const AgentConnectionStatus = makeMessageClass({ type: agentConnectionStatusType, fields: [s("status", "status", true), s("message"), s("reason"), n("retryInSeconds"), s("participantId")] });
|
|
971
961
|
export const AgentThreadEvent = makeMessageClass({ type: agentThreadEventType, base: "llm", fields: [m("event", "event", true)] });
|
|
972
962
|
export const AgentImageGenerationStarted = makeMessageClass({ type: agentImageGenerationStartedType, base: "llm", fields: imageGeneration });
|
|
973
963
|
export const AgentImageGenerationPartial = makeMessageClass({ type: agentImageGenerationPartialType, base: "llm", fields: [...imageGeneration, obj("image", "image", AgentGeneratedImage.fromJson), i("partialIndex")] });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { RemoteParticipant } from "@meshagent/meshagent";
|
|
1
|
+
import { MessagingStream, RemoteParticipant } from "@meshagent/meshagent";
|
|
2
2
|
import type { RoomClient, Content } from "@meshagent/meshagent";
|
|
3
|
-
import { AgentMessage, AgentModelChanged, AgentThreadStatus, ModelsResponse, ToolChoice, AgentConnectionStatus } from "./agent-messages.js";
|
|
3
|
+
import { AgentMessage, AgentModelChanged, AgentThreadStatus, ModelsResponse, ToolChoice, AgentConnectionStatus, AgentClientToolCallRequested } from "./agent-messages.js";
|
|
4
4
|
import type { AgentPayload, JsonMap, ClientToolkitDescription } from "./agent-messages.js";
|
|
5
5
|
import { ChangeEmitter } from "./change-emitter.js";
|
|
6
6
|
export declare class AgentMessageEvent {
|
|
@@ -90,6 +90,8 @@ export declare abstract class BaseChatClient extends ChangeEmitter {
|
|
|
90
90
|
stop(): Promise<void>;
|
|
91
91
|
agentParticipant(): RemoteParticipant | null;
|
|
92
92
|
localParticipantName(): string | undefined;
|
|
93
|
+
localParticipantId(): string | undefined;
|
|
94
|
+
isClientToolCallForLocalParticipant(request: InstanceType<typeof AgentClientToolCallRequested>): boolean;
|
|
93
95
|
protected cleanParticipantName(value: string | undefined): string | undefined;
|
|
94
96
|
openThread(threadPath: string, { load, sinceTurn, reloadIfOpen, drainPendingEvents, }?: {
|
|
95
97
|
load?: boolean;
|
|
@@ -131,7 +133,30 @@ export declare abstract class BaseChatClient extends ChangeEmitter {
|
|
|
131
133
|
}): void;
|
|
132
134
|
removeThreadSession(threadPath: string): void;
|
|
133
135
|
}
|
|
134
|
-
export declare
|
|
136
|
+
export declare const messagingChatThreadSubscribeType = "meshagent.chat.thread.subscribe";
|
|
137
|
+
export declare const messagingChatThreadListSubscribeType = "meshagent.chat.thread_list.subscribe";
|
|
138
|
+
export declare class ThreadSubscribe {
|
|
139
|
+
readonly threadId: string;
|
|
140
|
+
readonly stream: MessagingStream;
|
|
141
|
+
constructor({ threadId, stream }: {
|
|
142
|
+
threadId: string;
|
|
143
|
+
stream: MessagingStream;
|
|
144
|
+
});
|
|
145
|
+
get closed(): boolean;
|
|
146
|
+
send(message: AgentMessage, { attachment }?: {
|
|
147
|
+
attachment?: Uint8Array;
|
|
148
|
+
}): Promise<void>;
|
|
149
|
+
close(): Promise<void>;
|
|
150
|
+
}
|
|
151
|
+
export declare class ThreadListSubscribe {
|
|
152
|
+
readonly stream: MessagingStream;
|
|
153
|
+
constructor({ stream }: {
|
|
154
|
+
stream: MessagingStream;
|
|
155
|
+
});
|
|
156
|
+
get closed(): boolean;
|
|
157
|
+
close(): Promise<void>;
|
|
158
|
+
}
|
|
159
|
+
export declare class BaseMessagingChatClient extends BaseChatClient {
|
|
135
160
|
readonly room: RoomClient;
|
|
136
161
|
readonly agentName?: string;
|
|
137
162
|
private readonly pendingParticipantWaits;
|
|
@@ -146,6 +171,7 @@ export declare class MessagingChatClient extends BaseChatClient {
|
|
|
146
171
|
agentName?: string;
|
|
147
172
|
});
|
|
148
173
|
localParticipantName(): string | undefined;
|
|
174
|
+
localParticipantId(): string | undefined;
|
|
149
175
|
start(): Promise<void>;
|
|
150
176
|
stop(): Promise<void>;
|
|
151
177
|
private attachMessagingListeners;
|
|
@@ -164,6 +190,17 @@ export declare class MessagingChatClient extends BaseChatClient {
|
|
|
164
190
|
private reopenOpenSessions;
|
|
165
191
|
private readonly onMessagingMessage;
|
|
166
192
|
}
|
|
193
|
+
export declare class MessagingChatClient extends BaseMessagingChatClient {
|
|
194
|
+
private readonly threadSubscriptions;
|
|
195
|
+
private threadListSubscription?;
|
|
196
|
+
private readonly streamTasks;
|
|
197
|
+
stop(): Promise<void>;
|
|
198
|
+
private supportsThreadSubscriptions;
|
|
199
|
+
private trackStream;
|
|
200
|
+
sendAgentMessage(message: AgentMessage, { attachment }?: {
|
|
201
|
+
attachment?: Uint8Array;
|
|
202
|
+
}): Promise<void>;
|
|
203
|
+
}
|
|
167
204
|
export declare class ChatThreadSession extends ChangeEmitter {
|
|
168
205
|
private readonly client;
|
|
169
206
|
readonly threadPath: string;
|
|
@@ -171,6 +208,8 @@ export declare class ChatThreadSession extends ChangeEmitter {
|
|
|
171
208
|
private readonly messageIndexes;
|
|
172
209
|
private readonly localAgentMessageIds;
|
|
173
210
|
private readonly pendingLocalInputMessageIds;
|
|
211
|
+
private readonly resolvedInputMessageIds;
|
|
212
|
+
private readonly completedTurnIds;
|
|
174
213
|
private readonly mergedDeltaMessageIds;
|
|
175
214
|
private readonly pendingInputsById;
|
|
176
215
|
private openState;
|