@downcity/city 1.1.29 → 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 (114) hide show
  1. package/README.md +5 -11
  2. package/bin/cli/Index.js +3 -3
  3. package/bin/cli/Index.js.map +1 -1
  4. package/bin/cli/agent/AgentChat.js +1 -1
  5. package/bin/cli/agent/AgentChat.js.map +1 -1
  6. package/bin/cli/agent/AgentManager.js +3 -3
  7. package/bin/cli/agent/AgentManager.js.map +1 -1
  8. package/bin/cli/agent/Init.js +6 -6
  9. package/bin/cli/agent/Init.js.map +1 -1
  10. package/bin/cli/agent/Restart.js +1 -1
  11. package/bin/cli/agent/Restart.js.map +1 -1
  12. package/bin/cli/agent/Run.d.ts.map +1 -1
  13. package/bin/cli/agent/Run.js +6 -7
  14. package/bin/cli/agent/Run.js.map +1 -1
  15. package/bin/cli/agent/Start.js +1 -1
  16. package/bin/cli/agent/Start.js.map +1 -1
  17. package/bin/cli/model/ModelSupport.d.ts +1 -1
  18. package/bin/cli/model/ModelSupport.d.ts.map +1 -1
  19. package/bin/cli/model/ModelSupport.js +1 -1
  20. package/bin/cli/model/ModelSupport.js.map +1 -1
  21. package/bin/cli/shared/Chat.d.ts +1 -1
  22. package/bin/cli/shared/Chat.js +1 -1
  23. package/bin/cli/shared/ChatManager.d.ts +1 -1
  24. package/bin/cli/shared/ChatManager.js +20 -20
  25. package/bin/cli/shared/ChatManager.js.map +1 -1
  26. package/bin/cli/shared/Config.js +1 -1
  27. package/bin/cli/shared/Config.js.map +1 -1
  28. package/bin/cli/shared/ManagedPluginActionCommands.d.ts +14 -0
  29. package/bin/cli/shared/ManagedPluginActionCommands.d.ts.map +1 -0
  30. package/bin/cli/shared/{PluginRuntimeActionCommands.js → ManagedPluginActionCommands.js} +11 -11
  31. package/bin/cli/shared/{PluginRuntimeActionCommands.js.map → ManagedPluginActionCommands.js.map} +1 -1
  32. package/bin/cli/shared/{PluginRuntimeRemote.d.ts → ManagedPluginRemote.d.ts} +6 -6
  33. package/bin/cli/shared/{PluginRuntimeRemote.d.ts.map → ManagedPluginRemote.d.ts.map} +1 -1
  34. package/bin/cli/shared/{PluginRuntimeRemote.js → ManagedPluginRemote.js} +14 -14
  35. package/bin/cli/shared/ManagedPluginRemote.js.map +1 -0
  36. package/bin/cli/shared/PluginScheduleCommand.js +1 -1
  37. package/bin/cli/shared/PluginScheduleCommand.js.map +1 -1
  38. package/bin/cli/shared/{PluginRuntimeSupport.d.ts → PluginTargetSupport.d.ts} +3 -3
  39. package/bin/cli/shared/PluginTargetSupport.d.ts.map +1 -0
  40. package/bin/cli/shared/{PluginRuntimeSupport.js → PluginTargetSupport.js} +3 -3
  41. package/bin/cli/shared/PluginTargetSupport.js.map +1 -0
  42. package/bin/cli/shared/Plugins.d.ts.map +1 -1
  43. package/bin/cli/shared/Plugins.js +23 -20
  44. package/bin/cli/shared/Plugins.js.map +1 -1
  45. package/bin/cli/shared/PortHints.js +1 -1
  46. package/bin/config/DowncitySchema.d.ts.map +1 -1
  47. package/bin/config/DowncitySchema.js +2 -8
  48. package/bin/config/DowncitySchema.js.map +1 -1
  49. package/bin/config/Paths.d.ts +2 -2
  50. package/bin/config/Paths.js +2 -2
  51. package/bin/control/AgentStatusApiRoutes.js +2 -2
  52. package/bin/control/AgentStatusApiRoutes.js.map +1 -1
  53. package/bin/control/ChannelAccountApiRoutes.js +6 -6
  54. package/bin/control/ControlGateway.js +2 -2
  55. package/bin/control/ControlGateway.js.map +1 -1
  56. package/bin/control/PluginApiRoutes.js +5 -5
  57. package/bin/control/PluginApiRoutes.js.map +1 -1
  58. package/bin/control/gateway/AgentCatalog.js +1 -1
  59. package/bin/control/gateway/AgentCatalog.js.map +1 -1
  60. package/bin/control/instant/InstantApiRoutes.d.ts +3 -3
  61. package/bin/control/instant/InstantApiRoutes.d.ts.map +1 -1
  62. package/bin/control/instant/InstantApiRoutes.js +5 -5
  63. package/bin/control/instant/InstantApiRoutes.js.map +1 -1
  64. package/bin/control/instant/{InstantSessionService.d.ts → InstantSessionRunner.d.ts} +7 -7
  65. package/bin/control/instant/InstantSessionRunner.d.ts.map +1 -0
  66. package/bin/control/instant/{InstantSessionService.js → InstantSessionRunner.js} +4 -4
  67. package/bin/control/instant/InstantSessionRunner.js.map +1 -0
  68. package/bin/http/auth/RoutePolicy.js +4 -4
  69. package/bin/http/auth/RoutePolicy.js.map +1 -1
  70. package/bin/process/daemon/Api.d.ts +2 -2
  71. package/bin/process/daemon/Api.js +1 -1
  72. package/bin/process/registry/AgentHostRuntime.js +1 -1
  73. package/package.json +2 -2
  74. package/src/cli/Index.ts +3 -3
  75. package/src/cli/agent/AgentChat.ts +1 -1
  76. package/src/cli/agent/AgentManager.ts +3 -3
  77. package/src/cli/agent/Init.ts +6 -6
  78. package/src/cli/agent/Restart.ts +1 -1
  79. package/src/cli/agent/Run.ts +6 -7
  80. package/src/cli/agent/Start.ts +1 -1
  81. package/src/cli/model/ModelSupport.ts +1 -1
  82. package/src/cli/shared/Chat.ts +1 -1
  83. package/src/cli/shared/ChatManager.ts +20 -20
  84. package/src/cli/shared/Config.ts +1 -1
  85. package/src/cli/shared/{PluginRuntimeActionCommands.ts → ManagedPluginActionCommands.ts} +10 -10
  86. package/src/cli/shared/{PluginRuntimeRemote.ts → ManagedPluginRemote.ts} +15 -15
  87. package/src/cli/shared/PluginScheduleCommand.ts +1 -1
  88. package/src/cli/shared/{PluginRuntimeSupport.ts → PluginTargetSupport.ts} +2 -2
  89. package/src/cli/shared/Plugins.ts +28 -24
  90. package/src/cli/shared/PortHints.ts +1 -1
  91. package/src/config/DowncitySchema.ts +2 -8
  92. package/src/config/Paths.ts +2 -2
  93. package/src/control/AgentStatusApiRoutes.ts +5 -5
  94. package/src/control/ChannelAccountApiRoutes.ts +6 -6
  95. package/src/control/ControlGateway.ts +2 -2
  96. package/src/control/PluginApiRoutes.ts +5 -5
  97. package/src/control/gateway/AgentCatalog.ts +1 -1
  98. package/src/control/instant/InstantApiRoutes.ts +8 -8
  99. package/src/control/instant/{InstantSessionService.ts → InstantSessionRunner.ts} +7 -7
  100. package/src/http/auth/RoutePolicy.ts +4 -4
  101. package/src/process/daemon/Api.ts +2 -2
  102. package/src/process/registry/AgentHostRuntime.ts +1 -1
  103. package/bin/cli/shared/PluginRuntimeActionCommands.d.ts +0 -14
  104. package/bin/cli/shared/PluginRuntimeActionCommands.d.ts.map +0 -1
  105. package/bin/cli/shared/PluginRuntimeRemote.js.map +0 -1
  106. package/bin/cli/shared/PluginRuntimeSupport.d.ts.map +0 -1
  107. package/bin/cli/shared/PluginRuntimeSupport.js.map +0 -1
  108. package/bin/control/instant/InstantSessionService.d.ts.map +0 -1
  109. package/bin/control/instant/InstantSessionService.js.map +0 -1
  110. package/bin/process/registry/PluginRuntime.d.ts +0 -24
  111. package/bin/process/registry/PluginRuntime.d.ts.map +0 -1
  112. package/bin/process/registry/PluginRuntime.js +0 -31
  113. package/bin/process/registry/PluginRuntime.js.map +0 -1
  114. package/src/process/registry/PluginRuntime.ts +0 -42
@@ -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 { runPluginRuntimeControlCommand } from "./PluginRuntimeRemote.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,8 +49,8 @@ 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",
@@ -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",
@@ -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,7 +403,7 @@ async function runChannelAccountManager(): Promise<void> {
403
403
  async function runChatLifecycleAction(
404
404
  action: "start" | "stop" | "restart" | "status",
405
405
  ): Promise<void> {
406
- await runPluginRuntimeControlCommand({
406
+ await runManagedPluginControlCommand({
407
407
  pluginName: "chat",
408
408
  action,
409
409
  options: {
@@ -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 "./PluginRuntimeSupport.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,17 +1,17 @@
1
1
  /**
2
- * Runtime plugin action CLI 注册器。
2
+ * agent 托管的 plugin action CLI 注册器。
3
3
  *
4
4
  * 关键点(中文)
5
- * - 负责把 runtime plugin actions 挂到 commander(`city <plugin> <action>`)。
5
+ * - 负责把需要运行中 agent 承载的 plugin actions 挂到 commander(`city <plugin> <action>`)。
6
6
  * - 仅处理 CLI 参数映射与远程调用,不承载 plugin 状态机逻辑。
7
- * - runtime plugin 注册表与调度时间解析统一复用 agent 包实现,避免 city 维护第二套事实源。
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
- listRegisteredPlugins,
14
+ listManagedPlugins,
15
15
  parseScheduledRunAtMsOrThrow,
16
16
  } from "@downcity/agent";
17
17
  import type { BasePlugin, PluginAction } from "@downcity/agent";
@@ -21,7 +21,7 @@ import type { PluginCommandResponse } from "@downcity/agent";
21
21
  import type { PluginCliBaseOptions } from "@downcity/agent";
22
22
  import { printResult } from "@/utils/cli/CliOutput.js";
23
23
  import { parseBoolean, parsePort } from "./IndexSupport.js";
24
- import { runPluginRuntimeControlCommand } from "./PluginRuntimeRemote.js";
24
+ import { runManagedPluginControlCommand } from "./ManagedPluginRemote.js";
25
25
 
26
26
  const CHAT_PLUGIN_HELP_TEXT = [
27
27
  "",
@@ -280,7 +280,7 @@ function registerPluginActionCommand(params: {
280
280
 
281
281
  const remote = await callAgentTransport<PluginCommandResponse>({
282
282
  projectRoot: resolveProjectRoot(bridgeOptions.path),
283
- path: "/api/plugins/runtime/command",
283
+ path: "/api/plugins/command",
284
284
  method: "POST",
285
285
  host: bridgeOptions.host,
286
286
  port: bridgeOptions.port,
@@ -383,7 +383,7 @@ function registerPluginLifecycleCommands(params: {
383
383
  .description(item.description)
384
384
  .helpOption("--help", "display help for command"),
385
385
  ).action(async (options: PluginCliBaseOptions) => {
386
- await runPluginRuntimeControlCommand({
386
+ await runManagedPluginControlCommand({
387
387
  pluginName: params.plugin.name,
388
388
  action: item.action,
389
389
  options,
@@ -393,10 +393,10 @@ function registerPluginLifecycleCommands(params: {
393
393
  }
394
394
 
395
395
  /**
396
- * 注册所有 runtime plugin actions CLI 命令。
396
+ * 注册所有受 agent 托管的 plugin actions CLI 命令。
397
397
  */
398
- export function registerAllRuntimePluginsForCli(program: Command): void {
399
- const plugins = listRegisteredPlugins();
398
+ export function registerManagedPluginCommandsForCli(program: Command): void {
399
+ const plugins = listManagedPlugins();
400
400
  for (const plugin of plugins) {
401
401
  for (const [actionName, action] of Object.entries(plugin.actions)) {
402
402
  registerPluginActionCommand({
@@ -2,7 +2,7 @@
2
2
  * `city plugin` 运行态远程 Agent server 调用辅助。
3
3
  *
4
4
  * 关键点(中文)
5
- * - 统一处理 runtime list/control/command 三类需要访问 Agent server 的命令。
5
+ * - 统一处理 list/control/command 三类需要访问 Agent server 的命令。
6
6
  * - 这里不负责命令注册,只负责 transport 调用与结果输出。
7
7
  */
8
8
 
@@ -13,26 +13,26 @@ import type {
13
13
  PluginCommandResponse,
14
14
  PluginControlAction,
15
15
  PluginControlResponse,
16
- PluginListResponse,
16
+ PluginStateListResponse,
17
17
  } from "@downcity/agent";
18
18
  import {
19
19
  parseCommandPayload,
20
20
  resolvePluginProjectRoot,
21
21
  validateAgentProjectRoot,
22
- } from "./PluginRuntimeSupport.js";
22
+ } from "./PluginTargetSupport.js";
23
23
 
24
24
  const PLUGIN_COMMAND_TIMEOUT_MS = 120_000;
25
25
 
26
26
  /**
27
- * 执行 `plugin list --runtime`。
27
+ * 执行 `plugin list`。
28
28
  */
29
- export async function runPluginRuntimeListCommand(options: PluginCliBaseOptions): Promise<void> {
29
+ export async function runManagedPluginListCommand(options: PluginCliBaseOptions): Promise<void> {
30
30
  const resolved = await resolvePluginProjectRoot(options);
31
31
  if (!resolved.projectRoot) {
32
32
  printResult({
33
33
  asJson: options.json,
34
34
  success: false,
35
- title: "plugin runtime list failed",
35
+ title: "plugin list failed",
36
36
  payload: {
37
37
  error: resolved.error || "Failed to resolve agent project path",
38
38
  },
@@ -45,16 +45,16 @@ export async function runPluginRuntimeListCommand(options: PluginCliBaseOptions)
45
45
  printResult({
46
46
  asJson: options.json,
47
47
  success: false,
48
- title: "plugin runtime list failed",
48
+ title: "plugin list failed",
49
49
  payload: {
50
50
  error: pathError,
51
51
  },
52
52
  });
53
53
  return;
54
54
  }
55
- const remote = await callAgentTransport<PluginListResponse>({
55
+ const remote = await callAgentTransport<PluginStateListResponse>({
56
56
  projectRoot,
57
- path: "/api/plugins/runtime/list",
57
+ path: "/api/plugins/list",
58
58
  method: "GET",
59
59
  host: options.host,
60
60
  port: options.port,
@@ -65,7 +65,7 @@ export async function runPluginRuntimeListCommand(options: PluginCliBaseOptions)
65
65
  printResult({
66
66
  asJson: options.json,
67
67
  success: Boolean(remote.data.success),
68
- title: remote.data.success ? "plugin runtime listed" : "plugin runtime list failed",
68
+ title: remote.data.success ? "plugin listed" : "plugin list failed",
69
69
  payload: {
70
70
  ...(Array.isArray(remote.data.plugins) ? { plugins: remote.data.plugins } : {}),
71
71
  ...(remote.data.error ? { error: remote.data.error } : {}),
@@ -77,7 +77,7 @@ export async function runPluginRuntimeListCommand(options: PluginCliBaseOptions)
77
77
  printResult({
78
78
  asJson: options.json,
79
79
  success: false,
80
- title: "plugin runtime list failed",
80
+ title: "plugin list failed",
81
81
  payload: {
82
82
  error: remote.error || "Unknown error",
83
83
  },
@@ -87,7 +87,7 @@ export async function runPluginRuntimeListCommand(options: PluginCliBaseOptions)
87
87
  /**
88
88
  * 执行 `plugin status/start/stop/restart`。
89
89
  */
90
- export async function runPluginRuntimeControlCommand(params: {
90
+ export async function runManagedPluginControlCommand(params: {
91
91
  pluginName: string;
92
92
  action: PluginControlAction;
93
93
  options: PluginCliBaseOptions;
@@ -119,7 +119,7 @@ export async function runPluginRuntimeControlCommand(params: {
119
119
  }
120
120
  const remote = await callAgentTransport<PluginControlResponse>({
121
121
  projectRoot,
122
- path: "/api/plugins/runtime/control",
122
+ path: "/api/plugins/control",
123
123
  method: "POST",
124
124
  host: params.options.host,
125
125
  port: params.options.port,
@@ -156,7 +156,7 @@ export async function runPluginRuntimeControlCommand(params: {
156
156
  /**
157
157
  * 执行 `plugin command` 桥接。
158
158
  */
159
- export async function runPluginRuntimeCommandBridge(params: {
159
+ export async function runManagedPluginCommandBridge(params: {
160
160
  pluginName: string;
161
161
  command: string;
162
162
  payloadRaw?: string;
@@ -189,7 +189,7 @@ export async function runPluginRuntimeCommandBridge(params: {
189
189
  }
190
190
  const remote = await callAgentTransport<PluginCommandResponse>({
191
191
  projectRoot,
192
- path: "/api/plugins/runtime/command",
192
+ path: "/api/plugins/command",
193
193
  method: "POST",
194
194
  timeoutMs: PLUGIN_COMMAND_TIMEOUT_MS,
195
195
  host: params.options.host,
@@ -16,7 +16,7 @@ import {
16
16
  parsePositiveIntOption,
17
17
  resolvePluginScheduleProjectRoot,
18
18
  validateAgentProjectRoot,
19
- } from "./PluginRuntimeSupport.js";
19
+ } from "./PluginTargetSupport.js";
20
20
 
21
21
  /**
22
22
  * 执行 `plugin schedule list`。
@@ -2,7 +2,7 @@
2
2
  * `city plugin` 运行态命令共享辅助 + Agent 预检。
3
3
  *
4
4
  * 关键点(中文)
5
- * - 统一承载 runtime plugin 命令的参数解析、目标 agent 路径解析与项目目录校验。
5
+ * - 统一承载 plugin runtime 命令的参数解析、目标 agent 路径解析与项目目录校验。
6
6
  * - 提供 `checkAgentPreflight` 供 start/restart/status 等命令统一使用。
7
7
  * - 保持 command 注册层只关注命令树,不再直接承载路径解析细节。
8
8
  */
@@ -164,7 +164,7 @@ export async function resolveProjectRootByAgentName(agentName: string): Promise<
164
164
  }
165
165
 
166
166
  /**
167
- * 统一解析 runtime plugin 命令目标路径(agent 优先于 path)。
167
+ * 统一解析 plugin runtime 命令目标路径(agent 优先于 path)。
168
168
  */
169
169
  export async function resolvePluginProjectRoot(options: PluginCliBaseOptions): Promise<{
170
170
  projectRoot?: string;
@@ -15,7 +15,8 @@ import {
15
15
  buildStaticPluginAvailability,
16
16
  findBuiltinPlugin,
17
17
  findStaticPluginView,
18
- listRegisteredPlugins,
18
+ listLocalPlugins,
19
+ listManagedPlugins,
19
20
  listStaticPluginViews,
20
21
  runLocalPluginAction,
21
22
  } from "@downcity/agent";
@@ -25,18 +26,18 @@ import { getDowncityJsonPath } from "@/config/Paths.js";
25
26
  import type { PluginCliBaseOptions } from "@downcity/agent";
26
27
  import { emitCliBlock } from "./CliReporter.js";
27
28
  import { parseBoolean, parsePort } from "./IndexSupport.js";
28
- import { resolveProjectRoot } from "./PluginRuntimeSupport.js";
29
+ import { resolveProjectRoot } from "./PluginTargetSupport.js";
29
30
  import {
30
- runPluginRuntimeCommandBridge,
31
- runPluginRuntimeControlCommand,
32
- } from "./PluginRuntimeRemote.js";
31
+ runManagedPluginCommandBridge,
32
+ runManagedPluginControlCommand,
33
+ } from "./ManagedPluginRemote.js";
33
34
  import { registerPluginScheduleCommands } from "./PluginScheduleCommand.js";
34
35
  import { setCityPluginEnabled } from "@/platform/PluginLifecycle.js";
35
36
 
36
37
  type StaticCatalogEntry = {
37
38
  name: string;
38
39
  title: string;
39
- kind: "runtime" | "extension";
40
+ kind: "managed" | "local";
40
41
  enabled: boolean;
41
42
  available: boolean;
42
43
  actionCount: number;
@@ -122,7 +123,7 @@ function truncateCell(input: string, width: number): string {
122
123
  function renderPluginCatalogTable(rows: Array<{
123
124
  name: string;
124
125
  title: string;
125
- kind: "runtime" | "extension";
126
+ kind: "managed" | "local";
126
127
  enabled: boolean;
127
128
  available: boolean;
128
129
  actionCount: number;
@@ -166,24 +167,27 @@ function renderPluginCatalogTable(rows: Array<{
166
167
  }
167
168
 
168
169
  function listStaticCatalogEntries(): StaticCatalogEntry[] {
169
- const runtimeEntries = listRegisteredPlugins().map((plugin) => ({
170
+ const managedEntries = listManagedPlugins().map((plugin) => ({
170
171
  name: plugin.name,
171
- title: `${plugin.name} runtime plugin`,
172
- kind: "runtime" as const,
172
+ title: String(plugin.title || plugin.name || "").trim() || plugin.name,
173
+ kind: "managed" as const,
173
174
  enabled: true,
174
175
  available: true,
175
176
  actionCount: Object.keys(plugin.actions || {}).length,
176
177
  actions: Object.keys(plugin.actions || {}).sort((left, right) => left.localeCompare(right)),
177
178
  hasSystem: typeof plugin.system === "function",
178
- note: "Runtime plugin. Use `city plugin start/stop/restart/status` with an agent target for live state.",
179
+ note: "Managed plugin. Use `city plugin start/stop/restart/status` with an agent target for live state.",
179
180
  }));
180
181
 
181
- const extensionEntries = listStaticPluginViews().map((plugin) => {
182
+ const localNames = new Set(listLocalPlugins().map((plugin) => plugin.name));
183
+ const localEntries = listStaticPluginViews()
184
+ .filter((plugin) => localNames.has(plugin.name))
185
+ .map((plugin) => {
182
186
  const availability = buildSafeStaticPluginAvailability(plugin.name);
183
187
  return {
184
188
  name: plugin.name,
185
189
  title: plugin.title,
186
- kind: "extension" as const,
190
+ kind: "local" as const,
187
191
  enabled: availability.enabled,
188
192
  available: availability.available,
189
193
  actionCount: plugin.actions.length,
@@ -193,7 +197,7 @@ function listStaticCatalogEntries(): StaticCatalogEntry[] {
193
197
  };
194
198
  });
195
199
 
196
- const merged = [...runtimeEntries, ...extensionEntries];
200
+ const merged = [...managedEntries, ...localEntries];
197
201
  const unique = new Map<string, StaticCatalogEntry>();
198
202
  for (const entry of merged) {
199
203
  if (!unique.has(entry.name)) {
@@ -609,7 +613,7 @@ export function registerPluginsCommand(program: Command): void {
609
613
 
610
614
  plugin
611
615
  .command("status <pluginName>")
612
- .description("按 agent 目标查看 runtime plugin 运行状态")
616
+ .description("按 agent 目标查看托管 plugin 运行状态")
613
617
  .option("--path <path>", "项目根目录(默认当前目录)", ".")
614
618
  .option("--agent <name>", "agent 名称(从 managed agent registry 解析)")
615
619
  .option("--host <host>", "Server host(覆盖自动解析)")
@@ -617,7 +621,7 @@ export function registerPluginsCommand(program: Command): void {
617
621
  .option("--token <token>", "覆盖 Bearer Token(仅远程 HTTP 调用需要;默认本地走 IPC)")
618
622
  .option("--json [enabled]", "以 JSON 输出", parseBoolean, true)
619
623
  .action(async (pluginName: string, opts: PluginCliBaseOptions) => {
620
- await runPluginRuntimeControlCommand({
624
+ await runManagedPluginControlCommand({
621
625
  pluginName,
622
626
  action: "status",
623
627
  options: opts,
@@ -626,7 +630,7 @@ export function registerPluginsCommand(program: Command): void {
626
630
 
627
631
  plugin
628
632
  .command("start <pluginName>")
629
- .description("按 agent 目标启动 runtime plugin")
633
+ .description("按 agent 目标启动托管 plugin")
630
634
  .option("--path <path>", "项目根目录(默认当前目录)", ".")
631
635
  .option("--agent <name>", "agent 名称(从 managed agent registry 解析)")
632
636
  .option("--host <host>", "Server host(覆盖自动解析)")
@@ -634,7 +638,7 @@ export function registerPluginsCommand(program: Command): void {
634
638
  .option("--token <token>", "覆盖 Bearer Token(仅远程 HTTP 调用需要;默认本地走 IPC)")
635
639
  .option("--json [enabled]", "以 JSON 输出", parseBoolean, true)
636
640
  .action(async (pluginName: string, opts: PluginCliBaseOptions) => {
637
- await runPluginRuntimeControlCommand({
641
+ await runManagedPluginControlCommand({
638
642
  pluginName,
639
643
  action: "start",
640
644
  options: opts,
@@ -643,7 +647,7 @@ export function registerPluginsCommand(program: Command): void {
643
647
 
644
648
  plugin
645
649
  .command("stop <pluginName>")
646
- .description("按 agent 目标停止 runtime plugin")
650
+ .description("按 agent 目标停止托管 plugin")
647
651
  .option("--path <path>", "项目根目录(默认当前目录)", ".")
648
652
  .option("--agent <name>", "agent 名称(从 managed agent registry 解析)")
649
653
  .option("--host <host>", "Server host(覆盖自动解析)")
@@ -651,7 +655,7 @@ export function registerPluginsCommand(program: Command): void {
651
655
  .option("--token <token>", "覆盖 Bearer Token(仅远程 HTTP 调用需要;默认本地走 IPC)")
652
656
  .option("--json [enabled]", "以 JSON 输出", parseBoolean, true)
653
657
  .action(async (pluginName: string, opts: PluginCliBaseOptions) => {
654
- await runPluginRuntimeControlCommand({
658
+ await runManagedPluginControlCommand({
655
659
  pluginName,
656
660
  action: "stop",
657
661
  options: opts,
@@ -660,7 +664,7 @@ export function registerPluginsCommand(program: Command): void {
660
664
 
661
665
  plugin
662
666
  .command("restart <pluginName>")
663
- .description("按 agent 目标重启 runtime plugin")
667
+ .description("按 agent 目标重启托管 plugin")
664
668
  .option("--path <path>", "项目根目录(默认当前目录)", ".")
665
669
  .option("--agent <name>", "agent 名称(从 managed agent registry 解析)")
666
670
  .option("--host <host>", "Server host(覆盖自动解析)")
@@ -668,7 +672,7 @@ export function registerPluginsCommand(program: Command): void {
668
672
  .option("--token <token>", "覆盖 Bearer Token(仅远程 HTTP 调用需要;默认本地走 IPC)")
669
673
  .option("--json [enabled]", "以 JSON 输出", parseBoolean, true)
670
674
  .action(async (pluginName: string, opts: PluginCliBaseOptions) => {
671
- await runPluginRuntimeControlCommand({
675
+ await runManagedPluginControlCommand({
672
676
  pluginName,
673
677
  action: "restart",
674
678
  options: opts,
@@ -677,7 +681,7 @@ export function registerPluginsCommand(program: Command): void {
677
681
 
678
682
  plugin
679
683
  .command("command <pluginName> <command>")
680
- .description("按 agent 目标转发 runtime plugin command")
684
+ .description("按 agent 目标转发托管 plugin command")
681
685
  .option("--payload <json>", "可选 payload(JSON 字符串或普通字符串)")
682
686
  .option("--path <path>", "项目根目录(默认当前目录)", ".")
683
687
  .option("--agent <name>", "agent 名称(从 managed agent registry 解析)")
@@ -690,7 +694,7 @@ export function registerPluginsCommand(program: Command): void {
690
694
  command: string,
691
695
  opts: PluginCliBaseOptions & { payload?: string },
692
696
  ) => {
693
- await runPluginRuntimeCommandBridge({
697
+ await runManagedPluginCommandBridge({
694
698
  pluginName,
695
699
  command,
696
700
  payloadRaw: opts.payload,
@@ -23,7 +23,7 @@ export function buildRuntimePortFacts(): Array<{
23
23
  },
24
24
  {
25
25
  label: "Usage",
26
- value: "Runtime API / plugin endpoints (health, runtime plugin, task, extension plugin)",
26
+ value: "Runtime API / plugin endpoints (health, plugin runtime, task, extension plugin)",
27
27
  },
28
28
  ];
29
29
  }
@@ -120,11 +120,11 @@ export const DOWNCITY_JSON_SCHEMA: JsonObject = {
120
120
  },
121
121
  },
122
122
  },
123
- services: {
123
+ plugins: {
124
124
  type: "object",
125
125
  additionalProperties: true,
126
126
  properties: {
127
- skills: {
127
+ skill: {
128
128
  type: "object",
129
129
  additionalProperties: true,
130
130
  properties: {
@@ -187,12 +187,6 @@ export const DOWNCITY_JSON_SCHEMA: JsonObject = {
187
187
  },
188
188
  },
189
189
  },
190
- },
191
- },
192
- plugins: {
193
- type: "object",
194
- additionalProperties: true,
195
- properties: {
196
190
  asr: {
197
191
  type: "object",
198
192
  additionalProperties: true,
@@ -111,7 +111,7 @@ export function getDowncityMemoryDailyPath(cwd: string, date: string): string {
111
111
  }
112
112
 
113
113
  /**
114
- * Service Schedule JSONL 路径。
114
+ * Plugin Schedule JSONL 路径。
115
115
  *
116
116
  * 关键点(中文)
117
117
  * - 调度任务属于项目 runtime 本地状态,因此放在项目 `.downcity/` 下。
@@ -226,7 +226,7 @@ export function getDowncityDebugDirPath(cwd: string): string {
226
226
  }
227
227
 
228
228
  /**
229
- * Chat 元信息目录(由 services/chat 维护)。
229
+ * Chat 元信息目录(由 chat plugin runtime 维护)。
230
230
  *
231
231
  * 关键点(中文)
232
232
  * - 该目录存放 `sessionId -> chat` 的最近映射快照
@@ -19,7 +19,7 @@ type AgentStatusPayload = {
19
19
  reason?: string;
20
20
  };
21
21
 
22
- type PluginRuntimeListResponse = {
22
+ type PluginStateListResponse = {
23
23
  success?: boolean;
24
24
  plugins?: Array<{
25
25
  name?: unknown;
@@ -94,10 +94,10 @@ async function probeSelectedAgentStatus(
94
94
  };
95
95
  }
96
96
 
97
- let pluginsPayload: PluginRuntimeListResponse;
97
+ let pluginsPayload: PluginStateListResponse;
98
98
  try {
99
- pluginsPayload = await fetchStatusJson<PluginRuntimeListResponse>(
100
- new URL("/api/plugins/runtime/list", baseUrl).toString(),
99
+ pluginsPayload = await fetchStatusJson<PluginStateListResponse>(
100
+ new URL("/api/plugins/list", baseUrl).toString(),
101
101
  );
102
102
  } catch (error) {
103
103
  return {
@@ -152,7 +152,7 @@ async function probeSelectedAgentStatus(
152
152
 
153
153
  try {
154
154
  await fetchStatusJson<ChatStatusResponse>(
155
- new URL("/api/plugins/runtime/command", baseUrl).toString(),
155
+ new URL("/api/plugins/command", baseUrl).toString(),
156
156
  {
157
157
  method: "POST",
158
158
  headers: {
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  import type { Hono } from "hono";
10
- import { ChatChannelAccountService } from "@downcity/agent";
10
+ import { ChatChannelAccountManager } from "@downcity/agent";
11
11
  import { createAgentPlatformRuntime } from "@/process/registry/AgentHostRuntime.js";
12
12
 
13
13
  /**
@@ -15,11 +15,11 @@ import { createAgentPlatformRuntime } from "@/process/registry/AgentHostRuntime.
15
15
  */
16
16
  export function registerPlatformChannelAccountRoutes(params: { app: Hono }): void {
17
17
  const app = params.app;
18
- const service = new ChatChannelAccountService(createAgentPlatformRuntime());
18
+ const manager = new ChatChannelAccountManager(createAgentPlatformRuntime());
19
19
 
20
20
  app.get("/api/ui/channel-accounts", async (c) => {
21
21
  try {
22
- const payload = await service.list();
22
+ const payload = await manager.list();
23
23
  return c.json({
24
24
  success: true,
25
25
  ...payload,
@@ -47,7 +47,7 @@ export function registerPlatformChannelAccountRoutes(params: { app: Hono }): voi
47
47
  clearAppId?: boolean;
48
48
  clearAppSecret?: boolean;
49
49
  };
50
- const payload = await service.upsert({
50
+ const payload = await manager.upsert({
51
51
  id: String(body.id || "").trim(),
52
52
  channel: String(body.channel || "").trim(),
53
53
  name: String(body.name || "").trim(),
@@ -82,7 +82,7 @@ export function registerPlatformChannelAccountRoutes(params: { app: Hono }): voi
82
82
  domain?: string;
83
83
  sandbox?: boolean;
84
84
  };
85
- const payload = await service.probe({
85
+ const payload = await manager.probe({
86
86
  channel: String(body.channel || "").trim(),
87
87
  botToken: body.botToken,
88
88
  appId: body.appId,
@@ -108,7 +108,7 @@ export function registerPlatformChannelAccountRoutes(params: { app: Hono }): voi
108
108
  if (!id) {
109
109
  return c.json({ success: false, error: "Missing id" }, 400);
110
110
  }
111
- await service.remove(id);
111
+ await manager.remove(id);
112
112
  return c.json({
113
113
  success: true,
114
114
  id,
@@ -49,7 +49,7 @@ import type {
49
49
  PlatformLocalModelsResponse,
50
50
  } from "@downcity/agent";
51
51
  import type { AgentProjectInitializationResult } from "@downcity/agent";
52
- import { listBuiltinPluginRuntimeAuthPolicies } from "@downcity/agent";
52
+ import { listBuiltinPluginAuthPolicies } from "@downcity/agent";
53
53
  import { AuthService } from "@/http/auth/AuthService.js";
54
54
  import { registerAuthRoutes } from "@/http/auth/AuthRoutes.js";
55
55
  import {
@@ -120,7 +120,7 @@ export class ControlGateway {
120
120
  this.authService,
121
121
  [
122
122
  ...CONTROL_PLANE_AUTH_ROUTE_POLICIES,
123
- ...listBuiltinPluginRuntimeAuthPolicies(),
123
+ ...listBuiltinPluginAuthPolicies(),
124
124
  ],
125
125
  ),
126
126
  );