@sema-ai/registry-core 0.10.3
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/CHANGELOG.md +131 -0
- package/README.md +84 -0
- package/dist/api/auth-bridge.d.ts +332 -0
- package/dist/api/auth-bridge.d.ts.map +1 -0
- package/dist/api/auth-bridge.js +211 -0
- package/dist/api/auth-bridge.js.map +1 -0
- package/dist/api/auth.d.ts +258 -0
- package/dist/api/auth.d.ts.map +1 -0
- package/dist/api/auth.js +204 -0
- package/dist/api/auth.js.map +1 -0
- package/dist/api/scopes.d.ts +353 -0
- package/dist/api/scopes.d.ts.map +1 -0
- package/dist/api/scopes.js +229 -0
- package/dist/api/scopes.js.map +1 -0
- package/dist/bundle.d.ts +14 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +68 -0
- package/dist/bundle.js.map +1 -0
- package/dist/config-fns.d.ts +236 -0
- package/dist/config-fns.d.ts.map +1 -0
- package/dist/config-fns.js +272 -0
- package/dist/config-fns.js.map +1 -0
- package/dist/cross-domain.d.ts +35 -0
- package/dist/cross-domain.d.ts.map +1 -0
- package/dist/cross-domain.js +119 -0
- package/dist/cross-domain.js.map +1 -0
- package/dist/file-edit.d.ts +37 -0
- package/dist/file-edit.d.ts.map +1 -0
- package/dist/file-edit.js +126 -0
- package/dist/file-edit.js.map +1 -0
- package/dist/file-store.d.ts +39 -0
- package/dist/file-store.d.ts.map +1 -0
- package/dist/file-store.js +142 -0
- package/dist/file-store.js.map +1 -0
- package/dist/fleet.d.ts +479 -0
- package/dist/fleet.d.ts.map +1 -0
- package/dist/fleet.js +303 -0
- package/dist/fleet.js.map +1 -0
- package/dist/hash.d.ts +33 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +60 -0
- package/dist/hash.js.map +1 -0
- package/dist/hooks.d.ts +5478 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +628 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/local-load.d.ts +33 -0
- package/dist/local-load.d.ts.map +1 -0
- package/dist/local-load.js +164 -0
- package/dist/local-load.js.map +1 -0
- package/dist/migrate.d.ts +245 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +543 -0
- package/dist/migrate.js.map +1 -0
- package/dist/node.d.ts +12 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +12 -0
- package/dist/node.js.map +1 -0
- package/dist/reader.d.ts +19 -0
- package/dist/reader.d.ts.map +1 -0
- package/dist/reader.js +2 -0
- package/dist/reader.js.map +1 -0
- package/dist/remote-exec.d.ts +275 -0
- package/dist/remote-exec.d.ts.map +1 -0
- package/dist/remote-exec.js +183 -0
- package/dist/remote-exec.js.map +1 -0
- package/dist/resolve-roster.d.ts +29 -0
- package/dist/resolve-roster.d.ts.map +1 -0
- package/dist/resolve-roster.js +105 -0
- package/dist/resolve-roster.js.map +1 -0
- package/dist/safety-merge-spec.d.ts +328 -0
- package/dist/safety-merge-spec.d.ts.map +1 -0
- package/dist/safety-merge-spec.js +65 -0
- package/dist/safety-merge-spec.js.map +1 -0
- package/dist/scheduler-store-node.d.ts +15 -0
- package/dist/scheduler-store-node.d.ts.map +1 -0
- package/dist/scheduler-store-node.js +43 -0
- package/dist/scheduler-store-node.js.map +1 -0
- package/dist/scheduler-store.d.ts +65 -0
- package/dist/scheduler-store.d.ts.map +1 -0
- package/dist/scheduler-store.js +59 -0
- package/dist/scheduler-store.js.map +1 -0
- package/dist/secret-refs.d.ts +34 -0
- package/dist/secret-refs.d.ts.map +1 -0
- package/dist/secret-refs.js +49 -0
- package/dist/secret-refs.js.map +1 -0
- package/dist/sha256.d.ts +17 -0
- package/dist/sha256.d.ts.map +1 -0
- package/dist/sha256.js +115 -0
- package/dist/sha256.js.map +1 -0
- package/dist/skills-manifest.d.ts +13 -0
- package/dist/skills-manifest.d.ts.map +1 -0
- package/dist/skills-manifest.js +55 -0
- package/dist/skills-manifest.js.map +1 -0
- package/dist/types.d.ts +9911 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1727 -0
- package/dist/types.js.map +1 -0
- package/package.json +130 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret-reference inventory (Phase-3 "密钥引用校验"). sema-registry stores only env-NAMEs, never secret
|
|
3
|
+
* values (the ENV_NAME boundary). This collects EVERY env-NAME the effective config references, grouped by
|
|
4
|
+
* name with where each is used — so an operator can audit "which env vars must each host/service provide?"
|
|
5
|
+
* before a worker/model fails at runtime.
|
|
6
|
+
*
|
|
7
|
+
* Note: sema-registry can't verify a name actually EXISTS in a consumer's environment (that's the consumer's
|
|
8
|
+
* own env). For workers, the reconciler already reports a missing one as a `SecretMissing` status condition
|
|
9
|
+
* (surfaced on /fleet). This inventory is the center-side half — every referenced env-NAME, incl. the general
|
|
10
|
+
* `secretEnv` passthrough, so a rotation runbook built on it isn't blind to app-specific tokens.
|
|
11
|
+
*/
|
|
12
|
+
import type { EffectiveConfig } from "./types.js";
|
|
13
|
+
export interface EnvRefUse {
|
|
14
|
+
domain: string;
|
|
15
|
+
detail: string;
|
|
16
|
+
}
|
|
17
|
+
export interface EnvRef {
|
|
18
|
+
envName: string;
|
|
19
|
+
refs: EnvRefUse[];
|
|
20
|
+
}
|
|
21
|
+
/** Every env-NAME referenced across models / workers / mcp, grouped + sorted by name.
|
|
22
|
+
* (integrations domain DELETED in 0.6.0 — OA/Gitea coordinates ride worker.env/secretEnv, EXPERT-REDESIGN §9.) */
|
|
23
|
+
export declare function collectEnvRefs(eff: EffectiveConfig): EnvRef[];
|
|
24
|
+
/**
|
|
25
|
+
* Names of workers that reference a given env-NAME — via any of the 4 structured `secretRefs` OR the general
|
|
26
|
+
* `secretEnv` passthrough. Drives batch-rotate (POST /secrets/<name>/rotate): after a credential write, recreate
|
|
27
|
+
* exactly the workers that project it. Reads the raw workers domain (the same shape collectEnvRefs would see).
|
|
28
|
+
*/
|
|
29
|
+
export declare function workersReferencingSecret(workers: {
|
|
30
|
+
name: string;
|
|
31
|
+
secretRefs?: Record<string, string | undefined>;
|
|
32
|
+
secretEnv?: Record<string, string>;
|
|
33
|
+
}[], envName: string): string[];
|
|
34
|
+
//# sourceMappingURL=secret-refs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-refs.d.ts","sourceRoot":"","sources":["../src/secret-refs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB;AAED;mHACmH;AACnH,wBAAgB,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,EAAE,CA8B7D;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAQpL"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** Every env-NAME referenced across models / workers / mcp, grouped + sorted by name.
|
|
2
|
+
* (integrations domain DELETED in 0.6.0 — OA/Gitea coordinates ride worker.env/secretEnv, EXPERT-REDESIGN §9.) */
|
|
3
|
+
export function collectEnvRefs(eff) {
|
|
4
|
+
const map = new Map();
|
|
5
|
+
const add = (envName, domain, detail) => {
|
|
6
|
+
if (!envName)
|
|
7
|
+
return;
|
|
8
|
+
const list = map.get(envName) ?? [];
|
|
9
|
+
list.push({ domain, detail });
|
|
10
|
+
map.set(envName, list);
|
|
11
|
+
};
|
|
12
|
+
for (const m of eff.models.models)
|
|
13
|
+
add(m.apiKeyEnv, "models", `model "${m.name}".apiKeyEnv`);
|
|
14
|
+
for (const w of eff.workers.workers) {
|
|
15
|
+
const r = w.secretRefs;
|
|
16
|
+
add(r.apiKeyEnv, "workers", `worker "${w.name}".secretRefs.apiKeyEnv`);
|
|
17
|
+
add(r.serviceAuthTokenEnv, "workers", `worker "${w.name}".secretRefs.serviceAuthTokenEnv`);
|
|
18
|
+
add(r.gitTokenEnv, "workers", `worker "${w.name}".secretRefs.gitTokenEnv`);
|
|
19
|
+
add(r.tidbPasswordEnv, "workers", `worker "${w.name}".secretRefs.tidbPasswordEnv`);
|
|
20
|
+
// the general secretEnv passthrough also references env-NAMEs (worker-env.ts merges them) — include them
|
|
21
|
+
// so the rotation inventory isn't blind to app-specific tokens like OA_SERVICE_TOKEN→OA_CALLBACK_TOKEN.
|
|
22
|
+
for (const [key, envName] of Object.entries(w.secretEnv ?? {}))
|
|
23
|
+
add(envName, "workers", `worker "${w.name}".secretEnv.${key}`);
|
|
24
|
+
}
|
|
25
|
+
for (const s of eff.mcp.servers) {
|
|
26
|
+
const t = s.transport;
|
|
27
|
+
const refs = t.kind === "stdio" ? t.envRefs : t.headerRefs;
|
|
28
|
+
const kind = t.kind === "stdio" ? "envRefs" : "headerRefs";
|
|
29
|
+
for (const [key, envName] of Object.entries(refs ?? {}))
|
|
30
|
+
add(envName, "mcp", `server "${s.name}" ${kind}.${key}`);
|
|
31
|
+
}
|
|
32
|
+
return [...map.entries()].map(([envName, refs]) => ({ envName, refs })).sort((a, b) => a.envName.localeCompare(b.envName));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Names of workers that reference a given env-NAME — via any of the 4 structured `secretRefs` OR the general
|
|
36
|
+
* `secretEnv` passthrough. Drives batch-rotate (POST /secrets/<name>/rotate): after a credential write, recreate
|
|
37
|
+
* exactly the workers that project it. Reads the raw workers domain (the same shape collectEnvRefs would see).
|
|
38
|
+
*/
|
|
39
|
+
export function workersReferencingSecret(workers, envName) {
|
|
40
|
+
const out = [];
|
|
41
|
+
for (const w of workers) {
|
|
42
|
+
const inStructured = Object.values(w.secretRefs ?? {}).includes(envName);
|
|
43
|
+
const inPassthrough = Object.values(w.secretEnv ?? {}).includes(envName);
|
|
44
|
+
if (inStructured || inPassthrough)
|
|
45
|
+
out.push(w.name);
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=secret-refs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-refs.js","sourceRoot":"","sources":["../src/secret-refs.ts"],"names":[],"mappings":"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"}
|
package/dist/sha256.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure, dependency-free, **synchronous** SHA-256 over a UTF-8 string → lowercase hex.
|
|
3
|
+
*
|
|
4
|
+
* WHY a hand-rolled impl instead of `node:crypto`: this module sits in the PURE barrel
|
|
5
|
+
* (re-exported via skills-manifest.ts → resolve-roster.ts → index.ts). sema-registry's CLIENT components
|
|
6
|
+
* import that barrel for the zod types, so anything in it ships into the BROWSER bundle. A `node:crypto`
|
|
7
|
+
* import there breaks (or bloats with a polyfill) the client build — the exact blocker Codex flagged.
|
|
8
|
+
* Web Crypto (`crypto.subtle.digest`) is async-only, but `skillContentHash` is a sync contract used in
|
|
9
|
+
* hot paths (the /effective manifest transform, the content-endpoint lookup), so we need a sync digest.
|
|
10
|
+
*
|
|
11
|
+
* Byte-for-byte identical to `createHash("sha256").update(s,"utf8").digest("hex")` — verified against
|
|
12
|
+
* node:crypto in the tests — so the `sha256:<hex>` content-address the service re-hashes after pulling
|
|
13
|
+
* (tamper detection) still matches. This is content-addressing/integrity, NOT a secret/MAC.
|
|
14
|
+
*/
|
|
15
|
+
/** SHA-256 of a UTF-8 string → 64-char lowercase hex. */
|
|
16
|
+
export declare function sha256Hex(input: string): string;
|
|
17
|
+
//# sourceMappingURL=sha256.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sha256.d.ts","sourceRoot":"","sources":["../src/sha256.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAsCH,yDAAyD;AACzD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAqD/C"}
|
package/dist/sha256.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure, dependency-free, **synchronous** SHA-256 over a UTF-8 string → lowercase hex.
|
|
3
|
+
*
|
|
4
|
+
* WHY a hand-rolled impl instead of `node:crypto`: this module sits in the PURE barrel
|
|
5
|
+
* (re-exported via skills-manifest.ts → resolve-roster.ts → index.ts). sema-registry's CLIENT components
|
|
6
|
+
* import that barrel for the zod types, so anything in it ships into the BROWSER bundle. A `node:crypto`
|
|
7
|
+
* import there breaks (or bloats with a polyfill) the client build — the exact blocker Codex flagged.
|
|
8
|
+
* Web Crypto (`crypto.subtle.digest`) is async-only, but `skillContentHash` is a sync contract used in
|
|
9
|
+
* hot paths (the /effective manifest transform, the content-endpoint lookup), so we need a sync digest.
|
|
10
|
+
*
|
|
11
|
+
* Byte-for-byte identical to `createHash("sha256").update(s,"utf8").digest("hex")` — verified against
|
|
12
|
+
* node:crypto in the tests — so the `sha256:<hex>` content-address the service re-hashes after pulling
|
|
13
|
+
* (tamper detection) still matches. This is content-addressing/integrity, NOT a secret/MAC.
|
|
14
|
+
*/
|
|
15
|
+
const K = new Uint32Array([
|
|
16
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
17
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
18
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
19
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
20
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
21
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
22
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
23
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
|
24
|
+
]);
|
|
25
|
+
/** Encode a JS string to UTF-8 bytes (no Node Buffer / TextEncoder dependency required — but use
|
|
26
|
+
* TextEncoder when present for speed; it exists in both modern Node and browsers). */
|
|
27
|
+
function utf8Bytes(s) {
|
|
28
|
+
if (typeof TextEncoder !== "undefined")
|
|
29
|
+
return new TextEncoder().encode(s);
|
|
30
|
+
// Minimal fallback encoder (very old runtimes only).
|
|
31
|
+
const out = [];
|
|
32
|
+
for (let i = 0; i < s.length; i++) {
|
|
33
|
+
let c = s.charCodeAt(i);
|
|
34
|
+
if (c >= 0xd800 && c <= 0xdbff && i + 1 < s.length) {
|
|
35
|
+
const c2 = s.charCodeAt(i + 1);
|
|
36
|
+
if (c2 >= 0xdc00 && c2 <= 0xdfff) {
|
|
37
|
+
c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
|
|
38
|
+
i++;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (c < 0x80)
|
|
42
|
+
out.push(c);
|
|
43
|
+
else if (c < 0x800)
|
|
44
|
+
out.push(0xc0 | (c >> 6), 0x80 | (c & 0x3f));
|
|
45
|
+
else if (c < 0x10000)
|
|
46
|
+
out.push(0xe0 | (c >> 12), 0x80 | ((c >> 6) & 0x3f), 0x80 | (c & 0x3f));
|
|
47
|
+
else
|
|
48
|
+
out.push(0xf0 | (c >> 18), 0x80 | ((c >> 12) & 0x3f), 0x80 | ((c >> 6) & 0x3f), 0x80 | (c & 0x3f));
|
|
49
|
+
}
|
|
50
|
+
return Uint8Array.from(out);
|
|
51
|
+
}
|
|
52
|
+
const rotr = (x, n) => (x >>> n) | (x << (32 - n));
|
|
53
|
+
/** SHA-256 of a UTF-8 string → 64-char lowercase hex. */
|
|
54
|
+
export function sha256Hex(input) {
|
|
55
|
+
const msg = utf8Bytes(input);
|
|
56
|
+
const bitLen = msg.length * 8;
|
|
57
|
+
// Pad: 0x80, then zeros, then 64-bit big-endian length, to a multiple of 64 bytes.
|
|
58
|
+
const withOne = msg.length + 1;
|
|
59
|
+
const total = withOne + ((56 - (withOne % 64) + 64) % 64) + 8;
|
|
60
|
+
const buf = new Uint8Array(total);
|
|
61
|
+
buf.set(msg);
|
|
62
|
+
buf[msg.length] = 0x80;
|
|
63
|
+
// 64-bit length, big-endian. bitLen fits in 53 bits safely for any realistic skill body.
|
|
64
|
+
const hi = Math.floor(bitLen / 0x100000000);
|
|
65
|
+
const lo = bitLen >>> 0;
|
|
66
|
+
buf[total - 8] = (hi >>> 24) & 0xff;
|
|
67
|
+
buf[total - 7] = (hi >>> 16) & 0xff;
|
|
68
|
+
buf[total - 6] = (hi >>> 8) & 0xff;
|
|
69
|
+
buf[total - 5] = hi & 0xff;
|
|
70
|
+
buf[total - 4] = (lo >>> 24) & 0xff;
|
|
71
|
+
buf[total - 3] = (lo >>> 16) & 0xff;
|
|
72
|
+
buf[total - 2] = (lo >>> 8) & 0xff;
|
|
73
|
+
buf[total - 1] = lo & 0xff;
|
|
74
|
+
let h0 = 0x6a09e667, h1 = 0xbb67ae85, h2 = 0x3c6ef372, h3 = 0xa54ff53a;
|
|
75
|
+
let h4 = 0x510e527f, h5 = 0x9b05688c, h6 = 0x1f83d9ab, h7 = 0x5be0cd19;
|
|
76
|
+
const w = new Uint32Array(64);
|
|
77
|
+
for (let off = 0; off < total; off += 64) {
|
|
78
|
+
for (let i = 0; i < 16; i++) {
|
|
79
|
+
w[i] = (buf[off + i * 4] << 24) | (buf[off + i * 4 + 1] << 16) | (buf[off + i * 4 + 2] << 8) | buf[off + i * 4 + 3];
|
|
80
|
+
}
|
|
81
|
+
for (let i = 16; i < 64; i++) {
|
|
82
|
+
const s0 = rotr(w[i - 15], 7) ^ rotr(w[i - 15], 18) ^ (w[i - 15] >>> 3);
|
|
83
|
+
const s1 = rotr(w[i - 2], 17) ^ rotr(w[i - 2], 19) ^ (w[i - 2] >>> 10);
|
|
84
|
+
w[i] = (w[i - 16] + s0 + w[i - 7] + s1) | 0;
|
|
85
|
+
}
|
|
86
|
+
let a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7;
|
|
87
|
+
for (let i = 0; i < 64; i++) {
|
|
88
|
+
const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
|
|
89
|
+
const ch = (e & f) ^ (~e & g);
|
|
90
|
+
const t1 = (h + S1 + ch + K[i] + w[i]) | 0;
|
|
91
|
+
const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
|
|
92
|
+
const maj = (a & b) ^ (a & c) ^ (b & c);
|
|
93
|
+
const t2 = (S0 + maj) | 0;
|
|
94
|
+
h = g;
|
|
95
|
+
g = f;
|
|
96
|
+
f = e;
|
|
97
|
+
e = (d + t1) | 0;
|
|
98
|
+
d = c;
|
|
99
|
+
c = b;
|
|
100
|
+
b = a;
|
|
101
|
+
a = (t1 + t2) | 0;
|
|
102
|
+
}
|
|
103
|
+
h0 = (h0 + a) | 0;
|
|
104
|
+
h1 = (h1 + b) | 0;
|
|
105
|
+
h2 = (h2 + c) | 0;
|
|
106
|
+
h3 = (h3 + d) | 0;
|
|
107
|
+
h4 = (h4 + e) | 0;
|
|
108
|
+
h5 = (h5 + f) | 0;
|
|
109
|
+
h6 = (h6 + g) | 0;
|
|
110
|
+
h7 = (h7 + h) | 0;
|
|
111
|
+
}
|
|
112
|
+
const toHex = (n) => (n >>> 0).toString(16).padStart(8, "0");
|
|
113
|
+
return toHex(h0) + toHex(h1) + toHex(h2) + toHex(h3) + toHex(h4) + toHex(h5) + toHex(h6) + toHex(h7);
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=sha256.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sha256.js","sourceRoot":"","sources":["../src/sha256.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SkillsConfig, SkillsManifest } from "./types.js";
|
|
2
|
+
/** Content-address a skill body → algorithm-prefixed sha256 hex. Self-describing (future alg), immutable,
|
|
3
|
+
* and the SAME value carried in the manifest and used as the content-endpoint path. Memoized by content. */
|
|
4
|
+
export declare function skillContentHash(content: string): string;
|
|
5
|
+
/** Normalize a requested hash (bare 64-hex OR `sha256:<hex>`) to the canonical `sha256:<lowerhex>`, or null
|
|
6
|
+
* if malformed — so a junk/oversized path param is rejected before any scan. */
|
|
7
|
+
export declare function normalizeContentHash(raw: string): string | null;
|
|
8
|
+
/** /effective transform: strip each skill's `content`, replace with its `contentHash` (manifest shape). */
|
|
9
|
+
export declare function toSkillsManifest(cfg: SkillsConfig): SkillsManifest;
|
|
10
|
+
/** Content-addressed lookup: the body whose hash == `hash`, or undefined (unknown / malformed hash). Identical
|
|
11
|
+
* content across skills shares a hash → the first match's body is returned (bodies are identical by definition). */
|
|
12
|
+
export declare function findSkillContent(cfg: SkillsConfig, hash: string): string | undefined;
|
|
13
|
+
//# sourceMappingURL=skills-manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-manifest.d.ts","sourceRoot":"","sources":["../src/skills-manifest.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAQ/D;6GAC6G;AAC7G,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOxD;AAED;iFACiF;AACjF,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG/D;AAED,2GAA2G;AAC3G,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,YAAY,GAAG,cAAc,CAElE;AAED;qHACqH;AACrH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKpF"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skills content-addressing (docs/MCP-SKILLS.md §3.1, slice 2). The /effective payload ships skills as a
|
|
3
|
+
* MANIFEST — each skill's markdown `content` replaced by a `contentHash` — so the frequent 60s refresh stays
|
|
4
|
+
* small; the service pulls each body ONCE (at boot) via GET /api/config/skills/content/<hash>, caches it by
|
|
5
|
+
* hash, and re-pulls only when the hash changes (skills rarely change → big win). Bodies are immutable +
|
|
6
|
+
* deduped: identical content across skills shares one hash.
|
|
7
|
+
*
|
|
8
|
+
* sha256 here is for INTEGRITY + addressing (the service re-hashes after pulling to detect tampering/corruption)
|
|
9
|
+
* — distinct from the FNV `stableHash` in hash.ts, which is a fast non-crypto change-detector for ETags.
|
|
10
|
+
*
|
|
11
|
+
* The digest is a PURE-JS sha256 (./sha256.ts), NOT `node:crypto`: this module is re-exported through the
|
|
12
|
+
* package barrel, which sema-registry's CLIENT components import for the zod types — so a `node:crypto`
|
|
13
|
+
* import here would leak `node:*` into the browser bundle (the Codex blocker). Output is byte-identical to
|
|
14
|
+
* `createHash("sha256")`, so the `sha256:<hex>` content-address the service verifies still matches.
|
|
15
|
+
*/
|
|
16
|
+
import { sha256Hex } from "./sha256.js";
|
|
17
|
+
// Memoize content→hash: the /effective poll path (toSkillsManifest) and the content-endpoint lookup
|
|
18
|
+
// (findSkillContent) re-hash the same small, stable skill bodies repeatedly (× N workers × 60s). Skill
|
|
19
|
+
// bodies are few + rarely change, so this stays tiny; a cap guards against unbounded growth.
|
|
20
|
+
const _hashMemo = new Map();
|
|
21
|
+
const _HASH_MEMO_CAP = 512;
|
|
22
|
+
/** Content-address a skill body → algorithm-prefixed sha256 hex. Self-describing (future alg), immutable,
|
|
23
|
+
* and the SAME value carried in the manifest and used as the content-endpoint path. Memoized by content. */
|
|
24
|
+
export function skillContentHash(content) {
|
|
25
|
+
const hit = _hashMemo.get(content);
|
|
26
|
+
if (hit !== undefined)
|
|
27
|
+
return hit;
|
|
28
|
+
const h = `sha256:${sha256Hex(content)}`;
|
|
29
|
+
if (_hashMemo.size >= _HASH_MEMO_CAP)
|
|
30
|
+
_hashMemo.clear(); // bound — skills are few; simple evict-all is fine
|
|
31
|
+
_hashMemo.set(content, h);
|
|
32
|
+
return h;
|
|
33
|
+
}
|
|
34
|
+
/** Normalize a requested hash (bare 64-hex OR `sha256:<hex>`) to the canonical `sha256:<lowerhex>`, or null
|
|
35
|
+
* if malformed — so a junk/oversized path param is rejected before any scan. */
|
|
36
|
+
export function normalizeContentHash(raw) {
|
|
37
|
+
const m = /^(?:sha256:)?([0-9a-f]{64})$/i.exec(raw.trim());
|
|
38
|
+
return m ? `sha256:${m[1].toLowerCase()}` : null;
|
|
39
|
+
}
|
|
40
|
+
/** /effective transform: strip each skill's `content`, replace with its `contentHash` (manifest shape). */
|
|
41
|
+
export function toSkillsManifest(cfg) {
|
|
42
|
+
return { skills: cfg.skills.map(({ content, ...rest }) => ({ ...rest, contentHash: skillContentHash(content) })) };
|
|
43
|
+
}
|
|
44
|
+
/** Content-addressed lookup: the body whose hash == `hash`, or undefined (unknown / malformed hash). Identical
|
|
45
|
+
* content across skills shares a hash → the first match's body is returned (bodies are identical by definition). */
|
|
46
|
+
export function findSkillContent(cfg, hash) {
|
|
47
|
+
const want = normalizeContentHash(hash);
|
|
48
|
+
if (!want)
|
|
49
|
+
return undefined;
|
|
50
|
+
for (const s of cfg.skills)
|
|
51
|
+
if (skillContentHash(s.content) === want)
|
|
52
|
+
return s.content;
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=skills-manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-manifest.js","sourceRoot":"","sources":["../src/skills-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,oGAAoG;AACpG,uGAAuG;AACvG,6FAA6F;AAC7F,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;AAC5C,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B;6GAC6G;AAC7G,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC;IAClC,MAAM,CAAC,GAAG,UAAU,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;IACzC,IAAI,SAAS,CAAC,IAAI,IAAI,cAAc;QAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,mDAAmD;IAC5G,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC1B,OAAO,CAAC,CAAC;AACX,CAAC;AAED;iFACiF;AACjF,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,MAAM,CAAC,GAAG,+BAA+B,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACnD,CAAC;AAED,2GAA2G;AAC3G,MAAM,UAAU,gBAAgB,CAAC,GAAiB;IAChD,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,WAAW,EAAE,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AACrH,CAAC;AAED;qHACqH;AACrH,MAAM,UAAU,gBAAgB,CAAC,GAAiB,EAAE,IAAY;IAC9D,MAAM,IAAI,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM;QAAE,IAAI,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,IAAI;YAAE,OAAO,CAAC,CAAC,OAAO,CAAC;IACvF,OAAO,SAAS,CAAC;AACnB,CAAC"}
|