@downcity/city 1.1.29 → 1.1.39
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/README.md +5 -11
- package/bin/cli/Index.js +10 -5
- package/bin/cli/Index.js.map +1 -1
- package/bin/cli/agent/AgentChat.js +1 -1
- package/bin/cli/agent/AgentChat.js.map +1 -1
- package/bin/cli/agent/AgentManager.js +3 -3
- package/bin/cli/agent/AgentManager.js.map +1 -1
- package/bin/cli/agent/Init.d.ts.map +1 -1
- package/bin/cli/agent/Init.js +14 -14
- package/bin/cli/agent/Init.js.map +1 -1
- package/bin/cli/agent/Restart.js +1 -1
- package/bin/cli/agent/Restart.js.map +1 -1
- package/bin/cli/agent/Run.d.ts.map +1 -1
- package/bin/cli/agent/Run.js +12 -19
- package/bin/cli/agent/Run.js.map +1 -1
- package/bin/cli/agent/Start.js +1 -1
- package/bin/cli/agent/Start.js.map +1 -1
- package/bin/cli/control-plane/ControlPlaneProcess.d.ts.map +1 -1
- package/bin/cli/control-plane/ControlPlaneProcess.js +2 -3
- package/bin/cli/control-plane/ControlPlaneProcess.js.map +1 -1
- package/bin/cli/model/ModelSupport.d.ts +1 -1
- package/bin/cli/model/ModelSupport.d.ts.map +1 -1
- package/bin/cli/model/ModelSupport.js +1 -1
- package/bin/cli/model/ModelSupport.js.map +1 -1
- package/bin/cli/shared/Chat.d.ts +1 -1
- package/bin/cli/shared/Chat.js +1 -1
- package/bin/cli/shared/ChatAuth.d.ts.map +1 -1
- package/bin/cli/shared/ChatAuth.js +5 -7
- package/bin/cli/shared/ChatAuth.js.map +1 -1
- package/bin/cli/shared/ChatManager.d.ts +1 -1
- package/bin/cli/shared/ChatManager.d.ts.map +1 -1
- package/bin/cli/shared/ChatManager.js +20 -21
- package/bin/cli/shared/ChatManager.js.map +1 -1
- package/bin/cli/shared/Config.js +1 -1
- package/bin/cli/shared/Config.js.map +1 -1
- package/bin/cli/shared/ManagedPluginActionCommands.d.ts +15 -0
- package/bin/cli/shared/ManagedPluginActionCommands.d.ts.map +1 -0
- package/bin/cli/shared/{PluginRuntimeActionCommands.js → ManagedPluginActionCommands.js} +13 -12
- package/bin/cli/shared/ManagedPluginActionCommands.js.map +1 -0
- package/bin/cli/shared/{PluginRuntimeRemote.d.ts → ManagedPluginRemote.d.ts} +6 -6
- package/bin/cli/shared/{PluginRuntimeRemote.d.ts.map → ManagedPluginRemote.d.ts.map} +1 -1
- package/bin/cli/shared/{PluginRuntimeRemote.js → ManagedPluginRemote.js} +14 -14
- package/bin/cli/shared/ManagedPluginRemote.js.map +1 -0
- package/bin/cli/shared/PluginScheduleCommand.d.ts +3 -2
- package/bin/cli/shared/PluginScheduleCommand.d.ts.map +1 -1
- package/bin/cli/shared/PluginScheduleCommand.js +12 -11
- package/bin/cli/shared/PluginScheduleCommand.js.map +1 -1
- package/bin/cli/shared/{PluginRuntimeSupport.d.ts → PluginTargetSupport.d.ts} +7 -7
- package/bin/cli/shared/PluginTargetSupport.d.ts.map +1 -0
- package/bin/cli/shared/{PluginRuntimeSupport.js → PluginTargetSupport.js} +7 -8
- package/bin/cli/shared/{PluginRuntimeSupport.js.map → PluginTargetSupport.js.map} +1 -1
- package/bin/cli/shared/Plugins.d.ts.map +1 -1
- package/bin/cli/shared/Plugins.js +30 -21
- package/bin/cli/shared/Plugins.js.map +1 -1
- package/bin/cli/shared/PortHints.js +1 -1
- package/bin/config/DowncitySchema.d.ts.map +1 -1
- package/bin/config/DowncitySchema.js +2 -8
- package/bin/config/DowncitySchema.js.map +1 -1
- package/bin/config/Paths.d.ts +2 -2
- package/bin/config/Paths.js +2 -2
- package/bin/control/AgentStatusApiRoutes.js +2 -2
- package/bin/control/AgentStatusApiRoutes.js.map +1 -1
- package/bin/control/ChannelAccountApiRoutes.d.ts.map +1 -1
- package/bin/control/ChannelAccountApiRoutes.js +6 -7
- package/bin/control/ChannelAccountApiRoutes.js.map +1 -1
- package/bin/control/ControlGateway.d.ts.map +1 -1
- package/bin/control/ControlGateway.js +3 -2
- package/bin/control/ControlGateway.js.map +1 -1
- package/bin/control/PluginApiRoutes.d.ts.map +1 -1
- package/bin/control/PluginApiRoutes.js +38 -30
- package/bin/control/PluginApiRoutes.js.map +1 -1
- package/bin/control/gateway/AgentActions.d.ts.map +1 -1
- package/bin/control/gateway/AgentActions.js +16 -11
- package/bin/control/gateway/AgentActions.js.map +1 -1
- package/bin/control/gateway/AgentCatalog.js +1 -1
- package/bin/control/gateway/AgentCatalog.js.map +1 -1
- package/bin/control/instant/InstantApiRoutes.d.ts +3 -3
- package/bin/control/instant/InstantApiRoutes.d.ts.map +1 -1
- package/bin/control/instant/InstantApiRoutes.js +5 -5
- package/bin/control/instant/InstantApiRoutes.js.map +1 -1
- package/bin/control/instant/{InstantSessionService.d.ts → InstantSessionRunner.d.ts} +7 -7
- package/bin/control/instant/InstantSessionRunner.d.ts.map +1 -0
- package/bin/control/instant/{InstantSessionService.js → InstantSessionRunner.js} +4 -4
- package/bin/control/instant/InstantSessionRunner.js.map +1 -0
- package/bin/http/auth/RoutePolicy.js +4 -4
- package/bin/http/auth/RoutePolicy.js.map +1 -1
- package/bin/model/runtime/CreateRuntimeModel.d.ts +2 -10
- package/bin/model/runtime/CreateRuntimeModel.d.ts.map +1 -1
- package/bin/model/runtime/CreateRuntimeModel.js +1 -16
- package/bin/model/runtime/CreateRuntimeModel.js.map +1 -1
- package/bin/model/runtime/ExecutionModelBinding.d.ts +46 -0
- package/bin/model/runtime/ExecutionModelBinding.d.ts.map +1 -0
- package/bin/model/runtime/ExecutionModelBinding.js +96 -0
- package/bin/model/runtime/ExecutionModelBinding.js.map +1 -0
- package/bin/process/daemon/Api.d.ts +2 -2
- package/bin/process/daemon/Api.js +1 -1
- package/bin/process/registry/AgentHostRuntime.d.ts +1 -9
- package/bin/process/registry/AgentHostRuntime.d.ts.map +1 -1
- package/bin/process/registry/AgentHostRuntime.js +2 -156
- package/bin/process/registry/AgentHostRuntime.js.map +1 -1
- package/package.json +3 -2
- package/src/cli/Index.ts +13 -5
- package/src/cli/agent/AgentChat.ts +1 -1
- package/src/cli/agent/AgentManager.ts +3 -3
- package/src/cli/agent/Init.ts +15 -14
- package/src/cli/agent/Restart.ts +1 -1
- package/src/cli/agent/Run.ts +12 -18
- package/src/cli/agent/Start.ts +1 -1
- package/src/cli/control-plane/ControlPlaneProcess.ts +2 -3
- package/src/cli/model/ModelSupport.ts +1 -1
- package/src/cli/shared/Chat.ts +1 -1
- package/src/cli/shared/ChatAuth.ts +10 -11
- package/src/cli/shared/ChatManager.ts +21 -22
- package/src/cli/shared/Config.ts +1 -1
- package/src/cli/shared/{PluginRuntimeActionCommands.ts → ManagedPluginActionCommands.ts} +18 -15
- package/src/cli/shared/{PluginRuntimeRemote.ts → ManagedPluginRemote.ts} +15 -15
- package/src/cli/shared/PluginScheduleCommand.ts +12 -11
- package/src/cli/shared/{PluginRuntimeSupport.ts → PluginTargetSupport.ts} +8 -9
- package/src/cli/shared/Plugins.ts +38 -28
- package/src/cli/shared/PortHints.ts +1 -1
- package/src/config/DowncitySchema.ts +2 -8
- package/src/config/Paths.ts +2 -2
- package/src/control/AgentStatusApiRoutes.ts +5 -5
- package/src/control/ChannelAccountApiRoutes.ts +6 -7
- package/src/control/ControlGateway.ts +3 -2
- package/src/control/PluginApiRoutes.ts +42 -32
- package/src/control/gateway/AgentActions.ts +16 -11
- package/src/control/gateway/AgentCatalog.ts +1 -1
- package/src/control/instant/InstantApiRoutes.ts +8 -8
- package/src/control/instant/{InstantSessionService.ts → InstantSessionRunner.ts} +7 -7
- package/src/http/auth/RoutePolicy.ts +4 -4
- package/src/model/runtime/CreateRuntimeModel.ts +1 -26
- package/src/model/runtime/ExecutionModelBinding.ts +120 -0
- package/src/process/daemon/Api.ts +2 -2
- package/src/process/registry/AgentHostRuntime.ts +2 -164
- package/tsconfig.json +2 -1
- package/bin/cli/shared/PluginRuntimeActionCommands.d.ts +0 -14
- package/bin/cli/shared/PluginRuntimeActionCommands.d.ts.map +0 -1
- package/bin/cli/shared/PluginRuntimeActionCommands.js.map +0 -1
- package/bin/cli/shared/PluginRuntimeRemote.js.map +0 -1
- package/bin/cli/shared/PluginRuntimeSupport.d.ts.map +0 -1
- package/bin/control/instant/InstantSessionService.d.ts.map +0 -1
- package/bin/control/instant/InstantSessionService.js.map +0 -1
- package/bin/platform/chatAuthorization/Store.d.ts +0 -31
- package/bin/platform/chatAuthorization/Store.d.ts.map +0 -1
- package/bin/platform/chatAuthorization/Store.js +0 -145
- package/bin/platform/chatAuthorization/Store.js.map +0 -1
- package/bin/process/registry/PluginRuntime.d.ts +0 -24
- package/bin/process/registry/PluginRuntime.d.ts.map +0 -1
- package/bin/process/registry/PluginRuntime.js +0 -31
- package/bin/process/registry/PluginRuntime.js.map +0 -1
- package/src/platform/chatAuthorization/Store.ts +0 -181
- package/src/process/registry/PluginRuntime.ts +0 -42
|
@@ -16,8 +16,7 @@ import {
|
|
|
16
16
|
readDaemonPid,
|
|
17
17
|
stopDaemonProcess,
|
|
18
18
|
} from "@/process/daemon/Manager.js";
|
|
19
|
-
import {
|
|
20
|
-
import { createAgentPlatformRuntime } from "@/process/registry/AgentHostRuntime.js";
|
|
19
|
+
import { assertProjectExecutionModelReady } from "@/model/runtime/ExecutionModelBinding.js";
|
|
21
20
|
import { allocateAvailablePort } from "@/process/daemon/PortAllocator.js";
|
|
22
21
|
import {
|
|
23
22
|
ensureManagedAgentRegistry,
|
|
@@ -469,7 +468,7 @@ export async function prepareForegroundAgent(
|
|
|
469
468
|
|
|
470
469
|
injectAgentContext(cwd);
|
|
471
470
|
const projectRoot = resolve(String(cwd || "."));
|
|
472
|
-
|
|
471
|
+
assertProjectExecutionModelReady(projectRoot);
|
|
473
472
|
|
|
474
473
|
const shouldForeground = options.foreground === true;
|
|
475
474
|
if (!shouldForeground) {
|
|
@@ -181,7 +181,7 @@ export async function discoverProviderModels(params: {
|
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
export { resolveProjectRoot } from "../shared/
|
|
184
|
+
export { resolveProjectRoot } from "../shared/PluginTargetSupport.js";
|
|
185
185
|
|
|
186
186
|
/**
|
|
187
187
|
* 设置项目 `downcity.json.execution.modelId`。
|
package/src/cli/shared/Chat.ts
CHANGED
|
@@ -11,18 +11,16 @@ import path from "node:path";
|
|
|
11
11
|
import prompts from "prompts";
|
|
12
12
|
import type { Command } from "commander";
|
|
13
13
|
import {
|
|
14
|
+
isChatAuthorizationChannel,
|
|
14
15
|
listChatAuthorizationRoles,
|
|
16
|
+
readChatAuthorizationConfigSync,
|
|
15
17
|
resolveAuthorizedUserRole,
|
|
16
|
-
|
|
17
|
-
import { emitCliBlock } from "./CliReporter.js";
|
|
18
|
-
import { parseBoolean } from "./IndexSupport.js";
|
|
19
|
-
import {
|
|
20
|
-
isChatAuthorizationChannel,
|
|
18
|
+
setChatAuthorizationUserRole,
|
|
21
19
|
type ChatAuthorizationChannel,
|
|
22
20
|
type ChatAuthorizationRole,
|
|
23
|
-
} from "@downcity/
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
21
|
+
} from "@downcity/plugins";
|
|
22
|
+
import { emitCliBlock } from "./CliReporter.js";
|
|
23
|
+
import { parseBoolean } from "./IndexSupport.js";
|
|
26
24
|
|
|
27
25
|
type ChatAuthSetOptions = {
|
|
28
26
|
/**
|
|
@@ -141,9 +139,10 @@ export async function runChatAuthSet(params: {
|
|
|
141
139
|
|
|
142
140
|
if (!nextRole) return;
|
|
143
141
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
142
|
+
await setChatAuthorizationUserRole({
|
|
143
|
+
context: {
|
|
144
|
+
rootPath: projectRoot,
|
|
145
|
+
},
|
|
147
146
|
channel: principal.channel,
|
|
148
147
|
userId: principal.userId,
|
|
149
148
|
roleId: nextRole.roleId,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* `city chat` 交互式管理器。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* - 裸 `city chat` 进入 chat
|
|
5
|
+
* - 裸 `city chat` 进入 chat plugin 管理,而不是只输出静态 help。
|
|
6
6
|
* - chat channel account 属于 city 级配置,在这里通过“配置 channel”管理。
|
|
7
7
|
* - agent 只绑定 channel account,不在 agent 流程中维护密钥。
|
|
8
8
|
*/
|
|
@@ -10,23 +10,22 @@
|
|
|
10
10
|
import prompts from "prompts";
|
|
11
11
|
import type { PromptObject } from "prompts";
|
|
12
12
|
import {
|
|
13
|
-
|
|
13
|
+
ChatChannelAccountManager,
|
|
14
14
|
type ChatChannelAccountListItem,
|
|
15
|
-
} from "@downcity/
|
|
15
|
+
} from "@downcity/plugins";
|
|
16
16
|
import { emitCliBlock, emitCliList } from "./CliReporter.js";
|
|
17
|
-
import {
|
|
17
|
+
import { runManagedPluginControlCommand } from "./ManagedPluginRemote.js";
|
|
18
18
|
import type { StoredChannelAccountChannel } from "@downcity/agent";
|
|
19
19
|
import type {
|
|
20
20
|
ChatChannelAccountAction,
|
|
21
21
|
ChatManagerRootAction,
|
|
22
22
|
} from "./ChatManagerTypes.js";
|
|
23
23
|
import { runInteractiveChatAuthSetFlow } from "./ChatAuth.js";
|
|
24
|
-
import { createAgentPlatformRuntime } from "@/process/registry/AgentHostRuntime.js";
|
|
25
24
|
|
|
26
25
|
const CHAT_CHANNELS: StoredChannelAccountChannel[] = ["telegram", "feishu", "qq"];
|
|
27
26
|
|
|
28
|
-
function
|
|
29
|
-
return new
|
|
27
|
+
function createChannelAccountManager(): ChatChannelAccountManager {
|
|
28
|
+
return new ChatChannelAccountManager();
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
function isInteractiveTerminal(): boolean {
|
|
@@ -49,8 +48,8 @@ function formatCredentialSummary(account: ChatChannelAccountListItem): string {
|
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
async function promptRootAction(): Promise<ChatManagerRootAction | null> {
|
|
52
|
-
const
|
|
53
|
-
const accounts = await
|
|
51
|
+
const manager = createChannelAccountManager();
|
|
52
|
+
const accounts = await manager.list();
|
|
54
53
|
const response = (await prompts({
|
|
55
54
|
type: "select",
|
|
56
55
|
name: "action",
|
|
@@ -94,8 +93,8 @@ async function promptRootAction(): Promise<ChatManagerRootAction | null> {
|
|
|
94
93
|
}
|
|
95
94
|
|
|
96
95
|
async function promptChannelAccountAction(): Promise<ChatChannelAccountAction | null> {
|
|
97
|
-
const
|
|
98
|
-
const accounts = await
|
|
96
|
+
const manager = createChannelAccountManager();
|
|
97
|
+
const accounts = await manager.list();
|
|
99
98
|
const response = (await prompts({
|
|
100
99
|
type: "select",
|
|
101
100
|
name: "action",
|
|
@@ -139,8 +138,8 @@ async function promptChannelAccountAction(): Promise<ChatChannelAccountAction |
|
|
|
139
138
|
}
|
|
140
139
|
|
|
141
140
|
async function emitChannelAccountList(): Promise<void> {
|
|
142
|
-
const
|
|
143
|
-
const { items } = await
|
|
141
|
+
const manager = createChannelAccountManager();
|
|
142
|
+
const { items } = await manager.list();
|
|
144
143
|
if (items.length === 0) {
|
|
145
144
|
emitCliBlock({
|
|
146
145
|
tone: "info",
|
|
@@ -182,8 +181,8 @@ async function chooseChannel(): Promise<StoredChannelAccountChannel | null> {
|
|
|
182
181
|
}
|
|
183
182
|
|
|
184
183
|
async function chooseAccount(): Promise<ChatChannelAccountListItem | null> {
|
|
185
|
-
const
|
|
186
|
-
const { items } = await
|
|
184
|
+
const manager = createChannelAccountManager();
|
|
185
|
+
const { items } = await manager.list();
|
|
187
186
|
if (items.length === 0) {
|
|
188
187
|
emitCliBlock({
|
|
189
188
|
tone: "info",
|
|
@@ -296,8 +295,8 @@ async function addChannelAccount(): Promise<void> {
|
|
|
296
295
|
initial: true,
|
|
297
296
|
})) as { probe?: boolean };
|
|
298
297
|
|
|
299
|
-
const
|
|
300
|
-
const result = await
|
|
298
|
+
const manager = createChannelAccountManager();
|
|
299
|
+
const result = await manager.create({
|
|
301
300
|
channel,
|
|
302
301
|
name,
|
|
303
302
|
botToken: input.botToken,
|
|
@@ -324,8 +323,8 @@ async function editChannelAccount(): Promise<void> {
|
|
|
324
323
|
channel: account.channel,
|
|
325
324
|
current: account,
|
|
326
325
|
});
|
|
327
|
-
const
|
|
328
|
-
await
|
|
326
|
+
const manager = createChannelAccountManager();
|
|
327
|
+
await manager.upsert({
|
|
329
328
|
id: account.id,
|
|
330
329
|
channel: account.channel,
|
|
331
330
|
name: String(input.name || account.name).trim(),
|
|
@@ -356,8 +355,8 @@ async function removeChannelAccount(): Promise<void> {
|
|
|
356
355
|
|
|
357
356
|
if (response.remove !== true) return;
|
|
358
357
|
|
|
359
|
-
const
|
|
360
|
-
|
|
358
|
+
const manager = createChannelAccountManager();
|
|
359
|
+
await manager.remove(account.id);
|
|
361
360
|
emitCliBlock({
|
|
362
361
|
tone: "success",
|
|
363
362
|
title: "Channel account removed",
|
|
@@ -403,7 +402,7 @@ async function runChannelAccountManager(): Promise<void> {
|
|
|
403
402
|
async function runChatLifecycleAction(
|
|
404
403
|
action: "start" | "stop" | "restart" | "status",
|
|
405
404
|
): Promise<void> {
|
|
406
|
-
await
|
|
405
|
+
await runManagedPluginControlCommand({
|
|
407
406
|
pluginName: "chat",
|
|
408
407
|
action,
|
|
409
408
|
options: {
|
package/src/cli/shared/Config.ts
CHANGED
|
@@ -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 "./
|
|
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,27 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 受 agent 托管的 plugin action CLI 注册器。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* -
|
|
5
|
+
* - 负责把需要运行中 agent 承载的 plugin actions 挂到 commander(`city <plugin> <action>`)。
|
|
6
6
|
* - 仅处理 CLI 参数映射与远程调用,不承载 plugin 状态机逻辑。
|
|
7
|
-
* -
|
|
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
|
-
|
|
15
|
-
parseScheduledRunAtMsOrThrow,
|
|
14
|
+
parseActionScheduleRunAtMsOrThrow,
|
|
16
15
|
} from "@downcity/agent";
|
|
16
|
+
import { listPluginsWithLifecycle } from "@downcity/agent";
|
|
17
17
|
import type { BasePlugin, PluginAction } from "@downcity/agent";
|
|
18
18
|
import type { JsonObject, JsonValue } from "@downcity/agent";
|
|
19
|
-
import type {
|
|
19
|
+
import type { PluginActionScheduleInput } from "@downcity/agent";
|
|
20
20
|
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 {
|
|
24
|
+
import { runManagedPluginControlCommand } from "./ManagedPluginRemote.js";
|
|
25
25
|
|
|
26
26
|
const CHAT_PLUGIN_HELP_TEXT = [
|
|
27
27
|
"",
|
|
@@ -160,8 +160,8 @@ function hasLongOption(command: Command, longFlag: string): boolean {
|
|
|
160
160
|
*/
|
|
161
161
|
function extractCommandScheduleInput(
|
|
162
162
|
options: Record<string, unknown>,
|
|
163
|
-
):
|
|
164
|
-
const runAtMs =
|
|
163
|
+
): PluginActionScheduleInput | undefined {
|
|
164
|
+
const runAtMs = parseActionScheduleRunAtMsOrThrow({
|
|
165
165
|
delay: options.delay as string | number | undefined,
|
|
166
166
|
time: options.time as string | number | undefined,
|
|
167
167
|
});
|
|
@@ -245,7 +245,7 @@ function registerPluginActionCommand(params: {
|
|
|
245
245
|
})();
|
|
246
246
|
const actionOptions = toPluginActionCommandOpts(allOptions);
|
|
247
247
|
const bridgeOptions = toPluginCliBridgeOptions(allOptions);
|
|
248
|
-
let schedule:
|
|
248
|
+
let schedule: PluginActionScheduleInput | undefined;
|
|
249
249
|
try {
|
|
250
250
|
schedule = extractCommandScheduleInput(allOptions);
|
|
251
251
|
} catch (error) {
|
|
@@ -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/
|
|
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
|
|
386
|
+
await runManagedPluginControlCommand({
|
|
387
387
|
pluginName: params.plugin.name,
|
|
388
388
|
action: item.action,
|
|
389
389
|
options,
|
|
@@ -393,10 +393,13 @@ function registerPluginLifecycleCommands(params: {
|
|
|
393
393
|
}
|
|
394
394
|
|
|
395
395
|
/**
|
|
396
|
-
*
|
|
396
|
+
* 注册所有受 agent 托管的 plugin actions CLI 命令。
|
|
397
397
|
*/
|
|
398
|
-
export function
|
|
399
|
-
|
|
398
|
+
export function registerManagedPluginCommandsForCli(
|
|
399
|
+
program: Command,
|
|
400
|
+
pluginsInput: BasePlugin[],
|
|
401
|
+
): void {
|
|
402
|
+
const plugins = listPluginsWithLifecycle(pluginsInput);
|
|
400
403
|
for (const plugin of plugins) {
|
|
401
404
|
for (const [actionName, action] of Object.entries(plugin.actions)) {
|
|
402
405
|
registerPluginActionCommand({
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* `city plugin` 运行态远程 Agent server 调用辅助。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* - 统一处理
|
|
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
|
-
|
|
16
|
+
PluginStateListResponse,
|
|
17
17
|
} from "@downcity/agent";
|
|
18
18
|
import {
|
|
19
19
|
parseCommandPayload,
|
|
20
20
|
resolvePluginProjectRoot,
|
|
21
21
|
validateAgentProjectRoot,
|
|
22
|
-
} from "./
|
|
22
|
+
} from "./PluginTargetSupport.js";
|
|
23
23
|
|
|
24
24
|
const PLUGIN_COMMAND_TIMEOUT_MS = 120_000;
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
* 执行 `plugin list
|
|
27
|
+
* 执行 `plugin list`。
|
|
28
28
|
*/
|
|
29
|
-
export async function
|
|
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
|
|
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
|
|
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<
|
|
55
|
+
const remote = await callAgentTransport<PluginStateListResponse>({
|
|
56
56
|
projectRoot,
|
|
57
|
-
path: "/api/plugins/
|
|
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
|
|
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
|
|
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
|
|
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/
|
|
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
|
|
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/
|
|
192
|
+
path: "/api/plugins/command",
|
|
193
193
|
method: "POST",
|
|
194
194
|
timeoutMs: PLUGIN_COMMAND_TIMEOUT_MS,
|
|
195
195
|
host: params.options.host,
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
* `city plugin schedule` 命令。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
5
|
+
* - 命令名保留 schedule,是用户侧“延迟执行任务”的操作语义。
|
|
6
|
+
* - 内部使用 Agent 的 ActionScheduleStore,不依赖独立 schedule plugin。
|
|
7
|
+
* - 这里同时承载 schedule 子命令注册与 ActionSchedule 本地存储读写流程。
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
import type { Command } from "commander";
|
|
10
|
-
import {
|
|
11
|
+
import { ActionScheduleStore } from "@downcity/agent";
|
|
11
12
|
import { printResult } from "@/utils/cli/CliOutput.js";
|
|
12
13
|
import type { PluginCliBaseOptions } from "@downcity/agent";
|
|
13
14
|
import {
|
|
@@ -16,7 +17,7 @@ import {
|
|
|
16
17
|
parsePositiveIntOption,
|
|
17
18
|
resolvePluginScheduleProjectRoot,
|
|
18
19
|
validateAgentProjectRoot,
|
|
19
|
-
} from "./
|
|
20
|
+
} from "./PluginTargetSupport.js";
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* 执行 `plugin schedule list`。
|
|
@@ -57,7 +58,7 @@ export async function runPluginScheduleListCommand(params: {
|
|
|
57
58
|
const limit = params.limitRaw
|
|
58
59
|
? parsePositiveIntOption(params.limitRaw, "limit")
|
|
59
60
|
: 100;
|
|
60
|
-
const store = new
|
|
61
|
+
const store = new ActionScheduleStore(projectRoot);
|
|
61
62
|
try {
|
|
62
63
|
const jobs = store.listJobs({ status, limit });
|
|
63
64
|
printResult({
|
|
@@ -132,7 +133,7 @@ export async function runPluginScheduleInfoCommand(params: {
|
|
|
132
133
|
return;
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
const store = new
|
|
136
|
+
const store = new ActionScheduleStore(projectRoot);
|
|
136
137
|
try {
|
|
137
138
|
const job = store.getJobById(jobId);
|
|
138
139
|
if (!job) {
|
|
@@ -205,7 +206,7 @@ export async function runPluginScheduleCancelCommand(params: {
|
|
|
205
206
|
return;
|
|
206
207
|
}
|
|
207
208
|
|
|
208
|
-
const store = new
|
|
209
|
+
const store = new ActionScheduleStore(projectRoot);
|
|
209
210
|
try {
|
|
210
211
|
const current = store.getJobById(jobId);
|
|
211
212
|
if (!current) {
|
|
@@ -264,13 +265,13 @@ export async function runPluginScheduleCancelCommand(params: {
|
|
|
264
265
|
export function registerPluginScheduleCommands(plugin: Command): void {
|
|
265
266
|
const schedule = plugin
|
|
266
267
|
.command("schedule")
|
|
267
|
-
.description("
|
|
268
|
+
.description("查看和管理持久化延迟 action 任务")
|
|
268
269
|
.helpOption("--help", "display help for command");
|
|
269
270
|
|
|
270
271
|
addPluginScheduleOptions(
|
|
271
272
|
schedule
|
|
272
273
|
.command("list")
|
|
273
|
-
.description("列出当前 agent
|
|
274
|
+
.description("列出当前 agent 的延迟 action 任务")
|
|
274
275
|
.option("--status <status>", "状态过滤(pending|running|succeeded|failed|cancelled)")
|
|
275
276
|
.option("--limit <n>", "返回条数(默认 100)"),
|
|
276
277
|
).action(async (opts: PluginCliBaseOptions & { status?: string; limit?: string }) => {
|
|
@@ -284,7 +285,7 @@ export function registerPluginScheduleCommands(plugin: Command): void {
|
|
|
284
285
|
addPluginScheduleOptions(
|
|
285
286
|
schedule
|
|
286
287
|
.command("info <jobId>")
|
|
287
|
-
.description("
|
|
288
|
+
.description("查看单个延迟 action 任务详情"),
|
|
288
289
|
).action(async (jobId: string, opts: PluginCliBaseOptions) => {
|
|
289
290
|
await runPluginScheduleInfoCommand({
|
|
290
291
|
jobId,
|
|
@@ -295,7 +296,7 @@ export function registerPluginScheduleCommands(plugin: Command): void {
|
|
|
295
296
|
addPluginScheduleOptions(
|
|
296
297
|
schedule
|
|
297
298
|
.command("cancel <jobId>")
|
|
298
|
-
.description("
|
|
299
|
+
.description("取消一个尚未执行的延迟 action 任务"),
|
|
299
300
|
).action(async (jobId: string, opts: PluginCliBaseOptions) => {
|
|
300
301
|
await runPluginScheduleCancelCommand({
|
|
301
302
|
jobId,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* `city plugin` 运行态命令共享辅助 + Agent 预检。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* - 统一承载 runtime
|
|
5
|
+
* - 统一承载 plugin runtime 命令的参数解析、目标 agent 路径解析与项目目录校验。
|
|
6
6
|
* - 提供 `checkAgentPreflight` 供 start/restart/status 等命令统一使用。
|
|
7
7
|
* - 保持 command 注册层只关注命令树,不再直接承载路径解析细节。
|
|
8
8
|
*/
|
|
@@ -13,14 +13,13 @@ import type { Command } from "commander";
|
|
|
13
13
|
import { getProfileMdPath, getDowncityJsonPath } from "@/config/Paths.js";
|
|
14
14
|
import { listManagedAgentEntries } from "@/process/registry/CityRegistry.js";
|
|
15
15
|
import { isCityRunning } from "@/process/registry/CityRuntime.js";
|
|
16
|
-
import { ensureRuntimeExecutionBindingReady } from "@downcity/agent";
|
|
17
16
|
import type { JsonValue } from "@downcity/agent";
|
|
18
17
|
import { parsePort, resolveAgentName } from "./IndexSupport.js";
|
|
19
18
|
import { CliError } from "./CliError.js";
|
|
20
|
-
import type {
|
|
19
|
+
import type { ActionScheduleJobStatus } from "@downcity/agent";
|
|
21
20
|
import type { PluginCliBaseOptions } from "@downcity/agent";
|
|
22
21
|
import { parseBoolean } from "./IndexSupport.js";
|
|
23
|
-
import {
|
|
22
|
+
import { assertProjectExecutionModelReady } from "@/model/runtime/ExecutionModelBinding.js";
|
|
24
23
|
|
|
25
24
|
export function isRegistryEntryRunning(
|
|
26
25
|
entry: { status?: "running" | "stopped" },
|
|
@@ -77,7 +76,7 @@ export async function checkAgentPreflight(
|
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
// 关键点(中文):提前校验 execution binding,避免"启动成功后秒退"。
|
|
80
|
-
|
|
79
|
+
assertProjectExecutionModelReady(projectRoot);
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
/**
|
|
@@ -96,7 +95,7 @@ export function parsePositiveIntOption(value: string, fieldName: string): number
|
|
|
96
95
|
*/
|
|
97
96
|
export function normalizeScheduledJobStatus(
|
|
98
97
|
value: string | undefined,
|
|
99
|
-
):
|
|
98
|
+
): ActionScheduleJobStatus | undefined {
|
|
100
99
|
const text = String(value || "").trim().toLowerCase();
|
|
101
100
|
if (!text) return undefined;
|
|
102
101
|
if (
|
|
@@ -164,7 +163,7 @@ export async function resolveProjectRootByAgentName(agentName: string): Promise<
|
|
|
164
163
|
}
|
|
165
164
|
|
|
166
165
|
/**
|
|
167
|
-
* 统一解析 runtime
|
|
166
|
+
* 统一解析 plugin runtime 命令目标路径(agent 优先于 path)。
|
|
168
167
|
*/
|
|
169
168
|
export async function resolvePluginProjectRoot(options: PluginCliBaseOptions): Promise<{
|
|
170
169
|
projectRoot?: string;
|
|
@@ -206,7 +205,7 @@ export async function resolvePluginProjectRoot(options: PluginCliBaseOptions): P
|
|
|
206
205
|
}
|
|
207
206
|
|
|
208
207
|
/**
|
|
209
|
-
* 解析
|
|
208
|
+
* 解析 ActionSchedule 管理命令目标路径。
|
|
210
209
|
*/
|
|
211
210
|
export async function resolvePluginScheduleProjectRoot(options: PluginCliBaseOptions): Promise<{
|
|
212
211
|
projectRoot?: string;
|
|
@@ -266,7 +265,7 @@ export function addPluginTargetOptions(command: Command): Command {
|
|
|
266
265
|
}
|
|
267
266
|
|
|
268
267
|
/**
|
|
269
|
-
* 注入
|
|
268
|
+
* 注入 ActionSchedule 管理命令通用选项。
|
|
270
269
|
*/
|
|
271
270
|
export function addPluginScheduleOptions(command: Command): Command {
|
|
272
271
|
return command
|