@openchamber/web 1.11.0 → 1.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{JsonTreeView-CUIfrcFf.js → JsonTreeView-9F0tH9yA.js} +1 -1
- package/dist/assets/{MarkdownRendererImpl-Bma9y3dD.js → MarkdownRendererImpl-C3QofAGm.js} +2 -2
- package/dist/assets/{MultiRunWindow-Cwc0x7fs.js → MultiRunWindow-wnUGv0Dl.js} +1 -1
- package/dist/assets/{OnboardingScreen-BhozUlcE.js → OnboardingScreen-17dAs0NH.js} +2 -2
- package/dist/assets/{SettingsWindow-B4B2bn0C.js → SettingsWindow-BgyVY5gz.js} +1 -1
- package/dist/assets/{TerminalView-BpoHWJj6.js → TerminalView-D11XIZuz.js} +1 -1
- package/dist/assets/{ToolOutputDialog-7U42lN20.js → ToolOutputDialog-DFG7ANVw.js} +6 -6
- package/dist/assets/es-Chl2Hu6K.js +15 -0
- package/dist/assets/index-0bVkxg-Z.css +1 -0
- package/dist/assets/{index-B2ztI3pp.js → index-BV2XTsJJ.js} +1 -1
- package/dist/assets/ko-BSrH3F9n.js +15 -0
- package/dist/assets/{main-rHOaDqOy.js → main-BHkNwOz1.js} +2 -2
- package/dist/assets/main-Bqf4fXgq.js +225 -0
- package/dist/assets/miniChat-BmB-E5xo.js +2 -0
- package/dist/assets/{modelPrefsAutoSave-D5z_F_WP.js → modelPrefsAutoSave-2uwW8uD9.js} +104 -96
- package/dist/assets/pl-YlGvPmFg.js +15 -0
- package/dist/assets/pt-BR-BonIMDN_.js +15 -0
- package/dist/assets/renderElectronMiniChatApp-B_qrXCU2.js +2 -0
- package/dist/assets/uk-lPqA3MHn.js +15 -0
- package/dist/assets/{vendor-.bun-BFTPeDgG.js → vendor-.bun-Boz6Tqcq.js} +20 -20
- package/dist/assets/zh-CN-C5nQQsUL.js +15 -0
- package/dist/index.html +4 -4
- package/dist/mini-chat.html +4 -4
- package/package.json +1 -1
- package/server/lib/git/DOCUMENTATION.md +1 -0
- package/server/lib/git/routes.js +26 -0
- package/server/lib/git/service.js +96 -10
- package/server/lib/git/service.test.js +39 -0
- package/server/lib/opencode/settings-helpers.js +10 -1
- package/server/lib/opencode/settings-helpers.test.js +35 -0
- package/server/lib/opencode/skill-routes.js +43 -49
- package/server/lib/opencode/skills.js +78 -10
- package/server/lib/preview/proxy-runtime.js +43 -3
- package/dist/assets/es-DLzL0vVb.js +0 -15
- package/dist/assets/index-D5TVqnib.css +0 -1
- package/dist/assets/ko-apnbnEuD.js +0 -15
- package/dist/assets/main-ClS4RVxe.js +0 -217
- package/dist/assets/miniChat-Cx8YK32Y.js +0 -2
- package/dist/assets/pl-DUKUujvh.js +0 -15
- package/dist/assets/pt-BR-D0UPeIZC.js +0 -15
- package/dist/assets/renderElectronMiniChatApp-zbukf-1g.js +0 -2
- package/dist/assets/uk-CaTe2At9.js +0 -15
- package/dist/assets/zh-CN-D-oQmPdK.js +0 -15
|
@@ -69,6 +69,14 @@ function getClaudeSkillPath(workingDirectory, skillName) {
|
|
|
69
69
|
return path.join(getClaudeSkillDir(workingDirectory, skillName), 'SKILL.md');
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
function getUserClaudeSkillDir(skillName) {
|
|
73
|
+
return path.join(os.homedir(), '.claude', 'skills', skillName);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function getUserClaudeSkillPath(skillName) {
|
|
77
|
+
return path.join(getUserClaudeSkillDir(skillName), 'SKILL.md');
|
|
78
|
+
}
|
|
79
|
+
|
|
72
80
|
function getUserAgentsSkillDir(skillName) {
|
|
73
81
|
return path.join(os.homedir(), '.agents', 'skills', skillName);
|
|
74
82
|
}
|
|
@@ -107,6 +115,16 @@ function getSkillScope(skillName, workingDirectory) {
|
|
|
107
115
|
if (fs.existsSync(userPath)) {
|
|
108
116
|
return { scope: SKILL_SCOPE.USER, path: userPath, source: 'opencode' };
|
|
109
117
|
}
|
|
118
|
+
|
|
119
|
+
const userClaudePath = getUserClaudeSkillPath(skillName);
|
|
120
|
+
if (fs.existsSync(userClaudePath)) {
|
|
121
|
+
return { scope: SKILL_SCOPE.USER, path: userClaudePath, source: 'claude' };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const userAgentsPath = getUserAgentsSkillPath(skillName);
|
|
125
|
+
if (fs.existsSync(userAgentsPath)) {
|
|
126
|
+
return { scope: SKILL_SCOPE.USER, path: userAgentsPath, source: 'agents' };
|
|
127
|
+
}
|
|
110
128
|
|
|
111
129
|
return { scope: null, path: null, source: null };
|
|
112
130
|
}
|
|
@@ -226,11 +244,18 @@ function getSkillSources(skillName, workingDirectory, discoveredSkill = null) {
|
|
|
226
244
|
const claudePath = workingDirectory ? getClaudeSkillPath(workingDirectory, skillName) : null;
|
|
227
245
|
const claudeExists = claudePath && fs.existsSync(claudePath);
|
|
228
246
|
const claudeDir = claudeExists ? path.dirname(claudePath) : null;
|
|
247
|
+
const userClaudePath = getUserClaudeSkillPath(skillName);
|
|
248
|
+
const userClaudeExists = fs.existsSync(userClaudePath);
|
|
249
|
+
const userClaudeDir = userClaudeExists ? path.dirname(userClaudePath) : null;
|
|
229
250
|
|
|
230
251
|
const userPath = getUserSkillPath(skillName);
|
|
231
252
|
const userExists = fs.existsSync(userPath);
|
|
232
253
|
const userDir = userExists ? path.dirname(userPath) : null;
|
|
233
254
|
|
|
255
|
+
const userAgentsPath = getUserAgentsSkillPath(skillName);
|
|
256
|
+
const userAgentsExists = fs.existsSync(userAgentsPath);
|
|
257
|
+
const userAgentsDir = userAgentsExists ? path.dirname(userAgentsPath) : null;
|
|
258
|
+
|
|
234
259
|
const matchedDiscovered = discoveredSkill && discoveredSkill.name === skillName
|
|
235
260
|
? discoveredSkill
|
|
236
261
|
: discoverSkills(workingDirectory).find((skill) => skill.name === skillName);
|
|
@@ -240,7 +265,12 @@ function getSkillSources(skillName, workingDirectory, discoveredSkill = null) {
|
|
|
240
265
|
let mdSource = null;
|
|
241
266
|
let mdDir = null;
|
|
242
267
|
|
|
243
|
-
if (
|
|
268
|
+
if (matchedDiscovered?.path) {
|
|
269
|
+
mdPath = matchedDiscovered.path;
|
|
270
|
+
mdScope = matchedDiscovered.scope || null;
|
|
271
|
+
mdSource = matchedDiscovered.source || null;
|
|
272
|
+
mdDir = path.dirname(matchedDiscovered.path);
|
|
273
|
+
} else if (projectExists) {
|
|
244
274
|
mdPath = projectPath;
|
|
245
275
|
mdScope = SKILL_SCOPE.PROJECT;
|
|
246
276
|
mdSource = 'opencode';
|
|
@@ -255,14 +285,23 @@ function getSkillSources(skillName, workingDirectory, discoveredSkill = null) {
|
|
|
255
285
|
mdScope = SKILL_SCOPE.USER;
|
|
256
286
|
mdSource = 'opencode';
|
|
257
287
|
mdDir = userDir;
|
|
258
|
-
} else if (
|
|
259
|
-
mdPath =
|
|
260
|
-
mdScope =
|
|
261
|
-
mdSource =
|
|
262
|
-
mdDir =
|
|
288
|
+
} else if (userClaudeExists) {
|
|
289
|
+
mdPath = userClaudePath;
|
|
290
|
+
mdScope = SKILL_SCOPE.USER;
|
|
291
|
+
mdSource = 'claude';
|
|
292
|
+
mdDir = userClaudeDir;
|
|
293
|
+
} else if (userAgentsExists) {
|
|
294
|
+
mdPath = userAgentsPath;
|
|
295
|
+
mdScope = SKILL_SCOPE.USER;
|
|
296
|
+
mdSource = 'agents';
|
|
297
|
+
mdDir = userAgentsDir;
|
|
263
298
|
}
|
|
264
299
|
|
|
265
|
-
const mdExists = !!mdPath;
|
|
300
|
+
const mdExists = !!mdPath && fs.existsSync(mdPath);
|
|
301
|
+
if (!mdExists) {
|
|
302
|
+
mdPath = null;
|
|
303
|
+
mdDir = null;
|
|
304
|
+
}
|
|
266
305
|
|
|
267
306
|
const sources = {
|
|
268
307
|
md: {
|
|
@@ -288,6 +327,16 @@ function getSkillSources(skillName, workingDirectory, discoveredSkill = null) {
|
|
|
288
327
|
exists: userExists,
|
|
289
328
|
path: userPath,
|
|
290
329
|
dir: userDir
|
|
330
|
+
},
|
|
331
|
+
userClaudeMd: {
|
|
332
|
+
exists: userClaudeExists,
|
|
333
|
+
path: userClaudePath,
|
|
334
|
+
dir: userClaudeDir
|
|
335
|
+
},
|
|
336
|
+
userAgentsMd: {
|
|
337
|
+
exists: userAgentsExists,
|
|
338
|
+
path: userAgentsPath,
|
|
339
|
+
dir: userAgentsDir
|
|
291
340
|
}
|
|
292
341
|
};
|
|
293
342
|
|
|
@@ -374,22 +423,34 @@ function createSkill(skillName, config, workingDirectory, scope) {
|
|
|
374
423
|
console.log(`Created new skill: ${skillName} (scope: ${targetScope}, path: ${targetPath})`);
|
|
375
424
|
}
|
|
376
425
|
|
|
377
|
-
function updateSkill(skillName, updates, workingDirectory) {
|
|
426
|
+
function updateSkill(skillName, updates, workingDirectory, targetPath = null) {
|
|
378
427
|
ensureDirs();
|
|
379
428
|
|
|
380
|
-
const
|
|
429
|
+
const requestedPath = typeof targetPath === 'string' && targetPath.trim()
|
|
430
|
+
? path.resolve(targetPath.trim())
|
|
431
|
+
: null;
|
|
432
|
+
const existing = requestedPath && fs.existsSync(requestedPath)
|
|
433
|
+
? { scope: null, path: requestedPath, source: null }
|
|
434
|
+
: getSkillScope(skillName, workingDirectory);
|
|
381
435
|
if (!existing.path) {
|
|
382
436
|
throw new Error(`Skill "${skillName}" not found`);
|
|
383
437
|
}
|
|
438
|
+
if (path.basename(existing.path) !== 'SKILL.md') {
|
|
439
|
+
throw new Error(`Skill "${skillName}" target must be a SKILL.md file`);
|
|
440
|
+
}
|
|
384
441
|
|
|
385
442
|
const mdPath = existing.path;
|
|
386
443
|
const mdDir = path.dirname(mdPath);
|
|
387
444
|
const mdData = parseMdFile(mdPath);
|
|
445
|
+
const frontmatterName = typeof mdData.frontmatter?.name === 'string' ? mdData.frontmatter.name : skillName;
|
|
446
|
+
if (frontmatterName !== skillName) {
|
|
447
|
+
throw new Error(`Skill "${skillName}" does not match ${mdPath}`);
|
|
448
|
+
}
|
|
388
449
|
|
|
389
450
|
let mdModified = false;
|
|
390
451
|
|
|
391
452
|
for (const [field, value] of Object.entries(updates)) {
|
|
392
|
-
if (field === 'scope') {
|
|
453
|
+
if (field === 'scope' || field === 'source' || field === 'targetPath') {
|
|
393
454
|
continue;
|
|
394
455
|
}
|
|
395
456
|
|
|
@@ -464,6 +525,13 @@ function deleteSkill(skillName, workingDirectory) {
|
|
|
464
525
|
deleted = true;
|
|
465
526
|
}
|
|
466
527
|
|
|
528
|
+
const userClaudeDir = getUserClaudeSkillDir(skillName);
|
|
529
|
+
if (fs.existsSync(userClaudeDir)) {
|
|
530
|
+
fs.rmSync(userClaudeDir, { recursive: true, force: true });
|
|
531
|
+
console.log(`Deleted user-level claude skill directory: ${userClaudeDir}`);
|
|
532
|
+
deleted = true;
|
|
533
|
+
}
|
|
534
|
+
|
|
467
535
|
if (!deleted) {
|
|
468
536
|
throw new Error(`Skill "${skillName}" not found`);
|
|
469
537
|
}
|
|
@@ -484,9 +484,35 @@ const PREVIEW_BRIDGE_SCRIPT = String.raw`(() => {
|
|
|
484
484
|
};
|
|
485
485
|
|
|
486
486
|
const proxiedUrl = (value) => {
|
|
487
|
-
if (typeof value !== 'string'
|
|
488
|
-
if (
|
|
489
|
-
|
|
487
|
+
if (typeof value !== 'string') return value;
|
|
488
|
+
if (value.startsWith('/')) {
|
|
489
|
+
if (!shouldProxyPath(value)) return value;
|
|
490
|
+
return proxyBase + value;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
try {
|
|
494
|
+
const parsed = new URL(value, window.location.href);
|
|
495
|
+
if (parsed.origin === window.location.origin && shouldProxyPath(parsed.pathname)) {
|
|
496
|
+
return proxyBase + parsed.pathname + parsed.search + parsed.hash;
|
|
497
|
+
}
|
|
498
|
+
} catch {}
|
|
499
|
+
|
|
500
|
+
return value;
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
const proxiedWebSocketUrl = (value) => {
|
|
504
|
+
if (typeof value !== 'string') return value;
|
|
505
|
+
try {
|
|
506
|
+
const parsed = new URL(value, window.location.href);
|
|
507
|
+
const current = new URL(window.location.href);
|
|
508
|
+
const sameHost = parsed.host === current.host;
|
|
509
|
+
const isWebSocketProtocol = parsed.protocol === 'ws:' || parsed.protocol === 'wss:';
|
|
510
|
+
if (sameHost && isWebSocketProtocol && shouldProxyPath(parsed.pathname)) {
|
|
511
|
+
parsed.pathname = proxyBase + parsed.pathname;
|
|
512
|
+
return parsed.toString();
|
|
513
|
+
}
|
|
514
|
+
} catch {}
|
|
515
|
+
return value;
|
|
490
516
|
};
|
|
491
517
|
|
|
492
518
|
if (typeof window.fetch === 'function') {
|
|
@@ -529,6 +555,20 @@ const PREVIEW_BRIDGE_SCRIPT = String.raw`(() => {
|
|
|
529
555
|
Object.defineProperty(OpenChamberPreviewEventSource, 'name', { value: 'EventSource' });
|
|
530
556
|
window.EventSource = OpenChamberPreviewEventSource;
|
|
531
557
|
}
|
|
558
|
+
|
|
559
|
+
if (typeof window.WebSocket === 'function') {
|
|
560
|
+
const NativeWebSocket = window.WebSocket;
|
|
561
|
+
function OpenChamberPreviewAppWebSocket(url, protocols) {
|
|
562
|
+
const nextUrl = proxiedWebSocketUrl(String(url));
|
|
563
|
+
return arguments.length === 1
|
|
564
|
+
? new NativeWebSocket(nextUrl)
|
|
565
|
+
: new NativeWebSocket(nextUrl, protocols);
|
|
566
|
+
}
|
|
567
|
+
OpenChamberPreviewAppWebSocket.prototype = NativeWebSocket.prototype;
|
|
568
|
+
Object.setPrototypeOf(OpenChamberPreviewAppWebSocket, NativeWebSocket);
|
|
569
|
+
Object.defineProperty(OpenChamberPreviewAppWebSocket, 'name', { value: 'WebSocket' });
|
|
570
|
+
window.WebSocket = OpenChamberPreviewAppWebSocket;
|
|
571
|
+
}
|
|
532
572
|
};
|
|
533
573
|
|
|
534
574
|
const selectorPart = (element) => {
|