@downcity/agent 1.1.69 → 1.1.71

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/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,28 @@ 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";
23
+ import type { JsonObject } from "@/types/common/Json.js";
19
24
  import type { PluginStateControlAction } from "@/plugin/types/Plugin.js";
25
+ import type { ControlSessionExecuteAttachmentInput } from "@/runtime/server/http/control/types/ControlSessionExecute.js";
26
+ import {
27
+ readAuthControlPayload,
28
+ setAuthControlUserRole,
29
+ writeAuthControlConfig,
30
+ } from "@/runtime/server/http/control/AuthControlService.js";
31
+ import {
32
+ getDowncityChatHistoryPath,
33
+ getDowncitySessionMessagesPath,
34
+ } from "@/config/Paths.js";
35
+ import { resolveSessionSystemMessages } from "@/executor/composer/system/default/SystemDomain.js";
20
36
  import {
21
37
  controlPluginState,
22
38
  listPluginStates,
23
39
  } from "@/plugin/core/PluginStateController.js";
24
40
  import { parsePluginCommandRequestBody } from "@/plugin/core/PluginCommandRequest.js";
25
41
  import { runPluginCommand } from "@/plugin/core/PluginActionRunner.js";
42
+ import { executeBySessionId } from "@/runtime/server/http/control/ExecuteBySession.js";
26
43
 
27
44
  type RpcSessionRequest =
28
45
  | {
@@ -98,6 +115,36 @@ type RpcSessionRequest =
98
115
  id: string;
99
116
  method: "internal.status.get";
100
117
  }
118
+ | {
119
+ id: string;
120
+ method: "internal.sessions.execute";
121
+ params: {
122
+ sessionId: string;
123
+ instructions: string;
124
+ attachments?: ControlSessionExecuteAttachmentInput[];
125
+ };
126
+ }
127
+ | {
128
+ id: string;
129
+ method: "internal.sessions.clear_messages";
130
+ params: {
131
+ sessionId: string;
132
+ };
133
+ }
134
+ | {
135
+ id: string;
136
+ method: "internal.sessions.clear_chat_history";
137
+ params: {
138
+ sessionId: string;
139
+ };
140
+ }
141
+ | {
142
+ id: string;
143
+ method: "internal.sessions.resolve_system_prompt";
144
+ params: {
145
+ sessionId: string;
146
+ };
147
+ }
101
148
  | {
102
149
  id: string;
103
150
  method: "internal.plugins.catalog";
@@ -139,6 +186,27 @@ type RpcSessionRequest =
139
186
  actionName: string;
140
187
  payload?: JsonValue;
141
188
  };
189
+ }
190
+ | {
191
+ id: string;
192
+ method: "internal.authorization.get";
193
+ }
194
+ | {
195
+ id: string;
196
+ method: "internal.authorization.config";
197
+ params: {
198
+ config: JsonObject;
199
+ };
200
+ }
201
+ | {
202
+ id: string;
203
+ method: "internal.authorization.action";
204
+ params: {
205
+ action: string;
206
+ channel: string;
207
+ userId?: string;
208
+ roleId?: string;
209
+ };
142
210
  };
143
211
 
144
212
  type RpcSuccessFrame = {
@@ -176,6 +244,8 @@ export interface RpcServerStartOptions {
176
244
  sessionCollection: AgentSessionCollection;
177
245
  /** Agent 上下文访问口。 */
178
246
  getAgentContext?: () => AgentContext;
247
+ /** Agent 运行态访问口。 */
248
+ getAgentRuntime?: () => AgentRuntime;
179
249
  }
180
250
 
181
251
  /**
@@ -304,6 +374,67 @@ export async function startRpcServer(
304
374
  writeSuccess(request.id, { status: "ok" });
305
375
  return;
306
376
  }
377
+ case "internal.sessions.execute": {
378
+ const runtime = requireAgentRuntime(options);
379
+ const context = requireAgentContext(options);
380
+ const result = await executeBySessionId({
381
+ agentState: runtime,
382
+ executionContext: context,
383
+ sessionId: request.params.sessionId,
384
+ instructions: request.params.instructions,
385
+ attachments: request.params.attachments,
386
+ });
387
+ writeSuccess(request.id, {
388
+ sessionId: request.params.sessionId,
389
+ result,
390
+ });
391
+ return;
392
+ }
393
+ case "internal.sessions.clear_messages": {
394
+ const runtime = requireAgentRuntime(options);
395
+ const sessionId = String(request.params.sessionId || "").trim();
396
+ if (!sessionId) throw new Error("Missing sessionId");
397
+ const messagesPath = getDowncitySessionMessagesPath(
398
+ runtime.rootPath,
399
+ runtime.paths.agentId,
400
+ sessionId,
401
+ );
402
+ await fs.remove(dirname(messagesPath));
403
+ runtime.getSession(sessionId).clearExecutor();
404
+ writeSuccess(request.id, {
405
+ sessionId,
406
+ cleared: true,
407
+ });
408
+ return;
409
+ }
410
+ case "internal.sessions.clear_chat_history": {
411
+ const runtime = requireAgentRuntime(options);
412
+ const sessionId = String(request.params.sessionId || "").trim();
413
+ if (!sessionId) throw new Error("Missing sessionId");
414
+ await fs.remove(getDowncityChatHistoryPath(runtime.rootPath, sessionId));
415
+ writeSuccess(request.id, {
416
+ sessionId,
417
+ cleared: true,
418
+ });
419
+ return;
420
+ }
421
+ case "internal.sessions.resolve_system_prompt": {
422
+ const runtime = requireAgentRuntime(options);
423
+ const context = requireAgentContext(options);
424
+ const sessionId = String(request.params.sessionId || "").trim() || "consoleui-chat-main";
425
+ const systemMessages = await resolveSessionSystemMessages({
426
+ projectRoot: runtime.rootPath,
427
+ sessionId,
428
+ profile: "chat",
429
+ staticSystemPrompts: runtime.systems,
430
+ context,
431
+ });
432
+ writeSuccess(request.id, {
433
+ sessionId,
434
+ ...toSystemPromptPayload(systemMessages),
435
+ });
436
+ return;
437
+ }
307
438
  case "internal.plugins.catalog": {
308
439
  const context = requireAgentContext(options);
309
440
  writeSuccess(request.id, {
@@ -366,6 +497,41 @@ export async function startRpcServer(
366
497
  });
367
498
  return;
368
499
  }
500
+ case "internal.authorization.get": {
501
+ const context = requireAgentContext(options);
502
+ writeSuccess(request.id, await readAuthControlPayload(context));
503
+ return;
504
+ }
505
+ case "internal.authorization.config": {
506
+ const context = requireAgentContext(options);
507
+ writeSuccess(
508
+ request.id,
509
+ await writeAuthControlConfig({
510
+ context,
511
+ config: request.params.config,
512
+ }),
513
+ );
514
+ return;
515
+ }
516
+ case "internal.authorization.action": {
517
+ const context = requireAgentContext(options);
518
+ const action = String(request.params.action || "").trim();
519
+ if (action !== "setUserRole") {
520
+ throw new Error(`Unsupported authorization action: ${action}`);
521
+ }
522
+ writeSuccess(
523
+ request.id,
524
+ await setAuthControlUserRole({
525
+ context,
526
+ input: {
527
+ channel: request.params.channel,
528
+ userId: String(request.params.userId || "").trim(),
529
+ roleId: String(request.params.roleId || "").trim(),
530
+ },
531
+ }),
532
+ );
533
+ return;
534
+ }
369
535
  }
370
536
  } catch (error) {
371
537
  writeError(request.id, error);
@@ -439,3 +605,65 @@ function requireAgentContext(options: RpcServerStartOptions): AgentContext {
439
605
  }
440
606
  return context;
441
607
  }
608
+
609
+ function requireAgentRuntime(options: RpcServerStartOptions): AgentRuntime {
610
+ const runtime = options.getAgentRuntime?.();
611
+ if (!runtime) {
612
+ throw new Error("Agent RPC server was started without AgentRuntime");
613
+ }
614
+ return runtime;
615
+ }
616
+
617
+ function normalizeSystemText(input: string | null | undefined): string {
618
+ return String(input || "").trim();
619
+ }
620
+
621
+ function toSystemMessageText(message: SystemModelMessage): string {
622
+ const content = message.content as unknown;
623
+ if (typeof content === "string") return normalizeSystemText(content);
624
+ if (!Array.isArray(content)) return "";
625
+ const parts = content as Array<{ text?: unknown }>;
626
+ const texts: string[] = [];
627
+ for (const part of parts) {
628
+ if (!part || typeof part !== "object") continue;
629
+ const text = normalizeSystemText(String(part.text || ""));
630
+ if (!text) continue;
631
+ texts.push(text);
632
+ }
633
+ return texts.join("\n").trim();
634
+ }
635
+
636
+ /**
637
+ * 把 system messages 转成 Console/Town 可直接渲染的结构。
638
+ */
639
+ function toSystemPromptPayload(messages: SystemModelMessage[]): {
640
+ sections: Array<{
641
+ key: string;
642
+ title: string;
643
+ items: Array<{ index: number; content: string }>;
644
+ }>;
645
+ totalMessages: number;
646
+ totalChars: number;
647
+ } {
648
+ const items = messages
649
+ .map((message, index) => ({
650
+ index: index + 1,
651
+ content: toSystemMessageText(message),
652
+ }))
653
+ .filter((item) => item.content);
654
+ const totalChars = items.reduce(
655
+ (acc, item) => acc + String(item.content || "").length,
656
+ 0,
657
+ );
658
+ return {
659
+ sections: [
660
+ {
661
+ key: "resolved",
662
+ title: "Resolved System Messages",
663
+ items,
664
+ },
665
+ ],
666
+ totalMessages: items.length,
667
+ totalChars,
668
+ };
669
+ }
@@ -14,9 +14,9 @@ import type { AuthControlPayload } from "@/runtime/server/http/control/types/Aut
14
14
  const AUTH_PLUGIN_NAME = "auth";
15
15
  const AUTH_ACTIONS = {
16
16
  snapshot: "snapshot",
17
- readConfig: "readConfig",
18
- writeConfig: "writeConfig",
19
- setUserRole: "setUserRole",
17
+ readConfig: "read-config",
18
+ writeConfig: "write-config",
19
+ setUserRole: "set-user-role",
20
20
  } as const;
21
21
  const CHAT_AUTHORIZATION_CATALOG: JsonObject = {
22
22
  channels: ["telegram", "feishu", "qq"],