ocx 1.0.7 → 1.0.8
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 +175 -112
- package/dist/index.js.map +10 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -13026,9 +13026,102 @@ var coerce = {
|
|
|
13026
13026
|
date: (arg) => ZodDate.create({ ...arg, coerce: true })
|
|
13027
13027
|
};
|
|
13028
13028
|
var NEVER = INVALID;
|
|
13029
|
+
// src/utils/errors.ts
|
|
13030
|
+
var EXIT_CODES = {
|
|
13031
|
+
SUCCESS: 0,
|
|
13032
|
+
GENERAL: 1,
|
|
13033
|
+
NOT_FOUND: 66,
|
|
13034
|
+
NETWORK: 69,
|
|
13035
|
+
CONFIG: 78,
|
|
13036
|
+
INTEGRITY: 1
|
|
13037
|
+
};
|
|
13038
|
+
|
|
13039
|
+
class OCXError extends Error {
|
|
13040
|
+
code;
|
|
13041
|
+
exitCode;
|
|
13042
|
+
constructor(message, code, exitCode = EXIT_CODES.GENERAL) {
|
|
13043
|
+
super(message);
|
|
13044
|
+
this.code = code;
|
|
13045
|
+
this.exitCode = exitCode;
|
|
13046
|
+
this.name = "OCXError";
|
|
13047
|
+
}
|
|
13048
|
+
}
|
|
13049
|
+
|
|
13050
|
+
class NotFoundError extends OCXError {
|
|
13051
|
+
constructor(message) {
|
|
13052
|
+
super(message, "NOT_FOUND", EXIT_CODES.NOT_FOUND);
|
|
13053
|
+
this.name = "NotFoundError";
|
|
13054
|
+
}
|
|
13055
|
+
}
|
|
13056
|
+
|
|
13057
|
+
class NetworkError extends OCXError {
|
|
13058
|
+
constructor(message) {
|
|
13059
|
+
super(message, "NETWORK_ERROR", EXIT_CODES.NETWORK);
|
|
13060
|
+
this.name = "NetworkError";
|
|
13061
|
+
}
|
|
13062
|
+
}
|
|
13063
|
+
|
|
13064
|
+
class ConfigError extends OCXError {
|
|
13065
|
+
constructor(message) {
|
|
13066
|
+
super(message, "CONFIG_ERROR", EXIT_CODES.CONFIG);
|
|
13067
|
+
this.name = "ConfigError";
|
|
13068
|
+
}
|
|
13069
|
+
}
|
|
13070
|
+
|
|
13071
|
+
class ValidationError extends OCXError {
|
|
13072
|
+
constructor(message) {
|
|
13073
|
+
super(message, "VALIDATION_ERROR", EXIT_CODES.GENERAL);
|
|
13074
|
+
this.name = "ValidationError";
|
|
13075
|
+
}
|
|
13076
|
+
}
|
|
13077
|
+
|
|
13078
|
+
class ConflictError extends OCXError {
|
|
13079
|
+
constructor(message) {
|
|
13080
|
+
super(message, "CONFLICT", EXIT_CODES.GENERAL);
|
|
13081
|
+
this.name = "ConflictError";
|
|
13082
|
+
}
|
|
13083
|
+
}
|
|
13084
|
+
|
|
13085
|
+
class IntegrityError extends OCXError {
|
|
13086
|
+
constructor(component, expected, found) {
|
|
13087
|
+
const message = `Integrity verification failed for "${component}"
|
|
13088
|
+
` + ` Expected: ${expected}
|
|
13089
|
+
` + ` Found: ${found}
|
|
13090
|
+
|
|
13091
|
+
` + `The registry content has changed since this component was locked.
|
|
13092
|
+
` + `This could indicate tampering or an unauthorized update.`;
|
|
13093
|
+
super(message, "INTEGRITY_ERROR", EXIT_CODES.INTEGRITY);
|
|
13094
|
+
this.name = "IntegrityError";
|
|
13095
|
+
}
|
|
13096
|
+
}
|
|
13097
|
+
|
|
13029
13098
|
// src/schemas/registry.ts
|
|
13030
13099
|
var openCodeNameSchema = exports_external.string().min(1, "Name cannot be empty").max(64, "Name cannot exceed 64 characters").regex(/^[a-z0-9]+(-[a-z0-9]+)*$/, {
|
|
13031
|
-
message: "Must be lowercase alphanumeric with single hyphen separators (e.g., 'my-component', '
|
|
13100
|
+
message: "Must be lowercase alphanumeric with single hyphen separators (e.g., 'my-component', 'my-plugin'). Cannot start/end with hyphen or have consecutive hyphens."
|
|
13101
|
+
});
|
|
13102
|
+
var namespaceSchema = openCodeNameSchema;
|
|
13103
|
+
var qualifiedComponentSchema = exports_external.string().regex(/^[a-z0-9]+(-[a-z0-9]+)*\/[a-z0-9]+(-[a-z0-9]+)*$/, {
|
|
13104
|
+
message: 'Must be in format "namespace/component" (e.g., "kdco/librarian"). Both parts must be lowercase alphanumeric with hyphens.'
|
|
13105
|
+
});
|
|
13106
|
+
function parseQualifiedComponent(ref) {
|
|
13107
|
+
if (!ref.includes("/")) {
|
|
13108
|
+
throw new ValidationError(`Invalid component reference: "${ref}". Use format: namespace/component`);
|
|
13109
|
+
}
|
|
13110
|
+
const [namespace, component] = ref.split("/");
|
|
13111
|
+
if (!namespace || !component) {
|
|
13112
|
+
throw new ValidationError(`Invalid component reference: "${ref}". Both namespace and component are required.`);
|
|
13113
|
+
}
|
|
13114
|
+
return { namespace, component };
|
|
13115
|
+
}
|
|
13116
|
+
function createQualifiedComponent(namespace, component) {
|
|
13117
|
+
return `${namespace}/${component}`;
|
|
13118
|
+
}
|
|
13119
|
+
var dependencyRefSchema = exports_external.string().refine((dep) => {
|
|
13120
|
+
const barePattern = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
13121
|
+
const qualifiedPattern = /^[a-z0-9]+(-[a-z0-9]+)*\/[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
13122
|
+
return barePattern.test(dep) || qualifiedPattern.test(dep);
|
|
13123
|
+
}, {
|
|
13124
|
+
message: 'Dependency must be either a bare name (e.g., "utils") or qualified (e.g., "acme/utils")'
|
|
13032
13125
|
});
|
|
13033
13126
|
var componentTypeSchema = exports_external.enum([
|
|
13034
13127
|
"ocx:agent",
|
|
@@ -13098,7 +13191,7 @@ var componentManifestSchema = exports_external.object({
|
|
|
13098
13191
|
type: componentTypeSchema,
|
|
13099
13192
|
description: exports_external.string().min(1).max(1024),
|
|
13100
13193
|
files: exports_external.array(componentFileSchema),
|
|
13101
|
-
dependencies: exports_external.array(
|
|
13194
|
+
dependencies: exports_external.array(dependencyRefSchema).default([]),
|
|
13102
13195
|
npmDependencies: exports_external.array(exports_external.string()).optional(),
|
|
13103
13196
|
npmDevDependencies: exports_external.array(exports_external.string()).optional(),
|
|
13104
13197
|
mcpServers: exports_external.record(mcpServerSchema).optional(),
|
|
@@ -13141,28 +13234,24 @@ function normalizeComponentManifest(manifest) {
|
|
|
13141
13234
|
var semverRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/;
|
|
13142
13235
|
var registrySchema = exports_external.object({
|
|
13143
13236
|
name: exports_external.string().min(1, "Registry name cannot be empty"),
|
|
13144
|
-
|
|
13237
|
+
namespace: namespaceSchema,
|
|
13145
13238
|
version: exports_external.string().regex(semverRegex, {
|
|
13146
13239
|
message: "Version must be valid semver (e.g., '1.0.0', '2.1.0-beta.1')"
|
|
13147
13240
|
}),
|
|
13148
13241
|
author: exports_external.string().min(1, "Author cannot be empty"),
|
|
13149
13242
|
components: exports_external.array(componentManifestSchema)
|
|
13150
|
-
}).refine((data) => {
|
|
13151
|
-
return data.components.every((c2) => c2.name.startsWith(`${data.prefix}-`));
|
|
13152
|
-
}, {
|
|
13153
|
-
message: "All component names must start with the registry prefix"
|
|
13154
13243
|
}).refine((data) => {
|
|
13155
13244
|
const componentNames = new Set(data.components.map((c2) => c2.name));
|
|
13156
13245
|
for (const component of data.components) {
|
|
13157
13246
|
for (const dep of component.dependencies) {
|
|
13158
|
-
if (!componentNames.has(dep)) {
|
|
13247
|
+
if (!dep.includes("/") && !componentNames.has(dep)) {
|
|
13159
13248
|
return false;
|
|
13160
13249
|
}
|
|
13161
13250
|
}
|
|
13162
13251
|
}
|
|
13163
13252
|
return true;
|
|
13164
13253
|
}, {
|
|
13165
|
-
message: "
|
|
13254
|
+
message: "Bare dependencies must reference components that exist in the registry. Use qualified references (e.g., 'other-registry/component') for cross-namespace dependencies."
|
|
13166
13255
|
});
|
|
13167
13256
|
var packumentSchema = exports_external.object({
|
|
13168
13257
|
name: openCodeNameSchema,
|
|
@@ -13173,7 +13262,7 @@ var packumentSchema = exports_external.object({
|
|
|
13173
13262
|
});
|
|
13174
13263
|
var registryIndexSchema = exports_external.object({
|
|
13175
13264
|
name: exports_external.string(),
|
|
13176
|
-
|
|
13265
|
+
namespace: namespaceSchema,
|
|
13177
13266
|
version: exports_external.string(),
|
|
13178
13267
|
author: exports_external.string(),
|
|
13179
13268
|
components: exports_external.array(exports_external.object({
|
|
@@ -13183,67 +13272,6 @@ var registryIndexSchema = exports_external.object({
|
|
|
13183
13272
|
}))
|
|
13184
13273
|
});
|
|
13185
13274
|
|
|
13186
|
-
// src/utils/errors.ts
|
|
13187
|
-
var EXIT_CODES = {
|
|
13188
|
-
SUCCESS: 0,
|
|
13189
|
-
GENERAL: 1,
|
|
13190
|
-
NOT_FOUND: 66,
|
|
13191
|
-
NETWORK: 69,
|
|
13192
|
-
CONFIG: 78,
|
|
13193
|
-
INTEGRITY: 1
|
|
13194
|
-
};
|
|
13195
|
-
|
|
13196
|
-
class OCXError extends Error {
|
|
13197
|
-
code;
|
|
13198
|
-
exitCode;
|
|
13199
|
-
constructor(message, code, exitCode = EXIT_CODES.GENERAL) {
|
|
13200
|
-
super(message);
|
|
13201
|
-
this.code = code;
|
|
13202
|
-
this.exitCode = exitCode;
|
|
13203
|
-
this.name = "OCXError";
|
|
13204
|
-
}
|
|
13205
|
-
}
|
|
13206
|
-
|
|
13207
|
-
class NotFoundError extends OCXError {
|
|
13208
|
-
constructor(message) {
|
|
13209
|
-
super(message, "NOT_FOUND", EXIT_CODES.NOT_FOUND);
|
|
13210
|
-
this.name = "NotFoundError";
|
|
13211
|
-
}
|
|
13212
|
-
}
|
|
13213
|
-
|
|
13214
|
-
class NetworkError extends OCXError {
|
|
13215
|
-
constructor(message) {
|
|
13216
|
-
super(message, "NETWORK_ERROR", EXIT_CODES.NETWORK);
|
|
13217
|
-
this.name = "NetworkError";
|
|
13218
|
-
}
|
|
13219
|
-
}
|
|
13220
|
-
|
|
13221
|
-
class ConfigError extends OCXError {
|
|
13222
|
-
constructor(message) {
|
|
13223
|
-
super(message, "CONFIG_ERROR", EXIT_CODES.CONFIG);
|
|
13224
|
-
this.name = "ConfigError";
|
|
13225
|
-
}
|
|
13226
|
-
}
|
|
13227
|
-
|
|
13228
|
-
class ValidationError extends OCXError {
|
|
13229
|
-
constructor(message) {
|
|
13230
|
-
super(message, "VALIDATION_ERROR", EXIT_CODES.GENERAL);
|
|
13231
|
-
this.name = "ValidationError";
|
|
13232
|
-
}
|
|
13233
|
-
}
|
|
13234
|
-
class IntegrityError extends OCXError {
|
|
13235
|
-
constructor(component, expected, found) {
|
|
13236
|
-
const message = `Integrity verification failed for "${component}"
|
|
13237
|
-
` + ` Expected: ${expected}
|
|
13238
|
-
` + ` Found: ${found}
|
|
13239
|
-
|
|
13240
|
-
` + `The registry content has changed since this component was locked.
|
|
13241
|
-
` + `This could indicate tampering or an unauthorized update.`;
|
|
13242
|
-
super(message, "INTEGRITY_ERROR", EXIT_CODES.INTEGRITY);
|
|
13243
|
-
this.name = "IntegrityError";
|
|
13244
|
-
}
|
|
13245
|
-
}
|
|
13246
|
-
|
|
13247
13275
|
// src/registry/fetcher.ts
|
|
13248
13276
|
var cache = new Map;
|
|
13249
13277
|
async function fetchWithCache(url, parse) {
|
|
@@ -13348,6 +13376,15 @@ function r2(e4, n3) {
|
|
|
13348
13376
|
}
|
|
13349
13377
|
|
|
13350
13378
|
// src/registry/resolver.ts
|
|
13379
|
+
function parseComponentRef(ref, defaultNamespace) {
|
|
13380
|
+
if (ref.includes("/")) {
|
|
13381
|
+
return parseQualifiedComponent(ref);
|
|
13382
|
+
}
|
|
13383
|
+
if (defaultNamespace) {
|
|
13384
|
+
return { namespace: defaultNamespace, component: ref };
|
|
13385
|
+
}
|
|
13386
|
+
throw new ValidationError(`Component '${ref}' must include a namespace (e.g., 'kdco/${ref}')`);
|
|
13387
|
+
}
|
|
13351
13388
|
async function resolveDependencies(registries, componentNames) {
|
|
13352
13389
|
const resolved = new Map;
|
|
13353
13390
|
const visiting = new Set;
|
|
@@ -13359,39 +13396,39 @@ async function resolveDependencies(registries, componentNames) {
|
|
|
13359
13396
|
const plugins = new Set;
|
|
13360
13397
|
const agentConfigs = {};
|
|
13361
13398
|
const instructionsSet = new Set;
|
|
13362
|
-
async function resolve2(
|
|
13363
|
-
|
|
13399
|
+
async function resolve2(componentNamespace, componentName, path3 = []) {
|
|
13400
|
+
const qualifiedName = createQualifiedComponent(componentNamespace, componentName);
|
|
13401
|
+
if (resolved.has(qualifiedName)) {
|
|
13364
13402
|
return;
|
|
13365
13403
|
}
|
|
13366
|
-
if (visiting.has(
|
|
13367
|
-
const cycle = [...path3,
|
|
13404
|
+
if (visiting.has(qualifiedName)) {
|
|
13405
|
+
const cycle = [...path3, qualifiedName].join(" \u2192 ");
|
|
13368
13406
|
throw new ValidationError(`Circular dependency detected: ${cycle}`);
|
|
13369
13407
|
}
|
|
13370
|
-
visiting.add(
|
|
13371
|
-
|
|
13372
|
-
|
|
13373
|
-
|
|
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) {}
|
|
13408
|
+
visiting.add(qualifiedName);
|
|
13409
|
+
const regConfig = registries[componentNamespace];
|
|
13410
|
+
if (!regConfig) {
|
|
13411
|
+
throw new ConfigError(`Registry '${componentNamespace}' not configured. Add it to ocx.jsonc registries.`);
|
|
13381
13412
|
}
|
|
13382
|
-
|
|
13383
|
-
|
|
13413
|
+
let component;
|
|
13414
|
+
try {
|
|
13415
|
+
component = await fetchComponent(regConfig.url, componentName);
|
|
13416
|
+
} catch (_err) {
|
|
13417
|
+
throw new OCXError(`Component '${componentName}' not found in registry '${componentNamespace}'.`, "NOT_FOUND");
|
|
13384
13418
|
}
|
|
13385
13419
|
for (const dep of component.dependencies) {
|
|
13386
|
-
|
|
13420
|
+
const depRef = parseComponentRef(dep, componentNamespace);
|
|
13421
|
+
await resolve2(depRef.namespace, depRef.component, [...path3, qualifiedName]);
|
|
13387
13422
|
}
|
|
13388
13423
|
const normalizedComponent = normalizeComponentManifest(component);
|
|
13389
|
-
resolved.set(
|
|
13424
|
+
resolved.set(qualifiedName, {
|
|
13390
13425
|
...normalizedComponent,
|
|
13391
|
-
|
|
13392
|
-
|
|
13426
|
+
namespace: componentNamespace,
|
|
13427
|
+
registryName: componentNamespace,
|
|
13428
|
+
baseUrl: regConfig.url,
|
|
13429
|
+
qualifiedName
|
|
13393
13430
|
});
|
|
13394
|
-
visiting.delete(
|
|
13431
|
+
visiting.delete(qualifiedName);
|
|
13395
13432
|
if (normalizedComponent.mcpServers) {
|
|
13396
13433
|
const serverNames = [];
|
|
13397
13434
|
for (const [serverName, config2] of Object.entries(normalizedComponent.mcpServers)) {
|
|
@@ -13447,7 +13484,8 @@ async function resolveDependencies(registries, componentNames) {
|
|
|
13447
13484
|
}
|
|
13448
13485
|
}
|
|
13449
13486
|
for (const name of componentNames) {
|
|
13450
|
-
|
|
13487
|
+
const ref = parseComponentRef(name);
|
|
13488
|
+
await resolve2(ref.namespace, ref.component);
|
|
13451
13489
|
}
|
|
13452
13490
|
const components = Array.from(resolved.values());
|
|
13453
13491
|
const installOrder = Array.from(resolved.keys());
|
|
@@ -14803,12 +14841,13 @@ var installedComponentSchema = exports_external.object({
|
|
|
14803
14841
|
registry: exports_external.string(),
|
|
14804
14842
|
version: exports_external.string(),
|
|
14805
14843
|
hash: exports_external.string(),
|
|
14806
|
-
|
|
14807
|
-
installedAt: exports_external.string()
|
|
14844
|
+
files: exports_external.array(exports_external.string()),
|
|
14845
|
+
installedAt: exports_external.string(),
|
|
14846
|
+
alias: exports_external.string().optional()
|
|
14808
14847
|
});
|
|
14809
14848
|
var ocxLockSchema = exports_external.object({
|
|
14810
14849
|
lockVersion: exports_external.literal(1),
|
|
14811
|
-
installed: exports_external.record(installedComponentSchema).default({})
|
|
14850
|
+
installed: exports_external.record(qualifiedComponentSchema, installedComponentSchema).default({})
|
|
14812
14851
|
});
|
|
14813
14852
|
var opencodeMcpSchema = exports_external.record(mcpServerSchema);
|
|
14814
14853
|
var opencodeAgentSchema = exports_external.object({
|
|
@@ -16667,17 +16706,31 @@ async function runAdd(componentNames, options3) {
|
|
|
16667
16706
|
files.push({ path: file.path, content: Buffer.from(content) });
|
|
16668
16707
|
}
|
|
16669
16708
|
const computedHash = await hashBundle(files);
|
|
16670
|
-
const existingEntry = lock.installed[component.
|
|
16709
|
+
const existingEntry = lock.installed[component.qualifiedName];
|
|
16671
16710
|
if (existingEntry && existingEntry.hash !== computedHash) {
|
|
16672
|
-
throw new IntegrityError(component.
|
|
16711
|
+
throw new IntegrityError(component.qualifiedName, existingEntry.hash, computedHash);
|
|
16712
|
+
}
|
|
16713
|
+
for (const file of component.files) {
|
|
16714
|
+
const targetPath = join2(cwd, file.target);
|
|
16715
|
+
if (existsSync2(targetPath)) {
|
|
16716
|
+
const conflictingComponent = findComponentByFile(lock, file.target);
|
|
16717
|
+
if (conflictingComponent && conflictingComponent !== component.qualifiedName) {
|
|
16718
|
+
throw new ConflictError(`File conflict: ${file.target} already exists (installed by '${conflictingComponent}').
|
|
16719
|
+
|
|
16720
|
+
` + `To resolve:
|
|
16721
|
+
` + ` 1. Remove existing: rm ${file.target}
|
|
16722
|
+
` + ` 2. Or rename it manually and update references
|
|
16723
|
+
` + ` 3. Then run: ocx add ${component.qualifiedName}`);
|
|
16724
|
+
}
|
|
16725
|
+
}
|
|
16673
16726
|
}
|
|
16674
16727
|
await installComponent(component, files, cwd);
|
|
16675
16728
|
const index = await fetchRegistryIndex(component.baseUrl);
|
|
16676
|
-
lock.installed[component.
|
|
16729
|
+
lock.installed[component.qualifiedName] = {
|
|
16677
16730
|
registry: component.registryName,
|
|
16678
16731
|
version: index.version,
|
|
16679
16732
|
hash: computedHash,
|
|
16680
|
-
|
|
16733
|
+
files: component.files.map((f2) => f2.target),
|
|
16681
16734
|
installedAt: new Date().toISOString()
|
|
16682
16735
|
};
|
|
16683
16736
|
}
|
|
@@ -16763,10 +16816,6 @@ async function installComponent(component, files, cwd) {
|
|
|
16763
16816
|
await writeFile(targetPath, file.content);
|
|
16764
16817
|
}
|
|
16765
16818
|
}
|
|
16766
|
-
function getTargetPath(component) {
|
|
16767
|
-
const typeDir = component.type.replace(/^ocx:/, "");
|
|
16768
|
-
return component.files[0]?.target ?? `.opencode/${typeDir}/${component.name}`;
|
|
16769
|
-
}
|
|
16770
16819
|
async function hashContent(content) {
|
|
16771
16820
|
return createHash("sha256").update(content).digest("hex");
|
|
16772
16821
|
}
|
|
@@ -16822,6 +16871,14 @@ async function installNpmDependencies(dependencies, devDependencies, cwd, option
|
|
|
16822
16871
|
await run(parseNi, [...devDependencies, "-D"], { cwd });
|
|
16823
16872
|
}
|
|
16824
16873
|
}
|
|
16874
|
+
function findComponentByFile(lock, filePath) {
|
|
16875
|
+
for (const [qualifiedName, entry] of Object.entries(lock.installed)) {
|
|
16876
|
+
if (entry.files.includes(filePath)) {
|
|
16877
|
+
return qualifiedName;
|
|
16878
|
+
}
|
|
16879
|
+
}
|
|
16880
|
+
return null;
|
|
16881
|
+
}
|
|
16825
16882
|
|
|
16826
16883
|
// src/commands/build.ts
|
|
16827
16884
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
@@ -16896,7 +16953,7 @@ function registerBuildCommand(program2) {
|
|
|
16896
16953
|
}
|
|
16897
16954
|
const index = {
|
|
16898
16955
|
name: registry.name,
|
|
16899
|
-
|
|
16956
|
+
namespace: registry.namespace,
|
|
16900
16957
|
version: registry.version,
|
|
16901
16958
|
author: registry.author,
|
|
16902
16959
|
components: registry.components.map((c2) => ({
|
|
@@ -17764,7 +17821,11 @@ function registerDiffCommand(program2) {
|
|
|
17764
17821
|
}
|
|
17765
17822
|
continue;
|
|
17766
17823
|
}
|
|
17767
|
-
|
|
17824
|
+
if (!installed.files || installed.files.length === 0) {
|
|
17825
|
+
logger.warn(`No files recorded for component '${name}'`);
|
|
17826
|
+
continue;
|
|
17827
|
+
}
|
|
17828
|
+
const localPath = `${options3.cwd}/${installed.files[0]}`;
|
|
17768
17829
|
const localFile = Bun.file(localPath);
|
|
17769
17830
|
if (!await localFile.exists()) {
|
|
17770
17831
|
results.push({ name, hasChanges: true, diff: "Local file missing" });
|
|
@@ -17777,14 +17838,16 @@ function registerDiffCommand(program2) {
|
|
|
17777
17838
|
continue;
|
|
17778
17839
|
}
|
|
17779
17840
|
try {
|
|
17780
|
-
const
|
|
17841
|
+
const parsed = parseQualifiedComponent(name);
|
|
17842
|
+
const componentName = parsed.component;
|
|
17843
|
+
const upstream = await fetchComponent(registryConfig.url, componentName);
|
|
17781
17844
|
const rawUpstreamFile = upstream.files[0];
|
|
17782
17845
|
if (!rawUpstreamFile) {
|
|
17783
17846
|
results.push({ name, hasChanges: false });
|
|
17784
17847
|
continue;
|
|
17785
17848
|
}
|
|
17786
17849
|
const upstreamFile = normalizeFile(rawUpstreamFile);
|
|
17787
|
-
const upstreamContent = await fetchFileContent(registryConfig.url,
|
|
17850
|
+
const upstreamContent = await fetchFileContent(registryConfig.url, componentName, upstreamFile.path);
|
|
17788
17851
|
if (localContent === upstreamContent) {
|
|
17789
17852
|
results.push({ name, hasChanges: false });
|
|
17790
17853
|
} else {
|
|
@@ -18032,7 +18095,7 @@ function registerSearchCommand(program2) {
|
|
|
18032
18095
|
}
|
|
18033
18096
|
for (const comp of index.components) {
|
|
18034
18097
|
allComponents.push({
|
|
18035
|
-
name: comp.name
|
|
18098
|
+
name: `${index.namespace}/${comp.name}`,
|
|
18036
18099
|
description: comp.description,
|
|
18037
18100
|
type: comp.type,
|
|
18038
18101
|
registry: registryName
|
|
@@ -18076,7 +18139,7 @@ function registerSearchCommand(program2) {
|
|
|
18076
18139
|
}
|
|
18077
18140
|
|
|
18078
18141
|
// src/index.ts
|
|
18079
|
-
var version2 = "1.0.
|
|
18142
|
+
var version2 = "1.0.8";
|
|
18080
18143
|
async function main2() {
|
|
18081
18144
|
const program2 = new Command().name("ocx").description("OpenCode Extensions - Install agents, skills, plugins, and commands").version(version2);
|
|
18082
18145
|
registerInitCommand(program2);
|
|
@@ -18091,4 +18154,4 @@ main2().catch((err) => {
|
|
|
18091
18154
|
handleError(err);
|
|
18092
18155
|
});
|
|
18093
18156
|
|
|
18094
|
-
//# debugId=
|
|
18157
|
+
//# debugId=4504091B3609ACE764756E2164756E21
|