@hasna/skills 0.10.88 → 0.10.90
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 +36 -3
- package/bin/index.js +196 -102
- package/bin/mcp.js +80 -27
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/cli/commands/agent-integration.d.ts +20 -0
- package/dist/cli/commands/context.d.ts +4 -0
- package/dist/index.js +30 -13
- package/dist/lib/selection-resolver.d.ts +13 -1
- package/dist/lib/skill-context.d.ts +11 -0
- package/dist/runtime-prerequisites.js +3 -2
- package/dist/sdk/index.js +5 -2
- package/package.json +1 -1
package/bin/mcp.js
CHANGED
|
@@ -38,7 +38,7 @@ var package_default;
|
|
|
38
38
|
var init_package = __esm(() => {
|
|
39
39
|
package_default = {
|
|
40
40
|
name: "@hasna/skills",
|
|
41
|
-
version: "0.10.
|
|
41
|
+
version: "0.10.90",
|
|
42
42
|
description: "Skills library for AI coding agents",
|
|
43
43
|
type: "module",
|
|
44
44
|
bin: {
|
|
@@ -22957,7 +22957,8 @@ var init_codex_native_compatibility = __esm(() => {
|
|
|
22957
22957
|
"codex-cli 0.162.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
22958
22958
|
"codex-cli 0.163.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
22959
22959
|
"codex-cli 0.164.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
22960
|
-
"codex-cli 0.165.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
22960
|
+
"codex-cli 0.165.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
22961
|
+
"codex-cli 0.166.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
22961
22962
|
};
|
|
22962
22963
|
SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version2) => supportsCodexNativeCapability(version2, "hooks")));
|
|
22963
22964
|
});
|
|
@@ -37171,6 +37172,7 @@ var init_selected_document = __esm(() => {
|
|
|
37171
37172
|
});
|
|
37172
37173
|
|
|
37173
37174
|
// src/lib/selection-resolver.ts
|
|
37175
|
+
import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
|
|
37174
37176
|
async function resolveSelectionContext(profileId, options = {}) {
|
|
37175
37177
|
const sessionState = options.sessionId ? readSkillSessionSnapshotIfExists(options.sessionId, options) : null;
|
|
37176
37178
|
const session = sessionState?.receipt ?? null;
|
|
@@ -37255,21 +37257,70 @@ function unknownNameRefusal(slug, profile) {
|
|
|
37255
37257
|
return `Skill '${slug}' is not selected by this Skills profile or project lock.${hint} ` + `Read the accepted names with 'skills search <term>' or 'skills list --all --json'; accept one with 'skills pin <name>'. ${ACCEPTED_FORM}`;
|
|
37256
37258
|
}
|
|
37257
37259
|
async function loadSelectedSkill(spec, profileId, options = {}) {
|
|
37258
|
-
|
|
37260
|
+
if (!options.cacheFirst)
|
|
37261
|
+
return readSelectedSkill(spec, profileId, options);
|
|
37262
|
+
const { cacheFirst: _cacheFirst, cached: _cached, authority, ...service } = options;
|
|
37263
|
+
try {
|
|
37264
|
+
return await readSelectedSkill(spec, profileId, { ...service, authority, cached: true });
|
|
37265
|
+
} catch (cacheError) {
|
|
37266
|
+
if (!(cacheError instanceof SkillSelectionError) || !RECOVERABLE_CACHE_ERRORS.has(cacheError.code))
|
|
37267
|
+
throw cacheError;
|
|
37268
|
+
try {
|
|
37269
|
+
return await readSelectedSkill(spec, profileId, service);
|
|
37270
|
+
} catch (serviceError) {
|
|
37271
|
+
if (!(serviceError instanceof SkillSelectionError) || serviceError.code !== "SKILLS_API_UNAVAILABLE")
|
|
37272
|
+
throw serviceError;
|
|
37273
|
+
throw new SkillSelectionError(cacheError.code, "The verified cache can't serve this load and the Skills service can't be reached from here, so it has to run where the network is available. `skills sync` doesn't renew a session's pin.");
|
|
37274
|
+
}
|
|
37275
|
+
}
|
|
37276
|
+
}
|
|
37277
|
+
async function readSelectedSkill(spec, profileId, options) {
|
|
37278
|
+
const context = await resolveSelectionContext(profileId, options).catch((error61) => {
|
|
37279
|
+
if (options.cached && options.sessionId && error61 instanceof SkillSelectionError && error61.code === "CACHED_PROFILE_EXPIRED" && readSkillSessionSnapshotIfExists(options.sessionId, options)) {
|
|
37280
|
+
throw new SkillSelectionError("CACHED_PROFILE_EXPIRED", "This session's Skills pin was verified too long ago to read from the cache. Run the same command without --cached: that keeps the pin but needs the network and sign-in. `skills sync` doesn't renew a session's pin.");
|
|
37281
|
+
}
|
|
37282
|
+
throw error61;
|
|
37283
|
+
});
|
|
37259
37284
|
const selection = exactProfileSelection(spec, context.receipt.profile);
|
|
37260
37285
|
const entries = await readSelectedEntries(selection, context, options);
|
|
37261
37286
|
const { file: file2, content } = readSelectedDocument(entries, options.file);
|
|
37262
37287
|
const receipt = { ...selection, file: file2, source: options.cached ? "verified-cache" : "api", verifiedAt: context.receipt.verifiedAt };
|
|
37263
|
-
|
|
37264
|
-
|
|
37265
|
-
|
|
37266
|
-
|
|
37267
|
-
|
|
37268
|
-
|
|
37269
|
-
|
|
37270
|
-
|
|
37288
|
+
const sessionRecorded = options.sessionId ? recordSessionLoad(options.sessionId, selection, context, options) : undefined;
|
|
37289
|
+
return { content, selection, receipt, ...sessionRecorded === undefined ? {} : { sessionRecorded } };
|
|
37290
|
+
}
|
|
37291
|
+
function isUnwritableStore(error61) {
|
|
37292
|
+
for (let cause = error61, depth = 0;cause && depth < 4; cause = cause.cause, depth++)
|
|
37293
|
+
if (UNWRITABLE_CODES.has(cause.code))
|
|
37294
|
+
return true;
|
|
37295
|
+
return false;
|
|
37296
|
+
}
|
|
37297
|
+
function recordSessionLoad(sessionId, selection, context, options) {
|
|
37298
|
+
const key2 = selectionKey(selection);
|
|
37299
|
+
let snapshot2 = context.sessionSnapshot;
|
|
37300
|
+
for (let attempt = 0;attempt < SESSION_LOAD_RECORD_ATTEMPTS; attempt++) {
|
|
37301
|
+
try {
|
|
37302
|
+
const session = {
|
|
37303
|
+
...context.receipt,
|
|
37304
|
+
sessionId,
|
|
37305
|
+
loaded: [...new Set([...context.session?.loaded ?? [], key2])],
|
|
37306
|
+
...context.projectLock ? { projectLock: context.projectLock } : {}
|
|
37307
|
+
};
|
|
37308
|
+
writeSkillSession(session, { current: snapshot2, parent: context.parentSnapshot }, options);
|
|
37309
|
+
return true;
|
|
37310
|
+
} catch (error61) {
|
|
37311
|
+
const blocked = isUnwritableStore(error61) || error61 instanceof SkillSelectionError && error61.code === "SESSION_WRITE_BUSY";
|
|
37312
|
+
if (!blocked && !(error61 instanceof SkillSelectionError && error61.code === "SESSION_CONTEXT_CONFLICT"))
|
|
37313
|
+
throw error61;
|
|
37314
|
+
const current = readSkillSessionSnapshotIfExists(sessionId, options);
|
|
37315
|
+
if (current ? !isDeepStrictEqual5(current.receipt.profile, context.receipt.profile) : !blocked) {
|
|
37316
|
+
throw new SkillSelectionError("SESSION_CONTEXT_CONFLICT", "The Skills session's pin changed while this skill was loading, so its content no longer belongs to that pin. Load it again.");
|
|
37317
|
+
}
|
|
37318
|
+
if (blocked)
|
|
37319
|
+
return false;
|
|
37320
|
+
snapshot2 = skillSessionSnapshotBinding(current);
|
|
37321
|
+
}
|
|
37271
37322
|
}
|
|
37272
|
-
return
|
|
37323
|
+
return false;
|
|
37273
37324
|
}
|
|
37274
37325
|
async function pinSelectedSkillVersion(spec, profileId, options) {
|
|
37275
37326
|
const context = await resolveSelectionContext(profileId, options);
|
|
@@ -37298,13 +37349,15 @@ async function selectedSkillRequirements(spec, profileId, options = {}) {
|
|
|
37298
37349
|
}
|
|
37299
37350
|
return { ...getSkillRequirementsFromContent(selection.slug, texts, dependencies), selection };
|
|
37300
37351
|
}
|
|
37301
|
-
var ACCEPTED_FORM = "Accepted form: '<slug>' or '<slug>@<version>'.";
|
|
37352
|
+
var ACCEPTED_FORM = "Accepted form: '<slug>' or '<slug>@<version>'.", RECOVERABLE_CACHE_ERRORS, SESSION_LOAD_RECORD_ATTEMPTS = 8, UNWRITABLE_CODES;
|
|
37302
37353
|
var init_selection_resolver = __esm(() => {
|
|
37303
37354
|
init_profile_client();
|
|
37304
37355
|
init_skillinfo();
|
|
37305
37356
|
init_search();
|
|
37306
37357
|
init_selected_document();
|
|
37307
37358
|
init_selection_cache();
|
|
37359
|
+
RECOVERABLE_CACHE_ERRORS = new Set(["CACHED_PROFILE_EXPIRED", "CACHED_PROFILE_MISSING", "CACHED_BUNDLE_MISSING"]);
|
|
37360
|
+
UNWRITABLE_CODES = new Set(["EACCES", "EPERM", "EROFS", "ENOSPC", "EDQUOT"]);
|
|
37308
37361
|
});
|
|
37309
37362
|
|
|
37310
37363
|
// src/lib/selected-manifest.ts
|
|
@@ -37916,7 +37969,7 @@ var init_codex_hook_discovery_recovery = __esm(() => {
|
|
|
37916
37969
|
import { createHash as createHash26 } from "crypto";
|
|
37917
37970
|
import { lstatSync as lstatSync25, opendirSync as opendirSync4, readFileSync as readFileSync18, readdirSync as readdirSync9, realpathSync as realpathSync8 } from "fs";
|
|
37918
37971
|
import { basename as basename14, dirname as dirname24, isAbsolute as isAbsolute22, join as join33, relative as relative7, resolve as resolve23, sep as sep11 } from "path";
|
|
37919
|
-
import { isDeepStrictEqual as
|
|
37972
|
+
import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
|
|
37920
37973
|
function discoveryExecutable(agent) {
|
|
37921
37974
|
const command = DISCOVERY_RUNTIME_COMMANDS[agent];
|
|
37922
37975
|
const found = command ? Bun.which(command) : null;
|
|
@@ -38063,8 +38116,8 @@ function projectNativeDiscoveryFields(text2, format, fields2, path) {
|
|
|
38063
38116
|
}
|
|
38064
38117
|
function isSupersededSettingsProjection(agent, configPath, source) {
|
|
38065
38118
|
if (agent === "sumi")
|
|
38066
|
-
return source.path === configPath && source.format === "json" &&
|
|
38067
|
-
return agent === "codex" && source.path === configPath && source.format === "toml" &&
|
|
38119
|
+
return source.path === configPath && source.format === "json" && isDeepStrictEqual6(source.fields, [...SUMI_DISCOVERY_PROJECTION_FIELDS]);
|
|
38120
|
+
return agent === "codex" && source.path === configPath && source.format === "toml" && isDeepStrictEqual6(source.fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]);
|
|
38068
38121
|
}
|
|
38069
38122
|
function supersedesSettingsProjection(agent, sources, configPath) {
|
|
38070
38123
|
if (agent === "sumi")
|
|
@@ -38085,7 +38138,7 @@ function projected(source, changes, budget3 = discoveryByteBudget()) {
|
|
|
38085
38138
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || !Array.isArray(source.hookSources))
|
|
38086
38139
|
throw new Error("Codex V6 requires exact reviewed hook sources");
|
|
38087
38140
|
const current = captureCodexSettingsV6(source.path, source.hookSources, budget3);
|
|
38088
|
-
if (current.sha256 !== source.sha256 || !
|
|
38141
|
+
if (current.sha256 !== source.sha256 || !isDeepStrictEqual6(current.hookSources, source.hookSources))
|
|
38089
38142
|
throw new Error("Codex hook provider or dependency changed; explicit discovery review required");
|
|
38090
38143
|
return changes ? captureCodexSettingsV6(source.path, source.hookSources, budget3, changes).sha256 : current.sha256;
|
|
38091
38144
|
}
|
|
@@ -38361,7 +38414,7 @@ function verifyCodexSemanticCacheDiscovery(binding, reviewedRootAliases, narrowe
|
|
|
38361
38414
|
if (reviewedRootAliases !== undefined) {
|
|
38362
38415
|
const alias = reviewedRootAliases.find((alias2) => alias2.agent === "codex");
|
|
38363
38416
|
const expected = alias ? { alias: alias.alias, target: alias.target } : null;
|
|
38364
|
-
if (!
|
|
38417
|
+
if (!isDeepStrictEqual6(proof.hookRootAlias, expected))
|
|
38365
38418
|
throw new Error("Semantic cache hook alias differs from reviewed root binding");
|
|
38366
38419
|
}
|
|
38367
38420
|
const controls = binding.codexDisabledPluginSkills;
|
|
@@ -38371,7 +38424,7 @@ function verifyCodexSemanticCacheDiscovery(binding, reviewedRootAliases, narrowe
|
|
|
38371
38424
|
if (controls.some((control) => dirname24(dirname24(control.pluginParent)) !== cacheRoot))
|
|
38372
38425
|
throw new Error("Codex semantic cache names another enrolled cache");
|
|
38373
38426
|
const reviewedHookParents = proof.reviewedHookParents ?? [];
|
|
38374
|
-
if (!Array.isArray(reviewedHookParents) || reviewedHookParents.length > 4096 || reviewedHookParents.some((parent) => !parent || !(parent.installation === "remote-receipt" && Object.keys(parent).sort().join(",") === "installation,namespace,pluginId,pluginParent,remotePluginId,role" && typeof parent.remotePluginId === "string" || parent.installation === "local-marketplace" && Object.keys(parent).sort().join(",") === "installation,marketplaceSha256,marketplaceSourcePath,namespace,pluginId,pluginParent,role" && typeof parent.marketplaceSourcePath === "string" && /^[a-f0-9]{64}$/.test(parent.marketplaceSha256 ?? "")) || parent.role !== "reviewed-hook" || typeof parent.pluginId !== "string" || typeof parent.namespace !== "string" || typeof parent.pluginParent !== "string") || new Set(reviewedHookParents.map((parent) => parent.pluginParent)).size !== reviewedHookParents.length || !
|
|
38427
|
+
if (!Array.isArray(reviewedHookParents) || reviewedHookParents.length > 4096 || reviewedHookParents.some((parent) => !parent || !(parent.installation === "remote-receipt" && Object.keys(parent).sort().join(",") === "installation,namespace,pluginId,pluginParent,remotePluginId,role" && typeof parent.remotePluginId === "string" || parent.installation === "local-marketplace" && Object.keys(parent).sort().join(",") === "installation,marketplaceSha256,marketplaceSourcePath,namespace,pluginId,pluginParent,role" && typeof parent.marketplaceSourcePath === "string" && /^[a-f0-9]{64}$/.test(parent.marketplaceSha256 ?? "")) || parent.role !== "reviewed-hook" || typeof parent.pluginId !== "string" || typeof parent.namespace !== "string" || typeof parent.pluginParent !== "string") || new Set(reviewedHookParents.map((parent) => parent.pluginParent)).size !== reviewedHookParents.length || !isDeepStrictEqual6((proof.witness.hookParents ?? []).map(({ manifestSha256: _manifest, hooksSha256: _hooks, receiptSha256: _receipt, ...parent }) => parent), reviewedHookParents)) {
|
|
38375
38428
|
throw new Error("Invalid reviewed native-hook cache role");
|
|
38376
38429
|
}
|
|
38377
38430
|
for (const parent of reviewedHookParents)
|
|
@@ -38381,7 +38434,7 @@ function verifyCodexSemanticCacheDiscovery(binding, reviewedRootAliases, narrowe
|
|
|
38381
38434
|
const hookParentPaths = reviewedHookParents.map((parent) => parent.pluginParent);
|
|
38382
38435
|
const sources = binding.sources.filter((source) => codexSemanticCacheSourceRole(source, cacheRoot, parents3, hookParentPaths));
|
|
38383
38436
|
const directories = (binding.directories ?? []).filter((directory) => codexSemanticCacheDirectoryRole(directory.path, cacheRoot));
|
|
38384
|
-
if (!directories.length || !
|
|
38437
|
+
if (!directories.length || !isDeepStrictEqual6(sources, proof.supersededSources) || !isDeepStrictEqual6(directories, proof.supersededDirectories))
|
|
38385
38438
|
throw new Error("Codex semantic cache provenance changed");
|
|
38386
38439
|
const configPath = proof.configPath;
|
|
38387
38440
|
if (!isAbsolute22(configPath) || resolve23(configPath) !== configPath || basename14(configPath) !== "config.toml" || /[\x00-\x1f\x7f]/.test(configPath))
|
|
@@ -38427,8 +38480,8 @@ function verifyDiscovery(binding, codexRecovery, reviewedRootAliases, witnessTol
|
|
|
38427
38480
|
if (omitted.some((root) => !retiredRoots.includes(root)))
|
|
38428
38481
|
throw new Error("Missing reviewed directory membership inventory; provide a fresh discovery review");
|
|
38429
38482
|
const current = captureDiscoveryDirectoryProjection(ordinary.map((item) => item.path), retiredRoots).map(({ entries, ...item }) => item);
|
|
38430
|
-
if (!
|
|
38431
|
-
const changed = projection.filter((item, index) => !
|
|
38483
|
+
if (!isDeepStrictEqual6(current, projection)) {
|
|
38484
|
+
const changed = projection.filter((item, index) => !isDeepStrictEqual6(current[index], item));
|
|
38432
38485
|
for (const item of changed.length && current.length === projection.length ? changed : [null])
|
|
38433
38486
|
witnessChanged(new NativeDiscoveryWitnessChange("membership", item?.path ?? null, "Native discovery directory membership changed outside retired Codex roots"), witnessTolerance, item !== null && witnessTolerance?.acceptsMembership(item.path) === true);
|
|
38434
38487
|
}
|
|
@@ -38451,7 +38504,7 @@ function verifyDiscovery(binding, codexRecovery, reviewedRootAliases, witnessTol
|
|
|
38451
38504
|
safe6(source.path);
|
|
38452
38505
|
continue;
|
|
38453
38506
|
}
|
|
38454
|
-
if (semanticCache?.supersededSources.some((previous) =>
|
|
38507
|
+
if (semanticCache?.supersededSources.some((previous) => isDeepStrictEqual6(previous, source))) {
|
|
38455
38508
|
safe6(source.path);
|
|
38456
38509
|
continue;
|
|
38457
38510
|
}
|
|
@@ -38950,7 +39003,7 @@ function resolveDiscovery(options, exclusion) {
|
|
|
38950
39003
|
const parents3 = [...new Set([...(retained.codexDisabledPluginSkills ?? []).map((control) => control.pluginParent), ...proof.appOnlyParents.map((parent) => parent.pluginParent)])];
|
|
38951
39004
|
covered = covered.filter((source) => !codexSemanticCacheSourceRole(source, proof.witness.cacheRoot, parents3));
|
|
38952
39005
|
}
|
|
38953
|
-
if (covered.some((source) => !retained.sources.some((saved) =>
|
|
39006
|
+
if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual6(saved, source))) || [...roots].some((root) => !retained.roots.includes(root)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
|
|
38954
39007
|
unresolved("retained review is missing current runtime discovery coverage");
|
|
38955
39008
|
return retained;
|
|
38956
39009
|
}
|
|
@@ -39008,7 +39061,7 @@ function resolveDiscovery(options, exclusion) {
|
|
|
39008
39061
|
throw new Error("Retired native materialization changed during discovery review");
|
|
39009
39062
|
}
|
|
39010
39063
|
const combined = [...reviewedSources, ...reviewedSourcesWithManifestProjection];
|
|
39011
|
-
const unique = combined.filter((source, index) => combined.findIndex((candidate) =>
|
|
39064
|
+
const unique = combined.filter((source, index) => combined.findIndex((candidate) => isDeepStrictEqual6(candidate, source)) === index);
|
|
39012
39065
|
return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
|
|
39013
39066
|
}
|
|
39014
39067
|
function plugin(root) {
|
|
@@ -47756,7 +47809,7 @@ var init_execution_grants = __esm(() => {
|
|
|
47756
47809
|
});
|
|
47757
47810
|
|
|
47758
47811
|
// src/lib/execution-grant-client.ts
|
|
47759
|
-
import { isDeepStrictEqual as
|
|
47812
|
+
import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
|
|
47760
47813
|
function id(value) {
|
|
47761
47814
|
if (!grantIdentifier(value))
|
|
47762
47815
|
throw new Error("Invalid execution grant profile or revision identifier.");
|
|
@@ -47799,7 +47852,7 @@ async function resolveExecutionGrant(input2) {
|
|
|
47799
47852
|
if (!grantRecord(value) || Object.keys(value).length !== 3 || !grantIdentifier(value.policyRevision) || !grantIdentifier(value.grantId) || !grantRecord(value.bindings)) {
|
|
47800
47853
|
throw new SkillSelectionError("INVALID_EXECUTION_GRANT", "The Skills API returned an invalid execution grant.");
|
|
47801
47854
|
}
|
|
47802
|
-
if (!
|
|
47855
|
+
if (!isDeepStrictEqual7(value.bindings.selection, snapshot2.selection) || !isDeepStrictEqual7(value.bindings.consumer, snapshot2.consumer)) {
|
|
47803
47856
|
throw new SkillSelectionError("EXECUTION_GRANT_SCOPE_MISMATCH", "The Skills API returned a grant for a different selection or consumer.");
|
|
47804
47857
|
}
|
|
47805
47858
|
return value;
|
package/bin/migrate.js
CHANGED
package/bin/server.js
CHANGED
|
@@ -24140,7 +24140,7 @@ restoreLaunchCwd();
|
|
|
24140
24140
|
// package.json
|
|
24141
24141
|
var package_default = {
|
|
24142
24142
|
name: "@hasna/skills",
|
|
24143
|
-
version: "0.10.
|
|
24143
|
+
version: "0.10.90",
|
|
24144
24144
|
description: "Skills library for AI coding agents",
|
|
24145
24145
|
type: "module",
|
|
24146
24146
|
bin: {
|
package/bin/worker.js
CHANGED
|
@@ -24143,7 +24143,7 @@ import { randomUUID as randomUUID6 } from "crypto";
|
|
|
24143
24143
|
// package.json
|
|
24144
24144
|
var package_default = {
|
|
24145
24145
|
name: "@hasna/skills",
|
|
24146
|
-
version: "0.10.
|
|
24146
|
+
version: "0.10.90",
|
|
24147
24147
|
description: "Skills library for AI coding agents",
|
|
24148
24148
|
type: "module",
|
|
24149
24149
|
bin: {
|
|
@@ -16,12 +16,32 @@ export declare const MANAGED_HOOK_CONTEXT_MAX_CHARS = 12000;
|
|
|
16
16
|
export declare const MANAGED_HOOK_CONTEXT_MAX_SKILLS = 2;
|
|
17
17
|
/** Part of the cap kept for the policy, notices and up to ten load offers. */
|
|
18
18
|
export declare const MANAGED_HOOK_CONTEXT_RESERVE_CHARS = 2500;
|
|
19
|
+
/**
|
|
20
|
+
* A managed hook injects an unnamed prompt match only for a phrase of at least
|
|
21
|
+
* this many words. A one-word trigger says little about a turn's subject, more
|
|
22
|
+
* so in long text ("effect", "rollback", "handoff"), and several of them don't
|
|
23
|
+
* add up to a phrase, so such a match is offered as a load command instead
|
|
24
|
+
* (FAO-00144). SKILLS_HOOK_PROMPT_MIN_PHRASE_WORDS can only raise it.
|
|
25
|
+
*/
|
|
26
|
+
export declare const MANAGED_HOOK_PROMPT_MIN_PHRASE_WORDS = 2;
|
|
27
|
+
/** A subagent's start carries no prompt to match against, so its parent's skills are offered, not injected. */
|
|
28
|
+
export declare const MANAGED_HOOK_INHERITED_BODIES = 0;
|
|
19
29
|
/** The effective hook limits: the defaults above, or a valid lower environment override. */
|
|
20
30
|
export declare function managedHookContextLimits(): {
|
|
21
31
|
maxChars: number;
|
|
22
32
|
maxSkills: number;
|
|
23
33
|
bodyChars: number;
|
|
24
34
|
};
|
|
35
|
+
/** The effective phrase length: the default above, or a valid higher environment override. */
|
|
36
|
+
export declare function managedHookPromptMinPhraseWords(): number;
|
|
37
|
+
/**
|
|
38
|
+
* The selection flags one agent's managed hook passes to its context child.
|
|
39
|
+
* Sumi's plugin and Cursor's prompt hook both discard the output of a prompt
|
|
40
|
+
* call and only deliver what a later call restores, so a pointer could never
|
|
41
|
+
* reach their models: it would turn a delivered body into nothing. They keep the
|
|
42
|
+
* plain selection until they can carry pointers.
|
|
43
|
+
*/
|
|
44
|
+
export declare function managedHookSelectionArgs(agent: IntegrationAgent): string[];
|
|
25
45
|
/** Clamp assembled hook context to the cap at a line boundary, with a fixed note. */
|
|
26
46
|
export declare function capManagedHookContext(context: string, maxChars?: number): string;
|
|
27
47
|
/**
|
|
@@ -5,6 +5,8 @@ export declare function selectedProfileId(explicit?: string): string;
|
|
|
5
5
|
export interface ContextCommandOptions {
|
|
6
6
|
selectionProfile?: string;
|
|
7
7
|
cached?: boolean;
|
|
8
|
+
cacheFirst?: boolean;
|
|
9
|
+
pointerCacheFirst?: boolean;
|
|
8
10
|
autoReconcileSafe?: boolean;
|
|
9
11
|
autoMigrateSessionPin?: boolean;
|
|
10
12
|
backgroundRenewal?: boolean;
|
|
@@ -16,6 +18,8 @@ export interface ContextCommandOptions {
|
|
|
16
18
|
maxChars?: string;
|
|
17
19
|
maxSkills?: string;
|
|
18
20
|
file?: string;
|
|
21
|
+
minPromptPhraseWords?: string;
|
|
22
|
+
inheritedBodies?: string;
|
|
19
23
|
}
|
|
20
24
|
export declare function contextResolverOptions(options: ContextCommandOptions): SelectionResolverOptions;
|
|
21
25
|
export declare function registerContextCommands(parent: Command): void;
|
package/dist/index.js
CHANGED
|
@@ -9722,7 +9722,8 @@ var MEASURED_CODEX_CAPABILITIES = {
|
|
|
9722
9722
|
"codex-cli 0.162.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
9723
9723
|
"codex-cli 0.163.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
9724
9724
|
"codex-cli 0.164.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
9725
|
-
"codex-cli 0.165.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
9725
|
+
"codex-cli 0.165.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
9726
|
+
"codex-cli 0.166.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
9726
9727
|
};
|
|
9727
9728
|
function supportsCodexNativeCapability(version, capability) {
|
|
9728
9729
|
return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
|
|
@@ -16368,7 +16369,7 @@ import { basename as basename15, dirname as dirname27, isAbsolute as isAbsolute2
|
|
|
16368
16369
|
import { homedir as homedir5 } from "os";
|
|
16369
16370
|
import { isAbsolute as isAbsolute25, join as join39, resolve as resolve25 } from "path";
|
|
16370
16371
|
// package.json
|
|
16371
|
-
var version = "0.10.
|
|
16372
|
+
var version = "0.10.90";
|
|
16372
16373
|
var package_default = {
|
|
16373
16374
|
name: "@hasna/skills",
|
|
16374
16375
|
version,
|
|
@@ -24994,6 +24995,8 @@ function unknownNameRefusal(slug, profile) {
|
|
|
24994
24995
|
const hint = close.length > 0 ? ` Did you mean: ${close.join(", ")}?` : "";
|
|
24995
24996
|
return `Skill '${slug}' is not selected by this Skills profile or project lock.${hint} ` + `Read the accepted names with 'skills search <term>' or 'skills list --all --json'; accept one with 'skills pin <name>'. ${ACCEPTED_FORM}`;
|
|
24996
24997
|
}
|
|
24998
|
+
var RECOVERABLE_CACHE_ERRORS = new Set(["CACHED_PROFILE_EXPIRED", "CACHED_PROFILE_MISSING", "CACHED_BUNDLE_MISSING"]);
|
|
24999
|
+
var UNWRITABLE_CODES = new Set(["EACCES", "EPERM", "EROFS", "ENOSPC", "EDQUOT"]);
|
|
24997
25000
|
|
|
24998
25001
|
// src/lib/selected-manifest.ts
|
|
24999
25002
|
function jsonEntry(entries, path) {
|
|
@@ -54368,6 +54371,12 @@ async function buildSkillContextOnce(input2, options, mayResolveAgain) {
|
|
|
54368
54371
|
if (maxChars !== undefined && (!Number.isInteger(maxChars) || maxChars < 512 || maxChars > 64000) || !Number.isInteger(maxSkills) || maxSkills < 1 || maxSkills > 20) {
|
|
54369
54372
|
throw new SkillSelectionError("INVALID_CONTEXT_BUDGET", "Context limits must be 512\u201364000 characters and 1\u201320 skills.");
|
|
54370
54373
|
}
|
|
54374
|
+
const minPromptPhraseWords = options.minPromptPhraseWords ?? 0;
|
|
54375
|
+
const inheritedBodies = options.inheritedBodies ?? HISTORY_BODY_LIMITS["subagent-inherit"];
|
|
54376
|
+
if (!Number.isInteger(minPromptPhraseWords) || minPromptPhraseWords < 0 || !Number.isInteger(inheritedBodies) || inheritedBodies < 0) {
|
|
54377
|
+
throw new SkillSelectionError("INVALID_CONTEXT_BUDGET", "The prompt phrase and inherited body limits must be whole numbers of 0 or more.");
|
|
54378
|
+
}
|
|
54379
|
+
const historyBodyLimits = { ...HISTORY_BODY_LIMITS, "subagent-inherit": inheritedBodies };
|
|
54371
54380
|
const profileId = input2.profileId ?? "default";
|
|
54372
54381
|
const sessionId = input2.sessionId ? input2.agentId ? `${input2.sessionId}:${input2.agentId}` : input2.sessionId : undefined;
|
|
54373
54382
|
if (input2.parentSessionId !== undefined) {
|
|
@@ -54397,8 +54406,9 @@ async function buildSkillContextOnce(input2, options, mayResolveAgain) {
|
|
|
54397
54406
|
const key2 = selectionKey(selection);
|
|
54398
54407
|
if (restoredOrder.has(key2))
|
|
54399
54408
|
return [{ selection, reason: "session-restore", priority: 6, score: 2000, recency: restoredOrder.get(key2) }];
|
|
54400
|
-
|
|
54401
|
-
|
|
54409
|
+
const inherited = inheritedOrder.has(key2) ? { selection, reason: "subagent-inherit", priority: 6, score: 2000, recency: inheritedOrder.get(key2) } : undefined;
|
|
54410
|
+
if (inherited && inheritedBodies > 0)
|
|
54411
|
+
return [inherited];
|
|
54402
54412
|
if (explicit.has(key2))
|
|
54403
54413
|
return [{ selection, reason: "explicit", priority: 5, score: 1000 }];
|
|
54404
54414
|
if (selection.triggers?.always)
|
|
@@ -54407,7 +54417,10 @@ async function buildSkillContextOnce(input2, options, mayResolveAgain) {
|
|
|
54407
54417
|
if (matchedPath)
|
|
54408
54418
|
return [{ selection, reason: "path", priority: 3, score: 500 }];
|
|
54409
54419
|
const match = relevance.get(key2);
|
|
54410
|
-
|
|
54420
|
+
const weak = match !== undefined && (match.weak || match.priority === 1 && !match.phrases.some((phrase) => phrase.split(" ").length >= minPromptPhraseWords));
|
|
54421
|
+
if (match && !(inherited && weak))
|
|
54422
|
+
return [{ selection, reason: "prompt", priority: match.priority, score: match.score, weak }];
|
|
54423
|
+
return inherited ? [inherited] : [];
|
|
54411
54424
|
}).sort((a, b) => b.priority - a.priority || (b.recency ?? -1) - (a.recency ?? -1) || b.score - a.score || a.selection.slug.localeCompare(b.selection.slug));
|
|
54412
54425
|
const historyOffered = new Map;
|
|
54413
54426
|
const candidates = ranked.filter((candidate2) => {
|
|
@@ -54417,6 +54430,9 @@ async function buildSkillContextOnce(input2, options, mayResolveAgain) {
|
|
|
54417
54430
|
historyOffered.set(candidate2.reason, count + 1);
|
|
54418
54431
|
return count < HISTORY_CANDIDATE_LIMIT;
|
|
54419
54432
|
});
|
|
54433
|
+
const pointerSession = sessionId && /^[A-Za-z0-9._:@][A-Za-z0-9._:@-]{0,255}$/.test(sessionId) ? ` --session ${sessionId}` : "";
|
|
54434
|
+
const pointerCache = options.cached || options.pointerCacheFirst ? " --cache-first" : "";
|
|
54435
|
+
const loadCommandFor = (selection) => `skills load ${selection.slug}@${selection.version} --selection-profile ${profile.profileId}${pointerCache}${pointerSession}`;
|
|
54420
54436
|
const delivered = [];
|
|
54421
54437
|
let selections = [];
|
|
54422
54438
|
const omitted = [];
|
|
@@ -54426,7 +54442,7 @@ async function buildSkillContextOnce(input2, options, mayResolveAgain) {
|
|
|
54426
54442
|
const { selection, reason: reason2 } = candidates[index];
|
|
54427
54443
|
if (!input2.restore && !explicit.has(selectionKey(selection)) && loaded.has(selectionKey(selection)))
|
|
54428
54444
|
continue;
|
|
54429
|
-
const loadCommand =
|
|
54445
|
+
const loadCommand = loadCommandFor(selection);
|
|
54430
54446
|
if (selections.length >= maxSkills || ambiguous && reason2 === "prompt") {
|
|
54431
54447
|
omitted.push({ slug: selection.slug, version: selection.version, reason: "skill-limit", loadCommand });
|
|
54432
54448
|
continue;
|
|
@@ -54435,7 +54451,7 @@ async function buildSkillContextOnce(input2, options, mayResolveAgain) {
|
|
|
54435
54451
|
omitted.push({ slug: selection.slug, version: selection.version, reason: "weak-match", loadCommand });
|
|
54436
54452
|
continue;
|
|
54437
54453
|
}
|
|
54438
|
-
const historyLimit =
|
|
54454
|
+
const historyLimit = historyBodyLimits[reason2];
|
|
54439
54455
|
if (historyLimit !== undefined) {
|
|
54440
54456
|
const delivered2 = historyBodies.get(reason2) ?? 0;
|
|
54441
54457
|
if (delivered2 >= historyLimit) {
|
|
@@ -54446,12 +54462,13 @@ async function buildSkillContextOnce(input2, options, mayResolveAgain) {
|
|
|
54446
54462
|
if (reason2 === "prompt") {
|
|
54447
54463
|
const candidate2 = candidates[index];
|
|
54448
54464
|
let end = index;
|
|
54449
|
-
while (end + 1 < candidates.length && candidates[end + 1].reason === "prompt" && candidates[end + 1].priority === candidate2.priority && candidates[end + 1].score === candidate2.score
|
|
54465
|
+
while (end + 1 < candidates.length && candidates[end + 1].reason === "prompt" && candidates[end + 1].priority === candidate2.priority && candidates[end + 1].score === candidate2.score)
|
|
54450
54466
|
end++;
|
|
54451
|
-
const
|
|
54467
|
+
const block = candidates.slice(index, end + 1).filter((entry) => explicit.has(selectionKey(entry.selection)) || !loaded.has(selectionKey(entry.selection)));
|
|
54468
|
+
const tied = block.filter((entry) => !entry.weak);
|
|
54452
54469
|
if (tied.length > maxSkills - selections.length) {
|
|
54453
|
-
for (const entry of
|
|
54454
|
-
omitted.push({ slug: entry.selection.slug, version: entry.selection.version, reason: "ambiguous-match", loadCommand:
|
|
54470
|
+
for (const entry of block)
|
|
54471
|
+
omitted.push({ slug: entry.selection.slug, version: entry.selection.version, reason: entry.weak ? "weak-match" : "ambiguous-match", loadCommand: loadCommandFor(entry.selection) });
|
|
54455
54472
|
ambiguous = true;
|
|
54456
54473
|
index = end;
|
|
54457
54474
|
continue;
|
|
@@ -54478,7 +54495,7 @@ ${content}`;
|
|
|
54478
54495
|
return considered.has(key2) || !explicit.has(key2) && loaded.has(key2);
|
|
54479
54496
|
});
|
|
54480
54497
|
for (const offer of offers)
|
|
54481
|
-
omitted.push({ slug: offer.selection.slug, version: offer.selection.version, reason: offer.reason, loadCommand:
|
|
54498
|
+
omitted.push({ slug: offer.selection.slug, version: offer.selection.version, reason: offer.reason, loadCommand: loadCommandFor(offer.selection) });
|
|
54482
54499
|
let notice;
|
|
54483
54500
|
if (sessionId) {
|
|
54484
54501
|
if (!resolved.session || [...loaded].some((key2) => !previouslyLoaded.has(key2))) {
|
|
@@ -54494,7 +54511,7 @@ ${content}`;
|
|
|
54494
54511
|
slug: selection.slug,
|
|
54495
54512
|
version: selection.version,
|
|
54496
54513
|
reason: "write-busy",
|
|
54497
|
-
loadCommand:
|
|
54514
|
+
loadCommand: loadCommandFor(selection)
|
|
54498
54515
|
})));
|
|
54499
54516
|
selections = selections.filter((selection) => !unrecorded.has(selectionKey(selection)));
|
|
54500
54517
|
delivered.splice(0, delivered.length, ...delivered.filter((entry) => !unrecorded.has(entry.key)));
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/** One resolution path for API-selected content. Local drafts cannot shadow a published selection. */
|
|
2
1
|
import { type ProfileClient } from "./profile-client.js";
|
|
3
2
|
import type { ResolvedSkillProfile, ResolvedSkillSelection } from "../types/skill-selection.js";
|
|
4
3
|
import type { SkillBundleEntry } from "./skill-bundle.js";
|
|
@@ -6,6 +5,8 @@ import { type CachedSelectionProfile, type SelectionCacheOptions, type SkillSess
|
|
|
6
5
|
export interface SelectionResolverOptions extends SelectionCacheOptions {
|
|
7
6
|
client?: ProfileClient;
|
|
8
7
|
cached?: boolean;
|
|
8
|
+
/** Read the verified cache while it can serve a load, and the service after that. */
|
|
9
|
+
cacheFirst?: boolean;
|
|
9
10
|
/** Explicit cached authority binding, checked even when no credential is read. */
|
|
10
11
|
authority?: string;
|
|
11
12
|
workspaceId?: string;
|
|
@@ -42,9 +43,18 @@ export interface ResolvedSelectionContext {
|
|
|
42
43
|
export declare function resolveSelectionContext(profileId: string, options?: SelectionResolverOptions): Promise<ResolvedSelectionContext>;
|
|
43
44
|
export declare function readSelectedEntries(selection: ResolvedSkillSelection, context: ResolvedSelectionContext, options?: SelectionResolverOptions): Promise<SkillBundleEntry[]>;
|
|
44
45
|
export declare function exactProfileSelection(spec: string, profile: ResolvedSkillProfile): ResolvedSkillSelection;
|
|
46
|
+
/** Refusals that mean the verified cache can't serve a read, not that the read is wrong. Identity and integrity failures never fall back. */
|
|
47
|
+
export declare const RECOVERABLE_CACHE_ERRORS: ReadonlySet<string>;
|
|
48
|
+
/**
|
|
49
|
+
* Load one selected skill. With cacheFirst it reads the verified cache while that
|
|
50
|
+
* can serve this load, which works with no network, and the Skills service after
|
|
51
|
+
* that, as the managed hook does. A subagent inherits its parent's verifiedAt and
|
|
52
|
+
* gets no renewal of its own, so a pointer it holds outlives the cache's limit.
|
|
53
|
+
*/
|
|
45
54
|
export declare function loadSelectedSkill(spec: string, profileId: string, options?: SelectionResolverOptions & {
|
|
46
55
|
file?: string;
|
|
47
56
|
}): Promise<{
|
|
57
|
+
sessionRecorded?: boolean | undefined;
|
|
48
58
|
content: string;
|
|
49
59
|
selection: ResolvedSkillSelection;
|
|
50
60
|
receipt: {
|
|
@@ -66,6 +76,8 @@ export declare function loadSelectedSkill(spec: string, profileId: string, optio
|
|
|
66
76
|
};
|
|
67
77
|
};
|
|
68
78
|
}>;
|
|
79
|
+
/** A session store that this process can't write: a sandbox, or a full disk or quota. */
|
|
80
|
+
export declare function isUnwritableStore(error: unknown): boolean;
|
|
69
81
|
/** Pin the resolved profile metadata without copying a definition into the project. */
|
|
70
82
|
export declare function pinSelectedSkillVersion(spec: string, profileId: string, options: SelectionResolverOptions & {
|
|
71
83
|
projectDir: string;
|
|
@@ -15,6 +15,17 @@ export interface SkillContextInput {
|
|
|
15
15
|
export interface SkillContextOptions extends SelectionResolverOptions {
|
|
16
16
|
maxChars?: number;
|
|
17
17
|
maxSkills?: number;
|
|
18
|
+
/**
|
|
19
|
+
* An unnamed prompt match whose longest matched phrase has fewer words than
|
|
20
|
+
* this is offered as a load command instead of being injected, however many
|
|
21
|
+
* such words matched. Named, explicit, path and required selections are not
|
|
22
|
+
* affected. Unset, every counted match may be injected.
|
|
23
|
+
*/
|
|
24
|
+
minPromptPhraseWords?: number;
|
|
25
|
+
/** Print load pointers with --cache-first even though this context didn't come from the cache: a managed hook that fell back to the service. */
|
|
26
|
+
pointerCacheFirst?: boolean;
|
|
27
|
+
/** Bodies a child session receives from its parent's loaded skills; the rest are offered. Unset, HISTORY_BODY_LIMITS applies. */
|
|
28
|
+
inheritedBodies?: number;
|
|
18
29
|
/** Called with the resolved pin before any payload is read (again if a new child is resolved again); metadata only. */
|
|
19
30
|
onResolved?: (resolved: ResolvedSelectionContext) => void;
|
|
20
31
|
/**
|
|
@@ -49,7 +49,7 @@ var __require = import.meta.require;
|
|
|
49
49
|
// src/runtime-prerequisites.ts
|
|
50
50
|
import { isAbsolute as isAbsolute7 } from "path";
|
|
51
51
|
// package.json
|
|
52
|
-
var version = "0.10.
|
|
52
|
+
var version = "0.10.90";
|
|
53
53
|
var package_default = {
|
|
54
54
|
name: "@hasna/skills",
|
|
55
55
|
version,
|
|
@@ -2276,7 +2276,8 @@ var MEASURED_CODEX_CAPABILITIES = {
|
|
|
2276
2276
|
"codex-cli 0.162.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
2277
2277
|
"codex-cli 0.163.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
2278
2278
|
"codex-cli 0.164.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
2279
|
-
"codex-cli 0.165.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
2279
|
+
"codex-cli 0.165.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
2280
|
+
"codex-cli 0.166.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
2280
2281
|
};
|
|
2281
2282
|
function supportsCodexNativeCapability(version2, capability) {
|
|
2282
2283
|
return typeof version2 === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version2) && MEASURED_CODEX_CAPABILITIES[version2].includes(capability);
|
package/dist/sdk/index.js
CHANGED
|
@@ -32371,7 +32371,7 @@ var init_event_sink = __esm(() => {
|
|
|
32371
32371
|
init_dist();
|
|
32372
32372
|
});
|
|
32373
32373
|
// package.json
|
|
32374
|
-
var version = "0.10.
|
|
32374
|
+
var version = "0.10.90";
|
|
32375
32375
|
var package_default = {
|
|
32376
32376
|
name: "@hasna/skills",
|
|
32377
32377
|
version,
|
|
@@ -39270,7 +39270,8 @@ var MEASURED_CODEX_CAPABILITIES = {
|
|
|
39270
39270
|
"codex-cli 0.162.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
39271
39271
|
"codex-cli 0.163.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
39272
39272
|
"codex-cli 0.164.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
39273
|
-
"codex-cli 0.165.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
39273
|
+
"codex-cli 0.165.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
39274
|
+
"codex-cli 0.166.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
39274
39275
|
};
|
|
39275
39276
|
function supportsCodexNativeCapability(version2, capability) {
|
|
39276
39277
|
return typeof version2 === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version2) && MEASURED_CODEX_CAPABILITIES[version2].includes(capability);
|
|
@@ -55419,6 +55420,8 @@ function unknownNameRefusal(slug, profile) {
|
|
|
55419
55420
|
const hint = close.length > 0 ? ` Did you mean: ${close.join(", ")}?` : "";
|
|
55420
55421
|
return `Skill '${slug}' is not selected by this Skills profile or project lock.${hint} ` + `Read the accepted names with 'skills search <term>' or 'skills list --all --json'; accept one with 'skills pin <name>'. ${ACCEPTED_FORM}`;
|
|
55421
55422
|
}
|
|
55423
|
+
var RECOVERABLE_CACHE_ERRORS = new Set(["CACHED_PROFILE_EXPIRED", "CACHED_PROFILE_MISSING", "CACHED_BUNDLE_MISSING"]);
|
|
55424
|
+
var UNWRITABLE_CODES = new Set(["EACCES", "EPERM", "EROFS", "ENOSPC", "EDQUOT"]);
|
|
55422
55425
|
|
|
55423
55426
|
// src/lib/selected-run.ts
|
|
55424
55427
|
async function resolveSelectedRun(spec, profileId, options = {}) {
|