@hasna/skills 0.10.46 → 0.10.48
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/bin/index.js +1211 -926
- package/bin/maintenance.js +7 -2
- package/bin/mcp.js +577 -360
- package/bin/migrate.js +7 -5
- package/bin/server.js +29 -10
- package/bin/worker.js +12 -7
- package/dist/index.js +826 -613
- package/dist/lib/agent-discovery.d.ts +1 -1
- package/dist/lib/claude-plugin-manifest-witness.d.ts +9 -0
- package/dist/lib/profile-client.d.ts +6 -2
- package/dist/lib/remote-files.d.ts +1 -1
- package/dist/lib/selection-cache.d.ts +5 -0
- package/dist/lib/selection-resolver.d.ts +1 -0
- package/dist/lib/session-reconciliation.d.ts +6 -3
- package/dist/sdk/index.js +796 -564
- package/dist/server/skills-api.d.ts +1 -0
- package/dist/server/types.d.ts +3 -1
- package/dist/types/skill-selection.d.ts +2 -0
- package/migrations/postgres/0011_skill_authorization_epoch.sql +22 -0
- package/migrations/sqlite/0011_skill_authorization_epoch.sql +17 -0
- package/package.json +1 -1
package/bin/mcp.js
CHANGED
|
@@ -20019,7 +20019,7 @@ var package_default;
|
|
|
20019
20019
|
var init_package = __esm(() => {
|
|
20020
20020
|
package_default = {
|
|
20021
20021
|
name: "@hasna/skills",
|
|
20022
|
-
version: "0.10.
|
|
20022
|
+
version: "0.10.48",
|
|
20023
20023
|
description: "Skills library for AI coding agents",
|
|
20024
20024
|
type: "module",
|
|
20025
20025
|
bin: {
|
|
@@ -38525,7 +38525,7 @@ var init_sumi_settings_witness = __esm(() => {
|
|
|
38525
38525
|
});
|
|
38526
38526
|
|
|
38527
38527
|
// src/lib/agent-policy-limits.ts
|
|
38528
|
-
import { basename as basename4, isAbsolute as isAbsolute4, resolve as resolve3 } from "path";
|
|
38528
|
+
import { basename as basename4, isAbsolute as isAbsolute4, join as join10, resolve as resolve3, sep as sep3 } from "path";
|
|
38529
38529
|
function object4(value) {
|
|
38530
38530
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
38531
38531
|
}
|
|
@@ -38666,7 +38666,9 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38666
38666
|
text(source.path);
|
|
38667
38667
|
requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
|
|
38668
38668
|
if (source.hashMode !== undefined)
|
|
38669
|
-
requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4", "sumi-settings-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
38669
|
+
requireBound(["bytes", "path-bytes", "claude-plugin-manifest-v1", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4", "sumi-settings-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
38670
|
+
if (source.hashMode === "claude-plugin-manifest-v1")
|
|
38671
|
+
requireBound(agent === "claude" && value.agent === "claude" && ["automatic", "reviewed"].includes(value.method) && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute4(source.path) && resolve3(source.path) === source.path && source.path.endsWith(join10(sep3, ".claude-plugin", "plugin.json")) && source.managedPlugins === undefined);
|
|
38670
38672
|
if (source.hashMode === "sumi-settings-v1")
|
|
38671
38673
|
requireBound(agent === "sumi" && value.agent === "sumi" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute4(source.path) && resolve3(source.path) === source.path && basename4(source.path) === "sumi.json");
|
|
38672
38674
|
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4"))
|
|
@@ -42386,10 +42388,10 @@ var require_resolve_block_map = __commonJS((exports) => {
|
|
|
42386
42388
|
let offset = bm.offset;
|
|
42387
42389
|
let commentEnd = null;
|
|
42388
42390
|
for (const collItem of bm.items) {
|
|
42389
|
-
const { start, key, sep:
|
|
42391
|
+
const { start, key, sep: sep4, value } = collItem;
|
|
42390
42392
|
const keyProps = resolveProps.resolveProps(start, {
|
|
42391
42393
|
indicator: "explicit-key-ind",
|
|
42392
|
-
next: key ??
|
|
42394
|
+
next: key ?? sep4?.[0],
|
|
42393
42395
|
offset,
|
|
42394
42396
|
onError,
|
|
42395
42397
|
parentIndent: bm.indent,
|
|
@@ -42403,7 +42405,7 @@ var require_resolve_block_map = __commonJS((exports) => {
|
|
|
42403
42405
|
else if ("indent" in key && key.indent !== bm.indent)
|
|
42404
42406
|
onError(offset, "BAD_INDENT", startColMsg);
|
|
42405
42407
|
}
|
|
42406
|
-
if (!keyProps.anchor && !keyProps.tag && !
|
|
42408
|
+
if (!keyProps.anchor && !keyProps.tag && !sep4) {
|
|
42407
42409
|
commentEnd = keyProps.end;
|
|
42408
42410
|
if (keyProps.comment) {
|
|
42409
42411
|
if (map3.comment)
|
|
@@ -42428,7 +42430,7 @@ var require_resolve_block_map = __commonJS((exports) => {
|
|
|
42428
42430
|
ctx.atKey = false;
|
|
42429
42431
|
if (utilMapIncludes.mapIncludes(ctx, map3.items, keyNode))
|
|
42430
42432
|
onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
|
|
42431
|
-
const valueProps = resolveProps.resolveProps(
|
|
42433
|
+
const valueProps = resolveProps.resolveProps(sep4 ?? [], {
|
|
42432
42434
|
indicator: "map-value-ind",
|
|
42433
42435
|
next: value,
|
|
42434
42436
|
offset: keyNode.range[2],
|
|
@@ -42444,7 +42446,7 @@ var require_resolve_block_map = __commonJS((exports) => {
|
|
|
42444
42446
|
if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
|
|
42445
42447
|
onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
|
|
42446
42448
|
}
|
|
42447
|
-
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset,
|
|
42449
|
+
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep4, null, valueProps, onError);
|
|
42448
42450
|
if (ctx.schema.compat)
|
|
42449
42451
|
utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
|
|
42450
42452
|
offset = valueNode.range[2];
|
|
@@ -42530,7 +42532,7 @@ var require_resolve_end = __commonJS((exports) => {
|
|
|
42530
42532
|
let comment = "";
|
|
42531
42533
|
if (end) {
|
|
42532
42534
|
let hasSpace = false;
|
|
42533
|
-
let
|
|
42535
|
+
let sep4 = "";
|
|
42534
42536
|
for (const token of end) {
|
|
42535
42537
|
const { source, type } = token;
|
|
42536
42538
|
switch (type) {
|
|
@@ -42544,13 +42546,13 @@ var require_resolve_end = __commonJS((exports) => {
|
|
|
42544
42546
|
if (!comment)
|
|
42545
42547
|
comment = cb;
|
|
42546
42548
|
else
|
|
42547
|
-
comment +=
|
|
42548
|
-
|
|
42549
|
+
comment += sep4 + cb;
|
|
42550
|
+
sep4 = "";
|
|
42549
42551
|
break;
|
|
42550
42552
|
}
|
|
42551
42553
|
case "newline":
|
|
42552
42554
|
if (comment)
|
|
42553
|
-
|
|
42555
|
+
sep4 += source;
|
|
42554
42556
|
hasSpace = true;
|
|
42555
42557
|
break;
|
|
42556
42558
|
default:
|
|
@@ -42590,18 +42592,18 @@ var require_resolve_flow_collection = __commonJS((exports) => {
|
|
|
42590
42592
|
let offset = fc.offset + fc.start.source.length;
|
|
42591
42593
|
for (let i = 0;i < fc.items.length; ++i) {
|
|
42592
42594
|
const collItem = fc.items[i];
|
|
42593
|
-
const { start, key, sep:
|
|
42595
|
+
const { start, key, sep: sep4, value } = collItem;
|
|
42594
42596
|
const props = resolveProps.resolveProps(start, {
|
|
42595
42597
|
flow: fcName,
|
|
42596
42598
|
indicator: "explicit-key-ind",
|
|
42597
|
-
next: key ??
|
|
42599
|
+
next: key ?? sep4?.[0],
|
|
42598
42600
|
offset,
|
|
42599
42601
|
onError,
|
|
42600
42602
|
parentIndent: fc.indent,
|
|
42601
42603
|
startOnNewline: false
|
|
42602
42604
|
});
|
|
42603
42605
|
if (!props.found) {
|
|
42604
|
-
if (!props.anchor && !props.tag && !
|
|
42606
|
+
if (!props.anchor && !props.tag && !sep4 && !value) {
|
|
42605
42607
|
if (i === 0 && props.comma)
|
|
42606
42608
|
onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
|
|
42607
42609
|
else if (i < fc.items.length - 1)
|
|
@@ -42653,8 +42655,8 @@ var require_resolve_flow_collection = __commonJS((exports) => {
|
|
|
42653
42655
|
}
|
|
42654
42656
|
}
|
|
42655
42657
|
}
|
|
42656
|
-
if (!isMap && !
|
|
42657
|
-
const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end,
|
|
42658
|
+
if (!isMap && !sep4 && !props.found) {
|
|
42659
|
+
const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep4, null, props, onError);
|
|
42658
42660
|
coll.items.push(valueNode);
|
|
42659
42661
|
offset = valueNode.range[2];
|
|
42660
42662
|
if (isBlock(value))
|
|
@@ -42666,7 +42668,7 @@ var require_resolve_flow_collection = __commonJS((exports) => {
|
|
|
42666
42668
|
if (isBlock(key))
|
|
42667
42669
|
onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
|
|
42668
42670
|
ctx.atKey = false;
|
|
42669
|
-
const valueProps = resolveProps.resolveProps(
|
|
42671
|
+
const valueProps = resolveProps.resolveProps(sep4 ?? [], {
|
|
42670
42672
|
flow: fcName,
|
|
42671
42673
|
indicator: "map-value-ind",
|
|
42672
42674
|
next: value,
|
|
@@ -42677,8 +42679,8 @@ var require_resolve_flow_collection = __commonJS((exports) => {
|
|
|
42677
42679
|
});
|
|
42678
42680
|
if (valueProps.found) {
|
|
42679
42681
|
if (!isMap && !props.found && ctx.options.strict) {
|
|
42680
|
-
if (
|
|
42681
|
-
for (const st of
|
|
42682
|
+
if (sep4)
|
|
42683
|
+
for (const st of sep4) {
|
|
42682
42684
|
if (st === valueProps.found)
|
|
42683
42685
|
break;
|
|
42684
42686
|
if (st.type === "newline") {
|
|
@@ -42695,7 +42697,7 @@ var require_resolve_flow_collection = __commonJS((exports) => {
|
|
|
42695
42697
|
else
|
|
42696
42698
|
onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
|
|
42697
42699
|
}
|
|
42698
|
-
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end,
|
|
42700
|
+
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep4, null, valueProps, onError) : null;
|
|
42699
42701
|
if (valueNode) {
|
|
42700
42702
|
if (isBlock(value))
|
|
42701
42703
|
onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
|
|
@@ -42872,7 +42874,7 @@ var require_resolve_block_scalar = __commonJS((exports) => {
|
|
|
42872
42874
|
chompStart = i + 1;
|
|
42873
42875
|
}
|
|
42874
42876
|
let value = "";
|
|
42875
|
-
let
|
|
42877
|
+
let sep4 = "";
|
|
42876
42878
|
let prevMoreIndented = false;
|
|
42877
42879
|
for (let i = 0;i < contentStart; ++i)
|
|
42878
42880
|
value += lines[i][0].slice(trimIndent) + `
|
|
@@ -42890,33 +42892,33 @@ var require_resolve_block_scalar = __commonJS((exports) => {
|
|
|
42890
42892
|
indent = "";
|
|
42891
42893
|
}
|
|
42892
42894
|
if (type === Scalar.Scalar.BLOCK_LITERAL) {
|
|
42893
|
-
value +=
|
|
42894
|
-
|
|
42895
|
+
value += sep4 + indent.slice(trimIndent) + content;
|
|
42896
|
+
sep4 = `
|
|
42895
42897
|
`;
|
|
42896
42898
|
} else if (indent.length > trimIndent || content[0] === "\t") {
|
|
42897
|
-
if (
|
|
42898
|
-
|
|
42899
|
+
if (sep4 === " ")
|
|
42900
|
+
sep4 = `
|
|
42899
42901
|
`;
|
|
42900
|
-
else if (!prevMoreIndented &&
|
|
42902
|
+
else if (!prevMoreIndented && sep4 === `
|
|
42901
42903
|
`)
|
|
42902
|
-
|
|
42904
|
+
sep4 = `
|
|
42903
42905
|
|
|
42904
42906
|
`;
|
|
42905
|
-
value +=
|
|
42906
|
-
|
|
42907
|
+
value += sep4 + indent.slice(trimIndent) + content;
|
|
42908
|
+
sep4 = `
|
|
42907
42909
|
`;
|
|
42908
42910
|
prevMoreIndented = true;
|
|
42909
42911
|
} else if (content === "") {
|
|
42910
|
-
if (
|
|
42912
|
+
if (sep4 === `
|
|
42911
42913
|
`)
|
|
42912
42914
|
value += `
|
|
42913
42915
|
`;
|
|
42914
42916
|
else
|
|
42915
|
-
|
|
42917
|
+
sep4 = `
|
|
42916
42918
|
`;
|
|
42917
42919
|
} else {
|
|
42918
|
-
value +=
|
|
42919
|
-
|
|
42920
|
+
value += sep4 + content;
|
|
42921
|
+
sep4 = " ";
|
|
42920
42922
|
prevMoreIndented = false;
|
|
42921
42923
|
}
|
|
42922
42924
|
}
|
|
@@ -43097,27 +43099,27 @@ var require_resolve_flow_scalar = __commonJS((exports) => {
|
|
|
43097
43099
|
if (!match)
|
|
43098
43100
|
return source;
|
|
43099
43101
|
let res = match[1];
|
|
43100
|
-
let
|
|
43102
|
+
let sep4 = " ";
|
|
43101
43103
|
let pos = first.lastIndex;
|
|
43102
43104
|
line.lastIndex = pos;
|
|
43103
43105
|
while (match = line.exec(source)) {
|
|
43104
43106
|
if (match[1] === "") {
|
|
43105
|
-
if (
|
|
43107
|
+
if (sep4 === `
|
|
43106
43108
|
`)
|
|
43107
|
-
res +=
|
|
43109
|
+
res += sep4;
|
|
43108
43110
|
else
|
|
43109
|
-
|
|
43111
|
+
sep4 = `
|
|
43110
43112
|
`;
|
|
43111
43113
|
} else {
|
|
43112
|
-
res +=
|
|
43113
|
-
|
|
43114
|
+
res += sep4 + match[1];
|
|
43115
|
+
sep4 = " ";
|
|
43114
43116
|
}
|
|
43115
43117
|
pos = line.lastIndex;
|
|
43116
43118
|
}
|
|
43117
43119
|
const last = /[ \t]*(.*)/sy;
|
|
43118
43120
|
last.lastIndex = pos;
|
|
43119
43121
|
match = last.exec(source);
|
|
43120
|
-
return res +
|
|
43122
|
+
return res + sep4 + (match?.[1] ?? "");
|
|
43121
43123
|
}
|
|
43122
43124
|
function doubleQuotedValue(source, onError) {
|
|
43123
43125
|
let res = "";
|
|
@@ -43898,14 +43900,14 @@ var require_cst_stringify = __commonJS((exports) => {
|
|
|
43898
43900
|
}
|
|
43899
43901
|
}
|
|
43900
43902
|
}
|
|
43901
|
-
function stringifyItem({ start, key, sep:
|
|
43903
|
+
function stringifyItem({ start, key, sep: sep4, value }) {
|
|
43902
43904
|
let res = "";
|
|
43903
43905
|
for (const st of start)
|
|
43904
43906
|
res += st.source;
|
|
43905
43907
|
if (key)
|
|
43906
43908
|
res += stringifyToken(key);
|
|
43907
|
-
if (
|
|
43908
|
-
for (const st of
|
|
43909
|
+
if (sep4)
|
|
43910
|
+
for (const st of sep4)
|
|
43909
43911
|
res += st.source;
|
|
43910
43912
|
if (value)
|
|
43911
43913
|
res += stringifyToken(value);
|
|
@@ -45053,18 +45055,18 @@ var require_parser = __commonJS((exports) => {
|
|
|
45053
45055
|
if (this.type === "map-value-ind") {
|
|
45054
45056
|
const prev = getPrevProps(this.peek(2));
|
|
45055
45057
|
const start = getFirstKeyStartProps(prev);
|
|
45056
|
-
let
|
|
45058
|
+
let sep4;
|
|
45057
45059
|
if (scalar.end) {
|
|
45058
|
-
|
|
45059
|
-
|
|
45060
|
+
sep4 = scalar.end;
|
|
45061
|
+
sep4.push(this.sourceToken);
|
|
45060
45062
|
delete scalar.end;
|
|
45061
45063
|
} else
|
|
45062
|
-
|
|
45064
|
+
sep4 = [this.sourceToken];
|
|
45063
45065
|
const map3 = {
|
|
45064
45066
|
type: "block-map",
|
|
45065
45067
|
offset: scalar.offset,
|
|
45066
45068
|
indent: scalar.indent,
|
|
45067
|
-
items: [{ start, key: scalar, sep:
|
|
45069
|
+
items: [{ start, key: scalar, sep: sep4 }]
|
|
45068
45070
|
};
|
|
45069
45071
|
this.onKeyLine = true;
|
|
45070
45072
|
this.stack[this.stack.length - 1] = map3;
|
|
@@ -45218,15 +45220,15 @@ var require_parser = __commonJS((exports) => {
|
|
|
45218
45220
|
} else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
|
|
45219
45221
|
const start2 = getFirstKeyStartProps(it.start);
|
|
45220
45222
|
const key = it.key;
|
|
45221
|
-
const
|
|
45222
|
-
|
|
45223
|
+
const sep4 = it.sep;
|
|
45224
|
+
sep4.push(this.sourceToken);
|
|
45223
45225
|
delete it.key;
|
|
45224
45226
|
delete it.sep;
|
|
45225
45227
|
this.stack.push({
|
|
45226
45228
|
type: "block-map",
|
|
45227
45229
|
offset: this.offset,
|
|
45228
45230
|
indent: this.indent,
|
|
45229
|
-
items: [{ start: start2, key, sep:
|
|
45231
|
+
items: [{ start: start2, key, sep: sep4 }]
|
|
45230
45232
|
});
|
|
45231
45233
|
} else if (start.length > 0) {
|
|
45232
45234
|
it.sep = it.sep.concat(start, this.sourceToken);
|
|
@@ -45420,13 +45422,13 @@ var require_parser = __commonJS((exports) => {
|
|
|
45420
45422
|
const prev = getPrevProps(parent);
|
|
45421
45423
|
const start = getFirstKeyStartProps(prev);
|
|
45422
45424
|
fixFlowSeqItems(fc);
|
|
45423
|
-
const
|
|
45424
|
-
|
|
45425
|
+
const sep4 = fc.end.splice(1, fc.end.length);
|
|
45426
|
+
sep4.push(this.sourceToken);
|
|
45425
45427
|
const map3 = {
|
|
45426
45428
|
type: "block-map",
|
|
45427
45429
|
offset: fc.offset,
|
|
45428
45430
|
indent: fc.indent,
|
|
45429
|
-
items: [{ start, key: fc, sep:
|
|
45431
|
+
items: [{ start, key: fc, sep: sep4 }]
|
|
45430
45432
|
};
|
|
45431
45433
|
this.onKeyLine = true;
|
|
45432
45434
|
this.stack[this.stack.length - 1] = map3;
|
|
@@ -45699,7 +45701,7 @@ var init_dist = __esm(() => {
|
|
|
45699
45701
|
});
|
|
45700
45702
|
|
|
45701
45703
|
// src/lib/agent-hermes.ts
|
|
45702
|
-
import { dirname as dirname5, isAbsolute as isAbsolute5, join as
|
|
45704
|
+
import { dirname as dirname5, isAbsolute as isAbsolute5, join as join11, resolve as resolve4 } from "path";
|
|
45703
45705
|
function object5(value) {
|
|
45704
45706
|
return Boolean(value && typeof value === "object" && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null));
|
|
45705
45707
|
}
|
|
@@ -45733,7 +45735,7 @@ function assertHermesEnvironment(home) {
|
|
|
45733
45735
|
throw new Error(`NATIVE_SKILL_DRIFT: Hermes ${variable} requires a dedicated discovery adapter; unset it before using this adapter`);
|
|
45734
45736
|
}
|
|
45735
45737
|
const selected = process.env.HERMES_HOME?.trim();
|
|
45736
|
-
if (selected && (!isAbsolute5(selected) || resolve4(selected) !==
|
|
45738
|
+
if (selected && (!isAbsolute5(selected) || resolve4(selected) !== join11(resolve4(home), ".hermes")))
|
|
45737
45739
|
throw new Error("NATIVE_SKILL_DRIFT: custom Hermes homes/profiles require their own reviewed bridge");
|
|
45738
45740
|
if (process.env.HERMES_ENABLE_PROJECT_PLUGINS?.trim() && !["0", "false", "no", "off"].includes(process.env.HERMES_ENABLE_PROJECT_PLUGINS.trim().toLowerCase()))
|
|
45739
45741
|
throw new Error("NATIVE_SKILL_DRIFT: Hermes project plugins require a dedicated discovery review");
|
|
@@ -45745,7 +45747,7 @@ var init_agent_hermes = __esm(() => {
|
|
|
45745
45747
|
// src/lib/agent-discovery-directories.ts
|
|
45746
45748
|
import { createHash as createHash3 } from "crypto";
|
|
45747
45749
|
import { lstatSync as lstatSync6, opendirSync } from "fs";
|
|
45748
|
-
import { dirname as dirname6, isAbsolute as isAbsolute6, join as
|
|
45750
|
+
import { dirname as dirname6, isAbsolute as isAbsolute6, join as join12, resolve as resolve5 } from "path";
|
|
45749
45751
|
function need2(value, message) {
|
|
45750
45752
|
if (!value)
|
|
45751
45753
|
throw new Error(message);
|
|
@@ -45783,7 +45785,7 @@ function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
|
|
|
45783
45785
|
}
|
|
45784
45786
|
need2(new Set(names).size === names.length, "Ambiguous native discovery directory names");
|
|
45785
45787
|
for (const name of names.sort()) {
|
|
45786
|
-
const child =
|
|
45788
|
+
const child = join12(current, name), childRelative = relative3 ? `${relative3}/${name}` : name;
|
|
45787
45789
|
if (omittedRoots.includes(child))
|
|
45788
45790
|
continue;
|
|
45789
45791
|
need2(child.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
|
|
@@ -45831,7 +45833,7 @@ function verifyDiscoveryDirectoryProjection(directories, omittedRoots) {
|
|
|
45831
45833
|
need2(Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && value[0] && !isAbsolute6(value[0]) && !value[0].split("/").some((part) => !part || part === "." || part === "..") && ["file", "directory"].includes(value[1]) && row === JSON.stringify(value) + `
|
|
45832
45834
|
`, "Invalid reviewed directory member");
|
|
45833
45835
|
hash2.update(row);
|
|
45834
|
-
const path =
|
|
45836
|
+
const path = join12(directory.path, value[0]);
|
|
45835
45837
|
if (!omittedRoots.some((root) => path === root || path.startsWith(root + "/")))
|
|
45836
45838
|
kept.push(row);
|
|
45837
45839
|
}
|
|
@@ -45935,7 +45937,7 @@ var init_agent_discovery_bytes = __esm(() => {
|
|
|
45935
45937
|
// src/lib/agent-discovery-path-bytes.ts
|
|
45936
45938
|
import { createHash as createHash5 } from "crypto";
|
|
45937
45939
|
import { lstatSync as lstatSync8, readlinkSync } from "fs";
|
|
45938
|
-
import { dirname as dirname8, isAbsolute as isAbsolute8, join as
|
|
45940
|
+
import { dirname as dirname8, isAbsolute as isAbsolute8, join as join13, parse as parse7, resolve as resolve7, sep as sep4 } from "path";
|
|
45939
45941
|
function identity2(stat, mutable = false) {
|
|
45940
45942
|
return {
|
|
45941
45943
|
dev: String(stat.dev),
|
|
@@ -45953,7 +45955,7 @@ function canonical2(path) {
|
|
|
45953
45955
|
function trace(path) {
|
|
45954
45956
|
canonical2(path);
|
|
45955
45957
|
const rows = [], paths = [];
|
|
45956
|
-
let metadataBytes = 0, steps = 0, links = 0, cursor = parse7(path).root, pending = path.slice(cursor.length).split(
|
|
45958
|
+
let metadataBytes = 0, steps = 0, links = 0, cursor = parse7(path).root, pending = path.slice(cursor.length).split(sep4);
|
|
45957
45959
|
function record4(path2, row) {
|
|
45958
45960
|
const value = { path: path2, ...row };
|
|
45959
45961
|
metadataBytes += Buffer.byteLength(JSON.stringify(value));
|
|
@@ -45979,7 +45981,7 @@ function trace(path) {
|
|
|
45979
45981
|
cursor = dirname8(cursor);
|
|
45980
45982
|
continue;
|
|
45981
45983
|
}
|
|
45982
|
-
const candidate =
|
|
45984
|
+
const candidate = join13(cursor, component);
|
|
45983
45985
|
if (candidate.length > AGENT_POLICY_LIMITS.pathCharacters)
|
|
45984
45986
|
throw new Error("Discovery resolved path length limit exceeded");
|
|
45985
45987
|
const stat = lstatSync8(candidate, { bigint: true, throwIfNoEntry: false });
|
|
@@ -46001,7 +46003,7 @@ function trace(path) {
|
|
|
46001
46003
|
root();
|
|
46002
46004
|
}
|
|
46003
46005
|
const remainder = isAbsolute8(target) ? target.slice(parse7(target).root.length) : target;
|
|
46004
|
-
pending = [...remainder.split(
|
|
46006
|
+
pending = [...remainder.split(sep4), ...pending];
|
|
46005
46007
|
if (pending.length + steps > AGENT_POLICY_LIMITS.discoveryPathSteps)
|
|
46006
46008
|
throw new Error("Discovery path step limit exceeded");
|
|
46007
46009
|
continue;
|
|
@@ -46025,7 +46027,7 @@ function hashDiscoveryPathFile(path, budget2, changes) {
|
|
|
46025
46027
|
let createsMissingPath = false;
|
|
46026
46028
|
if (before.missing !== null && changes) {
|
|
46027
46029
|
for (const target of changes.keys()) {
|
|
46028
|
-
if (target === before.missing || target.startsWith(before.missing +
|
|
46030
|
+
if (target === before.missing || target.startsWith(before.missing + sep4)) {
|
|
46029
46031
|
createsMissingPath = true;
|
|
46030
46032
|
break;
|
|
46031
46033
|
}
|
|
@@ -46050,10 +46052,148 @@ var init_agent_discovery_path_bytes = __esm(() => {
|
|
|
46050
46052
|
init_agent_discovery_bytes();
|
|
46051
46053
|
});
|
|
46052
46054
|
|
|
46053
|
-
// src/lib/
|
|
46055
|
+
// src/lib/claude-plugin-manifest-witness.ts
|
|
46054
46056
|
import { createHash as createHash6 } from "crypto";
|
|
46057
|
+
function requireValue(value, reason) {
|
|
46058
|
+
if (!value)
|
|
46059
|
+
throw new Error("Claude plugin manifest " + reason);
|
|
46060
|
+
}
|
|
46061
|
+
function parse8(text2) {
|
|
46062
|
+
requireValue(Buffer.byteLength(text2, "utf8") <= CLAUDE_PLUGIN_MANIFEST_LIMITS.bytes, "exceeds its byte limit");
|
|
46063
|
+
let at = 0, nodes = 0;
|
|
46064
|
+
const numberPattern = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/y;
|
|
46065
|
+
const space = () => {
|
|
46066
|
+
while (at < text2.length && /[\x20\t\r\n]/.test(text2[at]))
|
|
46067
|
+
at++;
|
|
46068
|
+
};
|
|
46069
|
+
function string5() {
|
|
46070
|
+
requireValue(text2[at] === '"', "contains invalid JSON");
|
|
46071
|
+
const start = at++;
|
|
46072
|
+
while (at < text2.length) {
|
|
46073
|
+
const character = text2[at++];
|
|
46074
|
+
if (character === '"') {
|
|
46075
|
+
let value2;
|
|
46076
|
+
try {
|
|
46077
|
+
value2 = JSON.parse(text2.slice(start, at));
|
|
46078
|
+
} catch {
|
|
46079
|
+
throw new Error("Claude plugin manifest contains invalid JSON string");
|
|
46080
|
+
}
|
|
46081
|
+
requireValue(value2.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters, "exceeds its string limit");
|
|
46082
|
+
return value2;
|
|
46083
|
+
}
|
|
46084
|
+
if (character === "\\")
|
|
46085
|
+
at++;
|
|
46086
|
+
}
|
|
46087
|
+
throw new Error("Claude plugin manifest contains an unterminated JSON string");
|
|
46088
|
+
}
|
|
46089
|
+
function value(depth) {
|
|
46090
|
+
requireValue(depth <= CLAUDE_PLUGIN_MANIFEST_LIMITS.depth && ++nodes <= CLAUDE_PLUGIN_MANIFEST_LIMITS.nodes, "exceeds its nesting or node limit");
|
|
46091
|
+
space();
|
|
46092
|
+
const character = text2[at];
|
|
46093
|
+
if (character === '"')
|
|
46094
|
+
return { kind: "string", value: string5() };
|
|
46095
|
+
if (character === "{" || character === "[") {
|
|
46096
|
+
at++;
|
|
46097
|
+
space();
|
|
46098
|
+
const object6 = character === "{", end = object6 ? "}" : "]", entries = [], items = [], keys = new Set;
|
|
46099
|
+
if (text2[at] !== end)
|
|
46100
|
+
while (true) {
|
|
46101
|
+
if (object6) {
|
|
46102
|
+
space();
|
|
46103
|
+
const key = string5();
|
|
46104
|
+
requireValue(!keys.has(key), "contains a duplicate JSON key");
|
|
46105
|
+
keys.add(key);
|
|
46106
|
+
space();
|
|
46107
|
+
requireValue(text2[at++] === ":", "contains invalid JSON");
|
|
46108
|
+
entries.push([key, value(depth + 1)]);
|
|
46109
|
+
} else
|
|
46110
|
+
items.push(value(depth + 1));
|
|
46111
|
+
space();
|
|
46112
|
+
if (text2[at] === end)
|
|
46113
|
+
break;
|
|
46114
|
+
requireValue(text2[at++] === ",", "contains invalid JSON");
|
|
46115
|
+
}
|
|
46116
|
+
at++;
|
|
46117
|
+
return object6 ? { kind: "object", entries } : { kind: "array", items };
|
|
46118
|
+
}
|
|
46119
|
+
for (const literal3 of ["true", "false", "null"])
|
|
46120
|
+
if (text2.startsWith(literal3, at)) {
|
|
46121
|
+
at += literal3.length;
|
|
46122
|
+
return { kind: "literal", value: literal3 };
|
|
46123
|
+
}
|
|
46124
|
+
numberPattern.lastIndex = at;
|
|
46125
|
+
const number5 = numberPattern.exec(text2);
|
|
46126
|
+
requireValue(number5, "contains invalid JSON");
|
|
46127
|
+
at += number5[0].length;
|
|
46128
|
+
return { kind: "number", value: number5[0] };
|
|
46129
|
+
}
|
|
46130
|
+
const root = value(0);
|
|
46131
|
+
space();
|
|
46132
|
+
requireValue(at === text2.length && root.kind === "object", "requires a JSON object without trailing content");
|
|
46133
|
+
return root;
|
|
46134
|
+
}
|
|
46135
|
+
function canonical3(value) {
|
|
46136
|
+
if (value.kind === "string")
|
|
46137
|
+
return JSON.stringify(value.value);
|
|
46138
|
+
if (value.kind === "number")
|
|
46139
|
+
return value.value;
|
|
46140
|
+
if (value.kind === "literal")
|
|
46141
|
+
return value.value;
|
|
46142
|
+
if (value.kind === "array")
|
|
46143
|
+
return "[" + value.items.map(canonical3).join(",") + "]";
|
|
46144
|
+
return "{" + value.entries.map(([key, item]) => JSON.stringify(key) + ":" + canonical3(item)).join(",") + "}";
|
|
46145
|
+
}
|
|
46146
|
+
function validateText(value, field) {
|
|
46147
|
+
requireValue(value?.kind === "string" && value.value.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters, "has an invalid " + field + " field");
|
|
46148
|
+
}
|
|
46149
|
+
function validateDescriptiveFields(manifest) {
|
|
46150
|
+
const values = new Map(manifest.entries);
|
|
46151
|
+
for (const field of ["description", "version", "homepage", "license"]) {
|
|
46152
|
+
const value = values.get(field);
|
|
46153
|
+
if (value !== undefined)
|
|
46154
|
+
validateText(value, field);
|
|
46155
|
+
}
|
|
46156
|
+
const author = values.get("author");
|
|
46157
|
+
if (author !== undefined) {
|
|
46158
|
+
if (author.kind === "string")
|
|
46159
|
+
validateText(author, "author");
|
|
46160
|
+
else {
|
|
46161
|
+
requireValue(author.kind === "object" && author.entries.every(([key, value]) => ["name", "email", "url"].includes(key) && value.kind === "string" && value.value.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters), "has an invalid author field");
|
|
46162
|
+
}
|
|
46163
|
+
}
|
|
46164
|
+
const repository = values.get("repository");
|
|
46165
|
+
if (repository !== undefined) {
|
|
46166
|
+
if (repository.kind === "string")
|
|
46167
|
+
validateText(repository, "repository");
|
|
46168
|
+
else
|
|
46169
|
+
requireValue(repository.kind === "object" && repository.entries.every(([key, value]) => ["type", "url", "directory"].includes(key) && value.kind === "string" && value.value.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters), "has an invalid repository field");
|
|
46170
|
+
}
|
|
46171
|
+
const keywords = values.get("keywords");
|
|
46172
|
+
if (keywords !== undefined)
|
|
46173
|
+
requireValue(keywords.kind === "array" && keywords.items.every((value) => value.kind === "string" && value.value.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters), "has an invalid keywords field");
|
|
46174
|
+
}
|
|
46175
|
+
function hashClaudePluginManifest(text2) {
|
|
46176
|
+
const manifest = parse8(text2);
|
|
46177
|
+
validateDescriptiveFields(manifest);
|
|
46178
|
+
const discovery = { kind: "object", entries: manifest.entries.filter(([key]) => !DESCRIPTIVE_FIELDS.has(key)) };
|
|
46179
|
+
return createHash6("sha256").update(canonical3(discovery)).digest("hex");
|
|
46180
|
+
}
|
|
46181
|
+
function projectReviewedClaudePluginManifest(text2, reviewedSha256) {
|
|
46182
|
+
if (!/^[a-f0-9]{64}$/.test(reviewedSha256) || createHash6("sha256").update(text2).digest("hex") !== reviewedSha256) {
|
|
46183
|
+
throw new Error("Reviewed Claude plugin manifest changed before semantic projection");
|
|
46184
|
+
}
|
|
46185
|
+
return hashClaudePluginManifest(text2);
|
|
46186
|
+
}
|
|
46187
|
+
var CLAUDE_PLUGIN_MANIFEST_LIMITS, DESCRIPTIVE_FIELDS;
|
|
46188
|
+
var init_claude_plugin_manifest_witness = __esm(() => {
|
|
46189
|
+
CLAUDE_PLUGIN_MANIFEST_LIMITS = Object.freeze({ bytes: 1024 * 1024, depth: 32, nodes: 65536, stringCharacters: 16384 });
|
|
46190
|
+
DESCRIPTIVE_FIELDS = new Set(["description", "version", "author", "homepage", "repository", "license", "keywords"]);
|
|
46191
|
+
});
|
|
46192
|
+
|
|
46193
|
+
// src/lib/skill-bundle.ts
|
|
46194
|
+
import { createHash as createHash7 } from "crypto";
|
|
46055
46195
|
import { readFileSync as readFileSync9, readdirSync as readdirSync4, statSync as statSync6 } from "fs";
|
|
46056
|
-
import { join as
|
|
46196
|
+
import { join as join14, relative as relative3 } from "path";
|
|
46057
46197
|
import { createGunzip } from "zlib";
|
|
46058
46198
|
function isDotenvFile(lower) {
|
|
46059
46199
|
if (lower === ".env" || lower.startsWith(".env."))
|
|
@@ -46083,7 +46223,7 @@ function ownBytes(view) {
|
|
|
46083
46223
|
return out;
|
|
46084
46224
|
}
|
|
46085
46225
|
function sha256Hex(bytes) {
|
|
46086
|
-
return
|
|
46226
|
+
return createHash7("sha256").update(bytes).digest("hex");
|
|
46087
46227
|
}
|
|
46088
46228
|
function collectSkillBundleEntries(dir) {
|
|
46089
46229
|
const entries = [];
|
|
@@ -46092,7 +46232,7 @@ function collectSkillBundleEntries(dir) {
|
|
|
46092
46232
|
}
|
|
46093
46233
|
function walk(root, current, out) {
|
|
46094
46234
|
for (const entry of readdirSync4(current, { withFileTypes: true })) {
|
|
46095
|
-
const absolute =
|
|
46235
|
+
const absolute = join14(current, entry.name);
|
|
46096
46236
|
const rel = relative3(root, absolute).split("\\").join("/");
|
|
46097
46237
|
const isRootLevel = !rel.includes("/");
|
|
46098
46238
|
if (ANY_SEGMENT_EXCLUDES.has(entry.name.toLowerCase()))
|
|
@@ -46618,24 +46758,24 @@ var init_profile_limits = __esm(() => {
|
|
|
46618
46758
|
});
|
|
46619
46759
|
|
|
46620
46760
|
// src/lib/selection-cache.ts
|
|
46621
|
-
import { createHash as
|
|
46761
|
+
import { createHash as createHash8, randomUUID } from "crypto";
|
|
46622
46762
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
46623
46763
|
import { closeSync as closeSync7, constants as constants4, fstatSync as fstatSync7, fsyncSync, linkSync, lstatSync as lstatSync9, mkdirSync as mkdirSync3, openSync as openSync7, readFileSync as readFileSync10, readlinkSync as readlinkSync2, readSync as readSync4, renameSync, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
|
|
46624
46764
|
import { hostname as hostname3 } from "os";
|
|
46625
|
-
import { dirname as dirname9, join as
|
|
46765
|
+
import { dirname as dirname9, join as join15, parse as parse9, resolve as resolve8 } from "path";
|
|
46626
46766
|
import { isDeepStrictEqual } from "util";
|
|
46627
46767
|
function selectionCacheRoot(options = {}) {
|
|
46628
|
-
return resolve8(options.cacheDir ??
|
|
46768
|
+
return resolve8(options.cacheDir ?? join15(getDataDirReadOnly(), "selection-cache"));
|
|
46629
46769
|
}
|
|
46630
46770
|
function selectionKey(selection) {
|
|
46631
46771
|
validateSelection(selection);
|
|
46632
46772
|
return hash2([selection.authority, selection.workspaceId, selection.slug, selection.version, selection.bundleDigest]);
|
|
46633
46773
|
}
|
|
46634
46774
|
function hash2(value) {
|
|
46635
|
-
return
|
|
46775
|
+
return createHash8("sha256").update(JSON.stringify(value)).digest("hex");
|
|
46636
46776
|
}
|
|
46637
46777
|
function validateSelection(selection) {
|
|
46638
|
-
if (!selection || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(selection.slug) || !isValidSkillVersion(selection.version) || !/^sha256:[a-f0-9]{64}$/.test(selection.bundleDigest) || typeof selection.workspaceId !== "string" || !selection.workspaceId.trim() || typeof selection.profileRevision !== "string" || !selection.profileRevision.trim()) {
|
|
46778
|
+
if (!selection || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(selection.slug) || !isValidSkillVersion(selection.version) || !/^sha256:[a-f0-9]{64}$/.test(selection.bundleDigest) || typeof selection.workspaceId !== "string" || !selection.workspaceId.trim() || selection.authorizationEpoch !== undefined && (typeof selection.authorizationEpoch !== "string" || !/^[a-f0-9]{32}$/.test(selection.authorizationEpoch)) || typeof selection.profileRevision !== "string" || !selection.profileRevision.trim()) {
|
|
46639
46779
|
throw new SkillSelectionError("INVALID_SELECTION", "A skill selection must carry an exact version, digest, workspace and profile revision.");
|
|
46640
46780
|
}
|
|
46641
46781
|
const aliasError = selectionAliasError([selection]);
|
|
@@ -46669,15 +46809,15 @@ function validateResolvedProfile(profile, authority) {
|
|
|
46669
46809
|
}
|
|
46670
46810
|
function selectionBundlePath(selection, options = {}) {
|
|
46671
46811
|
validateSelection(selection);
|
|
46672
|
-
return
|
|
46812
|
+
return join15(selectionCacheRoot(options), "objects", hash2(selection.authority), hash2(selection.workspaceId), `${selection.bundleDigest.slice(7)}.tar.gz`);
|
|
46673
46813
|
}
|
|
46674
46814
|
function assertRegularPath(path, createParents = false) {
|
|
46675
46815
|
const absolute = resolve8(path);
|
|
46676
|
-
const root =
|
|
46816
|
+
const root = parse9(absolute).root;
|
|
46677
46817
|
let cursor = root;
|
|
46678
46818
|
const segments = absolute.slice(root.length).split("/");
|
|
46679
46819
|
for (let index = 0;index < segments.length; index++) {
|
|
46680
|
-
cursor =
|
|
46820
|
+
cursor = join15(cursor, segments[index]);
|
|
46681
46821
|
try {
|
|
46682
46822
|
const stat = lstatSync9(cursor);
|
|
46683
46823
|
if (stat.isSymbolicLink() || index < segments.length - 1 && !stat.isDirectory()) {
|
|
@@ -46729,7 +46869,7 @@ function writeSelectionJson(path, value) {
|
|
|
46729
46869
|
}
|
|
46730
46870
|
function atomicWrite(path, bytes, mode, durable = false) {
|
|
46731
46871
|
assertRegularPath(path, true);
|
|
46732
|
-
const temporary =
|
|
46872
|
+
const temporary = join15(dirname9(path), `.selection-${randomUUID()}.tmp`);
|
|
46733
46873
|
try {
|
|
46734
46874
|
const fd = openSync7(temporary, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, mode);
|
|
46735
46875
|
try {
|
|
@@ -46761,17 +46901,21 @@ function readSelectionJson(path) {
|
|
|
46761
46901
|
throw new SkillSelectionError("INVALID_RECEIPT", "The Skills selection receipt is unreadable; sync the profile again.");
|
|
46762
46902
|
}
|
|
46763
46903
|
}
|
|
46764
|
-
async function verifiedEntries(selection, bytes) {
|
|
46904
|
+
async function verifiedEntries(selection, bytes, signal, deadline) {
|
|
46765
46905
|
if (`sha256:${sha256Hex(bytes)}` !== selection.bundleDigest)
|
|
46766
46906
|
throw new SkillSelectionError("BUNDLE_DIGEST_MISMATCH", "The skill bundle does not match its selected digest.");
|
|
46767
|
-
const
|
|
46907
|
+
const remaining = deadline === undefined ? undefined : Math.floor(deadline - performance.now());
|
|
46908
|
+
signal?.throwIfAborted();
|
|
46909
|
+
if (remaining !== undefined && remaining <= 0)
|
|
46910
|
+
throw new SkillSelectionError("SKILLS_API_UNAVAILABLE", "Skills session authorization deadline exceeded.");
|
|
46911
|
+
const bundle = await inspectSkillBundle(bytes, { signal, ...remaining === undefined ? {} : { limits: { timeoutMs: remaining } } });
|
|
46768
46912
|
return bundle.entries;
|
|
46769
46913
|
}
|
|
46770
46914
|
async function readCachedSelection(selection, options = {}) {
|
|
46771
46915
|
const bytes = readRegularFile(selectionBundlePath(selection, options), SKILL_BUNDLE_INSPECTION_LIMITS.compressedBytes);
|
|
46772
46916
|
return bytes ? verifiedEntries(selection, bytes) : null;
|
|
46773
46917
|
}
|
|
46774
|
-
async function
|
|
46918
|
+
async function verifySelectionBundleResponse(selection, response, signal, deadline) {
|
|
46775
46919
|
validateSelection(selection);
|
|
46776
46920
|
if (!response?.ok)
|
|
46777
46921
|
throw new SkillSelectionError("BUNDLE_UNAVAILABLE", `The selected skill bundle is unavailable${response ? ` (HTTP ${response.status})` : ""}.`);
|
|
@@ -46781,15 +46925,27 @@ async function cacheSelectionBundle(selection, response, options = {}) {
|
|
|
46781
46925
|
await response.body?.cancel();
|
|
46782
46926
|
throw new SkillSelectionError("BUNDLE_IDENTITY_MISMATCH", "The returned bundle does not match the selected version and digest.");
|
|
46783
46927
|
}
|
|
46928
|
+
const epoch = response.headers.get("X-Skill-Authorization-Epoch");
|
|
46929
|
+
if (selection.authorizationEpoch !== undefined && epoch !== selection.authorizationEpoch) {
|
|
46930
|
+
response.body?.cancel().catch(() => {});
|
|
46931
|
+
throw new SkillSelectionError("SESSION_RECONCILIATION_REQUIRED", "The selected bundle lifecycle authorization changed or is unavailable.");
|
|
46932
|
+
}
|
|
46784
46933
|
const maximum = SKILL_BUNDLE_INSPECTION_LIMITS.compressedBytes;
|
|
46785
46934
|
const reader = response.body?.getReader();
|
|
46786
46935
|
if (!reader)
|
|
46787
46936
|
throw new SkillSelectionError("BUNDLE_UNAVAILABLE", "The selected bundle response has no body.");
|
|
46937
|
+
signal?.throwIfAborted();
|
|
46938
|
+
const abort = () => {
|
|
46939
|
+
reader.cancel().catch(() => {});
|
|
46940
|
+
};
|
|
46941
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
46788
46942
|
const chunks = [];
|
|
46789
46943
|
let length = 0;
|
|
46790
46944
|
try {
|
|
46791
46945
|
while (true) {
|
|
46946
|
+
signal?.throwIfAborted();
|
|
46792
46947
|
const next = await reader.read();
|
|
46948
|
+
signal?.throwIfAborted();
|
|
46793
46949
|
if (next.done)
|
|
46794
46950
|
break;
|
|
46795
46951
|
length += next.value.byteLength;
|
|
@@ -46798,9 +46954,10 @@ async function cacheSelectionBundle(selection, response, options = {}) {
|
|
|
46798
46954
|
chunks.push(next.value);
|
|
46799
46955
|
}
|
|
46800
46956
|
} catch (error61) {
|
|
46801
|
-
|
|
46957
|
+
reader.cancel().catch(() => {});
|
|
46802
46958
|
throw error61;
|
|
46803
46959
|
} finally {
|
|
46960
|
+
signal?.removeEventListener("abort", abort);
|
|
46804
46961
|
reader.releaseLock();
|
|
46805
46962
|
}
|
|
46806
46963
|
const bytes = new Uint8Array(length);
|
|
@@ -46809,7 +46966,12 @@ async function cacheSelectionBundle(selection, response, options = {}) {
|
|
|
46809
46966
|
bytes.set(chunk, offset);
|
|
46810
46967
|
offset += chunk.byteLength;
|
|
46811
46968
|
}
|
|
46812
|
-
const entries = await verifiedEntries(selection, bytes);
|
|
46969
|
+
const entries = await verifiedEntries(selection, bytes, signal, deadline);
|
|
46970
|
+
return { bytes, entries };
|
|
46971
|
+
}
|
|
46972
|
+
async function cacheSelectionBundle(selection, response, options = {}) {
|
|
46973
|
+
const { bytes, entries } = await verifySelectionBundleResponse(selection, response);
|
|
46974
|
+
const maximum = SKILL_BUNDLE_INSPECTION_LIMITS.compressedBytes;
|
|
46813
46975
|
const path = selectionBundlePath(selection, options);
|
|
46814
46976
|
const existing = readRegularFile(path, maximum);
|
|
46815
46977
|
if (existing)
|
|
@@ -46819,7 +46981,7 @@ async function cacheSelectionBundle(selection, response, options = {}) {
|
|
|
46819
46981
|
return entries;
|
|
46820
46982
|
}
|
|
46821
46983
|
function profilePath(profileId, options) {
|
|
46822
|
-
return
|
|
46984
|
+
return join15(selectionCacheRoot(options), "profiles", `${hash2(profileId)}.json`);
|
|
46823
46985
|
}
|
|
46824
46986
|
function readSelectionProfile(profileId, options = {}) {
|
|
46825
46987
|
const receipt = readSelectionJson(profilePath(profileId, options));
|
|
@@ -46845,7 +47007,7 @@ function assertFreshCachedProfile(receipt, options = {}) {
|
|
|
46845
47007
|
}
|
|
46846
47008
|
}
|
|
46847
47009
|
function projectSelectionLockPath(projectDir) {
|
|
46848
|
-
return
|
|
47010
|
+
return join15(resolve8(projectDir), ".skills", SELECTION_LOCK_FILE);
|
|
46849
47011
|
}
|
|
46850
47012
|
function readProjectSelection(projectDir) {
|
|
46851
47013
|
const receipt = readSelectionJson(projectSelectionLockPath(projectDir));
|
|
@@ -46856,7 +47018,7 @@ function readProjectSelection(projectDir) {
|
|
|
46856
47018
|
function sessionReceiptPath(sessionId, options = {}) {
|
|
46857
47019
|
if (!sessionId.trim() || sessionId.length > MAX_SKILL_SESSION_ID_CHARS)
|
|
46858
47020
|
throw new SkillSelectionError("INVALID_SESSION", `A Skills session id must contain 1\u2013${MAX_SKILL_SESSION_ID_CHARS} characters.`);
|
|
46859
|
-
return
|
|
47021
|
+
return join15(selectionCacheRoot(options), "sessions", `${hash2(sessionId)}.json`);
|
|
46860
47022
|
}
|
|
46861
47023
|
function skillSessionGeneration(receipt) {
|
|
46862
47024
|
return receipt.generation ?? 0;
|
|
@@ -47054,9 +47216,9 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
|
|
|
47054
47216
|
const currentReceipt = readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions);
|
|
47055
47217
|
if (currentReceipt?.sha256 !== receipt?.sha256 || currentReceipt?.generation !== receipt?.generation)
|
|
47056
47218
|
return null;
|
|
47057
|
-
const directory =
|
|
47058
|
-
const archivePath =
|
|
47059
|
-
const recordPath =
|
|
47219
|
+
const directory = join15(dirname9(dirname9(lock.path)), "session-lock-recoveries", randomUUID());
|
|
47220
|
+
const archivePath = join15(directory, "original.write-lock");
|
|
47221
|
+
const recordPath = join15(directory, "recovery.json");
|
|
47060
47222
|
assertRegularPath(archivePath, true);
|
|
47061
47223
|
archiveBytes(recordPath, Buffer.from(`${JSON.stringify({
|
|
47062
47224
|
schemaVersion: 1,
|
|
@@ -47081,7 +47243,7 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
|
|
|
47081
47243
|
moved = true;
|
|
47082
47244
|
const archivedPaths = [archivePath];
|
|
47083
47245
|
if (finalLock.stagingPath) {
|
|
47084
|
-
const publicationPath =
|
|
47246
|
+
const publicationPath = join15(directory, "publication.write-lock");
|
|
47085
47247
|
renameSync(finalLock.stagingPath, publicationPath);
|
|
47086
47248
|
archivedPaths.push(publicationPath);
|
|
47087
47249
|
}
|
|
@@ -47255,7 +47417,7 @@ __export(exports_remote_files, {
|
|
|
47255
47417
|
decodeRemoteFiles: () => decodeRemoteFiles,
|
|
47256
47418
|
MAX_REMOTE_FILE_BYTES: () => MAX_REMOTE_FILE_BYTES
|
|
47257
47419
|
});
|
|
47258
|
-
import { createHash as
|
|
47420
|
+
import { createHash as createHash9 } from "crypto";
|
|
47259
47421
|
function describeRemoteFiles(files) {
|
|
47260
47422
|
if (files.length > 10)
|
|
47261
47423
|
throw new Error("At most 10 input files are supported");
|
|
@@ -47272,9 +47434,9 @@ function describeRemoteFiles(files) {
|
|
|
47272
47434
|
});
|
|
47273
47435
|
}
|
|
47274
47436
|
function sha256(bytes) {
|
|
47275
|
-
return
|
|
47437
|
+
return createHash9("sha256").update(bytes).digest("hex");
|
|
47276
47438
|
}
|
|
47277
|
-
async function readBoundedResponse(response, maximum) {
|
|
47439
|
+
async function readBoundedResponse(response, maximum, signal) {
|
|
47278
47440
|
if (!Number.isSafeInteger(maximum) || maximum < 0 || maximum > MAX_REMOTE_FILE_BYTES)
|
|
47279
47441
|
throw new Error("Invalid artifact size limit");
|
|
47280
47442
|
const length = response.headers.get("content-length");
|
|
@@ -47285,11 +47447,18 @@ async function readBoundedResponse(response, maximum) {
|
|
|
47285
47447
|
const reader = response.body?.getReader();
|
|
47286
47448
|
if (!reader)
|
|
47287
47449
|
return new Uint8Array;
|
|
47450
|
+
signal?.throwIfAborted();
|
|
47451
|
+
const abort = () => {
|
|
47452
|
+
reader.cancel().catch(() => {});
|
|
47453
|
+
};
|
|
47454
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
47288
47455
|
const chunks = [];
|
|
47289
47456
|
let size = 0;
|
|
47290
47457
|
try {
|
|
47291
47458
|
while (true) {
|
|
47459
|
+
signal?.throwIfAborted();
|
|
47292
47460
|
const next = await reader.read();
|
|
47461
|
+
signal?.throwIfAborted();
|
|
47293
47462
|
if (next.done)
|
|
47294
47463
|
break;
|
|
47295
47464
|
size += next.value.byteLength;
|
|
@@ -47301,6 +47470,7 @@ async function readBoundedResponse(response, maximum) {
|
|
|
47301
47470
|
await reader.cancel().catch(() => {});
|
|
47302
47471
|
throw error61;
|
|
47303
47472
|
} finally {
|
|
47473
|
+
signal?.removeEventListener("abort", abort);
|
|
47304
47474
|
reader.releaseLock();
|
|
47305
47475
|
}
|
|
47306
47476
|
const bytes = new Uint8Array(size);
|
|
@@ -47360,10 +47530,12 @@ function validateSelection2(value) {
|
|
|
47360
47530
|
|
|
47361
47531
|
class HttpProfileClient {
|
|
47362
47532
|
key;
|
|
47533
|
+
signal;
|
|
47363
47534
|
authority;
|
|
47364
47535
|
origin;
|
|
47365
|
-
constructor(key, origin) {
|
|
47536
|
+
constructor(key, origin, signal) {
|
|
47366
47537
|
this.key = key;
|
|
47538
|
+
this.signal = signal;
|
|
47367
47539
|
if (!key.trim())
|
|
47368
47540
|
throw new Error("A Skills credential is required");
|
|
47369
47541
|
this.origin = normalizeSkillsApiOrigin(origin);
|
|
@@ -47377,7 +47549,7 @@ class HttpProfileClient {
|
|
|
47377
47549
|
...init,
|
|
47378
47550
|
redirect: "error",
|
|
47379
47551
|
credentials: "omit",
|
|
47380
|
-
signal: AbortSignal.timeout(15000),
|
|
47552
|
+
signal: this.signal ? AbortSignal.any([this.signal, AbortSignal.timeout(15000)]) : AbortSignal.timeout(15000),
|
|
47381
47553
|
headers: {
|
|
47382
47554
|
"Content-Type": "application/json",
|
|
47383
47555
|
"User-Agent": `hasna-skills/${package_default.version}`,
|
|
@@ -47402,22 +47574,28 @@ class HttpProfileClient {
|
|
|
47402
47574
|
}
|
|
47403
47575
|
async read(response, limit = MAX_PROFILE_DOCUMENT_BYTES) {
|
|
47404
47576
|
try {
|
|
47405
|
-
return JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, limit)));
|
|
47577
|
+
return JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, limit, this.signal)));
|
|
47406
47578
|
} catch {
|
|
47407
47579
|
invalid();
|
|
47408
47580
|
}
|
|
47409
47581
|
}
|
|
47582
|
+
async supportsPinRenewal() {
|
|
47583
|
+
const result = await this.read(await this.request("/capabilities"));
|
|
47584
|
+
if (!object6(result) || !Array.isArray(result.capabilities))
|
|
47585
|
+
invalid();
|
|
47586
|
+
return result.capabilities.includes("skills.session-pin-renewal");
|
|
47587
|
+
}
|
|
47410
47588
|
async resolveProfile(id) {
|
|
47411
47589
|
if (!identifier(id))
|
|
47412
47590
|
throw new Error("Invalid selection profile id");
|
|
47413
|
-
const result = await this.read(await this.request(`/profiles/${encodeURIComponent(id)}/resolve`), MAX_RESOLVED_PROFILE_BYTES);
|
|
47591
|
+
const result = await this.read(await this.request(`/profiles/${encodeURIComponent(id)}/resolve?pinAuthorization=epoch-v1`), MAX_RESOLVED_PROFILE_BYTES);
|
|
47414
47592
|
if (!object6(result) || result.profileId !== id || result.authority !== this.authority || !identifier(result.workspaceId) || !identifier(result.profileRevision) || !Array.isArray(result.selections) || result.selections.length > MAX_PROFILE_SELECTIONS)
|
|
47415
47593
|
invalid();
|
|
47416
47594
|
const seen = new Set;
|
|
47417
47595
|
for (const entry of result.selections) {
|
|
47418
47596
|
validateSelection2(entry);
|
|
47419
47597
|
const item = entry;
|
|
47420
|
-
if (seen.has(item.slug) || item.authority !== this.authority || item.workspaceId !== result.workspaceId || item.profileRevision !== result.profileRevision)
|
|
47598
|
+
if (item.authorizationEpoch !== undefined && (typeof item.authorizationEpoch !== "string" || !/^[a-f0-9]{32}$/.test(item.authorizationEpoch)) || seen.has(item.slug) || item.authority !== this.authority || item.workspaceId !== result.workspaceId || item.profileRevision !== result.profileRevision)
|
|
47421
47599
|
invalid();
|
|
47422
47600
|
seen.add(item.slug);
|
|
47423
47601
|
}
|
|
@@ -47464,7 +47642,7 @@ class HttpProfileClient {
|
|
|
47464
47642
|
return this.request(`/skills/${encodeURIComponent(slug)}/versions/${encodeURIComponent(version2)}/bundle`);
|
|
47465
47643
|
}
|
|
47466
47644
|
}
|
|
47467
|
-
async function createProfileClient() {
|
|
47645
|
+
async function createProfileClient(signal) {
|
|
47468
47646
|
let connection;
|
|
47469
47647
|
try {
|
|
47470
47648
|
connection = await resolveSkillsConnection();
|
|
@@ -47476,7 +47654,7 @@ async function createProfileClient() {
|
|
|
47476
47654
|
}
|
|
47477
47655
|
if (!connection)
|
|
47478
47656
|
throw new Error("Selection profiles require a configured Skills API");
|
|
47479
|
-
return new HttpProfileClient(connection.apiKey, connection.apiOrigin);
|
|
47657
|
+
return new HttpProfileClient(connection.apiKey, connection.apiOrigin, signal);
|
|
47480
47658
|
}
|
|
47481
47659
|
var init_profile_client = __esm(() => {
|
|
47482
47660
|
init_selection_cache();
|
|
@@ -47528,18 +47706,18 @@ function capturePreparationProcess(child, platform = process.platform, signalGro
|
|
|
47528
47706
|
|
|
47529
47707
|
// src/lib/dependency-preparation.ts
|
|
47530
47708
|
import { constants as constants5, closeSync as closeSync8, fstatSync as fstatSync8, lstatSync as lstatSync10, mkdirSync as mkdirSync4, openSync as openSync8, readFileSync as readFileSync11, readdirSync as readdirSync5, rmdirSync, unlinkSync as unlinkSync2, ftruncateSync, writeSync } from "fs";
|
|
47531
|
-
import { join as
|
|
47709
|
+
import { join as join16 } from "path";
|
|
47532
47710
|
function hasDependencyPreparationMarker(skillPath) {
|
|
47533
47711
|
try {
|
|
47534
|
-
lstatSync10(
|
|
47712
|
+
lstatSync10(join16(skillPath, DEPENDENCY_PREPARATION_MARKER));
|
|
47535
47713
|
return true;
|
|
47536
47714
|
} catch (error61) {
|
|
47537
47715
|
return error61.code !== "ENOENT";
|
|
47538
47716
|
}
|
|
47539
47717
|
}
|
|
47540
47718
|
function claimPreparation(skillPath) {
|
|
47541
|
-
const marker =
|
|
47542
|
-
const state =
|
|
47719
|
+
const marker = join16(skillPath, DEPENDENCY_PREPARATION_MARKER);
|
|
47720
|
+
const state = join16(marker, "state.json"), active = join16(marker, "active");
|
|
47543
47721
|
let created = false;
|
|
47544
47722
|
try {
|
|
47545
47723
|
mkdirSync4(marker, { mode: 448 });
|
|
@@ -47802,7 +47980,7 @@ var init_codex_native_skill_catalog = __esm(() => {
|
|
|
47802
47980
|
});
|
|
47803
47981
|
|
|
47804
47982
|
// src/lib/codex-plugin-skill-controls.ts
|
|
47805
|
-
import { basename as basename5, dirname as dirname10, join as
|
|
47983
|
+
import { basename as basename5, dirname as dirname10, join as join17, relative as relative4, resolve as resolve9, sep as sep5 } from "path";
|
|
47806
47984
|
import { lstatSync as lstatSync11, readdirSync as readdirSync6, readlinkSync as readlinkSync3, realpathSync as realpathSync3 } from "fs";
|
|
47807
47985
|
function refuse() {
|
|
47808
47986
|
throw new Error("CODEX_NATIVE_SKILL_IDENTITY_UNSUPPORTED: review native plugin names and hook controls");
|
|
@@ -47811,7 +47989,7 @@ function remoteInstallationMatches(parent, remotePluginId, read) {
|
|
|
47811
47989
|
try {
|
|
47812
47990
|
if (!remotePluginIdentifier(remotePluginId) || !lstatSync11(parent).isDirectory() || realpathSync3(parent) !== parent)
|
|
47813
47991
|
return false;
|
|
47814
|
-
const path =
|
|
47992
|
+
const path = join17(parent, ".codex-remote-plugin-install.json"), stat = lstatSync11(path, { throwIfNoEntry: false });
|
|
47815
47993
|
if (!stat?.isFile() || stat.isSymbolicLink() || stat.size > 16384)
|
|
47816
47994
|
return false;
|
|
47817
47995
|
const text2 = read(path);
|
|
@@ -47887,8 +48065,8 @@ function isBundledCleanupHooks(root, namespace, value) {
|
|
|
47887
48065
|
return true;
|
|
47888
48066
|
}
|
|
47889
48067
|
function rootControls(root, read) {
|
|
47890
|
-
const manifestPath =
|
|
47891
|
-
if (!lstatSync11(
|
|
48068
|
+
const manifestPath = join17(root, ".codex-plugin/plugin.json"), manifestFile = lstatSync11(manifestPath, { throwIfNoEntry: false });
|
|
48069
|
+
if (!lstatSync11(join17(root, ".codex-plugin"), { throwIfNoEntry: false })?.isDirectory() || !manifestFile?.isFile() || manifestFile.size > 1024 * 1024)
|
|
47892
48070
|
refuse();
|
|
47893
48071
|
let manifest, manifestSha256;
|
|
47894
48072
|
try {
|
|
@@ -47903,9 +48081,9 @@ function rootControls(root, read) {
|
|
|
47903
48081
|
const cacheVersion = basename5(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
|
|
47904
48082
|
if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
|
|
47905
48083
|
refuse();
|
|
47906
|
-
if (manifest.hooks !== undefined && !isBundledCleanupHooks(root, manifest.name, manifest.hooks) || manifest.commands !== undefined || manifest.mcpServers !== undefined && manifest.mcpServers !== "./.mcp.json" || manifest.apps !== undefined && manifest.apps !== "./.app.json" || lstatSync11(
|
|
48084
|
+
if (manifest.hooks !== undefined && !isBundledCleanupHooks(root, manifest.name, manifest.hooks) || manifest.commands !== undefined || manifest.mcpServers !== undefined && manifest.mcpServers !== "./.mcp.json" || manifest.apps !== undefined && manifest.apps !== "./.app.json" || lstatSync11(join17(root, "hooks"), { throwIfNoEntry: false }))
|
|
47907
48085
|
refuse();
|
|
47908
|
-
const mcp =
|
|
48086
|
+
const mcp = join17(root, ".mcp.json"), mcpPresent = lstatSync11(mcp, { throwIfNoEntry: false });
|
|
47909
48087
|
if (manifest.hooks !== undefined && (manifest.mcpServers !== undefined || mcpPresent))
|
|
47910
48088
|
refuse();
|
|
47911
48089
|
if (mcpPresent && (!mcpPresent.isFile() || mcpPresent.isSymbolicLink() || mcpPresent.size > 1024 * 1024 || realpathSync3(mcp) !== mcp))
|
|
@@ -47913,7 +48091,7 @@ function rootControls(root, read) {
|
|
|
47913
48091
|
if (Boolean(mcpPresent) !== (manifest.mcpServers !== undefined))
|
|
47914
48092
|
refuse();
|
|
47915
48093
|
const mcpSha256 = mcpPresent ? mcpControls(mcp, read) : undefined;
|
|
47916
|
-
const app =
|
|
48094
|
+
const app = join17(root, ".app.json"), present = lstatSync11(app, { throwIfNoEntry: false });
|
|
47917
48095
|
if (present && (!present.isFile() || present.isSymbolicLink() || present.size > 1024 * 1024))
|
|
47918
48096
|
refuse();
|
|
47919
48097
|
if (manifest.apps !== undefined && !present)
|
|
@@ -47923,7 +48101,7 @@ function rootControls(root, read) {
|
|
|
47923
48101
|
}
|
|
47924
48102
|
function reviewedDisabledCodexPluginParent(cache, parent, controls, rules) {
|
|
47925
48103
|
try {
|
|
47926
|
-
const parts = relative4(cache, parent).split(
|
|
48104
|
+
const parts = relative4(cache, parent).split(sep5), enrolled = controls.filter((control) => control.pluginParent === parent);
|
|
47927
48105
|
if (resolve9(parent) !== parent || parts.length !== 2 || parts.some((part) => !identifier2(part)) || !enrolled.length || !Array.isArray(rules))
|
|
47928
48106
|
return false;
|
|
47929
48107
|
for (let cursor = parent;; cursor = dirname10(cursor)) {
|
|
@@ -47933,7 +48111,7 @@ function reviewedDisabledCodexPluginParent(cache, parent, controls, rules) {
|
|
|
47933
48111
|
if (dirname10(cursor) === cursor)
|
|
47934
48112
|
break;
|
|
47935
48113
|
}
|
|
47936
|
-
return enrolled.every((control) => control.namespace === parts[1] && control.pluginId === `${parts[1]}@${parts[0]}` && remotePluginIdentifier(control.remotePluginId) && control.skillsOnly === true && !control.appSha256 && !control.mcpSha256 && control.name.startsWith(control.namespace + ":") && /^[a-f0-9]{64}$/.test(control.manifestSha256) && rules.some((rule) => typeof rule?.name === "string" && rule.name.trim() === control.name && rule.enabled === false) && !rules.some((rule) => (typeof rule?.name === "string" && rule.name.trim() === control.name || typeof rule?.path === "string" && (rule.path === parent || rule.path.startsWith(parent +
|
|
48114
|
+
return enrolled.every((control) => control.namespace === parts[1] && control.pluginId === `${parts[1]}@${parts[0]}` && remotePluginIdentifier(control.remotePluginId) && control.skillsOnly === true && !control.appSha256 && !control.mcpSha256 && control.name.startsWith(control.namespace + ":") && /^[a-f0-9]{64}$/.test(control.manifestSha256) && rules.some((rule) => typeof rule?.name === "string" && rule.name.trim() === control.name && rule.enabled === false) && !rules.some((rule) => (typeof rule?.name === "string" && rule.name.trim() === control.name || typeof rule?.path === "string" && (rule.path === parent || rule.path.startsWith(parent + sep5))) && rule.enabled !== false));
|
|
47937
48115
|
} catch {
|
|
47938
48116
|
return false;
|
|
47939
48117
|
}
|
|
@@ -47943,7 +48121,7 @@ function absentDisabledCodexPluginParent(cache, parent, controls, rules) {
|
|
|
47943
48121
|
}
|
|
47944
48122
|
function reviewedRetiredCodexRoot(cache, root, controls, rules, read, allowAbsent = false) {
|
|
47945
48123
|
try {
|
|
47946
|
-
const parent = dirname10(root), parts = relative4(cache, parent).split(
|
|
48124
|
+
const parent = dirname10(root), parts = relative4(cache, parent).split(sep5), enrolled = controls.filter((control) => control.pluginParent === parent);
|
|
47947
48125
|
if (resolve9(root) !== root || parts.length !== 2 || parts.some((part) => !identifier2(part)) || !basename5(root) || basename5(root) === "latest" || !enrolled.length || !Array.isArray(rules))
|
|
47948
48126
|
return false;
|
|
47949
48127
|
for (let cursor = root;; cursor = dirname10(cursor)) {
|
|
@@ -47953,14 +48131,14 @@ function reviewedRetiredCodexRoot(cache, root, controls, rules, read, allowAbsen
|
|
|
47953
48131
|
if (dirname10(cursor) === cursor)
|
|
47954
48132
|
break;
|
|
47955
48133
|
}
|
|
47956
|
-
if (!enrolled.every((control) => control.namespace === parts[1] && control.pluginId === `${parts[1]}@${parts[0]}` && remotePluginIdentifier(control.remotePluginId) && control.skillsOnly === true && !control.appSha256 && !control.mcpSha256 && control.name.startsWith(control.namespace + ":") && /^[a-f0-9]{64}$/.test(control.manifestSha256) && rules.some((rule) => typeof rule?.name === "string" && rule.name.trim() === control.name && rule.enabled === false) && !rules.some((rule) => (typeof rule?.name === "string" && rule.name.trim() === control.name || typeof rule?.path === "string" && (rule.path === parent || rule.path === root || rule.path.startsWith(root +
|
|
48134
|
+
if (!enrolled.every((control) => control.namespace === parts[1] && control.pluginId === `${parts[1]}@${parts[0]}` && remotePluginIdentifier(control.remotePluginId) && control.skillsOnly === true && !control.appSha256 && !control.mcpSha256 && control.name.startsWith(control.namespace + ":") && /^[a-f0-9]{64}$/.test(control.manifestSha256) && rules.some((rule) => typeof rule?.name === "string" && rule.name.trim() === control.name && rule.enabled === false) && !rules.some((rule) => (typeof rule?.name === "string" && rule.name.trim() === control.name || typeof rule?.path === "string" && (rule.path === parent || rule.path === root || rule.path.startsWith(root + sep5))) && rule.enabled !== false)))
|
|
47957
48135
|
return false;
|
|
47958
48136
|
if (!lstatSync11(root, { throwIfNoEntry: false }))
|
|
47959
48137
|
return allowAbsent && (lstatSync11(parent, { throwIfNoEntry: false }) ? enrolled.every((control) => remoteInstallationMatches(parent, control.remotePluginId, read)) : absentDisabledCodexPluginParent(cache, parent, controls, rules));
|
|
47960
48138
|
if (!enrolled.every((control) => remoteInstallationMatches(parent, control.remotePluginId, read)))
|
|
47961
48139
|
return false;
|
|
47962
48140
|
const parsed = rootControls(root, read);
|
|
47963
|
-
if (JSON.parse(read(
|
|
48141
|
+
if (JSON.parse(read(join17(root, ".codex-plugin/plugin.json"))).hooks !== undefined)
|
|
47964
48142
|
return false;
|
|
47965
48143
|
if (!enrolled.some((control) => control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && !parsed.appSha256 && !parsed.mcpSha256))
|
|
47966
48144
|
return false;
|
|
@@ -47968,7 +48146,7 @@ function reviewedRetiredCodexRoot(cache, root, controls, rules, read, allowAbsen
|
|
|
47968
48146
|
const emptySkills = (directory, depth) => depth <= 64 && readdirSync6(directory).every((name) => {
|
|
47969
48147
|
if (++entries > 4096 || name === "SKILL.md")
|
|
47970
48148
|
return false;
|
|
47971
|
-
const path =
|
|
48149
|
+
const path = join17(directory, name), stat = lstatSync11(path);
|
|
47972
48150
|
return !stat.isSymbolicLink() && (stat.isFile() || stat.isDirectory() && emptySkills(path, depth + 1));
|
|
47973
48151
|
});
|
|
47974
48152
|
return emptySkills(root, 0);
|
|
@@ -47984,7 +48162,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
|
|
|
47984
48162
|
for (const parent of new Set(controls.map((control) => control.pluginParent))) {
|
|
47985
48163
|
if (absentDisabledCodexPluginParent(cache, parent, controls, rules))
|
|
47986
48164
|
continue;
|
|
47987
|
-
if (!parent.startsWith(cache +
|
|
48165
|
+
if (!parent.startsWith(cache + sep5) || !lstatSync11(parent, { throwIfNoEntry: false })?.isDirectory() || realpathSync3(parent) !== parent)
|
|
47988
48166
|
return false;
|
|
47989
48167
|
for (const control of controls.filter((control2) => control2.pluginParent === parent)) {
|
|
47990
48168
|
if (control.remotePluginId !== undefined && !remoteInstallationMatches(parent, control.remotePluginId, read))
|
|
@@ -47995,7 +48173,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
|
|
|
47995
48173
|
if (entries > 4096)
|
|
47996
48174
|
return false;
|
|
47997
48175
|
for (const name of names) {
|
|
47998
|
-
let root =
|
|
48176
|
+
let root = join17(parent, name), stat = lstatSync11(root);
|
|
47999
48177
|
if (stat.isSymbolicLink()) {
|
|
48000
48178
|
const target = resolve9(parent, readlinkSync3(root));
|
|
48001
48179
|
if (name !== "latest" || dirname10(target) !== parent || !lstatSync11(target).isDirectory() || realpathSync3(target) !== target)
|
|
@@ -48003,7 +48181,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
|
|
|
48003
48181
|
root = target;
|
|
48004
48182
|
stat = lstatSync11(root);
|
|
48005
48183
|
}
|
|
48006
|
-
if (!stat.isDirectory() || ![".codex-plugin/plugin.json", ".app.json", "hooks", ".mcp.json"].some((path) => lstatSync11(
|
|
48184
|
+
if (!stat.isDirectory() || ![".codex-plugin/plugin.json", ".app.json", "hooks", ".mcp.json"].some((path) => lstatSync11(join17(root, path), { throwIfNoEntry: false })))
|
|
48007
48185
|
continue;
|
|
48008
48186
|
const parsed = rootControls(root, read);
|
|
48009
48187
|
if (!controls.some((control) => control.pluginParent === parent && control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && control.appSha256 === parsed.appSha256 && control.mcpSha256 === parsed.mcpSha256))
|
|
@@ -48017,10 +48195,10 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
|
|
|
48017
48195
|
}
|
|
48018
48196
|
function sourceInputUnchanged(input2, cache, read) {
|
|
48019
48197
|
try {
|
|
48020
|
-
const parts = relative4(cache, input2.pluginParent).split(
|
|
48021
|
-
if (parts.length !== 2 || parts.some((part) => !identifier2(part)) || parts[1] !== input2.namespace || input2.pluginId !== `${parts[1]}@${parts[0]}` || !codexPluginSourceIsConfigControlled({ id: input2.pluginId, sourceType: "local", sourceSha256: input2.sourceSha256 }) || input2.sourceSha256 !== hashNativeJsonControls(JSON.stringify({ type: "local", path: input2.sourceRoot })) || resolve9(input2.sourceRoot) !== input2.sourceRoot || !lstatSync11(input2.sourceRoot).isDirectory() || realpathSync3(input2.sourceRoot) !== input2.sourceRoot || input2.sourceRoot === cache || input2.sourceRoot.startsWith(cache +
|
|
48198
|
+
const parts = relative4(cache, input2.pluginParent).split(sep5);
|
|
48199
|
+
if (parts.length !== 2 || parts.some((part) => !identifier2(part)) || parts[1] !== input2.namespace || input2.pluginId !== `${parts[1]}@${parts[0]}` || !codexPluginSourceIsConfigControlled({ id: input2.pluginId, sourceType: "local", sourceSha256: input2.sourceSha256 }) || input2.sourceSha256 !== hashNativeJsonControls(JSON.stringify({ type: "local", path: input2.sourceRoot })) || resolve9(input2.sourceRoot) !== input2.sourceRoot || !lstatSync11(input2.sourceRoot).isDirectory() || realpathSync3(input2.sourceRoot) !== input2.sourceRoot || input2.sourceRoot === cache || input2.sourceRoot.startsWith(cache + sep5) || cache.startsWith(input2.sourceRoot + sep5))
|
|
48022
48200
|
return false;
|
|
48023
|
-
const path =
|
|
48201
|
+
const path = join17(input2.sourceRoot, ".codex-plugin/plugin.json"), stat = lstatSync11(path);
|
|
48024
48202
|
if (!stat.isFile() || stat.size > 1024 * 1024 || realpathSync3(path) !== path)
|
|
48025
48203
|
return false;
|
|
48026
48204
|
const text2 = read(path);
|
|
@@ -48035,7 +48213,7 @@ function reviewedCodexPluginSourceRoots(cache, inputs, read) {
|
|
|
48035
48213
|
if (!Array.isArray(inputs) || inputs.length > 4096 || new Set(inputs.map((input2) => input2.pluginId)).size !== inputs.length || new Set(inputs.map((input2) => input2.sourceRoot)).size !== inputs.length || inputs.some((input2) => !sourceInputUnchanged(input2, cache, read)))
|
|
48036
48214
|
refuse();
|
|
48037
48215
|
const roots = inputs.map((input2) => input2.sourceRoot);
|
|
48038
|
-
if (roots.some((root) => roots.some((other) => root !== other && root.startsWith(other +
|
|
48216
|
+
if (roots.some((root) => roots.some((other) => root !== other && root.startsWith(other + sep5))))
|
|
48039
48217
|
refuse();
|
|
48040
48218
|
return roots;
|
|
48041
48219
|
}
|
|
@@ -48056,7 +48234,7 @@ var init_codex_native_skill_policy = __esm(() => {
|
|
|
48056
48234
|
});
|
|
48057
48235
|
|
|
48058
48236
|
// src/lib/codex-settings-witness-v1.ts
|
|
48059
|
-
import { createHash as
|
|
48237
|
+
import { createHash as createHash10 } from "crypto";
|
|
48060
48238
|
function need3(value) {
|
|
48061
48239
|
if (!value)
|
|
48062
48240
|
throw new Error("Invalid Codex settings witness");
|
|
@@ -48100,7 +48278,7 @@ function numericTokens(text2) {
|
|
|
48100
48278
|
}
|
|
48101
48279
|
return result;
|
|
48102
48280
|
}
|
|
48103
|
-
function
|
|
48281
|
+
function canonical4(value, depth = 0, budget2 = { remaining: 65536 }) {
|
|
48104
48282
|
need3(depth <= 32 && --budget2.remaining >= 0);
|
|
48105
48283
|
if (value === null)
|
|
48106
48284
|
return ["null"];
|
|
@@ -48117,9 +48295,9 @@ function canonical3(value, depth = 0, budget2 = { remaining: 65536 }) {
|
|
|
48117
48295
|
return ["date", value.toISOString()];
|
|
48118
48296
|
}
|
|
48119
48297
|
if (Array.isArray(value))
|
|
48120
|
-
return ["array", value.map((child) =>
|
|
48298
|
+
return ["array", value.map((child) => canonical4(child, depth + 1, budget2))];
|
|
48121
48299
|
need3(value && typeof value === "object");
|
|
48122
|
-
return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key,
|
|
48300
|
+
return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical4(child, depth + 1, budget2)])];
|
|
48123
48301
|
}
|
|
48124
48302
|
function hashCodexSettingsReplacement(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48125
48303
|
need3(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
|
|
@@ -48140,13 +48318,13 @@ function hashCodexSettingsReplacement(text2, budget2 = { remaining: 256 * 1024 *
|
|
|
48140
48318
|
need3(typeof config2[key] === "string" && values.has(config2[key]));
|
|
48141
48319
|
delete config2[key];
|
|
48142
48320
|
}
|
|
48143
|
-
return sha(`hasna.skills.codex-settings.v1\x00${JSON.stringify([
|
|
48321
|
+
return sha(`hasna.skills.codex-settings.v1\x00${JSON.stringify([canonical4(config2), numericTokens(text2)])}`);
|
|
48144
48322
|
}
|
|
48145
48323
|
function captureCodexSettings(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48146
48324
|
const text2 = readNativeSettingsWitnessFile(path, budget2, "config.toml");
|
|
48147
48325
|
return { path, hashMode: "codex-settings-v1", sha256: hashCodexSettingsReplacement(text2) };
|
|
48148
48326
|
}
|
|
48149
|
-
var sha = (text2) =>
|
|
48327
|
+
var sha = (text2) => createHash10("sha256").update(text2).digest("hex"), EFFORT, VERBOSITY;
|
|
48150
48328
|
var init_codex_settings_witness_v1 = __esm(() => {
|
|
48151
48329
|
init_claude_settings_witness();
|
|
48152
48330
|
EFFORT = new Set(["none", "minimal", "low", "medium", "high", "xhigh"]);
|
|
@@ -48219,7 +48397,7 @@ function projectRegularCodexMcp(config2, source) {
|
|
|
48219
48397
|
var init_codex_mcp_discovery_projection = () => {};
|
|
48220
48398
|
|
|
48221
48399
|
// src/lib/codex-settings-witness.ts
|
|
48222
|
-
import { createHash as
|
|
48400
|
+
import { createHash as createHash11 } from "crypto";
|
|
48223
48401
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
48224
48402
|
function need4(value) {
|
|
48225
48403
|
if (!value)
|
|
@@ -48270,7 +48448,7 @@ function numericTokens2(text2) {
|
|
|
48270
48448
|
}
|
|
48271
48449
|
return result.sort();
|
|
48272
48450
|
}
|
|
48273
|
-
function
|
|
48451
|
+
function canonical5(value, depth = 0, budget2 = { remaining: 65536 }) {
|
|
48274
48452
|
need4(depth <= 32 && --budget2.remaining >= 0);
|
|
48275
48453
|
if (value === null)
|
|
48276
48454
|
return ["null"];
|
|
@@ -48287,9 +48465,9 @@ function canonical4(value, depth = 0, budget2 = { remaining: 65536 }) {
|
|
|
48287
48465
|
return ["date", value.toISOString()];
|
|
48288
48466
|
}
|
|
48289
48467
|
if (Array.isArray(value))
|
|
48290
|
-
return ["array", value.map((child) =>
|
|
48468
|
+
return ["array", value.map((child) => canonical5(child, depth + 1, budget2))];
|
|
48291
48469
|
need4(isRecord3(value));
|
|
48292
|
-
return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key,
|
|
48470
|
+
return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical5(child, depth + 1, budget2)])];
|
|
48293
48471
|
}
|
|
48294
48472
|
function normalize2(config2, version2 = 2) {
|
|
48295
48473
|
if (isRecord3(config2.hooks)) {
|
|
@@ -48463,7 +48641,7 @@ function settingsDigest2(text2, version2 = 2) {
|
|
|
48463
48641
|
const mcp = version2 >= 3 ? projectRegularCodexMcp(config2, text2) : { config: config2, numericSource: text2 };
|
|
48464
48642
|
const projected = version2 === 4 ? projectModelAvailabilityNux(mcp.config, mcp.numericSource) : mcp;
|
|
48465
48643
|
normalize2(projected.config, version2);
|
|
48466
|
-
return sha2(`hasna.skills.codex-settings.v${version2}\x00${JSON.stringify([
|
|
48644
|
+
return sha2(`hasna.skills.codex-settings.v${version2}\x00${JSON.stringify([canonical5(projected.config), numericTokens2(projected.numericSource)])}`);
|
|
48467
48645
|
}
|
|
48468
48646
|
function hashCodexSettingsReplacementV2(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48469
48647
|
need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
|
|
@@ -48490,7 +48668,7 @@ function hashCodexSettingsReplacementV4(text2, budget2 = { remaining: 256 * 1024
|
|
|
48490
48668
|
function captureCodexSettingsV4(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48491
48669
|
return { path, hashMode: "codex-settings-v4", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 4) };
|
|
48492
48670
|
}
|
|
48493
|
-
var sha2 = (text2) =>
|
|
48671
|
+
var sha2 = (text2) => createHash11("sha256").update(text2).digest("hex"), EFFORT2, VERBOSITY2, MODEL, CODEX_DISCOVERY_PROJECTION_FIELDS, INFERENCE;
|
|
48494
48672
|
var init_codex_settings_witness = __esm(() => {
|
|
48495
48673
|
init_codex_settings_witness_v1();
|
|
48496
48674
|
init_codex_settings_witness_v1();
|
|
@@ -48505,7 +48683,7 @@ var init_codex_settings_witness = __esm(() => {
|
|
|
48505
48683
|
|
|
48506
48684
|
// src/lib/managed-policy.ts
|
|
48507
48685
|
import { closeSync as closeSync9, constants as constants6, fstatSync as fstatSync9, lstatSync as lstatSync12, openSync as openSync9, readSync as readSync5 } from "fs";
|
|
48508
|
-
import { join as
|
|
48686
|
+
import { join as join18 } from "path";
|
|
48509
48687
|
function refusal(reason = "is unreadable") {
|
|
48510
48688
|
return new SkillSelectionError("INVALID_AGENT_POLICY", `The Skills agent loading policy ${reason}; refusing legacy fallback.`);
|
|
48511
48689
|
}
|
|
@@ -48530,7 +48708,7 @@ function parseManagedSkillPolicy(text2) {
|
|
|
48530
48708
|
return value;
|
|
48531
48709
|
}
|
|
48532
48710
|
function readManagedSkillPolicySnapshot(dataDir2 = getDataDirReadOnly()) {
|
|
48533
|
-
const path =
|
|
48711
|
+
const path = join18(dataDir2, "agent-policy.json");
|
|
48534
48712
|
let descriptor, observed = false;
|
|
48535
48713
|
try {
|
|
48536
48714
|
const stat = lstatSync12(path);
|
|
@@ -48583,7 +48761,7 @@ var init_managed_policy = __esm(() => {
|
|
|
48583
48761
|
});
|
|
48584
48762
|
|
|
48585
48763
|
// src/lib/agent-bridge.ts
|
|
48586
|
-
import { createHash as
|
|
48764
|
+
import { createHash as createHash12 } from "crypto";
|
|
48587
48765
|
var CLI_BRIDGE_VERSION = 1, markdown = `---
|
|
48588
48766
|
name: skills-cli
|
|
48589
48767
|
description: Discover, load, author, and run versioned skills through the Skills CLI when a task needs reusable instructions or an executable skill.
|
|
@@ -48599,7 +48777,7 @@ Use the Skills CLI as the skill authority for this station.
|
|
|
48599
48777
|
This bridge contains no skill payloads. Do not copy skill content into agent-native skill directories or load other native skill copies. If a Skills command refuses authority, selection, integrity, or native drift, report that refusal and use its repair guidance; do not substitute bundled or stale local content. Explicit local draft authoring remains available.
|
|
48600
48778
|
`, CLI_BRIDGE_DIGEST, CLI_BRIDGE_FILES;
|
|
48601
48779
|
var init_agent_bridge = __esm(() => {
|
|
48602
|
-
CLI_BRIDGE_DIGEST =
|
|
48780
|
+
CLI_BRIDGE_DIGEST = createHash12("sha256").update(markdown).digest("hex");
|
|
48603
48781
|
CLI_BRIDGE_FILES = Object.freeze({
|
|
48604
48782
|
"SKILL.md": markdown,
|
|
48605
48783
|
".hasna-skills.json": `${JSON.stringify({ managedBy: "@hasna/skills", kind: "cli-bridge", version: CLI_BRIDGE_VERSION, protocol: "selection-v1", contentSha256: CLI_BRIDGE_DIGEST }, null, 2)}
|
|
@@ -48612,39 +48790,39 @@ var init_agent_codex = () => {};
|
|
|
48612
48790
|
|
|
48613
48791
|
// src/lib/agent-sumi.ts
|
|
48614
48792
|
import { existsSync as existsSync8, lstatSync as lstatSync13, realpathSync as realpathSync4 } from "fs";
|
|
48615
|
-
import { join as
|
|
48793
|
+
import { join as join19, resolve as resolve10 } from "path";
|
|
48616
48794
|
function sumiConfigDirectory(home, env = process.env) {
|
|
48617
48795
|
for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
|
|
48618
48796
|
if (env[key] !== undefined)
|
|
48619
48797
|
throw new Error(`Sumi ${key} requires a dedicated discovery adapter; unset it before Skills integration`);
|
|
48620
48798
|
const selected = (key) => env[key]?.trim() ? env[key] : undefined;
|
|
48621
|
-
const expand = (value) => resolve10(value === "~" ? home : value.startsWith("~/") ?
|
|
48799
|
+
const expand = (value) => resolve10(value === "~" ? home : value.startsWith("~/") ? join19(home, value.slice(2)) : value);
|
|
48622
48800
|
const explicit = selected("SUMI_CONFIG_DIR");
|
|
48623
48801
|
const xdg = selected("XDG_CONFIG_HOME");
|
|
48624
48802
|
const custom2 = selected("SUMI_HOME");
|
|
48625
|
-
const
|
|
48803
|
+
const canonical6 = explicit ? expand(explicit) : xdg ? join19(expand(xdg), "sumi") : join19(custom2 ? expand(custom2) : join19(home, ".hasna-internal/sumi"), "config");
|
|
48626
48804
|
if (explicit || xdg || custom2)
|
|
48627
|
-
return
|
|
48628
|
-
const legacy =
|
|
48629
|
-
const a = lstatSync13(
|
|
48630
|
-
if (a && b && realpathSync4(
|
|
48805
|
+
return canonical6;
|
|
48806
|
+
const legacy = join19(home, ".config/sumi");
|
|
48807
|
+
const a = lstatSync13(canonical6, { throwIfNoEntry: false }), b = lstatSync13(legacy, { throwIfNoEntry: false });
|
|
48808
|
+
if (a && b && realpathSync4(canonical6) !== realpathSync4(legacy))
|
|
48631
48809
|
throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
|
|
48632
|
-
const path = a ?
|
|
48810
|
+
const path = a ? canonical6 : b ? legacy : canonical6;
|
|
48633
48811
|
if (!existsSync8(path))
|
|
48634
48812
|
return path;
|
|
48635
48813
|
const physical = realpathSync4(path);
|
|
48636
|
-
if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![
|
|
48814
|
+
if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![canonical6, legacy].includes(physical))
|
|
48637
48815
|
throw new Error("Sumi config alias must resolve to its canonical or legacy root");
|
|
48638
48816
|
return physical;
|
|
48639
48817
|
}
|
|
48640
48818
|
function sumiConfigPath(home) {
|
|
48641
|
-
return
|
|
48819
|
+
return join19(sumiConfigDirectory(home), "sumi.json");
|
|
48642
48820
|
}
|
|
48643
48821
|
var init_agent_sumi = () => {};
|
|
48644
48822
|
|
|
48645
48823
|
// src/lib/codex-hook-trust-files.ts
|
|
48646
48824
|
import { closeSync as closeSync10, constants as constants7, fstatSync as fstatSync10, fsyncSync as fsyncSync2, lstatSync as lstatSync14, openSync as openSync10, readSync as readSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
48647
|
-
import { createHash as
|
|
48825
|
+
import { createHash as createHash13 } from "crypto";
|
|
48648
48826
|
import { dirname as dirname11 } from "path";
|
|
48649
48827
|
function need5(value, code) {
|
|
48650
48828
|
if (!value)
|
|
@@ -48679,7 +48857,7 @@ function snapshot(file2, privateFile = false, options = {}) {
|
|
|
48679
48857
|
}
|
|
48680
48858
|
need5(length === Number(before.size) && sameStat(before, fstatSync10(fd, { bigint: true })) && sameStat(before, lstatSync14(file2, { bigint: true })), "INPUT_CHANGED");
|
|
48681
48859
|
const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
|
|
48682
|
-
return { file: file2, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256:
|
|
48860
|
+
return { file: file2, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash13("sha256").update(content).digest("hex") };
|
|
48683
48861
|
} finally {
|
|
48684
48862
|
closeSync10(fd);
|
|
48685
48863
|
}
|
|
@@ -48748,12 +48926,12 @@ var init_skill_aliases = __esm(() => {
|
|
|
48748
48926
|
|
|
48749
48927
|
// src/lib/project-state.ts
|
|
48750
48928
|
import { existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync5 } from "fs";
|
|
48751
|
-
import { join as
|
|
48929
|
+
import { join as join20 } from "path";
|
|
48752
48930
|
function getProjectStateDir(targetDir = process.cwd()) {
|
|
48753
|
-
return
|
|
48931
|
+
return join20(targetDir, SKILLS_PROJECT_DIR);
|
|
48754
48932
|
}
|
|
48755
48933
|
function getProjectConfigPath(targetDir = process.cwd()) {
|
|
48756
|
-
return
|
|
48934
|
+
return join20(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
|
|
48757
48935
|
}
|
|
48758
48936
|
function loadProjectConfig(targetDir = process.cwd()) {
|
|
48759
48937
|
const path = getProjectConfigPath(targetDir);
|
|
@@ -48869,7 +49047,7 @@ var init_project_state = __esm(() => {
|
|
|
48869
49047
|
|
|
48870
49048
|
// src/lib/installer.ts
|
|
48871
49049
|
import { existsSync as existsSync10, readFileSync as readFileSync13, rmSync } from "fs";
|
|
48872
|
-
import { join as
|
|
49050
|
+
import { join as join21 } from "path";
|
|
48873
49051
|
import { homedir as homedir2 } from "os";
|
|
48874
49052
|
function getSkillPath(name) {
|
|
48875
49053
|
const skillName = normalizeSkillName(getCanonicalSkillName(name));
|
|
@@ -48879,7 +49057,7 @@ function getSkillPath(name) {
|
|
|
48879
49057
|
const extensionPath = findExtensionSkillPath(skillName);
|
|
48880
49058
|
if (extensionPath)
|
|
48881
49059
|
return extensionPath;
|
|
48882
|
-
return
|
|
49060
|
+
return join21(getPortableSkillsRoot(), skillName);
|
|
48883
49061
|
}
|
|
48884
49062
|
function getCanonicalSkillName(name) {
|
|
48885
49063
|
return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
|
|
@@ -48933,11 +49111,11 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
|
|
|
48933
49111
|
const base = projectDir || process.cwd();
|
|
48934
49112
|
switch (agent) {
|
|
48935
49113
|
case "pi":
|
|
48936
|
-
return scope === "project" ?
|
|
49114
|
+
return scope === "project" ? join21(base, ".pi", "skills") : join21(homedir2(), ".pi", "agent", "skills");
|
|
48937
49115
|
case "opencode":
|
|
48938
|
-
return scope === "project" ?
|
|
49116
|
+
return scope === "project" ? join21(base, ".opencode", "skills") : join21(homedir2(), ".config", "opencode", "skills");
|
|
48939
49117
|
default:
|
|
48940
|
-
return scope === "project" ?
|
|
49118
|
+
return scope === "project" ? join21(base, `.${agent}`, "skills") : join21(homedir2(), `.${agent}`, "skills");
|
|
48941
49119
|
}
|
|
48942
49120
|
}
|
|
48943
49121
|
function warnMissingDependencies(name, targetDir) {
|
|
@@ -48952,7 +49130,7 @@ function warnMissingDependencies(name, targetDir) {
|
|
|
48952
49130
|
}
|
|
48953
49131
|
}
|
|
48954
49132
|
function readBundledSkillVersion(name) {
|
|
48955
|
-
const pkgPath =
|
|
49133
|
+
const pkgPath = join21(getSkillPath(name), "package.json");
|
|
48956
49134
|
if (!existsSync10(pkgPath))
|
|
48957
49135
|
return "unknown";
|
|
48958
49136
|
try {
|
|
@@ -49022,11 +49200,11 @@ var init_skill_doc_file = __esm(() => {
|
|
|
49022
49200
|
|
|
49023
49201
|
// src/lib/skillinfo.ts
|
|
49024
49202
|
import { existsSync as existsSync11, readFileSync as readFileSync14 } from "fs";
|
|
49025
|
-
import { join as
|
|
49203
|
+
import { join as join22 } from "path";
|
|
49026
49204
|
function isInstructionSkillDir(skillPath, meta3) {
|
|
49027
49205
|
if (meta3?.kind === "instruction")
|
|
49028
49206
|
return true;
|
|
49029
|
-
const skillMdPath =
|
|
49207
|
+
const skillMdPath = join22(skillPath, "SKILL.md");
|
|
49030
49208
|
if (!existsSync11(skillMdPath))
|
|
49031
49209
|
return false;
|
|
49032
49210
|
try {
|
|
@@ -49040,9 +49218,9 @@ function getSkillDocs(name) {
|
|
|
49040
49218
|
if (!existsSync11(skillPath))
|
|
49041
49219
|
return null;
|
|
49042
49220
|
return {
|
|
49043
|
-
skillMd: readIfExists(
|
|
49044
|
-
readme: readIfExists(
|
|
49045
|
-
claudeMd: readIfExists(
|
|
49221
|
+
skillMd: readIfExists(join22(skillPath, "SKILL.md")),
|
|
49222
|
+
readme: readIfExists(join22(skillPath, "README.md")),
|
|
49223
|
+
claudeMd: readIfExists(join22(skillPath, "CLAUDE.md"))
|
|
49046
49224
|
};
|
|
49047
49225
|
}
|
|
49048
49226
|
function getSkillBestDoc(name, file2) {
|
|
@@ -49058,14 +49236,14 @@ function getSkillRequirements(name) {
|
|
|
49058
49236
|
return null;
|
|
49059
49237
|
const texts = [];
|
|
49060
49238
|
for (const file2 of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
|
|
49061
|
-
const content = readIfExists(
|
|
49239
|
+
const content = readIfExists(join22(skillPath, file2));
|
|
49062
49240
|
if (content)
|
|
49063
49241
|
texts.push(content);
|
|
49064
49242
|
}
|
|
49065
49243
|
const meta3 = getSkill(name);
|
|
49066
49244
|
let dependencies = {};
|
|
49067
49245
|
try {
|
|
49068
|
-
dependencies = JSON.parse(readFileSync14(
|
|
49246
|
+
dependencies = JSON.parse(readFileSync14(join22(skillPath, "package.json"), "utf8")).dependencies || {};
|
|
49069
49247
|
} catch {}
|
|
49070
49248
|
return getSkillRequirementsFromContent(name, texts, dependencies, meta3);
|
|
49071
49249
|
}
|
|
@@ -49127,7 +49305,7 @@ async function runSkill(name, args, options = {}) {
|
|
|
49127
49305
|
error: `Skill '${name}' is an instruction skill (kind: instruction) and is not runnable. Instruction skills are consumed by coding agents via SKILL.md, not executed with 'skills run'.`
|
|
49128
49306
|
};
|
|
49129
49307
|
}
|
|
49130
|
-
const pkgPath =
|
|
49308
|
+
const pkgPath = join22(skillPath, "package.json");
|
|
49131
49309
|
if (!existsSync11(pkgPath)) {
|
|
49132
49310
|
return { exitCode: 1, error: `No package.json in skill '${name}'` };
|
|
49133
49311
|
}
|
|
@@ -49147,12 +49325,12 @@ async function runSkill(name, args, options = {}) {
|
|
|
49147
49325
|
} catch {
|
|
49148
49326
|
return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
|
|
49149
49327
|
}
|
|
49150
|
-
const entryPath =
|
|
49328
|
+
const entryPath = join22(skillPath, entryPoint2);
|
|
49151
49329
|
if (!existsSync11(entryPath)) {
|
|
49152
49330
|
return { exitCode: 1, error: `Entry point '${entryPoint2}' not found in skill '${name}'` };
|
|
49153
49331
|
}
|
|
49154
49332
|
const env = { ...process.env, ...options.env };
|
|
49155
|
-
if (!existsSync11(
|
|
49333
|
+
if (!existsSync11(join22(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
|
|
49156
49334
|
const failure = await prepareSkillDependencies(skillPath, env, options.preparationTimeoutMs);
|
|
49157
49335
|
if (failure)
|
|
49158
49336
|
return failure;
|
|
@@ -49178,7 +49356,7 @@ async function runSkill(name, args, options = {}) {
|
|
|
49178
49356
|
function detectProjectSkills(cwd = process.cwd()) {
|
|
49179
49357
|
let pkg;
|
|
49180
49358
|
try {
|
|
49181
|
-
pkg = JSON.parse(readFileSync14(
|
|
49359
|
+
pkg = JSON.parse(readFileSync14(join22(cwd, "package.json"), "utf8"));
|
|
49182
49360
|
} catch {
|
|
49183
49361
|
return { detected: [], recommended: [] };
|
|
49184
49362
|
}
|
|
@@ -49383,7 +49561,7 @@ var init_selection_resolver = __esm(() => {
|
|
|
49383
49561
|
});
|
|
49384
49562
|
|
|
49385
49563
|
// src/lib/plugin-projection.ts
|
|
49386
|
-
import { createHash as
|
|
49564
|
+
import { createHash as createHash14 } from "crypto";
|
|
49387
49565
|
function pluginRefusal(message) {
|
|
49388
49566
|
throw new SkillSelectionError("PLUGIN_ADMISSION_REFUSED", message);
|
|
49389
49567
|
}
|
|
@@ -49461,7 +49639,7 @@ function pluginFileWitnesses(entries) {
|
|
|
49461
49639
|
return { path: item.path, mode: item.mode, size: item.bytes.byteLength, sha256: pluginHash(item.bytes) };
|
|
49462
49640
|
});
|
|
49463
49641
|
}
|
|
49464
|
-
var PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) =>
|
|
49642
|
+
var PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) => createHash14("sha256").update(bytes).digest("hex");
|
|
49465
49643
|
var init_plugin_projection = __esm(() => {
|
|
49466
49644
|
init_selection_cache();
|
|
49467
49645
|
PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
|
|
@@ -49469,7 +49647,7 @@ var init_plugin_projection = __esm(() => {
|
|
|
49469
49647
|
|
|
49470
49648
|
// src/lib/plugin-projection-store.ts
|
|
49471
49649
|
import { constants as constants8, closeSync as closeSync11, fchmodSync, fstatSync as fstatSync11, fsyncSync as fsyncSync3, linkSync as linkSync2, lstatSync as lstatSync15, mkdirSync as mkdirSync6, openSync as openSync11, opendirSync as opendirSync2, readSync as readSync7, renameSync as renameSync2, rmdirSync as rmdirSync2, rmSync as rmSync2, unlinkSync as unlinkSync3, writeSync as writeSync2 } from "fs";
|
|
49472
|
-
import { dirname as dirname12, isAbsolute as isAbsolute9, join as
|
|
49650
|
+
import { dirname as dirname12, isAbsolute as isAbsolute9, join as join23, parse as parse10, resolve as resolve11 } from "path";
|
|
49473
49651
|
function stat(path) {
|
|
49474
49652
|
try {
|
|
49475
49653
|
return lstatSync15(path, { bigint: true });
|
|
@@ -49479,7 +49657,7 @@ function stat(path) {
|
|
|
49479
49657
|
return pluginRefusal("Cannot inspect plugin filesystem entry");
|
|
49480
49658
|
}
|
|
49481
49659
|
}
|
|
49482
|
-
function
|
|
49660
|
+
function canonical6(path) {
|
|
49483
49661
|
pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute9(path) && resolve11(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
|
|
49484
49662
|
}
|
|
49485
49663
|
function owner(stats, system = false) {
|
|
@@ -49490,12 +49668,12 @@ function same3(left, right, identityOnly = false) {
|
|
|
49490
49668
|
pluginNeed(right && left.dev === right.dev && left.ino === right.ino && left.mode === right.mode && left.uid === right.uid && left.gid === right.gid && (identityOnly || left.size === right.size && left.nlink === right.nlink && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs), "Plugin filesystem entry changed during access");
|
|
49491
49669
|
}
|
|
49492
49670
|
function ancestors(path, create = false) {
|
|
49493
|
-
|
|
49494
|
-
const result = [], parent = dirname12(path), filesystemRoot =
|
|
49671
|
+
canonical6(path);
|
|
49672
|
+
const result = [], parent = dirname12(path), filesystemRoot = parse10(parent).root;
|
|
49495
49673
|
let current = filesystemRoot;
|
|
49496
49674
|
for (const segment of ["", ...parent.slice(filesystemRoot.length).split("/").filter(Boolean)]) {
|
|
49497
49675
|
if (segment)
|
|
49498
|
-
current =
|
|
49676
|
+
current = join23(current, segment);
|
|
49499
49677
|
let currentStat = stat(current);
|
|
49500
49678
|
if (!currentStat && create) {
|
|
49501
49679
|
try {
|
|
@@ -49603,7 +49781,7 @@ function snapshotPluginTree(root, options = {}) {
|
|
|
49603
49781
|
pluginNeed(++visited <= PLUGIN_PROJECTION_LIMITS.files * 50, "Plugin tree membership exceeds its limit");
|
|
49604
49782
|
const path = relative5 ? `${relative5}/${name}` : name;
|
|
49605
49783
|
pluginNeed(new TextEncoder().encode(path).byteLength <= 100 && !/[\\:\x00-\x1f\x7f]/u.test(path), "Plugin entry path exceeds its limit or is unsafe");
|
|
49606
|
-
const absolute =
|
|
49784
|
+
const absolute = join23(directory, name), entryStat = stat(absolute);
|
|
49607
49785
|
pluginNeed(entryStat, "Plugin tree member disappeared");
|
|
49608
49786
|
if (relative5 === "" && name === ".orphaned_at" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
|
|
49609
49787
|
const bytes2 = readBytes(absolute, 32, "native-pin");
|
|
@@ -49620,7 +49798,7 @@ function snapshotPluginTree(root, options = {}) {
|
|
|
49620
49798
|
directories.push({ path: absolute, stat: entryStat, names: pins });
|
|
49621
49799
|
for (const pin of pins) {
|
|
49622
49800
|
pluginNeed(/^[1-9][0-9]{0,9}$/.test(pin) && Number(pin) <= 2147483647, "Unrecognized native plugin pin name");
|
|
49623
|
-
const pinPath =
|
|
49801
|
+
const pinPath = join23(absolute, pin), pinStat = stat(pinPath);
|
|
49624
49802
|
pluginNeed(pinStat, "Native plugin pin disappeared");
|
|
49625
49803
|
const bytes2 = readBytes(pinPath, 4096, "native-pin");
|
|
49626
49804
|
let value;
|
|
@@ -49717,7 +49895,7 @@ var init_selected_manifest = __esm(() => {
|
|
|
49717
49895
|
});
|
|
49718
49896
|
|
|
49719
49897
|
// src/lib/plugin-admission.ts
|
|
49720
|
-
import { isAbsolute as isAbsolute10, join as
|
|
49898
|
+
import { isAbsolute as isAbsolute10, join as join24, resolve as resolve12 } from "path";
|
|
49721
49899
|
function validatePluginTarget(value) {
|
|
49722
49900
|
pluginKeys(value, ["schemaVersion", "pluginId", "registrations", "native", "resolver"]);
|
|
49723
49901
|
pluginNeed(value.schemaVersion === 1, "Invalid plugin admission target");
|
|
@@ -49878,12 +50056,12 @@ function pluginResolverCommand(binding) {
|
|
|
49878
50056
|
}
|
|
49879
50057
|
function pluginBindingPath(storeRoot, id) {
|
|
49880
50058
|
pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
|
|
49881
|
-
return
|
|
50059
|
+
return join24(storeRoot, "bindings", `${id}.json`);
|
|
49882
50060
|
}
|
|
49883
50061
|
function pluginReceiptPath(storeRoot, id, digest) {
|
|
49884
50062
|
pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
|
|
49885
50063
|
pluginDigest(digest);
|
|
49886
|
-
return
|
|
50064
|
+
return join24(storeRoot, "receipts", id, `${digest.slice(7)}.json`);
|
|
49887
50065
|
}
|
|
49888
50066
|
function readPluginBinding(storeRoot, id) {
|
|
49889
50067
|
const value = readPluginJson(pluginBindingPath(storeRoot, id));
|
|
@@ -49903,7 +50081,7 @@ function readPluginAdmissionReceipt(storeRoot, id, digest) {
|
|
|
49903
50081
|
pluginNeed(receipt.plan.bindingId === id && receipt.plan.planDigest === digest, "Plugin receipt identity differs from its filename");
|
|
49904
50082
|
const binding = readPluginBinding(storeRoot, id);
|
|
49905
50083
|
pluginNeed(canonicalJson(binding) === canonicalJson(receipt.plan.binding) && receipt.plan.sourceCommand === pluginResolverCommand(binding), "Plugin receipt binding changed");
|
|
49906
|
-
pluginNeed(receipt.materializedPath ===
|
|
50084
|
+
pluginNeed(receipt.materializedPath === join24(storeRoot, "objects", id, digest.slice(7)), "Plugin receipt points outside its immutable materialization");
|
|
49907
50085
|
pluginText(receipt.admittedAt, 64);
|
|
49908
50086
|
pluginNeed(Number.isFinite(Date.parse(receipt.admittedAt)), "Invalid plugin admission time");
|
|
49909
50087
|
return receipt;
|
|
@@ -49921,7 +50099,7 @@ var init_plugin_admission = __esm(() => {
|
|
|
49921
50099
|
|
|
49922
50100
|
// src/lib/plugin-discovery.ts
|
|
49923
50101
|
import { closeSync as closeSync12, constants as constants9, fstatSync as fstatSync12, lstatSync as lstatSync16, openSync as openSync12, opendirSync as opendirSync3, readSync as readSync8 } from "fs";
|
|
49924
|
-
import { basename as basename6, dirname as dirname13, isAbsolute as isAbsolute11, join as
|
|
50102
|
+
import { basename as basename6, dirname as dirname13, isAbsolute as isAbsolute11, join as join25, resolve as resolve13 } from "path";
|
|
49925
50103
|
function validateManagedPluginWitnesses(value) {
|
|
49926
50104
|
pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
|
|
49927
50105
|
const seen = new Set;
|
|
@@ -49988,7 +50166,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
49988
50166
|
seen.add(target.pluginId);
|
|
49989
50167
|
const rows = plugins[target.pluginId];
|
|
49990
50168
|
pluginNeed(Array.isArray(rows) && rows.length === target.registrations.length, "Managed plugin registration membership changed");
|
|
49991
|
-
const [name, market] = target.pluginId.split("@"), cacheRoot =
|
|
50169
|
+
const [name, market] = target.pluginId.split("@"), cacheRoot = join25(dirname13(path), "cache", market, name);
|
|
49992
50170
|
const scopes = new Set, approvals = new Map, currentFiles = new Map;
|
|
49993
50171
|
plugins[target.pluginId] = rows.map((row) => {
|
|
49994
50172
|
pluginNeed(pluginObject(row), "Invalid managed plugin registration");
|
|
@@ -50001,7 +50179,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
50001
50179
|
pluginText(row.sourceProducerPath);
|
|
50002
50180
|
pluginText(row.lastUpdated, 64);
|
|
50003
50181
|
pluginNeed(Number.isFinite(Date.parse(row.lastUpdated)), "Invalid managed plugin update timestamp");
|
|
50004
|
-
pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath ===
|
|
50182
|
+
pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join25(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
|
|
50005
50183
|
const approval = (producer) => {
|
|
50006
50184
|
pluginText(producer);
|
|
50007
50185
|
const digest = `sha256:${basename6(producer)}`;
|
|
@@ -50044,11 +50222,11 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
50044
50222
|
directory.closeSync();
|
|
50045
50223
|
}
|
|
50046
50224
|
for (const version2 of names.sort()) {
|
|
50047
|
-
const files = pluginFileWitnesses(snapshotPluginTree(
|
|
50225
|
+
const files = pluginFileWitnesses(snapshotPluginTree(join25(cacheRoot, version2), { nativeRuntime: `claude-${target.native.version}` }));
|
|
50048
50226
|
verifiedBytes += files.reduce((total, file2) => total + file2.size, 0);
|
|
50049
50227
|
pluginNeed(verifiedBytes <= 256 * 1024 * 1024, "Managed plugin verification exceeds its aggregate byte budget");
|
|
50050
50228
|
const serialized = JSON.stringify(files);
|
|
50051
|
-
const expected = currentFiles.get(
|
|
50229
|
+
const expected = currentFiles.get(join25(cacheRoot, version2));
|
|
50052
50230
|
pluginNeed(expected === undefined || serialized === expected, "Current native cache differs from its exact registered producer receipt");
|
|
50053
50231
|
pluginNeed([...approvals.values()].some((receipt) => nativeVersionMatches(version2, receipt) && JSON.stringify(receipt.plan.files) === serialized), "A retained native plugin cache version differs from every approved projection");
|
|
50054
50232
|
}
|
|
@@ -50068,7 +50246,7 @@ var init_plugin_discovery = __esm(() => {
|
|
|
50068
50246
|
});
|
|
50069
50247
|
|
|
50070
50248
|
// src/lib/claude-marketplace-registry.ts
|
|
50071
|
-
import { createHash as
|
|
50249
|
+
import { createHash as createHash15 } from "crypto";
|
|
50072
50250
|
import { closeSync as closeSync13, constants as constants10, fstatSync as fstatSync13, lstatSync as lstatSync17, openSync as openSync13, readSync as readSync9 } from "fs";
|
|
50073
50251
|
import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute12, resolve as resolve14 } from "path";
|
|
50074
50252
|
function need6(value, reason) {
|
|
@@ -50123,7 +50301,7 @@ function readRegistry2(path, budget2) {
|
|
|
50123
50301
|
closeSync13(fd);
|
|
50124
50302
|
}
|
|
50125
50303
|
}
|
|
50126
|
-
function
|
|
50304
|
+
function parse11(text2) {
|
|
50127
50305
|
let at = 0, nodes = 0;
|
|
50128
50306
|
const numberPattern = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/y;
|
|
50129
50307
|
const space = () => {
|
|
@@ -50231,17 +50409,17 @@ function normalizeRow(row, version2 = 1) {
|
|
|
50231
50409
|
row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
|
|
50232
50410
|
}
|
|
50233
50411
|
function captureClaudeMarketplaceRegistry(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
50234
|
-
const value =
|
|
50412
|
+
const value = parse11(readRegistry2(path, budget2));
|
|
50235
50413
|
for (const [, row] of value.entries)
|
|
50236
50414
|
normalizeRow(row);
|
|
50237
|
-
const sha2562 =
|
|
50415
|
+
const sha2562 = createHash15("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
|
|
50238
50416
|
return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
|
|
50239
50417
|
}
|
|
50240
50418
|
function captureClaudeMarketplaceRegistryV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
50241
|
-
const value =
|
|
50419
|
+
const value = parse11(readRegistry2(path, budget2));
|
|
50242
50420
|
for (const [, row] of value.entries)
|
|
50243
50421
|
normalizeRow(row, 2);
|
|
50244
|
-
const sha2562 =
|
|
50422
|
+
const sha2562 = createHash15("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
|
|
50245
50423
|
return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2562 };
|
|
50246
50424
|
}
|
|
50247
50425
|
var CLAUDE_MARKETPLACE_REGISTRY_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, field = (object7, key) => object7.entries.find(([name]) => name === key)?.[1];
|
|
@@ -50263,7 +50441,7 @@ var init_codex_hook_additions_review = __esm(() => {
|
|
|
50263
50441
|
});
|
|
50264
50442
|
|
|
50265
50443
|
// src/lib/codex-hook-discovery-recovery.ts
|
|
50266
|
-
import { createHash as
|
|
50444
|
+
import { createHash as createHash16 } from "crypto";
|
|
50267
50445
|
function assertCodexHookDiscoveryRecovery(binding, witness) {
|
|
50268
50446
|
const proof = proofs2.get(witness);
|
|
50269
50447
|
need5(!!proof && binding.agent === "codex" && witness.discoverySha256 === sha3(JSON.stringify(binding)), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
|
|
@@ -50278,7 +50456,7 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
|
|
|
50278
50456
|
need5(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
|
|
50279
50457
|
return true;
|
|
50280
50458
|
}
|
|
50281
|
-
var sha3 = (text2) =>
|
|
50459
|
+
var sha3 = (text2) => createHash16("sha256").update(text2).digest("hex"), fields, proofs2;
|
|
50282
50460
|
var init_codex_hook_discovery_recovery = __esm(() => {
|
|
50283
50461
|
init_codex_hook_trust_files();
|
|
50284
50462
|
init_codex_hook_trust_layout();
|
|
@@ -50289,9 +50467,9 @@ var init_codex_hook_discovery_recovery = __esm(() => {
|
|
|
50289
50467
|
});
|
|
50290
50468
|
|
|
50291
50469
|
// src/lib/agent-discovery.ts
|
|
50292
|
-
import { createHash as
|
|
50470
|
+
import { createHash as createHash17 } from "crypto";
|
|
50293
50471
|
import { lstatSync as lstatSync18, readFileSync as readFileSync15, readdirSync as readdirSync7, realpathSync as realpathSync5 } from "fs";
|
|
50294
|
-
import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute13, join as
|
|
50472
|
+
import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute13, join as join26, resolve as resolve15, sep as sep6 } from "path";
|
|
50295
50473
|
import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
|
|
50296
50474
|
function parseConfig(text2, path, toml = false) {
|
|
50297
50475
|
try {
|
|
@@ -50378,6 +50556,12 @@ function projected(source, changes, budget2 = discoveryByteBudget()) {
|
|
|
50378
50556
|
throw new Error("Managed plugin registry witnesses require verified native registrations");
|
|
50379
50557
|
return hashManagedPluginRegistry(source.path, source.managedPlugins);
|
|
50380
50558
|
}
|
|
50559
|
+
if (source.hashMode === "claude-plugin-manifest-v1") {
|
|
50560
|
+
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || changes?.has(source.path))
|
|
50561
|
+
throw new Error("Claude plugin manifest witnesses require a native discovery source without synthetic changes");
|
|
50562
|
+
const text3 = read(source.path);
|
|
50563
|
+
return text3 === null ? null : hashClaudePluginManifest(text3);
|
|
50564
|
+
}
|
|
50381
50565
|
if (source.managedPlugins !== undefined)
|
|
50382
50566
|
throw new Error("Managed plugin rules require a typed registry witness");
|
|
50383
50567
|
if (source.hashMode !== undefined) {
|
|
@@ -50404,7 +50588,7 @@ function absentCodexSkillRoots(binding) {
|
|
|
50404
50588
|
throw new Error("Invalid disabled Codex discovery proof");
|
|
50405
50589
|
if (binding.method !== "reviewed" || controls.every((control) => lstatSync18(control.pluginParent, { throwIfNoEntry: false })))
|
|
50406
50590
|
return [];
|
|
50407
|
-
const cache = dirname15(dirname15(controls[0].pluginParent)), config2 =
|
|
50591
|
+
const cache = dirname15(dirname15(controls[0].pluginParent)), config2 = join26(dirname15(dirname15(cache)), "config.toml");
|
|
50408
50592
|
const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
|
|
50409
50593
|
if (!source || projected(source) !== source.sha256)
|
|
50410
50594
|
throw new Error("Missing current disabled Codex configuration witness");
|
|
@@ -50412,8 +50596,8 @@ function absentCodexSkillRoots(binding) {
|
|
|
50412
50596
|
return [...new Set(controls.map((control) => control.pluginParent))].filter((parent) => !codexDirectHookSelects(cache, parent) && absentDisabledCodexPluginParent(cache, parent, controls, rules));
|
|
50413
50597
|
}
|
|
50414
50598
|
function codexDirectHookSelects(cache, root) {
|
|
50415
|
-
const codex = dirname15(dirname15(cache)), config2 = Bun.TOML.parse(read(
|
|
50416
|
-
const hooks = read(
|
|
50599
|
+
const codex = dirname15(dirname15(cache)), config2 = Bun.TOML.parse(read(join26(codex, "config.toml")) ?? "");
|
|
50600
|
+
const hooks = read(join26(codex, "hooks.json"));
|
|
50417
50601
|
if (hooks !== null)
|
|
50418
50602
|
hashNativeJsonControls(hooks);
|
|
50419
50603
|
return JSON.stringify(config2.hooks ?? {}).includes(root) || hooks !== null && JSON.stringify(JSON.parse(hooks)).includes(root);
|
|
@@ -50425,7 +50609,7 @@ function retiredCodexRoots(binding) {
|
|
|
50425
50609
|
const controls = binding.codexDisabledPluginSkills;
|
|
50426
50610
|
if (binding.agent !== "codex" || binding.method !== "reviewed" || !Array.isArray(controls) || !controls.length || !Array.isArray(proof.roots) || proof.roots.length > AGENT_POLICY_LIMITS.discoveryRoots || new Set(proof.roots).size !== proof.roots.length || !Array.isArray(proof.directories) || proof.parents !== undefined && (!Array.isArray(proof.parents) || proof.parents.length > AGENT_POLICY_LIMITS.discoveryRoots || new Set(proof.parents).size !== proof.parents.length) || !proof.roots.length && !proof.parents?.length)
|
|
50427
50611
|
throw new Error("Invalid retired Codex materialization proof");
|
|
50428
|
-
const cache = dirname15(dirname15(controls[0].pluginParent)), config2 =
|
|
50612
|
+
const cache = dirname15(dirname15(controls[0].pluginParent)), config2 = join26(dirname15(dirname15(cache)), "config.toml");
|
|
50429
50613
|
const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
|
|
50430
50614
|
if (!source || projected(source) !== source.sha256)
|
|
50431
50615
|
throw new Error("Missing current retired Codex configuration witness");
|
|
@@ -50433,7 +50617,7 @@ function retiredCodexRoots(binding) {
|
|
|
50433
50617
|
if ((proof.parents ?? []).some((parent) => codexDirectHookSelects(cache, parent) || !reviewedDisabledCodexPluginParent(cache, parent, controls, rules)) || !reviewedCodexPluginCapabilitiesUnchanged(cache, controls, (path) => read(path), rules))
|
|
50434
50618
|
throw new Error("Retired Codex parent capabilities changed");
|
|
50435
50619
|
for (const root of proof.roots) {
|
|
50436
|
-
const manifest = binding.sources.find((source2) => source2.path ===
|
|
50620
|
+
const manifest = binding.sources.find((source2) => source2.path === join26(root, ".codex-plugin/plugin.json") && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined && [undefined, "bytes"].includes(source2.hashMode));
|
|
50437
50621
|
if (!manifest || codexDirectHookSelects(cache, root) || !reviewedRetiredCodexRoot(cache, root, controls, rules, (path) => read(path), true))
|
|
50438
50622
|
throw new Error("Retired Codex materialization changed");
|
|
50439
50623
|
}
|
|
@@ -50446,17 +50630,17 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
50446
50630
|
for (const source of binding.sources) {
|
|
50447
50631
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || ![undefined, "bytes"].includes(source.hashMode) || source.sha256 === null)
|
|
50448
50632
|
continue;
|
|
50449
|
-
const marker =
|
|
50633
|
+
const marker = sep6 + ".claude" + sep6 + "plugins" + sep6 + "cache" + sep6, at = source.path.indexOf(marker);
|
|
50450
50634
|
if (at < 0 || source.path.indexOf(marker, at + 1) >= 0)
|
|
50451
50635
|
continue;
|
|
50452
|
-
const cache = source.path.slice(0, at + marker.length - 1), parts = source.path.slice(at + marker.length).split(
|
|
50636
|
+
const cache = source.path.slice(0, at + marker.length - 1), parts = source.path.slice(at + marker.length).split(sep6);
|
|
50453
50637
|
if (parts.length < 4 || parts.slice(0, 3).some((part) => !part || part === "." || part === ".."))
|
|
50454
50638
|
continue;
|
|
50455
|
-
const root =
|
|
50639
|
+
const root = join26(cache, ...parts.slice(0, 3));
|
|
50456
50640
|
safe4(root);
|
|
50457
50641
|
if (lstatSync18(root, { throwIfNoEntry: false }))
|
|
50458
50642
|
continue;
|
|
50459
|
-
const claude = dirname15(dirname15(cache)), settings =
|
|
50643
|
+
const claude = dirname15(dirname15(cache)), settings = join26(claude, "settings.json"), registry2 = join26(claude, "plugins/installed_plugins.json");
|
|
50460
50644
|
const full = (path) => binding.sources.find((item) => item.path === path && item.sha256 !== null && item.format === undefined && item.fields === undefined);
|
|
50461
50645
|
const configSource = full(settings), registrySource = full(registry2);
|
|
50462
50646
|
if (!configSource || !registrySource || projected(configSource) !== configSource.sha256 || projected(registrySource) !== registrySource.sha256)
|
|
@@ -50475,10 +50659,10 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
50475
50659
|
const active = rows[0].installPath;
|
|
50476
50660
|
if (rows[0].version !== basename8(active) || resolve15(active) !== active || dirname15(active) !== dirname15(root) || active === root || !lstatSync18(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync5(active) !== active)
|
|
50477
50661
|
continue;
|
|
50478
|
-
const activeManifest = full(
|
|
50662
|
+
const activeManifest = full(join26(active, ".claude-plugin/plugin.json"));
|
|
50479
50663
|
if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
|
|
50480
50664
|
continue;
|
|
50481
|
-
if (Object.values(installed.plugins).some((value) => !Array.isArray(value) || value.some((row) => !row || typeof row.installPath !== "string" || row.installPath === root || row.installPath.startsWith(root +
|
|
50665
|
+
if (Object.values(installed.plugins).some((value) => !Array.isArray(value) || value.some((row) => !row || typeof row.installPath !== "string" || row.installPath === root || row.installPath.startsWith(root + sep6) || root.startsWith(row.installPath + sep6))))
|
|
50482
50666
|
continue;
|
|
50483
50667
|
result.add(root);
|
|
50484
50668
|
}
|
|
@@ -50493,10 +50677,10 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
50493
50677
|
throw new Error("Hermes discovery requires directory membership coverage; run skills hook install with a fresh discovery review");
|
|
50494
50678
|
const installationRoots = codexInstallationRoots(binding);
|
|
50495
50679
|
const retiredRoots = retiredCodexRoots(binding);
|
|
50496
|
-
const installationInput = (path) => installationRoots.some((root) => path === root || path.startsWith(root +
|
|
50680
|
+
const installationInput = (path) => installationRoots.some((root) => path === root || path.startsWith(root + sep6));
|
|
50497
50681
|
if (binding.directories !== undefined) {
|
|
50498
50682
|
const projected2 = binding.codexInstallationInputs?.directories ?? [];
|
|
50499
|
-
const ancestors2 = binding.directories.filter((directory) => installationRoots.some((root) => root.startsWith(directory.path +
|
|
50683
|
+
const ancestors2 = binding.directories.filter((directory) => installationRoots.some((root) => root.startsWith(directory.path + sep6)));
|
|
50500
50684
|
if (projected2.length !== ancestors2.length || projected2.some((directory) => !ancestors2.some((original) => original.path === directory.path)))
|
|
50501
50685
|
throw new Error("Missing installation input directory projection");
|
|
50502
50686
|
const ordinary = binding.directories.filter((directory) => !installationInput(directory.path) && !ancestors2.includes(directory));
|
|
@@ -50532,7 +50716,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
50532
50716
|
safe4(source.path);
|
|
50533
50717
|
continue;
|
|
50534
50718
|
}
|
|
50535
|
-
if (absentRoots.some((root) => source.path.startsWith(root +
|
|
50719
|
+
if (absentRoots.some((root) => source.path.startsWith(root + sep6)) && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined && [undefined, "bytes"].includes(source.hashMode)) {
|
|
50536
50720
|
safe4(source.path);
|
|
50537
50721
|
continue;
|
|
50538
50722
|
}
|
|
@@ -50555,12 +50739,12 @@ function codexInstallationRoots(binding) {
|
|
|
50555
50739
|
if (binding.agent !== "codex" || binding.method !== "reviewed" || proof.version !== "codex-cli 0.160.0" || !/^[a-f0-9]{64}$/.test(proof.catalogSha256) || !Array.isArray(proof.plugins) || !proof.plugins.length)
|
|
50556
50740
|
throw new Error("Invalid native installation input proof");
|
|
50557
50741
|
const cache = dirname15(dirname15(proof.plugins[0].pluginParent));
|
|
50558
|
-
const config2 =
|
|
50742
|
+
const config2 = join26(dirname15(dirname15(cache)), "config.toml"), home = dirname15(dirname15(dirname15(cache)));
|
|
50559
50743
|
const configSource = binding.sources.find((source) => source.path === config2 && source.sha256 !== null && (!source.format || source.format === "toml" && source.fields?.includes("plugins")));
|
|
50560
|
-
const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) =>
|
|
50561
|
-
if (!configSource || proof.plugins.some((input2) => nativeRoots.some((root) => root === input2.sourceRoot || root.startsWith(input2.sourceRoot +
|
|
50744
|
+
const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join26(home, path));
|
|
50745
|
+
if (!configSource || proof.plugins.some((input2) => nativeRoots.some((root) => root === input2.sourceRoot || root.startsWith(input2.sourceRoot + sep6) || input2.sourceRoot.startsWith(root + sep6)) || binding.sources.some((source) => basename8(source.path) === "config.toml" && (source.path === input2.sourceRoot || source.path.startsWith(input2.sourceRoot + sep6)))))
|
|
50562
50746
|
throw new Error("Native installation input overlaps configuration or loading roots");
|
|
50563
|
-
if (proof.plugins.some((input2) => dirname15(dirname15(input2.pluginParent)) !== cache || !binding.sources.some((source) => source.path ===
|
|
50747
|
+
if (proof.plugins.some((input2) => dirname15(dirname15(input2.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join26(input2.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
|
|
50564
50748
|
throw new Error("Missing native installation input source witness");
|
|
50565
50749
|
return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
|
|
50566
50750
|
const text2 = read(path);
|
|
@@ -50570,6 +50754,8 @@ function codexInstallationRoots(binding) {
|
|
|
50570
50754
|
});
|
|
50571
50755
|
}
|
|
50572
50756
|
function assertMarketplaceBinding(binding, source) {
|
|
50757
|
+
if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" || basename8(source.path) !== "plugin.json" || !source.path.endsWith(join26(sep6, ".claude-plugin", "plugin.json"))))
|
|
50758
|
+
throw new Error("Claude plugin manifest witnesses require Claude plugin discovery");
|
|
50573
50759
|
if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename8(source.path) !== "sumi.json"))
|
|
50574
50760
|
throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
|
|
50575
50761
|
if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) && (binding.agent !== "codex" || binding.method !== "reviewed" || basename8(source.path) !== "config.toml"))
|
|
@@ -50582,13 +50768,13 @@ function assertMarketplaceBinding(binding, source) {
|
|
|
50582
50768
|
function agentDiscoveryConfigPath(home, agent) {
|
|
50583
50769
|
if (agent === "sumi")
|
|
50584
50770
|
return sumiConfigPath(home);
|
|
50585
|
-
return
|
|
50771
|
+
return join26(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
|
|
50586
50772
|
}
|
|
50587
50773
|
function resolveAgentDiscovery(options) {
|
|
50588
|
-
const
|
|
50774
|
+
const canonical7 = options.canonical ?? resolve15, home = resolve15(options.home), agent = options.agent;
|
|
50589
50775
|
const sources = [], roots = new Set, builtinNames = [];
|
|
50590
|
-
const witness = (path, format, fields2) => {
|
|
50591
|
-
const source = { path:
|
|
50776
|
+
const witness = (path, format, fields2, hashMode) => {
|
|
50777
|
+
const source = { path: canonical7(path), sha256: null, ...format ? { format, fields: fields2 } : {}, ...hashMode ? { hashMode } : {} };
|
|
50592
50778
|
source.sha256 = projected(source);
|
|
50593
50779
|
sources.push(source);
|
|
50594
50780
|
return read(source.path);
|
|
@@ -50601,31 +50787,34 @@ function resolveAgentDiscovery(options) {
|
|
|
50601
50787
|
const unresolved = (detail) => {
|
|
50602
50788
|
throw new Error(`Native discovery is unresolved (${agent}: ${detail}); provide a reviewed --discovery-inputs file`);
|
|
50603
50789
|
};
|
|
50790
|
+
if (options.reviewed && (options.reviewed.version !== 1 || !Array.isArray(options.reviewed.agents) || options.reviewed.agents.some((item) => !item || typeof item !== "object") || new Set(options.reviewed.agents.map((item) => item.agent)).size !== options.reviewed.agents.length))
|
|
50791
|
+
throw new Error("Invalid --discovery-inputs version or agents");
|
|
50792
|
+
const review = options.reviewed?.agents.find((item) => item.agent === agent);
|
|
50604
50793
|
if (agent === "sumi") {
|
|
50605
50794
|
const directory = sumiConfigDirectory(home);
|
|
50606
|
-
if (witness(
|
|
50795
|
+
if (witness(join26(directory, "sumi.jsonc")) !== null)
|
|
50607
50796
|
unresolved("JSONC configuration requires a supported format adapter");
|
|
50608
|
-
for (const root of [directory,
|
|
50797
|
+
for (const root of [directory, join26(home, ".claude"), join26(home, ".agents")])
|
|
50609
50798
|
for (const name of ["skill", "skills"])
|
|
50610
|
-
roots.add(
|
|
50799
|
+
roots.add(canonical7(join26(root, name)));
|
|
50611
50800
|
if (config2.skills !== undefined && (!Array.isArray(config2.skills) || config2.skills.some((path) => typeof path !== "string")))
|
|
50612
50801
|
unresolved("skills must be a string array");
|
|
50613
50802
|
for (const value of config2.skills ?? []) {
|
|
50614
50803
|
if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute13(value) || value.startsWith("~/")))
|
|
50615
50804
|
unresolved("remote or relative skill sources need a dedicated discovery adapter");
|
|
50616
|
-
roots.add(
|
|
50805
|
+
roots.add(canonical7(value.startsWith("~/") ? join26(home, value.slice(2)) : value));
|
|
50617
50806
|
}
|
|
50618
50807
|
for (const key of ["plugin", "plugins"])
|
|
50619
50808
|
if (config2[key] !== undefined && !Array.isArray(config2[key]))
|
|
50620
50809
|
unresolved(`${key} must be an array`);
|
|
50621
|
-
const plugins = [
|
|
50810
|
+
const plugins = [join26(directory, "plugin"), join26(directory, "plugins")];
|
|
50622
50811
|
for (const path of plugins) {
|
|
50623
50812
|
safe4(path);
|
|
50624
50813
|
if (lstatSync18(path, { throwIfNoEntry: false })?.isDirectory())
|
|
50625
50814
|
for (const name of readdirSync7(path).sort()) {
|
|
50626
50815
|
if (name === "skills-cli.js" && path === plugins[1])
|
|
50627
50816
|
continue;
|
|
50628
|
-
const target =
|
|
50817
|
+
const target = join26(path, name);
|
|
50629
50818
|
if (!lstatSync18(target).isFile())
|
|
50630
50819
|
unresolved("local plugin packages need a dedicated discovery adapter");
|
|
50631
50820
|
witness(target);
|
|
@@ -50638,7 +50827,7 @@ function resolveAgentDiscovery(options) {
|
|
|
50638
50827
|
}
|
|
50639
50828
|
}
|
|
50640
50829
|
if (agent === "hermes") {
|
|
50641
|
-
const profile = witness(
|
|
50830
|
+
const profile = witness(join26(home, ".hermes/active_profile"));
|
|
50642
50831
|
if (profile?.trim() && profile.trim() !== "default")
|
|
50643
50832
|
unresolved("a non-default profile is active");
|
|
50644
50833
|
const declared = config2.skills?.external_dirs ?? [], paths = typeof declared === "string" ? [declared] : declared;
|
|
@@ -50652,7 +50841,7 @@ function resolveAgentDiscovery(options) {
|
|
|
50652
50841
|
continue;
|
|
50653
50842
|
if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
|
|
50654
50843
|
unresolved("user-specific tilde expansion requires a separate discovery adapter");
|
|
50655
|
-
const path = normalized === "~" ? home : normalized.startsWith("~/") ?
|
|
50844
|
+
const path = normalized === "~" ? home : normalized.startsWith("~/") ? join26(home, normalized.slice(2)) : resolve15(home, ".hermes", normalized);
|
|
50656
50845
|
safe4(path);
|
|
50657
50846
|
roots.add(path);
|
|
50658
50847
|
}
|
|
@@ -50662,7 +50851,7 @@ function resolveAgentDiscovery(options) {
|
|
|
50662
50851
|
if (executable) {
|
|
50663
50852
|
let packageRoot;
|
|
50664
50853
|
for (let directory = dirname15(realpathSync5(executable)), depth = 0;depth < 8; directory = dirname15(directory), depth++) {
|
|
50665
|
-
const path =
|
|
50854
|
+
const path = join26(directory, "package.json"), raw = read(path);
|
|
50666
50855
|
if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
|
|
50667
50856
|
packageRoot = directory;
|
|
50668
50857
|
witness(path);
|
|
@@ -50673,12 +50862,12 @@ function resolveAgentDiscovery(options) {
|
|
|
50673
50862
|
}
|
|
50674
50863
|
if (!packageRoot)
|
|
50675
50864
|
unresolved("installed Gemini package layout is not recognized");
|
|
50676
|
-
const builtinRoot =
|
|
50865
|
+
const builtinRoot = join26(packageRoot, "bundle/builtin");
|
|
50677
50866
|
safe4(builtinRoot);
|
|
50678
50867
|
if (!lstatSync18(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
|
|
50679
50868
|
unresolved("installed Gemini builtin root is missing");
|
|
50680
50869
|
for (const name of readdirSync7(builtinRoot).sort()) {
|
|
50681
|
-
const text2 = witness(
|
|
50870
|
+
const text2 = witness(join26(builtinRoot, name, "SKILL.md"));
|
|
50682
50871
|
const match = text2?.match(/^---\r?\n[\s\S]*?^name:\s*([a-z0-9][a-z0-9-]*)\s*$/m);
|
|
50683
50872
|
if (!match?.[1] || builtinNames.includes(match[1]))
|
|
50684
50873
|
unresolved("installed Gemini builtin name is missing or ambiguous");
|
|
@@ -50691,18 +50880,15 @@ function resolveAgentDiscovery(options) {
|
|
|
50691
50880
|
if (retained.agent !== agent || retained.method !== "reviewed")
|
|
50692
50881
|
unresolved("invalid retained review");
|
|
50693
50882
|
verifyAgentDiscovery(retained);
|
|
50694
|
-
if (!retained.sources.some((source) => source.path ===
|
|
50883
|
+
if (!retained.sources.some((source) => source.path === canonical7(configPath) && source.format === undefined && source.fields === undefined))
|
|
50695
50884
|
unresolved("retained review is missing the full agent configuration source");
|
|
50696
|
-
if (retained.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !==
|
|
50885
|
+
if (retained.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical7(configPath)))
|
|
50697
50886
|
unresolved("retained settings witness names another configuration source");
|
|
50698
|
-
const covered = supersedesSettingsProjection(agent, retained.sources,
|
|
50887
|
+
const covered = supersedesSettingsProjection(agent, retained.sources, canonical7(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical7(configPath), source)) : sources;
|
|
50699
50888
|
if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual4(saved, source))) || [...roots].some((root) => !retained.roots.includes(root)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
|
|
50700
50889
|
unresolved("retained review is missing current runtime discovery coverage");
|
|
50701
50890
|
return retained;
|
|
50702
50891
|
}
|
|
50703
|
-
if (options.reviewed && (options.reviewed.version !== 1 || !Array.isArray(options.reviewed.agents) || options.reviewed.agents.some((item) => !item || typeof item !== "object") || new Set(options.reviewed.agents.map((item) => item.agent)).size !== options.reviewed.agents.length))
|
|
50704
|
-
throw new Error("Invalid --discovery-inputs version or agents");
|
|
50705
|
-
const review = options.reviewed?.agents.find((item) => item.agent === agent);
|
|
50706
50892
|
if (review) {
|
|
50707
50893
|
if (review.pluginHooks !== "reviewed-no-skill-injection" || !Array.isArray(review.sources) || !review.sources.length || !Array.isArray(review.roots))
|
|
50708
50894
|
throw new Error("Discovery review must bind sources and confirm plugin hooks do not inject retired skills");
|
|
@@ -50710,47 +50896,77 @@ function resolveAgentDiscovery(options) {
|
|
|
50710
50896
|
if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
|
|
50711
50897
|
throw new Error("Explicit discovery reviews require full source-file hashes");
|
|
50712
50898
|
verifyAgentDiscovery(supplied);
|
|
50713
|
-
if (review.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !==
|
|
50899
|
+
if (review.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical7(configPath)))
|
|
50714
50900
|
throw new Error("Semantic settings witnesses must name the configured agent configuration source");
|
|
50715
|
-
if (!review.sources.some((source) => source.path ===
|
|
50901
|
+
if (!review.sources.some((source) => source.path === canonical7(configPath)))
|
|
50716
50902
|
throw new Error("Discovery review must include the agent configuration source");
|
|
50717
|
-
const reviewedSources = supersedesSettingsProjection(agent, review.sources,
|
|
50718
|
-
|
|
50903
|
+
const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical7(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical7(configPath), source)) : sources;
|
|
50904
|
+
const reviewedSourcesWithManifestProjection = review.sources.map((source) => {
|
|
50905
|
+
if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" || basename8(source.path) !== "plugin.json" || !source.path.endsWith(join26(sep6, ".claude-plugin", "plugin.json")))
|
|
50906
|
+
return source;
|
|
50907
|
+
const pluginRoot = dirname15(dirname15(source.path)), hooksPath = join26(pluginRoot, "hooks/hooks.json");
|
|
50908
|
+
const hookStat = lstatSync18(hooksPath, { throwIfNoEntry: false });
|
|
50909
|
+
const text2 = read(source.path);
|
|
50910
|
+
if (text2 === null)
|
|
50911
|
+
throw new Error("Reviewed Claude plugin manifest is missing");
|
|
50912
|
+
const manifestSha256 = projectReviewedClaudePluginManifest(text2, source.sha256 ?? "");
|
|
50913
|
+
const manifest = JSON.parse(text2);
|
|
50914
|
+
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest))
|
|
50915
|
+
throw new Error("Reviewed Claude plugin manifest must be an object");
|
|
50916
|
+
const reviewedHookPaths = new Set;
|
|
50917
|
+
if (hookStat)
|
|
50918
|
+
reviewedHookPaths.add(hooksPath);
|
|
50919
|
+
if (manifest.hooks !== undefined) {
|
|
50920
|
+
if (typeof manifest.hooks !== "string")
|
|
50921
|
+
throw new Error("Reviewed Claude plugin manifest has an unsupported hooks target");
|
|
50922
|
+
const declaredHookPath = resolve15(pluginRoot, manifest.hooks);
|
|
50923
|
+
if (!declaredHookPath.startsWith(pluginRoot + sep6))
|
|
50924
|
+
throw new Error("Reviewed Claude plugin hooks target escapes its root");
|
|
50925
|
+
reviewedHookPaths.add(declaredHookPath);
|
|
50926
|
+
}
|
|
50927
|
+
for (const hooksFile of reviewedHookPaths)
|
|
50928
|
+
if (!review.sources.some((hook) => hook.path === canonical7(hooksFile) && hook.sha256 !== null && hook.format === undefined && hook.fields === undefined && hook.managedPlugins === undefined && (hook.hashMode === undefined || hook.hashMode === "bytes")))
|
|
50929
|
+
throw new Error("Reviewed Claude plugin manifest requires separately reviewed exact hook file sources");
|
|
50930
|
+
return { path: source.path, sha256: manifestSha256, hashMode: "claude-plugin-manifest-v1" };
|
|
50931
|
+
});
|
|
50932
|
+
const combined = [...reviewedSources, ...reviewedSourcesWithManifestProjection];
|
|
50933
|
+
const unique = combined.filter((source, index) => combined.findIndex((candidate) => isDeepStrictEqual4(candidate, source)) === index);
|
|
50934
|
+
return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
|
|
50719
50935
|
}
|
|
50720
50936
|
function plugin(root) {
|
|
50721
|
-
root =
|
|
50937
|
+
root = canonical7(root);
|
|
50722
50938
|
safe4(root);
|
|
50723
|
-
const manifestPath =
|
|
50724
|
-
const raw = witness(manifestPath);
|
|
50939
|
+
const manifestPath = join26(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
|
|
50940
|
+
const raw = witness(manifestPath, undefined, undefined, agent === "claude" ? "claude-plugin-manifest-v1" : undefined);
|
|
50725
50941
|
if (raw === null)
|
|
50726
50942
|
unresolved("plugin manifest missing");
|
|
50727
50943
|
const manifest = parseConfig(raw, manifestPath);
|
|
50728
|
-
const hooks = witness(
|
|
50944
|
+
const hooks = witness(join26(root, "hooks/hooks.json"));
|
|
50729
50945
|
if (manifest.hooks !== undefined || hooks !== null)
|
|
50730
50946
|
unresolved("plugin hooks require a separate no-skill-injection review");
|
|
50731
|
-
const commands =
|
|
50947
|
+
const commands = join26(root, "commands");
|
|
50732
50948
|
safe4(commands);
|
|
50733
50949
|
if (agent === "claude" && (manifest.commands !== undefined || lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length))
|
|
50734
50950
|
unresolved("legacy command discovery requires retirement or a dedicated format adapter");
|
|
50735
|
-
const rootSkill = witness(
|
|
50951
|
+
const rootSkill = witness(join26(root, "SKILL.md"));
|
|
50736
50952
|
if (rootSkill !== null)
|
|
50737
50953
|
roots.add(root);
|
|
50738
50954
|
const declared = manifest.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
|
|
50739
50955
|
if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
|
|
50740
50956
|
unresolved("unsupported plugin skill paths");
|
|
50741
50957
|
if (agent === "claude")
|
|
50742
|
-
roots.add(
|
|
50958
|
+
roots.add(join26(root, "skills"));
|
|
50743
50959
|
for (const value of declared) {
|
|
50744
50960
|
const path = resolve15(root, value);
|
|
50745
|
-
if (path !== root && !path.startsWith(root +
|
|
50961
|
+
if (path !== root && !path.startsWith(root + sep6))
|
|
50746
50962
|
unresolved("plugin skill path escapes its root");
|
|
50747
|
-
roots.add(path.endsWith(`${
|
|
50963
|
+
roots.add(path.endsWith(`${sep6}SKILL.md`) ? dirname15(path) : path);
|
|
50748
50964
|
}
|
|
50749
50965
|
}
|
|
50750
50966
|
if (agent === "claude") {
|
|
50751
|
-
const registrations = witness(
|
|
50752
|
-
const installed = registrations === null ? {} : parseConfig(registrations,
|
|
50753
|
-
const commands =
|
|
50967
|
+
const registrations = witness(join26(home, ".claude/plugins/installed_plugins.json"));
|
|
50968
|
+
const installed = registrations === null ? {} : parseConfig(registrations, join26(home, ".claude/plugins/installed_plugins.json")).plugins;
|
|
50969
|
+
const commands = canonical7(join26(home, ".claude/commands"));
|
|
50754
50970
|
safe4(commands);
|
|
50755
50971
|
if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
|
|
50756
50972
|
unresolved("legacy home command discovery requires a dedicated format adapter");
|
|
@@ -50774,16 +50990,16 @@ function resolveAgentDiscovery(options) {
|
|
|
50774
50990
|
const market = config2.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
|
|
50775
50991
|
if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute13(market.source))
|
|
50776
50992
|
unresolved("enabled plugin marketplace is not an explicit local source");
|
|
50777
|
-
const catalogText = witness(
|
|
50993
|
+
const catalogText = witness(join26(market.source, ".agents/plugins/marketplace.json"));
|
|
50778
50994
|
if (catalogText === null)
|
|
50779
50995
|
unresolved("marketplace catalog missing");
|
|
50780
|
-
const catalog = parseConfig(catalogText,
|
|
50996
|
+
const catalog = parseConfig(catalogText, join26(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
|
|
50781
50997
|
if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
|
|
50782
50998
|
unresolved("plugin catalog source is missing or ambiguous");
|
|
50783
50999
|
plugin(resolve15(market.source, matches[0].source.path));
|
|
50784
51000
|
}
|
|
50785
51001
|
} else if (agent === "opencode") {
|
|
50786
|
-
if (witness(
|
|
51002
|
+
if (witness(join26(home, ".config/opencode/opencode.jsonc")) !== null || witness(join26(home, ".config/opencode/config.json")) !== null)
|
|
50787
51003
|
unresolved("additional config layers require review");
|
|
50788
51004
|
if ((config2.plugin?.length ?? 0) > 0 || config2.skills?.urls?.length)
|
|
50789
51005
|
unresolved("external plugin or remote skill source");
|
|
@@ -50792,15 +51008,15 @@ function resolveAgentDiscovery(options) {
|
|
|
50792
51008
|
unresolved("relative or malformed added skill root");
|
|
50793
51009
|
roots.add(path);
|
|
50794
51010
|
}
|
|
50795
|
-
const localPlugins =
|
|
51011
|
+
const localPlugins = join26(home, ".config/opencode/plugins");
|
|
50796
51012
|
safe4(localPlugins);
|
|
50797
51013
|
if (lstatSync18(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
|
|
50798
51014
|
unresolved("additional local plugin hooks require review");
|
|
50799
51015
|
} else if (agent === "sumi") {
|
|
50800
|
-
if ((config2.plugin?.length ?? 0) > 0 || (config2.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !==
|
|
51016
|
+
if ((config2.plugin?.length ?? 0) > 0 || (config2.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical7(configPath) && source.path !== canonical7(join26(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
|
|
50801
51017
|
unresolved("external or foreign local plugins require review");
|
|
50802
51018
|
} else if (agent === "hermes") {
|
|
50803
|
-
for (const directory of [
|
|
51019
|
+
for (const directory of [join26(home, ".hermes/plugins"), join26(home, ".hermes/hermes-agent")]) {
|
|
50804
51020
|
safe4(directory);
|
|
50805
51021
|
if (lstatSync18(directory, { throwIfNoEntry: false }))
|
|
50806
51022
|
unresolved("installed runtime/plugin discovery requires reviewed source bindings");
|
|
@@ -50810,26 +51026,26 @@ function resolveAgentDiscovery(options) {
|
|
|
50810
51026
|
} else if (agent === "gemini") {
|
|
50811
51027
|
if (Object.keys(config2.extensions ?? {}).length || config2.skills?.paths?.length)
|
|
50812
51028
|
unresolved("custom extension or skill paths");
|
|
50813
|
-
const directory =
|
|
51029
|
+
const directory = join26(home, ".gemini/extensions");
|
|
50814
51030
|
safe4(directory);
|
|
50815
51031
|
if (lstatSync18(directory, { throwIfNoEntry: false }))
|
|
50816
51032
|
for (const name of readdirSync7(directory)) {
|
|
50817
|
-
const root =
|
|
51033
|
+
const root = join26(directory, name);
|
|
50818
51034
|
safe4(root);
|
|
50819
51035
|
if (!lstatSync18(root)?.isDirectory())
|
|
50820
51036
|
continue;
|
|
50821
|
-
const raw = witness(
|
|
51037
|
+
const raw = witness(join26(root, "gemini-extension.json"));
|
|
50822
51038
|
if (raw === null)
|
|
50823
51039
|
unresolved("extension registration missing");
|
|
50824
|
-
const manifest = parseConfig(raw,
|
|
50825
|
-
if (manifest.hooks !== undefined || witness(
|
|
51040
|
+
const manifest = parseConfig(raw, join26(root, "gemini-extension.json"));
|
|
51041
|
+
if (manifest.hooks !== undefined || witness(join26(root, "hooks/hooks.json")) !== null || witness(join26(root, ".gemini-extension-install.json")) !== null)
|
|
50826
51042
|
unresolved("extension hooks or linked registration require review");
|
|
50827
|
-
roots.add(
|
|
51043
|
+
roots.add(join26(root, "skills"));
|
|
50828
51044
|
}
|
|
50829
51045
|
}
|
|
50830
|
-
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([
|
|
51046
|
+
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join26(home, ".hermes/plugins"), join26(home, ".hermes/hermes-agent")].map((path) => canonical7(path))) } : {} };
|
|
50831
51047
|
}
|
|
50832
|
-
var digest = (text2) =>
|
|
51048
|
+
var digest = (text2) => createHash17("sha256").update(text2).digest("hex");
|
|
50833
51049
|
var init_agent_discovery = __esm(() => {
|
|
50834
51050
|
init_sumi_settings_witness();
|
|
50835
51051
|
init_agent_policy_limits();
|
|
@@ -50837,6 +51053,7 @@ var init_agent_discovery = __esm(() => {
|
|
|
50837
51053
|
init_agent_discovery_directories();
|
|
50838
51054
|
init_agent_discovery_bytes();
|
|
50839
51055
|
init_agent_discovery_path_bytes();
|
|
51056
|
+
init_claude_plugin_manifest_witness();
|
|
50840
51057
|
init_plugin_discovery();
|
|
50841
51058
|
init_plugin_admission();
|
|
50842
51059
|
init_claude_marketplace_registry();
|
|
@@ -50852,9 +51069,9 @@ var init_agent_discovery = __esm(() => {
|
|
|
50852
51069
|
// src/lib/authoring-path.ts
|
|
50853
51070
|
import { lstatSync as lstatSync19, realpathSync as realpathSync6 } from "fs";
|
|
50854
51071
|
import { homedir as homedir3 } from "os";
|
|
50855
|
-
import { basename as basename9, dirname as dirname16, join as
|
|
51072
|
+
import { basename as basename9, dirname as dirname16, join as join27, resolve as resolve16, sep as sep7 } from "path";
|
|
50856
51073
|
function pathParts(path) {
|
|
50857
|
-
return resolve16(path).split(
|
|
51074
|
+
return resolve16(path).split(sep7).filter(Boolean);
|
|
50858
51075
|
}
|
|
50859
51076
|
function nativeRootMatch(path) {
|
|
50860
51077
|
const parts = pathParts(path);
|
|
@@ -50880,10 +51097,10 @@ function physicalPath(path) {
|
|
|
50880
51097
|
return resolve16(realpathSync6(cursor), ...suffix);
|
|
50881
51098
|
}
|
|
50882
51099
|
function contains(root, path) {
|
|
50883
|
-
return path === root || path.startsWith(root +
|
|
51100
|
+
return path === root || path.startsWith(root + sep7);
|
|
50884
51101
|
}
|
|
50885
51102
|
function configuredRoots(home, explicitHome) {
|
|
50886
|
-
const homeData =
|
|
51103
|
+
const homeData = join27(home, ".hasna", "skills");
|
|
50887
51104
|
const homePolicy = readManagedSkillPolicySnapshot(homeData);
|
|
50888
51105
|
const configuredPolicy = !explicitHome && resolve16(getDataDirReadOnly()) !== resolve16(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
|
|
50889
51106
|
const policy = homePolicy ?? configuredPolicy;
|
|
@@ -50914,7 +51131,7 @@ function configuredRoots(home, explicitHome) {
|
|
|
50914
51131
|
admitBinding(binding);
|
|
50915
51132
|
continue;
|
|
50916
51133
|
}
|
|
50917
|
-
const nativeHome =
|
|
51134
|
+
const nativeHome = join27(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
|
|
50918
51135
|
if (!lstatSync19(nativeHome, { throwIfNoEntry: false }))
|
|
50919
51136
|
continue;
|
|
50920
51137
|
roots.push(...resolveAgentDiscovery({ home, agent, canonical: physicalPath }).roots);
|
|
@@ -50929,8 +51146,8 @@ function assertPortableAuthoringPath(path, options = {}) {
|
|
|
50929
51146
|
const candidates = [lexical, physical];
|
|
50930
51147
|
let native = candidates.map(nativeRootMatch).find(Boolean);
|
|
50931
51148
|
const home = resolve16(options.homeDir ?? homedir3());
|
|
50932
|
-
const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) =>
|
|
50933
|
-
defaults.push(
|
|
51149
|
+
const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join27(home, ...parts));
|
|
51150
|
+
defaults.push(join27(home, ".codex/plugins/cache"), join27(home, ".claude/plugins/cache"), join27(home, ".claude/plugins/synced"), join27(home, ".gemini/extensions"));
|
|
50934
51151
|
for (const root of defaults) {
|
|
50935
51152
|
if (candidates.some((candidate) => contains(resolve16(root), candidate) || contains(physicalPath(root), candidate)))
|
|
50936
51153
|
native ??= root;
|
|
@@ -50966,22 +51183,22 @@ import {
|
|
|
50966
51183
|
statSync as statSync7,
|
|
50967
51184
|
writeFileSync as writeFileSync6
|
|
50968
51185
|
} from "fs";
|
|
50969
|
-
import { basename as basename10, dirname as dirname17, isAbsolute as isAbsolute14, join as
|
|
51186
|
+
import { basename as basename10, dirname as dirname17, isAbsolute as isAbsolute14, join as join28, normalize as normalize3, relative as relative5, resolve as resolve17, sep as sep8 } from "path";
|
|
50970
51187
|
function getPortableSkillsRoot(options = {}) {
|
|
50971
51188
|
return resolvePortableSkillsRoot(options, true);
|
|
50972
51189
|
}
|
|
50973
51190
|
function resolvePortableSkillsRoot(options, migrate) {
|
|
50974
51191
|
if (options.rootDir)
|
|
50975
51192
|
return options.rootDir;
|
|
50976
|
-
const appDir = options.homeDir ?
|
|
50977
|
-
const cache =
|
|
51193
|
+
const appDir = options.homeDir ? join28(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
|
|
51194
|
+
const cache = join28(appDir, SKILLS_CACHE_DIRNAME);
|
|
50978
51195
|
if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache))
|
|
50979
51196
|
return cache;
|
|
50980
|
-
const installed =
|
|
51197
|
+
const installed = join28(appDir, INSTALLED_SKILLS_DIRNAME);
|
|
50981
51198
|
return installed;
|
|
50982
51199
|
}
|
|
50983
51200
|
function getPortableSkillPath(name, options = {}) {
|
|
50984
|
-
return
|
|
51201
|
+
return join28(getPortableSkillsRoot(options), normalizePortableSkillName(name));
|
|
50985
51202
|
}
|
|
50986
51203
|
function findPortableSkill(name, options = {}) {
|
|
50987
51204
|
let normalized;
|
|
@@ -51007,7 +51224,7 @@ function listPortableSkills(options = {}) {
|
|
|
51007
51224
|
for (const entry of readdirSync8(root).sort()) {
|
|
51008
51225
|
if (entry.startsWith("."))
|
|
51009
51226
|
continue;
|
|
51010
|
-
const path =
|
|
51227
|
+
const path = join28(root, entry);
|
|
51011
51228
|
if (!safeIsDirectory(path))
|
|
51012
51229
|
continue;
|
|
51013
51230
|
try {
|
|
@@ -51040,9 +51257,9 @@ function isOfficialSkillName(name) {
|
|
|
51040
51257
|
function scaffoldPortableSkill(name, options = {}) {
|
|
51041
51258
|
const skillName = normalizeNewPortableSkillName(name);
|
|
51042
51259
|
const readOnlyRoot = resolvePortableSkillsRoot(options, false);
|
|
51043
|
-
assertPortableAuthoringPath(
|
|
51260
|
+
assertPortableAuthoringPath(join28(readOnlyRoot, skillName), options);
|
|
51044
51261
|
const root = getPortableSkillsRoot(options);
|
|
51045
|
-
const skillPath =
|
|
51262
|
+
const skillPath = join28(root, skillName);
|
|
51046
51263
|
assertPortableAuthoringPath(skillPath, options);
|
|
51047
51264
|
if (existsSync12(skillPath)) {
|
|
51048
51265
|
if (!options.overwrite)
|
|
@@ -51067,14 +51284,14 @@ function physicalImportPath(path) {
|
|
|
51067
51284
|
suffix.unshift(basename10(ancestor));
|
|
51068
51285
|
ancestor = dirname17(ancestor);
|
|
51069
51286
|
}
|
|
51070
|
-
return
|
|
51287
|
+
return join28(realpathSync7(ancestor), ...suffix);
|
|
51071
51288
|
}
|
|
51072
51289
|
function assertDisjointImportPaths(source, destination) {
|
|
51073
51290
|
const sourcePath = realpathSync7(source);
|
|
51074
51291
|
const destinationPath = physicalImportPath(destination);
|
|
51075
51292
|
const contains2 = (parent, child) => {
|
|
51076
51293
|
const path = relative5(parent, child);
|
|
51077
|
-
return path === "" || !isAbsolute14(path) && path !== ".." && !path.startsWith(`..${
|
|
51294
|
+
return path === "" || !isAbsolute14(path) && path !== ".." && !path.startsWith(`..${sep8}`);
|
|
51078
51295
|
};
|
|
51079
51296
|
if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
|
|
51080
51297
|
throw new Error("Source and destination skill directories must not overlap");
|
|
@@ -51093,11 +51310,11 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
51093
51310
|
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename10(absoluteSource)}')` : ""} matches a bundled official skill.`;
|
|
51094
51311
|
throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
|
|
51095
51312
|
}
|
|
51096
|
-
const readOnlyDestination =
|
|
51313
|
+
const readOnlyDestination = join28(resolvePortableSkillsRoot(options, false), skillName);
|
|
51097
51314
|
assertPortableAuthoringPath(readOnlyDestination, options);
|
|
51098
51315
|
assertDisjointImportPaths(absoluteSource, readOnlyDestination);
|
|
51099
51316
|
const root = getPortableSkillsRoot(options);
|
|
51100
|
-
const destination =
|
|
51317
|
+
const destination = join28(root, skillName);
|
|
51101
51318
|
assertPortableAuthoringPath(destination, options);
|
|
51102
51319
|
assertDisjointImportPaths(absoluteSource, destination);
|
|
51103
51320
|
if (existsSync12(destination)) {
|
|
@@ -51129,8 +51346,8 @@ function validatePortableSkillDirectory(name, skillPath) {
|
|
|
51129
51346
|
const warnings = [...base.warnings];
|
|
51130
51347
|
let manifest;
|
|
51131
51348
|
if (existsSync12(skillPath)) {
|
|
51132
|
-
const skillJsonPath =
|
|
51133
|
-
const skillMdPath =
|
|
51349
|
+
const skillJsonPath = join28(skillPath, "skill.json");
|
|
51350
|
+
const skillMdPath = join28(skillPath, "SKILL.md");
|
|
51134
51351
|
if (!existsSync12(skillJsonPath) && !existsSync12(skillMdPath)) {
|
|
51135
51352
|
add3(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
|
|
51136
51353
|
}
|
|
@@ -51150,7 +51367,7 @@ function validatePortableSkillDirectory(name, skillPath) {
|
|
|
51150
51367
|
add3(issues, "portable.version_missing", "Portable manifest missing version");
|
|
51151
51368
|
}
|
|
51152
51369
|
const contractIssues = validatePortableManifestContract(manifest, {
|
|
51153
|
-
strict: existsSync12(
|
|
51370
|
+
strict: existsSync12(join28(skillPath, "skill.json")),
|
|
51154
51371
|
skillPath
|
|
51155
51372
|
});
|
|
51156
51373
|
for (const issue2 of contractIssues)
|
|
@@ -51190,7 +51407,7 @@ function validatePortableSkillDirectory(name, skillPath) {
|
|
|
51190
51407
|
add3(issues, "portable.command_entry_unsafe", `Command '${command.name}' entry '${command.entry}' must stay inside the skill directory`);
|
|
51191
51408
|
continue;
|
|
51192
51409
|
}
|
|
51193
|
-
const entryPath =
|
|
51410
|
+
const entryPath = join28(skillPath, command.entry);
|
|
51194
51411
|
if (!existsSync12(entryPath))
|
|
51195
51412
|
add3(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
|
|
51196
51413
|
else if (statSync7(entryPath).isDirectory())
|
|
@@ -51201,7 +51418,7 @@ function validatePortableSkillDirectory(name, skillPath) {
|
|
|
51201
51418
|
} catch (error61) {
|
|
51202
51419
|
add3(issues, "portable.manifest_invalid", error61.message);
|
|
51203
51420
|
}
|
|
51204
|
-
if (manifest?.kind !== "instruction" && !existsSync12(
|
|
51421
|
+
if (manifest?.kind !== "instruction" && !existsSync12(join28(skillPath, "AGENTS.md"))) {
|
|
51205
51422
|
add3(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
|
|
51206
51423
|
}
|
|
51207
51424
|
}
|
|
@@ -51429,7 +51646,7 @@ var init_search = __esm(() => {
|
|
|
51429
51646
|
|
|
51430
51647
|
// src/lib/registry.ts
|
|
51431
51648
|
import { existsSync as existsSync13, readFileSync as readFileSync16, readdirSync as readdirSync9 } from "fs";
|
|
51432
|
-
import { join as
|
|
51649
|
+
import { join as join29 } from "path";
|
|
51433
51650
|
function parseSkillMdFrontmatter(content) {
|
|
51434
51651
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
51435
51652
|
if (!match)
|
|
@@ -51470,7 +51687,7 @@ function discoverSkillsInDir(dir, source = "custom") {
|
|
|
51470
51687
|
for (const entry of entries) {
|
|
51471
51688
|
if (!entry.isDirectory())
|
|
51472
51689
|
continue;
|
|
51473
|
-
const skillMdPath =
|
|
51690
|
+
const skillMdPath = join29(dir, entry.name, "SKILL.md");
|
|
51474
51691
|
if (!existsSync13(skillMdPath))
|
|
51475
51692
|
continue;
|
|
51476
51693
|
let content;
|
|
@@ -51490,7 +51707,7 @@ function discoverSkillsInDir(dir, source = "custom") {
|
|
|
51490
51707
|
category: fm.category || "Development Tools",
|
|
51491
51708
|
tags: fm.tags || [],
|
|
51492
51709
|
...fm.kind ? { kind: fm.kind } : {},
|
|
51493
|
-
...isHostedMetadataSkillDir(
|
|
51710
|
+
...isHostedMetadataSkillDir(join29(dir, entry.name)) ? { serverOwned: true } : {},
|
|
51494
51711
|
source
|
|
51495
51712
|
});
|
|
51496
51713
|
}
|
|
@@ -51506,8 +51723,8 @@ function findExtensionSkillPath(name) {
|
|
|
51506
51723
|
for (const entry of entries) {
|
|
51507
51724
|
if (!entry.isDirectory())
|
|
51508
51725
|
continue;
|
|
51509
|
-
const skillDir =
|
|
51510
|
-
const skillMdPath =
|
|
51726
|
+
const skillDir = join29(config2.extensionsDir, entry.name);
|
|
51727
|
+
const skillMdPath = join29(skillDir, "SKILL.md");
|
|
51511
51728
|
if (!existsSync13(skillMdPath))
|
|
51512
51729
|
continue;
|
|
51513
51730
|
let content;
|
|
@@ -51910,7 +52127,7 @@ var init_remote_customer_operations = __esm(() => {
|
|
|
51910
52127
|
});
|
|
51911
52128
|
|
|
51912
52129
|
// src/lib/canonical-json.ts
|
|
51913
|
-
import { createHash as
|
|
52130
|
+
import { createHash as createHash18 } from "crypto";
|
|
51914
52131
|
function canonicalJson2(value, maximumBytes = 2 * 1024 * 1024) {
|
|
51915
52132
|
return canonicalJsonAtDepth(value, maximumBytes, 64);
|
|
51916
52133
|
}
|
|
@@ -51954,7 +52171,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
|
|
|
51954
52171
|
return visit3(value, 0);
|
|
51955
52172
|
}
|
|
51956
52173
|
function canonicalJsonSha256(value, maximumBytes) {
|
|
51957
|
-
return
|
|
52174
|
+
return createHash18("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
|
|
51958
52175
|
}
|
|
51959
52176
|
var init_canonical_json = () => {};
|
|
51960
52177
|
|
|
@@ -52705,13 +52922,13 @@ var init_remote_workspace_leave = __esm(() => {
|
|
|
52705
52922
|
|
|
52706
52923
|
// src/lib/auth-store.ts
|
|
52707
52924
|
import { chmodSync, existsSync as existsSync14, mkdirSync as mkdirSync8, readFileSync as readFileSync17, renameSync as renameSync4, statSync as statSync8, unlinkSync as unlinkSync4, writeFileSync as writeFileSync7 } from "fs";
|
|
52708
|
-
import { basename as basename11, dirname as dirname18, join as
|
|
52925
|
+
import { basename as basename11, dirname as dirname18, join as join30 } from "path";
|
|
52709
52926
|
function getAuthFilePath(env = process.env) {
|
|
52710
52927
|
return skillsCredentialFilePath(env);
|
|
52711
52928
|
}
|
|
52712
52929
|
function getIdentityFilePath(env = process.env) {
|
|
52713
52930
|
const file2 = skillsCredentialFilePath(env);
|
|
52714
|
-
return
|
|
52931
|
+
return join30(dirname18(file2), basename11(file2).replace(/^credentials/, "identity") + ".json");
|
|
52715
52932
|
}
|
|
52716
52933
|
function getApiUrl(action, env = process.env, options = {}) {
|
|
52717
52934
|
return requireSkillsApiOrigin(action, env, options);
|
|
@@ -54180,7 +54397,7 @@ var init_remote_invitation_recovery = __esm(() => {
|
|
|
54180
54397
|
});
|
|
54181
54398
|
|
|
54182
54399
|
// src/lib/remote-private-publications.ts
|
|
54183
|
-
import { createHash as
|
|
54400
|
+
import { createHash as createHash19 } from "crypto";
|
|
54184
54401
|
function checkedPublicationDeclaration(value) {
|
|
54185
54402
|
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)
|
|
54186
54403
|
return bad();
|
|
@@ -54441,7 +54658,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures2, PrivatePublicationError, bad = ()
|
|
|
54441
54658
|
throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
|
|
54442
54659
|
}, invalid4 = () => {
|
|
54443
54660
|
throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
|
|
54444
|
-
}, 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, keys) => record10(v) && Object.keys(v).sort().join(",") === keys.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) =>
|
|
54661
|
+
}, 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, keys) => record10(v) && Object.keys(v).sort().join(",") === keys.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) => createHash19("sha256").update(bytes).digest("hex");
|
|
54445
54662
|
var init_remote_private_publications = __esm(() => {
|
|
54446
54663
|
init_fleet_credentials();
|
|
54447
54664
|
init_remote_workspace_selection();
|
|
@@ -54951,7 +55168,7 @@ var init_recurring_customer = __esm(() => {
|
|
|
54951
55168
|
|
|
54952
55169
|
// src/lib/recurring-recovery.ts
|
|
54953
55170
|
import { constants as constants12, closeSync as closeSync15, fsyncSync as fsyncSync4, fstatSync as fstatSync15, lstatSync as lstatSync21, mkdirSync as mkdirSync10, openSync as openSync15, readSync as readSync10, realpathSync as realpathSync8, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
|
|
54954
|
-
import { dirname as dirname19, isAbsolute as isAbsolute15, join as
|
|
55171
|
+
import { dirname as dirname19, isAbsolute as isAbsolute15, join as join31, resolve as resolve18 } from "path";
|
|
54955
55172
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
54956
55173
|
|
|
54957
55174
|
class RecoveryOwner {
|
|
@@ -54985,7 +55202,7 @@ class RecoveryOwner {
|
|
|
54985
55202
|
}
|
|
54986
55203
|
read(name) {
|
|
54987
55204
|
this.assert();
|
|
54988
|
-
const fd = openSync15(
|
|
55205
|
+
const fd = openSync15(join31(this.directory, name), constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
|
|
54989
55206
|
try {
|
|
54990
55207
|
const before = fstatSync15(fd);
|
|
54991
55208
|
if (!before.isFile() || before.nlink !== 1 || (before.mode & 4095) !== 384 || before.size < 1 || before.size > 8192 || process.getuid && before.uid !== process.getuid())
|
|
@@ -54998,7 +55215,7 @@ class RecoveryOwner {
|
|
|
54998
55215
|
break;
|
|
54999
55216
|
size += n2;
|
|
55000
55217
|
}
|
|
55001
|
-
const after = fstatSync15(fd), path = lstatSync21(
|
|
55218
|
+
const after = fstatSync15(fd), path = lstatSync21(join31(this.directory, name));
|
|
55002
55219
|
if (size !== before.size || after.size !== before.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs || path.dev !== before.dev || path.ino !== before.ino || !path.isFile() || path.isSymbolicLink())
|
|
55003
55220
|
invalid5();
|
|
55004
55221
|
this.assert();
|
|
@@ -55011,7 +55228,7 @@ class RecoveryOwner {
|
|
|
55011
55228
|
this.assert();
|
|
55012
55229
|
const bytes = canonicalJson2(value, 8192) + `
|
|
55013
55230
|
`;
|
|
55014
|
-
const fd = openSync15(
|
|
55231
|
+
const fd = openSync15(join31(this.directory, name), constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW, 384);
|
|
55015
55232
|
try {
|
|
55016
55233
|
writeFileSync9(fd, bytes);
|
|
55017
55234
|
fsyncSync4(fd);
|
|
@@ -55038,14 +55255,14 @@ class RecoveryOwner {
|
|
|
55038
55255
|
if (this.read("state.json") !== expected)
|
|
55039
55256
|
invalid5();
|
|
55040
55257
|
this.assert();
|
|
55041
|
-
renameSync6(
|
|
55258
|
+
renameSync6(join31(this.directory, name), join31(this.directory, "state.json"));
|
|
55042
55259
|
this.sync();
|
|
55043
55260
|
}
|
|
55044
55261
|
async locked(action) {
|
|
55045
55262
|
this.assert();
|
|
55046
55263
|
let fd;
|
|
55047
55264
|
try {
|
|
55048
|
-
fd = openSync15(
|
|
55265
|
+
fd = openSync15(join31(this.directory, "operation.lock"), constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW, 384);
|
|
55049
55266
|
} catch {
|
|
55050
55267
|
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.");
|
|
55051
55268
|
}
|
|
@@ -55058,10 +55275,10 @@ class RecoveryOwner {
|
|
|
55058
55275
|
} finally {
|
|
55059
55276
|
closeSync15(fd);
|
|
55060
55277
|
this.assert();
|
|
55061
|
-
const now = lstatSync21(
|
|
55278
|
+
const now = lstatSync21(join31(this.directory, "operation.lock"));
|
|
55062
55279
|
if (owner2.dev !== now.dev || owner2.ino !== now.ino || !now.isFile() || now.isSymbolicLink())
|
|
55063
55280
|
invalid5();
|
|
55064
|
-
unlinkSync5(
|
|
55281
|
+
unlinkSync5(join31(this.directory, "operation.lock"));
|
|
55065
55282
|
this.sync();
|
|
55066
55283
|
}
|
|
55067
55284
|
}
|
|
@@ -57191,21 +57408,21 @@ var init_credential_state = __esm(() => {
|
|
|
57191
57408
|
});
|
|
57192
57409
|
|
|
57193
57410
|
// src/lib/run-state.ts
|
|
57194
|
-
import { createHash as
|
|
57411
|
+
import { createHash as createHash20, randomBytes } from "crypto";
|
|
57195
57412
|
import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync19, readdirSync as readdirSync10, statSync as statSync9, writeFileSync as writeFileSync10 } from "fs";
|
|
57196
|
-
import { extname, join as
|
|
57413
|
+
import { extname, join as join32, relative as relative6 } from "path";
|
|
57197
57414
|
function createSkillRun(params, targetDir = process.cwd()) {
|
|
57198
57415
|
const now = new Date;
|
|
57199
57416
|
const id = createRunId(now);
|
|
57200
57417
|
const day = now.toISOString().slice(0, 10);
|
|
57201
57418
|
const skillName = normalizeSkillName(params.skill);
|
|
57202
57419
|
const root = getProjectStateDir(targetDir);
|
|
57203
|
-
const runDir =
|
|
57204
|
-
const logsDir =
|
|
57205
|
-
const exportDir =
|
|
57420
|
+
const runDir = join32(root, "runs", day, id);
|
|
57421
|
+
const logsDir = join32(runDir, "logs");
|
|
57422
|
+
const exportDir = join32(root, "exports", skillName, id);
|
|
57206
57423
|
mkdirSync11(logsDir, { recursive: true });
|
|
57207
57424
|
mkdirSync11(exportDir, { recursive: true });
|
|
57208
|
-
mkdirSync11(
|
|
57425
|
+
mkdirSync11(join32(root, "tmp"), { recursive: true });
|
|
57209
57426
|
const record11 = {
|
|
57210
57427
|
id,
|
|
57211
57428
|
skill: skillName,
|
|
@@ -57257,22 +57474,22 @@ function updateSkillRun(context2, patch) {
|
|
|
57257
57474
|
return context2.record;
|
|
57258
57475
|
}
|
|
57259
57476
|
function writeRunLogs(context2, stdout = "", stderr = "") {
|
|
57260
|
-
writeFileSync10(
|
|
57261
|
-
writeFileSync10(
|
|
57477
|
+
writeFileSync10(join32(context2.logsDir, "stdout.log"), stdout);
|
|
57478
|
+
writeFileSync10(join32(context2.logsDir, "stderr.log"), stderr);
|
|
57262
57479
|
}
|
|
57263
57480
|
function appendRunEvent(context2, event, data = {}) {
|
|
57264
57481
|
const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
|
|
57265
57482
|
`;
|
|
57266
|
-
const path =
|
|
57483
|
+
const path = join32(context2.runDir, "events.ndjson");
|
|
57267
57484
|
const previous = existsSync15(path) ? readFileSync19(path, "utf-8") : "";
|
|
57268
57485
|
writeFileSync10(path, previous + line);
|
|
57269
57486
|
}
|
|
57270
57487
|
function findSkillRun(runId, targetDir = process.cwd()) {
|
|
57271
|
-
const runsRoot =
|
|
57488
|
+
const runsRoot = join32(getProjectStateDir(targetDir), "runs");
|
|
57272
57489
|
if (!existsSync15(runsRoot))
|
|
57273
57490
|
return null;
|
|
57274
57491
|
for (const day of readdirSync10(runsRoot)) {
|
|
57275
|
-
const record11 = readRunRecord(
|
|
57492
|
+
const record11 = readRunRecord(join32(runsRoot, day, runId));
|
|
57276
57493
|
if (record11)
|
|
57277
57494
|
return record11;
|
|
57278
57495
|
}
|
|
@@ -57289,11 +57506,11 @@ function skillRunEnv(context2) {
|
|
|
57289
57506
|
};
|
|
57290
57507
|
}
|
|
57291
57508
|
function writeRunRecord(context2) {
|
|
57292
|
-
writeFileSync10(
|
|
57509
|
+
writeFileSync10(join32(context2.runDir, "run.json"), JSON.stringify(context2.record, null, 2) + `
|
|
57293
57510
|
`);
|
|
57294
57511
|
}
|
|
57295
57512
|
function writeArtifactsManifest(context2, artifacts) {
|
|
57296
|
-
writeFileSync10(
|
|
57513
|
+
writeFileSync10(join32(context2.runDir, "artifacts.json"), JSON.stringify({ runId: context2.record.id, artifacts }, null, 2) + `
|
|
57297
57514
|
`);
|
|
57298
57515
|
}
|
|
57299
57516
|
function collectRunArtifacts(context2) {
|
|
@@ -57306,14 +57523,14 @@ function collectRunArtifacts(context2) {
|
|
|
57306
57523
|
artifacts.push({
|
|
57307
57524
|
path: toProjectRelative(context2.targetDir, path),
|
|
57308
57525
|
mime: mimeForPath(path),
|
|
57309
|
-
sha256:
|
|
57526
|
+
sha256: createHash20("sha256").update(bytes).digest("hex"),
|
|
57310
57527
|
sizeBytes: stat3.size
|
|
57311
57528
|
});
|
|
57312
57529
|
}
|
|
57313
57530
|
return artifacts.sort((a, b) => a.path.localeCompare(b.path));
|
|
57314
57531
|
}
|
|
57315
57532
|
function readRunRecord(runDir) {
|
|
57316
|
-
const path =
|
|
57533
|
+
const path = join32(runDir, "run.json");
|
|
57317
57534
|
if (!existsSync15(path))
|
|
57318
57535
|
return null;
|
|
57319
57536
|
try {
|
|
@@ -57325,7 +57542,7 @@ function readRunRecord(runDir) {
|
|
|
57325
57542
|
function walkFiles(dir) {
|
|
57326
57543
|
const files = [];
|
|
57327
57544
|
for (const entry of readdirSync10(dir)) {
|
|
57328
|
-
const full =
|
|
57545
|
+
const full = join32(dir, entry);
|
|
57329
57546
|
if (statSync9(full).isDirectory())
|
|
57330
57547
|
files.push(...walkFiles(full));
|
|
57331
57548
|
else
|
|
@@ -57582,7 +57799,7 @@ import { closeSync as closeSync16, fstatSync as fstatSync16, openSync as openSyn
|
|
|
57582
57799
|
import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
|
|
57583
57800
|
import { createRequire as createRequire2 } from "module";
|
|
57584
57801
|
import { hostname as osHostname2 } from "os";
|
|
57585
|
-
import { isAbsolute as isAbsolute17, join as
|
|
57802
|
+
import { isAbsolute as isAbsolute17, join as join33 } from "path";
|
|
57586
57803
|
import { createRequire as createRequire22 } from "module";
|
|
57587
57804
|
function envToken2(name) {
|
|
57588
57805
|
return name.toUpperCase().replace(/-/g, "_");
|
|
@@ -57613,14 +57830,14 @@ function hasnaHomeDir2(env) {
|
|
|
57613
57830
|
if (override)
|
|
57614
57831
|
return override;
|
|
57615
57832
|
const home = homeDir2(env);
|
|
57616
|
-
return home ?
|
|
57833
|
+
return home ? join33(home, HASNA_HOME_DIR2) : null;
|
|
57617
57834
|
}
|
|
57618
57835
|
function appConfigDir2(name, env) {
|
|
57619
57836
|
const configRoot = absoluteOverride2(env, HASNA_CONFIG_HOME_ENV_KEY2);
|
|
57620
57837
|
if (configRoot)
|
|
57621
|
-
return
|
|
57838
|
+
return join33(configRoot, name);
|
|
57622
57839
|
const root = hasnaHomeDir2(env);
|
|
57623
|
-
return root ?
|
|
57840
|
+
return root ? join33(root, name, CONFIG_SUBDIR2) : null;
|
|
57624
57841
|
}
|
|
57625
57842
|
function credentialDiskSourceList2(name, env, profile = null) {
|
|
57626
57843
|
if (!SAFE_APP_SLUG2.test(name))
|
|
@@ -57629,7 +57846,7 @@ function credentialDiskSourceList2(name, env, profile = null) {
|
|
|
57629
57846
|
if (!directory2)
|
|
57630
57847
|
return [];
|
|
57631
57848
|
const file2 = profile ? `${CREDENTIALS_FILE2}-${profile}` : CREDENTIALS_FILE2;
|
|
57632
|
-
return [{ path:
|
|
57849
|
+
return [{ path: join33(directory2, file2), tier: "disk" }];
|
|
57633
57850
|
}
|
|
57634
57851
|
function credentialDiskSources2(name, env) {
|
|
57635
57852
|
return credentialDiskSourceList2(name, env, null).map((s) => s.path);
|
|
@@ -59120,10 +59337,10 @@ __export(exports_selected_run, {
|
|
|
59120
59337
|
prepareSelectedSecretBindings: () => prepareSelectedSecretBindings,
|
|
59121
59338
|
executeSelectedLocal: () => executeSelectedLocal
|
|
59122
59339
|
});
|
|
59123
|
-
import { createHash as
|
|
59340
|
+
import { createHash as createHash21 } from "crypto";
|
|
59124
59341
|
import { spawn } from "child_process";
|
|
59125
59342
|
import { mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync11, realpathSync as realpathSync10 } from "fs";
|
|
59126
|
-
import { dirname as dirname20, join as
|
|
59343
|
+
import { dirname as dirname20, join as join34, resolve as resolve19 } from "path";
|
|
59127
59344
|
import { tmpdir, hostname as stationHostname2 } from "os";
|
|
59128
59345
|
async function resolveSelectedRun(spec, profileId, options = {}) {
|
|
59129
59346
|
const context2 = await resolveSelectionContext(profileId, options);
|
|
@@ -59203,7 +59420,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
59203
59420
|
throw new SkillSelectionError("INVALID_SECRET_BINDINGS", "Explicit environment values must be bounded strings without NUL bytes.");
|
|
59204
59421
|
secretEnv[name] = value;
|
|
59205
59422
|
}
|
|
59206
|
-
const runDirectory = mkdtempSync3(
|
|
59423
|
+
const runDirectory = mkdtempSync3(join34(tmpdir(), "skills-execution-"));
|
|
59207
59424
|
const paths = new SkillEntryPaths;
|
|
59208
59425
|
for (const entry of entries) {
|
|
59209
59426
|
paths.add(entry.path, 100, () => {
|
|
@@ -59211,7 +59428,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
59211
59428
|
}, () => {
|
|
59212
59429
|
throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
|
|
59213
59430
|
});
|
|
59214
|
-
const destination =
|
|
59431
|
+
const destination = join34(runDirectory, entry.path);
|
|
59215
59432
|
mkdirSync12(dirname20(destination), { recursive: true, mode: 448 });
|
|
59216
59433
|
writeFileSync11(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
|
|
59217
59434
|
}
|
|
@@ -59239,20 +59456,20 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
59239
59456
|
}
|
|
59240
59457
|
if (bindings)
|
|
59241
59458
|
secretEnv = await resolveSelectedSecrets(bindings, options.createSecretsClient);
|
|
59242
|
-
const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [],
|
|
59459
|
+
const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], join34(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input2, timeoutMs);
|
|
59243
59460
|
result.stdout = redactExecutionSecrets(result.stdout, secretEnv);
|
|
59244
59461
|
result.stderr = redactExecutionSecrets(result.stderr, secretEnv);
|
|
59245
59462
|
const receipt = {
|
|
59246
59463
|
selection: selection2,
|
|
59247
59464
|
target: "local",
|
|
59248
59465
|
runtime: runtimeName,
|
|
59249
|
-
inputDigest: `sha256:${
|
|
59466
|
+
inputDigest: `sha256:${createHash21("sha256").update(input2).digest("hex")}`,
|
|
59250
59467
|
runDirectory,
|
|
59251
59468
|
...executionGrant ? { executionGrant } : {},
|
|
59252
59469
|
...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
|
|
59253
59470
|
...result
|
|
59254
59471
|
};
|
|
59255
|
-
writeFileSync11(
|
|
59472
|
+
writeFileSync11(join34(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
|
|
59256
59473
|
return receipt;
|
|
59257
59474
|
}
|
|
59258
59475
|
async function subprocess(command, cwd, env, input2, timeoutMs) {
|
|
@@ -59442,7 +59659,7 @@ var init_blog_article = __esm(() => {
|
|
|
59442
59659
|
|
|
59443
59660
|
// src/mcp/operation-tools.ts
|
|
59444
59661
|
import { existsSync as existsSync16, readdirSync as readdirSync11, statSync as statSync10 } from "fs";
|
|
59445
|
-
import { join as
|
|
59662
|
+
import { join as join35 } from "path";
|
|
59446
59663
|
function registerOperationTools(server) {
|
|
59447
59664
|
server.registerTool("cloud_skill_eligibility", {
|
|
59448
59665
|
title: "Cloud Skill Eligibility",
|
|
@@ -59919,7 +60136,7 @@ function registerOperationTools(server) {
|
|
|
59919
60136
|
if (exists) {
|
|
59920
60137
|
try {
|
|
59921
60138
|
skillCount = readdirSync11(agentSkillsPath).filter((f) => {
|
|
59922
|
-
const full =
|
|
60139
|
+
const full = join35(agentSkillsPath, f);
|
|
59923
60140
|
return !f.startsWith(".") && statSync10(full).isDirectory();
|
|
59924
60141
|
}).length;
|
|
59925
60142
|
} catch {}
|
|
@@ -59987,10 +60204,10 @@ var init_operation_tools = __esm(() => {
|
|
|
59987
60204
|
|
|
59988
60205
|
// src/lib/feedback.ts
|
|
59989
60206
|
import { appendFileSync, existsSync as existsSync17, mkdirSync as mkdirSync13 } from "fs";
|
|
59990
|
-
import { dirname as dirname21, join as
|
|
60207
|
+
import { dirname as dirname21, join as join36 } from "path";
|
|
59991
60208
|
import { Database } from "bun:sqlite";
|
|
59992
60209
|
function getFeedbackDbPath() {
|
|
59993
|
-
return
|
|
60210
|
+
return join36(getDataDir(), "skills.db");
|
|
59994
60211
|
}
|
|
59995
60212
|
function getFeedbackDb() {
|
|
59996
60213
|
const dbPath = getFeedbackDbPath();
|
|
@@ -60022,7 +60239,7 @@ function saveFeedback(input2) {
|
|
|
60022
60239
|
throw new Error("Feedback message is required");
|
|
60023
60240
|
const category = input2.category ?? "general";
|
|
60024
60241
|
if (isApiMode()) {
|
|
60025
|
-
const path =
|
|
60242
|
+
const path = join36(getDataDir(), "feedback.jsonl");
|
|
60026
60243
|
const dir = dirname21(path);
|
|
60027
60244
|
if (!existsSync17(dir))
|
|
60028
60245
|
mkdirSync13(dir, { recursive: true });
|
|
@@ -60187,9 +60404,9 @@ var init_resource_meta_tools = __esm(() => {
|
|
|
60187
60404
|
|
|
60188
60405
|
// src/lib/scheduler.ts
|
|
60189
60406
|
import { existsSync as existsSync18, readFileSync as readFileSync21, writeFileSync as writeFileSync12, mkdirSync as mkdirSync14 } from "fs";
|
|
60190
|
-
import { join as
|
|
60407
|
+
import { join as join37 } from "path";
|
|
60191
60408
|
function getSchedulesPath(targetDir = process.cwd()) {
|
|
60192
|
-
return
|
|
60409
|
+
return join37(targetDir, ".skills", "schedules.json");
|
|
60193
60410
|
}
|
|
60194
60411
|
function loadSchedules(targetDir = process.cwd()) {
|
|
60195
60412
|
const path = getSchedulesPath(targetDir);
|
|
@@ -60202,7 +60419,7 @@ function loadSchedules(targetDir = process.cwd()) {
|
|
|
60202
60419
|
}
|
|
60203
60420
|
function saveSchedules(data, targetDir = process.cwd()) {
|
|
60204
60421
|
const path = getSchedulesPath(targetDir);
|
|
60205
|
-
const dir =
|
|
60422
|
+
const dir = join37(targetDir, ".skills");
|
|
60206
60423
|
if (!existsSync18(dir))
|
|
60207
60424
|
mkdirSync14(dir, { recursive: true });
|
|
60208
60425
|
writeFileSync12(path, JSON.stringify(data, null, 2));
|
|
@@ -60474,7 +60691,7 @@ var init_schedule_tools = __esm(() => {
|
|
|
60474
60691
|
});
|
|
60475
60692
|
|
|
60476
60693
|
// src/lib/native-storage.ts
|
|
60477
|
-
import { createHash as
|
|
60694
|
+
import { createHash as createHash22, createHmac } from "crypto";
|
|
60478
60695
|
import {
|
|
60479
60696
|
existsSync as existsSync19,
|
|
60480
60697
|
mkdirSync as mkdirSync15,
|
|
@@ -60483,7 +60700,7 @@ import {
|
|
|
60483
60700
|
statSync as statSync11,
|
|
60484
60701
|
writeFileSync as writeFileSync13
|
|
60485
60702
|
} from "fs";
|
|
60486
|
-
import { dirname as dirname22, join as
|
|
60703
|
+
import { dirname as dirname22, join as join38, normalize as normalize4, relative as relative7, sep as sep9 } from "path";
|
|
60487
60704
|
function resolveSkillsNativeStorageConfig(env = process.env) {
|
|
60488
60705
|
assertNoRetiredModeEnvVars(env, {
|
|
60489
60706
|
app: SKILLS_ENV_NAMESPACE,
|
|
@@ -60524,7 +60741,7 @@ function getSkillsNativeStorageStatus(options = {}) {
|
|
|
60524
60741
|
local: {
|
|
60525
60742
|
dataDir: getDataDir(),
|
|
60526
60743
|
projectStateDir: getProjectStateDir(targetDir),
|
|
60527
|
-
feedbackDbPath:
|
|
60744
|
+
feedbackDbPath: join38(getDataDir(), "skills.db")
|
|
60528
60745
|
},
|
|
60529
60746
|
remote: {
|
|
60530
60747
|
databaseConfigured: Boolean(config2.databaseUrl),
|
|
@@ -60551,7 +60768,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
|
|
|
60551
60768
|
files.push({
|
|
60552
60769
|
path: relativePath,
|
|
60553
60770
|
sizeBytes: bytes.byteLength,
|
|
60554
|
-
sha256:
|
|
60771
|
+
sha256: createHash22("sha256").update(bytes).digest("hex"),
|
|
60555
60772
|
...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
|
|
60556
60773
|
});
|
|
60557
60774
|
}
|
|
@@ -60605,7 +60822,7 @@ function parsePositiveInteger(value) {
|
|
|
60605
60822
|
function walkFiles2(dir) {
|
|
60606
60823
|
const files = [];
|
|
60607
60824
|
for (const entry of readdirSync12(dir)) {
|
|
60608
|
-
const full =
|
|
60825
|
+
const full = join38(dir, entry);
|
|
60609
60826
|
const stats = statSync11(full);
|
|
60610
60827
|
if (stats.isDirectory())
|
|
60611
60828
|
files.push(...walkFiles2(full));
|
|
@@ -60844,7 +61061,7 @@ var init_private_publication_customer = __esm(() => {
|
|
|
60844
61061
|
|
|
60845
61062
|
// src/lib/private-publication-recovery.ts
|
|
60846
61063
|
import { constants as constants14, closeSync as closeSync18, fsyncSync as fsyncSync5, fstatSync as fstatSync18, lstatSync as lstatSync22, mkdirSync as mkdirSync16, openSync as openSync18, readSync as readSync12, realpathSync as realpathSync11, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync14 } from "fs";
|
|
60847
|
-
import { dirname as dirname23, isAbsolute as isAbsolute18, join as
|
|
61064
|
+
import { dirname as dirname23, isAbsolute as isAbsolute18, join as join39, resolve as resolve20 } from "path";
|
|
60848
61065
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
60849
61066
|
function safeDirectory(directory2) {
|
|
60850
61067
|
if (!isAbsolute18(directory2) || directory2 !== resolve20(directory2) || realpathSync11(directory2) !== directory2)
|
|
@@ -60867,7 +61084,7 @@ function unchangedDirectory(directory2, identity3) {
|
|
|
60867
61084
|
return fail2();
|
|
60868
61085
|
}
|
|
60869
61086
|
function readOwned(directory2, name, max) {
|
|
60870
|
-
const identity3 = safeDirectory(directory2), file2 =
|
|
61087
|
+
const identity3 = safeDirectory(directory2), file2 = join39(directory2, name);
|
|
60871
61088
|
const fd = openSync18(file2, constants14.O_RDONLY | constants14.O_NOFOLLOW);
|
|
60872
61089
|
try {
|
|
60873
61090
|
const stat3 = fstatSync18(fd);
|
|
@@ -60891,7 +61108,7 @@ function readOwned(directory2, name, max) {
|
|
|
60891
61108
|
}
|
|
60892
61109
|
}
|
|
60893
61110
|
function writeOwned(directory2, name, bytes) {
|
|
60894
|
-
const fd = openSync18(
|
|
61111
|
+
const fd = openSync18(join39(directory2, name), constants14.O_WRONLY | constants14.O_CREAT | constants14.O_EXCL | constants14.O_NOFOLLOW, 384);
|
|
60895
61112
|
try {
|
|
60896
61113
|
writeFileSync14(fd, bytes);
|
|
60897
61114
|
fsyncSync5(fd);
|
|
@@ -60904,7 +61121,7 @@ function save(directory2, value) {
|
|
|
60904
61121
|
writeOwned(directory2, temporary, JSON.stringify(value) + `
|
|
60905
61122
|
`);
|
|
60906
61123
|
unchangedDirectory(directory2, identity3);
|
|
60907
|
-
renameSync7(
|
|
61124
|
+
renameSync7(join39(directory2, temporary), join39(directory2, "receipt.json"));
|
|
60908
61125
|
const fd = openSync18(directory2, constants14.O_RDONLY | constants14.O_NOFOLLOW);
|
|
60909
61126
|
try {
|
|
60910
61127
|
fsyncSync5(fd);
|
|
@@ -60917,7 +61134,7 @@ function bind(client, receipt) {
|
|
|
60917
61134
|
throw new PrivatePublicationError("PUBLICATION_IDENTITY_CHANGED", "The fresh session does not match the recovery directory's server, account and membership.");
|
|
60918
61135
|
}
|
|
60919
61136
|
async function locked(directory2, action) {
|
|
60920
|
-
const identity3 = safeDirectory(directory2), file2 =
|
|
61137
|
+
const identity3 = safeDirectory(directory2), file2 = join39(directory2, "operation.lock");
|
|
60921
61138
|
let fd;
|
|
60922
61139
|
try {
|
|
60923
61140
|
fd = openSync18(file2, constants14.O_WRONLY | constants14.O_CREAT | constants14.O_EXCL | constants14.O_NOFOLLOW, 384);
|
|
@@ -62808,7 +63025,7 @@ var require_content_type = __commonJS((exports) => {
|
|
|
62808
63025
|
var QUOTE_REGEXP = /([\\"])/g;
|
|
62809
63026
|
var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
62810
63027
|
exports.format = format;
|
|
62811
|
-
exports.parse =
|
|
63028
|
+
exports.parse = parse12;
|
|
62812
63029
|
function format(obj) {
|
|
62813
63030
|
if (!obj || typeof obj !== "object") {
|
|
62814
63031
|
throw new TypeError("argument obj is required");
|
|
@@ -62832,7 +63049,7 @@ var require_content_type = __commonJS((exports) => {
|
|
|
62832
63049
|
}
|
|
62833
63050
|
return string6;
|
|
62834
63051
|
}
|
|
62835
|
-
function
|
|
63052
|
+
function parse12(string6) {
|
|
62836
63053
|
if (!string6) {
|
|
62837
63054
|
throw new TypeError("argument string is required");
|
|
62838
63055
|
}
|