aws-runtime-bridge 1.1.11 → 1.2.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.
Files changed (79) hide show
  1. package/dist/adapters/cc-switch/common.d.ts +1 -1
  2. package/dist/adapters/cc-switch/common.d.ts.map +1 -1
  3. package/dist/adapters/cc-switch/index.d.ts +1 -0
  4. package/dist/adapters/cc-switch/index.d.ts.map +1 -1
  5. package/dist/adapters/cc-switch/index.js +5 -5
  6. package/dist/adapters/cc-switch/mcp-claudecode.d.ts.map +1 -1
  7. package/dist/adapters/cc-switch/mcp-claudecode.js +2 -3
  8. package/dist/adapters/cc-switch/mcp-claudecode.test.d.ts +2 -0
  9. package/dist/adapters/cc-switch/mcp-claudecode.test.d.ts.map +1 -0
  10. package/dist/adapters/cc-switch/mcp-claudecode.test.js +74 -0
  11. package/dist/adapters/cc-switch/mcp-opencode.d.ts.map +1 -1
  12. package/dist/adapters/cc-switch/mcp-opencode.js +3 -7
  13. package/dist/adapters/cc-switch/mcp-opencode.test.d.ts +2 -0
  14. package/dist/adapters/cc-switch/mcp-opencode.test.d.ts.map +1 -0
  15. package/dist/adapters/cc-switch/mcp-opencode.test.js +61 -0
  16. package/dist/adapters/cc-switch/skill-claude.d.ts +2 -7
  17. package/dist/adapters/cc-switch/skill-claude.d.ts.map +1 -1
  18. package/dist/adapters/cc-switch/skill-claude.js +3 -83
  19. package/dist/adapters/cc-switch/skill-claudecode.d.ts +2 -7
  20. package/dist/adapters/cc-switch/skill-claudecode.d.ts.map +1 -1
  21. package/dist/adapters/cc-switch/skill-claudecode.js +3 -83
  22. package/dist/adapters/cc-switch/skill-codex.d.ts +5 -0
  23. package/dist/adapters/cc-switch/skill-codex.d.ts.map +1 -0
  24. package/dist/adapters/cc-switch/skill-codex.js +6 -0
  25. package/dist/adapters/cc-switch/skill-directory.d.ts +10 -0
  26. package/dist/adapters/cc-switch/skill-directory.d.ts.map +1 -0
  27. package/dist/adapters/cc-switch/skill-directory.js +137 -0
  28. package/dist/adapters/cc-switch/skill-directory.test.d.ts +2 -0
  29. package/dist/adapters/cc-switch/skill-directory.test.d.ts.map +1 -0
  30. package/dist/adapters/cc-switch/skill-directory.test.js +73 -0
  31. package/dist/adapters/cc-switch/skill-opencode.d.ts +2 -7
  32. package/dist/adapters/cc-switch/skill-opencode.d.ts.map +1 -1
  33. package/dist/adapters/cc-switch/skill-opencode.js +3 -87
  34. package/dist/config.d.ts +2 -0
  35. package/dist/config.d.ts.map +1 -1
  36. package/dist/config.js +5 -0
  37. package/dist/routes/instance.js +4 -5
  38. package/dist/routes/mcp.js +3 -2
  39. package/dist/routes/skills.js +3 -2
  40. package/dist/services/aws-client-agent-mcp.d.ts.map +1 -1
  41. package/dist/services/aws-client-agent-mcp.js +69 -3
  42. package/dist/services/aws-client-agent-mcp.test.js +69 -2
  43. package/dist/services/cc-switch-discovery.test.d.ts +2 -0
  44. package/dist/services/cc-switch-discovery.test.d.ts.map +1 -0
  45. package/dist/services/cc-switch-discovery.test.js +56 -0
  46. package/dist/services/cc-switch-sdk.d.ts +7 -2
  47. package/dist/services/cc-switch-sdk.d.ts.map +1 -1
  48. package/dist/services/cc-switch-sdk.js +15 -5
  49. package/dist/types.d.ts +2 -0
  50. package/dist/types.d.ts.map +1 -1
  51. package/dist/utils/mcp-utils.d.ts.map +1 -1
  52. package/dist/utils/mcp-utils.js +6 -5
  53. package/node_modules/@cc-switch/sdk/dist/constants.d.ts.map +1 -1
  54. package/node_modules/@cc-switch/sdk/dist/constants.js +4 -2
  55. package/node_modules/@cc-switch/sdk/dist/sdk.d.ts.map +1 -1
  56. package/node_modules/@cc-switch/sdk/dist/sdk.js +20 -30
  57. package/node_modules/@cc-switch/sdk/dist/services/mcp-model.d.ts.map +1 -1
  58. package/node_modules/@cc-switch/sdk/dist/services/mcp-model.js +7 -4
  59. package/node_modules/@cc-switch/sdk/dist/services/skill-model.d.ts.map +1 -1
  60. package/node_modules/@cc-switch/sdk/dist/services/skill-model.js +7 -4
  61. package/node_modules/@cc-switch/sdk/dist/types.d.ts +1 -0
  62. package/node_modules/@cc-switch/sdk/dist/types.d.ts.map +1 -1
  63. package/node_modules/@cc-switch/sdk/dist/utils/fs.d.ts +1 -0
  64. package/node_modules/@cc-switch/sdk/dist/utils/fs.d.ts.map +1 -1
  65. package/node_modules/@cc-switch/sdk/dist/utils/fs.js +23 -0
  66. package/package/cc-switch-sdk/dist/constants.d.ts.map +1 -1
  67. package/package/cc-switch-sdk/dist/constants.js +4 -2
  68. package/package/cc-switch-sdk/dist/sdk.d.ts.map +1 -1
  69. package/package/cc-switch-sdk/dist/sdk.js +20 -30
  70. package/package/cc-switch-sdk/dist/services/mcp-model.d.ts.map +1 -1
  71. package/package/cc-switch-sdk/dist/services/mcp-model.js +7 -4
  72. package/package/cc-switch-sdk/dist/services/skill-model.d.ts.map +1 -1
  73. package/package/cc-switch-sdk/dist/services/skill-model.js +7 -4
  74. package/package/cc-switch-sdk/dist/types.d.ts +1 -0
  75. package/package/cc-switch-sdk/dist/types.d.ts.map +1 -1
  76. package/package/cc-switch-sdk/dist/utils/fs.d.ts +1 -0
  77. package/package/cc-switch-sdk/dist/utils/fs.d.ts.map +1 -1
  78. package/package/cc-switch-sdk/dist/utils/fs.js +23 -0
  79. package/package.json +1 -1
@@ -0,0 +1,137 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ async function ensureDir(dir) {
4
+ await fs.mkdir(dir, { recursive: true });
5
+ }
6
+ async function pathExists(target) {
7
+ try {
8
+ await fs.access(target);
9
+ return true;
10
+ }
11
+ catch (error) {
12
+ if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {
13
+ return false;
14
+ }
15
+ return false;
16
+ }
17
+ }
18
+ async function removeIfExists(target) {
19
+ await fs.rm(target, { recursive: true, force: true });
20
+ }
21
+ async function copyDir(source, target) {
22
+ await ensureDir(target);
23
+ const entries = await fs.readdir(source, { withFileTypes: true });
24
+ for (const entry of entries) {
25
+ const srcPath = path.join(source, entry.name);
26
+ const tgtPath = path.join(target, entry.name);
27
+ if (entry.isDirectory()) {
28
+ await copyDir(srcPath, tgtPath);
29
+ continue;
30
+ }
31
+ if (entry.isSymbolicLink()) {
32
+ const linkTarget = await fs.readlink(srcPath);
33
+ await fs.symlink(linkTarget, tgtPath, 'junction');
34
+ continue;
35
+ }
36
+ if (entry.isFile()) {
37
+ await fs.copyFile(srcPath, tgtPath);
38
+ }
39
+ }
40
+ }
41
+ function parseYamlStringValue(raw) {
42
+ const trimmed = raw.trim();
43
+ if (!trimmed) {
44
+ return undefined;
45
+ }
46
+ if ((trimmed.startsWith('"') && trimmed.endsWith('"')) ||
47
+ (trimmed.startsWith("'") && trimmed.endsWith("'"))) {
48
+ return trimmed.slice(1, -1).trim();
49
+ }
50
+ return trimmed;
51
+ }
52
+ function fallbackNameFromDirectory(directory) {
53
+ return path.basename(directory).replace(/\.skill$/, '').replace(/[-_]/g, ' ');
54
+ }
55
+ async function parseSkillMetadata(directory) {
56
+ const skillFile = path.join(directory, 'SKILL.md');
57
+ if (!(await pathExists(skillFile))) {
58
+ return null;
59
+ }
60
+ const raw = (await fs.readFile(skillFile, 'utf-8')).replace(/^\uFEFF/, '');
61
+ const metadata = {};
62
+ if (raw.startsWith('---')) {
63
+ const end = raw.indexOf('\n---', 3);
64
+ if (end >= 0) {
65
+ const frontMatter = raw.slice(3, end).split(/\r?\n/);
66
+ for (const line of frontMatter) {
67
+ const match = line.match(/^\s*(name|description)\s*:\s*(.*)$/);
68
+ if (!match) {
69
+ continue;
70
+ }
71
+ const value = parseYamlStringValue(match[2]);
72
+ if (value) {
73
+ metadata[match[1]] = value;
74
+ }
75
+ }
76
+ }
77
+ }
78
+ return {
79
+ name: metadata.name || fallbackNameFromDirectory(directory),
80
+ description: metadata.description,
81
+ };
82
+ }
83
+ async function materializeSkillDir(sourceDir, targetDir, method) {
84
+ await removeIfExists(targetDir);
85
+ await ensureDir(path.dirname(targetDir));
86
+ if (method === 'copy') {
87
+ await copyDir(sourceDir, targetDir);
88
+ return;
89
+ }
90
+ if (method === 'symlink') {
91
+ await fs.symlink(sourceDir, targetDir, 'junction');
92
+ return;
93
+ }
94
+ try {
95
+ await fs.symlink(sourceDir, targetDir, 'junction');
96
+ }
97
+ catch {
98
+ await copyDir(sourceDir, targetDir);
99
+ }
100
+ }
101
+ export class DirectorySkillAdapter {
102
+ constructor(appId, skillsDir) {
103
+ this.appId = appId;
104
+ this.skillsDir = skillsDir;
105
+ }
106
+ async importSkills() {
107
+ await ensureDir(this.skillsDir);
108
+ const entries = await fs.readdir(this.skillsDir, { withFileTypes: true });
109
+ const skills = [];
110
+ for (const entry of entries) {
111
+ if (entry.name.startsWith('.') ||
112
+ (!entry.isDirectory() && !entry.isSymbolicLink())) {
113
+ continue;
114
+ }
115
+ const directory = path.join(this.skillsDir, entry.name);
116
+ const metadata = await parseSkillMetadata(directory);
117
+ if (!metadata) {
118
+ continue;
119
+ }
120
+ skills.push({
121
+ id: `skill_import_${this.appId}_${entry.name}`,
122
+ name: metadata.name,
123
+ directory,
124
+ description: metadata.description,
125
+ });
126
+ }
127
+ return skills;
128
+ }
129
+ async syncSkill(skill, sourceDir, method) {
130
+ const targetDir = path.join(this.skillsDir, skill.name);
131
+ await materializeSkillDir(sourceDir, targetDir, method);
132
+ }
133
+ async removeSkill(skill) {
134
+ const targetDir = path.join(this.skillsDir, skill.name);
135
+ await removeIfExists(targetDir);
136
+ }
137
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=skill-directory.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-directory.test.d.ts","sourceRoot":"","sources":["../../../src/adapters/cc-switch/skill-directory.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,73 @@
1
+ import { mkdir, mkdtemp, readFile, rm, symlink, writeFile } from 'node:fs/promises';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
+ import { DirectorySkillAdapter } from './skill-directory.js';
6
+ let tempDir;
7
+ let skillsDir;
8
+ async function writeSkill(directory, body) {
9
+ await mkdir(directory, { recursive: true });
10
+ await writeFile(path.join(directory, 'SKILL.md'), body, 'utf-8');
11
+ }
12
+ function buildSkill(name = 'frontend-design') {
13
+ return {
14
+ id: 'skill_test',
15
+ name,
16
+ directory: path.join(tempDir, 'source'),
17
+ description: 'A design skill',
18
+ apps: {
19
+ claude: false,
20
+ claudecode: true,
21
+ codex: false,
22
+ gemini: false,
23
+ opencode: false,
24
+ openclaw: false,
25
+ },
26
+ installedAt: Date.now(),
27
+ };
28
+ }
29
+ beforeEach(async () => {
30
+ tempDir = await mkdtemp(path.join(os.tmpdir(), 'skill-directory-adapter-'));
31
+ skillsDir = path.join(tempDir, 'skills');
32
+ });
33
+ afterEach(async () => {
34
+ await rm(tempDir, { recursive: true, force: true });
35
+ });
36
+ describe('DirectorySkillAdapter', () => {
37
+ it('imports only skill directories with SKILL.md and parses front matter', async () => {
38
+ await writeSkill(path.join(skillsDir, 'frontend-design'), '---\nname: Frontend Design\ndescription: Polished UI work\n---\n# Skill\n');
39
+ await mkdir(path.join(skillsDir, 'ordinary-folder'), { recursive: true });
40
+ await writeSkill(path.join(skillsDir, '.hidden-skill'), '---\nname: Hidden\n---\n');
41
+ const adapter = new DirectorySkillAdapter('claudecode', skillsDir);
42
+ const imported = await adapter.importSkills();
43
+ expect(imported).toHaveLength(1);
44
+ expect(imported[0]).toMatchObject({
45
+ id: 'skill_import_claudecode_frontend-design',
46
+ name: 'Frontend Design',
47
+ description: 'Polished UI work',
48
+ directory: path.join(skillsDir, 'frontend-design'),
49
+ });
50
+ });
51
+ it('imports symlinked skill directories', async () => {
52
+ const source = path.join(tempDir, 'linked-source');
53
+ await writeSkill(source, '---\nname: Linked Skill\n---\n# Skill\n');
54
+ await mkdir(skillsDir, { recursive: true });
55
+ await symlink(source, path.join(skillsDir, 'linked-skill'), 'junction');
56
+ const adapter = new DirectorySkillAdapter('opencode', skillsDir);
57
+ const imported = await adapter.importSkills();
58
+ expect(imported).toHaveLength(1);
59
+ expect(imported[0]?.name).toBe('Linked Skill');
60
+ });
61
+ it('syncs and removes skill directories', async () => {
62
+ const source = path.join(tempDir, 'source');
63
+ await writeSkill(source, '# Skill\n');
64
+ await writeFile(path.join(source, 'README.md'), 'hello', 'utf-8');
65
+ const adapter = new DirectorySkillAdapter('codex', skillsDir);
66
+ await adapter.syncSkill(buildSkill('copied-skill'), source, 'copy');
67
+ const copiedReadme = await readFile(path.join(skillsDir, 'copied-skill', 'README.md'), 'utf-8');
68
+ expect(copiedReadme).toBe('hello');
69
+ await adapter.removeSkill(buildSkill('copied-skill'));
70
+ const imported = await adapter.importSkills();
71
+ expect(imported).toHaveLength(0);
72
+ });
73
+ });
@@ -3,13 +3,8 @@
3
3
  *
4
4
  * 实现 ISkillAdapter 接口,负责 OpenCode 的 Skill 目录管理
5
5
  */
6
- import type { ISkillAdapter, InstalledSkill, SkillSyncMethod } from '@cc-switch/sdk';
7
- export declare class OpenCodeSkillAdapter implements ISkillAdapter {
8
- private readonly skillsDir;
9
- readonly appId: "opencode";
6
+ import { DirectorySkillAdapter } from './skill-directory.js';
7
+ export declare class OpenCodeSkillAdapter extends DirectorySkillAdapter {
10
8
  constructor(skillsDir: string);
11
- importSkills(): Promise<Array<Pick<InstalledSkill, "id" | "name" | "directory" | "description">>>;
12
- syncSkill(skill: InstalledSkill, sourceDir: string, method: SkillSyncMethod): Promise<void>;
13
- removeSkill(skill: InstalledSkill): Promise<void>;
14
9
  }
15
10
  //# sourceMappingURL=skill-opencode.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skill-opencode.d.ts","sourceRoot":"","sources":["../../../src/adapters/cc-switch/skill-opencode.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAwErF,qBAAa,oBAAqB,YAAW,aAAa;IAG5C,OAAO,CAAC,QAAQ,CAAC,SAAS;IAFtC,SAAgB,KAAK,EAAG,UAAU,CAAU;gBAEf,SAAS,EAAE,MAAM;IAExC,YAAY,IAAI,OAAO,CAC3B,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,GAAG,MAAM,GAAG,WAAW,GAAG,aAAa,CAAC,CAAC,CACzE;IAmBK,SAAS,CACb,KAAK,EAAE,cAAc,EACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,IAAI,CAAC;IAMV,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAKxD"}
1
+ {"version":3,"file":"skill-opencode.d.ts","sourceRoot":"","sources":["../../../src/adapters/cc-switch/skill-opencode.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,qBAAa,oBAAqB,SAAQ,qBAAqB;gBACjD,SAAS,EAAE,MAAM;CAG9B"}
@@ -3,93 +3,9 @@
3
3
  *
4
4
  * 实现 ISkillAdapter 接口,负责 OpenCode 的 Skill 目录管理
5
5
  */
6
- async function ensureDir(dir) {
7
- const fs = await import('node:fs/promises');
8
- await fs.mkdir(dir, { recursive: true });
9
- }
10
- async function removeIfExists(target) {
11
- const fs = await import('node:fs/promises');
12
- try {
13
- await fs.rm(target, { recursive: true, force: true });
14
- }
15
- catch {
16
- // ignore
17
- }
18
- }
19
- async function copyDir(source, target) {
20
- const fs = await import('node:fs/promises');
21
- const path = await import('node:path');
22
- await ensureDir(target);
23
- const entries = await fs.readdir(source, { withFileTypes: true });
24
- for (const entry of entries) {
25
- const srcPath = path.join(source, entry.name);
26
- const tgtPath = path.join(target, entry.name);
27
- if (entry.isDirectory()) {
28
- await copyDir(srcPath, tgtPath);
29
- }
30
- else {
31
- await fs.copyFile(srcPath, tgtPath);
32
- }
33
- }
34
- }
35
- /**
36
- * 从路径提取 skill 名称
37
- */
38
- function toNameFromPath(pathStr) {
39
- const base = pathStr.split(/[/\\]/).pop() || pathStr;
40
- return base.replace(/\.skill$/, '').replace(/[-_]/g, ' ');
41
- }
42
- async function materializeSkillDir(sourceDir, targetDir, method) {
43
- const fs = await import('node:fs/promises');
44
- const path = await import('node:path');
45
- await removeIfExists(targetDir);
46
- await ensureDir(path.dirname(targetDir));
47
- if (method === "copy") {
48
- await copyDir(sourceDir, targetDir);
49
- return;
50
- }
51
- if (method === "symlink") {
52
- await fs.symlink(sourceDir, targetDir, "junction");
53
- return;
54
- }
55
- // auto: 先尝试 symlink,失败则 copy
56
- try {
57
- await fs.symlink(sourceDir, targetDir, "junction");
58
- }
59
- catch {
60
- await copyDir(sourceDir, targetDir);
61
- }
62
- }
63
- export class OpenCodeSkillAdapter {
6
+ import { DirectorySkillAdapter } from './skill-directory.js';
7
+ export class OpenCodeSkillAdapter extends DirectorySkillAdapter {
64
8
  constructor(skillsDir) {
65
- this.skillsDir = skillsDir;
66
- this.appId = "opencode";
67
- }
68
- async importSkills() {
69
- const fs = await import('node:fs/promises');
70
- const path = await import('node:path');
71
- await ensureDir(this.skillsDir);
72
- const entries = await fs.readdir(this.skillsDir, { withFileTypes: true });
73
- return entries
74
- .filter((entry) => entry.isDirectory() || entry.isSymbolicLink())
75
- .map((entry) => {
76
- const directory = path.join(this.skillsDir, entry.name);
77
- return {
78
- id: `skill_import_${entry.name}`,
79
- name: toNameFromPath(entry.name),
80
- directory,
81
- description: undefined,
82
- };
83
- });
84
- }
85
- async syncSkill(skill, sourceDir, method) {
86
- const path = await import('node:path');
87
- const targetDir = path.join(this.skillsDir, skill.name);
88
- await materializeSkillDir(sourceDir, targetDir, method);
89
- }
90
- async removeSkill(skill) {
91
- const path = await import('node:path');
92
- const targetDir = path.join(this.skillsDir, skill.name);
93
- await removeIfExists(targetDir);
9
+ super('opencode', skillsDir);
94
10
  }
95
11
  }
package/dist/config.d.ts CHANGED
@@ -33,6 +33,8 @@ export declare function getClaudeSkillsDir(runtimeHome: string): string;
33
33
  export declare function getOpencodeConfigFile(runtimeHome: string): string;
34
34
  /** 获取 Codex 配置文件路径 */
35
35
  export declare function getCodexConfigFile(runtimeHome: string): string;
36
+ /** 获取 Codex Skills 目录 */
37
+ export declare function getCodexSkillsDir(runtimeHome: string): string;
36
38
  /** 获取 OpenCode Skills 目录 */
37
39
  export declare function getOpencodeSkillsDir(runtimeHome: string): string;
38
40
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,WAAW;AACX,eAAO,MAAM,IAAI,EAAE,MAElB,CAAC;AAEF,gBAAgB;AAChB,eAAO,MAAM,gBAAgB,EAAE,MACwC,CAAC;AAExE,oBAAoB;AACpB,eAAO,MAAM,8BAA8B,gCAAgC,CAAC;AAE5E,cAAc;AACd,eAAO,MAAM,OAAO,EAAE,MAA8C,CAAC;AAErE,kBAAkB;AAClB,eAAO,MAAM,YAAY,EAAE,MAC+C,CAAC;AAE3E,2BAA2B;AAC3B,eAAO,MAAM,wBAAwB,EAAE,OACiB,CAAC;AAEzD,oCAAoC;AACpC,eAAO,MAAM,oBAAoB,EAAE,OACiB,CAAC;AAErD,8BAA8B;AAC9B,eAAO,MAAM,kBAAkB,EAAE,MAAM,EAMC,CAAC;AAEzC,uBAAuB;AACvB,wBAAgB,uBAAuB,IAAI,IAAI,CAc9C;AAED,eAAe;AACf,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,8CAA8C;AAC9C,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK/D;AAED,2BAA2B;AAC3B,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAKlE;AAED,0BAA0B;AAC1B,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED,yBAAyB;AACzB,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED,sBAAsB;AACtB,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED,4BAA4B;AAC5B,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAKhE;AAED;;GAEG;AAEH,yBAAyB;AACzB,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,sBAAsB,EACrB,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE1C,eAAe;AACf,eAAO,MAAM,mBAAmB,SACiB,CAAC;AAElD,iCAAiC;AACjC,eAAO,MAAM,2BAA2B,QAEvC,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AAEF,qCAAqC;AACrC,eAAO,MAAM,uBAAuB,QAEnC,CAAC;AAEF;;GAEG;AAEH,eAAe;AACf,eAAO,MAAM,qBAAqB,SAA2C,CAAC;AAE9E,YAAY;AACZ,eAAO,MAAM,uBAAuB,QAAkC,CAAC;AAEvE,iBAAiB;AACjB,eAAO,MAAM,sBAAsB,QAAiC,CAAC;AAErE,oBAAoB;AACpB,eAAO,MAAM,2BAA2B,QAAsC,CAAC;AAE/E,WAAW;AACX,eAAO,MAAM,0BAA0B,QAAqC,CAAC;AAE7E,WAAW;AACX,eAAO,MAAM,uBAAuB,QAAkC,CAAC;AAEvE,aAAa;AACb,eAAO,MAAM,4BAA4B,QACH,CAAC;AAEvC,kCAAkC;AAClC,eAAO,MAAM,wBAAwB,QAC4B,CAAC;AAElE,aAAa;AACb,eAAO,MAAM,yBAAyB,QAErC,CAAC;AAEF,iBAAiB;AACjB,eAAO,MAAM,4BAA4B,QAExC,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,WAAW;AACX,eAAO,MAAM,IAAI,EAAE,MAElB,CAAC;AAEF,gBAAgB;AAChB,eAAO,MAAM,gBAAgB,EAAE,MACwC,CAAC;AAExE,oBAAoB;AACpB,eAAO,MAAM,8BAA8B,gCAAgC,CAAC;AAE5E,cAAc;AACd,eAAO,MAAM,OAAO,EAAE,MAA8C,CAAC;AAErE,kBAAkB;AAClB,eAAO,MAAM,YAAY,EAAE,MAC+C,CAAC;AAE3E,2BAA2B;AAC3B,eAAO,MAAM,wBAAwB,EAAE,OACiB,CAAC;AAEzD,oCAAoC;AACpC,eAAO,MAAM,oBAAoB,EAAE,OACiB,CAAC;AAErD,8BAA8B;AAC9B,eAAO,MAAM,kBAAkB,EAAE,MAAM,EAMC,CAAC;AAEzC,uBAAuB;AACvB,wBAAgB,uBAAuB,IAAI,IAAI,CAc9C;AAED,eAAe;AACf,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,8CAA8C;AAC9C,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK/D;AAED,2BAA2B;AAC3B,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAKlE;AAED,0BAA0B;AAC1B,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED,yBAAyB;AACzB,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED,sBAAsB;AACtB,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED,yBAAyB;AACzB,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK7D;AAED,4BAA4B;AAC5B,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAKhE;AAED;;GAEG;AAEH,yBAAyB;AACzB,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,sBAAsB,EACrB,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE1C,eAAe;AACf,eAAO,MAAM,mBAAmB,SACiB,CAAC;AAElD,iCAAiC;AACjC,eAAO,MAAM,2BAA2B,QAEvC,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AAEF,qCAAqC;AACrC,eAAO,MAAM,uBAAuB,QAEnC,CAAC;AAEF;;GAEG;AAEH,eAAe;AACf,eAAO,MAAM,qBAAqB,SAA2C,CAAC;AAE9E,YAAY;AACZ,eAAO,MAAM,uBAAuB,QAAkC,CAAC;AAEvE,iBAAiB;AACjB,eAAO,MAAM,sBAAsB,QAAiC,CAAC;AAErE,oBAAoB;AACpB,eAAO,MAAM,2BAA2B,QAAsC,CAAC;AAE/E,WAAW;AACX,eAAO,MAAM,0BAA0B,QAAqC,CAAC;AAE7E,WAAW;AACX,eAAO,MAAM,uBAAuB,QAAkC,CAAC;AAEvE,aAAa;AACb,eAAO,MAAM,4BAA4B,QACH,CAAC;AAEvC,kCAAkC;AAClC,eAAO,MAAM,wBAAwB,QAC4B,CAAC;AAElE,aAAa;AACb,eAAO,MAAM,yBAAyB,QAErC,CAAC;AAEF,iBAAiB;AACjB,eAAO,MAAM,4BAA4B,QAExC,CAAC"}
package/dist/config.js CHANGED
@@ -66,6 +66,11 @@ export function getCodexConfigFile(runtimeHome) {
66
66
  return (String(process.env.AWS_RUNTIME_CODEX_CONFIG_FILE || "").trim() ||
67
67
  path.join(runtimeHome, ".codex", "config.toml"));
68
68
  }
69
+ /** 获取 Codex Skills 目录 */
70
+ export function getCodexSkillsDir(runtimeHome) {
71
+ return (String(process.env.AWS_RUNTIME_CODEX_SKILLS_DIR || "").trim() ||
72
+ path.join(runtimeHome, ".codex", "skills"));
73
+ }
69
74
  /** 获取 OpenCode Skills 目录 */
70
75
  export function getOpencodeSkillsDir(runtimeHome) {
71
76
  return (String(process.env.AWS_RUNTIME_OPENCODE_SKILLS_DIR || "").trim() ||
@@ -5,7 +5,7 @@ import { validateToken } from "../middleware/auth.js";
5
5
  import { schedulerBaseUrl, runtimeToken } from "../config.js";
6
6
  import { loadInstanceState, saveInstanceState, } from "../services/instance-state.js";
7
7
  import { initInstance } from "../services/instance-init-service.js";
8
- import { loadCcSwitchSdk } from "../services/cc-switch-sdk.js";
8
+ import { discoverCcSwitchConfiguredItems, loadCcSwitchSdk } from "../services/cc-switch-sdk.js";
9
9
  import { syncLegacyStateFromSdk } from "../services/instance-init-service.js";
10
10
  import { detectToolStatuses, ensureToolsInstalled, SUPPORTED_INSTALLABLE_TOOLS, } from "../services/tool-installer.js";
11
11
  import { getConfiguredConnectionKeys } from "../services/auto-register.js";
@@ -133,8 +133,7 @@ instanceRouter.post("/cc-switch/state", validateToken, async (req, res) => {
133
133
  }
134
134
  try {
135
135
  const sdk = await loadCcSwitchSdk(agentId);
136
- const importedMcpCount = await sdk.importMcpFromApps();
137
- const importedSkillCount = await sdk.importSkillsFromApps();
136
+ const imported = await discoverCcSwitchConfiguredItems(sdk);
138
137
  const synced = await syncLegacyStateFromSdk(agentId, sdk);
139
138
  const state = synced.state;
140
139
  const toolStatus = await detectToolStatuses(state.enabledTools || []);
@@ -142,8 +141,8 @@ instanceRouter.post("/cc-switch/state", validateToken, async (req, res) => {
142
141
  ok: true,
143
142
  agentId: String(agentId),
144
143
  imported: {
145
- mcpServers: importedMcpCount,
146
- skills: importedSkillCount,
144
+ mcpServers: imported.mcpServers,
145
+ skills: imported.skills,
147
146
  },
148
147
  state: { ...state, toolStatus },
149
148
  });
@@ -1,6 +1,6 @@
1
1
  import { Router } from 'express';
2
2
  import { validateToken } from '../middleware/auth.js';
3
- import { loadCcSwitchSdk, runCcSwitchAdapter } from '../services/cc-switch-sdk.js';
3
+ import { discoverCcSwitchConfiguredItems, loadCcSwitchSdk, runCcSwitchAdapter } from '../services/cc-switch-sdk.js';
4
4
  import { syncLegacyStateFromSdk } from '../services/instance-init-service.js';
5
5
  import { normalizeSdkAppFlags, normalizeSdkMcpServerSpec } from '../utils/mcp-utils.js';
6
6
  export const mcpRouter = Router();
@@ -13,9 +13,10 @@ mcpRouter.post('/cc-switch/mcp/list', validateToken, async (req, res) => {
13
13
  }
14
14
  try {
15
15
  const sdk = await loadCcSwitchSdk(agentId);
16
+ const imported = await discoverCcSwitchConfiguredItems(sdk);
16
17
  const mcpServers = sdk.getAllMcpServers();
17
18
  const synced = await syncLegacyStateFromSdk(agentId, sdk);
18
- res.json({ ok: true, agentId: String(agentId), mcpServers, state: synced.state, configPath: synced.configPath });
19
+ res.json({ ok: true, agentId: String(agentId), imported, mcpServers, state: synced.state, configPath: synced.configPath });
19
20
  }
20
21
  catch (error) {
21
22
  const err = error;
@@ -1,6 +1,6 @@
1
1
  import { Router } from 'express';
2
2
  import { validateToken } from '../middleware/auth.js';
3
- import { loadCcSwitchSdk, runCcSwitchAdapter } from '../services/cc-switch-sdk.js';
3
+ import { discoverCcSwitchConfiguredItems, loadCcSwitchSdk, runCcSwitchAdapter } from '../services/cc-switch-sdk.js';
4
4
  import { syncLegacyStateFromSdk } from '../services/instance-init-service.js';
5
5
  import { resolveSkillSourceDir, ensureDirectoryExists } from '../utils/file-utils.js';
6
6
  import { normalizeSdkAppFlags } from '../utils/mcp-utils.js';
@@ -14,9 +14,10 @@ skillsRouter.post('/cc-switch/skills/list', validateToken, async (req, res) => {
14
14
  }
15
15
  try {
16
16
  const sdk = await loadCcSwitchSdk(agentId);
17
+ const imported = await discoverCcSwitchConfiguredItems(sdk);
17
18
  const skills = sdk.getAllSkills();
18
19
  const synced = await syncLegacyStateFromSdk(agentId, sdk);
19
- res.json({ ok: true, agentId: String(agentId), skills, state: synced.state });
20
+ res.json({ ok: true, agentId: String(agentId), imported, skills, state: synced.state });
20
21
  }
21
22
  catch (error) {
22
23
  const err = error;
@@ -1 +1 @@
1
- {"version":3,"file":"aws-client-agent-mcp.d.ts","sourceRoot":"","sources":["../../src/services/aws-client-agent-mcp.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAuB7C,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,sCAAsC;IACrD,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,sCAAsC;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAaD,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;CAC3C;AAqBD,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AA0FD,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,sCAA2C,GACnD,MAAM,GAAG,IAAI,CAgDf;AA2ED,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,sCAA2C,GACnD,kBAAkB,CAEpB;AAED,wBAAgB,gCAAgC,CAC9C,OAAO,GAAE,sCAA2C,GACnD,kBAAkB,CAsBpB;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,uBAAuB,GAC7B,kBAAkB,CAwBpB;AAED,wBAAgB,+BAA+B,IAAI,IAAI,CAgBtD"}
1
+ {"version":3,"file":"aws-client-agent-mcp.d.ts","sourceRoot":"","sources":["../../src/services/aws-client-agent-mcp.ts"],"names":[],"mappings":"AAwBA,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAuB7C,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,sCAAsC;IACrD,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,sCAAsC;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAaD,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;CAC3C;AAuBD,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAgLD,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,sCAA2C,GACnD,MAAM,GAAG,IAAI,CAoDf;AA2ED,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,sCAA2C,GACnD,kBAAkB,CAEpB;AAED,wBAAgB,gCAAgC,CAC9C,OAAO,GAAE,sCAA2C,GACnD,kBAAkB,CAsBpB;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,uBAAuB,GAC7B,kBAAkB,CAwBpB;AAED,wBAAgB,+BAA+B,IAAI,IAAI,CAgBtD"}
@@ -1,5 +1,5 @@
1
1
  import { createHash } from "node:crypto";
2
- import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync, } from "node:fs";
2
+ import { cpSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, realpathSync, rmSync, statSync, symlinkSync, writeFileSync, } from "node:fs";
3
3
  import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { getRuntimeHomeDir, port, schedulerBaseUrl } from "../config.js";
@@ -32,7 +32,10 @@ function getPackageRoot() {
32
32
  return path.resolve(path.dirname(currentFile), "..", "..");
33
33
  }
34
34
  function getBundledEntryPath(packageRoot = getPackageRoot()) {
35
- return path.join(packageRoot, "package", "aws-client-agent-mcp", "dist", "index.js");
35
+ return path.join(getBundledMcpRoot(packageRoot), "dist", "index.js");
36
+ }
37
+ function getBundledMcpRoot(packageRoot) {
38
+ return path.join(packageRoot, "package", "aws-client-agent-mcp");
36
39
  }
37
40
  function getReleasedMcpRoot() {
38
41
  return path.join(getRuntimeHomeDir(), ".aws-bridge", "mcp");
@@ -56,7 +59,66 @@ function getBridgeVersion(packageRoot) {
56
59
  return readPackageVersion(path.join(packageRoot, "package.json"));
57
60
  }
58
61
  function getBundledMcpVersion(packageRoot) {
59
- return readPackageVersion(path.join(packageRoot, "package", "aws-client-agent-mcp", "package.json"));
62
+ return readPackageVersion(path.join(getBundledMcpRoot(packageRoot), "package.json"));
63
+ }
64
+ function copyIfExists(sourcePath, targetPath) {
65
+ if (!existsSync(sourcePath)) {
66
+ return;
67
+ }
68
+ copyFileOrDirectory(sourcePath, targetPath);
69
+ }
70
+ function copyFileOrDirectory(sourcePath, targetPath) {
71
+ const stat = statSync(sourcePath);
72
+ if (stat.isDirectory()) {
73
+ cpSync(sourcePath, targetPath, {
74
+ errorOnExist: false,
75
+ force: true,
76
+ recursive: true,
77
+ });
78
+ return;
79
+ }
80
+ cpSync(sourcePath, targetPath, { errorOnExist: false, force: true });
81
+ }
82
+ function syncReleasedPackageMetadata(packageRoot, releasedRoot) {
83
+ const bundledMcpRoot = getBundledMcpRoot(packageRoot);
84
+ copyIfExists(path.join(bundledMcpRoot, "package.json"), path.join(releasedRoot, "package.json"));
85
+ copyIfExists(path.join(bundledMcpRoot, "README.md"), path.join(releasedRoot, "README.md"));
86
+ copyIfExists(path.join(bundledMcpRoot, "package-lock.json"), path.join(releasedRoot, "package-lock.json"));
87
+ }
88
+ function shouldReplaceNodeModulesLink(targetPath) {
89
+ if (!existsSync(targetPath)) {
90
+ return true;
91
+ }
92
+ const stat = lstatSync(targetPath);
93
+ return stat.isSymbolicLink() || stat.isDirectory();
94
+ }
95
+ function isExpectedNodeModulesLink(targetPath, sourcePath) {
96
+ if (!existsSync(targetPath)) {
97
+ return false;
98
+ }
99
+ try {
100
+ return realpathSync(targetPath) === realpathSync(sourcePath);
101
+ }
102
+ catch {
103
+ return false;
104
+ }
105
+ }
106
+ function ensureReleasedNodeModules(packageRoot, releasedRoot) {
107
+ const sourceNodeModules = path.join(packageRoot, "node_modules");
108
+ const releasedNodeModules = path.join(releasedRoot, "node_modules");
109
+ if (!existsSync(sourceNodeModules)) {
110
+ logger.warn(`[runtime-bridge] ${AWS_MCP_SERVER_NAME} MCP 未找到依赖目录,release 产物可能无法解析运行时依赖: ${sourceNodeModules}`);
111
+ return;
112
+ }
113
+ if (isExpectedNodeModulesLink(releasedNodeModules, sourceNodeModules)) {
114
+ return;
115
+ }
116
+ if (!shouldReplaceNodeModulesLink(releasedNodeModules)) {
117
+ logger.warn(`[runtime-bridge] ${AWS_MCP_SERVER_NAME} MCP 依赖路径已存在但不是目录或链接,已保留: ${releasedNodeModules}`);
118
+ return;
119
+ }
120
+ rmSync(releasedNodeModules, { recursive: true, force: true });
121
+ symlinkSync(sourceNodeModules, releasedNodeModules, process.platform === "win32" ? "junction" : "dir");
60
122
  }
61
123
  function listDistFiles(dirPath, rootPath = dirPath) {
62
124
  return readdirSync(dirPath, { withFileTypes: true }).flatMap((entry) => {
@@ -128,6 +190,8 @@ export function releaseBundledAwsClientAgentMcp(options = {}) {
128
190
  if (shouldRefreshReleasedMcp(releasedEntry, currentManifest, nextManifest)) {
129
191
  rmSync(releasedDist, { recursive: true, force: true });
130
192
  mkdirSync(releasedRoot, { recursive: true });
193
+ syncReleasedPackageMetadata(packageRoot, releasedRoot);
194
+ ensureReleasedNodeModules(packageRoot, releasedRoot);
131
195
  cpSync(bundledDist, releasedDist, {
132
196
  errorOnExist: false,
133
197
  force: true,
@@ -140,6 +204,8 @@ export function releaseBundledAwsClientAgentMcp(options = {}) {
140
204
  logger.info(`[runtime-bridge] ${AWS_MCP_SERVER_NAME} MCP 已更新到: ${releasedDist}`);
141
205
  }
142
206
  else {
207
+ syncReleasedPackageMetadata(packageRoot, releasedRoot);
208
+ ensureReleasedNodeModules(packageRoot, releasedRoot);
143
209
  logger.info(`[runtime-bridge] ${AWS_MCP_SERVER_NAME} MCP 已是最新: ${releasedDist}`);
144
210
  }
145
211
  return releasedEntry;