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.
Files changed (29) hide show
  1. package/README.md +77 -77
  2. package/dist/index.js +0 -0
  3. package/dist/routes/properties.test.js +4 -4
  4. package/dist/utils/yaml-utils.test.js +129 -129
  5. package/node_modules/@cc-switch/sdk/README.md +540 -540
  6. package/node_modules/@cc-switch/sdk/package.json +31 -31
  7. package/package/aws-client-agent-mcp/README.md +288 -288
  8. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +1 -0
  9. package/package/aws-client-agent-mcp/dist/agent-client.d.ts.map +1 -1
  10. package/package/aws-client-agent-mcp/dist/agent-client.js +12 -0
  11. package/package/aws-client-agent-mcp/dist/agent-client.js.map +1 -1
  12. package/package/aws-client-agent-mcp/dist/agent-client.test.js +31 -0
  13. package/package/aws-client-agent-mcp/dist/agent-client.test.js.map +1 -1
  14. package/package/aws-client-agent-mcp/package.json +52 -52
  15. package/package/cc-switch-sdk/README.md +540 -540
  16. package/package/cc-switch-sdk/package.json +31 -31
  17. package/package.json +78 -78
  18. package/dist/routes/runtime-mcp-proxy.d.ts +0 -3
  19. package/dist/routes/runtime-mcp-proxy.d.ts.map +0 -1
  20. package/dist/routes/runtime-mcp-proxy.js +0 -102
  21. package/dist/routes/runtime-mcp-proxy.test.d.ts +0 -2
  22. package/dist/routes/runtime-mcp-proxy.test.d.ts.map +0 -1
  23. package/dist/routes/runtime-mcp-proxy.test.js +0 -111
  24. package/node_modules/@cc-switch/sdk/dist/sdk-import.test.d.ts +0 -2
  25. package/node_modules/@cc-switch/sdk/dist/sdk-import.test.d.ts.map +0 -1
  26. package/node_modules/@cc-switch/sdk/dist/sdk-import.test.js +0 -119
  27. package/package/cc-switch-sdk/dist/sdk-import.test.d.ts +0 -2
  28. package/package/cc-switch-sdk/dist/sdk-import.test.d.ts.map +0 -1
  29. package/package/cc-switch-sdk/dist/sdk-import.test.js +0 -119
@@ -1,31 +1,31 @@
1
- {
2
- "name": "@cc-switch/sdk",
3
- "version": "0.1.0",
4
- "description": "Node SDK for MCP and Skill management",
5
- "type": "module",
6
- "main": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./dist/index.d.ts",
11
- "default": "./dist/index.js"
12
- }
13
- },
14
- "files": [
15
- "dist"
16
- ],
17
- "scripts": {
18
- "build": "tsc -p tsconfig.json",
19
- "typecheck": "tsc -p tsconfig.json --noEmit",
20
- "test": "vitest run --config vitest.config.ts",
21
- "test:watch": "vitest --config vitest.config.ts"
22
- },
23
- "dependencies": {
24
- "zod": "^4.1.12"
25
- },
26
- "devDependencies": {
27
- "@types/node": "^20.0.0",
28
- "typescript": "^5.3.0",
29
- "vitest": "^2.0.5"
30
- }
31
- }
1
+ {
2
+ "name": "@cc-switch/sdk",
3
+ "version": "0.1.0",
4
+ "description": "Node SDK for MCP and Skill management",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc -p tsconfig.json",
19
+ "typecheck": "tsc -p tsconfig.json --noEmit",
20
+ "test": "vitest run --config vitest.config.ts",
21
+ "test:watch": "vitest --config vitest.config.ts"
22
+ },
23
+ "dependencies": {
24
+ "zod": "^4.1.12"
25
+ },
26
+ "devDependencies": {
27
+ "@types/node": "^20.0.0",
28
+ "typescript": "^5.3.0",
29
+ "vitest": "^2.0.5"
30
+ }
31
+ }
package/package.json CHANGED
@@ -1,78 +1,78 @@
1
- {
2
- "name": "aws-runtime-bridge",
3
- "version": "1.3.0",
4
- "description": "AgentsWorkStudio runtime bridge service for machine-level agent runtime integration",
5
- "type": "module",
6
- "main": "dist/index.js",
7
- "bin": {
8
- "awsb": "dist/index.js",
9
- "aws-bridge": "dist/index.js",
10
- "aws-runtime-bridge": "dist/index.js"
11
- },
12
- "files": [
13
- "dist",
14
- "scripts/ensure-bin-executable.mjs",
15
- "package/aws-client-agent-mcp/dist",
16
- "package/aws-client-agent-mcp/package.json",
17
- "package/aws-client-agent-mcp/README.md",
18
- "package/cc-switch-sdk/dist",
19
- "package/cc-switch-sdk/package.json",
20
- "package/cc-switch-sdk/README.md"
21
- ],
22
- "bundleDependencies": [
23
- "@cc-switch/sdk"
24
- ],
25
- "engines": {
26
- "node": ">=20.0.0 <25"
27
- },
28
- "scripts": {
29
- "build:agent-mcp": "npm run build --prefix package/aws-client-agent-mcp",
30
- "build:sdk": "npm run build --prefix package/cc-switch-sdk",
31
- "prebuild": "npm run build:sdk && npm run build:agent-mcp",
32
- "build": "tsc -p tsconfig.json",
33
- "postinstall": "node scripts/ensure-bin-executable.mjs",
34
- "pretypecheck": "npm run build:sdk && npm run build:agent-mcp",
35
- "typecheck": "tsc -p tsconfig.json --noEmit",
36
- "prestart": "npm run build:sdk && npm run build:agent-mcp",
37
- "start": "node dist/index.js",
38
- "dev": "tsc -p tsconfig.json && node scripts/dev-runner.mjs",
39
- "prepare": "npm run build",
40
- "lint": "eslint src --max-warnings 0",
41
- "lint:fix": "eslint src --fix",
42
- "format": "prettier --write \"src/**/*.ts\"",
43
- "format:check": "prettier --check \"src/**/*.ts\"",
44
- "test": "vitest run",
45
- "test:watch": "vitest",
46
- "test:coverage": "vitest run --coverage"
47
- },
48
- "dependencies": {
49
- "@anthropic-ai/claude-agent-sdk": "^0.2.87",
50
- "@cc-switch/sdk": "file:package/cc-switch-sdk",
51
- "@modelcontextprotocol/sdk": "^1.27.1",
52
- "@openai/codex-sdk": "^0.125.0",
53
- "@opencode-ai/sdk": "^1.3.13",
54
- "axios": "^1.7.9",
55
- "cors": "^2.8.5",
56
- "express": "^4.21.2",
57
- "js-yaml": "^4.1.1",
58
- "node-pty": "^1.0.0",
59
- "uuid": "^11.0.3",
60
- "ws": "^8.14.2",
61
- "yaml": "^2.3.4"
62
- },
63
- "devDependencies": {
64
- "@eslint/js": "^9.0.0",
65
- "@types/cors": "^2.8.19",
66
- "@types/express": "^4.17.21",
67
- "@types/js-yaml": "^4.0.9",
68
- "@types/node": "^20.17.0",
69
- "@vitest/coverage-v8": "^2.0.0",
70
- "eslint": "^9.0.0",
71
- "eslint-plugin-import": "^2.29.0",
72
- "prettier": "^3.2.0",
73
- "tsx": "^4.21.0",
74
- "typescript": "^5.9.3",
75
- "typescript-eslint": "^8.0.0",
76
- "vitest": "^2.0.0"
77
- }
78
- }
1
+ {
2
+ "name": "aws-runtime-bridge",
3
+ "version": "1.3.1",
4
+ "description": "AgentsWorkStudio runtime bridge service for machine-level agent runtime integration",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "awsb": "dist/index.js",
9
+ "aws-bridge": "dist/index.js",
10
+ "aws-runtime-bridge": "dist/index.js"
11
+ },
12
+ "files": [
13
+ "dist",
14
+ "scripts/ensure-bin-executable.mjs",
15
+ "package/aws-client-agent-mcp/dist",
16
+ "package/aws-client-agent-mcp/package.json",
17
+ "package/aws-client-agent-mcp/README.md",
18
+ "package/cc-switch-sdk/dist",
19
+ "package/cc-switch-sdk/package.json",
20
+ "package/cc-switch-sdk/README.md"
21
+ ],
22
+ "bundleDependencies": [
23
+ "@cc-switch/sdk"
24
+ ],
25
+ "engines": {
26
+ "node": ">=20.0.0 <25"
27
+ },
28
+ "scripts": {
29
+ "build:agent-mcp": "npm run build --prefix package/aws-client-agent-mcp",
30
+ "build:sdk": "npm run build --prefix package/cc-switch-sdk",
31
+ "prebuild": "npm run build:sdk && npm run build:agent-mcp",
32
+ "build": "tsc -p tsconfig.json",
33
+ "postinstall": "node scripts/ensure-bin-executable.mjs",
34
+ "pretypecheck": "npm run build:sdk && npm run build:agent-mcp",
35
+ "typecheck": "tsc -p tsconfig.json --noEmit",
36
+ "prestart": "npm run build:sdk && npm run build:agent-mcp",
37
+ "start": "node dist/index.js",
38
+ "dev": "tsc -p tsconfig.json && node scripts/dev-runner.mjs",
39
+ "prepare": "npm run build",
40
+ "lint": "eslint src --max-warnings 0",
41
+ "lint:fix": "eslint src --fix",
42
+ "format": "prettier --write \"src/**/*.ts\"",
43
+ "format:check": "prettier --check \"src/**/*.ts\"",
44
+ "test": "vitest run",
45
+ "test:watch": "vitest",
46
+ "test:coverage": "vitest run --coverage"
47
+ },
48
+ "dependencies": {
49
+ "@anthropic-ai/claude-agent-sdk": "^0.2.87",
50
+ "@cc-switch/sdk": "file:package/cc-switch-sdk",
51
+ "@modelcontextprotocol/sdk": "^1.27.1",
52
+ "@openai/codex-sdk": "^0.125.0",
53
+ "@opencode-ai/sdk": "^1.3.13",
54
+ "axios": "^1.7.9",
55
+ "cors": "^2.8.5",
56
+ "express": "^4.21.2",
57
+ "js-yaml": "^4.1.1",
58
+ "node-pty": "^1.0.0",
59
+ "uuid": "^11.0.3",
60
+ "ws": "^8.14.2",
61
+ "yaml": "^2.3.4"
62
+ },
63
+ "devDependencies": {
64
+ "@eslint/js": "^9.0.0",
65
+ "@types/cors": "^2.8.19",
66
+ "@types/express": "^4.17.21",
67
+ "@types/js-yaml": "^4.0.9",
68
+ "@types/node": "^20.17.0",
69
+ "@vitest/coverage-v8": "^2.0.0",
70
+ "eslint": "^9.0.0",
71
+ "eslint-plugin-import": "^2.29.0",
72
+ "prettier": "^3.2.0",
73
+ "tsx": "^4.21.0",
74
+ "typescript": "^5.9.3",
75
+ "typescript-eslint": "^8.0.0",
76
+ "vitest": "^2.0.0"
77
+ }
78
+ }
@@ -1,3 +0,0 @@
1
- export declare const runtimeMcpProxyRouter: import("express-serve-static-core").Router;
2
- export declare function toRuntimeMcpProxyUrl(bridgeBaseUrl?: string): string;
3
- //# sourceMappingURL=runtime-mcp-proxy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"runtime-mcp-proxy.d.ts","sourceRoot":"","sources":["../../src/routes/runtime-mcp-proxy.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,qBAAqB,4CAAW,CAAC;AAwI9C,wBAAgB,oBAAoB,CAClC,aAAa,SAA6B,GACzC,MAAM,CAER"}
@@ -1,102 +0,0 @@
1
- import axios from "axios";
2
- import { Router } from "express";
3
- import { port, schedulerBaseUrl } from "../config.js";
4
- import { requestRuntimeAccessTokenRefresh } from "../services/auto-register.js";
5
- import { getRuntimeAccessToken, loadRuntimeBinding, } from "../services/runtime-binding.js";
6
- import { createLogger } from "../utils/logger.js";
7
- const log = createLogger("runtime-mcp-proxy");
8
- export const runtimeMcpProxyRouter = Router();
9
- function isLoopbackRequest(req) {
10
- const ip = req.ip || req.socket.remoteAddress || "";
11
- return ip === "127.0.0.1" || ip === "::1" || ip === "::ffff:127.0.0.1";
12
- }
13
- function normalizeSchedulerBaseUrl(value) {
14
- const candidate = String(value || "").trim() || schedulerBaseUrl;
15
- return candidate.replace(/\/+$/, "");
16
- }
17
- function normalizeMcpCallBody(rawBody) {
18
- const tool = String(rawBody?.tool || "").trim();
19
- if (!/^[a-zA-Z0-9_.:-]{1,128}$/.test(tool)) {
20
- return null;
21
- }
22
- const args = rawBody?.arguments;
23
- if (args == null) {
24
- return { tool, arguments: {} };
25
- }
26
- if (typeof args !== "object" || Array.isArray(args)) {
27
- return null;
28
- }
29
- return { tool, arguments: args };
30
- }
31
- async function forwardMcpCall(options) {
32
- const url = new URL("/mcp/call", options.schedulerBaseUrl).toString();
33
- const response = await axios.post(url, options.body, {
34
- headers: {
35
- "Content-Type": "application/json",
36
- "X-Runtime-Token": options.runtimeAccessToken,
37
- Authorization: `Bearer ${options.runtimeAccessToken}`,
38
- },
39
- timeout: 15000,
40
- validateStatus: () => true,
41
- });
42
- return { status: response.status, data: response.data };
43
- }
44
- function resolveRuntimeCredential(req) {
45
- const binding = loadRuntimeBinding();
46
- const requestedSchedulerBaseUrl = normalizeSchedulerBaseUrl(req.body?.schedulerBaseUrl || req.body?.serverUrl || binding.schedulerBaseUrl);
47
- const runtimeAccessToken = getRuntimeAccessToken(req.body?.userId || binding.userId, requestedSchedulerBaseUrl);
48
- return { runtimeAccessToken, schedulerBaseUrl: requestedSchedulerBaseUrl };
49
- }
50
- runtimeMcpProxyRouter.post("/mcp/call", async (req, res) => {
51
- if (!isLoopbackRequest(req)) {
52
- res.status(403).json({ ok: false, error: "loopback request required" });
53
- return;
54
- }
55
- const body = normalizeMcpCallBody(req.body || {});
56
- if (!body) {
57
- res.status(400).json({ ok: false, error: "invalid MCP call payload" });
58
- return;
59
- }
60
- let credential = resolveRuntimeCredential(req);
61
- if (!credential.runtimeAccessToken) {
62
- const refresh = await requestRuntimeAccessTokenRefresh();
63
- if (!refresh.success || !refresh.runtimeAccessToken) {
64
- res.status(401).json({
65
- ok: false,
66
- error: refresh.error || "runtime access token is not available",
67
- });
68
- return;
69
- }
70
- credential = {
71
- runtimeAccessToken: refresh.runtimeAccessToken,
72
- schedulerBaseUrl: credential.schedulerBaseUrl,
73
- };
74
- }
75
- const runtimeAccessToken = String(credential.runtimeAccessToken || "");
76
- try {
77
- let forwarded = await forwardMcpCall({
78
- runtimeAccessToken,
79
- schedulerBaseUrl: credential.schedulerBaseUrl,
80
- body,
81
- });
82
- if (forwarded.status === 401) {
83
- const refresh = await requestRuntimeAccessTokenRefresh();
84
- if (refresh.success && refresh.runtimeAccessToken) {
85
- forwarded = await forwardMcpCall({
86
- runtimeAccessToken: refresh.runtimeAccessToken,
87
- schedulerBaseUrl: credential.schedulerBaseUrl,
88
- body,
89
- });
90
- }
91
- }
92
- res.status(forwarded.status).json(forwarded.data);
93
- }
94
- catch (error) {
95
- const err = error;
96
- log.warn(`[runtime-bridge] MCP proxy call failed: ${err.message}`);
97
- res.status(502).json({ ok: false, error: "scheduler MCP call failed" });
98
- }
99
- });
100
- export function toRuntimeMcpProxyUrl(bridgeBaseUrl = `http://127.0.0.1:${port}`) {
101
- return new URL("/runtime/mcp/call", bridgeBaseUrl).toString();
102
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=runtime-mcp-proxy.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"runtime-mcp-proxy.test.d.ts","sourceRoot":"","sources":["../../src/routes/runtime-mcp-proxy.test.ts"],"names":[],"mappings":""}
@@ -1,111 +0,0 @@
1
- import express from "express";
2
- import { afterEach, describe, expect, it, vi } from "vitest";
3
- const postMock = vi.hoisted(() => vi.fn());
4
- const getRuntimeAccessTokenMock = vi.hoisted(() => vi.fn());
5
- const loadRuntimeBindingMock = vi.hoisted(() => vi.fn());
6
- const refreshMock = vi.hoisted(() => vi.fn());
7
- vi.mock("axios", () => ({
8
- default: {
9
- post: postMock,
10
- },
11
- }));
12
- vi.mock("../services/runtime-binding.js", () => ({
13
- getRuntimeAccessToken: getRuntimeAccessTokenMock,
14
- loadRuntimeBinding: loadRuntimeBindingMock,
15
- }));
16
- vi.mock("../services/auto-register.js", () => ({
17
- requestRuntimeAccessTokenRefresh: refreshMock,
18
- }));
19
- async function createServer() {
20
- const { runtimeMcpProxyRouter } = await import("./runtime-mcp-proxy.js");
21
- const app = express();
22
- app.use(express.json());
23
- app.use("/runtime", runtimeMcpProxyRouter);
24
- return new Promise((resolve) => {
25
- const server = app.listen(0, "127.0.0.1", () => {
26
- const address = server.address();
27
- if (!address || typeof address === "string") {
28
- throw new Error("expected TCP server address");
29
- }
30
- resolve({ server, baseUrl: `http://127.0.0.1:${address.port}` });
31
- });
32
- });
33
- }
34
- async function postJson(baseUrl, body) {
35
- const response = await fetch(`${baseUrl}/runtime/mcp/call`, {
36
- method: "POST",
37
- headers: { "Content-Type": "application/json" },
38
- body: JSON.stringify(body),
39
- });
40
- return { status: response.status, body: await response.json() };
41
- }
42
- describe("runtime MCP proxy", () => {
43
- afterEach(() => {
44
- vi.resetModules();
45
- vi.clearAllMocks();
46
- });
47
- it("forwards loopback MCP calls with the Bridge-held runtime token", async () => {
48
- loadRuntimeBindingMock.mockReturnValue({
49
- status: "paired",
50
- userId: "user-1",
51
- schedulerBaseUrl: "http://scheduler:7380",
52
- });
53
- getRuntimeAccessTokenMock.mockReturnValue("aws_rt_token_1234567890");
54
- postMock.mockResolvedValue({ status: 200, data: { ok: true } });
55
- const { server, baseUrl } = await createServer();
56
- try {
57
- const result = await postJson(baseUrl, {
58
- tool: "discover_colleague",
59
- arguments: { agentId: "agent-1" },
60
- });
61
- expect(result).toEqual({ status: 200, body: { ok: true } });
62
- expect(postMock).toHaveBeenCalledWith("http://scheduler:7380/mcp/call", { tool: "discover_colleague", arguments: { agentId: "agent-1" } }, expect.objectContaining({
63
- headers: expect.objectContaining({
64
- "X-Runtime-Token": "aws_rt_token_1234567890",
65
- }),
66
- }));
67
- }
68
- finally {
69
- server.close();
70
- }
71
- });
72
- it("rejects malformed MCP payloads before forwarding", async () => {
73
- const { server, baseUrl } = await createServer();
74
- try {
75
- const result = await postJson(baseUrl, {
76
- tool: "bad tool name",
77
- arguments: [],
78
- });
79
- expect(result.status).toBe(400);
80
- expect(postMock).not.toHaveBeenCalled();
81
- }
82
- finally {
83
- server.close();
84
- }
85
- });
86
- it("refreshes runtime token once after scheduler 401", async () => {
87
- loadRuntimeBindingMock.mockReturnValue({
88
- status: "paired",
89
- userId: "user-1",
90
- schedulerBaseUrl: "http://scheduler:7380",
91
- });
92
- getRuntimeAccessTokenMock.mockReturnValue("expired-token-1234567890");
93
- refreshMock.mockResolvedValue({
94
- success: true,
95
- runtimeAccessToken: "fresh-token-1234567890",
96
- });
97
- postMock
98
- .mockResolvedValueOnce({ status: 401, data: { error: "unauthorized" } })
99
- .mockResolvedValueOnce({ status: 200, data: { ok: true } });
100
- const { server, baseUrl } = await createServer();
101
- try {
102
- const result = await postJson(baseUrl, { tool: "discover_colleague" });
103
- expect(result).toEqual({ status: 200, body: { ok: true } });
104
- expect(postMock).toHaveBeenCalledTimes(2);
105
- expect(postMock.mock.calls[1][2].headers["X-Runtime-Token"]).toBe("fresh-token-1234567890");
106
- }
107
- finally {
108
- server.close();
109
- }
110
- });
111
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=sdk-import.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sdk-import.test.d.ts","sourceRoot":"","sources":["../src/sdk-import.test.ts"],"names":[],"mappings":""}
@@ -1,119 +0,0 @@
1
- import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
2
- import os from "node:os";
3
- import path from "node:path";
4
- import { afterEach, describe, expect, it } from "vitest";
5
- import { CcSwitchSdk } from "./sdk.js";
6
- class MemoryMcpAdapter {
7
- constructor(appId, imported = []) {
8
- this.appId = appId;
9
- this.imported = imported;
10
- this.synced = [];
11
- this.removed = [];
12
- }
13
- async importServers() {
14
- return this.imported;
15
- }
16
- async syncServer(server) {
17
- this.synced.push(server);
18
- }
19
- async removeServer(server) {
20
- this.removed.push(server);
21
- }
22
- }
23
- class MemorySkillAdapter {
24
- constructor(appId, imported = []) {
25
- this.appId = appId;
26
- this.imported = imported;
27
- this.synced = [];
28
- this.removed = [];
29
- }
30
- async importSkills() {
31
- return this.imported;
32
- }
33
- async syncSkill(skill, _sourceDir, _method) {
34
- this.synced.push(skill);
35
- }
36
- async removeSkill(skill) {
37
- this.removed.push(skill);
38
- }
39
- }
40
- describe("CcSwitchSdk imports", () => {
41
- let tempDir = "";
42
- const extraTempDirs = [];
43
- afterEach(async () => {
44
- if (tempDir) {
45
- await rm(tempDir, { recursive: true, force: true });
46
- tempDir = "";
47
- }
48
- for (const dir of extraTempDirs.splice(0)) {
49
- await rm(dir, { recursive: true, force: true });
50
- }
51
- });
52
- async function createSdk(adapters) {
53
- tempDir = await mkdtemp(path.join(os.tmpdir(), "cc-switch-sdk-import-"));
54
- const paths = {
55
- stateFile: path.join(tempDir, "state.json"),
56
- backupDir: path.join(tempDir, "backups"),
57
- claudeConfigFile: path.join(tempDir, "claude.json"),
58
- claudeSkillsDir: path.join(tempDir, "claude-skills"),
59
- claudecodeConfigFile: path.join(tempDir, "claudecode.json"),
60
- claudecodeSkillsDir: path.join(tempDir, "claudecode-skills"),
61
- codexConfigFile: path.join(tempDir, "codex.toml"),
62
- opencodeConfigFile: path.join(tempDir, "opencode.json"),
63
- opencodeSkillsDir: path.join(tempDir, "opencode-skills"),
64
- ssotSkillsDir: path.join(tempDir, "ssot-skills"),
65
- };
66
- const emptyMcpAdapters = Object.fromEntries(["claude", "claudecode", "codex", "gemini", "opencode", "openclaw"].map((appId) => [
67
- appId,
68
- new MemoryMcpAdapter(appId),
69
- ]));
70
- const emptySkillAdapters = Object.fromEntries(["claude", "claudecode", "codex", "gemini", "opencode", "openclaw"].map((appId) => [
71
- appId,
72
- new MemorySkillAdapter(appId),
73
- ]));
74
- const sdk = new CcSwitchSdk({
75
- paths,
76
- adapters: {
77
- mcp: { ...emptyMcpAdapters, ...adapters.mcp },
78
- skill: { ...emptySkillAdapters, ...adapters.skill },
79
- },
80
- });
81
- await sdk.load();
82
- return sdk;
83
- }
84
- it("merges imported MCP app flags before syncing", async () => {
85
- const sharedServer = {
86
- id: "mcp-1",
87
- name: "shared-mcp",
88
- server: { type: "stdio", command: "node" },
89
- apps: { claude: false, claudecode: true, codex: false, gemini: false, opencode: false, openclaw: false },
90
- };
91
- const claudecode = new MemoryMcpAdapter("claudecode", [sharedServer]);
92
- const opencode = new MemoryMcpAdapter("opencode", [{ ...sharedServer, id: "mcp-2" }]);
93
- const sdk = await createSdk({ mcp: { claudecode, opencode } });
94
- await sdk.importMcpFromApps();
95
- const [server] = sdk.getAllMcpServers();
96
- expect(server.apps.claudecode).toBe(true);
97
- expect(server.apps.opencode).toBe(true);
98
- expect(opencode.removed).toHaveLength(0);
99
- });
100
- it("merges imported Skill app flags before syncing", async () => {
101
- const sourceRoot = await mkdtemp(path.join(os.tmpdir(), "skill-source-"));
102
- extraTempDirs.push(sourceRoot);
103
- const sourceDir = path.join(sourceRoot, "demo-skill");
104
- await mkdir(sourceDir, { recursive: true });
105
- await writeFile(path.join(sourceDir, "SKILL.md"), "# Demo");
106
- const claudecode = new MemorySkillAdapter("claudecode", [
107
- { id: "skill-1", name: "demo-skill", directory: sourceDir },
108
- ]);
109
- const opencode = new MemorySkillAdapter("opencode", [
110
- { id: "skill-2", name: "demo-skill", directory: sourceDir },
111
- ]);
112
- const sdk = await createSdk({ skill: { claudecode, opencode } });
113
- await sdk.importSkillsFromApps();
114
- const [skill] = sdk.getAllSkills();
115
- expect(skill.apps.claudecode).toBe(true);
116
- expect(skill.apps.opencode).toBe(true);
117
- expect(opencode.removed).toHaveLength(0);
118
- });
119
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=sdk-import.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sdk-import.test.d.ts","sourceRoot":"","sources":["../src/sdk-import.test.ts"],"names":[],"mappings":""}