@jarel/myskills 0.1.0-beta.19 → 0.1.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -4
- package/dist/index.js +845 -583
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -269,10 +269,10 @@ function mergeDefs(...defs) {
|
|
|
269
269
|
function cloneDef(schema) {
|
|
270
270
|
return mergeDefs(schema._zod.def);
|
|
271
271
|
}
|
|
272
|
-
function getElementAtPath(obj,
|
|
273
|
-
if (!
|
|
272
|
+
function getElementAtPath(obj, path19) {
|
|
273
|
+
if (!path19)
|
|
274
274
|
return obj;
|
|
275
|
-
return
|
|
275
|
+
return path19.reduce((acc, key) => acc?.[key], obj);
|
|
276
276
|
}
|
|
277
277
|
function promiseAllObject(promisesObj) {
|
|
278
278
|
const keys = Object.keys(promisesObj);
|
|
@@ -531,11 +531,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
531
531
|
}
|
|
532
532
|
return false;
|
|
533
533
|
}
|
|
534
|
-
function prefixIssues(
|
|
534
|
+
function prefixIssues(path19, issues) {
|
|
535
535
|
return issues.map((iss) => {
|
|
536
536
|
var _a3;
|
|
537
537
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
538
|
-
iss.path.unshift(
|
|
538
|
+
iss.path.unshift(path19);
|
|
539
539
|
return iss;
|
|
540
540
|
});
|
|
541
541
|
}
|
|
@@ -1056,16 +1056,16 @@ function flattenError(error62, mapper = (issue4) => issue4.message) {
|
|
|
1056
1056
|
}
|
|
1057
1057
|
function formatError(error62, mapper = (issue4) => issue4.message) {
|
|
1058
1058
|
const fieldErrors = { _errors: [] };
|
|
1059
|
-
const processError = (error63,
|
|
1059
|
+
const processError = (error63, path19 = []) => {
|
|
1060
1060
|
for (const issue4 of error63.issues) {
|
|
1061
1061
|
if (issue4.code === "invalid_union" && issue4.errors.length) {
|
|
1062
|
-
issue4.errors.map((issues) => processError({ issues }, [...
|
|
1062
|
+
issue4.errors.map((issues) => processError({ issues }, [...path19, ...issue4.path]));
|
|
1063
1063
|
} else if (issue4.code === "invalid_key") {
|
|
1064
|
-
processError({ issues: issue4.issues }, [...
|
|
1064
|
+
processError({ issues: issue4.issues }, [...path19, ...issue4.path]);
|
|
1065
1065
|
} else if (issue4.code === "invalid_element") {
|
|
1066
|
-
processError({ issues: issue4.issues }, [...
|
|
1066
|
+
processError({ issues: issue4.issues }, [...path19, ...issue4.path]);
|
|
1067
1067
|
} else {
|
|
1068
|
-
const fullpath = [...
|
|
1068
|
+
const fullpath = [...path19, ...issue4.path];
|
|
1069
1069
|
if (fullpath.length === 0) {
|
|
1070
1070
|
fieldErrors._errors.push(mapper(issue4));
|
|
1071
1071
|
} else {
|
|
@@ -1104,17 +1104,17 @@ function formatError(error62, mapper = (issue4) => issue4.message) {
|
|
|
1104
1104
|
}
|
|
1105
1105
|
function treeifyError(error62, mapper = (issue4) => issue4.message) {
|
|
1106
1106
|
const result = { errors: [] };
|
|
1107
|
-
const processError = (error63,
|
|
1107
|
+
const processError = (error63, path19 = []) => {
|
|
1108
1108
|
var _a3;
|
|
1109
1109
|
for (const issue4 of error63.issues) {
|
|
1110
1110
|
if (issue4.code === "invalid_union" && issue4.errors.length) {
|
|
1111
|
-
issue4.errors.map((issues) => processError({ issues }, [...
|
|
1111
|
+
issue4.errors.map((issues) => processError({ issues }, [...path19, ...issue4.path]));
|
|
1112
1112
|
} else if (issue4.code === "invalid_key") {
|
|
1113
|
-
processError({ issues: issue4.issues }, [...
|
|
1113
|
+
processError({ issues: issue4.issues }, [...path19, ...issue4.path]);
|
|
1114
1114
|
} else if (issue4.code === "invalid_element") {
|
|
1115
|
-
processError({ issues: issue4.issues }, [...
|
|
1115
|
+
processError({ issues: issue4.issues }, [...path19, ...issue4.path]);
|
|
1116
1116
|
} else {
|
|
1117
|
-
const fullpath = [...
|
|
1117
|
+
const fullpath = [...path19, ...issue4.path];
|
|
1118
1118
|
if (fullpath.length === 0) {
|
|
1119
1119
|
result.errors.push(mapper(issue4));
|
|
1120
1120
|
continue;
|
|
@@ -1153,8 +1153,8 @@ function treeifyError(error62, mapper = (issue4) => issue4.message) {
|
|
|
1153
1153
|
}
|
|
1154
1154
|
function toDotPath(_path) {
|
|
1155
1155
|
const segs = [];
|
|
1156
|
-
const
|
|
1157
|
-
for (const seg of
|
|
1156
|
+
const path19 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
1157
|
+
for (const seg of path19) {
|
|
1158
1158
|
if (typeof seg === "number")
|
|
1159
1159
|
segs.push(`[${seg}]`);
|
|
1160
1160
|
else if (typeof seg === "symbol")
|
|
@@ -19150,13 +19150,13 @@ function resolveRef(ref, ctx) {
|
|
|
19150
19150
|
if (!ref.startsWith("#")) {
|
|
19151
19151
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
19152
19152
|
}
|
|
19153
|
-
const
|
|
19154
|
-
if (
|
|
19153
|
+
const path19 = ref.slice(1).split("/").filter(Boolean);
|
|
19154
|
+
if (path19.length === 0) {
|
|
19155
19155
|
return ctx.rootSchema;
|
|
19156
19156
|
}
|
|
19157
19157
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
19158
|
-
if (
|
|
19159
|
-
const key =
|
|
19158
|
+
if (path19[0] === defsKey) {
|
|
19159
|
+
const key = path19[1] === void 0 ? void 0 : decodeJSONPointerSegment(path19[1]);
|
|
19160
19160
|
if (!key || !ctx.defs[key]) {
|
|
19161
19161
|
throw new Error(`Reference not found: ${ref}`);
|
|
19162
19162
|
}
|
|
@@ -21082,27 +21082,27 @@ function unknownKeys(value, allowed) {
|
|
|
21082
21082
|
const allowedSet = new Set(allowed);
|
|
21083
21083
|
return Object.keys(value).filter((key) => !allowedSet.has(key)).sort();
|
|
21084
21084
|
}
|
|
21085
|
-
function issue2(errors, code, message,
|
|
21086
|
-
errors.push(
|
|
21085
|
+
function issue2(errors, code, message, path19) {
|
|
21086
|
+
errors.push(path19 ? { code, message, path: path19 } : { code, message });
|
|
21087
21087
|
}
|
|
21088
|
-
function checkUnknownKeys(value, allowed,
|
|
21088
|
+
function checkUnknownKeys(value, allowed, path19, errors) {
|
|
21089
21089
|
for (const key of unknownKeys(value, allowed)) {
|
|
21090
|
-
issue2(errors, "ARCHITECTURE_TARGET_UNKNOWN_FIELD", `Field '${key}' is not accepted.`, `${
|
|
21090
|
+
issue2(errors, "ARCHITECTURE_TARGET_UNKNOWN_FIELD", `Field '${key}' is not accepted.`, `${path19}.${key}`);
|
|
21091
21091
|
}
|
|
21092
21092
|
}
|
|
21093
|
-
function checkSensitiveKeys(value,
|
|
21093
|
+
function checkSensitiveKeys(value, path19, errors) {
|
|
21094
21094
|
if (Array.isArray(value)) {
|
|
21095
21095
|
for (const [index, item] of value.entries())
|
|
21096
|
-
checkSensitiveKeys(item, `${
|
|
21096
|
+
checkSensitiveKeys(item, `${path19}[${index}]`, errors);
|
|
21097
21097
|
return;
|
|
21098
21098
|
}
|
|
21099
21099
|
if (!isRecord2(value))
|
|
21100
21100
|
return;
|
|
21101
21101
|
for (const [key, item] of Object.entries(value)) {
|
|
21102
21102
|
if (isSensitiveMetadataKey(key) && !safeKnownKeys.has(key)) {
|
|
21103
|
-
issue2(errors, "ARCHITECTURE_TARGET_SENSITIVE_FIELD", `Field '${key}' is not permitted in metadata-only target records.`, `${
|
|
21103
|
+
issue2(errors, "ARCHITECTURE_TARGET_SENSITIVE_FIELD", `Field '${key}' is not permitted in metadata-only target records.`, `${path19}.${key}`);
|
|
21104
21104
|
}
|
|
21105
|
-
checkSensitiveKeys(item, `${
|
|
21105
|
+
checkSensitiveKeys(item, `${path19}.${key}`, errors);
|
|
21106
21106
|
}
|
|
21107
21107
|
}
|
|
21108
21108
|
function validIdentifier(value, maximum = architectureTargetLimits.identifierLength) {
|
|
@@ -21130,40 +21130,40 @@ function normalizeMetadata(value) {
|
|
|
21130
21130
|
normalized[key] = value[key];
|
|
21131
21131
|
return normalized;
|
|
21132
21132
|
}
|
|
21133
|
-
function validateMetadata2(value,
|
|
21133
|
+
function validateMetadata2(value, path19, errors) {
|
|
21134
21134
|
if (value === void 0)
|
|
21135
21135
|
return void 0;
|
|
21136
21136
|
if (!isRecord2(value)) {
|
|
21137
|
-
issue2(errors, "ARCHITECTURE_TARGET_METADATA_INVALID", "Metadata must be a bounded object of scalar values.",
|
|
21137
|
+
issue2(errors, "ARCHITECTURE_TARGET_METADATA_INVALID", "Metadata must be a bounded object of scalar values.", path19);
|
|
21138
21138
|
return void 0;
|
|
21139
21139
|
}
|
|
21140
21140
|
const entries = Object.entries(value);
|
|
21141
21141
|
if (entries.length > architectureTargetLimits.metadataKeys) {
|
|
21142
|
-
issue2(errors, "ARCHITECTURE_TARGET_LIMIT_EXCEEDED", `Metadata may contain at most ${architectureTargetLimits.metadataKeys} fields.`,
|
|
21142
|
+
issue2(errors, "ARCHITECTURE_TARGET_LIMIT_EXCEEDED", `Metadata may contain at most ${architectureTargetLimits.metadataKeys} fields.`, path19);
|
|
21143
21143
|
}
|
|
21144
21144
|
const normalized = {};
|
|
21145
21145
|
for (const [key, item] of entries) {
|
|
21146
21146
|
if (key.length === 0 || key.length > architectureTargetLimits.metadataKeyLength || isSensitiveMetadataKey(key)) {
|
|
21147
|
-
issue2(errors, "ARCHITECTURE_TARGET_SENSITIVE_FIELD", `Metadata field '${key}' is not allowed.`, `${
|
|
21147
|
+
issue2(errors, "ARCHITECTURE_TARGET_SENSITIVE_FIELD", `Metadata field '${key}' is not allowed.`, `${path19}.${key}`);
|
|
21148
21148
|
}
|
|
21149
21149
|
if (!metadataKeyPattern.test(key)) {
|
|
21150
|
-
issue2(errors, "ARCHITECTURE_TARGET_METADATA_INVALID", `Metadata field '${key}' must use a safe identifier shape.`, `${
|
|
21150
|
+
issue2(errors, "ARCHITECTURE_TARGET_METADATA_INVALID", `Metadata field '${key}' must use a safe identifier shape.`, `${path19}.${key}`);
|
|
21151
21151
|
}
|
|
21152
21152
|
if (item !== null && typeof item !== "string" && typeof item !== "number" && typeof item !== "boolean") {
|
|
21153
|
-
issue2(errors, "ARCHITECTURE_TARGET_METADATA_INVALID", "Metadata values must be scalar.", `${
|
|
21153
|
+
issue2(errors, "ARCHITECTURE_TARGET_METADATA_INVALID", "Metadata values must be scalar.", `${path19}.${key}`);
|
|
21154
21154
|
continue;
|
|
21155
21155
|
}
|
|
21156
21156
|
if (typeof item === "number" && !Number.isFinite(item)) {
|
|
21157
|
-
issue2(errors, "ARCHITECTURE_TARGET_METADATA_INVALID", "Metadata numbers must be finite.", `${
|
|
21157
|
+
issue2(errors, "ARCHITECTURE_TARGET_METADATA_INVALID", "Metadata numbers must be finite.", `${path19}.${key}`);
|
|
21158
21158
|
continue;
|
|
21159
21159
|
}
|
|
21160
21160
|
if (typeof item === "string") {
|
|
21161
21161
|
if (item.length > architectureTargetLimits.metadataStringLength) {
|
|
21162
|
-
issue2(errors, "ARCHITECTURE_TARGET_LIMIT_EXCEEDED", `Metadata strings must contain at most ${architectureTargetLimits.metadataStringLength} printable characters.`, `${
|
|
21162
|
+
issue2(errors, "ARCHITECTURE_TARGET_LIMIT_EXCEEDED", `Metadata strings must contain at most ${architectureTargetLimits.metadataStringLength} printable characters.`, `${path19}.${key}`);
|
|
21163
21163
|
continue;
|
|
21164
21164
|
}
|
|
21165
21165
|
if (!textPattern.test(item) || unsafeMetadataValuePattern.test(item)) {
|
|
21166
|
-
issue2(errors, "ARCHITECTURE_TARGET_SENSITIVE_FIELD", `Metadata value '${key}' contains unsafe or private content.`, `${
|
|
21166
|
+
issue2(errors, "ARCHITECTURE_TARGET_SENSITIVE_FIELD", `Metadata value '${key}' contains unsafe or private content.`, `${path19}.${key}`);
|
|
21167
21167
|
continue;
|
|
21168
21168
|
}
|
|
21169
21169
|
}
|
|
@@ -21175,81 +21175,81 @@ function isSensitiveMetadataKey(key) {
|
|
|
21175
21175
|
const normalized = key.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
|
|
21176
21176
|
return sensitiveMetadataKeyPattern.test(normalized);
|
|
21177
21177
|
}
|
|
21178
|
-
function validateOwner(value,
|
|
21178
|
+
function validateOwner(value, path19, errors) {
|
|
21179
21179
|
if (!isRecord2(value)) {
|
|
21180
|
-
issue2(errors, "ARCHITECTURE_TARGET_OWNER_INVALID", "Target owner must be an object.",
|
|
21180
|
+
issue2(errors, "ARCHITECTURE_TARGET_OWNER_INVALID", "Target owner must be an object.", path19);
|
|
21181
21181
|
return void 0;
|
|
21182
21182
|
}
|
|
21183
|
-
checkUnknownKeys(value, ["type", "id"],
|
|
21183
|
+
checkUnknownKeys(value, ["type", "id"], path19, errors);
|
|
21184
21184
|
if (!isOneOf(value.type, architectureTargetOwnerReferenceTypes)) {
|
|
21185
|
-
issue2(errors, "ARCHITECTURE_TARGET_OWNER_TYPE_INVALID", "Target owner type must be user, team, or organization.", `${
|
|
21185
|
+
issue2(errors, "ARCHITECTURE_TARGET_OWNER_TYPE_INVALID", "Target owner type must be user, team, or organization.", `${path19}.type`);
|
|
21186
21186
|
}
|
|
21187
21187
|
if (!validIdentifier(value.id))
|
|
21188
|
-
issue2(errors, "ARCHITECTURE_TARGET_OWNER_ID_INVALID", "Target owner id must be a bounded identifier.", `${
|
|
21188
|
+
issue2(errors, "ARCHITECTURE_TARGET_OWNER_ID_INVALID", "Target owner id must be a bounded identifier.", `${path19}.id`);
|
|
21189
21189
|
if (!isOneOf(value.type, architectureTargetOwnerReferenceTypes) || !validIdentifier(value.id))
|
|
21190
21190
|
return void 0;
|
|
21191
21191
|
return { type: value.type, id: value.id };
|
|
21192
21192
|
}
|
|
21193
|
-
function validateAdapterDescriptor(value,
|
|
21193
|
+
function validateAdapterDescriptor(value, path19, errors) {
|
|
21194
21194
|
if (!isRecord2(value)) {
|
|
21195
|
-
issue2(errors, "ARCHITECTURE_TARGET_ADAPTER_INVALID", "Target adapter descriptor must be an object.",
|
|
21195
|
+
issue2(errors, "ARCHITECTURE_TARGET_ADAPTER_INVALID", "Target adapter descriptor must be an object.", path19);
|
|
21196
21196
|
return void 0;
|
|
21197
21197
|
}
|
|
21198
|
-
checkUnknownKeys(value, ["kind", "version", "contractVersion"],
|
|
21198
|
+
checkUnknownKeys(value, ["kind", "version", "contractVersion"], path19, errors);
|
|
21199
21199
|
if (typeof value.kind !== "string" || !adapterKindPattern.test(value.kind)) {
|
|
21200
|
-
issue2(errors, "ARCHITECTURE_TARGET_ADAPTER_KIND_INVALID", "Adapter kind must be a lowercase bounded identifier.", `${
|
|
21200
|
+
issue2(errors, "ARCHITECTURE_TARGET_ADAPTER_KIND_INVALID", "Adapter kind must be a lowercase bounded identifier.", `${path19}.kind`);
|
|
21201
21201
|
}
|
|
21202
21202
|
if (!validText(value.version, architectureTargetLimits.adapterVersionLength)) {
|
|
21203
|
-
issue2(errors, "ARCHITECTURE_TARGET_ADAPTER_VERSION_INVALID", "Adapter version must be a bounded string.", `${
|
|
21203
|
+
issue2(errors, "ARCHITECTURE_TARGET_ADAPTER_VERSION_INVALID", "Adapter version must be a bounded string.", `${path19}.version`);
|
|
21204
21204
|
}
|
|
21205
21205
|
if (!architectureTargetAdapterContractVersions.includes(value.contractVersion)) {
|
|
21206
|
-
issue2(errors, "ARCHITECTURE_TARGET_ADAPTER_CONTRACT_VERSION_INVALID", "Adapter contract version must be 1 or 2.", `${
|
|
21206
|
+
issue2(errors, "ARCHITECTURE_TARGET_ADAPTER_CONTRACT_VERSION_INVALID", "Adapter contract version must be 1 or 2.", `${path19}.contractVersion`);
|
|
21207
21207
|
}
|
|
21208
21208
|
if (typeof value.kind !== "string" || !adapterKindPattern.test(value.kind) || !validText(value.version, architectureTargetLimits.adapterVersionLength) || value.contractVersion !== 1 && value.contractVersion !== 2)
|
|
21209
21209
|
return void 0;
|
|
21210
21210
|
return { kind: value.kind, version: value.version, contractVersion: value.contractVersion };
|
|
21211
21211
|
}
|
|
21212
|
-
function validateCapabilities(value,
|
|
21212
|
+
function validateCapabilities(value, path19, errors, contractVersion = 1) {
|
|
21213
21213
|
if (!isRecord2(value)) {
|
|
21214
|
-
issue2(errors, "ARCHITECTURE_TARGET_CAPABILITIES_INVALID", "Target capabilities must be an object.",
|
|
21214
|
+
issue2(errors, "ARCHITECTURE_TARGET_CAPABILITIES_INVALID", "Target capabilities must be an object.", path19);
|
|
21215
21215
|
return void 0;
|
|
21216
21216
|
}
|
|
21217
|
-
checkUnknownKeys(value, architectureTargetCapabilityNames,
|
|
21217
|
+
checkUnknownKeys(value, architectureTargetCapabilityNames, path19, errors);
|
|
21218
21218
|
const normalized = {};
|
|
21219
21219
|
const knownNames = new Set(architectureTargetCapabilityNames);
|
|
21220
21220
|
for (const [key, item] of Object.entries(value)) {
|
|
21221
21221
|
if (!knownNames.has(key))
|
|
21222
21222
|
continue;
|
|
21223
21223
|
if (typeof item !== "boolean") {
|
|
21224
|
-
issue2(errors, "ARCHITECTURE_TARGET_CAPABILITY_INVALID", "Capability values must be boolean.", `${
|
|
21224
|
+
issue2(errors, "ARCHITECTURE_TARGET_CAPABILITY_INVALID", "Capability values must be boolean.", `${path19}.${key}`);
|
|
21225
21225
|
continue;
|
|
21226
21226
|
}
|
|
21227
21227
|
if (contractVersion === 1 && architectureTargetMutationCapabilities.includes(key) && item === true) {
|
|
21228
|
-
issue2(errors, "ARCHITECTURE_TARGET_MUTATION_CAPABILITY_ENABLED", "Mutation capabilities must be absent or explicitly false in contract version 1.", `${
|
|
21228
|
+
issue2(errors, "ARCHITECTURE_TARGET_MUTATION_CAPABILITY_ENABLED", "Mutation capabilities must be absent or explicitly false in contract version 1.", `${path19}.${key}`);
|
|
21229
21229
|
continue;
|
|
21230
21230
|
}
|
|
21231
21231
|
normalized[key] = item;
|
|
21232
21232
|
}
|
|
21233
21233
|
if (contractVersion === 2 && (normalized.apply === true || normalized.rollback === true) && normalized["sync.write"] !== true) {
|
|
21234
|
-
issue2(errors, "ARCHITECTURE_TARGET_MUTATION_CAPABILITY_ENABLED", "Contract version 2 requires sync.write when apply or rollback is enabled.", `${
|
|
21234
|
+
issue2(errors, "ARCHITECTURE_TARGET_MUTATION_CAPABILITY_ENABLED", "Contract version 2 requires sync.write when apply or rollback is enabled.", `${path19}.sync.write`);
|
|
21235
21235
|
}
|
|
21236
21236
|
return normalized;
|
|
21237
21237
|
}
|
|
21238
|
-
function validateConsent(value,
|
|
21238
|
+
function validateConsent(value, path19, errors) {
|
|
21239
21239
|
if (!isRecord2(value)) {
|
|
21240
|
-
issue2(errors, "ARCHITECTURE_TARGET_CONSENT_INVALID", "Target consent must be an object.",
|
|
21240
|
+
issue2(errors, "ARCHITECTURE_TARGET_CONSENT_INVALID", "Target consent must be an object.", path19);
|
|
21241
21241
|
return void 0;
|
|
21242
21242
|
}
|
|
21243
|
-
checkUnknownKeys(value, ["status", "requestedAt", "grantedAt", "deniedAt", "revokedAt"],
|
|
21243
|
+
checkUnknownKeys(value, ["status", "requestedAt", "grantedAt", "deniedAt", "revokedAt"], path19, errors);
|
|
21244
21244
|
if (!isOneOf(value.status, architectureTargetConsentStatuses))
|
|
21245
|
-
issue2(errors, "ARCHITECTURE_TARGET_CONSENT_STATUS_INVALID", "Target consent status is invalid.", `${
|
|
21245
|
+
issue2(errors, "ARCHITECTURE_TARGET_CONSENT_STATUS_INVALID", "Target consent status is invalid.", `${path19}.status`);
|
|
21246
21246
|
if (!validIsoTimestamp(value.requestedAt))
|
|
21247
|
-
issue2(errors, "ARCHITECTURE_TARGET_CONSENT_TIMESTAMP_REQUIRED", "Consent requestedAt must be an ISO-8601 UTC timestamp.", `${
|
|
21247
|
+
issue2(errors, "ARCHITECTURE_TARGET_CONSENT_TIMESTAMP_REQUIRED", "Consent requestedAt must be an ISO-8601 UTC timestamp.", `${path19}.requestedAt`);
|
|
21248
21248
|
const timestamps = ["grantedAt", "deniedAt", "revokedAt"];
|
|
21249
21249
|
for (const timestamp of timestamps) {
|
|
21250
21250
|
const item = value[timestamp];
|
|
21251
21251
|
if (item !== void 0 && item !== null && !validIsoTimestamp(item)) {
|
|
21252
|
-
issue2(errors, "ARCHITECTURE_TARGET_TIMESTAMP_INVALID", `${timestamp} must be an ISO-8601 UTC timestamp or null.`, `${
|
|
21252
|
+
issue2(errors, "ARCHITECTURE_TARGET_TIMESTAMP_INVALID", `${timestamp} must be an ISO-8601 UTC timestamp or null.`, `${path19}.${timestamp}`);
|
|
21253
21253
|
}
|
|
21254
21254
|
}
|
|
21255
21255
|
const requiredTimestamp = {
|
|
@@ -21260,7 +21260,7 @@ function validateConsent(value, path18, errors) {
|
|
|
21260
21260
|
};
|
|
21261
21261
|
const required2 = isOneOf(value.status, architectureTargetConsentStatuses) ? requiredTimestamp[value.status] : null;
|
|
21262
21262
|
if (required2 && !validIsoTimestamp(value[required2])) {
|
|
21263
|
-
issue2(errors, "ARCHITECTURE_TARGET_CONSENT_TIMESTAMP_REQUIRED", `Consent ${required2} is required for status '${value.status}'.`, `${
|
|
21263
|
+
issue2(errors, "ARCHITECTURE_TARGET_CONSENT_TIMESTAMP_REQUIRED", `Consent ${required2} is required for status '${value.status}'.`, `${path19}.${required2}`);
|
|
21264
21264
|
}
|
|
21265
21265
|
if (!isOneOf(value.status, architectureTargetConsentStatuses) || !validIsoTimestamp(value.requestedAt))
|
|
21266
21266
|
return void 0;
|
|
@@ -21272,11 +21272,11 @@ function validateConsent(value, path18, errors) {
|
|
|
21272
21272
|
...value.revokedAt === void 0 ? {} : { revokedAt: value.revokedAt }
|
|
21273
21273
|
};
|
|
21274
21274
|
}
|
|
21275
|
-
function validateOptionalTimestamp(value,
|
|
21275
|
+
function validateOptionalTimestamp(value, path19, errors) {
|
|
21276
21276
|
if (value === void 0)
|
|
21277
21277
|
return void 0;
|
|
21278
21278
|
if (!validIsoTimestamp(value)) {
|
|
21279
|
-
issue2(errors, "ARCHITECTURE_TARGET_TIMESTAMP_INVALID", "Timestamp must be an ISO-8601 UTC timestamp.",
|
|
21279
|
+
issue2(errors, "ARCHITECTURE_TARGET_TIMESTAMP_INVALID", "Timestamp must be an ISO-8601 UTC timestamp.", path19);
|
|
21280
21280
|
return void 0;
|
|
21281
21281
|
}
|
|
21282
21282
|
return value;
|
|
@@ -21494,34 +21494,34 @@ function architectureTargetCapabilitiesDigest(input2, contractVersion = 1) {
|
|
|
21494
21494
|
throw new ArchitectureTargetValidationError(errors.length > 0 ? errors : [{ code: "ARCHITECTURE_TARGET_CAPABILITIES_INVALID", message: "Capabilities are invalid." }]);
|
|
21495
21495
|
return sha256Hex(canonicalizeJson(normalizeCapabilities(normalized)));
|
|
21496
21496
|
}
|
|
21497
|
-
function validateObservedSkill(value,
|
|
21497
|
+
function validateObservedSkill(value, path19, errors) {
|
|
21498
21498
|
if (!isRecord2(value)) {
|
|
21499
|
-
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill must be an object.",
|
|
21499
|
+
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill must be an object.", path19);
|
|
21500
21500
|
return void 0;
|
|
21501
21501
|
}
|
|
21502
|
-
checkUnknownKeys(value, ["skillRefId", "slug", "version", "digest", "kind", "enabled", "runtimeExposure", "configurationDigest", "configured", "managed", "supported", "metadata"],
|
|
21502
|
+
checkUnknownKeys(value, ["skillRefId", "slug", "version", "digest", "kind", "enabled", "runtimeExposure", "configurationDigest", "configured", "managed", "supported", "metadata"], path19, errors);
|
|
21503
21503
|
if (value.skillRefId !== void 0 && !validIdentifier(value.skillRefId))
|
|
21504
|
-
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill skillRefId must be a bounded identifier.", `${
|
|
21504
|
+
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill skillRefId must be a bounded identifier.", `${path19}.skillRefId`);
|
|
21505
21505
|
if (!validText(value.slug, architectureTargetLimits.identifierLength) || !identifierPattern.test(value.slug))
|
|
21506
|
-
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill slug must be a bounded identifier.", `${
|
|
21506
|
+
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill slug must be a bounded identifier.", `${path19}.slug`);
|
|
21507
21507
|
if (value.version !== void 0 && !validText(value.version, architectureTargetLimits.versionLength))
|
|
21508
|
-
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill version must be a bounded string.", `${
|
|
21508
|
+
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill version must be a bounded string.", `${path19}.version`);
|
|
21509
21509
|
if (value.digest !== void 0 && !validDigest(value.digest))
|
|
21510
|
-
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill digest must be a lowercase SHA-256 digest.", `${
|
|
21510
|
+
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill digest must be a lowercase SHA-256 digest.", `${path19}.digest`);
|
|
21511
21511
|
if (value.kind !== void 0 && value.kind !== "router" && value.kind !== "leaf")
|
|
21512
|
-
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill kind must be router or leaf.", `${
|
|
21512
|
+
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill kind must be router or leaf.", `${path19}.kind`);
|
|
21513
21513
|
if (value.enabled !== void 0 && typeof value.enabled !== "boolean")
|
|
21514
|
-
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill enabled must be boolean.", `${
|
|
21514
|
+
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill enabled must be boolean.", `${path19}.enabled`);
|
|
21515
21515
|
if (value.runtimeExposure !== void 0 && !isOneOf(value.runtimeExposure, runtimeExposureModes))
|
|
21516
|
-
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill runtimeExposure is invalid.", `${
|
|
21516
|
+
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill runtimeExposure is invalid.", `${path19}.runtimeExposure`);
|
|
21517
21517
|
if (value.configurationDigest !== void 0 && !validDigest(value.configurationDigest))
|
|
21518
|
-
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill configurationDigest must be a lowercase SHA-256 digest.", `${
|
|
21518
|
+
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", "Observed skill configurationDigest must be a lowercase SHA-256 digest.", `${path19}.configurationDigest`);
|
|
21519
21519
|
for (const key of ["configured", "managed", "supported"]) {
|
|
21520
21520
|
if (value[key] !== void 0 && typeof value[key] !== "boolean")
|
|
21521
|
-
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", `Observed skill ${key} must be boolean.`, `${
|
|
21521
|
+
issue2(errors, "ARCHITECTURE_TARGET_SKILL_INVALID", `Observed skill ${key} must be boolean.`, `${path19}.${key}`);
|
|
21522
21522
|
}
|
|
21523
|
-
const metadata = validateMetadata2(value.metadata, `${
|
|
21524
|
-
if (errors.some((error62) => error62.path?.startsWith(
|
|
21523
|
+
const metadata = validateMetadata2(value.metadata, `${path19}.metadata`, errors);
|
|
21524
|
+
if (errors.some((error62) => error62.path?.startsWith(path19)))
|
|
21525
21525
|
return void 0;
|
|
21526
21526
|
return {
|
|
21527
21527
|
...value.skillRefId === void 0 ? {} : { skillRefId: value.skillRefId },
|
|
@@ -21538,34 +21538,34 @@ function validateObservedSkill(value, path18, errors) {
|
|
|
21538
21538
|
...metadata && Object.keys(metadata).length > 0 ? { metadata } : {}
|
|
21539
21539
|
};
|
|
21540
21540
|
}
|
|
21541
|
-
function validateConfigFinding(value,
|
|
21541
|
+
function validateConfigFinding(value, path19, errors) {
|
|
21542
21542
|
if (!isRecord2(value)) {
|
|
21543
|
-
issue2(errors, "ARCHITECTURE_TARGET_CONFIG_FINDING_INVALID", "Configuration finding must be an object.",
|
|
21543
|
+
issue2(errors, "ARCHITECTURE_TARGET_CONFIG_FINDING_INVALID", "Configuration finding must be an object.", path19);
|
|
21544
21544
|
return void 0;
|
|
21545
21545
|
}
|
|
21546
|
-
checkUnknownKeys(value, ["code", "severity", "count"],
|
|
21546
|
+
checkUnknownKeys(value, ["code", "severity", "count"], path19, errors);
|
|
21547
21547
|
if (typeof value.code !== "string" || !findingCodePattern.test(value.code))
|
|
21548
|
-
issue2(errors, "ARCHITECTURE_TARGET_CONFIG_FINDING_INVALID", "Configuration finding code must be a bounded identifier.", `${
|
|
21548
|
+
issue2(errors, "ARCHITECTURE_TARGET_CONFIG_FINDING_INVALID", "Configuration finding code must be a bounded identifier.", `${path19}.code`);
|
|
21549
21549
|
if (!isOneOf(value.severity, architectureTargetConfigFindingSeverities))
|
|
21550
|
-
issue2(errors, "ARCHITECTURE_TARGET_CONFIG_FINDING_INVALID", "Configuration finding severity is invalid.", `${
|
|
21550
|
+
issue2(errors, "ARCHITECTURE_TARGET_CONFIG_FINDING_INVALID", "Configuration finding severity is invalid.", `${path19}.severity`);
|
|
21551
21551
|
if (typeof value.count !== "number" || !Number.isInteger(value.count) || value.count < 0 || value.count > architectureTargetLimits.counterMaximum)
|
|
21552
|
-
issue2(errors, "ARCHITECTURE_TARGET_CONFIG_FINDING_INVALID", "Configuration finding count must be a bounded non-negative integer.", `${
|
|
21552
|
+
issue2(errors, "ARCHITECTURE_TARGET_CONFIG_FINDING_INVALID", "Configuration finding count must be a bounded non-negative integer.", `${path19}.count`);
|
|
21553
21553
|
if (typeof value.code !== "string" || !findingCodePattern.test(value.code) || !isOneOf(value.severity, architectureTargetConfigFindingSeverities) || typeof value.count !== "number" || !Number.isInteger(value.count) || value.count < 0)
|
|
21554
21554
|
return void 0;
|
|
21555
21555
|
return { code: value.code, severity: value.severity, count: value.count };
|
|
21556
21556
|
}
|
|
21557
|
-
function validatePromptAwareness(value,
|
|
21557
|
+
function validatePromptAwareness(value, path19, errors) {
|
|
21558
21558
|
if (!isRecord2(value)) {
|
|
21559
|
-
issue2(errors, "ARCHITECTURE_TARGET_PROMPT_AWARENESS_INVALID", "Prompt awareness must be an object.",
|
|
21559
|
+
issue2(errors, "ARCHITECTURE_TARGET_PROMPT_AWARENESS_INVALID", "Prompt awareness must be an object.", path19);
|
|
21560
21560
|
return void 0;
|
|
21561
21561
|
}
|
|
21562
|
-
checkUnknownKeys(value, ["detected", "count", "redacted"],
|
|
21562
|
+
checkUnknownKeys(value, ["detected", "count", "redacted"], path19, errors);
|
|
21563
21563
|
if (typeof value.detected !== "boolean")
|
|
21564
|
-
issue2(errors, "ARCHITECTURE_TARGET_PROMPT_AWARENESS_INVALID", "Prompt awareness detected must be boolean.", `${
|
|
21564
|
+
issue2(errors, "ARCHITECTURE_TARGET_PROMPT_AWARENESS_INVALID", "Prompt awareness detected must be boolean.", `${path19}.detected`);
|
|
21565
21565
|
if (typeof value.count !== "number" || !Number.isInteger(value.count) || value.count < 0 || value.count > architectureTargetLimits.counterMaximum)
|
|
21566
|
-
issue2(errors, "ARCHITECTURE_TARGET_PROMPT_AWARENESS_INVALID", "Prompt awareness count must be a bounded non-negative integer.", `${
|
|
21566
|
+
issue2(errors, "ARCHITECTURE_TARGET_PROMPT_AWARENESS_INVALID", "Prompt awareness count must be a bounded non-negative integer.", `${path19}.count`);
|
|
21567
21567
|
if (value.redacted !== void 0 && typeof value.redacted !== "boolean")
|
|
21568
|
-
issue2(errors, "ARCHITECTURE_TARGET_PROMPT_AWARENESS_INVALID", "Prompt awareness redacted must be boolean.", `${
|
|
21568
|
+
issue2(errors, "ARCHITECTURE_TARGET_PROMPT_AWARENESS_INVALID", "Prompt awareness redacted must be boolean.", `${path19}.redacted`);
|
|
21569
21569
|
if (typeof value.detected !== "boolean" || typeof value.count !== "number" || !Number.isInteger(value.count) || value.count < 0 || value.redacted !== void 0 && typeof value.redacted !== "boolean")
|
|
21570
21570
|
return void 0;
|
|
21571
21571
|
return {
|
|
@@ -23216,9 +23216,9 @@ var require_yauzl = __commonJS({
|
|
|
23216
23216
|
exports.Entry = Entry;
|
|
23217
23217
|
exports.LocalFileHeader = LocalFileHeader;
|
|
23218
23218
|
exports.RandomAccessReader = RandomAccessReader;
|
|
23219
|
-
function openPromise(
|
|
23219
|
+
function openPromise(path19, options2) {
|
|
23220
23220
|
return new Promise((resolve, reject) => {
|
|
23221
|
-
open10(
|
|
23221
|
+
open10(path19, { ...options2, lazyEntries: true }, function(err, zipfile) {
|
|
23222
23222
|
if (err) return reject(err);
|
|
23223
23223
|
resolve(zipfile);
|
|
23224
23224
|
});
|
|
@@ -23248,7 +23248,7 @@ var require_yauzl = __commonJS({
|
|
|
23248
23248
|
});
|
|
23249
23249
|
});
|
|
23250
23250
|
}
|
|
23251
|
-
function open10(
|
|
23251
|
+
function open10(path19, options2, callback) {
|
|
23252
23252
|
if (typeof options2 === "function") {
|
|
23253
23253
|
callback = options2;
|
|
23254
23254
|
options2 = null;
|
|
@@ -23260,7 +23260,7 @@ var require_yauzl = __commonJS({
|
|
|
23260
23260
|
if (options2.validateEntrySizes == null) options2.validateEntrySizes = true;
|
|
23261
23261
|
if (options2.strictFileNames == null) options2.strictFileNames = false;
|
|
23262
23262
|
if (callback == null) callback = defaultCallback;
|
|
23263
|
-
fs.open(
|
|
23263
|
+
fs.open(path19, "r", function(err, fd) {
|
|
23264
23264
|
if (err) return callback(err);
|
|
23265
23265
|
fromFd(fd, options2, function(err2, zipfile) {
|
|
23266
23266
|
if (err2) fs.close(fd, defaultCallback);
|
|
@@ -25041,10 +25041,10 @@ function comparisonResult(input2, baseFiles, targetFiles, baseBytes, targetBytes
|
|
|
25041
25041
|
remaining -= preview.length;
|
|
25042
25042
|
return { sha256: digest2(content), byteSize: Buffer.byteLength(content), preview, previewTruncated: preview.length < content.length, previewOmitted: binary ? "binary" : unchanged ? "unchanged" : null };
|
|
25043
25043
|
};
|
|
25044
|
-
const changes = [.../* @__PURE__ */ new Set([...before.keys(), ...after.keys()])].sort().map((
|
|
25045
|
-
const status = !before.has(
|
|
25044
|
+
const changes = [.../* @__PURE__ */ new Set([...before.keys(), ...after.keys()])].sort().map((path19) => {
|
|
25045
|
+
const status = !before.has(path19) ? "added" : !after.has(path19) ? "removed" : before.get(path19) === after.get(path19) ? "unchanged" : "modified";
|
|
25046
25046
|
totals[status]++;
|
|
25047
|
-
return { path:
|
|
25047
|
+
return { path: path19, status, base: side(before.get(path19), status === "unchanged"), target: side(after.get(path19), status === "unchanged") };
|
|
25048
25048
|
});
|
|
25049
25049
|
return { schemaVersion: 1, base: { ...input2.base, byteSize: baseBytes }, target: { ...input2.target, byteSize: targetBytes }, totals, changes, previewLimitCharacters: 32768, notice: "Compared complete content. Previews are bounded and may be omitted or truncated. No package code was executed." };
|
|
25050
25050
|
}
|
|
@@ -25407,17 +25407,17 @@ var require_visit = __commonJS({
|
|
|
25407
25407
|
visit2.BREAK = BREAK;
|
|
25408
25408
|
visit2.SKIP = SKIP;
|
|
25409
25409
|
visit2.REMOVE = REMOVE;
|
|
25410
|
-
function visit_(key, node2, visitor,
|
|
25411
|
-
const ctrl = callVisitor(key, node2, visitor,
|
|
25410
|
+
function visit_(key, node2, visitor, path19) {
|
|
25411
|
+
const ctrl = callVisitor(key, node2, visitor, path19);
|
|
25412
25412
|
if (identity2.isNode(ctrl) || identity2.isPair(ctrl)) {
|
|
25413
|
-
replaceNode(key,
|
|
25414
|
-
return visit_(key, ctrl, visitor,
|
|
25413
|
+
replaceNode(key, path19, ctrl);
|
|
25414
|
+
return visit_(key, ctrl, visitor, path19);
|
|
25415
25415
|
}
|
|
25416
25416
|
if (typeof ctrl !== "symbol") {
|
|
25417
25417
|
if (identity2.isCollection(node2)) {
|
|
25418
|
-
|
|
25418
|
+
path19 = Object.freeze(path19.concat(node2));
|
|
25419
25419
|
for (let i = 0; i < node2.items.length; ++i) {
|
|
25420
|
-
const ci = visit_(i, node2.items[i], visitor,
|
|
25420
|
+
const ci = visit_(i, node2.items[i], visitor, path19);
|
|
25421
25421
|
if (typeof ci === "number")
|
|
25422
25422
|
i = ci - 1;
|
|
25423
25423
|
else if (ci === BREAK)
|
|
@@ -25428,13 +25428,13 @@ var require_visit = __commonJS({
|
|
|
25428
25428
|
}
|
|
25429
25429
|
}
|
|
25430
25430
|
} else if (identity2.isPair(node2)) {
|
|
25431
|
-
|
|
25432
|
-
const ck = visit_("key", node2.key, visitor,
|
|
25431
|
+
path19 = Object.freeze(path19.concat(node2));
|
|
25432
|
+
const ck = visit_("key", node2.key, visitor, path19);
|
|
25433
25433
|
if (ck === BREAK)
|
|
25434
25434
|
return BREAK;
|
|
25435
25435
|
else if (ck === REMOVE)
|
|
25436
25436
|
node2.key = null;
|
|
25437
|
-
const cv = visit_("value", node2.value, visitor,
|
|
25437
|
+
const cv = visit_("value", node2.value, visitor, path19);
|
|
25438
25438
|
if (cv === BREAK)
|
|
25439
25439
|
return BREAK;
|
|
25440
25440
|
else if (cv === REMOVE)
|
|
@@ -25455,17 +25455,17 @@ var require_visit = __commonJS({
|
|
|
25455
25455
|
visitAsync.BREAK = BREAK;
|
|
25456
25456
|
visitAsync.SKIP = SKIP;
|
|
25457
25457
|
visitAsync.REMOVE = REMOVE;
|
|
25458
|
-
async function visitAsync_(key, node2, visitor,
|
|
25459
|
-
const ctrl = await callVisitor(key, node2, visitor,
|
|
25458
|
+
async function visitAsync_(key, node2, visitor, path19) {
|
|
25459
|
+
const ctrl = await callVisitor(key, node2, visitor, path19);
|
|
25460
25460
|
if (identity2.isNode(ctrl) || identity2.isPair(ctrl)) {
|
|
25461
|
-
replaceNode(key,
|
|
25462
|
-
return visitAsync_(key, ctrl, visitor,
|
|
25461
|
+
replaceNode(key, path19, ctrl);
|
|
25462
|
+
return visitAsync_(key, ctrl, visitor, path19);
|
|
25463
25463
|
}
|
|
25464
25464
|
if (typeof ctrl !== "symbol") {
|
|
25465
25465
|
if (identity2.isCollection(node2)) {
|
|
25466
|
-
|
|
25466
|
+
path19 = Object.freeze(path19.concat(node2));
|
|
25467
25467
|
for (let i = 0; i < node2.items.length; ++i) {
|
|
25468
|
-
const ci = await visitAsync_(i, node2.items[i], visitor,
|
|
25468
|
+
const ci = await visitAsync_(i, node2.items[i], visitor, path19);
|
|
25469
25469
|
if (typeof ci === "number")
|
|
25470
25470
|
i = ci - 1;
|
|
25471
25471
|
else if (ci === BREAK)
|
|
@@ -25476,13 +25476,13 @@ var require_visit = __commonJS({
|
|
|
25476
25476
|
}
|
|
25477
25477
|
}
|
|
25478
25478
|
} else if (identity2.isPair(node2)) {
|
|
25479
|
-
|
|
25480
|
-
const ck = await visitAsync_("key", node2.key, visitor,
|
|
25479
|
+
path19 = Object.freeze(path19.concat(node2));
|
|
25480
|
+
const ck = await visitAsync_("key", node2.key, visitor, path19);
|
|
25481
25481
|
if (ck === BREAK)
|
|
25482
25482
|
return BREAK;
|
|
25483
25483
|
else if (ck === REMOVE)
|
|
25484
25484
|
node2.key = null;
|
|
25485
|
-
const cv = await visitAsync_("value", node2.value, visitor,
|
|
25485
|
+
const cv = await visitAsync_("value", node2.value, visitor, path19);
|
|
25486
25486
|
if (cv === BREAK)
|
|
25487
25487
|
return BREAK;
|
|
25488
25488
|
else if (cv === REMOVE)
|
|
@@ -25509,23 +25509,23 @@ var require_visit = __commonJS({
|
|
|
25509
25509
|
}
|
|
25510
25510
|
return visitor;
|
|
25511
25511
|
}
|
|
25512
|
-
function callVisitor(key, node2, visitor,
|
|
25512
|
+
function callVisitor(key, node2, visitor, path19) {
|
|
25513
25513
|
if (typeof visitor === "function")
|
|
25514
|
-
return visitor(key, node2,
|
|
25514
|
+
return visitor(key, node2, path19);
|
|
25515
25515
|
if (identity2.isMap(node2))
|
|
25516
|
-
return visitor.Map?.(key, node2,
|
|
25516
|
+
return visitor.Map?.(key, node2, path19);
|
|
25517
25517
|
if (identity2.isSeq(node2))
|
|
25518
|
-
return visitor.Seq?.(key, node2,
|
|
25518
|
+
return visitor.Seq?.(key, node2, path19);
|
|
25519
25519
|
if (identity2.isPair(node2))
|
|
25520
|
-
return visitor.Pair?.(key, node2,
|
|
25520
|
+
return visitor.Pair?.(key, node2, path19);
|
|
25521
25521
|
if (identity2.isScalar(node2))
|
|
25522
|
-
return visitor.Scalar?.(key, node2,
|
|
25522
|
+
return visitor.Scalar?.(key, node2, path19);
|
|
25523
25523
|
if (identity2.isAlias(node2))
|
|
25524
|
-
return visitor.Alias?.(key, node2,
|
|
25524
|
+
return visitor.Alias?.(key, node2, path19);
|
|
25525
25525
|
return void 0;
|
|
25526
25526
|
}
|
|
25527
|
-
function replaceNode(key,
|
|
25528
|
-
const parent =
|
|
25527
|
+
function replaceNode(key, path19, node2) {
|
|
25528
|
+
const parent = path19[path19.length - 1];
|
|
25529
25529
|
if (identity2.isCollection(parent)) {
|
|
25530
25530
|
parent.items[key] = node2;
|
|
25531
25531
|
} else if (identity2.isPair(parent)) {
|
|
@@ -26137,10 +26137,10 @@ var require_Collection = __commonJS({
|
|
|
26137
26137
|
var createNode = require_createNode();
|
|
26138
26138
|
var identity2 = require_identity();
|
|
26139
26139
|
var Node = require_Node();
|
|
26140
|
-
function collectionFromPath(schema,
|
|
26140
|
+
function collectionFromPath(schema, path19, value) {
|
|
26141
26141
|
let v = value;
|
|
26142
|
-
for (let i =
|
|
26143
|
-
const k =
|
|
26142
|
+
for (let i = path19.length - 1; i >= 0; --i) {
|
|
26143
|
+
const k = path19[i];
|
|
26144
26144
|
if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
|
|
26145
26145
|
const a = [];
|
|
26146
26146
|
a[k] = v;
|
|
@@ -26159,7 +26159,7 @@ var require_Collection = __commonJS({
|
|
|
26159
26159
|
sourceObjects: /* @__PURE__ */ new Map()
|
|
26160
26160
|
});
|
|
26161
26161
|
}
|
|
26162
|
-
var isEmptyPath = (
|
|
26162
|
+
var isEmptyPath = (path19) => path19 == null || typeof path19 === "object" && !!path19[Symbol.iterator]().next().done;
|
|
26163
26163
|
var Collection = class extends Node.NodeBase {
|
|
26164
26164
|
constructor(type, schema) {
|
|
26165
26165
|
super(type);
|
|
@@ -26189,11 +26189,11 @@ var require_Collection = __commonJS({
|
|
|
26189
26189
|
* be a Pair instance or a `{ key, value }` object, which may not have a key
|
|
26190
26190
|
* that already exists in the map.
|
|
26191
26191
|
*/
|
|
26192
|
-
addIn(
|
|
26193
|
-
if (isEmptyPath(
|
|
26192
|
+
addIn(path19, value) {
|
|
26193
|
+
if (isEmptyPath(path19))
|
|
26194
26194
|
this.add(value);
|
|
26195
26195
|
else {
|
|
26196
|
-
const [key, ...rest] =
|
|
26196
|
+
const [key, ...rest] = path19;
|
|
26197
26197
|
const node2 = this.get(key, true);
|
|
26198
26198
|
if (identity2.isCollection(node2))
|
|
26199
26199
|
node2.addIn(rest, value);
|
|
@@ -26207,8 +26207,8 @@ var require_Collection = __commonJS({
|
|
|
26207
26207
|
* Removes a value from the collection.
|
|
26208
26208
|
* @returns `true` if the item was found and removed.
|
|
26209
26209
|
*/
|
|
26210
|
-
deleteIn(
|
|
26211
|
-
const [key, ...rest] =
|
|
26210
|
+
deleteIn(path19) {
|
|
26211
|
+
const [key, ...rest] = path19;
|
|
26212
26212
|
if (rest.length === 0)
|
|
26213
26213
|
return this.delete(key);
|
|
26214
26214
|
const node2 = this.get(key, true);
|
|
@@ -26222,8 +26222,8 @@ var require_Collection = __commonJS({
|
|
|
26222
26222
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
26223
26223
|
* `true` (collections are always returned intact).
|
|
26224
26224
|
*/
|
|
26225
|
-
getIn(
|
|
26226
|
-
const [key, ...rest] =
|
|
26225
|
+
getIn(path19, keepScalar) {
|
|
26226
|
+
const [key, ...rest] = path19;
|
|
26227
26227
|
const node2 = this.get(key, true);
|
|
26228
26228
|
if (rest.length === 0)
|
|
26229
26229
|
return !keepScalar && identity2.isScalar(node2) ? node2.value : node2;
|
|
@@ -26241,8 +26241,8 @@ var require_Collection = __commonJS({
|
|
|
26241
26241
|
/**
|
|
26242
26242
|
* Checks if the collection includes a value with the key `key`.
|
|
26243
26243
|
*/
|
|
26244
|
-
hasIn(
|
|
26245
|
-
const [key, ...rest] =
|
|
26244
|
+
hasIn(path19) {
|
|
26245
|
+
const [key, ...rest] = path19;
|
|
26246
26246
|
if (rest.length === 0)
|
|
26247
26247
|
return this.has(key);
|
|
26248
26248
|
const node2 = this.get(key, true);
|
|
@@ -26252,8 +26252,8 @@ var require_Collection = __commonJS({
|
|
|
26252
26252
|
* Sets a value in this collection. For `!!set`, `value` needs to be a
|
|
26253
26253
|
* boolean to add/remove the item from the set.
|
|
26254
26254
|
*/
|
|
26255
|
-
setIn(
|
|
26256
|
-
const [key, ...rest] =
|
|
26255
|
+
setIn(path19, value) {
|
|
26256
|
+
const [key, ...rest] = path19;
|
|
26257
26257
|
if (rest.length === 0) {
|
|
26258
26258
|
this.set(key, value);
|
|
26259
26259
|
} else {
|
|
@@ -28768,9 +28768,9 @@ var require_Document = __commonJS({
|
|
|
28768
28768
|
this.contents.add(value);
|
|
28769
28769
|
}
|
|
28770
28770
|
/** Adds a value to the document. */
|
|
28771
|
-
addIn(
|
|
28771
|
+
addIn(path19, value) {
|
|
28772
28772
|
if (assertCollection(this.contents))
|
|
28773
|
-
this.contents.addIn(
|
|
28773
|
+
this.contents.addIn(path19, value);
|
|
28774
28774
|
}
|
|
28775
28775
|
/**
|
|
28776
28776
|
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
@@ -28845,14 +28845,14 @@ var require_Document = __commonJS({
|
|
|
28845
28845
|
* Removes a value from the document.
|
|
28846
28846
|
* @returns `true` if the item was found and removed.
|
|
28847
28847
|
*/
|
|
28848
|
-
deleteIn(
|
|
28849
|
-
if (Collection.isEmptyPath(
|
|
28848
|
+
deleteIn(path19) {
|
|
28849
|
+
if (Collection.isEmptyPath(path19)) {
|
|
28850
28850
|
if (this.contents == null)
|
|
28851
28851
|
return false;
|
|
28852
28852
|
this.contents = null;
|
|
28853
28853
|
return true;
|
|
28854
28854
|
}
|
|
28855
|
-
return assertCollection(this.contents) ? this.contents.deleteIn(
|
|
28855
|
+
return assertCollection(this.contents) ? this.contents.deleteIn(path19) : false;
|
|
28856
28856
|
}
|
|
28857
28857
|
/**
|
|
28858
28858
|
* Returns item at `key`, or `undefined` if not found. By default unwraps
|
|
@@ -28867,10 +28867,10 @@ var require_Document = __commonJS({
|
|
|
28867
28867
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
28868
28868
|
* `true` (collections are always returned intact).
|
|
28869
28869
|
*/
|
|
28870
|
-
getIn(
|
|
28871
|
-
if (Collection.isEmptyPath(
|
|
28870
|
+
getIn(path19, keepScalar) {
|
|
28871
|
+
if (Collection.isEmptyPath(path19))
|
|
28872
28872
|
return !keepScalar && identity2.isScalar(this.contents) ? this.contents.value : this.contents;
|
|
28873
|
-
return identity2.isCollection(this.contents) ? this.contents.getIn(
|
|
28873
|
+
return identity2.isCollection(this.contents) ? this.contents.getIn(path19, keepScalar) : void 0;
|
|
28874
28874
|
}
|
|
28875
28875
|
/**
|
|
28876
28876
|
* Checks if the document includes a value with the key `key`.
|
|
@@ -28881,10 +28881,10 @@ var require_Document = __commonJS({
|
|
|
28881
28881
|
/**
|
|
28882
28882
|
* Checks if the document includes a value at `path`.
|
|
28883
28883
|
*/
|
|
28884
|
-
hasIn(
|
|
28885
|
-
if (Collection.isEmptyPath(
|
|
28884
|
+
hasIn(path19) {
|
|
28885
|
+
if (Collection.isEmptyPath(path19))
|
|
28886
28886
|
return this.contents !== void 0;
|
|
28887
|
-
return identity2.isCollection(this.contents) ? this.contents.hasIn(
|
|
28887
|
+
return identity2.isCollection(this.contents) ? this.contents.hasIn(path19) : false;
|
|
28888
28888
|
}
|
|
28889
28889
|
/**
|
|
28890
28890
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
@@ -28901,13 +28901,13 @@ var require_Document = __commonJS({
|
|
|
28901
28901
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
28902
28902
|
* boolean to add/remove the item from the set.
|
|
28903
28903
|
*/
|
|
28904
|
-
setIn(
|
|
28905
|
-
if (Collection.isEmptyPath(
|
|
28904
|
+
setIn(path19, value) {
|
|
28905
|
+
if (Collection.isEmptyPath(path19)) {
|
|
28906
28906
|
this.contents = value;
|
|
28907
28907
|
} else if (this.contents == null) {
|
|
28908
|
-
this.contents = Collection.collectionFromPath(this.schema, Array.from(
|
|
28908
|
+
this.contents = Collection.collectionFromPath(this.schema, Array.from(path19), value);
|
|
28909
28909
|
} else if (assertCollection(this.contents)) {
|
|
28910
|
-
this.contents.setIn(
|
|
28910
|
+
this.contents.setIn(path19, value);
|
|
28911
28911
|
}
|
|
28912
28912
|
}
|
|
28913
28913
|
/**
|
|
@@ -30868,9 +30868,9 @@ var require_cst_visit = __commonJS({
|
|
|
30868
30868
|
visit2.BREAK = BREAK;
|
|
30869
30869
|
visit2.SKIP = SKIP;
|
|
30870
30870
|
visit2.REMOVE = REMOVE;
|
|
30871
|
-
visit2.itemAtPath = (cst,
|
|
30871
|
+
visit2.itemAtPath = (cst, path19) => {
|
|
30872
30872
|
let item = cst;
|
|
30873
|
-
for (const [field, index] of
|
|
30873
|
+
for (const [field, index] of path19) {
|
|
30874
30874
|
const tok = item?.[field];
|
|
30875
30875
|
if (tok && "items" in tok) {
|
|
30876
30876
|
item = tok.items[index];
|
|
@@ -30879,23 +30879,23 @@ var require_cst_visit = __commonJS({
|
|
|
30879
30879
|
}
|
|
30880
30880
|
return item;
|
|
30881
30881
|
};
|
|
30882
|
-
visit2.parentCollection = (cst,
|
|
30883
|
-
const parent = visit2.itemAtPath(cst,
|
|
30884
|
-
const field =
|
|
30882
|
+
visit2.parentCollection = (cst, path19) => {
|
|
30883
|
+
const parent = visit2.itemAtPath(cst, path19.slice(0, -1));
|
|
30884
|
+
const field = path19[path19.length - 1][0];
|
|
30885
30885
|
const coll = parent?.[field];
|
|
30886
30886
|
if (coll && "items" in coll)
|
|
30887
30887
|
return coll;
|
|
30888
30888
|
throw new Error("Parent collection not found");
|
|
30889
30889
|
};
|
|
30890
|
-
function _visit(
|
|
30891
|
-
let ctrl = visitor(item,
|
|
30890
|
+
function _visit(path19, item, visitor) {
|
|
30891
|
+
let ctrl = visitor(item, path19);
|
|
30892
30892
|
if (typeof ctrl === "symbol")
|
|
30893
30893
|
return ctrl;
|
|
30894
30894
|
for (const field of ["key", "value"]) {
|
|
30895
30895
|
const token = item[field];
|
|
30896
30896
|
if (token && "items" in token) {
|
|
30897
30897
|
for (let i = 0; i < token.items.length; ++i) {
|
|
30898
|
-
const ci = _visit(Object.freeze(
|
|
30898
|
+
const ci = _visit(Object.freeze(path19.concat([[field, i]])), token.items[i], visitor);
|
|
30899
30899
|
if (typeof ci === "number")
|
|
30900
30900
|
i = ci - 1;
|
|
30901
30901
|
else if (ci === BREAK)
|
|
@@ -30906,10 +30906,10 @@ var require_cst_visit = __commonJS({
|
|
|
30906
30906
|
}
|
|
30907
30907
|
}
|
|
30908
30908
|
if (typeof ctrl === "function" && field === "key")
|
|
30909
|
-
ctrl = ctrl(item,
|
|
30909
|
+
ctrl = ctrl(item, path19);
|
|
30910
30910
|
}
|
|
30911
30911
|
}
|
|
30912
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
30912
|
+
return typeof ctrl === "function" ? ctrl(item, path19) : ctrl;
|
|
30913
30913
|
}
|
|
30914
30914
|
exports.visit = visit2;
|
|
30915
30915
|
}
|
|
@@ -33725,13 +33725,13 @@ __export(skill_improvement_exports, {
|
|
|
33725
33725
|
readImprovementReport: () => readImprovementReport,
|
|
33726
33726
|
runImprovementJob: () => runImprovementJob
|
|
33727
33727
|
});
|
|
33728
|
-
import { createHash as
|
|
33728
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
33729
33729
|
import { execFile, spawn } from "node:child_process";
|
|
33730
33730
|
import { promisify } from "node:util";
|
|
33731
|
-
import { access, lstat as lstat13, mkdir as
|
|
33731
|
+
import { access, lstat as lstat13, mkdir as mkdir3, open as open9, readFile as readFile3, realpath as realpath9, rm as rm3 } from "node:fs/promises";
|
|
33732
33732
|
import { constants as constants5 } from "node:fs";
|
|
33733
|
-
import
|
|
33734
|
-
import
|
|
33733
|
+
import os6 from "node:os";
|
|
33734
|
+
import path15 from "node:path";
|
|
33735
33735
|
import { StringDecoder } from "node:string_decoder";
|
|
33736
33736
|
async function createImprovementJob(options2) {
|
|
33737
33737
|
requireSupportedImprovementHost();
|
|
@@ -33778,7 +33778,7 @@ async function createImprovementJob(options2) {
|
|
|
33778
33778
|
...suite ? { suite } : {},
|
|
33779
33779
|
executable,
|
|
33780
33780
|
executableDigest: await executableDigest(executable),
|
|
33781
|
-
runnerPin: (await
|
|
33781
|
+
runnerPin: (await readFile3(executable)).subarray(0, 2).toString() === "#!" ? "launcher-only" : "native-binary",
|
|
33782
33782
|
runnerVersion,
|
|
33783
33783
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
33784
33784
|
maxWallMinutes,
|
|
@@ -33786,8 +33786,8 @@ async function createImprovementJob(options2) {
|
|
|
33786
33786
|
...options2.registry ? { registry: options2.registry } : {}
|
|
33787
33787
|
};
|
|
33788
33788
|
const planDigest = digest4(plan);
|
|
33789
|
-
await
|
|
33790
|
-
await atomicPrivateWrite(output2,
|
|
33789
|
+
await mkdir3(output2, { mode: 448 });
|
|
33790
|
+
await atomicPrivateWrite(output2, path15.join(output2, "plan.json"), JSON.stringify({ plan, planDigest }, null, 2));
|
|
33791
33791
|
return { plan, planDigest };
|
|
33792
33792
|
}
|
|
33793
33793
|
async function runImprovementJob(options2) {
|
|
@@ -33807,7 +33807,7 @@ async function runImprovementJob(options2) {
|
|
|
33807
33807
|
return snapshot.files;
|
|
33808
33808
|
}));
|
|
33809
33809
|
if (await executableDigest(plan.executable) !== plan.executableDigest) throw new ImprovementError("Runner executable changed after planning.");
|
|
33810
|
-
const lock =
|
|
33810
|
+
const lock = path15.join(job, "started");
|
|
33811
33811
|
try {
|
|
33812
33812
|
const file2 = await open9(lock, "wx", 384);
|
|
33813
33813
|
await file2.close();
|
|
@@ -33819,7 +33819,7 @@ async function runImprovementJob(options2) {
|
|
|
33819
33819
|
const startedAt = Date.now();
|
|
33820
33820
|
const wallLimit = AbortSignal.timeout(plan.maxWallMinutes * 6e4);
|
|
33821
33821
|
const signal = options2.signal ? AbortSignal.any([options2.signal, wallLimit]) : wallLimit;
|
|
33822
|
-
const save = () => atomicPrivateWrite(job,
|
|
33822
|
+
const save = () => atomicPrivateWrite(job, path15.join(job, "report.json"), JSON.stringify(report, null, 2));
|
|
33823
33823
|
await save();
|
|
33824
33824
|
const invoke = async (payload, stage) => {
|
|
33825
33825
|
if (signal.aborted) throw new ImprovementError(wallLimit.aborted ? "Wall time budget exhausted." : "Run cancelled.");
|
|
@@ -33872,7 +33872,7 @@ async function runImprovementJob(options2) {
|
|
|
33872
33872
|
loadSkillManifestFromPackageFiles(files2);
|
|
33873
33873
|
validateCodexSkill(files2, source2.manifest.name);
|
|
33874
33874
|
if (hasBlockingFindings(scanPackageFiles(files2).findings)) throw new ImprovementError("Candidate failed the package safety scan; evaluation was not started.");
|
|
33875
|
-
await writeNewPackageTree(job,
|
|
33875
|
+
await writeNewPackageTree(job, path15.join(job, "candidate"), files2);
|
|
33876
33876
|
report.candidateDigest = treeDigest(files2);
|
|
33877
33877
|
await options2.lifecycle?.candidate(report.candidateDigest, files2);
|
|
33878
33878
|
await options2.lifecycle?.stage("propose", "completed", analysis.findings.length);
|
|
@@ -33920,7 +33920,7 @@ async function runImprovementJob(options2) {
|
|
|
33920
33920
|
async function readImprovementReport(jobPath) {
|
|
33921
33921
|
jobPath = systemAlias(jobPath);
|
|
33922
33922
|
const { planDigest } = await readPlan(jobPath);
|
|
33923
|
-
const report = JSON.parse(await readRegularText(
|
|
33923
|
+
const report = JSON.parse(await readRegularText(path15.join(jobPath, "report.json"), MAX_STATE));
|
|
33924
33924
|
if (report.schemaVersion !== 1 || report.provenance !== "local-report" || report.planDigest !== planDigest) throw new ImprovementError("Report does not match the accepted plan.");
|
|
33925
33925
|
return report;
|
|
33926
33926
|
}
|
|
@@ -33928,7 +33928,7 @@ async function exportImprovementCandidate(options2) {
|
|
|
33928
33928
|
const { plan } = await readPlan(options2.jobPath);
|
|
33929
33929
|
const report = await readImprovementReport(options2.jobPath);
|
|
33930
33930
|
if (report.state !== "completed" || !report.candidateDigest) throw new ImprovementError("Only a completed candidate can be exported for review.");
|
|
33931
|
-
const snapshot = await checkedPackage(
|
|
33931
|
+
const snapshot = await checkedPackage(path15.join(options2.jobPath, "candidate"));
|
|
33932
33932
|
if (treeDigest(snapshot.files) !== report.candidateDigest) throw new ImprovementError("Candidate digest changed since evaluation.");
|
|
33933
33933
|
if (snapshot.manifest.version !== plan.targetVersion) throw new ImprovementError("Candidate identity does not match the plan.");
|
|
33934
33934
|
const output2 = await destination(options2.outputPath);
|
|
@@ -33938,7 +33938,7 @@ async function exportImprovementCandidate(options2) {
|
|
|
33938
33938
|
}
|
|
33939
33939
|
async function readImprovementPlan(job) {
|
|
33940
33940
|
job = systemAlias(job);
|
|
33941
|
-
const value = JSON.parse(await readRegularText(
|
|
33941
|
+
const value = JSON.parse(await readRegularText(path15.join(job, "plan.json"), MAX_STATE));
|
|
33942
33942
|
if (isRecord7(value) && isRecord7(value.plan) && value.plan.adapter === "codex-text-v1") throw new ImprovementError("This job was planned for the retired codex-text-v1 adapter. Codex execution is disabled until it passes a future isolation gate; create a new plan for Claude Code. No fallback runner is used.");
|
|
33943
33943
|
if (!isRecord7(value) || !isRecord7(value.plan) || value.plan.schemaVersion !== 1 || value.plan.adapter !== "claude-code-text-v1" || digest4(value.plan) !== value.planDigest) throw new ImprovementError("Plan digest is invalid or the plan changed.");
|
|
33944
33944
|
return value;
|
|
@@ -33985,21 +33985,21 @@ function validateAnalysis(value) {
|
|
|
33985
33985
|
return { disposition: value.disposition, findings: value.findings.map((f) => ({ id: f.id, severity: f.severity, summary: f.summary })), changes: value.changes.map((f) => ({ path: f.path, content: f.content })), rationale: value.rationale };
|
|
33986
33986
|
}
|
|
33987
33987
|
async function destination(input2) {
|
|
33988
|
-
const absolute2 =
|
|
33989
|
-
const parent = await realpath9(
|
|
33988
|
+
const absolute2 = path15.resolve(input2);
|
|
33989
|
+
const parent = await realpath9(path15.dirname(absolute2));
|
|
33990
33990
|
await assertRegularDirectory(parent);
|
|
33991
|
-
return
|
|
33991
|
+
return path15.join(parent, path15.basename(absolute2));
|
|
33992
33992
|
}
|
|
33993
33993
|
function systemAlias(input2) {
|
|
33994
|
-
const absolute2 =
|
|
33994
|
+
const absolute2 = path15.resolve(input2);
|
|
33995
33995
|
if (process.platform === "darwin" && ["/tmp", "/var", "/etc"].some((prefix) => absolute2 === prefix || absolute2.startsWith(prefix + "/"))) return "/private" + absolute2;
|
|
33996
33996
|
return absolute2;
|
|
33997
33997
|
}
|
|
33998
33998
|
function assertSeparate(a, b) {
|
|
33999
|
-
if (a === b || a.startsWith(b +
|
|
33999
|
+
if (a === b || a.startsWith(b + path15.sep) || b.startsWith(a + path15.sep)) throw new ImprovementError("Job and export paths must not overlap source, reviewer, or job directories.");
|
|
34000
34000
|
}
|
|
34001
34001
|
async function resolveExecutable(input2) {
|
|
34002
|
-
const candidates = input2.includes(
|
|
34002
|
+
const candidates = input2.includes(path15.sep) ? [path15.resolve(input2)] : (process.env.PATH ?? "").split(path15.delimiter).filter(Boolean).map((p) => path15.join(p, input2));
|
|
34003
34003
|
for (const candidate of candidates) {
|
|
34004
34004
|
try {
|
|
34005
34005
|
const resolved = await realpath9(candidate);
|
|
@@ -34012,10 +34012,10 @@ async function resolveExecutable(input2) {
|
|
|
34012
34012
|
throw new ImprovementError("Claude Code executable is unavailable. Install Claude Code and sign in with your existing account before planning a run.");
|
|
34013
34013
|
}
|
|
34014
34014
|
async function executableDigest(executable) {
|
|
34015
|
-
return
|
|
34015
|
+
return createHash8("sha256").update(await readFile3(executable)).digest("hex");
|
|
34016
34016
|
}
|
|
34017
34017
|
function claudeEnvironment(tmp) {
|
|
34018
|
-
const env = { PATH: process.env.PATH, HOME:
|
|
34018
|
+
const env = { PATH: process.env.PATH, HOME: os6.homedir(), TMPDIR: tmp, LANG: "en_US.UTF-8" };
|
|
34019
34019
|
for (const name of ["USER", "LOGNAME", "SHELL", "CLAUDE_CONFIG_DIR"]) if (process.env[name]) env[name] = process.env[name];
|
|
34020
34020
|
return env;
|
|
34021
34021
|
}
|
|
@@ -34027,7 +34027,7 @@ async function inspectImprovementRunner(input2) {
|
|
|
34027
34027
|
const executable = await resolveExecutable(input2 ?? "claude");
|
|
34028
34028
|
let version2;
|
|
34029
34029
|
try {
|
|
34030
|
-
const { stdout: stdout2 } = await promisify(execFile)(executable, ["--version"], { timeout: 1e4, maxBuffer: 4096, encoding: "utf8", env: claudeEnvironment(
|
|
34030
|
+
const { stdout: stdout2 } = await promisify(execFile)(executable, ["--version"], { timeout: 1e4, maxBuffer: 4096, encoding: "utf8", env: claudeEnvironment(os6.tmpdir()) });
|
|
34031
34031
|
version2 = /^([0-9]+\.[0-9]+\.[0-9]+) \(Claude Code\)\s*$/.exec(stdout2)?.[1];
|
|
34032
34032
|
} catch {
|
|
34033
34033
|
}
|
|
@@ -34087,8 +34087,8 @@ function claudeEventViolation(state, event, model, runnerVersion) {
|
|
|
34087
34087
|
return claudeFailure.invalid;
|
|
34088
34088
|
}
|
|
34089
34089
|
async function invokeClaude(plan, job, call, payload, stage, signal) {
|
|
34090
|
-
const scratch =
|
|
34091
|
-
await
|
|
34090
|
+
const scratch = path15.join(job, `call-${call}`);
|
|
34091
|
+
await mkdir3(scratch, { mode: 448 });
|
|
34092
34092
|
const string4 = { type: "string" };
|
|
34093
34093
|
const schema = stage === "evaluate" ? { type: "object", additionalProperties: false, properties: { response: string4 }, required: ["response"] } : {
|
|
34094
34094
|
type: "object",
|
|
@@ -34217,7 +34217,7 @@ async function invokeClaude(plan, job, call, payload, stage, signal) {
|
|
|
34217
34217
|
if (JSON.stringify(state.value).length > MAX_OUTPUT) throw new ImprovementError("Runner output limit exceeded.");
|
|
34218
34218
|
return { value: state.value, observedModel: plan.model };
|
|
34219
34219
|
} finally {
|
|
34220
|
-
await
|
|
34220
|
+
await rm3(scratch, { recursive: true, force: true });
|
|
34221
34221
|
}
|
|
34222
34222
|
}
|
|
34223
34223
|
var ImprovementError, MAX_OUTPUT, MAX_STATE, MAX_STREAM, MAX_EVENT, digest4, treeDigest, readPlan, MINIMUM_CLAUDE_VERSION, CLAUDE_SYSTEM_PROMPT, allowedClaudePlugins, claudeFailure;
|
|
@@ -34233,7 +34233,7 @@ var init_skill_improvement = __esm({
|
|
|
34233
34233
|
MAX_STATE = 8 * 1024 * 1024;
|
|
34234
34234
|
MAX_STREAM = 16 * 1024 * 1024;
|
|
34235
34235
|
MAX_EVENT = 4 * 1024 * 1024;
|
|
34236
|
-
digest4 = (value) =>
|
|
34236
|
+
digest4 = (value) => createHash8("sha256").update(JSON.stringify(value)).digest("hex");
|
|
34237
34237
|
treeDigest = (files2) => digest4({ files: [...files2].sort((a, b) => a.path.localeCompare(b.path)) });
|
|
34238
34238
|
readPlan = readImprovementPlan;
|
|
34239
34239
|
MINIMUM_CLAUDE_VERSION = [2, 1, 283];
|
|
@@ -34260,9 +34260,9 @@ __export(skill_improvement_registry_exports, {
|
|
|
34260
34260
|
shareImprovementEvidence: () => shareImprovementEvidence,
|
|
34261
34261
|
shareRecordedImprovementEvidence: () => shareRecordedImprovementEvidence
|
|
34262
34262
|
});
|
|
34263
|
-
import { createHash as
|
|
34264
|
-
import { mkdir as
|
|
34265
|
-
import
|
|
34263
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
34264
|
+
import { mkdir as mkdir4, realpath as realpath10 } from "node:fs/promises";
|
|
34265
|
+
import path16 from "node:path";
|
|
34266
34266
|
async function fetchImprovementJob(api, input2) {
|
|
34267
34267
|
const response = await api.get(`${base2}/plans/${encodeURIComponent(input2.planId)}`);
|
|
34268
34268
|
const record5 = checkedRecord(response.plan, input2.planId);
|
|
@@ -34297,14 +34297,14 @@ async function fetchImprovementJob(api, input2) {
|
|
|
34297
34297
|
if (snapshot.artifact.sha256 !== pin.artifactSha256) throw new Error("A downloaded release differs from the prepared artifact digest.");
|
|
34298
34298
|
return snapshot;
|
|
34299
34299
|
}));
|
|
34300
|
-
const output2 =
|
|
34300
|
+
const output2 = path16.join(await realpath10(path16.dirname(path16.resolve(input2.outputPath))), path16.basename(input2.outputPath));
|
|
34301
34301
|
const inputs = `${output2}.inputs`;
|
|
34302
|
-
await
|
|
34303
|
-
const sourcePath =
|
|
34302
|
+
await mkdir4(inputs, { mode: 448 });
|
|
34303
|
+
const sourcePath = path16.join(inputs, "source");
|
|
34304
34304
|
await writeNewPackageTree(inputs, sourcePath, snapshots[0].files);
|
|
34305
34305
|
const reviewerPaths = [];
|
|
34306
34306
|
for (let i = 1; i < snapshots.length; i += 1) {
|
|
34307
|
-
const dir =
|
|
34307
|
+
const dir = path16.join(inputs, `reviewer-${i}`);
|
|
34308
34308
|
await writeNewPackageTree(inputs, dir, snapshots[i].files);
|
|
34309
34309
|
reviewerPaths.push(dir);
|
|
34310
34310
|
}
|
|
@@ -34340,7 +34340,7 @@ async function registryLifecycle(api, jobPath, coordinatorVersion) {
|
|
|
34340
34340
|
let runId;
|
|
34341
34341
|
let sequence = 0;
|
|
34342
34342
|
const jobRoot = await realpath10(jobPath);
|
|
34343
|
-
const statePath =
|
|
34343
|
+
const statePath = path16.join(jobRoot, "registry-run.json");
|
|
34344
34344
|
const save = async (reportSha256) => atomicPrivateWrite(jobRoot, statePath, JSON.stringify({ planDigest, planId: binding.planId, runId, sequence, reportSha256: reportSha256 ?? null }, null, 2));
|
|
34345
34345
|
const event = async (value) => {
|
|
34346
34346
|
if (!runId) throw new Error("The registry run has not started.");
|
|
@@ -34443,7 +34443,7 @@ async function shareImprovementEvidence(api, input2) {
|
|
|
34443
34443
|
if (!plan.registry || plan.registry.apiUrl !== api.apiUrl) throw new Error("Evidence sharing requires the original registry endpoint and plan.");
|
|
34444
34444
|
if (plan.registry.record.plan.resultSharing === "local-only") throw new Error("This plan is local-only; evidence sharing was not authorized.");
|
|
34445
34445
|
if (input2.disclosure !== "summary") throw new Error("This adapter shares summary evidence only. Raw findings stay local.");
|
|
34446
|
-
const state = JSON.parse(await readRegularText(
|
|
34446
|
+
const state = JSON.parse(await readRegularText(path16.join(await realpath10(input2.jobPath), "registry-run.json"), 64e3));
|
|
34447
34447
|
if (!state || state.planDigest !== planDigest || typeof state.runId !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:@+-]{0,127}$/.test(state.runId) || typeof state.reportSha256 !== "string" || !/^[0-9a-f]{64}$/.test(state.reportSha256)) throw new Error("No confirmed registry completion is available to share.");
|
|
34448
34448
|
return postImprovementEvidence(api, state.runId, state.reportSha256, input2.disclosure, input2.proposals);
|
|
34449
34449
|
}
|
|
@@ -34460,7 +34460,7 @@ var init_skill_improvement_registry = __esm({
|
|
|
34460
34460
|
init_dist();
|
|
34461
34461
|
init_install_filesystem();
|
|
34462
34462
|
init_skill_improvement();
|
|
34463
|
-
hash2 = (value) =>
|
|
34463
|
+
hash2 = (value) => createHash9("sha256").update(canonicalizeJson(value)).digest("hex");
|
|
34464
34464
|
base2 = "/v1/improvements";
|
|
34465
34465
|
}
|
|
34466
34466
|
});
|
|
@@ -34531,9 +34531,9 @@ function option(input2, key) {
|
|
|
34531
34531
|
if (typeof value !== "string" || !value) throw new Error(`--${key} requires a file.`);
|
|
34532
34532
|
return value;
|
|
34533
34533
|
}
|
|
34534
|
-
async function readInput(context,
|
|
34534
|
+
async function readInput(context, path19) {
|
|
34535
34535
|
try {
|
|
34536
|
-
return await context.readInput(
|
|
34536
|
+
return await context.readInput(path19);
|
|
34537
34537
|
} catch {
|
|
34538
34538
|
throw new Error("Evaluation input must be a bounded valid JSON object.");
|
|
34539
34539
|
}
|
|
@@ -35045,52 +35045,466 @@ function decodeResponseUtf8(bytes2) {
|
|
|
35045
35045
|
}
|
|
35046
35046
|
}
|
|
35047
35047
|
|
|
35048
|
+
// src/device-login-store.ts
|
|
35049
|
+
init_install_filesystem();
|
|
35050
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
35051
|
+
import os5 from "node:os";
|
|
35052
|
+
import path9 from "node:path";
|
|
35053
|
+
|
|
35054
|
+
// src/token-store.ts
|
|
35055
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
35056
|
+
import { chmod, mkdir as mkdir2, readFile, rm as rm2, writeFile } from "node:fs/promises";
|
|
35057
|
+
import os4 from "node:os";
|
|
35058
|
+
import path8 from "node:path";
|
|
35059
|
+
var KEYRING_SERVICE = "ai.jarel.myskills.cli";
|
|
35060
|
+
function createTokenStore(env = process.env, namespace) {
|
|
35061
|
+
const fileStore = createFileTokenStore(env);
|
|
35062
|
+
if (env.MYSKILLS_TOKEN_STORE === "file" || env.MYSKILLS_TOKEN_FILE) {
|
|
35063
|
+
return fileStore;
|
|
35064
|
+
}
|
|
35065
|
+
return createKeyringTokenStore(fileStore, void 0, namespace);
|
|
35066
|
+
}
|
|
35067
|
+
function createFileTokenStore(env = process.env) {
|
|
35068
|
+
const filePath = tokenFilePath(env);
|
|
35069
|
+
return {
|
|
35070
|
+
async get(apiUrl) {
|
|
35071
|
+
return (await readPayload(filePath)).tokens[normalizeApiUrl(apiUrl)] ?? null;
|
|
35072
|
+
},
|
|
35073
|
+
async set(apiUrl, token) {
|
|
35074
|
+
const payload = await readPayload(filePath);
|
|
35075
|
+
payload.tokens[normalizeApiUrl(apiUrl)] = token;
|
|
35076
|
+
await writePayload(filePath, payload);
|
|
35077
|
+
},
|
|
35078
|
+
async delete(apiUrl) {
|
|
35079
|
+
const payload = await readPayload(filePath);
|
|
35080
|
+
delete payload.tokens[normalizeApiUrl(apiUrl)];
|
|
35081
|
+
if (Object.keys(payload.tokens).length === 0) {
|
|
35082
|
+
await rm2(filePath, { force: true });
|
|
35083
|
+
return;
|
|
35084
|
+
}
|
|
35085
|
+
await writePayload(filePath, payload);
|
|
35086
|
+
},
|
|
35087
|
+
describe() {
|
|
35088
|
+
return {
|
|
35089
|
+
backend: "file",
|
|
35090
|
+
filePath
|
|
35091
|
+
};
|
|
35092
|
+
}
|
|
35093
|
+
};
|
|
35094
|
+
}
|
|
35095
|
+
function createKeyringTokenStore(fallback, backend = nativeKeyringBackend, namespace) {
|
|
35096
|
+
const credentialKey = (apiUrl) => keyringCredentialKey(apiUrl, namespace);
|
|
35097
|
+
let usedFallback = false;
|
|
35098
|
+
return {
|
|
35099
|
+
async get(apiUrl) {
|
|
35100
|
+
let raw;
|
|
35101
|
+
try {
|
|
35102
|
+
raw = await backend.get(credentialKey(apiUrl));
|
|
35103
|
+
} catch {
|
|
35104
|
+
throw new Error("Cannot read the OS keyring. Unlock or restore keyring access, or explicitly select MYSKILLS_TOKEN_STORE=file.");
|
|
35105
|
+
}
|
|
35106
|
+
if (raw === null) {
|
|
35107
|
+
const token2 = await fallback.get(apiUrl);
|
|
35108
|
+
usedFallback = token2 !== null;
|
|
35109
|
+
return token2;
|
|
35110
|
+
}
|
|
35111
|
+
let token;
|
|
35112
|
+
try {
|
|
35113
|
+
token = parseStoredToken(JSON.parse(raw));
|
|
35114
|
+
} catch {
|
|
35115
|
+
token = null;
|
|
35116
|
+
}
|
|
35117
|
+
if (!token) {
|
|
35118
|
+
throw new Error("The OS keyring credential has an invalid format. Remove it with myskills logout, then log in again.");
|
|
35119
|
+
}
|
|
35120
|
+
usedFallback = false;
|
|
35121
|
+
return token;
|
|
35122
|
+
},
|
|
35123
|
+
async set(apiUrl, token) {
|
|
35124
|
+
try {
|
|
35125
|
+
await backend.set(credentialKey(apiUrl), JSON.stringify(token));
|
|
35126
|
+
} catch {
|
|
35127
|
+
throw new Error("Cannot save the token in the OS keyring. Unlock or restore keyring access, or explicitly select MYSKILLS_TOKEN_STORE=file.");
|
|
35128
|
+
}
|
|
35129
|
+
usedFallback = false;
|
|
35130
|
+
try {
|
|
35131
|
+
await fallback.delete(apiUrl);
|
|
35132
|
+
} catch {
|
|
35133
|
+
throw new Error("The token was saved in the OS keyring, but the older file credential could not be removed. Token storage cleanup is incomplete.");
|
|
35134
|
+
}
|
|
35135
|
+
},
|
|
35136
|
+
async delete(apiUrl) {
|
|
35137
|
+
const results = await Promise.allSettled([backend.delete(credentialKey(apiUrl)), fallback.delete(apiUrl)]);
|
|
35138
|
+
const failed = results.flatMap((result, index) => result.status === "rejected" ? [index === 0 ? "OS keyring" : "file"] : []);
|
|
35139
|
+
if (failed.length > 0) {
|
|
35140
|
+
throw new Error(`Logout cleanup is incomplete: could not remove the ${failed.join(" and ")} credential. Restore storage access and retry logout.`);
|
|
35141
|
+
}
|
|
35142
|
+
usedFallback = false;
|
|
35143
|
+
},
|
|
35144
|
+
async describe() {
|
|
35145
|
+
const fallbackInfo = await fallback.describe?.();
|
|
35146
|
+
if (usedFallback && fallbackInfo) {
|
|
35147
|
+
return fallbackInfo;
|
|
35148
|
+
}
|
|
35149
|
+
return {
|
|
35150
|
+
backend: "keyring",
|
|
35151
|
+
fallbackFilePath: fallbackInfo?.filePath
|
|
35152
|
+
};
|
|
35153
|
+
}
|
|
35154
|
+
};
|
|
35155
|
+
}
|
|
35156
|
+
var nativeKeyringBackend = {
|
|
35157
|
+
async get(apiUrl) {
|
|
35158
|
+
const { Entry } = await import("@napi-rs/keyring");
|
|
35159
|
+
return new Entry(KEYRING_SERVICE, keyringAccount(apiUrl)).getPassword();
|
|
35160
|
+
},
|
|
35161
|
+
async set(apiUrl, raw) {
|
|
35162
|
+
const { Entry } = await import("@napi-rs/keyring");
|
|
35163
|
+
new Entry(KEYRING_SERVICE, keyringAccount(apiUrl)).setPassword(raw);
|
|
35164
|
+
},
|
|
35165
|
+
async delete(apiUrl) {
|
|
35166
|
+
const { Entry } = await import("@napi-rs/keyring");
|
|
35167
|
+
new Entry(KEYRING_SERVICE, keyringAccount(apiUrl)).deletePassword();
|
|
35168
|
+
}
|
|
35169
|
+
};
|
|
35170
|
+
function keyringCredentialKey(apiUrl, namespace) {
|
|
35171
|
+
const prefix = namespace === void 0 ? "" : `config-profile:${createHash4("sha256").update(namespace).digest("hex")}:`;
|
|
35172
|
+
return `${prefix}${normalizeApiUrl(apiUrl)}`;
|
|
35173
|
+
}
|
|
35174
|
+
function tokenFilePath(env) {
|
|
35175
|
+
if (env.MYSKILLS_TOKEN_FILE) {
|
|
35176
|
+
return path8.resolve(env.MYSKILLS_TOKEN_FILE);
|
|
35177
|
+
}
|
|
35178
|
+
if (env.MYSKILLS_CONFIG_DIR) {
|
|
35179
|
+
return path8.join(path8.resolve(env.MYSKILLS_CONFIG_DIR), "tokens.json");
|
|
35180
|
+
}
|
|
35181
|
+
const baseDir = env.XDG_CONFIG_HOME ? path8.join(env.XDG_CONFIG_HOME, "myskills-app") : path8.join(os4.homedir(), ".config", "myskills-app");
|
|
35182
|
+
return path8.join(baseDir, "tokens.json");
|
|
35183
|
+
}
|
|
35184
|
+
async function readPayload(filePath) {
|
|
35185
|
+
try {
|
|
35186
|
+
const raw = await readFile(filePath, "utf8");
|
|
35187
|
+
return parsePayload(raw);
|
|
35188
|
+
} catch (error62) {
|
|
35189
|
+
if (isNodeError(error62) && error62.code === "ENOENT") {
|
|
35190
|
+
return { version: 1, tokens: {} };
|
|
35191
|
+
}
|
|
35192
|
+
throw error62;
|
|
35193
|
+
}
|
|
35194
|
+
}
|
|
35195
|
+
async function writePayload(filePath, payload) {
|
|
35196
|
+
await mkdir2(path8.dirname(filePath), { recursive: true, mode: 448 });
|
|
35197
|
+
await writeFile(filePath, `${JSON.stringify(payload, null, 2)}
|
|
35198
|
+
`, { mode: 384 });
|
|
35199
|
+
await chmod(filePath, 384);
|
|
35200
|
+
}
|
|
35201
|
+
function parsePayload(raw) {
|
|
35202
|
+
let parsed;
|
|
35203
|
+
try {
|
|
35204
|
+
parsed = JSON.parse(raw);
|
|
35205
|
+
} catch {
|
|
35206
|
+
throw new Error("Token store file contains invalid JSON. Repair or remove the file before logging in again.");
|
|
35207
|
+
}
|
|
35208
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
35209
|
+
throw new Error("Token store file must contain a JSON object.");
|
|
35210
|
+
}
|
|
35211
|
+
const record5 = parsed;
|
|
35212
|
+
if (record5.version !== 1 || !record5.tokens || typeof record5.tokens !== "object" || Array.isArray(record5.tokens)) {
|
|
35213
|
+
throw new Error("Token store file has an unsupported format.");
|
|
35214
|
+
}
|
|
35215
|
+
const tokens = {};
|
|
35216
|
+
for (const [apiUrl, token] of Object.entries(record5.tokens)) {
|
|
35217
|
+
const parsedToken = parseStoredToken(token);
|
|
35218
|
+
if (parsedToken) {
|
|
35219
|
+
tokens[normalizeApiUrl(apiUrl)] = parsedToken;
|
|
35220
|
+
}
|
|
35221
|
+
}
|
|
35222
|
+
return { version: 1, tokens };
|
|
35223
|
+
}
|
|
35224
|
+
function parseStoredToken(input2) {
|
|
35225
|
+
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) {
|
|
35226
|
+
return null;
|
|
35227
|
+
}
|
|
35228
|
+
const record5 = input2;
|
|
35229
|
+
if (record5.kind !== "session" && record5.kind !== "api" || typeof record5.token !== "string" || !record5.token) {
|
|
35230
|
+
return null;
|
|
35231
|
+
}
|
|
35232
|
+
return {
|
|
35233
|
+
kind: record5.kind,
|
|
35234
|
+
token: record5.token,
|
|
35235
|
+
email: typeof record5.email === "string" ? record5.email : void 0,
|
|
35236
|
+
expiresAt: typeof record5.expiresAt === "string" ? record5.expiresAt : void 0
|
|
35237
|
+
};
|
|
35238
|
+
}
|
|
35239
|
+
function normalizeApiUrl(apiUrl) {
|
|
35240
|
+
return apiUrl.replace(/\/+$/, "");
|
|
35241
|
+
}
|
|
35242
|
+
function keyringAccount(apiUrl) {
|
|
35243
|
+
return `api-url:${Buffer.from(normalizeApiUrl(apiUrl)).toString("base64url")}`;
|
|
35244
|
+
}
|
|
35245
|
+
function isNodeError(error62) {
|
|
35246
|
+
return error62 instanceof Error && "code" in error62;
|
|
35247
|
+
}
|
|
35248
|
+
|
|
35249
|
+
// src/device-login-store.ts
|
|
35250
|
+
var DeviceLoginError = class extends Error {
|
|
35251
|
+
constructor(message, code) {
|
|
35252
|
+
super(message);
|
|
35253
|
+
this.code = code;
|
|
35254
|
+
}
|
|
35255
|
+
code;
|
|
35256
|
+
};
|
|
35257
|
+
function createDeviceLoginStore(namespace, backend = nativeKeyringBackend, lockDirectory) {
|
|
35258
|
+
const key = (apiUrl) => `device-login:${keyringCredentialKey(apiUrl, namespace)}`;
|
|
35259
|
+
return {
|
|
35260
|
+
async get(apiUrl) {
|
|
35261
|
+
let raw;
|
|
35262
|
+
try {
|
|
35263
|
+
raw = await backend.get(key(apiUrl));
|
|
35264
|
+
} catch {
|
|
35265
|
+
throw unavailable();
|
|
35266
|
+
}
|
|
35267
|
+
if (raw === null) return null;
|
|
35268
|
+
try {
|
|
35269
|
+
if (raw.length > 16384) throw new Error();
|
|
35270
|
+
const value = JSON.parse(raw);
|
|
35271
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error();
|
|
35272
|
+
return value;
|
|
35273
|
+
} catch {
|
|
35274
|
+
throw new DeviceLoginError("The pending browser login is invalid. Run myskills logout for this API and configuration profile, then log in again.", "DEVICE_LOGIN_STATE_INVALID");
|
|
35275
|
+
}
|
|
35276
|
+
},
|
|
35277
|
+
async set(apiUrl, request) {
|
|
35278
|
+
try {
|
|
35279
|
+
await backend.set(key(apiUrl), JSON.stringify(request));
|
|
35280
|
+
} catch {
|
|
35281
|
+
throw unavailable();
|
|
35282
|
+
}
|
|
35283
|
+
},
|
|
35284
|
+
async delete(apiUrl) {
|
|
35285
|
+
try {
|
|
35286
|
+
await backend.delete(key(apiUrl));
|
|
35287
|
+
} catch {
|
|
35288
|
+
throw new DeviceLoginError("Pending browser login cleanup failed. Restore OS keyring access and retry logout for this API and configuration profile.", "DEVICE_LOGIN_CLEANUP_FAILED");
|
|
35289
|
+
}
|
|
35290
|
+
},
|
|
35291
|
+
async withLock(apiUrl, work) {
|
|
35292
|
+
const directory = path9.join(lockDirectory ?? deviceLoginLockDirectory(), createHash5("sha256").update(key(apiUrl)).digest("hex"));
|
|
35293
|
+
let acquired = false;
|
|
35294
|
+
try {
|
|
35295
|
+
return await withInstallRootLock(directory, async () => {
|
|
35296
|
+
acquired = true;
|
|
35297
|
+
return work();
|
|
35298
|
+
});
|
|
35299
|
+
} catch (error62) {
|
|
35300
|
+
if (acquired) throw error62;
|
|
35301
|
+
throw new DeviceLoginError("Browser login is busy or its process lock could not be acquired. Wait for the other command to exit and retry; preserve an ambiguous lock for operator recovery.", "DEVICE_LOGIN_BUSY");
|
|
35302
|
+
}
|
|
35303
|
+
}
|
|
35304
|
+
};
|
|
35305
|
+
}
|
|
35306
|
+
function deviceLoginLockDirectory() {
|
|
35307
|
+
try {
|
|
35308
|
+
const home = os5.userInfo().homedir;
|
|
35309
|
+
if (!path9.isAbsolute(home)) throw new Error();
|
|
35310
|
+
return path9.join(home, ".config", "myskills-app", "device-login-locks");
|
|
35311
|
+
} catch {
|
|
35312
|
+
throw new DeviceLoginError("Cannot determine the OS-account home for secure browser-login locking. Configure a valid OS account before browser login or logout; HOME overrides are not used.", "DEVICE_LOGIN_LOCK_UNAVAILABLE");
|
|
35313
|
+
}
|
|
35314
|
+
}
|
|
35315
|
+
function unavailable() {
|
|
35316
|
+
return new DeviceLoginError("Cannot access secure pending-login storage in the OS keyring. Unlock or restore keyring access, or explicitly use login --method browser --no-resume for an in-memory request.", "DEVICE_LOGIN_STORE_UNAVAILABLE");
|
|
35317
|
+
}
|
|
35318
|
+
|
|
35048
35319
|
// src/device-login.ts
|
|
35049
|
-
async function browserDeviceLogin(apiUrl, scopes, runtime) {
|
|
35050
|
-
|
|
35051
|
-
|
|
35052
|
-
|
|
35053
|
-
|
|
35054
|
-
|
|
35055
|
-
|
|
35056
|
-
|
|
35057
|
-
|
|
35058
|
-
|
|
35059
|
-
|
|
35320
|
+
async function browserDeviceLogin(apiUrl, scopes, runtime, noResume = false) {
|
|
35321
|
+
apiUrl = apiUrl.replace(/\/+$/, "");
|
|
35322
|
+
const api = safeUrl(apiUrl);
|
|
35323
|
+
if (api.username || api.password || api.search || api.hash) throw invalidResponse();
|
|
35324
|
+
if (!noResume && !runtime.deviceLoginStore) throw new DeviceLoginError("No secure pending-login store is configured. Use login --method browser --no-resume explicitly for an in-memory request.", "DEVICE_LOGIN_STORE_UNAVAILABLE");
|
|
35325
|
+
const controller = new AbortController();
|
|
35326
|
+
const interrupt = () => controller.abort();
|
|
35327
|
+
process.once("SIGINT", interrupt);
|
|
35328
|
+
process.once("SIGTERM", interrupt);
|
|
35329
|
+
const signal = runtime.deviceLogin?.signal ? AbortSignal.any([controller.signal, runtime.deviceLogin.signal]) : controller.signal;
|
|
35330
|
+
const now = runtime.deviceLogin?.now ?? Date.now;
|
|
35331
|
+
const sleep = runtime.deviceLogin?.sleep ?? ((milliseconds, abort) => delay(milliseconds, void 0, { signal: abort }));
|
|
35332
|
+
const store = noResume ? void 0 : runtime.deviceLoginStore;
|
|
35333
|
+
const requestedScopes = scopes ? [...new Set(scopes)].sort() : null;
|
|
35334
|
+
let request;
|
|
35335
|
+
async function post(path19, body, deadline) {
|
|
35336
|
+
const budget = deadline === void 0 ? 15e3 : Math.min(15e3, deadline - now());
|
|
35337
|
+
if (budget <= 0) throw expired();
|
|
35338
|
+
const abort = AbortSignal.any([signal, AbortSignal.timeout(Math.max(1, Math.floor(budget)))]);
|
|
35339
|
+
try {
|
|
35340
|
+
const response = await runtime.fetch(`${apiUrl}/v1/auth/device/${path19}`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body), signal: abort, redirect: "error" });
|
|
35341
|
+
if (!response.ok) throw new DeviceLoginError(`Browser login request failed (HTTP ${response.status}). Retry before the original deadline if a pending request exists.`, "DEVICE_LOGIN_REQUEST_FAILED");
|
|
35342
|
+
const text = decodeResponseUtf8(await readBoundedResponse(response, 16384, abort));
|
|
35343
|
+
let result;
|
|
35344
|
+
try {
|
|
35345
|
+
result = JSON.parse(text);
|
|
35346
|
+
} catch {
|
|
35347
|
+
throw invalidResponse();
|
|
35348
|
+
}
|
|
35349
|
+
if (!result || typeof result !== "object" || Array.isArray(result)) throw invalidResponse();
|
|
35350
|
+
return result;
|
|
35351
|
+
} catch (error62) {
|
|
35352
|
+
if (error62 instanceof DeviceLoginError) throw error62;
|
|
35353
|
+
if (deadline !== void 0 && now() >= deadline) throw expired();
|
|
35354
|
+
throw interrupted();
|
|
35355
|
+
}
|
|
35060
35356
|
}
|
|
35061
|
-
|
|
35062
|
-
|
|
35063
|
-
|
|
35064
|
-
|
|
35065
|
-
|
|
35066
|
-
const deadline = Date.now() + request.expiresIn * 1e3;
|
|
35067
|
-
runtime.io.stdout(`Open ${verification.href} and enter device code ${request.userCode}.`);
|
|
35068
|
-
runtime.io.stdout("Review the permissions in your browser. Waiting for your decision\u2026");
|
|
35069
|
-
while (Date.now() < deadline) {
|
|
35070
|
-
await delay(Math.min(interval * 1e3, Math.max(1, deadline - Date.now())));
|
|
35071
|
-
if (Date.now() >= deadline) break;
|
|
35072
|
-
const result = await post("poll", { deviceCode: request.deviceCode });
|
|
35073
|
-
if (result.status === "pending" || result.status === "slow_down") {
|
|
35074
|
-
interval = pollInterval(result.interval);
|
|
35075
|
-
continue;
|
|
35357
|
+
async function clearPending(outcome) {
|
|
35358
|
+
try {
|
|
35359
|
+
await store?.delete(apiUrl);
|
|
35360
|
+
} catch {
|
|
35361
|
+
throw new DeviceLoginError(`${outcome?.message ?? "The credential was saved."} Pending browser login cleanup failed; restore OS keyring access and retry logout.`, outcome?.code ?? "DEVICE_LOGIN_CLEANUP_FAILED");
|
|
35076
35362
|
}
|
|
35077
|
-
|
|
35078
|
-
|
|
35079
|
-
|
|
35080
|
-
|
|
35081
|
-
|
|
35082
|
-
|
|
35083
|
-
|
|
35363
|
+
}
|
|
35364
|
+
async function run() {
|
|
35365
|
+
if (signal.aborted) throw interrupted();
|
|
35366
|
+
if (noResume && runtime.deviceLoginStore) {
|
|
35367
|
+
let previous2;
|
|
35368
|
+
try {
|
|
35369
|
+
previous2 = await runtime.deviceLoginStore.get(apiUrl);
|
|
35370
|
+
} catch (error63) {
|
|
35371
|
+
if (!(error63 instanceof DeviceLoginError) || error63.code !== "DEVICE_LOGIN_STORE_UNAVAILABLE") throw error63;
|
|
35372
|
+
previous2 = null;
|
|
35373
|
+
runtime.io.stdout("Secure pending state could not be checked. Run logout after keyring access returns before using resumable login again.");
|
|
35374
|
+
}
|
|
35375
|
+
if (previous2 !== null) throw new DeviceLoginError("A pending browser login already exists. Run myskills logout for this API and configuration profile before starting an independent --no-resume request.", "DEVICE_LOGIN_PENDING_EXISTS");
|
|
35376
|
+
}
|
|
35377
|
+
const previous = await store?.get(apiUrl);
|
|
35378
|
+
if (previous !== null && previous !== void 0) {
|
|
35379
|
+
request = pendingRequest(previous);
|
|
35380
|
+
if (Math.min(Date.parse(request.expiresAt), request.deadline) <= now()) {
|
|
35381
|
+
const error63 = expired();
|
|
35382
|
+
await clearPending(error63);
|
|
35383
|
+
throw error63;
|
|
35384
|
+
}
|
|
35385
|
+
if (Date.parse(request.expiresAt) > now() + 6e5) throw invalidState();
|
|
35386
|
+
if (JSON.stringify(request.scopes) !== JSON.stringify(requestedScopes)) throw new DeviceLoginError("A pending browser login requests different scopes. Repeat the same --scopes choice, or run myskills logout for this API and configuration profile before starting a new request.", "DEVICE_LOGIN_SCOPES_MISMATCH");
|
|
35387
|
+
runtime.io.stdout("Resuming the pending browser login.");
|
|
35388
|
+
} else {
|
|
35389
|
+
if (noResume) runtime.io.stdout("Browser login resume is disabled. Interruption requires a new code.");
|
|
35390
|
+
const startedAt = now();
|
|
35391
|
+
const result = await post("start", scopes ? { scopes } : {});
|
|
35392
|
+
if (typeof result.expiresIn !== "number" || !Number.isFinite(result.expiresIn) || result.expiresIn < 1 || result.expiresIn > 600) throw invalidResponse();
|
|
35393
|
+
request = pendingRequest({ ...result, version: 1, scopes: requestedScopes, deadline: Math.min(Date.parse(String(result.expiresAt)), startedAt + result.expiresIn * 1e3), nextPollAt: now() + pollInterval(result.interval) * 1e3 });
|
|
35394
|
+
if (Date.parse(request.expiresAt) > now() + 6e5) throw invalidResponse();
|
|
35395
|
+
if (request.deadline <= now()) throw expired();
|
|
35396
|
+
await store?.set(apiUrl, request);
|
|
35397
|
+
}
|
|
35398
|
+
const deadline = Math.min(Date.parse(request.expiresAt), request.deadline);
|
|
35399
|
+
runtime.io.stdout(`Open ${request.verificationUri} and enter device code ${request.userCode}.`);
|
|
35400
|
+
runtime.io.stdout(`Browser login expires at ${new Date(deadline).toISOString()}. Review the permissions in your browser. Waiting for your decision\u2026`);
|
|
35401
|
+
while (now() < deadline) {
|
|
35402
|
+
if (signal.aborted) throw interrupted();
|
|
35403
|
+
try {
|
|
35404
|
+
await sleep(Math.max(0, Math.min(request.nextPollAt, deadline) - now()), signal);
|
|
35405
|
+
} catch {
|
|
35406
|
+
throw interrupted();
|
|
35407
|
+
}
|
|
35408
|
+
if (signal.aborted) throw interrupted();
|
|
35409
|
+
if (now() >= deadline) break;
|
|
35410
|
+
request.nextPollAt = now() + request.interval * 1e3;
|
|
35411
|
+
await store?.set(apiUrl, request);
|
|
35412
|
+
let result;
|
|
35413
|
+
try {
|
|
35414
|
+
result = await post("poll", { deviceCode: request.deviceCode }, deadline);
|
|
35415
|
+
} catch (error64) {
|
|
35416
|
+
if (error64 instanceof DeviceLoginError && error64.code === "DEVICE_LOGIN_EXPIRED") await clearPending(error64);
|
|
35417
|
+
throw error64;
|
|
35418
|
+
}
|
|
35419
|
+
if (result.status === "pending" || result.status === "slow_down") {
|
|
35420
|
+
request.interval = pollInterval(result.interval);
|
|
35421
|
+
request.nextPollAt = now() + request.interval * 1e3;
|
|
35422
|
+
await store?.set(apiUrl, request);
|
|
35423
|
+
continue;
|
|
35424
|
+
}
|
|
35425
|
+
if (result.status === "authorized") {
|
|
35426
|
+
if (typeof result.token !== "string" || !/^aiss_[A-Za-z0-9_-]{43}$/.test(result.token) || typeof result.email !== "string" || typeof result.expiresAt !== "string" || !Number.isFinite(Date.parse(result.expiresAt)) || Date.parse(result.expiresAt) <= now()) {
|
|
35427
|
+
const error64 = invalidResponse();
|
|
35428
|
+
await clearPending(error64);
|
|
35429
|
+
throw error64;
|
|
35430
|
+
}
|
|
35431
|
+
try {
|
|
35432
|
+
if (!runtime.tokenStore) throw new Error();
|
|
35433
|
+
await runtime.tokenStore.set(apiUrl, { kind: "api", token: result.token, email: result.email, expiresAt: result.expiresAt });
|
|
35434
|
+
} catch {
|
|
35435
|
+
const error64 = new DeviceLoginError("Browser authorization completed, but credential saving was not confirmed. This one-time code cannot be redeemed again. Check myskills auth status; if necessary revoke the CLI browser login token in account settings and start a new login.", "DEVICE_LOGIN_TOKEN_SAVE_FAILED");
|
|
35436
|
+
await clearPending(error64);
|
|
35437
|
+
throw error64;
|
|
35438
|
+
}
|
|
35439
|
+
await clearPending();
|
|
35440
|
+
try {
|
|
35441
|
+
await runtime.configStore?.setApiUrl(apiUrl);
|
|
35442
|
+
} catch {
|
|
35443
|
+
throw new DeviceLoginError("The browser login credential was saved, but saving the selected API URL failed. Use --api-url for this registry and repair the configuration store.", "DEVICE_LOGIN_CONFIG_SAVE_FAILED");
|
|
35444
|
+
}
|
|
35445
|
+
runtime.io.stdout(`${result.email.replace(/[\u0000-\u001F\u007F-\u009F]/gu, " ")} logged-in expires=${result.expiresAt}`);
|
|
35446
|
+
return;
|
|
35447
|
+
}
|
|
35448
|
+
const error63 = result.status === "denied" ? new DeviceLoginError("Browser login denied. Start again to request a new code.", "DEVICE_LOGIN_DENIED") : result.status === "expired" ? expired() : result.status === "invalid" ? new DeviceLoginError("Browser login is invalid or already redeemed. A lost response after one-time redemption cannot be recovered. Check myskills auth status or revoke the CLI browser login token in account settings, then start again.", "DEVICE_LOGIN_INVALID") : invalidResponse();
|
|
35449
|
+
await clearPending(error63);
|
|
35450
|
+
throw error63;
|
|
35084
35451
|
}
|
|
35085
|
-
|
|
35086
|
-
|
|
35452
|
+
const error62 = expired();
|
|
35453
|
+
await clearPending(error62);
|
|
35454
|
+
throw error62;
|
|
35455
|
+
}
|
|
35456
|
+
try {
|
|
35457
|
+
if (runtime.deviceLoginStore) await runtime.deviceLoginStore.withLock(apiUrl, run);
|
|
35458
|
+
else await run();
|
|
35459
|
+
} finally {
|
|
35460
|
+
process.removeListener("SIGINT", interrupt);
|
|
35461
|
+
process.removeListener("SIGTERM", interrupt);
|
|
35462
|
+
}
|
|
35463
|
+
function interrupted() {
|
|
35464
|
+
return new DeviceLoginError(request && store ? `Browser login interrupted. Repeat the same login command before ${new Date(request.deadline).toISOString()} to resume. A response lost after one-time redemption cannot be recovered.` : "Browser login interrupted. Start again to request a new code.", "DEVICE_LOGIN_INTERRUPTED");
|
|
35465
|
+
}
|
|
35466
|
+
}
|
|
35467
|
+
function pendingRequest(input2) {
|
|
35468
|
+
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) throw invalidState();
|
|
35469
|
+
const value = input2;
|
|
35470
|
+
if (value.version !== 1 || typeof value.deviceCode !== "string" || !/^[A-Za-z0-9_-]{43}$/.test(value.deviceCode) || typeof value.userCode !== "string" || !/^[23456789ABCDEFGHJKLMNPQRSTUVWXYZ]{5}-[23456789ABCDEFGHJKLMNPQRSTUVWXYZ]{5}$/.test(value.userCode) || typeof value.verificationUri !== "string" || typeof value.expiresAt !== "string" || !Number.isFinite(Date.parse(value.expiresAt)) || !(value.scopes === null || Array.isArray(value.scopes) && value.scopes.length > 0 && value.scopes.length <= 100 && value.scopes.every((scope) => typeof scope === "string" && /^[a-z][a-z-]*:[a-z][a-z-]*$/.test(scope))) || typeof value.deadline !== "number" || !Number.isFinite(value.deadline) || value.deadline > Date.parse(value.expiresAt) || typeof value.nextPollAt !== "number" || !Number.isFinite(value.nextPollAt)) throw invalidState();
|
|
35471
|
+
const verification = safeUrl(value.verificationUri);
|
|
35472
|
+
if (verification.username || verification.password || verification.search || verification.hash || verification.pathname !== "/auth/device") throw invalidState();
|
|
35473
|
+
return {
|
|
35474
|
+
version: 1,
|
|
35475
|
+
deviceCode: value.deviceCode,
|
|
35476
|
+
userCode: value.userCode,
|
|
35477
|
+
verificationUri: verification.href,
|
|
35478
|
+
expiresAt: value.expiresAt,
|
|
35479
|
+
deadline: value.deadline,
|
|
35480
|
+
scopes: value.scopes === null ? null : [...new Set(value.scopes)].sort(),
|
|
35481
|
+
interval: pollInterval(value.interval),
|
|
35482
|
+
nextPollAt: value.nextPollAt
|
|
35483
|
+
};
|
|
35484
|
+
}
|
|
35485
|
+
function safeUrl(value) {
|
|
35486
|
+
let url3;
|
|
35487
|
+
try {
|
|
35488
|
+
url3 = new URL(value);
|
|
35489
|
+
} catch {
|
|
35490
|
+
throw invalidResponse();
|
|
35087
35491
|
}
|
|
35088
|
-
throw new
|
|
35492
|
+
if (url3.protocol !== "https:" && !(url3.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url3.hostname))) throw new DeviceLoginError("Browser login requires HTTPS, except on loopback.", "DEVICE_LOGIN_URL_INVALID");
|
|
35493
|
+
return url3;
|
|
35089
35494
|
}
|
|
35090
35495
|
function pollInterval(value) {
|
|
35091
|
-
if (typeof value !== "number" || !Number.isInteger(value) || value < 5 || value > 60) throw
|
|
35496
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 5 || value > 60) throw invalidResponse();
|
|
35092
35497
|
return value;
|
|
35093
35498
|
}
|
|
35499
|
+
function expired() {
|
|
35500
|
+
return new DeviceLoginError("Browser login expired. Start again to request a new code.", "DEVICE_LOGIN_EXPIRED");
|
|
35501
|
+
}
|
|
35502
|
+
function invalidResponse() {
|
|
35503
|
+
return new DeviceLoginError("Invalid browser login response.", "DEVICE_LOGIN_RESPONSE_INVALID");
|
|
35504
|
+
}
|
|
35505
|
+
function invalidState() {
|
|
35506
|
+
return new DeviceLoginError("The pending browser login is invalid. Run myskills logout for this API and configuration profile, then log in again.", "DEVICE_LOGIN_STATE_INVALID");
|
|
35507
|
+
}
|
|
35094
35508
|
|
|
35095
35509
|
// src/cli.ts
|
|
35096
35510
|
init_dist();
|
|
@@ -35485,8 +35899,8 @@ var organizationReadPaths = {
|
|
|
35485
35899
|
};
|
|
35486
35900
|
async function runRegistryCollaborationCommand(input2, context) {
|
|
35487
35901
|
const [action, ...args] = input2.args;
|
|
35488
|
-
const send = async (method,
|
|
35489
|
-
context.output(await context.request(method,
|
|
35902
|
+
const send = async (method, path19, body) => {
|
|
35903
|
+
context.output(await context.request(method, path19, body));
|
|
35490
35904
|
};
|
|
35491
35905
|
if (input2.command === "skills" && action === "managed") {
|
|
35492
35906
|
if (args.length) {
|
|
@@ -35634,7 +36048,7 @@ function role(input2, allowed) {
|
|
|
35634
36048
|
|
|
35635
36049
|
// src/account-admin-commands.ts
|
|
35636
36050
|
import { lstat as lstat8, open as open5, unlink } from "node:fs/promises";
|
|
35637
|
-
import
|
|
36051
|
+
import path10 from "node:path";
|
|
35638
36052
|
var accountAdminHelp = [
|
|
35639
36053
|
" account register --email <email> [--name <name>] (prompts for a password and an optional invitation token)",
|
|
35640
36054
|
" account verify-email-request|password-reset-request --email <email>",
|
|
@@ -35938,7 +36352,7 @@ async function requiredSecret(context, label, trim = false) {
|
|
|
35938
36352
|
return value;
|
|
35939
36353
|
}
|
|
35940
36354
|
async function withReservedOutput(output2, action, lostMessage) {
|
|
35941
|
-
const file2 =
|
|
36355
|
+
const file2 = path10.resolve(output2);
|
|
35942
36356
|
let handle;
|
|
35943
36357
|
try {
|
|
35944
36358
|
handle = await open5(file2, "wx", 384);
|
|
@@ -36117,16 +36531,16 @@ async function runArchitectureTargetCommand(input2, context) {
|
|
|
36117
36531
|
// src/cli.ts
|
|
36118
36532
|
init_dist2();
|
|
36119
36533
|
init_dist();
|
|
36120
|
-
import { createHash as
|
|
36121
|
-
import { lstat as lstat14, mkdir as
|
|
36122
|
-
import
|
|
36123
|
-
import
|
|
36534
|
+
import { createHash as createHash10, randomUUID as randomUUID3 } from "node:crypto";
|
|
36535
|
+
import { lstat as lstat14, mkdir as mkdir5, readFile as readFile4, readdir as readdir6, realpath as realpath11, rename as rename3, rm as rm4, stat as stat3, writeFile as writeFile2 } from "node:fs/promises";
|
|
36536
|
+
import os7 from "node:os";
|
|
36537
|
+
import path17 from "node:path";
|
|
36124
36538
|
|
|
36125
36539
|
// src/codex-readonly-adapter.ts
|
|
36126
36540
|
init_dist();
|
|
36127
36541
|
import { constants as fsConstants } from "node:fs";
|
|
36128
36542
|
import { open as open6, lstat as lstat9, readdir as readdir5 } from "node:fs/promises";
|
|
36129
|
-
import
|
|
36543
|
+
import path11 from "node:path";
|
|
36130
36544
|
var codexAdapterProfiles = ["personal", "work", "shared"];
|
|
36131
36545
|
var codexAdapterDescriptor = Object.freeze({
|
|
36132
36546
|
kind: "codex",
|
|
@@ -36253,7 +36667,7 @@ var CodexReadOnlyArchitectureTargetAdapter = class {
|
|
|
36253
36667
|
#clock;
|
|
36254
36668
|
constructor(optionsOrRoot, profile, clock) {
|
|
36255
36669
|
const options2 = typeof optionsOrRoot === "string" ? { root: optionsOrRoot, profile, clock } : optionsOrRoot;
|
|
36256
|
-
if (typeof options2.root !== "string" || !options2.root || !
|
|
36670
|
+
if (typeof options2.root !== "string" || !options2.root || !path11.isAbsolute(options2.root)) {
|
|
36257
36671
|
throw new TypeError("A consented absolute target root is required.");
|
|
36258
36672
|
}
|
|
36259
36673
|
if (!isCodexAdapterProfile(options2.profile)) {
|
|
@@ -36262,7 +36676,7 @@ var CodexReadOnlyArchitectureTargetAdapter = class {
|
|
|
36262
36676
|
if (options2.clock !== void 0 && typeof options2.clock !== "function") {
|
|
36263
36677
|
throw new TypeError("The adapter clock must be a function.");
|
|
36264
36678
|
}
|
|
36265
|
-
this.#root =
|
|
36679
|
+
this.#root = path11.resolve(options2.root);
|
|
36266
36680
|
this.#profile = options2.profile;
|
|
36267
36681
|
this.#clock = options2.clock ?? (() => /* @__PURE__ */ new Date());
|
|
36268
36682
|
}
|
|
@@ -36393,7 +36807,7 @@ var CodexReadOnlyArchitectureTargetAdapter = class {
|
|
|
36393
36807
|
return result;
|
|
36394
36808
|
}
|
|
36395
36809
|
async #readMetadataFile(relativeName) {
|
|
36396
|
-
const filePath =
|
|
36810
|
+
const filePath = path11.join(this.#root, relativeName);
|
|
36397
36811
|
let handle;
|
|
36398
36812
|
try {
|
|
36399
36813
|
handle = await open6(filePath, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW | fsConstants.O_NONBLOCK);
|
|
@@ -36417,7 +36831,7 @@ var CodexReadOnlyArchitectureTargetAdapter = class {
|
|
|
36417
36831
|
}
|
|
36418
36832
|
}
|
|
36419
36833
|
async #readSkills(profileResolutions, routerPolicy, findings) {
|
|
36420
|
-
const skillsDirectory =
|
|
36834
|
+
const skillsDirectory = path11.join(this.#root, SKILLS_DIRECTORY);
|
|
36421
36835
|
let entries;
|
|
36422
36836
|
try {
|
|
36423
36837
|
const directory = await lstat9(skillsDirectory);
|
|
@@ -36450,7 +36864,7 @@ var CodexReadOnlyArchitectureTargetAdapter = class {
|
|
|
36450
36864
|
return skills.sort(compareSkills);
|
|
36451
36865
|
}
|
|
36452
36866
|
async #readSkill(directorySlug, profileResolutions, routerPolicy, findings) {
|
|
36453
|
-
const skillPath =
|
|
36867
|
+
const skillPath = path11.join(this.#root, SKILLS_DIRECTORY, directorySlug, "SKILL.md");
|
|
36454
36868
|
const frontmatter = await readFrontmatter(skillPath);
|
|
36455
36869
|
if (frontmatter.status === "missing") findings.add("skill-frontmatter-missing");
|
|
36456
36870
|
if (frontmatter.status === "invalid") findings.add("skill-frontmatter-invalid");
|
|
@@ -36817,10 +37231,10 @@ var CompanionLease = class {
|
|
|
36817
37231
|
|
|
36818
37232
|
// src/codex-bootstrap.ts
|
|
36819
37233
|
init_dist2();
|
|
36820
|
-
import { createHash as
|
|
37234
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
36821
37235
|
import { constants as fsConstants2 } from "node:fs";
|
|
36822
|
-
import { lstat as lstat10, open as open7, opendir as opendir3, readFile, realpath as realpath6, stat as stat2, unlink as unlink2 } from "node:fs/promises";
|
|
36823
|
-
import
|
|
37236
|
+
import { lstat as lstat10, open as open7, opendir as opendir3, readFile as readFile2, realpath as realpath6, stat as stat2, unlink as unlink2 } from "node:fs/promises";
|
|
37237
|
+
import path12 from "node:path";
|
|
36824
37238
|
import { TextDecoder as TextDecoder3 } from "node:util";
|
|
36825
37239
|
var CODEX_BOOTSTRAP_REPORT_SCHEMA = "myskills.codex-bootstrap-dry-run.v3";
|
|
36826
37240
|
var CODEX_BOOTSTRAP_CONTRACT_VERSIONS = Object.freeze({
|
|
@@ -36961,7 +37375,7 @@ async function readCodexBootstrapContextFile(contextPath) {
|
|
|
36961
37375
|
}
|
|
36962
37376
|
let text;
|
|
36963
37377
|
try {
|
|
36964
|
-
text = await
|
|
37378
|
+
text = await readFile2(path12.resolve(contextPath), "utf8");
|
|
36965
37379
|
} catch {
|
|
36966
37380
|
throw new CodexBootstrapError("BOOTSTRAP_CONTEXT_INVALID", "The work context file could not be read.");
|
|
36967
37381
|
}
|
|
@@ -37211,14 +37625,14 @@ async function normalizePaths(input2) {
|
|
|
37211
37625
|
if (sourceRoots.length === 0) {
|
|
37212
37626
|
throw new CodexBootstrapError("BOOTSTRAP_SOURCE_ROOT_REQUIRED", "At least one typed work or shared source root is required.");
|
|
37213
37627
|
}
|
|
37214
|
-
const liveSkillsRoot =
|
|
37628
|
+
const liveSkillsRoot = path12.resolve(input2.liveSkillsRoot);
|
|
37215
37629
|
const realLiveRoot = await existingDirectoryRealpath(liveSkillsRoot, "BOOTSTRAP_ROOT_INVALID");
|
|
37216
37630
|
const normalizedSourceRoots = [];
|
|
37217
37631
|
for (const source2 of sourceRoots) {
|
|
37218
37632
|
if (!SOURCE_TYPES.includes(source2.type) || !isAbsolutePath(source2.root)) {
|
|
37219
37633
|
throw new CodexBootstrapError("BOOTSTRAP_SOURCE_ROOT_INVALID", "Every source root must be an absolute, typed work or shared directory.");
|
|
37220
37634
|
}
|
|
37221
|
-
const root =
|
|
37635
|
+
const root = path12.resolve(source2.root);
|
|
37222
37636
|
const realRoot = await existingDirectoryRealpath(root, "BOOTSTRAP_SOURCE_ROOT_INVALID");
|
|
37223
37637
|
if (pathsOverlap2(realRoot, realLiveRoot) || normalizedSourceRoots.some((existing) => pathsOverlap2(existing.realRoot, realRoot))) {
|
|
37224
37638
|
throw new CodexBootstrapError("BOOTSTRAP_ROOT_OVERLAP", "Source and target roots must be separate trust compartments.");
|
|
@@ -37226,8 +37640,8 @@ async function normalizePaths(input2) {
|
|
|
37226
37640
|
normalizedSourceRoots.push({ type: source2.type, root, realRoot });
|
|
37227
37641
|
}
|
|
37228
37642
|
const requestedReportPath = await resolveReportPath(input2);
|
|
37229
|
-
const reportParent = await secureReportParent(
|
|
37230
|
-
const reportPath =
|
|
37643
|
+
const reportParent = await secureReportParent(path12.dirname(requestedReportPath));
|
|
37644
|
+
const reportPath = path12.join(reportParent, path12.basename(requestedReportPath));
|
|
37231
37645
|
if (isContained(realLiveRoot, reportParent) || normalizedSourceRoots.some((source2) => isContained(source2.realRoot, reportParent))) {
|
|
37232
37646
|
throw new CodexBootstrapError("BOOTSTRAP_OUTPUT_UNSAFE", "The report location must be outside source and target roots.");
|
|
37233
37647
|
}
|
|
@@ -37267,7 +37681,7 @@ function rawSourceRoots(input2) {
|
|
|
37267
37681
|
if (input2.sharedSourceRoot !== void 0) roots.push({ type: "shared", root: input2.sharedSourceRoot });
|
|
37268
37682
|
const unique = /* @__PURE__ */ new Map();
|
|
37269
37683
|
for (const source2 of roots) {
|
|
37270
|
-
const normalizedRoot = typeof source2.root === "string" ?
|
|
37684
|
+
const normalizedRoot = typeof source2.root === "string" ? path12.resolve(source2.root) : String(source2.root);
|
|
37271
37685
|
unique.set(`${String(source2.type)}\0${normalizedRoot}`, source2);
|
|
37272
37686
|
}
|
|
37273
37687
|
return [...unique.values()];
|
|
@@ -37277,7 +37691,7 @@ async function resolveReportPath(input2) {
|
|
|
37277
37691
|
if (!isAbsolutePath(requested)) {
|
|
37278
37692
|
throw new CodexBootstrapError("BOOTSTRAP_OUTPUT_REQUIRED", "An absolute report path is required.");
|
|
37279
37693
|
}
|
|
37280
|
-
const absolute2 =
|
|
37694
|
+
const absolute2 = path12.resolve(requested);
|
|
37281
37695
|
let requestedStat;
|
|
37282
37696
|
try {
|
|
37283
37697
|
requestedStat = await lstat10(absolute2);
|
|
@@ -37287,14 +37701,14 @@ async function resolveReportPath(input2) {
|
|
|
37287
37701
|
if (requestedStat?.isSymbolicLink()) {
|
|
37288
37702
|
throw new CodexBootstrapError("BOOTSTRAP_OUTPUT_UNSAFE", "The report location must not be a symlink.");
|
|
37289
37703
|
}
|
|
37290
|
-
if (requestedStat?.isDirectory() || requested.endsWith(
|
|
37704
|
+
if (requestedStat?.isDirectory() || requested.endsWith(path12.sep)) return path12.join(absolute2, "dry-run-report.json");
|
|
37291
37705
|
if (requestedStat && !requestedStat.isFile()) {
|
|
37292
37706
|
throw new CodexBootstrapError("BOOTSTRAP_OUTPUT_INVALID", "The report location must be a regular file.");
|
|
37293
37707
|
}
|
|
37294
37708
|
return absolute2;
|
|
37295
37709
|
}
|
|
37296
37710
|
async function secureReportParent(parentPath) {
|
|
37297
|
-
const lexicalParent =
|
|
37711
|
+
const lexicalParent = path12.resolve(parentPath);
|
|
37298
37712
|
const realParent = await existingDirectoryRealpath(lexicalParent, "BOOTSTRAP_OUTPUT_INVALID");
|
|
37299
37713
|
let parentStats;
|
|
37300
37714
|
try {
|
|
@@ -37335,13 +37749,13 @@ async function selectSources(paths, selectors, exclusions) {
|
|
|
37335
37749
|
const roots = paths.sourceRoots.filter((source2) => selector.sourceType === void 0 || source2.type === selector.sourceType);
|
|
37336
37750
|
const matches = [];
|
|
37337
37751
|
for (const source2 of roots) {
|
|
37338
|
-
const sourceDir =
|
|
37752
|
+
const sourceDir = path12.join(source2.realRoot, selector.slug);
|
|
37339
37753
|
try {
|
|
37340
37754
|
const entry = await lstat10(sourceDir);
|
|
37341
37755
|
if (entry.isSymbolicLink() || !entry.isDirectory()) continue;
|
|
37342
37756
|
const realSourceDir = await realpath6(sourceDir);
|
|
37343
37757
|
if (!isContained(source2.realRoot, realSourceDir)) throw new Error("source path escape");
|
|
37344
|
-
const liveDir =
|
|
37758
|
+
const liveDir = path12.join(paths.realLiveRoot, selector.slug);
|
|
37345
37759
|
matches.push({
|
|
37346
37760
|
slug: selector.slug,
|
|
37347
37761
|
sourceType: source2.type,
|
|
@@ -37572,8 +37986,8 @@ function safeFinding(finding) {
|
|
|
37572
37986
|
return { category: finding.category, severity: finding.severity, ...finding.path ? { path: finding.path } : {} };
|
|
37573
37987
|
}
|
|
37574
37988
|
async function captureTargetAbsence(targetPath, boundaryRoot) {
|
|
37575
|
-
const absoluteTargetPath =
|
|
37576
|
-
const parentPath =
|
|
37989
|
+
const absoluteTargetPath = path12.resolve(targetPath);
|
|
37990
|
+
const parentPath = path12.dirname(absoluteTargetPath);
|
|
37577
37991
|
const parentStats = await lstat10(parentPath, { bigint: true });
|
|
37578
37992
|
if (parentStats.isSymbolicLink() || !parentStats.isDirectory()) throw new Error("target absence parent is not regular");
|
|
37579
37993
|
const parentRealPath = await realpath6(parentPath);
|
|
@@ -37584,7 +37998,7 @@ async function captureTargetAbsence(targetPath, boundaryRoot) {
|
|
|
37584
37998
|
if (nodeErrorCode(error62) === "ENOENT") {
|
|
37585
37999
|
return {
|
|
37586
38000
|
targetPath: absoluteTargetPath,
|
|
37587
|
-
boundaryRoot:
|
|
38001
|
+
boundaryRoot: path12.resolve(boundaryRoot),
|
|
37588
38002
|
parentPath,
|
|
37589
38003
|
parentRealPath,
|
|
37590
38004
|
parentStats
|
|
@@ -37620,8 +38034,8 @@ async function readBootstrapSnapshot(rootPath, boundaryRoot, testHooks) {
|
|
|
37620
38034
|
if (typeof NO_FOLLOW_FLAG !== "number" || NO_FOLLOW_FLAG === 0 || typeof DIRECTORY_FLAG !== "number" || DIRECTORY_FLAG === 0) {
|
|
37621
38035
|
throw new Error("secure filesystem flags unavailable");
|
|
37622
38036
|
}
|
|
37623
|
-
const absoluteRoot =
|
|
37624
|
-
const absoluteBoundaryRoot =
|
|
38037
|
+
const absoluteRoot = path12.resolve(rootPath);
|
|
38038
|
+
const absoluteBoundaryRoot = path12.resolve(boundaryRoot);
|
|
37625
38039
|
const state = { directories: [], files: [], identities: [], entries: 0, totalBytes: 0 };
|
|
37626
38040
|
await readBootstrapDirectory(absoluteRoot, absoluteBoundaryRoot, "", 0, state, testHooks);
|
|
37627
38041
|
if (!state.rootPath || !state.rootRealPath || !state.rootStats || state.directories.length === 0 || state.files.length !== state.identities.length) {
|
|
@@ -37670,7 +38084,7 @@ async function readBootstrapDirectory(directoryPath, boundaryRoot, relativePrefi
|
|
|
37670
38084
|
entryNames: entries.map((entry) => entry.name)
|
|
37671
38085
|
});
|
|
37672
38086
|
for (const entry of entries) {
|
|
37673
|
-
const entryPath =
|
|
38087
|
+
const entryPath = path12.join(directoryPath, entry.name);
|
|
37674
38088
|
const relativePath = relativePrefix ? `${relativePrefix}/${entry.name}` : entry.name;
|
|
37675
38089
|
if (entry.isSymbolicLink()) throw new Error("snapshot symlink is not allowed");
|
|
37676
38090
|
if (isSensitiveSnapshotPath(relativePath)) throw new Error("snapshot sensitive path is not allowed");
|
|
@@ -37819,7 +38233,7 @@ function snapshotToPackageFiles(snapshot) {
|
|
|
37819
38233
|
return Object.freeze(snapshot.files.map((file2) => Object.freeze({ path: file2.path, content: file2.content })));
|
|
37820
38234
|
}
|
|
37821
38235
|
function snapshotArtifactIdentity(snapshot) {
|
|
37822
|
-
const hash3 =
|
|
38236
|
+
const hash3 = createHash6("sha256");
|
|
37823
38237
|
for (const file2 of snapshot.files) {
|
|
37824
38238
|
const pathBytes = Buffer.from(file2.path, "utf8");
|
|
37825
38239
|
const contentBytes = Buffer.from(file2.content, "utf8");
|
|
@@ -37988,7 +38402,7 @@ function compareOrdinal2(left, right) {
|
|
|
37988
38402
|
return left === right ? 0 : left < right ? -1 : 1;
|
|
37989
38403
|
}
|
|
37990
38404
|
function sha256(value) {
|
|
37991
|
-
return
|
|
38405
|
+
return createHash6("sha256").update(value, "utf8").digest("hex");
|
|
37992
38406
|
}
|
|
37993
38407
|
function normalizeTimestamp(value) {
|
|
37994
38408
|
const timestamp = value ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -38074,7 +38488,7 @@ async function verifyReportPathAfterWrite(paths, reportHandle, parentBefore, ope
|
|
|
38074
38488
|
async function cleanupReportDestination(reportPath, openedIdentity) {
|
|
38075
38489
|
if (!openedIdentity) return;
|
|
38076
38490
|
try {
|
|
38077
|
-
const parentPath =
|
|
38491
|
+
const parentPath = path12.dirname(reportPath);
|
|
38078
38492
|
const parentReal = await realpath6(parentPath);
|
|
38079
38493
|
const reportReal = await realpath6(reportPath);
|
|
38080
38494
|
if (parentReal !== parentPath || reportReal !== reportPath) return;
|
|
@@ -38084,7 +38498,7 @@ async function cleanupReportDestination(reportPath, openedIdentity) {
|
|
|
38084
38498
|
}
|
|
38085
38499
|
}
|
|
38086
38500
|
function isAbsolutePath(value) {
|
|
38087
|
-
return typeof value === "string" && value.length > 0 &&
|
|
38501
|
+
return typeof value === "string" && value.length > 0 && path12.isAbsolute(value) && !value.includes("\0");
|
|
38088
38502
|
}
|
|
38089
38503
|
function isSensitiveSnapshotPath(relativePath) {
|
|
38090
38504
|
const segments = relativePath.split("/");
|
|
@@ -38097,8 +38511,8 @@ function isRecord6(value) {
|
|
|
38097
38511
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
38098
38512
|
}
|
|
38099
38513
|
function isContained(root, target) {
|
|
38100
|
-
const relative =
|
|
38101
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
38514
|
+
const relative = path12.relative(path12.resolve(root), path12.resolve(target));
|
|
38515
|
+
return relative === "" || !relative.startsWith("..") && !path12.isAbsolute(relative);
|
|
38102
38516
|
}
|
|
38103
38517
|
function pathsOverlap2(left, right) {
|
|
38104
38518
|
return isContained(left, right) || isContained(right, left);
|
|
@@ -38111,7 +38525,7 @@ function nodeErrorCode(error62) {
|
|
|
38111
38525
|
init_dist2();
|
|
38112
38526
|
init_install_filesystem();
|
|
38113
38527
|
import { lstat as lstat11, realpath as realpath7 } from "node:fs/promises";
|
|
38114
|
-
import
|
|
38528
|
+
import path13 from "node:path";
|
|
38115
38529
|
var DEFAULT_VERSION = "0.1.0";
|
|
38116
38530
|
var DEFAULT_LICENSE = "UNLICENSED";
|
|
38117
38531
|
var DEFAULT_SUMMARY = "Describe what this skill does.";
|
|
@@ -38138,11 +38552,11 @@ async function initSkillPackage(options2) {
|
|
|
38138
38552
|
` },
|
|
38139
38553
|
{ path: "SKILL.md", content: skillDocument(manifest.name, manifest.summary) }
|
|
38140
38554
|
];
|
|
38141
|
-
const requestedOutput =
|
|
38555
|
+
const requestedOutput = path13.resolve(options2.output ?? path13.join(process.cwd(), options2.name));
|
|
38142
38556
|
if (CONTROL_CHARACTER_PATTERN3.test(requestedOutput)) {
|
|
38143
38557
|
throw new SkillInitInputError("Output path must not contain control characters.");
|
|
38144
38558
|
}
|
|
38145
|
-
const requestedParent =
|
|
38559
|
+
const requestedParent = path13.dirname(requestedOutput);
|
|
38146
38560
|
try {
|
|
38147
38561
|
await assertRegularDirectory(requestedParent);
|
|
38148
38562
|
} catch {
|
|
@@ -38155,7 +38569,7 @@ async function initSkillPackage(options2) {
|
|
|
38155
38569
|
} catch {
|
|
38156
38570
|
throw new SkillInitDestinationError(`Output parent must be an existing regular directory: ${requestedParent}.`);
|
|
38157
38571
|
}
|
|
38158
|
-
const outputPath =
|
|
38572
|
+
const outputPath = path13.join(parent, path13.basename(requestedOutput));
|
|
38159
38573
|
let destinationExists = false;
|
|
38160
38574
|
try {
|
|
38161
38575
|
await lstat11(outputPath);
|
|
@@ -38224,10 +38638,10 @@ function isNonBlankText(value) {
|
|
|
38224
38638
|
// src/author-package.ts
|
|
38225
38639
|
init_dist2();
|
|
38226
38640
|
init_install_filesystem();
|
|
38227
|
-
import { createHash as
|
|
38641
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
38228
38642
|
import { constants as constants4 } from "node:fs";
|
|
38229
38643
|
import { lstat as lstat12, open as open8, realpath as realpath8 } from "node:fs/promises";
|
|
38230
|
-
import
|
|
38644
|
+
import path14 from "node:path";
|
|
38231
38645
|
var SkillPackageDestinationError = class extends Error {
|
|
38232
38646
|
constructor(message) {
|
|
38233
38647
|
super(message);
|
|
@@ -38236,14 +38650,14 @@ var SkillPackageDestinationError = class extends Error {
|
|
|
38236
38650
|
};
|
|
38237
38651
|
async function packageSkill(options2, fault) {
|
|
38238
38652
|
if (process.platform !== "darwin" && process.platform !== "linux") throw new Error("Local skill packaging requires macOS or Linux.");
|
|
38239
|
-
const inputPath = await systemAliasPath(
|
|
38240
|
-
const outputPath = await systemAliasPath(
|
|
38653
|
+
const inputPath = await systemAliasPath(path14.resolve(options2.path));
|
|
38654
|
+
const outputPath = await systemAliasPath(path14.resolve(options2.output));
|
|
38241
38655
|
if (/[\u0000-\u001f\u007f-\u009f]/u.test(inputPath + outputPath)) throw new Error("Package paths must not contain control characters.");
|
|
38242
|
-
if (
|
|
38656
|
+
if (path14.extname(outputPath).toLowerCase() !== ".zip") throw new SkillPackageDestinationError("Output must name a .zip file.");
|
|
38243
38657
|
const source2 = await lstat12(inputPath, { bigint: true });
|
|
38244
38658
|
if (!source2.isDirectory() || source2.isSymbolicLink()) throw new Error("Package input must be a regular directory.");
|
|
38245
38659
|
const sourcePath = await realpath8(inputPath);
|
|
38246
|
-
const parentPath =
|
|
38660
|
+
const parentPath = path14.dirname(outputPath);
|
|
38247
38661
|
assertOutsideSource(sourcePath, parentPath);
|
|
38248
38662
|
const parent = await openDirectoryWithoutSymlinks(parentPath);
|
|
38249
38663
|
try {
|
|
@@ -38255,7 +38669,7 @@ async function packageSkill(options2, fault) {
|
|
|
38255
38669
|
await fault?.("checked");
|
|
38256
38670
|
assertIdentity(source2, await lstat12(inputPath, { bigint: true }));
|
|
38257
38671
|
await assertDestinationParent(parentPath, parent, parentIdentity, sourcePath);
|
|
38258
|
-
const destination2 = process.platform === "linux" ? `/proc/self/fd/${parent.fd}/${
|
|
38672
|
+
const destination2 = process.platform === "linux" ? `/proc/self/fd/${parent.fd}/${path14.basename(outputPath)}` : outputPath;
|
|
38259
38673
|
const noFollow = process.platform === "darwin" ? 536870912 : constants4.O_NOFOLLOW;
|
|
38260
38674
|
let output2;
|
|
38261
38675
|
try {
|
|
@@ -38279,7 +38693,7 @@ async function packageSkill(options2, fault) {
|
|
|
38279
38693
|
}
|
|
38280
38694
|
return {
|
|
38281
38695
|
output: outputPath,
|
|
38282
|
-
sha256:
|
|
38696
|
+
sha256: createHash7("sha256").update(bytes2).digest("hex"),
|
|
38283
38697
|
size: bytes2.byteLength,
|
|
38284
38698
|
manifest: snapshot.manifest,
|
|
38285
38699
|
scan: snapshot.scan
|
|
@@ -38289,8 +38703,8 @@ async function packageSkill(options2, fault) {
|
|
|
38289
38703
|
}
|
|
38290
38704
|
}
|
|
38291
38705
|
function assertOutsideSource(sourcePath, directory) {
|
|
38292
|
-
const relative =
|
|
38293
|
-
if (relative === "" || !relative.startsWith(`..${
|
|
38706
|
+
const relative = path14.relative(sourcePath, directory);
|
|
38707
|
+
if (relative === "" || !relative.startsWith(`..${path14.sep}`) && relative !== ".." && !path14.isAbsolute(relative)) {
|
|
38294
38708
|
throw new SkillPackageDestinationError("Output parent must be outside the source package directory.");
|
|
38295
38709
|
}
|
|
38296
38710
|
}
|
|
@@ -38329,13 +38743,13 @@ async function systemAliasPath(requested) {
|
|
|
38329
38743
|
if (!alias) return requested;
|
|
38330
38744
|
const resolved = await realpath8(alias);
|
|
38331
38745
|
if (resolved !== `/private${alias}`) throw new Error("Package system path alias has an unexpected destination.");
|
|
38332
|
-
return
|
|
38746
|
+
return path14.join(resolved, path14.relative(alias, requested));
|
|
38333
38747
|
}
|
|
38334
38748
|
|
|
38335
38749
|
// src/cli.ts
|
|
38336
38750
|
var DEFAULT_API_URL = "http://localhost:3001";
|
|
38337
38751
|
var SCOPE_TARGET_LIST_LIMIT = 500;
|
|
38338
|
-
var CLI_VERSION = "0.1.0-beta.
|
|
38752
|
+
var CLI_VERSION = "0.1.0-beta.20";
|
|
38339
38753
|
var CLI_VISIBILITY_SCOPES = ["public", "authenticated", "organization", "team", "private", "explicit-users"];
|
|
38340
38754
|
var LOGIN_AUTH_METHODS = ["password", "api-key", "browser"];
|
|
38341
38755
|
var OBSERVED_IDENTIFIER_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
@@ -38374,8 +38788,7 @@ var CODEX_OBSERVATION_OPTIONS = /* @__PURE__ */ new Set([
|
|
|
38374
38788
|
async function runCli(argv, runtime) {
|
|
38375
38789
|
let parsed;
|
|
38376
38790
|
let namespace;
|
|
38377
|
-
const
|
|
38378
|
-
const legacyEnrollmentDirectory = runtime.workspaceEnrollmentStateDirectory ? void 0 : legacyWorkspaceEnrollmentDirectory(runtime.env);
|
|
38791
|
+
const enrollmentEnv = runtime.env;
|
|
38379
38792
|
try {
|
|
38380
38793
|
const selected = selectConfigurationProfile(argv, runtime.env);
|
|
38381
38794
|
parsed = parseArgs(selected.argv);
|
|
@@ -38400,15 +38813,15 @@ async function runCli(argv, runtime) {
|
|
|
38400
38813
|
if (parsed.options.workspace && parsed.options.dir) throw new CliError("Choose --workspace or --dir, not both.", 2);
|
|
38401
38814
|
const workspace = optionalStringOption(parsed, "workspace");
|
|
38402
38815
|
if (workspace) {
|
|
38403
|
-
if (!
|
|
38816
|
+
if (!path17.isAbsolute(workspace)) throw new CliError("Workspace must be an absolute directory.", 2);
|
|
38404
38817
|
if (parsed.options.platform && parsed.options.platform !== "codex") throw new CliError("Workspace installation supports the Codex platform.", 2);
|
|
38405
38818
|
await assertRegularDirectory(workspace);
|
|
38406
38819
|
const canonicalWorkspace = await realpath11(workspace);
|
|
38407
|
-
if (canonicalWorkspace ===
|
|
38408
|
-
const relative =
|
|
38409
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
38820
|
+
if (canonicalWorkspace === os7.homedir() || [".codex", ".agents"].some((directory) => {
|
|
38821
|
+
const relative = path17.relative(path17.join(os7.homedir(), directory), canonicalWorkspace);
|
|
38822
|
+
return relative === "" || !relative.startsWith("..") && !path17.isAbsolute(relative);
|
|
38410
38823
|
})) throw new CliError("Choose a project workspace, not global configuration.", 2);
|
|
38411
|
-
await ensureSafeDirectory(canonicalWorkspace,
|
|
38824
|
+
await ensureSafeDirectory(canonicalWorkspace, path17.join(canonicalWorkspace, ".agents", "skills"));
|
|
38412
38825
|
parsed.options.workspace = canonicalWorkspace;
|
|
38413
38826
|
}
|
|
38414
38827
|
const root = installRoot(parsed, runtime);
|
|
@@ -38419,11 +38832,15 @@ async function runCli(argv, runtime) {
|
|
|
38419
38832
|
await lstat14(workspaceBindingPath(canonicalRoot));
|
|
38420
38833
|
throw new CliError("This installation root belongs to an enrolled Codex workspace. Use --workspace for workspace mutations.", 2);
|
|
38421
38834
|
} catch (error62) {
|
|
38422
|
-
if (!
|
|
38835
|
+
if (!isNodeError2(error62) || error62.code !== "ENOENT") throw error62;
|
|
38423
38836
|
}
|
|
38424
38837
|
}
|
|
38425
38838
|
const managedMutation = parsed.command === "architecture-artifacts" || parsed.command === "codex" && parsed.args[0] === "enroll" || ["install", "update", "rollback", "companion"].includes(parsed.command);
|
|
38426
|
-
if (workspace && managedMutation)
|
|
38839
|
+
if (workspace && managedMutation) {
|
|
38840
|
+
const enrollmentDirectory = runtime.workspaceEnrollmentStateDirectory ?? workspaceEnrollmentDirectory(enrollmentEnv);
|
|
38841
|
+
const legacyEnrollmentDirectory = runtime.workspaceEnrollmentStateDirectory ? void 0 : legacyWorkspaceEnrollmentDirectory(enrollmentEnv);
|
|
38842
|
+
return withWorkspaceEnrollment(String(parsed.options.workspace), enrollmentDirectory, parsed.command === "codex" && parsed.args[0] === "enroll", () => dispatchCli(parsed, runtime), { legacyDirectory: legacyEnrollmentDirectory, onAuthorityWait: runtime.workspaceEnrollmentWait });
|
|
38843
|
+
}
|
|
38427
38844
|
return dispatchCli(parsed, runtime);
|
|
38428
38845
|
});
|
|
38429
38846
|
}
|
|
@@ -38599,9 +39016,9 @@ function parityCommandContext(parsed, runtime) {
|
|
|
38599
39016
|
},
|
|
38600
39017
|
async writeOutput(outputPath, contents) {
|
|
38601
39018
|
try {
|
|
38602
|
-
await
|
|
39019
|
+
await writeFile2(path17.resolve(outputPath), contents, { mode: 384, flag: "wx" });
|
|
38603
39020
|
} catch (error62) {
|
|
38604
|
-
if (
|
|
39021
|
+
if (isNodeError2(error62) && error62.code === "EEXIST") throw new CliError("The output path already exists. Choose a new file; existing files are not replaced.", 1, "OUTPUT_EXISTS");
|
|
38605
39022
|
throw error62;
|
|
38606
39023
|
}
|
|
38607
39024
|
}
|
|
@@ -38800,7 +39217,7 @@ async function initCommand(parsed, runtime) {
|
|
|
38800
39217
|
}
|
|
38801
39218
|
const quotedPath = displayCliPath(result.outputPath);
|
|
38802
39219
|
const next = {
|
|
38803
|
-
edit: displayCliPath(
|
|
39220
|
+
edit: displayCliPath(path17.join(result.outputPath, "SKILL.md")),
|
|
38804
39221
|
validate: `myskills validate --path ${quotedPath}`,
|
|
38805
39222
|
scan: `myskills scan --path ${quotedPath}`,
|
|
38806
39223
|
submit: `myskills submit --path ${quotedPath}`
|
|
@@ -38936,9 +39353,9 @@ async function loginCommand(parsed, runtime) {
|
|
|
38936
39353
|
const method = await loginAuthMethod(parsed, runtime);
|
|
38937
39354
|
if (method === "browser") {
|
|
38938
39355
|
try {
|
|
38939
|
-
await browserDeviceLogin(apiUrl, optionalStringOption(parsed, "scopes")?.split(",").map((scope) => scope.trim()), runtime);
|
|
39356
|
+
await browserDeviceLogin(apiUrl, optionalStringOption(parsed, "scopes")?.split(",").map((scope) => scope.trim()), runtime, parsed.options["no-resume"] === true);
|
|
38940
39357
|
} catch (error62) {
|
|
38941
|
-
throw new CliError(error62 instanceof
|
|
39358
|
+
throw new CliError(error62 instanceof DeviceLoginError ? error62.message : "Browser login failed.", 1, error62 instanceof DeviceLoginError ? error62.code : "DEVICE_LOGIN_FAILED");
|
|
38942
39359
|
}
|
|
38943
39360
|
return 0;
|
|
38944
39361
|
}
|
|
@@ -38990,6 +39407,39 @@ async function completeMfaLogin(loginResponse, parsed, runtime) {
|
|
|
38990
39407
|
return authSessionFromResponse(verifyResponse);
|
|
38991
39408
|
}
|
|
38992
39409
|
async function logoutCommand(parsed, runtime) {
|
|
39410
|
+
const apiUrl = apiBaseUrl(parsed, runtime);
|
|
39411
|
+
if (runtime.deviceLoginStore) {
|
|
39412
|
+
try {
|
|
39413
|
+
return await runtime.deviceLoginStore.withLock(apiUrl, async () => {
|
|
39414
|
+
let pending = null;
|
|
39415
|
+
let cleanupFailed = false;
|
|
39416
|
+
try {
|
|
39417
|
+
pending = await runtime.deviceLoginStore.get(apiUrl).catch((error62) => {
|
|
39418
|
+
if (error62 instanceof DeviceLoginError && error62.code === "DEVICE_LOGIN_STATE_INVALID") return true;
|
|
39419
|
+
throw error62;
|
|
39420
|
+
});
|
|
39421
|
+
await runtime.deviceLoginStore.delete(apiUrl);
|
|
39422
|
+
} catch {
|
|
39423
|
+
cleanupFailed = true;
|
|
39424
|
+
}
|
|
39425
|
+
let result;
|
|
39426
|
+
try {
|
|
39427
|
+
result = await logoutCredential(parsed, runtime, pending !== null);
|
|
39428
|
+
} catch (error62) {
|
|
39429
|
+
if (cleanupFailed) throw new CliError("Credential logout was attempted, but pending browser login cleanup could not be confirmed. Restore OS keyring access and retry logout; check account settings for remote revocation.", 1, "DEVICE_LOGIN_CLEANUP_FAILED");
|
|
39430
|
+
throw error62;
|
|
39431
|
+
}
|
|
39432
|
+
if (cleanupFailed) throw new CliError("Credential logout completed, but pending browser login cleanup could not be confirmed. Restore OS keyring access and retry logout before resuming browser login.", 1, "DEVICE_LOGIN_CLEANUP_FAILED");
|
|
39433
|
+
return result;
|
|
39434
|
+
});
|
|
39435
|
+
} catch (error62) {
|
|
39436
|
+
if (error62 instanceof DeviceLoginError) throw new CliError(error62.message, 1, error62.code);
|
|
39437
|
+
throw error62;
|
|
39438
|
+
}
|
|
39439
|
+
}
|
|
39440
|
+
return logoutCredential(parsed, runtime, false);
|
|
39441
|
+
}
|
|
39442
|
+
async function logoutCredential(parsed, runtime, removedPending) {
|
|
38993
39443
|
const apiUrl = apiBaseUrl(parsed, runtime);
|
|
38994
39444
|
let resolved;
|
|
38995
39445
|
try {
|
|
@@ -39005,6 +39455,10 @@ async function logoutCommand(parsed, runtime) {
|
|
|
39005
39455
|
throw new CliError("Stored credentials were unreadable. Local cleanup succeeded, but remote revocation could not be confirmed. Revoke the session or API token through the account settings.", 1, "LOGOUT_REMOTE_UNCONFIRMED");
|
|
39006
39456
|
}
|
|
39007
39457
|
if (!resolved) {
|
|
39458
|
+
if (removedPending) {
|
|
39459
|
+
runtime.io.stdout("pending browser login removed local-only");
|
|
39460
|
+
return 0;
|
|
39461
|
+
}
|
|
39008
39462
|
throw new CliError("Not logged in. Run myskills login, set MYSKILLS_TOKEN, or pass --token.", 1);
|
|
39009
39463
|
}
|
|
39010
39464
|
if (resolved.source === "store" && resolved.stored.kind === "api") {
|
|
@@ -39299,17 +39753,17 @@ async function reviewCommand(parsed, runtime) {
|
|
|
39299
39753
|
}
|
|
39300
39754
|
const outputPath = optionalStringOption(parsed, "output");
|
|
39301
39755
|
if (outputPath) {
|
|
39302
|
-
await
|
|
39303
|
-
await
|
|
39756
|
+
await mkdir5(path17.dirname(path17.resolve(outputPath)), { recursive: true });
|
|
39757
|
+
await writeFile2(path17.resolve(outputPath), response.text, { encoding: "utf8", mode: 384 });
|
|
39304
39758
|
}
|
|
39305
39759
|
if (parsed.options.json) {
|
|
39306
39760
|
runtime.io.stdout(JSON.stringify({
|
|
39307
39761
|
artifactSha256,
|
|
39308
|
-
...outputPath ? { output:
|
|
39762
|
+
...outputPath ? { output: path17.resolve(outputPath) } : {},
|
|
39309
39763
|
payload: parseJsonResponse(`/v1/review/submissions/${submissionId}/bundle`, apiBaseUrl(parsed, runtime), response.text)
|
|
39310
39764
|
}, null, 2));
|
|
39311
39765
|
} else {
|
|
39312
|
-
runtime.io.stdout([`artifactSha256=${artifactSha256}`, ...outputPath ? [`output=${
|
|
39766
|
+
runtime.io.stdout([`artifactSha256=${artifactSha256}`, ...outputPath ? [`output=${path17.resolve(outputPath)}`] : []].map((field) => terminalSafeText(field)).join(" "));
|
|
39313
39767
|
}
|
|
39314
39768
|
return 0;
|
|
39315
39769
|
}
|
|
@@ -39716,7 +40170,7 @@ function assertCodexObservationOptions(parsed, healthOnly) {
|
|
|
39716
40170
|
}
|
|
39717
40171
|
function requiredCodexRoot(parsed) {
|
|
39718
40172
|
const root = parsed.options.root;
|
|
39719
|
-
if (typeof root !== "string" || !root || hasControlCharacter(root) || !
|
|
40173
|
+
if (typeof root !== "string" || !root || hasControlCharacter(root) || !path17.isAbsolute(root)) {
|
|
39720
40174
|
throw new CliError("An explicit absolute --root is required; the CLI does not discover a Codex home or profile.", 2, "CODEX_TARGET_ROOT_INVALID");
|
|
39721
40175
|
}
|
|
39722
40176
|
return root;
|
|
@@ -39768,7 +40222,7 @@ async function readCodexAdapterContext(parsed) {
|
|
|
39768
40222
|
}
|
|
39769
40223
|
let text;
|
|
39770
40224
|
try {
|
|
39771
|
-
text = await
|
|
40225
|
+
text = await readFile4(path17.resolve(contextPath), "utf8");
|
|
39772
40226
|
} catch {
|
|
39773
40227
|
throw new CliError("The context JSON file could not be read.", 2, "CODEX_TARGET_CONTEXT_INVALID");
|
|
39774
40228
|
}
|
|
@@ -40029,7 +40483,7 @@ async function releaseMetadataOptions(parsed) {
|
|
|
40029
40483
|
const releaseNotesFile = optionalStringOption(parsed, "release-notes-file");
|
|
40030
40484
|
const adapterContractVersion = optionalStringOption(parsed, "minimum-adapter-contract-version");
|
|
40031
40485
|
const raw = {
|
|
40032
|
-
...releaseNotesFile ? { releaseNotes: await
|
|
40486
|
+
...releaseNotesFile ? { releaseNotes: await readFile4(path17.resolve(releaseNotesFile), "utf8") } : {},
|
|
40033
40487
|
...optionalStringOption(parsed, "change-kind") ? { changeKind: optionalStringOption(parsed, "change-kind") } : {},
|
|
40034
40488
|
...parsed.options["requires-user-action"] === true ? { requiresUserAction: true } : {},
|
|
40035
40489
|
compatibility: {
|
|
@@ -40054,7 +40508,7 @@ async function exportCommand(parsed, runtime) {
|
|
|
40054
40508
|
const outputDir = stringOption(parsed, "output");
|
|
40055
40509
|
const token = await tokenOption(parsed, runtime) ?? void 0;
|
|
40056
40510
|
const bundle = await downloadVerifiedBundle({ slug, version: version2, platform }, parsed, runtime, token);
|
|
40057
|
-
const outputRoot =
|
|
40511
|
+
const outputRoot = path17.resolve(outputDir);
|
|
40058
40512
|
await exportPackageTree(bundle.files, outputRoot);
|
|
40059
40513
|
runtime.io.stdout(terminalText`${slug}@${version2}\texported\tfiles=${bundle.files.length}\t${outputRoot}`);
|
|
40060
40514
|
return 0;
|
|
@@ -40117,18 +40571,18 @@ async function verifiedLibraryReviewBundle(pathname, parsed, runtime, token) {
|
|
|
40117
40571
|
throw new CliError("The review bundle response has no valid artifact digest. Nothing was printed or written.", 1, "ARTIFACT_HASH_MISSING");
|
|
40118
40572
|
}
|
|
40119
40573
|
const bytes2 = Buffer.from(response.text, "utf8");
|
|
40120
|
-
if (
|
|
40574
|
+
if (createHash10("sha256").update(bytes2).digest("hex") !== artifactSha256 || expectedDigest !== void 0 && artifactSha256 !== expectedDigest) {
|
|
40121
40575
|
throw new CliError("The review bundle does not match its artifact digest. Nothing was printed or written; do not elevate this release.", 1, "ARTIFACT_HASH_MISMATCH");
|
|
40122
40576
|
}
|
|
40123
40577
|
const payload = parseJsonResponse(pathname, apiBaseUrl(parsed, runtime), response.text);
|
|
40124
40578
|
if (!Array.isArray(payload.files)) throw new CliError("The review bundle is not an inspectable package.", 1, "ARTIFACT_INVALID");
|
|
40125
40579
|
const outputPath = optionalStringOption(parsed, "output");
|
|
40126
|
-
const output2 = outputPath ?
|
|
40580
|
+
const output2 = outputPath ? path17.resolve(outputPath) : null;
|
|
40127
40581
|
if (output2) {
|
|
40128
40582
|
try {
|
|
40129
|
-
await
|
|
40583
|
+
await writeFile2(output2, bytes2, { mode: 384, flag: "wx" });
|
|
40130
40584
|
} catch (error62) {
|
|
40131
|
-
if (
|
|
40585
|
+
if (isNodeError2(error62) && error62.code === "EEXIST") throw new CliError("The output path already exists. Choose a new file; existing files are not replaced.", 1, "OUTPUT_EXISTS");
|
|
40132
40586
|
throw error62;
|
|
40133
40587
|
}
|
|
40134
40588
|
}
|
|
@@ -40431,8 +40885,8 @@ async function rollbackCommand(parsed, runtime) {
|
|
|
40431
40885
|
assertMatchingProvenance(existing, provenance);
|
|
40432
40886
|
}
|
|
40433
40887
|
const outputRoot = skillInstallPath(root, slug);
|
|
40434
|
-
const sourceSnapshotPath =
|
|
40435
|
-
assertChildPath(
|
|
40888
|
+
const sourceSnapshotPath = path17.resolve(previous.snapshotPath);
|
|
40889
|
+
assertChildPath(path17.join(root, ".myskills-app", "history"), sourceSnapshotPath);
|
|
40436
40890
|
if (!await pathExists(outputRoot) || !await pathExists(sourceSnapshotPath)) {
|
|
40437
40891
|
throw new CliError(`${slug} cannot roll back because its active install or snapshot is missing.`, 1);
|
|
40438
40892
|
}
|
|
@@ -40468,7 +40922,7 @@ async function rollbackCommand(parsed, runtime) {
|
|
|
40468
40922
|
await runtime.installFault?.("prepared");
|
|
40469
40923
|
await runtime.beforeInstallPromotion?.();
|
|
40470
40924
|
await assertInstalledBytes(existing);
|
|
40471
|
-
await ensureSafeDirectory(root,
|
|
40925
|
+
await ensureSafeDirectory(root, path17.dirname(recoverySnapshotPath));
|
|
40472
40926
|
await rename3(outputRoot, recoverySnapshotPath);
|
|
40473
40927
|
transaction2 = { ...transaction2, state: "previous-staged" };
|
|
40474
40928
|
await writeInstallTransaction(root, transaction2);
|
|
@@ -40496,14 +40950,14 @@ async function rollbackCommand(parsed, runtime) {
|
|
|
40496
40950
|
transaction2 = { ...transaction2, state: "registry-committed" };
|
|
40497
40951
|
await writeInstallTransaction(root, transaction2);
|
|
40498
40952
|
await runtime.installFault?.("registry-committed");
|
|
40499
|
-
await
|
|
40500
|
-
await
|
|
40501
|
-
await
|
|
40953
|
+
await rm4(recoverySnapshotPath, { recursive: true, force: true });
|
|
40954
|
+
await rm4(sourceSnapshotPath, { recursive: true, force: true });
|
|
40955
|
+
await rm4(installTransactionPath(root, transactionId), { force: true });
|
|
40502
40956
|
runtime.io.stdout(terminalText`${slug}@${previous.version}\trolled-back\tplatform=${previous.platform}\t${outputRoot}`);
|
|
40503
40957
|
return 0;
|
|
40504
40958
|
}
|
|
40505
40959
|
function workspaceBindingPath(root) {
|
|
40506
|
-
return
|
|
40960
|
+
return path17.join(root, ".myskills-app", "codex-workspace.json");
|
|
40507
40961
|
}
|
|
40508
40962
|
async function readWorkspaceBinding(root) {
|
|
40509
40963
|
let input2;
|
|
@@ -40575,7 +41029,7 @@ async function codexWorkspaceCommand(parsed, runtime) {
|
|
|
40575
41029
|
await lstat14(workspaceBindingPath(root));
|
|
40576
41030
|
binding = await readWorkspaceBinding(root);
|
|
40577
41031
|
} catch (error62) {
|
|
40578
|
-
if (!
|
|
41032
|
+
if (!isNodeError2(error62) || error62.code !== "ENOENT") throw error62;
|
|
40579
41033
|
}
|
|
40580
41034
|
if (binding) assertMatchingProvenance(binding, provenance);
|
|
40581
41035
|
const requestedTarget = optionalStringOption(parsed, "target-id");
|
|
@@ -40594,7 +41048,7 @@ async function codexWorkspaceCommand(parsed, runtime) {
|
|
|
40594
41048
|
profileId: parseArchitectureReference(stringOption(parsed, "profile-id"), "profile"),
|
|
40595
41049
|
adapter: codexWorkspaceDescriptor,
|
|
40596
41050
|
capabilities: codexWorkspaceCapabilities,
|
|
40597
|
-
identityDigest:
|
|
41051
|
+
identityDigest: createHash10("sha256").update(randomUUID3()).digest("hex")
|
|
40598
41052
|
}, parsed, runtime, token)).target);
|
|
40599
41053
|
}
|
|
40600
41054
|
binding = { schemaVersion: 1, rootDigest: workspaceRootDigest(root), provenance, target };
|
|
@@ -40812,7 +41266,7 @@ async function storedProjectRoot(parsed) {
|
|
|
40812
41266
|
try {
|
|
40813
41267
|
return (await canonicalScopeDirectory(value, { allowBroad: true, label: "The project directory" })).path;
|
|
40814
41268
|
} catch (error62) {
|
|
40815
|
-
if (typeof value === "string" &&
|
|
41269
|
+
if (typeof value === "string" && path17.isAbsolute(value)) return path17.resolve(value);
|
|
40816
41270
|
throw error62;
|
|
40817
41271
|
}
|
|
40818
41272
|
}
|
|
@@ -40951,7 +41405,7 @@ async function scopesEnroll(parsed, runtime) {
|
|
|
40951
41405
|
const upgraded = record5.rootIdentity.dev === null;
|
|
40952
41406
|
let backupName = null;
|
|
40953
41407
|
if (upgraded) {
|
|
40954
|
-
backupName = await backup(`workspace-scopes.root-identity.${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.${
|
|
41408
|
+
backupName = await backup(`workspace-scopes.root-identity.${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.${createHash10("sha256").update(snapshot.bytes).digest("hex").slice(0, 12)}.json`, snapshot.bytes);
|
|
40955
41409
|
await assertScopeRootUnchanged(location.path, current.identity);
|
|
40956
41410
|
record5.rootIdentity = current.identity;
|
|
40957
41411
|
await write(state);
|
|
@@ -41589,7 +42043,7 @@ async function installSkillVersion(input2) {
|
|
|
41589
42043
|
if (existing) await assertInstalledBytes(existing);
|
|
41590
42044
|
else if (await pathExists(outputRoot)) throw new CliError("Installation appeared after planning.", 1);
|
|
41591
42045
|
if (snapshotPath && existing) {
|
|
41592
|
-
await ensureSafeDirectory(input2.root,
|
|
42046
|
+
await ensureSafeDirectory(input2.root, path17.dirname(snapshotPath));
|
|
41593
42047
|
await rename3(outputRoot, snapshotPath);
|
|
41594
42048
|
history.push({
|
|
41595
42049
|
version: existing.version,
|
|
@@ -41606,7 +42060,7 @@ async function installSkillVersion(input2) {
|
|
|
41606
42060
|
await input2.runtime.installFault?.("previous-staged");
|
|
41607
42061
|
}
|
|
41608
42062
|
await checkpointInstallPromotion(input2.root, input2.runtime);
|
|
41609
|
-
await ensureSafeDirectory(input2.root,
|
|
42063
|
+
await ensureSafeDirectory(input2.root, path17.dirname(outputRoot));
|
|
41610
42064
|
await rename3(stageRoot, outputRoot);
|
|
41611
42065
|
transaction2 = { ...transaction2, state: "installed" };
|
|
41612
42066
|
await writeInstallTransaction(input2.root, transaction2);
|
|
@@ -41630,7 +42084,7 @@ async function installSkillVersion(input2) {
|
|
|
41630
42084
|
transaction2 = { ...transaction2, state: "registry-committed" };
|
|
41631
42085
|
await writeInstallTransaction(input2.root, transaction2);
|
|
41632
42086
|
await input2.runtime.installFault?.("registry-committed");
|
|
41633
|
-
await
|
|
42087
|
+
await rm4(installTransactionPath(input2.root, transactionId), { force: true });
|
|
41634
42088
|
return installed;
|
|
41635
42089
|
}
|
|
41636
42090
|
async function downloadVerifiedBundle(input2, parsed, runtime, token) {
|
|
@@ -41731,9 +42185,9 @@ function selectReleasePlatform(release, requestedPlatform) {
|
|
|
41731
42185
|
function installRoot(parsed, runtime) {
|
|
41732
42186
|
if (parsed.command === "codex" && !optionalStringOption(parsed, "workspace")) throw new CliError("Codex commands require an explicit --workspace <absolute-dir>.", 2);
|
|
41733
42187
|
const workspace = optionalStringOption(parsed, "workspace");
|
|
41734
|
-
if (workspace && (!
|
|
41735
|
-
const configured = optionalStringOption(parsed, "dir") ?? (workspace ?
|
|
41736
|
-
return
|
|
42188
|
+
if (workspace && (!path17.isAbsolute(workspace) || path17.resolve(workspace) === os7.homedir() || path17.resolve(workspace) === path17.join(os7.homedir(), ".codex"))) throw new CliError("Choose an absolute project workspace, not the home or global Codex directory.", 2);
|
|
42189
|
+
const configured = optionalStringOption(parsed, "dir") ?? (workspace ? path17.join(workspace, ".agents", "skills") : void 0) ?? runtime.env.MYSKILLS_INSTALL_DIR ?? (runtime.env.XDG_DATA_HOME ? path17.join(runtime.env.XDG_DATA_HOME, "myskills-app", "skills") : void 0) ?? (runtime.env.HOME ? path17.join(runtime.env.HOME, ".local", "share", "myskills-app", "skills") : void 0) ?? path17.join(process.cwd(), ".myskills-app", "skills");
|
|
42190
|
+
return path17.resolve(configured);
|
|
41737
42191
|
}
|
|
41738
42192
|
async function readInstallRegistry(root) {
|
|
41739
42193
|
assertInstallRootLocked(root);
|
|
@@ -41744,7 +42198,7 @@ async function readInstallRegistryFile(root) {
|
|
|
41744
42198
|
try {
|
|
41745
42199
|
return parseInstallRegistry(await readRegularText(installRegistryPath(root)), root);
|
|
41746
42200
|
} catch (error62) {
|
|
41747
|
-
if (
|
|
42201
|
+
if (isNodeError2(error62) && error62.code === "ENOENT") {
|
|
41748
42202
|
return { version: 1, installations: {} };
|
|
41749
42203
|
}
|
|
41750
42204
|
throw error62;
|
|
@@ -41810,8 +42264,8 @@ function parseInstallHistory(input2, root) {
|
|
|
41810
42264
|
if (typeof record5.version !== "string" || !parseSemanticVersion(record5.version) || typeof record5.platform !== "string" || typeof record5.snapshotPath !== "string") {
|
|
41811
42265
|
return [];
|
|
41812
42266
|
}
|
|
41813
|
-
const snapshotPath =
|
|
41814
|
-
assertChildPath(
|
|
42267
|
+
const snapshotPath = path17.resolve(record5.snapshotPath);
|
|
42268
|
+
assertChildPath(path17.join(root, ".myskills-app", "history"), snapshotPath);
|
|
41815
42269
|
return [{
|
|
41816
42270
|
version: record5.version,
|
|
41817
42271
|
platform: record5.platform,
|
|
@@ -42423,10 +42877,10 @@ async function readObservedStateFixture(inputPath) {
|
|
|
42423
42877
|
if (hasControlCharacter(inputPath)) {
|
|
42424
42878
|
throw new CliError("Observed-state fixture path contains control characters.", 2, "OBSERVED_STATE_INVALID");
|
|
42425
42879
|
}
|
|
42426
|
-
const resolvedPath =
|
|
42880
|
+
const resolvedPath = path17.resolve(inputPath);
|
|
42427
42881
|
let text;
|
|
42428
42882
|
try {
|
|
42429
|
-
text = await
|
|
42883
|
+
text = await readFile4(resolvedPath, "utf8");
|
|
42430
42884
|
} catch {
|
|
42431
42885
|
throw new CliError("Observed-state fixture could not be read.", 2, "OBSERVED_STATE_INVALID");
|
|
42432
42886
|
}
|
|
@@ -42795,22 +43249,22 @@ function optionalRecordBoolean(record5, key) {
|
|
|
42795
43249
|
return typeof value === "boolean" ? value : void 0;
|
|
42796
43250
|
}
|
|
42797
43251
|
function installRegistryPath(root) {
|
|
42798
|
-
return
|
|
43252
|
+
return path17.join(root, ".myskills-app", "installed.json");
|
|
42799
43253
|
}
|
|
42800
43254
|
function installTransactionsRoot(root) {
|
|
42801
|
-
return
|
|
43255
|
+
return path17.join(root, ".myskills-app", "transactions");
|
|
42802
43256
|
}
|
|
42803
43257
|
function installTransactionPath(root, transactionId) {
|
|
42804
|
-
return
|
|
43258
|
+
return path17.join(installTransactionsRoot(root), `${transactionId}.json`);
|
|
42805
43259
|
}
|
|
42806
43260
|
function installStagePath(root, transactionId) {
|
|
42807
|
-
return
|
|
43261
|
+
return path17.join(root, ".myskills-app", "staging", transactionId);
|
|
42808
43262
|
}
|
|
42809
43263
|
function skillInstallPath(root, slug) {
|
|
42810
|
-
return
|
|
43264
|
+
return path17.join(root, parseInstallSlug(slug));
|
|
42811
43265
|
}
|
|
42812
43266
|
function historySnapshotPath(root, slug, version2, transactionId = randomUUID3()) {
|
|
42813
|
-
return
|
|
43267
|
+
return path17.join(root, ".myskills-app", "history", parseInstallSlug(slug), `${transactionId}-${version2}`);
|
|
42814
43268
|
}
|
|
42815
43269
|
async function writeInstallTransaction(root, transaction2) {
|
|
42816
43270
|
assertInstallRootLocked(root);
|
|
@@ -42840,33 +43294,33 @@ async function recoverInstallTransactions(root) {
|
|
|
42840
43294
|
await assertRegularDirectory(installTransactionsRoot(root));
|
|
42841
43295
|
entries = await readdir6(installTransactionsRoot(root), { withFileTypes: true });
|
|
42842
43296
|
} catch (error62) {
|
|
42843
|
-
if (
|
|
43297
|
+
if (isNodeError2(error62) && error62.code === "ENOENT") return;
|
|
42844
43298
|
throw error62;
|
|
42845
43299
|
}
|
|
42846
43300
|
const files2 = entries.filter((entry) => entry.isFile() && /^[0-9a-f-]{36}\.json$/.test(entry.name)).map((entry) => entry.name).sort();
|
|
42847
43301
|
if (files2.length === 0) return;
|
|
42848
43302
|
const registry2 = await readInstallRegistryFile(root);
|
|
42849
43303
|
for (const filename of files2) {
|
|
42850
|
-
const journalPath2 =
|
|
43304
|
+
const journalPath2 = path17.join(installTransactionsRoot(root), filename);
|
|
42851
43305
|
const transaction2 = parseInstallTransaction(await readRegularText(journalPath2), filename, root);
|
|
42852
43306
|
const outputRoot = skillInstallPath(root, transaction2.slug);
|
|
42853
43307
|
const stageRoot = installStagePath(root, transaction2.id);
|
|
42854
43308
|
const snapshotPath = transaction2.previous && transaction2.snapshotCreated ? historySnapshotPath(root, transaction2.slug, transaction2.previous.version, transaction2.id) : null;
|
|
42855
|
-
if (snapshotPath) await ensureSafeDirectory(root,
|
|
42856
|
-
await ensureSafeDirectory(root,
|
|
43309
|
+
if (snapshotPath) await ensureSafeDirectory(root, path17.dirname(snapshotPath));
|
|
43310
|
+
await ensureSafeDirectory(root, path17.dirname(stageRoot));
|
|
42857
43311
|
const installed = registry2.installations[transaction2.slug];
|
|
42858
43312
|
const candidateCommitted = Boolean(
|
|
42859
43313
|
installed && installed.version === transaction2.targetVersion && installed.platform === transaction2.targetPlatform && installed.artifact.sha256 === transaction2.targetArtifact.sha256 && installed.contentDigest === transaction2.targetContentDigest && installed.contentDigestAlgorithm === transaction2.targetContentDigestAlgorithm && await pathExists(outputRoot) && await directoryMatchesDigest(outputRoot, transaction2.targetContentDigest, transaction2.targetContentDigestAlgorithm)
|
|
42860
43314
|
);
|
|
42861
43315
|
if (candidateCommitted) {
|
|
42862
|
-
await
|
|
43316
|
+
await rm4(stageRoot, { recursive: true, force: true });
|
|
42863
43317
|
if (transaction2.operation === "rollback") {
|
|
42864
|
-
if (snapshotPath) await
|
|
43318
|
+
if (snapshotPath) await rm4(snapshotPath, { recursive: true, force: true });
|
|
42865
43319
|
if (transaction2.sourceSnapshotPath) {
|
|
42866
|
-
await
|
|
43320
|
+
await rm4(transaction2.sourceSnapshotPath, { recursive: true, force: true });
|
|
42867
43321
|
}
|
|
42868
43322
|
}
|
|
42869
|
-
await
|
|
43323
|
+
await rm4(journalPath2, { force: true });
|
|
42870
43324
|
continue;
|
|
42871
43325
|
}
|
|
42872
43326
|
const previousAtOutput = Boolean(transaction2.previous?.contentDigest && await directoryMatchesDigest(outputRoot, transaction2.previous.contentDigest, transaction2.previous.contentDigestAlgorithm));
|
|
@@ -42881,8 +43335,8 @@ async function recoverInstallTransactions(root) {
|
|
|
42881
43335
|
throw new CliError("Recovery snapshot does not match its verified bytes. Preserve both copies for operator recovery.", 1);
|
|
42882
43336
|
}
|
|
42883
43337
|
if (!previousAtOutput) {
|
|
42884
|
-
await
|
|
42885
|
-
await ensureSafeDirectory(root,
|
|
43338
|
+
await rm4(outputRoot, { recursive: true, force: true });
|
|
43339
|
+
await ensureSafeDirectory(root, path17.dirname(outputRoot));
|
|
42886
43340
|
await rename3(snapshotPath, outputRoot);
|
|
42887
43341
|
}
|
|
42888
43342
|
} else if (transaction2.snapshotCreated) {
|
|
@@ -42890,17 +43344,17 @@ async function recoverInstallTransactions(root) {
|
|
|
42890
43344
|
throw new CliError(`Install recovery for ${transaction2.slug} requires manual intervention; its rollback snapshot is missing.`, 1);
|
|
42891
43345
|
}
|
|
42892
43346
|
} else if (!transaction2.previous || transaction2.state !== "prepared") {
|
|
42893
|
-
await
|
|
43347
|
+
await rm4(outputRoot, { recursive: true, force: true });
|
|
42894
43348
|
}
|
|
42895
|
-
await
|
|
43349
|
+
await rm4(stageRoot, { recursive: true, force: true });
|
|
42896
43350
|
if (transaction2.previous) {
|
|
42897
43351
|
registry2.installations[transaction2.slug] = transaction2.previous;
|
|
42898
43352
|
} else {
|
|
42899
43353
|
delete registry2.installations[transaction2.slug];
|
|
42900
43354
|
}
|
|
42901
43355
|
await writeInstallRegistry(root, registry2);
|
|
42902
|
-
if (previousAtOutput && snapshotPath) await
|
|
42903
|
-
await
|
|
43356
|
+
if (previousAtOutput && snapshotPath) await rm4(snapshotPath, { recursive: true, force: true });
|
|
43357
|
+
await rm4(journalPath2, { force: true });
|
|
42904
43358
|
}
|
|
42905
43359
|
}
|
|
42906
43360
|
function parseInstallTransaction(raw, filename, root) {
|
|
@@ -42933,8 +43387,8 @@ function parseInstallTransaction(raw, filename, root) {
|
|
|
42933
43387
|
if (typeof record5.sourceSnapshotPath !== "string") {
|
|
42934
43388
|
throw new CliError("Install rollback transaction is missing its source snapshot.", 1);
|
|
42935
43389
|
}
|
|
42936
|
-
sourceSnapshotPath =
|
|
42937
|
-
assertChildPath(
|
|
43390
|
+
sourceSnapshotPath = path17.resolve(record5.sourceSnapshotPath);
|
|
43391
|
+
assertChildPath(path17.join(root, ".myskills-app", "history"), sourceSnapshotPath);
|
|
42938
43392
|
} else if (record5.sourceSnapshotPath !== void 0) {
|
|
42939
43393
|
throw new CliError("Install transaction journal is invalid.", 1);
|
|
42940
43394
|
}
|
|
@@ -42961,7 +43415,7 @@ function parseContentDigestAlgorithm(input2) {
|
|
|
42961
43415
|
}
|
|
42962
43416
|
function contentDigestForFiles(files2, algorithm) {
|
|
42963
43417
|
const normalized = files2.map((file2) => ({ path: safeBundlePath(file2.path), content: file2.content })).sort((left, right) => algorithm === CONTENT_DIGEST_ALGORITHM ? left.path < right.path ? -1 : left.path > right.path ? 1 : 0 : left.path.localeCompare(right.path));
|
|
42964
|
-
return
|
|
43418
|
+
return createHash10("sha256").update(JSON.stringify(normalized)).digest("hex");
|
|
42965
43419
|
}
|
|
42966
43420
|
async function readStoredPackageSnapshot(inputPath) {
|
|
42967
43421
|
const files2 = await readPackageFilesFromPath(inputPath);
|
|
@@ -43014,15 +43468,15 @@ async function pathExists(filePath) {
|
|
|
43014
43468
|
await stat3(filePath);
|
|
43015
43469
|
return true;
|
|
43016
43470
|
} catch (error62) {
|
|
43017
|
-
if (
|
|
43471
|
+
if (isNodeError2(error62) && error62.code === "ENOENT") {
|
|
43018
43472
|
return false;
|
|
43019
43473
|
}
|
|
43020
43474
|
throw error62;
|
|
43021
43475
|
}
|
|
43022
43476
|
}
|
|
43023
43477
|
function assertChildPath(root, target) {
|
|
43024
|
-
const relative =
|
|
43025
|
-
if (relative.startsWith("..") ||
|
|
43478
|
+
const relative = path17.relative(path17.resolve(root), path17.resolve(target));
|
|
43479
|
+
if (relative.startsWith("..") || path17.isAbsolute(relative)) {
|
|
43026
43480
|
throw new CliError("Install registry contains an unsafe path.", 1);
|
|
43027
43481
|
}
|
|
43028
43482
|
}
|
|
@@ -43120,7 +43574,7 @@ async function apiFetch(pathname, parsed, runtime, init, artifact) {
|
|
|
43120
43574
|
let text;
|
|
43121
43575
|
try {
|
|
43122
43576
|
const bytes2 = await readBoundedResponse(response, response.ok && artifact ? artifact.byteSize : MAX_PACKAGE_RESPONSE_BYTES, signal);
|
|
43123
|
-
if (response.ok && artifact && (bytes2.length !== artifact.byteSize ||
|
|
43577
|
+
if (response.ok && artifact && (bytes2.length !== artifact.byteSize || createHash10("sha256").update(bytes2).digest("hex") !== artifact.sha256)) {
|
|
43124
43578
|
throw new Error("Downloaded bundle did not match release metadata.");
|
|
43125
43579
|
}
|
|
43126
43580
|
text = decodeResponseUtf8(bytes2);
|
|
@@ -43332,11 +43786,11 @@ async function doctorTokenStoreCheck(runtime) {
|
|
|
43332
43786
|
}
|
|
43333
43787
|
async function doctorInstallDirCheck(parsed, runtime) {
|
|
43334
43788
|
const root = installRoot(parsed, runtime);
|
|
43335
|
-
const testFile =
|
|
43789
|
+
const testFile = path17.join(root, ".myskills-app", `doctor-write-test-${randomUUID3()}`);
|
|
43336
43790
|
try {
|
|
43337
43791
|
assertInstallRootLocked(root);
|
|
43338
43792
|
await atomicPrivateWrite(root, testFile, "ok\n");
|
|
43339
|
-
await
|
|
43793
|
+
await rm4(testFile, { force: true });
|
|
43340
43794
|
return {
|
|
43341
43795
|
name: "install_dir",
|
|
43342
43796
|
ok: true,
|
|
@@ -43379,7 +43833,7 @@ async function filePermissions(filePath) {
|
|
|
43379
43833
|
try {
|
|
43380
43834
|
return ((await stat3(filePath)).mode & 511).toString(8).padStart(3, "0");
|
|
43381
43835
|
} catch (error62) {
|
|
43382
|
-
if (
|
|
43836
|
+
if (isNodeError2(error62) && error62.code === "ENOENT") {
|
|
43383
43837
|
return null;
|
|
43384
43838
|
}
|
|
43385
43839
|
throw error62;
|
|
@@ -43605,7 +44059,7 @@ function releaseArtifact(response) {
|
|
|
43605
44059
|
byteSize: record5.byteSize
|
|
43606
44060
|
};
|
|
43607
44061
|
}
|
|
43608
|
-
function
|
|
44062
|
+
function isNodeError2(error62) {
|
|
43609
44063
|
return error62 instanceof Error && "code" in error62;
|
|
43610
44064
|
}
|
|
43611
44065
|
function parseBundlePayload(text) {
|
|
@@ -43654,7 +44108,7 @@ function parseArgs(argv) {
|
|
|
43654
44108
|
continue;
|
|
43655
44109
|
}
|
|
43656
44110
|
const key = value.slice(2);
|
|
43657
|
-
if (key === "json" || key === "api-key" || key === "health" || key === "clear-organizations" || key === "dry-run" || key === "allow-loopback-http" || key === "upload" || key === "include-prerelease" || key === "requires-user-action" || key === "accept-user-action" || key === "allow-cloud" || key === "accept-current-root") {
|
|
44111
|
+
if (key === "json" || key === "api-key" || key === "no-resume" || key === "health" || key === "clear-organizations" || key === "dry-run" || key === "allow-loopback-http" || key === "upload" || key === "include-prerelease" || key === "requires-user-action" || key === "accept-user-action" || key === "allow-cloud" || key === "accept-current-root") {
|
|
43658
44112
|
options2[key] = true;
|
|
43659
44113
|
continue;
|
|
43660
44114
|
}
|
|
@@ -43711,7 +44165,7 @@ function helpText(runtime) {
|
|
|
43711
44165
|
" search [query] [--limit <1-100>] [--cursor <cursor>] [--api-url <url>]",
|
|
43712
44166
|
" info <skill-slug> [--version <exact-version>] [--api-url <url>]",
|
|
43713
44167
|
" login [--api-url <url>] [--method <password|api-key|browser>] [--email <email>]",
|
|
43714
|
-
" login --method browser [--scopes
|
|
44168
|
+
" login --method browser [--scopes <comma-separated-scopes>] [--no-resume] (repeat to resume before the displayed deadline)",
|
|
43715
44169
|
" login --api-key [--api-url <url>]",
|
|
43716
44170
|
" logout [--api-url <url>] [--token <token>]",
|
|
43717
44171
|
" whoami [--api-url <url>] [--token <token>]",
|
|
@@ -43811,11 +44265,11 @@ var LibraryCurationUnavailableError = class extends CliError {
|
|
|
43811
44265
|
|
|
43812
44266
|
// src/config-store.ts
|
|
43813
44267
|
import { chmodSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
43814
|
-
import
|
|
43815
|
-
import
|
|
44268
|
+
import os8 from "node:os";
|
|
44269
|
+
import path18 from "node:path";
|
|
43816
44270
|
function createFileConfigStore(env = process.env) {
|
|
43817
44271
|
const filePath = configFilePath(env);
|
|
43818
|
-
let payload =
|
|
44272
|
+
let payload = readPayload2(filePath);
|
|
43819
44273
|
return {
|
|
43820
44274
|
getApiUrl() {
|
|
43821
44275
|
return payload.apiUrl;
|
|
@@ -43825,7 +44279,7 @@ function createFileConfigStore(env = process.env) {
|
|
|
43825
44279
|
...payload,
|
|
43826
44280
|
apiUrl: apiUrl.replace(/\/+$/, "")
|
|
43827
44281
|
};
|
|
43828
|
-
|
|
44282
|
+
writePayload2(filePath, payload);
|
|
43829
44283
|
},
|
|
43830
44284
|
async resetApiUrl() {
|
|
43831
44285
|
payload = { version: 1 };
|
|
@@ -43835,31 +44289,31 @@ function createFileConfigStore(env = process.env) {
|
|
|
43835
44289
|
}
|
|
43836
44290
|
function configFilePath(env) {
|
|
43837
44291
|
if (env.MYSKILLS_CONFIG_FILE) {
|
|
43838
|
-
return
|
|
44292
|
+
return path18.resolve(env.MYSKILLS_CONFIG_FILE);
|
|
43839
44293
|
}
|
|
43840
44294
|
if (env.MYSKILLS_CONFIG_DIR) {
|
|
43841
|
-
return
|
|
44295
|
+
return path18.join(path18.resolve(env.MYSKILLS_CONFIG_DIR), "config.json");
|
|
43842
44296
|
}
|
|
43843
|
-
const baseDir = env.XDG_CONFIG_HOME ?
|
|
43844
|
-
return
|
|
44297
|
+
const baseDir = env.XDG_CONFIG_HOME ? path18.join(env.XDG_CONFIG_HOME, "myskills-app") : path18.join(os8.homedir(), ".config", "myskills-app");
|
|
44298
|
+
return path18.join(baseDir, "config.json");
|
|
43845
44299
|
}
|
|
43846
|
-
function
|
|
44300
|
+
function readPayload2(filePath) {
|
|
43847
44301
|
try {
|
|
43848
|
-
return
|
|
44302
|
+
return parsePayload2(readFileSync(filePath, "utf8"));
|
|
43849
44303
|
} catch (error62) {
|
|
43850
|
-
if (
|
|
44304
|
+
if (isNodeError3(error62) && error62.code === "ENOENT") {
|
|
43851
44305
|
return { version: 1 };
|
|
43852
44306
|
}
|
|
43853
44307
|
throw error62;
|
|
43854
44308
|
}
|
|
43855
44309
|
}
|
|
43856
|
-
function
|
|
43857
|
-
mkdirSync(
|
|
44310
|
+
function writePayload2(filePath, payload) {
|
|
44311
|
+
mkdirSync(path18.dirname(filePath), { recursive: true, mode: 448 });
|
|
43858
44312
|
writeFileSync(filePath, `${JSON.stringify(payload, null, 2)}
|
|
43859
44313
|
`, { mode: 384 });
|
|
43860
44314
|
chmodSync(filePath, 384);
|
|
43861
44315
|
}
|
|
43862
|
-
function
|
|
44316
|
+
function parsePayload2(raw) {
|
|
43863
44317
|
const parsed = JSON.parse(raw);
|
|
43864
44318
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
43865
44319
|
throw new Error("Config file must contain a JSON object.");
|
|
@@ -43873,198 +44327,6 @@ function parsePayload(raw) {
|
|
|
43873
44327
|
apiUrl: typeof record5.apiUrl === "string" && record5.apiUrl ? record5.apiUrl.replace(/\/+$/, "") : void 0
|
|
43874
44328
|
};
|
|
43875
44329
|
}
|
|
43876
|
-
function isNodeError2(error62) {
|
|
43877
|
-
return error62 instanceof Error && "code" in error62;
|
|
43878
|
-
}
|
|
43879
|
-
|
|
43880
|
-
// src/token-store.ts
|
|
43881
|
-
import { createHash as createHash9 } from "node:crypto";
|
|
43882
|
-
import { chmod, mkdir as mkdir5, readFile as readFile4, rm as rm4, writeFile as writeFile2 } from "node:fs/promises";
|
|
43883
|
-
import os7 from "node:os";
|
|
43884
|
-
import path17 from "node:path";
|
|
43885
|
-
var KEYRING_SERVICE = "ai.jarel.myskills.cli";
|
|
43886
|
-
function createTokenStore(env = process.env, namespace) {
|
|
43887
|
-
const fileStore = createFileTokenStore(env);
|
|
43888
|
-
if (env.MYSKILLS_TOKEN_STORE === "file" || env.MYSKILLS_TOKEN_FILE) {
|
|
43889
|
-
return fileStore;
|
|
43890
|
-
}
|
|
43891
|
-
return createKeyringTokenStore(fileStore, void 0, namespace);
|
|
43892
|
-
}
|
|
43893
|
-
function createFileTokenStore(env = process.env) {
|
|
43894
|
-
const filePath = tokenFilePath(env);
|
|
43895
|
-
return {
|
|
43896
|
-
async get(apiUrl) {
|
|
43897
|
-
return (await readPayload2(filePath)).tokens[normalizeApiUrl(apiUrl)] ?? null;
|
|
43898
|
-
},
|
|
43899
|
-
async set(apiUrl, token) {
|
|
43900
|
-
const payload = await readPayload2(filePath);
|
|
43901
|
-
payload.tokens[normalizeApiUrl(apiUrl)] = token;
|
|
43902
|
-
await writePayload2(filePath, payload);
|
|
43903
|
-
},
|
|
43904
|
-
async delete(apiUrl) {
|
|
43905
|
-
const payload = await readPayload2(filePath);
|
|
43906
|
-
delete payload.tokens[normalizeApiUrl(apiUrl)];
|
|
43907
|
-
if (Object.keys(payload.tokens).length === 0) {
|
|
43908
|
-
await rm4(filePath, { force: true });
|
|
43909
|
-
return;
|
|
43910
|
-
}
|
|
43911
|
-
await writePayload2(filePath, payload);
|
|
43912
|
-
},
|
|
43913
|
-
describe() {
|
|
43914
|
-
return {
|
|
43915
|
-
backend: "file",
|
|
43916
|
-
filePath
|
|
43917
|
-
};
|
|
43918
|
-
}
|
|
43919
|
-
};
|
|
43920
|
-
}
|
|
43921
|
-
function createKeyringTokenStore(fallback, backend = nativeKeyringBackend, namespace) {
|
|
43922
|
-
const prefix = namespace === void 0 ? void 0 : `config-profile:${createHash9("sha256").update(namespace).digest("hex")}:`;
|
|
43923
|
-
const credentialKey = (apiUrl) => prefix === void 0 ? apiUrl : `${prefix}${normalizeApiUrl(apiUrl)}`;
|
|
43924
|
-
let usedFallback = false;
|
|
43925
|
-
return {
|
|
43926
|
-
async get(apiUrl) {
|
|
43927
|
-
let raw;
|
|
43928
|
-
try {
|
|
43929
|
-
raw = await backend.get(credentialKey(apiUrl));
|
|
43930
|
-
} catch {
|
|
43931
|
-
throw new Error("Cannot read the OS keyring. Unlock or restore keyring access, or explicitly select MYSKILLS_TOKEN_STORE=file.");
|
|
43932
|
-
}
|
|
43933
|
-
if (raw === null) {
|
|
43934
|
-
const token2 = await fallback.get(apiUrl);
|
|
43935
|
-
usedFallback = token2 !== null;
|
|
43936
|
-
return token2;
|
|
43937
|
-
}
|
|
43938
|
-
let token;
|
|
43939
|
-
try {
|
|
43940
|
-
token = parseStoredToken(JSON.parse(raw));
|
|
43941
|
-
} catch {
|
|
43942
|
-
token = null;
|
|
43943
|
-
}
|
|
43944
|
-
if (!token) {
|
|
43945
|
-
throw new Error("The OS keyring credential has an invalid format. Remove it with myskills logout, then log in again.");
|
|
43946
|
-
}
|
|
43947
|
-
usedFallback = false;
|
|
43948
|
-
return token;
|
|
43949
|
-
},
|
|
43950
|
-
async set(apiUrl, token) {
|
|
43951
|
-
try {
|
|
43952
|
-
await backend.set(credentialKey(apiUrl), JSON.stringify(token));
|
|
43953
|
-
} catch {
|
|
43954
|
-
throw new Error("Cannot save the token in the OS keyring. Unlock or restore keyring access, or explicitly select MYSKILLS_TOKEN_STORE=file.");
|
|
43955
|
-
}
|
|
43956
|
-
usedFallback = false;
|
|
43957
|
-
try {
|
|
43958
|
-
await fallback.delete(apiUrl);
|
|
43959
|
-
} catch {
|
|
43960
|
-
throw new Error("The token was saved in the OS keyring, but the older file credential could not be removed. Token storage cleanup is incomplete.");
|
|
43961
|
-
}
|
|
43962
|
-
},
|
|
43963
|
-
async delete(apiUrl) {
|
|
43964
|
-
const results = await Promise.allSettled([backend.delete(credentialKey(apiUrl)), fallback.delete(apiUrl)]);
|
|
43965
|
-
const failed = results.flatMap((result, index) => result.status === "rejected" ? [index === 0 ? "OS keyring" : "file"] : []);
|
|
43966
|
-
if (failed.length > 0) {
|
|
43967
|
-
throw new Error(`Logout cleanup is incomplete: could not remove the ${failed.join(" and ")} credential. Restore storage access and retry logout.`);
|
|
43968
|
-
}
|
|
43969
|
-
usedFallback = false;
|
|
43970
|
-
},
|
|
43971
|
-
async describe() {
|
|
43972
|
-
const fallbackInfo = await fallback.describe?.();
|
|
43973
|
-
if (usedFallback && fallbackInfo) {
|
|
43974
|
-
return fallbackInfo;
|
|
43975
|
-
}
|
|
43976
|
-
return {
|
|
43977
|
-
backend: "keyring",
|
|
43978
|
-
fallbackFilePath: fallbackInfo?.filePath
|
|
43979
|
-
};
|
|
43980
|
-
}
|
|
43981
|
-
};
|
|
43982
|
-
}
|
|
43983
|
-
var nativeKeyringBackend = {
|
|
43984
|
-
async get(apiUrl) {
|
|
43985
|
-
const { Entry } = await import("@napi-rs/keyring");
|
|
43986
|
-
return new Entry(KEYRING_SERVICE, keyringAccount(apiUrl)).getPassword();
|
|
43987
|
-
},
|
|
43988
|
-
async set(apiUrl, raw) {
|
|
43989
|
-
const { Entry } = await import("@napi-rs/keyring");
|
|
43990
|
-
new Entry(KEYRING_SERVICE, keyringAccount(apiUrl)).setPassword(raw);
|
|
43991
|
-
},
|
|
43992
|
-
async delete(apiUrl) {
|
|
43993
|
-
const { Entry } = await import("@napi-rs/keyring");
|
|
43994
|
-
new Entry(KEYRING_SERVICE, keyringAccount(apiUrl)).deletePassword();
|
|
43995
|
-
}
|
|
43996
|
-
};
|
|
43997
|
-
function tokenFilePath(env) {
|
|
43998
|
-
if (env.MYSKILLS_TOKEN_FILE) {
|
|
43999
|
-
return path17.resolve(env.MYSKILLS_TOKEN_FILE);
|
|
44000
|
-
}
|
|
44001
|
-
if (env.MYSKILLS_CONFIG_DIR) {
|
|
44002
|
-
return path17.join(path17.resolve(env.MYSKILLS_CONFIG_DIR), "tokens.json");
|
|
44003
|
-
}
|
|
44004
|
-
const baseDir = env.XDG_CONFIG_HOME ? path17.join(env.XDG_CONFIG_HOME, "myskills-app") : path17.join(os7.homedir(), ".config", "myskills-app");
|
|
44005
|
-
return path17.join(baseDir, "tokens.json");
|
|
44006
|
-
}
|
|
44007
|
-
async function readPayload2(filePath) {
|
|
44008
|
-
try {
|
|
44009
|
-
const raw = await readFile4(filePath, "utf8");
|
|
44010
|
-
return parsePayload2(raw);
|
|
44011
|
-
} catch (error62) {
|
|
44012
|
-
if (isNodeError3(error62) && error62.code === "ENOENT") {
|
|
44013
|
-
return { version: 1, tokens: {} };
|
|
44014
|
-
}
|
|
44015
|
-
throw error62;
|
|
44016
|
-
}
|
|
44017
|
-
}
|
|
44018
|
-
async function writePayload2(filePath, payload) {
|
|
44019
|
-
await mkdir5(path17.dirname(filePath), { recursive: true, mode: 448 });
|
|
44020
|
-
await writeFile2(filePath, `${JSON.stringify(payload, null, 2)}
|
|
44021
|
-
`, { mode: 384 });
|
|
44022
|
-
await chmod(filePath, 384);
|
|
44023
|
-
}
|
|
44024
|
-
function parsePayload2(raw) {
|
|
44025
|
-
let parsed;
|
|
44026
|
-
try {
|
|
44027
|
-
parsed = JSON.parse(raw);
|
|
44028
|
-
} catch {
|
|
44029
|
-
throw new Error("Token store file contains invalid JSON. Repair or remove the file before logging in again.");
|
|
44030
|
-
}
|
|
44031
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
44032
|
-
throw new Error("Token store file must contain a JSON object.");
|
|
44033
|
-
}
|
|
44034
|
-
const record5 = parsed;
|
|
44035
|
-
if (record5.version !== 1 || !record5.tokens || typeof record5.tokens !== "object" || Array.isArray(record5.tokens)) {
|
|
44036
|
-
throw new Error("Token store file has an unsupported format.");
|
|
44037
|
-
}
|
|
44038
|
-
const tokens = {};
|
|
44039
|
-
for (const [apiUrl, token] of Object.entries(record5.tokens)) {
|
|
44040
|
-
const parsedToken = parseStoredToken(token);
|
|
44041
|
-
if (parsedToken) {
|
|
44042
|
-
tokens[normalizeApiUrl(apiUrl)] = parsedToken;
|
|
44043
|
-
}
|
|
44044
|
-
}
|
|
44045
|
-
return { version: 1, tokens };
|
|
44046
|
-
}
|
|
44047
|
-
function parseStoredToken(input2) {
|
|
44048
|
-
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) {
|
|
44049
|
-
return null;
|
|
44050
|
-
}
|
|
44051
|
-
const record5 = input2;
|
|
44052
|
-
if (record5.kind !== "session" && record5.kind !== "api" || typeof record5.token !== "string" || !record5.token) {
|
|
44053
|
-
return null;
|
|
44054
|
-
}
|
|
44055
|
-
return {
|
|
44056
|
-
kind: record5.kind,
|
|
44057
|
-
token: record5.token,
|
|
44058
|
-
email: typeof record5.email === "string" ? record5.email : void 0,
|
|
44059
|
-
expiresAt: typeof record5.expiresAt === "string" ? record5.expiresAt : void 0
|
|
44060
|
-
};
|
|
44061
|
-
}
|
|
44062
|
-
function normalizeApiUrl(apiUrl) {
|
|
44063
|
-
return apiUrl.replace(/\/+$/, "");
|
|
44064
|
-
}
|
|
44065
|
-
function keyringAccount(apiUrl) {
|
|
44066
|
-
return `api-url:${Buffer.from(normalizeApiUrl(apiUrl)).toString("base64url")}`;
|
|
44067
|
-
}
|
|
44068
44330
|
function isNodeError3(error62) {
|
|
44069
44331
|
return error62 instanceof Error && "code" in error62;
|
|
44070
44332
|
}
|
|
@@ -44185,7 +44447,7 @@ try {
|
|
|
44185
44447
|
const exitCode = await runCli(process.argv.slice(2), {
|
|
44186
44448
|
env: process.env,
|
|
44187
44449
|
fetch: fetchImpl,
|
|
44188
|
-
createStores: (env, namespace) => ({ configStore: createFileConfigStore(env), tokenStore: createTokenStore(env, namespace) }),
|
|
44450
|
+
createStores: (env, namespace) => ({ configStore: createFileConfigStore(env), tokenStore: createTokenStore(env, namespace), deviceLoginStore: createDeviceLoginStore(namespace) }),
|
|
44189
44451
|
prompt,
|
|
44190
44452
|
io: {
|
|
44191
44453
|
stdout: (line) => console.log(line),
|