@hasna/skills 0.10.27 → 0.10.30
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 +44 -1
- package/bin/index.js +1126 -921
- package/bin/mcp.js +360 -279
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.js +661 -471
- package/dist/lib/agent-adapters.d.ts +7 -1
- package/dist/lib/agent-sumi.d.ts +15 -0
- package/dist/lib/native-discovery-roots.d.ts +1 -1
- package/dist/lib/registry.d.ts +20 -3
- package/dist/lib/selection-resolver.d.ts +1 -0
- package/dist/lib/skill-context.d.ts +2 -0
- package/dist/sdk/index.js +653 -467
- package/package.json +1 -1
package/bin/mcp.js
CHANGED
|
@@ -20019,7 +20019,7 @@ var package_default;
|
|
|
20019
20019
|
var init_package = __esm(() => {
|
|
20020
20020
|
package_default = {
|
|
20021
20021
|
name: "@hasna/skills",
|
|
20022
|
-
version: "0.10.
|
|
20022
|
+
version: "0.10.30",
|
|
20023
20023
|
description: "Skills library for AI coding agents",
|
|
20024
20024
|
type: "module",
|
|
20025
20025
|
bin: {
|
|
@@ -38184,6 +38184,8 @@ var init_native_discovery_roots = __esm(() => {
|
|
|
38184
38184
|
["codex", ".codex/skills"],
|
|
38185
38185
|
["codex", ".agents/skills"],
|
|
38186
38186
|
["gemini", ".gemini/skills"],
|
|
38187
|
+
["sumi", ".sumi/skills"],
|
|
38188
|
+
["sumi", ".sumi/skill"],
|
|
38187
38189
|
["codewith", ".codewith/skills"],
|
|
38188
38190
|
["opencode", ".config/opencode/skills"],
|
|
38189
38191
|
["opencode", ".opencode/skills"],
|
|
@@ -38201,7 +38203,7 @@ var init_native_discovery_roots = __esm(() => {
|
|
|
38201
38203
|
// src/lib/agent-adapters.ts
|
|
38202
38204
|
var INTEGRATION_AGENTS;
|
|
38203
38205
|
var init_agent_adapters = __esm(() => {
|
|
38204
|
-
INTEGRATION_AGENTS = ["claude", "codex", "gemini", "opencode", "cursor", "hermes"];
|
|
38206
|
+
INTEGRATION_AGENTS = ["claude", "codex", "gemini", "opencode", "cursor", "hermes", "sumi"];
|
|
38205
38207
|
});
|
|
38206
38208
|
|
|
38207
38209
|
// src/lib/agent-policy-limits.ts
|
|
@@ -47926,12 +47928,14 @@ function disablesOneSkill(entry) {
|
|
|
47926
47928
|
return selector.length === 1 && typeof entry[selector[0]] === "string" && entry[selector[0]].length > 0;
|
|
47927
47929
|
}
|
|
47928
47930
|
function inference(target, version2) {
|
|
47929
|
-
const keys = version2 === 3 ? [...INFERENCE, "service_tier", "plan_mode_reasoning_effort"] : INFERENCE;
|
|
47931
|
+
const keys = version2 === 3 ? [...INFERENCE, "service_tier", "plan_mode_reasoning_effort", "personality"] : INFERENCE;
|
|
47930
47932
|
for (const key of keys)
|
|
47931
47933
|
if (Object.hasOwn(target, key)) {
|
|
47932
47934
|
const value = target[key];
|
|
47933
47935
|
if (key === "model")
|
|
47934
47936
|
need4(typeof value === "string" && MODEL.test(value));
|
|
47937
|
+
else if (key === "personality")
|
|
47938
|
+
need4(typeof value === "string" && ["none", "friendly", "pragmatic"].includes(value));
|
|
47935
47939
|
else if (version2 === 3 && key !== "model_verbosity") {
|
|
47936
47940
|
need4(typeof value === "string" && value.length <= 128 && !/[\x00-\x1f\x7f]/.test(value));
|
|
47937
47941
|
if (key !== "service_tier")
|
|
@@ -48090,6 +48094,38 @@ var init_agent_bridge = __esm(() => {
|
|
|
48090
48094
|
// src/lib/agent-codex.ts
|
|
48091
48095
|
var init_agent_codex = () => {};
|
|
48092
48096
|
|
|
48097
|
+
// src/lib/agent-sumi.ts
|
|
48098
|
+
import { existsSync as existsSync8, lstatSync as lstatSync13, realpathSync as realpathSync4 } from "fs";
|
|
48099
|
+
import { join as join18, resolve as resolve10 } from "path";
|
|
48100
|
+
function sumiConfigDirectory(home, env = process.env) {
|
|
48101
|
+
for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
|
|
48102
|
+
if (env[key] !== undefined)
|
|
48103
|
+
throw new Error(`Sumi ${key} requires a dedicated discovery adapter; unset it before Skills integration`);
|
|
48104
|
+
const selected = (key) => env[key]?.trim() ? env[key] : undefined;
|
|
48105
|
+
const expand = (value) => resolve10(value === "~" ? home : value.startsWith("~/") ? join18(home, value.slice(2)) : value);
|
|
48106
|
+
const explicit = selected("SUMI_CONFIG_DIR");
|
|
48107
|
+
const xdg = selected("XDG_CONFIG_HOME");
|
|
48108
|
+
const custom2 = selected("SUMI_HOME");
|
|
48109
|
+
const canonical5 = explicit ? expand(explicit) : xdg ? join18(expand(xdg), "sumi") : join18(custom2 ? expand(custom2) : join18(home, ".hasna-internal/sumi"), "config");
|
|
48110
|
+
if (explicit || xdg || custom2)
|
|
48111
|
+
return canonical5;
|
|
48112
|
+
const legacy = join18(home, ".config/sumi");
|
|
48113
|
+
const a = lstatSync13(canonical5, { throwIfNoEntry: false }), b = lstatSync13(legacy, { throwIfNoEntry: false });
|
|
48114
|
+
if (a && b && realpathSync4(canonical5) !== realpathSync4(legacy))
|
|
48115
|
+
throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
|
|
48116
|
+
const path = a ? canonical5 : b ? legacy : canonical5;
|
|
48117
|
+
if (!existsSync8(path))
|
|
48118
|
+
return path;
|
|
48119
|
+
const physical = realpathSync4(path);
|
|
48120
|
+
if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![canonical5, legacy].includes(physical))
|
|
48121
|
+
throw new Error("Sumi config alias must resolve to its canonical or legacy root");
|
|
48122
|
+
return physical;
|
|
48123
|
+
}
|
|
48124
|
+
function sumiConfigPath(home) {
|
|
48125
|
+
return join18(sumiConfigDirectory(home), "sumi.json");
|
|
48126
|
+
}
|
|
48127
|
+
var init_agent_sumi = () => {};
|
|
48128
|
+
|
|
48093
48129
|
// src/lib/agent-integration.ts
|
|
48094
48130
|
var init_agent_integration = __esm(() => {
|
|
48095
48131
|
init_codex_plugin_skill_controls();
|
|
@@ -48103,6 +48139,7 @@ var init_agent_integration = __esm(() => {
|
|
|
48103
48139
|
init_agent_discovery();
|
|
48104
48140
|
init_agent_adapters();
|
|
48105
48141
|
init_agent_codex();
|
|
48142
|
+
init_agent_sumi();
|
|
48106
48143
|
init_agent_hermes();
|
|
48107
48144
|
init_claude_settings_witness();
|
|
48108
48145
|
});
|
|
@@ -48140,17 +48177,17 @@ var init_skill_aliases = __esm(() => {
|
|
|
48140
48177
|
});
|
|
48141
48178
|
|
|
48142
48179
|
// src/lib/project-state.ts
|
|
48143
|
-
import { existsSync as
|
|
48144
|
-
import { join as
|
|
48180
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync4 } from "fs";
|
|
48181
|
+
import { join as join19 } from "path";
|
|
48145
48182
|
function getProjectStateDir(targetDir = process.cwd()) {
|
|
48146
|
-
return
|
|
48183
|
+
return join19(targetDir, SKILLS_PROJECT_DIR);
|
|
48147
48184
|
}
|
|
48148
48185
|
function getProjectConfigPath(targetDir = process.cwd()) {
|
|
48149
|
-
return
|
|
48186
|
+
return join19(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
|
|
48150
48187
|
}
|
|
48151
48188
|
function loadProjectConfig(targetDir = process.cwd()) {
|
|
48152
48189
|
const path = getProjectConfigPath(targetDir);
|
|
48153
|
-
if (!
|
|
48190
|
+
if (!existsSync9(path))
|
|
48154
48191
|
return null;
|
|
48155
48192
|
try {
|
|
48156
48193
|
return normalizeProjectConfig(JSON.parse(readFileSync12(path, "utf-8")));
|
|
@@ -48261,8 +48298,8 @@ var init_project_state = __esm(() => {
|
|
|
48261
48298
|
});
|
|
48262
48299
|
|
|
48263
48300
|
// src/lib/installer.ts
|
|
48264
|
-
import { existsSync as
|
|
48265
|
-
import { join as
|
|
48301
|
+
import { existsSync as existsSync10, readFileSync as readFileSync13, rmSync } from "fs";
|
|
48302
|
+
import { join as join20 } from "path";
|
|
48266
48303
|
import { homedir as homedir2 } from "os";
|
|
48267
48304
|
function getSkillPath(name) {
|
|
48268
48305
|
const skillName = normalizeSkillName(getCanonicalSkillName(name));
|
|
@@ -48272,7 +48309,7 @@ function getSkillPath(name) {
|
|
|
48272
48309
|
const extensionPath = findExtensionSkillPath(skillName);
|
|
48273
48310
|
if (extensionPath)
|
|
48274
48311
|
return extensionPath;
|
|
48275
|
-
return
|
|
48312
|
+
return join20(getPortableSkillsRoot(), skillName);
|
|
48276
48313
|
}
|
|
48277
48314
|
function getCanonicalSkillName(name) {
|
|
48278
48315
|
return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
|
|
@@ -48281,7 +48318,7 @@ function installSkill(name, options = {}) {
|
|
|
48281
48318
|
const { targetDir = process.cwd(), overwrite = false } = options;
|
|
48282
48319
|
const canonicalName = getCanonicalSkillName(name);
|
|
48283
48320
|
const skillName = normalizeSkillName(canonicalName);
|
|
48284
|
-
if (!
|
|
48321
|
+
if (!existsSync10(getSkillPath(name))) {
|
|
48285
48322
|
const knownOfficial = Boolean(getSkill(name));
|
|
48286
48323
|
return {
|
|
48287
48324
|
skill: canonicalName,
|
|
@@ -48326,11 +48363,11 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
|
|
|
48326
48363
|
const base = projectDir || process.cwd();
|
|
48327
48364
|
switch (agent) {
|
|
48328
48365
|
case "pi":
|
|
48329
|
-
return scope === "project" ?
|
|
48366
|
+
return scope === "project" ? join20(base, ".pi", "skills") : join20(homedir2(), ".pi", "agent", "skills");
|
|
48330
48367
|
case "opencode":
|
|
48331
|
-
return scope === "project" ?
|
|
48368
|
+
return scope === "project" ? join20(base, ".opencode", "skills") : join20(homedir2(), ".config", "opencode", "skills");
|
|
48332
48369
|
default:
|
|
48333
|
-
return scope === "project" ?
|
|
48370
|
+
return scope === "project" ? join20(base, `.${agent}`, "skills") : join20(homedir2(), `.${agent}`, "skills");
|
|
48334
48371
|
}
|
|
48335
48372
|
}
|
|
48336
48373
|
function warnMissingDependencies(name, targetDir) {
|
|
@@ -48345,8 +48382,8 @@ function warnMissingDependencies(name, targetDir) {
|
|
|
48345
48382
|
}
|
|
48346
48383
|
}
|
|
48347
48384
|
function readBundledSkillVersion(name) {
|
|
48348
|
-
const pkgPath =
|
|
48349
|
-
if (!
|
|
48385
|
+
const pkgPath = join20(getSkillPath(name), "package.json");
|
|
48386
|
+
if (!existsSync10(pkgPath))
|
|
48350
48387
|
return "unknown";
|
|
48351
48388
|
try {
|
|
48352
48389
|
const pkg = JSON.parse(readFileSync13(pkgPath, "utf-8"));
|
|
@@ -48413,13 +48450,13 @@ var init_skill_doc_file = __esm(() => {
|
|
|
48413
48450
|
});
|
|
48414
48451
|
|
|
48415
48452
|
// src/lib/skillinfo.ts
|
|
48416
|
-
import { existsSync as
|
|
48417
|
-
import { join as
|
|
48453
|
+
import { existsSync as existsSync11, readFileSync as readFileSync14 } from "fs";
|
|
48454
|
+
import { join as join21 } from "path";
|
|
48418
48455
|
function isInstructionSkillDir(skillPath, meta3) {
|
|
48419
48456
|
if (meta3?.kind === "instruction")
|
|
48420
48457
|
return true;
|
|
48421
|
-
const skillMdPath =
|
|
48422
|
-
if (!
|
|
48458
|
+
const skillMdPath = join21(skillPath, "SKILL.md");
|
|
48459
|
+
if (!existsSync11(skillMdPath))
|
|
48423
48460
|
return false;
|
|
48424
48461
|
try {
|
|
48425
48462
|
return parseSkillFrontmatter(readFileSync14(skillMdPath, "utf-8"))?.kind === "instruction";
|
|
@@ -48429,12 +48466,12 @@ function isInstructionSkillDir(skillPath, meta3) {
|
|
|
48429
48466
|
}
|
|
48430
48467
|
function getSkillDocs(name) {
|
|
48431
48468
|
const skillPath = getSkillPath(name);
|
|
48432
|
-
if (!
|
|
48469
|
+
if (!existsSync11(skillPath))
|
|
48433
48470
|
return null;
|
|
48434
48471
|
return {
|
|
48435
|
-
skillMd: readIfExists(
|
|
48436
|
-
readme: readIfExists(
|
|
48437
|
-
claudeMd: readIfExists(
|
|
48472
|
+
skillMd: readIfExists(join21(skillPath, "SKILL.md")),
|
|
48473
|
+
readme: readIfExists(join21(skillPath, "README.md")),
|
|
48474
|
+
claudeMd: readIfExists(join21(skillPath, "CLAUDE.md"))
|
|
48438
48475
|
};
|
|
48439
48476
|
}
|
|
48440
48477
|
function getSkillBestDoc(name, file2) {
|
|
@@ -48446,18 +48483,18 @@ function getSkillBestDoc(name, file2) {
|
|
|
48446
48483
|
}
|
|
48447
48484
|
function getSkillRequirements(name) {
|
|
48448
48485
|
const skillPath = getSkillPath(name);
|
|
48449
|
-
if (!
|
|
48486
|
+
if (!existsSync11(skillPath))
|
|
48450
48487
|
return null;
|
|
48451
48488
|
const texts = [];
|
|
48452
48489
|
for (const file2 of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
|
|
48453
|
-
const content = readIfExists(
|
|
48490
|
+
const content = readIfExists(join21(skillPath, file2));
|
|
48454
48491
|
if (content)
|
|
48455
48492
|
texts.push(content);
|
|
48456
48493
|
}
|
|
48457
48494
|
const meta3 = getSkill(name);
|
|
48458
48495
|
let dependencies = {};
|
|
48459
48496
|
try {
|
|
48460
|
-
dependencies = JSON.parse(readFileSync14(
|
|
48497
|
+
dependencies = JSON.parse(readFileSync14(join21(skillPath, "package.json"), "utf8")).dependencies || {};
|
|
48461
48498
|
} catch {}
|
|
48462
48499
|
return getSkillRequirementsFromContent(name, texts, dependencies, meta3);
|
|
48463
48500
|
}
|
|
@@ -48510,7 +48547,7 @@ async function runSkill(name, args, options = {}) {
|
|
|
48510
48547
|
const meta3 = getSkill(name);
|
|
48511
48548
|
const canonicalName = meta3?.name ?? name;
|
|
48512
48549
|
const skillPath = getSkillPath(canonicalName);
|
|
48513
|
-
if (!
|
|
48550
|
+
if (!existsSync11(skillPath)) {
|
|
48514
48551
|
return { exitCode: 1, error: `Skill '${name}' not found` };
|
|
48515
48552
|
}
|
|
48516
48553
|
if (isInstructionSkillDir(skillPath, meta3)) {
|
|
@@ -48519,8 +48556,8 @@ async function runSkill(name, args, options = {}) {
|
|
|
48519
48556
|
error: `Skill '${name}' is an instruction skill (kind: instruction) and is not runnable. Instruction skills are consumed by coding agents via SKILL.md, not executed with 'skills run'.`
|
|
48520
48557
|
};
|
|
48521
48558
|
}
|
|
48522
|
-
const pkgPath =
|
|
48523
|
-
if (!
|
|
48559
|
+
const pkgPath = join21(skillPath, "package.json");
|
|
48560
|
+
if (!existsSync11(pkgPath)) {
|
|
48524
48561
|
return { exitCode: 1, error: `No package.json in skill '${name}'` };
|
|
48525
48562
|
}
|
|
48526
48563
|
let entryPoint2;
|
|
@@ -48539,12 +48576,12 @@ async function runSkill(name, args, options = {}) {
|
|
|
48539
48576
|
} catch {
|
|
48540
48577
|
return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
|
|
48541
48578
|
}
|
|
48542
|
-
const entryPath =
|
|
48543
|
-
if (!
|
|
48579
|
+
const entryPath = join21(skillPath, entryPoint2);
|
|
48580
|
+
if (!existsSync11(entryPath)) {
|
|
48544
48581
|
return { exitCode: 1, error: `Entry point '${entryPoint2}' not found in skill '${name}'` };
|
|
48545
48582
|
}
|
|
48546
48583
|
const env = { ...process.env, ...options.env };
|
|
48547
|
-
if (!
|
|
48584
|
+
if (!existsSync11(join21(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
|
|
48548
48585
|
const failure = await prepareSkillDependencies(skillPath, env, options.preparationTimeoutMs);
|
|
48549
48586
|
if (failure)
|
|
48550
48587
|
return failure;
|
|
@@ -48570,7 +48607,7 @@ async function runSkill(name, args, options = {}) {
|
|
|
48570
48607
|
function detectProjectSkills(cwd = process.cwd()) {
|
|
48571
48608
|
let pkg;
|
|
48572
48609
|
try {
|
|
48573
|
-
pkg = JSON.parse(readFileSync14(
|
|
48610
|
+
pkg = JSON.parse(readFileSync14(join21(cwd, "package.json"), "utf8"));
|
|
48574
48611
|
} catch {
|
|
48575
48612
|
return { detected: [], recommended: [] };
|
|
48576
48613
|
}
|
|
@@ -48608,7 +48645,7 @@ function extractEnvVars(text2) {
|
|
|
48608
48645
|
}
|
|
48609
48646
|
function readIfExists(path) {
|
|
48610
48647
|
try {
|
|
48611
|
-
if (
|
|
48648
|
+
if (existsSync11(path)) {
|
|
48612
48649
|
return readFileSync14(path, "utf-8");
|
|
48613
48650
|
}
|
|
48614
48651
|
} catch {}
|
|
@@ -48665,6 +48702,8 @@ var init_selected_document = __esm(() => {
|
|
|
48665
48702
|
async function resolveSelectionContext(profileId, options = {}) {
|
|
48666
48703
|
const sessionState = options.sessionId ? readSkillSessionSnapshotIfExists(options.sessionId, options) : null;
|
|
48667
48704
|
const session = sessionState?.receipt ?? null;
|
|
48705
|
+
if (options.nativeParentSessionId !== undefined && session && (session.parent?.sessionId ?? null) !== options.nativeParentSessionId)
|
|
48706
|
+
throw new SkillSelectionError("SESSION_PARENT_MISMATCH", "The native session id is already bound to different parent custody.");
|
|
48668
48707
|
const parentState = !session && options.parentSessionId ? readSkillSessionSnapshotIfExists(options.parentSessionId, options) : null;
|
|
48669
48708
|
if (!session && options.parentSessionId && !parentState) {
|
|
48670
48709
|
throw new SkillSelectionError("SESSION_PARENT_NOT_FOUND", "A child Skills session requires an existing parent receipt so its inherited pin can be bound exactly.");
|
|
@@ -48858,11 +48897,11 @@ var init_plugin_projection = __esm(() => {
|
|
|
48858
48897
|
});
|
|
48859
48898
|
|
|
48860
48899
|
// src/lib/plugin-projection-store.ts
|
|
48861
|
-
import { constants as constants7, closeSync as closeSync10, fchmodSync, fstatSync as fstatSync10, fsyncSync as fsyncSync2, linkSync, lstatSync as
|
|
48862
|
-
import { dirname as dirname11, isAbsolute as isAbsolute9, join as
|
|
48900
|
+
import { constants as constants7, closeSync as closeSync10, fchmodSync, fstatSync as fstatSync10, fsyncSync as fsyncSync2, linkSync, lstatSync as lstatSync14, mkdirSync as mkdirSync6, openSync as openSync10, opendirSync as opendirSync2, readSync as readSync6, renameSync as renameSync2, rmdirSync as rmdirSync2, rmSync as rmSync2, unlinkSync as unlinkSync3, writeSync as writeSync2 } from "fs";
|
|
48901
|
+
import { dirname as dirname11, isAbsolute as isAbsolute9, join as join22, parse as parse9, resolve as resolve11 } from "path";
|
|
48863
48902
|
function stat(path) {
|
|
48864
48903
|
try {
|
|
48865
|
-
return
|
|
48904
|
+
return lstatSync14(path, { bigint: true });
|
|
48866
48905
|
} catch (error61) {
|
|
48867
48906
|
if (missing(error61))
|
|
48868
48907
|
return null;
|
|
@@ -48870,7 +48909,7 @@ function stat(path) {
|
|
|
48870
48909
|
}
|
|
48871
48910
|
}
|
|
48872
48911
|
function canonical5(path) {
|
|
48873
|
-
pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute9(path) &&
|
|
48912
|
+
pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute9(path) && resolve11(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
|
|
48874
48913
|
}
|
|
48875
48914
|
function owner(stats, system = false) {
|
|
48876
48915
|
const current = uid();
|
|
@@ -48885,7 +48924,7 @@ function ancestors(path, create = false) {
|
|
|
48885
48924
|
let current = filesystemRoot;
|
|
48886
48925
|
for (const segment of ["", ...parent.slice(filesystemRoot.length).split("/").filter(Boolean)]) {
|
|
48887
48926
|
if (segment)
|
|
48888
|
-
current =
|
|
48927
|
+
current = join22(current, segment);
|
|
48889
48928
|
let currentStat = stat(current);
|
|
48890
48929
|
if (!currentStat && create) {
|
|
48891
48930
|
try {
|
|
@@ -48993,7 +49032,7 @@ function snapshotPluginTree(root, options = {}) {
|
|
|
48993
49032
|
pluginNeed(++visited <= PLUGIN_PROJECTION_LIMITS.files * 50, "Plugin tree membership exceeds its limit");
|
|
48994
49033
|
const path = relative5 ? `${relative5}/${name}` : name;
|
|
48995
49034
|
pluginNeed(new TextEncoder().encode(path).byteLength <= 100 && !/[\\:\x00-\x1f\x7f]/u.test(path), "Plugin entry path exceeds its limit or is unsafe");
|
|
48996
|
-
const absolute =
|
|
49035
|
+
const absolute = join22(directory, name), entryStat = stat(absolute);
|
|
48997
49036
|
pluginNeed(entryStat, "Plugin tree member disappeared");
|
|
48998
49037
|
if (relative5 === "" && name === ".orphaned_at" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
|
|
48999
49038
|
const bytes2 = readBytes(absolute, 32, "native-pin");
|
|
@@ -49010,7 +49049,7 @@ function snapshotPluginTree(root, options = {}) {
|
|
|
49010
49049
|
directories.push({ path: absolute, stat: entryStat, names: pins });
|
|
49011
49050
|
for (const pin of pins) {
|
|
49012
49051
|
pluginNeed(/^[1-9][0-9]{0,9}$/.test(pin) && Number(pin) <= 2147483647, "Unrecognized native plugin pin name");
|
|
49013
|
-
const pinPath =
|
|
49052
|
+
const pinPath = join22(absolute, pin), pinStat = stat(pinPath);
|
|
49014
49053
|
pluginNeed(pinStat, "Native plugin pin disappeared");
|
|
49015
49054
|
const bytes2 = readBytes(pinPath, 4096, "native-pin");
|
|
49016
49055
|
let value;
|
|
@@ -49107,7 +49146,7 @@ var init_selected_manifest = __esm(() => {
|
|
|
49107
49146
|
});
|
|
49108
49147
|
|
|
49109
49148
|
// src/lib/plugin-admission.ts
|
|
49110
|
-
import { isAbsolute as isAbsolute10, join as
|
|
49149
|
+
import { isAbsolute as isAbsolute10, join as join23, resolve as resolve12 } from "path";
|
|
49111
49150
|
function validatePluginTarget(value) {
|
|
49112
49151
|
pluginKeys(value, ["schemaVersion", "pluginId", "registrations", "native", "resolver"]);
|
|
49113
49152
|
pluginNeed(value.schemaVersion === 1, "Invalid plugin admission target");
|
|
@@ -49117,7 +49156,7 @@ function validatePluginTarget(value) {
|
|
|
49117
49156
|
for (const registration of value.registrations) {
|
|
49118
49157
|
pluginKeys(registration, ["scope", "projectPath"]);
|
|
49119
49158
|
pluginNeed(registration.scope === "user" || registration.scope === "project", "Unsupported plugin registration scope");
|
|
49120
|
-
pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute10(registration.projectPath) &&
|
|
49159
|
+
pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute10(registration.projectPath) && resolve12(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
|
|
49121
49160
|
const key = JSON.stringify([registration.scope, registration.projectPath]);
|
|
49122
49161
|
pluginNeed(!scopes.has(key), "Duplicate plugin registration scope");
|
|
49123
49162
|
scopes.add(key);
|
|
@@ -49125,7 +49164,7 @@ function validatePluginTarget(value) {
|
|
|
49125
49164
|
for (const key of ["native", "resolver"]) {
|
|
49126
49165
|
pluginKeys(value[key], key === "native" ? ["version", "executable", "digest"] : ["executable", "digest"]);
|
|
49127
49166
|
pluginText(value[key].executable);
|
|
49128
|
-
pluginNeed(isAbsolute10(value[key].executable) &&
|
|
49167
|
+
pluginNeed(isAbsolute10(value[key].executable) && resolve12(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
|
|
49129
49168
|
pluginDigest(value[key].digest);
|
|
49130
49169
|
}
|
|
49131
49170
|
pluginNeed(["2.1.274", "2.1.276"].includes(value.native.version), "Plugin admission requires a certified Claude command-source runtime (2.1.274 or 2.1.276)");
|
|
@@ -49268,12 +49307,12 @@ function pluginResolverCommand(binding) {
|
|
|
49268
49307
|
}
|
|
49269
49308
|
function pluginBindingPath(storeRoot, id) {
|
|
49270
49309
|
pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
|
|
49271
|
-
return
|
|
49310
|
+
return join23(storeRoot, "bindings", `${id}.json`);
|
|
49272
49311
|
}
|
|
49273
49312
|
function pluginReceiptPath(storeRoot, id, digest) {
|
|
49274
49313
|
pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
|
|
49275
49314
|
pluginDigest(digest);
|
|
49276
|
-
return
|
|
49315
|
+
return join23(storeRoot, "receipts", id, `${digest.slice(7)}.json`);
|
|
49277
49316
|
}
|
|
49278
49317
|
function readPluginBinding(storeRoot, id) {
|
|
49279
49318
|
const value = readPluginJson(pluginBindingPath(storeRoot, id));
|
|
@@ -49293,7 +49332,7 @@ function readPluginAdmissionReceipt(storeRoot, id, digest) {
|
|
|
49293
49332
|
pluginNeed(receipt.plan.bindingId === id && receipt.plan.planDigest === digest, "Plugin receipt identity differs from its filename");
|
|
49294
49333
|
const binding = readPluginBinding(storeRoot, id);
|
|
49295
49334
|
pluginNeed(canonicalJson(binding) === canonicalJson(receipt.plan.binding) && receipt.plan.sourceCommand === pluginResolverCommand(binding), "Plugin receipt binding changed");
|
|
49296
|
-
pluginNeed(receipt.materializedPath ===
|
|
49335
|
+
pluginNeed(receipt.materializedPath === join23(storeRoot, "objects", id, digest.slice(7)), "Plugin receipt points outside its immutable materialization");
|
|
49297
49336
|
pluginText(receipt.admittedAt, 64);
|
|
49298
49337
|
pluginNeed(Number.isFinite(Date.parse(receipt.admittedAt)), "Invalid plugin admission time");
|
|
49299
49338
|
return receipt;
|
|
@@ -49310,8 +49349,8 @@ var init_plugin_admission = __esm(() => {
|
|
|
49310
49349
|
});
|
|
49311
49350
|
|
|
49312
49351
|
// src/lib/plugin-discovery.ts
|
|
49313
|
-
import { closeSync as closeSync11, constants as constants8, fstatSync as fstatSync11, lstatSync as
|
|
49314
|
-
import { basename as basename6, dirname as dirname12, isAbsolute as isAbsolute11, join as
|
|
49352
|
+
import { closeSync as closeSync11, constants as constants8, fstatSync as fstatSync11, lstatSync as lstatSync15, openSync as openSync11, opendirSync as opendirSync3, readSync as readSync7 } from "fs";
|
|
49353
|
+
import { basename as basename6, dirname as dirname12, isAbsolute as isAbsolute11, join as join24, resolve as resolve13 } from "path";
|
|
49315
49354
|
function validateManagedPluginWitnesses(value) {
|
|
49316
49355
|
pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
|
|
49317
49356
|
const seen = new Set;
|
|
@@ -49320,21 +49359,21 @@ function validateManagedPluginWitnesses(value) {
|
|
|
49320
49359
|
pluginNeed(typeof item.bindingId === "string" && /^[a-f0-9]{64}$/.test(item.bindingId) && !seen.has(item.bindingId), "Invalid or duplicate managed plugin witness");
|
|
49321
49360
|
seen.add(item.bindingId);
|
|
49322
49361
|
pluginText(item.storeRoot);
|
|
49323
|
-
pluginNeed(isAbsolute11(item.storeRoot) &&
|
|
49362
|
+
pluginNeed(isAbsolute11(item.storeRoot) && resolve13(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
|
|
49324
49363
|
}
|
|
49325
49364
|
}
|
|
49326
49365
|
function safe3(path) {
|
|
49327
49366
|
pluginText(path);
|
|
49328
|
-
pluginNeed(isAbsolute11(path) &&
|
|
49367
|
+
pluginNeed(isAbsolute11(path) && resolve13(path) === path, "Invalid plugin registry path");
|
|
49329
49368
|
for (let at = path;; at = dirname12(at)) {
|
|
49330
|
-
pluginNeed(!
|
|
49369
|
+
pluginNeed(!lstatSync15(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
|
|
49331
49370
|
if (at === dirname12(at))
|
|
49332
49371
|
break;
|
|
49333
49372
|
}
|
|
49334
49373
|
}
|
|
49335
49374
|
function readRegistry(path) {
|
|
49336
49375
|
safe3(path);
|
|
49337
|
-
const initial =
|
|
49376
|
+
const initial = lstatSync15(path);
|
|
49338
49377
|
pluginNeed(initial.isFile() && initial.size <= 1024 * 1024, "Plugin registry is not a bounded regular file");
|
|
49339
49378
|
const fd = openSync11(path, constants8.O_RDONLY | constants8.O_NOFOLLOW | constants8.O_NONBLOCK);
|
|
49340
49379
|
try {
|
|
@@ -49348,7 +49387,7 @@ function readRegistry(path) {
|
|
|
49348
49387
|
break;
|
|
49349
49388
|
length += count;
|
|
49350
49389
|
}
|
|
49351
|
-
const after = fstatSync11(fd), current =
|
|
49390
|
+
const after = fstatSync11(fd), current = lstatSync15(path);
|
|
49352
49391
|
safe3(path);
|
|
49353
49392
|
pluginNeed(length <= 1024 * 1024 && length === opened.size && after.size === opened.size && after.mtimeMs === opened.mtimeMs && after.ctimeMs === opened.ctimeMs && current.dev === opened.dev && current.ino === opened.ino && current.mtimeMs === opened.mtimeMs && current.ctimeMs === opened.ctimeMs, "Plugin registry changed during read");
|
|
49354
49393
|
let value;
|
|
@@ -49378,7 +49417,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
49378
49417
|
seen.add(target.pluginId);
|
|
49379
49418
|
const rows = plugins[target.pluginId];
|
|
49380
49419
|
pluginNeed(Array.isArray(rows) && rows.length === target.registrations.length, "Managed plugin registration membership changed");
|
|
49381
|
-
const [name, market] = target.pluginId.split("@"), cacheRoot =
|
|
49420
|
+
const [name, market] = target.pluginId.split("@"), cacheRoot = join24(dirname12(path), "cache", market, name);
|
|
49382
49421
|
const scopes = new Set, approvals = new Map, currentFiles = new Map;
|
|
49383
49422
|
plugins[target.pluginId] = rows.map((row) => {
|
|
49384
49423
|
pluginNeed(pluginObject(row), "Invalid managed plugin registration");
|
|
@@ -49391,7 +49430,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
49391
49430
|
pluginText(row.sourceProducerPath);
|
|
49392
49431
|
pluginText(row.lastUpdated, 64);
|
|
49393
49432
|
pluginNeed(Number.isFinite(Date.parse(row.lastUpdated)), "Invalid managed plugin update timestamp");
|
|
49394
|
-
pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath ===
|
|
49433
|
+
pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join24(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
|
|
49395
49434
|
const approval = (producer) => {
|
|
49396
49435
|
pluginText(producer);
|
|
49397
49436
|
const digest = `sha256:${basename6(producer)}`;
|
|
@@ -49421,7 +49460,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
49421
49460
|
return Object.fromEntries(Object.entries(row).filter(([key]) => !["version", "installPath", "sourceProducerPath", "previousProducerPaths", "lastUpdated"].includes(key)));
|
|
49422
49461
|
});
|
|
49423
49462
|
safe3(cacheRoot);
|
|
49424
|
-
const before =
|
|
49463
|
+
const before = lstatSync15(cacheRoot);
|
|
49425
49464
|
pluginNeed(before.isDirectory(), "Invalid managed plugin cache root");
|
|
49426
49465
|
const directory = opendirSync3(cacheRoot), names = [];
|
|
49427
49466
|
try {
|
|
@@ -49434,17 +49473,17 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
49434
49473
|
directory.closeSync();
|
|
49435
49474
|
}
|
|
49436
49475
|
for (const version2 of names.sort()) {
|
|
49437
|
-
const files = pluginFileWitnesses(snapshotPluginTree(
|
|
49476
|
+
const files = pluginFileWitnesses(snapshotPluginTree(join24(cacheRoot, version2), { nativeRuntime: `claude-${target.native.version}` }));
|
|
49438
49477
|
verifiedBytes += files.reduce((total, file2) => total + file2.size, 0);
|
|
49439
49478
|
pluginNeed(verifiedBytes <= 256 * 1024 * 1024, "Managed plugin verification exceeds its aggregate byte budget");
|
|
49440
49479
|
const serialized = JSON.stringify(files);
|
|
49441
|
-
const expected = currentFiles.get(
|
|
49480
|
+
const expected = currentFiles.get(join24(cacheRoot, version2));
|
|
49442
49481
|
pluginNeed(expected === undefined || serialized === expected, "Current native cache differs from its exact registered producer receipt");
|
|
49443
49482
|
pluginNeed([...approvals.values()].some((receipt) => nativeVersionMatches(version2, receipt) && JSON.stringify(receipt.plan.files) === serialized), "A retained native plugin cache version differs from every approved projection");
|
|
49444
49483
|
}
|
|
49445
49484
|
for (const row of rows)
|
|
49446
49485
|
pluginNeed(names.includes(row.version), "Managed native plugin installation is missing");
|
|
49447
|
-
const after =
|
|
49486
|
+
const after = lstatSync15(cacheRoot);
|
|
49448
49487
|
safe3(cacheRoot);
|
|
49449
49488
|
pluginNeed(before.dev === after.dev && before.ino === after.ino && before.mtimeMs === after.mtimeMs && before.ctimeMs === after.ctimeMs, "Managed cache version membership changed during verification");
|
|
49450
49489
|
}
|
|
@@ -49459,19 +49498,19 @@ var init_plugin_discovery = __esm(() => {
|
|
|
49459
49498
|
|
|
49460
49499
|
// src/lib/claude-marketplace-registry.ts
|
|
49461
49500
|
import { createHash as createHash13 } from "crypto";
|
|
49462
|
-
import { closeSync as closeSync12, constants as constants9, fstatSync as fstatSync12, lstatSync as
|
|
49463
|
-
import { basename as basename7, dirname as dirname13, isAbsolute as isAbsolute12, resolve as
|
|
49501
|
+
import { closeSync as closeSync12, constants as constants9, fstatSync as fstatSync12, lstatSync as lstatSync16, openSync as openSync12, readSync as readSync8 } from "fs";
|
|
49502
|
+
import { basename as basename7, dirname as dirname13, isAbsolute as isAbsolute12, resolve as resolve14 } from "path";
|
|
49464
49503
|
function need5(value, reason) {
|
|
49465
49504
|
if (!value)
|
|
49466
49505
|
throw new Error(`Claude marketplace registry ${reason}`);
|
|
49467
49506
|
}
|
|
49468
49507
|
function absolutePath2(value) {
|
|
49469
|
-
need5(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute12(value) &&
|
|
49508
|
+
need5(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute12(value) && resolve14(value) === value, "requires a normalized absolute path");
|
|
49470
49509
|
}
|
|
49471
49510
|
function parents2(path) {
|
|
49472
49511
|
const result = [];
|
|
49473
49512
|
for (let at = dirname13(path);; at = dirname13(at)) {
|
|
49474
|
-
const stat2 =
|
|
49513
|
+
const stat2 = lstatSync16(at, { bigint: true });
|
|
49475
49514
|
need5(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
|
|
49476
49515
|
result.push([at, stat2]);
|
|
49477
49516
|
if (at === dirname13(at))
|
|
@@ -49482,7 +49521,7 @@ function readRegistry2(path, budget) {
|
|
|
49482
49521
|
absolutePath2(path);
|
|
49483
49522
|
need5(basename7(path) === "known_marketplaces.json", "requires known_marketplaces.json");
|
|
49484
49523
|
need5(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
|
|
49485
|
-
const ancestors2 = parents2(path), initial =
|
|
49524
|
+
const ancestors2 = parents2(path), initial = lstatSync16(path, { bigint: true });
|
|
49486
49525
|
need5(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
|
|
49487
49526
|
need5(initial.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
|
|
49488
49527
|
const fd = openSync12(path, constants9.O_RDONLY | constants9.O_NOFOLLOW | constants9.O_NONBLOCK);
|
|
@@ -49497,10 +49536,10 @@ function readRegistry2(path, budget) {
|
|
|
49497
49536
|
break;
|
|
49498
49537
|
length += count;
|
|
49499
49538
|
}
|
|
49500
|
-
const after = fstatSync12(fd, { bigint: true }), current =
|
|
49539
|
+
const after = fstatSync12(fd, { bigint: true }), current = lstatSync16(path, { bigint: true });
|
|
49501
49540
|
need5(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
|
|
49502
49541
|
for (const [ancestor, before] of ancestors2) {
|
|
49503
|
-
const now =
|
|
49542
|
+
const now = lstatSync16(ancestor, { bigint: true });
|
|
49504
49543
|
need5(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
|
|
49505
49544
|
}
|
|
49506
49545
|
budget.remaining -= length;
|
|
@@ -49640,7 +49679,7 @@ var init_claude_marketplace_registry = __esm(() => {
|
|
|
49640
49679
|
});
|
|
49641
49680
|
|
|
49642
49681
|
// src/lib/codex-hook-trust-files.ts
|
|
49643
|
-
import { closeSync as closeSync13, constants as constants10, fstatSync as fstatSync13, fsyncSync as fsyncSync3, lstatSync as
|
|
49682
|
+
import { closeSync as closeSync13, constants as constants10, fstatSync as fstatSync13, fsyncSync as fsyncSync3, lstatSync as lstatSync17, openSync as openSync13, readSync as readSync9, writeFileSync as writeFileSync5 } from "fs";
|
|
49644
49683
|
import { createHash as createHash14 } from "crypto";
|
|
49645
49684
|
import { dirname as dirname14 } from "path";
|
|
49646
49685
|
function need6(value, code) {
|
|
@@ -49649,7 +49688,7 @@ function need6(value, code) {
|
|
|
49649
49688
|
}
|
|
49650
49689
|
function safeParents(file2) {
|
|
49651
49690
|
for (let p = dirname14(file2);; p = dirname14(p)) {
|
|
49652
|
-
const s =
|
|
49691
|
+
const s = lstatSync17(p);
|
|
49653
49692
|
need6(s.isDirectory() && !s.isSymbolicLink(), "UNSAFE_PARENT");
|
|
49654
49693
|
need6((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
|
|
49655
49694
|
if (dirname14(p) === p)
|
|
@@ -49659,7 +49698,7 @@ function safeParents(file2) {
|
|
|
49659
49698
|
function snapshot(file2, privateFile = false, options = {}) {
|
|
49660
49699
|
const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
|
|
49661
49700
|
safeParents(file2);
|
|
49662
|
-
const initial =
|
|
49701
|
+
const initial = lstatSync17(file2, { bigint: true });
|
|
49663
49702
|
need6(initial.isFile() && initial.uid === BigInt(process.getuid()) && (initial.nlink === 1n || readOnlyPackage && initial.nlink > 1n) && (initial.mode & 0o022n) === 0n && (!privateFile || (initial.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
|
|
49664
49703
|
need6(initial.size <= 8n * 1024n * 1024n, "FILE_BOUND");
|
|
49665
49704
|
const fd = openSync13(file2, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
|
|
@@ -49674,7 +49713,7 @@ function snapshot(file2, privateFile = false, options = {}) {
|
|
|
49674
49713
|
break;
|
|
49675
49714
|
length += n2;
|
|
49676
49715
|
}
|
|
49677
|
-
need6(length === Number(before.size) && sameStat(before, fstatSync13(fd, { bigint: true })) && sameStat(before,
|
|
49716
|
+
need6(length === Number(before.size) && sameStat(before, fstatSync13(fd, { bigint: true })) && sameStat(before, lstatSync17(file2, { bigint: true })), "INPUT_CHANGED");
|
|
49678
49717
|
const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
|
|
49679
49718
|
return { file: file2, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash14("sha256").update(content).digest("hex") };
|
|
49680
49719
|
} finally {
|
|
@@ -49729,8 +49768,8 @@ var init_codex_hook_discovery_recovery = __esm(() => {
|
|
|
49729
49768
|
|
|
49730
49769
|
// src/lib/agent-discovery.ts
|
|
49731
49770
|
import { createHash as createHash16 } from "crypto";
|
|
49732
|
-
import { lstatSync as
|
|
49733
|
-
import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute13, join as
|
|
49771
|
+
import { lstatSync as lstatSync18, readFileSync as readFileSync15, readdirSync as readdirSync7, realpathSync as realpathSync5 } from "fs";
|
|
49772
|
+
import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute13, join as join25, resolve as resolve15, sep as sep5 } from "path";
|
|
49734
49773
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
49735
49774
|
function parseConfig(text2, path, toml = false) {
|
|
49736
49775
|
try {
|
|
@@ -49746,7 +49785,7 @@ function safe4(path) {
|
|
|
49746
49785
|
if (!isAbsolute13(path) || path.includes("\x00"))
|
|
49747
49786
|
throw new Error("Expected an absolute native discovery path");
|
|
49748
49787
|
for (let cursor = path;; cursor = dirname15(cursor)) {
|
|
49749
|
-
if (
|
|
49788
|
+
if (lstatSync18(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
49750
49789
|
throw new Error(`Refusing symlink native discovery input: ${cursor}`);
|
|
49751
49790
|
if (dirname15(cursor) === cursor)
|
|
49752
49791
|
break;
|
|
@@ -49756,7 +49795,7 @@ function read(path, changes) {
|
|
|
49756
49795
|
safe4(path);
|
|
49757
49796
|
if (changes?.has(path))
|
|
49758
49797
|
return changes.get(path);
|
|
49759
|
-
const stat2 =
|
|
49798
|
+
const stat2 = lstatSync18(path, { throwIfNoEntry: false });
|
|
49760
49799
|
if (!stat2)
|
|
49761
49800
|
return null;
|
|
49762
49801
|
if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
|
|
@@ -49867,12 +49906,12 @@ function codexInstallationRoots(binding) {
|
|
|
49867
49906
|
if (binding.agent !== "codex" || binding.method !== "reviewed" || proof.version !== "codex-cli 0.160.0" || !/^[a-f0-9]{64}$/.test(proof.catalogSha256) || !Array.isArray(proof.plugins) || !proof.plugins.length)
|
|
49868
49907
|
throw new Error("Invalid native installation input proof");
|
|
49869
49908
|
const cache = dirname15(dirname15(proof.plugins[0].pluginParent));
|
|
49870
|
-
const config2 =
|
|
49909
|
+
const config2 = join25(dirname15(dirname15(cache)), "config.toml"), home = dirname15(dirname15(dirname15(cache)));
|
|
49871
49910
|
const configSource = binding.sources.find((source) => source.path === config2 && source.sha256 !== null && (!source.format || source.format === "toml" && source.fields?.includes("plugins")));
|
|
49872
|
-
const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) =>
|
|
49911
|
+
const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join25(home, path));
|
|
49873
49912
|
if (!configSource || proof.plugins.some((input2) => nativeRoots.some((root) => root === input2.sourceRoot || root.startsWith(input2.sourceRoot + sep5) || input2.sourceRoot.startsWith(root + sep5)) || binding.sources.some((source) => basename8(source.path) === "config.toml" && (source.path === input2.sourceRoot || source.path.startsWith(input2.sourceRoot + sep5)))))
|
|
49874
49913
|
throw new Error("Native installation input overlaps configuration or loading roots");
|
|
49875
|
-
if (proof.plugins.some((input2) => dirname15(dirname15(input2.pluginParent)) !== cache || !binding.sources.some((source) => source.path ===
|
|
49914
|
+
if (proof.plugins.some((input2) => dirname15(dirname15(input2.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join25(input2.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
|
|
49876
49915
|
throw new Error("Missing native installation input source witness");
|
|
49877
49916
|
return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
|
|
49878
49917
|
const text2 = read(path);
|
|
@@ -49890,10 +49929,12 @@ function assertMarketplaceBinding(binding, source) {
|
|
|
49890
49929
|
throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
|
|
49891
49930
|
}
|
|
49892
49931
|
function agentDiscoveryConfigPath(home, agent) {
|
|
49893
|
-
|
|
49932
|
+
if (agent === "sumi")
|
|
49933
|
+
return sumiConfigPath(home);
|
|
49934
|
+
return join25(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
|
|
49894
49935
|
}
|
|
49895
49936
|
function resolveAgentDiscovery(options) {
|
|
49896
|
-
const canonical6 = options.canonical ??
|
|
49937
|
+
const canonical6 = options.canonical ?? resolve15, home = resolve15(options.home), agent = options.agent;
|
|
49897
49938
|
const sources = [], roots = new Set, builtinNames = [];
|
|
49898
49939
|
const witness = (path, format, fields2) => {
|
|
49899
49940
|
const source = { path: canonical6(path), sha256: null, ...format ? { format, fields: fields2 } : {} };
|
|
@@ -49904,13 +49945,49 @@ function resolveAgentDiscovery(options) {
|
|
|
49904
49945
|
if (agent === "hermes")
|
|
49905
49946
|
assertHermesEnvironment(home);
|
|
49906
49947
|
const configPath = agentDiscoveryConfigPath(home, agent);
|
|
49907
|
-
const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? [...CODEX_DISCOVERY_PROJECTION_FIELDS] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : ["version"]);
|
|
49948
|
+
const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? [...CODEX_DISCOVERY_PROJECTION_FIELDS] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : agent === "sumi" ? ["skills", "plugin", "plugins", "permissions"] : ["version"]);
|
|
49908
49949
|
const config2 = configText === null ? {} : agent === "hermes" ? parseHermesConfig(configText) : parseConfig(configText, configPath, agent === "codex");
|
|
49909
49950
|
const unresolved = (detail) => {
|
|
49910
49951
|
throw new Error(`Native discovery is unresolved (${agent}: ${detail}); provide a reviewed --discovery-inputs file`);
|
|
49911
49952
|
};
|
|
49953
|
+
if (agent === "sumi") {
|
|
49954
|
+
const directory = sumiConfigDirectory(home);
|
|
49955
|
+
if (witness(join25(directory, "sumi.jsonc")) !== null)
|
|
49956
|
+
unresolved("JSONC configuration requires a supported format adapter");
|
|
49957
|
+
for (const root of [directory, join25(home, ".claude"), join25(home, ".agents")])
|
|
49958
|
+
for (const name of ["skill", "skills"])
|
|
49959
|
+
roots.add(join25(root, name));
|
|
49960
|
+
if (config2.skills !== undefined && (!Array.isArray(config2.skills) || config2.skills.some((path) => typeof path !== "string")))
|
|
49961
|
+
unresolved("skills must be a string array");
|
|
49962
|
+
for (const value of config2.skills ?? []) {
|
|
49963
|
+
if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute13(value) || value.startsWith("~/")))
|
|
49964
|
+
unresolved("remote or relative skill sources need a dedicated discovery adapter");
|
|
49965
|
+
roots.add(value.startsWith("~/") ? join25(home, value.slice(2)) : value);
|
|
49966
|
+
}
|
|
49967
|
+
for (const key of ["plugin", "plugins"])
|
|
49968
|
+
if (config2[key] !== undefined && !Array.isArray(config2[key]))
|
|
49969
|
+
unresolved(`${key} must be an array`);
|
|
49970
|
+
const plugins = [join25(directory, "plugin"), join25(directory, "plugins")];
|
|
49971
|
+
for (const path of plugins) {
|
|
49972
|
+
safe4(path);
|
|
49973
|
+
if (lstatSync18(path, { throwIfNoEntry: false })?.isDirectory())
|
|
49974
|
+
for (const name of readdirSync7(path).sort()) {
|
|
49975
|
+
if (name === "skills-cli.js" && path === plugins[1])
|
|
49976
|
+
continue;
|
|
49977
|
+
const target = join25(path, name);
|
|
49978
|
+
if (!lstatSync18(target).isFile())
|
|
49979
|
+
unresolved("local plugin packages need a dedicated discovery adapter");
|
|
49980
|
+
witness(target);
|
|
49981
|
+
}
|
|
49982
|
+
}
|
|
49983
|
+
for (const root of roots) {
|
|
49984
|
+
safe4(root);
|
|
49985
|
+
if (lstatSync18(root, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(root).some((name) => name.endsWith(".md")))
|
|
49986
|
+
unresolved("flat markdown skills require a dedicated native migration adapter");
|
|
49987
|
+
}
|
|
49988
|
+
}
|
|
49912
49989
|
if (agent === "hermes") {
|
|
49913
|
-
const profile = witness(
|
|
49990
|
+
const profile = witness(join25(home, ".hermes/active_profile"));
|
|
49914
49991
|
if (profile?.trim() && profile.trim() !== "default")
|
|
49915
49992
|
unresolved("a non-default profile is active");
|
|
49916
49993
|
const declared = config2.skills?.external_dirs ?? [], paths = typeof declared === "string" ? [declared] : declared;
|
|
@@ -49924,7 +50001,7 @@ function resolveAgentDiscovery(options) {
|
|
|
49924
50001
|
continue;
|
|
49925
50002
|
if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
|
|
49926
50003
|
unresolved("user-specific tilde expansion requires a separate discovery adapter");
|
|
49927
|
-
const path = normalized === "~" ? home : normalized.startsWith("~/") ?
|
|
50004
|
+
const path = normalized === "~" ? home : normalized.startsWith("~/") ? join25(home, normalized.slice(2)) : resolve15(home, ".hermes", normalized);
|
|
49928
50005
|
safe4(path);
|
|
49929
50006
|
roots.add(path);
|
|
49930
50007
|
}
|
|
@@ -49933,8 +50010,8 @@ function resolveAgentDiscovery(options) {
|
|
|
49933
50010
|
const executable = Bun.which("gemini");
|
|
49934
50011
|
if (executable) {
|
|
49935
50012
|
let packageRoot;
|
|
49936
|
-
for (let directory = dirname15(
|
|
49937
|
-
const path =
|
|
50013
|
+
for (let directory = dirname15(realpathSync5(executable)), depth = 0;depth < 8; directory = dirname15(directory), depth++) {
|
|
50014
|
+
const path = join25(directory, "package.json"), raw = read(path);
|
|
49938
50015
|
if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
|
|
49939
50016
|
packageRoot = directory;
|
|
49940
50017
|
witness(path);
|
|
@@ -49945,12 +50022,12 @@ function resolveAgentDiscovery(options) {
|
|
|
49945
50022
|
}
|
|
49946
50023
|
if (!packageRoot)
|
|
49947
50024
|
unresolved("installed Gemini package layout is not recognized");
|
|
49948
|
-
const builtinRoot =
|
|
50025
|
+
const builtinRoot = join25(packageRoot, "bundle/builtin");
|
|
49949
50026
|
safe4(builtinRoot);
|
|
49950
|
-
if (!
|
|
50027
|
+
if (!lstatSync18(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
|
|
49951
50028
|
unresolved("installed Gemini builtin root is missing");
|
|
49952
50029
|
for (const name of readdirSync7(builtinRoot).sort()) {
|
|
49953
|
-
const text2 = witness(
|
|
50030
|
+
const text2 = witness(join25(builtinRoot, name, "SKILL.md"));
|
|
49954
50031
|
const match = text2?.match(/^---\r?\n[\s\S]*?^name:\s*([a-z0-9][a-z0-9-]*)\s*$/m);
|
|
49955
50032
|
if (!match?.[1] || builtinNames.includes(match[1]))
|
|
49956
50033
|
unresolved("installed Gemini builtin name is missing or ambiguous");
|
|
@@ -49992,39 +50069,39 @@ function resolveAgentDiscovery(options) {
|
|
|
49992
50069
|
function plugin(root) {
|
|
49993
50070
|
root = canonical6(root);
|
|
49994
50071
|
safe4(root);
|
|
49995
|
-
const manifestPath =
|
|
50072
|
+
const manifestPath = join25(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
|
|
49996
50073
|
const raw = witness(manifestPath);
|
|
49997
50074
|
if (raw === null)
|
|
49998
50075
|
unresolved("plugin manifest missing");
|
|
49999
50076
|
const manifest = parseConfig(raw, manifestPath);
|
|
50000
|
-
const hooks = witness(
|
|
50077
|
+
const hooks = witness(join25(root, "hooks/hooks.json"));
|
|
50001
50078
|
if (manifest.hooks !== undefined || hooks !== null)
|
|
50002
50079
|
unresolved("plugin hooks require a separate no-skill-injection review");
|
|
50003
|
-
const commands =
|
|
50080
|
+
const commands = join25(root, "commands");
|
|
50004
50081
|
safe4(commands);
|
|
50005
|
-
if (agent === "claude" && (manifest.commands !== undefined ||
|
|
50082
|
+
if (agent === "claude" && (manifest.commands !== undefined || lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length))
|
|
50006
50083
|
unresolved("legacy command discovery requires retirement or a dedicated format adapter");
|
|
50007
|
-
const rootSkill = witness(
|
|
50084
|
+
const rootSkill = witness(join25(root, "SKILL.md"));
|
|
50008
50085
|
if (rootSkill !== null)
|
|
50009
50086
|
roots.add(root);
|
|
50010
50087
|
const declared = manifest.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
|
|
50011
50088
|
if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
|
|
50012
50089
|
unresolved("unsupported plugin skill paths");
|
|
50013
50090
|
if (agent === "claude")
|
|
50014
|
-
roots.add(
|
|
50091
|
+
roots.add(join25(root, "skills"));
|
|
50015
50092
|
for (const value of declared) {
|
|
50016
|
-
const path =
|
|
50093
|
+
const path = resolve15(root, value);
|
|
50017
50094
|
if (path !== root && !path.startsWith(root + sep5))
|
|
50018
50095
|
unresolved("plugin skill path escapes its root");
|
|
50019
50096
|
roots.add(path.endsWith(`${sep5}SKILL.md`) ? dirname15(path) : path);
|
|
50020
50097
|
}
|
|
50021
50098
|
}
|
|
50022
50099
|
if (agent === "claude") {
|
|
50023
|
-
const registrations = witness(
|
|
50024
|
-
const installed = registrations === null ? {} : parseConfig(registrations,
|
|
50025
|
-
const commands = canonical6(
|
|
50100
|
+
const registrations = witness(join25(home, ".claude/plugins/installed_plugins.json"));
|
|
50101
|
+
const installed = registrations === null ? {} : parseConfig(registrations, join25(home, ".claude/plugins/installed_plugins.json")).plugins;
|
|
50102
|
+
const commands = canonical6(join25(home, ".claude/commands"));
|
|
50026
50103
|
safe4(commands);
|
|
50027
|
-
if (
|
|
50104
|
+
if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
|
|
50028
50105
|
unresolved("legacy home command discovery requires a dedicated format adapter");
|
|
50029
50106
|
for (const [id, enabled] of Object.entries(config2.enabledPlugins ?? {})) {
|
|
50030
50107
|
if (enabled === false)
|
|
@@ -50046,16 +50123,16 @@ function resolveAgentDiscovery(options) {
|
|
|
50046
50123
|
const market = config2.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
|
|
50047
50124
|
if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute13(market.source))
|
|
50048
50125
|
unresolved("enabled plugin marketplace is not an explicit local source");
|
|
50049
|
-
const catalogText = witness(
|
|
50126
|
+
const catalogText = witness(join25(market.source, ".agents/plugins/marketplace.json"));
|
|
50050
50127
|
if (catalogText === null)
|
|
50051
50128
|
unresolved("marketplace catalog missing");
|
|
50052
|
-
const catalog = parseConfig(catalogText,
|
|
50129
|
+
const catalog = parseConfig(catalogText, join25(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
|
|
50053
50130
|
if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
|
|
50054
50131
|
unresolved("plugin catalog source is missing or ambiguous");
|
|
50055
|
-
plugin(
|
|
50132
|
+
plugin(resolve15(market.source, matches[0].source.path));
|
|
50056
50133
|
}
|
|
50057
50134
|
} else if (agent === "opencode") {
|
|
50058
|
-
if (witness(
|
|
50135
|
+
if (witness(join25(home, ".config/opencode/opencode.jsonc")) !== null || witness(join25(home, ".config/opencode/config.json")) !== null)
|
|
50059
50136
|
unresolved("additional config layers require review");
|
|
50060
50137
|
if ((config2.plugin?.length ?? 0) > 0 || config2.skills?.urls?.length)
|
|
50061
50138
|
unresolved("external plugin or remote skill source");
|
|
@@ -50064,14 +50141,17 @@ function resolveAgentDiscovery(options) {
|
|
|
50064
50141
|
unresolved("relative or malformed added skill root");
|
|
50065
50142
|
roots.add(path);
|
|
50066
50143
|
}
|
|
50067
|
-
const localPlugins =
|
|
50144
|
+
const localPlugins = join25(home, ".config/opencode/plugins");
|
|
50068
50145
|
safe4(localPlugins);
|
|
50069
|
-
if (
|
|
50146
|
+
if (lstatSync18(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
|
|
50070
50147
|
unresolved("additional local plugin hooks require review");
|
|
50148
|
+
} else if (agent === "sumi") {
|
|
50149
|
+
if ((config2.plugin?.length ?? 0) > 0 || (config2.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical6(configPath) && source.path !== canonical6(join25(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
|
|
50150
|
+
unresolved("external or foreign local plugins require review");
|
|
50071
50151
|
} else if (agent === "hermes") {
|
|
50072
|
-
for (const directory of [
|
|
50152
|
+
for (const directory of [join25(home, ".hermes/plugins"), join25(home, ".hermes/hermes-agent")]) {
|
|
50073
50153
|
safe4(directory);
|
|
50074
|
-
if (
|
|
50154
|
+
if (lstatSync18(directory, { throwIfNoEntry: false }))
|
|
50075
50155
|
unresolved("installed runtime/plugin discovery requires reviewed source bindings");
|
|
50076
50156
|
}
|
|
50077
50157
|
if (Bun.which("hermes") || Object.keys(config2.plugins ?? {}).length)
|
|
@@ -50079,24 +50159,24 @@ function resolveAgentDiscovery(options) {
|
|
|
50079
50159
|
} else if (agent === "gemini") {
|
|
50080
50160
|
if (Object.keys(config2.extensions ?? {}).length || config2.skills?.paths?.length)
|
|
50081
50161
|
unresolved("custom extension or skill paths");
|
|
50082
|
-
const directory =
|
|
50162
|
+
const directory = join25(home, ".gemini/extensions");
|
|
50083
50163
|
safe4(directory);
|
|
50084
|
-
if (
|
|
50164
|
+
if (lstatSync18(directory, { throwIfNoEntry: false }))
|
|
50085
50165
|
for (const name of readdirSync7(directory)) {
|
|
50086
|
-
const root =
|
|
50166
|
+
const root = join25(directory, name);
|
|
50087
50167
|
safe4(root);
|
|
50088
|
-
if (!
|
|
50168
|
+
if (!lstatSync18(root)?.isDirectory())
|
|
50089
50169
|
continue;
|
|
50090
|
-
const raw = witness(
|
|
50170
|
+
const raw = witness(join25(root, "gemini-extension.json"));
|
|
50091
50171
|
if (raw === null)
|
|
50092
50172
|
unresolved("extension registration missing");
|
|
50093
|
-
const manifest = parseConfig(raw,
|
|
50094
|
-
if (manifest.hooks !== undefined || witness(
|
|
50173
|
+
const manifest = parseConfig(raw, join25(root, "gemini-extension.json"));
|
|
50174
|
+
if (manifest.hooks !== undefined || witness(join25(root, "hooks/hooks.json")) !== null || witness(join25(root, ".gemini-extension-install.json")) !== null)
|
|
50095
50175
|
unresolved("extension hooks or linked registration require review");
|
|
50096
|
-
roots.add(
|
|
50176
|
+
roots.add(join25(root, "skills"));
|
|
50097
50177
|
}
|
|
50098
50178
|
}
|
|
50099
|
-
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([
|
|
50179
|
+
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join25(home, ".hermes/plugins"), join25(home, ".hermes/hermes-agent")].map((path) => canonical6(path))) } : {} };
|
|
50100
50180
|
}
|
|
50101
50181
|
var digest = (text2) => createHash16("sha256").update(text2).digest("hex");
|
|
50102
50182
|
var init_agent_discovery = __esm(() => {
|
|
@@ -50112,16 +50192,17 @@ var init_agent_discovery = __esm(() => {
|
|
|
50112
50192
|
init_codex_hook_discovery_recovery();
|
|
50113
50193
|
init_codex_settings_witness();
|
|
50114
50194
|
init_codex_plugin_skill_controls();
|
|
50195
|
+
init_agent_sumi();
|
|
50115
50196
|
init_native_discovery_roots();
|
|
50116
50197
|
init_agent_discovery_directories();
|
|
50117
50198
|
});
|
|
50118
50199
|
|
|
50119
50200
|
// src/lib/authoring-path.ts
|
|
50120
|
-
import { lstatSync as
|
|
50201
|
+
import { lstatSync as lstatSync19, realpathSync as realpathSync6 } from "fs";
|
|
50121
50202
|
import { homedir as homedir3 } from "os";
|
|
50122
|
-
import { basename as basename9, dirname as dirname16, join as
|
|
50203
|
+
import { basename as basename9, dirname as dirname16, join as join26, resolve as resolve16, sep as sep6 } from "path";
|
|
50123
50204
|
function pathParts(path) {
|
|
50124
|
-
return
|
|
50205
|
+
return resolve16(path).split(sep6).filter(Boolean);
|
|
50125
50206
|
}
|
|
50126
50207
|
function nativeRootMatch(path) {
|
|
50127
50208
|
const parts = pathParts(path);
|
|
@@ -50135,24 +50216,24 @@ function nativeRootMatch(path) {
|
|
|
50135
50216
|
return;
|
|
50136
50217
|
}
|
|
50137
50218
|
function physicalPath(path) {
|
|
50138
|
-
let cursor =
|
|
50219
|
+
let cursor = resolve16(path);
|
|
50139
50220
|
const suffix = [];
|
|
50140
|
-
while (!
|
|
50221
|
+
while (!lstatSync19(cursor, { throwIfNoEntry: false })) {
|
|
50141
50222
|
suffix.unshift(basename9(cursor));
|
|
50142
50223
|
const parent = dirname16(cursor);
|
|
50143
50224
|
if (parent === cursor)
|
|
50144
|
-
return
|
|
50225
|
+
return resolve16(path);
|
|
50145
50226
|
cursor = parent;
|
|
50146
50227
|
}
|
|
50147
|
-
return
|
|
50228
|
+
return resolve16(realpathSync6(cursor), ...suffix);
|
|
50148
50229
|
}
|
|
50149
50230
|
function contains(root, path) {
|
|
50150
50231
|
return path === root || path.startsWith(root + sep6);
|
|
50151
50232
|
}
|
|
50152
50233
|
function configuredRoots(home, explicitHome) {
|
|
50153
|
-
const homeData =
|
|
50234
|
+
const homeData = join26(home, ".hasna", "skills");
|
|
50154
50235
|
const homePolicy = readManagedSkillPolicySnapshot(homeData);
|
|
50155
|
-
const configuredPolicy = !explicitHome &&
|
|
50236
|
+
const configuredPolicy = !explicitHome && resolve16(getDataDirReadOnly()) !== resolve16(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
|
|
50156
50237
|
const policy = homePolicy ?? configuredPolicy;
|
|
50157
50238
|
const bridge = policy?.value.bridge;
|
|
50158
50239
|
if (bridge && (typeof bridge.home !== "string" || physicalPath(bridge.home) !== physicalPath(home))) {
|
|
@@ -50181,8 +50262,8 @@ function configuredRoots(home, explicitHome) {
|
|
|
50181
50262
|
admitBinding(binding);
|
|
50182
50263
|
continue;
|
|
50183
50264
|
}
|
|
50184
|
-
const nativeHome =
|
|
50185
|
-
if (!
|
|
50265
|
+
const nativeHome = join26(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
|
|
50266
|
+
if (!lstatSync19(nativeHome, { throwIfNoEntry: false }))
|
|
50186
50267
|
continue;
|
|
50187
50268
|
roots.push(...resolveAgentDiscovery({ home, agent, canonical: physicalPath }).roots);
|
|
50188
50269
|
}
|
|
@@ -50191,22 +50272,22 @@ function configuredRoots(home, explicitHome) {
|
|
|
50191
50272
|
function assertPortableAuthoringPath(path, options = {}) {
|
|
50192
50273
|
if (typeof path !== "string" || !path || path.includes("\x00"))
|
|
50193
50274
|
throw new Error("Invalid portable authoring path");
|
|
50194
|
-
const lexical =
|
|
50275
|
+
const lexical = resolve16(path);
|
|
50195
50276
|
const physical = physicalPath(lexical);
|
|
50196
50277
|
const candidates = [lexical, physical];
|
|
50197
50278
|
let native = candidates.map(nativeRootMatch).find(Boolean);
|
|
50198
|
-
const home =
|
|
50199
|
-
const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) =>
|
|
50200
|
-
defaults.push(
|
|
50279
|
+
const home = resolve16(options.homeDir ?? homedir3());
|
|
50280
|
+
const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join26(home, ...parts));
|
|
50281
|
+
defaults.push(join26(home, ".codex/plugins/cache"), join26(home, ".claude/plugins/cache"), join26(home, ".claude/plugins/synced"), join26(home, ".gemini/extensions"));
|
|
50201
50282
|
for (const root of defaults) {
|
|
50202
|
-
if (candidates.some((candidate) => contains(
|
|
50283
|
+
if (candidates.some((candidate) => contains(resolve16(root), candidate) || contains(physicalPath(root), candidate)))
|
|
50203
50284
|
native ??= root;
|
|
50204
50285
|
}
|
|
50205
50286
|
if (native) {
|
|
50206
50287
|
throw new Error(`Refusing portable Skills authoring below native discovery root '${native}': ${lexical}. Set HASNA_SKILLS_DIR to a private authoring corpus outside native roots.`);
|
|
50207
50288
|
}
|
|
50208
50289
|
for (const root of configuredRoots(home, options.homeDir !== undefined)) {
|
|
50209
|
-
if (candidates.some((candidate) => contains(
|
|
50290
|
+
if (candidates.some((candidate) => contains(resolve16(root), candidate) || contains(physicalPath(root), candidate))) {
|
|
50210
50291
|
throw new Error(`Refusing portable Skills authoring below configured native discovery root: ${lexical}`);
|
|
50211
50292
|
}
|
|
50212
50293
|
}
|
|
@@ -50223,32 +50304,32 @@ var init_authoring_path = __esm(() => {
|
|
|
50223
50304
|
|
|
50224
50305
|
// src/lib/portable-skills.ts
|
|
50225
50306
|
import {
|
|
50226
|
-
existsSync as
|
|
50307
|
+
existsSync as existsSync12,
|
|
50227
50308
|
mkdirSync as mkdirSync7,
|
|
50228
50309
|
mkdtempSync,
|
|
50229
50310
|
readdirSync as readdirSync8,
|
|
50230
|
-
realpathSync as
|
|
50311
|
+
realpathSync as realpathSync7,
|
|
50231
50312
|
renameSync as renameSync3,
|
|
50232
50313
|
rmSync as rmSync3,
|
|
50233
50314
|
statSync as statSync7,
|
|
50234
50315
|
writeFileSync as writeFileSync6
|
|
50235
50316
|
} from "fs";
|
|
50236
|
-
import { basename as basename10, dirname as dirname17, isAbsolute as isAbsolute14, join as
|
|
50317
|
+
import { basename as basename10, dirname as dirname17, isAbsolute as isAbsolute14, join as join27, normalize as normalize3, relative as relative5, resolve as resolve17, sep as sep7 } from "path";
|
|
50237
50318
|
function getPortableSkillsRoot(options = {}) {
|
|
50238
50319
|
return resolvePortableSkillsRoot(options, true);
|
|
50239
50320
|
}
|
|
50240
50321
|
function resolvePortableSkillsRoot(options, migrate) {
|
|
50241
50322
|
if (options.rootDir)
|
|
50242
50323
|
return options.rootDir;
|
|
50243
|
-
const appDir = options.homeDir ?
|
|
50244
|
-
const cache =
|
|
50324
|
+
const appDir = options.homeDir ? join27(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
|
|
50325
|
+
const cache = join27(appDir, SKILLS_CACHE_DIRNAME);
|
|
50245
50326
|
if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache))
|
|
50246
50327
|
return cache;
|
|
50247
|
-
const installed =
|
|
50328
|
+
const installed = join27(appDir, INSTALLED_SKILLS_DIRNAME);
|
|
50248
50329
|
return installed;
|
|
50249
50330
|
}
|
|
50250
50331
|
function getPortableSkillPath(name, options = {}) {
|
|
50251
|
-
return
|
|
50332
|
+
return join27(getPortableSkillsRoot(options), normalizePortableSkillName(name));
|
|
50252
50333
|
}
|
|
50253
50334
|
function findPortableSkill(name, options = {}) {
|
|
50254
50335
|
let normalized;
|
|
@@ -50258,7 +50339,7 @@ function findPortableSkill(name, options = {}) {
|
|
|
50258
50339
|
return null;
|
|
50259
50340
|
}
|
|
50260
50341
|
const path = getPortableSkillPath(normalized, options);
|
|
50261
|
-
if (!
|
|
50342
|
+
if (!existsSync12(path) || !statSync7(path).isDirectory())
|
|
50262
50343
|
return null;
|
|
50263
50344
|
try {
|
|
50264
50345
|
return summarizePortableSkill(path, normalized);
|
|
@@ -50274,7 +50355,7 @@ function listPortableSkills(options = {}) {
|
|
|
50274
50355
|
for (const entry of readdirSync8(root).sort()) {
|
|
50275
50356
|
if (entry.startsWith("."))
|
|
50276
50357
|
continue;
|
|
50277
|
-
const path =
|
|
50358
|
+
const path = join27(root, entry);
|
|
50278
50359
|
if (!safeIsDirectory(path))
|
|
50279
50360
|
continue;
|
|
50280
50361
|
try {
|
|
@@ -50307,11 +50388,11 @@ function isOfficialSkillName(name) {
|
|
|
50307
50388
|
function scaffoldPortableSkill(name, options = {}) {
|
|
50308
50389
|
const skillName = normalizeNewPortableSkillName(name);
|
|
50309
50390
|
const readOnlyRoot = resolvePortableSkillsRoot(options, false);
|
|
50310
|
-
assertPortableAuthoringPath(
|
|
50391
|
+
assertPortableAuthoringPath(join27(readOnlyRoot, skillName), options);
|
|
50311
50392
|
const root = getPortableSkillsRoot(options);
|
|
50312
|
-
const skillPath =
|
|
50393
|
+
const skillPath = join27(root, skillName);
|
|
50313
50394
|
assertPortableAuthoringPath(skillPath, options);
|
|
50314
|
-
if (
|
|
50395
|
+
if (existsSync12(skillPath)) {
|
|
50315
50396
|
if (!options.overwrite)
|
|
50316
50397
|
throw new Error(`Skill '${skillName}' already exists at ${skillPath}`);
|
|
50317
50398
|
rmSync3(skillPath, { recursive: true, force: true });
|
|
@@ -50328,16 +50409,16 @@ function scaffoldPortableSkill(name, options = {}) {
|
|
|
50328
50409
|
return { name: skillName, path: skillPath, manifest, created: true };
|
|
50329
50410
|
}
|
|
50330
50411
|
function physicalImportPath(path) {
|
|
50331
|
-
let ancestor =
|
|
50412
|
+
let ancestor = resolve17(path);
|
|
50332
50413
|
const suffix = [];
|
|
50333
|
-
while (!
|
|
50414
|
+
while (!existsSync12(ancestor)) {
|
|
50334
50415
|
suffix.unshift(basename10(ancestor));
|
|
50335
50416
|
ancestor = dirname17(ancestor);
|
|
50336
50417
|
}
|
|
50337
|
-
return
|
|
50418
|
+
return join27(realpathSync7(ancestor), ...suffix);
|
|
50338
50419
|
}
|
|
50339
50420
|
function assertDisjointImportPaths(source, destination) {
|
|
50340
|
-
const sourcePath =
|
|
50421
|
+
const sourcePath = realpathSync7(source);
|
|
50341
50422
|
const destinationPath = physicalImportPath(destination);
|
|
50342
50423
|
const contains2 = (parent, child) => {
|
|
50343
50424
|
const path = relative5(parent, child);
|
|
@@ -50349,7 +50430,7 @@ function assertDisjointImportPaths(source, destination) {
|
|
|
50349
50430
|
}
|
|
50350
50431
|
function portPortableSkill(sourcePath, options = {}) {
|
|
50351
50432
|
const absoluteSource = normalize3(sourcePath);
|
|
50352
|
-
if (!
|
|
50433
|
+
if (!existsSync12(absoluteSource) || !statSync7(absoluteSource).isDirectory()) {
|
|
50353
50434
|
throw new Error(`Skill source directory not found: ${sourcePath}`);
|
|
50354
50435
|
}
|
|
50355
50436
|
const inferred = readPortableSkillManifestForImport(absoluteSource);
|
|
@@ -50360,14 +50441,14 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
50360
50441
|
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename10(absoluteSource)}')` : ""} matches a bundled official skill.`;
|
|
50361
50442
|
throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
|
|
50362
50443
|
}
|
|
50363
|
-
const readOnlyDestination =
|
|
50444
|
+
const readOnlyDestination = join27(resolvePortableSkillsRoot(options, false), skillName);
|
|
50364
50445
|
assertPortableAuthoringPath(readOnlyDestination, options);
|
|
50365
50446
|
assertDisjointImportPaths(absoluteSource, readOnlyDestination);
|
|
50366
50447
|
const root = getPortableSkillsRoot(options);
|
|
50367
|
-
const destination =
|
|
50448
|
+
const destination = join27(root, skillName);
|
|
50368
50449
|
assertPortableAuthoringPath(destination, options);
|
|
50369
50450
|
assertDisjointImportPaths(absoluteSource, destination);
|
|
50370
|
-
if (
|
|
50451
|
+
if (existsSync12(destination)) {
|
|
50371
50452
|
if (!options.overwrite)
|
|
50372
50453
|
throw new Error(`Skill '${skillName}' already exists at ${destination}`);
|
|
50373
50454
|
rmSync3(destination, { recursive: true, force: true });
|
|
@@ -50395,10 +50476,10 @@ function validatePortableSkillDirectory(name, skillPath) {
|
|
|
50395
50476
|
const issues = [...base.issues];
|
|
50396
50477
|
const warnings = [...base.warnings];
|
|
50397
50478
|
let manifest;
|
|
50398
|
-
if (
|
|
50399
|
-
const skillJsonPath =
|
|
50400
|
-
const skillMdPath =
|
|
50401
|
-
if (!
|
|
50479
|
+
if (existsSync12(skillPath)) {
|
|
50480
|
+
const skillJsonPath = join27(skillPath, "skill.json");
|
|
50481
|
+
const skillMdPath = join27(skillPath, "SKILL.md");
|
|
50482
|
+
if (!existsSync12(skillJsonPath) && !existsSync12(skillMdPath)) {
|
|
50402
50483
|
add3(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
|
|
50403
50484
|
}
|
|
50404
50485
|
try {
|
|
@@ -50417,7 +50498,7 @@ function validatePortableSkillDirectory(name, skillPath) {
|
|
|
50417
50498
|
add3(issues, "portable.version_missing", "Portable manifest missing version");
|
|
50418
50499
|
}
|
|
50419
50500
|
const contractIssues = validatePortableManifestContract(manifest, {
|
|
50420
|
-
strict:
|
|
50501
|
+
strict: existsSync12(join27(skillPath, "skill.json")),
|
|
50421
50502
|
skillPath
|
|
50422
50503
|
});
|
|
50423
50504
|
for (const issue2 of contractIssues)
|
|
@@ -50457,8 +50538,8 @@ function validatePortableSkillDirectory(name, skillPath) {
|
|
|
50457
50538
|
add3(issues, "portable.command_entry_unsafe", `Command '${command.name}' entry '${command.entry}' must stay inside the skill directory`);
|
|
50458
50539
|
continue;
|
|
50459
50540
|
}
|
|
50460
|
-
const entryPath =
|
|
50461
|
-
if (!
|
|
50541
|
+
const entryPath = join27(skillPath, command.entry);
|
|
50542
|
+
if (!existsSync12(entryPath))
|
|
50462
50543
|
add3(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
|
|
50463
50544
|
else if (statSync7(entryPath).isDirectory())
|
|
50464
50545
|
add3(issues, "portable.command_entry_directory", `Command '${command.name}' entry '${command.entry}' must be a file`);
|
|
@@ -50468,7 +50549,7 @@ function validatePortableSkillDirectory(name, skillPath) {
|
|
|
50468
50549
|
} catch (error61) {
|
|
50469
50550
|
add3(issues, "portable.manifest_invalid", error61.message);
|
|
50470
50551
|
}
|
|
50471
|
-
if (manifest?.kind !== "instruction" && !
|
|
50552
|
+
if (manifest?.kind !== "instruction" && !existsSync12(join27(skillPath, "AGENTS.md"))) {
|
|
50472
50553
|
add3(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
|
|
50473
50554
|
}
|
|
50474
50555
|
}
|
|
@@ -50695,8 +50776,8 @@ var init_search = __esm(() => {
|
|
|
50695
50776
|
});
|
|
50696
50777
|
|
|
50697
50778
|
// src/lib/registry.ts
|
|
50698
|
-
import { existsSync as
|
|
50699
|
-
import { join as
|
|
50779
|
+
import { existsSync as existsSync13, readFileSync as readFileSync16, readdirSync as readdirSync9 } from "fs";
|
|
50780
|
+
import { join as join28 } from "path";
|
|
50700
50781
|
function parseSkillMdFrontmatter(content) {
|
|
50701
50782
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
50702
50783
|
if (!match)
|
|
@@ -50729,7 +50810,7 @@ function parseSkillMdFrontmatter(content) {
|
|
|
50729
50810
|
return Object.keys(result).length > 0 ? result : null;
|
|
50730
50811
|
}
|
|
50731
50812
|
function discoverSkillsInDir(dir, source = "custom") {
|
|
50732
|
-
if (!
|
|
50813
|
+
if (!existsSync13(dir))
|
|
50733
50814
|
return [];
|
|
50734
50815
|
const result = [];
|
|
50735
50816
|
try {
|
|
@@ -50737,8 +50818,8 @@ function discoverSkillsInDir(dir, source = "custom") {
|
|
|
50737
50818
|
for (const entry of entries) {
|
|
50738
50819
|
if (!entry.isDirectory())
|
|
50739
50820
|
continue;
|
|
50740
|
-
const skillMdPath =
|
|
50741
|
-
if (!
|
|
50821
|
+
const skillMdPath = join28(dir, entry.name, "SKILL.md");
|
|
50822
|
+
if (!existsSync13(skillMdPath))
|
|
50742
50823
|
continue;
|
|
50743
50824
|
let content;
|
|
50744
50825
|
try {
|
|
@@ -50757,7 +50838,7 @@ function discoverSkillsInDir(dir, source = "custom") {
|
|
|
50757
50838
|
category: fm.category || "Development Tools",
|
|
50758
50839
|
tags: fm.tags || [],
|
|
50759
50840
|
...fm.kind ? { kind: fm.kind } : {},
|
|
50760
|
-
...isHostedMetadataSkillDir(
|
|
50841
|
+
...isHostedMetadataSkillDir(join28(dir, entry.name)) ? { serverOwned: true } : {},
|
|
50761
50842
|
source
|
|
50762
50843
|
});
|
|
50763
50844
|
}
|
|
@@ -50766,16 +50847,16 @@ function discoverSkillsInDir(dir, source = "custom") {
|
|
|
50766
50847
|
}
|
|
50767
50848
|
function findExtensionSkillPath(name) {
|
|
50768
50849
|
const config2 = loadConfig();
|
|
50769
|
-
if (!config2.extensionsDir || !
|
|
50850
|
+
if (!config2.extensionsDir || !existsSync13(config2.extensionsDir))
|
|
50770
50851
|
return null;
|
|
50771
50852
|
try {
|
|
50772
50853
|
const entries = readdirSync9(config2.extensionsDir, { withFileTypes: true });
|
|
50773
50854
|
for (const entry of entries) {
|
|
50774
50855
|
if (!entry.isDirectory())
|
|
50775
50856
|
continue;
|
|
50776
|
-
const skillDir =
|
|
50777
|
-
const skillMdPath =
|
|
50778
|
-
if (!
|
|
50857
|
+
const skillDir = join28(config2.extensionsDir, entry.name);
|
|
50858
|
+
const skillMdPath = join28(skillDir, "SKILL.md");
|
|
50859
|
+
if (!existsSync13(skillMdPath))
|
|
50779
50860
|
continue;
|
|
50780
50861
|
let content;
|
|
50781
50862
|
try {
|
|
@@ -50818,8 +50899,8 @@ function clearRegistryCache() {
|
|
|
50818
50899
|
registryCacheTime = 0;
|
|
50819
50900
|
registryCacheKey = null;
|
|
50820
50901
|
}
|
|
50821
|
-
function getSkillsByCategory(category) {
|
|
50822
|
-
return loadRegistry().filter((s) => s.category === category);
|
|
50902
|
+
function getSkillsByCategory(category, catalog) {
|
|
50903
|
+
return (catalog ?? loadRegistry()).filter((s) => s.category === category);
|
|
50823
50904
|
}
|
|
50824
50905
|
function getSkill(name) {
|
|
50825
50906
|
const registry2 = loadRegistry();
|
|
@@ -51971,14 +52052,14 @@ var init_remote_workspace_leave = __esm(() => {
|
|
|
51971
52052
|
});
|
|
51972
52053
|
|
|
51973
52054
|
// src/lib/auth-store.ts
|
|
51974
|
-
import { chmodSync, existsSync as
|
|
51975
|
-
import { basename as basename11, dirname as dirname18, join as
|
|
52055
|
+
import { chmodSync, existsSync as existsSync14, mkdirSync as mkdirSync8, readFileSync as readFileSync17, renameSync as renameSync4, statSync as statSync8, unlinkSync as unlinkSync4, writeFileSync as writeFileSync7 } from "fs";
|
|
52056
|
+
import { basename as basename11, dirname as dirname18, join as join29 } from "path";
|
|
51976
52057
|
function getAuthFilePath(env = process.env) {
|
|
51977
52058
|
return skillsCredentialFilePath(env);
|
|
51978
52059
|
}
|
|
51979
52060
|
function getIdentityFilePath(env = process.env) {
|
|
51980
52061
|
const file2 = skillsCredentialFilePath(env);
|
|
51981
|
-
return
|
|
52062
|
+
return join29(dirname18(file2), basename11(file2).replace(/^credentials/, "identity") + ".json");
|
|
51982
52063
|
}
|
|
51983
52064
|
function getApiUrl(action, env = process.env, options = {}) {
|
|
51984
52065
|
return requireSkillsApiOrigin(action, env, options);
|
|
@@ -52206,10 +52287,10 @@ async function readQuoteUnavailableCode(response) {
|
|
|
52206
52287
|
let timer;
|
|
52207
52288
|
let deadlineExceeded = false;
|
|
52208
52289
|
const expired = Symbol("quote body deadline");
|
|
52209
|
-
const deadline = new Promise((
|
|
52290
|
+
const deadline = new Promise((resolve18) => {
|
|
52210
52291
|
timer = setTimeout(() => {
|
|
52211
52292
|
deadlineExceeded = true;
|
|
52212
|
-
|
|
52293
|
+
resolve18(expired);
|
|
52213
52294
|
reader.cancel().catch(() => {});
|
|
52214
52295
|
}, 1500);
|
|
52215
52296
|
});
|
|
@@ -53692,12 +53773,12 @@ class RemotePrivatePublicationsClient {
|
|
|
53692
53773
|
previous = view;
|
|
53693
53774
|
if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
|
|
53694
53775
|
return view;
|
|
53695
|
-
await new Promise((
|
|
53776
|
+
await new Promise((resolve18) => {
|
|
53696
53777
|
const timer = setTimeout(done, Math.min(1000, until - Date.now()));
|
|
53697
53778
|
function done() {
|
|
53698
53779
|
clearTimeout(timer);
|
|
53699
53780
|
options.signal?.removeEventListener("abort", done);
|
|
53700
|
-
|
|
53781
|
+
resolve18();
|
|
53701
53782
|
}
|
|
53702
53783
|
options.signal?.addEventListener("abort", done, { once: true });
|
|
53703
53784
|
});
|
|
@@ -53985,10 +54066,10 @@ var init_remote_auth = __esm(() => {
|
|
|
53985
54066
|
});
|
|
53986
54067
|
|
|
53987
54068
|
// src/lib/workspace-profile.ts
|
|
53988
|
-
import { constants as constants11, closeSync as closeSync14, fstatSync as fstatSync14, lstatSync as
|
|
54069
|
+
import { constants as constants11, closeSync as closeSync14, fstatSync as fstatSync14, lstatSync as lstatSync20, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync2, openSync as openSync14, readFileSync as readFileSync18, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "fs";
|
|
53989
54070
|
function stat2(path) {
|
|
53990
54071
|
try {
|
|
53991
|
-
return
|
|
54072
|
+
return lstatSync20(path);
|
|
53992
54073
|
} catch (error61) {
|
|
53993
54074
|
if (error61.code === "ENOENT")
|
|
53994
54075
|
return null;
|
|
@@ -54217,8 +54298,8 @@ var init_recurring_customer = __esm(() => {
|
|
|
54217
54298
|
});
|
|
54218
54299
|
|
|
54219
54300
|
// src/lib/recurring-recovery.ts
|
|
54220
|
-
import { constants as constants12, closeSync as closeSync15, fsyncSync as fsyncSync4, fstatSync as fstatSync15, lstatSync as
|
|
54221
|
-
import { dirname as dirname19, isAbsolute as isAbsolute15, join as
|
|
54301
|
+
import { constants as constants12, closeSync as closeSync15, fsyncSync as fsyncSync4, fstatSync as fstatSync15, lstatSync as lstatSync21, mkdirSync as mkdirSync10, openSync as openSync15, readSync as readSync10, realpathSync as realpathSync8, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
|
|
54302
|
+
import { dirname as dirname19, isAbsolute as isAbsolute15, join as join30, resolve as resolve18 } from "path";
|
|
54222
54303
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
54223
54304
|
|
|
54224
54305
|
class RecoveryOwner {
|
|
@@ -54226,10 +54307,10 @@ class RecoveryOwner {
|
|
|
54226
54307
|
parents = [];
|
|
54227
54308
|
constructor(directory) {
|
|
54228
54309
|
this.directory = directory;
|
|
54229
|
-
if (!isAbsolute15(directory) ||
|
|
54310
|
+
if (!isAbsolute15(directory) || resolve18(directory) !== directory || realpathSync8(directory) !== directory)
|
|
54230
54311
|
invalid5();
|
|
54231
54312
|
for (let path = directory;; path = dirname19(path)) {
|
|
54232
|
-
const stat3 =
|
|
54313
|
+
const stat3 = lstatSync21(path);
|
|
54233
54314
|
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
54234
54315
|
invalid5();
|
|
54235
54316
|
this.parents.push({ path, dev: stat3.dev, ino: stat3.ino });
|
|
@@ -54239,20 +54320,20 @@ class RecoveryOwner {
|
|
|
54239
54320
|
this.assert();
|
|
54240
54321
|
}
|
|
54241
54322
|
assert() {
|
|
54242
|
-
if (
|
|
54323
|
+
if (realpathSync8(this.directory) !== this.directory)
|
|
54243
54324
|
invalid5();
|
|
54244
54325
|
for (const prior of this.parents) {
|
|
54245
|
-
const now =
|
|
54326
|
+
const now = lstatSync21(prior.path);
|
|
54246
54327
|
if (!now.isDirectory() || now.isSymbolicLink() || now.dev !== prior.dev || now.ino !== prior.ino)
|
|
54247
54328
|
invalid5();
|
|
54248
54329
|
}
|
|
54249
|
-
const own2 =
|
|
54330
|
+
const own2 = lstatSync21(this.directory);
|
|
54250
54331
|
if ((own2.mode & 511) !== 448 || (own2.mode & 3584) !== 0 || process.getuid && own2.uid !== process.getuid())
|
|
54251
54332
|
invalid5();
|
|
54252
54333
|
}
|
|
54253
54334
|
read(name) {
|
|
54254
54335
|
this.assert();
|
|
54255
|
-
const fd = openSync15(
|
|
54336
|
+
const fd = openSync15(join30(this.directory, name), constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
|
|
54256
54337
|
try {
|
|
54257
54338
|
const before = fstatSync15(fd);
|
|
54258
54339
|
if (!before.isFile() || before.nlink !== 1 || (before.mode & 4095) !== 384 || before.size < 1 || before.size > 8192 || process.getuid && before.uid !== process.getuid())
|
|
@@ -54265,7 +54346,7 @@ class RecoveryOwner {
|
|
|
54265
54346
|
break;
|
|
54266
54347
|
size += n2;
|
|
54267
54348
|
}
|
|
54268
|
-
const after = fstatSync15(fd), path =
|
|
54349
|
+
const after = fstatSync15(fd), path = lstatSync21(join30(this.directory, name));
|
|
54269
54350
|
if (size !== before.size || after.size !== before.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs || path.dev !== before.dev || path.ino !== before.ino || !path.isFile() || path.isSymbolicLink())
|
|
54270
54351
|
invalid5();
|
|
54271
54352
|
this.assert();
|
|
@@ -54278,7 +54359,7 @@ class RecoveryOwner {
|
|
|
54278
54359
|
this.assert();
|
|
54279
54360
|
const bytes = canonicalJson2(value, 8192) + `
|
|
54280
54361
|
`;
|
|
54281
|
-
const fd = openSync15(
|
|
54362
|
+
const fd = openSync15(join30(this.directory, name), constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW, 384);
|
|
54282
54363
|
try {
|
|
54283
54364
|
writeFileSync9(fd, bytes);
|
|
54284
54365
|
fsyncSync4(fd);
|
|
@@ -54305,14 +54386,14 @@ class RecoveryOwner {
|
|
|
54305
54386
|
if (this.read("state.json") !== expected)
|
|
54306
54387
|
invalid5();
|
|
54307
54388
|
this.assert();
|
|
54308
|
-
renameSync6(
|
|
54389
|
+
renameSync6(join30(this.directory, name), join30(this.directory, "state.json"));
|
|
54309
54390
|
this.sync();
|
|
54310
54391
|
}
|
|
54311
54392
|
async locked(action) {
|
|
54312
54393
|
this.assert();
|
|
54313
54394
|
let fd;
|
|
54314
54395
|
try {
|
|
54315
|
-
fd = openSync15(
|
|
54396
|
+
fd = openSync15(join30(this.directory, "operation.lock"), constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW, 384);
|
|
54316
54397
|
} catch {
|
|
54317
54398
|
throw new RecurringCustomerError("RECURRING_RECOVERY_BUSY", "Recovery is locked. Confirm the original process has stopped before explicitly reconciling the retained lock; no request was retried.");
|
|
54318
54399
|
}
|
|
@@ -54325,10 +54406,10 @@ class RecoveryOwner {
|
|
|
54325
54406
|
} finally {
|
|
54326
54407
|
closeSync15(fd);
|
|
54327
54408
|
this.assert();
|
|
54328
|
-
const now =
|
|
54409
|
+
const now = lstatSync21(join30(this.directory, "operation.lock"));
|
|
54329
54410
|
if (owner2.dev !== now.dev || owner2.ino !== now.ino || !now.isFile() || now.isSymbolicLink())
|
|
54330
54411
|
invalid5();
|
|
54331
|
-
unlinkSync5(
|
|
54412
|
+
unlinkSync5(join30(this.directory, "operation.lock"));
|
|
54332
54413
|
this.sync();
|
|
54333
54414
|
}
|
|
54334
54415
|
}
|
|
@@ -54361,7 +54442,7 @@ function base(customer, organizationId) {
|
|
|
54361
54442
|
};
|
|
54362
54443
|
}
|
|
54363
54444
|
function create(directory, intent) {
|
|
54364
|
-
if (!isAbsolute15(directory) ||
|
|
54445
|
+
if (!isAbsolute15(directory) || resolve18(directory) !== directory || realpathSync8(dirname19(directory)) !== dirname19(directory))
|
|
54365
54446
|
invalid5();
|
|
54366
54447
|
mkdirSync10(directory, { mode: 448 });
|
|
54367
54448
|
const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
|
|
@@ -56459,20 +56540,20 @@ var init_credential_state = __esm(() => {
|
|
|
56459
56540
|
|
|
56460
56541
|
// src/lib/run-state.ts
|
|
56461
56542
|
import { createHash as createHash19, randomBytes } from "crypto";
|
|
56462
|
-
import { existsSync as
|
|
56463
|
-
import { extname, join as
|
|
56543
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync19, readdirSync as readdirSync10, statSync as statSync9, writeFileSync as writeFileSync10 } from "fs";
|
|
56544
|
+
import { extname, join as join31, relative as relative6 } from "path";
|
|
56464
56545
|
function createSkillRun(params, targetDir = process.cwd()) {
|
|
56465
56546
|
const now = new Date;
|
|
56466
56547
|
const id = createRunId(now);
|
|
56467
56548
|
const day = now.toISOString().slice(0, 10);
|
|
56468
56549
|
const skillName = normalizeSkillName(params.skill);
|
|
56469
56550
|
const root = getProjectStateDir(targetDir);
|
|
56470
|
-
const runDir =
|
|
56471
|
-
const logsDir =
|
|
56472
|
-
const exportDir =
|
|
56551
|
+
const runDir = join31(root, "runs", day, id);
|
|
56552
|
+
const logsDir = join31(runDir, "logs");
|
|
56553
|
+
const exportDir = join31(root, "exports", skillName, id);
|
|
56473
56554
|
mkdirSync11(logsDir, { recursive: true });
|
|
56474
56555
|
mkdirSync11(exportDir, { recursive: true });
|
|
56475
|
-
mkdirSync11(
|
|
56556
|
+
mkdirSync11(join31(root, "tmp"), { recursive: true });
|
|
56476
56557
|
const record11 = {
|
|
56477
56558
|
id,
|
|
56478
56559
|
skill: skillName,
|
|
@@ -56524,22 +56605,22 @@ function updateSkillRun(context2, patch) {
|
|
|
56524
56605
|
return context2.record;
|
|
56525
56606
|
}
|
|
56526
56607
|
function writeRunLogs(context2, stdout = "", stderr = "") {
|
|
56527
|
-
writeFileSync10(
|
|
56528
|
-
writeFileSync10(
|
|
56608
|
+
writeFileSync10(join31(context2.logsDir, "stdout.log"), stdout);
|
|
56609
|
+
writeFileSync10(join31(context2.logsDir, "stderr.log"), stderr);
|
|
56529
56610
|
}
|
|
56530
56611
|
function appendRunEvent(context2, event, data = {}) {
|
|
56531
56612
|
const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
|
|
56532
56613
|
`;
|
|
56533
|
-
const path =
|
|
56534
|
-
const previous =
|
|
56614
|
+
const path = join31(context2.runDir, "events.ndjson");
|
|
56615
|
+
const previous = existsSync15(path) ? readFileSync19(path, "utf-8") : "";
|
|
56535
56616
|
writeFileSync10(path, previous + line);
|
|
56536
56617
|
}
|
|
56537
56618
|
function findSkillRun(runId, targetDir = process.cwd()) {
|
|
56538
|
-
const runsRoot =
|
|
56539
|
-
if (!
|
|
56619
|
+
const runsRoot = join31(getProjectStateDir(targetDir), "runs");
|
|
56620
|
+
if (!existsSync15(runsRoot))
|
|
56540
56621
|
return null;
|
|
56541
56622
|
for (const day of readdirSync10(runsRoot)) {
|
|
56542
|
-
const record11 = readRunRecord(
|
|
56623
|
+
const record11 = readRunRecord(join31(runsRoot, day, runId));
|
|
56543
56624
|
if (record11)
|
|
56544
56625
|
return record11;
|
|
56545
56626
|
}
|
|
@@ -56556,15 +56637,15 @@ function skillRunEnv(context2) {
|
|
|
56556
56637
|
};
|
|
56557
56638
|
}
|
|
56558
56639
|
function writeRunRecord(context2) {
|
|
56559
|
-
writeFileSync10(
|
|
56640
|
+
writeFileSync10(join31(context2.runDir, "run.json"), JSON.stringify(context2.record, null, 2) + `
|
|
56560
56641
|
`);
|
|
56561
56642
|
}
|
|
56562
56643
|
function writeArtifactsManifest(context2, artifacts) {
|
|
56563
|
-
writeFileSync10(
|
|
56644
|
+
writeFileSync10(join31(context2.runDir, "artifacts.json"), JSON.stringify({ runId: context2.record.id, artifacts }, null, 2) + `
|
|
56564
56645
|
`);
|
|
56565
56646
|
}
|
|
56566
56647
|
function collectRunArtifacts(context2) {
|
|
56567
|
-
if (!
|
|
56648
|
+
if (!existsSync15(context2.exportDir))
|
|
56568
56649
|
return [];
|
|
56569
56650
|
const artifacts = [];
|
|
56570
56651
|
for (const path of walkFiles(context2.exportDir)) {
|
|
@@ -56580,8 +56661,8 @@ function collectRunArtifacts(context2) {
|
|
|
56580
56661
|
return artifacts.sort((a, b) => a.path.localeCompare(b.path));
|
|
56581
56662
|
}
|
|
56582
56663
|
function readRunRecord(runDir) {
|
|
56583
|
-
const path =
|
|
56584
|
-
if (!
|
|
56664
|
+
const path = join31(runDir, "run.json");
|
|
56665
|
+
if (!existsSync15(path))
|
|
56585
56666
|
return null;
|
|
56586
56667
|
try {
|
|
56587
56668
|
return JSON.parse(readFileSync19(path, "utf-8"));
|
|
@@ -56592,7 +56673,7 @@ function readRunRecord(runDir) {
|
|
|
56592
56673
|
function walkFiles(dir) {
|
|
56593
56674
|
const files = [];
|
|
56594
56675
|
for (const entry of readdirSync10(dir)) {
|
|
56595
|
-
const full =
|
|
56676
|
+
const full = join31(dir, entry);
|
|
56596
56677
|
if (statSync9(full).isDirectory())
|
|
56597
56678
|
files.push(...walkFiles(full));
|
|
56598
56679
|
else
|
|
@@ -56849,7 +56930,7 @@ import { closeSync as closeSync16, fstatSync as fstatSync16, openSync as openSyn
|
|
|
56849
56930
|
import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
|
|
56850
56931
|
import { createRequire as createRequire2 } from "module";
|
|
56851
56932
|
import { hostname as osHostname2 } from "os";
|
|
56852
|
-
import { isAbsolute as isAbsolute17, join as
|
|
56933
|
+
import { isAbsolute as isAbsolute17, join as join32 } from "path";
|
|
56853
56934
|
import { createRequire as createRequire22 } from "module";
|
|
56854
56935
|
function envToken2(name) {
|
|
56855
56936
|
return name.toUpperCase().replace(/-/g, "_");
|
|
@@ -56880,14 +56961,14 @@ function hasnaHomeDir2(env) {
|
|
|
56880
56961
|
if (override)
|
|
56881
56962
|
return override;
|
|
56882
56963
|
const home = homeDir2(env);
|
|
56883
|
-
return home ?
|
|
56964
|
+
return home ? join32(home, HASNA_HOME_DIR2) : null;
|
|
56884
56965
|
}
|
|
56885
56966
|
function appConfigDir2(name, env) {
|
|
56886
56967
|
const configRoot = absoluteOverride2(env, HASNA_CONFIG_HOME_ENV_KEY2);
|
|
56887
56968
|
if (configRoot)
|
|
56888
|
-
return
|
|
56969
|
+
return join32(configRoot, name);
|
|
56889
56970
|
const root = hasnaHomeDir2(env);
|
|
56890
|
-
return root ?
|
|
56971
|
+
return root ? join32(root, name, CONFIG_SUBDIR2) : null;
|
|
56891
56972
|
}
|
|
56892
56973
|
function credentialDiskSourceList2(name, env, profile = null) {
|
|
56893
56974
|
if (!SAFE_APP_SLUG2.test(name))
|
|
@@ -56896,7 +56977,7 @@ function credentialDiskSourceList2(name, env, profile = null) {
|
|
|
56896
56977
|
if (!directory2)
|
|
56897
56978
|
return [];
|
|
56898
56979
|
const file2 = profile ? `${CREDENTIALS_FILE2}-${profile}` : CREDENTIALS_FILE2;
|
|
56899
|
-
return [{ path:
|
|
56980
|
+
return [{ path: join32(directory2, file2), tier: "disk" }];
|
|
56900
56981
|
}
|
|
56901
56982
|
function credentialDiskSources2(name, env) {
|
|
56902
56983
|
return credentialDiskSourceList2(name, env, null).map((s) => s.path);
|
|
@@ -58010,7 +58091,7 @@ function createSecretsClientFromEnv(env = process.env, overrides = {}) {
|
|
|
58010
58091
|
});
|
|
58011
58092
|
return new SecretsClient({ ...clientOverrides, baseUrl, apiKey });
|
|
58012
58093
|
}
|
|
58013
|
-
var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), CREDENTIAL_PROFILE_ENV_KEY2 = "HASNA_PROFILE", CredentialResolutionError2, CredentialFileUnsafeError2, HASNA_HOME_ENV_KEY2 = "HASNA_HOME", HASNA_CONFIG_HOME_ENV_KEY2 = "HASNA_CONFIG_HOME", KEYCHAIN_STATION_ENV_KEY2 = "HASNA_STATION", HASNA_HOME_DIR2 = ".hasna", CONFIG_SUBDIR2 = "config", CREDENTIALS_FILE2 = "credentials", KEYCHAIN_SECURITY_BIN2 = "/usr/bin/security", KEYCHAIN_SERVICE_PREFIX2 = "hasna.credentials", KEYCHAIN_ITEM_NOT_FOUND_STATUS2 = 44, KEYCHAIN_SPAWN_TIMEOUT_MS2 = 1e4, MAX_CREDENTIAL_FILE_BYTES2, SAFE_APP_SLUG2, SAFE_PROFILE2, ILLEGAL_IN_HEADER_VALUE2, VAULT_POINTER_SHAPE2, CREDENTIAL_SHAPED_KEY2, INSPECT_CUSTOM2, CREDENTIAL_SEAL2, CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE = "caller-supplied CredentialProvider", AMBIENT_ENVIRONMENT2, SECRETS_PACKAGE_SPECIFIER, requireSecretsSdk2, DEFAULT_FLEET_GATEWAY_ORIGIN2 = "https://api.hasna.com", DEFAULT_AUTHORITY_SOURCE = "default", ASCII_CONTROL_PATTERN2, DNS_LABEL_PATTERN2, ClientTransportConfigurationError2, HasnaHttpError, DEFAULT_RETRY_STATUSES, IDEMPOTENT_METHODS2, AUTHORITY_OVERRIDE_HEADERS2, defaultSleep = (ms) => new Promise((
|
|
58094
|
+
var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), CREDENTIAL_PROFILE_ENV_KEY2 = "HASNA_PROFILE", CredentialResolutionError2, CredentialFileUnsafeError2, HASNA_HOME_ENV_KEY2 = "HASNA_HOME", HASNA_CONFIG_HOME_ENV_KEY2 = "HASNA_CONFIG_HOME", KEYCHAIN_STATION_ENV_KEY2 = "HASNA_STATION", HASNA_HOME_DIR2 = ".hasna", CONFIG_SUBDIR2 = "config", CREDENTIALS_FILE2 = "credentials", KEYCHAIN_SECURITY_BIN2 = "/usr/bin/security", KEYCHAIN_SERVICE_PREFIX2 = "hasna.credentials", KEYCHAIN_ITEM_NOT_FOUND_STATUS2 = 44, KEYCHAIN_SPAWN_TIMEOUT_MS2 = 1e4, MAX_CREDENTIAL_FILE_BYTES2, SAFE_APP_SLUG2, SAFE_PROFILE2, ILLEGAL_IN_HEADER_VALUE2, VAULT_POINTER_SHAPE2, CREDENTIAL_SHAPED_KEY2, INSPECT_CUSTOM2, CREDENTIAL_SEAL2, CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE = "caller-supplied CredentialProvider", AMBIENT_ENVIRONMENT2, SECRETS_PACKAGE_SPECIFIER, requireSecretsSdk2, DEFAULT_FLEET_GATEWAY_ORIGIN2 = "https://api.hasna.com", DEFAULT_AUTHORITY_SOURCE = "default", ASCII_CONTROL_PATTERN2, DNS_LABEL_PATTERN2, ClientTransportConfigurationError2, HasnaHttpError, DEFAULT_RETRY_STATUSES, IDEMPOTENT_METHODS2, AUTHORITY_OVERRIDE_HEADERS2, defaultSleep = (ms) => new Promise((resolve19) => setTimeout(resolve19, ms)), init_transport2, MAX_CREDENTIAL_FILE_BYTES22, INSPECT_CUSTOM22, CREDENTIAL_SEAL22, AMBIENT_ENVIRONMENT22, SECRETS_PACKAGE_SPECIFIER2, requireSecretsSdk22, IDEMPOTENT_METHODS22, AUTHORITY_OVERRIDE_HEADERS22, init_storage, PATHS_RESOLVER_APP_SLUG_RE2, SQLITE_SIDECAR_FILES, LEGACY_SERVICE_FILES, init_data_dir, SecretsTestIsolationError, TEST_ENTRYPOINT_RE, init_test_isolation, init_client, ApiError;
|
|
58014
58095
|
var init_sdk = __esm(() => {
|
|
58015
58096
|
init_transport2 = __esm2(() => {
|
|
58016
58097
|
CredentialResolutionError2 = class CredentialResolutionError3 extends Error {
|
|
@@ -58145,7 +58226,7 @@ var init_sdk = __esm(() => {
|
|
|
58145
58226
|
});
|
|
58146
58227
|
|
|
58147
58228
|
// src/lib/execution-secrets.ts
|
|
58148
|
-
import { constants as constants13, closeSync as closeSync17, fstatSync as fstatSync17, openSync as openSync17, readSync as readSync11, realpathSync as
|
|
58229
|
+
import { constants as constants13, closeSync as closeSync17, fstatSync as fstatSync17, openSync as openSync17, readSync as readSync11, realpathSync as realpathSync9 } from "fs";
|
|
58149
58230
|
import { hostname as stationHostname } from "os";
|
|
58150
58231
|
function selectedSecretBindingsTemplate(scope, names, createClient = createSecretsClientFromEnv) {
|
|
58151
58232
|
let secretsAuthority;
|
|
@@ -58158,7 +58239,7 @@ function selectedSecretBindingsTemplate(scope, names, createClient = createSecre
|
|
|
58158
58239
|
return {
|
|
58159
58240
|
schema: "hasna.skills-secret-bindings.v1",
|
|
58160
58241
|
selection: { authority, workspaceId, profileId: scope.profileId, profileRevision, slug: slug2, version: version2, bundleDigest },
|
|
58161
|
-
consumer: { stationId: process.env.HASNA_STATION || stationHostname(), workspaceDirectory:
|
|
58242
|
+
consumer: { stationId: process.env.HASNA_STATION || stationHostname(), workspaceDirectory: realpathSync9(scope.cwd) },
|
|
58162
58243
|
secretsAuthority,
|
|
58163
58244
|
bindings: Object.fromEntries(names.map((name) => [name, ""]))
|
|
58164
58245
|
};
|
|
@@ -58196,7 +58277,7 @@ function validateSelectedSecretBindings(value, scope, names) {
|
|
|
58196
58277
|
}
|
|
58197
58278
|
let workspaceDirectory;
|
|
58198
58279
|
try {
|
|
58199
|
-
workspaceDirectory =
|
|
58280
|
+
workspaceDirectory = realpathSync9(scope.cwd);
|
|
58200
58281
|
} catch {
|
|
58201
58282
|
return refuse2("SECRET_BINDING_CONSUMER_MISMATCH", "The execution workspace cannot be resolved.");
|
|
58202
58283
|
}
|
|
@@ -58389,8 +58470,8 @@ __export(exports_selected_run, {
|
|
|
58389
58470
|
});
|
|
58390
58471
|
import { createHash as createHash20 } from "crypto";
|
|
58391
58472
|
import { spawn } from "child_process";
|
|
58392
|
-
import { mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync11, realpathSync as
|
|
58393
|
-
import { dirname as dirname20, join as
|
|
58473
|
+
import { mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync11, realpathSync as realpathSync10 } from "fs";
|
|
58474
|
+
import { dirname as dirname20, join as join33, resolve as resolve19 } from "path";
|
|
58394
58475
|
import { tmpdir, hostname as stationHostname2 } from "os";
|
|
58395
58476
|
async function resolveSelectedRun(spec, profileId, options = {}) {
|
|
58396
58477
|
const context2 = await resolveSelectionContext(profileId, options);
|
|
@@ -58470,7 +58551,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
58470
58551
|
throw new SkillSelectionError("INVALID_SECRET_BINDINGS", "Explicit environment values must be bounded strings without NUL bytes.");
|
|
58471
58552
|
secretEnv[name] = value;
|
|
58472
58553
|
}
|
|
58473
|
-
const runDirectory = mkdtempSync3(
|
|
58554
|
+
const runDirectory = mkdtempSync3(join33(tmpdir(), "skills-execution-"));
|
|
58474
58555
|
const paths = new SkillEntryPaths;
|
|
58475
58556
|
for (const entry of entries) {
|
|
58476
58557
|
paths.add(entry.path, 100, () => {
|
|
@@ -58478,12 +58559,12 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
58478
58559
|
}, () => {
|
|
58479
58560
|
throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
|
|
58480
58561
|
});
|
|
58481
|
-
const destination =
|
|
58562
|
+
const destination = join33(runDirectory, entry.path);
|
|
58482
58563
|
mkdirSync12(dirname20(destination), { recursive: true, mode: 448 });
|
|
58483
58564
|
writeFileSync11(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
|
|
58484
58565
|
}
|
|
58485
58566
|
env.SKILLS_INPUT_JSON = input2;
|
|
58486
|
-
env.SKILLS_WORKSPACE_DIR =
|
|
58567
|
+
env.SKILLS_WORKSPACE_DIR = resolve19(options.cwd ?? process.cwd());
|
|
58487
58568
|
env.SKILLS_RUN_DIR = runDirectory;
|
|
58488
58569
|
if (runtime.version) {
|
|
58489
58570
|
const version2 = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], "--version"], runDirectory, env, "", Math.min(timeoutMs, 5000));
|
|
@@ -58496,7 +58577,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
58496
58577
|
const { authority: authority2, workspaceId, profileRevision, slug: slug2, version: version2, bundleDigest } = selection2;
|
|
58497
58578
|
const request2 = {
|
|
58498
58579
|
selection: { authority: authority2, workspaceId, profileId, profileRevision, slug: slug2, version: version2, bundleDigest },
|
|
58499
|
-
consumer: { stationId: process.env.HASNA_STATION || stationHostname2(), workspaceDirectory:
|
|
58580
|
+
consumer: { stationId: process.env.HASNA_STATION || stationHostname2(), workspaceDirectory: realpathSync10(options.cwd ?? process.cwd()) }
|
|
58500
58581
|
};
|
|
58501
58582
|
const grant = await (options.resolveExecutionGrant ?? resolveExecutionGrant)(request2);
|
|
58502
58583
|
if (!grant || !grantIdentifier(grant.policyRevision) || !grantIdentifier(grant.grantId))
|
|
@@ -58506,7 +58587,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
58506
58587
|
}
|
|
58507
58588
|
if (bindings)
|
|
58508
58589
|
secretEnv = await resolveSelectedSecrets(bindings, options.createSecretsClient);
|
|
58509
|
-
const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [],
|
|
58590
|
+
const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], join33(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input2, timeoutMs);
|
|
58510
58591
|
result.stdout = redactExecutionSecrets(result.stdout, secretEnv);
|
|
58511
58592
|
result.stderr = redactExecutionSecrets(result.stderr, secretEnv);
|
|
58512
58593
|
const receipt = {
|
|
@@ -58519,7 +58600,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
58519
58600
|
...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
|
|
58520
58601
|
...result
|
|
58521
58602
|
};
|
|
58522
|
-
writeFileSync11(
|
|
58603
|
+
writeFileSync11(join33(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
|
|
58523
58604
|
return receipt;
|
|
58524
58605
|
}
|
|
58525
58606
|
async function subprocess(command, cwd, env, input2, timeoutMs) {
|
|
@@ -58708,8 +58789,8 @@ var init_blog_article = __esm(() => {
|
|
|
58708
58789
|
});
|
|
58709
58790
|
|
|
58710
58791
|
// src/mcp/operation-tools.ts
|
|
58711
|
-
import { existsSync as
|
|
58712
|
-
import { join as
|
|
58792
|
+
import { existsSync as existsSync16, readdirSync as readdirSync11, statSync as statSync10 } from "fs";
|
|
58793
|
+
import { join as join34 } from "path";
|
|
58713
58794
|
function registerOperationTools(server) {
|
|
58714
58795
|
server.registerTool("cloud_skill_eligibility", {
|
|
58715
58796
|
title: "Cloud Skill Eligibility",
|
|
@@ -59181,12 +59262,12 @@ function registerOperationTools(server) {
|
|
|
59181
59262
|
const agents = [];
|
|
59182
59263
|
for (const agent of AGENT_TARGETS) {
|
|
59183
59264
|
const agentSkillsPath = getAgentSkillsDir(agent, "global");
|
|
59184
|
-
const exists =
|
|
59265
|
+
const exists = existsSync16(agentSkillsPath);
|
|
59185
59266
|
let skillCount = 0;
|
|
59186
59267
|
if (exists) {
|
|
59187
59268
|
try {
|
|
59188
59269
|
skillCount = readdirSync11(agentSkillsPath).filter((f) => {
|
|
59189
|
-
const full =
|
|
59270
|
+
const full = join34(agentSkillsPath, f);
|
|
59190
59271
|
return !f.startsWith(".") && statSync10(full).isDirectory();
|
|
59191
59272
|
}).length;
|
|
59192
59273
|
} catch {}
|
|
@@ -59253,16 +59334,16 @@ var init_operation_tools = __esm(() => {
|
|
|
59253
59334
|
});
|
|
59254
59335
|
|
|
59255
59336
|
// src/lib/feedback.ts
|
|
59256
|
-
import { appendFileSync, existsSync as
|
|
59257
|
-
import { dirname as dirname21, join as
|
|
59337
|
+
import { appendFileSync, existsSync as existsSync17, mkdirSync as mkdirSync13 } from "fs";
|
|
59338
|
+
import { dirname as dirname21, join as join35 } from "path";
|
|
59258
59339
|
import { Database } from "bun:sqlite";
|
|
59259
59340
|
function getFeedbackDbPath() {
|
|
59260
|
-
return
|
|
59341
|
+
return join35(getDataDir(), "skills.db");
|
|
59261
59342
|
}
|
|
59262
59343
|
function getFeedbackDb() {
|
|
59263
59344
|
const dbPath = getFeedbackDbPath();
|
|
59264
59345
|
const dir = dirname21(dbPath);
|
|
59265
|
-
if (!
|
|
59346
|
+
if (!existsSync17(dir))
|
|
59266
59347
|
mkdirSync13(dir, { recursive: true });
|
|
59267
59348
|
const db = new Database(dbPath);
|
|
59268
59349
|
db.exec("PRAGMA journal_mode = WAL");
|
|
@@ -59289,9 +59370,9 @@ function saveFeedback(input2) {
|
|
|
59289
59370
|
throw new Error("Feedback message is required");
|
|
59290
59371
|
const category = input2.category ?? "general";
|
|
59291
59372
|
if (isApiMode()) {
|
|
59292
|
-
const path =
|
|
59373
|
+
const path = join35(getDataDir(), "feedback.jsonl");
|
|
59293
59374
|
const dir = dirname21(path);
|
|
59294
|
-
if (!
|
|
59375
|
+
if (!existsSync17(dir))
|
|
59295
59376
|
mkdirSync13(dir, { recursive: true });
|
|
59296
59377
|
appendFileSync(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
|
|
59297
59378
|
`);
|
|
@@ -59453,14 +59534,14 @@ var init_resource_meta_tools = __esm(() => {
|
|
|
59453
59534
|
});
|
|
59454
59535
|
|
|
59455
59536
|
// src/lib/scheduler.ts
|
|
59456
|
-
import { existsSync as
|
|
59457
|
-
import { join as
|
|
59537
|
+
import { existsSync as existsSync18, readFileSync as readFileSync21, writeFileSync as writeFileSync12, mkdirSync as mkdirSync14 } from "fs";
|
|
59538
|
+
import { join as join36 } from "path";
|
|
59458
59539
|
function getSchedulesPath(targetDir = process.cwd()) {
|
|
59459
|
-
return
|
|
59540
|
+
return join36(targetDir, ".skills", "schedules.json");
|
|
59460
59541
|
}
|
|
59461
59542
|
function loadSchedules(targetDir = process.cwd()) {
|
|
59462
59543
|
const path = getSchedulesPath(targetDir);
|
|
59463
|
-
if (
|
|
59544
|
+
if (existsSync18(path)) {
|
|
59464
59545
|
try {
|
|
59465
59546
|
return JSON.parse(readFileSync21(path, "utf-8"));
|
|
59466
59547
|
} catch {}
|
|
@@ -59469,8 +59550,8 @@ function loadSchedules(targetDir = process.cwd()) {
|
|
|
59469
59550
|
}
|
|
59470
59551
|
function saveSchedules(data, targetDir = process.cwd()) {
|
|
59471
59552
|
const path = getSchedulesPath(targetDir);
|
|
59472
|
-
const dir =
|
|
59473
|
-
if (!
|
|
59553
|
+
const dir = join36(targetDir, ".skills");
|
|
59554
|
+
if (!existsSync18(dir))
|
|
59474
59555
|
mkdirSync14(dir, { recursive: true });
|
|
59475
59556
|
writeFileSync12(path, JSON.stringify(data, null, 2));
|
|
59476
59557
|
}
|
|
@@ -59743,14 +59824,14 @@ var init_schedule_tools = __esm(() => {
|
|
|
59743
59824
|
// src/lib/native-storage.ts
|
|
59744
59825
|
import { createHash as createHash21, createHmac } from "crypto";
|
|
59745
59826
|
import {
|
|
59746
|
-
existsSync as
|
|
59827
|
+
existsSync as existsSync19,
|
|
59747
59828
|
mkdirSync as mkdirSync15,
|
|
59748
59829
|
readFileSync as readFileSync22,
|
|
59749
59830
|
readdirSync as readdirSync12,
|
|
59750
59831
|
statSync as statSync11,
|
|
59751
59832
|
writeFileSync as writeFileSync13
|
|
59752
59833
|
} from "fs";
|
|
59753
|
-
import { dirname as dirname22, join as
|
|
59834
|
+
import { dirname as dirname22, join as join37, normalize as normalize4, relative as relative7, sep as sep8 } from "path";
|
|
59754
59835
|
function resolveSkillsNativeStorageConfig(env = process.env) {
|
|
59755
59836
|
assertNoRetiredModeEnvVars(env, {
|
|
59756
59837
|
app: SKILLS_ENV_NAMESPACE,
|
|
@@ -59791,7 +59872,7 @@ function getSkillsNativeStorageStatus(options = {}) {
|
|
|
59791
59872
|
local: {
|
|
59792
59873
|
dataDir: getDataDir(),
|
|
59793
59874
|
projectStateDir: getProjectStateDir(targetDir),
|
|
59794
|
-
feedbackDbPath:
|
|
59875
|
+
feedbackDbPath: join37(getDataDir(), "skills.db")
|
|
59795
59876
|
},
|
|
59796
59877
|
remote: {
|
|
59797
59878
|
databaseConfigured: Boolean(config2.databaseUrl),
|
|
@@ -59811,7 +59892,7 @@ function getStorageStatus(options = {}) {
|
|
|
59811
59892
|
function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
|
|
59812
59893
|
const projectStateDir = getProjectStateDir(targetDir);
|
|
59813
59894
|
const files = [];
|
|
59814
|
-
if (
|
|
59895
|
+
if (existsSync19(projectStateDir)) {
|
|
59815
59896
|
for (const filePath of walkFiles2(projectStateDir)) {
|
|
59816
59897
|
const bytes = readFileSync22(filePath);
|
|
59817
59898
|
const relativePath = toPosix(relative7(targetDir, filePath));
|
|
@@ -59872,7 +59953,7 @@ function parsePositiveInteger(value) {
|
|
|
59872
59953
|
function walkFiles2(dir) {
|
|
59873
59954
|
const files = [];
|
|
59874
59955
|
for (const entry of readdirSync12(dir)) {
|
|
59875
|
-
const full =
|
|
59956
|
+
const full = join37(dir, entry);
|
|
59876
59957
|
const stats = statSync11(full);
|
|
59877
59958
|
if (stats.isDirectory())
|
|
59878
59959
|
files.push(...walkFiles2(full));
|
|
@@ -60110,20 +60191,20 @@ var init_private_publication_customer = __esm(() => {
|
|
|
60110
60191
|
});
|
|
60111
60192
|
|
|
60112
60193
|
// src/lib/private-publication-recovery.ts
|
|
60113
|
-
import { constants as constants14, closeSync as closeSync18, fsyncSync as fsyncSync5, fstatSync as fstatSync18, lstatSync as
|
|
60114
|
-
import { dirname as dirname23, isAbsolute as isAbsolute18, join as
|
|
60194
|
+
import { constants as constants14, closeSync as closeSync18, fsyncSync as fsyncSync5, fstatSync as fstatSync18, lstatSync as lstatSync22, mkdirSync as mkdirSync16, openSync as openSync18, readSync as readSync12, realpathSync as realpathSync11, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync14 } from "fs";
|
|
60195
|
+
import { dirname as dirname23, isAbsolute as isAbsolute18, join as join38, resolve as resolve20 } from "path";
|
|
60115
60196
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
60116
60197
|
function safeDirectory(directory2) {
|
|
60117
|
-
if (!isAbsolute18(directory2) || directory2 !==
|
|
60198
|
+
if (!isAbsolute18(directory2) || directory2 !== resolve20(directory2) || realpathSync11(directory2) !== directory2)
|
|
60118
60199
|
return fail2();
|
|
60119
60200
|
for (let path = directory2;; path = dirname23(path)) {
|
|
60120
|
-
const stat3 =
|
|
60201
|
+
const stat3 = lstatSync22(path);
|
|
60121
60202
|
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
60122
60203
|
return fail2();
|
|
60123
60204
|
if (path === dirname23(path))
|
|
60124
60205
|
break;
|
|
60125
60206
|
}
|
|
60126
|
-
const own2 =
|
|
60207
|
+
const own2 = lstatSync22(directory2);
|
|
60127
60208
|
if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
|
|
60128
60209
|
return fail2();
|
|
60129
60210
|
return { dev: own2.dev, ino: own2.ino };
|
|
@@ -60134,7 +60215,7 @@ function unchangedDirectory(directory2, identity3) {
|
|
|
60134
60215
|
return fail2();
|
|
60135
60216
|
}
|
|
60136
60217
|
function readOwned(directory2, name, max) {
|
|
60137
|
-
const identity3 = safeDirectory(directory2), file2 =
|
|
60218
|
+
const identity3 = safeDirectory(directory2), file2 = join38(directory2, name);
|
|
60138
60219
|
const fd = openSync18(file2, constants14.O_RDONLY | constants14.O_NOFOLLOW);
|
|
60139
60220
|
try {
|
|
60140
60221
|
const stat3 = fstatSync18(fd);
|
|
@@ -60158,7 +60239,7 @@ function readOwned(directory2, name, max) {
|
|
|
60158
60239
|
}
|
|
60159
60240
|
}
|
|
60160
60241
|
function writeOwned(directory2, name, bytes) {
|
|
60161
|
-
const fd = openSync18(
|
|
60242
|
+
const fd = openSync18(join38(directory2, name), constants14.O_WRONLY | constants14.O_CREAT | constants14.O_EXCL | constants14.O_NOFOLLOW, 384);
|
|
60162
60243
|
try {
|
|
60163
60244
|
writeFileSync14(fd, bytes);
|
|
60164
60245
|
fsyncSync5(fd);
|
|
@@ -60171,7 +60252,7 @@ function save(directory2, value) {
|
|
|
60171
60252
|
writeOwned(directory2, temporary, JSON.stringify(value) + `
|
|
60172
60253
|
`);
|
|
60173
60254
|
unchangedDirectory(directory2, identity3);
|
|
60174
|
-
renameSync7(
|
|
60255
|
+
renameSync7(join38(directory2, temporary), join38(directory2, "receipt.json"));
|
|
60175
60256
|
const fd = openSync18(directory2, constants14.O_RDONLY | constants14.O_NOFOLLOW);
|
|
60176
60257
|
try {
|
|
60177
60258
|
fsyncSync5(fd);
|
|
@@ -60184,7 +60265,7 @@ function bind(client, receipt) {
|
|
|
60184
60265
|
throw new PrivatePublicationError("PUBLICATION_IDENTITY_CHANGED", "The fresh session does not match the recovery directory's server, account and membership.");
|
|
60185
60266
|
}
|
|
60186
60267
|
async function locked(directory2, action) {
|
|
60187
|
-
const identity3 = safeDirectory(directory2), file2 =
|
|
60268
|
+
const identity3 = safeDirectory(directory2), file2 = join38(directory2, "operation.lock");
|
|
60188
60269
|
let fd;
|
|
60189
60270
|
try {
|
|
60190
60271
|
fd = openSync18(file2, constants14.O_WRONLY | constants14.O_CREAT | constants14.O_EXCL | constants14.O_NOFOLLOW, 384);
|
|
@@ -60200,7 +60281,7 @@ async function locked(directory2, action) {
|
|
|
60200
60281
|
} finally {
|
|
60201
60282
|
closeSync18(fd);
|
|
60202
60283
|
unchangedDirectory(directory2, identity3);
|
|
60203
|
-
const now =
|
|
60284
|
+
const now = lstatSync22(file2);
|
|
60204
60285
|
if (now.dev !== lock.dev || now.ino !== lock.ino || !now.isFile() || now.isSymbolicLink())
|
|
60205
60286
|
fail2();
|
|
60206
60287
|
unlinkSync6(file2);
|
|
@@ -60252,7 +60333,7 @@ async function preparePrivatePublication(client, sourceDirectory, recoveryDirect
|
|
|
60252
60333
|
phase: "prepared",
|
|
60253
60334
|
intent: null
|
|
60254
60335
|
};
|
|
60255
|
-
if (!isAbsolute18(recoveryDirectory) ||
|
|
60336
|
+
if (!isAbsolute18(recoveryDirectory) || resolve20(recoveryDirectory) !== recoveryDirectory || realpathSync11(dirname23(recoveryDirectory)) !== dirname23(recoveryDirectory))
|
|
60256
60337
|
return fail2();
|
|
60257
60338
|
mkdirSync16(recoveryDirectory, { mode: 448 });
|
|
60258
60339
|
safeDirectory(recoveryDirectory);
|
|
@@ -61068,7 +61149,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
61068
61149
|
request2[bodyBufferKey] = buffered;
|
|
61069
61150
|
return Promise.resolve(buffered);
|
|
61070
61151
|
}
|
|
61071
|
-
const promise3 = new Promise((
|
|
61152
|
+
const promise3 = new Promise((resolve21, reject) => {
|
|
61072
61153
|
const chunks = [];
|
|
61073
61154
|
let settled = false;
|
|
61074
61155
|
const finish = (callback) => {
|
|
@@ -61090,7 +61171,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
61090
61171
|
reject(error61 ?? normalizeAbortError(request2, incoming));
|
|
61091
61172
|
else {
|
|
61092
61173
|
request2[bodyBufferKey] = recovered;
|
|
61093
|
-
|
|
61174
|
+
resolve21(recovered);
|
|
61094
61175
|
}
|
|
61095
61176
|
});
|
|
61096
61177
|
return true;
|
|
@@ -61102,7 +61183,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
61102
61183
|
finish(() => {
|
|
61103
61184
|
const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks);
|
|
61104
61185
|
request2[bodyBufferKey] = buffer;
|
|
61105
|
-
|
|
61186
|
+
resolve21(buffer);
|
|
61106
61187
|
});
|
|
61107
61188
|
};
|
|
61108
61189
|
const onError = (error61) => {
|
|
@@ -61376,7 +61457,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
61376
61457
|
});
|
|
61377
61458
|
if (!chunk) {
|
|
61378
61459
|
if (i === 1) {
|
|
61379
|
-
await new Promise((
|
|
61460
|
+
await new Promise((resolve21) => setTimeout(resolve21));
|
|
61380
61461
|
maxReadCount = 3;
|
|
61381
61462
|
continue;
|
|
61382
61463
|
}
|
|
@@ -62606,9 +62687,9 @@ data:
|
|
|
62606
62687
|
const initRequest = messages.find((m) => isInitializeRequest(m));
|
|
62607
62688
|
const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
|
|
62608
62689
|
if (this._enableJsonResponse) {
|
|
62609
|
-
return new Promise((
|
|
62690
|
+
return new Promise((resolve21) => {
|
|
62610
62691
|
this._streamMapping.set(streamId, {
|
|
62611
|
-
resolveJson:
|
|
62692
|
+
resolveJson: resolve21,
|
|
62612
62693
|
cleanup: () => {
|
|
62613
62694
|
this._streamMapping.delete(streamId);
|
|
62614
62695
|
}
|
|
@@ -62977,19 +63058,19 @@ async function connectMcpForNode() {
|
|
|
62977
63058
|
return { server: server2, transport };
|
|
62978
63059
|
}
|
|
62979
63060
|
function readBody(req) {
|
|
62980
|
-
return new Promise((
|
|
63061
|
+
return new Promise((resolve21, reject) => {
|
|
62981
63062
|
const chunks = [];
|
|
62982
63063
|
req.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
62983
63064
|
req.on("end", () => {
|
|
62984
63065
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
62985
63066
|
if (!raw.trim()) {
|
|
62986
|
-
|
|
63067
|
+
resolve21(undefined);
|
|
62987
63068
|
return;
|
|
62988
63069
|
}
|
|
62989
63070
|
try {
|
|
62990
|
-
|
|
63071
|
+
resolve21(JSON.parse(raw));
|
|
62991
63072
|
} catch {
|
|
62992
|
-
|
|
63073
|
+
resolve21(undefined);
|
|
62993
63074
|
}
|
|
62994
63075
|
});
|
|
62995
63076
|
req.on("error", reject);
|
|
@@ -63031,9 +63112,9 @@ async function startSkillsMcpHttpServer(options = {}) {
|
|
|
63031
63112
|
}
|
|
63032
63113
|
}
|
|
63033
63114
|
});
|
|
63034
|
-
await new Promise((
|
|
63115
|
+
await new Promise((resolve21, reject) => {
|
|
63035
63116
|
httpServer.once("error", reject);
|
|
63036
|
-
httpServer.listen(port, hostname4, () =>
|
|
63117
|
+
httpServer.listen(port, hostname4, () => resolve21());
|
|
63037
63118
|
});
|
|
63038
63119
|
const address = httpServer.address();
|
|
63039
63120
|
const listenPort = typeof address === "object" && address ? address.port : port;
|