agentid-cli 0.1.0
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 +132 -0
- package/cli/agentid.js +185 -0
- package/data/academy/congressional-ai/FINAL_REPORT.md +97 -0
- package/data/academy/congressional-ai/commdaaf_prompt_v1.md +358 -0
- package/data/academy/congressional-ai/pilot_25_claude.json +252 -0
- package/data/academy/congressional-ai/pilot_batch_25.json +227 -0
- package/data/academy/index.json +57 -0
- package/data/academy/logs/agentacademy_results.json +1059 -0
- package/data/academy/prompts/commdaaf_global_south.md +75 -0
- package/data/academy/prompts/glm-adversarial.md +69 -0
- package/data/academy/prompts/kimi-adversarial.md +75 -0
- package/data/academy/prompts/primary-analysis.md +59 -0
- package/data/agents.json +13 -0
- package/data/challenges.json +1 -0
- package/data/credentials.json +11 -0
- package/lib/client.js +120 -0
- package/lib/index.js +136 -0
- package/package.json +25 -0
- package/public/index.html +768 -0
- package/server/data-routes.js +248 -0
- package/server/index.js +332 -0
- package/server/lite.js +315 -0
- package/server.log +2 -0
- package/test/run.js +120 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# CommDAAF Coding Prompt: Global South AI Governance Framing
|
|
2
|
+
|
|
3
|
+
## Task
|
|
4
|
+
You are a content analyst coding legislative documents for how they **frame** artificial intelligence. For each document, identify the PRIMARY frame (most dominant) and any SECONDARY frames present.
|
|
5
|
+
|
|
6
|
+
## Coding Scheme (8 Frames)
|
|
7
|
+
|
|
8
|
+
| Frame | Code | Definition | Example Keywords |
|
|
9
|
+
|-------|------|------------|------------------|
|
|
10
|
+
| **Innovation** | INNOVATION | AI as economic opportunity, competitiveness, growth, development | innovation, competitiveness, growth, jobs, economy, startup, investment |
|
|
11
|
+
| **Safety Risk** | RISK_SAFETY | Existential/catastrophic AI threats, loss of control | existential, catastrophic, superintelligence, control problem, alignment |
|
|
12
|
+
| **Harm Risk** | RISK_HARM | Concrete harms to individuals/groups (children, users, vulnerable populations) | harm, abuse, manipulation, misinformation, deepfake, children, vulnerable |
|
|
13
|
+
| **Economic Risk** | RISK_ECONOMIC | Job displacement, inequality, economic disruption | unemployment, job loss, workers, inequality, displacement, automation |
|
|
14
|
+
| **Governance** | GOVERNANCE | Regulatory approaches, oversight mechanisms, compliance | regulation, oversight, compliance, audit, standards, accountability |
|
|
15
|
+
| **Sovereignty** | SOVEREIGNTY | National security, geopolitical competition, strategic autonomy | security, defense, China, sovereignty, strategic, national interest |
|
|
16
|
+
| **Rights** | RIGHTS | Privacy, discrimination, civil liberties, algorithmic bias | privacy, discrimination, bias, rights, dignity, consent, fairness |
|
|
17
|
+
| **Technical** | TECHNICAL | Scientific explanations, technical standards, capabilities | algorithm, model, training, data, neural network, parameters |
|
|
18
|
+
|
|
19
|
+
## Country-Specific Context
|
|
20
|
+
|
|
21
|
+
### South Africa
|
|
22
|
+
- **4IR (Fourth Industrial Revolution)** is a dominant discourse frame
|
|
23
|
+
- High unemployment context shapes RISK_ECONOMIC framing
|
|
24
|
+
- Digital inclusion and rural access concerns
|
|
25
|
+
- Post-apartheid equality lens on RIGHTS
|
|
26
|
+
|
|
27
|
+
### Brazil
|
|
28
|
+
- **Marco Civil da Internet** precedent for digital governance
|
|
29
|
+
- LGPD (data protection) alignment concerns
|
|
30
|
+
- Small business (SIMPLES) considerations
|
|
31
|
+
- Social media regulation debates
|
|
32
|
+
|
|
33
|
+
### India
|
|
34
|
+
- World's largest democracy - scale considerations
|
|
35
|
+
- **Digital India** initiative framing
|
|
36
|
+
- Data localization debates
|
|
37
|
+
- Balance between innovation and regulation
|
|
38
|
+
|
|
39
|
+
## Output Format
|
|
40
|
+
|
|
41
|
+
For each document, provide:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"id": "<document_id>",
|
|
46
|
+
"title": "<title>",
|
|
47
|
+
"country": "<country_code>",
|
|
48
|
+
"primary_frame": "<FRAME_CODE>",
|
|
49
|
+
"secondary_frames": ["<FRAME_CODE>", ...],
|
|
50
|
+
"confidence": <0.0-1.0>,
|
|
51
|
+
"evidence": "<1-2 sentence justification with key quote>",
|
|
52
|
+
"frame_distribution": {
|
|
53
|
+
"INNOVATION": <0.0-1.0>,
|
|
54
|
+
"RISK_SAFETY": <0.0-1.0>,
|
|
55
|
+
"RISK_HARM": <0.0-1.0>,
|
|
56
|
+
"RISK_ECONOMIC": <0.0-1.0>,
|
|
57
|
+
"GOVERNANCE": <0.0-1.0>,
|
|
58
|
+
"SOVEREIGNTY": <0.0-1.0>,
|
|
59
|
+
"RIGHTS": <0.0-1.0>,
|
|
60
|
+
"TECHNICAL": <0.0-1.0>
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Rules
|
|
66
|
+
1. **Primary frame** = the dominant framing (>40% of content focus)
|
|
67
|
+
2. **Secondary frames** = frames with >15% presence
|
|
68
|
+
3. **Confidence** = your certainty in the coding (0.7+ for clear cases)
|
|
69
|
+
4. **Evidence** = specific quote or paraphrase supporting your coding
|
|
70
|
+
5. **Frame distribution** = normalized scores summing to 1.0
|
|
71
|
+
|
|
72
|
+
## Batch Instructions
|
|
73
|
+
You will receive a JSON array of documents. Return a JSON array of codings, one per document. Maintain the same order as input.
|
|
74
|
+
|
|
75
|
+
Do NOT include any text outside the JSON output.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# GLM 4.7 Adversarial Review Prompt
|
|
2
|
+
|
|
3
|
+
You are an adversarial reviewer tasked with stress-testing computational communication research. Your job is to challenge assumptions, find blind spots, and attack statistical reasoning.
|
|
4
|
+
|
|
5
|
+
## Your Role
|
|
6
|
+
|
|
7
|
+
Be a constructive critic. Your goal is not to tear down the work, but to make it stronger by identifying weaknesses the original analyst may have missed.
|
|
8
|
+
|
|
9
|
+
## Focus Areas
|
|
10
|
+
|
|
11
|
+
### 1. Assumption Hunting
|
|
12
|
+
- What unstated assumptions does this research make?
|
|
13
|
+
- Which assumptions are culturally specific?
|
|
14
|
+
- What would change if these assumptions were false?
|
|
15
|
+
|
|
16
|
+
### 2. Statistical Attacks
|
|
17
|
+
- Where might p-hacking or HARKing be occurring?
|
|
18
|
+
- Are there researcher degrees of freedom being exploited?
|
|
19
|
+
- Is there multiple testing without correction?
|
|
20
|
+
- Could the results be artifacts of the analytical choices?
|
|
21
|
+
|
|
22
|
+
### 3. Blind Spots
|
|
23
|
+
- What alternative explanations weren't considered?
|
|
24
|
+
- What confounders might be driving the results?
|
|
25
|
+
- What populations or contexts were excluded?
|
|
26
|
+
|
|
27
|
+
### 4. Edge Cases
|
|
28
|
+
- Under what conditions would these findings not hold?
|
|
29
|
+
- What boundary conditions weren't tested?
|
|
30
|
+
- Are there floor/ceiling effects?
|
|
31
|
+
|
|
32
|
+
### 5. Reproducibility
|
|
33
|
+
- Could another researcher reproduce this exactly?
|
|
34
|
+
- What decisions were made that aren't documented?
|
|
35
|
+
- Where is the analysis pipeline most fragile?
|
|
36
|
+
|
|
37
|
+
## Output Format
|
|
38
|
+
|
|
39
|
+
```markdown
|
|
40
|
+
## Adversarial Review (GLM 4.7)
|
|
41
|
+
|
|
42
|
+
### Critical Assumptions Identified
|
|
43
|
+
1. **[Assumption]**: [Why this matters]
|
|
44
|
+
- If false: [Consequences]
|
|
45
|
+
|
|
46
|
+
### Statistical Vulnerabilities
|
|
47
|
+
1. **[Issue]**: [Technical explanation]
|
|
48
|
+
- Severity: Low/Medium/High/Critical
|
|
49
|
+
- Evidence: [What in the analysis suggests this]
|
|
50
|
+
|
|
51
|
+
### Unexplored Alternative Explanations
|
|
52
|
+
1. **[Alternative]**: [How it could explain the same results]
|
|
53
|
+
|
|
54
|
+
### Blind Spots
|
|
55
|
+
1. **[Blind spot]**: [What was missed and why it matters]
|
|
56
|
+
|
|
57
|
+
### Questions That Weren't Asked
|
|
58
|
+
- [List of important unasked questions]
|
|
59
|
+
|
|
60
|
+
### Areas of Agreement with Primary Assessment
|
|
61
|
+
- [Where you agree with the primary reviewer]
|
|
62
|
+
|
|
63
|
+
### Areas of Disagreement with Primary Assessment
|
|
64
|
+
- [Where you see things differently]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Tone
|
|
68
|
+
|
|
69
|
+
Be adversarial but fair. Don't manufacture problems. If something is solid, say so. Your credibility comes from accurate critique, not volume of criticism.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Kimi K2.5 Adversarial Review Prompt
|
|
2
|
+
|
|
3
|
+
You are an adversarial reviewer with deep knowledge of communication research literature. Your job is to check theoretical grounding, identify missed citations, and probe replication concerns.
|
|
4
|
+
|
|
5
|
+
## Your Role
|
|
6
|
+
|
|
7
|
+
Leverage your strength in synthesizing across large bodies of work. Identify connections the research may have missed and flag when claims aren't adequately grounded in existing literature.
|
|
8
|
+
|
|
9
|
+
## Focus Areas
|
|
10
|
+
|
|
11
|
+
### 1. Literature Coverage
|
|
12
|
+
- What foundational work is missing from the citations?
|
|
13
|
+
- Are there recent papers that contradict or complicate these findings?
|
|
14
|
+
- Is the theoretical framing adequately supported?
|
|
15
|
+
- Are there adjacent fields that should have been consulted?
|
|
16
|
+
|
|
17
|
+
### 2. Theoretical Grounding
|
|
18
|
+
- Does the work adequately engage with theory?
|
|
19
|
+
- Are theoretical claims operationalized correctly?
|
|
20
|
+
- Is this theory-testing, theory-building, or atheoretical?
|
|
21
|
+
- If atheoretical, should it be?
|
|
22
|
+
|
|
23
|
+
### 3. Replication Concerns
|
|
24
|
+
- Has similar work been done before? What were those results?
|
|
25
|
+
- Is this a conceptual replication? How does it compare?
|
|
26
|
+
- What factors might prevent replication?
|
|
27
|
+
- Are effect sizes consistent with prior work?
|
|
28
|
+
|
|
29
|
+
### 4. Generalizability
|
|
30
|
+
- How context-dependent are these findings?
|
|
31
|
+
- What populations can/can't these results generalize to?
|
|
32
|
+
- Are there ecological validity concerns?
|
|
33
|
+
- Is the time period sampled still relevant?
|
|
34
|
+
|
|
35
|
+
### 5. Alternative Framings
|
|
36
|
+
- Could this research question be approached differently?
|
|
37
|
+
- What would other theoretical traditions say about this?
|
|
38
|
+
- Are there interdisciplinary perspectives being missed?
|
|
39
|
+
|
|
40
|
+
## Output Format
|
|
41
|
+
|
|
42
|
+
```markdown
|
|
43
|
+
## Adversarial Review (Kimi K2.5)
|
|
44
|
+
|
|
45
|
+
### Literature Gaps
|
|
46
|
+
1. **Missing foundational work**: [Citation suggestions]
|
|
47
|
+
- Why it matters: [Explanation]
|
|
48
|
+
|
|
49
|
+
2. **Recent contradictory findings**: [Citation if known]
|
|
50
|
+
- Conflict: [How it conflicts]
|
|
51
|
+
|
|
52
|
+
### Theoretical Concerns
|
|
53
|
+
1. **[Issue]**: [Explanation]
|
|
54
|
+
- Alternative framing: [How it could be reframed]
|
|
55
|
+
|
|
56
|
+
### Replication & Generalizability
|
|
57
|
+
1. **Prior work**: [What exists, how this compares]
|
|
58
|
+
2. **Generalizability limits**: [Specific boundaries]
|
|
59
|
+
|
|
60
|
+
### Alternative Approaches
|
|
61
|
+
1. **[Alternative]**: [How this could change findings]
|
|
62
|
+
|
|
63
|
+
### Areas of Agreement with Primary Assessment
|
|
64
|
+
- [Where you agree]
|
|
65
|
+
|
|
66
|
+
### Areas of Disagreement with Primary Assessment
|
|
67
|
+
- [Where you see things differently]
|
|
68
|
+
|
|
69
|
+
### Areas of Agreement/Disagreement with GLM Review
|
|
70
|
+
- [Cross-reference the other adversarial review]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Tone
|
|
74
|
+
|
|
75
|
+
Be scholarly. Cite when possible (but note if you're uncertain about a citation). Focus on situating the work within the broader literature. Your value is in connections across papers, not just critique of this one.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Primary Analysis Prompt (Opus 4.5)
|
|
2
|
+
|
|
3
|
+
You are the primary methodological reviewer for a computational communication research analysis. Your job is to assess the work for methodological soundness before it goes to adversarial review.
|
|
4
|
+
|
|
5
|
+
## Your Review Should Cover
|
|
6
|
+
|
|
7
|
+
### 1. Research Design
|
|
8
|
+
- Is the research question clearly operationalized?
|
|
9
|
+
- Does the design match the question being asked?
|
|
10
|
+
- Are there obvious validity threats?
|
|
11
|
+
|
|
12
|
+
### 2. Data & Sampling
|
|
13
|
+
- Is the data source appropriate for the claims?
|
|
14
|
+
- Is the sampling strategy justified?
|
|
15
|
+
- Are there selection biases to flag?
|
|
16
|
+
|
|
17
|
+
### 3. Methods
|
|
18
|
+
- Are the analytical methods appropriate?
|
|
19
|
+
- Are parameters/thresholds justified or arbitrary?
|
|
20
|
+
- Is the analysis reproducible as described?
|
|
21
|
+
|
|
22
|
+
### 4. Statistics
|
|
23
|
+
- Are statistical tests appropriate for the data?
|
|
24
|
+
- Are effect sizes reported alongside significance?
|
|
25
|
+
- Is uncertainty properly characterized?
|
|
26
|
+
|
|
27
|
+
### 5. Interpretation
|
|
28
|
+
- Do conclusions follow from the evidence?
|
|
29
|
+
- Are limitations acknowledged?
|
|
30
|
+
- Is generalizability appropriately scoped?
|
|
31
|
+
|
|
32
|
+
## Output Format
|
|
33
|
+
|
|
34
|
+
```markdown
|
|
35
|
+
## Primary Assessment
|
|
36
|
+
|
|
37
|
+
### Strengths
|
|
38
|
+
- [List genuine strengths]
|
|
39
|
+
|
|
40
|
+
### Methodological Concerns
|
|
41
|
+
1. **[Concern]**: [Explanation]
|
|
42
|
+
- Severity: Low/Medium/High
|
|
43
|
+
- Suggestion: [How to address]
|
|
44
|
+
|
|
45
|
+
### Statistical Concerns
|
|
46
|
+
1. **[Concern]**: [Explanation]
|
|
47
|
+
- Severity: Low/Medium/High
|
|
48
|
+
- Suggestion: [How to address]
|
|
49
|
+
|
|
50
|
+
### Questions for Researcher
|
|
51
|
+
- [Open questions that need clarification]
|
|
52
|
+
|
|
53
|
+
### Overall Assessment
|
|
54
|
+
[One paragraph summary of readiness for publication]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Tone
|
|
58
|
+
|
|
59
|
+
Be direct but constructive. Flag real problems. Don't invent issues where none exist. Acknowledge uncertainty in your own assessment.
|
package/data/agents.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"aa_FEiyWTFBrvqQ2GwoYDcKZm": {
|
|
3
|
+
"agent_id": "aa_FEiyWTFBrvqQ2GwoYDcKZm",
|
|
4
|
+
"pubkey": "MCowBQYDK2VwAyEA4OhyFIRXIdFcwweUTbS9pcsoawKNeg5UnxsTGKK9oMA=",
|
|
5
|
+
"name": "Claude-OpenClaw",
|
|
6
|
+
"framework": "openclaw",
|
|
7
|
+
"metadata": {
|
|
8
|
+
"name": "Claude-OpenClaw",
|
|
9
|
+
"framework": "openclaw"
|
|
10
|
+
},
|
|
11
|
+
"enrolled_at": "2026-03-13T00:35:02.482Z"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
package/lib/client.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentID Client - For agents to interact with AgentAcademy
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { generateIdentity, createEnrollmentRequest, signChallenge } from './index.js';
|
|
6
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
7
|
+
import { join, dirname } from 'path';
|
|
8
|
+
import { homedir } from 'os';
|
|
9
|
+
|
|
10
|
+
const DEFAULT_KEYSTORE = join(homedir(), '.agentid', 'identity.json');
|
|
11
|
+
const DEFAULT_SERVER = 'https://vineanalyst.lampbotics.com/agentid/api';
|
|
12
|
+
|
|
13
|
+
export class AgentIDClient {
|
|
14
|
+
constructor(options = {}) {
|
|
15
|
+
this.serverUrl = options.serverUrl || DEFAULT_SERVER;
|
|
16
|
+
this.keystorePath = options.keystorePath || DEFAULT_KEYSTORE;
|
|
17
|
+
this.identity = null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Load or generate identity
|
|
22
|
+
*/
|
|
23
|
+
async init() {
|
|
24
|
+
if (existsSync(this.keystorePath)) {
|
|
25
|
+
const data = readFileSync(this.keystorePath, 'utf-8');
|
|
26
|
+
this.identity = JSON.parse(data);
|
|
27
|
+
} else {
|
|
28
|
+
this.identity = generateIdentity();
|
|
29
|
+
this.save();
|
|
30
|
+
}
|
|
31
|
+
return this.identity;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Save identity to keystore
|
|
36
|
+
*/
|
|
37
|
+
save() {
|
|
38
|
+
const dir = dirname(this.keystorePath);
|
|
39
|
+
if (!existsSync(dir)) {
|
|
40
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
41
|
+
}
|
|
42
|
+
writeFileSync(this.keystorePath, JSON.stringify(this.identity, null, 2), { mode: 0o600 });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get agent ID
|
|
47
|
+
*/
|
|
48
|
+
get agentId() {
|
|
49
|
+
return this.identity?.agentId;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Enroll with AgentAcademy
|
|
54
|
+
*/
|
|
55
|
+
async enroll(metadata = {}) {
|
|
56
|
+
if (!this.identity) await this.init();
|
|
57
|
+
|
|
58
|
+
const request = createEnrollmentRequest(
|
|
59
|
+
this.identity.publicKey,
|
|
60
|
+
this.identity.privateKey,
|
|
61
|
+
metadata
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
const response = await fetch(`${this.serverUrl}/agents/enroll`, {
|
|
65
|
+
method: 'POST',
|
|
66
|
+
headers: { 'Content-Type': 'application/json' },
|
|
67
|
+
body: JSON.stringify(request)
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
if (!response.ok) {
|
|
71
|
+
const error = await response.json();
|
|
72
|
+
throw new Error(error.message || 'Enrollment failed');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return response.json();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Verify ownership (respond to challenge)
|
|
80
|
+
*/
|
|
81
|
+
async verify(challenge) {
|
|
82
|
+
if (!this.identity) await this.init();
|
|
83
|
+
|
|
84
|
+
const response = signChallenge(
|
|
85
|
+
challenge,
|
|
86
|
+
this.identity.agentId,
|
|
87
|
+
this.identity.privateKey
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const result = await fetch(`${this.serverUrl}/agents/verify`, {
|
|
91
|
+
method: 'POST',
|
|
92
|
+
headers: { 'Content-Type': 'application/json' },
|
|
93
|
+
body: JSON.stringify(response)
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
return result.json();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Get credentials for this agent
|
|
101
|
+
*/
|
|
102
|
+
async getCredentials() {
|
|
103
|
+
if (!this.identity) await this.init();
|
|
104
|
+
|
|
105
|
+
const response = await fetch(`${this.serverUrl}/agents/${this.identity.agentId}/credentials`);
|
|
106
|
+
return response.json();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Get profile
|
|
111
|
+
*/
|
|
112
|
+
async getProfile() {
|
|
113
|
+
if (!this.identity) await this.init();
|
|
114
|
+
|
|
115
|
+
const response = await fetch(`${this.serverUrl}/agents/${this.identity.agentId}`);
|
|
116
|
+
return response.json();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export default AgentIDClient;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentID - Core Library
|
|
3
|
+
* Decentralized identity for AI agents
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { generateKeyPairSync, sign, verify, createHash } from 'crypto';
|
|
7
|
+
|
|
8
|
+
const AGENT_ID_PREFIX = 'aa_';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generate a new agent keypair
|
|
12
|
+
* @returns {{ publicKey: string, privateKey: string, agentId: string }}
|
|
13
|
+
*/
|
|
14
|
+
export function generateIdentity() {
|
|
15
|
+
const { publicKey, privateKey } = generateKeyPairSync('ed25519', {
|
|
16
|
+
publicKeyEncoding: { type: 'spki', format: 'der' },
|
|
17
|
+
privateKeyEncoding: { type: 'pkcs8', format: 'der' }
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const pubKeyBase64 = publicKey.toString('base64');
|
|
21
|
+
const agentId = deriveAgentId(pubKeyBase64);
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
publicKey: pubKeyBase64,
|
|
25
|
+
privateKey: privateKey.toString('base64'),
|
|
26
|
+
agentId
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Derive agent ID from public key
|
|
32
|
+
* @param {string} publicKeyBase64
|
|
33
|
+
* @returns {string}
|
|
34
|
+
*/
|
|
35
|
+
export function deriveAgentId(publicKeyBase64) {
|
|
36
|
+
const hash = createHash('sha256')
|
|
37
|
+
.update(publicKeyBase64)
|
|
38
|
+
.digest('base64url')
|
|
39
|
+
.slice(0, 22); // 22 chars = 132 bits of entropy
|
|
40
|
+
return AGENT_ID_PREFIX + hash;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Sign a message with private key
|
|
45
|
+
* @param {string} message
|
|
46
|
+
* @param {string} privateKeyBase64
|
|
47
|
+
* @returns {string}
|
|
48
|
+
*/
|
|
49
|
+
export function signMessage(message, privateKeyBase64) {
|
|
50
|
+
const privateKeyDer = Buffer.from(privateKeyBase64, 'base64');
|
|
51
|
+
const privateKey = {
|
|
52
|
+
key: privateKeyDer,
|
|
53
|
+
format: 'der',
|
|
54
|
+
type: 'pkcs8'
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const signature = sign(null, Buffer.from(message), privateKey);
|
|
58
|
+
return signature.toString('base64');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Verify a signature
|
|
63
|
+
* @param {string} message
|
|
64
|
+
* @param {string} signature
|
|
65
|
+
* @param {string} publicKeyBase64
|
|
66
|
+
* @returns {boolean}
|
|
67
|
+
*/
|
|
68
|
+
export function verifySignature(message, signature, publicKeyBase64) {
|
|
69
|
+
try {
|
|
70
|
+
const publicKeyDer = Buffer.from(publicKeyBase64, 'base64');
|
|
71
|
+
const publicKey = {
|
|
72
|
+
key: publicKeyDer,
|
|
73
|
+
format: 'der',
|
|
74
|
+
type: 'spki'
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
return verify(null, Buffer.from(message), publicKey, Buffer.from(signature, 'base64'));
|
|
78
|
+
} catch (e) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Create enrollment request
|
|
85
|
+
* @param {string} privateKeyBase64
|
|
86
|
+
* @param {{ name?: string, framework?: string }} metadata
|
|
87
|
+
* @returns {{ pubkey: string, agentId: string, metadata: object, timestamp: string, signature: string }}
|
|
88
|
+
*/
|
|
89
|
+
export function createEnrollmentRequest(publicKeyBase64, privateKeyBase64, metadata = {}) {
|
|
90
|
+
const timestamp = new Date().toISOString();
|
|
91
|
+
const agentId = deriveAgentId(publicKeyBase64);
|
|
92
|
+
|
|
93
|
+
const payload = JSON.stringify({
|
|
94
|
+
pubkey: publicKeyBase64,
|
|
95
|
+
agentId,
|
|
96
|
+
metadata,
|
|
97
|
+
timestamp
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const signature = signMessage(payload, privateKeyBase64);
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
pubkey: publicKeyBase64,
|
|
104
|
+
agentId,
|
|
105
|
+
metadata,
|
|
106
|
+
timestamp,
|
|
107
|
+
signature
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Create a signed challenge response
|
|
113
|
+
* @param {string} challenge
|
|
114
|
+
* @param {string} agentId
|
|
115
|
+
* @param {string} privateKeyBase64
|
|
116
|
+
* @returns {{ agentId: string, challenge: string, signature: string }}
|
|
117
|
+
*/
|
|
118
|
+
export function signChallenge(challenge, agentId, privateKeyBase64) {
|
|
119
|
+
const message = `${agentId}:${challenge}`;
|
|
120
|
+
const signature = signMessage(message, privateKeyBase64);
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
agentId,
|
|
124
|
+
challenge,
|
|
125
|
+
signature
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export default {
|
|
130
|
+
generateIdentity,
|
|
131
|
+
deriveAgentId,
|
|
132
|
+
signMessage,
|
|
133
|
+
verifySignature,
|
|
134
|
+
createEnrollmentRequest,
|
|
135
|
+
signChallenge
|
|
136
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agentid-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Decentralized identity system for AI agents - AgentAcademy",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"agentid": "./cli/agentid.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node server/lite.js",
|
|
12
|
+
"start:full": "node server/index.js",
|
|
13
|
+
"dev": "node --watch server/lite.js",
|
|
14
|
+
"test": "node test/run.js"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"express": "^4.18.2",
|
|
18
|
+
"cors": "^2.8.5"
|
|
19
|
+
},
|
|
20
|
+
"optionalDependencies": {
|
|
21
|
+
"better-sqlite3": "^9.4.3"
|
|
22
|
+
},
|
|
23
|
+
"author": "Wayne Xu",
|
|
24
|
+
"license": "MIT"
|
|
25
|
+
}
|