@agenticprimitives/agent-skills 0.0.0-alpha.13 → 0.0.0-alpha.15
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 +4 -53
- package/dist/index.d.ts +3 -193
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -194
- package/dist/index.js.map +1 -1
- package/package.json +6 -8
package/README.md
CHANGED
|
@@ -1,59 +1,10 @@
|
|
|
1
1
|
# @agenticprimitives/agent-skills
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Deprecated.** Use [`@agenticprimitives/capability-claims`](../capability-claims) (ADR-0051).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
> Part of [agenticprimitives](../../README.md) — the trust substrate for the agent economy: one canonical Smart Agent identity with custody, delegation, naming, credentials, and audit evidence designed as one system.
|
|
8
|
-
|
|
9
|
-
## What ships today
|
|
10
|
-
|
|
11
|
-
This SDK owns the credential shape (`SkillClaimCredential`), the self/endorsed builders, the commitment/digest math, and a thin on-chain definition reader ([spec 251](../../specs/251-skills-and-geo-features.md)):
|
|
12
|
-
|
|
13
|
-
- **Builders** — `buildSelfSkillClaim` (subject == issuer; proficiency capped at `SELF_MAX_PROFICIENCY`; self-meaningless relations forbidden) and `buildEndorsedSkillClaim` (cross-issued; returns the `endorsementDigest` the issuer signs).
|
|
14
|
-
- **Codelists** — `SKILL_KIND` (lockstep with `SkillDefinitionRegistry.KIND_*` on chain — a cross-stack test reads the live `.sol`), `SKILL_RELATION`, `SkillVisibility`. All are keccak hashes of the `ns/skill#` C-box concept URIs.
|
|
15
|
-
- **Math** — `computeSkillId`, `conceptHash`, `skillClaimId`, `skillEndorsementDigest`, `skillClaimHash`.
|
|
16
|
-
- **Definition reader** — `skillDefinitionExists(read, registry, ref)` via an injected `readContract` function (no viem/contract dependency) + `SKILL_DEFINITION_READ_ABI`.
|
|
5
|
+
This package re-exports `capability-claims` for backward compatibility.
|
|
17
6
|
|
|
18
7
|
```ts
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const { credential, endorsementDigest } = buildEndorsedSkillClaim({
|
|
22
|
-
chainId: 84532,
|
|
23
|
-
subject: kcAgent, // the Smart Agent the claim is about
|
|
24
|
-
issuer: certifyingBody, // a different SA endorses it
|
|
25
|
-
definition: { skillId, version: 1 }, // points to the on-chain SkillDefinitionRegistry
|
|
26
|
-
relation: SKILL_RELATION.certifiedIn,
|
|
27
|
-
proficiencyScore: 9000,
|
|
28
|
-
nonce,
|
|
29
|
-
});
|
|
30
|
-
// the issuer signs `endorsementDigest` (ERC-1271); the app stores `credential` in the subject's vault.
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Vault I/O is the app's job — this package is transport-agnostic and builds the credential only. `evidenceCommit` is a bytes32 commitment/merkle root, never a URI; the preimage stays in the vault.
|
|
34
|
-
|
|
35
|
-
## How it's different
|
|
36
|
-
|
|
37
|
-
Skill taxonomies and agent-capability frameworks (OASF-style schemas, marketplace skill catalogs) describe what a skill *is*; they have no answer for who *verifiably has it*. The deltas here:
|
|
38
|
-
|
|
39
|
-
1. **Claims are credentials, not catalog rows.** A claim is a signed VC bound to a persistent Smart Agent address — endorsable by another on-chain identity, revocable, and intact through credential recovery.
|
|
40
|
-
2. **Public taxonomy, private possession.** Definitions are shared on-chain anchors; the agent↔skill association never touches the chain unless the holder opts in. Competitors' public skill registries make every participant's capability map free intelligence.
|
|
41
|
-
3. **Lockstep, CI-checked.** `SKILL_KIND.Leaf === SkillDefinitionRegistry.KIND_LEAF` is asserted by a cross-stack test against the live Solidity — the SDK cannot drift from the contract.
|
|
42
|
-
|
|
43
|
-
Geo is the independent sibling [`@agenticprimitives/geo-features`](../geo-features) — no skill↔geo mapping exists on chain or in the SDKs; a "skill X in region Y" fact is two separate claims. Neutral substrate: no vertical vocabulary (domain language lives in apps, per [ADR-0021](../../docs/architecture/decisions/0021-generic-packages-vs-white-label-apps.md)).
|
|
44
|
-
|
|
45
|
-
## Status
|
|
46
|
-
|
|
47
|
-
**W1 foundational — the off-chain skill-claim layer of the spec-251 skills/geo substrate is shipped.** The on-chain peer is `SkillDefinitionRegistry.sol` in [`packages/contracts`](../contracts). See [AUDIT.md](./AUDIT.md).
|
|
48
|
-
|
|
49
|
-
> Testnet/pilot-ready. Production launch is gated on the public checklist in the root README — including third-party contract audit and governance key rotation. Track every security finding live in [`docs/audits/findings.yaml`](../../docs/audits/findings.yaml).
|
|
50
|
-
|
|
51
|
-
**Authoritative spec:** [`specs/251-skills-and-geo-features.md`](../../specs/251-skills-and-geo-features.md). Bounded surface: `CLAUDE.md` + `capability.manifest.json`.
|
|
52
|
-
|
|
53
|
-
## Build
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
pnpm --filter @agenticprimitives/agent-skills typecheck
|
|
57
|
-
pnpm --filter @agenticprimitives/agent-skills test
|
|
58
|
-
pnpm --filter @agenticprimitives/agent-skills build
|
|
8
|
+
// Prefer:
|
|
9
|
+
import { buildEndorsedSkillClaim } from '@agenticprimitives/capability-claims';
|
|
59
10
|
```
|
package/dist/index.d.ts
CHANGED
|
@@ -1,196 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @agenticprimitives/
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Definitions are PUBLIC, versioned, on-chain anchors (SkillDefinitionRegistry).
|
|
6
|
-
* A claim — a Smart Agent's relation to a skill — is a PRIVATE verifiable credential
|
|
7
|
-
* in that agent's vault, pointing to an on-chain `(skillId, version)`. There is no
|
|
8
|
-
* on-chain claim registry; this SDK owns the credential shape + builders + the
|
|
9
|
-
* commitment/digest math + an on-chain definition reader.
|
|
10
|
-
*
|
|
11
|
-
* Neutral substrate — NO domain/faith vocabulary (spec 251).
|
|
2
|
+
* @deprecated Import `@agenticprimitives/capability-claims` instead.
|
|
3
|
+
* Compatibility re-export shim (ADR-0051).
|
|
12
4
|
*/
|
|
13
|
-
|
|
14
|
-
export declare const PACKAGE_NAME = "@agenticprimitives/agent-skills";
|
|
15
|
-
export declare const PACKAGE_STATUS: "w1-foundational";
|
|
16
|
-
export declare const SPEC_REF = "specs/251-skills-and-geo-features.md";
|
|
17
|
-
export type Uri = string;
|
|
18
|
-
export type Hex32 = `0x${string}`;
|
|
19
|
-
/** On-chain-bound skill kinds. `SKILL_KIND.Leaf === SkillDefinitionRegistry.KIND_LEAF`. */
|
|
20
|
-
export declare const SKILL_KIND: {
|
|
21
|
-
readonly Leaf: `0x${string}`;
|
|
22
|
-
readonly Domain: `0x${string}`;
|
|
23
|
-
readonly Custom: `0x${string}`;
|
|
24
|
-
};
|
|
25
|
-
export declare const SKILL_KIND_URI: {
|
|
26
|
-
readonly Leaf: "https://agenticprimitives.dev/ns/skill#Leaf";
|
|
27
|
-
readonly Domain: "https://agenticprimitives.dev/ns/skill#Domain";
|
|
28
|
-
readonly Custom: "https://agenticprimitives.dev/ns/skill#Custom";
|
|
29
|
-
};
|
|
30
|
-
/** Claim relations (C-box `aps:skillRelation`). Off-chain only (in the credential). */
|
|
31
|
-
export declare const SKILL_RELATION: {
|
|
32
|
-
readonly hasSkill: `0x${string}`;
|
|
33
|
-
readonly practicesSkill: `0x${string}`;
|
|
34
|
-
readonly certifiedIn: `0x${string}`;
|
|
35
|
-
readonly endorsesSkill: `0x${string}`;
|
|
36
|
-
readonly mentorsIn: `0x${string}`;
|
|
37
|
-
readonly canTrainOthersIn: `0x${string}`;
|
|
38
|
-
};
|
|
39
|
-
export type SkillVisibility = 'public' | 'public-coarse' | 'private-commitment' | 'private-zk' | 'offchain-only';
|
|
40
|
-
/** Relations that are meaningless about oneself — forbidden on a self claim (mirrors smart-agent). */
|
|
41
|
-
export declare const SELF_FORBIDDEN_RELATIONS: readonly Hex32[];
|
|
42
|
-
export declare const SELF_MAX_PROFICIENCY = 6000;
|
|
43
|
-
export declare const MAX_PROFICIENCY = 10000;
|
|
44
|
-
/** Compute a stable skillId from a canonical id key (keccak). */
|
|
45
|
-
export declare function computeSkillId(canonicalKey: string): Hex32;
|
|
46
|
-
/** Canonical conceptHash a steward commits on chain (keccak of prefLabel + ancestors). */
|
|
47
|
-
export declare function conceptHash(prefLabel: string, ancestors?: string[]): Hex32;
|
|
48
|
-
/** Payload a steward submits to `SkillDefinitionRegistry.publish(...)`. */
|
|
49
|
-
export interface SkillDefinitionPublishInput {
|
|
50
|
-
skillId: Hex32;
|
|
51
|
-
skillKind: Hex32;
|
|
52
|
-
stewardAccount: Address;
|
|
53
|
-
conceptHash: Hex32;
|
|
54
|
-
ontologyMerkleRoot: Hex32;
|
|
55
|
-
metadataURI: string;
|
|
56
|
-
validAfter: bigint;
|
|
57
|
-
validUntil: bigint;
|
|
58
|
-
}
|
|
59
|
-
/** A reference to an on-chain skill definition version — what a claim points to. */
|
|
60
|
-
export interface SkillDefinitionRef {
|
|
61
|
-
skillId: Hex32;
|
|
62
|
-
version: number;
|
|
63
|
-
}
|
|
64
|
-
export interface SkillClaimSubject {
|
|
65
|
-
/** The Smart Agent the claim is about. */
|
|
66
|
-
subject: Address;
|
|
67
|
-
/** The on-chain definition version this claim references. */
|
|
68
|
-
definition: SkillDefinitionRef;
|
|
69
|
-
/** A SKILL_RELATION value. */
|
|
70
|
-
relation: Hex32;
|
|
71
|
-
visibility: SkillVisibility;
|
|
72
|
-
/** 0..10000 basis points. */
|
|
73
|
-
proficiencyScore?: number;
|
|
74
|
-
/** keccak commitment / merkle root (ZK-targetable). NEVER a URI; preimage in the vault. */
|
|
75
|
-
evidenceCommit?: Hex32;
|
|
76
|
-
validAfter?: number;
|
|
77
|
-
validUntil?: number;
|
|
78
|
-
nonce: Hex32;
|
|
79
|
-
/** Deterministic claim id (see {@link skillClaimId}). */
|
|
80
|
-
claimId: Hex32;
|
|
81
|
-
}
|
|
82
|
-
/** The vault-resident skill claim credential (a VC). */
|
|
83
|
-
export interface SkillClaimCredential {
|
|
84
|
-
'@context': string[];
|
|
85
|
-
type: ['VerifiableCredential', 'SkillClaimCredential'];
|
|
86
|
-
/** CAIP-10 of the issuer Smart Agent. */
|
|
87
|
-
issuer: string;
|
|
88
|
-
validFrom?: string;
|
|
89
|
-
validUntil?: string;
|
|
90
|
-
credentialSubject: SkillClaimSubject;
|
|
91
|
-
}
|
|
92
|
-
/** Deterministic claim id = keccak(abi.encode(subject, skillId, relation, nonce)). */
|
|
93
|
-
export declare function skillClaimId(args: {
|
|
94
|
-
subject: Address;
|
|
95
|
-
skillId: Hex32;
|
|
96
|
-
relation: Hex32;
|
|
97
|
-
nonce: Hex32;
|
|
98
|
-
}): Hex32;
|
|
99
|
-
/**
|
|
100
|
-
* NEW-SKILL-1 — typehash now binds `chainId` + `verifyingContract` so an endorsement
|
|
101
|
-
* signature can't be replayed across chains or against a different SkillDefinitionRegistry
|
|
102
|
-
* deployment (mirrors the EIP-712 domain binding in payments/mandate-sign.ts).
|
|
103
|
-
*
|
|
104
|
-
* Typehash for the cross-issued endorsement (issuer signs; verified via ERC-1271).
|
|
105
|
-
*/
|
|
106
|
-
export declare const SKILL_ENDORSEMENT_TYPEHASH: Hex32;
|
|
107
|
-
/**
|
|
108
|
-
* The digest an issuer signs to endorse a cross-issued claim (ERC-1271-verifiable).
|
|
109
|
-
*
|
|
110
|
-
* NEW-SKILL-1 — `chainId` + `verifyingContract` are folded into the digest so the same
|
|
111
|
-
* endorsement can't be replayed on another chain or against a different registry deployment.
|
|
112
|
-
* `verifyingContract` is the SkillDefinitionRegistry the endorsed `(skillId, version)` lives in.
|
|
113
|
-
*/
|
|
114
|
-
export declare function skillEndorsementDigest(args: {
|
|
115
|
-
chainId: number;
|
|
116
|
-
verifyingContract: Address;
|
|
117
|
-
subject: Address;
|
|
118
|
-
skillId: Hex32;
|
|
119
|
-
skillVersion: number;
|
|
120
|
-
relation: Hex32;
|
|
121
|
-
proficiencyScore: number;
|
|
122
|
-
validAfter: number;
|
|
123
|
-
validUntil: number;
|
|
124
|
-
nonce: Hex32;
|
|
125
|
-
}): Hex32;
|
|
126
|
-
/** Build a SELF skill claim (subject == issuer). Capped proficiency; self-meaningless relations forbidden. */
|
|
127
|
-
export declare function buildSelfSkillClaim(args: {
|
|
128
|
-
chainId: number;
|
|
129
|
-
subject: Address;
|
|
130
|
-
definition: SkillDefinitionRef;
|
|
131
|
-
relation: Hex32;
|
|
132
|
-
visibility?: SkillVisibility;
|
|
133
|
-
proficiencyScore?: number;
|
|
134
|
-
evidenceCommit?: Hex32;
|
|
135
|
-
validAfter?: number;
|
|
136
|
-
validUntil?: number;
|
|
137
|
-
nonce: Hex32;
|
|
138
|
-
}): SkillClaimCredential;
|
|
139
|
-
/** Build an ENDORSED skill claim + the digest the issuer must sign (cross-issued; subject != issuer). */
|
|
140
|
-
export declare function buildEndorsedSkillClaim(args: {
|
|
141
|
-
chainId: number;
|
|
142
|
-
/** NEW-SKILL-1 — the SkillDefinitionRegistry the endorsed `(skillId, version)` lives in; bound into the digest. */
|
|
143
|
-
registry: Address;
|
|
144
|
-
subject: Address;
|
|
145
|
-
issuer: Address;
|
|
146
|
-
definition: SkillDefinitionRef;
|
|
147
|
-
relation: Hex32;
|
|
148
|
-
visibility?: SkillVisibility;
|
|
149
|
-
proficiencyScore?: number;
|
|
150
|
-
evidenceCommit?: Hex32;
|
|
151
|
-
validAfter?: number;
|
|
152
|
-
validUntil?: number;
|
|
153
|
-
nonce: Hex32;
|
|
154
|
-
}): {
|
|
155
|
-
credential: SkillClaimCredential;
|
|
156
|
-
endorsementDigest: Hex32;
|
|
157
|
-
};
|
|
158
|
-
/** The canonical hash of a claim credential body (for vault keys / receipts). */
|
|
159
|
-
export declare function skillClaimHash(credential: SkillClaimCredential): Hex;
|
|
160
|
-
/** Minimal read ABI for SkillDefinitionRegistry — `exists` + `latestVersion`. */
|
|
161
|
-
export declare const SKILL_DEFINITION_READ_ABI: readonly [{
|
|
162
|
-
readonly type: "function";
|
|
163
|
-
readonly name: "exists";
|
|
164
|
-
readonly stateMutability: "view";
|
|
165
|
-
readonly inputs: readonly [{
|
|
166
|
-
readonly name: "skillId";
|
|
167
|
-
readonly type: "bytes32";
|
|
168
|
-
}, {
|
|
169
|
-
readonly name: "version";
|
|
170
|
-
readonly type: "uint64";
|
|
171
|
-
}];
|
|
172
|
-
readonly outputs: readonly [{
|
|
173
|
-
readonly type: "bool";
|
|
174
|
-
}];
|
|
175
|
-
}, {
|
|
176
|
-
readonly type: "function";
|
|
177
|
-
readonly name: "latestVersion";
|
|
178
|
-
readonly stateMutability: "view";
|
|
179
|
-
readonly inputs: readonly [{
|
|
180
|
-
readonly name: "";
|
|
181
|
-
readonly type: "bytes32";
|
|
182
|
-
}];
|
|
183
|
-
readonly outputs: readonly [{
|
|
184
|
-
readonly type: "uint64";
|
|
185
|
-
}];
|
|
186
|
-
}];
|
|
187
|
-
/** A `readContract`-shaped function (inject viem's `publicClient.readContract`). */
|
|
188
|
-
export type ReadContractFn = (args: {
|
|
189
|
-
address: Address;
|
|
190
|
-
abi: typeof SKILL_DEFINITION_READ_ABI;
|
|
191
|
-
functionName: string;
|
|
192
|
-
args: readonly unknown[];
|
|
193
|
-
}) => Promise<unknown>;
|
|
194
|
-
/** Confirm a claim's pinned `(skillId, version)` still exists on the registry. */
|
|
195
|
-
export declare function skillDefinitionExists(read: ReadContractFn, registry: Address, ref: SkillDefinitionRef): Promise<boolean>;
|
|
5
|
+
export * from '@agenticprimitives/capability-claims';
|
|
196
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,sCAAsC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,197 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @agenticprimitives/
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Definitions are PUBLIC, versioned, on-chain anchors (SkillDefinitionRegistry).
|
|
6
|
-
* A claim — a Smart Agent's relation to a skill — is a PRIVATE verifiable credential
|
|
7
|
-
* in that agent's vault, pointing to an on-chain `(skillId, version)`. There is no
|
|
8
|
-
* on-chain claim registry; this SDK owns the credential shape + builders + the
|
|
9
|
-
* commitment/digest math + an on-chain definition reader.
|
|
10
|
-
*
|
|
11
|
-
* Neutral substrate — NO domain/faith vocabulary (spec 251).
|
|
2
|
+
* @deprecated Import `@agenticprimitives/capability-claims` instead.
|
|
3
|
+
* Compatibility re-export shim (ADR-0051).
|
|
12
4
|
*/
|
|
13
|
-
|
|
14
|
-
import { utf8ToBytes } from '@noble/hashes/utils.js';
|
|
15
|
-
import { credentialHash, VC_CONTEXT_V2 } from '@agenticprimitives/verifiable-credentials';
|
|
16
|
-
export const PACKAGE_NAME = '@agenticprimitives/agent-skills';
|
|
17
|
-
export const PACKAGE_STATUS = 'w1-foundational';
|
|
18
|
-
export const SPEC_REF = 'specs/251-skills-and-geo-features.md';
|
|
19
|
-
const NS = 'https://agenticprimitives.dev/ns/skill#';
|
|
20
|
-
// ─── C-box codelists (keccak of the ns/skill# concept URIs) ────────────────
|
|
21
|
-
// The kind values are LOCKSTEP with SkillDefinitionRegistry.KIND_* (ADR-0009);
|
|
22
|
-
// the cross-stack test asserts equality against the live .sol.
|
|
23
|
-
/** On-chain-bound skill kinds. `SKILL_KIND.Leaf === SkillDefinitionRegistry.KIND_LEAF`. */
|
|
24
|
-
export const SKILL_KIND = {
|
|
25
|
-
Leaf: hashUri(`${NS}Leaf`),
|
|
26
|
-
Domain: hashUri(`${NS}Domain`),
|
|
27
|
-
Custom: hashUri(`${NS}Custom`),
|
|
28
|
-
};
|
|
29
|
-
export const SKILL_KIND_URI = { Leaf: `${NS}Leaf`, Domain: `${NS}Domain`, Custom: `${NS}Custom` };
|
|
30
|
-
/** Claim relations (C-box `aps:skillRelation`). Off-chain only (in the credential). */
|
|
31
|
-
export const SKILL_RELATION = {
|
|
32
|
-
hasSkill: hashUri(`${NS}hasSkill`),
|
|
33
|
-
practicesSkill: hashUri(`${NS}practicesSkill`),
|
|
34
|
-
certifiedIn: hashUri(`${NS}certifiedIn`),
|
|
35
|
-
endorsesSkill: hashUri(`${NS}endorsesSkill`),
|
|
36
|
-
mentorsIn: hashUri(`${NS}mentorsIn`),
|
|
37
|
-
canTrainOthersIn: hashUri(`${NS}canTrainOthersIn`),
|
|
38
|
-
};
|
|
39
|
-
/** Relations that are meaningless about oneself — forbidden on a self claim (mirrors smart-agent). */
|
|
40
|
-
export const SELF_FORBIDDEN_RELATIONS = [
|
|
41
|
-
SKILL_RELATION.certifiedIn,
|
|
42
|
-
SKILL_RELATION.endorsesSkill,
|
|
43
|
-
SKILL_RELATION.mentorsIn,
|
|
44
|
-
SKILL_RELATION.canTrainOthersIn,
|
|
45
|
-
];
|
|
46
|
-
export const SELF_MAX_PROFICIENCY = 6000;
|
|
47
|
-
export const MAX_PROFICIENCY = 10000;
|
|
48
|
-
// ─── Definitions (the on-chain anchor) ─────────────────────────────────────
|
|
49
|
-
/** Compute a stable skillId from a canonical id key (keccak). */
|
|
50
|
-
export function computeSkillId(canonicalKey) {
|
|
51
|
-
return hashUri(canonicalKey);
|
|
52
|
-
}
|
|
53
|
-
/** Canonical conceptHash a steward commits on chain (keccak of prefLabel + ancestors). */
|
|
54
|
-
export function conceptHash(prefLabel, ancestors = []) {
|
|
55
|
-
return hashUri([prefLabel, ...ancestors].join('|'));
|
|
56
|
-
}
|
|
57
|
-
/** Deterministic claim id = keccak(abi.encode(subject, skillId, relation, nonce)). */
|
|
58
|
-
export function skillClaimId(args) {
|
|
59
|
-
const buf = new Uint8Array(4 * 32);
|
|
60
|
-
writeAddress(buf, 0, args.subject);
|
|
61
|
-
writeHex32(buf, 32, args.skillId);
|
|
62
|
-
writeHex32(buf, 64, args.relation);
|
|
63
|
-
writeHex32(buf, 96, args.nonce);
|
|
64
|
-
return toHex32(keccak_256(buf));
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* NEW-SKILL-1 — typehash now binds `chainId` + `verifyingContract` so an endorsement
|
|
68
|
-
* signature can't be replayed across chains or against a different SkillDefinitionRegistry
|
|
69
|
-
* deployment (mirrors the EIP-712 domain binding in payments/mandate-sign.ts).
|
|
70
|
-
*
|
|
71
|
-
* Typehash for the cross-issued endorsement (issuer signs; verified via ERC-1271).
|
|
72
|
-
*/
|
|
73
|
-
export const SKILL_ENDORSEMENT_TYPEHASH = hashUri('SkillEndorsement(uint256 chainId,address verifyingContract,address subjectAgent,bytes32 skillId,uint64 skillVersion,bytes32 relation,uint16 proficiencyScore,uint64 validAfter,uint64 validUntil,bytes32 nonce)');
|
|
74
|
-
/**
|
|
75
|
-
* The digest an issuer signs to endorse a cross-issued claim (ERC-1271-verifiable).
|
|
76
|
-
*
|
|
77
|
-
* NEW-SKILL-1 — `chainId` + `verifyingContract` are folded into the digest so the same
|
|
78
|
-
* endorsement can't be replayed on another chain or against a different registry deployment.
|
|
79
|
-
* `verifyingContract` is the SkillDefinitionRegistry the endorsed `(skillId, version)` lives in.
|
|
80
|
-
*/
|
|
81
|
-
export function skillEndorsementDigest(args) {
|
|
82
|
-
const buf = new Uint8Array(11 * 32);
|
|
83
|
-
writeHex32(buf, 0, SKILL_ENDORSEMENT_TYPEHASH);
|
|
84
|
-
writeUint(buf, 32, BigInt(args.chainId));
|
|
85
|
-
writeAddress(buf, 64, args.verifyingContract);
|
|
86
|
-
writeAddress(buf, 96, args.subject);
|
|
87
|
-
writeHex32(buf, 128, args.skillId);
|
|
88
|
-
writeUint(buf, 160, BigInt(args.skillVersion));
|
|
89
|
-
writeHex32(buf, 192, args.relation);
|
|
90
|
-
writeUint(buf, 224, BigInt(args.proficiencyScore));
|
|
91
|
-
writeUint(buf, 256, BigInt(args.validAfter));
|
|
92
|
-
writeUint(buf, 288, BigInt(args.validUntil));
|
|
93
|
-
writeHex32(buf, 320, args.nonce);
|
|
94
|
-
return toHex32(keccak_256(buf));
|
|
95
|
-
}
|
|
96
|
-
function caip10(chainId, addr) {
|
|
97
|
-
return `eip155:${chainId}:${addr}`;
|
|
98
|
-
}
|
|
99
|
-
function buildSubject(args) {
|
|
100
|
-
return {
|
|
101
|
-
subject: args.subject,
|
|
102
|
-
definition: args.definition,
|
|
103
|
-
relation: args.relation,
|
|
104
|
-
visibility: args.visibility,
|
|
105
|
-
proficiencyScore: args.proficiencyScore,
|
|
106
|
-
evidenceCommit: args.evidenceCommit,
|
|
107
|
-
validAfter: args.validAfter,
|
|
108
|
-
validUntil: args.validUntil,
|
|
109
|
-
nonce: args.nonce,
|
|
110
|
-
claimId: skillClaimId({ subject: args.subject, skillId: args.definition.skillId, relation: args.relation, nonce: args.nonce }),
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
/** Build a SELF skill claim (subject == issuer). Capped proficiency; self-meaningless relations forbidden. */
|
|
114
|
-
export function buildSelfSkillClaim(args) {
|
|
115
|
-
if (SELF_FORBIDDEN_RELATIONS.includes(args.relation)) {
|
|
116
|
-
throw new Error('agent-skills: that relation is meaningless about oneself (use an endorsed claim)');
|
|
117
|
-
}
|
|
118
|
-
if ((args.proficiencyScore ?? 0) > SELF_MAX_PROFICIENCY) {
|
|
119
|
-
throw new Error(`agent-skills: self proficiency capped at ${SELF_MAX_PROFICIENCY}`);
|
|
120
|
-
}
|
|
121
|
-
return {
|
|
122
|
-
'@context': [VC_CONTEXT_V2],
|
|
123
|
-
type: ['VerifiableCredential', 'SkillClaimCredential'],
|
|
124
|
-
issuer: caip10(args.chainId, args.subject),
|
|
125
|
-
credentialSubject: buildSubject({ ...args, visibility: args.visibility ?? 'private-commitment' }),
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
/** Build an ENDORSED skill claim + the digest the issuer must sign (cross-issued; subject != issuer). */
|
|
129
|
-
export function buildEndorsedSkillClaim(args) {
|
|
130
|
-
if (args.subject === args.issuer)
|
|
131
|
-
throw new Error('agent-skills: an endorsed claim must be cross-issued');
|
|
132
|
-
if ((args.proficiencyScore ?? 0) > MAX_PROFICIENCY)
|
|
133
|
-
throw new Error('agent-skills: proficiency out of range');
|
|
134
|
-
const credential = {
|
|
135
|
-
'@context': [VC_CONTEXT_V2],
|
|
136
|
-
type: ['VerifiableCredential', 'SkillClaimCredential'],
|
|
137
|
-
issuer: caip10(args.chainId, args.issuer),
|
|
138
|
-
credentialSubject: buildSubject({ ...args, visibility: args.visibility ?? 'public' }),
|
|
139
|
-
};
|
|
140
|
-
const endorsementDigest = skillEndorsementDigest({
|
|
141
|
-
chainId: args.chainId, // NEW-SKILL-1 — bind chain + registry so the signature is deployment-scoped
|
|
142
|
-
verifyingContract: args.registry,
|
|
143
|
-
subject: args.subject,
|
|
144
|
-
skillId: args.definition.skillId,
|
|
145
|
-
skillVersion: args.definition.version,
|
|
146
|
-
relation: args.relation,
|
|
147
|
-
proficiencyScore: args.proficiencyScore ?? 0,
|
|
148
|
-
validAfter: args.validAfter ?? 0,
|
|
149
|
-
validUntil: args.validUntil ?? 0,
|
|
150
|
-
nonce: args.nonce,
|
|
151
|
-
});
|
|
152
|
-
return { credential, endorsementDigest };
|
|
153
|
-
}
|
|
154
|
-
/** The canonical hash of a claim credential body (for vault keys / receipts). */
|
|
155
|
-
export function skillClaimHash(credential) {
|
|
156
|
-
return credentialHash(credential);
|
|
157
|
-
}
|
|
158
|
-
// ─── On-chain definition reader (minimal ABI fragment) ─────────────────────
|
|
159
|
-
/** Minimal read ABI for SkillDefinitionRegistry — `exists` + `latestVersion`. */
|
|
160
|
-
export const SKILL_DEFINITION_READ_ABI = [
|
|
161
|
-
{ type: 'function', name: 'exists', stateMutability: 'view', inputs: [{ name: 'skillId', type: 'bytes32' }, { name: 'version', type: 'uint64' }], outputs: [{ type: 'bool' }] },
|
|
162
|
-
{ type: 'function', name: 'latestVersion', stateMutability: 'view', inputs: [{ name: '', type: 'bytes32' }], outputs: [{ type: 'uint64' }] },
|
|
163
|
-
];
|
|
164
|
-
/** Confirm a claim's pinned `(skillId, version)` still exists on the registry. */
|
|
165
|
-
export async function skillDefinitionExists(read, registry, ref) {
|
|
166
|
-
return (await read({ address: registry, abi: SKILL_DEFINITION_READ_ABI, functionName: 'exists', args: [ref.skillId, BigInt(ref.version)] }));
|
|
167
|
-
}
|
|
168
|
-
// ─── Hash helpers ──────────────────────────────────────────────────────────
|
|
169
|
-
function hashUri(s) {
|
|
170
|
-
return toHex32(keccak_256(utf8ToBytes(s)));
|
|
171
|
-
}
|
|
172
|
-
function toHex32(b) {
|
|
173
|
-
let hex = '0x';
|
|
174
|
-
for (const v of b)
|
|
175
|
-
hex += v.toString(16).padStart(2, '0');
|
|
176
|
-
return hex;
|
|
177
|
-
}
|
|
178
|
-
function writeHex32(buf, offset, h) {
|
|
179
|
-
const clean = h.toLowerCase().replace(/^0x/, '').padStart(64, '0');
|
|
180
|
-
for (let i = 0; i < 32; i++)
|
|
181
|
-
buf[offset + i] = parseInt(clean.substring(i * 2, i * 2 + 2), 16);
|
|
182
|
-
}
|
|
183
|
-
function writeAddress(buf, offset, addr) {
|
|
184
|
-
const clean = addr.toLowerCase().replace(/^0x/, '');
|
|
185
|
-
if (clean.length !== 40)
|
|
186
|
-
throw new Error(`bad address: ${addr}`);
|
|
187
|
-
for (let i = 0; i < 20; i++)
|
|
188
|
-
buf[offset + 12 + i] = parseInt(clean.substring(i * 2, i * 2 + 2), 16);
|
|
189
|
-
}
|
|
190
|
-
function writeUint(buf, offset, n) {
|
|
191
|
-
let v = n;
|
|
192
|
-
for (let i = 31; i >= 0; i--) {
|
|
193
|
-
buf[offset + i] = Number(v & 0xffn);
|
|
194
|
-
v >>= 8n;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
5
|
+
export * from '@agenticprimitives/capability-claims';
|
|
197
6
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,sCAAsC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agenticprimitives/agent-skills",
|
|
3
|
-
"version": "0.0.0-alpha.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.0-alpha.15",
|
|
4
|
+
"description": "Deprecated alias — re-exports @agenticprimitives/capability-claims (ADR-0051).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -25,19 +25,17 @@
|
|
|
25
25
|
"publishConfig": {
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@agenticprimitives/capability-claims": "0.0.0-alpha.15"
|
|
30
|
+
},
|
|
28
31
|
"devDependencies": {
|
|
29
32
|
"vitest": "^4.1.8"
|
|
30
33
|
},
|
|
31
34
|
"keywords": [
|
|
32
35
|
"agentic",
|
|
33
36
|
"primitives",
|
|
34
|
-
"
|
|
37
|
+
"deprecated"
|
|
35
38
|
],
|
|
36
|
-
"dependencies": {
|
|
37
|
-
"@noble/hashes": "^2.2.0",
|
|
38
|
-
"@agenticprimitives/types": "1.0.0-alpha.16",
|
|
39
|
-
"@agenticprimitives/verifiable-credentials": "0.0.0-alpha.13"
|
|
40
|
-
},
|
|
41
39
|
"scripts": {
|
|
42
40
|
"build": "tsc -p tsconfig.build.json",
|
|
43
41
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|