@downcity/city 1.1.24 → 1.1.32

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.
Files changed (192) hide show
  1. package/README.md +5 -11
  2. package/bin/cli/Index.d.ts +1 -1
  3. package/bin/cli/Index.js +4 -6
  4. package/bin/cli/Index.js.map +1 -1
  5. package/bin/cli/agent/AgentChat.js +1 -1
  6. package/bin/cli/agent/AgentChat.js.map +1 -1
  7. package/bin/cli/agent/AgentHistory.d.ts.map +1 -1
  8. package/bin/cli/agent/AgentHistory.js +2 -1
  9. package/bin/cli/agent/AgentHistory.js.map +1 -1
  10. package/bin/cli/agent/AgentManager.js +3 -3
  11. package/bin/cli/agent/AgentManager.js.map +1 -1
  12. package/bin/cli/agent/Init.js +6 -6
  13. package/bin/cli/agent/Init.js.map +1 -1
  14. package/bin/cli/agent/Restart.js +1 -1
  15. package/bin/cli/agent/Restart.js.map +1 -1
  16. package/bin/cli/agent/Run.d.ts.map +1 -1
  17. package/bin/cli/agent/Run.js +6 -7
  18. package/bin/cli/agent/Run.js.map +1 -1
  19. package/bin/cli/agent/Start.js +1 -1
  20. package/bin/cli/agent/Start.js.map +1 -1
  21. package/bin/cli/control-plane/ControlPlaneCommand.d.ts.map +1 -1
  22. package/bin/cli/control-plane/ControlPlaneCommand.js +19 -1
  23. package/bin/cli/control-plane/ControlPlaneCommand.js.map +1 -1
  24. package/bin/cli/control-plane/ControlPlanePublicManager.d.ts +17 -0
  25. package/bin/cli/control-plane/ControlPlanePublicManager.d.ts.map +1 -0
  26. package/bin/cli/control-plane/ControlPlanePublicManager.js +229 -0
  27. package/bin/cli/control-plane/ControlPlanePublicManager.js.map +1 -0
  28. package/bin/cli/control-plane/ControlPlanePublicMode.d.ts +53 -0
  29. package/bin/cli/control-plane/ControlPlanePublicMode.d.ts.map +1 -0
  30. package/bin/cli/control-plane/ControlPlanePublicMode.js +106 -0
  31. package/bin/cli/control-plane/ControlPlanePublicMode.js.map +1 -0
  32. package/bin/cli/control-plane/ControlPlaneRuntime.d.ts.map +1 -1
  33. package/bin/cli/control-plane/ControlPlaneRuntime.js +8 -6
  34. package/bin/cli/control-plane/ControlPlaneRuntime.js.map +1 -1
  35. package/bin/cli/control-plane/ControlPlaneStatus.d.ts.map +1 -1
  36. package/bin/cli/control-plane/ControlPlaneStatus.js +22 -8
  37. package/bin/cli/control-plane/ControlPlaneStatus.js.map +1 -1
  38. package/bin/cli/model/ModelManageCommand.d.ts.map +1 -1
  39. package/bin/cli/model/ModelManageCommand.js +22 -18
  40. package/bin/cli/model/ModelManageCommand.js.map +1 -1
  41. package/bin/cli/model/ModelManager.d.ts +1 -1
  42. package/bin/cli/model/ModelManager.d.ts.map +1 -1
  43. package/bin/cli/model/ModelManager.js +378 -76
  44. package/bin/cli/model/ModelManager.js.map +1 -1
  45. package/bin/cli/model/ModelManagerTypes.d.ts +97 -3
  46. package/bin/cli/model/ModelManagerTypes.d.ts.map +1 -1
  47. package/bin/cli/model/ModelSupport.d.ts +1 -1
  48. package/bin/cli/model/ModelSupport.d.ts.map +1 -1
  49. package/bin/cli/model/ModelSupport.js +1 -1
  50. package/bin/cli/model/ModelSupport.js.map +1 -1
  51. package/bin/cli/shared/Chat.d.ts +1 -1
  52. package/bin/cli/shared/Chat.js +2 -2
  53. package/bin/cli/shared/Chat.js.map +1 -1
  54. package/bin/cli/shared/ChatManager.d.ts +1 -1
  55. package/bin/cli/shared/ChatManager.js +27 -27
  56. package/bin/cli/shared/ChatManager.js.map +1 -1
  57. package/bin/cli/shared/Config.js +1 -1
  58. package/bin/cli/shared/Config.js.map +1 -1
  59. package/bin/cli/shared/ManagedPluginActionCommands.d.ts +14 -0
  60. package/bin/cli/shared/ManagedPluginActionCommands.d.ts.map +1 -0
  61. package/bin/cli/{service/ServiceActionCommands.js → shared/ManagedPluginActionCommands.js} +60 -60
  62. package/bin/cli/shared/ManagedPluginActionCommands.js.map +1 -0
  63. package/bin/cli/shared/ManagedPluginRemote.d.ts +30 -0
  64. package/bin/cli/shared/ManagedPluginRemote.d.ts.map +1 -0
  65. package/bin/cli/{service/ServiceCommandRemote.js → shared/ManagedPluginRemote.js} +34 -34
  66. package/bin/cli/shared/ManagedPluginRemote.js.map +1 -0
  67. package/bin/cli/shared/PluginScheduleCommand.d.ts +36 -0
  68. package/bin/cli/shared/PluginScheduleCommand.d.ts.map +1 -0
  69. package/bin/cli/{service/ServiceScheduleCommand.js → shared/PluginScheduleCommand.js} +41 -41
  70. package/bin/cli/shared/PluginScheduleCommand.js.map +1 -0
  71. package/bin/cli/{service/ServiceCommandSupport.d.ts → shared/PluginTargetSupport.d.ts} +12 -12
  72. package/bin/cli/shared/PluginTargetSupport.d.ts.map +1 -0
  73. package/bin/cli/{service/ServiceCommandSupport.js → shared/PluginTargetSupport.js} +14 -14
  74. package/bin/cli/shared/PluginTargetSupport.js.map +1 -0
  75. package/bin/cli/shared/Plugins.d.ts.map +1 -1
  76. package/bin/cli/shared/Plugins.js +159 -30
  77. package/bin/cli/shared/Plugins.js.map +1 -1
  78. package/bin/cli/shared/PortHints.js +1 -1
  79. package/bin/cli/shared/PortHints.js.map +1 -1
  80. package/bin/config/DowncitySchema.d.ts.map +1 -1
  81. package/bin/config/DowncitySchema.js +2 -8
  82. package/bin/config/DowncitySchema.js.map +1 -1
  83. package/bin/config/Paths.d.ts +12 -10
  84. package/bin/config/Paths.d.ts.map +1 -1
  85. package/bin/config/Paths.js +23 -17
  86. package/bin/config/Paths.js.map +1 -1
  87. package/bin/control/AgentStatusApiRoutes.js +30 -30
  88. package/bin/control/AgentStatusApiRoutes.js.map +1 -1
  89. package/bin/control/ChannelAccountApiRoutes.js +6 -6
  90. package/bin/control/ControlGateway.js +2 -2
  91. package/bin/control/ControlGateway.js.map +1 -1
  92. package/bin/control/ModelApiRoutes.d.ts +1 -1
  93. package/bin/control/ModelApiRoutes.d.ts.map +1 -1
  94. package/bin/control/ModelApiRoutes.js +1 -1
  95. package/bin/control/ModelApiRoutes.js.map +1 -1
  96. package/bin/control/ModelPoolService.d.ts +4 -121
  97. package/bin/control/ModelPoolService.d.ts.map +1 -1
  98. package/bin/control/ModelPoolService.js +4 -322
  99. package/bin/control/ModelPoolService.js.map +1 -1
  100. package/bin/control/PluginApiRoutes.js +5 -5
  101. package/bin/control/PluginApiRoutes.js.map +1 -1
  102. package/bin/control/gateway/AgentActions.d.ts.map +1 -1
  103. package/bin/control/gateway/AgentActions.js +18 -3
  104. package/bin/control/gateway/AgentActions.js.map +1 -1
  105. package/bin/control/gateway/AgentCatalog.js +2 -2
  106. package/bin/control/gateway/AgentCatalog.js.map +1 -1
  107. package/bin/control/instant/InstantApiRoutes.d.ts +3 -3
  108. package/bin/control/instant/InstantApiRoutes.d.ts.map +1 -1
  109. package/bin/control/instant/InstantApiRoutes.js +5 -5
  110. package/bin/control/instant/InstantApiRoutes.js.map +1 -1
  111. package/bin/control/instant/{InstantSessionService.d.ts → InstantSessionRunner.d.ts} +7 -7
  112. package/bin/control/instant/InstantSessionRunner.d.ts.map +1 -0
  113. package/bin/control/instant/{InstantSessionService.js → InstantSessionRunner.js} +4 -4
  114. package/bin/control/instant/InstantSessionRunner.js.map +1 -0
  115. package/bin/http/auth/RoutePolicy.js +7 -7
  116. package/bin/http/auth/RoutePolicy.js.map +1 -1
  117. package/bin/model/service/ModelPoolService.d.ts +145 -0
  118. package/bin/model/service/ModelPoolService.d.ts.map +1 -0
  119. package/bin/model/service/ModelPoolService.js +424 -0
  120. package/bin/model/service/ModelPoolService.js.map +1 -0
  121. package/bin/process/daemon/Api.d.ts +2 -2
  122. package/bin/process/daemon/Api.js +1 -1
  123. package/bin/process/registry/AgentHostRuntime.d.ts +1 -1
  124. package/bin/process/registry/AgentHostRuntime.d.ts.map +1 -1
  125. package/bin/process/registry/AgentHostRuntime.js +85 -4
  126. package/bin/process/registry/AgentHostRuntime.js.map +1 -1
  127. package/package.json +2 -2
  128. package/src/cli/Index.ts +4 -6
  129. package/src/cli/agent/AgentChat.ts +1 -1
  130. package/src/cli/agent/AgentHistory.ts +6 -1
  131. package/src/cli/agent/AgentManager.ts +3 -3
  132. package/src/cli/agent/Init.ts +6 -6
  133. package/src/cli/agent/Restart.ts +1 -1
  134. package/src/cli/agent/Run.ts +6 -7
  135. package/src/cli/agent/Start.ts +1 -1
  136. package/src/cli/control-plane/ControlPlaneCommand.ts +28 -1
  137. package/src/cli/control-plane/ControlPlanePublicManager.ts +280 -0
  138. package/src/cli/control-plane/ControlPlanePublicMode.ts +141 -0
  139. package/src/cli/control-plane/ControlPlaneRuntime.ts +8 -6
  140. package/src/cli/control-plane/ControlPlaneStatus.ts +22 -8
  141. package/src/cli/model/ModelManageCommand.ts +23 -19
  142. package/src/cli/model/ModelManager.ts +419 -76
  143. package/src/cli/model/ModelManagerTypes.ts +82 -0
  144. package/src/cli/model/ModelSupport.ts +1 -1
  145. package/src/cli/shared/Chat.ts +2 -2
  146. package/src/cli/shared/ChatManager.ts +27 -27
  147. package/src/cli/shared/Config.ts +1 -1
  148. package/src/cli/{service/ServiceActionCommands.ts → shared/ManagedPluginActionCommands.ts} +75 -75
  149. package/src/cli/{service/ServiceCommandRemote.ts → shared/ManagedPluginRemote.ts} +47 -47
  150. package/src/cli/{service/ServiceScheduleCommand.ts → shared/PluginScheduleCommand.ts} +49 -49
  151. package/src/cli/{service/ServiceCommandSupport.ts → shared/PluginTargetSupport.ts} +14 -14
  152. package/src/cli/shared/Plugins.ts +195 -35
  153. package/src/cli/shared/PortHints.ts +1 -1
  154. package/src/config/DowncitySchema.ts +2 -8
  155. package/src/config/Paths.ts +55 -14
  156. package/src/control/AgentStatusApiRoutes.ts +35 -35
  157. package/src/control/ChannelAccountApiRoutes.ts +6 -6
  158. package/src/control/ControlGateway.ts +2 -2
  159. package/src/control/ModelApiRoutes.ts +1 -1
  160. package/src/control/ModelPoolService.ts +4 -390
  161. package/src/control/PluginApiRoutes.ts +5 -5
  162. package/src/control/gateway/AgentActions.ts +20 -5
  163. package/src/control/gateway/AgentCatalog.ts +2 -2
  164. package/src/control/instant/InstantApiRoutes.ts +8 -8
  165. package/src/control/instant/{InstantSessionService.ts → InstantSessionRunner.ts} +7 -7
  166. package/src/http/auth/RoutePolicy.ts +7 -7
  167. package/src/model/service/ModelPoolService.ts +525 -0
  168. package/src/process/daemon/Api.ts +2 -2
  169. package/src/process/registry/AgentHostRuntime.ts +95 -5
  170. package/bin/cli/service/ServiceActionCommands.d.ts +0 -14
  171. package/bin/cli/service/ServiceActionCommands.d.ts.map +0 -1
  172. package/bin/cli/service/ServiceActionCommands.js.map +0 -1
  173. package/bin/cli/service/ServiceCommandRemote.d.ts +0 -30
  174. package/bin/cli/service/ServiceCommandRemote.d.ts.map +0 -1
  175. package/bin/cli/service/ServiceCommandRemote.js.map +0 -1
  176. package/bin/cli/service/ServiceCommandSupport.d.ts.map +0 -1
  177. package/bin/cli/service/ServiceCommandSupport.js.map +0 -1
  178. package/bin/cli/service/ServiceScheduleCommand.d.ts +0 -36
  179. package/bin/cli/service/ServiceScheduleCommand.d.ts.map +0 -1
  180. package/bin/cli/service/ServiceScheduleCommand.js.map +0 -1
  181. package/bin/cli/service/Services.d.ts +0 -14
  182. package/bin/cli/service/Services.d.ts.map +0 -1
  183. package/bin/cli/service/Services.js +0 -154
  184. package/bin/cli/service/Services.js.map +0 -1
  185. package/bin/control/instant/InstantSessionService.d.ts.map +0 -1
  186. package/bin/control/instant/InstantSessionService.js.map +0 -1
  187. package/bin/process/registry/PluginRuntime.d.ts +0 -24
  188. package/bin/process/registry/PluginRuntime.d.ts.map +0 -1
  189. package/bin/process/registry/PluginRuntime.js +0 -31
  190. package/bin/process/registry/PluginRuntime.js.map +0 -1
  191. package/src/cli/service/Services.ts +0 -189
  192. package/src/process/registry/PluginRuntime.ts +0 -42
@@ -3,35 +3,117 @@
3
3
  */
4
4
 
5
5
  export type ModelManagerRootAction =
6
+ /**
7
+ * 进入 provider 管理列表。
8
+ */
6
9
  | "providers"
10
+ /**
11
+ * 进入 model 管理列表。
12
+ */
7
13
  | "models"
14
+ /**
15
+ * 跳转到创建流程。
16
+ */
8
17
  | "create"
18
+ /**
19
+ * 退出 manager。
20
+ */
9
21
  | "exit";
10
22
 
11
23
  export type ModelManagerProviderAction =
24
+ /**
25
+ * 查看 provider 详情。
26
+ */
12
27
  | "details"
28
+ /**
29
+ * 编辑 provider 配置。
30
+ */
31
+ | "edit"
32
+ /**
33
+ * 测试 provider 并导入发现到的模型。
34
+ */
13
35
  | "discover"
36
+ /**
37
+ * 删除 provider。
38
+ */
39
+ | "remove"
40
+ /**
41
+ * 返回上一层。
42
+ */
14
43
  | "back";
15
44
 
16
45
  export type ModelManagerModelAction =
46
+ /**
47
+ * 查看 model 详情。
48
+ */
17
49
  | "details"
50
+ /**
51
+ * 编辑 model 配置。
52
+ */
53
+ | "edit"
54
+ /**
55
+ * 切换暂停状态。
56
+ */
18
57
  | "togglePause"
58
+ /**
59
+ * 测试 model 可调用性。
60
+ */
19
61
  | "test"
62
+ /**
63
+ * 绑定到项目。
64
+ */
20
65
  | "use"
66
+ /**
67
+ * 删除 model。
68
+ */
69
+ | "remove"
70
+ /**
71
+ * 返回上一层。
72
+ */
21
73
  | "back";
22
74
 
23
75
  export interface ModelManagerProviderSummary {
76
+ /**
77
+ * provider 在全局模型池中的唯一 ID。
78
+ */
24
79
  id: string;
80
+ /**
81
+ * provider 类型,例如 `openai`、`anthropic`。
82
+ */
25
83
  type: string;
84
+ /**
85
+ * provider 自定义 base URL;为空表示使用 SDK 默认地址。
86
+ */
26
87
  baseUrl?: string;
88
+ /**
89
+ * 当前引用该 provider 的模型数量。
90
+ */
27
91
  modelCount: number;
28
92
  }
29
93
 
30
94
  export interface ModelManagerModelSummary {
95
+ /**
96
+ * model 在全局模型池中的唯一 ID。
97
+ */
31
98
  id: string;
99
+ /**
100
+ * 当前 model 绑定的 provider ID。
101
+ */
32
102
  providerId: string;
103
+ /**
104
+ * 上游真实模型名。
105
+ */
33
106
  name: string;
107
+ /**
108
+ * 当前 model 是否已暂停。
109
+ */
34
110
  isPaused: boolean;
111
+ /**
112
+ * 可选的 temperature 覆写;为空表示使用上游默认值。
113
+ */
35
114
  temperature?: number;
115
+ /**
116
+ * 可选的 maxTokens 覆写;为空表示使用上游默认值。
117
+ */
36
118
  maxTokens?: number;
37
119
  }
@@ -181,7 +181,7 @@ export async function discoverProviderModels(params: {
181
181
  }
182
182
  }
183
183
 
184
- export { resolveProjectRoot } from "../service/ServiceCommandSupport.js";
184
+ export { resolveProjectRoot } from "../shared/PluginTargetSupport.js";
185
185
 
186
186
  /**
187
187
  * 设置项目 `downcity.json.execution.modelId`。
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - 这里先注册裸 `city chat` 的交互式入口。
6
- * - 具体 service actions/lifecycle 命令仍由 service 注册器补充到同一个命令组。
6
+ * - 具体 plugin runtime actions/lifecycle 命令仍由 plugin runtime 注册器补充到同一个命令组。
7
7
  */
8
8
 
9
9
  import type { Command } from "commander";
@@ -16,7 +16,7 @@ import { runInteractiveChatManager } from "./ChatManager.js";
16
16
  export function registerChatCommand(program: Command): void {
17
17
  const chat = program
18
18
  .command("chat")
19
- .description("管理 chat service(无参数时启动交互式管理器)")
19
+ .description("管理 chat plugin(无参数时启动交互式管理器)")
20
20
  .helpOption("--help", "display help for command")
21
21
  .action(async () => {
22
22
  if (process.stdin.isTTY === true && process.stdout.isTTY === true) {
@@ -2,7 +2,7 @@
2
2
  * `city chat` 交互式管理器。
3
3
  *
4
4
  * 关键点(中文)
5
- * - 裸 `city chat` 进入 chat service 管理,而不是只输出静态 help。
5
+ * - 裸 `city chat` 进入 chat plugin 管理,而不是只输出静态 help。
6
6
  * - chat channel account 属于 city 级配置,在这里通过“配置 channel”管理。
7
7
  * - agent 只绑定 channel account,不在 agent 流程中维护密钥。
8
8
  */
@@ -10,11 +10,11 @@
10
10
  import prompts from "prompts";
11
11
  import type { PromptObject } from "prompts";
12
12
  import {
13
- ChatChannelAccountService,
13
+ ChatChannelAccountManager,
14
14
  type ChatChannelAccountListItem,
15
15
  } from "@downcity/agent";
16
16
  import { emitCliBlock, emitCliList } from "./CliReporter.js";
17
- import { runServiceControlCommand } from "../service/ServiceCommandRemote.js";
17
+ import { runManagedPluginControlCommand } from "./ManagedPluginRemote.js";
18
18
  import type { StoredChannelAccountChannel } from "@downcity/agent";
19
19
  import type {
20
20
  ChatChannelAccountAction,
@@ -25,8 +25,8 @@ import { createAgentPlatformRuntime } from "@/process/registry/AgentHostRuntime.
25
25
 
26
26
  const CHAT_CHANNELS: StoredChannelAccountChannel[] = ["telegram", "feishu", "qq"];
27
27
 
28
- function createChannelAccountService(): ChatChannelAccountService {
29
- return new ChatChannelAccountService(createAgentPlatformRuntime());
28
+ function createChannelAccountManager(): ChatChannelAccountManager {
29
+ return new ChatChannelAccountManager(createAgentPlatformRuntime());
30
30
  }
31
31
 
32
32
  function isInteractiveTerminal(): boolean {
@@ -49,31 +49,31 @@ function formatCredentialSummary(account: ChatChannelAccountListItem): string {
49
49
  }
50
50
 
51
51
  async function promptRootAction(): Promise<ChatManagerRootAction | null> {
52
- const service = createChannelAccountService();
53
- const accounts = await service.list();
52
+ const manager = createChannelAccountManager();
53
+ const accounts = await manager.list();
54
54
  const response = (await prompts({
55
55
  type: "select",
56
56
  name: "action",
57
- message: "管理 chat service",
57
+ message: "管理 chat plugin",
58
58
  choices: [
59
59
  {
60
60
  title: "查看状态",
61
- description: "查看当前项目 chat service 运行状态",
61
+ description: "查看当前项目 chat plugin 运行状态",
62
62
  value: "status",
63
63
  },
64
64
  {
65
65
  title: "启动",
66
- description: "启动当前项目 chat service",
66
+ description: "启动当前项目 chat plugin",
67
67
  value: "start",
68
68
  },
69
69
  {
70
70
  title: "停止",
71
- description: "停止当前项目 chat service",
71
+ description: "停止当前项目 chat plugin",
72
72
  value: "stop",
73
73
  },
74
74
  {
75
75
  title: "重启",
76
- description: "重启当前项目 chat service",
76
+ description: "重启当前项目 chat plugin",
77
77
  value: "restart",
78
78
  },
79
79
  {
@@ -94,8 +94,8 @@ async function promptRootAction(): Promise<ChatManagerRootAction | null> {
94
94
  }
95
95
 
96
96
  async function promptChannelAccountAction(): Promise<ChatChannelAccountAction | null> {
97
- const service = createChannelAccountService();
98
- const accounts = await service.list();
97
+ const manager = createChannelAccountManager();
98
+ const accounts = await manager.list();
99
99
  const response = (await prompts({
100
100
  type: "select",
101
101
  name: "action",
@@ -128,7 +128,7 @@ async function promptChannelAccountAction(): Promise<ChatChannelAccountAction |
128
128
  },
129
129
  {
130
130
  title: "返回",
131
- description: "回到 chat service 菜单",
131
+ description: "回到 chat plugin 菜单",
132
132
  value: "back",
133
133
  },
134
134
  ],
@@ -139,8 +139,8 @@ async function promptChannelAccountAction(): Promise<ChatChannelAccountAction |
139
139
  }
140
140
 
141
141
  async function emitChannelAccountList(): Promise<void> {
142
- const service = createChannelAccountService();
143
- const { items } = await service.list();
142
+ const manager = createChannelAccountManager();
143
+ const { items } = await manager.list();
144
144
  if (items.length === 0) {
145
145
  emitCliBlock({
146
146
  tone: "info",
@@ -182,8 +182,8 @@ async function chooseChannel(): Promise<StoredChannelAccountChannel | null> {
182
182
  }
183
183
 
184
184
  async function chooseAccount(): Promise<ChatChannelAccountListItem | null> {
185
- const service = createChannelAccountService();
186
- const { items } = await service.list();
185
+ const manager = createChannelAccountManager();
186
+ const { items } = await manager.list();
187
187
  if (items.length === 0) {
188
188
  emitCliBlock({
189
189
  tone: "info",
@@ -296,8 +296,8 @@ async function addChannelAccount(): Promise<void> {
296
296
  initial: true,
297
297
  })) as { probe?: boolean };
298
298
 
299
- const service = createChannelAccountService();
300
- const result = await service.create({
299
+ const manager = createChannelAccountManager();
300
+ const result = await manager.create({
301
301
  channel,
302
302
  name,
303
303
  botToken: input.botToken,
@@ -324,8 +324,8 @@ async function editChannelAccount(): Promise<void> {
324
324
  channel: account.channel,
325
325
  current: account,
326
326
  });
327
- const service = createChannelAccountService();
328
- await service.upsert({
327
+ const manager = createChannelAccountManager();
328
+ await manager.upsert({
329
329
  id: account.id,
330
330
  channel: account.channel,
331
331
  name: String(input.name || account.name).trim(),
@@ -356,8 +356,8 @@ async function removeChannelAccount(): Promise<void> {
356
356
 
357
357
  if (response.remove !== true) return;
358
358
 
359
- const service = createChannelAccountService();
360
- service.remove(account.id);
359
+ const manager = createChannelAccountManager();
360
+ await manager.remove(account.id);
361
361
  emitCliBlock({
362
362
  tone: "success",
363
363
  title: "Channel account removed",
@@ -403,8 +403,8 @@ async function runChannelAccountManager(): Promise<void> {
403
403
  async function runChatLifecycleAction(
404
404
  action: "start" | "stop" | "restart" | "status",
405
405
  ): Promise<void> {
406
- await runServiceControlCommand({
407
- serviceName: "chat",
406
+ await runManagedPluginControlCommand({
407
+ pluginName: "chat",
408
408
  action,
409
409
  options: {
410
410
  path: ".",
@@ -14,7 +14,7 @@ import { getDowncityJsonPath } from "@/config/Paths.js";
14
14
  import { printResult } from "@/utils/cli/CliOutput.js";
15
15
  import { aliasCommand } from "./Alias.js";
16
16
  import { parseBoolean } from "./IndexSupport.js";
17
- import { resolveProjectRoot } from "../service/ServiceCommandSupport.js";
17
+ import { resolveProjectRoot } from "./PluginTargetSupport.js";
18
18
  import type { DowncityConfig } from "@downcity/agent";
19
19
 
20
20
  function isPlainObject(value: unknown): value is Record<string, unknown> {
@@ -1,29 +1,29 @@
1
1
  /**
2
- * Service action CLI 注册器。
2
+ * agent 托管的 plugin action CLI 注册器。
3
3
  *
4
4
  * 关键点(中文)
5
- * - 负责把 service actions 挂到 commander(`city <service> <action>`)。
6
- * - 仅处理 CLI 参数映射与远程调用,不承载 service 状态机逻辑。
7
- * - service 注册表与调度时间解析统一复用 agent 包实现,避免 city 维护第二套事实源。
5
+ * - 负责把需要运行中 agent 承载的 plugin actions 挂到 commander(`city <plugin> <action>`)。
6
+ * - 仅处理 CLI 参数映射与远程调用,不承载 plugin 状态机逻辑。
7
+ * - 命令注册表与调度时间解析统一复用 agent 包实现,避免 city 维护第二套事实源。
8
8
  */
9
9
 
10
10
  import path from "node:path";
11
11
  import type { Command } from "commander";
12
12
  import {
13
13
  callAgentTransport,
14
- listRegisteredServices,
14
+ listManagedPlugins,
15
15
  parseScheduledRunAtMsOrThrow,
16
16
  } from "@downcity/agent";
17
- import type { Service, ServiceAction } from "@downcity/agent";
17
+ import type { BasePlugin, PluginAction } from "@downcity/agent";
18
18
  import type { JsonObject, JsonValue } from "@downcity/agent";
19
- import type { ServiceCommandScheduleInput } from "@downcity/agent";
20
- import type { ServiceCommandResponse } from "@downcity/agent";
21
- import type { ServiceCliBaseOptions } from "@downcity/agent";
19
+ import type { PluginCommandScheduleInput } from "@downcity/agent";
20
+ import type { PluginCommandResponse } from "@downcity/agent";
21
+ import type { PluginCliBaseOptions } from "@downcity/agent";
22
22
  import { printResult } from "@/utils/cli/CliOutput.js";
23
- import { parseBoolean, parsePort } from "../shared/IndexSupport.js";
24
- import { runServiceControlCommand } from "./ServiceCommandRemote.js";
23
+ import { parseBoolean, parsePort } from "./IndexSupport.js";
24
+ import { runManagedPluginControlCommand } from "./ManagedPluginRemote.js";
25
25
 
26
- const CHAT_SERVICE_HELP_TEXT = [
26
+ const CHAT_PLUGIN_HELP_TEXT = [
27
27
  "",
28
28
  "Chat quick guide:",
29
29
  " 直接输出 assistant 文本会发送到当前 chat channel。",
@@ -40,7 +40,7 @@ const CHAT_SERVICE_HELP_TEXT = [
40
40
 
41
41
  const CHAT_HELP_HOOK_ATTACHED = Symbol("chat-help-hook-attached");
42
42
 
43
- type ServiceCliBridgeOptions = {
43
+ type PluginCliBridgeOptions = {
44
44
  path?: string;
45
45
  host?: string;
46
46
  port?: number;
@@ -85,7 +85,7 @@ function toJsonValue(input: unknown): JsonValue | undefined {
85
85
  return undefined;
86
86
  }
87
87
 
88
- function toServiceActionCommandOpts(
88
+ function toPluginActionCommandOpts(
89
89
  options: Record<string, unknown>,
90
90
  ): Record<string, JsonValue> {
91
91
  const reservedKeys = new Set(["path", "host", "port", "token", "json", "delay", "time"]);
@@ -99,9 +99,9 @@ function toServiceActionCommandOpts(
99
99
  return normalized;
100
100
  }
101
101
 
102
- function toServiceCliBridgeOptions(
102
+ function toPluginCliBridgeOptions(
103
103
  options: Record<string, unknown>,
104
- ): ServiceCliBridgeOptions {
104
+ ): PluginCliBridgeOptions {
105
105
  return {
106
106
  path: typeof options.path === "string" ? options.path : ".",
107
107
  host: typeof options.host === "string" ? options.host : undefined,
@@ -111,7 +111,7 @@ function toServiceCliBridgeOptions(
111
111
  };
112
112
  }
113
113
 
114
- function flattenServiceActionCommandArgs(values: unknown[]): string[] {
114
+ function flattenPluginActionCommandArgs(values: unknown[]): string[] {
115
115
  const out: string[] = [];
116
116
  const pushValue = (value: unknown): void => {
117
117
  if (value === undefined || value === null) return;
@@ -160,7 +160,7 @@ function hasLongOption(command: Command, longFlag: string): boolean {
160
160
  */
161
161
  function extractCommandScheduleInput(
162
162
  options: Record<string, unknown>,
163
- ): ServiceCommandScheduleInput | undefined {
163
+ ): PluginCommandScheduleInput | undefined {
164
164
  const runAtMs = parseScheduledRunAtMsOrThrow({
165
165
  delay: options.delay as string | number | undefined,
166
166
  time: options.time as string | number | undefined,
@@ -169,38 +169,38 @@ function extractCommandScheduleInput(
169
169
  return { runAtMs };
170
170
  }
171
171
 
172
- function registerServiceActionCommand(params: {
172
+ function registerPluginActionCommand(params: {
173
173
  program: Command;
174
- service: Service;
174
+ plugin: BasePlugin;
175
175
  actionName: string;
176
- action: ServiceAction<JsonValue, JsonValue>;
176
+ action: PluginAction<JsonValue, JsonValue>;
177
177
  }): void {
178
178
  const commandSpec = params.action.command;
179
179
  if (!commandSpec) return;
180
180
 
181
- const serviceCommand =
182
- params.program.commands.find((item) => item.name() === params.service.name) ||
181
+ const pluginCommand =
182
+ params.program.commands.find((item) => item.name() === params.plugin.name) ||
183
183
  params.program
184
- .command(params.service.name)
185
- .description(`${params.service.name} service actions`)
184
+ .command(params.plugin.name)
185
+ .description(`${params.plugin.name} plugin actions`)
186
186
  .helpOption("--help", "display help for command");
187
187
 
188
188
  if (
189
- params.service.name === "chat" &&
190
- !(serviceCommand as Command & { [CHAT_HELP_HOOK_ATTACHED]?: boolean })[
189
+ params.plugin.name === "chat" &&
190
+ !(pluginCommand as Command & { [CHAT_HELP_HOOK_ATTACHED]?: boolean })[
191
191
  CHAT_HELP_HOOK_ATTACHED
192
192
  ]
193
193
  ) {
194
- const chatCommand = serviceCommand as Command & {
194
+ const chatCommand = pluginCommand as Command & {
195
195
  [CHAT_HELP_HOOK_ATTACHED]?: boolean;
196
196
  };
197
197
  chatCommand.on("--help", () => {
198
- console.log(CHAT_SERVICE_HELP_TEXT);
198
+ console.log(CHAT_PLUGIN_HELP_TEXT);
199
199
  });
200
200
  chatCommand[CHAT_HELP_HOOK_ATTACHED] = true;
201
201
  }
202
202
 
203
- const actionCommand = serviceCommand
203
+ const actionCommand = pluginCommand
204
204
  .command(params.actionName)
205
205
  .description(commandSpec.description)
206
206
  .helpOption("--help", "display help for command")
@@ -212,12 +212,12 @@ function registerServiceActionCommand(params: {
212
212
 
213
213
  commandSpec.configure?.(actionCommand);
214
214
  if (!hasLongOption(actionCommand, "--delay")) {
215
- actionCommand.option("--delay <ms>", "延迟执行毫秒数(所有 service action 通用)");
215
+ actionCommand.option("--delay <ms>", "延迟执行毫秒数(所有 plugin action 通用)");
216
216
  }
217
217
  if (!hasLongOption(actionCommand, "--time")) {
218
218
  actionCommand.option(
219
219
  "--time <time>",
220
- "定时执行时间(Unix 时间戳秒/毫秒或 ISO 时间,所有 service action 通用)",
220
+ "定时执行时间(Unix 时间戳秒/毫秒或 ISO 时间,所有 plugin action 通用)",
221
221
  );
222
222
  }
223
223
 
@@ -225,7 +225,7 @@ function registerServiceActionCommand(params: {
225
225
  const last = rawArgs.at(-1);
226
226
  const commandLike = isCommanderCommandLike(last) ? last : null;
227
227
  const positionalArgs = commandLike
228
- ? flattenServiceActionCommandArgs(
228
+ ? flattenPluginActionCommandArgs(
229
229
  Array.isArray(commandLike.processedArgs)
230
230
  ? (commandLike.processedArgs as unknown[])
231
231
  : [],
@@ -235,7 +235,7 @@ function registerServiceActionCommand(params: {
235
235
  const fallbackPositional = isPlainOptionsObject(fallbackLast)
236
236
  ? rawArgs.slice(0, -1)
237
237
  : rawArgs;
238
- return flattenServiceActionCommandArgs(fallbackPositional);
238
+ return flattenPluginActionCommandArgs(fallbackPositional);
239
239
  })();
240
240
  const allOptions = commandLike
241
241
  ? ((commandLike.opts() as Record<string, unknown>) || {})
@@ -243,16 +243,16 @@ function registerServiceActionCommand(params: {
243
243
  const fallbackLast = rawArgs.at(-1);
244
244
  return isPlainOptionsObject(fallbackLast) ? fallbackLast : {};
245
245
  })();
246
- const actionOptions = toServiceActionCommandOpts(allOptions);
247
- const bridgeOptions = toServiceCliBridgeOptions(allOptions);
248
- let schedule: ServiceCommandScheduleInput | undefined;
246
+ const actionOptions = toPluginActionCommandOpts(allOptions);
247
+ const bridgeOptions = toPluginCliBridgeOptions(allOptions);
248
+ let schedule: PluginCommandScheduleInput | undefined;
249
249
  try {
250
250
  schedule = extractCommandScheduleInput(allOptions);
251
251
  } catch (error) {
252
252
  printResult({
253
253
  asJson: bridgeOptions.json,
254
254
  success: false,
255
- title: `${params.service.name}.${params.actionName} failed`,
255
+ title: `${params.plugin.name}.${params.actionName} failed`,
256
256
  payload: {
257
257
  error: `Failed to parse schedule input: ${String(error)}`,
258
258
  },
@@ -270,7 +270,7 @@ function registerServiceActionCommand(params: {
270
270
  printResult({
271
271
  asJson: bridgeOptions.json,
272
272
  success: false,
273
- title: `${params.service.name}.${params.actionName} failed`,
273
+ title: `${params.plugin.name}.${params.actionName} failed`,
274
274
  payload: {
275
275
  error: `Failed to parse command input: ${String(error)}`,
276
276
  },
@@ -278,15 +278,15 @@ function registerServiceActionCommand(params: {
278
278
  return;
279
279
  }
280
280
 
281
- const remote = await callAgentTransport<ServiceCommandResponse>({
281
+ const remote = await callAgentTransport<PluginCommandResponse>({
282
282
  projectRoot: resolveProjectRoot(bridgeOptions.path),
283
- path: "/api/services/command",
283
+ path: "/api/plugins/command",
284
284
  method: "POST",
285
285
  host: bridgeOptions.host,
286
286
  port: bridgeOptions.port,
287
287
  authToken: bridgeOptions.token,
288
288
  body: {
289
- serviceName: params.service.name,
289
+ pluginName: params.plugin.name,
290
290
  command: params.actionName,
291
291
  payload,
292
292
  ...(schedule ? { schedule } : {}),
@@ -299,8 +299,8 @@ function registerServiceActionCommand(params: {
299
299
  asJson: bridgeOptions.json,
300
300
  success: Boolean(data.success),
301
301
  title: data.success
302
- ? `${params.service.name}.${params.actionName} ok`
303
- : `${params.service.name}.${params.actionName} failed`,
302
+ ? `${params.plugin.name}.${params.actionName} ok`
303
+ : `${params.plugin.name}.${params.actionName} failed`,
304
304
  payload: {
305
305
  ...(data.data !== undefined ? { data: data.data } : {}),
306
306
  ...(data.message ? { message: data.message } : {}),
@@ -313,7 +313,7 @@ function registerServiceActionCommand(params: {
313
313
  printResult({
314
314
  asJson: bridgeOptions.json,
315
315
  success: false,
316
- title: `${params.service.name}.${params.actionName} failed`,
316
+ title: `${params.plugin.name}.${params.actionName} failed`,
317
317
  payload: {
318
318
  error: remote.error || "Unknown error",
319
319
  },
@@ -321,11 +321,11 @@ function registerServiceActionCommand(params: {
321
321
  });
322
322
  }
323
323
 
324
- function hasServiceSubcommand(command: Command, name: string): boolean {
324
+ function hasPluginSubcommand(command: Command, name: string): boolean {
325
325
  return command.commands.some((item) => item.name() === name);
326
326
  }
327
327
 
328
- function attachServiceLifecycleOptions(command: Command): Command {
328
+ function attachPluginLifecycleOptions(command: Command): Command {
329
329
  return command
330
330
  .option("--path <path>", "项目根目录(默认当前目录)", ".")
331
331
  .option("--host <host>", "Server host(覆盖自动解析)")
@@ -334,57 +334,57 @@ function attachServiceLifecycleOptions(command: Command): Command {
334
334
  .option("--json [enabled]", "以 JSON 输出", parseBoolean, true);
335
335
  }
336
336
 
337
- function registerServiceLifecycleCommands(params: {
337
+ function registerPluginLifecycleCommands(params: {
338
338
  program: Command;
339
- service: Service;
339
+ plugin: BasePlugin;
340
340
  }): void {
341
- if (!params.service.lifecycle?.start && !params.service.lifecycle?.stop) {
341
+ if (!params.plugin.lifecycle?.start && !params.plugin.lifecycle?.stop) {
342
342
  return;
343
343
  }
344
344
 
345
- const serviceCommand =
346
- params.program.commands.find((item) => item.name() === params.service.name) ||
345
+ const pluginCommand =
346
+ params.program.commands.find((item) => item.name() === params.plugin.name) ||
347
347
  params.program
348
- .command(params.service.name)
349
- .description(`${params.service.name} service actions`)
348
+ .command(params.plugin.name)
349
+ .description(`${params.plugin.name} plugin actions`)
350
350
  .helpOption("--help", "display help for command");
351
351
 
352
352
  const lifecycleCommands = [
353
353
  {
354
354
  name: "start",
355
- description: `启动 ${params.service.name} service`,
355
+ description: `启动 ${params.plugin.name} plugin`,
356
356
  action: "start" as const,
357
357
  },
358
358
  {
359
359
  name: "stop",
360
- description: `停止 ${params.service.name} service`,
360
+ description: `停止 ${params.plugin.name} plugin`,
361
361
  action: "stop" as const,
362
362
  },
363
363
  {
364
364
  name: "restart",
365
- description: `重启 ${params.service.name} service`,
365
+ description: `重启 ${params.plugin.name} plugin`,
366
366
  action: "restart" as const,
367
367
  },
368
368
  {
369
369
  name: "status",
370
- description: `查看 ${params.service.name} service 运行状态`,
370
+ description: `查看 ${params.plugin.name} plugin 运行状态`,
371
371
  action: "status" as const,
372
372
  },
373
373
  ];
374
374
 
375
375
  for (const item of lifecycleCommands) {
376
- if (hasServiceSubcommand(serviceCommand, item.name)) {
376
+ if (hasPluginSubcommand(pluginCommand, item.name)) {
377
377
  continue;
378
378
  }
379
379
 
380
- attachServiceLifecycleOptions(
381
- serviceCommand
380
+ attachPluginLifecycleOptions(
381
+ pluginCommand
382
382
  .command(item.name)
383
383
  .description(item.description)
384
384
  .helpOption("--help", "display help for command"),
385
- ).action(async (options: ServiceCliBaseOptions) => {
386
- await runServiceControlCommand({
387
- serviceName: params.service.name,
385
+ ).action(async (options: PluginCliBaseOptions) => {
386
+ await runManagedPluginControlCommand({
387
+ pluginName: params.plugin.name,
388
388
  action: item.action,
389
389
  options,
390
390
  });
@@ -393,24 +393,24 @@ function registerServiceLifecycleCommands(params: {
393
393
  }
394
394
 
395
395
  /**
396
- * 注册所有 service actions CLI 命令。
396
+ * 注册所有受 agent 托管的 plugin actions CLI 命令。
397
397
  */
398
- export function registerAllServicesForCli(program: Command): void {
399
- const services = listRegisteredServices();
400
- for (const service of services) {
401
- for (const [actionName, action] of Object.entries(service.actions)) {
402
- registerServiceActionCommand({
398
+ export function registerManagedPluginCommandsForCli(program: Command): void {
399
+ const plugins = listManagedPlugins();
400
+ for (const plugin of plugins) {
401
+ for (const [actionName, action] of Object.entries(plugin.actions)) {
402
+ registerPluginActionCommand({
403
403
  program,
404
- service,
404
+ plugin,
405
405
  actionName,
406
- action,
406
+ action: action as PluginAction<JsonValue, JsonValue>,
407
407
  });
408
408
  }
409
409
  }
410
- for (const service of services) {
411
- registerServiceLifecycleCommands({
410
+ for (const plugin of plugins) {
411
+ registerPluginLifecycleCommands({
412
412
  program,
413
- service,
413
+ plugin,
414
414
  });
415
415
  }
416
416
  }