create-agent 0.0.19 → 0.0.21

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/.nojekyll ADDED
File without changes
package/README.md CHANGED
@@ -46,6 +46,7 @@ The tool outputs a spec-compliant DID document to `stdout`:
46
46
  ```json
47
47
  {
48
48
  "@context": [
49
+ "https://www.w3.org/ns/did/v1",
49
50
  "https://www.w3.org/ns/cid/v1",
50
51
  "https://w3id.org/nostr/context"
51
52
  ],
package/SKILL.md CHANGED
@@ -52,7 +52,7 @@ layers.
52
52
 
53
53
  ```json
54
54
  {
55
- "@context": ["https://www.w3.org/ns/cid/v1", "https://w3id.org/nostr/context"],
55
+ "@context": ["https://www.w3.org/ns/did/v1", "https://www.w3.org/ns/cid/v1", "https://w3id.org/nostr/context"],
56
56
  "id": "did:nostr:dd82687ee5a352c6d6de337bce53f150ca1567f3861475c74e7da62695931d23",
57
57
  "type": "DIDNostr",
58
58
  "seeAlso": "https://init-agent.com/SKILL.md",
@@ -82,11 +82,12 @@ layers.
82
82
 
83
83
  ## Current spec facts (verify; do not recall from memory)
84
84
 
85
- did:nostr is a young, evolving method. As of **2026-06-29** the canonical
85
+ did:nostr is a young, evolving method. As of **2026-07-26** (spec 0.1.1) the canonical
86
86
  shape is:
87
87
 
88
- - `@context`: `["https://www.w3.org/ns/cid/v1", "https://w3id.org/nostr/context"]`
89
- — note **CID v1**, not the older DID v1 context.
88
+ - `@context`: `["https://www.w3.org/ns/did/v1", "https://www.w3.org/ns/cid/v1", "https://w3id.org/nostr/context"]`
89
+ — note it leads with **DID v1** (required by DID Core), followed by **CID v1**, which
90
+ defines the `Multikey` terms.
90
91
  - `type`: `DIDNostr`; verification method `type`: `Multikey`.
91
92
  - `publicKeyMultibase`: `fe70102` + lowercase-hex pubkey.
92
93
  - `authentication` and `assertionMethod`: `["#key1"]`.
@@ -4,11 +4,13 @@ import { generateAgent } from '../index.js'
4
4
  import { execSync } from 'child_process'
5
5
  import fs from 'fs'
6
6
 
7
- // Check if in a git repo
8
- function isGitRepo() {
7
+ // Check if this directory is the top of its own git repo. A subfolder of
8
+ // another repo does not count: its git config is the parent's, so a key saved
9
+ // there would be shared with (and overwritten by) every other subfolder.
10
+ function isRepoRoot() {
9
11
  try {
10
- execSync('git rev-parse --git-dir', { stdio: 'ignore' })
11
- return true
12
+ const top = execSync('git rev-parse --show-toplevel', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim()
13
+ return fs.realpathSync(top) === fs.realpathSync(process.cwd())
12
14
  } catch {
13
15
  return false
14
16
  }
@@ -27,7 +29,7 @@ function hasIdentity() {
27
29
  }
28
30
 
29
31
  // Main
30
- if (!isGitRepo()) {
32
+ if (!isRepoRoot()) {
31
33
  console.error('\x1b[36mInitializing git repository...\x1b[0m')
32
34
  execSync('git init', { stdio: 'inherit' })
33
35
  }
package/index.js CHANGED
@@ -25,6 +25,7 @@ export function generateAgent() {
25
25
  // Create DID document per https://nostrcg.github.io/did-nostr/
26
26
  const did = {
27
27
  "@context": [
28
+ "https://www.w3.org/ns/did/v1",
28
29
  "https://www.w3.org/ns/cid/v1",
29
30
  "https://w3id.org/nostr/context"
30
31
  ],
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-agent",
3
3
  "type": "module",
4
- "version": "0.0.19",
4
+ "version": "0.0.21",
5
5
  "description": "create an agent",
6
6
  "scripts": {
7
7
  "test": "node --test"
@@ -27,4 +27,4 @@
27
27
  "dependencies": {
28
28
  "nostr-tools": "^2.10.4"
29
29
  }
30
- }
30
+ }
@@ -0,0 +1,67 @@
1
+ import { test, describe } from 'node:test'
2
+ import assert from 'node:assert'
3
+ import { execSync, execFileSync } from 'child_process'
4
+ import fs from 'fs'
5
+ import os from 'os'
6
+ import path from 'path'
7
+
8
+ const bin = path.resolve('bin/create-agent.js')
9
+ const git = (cwd, args) => execSync(`git ${args}`, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim()
10
+ const run = (cwd) => execFileSync('node', [bin], { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] })
11
+ const tmp = () => fs.mkdtempSync(path.join(os.tmpdir(), 'create-agent-'))
12
+
13
+ describe('create-agent CLI', () => {
14
+ test('in a subfolder of a repo, makes the subfolder its own repo', () => {
15
+ const parent = tmp()
16
+ git(parent, 'init -q')
17
+ const sub = path.join(parent, 'project')
18
+ fs.mkdirSync(sub)
19
+
20
+ run(sub)
21
+
22
+ assert.ok(fs.existsSync(path.join(sub, '.git')), 'subfolder should get its own .git')
23
+ assert.ok(fs.existsSync(path.join(sub, 'agent.did.json')))
24
+ assert.match(git(sub, 'config --local nostr.privkey'), /^[0-9a-f]{64}$/)
25
+ assert.throws(() => git(parent, 'config --local nostr.privkey'), 'parent config must not hold the key')
26
+ })
27
+
28
+ test('two subfolders of one repo keep separate keys', () => {
29
+ const parent = tmp()
30
+ git(parent, 'init -q')
31
+ const a = path.join(parent, 'a')
32
+ const b = path.join(parent, 'b')
33
+ fs.mkdirSync(a)
34
+ fs.mkdirSync(b)
35
+
36
+ run(a)
37
+ const keyA = git(a, 'config --local nostr.privkey')
38
+ run(b)
39
+
40
+ assert.strictEqual(git(a, 'config --local nostr.privkey'), keyA, "b must not overwrite a's key")
41
+ assert.notStrictEqual(git(b, 'config --local nostr.privkey'), keyA)
42
+ })
43
+
44
+ test('at the top of an existing repo, uses that repo', () => {
45
+ const dir = tmp()
46
+ git(dir, 'init -q')
47
+ const before = fs.readdirSync(path.join(dir, '.git')).length
48
+
49
+ run(dir)
50
+
51
+ assert.match(git(dir, 'config --local nostr.privkey'), /^[0-9a-f]{64}$/)
52
+ assert.ok(fs.readdirSync(path.join(dir, '.git')).length >= before)
53
+ })
54
+
55
+ test('outside any repo, initialises one', () => {
56
+ const dir = tmp()
57
+ run(dir)
58
+ assert.ok(fs.existsSync(path.join(dir, '.git')))
59
+ assert.match(git(dir, 'config --local nostr.privkey'), /^[0-9a-f]{64}$/)
60
+ })
61
+
62
+ test('refuses to run twice in the same folder', () => {
63
+ const dir = tmp()
64
+ run(dir)
65
+ assert.throws(() => run(dir), /already exists/)
66
+ })
67
+ })
@@ -43,6 +43,7 @@ describe('generateAgent', () => {
43
43
  const { did, pubkey } = generateAgent()
44
44
 
45
45
  assert.deepStrictEqual(did['@context'], [
46
+ 'https://www.w3.org/ns/did/v1',
46
47
  'https://www.w3.org/ns/cid/v1',
47
48
  'https://w3id.org/nostr/context'
48
49
  ])
@@ -1,34 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "WebFetch(domain:did-nostr.com)",
5
- "WebFetch(domain:nostrcg.github.io)",
6
- "Bash(npm test *)",
7
- "Bash(gh repo *)",
8
- "Bash(gh issue *)",
9
- "Bash(git push *)",
10
- "Bash(gh pr create --base gh-pages --title 'Update DID document to latest did:nostr spec \\(DID → CID context\\)' --body ' *)",
11
- "Bash(gh pr *)",
12
- "Bash(gh api *)",
13
- "Bash(git checkout *)",
14
- "Bash(git pull *)",
15
- "Bash(npm install *)",
16
- "WebFetch(domain:github.com)",
17
- "Bash(curl -sL \"https://www.w3.org/ns/cid/v1\")",
18
- "Bash(curl -sL \"https://w3id.org/nostr/context\")",
19
- "Bash(python3 -c \"import json;d=json.load\\(open\\('vocab.jsonld'\\)\\);print\\(json.dumps\\(d['@context']\\)[:600]\\)\")",
20
- "Bash(python3 -c \"import json;d=json.load\\(open\\('vocab.json'\\)\\);print\\(json.dumps\\(d['@context']\\)[:600]\\)\")",
21
- "Bash(node -e \"import\\('./index.js'\\).then\\(m=>{const a=m.generateAgent\\(\\);console.log\\('seeAlso:',a.did.seeAlso\\)}\\)\")",
22
- "WebFetch(domain:blocktrails.com)",
23
- "WebFetch(domain:aam.wtf)",
24
- "WebFetch(domain:www.npmjs.com)",
25
- "Bash(npm view *)",
26
- "Bash(python3 -c \"import json,sys; d=json.load\\(sys.stdin\\); print\\('name:',d.get\\('name'\\)\\); print\\('version:',d.get\\('version'\\)\\); print\\('description:',d.get\\('description'\\)\\); print\\('keywords:',d.get\\('keywords'\\)\\); print\\('homepage:',d.get\\('homepage'\\)\\); print\\('author:',d.get\\('author'\\)\\); print\\('bin:',d.get\\('bin'\\)\\); print\\('repository:',d.get\\('repository'\\)\\)\")",
27
- "WebFetch(domain:www.blocktrails.com)",
28
- "WebFetch(domain:blocktrails.org)",
29
- "Bash(git add *)",
30
- "Bash(git commit -q -m ' *)",
31
- "Bash(python3 -c \"import json;print\\(json.load\\(open\\('package.json'\\)\\)['version']\\)\")"
32
- ]
33
- }
34
- }