@downcity/agent 1.1.69 → 1.1.70
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/bin/agent/Agent.d.ts.map +1 -1
- package/bin/agent/Agent.js +1 -0
- package/bin/agent/Agent.js.map +1 -1
- package/bin/config/Config.d.ts.map +1 -1
- package/bin/config/Config.js +16 -4
- package/bin/config/Config.js.map +1 -1
- package/bin/rpc/Client.d.ts +80 -0
- package/bin/rpc/Client.d.ts.map +1 -1
- package/bin/rpc/Client.js +46 -0
- package/bin/rpc/Client.js.map +1 -1
- package/bin/rpc/Server.d.ts +3 -0
- package/bin/rpc/Server.d.ts.map +1 -1
- package/bin/rpc/Server.js +115 -0
- package/bin/rpc/Server.js.map +1 -1
- package/package.json +1 -1
- package/src/agent/Agent.ts +1 -0
- package/src/config/Config.ts +17 -4
- package/src/rpc/Client.ts +148 -0
- package/src/rpc/Server.ts +166 -0
- package/tsconfig.tsbuildinfo +1 -1
package/src/config/Config.ts
CHANGED
|
@@ -96,6 +96,17 @@ function assertNoProjectExtensionsLayer(
|
|
|
96
96
|
);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
function normalizeDefaultAgentId(projectRoot: string): string {
|
|
100
|
+
const basename = path.basename(projectRoot);
|
|
101
|
+
return basename
|
|
102
|
+
.trim()
|
|
103
|
+
.toLowerCase()
|
|
104
|
+
.replace(/[^a-z0-9]+/g, "_")
|
|
105
|
+
.replace(/^_+|_+$/g, "")
|
|
106
|
+
.replace(/_{2,}/g, "_")
|
|
107
|
+
.trim() || basename || "agent";
|
|
108
|
+
}
|
|
109
|
+
|
|
99
110
|
/**
|
|
100
111
|
* 加载当前项目最终生效的 `downcity.json` 配置。
|
|
101
112
|
*
|
|
@@ -124,10 +135,12 @@ export function loadDowncityConfig(projectRoot: string): DowncityConfig {
|
|
|
124
135
|
}
|
|
125
136
|
|
|
126
137
|
const candidate = merged as Partial<DowncityConfig>;
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
138
|
+
// 关键点(中文):运行态 agent id 与 CLI resolveAgentId 保持一致,未显式配置时用目录名兜底。
|
|
139
|
+
const config: DowncityConfig = {
|
|
140
|
+
...candidate,
|
|
141
|
+
id: String(candidate.id || "").trim() || normalizeDefaultAgentId(projectRoot),
|
|
142
|
+
version: String(candidate.version || "").trim() || "1.0.0",
|
|
143
|
+
};
|
|
131
144
|
assertProjectExecutionTarget(config);
|
|
132
145
|
return config;
|
|
133
146
|
}
|
package/src/rpc/Client.ts
CHANGED
|
@@ -29,6 +29,7 @@ import type {
|
|
|
29
29
|
} from "@/plugin/types/Plugin.js";
|
|
30
30
|
import type { AgentSessionEvent } from "@/types/sdk/AgentSessionEvent.js";
|
|
31
31
|
import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
|
|
32
|
+
import type { ControlSessionExecuteAttachmentInput } from "@/runtime/server/http/control/types/ControlSessionExecute.js";
|
|
32
33
|
|
|
33
34
|
type RpcClientRequest =
|
|
34
35
|
| {
|
|
@@ -97,6 +98,36 @@ type RpcClientRequest =
|
|
|
97
98
|
id: string;
|
|
98
99
|
method: "internal.status.get";
|
|
99
100
|
}
|
|
101
|
+
| {
|
|
102
|
+
id: string;
|
|
103
|
+
method: "internal.sessions.execute";
|
|
104
|
+
params: {
|
|
105
|
+
sessionId: string;
|
|
106
|
+
instructions: string;
|
|
107
|
+
attachments?: ControlSessionExecuteAttachmentInput[];
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
| {
|
|
111
|
+
id: string;
|
|
112
|
+
method: "internal.sessions.clear_messages";
|
|
113
|
+
params: {
|
|
114
|
+
sessionId: string;
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
| {
|
|
118
|
+
id: string;
|
|
119
|
+
method: "internal.sessions.clear_chat_history";
|
|
120
|
+
params: {
|
|
121
|
+
sessionId: string;
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
| {
|
|
125
|
+
id: string;
|
|
126
|
+
method: "internal.sessions.resolve_system_prompt";
|
|
127
|
+
params: {
|
|
128
|
+
sessionId: string;
|
|
129
|
+
};
|
|
130
|
+
}
|
|
100
131
|
| {
|
|
101
132
|
id: string;
|
|
102
133
|
method: "internal.plugins.catalog";
|
|
@@ -188,6 +219,60 @@ export interface RpcSessionSubscription {
|
|
|
188
219
|
unsubscribe(): Promise<void>;
|
|
189
220
|
}
|
|
190
221
|
|
|
222
|
+
/**
|
|
223
|
+
* RPC system prompt 分段条目。
|
|
224
|
+
*/
|
|
225
|
+
export interface RpcSystemPromptSectionItem {
|
|
226
|
+
/** 消息序号。 */
|
|
227
|
+
index: number;
|
|
228
|
+
/** system message 文本内容。 */
|
|
229
|
+
content: string;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* RPC system prompt 分段。
|
|
234
|
+
*/
|
|
235
|
+
export interface RpcSystemPromptSection {
|
|
236
|
+
/** 分段稳定 key。 */
|
|
237
|
+
key: string;
|
|
238
|
+
/** 分段展示标题。 */
|
|
239
|
+
title: string;
|
|
240
|
+
/** 分段内消息条目。 */
|
|
241
|
+
items: RpcSystemPromptSectionItem[];
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* RPC system prompt 响应。
|
|
246
|
+
*/
|
|
247
|
+
export interface RpcSystemPromptPayload {
|
|
248
|
+
/** 请求是否成功。 */
|
|
249
|
+
success?: boolean;
|
|
250
|
+
/** 当前 session id。 */
|
|
251
|
+
sessionId: string;
|
|
252
|
+
/** system message 总数。 */
|
|
253
|
+
totalMessages: number;
|
|
254
|
+
/** system message 总字符数。 */
|
|
255
|
+
totalChars: number;
|
|
256
|
+
/** system message 分段。 */
|
|
257
|
+
sections: RpcSystemPromptSection[];
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* RPC session execute 响应。
|
|
262
|
+
*/
|
|
263
|
+
export interface RpcSessionExecuteResult {
|
|
264
|
+
/** 执行是否成功。 */
|
|
265
|
+
success: boolean;
|
|
266
|
+
/** 失败错误信息。 */
|
|
267
|
+
error?: string;
|
|
268
|
+
/** assistant 原始消息。 */
|
|
269
|
+
assistantMessage?: unknown;
|
|
270
|
+
/** 用户可见文本。 */
|
|
271
|
+
userVisible: string;
|
|
272
|
+
/** 是否进入队列。 */
|
|
273
|
+
queued: boolean;
|
|
274
|
+
}
|
|
275
|
+
|
|
191
276
|
/**
|
|
192
277
|
* RPC Client。
|
|
193
278
|
*/
|
|
@@ -353,6 +438,69 @@ export class RpcClient {
|
|
|
353
438
|
});
|
|
354
439
|
}
|
|
355
440
|
|
|
441
|
+
/**
|
|
442
|
+
* 在 Agent runtime 内执行一轮 session 指令。
|
|
443
|
+
*/
|
|
444
|
+
async execute_internal_session(params: {
|
|
445
|
+
session_id: string;
|
|
446
|
+
instructions: string;
|
|
447
|
+
attachments?: ControlSessionExecuteAttachmentInput[];
|
|
448
|
+
}): Promise<{ sessionId: string; result: RpcSessionExecuteResult }> {
|
|
449
|
+
return await this.request<{
|
|
450
|
+
sessionId: string;
|
|
451
|
+
result: RpcSessionExecuteResult;
|
|
452
|
+
}>({
|
|
453
|
+
method: "internal.sessions.execute",
|
|
454
|
+
params: {
|
|
455
|
+
sessionId: params.session_id,
|
|
456
|
+
instructions: params.instructions,
|
|
457
|
+
...(params.attachments !== undefined ? { attachments: params.attachments } : {}),
|
|
458
|
+
},
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* 清空 Agent runtime 内指定 session 的消息。
|
|
464
|
+
*/
|
|
465
|
+
async clear_internal_session_messages(
|
|
466
|
+
session_id: string,
|
|
467
|
+
): Promise<{ sessionId: string; cleared: boolean }> {
|
|
468
|
+
return await this.request<{ sessionId: string; cleared: boolean }>({
|
|
469
|
+
method: "internal.sessions.clear_messages",
|
|
470
|
+
params: {
|
|
471
|
+
sessionId: session_id,
|
|
472
|
+
},
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* 清空 Agent runtime 内指定 session 的 chat history。
|
|
478
|
+
*/
|
|
479
|
+
async clear_internal_chat_history(
|
|
480
|
+
session_id: string,
|
|
481
|
+
): Promise<{ sessionId: string; cleared: boolean }> {
|
|
482
|
+
return await this.request<{ sessionId: string; cleared: boolean }>({
|
|
483
|
+
method: "internal.sessions.clear_chat_history",
|
|
484
|
+
params: {
|
|
485
|
+
sessionId: session_id,
|
|
486
|
+
},
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* 解析 Agent runtime 内指定 session 的 system prompt。
|
|
492
|
+
*/
|
|
493
|
+
async resolve_internal_system_prompt(
|
|
494
|
+
session_id: string,
|
|
495
|
+
): Promise<RpcSystemPromptPayload> {
|
|
496
|
+
return await this.request<RpcSystemPromptPayload>({
|
|
497
|
+
method: "internal.sessions.resolve_system_prompt",
|
|
498
|
+
params: {
|
|
499
|
+
sessionId: session_id,
|
|
500
|
+
},
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
|
|
356
504
|
/**
|
|
357
505
|
* 列出 Agent runtime 注册的 plugin catalog。
|
|
358
506
|
*/
|
package/src/rpc/Server.ts
CHANGED
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import net from "node:net";
|
|
11
|
+
import fs from "fs-extra";
|
|
12
|
+
import { dirname } from "node:path";
|
|
13
|
+
import type { SystemModelMessage } from "ai";
|
|
11
14
|
import type {
|
|
12
15
|
AgentListSessionsInput,
|
|
13
16
|
AgentSessionCollection,
|
|
@@ -15,14 +18,22 @@ import type {
|
|
|
15
18
|
import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
|
|
16
19
|
import type { AgentSessionEvent } from "@/types/sdk/AgentSessionEvent.js";
|
|
17
20
|
import type { AgentContext } from "@/types/runtime/agent/AgentContext.js";
|
|
21
|
+
import type { AgentRuntime } from "@/types/runtime/agent/AgentRuntime.js";
|
|
18
22
|
import type { JsonValue } from "@/types/common/Json.js";
|
|
19
23
|
import type { PluginStateControlAction } from "@/plugin/types/Plugin.js";
|
|
24
|
+
import type { ControlSessionExecuteAttachmentInput } from "@/runtime/server/http/control/types/ControlSessionExecute.js";
|
|
25
|
+
import {
|
|
26
|
+
getDowncityChatHistoryPath,
|
|
27
|
+
getDowncitySessionMessagesPath,
|
|
28
|
+
} from "@/config/Paths.js";
|
|
29
|
+
import { resolveSessionSystemMessages } from "@/executor/composer/system/default/SystemDomain.js";
|
|
20
30
|
import {
|
|
21
31
|
controlPluginState,
|
|
22
32
|
listPluginStates,
|
|
23
33
|
} from "@/plugin/core/PluginStateController.js";
|
|
24
34
|
import { parsePluginCommandRequestBody } from "@/plugin/core/PluginCommandRequest.js";
|
|
25
35
|
import { runPluginCommand } from "@/plugin/core/PluginActionRunner.js";
|
|
36
|
+
import { executeBySessionId } from "@/runtime/server/http/control/ExecuteBySession.js";
|
|
26
37
|
|
|
27
38
|
type RpcSessionRequest =
|
|
28
39
|
| {
|
|
@@ -98,6 +109,36 @@ type RpcSessionRequest =
|
|
|
98
109
|
id: string;
|
|
99
110
|
method: "internal.status.get";
|
|
100
111
|
}
|
|
112
|
+
| {
|
|
113
|
+
id: string;
|
|
114
|
+
method: "internal.sessions.execute";
|
|
115
|
+
params: {
|
|
116
|
+
sessionId: string;
|
|
117
|
+
instructions: string;
|
|
118
|
+
attachments?: ControlSessionExecuteAttachmentInput[];
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
| {
|
|
122
|
+
id: string;
|
|
123
|
+
method: "internal.sessions.clear_messages";
|
|
124
|
+
params: {
|
|
125
|
+
sessionId: string;
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
| {
|
|
129
|
+
id: string;
|
|
130
|
+
method: "internal.sessions.clear_chat_history";
|
|
131
|
+
params: {
|
|
132
|
+
sessionId: string;
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
| {
|
|
136
|
+
id: string;
|
|
137
|
+
method: "internal.sessions.resolve_system_prompt";
|
|
138
|
+
params: {
|
|
139
|
+
sessionId: string;
|
|
140
|
+
};
|
|
141
|
+
}
|
|
101
142
|
| {
|
|
102
143
|
id: string;
|
|
103
144
|
method: "internal.plugins.catalog";
|
|
@@ -176,6 +217,8 @@ export interface RpcServerStartOptions {
|
|
|
176
217
|
sessionCollection: AgentSessionCollection;
|
|
177
218
|
/** Agent 上下文访问口。 */
|
|
178
219
|
getAgentContext?: () => AgentContext;
|
|
220
|
+
/** Agent 运行态访问口。 */
|
|
221
|
+
getAgentRuntime?: () => AgentRuntime;
|
|
179
222
|
}
|
|
180
223
|
|
|
181
224
|
/**
|
|
@@ -304,6 +347,67 @@ export async function startRpcServer(
|
|
|
304
347
|
writeSuccess(request.id, { status: "ok" });
|
|
305
348
|
return;
|
|
306
349
|
}
|
|
350
|
+
case "internal.sessions.execute": {
|
|
351
|
+
const runtime = requireAgentRuntime(options);
|
|
352
|
+
const context = requireAgentContext(options);
|
|
353
|
+
const result = await executeBySessionId({
|
|
354
|
+
agentState: runtime,
|
|
355
|
+
executionContext: context,
|
|
356
|
+
sessionId: request.params.sessionId,
|
|
357
|
+
instructions: request.params.instructions,
|
|
358
|
+
attachments: request.params.attachments,
|
|
359
|
+
});
|
|
360
|
+
writeSuccess(request.id, {
|
|
361
|
+
sessionId: request.params.sessionId,
|
|
362
|
+
result,
|
|
363
|
+
});
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
case "internal.sessions.clear_messages": {
|
|
367
|
+
const runtime = requireAgentRuntime(options);
|
|
368
|
+
const sessionId = String(request.params.sessionId || "").trim();
|
|
369
|
+
if (!sessionId) throw new Error("Missing sessionId");
|
|
370
|
+
const messagesPath = getDowncitySessionMessagesPath(
|
|
371
|
+
runtime.rootPath,
|
|
372
|
+
runtime.paths.agentId,
|
|
373
|
+
sessionId,
|
|
374
|
+
);
|
|
375
|
+
await fs.remove(dirname(messagesPath));
|
|
376
|
+
runtime.getSession(sessionId).clearExecutor();
|
|
377
|
+
writeSuccess(request.id, {
|
|
378
|
+
sessionId,
|
|
379
|
+
cleared: true,
|
|
380
|
+
});
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
case "internal.sessions.clear_chat_history": {
|
|
384
|
+
const runtime = requireAgentRuntime(options);
|
|
385
|
+
const sessionId = String(request.params.sessionId || "").trim();
|
|
386
|
+
if (!sessionId) throw new Error("Missing sessionId");
|
|
387
|
+
await fs.remove(getDowncityChatHistoryPath(runtime.rootPath, sessionId));
|
|
388
|
+
writeSuccess(request.id, {
|
|
389
|
+
sessionId,
|
|
390
|
+
cleared: true,
|
|
391
|
+
});
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
case "internal.sessions.resolve_system_prompt": {
|
|
395
|
+
const runtime = requireAgentRuntime(options);
|
|
396
|
+
const context = requireAgentContext(options);
|
|
397
|
+
const sessionId = String(request.params.sessionId || "").trim() || "consoleui-chat-main";
|
|
398
|
+
const systemMessages = await resolveSessionSystemMessages({
|
|
399
|
+
projectRoot: runtime.rootPath,
|
|
400
|
+
sessionId,
|
|
401
|
+
profile: "chat",
|
|
402
|
+
staticSystemPrompts: runtime.systems,
|
|
403
|
+
context,
|
|
404
|
+
});
|
|
405
|
+
writeSuccess(request.id, {
|
|
406
|
+
sessionId,
|
|
407
|
+
...toSystemPromptPayload(systemMessages),
|
|
408
|
+
});
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
307
411
|
case "internal.plugins.catalog": {
|
|
308
412
|
const context = requireAgentContext(options);
|
|
309
413
|
writeSuccess(request.id, {
|
|
@@ -439,3 +543,65 @@ function requireAgentContext(options: RpcServerStartOptions): AgentContext {
|
|
|
439
543
|
}
|
|
440
544
|
return context;
|
|
441
545
|
}
|
|
546
|
+
|
|
547
|
+
function requireAgentRuntime(options: RpcServerStartOptions): AgentRuntime {
|
|
548
|
+
const runtime = options.getAgentRuntime?.();
|
|
549
|
+
if (!runtime) {
|
|
550
|
+
throw new Error("Agent RPC server was started without AgentRuntime");
|
|
551
|
+
}
|
|
552
|
+
return runtime;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
function normalizeSystemText(input: string | null | undefined): string {
|
|
556
|
+
return String(input || "").trim();
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
function toSystemMessageText(message: SystemModelMessage): string {
|
|
560
|
+
const content = message.content as unknown;
|
|
561
|
+
if (typeof content === "string") return normalizeSystemText(content);
|
|
562
|
+
if (!Array.isArray(content)) return "";
|
|
563
|
+
const parts = content as Array<{ text?: unknown }>;
|
|
564
|
+
const texts: string[] = [];
|
|
565
|
+
for (const part of parts) {
|
|
566
|
+
if (!part || typeof part !== "object") continue;
|
|
567
|
+
const text = normalizeSystemText(String(part.text || ""));
|
|
568
|
+
if (!text) continue;
|
|
569
|
+
texts.push(text);
|
|
570
|
+
}
|
|
571
|
+
return texts.join("\n").trim();
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* 把 system messages 转成 Console/Town 可直接渲染的结构。
|
|
576
|
+
*/
|
|
577
|
+
function toSystemPromptPayload(messages: SystemModelMessage[]): {
|
|
578
|
+
sections: Array<{
|
|
579
|
+
key: string;
|
|
580
|
+
title: string;
|
|
581
|
+
items: Array<{ index: number; content: string }>;
|
|
582
|
+
}>;
|
|
583
|
+
totalMessages: number;
|
|
584
|
+
totalChars: number;
|
|
585
|
+
} {
|
|
586
|
+
const items = messages
|
|
587
|
+
.map((message, index) => ({
|
|
588
|
+
index: index + 1,
|
|
589
|
+
content: toSystemMessageText(message),
|
|
590
|
+
}))
|
|
591
|
+
.filter((item) => item.content);
|
|
592
|
+
const totalChars = items.reduce(
|
|
593
|
+
(acc, item) => acc + String(item.content || "").length,
|
|
594
|
+
0,
|
|
595
|
+
);
|
|
596
|
+
return {
|
|
597
|
+
sections: [
|
|
598
|
+
{
|
|
599
|
+
key: "resolved",
|
|
600
|
+
title: "Resolved System Messages",
|
|
601
|
+
items,
|
|
602
|
+
},
|
|
603
|
+
],
|
|
604
|
+
totalMessages: items.length,
|
|
605
|
+
totalChars,
|
|
606
|
+
};
|
|
607
|
+
}
|