@hasna/skills 0.8.11 → 0.9.1
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 +21 -4
- package/bin/index.js +853 -446
- package/bin/mcp.js +309 -155
- package/bin/migrate.js +100 -10
- package/bin/server.js +596 -51
- package/bin/worker.js +283 -20
- package/dist/cli/commands/registry.d.ts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +498 -184
- package/dist/lib/agent-discovery.d.ts +1 -1
- package/dist/lib/claude-settings-witness.d.ts +19 -0
- package/dist/lib/cloud-executions.d.ts +20 -0
- package/dist/lib/registry-types.d.ts +3 -0
- package/dist/lib/remote-client.d.ts +11 -0
- package/dist/lib/revision.d.ts +3 -0
- package/dist/sdk/execution/admission.d.ts +2 -1
- package/dist/sdk/execution/types.d.ts +9 -0
- package/dist/sdk/index.d.ts +1 -0
- package/dist/sdk/index.js +1755 -752
- package/dist/server/runtime-policy.d.ts +4 -2
- package/dist/server/runtime-pure-contract.d.ts +51 -0
- package/dist/server/runtime-store.d.ts +4 -0
- package/dist/server/runtime-worker.d.ts +2 -1
- package/dist/server/selection-store.d.ts +9 -1
- package/dist/server/skills-api.d.ts +2 -1
- package/dist/server/sqlite-store.d.ts +4 -1
- package/dist/server/store.d.ts +6 -1
- package/dist/server/types.d.ts +27 -0
- package/docs/plugin-admission.md +67 -0
- package/migrations/postgres/0010_skill_archive_lifecycle.sql +5 -0
- package/migrations/sqlite/0010_skill_archive_lifecycle.sql +5 -0
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -36868,7 +36868,7 @@ var package_default;
|
|
|
36868
36868
|
var init_package = __esm(() => {
|
|
36869
36869
|
package_default = {
|
|
36870
36870
|
name: "@hasna/skills",
|
|
36871
|
-
version: "0.
|
|
36871
|
+
version: "0.9.1",
|
|
36872
36872
|
description: "Skills library for AI coding agents",
|
|
36873
36873
|
type: "module",
|
|
36874
36874
|
bin: {
|
|
@@ -39186,6 +39186,7 @@ function readManifest(skillPath, fallbackName, normalizeName) {
|
|
|
39186
39186
|
const version = readDeclaredSkillVersion(skillPath) ?? PORTABLE_SKILL_DEFAULT_VERSION;
|
|
39187
39187
|
const kind = parseSkillKind(stringField(jsonManifest, "kind") ?? frontmatter?.kind);
|
|
39188
39188
|
const commands = parseManifestCommands(jsonManifest) ?? (kind === "instruction" ? [] : inferPackageCommands(pkg, name)) ?? [];
|
|
39189
|
+
const runtime = parseManifestRuntime(jsonManifest) ?? inferRuntimeFromCommands(commands);
|
|
39189
39190
|
return {
|
|
39190
39191
|
$schema: stringField(jsonManifest, "$schema") ?? PORTABLE_SKILL_SCHEMA,
|
|
39191
39192
|
standard: stringField(jsonManifest, "standard") ?? PORTABLE_SKILL_STANDARD,
|
|
@@ -39198,7 +39199,7 @@ function readManifest(skillPath, fallbackName, normalizeName) {
|
|
|
39198
39199
|
...kind ? { kind } : {},
|
|
39199
39200
|
inputs: kind === "instruction" ? parseManifestInputs(jsonManifest) ?? [] : parseManifestInputs(jsonManifest) ?? DEFAULT_INPUTS,
|
|
39200
39201
|
commands,
|
|
39201
|
-
...
|
|
39202
|
+
...runtime ? { runtime } : {},
|
|
39202
39203
|
...parseManifestProvenance(jsonManifest) ? { provenance: parseManifestProvenance(jsonManifest) } : {}
|
|
39203
39204
|
};
|
|
39204
39205
|
}
|
|
@@ -39717,6 +39718,12 @@ function inferPackageCommands(pkg, fallbackName) {
|
|
|
39717
39718
|
}
|
|
39718
39719
|
return;
|
|
39719
39720
|
}
|
|
39721
|
+
function inferRuntimeFromCommands(commands) {
|
|
39722
|
+
const entrypoint = commands.find((command) => command.entry)?.entry;
|
|
39723
|
+
if (!entrypoint || !entrypoint.toLowerCase().endsWith(".py"))
|
|
39724
|
+
return;
|
|
39725
|
+
return { ...defaultRuntimeContract(entrypoint), runtime: "python3" };
|
|
39726
|
+
}
|
|
39720
39727
|
function readJsonObject(path) {
|
|
39721
39728
|
const parsed = JSON.parse(readFileSync6(path, "utf-8"));
|
|
39722
39729
|
if (!isRecord2(parsed))
|
|
@@ -43298,7 +43305,9 @@ function assertAgentPolicyCollections(policy) {
|
|
|
43298
43305
|
text(source.path);
|
|
43299
43306
|
requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
|
|
43300
43307
|
if (source.hashMode !== undefined)
|
|
43301
|
-
requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
43308
|
+
requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
43309
|
+
if (source.hashMode === "claude-settings-v1")
|
|
43310
|
+
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve5(source.path) === source.path && basename3(source.path) === "settings.json");
|
|
43302
43311
|
if (source.hashMode === "claude-marketplace-registry")
|
|
43303
43312
|
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve5(source.path) === source.path && basename3(source.path) === "known_marketplaces.json");
|
|
43304
43313
|
if (source.hashMode === "claude-plugin-registry") {
|
|
@@ -54505,10 +54514,232 @@ var init_claude_marketplace_registry = __esm(() => {
|
|
|
54505
54514
|
CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
|
|
54506
54515
|
});
|
|
54507
54516
|
|
|
54508
|
-
// src/lib/
|
|
54517
|
+
// src/lib/claude-settings-witness.ts
|
|
54509
54518
|
import { createHash as createHash12 } from "crypto";
|
|
54510
|
-
import {
|
|
54511
|
-
import {
|
|
54519
|
+
import { closeSync as closeSync10, constants as constants10, fstatSync as fstatSync10, lstatSync as lstatSync16, openSync as openSync10, readSync as readSync8 } from "fs";
|
|
54520
|
+
import { basename as basename7, dirname as dirname13, isAbsolute as isAbsolute13, resolve as resolve14 } from "path";
|
|
54521
|
+
function need3(value, reason) {
|
|
54522
|
+
if (!value)
|
|
54523
|
+
throw new Error(`Claude settings witness ${reason}`);
|
|
54524
|
+
}
|
|
54525
|
+
function absolutePath2(value) {
|
|
54526
|
+
need3(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute13(value) && resolve14(value) === value, "requires a normalized absolute path");
|
|
54527
|
+
}
|
|
54528
|
+
function parents2(path) {
|
|
54529
|
+
const result2 = [];
|
|
54530
|
+
for (let at2 = dirname13(path);; at2 = dirname13(at2)) {
|
|
54531
|
+
const stat2 = lstatSync16(at2, { bigint: true });
|
|
54532
|
+
need3(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
|
|
54533
|
+
result2.push([at2, stat2]);
|
|
54534
|
+
if (at2 === dirname13(at2))
|
|
54535
|
+
return result2;
|
|
54536
|
+
}
|
|
54537
|
+
}
|
|
54538
|
+
function readSettings(path, budget) {
|
|
54539
|
+
absolutePath2(path);
|
|
54540
|
+
need3(basename7(path) === "settings.json", "requires settings.json");
|
|
54541
|
+
need3(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
|
|
54542
|
+
const ancestors2 = parents2(path), initial2 = lstatSync16(path, { bigint: true });
|
|
54543
|
+
need3(initial2.isFile() && !initial2.isSymbolicLink() && initial2.size <= BigInt(CLAUDE_SETTINGS_WITNESS_LIMITS.bytes), "is not a bounded regular file");
|
|
54544
|
+
need3(initial2.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
|
|
54545
|
+
const fd = openSync10(path, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
|
|
54546
|
+
try {
|
|
54547
|
+
const opened = fstatSync10(fd, { bigint: true });
|
|
54548
|
+
need3(opened.isFile() && sameFile2(initial2, opened), "changed during open");
|
|
54549
|
+
const bytes = Buffer.alloc(Number(opened.size) + 1);
|
|
54550
|
+
let length = 0;
|
|
54551
|
+
while (length < bytes.length) {
|
|
54552
|
+
const count = readSync8(fd, bytes, length, bytes.length - length, null);
|
|
54553
|
+
if (!count)
|
|
54554
|
+
break;
|
|
54555
|
+
length += count;
|
|
54556
|
+
}
|
|
54557
|
+
const after2 = fstatSync10(fd, { bigint: true }), current = lstatSync16(path, { bigint: true });
|
|
54558
|
+
need3(current.isFile() && sameFile2(opened, after2) && sameFile2(after2, current) && BigInt(length) === opened.size, "changed during read");
|
|
54559
|
+
for (const [ancestor, before2] of ancestors2) {
|
|
54560
|
+
const now3 = lstatSync16(ancestor, { bigint: true });
|
|
54561
|
+
need3(now3.isDirectory() && before2.dev === now3.dev && before2.ino === now3.ino && before2.mode === now3.mode, "parent changed during read");
|
|
54562
|
+
}
|
|
54563
|
+
budget.remaining -= length;
|
|
54564
|
+
try {
|
|
54565
|
+
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes.subarray(0, length));
|
|
54566
|
+
} catch {
|
|
54567
|
+
throw new Error("Claude settings witness is not strict UTF-8");
|
|
54568
|
+
}
|
|
54569
|
+
} finally {
|
|
54570
|
+
closeSync10(fd);
|
|
54571
|
+
}
|
|
54572
|
+
}
|
|
54573
|
+
function parse6(text2) {
|
|
54574
|
+
let at2 = 0, nodes = 0;
|
|
54575
|
+
const numberPattern = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/y;
|
|
54576
|
+
const space = () => {
|
|
54577
|
+
while (at2 < text2.length && /[\x20\t\r\n]/.test(text2[at2]))
|
|
54578
|
+
at2++;
|
|
54579
|
+
};
|
|
54580
|
+
function string() {
|
|
54581
|
+
need3(text2[at2] === '"', "contains invalid JSON");
|
|
54582
|
+
const start = at2++;
|
|
54583
|
+
while (at2 < text2.length) {
|
|
54584
|
+
const character = text2[at2++];
|
|
54585
|
+
if (character === '"') {
|
|
54586
|
+
let value2;
|
|
54587
|
+
try {
|
|
54588
|
+
value2 = JSON.parse(text2.slice(start, at2));
|
|
54589
|
+
} catch {
|
|
54590
|
+
throw new Error("Claude settings witness contains invalid JSON string");
|
|
54591
|
+
}
|
|
54592
|
+
need3(value2.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.stringCharacters, "exceeds its string limit");
|
|
54593
|
+
return value2;
|
|
54594
|
+
}
|
|
54595
|
+
if (character === "\\")
|
|
54596
|
+
at2++;
|
|
54597
|
+
}
|
|
54598
|
+
throw new Error("Claude settings witness contains an unterminated JSON string");
|
|
54599
|
+
}
|
|
54600
|
+
function value(depth) {
|
|
54601
|
+
need3(depth <= CLAUDE_SETTINGS_WITNESS_LIMITS.depth && ++nodes <= CLAUDE_SETTINGS_WITNESS_LIMITS.nodes, "exceeds its nesting or node limit");
|
|
54602
|
+
space();
|
|
54603
|
+
const character = text2[at2];
|
|
54604
|
+
if (character === '"')
|
|
54605
|
+
return { kind: "string", value: string() };
|
|
54606
|
+
if (character === "{" || character === "[") {
|
|
54607
|
+
at2++;
|
|
54608
|
+
space();
|
|
54609
|
+
const object4 = character === "{", end = object4 ? "}" : "]", entries = [], items = [], keys2 = new Set;
|
|
54610
|
+
if (text2[at2] !== end)
|
|
54611
|
+
while (true) {
|
|
54612
|
+
if (object4) {
|
|
54613
|
+
space();
|
|
54614
|
+
const key = string();
|
|
54615
|
+
need3(!keys2.has(key), "contains a duplicate JSON key");
|
|
54616
|
+
keys2.add(key);
|
|
54617
|
+
space();
|
|
54618
|
+
need3(text2[at2++] === ":", "contains invalid JSON");
|
|
54619
|
+
entries.push([key, value(depth + 1)]);
|
|
54620
|
+
} else
|
|
54621
|
+
items.push(value(depth + 1));
|
|
54622
|
+
space();
|
|
54623
|
+
if (text2[at2] === end)
|
|
54624
|
+
break;
|
|
54625
|
+
need3(text2[at2++] === ",", "contains invalid JSON");
|
|
54626
|
+
}
|
|
54627
|
+
at2++;
|
|
54628
|
+
return object4 ? { kind: "object", entries } : { kind: "array", items };
|
|
54629
|
+
}
|
|
54630
|
+
for (const literal of ["true", "false", "null"])
|
|
54631
|
+
if (text2.startsWith(literal, at2)) {
|
|
54632
|
+
at2 += literal.length;
|
|
54633
|
+
return { kind: "literal", value: literal };
|
|
54634
|
+
}
|
|
54635
|
+
numberPattern.lastIndex = at2;
|
|
54636
|
+
const number = numberPattern.exec(text2);
|
|
54637
|
+
need3(number, "contains invalid JSON");
|
|
54638
|
+
at2 += number[0].length;
|
|
54639
|
+
return { kind: "number", value: number[0] };
|
|
54640
|
+
}
|
|
54641
|
+
const root2 = value(0);
|
|
54642
|
+
space();
|
|
54643
|
+
need3(at2 === text2.length && root2.kind === "object", "requires a JSON object without trailing content");
|
|
54644
|
+
need3(root2.entries.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.rows, "exceeds its settings field limit");
|
|
54645
|
+
return root2;
|
|
54646
|
+
}
|
|
54647
|
+
function canonical3(value) {
|
|
54648
|
+
if (value.kind === "object")
|
|
54649
|
+
return { kind: "object", entries: value.entries.map(([key, child]) => [key, canonical3(child)]).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0) };
|
|
54650
|
+
if (value.kind === "array")
|
|
54651
|
+
return { kind: "array", items: value.items.map(canonical3) };
|
|
54652
|
+
return value;
|
|
54653
|
+
}
|
|
54654
|
+
function settingsDigest(text2) {
|
|
54655
|
+
const value = parse6(text2);
|
|
54656
|
+
value.entries = value.entries.filter(([key, child]) => {
|
|
54657
|
+
if (key === "model") {
|
|
54658
|
+
need3(child.kind === "string", "contains an invalid model selection");
|
|
54659
|
+
return !BUILTIN_MODEL_SELECTIONS.has(child.value);
|
|
54660
|
+
}
|
|
54661
|
+
if (BOOLEAN_PREFERENCES.has(key)) {
|
|
54662
|
+
need3(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid display preference");
|
|
54663
|
+
return false;
|
|
54664
|
+
}
|
|
54665
|
+
if (Object.hasOwn(ENUM_PREFERENCES, key)) {
|
|
54666
|
+
need3(child.kind === "string" && ENUM_PREFERENCES[key].includes(child.value), "contains an invalid display preference");
|
|
54667
|
+
return false;
|
|
54668
|
+
}
|
|
54669
|
+
return true;
|
|
54670
|
+
});
|
|
54671
|
+
return createHash12("sha256").update("hasna.skills.claude-settings.v1\x00").update(JSON.stringify(canonical3(value))).digest("hex");
|
|
54672
|
+
}
|
|
54673
|
+
function hashClaudeSettingsReplacement(text2, budget) {
|
|
54674
|
+
need3(typeof text2 === "string", "requires settings text");
|
|
54675
|
+
const bytes = Buffer.byteLength(text2);
|
|
54676
|
+
need3(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
|
|
54677
|
+
budget.remaining -= bytes;
|
|
54678
|
+
return settingsDigest(text2);
|
|
54679
|
+
}
|
|
54680
|
+
function captureClaudeSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
54681
|
+
return { path, hashMode: "claude-settings-v1", sha256: settingsDigest(readSettings(path, budget)) };
|
|
54682
|
+
}
|
|
54683
|
+
var CLAUDE_SETTINGS_WITNESS_LIMITS, sameFile2 = (a, b) => a.dev === b.dev && a.ino === b.ino && a.mode === b.mode && a.uid === b.uid && a.gid === b.gid && a.nlink === b.nlink && a.size === b.size && a.mtimeNs === b.mtimeNs && a.ctimeNs === b.ctimeNs, BOOLEAN_PREFERENCES, ENUM_PREFERENCES, BUILTIN_MODEL_SELECTIONS;
|
|
54684
|
+
var init_claude_settings_witness = __esm(() => {
|
|
54685
|
+
CLAUDE_SETTINGS_WITNESS_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
|
|
54686
|
+
BOOLEAN_PREFERENCES = new Set([
|
|
54687
|
+
"autoScrollEnabled",
|
|
54688
|
+
"axScreenReader",
|
|
54689
|
+
"emojiCompletionEnabled",
|
|
54690
|
+
"prefersReducedMotion",
|
|
54691
|
+
"showTurnDuration",
|
|
54692
|
+
"spinnerTipsEnabled",
|
|
54693
|
+
"syntaxHighlightingDisabled",
|
|
54694
|
+
"terminalProgressBarEnabled",
|
|
54695
|
+
"terminalTitleFromRename",
|
|
54696
|
+
"verbose",
|
|
54697
|
+
"wheelScrollAccelerationEnabled"
|
|
54698
|
+
]);
|
|
54699
|
+
ENUM_PREFERENCES = Object.freeze({
|
|
54700
|
+
editorMode: ["normal", "vim"],
|
|
54701
|
+
tui: ["default", "fullscreen"],
|
|
54702
|
+
viewMode: ["default", "verbose", "focus"]
|
|
54703
|
+
});
|
|
54704
|
+
BUILTIN_MODEL_SELECTIONS = new Set([
|
|
54705
|
+
"default",
|
|
54706
|
+
"best",
|
|
54707
|
+
"fable",
|
|
54708
|
+
"fable[1m]",
|
|
54709
|
+
"sonnet",
|
|
54710
|
+
"sonnet[1m]",
|
|
54711
|
+
"opus",
|
|
54712
|
+
"opus[1m]",
|
|
54713
|
+
"haiku",
|
|
54714
|
+
"opusplan",
|
|
54715
|
+
"claude-fable-5-1",
|
|
54716
|
+
"claude-fable-5",
|
|
54717
|
+
"claude-fable-5[1m]",
|
|
54718
|
+
"claude-opus-5",
|
|
54719
|
+
"claude-sonnet-5",
|
|
54720
|
+
"claude-haiku-4-5-20251001",
|
|
54721
|
+
"claude-opus-4-6",
|
|
54722
|
+
"claude-sonnet-4-5",
|
|
54723
|
+
"claude-sonnet-4-5-20250929",
|
|
54724
|
+
"claude-opus-4-8",
|
|
54725
|
+
"claude-opus-4-8[1m]",
|
|
54726
|
+
"claude-opus-4-7",
|
|
54727
|
+
"claude-sonnet-4-6",
|
|
54728
|
+
"claude-opus-4-5-20251101",
|
|
54729
|
+
"claude-opus-4-5",
|
|
54730
|
+
"claude-haiku-4-5",
|
|
54731
|
+
"claude-fable-5-1[1m]",
|
|
54732
|
+
"claude-opus-5[1m]",
|
|
54733
|
+
"claude-opus-4-7[1m]",
|
|
54734
|
+
"claude-opus-4-6[1m]",
|
|
54735
|
+
"claude-sonnet-4-6[1m]"
|
|
54736
|
+
]);
|
|
54737
|
+
});
|
|
54738
|
+
|
|
54739
|
+
// src/lib/agent-discovery.ts
|
|
54740
|
+
import { createHash as createHash13 } from "crypto";
|
|
54741
|
+
import { lstatSync as lstatSync17, readFileSync as readFileSync14, readdirSync as readdirSync9, realpathSync as realpathSync4 } from "fs";
|
|
54742
|
+
import { basename as basename8, dirname as dirname14, isAbsolute as isAbsolute14, join as join28, resolve as resolve15, sep as sep5 } from "path";
|
|
54512
54743
|
function parseConfig(text2, path, toml = false) {
|
|
54513
54744
|
try {
|
|
54514
54745
|
const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
|
|
@@ -54520,12 +54751,12 @@ function parseConfig(text2, path, toml = false) {
|
|
|
54520
54751
|
}
|
|
54521
54752
|
}
|
|
54522
54753
|
function safe4(path) {
|
|
54523
|
-
if (!
|
|
54754
|
+
if (!isAbsolute14(path) || path.includes("\x00"))
|
|
54524
54755
|
throw new Error("Expected an absolute native discovery path");
|
|
54525
|
-
for (let cursor = path;; cursor =
|
|
54526
|
-
if (
|
|
54756
|
+
for (let cursor = path;; cursor = dirname14(cursor)) {
|
|
54757
|
+
if (lstatSync17(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
54527
54758
|
throw new Error(`Refusing symlink native discovery input: ${cursor}`);
|
|
54528
|
-
if (
|
|
54759
|
+
if (dirname14(cursor) === cursor)
|
|
54529
54760
|
break;
|
|
54530
54761
|
}
|
|
54531
54762
|
}
|
|
@@ -54533,7 +54764,7 @@ function read2(path, changes) {
|
|
|
54533
54764
|
safe4(path);
|
|
54534
54765
|
if (changes?.has(path))
|
|
54535
54766
|
return changes.get(path);
|
|
54536
|
-
const stat2 =
|
|
54767
|
+
const stat2 = lstatSync17(path, { throwIfNoEntry: false });
|
|
54537
54768
|
if (!stat2)
|
|
54538
54769
|
return null;
|
|
54539
54770
|
if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
|
|
@@ -54541,6 +54772,14 @@ function read2(path, changes) {
|
|
|
54541
54772
|
return readFileSync14(path, "utf8");
|
|
54542
54773
|
}
|
|
54543
54774
|
function projected(source, changes, budget = discoveryByteBudget()) {
|
|
54775
|
+
if (source.hashMode === "claude-settings-v1") {
|
|
54776
|
+
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
54777
|
+
throw new Error("Claude settings witnesses require exact typed metadata");
|
|
54778
|
+
const current = captureClaudeSettings(source.path, budget).sha256;
|
|
54779
|
+
if (current !== source.sha256)
|
|
54780
|
+
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
54781
|
+
return changes?.has(source.path) ? hashClaudeSettingsReplacement(changes.get(source.path), budget) : current;
|
|
54782
|
+
}
|
|
54544
54783
|
if (source.hashMode === "claude-marketplace-registry") {
|
|
54545
54784
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256) || changes?.has(source.path))
|
|
54546
54785
|
throw new Error("Claude marketplace witnesses require an exact reviewed registry without synthetic changes");
|
|
@@ -54598,6 +54837,8 @@ function verifyAgentDiscovery(binding) {
|
|
|
54598
54837
|
safe4(root2);
|
|
54599
54838
|
}
|
|
54600
54839
|
function assertMarketplaceBinding(binding, source) {
|
|
54840
|
+
if (source.hashMode === "claude-settings-v1" && (binding.agent !== "claude" || binding.method !== "reviewed" || basename8(source.path) !== "settings.json"))
|
|
54841
|
+
throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
|
|
54601
54842
|
if (source.hashMode === "claude-marketplace-registry" && (binding.agent !== "claude" || binding.method !== "reviewed"))
|
|
54602
54843
|
throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
|
|
54603
54844
|
}
|
|
@@ -54608,9 +54849,9 @@ function rebindAgentDiscovery(binding, changes) {
|
|
|
54608
54849
|
return { ...source, sha256: projected(source, changes, budget) };
|
|
54609
54850
|
}) };
|
|
54610
54851
|
}
|
|
54611
|
-
function assertProjectDiscovery(agent, directories, home,
|
|
54852
|
+
function assertProjectDiscovery(agent, directories, home, canonical4 = resolve15, reviewed) {
|
|
54612
54853
|
for (const directory of directories) {
|
|
54613
|
-
const isHome =
|
|
54854
|
+
const isHome = resolve15(directory) === resolve15(home);
|
|
54614
54855
|
if (agent === "hermes") {
|
|
54615
54856
|
assertHermesEnvironment(home);
|
|
54616
54857
|
continue;
|
|
@@ -54619,7 +54860,7 @@ function assertProjectDiscovery(agent, directories, home, canonical3 = resolve14
|
|
|
54619
54860
|
continue;
|
|
54620
54861
|
const paths = agent === "claude" ? [...isHome ? [] : [".claude/settings.json"], ".claude/settings.local.json"] : agent === "codex" ? [".codex/config.toml"] : agent === "gemini" ? [".gemini/settings.json"] : agent === "opencode" ? ["opencode.json", "opencode.jsonc", ".opencode/opencode.json", ".opencode/opencode.jsonc"] : [".cursor/hooks.json"];
|
|
54621
54862
|
for (const suffix of paths) {
|
|
54622
|
-
const path =
|
|
54863
|
+
const path = canonical4(join28(directory, suffix)), raw = read2(path);
|
|
54623
54864
|
if (raw === null)
|
|
54624
54865
|
continue;
|
|
54625
54866
|
if (suffix.endsWith(".jsonc"))
|
|
@@ -54632,25 +54873,25 @@ function assertProjectDiscovery(agent, directories, home, canonical3 = resolve14
|
|
|
54632
54873
|
const managed = reviewed.sources.flatMap((source) => source.hashMode === "claude-plugin-registry" ? source.managedPlugins ?? [] : []);
|
|
54633
54874
|
if (exact && projected(exact) === exact.sha256 && managed.length) {
|
|
54634
54875
|
const bindings = managed.map((item) => readPluginBinding(item.storeRoot, item.bindingId));
|
|
54635
|
-
admittedPlugins = Object.entries(config.enabledPlugins).every(([id, enabled]) => typeof enabled === "boolean" && bindings.some((binding) => binding.target.pluginId === id && binding.target.registrations.some((scope) => scope.scope === "project" && scope.projectPath ===
|
|
54876
|
+
admittedPlugins = Object.entries(config.enabledPlugins).every(([id, enabled]) => typeof enabled === "boolean" && bindings.some((binding) => binding.target.pluginId === id && binding.target.registrations.some((scope) => scope.scope === "project" && scope.projectPath === canonical4(directory))));
|
|
54636
54877
|
}
|
|
54637
54878
|
}
|
|
54638
54879
|
if (keys2.some((key) => config[key] !== undefined && !(key === "enabledPlugins" && admittedPlugins)) || config.disableAllHooks === true || config.disableBundledSkills === false || config.hooksConfig?.enabled === false || config.permission?.skill !== undefined || config.permissions?.deny?.some((rule) => typeof rule === "string" && /^Skill(?:\(|$)/.test(rule)))
|
|
54639
54880
|
throw new Error(`NATIVE_SKILL_DRIFT: higher-precedence project skill or hook configuration requires review: ${path}`);
|
|
54640
54881
|
}
|
|
54641
54882
|
if (agent === "claude") {
|
|
54642
|
-
const commands =
|
|
54883
|
+
const commands = canonical4(join28(directory, ".claude/commands"));
|
|
54643
54884
|
safe4(commands);
|
|
54644
|
-
if (
|
|
54885
|
+
if (lstatSync17(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
|
|
54645
54886
|
throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
|
|
54646
54887
|
}
|
|
54647
54888
|
}
|
|
54648
54889
|
}
|
|
54649
54890
|
function resolveAgentDiscovery(options) {
|
|
54650
|
-
const
|
|
54891
|
+
const canonical4 = options.canonical ?? resolve15, home = resolve15(options.home), agent = options.agent;
|
|
54651
54892
|
const sources = [], roots = new Set, builtinNames = [];
|
|
54652
54893
|
const witness = (path, format, fields) => {
|
|
54653
|
-
const source = { path:
|
|
54894
|
+
const source = { path: canonical4(path), sha256: null, ...format ? { format, fields } : {} };
|
|
54654
54895
|
source.sha256 = projected(source);
|
|
54655
54896
|
sources.push(source);
|
|
54656
54897
|
return read2(source.path);
|
|
@@ -54678,7 +54919,7 @@ function resolveAgentDiscovery(options) {
|
|
|
54678
54919
|
continue;
|
|
54679
54920
|
if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
|
|
54680
54921
|
unresolved("user-specific tilde expansion requires a separate discovery adapter");
|
|
54681
|
-
const path = normalized === "~" ? home : normalized.startsWith("~/") ? join28(home, normalized.slice(2)) :
|
|
54922
|
+
const path = normalized === "~" ? home : normalized.startsWith("~/") ? join28(home, normalized.slice(2)) : resolve15(home, ".hermes", normalized);
|
|
54682
54923
|
safe4(path);
|
|
54683
54924
|
roots.add(path);
|
|
54684
54925
|
}
|
|
@@ -54687,21 +54928,21 @@ function resolveAgentDiscovery(options) {
|
|
|
54687
54928
|
const executable = Bun.which("gemini");
|
|
54688
54929
|
if (executable) {
|
|
54689
54930
|
let packageRoot;
|
|
54690
|
-
for (let directory =
|
|
54931
|
+
for (let directory = dirname14(realpathSync4(executable)), depth = 0;depth < 8; directory = dirname14(directory), depth++) {
|
|
54691
54932
|
const path = join28(directory, "package.json"), raw = read2(path);
|
|
54692
54933
|
if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
|
|
54693
54934
|
packageRoot = directory;
|
|
54694
54935
|
witness(path);
|
|
54695
54936
|
break;
|
|
54696
54937
|
}
|
|
54697
|
-
if (
|
|
54938
|
+
if (dirname14(directory) === directory)
|
|
54698
54939
|
break;
|
|
54699
54940
|
}
|
|
54700
54941
|
if (!packageRoot)
|
|
54701
54942
|
unresolved("installed Gemini package layout is not recognized");
|
|
54702
54943
|
const builtinRoot = join28(packageRoot, "bundle/builtin");
|
|
54703
54944
|
safe4(builtinRoot);
|
|
54704
|
-
if (!
|
|
54945
|
+
if (!lstatSync17(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
|
|
54705
54946
|
unresolved("installed Gemini builtin root is missing");
|
|
54706
54947
|
for (const name of readdirSync9(builtinRoot).sort()) {
|
|
54707
54948
|
const text2 = witness(join28(builtinRoot, name, "SKILL.md"));
|
|
@@ -54722,12 +54963,14 @@ function resolveAgentDiscovery(options) {
|
|
|
54722
54963
|
if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
|
|
54723
54964
|
throw new Error("Explicit discovery reviews require full source-file hashes");
|
|
54724
54965
|
verifyAgentDiscovery(supplied);
|
|
54725
|
-
if (
|
|
54966
|
+
if (review.sources.some((source) => source.hashMode === "claude-settings-v1" && source.path !== canonical4(configPath)))
|
|
54967
|
+
throw new Error("Semantic settings witnesses must name the configured Claude configuration source");
|
|
54968
|
+
if (!review.sources.some((source) => source.path === canonical4(configPath)))
|
|
54726
54969
|
throw new Error("Discovery review must include the agent configuration source");
|
|
54727
54970
|
return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: [...sources, ...review.sources], ...agent === "gemini" ? { builtinNames } : {} };
|
|
54728
54971
|
}
|
|
54729
54972
|
function plugin(root2) {
|
|
54730
|
-
root2 =
|
|
54973
|
+
root2 = canonical4(root2);
|
|
54731
54974
|
safe4(root2);
|
|
54732
54975
|
const manifestPath = join28(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
|
|
54733
54976
|
const raw = witness(manifestPath);
|
|
@@ -54739,7 +54982,7 @@ function resolveAgentDiscovery(options) {
|
|
|
54739
54982
|
unresolved("plugin hooks require a separate no-skill-injection review");
|
|
54740
54983
|
const commands = join28(root2, "commands");
|
|
54741
54984
|
safe4(commands);
|
|
54742
|
-
if (agent === "claude" && (manifest.commands !== undefined ||
|
|
54985
|
+
if (agent === "claude" && (manifest.commands !== undefined || lstatSync17(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length))
|
|
54743
54986
|
unresolved("legacy command discovery requires retirement or a dedicated format adapter");
|
|
54744
54987
|
const rootSkill = witness(join28(root2, "SKILL.md"));
|
|
54745
54988
|
if (rootSkill !== null)
|
|
@@ -54750,18 +54993,18 @@ function resolveAgentDiscovery(options) {
|
|
|
54750
54993
|
if (agent === "claude")
|
|
54751
54994
|
roots.add(join28(root2, "skills"));
|
|
54752
54995
|
for (const value of declared) {
|
|
54753
|
-
const path =
|
|
54996
|
+
const path = resolve15(root2, value);
|
|
54754
54997
|
if (path !== root2 && !path.startsWith(root2 + sep5))
|
|
54755
54998
|
unresolved("plugin skill path escapes its root");
|
|
54756
|
-
roots.add(path.endsWith(`${sep5}SKILL.md`) ?
|
|
54999
|
+
roots.add(path.endsWith(`${sep5}SKILL.md`) ? dirname14(path) : path);
|
|
54757
55000
|
}
|
|
54758
55001
|
}
|
|
54759
55002
|
if (agent === "claude") {
|
|
54760
55003
|
const registrations = witness(join28(home, ".claude/plugins/installed_plugins.json"));
|
|
54761
55004
|
const installed = registrations === null ? {} : parseConfig(registrations, join28(home, ".claude/plugins/installed_plugins.json")).plugins;
|
|
54762
|
-
const commands =
|
|
55005
|
+
const commands = canonical4(join28(home, ".claude/commands"));
|
|
54763
55006
|
safe4(commands);
|
|
54764
|
-
if (
|
|
55007
|
+
if (lstatSync17(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
|
|
54765
55008
|
unresolved("legacy home command discovery requires a dedicated format adapter");
|
|
54766
55009
|
for (const [id, enabled] of Object.entries(config.enabledPlugins ?? {})) {
|
|
54767
55010
|
if (enabled === false)
|
|
@@ -54781,7 +55024,7 @@ function resolveAgentDiscovery(options) {
|
|
|
54781
55024
|
unresolved("unsupported plugin enablement");
|
|
54782
55025
|
const split2 = id.lastIndexOf("@"), name = id.slice(0, split2), marketplace = id.slice(split2 + 1);
|
|
54783
55026
|
const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
|
|
54784
|
-
if (split2 < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !
|
|
55027
|
+
if (split2 < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute14(market.source))
|
|
54785
55028
|
unresolved("enabled plugin marketplace is not an explicit local source");
|
|
54786
55029
|
const catalogText = witness(join28(market.source, ".agents/plugins/marketplace.json"));
|
|
54787
55030
|
if (catalogText === null)
|
|
@@ -54789,7 +55032,7 @@ function resolveAgentDiscovery(options) {
|
|
|
54789
55032
|
const catalog = parseConfig(catalogText, join28(market.source, ".agents/plugins/marketplace.json")), matches2 = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
|
|
54790
55033
|
if (matches2.length !== 1 || matches2[0]?.source?.source !== "local" || typeof matches2[0]?.source?.path !== "string")
|
|
54791
55034
|
unresolved("plugin catalog source is missing or ambiguous");
|
|
54792
|
-
plugin(
|
|
55035
|
+
plugin(resolve15(market.source, matches2[0].source.path));
|
|
54793
55036
|
}
|
|
54794
55037
|
} else if (agent === "opencode") {
|
|
54795
55038
|
if (witness(join28(home, ".config/opencode/opencode.jsonc")) !== null || witness(join28(home, ".config/opencode/config.json")) !== null)
|
|
@@ -54797,18 +55040,18 @@ function resolveAgentDiscovery(options) {
|
|
|
54797
55040
|
if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
|
|
54798
55041
|
unresolved("external plugin or remote skill source");
|
|
54799
55042
|
for (const path of config.skills?.paths ?? []) {
|
|
54800
|
-
if (typeof path !== "string" || !
|
|
55043
|
+
if (typeof path !== "string" || !isAbsolute14(path))
|
|
54801
55044
|
unresolved("relative or malformed added skill root");
|
|
54802
55045
|
roots.add(path);
|
|
54803
55046
|
}
|
|
54804
55047
|
const localPlugins = join28(home, ".config/opencode/plugins");
|
|
54805
55048
|
safe4(localPlugins);
|
|
54806
|
-
if (
|
|
55049
|
+
if (lstatSync17(localPlugins, { throwIfNoEntry: false }) && readdirSync9(localPlugins).some((name) => name !== "skills-cli.js"))
|
|
54807
55050
|
unresolved("additional local plugin hooks require review");
|
|
54808
55051
|
} else if (agent === "hermes") {
|
|
54809
55052
|
for (const directory of [join28(home, ".hermes/plugins"), join28(home, ".hermes/hermes-agent")]) {
|
|
54810
55053
|
safe4(directory);
|
|
54811
|
-
if (
|
|
55054
|
+
if (lstatSync17(directory, { throwIfNoEntry: false }))
|
|
54812
55055
|
unresolved("installed runtime/plugin discovery requires reviewed source bindings");
|
|
54813
55056
|
}
|
|
54814
55057
|
if (Bun.which("hermes") || Object.keys(config.plugins ?? {}).length)
|
|
@@ -54818,11 +55061,11 @@ function resolveAgentDiscovery(options) {
|
|
|
54818
55061
|
unresolved("custom extension or skill paths");
|
|
54819
55062
|
const directory = join28(home, ".gemini/extensions");
|
|
54820
55063
|
safe4(directory);
|
|
54821
|
-
if (
|
|
55064
|
+
if (lstatSync17(directory, { throwIfNoEntry: false }))
|
|
54822
55065
|
for (const name of readdirSync9(directory)) {
|
|
54823
55066
|
const root2 = join28(directory, name);
|
|
54824
55067
|
safe4(root2);
|
|
54825
|
-
if (!
|
|
55068
|
+
if (!lstatSync17(root2)?.isDirectory())
|
|
54826
55069
|
continue;
|
|
54827
55070
|
const raw = witness(join28(root2, "gemini-extension.json"));
|
|
54828
55071
|
if (raw === null)
|
|
@@ -54833,9 +55076,9 @@ function resolveAgentDiscovery(options) {
|
|
|
54833
55076
|
roots.add(join28(root2, "skills"));
|
|
54834
55077
|
}
|
|
54835
55078
|
}
|
|
54836
|
-
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join28(home, ".hermes/plugins"), join28(home, ".hermes/hermes-agent")].map((path) =>
|
|
55079
|
+
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join28(home, ".hermes/plugins"), join28(home, ".hermes/hermes-agent")].map((path) => canonical4(path))) } : {} };
|
|
54837
55080
|
}
|
|
54838
|
-
var digest = (text2) =>
|
|
55081
|
+
var digest = (text2) => createHash13("sha256").update(text2).digest("hex");
|
|
54839
55082
|
var init_agent_discovery = __esm(() => {
|
|
54840
55083
|
init_agent_policy_limits();
|
|
54841
55084
|
init_agent_hermes();
|
|
@@ -54845,6 +55088,7 @@ var init_agent_discovery = __esm(() => {
|
|
|
54845
55088
|
init_plugin_discovery();
|
|
54846
55089
|
init_plugin_admission();
|
|
54847
55090
|
init_claude_marketplace_registry();
|
|
55091
|
+
init_claude_settings_witness();
|
|
54848
55092
|
init_agent_discovery_directories();
|
|
54849
55093
|
});
|
|
54850
55094
|
|
|
@@ -55006,16 +55250,16 @@ var init_agent_codex = __esm(() => {
|
|
|
55006
55250
|
});
|
|
55007
55251
|
|
|
55008
55252
|
// src/lib/agent-integration.ts
|
|
55009
|
-
import { createHash as
|
|
55010
|
-
import { existsSync as existsSync15, lstatSync as
|
|
55011
|
-
import { dirname as
|
|
55253
|
+
import { createHash as createHash14, randomUUID as randomUUID6 } from "crypto";
|
|
55254
|
+
import { existsSync as existsSync15, lstatSync as lstatSync18, statSync as statSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync15, readdirSync as readdirSync10, opendirSync as opendirSync5, readlinkSync as readlinkSync2, realpathSync as realpathSync5, renameSync as renameSync4, rmdirSync as rmdirSync3, writeFileSync as writeFileSync5, unlinkSync as unlinkSync4, chmodSync, openSync as openSync11, closeSync as closeSync11, fsyncSync as fsyncSync3, fstatSync as fstatSync11, readSync as readSync9, constants as constants11, linkSync as linkSync2 } from "fs";
|
|
55255
|
+
import { dirname as dirname15, join as join29, resolve as resolve16, relative as relative5, isAbsolute as isAbsolute15, sep as sep6 } from "path";
|
|
55012
55256
|
import { homedir as homedir4 } from "os";
|
|
55013
55257
|
function assertSafePath(path) {
|
|
55014
|
-
let cursor =
|
|
55258
|
+
let cursor = resolve16(path);
|
|
55015
55259
|
while (true) {
|
|
55016
|
-
if (
|
|
55260
|
+
if (lstatSync18(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
55017
55261
|
throw new Error(`Refusing symlink path: ${cursor}`);
|
|
55018
|
-
const parent =
|
|
55262
|
+
const parent = dirname15(cursor);
|
|
55019
55263
|
if (parent === cursor)
|
|
55020
55264
|
return;
|
|
55021
55265
|
cursor = parent;
|
|
@@ -55024,16 +55268,16 @@ function assertSafePath(path) {
|
|
|
55024
55268
|
function readRootAlias(home, agent) {
|
|
55025
55269
|
assertSafePath(home);
|
|
55026
55270
|
const realHome = realpathSync5(home), alias = join29(realHome, `.${agent}`);
|
|
55027
|
-
const stat2 =
|
|
55271
|
+
const stat2 = lstatSync18(alias, { throwIfNoEntry: false, bigint: true });
|
|
55028
55272
|
if (!stat2?.isSymbolicLink())
|
|
55029
55273
|
throw new Error(`Agent root alias changed after planning: ${alias}`);
|
|
55030
|
-
const link2 = readlinkSync2(alias), targetPath =
|
|
55274
|
+
const link2 = readlinkSync2(alias), targetPath = resolve16(dirname15(alias), link2);
|
|
55031
55275
|
assertSafePath(targetPath);
|
|
55032
|
-
const targetStat =
|
|
55276
|
+
const targetStat = lstatSync18(targetPath, { throwIfNoEntry: false });
|
|
55033
55277
|
if (!targetStat?.isDirectory())
|
|
55034
55278
|
throw new Error(`Agent root alias must target an existing directory: ${alias}`);
|
|
55035
55279
|
const target = realpathSync5(targetPath), inside = relative5(realHome, target);
|
|
55036
|
-
if (!inside || inside === ".." || inside.startsWith(`..${sep6}`) ||
|
|
55280
|
+
if (!inside || inside === ".." || inside.startsWith(`..${sep6}`) || isAbsolute15(inside))
|
|
55037
55281
|
throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
|
|
55038
55282
|
return { agent, home: realHome, alias, target, link: link2, aliasIdentity: `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
|
|
55039
55283
|
}
|
|
@@ -55042,14 +55286,14 @@ function rootAliases(home, allowed = false) {
|
|
|
55042
55286
|
return [];
|
|
55043
55287
|
const result2 = [];
|
|
55044
55288
|
for (const agent of ["claude", "codex"])
|
|
55045
|
-
if (
|
|
55289
|
+
if (lstatSync18(join29(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
|
|
55046
55290
|
result2.push(readRootAlias(home, agent));
|
|
55047
55291
|
if (result2.some((item, index) => result2.slice(index + 1).some((other) => item.target === other.target || item.target.startsWith(other.target + sep6) || other.target.startsWith(item.target + sep6))))
|
|
55048
55292
|
throw new Error("Agent root alias targets must not overlap");
|
|
55049
55293
|
return result2;
|
|
55050
55294
|
}
|
|
55051
55295
|
function canonicalAgentPath(path, aliases) {
|
|
55052
|
-
const absolute =
|
|
55296
|
+
const absolute = resolve16(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep6));
|
|
55053
55297
|
return binding ? join29(binding.target, relative5(binding.alias, absolute)) : absolute;
|
|
55054
55298
|
}
|
|
55055
55299
|
function recheckRootAliases(aliases) {
|
|
@@ -55063,35 +55307,35 @@ function recheckRootAliases(aliases) {
|
|
|
55063
55307
|
}
|
|
55064
55308
|
function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
|
|
55065
55309
|
assertSafePath(path);
|
|
55066
|
-
const before2 =
|
|
55310
|
+
const before2 = lstatSync18(path);
|
|
55067
55311
|
if (!before2.isFile() || before2.size > maximum)
|
|
55068
55312
|
throw new Error("Unsupported or oversized native skill file");
|
|
55069
|
-
const descriptor =
|
|
55313
|
+
const descriptor = openSync11(path, constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
|
|
55070
55314
|
try {
|
|
55071
|
-
const opened =
|
|
55315
|
+
const opened = fstatSync11(descriptor);
|
|
55072
55316
|
if (!opened.isFile() || opened.dev !== before2.dev || opened.ino !== before2.ino || opened.size !== before2.size)
|
|
55073
55317
|
throw new Error("Native skill file changed while reading");
|
|
55074
55318
|
const bytes = Buffer.allocUnsafe(before2.size + 1);
|
|
55075
55319
|
let length = 0;
|
|
55076
55320
|
while (length < bytes.length) {
|
|
55077
|
-
const count =
|
|
55321
|
+
const count = readSync9(descriptor, bytes, length, bytes.length - length, null);
|
|
55078
55322
|
if (!count)
|
|
55079
55323
|
break;
|
|
55080
55324
|
length += count;
|
|
55081
55325
|
}
|
|
55082
|
-
const after2 =
|
|
55326
|
+
const after2 = fstatSync11(descriptor);
|
|
55083
55327
|
if (length !== before2.size || after2.size !== before2.size || after2.mtimeMs !== opened.mtimeMs || after2.ctimeMs !== opened.ctimeMs)
|
|
55084
55328
|
throw new Error("Native skill file changed while reading");
|
|
55085
55329
|
return bytes.subarray(0, length);
|
|
55086
55330
|
} finally {
|
|
55087
|
-
|
|
55331
|
+
closeSync11(descriptor);
|
|
55088
55332
|
}
|
|
55089
55333
|
}
|
|
55090
55334
|
function treeHash(root2) {
|
|
55091
|
-
const hash2 =
|
|
55335
|
+
const hash2 = createHash14("sha256");
|
|
55092
55336
|
let bytes = 0, files = 0;
|
|
55093
55337
|
function visit2(path) {
|
|
55094
|
-
const stat2 =
|
|
55338
|
+
const stat2 = lstatSync18(path);
|
|
55095
55339
|
if (stat2.isSymbolicLink())
|
|
55096
55340
|
throw new Error(`Refusing symlink in skill: ${path}`);
|
|
55097
55341
|
const rel = relative5(root2, path);
|
|
@@ -55117,11 +55361,11 @@ function treeHash(root2) {
|
|
|
55117
55361
|
function projectAncestorDirectories(projects) {
|
|
55118
55362
|
const directories = new Set;
|
|
55119
55363
|
for (const project of projects) {
|
|
55120
|
-
for (let path =
|
|
55364
|
+
for (let path = resolve16(project), depth = 0;; depth++) {
|
|
55121
55365
|
if (depth >= 100)
|
|
55122
55366
|
throw new Error("NATIVE_SKILL_DRIFT: project ancestor discovery limit exceeded");
|
|
55123
55367
|
directories.add(path);
|
|
55124
|
-
const parent =
|
|
55368
|
+
const parent = dirname15(path);
|
|
55125
55369
|
if (parent === path)
|
|
55126
55370
|
break;
|
|
55127
55371
|
path = parent;
|
|
@@ -55148,10 +55392,10 @@ function inventoryNativeSkills(home = homedir4(), options = {}) {
|
|
|
55148
55392
|
throw new Error("Native skill discovery metadata limit exceeded");
|
|
55149
55393
|
}
|
|
55150
55394
|
function emptySiblingCacheAlias(path, parent) {
|
|
55151
|
-
const link2 = readlinkSync2(path), target =
|
|
55152
|
-
if (
|
|
55395
|
+
const link2 = readlinkSync2(path), target = resolve16(parent, link2);
|
|
55396
|
+
if (dirname15(target) !== parent || (isAbsolute15(link2) ? link2 !== target : dirname15(link2) !== "."))
|
|
55153
55397
|
return false;
|
|
55154
|
-
if (!
|
|
55398
|
+
if (!lstatSync18(target, { throwIfNoEntry: false })?.isDirectory())
|
|
55155
55399
|
return false;
|
|
55156
55400
|
const scan = cacheScans.get(target);
|
|
55157
55401
|
return Boolean(scan?.complete && !scan.hasSkills && scan.entries <= maxAliasProofEntries);
|
|
@@ -55163,7 +55407,7 @@ function inventoryNativeSkills(home = homedir4(), options = {}) {
|
|
|
55163
55407
|
assertSafePath(path);
|
|
55164
55408
|
if (!existsSync15(path))
|
|
55165
55409
|
return scan;
|
|
55166
|
-
const stat2 =
|
|
55410
|
+
const stat2 = lstatSync18(path);
|
|
55167
55411
|
if (stat2.isFile())
|
|
55168
55412
|
return scan;
|
|
55169
55413
|
if (!stat2.isDirectory())
|
|
@@ -55182,7 +55426,7 @@ function inventoryNativeSkills(home = homedir4(), options = {}) {
|
|
|
55182
55426
|
}
|
|
55183
55427
|
const bridge = !vendor && isOwnedCliBridge(path, bridgePaths);
|
|
55184
55428
|
const rootAlias = aliases.find((item) => path === item.target || path.startsWith(item.target + sep6));
|
|
55185
|
-
entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" && path.startsWith(canonicalAgentPath(join29(home, ".codex", "skills", ".system"), aliases) + sep6) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome:
|
|
55429
|
+
entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" && path.startsWith(canonicalAgentPath(join29(home, ".codex", "skills", ".system"), aliases) + sep6) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome: resolve16(home) } : {}, ...rootAlias ? { rootAlias } : {} });
|
|
55186
55430
|
return scan;
|
|
55187
55431
|
}
|
|
55188
55432
|
if (depth > (vendor ? 32 : 3))
|
|
@@ -55209,7 +55453,7 @@ function inventoryNativeSkills(home = homedir4(), options = {}) {
|
|
|
55209
55453
|
if (isVendor && !options.includeVendor)
|
|
55210
55454
|
continue;
|
|
55211
55455
|
const child = join29(path, name);
|
|
55212
|
-
if (isVendor &&
|
|
55456
|
+
if (isVendor && lstatSync18(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
|
|
55213
55457
|
const target = statSync8(child, { throwIfNoEntry: false });
|
|
55214
55458
|
if (target?.isFile() || pluginCache && target?.isDirectory() && emptySiblingCacheAlias(child, path)) {
|
|
55215
55459
|
scan.entries++;
|
|
@@ -55331,7 +55575,7 @@ function configureHooks(config, agent, command, profileId, nativeReady) {
|
|
|
55331
55575
|
function disableCodexSkills(text2, skills, aliases, bridgePath) {
|
|
55332
55576
|
const bundled = disableCodexBundledSkills(text2);
|
|
55333
55577
|
let result2 = bundled;
|
|
55334
|
-
const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [
|
|
55578
|
+
const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [resolve16(bridgePath), resolve16(join29(bridgePath, "SKILL.md"))].includes(canonicalAgentPath(entry.path, aliases));
|
|
55335
55579
|
const previousConfig = Bun.TOML.parse(bundled).skills?.config;
|
|
55336
55580
|
if (previousConfig !== undefined && (!Array.isArray(previousConfig) || previousConfig.some((entry) => !entry || typeof entry !== "object" || entry.path !== undefined && entry.name !== undefined)))
|
|
55337
55581
|
throw new Error("Codex skill controls require one path or name selector per [[skills.config]] entry; review ambiguous entries before running skills hook install");
|
|
@@ -55343,7 +55587,7 @@ function disableCodexSkills(text2, skills, aliases, bridgePath) {
|
|
|
55343
55587
|
result2 = result2.replace(CODEX_SKILL_CONFIG_SECTIONS, (section) => {
|
|
55344
55588
|
const parsed = Bun.TOML.parse(section);
|
|
55345
55589
|
const declared = parsed.skills?.config?.[0];
|
|
55346
|
-
if (!declared || !(skill.enabled && bridgeSelector(declared)) && !(typeof declared.path === "string" && [
|
|
55590
|
+
if (!declared || !(skill.enabled && bridgeSelector(declared)) && !(typeof declared.path === "string" && [resolve16(path), resolve16(skill.path)].includes(canonicalAgentPath(declared.path, aliases))))
|
|
55347
55591
|
return section;
|
|
55348
55592
|
found = true;
|
|
55349
55593
|
return /^\s*enabled\s*=/m.test(section) ? section.replace(/^\s*enabled\s*=.*$/m, `enabled = ${skill.enabled}`) : `${section.trimEnd()}
|
|
@@ -55461,7 +55705,7 @@ function planAgentIntegration(options) {
|
|
|
55461
55705
|
version: CLI_BRIDGE_VERSION,
|
|
55462
55706
|
digest: CLI_BRIDGE_DIGEST,
|
|
55463
55707
|
agents: [...new Set([...priorAgents, ...options.agents])].sort(),
|
|
55464
|
-
home:
|
|
55708
|
+
home: resolve16(home),
|
|
55465
55709
|
includeVendor: true,
|
|
55466
55710
|
...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join29(dataDir3, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha(renderHermesSupervisor(bindings.get("hermes").command, bindings.get("hermes").profileId)) } } } : {},
|
|
55467
55711
|
commands: { ...policy.bridge?.commands, ...Object.fromEntries([...bindings].map(([agent, binding]) => [agent, binding.command])) },
|
|
@@ -55478,7 +55722,7 @@ function planAgentIntegration(options) {
|
|
|
55478
55722
|
}
|
|
55479
55723
|
function atomicWrite2(path, content) {
|
|
55480
55724
|
assertSafePath(path);
|
|
55481
|
-
mkdirSync7(
|
|
55725
|
+
mkdirSync7(dirname15(path), { recursive: true, mode: 448 });
|
|
55482
55726
|
const temporary = `${path}.skills-${randomUUID6()}`;
|
|
55483
55727
|
try {
|
|
55484
55728
|
writeFileSync5(temporary, content, { mode: 384, flag: "wx" });
|
|
@@ -55491,10 +55735,10 @@ function atomicWrite2(path, content) {
|
|
|
55491
55735
|
function applyAgentIntegration(plan) {
|
|
55492
55736
|
const policyPath = join29(plan.dataDir, "agent-policy.json");
|
|
55493
55737
|
assertSafePath(policyPath);
|
|
55494
|
-
const currentText = (path) =>
|
|
55738
|
+
const currentText = (path) => resolve16(path) === resolve16(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
|
|
55495
55739
|
readManagedSkillPolicySnapshot(plan.dataDir);
|
|
55496
55740
|
for (const change of plan.changes)
|
|
55497
|
-
if (
|
|
55741
|
+
if (resolve16(change.path) === resolve16(policyPath))
|
|
55498
55742
|
parseManagedSkillPolicy(change.after);
|
|
55499
55743
|
const aliases = plan.rootAliases ?? [];
|
|
55500
55744
|
recheckRootAliases(aliases);
|
|
@@ -55524,7 +55768,7 @@ function applyAgentIntegration(plan) {
|
|
|
55524
55768
|
recheckRootAliases(aliases);
|
|
55525
55769
|
if (currentText(change.path) !== change.before)
|
|
55526
55770
|
throw new Error(`Configuration changed after planning: ${change.path}`);
|
|
55527
|
-
for (let directory =
|
|
55771
|
+
for (let directory = dirname15(change.path);!existsSync15(directory); directory = dirname15(directory))
|
|
55528
55772
|
createdDirectories.add(directory);
|
|
55529
55773
|
const after2 = change.after;
|
|
55530
55774
|
atomicWrite2(change.path, after2);
|
|
@@ -55564,11 +55808,11 @@ function applyAgentIntegration(plan) {
|
|
|
55564
55808
|
}
|
|
55565
55809
|
function syncArchiveDirectory(path) {
|
|
55566
55810
|
assertSafePath(path);
|
|
55567
|
-
const descriptor =
|
|
55811
|
+
const descriptor = openSync11(path, constants11.O_RDONLY | constants11.O_DIRECTORY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
|
|
55568
55812
|
try {
|
|
55569
55813
|
fsyncSync3(descriptor);
|
|
55570
55814
|
} finally {
|
|
55571
|
-
|
|
55815
|
+
closeSync11(descriptor);
|
|
55572
55816
|
}
|
|
55573
55817
|
}
|
|
55574
55818
|
function writeArchiveJournal(path, value) {
|
|
@@ -55576,18 +55820,18 @@ function writeArchiveJournal(path, value) {
|
|
|
55576
55820
|
const temporary = `${path}.skills-${randomUUID6()}`;
|
|
55577
55821
|
let descriptor;
|
|
55578
55822
|
try {
|
|
55579
|
-
descriptor =
|
|
55823
|
+
descriptor = openSync11(temporary, constants11.O_WRONLY | constants11.O_CREAT | constants11.O_EXCL | constants11.O_NOFOLLOW, 384);
|
|
55580
55824
|
writeFileSync5(descriptor, `${JSON.stringify(value)}
|
|
55581
55825
|
`);
|
|
55582
55826
|
fsyncSync3(descriptor);
|
|
55583
|
-
|
|
55827
|
+
closeSync11(descriptor);
|
|
55584
55828
|
descriptor = undefined;
|
|
55585
55829
|
renameSync4(temporary, path);
|
|
55586
|
-
syncArchiveDirectory(
|
|
55830
|
+
syncArchiveDirectory(dirname15(path));
|
|
55587
55831
|
} finally {
|
|
55588
55832
|
if (descriptor !== undefined)
|
|
55589
|
-
|
|
55590
|
-
if (
|
|
55833
|
+
closeSync11(descriptor);
|
|
55834
|
+
if (lstatSync18(temporary, { throwIfNoEntry: false }))
|
|
55591
55835
|
unlinkSync4(temporary);
|
|
55592
55836
|
}
|
|
55593
55837
|
}
|
|
@@ -55620,7 +55864,7 @@ function archiveNativeSkills(inventory, options) {
|
|
|
55620
55864
|
const moved = [];
|
|
55621
55865
|
const verifyArchive = (entry) => {
|
|
55622
55866
|
assertSafePath(entry.archive);
|
|
55623
|
-
const stat2 =
|
|
55867
|
+
const stat2 = lstatSync18(entry.archive);
|
|
55624
55868
|
if (entry.discoveryOnly ? !stat2.isFile() : !stat2.isDirectory())
|
|
55625
55869
|
throw new Error("Archive type changed");
|
|
55626
55870
|
if ((entry.discoveryOnly ? sha(readNativeBytes(entry.archive)) : treeHash(entry.archive)) !== entry.hash)
|
|
@@ -55628,14 +55872,14 @@ function archiveNativeSkills(inventory, options) {
|
|
|
55628
55872
|
};
|
|
55629
55873
|
assertSafePath(archiveRoot);
|
|
55630
55874
|
const created = [];
|
|
55631
|
-
for (let path = archiveRoot;!existsSync15(path); path =
|
|
55875
|
+
for (let path = archiveRoot;!existsSync15(path); path = dirname15(path))
|
|
55632
55876
|
created.push(path);
|
|
55633
55877
|
mkdirSync7(archiveRoot, { recursive: true, mode: 448 });
|
|
55634
55878
|
try {
|
|
55635
55879
|
for (const directory of created)
|
|
55636
55880
|
syncArchiveDirectory(directory);
|
|
55637
55881
|
if (created.length)
|
|
55638
|
-
syncArchiveDirectory(
|
|
55882
|
+
syncArchiveDirectory(dirname15(created.at(-1)));
|
|
55639
55883
|
writeArchiveJournal(receiptPath, journal);
|
|
55640
55884
|
for (const [index, entry] of selected.entries()) {
|
|
55641
55885
|
recheckRootAliases(aliases);
|
|
@@ -55647,7 +55891,7 @@ function archiveNativeSkills(inventory, options) {
|
|
|
55647
55891
|
writeArchiveJournal(receiptPath, journal);
|
|
55648
55892
|
renameSync4(move.source, move.archive);
|
|
55649
55893
|
moved.push(move);
|
|
55650
|
-
syncArchiveDirectory(
|
|
55894
|
+
syncArchiveDirectory(dirname15(move.source));
|
|
55651
55895
|
syncArchiveDirectory(archiveRoot);
|
|
55652
55896
|
verifyArchive(move);
|
|
55653
55897
|
move.status = "archived";
|
|
@@ -55668,7 +55912,7 @@ function archiveNativeSkills(inventory, options) {
|
|
|
55668
55912
|
recheckRootAliases(aliases);
|
|
55669
55913
|
assertSafePath(entry.source);
|
|
55670
55914
|
assertSafePath(entry.archive);
|
|
55671
|
-
if (
|
|
55915
|
+
if (lstatSync18(entry.source, { throwIfNoEntry: false })) {
|
|
55672
55916
|
entry.status = "recovery-required";
|
|
55673
55917
|
entry.conflict = "source-occupied";
|
|
55674
55918
|
continue;
|
|
@@ -55682,10 +55926,10 @@ function archiveNativeSkills(inventory, options) {
|
|
|
55682
55926
|
}
|
|
55683
55927
|
if (entry.discoveryOnly) {
|
|
55684
55928
|
linkSync2(entry.archive, entry.source);
|
|
55685
|
-
syncArchiveDirectory(
|
|
55929
|
+
syncArchiveDirectory(dirname15(entry.source));
|
|
55686
55930
|
unlinkSync4(entry.archive);
|
|
55687
55931
|
} else {
|
|
55688
|
-
if (
|
|
55932
|
+
if (lstatSync18(entry.source, { throwIfNoEntry: false })) {
|
|
55689
55933
|
entry.status = "recovery-required";
|
|
55690
55934
|
entry.conflict = "source-occupied";
|
|
55691
55935
|
continue;
|
|
@@ -55693,7 +55937,7 @@ function archiveNativeSkills(inventory, options) {
|
|
|
55693
55937
|
renameSync4(entry.archive, entry.source);
|
|
55694
55938
|
}
|
|
55695
55939
|
entry.status = "restored";
|
|
55696
|
-
syncArchiveDirectory(
|
|
55940
|
+
syncArchiveDirectory(dirname15(entry.source));
|
|
55697
55941
|
syncArchiveDirectory(archiveRoot);
|
|
55698
55942
|
} catch {
|
|
55699
55943
|
entry.status = "recovery-required";
|
|
@@ -55713,7 +55957,7 @@ function archiveNativeSkills(inventory, options) {
|
|
|
55713
55957
|
return { entries: entries.map(({ status, conflict, ...entry }) => entry), receiptPath, ...aliases.length ? { rootAliases: aliases } : {} };
|
|
55714
55958
|
}
|
|
55715
55959
|
function assertManagedAgentBridge(agent, options = {}) {
|
|
55716
|
-
const home =
|
|
55960
|
+
const home = resolve16(options.home ?? homedir4()), dataDir3 = options.dataDir ?? getDataDirReadOnly();
|
|
55717
55961
|
assertSafePath(join29(dataDir3, "agent-policy.json"));
|
|
55718
55962
|
const snapshot = readManagedSkillPolicySnapshot(dataDir3);
|
|
55719
55963
|
if (!snapshot)
|
|
@@ -55836,7 +56080,7 @@ function assertNativeExportAllowed(dataDir3 = getDataDirReadOnly()) {
|
|
|
55836
56080
|
if (requiresCliSkillLoading(dataDir3))
|
|
55837
56081
|
throw new Error("NATIVE_SKILL_EXPORT_DISABLED: this station loads skills through the Skills CLI; use skills sync --selection-profile <id>");
|
|
55838
56082
|
}
|
|
55839
|
-
var sha = (data) =>
|
|
56083
|
+
var sha = (data) => createHash14("sha256").update(data).digest("hex"), HOOK_EVENTS, ROOTS, SKILLS_LOADING_POLICY = "Skills loading policy: discover skills with `skills list` or `skills search`, and read selected instructions with `skills load <slug>`. Use `skills sync` to refresh the shared profile. The only native skill is the owned skills-cli bridge. Create and edit payload skills in the Skills authoring workspace; do not copy payload instructions into native discovery folders. Context loading does not authorize execution; use `skills run` only when the task calls for running a skill.";
|
|
55840
56084
|
var init_agent_integration = __esm(() => {
|
|
55841
56085
|
init_config();
|
|
55842
56086
|
init_managed_policy();
|
|
@@ -56004,7 +56248,7 @@ var init_home_migration = __esm(() => {
|
|
|
56004
56248
|
import {
|
|
56005
56249
|
cpSync as cpSync2,
|
|
56006
56250
|
existsSync as existsSync17,
|
|
56007
|
-
lstatSync as
|
|
56251
|
+
lstatSync as lstatSync19,
|
|
56008
56252
|
mkdirSync as mkdirSync9,
|
|
56009
56253
|
mkdtempSync as mkdtempSync2,
|
|
56010
56254
|
readFileSync as readFileSync16,
|
|
@@ -56015,14 +56259,14 @@ import {
|
|
|
56015
56259
|
writeFileSync as writeFileSync7
|
|
56016
56260
|
} from "fs";
|
|
56017
56261
|
import { homedir as homedir5 } from "os";
|
|
56018
|
-
import { basename as
|
|
56262
|
+
import { basename as basename9, dirname as dirname16, join as join31 } from "path";
|
|
56019
56263
|
function isSkillsOwnershipMarker(marker) {
|
|
56020
56264
|
return typeof marker === "object" && marker !== null && Object.hasOwn(marker, "managedBy") && marker.managedBy === SYNC_MARKER_MANAGED_BY;
|
|
56021
56265
|
}
|
|
56022
56266
|
function hasSkillsOwnershipMarker(dir) {
|
|
56023
56267
|
const path = join31(dir, SYNC_MARKER_FILE);
|
|
56024
56268
|
try {
|
|
56025
|
-
if (!
|
|
56269
|
+
if (!lstatSync19(path).isFile())
|
|
56026
56270
|
return false;
|
|
56027
56271
|
const marker = JSON.parse(readFileSync16(path, "utf8"));
|
|
56028
56272
|
return isSkillsOwnershipMarker(marker);
|
|
@@ -56247,9 +56491,9 @@ function writeManagedSkillDir(dir, skillMd, options) {
|
|
|
56247
56491
|
const action = dirExists ? "update" : "create";
|
|
56248
56492
|
if (options.dryRun)
|
|
56249
56493
|
return { action, path: skillMdPath };
|
|
56250
|
-
const parentDir =
|
|
56494
|
+
const parentDir = dirname16(dir);
|
|
56251
56495
|
mkdirSync9(parentDir, { recursive: true });
|
|
56252
|
-
const transactionDir = mkdtempSync2(join31(parentDir, `.hasna-skills-write-${
|
|
56496
|
+
const transactionDir = mkdtempSync2(join31(parentDir, `.hasna-skills-write-${basename9(dir)}-`));
|
|
56253
56497
|
const candidateDir = join31(transactionDir, "candidate");
|
|
56254
56498
|
const backupDir = join31(transactionDir, "backup");
|
|
56255
56499
|
const candidateSkillMdPath = join31(candidateDir, "SKILL.md");
|
|
@@ -58099,7 +58343,7 @@ var _parse = (_Err) => {
|
|
|
58099
58343
|
return result2.value;
|
|
58100
58344
|
};
|
|
58101
58345
|
return fn;
|
|
58102
|
-
},
|
|
58346
|
+
}, parse7, _parseAsync = (_Err) => {
|
|
58103
58347
|
const fn = async (schema, value, _ctx, params) => {
|
|
58104
58348
|
const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
|
|
58105
58349
|
let result2 = schema._zod.run({ value, issues: [] }, ctx);
|
|
@@ -58144,16 +58388,16 @@ var _parse = (_Err) => {
|
|
|
58144
58388
|
result2 = await result2;
|
|
58145
58389
|
return result2.issues.length === 0;
|
|
58146
58390
|
}, _encode = (_Err) => {
|
|
58147
|
-
const
|
|
58391
|
+
const parse8 = _parse(_Err);
|
|
58148
58392
|
const fn = (schema, value, _ctx, _params) => {
|
|
58149
58393
|
const ctx = _ctx ? { ..._ctx, direction: "backward" } : { direction: "backward" };
|
|
58150
|
-
return
|
|
58394
|
+
return parse8(schema, value, ctx, finalizeParams(fn, _params));
|
|
58151
58395
|
};
|
|
58152
58396
|
return fn;
|
|
58153
58397
|
}, encode, _decode = (_Err) => {
|
|
58154
|
-
const
|
|
58398
|
+
const parse8 = _parse(_Err);
|
|
58155
58399
|
const fn = (schema, value, _ctx, _params) => {
|
|
58156
|
-
return
|
|
58400
|
+
return parse8(schema, value, _ctx, finalizeParams(fn, _params));
|
|
58157
58401
|
};
|
|
58158
58402
|
return fn;
|
|
58159
58403
|
}, decode, _encodeAsync = (_Err) => {
|
|
@@ -58184,7 +58428,7 @@ var init_parse = __esm(() => {
|
|
|
58184
58428
|
init_core();
|
|
58185
58429
|
init_errors();
|
|
58186
58430
|
init_util();
|
|
58187
|
-
|
|
58431
|
+
parse7 = /* @__PURE__ */ _parse($ZodRealError);
|
|
58188
58432
|
parseAsync = /* @__PURE__ */ _parseAsync($ZodRealError);
|
|
58189
58433
|
safeParse = /* @__PURE__ */ _safeParse($ZodRealError);
|
|
58190
58434
|
safeParseAsync = /* @__PURE__ */ _safeParseAsync($ZodRealError);
|
|
@@ -61109,10 +61353,10 @@ var init_schemas = __esm(() => {
|
|
|
61109
61353
|
throw new Error("implement() must be called with a function");
|
|
61110
61354
|
}
|
|
61111
61355
|
return Object.defineProperty(function(...args) {
|
|
61112
|
-
const parsedArgs = inst._def.input ?
|
|
61356
|
+
const parsedArgs = inst._def.input ? parse7(inst._def.input, args) : args;
|
|
61113
61357
|
const result2 = Reflect.apply(func, this, parsedArgs);
|
|
61114
61358
|
if (inst._def.output) {
|
|
61115
|
-
return
|
|
61359
|
+
return parse7(inst._def.output, result2);
|
|
61116
61360
|
}
|
|
61117
61361
|
return result2;
|
|
61118
61362
|
}, "_zod", { value: inst._zod, enumerable: false });
|
|
@@ -72813,7 +73057,7 @@ __export(exports_core2, {
|
|
|
72813
73057
|
prettifyError: () => prettifyError,
|
|
72814
73058
|
parseURLObject: () => parseURLObject,
|
|
72815
73059
|
parseAsync: () => parseAsync,
|
|
72816
|
-
parse: () =>
|
|
73060
|
+
parse: () => parse7,
|
|
72817
73061
|
meta: () => meta,
|
|
72818
73062
|
mergeValues: () => mergeValues,
|
|
72819
73063
|
memoizer: () => memoizer,
|
|
@@ -73203,12 +73447,12 @@ var init_errors2 = __esm(() => {
|
|
|
73203
73447
|
});
|
|
73204
73448
|
|
|
73205
73449
|
// node_modules/zod/v4/classic/parse.js
|
|
73206
|
-
var
|
|
73450
|
+
var parse9, parseAsync2, safeParse2, safeParseAsync2, encode2, decode2, encodeAsync2, decodeAsync2, safeEncode2, safeDecode2, safeEncodeAsync2, safeDecodeAsync2;
|
|
73207
73451
|
var init_parse2 = __esm(() => {
|
|
73208
73452
|
init_core2();
|
|
73209
73453
|
init_errors2();
|
|
73210
73454
|
init_core2();
|
|
73211
|
-
|
|
73455
|
+
parse9 = /* @__PURE__ */ _parse(ZodRealError);
|
|
73212
73456
|
parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
73213
73457
|
safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
73214
73458
|
safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
|
|
@@ -74009,7 +74253,7 @@ var init_schemas2 = __esm(() => {
|
|
|
74009
74253
|
exports_util.own(this, "~standard", value);
|
|
74010
74254
|
},
|
|
74011
74255
|
parse: function _parse2(data, params) {
|
|
74012
|
-
return
|
|
74256
|
+
return parse9(this, data, params, { callee: _parse2 });
|
|
74013
74257
|
},
|
|
74014
74258
|
parseAsync: async function _parseAsync2(data, params) {
|
|
74015
74259
|
return await parseAsync2(this, data, params, { callee: _parseAsync2 });
|
|
@@ -75702,7 +75946,7 @@ __export(exports_external, {
|
|
|
75702
75946
|
pipe: () => pipe,
|
|
75703
75947
|
partialRecord: () => partialRecord,
|
|
75704
75948
|
parseAsync: () => parseAsync2,
|
|
75705
|
-
parse: () =>
|
|
75949
|
+
parse: () => parse9,
|
|
75706
75950
|
overwrite: () => _overwrite,
|
|
75707
75951
|
output: () => output,
|
|
75708
75952
|
optional: () => optional,
|
|
@@ -75969,6 +76213,8 @@ function normalizeRemoteSkill(skill) {
|
|
|
75969
76213
|
tags: skill.tags || ["remote"],
|
|
75970
76214
|
dependencies: skill.dependencies,
|
|
75971
76215
|
...skill.version ? { version: skill.version } : {},
|
|
76216
|
+
...skill.revisionId !== undefined ? { revisionId: skill.revisionId } : {},
|
|
76217
|
+
...skill.lifecycle ? { lifecycle: skill.lifecycle } : {},
|
|
75972
76218
|
availability: normalizeRemoteAvailability(skill.availability),
|
|
75973
76219
|
source: "remote"
|
|
75974
76220
|
};
|
|
@@ -76086,6 +76332,8 @@ var init_remote_registry = __esm(() => {
|
|
|
76086
76332
|
tags: exports_external.array(exports_external.string()).optional(),
|
|
76087
76333
|
dependencies: exports_external.array(exports_external.string()).optional(),
|
|
76088
76334
|
version: exports_external.string().optional(),
|
|
76335
|
+
revisionId: exports_external.union([exports_external.string().regex(/^[\x21-\x7e]+$/), exports_external.null()]).optional(),
|
|
76336
|
+
lifecycle: exports_external.enum(["active", "archived"]).optional(),
|
|
76089
76337
|
availability: remoteAvailabilitySchema.optional()
|
|
76090
76338
|
}).passthrough().refine((skill) => skill.name || skill.slug, {
|
|
76091
76339
|
message: "Remote skill requires name or slug"
|
|
@@ -76183,7 +76431,7 @@ var init_v4 = __esm(() => {
|
|
|
76183
76431
|
});
|
|
76184
76432
|
|
|
76185
76433
|
// src/lib/canonical-json.ts
|
|
76186
|
-
import { createHash as
|
|
76434
|
+
import { createHash as createHash15 } from "crypto";
|
|
76187
76435
|
function canonicalJson2(value, maximumBytes = 2 * 1024 * 1024) {
|
|
76188
76436
|
return canonicalJsonAtDepth(value, maximumBytes, 64);
|
|
76189
76437
|
}
|
|
@@ -76227,7 +76475,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
|
|
|
76227
76475
|
return visit3(value, 0);
|
|
76228
76476
|
}
|
|
76229
76477
|
function canonicalJsonSha256(value, maximumBytes) {
|
|
76230
|
-
return
|
|
76478
|
+
return createHash15("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
|
|
76231
76479
|
}
|
|
76232
76480
|
var init_canonical_json = () => {};
|
|
76233
76481
|
|
|
@@ -76981,13 +77229,13 @@ var init_remote_workspace_leave = __esm(() => {
|
|
|
76981
77229
|
|
|
76982
77230
|
// src/lib/auth-store.ts
|
|
76983
77231
|
import { chmodSync as chmodSync2, existsSync as existsSync20, mkdirSync as mkdirSync11, readFileSync as readFileSync19, renameSync as renameSync7, statSync as statSync11, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
|
|
76984
|
-
import { basename as
|
|
77232
|
+
import { basename as basename10, dirname as dirname17, join as join34 } from "path";
|
|
76985
77233
|
function getAuthFilePath(env3 = process.env) {
|
|
76986
77234
|
return skillsCredentialFilePath(env3);
|
|
76987
77235
|
}
|
|
76988
77236
|
function getIdentityFilePath(env3 = process.env) {
|
|
76989
77237
|
const file2 = skillsCredentialFilePath(env3);
|
|
76990
|
-
return join34(
|
|
77238
|
+
return join34(dirname17(file2), basename10(file2).replace(/^credentials/, "identity") + ".json");
|
|
76991
77239
|
}
|
|
76992
77240
|
function getAuthIdentity(env3 = process.env) {
|
|
76993
77241
|
return readIdentity(env3);
|
|
@@ -77021,7 +77269,7 @@ function getAuthConfig(env3 = process.env, options = {}) {
|
|
|
77021
77269
|
}
|
|
77022
77270
|
function writeCredentialValues(values2, env3 = process.env) {
|
|
77023
77271
|
const file2 = skillsCredentialFilePath(env3);
|
|
77024
|
-
mkdirSync11(
|
|
77272
|
+
mkdirSync11(dirname17(file2), { recursive: true, mode: 448 });
|
|
77025
77273
|
const lines = [];
|
|
77026
77274
|
const written = new Set;
|
|
77027
77275
|
if (existsSync20(file2)) {
|
|
@@ -77359,10 +77607,10 @@ async function readQuoteUnavailableCode(response) {
|
|
|
77359
77607
|
let timer;
|
|
77360
77608
|
let deadlineExceeded = false;
|
|
77361
77609
|
const expired = Symbol("quote body deadline");
|
|
77362
|
-
const deadline = new Promise((
|
|
77610
|
+
const deadline = new Promise((resolve17) => {
|
|
77363
77611
|
timer = setTimeout(() => {
|
|
77364
77612
|
deadlineExceeded = true;
|
|
77365
|
-
|
|
77613
|
+
resolve17(expired);
|
|
77366
77614
|
reader.cancel().catch(() => {});
|
|
77367
77615
|
}, 1500);
|
|
77368
77616
|
});
|
|
@@ -77474,6 +77722,7 @@ __export(exports_remote_client, {
|
|
|
77474
77722
|
RemoteWorkspaceSelectionError: () => RemoteWorkspaceSelectionError,
|
|
77475
77723
|
RemoteWorkspaceMemberError: () => RemoteWorkspaceMemberError,
|
|
77476
77724
|
RemoteSkillsClient: () => RemoteSkillsClient,
|
|
77725
|
+
RemoteSkillLifecycleError: () => RemoteSkillLifecycleError,
|
|
77477
77726
|
RemoteRouteUnsupportedError: () => RemoteRouteUnsupportedError,
|
|
77478
77727
|
RemoteRequestError: () => RemoteRequestError,
|
|
77479
77728
|
RemoteQuoteUnavailableError: () => RemoteQuoteUnavailableError,
|
|
@@ -77605,6 +77854,39 @@ class RemoteSkillsClient {
|
|
|
77605
77854
|
})();
|
|
77606
77855
|
return this.capabilities;
|
|
77607
77856
|
}
|
|
77857
|
+
async addSkillPublishScope(keyId, expectedScopes, expectedOrgId) {
|
|
77858
|
+
if (!/^[A-Za-z0-9_-]+$/.test(keyId))
|
|
77859
|
+
throw new Error("Invalid API key id");
|
|
77860
|
+
if (!/^[A-Za-z0-9_-]{1,256}$/.test(expectedOrgId))
|
|
77861
|
+
throw new Error("Invalid expected organization id");
|
|
77862
|
+
if (!Array.isArray(expectedScopes) || expectedScopes.length > 32 || expectedScopes.some((scope) => typeof scope !== "string" || scope.length > 128 || !/^(?:\*|[a-z][a-z0-9_-]*:(?:\*|[a-z][a-z0-9_-]*))$/.test(scope)) || new Set(expectedScopes).size !== expectedScopes.length)
|
|
77863
|
+
throw new Error("Invalid expected API key scopes");
|
|
77864
|
+
const path = `/api/v1/admin/keys/${encodeURIComponent(keyId)}/scopes`;
|
|
77865
|
+
const response = await this.request(path, { method: "PATCH", body: JSON.stringify({ expected_scopes: expectedScopes, add_scopes: ["skills:publish"] }) });
|
|
77866
|
+
if (!response.ok)
|
|
77867
|
+
throw new RemoteRequestError(path, response.status);
|
|
77868
|
+
let value;
|
|
77869
|
+
try {
|
|
77870
|
+
value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readBoundedResponse(response, 64 * 1024)));
|
|
77871
|
+
} catch {
|
|
77872
|
+
throw new Error("Invalid API key scope update response");
|
|
77873
|
+
}
|
|
77874
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
77875
|
+
throw new Error("Invalid API key scope update response");
|
|
77876
|
+
const body = value;
|
|
77877
|
+
const returnedId = body.keyId;
|
|
77878
|
+
const orgId = body.orgId;
|
|
77879
|
+
const scopes = body.scopes;
|
|
77880
|
+
if (returnedId !== keyId || typeof orgId !== "string" || !orgId || expectedOrgId !== undefined && orgId !== expectedOrgId || !Array.isArray(scopes) || scopes.some((scope) => typeof scope !== "string") || body.updated !== true) {
|
|
77881
|
+
throw new Error("Invalid API key scope update response");
|
|
77882
|
+
}
|
|
77883
|
+
const returnedScopes = scopes;
|
|
77884
|
+
const expectedResult = expectedScopes.includes("skills:publish") ? expectedScopes : [...expectedScopes, "skills:publish"];
|
|
77885
|
+
if (returnedScopes.length !== expectedResult.length || expectedResult.some((scope, index) => returnedScopes[index] !== scope)) {
|
|
77886
|
+
throw new Error("API key scope update response did not preserve the expected scopes");
|
|
77887
|
+
}
|
|
77888
|
+
return { keyId, orgId, scopes: [...returnedScopes], updated: true };
|
|
77889
|
+
}
|
|
77608
77890
|
async submitQuotedRun(slug2, input2 = {}, args = [], approval = {}) {
|
|
77609
77891
|
runQuoteReceipt(approval.quoteReceipt);
|
|
77610
77892
|
({ input: input2, args, approval } = JSON.parse(JSON.stringify({ input: input2, args, approval })));
|
|
@@ -78122,6 +78404,19 @@ class RemoteSkillsClient {
|
|
|
78122
78404
|
async deleteSkill(slug2) {
|
|
78123
78405
|
return this.request(`/api/v1/skills/${encodeURIComponent(slug2)}`, { method: "DELETE" });
|
|
78124
78406
|
}
|
|
78407
|
+
async setSkillLifecycle(slug2, lifecycle, options) {
|
|
78408
|
+
const path = `/api/v1/skills/${encodeURIComponent(slug2)}/lifecycle`;
|
|
78409
|
+
const response = await this.request(path, {
|
|
78410
|
+
method: "PATCH",
|
|
78411
|
+
headers: { "If-Match": options.expectedRevisionId },
|
|
78412
|
+
body: JSON.stringify({ lifecycle, ...options.reason ? { reason: options.reason } : {}, ...options.replacementSlug ? { replacementSlug: options.replacementSlug } : {} })
|
|
78413
|
+
});
|
|
78414
|
+
if (!response.ok) {
|
|
78415
|
+
const code = await readResponseCode(response);
|
|
78416
|
+
throw new RemoteSkillLifecycleError(path, response.status, code);
|
|
78417
|
+
}
|
|
78418
|
+
return response.json();
|
|
78419
|
+
}
|
|
78125
78420
|
async downloadSkillBundle(slug2) {
|
|
78126
78421
|
return this.request(`/api/v1/skills/${encodeURIComponent(slug2)}/bundle`, { method: "GET" });
|
|
78127
78422
|
}
|
|
@@ -78273,9 +78568,13 @@ function normalizeSkillSummaryList(payload) {
|
|
|
78273
78568
|
return payload.map(normalizeSkillSummary);
|
|
78274
78569
|
}
|
|
78275
78570
|
async function responseBodyCarriesCode(response, codes) {
|
|
78571
|
+
const code = await readResponseCode(response);
|
|
78572
|
+
return code !== undefined && codes.includes(code);
|
|
78573
|
+
}
|
|
78574
|
+
async function readResponseCode(response) {
|
|
78276
78575
|
const reader = response.body?.getReader();
|
|
78277
78576
|
if (!reader)
|
|
78278
|
-
return
|
|
78577
|
+
return;
|
|
78279
78578
|
const maximum = 8 * 1024;
|
|
78280
78579
|
let deadline;
|
|
78281
78580
|
const expired = new Promise((_, reject2) => {
|
|
@@ -78290,7 +78589,7 @@ async function responseBodyCarriesCode(response, codes) {
|
|
|
78290
78589
|
break;
|
|
78291
78590
|
size2 += next.value.byteLength;
|
|
78292
78591
|
if (size2 > maximum)
|
|
78293
|
-
return
|
|
78592
|
+
return;
|
|
78294
78593
|
chunks.push(next.value);
|
|
78295
78594
|
}
|
|
78296
78595
|
const bytes = new Uint8Array(size2);
|
|
@@ -78301,11 +78600,11 @@ async function responseBodyCarriesCode(response, codes) {
|
|
|
78301
78600
|
}
|
|
78302
78601
|
const payload = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
78303
78602
|
if (!payload || typeof payload !== "object" || Array.isArray(payload) || !Object.hasOwn(payload, "code"))
|
|
78304
|
-
return
|
|
78603
|
+
return;
|
|
78305
78604
|
const code = payload.code;
|
|
78306
|
-
return typeof code === "string" &&
|
|
78605
|
+
return typeof code === "string" && /^[A-Z][A-Z0-9_:-]{0,127}$/.test(code) ? code : undefined;
|
|
78307
78606
|
} catch {
|
|
78308
|
-
return
|
|
78607
|
+
return;
|
|
78309
78608
|
} finally {
|
|
78310
78609
|
clearTimeout(deadline);
|
|
78311
78610
|
reader.cancel().catch(() => {});
|
|
@@ -78334,7 +78633,7 @@ async function createRemoteSkillsClient(env3 = process.env) {
|
|
|
78334
78633
|
function createRemoteSkillsClientReadOnly(env3 = process.env) {
|
|
78335
78634
|
return createRemoteSkillsClient(env3);
|
|
78336
78635
|
}
|
|
78337
|
-
var RemoteRouteUnsupportedError, RemoteRequestError, RemoteCreditCheckoutError, RemoteQuoteUnavailableError, RemoteWorkspaceMemberError, RemoteWorkspaceSelectionError, RemoteCapabilityUnavailableError, INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
|
|
78636
|
+
var RemoteRouteUnsupportedError, RemoteRequestError, KNOWN_SKILL_LIFECYCLE_CODES, RemoteSkillLifecycleError, RemoteCreditCheckoutError, RemoteQuoteUnavailableError, RemoteWorkspaceMemberError, RemoteWorkspaceSelectionError, RemoteCapabilityUnavailableError, INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
|
|
78338
78637
|
var init_remote_client = __esm(() => {
|
|
78339
78638
|
init_remote_recurring();
|
|
78340
78639
|
init_remote_invitations();
|
|
@@ -78371,6 +78670,17 @@ var init_remote_client = __esm(() => {
|
|
|
78371
78670
|
this.name = "RemoteRequestError";
|
|
78372
78671
|
}
|
|
78373
78672
|
};
|
|
78673
|
+
KNOWN_SKILL_LIFECYCLE_CODES = new Set(["SKILL_ARCHIVE_PROFILE_CONFLICT", "LIFECYCLE_ROLE_REQUIRED"]);
|
|
78674
|
+
RemoteSkillLifecycleError = class RemoteSkillLifecycleError extends RemoteRequestError {
|
|
78675
|
+
code;
|
|
78676
|
+
constructor(path, status, code) {
|
|
78677
|
+
super(path, status);
|
|
78678
|
+
this.name = "RemoteSkillLifecycleError";
|
|
78679
|
+
const safeCode = code !== undefined && KNOWN_SKILL_LIFECYCLE_CODES.has(code) ? code : undefined;
|
|
78680
|
+
this.code = safeCode;
|
|
78681
|
+
this.message = `Skill lifecycle update was refused (HTTP ${status}${safeCode ? `, code ${safeCode}` : ""})`;
|
|
78682
|
+
}
|
|
78683
|
+
};
|
|
78374
78684
|
RemoteCreditCheckoutError = class RemoteCreditCheckoutError extends RemoteRequestError {
|
|
78375
78685
|
code;
|
|
78376
78686
|
requestIdempotencyKey;
|
|
@@ -78424,9 +78734,9 @@ var init_remote_client = __esm(() => {
|
|
|
78424
78734
|
});
|
|
78425
78735
|
|
|
78426
78736
|
// src/lib/revision.ts
|
|
78427
|
-
import { createHash as
|
|
78737
|
+
import { createHash as createHash16 } from "crypto";
|
|
78428
78738
|
function revisionIdOf(content) {
|
|
78429
|
-
const
|
|
78739
|
+
const canonicalContent = {
|
|
78430
78740
|
slug: content.slug,
|
|
78431
78741
|
displayName: content.displayName,
|
|
78432
78742
|
description: content.description,
|
|
@@ -78438,8 +78748,14 @@ function revisionIdOf(content) {
|
|
|
78438
78748
|
skillMd: content.skillMd ?? null,
|
|
78439
78749
|
bundleSha256: content.bundleSha256 ?? null,
|
|
78440
78750
|
bundleByteSize: content.bundleByteSize ?? null
|
|
78441
|
-
}
|
|
78442
|
-
|
|
78751
|
+
};
|
|
78752
|
+
if (content.lifecycle === "archived" || content.archiveReason !== undefined || content.replacementSlug !== undefined) {
|
|
78753
|
+
canonicalContent.lifecycle = content.lifecycle ?? "active";
|
|
78754
|
+
canonicalContent.archiveReason = content.archiveReason ?? null;
|
|
78755
|
+
canonicalContent.replacementSlug = content.replacementSlug ?? null;
|
|
78756
|
+
}
|
|
78757
|
+
const canonical4 = JSON.stringify(canonicalContent);
|
|
78758
|
+
return createHash16("sha256").update(canonical4).digest("hex");
|
|
78443
78759
|
}
|
|
78444
78760
|
var REVISION_ID_PATTERN;
|
|
78445
78761
|
var init_revision = __esm(() => {
|
|
@@ -78469,7 +78785,7 @@ var init_skill_bundles = __esm(() => {
|
|
|
78469
78785
|
|
|
78470
78786
|
// src/lib/pull.ts
|
|
78471
78787
|
import { existsSync as existsSync21, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readFileSync as readFileSync20, renameSync as renameSync8, rmSync as rmSync6, writeFileSync as writeFileSync10 } from "fs";
|
|
78472
|
-
import { dirname as
|
|
78788
|
+
import { dirname as dirname18, join as join35 } from "path";
|
|
78473
78789
|
async function pullSkills(options = {}) {
|
|
78474
78790
|
const client2 = options.client !== undefined ? options.client : await createRemoteSkillsClient();
|
|
78475
78791
|
if (!client2) {
|
|
@@ -78773,7 +79089,7 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
|
|
|
78773
79089
|
try {
|
|
78774
79090
|
for (const entry of entries) {
|
|
78775
79091
|
const destination = join35(staging, entry.path);
|
|
78776
|
-
mkdirSync12(
|
|
79092
|
+
mkdirSync12(dirname18(destination), { recursive: true });
|
|
78777
79093
|
writeFileSync10(destination, entry.bytes, { mode: entry.mode });
|
|
78778
79094
|
}
|
|
78779
79095
|
writePullMarker(staging, {
|
|
@@ -78888,8 +79204,8 @@ var init_pull = __esm(() => {
|
|
|
78888
79204
|
});
|
|
78889
79205
|
|
|
78890
79206
|
// src/lib/skill-context.ts
|
|
78891
|
-
import { createHash as
|
|
78892
|
-
import { resolve as
|
|
79207
|
+
import { createHash as createHash17 } from "crypto";
|
|
79208
|
+
import { resolve as resolve17 } from "path";
|
|
78893
79209
|
function words2(value) {
|
|
78894
79210
|
return new Set(value.toLowerCase().match(/[a-z0-9]+/g) ?? []);
|
|
78895
79211
|
}
|
|
@@ -78924,7 +79240,7 @@ async function buildSkillContext(input2, options = {}) {
|
|
|
78924
79240
|
const promptWords = words2(prompt);
|
|
78925
79241
|
const promptNames = new Set(prompt.toLowerCase().match(/[a-z0-9]+(?:-[a-z0-9]+)*/g) ?? []);
|
|
78926
79242
|
const loaded = new Set(resolved.session?.loaded ?? []);
|
|
78927
|
-
const paths = [...input2.paths ?? [], ...input2.cwd ? [input2.cwd,
|
|
79243
|
+
const paths = [...input2.paths ?? [], ...input2.cwd ? [input2.cwd, resolve17(input2.cwd)] : []];
|
|
78928
79244
|
const candidates = profile.selections.map((selection) => {
|
|
78929
79245
|
const key = selectionKey(selection);
|
|
78930
79246
|
if (input2.restore && loaded.has(key))
|
|
@@ -78977,7 +79293,7 @@ ${content}`;
|
|
|
78977
79293
|
`);
|
|
78978
79294
|
const receipt = {
|
|
78979
79295
|
schemaVersion: 1,
|
|
78980
|
-
id:
|
|
79296
|
+
id: createHash17("sha256").update(JSON.stringify({ profile: profile.profileRevision, sessionId, selections, omitted })).digest("hex"),
|
|
78981
79297
|
profileId: profile.profileId,
|
|
78982
79298
|
profileRevision: profile.profileRevision,
|
|
78983
79299
|
authority: profile.authority,
|
|
@@ -78999,7 +79315,7 @@ var init_skill_context = __esm(() => {
|
|
|
78999
79315
|
});
|
|
79000
79316
|
|
|
79001
79317
|
// src/lib/session-reconciliation.ts
|
|
79002
|
-
import { createHash as
|
|
79318
|
+
import { createHash as createHash18 } from "crypto";
|
|
79003
79319
|
function exactTimestamp(value) {
|
|
79004
79320
|
const parsed = value === undefined ? Number.NaN : Date.parse(value);
|
|
79005
79321
|
if (!Number.isFinite(parsed) || new Date(parsed).toISOString() !== value) {
|
|
@@ -79092,7 +79408,7 @@ async function reconcileSkillSession(input2, options = {}) {
|
|
|
79092
79408
|
const result2 = replaceSkillSession(skillSessionSnapshotBinding(snapshot), replacement, { ...plan, planDigest }, options, () => assertPlanWindow(issuedAt, expiresAt, (options.now ?? Date.now)()));
|
|
79093
79409
|
return { applied: true, plan, planDigest, ...result2 };
|
|
79094
79410
|
}
|
|
79095
|
-
var SESSION_RECONCILIATION_PLAN_TTL_MS, digest3 = (value) =>
|
|
79411
|
+
var SESSION_RECONCILIATION_PLAN_TTL_MS, digest3 = (value) => createHash18("sha256").update(JSON.stringify(value)).digest("hex");
|
|
79096
79412
|
var init_session_reconciliation = __esm(() => {
|
|
79097
79413
|
init_profile_client();
|
|
79098
79414
|
init_selection_cache();
|
|
@@ -79108,7 +79424,7 @@ __export(exports_context, {
|
|
|
79108
79424
|
parseSkillContextInput: () => parseSkillContextInput,
|
|
79109
79425
|
contextResolverOptions: () => contextResolverOptions
|
|
79110
79426
|
});
|
|
79111
|
-
import { readSync as
|
|
79427
|
+
import { readSync as readSync10 } from "fs";
|
|
79112
79428
|
function selectedProfileId(explicit) {
|
|
79113
79429
|
return explicit ?? process.env.HASNA_SKILLS_SELECTION_PROFILE ?? readManagedSkillPolicy()?.profileId ?? "default";
|
|
79114
79430
|
}
|
|
@@ -79186,7 +79502,7 @@ async function readContextStdin() {
|
|
|
79186
79502
|
let size2 = 0;
|
|
79187
79503
|
while (true) {
|
|
79188
79504
|
const chunk2 = Buffer.allocUnsafe(8192);
|
|
79189
|
-
const count =
|
|
79505
|
+
const count = readSync10(0, chunk2, 0, chunk2.length, null);
|
|
79190
79506
|
if (count === 0)
|
|
79191
79507
|
break;
|
|
79192
79508
|
size2 += count;
|
|
@@ -79663,12 +79979,12 @@ function handleBrowseError(error61) {
|
|
|
79663
79979
|
async function writeJson(value, space) {
|
|
79664
79980
|
const text3 = `${JSON.stringify(value, null, space)}
|
|
79665
79981
|
`;
|
|
79666
|
-
await new Promise((
|
|
79982
|
+
await new Promise((resolve18, reject2) => {
|
|
79667
79983
|
process.stdout.write(text3, (error61) => {
|
|
79668
79984
|
if (error61)
|
|
79669
79985
|
reject2(error61);
|
|
79670
79986
|
else
|
|
79671
|
-
|
|
79987
|
+
resolve18();
|
|
79672
79988
|
});
|
|
79673
79989
|
});
|
|
79674
79990
|
}
|
|
@@ -80200,7 +80516,7 @@ function handleDiff(name, options) {
|
|
|
80200
80516
|
const sourcePath = getSkillPath(bare);
|
|
80201
80517
|
const canonicalDir = join36(resolveCorpusRoot(), normalized);
|
|
80202
80518
|
const canonicalSkillMd = join36(canonicalDir, "SKILL.md");
|
|
80203
|
-
const
|
|
80519
|
+
const canonical4 = {
|
|
80204
80520
|
present: existsSync22(canonicalSkillMd),
|
|
80205
80521
|
path: canonicalDir,
|
|
80206
80522
|
...existsSync22(canonicalSkillMd) ? { hash: hashSkillMarkdownFile(canonicalSkillMd) } : {},
|
|
@@ -80232,7 +80548,7 @@ function handleDiff(name, options) {
|
|
|
80232
80548
|
stub = undefined;
|
|
80233
80549
|
}
|
|
80234
80550
|
}
|
|
80235
|
-
const diverged = present &&
|
|
80551
|
+
const diverged = present && canonical4.present && managed && hash3 !== canonical4.hash;
|
|
80236
80552
|
homes.push({
|
|
80237
80553
|
agent,
|
|
80238
80554
|
path: dir,
|
|
@@ -80247,7 +80563,7 @@ function handleDiff(name, options) {
|
|
|
80247
80563
|
if (options.json) {
|
|
80248
80564
|
console.log(JSON.stringify({
|
|
80249
80565
|
name: bare,
|
|
80250
|
-
canonical:
|
|
80566
|
+
canonical: canonical4,
|
|
80251
80567
|
pinned,
|
|
80252
80568
|
installedVersion,
|
|
80253
80569
|
registryVersion,
|
|
@@ -80255,10 +80571,10 @@ function handleDiff(name, options) {
|
|
|
80255
80571
|
homes
|
|
80256
80572
|
}, null, 2));
|
|
80257
80573
|
} else {
|
|
80258
|
-
if (!
|
|
80574
|
+
if (!canonical4.present) {
|
|
80259
80575
|
console.log(source_default.yellow(`${bare}: no canonical corpus entry`));
|
|
80260
80576
|
} else {
|
|
80261
|
-
console.log(source_default.dim(`${bare} canonical: ${
|
|
80577
|
+
console.log(source_default.dim(`${bare} canonical: ${canonical4.hash?.slice(0, 12)}\u2026`));
|
|
80262
80578
|
}
|
|
80263
80579
|
if (pinned) {
|
|
80264
80580
|
console.log(upToDate ? source_default.green(`\u2713 pin is up to date (${installedVersion})`) : source_default.yellow(`pin metadata differs: ${installedVersion} \u2192 ${registryVersion}`));
|
|
@@ -80269,14 +80585,14 @@ function handleDiff(name, options) {
|
|
|
80269
80585
|
} else if (!home.managed) {
|
|
80270
80586
|
console.log(`${source_default.dim("\u2022")} ${home.agent}: ${source_default.yellow("unmarked (adoption candidate)")}`);
|
|
80271
80587
|
} else if (home.diverged) {
|
|
80272
|
-
const stubNote = home.stub === true ? " (home is a pointer stub; canonical holds content)" :
|
|
80273
|
-
console.log(`${source_default.red("\u2717")} ${home.agent}: ${source_default.red("diverged")} ${source_default.dim(home.hash?.slice(0, 12))} \u2260 ${source_default.dim(
|
|
80588
|
+
const stubNote = home.stub === true ? " (home is a pointer stub; canonical holds content)" : canonical4.stub === true ? " (home holds content; canonical renders a pointer stub \u2014 sync refuses to replace it)" : "";
|
|
80589
|
+
console.log(`${source_default.red("\u2717")} ${home.agent}: ${source_default.red("diverged")} ${source_default.dim(home.hash?.slice(0, 12))} \u2260 ${source_default.dim(canonical4.hash?.slice(0, 12))}${stubNote}`);
|
|
80274
80590
|
} else {
|
|
80275
80591
|
console.log(`${source_default.green("\u2713")} ${home.agent}: ${source_default.green("matches canonical")}`);
|
|
80276
80592
|
}
|
|
80277
80593
|
}
|
|
80278
80594
|
}
|
|
80279
|
-
if (divergedHomes.length > 0 || homes.length > 0 && !
|
|
80595
|
+
if (divergedHomes.length > 0 || homes.length > 0 && !canonical4.present)
|
|
80280
80596
|
process.exitCode = 1;
|
|
80281
80597
|
}
|
|
80282
80598
|
var init_introspect = __esm(() => {
|
|
@@ -81012,7 +81328,7 @@ var init_init = __esm(() => {
|
|
|
81012
81328
|
});
|
|
81013
81329
|
|
|
81014
81330
|
// src/lib/home-adoption.ts
|
|
81015
|
-
import { constants as
|
|
81331
|
+
import { constants as constants12, closeSync as closeSync12, fstatSync as fstatSync12, lstatSync as lstatSync20, openSync as openSync12, readSync as readSync11, existsSync as existsSync24, mkdirSync as mkdirSync13, readdirSync as readdirSync13, readFileSync as readFileSync25, rmSync as rmSync7, statSync as statSync12, writeFileSync as writeFileSync12 } from "fs";
|
|
81016
81332
|
import { homedir as homedir7 } from "os";
|
|
81017
81333
|
import { join as join38 } from "path";
|
|
81018
81334
|
function indexCanonicalCorpus(corpusRoot) {
|
|
@@ -81167,25 +81483,25 @@ function adoptUnmarkedHomes(options = {}) {
|
|
|
81167
81483
|
function pruneOwnership(dir) {
|
|
81168
81484
|
let descriptor;
|
|
81169
81485
|
try {
|
|
81170
|
-
const directory =
|
|
81486
|
+
const directory = lstatSync20(dir);
|
|
81171
81487
|
if (!directory.isDirectory())
|
|
81172
81488
|
return;
|
|
81173
|
-
const markerPath = join38(dir, SYNC_MARKER_FILE), markerPathBefore =
|
|
81489
|
+
const markerPath = join38(dir, SYNC_MARKER_FILE), markerPathBefore = lstatSync20(markerPath);
|
|
81174
81490
|
if (!markerPathBefore.isFile())
|
|
81175
81491
|
return;
|
|
81176
|
-
descriptor =
|
|
81177
|
-
const before2 =
|
|
81492
|
+
descriptor = openSync12(markerPath, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
|
|
81493
|
+
const before2 = fstatSync12(descriptor);
|
|
81178
81494
|
if (!before2.isFile() || before2.dev !== markerPathBefore.dev || before2.ino !== markerPathBefore.ino || before2.size !== markerPathBefore.size || before2.mtimeMs !== markerPathBefore.mtimeMs || before2.ctimeMs !== markerPathBefore.ctimeMs || before2.size < 1 || before2.size > 65536)
|
|
81179
81495
|
return;
|
|
81180
81496
|
const bytes = Buffer.alloc(before2.size + 1);
|
|
81181
81497
|
let length = 0;
|
|
81182
81498
|
while (length < bytes.length) {
|
|
81183
|
-
const count =
|
|
81499
|
+
const count = readSync11(descriptor, bytes, length, bytes.length - length, length);
|
|
81184
81500
|
if (!count)
|
|
81185
81501
|
break;
|
|
81186
81502
|
length += count;
|
|
81187
81503
|
}
|
|
81188
|
-
const after2 =
|
|
81504
|
+
const after2 = fstatSync12(descriptor), current = lstatSync20(dir), markerPathAfter = lstatSync20(markerPath);
|
|
81189
81505
|
if (!markerPathAfter.isFile() || markerPathAfter.dev !== before2.dev || markerPathAfter.ino !== before2.ino || markerPathAfter.size !== before2.size || markerPathAfter.mtimeMs !== before2.mtimeMs || markerPathAfter.ctimeMs !== before2.ctimeMs || length !== before2.size || after2.size !== before2.size || after2.mtimeMs !== before2.mtimeMs || after2.ctimeMs !== before2.ctimeMs || !current.isDirectory() || current.dev !== directory.dev || current.ino !== directory.ino)
|
|
81190
81506
|
return;
|
|
81191
81507
|
const text3 = bytes.subarray(0, length).toString("utf8"), marker = JSON.parse(text3);
|
|
@@ -81196,7 +81512,7 @@ function pruneOwnership(dir) {
|
|
|
81196
81512
|
return;
|
|
81197
81513
|
} finally {
|
|
81198
81514
|
if (descriptor !== undefined)
|
|
81199
|
-
|
|
81515
|
+
closeSync12(descriptor);
|
|
81200
81516
|
}
|
|
81201
81517
|
}
|
|
81202
81518
|
function pruneStrayHomes(options = {}) {
|
|
@@ -81381,7 +81697,7 @@ var init_home_census = __esm(() => {
|
|
|
81381
81697
|
});
|
|
81382
81698
|
|
|
81383
81699
|
// src/cli/env-assignment.ts
|
|
81384
|
-
import { closeSync as
|
|
81700
|
+
import { closeSync as closeSync13, constants as constants13, fstatSync as fstatSync13, ftruncateSync as ftruncateSync2, lstatSync as lstatSync21, openSync as openSync13, readFileSync as readFileSync27, writeSync as writeSync3 } from "fs";
|
|
81385
81701
|
function serializeValue(value) {
|
|
81386
81702
|
if (controls.test(value))
|
|
81387
81703
|
throw new EnvAssignmentError("Environment values cannot contain control characters or newlines.");
|
|
@@ -81460,7 +81776,7 @@ function setEnvAssignment(path, assignment) {
|
|
|
81460
81776
|
try {
|
|
81461
81777
|
const previous = (() => {
|
|
81462
81778
|
try {
|
|
81463
|
-
return
|
|
81779
|
+
return lstatSync21(path);
|
|
81464
81780
|
} catch (error61) {
|
|
81465
81781
|
if (error61.code === "ENOENT")
|
|
81466
81782
|
return;
|
|
@@ -81469,8 +81785,8 @@ function setEnvAssignment(path, assignment) {
|
|
|
81469
81785
|
})();
|
|
81470
81786
|
if (previous && !previous.isFile())
|
|
81471
81787
|
throw new EnvAssignmentError("The project .env must be a regular file, not a symlink or special file.");
|
|
81472
|
-
descriptor =
|
|
81473
|
-
const opened =
|
|
81788
|
+
descriptor = openSync13(path, previous ? constants13.O_RDWR | constants13.O_NOFOLLOW | constants13.O_NONBLOCK : constants13.O_WRONLY | constants13.O_CREAT | constants13.O_EXCL | constants13.O_NOFOLLOW, 384);
|
|
81789
|
+
const opened = fstatSync13(descriptor);
|
|
81474
81790
|
if (!opened.isFile() || previous && (opened.ino !== previous.ino || opened.dev !== previous.dev)) {
|
|
81475
81791
|
throw new EnvAssignmentError("The project .env changed while opening it; retry with a regular file.");
|
|
81476
81792
|
}
|
|
@@ -81497,7 +81813,7 @@ function setEnvAssignment(path, assignment) {
|
|
|
81497
81813
|
throw new EnvAssignmentError("Cannot safely read or write the project .env file.");
|
|
81498
81814
|
} finally {
|
|
81499
81815
|
if (descriptor !== undefined)
|
|
81500
|
-
|
|
81816
|
+
closeSync13(descriptor);
|
|
81501
81817
|
}
|
|
81502
81818
|
}
|
|
81503
81819
|
var INVALID_LAYOUT = "Cannot safely update .env with multiline or unsupported assignments. Use single-line KEY=VALUE entries or edit the file manually.", controls, EnvAssignmentError;
|
|
@@ -81894,6 +82210,15 @@ class CloudExecutionClient {
|
|
|
81894
82210
|
}
|
|
81895
82211
|
return response;
|
|
81896
82212
|
}
|
|
82213
|
+
async eligibility(slug2, version2, bundleDigest) {
|
|
82214
|
+
if (!/^[a-z0-9-]+$/.test(slug2) || !/^\d+\.\d+\.\d+$/.test(version2) || bundleDigest !== undefined && !/^(sha256:)?[a-f0-9]{64}$/.test(bundleDigest))
|
|
82215
|
+
throw Error("Cloud eligibility requires an exact skill version and valid digest");
|
|
82216
|
+
const query = new URLSearchParams({ version: version2, ...bundleDigest ? { bundleDigest } : {} });
|
|
82217
|
+
const v = await jsonBody(await this.request(`${slug2}/eligibility?${query}`));
|
|
82218
|
+
if (!v || v.contractVersion !== 1 || typeof v.eligible !== "boolean" || v.skill !== slug2 || v.version !== version2 || !/^[a-f0-9]{64}$/.test(v.bundleDigest) || bundleDigest && bundleDigest.replace(/^sha256:/, "") !== v.bundleDigest || v.eligible && (!v.executionContract || !["pdf.v1", "regex-test.v1"].includes(v.executionContract.id)))
|
|
82219
|
+
throw Error("Invalid cloud eligibility receipt");
|
|
82220
|
+
return v;
|
|
82221
|
+
}
|
|
81897
82222
|
async submit(slug2, version2, input2, key, selection) {
|
|
81898
82223
|
if (!/^[a-z0-9-]+$/.test(slug2) || !/^\d+\.\d+\.\d+$/.test(version2))
|
|
81899
82224
|
throw Error("Cloud execution requires skill@exact-version");
|
|
@@ -82006,11 +82331,11 @@ var init_cloud_executions = __esm(() => {
|
|
|
82006
82331
|
// node_modules/@hasna/secrets/dist/sdk.js
|
|
82007
82332
|
import { isIP as isIP3 } from "net";
|
|
82008
82333
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
82009
|
-
import { closeSync as
|
|
82334
|
+
import { closeSync as closeSync14, fstatSync as fstatSync14, openSync as openSync14, readFileSync as readFileSync29 } from "fs";
|
|
82010
82335
|
import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
|
|
82011
82336
|
import { createRequire as createRequire2 } from "module";
|
|
82012
82337
|
import { hostname as osHostname2 } from "os";
|
|
82013
|
-
import { isAbsolute as
|
|
82338
|
+
import { isAbsolute as isAbsolute16, join as join41 } from "path";
|
|
82014
82339
|
import { createRequire as createRequire22 } from "module";
|
|
82015
82340
|
function envToken2(name) {
|
|
82016
82341
|
return name.toUpperCase().replace(/-/g, "_");
|
|
@@ -82034,7 +82359,7 @@ function homeDir2(env3) {
|
|
|
82034
82359
|
}
|
|
82035
82360
|
function absoluteOverride2(env3, key) {
|
|
82036
82361
|
const value = env3[key]?.trim();
|
|
82037
|
-
return value &&
|
|
82362
|
+
return value && isAbsolute16(value) ? value : null;
|
|
82038
82363
|
}
|
|
82039
82364
|
function hasnaHomeDir2(env3) {
|
|
82040
82365
|
const override = absoluteOverride2(env3, HASNA_HOME_ENV_KEY2);
|
|
@@ -82111,7 +82436,7 @@ function readAppConfigFile2(path) {
|
|
|
82111
82436
|
};
|
|
82112
82437
|
let fd = -1;
|
|
82113
82438
|
try {
|
|
82114
|
-
fd =
|
|
82439
|
+
fd = openSync14(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
|
|
82115
82440
|
} catch (error61) {
|
|
82116
82441
|
const code = error61.code;
|
|
82117
82442
|
if (code === "ENOENT" || code === "ENOTDIR")
|
|
@@ -82121,7 +82446,7 @@ function readAppConfigFile2(path) {
|
|
|
82121
82446
|
unsafe(`the path could not be opened (${code ?? "unknown error"})`);
|
|
82122
82447
|
}
|
|
82123
82448
|
try {
|
|
82124
|
-
const before2 =
|
|
82449
|
+
const before2 = fstatSync14(fd);
|
|
82125
82450
|
if (!before2.isFile())
|
|
82126
82451
|
unsafe("the path is not a regular file");
|
|
82127
82452
|
if (!configFileModeAllowed2(before2.mode)) {
|
|
@@ -82133,14 +82458,14 @@ function readAppConfigFile2(path) {
|
|
|
82133
82458
|
if (before2.size > MAX_CREDENTIAL_FILE_BYTES2)
|
|
82134
82459
|
unsafe("the file exceeds the size limit");
|
|
82135
82460
|
const bytes = readFileSync29(fd);
|
|
82136
|
-
const after2 =
|
|
82461
|
+
const after2 = fstatSync14(fd);
|
|
82137
82462
|
if (!configFileReadsCoherent2(before2, after2)) {
|
|
82138
82463
|
unsafe("the file changed while being read");
|
|
82139
82464
|
}
|
|
82140
82465
|
return parseEnvFile2(bytes.toString("utf8"));
|
|
82141
82466
|
} finally {
|
|
82142
82467
|
if (fd !== -1)
|
|
82143
|
-
|
|
82468
|
+
closeSync14(fd);
|
|
82144
82469
|
}
|
|
82145
82470
|
}
|
|
82146
82471
|
function readCredentialFile2(path, apiKeyKeys) {
|
|
@@ -83171,7 +83496,7 @@ function createSecretsClientFromEnv(env3 = process.env, overrides = {}) {
|
|
|
83171
83496
|
});
|
|
83172
83497
|
return new SecretsClient({ ...clientOverrides, baseUrl, apiKey });
|
|
83173
83498
|
}
|
|
83174
|
-
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((
|
|
83499
|
+
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((resolve18) => setTimeout(resolve18, 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_RE3, SQLITE_SIDECAR_FILES, LEGACY_SERVICE_FILES, init_data_dir, SecretsTestIsolationError, TEST_ENTRYPOINT_RE, init_test_isolation, init_client, ApiError;
|
|
83175
83500
|
var init_sdk = __esm(() => {
|
|
83176
83501
|
init_transport2 = __esm2(() => {
|
|
83177
83502
|
CredentialResolutionError2 = class CredentialResolutionError3 extends Error {
|
|
@@ -83306,7 +83631,7 @@ var init_sdk = __esm(() => {
|
|
|
83306
83631
|
});
|
|
83307
83632
|
|
|
83308
83633
|
// src/lib/execution-secrets.ts
|
|
83309
|
-
import { constants as
|
|
83634
|
+
import { constants as constants14, closeSync as closeSync15, fstatSync as fstatSync15, openSync as openSync15, readSync as readSync12, realpathSync as realpathSync6 } from "fs";
|
|
83310
83635
|
import { hostname as stationHostname } from "os";
|
|
83311
83636
|
function selectedSecretBindingsTemplate(scope, names, createClient2 = createSecretsClientFromEnv) {
|
|
83312
83637
|
let secretsAuthority;
|
|
@@ -83350,13 +83675,13 @@ function declaredSecretNames(value) {
|
|
|
83350
83675
|
function readSelectedSecretBindings(path) {
|
|
83351
83676
|
let fd;
|
|
83352
83677
|
try {
|
|
83353
|
-
fd =
|
|
83354
|
-
const stat2 =
|
|
83678
|
+
fd = openSync15(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
|
|
83679
|
+
const stat2 = fstatSync15(fd);
|
|
83355
83680
|
if (!stat2.isFile() || stat2.size > 65536)
|
|
83356
83681
|
throw new Error;
|
|
83357
83682
|
const bytes = Buffer.alloc(65537);
|
|
83358
83683
|
let size2 = 0, count;
|
|
83359
|
-
while ((count =
|
|
83684
|
+
while ((count = readSync12(fd, bytes, size2, bytes.length - size2, null)) > 0) {
|
|
83360
83685
|
size2 += count;
|
|
83361
83686
|
if (size2 > 65536)
|
|
83362
83687
|
throw new Error;
|
|
@@ -83366,7 +83691,7 @@ function readSelectedSecretBindings(path) {
|
|
|
83366
83691
|
return refuse("INVALID_SECRET_BINDINGS", "Secret bindings must be a regular JSON file of at most 64 KiB, containing reference names only.");
|
|
83367
83692
|
} finally {
|
|
83368
83693
|
if (fd !== undefined)
|
|
83369
|
-
|
|
83694
|
+
closeSync15(fd);
|
|
83370
83695
|
}
|
|
83371
83696
|
}
|
|
83372
83697
|
function validateSelectedSecretBindings(value, scope, names) {
|
|
@@ -83655,10 +83980,10 @@ __export(exports_selected_run, {
|
|
|
83655
83980
|
prepareSelectedSecretBindings: () => prepareSelectedSecretBindings,
|
|
83656
83981
|
executeSelectedLocal: () => executeSelectedLocal
|
|
83657
83982
|
});
|
|
83658
|
-
import { createHash as
|
|
83983
|
+
import { createHash as createHash19 } from "crypto";
|
|
83659
83984
|
import { spawn as spawn2 } from "child_process";
|
|
83660
83985
|
import { mkdirSync as mkdirSync14, mkdtempSync as mkdtempSync4, writeFileSync as writeFileSync13, realpathSync as realpathSync7 } from "fs";
|
|
83661
|
-
import { dirname as
|
|
83986
|
+
import { dirname as dirname19, join as join42, resolve as resolve18 } from "path";
|
|
83662
83987
|
import { tmpdir, hostname as stationHostname2 } from "os";
|
|
83663
83988
|
async function resolveSelectedRun(spec, profileId, options = {}) {
|
|
83664
83989
|
const context = await resolveSelectionContext(profileId, options);
|
|
@@ -83747,11 +84072,11 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
83747
84072
|
throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
|
|
83748
84073
|
});
|
|
83749
84074
|
const destination = join42(runDirectory, entry.path);
|
|
83750
|
-
mkdirSync14(
|
|
84075
|
+
mkdirSync14(dirname19(destination), { recursive: true, mode: 448 });
|
|
83751
84076
|
writeFileSync13(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
|
|
83752
84077
|
}
|
|
83753
84078
|
env3.SKILLS_INPUT_JSON = input2;
|
|
83754
|
-
env3.SKILLS_WORKSPACE_DIR =
|
|
84079
|
+
env3.SKILLS_WORKSPACE_DIR = resolve18(options.cwd ?? process.cwd());
|
|
83755
84080
|
env3.SKILLS_RUN_DIR = runDirectory;
|
|
83756
84081
|
if (runtime.version) {
|
|
83757
84082
|
const version2 = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], "--version"], runDirectory, env3, "", Math.min(timeoutMs, 5000));
|
|
@@ -83781,7 +84106,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
83781
84106
|
selection: selection2,
|
|
83782
84107
|
target: "local",
|
|
83783
84108
|
runtime: runtimeName,
|
|
83784
|
-
inputDigest: `sha256:${
|
|
84109
|
+
inputDigest: `sha256:${createHash19("sha256").update(input2).digest("hex")}`,
|
|
83785
84110
|
runDirectory,
|
|
83786
84111
|
...executionGrant ? { executionGrant } : {},
|
|
83787
84112
|
...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
|
|
@@ -87998,7 +88323,7 @@ var init_runs = __esm(() => {
|
|
|
87998
88323
|
});
|
|
87999
88324
|
|
|
88000
88325
|
// src/lib/run-state.ts
|
|
88001
|
-
import { createHash as
|
|
88326
|
+
import { createHash as createHash20, randomBytes } from "crypto";
|
|
88002
88327
|
import { existsSync as existsSync27, mkdirSync as mkdirSync15, readFileSync as readFileSync30, readdirSync as readdirSync16, statSync as statSync15, writeFileSync as writeFileSync14 } from "fs";
|
|
88003
88328
|
import { extname, join as join43, relative as relative6 } from "path";
|
|
88004
88329
|
function createSkillRun(params, targetDir = process.cwd()) {
|
|
@@ -88135,7 +88460,7 @@ function collectRunArtifacts(context) {
|
|
|
88135
88460
|
artifacts.push({
|
|
88136
88461
|
path: toProjectRelative(context.targetDir, path),
|
|
88137
88462
|
mime: mimeForPath(path),
|
|
88138
|
-
sha256:
|
|
88463
|
+
sha256: createHash20("sha256").update(bytes).digest("hex"),
|
|
88139
88464
|
sizeBytes: stat2.size
|
|
88140
88465
|
});
|
|
88141
88466
|
}
|
|
@@ -89138,12 +89463,12 @@ class StdioServerTransport {
|
|
|
89138
89463
|
this.onclose?.();
|
|
89139
89464
|
}
|
|
89140
89465
|
send(message) {
|
|
89141
|
-
return new Promise((
|
|
89466
|
+
return new Promise((resolve19) => {
|
|
89142
89467
|
const json2 = serializeMessage(message);
|
|
89143
89468
|
if (this._stdout.write(json2)) {
|
|
89144
|
-
|
|
89469
|
+
resolve19();
|
|
89145
89470
|
} else {
|
|
89146
|
-
this._stdout.once("drain",
|
|
89471
|
+
this._stdout.once("drain", resolve19);
|
|
89147
89472
|
}
|
|
89148
89473
|
});
|
|
89149
89474
|
}
|
|
@@ -89185,7 +89510,7 @@ var init_schemas3 = __esm(() => {
|
|
|
89185
89510
|
own(this, "with", value);
|
|
89186
89511
|
},
|
|
89187
89512
|
parse(data, params) {
|
|
89188
|
-
return
|
|
89513
|
+
return parse7(this, data, params, { callee: this.parse });
|
|
89189
89514
|
},
|
|
89190
89515
|
parseAsync(data, params) {
|
|
89191
89516
|
return parseAsync(this, data, params, { callee: this.parseAsync });
|
|
@@ -91329,7 +91654,7 @@ class Protocol {
|
|
|
91329
91654
|
return;
|
|
91330
91655
|
}
|
|
91331
91656
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1000;
|
|
91332
|
-
await new Promise((
|
|
91657
|
+
await new Promise((resolve19) => setTimeout(resolve19, pollInterval));
|
|
91333
91658
|
options?.signal?.throwIfAborted();
|
|
91334
91659
|
}
|
|
91335
91660
|
} catch (error61) {
|
|
@@ -91341,7 +91666,7 @@ class Protocol {
|
|
|
91341
91666
|
}
|
|
91342
91667
|
request(request2, resultSchema, options) {
|
|
91343
91668
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
91344
|
-
return new Promise((
|
|
91669
|
+
return new Promise((resolve19, reject2) => {
|
|
91345
91670
|
const earlyReject = (error61) => {
|
|
91346
91671
|
reject2(error61);
|
|
91347
91672
|
};
|
|
@@ -91419,7 +91744,7 @@ class Protocol {
|
|
|
91419
91744
|
if (!parseResult.success) {
|
|
91420
91745
|
reject2(parseResult.error);
|
|
91421
91746
|
} else {
|
|
91422
|
-
|
|
91747
|
+
resolve19(parseResult.data);
|
|
91423
91748
|
}
|
|
91424
91749
|
} catch (error61) {
|
|
91425
91750
|
reject2(error61);
|
|
@@ -91610,12 +91935,12 @@ class Protocol {
|
|
|
91610
91935
|
interval = task.pollInterval;
|
|
91611
91936
|
}
|
|
91612
91937
|
} catch {}
|
|
91613
|
-
return new Promise((
|
|
91938
|
+
return new Promise((resolve19, reject2) => {
|
|
91614
91939
|
if (signal.aborted) {
|
|
91615
91940
|
reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
91616
91941
|
return;
|
|
91617
91942
|
}
|
|
91618
|
-
const timeoutId = setTimeout(
|
|
91943
|
+
const timeoutId = setTimeout(resolve19, interval);
|
|
91619
91944
|
signal.addEventListener("abort", () => {
|
|
91620
91945
|
clearTimeout(timeoutId);
|
|
91621
91946
|
reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -92092,11 +92417,11 @@ var require_codegen = __commonJS((exports) => {
|
|
|
92092
92417
|
const rhs = this.rhs === undefined ? "" : ` = ${this.rhs}`;
|
|
92093
92418
|
return `${varKind} ${this.name}${rhs};` + _n;
|
|
92094
92419
|
}
|
|
92095
|
-
optimizeNames(names,
|
|
92420
|
+
optimizeNames(names, constants15) {
|
|
92096
92421
|
if (!names[this.name.str])
|
|
92097
92422
|
return;
|
|
92098
92423
|
if (this.rhs)
|
|
92099
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
92424
|
+
this.rhs = optimizeExpr(this.rhs, names, constants15);
|
|
92100
92425
|
return this;
|
|
92101
92426
|
}
|
|
92102
92427
|
get names() {
|
|
@@ -92114,10 +92439,10 @@ var require_codegen = __commonJS((exports) => {
|
|
|
92114
92439
|
render({ _n }) {
|
|
92115
92440
|
return `${this.lhs} = ${this.rhs};` + _n;
|
|
92116
92441
|
}
|
|
92117
|
-
optimizeNames(names,
|
|
92442
|
+
optimizeNames(names, constants15) {
|
|
92118
92443
|
if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
|
|
92119
92444
|
return;
|
|
92120
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
92445
|
+
this.rhs = optimizeExpr(this.rhs, names, constants15);
|
|
92121
92446
|
return this;
|
|
92122
92447
|
}
|
|
92123
92448
|
get names() {
|
|
@@ -92183,8 +92508,8 @@ var require_codegen = __commonJS((exports) => {
|
|
|
92183
92508
|
optimizeNodes() {
|
|
92184
92509
|
return `${this.code}` ? this : undefined;
|
|
92185
92510
|
}
|
|
92186
|
-
optimizeNames(names,
|
|
92187
|
-
this.code = optimizeExpr(this.code, names,
|
|
92511
|
+
optimizeNames(names, constants15) {
|
|
92512
|
+
this.code = optimizeExpr(this.code, names, constants15);
|
|
92188
92513
|
return this;
|
|
92189
92514
|
}
|
|
92190
92515
|
get names() {
|
|
@@ -92214,12 +92539,12 @@ var require_codegen = __commonJS((exports) => {
|
|
|
92214
92539
|
}
|
|
92215
92540
|
return nodes.length > 0 ? this : undefined;
|
|
92216
92541
|
}
|
|
92217
|
-
optimizeNames(names,
|
|
92542
|
+
optimizeNames(names, constants15) {
|
|
92218
92543
|
const { nodes } = this;
|
|
92219
92544
|
let i = nodes.length;
|
|
92220
92545
|
while (i--) {
|
|
92221
92546
|
const n2 = nodes[i];
|
|
92222
|
-
if (n2.optimizeNames(names,
|
|
92547
|
+
if (n2.optimizeNames(names, constants15))
|
|
92223
92548
|
continue;
|
|
92224
92549
|
subtractNames(names, n2.names);
|
|
92225
92550
|
nodes.splice(i, 1);
|
|
@@ -92276,12 +92601,12 @@ var require_codegen = __commonJS((exports) => {
|
|
|
92276
92601
|
return;
|
|
92277
92602
|
return this;
|
|
92278
92603
|
}
|
|
92279
|
-
optimizeNames(names,
|
|
92604
|
+
optimizeNames(names, constants15) {
|
|
92280
92605
|
var _a3;
|
|
92281
|
-
this.else = (_a3 = this.else) === null || _a3 === undefined ? undefined : _a3.optimizeNames(names,
|
|
92282
|
-
if (!(super.optimizeNames(names,
|
|
92606
|
+
this.else = (_a3 = this.else) === null || _a3 === undefined ? undefined : _a3.optimizeNames(names, constants15);
|
|
92607
|
+
if (!(super.optimizeNames(names, constants15) || this.else))
|
|
92283
92608
|
return;
|
|
92284
|
-
this.condition = optimizeExpr(this.condition, names,
|
|
92609
|
+
this.condition = optimizeExpr(this.condition, names, constants15);
|
|
92285
92610
|
return this;
|
|
92286
92611
|
}
|
|
92287
92612
|
get names() {
|
|
@@ -92306,10 +92631,10 @@ var require_codegen = __commonJS((exports) => {
|
|
|
92306
92631
|
render(opts) {
|
|
92307
92632
|
return `for(${this.iteration})` + super.render(opts);
|
|
92308
92633
|
}
|
|
92309
|
-
optimizeNames(names,
|
|
92310
|
-
if (!super.optimizeNames(names,
|
|
92634
|
+
optimizeNames(names, constants15) {
|
|
92635
|
+
if (!super.optimizeNames(names, constants15))
|
|
92311
92636
|
return;
|
|
92312
|
-
this.iteration = optimizeExpr(this.iteration, names,
|
|
92637
|
+
this.iteration = optimizeExpr(this.iteration, names, constants15);
|
|
92313
92638
|
return this;
|
|
92314
92639
|
}
|
|
92315
92640
|
get names() {
|
|
@@ -92347,10 +92672,10 @@ var require_codegen = __commonJS((exports) => {
|
|
|
92347
92672
|
render(opts) {
|
|
92348
92673
|
return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
|
|
92349
92674
|
}
|
|
92350
|
-
optimizeNames(names,
|
|
92351
|
-
if (!super.optimizeNames(names,
|
|
92675
|
+
optimizeNames(names, constants15) {
|
|
92676
|
+
if (!super.optimizeNames(names, constants15))
|
|
92352
92677
|
return;
|
|
92353
|
-
this.iterable = optimizeExpr(this.iterable, names,
|
|
92678
|
+
this.iterable = optimizeExpr(this.iterable, names, constants15);
|
|
92354
92679
|
return this;
|
|
92355
92680
|
}
|
|
92356
92681
|
get names() {
|
|
@@ -92395,11 +92720,11 @@ var require_codegen = __commonJS((exports) => {
|
|
|
92395
92720
|
(_b = this.finally) === null || _b === undefined || _b.optimizeNodes();
|
|
92396
92721
|
return this;
|
|
92397
92722
|
}
|
|
92398
|
-
optimizeNames(names,
|
|
92723
|
+
optimizeNames(names, constants15) {
|
|
92399
92724
|
var _a3, _b;
|
|
92400
|
-
super.optimizeNames(names,
|
|
92401
|
-
(_a3 = this.catch) === null || _a3 === undefined || _a3.optimizeNames(names,
|
|
92402
|
-
(_b = this.finally) === null || _b === undefined || _b.optimizeNames(names,
|
|
92725
|
+
super.optimizeNames(names, constants15);
|
|
92726
|
+
(_a3 = this.catch) === null || _a3 === undefined || _a3.optimizeNames(names, constants15);
|
|
92727
|
+
(_b = this.finally) === null || _b === undefined || _b.optimizeNames(names, constants15);
|
|
92403
92728
|
return this;
|
|
92404
92729
|
}
|
|
92405
92730
|
get names() {
|
|
@@ -92673,7 +92998,7 @@ var require_codegen = __commonJS((exports) => {
|
|
|
92673
92998
|
function addExprNames(names, from) {
|
|
92674
92999
|
return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
|
|
92675
93000
|
}
|
|
92676
|
-
function optimizeExpr(expr, names,
|
|
93001
|
+
function optimizeExpr(expr, names, constants15) {
|
|
92677
93002
|
if (expr instanceof code_1.Name)
|
|
92678
93003
|
return replaceName(expr);
|
|
92679
93004
|
if (!canOptimize(expr))
|
|
@@ -92688,14 +93013,14 @@ var require_codegen = __commonJS((exports) => {
|
|
|
92688
93013
|
return items;
|
|
92689
93014
|
}, []));
|
|
92690
93015
|
function replaceName(n2) {
|
|
92691
|
-
const c =
|
|
93016
|
+
const c = constants15[n2.str];
|
|
92692
93017
|
if (c === undefined || names[n2.str] !== 1)
|
|
92693
93018
|
return n2;
|
|
92694
93019
|
delete names[n2.str];
|
|
92695
93020
|
return c;
|
|
92696
93021
|
}
|
|
92697
93022
|
function canOptimize(e2) {
|
|
92698
|
-
return e2 instanceof code_1._Code && e2._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 &&
|
|
93023
|
+
return e2 instanceof code_1._Code && e2._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants15[c.str] !== undefined);
|
|
92699
93024
|
}
|
|
92700
93025
|
}
|
|
92701
93026
|
function subtractNames(names, from) {
|
|
@@ -94600,7 +94925,7 @@ var require_compile = __commonJS((exports) => {
|
|
|
94600
94925
|
const schOrFunc = root2.refs[ref];
|
|
94601
94926
|
if (schOrFunc)
|
|
94602
94927
|
return schOrFunc;
|
|
94603
|
-
let _sch =
|
|
94928
|
+
let _sch = resolve19.call(this, root2, ref);
|
|
94604
94929
|
if (_sch === undefined) {
|
|
94605
94930
|
const schema = (_a3 = root2.localRefs) === null || _a3 === undefined ? undefined : _a3[ref];
|
|
94606
94931
|
const { schemaId } = this.opts;
|
|
@@ -94627,7 +94952,7 @@ var require_compile = __commonJS((exports) => {
|
|
|
94627
94952
|
function sameSchemaEnv(s1, s2) {
|
|
94628
94953
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
94629
94954
|
}
|
|
94630
|
-
function
|
|
94955
|
+
function resolve19(root2, ref) {
|
|
94631
94956
|
let sch;
|
|
94632
94957
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
94633
94958
|
ref = sch;
|
|
@@ -95425,11 +95750,11 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
95425
95750
|
if (typeof uri === "string") {
|
|
95426
95751
|
uri = normalizeString(uri, options);
|
|
95427
95752
|
} else if (typeof uri === "object") {
|
|
95428
|
-
uri =
|
|
95753
|
+
uri = parse12(serialize(uri, options), options);
|
|
95429
95754
|
}
|
|
95430
95755
|
return uri;
|
|
95431
95756
|
}
|
|
95432
|
-
function
|
|
95757
|
+
function resolve19(baseURI, relativeURI, options) {
|
|
95433
95758
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
95434
95759
|
const {
|
|
95435
95760
|
parsed: baseParsed,
|
|
@@ -95465,8 +95790,8 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
95465
95790
|
function resolveComponent(base2, relative7, options, skipNormalization) {
|
|
95466
95791
|
const target = {};
|
|
95467
95792
|
if (!skipNormalization) {
|
|
95468
|
-
base2 =
|
|
95469
|
-
relative7 =
|
|
95793
|
+
base2 = parse12(serialize(base2, options), options);
|
|
95794
|
+
relative7 = parse12(serialize(relative7, options), options);
|
|
95470
95795
|
}
|
|
95471
95796
|
options = options || {};
|
|
95472
95797
|
if (!options.tolerant && relative7.scheme) {
|
|
@@ -95766,7 +96091,7 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
95766
96091
|
}
|
|
95767
96092
|
return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
|
|
95768
96093
|
}
|
|
95769
|
-
function
|
|
96094
|
+
function parse12(uri, opts) {
|
|
95770
96095
|
return parseWithStatus(uri, opts).parsed;
|
|
95771
96096
|
}
|
|
95772
96097
|
function normalizeString(uri, opts) {
|
|
@@ -95799,11 +96124,11 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
95799
96124
|
var fastUri = {
|
|
95800
96125
|
SCHEMES,
|
|
95801
96126
|
normalize: normalize3,
|
|
95802
|
-
resolve:
|
|
96127
|
+
resolve: resolve19,
|
|
95803
96128
|
resolveComponent,
|
|
95804
96129
|
equal,
|
|
95805
96130
|
serialize,
|
|
95806
|
-
parse:
|
|
96131
|
+
parse: parse12
|
|
95807
96132
|
};
|
|
95808
96133
|
module.exports = fastUri;
|
|
95809
96134
|
module.exports.default = fastUri;
|
|
@@ -99585,7 +99910,7 @@ class McpServer {
|
|
|
99585
99910
|
let task = createTaskResult.task;
|
|
99586
99911
|
const pollInterval = task.pollInterval ?? 5000;
|
|
99587
99912
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
99588
|
-
await new Promise((
|
|
99913
|
+
await new Promise((resolve19) => setTimeout(resolve19, pollInterval));
|
|
99589
99914
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
99590
99915
|
if (!updatedTask) {
|
|
99591
99916
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -100272,7 +100597,7 @@ var init_remote_invitation_recovery = __esm(() => {
|
|
|
100272
100597
|
});
|
|
100273
100598
|
|
|
100274
100599
|
// src/lib/remote-private-publications.ts
|
|
100275
|
-
import { createHash as
|
|
100600
|
+
import { createHash as createHash21 } from "crypto";
|
|
100276
100601
|
function checkedPublicationDeclaration(value) {
|
|
100277
100602
|
if (!exact(value, ["idempotencyKey", "version", "expectedCurrentVersionId", "manifestText", "archiveSha256", "archiveByteSize"]) || !publicationUuid(value.idempotencyKey) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || typeof value.manifestText !== "string" || Buffer.byteLength(value.manifestText) > 16384 || !hash3(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES)
|
|
100278
100603
|
return bad();
|
|
@@ -100517,12 +100842,12 @@ class RemotePrivatePublicationsClient {
|
|
|
100517
100842
|
previous = view;
|
|
100518
100843
|
if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
|
|
100519
100844
|
return view;
|
|
100520
|
-
await new Promise((
|
|
100845
|
+
await new Promise((resolve19) => {
|
|
100521
100846
|
const timer = setTimeout(done, Math.min(1000, until - Date.now()));
|
|
100522
100847
|
function done() {
|
|
100523
100848
|
clearTimeout(timer);
|
|
100524
100849
|
options.signal?.removeEventListener("abort", done);
|
|
100525
|
-
|
|
100850
|
+
resolve19();
|
|
100526
100851
|
}
|
|
100527
100852
|
options.signal?.addEventListener("abort", done, { once: true });
|
|
100528
100853
|
});
|
|
@@ -100533,7 +100858,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures2, PrivatePublicationError, bad = ()
|
|
|
100533
100858
|
throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
|
|
100534
100859
|
}, invalid5 = () => {
|
|
100535
100860
|
throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
|
|
100536
|
-
}, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record10 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys3) => record10(v) && Object.keys(v).sort().join(",") === keys3.sort().join(","), date6 = (v) => typeof v === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v) && Number.isFinite(Date.parse(v)), publicationSha256 = (bytes) =>
|
|
100861
|
+
}, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record10 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys3) => record10(v) && Object.keys(v).sort().join(",") === keys3.sort().join(","), date6 = (v) => typeof v === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v) && Number.isFinite(Date.parse(v)), publicationSha256 = (bytes) => createHash21("sha256").update(bytes).digest("hex");
|
|
100537
100862
|
var init_remote_private_publications = __esm(() => {
|
|
100538
100863
|
init_fleet_credentials();
|
|
100539
100864
|
init_remote_workspace_selection();
|
|
@@ -100810,11 +101135,11 @@ var init_remote_auth = __esm(() => {
|
|
|
100810
101135
|
});
|
|
100811
101136
|
|
|
100812
101137
|
// src/lib/workspace-profile.ts
|
|
100813
|
-
import { constants as
|
|
100814
|
-
import { dirname as
|
|
101138
|
+
import { constants as constants15, closeSync as closeSync16, fstatSync as fstatSync16, lstatSync as lstatSync22, mkdirSync as mkdirSync16, mkdtempSync as mkdtempSync5, openSync as openSync16, readFileSync as readFileSync31, renameSync as renameSync9, rmSync as rmSync8, writeFileSync as writeFileSync15 } from "fs";
|
|
101139
|
+
import { dirname as dirname20, join as join44 } from "path";
|
|
100815
101140
|
function stat2(path) {
|
|
100816
101141
|
try {
|
|
100817
|
-
return
|
|
101142
|
+
return lstatSync22(path);
|
|
100818
101143
|
} catch (error61) {
|
|
100819
101144
|
if (error61.code === "ENOENT")
|
|
100820
101145
|
return null;
|
|
@@ -100824,14 +101149,14 @@ function stat2(path) {
|
|
|
100824
101149
|
function safeText(file2) {
|
|
100825
101150
|
if (stat2(file2) === null)
|
|
100826
101151
|
return null;
|
|
100827
|
-
const fd =
|
|
101152
|
+
const fd = openSync16(file2, constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK);
|
|
100828
101153
|
try {
|
|
100829
|
-
const s =
|
|
101154
|
+
const s = fstatSync16(fd);
|
|
100830
101155
|
if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
|
|
100831
101156
|
return fail2("The selected profile must use bounded owner-only regular files.");
|
|
100832
101157
|
return readFileSync31(fd, "utf8");
|
|
100833
101158
|
} finally {
|
|
100834
|
-
|
|
101159
|
+
closeSync16(fd);
|
|
100835
101160
|
}
|
|
100836
101161
|
}
|
|
100837
101162
|
function checkIdentityMetadata(file2, identity4) {
|
|
@@ -100896,18 +101221,18 @@ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
|
|
|
100896
101221
|
`);
|
|
100897
101222
|
if (Buffer.byteLength(credentialBody("x".repeat(8192)), "utf8") > 65536)
|
|
100898
101223
|
return fail2("The selected profile has insufficient space for a bounded credential. Reduce its unrelated configuration before signing in.");
|
|
100899
|
-
const
|
|
100900
|
-
for (let path =
|
|
101224
|
+
const parents3 = [];
|
|
101225
|
+
for (let path = dirname20(file2);; path = dirname20(path)) {
|
|
100901
101226
|
const before2 = stat2(path);
|
|
100902
101227
|
if (before2 && (!before2.isDirectory() || before2.isSymbolicLink()))
|
|
100903
101228
|
return fail2("The profile directory must not be a symbolic link.");
|
|
100904
|
-
|
|
100905
|
-
if (path ===
|
|
101229
|
+
parents3.push([path, before2]);
|
|
101230
|
+
if (path === dirname20(path))
|
|
100906
101231
|
break;
|
|
100907
101232
|
}
|
|
100908
101233
|
const unchanged2 = () => {
|
|
100909
101234
|
unchangedFiles();
|
|
100910
|
-
for (const [path, before2] of
|
|
101235
|
+
for (const [path, before2] of parents3) {
|
|
100911
101236
|
const now3 = stat2(path);
|
|
100912
101237
|
if (!before2 ? now3 !== null : !now3 || !now3.isDirectory() || before2.dev !== now3.dev || before2.ino !== now3.ino)
|
|
100913
101238
|
changed();
|
|
@@ -100961,14 +101286,14 @@ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
|
|
|
100961
101286
|
return fail2("The new profile exceeds the credential reader size limit.");
|
|
100962
101287
|
const identity4 = JSON.stringify({ email: verified.user.email, userId: verified.user.id, orgId: verified.organization.id, orgSlug: verified.organization.slug, apiUrl: origin }, null, 2) + `
|
|
100963
101288
|
`;
|
|
100964
|
-
mkdirSync16(
|
|
100965
|
-
const temp = mkdtempSync5(join44(
|
|
101289
|
+
mkdirSync16(dirname20(file2), { recursive: true, mode: 448 });
|
|
101290
|
+
const temp = mkdtempSync5(join44(dirname20(file2), ".workspace-login-"));
|
|
100966
101291
|
let identityInstalled = false;
|
|
100967
101292
|
try {
|
|
100968
101293
|
writeFileSync15(join44(temp, "credentials"), body, { mode: 384, flag: "wx" });
|
|
100969
101294
|
writeFileSync15(join44(temp, "identity"), identity4, { mode: 384, flag: "wx" });
|
|
100970
101295
|
unchangedFiles();
|
|
100971
|
-
for (const [path, before2] of
|
|
101296
|
+
for (const [path, before2] of parents3) {
|
|
100972
101297
|
const now3 = stat2(path);
|
|
100973
101298
|
if (!now3 || !now3.isDirectory() || now3.isSymbolicLink() || before2 && (before2.dev !== now3.dev || before2.ino !== now3.ino))
|
|
100974
101299
|
changed();
|
|
@@ -101178,8 +101503,8 @@ var init_recurring_customer = __esm(() => {
|
|
|
101178
101503
|
});
|
|
101179
101504
|
|
|
101180
101505
|
// src/lib/recurring-recovery.ts
|
|
101181
|
-
import { constants as
|
|
101182
|
-
import { dirname as
|
|
101506
|
+
import { constants as constants16, closeSync as closeSync17, fsyncSync as fsyncSync4, fstatSync as fstatSync17, lstatSync as lstatSync23, mkdirSync as mkdirSync17, openSync as openSync17, readSync as readSync13, realpathSync as realpathSync8, renameSync as renameSync10, unlinkSync as unlinkSync6, writeFileSync as writeFileSync16 } from "fs";
|
|
101507
|
+
import { dirname as dirname21, isAbsolute as isAbsolute17, join as join45, resolve as resolve19 } from "path";
|
|
101183
101508
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
101184
101509
|
|
|
101185
101510
|
class RecoveryOwner {
|
|
@@ -101187,14 +101512,14 @@ class RecoveryOwner {
|
|
|
101187
101512
|
parents = [];
|
|
101188
101513
|
constructor(directory) {
|
|
101189
101514
|
this.directory = directory;
|
|
101190
|
-
if (!
|
|
101515
|
+
if (!isAbsolute17(directory) || resolve19(directory) !== directory || realpathSync8(directory) !== directory)
|
|
101191
101516
|
invalid6();
|
|
101192
|
-
for (let path = directory;; path =
|
|
101193
|
-
const stat3 =
|
|
101517
|
+
for (let path = directory;; path = dirname21(path)) {
|
|
101518
|
+
const stat3 = lstatSync23(path);
|
|
101194
101519
|
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
101195
101520
|
invalid6();
|
|
101196
101521
|
this.parents.push({ path, dev: stat3.dev, ino: stat3.ino });
|
|
101197
|
-
if (path ===
|
|
101522
|
+
if (path === dirname21(path))
|
|
101198
101523
|
break;
|
|
101199
101524
|
}
|
|
101200
101525
|
this.assert();
|
|
@@ -101203,59 +101528,59 @@ class RecoveryOwner {
|
|
|
101203
101528
|
if (realpathSync8(this.directory) !== this.directory)
|
|
101204
101529
|
invalid6();
|
|
101205
101530
|
for (const prior of this.parents) {
|
|
101206
|
-
const now3 =
|
|
101531
|
+
const now3 = lstatSync23(prior.path);
|
|
101207
101532
|
if (!now3.isDirectory() || now3.isSymbolicLink() || now3.dev !== prior.dev || now3.ino !== prior.ino)
|
|
101208
101533
|
invalid6();
|
|
101209
101534
|
}
|
|
101210
|
-
const own2 =
|
|
101535
|
+
const own2 = lstatSync23(this.directory);
|
|
101211
101536
|
if ((own2.mode & 511) !== 448 || (own2.mode & 3584) !== 0 || process.getuid && own2.uid !== process.getuid())
|
|
101212
101537
|
invalid6();
|
|
101213
101538
|
}
|
|
101214
101539
|
read(name) {
|
|
101215
101540
|
this.assert();
|
|
101216
|
-
const fd =
|
|
101541
|
+
const fd = openSync17(join45(this.directory, name), constants16.O_RDONLY | constants16.O_NOFOLLOW | constants16.O_NONBLOCK);
|
|
101217
101542
|
try {
|
|
101218
|
-
const before2 =
|
|
101543
|
+
const before2 = fstatSync17(fd);
|
|
101219
101544
|
if (!before2.isFile() || before2.nlink !== 1 || (before2.mode & 4095) !== 384 || before2.size < 1 || before2.size > 8192 || process.getuid && before2.uid !== process.getuid())
|
|
101220
101545
|
invalid6();
|
|
101221
101546
|
const bytes = Buffer.alloc(before2.size + 1);
|
|
101222
101547
|
let size2 = 0;
|
|
101223
101548
|
while (size2 < bytes.length) {
|
|
101224
|
-
const n2 =
|
|
101549
|
+
const n2 = readSync13(fd, bytes, size2, bytes.length - size2, size2);
|
|
101225
101550
|
if (!n2)
|
|
101226
101551
|
break;
|
|
101227
101552
|
size2 += n2;
|
|
101228
101553
|
}
|
|
101229
|
-
const after2 =
|
|
101554
|
+
const after2 = fstatSync17(fd), path = lstatSync23(join45(this.directory, name));
|
|
101230
101555
|
if (size2 !== before2.size || after2.size !== before2.size || before2.mtimeMs !== after2.mtimeMs || before2.ctimeMs !== after2.ctimeMs || path.dev !== before2.dev || path.ino !== before2.ino || !path.isFile() || path.isSymbolicLink())
|
|
101231
101556
|
invalid6();
|
|
101232
101557
|
this.assert();
|
|
101233
101558
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2));
|
|
101234
101559
|
} finally {
|
|
101235
|
-
|
|
101560
|
+
closeSync17(fd);
|
|
101236
101561
|
}
|
|
101237
101562
|
}
|
|
101238
101563
|
write(name, value) {
|
|
101239
101564
|
this.assert();
|
|
101240
101565
|
const bytes = canonicalJson2(value, 8192) + `
|
|
101241
101566
|
`;
|
|
101242
|
-
const fd =
|
|
101567
|
+
const fd = openSync17(join45(this.directory, name), constants16.O_WRONLY | constants16.O_CREAT | constants16.O_EXCL | constants16.O_NOFOLLOW, 384);
|
|
101243
101568
|
try {
|
|
101244
101569
|
writeFileSync16(fd, bytes);
|
|
101245
101570
|
fsyncSync4(fd);
|
|
101246
101571
|
} finally {
|
|
101247
|
-
|
|
101572
|
+
closeSync17(fd);
|
|
101248
101573
|
}
|
|
101249
101574
|
this.assert();
|
|
101250
101575
|
this.sync();
|
|
101251
101576
|
}
|
|
101252
101577
|
sync() {
|
|
101253
101578
|
this.assert();
|
|
101254
|
-
const fd =
|
|
101579
|
+
const fd = openSync17(this.directory, constants16.O_RDONLY | constants16.O_NOFOLLOW);
|
|
101255
101580
|
try {
|
|
101256
101581
|
fsyncSync4(fd);
|
|
101257
101582
|
} finally {
|
|
101258
|
-
|
|
101583
|
+
closeSync17(fd);
|
|
101259
101584
|
}
|
|
101260
101585
|
}
|
|
101261
101586
|
saveState(state, expected) {
|
|
@@ -101273,20 +101598,20 @@ class RecoveryOwner {
|
|
|
101273
101598
|
this.assert();
|
|
101274
101599
|
let fd;
|
|
101275
101600
|
try {
|
|
101276
|
-
fd =
|
|
101601
|
+
fd = openSync17(join45(this.directory, "operation.lock"), constants16.O_WRONLY | constants16.O_CREAT | constants16.O_EXCL | constants16.O_NOFOLLOW, 384);
|
|
101277
101602
|
} catch {
|
|
101278
101603
|
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.");
|
|
101279
101604
|
}
|
|
101280
|
-
const owner2 =
|
|
101605
|
+
const owner2 = fstatSync17(fd);
|
|
101281
101606
|
try {
|
|
101282
101607
|
writeFileSync16(fd, JSON.stringify({ pid: process.pid }));
|
|
101283
101608
|
fsyncSync4(fd);
|
|
101284
101609
|
this.sync();
|
|
101285
101610
|
return await action();
|
|
101286
101611
|
} finally {
|
|
101287
|
-
|
|
101612
|
+
closeSync17(fd);
|
|
101288
101613
|
this.assert();
|
|
101289
|
-
const now3 =
|
|
101614
|
+
const now3 = lstatSync23(join45(this.directory, "operation.lock"));
|
|
101290
101615
|
if (owner2.dev !== now3.dev || owner2.ino !== now3.ino || !now3.isFile() || now3.isSymbolicLink())
|
|
101291
101616
|
invalid6();
|
|
101292
101617
|
unlinkSync6(join45(this.directory, "operation.lock"));
|
|
@@ -101322,7 +101647,7 @@ function base2(customer, organizationId) {
|
|
|
101322
101647
|
};
|
|
101323
101648
|
}
|
|
101324
101649
|
function create3(directory, intent) {
|
|
101325
|
-
if (!
|
|
101650
|
+
if (!isAbsolute17(directory) || resolve19(directory) !== directory || realpathSync8(dirname21(directory)) !== dirname21(directory))
|
|
101326
101651
|
invalid6();
|
|
101327
101652
|
mkdirSync17(directory, { mode: 448 });
|
|
101328
101653
|
const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
|
|
@@ -101485,7 +101810,7 @@ var init_recurring_recovery = __esm(() => {
|
|
|
101485
101810
|
});
|
|
101486
101811
|
|
|
101487
101812
|
// src/lib/recurring-surface.ts
|
|
101488
|
-
import { isAbsolute as
|
|
101813
|
+
import { isAbsolute as isAbsolute18 } from "path";
|
|
101489
101814
|
function recurringMcpSchema(action) {
|
|
101490
101815
|
return action === "activate" ? recurringSurfaceSchemas.activate.extend({ code, confirm: exports_external.literal(true) }) : recurringSurfaceSchemas[action];
|
|
101491
101816
|
}
|
|
@@ -101590,7 +101915,7 @@ var init_recurring_surface = __esm(() => {
|
|
|
101590
101915
|
uuid13 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
|
|
101591
101916
|
context = { userId: uuid13.optional(), membershipId: uuid13.optional() };
|
|
101592
101917
|
page2 = { limit: exports_external.number().int().min(1).max(100).optional(), cursor: exports_external.string().min(1).max(2048).optional() };
|
|
101593
|
-
directory = exports_external.string().max(4096).refine(
|
|
101918
|
+
directory = exports_external.string().max(4096).refine(isAbsolute18, "Use an absolute recovery directory");
|
|
101594
101919
|
email4 = exports_external.string().trim().toLowerCase().email().max(254);
|
|
101595
101920
|
code = exports_external.string().regex(/^\d{6}$/);
|
|
101596
101921
|
recurringSurfaceSchemas = {
|
|
@@ -102965,6 +103290,18 @@ var init_run_routing = __esm(() => {
|
|
|
102965
103290
|
import { existsSync as existsSync28, readdirSync as readdirSync17, statSync as statSync16 } from "fs";
|
|
102966
103291
|
import { join as join46 } from "path";
|
|
102967
103292
|
function registerOperationTools(server) {
|
|
103293
|
+
server.registerTool("cloud_skill_eligibility", {
|
|
103294
|
+
title: "Cloud Skill Eligibility",
|
|
103295
|
+
description: "Inspect the authenticated workspace's exact reviewed cloud contract. Does not execute or admit a skill.",
|
|
103296
|
+
inputSchema: { name: exports_external.string(), version: exports_external.string(), bundleDigest: exports_external.string().optional() }
|
|
103297
|
+
}, async ({ name, version: version2, bundleDigest }) => {
|
|
103298
|
+
try {
|
|
103299
|
+
const { CloudExecutionClient: CloudExecutionClient2 } = await Promise.resolve().then(() => (init_cloud_executions(), exports_cloud_executions));
|
|
103300
|
+
return mcpJson(await (await CloudExecutionClient2.configured()).eligibility(name, version2, bundleDigest));
|
|
103301
|
+
} catch (error61) {
|
|
103302
|
+
return mcpError("CLOUD_ELIGIBILITY_FAILED", error61.message);
|
|
103303
|
+
}
|
|
103304
|
+
});
|
|
102968
103305
|
server.registerTool("scaffold_skill", {
|
|
102969
103306
|
title: "Scaffold Skill",
|
|
102970
103307
|
description: "Create a portable skill folder under ~/.hasna/skills/installed/<name> with SKILL.md, skill.json, AGENTS.md, package.json, and src/index.ts.",
|
|
@@ -103496,14 +103833,14 @@ var init_operation_tools = __esm(() => {
|
|
|
103496
103833
|
|
|
103497
103834
|
// src/lib/feedback.ts
|
|
103498
103835
|
import { appendFileSync as appendFileSync2, existsSync as existsSync29, mkdirSync as mkdirSync18 } from "fs";
|
|
103499
|
-
import { dirname as
|
|
103836
|
+
import { dirname as dirname22, join as join47 } from "path";
|
|
103500
103837
|
import { Database } from "bun:sqlite";
|
|
103501
103838
|
function getFeedbackDbPath() {
|
|
103502
103839
|
return join47(getDataDir(), "skills.db");
|
|
103503
103840
|
}
|
|
103504
103841
|
function getFeedbackDb() {
|
|
103505
103842
|
const dbPath = getFeedbackDbPath();
|
|
103506
|
-
const dir =
|
|
103843
|
+
const dir = dirname22(dbPath);
|
|
103507
103844
|
if (!existsSync29(dir))
|
|
103508
103845
|
mkdirSync18(dir, { recursive: true });
|
|
103509
103846
|
const db = new Database(dbPath);
|
|
@@ -103532,7 +103869,7 @@ function saveFeedback(input2) {
|
|
|
103532
103869
|
const category = input2.category ?? "general";
|
|
103533
103870
|
if (isApiMode()) {
|
|
103534
103871
|
const path = join47(getDataDir(), "feedback.jsonl");
|
|
103535
|
-
const dir =
|
|
103872
|
+
const dir = dirname22(path);
|
|
103536
103873
|
if (!existsSync29(dir))
|
|
103537
103874
|
mkdirSync18(dir, { recursive: true });
|
|
103538
103875
|
appendFileSync2(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
|
|
@@ -104010,7 +104347,7 @@ var init_schedule_tools = __esm(() => {
|
|
|
104010
104347
|
});
|
|
104011
104348
|
|
|
104012
104349
|
// src/lib/native-storage.ts
|
|
104013
|
-
import { createHash as
|
|
104350
|
+
import { createHash as createHash22, createHmac as createHmac3 } from "crypto";
|
|
104014
104351
|
import {
|
|
104015
104352
|
existsSync as existsSync31,
|
|
104016
104353
|
mkdirSync as mkdirSync20,
|
|
@@ -104019,7 +104356,7 @@ import {
|
|
|
104019
104356
|
statSync as statSync17,
|
|
104020
104357
|
writeFileSync as writeFileSync18
|
|
104021
104358
|
} from "fs";
|
|
104022
|
-
import { dirname as
|
|
104359
|
+
import { dirname as dirname23, join as join49, normalize as normalize3, relative as relative7, sep as sep7 } from "path";
|
|
104023
104360
|
function resolveSkillsNativeStorageConfig(env3 = process.env) {
|
|
104024
104361
|
assertNoRetiredModeEnvVars(env3, {
|
|
104025
104362
|
app: SKILLS_ENV_NAMESPACE,
|
|
@@ -104087,7 +104424,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
|
|
|
104087
104424
|
files.push({
|
|
104088
104425
|
path: relativePath,
|
|
104089
104426
|
sizeBytes: bytes.byteLength,
|
|
104090
|
-
sha256:
|
|
104427
|
+
sha256: createHash22("sha256").update(bytes).digest("hex"),
|
|
104091
104428
|
...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
|
|
104092
104429
|
});
|
|
104093
104430
|
}
|
|
@@ -104379,20 +104716,20 @@ var init_private_publication_customer = __esm(() => {
|
|
|
104379
104716
|
});
|
|
104380
104717
|
|
|
104381
104718
|
// src/lib/private-publication-recovery.ts
|
|
104382
|
-
import { constants as
|
|
104383
|
-
import { dirname as
|
|
104719
|
+
import { constants as constants17, closeSync as closeSync18, fsyncSync as fsyncSync5, fstatSync as fstatSync18, lstatSync as lstatSync24, mkdirSync as mkdirSync21, openSync as openSync18, readSync as readSync14, realpathSync as realpathSync9, renameSync as renameSync11, unlinkSync as unlinkSync7, writeFileSync as writeFileSync19 } from "fs";
|
|
104720
|
+
import { dirname as dirname24, isAbsolute as isAbsolute19, join as join50, resolve as resolve20 } from "path";
|
|
104384
104721
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
104385
104722
|
function safeDirectory(directory2) {
|
|
104386
|
-
if (!
|
|
104723
|
+
if (!isAbsolute19(directory2) || directory2 !== resolve20(directory2) || realpathSync9(directory2) !== directory2)
|
|
104387
104724
|
return fail3();
|
|
104388
|
-
for (let path = directory2;; path =
|
|
104389
|
-
const stat3 =
|
|
104725
|
+
for (let path = directory2;; path = dirname24(path)) {
|
|
104726
|
+
const stat3 = lstatSync24(path);
|
|
104390
104727
|
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
104391
104728
|
return fail3();
|
|
104392
|
-
if (path ===
|
|
104729
|
+
if (path === dirname24(path))
|
|
104393
104730
|
break;
|
|
104394
104731
|
}
|
|
104395
|
-
const own2 =
|
|
104732
|
+
const own2 = lstatSync24(directory2);
|
|
104396
104733
|
if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
|
|
104397
104734
|
return fail3();
|
|
104398
104735
|
return { dev: own2.dev, ino: own2.ino };
|
|
@@ -104404,35 +104741,35 @@ function unchangedDirectory(directory2, identity4) {
|
|
|
104404
104741
|
}
|
|
104405
104742
|
function readOwned(directory2, name, max2) {
|
|
104406
104743
|
const identity4 = safeDirectory(directory2), file2 = join50(directory2, name);
|
|
104407
|
-
const fd =
|
|
104744
|
+
const fd = openSync18(file2, constants17.O_RDONLY | constants17.O_NOFOLLOW);
|
|
104408
104745
|
try {
|
|
104409
|
-
const stat3 =
|
|
104746
|
+
const stat3 = fstatSync18(fd);
|
|
104410
104747
|
if (!stat3.isFile() || stat3.nlink !== 1 || stat3.size > max2 || stat3.size < 1 || (stat3.mode & 63) !== 0 || process.getuid && stat3.uid !== process.getuid())
|
|
104411
104748
|
return fail3();
|
|
104412
104749
|
const buffer = Buffer.alloc(Math.min(max2, stat3.size) + 1);
|
|
104413
104750
|
let length = 0;
|
|
104414
104751
|
while (length < buffer.length) {
|
|
104415
|
-
const count =
|
|
104752
|
+
const count = readSync14(fd, buffer, length, buffer.length - length, length);
|
|
104416
104753
|
if (count === 0)
|
|
104417
104754
|
break;
|
|
104418
104755
|
length += count;
|
|
104419
104756
|
}
|
|
104420
|
-
const bytes = buffer.subarray(0, length), after2 =
|
|
104757
|
+
const bytes = buffer.subarray(0, length), after2 = fstatSync18(fd);
|
|
104421
104758
|
unchangedDirectory(directory2, identity4);
|
|
104422
104759
|
if (bytes.length !== stat3.size || stat3.size !== after2.size || stat3.mtimeMs !== after2.mtimeMs || stat3.ctimeMs !== after2.ctimeMs)
|
|
104423
104760
|
return fail3();
|
|
104424
104761
|
return bytes;
|
|
104425
104762
|
} finally {
|
|
104426
|
-
|
|
104763
|
+
closeSync18(fd);
|
|
104427
104764
|
}
|
|
104428
104765
|
}
|
|
104429
104766
|
function writeOwned(directory2, name, bytes) {
|
|
104430
|
-
const fd =
|
|
104767
|
+
const fd = openSync18(join50(directory2, name), constants17.O_WRONLY | constants17.O_CREAT | constants17.O_EXCL | constants17.O_NOFOLLOW, 384);
|
|
104431
104768
|
try {
|
|
104432
104769
|
writeFileSync19(fd, bytes);
|
|
104433
104770
|
fsyncSync5(fd);
|
|
104434
104771
|
} finally {
|
|
104435
|
-
|
|
104772
|
+
closeSync18(fd);
|
|
104436
104773
|
}
|
|
104437
104774
|
}
|
|
104438
104775
|
function save(directory2, value) {
|
|
@@ -104441,11 +104778,11 @@ function save(directory2, value) {
|
|
|
104441
104778
|
`);
|
|
104442
104779
|
unchangedDirectory(directory2, identity4);
|
|
104443
104780
|
renameSync11(join50(directory2, temporary), join50(directory2, "receipt.json"));
|
|
104444
|
-
const fd =
|
|
104781
|
+
const fd = openSync18(directory2, constants17.O_RDONLY | constants17.O_NOFOLLOW);
|
|
104445
104782
|
try {
|
|
104446
104783
|
fsyncSync5(fd);
|
|
104447
104784
|
} finally {
|
|
104448
|
-
|
|
104785
|
+
closeSync18(fd);
|
|
104449
104786
|
}
|
|
104450
104787
|
}
|
|
104451
104788
|
function bind2(client2, receipt) {
|
|
@@ -104456,20 +104793,20 @@ async function locked(directory2, action) {
|
|
|
104456
104793
|
const identity4 = safeDirectory(directory2), file2 = join50(directory2, "operation.lock");
|
|
104457
104794
|
let fd;
|
|
104458
104795
|
try {
|
|
104459
|
-
fd =
|
|
104796
|
+
fd = openSync18(file2, constants17.O_WRONLY | constants17.O_CREAT | constants17.O_EXCL | constants17.O_NOFOLLOW, 384);
|
|
104460
104797
|
} catch {
|
|
104461
104798
|
throw new PrivatePublicationError("PUBLICATION_RECOVERY_BUSY", "Another operation holds this recovery directory. If it crashed, confirm that process has stopped before explicitly removing operation.lock and resuming.");
|
|
104462
104799
|
}
|
|
104463
|
-
const lock =
|
|
104800
|
+
const lock = fstatSync18(fd);
|
|
104464
104801
|
try {
|
|
104465
104802
|
writeFileSync19(fd, JSON.stringify({ pid: process.pid }) + `
|
|
104466
104803
|
`);
|
|
104467
104804
|
fsyncSync5(fd);
|
|
104468
104805
|
return await action();
|
|
104469
104806
|
} finally {
|
|
104470
|
-
|
|
104807
|
+
closeSync18(fd);
|
|
104471
104808
|
unchangedDirectory(directory2, identity4);
|
|
104472
|
-
const now3 =
|
|
104809
|
+
const now3 = lstatSync24(file2);
|
|
104473
104810
|
if (now3.dev !== lock.dev || now3.ino !== lock.ino || !now3.isFile() || now3.isSymbolicLink())
|
|
104474
104811
|
fail3();
|
|
104475
104812
|
unlinkSync7(file2);
|
|
@@ -104521,15 +104858,15 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
|
|
|
104521
104858
|
phase: "prepared",
|
|
104522
104859
|
intent: null
|
|
104523
104860
|
};
|
|
104524
|
-
if (!
|
|
104861
|
+
if (!isAbsolute19(recoveryDirectory) || resolve20(recoveryDirectory) !== recoveryDirectory || realpathSync9(dirname24(recoveryDirectory)) !== dirname24(recoveryDirectory))
|
|
104525
104862
|
return fail3();
|
|
104526
104863
|
mkdirSync21(recoveryDirectory, { mode: 448 });
|
|
104527
104864
|
safeDirectory(recoveryDirectory);
|
|
104528
|
-
const parent =
|
|
104865
|
+
const parent = openSync18(dirname24(recoveryDirectory), constants17.O_RDONLY | constants17.O_NOFOLLOW);
|
|
104529
104866
|
try {
|
|
104530
104867
|
fsyncSync5(parent);
|
|
104531
104868
|
} finally {
|
|
104532
|
-
|
|
104869
|
+
closeSync18(parent);
|
|
104533
104870
|
}
|
|
104534
104871
|
writeOwned(recoveryDirectory, "bundle.tgz", packed.bytes);
|
|
104535
104872
|
save(recoveryDirectory, receipt);
|
|
@@ -104622,10 +104959,10 @@ var init_private_publication_recovery = __esm(() => {
|
|
|
104622
104959
|
});
|
|
104623
104960
|
|
|
104624
104961
|
// src/mcp/private-publication-tools.ts
|
|
104625
|
-
import { isAbsolute as
|
|
104962
|
+
import { isAbsolute as isAbsolute20 } from "path";
|
|
104626
104963
|
function registerPrivatePublicationTools(server) {
|
|
104627
104964
|
const uuid9 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
|
|
104628
|
-
const directory2 = exports_external.string().max(4096).refine(
|
|
104965
|
+
const directory2 = exports_external.string().max(4096).refine(isAbsolute20, "Use an absolute local directory");
|
|
104629
104966
|
const verification2 = { email: exports_external.string().email().max(254), code: exports_external.string().regex(/^\d{6}$/), userId: uuid9, membershipId: uuid9, recoveryDirectory: directory2 };
|
|
104630
104967
|
const description = "Manage a private source publication using fresh workspace-bound verification and a host-local recovery directory. Publishing requires explicit UUID current-version comparison and upload consent. Resume reuses immutable saved bytes and intent; an uncertain PUT is finalized for server verification, never uploaded twice. Sessions and signed URLs are not returned or persisted. Private execution is unavailable. Host request history may contain the supplied verification code.";
|
|
104631
104968
|
const handler = (action) => async (value) => {
|
|
@@ -104985,7 +105322,7 @@ var init_mcp2 = __esm(() => {
|
|
|
104985
105322
|
// src/cli/commands/runtime-mcp.ts
|
|
104986
105323
|
import { existsSync as existsSync32, mkdirSync as mkdirSync22, readFileSync as readFileSync34, writeFileSync as writeFileSync20 } from "fs";
|
|
104987
105324
|
import { homedir as homedir9 } from "os";
|
|
104988
|
-
import { dirname as
|
|
105325
|
+
import { dirname as dirname25, join as join51 } from "path";
|
|
104989
105326
|
async function handleMcp(options) {
|
|
104990
105327
|
if (options.register) {
|
|
104991
105328
|
let agents;
|
|
@@ -105159,7 +105496,7 @@ function writeJsonObject(path, data) {
|
|
|
105159
105496
|
`);
|
|
105160
105497
|
}
|
|
105161
105498
|
function writeTextFile(path, content) {
|
|
105162
|
-
mkdirSync22(
|
|
105499
|
+
mkdirSync22(dirname25(path), { recursive: true });
|
|
105163
105500
|
writeFileSync20(path, content.endsWith(`
|
|
105164
105501
|
`) ? content : `${content}
|
|
105165
105502
|
`);
|
|
@@ -105269,9 +105606,9 @@ var exports_runtime = {};
|
|
|
105269
105606
|
__export(exports_runtime, {
|
|
105270
105607
|
registerRuntime: () => registerRuntime
|
|
105271
105608
|
});
|
|
105272
|
-
import { createHash as
|
|
105273
|
-
import { lstatSync as
|
|
105274
|
-
import { basename as
|
|
105609
|
+
import { createHash as createHash23, randomUUID as randomUUID9 } from "crypto";
|
|
105610
|
+
import { lstatSync as lstatSync25, mkdirSync as mkdirSync23, readFileSync as readFileSync35, realpathSync as realpathSync10, writeFileSync as writeFileSync21 } from "fs";
|
|
105611
|
+
import { basename as basename11, isAbsolute as isAbsolute21, join as join52 } from "path";
|
|
105275
105612
|
import { createInterface } from "readline";
|
|
105276
105613
|
function registerRuntime(parent) {
|
|
105277
105614
|
parent.command("run").argument("<skill>", "Skill name").argument("[args...]", "Arguments to pass to the skill; use -- to end Skills options").allowUnknownOption(true).passThroughOptions(true).option("--json", "Output result as JSON", false).option("--remote", "Run on the configured server, using its catalog and quote", false).option("--target <target>", "Execution target: local or cloud").option("--secret-bindings <path>", "Reviewed, exact-selection local execution vault bindings (JSON file)").option("--secret-bindings-template", "Print a scoped bindings template without resolving secrets or running the skill", false).option("--input <json>", "Structured cloud execution input").option("--skill-version <version>", "Exact selected skill version").option("--selection-profile <id>", "Selected Skills profile").option("--session <id>", "Pinned Skills session").option("--cached", "Use the explicit verified selected cache", false).option("--yes", "Approve the server's quoted credit cost for this run", false).option("--idempotency-key <key>", "Reuse this key when retrying the same remote submission").option("--file <path>", "Attach a local input file to a remote run (repeatable)", (value, prior) => [...prior, value], []).option("--wait", "Poll remote runs until a terminal status", false).option("--poll-interval-ms <ms>", "Remote polling interval in milliseconds", "1000").option("--poll-timeout-ms <ms>", "Maximum time to wait for a remote run", "300000").description("Run a skill directly").action(async (name, args2, options, command) => {
|
|
@@ -105281,6 +105618,15 @@ function registerRuntime(parent) {
|
|
|
105281
105618
|
await handleRun(name, args2, options, separatorBeforeSkill);
|
|
105282
105619
|
});
|
|
105283
105620
|
const executions = parent.command("executions").description("Inspect isolated cloud executions");
|
|
105621
|
+
executions.command("eligibility").argument("<skill>").requiredOption("--skill-version <version>", "Exact published version").option("--bundle-digest <digest>", "Expected published bundle SHA256").option("--json", "Output as JSON", false).description("Inspect reviewed cloud eligibility without executing a skill").action(async (slug2, options) => {
|
|
105622
|
+
try {
|
|
105623
|
+
const client2 = await CloudExecutionClient.configured();
|
|
105624
|
+
await writeCliOutput(JSON.stringify(await client2.eligibility(slug2, options.skillVersion, options.bundleDigest), null, 2));
|
|
105625
|
+
} catch (error61) {
|
|
105626
|
+
console.error(JSON.stringify({ error: error61.message }));
|
|
105627
|
+
process.exitCode = 1;
|
|
105628
|
+
}
|
|
105629
|
+
});
|
|
105284
105630
|
for (const operation of ["show", "logs", "artifacts", "cancel"]) {
|
|
105285
105631
|
executions.command(operation).argument("<execution-id>").option("--json", "Output as JSON", false).action(async (id2) => {
|
|
105286
105632
|
try {
|
|
@@ -105301,7 +105647,7 @@ function registerRuntime(parent) {
|
|
|
105301
105647
|
if (!expected)
|
|
105302
105648
|
throw new Error("Cloud artifact not found");
|
|
105303
105649
|
const bytes = await client2.download(id2, name);
|
|
105304
|
-
if (bytes.length !== expected.byteSize ||
|
|
105650
|
+
if (bytes.length !== expected.byteSize || createHash23("sha256").update(bytes).digest("hex") !== expected.sha256)
|
|
105305
105651
|
throw new Error("Cloud artifact integrity verification failed");
|
|
105306
105652
|
writeFileSync21(options.output, bytes, { flag: "wx", mode: 384 });
|
|
105307
105653
|
console.log(JSON.stringify({ path: options.output, sha256: expected.sha256, byteSize: bytes.length }));
|
|
@@ -105389,7 +105735,7 @@ Updating ${name}...
|
|
|
105389
105735
|
async function readUpdatedVersion(bunExecutable) {
|
|
105390
105736
|
const output2 = await readUpdateCommand([bunExecutable, "pm", "bin", "-g"]);
|
|
105391
105737
|
const globalBin = output2.replace(/\r?\n$/, "");
|
|
105392
|
-
if (!globalBin || !
|
|
105738
|
+
if (!globalBin || !isAbsolute21(globalBin) || /[\r\n\0]/.test(globalBin))
|
|
105393
105739
|
throw new Error("Update bin discovery failed");
|
|
105394
105740
|
const installed = Bun.which("skills", { PATH: globalBin, cwd: globalBin });
|
|
105395
105741
|
const selected = Bun.which("skills");
|
|
@@ -105525,14 +105871,14 @@ function requireHttpUrl(value) {
|
|
|
105525
105871
|
}
|
|
105526
105872
|
function promptLine(question) {
|
|
105527
105873
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
105528
|
-
return new Promise((
|
|
105874
|
+
return new Promise((resolve21) => {
|
|
105529
105875
|
let settled = false;
|
|
105530
105876
|
const finish = (answer) => {
|
|
105531
105877
|
if (settled)
|
|
105532
105878
|
return;
|
|
105533
105879
|
settled = true;
|
|
105534
105880
|
rl.close();
|
|
105535
|
-
|
|
105881
|
+
resolve21(answer);
|
|
105536
105882
|
};
|
|
105537
105883
|
rl.once("SIGINT", () => finish(null));
|
|
105538
105884
|
rl.once("close", () => finish(null));
|
|
@@ -105709,10 +106055,10 @@ async function handleRun(name, args2, options, separatorBeforeSkill) {
|
|
|
105709
106055
|
try {
|
|
105710
106056
|
parsePollingOptions(options);
|
|
105711
106057
|
inputFiles = (options.file ?? []).map((path) => {
|
|
105712
|
-
const info =
|
|
106058
|
+
const info = lstatSync25(path);
|
|
105713
106059
|
if (!info.isFile() || info.size > 20 * 1024 * 1024)
|
|
105714
106060
|
throw new Error("Input must be a regular file no larger than 20 MiB");
|
|
105715
|
-
return { name:
|
|
106061
|
+
return { name: basename11(path), bytes: new Uint8Array(readFileSync35(path)) };
|
|
105716
106062
|
});
|
|
105717
106063
|
describeRemoteFiles(inputFiles);
|
|
105718
106064
|
client2 = new RemoteSkillsClient(routing.apiKey, routing.apiOrigin);
|
|
@@ -106139,7 +106485,7 @@ function ensureSafeExportParent(root2, relativePath) {
|
|
|
106139
106485
|
if (part)
|
|
106140
106486
|
parent = join52(parent, part);
|
|
106141
106487
|
try {
|
|
106142
|
-
if (!
|
|
106488
|
+
if (!lstatSync25(parent).isDirectory() || lstatSync25(parent).isSymbolicLink())
|
|
106143
106489
|
throw new Error("Unsafe artifact directory");
|
|
106144
106490
|
} catch (error61) {
|
|
106145
106491
|
if (error61.code !== "ENOENT")
|
|
@@ -106177,7 +106523,7 @@ async function pollRemoteRun(client2, runId2, options) {
|
|
|
106177
106523
|
const remaining = deadline - Date.now();
|
|
106178
106524
|
if (remaining <= 0)
|
|
106179
106525
|
break;
|
|
106180
|
-
await new Promise((
|
|
106526
|
+
await new Promise((resolve21) => setTimeout(resolve21, Math.min(options.intervalMs, remaining)));
|
|
106181
106527
|
}
|
|
106182
106528
|
return {
|
|
106183
106529
|
run: current ?? { id: runId2, status: "queued" },
|
|
@@ -106369,7 +106715,7 @@ async function readCode() {
|
|
|
106369
106715
|
function promptCode() {
|
|
106370
106716
|
const { stdin, stderr: output2 } = process;
|
|
106371
106717
|
const { isRaw: wasRaw, readableFlowing: wasFlowing } = stdin;
|
|
106372
|
-
return new Promise((
|
|
106718
|
+
return new Promise((resolve21) => {
|
|
106373
106719
|
let value = "", settled = false;
|
|
106374
106720
|
const finish = (answer) => {
|
|
106375
106721
|
if (settled)
|
|
@@ -106386,7 +106732,7 @@ function promptCode() {
|
|
|
106386
106732
|
`);
|
|
106387
106733
|
if (answer === null)
|
|
106388
106734
|
process.exitCode = 130;
|
|
106389
|
-
|
|
106735
|
+
resolve21(answer);
|
|
106390
106736
|
};
|
|
106391
106737
|
const cancel = () => finish(null);
|
|
106392
106738
|
const keypress = (text3, key) => {
|
|
@@ -106431,37 +106777,37 @@ var exports_recurring = {};
|
|
|
106431
106777
|
__export(exports_recurring, {
|
|
106432
106778
|
registerRecurringCommands: () => registerRecurringCommands
|
|
106433
106779
|
});
|
|
106434
|
-
import { constants as
|
|
106780
|
+
import { constants as constants18, closeSync as closeSync19, fstatSync as fstatSync19, lstatSync as lstatSync26, openSync as openSync19, readSync as readSync15 } from "fs";
|
|
106435
106781
|
import { createInterface as createInterface2 } from "readline";
|
|
106436
106782
|
function readRequest(path) {
|
|
106437
|
-
const fd =
|
|
106783
|
+
const fd = openSync19(path, constants18.O_RDONLY | constants18.O_NOFOLLOW | constants18.O_NONBLOCK);
|
|
106438
106784
|
try {
|
|
106439
|
-
const before2 =
|
|
106785
|
+
const before2 = fstatSync19(fd);
|
|
106440
106786
|
if (!before2.isFile() || before2.size > 1048576 || before2.size < 1)
|
|
106441
106787
|
throw new RecurringInputError;
|
|
106442
106788
|
const bytes = Buffer.alloc(before2.size + 1);
|
|
106443
106789
|
let length = 0;
|
|
106444
106790
|
while (length < bytes.length) {
|
|
106445
|
-
const n2 =
|
|
106791
|
+
const n2 = readSync15(fd, bytes, length, bytes.length - length, length);
|
|
106446
106792
|
if (!n2)
|
|
106447
106793
|
break;
|
|
106448
106794
|
length += n2;
|
|
106449
106795
|
}
|
|
106450
|
-
const after2 =
|
|
106796
|
+
const after2 = fstatSync19(fd), current = lstatSync26(path);
|
|
106451
106797
|
if (length !== before2.size || after2.size !== before2.size || before2.mtimeMs !== after2.mtimeMs || before2.ctimeMs !== after2.ctimeMs || current.dev !== before2.dev || current.ino !== before2.ino || !current.isFile() || current.isSymbolicLink())
|
|
106452
106798
|
throw new RecurringInputError;
|
|
106453
106799
|
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
|
|
106454
106800
|
} catch {
|
|
106455
106801
|
throw new RecurringInputError;
|
|
106456
106802
|
} finally {
|
|
106457
|
-
|
|
106803
|
+
closeSync19(fd);
|
|
106458
106804
|
}
|
|
106459
106805
|
}
|
|
106460
106806
|
async function acceptAtTerminal(draft) {
|
|
106461
|
-
await new Promise((
|
|
106807
|
+
await new Promise((resolve21, reject2) => process.stderr.write(`${jsonText(draft)}
|
|
106462
106808
|
This grants an additional recurring budget. Each occurrence reprices within the approved ceilings. Revocation prevents new authority; an already-authorized attempt may finish, and cancellation is separate.
|
|
106463
|
-
`, (error61) => error61 ? reject2(error61) :
|
|
106464
|
-
return new Promise((
|
|
106809
|
+
`, (error61) => error61 ? reject2(error61) : resolve21()));
|
|
106810
|
+
return new Promise((resolve21) => {
|
|
106465
106811
|
const rl = createInterface2({ input: process.stdin, output: process.stderr });
|
|
106466
106812
|
let settled = false;
|
|
106467
106813
|
const finish = (accepted) => {
|
|
@@ -106472,7 +106818,7 @@ This grants an additional recurring budget. Each occurrence reprices within the
|
|
|
106472
106818
|
rl.close();
|
|
106473
106819
|
if (!accepted)
|
|
106474
106820
|
process.exitCode = 130;
|
|
106475
|
-
|
|
106821
|
+
resolve21(accepted);
|
|
106476
106822
|
};
|
|
106477
106823
|
const timer = setTimeout(() => finish(false), 5 * 60 * 1000);
|
|
106478
106824
|
rl.once("SIGINT", () => finish(false));
|
|
@@ -106880,7 +107226,7 @@ var init_portable_snapshot_filter = __esm(() => {
|
|
|
106880
107226
|
});
|
|
106881
107227
|
|
|
106882
107228
|
// src/lib/station-snapshot.ts
|
|
106883
|
-
import { createHash as
|
|
107229
|
+
import { createHash as createHash24 } from "crypto";
|
|
106884
107230
|
import {
|
|
106885
107231
|
copyFileSync,
|
|
106886
107232
|
mkdirSync as mkdirSync24,
|
|
@@ -106888,14 +107234,14 @@ import {
|
|
|
106888
107234
|
statSync as statSync19,
|
|
106889
107235
|
writeFileSync as writeFileSync22
|
|
106890
107236
|
} from "fs";
|
|
106891
|
-
import { dirname as
|
|
107237
|
+
import { dirname as dirname27, isAbsolute as isAbsolute22, relative as relative8, resolve as resolve21, sep as sep9 } from "path";
|
|
106892
107238
|
function validateStationId(stationId) {
|
|
106893
107239
|
if (!/^[a-z0-9-]+$/.test(stationId)) {
|
|
106894
107240
|
throw new StationSnapshotError("INVALID_STATION", `station id must be a slug, got: ${stationId}`);
|
|
106895
107241
|
}
|
|
106896
107242
|
}
|
|
106897
107243
|
function sha256File(filePath) {
|
|
106898
|
-
return
|
|
107244
|
+
return createHash24("sha256").update(readFileSync36(filePath)).digest("hex");
|
|
106899
107245
|
}
|
|
106900
107246
|
function scanHome(definition, homesRoot) {
|
|
106901
107247
|
const homePath = homePathFor(definition, homesRoot);
|
|
@@ -106966,7 +107312,7 @@ function humanHomes(scanned) {
|
|
|
106966
107312
|
}));
|
|
106967
107313
|
}
|
|
106968
107314
|
function writeStationSnapshot(options) {
|
|
106969
|
-
const repoRoot =
|
|
107315
|
+
const repoRoot = resolve21(options.repoRoot ?? process.cwd());
|
|
106970
107316
|
const { scanned, plans, totalBytes } = planStationSnapshot(options);
|
|
106971
107317
|
const manifestFiles = plans.map((plan) => ({
|
|
106972
107318
|
relativePath: plan.source.relativePath,
|
|
@@ -106992,9 +107338,9 @@ function writeStationSnapshot(options) {
|
|
|
106992
107338
|
const conflicts = [];
|
|
106993
107339
|
const untouched = [];
|
|
106994
107340
|
for (const plan of plans) {
|
|
106995
|
-
const destination =
|
|
107341
|
+
const destination = resolve21(repoRoot, plan.destination);
|
|
106996
107342
|
const destinationRelative = relative8(repoRoot, destination);
|
|
106997
|
-
if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep9) ||
|
|
107343
|
+
if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep9) || isAbsolute22(destinationRelative)) {
|
|
106998
107344
|
throw new StationSnapshotError("DESTINATION_ESCAPE", `destination escapes repo root: ${plan.destination}`);
|
|
106999
107345
|
}
|
|
107000
107346
|
let existingDigest = null;
|
|
@@ -107015,8 +107361,8 @@ function writeStationSnapshot(options) {
|
|
|
107015
107361
|
}
|
|
107016
107362
|
let written = 0;
|
|
107017
107363
|
for (const plan of untouched) {
|
|
107018
|
-
const destination =
|
|
107019
|
-
mkdirSync24(
|
|
107364
|
+
const destination = resolve21(repoRoot, plan.destination);
|
|
107365
|
+
mkdirSync24(dirname27(destination), { recursive: true });
|
|
107020
107366
|
copyFileSync(plan.source.fullPath, destination);
|
|
107021
107367
|
written += 1;
|
|
107022
107368
|
}
|
|
@@ -107034,8 +107380,8 @@ function writeStationSnapshot(options) {
|
|
|
107034
107380
|
},
|
|
107035
107381
|
files: manifestFiles
|
|
107036
107382
|
};
|
|
107037
|
-
const manifestPath =
|
|
107038
|
-
mkdirSync24(
|
|
107383
|
+
const manifestPath = resolve21(repoRoot, "resources", options.stationId, "skills", "sync-manifest.json");
|
|
107384
|
+
mkdirSync24(dirname27(manifestPath), { recursive: true });
|
|
107039
107385
|
writeFileSync22(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
107040
107386
|
`);
|
|
107041
107387
|
return {
|
|
@@ -107469,10 +107815,10 @@ var init_create_sync_config = __esm(() => {
|
|
|
107469
107815
|
// src/lib/codex-hook-rpc.ts
|
|
107470
107816
|
import { execFile, spawn as spawn3 } from "child_process";
|
|
107471
107817
|
import { realpathSync as realpathSync11, statSync as statSync20 } from "fs";
|
|
107472
|
-
import { isAbsolute as
|
|
107818
|
+
import { isAbsolute as isAbsolute23 } from "path";
|
|
107473
107819
|
import { promisify } from "util";
|
|
107474
107820
|
async function connectCodexHookRpc(options) {
|
|
107475
|
-
const found =
|
|
107821
|
+
const found = isAbsolute23(options.command) ? options.command : Bun.which(options.command, { PATH: process.env.PATH });
|
|
107476
107822
|
if (!found)
|
|
107477
107823
|
throw new Error("CODEX_HOOK_TRUST_NATIVE_UNAVAILABLE: install Codex or pass --codex-command");
|
|
107478
107824
|
const binary = realpathSync11(found), stat3 = statSync20(binary);
|
|
@@ -107558,13 +107904,13 @@ async function connectCodexHookRpc(options) {
|
|
|
107558
107904
|
request(method2, params) {
|
|
107559
107905
|
if (stopped)
|
|
107560
107906
|
return Promise.reject(new Error("CODEX_HOOK_TRUST_NATIVE_RPC_CLOSED"));
|
|
107561
|
-
return new Promise((
|
|
107907
|
+
return new Promise((resolve22, reject2) => {
|
|
107562
107908
|
const id2 = nextId++;
|
|
107563
107909
|
const timer = setTimeout(() => {
|
|
107564
107910
|
fail4();
|
|
107565
107911
|
child.kill();
|
|
107566
107912
|
}, 20000);
|
|
107567
|
-
pending.set(id2, { resolve:
|
|
107913
|
+
pending.set(id2, { resolve: resolve22, reject: reject2, timer });
|
|
107568
107914
|
child.stdin.write(JSON.stringify({ id: id2, method: method2, params }) + `
|
|
107569
107915
|
`);
|
|
107570
107916
|
});
|
|
@@ -107574,14 +107920,14 @@ async function connectCodexHookRpc(options) {
|
|
|
107574
107920
|
child.stdin.end();
|
|
107575
107921
|
if (child.exitCode !== null || child.signalCode !== null)
|
|
107576
107922
|
return;
|
|
107577
|
-
await new Promise((
|
|
107923
|
+
await new Promise((resolve22) => {
|
|
107578
107924
|
const timer = setTimeout(() => {
|
|
107579
107925
|
child.kill();
|
|
107580
|
-
|
|
107926
|
+
resolve22();
|
|
107581
107927
|
}, 1000);
|
|
107582
107928
|
child.once("exit", () => {
|
|
107583
107929
|
clearTimeout(timer);
|
|
107584
|
-
|
|
107930
|
+
resolve22();
|
|
107585
107931
|
});
|
|
107586
107932
|
});
|
|
107587
107933
|
}
|
|
@@ -107688,59 +108034,59 @@ var fail4 = () => new Error('CODEX_HOOK_TRUST_UNSUPPORTED_LAYOUT: preserve and c
|
|
|
107688
108034
|
var init_codex_hook_trust_layout = () => {};
|
|
107689
108035
|
|
|
107690
108036
|
// src/lib/codex-hook-trust-files.ts
|
|
107691
|
-
import { closeSync as
|
|
107692
|
-
import { createHash as
|
|
107693
|
-
import { dirname as
|
|
107694
|
-
function
|
|
108037
|
+
import { closeSync as closeSync20, constants as constants19, fstatSync as fstatSync20, fsyncSync as fsyncSync6, lstatSync as lstatSync27, openSync as openSync20, readSync as readSync16, writeFileSync as writeFileSync23 } from "fs";
|
|
108038
|
+
import { createHash as createHash25 } from "crypto";
|
|
108039
|
+
import { dirname as dirname28 } from "path";
|
|
108040
|
+
function need4(value, code2) {
|
|
107695
108041
|
if (!value)
|
|
107696
108042
|
throw new Error(`CODEX_HOOK_TRUST_${code2}`);
|
|
107697
108043
|
}
|
|
107698
108044
|
function safeParents(file2) {
|
|
107699
|
-
for (let p =
|
|
107700
|
-
const s =
|
|
107701
|
-
|
|
107702
|
-
|
|
107703
|
-
if (
|
|
108045
|
+
for (let p = dirname28(file2);; p = dirname28(p)) {
|
|
108046
|
+
const s = lstatSync27(p);
|
|
108047
|
+
need4(s.isDirectory() && !s.isSymbolicLink(), "UNSAFE_PARENT");
|
|
108048
|
+
need4((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
|
|
108049
|
+
if (dirname28(p) === p)
|
|
107704
108050
|
break;
|
|
107705
108051
|
}
|
|
107706
108052
|
}
|
|
107707
108053
|
function snapshot(file2, privateFile = false, options = {}) {
|
|
107708
108054
|
const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
|
|
107709
108055
|
safeParents(file2);
|
|
107710
|
-
const initial2 =
|
|
107711
|
-
|
|
107712
|
-
|
|
107713
|
-
const fd =
|
|
108056
|
+
const initial2 = lstatSync27(file2, { bigint: true });
|
|
108057
|
+
need4(initial2.isFile() && initial2.uid === BigInt(process.getuid()) && (initial2.nlink === 1n || readOnlyPackage && initial2.nlink > 1n) && (initial2.mode & 0o022n) === 0n && (!privateFile || (initial2.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
|
|
108058
|
+
need4(initial2.size <= 8n * 1024n * 1024n, "FILE_BOUND");
|
|
108059
|
+
const fd = openSync20(file2, constants19.O_RDONLY | constants19.O_NOFOLLOW | constants19.O_NONBLOCK);
|
|
107714
108060
|
try {
|
|
107715
|
-
const before2 =
|
|
107716
|
-
|
|
108061
|
+
const before2 = fstatSync20(fd, { bigint: true });
|
|
108062
|
+
need4(sameStat(initial2, before2), "INPUT_CHANGED");
|
|
107717
108063
|
const bytes = Buffer.alloc(Number(before2.size) + 1);
|
|
107718
108064
|
let length = 0;
|
|
107719
108065
|
while (length < bytes.length) {
|
|
107720
|
-
const n2 =
|
|
108066
|
+
const n2 = readSync16(fd, bytes, length, bytes.length - length, null);
|
|
107721
108067
|
if (!n2)
|
|
107722
108068
|
break;
|
|
107723
108069
|
length += n2;
|
|
107724
108070
|
}
|
|
107725
|
-
|
|
108071
|
+
need4(length === Number(before2.size) && sameStat(before2, fstatSync20(fd, { bigint: true })) && sameStat(before2, lstatSync27(file2, { bigint: true })), "INPUT_CHANGED");
|
|
107726
108072
|
const content = bytes.subarray(0, length), text3 = new TextDecoder("utf-8", { fatal: true }).decode(content);
|
|
107727
|
-
return { file: file2, privateFile, readOnlyPackage, text: text3, bytes: content, stat: before2, sha256:
|
|
108073
|
+
return { file: file2, privateFile, readOnlyPackage, text: text3, bytes: content, stat: before2, sha256: createHash25("sha256").update(content).digest("hex") };
|
|
107728
108074
|
} finally {
|
|
107729
|
-
|
|
108075
|
+
closeSync20(fd);
|
|
107730
108076
|
}
|
|
107731
108077
|
}
|
|
107732
108078
|
function unchanged2(before2) {
|
|
107733
108079
|
const after2 = snapshot(before2.file, before2.privateFile, before2.readOnlyPackage ? { readOnlyPackage: true } : {});
|
|
107734
|
-
|
|
108080
|
+
need4(sameStat(before2.stat, after2.stat) && after2.sha256 === before2.sha256, "INPUT_CHANGED");
|
|
107735
108081
|
}
|
|
107736
108082
|
function save2(file2, content) {
|
|
107737
108083
|
safeParents(file2);
|
|
107738
|
-
const fd =
|
|
108084
|
+
const fd = openSync20(file2, constants19.O_WRONLY | constants19.O_CREAT | constants19.O_EXCL | constants19.O_NOFOLLOW, 384);
|
|
107739
108085
|
try {
|
|
107740
108086
|
writeFileSync23(fd, content);
|
|
107741
108087
|
fsyncSync6(fd);
|
|
107742
108088
|
} finally {
|
|
107743
|
-
|
|
108089
|
+
closeSync20(fd);
|
|
107744
108090
|
}
|
|
107745
108091
|
}
|
|
107746
108092
|
var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs", "ctimeNs"].every((key) => a[key] === b[key]);
|
|
@@ -107748,26 +108094,26 @@ var init_codex_hook_trust_files = () => {};
|
|
|
107748
108094
|
|
|
107749
108095
|
// src/lib/codex-hook-trust-identity.ts
|
|
107750
108096
|
import { realpathSync as realpathSync12 } from "fs";
|
|
107751
|
-
import { dirname as
|
|
108097
|
+
import { dirname as dirname29, isAbsolute as isAbsolute24, join as join55 } from "path";
|
|
107752
108098
|
function bindSkillsCli(command, reviewed) {
|
|
107753
108099
|
const normal = Bun.which("skills", { PATH: process.env.PATH });
|
|
107754
|
-
|
|
108100
|
+
need4(normal, "SKILLS_COMMAND_UNAVAILABLE");
|
|
107755
108101
|
const resolved = realpathSync12(normal);
|
|
107756
|
-
const bound =
|
|
107757
|
-
|
|
108102
|
+
const bound = isAbsolute24(command) ? command : command === "skills" ? normal : undefined;
|
|
108103
|
+
need4(bound && realpathSync12(bound) === resolved, "SKILLS_COMMAND_MISMATCH");
|
|
107758
108104
|
const entrypoint = reviewed?.path ?? process.argv[1];
|
|
107759
|
-
|
|
108105
|
+
need4(entrypoint && realpathSync12(entrypoint) === resolved, "SKILLS_ENTRYPOINT_MISMATCH");
|
|
107760
108106
|
const cli = snapshot(resolved, false, { readOnlyPackage: true });
|
|
107761
|
-
const manifest = snapshot(join55(
|
|
108107
|
+
const manifest = snapshot(join55(dirname29(dirname29(resolved)), "package.json"), false, { readOnlyPackage: true });
|
|
107762
108108
|
const pkg = JSON.parse(manifest.text);
|
|
107763
|
-
|
|
108109
|
+
need4(pkg.name === "@hasna/skills" && /^\d+\.\d+\.\d+$/.test(pkg.version) && pkg.bin?.skills === "bin/index.js" && resolved === join55(dirname29(manifest.file), "bin/index.js"), "SKILLS_PACKAGE_MISMATCH");
|
|
107764
108110
|
if (reviewed)
|
|
107765
|
-
|
|
107766
|
-
|
|
108111
|
+
need4(/^[a-f0-9]{64}$/.test(reviewed.sha256) && reviewed.sha256 === cli.sha256 && reviewed.version === pkg.version, "SKILLS_RELEASE_MISMATCH");
|
|
108112
|
+
need4((cli.stat.mode & 0o100n) !== 0n, "SKILLS_COMMAND_NOT_EXECUTABLE");
|
|
107767
108113
|
return {
|
|
107768
108114
|
receipt: { path: resolved, version: pkg.version, sha256: cli.sha256, manifestSha256: manifest.sha256 },
|
|
107769
108115
|
recheck() {
|
|
107770
|
-
|
|
108116
|
+
need4(Bun.which("skills", { PATH: process.env.PATH }) === normal && realpathSync12(normal) === resolved && realpathSync12(bound) === resolved && realpathSync12(entrypoint) === resolved, "SKILLS_COMMAND_CHANGED");
|
|
107771
108117
|
unchanged2(cli);
|
|
107772
108118
|
unchanged2(manifest);
|
|
107773
108119
|
}
|
|
@@ -107778,15 +108124,15 @@ var init_codex_hook_trust_identity = __esm(() => {
|
|
|
107778
108124
|
});
|
|
107779
108125
|
|
|
107780
108126
|
// src/lib/agent-codex-trust.ts
|
|
107781
|
-
import { lstatSync as
|
|
107782
|
-
import { createHash as
|
|
107783
|
-
import { join as join56, resolve as
|
|
108127
|
+
import { lstatSync as lstatSync28, mkdirSync as mkdirSync25, readdirSync as readdirSync20 } from "fs";
|
|
108128
|
+
import { createHash as createHash26, randomUUID as randomUUID10 } from "crypto";
|
|
108129
|
+
import { join as join56, resolve as resolve22 } from "path";
|
|
107784
108130
|
import { homedir as homedir11 } from "os";
|
|
107785
108131
|
import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
|
|
107786
108132
|
async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRpc) {
|
|
107787
108133
|
let rpc, journal;
|
|
107788
108134
|
try {
|
|
107789
|
-
const home =
|
|
108135
|
+
const home = resolve22(options.home ?? homedir11()), dataDir3 = resolve22(options.dataDir ?? getDataDirReadOnly());
|
|
107790
108136
|
assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
|
|
107791
108137
|
const policyFile = snapshot(join56(dataDir3, "agent-policy.json"), true), policy = parseManagedSkillPolicy(policyFile.text);
|
|
107792
108138
|
const binding = policy.bridge, alias = binding.rootAliases?.find((item) => item.agent === "codex");
|
|
@@ -107797,35 +108143,35 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
107797
108143
|
for (const [event, [nativeEvent, label]] of Object.entries(eventNames)) {
|
|
107798
108144
|
const command = renderAgentHookCommand(binding.commands.codex, "codex", binding.profiles.codex, event);
|
|
107799
108145
|
const groups = declarations[event];
|
|
107800
|
-
|
|
108146
|
+
need4(Array.isArray(groups), "DECLARATION_CHANGED");
|
|
107801
108147
|
const matches2 = groups.flatMap((group, gi) => (group.hooks ?? []).flatMap((entry, hi) => entry.command === command ? [{ group, entry, gi, hi }] : []));
|
|
107802
|
-
|
|
108148
|
+
need4(matches2.length === 1 && isDeepStrictEqual6(matches2[0].group, { hooks: [{ type: "command", command, timeout: 15 }] }), "DECLARATION_CHANGED");
|
|
107803
108149
|
expected.push({ event: nativeEvent, key: `${join56(home, ".codex/hooks.json")}:${label}:${matches2[0].gi}:${matches2[0].hi}`, command });
|
|
107804
108150
|
}
|
|
107805
108151
|
codexTrustTextWitness(configFile.text, expected.map((h) => h.key));
|
|
107806
108152
|
rpc = await connect({ command: options.codexCommand ?? "codex", home, codexHome });
|
|
107807
|
-
|
|
108153
|
+
need4(SUPPORTED_CODEX_HOOK_VERSIONS.includes(rpc.version), "NATIVE_UNSUPPORTED_VERSION");
|
|
107808
108154
|
const list2 = async () => {
|
|
107809
108155
|
const response = await rpc.request("hooks/list", { cwds: [home] });
|
|
107810
|
-
|
|
108156
|
+
need4(Array.isArray(response?.data) && response.data.length === 1 && response.data[0].cwd === home && Array.isArray(response.data[0].hooks) && response.data[0].hooks.length <= 1e4 && !response.data[0].errors?.length && !response.data[0].warnings?.length, "NATIVE_DISCOVERY_REFUSED");
|
|
107811
108157
|
return response.data[0].hooks;
|
|
107812
108158
|
};
|
|
107813
108159
|
const admit = (hooks) => expected.map((wanted) => {
|
|
107814
108160
|
const canonicalKey = wanted.key.replace(join56(home, ".codex/hooks.json"), hooksPath);
|
|
107815
108161
|
const matches2 = hooks.filter((h2) => h2.key === wanted.key || h2.key === canonicalKey);
|
|
107816
|
-
|
|
108162
|
+
need4(matches2.length === 1, "AMBIGUOUS_IDENTITY");
|
|
107817
108163
|
const h = matches2[0];
|
|
107818
|
-
|
|
107819
|
-
|
|
107820
|
-
|
|
108164
|
+
need4(h.eventName === wanted.event && h.handlerType === "command" && h.command === wanted.command && h.matcher === null && h.timeoutSec === 15 && h.async === false && h.statusMessage === null && h.additionalContextLimit === null && [hooksPath, join56(home, ".codex/hooks.json")].includes(h.sourcePath) && h.source === "user" && h.pluginId === null && h.isManaged === false && /^sha256:[a-f0-9]{64}$/.test(h.currentHash) && typeof h.enabled === "boolean", "NATIVE_IDENTITY_CHANGED");
|
|
108165
|
+
need4(hooks.filter((other) => other.command === wanted.command).length === 1, "AMBIGUOUS_IDENTITY");
|
|
108166
|
+
need4(["trusted", "untrusted", "modified"].includes(h.trustStatus), "UNKNOWN_TRUST_STATUS");
|
|
107821
108167
|
return { key: h.key, event: wanted.event, command: wanted.command, handlerType: h.handlerType, timeoutSec: h.timeoutSec, sourcePath: h.sourcePath, currentHash: h.currentHash, enabled: h.enabled, trustStatus: h.trustStatus };
|
|
107822
108168
|
});
|
|
107823
108169
|
const discovered = await list2(), admitted = admit(discovered);
|
|
107824
108170
|
const config2 = await rpc.request("config/read", { includeLayers: true, cwd: home });
|
|
107825
108171
|
const layers = config2?.layers?.filter((layer) => layer.name?.type === "user" && layer.name.file === configPath && !layer.name.profile);
|
|
107826
|
-
|
|
107827
|
-
|
|
107828
|
-
|
|
108172
|
+
need4(layers?.length === 1 && /^sha256:[a-f0-9]{64}$/.test(layers[0].version) && !layers[0].disabledReason && isDeepStrictEqual6(layers[0].config, original), "NATIVE_CONFIG_MISMATCH");
|
|
108173
|
+
need4(config2.config && config2.config.features?.hooks !== false, "NATIVE_HOOKS_DISABLED");
|
|
108174
|
+
need4(config2.layers.slice(0, config2.layers.indexOf(layers[0])).every((layer) => layer.config?.hooks === undefined && layer.config?.features?.hooks === undefined), "NATIVE_CONFIG_OVERRIDDEN");
|
|
107829
108175
|
const keys3 = admitted.map((h) => h.key), planned = admitted.filter((h) => !h.enabled || h.trustStatus !== "trusted");
|
|
107830
108176
|
const preservationText = codexTrustTextWitness(configFile.text, keys3);
|
|
107831
108177
|
const checkInputs = () => {
|
|
@@ -107836,19 +108182,19 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
107836
108182
|
unchanged2(configFile);
|
|
107837
108183
|
};
|
|
107838
108184
|
checkInputs();
|
|
107839
|
-
const planDigest =
|
|
108185
|
+
const planDigest = createHash26("sha256").update(json2({ version: 1, home, configPath, configSha256: configFile.sha256, configVersion: layers[0].version, policySha256: policyFile.sha256, hooksSha256: hooksFile.sha256, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, declarations: expected, admitted })).digest("hex");
|
|
107840
108186
|
const baseReceipt = { planDigest, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, ownedNativeProcessId: rpc.processId, agent: "codex", applied: false, planned, nativeEligible: planned.length === 0, transport: "owned-stdio-process", existingSessionsReloaded: false, nativeExecutionVerified: false };
|
|
107841
108187
|
if (options.apply)
|
|
107842
|
-
|
|
108188
|
+
need4(options.reviewedPlanDigest === planDigest, "PLAN_CHANGED: run the dry-run again and pass its reviewed --plan-digest with --apply");
|
|
107843
108189
|
const parent = join56(dataDir3, "native-hook-trust");
|
|
107844
|
-
const st =
|
|
108190
|
+
const st = lstatSync28(parent, { throwIfNoEntry: false });
|
|
107845
108191
|
if (st) {
|
|
107846
|
-
|
|
108192
|
+
need4(st.isDirectory() && !st.isSymbolicLink() && st.uid === process.getuid() && (st.mode & 511) === 448, "UNSAFE_JOURNAL");
|
|
107847
108193
|
const priorJournals = readdirSync20(parent);
|
|
107848
|
-
|
|
108194
|
+
need4(priorJournals.length < 1000, "JOURNAL_BOUND");
|
|
107849
108195
|
for (const name of priorJournals) {
|
|
107850
|
-
|
|
107851
|
-
|
|
108196
|
+
need4(/^[a-f0-9-]{36}$/.test(name), "UNSAFE_JOURNAL");
|
|
108197
|
+
need4(lstatSync28(join56(parent, name, "receipt.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_REQUIRED: inspect the incomplete private journal before applying again");
|
|
107852
108198
|
}
|
|
107853
108199
|
}
|
|
107854
108200
|
if (!options.apply || !planned.length)
|
|
@@ -107861,7 +108207,7 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
107861
108207
|
save2(join56(journal, "hooks.before.json"), hooksFile.bytes);
|
|
107862
108208
|
save2(join56(journal, "policy.before.json"), policyFile.bytes);
|
|
107863
108209
|
save2(join56(journal, "intent.json"), json2({ version: 1, planDigest, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, configPath, beforeSha256: configFile.sha256, hooksSha256: hooksFile.sha256, policySha256: policyFile.sha256, expectedVersion: layers[0].version, hooks: planned }));
|
|
107864
|
-
|
|
108210
|
+
need4(isDeepStrictEqual6(admit(await list2()), admitted), "NATIVE_DISCOVERY_CHANGED");
|
|
107865
108211
|
checkInputs();
|
|
107866
108212
|
let result2;
|
|
107867
108213
|
try {
|
|
@@ -107869,19 +108215,19 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
107869
108215
|
} catch {
|
|
107870
108216
|
throw new Error("CODEX_HOOK_TRUST_NATIVE_WRITE_FAILED: reconcile the private journal before retrying");
|
|
107871
108217
|
}
|
|
107872
|
-
|
|
108218
|
+
need4(result2?.status === "ok" && result2.filePath === configPath && /^sha256:[a-f0-9]{64}$/.test(result2.version), "NATIVE_WRITE_OVERRIDDEN");
|
|
107873
108219
|
const after2 = snapshot(configPath, true), expectedConfig = structuredClone(original);
|
|
107874
108220
|
expectedConfig.hooks ??= {};
|
|
107875
108221
|
expectedConfig.hooks.state ??= {};
|
|
107876
108222
|
for (const h of planned)
|
|
107877
108223
|
expectedConfig.hooks.state[h.key] = { ...expectedConfig.hooks.state[h.key], enabled: true, trusted_hash: h.currentHash };
|
|
107878
|
-
|
|
108224
|
+
need4(isDeepStrictEqual6(structure(after2.text), expectedConfig) && codexTrustTextWitness(after2.text, keys3) === preservationText, "PRESERVATION_FAILED");
|
|
107879
108225
|
unchanged2(policyFile);
|
|
107880
108226
|
unchanged2(hooksFile);
|
|
107881
108227
|
assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
|
|
107882
108228
|
const current = await list2(), confirmed = admit(current);
|
|
107883
|
-
|
|
107884
|
-
|
|
108229
|
+
need4(confirmed.every((h) => h.enabled && h.trustStatus === "trusted") && isDeepStrictEqual6(confirmed.map((h) => [h.key, h.currentHash]), admitted.map((h) => [h.key, h.currentHash])), "NATIVE_NOT_ELIGIBLE");
|
|
108230
|
+
need4(isDeepStrictEqual6(current.filter((h) => !keys3.includes(h.key)), discovered.filter((h) => !keys3.includes(h.key))), "UNRELATED_HOOK_CHANGED");
|
|
107885
108231
|
unchanged2(after2);
|
|
107886
108232
|
unchanged2(hooksFile);
|
|
107887
108233
|
unchanged2(policyFile);
|
|
@@ -107996,7 +108342,7 @@ __export(exports_agent_integration, {
|
|
|
107996
108342
|
registerAgentIntegration: () => registerAgentIntegration
|
|
107997
108343
|
});
|
|
107998
108344
|
import { readFileSync as readFileSync37 } from "fs";
|
|
107999
|
-
import { isAbsolute as
|
|
108345
|
+
import { isAbsolute as isAbsolute25 } from "path";
|
|
108000
108346
|
function pinnedHookProfile(input3, configuredProfile) {
|
|
108001
108347
|
try {
|
|
108002
108348
|
const parsed = parseSkillContextInput(JSON.stringify(input3));
|
|
@@ -108114,12 +108460,12 @@ function registerAgentIntegration(parent) {
|
|
|
108114
108460
|
input3.hook_event_name = event;
|
|
108115
108461
|
const projects = [process.cwd()];
|
|
108116
108462
|
if (input3.cwd !== undefined) {
|
|
108117
|
-
if (typeof input3.cwd !== "string" || !
|
|
108463
|
+
if (typeof input3.cwd !== "string" || !isAbsolute25(input3.cwd) || input3.cwd.includes("\x00"))
|
|
108118
108464
|
throw new Error("Invalid native hook working directory");
|
|
108119
108465
|
projects.push(input3.cwd);
|
|
108120
108466
|
}
|
|
108121
108467
|
if (options.agent === "cursor") {
|
|
108122
|
-
if (!Array.isArray(input3.workspace_roots) || input3.workspace_roots.length > 32 || input3.workspace_roots.some((path) => typeof path !== "string" || !
|
|
108468
|
+
if (!Array.isArray(input3.workspace_roots) || input3.workspace_roots.length > 32 || input3.workspace_roots.some((path) => typeof path !== "string" || !isAbsolute25(path) || path.includes("\x00")))
|
|
108123
108469
|
throw new Error("Invalid Cursor workspace roots");
|
|
108124
108470
|
projects.push(...input3.workspace_roots);
|
|
108125
108471
|
input3.cwd ??= input3.workspace_roots[0] ?? process.cwd();
|
|
@@ -108357,17 +108703,17 @@ var exports_profiles = {};
|
|
|
108357
108703
|
__export(exports_profiles, {
|
|
108358
108704
|
registerProfiles: () => registerProfiles
|
|
108359
108705
|
});
|
|
108360
|
-
import { closeSync as
|
|
108706
|
+
import { closeSync as closeSync21, constants as constants20, fstatSync as fstatSync21, openSync as openSync21, readSync as readSync17, writeFileSync as writeFileSync24 } from "fs";
|
|
108361
108707
|
function readProfileInput(path) {
|
|
108362
|
-
const fd =
|
|
108708
|
+
const fd = openSync21(path, constants20.O_RDONLY | constants20.O_NONBLOCK);
|
|
108363
108709
|
try {
|
|
108364
|
-
const stat3 =
|
|
108710
|
+
const stat3 = fstatSync21(fd);
|
|
108365
108711
|
if (!stat3.isFile() || stat3.size > MAX_PROFILE_DOCUMENT_BYTES)
|
|
108366
108712
|
throw new Error("Profile input exceeds the size limit or is not a regular file");
|
|
108367
108713
|
const bytes = Buffer.alloc(MAX_PROFILE_DOCUMENT_BYTES + 1);
|
|
108368
108714
|
let size2 = 0;
|
|
108369
108715
|
while (size2 < bytes.length) {
|
|
108370
|
-
const read3 =
|
|
108716
|
+
const read3 = readSync17(fd, bytes, size2, bytes.length - size2, null);
|
|
108371
108717
|
if (!read3)
|
|
108372
108718
|
break;
|
|
108373
108719
|
size2 += read3;
|
|
@@ -108376,7 +108722,7 @@ function readProfileInput(path) {
|
|
|
108376
108722
|
throw new Error("Profile input exceeds the size limit");
|
|
108377
108723
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2));
|
|
108378
108724
|
} finally {
|
|
108379
|
-
|
|
108725
|
+
closeSync21(fd);
|
|
108380
108726
|
}
|
|
108381
108727
|
}
|
|
108382
108728
|
function registerProfiles(parent) {
|
|
@@ -108427,23 +108773,23 @@ __export(exports_grants, {
|
|
|
108427
108773
|
registerGrants: () => registerGrants
|
|
108428
108774
|
});
|
|
108429
108775
|
import {
|
|
108430
|
-
constants as
|
|
108431
|
-
closeSync as
|
|
108432
|
-
fstatSync as
|
|
108433
|
-
openSync as
|
|
108434
|
-
readSync as
|
|
108776
|
+
constants as constants21,
|
|
108777
|
+
closeSync as closeSync23,
|
|
108778
|
+
fstatSync as fstatSync23,
|
|
108779
|
+
openSync as openSync23,
|
|
108780
|
+
readSync as readSync18,
|
|
108435
108781
|
writeFileSync as writeFileSync25
|
|
108436
108782
|
} from "fs";
|
|
108437
108783
|
function readInput(path) {
|
|
108438
|
-
const fd =
|
|
108784
|
+
const fd = openSync23(path, constants21.O_RDONLY | constants21.O_NONBLOCK);
|
|
108439
108785
|
try {
|
|
108440
|
-
const stat3 =
|
|
108786
|
+
const stat3 = fstatSync23(fd);
|
|
108441
108787
|
if (!stat3.isFile() || stat3.size > MAX_EXECUTION_GRANT_BYTES)
|
|
108442
108788
|
throw new Error("Grant input must be a regular file within the policy size limit.");
|
|
108443
108789
|
const bytes = Buffer.alloc(MAX_EXECUTION_GRANT_BYTES + 1);
|
|
108444
108790
|
let size2 = 0;
|
|
108445
108791
|
while (size2 < bytes.length) {
|
|
108446
|
-
const count =
|
|
108792
|
+
const count = readSync18(fd, bytes, size2, bytes.length - size2, null);
|
|
108447
108793
|
if (!count)
|
|
108448
108794
|
break;
|
|
108449
108795
|
size2 += count;
|
|
@@ -108456,7 +108802,7 @@ function readInput(path) {
|
|
|
108456
108802
|
throw new Error("Grant input must be a JSON document containing a grants array.");
|
|
108457
108803
|
}
|
|
108458
108804
|
} finally {
|
|
108459
|
-
|
|
108805
|
+
closeSync23(fd);
|
|
108460
108806
|
}
|
|
108461
108807
|
}
|
|
108462
108808
|
function registerGrants(parent) {
|
|
@@ -108492,7 +108838,7 @@ var init_grants = __esm(() => {
|
|
|
108492
108838
|
});
|
|
108493
108839
|
|
|
108494
108840
|
// src/lib/station-hydrate.ts
|
|
108495
|
-
import { createHash as
|
|
108841
|
+
import { createHash as createHash27 } from "crypto";
|
|
108496
108842
|
import {
|
|
108497
108843
|
copyFileSync as copyFileSync2,
|
|
108498
108844
|
mkdirSync as mkdirSync26,
|
|
@@ -108501,7 +108847,7 @@ import {
|
|
|
108501
108847
|
statSync as statSync21,
|
|
108502
108848
|
writeFileSync as writeFileSync26
|
|
108503
108849
|
} from "fs";
|
|
108504
|
-
import { dirname as
|
|
108850
|
+
import { dirname as dirname30, join as join57, resolve as resolve23, sep as sep10 } from "path";
|
|
108505
108851
|
function fail5(code2, message, detail = []) {
|
|
108506
108852
|
throw new StationSnapshotError(code2, message, detail);
|
|
108507
108853
|
}
|
|
@@ -108695,12 +109041,12 @@ function skillSha256(skill) {
|
|
|
108695
109041
|
return sha256File(skill.files[0].winner.fullPath);
|
|
108696
109042
|
}
|
|
108697
109043
|
const joined = skill.files.map((file2) => sha256File(file2.winner.fullPath));
|
|
108698
|
-
return
|
|
109044
|
+
return createHash27("sha256").update(joined.sort().join(`
|
|
108699
109045
|
`)).digest("hex");
|
|
108700
109046
|
}
|
|
108701
109047
|
function writeStationHydration(options) {
|
|
108702
|
-
const repoRoot =
|
|
108703
|
-
const cacheRoot =
|
|
109048
|
+
const repoRoot = resolve23(options.repoRoot ?? process.cwd());
|
|
109049
|
+
const cacheRoot = resolve23(options.cacheRoot ?? resolveCorpusRoot());
|
|
108704
109050
|
const plan = planStationHydration(options.stationId, repoRoot);
|
|
108705
109051
|
const resultSkills = plan.winners.map((skill) => ({
|
|
108706
109052
|
ident: skill.ident,
|
|
@@ -108754,7 +109100,7 @@ function writeStationHydration(options) {
|
|
|
108754
109100
|
}
|
|
108755
109101
|
let written = 0;
|
|
108756
109102
|
for (const entry of toWrite) {
|
|
108757
|
-
mkdirSync26(
|
|
109103
|
+
mkdirSync26(dirname30(entry.destination), { recursive: true });
|
|
108758
109104
|
copyFileSync2(entry.fullPath, entry.destination);
|
|
108759
109105
|
written += 1;
|
|
108760
109106
|
}
|
|
@@ -108775,8 +109121,8 @@ function writeStationHydration(options) {
|
|
|
108775
109121
|
},
|
|
108776
109122
|
skills: resultSkills
|
|
108777
109123
|
};
|
|
108778
|
-
const hydrationManifestPath = join57(
|
|
108779
|
-
mkdirSync26(
|
|
109124
|
+
const hydrationManifestPath = join57(dirname30(cacheRoot), `hydration-${options.stationId}.json`);
|
|
109125
|
+
mkdirSync26(dirname30(hydrationManifestPath), { recursive: true });
|
|
108780
109126
|
writeFileSync26(hydrationManifestPath, `${JSON.stringify(hydration, null, 2)}
|
|
108781
109127
|
`);
|
|
108782
109128
|
return {
|
|
@@ -108852,10 +109198,10 @@ var init_hydrate = __esm(() => {
|
|
|
108852
109198
|
});
|
|
108853
109199
|
|
|
108854
109200
|
// src/lib/prepare-skill.ts
|
|
108855
|
-
import { createHash as
|
|
108856
|
-
import { chmodSync as chmodSync3, existsSync as existsSync34, lstatSync as
|
|
109201
|
+
import { createHash as createHash28, randomUUID as randomUUID11 } from "crypto";
|
|
109202
|
+
import { chmodSync as chmodSync3, existsSync as existsSync34, lstatSync as lstatSync29, mkdirSync as mkdirSync27, mkdtempSync as mkdtempSync6, readFileSync as readFileSync39, readdirSync as readdirSync22, renameSync as renameSync12, rmSync as rmSync9, writeFileSync as writeFileSync27 } from "fs";
|
|
108857
109203
|
import { tmpdir as tmpdir2 } from "os";
|
|
108858
|
-
import { dirname as
|
|
109204
|
+
import { dirname as dirname31, isAbsolute as isAbsolute26, join as join58, relative as relative9, resolve as resolve24, sep as sep11 } from "path";
|
|
108859
109205
|
function prepareSkill(name, options) {
|
|
108860
109206
|
const normalized = normalizePortableSkillName(name);
|
|
108861
109207
|
if (!new RegExp(SEMVER_PATTERN).test(options.version))
|
|
@@ -108900,7 +109246,7 @@ function prepareSkill(name, options) {
|
|
|
108900
109246
|
mkdirSync27(join58(staging, directory2), { recursive: true });
|
|
108901
109247
|
for (const file2 of before2.files) {
|
|
108902
109248
|
const destination = join58(staging, file2.path);
|
|
108903
|
-
mkdirSync27(
|
|
109249
|
+
mkdirSync27(dirname31(destination), { recursive: true });
|
|
108904
109250
|
writeFileSync27(destination, file2.bytes, { mode: file2.mode });
|
|
108905
109251
|
}
|
|
108906
109252
|
const stagedManifest = join58(staging, "skill.json");
|
|
@@ -108960,8 +109306,8 @@ function validateRuntimeEntrypoint(candidate2, root2) {
|
|
|
108960
109306
|
const entry = candidate2.runtime.entrypoint;
|
|
108961
109307
|
if (typeof entry !== "string")
|
|
108962
109308
|
return;
|
|
108963
|
-
const target =
|
|
108964
|
-
if (
|
|
109309
|
+
const target = resolve24(root2, entry), rel = relative9(root2, target);
|
|
109310
|
+
if (isAbsolute26(entry) || /^[a-zA-Z]:/.test(entry) || entry.includes("\\") || !rel || rel === ".." || rel.startsWith(`..${sep11}`) || isAbsolute26(rel) || !existsSync34(target) || !lstatSync29(target).isFile()) {
|
|
108965
109311
|
throw new Error("Executable runtime.entrypoint must name an existing regular file inside the skill directory.");
|
|
108966
109312
|
}
|
|
108967
109313
|
}
|
|
@@ -108982,6 +109328,7 @@ function validateRawCandidate(candidate2) {
|
|
|
108982
109328
|
const issues = validatePortableManifestContract(candidate2, { strict: true });
|
|
108983
109329
|
if (issues.length)
|
|
108984
109330
|
throw new Error(`Invalid skill.json: ${issues.map((issue2) => issue2.code).join(", ")}`);
|
|
109331
|
+
validateRuntimeEntrypointCompatibility(candidate2);
|
|
108985
109332
|
for (const field2 of ["inputs", "commands"]) {
|
|
108986
109333
|
const items = candidate2[field2];
|
|
108987
109334
|
if (items === undefined)
|
|
@@ -109007,6 +109354,18 @@ function validateRawCandidate(candidate2) {
|
|
|
109007
109354
|
}
|
|
109008
109355
|
}
|
|
109009
109356
|
}
|
|
109357
|
+
function validateRuntimeEntrypointCompatibility(candidate2) {
|
|
109358
|
+
if (candidate2.kind !== "executable" || !isRecord6(candidate2.runtime))
|
|
109359
|
+
return;
|
|
109360
|
+
const runtime = candidate2.runtime.runtime;
|
|
109361
|
+
const entrypoint = candidate2.runtime.entrypoint;
|
|
109362
|
+
if (typeof runtime !== "string" || typeof entrypoint !== "string")
|
|
109363
|
+
return;
|
|
109364
|
+
const extension = entrypoint.toLowerCase().split(".").pop();
|
|
109365
|
+
if (extension === "py" && runtime !== "python3") {
|
|
109366
|
+
throw new Error("Invalid skill.json: runtime.entrypoint with .py extension requires runtime python3.");
|
|
109367
|
+
}
|
|
109368
|
+
}
|
|
109010
109369
|
function compareVersions(left, right) {
|
|
109011
109370
|
const parts = (value) => value.split("+")[0].split(/-(.*)/s).slice(0, 2);
|
|
109012
109371
|
const [a, ap] = parts(left), [b, bp] = parts(right);
|
|
@@ -109033,11 +109392,11 @@ function compareVersions(left, right) {
|
|
|
109033
109392
|
return 0;
|
|
109034
109393
|
}
|
|
109035
109394
|
function snapshot2(root2) {
|
|
109036
|
-
const rootStat =
|
|
109395
|
+
const rootStat = lstatSync29(root2);
|
|
109037
109396
|
if (rootStat.isSymbolicLink() || !rootStat.isDirectory())
|
|
109038
109397
|
throw new Error("Skill root must be a real directory, not a symlink.");
|
|
109039
109398
|
const files = [], directories = [];
|
|
109040
|
-
const hash4 =
|
|
109399
|
+
const hash4 = createHash28("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
|
|
109041
109400
|
let count = 0, bytes = 0;
|
|
109042
109401
|
const walk2 = (relative10) => {
|
|
109043
109402
|
for (const name of readdirSync22(join58(root2, relative10)).sort()) {
|
|
@@ -109046,7 +109405,7 @@ function snapshot2(root2) {
|
|
|
109046
109405
|
const path = relative10 ? `${relative10}/${name}` : name;
|
|
109047
109406
|
if (++count > 20000)
|
|
109048
109407
|
throw new Error("Skill exceeds the preparation entry limit (20000).");
|
|
109049
|
-
const absolute = join58(root2, path), stat3 =
|
|
109408
|
+
const absolute = join58(root2, path), stat3 = lstatSync29(absolute);
|
|
109050
109409
|
if (stat3.isSymbolicLink())
|
|
109051
109410
|
throw new Error(`Skill contains a symlink: ${path}. No files were changed.`);
|
|
109052
109411
|
if (stat3.isDirectory() && name === "node_modules")
|
|
@@ -109461,7 +109820,7 @@ var init_schedule = __esm(() => {
|
|
|
109461
109820
|
|
|
109462
109821
|
// src/lib/registry-sync.ts
|
|
109463
109822
|
import { mkdirSync as mkdirSync28, writeFileSync as writeFileSync28 } from "fs";
|
|
109464
|
-
import { dirname as
|
|
109823
|
+
import { dirname as dirname32, relative as relative10 } from "path";
|
|
109465
109824
|
function createRegistrySyncArtifact(options = {}) {
|
|
109466
109825
|
const profile = options.profile ?? "all";
|
|
109467
109826
|
const includeDocs = options.includeDocs ?? true;
|
|
@@ -109518,7 +109877,7 @@ function createRegistrySyncArtifact(options = {}) {
|
|
|
109518
109877
|
};
|
|
109519
109878
|
}
|
|
109520
109879
|
function writeRegistrySyncArtifact(path, artifact) {
|
|
109521
|
-
mkdirSync28(
|
|
109880
|
+
mkdirSync28(dirname32(path), { recursive: true });
|
|
109522
109881
|
writeFileSync28(path, `${JSON.stringify(artifact, null, 2)}
|
|
109523
109882
|
`);
|
|
109524
109883
|
}
|
|
@@ -109542,7 +109901,8 @@ var exports_registry2 = {};
|
|
|
109542
109901
|
__export(exports_registry2, {
|
|
109543
109902
|
registerVersions: () => registerVersions,
|
|
109544
109903
|
registerRegistry: () => registerRegistry,
|
|
109545
|
-
registerPull: () => registerPull
|
|
109904
|
+
registerPull: () => registerPull,
|
|
109905
|
+
registerLifecycle: () => registerLifecycle
|
|
109546
109906
|
});
|
|
109547
109907
|
function registerRegistry(parent) {
|
|
109548
109908
|
const registry2 = parent.command("registry").description("Generate registry artifacts for hosted skills services");
|
|
@@ -109551,12 +109911,12 @@ function registerRegistry(parent) {
|
|
|
109551
109911
|
async function writeJson2(value, space) {
|
|
109552
109912
|
const text3 = `${JSON.stringify(value, null, space)}
|
|
109553
109913
|
`;
|
|
109554
|
-
await new Promise((
|
|
109914
|
+
await new Promise((resolve25, reject2) => {
|
|
109555
109915
|
process.stdout.write(text3, (error61) => {
|
|
109556
109916
|
if (error61)
|
|
109557
109917
|
reject2(error61);
|
|
109558
109918
|
else
|
|
109559
|
-
|
|
109919
|
+
resolve25();
|
|
109560
109920
|
});
|
|
109561
109921
|
});
|
|
109562
109922
|
}
|
|
@@ -109698,6 +110058,25 @@ Versions of ${name}
|
|
|
109698
110058
|
}
|
|
109699
110059
|
});
|
|
109700
110060
|
}
|
|
110061
|
+
function registerLifecycle(parent) {
|
|
110062
|
+
parent.command("lifecycle").argument("<name>", "Skill name on the configured instance").requiredOption("--state <state>", "Lifecycle state: active or archived").requiredOption("--revision <revision>", "Exact revision id from skills info/get").option("--reason <reason>", "Bounded archive reason").option("--replacement <slug>", "Optional successor slug").option("--json", "Output as JSON", false).description("Change a hosted skill's active/archive lifecycle with an exact revision guard").action(async (name, options) => {
|
|
110063
|
+
if (options.state !== "active" && options.state !== "archived")
|
|
110064
|
+
throw new Error("--state must be active or archived");
|
|
110065
|
+
const client2 = await createRemoteSkillsClient();
|
|
110066
|
+
if (!client2)
|
|
110067
|
+
throw new Error("No API key configured, so there is no instance to update.");
|
|
110068
|
+
try {
|
|
110069
|
+
const result2 = await client2.setSkillLifecycle(name.trim(), options.state, { expectedRevisionId: options.revision, ...options.reason ? { reason: options.reason } : {}, ...options.replacement ? { replacementSlug: options.replacement } : {} });
|
|
110070
|
+
console.log(options.json ? JSON.stringify(result2, null, 2) : `Updated ${name} to ${options.state}.`);
|
|
110071
|
+
} catch (error61) {
|
|
110072
|
+
if (options.json)
|
|
110073
|
+
console.log(JSON.stringify({ error: error61.message }, null, 2));
|
|
110074
|
+
else
|
|
110075
|
+
console.error(source_default.red(error61.message));
|
|
110076
|
+
process.exitCode = 1;
|
|
110077
|
+
}
|
|
110078
|
+
});
|
|
110079
|
+
}
|
|
109701
110080
|
var init_registry2 = __esm(() => {
|
|
109702
110081
|
init_source();
|
|
109703
110082
|
init_registry_sync();
|
|
@@ -110013,7 +110392,7 @@ var exports_private_publications = {};
|
|
|
110013
110392
|
__export(exports_private_publications, {
|
|
110014
110393
|
registerPrivatePublications: () => registerPrivatePublications
|
|
110015
110394
|
});
|
|
110016
|
-
import { resolve as
|
|
110395
|
+
import { resolve as resolve25 } from "path";
|
|
110017
110396
|
function verifyOptions(options, action) {
|
|
110018
110397
|
if (options.userId === undefined !== (options.membershipId === undefined) || options.userId !== undefined && (!publicationUuid(options.userId) || !publicationUuid(options.membershipId)))
|
|
110019
110398
|
throw new PrivatePublicationError("PUBLICATION_CONTEXT_REQUIRED", "Provide both observed --user-id and --membership-id UUIDs.");
|
|
@@ -110058,9 +110437,9 @@ function registerPrivatePublications(parent) {
|
|
|
110058
110437
|
if (code2 === null)
|
|
110059
110438
|
return;
|
|
110060
110439
|
const context2 = options.userId ? { userId: options.userId, membershipId: options.membershipId } : undefined;
|
|
110061
|
-
const client2 = await privatePublicationSession(options.email, code2, context2), directory2 =
|
|
110440
|
+
const client2 = await privatePublicationSession(options.email, code2, context2), directory2 = resolve25(options.recoveryDir);
|
|
110062
110441
|
if (action === "publish")
|
|
110063
|
-
await preparePrivatePublication(client2,
|
|
110442
|
+
await preparePrivatePublication(client2, resolve25(args2[0]), directory2, { skillId: options.skillId, expectedCurrentVersionId: options.expectedCurrentVersion ?? null, idempotencyKey: options.idempotencyKey });
|
|
110064
110443
|
const result2 = action === "publish" || action === "resume" ? await continuePrivatePublication(client2, directory2, { confirm: true, waitMs: Number(options.waitSeconds) * 1000 }) : await inspectPrivatePublication(client2, directory2, action === "cancel");
|
|
110065
110444
|
print2(result2, options.json);
|
|
110066
110445
|
} catch (error61) {
|
|
@@ -110161,7 +110540,7 @@ __export(exports_auth, {
|
|
|
110161
110540
|
import { createInterface as createInterface3 } from "readline";
|
|
110162
110541
|
function prompt(question) {
|
|
110163
110542
|
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
110164
|
-
return new Promise((
|
|
110543
|
+
return new Promise((resolve26) => {
|
|
110165
110544
|
let settled = false;
|
|
110166
110545
|
const finish = (answer) => {
|
|
110167
110546
|
if (settled)
|
|
@@ -110170,7 +110549,7 @@ function prompt(question) {
|
|
|
110170
110549
|
rl.close();
|
|
110171
110550
|
if (answer === null)
|
|
110172
110551
|
process.exitCode = 130;
|
|
110173
|
-
|
|
110552
|
+
resolve26(answer);
|
|
110174
110553
|
};
|
|
110175
110554
|
rl.once("SIGINT", () => finish(null));
|
|
110176
110555
|
rl.once("close", () => finish(null));
|
|
@@ -110245,6 +110624,11 @@ function authIdentityPayload(authSource, live, cached2, offline = false) {
|
|
|
110245
110624
|
const userId = stringField2(user?.id) ?? cached2?.userId;
|
|
110246
110625
|
const orgId = stringField2(organization2?.id) ?? cached2?.orgId;
|
|
110247
110626
|
const role3 = stringField2(user?.role);
|
|
110627
|
+
const apiKey = recordField(root2.apiKey) ?? recordField(data?.apiKey);
|
|
110628
|
+
const apiKeyId = stringField2(apiKey?.id);
|
|
110629
|
+
const apiKeyScopes = apiKey?.scopes;
|
|
110630
|
+
const safeApiKeyId = apiKeyId && /^[A-Za-z0-9_-]{1,256}$/.test(apiKeyId) ? apiKeyId : undefined;
|
|
110631
|
+
const safeApiKeyScopes = Array.isArray(apiKeyScopes) && apiKeyScopes.length <= 32 && apiKeyScopes.every((scope) => typeof scope === "string" && scope.length <= 128 && /^(?:\*|[a-z][a-z0-9_-]*:(?:\*|[a-z][a-z0-9_-]*))$/.test(scope)) ? [...new Set(apiKeyScopes)] : undefined;
|
|
110248
110632
|
return {
|
|
110249
110633
|
status: "authenticated",
|
|
110250
110634
|
authSource,
|
|
@@ -110254,7 +110638,8 @@ function authIdentityPayload(authSource, live, cached2, offline = false) {
|
|
|
110254
110638
|
...orgName ? { organizationName: orgName } : {},
|
|
110255
110639
|
...userId ? { userId } : {},
|
|
110256
110640
|
...orgId ? { orgId } : {},
|
|
110257
|
-
...role3 ? { role: role3 } : {}
|
|
110641
|
+
...role3 ? { role: role3 } : {},
|
|
110642
|
+
...safeApiKeyId && safeApiKeyScopes ? { apiKeyId: safeApiKeyId, scopes: safeApiKeyScopes } : {}
|
|
110258
110643
|
};
|
|
110259
110644
|
}
|
|
110260
110645
|
function printWhoami(payload) {
|
|
@@ -110264,6 +110649,8 @@ function printWhoami(payload) {
|
|
|
110264
110649
|
console.log(source_default.bold("Org: ") + payload.organization);
|
|
110265
110650
|
if (payload.role)
|
|
110266
110651
|
console.log(source_default.bold("Role: ") + payload.role);
|
|
110652
|
+
if (payload.apiKeyId)
|
|
110653
|
+
console.log(source_default.bold("Key: ") + payload.apiKeyId);
|
|
110267
110654
|
if (payload.organizationName)
|
|
110268
110655
|
console.log(source_default.bold("Name: ") + payload.organizationName);
|
|
110269
110656
|
if (payload.authSource)
|
|
@@ -110278,7 +110665,7 @@ function printWhoami(payload) {
|
|
|
110278
110665
|
console.log(source_default.dim("(offline \u2014 showing cached info)"));
|
|
110279
110666
|
}
|
|
110280
110667
|
function sleep(ms) {
|
|
110281
|
-
return new Promise((
|
|
110668
|
+
return new Promise((resolve26) => setTimeout(resolve26, ms));
|
|
110282
110669
|
}
|
|
110283
110670
|
function browserCommand(url2) {
|
|
110284
110671
|
if (process.platform === "darwin")
|
|
@@ -110585,6 +110972,25 @@ function registerAuth(parent) {
|
|
|
110585
110972
|
writeCommandError(error61, "Failed to revoke API key", options.json);
|
|
110586
110973
|
}
|
|
110587
110974
|
});
|
|
110975
|
+
keys3.command("add-publish-scope").argument("<key-id>").requiredOption("--expected-scopes <csv>", "Current comma-separated scopes; stale values are refused").option("--json", "Output as JSON", false).description("Add skills:publish to one existing key without minting or rotating it").action(async (id3, options) => {
|
|
110976
|
+
try {
|
|
110977
|
+
const connection = await resolveSkillsConnection();
|
|
110978
|
+
if (!connection)
|
|
110979
|
+
throw new Error("A hosted Skills credential is required for key scope administration");
|
|
110980
|
+
const identity4 = await apiRequest("/api/auth/whoami", { headers: { Authorization: `Bearer ${connection.apiKey}` } }, connection.apiOrigin);
|
|
110981
|
+
const identityOrg = recordField(identity4.organization);
|
|
110982
|
+
const orgId = stringField2(identityOrg?.id);
|
|
110983
|
+
if (!orgId)
|
|
110984
|
+
throw new Error("The Skills authority did not return a tenant identity; refusing key scope administration");
|
|
110985
|
+
const result2 = await new RemoteSkillsClient(connection.apiKey, connection.apiOrigin).addSkillPublishScope(id3, options.expectedScopes.split(",").map((scope) => scope.trim()).filter(Boolean), orgId);
|
|
110986
|
+
if (options.json || !isTTY)
|
|
110987
|
+
console.log(JSON.stringify(result2, null, 2));
|
|
110988
|
+
else
|
|
110989
|
+
console.log(source_default.green(`Added skills:publish to ${id3}; scopes read back from the server.`));
|
|
110990
|
+
} catch (error61) {
|
|
110991
|
+
writeCommandError(error61, "Failed to add Skills publication scope", options.json);
|
|
110992
|
+
}
|
|
110993
|
+
});
|
|
110588
110994
|
auth.command("login").description("Sign in with browser/device code or email code").option("--email <email>", "Email address (non-interactive)").option("--code <code>", "Verification code (non-interactive)").option("--membership-id <id>", "Enroll an exact workspace membership into an explicit HASNA_PROFILE").option("--code-stdin", "Read a fresh six-digit code for workspace enrollment from stdin").option("--api-key <key>", "Verify and store an API key").option("--device", "Use browser/device-code login", false).option("--no-open", "Do not open a browser for device-code login").option("--poll", "Poll until browser authentication completes in non-interactive mode", false).option("--poll-timeout-ms <ms>", "Maximum time to wait for device-code login").option("--json", "Output result as JSON", false).action(async (options) => {
|
|
110589
110995
|
if (options.membershipId !== undefined) {
|
|
110590
110996
|
if (options.apiKey || options.device || options.code || options.poll) {
|
|
@@ -110780,7 +111186,7 @@ function promptInvitationProof(kind) {
|
|
|
110780
111186
|
const label = kind === "token" ? "invitation token" : "recovery code";
|
|
110781
111187
|
const character = kind === "token" ? /^[A-Za-z0-9_-]$/ : /^\d$/;
|
|
110782
111188
|
const { stdin, stderr: output2 } = process, wasRaw = stdin.isRaw, wasFlowing = stdin.readableFlowing;
|
|
110783
|
-
return new Promise((
|
|
111189
|
+
return new Promise((resolve26) => {
|
|
110784
111190
|
let value = "", settled = false, overflow = false;
|
|
110785
111191
|
const finish = (answer) => {
|
|
110786
111192
|
if (settled)
|
|
@@ -110797,7 +111203,7 @@ function promptInvitationProof(kind) {
|
|
|
110797
111203
|
`);
|
|
110798
111204
|
if (answer === null)
|
|
110799
111205
|
process.exitCode = 130;
|
|
110800
|
-
|
|
111206
|
+
resolve26(answer);
|
|
110801
111207
|
};
|
|
110802
111208
|
const cancel = () => finish(null);
|
|
110803
111209
|
const keypress = (text3, key) => {
|
|
@@ -119648,10 +120054,11 @@ var { registerPortableSkillCommands: registerPortableSkillCommands2 } = await Pr
|
|
|
119648
120054
|
registerPortableSkillCommands2(program2);
|
|
119649
120055
|
var { registerSchedule: registerSchedule2 } = await Promise.resolve().then(() => (init_schedule(), exports_schedule));
|
|
119650
120056
|
registerSchedule2(program2);
|
|
119651
|
-
var { registerRegistry: registerRegistry2, registerPull: registerPull2, registerVersions: registerVersions2 } = await Promise.resolve().then(() => (init_registry2(), exports_registry2));
|
|
120057
|
+
var { registerRegistry: registerRegistry2, registerPull: registerPull2, registerVersions: registerVersions2, registerLifecycle: registerLifecycle2 } = await Promise.resolve().then(() => (init_registry2(), exports_registry2));
|
|
119652
120058
|
registerRegistry2(program2);
|
|
119653
120059
|
registerPull2(program2);
|
|
119654
120060
|
registerVersions2(program2);
|
|
120061
|
+
registerLifecycle2(program2);
|
|
119655
120062
|
var { registerPublish: registerPublish2 } = await Promise.resolve().then(() => (init_publish(), exports_publish));
|
|
119656
120063
|
registerPublish2(program2);
|
|
119657
120064
|
var { registerPrivatePublications: registerPrivatePublications2 } = await Promise.resolve().then(() => (init_private_publications(), exports_private_publications));
|