aws-runtime-bridge 1.9.9 → 1.9.20
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/dist/adapter/AcodeSdkAdapter.d.ts +40 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts.map +1 -1
- package/dist/adapter/AcodeSdkAdapter.js +353 -7
- package/dist/adapter/AcodeSdkAdapter.test.js +155 -8
- package/dist/adapter/OpencodeSdkAdapter.d.ts.map +1 -1
- package/dist/adapter/OpencodeSdkAdapter.js +36 -3
- package/dist/adapter/instance-ai-config-resolver.d.ts +49 -0
- package/dist/adapter/instance-ai-config-resolver.d.ts.map +1 -0
- package/dist/adapter/instance-ai-config-resolver.js +46 -0
- package/dist/adapter/types.d.ts +27 -2
- package/dist/adapter/types.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/routes/dashboard.d.ts.map +1 -1
- package/dist/routes/dashboard.js +1092 -8
- package/dist/routes/events.d.ts +7 -0
- package/dist/routes/events.d.ts.map +1 -0
- package/dist/routes/events.js +22 -0
- package/dist/routes/file-browser.d.ts +1 -1
- package/dist/routes/file-browser.d.ts.map +1 -1
- package/dist/routes/file-browser.js +25 -9
- package/dist/routes/file-snapshot.d.ts +10 -0
- package/dist/routes/file-snapshot.d.ts.map +1 -0
- package/dist/routes/file-snapshot.js +156 -0
- package/dist/routes/git.d.ts +10 -0
- package/dist/routes/git.d.ts.map +1 -1
- package/dist/routes/git.js +305 -2
- package/dist/routes/git.test.js +39 -2
- package/dist/routes/instance.js +3 -1
- package/dist/routes/memory.d.ts +3 -0
- package/dist/routes/memory.d.ts.map +1 -1
- package/dist/routes/memory.js +3 -0
- package/dist/routes/terminal.d.ts +2 -1
- package/dist/routes/terminal.d.ts.map +1 -1
- package/dist/routes/terminal.js +378 -41
- package/dist/routes/terminal.test.js +33 -7
- package/dist/services/agent-event-store.d.ts +59 -0
- package/dist/services/agent-event-store.d.ts.map +1 -0
- package/dist/services/agent-event-store.js +68 -0
- package/dist/services/event-delta-pusher.d.ts +40 -0
- package/dist/services/event-delta-pusher.d.ts.map +1 -0
- package/dist/services/event-delta-pusher.js +95 -0
- package/dist/services/fileSnapshotStore.d.ts +96 -0
- package/dist/services/fileSnapshotStore.d.ts.map +1 -0
- package/dist/services/fileSnapshotStore.js +500 -0
- package/dist/services/instance-ai-config-service.d.ts +49 -0
- package/dist/services/instance-ai-config-service.d.ts.map +1 -0
- package/dist/services/instance-ai-config-service.js +174 -0
- package/dist/services/panel-auth.d.ts +23 -0
- package/dist/services/panel-auth.d.ts.map +1 -1
- package/dist/services/panel-auth.js +64 -1
- package/dist/services/ring-buffer.d.ts +67 -0
- package/dist/services/ring-buffer.d.ts.map +1 -0
- package/dist/services/ring-buffer.js +103 -0
- package/dist/services/session-output.d.ts +47 -3
- package/dist/services/session-output.d.ts.map +1 -1
- package/dist/services/session-output.js +112 -2
- package/dist/utils/instance-ai-config-debug-logger.d.ts +37 -0
- package/dist/utils/instance-ai-config-debug-logger.d.ts.map +1 -0
- package/dist/utils/instance-ai-config-debug-logger.js +63 -0
- package/dist/utils/logger.d.ts +18 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +48 -4
- package/package/acode/dist/built-in-file-tools.d.ts +1 -1
- package/package/acode/dist/built-in-file-tools.d.ts.map +1 -1
- package/package/acode/dist/built-in-file-tools.js +5 -3
- package/package/acode/dist/builtins/commandArtifacts.d.ts +8 -1
- package/package/acode/dist/builtins/commandArtifacts.d.ts.map +1 -1
- package/package/acode/dist/builtins/commandArtifacts.js +24 -4
- package/package/acode/dist/builtins/shellCommandResult.d.ts +1 -0
- package/package/acode/dist/builtins/shellCommandResult.d.ts.map +1 -1
- package/package/acode/dist/builtins/shellCommandResult.js +3 -3
- package/package/acode/dist/builtins/shellCommandRunner.d.ts +1 -0
- package/package/acode/dist/builtins/shellCommandRunner.d.ts.map +1 -1
- package/package/acode/dist/builtins/shellCommandRunner.js +1 -0
- package/package/acode/dist/cli.js +2 -0
- package/package/acode/dist/runtime.d.ts.map +1 -1
- package/package/acode/dist/runtime.js +156 -5
- package/package/acode/dist/types.d.ts +1 -0
- package/package/acode/dist/types.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +5 -0
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/agent-client.js +16 -0
- package/package/aws-client-agent-mcp/dist/agent-client.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/context-manager.d.ts +136 -0
- package/package/aws-client-agent-mcp/dist/context-manager.d.ts.map +1 -0
- package/package/aws-client-agent-mcp/dist/context-manager.js +473 -0
- package/package/aws-client-agent-mcp/dist/context-manager.js.map +1 -0
- package/package/aws-client-agent-mcp/dist/context-manager.test.d.ts +6 -0
- package/package/aws-client-agent-mcp/dist/context-manager.test.d.ts.map +1 -0
- package/package/aws-client-agent-mcp/dist/context-manager.test.js +307 -0
- package/package/aws-client-agent-mcp/dist/context-manager.test.js.map +1 -0
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +170 -2
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.js +947 -9
- package/package/aws-client-agent-mcp/dist/mcp-server.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.test.js +103 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.test.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +15 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +62 -2
- package/package/aws-client-agent-mcp/dist/mcp-tools.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts +46 -1
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/memory-store.js +164 -12
- package/package/aws-client-agent-mcp/dist/memory-store.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/memory-tools.d.ts +8 -0
- package/package/aws-client-agent-mcp/dist/memory-tools.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/memory-tools.js +88 -1
- package/package/aws-client-agent-mcp/dist/memory-tools.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts +7 -1
- package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/server-memory-store.js +18 -0
- package/package/aws-client-agent-mcp/dist/server-memory-store.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/types.d.ts +103 -2
- package/package/aws-client-agent-mcp/dist/types.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/types.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.d.ts +27 -2
- package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.js +122 -5
- package/package/aws-client-agent-mcp/dist/websocket-client.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI 配置服务
|
|
3
|
+
*
|
|
4
|
+
* 管理 ACode 实例的 AI provider 配置(model/baseURL/apiKey)。
|
|
5
|
+
* 支持三层来源(api > env > file)仲裁,deep-merge 后写入
|
|
6
|
+
* per-instance acode.json 供 ACode runtime 加载。
|
|
7
|
+
*/
|
|
8
|
+
import fs from "node:fs/promises";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import { getAcodeConfigFile, getRuntimeHomeDir } from "../config.js";
|
|
11
|
+
import { getInstanceAiConfigDebugLogger } from "../utils/instance-ai-config-debug-logger.js";
|
|
12
|
+
// ── 敏感信息脱敏 ─────────────────────────────────────────
|
|
13
|
+
const SENSITIVE_KEYS = new Set([
|
|
14
|
+
"apiKey", "api_key", "apikey",
|
|
15
|
+
"key", "secret", "token", "password",
|
|
16
|
+
]);
|
|
17
|
+
/**
|
|
18
|
+
* 脱敏日志中的敏感字段(apiKey / secret / token / password)。
|
|
19
|
+
* 返回新对象,不修改原对象。
|
|
20
|
+
*/
|
|
21
|
+
export function redactForLog(obj) {
|
|
22
|
+
const result = { ...obj };
|
|
23
|
+
for (const key of Object.keys(result)) {
|
|
24
|
+
if (SENSITIVE_KEYS.has(key)) {
|
|
25
|
+
const val = result[key];
|
|
26
|
+
if (typeof val === "string" && val.length > 0) {
|
|
27
|
+
result[key] = val.length > 8
|
|
28
|
+
? `${val.slice(0, 4)}...${val.slice(-4)}`
|
|
29
|
+
: "***";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else if (typeof result[key] === "object" && result[key] !== null) {
|
|
33
|
+
result[key] = redactForLog(result[key]);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
// ── 配置准备 ─────────────────────────────────────────────
|
|
39
|
+
function loadEnvLayer() {
|
|
40
|
+
return {
|
|
41
|
+
...(process.env.ACODE_MODEL ? { model: process.env.ACODE_MODEL } : {}),
|
|
42
|
+
...(process.env.ACODE_BASE_URL ? { baseURL: process.env.ACODE_BASE_URL } : {}),
|
|
43
|
+
...(process.env.ACODE_API_KEY ? { apiKey: process.env.ACODE_API_KEY } : {}),
|
|
44
|
+
...(process.env.ACODE_EFFORT ? { effort: process.env.ACODE_EFFORT } : {}),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
async function loadFileLayer(acodeConfigPath) {
|
|
48
|
+
try {
|
|
49
|
+
const raw = await fs.readFile(acodeConfigPath, "utf-8");
|
|
50
|
+
const parsed = JSON.parse(raw);
|
|
51
|
+
const provider = parsed.provider;
|
|
52
|
+
const def = provider?.default;
|
|
53
|
+
const opts = def?.options;
|
|
54
|
+
return {
|
|
55
|
+
...(def?.model ? { model: def.model } : {}),
|
|
56
|
+
...(opts?.baseURL || opts?.baseUrl ? { baseURL: opts.baseURL || opts.baseUrl } : {}),
|
|
57
|
+
...(opts?.apiKey ? { apiKey: opts.apiKey } : {}),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return {};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 仲裁来源标签。优先级:api > env > file > default
|
|
66
|
+
*/
|
|
67
|
+
function resolveSourceLabel(key, apiVal, envVal, fileVal) {
|
|
68
|
+
if (apiVal !== undefined)
|
|
69
|
+
return "api";
|
|
70
|
+
if (envVal !== undefined)
|
|
71
|
+
return "env";
|
|
72
|
+
if (fileVal !== undefined)
|
|
73
|
+
return "file";
|
|
74
|
+
return "default";
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 准备 ACode 实例配置。
|
|
78
|
+
*
|
|
79
|
+
* 主流程:
|
|
80
|
+
* 1. 从 apiOverrides(请求体)、env(环境变量)、file(acode.json)三层收集配置
|
|
81
|
+
* 2. 按 api > env > file 优先级仲裁每个字段
|
|
82
|
+
* 3. 将仲裁结果 deep-merge 写入 per-instance acode.json
|
|
83
|
+
* 4. 返回合并后的 config 和 per-instance 文件路径
|
|
84
|
+
*/
|
|
85
|
+
export async function prepareAcodeInstanceConfig(options) {
|
|
86
|
+
const runtimeHome = getRuntimeHomeDir();
|
|
87
|
+
const globalConfigPath = getAcodeConfigFile(runtimeHome);
|
|
88
|
+
const perInstanceDir = path.join(runtimeHome, ".aws-bridge", "instances", options.agentId);
|
|
89
|
+
const perInstanceConfigPath = path.join(perInstanceDir, "acode.json");
|
|
90
|
+
// 收集三层配置
|
|
91
|
+
const apiLayer = options.apiOverrides ?? {};
|
|
92
|
+
const envLayer = loadEnvLayer();
|
|
93
|
+
const fileLayer = await loadFileLayer(globalConfigPath);
|
|
94
|
+
// 逐字段仲裁(api > env > file)
|
|
95
|
+
const model = apiLayer.model ?? envLayer.model ?? fileLayer.model;
|
|
96
|
+
const baseURL = apiLayer.baseURL ?? envLayer.baseURL ?? fileLayer.baseURL;
|
|
97
|
+
const apiKey = apiLayer.apiKey ?? envLayer.apiKey ?? fileLayer.apiKey;
|
|
98
|
+
const effort = apiLayer.effort ?? envLayer.effort;
|
|
99
|
+
const resolvedConfig = {};
|
|
100
|
+
if (model)
|
|
101
|
+
resolvedConfig.model = model;
|
|
102
|
+
if (baseURL)
|
|
103
|
+
resolvedConfig.baseURL = baseURL;
|
|
104
|
+
if (apiKey)
|
|
105
|
+
resolvedConfig.apiKey = apiKey;
|
|
106
|
+
if (effort)
|
|
107
|
+
resolvedConfig.effort = effort;
|
|
108
|
+
const source = {
|
|
109
|
+
model: resolveSourceLabel("model", apiLayer.model, envLayer.model, fileLayer.model),
|
|
110
|
+
baseURL: resolveSourceLabel("baseURL", apiLayer.baseURL, envLayer.baseURL, fileLayer.baseURL),
|
|
111
|
+
apiKey: resolveSourceLabel("apiKey", apiLayer.apiKey, envLayer.apiKey, fileLayer.apiKey),
|
|
112
|
+
effort: resolveSourceLabel("effort", apiLayer.effort, envLayer.effort, undefined),
|
|
113
|
+
};
|
|
114
|
+
// 写入 per-instance acode.json(deep-merge 全局配置 + 仲裁结果)
|
|
115
|
+
const dbg = getInstanceAiConfigDebugLogger();
|
|
116
|
+
try {
|
|
117
|
+
await fs.mkdir(perInstanceDir, { recursive: true });
|
|
118
|
+
// 读取全局 acode.json 作为 base
|
|
119
|
+
let baseConfig = {};
|
|
120
|
+
try {
|
|
121
|
+
const globalRaw = await fs.readFile(globalConfigPath, "utf-8");
|
|
122
|
+
baseConfig = JSON.parse(globalRaw);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// 全局文件不存在则用空对象
|
|
126
|
+
}
|
|
127
|
+
// deep-merge provider.default.options
|
|
128
|
+
const mergedConfig = JSON.parse(JSON.stringify(baseConfig));
|
|
129
|
+
const provider = (mergedConfig.provider ?? {});
|
|
130
|
+
const def = (provider.default ?? {});
|
|
131
|
+
const options_ = (def.options ?? {});
|
|
132
|
+
if (model)
|
|
133
|
+
options_.model = model;
|
|
134
|
+
if (baseURL)
|
|
135
|
+
options_.baseURL = baseURL;
|
|
136
|
+
if (apiKey)
|
|
137
|
+
options_.apiKey = apiKey;
|
|
138
|
+
if (effort)
|
|
139
|
+
options_.effort = effort;
|
|
140
|
+
def.options = options_;
|
|
141
|
+
provider.default = def;
|
|
142
|
+
mergedConfig.provider = provider;
|
|
143
|
+
await fs.writeFile(perInstanceConfigPath, JSON.stringify(mergedConfig, null, 2), "utf-8");
|
|
144
|
+
void dbg.log({
|
|
145
|
+
level: "info",
|
|
146
|
+
category: "apply",
|
|
147
|
+
message: "per-instance acode.json 已写入",
|
|
148
|
+
source: "bridge",
|
|
149
|
+
agentId: options.agentId,
|
|
150
|
+
sessionId: options.sessionId,
|
|
151
|
+
details: {
|
|
152
|
+
perInstanceConfigPath,
|
|
153
|
+
source,
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
159
|
+
void dbg.log({
|
|
160
|
+
level: "error",
|
|
161
|
+
category: "apply",
|
|
162
|
+
message: `per-instance acode.json 写入失败: ${message}`,
|
|
163
|
+
source: "bridge",
|
|
164
|
+
agentId: options.agentId,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
instanceConfig: {
|
|
169
|
+
config: resolvedConfig,
|
|
170
|
+
source,
|
|
171
|
+
},
|
|
172
|
+
perInstanceConfigPath,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
@@ -12,6 +12,14 @@ export declare function createSession(): string;
|
|
|
12
12
|
export declare function validateSession(token: string | undefined | null): boolean;
|
|
13
13
|
/** 销毁指定会话(登出) */
|
|
14
14
|
export declare function destroySession(token: string): void;
|
|
15
|
+
/** 列出所有活跃会话(用于管理面板) */
|
|
16
|
+
export declare function getAllSessions(): Array<{
|
|
17
|
+
token: string;
|
|
18
|
+
createdAt: number;
|
|
19
|
+
lastUsedAt: number;
|
|
20
|
+
}>;
|
|
21
|
+
/** 获取当前活跃会话数 */
|
|
22
|
+
export declare function getActiveSessionCount(): number;
|
|
15
23
|
interface PanelCredentials {
|
|
16
24
|
username: string;
|
|
17
25
|
password: string;
|
|
@@ -22,5 +30,20 @@ export declare function getPanelCredentials(): PanelCredentials;
|
|
|
22
30
|
export declare function validateCredentials(username: string, password: string): boolean;
|
|
23
31
|
/** 清除凭据缓存(配置文件变更后调用) */
|
|
24
32
|
export declare function clearCredentialsCache(): void;
|
|
33
|
+
/**
|
|
34
|
+
* 检查 config.json 中是否已配置过面板凭据(panelUsername/panelPassword)。
|
|
35
|
+
* 用于首次登录引导:如果未配置过(文件不存在或缺少字段),应引导用户设置。
|
|
36
|
+
* 已配置过的场景(包括值正好为 root/root)不再重复引导。
|
|
37
|
+
*/
|
|
38
|
+
export declare function hasConfiguredCredentials(): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* 判断当前凭据是否为默认值 root/root。
|
|
41
|
+
*/
|
|
42
|
+
export declare function isDefaultCredentials(): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* 写入新的面板凭据到 config.json,并更新缓存。
|
|
45
|
+
* 主流程:读取现有配置 → 合并新字段 → 写回文件 → 清缓存。
|
|
46
|
+
*/
|
|
47
|
+
export declare function setPanelCredentials(username: string, password: string): void;
|
|
25
48
|
export {};
|
|
26
49
|
//# sourceMappingURL=panel-auth.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"panel-auth.d.ts","sourceRoot":"","sources":["../../src/services/panel-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAwCH,yBAAyB;AACzB,wBAAgB,aAAa,IAAI,MAAM,CAMtC;AAED,kCAAkC;AAClC,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAWzE;AAED,iBAAiB;AACjB,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAElD;AAID,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AA0BD,mCAAmC;AACnC,wBAAgB,mBAAmB,IAAI,gBAAgB,CAWtD;AAED,cAAc;AACd,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAGT;AAED,wBAAwB;AACxB,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C"}
|
|
1
|
+
{"version":3,"file":"panel-auth.d.ts","sourceRoot":"","sources":["../../src/services/panel-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAwCH,yBAAyB;AACzB,wBAAgB,aAAa,IAAI,MAAM,CAMtC;AAED,kCAAkC;AAClC,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAWzE;AAED,iBAAiB;AACjB,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,uBAAuB;AACvB,wBAAgB,cAAc,IAAI,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAEhG;AAED,gBAAgB;AAChB,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAID,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AA0BD,mCAAmC;AACnC,wBAAgB,mBAAmB,IAAI,gBAAgB,CAWtD;AAED,cAAc;AACd,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAGT;AAED,wBAAwB;AACxB,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CAWlD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAG9C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,IAAI,CA8BN"}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* 会话使用服务端内存存储 + HttpOnly Cookie 实现,无需外部依赖。
|
|
8
8
|
*/
|
|
9
9
|
import { randomUUID } from "node:crypto";
|
|
10
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
10
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
11
11
|
import os from "node:os";
|
|
12
12
|
import path from "node:path";
|
|
13
13
|
import { logger } from "../utils/logger.js";
|
|
@@ -60,6 +60,14 @@ export function validateSession(token) {
|
|
|
60
60
|
export function destroySession(token) {
|
|
61
61
|
sessions.delete(token);
|
|
62
62
|
}
|
|
63
|
+
/** 列出所有活跃会话(用于管理面板) */
|
|
64
|
+
export function getAllSessions() {
|
|
65
|
+
return Array.from(sessions.values());
|
|
66
|
+
}
|
|
67
|
+
/** 获取当前活跃会话数 */
|
|
68
|
+
export function getActiveSessionCount() {
|
|
69
|
+
return sessions.size;
|
|
70
|
+
}
|
|
63
71
|
let cachedCredentials = null;
|
|
64
72
|
function getConfigFilePath() {
|
|
65
73
|
return path.join(os.homedir(), ".aws-bridge", "config.json");
|
|
@@ -103,3 +111,58 @@ export function validateCredentials(username, password) {
|
|
|
103
111
|
export function clearCredentialsCache() {
|
|
104
112
|
cachedCredentials = null;
|
|
105
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* 检查 config.json 中是否已配置过面板凭据(panelUsername/panelPassword)。
|
|
116
|
+
* 用于首次登录引导:如果未配置过(文件不存在或缺少字段),应引导用户设置。
|
|
117
|
+
* 已配置过的场景(包括值正好为 root/root)不再重复引导。
|
|
118
|
+
*/
|
|
119
|
+
export function hasConfiguredCredentials() {
|
|
120
|
+
const configPath = getConfigFilePath();
|
|
121
|
+
if (!existsSync(configPath))
|
|
122
|
+
return false;
|
|
123
|
+
try {
|
|
124
|
+
const raw = readFileSync(configPath, "utf-8");
|
|
125
|
+
const parsed = JSON.parse(raw);
|
|
126
|
+
return !!(parsed.panelUsername && parsed.panelPassword);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* 判断当前凭据是否为默认值 root/root。
|
|
134
|
+
*/
|
|
135
|
+
export function isDefaultCredentials() {
|
|
136
|
+
const creds = getPanelCredentials();
|
|
137
|
+
return creds.username === "root" && creds.password === "root";
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* 写入新的面板凭据到 config.json,并更新缓存。
|
|
141
|
+
* 主流程:读取现有配置 → 合并新字段 → 写回文件 → 清缓存。
|
|
142
|
+
*/
|
|
143
|
+
export function setPanelCredentials(username, password) {
|
|
144
|
+
const configPath = getConfigFilePath();
|
|
145
|
+
const configDir = path.dirname(configPath);
|
|
146
|
+
// 读取现有配置
|
|
147
|
+
let existing = {};
|
|
148
|
+
if (existsSync(configPath)) {
|
|
149
|
+
try {
|
|
150
|
+
existing = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// 配置不可读则从头创建
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
existing.panelUsername = username;
|
|
157
|
+
existing.panelPassword = password;
|
|
158
|
+
// 确保目录存在
|
|
159
|
+
try {
|
|
160
|
+
mkdirSync(configDir, { recursive: true });
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// 目录已存在
|
|
164
|
+
}
|
|
165
|
+
writeFileSync(configPath, JSON.stringify(existing, null, 2), "utf-8");
|
|
166
|
+
clearCredentialsCache();
|
|
167
|
+
logger.info("[panel-auth] 面板凭据已更新");
|
|
168
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 环状缓冲区
|
|
3
|
+
*
|
|
4
|
+
* 提供固定容量的泛型环状缓冲区,支持追加和按条件合并。
|
|
5
|
+
* 当缓冲区满时自动覆盖最旧的元素。
|
|
6
|
+
*/
|
|
7
|
+
export interface RingBufferEntry<T> {
|
|
8
|
+
data: T;
|
|
9
|
+
readonly timestamp: number;
|
|
10
|
+
readonly index: number;
|
|
11
|
+
}
|
|
12
|
+
export type RingBufferSlice<T> = readonly RingBufferEntry<T>[];
|
|
13
|
+
/**
|
|
14
|
+
* 泛型环状缓冲区。
|
|
15
|
+
* 容量固定,写入超过容量后自动覆盖最旧条目。
|
|
16
|
+
* 每个 entry 携带单调递增 index,支持增量查询。
|
|
17
|
+
*/
|
|
18
|
+
export declare class RingBuffer<T> {
|
|
19
|
+
private readonly entries;
|
|
20
|
+
private readonly capacity;
|
|
21
|
+
private nextIndex;
|
|
22
|
+
private totalAppended;
|
|
23
|
+
constructor(capacity: number);
|
|
24
|
+
/**
|
|
25
|
+
* 追加一条记录到缓冲区尾部。
|
|
26
|
+
* 缓冲区满时自动覆盖最旧的记录。
|
|
27
|
+
* @returns 新创建的条目
|
|
28
|
+
*/
|
|
29
|
+
append(item: T): RingBufferEntry<T>;
|
|
30
|
+
/**
|
|
31
|
+
* 按条件追加或合并到最后一条记录。
|
|
32
|
+
* 如果缓冲区非空且 condition 返回 true,将 item 合并到最后一条记录中;
|
|
33
|
+
* 否则直接追加新记录。
|
|
34
|
+
*
|
|
35
|
+
* @param item 待追加的数据
|
|
36
|
+
* @param condition 判断是否与最后一条合并,接收最后一条条目
|
|
37
|
+
* @param merge 合并函数,接收已有数据和新增数据,返回合并结果
|
|
38
|
+
* @returns 被合并或新创建的条目
|
|
39
|
+
*/
|
|
40
|
+
appendOrMerge(item: T, condition: (lastEntry: RingBufferEntry<T>) => boolean, merge: (last: T, next: T) => T): RingBufferEntry<T>;
|
|
41
|
+
/**
|
|
42
|
+
* 返回当前所有条目的快照。
|
|
43
|
+
*/
|
|
44
|
+
slice(): RingBufferSlice<T>;
|
|
45
|
+
/**
|
|
46
|
+
* 返回当前条目数。
|
|
47
|
+
*/
|
|
48
|
+
get size(): number;
|
|
49
|
+
/**
|
|
50
|
+
* 返回最近 N 条记录。
|
|
51
|
+
*/
|
|
52
|
+
getLastN(n: number): RingBufferSlice<T>;
|
|
53
|
+
/**
|
|
54
|
+
* 返回自指定 index(不含)之后的记录。
|
|
55
|
+
* @returns 包含 entries、nextIndex(下一个待分配 index)、oldestIndex(最老条目的 index)
|
|
56
|
+
*/
|
|
57
|
+
getSinceIndex(index: number): {
|
|
58
|
+
entries: RingBufferSlice<T>;
|
|
59
|
+
nextIndex: number;
|
|
60
|
+
oldestIndex: number;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* 清空缓冲区。
|
|
64
|
+
*/
|
|
65
|
+
clear(): void;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=ring-buffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ring-buffer.d.ts","sourceRoot":"","sources":["../../src/services/ring-buffer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,IAAI,EAAE,CAAC,CAAC;IACR,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,SAAS,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;AAE/D;;;;GAIG;AACH,qBAAa,UAAU,CAAC,CAAC;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,aAAa,CAAK;gBAEd,QAAQ,EAAE,MAAM;IAQ5B;;;;OAIG;IACH,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC;IAanC;;;;;;;;;OASG;IACH,aAAa,CACX,IAAI,EAAE,CAAC,EACP,SAAS,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,OAAO,EACrD,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,GAC7B,eAAe,CAAC,CAAC,CAAC;IAWrB;;OAEG;IACH,KAAK,IAAI,eAAe,CAAC,CAAC,CAAC;IAI3B;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC;IAQvC;;;OAGG;IACH,aAAa,CACX,KAAK,EAAE,MAAM,GACZ;QAAE,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE;IAQ1E;;OAEG;IACH,KAAK,IAAI,IAAI;CAKd"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 环状缓冲区
|
|
3
|
+
*
|
|
4
|
+
* 提供固定容量的泛型环状缓冲区,支持追加和按条件合并。
|
|
5
|
+
* 当缓冲区满时自动覆盖最旧的元素。
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* 泛型环状缓冲区。
|
|
9
|
+
* 容量固定,写入超过容量后自动覆盖最旧条目。
|
|
10
|
+
* 每个 entry 携带单调递增 index,支持增量查询。
|
|
11
|
+
*/
|
|
12
|
+
export class RingBuffer {
|
|
13
|
+
constructor(capacity) {
|
|
14
|
+
this.nextIndex = 0;
|
|
15
|
+
this.totalAppended = 0;
|
|
16
|
+
if (capacity <= 0) {
|
|
17
|
+
throw new Error("RingBuffer capacity must be positive");
|
|
18
|
+
}
|
|
19
|
+
this.capacity = capacity;
|
|
20
|
+
this.entries = [];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 追加一条记录到缓冲区尾部。
|
|
24
|
+
* 缓冲区满时自动覆盖最旧的记录。
|
|
25
|
+
* @returns 新创建的条目
|
|
26
|
+
*/
|
|
27
|
+
append(item) {
|
|
28
|
+
const index = this.totalAppended;
|
|
29
|
+
const entry = { data: item, timestamp: Date.now(), index };
|
|
30
|
+
if (this.entries.length < this.capacity) {
|
|
31
|
+
this.entries.push(entry);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
this.entries[this.nextIndex % this.capacity] = entry;
|
|
35
|
+
}
|
|
36
|
+
this.nextIndex++;
|
|
37
|
+
this.totalAppended++;
|
|
38
|
+
return entry;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 按条件追加或合并到最后一条记录。
|
|
42
|
+
* 如果缓冲区非空且 condition 返回 true,将 item 合并到最后一条记录中;
|
|
43
|
+
* 否则直接追加新记录。
|
|
44
|
+
*
|
|
45
|
+
* @param item 待追加的数据
|
|
46
|
+
* @param condition 判断是否与最后一条合并,接收最后一条条目
|
|
47
|
+
* @param merge 合并函数,接收已有数据和新增数据,返回合并结果
|
|
48
|
+
* @returns 被合并或新创建的条目
|
|
49
|
+
*/
|
|
50
|
+
appendOrMerge(item, condition, merge) {
|
|
51
|
+
if (this.entries.length > 0) {
|
|
52
|
+
const lastEntry = this.entries[this.entries.length - 1];
|
|
53
|
+
if (condition(lastEntry)) {
|
|
54
|
+
lastEntry.data = merge(lastEntry.data, item);
|
|
55
|
+
return lastEntry;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return this.append(item);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 返回当前所有条目的快照。
|
|
62
|
+
*/
|
|
63
|
+
slice() {
|
|
64
|
+
return [...this.entries];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 返回当前条目数。
|
|
68
|
+
*/
|
|
69
|
+
get size() {
|
|
70
|
+
return this.entries.length;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 返回最近 N 条记录。
|
|
74
|
+
*/
|
|
75
|
+
getLastN(n) {
|
|
76
|
+
if (n <= 0)
|
|
77
|
+
return [];
|
|
78
|
+
const total = this.entries.length;
|
|
79
|
+
if (total === 0)
|
|
80
|
+
return [];
|
|
81
|
+
const count = Math.min(n, total);
|
|
82
|
+
return this.entries.slice(total - count);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* 返回自指定 index(不含)之后的记录。
|
|
86
|
+
* @returns 包含 entries、nextIndex(下一个待分配 index)、oldestIndex(最老条目的 index)
|
|
87
|
+
*/
|
|
88
|
+
getSinceIndex(index) {
|
|
89
|
+
const oldestIndex = this.entries.length > 0
|
|
90
|
+
? this.entries[0].index
|
|
91
|
+
: this.totalAppended;
|
|
92
|
+
const entries = this.entries.filter((e) => e.index > index);
|
|
93
|
+
return { entries, nextIndex: this.totalAppended, oldestIndex };
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* 清空缓冲区。
|
|
97
|
+
*/
|
|
98
|
+
clear() {
|
|
99
|
+
this.entries.length = 0;
|
|
100
|
+
this.nextIndex = 0;
|
|
101
|
+
this.totalAppended = 0;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -3,8 +3,52 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 管理终端会话的输出缓冲和刷新机制
|
|
5
5
|
*/
|
|
6
|
-
import type
|
|
6
|
+
import { type AxiosResponse } from "axios";
|
|
7
7
|
import type { Session } from "../types.js";
|
|
8
|
+
import { RingBuffer, type RingBufferEntry, type RingBufferSlice } from "./ring-buffer.js";
|
|
9
|
+
/**
|
|
10
|
+
* 桥接侧本地事件的 category 分类。
|
|
11
|
+
* status — 状态变更事件;output — 输出增量事件;question — 询问事件;file_changed — 文件变更事件。
|
|
12
|
+
*/
|
|
13
|
+
export type BridgeEventCategory = "status" | "output" | "question" | "file_changed";
|
|
14
|
+
/**
|
|
15
|
+
* 桥接侧 ring buffer 中存储的事件负载。
|
|
16
|
+
*
|
|
17
|
+
* 记录从 sendStatus / sendOutput / sendQuestionRequest / sendFileChanged
|
|
18
|
+
* 产生的非关键时间线数据,供本地增量查询和调试面板使用。
|
|
19
|
+
*/
|
|
20
|
+
export interface BridgeEventPayload {
|
|
21
|
+
readonly category: BridgeEventCategory;
|
|
22
|
+
readonly agentId: string;
|
|
23
|
+
readonly sessionId: string | null;
|
|
24
|
+
readonly status?: string;
|
|
25
|
+
readonly output?: string;
|
|
26
|
+
readonly seq?: number;
|
|
27
|
+
readonly questions?: unknown[];
|
|
28
|
+
readonly actionType?: string;
|
|
29
|
+
readonly actionLabel?: string;
|
|
30
|
+
readonly actionDetail?: string;
|
|
31
|
+
readonly actionResult?: string;
|
|
32
|
+
readonly actionId?: string;
|
|
33
|
+
readonly inputTokens?: number;
|
|
34
|
+
readonly outputTokens?: number;
|
|
35
|
+
readonly sourceEventType?: string;
|
|
36
|
+
readonly logLevel?: string;
|
|
37
|
+
readonly logCategory?: string;
|
|
38
|
+
readonly workspacePath?: string;
|
|
39
|
+
readonly filePath?: string;
|
|
40
|
+
readonly eventType?: string;
|
|
41
|
+
readonly size?: number;
|
|
42
|
+
}
|
|
43
|
+
/** RingBufferEntry 的便捷导出 */
|
|
44
|
+
export type { RingBufferEntry, RingBufferSlice };
|
|
45
|
+
/**
|
|
46
|
+
* 全局桥接侧事件环状缓冲区。
|
|
47
|
+
*
|
|
48
|
+
* 容量 2000 条,适用于记录非关键状态/输出事件。
|
|
49
|
+
* 通过 sendStatus/sendOutput 自动写入,同时保留原有的 server 回调路径。
|
|
50
|
+
*/
|
|
51
|
+
export declare const bridgeEventBuffer: RingBuffer<BridgeEventPayload>;
|
|
8
52
|
interface RuntimeStatusActionInfo {
|
|
9
53
|
actionType?: string;
|
|
10
54
|
actionLabel?: string;
|
|
@@ -40,7 +84,8 @@ export declare const sessions: Map<string, Session>;
|
|
|
40
84
|
export declare function sendStatus(agentId: string, sessionId: string | null, status: string, actionInfo?: RuntimeStatusActionInfo, usage?: {
|
|
41
85
|
inputTokens: number;
|
|
42
86
|
outputTokens: number;
|
|
43
|
-
|
|
87
|
+
contextLimit?: number;
|
|
88
|
+
}, authOptions?: RuntimeCallbackAuthOptions, timestamp?: number, sourceEventType?: string): Promise<AxiosResponse<unknown> | undefined>;
|
|
44
89
|
/**
|
|
45
90
|
* 发送输出到调度器
|
|
46
91
|
*
|
|
@@ -88,5 +133,4 @@ export declare function scheduleOutputFlush(sessionId: string): void;
|
|
|
88
133
|
* @param sessionId - 会话 ID
|
|
89
134
|
*/
|
|
90
135
|
export declare function flushSessionOutput(sessionId: string): Promise<void>;
|
|
91
|
-
export {};
|
|
92
136
|
//# sourceMappingURL=session-output.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-output.d.ts","sourceRoot":"","sources":["../../src/services/session-output.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"session-output.d.ts","sourceRoot":"","sources":["../../src/services/session-output.ts"],"names":[],"mappings":"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"}
|