@snapback/cli 1.6.0 → 3.0.0
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 +120 -21
- package/dist/SkippedTestDetector-AXTMWWHC.js +5 -0
- package/dist/SkippedTestDetector-QLSQV7K7.js +5 -0
- package/dist/analysis-6WTBZJH3.js +6 -0
- package/dist/analysis-C472LUGW.js +2475 -0
- package/dist/auth-TDIHGKKL.js +1446 -0
- package/dist/auto-provision-organization-CXHL46P3.js +161 -0
- package/dist/{chunk-FVIYXFCL.js → chunk-4YTE4JEW.js} +2 -3
- package/dist/chunk-5EOPYJ4Y.js +12 -0
- package/dist/{chunk-ARVV3F4K.js → chunk-5SQA44V7.js} +1085 -18
- package/dist/{chunk-RB7H4UQJ.js → chunk-7ADPL4Q3.js} +10 -3
- package/dist/chunk-CBGOC6RV.js +293 -0
- package/dist/chunk-CPZWXRP2.js +4432 -0
- package/dist/{chunk-7JX6Y4TL.js → chunk-DPWFZNMY.js} +21 -34
- package/dist/{chunk-R7CUQ7CU.js → chunk-E6V6QKS7.js} +317 -33
- package/dist/chunk-FMWCFAY7.js +111 -0
- package/dist/chunk-GQ73B37K.js +314 -0
- package/dist/chunk-LIBBDBW5.js +6136 -0
- package/dist/chunk-O7HMAZ7L.js +3497 -0
- package/dist/chunk-PL4HF4M2.js +593 -0
- package/dist/chunk-Q4VC7GND.js +2300 -0
- package/dist/chunk-WS36HDEU.js +3735 -0
- package/dist/chunk-ZBQDE6WJ.js +108 -0
- package/dist/client-62E3L6DW.js +8 -0
- package/dist/dist-5LR7APG5.js +5 -0
- package/dist/dist-NFU5UJEW.js +9 -0
- package/dist/dist-OO5LJHL6.js +12 -0
- package/dist/index.js +61644 -37198
- package/dist/local-service-adapter-AB3UYRUK.js +6 -0
- package/dist/pioneer-oauth-hook-V2JKEXM7.js +12 -0
- package/dist/{secure-credentials-IWQB6KU4.js → secure-credentials-UEPG7GWW.js} +2 -3
- package/dist/snapback-dir-MG7DTRMF.js +6 -0
- package/package.json +12 -11
- package/scripts/postinstall.mjs +2 -3
- package/dist/SkippedTestDetector-5WJZKZQ3.js +0 -5
- package/dist/SkippedTestDetector-5WJZKZQ3.js.map +0 -1
- package/dist/analysis-YI4UNUCM.js +0 -6
- package/dist/analysis-YI4UNUCM.js.map +0 -1
- package/dist/chunk-7JX6Y4TL.js.map +0 -1
- package/dist/chunk-ARVV3F4K.js.map +0 -1
- package/dist/chunk-EU2IZPOK.js +0 -13002
- package/dist/chunk-EU2IZPOK.js.map +0 -1
- package/dist/chunk-FVIYXFCL.js.map +0 -1
- package/dist/chunk-R7CUQ7CU.js.map +0 -1
- package/dist/chunk-RB7H4UQJ.js.map +0 -1
- package/dist/chunk-SOABQWAU.js +0 -385
- package/dist/chunk-SOABQWAU.js.map +0 -1
- package/dist/dist-O6EBXLN6.js +0 -5
- package/dist/dist-O6EBXLN6.js.map +0 -1
- package/dist/dist-PJVBBZTF.js +0 -5
- package/dist/dist-PJVBBZTF.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/learning-pruner-QC4CTJDX.js +0 -5
- package/dist/learning-pruner-QC4CTJDX.js.map +0 -1
- package/dist/secure-credentials-IWQB6KU4.js.map +0 -1
- package/dist/snapback-dir-V6MWXIW4.js +0 -5
- package/dist/snapback-dir-V6MWXIW4.js.map +0 -1
|
@@ -1,32 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node --no-warnings=ExperimentalWarning
|
|
2
|
-
import { __name } from './chunk-
|
|
2
|
+
import { __name } from './chunk-7ADPL4Q3.js';
|
|
3
3
|
import { mkdir, writeFile, access, constants, readFile, appendFile, stat } from 'fs/promises';
|
|
4
4
|
import { homedir } from 'os';
|
|
5
5
|
import { join, dirname } from 'path';
|
|
6
6
|
import { z } from 'zod';
|
|
7
|
-
import { nanoid } from 'nanoid';
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
const id = nanoid();
|
|
11
|
-
return prefix ? `${prefix}-${id}` : id;
|
|
12
|
-
}
|
|
13
|
-
__name(generateId, "generateId");
|
|
14
|
-
function slugify(description, maxLength = 30) {
|
|
15
|
-
return description.toLowerCase().trim().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, maxLength);
|
|
16
|
-
}
|
|
17
|
-
__name(slugify, "slugify");
|
|
18
|
-
function generateSnapshotId(description) {
|
|
19
|
-
if (description && description.length > 0) {
|
|
20
|
-
const slug = slugify(description);
|
|
21
|
-
if (slug.length > 0) {
|
|
22
|
-
return `snapshot-${slug}-${Date.now()}-${nanoid(9)}`;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return `snapshot-${Date.now()}-${nanoid(9)}`;
|
|
26
|
-
}
|
|
27
|
-
__name(generateSnapshotId, "generateSnapshotId");
|
|
28
|
-
|
|
29
|
-
// src/services/snapback-dir.ts
|
|
8
|
+
process.env.SNAPBACK_CLI='true';
|
|
30
9
|
var SNAPBACK_DIR = ".snapback";
|
|
31
10
|
var GLOBAL_SNAPBACK_DIR = ".snapback";
|
|
32
11
|
var WorkspaceConfigSchema = z.object({
|
|
@@ -259,7 +238,9 @@ async function deleteGlobalJson(relativePath) {
|
|
|
259
238
|
__name(deleteGlobalJson, "deleteGlobalJson");
|
|
260
239
|
async function getWorkspaceConfig(workspaceRoot) {
|
|
261
240
|
const data = await readSnapbackJson("config.json", workspaceRoot);
|
|
262
|
-
if (!data)
|
|
241
|
+
if (!data) {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
263
244
|
const result = WorkspaceConfigSchema.safeParse(data);
|
|
264
245
|
return result.success ? result.data : null;
|
|
265
246
|
}
|
|
@@ -270,7 +251,9 @@ async function saveWorkspaceConfig(config, workspaceRoot) {
|
|
|
270
251
|
__name(saveWorkspaceConfig, "saveWorkspaceConfig");
|
|
271
252
|
async function getWorkspaceVitals(workspaceRoot) {
|
|
272
253
|
const data = await readSnapbackJson("vitals.json", workspaceRoot);
|
|
273
|
-
if (!data)
|
|
254
|
+
if (!data) {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
274
257
|
const result = WorkspaceVitalsSchema.safeParse(data);
|
|
275
258
|
return result.success ? result.data : null;
|
|
276
259
|
}
|
|
@@ -281,7 +264,9 @@ async function saveWorkspaceVitals(vitals, workspaceRoot) {
|
|
|
281
264
|
__name(saveWorkspaceVitals, "saveWorkspaceVitals");
|
|
282
265
|
async function getProtectedFiles(workspaceRoot) {
|
|
283
266
|
const data = await readSnapbackJson("protected.json", workspaceRoot);
|
|
284
|
-
if (!data)
|
|
267
|
+
if (!data) {
|
|
268
|
+
return [];
|
|
269
|
+
}
|
|
285
270
|
const result = z.array(ProtectedFileSchema).safeParse(data);
|
|
286
271
|
return result.success ? result.data : [];
|
|
287
272
|
}
|
|
@@ -292,7 +277,9 @@ async function saveProtectedFiles(files, workspaceRoot) {
|
|
|
292
277
|
__name(saveProtectedFiles, "saveProtectedFiles");
|
|
293
278
|
async function getCurrentSession(workspaceRoot) {
|
|
294
279
|
const data = await readSnapbackJson("session/current.json", workspaceRoot);
|
|
295
|
-
if (!data)
|
|
280
|
+
if (!data) {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
296
283
|
const result = SessionStateSchema.safeParse(data);
|
|
297
284
|
return result.success ? result.data : null;
|
|
298
285
|
}
|
|
@@ -330,7 +317,7 @@ async function getViolations(workspaceRoot) {
|
|
|
330
317
|
__name(getViolations, "getViolations");
|
|
331
318
|
async function getCredentials() {
|
|
332
319
|
try {
|
|
333
|
-
const { getCredentialsSecure } = await import('./secure-credentials-
|
|
320
|
+
const { getCredentialsSecure } = await import('./secure-credentials-UEPG7GWW.js');
|
|
334
321
|
return await getCredentialsSecure();
|
|
335
322
|
} catch {
|
|
336
323
|
return readGlobalJson("credentials.json");
|
|
@@ -339,7 +326,7 @@ async function getCredentials() {
|
|
|
339
326
|
__name(getCredentials, "getCredentials");
|
|
340
327
|
async function saveCredentials(credentials) {
|
|
341
328
|
try {
|
|
342
|
-
const { saveCredentialsSecure } = await import('./secure-credentials-
|
|
329
|
+
const { saveCredentialsSecure } = await import('./secure-credentials-UEPG7GWW.js');
|
|
343
330
|
return await saveCredentialsSecure(credentials);
|
|
344
331
|
} catch {
|
|
345
332
|
await createGlobalDirectory();
|
|
@@ -349,7 +336,7 @@ async function saveCredentials(credentials) {
|
|
|
349
336
|
__name(saveCredentials, "saveCredentials");
|
|
350
337
|
async function clearCredentials() {
|
|
351
338
|
try {
|
|
352
|
-
const { clearCredentialsSecure } = await import('./secure-credentials-
|
|
339
|
+
const { clearCredentialsSecure } = await import('./secure-credentials-UEPG7GWW.js');
|
|
353
340
|
return await clearCredentialsSecure();
|
|
354
341
|
} catch {
|
|
355
342
|
await deleteGlobalJson("credentials.json");
|
|
@@ -358,7 +345,9 @@ async function clearCredentials() {
|
|
|
358
345
|
__name(clearCredentials, "clearCredentials");
|
|
359
346
|
async function getGlobalConfig() {
|
|
360
347
|
const data = await readGlobalJson("config.json");
|
|
361
|
-
if (!data)
|
|
348
|
+
if (!data) {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
362
351
|
const result = GlobalConfigSchema.safeParse(data);
|
|
363
352
|
return result.success ? result.data : null;
|
|
364
353
|
}
|
|
@@ -415,6 +404,4 @@ async function getStats(path) {
|
|
|
415
404
|
}
|
|
416
405
|
__name(getStats, "getStats");
|
|
417
406
|
|
|
418
|
-
export { GlobalConfigSchema, GlobalCredentialsSchema, LearningEntrySchema, ProtectedFileSchema, SessionStateSchema, ViolationEntrySchema, WorkspaceConfigSchema, WorkspaceVitalsSchema, appendSnapbackJsonl, clearCredentials, createGlobalDirectory, createSnapbackDirectory, deleteGlobalJson, endCurrentSession, findWorkspaceRoot,
|
|
419
|
-
//# sourceMappingURL=chunk-7JX6Y4TL.js.map
|
|
420
|
-
//# sourceMappingURL=chunk-7JX6Y4TL.js.map
|
|
407
|
+
export { GlobalConfigSchema, GlobalCredentialsSchema, LearningEntrySchema, ProtectedFileSchema, SessionStateSchema, ViolationEntrySchema, WorkspaceConfigSchema, WorkspaceVitalsSchema, appendSnapbackJsonl, clearCredentials, createGlobalDirectory, createSnapbackDirectory, deleteGlobalJson, endCurrentSession, findWorkspaceRoot, getCredentials, getCurrentSession, getGlobalConfig, getGlobalDir, getGlobalPath, getLearnings, getProtectedFiles, getStats, getViolations, getWorkspaceConfig, getWorkspaceDir, getWorkspacePath, getWorkspaceVitals, isLoggedIn, isSnapbackInitialized, loadSnapbackJsonl, pathExists, readGlobalJson, readSnapbackJson, recordLearning, recordViolation, saveCredentials, saveCurrentSession, saveGlobalConfig, saveProtectedFiles, saveWorkspaceConfig, saveWorkspaceVitals, writeGlobalJson, writeSnapbackJson };
|
|
@@ -1,17 +1,92 @@
|
|
|
1
1
|
#!/usr/bin/env node --no-warnings=ExperimentalWarning
|
|
2
|
-
import { __name } from './chunk-
|
|
3
|
-
import {
|
|
2
|
+
import { __name } from './chunk-7ADPL4Q3.js';
|
|
3
|
+
import { readFileSync, mkdirSync, writeFileSync, existsSync } from 'fs';
|
|
4
4
|
import { homedir, platform } from 'os';
|
|
5
5
|
import { join, resolve, dirname } from 'path';
|
|
6
6
|
import { randomUUID } from 'crypto';
|
|
7
7
|
import { exec, execSync } from 'child_process';
|
|
8
8
|
import { promisify } from 'util';
|
|
9
9
|
|
|
10
|
+
process.env.SNAPBACK_CLI='true';
|
|
10
11
|
var __defProp = Object.defineProperty;
|
|
11
12
|
var __name2 = /* @__PURE__ */ __name((target, value) => __defProp(target, "name", {
|
|
12
13
|
value,
|
|
13
14
|
configurable: true
|
|
14
15
|
}), "__name");
|
|
16
|
+
var CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
17
|
+
function getCacheFilePath() {
|
|
18
|
+
return join(homedir(), ".snapback", "mcp-configs", "paths.json");
|
|
19
|
+
}
|
|
20
|
+
__name(getCacheFilePath, "getCacheFilePath");
|
|
21
|
+
__name2(getCacheFilePath, "getCacheFilePath");
|
|
22
|
+
function readCache() {
|
|
23
|
+
try {
|
|
24
|
+
const raw = readFileSync(getCacheFilePath(), "utf-8");
|
|
25
|
+
const parsed = JSON.parse(raw);
|
|
26
|
+
if (parsed.version === 1 && typeof parsed.discovered === "object") {
|
|
27
|
+
return parsed;
|
|
28
|
+
}
|
|
29
|
+
} catch {
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
version: 1,
|
|
33
|
+
discovered: {}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
__name(readCache, "readCache");
|
|
37
|
+
__name2(readCache, "readCache");
|
|
38
|
+
function writeCache(cache) {
|
|
39
|
+
try {
|
|
40
|
+
const dir = join(homedir(), ".snapback", "mcp-configs");
|
|
41
|
+
mkdirSync(dir, {
|
|
42
|
+
recursive: true
|
|
43
|
+
});
|
|
44
|
+
writeFileSync(getCacheFilePath(), JSON.stringify(cache, null, 2));
|
|
45
|
+
} catch {
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
__name(writeCache, "writeCache");
|
|
49
|
+
__name2(writeCache, "writeCache");
|
|
50
|
+
function getCachedPath(clientName) {
|
|
51
|
+
const cache = readCache();
|
|
52
|
+
const entry = cache.discovered[clientName];
|
|
53
|
+
if (!entry) return null;
|
|
54
|
+
const age = Date.now() - new Date(entry.discoveredAt).getTime();
|
|
55
|
+
if (age > CACHE_TTL_MS) return null;
|
|
56
|
+
if (!existsSync(entry.path)) {
|
|
57
|
+
delete cache.discovered[clientName];
|
|
58
|
+
writeCache(cache);
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return entry.path;
|
|
62
|
+
}
|
|
63
|
+
__name(getCachedPath, "getCachedPath");
|
|
64
|
+
__name2(getCachedPath, "getCachedPath");
|
|
65
|
+
function setCachedPath(clientName, configPath) {
|
|
66
|
+
const cache = readCache();
|
|
67
|
+
cache.discovered[clientName] = {
|
|
68
|
+
path: configPath,
|
|
69
|
+
discoveredAt: /* @__PURE__ */ (/* @__PURE__ */ new Date()).toISOString(),
|
|
70
|
+
platform: process.platform
|
|
71
|
+
};
|
|
72
|
+
writeCache(cache);
|
|
73
|
+
}
|
|
74
|
+
__name(setCachedPath, "setCachedPath");
|
|
75
|
+
__name2(setCachedPath, "setCachedPath");
|
|
76
|
+
function evictCachedPath(clientName) {
|
|
77
|
+
const cache = readCache();
|
|
78
|
+
if (cache.discovered[clientName]) {
|
|
79
|
+
delete cache.discovered[clientName];
|
|
80
|
+
writeCache(cache);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
__name(evictCachedPath, "evictCachedPath");
|
|
84
|
+
__name2(evictCachedPath, "evictCachedPath");
|
|
85
|
+
function getAllCachedPaths() {
|
|
86
|
+
return readCache().discovered;
|
|
87
|
+
}
|
|
88
|
+
__name(getAllCachedPaths, "getAllCachedPaths");
|
|
89
|
+
__name2(getAllCachedPaths, "getAllCachedPaths");
|
|
15
90
|
var CLIENT_CONFIGS = {
|
|
16
91
|
claude: /* @__PURE__ */ __name2((home) => {
|
|
17
92
|
switch (platform()) {
|
|
@@ -36,14 +111,17 @@ var CLIENT_CONFIGS = {
|
|
|
36
111
|
] : [],
|
|
37
112
|
join(_home, ".cursor/mcp.json")
|
|
38
113
|
], "cursor"),
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
join(cwd, ".windsurf/mcp.json")
|
|
42
|
-
] : [],
|
|
114
|
+
// Windsurf only has a global config — no project-level support (confirmed by Windsurf docs, June 2025)
|
|
115
|
+
windsurf: /* @__PURE__ */ __name2((home) => [
|
|
43
116
|
join(home, ".codeium/windsurf/mcp_config.json")
|
|
44
117
|
], "windsurf"),
|
|
45
|
-
|
|
46
|
-
|
|
118
|
+
// Continue: global config.json or config.yaml; project-level .continue/mcpServers/mcp.json
|
|
119
|
+
continue: /* @__PURE__ */ __name2((home, cwd) => [
|
|
120
|
+
...cwd ? [
|
|
121
|
+
join(cwd, ".continue/mcpServers/mcp.json")
|
|
122
|
+
] : [],
|
|
123
|
+
join(home, ".continue/config.json"),
|
|
124
|
+
join(home, ".continue/config.yaml")
|
|
47
125
|
], "continue"),
|
|
48
126
|
// New clients
|
|
49
127
|
vscode: /* @__PURE__ */ __name2((_home, cwd) => [
|
|
@@ -51,9 +129,16 @@ var CLIENT_CONFIGS = {
|
|
|
51
129
|
join(cwd, ".vscode/mcp.json")
|
|
52
130
|
] : []
|
|
53
131
|
], "vscode"),
|
|
54
|
-
|
|
132
|
+
// Zed: global ~/.config/zed/settings.json, plus project-level .zed/settings.json
|
|
133
|
+
zed: /* @__PURE__ */ __name2((home, cwd) => [
|
|
134
|
+
...cwd ? [
|
|
135
|
+
join(cwd, ".zed/settings.json")
|
|
136
|
+
] : [],
|
|
55
137
|
join(home, ".config/zed/settings.json")
|
|
56
138
|
], "zed"),
|
|
139
|
+
// Cline / Roo Code store their actual settings in VS Code extension globalStorage,
|
|
140
|
+
// but `snap tools configure --cline/--roo-code` writes to these paths as a side-channel.
|
|
141
|
+
// Detection via these paths is best-effort; users may need `snap mcp link --client cline` instead.
|
|
57
142
|
cline: /* @__PURE__ */ __name2((home) => [
|
|
58
143
|
join(home, ".cline/mcp.json")
|
|
59
144
|
], "cline"),
|
|
@@ -71,19 +156,26 @@ var CLIENT_CONFIGS = {
|
|
|
71
156
|
const workspaceConfig = cwd ? [
|
|
72
157
|
join(cwd, ".qoder-mcp-config.json")
|
|
73
158
|
] : [];
|
|
74
|
-
const
|
|
159
|
+
const globalConfigs = (() => {
|
|
75
160
|
switch (platform()) {
|
|
76
161
|
case "darwin":
|
|
77
|
-
return
|
|
162
|
+
return [
|
|
163
|
+
join(home, "Library/Application Support/Qoder/SharedClientCache/mcp.json"),
|
|
164
|
+
join(home, "Library/Application Support/Qoder/SharedClientCache/extension/local/mcp.json")
|
|
165
|
+
];
|
|
78
166
|
case "win32":
|
|
79
|
-
return
|
|
167
|
+
return [
|
|
168
|
+
join(process.env.APPDATA || "", "Qoder/mcp.json")
|
|
169
|
+
];
|
|
80
170
|
default:
|
|
81
|
-
return
|
|
171
|
+
return [
|
|
172
|
+
join(home, ".config/Qoder/mcp.json")
|
|
173
|
+
];
|
|
82
174
|
}
|
|
83
175
|
})();
|
|
84
176
|
return [
|
|
85
177
|
...workspaceConfig,
|
|
86
|
-
|
|
178
|
+
...globalConfigs
|
|
87
179
|
];
|
|
88
180
|
}, "qoder")
|
|
89
181
|
};
|
|
@@ -106,7 +198,12 @@ function detectAIClients(options = {}) {
|
|
|
106
198
|
const clients = [];
|
|
107
199
|
const seenPaths = /* @__PURE__ */ new Set();
|
|
108
200
|
for (const [name, getPaths] of Object.entries(CLIENT_CONFIGS)) {
|
|
109
|
-
const
|
|
201
|
+
const candidates = getPaths(home, cwd);
|
|
202
|
+
const cachedPath = getCachedPath(name);
|
|
203
|
+
const paths = cachedPath && candidates.includes(cachedPath) ? [
|
|
204
|
+
cachedPath,
|
|
205
|
+
...candidates.filter((p) => p !== cachedPath)
|
|
206
|
+
] : candidates;
|
|
110
207
|
for (const configPath of paths) {
|
|
111
208
|
if (seenPaths.has(configPath)) {
|
|
112
209
|
continue;
|
|
@@ -115,6 +212,7 @@ function detectAIClients(options = {}) {
|
|
|
115
212
|
const exists = existsSync(configPath);
|
|
116
213
|
let hasSnapback = false;
|
|
117
214
|
if (exists) {
|
|
215
|
+
setCachedPath(name, configPath);
|
|
118
216
|
try {
|
|
119
217
|
const content = readFileSync(configPath, "utf-8");
|
|
120
218
|
if (configPath.endsWith(".yaml") || configPath.endsWith(".yml")) {
|
|
@@ -169,12 +267,17 @@ function checkForSnapback(config, format) {
|
|
|
169
267
|
case "windsurf":
|
|
170
268
|
case "cline":
|
|
171
269
|
case "roo-code":
|
|
172
|
-
case "qoder":
|
|
173
270
|
if ("mcpServers" in configObj && typeof configObj.mcpServers === "object" && configObj.mcpServers !== null) {
|
|
174
271
|
const servers = configObj.mcpServers;
|
|
175
272
|
return "snapback" in servers || `snapback-${format}` in servers;
|
|
176
273
|
}
|
|
177
274
|
return false;
|
|
275
|
+
case "qoder":
|
|
276
|
+
if ("mcpServers" in configObj && typeof configObj.mcpServers === "object" && configObj.mcpServers !== null) {
|
|
277
|
+
const servers = configObj.mcpServers;
|
|
278
|
+
return Object.keys(servers).some((k) => k === "snapback" || k.startsWith("snapback-"));
|
|
279
|
+
}
|
|
280
|
+
return false;
|
|
178
281
|
case "vscode":
|
|
179
282
|
if ("servers" in configObj && typeof configObj.servers === "object" && configObj.servers !== null) {
|
|
180
283
|
const servers = configObj.servers;
|
|
@@ -771,6 +874,32 @@ function resolveNodePath() {
|
|
|
771
874
|
}
|
|
772
875
|
__name(resolveNodePath, "resolveNodePath");
|
|
773
876
|
__name2(resolveNodePath, "resolveNodePath");
|
|
877
|
+
function resolveSnapbackBinaryPath() {
|
|
878
|
+
try {
|
|
879
|
+
const isWindows = process.platform === "win32";
|
|
880
|
+
const command = isWindows ? "where snapback" : "which snapback";
|
|
881
|
+
const result = execSync(command, {
|
|
882
|
+
encoding: "utf-8",
|
|
883
|
+
timeout: 5e3
|
|
884
|
+
}).trim();
|
|
885
|
+
const binaryPath = result.split(/\r?\n/)[0].trim();
|
|
886
|
+
if (binaryPath && existsSync(binaryPath)) {
|
|
887
|
+
return binaryPath;
|
|
888
|
+
}
|
|
889
|
+
} catch {
|
|
890
|
+
}
|
|
891
|
+
const commonPaths = [
|
|
892
|
+
"/opt/homebrew/bin/snapback",
|
|
893
|
+
"/usr/local/bin/snapback",
|
|
894
|
+
"/usr/bin/snapback"
|
|
895
|
+
];
|
|
896
|
+
for (const p of commonPaths) {
|
|
897
|
+
if (existsSync(p)) return p;
|
|
898
|
+
}
|
|
899
|
+
return "snapback";
|
|
900
|
+
}
|
|
901
|
+
__name(resolveSnapbackBinaryPath, "resolveSnapbackBinaryPath");
|
|
902
|
+
__name2(resolveSnapbackBinaryPath, "resolveSnapbackBinaryPath");
|
|
774
903
|
function isCommandExecutable2(command) {
|
|
775
904
|
if (command.startsWith("/") || command.match(/^[A-Z]:\\/i)) {
|
|
776
905
|
return existsSync(command);
|
|
@@ -793,14 +922,11 @@ var STDIO_ONLY_CLIENTS = /* @__PURE__ */ new Set([
|
|
|
793
922
|
"claude"
|
|
794
923
|
]);
|
|
795
924
|
function getSnapbackMCPConfig(options = {}) {
|
|
796
|
-
const { apiKey, workspaceId, serverUrl, useBinary = false, customCommand, additionalEnv, workspaceRoot, useLocalDev = false, localCliPath, client } = options;
|
|
925
|
+
const { apiKey, workspaceId, serverUrl, useBinary = false, customCommand, additionalEnv, workspaceRoot, useLocalDev = false, localCliPath, client, useDoppler = false, dopplerProject = "snapback-shared", dopplerConfig = "dev", useSse = false, useStreamableHttp = false } = options;
|
|
797
926
|
const useNpx = options.useNpx ?? (client ? STDIO_ONLY_CLIENTS.has(client) : false);
|
|
798
927
|
const env = {
|
|
799
928
|
...additionalEnv
|
|
800
929
|
};
|
|
801
|
-
if (workspaceId) {
|
|
802
|
-
env.SNAPBACK_WORKSPACE_ID = workspaceId;
|
|
803
|
-
}
|
|
804
930
|
if (apiKey) {
|
|
805
931
|
env.SNAPBACK_API_KEY = apiKey;
|
|
806
932
|
}
|
|
@@ -813,9 +939,65 @@ function getSnapbackMCPConfig(options = {}) {
|
|
|
813
939
|
}
|
|
814
940
|
};
|
|
815
941
|
}
|
|
942
|
+
if (useSse || useStreamableHttp) {
|
|
943
|
+
const url = serverUrl || "https://mcp.snapback.dev/mcp";
|
|
944
|
+
const headers2 = {};
|
|
945
|
+
if (workspaceId) {
|
|
946
|
+
headers2["x-workspace-id"] = workspaceId;
|
|
947
|
+
}
|
|
948
|
+
if (apiKey) {
|
|
949
|
+
headers2["x-api-key"] = apiKey;
|
|
950
|
+
}
|
|
951
|
+
return {
|
|
952
|
+
url,
|
|
953
|
+
...Object.keys(headers2).length > 0 && {
|
|
954
|
+
headers: headers2
|
|
955
|
+
}
|
|
956
|
+
};
|
|
957
|
+
}
|
|
958
|
+
if (useDoppler && localCliPath) {
|
|
959
|
+
const tier = apiKey ? "pro" : "free";
|
|
960
|
+
const nodePath = resolveNodePath();
|
|
961
|
+
const dopplerArgs = [
|
|
962
|
+
"run",
|
|
963
|
+
"--project",
|
|
964
|
+
dopplerProject,
|
|
965
|
+
"--config",
|
|
966
|
+
dopplerConfig,
|
|
967
|
+
"--",
|
|
968
|
+
nodePath,
|
|
969
|
+
localCliPath,
|
|
970
|
+
"mcp",
|
|
971
|
+
"--stdio",
|
|
972
|
+
"--tier",
|
|
973
|
+
tier
|
|
974
|
+
];
|
|
975
|
+
if (workspaceRoot) {
|
|
976
|
+
dopplerArgs.push("--workspace", workspaceRoot);
|
|
977
|
+
}
|
|
978
|
+
return {
|
|
979
|
+
command: "doppler",
|
|
980
|
+
args: dopplerArgs
|
|
981
|
+
};
|
|
982
|
+
}
|
|
816
983
|
if (useNpx) {
|
|
984
|
+
const isClaudeDesktop = client === "claude";
|
|
985
|
+
if (isClaudeDesktop) {
|
|
986
|
+
const args2 = [
|
|
987
|
+
"--yes",
|
|
988
|
+
"@snapback/mcpb"
|
|
989
|
+
];
|
|
990
|
+
if (workspaceRoot) {
|
|
991
|
+
args2.push(workspaceRoot);
|
|
992
|
+
}
|
|
993
|
+
return {
|
|
994
|
+
command: "npx",
|
|
995
|
+
args: args2
|
|
996
|
+
};
|
|
997
|
+
}
|
|
817
998
|
const tier = apiKey ? "pro" : "free";
|
|
818
999
|
const args = [
|
|
1000
|
+
"--yes",
|
|
819
1001
|
"@snapback/cli",
|
|
820
1002
|
"mcp",
|
|
821
1003
|
"--stdio",
|
|
@@ -833,12 +1015,19 @@ function getSnapbackMCPConfig(options = {}) {
|
|
|
833
1015
|
}
|
|
834
1016
|
};
|
|
835
1017
|
}
|
|
836
|
-
if (serverUrl || !useLocalDev && !useBinary) {
|
|
837
|
-
const url = serverUrl || "https://
|
|
1018
|
+
if (serverUrl || !useLocalDev && !useBinary && !useDoppler) {
|
|
1019
|
+
const url = serverUrl || "https://mcp.snapback.dev/mcp";
|
|
1020
|
+
const headers2 = {};
|
|
1021
|
+
if (workspaceId) {
|
|
1022
|
+
headers2["x-workspace-id"] = workspaceId;
|
|
1023
|
+
}
|
|
1024
|
+
if (apiKey) {
|
|
1025
|
+
headers2["x-api-key"] = apiKey;
|
|
1026
|
+
}
|
|
838
1027
|
return {
|
|
839
1028
|
url,
|
|
840
|
-
...Object.keys(
|
|
841
|
-
|
|
1029
|
+
...Object.keys(headers2).length > 0 && {
|
|
1030
|
+
headers: headers2
|
|
842
1031
|
}
|
|
843
1032
|
};
|
|
844
1033
|
}
|
|
@@ -875,17 +1064,24 @@ function getSnapbackMCPConfig(options = {}) {
|
|
|
875
1064
|
args.push("--workspace", workspaceRoot);
|
|
876
1065
|
}
|
|
877
1066
|
return {
|
|
878
|
-
command:
|
|
1067
|
+
command: resolveSnapbackBinaryPath(),
|
|
879
1068
|
args,
|
|
880
1069
|
...Object.keys(env).length > 0 && {
|
|
881
1070
|
env
|
|
882
1071
|
}
|
|
883
1072
|
};
|
|
884
1073
|
}
|
|
1074
|
+
const headers = {};
|
|
1075
|
+
if (workspaceId) {
|
|
1076
|
+
headers["x-workspace-id"] = workspaceId;
|
|
1077
|
+
}
|
|
1078
|
+
if (apiKey) {
|
|
1079
|
+
headers["x-api-key"] = apiKey;
|
|
1080
|
+
}
|
|
885
1081
|
return {
|
|
886
|
-
url: "https://
|
|
887
|
-
...Object.keys(
|
|
888
|
-
|
|
1082
|
+
url: "https://mcp.snapback.dev/mcp",
|
|
1083
|
+
...Object.keys(headers).length > 0 && {
|
|
1084
|
+
headers
|
|
889
1085
|
}
|
|
890
1086
|
};
|
|
891
1087
|
}
|
|
@@ -986,6 +1182,7 @@ function removeSnapbackConfig(client) {
|
|
|
986
1182
|
}
|
|
987
1183
|
}
|
|
988
1184
|
writeFileSync(client.configPath, JSON.stringify(config, null, 2));
|
|
1185
|
+
evictCachedPath(client.name);
|
|
989
1186
|
return {
|
|
990
1187
|
success: true
|
|
991
1188
|
};
|
|
@@ -1033,17 +1230,25 @@ function mergeConfig(existing, snapbackConfig, format) {
|
|
|
1033
1230
|
}
|
|
1034
1231
|
}
|
|
1035
1232
|
};
|
|
1036
|
-
case "qoder":
|
|
1233
|
+
case "qoder": {
|
|
1234
|
+
let qoderType;
|
|
1235
|
+
if (snapbackConfig.url) {
|
|
1236
|
+
const isLocal = snapbackConfig.url.startsWith("http://localhost") || snapbackConfig.url.startsWith("http://127.0.0.1");
|
|
1237
|
+
qoderType = isLocal ? "sse" : "http";
|
|
1238
|
+
} else {
|
|
1239
|
+
qoderType = "stdio";
|
|
1240
|
+
}
|
|
1037
1241
|
return {
|
|
1038
1242
|
...existing,
|
|
1039
1243
|
mcpServers: {
|
|
1040
1244
|
...existing.mcpServers || {},
|
|
1041
1245
|
[serverKey]: {
|
|
1042
|
-
type:
|
|
1246
|
+
type: qoderType,
|
|
1043
1247
|
...snapbackConfig
|
|
1044
1248
|
}
|
|
1045
1249
|
}
|
|
1046
1250
|
};
|
|
1251
|
+
}
|
|
1047
1252
|
case "vscode": {
|
|
1048
1253
|
const vscodeConfig = existing;
|
|
1049
1254
|
const servers = vscodeConfig.servers || {};
|
|
@@ -1105,6 +1310,87 @@ function mergeConfig(existing, snapbackConfig, format) {
|
|
|
1105
1310
|
}
|
|
1106
1311
|
__name(mergeConfig, "mergeConfig");
|
|
1107
1312
|
__name2(mergeConfig, "mergeConfig");
|
|
1313
|
+
function patchApiKeyInClientConfig(client, apiKey) {
|
|
1314
|
+
try {
|
|
1315
|
+
if (!existsSync(client.configPath)) return false;
|
|
1316
|
+
const raw = readFileSync(client.configPath, "utf-8");
|
|
1317
|
+
const config = JSON.parse(raw);
|
|
1318
|
+
const serverKey = getServerKey(client.format);
|
|
1319
|
+
let patched = false;
|
|
1320
|
+
const patchEntry = /* @__PURE__ */ __name2((entry) => {
|
|
1321
|
+
if (typeof entry !== "object" || entry === null) return false;
|
|
1322
|
+
const e = entry;
|
|
1323
|
+
if (e.url && typeof e.url === "string") {
|
|
1324
|
+
if (!e.headers || typeof e.headers !== "object") {
|
|
1325
|
+
e.headers = {};
|
|
1326
|
+
}
|
|
1327
|
+
e.headers["x-api-key"] = apiKey;
|
|
1328
|
+
const headers = e.headers;
|
|
1329
|
+
if (headers.Authorization?.includes("<your-token>")) {
|
|
1330
|
+
delete headers.Authorization;
|
|
1331
|
+
}
|
|
1332
|
+
return true;
|
|
1333
|
+
}
|
|
1334
|
+
if (!e.env || typeof e.env !== "object") {
|
|
1335
|
+
e.env = {};
|
|
1336
|
+
}
|
|
1337
|
+
e.env.SNAPBACK_API_KEY = apiKey;
|
|
1338
|
+
return true;
|
|
1339
|
+
}, "patchEntry");
|
|
1340
|
+
switch (client.format) {
|
|
1341
|
+
case "claude":
|
|
1342
|
+
case "cursor":
|
|
1343
|
+
case "windsurf":
|
|
1344
|
+
case "cline":
|
|
1345
|
+
case "roo-code":
|
|
1346
|
+
case "gemini": {
|
|
1347
|
+
const servers = config.mcpServers || {};
|
|
1348
|
+
const entry = servers[serverKey] ?? servers.snapback;
|
|
1349
|
+
if (entry) patched = patchEntry(entry);
|
|
1350
|
+
break;
|
|
1351
|
+
}
|
|
1352
|
+
case "qoder": {
|
|
1353
|
+
const servers = config.mcpServers || {};
|
|
1354
|
+
for (const key of Object.keys(servers)) {
|
|
1355
|
+
if (key === "snapback" || key.startsWith("snapback-")) {
|
|
1356
|
+
patched = patchEntry(servers[key]) || patched;
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
break;
|
|
1360
|
+
}
|
|
1361
|
+
case "vscode": {
|
|
1362
|
+
const servers = config.servers || {};
|
|
1363
|
+
const entry = servers[serverKey] ?? servers.snapback;
|
|
1364
|
+
if (entry) patched = patchEntry(entry);
|
|
1365
|
+
break;
|
|
1366
|
+
}
|
|
1367
|
+
case "zed": {
|
|
1368
|
+
const servers = config.context_servers || {};
|
|
1369
|
+
const entry = servers[serverKey] ?? servers.snapback;
|
|
1370
|
+
if (entry) patched = patchEntry(entry);
|
|
1371
|
+
break;
|
|
1372
|
+
}
|
|
1373
|
+
case "continue": {
|
|
1374
|
+
const exp = config.experimental || {};
|
|
1375
|
+
const list = exp.modelContextProtocolServers || [];
|
|
1376
|
+
for (const item of list) {
|
|
1377
|
+
if (typeof item.name === "string" && item.name.startsWith("snapback")) {
|
|
1378
|
+
patched = patchEntry(item) || patched;
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
break;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
if (patched) {
|
|
1385
|
+
writeFileSync(client.configPath, JSON.stringify(config, null, 2));
|
|
1386
|
+
}
|
|
1387
|
+
return patched;
|
|
1388
|
+
} catch {
|
|
1389
|
+
return false;
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
__name(patchApiKeyInClientConfig, "patchApiKeyInClientConfig");
|
|
1393
|
+
__name2(patchApiKeyInClientConfig, "patchApiKeyInClientConfig");
|
|
1108
1394
|
function validateConfig(client) {
|
|
1109
1395
|
try {
|
|
1110
1396
|
const content = readFileSync(client.configPath, "utf-8");
|
|
@@ -1418,6 +1704,4 @@ function findCliPath() {
|
|
|
1418
1704
|
__name(findCliPath, "findCliPath");
|
|
1419
1705
|
__name2(findCliPath, "findCliPath");
|
|
1420
1706
|
|
|
1421
|
-
export { createManagedMetadata, detectAIClients, detectMCPProcesses, detectWorkspaceConfig, getClient, getClientConfigPath, getConfiguredClients, getOrCreateIdentity, getServerKey, getSnapbackConfigDir, getSnapbackMCPConfig, injectWorkspacePath, isCommandExecutable2, isOwnedByThisInstall, isSnapbackMCPRunning, readClientConfig, removeSnapbackConfig, repairClientConfig, resetIdentityCache, resolveNodePath, validateClientConfig, validateConfig, validateWorkspacePath, writeClientConfig };
|
|
1422
|
-
//# sourceMappingURL=chunk-R7CUQ7CU.js.map
|
|
1423
|
-
//# sourceMappingURL=chunk-R7CUQ7CU.js.map
|
|
1707
|
+
export { createManagedMetadata, detectAIClients, detectMCPProcesses, detectWorkspaceConfig, evictCachedPath, getAllCachedPaths, getCachedPath, getClient, getClientConfigPath, getConfiguredClients, getOrCreateIdentity, getServerKey, getSnapbackConfigDir, getSnapbackMCPConfig, injectWorkspacePath, isCommandExecutable2, isOwnedByThisInstall, isSnapbackMCPRunning, patchApiKeyInClientConfig, readClientConfig, removeSnapbackConfig, repairClientConfig, resetIdentityCache, resolveNodePath, setCachedPath, validateClientConfig, validateConfig, validateWorkspacePath, writeClientConfig };
|