@hasna/skills 0.9.2 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.js +144 -12
- package/bin/maintenance.js +4913 -0
- package/bin/mcp.js +3 -2
- package/bin/migrate.js +55 -2
- package/bin/server.js +173 -10
- package/bin/worker.js +173 -10
- package/dist/index.js +8 -5
- package/dist/lib/agent-codex-trust.d.ts +34 -0
- package/dist/lib/agent-integration.d.ts +1 -0
- package/dist/lib/codex-hook-rpc.d.ts +1 -1
- package/dist/sdk/index.js +178 -13
- package/dist/server/maintenance-entry.d.ts +2 -0
- package/dist/server/maintenance.d.ts +1 -0
- package/dist/server/sqlite-store.d.ts +3 -1
- package/dist/server/store.d.ts +7 -1
- package/dist/server/types.d.ts +44 -0
- package/migrations/postgres/0005_operator_scope_receipts.sql +9 -0
- package/migrations/sqlite/0005_operator_scope_receipts.sql +7 -0
- package/package.json +3 -2
package/bin/index.js
CHANGED
|
@@ -36868,7 +36868,7 @@ var package_default;
|
|
|
36868
36868
|
var init_package = __esm(() => {
|
|
36869
36869
|
package_default = {
|
|
36870
36870
|
name: "@hasna/skills",
|
|
36871
|
-
version: "0.9.
|
|
36871
|
+
version: "0.9.4",
|
|
36872
36872
|
description: "Skills library for AI coding agents",
|
|
36873
36873
|
type: "module",
|
|
36874
36874
|
bin: {
|
|
@@ -36877,6 +36877,7 @@ var init_package = __esm(() => {
|
|
|
36877
36877
|
"skills-serve": "bin/server.js",
|
|
36878
36878
|
"skills-server": "bin/server.js",
|
|
36879
36879
|
"skills-worker": "bin/worker.js",
|
|
36880
|
+
"skills-maintenance": "bin/maintenance.js",
|
|
36880
36881
|
"skills-migrate": "bin/migrate.js"
|
|
36881
36882
|
},
|
|
36882
36883
|
exports: {
|
|
@@ -36917,7 +36918,7 @@ var init_package = __esm(() => {
|
|
|
36917
36918
|
types: "./dist/index.d.ts",
|
|
36918
36919
|
scripts: {
|
|
36919
36920
|
clean: "rm -rf bin/ dist/",
|
|
36920
|
-
build: "bun run clean && bun build ./src/cli/index.tsx --outdir ./bin --target bun && bun build ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build ./src/server/index.ts --outfile ./bin/server.js --target bun && bun build ./src/server/worker.ts --outfile ./bin/worker.js --target bun && bun build ./src/server/migrate.ts --outfile ./bin/migrate.js --target bun && bun build ./src/index.ts ./src/storage.ts ./src/sdk/index.ts ./src/admin-contract.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist",
|
|
36921
|
+
build: "bun run clean && bun build ./src/cli/index.tsx --outdir ./bin --target bun && bun build ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build ./src/server/index.ts --outfile ./bin/server.js --target bun && bun build ./src/server/worker.ts --outfile ./bin/worker.js --target bun && bun build ./src/server/migrate.ts --outfile ./bin/migrate.js --target bun && bun build ./src/server/maintenance.ts --outfile ./bin/maintenance.js --target bun && bun build ./src/index.ts ./src/storage.ts ./src/sdk/index.ts ./src/admin-contract.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist",
|
|
36921
36922
|
"build:js": "rm -rf dist && bun build ./src/index.ts ./src/storage.ts ./src/sdk/index.ts ./src/admin-contract.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist",
|
|
36922
36923
|
test: "bun test --timeout 30000",
|
|
36923
36924
|
dev: "bun run ./src/cli/index.tsx",
|
|
@@ -55451,10 +55452,12 @@ function projectAncestorDirectories(projects) {
|
|
|
55451
55452
|
}
|
|
55452
55453
|
function inventoryNativeSkills(home = homedir4(), options = {}) {
|
|
55453
55454
|
const aliases = rootAliases(home, options.allowRootAliases);
|
|
55454
|
-
const
|
|
55455
|
+
const selectedAgents = options.agents ? new Set(options.agents) : undefined;
|
|
55456
|
+
const rootDefinitions = selectedAgents ? ROOTS.filter(([agent, path]) => selectedAgents.has(agent) || selectedAgents.has("hermes") && agent === "codex" && path === ".agents/skills") : ROOTS;
|
|
55457
|
+
const roots = rootDefinitions.map(([agent, path]) => [agent, canonicalAgentPath(join29(home, path), aliases)]);
|
|
55455
55458
|
const bridgePaths = Object.values(AGENT_ADAPTERS).map((adapter) => canonicalAgentPath(join29(home, adapter.root, CLI_BRIDGE_NAME), aliases));
|
|
55456
55459
|
for (const project of projectAncestorDirectories([...options.projectDirs ?? [], ...options.projectDir ? [options.projectDir] : []])) {
|
|
55457
|
-
for (const [agent, path] of
|
|
55460
|
+
for (const [agent, path] of rootDefinitions)
|
|
55458
55461
|
roots.push([agent, canonicalAgentPath(join29(project, path), aliases)]);
|
|
55459
55462
|
}
|
|
55460
55463
|
const entries = [], seen = new Set;
|
|
@@ -55710,7 +55713,7 @@ function planAgentIntegration(options) {
|
|
|
55710
55713
|
return [agent, { command, profileId: profileId2 }];
|
|
55711
55714
|
}));
|
|
55712
55715
|
const discoveries = [...new Set(options.agents)].map((agent) => resolveAgentDiscovery({ home, agent, reviewed: options.discoveryInputs, canonical: (path) => canonicalAgentPath(path, aliases) }));
|
|
55713
|
-
const nativeSkills = inventoryNativeSkills(home, { includeVendor: true, guardHermes: options.agents.includes("hermes"), projectDir: options.projectDir, agentRoots: discoveries.flatMap((binding) => binding.roots.map((path) => ({ agent: binding.agent, path }))), allowRootAliases: options.allowRootAliases });
|
|
55716
|
+
const nativeSkills = inventoryNativeSkills(home, { includeVendor: true, guardHermes: options.agents.includes("hermes"), agents: options.agents, projectDir: options.projectDir, agentRoots: discoveries.flatMap((binding) => binding.roots.map((path) => ({ agent: binding.agent, path }))), allowRootAliases: options.allowRootAliases });
|
|
55714
55717
|
const changes = [];
|
|
55715
55718
|
for (const agent of [...new Set(options.agents)]) {
|
|
55716
55719
|
if (!INTEGRATION_AGENTS.includes(agent))
|
|
@@ -56110,7 +56113,7 @@ function assertManagedAgentBridge(agent, options = {}) {
|
|
|
56110
56113
|
} catch (error) {
|
|
56111
56114
|
throw new Error(`NATIVE_SKILL_DRIFT: ${error.message}`);
|
|
56112
56115
|
}
|
|
56113
|
-
const inventory = inventoryNativeSkills(home, { includeVendor: true, guardHermes: agent === "hermes", projectDirs: [...roots], agentRoots: discovery.roots.map((path) => ({ agent, path })), allowRootAliases: aliases.length > 0 });
|
|
56116
|
+
const inventory = inventoryNativeSkills(home, { includeVendor: true, guardHermes: agent === "hermes", agents: [agent], projectDirs: [...roots], agentRoots: discovery.roots.map((path) => ({ agent, path })), allowRootAliases: aliases.length > 0 });
|
|
56114
56117
|
const unexpected = inventory.filter((entry) => visible(entry) && !entry.bridge && !disabledBuiltin(entry));
|
|
56115
56118
|
if (unexpected.length) {
|
|
56116
56119
|
const paths = unexpected.slice(0, 3).map((entry) => {
|
|
@@ -108021,7 +108024,7 @@ async function connectCodexHookRpc(options) {
|
|
|
108021
108024
|
}
|
|
108022
108025
|
var SUPPORTED_CODEX_HOOK_VERSIONS;
|
|
108023
108026
|
var init_codex_hook_rpc = __esm(() => {
|
|
108024
|
-
SUPPORTED_CODEX_HOOK_VERSIONS = ["codex-cli 0.153.0", "codex-cli 0.154.0", "codex-cli 0.155.0"];
|
|
108027
|
+
SUPPORTED_CODEX_HOOK_VERSIONS = ["codex-cli 0.153.0", "codex-cli 0.154.0", "codex-cli 0.155.0", "codex-cli 0.155.1"];
|
|
108025
108028
|
});
|
|
108026
108029
|
|
|
108027
108030
|
// src/lib/codex-hook-trust-layout.ts
|
|
@@ -108098,7 +108101,7 @@ function codexTrustTextWitness(text3, keys3) {
|
|
|
108098
108101
|
let result2 = text3;
|
|
108099
108102
|
for (const span of replacements2.reverse())
|
|
108100
108103
|
result2 = result2.slice(0, span.start) + span.comments + result2.slice(span.end);
|
|
108101
|
-
return result2.split(/\r?\n/).filter((line) => line.trim()).join(`
|
|
108104
|
+
return canonicalizeTableOrder(result2).split(/\r?\n/).filter((line) => line.trim()).join(`
|
|
108102
108105
|
`);
|
|
108103
108106
|
}
|
|
108104
108107
|
var fail4 = () => new Error('CODEX_HOOK_TRUST_UNSUPPORTED_LAYOUT: preserve and convert hook trust to ordinary [hooks.state."<key>"] tables before enrollment'), prune = (value) => {
|
|
@@ -108107,6 +108110,25 @@ var fail4 = () => new Error('CODEX_HOOK_TRUST_UNSUPPORTED_LAYOUT: preserve and c
|
|
|
108107
108110
|
if (value.hooks && !Object.keys(value.hooks).length)
|
|
108108
108111
|
delete value.hooks;
|
|
108109
108112
|
return value;
|
|
108113
|
+
}, canonicalizeTableOrder = (text3) => {
|
|
108114
|
+
const headers = [...text3.matchAll(/^[ \t]*(\[\[?[^\r\n]+\]\]?)[ \t]*(#[^\r\n]*)?(?:\r?\n|$)/gm)];
|
|
108115
|
+
if (!headers.length)
|
|
108116
|
+
return text3;
|
|
108117
|
+
const keys3 = headers.map((header) => header[1].trim());
|
|
108118
|
+
if (keys3.some((key) => key.startsWith("[[") || keys3.filter((other) => other === key).length > 1))
|
|
108119
|
+
return text3;
|
|
108120
|
+
const plain = keys3.map((key) => key.slice(1, -1).trim());
|
|
108121
|
+
if (plain.some((key, index) => plain.some((other, otherIndex) => index !== otherIndex && (other.startsWith(`${key}.`) || key.startsWith(`${other}.`)))))
|
|
108122
|
+
return text3;
|
|
108123
|
+
const first = headers[0].index;
|
|
108124
|
+
const prefix = text3.slice(0, first);
|
|
108125
|
+
const blocks = headers.map((header, index) => ({
|
|
108126
|
+
key: header[1],
|
|
108127
|
+
order: index,
|
|
108128
|
+
text: text3.slice(header.index, headers[index + 1]?.index ?? text3.length)
|
|
108129
|
+
}));
|
|
108130
|
+
blocks.sort((a, b) => a.key.localeCompare(b.key) || a.order - b.order);
|
|
108131
|
+
return prefix + blocks.map((block) => block.text).join("");
|
|
108110
108132
|
};
|
|
108111
108133
|
var init_codex_hook_trust_layout = () => {};
|
|
108112
108134
|
|
|
@@ -108206,6 +108228,101 @@ import { createHash as createHash26, randomUUID as randomUUID10 } from "crypto";
|
|
|
108206
108228
|
import { join as join56, resolve as resolve22 } from "path";
|
|
108207
108229
|
import { homedir as homedir11 } from "os";
|
|
108208
108230
|
import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
|
|
108231
|
+
async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc) {
|
|
108232
|
+
let rpc;
|
|
108233
|
+
try {
|
|
108234
|
+
const home = resolve22(options.home ?? homedir11()), dataDir3 = resolve22(options.dataDir ?? getDataDirReadOnly());
|
|
108235
|
+
const parent = resolve22(join56(dataDir3, "native-hook-trust")), journal = resolve22(options.journal);
|
|
108236
|
+
need4(journal.startsWith(parent + "/") && /^[a-f0-9-]{36}$/.test(journal.slice(parent.length + 1)), "RECONCILE_JOURNAL_PATH");
|
|
108237
|
+
const dir = lstatSync28(journal, { throwIfNoEntry: false });
|
|
108238
|
+
need4(!!dir && dir.isDirectory() && !dir.isSymbolicLink() && dir.uid === process.getuid() && (dir.mode & 511) === 448, "UNSAFE_JOURNAL");
|
|
108239
|
+
need4(!lstatSync28(join56(journal, "receipt.json"), { throwIfNoEntry: false }), "RECONCILE_ALREADY_COMPLETE");
|
|
108240
|
+
need4(lstatSync28(join56(journal, "stopped.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_JOURNAL_INCOMPLETE");
|
|
108241
|
+
const stoppedFile = snapshot(join56(journal, "stopped.json"), true);
|
|
108242
|
+
const intentFile = snapshot(join56(journal, "intent.json"), true), intent = JSON.parse(intentFile.text);
|
|
108243
|
+
const configBefore = snapshot(join56(journal, "config.before.toml"), true), hooksBefore = snapshot(join56(journal, "hooks.before.json"), true), policyBefore = snapshot(join56(journal, "policy.before.json"), true);
|
|
108244
|
+
const legacyIntent = intent.home === undefined && intent.configSha256 === undefined && intent.configVersion === undefined && intent.declarations === undefined && intent.admitted === undefined && intent.nativeHooks === undefined;
|
|
108245
|
+
need4(intent.version === 1 && /^[a-f0-9]{64}$/.test(intent.planDigest) && typeof intent.configPath === "string" && /^[a-f0-9]{64}$/.test(intent.policySha256) && /^[a-f0-9]{64}$/.test(intent.hooksSha256) && Array.isArray(intent.hooks) && intent.hooks.length > 0 && intent.hooks.length <= 100 && (legacyIntent || typeof intent.home === "string" && intent.home === home && /^[a-f0-9]{64}$/.test(intent.configSha256) && typeof intent.configVersion === "string" && Array.isArray(intent.declarations) && Array.isArray(intent.admitted) && Array.isArray(intent.nativeHooks)), "RECONCILE_INTENT_INVALID");
|
|
108246
|
+
const declarations = intent.declarations ?? intent.hooks.map((hook) => ({ event: hook.event, key: `${join56(home, ".codex/hooks.json")}${hook.key.slice(hook.key.indexOf(".codex/hooks.json") + ".codex/hooks.json".length)}`, command: hook.command }));
|
|
108247
|
+
const admitted = intent.admitted ?? intent.hooks;
|
|
108248
|
+
const configSha256 = intent.configSha256 ?? configBefore.sha256, configVersion = intent.configVersion ?? intent.expectedVersion;
|
|
108249
|
+
const digestInput = { version: 1, home: intent.home ?? home, configPath: intent.configPath, configSha256, configVersion, policySha256: intent.policySha256, hooksSha256: intent.hooksSha256, skillsCli: intent.skillsCli, nativeVersion: intent.nativeVersion, declarations, admitted };
|
|
108250
|
+
need4(makePlanDigest(digestInput) === intent.planDigest, "RECONCILE_PLAN_CHANGED");
|
|
108251
|
+
need4(isDeepStrictEqual6(intent.hooks, admitted.filter((hook) => !hook.enabled || hook.trustStatus !== "trusted")), "RECONCILE_INTENT_HOOKS_CHANGED");
|
|
108252
|
+
need4(configBefore.sha256 === intent.beforeSha256 && hooksBefore.sha256 === intent.hooksSha256 && policyBefore.sha256 === intent.policySha256, "RECONCILE_JOURNAL_CHANGED");
|
|
108253
|
+
const currentConfig = snapshot(intent.configPath, true);
|
|
108254
|
+
need4(codexTrustTextWitness(configBefore.text, intent.hooks.map((h) => h.key)) === codexTrustTextWitness(currentConfig.text, intent.hooks.map((h) => h.key)), "RECONCILE_UNRELATED_CONFIG_CHANGED");
|
|
108255
|
+
const before2 = structure(configBefore.text), current = structure(currentConfig.text), expectedConfig = structuredClone(before2);
|
|
108256
|
+
expectedConfig.hooks ??= {};
|
|
108257
|
+
expectedConfig.hooks.state ??= {};
|
|
108258
|
+
for (const hook of intent.hooks)
|
|
108259
|
+
expectedConfig.hooks.state[hook.key] = { ...expectedConfig.hooks.state[hook.key], enabled: true, trusted_hash: hook.currentHash };
|
|
108260
|
+
need4(isDeepStrictEqual6(expectedConfig, current), "RECONCILE_CONFIG_DRIFT");
|
|
108261
|
+
const policyCurrent = snapshot(join56(dataDir3, "agent-policy.json"), true);
|
|
108262
|
+
need4(policyCurrent.sha256 === policyBefore.sha256, "RECONCILE_POLICY_CHANGED");
|
|
108263
|
+
const policy = parseManagedSkillPolicy(policyBefore.text), binding = policy.bridge;
|
|
108264
|
+
assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
|
|
108265
|
+
const skillsCli = bindSkillsCli(binding.commands.codex, options.reviewedSkillsCli);
|
|
108266
|
+
need4(isDeepStrictEqual6(skillsCli.receipt, intent.skillsCli), "RECONCILE_SKILLS_BINDING_CHANGED");
|
|
108267
|
+
const alias = binding.rootAliases?.find((item) => item.agent === "codex"), codexHome = alias?.target ?? join56(home, ".codex"), hooksPath = join56(codexHome, "hooks.json");
|
|
108268
|
+
need4(resolve22(intent.configPath) === resolve22(join56(codexHome, "config.toml")), "RECONCILE_CONFIG_PATH_CHANGED");
|
|
108269
|
+
const hooksCurrent = snapshot(hooksPath);
|
|
108270
|
+
need4(hooksCurrent.sha256 === intent.hooksSha256 || hooksCurrent.sha256 === hooksBefore.sha256, "RECONCILE_HOOKS_CHANGED");
|
|
108271
|
+
rpc = await connect({ command: options.codexCommand ?? "codex", home, codexHome });
|
|
108272
|
+
need4(rpc.version === intent.nativeVersion, "RECONCILE_NATIVE_VERSION_CHANGED");
|
|
108273
|
+
const discovered = await rpc.request("hooks/list", { cwds: [home] });
|
|
108274
|
+
need4(Array.isArray(discovered?.data) && discovered.data.length === 1 && discovered.data[0].cwd === home && !discovered.data[0].errors?.length && !discovered.data[0].warnings?.length, "RECONCILE_NATIVE_DISCOVERY_REFUSED");
|
|
108275
|
+
const nativeHooks = discovered.data[0].hooks;
|
|
108276
|
+
const recordedNativeHooks = intent.nativeHooks;
|
|
108277
|
+
if (recordedNativeHooks)
|
|
108278
|
+
need4(nativeHooks.length === recordedNativeHooks.length, "RECONCILE_NATIVE_HOOK_LIST_CHANGED");
|
|
108279
|
+
const plannedKeys = new Set(intent.hooks.map((hook) => hook.key));
|
|
108280
|
+
for (const expected of recordedNativeHooks ?? []) {
|
|
108281
|
+
const matches2 = nativeHooks.filter((hook) => hook.key === expected.key);
|
|
108282
|
+
need4(matches2.length === 1, "RECONCILE_NATIVE_HOOK_LIST_CHANGED");
|
|
108283
|
+
const actual = safeNativeHook(matches2[0]);
|
|
108284
|
+
const stable = (hook) => {
|
|
108285
|
+
const { enabled, trustStatus, ...identity4 } = hook;
|
|
108286
|
+
return identity4;
|
|
108287
|
+
};
|
|
108288
|
+
need4(isDeepStrictEqual6(stable(actual), stable(expected)), "RECONCILE_NATIVE_IDENTITY_CHANGED");
|
|
108289
|
+
if (!plannedKeys.has(expected.key))
|
|
108290
|
+
need4(isDeepStrictEqual6(actual, expected), "RECONCILE_UNRELATED_HOOK_CHANGED");
|
|
108291
|
+
}
|
|
108292
|
+
for (const wanted of intent.hooks) {
|
|
108293
|
+
const matches2 = nativeHooks.filter((h2) => h2.key === wanted.key || h2.key === wanted.key.replace(join56(home, ".codex/hooks.json"), hooksPath));
|
|
108294
|
+
need4(matches2.length === 1, "RECONCILE_NATIVE_IDENTITY_CHANGED");
|
|
108295
|
+
const h = matches2[0];
|
|
108296
|
+
need4(h.enabled === true && h.trustStatus === "trusted" && h.currentHash === wanted.currentHash, "RECONCILE_NATIVE_STATE_INCOMPLETE");
|
|
108297
|
+
}
|
|
108298
|
+
const config2 = await rpc.request("config/read", { includeLayers: true, cwd: home });
|
|
108299
|
+
const layers = config2?.layers?.filter((layer) => layer.name?.type === "user" && layer.name.file === intent.configPath && !layer.name.profile);
|
|
108300
|
+
need4(layers?.length === 1 && !layers[0].disabledReason && isDeepStrictEqual6(layers[0].config, current), "RECONCILE_NATIVE_CONFIG_MISMATCH");
|
|
108301
|
+
const finalDiscovery = await rpc.request("hooks/list", { cwds: [home] });
|
|
108302
|
+
need4(Array.isArray(finalDiscovery?.data) && finalDiscovery.data.length === 1 && finalDiscovery.data[0].cwd === home && !finalDiscovery.data[0].errors?.length && !finalDiscovery.data[0].warnings?.length && (!recordedNativeHooks || isDeepStrictEqual6(finalDiscovery.data[0].hooks.map(safeNativeHook), nativeHooks.map(safeNativeHook))), "RECONCILE_NATIVE_STATE_CHANGED");
|
|
108303
|
+
const finalConfig = await rpc.request("config/read", { includeLayers: true, cwd: home });
|
|
108304
|
+
const finalLayers = finalConfig?.layers?.filter((layer) => layer.name?.type === "user" && layer.name.file === intent.configPath && !layer.name.profile);
|
|
108305
|
+
need4(finalLayers?.length === 1 && isDeepStrictEqual6(finalLayers[0].config, current), "RECONCILE_NATIVE_CONFIG_CHANGED");
|
|
108306
|
+
unchanged2(stoppedFile);
|
|
108307
|
+
unchanged2(intentFile);
|
|
108308
|
+
unchanged2(configBefore);
|
|
108309
|
+
unchanged2(hooksBefore);
|
|
108310
|
+
unchanged2(policyBefore);
|
|
108311
|
+
unchanged2(policyCurrent);
|
|
108312
|
+
unchanged2(hooksCurrent);
|
|
108313
|
+
unchanged2(currentConfig);
|
|
108314
|
+
skillsCli.recheck();
|
|
108315
|
+
assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
|
|
108316
|
+
const receipt = { version: 1, status: "reconciled", reconciled: true, automaticRollback: false, journal, planDigest: intent.planDigest, nativeVersion: rpc.version, nativeStateVerified: true, nativeExecutionVerified: false, configSha256: currentConfig.sha256, hooksSha256: hooksCurrent.sha256, policySha256: policyBefore.sha256, skillsCli: skillsCli.receipt, nativeInventoryScope: recordedNativeHooks ? "complete" : "declared-managed-hooks-only", unrelatedNativeHooksPreserved: !!recordedNativeHooks, unrelatedSettingsAndCommentsPreserved: true };
|
|
108317
|
+
save2(join56(journal, "receipt.json"), json2(receipt));
|
|
108318
|
+
return receipt;
|
|
108319
|
+
} catch (error61) {
|
|
108320
|
+
const message = error61 instanceof Error && error61.message.startsWith("CODEX_HOOK_TRUST_") ? error61.message : "CODEX_HOOK_TRUST_RECONCILE_REFUSED";
|
|
108321
|
+
throw new Error(message);
|
|
108322
|
+
} finally {
|
|
108323
|
+
await rpc?.close();
|
|
108324
|
+
}
|
|
108325
|
+
}
|
|
108209
108326
|
async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRpc) {
|
|
108210
108327
|
let rpc, journal;
|
|
108211
108328
|
try {
|
|
@@ -108259,7 +108376,8 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
108259
108376
|
unchanged2(configFile);
|
|
108260
108377
|
};
|
|
108261
108378
|
checkInputs();
|
|
108262
|
-
const
|
|
108379
|
+
const digestInput = { version: 1, home, configPath, configSha256: configFile.sha256, configVersion: layers[0].version, policySha256: policyFile.sha256, hooksSha256: hooksFile.sha256, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, declarations: expected, admitted };
|
|
108380
|
+
const planDigest = makePlanDigest(digestInput);
|
|
108263
108381
|
const baseReceipt = { planDigest, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, ownedNativeProcessId: rpc.processId, agent: "codex", applied: false, planned, nativeEligible: planned.length === 0, transport: "owned-stdio-process", existingSessionsReloaded: false, nativeExecutionVerified: false };
|
|
108264
108382
|
if (options.apply)
|
|
108265
108383
|
need4(options.reviewedPlanDigest === planDigest, "PLAN_CHANGED: run the dry-run again and pass its reviewed --plan-digest with --apply");
|
|
@@ -108283,7 +108401,7 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
108283
108401
|
save2(join56(journal, "config.before.toml"), configFile.bytes);
|
|
108284
108402
|
save2(join56(journal, "hooks.before.json"), hooksFile.bytes);
|
|
108285
108403
|
save2(join56(journal, "policy.before.json"), policyFile.bytes);
|
|
108286
|
-
save2(join56(journal, "intent.json"), json2({
|
|
108404
|
+
save2(join56(journal, "intent.json"), json2({ ...digestInput, planDigest, hooks: planned, nativeHooks: discovered.map(safeNativeHook) }));
|
|
108287
108405
|
need4(isDeepStrictEqual6(admit(await list2()), admitted), "NATIVE_DISCOVERY_CHANGED");
|
|
108288
108406
|
checkInputs();
|
|
108289
108407
|
let result2;
|
|
@@ -108325,7 +108443,7 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
108325
108443
|
}
|
|
108326
108444
|
}
|
|
108327
108445
|
var json2 = (value) => JSON.stringify(value, null, 2) + `
|
|
108328
|
-
`, structure = (text3) => JSON.parse(JSON.stringify(Bun.TOML.parse(text3))), eventNames;
|
|
108446
|
+
`, structure = (text3) => JSON.parse(JSON.stringify(Bun.TOML.parse(text3))), eventNames, makePlanDigest = (value) => createHash26("sha256").update(json2(value)).digest("hex"), safeNativeHook = (hook) => ({ key: hook.key, eventName: hook.eventName, handlerType: hook.handlerType, command: hook.command, matcher: hook.matcher, timeoutSec: hook.timeoutSec, async: hook.async, statusMessage: hook.statusMessage, additionalContextLimit: hook.additionalContextLimit, sourcePath: hook.sourcePath, source: hook.source, pluginId: hook.pluginId, isManaged: hook.isManaged, currentHash: hook.currentHash, enabled: hook.enabled, trustStatus: hook.trustStatus });
|
|
108329
108447
|
var init_agent_codex_trust = __esm(() => {
|
|
108330
108448
|
init_config();
|
|
108331
108449
|
init_managed_policy();
|
|
@@ -108503,7 +108621,7 @@ function registerAgentIntegration(parent) {
|
|
|
108503
108621
|
process.exitCode = 1;
|
|
108504
108622
|
}
|
|
108505
108623
|
});
|
|
108506
|
-
hook.command("trust").requiredOption("--agent <agent>", "Native trust adapter (codex)").option("--codex-command <path>", "Installed Codex executable used for its native configuration API", "codex").option("--apply", "Enable and trust only the exact managed Skills hook identities", false).option("--plan-digest <sha256>", "Exact reviewed dry-run digest required with --apply").option("--json", "Output the native trust plan or receipt", false).description("Plan or enroll exact Skills hooks through Codex native trust controls").action(async (options) => {
|
|
108624
|
+
const trust = hook.command("trust").requiredOption("--agent <agent>", "Native trust adapter (codex)").option("--codex-command <path>", "Installed Codex executable used for its native configuration API", "codex").option("--apply", "Enable and trust only the exact managed Skills hook identities", false).option("--plan-digest <sha256>", "Exact reviewed dry-run digest required with --apply").option("--json", "Output the native trust plan or receipt", false).description("Plan or enroll exact Skills hooks through Codex native trust controls").action(async (options) => {
|
|
108507
108625
|
try {
|
|
108508
108626
|
if (options.agent !== "codex")
|
|
108509
108627
|
throw new Error("Native trust enrollment currently supports --agent codex only");
|
|
@@ -108517,6 +108635,20 @@ function registerAgentIntegration(parent) {
|
|
|
108517
108635
|
process.exitCode = 1;
|
|
108518
108636
|
}
|
|
108519
108637
|
});
|
|
108638
|
+
trust.command("reconcile").requiredOption("--agent <agent>", "Native trust adapter (codex)").requiredOption("--journal <path>", "Private incomplete native trust journal to inspect").option("--codex-command <path>", "Installed Codex executable used for its native configuration API", "codex").option("--json", "Output the reconciliation receipt", false).description("Verify an interrupted Codex native trust write and resolve its private journal").action(async (options) => {
|
|
108639
|
+
try {
|
|
108640
|
+
if (options.agent !== "codex")
|
|
108641
|
+
throw new Error("Native trust reconciliation currently supports --agent codex only");
|
|
108642
|
+
const result2 = await reconcileCodexNativeHooks({ journal: options.journal, codexCommand: options.codexCommand });
|
|
108643
|
+
if (options.json)
|
|
108644
|
+
await writeCliOutput(JSON.stringify(result2));
|
|
108645
|
+
else
|
|
108646
|
+
await writeCliOutput(`Reconciled native Codex trust journal ${result2.journal}. No native configuration was written.`);
|
|
108647
|
+
} catch (error61) {
|
|
108648
|
+
console.error(error61.message);
|
|
108649
|
+
process.exitCode = 1;
|
|
108650
|
+
}
|
|
108651
|
+
});
|
|
108520
108652
|
hook.command("user-prompt").requiredOption("--agent <agent>", `Native payload/output adapter: ${INTEGRATION_AGENTS.join(", ")}`).option("--event <event>", "Native lifecycle event supplied by the installed adapter").option("--selection-profile <id>", "Selection profile to load").description("Read native lifecycle JSON on stdin and return selected context").action(async (options) => {
|
|
108521
108653
|
const deadline = Date.now() + 12000;
|
|
108522
108654
|
let event = options.agent === "hermes" && options.event === "pre_tool_call" ? "pre_tool_call" : "UserPromptSubmit";
|