@axiom-lattice/gateway 2.1.49 → 2.1.50
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/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +8 -0
- package/dist/index.js +243 -126
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +129 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/controllers/auth.ts +73 -0
- package/src/controllers/run.ts +10 -2
- package/src/controllers/thread_status.ts +66 -228
- package/src/index.ts +16 -9
- package/src/routes/index.ts +9 -0
- package/src/types/index.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axiom-lattice/gateway",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.50",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "dist/index.mjs",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"pg": "^8.11.0",
|
|
39
39
|
"redis": "^5.0.1",
|
|
40
40
|
"uuid": "^9.0.1",
|
|
41
|
-
"@axiom-lattice/core": "2.1.
|
|
42
|
-
"@axiom-lattice/pg-stores": "1.0.
|
|
41
|
+
"@axiom-lattice/core": "2.1.44",
|
|
42
|
+
"@axiom-lattice/pg-stores": "1.0.34",
|
|
43
43
|
"@axiom-lattice/protocols": "2.1.23",
|
|
44
44
|
"@axiom-lattice/queue-redis": "1.0.22"
|
|
45
45
|
},
|
package/src/controllers/auth.ts
CHANGED
|
@@ -29,6 +29,11 @@ interface AssignTenantRequest {
|
|
|
29
29
|
role?: UserTenantRole;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
interface ChangePasswordRequest {
|
|
33
|
+
currentPassword: string;
|
|
34
|
+
newPassword: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
32
37
|
export interface AuthConfig {
|
|
33
38
|
autoApproveUsers: boolean;
|
|
34
39
|
allowTenantRegistration: boolean;
|
|
@@ -391,6 +396,71 @@ export class AuthController {
|
|
|
391
396
|
}
|
|
392
397
|
return btoa(JSON.stringify(payload));
|
|
393
398
|
}
|
|
399
|
+
|
|
400
|
+
async changePassword(
|
|
401
|
+
request: FastifyRequest<{ Body: ChangePasswordRequest }>,
|
|
402
|
+
reply: FastifyReply
|
|
403
|
+
) {
|
|
404
|
+
const userId = (request as any).user?.id;
|
|
405
|
+
const { currentPassword, newPassword } = request.body;
|
|
406
|
+
|
|
407
|
+
if (!userId) {
|
|
408
|
+
return reply.status(401).send({
|
|
409
|
+
success: false,
|
|
410
|
+
error: "Unauthorized",
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
const user = await this.userStore.getUserById(userId);
|
|
416
|
+
if (!user) {
|
|
417
|
+
return reply.status(404).send({
|
|
418
|
+
success: false,
|
|
419
|
+
error: "User not found",
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// Verify current password
|
|
424
|
+
const isValidPassword = await this.verifyPassword(
|
|
425
|
+
currentPassword,
|
|
426
|
+
user.metadata?.passwordHash || ""
|
|
427
|
+
);
|
|
428
|
+
|
|
429
|
+
if (!isValidPassword) {
|
|
430
|
+
return reply.status(401).send({
|
|
431
|
+
success: false,
|
|
432
|
+
error: "Current password is incorrect",
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Validate new password length
|
|
437
|
+
if (newPassword.length < 6) {
|
|
438
|
+
return reply.status(400).send({
|
|
439
|
+
success: false,
|
|
440
|
+
error: "New password must be at least 6 characters",
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Update password
|
|
445
|
+
await this.userStore.updateUser(userId, {
|
|
446
|
+
metadata: {
|
|
447
|
+
...user.metadata,
|
|
448
|
+
passwordHash: await this.hashPassword(newPassword),
|
|
449
|
+
},
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
return reply.send({
|
|
453
|
+
success: true,
|
|
454
|
+
message: "Password changed successfully",
|
|
455
|
+
});
|
|
456
|
+
} catch (error) {
|
|
457
|
+
console.error("Change password error:", error);
|
|
458
|
+
return reply.status(500).send({
|
|
459
|
+
success: false,
|
|
460
|
+
error: "Failed to change password",
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
}
|
|
394
464
|
}
|
|
395
465
|
|
|
396
466
|
export function registerAuthRoutes(
|
|
@@ -440,4 +510,7 @@ export function registerAuthRoutes(
|
|
|
440
510
|
app.post("/api/auth/approve", { preHandler: authHook }, (req, res) => controller.approveUser(req as any, res));
|
|
441
511
|
app.get("/api/auth/pending", { preHandler: authHook }, (req, res) => controller.listPendingUsers(req, res));
|
|
442
512
|
app.post("/api/auth/assign-tenant", { preHandler: authHook }, (req, res) => controller.assignTenant(req as any, res));
|
|
513
|
+
app.post("/api/auth/change-password", { preHandler: authHook },
|
|
514
|
+
(req, res) => controller.changePassword(req as any, res)
|
|
515
|
+
);
|
|
443
516
|
}
|
package/src/controllers/run.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
ThreadStatus,
|
|
7
7
|
agentLatticeManager,
|
|
8
8
|
agentInstanceManager,
|
|
9
|
+
QueueMode,
|
|
9
10
|
} from "@axiom-lattice/core";
|
|
10
11
|
import { MessageChunkTypes } from "@axiom-lattice/protocols";
|
|
11
12
|
|
|
@@ -26,10 +27,12 @@ export const createRun = async (
|
|
|
26
27
|
const {
|
|
27
28
|
assistant_id,
|
|
28
29
|
thread_id,
|
|
30
|
+
message_id,
|
|
29
31
|
command,
|
|
30
32
|
streaming,
|
|
31
33
|
background,
|
|
32
34
|
custom_run_config,
|
|
35
|
+
mode,
|
|
33
36
|
...input
|
|
34
37
|
} = request.body as CreateRunRequest;
|
|
35
38
|
|
|
@@ -72,11 +75,16 @@ export const createRun = async (
|
|
|
72
75
|
try {
|
|
73
76
|
|
|
74
77
|
// Execute agent with streaming
|
|
78
|
+
// Only pass id if message_id is provided (for backward compatibility)
|
|
79
|
+
const messageInput = message_id
|
|
80
|
+
? { ...input, id: message_id }
|
|
81
|
+
: input;
|
|
82
|
+
|
|
75
83
|
const result = await agent.addMessage({
|
|
76
|
-
input,
|
|
84
|
+
input: messageInput,
|
|
77
85
|
command,
|
|
78
86
|
custom_run_config,
|
|
79
|
-
});
|
|
87
|
+
}, mode as QueueMode);
|
|
80
88
|
|
|
81
89
|
// const agentStatus = await agent.getRunStatus()
|
|
82
90
|
// console.log(agentStatus)
|
|
@@ -1,228 +1,66 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
// message: error instanceof Error ? error.message : String(error),
|
|
68
|
-
// });
|
|
69
|
-
// }
|
|
70
|
-
// }
|
|
71
|
-
|
|
72
|
-
// /**
|
|
73
|
-
// * GET /api/threads/active
|
|
74
|
-
// * Query all active threads (BUSY + INTERRUPTED)
|
|
75
|
-
// */
|
|
76
|
-
// export async function getActiveThreadsHandler(
|
|
77
|
-
// request: FastifyRequest,
|
|
78
|
-
// reply: FastifyReply
|
|
79
|
-
// ) {
|
|
80
|
-
// try {
|
|
81
|
-
// const tenant_id = request.headers["x-tenant-id"] as string;
|
|
82
|
-
|
|
83
|
-
// if (!tenant_id) {
|
|
84
|
-
// return reply.code(400).send({ error: "Missing x-tenant-id header" });
|
|
85
|
-
// }
|
|
86
|
-
|
|
87
|
-
// const threads = lifecycleManager.getActiveThreads(tenant_id);
|
|
88
|
-
|
|
89
|
-
// return reply.send({
|
|
90
|
-
// threads,
|
|
91
|
-
// count: threads.length,
|
|
92
|
-
// });
|
|
93
|
-
// } catch (error) {
|
|
94
|
-
// console.error("Error getting active threads:", error);
|
|
95
|
-
// return reply.code(500).send({
|
|
96
|
-
// error: "Internal server error",
|
|
97
|
-
// message: error instanceof Error ? error.message : String(error),
|
|
98
|
-
// });
|
|
99
|
-
// }
|
|
100
|
-
// }
|
|
101
|
-
|
|
102
|
-
// /**
|
|
103
|
-
// * POST /api/threads/:thread_id/messages
|
|
104
|
-
// * Add message to queue or execute immediately (steer mode)
|
|
105
|
-
// */
|
|
106
|
-
// export async function addMessageHandler(
|
|
107
|
-
// request: FastifyRequest,
|
|
108
|
-
// reply: FastifyReply
|
|
109
|
-
// ) {
|
|
110
|
-
// try {
|
|
111
|
-
// const { thread_id } = request.params as { thread_id: string };
|
|
112
|
-
// const tenant_id = request.headers["x-tenant-id"] as string;
|
|
113
|
-
// const { assistant_id, content, mode } = request.body as {
|
|
114
|
-
// assistant_id: string;
|
|
115
|
-
// content: any;
|
|
116
|
-
// mode?: QueueMode;
|
|
117
|
-
// };
|
|
118
|
-
|
|
119
|
-
// if (!tenant_id) {
|
|
120
|
-
// return reply.code(400).send({ error: "Missing x-tenant-id header" });
|
|
121
|
-
// }
|
|
122
|
-
|
|
123
|
-
// if (!assistant_id || !content) {
|
|
124
|
-
// return reply.code(400).send({ error: "Missing assistant_id or content" });
|
|
125
|
-
// }
|
|
126
|
-
|
|
127
|
-
// const result = await lifecycleManager.addMessage(
|
|
128
|
-
// tenant_id,
|
|
129
|
-
// assistant_id,
|
|
130
|
-
// thread_id,
|
|
131
|
-
// content,
|
|
132
|
-
// mode
|
|
133
|
-
// );
|
|
134
|
-
|
|
135
|
-
// return reply.send({
|
|
136
|
-
// success: true,
|
|
137
|
-
// threadId: thread_id,
|
|
138
|
-
// ...result,
|
|
139
|
-
// });
|
|
140
|
-
// } catch (error) {
|
|
141
|
-
// console.error("Error adding message:", error);
|
|
142
|
-
// return reply.code(500).send({
|
|
143
|
-
// error: "Internal server error",
|
|
144
|
-
// message: error instanceof Error ? error.message : String(error),
|
|
145
|
-
// });
|
|
146
|
-
// }
|
|
147
|
-
// }
|
|
148
|
-
|
|
149
|
-
// /**
|
|
150
|
-
// * DELETE /api/threads/:thread_id/messages/:message_id
|
|
151
|
-
// * Remove pending message
|
|
152
|
-
// */
|
|
153
|
-
// export async function removeMessageHandler(
|
|
154
|
-
// request: FastifyRequest,
|
|
155
|
-
// reply: FastifyReply
|
|
156
|
-
// ) {
|
|
157
|
-
// try {
|
|
158
|
-
// const { thread_id, message_id } = request.params as {
|
|
159
|
-
// thread_id: string;
|
|
160
|
-
// message_id: string;
|
|
161
|
-
// };
|
|
162
|
-
// const tenant_id = request.headers["x-tenant-id"] as string;
|
|
163
|
-
|
|
164
|
-
// if (!tenant_id) {
|
|
165
|
-
// return reply.code(400).send({ error: "Missing x-tenant-id header" });
|
|
166
|
-
// }
|
|
167
|
-
|
|
168
|
-
// const success = await lifecycleManager.removePendingMessage(
|
|
169
|
-
// tenant_id,
|
|
170
|
-
// thread_id,
|
|
171
|
-
// message_id
|
|
172
|
-
// );
|
|
173
|
-
|
|
174
|
-
// if (!success) {
|
|
175
|
-
// return reply.code(404).send({
|
|
176
|
-
// error: "Message not found",
|
|
177
|
-
// messageId: message_id,
|
|
178
|
-
// });
|
|
179
|
-
// }
|
|
180
|
-
|
|
181
|
-
// return reply.send({
|
|
182
|
-
// success: true,
|
|
183
|
-
// messageId: message_id,
|
|
184
|
-
// });
|
|
185
|
-
// } catch (error) {
|
|
186
|
-
// console.error("Error removing message:", error);
|
|
187
|
-
// return reply.code(500).send({
|
|
188
|
-
// error: "Internal server error",
|
|
189
|
-
// message: error instanceof Error ? error.message : String(error),
|
|
190
|
-
// });
|
|
191
|
-
// }
|
|
192
|
-
// }
|
|
193
|
-
|
|
194
|
-
// /**
|
|
195
|
-
// * PUT /api/threads/:thread_id/queue-config
|
|
196
|
-
// * Update queue configuration
|
|
197
|
-
// */
|
|
198
|
-
// export async function updateQueueConfigHandler(
|
|
199
|
-
// request: FastifyRequest,
|
|
200
|
-
// reply: FastifyReply
|
|
201
|
-
// ) {
|
|
202
|
-
// try {
|
|
203
|
-
// const { thread_id } = request.params as { thread_id: string };
|
|
204
|
-
// const tenant_id = request.headers["x-tenant-id"] as string;
|
|
205
|
-
// const config = request.body as {
|
|
206
|
-
// mode?: QueueMode;
|
|
207
|
-
// maxSize?: number;
|
|
208
|
-
// };
|
|
209
|
-
|
|
210
|
-
// if (!tenant_id) {
|
|
211
|
-
// return reply.code(400).send({ error: "Missing x-tenant-id header" });
|
|
212
|
-
// }
|
|
213
|
-
|
|
214
|
-
// await lifecycleManager.setQueueConfig(tenant_id, thread_id, config);
|
|
215
|
-
|
|
216
|
-
// return reply.send({
|
|
217
|
-
// success: true,
|
|
218
|
-
// threadId: thread_id,
|
|
219
|
-
// config,
|
|
220
|
-
// });
|
|
221
|
-
// } catch (error) {
|
|
222
|
-
// console.error("Error updating queue config:", error);
|
|
223
|
-
// return reply.code(500).send({
|
|
224
|
-
// error: "Internal server error",
|
|
225
|
-
// message: error instanceof Error ? error.message : String(error),
|
|
226
|
-
// });
|
|
227
|
-
// }
|
|
228
|
-
// }
|
|
1
|
+
import { FastifyRequest, FastifyReply } from "fastify";
|
|
2
|
+
import { agentInstanceManager } from "@axiom-lattice/core";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* DELETE /api/assistants/:assistant_id/threads/:thread_id/pending-messages/:message_id
|
|
6
|
+
* Remove pending message from queue
|
|
7
|
+
*/
|
|
8
|
+
export async function removePendingMessageHandler(
|
|
9
|
+
request: FastifyRequest,
|
|
10
|
+
reply: FastifyReply
|
|
11
|
+
) {
|
|
12
|
+
try {
|
|
13
|
+
const { assistant_id, thread_id, message_id } = request.params as {
|
|
14
|
+
assistant_id: string;
|
|
15
|
+
thread_id: string;
|
|
16
|
+
message_id: string;
|
|
17
|
+
};
|
|
18
|
+
const tenant_id = request.headers["x-tenant-id"] as string;
|
|
19
|
+
const workspace_id = request.headers["x-workspace-id"] as string;
|
|
20
|
+
const project_id = request.headers["x-project-id"] as string;
|
|
21
|
+
|
|
22
|
+
if (!tenant_id) {
|
|
23
|
+
return reply.code(400).send({ error: "Missing x-tenant-id header" });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!assistant_id) {
|
|
27
|
+
return reply.code(400).send({ error: "Missing assistant_id parameter" });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Get agent instance
|
|
31
|
+
const agent = agentInstanceManager.getAgent({
|
|
32
|
+
assistant_id,
|
|
33
|
+
thread_id,
|
|
34
|
+
tenant_id,
|
|
35
|
+
workspace_id,
|
|
36
|
+
project_id,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (!agent) {
|
|
40
|
+
return reply.code(404).send({
|
|
41
|
+
error: "Thread not found",
|
|
42
|
+
threadId: thread_id,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const success = await agent.removePendingMessage(message_id);
|
|
47
|
+
|
|
48
|
+
if (!success) {
|
|
49
|
+
return reply.code(404).send({
|
|
50
|
+
error: "Message not found",
|
|
51
|
+
messageId: message_id,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return reply.send({
|
|
56
|
+
success: true,
|
|
57
|
+
messageId: message_id,
|
|
58
|
+
});
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error("Error removing pending message:", error);
|
|
61
|
+
return reply.code(500).send({
|
|
62
|
+
error: "Internal server error",
|
|
63
|
+
message: error instanceof Error ? error.message : String(error),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -69,6 +69,22 @@ const app = fastify({
|
|
|
69
69
|
bodyLimit: Number(process.env.BODY_LIMIT) || 50 * 1024 * 1024, // Default 50MB, configurable via BODY_LIMIT env var
|
|
70
70
|
});
|
|
71
71
|
|
|
72
|
+
// Custom content type parser to handle DELETE requests with Content-Type but no body
|
|
73
|
+
// This prevents "Body cannot be empty when content-type is set to 'application/json'" error
|
|
74
|
+
app.addContentTypeParser('application/json', { parseAs: 'string' }, function (request, body, done) {
|
|
75
|
+
// For DELETE requests or empty body, return empty object
|
|
76
|
+
if (request.method === 'DELETE' || !body || body.length === 0) {
|
|
77
|
+
done(null, {});
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const json = JSON.parse(body as string);
|
|
82
|
+
done(null, json);
|
|
83
|
+
} catch (err) {
|
|
84
|
+
done(err as Error, undefined);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
72
88
|
|
|
73
89
|
// Add custom logging hooks
|
|
74
90
|
app.addHook("onRequest", (request, reply, done) => {
|
|
@@ -93,15 +109,6 @@ app.addHook("onRequest", (request, reply, done) => {
|
|
|
93
109
|
done();
|
|
94
110
|
});
|
|
95
111
|
|
|
96
|
-
// Fix for DELETE requests with Content-Type: application/json header
|
|
97
|
-
// Some clients send Content-Type header even for DELETE requests without body
|
|
98
|
-
app.addHook("onRequest", async (request, reply) => {
|
|
99
|
-
if (request.method === "DELETE" && request.headers["content-type"]) {
|
|
100
|
-
// Remove content-type header for DELETE requests to avoid body parsing errors
|
|
101
|
-
delete request.headers["content-type"];
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
|
|
105
112
|
app.addHook("onResponse", (request, reply, done) => {
|
|
106
113
|
// Convert headers to strings (Fastify headers can be string | string[])
|
|
107
114
|
const getHeaderValue = (
|
package/src/routes/index.ts
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
getSandboxUrlSchema,
|
|
31
31
|
dataQuerySchema,
|
|
32
32
|
} from "../schemas";
|
|
33
|
+
import { removePendingMessageHandler } from "../controllers/thread_status";
|
|
33
34
|
import { registerSandboxProxyRoutes } from "../controllers/sandbox";
|
|
34
35
|
import { registerWorkspaceRoutes } from "../controllers/workspace";
|
|
35
36
|
import { registerDatabaseConfigRoutes } from "../controllers/database-configs";
|
|
@@ -346,4 +347,12 @@ export const registerLatticeRoutes = (app: FastifyInstance): void => {
|
|
|
346
347
|
// app.post("/api/threads/:thread_id/messages", addMessageHandler);
|
|
347
348
|
// app.delete("/api/threads/:thread_id/messages/:message_id", removeMessageHandler);
|
|
348
349
|
// app.put("/api/threads/:thread_id/queue-config", updateQueueConfigHandler);
|
|
350
|
+
|
|
351
|
+
// Delete pending message route
|
|
352
|
+
app.delete<{
|
|
353
|
+
Params: { assistant_id: string; thread_id: string; message_id: string };
|
|
354
|
+
}>(
|
|
355
|
+
"/api/assistants/:assistant_id/threads/:thread_id/pending-messages/:message_id",
|
|
356
|
+
removePendingMessageHandler
|
|
357
|
+
);
|
|
349
358
|
};
|
package/src/types/index.ts
CHANGED
|
@@ -77,10 +77,12 @@ export interface CreateRunRequest {
|
|
|
77
77
|
thread_id: string;
|
|
78
78
|
assistant_id: string;
|
|
79
79
|
message: any;
|
|
80
|
+
message_id?: string;
|
|
80
81
|
command?: any;
|
|
81
82
|
streaming?: boolean;
|
|
82
83
|
background?: boolean;
|
|
83
84
|
custom_run_config?: Record<string, any>;
|
|
85
|
+
mode?: 'collect' | 'followup' | 'steer';
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
// 添加消息请求类型
|