ocx 1.0.5 → 1.0.6

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/index.js CHANGED
@@ -13082,7 +13082,8 @@ var componentManifestSchema = exports_external.object({
13082
13082
  npmDependencies: exports_external.array(exports_external.string()).optional(),
13083
13083
  npmDevDependencies: exports_external.array(exports_external.string()).optional(),
13084
13084
  mcpServers: exports_external.record(mcpServerSchema).optional(),
13085
- mcpScope: exports_external.enum(["agent", "global"]).default("agent")
13085
+ mcpScope: exports_external.enum(["agent", "global"]).default("agent"),
13086
+ disabledTools: exports_external.array(exports_external.string()).optional()
13086
13087
  });
13087
13088
  var semverRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/;
13088
13089
  var registrySchema = exports_external.object({
@@ -13251,6 +13252,93 @@ async function fetchFileContent(baseUrl, componentName, filePath) {
13251
13252
  return response.text();
13252
13253
  }
13253
13254
 
13255
+ // src/registry/resolver.ts
13256
+ async function resolveDependencies(registries, componentNames) {
13257
+ const resolved = new Map;
13258
+ const visiting = new Set;
13259
+ const mcpServers = {};
13260
+ const agentMcpBindings = [];
13261
+ const npmDeps = new Set;
13262
+ const npmDevDeps = new Set;
13263
+ const disabledTools = new Set;
13264
+ async function resolve2(name, path3 = []) {
13265
+ if (resolved.has(name)) {
13266
+ return;
13267
+ }
13268
+ if (visiting.has(name)) {
13269
+ const cycle = [...path3, name].join(" \u2192 ");
13270
+ throw new ValidationError(`Circular dependency detected: ${cycle}`);
13271
+ }
13272
+ visiting.add(name);
13273
+ let component = null;
13274
+ let foundRegistry = null;
13275
+ const registryEntries = Object.entries(registries);
13276
+ for (const [regName, regConfig] of registryEntries) {
13277
+ try {
13278
+ const manifest = await fetchComponent(regConfig.url, name);
13279
+ component = manifest;
13280
+ foundRegistry = { name: regName, url: regConfig.url };
13281
+ break;
13282
+ } catch (_err) {}
13283
+ }
13284
+ if (!component || !foundRegistry) {
13285
+ throw new OCXError(`Component '${name}' not found in any configured registry.`, "NOT_FOUND");
13286
+ }
13287
+ for (const dep of component.dependencies) {
13288
+ await resolve2(dep, [...path3, name]);
13289
+ }
13290
+ resolved.set(name, {
13291
+ ...component,
13292
+ registryName: foundRegistry.name,
13293
+ baseUrl: foundRegistry.url
13294
+ });
13295
+ visiting.delete(name);
13296
+ if (component.mcpServers) {
13297
+ const serverNames = [];
13298
+ for (const [serverName, config2] of Object.entries(component.mcpServers)) {
13299
+ mcpServers[serverName] = config2;
13300
+ serverNames.push(serverName);
13301
+ }
13302
+ const scope = component.mcpScope ?? "agent";
13303
+ if (component.type === "ocx:agent" && scope === "agent" && serverNames.length > 0) {
13304
+ agentMcpBindings.push({
13305
+ agentName: component.name,
13306
+ serverNames
13307
+ });
13308
+ }
13309
+ }
13310
+ if (component.npmDependencies) {
13311
+ for (const dep of component.npmDependencies) {
13312
+ npmDeps.add(dep);
13313
+ }
13314
+ }
13315
+ if (component.npmDevDependencies) {
13316
+ for (const dep of component.npmDevDependencies) {
13317
+ npmDevDeps.add(dep);
13318
+ }
13319
+ }
13320
+ if (component.disabledTools) {
13321
+ for (const tool of component.disabledTools) {
13322
+ disabledTools.add(tool);
13323
+ }
13324
+ }
13325
+ }
13326
+ for (const name of componentNames) {
13327
+ await resolve2(name);
13328
+ }
13329
+ const components = Array.from(resolved.values());
13330
+ const installOrder = Array.from(resolved.keys());
13331
+ return {
13332
+ components,
13333
+ installOrder,
13334
+ mcpServers,
13335
+ agentMcpBindings,
13336
+ npmDependencies: Array.from(npmDeps),
13337
+ npmDevDependencies: Array.from(npmDevDeps),
13338
+ disabledTools: Array.from(disabledTools)
13339
+ };
13340
+ }
13341
+
13254
13342
  // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js
13255
13343
  function createScanner(text2, ignoreTrivia = false) {
13256
13344
  const len = text2.length;
@@ -13699,6 +13787,249 @@ var cachedBreakLinesWithSpaces = {
13699
13787
  })
13700
13788
  }
13701
13789
  };
13790
+ var supportedEols = [`
13791
+ `, "\r", `\r
13792
+ `];
13793
+
13794
+ // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/format.js
13795
+ function format(documentText, range, options2) {
13796
+ let initialIndentLevel;
13797
+ let formatText;
13798
+ let formatTextStart;
13799
+ let rangeStart;
13800
+ let rangeEnd;
13801
+ if (range) {
13802
+ rangeStart = range.offset;
13803
+ rangeEnd = rangeStart + range.length;
13804
+ formatTextStart = rangeStart;
13805
+ while (formatTextStart > 0 && !isEOL(documentText, formatTextStart - 1)) {
13806
+ formatTextStart--;
13807
+ }
13808
+ let endOffset = rangeEnd;
13809
+ while (endOffset < documentText.length && !isEOL(documentText, endOffset)) {
13810
+ endOffset++;
13811
+ }
13812
+ formatText = documentText.substring(formatTextStart, endOffset);
13813
+ initialIndentLevel = computeIndentLevel(formatText, options2);
13814
+ } else {
13815
+ formatText = documentText;
13816
+ initialIndentLevel = 0;
13817
+ formatTextStart = 0;
13818
+ rangeStart = 0;
13819
+ rangeEnd = documentText.length;
13820
+ }
13821
+ const eol = getEOL(options2, documentText);
13822
+ const eolFastPathSupported = supportedEols.includes(eol);
13823
+ let numberLineBreaks = 0;
13824
+ let indentLevel = 0;
13825
+ let indentValue;
13826
+ if (options2.insertSpaces) {
13827
+ indentValue = cachedSpaces[options2.tabSize || 4] ?? repeat(cachedSpaces[1], options2.tabSize || 4);
13828
+ } else {
13829
+ indentValue = "\t";
13830
+ }
13831
+ const indentType = indentValue === "\t" ? "\t" : " ";
13832
+ let scanner = createScanner(formatText, false);
13833
+ let hasError = false;
13834
+ function newLinesAndIndent() {
13835
+ if (numberLineBreaks > 1) {
13836
+ return repeat(eol, numberLineBreaks) + repeat(indentValue, initialIndentLevel + indentLevel);
13837
+ }
13838
+ const amountOfSpaces = indentValue.length * (initialIndentLevel + indentLevel);
13839
+ if (!eolFastPathSupported || amountOfSpaces > cachedBreakLinesWithSpaces[indentType][eol].length) {
13840
+ return eol + repeat(indentValue, initialIndentLevel + indentLevel);
13841
+ }
13842
+ if (amountOfSpaces <= 0) {
13843
+ return eol;
13844
+ }
13845
+ return cachedBreakLinesWithSpaces[indentType][eol][amountOfSpaces];
13846
+ }
13847
+ function scanNext() {
13848
+ let token = scanner.scan();
13849
+ numberLineBreaks = 0;
13850
+ while (token === 15 || token === 14) {
13851
+ if (token === 14 && options2.keepLines) {
13852
+ numberLineBreaks += 1;
13853
+ } else if (token === 14) {
13854
+ numberLineBreaks = 1;
13855
+ }
13856
+ token = scanner.scan();
13857
+ }
13858
+ hasError = token === 16 || scanner.getTokenError() !== 0;
13859
+ return token;
13860
+ }
13861
+ const editOperations = [];
13862
+ function addEdit(text2, startOffset, endOffset) {
13863
+ if (!hasError && (!range || startOffset < rangeEnd && endOffset > rangeStart) && documentText.substring(startOffset, endOffset) !== text2) {
13864
+ editOperations.push({ offset: startOffset, length: endOffset - startOffset, content: text2 });
13865
+ }
13866
+ }
13867
+ let firstToken = scanNext();
13868
+ if (options2.keepLines && numberLineBreaks > 0) {
13869
+ addEdit(repeat(eol, numberLineBreaks), 0, 0);
13870
+ }
13871
+ if (firstToken !== 17) {
13872
+ let firstTokenStart = scanner.getTokenOffset() + formatTextStart;
13873
+ let initialIndent = indentValue.length * initialIndentLevel < 20 && options2.insertSpaces ? cachedSpaces[indentValue.length * initialIndentLevel] : repeat(indentValue, initialIndentLevel);
13874
+ addEdit(initialIndent, formatTextStart, firstTokenStart);
13875
+ }
13876
+ while (firstToken !== 17) {
13877
+ let firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
13878
+ let secondToken = scanNext();
13879
+ let replaceContent = "";
13880
+ let needsLineBreak = false;
13881
+ while (numberLineBreaks === 0 && (secondToken === 12 || secondToken === 13)) {
13882
+ let commentTokenStart = scanner.getTokenOffset() + formatTextStart;
13883
+ addEdit(cachedSpaces[1], firstTokenEnd, commentTokenStart);
13884
+ firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
13885
+ needsLineBreak = secondToken === 12;
13886
+ replaceContent = needsLineBreak ? newLinesAndIndent() : "";
13887
+ secondToken = scanNext();
13888
+ }
13889
+ if (secondToken === 2) {
13890
+ if (firstToken !== 1) {
13891
+ indentLevel--;
13892
+ }
13893
+ if (options2.keepLines && numberLineBreaks > 0 || !options2.keepLines && firstToken !== 1) {
13894
+ replaceContent = newLinesAndIndent();
13895
+ } else if (options2.keepLines) {
13896
+ replaceContent = cachedSpaces[1];
13897
+ }
13898
+ } else if (secondToken === 4) {
13899
+ if (firstToken !== 3) {
13900
+ indentLevel--;
13901
+ }
13902
+ if (options2.keepLines && numberLineBreaks > 0 || !options2.keepLines && firstToken !== 3) {
13903
+ replaceContent = newLinesAndIndent();
13904
+ } else if (options2.keepLines) {
13905
+ replaceContent = cachedSpaces[1];
13906
+ }
13907
+ } else {
13908
+ switch (firstToken) {
13909
+ case 3:
13910
+ case 1:
13911
+ indentLevel++;
13912
+ if (options2.keepLines && numberLineBreaks > 0 || !options2.keepLines) {
13913
+ replaceContent = newLinesAndIndent();
13914
+ } else {
13915
+ replaceContent = cachedSpaces[1];
13916
+ }
13917
+ break;
13918
+ case 5:
13919
+ if (options2.keepLines && numberLineBreaks > 0 || !options2.keepLines) {
13920
+ replaceContent = newLinesAndIndent();
13921
+ } else {
13922
+ replaceContent = cachedSpaces[1];
13923
+ }
13924
+ break;
13925
+ case 12:
13926
+ replaceContent = newLinesAndIndent();
13927
+ break;
13928
+ case 13:
13929
+ if (numberLineBreaks > 0) {
13930
+ replaceContent = newLinesAndIndent();
13931
+ } else if (!needsLineBreak) {
13932
+ replaceContent = cachedSpaces[1];
13933
+ }
13934
+ break;
13935
+ case 6:
13936
+ if (options2.keepLines && numberLineBreaks > 0) {
13937
+ replaceContent = newLinesAndIndent();
13938
+ } else if (!needsLineBreak) {
13939
+ replaceContent = cachedSpaces[1];
13940
+ }
13941
+ break;
13942
+ case 10:
13943
+ if (options2.keepLines && numberLineBreaks > 0) {
13944
+ replaceContent = newLinesAndIndent();
13945
+ } else if (secondToken === 6 && !needsLineBreak) {
13946
+ replaceContent = "";
13947
+ }
13948
+ break;
13949
+ case 7:
13950
+ case 8:
13951
+ case 9:
13952
+ case 11:
13953
+ case 2:
13954
+ case 4:
13955
+ if (options2.keepLines && numberLineBreaks > 0) {
13956
+ replaceContent = newLinesAndIndent();
13957
+ } else {
13958
+ if ((secondToken === 12 || secondToken === 13) && !needsLineBreak) {
13959
+ replaceContent = cachedSpaces[1];
13960
+ } else if (secondToken !== 5 && secondToken !== 17) {
13961
+ hasError = true;
13962
+ }
13963
+ }
13964
+ break;
13965
+ case 16:
13966
+ hasError = true;
13967
+ break;
13968
+ }
13969
+ if (numberLineBreaks > 0 && (secondToken === 12 || secondToken === 13)) {
13970
+ replaceContent = newLinesAndIndent();
13971
+ }
13972
+ }
13973
+ if (secondToken === 17) {
13974
+ if (options2.keepLines && numberLineBreaks > 0) {
13975
+ replaceContent = newLinesAndIndent();
13976
+ } else {
13977
+ replaceContent = options2.insertFinalNewline ? eol : "";
13978
+ }
13979
+ }
13980
+ const secondTokenStart = scanner.getTokenOffset() + formatTextStart;
13981
+ addEdit(replaceContent, firstTokenEnd, secondTokenStart);
13982
+ firstToken = secondToken;
13983
+ }
13984
+ return editOperations;
13985
+ }
13986
+ function repeat(s2, count) {
13987
+ let result = "";
13988
+ for (let i2 = 0;i2 < count; i2++) {
13989
+ result += s2;
13990
+ }
13991
+ return result;
13992
+ }
13993
+ function computeIndentLevel(content, options2) {
13994
+ let i2 = 0;
13995
+ let nChars = 0;
13996
+ const tabSize = options2.tabSize || 4;
13997
+ while (i2 < content.length) {
13998
+ let ch = content.charAt(i2);
13999
+ if (ch === cachedSpaces[1]) {
14000
+ nChars++;
14001
+ } else if (ch === "\t") {
14002
+ nChars += tabSize;
14003
+ } else {
14004
+ break;
14005
+ }
14006
+ i2++;
14007
+ }
14008
+ return Math.floor(nChars / tabSize);
14009
+ }
14010
+ function getEOL(options2, text2) {
14011
+ for (let i2 = 0;i2 < text2.length; i2++) {
14012
+ const ch = text2.charAt(i2);
14013
+ if (ch === "\r") {
14014
+ if (i2 + 1 < text2.length && text2.charAt(i2 + 1) === `
14015
+ `) {
14016
+ return `\r
14017
+ `;
14018
+ }
14019
+ return "\r";
14020
+ } else if (ch === `
14021
+ `) {
14022
+ return `
14023
+ `;
14024
+ }
14025
+ }
14026
+ return options2 && options2.eol || `
14027
+ `;
14028
+ }
14029
+ function isEOL(text2, offset) {
14030
+ return `\r
14031
+ `.indexOf(text2.charAt(offset)) !== -1;
14032
+ }
13702
14033
 
13703
14034
  // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/parser.js
13704
14035
  var ParseOptions;
@@ -13750,6 +14081,95 @@ function parse(text2, errors2 = [], options2 = ParseOptions.DEFAULT) {
13750
14081
  visit(text2, visitor, options2);
13751
14082
  return currentParent[0];
13752
14083
  }
14084
+ function parseTree(text2, errors2 = [], options2 = ParseOptions.DEFAULT) {
14085
+ let currentParent = { type: "array", offset: -1, length: -1, children: [], parent: undefined };
14086
+ function ensurePropertyComplete(endOffset) {
14087
+ if (currentParent.type === "property") {
14088
+ currentParent.length = endOffset - currentParent.offset;
14089
+ currentParent = currentParent.parent;
14090
+ }
14091
+ }
14092
+ function onValue(valueNode) {
14093
+ currentParent.children.push(valueNode);
14094
+ return valueNode;
14095
+ }
14096
+ const visitor = {
14097
+ onObjectBegin: (offset) => {
14098
+ currentParent = onValue({ type: "object", offset, length: -1, parent: currentParent, children: [] });
14099
+ },
14100
+ onObjectProperty: (name, offset, length) => {
14101
+ currentParent = onValue({ type: "property", offset, length: -1, parent: currentParent, children: [] });
14102
+ currentParent.children.push({ type: "string", value: name, offset, length, parent: currentParent });
14103
+ },
14104
+ onObjectEnd: (offset, length) => {
14105
+ ensurePropertyComplete(offset + length);
14106
+ currentParent.length = offset + length - currentParent.offset;
14107
+ currentParent = currentParent.parent;
14108
+ ensurePropertyComplete(offset + length);
14109
+ },
14110
+ onArrayBegin: (offset, length) => {
14111
+ currentParent = onValue({ type: "array", offset, length: -1, parent: currentParent, children: [] });
14112
+ },
14113
+ onArrayEnd: (offset, length) => {
14114
+ currentParent.length = offset + length - currentParent.offset;
14115
+ currentParent = currentParent.parent;
14116
+ ensurePropertyComplete(offset + length);
14117
+ },
14118
+ onLiteralValue: (value, offset, length) => {
14119
+ onValue({ type: getNodeType(value), offset, length, parent: currentParent, value });
14120
+ ensurePropertyComplete(offset + length);
14121
+ },
14122
+ onSeparator: (sep, offset, length) => {
14123
+ if (currentParent.type === "property") {
14124
+ if (sep === ":") {
14125
+ currentParent.colonOffset = offset;
14126
+ } else if (sep === ",") {
14127
+ ensurePropertyComplete(offset);
14128
+ }
14129
+ }
14130
+ },
14131
+ onError: (error, offset, length) => {
14132
+ errors2.push({ error, offset, length });
14133
+ }
14134
+ };
14135
+ visit(text2, visitor, options2);
14136
+ const result = currentParent.children[0];
14137
+ if (result) {
14138
+ delete result.parent;
14139
+ }
14140
+ return result;
14141
+ }
14142
+ function findNodeAtLocation(root, path3) {
14143
+ if (!root) {
14144
+ return;
14145
+ }
14146
+ let node = root;
14147
+ for (let segment of path3) {
14148
+ if (typeof segment === "string") {
14149
+ if (node.type !== "object" || !Array.isArray(node.children)) {
14150
+ return;
14151
+ }
14152
+ let found = false;
14153
+ for (const propertyNode of node.children) {
14154
+ if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment && propertyNode.children.length === 2) {
14155
+ node = propertyNode.children[1];
14156
+ found = true;
14157
+ break;
14158
+ }
14159
+ }
14160
+ if (!found) {
14161
+ return;
14162
+ }
14163
+ } else {
14164
+ const index = segment;
14165
+ if (node.type !== "array" || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {
14166
+ return;
14167
+ }
14168
+ node = node.children[index];
14169
+ }
14170
+ }
14171
+ return node;
14172
+ }
13753
14173
  function visit(text2, visitor, options2 = ParseOptions.DEFAULT) {
13754
14174
  const _scanner = createScanner(text2, false);
13755
14175
  const _jsonPath = [];
@@ -14002,6 +14422,170 @@ function visit(text2, visitor, options2 = ParseOptions.DEFAULT) {
14002
14422
  }
14003
14423
  return true;
14004
14424
  }
14425
+ function getNodeType(value) {
14426
+ switch (typeof value) {
14427
+ case "boolean":
14428
+ return "boolean";
14429
+ case "number":
14430
+ return "number";
14431
+ case "string":
14432
+ return "string";
14433
+ case "object": {
14434
+ if (!value) {
14435
+ return "null";
14436
+ } else if (Array.isArray(value)) {
14437
+ return "array";
14438
+ }
14439
+ return "object";
14440
+ }
14441
+ default:
14442
+ return "null";
14443
+ }
14444
+ }
14445
+
14446
+ // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/edit.js
14447
+ function setProperty(text2, originalPath, value, options2) {
14448
+ const path3 = originalPath.slice();
14449
+ const errors2 = [];
14450
+ const root = parseTree(text2, errors2);
14451
+ let parent = undefined;
14452
+ let lastSegment = undefined;
14453
+ while (path3.length > 0) {
14454
+ lastSegment = path3.pop();
14455
+ parent = findNodeAtLocation(root, path3);
14456
+ if (parent === undefined && value !== undefined) {
14457
+ if (typeof lastSegment === "string") {
14458
+ value = { [lastSegment]: value };
14459
+ } else {
14460
+ value = [value];
14461
+ }
14462
+ } else {
14463
+ break;
14464
+ }
14465
+ }
14466
+ if (!parent) {
14467
+ if (value === undefined) {
14468
+ throw new Error("Can not delete in empty document");
14469
+ }
14470
+ return withFormatting(text2, { offset: root ? root.offset : 0, length: root ? root.length : 0, content: JSON.stringify(value) }, options2);
14471
+ } else if (parent.type === "object" && typeof lastSegment === "string" && Array.isArray(parent.children)) {
14472
+ const existing = findNodeAtLocation(parent, [lastSegment]);
14473
+ if (existing !== undefined) {
14474
+ if (value === undefined) {
14475
+ if (!existing.parent) {
14476
+ throw new Error("Malformed AST");
14477
+ }
14478
+ const propertyIndex = parent.children.indexOf(existing.parent);
14479
+ let removeBegin;
14480
+ let removeEnd = existing.parent.offset + existing.parent.length;
14481
+ if (propertyIndex > 0) {
14482
+ let previous = parent.children[propertyIndex - 1];
14483
+ removeBegin = previous.offset + previous.length;
14484
+ } else {
14485
+ removeBegin = parent.offset + 1;
14486
+ if (parent.children.length > 1) {
14487
+ let next = parent.children[1];
14488
+ removeEnd = next.offset;
14489
+ }
14490
+ }
14491
+ return withFormatting(text2, { offset: removeBegin, length: removeEnd - removeBegin, content: "" }, options2);
14492
+ } else {
14493
+ return withFormatting(text2, { offset: existing.offset, length: existing.length, content: JSON.stringify(value) }, options2);
14494
+ }
14495
+ } else {
14496
+ if (value === undefined) {
14497
+ return [];
14498
+ }
14499
+ const newProperty = `${JSON.stringify(lastSegment)}: ${JSON.stringify(value)}`;
14500
+ const index = options2.getInsertionIndex ? options2.getInsertionIndex(parent.children.map((p2) => p2.children[0].value)) : parent.children.length;
14501
+ let edit;
14502
+ if (index > 0) {
14503
+ let previous = parent.children[index - 1];
14504
+ edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
14505
+ } else if (parent.children.length === 0) {
14506
+ edit = { offset: parent.offset + 1, length: 0, content: newProperty };
14507
+ } else {
14508
+ edit = { offset: parent.offset + 1, length: 0, content: newProperty + "," };
14509
+ }
14510
+ return withFormatting(text2, edit, options2);
14511
+ }
14512
+ } else if (parent.type === "array" && typeof lastSegment === "number" && Array.isArray(parent.children)) {
14513
+ const insertIndex = lastSegment;
14514
+ if (insertIndex === -1) {
14515
+ const newProperty = `${JSON.stringify(value)}`;
14516
+ let edit;
14517
+ if (parent.children.length === 0) {
14518
+ edit = { offset: parent.offset + 1, length: 0, content: newProperty };
14519
+ } else {
14520
+ const previous = parent.children[parent.children.length - 1];
14521
+ edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
14522
+ }
14523
+ return withFormatting(text2, edit, options2);
14524
+ } else if (value === undefined && parent.children.length >= 0) {
14525
+ const removalIndex = lastSegment;
14526
+ const toRemove = parent.children[removalIndex];
14527
+ let edit;
14528
+ if (parent.children.length === 1) {
14529
+ edit = { offset: parent.offset + 1, length: parent.length - 2, content: "" };
14530
+ } else if (parent.children.length - 1 === removalIndex) {
14531
+ let previous = parent.children[removalIndex - 1];
14532
+ let offset = previous.offset + previous.length;
14533
+ let parentEndOffset = parent.offset + parent.length;
14534
+ edit = { offset, length: parentEndOffset - 2 - offset, content: "" };
14535
+ } else {
14536
+ edit = { offset: toRemove.offset, length: parent.children[removalIndex + 1].offset - toRemove.offset, content: "" };
14537
+ }
14538
+ return withFormatting(text2, edit, options2);
14539
+ } else if (value !== undefined) {
14540
+ let edit;
14541
+ const newProperty = `${JSON.stringify(value)}`;
14542
+ if (!options2.isArrayInsertion && parent.children.length > lastSegment) {
14543
+ const toModify = parent.children[lastSegment];
14544
+ edit = { offset: toModify.offset, length: toModify.length, content: newProperty };
14545
+ } else if (parent.children.length === 0 || lastSegment === 0) {
14546
+ edit = { offset: parent.offset + 1, length: 0, content: parent.children.length === 0 ? newProperty : newProperty + "," };
14547
+ } else {
14548
+ const index = lastSegment > parent.children.length ? parent.children.length : lastSegment;
14549
+ const previous = parent.children[index - 1];
14550
+ edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
14551
+ }
14552
+ return withFormatting(text2, edit, options2);
14553
+ } else {
14554
+ throw new Error(`Can not ${value === undefined ? "remove" : options2.isArrayInsertion ? "insert" : "modify"} Array index ${insertIndex} as length is not sufficient`);
14555
+ }
14556
+ } else {
14557
+ throw new Error(`Can not add ${typeof lastSegment !== "number" ? "index" : "property"} to parent of type ${parent.type}`);
14558
+ }
14559
+ }
14560
+ function withFormatting(text2, edit, options2) {
14561
+ if (!options2.formattingOptions) {
14562
+ return [edit];
14563
+ }
14564
+ let newText = applyEdit(text2, edit);
14565
+ let begin = edit.offset;
14566
+ let end = edit.offset + edit.content.length;
14567
+ if (edit.length === 0 || edit.content.length === 0) {
14568
+ while (begin > 0 && !isEOL(newText, begin - 1)) {
14569
+ begin--;
14570
+ }
14571
+ while (end < newText.length && !isEOL(newText, end)) {
14572
+ end++;
14573
+ }
14574
+ }
14575
+ const edits = format(newText, { offset: begin, length: end - begin }, { ...options2.formattingOptions, keepLines: false });
14576
+ for (let i2 = edits.length - 1;i2 >= 0; i2--) {
14577
+ const edit2 = edits[i2];
14578
+ newText = applyEdit(newText, edit2);
14579
+ begin = Math.min(begin, edit2.offset);
14580
+ end = Math.max(end, edit2.offset + edit2.length);
14581
+ end += edit2.content.length - edit2.length;
14582
+ }
14583
+ const editLength = text2.length - (newText.length - end) - begin;
14584
+ return [{ offset: begin, length: editLength, content: newText.substring(begin, end) }];
14585
+ }
14586
+ function applyEdit(text2, edit) {
14587
+ return text2.substring(0, edit.offset) + edit.content + text2.substring(edit.offset + edit.length);
14588
+ }
14005
14589
 
14006
14590
  // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/main.js
14007
14591
  var ScanError;
@@ -14054,158 +14638,28 @@ var ParseErrorCode;
14054
14638
  ParseErrorCode2[ParseErrorCode2["InvalidEscapeCharacter"] = 15] = "InvalidEscapeCharacter";
14055
14639
  ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
14056
14640
  })(ParseErrorCode || (ParseErrorCode = {}));
14057
-
14058
- // src/registry/opencode-config.ts
14059
- async function readOpencodeConfig(cwd) {
14060
- const jsonPath = `${cwd}/opencode.json`;
14061
- const jsoncPath = `${cwd}/opencode.jsonc`;
14062
- for (const configPath of [jsoncPath, jsonPath]) {
14063
- const file = Bun.file(configPath);
14064
- if (await file.exists()) {
14065
- const content = await file.text();
14066
- return {
14067
- config: parse2(content, [], { allowTrailingComma: true }),
14068
- path: configPath
14069
- };
14070
- }
14071
- }
14072
- return null;
14073
- }
14074
- async function writeOpencodeConfig(path3, config2) {
14075
- const content = JSON.stringify(config2, null, 2);
14076
- await Bun.write(path3, content);
14077
- }
14078
- function applyMcpServers(config2, mcpServers) {
14079
- const added = [];
14080
- const skipped = [];
14081
- if (!config2.mcp) {
14082
- config2.mcp = {};
14083
- }
14084
- for (const [name, server] of Object.entries(mcpServers)) {
14085
- if (config2.mcp[name]) {
14086
- skipped.push(name);
14087
- } else {
14088
- const serverConfig = {
14089
- type: server.type,
14090
- enabled: server.enabled
14091
- };
14092
- if (server.type === "remote" && server.url) {
14093
- serverConfig.url = server.url;
14094
- }
14095
- if (server.type === "local" && server.command) {
14096
- serverConfig.command = server.command;
14097
- }
14098
- if (server.headers) {
14099
- serverConfig.headers = server.headers;
14100
- }
14101
- config2.mcp[name] = serverConfig;
14102
- added.push(name);
14103
- }
14104
- }
14105
- return { config: config2, added, skipped };
14106
- }
14107
- async function updateOpencodeConfig(cwd, options2) {
14108
- const existing = await readOpencodeConfig(cwd);
14109
- let config2;
14110
- let configPath;
14111
- let created = false;
14112
- if (existing) {
14113
- config2 = existing.config;
14114
- configPath = existing.path;
14115
- } else {
14116
- config2 = {
14117
- $schema: "https://opencode.ai/config.json"
14118
- };
14119
- configPath = `${cwd}/opencode.json`;
14120
- created = true;
14121
- }
14122
- let mcpAdded = [];
14123
- let mcpSkipped = [];
14124
- if (options2.mcpServers && Object.keys(options2.mcpServers).length > 0) {
14125
- const result = applyMcpServers(config2, options2.mcpServers);
14126
- config2 = result.config;
14127
- mcpAdded = result.added;
14128
- mcpSkipped = result.skipped;
14129
- }
14130
- if (options2.defaultAgent && !config2.default_agent) {
14131
- config2.default_agent = options2.defaultAgent;
14132
- }
14133
- await writeOpencodeConfig(configPath, config2);
14134
- return {
14135
- path: configPath,
14136
- created,
14137
- mcpAdded,
14138
- mcpSkipped
14139
- };
14641
+ function modify(text2, path3, value, options2) {
14642
+ return setProperty(text2, path3, value, options2);
14140
14643
  }
14141
-
14142
- // src/registry/resolver.ts
14143
- async function resolveDependencies(registries, componentNames) {
14144
- const resolved = new Map;
14145
- const visiting = new Set;
14146
- const mcpServers = {};
14147
- const npmDeps = new Set;
14148
- const npmDevDeps = new Set;
14149
- async function resolve2(name, path3 = []) {
14150
- if (resolved.has(name)) {
14151
- return;
14644
+ function applyEdits(text2, edits) {
14645
+ let sortedEdits = edits.slice(0).sort((a3, b2) => {
14646
+ const diff = a3.offset - b2.offset;
14647
+ if (diff === 0) {
14648
+ return a3.length - b2.length;
14152
14649
  }
14153
- if (visiting.has(name)) {
14154
- const cycle = [...path3, name].join(" \u2192 ");
14155
- throw new ValidationError(`Circular dependency detected: ${cycle}`);
14156
- }
14157
- visiting.add(name);
14158
- let component = null;
14159
- let foundRegistry = null;
14160
- const registryEntries = Object.entries(registries);
14161
- for (const [regName, regConfig] of registryEntries) {
14162
- try {
14163
- const manifest = await fetchComponent(regConfig.url, name);
14164
- component = manifest;
14165
- foundRegistry = { name: regName, url: regConfig.url };
14166
- break;
14167
- } catch (_err) {}
14168
- }
14169
- if (!component || !foundRegistry) {
14170
- throw new OCXError(`Component '${name}' not found in any configured registry.`, "NOT_FOUND");
14171
- }
14172
- for (const dep of component.dependencies) {
14173
- await resolve2(dep, [...path3, name]);
14174
- }
14175
- resolved.set(name, {
14176
- ...component,
14177
- registryName: foundRegistry.name,
14178
- baseUrl: foundRegistry.url
14179
- });
14180
- visiting.delete(name);
14181
- if (component.mcpServers) {
14182
- for (const [serverName, config2] of Object.entries(component.mcpServers)) {
14183
- mcpServers[serverName] = config2;
14184
- }
14185
- }
14186
- if (component.npmDependencies) {
14187
- for (const dep of component.npmDependencies) {
14188
- npmDeps.add(dep);
14189
- }
14190
- }
14191
- if (component.npmDevDependencies) {
14192
- for (const dep of component.npmDevDependencies) {
14193
- npmDevDeps.add(dep);
14194
- }
14650
+ return diff;
14651
+ });
14652
+ let lastModifiedOffset = text2.length;
14653
+ for (let i2 = sortedEdits.length - 1;i2 >= 0; i2--) {
14654
+ let e2 = sortedEdits[i2];
14655
+ if (e2.offset + e2.length <= lastModifiedOffset) {
14656
+ text2 = applyEdit(text2, e2);
14657
+ } else {
14658
+ throw new Error("Overlapping edit");
14195
14659
  }
14660
+ lastModifiedOffset = e2.offset;
14196
14661
  }
14197
- for (const name of componentNames) {
14198
- await resolve2(name);
14199
- }
14200
- const components = Array.from(resolved.values());
14201
- const installOrder = Array.from(resolved.keys());
14202
- return {
14203
- components,
14204
- installOrder,
14205
- mcpServers,
14206
- npmDependencies: Array.from(npmDeps),
14207
- npmDevDependencies: Array.from(npmDevDeps)
14208
- };
14662
+ return text2;
14209
14663
  }
14210
14664
 
14211
14665
  // src/schemas/config.ts
@@ -14274,6 +14728,158 @@ async function readOcxLock(cwd) {
14274
14728
  return ocxLockSchema.parse(json);
14275
14729
  }
14276
14730
 
14731
+ // src/updaters/update-opencode-config.ts
14732
+ var JSONC_OPTIONS = {
14733
+ formattingOptions: {
14734
+ tabSize: 2,
14735
+ insertSpaces: false,
14736
+ eol: `
14737
+ `
14738
+ }
14739
+ };
14740
+ async function readOpencodeConfig(cwd) {
14741
+ const jsonPath = `${cwd}/opencode.json`;
14742
+ const jsoncPath = `${cwd}/opencode.jsonc`;
14743
+ for (const configPath of [jsoncPath, jsonPath]) {
14744
+ const file = Bun.file(configPath);
14745
+ if (await file.exists()) {
14746
+ const content = await file.text();
14747
+ return {
14748
+ config: parse2(content, [], { allowTrailingComma: true }),
14749
+ content,
14750
+ path: configPath
14751
+ };
14752
+ }
14753
+ }
14754
+ return null;
14755
+ }
14756
+ async function writeOpencodeConfig(path3, content) {
14757
+ await Bun.write(path3, content);
14758
+ }
14759
+ function applyMcpServers(content, config2, mcpServers) {
14760
+ const added = [];
14761
+ const skipped = [];
14762
+ let updatedContent = content;
14763
+ const existingMcp = config2.mcp ?? {};
14764
+ for (const [name, server] of Object.entries(mcpServers)) {
14765
+ if (existingMcp[name]) {
14766
+ skipped.push(name);
14767
+ continue;
14768
+ }
14769
+ const serverConfig = {
14770
+ type: server.type
14771
+ };
14772
+ if (server.type === "remote" && server.url) {
14773
+ serverConfig.url = server.url;
14774
+ }
14775
+ if (server.type === "local" && server.command) {
14776
+ serverConfig.command = server.command;
14777
+ }
14778
+ if (server.headers) {
14779
+ serverConfig.headers = server.headers;
14780
+ }
14781
+ if (server.enabled !== undefined) {
14782
+ serverConfig.enabled = server.enabled;
14783
+ }
14784
+ const edits = modify(updatedContent, ["mcp", name], serverConfig, JSONC_OPTIONS);
14785
+ updatedContent = applyEdits(updatedContent, edits);
14786
+ added.push(name);
14787
+ }
14788
+ return { content: updatedContent, added, skipped };
14789
+ }
14790
+ function applyGlobalToolDisables(content, serverNames) {
14791
+ let updatedContent = content;
14792
+ for (const name of serverNames) {
14793
+ const toolPattern = `${name}_*`;
14794
+ const edits = modify(updatedContent, ["tools", toolPattern], false, JSONC_OPTIONS);
14795
+ updatedContent = applyEdits(updatedContent, edits);
14796
+ }
14797
+ return updatedContent;
14798
+ }
14799
+ function applyDisabledTools(content, toolNames) {
14800
+ let updatedContent = content;
14801
+ for (const name of toolNames) {
14802
+ const edits = modify(updatedContent, ["tools", name], false, JSONC_OPTIONS);
14803
+ updatedContent = applyEdits(updatedContent, edits);
14804
+ }
14805
+ return updatedContent;
14806
+ }
14807
+ function applyAgentToolEnables(content, bindings) {
14808
+ let updatedContent = content;
14809
+ const agentsConfigured = [];
14810
+ for (const binding of bindings) {
14811
+ for (const serverName of binding.serverNames) {
14812
+ const toolPattern = `${serverName}_*`;
14813
+ const edits = modify(updatedContent, ["agent", binding.agentName, "tools", toolPattern], true, JSONC_OPTIONS);
14814
+ updatedContent = applyEdits(updatedContent, edits);
14815
+ }
14816
+ if (binding.serverNames.length > 0) {
14817
+ agentsConfigured.push(binding.agentName);
14818
+ }
14819
+ }
14820
+ return { content: updatedContent, agentsConfigured: [...new Set(agentsConfigured)] };
14821
+ }
14822
+ function applyDefaultAgent(content, config2, defaultAgent) {
14823
+ if (config2.default_agent) {
14824
+ return content;
14825
+ }
14826
+ const edits = modify(content, ["default_agent"], defaultAgent, JSONC_OPTIONS);
14827
+ return applyEdits(content, edits);
14828
+ }
14829
+ async function updateOpencodeConfig(cwd, options2) {
14830
+ const existing = await readOpencodeConfig(cwd);
14831
+ let content;
14832
+ let config2;
14833
+ let configPath;
14834
+ let created = false;
14835
+ if (existing) {
14836
+ content = existing.content;
14837
+ config2 = existing.config;
14838
+ configPath = existing.path;
14839
+ } else {
14840
+ config2 = { $schema: "https://opencode.ai/config.json" };
14841
+ content = JSON.stringify(config2, null, "\t");
14842
+ configPath = `${cwd}/opencode.json`;
14843
+ created = true;
14844
+ }
14845
+ let mcpAdded = [];
14846
+ let mcpSkipped = [];
14847
+ let agentsConfigured = [];
14848
+ let toolsDisabled = [];
14849
+ if (options2.mcpServers && Object.keys(options2.mcpServers).length > 0) {
14850
+ const result = applyMcpServers(content, config2, options2.mcpServers);
14851
+ content = result.content;
14852
+ mcpAdded = result.added;
14853
+ mcpSkipped = result.skipped;
14854
+ }
14855
+ if (options2.agentMcpBindings && options2.agentMcpBindings.length > 0) {
14856
+ const allScopedServers = [...new Set(options2.agentMcpBindings.flatMap((b2) => b2.serverNames))];
14857
+ if (allScopedServers.length > 0) {
14858
+ content = applyGlobalToolDisables(content, allScopedServers);
14859
+ const agentResult = applyAgentToolEnables(content, options2.agentMcpBindings);
14860
+ content = agentResult.content;
14861
+ agentsConfigured = agentResult.agentsConfigured;
14862
+ }
14863
+ }
14864
+ if (options2.defaultAgent) {
14865
+ const updatedConfig = parse2(content, [], { allowTrailingComma: true });
14866
+ content = applyDefaultAgent(content, updatedConfig, options2.defaultAgent);
14867
+ }
14868
+ if (options2.disabledTools && options2.disabledTools.length > 0) {
14869
+ content = applyDisabledTools(content, options2.disabledTools);
14870
+ toolsDisabled = options2.disabledTools;
14871
+ }
14872
+ await writeOpencodeConfig(configPath, content);
14873
+ return {
14874
+ path: configPath,
14875
+ created,
14876
+ mcpAdded,
14877
+ mcpSkipped,
14878
+ agentsConfigured,
14879
+ toolsDisabled
14880
+ };
14881
+ }
14882
+
14277
14883
  // src/utils/env.ts
14278
14884
  var isCI = Boolean(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI || process.env.CIRCLECI || process.env.JENKINS_URL || process.env.BUILDKITE);
14279
14885
  var isTTY = Boolean(process.stdout.isTTY && !isCI);
@@ -15863,9 +16469,13 @@ async function runAdd(componentNames, options3) {
15863
16469
  };
15864
16470
  }
15865
16471
  installSpin?.succeed(`Installed ${resolved.components.length} components`);
15866
- if (Object.keys(resolved.mcpServers).length > 0) {
16472
+ const hasMcpChanges = Object.keys(resolved.mcpServers).length > 0 || resolved.agentMcpBindings.length > 0;
16473
+ const hasDisabledTools = resolved.disabledTools.length > 0;
16474
+ if (hasMcpChanges || hasDisabledTools) {
15867
16475
  const result = await updateOpencodeConfig(cwd, {
15868
- mcpServers: resolved.mcpServers
16476
+ mcpServers: resolved.mcpServers,
16477
+ agentMcpBindings: resolved.agentMcpBindings,
16478
+ disabledTools: resolved.disabledTools
15869
16479
  });
15870
16480
  if (result.mcpSkipped.length > 0 && !options3.quiet) {
15871
16481
  for (const name of result.mcpSkipped) {
@@ -15874,6 +16484,12 @@ async function runAdd(componentNames, options3) {
15874
16484
  }
15875
16485
  if (!options3.quiet && result.mcpAdded.length > 0) {
15876
16486
  logger.info(`Configured ${result.mcpAdded.length} MCP servers`);
16487
+ for (const binding of resolved.agentMcpBindings) {
16488
+ logger.info(` Scoped to agent "${binding.agentName}": ${binding.serverNames.join(", ")}`);
16489
+ }
16490
+ }
16491
+ if (!options3.quiet && result.toolsDisabled.length > 0) {
16492
+ logger.info(`Disabled ${result.toolsDisabled.length} tools: ${result.toolsDisabled.join(", ")}`);
15877
16493
  }
15878
16494
  }
15879
16495
  const hasNpmDeps = resolved.npmDependencies.length > 0;
@@ -17229,7 +17845,7 @@ function registerSearchCommand(program2) {
17229
17845
  }
17230
17846
 
17231
17847
  // src/index.ts
17232
- var version2 = "1.0.5";
17848
+ var version2 = "1.0.6";
17233
17849
  async function main2() {
17234
17850
  const program2 = new Command().name("ocx").description("OpenCode Extensions - Install agents, skills, plugins, and commands").version(version2);
17235
17851
  registerInitCommand(program2);
@@ -17244,4 +17860,4 @@ main2().catch((err) => {
17244
17860
  handleError(err);
17245
17861
  });
17246
17862
 
17247
- //# debugId=D94D02DC5FA0777E64756E2164756E21
17863
+ //# debugId=1145245802C7C7C964756E2164756E21