@hasna/skills 0.10.25 → 0.10.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/bin/index.js +437 -327
- package/bin/mcp.js +263 -117
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +326 -219
- package/dist/lib/agent-discovery.d.ts +1 -1
- package/dist/lib/agent-integration.d.ts +1 -0
- package/dist/lib/codex-local-mcp-controls.d.ts +4 -0
- package/dist/lib/codex-mcp-discovery-projection.d.ts +7 -0
- package/dist/lib/codex-settings-witness.d.ts +15 -0
- package/dist/sdk/index.js +423 -318
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9101,8 +9101,8 @@ function assertAgentPolicyCollections(policy) {
|
|
|
9101
9101
|
text(source.path);
|
|
9102
9102
|
requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
|
|
9103
9103
|
if (source.hashMode !== undefined)
|
|
9104
|
-
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"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
9105
|
-
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2")
|
|
9104
|
+
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"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
9105
|
+
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3")
|
|
9106
9106
|
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute2(source.path) && resolve2(source.path) === source.path && basename2(source.path) === "config.toml");
|
|
9107
9107
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3")
|
|
9108
9108
|
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute2(source.path) && resolve2(source.path) === source.path && basename2(source.path) === "settings.json");
|
|
@@ -9141,7 +9141,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
9141
9141
|
import { createHash as createHash18 } from "crypto";
|
|
9142
9142
|
import { lstatSync as lstatSync21, readFileSync as readFileSync17, readdirSync as readdirSync10, realpathSync as realpathSync7 } from "fs";
|
|
9143
9143
|
import { basename as basename9, dirname as dirname17, isAbsolute as isAbsolute16, join as join27, resolve as resolve15, sep as sep6 } from "path";
|
|
9144
|
-
import { isDeepStrictEqual as
|
|
9144
|
+
import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
|
|
9145
9145
|
|
|
9146
9146
|
// node_modules/yaml/dist/index.js
|
|
9147
9147
|
var composer = require_composer();
|
|
@@ -10914,7 +10914,7 @@ function replaceSkillSession(expected, replacement, plan, options = {}, beforeCo
|
|
|
10914
10914
|
// package.json
|
|
10915
10915
|
var package_default = {
|
|
10916
10916
|
name: "@hasna/skills",
|
|
10917
|
-
version: "0.10.
|
|
10917
|
+
version: "0.10.27",
|
|
10918
10918
|
description: "Skills library for AI coding agents",
|
|
10919
10919
|
type: "module",
|
|
10920
10920
|
bin: {
|
|
@@ -12749,6 +12749,72 @@ import {
|
|
|
12749
12749
|
import { homedir as homedir3 } from "os";
|
|
12750
12750
|
import { basename as basename6, dirname as dirname12, join as join18 } from "path";
|
|
12751
12751
|
|
|
12752
|
+
// src/lib/codex-local-mcp-controls.ts
|
|
12753
|
+
function isCodexLocalStdioMcpServer(name, server) {
|
|
12754
|
+
const identifier2 = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(value);
|
|
12755
|
+
const refuse = () => {
|
|
12756
|
+
throw new Error("Unsupported Codex local stdio MCP controls");
|
|
12757
|
+
};
|
|
12758
|
+
const object4 = (v) => Boolean(v && typeof v === "object" && !Array.isArray(v) && !(v instanceof Date));
|
|
12759
|
+
const textField = (v, empty = false) => typeof v === "string" && (empty || Boolean(v.trim())) && Buffer.byteLength(v) <= 16384 && !/[\x00-\x1f\x7f]/.test(v);
|
|
12760
|
+
const envName = (v) => typeof v === "string" && /^[A-Za-z_][A-Za-z0-9_]{0,255}$/.test(v);
|
|
12761
|
+
const optional = (v, valid) => v === undefined || v === null || valid(v);
|
|
12762
|
+
const stringList = (v) => Array.isArray(v) && v.length <= 256 && v.every((item) => textField(item));
|
|
12763
|
+
const approval = (v) => ["auto", "prompt", "writes", "approve"].includes(v);
|
|
12764
|
+
const duration = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0;
|
|
12765
|
+
const positiveInteger = (v) => Number.isSafeInteger(v) && v > 0;
|
|
12766
|
+
const fields = [
|
|
12767
|
+
"command",
|
|
12768
|
+
"args",
|
|
12769
|
+
"cwd",
|
|
12770
|
+
"env",
|
|
12771
|
+
"env_vars",
|
|
12772
|
+
"enabled",
|
|
12773
|
+
"required",
|
|
12774
|
+
"environment_id",
|
|
12775
|
+
"startup_readiness",
|
|
12776
|
+
"supports_parallel_tool_calls",
|
|
12777
|
+
"tool_input_schema_max_bytes",
|
|
12778
|
+
"startup_timeout_sec",
|
|
12779
|
+
"startup_timeout_ms",
|
|
12780
|
+
"tool_timeout_sec",
|
|
12781
|
+
"default_tools_approval_mode",
|
|
12782
|
+
"enabled_tools",
|
|
12783
|
+
"disabled_tools",
|
|
12784
|
+
"omit_tools_from",
|
|
12785
|
+
"tools",
|
|
12786
|
+
"name"
|
|
12787
|
+
];
|
|
12788
|
+
try {
|
|
12789
|
+
if (!identifier2(name) || !object4(server) || !Object.keys(server).every((key) => fields.includes(key)) || !textField(server.command) || !optional(server.args, (v) => Array.isArray(v) && v.length <= 256 && v.every((arg) => textField(arg, true))) || !optional(server.cwd, textField) || !optional(server.env, (v) => object4(v) && Object.keys(v).length <= 256 && Object.entries(v).every(([key, value]) => envName(key) && textField(value, true))) || !["enabled", "required", "supports_parallel_tool_calls"].every((key) => optional(server[key], (v) => typeof v === "boolean")) || !optional(server.environment_id, (v) => v === "local") || !optional(server.startup_readiness, (v) => ["connection", "catalog"].includes(v)) || !optional(server.tool_input_schema_max_bytes, positiveInteger) || !["startup_timeout_sec", "tool_timeout_sec"].every((key) => optional(server[key], duration)) || !optional(server.startup_timeout_ms, (v) => Number.isSafeInteger(v) && v >= 0) || !optional(server.default_tools_approval_mode, approval) || !["enabled_tools", "disabled_tools"].every((key) => optional(server[key], stringList)) || !optional(server.omit_tools_from, (v) => Array.isArray(v) && v.length <= 256 && v.every((item) => ["code_mode", "deferred", "direct"].includes(item))) || !optional(server.name, textField))
|
|
12790
|
+
refuse();
|
|
12791
|
+
if (server.env_vars !== undefined && server.env_vars !== null) {
|
|
12792
|
+
if (!Array.isArray(server.env_vars) || server.env_vars.length > 256)
|
|
12793
|
+
refuse();
|
|
12794
|
+
const names = server.env_vars.map((entry) => {
|
|
12795
|
+
if (envName(entry))
|
|
12796
|
+
return entry;
|
|
12797
|
+
if (!object4(entry) || !Object.keys(entry).every((key) => ["name", "source"].includes(key)) || !envName(entry.name) || !optional(entry.source, (v) => v === "local"))
|
|
12798
|
+
refuse();
|
|
12799
|
+
return entry.name;
|
|
12800
|
+
});
|
|
12801
|
+
if (new Set(names).size !== names.length)
|
|
12802
|
+
refuse();
|
|
12803
|
+
}
|
|
12804
|
+
if (server.tools !== undefined && server.tools !== null) {
|
|
12805
|
+
if (!object4(server.tools) || Object.keys(server.tools).length > 256)
|
|
12806
|
+
refuse();
|
|
12807
|
+
for (const [tool, config] of Object.entries(server.tools)) {
|
|
12808
|
+
if (!textField(tool) || !object4(config) || !Object.keys(config).every((key) => ["approval_mode", "output_token_limit"].includes(key)) || !optional(config.approval_mode, approval) || !optional(config.output_token_limit, positiveInteger))
|
|
12809
|
+
refuse();
|
|
12810
|
+
}
|
|
12811
|
+
}
|
|
12812
|
+
return true;
|
|
12813
|
+
} catch {
|
|
12814
|
+
return false;
|
|
12815
|
+
}
|
|
12816
|
+
}
|
|
12817
|
+
|
|
12752
12818
|
// src/lib/claude-settings-witness.ts
|
|
12753
12819
|
import { createHash as createHash8 } from "crypto";
|
|
12754
12820
|
import { closeSync as closeSync6, constants as constants5, fstatSync as fstatSync6, lstatSync as lstatSync11, openSync as openSync6, readSync as readSync4 } from "fs";
|
|
@@ -13430,65 +13496,14 @@ function mcpControls(path, read2) {
|
|
|
13430
13496
|
refuse2();
|
|
13431
13497
|
}
|
|
13432
13498
|
const object5 = (v) => Boolean(v && typeof v === "object" && !Array.isArray(v));
|
|
13433
|
-
const textField = (v, empty = false) => typeof v === "string" && (empty || Boolean(v.trim())) && Buffer.byteLength(v) <= 16384 && !/[\x00-\x1f\x7f]/.test(v);
|
|
13434
|
-
const envName = (v) => typeof v === "string" && /^[A-Za-z_][A-Za-z0-9_]{0,255}$/.test(v);
|
|
13435
|
-
const optional = (v, valid) => v === undefined || v === null || valid(v);
|
|
13436
|
-
const stringList = (v) => Array.isArray(v) && v.length <= 256 && v.every((item) => textField(item));
|
|
13437
|
-
const approval = (v) => ["auto", "prompt", "writes", "approve"].includes(v);
|
|
13438
|
-
const duration = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0;
|
|
13439
|
-
const positiveInteger = (v) => Number.isSafeInteger(v) && v > 0;
|
|
13440
|
-
const fields = [
|
|
13441
|
-
"command",
|
|
13442
|
-
"args",
|
|
13443
|
-
"cwd",
|
|
13444
|
-
"env",
|
|
13445
|
-
"env_vars",
|
|
13446
|
-
"enabled",
|
|
13447
|
-
"required",
|
|
13448
|
-
"environment_id",
|
|
13449
|
-
"startup_readiness",
|
|
13450
|
-
"supports_parallel_tool_calls",
|
|
13451
|
-
"tool_input_schema_max_bytes",
|
|
13452
|
-
"startup_timeout_sec",
|
|
13453
|
-
"startup_timeout_ms",
|
|
13454
|
-
"tool_timeout_sec",
|
|
13455
|
-
"default_tools_approval_mode",
|
|
13456
|
-
"enabled_tools",
|
|
13457
|
-
"disabled_tools",
|
|
13458
|
-
"omit_tools_from",
|
|
13459
|
-
"tools",
|
|
13460
|
-
"name"
|
|
13461
|
-
];
|
|
13462
13499
|
if (!object5(value) || Object.keys(value).length !== 1 || !object5(value.mcpServers))
|
|
13463
13500
|
refuse2();
|
|
13464
13501
|
const servers = Object.entries(value.mcpServers);
|
|
13465
13502
|
if (!servers.length || servers.length > 256)
|
|
13466
13503
|
refuse2();
|
|
13467
|
-
for (const [name, server] of servers)
|
|
13468
|
-
if (!
|
|
13504
|
+
for (const [name, server] of servers)
|
|
13505
|
+
if (!isCodexLocalStdioMcpServer(name, server))
|
|
13469
13506
|
refuse2();
|
|
13470
|
-
if (server.env_vars !== undefined && server.env_vars !== null) {
|
|
13471
|
-
if (!Array.isArray(server.env_vars) || server.env_vars.length > 256)
|
|
13472
|
-
refuse2();
|
|
13473
|
-
const names = server.env_vars.map((entry) => {
|
|
13474
|
-
if (envName(entry))
|
|
13475
|
-
return entry;
|
|
13476
|
-
if (!object5(entry) || !Object.keys(entry).every((key) => ["name", "source"].includes(key)) || !envName(entry.name) || !optional(entry.source, (v) => v === "local"))
|
|
13477
|
-
refuse2();
|
|
13478
|
-
return entry.name;
|
|
13479
|
-
});
|
|
13480
|
-
if (new Set(names).size !== names.length)
|
|
13481
|
-
refuse2();
|
|
13482
|
-
}
|
|
13483
|
-
if (server.tools !== undefined && server.tools !== null) {
|
|
13484
|
-
if (!object5(server.tools) || Object.keys(server.tools).length > 256)
|
|
13485
|
-
refuse2();
|
|
13486
|
-
for (const [tool, config] of Object.entries(server.tools)) {
|
|
13487
|
-
if (!textField(tool) || !object5(config) || !Object.keys(config).every((key) => ["approval_mode", "output_token_limit"].includes(key)) || !optional(config.approval_mode, approval) || !optional(config.output_token_limit, positiveInteger))
|
|
13488
|
-
refuse2();
|
|
13489
|
-
}
|
|
13490
|
-
}
|
|
13491
|
-
}
|
|
13492
13507
|
return sha2562;
|
|
13493
13508
|
}
|
|
13494
13509
|
function rootControls(root, read2) {
|
|
@@ -13858,6 +13873,69 @@ function captureCodexSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
|
13858
13873
|
const text2 = readNativeSettingsWitnessFile(path, budget, "config.toml");
|
|
13859
13874
|
return { path, hashMode: "codex-settings-v1", sha256: hashCodexSettingsReplacement(text2) };
|
|
13860
13875
|
}
|
|
13876
|
+
// src/lib/codex-mcp-discovery-projection.ts
|
|
13877
|
+
import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
|
|
13878
|
+
function record2(value) {
|
|
13879
|
+
return !!value && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date);
|
|
13880
|
+
}
|
|
13881
|
+
function localStdio(name, row) {
|
|
13882
|
+
return name !== "codex_apps" && name !== "_codex_apps" && isCodexLocalStdioMcpServer(name, row);
|
|
13883
|
+
}
|
|
13884
|
+
function stripEmptyParent(config) {
|
|
13885
|
+
if (record2(config.mcp_servers) && !Object.keys(config.mcp_servers).length)
|
|
13886
|
+
delete config.mcp_servers;
|
|
13887
|
+
return config;
|
|
13888
|
+
}
|
|
13889
|
+
function projectRegularCodexMcp(config, source) {
|
|
13890
|
+
const unchanged2 = { config, numericSource: source };
|
|
13891
|
+
if (!record2(config.mcp_servers))
|
|
13892
|
+
return unchanged2;
|
|
13893
|
+
const candidates = Object.entries(config.mcp_servers).filter(([name, row]) => localStdio(name, row)).map(([name]) => name);
|
|
13894
|
+
if (!candidates.length)
|
|
13895
|
+
return unchanged2;
|
|
13896
|
+
const headers = [];
|
|
13897
|
+
let attempts = 0;
|
|
13898
|
+
for (const match of source.matchAll(/^[ \t]*\[{1,2}[^\r\n]*\]{1,2}[ \t]*(?:#[^\r\n]*)?(?:\r?\n|$)/gm)) {
|
|
13899
|
+
if (++attempts > 256)
|
|
13900
|
+
return unchanged2;
|
|
13901
|
+
try {
|
|
13902
|
+
Bun.TOML.parse(source.slice(0, match.index));
|
|
13903
|
+
} catch {
|
|
13904
|
+
continue;
|
|
13905
|
+
}
|
|
13906
|
+
let header;
|
|
13907
|
+
try {
|
|
13908
|
+
header = Bun.TOML.parse(match[0]);
|
|
13909
|
+
} catch {
|
|
13910
|
+
return unchanged2;
|
|
13911
|
+
}
|
|
13912
|
+
const path = [];
|
|
13913
|
+
while (record2(header) && Object.keys(header).length === 1) {
|
|
13914
|
+
const key = Object.keys(header)[0];
|
|
13915
|
+
path.push(key);
|
|
13916
|
+
header = header[key];
|
|
13917
|
+
}
|
|
13918
|
+
headers.push({ start: match.index, path });
|
|
13919
|
+
}
|
|
13920
|
+
const names = candidates.filter((name) => headers.filter((header) => header.path.length === 2 && header.path[0] === "mcp_servers" && header.path[1] === name).length === 1);
|
|
13921
|
+
if (!names.length)
|
|
13922
|
+
return unchanged2;
|
|
13923
|
+
const selected = headers.map((header, index) => ({ ...header, end: headers[index + 1]?.start ?? source.length })).filter((header) => header.path[0] === "mcp_servers" && names.includes(header.path[1]));
|
|
13924
|
+
let numericSource = source;
|
|
13925
|
+
for (const range of selected.reverse())
|
|
13926
|
+
numericSource = numericSource.slice(0, range.start) + numericSource.slice(range.end);
|
|
13927
|
+
const expected = structuredClone(config);
|
|
13928
|
+
for (const name of names)
|
|
13929
|
+
delete expected.mcp_servers[name];
|
|
13930
|
+
stripEmptyParent(expected);
|
|
13931
|
+
try {
|
|
13932
|
+
if (!isDeepStrictEqual2(stripEmptyParent(Bun.TOML.parse(numericSource)), expected))
|
|
13933
|
+
return unchanged2;
|
|
13934
|
+
} catch {
|
|
13935
|
+
return unchanged2;
|
|
13936
|
+
}
|
|
13937
|
+
return { config: expected, numericSource };
|
|
13938
|
+
}
|
|
13861
13939
|
|
|
13862
13940
|
// src/lib/codex-settings-witness.ts
|
|
13863
13941
|
import { createHash as createHash10 } from "crypto";
|
|
@@ -13937,7 +14015,7 @@ function canonical4(value, depth = 0, budget = { remaining: 65536 }) {
|
|
|
13937
14015
|
need4(isRecord3(value));
|
|
13938
14016
|
return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical4(child, depth + 1, budget)])];
|
|
13939
14017
|
}
|
|
13940
|
-
function normalize3(config) {
|
|
14018
|
+
function normalize3(config, version = 2) {
|
|
13941
14019
|
if (isRecord3(config.hooks)) {
|
|
13942
14020
|
delete config.hooks.state;
|
|
13943
14021
|
if (!Object.keys(config.hooks).length)
|
|
@@ -13955,11 +14033,11 @@ function normalize3(config) {
|
|
|
13955
14033
|
if (!Object.keys(skills).length)
|
|
13956
14034
|
delete config.skills;
|
|
13957
14035
|
}
|
|
13958
|
-
inference(config);
|
|
14036
|
+
inference(config, version);
|
|
13959
14037
|
if (isRecord3(config.profiles)) {
|
|
13960
14038
|
for (const profile of Object.values(config.profiles))
|
|
13961
14039
|
if (isRecord3(profile))
|
|
13962
|
-
inference(profile);
|
|
14040
|
+
inference(profile, version);
|
|
13963
14041
|
}
|
|
13964
14042
|
}
|
|
13965
14043
|
function disablesOneSkill(entry) {
|
|
@@ -13971,18 +14049,23 @@ function disablesOneSkill(entry) {
|
|
|
13971
14049
|
const selector = ["path", "name"].filter((key) => Object.hasOwn(entry, key));
|
|
13972
14050
|
return selector.length === 1 && typeof entry[selector[0]] === "string" && entry[selector[0]].length > 0;
|
|
13973
14051
|
}
|
|
13974
|
-
function inference(target) {
|
|
13975
|
-
|
|
14052
|
+
function inference(target, version) {
|
|
14053
|
+
const keys = version === 3 ? [...INFERENCE, "service_tier", "plan_mode_reasoning_effort"] : INFERENCE;
|
|
14054
|
+
for (const key of keys)
|
|
13976
14055
|
if (Object.hasOwn(target, key)) {
|
|
13977
14056
|
const value = target[key];
|
|
13978
14057
|
if (key === "model")
|
|
13979
14058
|
need4(typeof value === "string" && MODEL.test(value));
|
|
13980
|
-
else
|
|
14059
|
+
else if (version === 3 && key !== "model_verbosity") {
|
|
14060
|
+
need4(typeof value === "string" && value.length <= 128 && !/[\x00-\x1f\x7f]/.test(value));
|
|
14061
|
+
if (key !== "service_tier")
|
|
14062
|
+
need4(value.length > 0);
|
|
14063
|
+
} else
|
|
13981
14064
|
need4(typeof value === "string" && (key === "model_reasoning_effort" ? EFFORT2.has(value) : VERBOSITY2.has(value)));
|
|
13982
14065
|
delete target[key];
|
|
13983
14066
|
}
|
|
13984
14067
|
}
|
|
13985
|
-
function settingsDigest2(text2) {
|
|
14068
|
+
function settingsDigest2(text2, version = 2) {
|
|
13986
14069
|
let config;
|
|
13987
14070
|
try {
|
|
13988
14071
|
config = Bun.TOML.parse(text2);
|
|
@@ -13990,8 +14073,9 @@ function settingsDigest2(text2) {
|
|
|
13990
14073
|
throw new Error("Invalid Codex settings witness");
|
|
13991
14074
|
}
|
|
13992
14075
|
need4(isRecord3(config));
|
|
13993
|
-
|
|
13994
|
-
|
|
14076
|
+
const projected = version === 3 ? projectRegularCodexMcp(config, text2) : { config, numericSource: text2 };
|
|
14077
|
+
normalize3(projected.config, version);
|
|
14078
|
+
return sha2(`hasna.skills.codex-settings.v${version}\x00${JSON.stringify([canonical4(projected.config), numericTokens2(projected.numericSource)])}`);
|
|
13995
14079
|
}
|
|
13996
14080
|
function hashCodexSettingsReplacementV2(text2, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
13997
14081
|
need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
|
|
@@ -14015,10 +14099,29 @@ function upgradeCodexSettingsWitness(previous, reviewedSettingsPath) {
|
|
|
14015
14099
|
throw new Error("Codex non-preference settings changed; explicit discovery review required");
|
|
14016
14100
|
return { path: previous.path, hashMode: "codex-settings-v2", sha256: sha2562 };
|
|
14017
14101
|
}
|
|
14102
|
+
function hashCodexSettingsReplacementV3(text2, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
14103
|
+
need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
|
|
14104
|
+
budget.remaining -= Buffer.byteLength(text2);
|
|
14105
|
+
return settingsDigest2(text2, 3);
|
|
14106
|
+
}
|
|
14107
|
+
function captureCodexSettingsV3(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
14108
|
+
return { path, hashMode: "codex-settings-v3", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget, "config.toml"), 3) };
|
|
14109
|
+
}
|
|
14110
|
+
function upgradeCodexSettingsWitnessV3(previous, reviewedSettingsPath) {
|
|
14111
|
+
need4(previous && Object.keys(previous).every((key) => ["path", "hashMode", "sha256"].includes(key)) && (previous.hashMode === undefined || ["bytes", "codex-settings-v1", "codex-settings-v2"].includes(previous.hashMode)) && /^[a-f0-9]{64}$/.test(previous.sha256));
|
|
14112
|
+
const budget = { remaining: 2 * 1024 * 1024 };
|
|
14113
|
+
const before = readNativeSettingsWitnessFile(reviewedSettingsPath, budget, "config.toml"), current = readNativeSettingsWitnessFile(previous.path, budget, "config.toml");
|
|
14114
|
+
const original = previous.hashMode === "codex-settings-v2" ? settingsDigest2(before) : previous.hashMode === "codex-settings-v1" ? hashCodexSettingsReplacement(before) : sha2(before);
|
|
14115
|
+
need4(original === previous.sha256);
|
|
14116
|
+
const sha2562 = settingsDigest2(current, 3);
|
|
14117
|
+
if (settingsDigest2(before, 3) !== sha2562)
|
|
14118
|
+
throw new Error("Codex settings outside the reviewed V3 contract changed; explicit discovery review required");
|
|
14119
|
+
return { path: previous.path, hashMode: "codex-settings-v3", sha256: sha2562 };
|
|
14120
|
+
}
|
|
14018
14121
|
|
|
14019
14122
|
// src/lib/agent-integration.ts
|
|
14020
14123
|
import { createHash as createHash12, randomUUID as randomUUID2 } from "crypto";
|
|
14021
|
-
import { isDeepStrictEqual as
|
|
14124
|
+
import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
|
|
14022
14125
|
import { existsSync as existsSync8, lstatSync as lstatSync15, statSync as statSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync12, readdirSync as readdirSync8, opendirSync as opendirSync3, readlinkSync as readlinkSync4, realpathSync as realpathSync6, renameSync as renameSync2, rmdirSync as rmdirSync2, writeFileSync as writeFileSync4, unlinkSync as unlinkSync3, chmodSync, openSync as openSync8, closeSync as closeSync8, fsyncSync as fsyncSync2, fstatSync as fstatSync8, readSync as readSync6, constants as constants7, linkSync } from "fs";
|
|
14023
14126
|
import { dirname as dirname11, join as join17, resolve as resolve10, relative as relative5, isAbsolute as isAbsolute11, sep as sep5 } from "path";
|
|
14024
14127
|
import { homedir as homedir2 } from "os";
|
|
@@ -14147,7 +14250,7 @@ function isOwnedCliBridge(path, expectedPaths) {
|
|
|
14147
14250
|
}
|
|
14148
14251
|
|
|
14149
14252
|
// src/lib/agent-codex.ts
|
|
14150
|
-
import { isDeepStrictEqual as
|
|
14253
|
+
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
14151
14254
|
var CODEX_SKILL_CONFIG_SECTIONS = /^\[\[skills\.config\]\][^\n]*(?:\n(?!\s*\[)[^\n]*)*/gm;
|
|
14152
14255
|
var codexPathConfigRefusal = () => new Error("Codex skill path controls require ordinary [[skills.config]] TOML tables or a native single-line inline array; preserve and review unsupported inline, dotted, or malformed definitions before running skills hook install");
|
|
14153
14256
|
function splitTopLevel(value, delimiter) {
|
|
@@ -14278,7 +14381,7 @@ function normalizeCodexInlinePathConfig(text2) {
|
|
|
14278
14381
|
const expectedWithoutConfig = structuredClone(before);
|
|
14279
14382
|
delete expectedWithoutConfig.skills.config;
|
|
14280
14383
|
try {
|
|
14281
|
-
if (
|
|
14384
|
+
if (isDeepStrictEqual3(Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, "")), expectedWithoutConfig))
|
|
14282
14385
|
return text2;
|
|
14283
14386
|
} catch {}
|
|
14284
14387
|
const matches = [];
|
|
@@ -14331,7 +14434,7 @@ function normalizeCodexInlinePathConfig(text2) {
|
|
|
14331
14434
|
try {
|
|
14332
14435
|
const after = Bun.TOML.parse(candidate);
|
|
14333
14436
|
const expected = structuredClone(before);
|
|
14334
|
-
if (
|
|
14437
|
+
if (isDeepStrictEqual3(after, expected))
|
|
14335
14438
|
matches.push(candidate);
|
|
14336
14439
|
} catch {}
|
|
14337
14440
|
}
|
|
@@ -14347,11 +14450,11 @@ function assertCodexPathConfigEditable(text2) {
|
|
|
14347
14450
|
delete expected.skills.config;
|
|
14348
14451
|
try {
|
|
14349
14452
|
const withoutSections = Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, ""));
|
|
14350
|
-
if (
|
|
14453
|
+
if (isDeepStrictEqual3(withoutSections, expected))
|
|
14351
14454
|
return;
|
|
14352
14455
|
const normalized = normalizeCodexInlinePathConfig(text2);
|
|
14353
14456
|
const withoutNormalizedSections = Bun.TOML.parse(normalized.replace(CODEX_SKILL_CONFIG_SECTIONS, ""));
|
|
14354
|
-
if (
|
|
14457
|
+
if (isDeepStrictEqual3(withoutNormalizedSections, expected))
|
|
14355
14458
|
return;
|
|
14356
14459
|
} catch {}
|
|
14357
14460
|
throw codexPathConfigRefusal();
|
|
@@ -14389,7 +14492,7 @@ function disableCodexBundledSkills(text2) {
|
|
|
14389
14492
|
const candidates = new Set;
|
|
14390
14493
|
const consider = (candidate) => {
|
|
14391
14494
|
try {
|
|
14392
|
-
if (
|
|
14495
|
+
if (isDeepStrictEqual3(Bun.TOML.parse(candidate), expected))
|
|
14393
14496
|
candidates.add(candidate);
|
|
14394
14497
|
} catch {}
|
|
14395
14498
|
};
|
|
@@ -14719,7 +14822,7 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
|
|
|
14719
14822
|
admit(path);
|
|
14720
14823
|
const scan = { complete: true, hasSkills: false, entries: 1 };
|
|
14721
14824
|
assertSafePath(path);
|
|
14722
|
-
if (configuredRoot && agent === "codex" && installationInputs.
|
|
14825
|
+
if (configuredRoot && agent === "codex" && installationInputs.some((root) => path === root || path.startsWith(`${root}${sep5}`)))
|
|
14723
14826
|
return scan;
|
|
14724
14827
|
if (!existsSync8(path))
|
|
14725
14828
|
return scan;
|
|
@@ -15200,6 +15303,8 @@ function atomicWrite2(path, content) {
|
|
|
15200
15303
|
}
|
|
15201
15304
|
}
|
|
15202
15305
|
function planAgentSettingsWitnessUpgrade(options) {
|
|
15306
|
+
if (options.targetCodexVersion !== undefined && (options.agent !== "codex" || ![2, 3].includes(options.targetCodexVersion)))
|
|
15307
|
+
throw new Error("Invalid Codex witness target version");
|
|
15203
15308
|
const home = resolve10(options.home ?? homedir2()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
|
|
15204
15309
|
const snapshot = readManagedSkillPolicySnapshot(dataDir2);
|
|
15205
15310
|
if (!snapshot || sha3(snapshot.text) !== options.expectedPolicySha256)
|
|
@@ -15221,21 +15326,21 @@ function planAgentSettingsWitnessUpgrade(options) {
|
|
|
15221
15326
|
throw new Error("Settings witness upgrade requires a preserved settings preimage");
|
|
15222
15327
|
const replaced = [previous];
|
|
15223
15328
|
if (options.agent === "codex") {
|
|
15224
|
-
if (previous.hashMode !== undefined && previous.hashMode !== "bytes" && previous.hashMode !== "codex-settings-v1")
|
|
15225
|
-
throw new Error("Codex settings witness upgrade requires
|
|
15329
|
+
if (previous.hashMode !== undefined && previous.hashMode !== "bytes" && previous.hashMode !== "codex-settings-v1" && !(options.targetCodexVersion === 3 && previous.hashMode === "codex-settings-v2"))
|
|
15330
|
+
throw new Error("Codex settings witness upgrade requires an eligible preserved configuration witness");
|
|
15226
15331
|
const preimage = readCodexSettingsPreimage(options.reviewedPreimage);
|
|
15227
15332
|
for (const source of binding.sources) {
|
|
15228
15333
|
if (source === previous || source.path !== configPath)
|
|
15229
15334
|
continue;
|
|
15230
15335
|
const fields = source.fields;
|
|
15231
|
-
if (source.hashMode !== undefined || source.format !== "toml" || !Array.isArray(fields) || !
|
|
15336
|
+
if (source.hashMode !== undefined || source.format !== "toml" || !Array.isArray(fields) || !isDeepStrictEqual4(fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]) || typeof source.sha256 !== "string")
|
|
15232
15337
|
throw new Error("Codex settings witness upgrade found an unrecognized configuration witness");
|
|
15233
15338
|
if (projectNativeDiscoveryFields(preimage, "toml", fields, configPath) !== source.sha256)
|
|
15234
15339
|
throw new Error("Reviewed preimage does not explain the Codex discovery projection witness");
|
|
15235
15340
|
replaced.push(source);
|
|
15236
15341
|
}
|
|
15237
15342
|
}
|
|
15238
|
-
const next = options.agent === "claude" ? upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
|
|
15343
|
+
const next = options.agent === "claude" ? upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : options.targetCodexVersion === 3 ? upgradeCodexSettingsWitnessV3(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
|
|
15239
15344
|
const rebound = [];
|
|
15240
15345
|
for (const source of binding.sources) {
|
|
15241
15346
|
if (!replaced.includes(source)) {
|
|
@@ -15272,7 +15377,7 @@ function applyAgentIntegration(plan) {
|
|
|
15272
15377
|
const upgrade = plan.settingsWitnessUpgrade;
|
|
15273
15378
|
if (!plan.managedAgentChecks || !plan.observedPolicy?.before)
|
|
15274
15379
|
throw new Error("Invalid settings witness upgrade plan");
|
|
15275
|
-
const verified = planAgentSettingsWitnessUpgrade({ agent: upgrade.agent, reviewedPreimage: upgrade.reviewedPreimage, home: plan.managedAgentChecks.home, dataDir: plan.dataDir, expectedPolicySha256: sha3(plan.observedPolicy.before), expectedSettingsSha256: upgrade.currentSettingsSha256 });
|
|
15380
|
+
const verified = planAgentSettingsWitnessUpgrade({ agent: upgrade.agent, ...upgrade.agent === "codex" ? { targetCodexVersion: upgrade.toHashMode === "codex-settings-v3" ? 3 : 2 } : {}, reviewedPreimage: upgrade.reviewedPreimage, home: plan.managedAgentChecks.home, dataDir: plan.dataDir, expectedPolicySha256: sha3(plan.observedPolicy.before), expectedSettingsSha256: upgrade.currentSettingsSha256 });
|
|
15276
15381
|
if (JSON.stringify(verified.changes) !== JSON.stringify(plan.changes) || JSON.stringify(verified.settingsWitnessUpgrade) !== JSON.stringify(upgrade))
|
|
15277
15382
|
throw new Error("Settings witness upgrade plan changed");
|
|
15278
15383
|
provenDiscovery = verified.discoveryBefore[0];
|
|
@@ -18248,19 +18353,19 @@ function projectNativeDiscoveryFields(text2, format, fields2, path) {
|
|
|
18248
18353
|
return digest(JSON.stringify(Object.fromEntries(fields2.map((field2) => [field2, object5[field2] ?? null]))));
|
|
18249
18354
|
}
|
|
18250
18355
|
function isSupersededCodexProjection(agent, configPath, source) {
|
|
18251
|
-
return agent === "codex" && source.path === configPath && source.format === "toml" &&
|
|
18356
|
+
return agent === "codex" && source.path === configPath && source.format === "toml" && isDeepStrictEqual5(source.fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]);
|
|
18252
18357
|
}
|
|
18253
18358
|
function supersedesCodexProjection(sources, configPath) {
|
|
18254
|
-
return sources.some((source) => source.path === configPath && source.hashMode === "codex-settings-v2");
|
|
18359
|
+
return sources.some((source) => source.path === configPath && (source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3"));
|
|
18255
18360
|
}
|
|
18256
18361
|
function projected(source, changes, budget = discoveryByteBudget()) {
|
|
18257
|
-
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2") {
|
|
18362
|
+
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3") {
|
|
18258
18363
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
18259
18364
|
throw new Error("Codex settings witnesses require exact typed metadata");
|
|
18260
|
-
const current = (source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget).sha256;
|
|
18365
|
+
const current = (source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget).sha256;
|
|
18261
18366
|
if (current !== source.sha256)
|
|
18262
18367
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
18263
|
-
return changes?.has(source.path) ? (source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget) : current;
|
|
18368
|
+
return changes?.has(source.path) ? (source.hashMode === "codex-settings-v3" ? hashCodexSettingsReplacementV3 : source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget) : current;
|
|
18264
18369
|
}
|
|
18265
18370
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
|
|
18266
18371
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
@@ -18360,7 +18465,7 @@ function codexInstallationRoots(binding) {
|
|
|
18360
18465
|
});
|
|
18361
18466
|
}
|
|
18362
18467
|
function assertMarketplaceBinding(binding, source) {
|
|
18363
|
-
if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2") && (binding.agent !== "codex" || binding.method !== "reviewed" || basename9(source.path) !== "config.toml"))
|
|
18468
|
+
if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3") && (binding.agent !== "codex" || binding.method !== "reviewed" || basename9(source.path) !== "config.toml"))
|
|
18364
18469
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
18365
18470
|
if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" || basename9(source.path) !== "settings.json"))
|
|
18366
18471
|
throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
|
|
@@ -18510,10 +18615,10 @@ function resolveAgentDiscovery(options) {
|
|
|
18510
18615
|
verifyAgentDiscovery(retained);
|
|
18511
18616
|
if (!retained.sources.some((source) => source.path === canonical6(configPath) && source.format === undefined && source.fields === undefined))
|
|
18512
18617
|
unresolved("retained review is missing the full agent configuration source");
|
|
18513
|
-
if (retained.sources.some((source) => (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.path !== canonical6(configPath)))
|
|
18618
|
+
if (retained.sources.some((source) => (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.path !== canonical6(configPath)))
|
|
18514
18619
|
unresolved("retained settings witness names another configuration source");
|
|
18515
18620
|
const covered = supersedesCodexProjection(retained.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededCodexProjection(agent, canonical6(configPath), source)) : sources;
|
|
18516
|
-
if (covered.some((source) => !retained.sources.some((saved) =>
|
|
18621
|
+
if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual5(saved, source))) || [...roots].some((root2) => !retained.roots.includes(root2)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
|
|
18517
18622
|
unresolved("retained review is missing current runtime discovery coverage");
|
|
18518
18623
|
return retained;
|
|
18519
18624
|
}
|
|
@@ -18527,7 +18632,7 @@ function resolveAgentDiscovery(options) {
|
|
|
18527
18632
|
if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
|
|
18528
18633
|
throw new Error("Explicit discovery reviews require full source-file hashes");
|
|
18529
18634
|
verifyAgentDiscovery(supplied);
|
|
18530
|
-
if (review.sources.some((source) => (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.path !== canonical6(configPath)))
|
|
18635
|
+
if (review.sources.some((source) => (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.path !== canonical6(configPath)))
|
|
18531
18636
|
throw new Error("Semantic settings witnesses must name the configured Claude configuration source");
|
|
18532
18637
|
if (!review.sources.some((source) => source.path === canonical6(configPath)))
|
|
18533
18638
|
throw new Error("Discovery review must include the agent configuration source");
|
|
@@ -19505,7 +19610,7 @@ function createSkillRun(params, targetDir = process.cwd()) {
|
|
|
19505
19610
|
mkdirSync10(logsDir, { recursive: true });
|
|
19506
19611
|
mkdirSync10(exportDir, { recursive: true });
|
|
19507
19612
|
mkdirSync10(join31(root2, "tmp"), { recursive: true });
|
|
19508
|
-
const
|
|
19613
|
+
const record3 = {
|
|
19509
19614
|
id,
|
|
19510
19615
|
skill: skillName,
|
|
19511
19616
|
status: params.status ?? "running",
|
|
@@ -19523,10 +19628,10 @@ function createSkillRun(params, targetDir = process.cwd()) {
|
|
|
19523
19628
|
logsDir: toProjectRelative(targetDir, logsDir)
|
|
19524
19629
|
}
|
|
19525
19630
|
};
|
|
19526
|
-
const context = { targetDir, runDir, exportDir, logsDir, record:
|
|
19631
|
+
const context = { targetDir, runDir, exportDir, logsDir, record: record3 };
|
|
19527
19632
|
writeRunRecord(context);
|
|
19528
19633
|
writeArtifactsManifest(context, []);
|
|
19529
|
-
appendRunEvent(context, "created", { status:
|
|
19634
|
+
appendRunEvent(context, "created", { status: record3.status });
|
|
19530
19635
|
return context;
|
|
19531
19636
|
}
|
|
19532
19637
|
function completeSkillRun(context, patch) {
|
|
@@ -19576,9 +19681,9 @@ function listSkillRuns(targetDir = process.cwd(), limit = 50) {
|
|
|
19576
19681
|
if (!statSync11(dayDir).isDirectory())
|
|
19577
19682
|
continue;
|
|
19578
19683
|
for (const runId of readdirSync13(dayDir).sort().reverse()) {
|
|
19579
|
-
const
|
|
19580
|
-
if (
|
|
19581
|
-
records.push(
|
|
19684
|
+
const record3 = readRunRecord(join31(dayDir, runId));
|
|
19685
|
+
if (record3)
|
|
19686
|
+
records.push(record3);
|
|
19582
19687
|
if (records.length >= limit)
|
|
19583
19688
|
return records;
|
|
19584
19689
|
}
|
|
@@ -19590,9 +19695,9 @@ function findSkillRun(runId, targetDir = process.cwd()) {
|
|
|
19590
19695
|
if (!existsSync15(runsRoot))
|
|
19591
19696
|
return null;
|
|
19592
19697
|
for (const day of readdirSync13(runsRoot)) {
|
|
19593
|
-
const
|
|
19594
|
-
if (
|
|
19595
|
-
return
|
|
19698
|
+
const record3 = readRunRecord(join31(runsRoot, day, runId));
|
|
19699
|
+
if (record3)
|
|
19700
|
+
return record3;
|
|
19596
19701
|
}
|
|
19597
19702
|
return null;
|
|
19598
19703
|
}
|
|
@@ -19733,7 +19838,7 @@ __export(exports_external, {
|
|
|
19733
19838
|
regexes: () => exports_regexes,
|
|
19734
19839
|
regex: () => _regex,
|
|
19735
19840
|
refine: () => refine,
|
|
19736
|
-
record: () =>
|
|
19841
|
+
record: () => record3,
|
|
19737
19842
|
readonly: () => readonly,
|
|
19738
19843
|
property: () => _property,
|
|
19739
19844
|
properties: () => _properties,
|
|
@@ -35507,8 +35612,8 @@ function rewriteKeyNames(ctx) {
|
|
|
35507
35612
|
bySchema.set(entry.schema, entry);
|
|
35508
35613
|
}
|
|
35509
35614
|
const rewrites = new Map;
|
|
35510
|
-
for (const
|
|
35511
|
-
const seen = ctx.seen.get(
|
|
35615
|
+
for (const record3 of pendingRecords.get(ctx) ?? []) {
|
|
35616
|
+
const seen = ctx.seen.get(record3);
|
|
35512
35617
|
const names = (seen?.def ?? seen?.schema)?.propertyNames;
|
|
35513
35618
|
if (!names || names === true || rewrites.has(names))
|
|
35514
35619
|
continue;
|
|
@@ -35835,7 +35940,7 @@ __export(exports_schemas2, {
|
|
|
35835
35940
|
strictObject: () => strictObject,
|
|
35836
35941
|
set: () => set,
|
|
35837
35942
|
refine: () => refine,
|
|
35838
|
-
record: () =>
|
|
35943
|
+
record: () => record3,
|
|
35839
35944
|
readonly: () => readonly,
|
|
35840
35945
|
promise: () => promise,
|
|
35841
35946
|
preprocess: () => preprocess,
|
|
@@ -37005,7 +37110,7 @@ var ZodRecord = /* @__PURE__ */ $constructor("ZodRecord", (inst, def) => {
|
|
|
37005
37110
|
inst.keyType = def.keyType;
|
|
37006
37111
|
inst.valueType = def.valueType;
|
|
37007
37112
|
});
|
|
37008
|
-
function
|
|
37113
|
+
function record3(keyType, valueType, params) {
|
|
37009
37114
|
if (!valueType || !valueType._zod) {
|
|
37010
37115
|
return new ZodRecord({
|
|
37011
37116
|
type: "record",
|
|
@@ -37471,7 +37576,7 @@ var stringbool = (...args) => _stringbool({
|
|
|
37471
37576
|
}, ...args);
|
|
37472
37577
|
function json(params) {
|
|
37473
37578
|
const jsonSchema = lazy(() => {
|
|
37474
|
-
return union([string2(params), number2(), boolean2(), _null3(), array2(jsonSchema),
|
|
37579
|
+
return union([string2(params), number2(), boolean2(), _null3(), array2(jsonSchema), record3(string2(), jsonSchema)]);
|
|
37475
37580
|
});
|
|
37476
37581
|
return jsonSchema;
|
|
37477
37582
|
}
|
|
@@ -39459,12 +39564,12 @@ class RemoteWorkspaceInvitationReadError extends Error {
|
|
|
39459
39564
|
}
|
|
39460
39565
|
}
|
|
39461
39566
|
function invitationFailure(value, status) {
|
|
39462
|
-
if (!
|
|
39567
|
+
if (!record4(value) || typeof value.code !== "string" || !Object.hasOwn(invitationFailures, value.code))
|
|
39463
39568
|
return null;
|
|
39464
39569
|
const code = value.code;
|
|
39465
39570
|
return invitationFailures[code][0] === status ? code : null;
|
|
39466
39571
|
}
|
|
39467
|
-
var
|
|
39572
|
+
var record4 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
39468
39573
|
var uuid5 = (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);
|
|
39469
39574
|
var role = (v) => typeof v === "string" && ["owner", "admin", "member", "viewer"].includes(v);
|
|
39470
39575
|
var email3 = (v) => typeof v === "string" && v.length <= 254 && !/[\p{Cc}\p{Cs}\u2028\u2029\s]/u.test(v) && /^[^@]+@[^@]+\.[^@]+$/.test(v);
|
|
@@ -39473,7 +39578,7 @@ var inputFailure = () => {
|
|
|
39473
39578
|
throw new WorkspaceInvitationInputError;
|
|
39474
39579
|
};
|
|
39475
39580
|
function invitationInput(action, input2) {
|
|
39476
|
-
if (!
|
|
39581
|
+
if (!record4(input2))
|
|
39477
39582
|
return inputFailure();
|
|
39478
39583
|
const keys = {
|
|
39479
39584
|
list: ["after"],
|
|
@@ -39524,7 +39629,7 @@ function invalid2() {
|
|
|
39524
39629
|
throw new RemoteWorkspaceInvitationReadError;
|
|
39525
39630
|
}
|
|
39526
39631
|
function projection(v, organizationId) {
|
|
39527
|
-
if (!
|
|
39632
|
+
if (!record4(v) || !uuid5(v.id) || v.organizationId !== organizationId || !email3(v.email) || v.email !== v.email.trim().toLowerCase() || !role(v.role) || !Number.isInteger(v.generation) || Number(v.generation) < 1 || Number(v.generation) > 10 || typeof v.status !== "string" || !["pending", "expired", "accepted", "revoked"].includes(v.status) || !timestamp(v.expiresAt) || !timestamp(v.createdAt) || !record4(v.delivery) || typeof v.delivery.state !== "string" || !["queued", "sending", "uncertain", "provider_accepted", "failed", "cancelled"].includes(v.delivery.state) || !Number.isInteger(v.delivery.attempts) || Number(v.delivery.attempts) < 0 || Number(v.delivery.attempts) > 5)
|
|
39528
39633
|
return invalid2();
|
|
39529
39634
|
return {
|
|
39530
39635
|
id: v.id,
|
|
@@ -39539,7 +39644,7 @@ function projection(v, organizationId) {
|
|
|
39539
39644
|
};
|
|
39540
39645
|
}
|
|
39541
39646
|
function parseInvitationResult(action, value, input2, organizationId) {
|
|
39542
|
-
if (!
|
|
39647
|
+
if (!record4(value))
|
|
39543
39648
|
return invalid2();
|
|
39544
39649
|
const request = input2;
|
|
39545
39650
|
if (action === "accept") {
|
|
@@ -39572,7 +39677,7 @@ function parseInvitationResult(action, value, input2, organizationId) {
|
|
|
39572
39677
|
}
|
|
39573
39678
|
|
|
39574
39679
|
// src/lib/remote-workspace-selection.ts
|
|
39575
|
-
var
|
|
39680
|
+
var record5 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
39576
39681
|
var uuid8 = (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);
|
|
39577
39682
|
var text2 = (v, max = 1024) => typeof v === "string" && !!v.trim() && v.length <= max && !/[\p{Cc}\p{Cs}\u2028\u2029]/u.test(v);
|
|
39578
39683
|
var role2 = (v) => typeof v === "string" && ["owner", "admin", "member", "viewer"].includes(v);
|
|
@@ -39597,7 +39702,7 @@ function workspaceExpectedUserId(value) {
|
|
|
39597
39702
|
return value;
|
|
39598
39703
|
}
|
|
39599
39704
|
function workspaceContext(value) {
|
|
39600
|
-
if (!
|
|
39705
|
+
if (!record5(value) || Object.keys(value).sort().join(",") !== "membershipId,userId" || !uuid8(value.userId) || !uuid8(value.membershipId))
|
|
39601
39706
|
throw new WorkspaceContextInputError;
|
|
39602
39707
|
return { userId: value.userId, membershipId: value.membershipId };
|
|
39603
39708
|
}
|
|
@@ -39605,15 +39710,15 @@ function invalid3() {
|
|
|
39605
39710
|
throw new Error(invalidWorkspaceResult);
|
|
39606
39711
|
}
|
|
39607
39712
|
function organization(v) {
|
|
39608
|
-
if (!
|
|
39713
|
+
if (!record5(v) || !uuid8(v.id) || !text2(v.slug) || !text2(v.name))
|
|
39609
39714
|
return invalid3();
|
|
39610
39715
|
return { id: v.id, slug: v.slug, name: v.name };
|
|
39611
39716
|
}
|
|
39612
39717
|
function parseAccountWorkspaces(value) {
|
|
39613
|
-
if (!
|
|
39718
|
+
if (!record5(value) || !Array.isArray(value.workspaces) || !value.workspaces.length || value.workspaces.length > 1000)
|
|
39614
39719
|
return invalid3();
|
|
39615
39720
|
const workspaces = value.workspaces.map((v) => {
|
|
39616
|
-
if (!
|
|
39721
|
+
if (!record5(v) || !uuid8(v.membershipId) || !role2(v.role) || typeof v.current !== "boolean")
|
|
39617
39722
|
return invalid3();
|
|
39618
39723
|
return { membershipId: v.membershipId, organization: organization(v.organization), role: v.role, current: v.current };
|
|
39619
39724
|
});
|
|
@@ -39622,10 +39727,10 @@ function parseAccountWorkspaces(value) {
|
|
|
39622
39727
|
return { workspaces };
|
|
39623
39728
|
}
|
|
39624
39729
|
function parseWorkspaceIdentity(value, expectedUserId) {
|
|
39625
|
-
if (!
|
|
39730
|
+
if (!record5(value))
|
|
39626
39731
|
return invalid3();
|
|
39627
39732
|
const user = value.user;
|
|
39628
|
-
if (!
|
|
39733
|
+
if (!record5(user) || !uuid8(user.id) || !uuid8(user.membershipId) || !text2(user.email, 320) || !(user.displayName === null || text2(user.displayName)) || !role2(user.role))
|
|
39629
39734
|
return invalid3();
|
|
39630
39735
|
if (user.id !== expectedUserId)
|
|
39631
39736
|
throw new WorkspaceIdentityMismatchError;
|
|
@@ -39643,8 +39748,8 @@ function parseWorkspaceSession(value, expected) {
|
|
|
39643
39748
|
return { token: sessionToken(value.token), ...identity4 };
|
|
39644
39749
|
}
|
|
39645
39750
|
function parseWorkspaceLogin(value, expectedUserId) {
|
|
39646
|
-
const user =
|
|
39647
|
-
if (!
|
|
39751
|
+
const user = record5(value) && value.user;
|
|
39752
|
+
if (!record5(value) || !record5(user) || !uuid8(user.id))
|
|
39648
39753
|
return invalid3();
|
|
39649
39754
|
if (expectedUserId !== undefined && user.id !== expectedUserId)
|
|
39650
39755
|
throw new WorkspaceIdentityMismatchError;
|
|
@@ -39659,18 +39764,18 @@ var workspaceSelectionFailures = {
|
|
|
39659
39764
|
WORKSPACE_BUSY: [503, "Workspace is busy. Refresh before retrying."]
|
|
39660
39765
|
};
|
|
39661
39766
|
function workspaceSelectionFailure(value, status) {
|
|
39662
|
-
if (!
|
|
39767
|
+
if (!record5(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceSelectionFailures, value.code))
|
|
39663
39768
|
return null;
|
|
39664
39769
|
const code = value.code;
|
|
39665
39770
|
return workspaceSelectionFailures[code][0] === status ? code : null;
|
|
39666
39771
|
}
|
|
39667
39772
|
|
|
39668
39773
|
// src/lib/remote-workspace.ts
|
|
39669
|
-
var
|
|
39774
|
+
var record6 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
39670
39775
|
var cursor = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,512}$/.test(value);
|
|
39671
39776
|
var uuid10 = (value) => typeof value === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(value);
|
|
39672
39777
|
function workspaceMembersQuery(options = {}) {
|
|
39673
|
-
if (!
|
|
39778
|
+
if (!record6(options) || Object.keys(options).some((key) => key !== "limit" && key !== "cursor") || options.limit !== undefined && (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > 100) || options.cursor !== undefined && !cursor(options.cursor))
|
|
39674
39779
|
throw new Error("Use a roster limit from 1 to 100 and an unchanged continuation cursor.");
|
|
39675
39780
|
const query = new URLSearchParams;
|
|
39676
39781
|
if (options.limit !== undefined)
|
|
@@ -39686,7 +39791,7 @@ function timestamp2(value) {
|
|
|
39686
39791
|
return Number.isFinite(time3) && new Date(time3).toISOString().slice(0, 23) === value.slice(0, 23);
|
|
39687
39792
|
}
|
|
39688
39793
|
function parseMember(row, fail) {
|
|
39689
|
-
if (!
|
|
39794
|
+
if (!record6(row) || !uuid10(row.membershipId) || !uuid10(row.userId) || typeof row.email !== "string" || !row.email || !(row.displayName === null || typeof row.displayName === "string") || !isRole(row.role) || !timestamp2(row.createdAt))
|
|
39690
39795
|
return fail();
|
|
39691
39796
|
return {
|
|
39692
39797
|
membershipId: row.membershipId,
|
|
@@ -39706,7 +39811,7 @@ class WorkspaceMemberInputError extends Error {
|
|
|
39706
39811
|
}
|
|
39707
39812
|
}
|
|
39708
39813
|
function mutationInput(membershipId, input2, roleChange) {
|
|
39709
|
-
if (typeof membershipId !== "string" || !uuid10(membershipId) || membershipId !== membershipId.toLowerCase() || !
|
|
39814
|
+
if (typeof membershipId !== "string" || !uuid10(membershipId) || membershipId !== membershipId.toLowerCase() || !record6(input2) || Object.keys(input2).sort().join(",") !== (roleChange ? "expectedRole,role" : "expectedRole"))
|
|
39710
39815
|
throw new WorkspaceMemberInputError;
|
|
39711
39816
|
const expectedRole = input2.expectedRole, role3 = roleChange ? input2.role : undefined;
|
|
39712
39817
|
if (!isRole(expectedRole) || roleChange && !isRole(role3))
|
|
@@ -39726,7 +39831,7 @@ function parseWorkspaceMemberRoleResult(value, membershipId, role3) {
|
|
|
39726
39831
|
const fail = () => {
|
|
39727
39832
|
throw new Error(invalidMemberResult);
|
|
39728
39833
|
};
|
|
39729
|
-
if (!
|
|
39834
|
+
if (!record6(value) || !uuid10(value.organizationId) || typeof value.changed !== "boolean")
|
|
39730
39835
|
return fail();
|
|
39731
39836
|
const member = parseMember(value.member, fail);
|
|
39732
39837
|
if (member.membershipId !== membershipId || member.role !== role3)
|
|
@@ -39734,7 +39839,7 @@ function parseWorkspaceMemberRoleResult(value, membershipId, role3) {
|
|
|
39734
39839
|
return { organizationId: value.organizationId, member, changed: value.changed };
|
|
39735
39840
|
}
|
|
39736
39841
|
function parseWorkspaceMemberRemovalResult(value, membershipId) {
|
|
39737
|
-
if (!
|
|
39842
|
+
if (!record6(value) || !uuid10(value.organizationId) || value.membershipId !== membershipId || value.removed !== true || typeof value.alreadyRemoved !== "boolean")
|
|
39738
39843
|
throw new Error(invalidMemberResult);
|
|
39739
39844
|
return { organizationId: value.organizationId, membershipId, removed: true, alreadyRemoved: value.alreadyRemoved };
|
|
39740
39845
|
}
|
|
@@ -39751,7 +39856,7 @@ var workspaceMemberFailures = {
|
|
|
39751
39856
|
MEMBERSHIP_BUSY: [503, "Membership is busy. Refresh the roster before another action."]
|
|
39752
39857
|
};
|
|
39753
39858
|
function workspaceMemberFailure(value, status) {
|
|
39754
|
-
if (!
|
|
39859
|
+
if (!record6(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceMemberFailures, value.code))
|
|
39755
39860
|
return null;
|
|
39756
39861
|
const code = value.code;
|
|
39757
39862
|
return workspaceMemberFailures[code][0] === status ? code : null;
|
|
@@ -39760,7 +39865,7 @@ function parseWorkspaceMembersPage(value) {
|
|
|
39760
39865
|
const fail = () => {
|
|
39761
39866
|
throw new Error("The server returned an invalid workspace roster.");
|
|
39762
39867
|
};
|
|
39763
|
-
if (!
|
|
39868
|
+
if (!record6(value) || !uuid10(value.organizationId) || !Array.isArray(value.members) || value.members.length > 100 || !(value.nextCursor === null || cursor(value.nextCursor)) || !value.members.length && value.nextCursor !== null)
|
|
39764
39869
|
return fail();
|
|
39765
39870
|
const members2 = value.members.map((row) => parseMember(row, fail));
|
|
39766
39871
|
if (new Set(members2.map((row) => row.membershipId)).size !== members2.length)
|
|
@@ -39836,44 +39941,44 @@ function getApiUrl(action, env = process.env, options = {}) {
|
|
|
39836
39941
|
// src/lib/remote-run-contract.ts
|
|
39837
39942
|
var REMOTE_SKILL_RUN_CONTRACT_VERSION = 1;
|
|
39838
39943
|
function normalizeRemoteSkillRunContract(payload, fallbackSkill) {
|
|
39839
|
-
const
|
|
39944
|
+
const record7 = isRecord4(payload) ? payload : {};
|
|
39840
39945
|
return {
|
|
39841
39946
|
contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
|
|
39842
|
-
...pickString(
|
|
39843
|
-
skill: pickStringValue(
|
|
39844
|
-
...pickString(
|
|
39845
|
-
...pickString(
|
|
39846
|
-
...pickNumber(
|
|
39847
|
-
...pickString(
|
|
39848
|
-
...pickString(
|
|
39849
|
-
...pickString(
|
|
39850
|
-
...pickString(
|
|
39851
|
-
...pickNumber(
|
|
39852
|
-
...pickString(
|
|
39853
|
-
...hasOwn(
|
|
39854
|
-
...pickString(
|
|
39855
|
-
...pickString(
|
|
39856
|
-
...pickString(
|
|
39857
|
-
...pickString(
|
|
39858
|
-
...hasOwn(
|
|
39947
|
+
...pickString(record7, "id"),
|
|
39948
|
+
skill: pickStringValue(record7, "skill") ?? fallbackSkill,
|
|
39949
|
+
...pickString(record7, "requestedSlug"),
|
|
39950
|
+
...pickString(record7, "status"),
|
|
39951
|
+
...pickNumber(record7, "exitCode"),
|
|
39952
|
+
...pickString(record7, "correlationId"),
|
|
39953
|
+
...pickString(record7, "createdAt"),
|
|
39954
|
+
...pickString(record7, "startedAt"),
|
|
39955
|
+
...pickString(record7, "completedAt"),
|
|
39956
|
+
...pickNumber(record7, "durationMs"),
|
|
39957
|
+
...pickString(record7, "outputType"),
|
|
39958
|
+
...hasOwn(record7, "outputPreview") ? { outputPreview: record7.outputPreview } : {},
|
|
39959
|
+
...pickString(record7, "errorCode"),
|
|
39960
|
+
...pickString(record7, "errorMessage"),
|
|
39961
|
+
...pickString(record7, "error"),
|
|
39962
|
+
...pickString(record7, "code"),
|
|
39963
|
+
...hasOwn(record7, "details") ? { details: record7.details } : {}
|
|
39859
39964
|
};
|
|
39860
39965
|
}
|
|
39861
39966
|
function isRecord4(value) {
|
|
39862
39967
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
39863
39968
|
}
|
|
39864
|
-
function hasOwn(
|
|
39865
|
-
return Object.prototype.hasOwnProperty.call(
|
|
39969
|
+
function hasOwn(record7, key) {
|
|
39970
|
+
return Object.prototype.hasOwnProperty.call(record7, key);
|
|
39866
39971
|
}
|
|
39867
|
-
function pickString(
|
|
39868
|
-
const value = pickStringValue(
|
|
39972
|
+
function pickString(record7, key) {
|
|
39973
|
+
const value = pickStringValue(record7, key);
|
|
39869
39974
|
return value === undefined ? {} : { [key]: value };
|
|
39870
39975
|
}
|
|
39871
|
-
function pickStringValue(
|
|
39872
|
-
const value =
|
|
39976
|
+
function pickStringValue(record7, key) {
|
|
39977
|
+
const value = record7[key];
|
|
39873
39978
|
return typeof value === "string" ? value : undefined;
|
|
39874
39979
|
}
|
|
39875
|
-
function pickNumber(
|
|
39876
|
-
const value =
|
|
39980
|
+
function pickNumber(record7, key) {
|
|
39981
|
+
const value = record7[key];
|
|
39877
39982
|
return typeof value === "number" && Number.isFinite(value) ? { [key]: value } : {};
|
|
39878
39983
|
}
|
|
39879
39984
|
|
|
@@ -40093,11 +40198,11 @@ var permissionNames = [
|
|
|
40093
40198
|
"executionGrantsWrite",
|
|
40094
40199
|
"executionGrantsResolve"
|
|
40095
40200
|
];
|
|
40096
|
-
var
|
|
40201
|
+
var record7 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
40097
40202
|
function parseSkillsAccess(value) {
|
|
40098
40203
|
if (value === undefined)
|
|
40099
40204
|
return {};
|
|
40100
|
-
if (!
|
|
40205
|
+
if (!record7(value))
|
|
40101
40206
|
throw new Error("Invalid Skills permission contract");
|
|
40102
40207
|
const result = {};
|
|
40103
40208
|
if (value.scopes !== undefined) {
|
|
@@ -40106,7 +40211,7 @@ function parseSkillsAccess(value) {
|
|
|
40106
40211
|
result.scopes = [...value.scopes];
|
|
40107
40212
|
}
|
|
40108
40213
|
if (value.permissions !== undefined) {
|
|
40109
|
-
if (!
|
|
40214
|
+
if (!record7(value.permissions))
|
|
40110
40215
|
throw new Error("Invalid Skills permission contract");
|
|
40111
40216
|
result.permissions = {};
|
|
40112
40217
|
for (const name of permissionNames) {
|
|
@@ -41003,13 +41108,13 @@ class RemoteSkillsClient {
|
|
|
41003
41108
|
return normalizeUpdatedSincePage(await response.json());
|
|
41004
41109
|
}
|
|
41005
41110
|
}
|
|
41006
|
-
function requireOptionalString(
|
|
41007
|
-
if (
|
|
41111
|
+
function requireOptionalString(record8, field2) {
|
|
41112
|
+
if (record8[field2] === undefined)
|
|
41008
41113
|
return;
|
|
41009
|
-
if (typeof
|
|
41114
|
+
if (typeof record8[field2] !== "string") {
|
|
41010
41115
|
throw new Error(`Remote payload did not match the expected contract (${field2} must be a string when present)`);
|
|
41011
41116
|
}
|
|
41012
|
-
return
|
|
41117
|
+
return record8[field2];
|
|
41013
41118
|
}
|
|
41014
41119
|
var INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
|
|
41015
41120
|
function isVersionRecord(value) {
|
|
@@ -41032,19 +41137,19 @@ function normalizePin(entry) {
|
|
|
41032
41137
|
if (!entry || typeof entry !== "object") {
|
|
41033
41138
|
throw new Error("Remote pin payload did not match the expected contract (expected an object)");
|
|
41034
41139
|
}
|
|
41035
|
-
const
|
|
41036
|
-
const slug2 = typeof
|
|
41140
|
+
const record8 = entry;
|
|
41141
|
+
const slug2 = typeof record8.slug === "string" && record8.slug.trim() ? record8.slug.trim() : undefined;
|
|
41037
41142
|
if (!slug2) {
|
|
41038
41143
|
throw new Error("Remote pin payload did not match the expected contract (missing slug)");
|
|
41039
41144
|
}
|
|
41040
41145
|
let metadata;
|
|
41041
|
-
if (
|
|
41042
|
-
if (!
|
|
41146
|
+
if (record8.metadata !== undefined) {
|
|
41147
|
+
if (!record8.metadata || typeof record8.metadata !== "object" || Array.isArray(record8.metadata)) {
|
|
41043
41148
|
throw new Error("Remote pin payload did not match the expected contract (metadata must be a JSON object when present)");
|
|
41044
41149
|
}
|
|
41045
|
-
metadata =
|
|
41150
|
+
metadata = record8.metadata;
|
|
41046
41151
|
}
|
|
41047
|
-
const pinnedAt = requireOptionalString(
|
|
41152
|
+
const pinnedAt = requireOptionalString(record8, "pinnedAt");
|
|
41048
41153
|
return {
|
|
41049
41154
|
slug: slug2,
|
|
41050
41155
|
...pinnedAt !== undefined ? { pinnedAt } : {},
|
|
@@ -41061,16 +41166,16 @@ function normalizeSkillSummary(entry) {
|
|
|
41061
41166
|
if (!entry || typeof entry !== "object") {
|
|
41062
41167
|
throw new Error("Remote skill payload did not match the expected contract (expected an object)");
|
|
41063
41168
|
}
|
|
41064
|
-
const
|
|
41065
|
-
const slug2 = typeof
|
|
41169
|
+
const record8 = entry;
|
|
41170
|
+
const slug2 = typeof record8.slug === "string" && record8.slug.trim() ? record8.slug.trim() : undefined;
|
|
41066
41171
|
if (!slug2) {
|
|
41067
41172
|
throw new Error("Remote skill payload did not match the expected contract (missing slug)");
|
|
41068
41173
|
}
|
|
41069
41174
|
return {
|
|
41070
41175
|
slug: slug2,
|
|
41071
|
-
...requireOptionalString(
|
|
41072
|
-
...requireOptionalString(
|
|
41073
|
-
...requireOptionalString(
|
|
41176
|
+
...requireOptionalString(record8, "name") !== undefined ? { name: requireOptionalString(record8, "name") } : {},
|
|
41177
|
+
...requireOptionalString(record8, "version") !== undefined ? { version: requireOptionalString(record8, "version") } : {},
|
|
41178
|
+
...requireOptionalString(record8, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record8, "updatedAt") } : {}
|
|
41074
41179
|
};
|
|
41075
41180
|
}
|
|
41076
41181
|
function normalizeSkillSummaryList(payload) {
|
|
@@ -41127,12 +41232,12 @@ function normalizeUpdatedSincePage(payload) {
|
|
|
41127
41232
|
if (!payload || typeof payload !== "object") {
|
|
41128
41233
|
throw new Error("Updated-since payload did not match the expected contract (expected an object)");
|
|
41129
41234
|
}
|
|
41130
|
-
const
|
|
41131
|
-
if (!Array.isArray(
|
|
41235
|
+
const record8 = payload;
|
|
41236
|
+
if (!Array.isArray(record8.skills)) {
|
|
41132
41237
|
throw new Error("Updated-since payload did not match the expected contract (missing skills array)");
|
|
41133
41238
|
}
|
|
41134
|
-
const skills =
|
|
41135
|
-
const nextCursor =
|
|
41239
|
+
const skills = record8.skills.map(normalizeSkillSummary);
|
|
41240
|
+
const nextCursor = record8.nextCursor === undefined || record8.nextCursor === null ? null : record8.nextCursor;
|
|
41136
41241
|
if (nextCursor !== null && typeof nextCursor !== "string") {
|
|
41137
41242
|
throw new Error("Updated-since payload did not match the expected contract (nextCursor must be a string or absent)");
|
|
41138
41243
|
}
|
|
@@ -41371,8 +41476,8 @@ function revisionIdOf(content) {
|
|
|
41371
41476
|
const canonical6 = JSON.stringify(canonicalContent);
|
|
41372
41477
|
return createHash21("sha256").update(canonical6).digest("hex");
|
|
41373
41478
|
}
|
|
41374
|
-
function revisionIdOfRecord(
|
|
41375
|
-
return revisionIdOf(
|
|
41479
|
+
function revisionIdOfRecord(record8) {
|
|
41480
|
+
return revisionIdOf(record8);
|
|
41376
41481
|
}
|
|
41377
41482
|
// src/lib/pull.ts
|
|
41378
41483
|
import { existsSync as existsSync17, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readFileSync as readFileSync21, renameSync as renameSync6, rmSync as rmSync5, writeFileSync as writeFileSync11 } from "fs";
|
|
@@ -41748,16 +41853,16 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
|
|
|
41748
41853
|
}
|
|
41749
41854
|
return { path: target, created };
|
|
41750
41855
|
}
|
|
41751
|
-
function writePullMarker(dir,
|
|
41856
|
+
function writePullMarker(dir, record8) {
|
|
41752
41857
|
const marker = {
|
|
41753
41858
|
managedBy: "@hasna/skills",
|
|
41754
|
-
skill:
|
|
41755
|
-
source:
|
|
41756
|
-
...
|
|
41757
|
-
...
|
|
41758
|
-
...
|
|
41759
|
-
...
|
|
41760
|
-
...
|
|
41859
|
+
skill: record8.skill,
|
|
41860
|
+
source: record8.source ?? "pull",
|
|
41861
|
+
...record8.version ? { version: record8.version } : {},
|
|
41862
|
+
...record8.contentHash ? { contentHash: record8.contentHash } : {},
|
|
41863
|
+
...record8.sourceCommit ? { sourceCommit: record8.sourceCommit } : {},
|
|
41864
|
+
...record8.signature ? { signature: record8.signature } : {},
|
|
41865
|
+
...record8.revisionId ? { revisionId: record8.revisionId } : {},
|
|
41761
41866
|
syncedAt: new Date().toISOString()
|
|
41762
41867
|
};
|
|
41763
41868
|
writeFileSync11(join33(dir, PULL_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
|
|
@@ -41772,19 +41877,19 @@ async function safeMeta(client2, slug2) {
|
|
|
41772
41877
|
}
|
|
41773
41878
|
if (!raw || typeof raw !== "object")
|
|
41774
41879
|
return null;
|
|
41775
|
-
const
|
|
41776
|
-
const kind =
|
|
41777
|
-
const tags = Array.isArray(
|
|
41880
|
+
const record8 = raw;
|
|
41881
|
+
const kind = record8.kind === "instruction" || record8.kind === "executable" ? record8.kind : undefined;
|
|
41882
|
+
const tags = Array.isArray(record8.tags) ? record8.tags.filter((tag) => typeof tag === "string" && tag.trim().length > 0) : undefined;
|
|
41778
41883
|
return {
|
|
41779
|
-
...str(
|
|
41780
|
-
...str(
|
|
41781
|
-
...str(
|
|
41884
|
+
...str(record8.displayName) ? { displayName: str(record8.displayName) } : {},
|
|
41885
|
+
...str(record8.description) ? { description: str(record8.description) } : {},
|
|
41886
|
+
...str(record8.category) ? { category: str(record8.category) } : {},
|
|
41782
41887
|
...tags && tags.length ? { tags } : {},
|
|
41783
|
-
...str(
|
|
41888
|
+
...str(record8.version) ? { version: str(record8.version) } : {},
|
|
41784
41889
|
...kind ? { kind } : {},
|
|
41785
|
-
...REVISION_ID_PATTERN.test(str(
|
|
41786
|
-
...typeof
|
|
41787
|
-
...str(
|
|
41890
|
+
...REVISION_ID_PATTERN.test(str(record8.revisionId) ?? "") ? { revisionId: str(record8.revisionId) } : {},
|
|
41891
|
+
...typeof record8.skillMd === "string" && record8.skillMd.length > 0 ? { skillMd: record8.skillMd } : {},
|
|
41892
|
+
...str(record8.publishedSource) ? { publishedSource: str(record8.publishedSource) } : {}
|
|
41788
41893
|
};
|
|
41789
41894
|
}
|
|
41790
41895
|
function pickCorpusOptions(options) {
|
|
@@ -41793,8 +41898,8 @@ function pickCorpusOptions(options) {
|
|
|
41793
41898
|
function extractSlug(entry) {
|
|
41794
41899
|
if (!entry || typeof entry !== "object")
|
|
41795
41900
|
return;
|
|
41796
|
-
const
|
|
41797
|
-
return str(
|
|
41901
|
+
const record8 = entry;
|
|
41902
|
+
return str(record8.slug) ?? str(record8.name);
|
|
41798
41903
|
}
|
|
41799
41904
|
function dedupe(values) {
|
|
41800
41905
|
return [...new Set(values)];
|
|
@@ -41851,7 +41956,7 @@ class RemoteInvitationEmailUnconfirmedError extends Error {
|
|
|
41851
41956
|
this.name = "RemoteInvitationEmailUnconfirmedError";
|
|
41852
41957
|
}
|
|
41853
41958
|
}
|
|
41854
|
-
var
|
|
41959
|
+
var record8 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
41855
41960
|
var uuid11 = (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);
|
|
41856
41961
|
function invitationEmailIds(invitationId, challengeId) {
|
|
41857
41962
|
if (!uuid11(invitationId) || !uuid11(challengeId))
|
|
@@ -41860,7 +41965,7 @@ function invitationEmailIds(invitationId, challengeId) {
|
|
|
41860
41965
|
}
|
|
41861
41966
|
function invitationEmailInput(action, input2) {
|
|
41862
41967
|
const keys = ["invitationId", "token", "challengeId", "confirm", ...action === "accept" ? ["code"] : []];
|
|
41863
|
-
if (!
|
|
41968
|
+
if (!record8(input2) || Object.keys(input2).length !== keys.length || keys.some((key) => !Object.hasOwn(input2, key)))
|
|
41864
41969
|
throw new InvitationEmailInputError;
|
|
41865
41970
|
const value = { ...input2 };
|
|
41866
41971
|
const ids = invitationEmailIds(value.invitationId, value.challengeId);
|
|
@@ -41889,12 +41994,12 @@ async function requestInvitationEmail(origin, action, input2) {
|
|
|
41889
41994
|
signal: AbortSignal.timeout(15000)
|
|
41890
41995
|
});
|
|
41891
41996
|
const parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readBoundedResponse(response, 4096)));
|
|
41892
|
-
if (!response.ok &&
|
|
41997
|
+
if (!response.ok && record8(parsed) && typeof parsed.code === "string" && Object.hasOwn(refusals, parsed.code)) {
|
|
41893
41998
|
const code = parsed.code;
|
|
41894
41999
|
if (response.status === refusals[code][0])
|
|
41895
42000
|
throw new RemoteInvitationEmailError(code);
|
|
41896
42001
|
}
|
|
41897
|
-
if (!
|
|
42002
|
+
if (!record8(parsed))
|
|
41898
42003
|
throw new RemoteInvitationEmailUnconfirmedError(action);
|
|
41899
42004
|
if (action === "challenge" && response.status === 202 && parsed.challengeId === value.challengeId && parsed.expiresIn === 600 && typeof parsed.message === "string" && parsed.message.length <= 256) {
|
|
41900
42005
|
return { challengeId: value.challengeId, message: "If this invitation is eligible, a verification code will arrive. Delivery is not confirmed.", expiresIn: 600 };
|
|
@@ -41954,8 +42059,8 @@ var invalid4 = () => {
|
|
|
41954
42059
|
};
|
|
41955
42060
|
var 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);
|
|
41956
42061
|
var hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v);
|
|
41957
|
-
var
|
|
41958
|
-
var exact = (v, keys) =>
|
|
42062
|
+
var record9 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
42063
|
+
var exact = (v, keys) => record9(v) && Object.keys(v).sort().join(",") === keys.sort().join(",");
|
|
41959
42064
|
var date5 = (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));
|
|
41960
42065
|
var publicationSha256 = (bytes) => createHash22("sha256").update(bytes).digest("hex");
|
|
41961
42066
|
function checkedPublicationDeclaration(value) {
|
|
@@ -41963,7 +42068,7 @@ function checkedPublicationDeclaration(value) {
|
|
|
41963
42068
|
return bad();
|
|
41964
42069
|
try {
|
|
41965
42070
|
const manifest = JSON.parse(value.manifestText);
|
|
41966
|
-
if (!
|
|
42071
|
+
if (!record9(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash3(manifest.provenance?.content_hash))
|
|
41967
42072
|
return bad();
|
|
41968
42073
|
} catch {
|
|
41969
42074
|
return bad();
|
|
@@ -42021,7 +42126,7 @@ async function boundedJson(url2, init, token, mutation, budget2 = 15000, signal)
|
|
|
42021
42126
|
return invalid4();
|
|
42022
42127
|
}
|
|
42023
42128
|
if (!response.ok) {
|
|
42024
|
-
const code =
|
|
42129
|
+
const code = record9(body) && typeof body.code === "string" && Object.hasOwn(failures2, body.code) ? body.code : null;
|
|
42025
42130
|
if (code && failures2[code][0] === response.status)
|
|
42026
42131
|
throw new PrivatePublicationError(code, failures2[code][1], mutation && code === "PUBLICATION_UNCERTAIN", response.status);
|
|
42027
42132
|
throw new PrivatePublicationError("PUBLICATION_REQUEST_FAILED", "The publication request was refused. Inspect its status before retrying.", mutation && response.status >= 500, response.status);
|
|
@@ -42076,8 +42181,8 @@ class RemotePrivatePublicationsClient {
|
|
|
42076
42181
|
if (options.timeoutMs !== undefined && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 1 || options.timeoutMs > 15000))
|
|
42077
42182
|
return bad();
|
|
42078
42183
|
const response = await boundedJson(skillsApiRequestUrl(this.apiOrigin, "/api/v1/capabilities"), {}, this.#token, false, options.timeoutMs, options.signal);
|
|
42079
|
-
const p =
|
|
42080
|
-
if (!
|
|
42184
|
+
const p = record9(response) && response.privatePublishing;
|
|
42185
|
+
if (!record9(response) || response.contractVersion !== 1 || response.apiVersion !== 1 || !exact(p, ["contractVersion", "enabled", "authentication", "maxArchiveBytes", "uploadMaxTtlSeconds", "executionEnabled"]) || p.contractVersion !== 1 || typeof p.enabled !== "boolean" || p.authentication !== "interactive-session" || p.maxArchiveBytes !== PRIVATE_PUBLICATION_MAX_BYTES || p.uploadMaxTtlSeconds !== 300 || typeof p.executionEnabled !== "boolean")
|
|
42081
42186
|
throw new PrivatePublicationError("PUBLICATION_CONTRACT_UNAVAILABLE", "This server does not support the hosted private publication contract.");
|
|
42082
42187
|
return Object.freeze({ ...p });
|
|
42083
42188
|
}
|
|
@@ -42093,7 +42198,7 @@ class RemotePrivatePublicationsClient {
|
|
|
42093
42198
|
async#view(path, method, skillId, intentId, declaration, options = {}) {
|
|
42094
42199
|
const value = await boundedJson(path, { method, ...method === "GET" ? {} : { body: JSON.stringify(declaration ?? {}) } }, this.#token, method !== "GET", options.timeoutMs, options.signal);
|
|
42095
42200
|
try {
|
|
42096
|
-
if (!
|
|
42201
|
+
if (!record9(value) || !Object.keys(value).every((k) => k === "upload" || k === "changed") || value.changed !== undefined && typeof value.changed !== "boolean")
|
|
42097
42202
|
return invalid4();
|
|
42098
42203
|
return checkedPublicationView(value.upload, skillId, intentId, declaration);
|
|
42099
42204
|
} catch (error61) {
|
|
@@ -42256,10 +42361,10 @@ async function requestAuthApi(instance, path, options) {
|
|
|
42256
42361
|
const text3 = await res.text();
|
|
42257
42362
|
const body = text3 ? parseJsonBody(text3) : {};
|
|
42258
42363
|
if (!res.ok) {
|
|
42259
|
-
const
|
|
42260
|
-
const detail = typeof
|
|
42261
|
-
const error61 = typeof
|
|
42262
|
-
const code = typeof
|
|
42364
|
+
const record10 = isRecord6(body) ? body : {};
|
|
42365
|
+
const detail = typeof record10.detail === "string" ? record10.detail : undefined;
|
|
42366
|
+
const error61 = typeof record10.error === "string" ? record10.error : undefined;
|
|
42367
|
+
const code = typeof record10.code === "string" ? record10.code : undefined;
|
|
42263
42368
|
throw new HostedApiError(detail || error61 || `${res.status} ${res.statusText}`, {
|
|
42264
42369
|
status: res.status,
|
|
42265
42370
|
code,
|
|
@@ -44068,7 +44173,7 @@ class SkillsPostgresSyncStore {
|
|
|
44068
44173
|
}
|
|
44069
44174
|
async upsertRecords(records) {
|
|
44070
44175
|
let count = 0;
|
|
44071
|
-
for (const
|
|
44176
|
+
for (const record10 of records) {
|
|
44072
44177
|
await this.client.query([
|
|
44073
44178
|
"INSERT INTO skills_sync_records",
|
|
44074
44179
|
"(scope, kind, id, updated_at, deleted_at, source, payload)",
|
|
@@ -44079,13 +44184,13 @@ class SkillsPostgresSyncStore {
|
|
|
44079
44184
|
"source = EXCLUDED.source,",
|
|
44080
44185
|
"payload = EXCLUDED.payload"
|
|
44081
44186
|
].join(" "), [
|
|
44082
|
-
|
|
44083
|
-
|
|
44084
|
-
|
|
44085
|
-
|
|
44086
|
-
|
|
44087
|
-
|
|
44088
|
-
JSON.stringify(
|
|
44187
|
+
record10.scope,
|
|
44188
|
+
record10.kind,
|
|
44189
|
+
record10.id,
|
|
44190
|
+
record10.updatedAt,
|
|
44191
|
+
record10.deletedAt ?? null,
|
|
44192
|
+
record10.source ?? null,
|
|
44193
|
+
JSON.stringify(record10.payload)
|
|
44089
44194
|
]);
|
|
44090
44195
|
count += 1;
|
|
44091
44196
|
}
|
|
@@ -45489,6 +45594,7 @@ export {
|
|
|
45489
45594
|
validateCron,
|
|
45490
45595
|
validateBlogArticleRunOptions,
|
|
45491
45596
|
uploadSkillsSnapshotFilesToS3,
|
|
45597
|
+
upgradeCodexSettingsWitnessV3,
|
|
45492
45598
|
upgradeCodexSettingsWitness,
|
|
45493
45599
|
upgradeClaudeSettingsWitness,
|
|
45494
45600
|
updateSkillRun,
|
|
@@ -45674,6 +45780,7 @@ export {
|
|
|
45674
45780
|
captureDiscoveryPathSources,
|
|
45675
45781
|
captureDiscoveryDirectories,
|
|
45676
45782
|
captureDiscoveryByteSources,
|
|
45783
|
+
captureCodexSettingsV3,
|
|
45677
45784
|
captureCodexSettingsV2,
|
|
45678
45785
|
captureCodexSettings,
|
|
45679
45786
|
captureCodexNativeSkillCatalog,
|