@hasna/skills 0.10.26 → 0.10.28
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 +29 -0
- package/bin/index.js +438 -326
- package/bin/mcp.js +265 -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 +327 -218
- 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 +424 -317
- 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.28",
|
|
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,25 @@ 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", "personality"] : 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 (key === "personality")
|
|
14060
|
+
need4(typeof value === "string" && ["none", "friendly", "pragmatic"].includes(value));
|
|
14061
|
+
else if (version === 3 && key !== "model_verbosity") {
|
|
14062
|
+
need4(typeof value === "string" && value.length <= 128 && !/[\x00-\x1f\x7f]/.test(value));
|
|
14063
|
+
if (key !== "service_tier")
|
|
14064
|
+
need4(value.length > 0);
|
|
14065
|
+
} else
|
|
13981
14066
|
need4(typeof value === "string" && (key === "model_reasoning_effort" ? EFFORT2.has(value) : VERBOSITY2.has(value)));
|
|
13982
14067
|
delete target[key];
|
|
13983
14068
|
}
|
|
13984
14069
|
}
|
|
13985
|
-
function settingsDigest2(text2) {
|
|
14070
|
+
function settingsDigest2(text2, version = 2) {
|
|
13986
14071
|
let config;
|
|
13987
14072
|
try {
|
|
13988
14073
|
config = Bun.TOML.parse(text2);
|
|
@@ -13990,8 +14075,9 @@ function settingsDigest2(text2) {
|
|
|
13990
14075
|
throw new Error("Invalid Codex settings witness");
|
|
13991
14076
|
}
|
|
13992
14077
|
need4(isRecord3(config));
|
|
13993
|
-
|
|
13994
|
-
|
|
14078
|
+
const projected = version === 3 ? projectRegularCodexMcp(config, text2) : { config, numericSource: text2 };
|
|
14079
|
+
normalize3(projected.config, version);
|
|
14080
|
+
return sha2(`hasna.skills.codex-settings.v${version}\x00${JSON.stringify([canonical4(projected.config), numericTokens2(projected.numericSource)])}`);
|
|
13995
14081
|
}
|
|
13996
14082
|
function hashCodexSettingsReplacementV2(text2, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
13997
14083
|
need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
|
|
@@ -14015,10 +14101,29 @@ function upgradeCodexSettingsWitness(previous, reviewedSettingsPath) {
|
|
|
14015
14101
|
throw new Error("Codex non-preference settings changed; explicit discovery review required");
|
|
14016
14102
|
return { path: previous.path, hashMode: "codex-settings-v2", sha256: sha2562 };
|
|
14017
14103
|
}
|
|
14104
|
+
function hashCodexSettingsReplacementV3(text2, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
14105
|
+
need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
|
|
14106
|
+
budget.remaining -= Buffer.byteLength(text2);
|
|
14107
|
+
return settingsDigest2(text2, 3);
|
|
14108
|
+
}
|
|
14109
|
+
function captureCodexSettingsV3(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
14110
|
+
return { path, hashMode: "codex-settings-v3", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget, "config.toml"), 3) };
|
|
14111
|
+
}
|
|
14112
|
+
function upgradeCodexSettingsWitnessV3(previous, reviewedSettingsPath) {
|
|
14113
|
+
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));
|
|
14114
|
+
const budget = { remaining: 2 * 1024 * 1024 };
|
|
14115
|
+
const before = readNativeSettingsWitnessFile(reviewedSettingsPath, budget, "config.toml"), current = readNativeSettingsWitnessFile(previous.path, budget, "config.toml");
|
|
14116
|
+
const original = previous.hashMode === "codex-settings-v2" ? settingsDigest2(before) : previous.hashMode === "codex-settings-v1" ? hashCodexSettingsReplacement(before) : sha2(before);
|
|
14117
|
+
need4(original === previous.sha256);
|
|
14118
|
+
const sha2562 = settingsDigest2(current, 3);
|
|
14119
|
+
if (settingsDigest2(before, 3) !== sha2562)
|
|
14120
|
+
throw new Error("Codex settings outside the reviewed V3 contract changed; explicit discovery review required");
|
|
14121
|
+
return { path: previous.path, hashMode: "codex-settings-v3", sha256: sha2562 };
|
|
14122
|
+
}
|
|
14018
14123
|
|
|
14019
14124
|
// src/lib/agent-integration.ts
|
|
14020
14125
|
import { createHash as createHash12, randomUUID as randomUUID2 } from "crypto";
|
|
14021
|
-
import { isDeepStrictEqual as
|
|
14126
|
+
import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
|
|
14022
14127
|
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
14128
|
import { dirname as dirname11, join as join17, resolve as resolve10, relative as relative5, isAbsolute as isAbsolute11, sep as sep5 } from "path";
|
|
14024
14129
|
import { homedir as homedir2 } from "os";
|
|
@@ -14147,7 +14252,7 @@ function isOwnedCliBridge(path, expectedPaths) {
|
|
|
14147
14252
|
}
|
|
14148
14253
|
|
|
14149
14254
|
// src/lib/agent-codex.ts
|
|
14150
|
-
import { isDeepStrictEqual as
|
|
14255
|
+
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
14151
14256
|
var CODEX_SKILL_CONFIG_SECTIONS = /^\[\[skills\.config\]\][^\n]*(?:\n(?!\s*\[)[^\n]*)*/gm;
|
|
14152
14257
|
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
14258
|
function splitTopLevel(value, delimiter) {
|
|
@@ -14278,7 +14383,7 @@ function normalizeCodexInlinePathConfig(text2) {
|
|
|
14278
14383
|
const expectedWithoutConfig = structuredClone(before);
|
|
14279
14384
|
delete expectedWithoutConfig.skills.config;
|
|
14280
14385
|
try {
|
|
14281
|
-
if (
|
|
14386
|
+
if (isDeepStrictEqual3(Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, "")), expectedWithoutConfig))
|
|
14282
14387
|
return text2;
|
|
14283
14388
|
} catch {}
|
|
14284
14389
|
const matches = [];
|
|
@@ -14331,7 +14436,7 @@ function normalizeCodexInlinePathConfig(text2) {
|
|
|
14331
14436
|
try {
|
|
14332
14437
|
const after = Bun.TOML.parse(candidate);
|
|
14333
14438
|
const expected = structuredClone(before);
|
|
14334
|
-
if (
|
|
14439
|
+
if (isDeepStrictEqual3(after, expected))
|
|
14335
14440
|
matches.push(candidate);
|
|
14336
14441
|
} catch {}
|
|
14337
14442
|
}
|
|
@@ -14347,11 +14452,11 @@ function assertCodexPathConfigEditable(text2) {
|
|
|
14347
14452
|
delete expected.skills.config;
|
|
14348
14453
|
try {
|
|
14349
14454
|
const withoutSections = Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, ""));
|
|
14350
|
-
if (
|
|
14455
|
+
if (isDeepStrictEqual3(withoutSections, expected))
|
|
14351
14456
|
return;
|
|
14352
14457
|
const normalized = normalizeCodexInlinePathConfig(text2);
|
|
14353
14458
|
const withoutNormalizedSections = Bun.TOML.parse(normalized.replace(CODEX_SKILL_CONFIG_SECTIONS, ""));
|
|
14354
|
-
if (
|
|
14459
|
+
if (isDeepStrictEqual3(withoutNormalizedSections, expected))
|
|
14355
14460
|
return;
|
|
14356
14461
|
} catch {}
|
|
14357
14462
|
throw codexPathConfigRefusal();
|
|
@@ -14389,7 +14494,7 @@ function disableCodexBundledSkills(text2) {
|
|
|
14389
14494
|
const candidates = new Set;
|
|
14390
14495
|
const consider = (candidate) => {
|
|
14391
14496
|
try {
|
|
14392
|
-
if (
|
|
14497
|
+
if (isDeepStrictEqual3(Bun.TOML.parse(candidate), expected))
|
|
14393
14498
|
candidates.add(candidate);
|
|
14394
14499
|
} catch {}
|
|
14395
14500
|
};
|
|
@@ -15200,6 +15305,8 @@ function atomicWrite2(path, content) {
|
|
|
15200
15305
|
}
|
|
15201
15306
|
}
|
|
15202
15307
|
function planAgentSettingsWitnessUpgrade(options) {
|
|
15308
|
+
if (options.targetCodexVersion !== undefined && (options.agent !== "codex" || ![2, 3].includes(options.targetCodexVersion)))
|
|
15309
|
+
throw new Error("Invalid Codex witness target version");
|
|
15203
15310
|
const home = resolve10(options.home ?? homedir2()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
|
|
15204
15311
|
const snapshot = readManagedSkillPolicySnapshot(dataDir2);
|
|
15205
15312
|
if (!snapshot || sha3(snapshot.text) !== options.expectedPolicySha256)
|
|
@@ -15221,21 +15328,21 @@ function planAgentSettingsWitnessUpgrade(options) {
|
|
|
15221
15328
|
throw new Error("Settings witness upgrade requires a preserved settings preimage");
|
|
15222
15329
|
const replaced = [previous];
|
|
15223
15330
|
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
|
|
15331
|
+
if (previous.hashMode !== undefined && previous.hashMode !== "bytes" && previous.hashMode !== "codex-settings-v1" && !(options.targetCodexVersion === 3 && previous.hashMode === "codex-settings-v2"))
|
|
15332
|
+
throw new Error("Codex settings witness upgrade requires an eligible preserved configuration witness");
|
|
15226
15333
|
const preimage = readCodexSettingsPreimage(options.reviewedPreimage);
|
|
15227
15334
|
for (const source of binding.sources) {
|
|
15228
15335
|
if (source === previous || source.path !== configPath)
|
|
15229
15336
|
continue;
|
|
15230
15337
|
const fields = source.fields;
|
|
15231
|
-
if (source.hashMode !== undefined || source.format !== "toml" || !Array.isArray(fields) || !
|
|
15338
|
+
if (source.hashMode !== undefined || source.format !== "toml" || !Array.isArray(fields) || !isDeepStrictEqual4(fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]) || typeof source.sha256 !== "string")
|
|
15232
15339
|
throw new Error("Codex settings witness upgrade found an unrecognized configuration witness");
|
|
15233
15340
|
if (projectNativeDiscoveryFields(preimage, "toml", fields, configPath) !== source.sha256)
|
|
15234
15341
|
throw new Error("Reviewed preimage does not explain the Codex discovery projection witness");
|
|
15235
15342
|
replaced.push(source);
|
|
15236
15343
|
}
|
|
15237
15344
|
}
|
|
15238
|
-
const next = options.agent === "claude" ? upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
|
|
15345
|
+
const next = options.agent === "claude" ? upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : options.targetCodexVersion === 3 ? upgradeCodexSettingsWitnessV3(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
|
|
15239
15346
|
const rebound = [];
|
|
15240
15347
|
for (const source of binding.sources) {
|
|
15241
15348
|
if (!replaced.includes(source)) {
|
|
@@ -15272,7 +15379,7 @@ function applyAgentIntegration(plan) {
|
|
|
15272
15379
|
const upgrade = plan.settingsWitnessUpgrade;
|
|
15273
15380
|
if (!plan.managedAgentChecks || !plan.observedPolicy?.before)
|
|
15274
15381
|
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 });
|
|
15382
|
+
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
15383
|
if (JSON.stringify(verified.changes) !== JSON.stringify(plan.changes) || JSON.stringify(verified.settingsWitnessUpgrade) !== JSON.stringify(upgrade))
|
|
15277
15384
|
throw new Error("Settings witness upgrade plan changed");
|
|
15278
15385
|
provenDiscovery = verified.discoveryBefore[0];
|
|
@@ -18248,19 +18355,19 @@ function projectNativeDiscoveryFields(text2, format, fields2, path) {
|
|
|
18248
18355
|
return digest(JSON.stringify(Object.fromEntries(fields2.map((field2) => [field2, object5[field2] ?? null]))));
|
|
18249
18356
|
}
|
|
18250
18357
|
function isSupersededCodexProjection(agent, configPath, source) {
|
|
18251
|
-
return agent === "codex" && source.path === configPath && source.format === "toml" &&
|
|
18358
|
+
return agent === "codex" && source.path === configPath && source.format === "toml" && isDeepStrictEqual5(source.fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]);
|
|
18252
18359
|
}
|
|
18253
18360
|
function supersedesCodexProjection(sources, configPath) {
|
|
18254
|
-
return sources.some((source) => source.path === configPath && source.hashMode === "codex-settings-v2");
|
|
18361
|
+
return sources.some((source) => source.path === configPath && (source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3"));
|
|
18255
18362
|
}
|
|
18256
18363
|
function projected(source, changes, budget = discoveryByteBudget()) {
|
|
18257
|
-
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2") {
|
|
18364
|
+
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3") {
|
|
18258
18365
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
18259
18366
|
throw new Error("Codex settings witnesses require exact typed metadata");
|
|
18260
|
-
const current = (source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget).sha256;
|
|
18367
|
+
const current = (source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget).sha256;
|
|
18261
18368
|
if (current !== source.sha256)
|
|
18262
18369
|
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;
|
|
18370
|
+
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
18371
|
}
|
|
18265
18372
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
|
|
18266
18373
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
@@ -18360,7 +18467,7 @@ function codexInstallationRoots(binding) {
|
|
|
18360
18467
|
});
|
|
18361
18468
|
}
|
|
18362
18469
|
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"))
|
|
18470
|
+
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
18471
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
18365
18472
|
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
18473
|
throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
|
|
@@ -18510,10 +18617,10 @@ function resolveAgentDiscovery(options) {
|
|
|
18510
18617
|
verifyAgentDiscovery(retained);
|
|
18511
18618
|
if (!retained.sources.some((source) => source.path === canonical6(configPath) && source.format === undefined && source.fields === undefined))
|
|
18512
18619
|
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)))
|
|
18620
|
+
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
18621
|
unresolved("retained settings witness names another configuration source");
|
|
18515
18622
|
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) =>
|
|
18623
|
+
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
18624
|
unresolved("retained review is missing current runtime discovery coverage");
|
|
18518
18625
|
return retained;
|
|
18519
18626
|
}
|
|
@@ -18527,7 +18634,7 @@ function resolveAgentDiscovery(options) {
|
|
|
18527
18634
|
if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
|
|
18528
18635
|
throw new Error("Explicit discovery reviews require full source-file hashes");
|
|
18529
18636
|
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)))
|
|
18637
|
+
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
18638
|
throw new Error("Semantic settings witnesses must name the configured Claude configuration source");
|
|
18532
18639
|
if (!review.sources.some((source) => source.path === canonical6(configPath)))
|
|
18533
18640
|
throw new Error("Discovery review must include the agent configuration source");
|
|
@@ -19505,7 +19612,7 @@ function createSkillRun(params, targetDir = process.cwd()) {
|
|
|
19505
19612
|
mkdirSync10(logsDir, { recursive: true });
|
|
19506
19613
|
mkdirSync10(exportDir, { recursive: true });
|
|
19507
19614
|
mkdirSync10(join31(root2, "tmp"), { recursive: true });
|
|
19508
|
-
const
|
|
19615
|
+
const record3 = {
|
|
19509
19616
|
id,
|
|
19510
19617
|
skill: skillName,
|
|
19511
19618
|
status: params.status ?? "running",
|
|
@@ -19523,10 +19630,10 @@ function createSkillRun(params, targetDir = process.cwd()) {
|
|
|
19523
19630
|
logsDir: toProjectRelative(targetDir, logsDir)
|
|
19524
19631
|
}
|
|
19525
19632
|
};
|
|
19526
|
-
const context = { targetDir, runDir, exportDir, logsDir, record:
|
|
19633
|
+
const context = { targetDir, runDir, exportDir, logsDir, record: record3 };
|
|
19527
19634
|
writeRunRecord(context);
|
|
19528
19635
|
writeArtifactsManifest(context, []);
|
|
19529
|
-
appendRunEvent(context, "created", { status:
|
|
19636
|
+
appendRunEvent(context, "created", { status: record3.status });
|
|
19530
19637
|
return context;
|
|
19531
19638
|
}
|
|
19532
19639
|
function completeSkillRun(context, patch) {
|
|
@@ -19576,9 +19683,9 @@ function listSkillRuns(targetDir = process.cwd(), limit = 50) {
|
|
|
19576
19683
|
if (!statSync11(dayDir).isDirectory())
|
|
19577
19684
|
continue;
|
|
19578
19685
|
for (const runId of readdirSync13(dayDir).sort().reverse()) {
|
|
19579
|
-
const
|
|
19580
|
-
if (
|
|
19581
|
-
records.push(
|
|
19686
|
+
const record3 = readRunRecord(join31(dayDir, runId));
|
|
19687
|
+
if (record3)
|
|
19688
|
+
records.push(record3);
|
|
19582
19689
|
if (records.length >= limit)
|
|
19583
19690
|
return records;
|
|
19584
19691
|
}
|
|
@@ -19590,9 +19697,9 @@ function findSkillRun(runId, targetDir = process.cwd()) {
|
|
|
19590
19697
|
if (!existsSync15(runsRoot))
|
|
19591
19698
|
return null;
|
|
19592
19699
|
for (const day of readdirSync13(runsRoot)) {
|
|
19593
|
-
const
|
|
19594
|
-
if (
|
|
19595
|
-
return
|
|
19700
|
+
const record3 = readRunRecord(join31(runsRoot, day, runId));
|
|
19701
|
+
if (record3)
|
|
19702
|
+
return record3;
|
|
19596
19703
|
}
|
|
19597
19704
|
return null;
|
|
19598
19705
|
}
|
|
@@ -19733,7 +19840,7 @@ __export(exports_external, {
|
|
|
19733
19840
|
regexes: () => exports_regexes,
|
|
19734
19841
|
regex: () => _regex,
|
|
19735
19842
|
refine: () => refine,
|
|
19736
|
-
record: () =>
|
|
19843
|
+
record: () => record3,
|
|
19737
19844
|
readonly: () => readonly,
|
|
19738
19845
|
property: () => _property,
|
|
19739
19846
|
properties: () => _properties,
|
|
@@ -35507,8 +35614,8 @@ function rewriteKeyNames(ctx) {
|
|
|
35507
35614
|
bySchema.set(entry.schema, entry);
|
|
35508
35615
|
}
|
|
35509
35616
|
const rewrites = new Map;
|
|
35510
|
-
for (const
|
|
35511
|
-
const seen = ctx.seen.get(
|
|
35617
|
+
for (const record3 of pendingRecords.get(ctx) ?? []) {
|
|
35618
|
+
const seen = ctx.seen.get(record3);
|
|
35512
35619
|
const names = (seen?.def ?? seen?.schema)?.propertyNames;
|
|
35513
35620
|
if (!names || names === true || rewrites.has(names))
|
|
35514
35621
|
continue;
|
|
@@ -35835,7 +35942,7 @@ __export(exports_schemas2, {
|
|
|
35835
35942
|
strictObject: () => strictObject,
|
|
35836
35943
|
set: () => set,
|
|
35837
35944
|
refine: () => refine,
|
|
35838
|
-
record: () =>
|
|
35945
|
+
record: () => record3,
|
|
35839
35946
|
readonly: () => readonly,
|
|
35840
35947
|
promise: () => promise,
|
|
35841
35948
|
preprocess: () => preprocess,
|
|
@@ -37005,7 +37112,7 @@ var ZodRecord = /* @__PURE__ */ $constructor("ZodRecord", (inst, def) => {
|
|
|
37005
37112
|
inst.keyType = def.keyType;
|
|
37006
37113
|
inst.valueType = def.valueType;
|
|
37007
37114
|
});
|
|
37008
|
-
function
|
|
37115
|
+
function record3(keyType, valueType, params) {
|
|
37009
37116
|
if (!valueType || !valueType._zod) {
|
|
37010
37117
|
return new ZodRecord({
|
|
37011
37118
|
type: "record",
|
|
@@ -37471,7 +37578,7 @@ var stringbool = (...args) => _stringbool({
|
|
|
37471
37578
|
}, ...args);
|
|
37472
37579
|
function json(params) {
|
|
37473
37580
|
const jsonSchema = lazy(() => {
|
|
37474
|
-
return union([string2(params), number2(), boolean2(), _null3(), array2(jsonSchema),
|
|
37581
|
+
return union([string2(params), number2(), boolean2(), _null3(), array2(jsonSchema), record3(string2(), jsonSchema)]);
|
|
37475
37582
|
});
|
|
37476
37583
|
return jsonSchema;
|
|
37477
37584
|
}
|
|
@@ -39459,12 +39566,12 @@ class RemoteWorkspaceInvitationReadError extends Error {
|
|
|
39459
39566
|
}
|
|
39460
39567
|
}
|
|
39461
39568
|
function invitationFailure(value, status) {
|
|
39462
|
-
if (!
|
|
39569
|
+
if (!record4(value) || typeof value.code !== "string" || !Object.hasOwn(invitationFailures, value.code))
|
|
39463
39570
|
return null;
|
|
39464
39571
|
const code = value.code;
|
|
39465
39572
|
return invitationFailures[code][0] === status ? code : null;
|
|
39466
39573
|
}
|
|
39467
|
-
var
|
|
39574
|
+
var record4 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
39468
39575
|
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
39576
|
var role = (v) => typeof v === "string" && ["owner", "admin", "member", "viewer"].includes(v);
|
|
39470
39577
|
var email3 = (v) => typeof v === "string" && v.length <= 254 && !/[\p{Cc}\p{Cs}\u2028\u2029\s]/u.test(v) && /^[^@]+@[^@]+\.[^@]+$/.test(v);
|
|
@@ -39473,7 +39580,7 @@ var inputFailure = () => {
|
|
|
39473
39580
|
throw new WorkspaceInvitationInputError;
|
|
39474
39581
|
};
|
|
39475
39582
|
function invitationInput(action, input2) {
|
|
39476
|
-
if (!
|
|
39583
|
+
if (!record4(input2))
|
|
39477
39584
|
return inputFailure();
|
|
39478
39585
|
const keys = {
|
|
39479
39586
|
list: ["after"],
|
|
@@ -39524,7 +39631,7 @@ function invalid2() {
|
|
|
39524
39631
|
throw new RemoteWorkspaceInvitationReadError;
|
|
39525
39632
|
}
|
|
39526
39633
|
function projection(v, organizationId) {
|
|
39527
|
-
if (!
|
|
39634
|
+
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
39635
|
return invalid2();
|
|
39529
39636
|
return {
|
|
39530
39637
|
id: v.id,
|
|
@@ -39539,7 +39646,7 @@ function projection(v, organizationId) {
|
|
|
39539
39646
|
};
|
|
39540
39647
|
}
|
|
39541
39648
|
function parseInvitationResult(action, value, input2, organizationId) {
|
|
39542
|
-
if (!
|
|
39649
|
+
if (!record4(value))
|
|
39543
39650
|
return invalid2();
|
|
39544
39651
|
const request = input2;
|
|
39545
39652
|
if (action === "accept") {
|
|
@@ -39572,7 +39679,7 @@ function parseInvitationResult(action, value, input2, organizationId) {
|
|
|
39572
39679
|
}
|
|
39573
39680
|
|
|
39574
39681
|
// src/lib/remote-workspace-selection.ts
|
|
39575
|
-
var
|
|
39682
|
+
var record5 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
39576
39683
|
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
39684
|
var text2 = (v, max = 1024) => typeof v === "string" && !!v.trim() && v.length <= max && !/[\p{Cc}\p{Cs}\u2028\u2029]/u.test(v);
|
|
39578
39685
|
var role2 = (v) => typeof v === "string" && ["owner", "admin", "member", "viewer"].includes(v);
|
|
@@ -39597,7 +39704,7 @@ function workspaceExpectedUserId(value) {
|
|
|
39597
39704
|
return value;
|
|
39598
39705
|
}
|
|
39599
39706
|
function workspaceContext(value) {
|
|
39600
|
-
if (!
|
|
39707
|
+
if (!record5(value) || Object.keys(value).sort().join(",") !== "membershipId,userId" || !uuid8(value.userId) || !uuid8(value.membershipId))
|
|
39601
39708
|
throw new WorkspaceContextInputError;
|
|
39602
39709
|
return { userId: value.userId, membershipId: value.membershipId };
|
|
39603
39710
|
}
|
|
@@ -39605,15 +39712,15 @@ function invalid3() {
|
|
|
39605
39712
|
throw new Error(invalidWorkspaceResult);
|
|
39606
39713
|
}
|
|
39607
39714
|
function organization(v) {
|
|
39608
|
-
if (!
|
|
39715
|
+
if (!record5(v) || !uuid8(v.id) || !text2(v.slug) || !text2(v.name))
|
|
39609
39716
|
return invalid3();
|
|
39610
39717
|
return { id: v.id, slug: v.slug, name: v.name };
|
|
39611
39718
|
}
|
|
39612
39719
|
function parseAccountWorkspaces(value) {
|
|
39613
|
-
if (!
|
|
39720
|
+
if (!record5(value) || !Array.isArray(value.workspaces) || !value.workspaces.length || value.workspaces.length > 1000)
|
|
39614
39721
|
return invalid3();
|
|
39615
39722
|
const workspaces = value.workspaces.map((v) => {
|
|
39616
|
-
if (!
|
|
39723
|
+
if (!record5(v) || !uuid8(v.membershipId) || !role2(v.role) || typeof v.current !== "boolean")
|
|
39617
39724
|
return invalid3();
|
|
39618
39725
|
return { membershipId: v.membershipId, organization: organization(v.organization), role: v.role, current: v.current };
|
|
39619
39726
|
});
|
|
@@ -39622,10 +39729,10 @@ function parseAccountWorkspaces(value) {
|
|
|
39622
39729
|
return { workspaces };
|
|
39623
39730
|
}
|
|
39624
39731
|
function parseWorkspaceIdentity(value, expectedUserId) {
|
|
39625
|
-
if (!
|
|
39732
|
+
if (!record5(value))
|
|
39626
39733
|
return invalid3();
|
|
39627
39734
|
const user = value.user;
|
|
39628
|
-
if (!
|
|
39735
|
+
if (!record5(user) || !uuid8(user.id) || !uuid8(user.membershipId) || !text2(user.email, 320) || !(user.displayName === null || text2(user.displayName)) || !role2(user.role))
|
|
39629
39736
|
return invalid3();
|
|
39630
39737
|
if (user.id !== expectedUserId)
|
|
39631
39738
|
throw new WorkspaceIdentityMismatchError;
|
|
@@ -39643,8 +39750,8 @@ function parseWorkspaceSession(value, expected) {
|
|
|
39643
39750
|
return { token: sessionToken(value.token), ...identity4 };
|
|
39644
39751
|
}
|
|
39645
39752
|
function parseWorkspaceLogin(value, expectedUserId) {
|
|
39646
|
-
const user =
|
|
39647
|
-
if (!
|
|
39753
|
+
const user = record5(value) && value.user;
|
|
39754
|
+
if (!record5(value) || !record5(user) || !uuid8(user.id))
|
|
39648
39755
|
return invalid3();
|
|
39649
39756
|
if (expectedUserId !== undefined && user.id !== expectedUserId)
|
|
39650
39757
|
throw new WorkspaceIdentityMismatchError;
|
|
@@ -39659,18 +39766,18 @@ var workspaceSelectionFailures = {
|
|
|
39659
39766
|
WORKSPACE_BUSY: [503, "Workspace is busy. Refresh before retrying."]
|
|
39660
39767
|
};
|
|
39661
39768
|
function workspaceSelectionFailure(value, status) {
|
|
39662
|
-
if (!
|
|
39769
|
+
if (!record5(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceSelectionFailures, value.code))
|
|
39663
39770
|
return null;
|
|
39664
39771
|
const code = value.code;
|
|
39665
39772
|
return workspaceSelectionFailures[code][0] === status ? code : null;
|
|
39666
39773
|
}
|
|
39667
39774
|
|
|
39668
39775
|
// src/lib/remote-workspace.ts
|
|
39669
|
-
var
|
|
39776
|
+
var record6 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
39670
39777
|
var cursor = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,512}$/.test(value);
|
|
39671
39778
|
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
39779
|
function workspaceMembersQuery(options = {}) {
|
|
39673
|
-
if (!
|
|
39780
|
+
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
39781
|
throw new Error("Use a roster limit from 1 to 100 and an unchanged continuation cursor.");
|
|
39675
39782
|
const query = new URLSearchParams;
|
|
39676
39783
|
if (options.limit !== undefined)
|
|
@@ -39686,7 +39793,7 @@ function timestamp2(value) {
|
|
|
39686
39793
|
return Number.isFinite(time3) && new Date(time3).toISOString().slice(0, 23) === value.slice(0, 23);
|
|
39687
39794
|
}
|
|
39688
39795
|
function parseMember(row, fail) {
|
|
39689
|
-
if (!
|
|
39796
|
+
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
39797
|
return fail();
|
|
39691
39798
|
return {
|
|
39692
39799
|
membershipId: row.membershipId,
|
|
@@ -39706,7 +39813,7 @@ class WorkspaceMemberInputError extends Error {
|
|
|
39706
39813
|
}
|
|
39707
39814
|
}
|
|
39708
39815
|
function mutationInput(membershipId, input2, roleChange) {
|
|
39709
|
-
if (typeof membershipId !== "string" || !uuid10(membershipId) || membershipId !== membershipId.toLowerCase() || !
|
|
39816
|
+
if (typeof membershipId !== "string" || !uuid10(membershipId) || membershipId !== membershipId.toLowerCase() || !record6(input2) || Object.keys(input2).sort().join(",") !== (roleChange ? "expectedRole,role" : "expectedRole"))
|
|
39710
39817
|
throw new WorkspaceMemberInputError;
|
|
39711
39818
|
const expectedRole = input2.expectedRole, role3 = roleChange ? input2.role : undefined;
|
|
39712
39819
|
if (!isRole(expectedRole) || roleChange && !isRole(role3))
|
|
@@ -39726,7 +39833,7 @@ function parseWorkspaceMemberRoleResult(value, membershipId, role3) {
|
|
|
39726
39833
|
const fail = () => {
|
|
39727
39834
|
throw new Error(invalidMemberResult);
|
|
39728
39835
|
};
|
|
39729
|
-
if (!
|
|
39836
|
+
if (!record6(value) || !uuid10(value.organizationId) || typeof value.changed !== "boolean")
|
|
39730
39837
|
return fail();
|
|
39731
39838
|
const member = parseMember(value.member, fail);
|
|
39732
39839
|
if (member.membershipId !== membershipId || member.role !== role3)
|
|
@@ -39734,7 +39841,7 @@ function parseWorkspaceMemberRoleResult(value, membershipId, role3) {
|
|
|
39734
39841
|
return { organizationId: value.organizationId, member, changed: value.changed };
|
|
39735
39842
|
}
|
|
39736
39843
|
function parseWorkspaceMemberRemovalResult(value, membershipId) {
|
|
39737
|
-
if (!
|
|
39844
|
+
if (!record6(value) || !uuid10(value.organizationId) || value.membershipId !== membershipId || value.removed !== true || typeof value.alreadyRemoved !== "boolean")
|
|
39738
39845
|
throw new Error(invalidMemberResult);
|
|
39739
39846
|
return { organizationId: value.organizationId, membershipId, removed: true, alreadyRemoved: value.alreadyRemoved };
|
|
39740
39847
|
}
|
|
@@ -39751,7 +39858,7 @@ var workspaceMemberFailures = {
|
|
|
39751
39858
|
MEMBERSHIP_BUSY: [503, "Membership is busy. Refresh the roster before another action."]
|
|
39752
39859
|
};
|
|
39753
39860
|
function workspaceMemberFailure(value, status) {
|
|
39754
|
-
if (!
|
|
39861
|
+
if (!record6(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceMemberFailures, value.code))
|
|
39755
39862
|
return null;
|
|
39756
39863
|
const code = value.code;
|
|
39757
39864
|
return workspaceMemberFailures[code][0] === status ? code : null;
|
|
@@ -39760,7 +39867,7 @@ function parseWorkspaceMembersPage(value) {
|
|
|
39760
39867
|
const fail = () => {
|
|
39761
39868
|
throw new Error("The server returned an invalid workspace roster.");
|
|
39762
39869
|
};
|
|
39763
|
-
if (!
|
|
39870
|
+
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
39871
|
return fail();
|
|
39765
39872
|
const members2 = value.members.map((row) => parseMember(row, fail));
|
|
39766
39873
|
if (new Set(members2.map((row) => row.membershipId)).size !== members2.length)
|
|
@@ -39836,44 +39943,44 @@ function getApiUrl(action, env = process.env, options = {}) {
|
|
|
39836
39943
|
// src/lib/remote-run-contract.ts
|
|
39837
39944
|
var REMOTE_SKILL_RUN_CONTRACT_VERSION = 1;
|
|
39838
39945
|
function normalizeRemoteSkillRunContract(payload, fallbackSkill) {
|
|
39839
|
-
const
|
|
39946
|
+
const record7 = isRecord4(payload) ? payload : {};
|
|
39840
39947
|
return {
|
|
39841
39948
|
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(
|
|
39949
|
+
...pickString(record7, "id"),
|
|
39950
|
+
skill: pickStringValue(record7, "skill") ?? fallbackSkill,
|
|
39951
|
+
...pickString(record7, "requestedSlug"),
|
|
39952
|
+
...pickString(record7, "status"),
|
|
39953
|
+
...pickNumber(record7, "exitCode"),
|
|
39954
|
+
...pickString(record7, "correlationId"),
|
|
39955
|
+
...pickString(record7, "createdAt"),
|
|
39956
|
+
...pickString(record7, "startedAt"),
|
|
39957
|
+
...pickString(record7, "completedAt"),
|
|
39958
|
+
...pickNumber(record7, "durationMs"),
|
|
39959
|
+
...pickString(record7, "outputType"),
|
|
39960
|
+
...hasOwn(record7, "outputPreview") ? { outputPreview: record7.outputPreview } : {},
|
|
39961
|
+
...pickString(record7, "errorCode"),
|
|
39962
|
+
...pickString(record7, "errorMessage"),
|
|
39963
|
+
...pickString(record7, "error"),
|
|
39964
|
+
...pickString(record7, "code"),
|
|
39965
|
+
...hasOwn(record7, "details") ? { details: record7.details } : {}
|
|
39859
39966
|
};
|
|
39860
39967
|
}
|
|
39861
39968
|
function isRecord4(value) {
|
|
39862
39969
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
39863
39970
|
}
|
|
39864
|
-
function hasOwn(
|
|
39865
|
-
return Object.prototype.hasOwnProperty.call(
|
|
39971
|
+
function hasOwn(record7, key) {
|
|
39972
|
+
return Object.prototype.hasOwnProperty.call(record7, key);
|
|
39866
39973
|
}
|
|
39867
|
-
function pickString(
|
|
39868
|
-
const value = pickStringValue(
|
|
39974
|
+
function pickString(record7, key) {
|
|
39975
|
+
const value = pickStringValue(record7, key);
|
|
39869
39976
|
return value === undefined ? {} : { [key]: value };
|
|
39870
39977
|
}
|
|
39871
|
-
function pickStringValue(
|
|
39872
|
-
const value =
|
|
39978
|
+
function pickStringValue(record7, key) {
|
|
39979
|
+
const value = record7[key];
|
|
39873
39980
|
return typeof value === "string" ? value : undefined;
|
|
39874
39981
|
}
|
|
39875
|
-
function pickNumber(
|
|
39876
|
-
const value =
|
|
39982
|
+
function pickNumber(record7, key) {
|
|
39983
|
+
const value = record7[key];
|
|
39877
39984
|
return typeof value === "number" && Number.isFinite(value) ? { [key]: value } : {};
|
|
39878
39985
|
}
|
|
39879
39986
|
|
|
@@ -40093,11 +40200,11 @@ var permissionNames = [
|
|
|
40093
40200
|
"executionGrantsWrite",
|
|
40094
40201
|
"executionGrantsResolve"
|
|
40095
40202
|
];
|
|
40096
|
-
var
|
|
40203
|
+
var record7 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
40097
40204
|
function parseSkillsAccess(value) {
|
|
40098
40205
|
if (value === undefined)
|
|
40099
40206
|
return {};
|
|
40100
|
-
if (!
|
|
40207
|
+
if (!record7(value))
|
|
40101
40208
|
throw new Error("Invalid Skills permission contract");
|
|
40102
40209
|
const result = {};
|
|
40103
40210
|
if (value.scopes !== undefined) {
|
|
@@ -40106,7 +40213,7 @@ function parseSkillsAccess(value) {
|
|
|
40106
40213
|
result.scopes = [...value.scopes];
|
|
40107
40214
|
}
|
|
40108
40215
|
if (value.permissions !== undefined) {
|
|
40109
|
-
if (!
|
|
40216
|
+
if (!record7(value.permissions))
|
|
40110
40217
|
throw new Error("Invalid Skills permission contract");
|
|
40111
40218
|
result.permissions = {};
|
|
40112
40219
|
for (const name of permissionNames) {
|
|
@@ -41003,13 +41110,13 @@ class RemoteSkillsClient {
|
|
|
41003
41110
|
return normalizeUpdatedSincePage(await response.json());
|
|
41004
41111
|
}
|
|
41005
41112
|
}
|
|
41006
|
-
function requireOptionalString(
|
|
41007
|
-
if (
|
|
41113
|
+
function requireOptionalString(record8, field2) {
|
|
41114
|
+
if (record8[field2] === undefined)
|
|
41008
41115
|
return;
|
|
41009
|
-
if (typeof
|
|
41116
|
+
if (typeof record8[field2] !== "string") {
|
|
41010
41117
|
throw new Error(`Remote payload did not match the expected contract (${field2} must be a string when present)`);
|
|
41011
41118
|
}
|
|
41012
|
-
return
|
|
41119
|
+
return record8[field2];
|
|
41013
41120
|
}
|
|
41014
41121
|
var INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
|
|
41015
41122
|
function isVersionRecord(value) {
|
|
@@ -41032,19 +41139,19 @@ function normalizePin(entry) {
|
|
|
41032
41139
|
if (!entry || typeof entry !== "object") {
|
|
41033
41140
|
throw new Error("Remote pin payload did not match the expected contract (expected an object)");
|
|
41034
41141
|
}
|
|
41035
|
-
const
|
|
41036
|
-
const slug2 = typeof
|
|
41142
|
+
const record8 = entry;
|
|
41143
|
+
const slug2 = typeof record8.slug === "string" && record8.slug.trim() ? record8.slug.trim() : undefined;
|
|
41037
41144
|
if (!slug2) {
|
|
41038
41145
|
throw new Error("Remote pin payload did not match the expected contract (missing slug)");
|
|
41039
41146
|
}
|
|
41040
41147
|
let metadata;
|
|
41041
|
-
if (
|
|
41042
|
-
if (!
|
|
41148
|
+
if (record8.metadata !== undefined) {
|
|
41149
|
+
if (!record8.metadata || typeof record8.metadata !== "object" || Array.isArray(record8.metadata)) {
|
|
41043
41150
|
throw new Error("Remote pin payload did not match the expected contract (metadata must be a JSON object when present)");
|
|
41044
41151
|
}
|
|
41045
|
-
metadata =
|
|
41152
|
+
metadata = record8.metadata;
|
|
41046
41153
|
}
|
|
41047
|
-
const pinnedAt = requireOptionalString(
|
|
41154
|
+
const pinnedAt = requireOptionalString(record8, "pinnedAt");
|
|
41048
41155
|
return {
|
|
41049
41156
|
slug: slug2,
|
|
41050
41157
|
...pinnedAt !== undefined ? { pinnedAt } : {},
|
|
@@ -41061,16 +41168,16 @@ function normalizeSkillSummary(entry) {
|
|
|
41061
41168
|
if (!entry || typeof entry !== "object") {
|
|
41062
41169
|
throw new Error("Remote skill payload did not match the expected contract (expected an object)");
|
|
41063
41170
|
}
|
|
41064
|
-
const
|
|
41065
|
-
const slug2 = typeof
|
|
41171
|
+
const record8 = entry;
|
|
41172
|
+
const slug2 = typeof record8.slug === "string" && record8.slug.trim() ? record8.slug.trim() : undefined;
|
|
41066
41173
|
if (!slug2) {
|
|
41067
41174
|
throw new Error("Remote skill payload did not match the expected contract (missing slug)");
|
|
41068
41175
|
}
|
|
41069
41176
|
return {
|
|
41070
41177
|
slug: slug2,
|
|
41071
|
-
...requireOptionalString(
|
|
41072
|
-
...requireOptionalString(
|
|
41073
|
-
...requireOptionalString(
|
|
41178
|
+
...requireOptionalString(record8, "name") !== undefined ? { name: requireOptionalString(record8, "name") } : {},
|
|
41179
|
+
...requireOptionalString(record8, "version") !== undefined ? { version: requireOptionalString(record8, "version") } : {},
|
|
41180
|
+
...requireOptionalString(record8, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record8, "updatedAt") } : {}
|
|
41074
41181
|
};
|
|
41075
41182
|
}
|
|
41076
41183
|
function normalizeSkillSummaryList(payload) {
|
|
@@ -41127,12 +41234,12 @@ function normalizeUpdatedSincePage(payload) {
|
|
|
41127
41234
|
if (!payload || typeof payload !== "object") {
|
|
41128
41235
|
throw new Error("Updated-since payload did not match the expected contract (expected an object)");
|
|
41129
41236
|
}
|
|
41130
|
-
const
|
|
41131
|
-
if (!Array.isArray(
|
|
41237
|
+
const record8 = payload;
|
|
41238
|
+
if (!Array.isArray(record8.skills)) {
|
|
41132
41239
|
throw new Error("Updated-since payload did not match the expected contract (missing skills array)");
|
|
41133
41240
|
}
|
|
41134
|
-
const skills =
|
|
41135
|
-
const nextCursor =
|
|
41241
|
+
const skills = record8.skills.map(normalizeSkillSummary);
|
|
41242
|
+
const nextCursor = record8.nextCursor === undefined || record8.nextCursor === null ? null : record8.nextCursor;
|
|
41136
41243
|
if (nextCursor !== null && typeof nextCursor !== "string") {
|
|
41137
41244
|
throw new Error("Updated-since payload did not match the expected contract (nextCursor must be a string or absent)");
|
|
41138
41245
|
}
|
|
@@ -41371,8 +41478,8 @@ function revisionIdOf(content) {
|
|
|
41371
41478
|
const canonical6 = JSON.stringify(canonicalContent);
|
|
41372
41479
|
return createHash21("sha256").update(canonical6).digest("hex");
|
|
41373
41480
|
}
|
|
41374
|
-
function revisionIdOfRecord(
|
|
41375
|
-
return revisionIdOf(
|
|
41481
|
+
function revisionIdOfRecord(record8) {
|
|
41482
|
+
return revisionIdOf(record8);
|
|
41376
41483
|
}
|
|
41377
41484
|
// src/lib/pull.ts
|
|
41378
41485
|
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 +41855,16 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
|
|
|
41748
41855
|
}
|
|
41749
41856
|
return { path: target, created };
|
|
41750
41857
|
}
|
|
41751
|
-
function writePullMarker(dir,
|
|
41858
|
+
function writePullMarker(dir, record8) {
|
|
41752
41859
|
const marker = {
|
|
41753
41860
|
managedBy: "@hasna/skills",
|
|
41754
|
-
skill:
|
|
41755
|
-
source:
|
|
41756
|
-
...
|
|
41757
|
-
...
|
|
41758
|
-
...
|
|
41759
|
-
...
|
|
41760
|
-
...
|
|
41861
|
+
skill: record8.skill,
|
|
41862
|
+
source: record8.source ?? "pull",
|
|
41863
|
+
...record8.version ? { version: record8.version } : {},
|
|
41864
|
+
...record8.contentHash ? { contentHash: record8.contentHash } : {},
|
|
41865
|
+
...record8.sourceCommit ? { sourceCommit: record8.sourceCommit } : {},
|
|
41866
|
+
...record8.signature ? { signature: record8.signature } : {},
|
|
41867
|
+
...record8.revisionId ? { revisionId: record8.revisionId } : {},
|
|
41761
41868
|
syncedAt: new Date().toISOString()
|
|
41762
41869
|
};
|
|
41763
41870
|
writeFileSync11(join33(dir, PULL_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
|
|
@@ -41772,19 +41879,19 @@ async function safeMeta(client2, slug2) {
|
|
|
41772
41879
|
}
|
|
41773
41880
|
if (!raw || typeof raw !== "object")
|
|
41774
41881
|
return null;
|
|
41775
|
-
const
|
|
41776
|
-
const kind =
|
|
41777
|
-
const tags = Array.isArray(
|
|
41882
|
+
const record8 = raw;
|
|
41883
|
+
const kind = record8.kind === "instruction" || record8.kind === "executable" ? record8.kind : undefined;
|
|
41884
|
+
const tags = Array.isArray(record8.tags) ? record8.tags.filter((tag) => typeof tag === "string" && tag.trim().length > 0) : undefined;
|
|
41778
41885
|
return {
|
|
41779
|
-
...str(
|
|
41780
|
-
...str(
|
|
41781
|
-
...str(
|
|
41886
|
+
...str(record8.displayName) ? { displayName: str(record8.displayName) } : {},
|
|
41887
|
+
...str(record8.description) ? { description: str(record8.description) } : {},
|
|
41888
|
+
...str(record8.category) ? { category: str(record8.category) } : {},
|
|
41782
41889
|
...tags && tags.length ? { tags } : {},
|
|
41783
|
-
...str(
|
|
41890
|
+
...str(record8.version) ? { version: str(record8.version) } : {},
|
|
41784
41891
|
...kind ? { kind } : {},
|
|
41785
|
-
...REVISION_ID_PATTERN.test(str(
|
|
41786
|
-
...typeof
|
|
41787
|
-
...str(
|
|
41892
|
+
...REVISION_ID_PATTERN.test(str(record8.revisionId) ?? "") ? { revisionId: str(record8.revisionId) } : {},
|
|
41893
|
+
...typeof record8.skillMd === "string" && record8.skillMd.length > 0 ? { skillMd: record8.skillMd } : {},
|
|
41894
|
+
...str(record8.publishedSource) ? { publishedSource: str(record8.publishedSource) } : {}
|
|
41788
41895
|
};
|
|
41789
41896
|
}
|
|
41790
41897
|
function pickCorpusOptions(options) {
|
|
@@ -41793,8 +41900,8 @@ function pickCorpusOptions(options) {
|
|
|
41793
41900
|
function extractSlug(entry) {
|
|
41794
41901
|
if (!entry || typeof entry !== "object")
|
|
41795
41902
|
return;
|
|
41796
|
-
const
|
|
41797
|
-
return str(
|
|
41903
|
+
const record8 = entry;
|
|
41904
|
+
return str(record8.slug) ?? str(record8.name);
|
|
41798
41905
|
}
|
|
41799
41906
|
function dedupe(values) {
|
|
41800
41907
|
return [...new Set(values)];
|
|
@@ -41851,7 +41958,7 @@ class RemoteInvitationEmailUnconfirmedError extends Error {
|
|
|
41851
41958
|
this.name = "RemoteInvitationEmailUnconfirmedError";
|
|
41852
41959
|
}
|
|
41853
41960
|
}
|
|
41854
|
-
var
|
|
41961
|
+
var record8 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
41855
41962
|
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
41963
|
function invitationEmailIds(invitationId, challengeId) {
|
|
41857
41964
|
if (!uuid11(invitationId) || !uuid11(challengeId))
|
|
@@ -41860,7 +41967,7 @@ function invitationEmailIds(invitationId, challengeId) {
|
|
|
41860
41967
|
}
|
|
41861
41968
|
function invitationEmailInput(action, input2) {
|
|
41862
41969
|
const keys = ["invitationId", "token", "challengeId", "confirm", ...action === "accept" ? ["code"] : []];
|
|
41863
|
-
if (!
|
|
41970
|
+
if (!record8(input2) || Object.keys(input2).length !== keys.length || keys.some((key) => !Object.hasOwn(input2, key)))
|
|
41864
41971
|
throw new InvitationEmailInputError;
|
|
41865
41972
|
const value = { ...input2 };
|
|
41866
41973
|
const ids = invitationEmailIds(value.invitationId, value.challengeId);
|
|
@@ -41889,12 +41996,12 @@ async function requestInvitationEmail(origin, action, input2) {
|
|
|
41889
41996
|
signal: AbortSignal.timeout(15000)
|
|
41890
41997
|
});
|
|
41891
41998
|
const parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readBoundedResponse(response, 4096)));
|
|
41892
|
-
if (!response.ok &&
|
|
41999
|
+
if (!response.ok && record8(parsed) && typeof parsed.code === "string" && Object.hasOwn(refusals, parsed.code)) {
|
|
41893
42000
|
const code = parsed.code;
|
|
41894
42001
|
if (response.status === refusals[code][0])
|
|
41895
42002
|
throw new RemoteInvitationEmailError(code);
|
|
41896
42003
|
}
|
|
41897
|
-
if (!
|
|
42004
|
+
if (!record8(parsed))
|
|
41898
42005
|
throw new RemoteInvitationEmailUnconfirmedError(action);
|
|
41899
42006
|
if (action === "challenge" && response.status === 202 && parsed.challengeId === value.challengeId && parsed.expiresIn === 600 && typeof parsed.message === "string" && parsed.message.length <= 256) {
|
|
41900
42007
|
return { challengeId: value.challengeId, message: "If this invitation is eligible, a verification code will arrive. Delivery is not confirmed.", expiresIn: 600 };
|
|
@@ -41954,8 +42061,8 @@ var invalid4 = () => {
|
|
|
41954
42061
|
};
|
|
41955
42062
|
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
42063
|
var hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v);
|
|
41957
|
-
var
|
|
41958
|
-
var exact = (v, keys) =>
|
|
42064
|
+
var record9 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
42065
|
+
var exact = (v, keys) => record9(v) && Object.keys(v).sort().join(",") === keys.sort().join(",");
|
|
41959
42066
|
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
42067
|
var publicationSha256 = (bytes) => createHash22("sha256").update(bytes).digest("hex");
|
|
41961
42068
|
function checkedPublicationDeclaration(value) {
|
|
@@ -41963,7 +42070,7 @@ function checkedPublicationDeclaration(value) {
|
|
|
41963
42070
|
return bad();
|
|
41964
42071
|
try {
|
|
41965
42072
|
const manifest = JSON.parse(value.manifestText);
|
|
41966
|
-
if (!
|
|
42073
|
+
if (!record9(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash3(manifest.provenance?.content_hash))
|
|
41967
42074
|
return bad();
|
|
41968
42075
|
} catch {
|
|
41969
42076
|
return bad();
|
|
@@ -42021,7 +42128,7 @@ async function boundedJson(url2, init, token, mutation, budget2 = 15000, signal)
|
|
|
42021
42128
|
return invalid4();
|
|
42022
42129
|
}
|
|
42023
42130
|
if (!response.ok) {
|
|
42024
|
-
const code =
|
|
42131
|
+
const code = record9(body) && typeof body.code === "string" && Object.hasOwn(failures2, body.code) ? body.code : null;
|
|
42025
42132
|
if (code && failures2[code][0] === response.status)
|
|
42026
42133
|
throw new PrivatePublicationError(code, failures2[code][1], mutation && code === "PUBLICATION_UNCERTAIN", response.status);
|
|
42027
42134
|
throw new PrivatePublicationError("PUBLICATION_REQUEST_FAILED", "The publication request was refused. Inspect its status before retrying.", mutation && response.status >= 500, response.status);
|
|
@@ -42076,8 +42183,8 @@ class RemotePrivatePublicationsClient {
|
|
|
42076
42183
|
if (options.timeoutMs !== undefined && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 1 || options.timeoutMs > 15000))
|
|
42077
42184
|
return bad();
|
|
42078
42185
|
const response = await boundedJson(skillsApiRequestUrl(this.apiOrigin, "/api/v1/capabilities"), {}, this.#token, false, options.timeoutMs, options.signal);
|
|
42079
|
-
const p =
|
|
42080
|
-
if (!
|
|
42186
|
+
const p = record9(response) && response.privatePublishing;
|
|
42187
|
+
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
42188
|
throw new PrivatePublicationError("PUBLICATION_CONTRACT_UNAVAILABLE", "This server does not support the hosted private publication contract.");
|
|
42082
42189
|
return Object.freeze({ ...p });
|
|
42083
42190
|
}
|
|
@@ -42093,7 +42200,7 @@ class RemotePrivatePublicationsClient {
|
|
|
42093
42200
|
async#view(path, method, skillId, intentId, declaration, options = {}) {
|
|
42094
42201
|
const value = await boundedJson(path, { method, ...method === "GET" ? {} : { body: JSON.stringify(declaration ?? {}) } }, this.#token, method !== "GET", options.timeoutMs, options.signal);
|
|
42095
42202
|
try {
|
|
42096
|
-
if (!
|
|
42203
|
+
if (!record9(value) || !Object.keys(value).every((k) => k === "upload" || k === "changed") || value.changed !== undefined && typeof value.changed !== "boolean")
|
|
42097
42204
|
return invalid4();
|
|
42098
42205
|
return checkedPublicationView(value.upload, skillId, intentId, declaration);
|
|
42099
42206
|
} catch (error61) {
|
|
@@ -42256,10 +42363,10 @@ async function requestAuthApi(instance, path, options) {
|
|
|
42256
42363
|
const text3 = await res.text();
|
|
42257
42364
|
const body = text3 ? parseJsonBody(text3) : {};
|
|
42258
42365
|
if (!res.ok) {
|
|
42259
|
-
const
|
|
42260
|
-
const detail = typeof
|
|
42261
|
-
const error61 = typeof
|
|
42262
|
-
const code = typeof
|
|
42366
|
+
const record10 = isRecord6(body) ? body : {};
|
|
42367
|
+
const detail = typeof record10.detail === "string" ? record10.detail : undefined;
|
|
42368
|
+
const error61 = typeof record10.error === "string" ? record10.error : undefined;
|
|
42369
|
+
const code = typeof record10.code === "string" ? record10.code : undefined;
|
|
42263
42370
|
throw new HostedApiError(detail || error61 || `${res.status} ${res.statusText}`, {
|
|
42264
42371
|
status: res.status,
|
|
42265
42372
|
code,
|
|
@@ -44068,7 +44175,7 @@ class SkillsPostgresSyncStore {
|
|
|
44068
44175
|
}
|
|
44069
44176
|
async upsertRecords(records) {
|
|
44070
44177
|
let count = 0;
|
|
44071
|
-
for (const
|
|
44178
|
+
for (const record10 of records) {
|
|
44072
44179
|
await this.client.query([
|
|
44073
44180
|
"INSERT INTO skills_sync_records",
|
|
44074
44181
|
"(scope, kind, id, updated_at, deleted_at, source, payload)",
|
|
@@ -44079,13 +44186,13 @@ class SkillsPostgresSyncStore {
|
|
|
44079
44186
|
"source = EXCLUDED.source,",
|
|
44080
44187
|
"payload = EXCLUDED.payload"
|
|
44081
44188
|
].join(" "), [
|
|
44082
|
-
|
|
44083
|
-
|
|
44084
|
-
|
|
44085
|
-
|
|
44086
|
-
|
|
44087
|
-
|
|
44088
|
-
JSON.stringify(
|
|
44189
|
+
record10.scope,
|
|
44190
|
+
record10.kind,
|
|
44191
|
+
record10.id,
|
|
44192
|
+
record10.updatedAt,
|
|
44193
|
+
record10.deletedAt ?? null,
|
|
44194
|
+
record10.source ?? null,
|
|
44195
|
+
JSON.stringify(record10.payload)
|
|
44089
44196
|
]);
|
|
44090
44197
|
count += 1;
|
|
44091
44198
|
}
|
|
@@ -45489,6 +45596,7 @@ export {
|
|
|
45489
45596
|
validateCron,
|
|
45490
45597
|
validateBlogArticleRunOptions,
|
|
45491
45598
|
uploadSkillsSnapshotFilesToS3,
|
|
45599
|
+
upgradeCodexSettingsWitnessV3,
|
|
45492
45600
|
upgradeCodexSettingsWitness,
|
|
45493
45601
|
upgradeClaudeSettingsWitness,
|
|
45494
45602
|
updateSkillRun,
|
|
@@ -45674,6 +45782,7 @@ export {
|
|
|
45674
45782
|
captureDiscoveryPathSources,
|
|
45675
45783
|
captureDiscoveryDirectories,
|
|
45676
45784
|
captureDiscoveryByteSources,
|
|
45785
|
+
captureCodexSettingsV3,
|
|
45677
45786
|
captureCodexSettingsV2,
|
|
45678
45787
|
captureCodexSettings,
|
|
45679
45788
|
captureCodexNativeSkillCatalog,
|