aws-runtime-bridge 1.3.0 → 1.3.1
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 +77 -77
- package/dist/index.js +0 -0
- package/dist/routes/properties.test.js +4 -4
- package/dist/utils/yaml-utils.test.js +129 -129
- package/node_modules/@cc-switch/sdk/README.md +540 -540
- package/node_modules/@cc-switch/sdk/package.json +31 -31
- package/package/aws-client-agent-mcp/README.md +288 -288
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +1 -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 +12 -0
- package/package/aws-client-agent-mcp/dist/agent-client.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/agent-client.test.js +31 -0
- package/package/aws-client-agent-mcp/dist/agent-client.test.js.map +1 -1
- package/package/aws-client-agent-mcp/package.json +52 -52
- package/package/cc-switch-sdk/README.md +540 -540
- package/package/cc-switch-sdk/package.json +31 -31
- package/package.json +78 -78
- package/dist/routes/runtime-mcp-proxy.d.ts +0 -3
- package/dist/routes/runtime-mcp-proxy.d.ts.map +0 -1
- package/dist/routes/runtime-mcp-proxy.js +0 -102
- package/dist/routes/runtime-mcp-proxy.test.d.ts +0 -2
- package/dist/routes/runtime-mcp-proxy.test.d.ts.map +0 -1
- package/dist/routes/runtime-mcp-proxy.test.js +0 -111
- package/node_modules/@cc-switch/sdk/dist/sdk-import.test.d.ts +0 -2
- package/node_modules/@cc-switch/sdk/dist/sdk-import.test.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/sdk-import.test.js +0 -119
- package/package/cc-switch-sdk/dist/sdk-import.test.d.ts +0 -2
- package/package/cc-switch-sdk/dist/sdk-import.test.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/sdk-import.test.js +0 -119
package/README.md
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
# aws-runtime-bridge
|
|
2
|
-
|
|
3
|
-
AgentsWorkStudio 机器实例运行时桥接服务,用于在实例上管理 Agent 运行时、终端、配置与回调通信。
|
|
4
|
-
|
|
5
|
-
## 全局安装
|
|
6
|
-
|
|
7
|
-
从 npm 包安装时:
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install -g aws-runtime-bridge
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
安装脚本会在 macOS、Linux 与常见 Unix 平台自动为 CLI 入口补齐可执行权限;Windows 平台无需 chmod,会自动跳过该步骤。
|
|
14
|
-
|
|
15
|
-
从当前仓库安装时:
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
cd aws-runtime-bridge
|
|
19
|
-
npm install
|
|
20
|
-
npm run build
|
|
21
|
-
npm install -g .
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## 启动
|
|
25
|
-
|
|
26
|
-
首次运行 `awsb` / `aws-bridge` 时,如果不存在 `~/.aws-bridge/config.json`,CLI 会进入交互式配置引导;也可以在提示中选择跳过。跳过时仍会创建配置文件并自动生成随机 `connectionKey`,终端会输出该密钥,请保存后在 server/面板连接此 Bridge 时使用。非交互环境(如 systemd、CI、Docker 后台启动)不会阻塞等待输入,也会自动生成 `connectionKey` 并跳过引导。
|
|
27
|
-
|
|
28
|
-
引导会生成类似下面的配置:
|
|
29
|
-
|
|
30
|
-
```json
|
|
31
|
-
{
|
|
32
|
-
"connectionKey": "gkmzjaznX55..",
|
|
33
|
-
"autoRegisterTargets": [
|
|
34
|
-
{
|
|
35
|
-
"serverUrl": "http://127.0.0.1:8080",
|
|
36
|
-
"instanceName": "至强主机",
|
|
37
|
-
"userKey": "aws_live_crh_g0GGrg5IntODg1sFwnas7qf4yGrcwoisDWPBtd8",
|
|
38
|
-
"registerIp": "127.0.0.1"
|
|
39
|
-
}
|
|
40
|
-
]
|
|
41
|
-
}
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
如需在交互式终端中也强制跳过引导,可设置 `AWS_BRIDGE_SKIP_SETUP=true`;此时仍会生成随机 `connectionKey`。
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
AWS_RUNTIME_BRIDGE_PORT=18081 \
|
|
48
|
-
AWS_RUNTIME_SCHEDULER_BASE_URL=http://your-server-host:7380 \
|
|
49
|
-
AWS_RUNTIME_CALLBACK_TOKEN=replace-with-a-long-random-runtime-callback-token \
|
|
50
|
-
AWS_RUNTIME_HOME_DIR=/opt/agentswork/runtime-home \
|
|
51
|
-
aws-bridge
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
`aws-runtime-bridge` 命令仍作为兼容别名保留。安装 `aws-runtime-bridge` 后,包内会随附
|
|
55
|
-
`aws-client-agent-mcp` 的编译产物;bridge 启动时只负责准备该 MCP 产物,不再在 Agent 启动时默认动态注入 `aws-mcp`。
|
|
56
|
-
|
|
57
|
-
请在面板中为目标运行时安装/配置 MCP;这样 Claude Code、Codex、OpenCode、PTY 等不同启动模式都走一致的持久化 MCP 配置链路。
|
|
58
|
-
|
|
59
|
-
如需使用自定义 MCP 可执行文件,可设置:
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
AWS_CLIENT_AGENT_MCP_COMMAND=/absolute/path/to/aws-client-agent-mcp \
|
|
63
|
-
AWS_CLIENT_AGENT_MCP_ARGS='[]' \
|
|
64
|
-
aws-bridge
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## 关键环境变量
|
|
68
|
-
|
|
69
|
-
| 变量名 | 说明 | 默认值 |
|
|
70
|
-
| --- | --- | --- |
|
|
71
|
-
| `AWS_RUNTIME_BRIDGE_PORT` | Bridge HTTP 端口 | `18081` |
|
|
72
|
-
| `AWS_RUNTIME_SCHEDULER_BASE_URL` | aws-mcp-server 地址 | `http://localhost:8080` |
|
|
73
|
-
| `AWS_RUNTIME_CALLBACK_TOKEN` | 后端调用 bridge 的回调 Token | 无,生产必须显式设置 |
|
|
74
|
-
| `AWS_RUNTIME_HOME_DIR` | Bridge 管理配置与状态的主目录 | 当前用户 Home |
|
|
75
|
-
| `AWS_RUNTIME_CORS_ORIGINS` | 允许访问 bridge 的来源,逗号分隔 | 本地开发地址 |
|
|
76
|
-
|
|
77
|
-
生产环境中,`AWS_RUNTIME_SCHEDULER_BASE_URL` 必须填写机器实例可访问的 `aws-mcp-server` 地址,不能使用容器内的 `localhost`。
|
|
1
|
+
# aws-runtime-bridge
|
|
2
|
+
|
|
3
|
+
AgentsWorkStudio 机器实例运行时桥接服务,用于在实例上管理 Agent 运行时、终端、配置与回调通信。
|
|
4
|
+
|
|
5
|
+
## 全局安装
|
|
6
|
+
|
|
7
|
+
从 npm 包安装时:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g aws-runtime-bridge
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
安装脚本会在 macOS、Linux 与常见 Unix 平台自动为 CLI 入口补齐可执行权限;Windows 平台无需 chmod,会自动跳过该步骤。
|
|
14
|
+
|
|
15
|
+
从当前仓库安装时:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
cd aws-runtime-bridge
|
|
19
|
+
npm install
|
|
20
|
+
npm run build
|
|
21
|
+
npm install -g .
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 启动
|
|
25
|
+
|
|
26
|
+
首次运行 `awsb` / `aws-bridge` 时,如果不存在 `~/.aws-bridge/config.json`,CLI 会进入交互式配置引导;也可以在提示中选择跳过。跳过时仍会创建配置文件并自动生成随机 `connectionKey`,终端会输出该密钥,请保存后在 server/面板连接此 Bridge 时使用。非交互环境(如 systemd、CI、Docker 后台启动)不会阻塞等待输入,也会自动生成 `connectionKey` 并跳过引导。
|
|
27
|
+
|
|
28
|
+
引导会生成类似下面的配置:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"connectionKey": "gkmzjaznX55..",
|
|
33
|
+
"autoRegisterTargets": [
|
|
34
|
+
{
|
|
35
|
+
"serverUrl": "http://127.0.0.1:8080",
|
|
36
|
+
"instanceName": "至强主机",
|
|
37
|
+
"userKey": "aws_live_crh_g0GGrg5IntODg1sFwnas7qf4yGrcwoisDWPBtd8",
|
|
38
|
+
"registerIp": "127.0.0.1"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
如需在交互式终端中也强制跳过引导,可设置 `AWS_BRIDGE_SKIP_SETUP=true`;此时仍会生成随机 `connectionKey`。
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
AWS_RUNTIME_BRIDGE_PORT=18081 \
|
|
48
|
+
AWS_RUNTIME_SCHEDULER_BASE_URL=http://your-server-host:7380 \
|
|
49
|
+
AWS_RUNTIME_CALLBACK_TOKEN=replace-with-a-long-random-runtime-callback-token \
|
|
50
|
+
AWS_RUNTIME_HOME_DIR=/opt/agentswork/runtime-home \
|
|
51
|
+
aws-bridge
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`aws-runtime-bridge` 命令仍作为兼容别名保留。安装 `aws-runtime-bridge` 后,包内会随附
|
|
55
|
+
`aws-client-agent-mcp` 的编译产物;bridge 启动时只负责准备该 MCP 产物,不再在 Agent 启动时默认动态注入 `aws-mcp`。
|
|
56
|
+
|
|
57
|
+
请在面板中为目标运行时安装/配置 MCP;这样 Claude Code、Codex、OpenCode、PTY 等不同启动模式都走一致的持久化 MCP 配置链路。
|
|
58
|
+
|
|
59
|
+
如需使用自定义 MCP 可执行文件,可设置:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
AWS_CLIENT_AGENT_MCP_COMMAND=/absolute/path/to/aws-client-agent-mcp \
|
|
63
|
+
AWS_CLIENT_AGENT_MCP_ARGS='[]' \
|
|
64
|
+
aws-bridge
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 关键环境变量
|
|
68
|
+
|
|
69
|
+
| 变量名 | 说明 | 默认值 |
|
|
70
|
+
| --- | --- | --- |
|
|
71
|
+
| `AWS_RUNTIME_BRIDGE_PORT` | Bridge HTTP 端口 | `18081` |
|
|
72
|
+
| `AWS_RUNTIME_SCHEDULER_BASE_URL` | aws-mcp-server 地址 | `http://localhost:8080` |
|
|
73
|
+
| `AWS_RUNTIME_CALLBACK_TOKEN` | 后端调用 bridge 的回调 Token | 无,生产必须显式设置 |
|
|
74
|
+
| `AWS_RUNTIME_HOME_DIR` | Bridge 管理配置与状态的主目录 | 当前用户 Home |
|
|
75
|
+
| `AWS_RUNTIME_CORS_ORIGINS` | 允许访问 bridge 的来源,逗号分隔 | 本地开发地址 |
|
|
76
|
+
|
|
77
|
+
生产环境中,`AWS_RUNTIME_SCHEDULER_BASE_URL` 必须填写机器实例可访问的 `aws-mcp-server` 地址,不能使用容器内的 `localhost`。
|
package/dist/index.js
CHANGED
|
File without changes
|
|
@@ -41,10 +41,10 @@ describe('properties file operations', () => {
|
|
|
41
41
|
}
|
|
42
42
|
return result;
|
|
43
43
|
};
|
|
44
|
-
const props = parseProperties(`
|
|
45
|
-
# Comment
|
|
46
|
-
agent.role.name=Backend Developer
|
|
47
|
-
project.workspace.path=/home/project
|
|
44
|
+
const props = parseProperties(`
|
|
45
|
+
# Comment
|
|
46
|
+
agent.role.name=Backend Developer
|
|
47
|
+
project.workspace.path=/home/project
|
|
48
48
|
`);
|
|
49
49
|
expect(props['agent.role.name']).toBe('Backend Developer');
|
|
50
50
|
expect(props['project.workspace.path']).toBe('/home/project');
|
|
@@ -12,95 +12,95 @@ describe('yaml-utils', () => {
|
|
|
12
12
|
expect(hasMatchingAgentPath('', 'test')).toBeNull();
|
|
13
13
|
});
|
|
14
14
|
it('should return null when no agent key exists', () => {
|
|
15
|
-
const yaml = `
|
|
16
|
-
other:
|
|
17
|
-
- name: test
|
|
15
|
+
const yaml = `
|
|
16
|
+
other:
|
|
17
|
+
- name: test
|
|
18
18
|
`;
|
|
19
19
|
expect(hasMatchingAgentPath(yaml, 'test')).toBeNull();
|
|
20
20
|
});
|
|
21
21
|
it('should return null when agent is not an array', () => {
|
|
22
|
-
const yaml = `
|
|
23
|
-
agent:
|
|
24
|
-
name: single
|
|
22
|
+
const yaml = `
|
|
23
|
+
agent:
|
|
24
|
+
name: single
|
|
25
25
|
`;
|
|
26
26
|
expect(hasMatchingAgentPath(yaml, 'test')).toBeNull();
|
|
27
27
|
});
|
|
28
28
|
it('should return null when agent has no path', () => {
|
|
29
|
-
const yaml = `
|
|
30
|
-
agent:
|
|
31
|
-
- name: test
|
|
32
|
-
description: no path
|
|
29
|
+
const yaml = `
|
|
30
|
+
agent:
|
|
31
|
+
- name: test
|
|
32
|
+
description: no path
|
|
33
33
|
`;
|
|
34
34
|
expect(hasMatchingAgentPath(yaml, 'test')).toBeNull();
|
|
35
35
|
});
|
|
36
36
|
it('should match exact path', () => {
|
|
37
|
-
const yaml = `
|
|
38
|
-
agent:
|
|
39
|
-
- name: test
|
|
40
|
-
path: src/modules
|
|
37
|
+
const yaml = `
|
|
38
|
+
agent:
|
|
39
|
+
- name: test
|
|
40
|
+
path: src/modules
|
|
41
41
|
`;
|
|
42
42
|
expect(hasMatchingAgentPath(yaml, 'src/modules')).toBe('src/modules');
|
|
43
43
|
});
|
|
44
44
|
it('should match path with different separators (backslash)', () => {
|
|
45
|
-
const yaml = `
|
|
46
|
-
agent:
|
|
47
|
-
- name: test
|
|
48
|
-
path: src/modules
|
|
45
|
+
const yaml = `
|
|
46
|
+
agent:
|
|
47
|
+
- name: test
|
|
48
|
+
path: src/modules
|
|
49
49
|
`;
|
|
50
50
|
expect(hasMatchingAgentPath(yaml, 'src\\modules')).toBe('src/modules');
|
|
51
51
|
});
|
|
52
52
|
it('should match path with forward slash when yaml has backslash', () => {
|
|
53
|
-
const yaml = `
|
|
54
|
-
agent:
|
|
55
|
-
- name: test
|
|
56
|
-
path: src\\modules
|
|
53
|
+
const yaml = `
|
|
54
|
+
agent:
|
|
55
|
+
- name: test
|
|
56
|
+
path: src\\modules
|
|
57
57
|
`;
|
|
58
58
|
expect(hasMatchingAgentPath(yaml, 'src/modules')).toBe('src\\modules');
|
|
59
59
|
});
|
|
60
60
|
it('should match current directory "." path', () => {
|
|
61
|
-
const yaml = `
|
|
62
|
-
agent:
|
|
63
|
-
- name: test
|
|
64
|
-
path: .
|
|
61
|
+
const yaml = `
|
|
62
|
+
agent:
|
|
63
|
+
- name: test
|
|
64
|
+
path: .
|
|
65
65
|
`;
|
|
66
66
|
expect(hasMatchingAgentPath(yaml, '.')).toBe('.');
|
|
67
67
|
});
|
|
68
68
|
it('should match empty path when target is "."', () => {
|
|
69
|
-
const yaml = `
|
|
70
|
-
agent:
|
|
71
|
-
- name: test
|
|
72
|
-
path: ''
|
|
69
|
+
const yaml = `
|
|
70
|
+
agent:
|
|
71
|
+
- name: test
|
|
72
|
+
path: ''
|
|
73
73
|
`;
|
|
74
74
|
expect(hasMatchingAgentPath(yaml, '.')).toBe('');
|
|
75
75
|
});
|
|
76
76
|
it('should return null when no matching path found', () => {
|
|
77
|
-
const yaml = `
|
|
78
|
-
agent:
|
|
79
|
-
- name: test
|
|
80
|
-
path: other/path
|
|
77
|
+
const yaml = `
|
|
78
|
+
agent:
|
|
79
|
+
- name: test
|
|
80
|
+
path: other/path
|
|
81
81
|
`;
|
|
82
82
|
expect(hasMatchingAgentPath(yaml, 'different/path')).toBeNull();
|
|
83
83
|
});
|
|
84
84
|
it('should return first matching path from multiple agents', () => {
|
|
85
|
-
const yaml = `
|
|
86
|
-
agent:
|
|
87
|
-
- name: first
|
|
88
|
-
path: first/path
|
|
89
|
-
- name: second
|
|
90
|
-
path: second/path
|
|
85
|
+
const yaml = `
|
|
86
|
+
agent:
|
|
87
|
+
- name: first
|
|
88
|
+
path: first/path
|
|
89
|
+
- name: second
|
|
90
|
+
path: second/path
|
|
91
91
|
`;
|
|
92
92
|
expect(hasMatchingAgentPath(yaml, 'first/path')).toBe('first/path');
|
|
93
93
|
expect(hasMatchingAgentPath(yaml, 'second/path')).toBe('second/path');
|
|
94
94
|
});
|
|
95
95
|
it('should handle complex YAML with nested objects', () => {
|
|
96
|
-
const yaml = `
|
|
97
|
-
agent:
|
|
98
|
-
- name: complex
|
|
99
|
-
path: complex/path
|
|
100
|
-
project: my-project
|
|
101
|
-
prompt: |
|
|
102
|
-
This is a multi-line
|
|
103
|
-
prompt
|
|
96
|
+
const yaml = `
|
|
97
|
+
agent:
|
|
98
|
+
- name: complex
|
|
99
|
+
path: complex/path
|
|
100
|
+
project: my-project
|
|
101
|
+
prompt: |
|
|
102
|
+
This is a multi-line
|
|
103
|
+
prompt
|
|
104
104
|
`;
|
|
105
105
|
expect(hasMatchingAgentPath(yaml, 'complex/path')).toBe('complex/path');
|
|
106
106
|
});
|
|
@@ -113,12 +113,12 @@ agent:
|
|
|
113
113
|
expect(result.isTemplate).toBe(false);
|
|
114
114
|
});
|
|
115
115
|
it('should return matching agent config', () => {
|
|
116
|
-
const yaml = `
|
|
117
|
-
agent:
|
|
118
|
-
- name: my-agent
|
|
119
|
-
path: src/modules
|
|
120
|
-
project: my-project
|
|
121
|
-
prompt: test prompt
|
|
116
|
+
const yaml = `
|
|
117
|
+
agent:
|
|
118
|
+
- name: my-agent
|
|
119
|
+
path: src/modules
|
|
120
|
+
project: my-project
|
|
121
|
+
prompt: test prompt
|
|
122
122
|
`;
|
|
123
123
|
const result = extractAgentConfigOrTemplate(yaml, 'src/modules');
|
|
124
124
|
expect(result.isTemplate).toBe(false);
|
|
@@ -127,11 +127,11 @@ agent:
|
|
|
127
127
|
expect(result.content).toContain('my-project');
|
|
128
128
|
});
|
|
129
129
|
it('should generate template when no matching agent found', () => {
|
|
130
|
-
const yaml = `
|
|
131
|
-
agent:
|
|
132
|
-
- name: other-agent
|
|
133
|
-
path: other/path
|
|
134
|
-
project: existing-project
|
|
130
|
+
const yaml = `
|
|
131
|
+
agent:
|
|
132
|
+
- name: other-agent
|
|
133
|
+
path: other/path
|
|
134
|
+
project: existing-project
|
|
135
135
|
`;
|
|
136
136
|
const result = extractAgentConfigOrTemplate(yaml, 'new/path');
|
|
137
137
|
expect(result.isTemplate).toBe(true);
|
|
@@ -139,10 +139,10 @@ agent:
|
|
|
139
139
|
expect(result.content).toContain('new/path');
|
|
140
140
|
});
|
|
141
141
|
it('should generate template with empty project when no agents have project', () => {
|
|
142
|
-
const yaml = `
|
|
143
|
-
agent:
|
|
144
|
-
- name: agent1
|
|
145
|
-
path: path1
|
|
142
|
+
const yaml = `
|
|
143
|
+
agent:
|
|
144
|
+
- name: agent1
|
|
145
|
+
path: path1
|
|
146
146
|
`;
|
|
147
147
|
const result = extractAgentConfigOrTemplate(yaml, 'new/path');
|
|
148
148
|
expect(result.isTemplate).toBe(true);
|
|
@@ -150,21 +150,21 @@ agent:
|
|
|
150
150
|
expect(result.content).toContain('project: ""');
|
|
151
151
|
});
|
|
152
152
|
it('should match current directory "." path', () => {
|
|
153
|
-
const yaml = `
|
|
154
|
-
agent:
|
|
155
|
-
- name: root-agent
|
|
156
|
-
path: .
|
|
157
|
-
project: root-project
|
|
153
|
+
const yaml = `
|
|
154
|
+
agent:
|
|
155
|
+
- name: root-agent
|
|
156
|
+
path: .
|
|
157
|
+
project: root-project
|
|
158
158
|
`;
|
|
159
159
|
const result = extractAgentConfigOrTemplate(yaml, '.');
|
|
160
160
|
expect(result.isTemplate).toBe(false);
|
|
161
161
|
expect(result.content).toContain('root-agent');
|
|
162
162
|
});
|
|
163
163
|
it('should normalize path separators in output', () => {
|
|
164
|
-
const yaml = `
|
|
165
|
-
agent:
|
|
166
|
-
- name: test
|
|
167
|
-
path: src\\modules
|
|
164
|
+
const yaml = `
|
|
165
|
+
agent:
|
|
166
|
+
- name: test
|
|
167
|
+
path: src\\modules
|
|
168
168
|
`;
|
|
169
169
|
const result = extractAgentConfigOrTemplate(yaml, 'src/modules');
|
|
170
170
|
expect(result.isTemplate).toBe(false);
|
|
@@ -192,78 +192,78 @@ agent:
|
|
|
192
192
|
expect(autoFillPathInYml(invalidYaml, 'test/path')).toBe(invalidYaml);
|
|
193
193
|
});
|
|
194
194
|
it('should return original content when no agent key', () => {
|
|
195
|
-
const yaml = `
|
|
196
|
-
other:
|
|
197
|
-
- name: test
|
|
195
|
+
const yaml = `
|
|
196
|
+
other:
|
|
197
|
+
- name: test
|
|
198
198
|
`;
|
|
199
199
|
expect(autoFillPathInYml(yaml, 'test/path')).toBe(yaml);
|
|
200
200
|
});
|
|
201
201
|
it('should fill empty path', () => {
|
|
202
|
-
const yaml = `
|
|
203
|
-
agent:
|
|
204
|
-
- name: test
|
|
205
|
-
path: ''
|
|
206
|
-
project: my-project
|
|
202
|
+
const yaml = `
|
|
203
|
+
agent:
|
|
204
|
+
- name: test
|
|
205
|
+
path: ''
|
|
206
|
+
project: my-project
|
|
207
207
|
`;
|
|
208
208
|
const result = autoFillPathInYml(yaml, 'new/path');
|
|
209
209
|
expect(result).toContain('new/path');
|
|
210
210
|
expect(result).not.toContain("path: ''");
|
|
211
211
|
});
|
|
212
212
|
it('should fill undefined path', () => {
|
|
213
|
-
const yaml = `
|
|
214
|
-
agent:
|
|
215
|
-
- name: test
|
|
216
|
-
project: my-project
|
|
213
|
+
const yaml = `
|
|
214
|
+
agent:
|
|
215
|
+
- name: test
|
|
216
|
+
project: my-project
|
|
217
217
|
`;
|
|
218
218
|
const result = autoFillPathInYml(yaml, 'new/path');
|
|
219
219
|
expect(result).toContain('new/path');
|
|
220
220
|
});
|
|
221
221
|
it('should fill null path', () => {
|
|
222
|
-
const yaml = `
|
|
223
|
-
agent:
|
|
224
|
-
- name: test
|
|
225
|
-
path: null
|
|
222
|
+
const yaml = `
|
|
223
|
+
agent:
|
|
224
|
+
- name: test
|
|
225
|
+
path: null
|
|
226
226
|
`;
|
|
227
227
|
const result = autoFillPathInYml(yaml, 'new/path');
|
|
228
228
|
expect(result).toContain('new/path');
|
|
229
229
|
});
|
|
230
230
|
it('should fill whitespace-only path', () => {
|
|
231
|
-
const yaml = `
|
|
232
|
-
agent:
|
|
233
|
-
- name: test
|
|
234
|
-
path: ' '
|
|
231
|
+
const yaml = `
|
|
232
|
+
agent:
|
|
233
|
+
- name: test
|
|
234
|
+
path: ' '
|
|
235
235
|
`;
|
|
236
236
|
const result = autoFillPathInYml(yaml, 'new/path');
|
|
237
237
|
expect(result).toContain('new/path');
|
|
238
238
|
});
|
|
239
239
|
it('should not modify existing non-empty path', () => {
|
|
240
|
-
const yaml = `
|
|
241
|
-
agent:
|
|
242
|
-
- name: test
|
|
243
|
-
path: existing/path
|
|
240
|
+
const yaml = `
|
|
241
|
+
agent:
|
|
242
|
+
- name: test
|
|
243
|
+
path: existing/path
|
|
244
244
|
`;
|
|
245
245
|
const result = autoFillPathInYml(yaml, 'new/path');
|
|
246
246
|
expect(result).toContain('existing/path');
|
|
247
247
|
expect(result).not.toContain('new/path');
|
|
248
248
|
});
|
|
249
249
|
it('should handle multiple agents', () => {
|
|
250
|
-
const yaml = `
|
|
251
|
-
agent:
|
|
252
|
-
- name: agent1
|
|
253
|
-
path: ''
|
|
254
|
-
- name: agent2
|
|
255
|
-
path: existing/path
|
|
256
|
-
- name: agent3
|
|
250
|
+
const yaml = `
|
|
251
|
+
agent:
|
|
252
|
+
- name: agent1
|
|
253
|
+
path: ''
|
|
254
|
+
- name: agent2
|
|
255
|
+
path: existing/path
|
|
256
|
+
- name: agent3
|
|
257
257
|
`;
|
|
258
258
|
const result = autoFillPathInYml(yaml, 'new/path');
|
|
259
259
|
// agent1 should have path filled
|
|
260
260
|
expect(result).toContain('new/path');
|
|
261
261
|
});
|
|
262
262
|
it('should return original content when no modification needed', () => {
|
|
263
|
-
const yaml = `
|
|
264
|
-
agent:
|
|
265
|
-
- name: test
|
|
266
|
-
path: existing/path
|
|
263
|
+
const yaml = `
|
|
264
|
+
agent:
|
|
265
|
+
- name: test
|
|
266
|
+
path: existing/path
|
|
267
267
|
`;
|
|
268
268
|
const result = autoFillPathInYml(yaml, 'new/path');
|
|
269
269
|
expect(result).toBe(yaml);
|
|
@@ -296,11 +296,11 @@ agent:
|
|
|
296
296
|
it('should load config from workspace directory with matching path "."', async () => {
|
|
297
297
|
const configPath = path.join(workspacePath, relativePath);
|
|
298
298
|
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
299
|
-
await fs.writeFile(configPath, `
|
|
300
|
-
agent:
|
|
301
|
-
- name: local-agent
|
|
302
|
-
path: .
|
|
303
|
-
project: local-project
|
|
299
|
+
await fs.writeFile(configPath, `
|
|
300
|
+
agent:
|
|
301
|
+
- name: local-agent
|
|
302
|
+
path: .
|
|
303
|
+
project: local-project
|
|
304
304
|
`, 'utf-8');
|
|
305
305
|
const result = await loadYmlWithUpwardSearch(workspacePath, relativePath);
|
|
306
306
|
expect(result.content).not.toBeNull();
|
|
@@ -312,11 +312,11 @@ agent:
|
|
|
312
312
|
// 在 project/module 目录创建配置,匹配 src 路径
|
|
313
313
|
const parentConfigPath = path.join(tempRoot, 'project', 'module', relativePath);
|
|
314
314
|
await fs.mkdir(path.dirname(parentConfigPath), { recursive: true });
|
|
315
|
-
await fs.writeFile(parentConfigPath, `
|
|
316
|
-
agent:
|
|
317
|
-
- name: module-agent
|
|
318
|
-
path: src
|
|
319
|
-
project: module-project
|
|
315
|
+
await fs.writeFile(parentConfigPath, `
|
|
316
|
+
agent:
|
|
317
|
+
- name: module-agent
|
|
318
|
+
path: src
|
|
319
|
+
project: module-project
|
|
320
320
|
`, 'utf-8');
|
|
321
321
|
const result = await loadYmlWithUpwardSearch(workspacePath, relativePath);
|
|
322
322
|
expect(result.content).not.toBeNull();
|
|
@@ -328,10 +328,10 @@ agent:
|
|
|
328
328
|
// 在 project/module 目录创建配置,但不匹配 src 路径
|
|
329
329
|
const parentConfigPath = path.join(tempRoot, 'project', 'module', relativePath);
|
|
330
330
|
await fs.mkdir(path.dirname(parentConfigPath), { recursive: true });
|
|
331
|
-
await fs.writeFile(parentConfigPath, `
|
|
332
|
-
agent:
|
|
333
|
-
- name: other-agent
|
|
334
|
-
path: other/path
|
|
331
|
+
await fs.writeFile(parentConfigPath, `
|
|
332
|
+
agent:
|
|
333
|
+
- name: other-agent
|
|
334
|
+
path: other/path
|
|
335
335
|
`, 'utf-8');
|
|
336
336
|
const result = await loadYmlWithUpwardSearch(workspacePath, relativePath);
|
|
337
337
|
expect(result.content).not.toBeNull();
|
|
@@ -342,17 +342,17 @@ agent:
|
|
|
342
342
|
// 在 workspace 目录创建匹配的配置
|
|
343
343
|
const localConfigPath = path.join(workspacePath, relativePath);
|
|
344
344
|
await fs.mkdir(path.dirname(localConfigPath), { recursive: true });
|
|
345
|
-
await fs.writeFile(localConfigPath, `
|
|
346
|
-
agent:
|
|
347
|
-
- name: local-agent
|
|
348
|
-
path: .
|
|
345
|
+
await fs.writeFile(localConfigPath, `
|
|
346
|
+
agent:
|
|
347
|
+
- name: local-agent
|
|
348
|
+
path: .
|
|
349
349
|
`, 'utf-8');
|
|
350
350
|
// 在 parent 目录也创建配置
|
|
351
351
|
const parentConfigPath = path.join(tempRoot, 'project', 'module', relativePath);
|
|
352
|
-
await fs.writeFile(parentConfigPath, `
|
|
353
|
-
agent:
|
|
354
|
-
- name: parent-agent
|
|
355
|
-
path: src
|
|
352
|
+
await fs.writeFile(parentConfigPath, `
|
|
353
|
+
agent:
|
|
354
|
+
- name: parent-agent
|
|
355
|
+
path: src
|
|
356
356
|
`, 'utf-8');
|
|
357
357
|
const result = await loadYmlWithUpwardSearch(workspacePath, relativePath);
|
|
358
358
|
// 应该使用 local 的配置,因为更近且匹配
|