ocx 1.0.5 → 1.0.7

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
@@ -4533,32 +4533,32 @@ var require_fuzzysort = __commonJS((exports, module) => {
4533
4533
  noResults.total = 0;
4534
4534
  var NULL = null;
4535
4535
  var noTarget = prepare("");
4536
- var fastpriorityqueue = (r2) => {
4537
- var e2 = [], o2 = 0, a3 = {}, v2 = (r3) => {
4538
- for (var a4 = 0, v3 = e2[a4], c2 = 1;c2 < o2; ) {
4536
+ var fastpriorityqueue = (r3) => {
4537
+ var e4 = [], o2 = 0, a3 = {}, v2 = (r4) => {
4538
+ for (var a4 = 0, v3 = e4[a4], c2 = 1;c2 < o2; ) {
4539
4539
  var s2 = c2 + 1;
4540
- a4 = c2, s2 < o2 && e2[s2]._score < e2[c2]._score && (a4 = s2), e2[a4 - 1 >> 1] = e2[a4], c2 = 1 + (a4 << 1);
4540
+ a4 = c2, s2 < o2 && e4[s2]._score < e4[c2]._score && (a4 = s2), e4[a4 - 1 >> 1] = e4[a4], c2 = 1 + (a4 << 1);
4541
4541
  }
4542
- for (var f2 = a4 - 1 >> 1;a4 > 0 && v3._score < e2[f2]._score; f2 = (a4 = f2) - 1 >> 1)
4543
- e2[a4] = e2[f2];
4544
- e2[a4] = v3;
4542
+ for (var f2 = a4 - 1 >> 1;a4 > 0 && v3._score < e4[f2]._score; f2 = (a4 = f2) - 1 >> 1)
4543
+ e4[a4] = e4[f2];
4544
+ e4[a4] = v3;
4545
4545
  };
4546
- return a3.add = (r3) => {
4546
+ return a3.add = (r4) => {
4547
4547
  var a4 = o2;
4548
- e2[o2++] = r3;
4549
- for (var v3 = a4 - 1 >> 1;a4 > 0 && r3._score < e2[v3]._score; v3 = (a4 = v3) - 1 >> 1)
4550
- e2[a4] = e2[v3];
4551
- e2[a4] = r3;
4552
- }, a3.poll = (r3) => {
4548
+ e4[o2++] = r4;
4549
+ for (var v3 = a4 - 1 >> 1;a4 > 0 && r4._score < e4[v3]._score; v3 = (a4 = v3) - 1 >> 1)
4550
+ e4[a4] = e4[v3];
4551
+ e4[a4] = r4;
4552
+ }, a3.poll = (r4) => {
4553
4553
  if (o2 !== 0) {
4554
- var a4 = e2[0];
4555
- return e2[0] = e2[--o2], v2(), a4;
4554
+ var a4 = e4[0];
4555
+ return e4[0] = e4[--o2], v2(), a4;
4556
4556
  }
4557
- }, a3.peek = (r3) => {
4557
+ }, a3.peek = (r4) => {
4558
4558
  if (o2 !== 0)
4559
- return e2[0];
4560
- }, a3.replaceTop = (r3) => {
4561
- e2[0] = r3, v2();
4559
+ return e4[0];
4560
+ }, a3.replaceTop = (r4) => {
4561
+ e4[0] = r4, v2();
4562
4562
  }, a3;
4563
4563
  };
4564
4564
  var q2 = fastpriorityqueue();
@@ -13052,11 +13052,14 @@ var targetPathSchema = exports_external.string().refine((path3) => path3.startsW
13052
13052
  var skillTargetSchema = exports_external.string().regex(/^\.opencode\/skill\/[a-z0-9]+(-[a-z0-9]+)*\/SKILL\.md$/, {
13053
13053
  message: 'Skill target must match pattern ".opencode/skill/<name>/SKILL.md" where name follows OpenCode naming rules'
13054
13054
  });
13055
- var mcpServerSchema = exports_external.object({
13055
+ var mcpServerObjectSchema = exports_external.object({
13056
13056
  type: exports_external.enum(["remote", "local"]),
13057
13057
  url: exports_external.string().url().optional(),
13058
13058
  command: exports_external.array(exports_external.string()).optional(),
13059
+ args: exports_external.array(exports_external.string()).optional(),
13060
+ environment: exports_external.record(exports_external.string()).optional(),
13059
13061
  headers: exports_external.record(exports_external.string()).optional(),
13062
+ oauth: exports_external.boolean().optional(),
13060
13063
  enabled: exports_external.boolean().default(true)
13061
13064
  }).refine((data) => {
13062
13065
  if (data.type === "remote" && !data.url) {
@@ -13069,10 +13072,27 @@ var mcpServerSchema = exports_external.object({
13069
13072
  }, {
13070
13073
  message: "Remote MCP servers require 'url', local servers require 'command'"
13071
13074
  });
13072
- var componentFileSchema = exports_external.object({
13075
+ var mcpServerSchema = exports_external.union([exports_external.string().url(), mcpServerObjectSchema]);
13076
+ var componentFileObjectSchema = exports_external.object({
13073
13077
  path: exports_external.string().min(1, "File path cannot be empty"),
13074
13078
  target: targetPathSchema
13075
13079
  });
13080
+ var componentFileSchema = exports_external.union([
13081
+ exports_external.string().min(1, "File path cannot be empty"),
13082
+ componentFileObjectSchema
13083
+ ]);
13084
+ var agentConfigSchema = exports_external.object({
13085
+ tools: exports_external.record(exports_external.boolean()).optional(),
13086
+ temperature: exports_external.number().min(0).max(2).optional(),
13087
+ prompt: exports_external.string().optional(),
13088
+ permission: exports_external.record(exports_external.enum(["allow", "deny"])).optional()
13089
+ });
13090
+ var opencodeConfigSchema = exports_external.object({
13091
+ plugins: exports_external.array(exports_external.string()).optional(),
13092
+ tools: exports_external.record(exports_external.boolean()).optional(),
13093
+ agent: exports_external.record(agentConfigSchema).optional(),
13094
+ instructions: exports_external.array(exports_external.string()).optional()
13095
+ });
13076
13096
  var componentManifestSchema = exports_external.object({
13077
13097
  name: openCodeNameSchema,
13078
13098
  type: componentTypeSchema,
@@ -13082,8 +13102,42 @@ var componentManifestSchema = exports_external.object({
13082
13102
  npmDependencies: exports_external.array(exports_external.string()).optional(),
13083
13103
  npmDevDependencies: exports_external.array(exports_external.string()).optional(),
13084
13104
  mcpServers: exports_external.record(mcpServerSchema).optional(),
13085
- mcpScope: exports_external.enum(["agent", "global"]).default("agent")
13105
+ mcpScope: exports_external.enum(["agent", "global"]).default("agent"),
13106
+ opencode: opencodeConfigSchema.optional(),
13107
+ disabledTools: exports_external.array(exports_external.string()).optional()
13086
13108
  });
13109
+ function inferTargetPath(sourcePath) {
13110
+ return `.opencode/${sourcePath}`;
13111
+ }
13112
+ function normalizeFile(file) {
13113
+ if (typeof file === "string") {
13114
+ return {
13115
+ path: file,
13116
+ target: inferTargetPath(file)
13117
+ };
13118
+ }
13119
+ return file;
13120
+ }
13121
+ function normalizeMcpServer(server) {
13122
+ if (typeof server === "string") {
13123
+ return {
13124
+ type: "remote",
13125
+ url: server,
13126
+ enabled: true
13127
+ };
13128
+ }
13129
+ return server;
13130
+ }
13131
+ function normalizeComponentManifest(manifest) {
13132
+ return {
13133
+ ...manifest,
13134
+ files: manifest.files.map(normalizeFile),
13135
+ mcpServers: manifest.mcpServers ? Object.fromEntries(Object.entries(manifest.mcpServers).map(([name, server]) => [
13136
+ name,
13137
+ normalizeMcpServer(server)
13138
+ ])) : undefined
13139
+ };
13140
+ }
13087
13141
  var semverRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/;
13088
13142
  var registrySchema = exports_external.object({
13089
13143
  name: exports_external.string().min(1, "Registry name cannot be empty"),
@@ -13251,6 +13305,166 @@ async function fetchFileContent(baseUrl, componentName, filePath) {
13251
13305
  return response.text();
13252
13306
  }
13253
13307
 
13308
+ // ../../node_modules/.bun/remeda@2.33.0/node_modules/remeda/dist/lazyDataLastImpl-DtF3cihj.js
13309
+ function e2(e3, t2, n2) {
13310
+ let r2 = (n3) => e3(n3, ...t2);
13311
+ return n2 === undefined ? r2 : Object.assign(r2, { lazy: n2, lazyArgs: t2 });
13312
+ }
13313
+
13314
+ // ../../node_modules/.bun/remeda@2.33.0/node_modules/remeda/dist/purry-GjwKKIlp.js
13315
+ function t2(t3, n2, r2) {
13316
+ let i2 = t3.length - n2.length;
13317
+ if (i2 === 0)
13318
+ return t3(...n2);
13319
+ if (i2 === 1)
13320
+ return e2(t3, n2, r2);
13321
+ throw Error(`Wrong number of arguments`);
13322
+ }
13323
+
13324
+ // ../../node_modules/.bun/remeda@2.33.0/node_modules/remeda/dist/isPlainObject.js
13325
+ function e3(e4) {
13326
+ if (typeof e4 != `object` || !e4)
13327
+ return false;
13328
+ let t3 = Object.getPrototypeOf(e4);
13329
+ return t3 === null || t3 === Object.prototype;
13330
+ }
13331
+
13332
+ // ../../node_modules/.bun/remeda@2.33.0/node_modules/remeda/dist/mergeDeep.js
13333
+ function n2(...t3) {
13334
+ return t2(r2, t3);
13335
+ }
13336
+ function r2(e4, n3) {
13337
+ let i2 = { ...e4, ...n3 };
13338
+ for (let a3 in n3) {
13339
+ if (!(a3 in e4))
13340
+ continue;
13341
+ let { [a3]: o2 } = e4;
13342
+ if (!e3(o2))
13343
+ continue;
13344
+ let { [a3]: s2 } = n3;
13345
+ e3(s2) && (i2[a3] = r2(o2, s2));
13346
+ }
13347
+ return i2;
13348
+ }
13349
+
13350
+ // src/registry/resolver.ts
13351
+ async function resolveDependencies(registries, componentNames) {
13352
+ const resolved = new Map;
13353
+ const visiting = new Set;
13354
+ const mcpServers = {};
13355
+ const agentMcpBindings = [];
13356
+ const npmDeps = new Set;
13357
+ const npmDevDeps = new Set;
13358
+ const disabledTools = new Set;
13359
+ const plugins = new Set;
13360
+ const agentConfigs = {};
13361
+ const instructionsSet = new Set;
13362
+ async function resolve2(name, path3 = []) {
13363
+ if (resolved.has(name)) {
13364
+ return;
13365
+ }
13366
+ if (visiting.has(name)) {
13367
+ const cycle = [...path3, name].join(" \u2192 ");
13368
+ throw new ValidationError(`Circular dependency detected: ${cycle}`);
13369
+ }
13370
+ visiting.add(name);
13371
+ let component = null;
13372
+ let foundRegistry = null;
13373
+ const registryEntries = Object.entries(registries);
13374
+ for (const [regName, regConfig] of registryEntries) {
13375
+ try {
13376
+ const manifest = await fetchComponent(regConfig.url, name);
13377
+ component = manifest;
13378
+ foundRegistry = { name: regName, url: regConfig.url };
13379
+ break;
13380
+ } catch (_err) {}
13381
+ }
13382
+ if (!component || !foundRegistry) {
13383
+ throw new OCXError(`Component '${name}' not found in any configured registry.`, "NOT_FOUND");
13384
+ }
13385
+ for (const dep of component.dependencies) {
13386
+ await resolve2(dep, [...path3, name]);
13387
+ }
13388
+ const normalizedComponent = normalizeComponentManifest(component);
13389
+ resolved.set(name, {
13390
+ ...normalizedComponent,
13391
+ registryName: foundRegistry.name,
13392
+ baseUrl: foundRegistry.url
13393
+ });
13394
+ visiting.delete(name);
13395
+ if (normalizedComponent.mcpServers) {
13396
+ const serverNames = [];
13397
+ for (const [serverName, config2] of Object.entries(normalizedComponent.mcpServers)) {
13398
+ mcpServers[serverName] = config2;
13399
+ serverNames.push(serverName);
13400
+ }
13401
+ const scope = component.mcpScope ?? "agent";
13402
+ if (component.type === "ocx:agent" && scope === "agent" && serverNames.length > 0) {
13403
+ agentMcpBindings.push({
13404
+ agentName: component.name,
13405
+ serverNames
13406
+ });
13407
+ }
13408
+ }
13409
+ if (component.npmDependencies) {
13410
+ for (const dep of component.npmDependencies) {
13411
+ npmDeps.add(dep);
13412
+ }
13413
+ }
13414
+ if (component.npmDevDependencies) {
13415
+ for (const dep of component.npmDevDependencies) {
13416
+ npmDevDeps.add(dep);
13417
+ }
13418
+ }
13419
+ if (component.disabledTools) {
13420
+ for (const tool of component.disabledTools) {
13421
+ disabledTools.add(tool);
13422
+ }
13423
+ }
13424
+ if (component.opencode) {
13425
+ if (component.opencode.plugins) {
13426
+ for (const plugin of component.opencode.plugins) {
13427
+ plugins.add(plugin);
13428
+ }
13429
+ }
13430
+ if (component.opencode.agent) {
13431
+ for (const [agentName, config2] of Object.entries(component.opencode.agent)) {
13432
+ agentConfigs[agentName] = n2(agentConfigs[agentName] ?? {}, config2);
13433
+ }
13434
+ }
13435
+ if (component.opencode.instructions) {
13436
+ for (const instruction of component.opencode.instructions) {
13437
+ instructionsSet.add(instruction);
13438
+ }
13439
+ }
13440
+ if (component.opencode.tools) {
13441
+ for (const [tool, enabled] of Object.entries(component.opencode.tools)) {
13442
+ if (enabled === false) {
13443
+ disabledTools.add(tool);
13444
+ }
13445
+ }
13446
+ }
13447
+ }
13448
+ }
13449
+ for (const name of componentNames) {
13450
+ await resolve2(name);
13451
+ }
13452
+ const components = Array.from(resolved.values());
13453
+ const installOrder = Array.from(resolved.keys());
13454
+ return {
13455
+ components,
13456
+ installOrder,
13457
+ mcpServers,
13458
+ agentMcpBindings,
13459
+ npmDependencies: Array.from(npmDeps),
13460
+ npmDevDependencies: Array.from(npmDevDeps),
13461
+ disabledTools: Array.from(disabledTools),
13462
+ plugins: Array.from(plugins),
13463
+ agentConfigs,
13464
+ instructions: Array.from(instructionsSet)
13465
+ };
13466
+ }
13467
+
13254
13468
  // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js
13255
13469
  function createScanner(text2, ignoreTrivia = false) {
13256
13470
  const len = text2.length;
@@ -13699,6 +13913,249 @@ var cachedBreakLinesWithSpaces = {
13699
13913
  })
13700
13914
  }
13701
13915
  };
13916
+ var supportedEols = [`
13917
+ `, "\r", `\r
13918
+ `];
13919
+
13920
+ // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/format.js
13921
+ function format(documentText, range, options2) {
13922
+ let initialIndentLevel;
13923
+ let formatText;
13924
+ let formatTextStart;
13925
+ let rangeStart;
13926
+ let rangeEnd;
13927
+ if (range) {
13928
+ rangeStart = range.offset;
13929
+ rangeEnd = rangeStart + range.length;
13930
+ formatTextStart = rangeStart;
13931
+ while (formatTextStart > 0 && !isEOL(documentText, formatTextStart - 1)) {
13932
+ formatTextStart--;
13933
+ }
13934
+ let endOffset = rangeEnd;
13935
+ while (endOffset < documentText.length && !isEOL(documentText, endOffset)) {
13936
+ endOffset++;
13937
+ }
13938
+ formatText = documentText.substring(formatTextStart, endOffset);
13939
+ initialIndentLevel = computeIndentLevel(formatText, options2);
13940
+ } else {
13941
+ formatText = documentText;
13942
+ initialIndentLevel = 0;
13943
+ formatTextStart = 0;
13944
+ rangeStart = 0;
13945
+ rangeEnd = documentText.length;
13946
+ }
13947
+ const eol = getEOL(options2, documentText);
13948
+ const eolFastPathSupported = supportedEols.includes(eol);
13949
+ let numberLineBreaks = 0;
13950
+ let indentLevel = 0;
13951
+ let indentValue;
13952
+ if (options2.insertSpaces) {
13953
+ indentValue = cachedSpaces[options2.tabSize || 4] ?? repeat(cachedSpaces[1], options2.tabSize || 4);
13954
+ } else {
13955
+ indentValue = "\t";
13956
+ }
13957
+ const indentType = indentValue === "\t" ? "\t" : " ";
13958
+ let scanner = createScanner(formatText, false);
13959
+ let hasError = false;
13960
+ function newLinesAndIndent() {
13961
+ if (numberLineBreaks > 1) {
13962
+ return repeat(eol, numberLineBreaks) + repeat(indentValue, initialIndentLevel + indentLevel);
13963
+ }
13964
+ const amountOfSpaces = indentValue.length * (initialIndentLevel + indentLevel);
13965
+ if (!eolFastPathSupported || amountOfSpaces > cachedBreakLinesWithSpaces[indentType][eol].length) {
13966
+ return eol + repeat(indentValue, initialIndentLevel + indentLevel);
13967
+ }
13968
+ if (amountOfSpaces <= 0) {
13969
+ return eol;
13970
+ }
13971
+ return cachedBreakLinesWithSpaces[indentType][eol][amountOfSpaces];
13972
+ }
13973
+ function scanNext() {
13974
+ let token = scanner.scan();
13975
+ numberLineBreaks = 0;
13976
+ while (token === 15 || token === 14) {
13977
+ if (token === 14 && options2.keepLines) {
13978
+ numberLineBreaks += 1;
13979
+ } else if (token === 14) {
13980
+ numberLineBreaks = 1;
13981
+ }
13982
+ token = scanner.scan();
13983
+ }
13984
+ hasError = token === 16 || scanner.getTokenError() !== 0;
13985
+ return token;
13986
+ }
13987
+ const editOperations = [];
13988
+ function addEdit(text2, startOffset, endOffset) {
13989
+ if (!hasError && (!range || startOffset < rangeEnd && endOffset > rangeStart) && documentText.substring(startOffset, endOffset) !== text2) {
13990
+ editOperations.push({ offset: startOffset, length: endOffset - startOffset, content: text2 });
13991
+ }
13992
+ }
13993
+ let firstToken = scanNext();
13994
+ if (options2.keepLines && numberLineBreaks > 0) {
13995
+ addEdit(repeat(eol, numberLineBreaks), 0, 0);
13996
+ }
13997
+ if (firstToken !== 17) {
13998
+ let firstTokenStart = scanner.getTokenOffset() + formatTextStart;
13999
+ let initialIndent = indentValue.length * initialIndentLevel < 20 && options2.insertSpaces ? cachedSpaces[indentValue.length * initialIndentLevel] : repeat(indentValue, initialIndentLevel);
14000
+ addEdit(initialIndent, formatTextStart, firstTokenStart);
14001
+ }
14002
+ while (firstToken !== 17) {
14003
+ let firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
14004
+ let secondToken = scanNext();
14005
+ let replaceContent = "";
14006
+ let needsLineBreak = false;
14007
+ while (numberLineBreaks === 0 && (secondToken === 12 || secondToken === 13)) {
14008
+ let commentTokenStart = scanner.getTokenOffset() + formatTextStart;
14009
+ addEdit(cachedSpaces[1], firstTokenEnd, commentTokenStart);
14010
+ firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
14011
+ needsLineBreak = secondToken === 12;
14012
+ replaceContent = needsLineBreak ? newLinesAndIndent() : "";
14013
+ secondToken = scanNext();
14014
+ }
14015
+ if (secondToken === 2) {
14016
+ if (firstToken !== 1) {
14017
+ indentLevel--;
14018
+ }
14019
+ if (options2.keepLines && numberLineBreaks > 0 || !options2.keepLines && firstToken !== 1) {
14020
+ replaceContent = newLinesAndIndent();
14021
+ } else if (options2.keepLines) {
14022
+ replaceContent = cachedSpaces[1];
14023
+ }
14024
+ } else if (secondToken === 4) {
14025
+ if (firstToken !== 3) {
14026
+ indentLevel--;
14027
+ }
14028
+ if (options2.keepLines && numberLineBreaks > 0 || !options2.keepLines && firstToken !== 3) {
14029
+ replaceContent = newLinesAndIndent();
14030
+ } else if (options2.keepLines) {
14031
+ replaceContent = cachedSpaces[1];
14032
+ }
14033
+ } else {
14034
+ switch (firstToken) {
14035
+ case 3:
14036
+ case 1:
14037
+ indentLevel++;
14038
+ if (options2.keepLines && numberLineBreaks > 0 || !options2.keepLines) {
14039
+ replaceContent = newLinesAndIndent();
14040
+ } else {
14041
+ replaceContent = cachedSpaces[1];
14042
+ }
14043
+ break;
14044
+ case 5:
14045
+ if (options2.keepLines && numberLineBreaks > 0 || !options2.keepLines) {
14046
+ replaceContent = newLinesAndIndent();
14047
+ } else {
14048
+ replaceContent = cachedSpaces[1];
14049
+ }
14050
+ break;
14051
+ case 12:
14052
+ replaceContent = newLinesAndIndent();
14053
+ break;
14054
+ case 13:
14055
+ if (numberLineBreaks > 0) {
14056
+ replaceContent = newLinesAndIndent();
14057
+ } else if (!needsLineBreak) {
14058
+ replaceContent = cachedSpaces[1];
14059
+ }
14060
+ break;
14061
+ case 6:
14062
+ if (options2.keepLines && numberLineBreaks > 0) {
14063
+ replaceContent = newLinesAndIndent();
14064
+ } else if (!needsLineBreak) {
14065
+ replaceContent = cachedSpaces[1];
14066
+ }
14067
+ break;
14068
+ case 10:
14069
+ if (options2.keepLines && numberLineBreaks > 0) {
14070
+ replaceContent = newLinesAndIndent();
14071
+ } else if (secondToken === 6 && !needsLineBreak) {
14072
+ replaceContent = "";
14073
+ }
14074
+ break;
14075
+ case 7:
14076
+ case 8:
14077
+ case 9:
14078
+ case 11:
14079
+ case 2:
14080
+ case 4:
14081
+ if (options2.keepLines && numberLineBreaks > 0) {
14082
+ replaceContent = newLinesAndIndent();
14083
+ } else {
14084
+ if ((secondToken === 12 || secondToken === 13) && !needsLineBreak) {
14085
+ replaceContent = cachedSpaces[1];
14086
+ } else if (secondToken !== 5 && secondToken !== 17) {
14087
+ hasError = true;
14088
+ }
14089
+ }
14090
+ break;
14091
+ case 16:
14092
+ hasError = true;
14093
+ break;
14094
+ }
14095
+ if (numberLineBreaks > 0 && (secondToken === 12 || secondToken === 13)) {
14096
+ replaceContent = newLinesAndIndent();
14097
+ }
14098
+ }
14099
+ if (secondToken === 17) {
14100
+ if (options2.keepLines && numberLineBreaks > 0) {
14101
+ replaceContent = newLinesAndIndent();
14102
+ } else {
14103
+ replaceContent = options2.insertFinalNewline ? eol : "";
14104
+ }
14105
+ }
14106
+ const secondTokenStart = scanner.getTokenOffset() + formatTextStart;
14107
+ addEdit(replaceContent, firstTokenEnd, secondTokenStart);
14108
+ firstToken = secondToken;
14109
+ }
14110
+ return editOperations;
14111
+ }
14112
+ function repeat(s2, count) {
14113
+ let result = "";
14114
+ for (let i2 = 0;i2 < count; i2++) {
14115
+ result += s2;
14116
+ }
14117
+ return result;
14118
+ }
14119
+ function computeIndentLevel(content, options2) {
14120
+ let i2 = 0;
14121
+ let nChars = 0;
14122
+ const tabSize = options2.tabSize || 4;
14123
+ while (i2 < content.length) {
14124
+ let ch = content.charAt(i2);
14125
+ if (ch === cachedSpaces[1]) {
14126
+ nChars++;
14127
+ } else if (ch === "\t") {
14128
+ nChars += tabSize;
14129
+ } else {
14130
+ break;
14131
+ }
14132
+ i2++;
14133
+ }
14134
+ return Math.floor(nChars / tabSize);
14135
+ }
14136
+ function getEOL(options2, text2) {
14137
+ for (let i2 = 0;i2 < text2.length; i2++) {
14138
+ const ch = text2.charAt(i2);
14139
+ if (ch === "\r") {
14140
+ if (i2 + 1 < text2.length && text2.charAt(i2 + 1) === `
14141
+ `) {
14142
+ return `\r
14143
+ `;
14144
+ }
14145
+ return "\r";
14146
+ } else if (ch === `
14147
+ `) {
14148
+ return `
14149
+ `;
14150
+ }
14151
+ }
14152
+ return options2 && options2.eol || `
14153
+ `;
14154
+ }
14155
+ function isEOL(text2, offset) {
14156
+ return `\r
14157
+ `.indexOf(text2.charAt(offset)) !== -1;
14158
+ }
13702
14159
 
13703
14160
  // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/parser.js
13704
14161
  var ParseOptions;
@@ -13750,6 +14207,95 @@ function parse(text2, errors2 = [], options2 = ParseOptions.DEFAULT) {
13750
14207
  visit(text2, visitor, options2);
13751
14208
  return currentParent[0];
13752
14209
  }
14210
+ function parseTree(text2, errors2 = [], options2 = ParseOptions.DEFAULT) {
14211
+ let currentParent = { type: "array", offset: -1, length: -1, children: [], parent: undefined };
14212
+ function ensurePropertyComplete(endOffset) {
14213
+ if (currentParent.type === "property") {
14214
+ currentParent.length = endOffset - currentParent.offset;
14215
+ currentParent = currentParent.parent;
14216
+ }
14217
+ }
14218
+ function onValue(valueNode) {
14219
+ currentParent.children.push(valueNode);
14220
+ return valueNode;
14221
+ }
14222
+ const visitor = {
14223
+ onObjectBegin: (offset) => {
14224
+ currentParent = onValue({ type: "object", offset, length: -1, parent: currentParent, children: [] });
14225
+ },
14226
+ onObjectProperty: (name, offset, length) => {
14227
+ currentParent = onValue({ type: "property", offset, length: -1, parent: currentParent, children: [] });
14228
+ currentParent.children.push({ type: "string", value: name, offset, length, parent: currentParent });
14229
+ },
14230
+ onObjectEnd: (offset, length) => {
14231
+ ensurePropertyComplete(offset + length);
14232
+ currentParent.length = offset + length - currentParent.offset;
14233
+ currentParent = currentParent.parent;
14234
+ ensurePropertyComplete(offset + length);
14235
+ },
14236
+ onArrayBegin: (offset, length) => {
14237
+ currentParent = onValue({ type: "array", offset, length: -1, parent: currentParent, children: [] });
14238
+ },
14239
+ onArrayEnd: (offset, length) => {
14240
+ currentParent.length = offset + length - currentParent.offset;
14241
+ currentParent = currentParent.parent;
14242
+ ensurePropertyComplete(offset + length);
14243
+ },
14244
+ onLiteralValue: (value, offset, length) => {
14245
+ onValue({ type: getNodeType(value), offset, length, parent: currentParent, value });
14246
+ ensurePropertyComplete(offset + length);
14247
+ },
14248
+ onSeparator: (sep, offset, length) => {
14249
+ if (currentParent.type === "property") {
14250
+ if (sep === ":") {
14251
+ currentParent.colonOffset = offset;
14252
+ } else if (sep === ",") {
14253
+ ensurePropertyComplete(offset);
14254
+ }
14255
+ }
14256
+ },
14257
+ onError: (error, offset, length) => {
14258
+ errors2.push({ error, offset, length });
14259
+ }
14260
+ };
14261
+ visit(text2, visitor, options2);
14262
+ const result = currentParent.children[0];
14263
+ if (result) {
14264
+ delete result.parent;
14265
+ }
14266
+ return result;
14267
+ }
14268
+ function findNodeAtLocation(root, path3) {
14269
+ if (!root) {
14270
+ return;
14271
+ }
14272
+ let node = root;
14273
+ for (let segment of path3) {
14274
+ if (typeof segment === "string") {
14275
+ if (node.type !== "object" || !Array.isArray(node.children)) {
14276
+ return;
14277
+ }
14278
+ let found = false;
14279
+ for (const propertyNode of node.children) {
14280
+ if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment && propertyNode.children.length === 2) {
14281
+ node = propertyNode.children[1];
14282
+ found = true;
14283
+ break;
14284
+ }
14285
+ }
14286
+ if (!found) {
14287
+ return;
14288
+ }
14289
+ } else {
14290
+ const index = segment;
14291
+ if (node.type !== "array" || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {
14292
+ return;
14293
+ }
14294
+ node = node.children[index];
14295
+ }
14296
+ }
14297
+ return node;
14298
+ }
13753
14299
  function visit(text2, visitor, options2 = ParseOptions.DEFAULT) {
13754
14300
  const _scanner = createScanner(text2, false);
13755
14301
  const _jsonPath = [];
@@ -14002,6 +14548,170 @@ function visit(text2, visitor, options2 = ParseOptions.DEFAULT) {
14002
14548
  }
14003
14549
  return true;
14004
14550
  }
14551
+ function getNodeType(value) {
14552
+ switch (typeof value) {
14553
+ case "boolean":
14554
+ return "boolean";
14555
+ case "number":
14556
+ return "number";
14557
+ case "string":
14558
+ return "string";
14559
+ case "object": {
14560
+ if (!value) {
14561
+ return "null";
14562
+ } else if (Array.isArray(value)) {
14563
+ return "array";
14564
+ }
14565
+ return "object";
14566
+ }
14567
+ default:
14568
+ return "null";
14569
+ }
14570
+ }
14571
+
14572
+ // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/edit.js
14573
+ function setProperty(text2, originalPath, value, options2) {
14574
+ const path3 = originalPath.slice();
14575
+ const errors2 = [];
14576
+ const root = parseTree(text2, errors2);
14577
+ let parent = undefined;
14578
+ let lastSegment = undefined;
14579
+ while (path3.length > 0) {
14580
+ lastSegment = path3.pop();
14581
+ parent = findNodeAtLocation(root, path3);
14582
+ if (parent === undefined && value !== undefined) {
14583
+ if (typeof lastSegment === "string") {
14584
+ value = { [lastSegment]: value };
14585
+ } else {
14586
+ value = [value];
14587
+ }
14588
+ } else {
14589
+ break;
14590
+ }
14591
+ }
14592
+ if (!parent) {
14593
+ if (value === undefined) {
14594
+ throw new Error("Can not delete in empty document");
14595
+ }
14596
+ return withFormatting(text2, { offset: root ? root.offset : 0, length: root ? root.length : 0, content: JSON.stringify(value) }, options2);
14597
+ } else if (parent.type === "object" && typeof lastSegment === "string" && Array.isArray(parent.children)) {
14598
+ const existing = findNodeAtLocation(parent, [lastSegment]);
14599
+ if (existing !== undefined) {
14600
+ if (value === undefined) {
14601
+ if (!existing.parent) {
14602
+ throw new Error("Malformed AST");
14603
+ }
14604
+ const propertyIndex = parent.children.indexOf(existing.parent);
14605
+ let removeBegin;
14606
+ let removeEnd = existing.parent.offset + existing.parent.length;
14607
+ if (propertyIndex > 0) {
14608
+ let previous = parent.children[propertyIndex - 1];
14609
+ removeBegin = previous.offset + previous.length;
14610
+ } else {
14611
+ removeBegin = parent.offset + 1;
14612
+ if (parent.children.length > 1) {
14613
+ let next = parent.children[1];
14614
+ removeEnd = next.offset;
14615
+ }
14616
+ }
14617
+ return withFormatting(text2, { offset: removeBegin, length: removeEnd - removeBegin, content: "" }, options2);
14618
+ } else {
14619
+ return withFormatting(text2, { offset: existing.offset, length: existing.length, content: JSON.stringify(value) }, options2);
14620
+ }
14621
+ } else {
14622
+ if (value === undefined) {
14623
+ return [];
14624
+ }
14625
+ const newProperty = `${JSON.stringify(lastSegment)}: ${JSON.stringify(value)}`;
14626
+ const index = options2.getInsertionIndex ? options2.getInsertionIndex(parent.children.map((p2) => p2.children[0].value)) : parent.children.length;
14627
+ let edit;
14628
+ if (index > 0) {
14629
+ let previous = parent.children[index - 1];
14630
+ edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
14631
+ } else if (parent.children.length === 0) {
14632
+ edit = { offset: parent.offset + 1, length: 0, content: newProperty };
14633
+ } else {
14634
+ edit = { offset: parent.offset + 1, length: 0, content: newProperty + "," };
14635
+ }
14636
+ return withFormatting(text2, edit, options2);
14637
+ }
14638
+ } else if (parent.type === "array" && typeof lastSegment === "number" && Array.isArray(parent.children)) {
14639
+ const insertIndex = lastSegment;
14640
+ if (insertIndex === -1) {
14641
+ const newProperty = `${JSON.stringify(value)}`;
14642
+ let edit;
14643
+ if (parent.children.length === 0) {
14644
+ edit = { offset: parent.offset + 1, length: 0, content: newProperty };
14645
+ } else {
14646
+ const previous = parent.children[parent.children.length - 1];
14647
+ edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
14648
+ }
14649
+ return withFormatting(text2, edit, options2);
14650
+ } else if (value === undefined && parent.children.length >= 0) {
14651
+ const removalIndex = lastSegment;
14652
+ const toRemove = parent.children[removalIndex];
14653
+ let edit;
14654
+ if (parent.children.length === 1) {
14655
+ edit = { offset: parent.offset + 1, length: parent.length - 2, content: "" };
14656
+ } else if (parent.children.length - 1 === removalIndex) {
14657
+ let previous = parent.children[removalIndex - 1];
14658
+ let offset = previous.offset + previous.length;
14659
+ let parentEndOffset = parent.offset + parent.length;
14660
+ edit = { offset, length: parentEndOffset - 2 - offset, content: "" };
14661
+ } else {
14662
+ edit = { offset: toRemove.offset, length: parent.children[removalIndex + 1].offset - toRemove.offset, content: "" };
14663
+ }
14664
+ return withFormatting(text2, edit, options2);
14665
+ } else if (value !== undefined) {
14666
+ let edit;
14667
+ const newProperty = `${JSON.stringify(value)}`;
14668
+ if (!options2.isArrayInsertion && parent.children.length > lastSegment) {
14669
+ const toModify = parent.children[lastSegment];
14670
+ edit = { offset: toModify.offset, length: toModify.length, content: newProperty };
14671
+ } else if (parent.children.length === 0 || lastSegment === 0) {
14672
+ edit = { offset: parent.offset + 1, length: 0, content: parent.children.length === 0 ? newProperty : newProperty + "," };
14673
+ } else {
14674
+ const index = lastSegment > parent.children.length ? parent.children.length : lastSegment;
14675
+ const previous = parent.children[index - 1];
14676
+ edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
14677
+ }
14678
+ return withFormatting(text2, edit, options2);
14679
+ } else {
14680
+ throw new Error(`Can not ${value === undefined ? "remove" : options2.isArrayInsertion ? "insert" : "modify"} Array index ${insertIndex} as length is not sufficient`);
14681
+ }
14682
+ } else {
14683
+ throw new Error(`Can not add ${typeof lastSegment !== "number" ? "index" : "property"} to parent of type ${parent.type}`);
14684
+ }
14685
+ }
14686
+ function withFormatting(text2, edit, options2) {
14687
+ if (!options2.formattingOptions) {
14688
+ return [edit];
14689
+ }
14690
+ let newText = applyEdit(text2, edit);
14691
+ let begin = edit.offset;
14692
+ let end = edit.offset + edit.content.length;
14693
+ if (edit.length === 0 || edit.content.length === 0) {
14694
+ while (begin > 0 && !isEOL(newText, begin - 1)) {
14695
+ begin--;
14696
+ }
14697
+ while (end < newText.length && !isEOL(newText, end)) {
14698
+ end++;
14699
+ }
14700
+ }
14701
+ const edits = format(newText, { offset: begin, length: end - begin }, { ...options2.formattingOptions, keepLines: false });
14702
+ for (let i2 = edits.length - 1;i2 >= 0; i2--) {
14703
+ const edit2 = edits[i2];
14704
+ newText = applyEdit(newText, edit2);
14705
+ begin = Math.min(begin, edit2.offset);
14706
+ end = Math.max(end, edit2.offset + edit2.length);
14707
+ end += edit2.content.length - edit2.length;
14708
+ }
14709
+ const editLength = text2.length - (newText.length - end) - begin;
14710
+ return [{ offset: begin, length: editLength, content: newText.substring(begin, end) }];
14711
+ }
14712
+ function applyEdit(text2, edit) {
14713
+ return text2.substring(0, edit.offset) + edit.content + text2.substring(edit.offset + edit.length);
14714
+ }
14005
14715
 
14006
14716
  // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/main.js
14007
14717
  var ScanError;
@@ -14054,158 +14764,28 @@ var ParseErrorCode;
14054
14764
  ParseErrorCode2[ParseErrorCode2["InvalidEscapeCharacter"] = 15] = "InvalidEscapeCharacter";
14055
14765
  ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
14056
14766
  })(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);
14767
+ function modify(text2, path3, value, options2) {
14768
+ return setProperty(text2, path3, value, options2);
14077
14769
  }
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);
14770
+ function applyEdits(text2, edits) {
14771
+ let sortedEdits = edits.slice(0).sort((a3, b2) => {
14772
+ const diff = a3.offset - b2.offset;
14773
+ if (diff === 0) {
14774
+ return a3.length - b2.length;
14103
14775
  }
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
- };
14140
- }
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;
14152
- }
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
- }
14776
+ return diff;
14777
+ });
14778
+ let lastModifiedOffset = text2.length;
14779
+ for (let i2 = sortedEdits.length - 1;i2 >= 0; i2--) {
14780
+ let e4 = sortedEdits[i2];
14781
+ if (e4.offset + e4.length <= lastModifiedOffset) {
14782
+ text2 = applyEdit(text2, e4);
14783
+ } else {
14784
+ throw new Error("Overlapping edit");
14195
14785
  }
14786
+ lastModifiedOffset = e4.offset;
14196
14787
  }
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
- };
14788
+ return text2;
14209
14789
  }
14210
14790
 
14211
14791
  // src/schemas/config.ts
@@ -14233,13 +14813,18 @@ var ocxLockSchema = exports_external.object({
14233
14813
  var opencodeMcpSchema = exports_external.record(mcpServerSchema);
14234
14814
  var opencodeAgentSchema = exports_external.object({
14235
14815
  disable: exports_external.boolean().optional(),
14236
- tools: exports_external.record(exports_external.boolean()).optional()
14816
+ tools: exports_external.record(exports_external.boolean()).optional(),
14817
+ temperature: exports_external.number().min(0).max(2).optional(),
14818
+ prompt: exports_external.string().optional(),
14819
+ permission: exports_external.record(exports_external.enum(["allow", "deny"])).optional()
14237
14820
  });
14238
14821
  var opencodeConfigPatchSchema = exports_external.object({
14239
14822
  default_agent: exports_external.string().optional(),
14240
14823
  mcp: opencodeMcpSchema.optional(),
14241
14824
  tools: exports_external.record(exports_external.boolean()).optional(),
14242
- agent: exports_external.record(opencodeAgentSchema).optional()
14825
+ agent: exports_external.record(opencodeAgentSchema).optional(),
14826
+ plugin: exports_external.array(exports_external.string()).optional(),
14827
+ instructions: exports_external.array(exports_external.string()).optional()
14243
14828
  });
14244
14829
  var CONFIG_FILE = "ocx.jsonc";
14245
14830
  var LOCK_FILE = "ocx.lock";
@@ -14274,6 +14859,240 @@ async function readOcxLock(cwd) {
14274
14859
  return ocxLockSchema.parse(json);
14275
14860
  }
14276
14861
 
14862
+ // src/updaters/update-opencode-config.ts
14863
+ var JSONC_OPTIONS = {
14864
+ formattingOptions: {
14865
+ tabSize: 2,
14866
+ insertSpaces: false,
14867
+ eol: `
14868
+ `
14869
+ }
14870
+ };
14871
+ async function readOpencodeConfig(cwd) {
14872
+ const jsonPath = `${cwd}/opencode.json`;
14873
+ const jsoncPath = `${cwd}/opencode.jsonc`;
14874
+ for (const configPath of [jsoncPath, jsonPath]) {
14875
+ const file = Bun.file(configPath);
14876
+ if (await file.exists()) {
14877
+ const content = await file.text();
14878
+ return {
14879
+ config: parse2(content, [], { allowTrailingComma: true }),
14880
+ content,
14881
+ path: configPath
14882
+ };
14883
+ }
14884
+ }
14885
+ return null;
14886
+ }
14887
+ async function writeOpencodeConfig(path3, content) {
14888
+ await Bun.write(path3, content);
14889
+ }
14890
+ function applyMcpServers(content, config2, mcpServers) {
14891
+ const added = [];
14892
+ const skipped = [];
14893
+ let updatedContent = content;
14894
+ const existingMcp = config2.mcp ?? {};
14895
+ for (const [name, server] of Object.entries(mcpServers)) {
14896
+ if (existingMcp[name]) {
14897
+ skipped.push(name);
14898
+ continue;
14899
+ }
14900
+ const serverConfig = {
14901
+ type: server.type
14902
+ };
14903
+ if (server.type === "remote" && server.url) {
14904
+ serverConfig.url = server.url;
14905
+ }
14906
+ if (server.type === "local" && server.command) {
14907
+ serverConfig.command = server.command;
14908
+ }
14909
+ if (server.headers) {
14910
+ serverConfig.headers = server.headers;
14911
+ }
14912
+ if (server.enabled !== undefined) {
14913
+ serverConfig.enabled = server.enabled;
14914
+ }
14915
+ const edits = modify(updatedContent, ["mcp", name], serverConfig, JSONC_OPTIONS);
14916
+ updatedContent = applyEdits(updatedContent, edits);
14917
+ added.push(name);
14918
+ }
14919
+ return { content: updatedContent, added, skipped };
14920
+ }
14921
+ function applyGlobalToolDisables(content, serverNames) {
14922
+ let updatedContent = content;
14923
+ for (const name of serverNames) {
14924
+ const toolPattern = `${name}_*`;
14925
+ const edits = modify(updatedContent, ["tools", toolPattern], false, JSONC_OPTIONS);
14926
+ updatedContent = applyEdits(updatedContent, edits);
14927
+ }
14928
+ return updatedContent;
14929
+ }
14930
+ function applyDisabledTools(content, toolNames) {
14931
+ let updatedContent = content;
14932
+ for (const name of toolNames) {
14933
+ const edits = modify(updatedContent, ["tools", name], false, JSONC_OPTIONS);
14934
+ updatedContent = applyEdits(updatedContent, edits);
14935
+ }
14936
+ return updatedContent;
14937
+ }
14938
+ function applyAgentToolEnables(content, bindings) {
14939
+ let updatedContent = content;
14940
+ const agentsConfigured = [];
14941
+ for (const binding of bindings) {
14942
+ for (const serverName of binding.serverNames) {
14943
+ const toolPattern = `${serverName}_*`;
14944
+ const edits = modify(updatedContent, ["agent", binding.agentName, "tools", toolPattern], true, JSONC_OPTIONS);
14945
+ updatedContent = applyEdits(updatedContent, edits);
14946
+ }
14947
+ if (binding.serverNames.length > 0) {
14948
+ agentsConfigured.push(binding.agentName);
14949
+ }
14950
+ }
14951
+ return { content: updatedContent, agentsConfigured: [...new Set(agentsConfigured)] };
14952
+ }
14953
+ function applyDefaultAgent(content, config2, defaultAgent) {
14954
+ if (config2.default_agent) {
14955
+ return content;
14956
+ }
14957
+ const edits = modify(content, ["default_agent"], defaultAgent, JSONC_OPTIONS);
14958
+ return applyEdits(content, edits);
14959
+ }
14960
+ function applyPlugins(content, config2, plugins) {
14961
+ const added = [];
14962
+ let updatedContent = content;
14963
+ const existingPlugins = config2.plugin ?? [];
14964
+ for (const plugin of plugins) {
14965
+ if (existingPlugins.includes(plugin)) {
14966
+ continue;
14967
+ }
14968
+ const newIndex = existingPlugins.length + added.length;
14969
+ const edits = modify(updatedContent, ["plugin", newIndex], plugin, JSONC_OPTIONS);
14970
+ updatedContent = applyEdits(updatedContent, edits);
14971
+ added.push(plugin);
14972
+ }
14973
+ return { content: updatedContent, added };
14974
+ }
14975
+ function applyAgentConfigs(content, existingConfig, agentConfigs) {
14976
+ let updatedContent = content;
14977
+ const agentsConfigured = [];
14978
+ for (const [agentName, componentAgentConfig] of Object.entries(agentConfigs)) {
14979
+ const existingAgentConfig = existingConfig.agent?.[agentName] ?? {};
14980
+ const merged = n2(componentAgentConfig, existingAgentConfig);
14981
+ if (merged.tools) {
14982
+ for (const [toolPattern, enabled] of Object.entries(merged.tools)) {
14983
+ const edits = modify(updatedContent, ["agent", agentName, "tools", toolPattern], enabled, JSONC_OPTIONS);
14984
+ updatedContent = applyEdits(updatedContent, edits);
14985
+ }
14986
+ }
14987
+ if (merged.temperature !== undefined) {
14988
+ const edits = modify(updatedContent, ["agent", agentName, "temperature"], merged.temperature, JSONC_OPTIONS);
14989
+ updatedContent = applyEdits(updatedContent, edits);
14990
+ }
14991
+ if (merged.prompt) {
14992
+ const edits = modify(updatedContent, ["agent", agentName, "prompt"], merged.prompt, JSONC_OPTIONS);
14993
+ updatedContent = applyEdits(updatedContent, edits);
14994
+ }
14995
+ if (merged.permission) {
14996
+ for (const [pattern, permission] of Object.entries(merged.permission)) {
14997
+ const edits = modify(updatedContent, ["agent", agentName, "permission", pattern], permission, JSONC_OPTIONS);
14998
+ updatedContent = applyEdits(updatedContent, edits);
14999
+ }
15000
+ }
15001
+ agentsConfigured.push(agentName);
15002
+ }
15003
+ return { content: updatedContent, agentsConfigured };
15004
+ }
15005
+ function applyInstructions(content, config2, instructions) {
15006
+ const added = [];
15007
+ let updatedContent = content;
15008
+ const existingInstructions = config2.instructions ?? [];
15009
+ for (const instruction of instructions) {
15010
+ if (existingInstructions.includes(instruction)) {
15011
+ continue;
15012
+ }
15013
+ const newIndex = existingInstructions.length + added.length;
15014
+ const edits = modify(updatedContent, ["instructions", newIndex], instruction, JSONC_OPTIONS);
15015
+ updatedContent = applyEdits(updatedContent, edits);
15016
+ added.push(instruction);
15017
+ }
15018
+ return { content: updatedContent, added };
15019
+ }
15020
+ async function updateOpencodeConfig(cwd, options2) {
15021
+ const existing = await readOpencodeConfig(cwd);
15022
+ let content;
15023
+ let config2;
15024
+ let configPath;
15025
+ let created = false;
15026
+ if (existing) {
15027
+ content = existing.content;
15028
+ config2 = existing.config;
15029
+ configPath = existing.path;
15030
+ } else {
15031
+ config2 = { $schema: "https://opencode.ai/config.json" };
15032
+ content = JSON.stringify(config2, null, "\t");
15033
+ configPath = `${cwd}/opencode.json`;
15034
+ created = true;
15035
+ }
15036
+ let mcpAdded = [];
15037
+ let mcpSkipped = [];
15038
+ let agentsConfigured = [];
15039
+ let toolsDisabled = [];
15040
+ let pluginsAdded = [];
15041
+ let instructionsAdded = [];
15042
+ if (options2.mcpServers && Object.keys(options2.mcpServers).length > 0) {
15043
+ const result = applyMcpServers(content, config2, options2.mcpServers);
15044
+ content = result.content;
15045
+ mcpAdded = result.added;
15046
+ mcpSkipped = result.skipped;
15047
+ }
15048
+ if (options2.agentMcpBindings && options2.agentMcpBindings.length > 0) {
15049
+ const allScopedServers = [...new Set(options2.agentMcpBindings.flatMap((b2) => b2.serverNames))];
15050
+ if (allScopedServers.length > 0) {
15051
+ content = applyGlobalToolDisables(content, allScopedServers);
15052
+ const agentResult = applyAgentToolEnables(content, options2.agentMcpBindings);
15053
+ content = agentResult.content;
15054
+ agentsConfigured = agentResult.agentsConfigured;
15055
+ }
15056
+ }
15057
+ if (options2.defaultAgent) {
15058
+ const updatedConfig = parse2(content, [], { allowTrailingComma: true });
15059
+ content = applyDefaultAgent(content, updatedConfig, options2.defaultAgent);
15060
+ }
15061
+ if (options2.disabledTools && options2.disabledTools.length > 0) {
15062
+ content = applyDisabledTools(content, options2.disabledTools);
15063
+ toolsDisabled = options2.disabledTools;
15064
+ }
15065
+ if (options2.plugins && options2.plugins.length > 0) {
15066
+ const updatedConfig = parse2(content, [], { allowTrailingComma: true });
15067
+ const result = applyPlugins(content, updatedConfig, options2.plugins);
15068
+ content = result.content;
15069
+ pluginsAdded = result.added;
15070
+ }
15071
+ if (options2.agentConfigs && Object.keys(options2.agentConfigs).length > 0) {
15072
+ const updatedConfig = parse2(content, [], { allowTrailingComma: true });
15073
+ const result = applyAgentConfigs(content, updatedConfig, options2.agentConfigs);
15074
+ content = result.content;
15075
+ agentsConfigured = [...new Set([...agentsConfigured, ...result.agentsConfigured])];
15076
+ }
15077
+ if (options2.instructions && options2.instructions.length > 0) {
15078
+ const updatedConfig = parse2(content, [], { allowTrailingComma: true });
15079
+ const result = applyInstructions(content, updatedConfig, options2.instructions);
15080
+ content = result.content;
15081
+ instructionsAdded = result.added;
15082
+ }
15083
+ await writeOpencodeConfig(configPath, content);
15084
+ return {
15085
+ path: configPath,
15086
+ created,
15087
+ mcpAdded,
15088
+ mcpSkipped,
15089
+ agentsConfigured,
15090
+ toolsDisabled,
15091
+ pluginsAdded,
15092
+ instructionsAdded
15093
+ };
15094
+ }
15095
+
14277
15096
  // src/utils/env.ts
14278
15097
  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
15098
  var isTTY = Boolean(process.stdout.isTTY && !isCI);
@@ -15863,9 +16682,19 @@ async function runAdd(componentNames, options3) {
15863
16682
  };
15864
16683
  }
15865
16684
  installSpin?.succeed(`Installed ${resolved.components.length} components`);
15866
- if (Object.keys(resolved.mcpServers).length > 0) {
16685
+ const hasMcpChanges = Object.keys(resolved.mcpServers).length > 0 || resolved.agentMcpBindings.length > 0;
16686
+ const hasDisabledTools = resolved.disabledTools.length > 0;
16687
+ const hasPlugins = resolved.plugins.length > 0;
16688
+ const hasAgentConfigs = Object.keys(resolved.agentConfigs).length > 0;
16689
+ const hasInstructions = resolved.instructions.length > 0;
16690
+ if (hasMcpChanges || hasDisabledTools || hasPlugins || hasAgentConfigs || hasInstructions) {
15867
16691
  const result = await updateOpencodeConfig(cwd, {
15868
- mcpServers: resolved.mcpServers
16692
+ mcpServers: resolved.mcpServers,
16693
+ agentMcpBindings: resolved.agentMcpBindings,
16694
+ disabledTools: resolved.disabledTools,
16695
+ plugins: resolved.plugins,
16696
+ agentConfigs: resolved.agentConfigs,
16697
+ instructions: resolved.instructions
15869
16698
  });
15870
16699
  if (result.mcpSkipped.length > 0 && !options3.quiet) {
15871
16700
  for (const name of result.mcpSkipped) {
@@ -15874,6 +16703,21 @@ async function runAdd(componentNames, options3) {
15874
16703
  }
15875
16704
  if (!options3.quiet && result.mcpAdded.length > 0) {
15876
16705
  logger.info(`Configured ${result.mcpAdded.length} MCP servers`);
16706
+ for (const binding of resolved.agentMcpBindings) {
16707
+ logger.info(` Scoped to agent "${binding.agentName}": ${binding.serverNames.join(", ")}`);
16708
+ }
16709
+ }
16710
+ if (!options3.quiet && result.toolsDisabled.length > 0) {
16711
+ logger.info(`Disabled ${result.toolsDisabled.length} tools: ${result.toolsDisabled.join(", ")}`);
16712
+ }
16713
+ if (!options3.quiet && result.pluginsAdded.length > 0) {
16714
+ logger.info(`Added ${result.pluginsAdded.length} plugins: ${result.pluginsAdded.join(", ")}`);
16715
+ }
16716
+ if (!options3.quiet && result.agentsConfigured.length > 0) {
16717
+ logger.info(`Configured ${result.agentsConfigured.length} agents: ${result.agentsConfigured.join(", ")}`);
16718
+ }
16719
+ if (!options3.quiet && result.instructionsAdded.length > 0) {
16720
+ logger.info(`Added ${result.instructionsAdded.length} instructions`);
15877
16721
  }
15878
16722
  }
15879
16723
  const hasNpmDeps = resolved.npmDependencies.length > 0;
@@ -15920,7 +16764,8 @@ async function installComponent(component, files, cwd) {
15920
16764
  }
15921
16765
  }
15922
16766
  function getTargetPath(component) {
15923
- return component.files[0]?.target ?? `.opencode/${component.type}/${component.name}`;
16767
+ const typeDir = component.type.replace(/^ocx:/, "");
16768
+ return component.files[0]?.target ?? `.opencode/${typeDir}/${component.name}`;
15924
16769
  }
15925
16770
  async function hashContent(content) {
15926
16771
  return createHash("sha256").update(content).digest("hex");
@@ -16003,7 +16848,7 @@ function registerBuildCommand(program2) {
16003
16848
  if (!parseResult.success) {
16004
16849
  if (!options3.json) {
16005
16850
  spinner2.fail("Registry validation failed");
16006
- const errors3 = parseResult.error.errors.map((e2) => ` ${e2.path.join(".")}: ${e2.message}`);
16851
+ const errors3 = parseResult.error.errors.map((e4) => ` ${e4.path.join(".")}: ${e4.message}`);
16007
16852
  for (const err of errors3) {
16008
16853
  console.log(kleur_default.red(err));
16009
16854
  }
@@ -16026,7 +16871,8 @@ function registerBuildCommand(program2) {
16026
16871
  };
16027
16872
  const packumentPath = join3(componentsDir, `${component.name}.json`);
16028
16873
  await Bun.write(packumentPath, JSON.stringify(packument, null, 2));
16029
- for (const file of component.files) {
16874
+ for (const rawFile of component.files) {
16875
+ const file = normalizeFile(rawFile);
16030
16876
  const sourceFilePath = join3(sourcePath, "files", file.path);
16031
16877
  const destFilePath = join3(componentsDir, component.name, file.path);
16032
16878
  const destFileDir = dirname3(destFilePath);
@@ -16932,11 +17778,12 @@ function registerDiffCommand(program2) {
16932
17778
  }
16933
17779
  try {
16934
17780
  const upstream = await fetchComponent(registryConfig.url, name);
16935
- const upstreamFile = upstream.files[0];
16936
- if (!upstreamFile) {
17781
+ const rawUpstreamFile = upstream.files[0];
17782
+ if (!rawUpstreamFile) {
16937
17783
  results.push({ name, hasChanges: false });
16938
17784
  continue;
16939
17785
  }
17786
+ const upstreamFile = normalizeFile(rawUpstreamFile);
16940
17787
  const upstreamContent = await fetchFileContent(registryConfig.url, name, upstreamFile.path);
16941
17788
  if (localContent === upstreamContent) {
16942
17789
  results.push({ name, hasChanges: false });
@@ -17206,7 +18053,7 @@ function registerSearchCommand(program2) {
17206
18053
  keys: ["name", "description"],
17207
18054
  limit
17208
18055
  });
17209
- results = fuzzyResults.map((r2) => r2.obj);
18056
+ results = fuzzyResults.map((r3) => r3.obj);
17210
18057
  } else {
17211
18058
  results = results.slice(0, limit);
17212
18059
  }
@@ -17229,7 +18076,7 @@ function registerSearchCommand(program2) {
17229
18076
  }
17230
18077
 
17231
18078
  // src/index.ts
17232
- var version2 = "1.0.5";
18079
+ var version2 = "1.0.7";
17233
18080
  async function main2() {
17234
18081
  const program2 = new Command().name("ocx").description("OpenCode Extensions - Install agents, skills, plugins, and commands").version(version2);
17235
18082
  registerInitCommand(program2);
@@ -17244,4 +18091,4 @@ main2().catch((err) => {
17244
18091
  handleError(err);
17245
18092
  });
17246
18093
 
17247
- //# debugId=D94D02DC5FA0777E64756E2164756E21
18094
+ //# debugId=787522CA1BFEEB9464756E2164756E21