@downcity/plugins 1.0.66 → 1.0.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/BuiltinPlugins.d.ts +0 -5
- package/bin/BuiltinPlugins.d.ts.map +1 -1
- package/bin/BuiltinPlugins.js +1 -5
- package/bin/BuiltinPlugins.js.map +1 -1
- package/bin/index.d.ts +0 -2
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js +0 -1
- package/bin/index.js.map +1 -1
- package/bin/task/runtime/TaskRunnerRound.d.ts.map +1 -1
- package/bin/task/runtime/TaskRunnerRound.js +7 -2
- package/bin/task/runtime/TaskRunnerRound.js.map +1 -1
- package/bin/task/runtime/TaskRunnerSession.d.ts.map +1 -1
- package/bin/task/runtime/TaskRunnerSession.js +10 -3
- package/bin/task/runtime/TaskRunnerSession.js.map +1 -1
- package/package.json +4 -3
- package/scripts/unrestricted-sandbox-approval.test.mjs +9 -9
- package/src/BuiltinPlugins.ts +0 -9
- package/src/index.ts +0 -5
- package/src/task/runtime/TaskRunnerRound.ts +15 -5
- package/src/task/runtime/TaskRunnerSession.ts +11 -4
- package/bin/shell/Index.d.ts +0 -9
- package/bin/shell/Index.d.ts.map +0 -1
- package/bin/shell/Index.js +0 -9
- package/bin/shell/Index.js.map +0 -1
- package/bin/shell/ShellPlugin.d.ts +0 -65
- package/bin/shell/ShellPlugin.d.ts.map +0 -1
- package/bin/shell/ShellPlugin.js +0 -175
- package/bin/shell/ShellPlugin.js.map +0 -1
- package/bin/shell/ShellRuntimeTypes.d.ts +0 -160
- package/bin/shell/ShellRuntimeTypes.d.ts.map +0 -1
- package/bin/shell/ShellRuntimeTypes.js +0 -10
- package/bin/shell/ShellRuntimeTypes.js.map +0 -1
- package/bin/shell/runtime/Paths.d.ts +0 -12
- package/bin/shell/runtime/Paths.d.ts.map +0 -1
- package/bin/shell/runtime/Paths.js +0 -21
- package/bin/shell/runtime/Paths.js.map +0 -1
- package/bin/shell/runtime/ShellActionResponse.d.ts +0 -52
- package/bin/shell/runtime/ShellActionResponse.d.ts.map +0 -1
- package/bin/shell/runtime/ShellActionResponse.js +0 -73
- package/bin/shell/runtime/ShellActionResponse.js.map +0 -1
- package/bin/shell/runtime/ShellActionRuntime.d.ts +0 -73
- package/bin/shell/runtime/ShellActionRuntime.d.ts.map +0 -1
- package/bin/shell/runtime/ShellActionRuntime.js +0 -647
- package/bin/shell/runtime/ShellActionRuntime.js.map +0 -1
- package/bin/shell/runtime/ShellActionRuntimeSupport.d.ts +0 -88
- package/bin/shell/runtime/ShellActionRuntimeSupport.d.ts.map +0 -1
- package/bin/shell/runtime/ShellActionRuntimeSupport.js +0 -353
- package/bin/shell/runtime/ShellActionRuntimeSupport.js.map +0 -1
- package/bin/shell/runtime/ShellApprovalRuntime.d.ts +0 -62
- package/bin/shell/runtime/ShellApprovalRuntime.d.ts.map +0 -1
- package/bin/shell/runtime/ShellApprovalRuntime.js +0 -215
- package/bin/shell/runtime/ShellApprovalRuntime.js.map +0 -1
- package/bin/shell/runtime/ShellProcessEvents.d.ts +0 -22
- package/bin/shell/runtime/ShellProcessEvents.d.ts.map +0 -1
- package/bin/shell/runtime/ShellProcessEvents.js +0 -41
- package/bin/shell/runtime/ShellProcessEvents.js.map +0 -1
- package/bin/shell/runtime/ShellRuntimeEnvironment.d.ts +0 -21
- package/bin/shell/runtime/ShellRuntimeEnvironment.d.ts.map +0 -1
- package/bin/shell/runtime/ShellRuntimeEnvironment.js +0 -70
- package/bin/shell/runtime/ShellRuntimeEnvironment.js.map +0 -1
- package/bin/shell/types/ShellPluginOptions.d.ts +0 -103
- package/bin/shell/types/ShellPluginOptions.d.ts.map +0 -1
- package/bin/shell/types/ShellPluginOptions.js +0 -10
- package/bin/shell/types/ShellPluginOptions.js.map +0 -1
- package/src/shell/Index.ts +0 -9
- package/src/shell/ShellPlugin.ts +0 -239
- package/src/shell/ShellRuntimeTypes.ts +0 -168
- package/src/shell/runtime/Paths.ts +0 -28
- package/src/shell/runtime/ShellActionResponse.ts +0 -135
- package/src/shell/runtime/ShellActionRuntime.ts +0 -794
- package/src/shell/runtime/ShellActionRuntimeSupport.ts +0 -477
- package/src/shell/runtime/ShellApprovalRuntime.ts +0 -276
- package/src/shell/runtime/ShellProcessEvents.ts +0 -65
- package/src/shell/runtime/ShellRuntimeEnvironment.ts +0 -71
- package/src/shell/types/ShellPluginOptions.ts +0 -122
package/src/shell/ShellPlugin.ts
DELETED
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ShellPlugin:shell plugin 的类实现。
|
|
3
|
-
*
|
|
4
|
-
* 关键点(中文)
|
|
5
|
-
* - shell session map 与 bound runtime 都归属于 plugin 实例。
|
|
6
|
-
* - agent 持有 ShellPlugin 实例,从而形成 per-agent shell 状态边界。
|
|
7
|
-
* - ShellActionRuntime 只保留纯运行时流程,不再承载模块级单例状态。
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { BasePlugin } from "@downcity/agent/internal/plugin/core/BasePlugin.js";
|
|
11
|
-
import type { PluginActions } from "@downcity/agent/internal/plugin/types/Plugin.js";
|
|
12
|
-
import type { AgentContext } from "@downcity/agent/internal/types/runtime/agent/AgentContext.js";
|
|
13
|
-
import type {
|
|
14
|
-
ShellPluginState,
|
|
15
|
-
ShellSessionRuntimeState,
|
|
16
|
-
} from "@/shell/ShellRuntimeTypes.js";
|
|
17
|
-
import type { ShellPluginOptions } from "@/shell/types/ShellPluginOptions.js";
|
|
18
|
-
import type {
|
|
19
|
-
ShellCloseRequest,
|
|
20
|
-
ShellExecRequest,
|
|
21
|
-
ShellQueryRequest,
|
|
22
|
-
ShellReadRequest,
|
|
23
|
-
ShellStartRequest,
|
|
24
|
-
ShellWaitRequest,
|
|
25
|
-
ShellWriteRequest,
|
|
26
|
-
} from "@downcity/agent/internal/executor/tools/shell/types/ShellPlugin.js";
|
|
27
|
-
import {
|
|
28
|
-
bindShellRuntime,
|
|
29
|
-
closeAllShellSessions,
|
|
30
|
-
closeShellSession,
|
|
31
|
-
createShellPluginState,
|
|
32
|
-
approveShellApproval,
|
|
33
|
-
denyShellApproval,
|
|
34
|
-
execShellCommand,
|
|
35
|
-
getShellSessionStatus,
|
|
36
|
-
listShellApprovals,
|
|
37
|
-
readShellSession,
|
|
38
|
-
startShellSession,
|
|
39
|
-
waitShellSession,
|
|
40
|
-
writeShellSession,
|
|
41
|
-
} from "./runtime/ShellActionRuntime.js";
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Shell plugin 类实现。
|
|
45
|
-
*/
|
|
46
|
-
export class ShellPlugin extends BasePlugin {
|
|
47
|
-
/**
|
|
48
|
-
* plugin 名称。
|
|
49
|
-
*/
|
|
50
|
-
readonly name = "shell";
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* 当前实例持有的 shell 状态对象。
|
|
54
|
-
*/
|
|
55
|
-
private readonly state: ShellPluginState;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* 当前实例暴露的 action 定义表。
|
|
59
|
-
*/
|
|
60
|
-
readonly actions: PluginActions;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* 当前实例持有的 in-memory shell sessions。
|
|
64
|
-
*/
|
|
65
|
-
public readonly sessions: Map<string, ShellSessionRuntimeState>;
|
|
66
|
-
|
|
67
|
-
constructor(options: ShellPluginOptions = {}) {
|
|
68
|
-
super();
|
|
69
|
-
this.state = createShellPluginState(options);
|
|
70
|
-
this.sessions = this.state.sessions;
|
|
71
|
-
this.actions = {
|
|
72
|
-
exec: {
|
|
73
|
-
execute: async (params) => ({
|
|
74
|
-
success: true,
|
|
75
|
-
data: await this.exec(params.context, params.payload as ShellExecRequest),
|
|
76
|
-
}),
|
|
77
|
-
},
|
|
78
|
-
start: {
|
|
79
|
-
execute: async (params) => ({
|
|
80
|
-
success: true,
|
|
81
|
-
data: await this.start(params.context, params.payload as ShellStartRequest),
|
|
82
|
-
}),
|
|
83
|
-
},
|
|
84
|
-
status: {
|
|
85
|
-
execute: async (params) => ({
|
|
86
|
-
success: true,
|
|
87
|
-
data: await this.status(params.context, params.payload as ShellQueryRequest),
|
|
88
|
-
}),
|
|
89
|
-
},
|
|
90
|
-
read: {
|
|
91
|
-
execute: async (params) => ({
|
|
92
|
-
success: true,
|
|
93
|
-
data: await this.read(params.context, params.payload as ShellReadRequest),
|
|
94
|
-
}),
|
|
95
|
-
},
|
|
96
|
-
write: {
|
|
97
|
-
execute: async (params) => ({
|
|
98
|
-
success: true,
|
|
99
|
-
data: await this.write(params.context, params.payload as ShellWriteRequest),
|
|
100
|
-
}),
|
|
101
|
-
},
|
|
102
|
-
wait: {
|
|
103
|
-
execute: async (params) => ({
|
|
104
|
-
success: true,
|
|
105
|
-
data: await this.wait(params.context, params.payload as ShellWaitRequest),
|
|
106
|
-
}),
|
|
107
|
-
},
|
|
108
|
-
close: {
|
|
109
|
-
execute: async (params) => ({
|
|
110
|
-
success: true,
|
|
111
|
-
data: await this.close(params.context, params.payload as ShellCloseRequest),
|
|
112
|
-
}),
|
|
113
|
-
},
|
|
114
|
-
approvals: {
|
|
115
|
-
execute: async () => ({
|
|
116
|
-
success: true,
|
|
117
|
-
data: { approvals: listShellApprovals(this.state) },
|
|
118
|
-
}),
|
|
119
|
-
},
|
|
120
|
-
approve: {
|
|
121
|
-
execute: async (params) => {
|
|
122
|
-
const payload = params.payload as { approvalId?: unknown; approval_id?: unknown };
|
|
123
|
-
const approvalId = String(payload?.approvalId || payload?.approval_id || "").trim();
|
|
124
|
-
if (!approvalId) {
|
|
125
|
-
return { success: false, error: "approvalId is required" };
|
|
126
|
-
}
|
|
127
|
-
const ok = await approveShellApproval(this.state, params.context, approvalId);
|
|
128
|
-
return {
|
|
129
|
-
success: ok,
|
|
130
|
-
data: { approvalId, approved: ok },
|
|
131
|
-
...(ok ? {} : { error: "approval request not found" }),
|
|
132
|
-
};
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
deny: {
|
|
136
|
-
execute: async (params) => {
|
|
137
|
-
const payload = params.payload as { approvalId?: unknown; approval_id?: unknown };
|
|
138
|
-
const approvalId = String(payload?.approvalId || payload?.approval_id || "").trim();
|
|
139
|
-
if (!approvalId) {
|
|
140
|
-
return { success: false, error: "approvalId is required" };
|
|
141
|
-
}
|
|
142
|
-
const ok = await denyShellApproval(this.state, params.context, approvalId);
|
|
143
|
-
return {
|
|
144
|
-
success: ok,
|
|
145
|
-
data: { approvalId, denied: ok },
|
|
146
|
-
...(ok ? {} : { error: "approval request not found" }),
|
|
147
|
-
};
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
this.lifecycle = {
|
|
153
|
-
start: async (context) => {
|
|
154
|
-
bindShellRuntime(this.state, context);
|
|
155
|
-
},
|
|
156
|
-
stop: async () => {
|
|
157
|
-
await closeAllShellSessions(this.state, true);
|
|
158
|
-
for (const session of this.state.sessions.values()) {
|
|
159
|
-
if (session.cleanupTimer) {
|
|
160
|
-
clearTimeout(session.cleanupTimer);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
this.state.sessions.clear();
|
|
164
|
-
this.state.approvals.clear();
|
|
165
|
-
this.state.context = null;
|
|
166
|
-
},
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* 启动一个 shell session。
|
|
172
|
-
*/
|
|
173
|
-
async start(
|
|
174
|
-
context: AgentContext,
|
|
175
|
-
request: ShellStartRequest,
|
|
176
|
-
) {
|
|
177
|
-
return await startShellSession(this.state, context, request);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* 查询 shell session 状态。
|
|
182
|
-
*/
|
|
183
|
-
async status(
|
|
184
|
-
context: AgentContext,
|
|
185
|
-
request: ShellQueryRequest,
|
|
186
|
-
) {
|
|
187
|
-
return await getShellSessionStatus(this.state, context, request);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* 读取 shell session 输出。
|
|
192
|
-
*/
|
|
193
|
-
async read(
|
|
194
|
-
context: AgentContext,
|
|
195
|
-
request: ShellReadRequest,
|
|
196
|
-
) {
|
|
197
|
-
return await readShellSession(this.state, context, request);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* 向 shell session 写入 stdin。
|
|
202
|
-
*/
|
|
203
|
-
async write(
|
|
204
|
-
context: AgentContext,
|
|
205
|
-
request: ShellWriteRequest,
|
|
206
|
-
) {
|
|
207
|
-
return await writeShellSession(this.state, context, request);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* 等待 shell session 状态变化。
|
|
212
|
-
*/
|
|
213
|
-
async wait(
|
|
214
|
-
context: AgentContext,
|
|
215
|
-
request: ShellWaitRequest,
|
|
216
|
-
) {
|
|
217
|
-
return await waitShellSession(this.state, context, request);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* 关闭 shell session。
|
|
222
|
-
*/
|
|
223
|
-
async close(
|
|
224
|
-
context: AgentContext,
|
|
225
|
-
request: ShellCloseRequest,
|
|
226
|
-
) {
|
|
227
|
-
return await closeShellSession(this.state, context, request);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* 执行一次 one-shot shell command。
|
|
232
|
-
*/
|
|
233
|
-
async exec(
|
|
234
|
-
context: AgentContext,
|
|
235
|
-
request: ShellExecRequest,
|
|
236
|
-
) {
|
|
237
|
-
return await execShellCommand(this.state, context, request);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ShellRuntime 类型定义。
|
|
3
|
-
*
|
|
4
|
-
* 关键点(中文)
|
|
5
|
-
* - 这些类型描述 shell plugin runtime 的实例级运行态。
|
|
6
|
-
* - 状态所有权归属于 `ShellPlugin` 实例,而不是模块级单例。
|
|
7
|
-
* - 统一归档到 `src/shell/` 相邻层级,避免继续分散在跨域目录里。
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import type { ChildProcessWithoutNullStreams } from "node:child_process";
|
|
11
|
-
import type { AgentContext } from "@downcity/agent/internal/types/runtime/agent/AgentContext.js";
|
|
12
|
-
import type {
|
|
13
|
-
ShellApprovalStatus,
|
|
14
|
-
ShellApprovalToolName,
|
|
15
|
-
ShellSessionSnapshot,
|
|
16
|
-
} from "@downcity/agent/internal/executor/tools/shell/types/ShellPlugin.js";
|
|
17
|
-
import type { ResolvedShellPluginOptions } from "@/shell/types/ShellPluginOptions.js";
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* unrestricted sandbox 审批运行态。
|
|
21
|
-
*/
|
|
22
|
-
export type ShellApprovalRuntimeState = {
|
|
23
|
-
/**
|
|
24
|
-
* 当前审批请求 ID。
|
|
25
|
-
*/
|
|
26
|
-
approvalId: string;
|
|
27
|
-
/**
|
|
28
|
-
* 关联的 shell_id。
|
|
29
|
-
*/
|
|
30
|
-
shellId: string;
|
|
31
|
-
/**
|
|
32
|
-
* 所属 session/聊天上下文。
|
|
33
|
-
*/
|
|
34
|
-
ownerContextId?: string;
|
|
35
|
-
/**
|
|
36
|
-
* 关联工具名。
|
|
37
|
-
*/
|
|
38
|
-
toolName: ShellApprovalToolName;
|
|
39
|
-
/**
|
|
40
|
-
* 申请执行的命令。
|
|
41
|
-
*
|
|
42
|
-
* 说明(中文)
|
|
43
|
-
* - `shell_write` 使用该字段保存 stdin 写入预览,保持审批队列结构统一。
|
|
44
|
-
*/
|
|
45
|
-
cmd: string;
|
|
46
|
-
/**
|
|
47
|
-
* 审批动作类型。
|
|
48
|
-
*/
|
|
49
|
-
operation: "exec" | "start" | "write";
|
|
50
|
-
/**
|
|
51
|
-
* stdin 写入内容预览;仅 `shell_write` 审批存在。
|
|
52
|
-
*/
|
|
53
|
-
inputPreview?: string;
|
|
54
|
-
/**
|
|
55
|
-
* stdin 写入字符数;仅 `shell_write` 审批存在。
|
|
56
|
-
*/
|
|
57
|
-
inputChars?: number;
|
|
58
|
-
/**
|
|
59
|
-
* 命令执行目录。
|
|
60
|
-
*/
|
|
61
|
-
cwd: string;
|
|
62
|
-
/**
|
|
63
|
-
* 申请原因。
|
|
64
|
-
*/
|
|
65
|
-
reason: string;
|
|
66
|
-
/**
|
|
67
|
-
* 当前审批创建时间。
|
|
68
|
-
*/
|
|
69
|
-
createdAt: number;
|
|
70
|
-
/**
|
|
71
|
-
* 审批超时定时器。
|
|
72
|
-
*/
|
|
73
|
-
timer: NodeJS.Timeout;
|
|
74
|
-
/**
|
|
75
|
-
* 兑现审批结果。
|
|
76
|
-
*/
|
|
77
|
-
resolve: (status: ShellApprovalStatus) => void;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* 单个 shell wait 调用挂起时注册的 waiter。
|
|
82
|
-
*/
|
|
83
|
-
export type ShellSessionWaiter = {
|
|
84
|
-
/**
|
|
85
|
-
* 当前等待完成后的唤醒回调。
|
|
86
|
-
*/
|
|
87
|
-
resolve: () => void;
|
|
88
|
-
/**
|
|
89
|
-
* 当前 waiter 对应的超时定时器。
|
|
90
|
-
*/
|
|
91
|
-
timer: NodeJS.Timeout;
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* 单个 shell session 的内存运行态。
|
|
96
|
-
*/
|
|
97
|
-
export type ShellSessionRuntimeState = {
|
|
98
|
-
/**
|
|
99
|
-
* 当前 shell session 的对外快照。
|
|
100
|
-
*/
|
|
101
|
-
snapshot: ShellSessionSnapshot;
|
|
102
|
-
/**
|
|
103
|
-
* 当前 shell session 对应的子进程句柄。
|
|
104
|
-
*/
|
|
105
|
-
child: ChildProcessWithoutNullStreams;
|
|
106
|
-
/**
|
|
107
|
-
* 当前已缓存的标准输出与标准错误文本。
|
|
108
|
-
*/
|
|
109
|
-
outputText: string;
|
|
110
|
-
/**
|
|
111
|
-
* 当前输出持久化文件路径。
|
|
112
|
-
*/
|
|
113
|
-
outputFilePath: string;
|
|
114
|
-
/**
|
|
115
|
-
* 当前快照持久化文件路径。
|
|
116
|
-
*/
|
|
117
|
-
snapshotFilePath: string;
|
|
118
|
-
/**
|
|
119
|
-
* 串行化文件写入链,避免并发 append 乱序。
|
|
120
|
-
*/
|
|
121
|
-
writeChain: Promise<void>;
|
|
122
|
-
/**
|
|
123
|
-
* 终态后的延迟清理定时器。
|
|
124
|
-
*/
|
|
125
|
-
cleanupTimer: NodeJS.Timeout | null;
|
|
126
|
-
/**
|
|
127
|
-
* 当前挂起等待该 session 状态变化的 waiter 集合。
|
|
128
|
-
*/
|
|
129
|
-
waiters: Set<ShellSessionWaiter>;
|
|
130
|
-
/**
|
|
131
|
-
* 当前 shell 进入终态后的完成 promise。
|
|
132
|
-
*
|
|
133
|
-
* 关键点(中文)
|
|
134
|
-
* - 供 `shell.exec` 这类 one-shot 路径直接等待进程结束。
|
|
135
|
-
* - 这样可以减少对版本轮询的依赖,降低瞬时命令的竞态超时。
|
|
136
|
-
*/
|
|
137
|
-
completionPromise: Promise<void>;
|
|
138
|
-
/**
|
|
139
|
-
* 当前 shell 进入终态时触发的完成回调。
|
|
140
|
-
*/
|
|
141
|
-
resolveCompletion: () => void;
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* `ShellPlugin` 实例级状态。
|
|
146
|
-
*/
|
|
147
|
-
export type ShellPluginState = {
|
|
148
|
-
/**
|
|
149
|
-
* 当前 shell plugin 归一化后的运行参数。
|
|
150
|
-
*/
|
|
151
|
-
options: ResolvedShellPluginOptions;
|
|
152
|
-
/**
|
|
153
|
-
* 当前实例持有的全部 in-memory shell session。
|
|
154
|
-
*/
|
|
155
|
-
sessions: Map<string, ShellSessionRuntimeState>;
|
|
156
|
-
/**
|
|
157
|
-
* 当前实例持有的全部 pending unrestricted sandbox 审批。
|
|
158
|
-
*/
|
|
159
|
-
approvals: Map<string, ShellApprovalRuntimeState>;
|
|
160
|
-
/**
|
|
161
|
-
* 当前实例最近一次启动时绑定的 agent context。
|
|
162
|
-
*
|
|
163
|
-
* 关键点(中文)
|
|
164
|
-
* - 仅用于 shell 自动通知 chat 的回调路径。
|
|
165
|
-
* - 这是实例字段,不再是模块级全局变量。
|
|
166
|
-
*/
|
|
167
|
-
context: AgentContext | null;
|
|
168
|
-
};
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shell service 路径工具。
|
|
3
|
-
*
|
|
4
|
-
* 关键点(中文)
|
|
5
|
-
* - shell 运行产物统一落在 `.downcity/shell/<shellId>/`。
|
|
6
|
-
* - 目录结构简单稳定,便于调试与后续恢复。
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import path from "node:path";
|
|
10
|
-
|
|
11
|
-
export function getShellRootDir(projectRoot: string): string {
|
|
12
|
-
return path.join(projectRoot, ".downcity", "shell");
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function getShellDir(projectRoot: string, shellId: string): string {
|
|
16
|
-
return path.join(getShellRootDir(projectRoot), String(shellId || "").trim());
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function getShellSnapshotPath(
|
|
20
|
-
projectRoot: string,
|
|
21
|
-
shellId: string,
|
|
22
|
-
): string {
|
|
23
|
-
return path.join(getShellDir(projectRoot, shellId), "snapshot.json");
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function getShellOutputPath(projectRoot: string, shellId: string): string {
|
|
27
|
-
return path.join(getShellDir(projectRoot, shellId), "output.log");
|
|
28
|
-
}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shell action 返回结构辅助。
|
|
3
|
-
*
|
|
4
|
-
* 关键点(中文)
|
|
5
|
-
* - 集中处理输出游标、token 近似裁剪与标准 action response。
|
|
6
|
-
* - 这里不读取文件、不修改 session,只基于传入文本构造返回对象。
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { AgentContext } from "@downcity/agent/internal/types/runtime/agent/AgentContext.js";
|
|
10
|
-
import type {
|
|
11
|
-
ShellActionResponse,
|
|
12
|
-
ShellOutputChunk,
|
|
13
|
-
ShellSessionSnapshot,
|
|
14
|
-
} from "@downcity/agent/internal/executor/tools/shell/types/ShellPlugin.js";
|
|
15
|
-
|
|
16
|
-
const DEFAULT_MAX_OUTPUT_CHARS = 12_000;
|
|
17
|
-
const DEFAULT_MAX_OUTPUT_LINES = 200;
|
|
18
|
-
const APPROX_CHARS_PER_TOKEN = 4;
|
|
19
|
-
|
|
20
|
-
function resolveOutputLimits(params: {
|
|
21
|
-
context: AgentContext;
|
|
22
|
-
maxOutputTokens?: number;
|
|
23
|
-
}): {
|
|
24
|
-
maxChars: number;
|
|
25
|
-
maxLines: number;
|
|
26
|
-
} {
|
|
27
|
-
const byTokens =
|
|
28
|
-
typeof params.maxOutputTokens === "number" &&
|
|
29
|
-
Number.isFinite(params.maxOutputTokens) &&
|
|
30
|
-
params.maxOutputTokens > 0
|
|
31
|
-
? Math.max(200, Math.floor(params.maxOutputTokens * APPROX_CHARS_PER_TOKEN))
|
|
32
|
-
: null;
|
|
33
|
-
return {
|
|
34
|
-
maxChars:
|
|
35
|
-
byTokens == null
|
|
36
|
-
? DEFAULT_MAX_OUTPUT_CHARS
|
|
37
|
-
: Math.min(DEFAULT_MAX_OUTPUT_CHARS, byTokens),
|
|
38
|
-
maxLines: DEFAULT_MAX_OUTPUT_LINES,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function splitOutputByLimits(
|
|
43
|
-
text: string,
|
|
44
|
-
maxChars: number,
|
|
45
|
-
maxLines: number,
|
|
46
|
-
): { head: string; tail: string } {
|
|
47
|
-
const limitedByChars = text.slice(0, Math.min(text.length, maxChars));
|
|
48
|
-
let head = limitedByChars;
|
|
49
|
-
if (maxLines > 0) {
|
|
50
|
-
const lines = limitedByChars.split("\n");
|
|
51
|
-
if (lines.length > maxLines) {
|
|
52
|
-
head = lines.slice(0, maxLines).join("\n");
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return {
|
|
56
|
-
head,
|
|
57
|
-
tail: text.slice(head.length),
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* 根据游标与 token 限制构造输出块。
|
|
63
|
-
*/
|
|
64
|
-
export function createOutputChunk(params: {
|
|
65
|
-
/**
|
|
66
|
-
* 当前 shell session 标识。
|
|
67
|
-
*/
|
|
68
|
-
shellId: string;
|
|
69
|
-
/**
|
|
70
|
-
* 当前完整输出文本。
|
|
71
|
-
*/
|
|
72
|
-
outputText: string;
|
|
73
|
-
/**
|
|
74
|
-
* 本次读取起始游标。
|
|
75
|
-
*/
|
|
76
|
-
fromCursor?: number;
|
|
77
|
-
/**
|
|
78
|
-
* 当前 Agent 执行上下文。
|
|
79
|
-
*/
|
|
80
|
-
context: AgentContext;
|
|
81
|
-
/**
|
|
82
|
-
* 输出 token 近似上限。
|
|
83
|
-
*/
|
|
84
|
-
maxOutputTokens?: number;
|
|
85
|
-
}): ShellOutputChunk {
|
|
86
|
-
const fromCursor =
|
|
87
|
-
typeof params.fromCursor === "number" && params.fromCursor >= 0
|
|
88
|
-
? Math.floor(params.fromCursor)
|
|
89
|
-
: 0;
|
|
90
|
-
const available = params.outputText.slice(fromCursor);
|
|
91
|
-
const originalChars = available.length;
|
|
92
|
-
const originalLines = available ? available.split("\n").length : 0;
|
|
93
|
-
const limits = resolveOutputLimits({
|
|
94
|
-
context: params.context,
|
|
95
|
-
maxOutputTokens: params.maxOutputTokens,
|
|
96
|
-
});
|
|
97
|
-
const { head, tail } = splitOutputByLimits(
|
|
98
|
-
available,
|
|
99
|
-
limits.maxChars,
|
|
100
|
-
limits.maxLines,
|
|
101
|
-
);
|
|
102
|
-
return {
|
|
103
|
-
shellId: params.shellId,
|
|
104
|
-
output: head,
|
|
105
|
-
startCursor: fromCursor,
|
|
106
|
-
endCursor: fromCursor + head.length,
|
|
107
|
-
originalChars,
|
|
108
|
-
originalLines,
|
|
109
|
-
hasMoreOutput: tail.length > 0,
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* 构造 shell action 标准返回。
|
|
115
|
-
*/
|
|
116
|
-
export function buildActionResponse(params: {
|
|
117
|
-
/**
|
|
118
|
-
* 当前 shell 快照。
|
|
119
|
-
*/
|
|
120
|
-
shell: ShellSessionSnapshot;
|
|
121
|
-
/**
|
|
122
|
-
* 可选输出块。
|
|
123
|
-
*/
|
|
124
|
-
chunk?: ShellOutputChunk;
|
|
125
|
-
/**
|
|
126
|
-
* 可选人类可读提示。
|
|
127
|
-
*/
|
|
128
|
-
note?: string;
|
|
129
|
-
}): ShellActionResponse {
|
|
130
|
-
return {
|
|
131
|
-
shell: params.shell,
|
|
132
|
-
...(params.chunk ? { chunk: params.chunk } : {}),
|
|
133
|
-
...(params.note ? { note: params.note } : {}),
|
|
134
|
-
};
|
|
135
|
-
}
|