@newtype-ai/nit 0.4.9 → 0.4.11
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 +6 -1
- package/dist/{chunk-Q5GX7ZXR.js → chunk-445BLP4Q.js} +377 -314
- package/dist/chunk-M6SR6QMR.js +291 -0
- package/dist/cli.js +121 -2
- package/dist/index.d.ts +91 -1
- package/dist/index.js +22 -10
- package/dist/remote-WZ625MBZ.js +15 -0
- package/package.json +1 -1
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
// nit — version control for agent cards
|
|
2
|
+
|
|
3
|
+
// src/remote.ts
|
|
4
|
+
import { createHash as createHash2 } from "crypto";
|
|
5
|
+
|
|
6
|
+
// src/identity.ts
|
|
7
|
+
import {
|
|
8
|
+
createHash,
|
|
9
|
+
generateKeyPairSync,
|
|
10
|
+
createPrivateKey,
|
|
11
|
+
createPublicKey,
|
|
12
|
+
sign,
|
|
13
|
+
verify
|
|
14
|
+
} from "crypto";
|
|
15
|
+
import { promises as fs } from "fs";
|
|
16
|
+
import { join } from "path";
|
|
17
|
+
function base64urlToBase64(b64url) {
|
|
18
|
+
let s = b64url.replace(/-/g, "+").replace(/_/g, "/");
|
|
19
|
+
while (s.length % 4 !== 0) s += "=";
|
|
20
|
+
return s;
|
|
21
|
+
}
|
|
22
|
+
function base64ToBase64url(b64) {
|
|
23
|
+
return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
24
|
+
}
|
|
25
|
+
async function generateKeypair(nitDir) {
|
|
26
|
+
const identityDir = join(nitDir, "identity");
|
|
27
|
+
await fs.mkdir(identityDir, { recursive: true });
|
|
28
|
+
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
|
29
|
+
const pubJwk = publicKey.export({ format: "jwk" });
|
|
30
|
+
const privJwk = privateKey.export({ format: "jwk" });
|
|
31
|
+
const pubBase64 = base64urlToBase64(pubJwk.x);
|
|
32
|
+
const privBase64 = base64urlToBase64(privJwk.d);
|
|
33
|
+
const pubPath = join(identityDir, "agent.pub");
|
|
34
|
+
const keyPath = join(identityDir, "agent.key");
|
|
35
|
+
await fs.writeFile(pubPath, pubBase64 + "\n", "utf-8");
|
|
36
|
+
await fs.writeFile(keyPath, privBase64 + "\n", {
|
|
37
|
+
mode: 384,
|
|
38
|
+
encoding: "utf-8"
|
|
39
|
+
});
|
|
40
|
+
return { publicKey: pubBase64, privateKey: privBase64 };
|
|
41
|
+
}
|
|
42
|
+
async function loadPublicKey(nitDir) {
|
|
43
|
+
const pubPath = join(nitDir, "identity", "agent.pub");
|
|
44
|
+
try {
|
|
45
|
+
return (await fs.readFile(pubPath, "utf-8")).trim();
|
|
46
|
+
} catch {
|
|
47
|
+
throw new Error(
|
|
48
|
+
"No identity found. Run `nit init` to generate a keypair."
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function loadPrivateKey(nitDir) {
|
|
53
|
+
const pubBase64 = await loadPublicKey(nitDir);
|
|
54
|
+
const keyPath = join(nitDir, "identity", "agent.key");
|
|
55
|
+
let privBase64;
|
|
56
|
+
try {
|
|
57
|
+
privBase64 = (await fs.readFile(keyPath, "utf-8")).trim();
|
|
58
|
+
} catch {
|
|
59
|
+
throw new Error(
|
|
60
|
+
"Private key not found at .nit/identity/agent.key. Regenerate with `nit init`."
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
const xB64url = base64ToBase64url(pubBase64);
|
|
64
|
+
const dB64url = base64ToBase64url(privBase64);
|
|
65
|
+
return createPrivateKey({
|
|
66
|
+
key: { kty: "OKP", crv: "Ed25519", x: xB64url, d: dB64url },
|
|
67
|
+
format: "jwk"
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
async function loadRawKeyPair(nitDir) {
|
|
71
|
+
const pubBase64 = await loadPublicKey(nitDir);
|
|
72
|
+
const keyPath = join(nitDir, "identity", "agent.key");
|
|
73
|
+
let privBase64;
|
|
74
|
+
try {
|
|
75
|
+
privBase64 = (await fs.readFile(keyPath, "utf-8")).trim();
|
|
76
|
+
} catch {
|
|
77
|
+
throw new Error(
|
|
78
|
+
"Private key not found at .nit/identity/agent.key. Regenerate with `nit init`."
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
const seed = Buffer.from(privBase64, "base64");
|
|
82
|
+
const pubkey = Buffer.from(pubBase64, "base64");
|
|
83
|
+
const keypair = new Uint8Array(64);
|
|
84
|
+
keypair.set(seed, 0);
|
|
85
|
+
keypair.set(pubkey, 32);
|
|
86
|
+
return keypair;
|
|
87
|
+
}
|
|
88
|
+
function formatPublicKeyField(pubBase64) {
|
|
89
|
+
return `ed25519:${pubBase64}`;
|
|
90
|
+
}
|
|
91
|
+
function parsePublicKeyField(field) {
|
|
92
|
+
const prefix = "ed25519:";
|
|
93
|
+
if (!field.startsWith(prefix)) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
`Invalid publicKey format: expected "ed25519:<base64>", got "${field}"`
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
return field.slice(prefix.length);
|
|
99
|
+
}
|
|
100
|
+
async function signChallenge(nitDir, challenge) {
|
|
101
|
+
const privateKey = await loadPrivateKey(nitDir);
|
|
102
|
+
const sig = sign(null, Buffer.from(challenge, "utf-8"), privateKey);
|
|
103
|
+
return sig.toString("base64");
|
|
104
|
+
}
|
|
105
|
+
async function signMessage(nitDir, message) {
|
|
106
|
+
const privateKey = await loadPrivateKey(nitDir);
|
|
107
|
+
const sig = sign(null, Buffer.from(message, "utf-8"), privateKey);
|
|
108
|
+
return sig.toString("base64");
|
|
109
|
+
}
|
|
110
|
+
var NIT_NAMESPACE = "801ba518-f326-47e5-97c9-d1efd1865a19";
|
|
111
|
+
function deriveAgentId(publicKeyField) {
|
|
112
|
+
return uuidv5(publicKeyField, NIT_NAMESPACE);
|
|
113
|
+
}
|
|
114
|
+
async function loadAgentId(nitDir) {
|
|
115
|
+
const idPath = join(nitDir, "identity", "agent-id");
|
|
116
|
+
try {
|
|
117
|
+
return (await fs.readFile(idPath, "utf-8")).trim();
|
|
118
|
+
} catch {
|
|
119
|
+
throw new Error(
|
|
120
|
+
"No agent ID found. Run `nit init` to generate identity."
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async function saveAgentId(nitDir, agentId) {
|
|
125
|
+
const idPath = join(nitDir, "identity", "agent-id");
|
|
126
|
+
await fs.writeFile(idPath, agentId + "\n", "utf-8");
|
|
127
|
+
}
|
|
128
|
+
function parseUuid(uuid) {
|
|
129
|
+
const hex = uuid.replace(/-/g, "");
|
|
130
|
+
return Buffer.from(hex, "hex");
|
|
131
|
+
}
|
|
132
|
+
function formatUuid(bytes) {
|
|
133
|
+
const hex = bytes.toString("hex");
|
|
134
|
+
return [
|
|
135
|
+
hex.slice(0, 8),
|
|
136
|
+
hex.slice(8, 12),
|
|
137
|
+
hex.slice(12, 16),
|
|
138
|
+
hex.slice(16, 20),
|
|
139
|
+
hex.slice(20, 32)
|
|
140
|
+
].join("-");
|
|
141
|
+
}
|
|
142
|
+
function uuidv5(name, namespace) {
|
|
143
|
+
const namespaceBytes = parseUuid(namespace);
|
|
144
|
+
const nameBytes = Buffer.from(name, "utf-8");
|
|
145
|
+
const data = Buffer.concat([namespaceBytes, nameBytes]);
|
|
146
|
+
const hash = createHash("sha1").update(data).digest();
|
|
147
|
+
const uuid = Buffer.from(hash.subarray(0, 16));
|
|
148
|
+
uuid[6] = uuid[6] & 15 | 80;
|
|
149
|
+
uuid[8] = uuid[8] & 63 | 128;
|
|
150
|
+
return formatUuid(uuid);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/remote.ts
|
|
154
|
+
function sha256Hex(data) {
|
|
155
|
+
return createHash2("sha256").update(data, "utf-8").digest("hex");
|
|
156
|
+
}
|
|
157
|
+
async function buildAuthHeaders(nitDir, method, path, body) {
|
|
158
|
+
const agentId = await loadAgentId(nitDir);
|
|
159
|
+
const timestamp = Math.floor(Date.now() / 1e3).toString();
|
|
160
|
+
let message = `${method}
|
|
161
|
+
${path}
|
|
162
|
+
${agentId}
|
|
163
|
+
${timestamp}`;
|
|
164
|
+
if (body !== void 0) {
|
|
165
|
+
message += `
|
|
166
|
+
${sha256Hex(body)}`;
|
|
167
|
+
}
|
|
168
|
+
const signature = await signMessage(nitDir, message);
|
|
169
|
+
return {
|
|
170
|
+
"X-Nit-Agent-Id": agentId,
|
|
171
|
+
"X-Nit-Timestamp": timestamp,
|
|
172
|
+
"X-Nit-Signature": signature
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
async function pushBranch(nitDir, apiBase, branch, cardJson, commitHash) {
|
|
176
|
+
const path = `/agent-card/branches/${encodeURIComponent(branch)}`;
|
|
177
|
+
const body = JSON.stringify({ card_json: cardJson, commit_hash: commitHash });
|
|
178
|
+
try {
|
|
179
|
+
const authHeaders = await buildAuthHeaders(nitDir, "PUT", path, body);
|
|
180
|
+
const res = await fetch(`${apiBase}${path}`, {
|
|
181
|
+
method: "PUT",
|
|
182
|
+
headers: {
|
|
183
|
+
"Content-Type": "application/json",
|
|
184
|
+
...authHeaders
|
|
185
|
+
},
|
|
186
|
+
body
|
|
187
|
+
});
|
|
188
|
+
if (!res.ok) {
|
|
189
|
+
const text = await res.text();
|
|
190
|
+
return {
|
|
191
|
+
branch,
|
|
192
|
+
commitHash,
|
|
193
|
+
remoteUrl: apiBase,
|
|
194
|
+
success: false,
|
|
195
|
+
error: `HTTP ${res.status}: ${text}`
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
return { branch, commitHash, remoteUrl: apiBase, success: true };
|
|
199
|
+
} catch (err) {
|
|
200
|
+
return {
|
|
201
|
+
branch,
|
|
202
|
+
commitHash,
|
|
203
|
+
remoteUrl: apiBase,
|
|
204
|
+
success: false,
|
|
205
|
+
error: err instanceof Error ? err.message : String(err)
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async function pushAll(nitDir, apiBase, branches) {
|
|
210
|
+
const results = [];
|
|
211
|
+
for (const b of branches) {
|
|
212
|
+
const result = await pushBranch(nitDir, apiBase, b.name, b.cardJson, b.commitHash);
|
|
213
|
+
results.push(result);
|
|
214
|
+
}
|
|
215
|
+
return results;
|
|
216
|
+
}
|
|
217
|
+
async function listRemoteBranches(nitDir, apiBase) {
|
|
218
|
+
const path = "/agent-card/branches";
|
|
219
|
+
const authHeaders = await buildAuthHeaders(nitDir, "GET", path);
|
|
220
|
+
const res = await fetch(`${apiBase}${path}`, {
|
|
221
|
+
headers: authHeaders
|
|
222
|
+
});
|
|
223
|
+
if (!res.ok) {
|
|
224
|
+
throw new Error(`Failed to list remote branches: HTTP ${res.status}`);
|
|
225
|
+
}
|
|
226
|
+
const data = await res.json();
|
|
227
|
+
return data.branches.map((b) => b.name);
|
|
228
|
+
}
|
|
229
|
+
async function deleteRemoteBranch(nitDir, apiBase, branch) {
|
|
230
|
+
const path = `/agent-card/branches/${encodeURIComponent(branch)}`;
|
|
231
|
+
const authHeaders = await buildAuthHeaders(nitDir, "DELETE", path);
|
|
232
|
+
const res = await fetch(`${apiBase}${path}`, {
|
|
233
|
+
method: "DELETE",
|
|
234
|
+
headers: authHeaders
|
|
235
|
+
});
|
|
236
|
+
return res.ok;
|
|
237
|
+
}
|
|
238
|
+
async function fetchBranchCard(cardUrl, branch, nitDir) {
|
|
239
|
+
const baseUrl = cardUrl.replace(/\/$/, "");
|
|
240
|
+
let url = `${baseUrl}/.well-known/agent-card.json`;
|
|
241
|
+
if (branch !== "main") {
|
|
242
|
+
url += `?branch=${encodeURIComponent(branch)}`;
|
|
243
|
+
}
|
|
244
|
+
const res = await fetch(url);
|
|
245
|
+
if (res.ok) {
|
|
246
|
+
return await res.json();
|
|
247
|
+
}
|
|
248
|
+
if (res.status === 401 && branch !== "main") {
|
|
249
|
+
if (!nitDir) {
|
|
250
|
+
throw new Error(
|
|
251
|
+
`Branch "${branch}" requires authentication. Provide nitDir for signing.`
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
const challengeData = await res.json();
|
|
255
|
+
const signature = await signChallenge(nitDir, challengeData.challenge);
|
|
256
|
+
const authRes = await fetch(url, {
|
|
257
|
+
headers: {
|
|
258
|
+
"X-Nit-Challenge": challengeData.challenge,
|
|
259
|
+
"X-Nit-Signature": signature
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
if (!authRes.ok) {
|
|
263
|
+
const body = await authRes.text();
|
|
264
|
+
throw new Error(
|
|
265
|
+
`Failed to fetch branch "${branch}" after challenge: HTTP ${authRes.status} ${body}`
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
return await authRes.json();
|
|
269
|
+
}
|
|
270
|
+
throw new Error(`Failed to fetch card: HTTP ${res.status}`);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export {
|
|
274
|
+
generateKeypair,
|
|
275
|
+
loadPublicKey,
|
|
276
|
+
loadPrivateKey,
|
|
277
|
+
loadRawKeyPair,
|
|
278
|
+
formatPublicKeyField,
|
|
279
|
+
parsePublicKeyField,
|
|
280
|
+
signChallenge,
|
|
281
|
+
signMessage,
|
|
282
|
+
NIT_NAMESPACE,
|
|
283
|
+
deriveAgentId,
|
|
284
|
+
loadAgentId,
|
|
285
|
+
saveAgentId,
|
|
286
|
+
pushBranch,
|
|
287
|
+
pushAll,
|
|
288
|
+
listRemoteBranches,
|
|
289
|
+
deleteRemoteBranch,
|
|
290
|
+
fetchBranchCard
|
|
291
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// nit — version control for agent cards
|
|
3
3
|
import {
|
|
4
|
+
authSet,
|
|
5
|
+
authShow,
|
|
4
6
|
branch,
|
|
5
7
|
broadcast,
|
|
6
8
|
checkout,
|
|
@@ -10,16 +12,20 @@ import {
|
|
|
10
12
|
init,
|
|
11
13
|
log,
|
|
12
14
|
loginPayload,
|
|
15
|
+
pull,
|
|
13
16
|
push,
|
|
14
17
|
remote,
|
|
15
18
|
remoteAdd,
|
|
16
19
|
remoteSetUrl,
|
|
20
|
+
reset,
|
|
17
21
|
rpcInfo,
|
|
18
22
|
rpcSetUrl,
|
|
23
|
+
show,
|
|
19
24
|
sign,
|
|
20
25
|
signTx,
|
|
21
26
|
status
|
|
22
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-445BLP4Q.js";
|
|
28
|
+
import "./chunk-M6SR6QMR.js";
|
|
23
29
|
|
|
24
30
|
// src/update-check.ts
|
|
25
31
|
import { execSync } from "child_process";
|
|
@@ -32,7 +38,7 @@ var FETCH_TIMEOUT_MS = 3e3;
|
|
|
32
38
|
var REGISTRY_URL = "https://registry.npmjs.org/@newtype-ai/nit/latest";
|
|
33
39
|
function getCurrentVersion() {
|
|
34
40
|
try {
|
|
35
|
-
return "0.4.
|
|
41
|
+
return "0.4.11";
|
|
36
42
|
} catch {
|
|
37
43
|
return "0.0.0";
|
|
38
44
|
}
|
|
@@ -162,6 +168,18 @@ async function main() {
|
|
|
162
168
|
case "rpc":
|
|
163
169
|
await cmdRpc(args);
|
|
164
170
|
break;
|
|
171
|
+
case "auth":
|
|
172
|
+
await cmdAuth(args);
|
|
173
|
+
break;
|
|
174
|
+
case "reset":
|
|
175
|
+
await cmdReset(args);
|
|
176
|
+
break;
|
|
177
|
+
case "show":
|
|
178
|
+
await cmdShow(args);
|
|
179
|
+
break;
|
|
180
|
+
case "pull":
|
|
181
|
+
await cmdPull(args);
|
|
182
|
+
break;
|
|
165
183
|
case "help":
|
|
166
184
|
case "--help":
|
|
167
185
|
case "-h":
|
|
@@ -359,6 +377,7 @@ async function cmdSign(args) {
|
|
|
359
377
|
if (payload.createdSkill) {
|
|
360
378
|
console.error(`Created skill template '${payload.createdSkill}'`);
|
|
361
379
|
}
|
|
380
|
+
console.error(`Auth: use browser profile="user" to reuse existing sessions. If login required, click OAuth buttons. Do NOT enter credentials.`);
|
|
362
381
|
const { switchedBranch: _s, createdSkill: _c, ...output } = payload;
|
|
363
382
|
console.log(JSON.stringify(output, null, 2));
|
|
364
383
|
return;
|
|
@@ -439,6 +458,100 @@ async function cmdRpc(args) {
|
|
|
439
458
|
console.log(` ${bold(chain)}: ${config.url}`);
|
|
440
459
|
}
|
|
441
460
|
}
|
|
461
|
+
async function cmdReset(args) {
|
|
462
|
+
const target = args[0];
|
|
463
|
+
const result = await reset(target);
|
|
464
|
+
console.log(`Reset to ${dim(result.hash.slice(0, 8))}`);
|
|
465
|
+
}
|
|
466
|
+
async function cmdShow(args) {
|
|
467
|
+
const target = args[0];
|
|
468
|
+
const s = await show(target);
|
|
469
|
+
const date = new Date(s.timestamp * 1e3).toISOString().slice(0, 19);
|
|
470
|
+
console.log(`${bold("commit")} ${yellow(s.hash.slice(0, 8))}`);
|
|
471
|
+
console.log(`Author: ${s.author}`);
|
|
472
|
+
console.log(`Date: ${date}`);
|
|
473
|
+
if (s.parent) {
|
|
474
|
+
console.log(`Parent: ${dim(s.parent.slice(0, 8))}`);
|
|
475
|
+
}
|
|
476
|
+
console.log();
|
|
477
|
+
console.log(` ${s.message}`);
|
|
478
|
+
console.log();
|
|
479
|
+
console.log(JSON.stringify(s.cardJson, null, 2));
|
|
480
|
+
}
|
|
481
|
+
async function cmdPull(args) {
|
|
482
|
+
const all = args.includes("--all");
|
|
483
|
+
const results = await pull({ all });
|
|
484
|
+
for (const r of results) {
|
|
485
|
+
if (r.updated) {
|
|
486
|
+
console.log(`${green("\u2713")} ${r.branch} \u2190 ${dim(r.commitHash.slice(0, 8))}`);
|
|
487
|
+
} else {
|
|
488
|
+
console.log(`${dim("\u2014")} ${r.branch} ${dim("(up to date)")}`);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
async function cmdAuth(args) {
|
|
493
|
+
const subcommand = args[0];
|
|
494
|
+
if (subcommand === "set") {
|
|
495
|
+
const domain = args[1];
|
|
496
|
+
if (!domain) {
|
|
497
|
+
console.error("Usage: nit auth set <domain> --provider <google|github|x> --account <email>");
|
|
498
|
+
process.exit(1);
|
|
499
|
+
}
|
|
500
|
+
const providerIndex = args.indexOf("--provider");
|
|
501
|
+
if (providerIndex === -1 || !args[providerIndex + 1]) {
|
|
502
|
+
console.error("Missing --provider. Usage: nit auth set <domain> --provider <google|github|x> --account <email>");
|
|
503
|
+
process.exit(1);
|
|
504
|
+
}
|
|
505
|
+
const provider = args[providerIndex + 1];
|
|
506
|
+
const validProviders = ["google", "github", "x"];
|
|
507
|
+
if (!validProviders.includes(provider)) {
|
|
508
|
+
console.error(`Unknown provider: ${provider}. Use: google, github, x`);
|
|
509
|
+
process.exit(1);
|
|
510
|
+
}
|
|
511
|
+
const accountIndex = args.indexOf("--account");
|
|
512
|
+
if (accountIndex === -1 || !args[accountIndex + 1]) {
|
|
513
|
+
console.error("Missing --account. Usage: nit auth set <domain> --provider <google|github|x> --account <email>");
|
|
514
|
+
process.exit(1);
|
|
515
|
+
}
|
|
516
|
+
const account = args[accountIndex + 1];
|
|
517
|
+
const result = await authSet(domain, provider, account);
|
|
518
|
+
if (result.createdBranch) {
|
|
519
|
+
console.log(`Created branch '${green(result.branch)}'`);
|
|
520
|
+
}
|
|
521
|
+
if (result.switchedBranch) {
|
|
522
|
+
console.log(`Switched to branch '${green(result.switchedBranch)}'`);
|
|
523
|
+
}
|
|
524
|
+
console.log(`${green("\u2713")} Auth configured for ${bold(domain)}: ${result.provider} (${result.account})`);
|
|
525
|
+
console.log(dim(` Updated SKILL.md: ${result.skillId}/SKILL.md`));
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
if (subcommand === "show") {
|
|
529
|
+
const domain = args[1];
|
|
530
|
+
const results = await authShow(domain);
|
|
531
|
+
if (results.length === 0) {
|
|
532
|
+
if (domain) {
|
|
533
|
+
console.log(dim(`No auth configured for '${domain}'.`));
|
|
534
|
+
} else {
|
|
535
|
+
console.log(dim("No branches with auth configured."));
|
|
536
|
+
}
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
for (const r of results) {
|
|
540
|
+
if (r.auth) {
|
|
541
|
+
console.log(` ${bold(r.branch)}: ${r.auth.provider} (${r.auth.account})`);
|
|
542
|
+
} else {
|
|
543
|
+
console.log(` ${bold(r.branch)}: ${dim("(no auth)")}`);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
if (subcommand) {
|
|
549
|
+
console.error(`nit auth: unknown subcommand '${subcommand}'`);
|
|
550
|
+
}
|
|
551
|
+
console.error("Usage: nit auth set <domain> --provider <google|github|x> --account <email>");
|
|
552
|
+
console.error(" nit auth show [domain]");
|
|
553
|
+
process.exit(1);
|
|
554
|
+
}
|
|
442
555
|
function printUsage() {
|
|
443
556
|
console.log(`
|
|
444
557
|
${bold("nit")} \u2014 version control for agent cards
|
|
@@ -454,6 +567,9 @@ ${bold("Commands:")}
|
|
|
454
567
|
branch [name] List branches or create a new one
|
|
455
568
|
checkout <branch> Switch branch (overwrites agent-card.json)
|
|
456
569
|
push [--all] Push branch(es) to remote
|
|
570
|
+
pull [--all] Pull branch(es) from remote
|
|
571
|
+
reset [target] Restore agent-card.json from HEAD or target
|
|
572
|
+
show [target] Show commit metadata and card content
|
|
457
573
|
sign "message" Sign a message with your Ed25519 key
|
|
458
574
|
sign --login <dom> Switch to domain branch + generate login payload
|
|
459
575
|
remote Show remote info
|
|
@@ -463,6 +579,9 @@ ${bold("Commands:")}
|
|
|
463
579
|
broadcast --chain <c> <tx> Send signed tx to RPC endpoint
|
|
464
580
|
rpc Show configured RPC endpoints
|
|
465
581
|
rpc set-url <c> <url> Set RPC endpoint for a chain
|
|
582
|
+
auth set <dom> --provider <p> --account <a>
|
|
583
|
+
Configure OAuth auth for a branch
|
|
584
|
+
auth show [dom] Show auth config for branch(es)
|
|
466
585
|
|
|
467
586
|
${bold("Examples:")}
|
|
468
587
|
nit init
|
package/dist/index.d.ts
CHANGED
|
@@ -151,6 +151,13 @@ interface BroadcastResult {
|
|
|
151
151
|
/** RPC endpoint used */
|
|
152
152
|
rpcUrl: string;
|
|
153
153
|
}
|
|
154
|
+
/** OAuth provider for per-branch authentication config. */
|
|
155
|
+
type AuthProvider = 'google' | 'github' | 'x';
|
|
156
|
+
/** Per-branch authentication configuration stored in SKILL.md frontmatter. */
|
|
157
|
+
interface AuthConfig {
|
|
158
|
+
provider: AuthProvider;
|
|
159
|
+
account: string;
|
|
160
|
+
}
|
|
154
161
|
/** Result of generating a login payload for app authentication. */
|
|
155
162
|
interface LoginPayload {
|
|
156
163
|
agent_id: string;
|
|
@@ -420,5 +427,88 @@ declare function rpcSetUrl(chain: string, url: string, options?: {
|
|
|
420
427
|
declare function rpcInfo(options?: {
|
|
421
428
|
projectDir?: string;
|
|
422
429
|
}): Promise<Record<string, NitRpcConfig>>;
|
|
430
|
+
/**
|
|
431
|
+
* Restore agent-card.json from a commit, discarding uncommitted changes.
|
|
432
|
+
*
|
|
433
|
+
* - No target: restore from HEAD (discard all uncommitted changes)
|
|
434
|
+
* - Commit hash or branch name: restore card from that commit
|
|
435
|
+
*
|
|
436
|
+
* Does NOT move the branch pointer — only overwrites the working card.
|
|
437
|
+
*/
|
|
438
|
+
declare function reset(target?: string, options?: {
|
|
439
|
+
projectDir?: string;
|
|
440
|
+
}): Promise<{
|
|
441
|
+
hash: string;
|
|
442
|
+
}>;
|
|
443
|
+
interface ShowResult {
|
|
444
|
+
hash: string;
|
|
445
|
+
card: string;
|
|
446
|
+
parent: string | null;
|
|
447
|
+
author: string;
|
|
448
|
+
timestamp: number;
|
|
449
|
+
message: string;
|
|
450
|
+
cardJson: AgentCard;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Show a commit's metadata and card content.
|
|
454
|
+
*
|
|
455
|
+
* - No target: show HEAD
|
|
456
|
+
* - Commit hash or branch name: show that commit
|
|
457
|
+
*/
|
|
458
|
+
declare function show(target?: string, options?: {
|
|
459
|
+
projectDir?: string;
|
|
460
|
+
}): Promise<ShowResult>;
|
|
461
|
+
interface PullResult {
|
|
462
|
+
branch: string;
|
|
463
|
+
commitHash: string;
|
|
464
|
+
updated: boolean;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Fetch current branch (or all branches) from the remote and update local state.
|
|
468
|
+
*
|
|
469
|
+
* 1. Fetch card JSON from remote
|
|
470
|
+
* 2. Write card to object store
|
|
471
|
+
* 3. Create a commit object
|
|
472
|
+
* 4. Update branch ref + remote-tracking ref
|
|
473
|
+
* 5. Write card to working copy (current branch only)
|
|
474
|
+
*/
|
|
475
|
+
declare function pull(options?: {
|
|
476
|
+
projectDir?: string;
|
|
477
|
+
remoteName?: string;
|
|
478
|
+
all?: boolean;
|
|
479
|
+
}): Promise<PullResult[]>;
|
|
480
|
+
interface AuthSetResult {
|
|
481
|
+
branch: string;
|
|
482
|
+
skillId: string;
|
|
483
|
+
provider: AuthProvider;
|
|
484
|
+
account: string;
|
|
485
|
+
switchedBranch?: string;
|
|
486
|
+
createdBranch?: boolean;
|
|
487
|
+
}
|
|
488
|
+
interface AuthShowResult {
|
|
489
|
+
branch: string;
|
|
490
|
+
auth: AuthConfig | null;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Configure OAuth authentication for a branch.
|
|
494
|
+
*
|
|
495
|
+
* 1. Switches to the target branch (creates if needed)
|
|
496
|
+
* 2. Updates the branch's SKILL.md with auth frontmatter + consent instructions
|
|
497
|
+
* 3. Adds skill pointer to agent-card.json if not present
|
|
498
|
+
*
|
|
499
|
+
* The SKILL.md tells OpenClaw which OAuth provider and account to use when
|
|
500
|
+
* the agent encounters a login page. The agent reuses the human's existing
|
|
501
|
+
* Chrome session (browser-profile = user) and only handles OAuth consent
|
|
502
|
+
* flows — never enters credentials.
|
|
503
|
+
*/
|
|
504
|
+
declare function authSet(domain: string, provider: AuthProvider, account: string, options?: {
|
|
505
|
+
projectDir?: string;
|
|
506
|
+
}): Promise<AuthSetResult>;
|
|
507
|
+
/**
|
|
508
|
+
* Show auth config for a specific branch, or all branches with auth configured.
|
|
509
|
+
*/
|
|
510
|
+
declare function authShow(domain?: string, options?: {
|
|
511
|
+
projectDir?: string;
|
|
512
|
+
}): Promise<AuthShowResult[]>;
|
|
423
513
|
|
|
424
|
-
export { type AgentCard, type AgentCardSkill, type BroadcastResult, type DiffResult, type FieldDiff, type InitResult, type LoginPayload, NIT_NAMESPACE, type NitBranch, type NitCommit, type NitConfig, type NitHead, type NitRemoteConfig, type NitRpcConfig, type PushResult, type RemoteInfo, type SignTxResult, type SkillMetadata, type StatusResult, type WalletAddresses$1 as WalletAddresses, base58Encode, branch, broadcast, checkout, commit, deriveAgentId, diff, diffCards, fetchBranchCard, findNitDir, formatDiff, formatPublicKeyField, getEvmAddress, getSolanaAddress, getWalletAddresses, init, loadAgentId, loadRawKeyPair, loadSecp256k1RawKeyPair, log, loginPayload, parsePublicKeyField, push, remote, remoteAdd, remoteSetUrl, rpcInfo, rpcSetUrl, sign, signChallenge, signEvmHash, signMessage, signSolanaBytes, signTx, status };
|
|
514
|
+
export { type AgentCard, type AgentCardSkill, type AuthConfig, type AuthProvider, type AuthSetResult, type AuthShowResult, type BroadcastResult, type DiffResult, type FieldDiff, type InitResult, type LoginPayload, NIT_NAMESPACE, type NitBranch, type NitCommit, type NitConfig, type NitHead, type NitRemoteConfig, type NitRpcConfig, type PullResult, type PushResult, type RemoteInfo, type ShowResult, type SignTxResult, type SkillMetadata, type StatusResult, type WalletAddresses$1 as WalletAddresses, authSet, authShow, base58Encode, branch, broadcast, checkout, commit, deriveAgentId, diff, diffCards, fetchBranchCard, findNitDir, formatDiff, formatPublicKeyField, getEvmAddress, getSolanaAddress, getWalletAddresses, init, loadAgentId, loadRawKeyPair, loadSecp256k1RawKeyPair, log, loginPayload, parsePublicKeyField, pull, push, remote, remoteAdd, remoteSetUrl, reset, rpcInfo, rpcSetUrl, show, sign, signChallenge, signEvmHash, signMessage, signSolanaBytes, signTx, status };
|
package/dist/index.js
CHANGED
|
@@ -1,44 +1,53 @@
|
|
|
1
1
|
// nit — version control for agent cards
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
authSet,
|
|
4
|
+
authShow,
|
|
4
5
|
base58Encode,
|
|
5
6
|
branch,
|
|
6
7
|
broadcast,
|
|
7
8
|
checkout,
|
|
8
9
|
commit,
|
|
9
|
-
deriveAgentId,
|
|
10
10
|
diff,
|
|
11
11
|
diffCards,
|
|
12
|
-
fetchBranchCard,
|
|
13
12
|
findNitDir,
|
|
14
13
|
formatDiff,
|
|
15
|
-
formatPublicKeyField,
|
|
16
14
|
getEvmAddress,
|
|
17
15
|
getSolanaAddress,
|
|
18
16
|
getWalletAddresses,
|
|
19
17
|
init,
|
|
20
|
-
loadAgentId,
|
|
21
|
-
loadRawKeyPair,
|
|
22
18
|
loadSecp256k1RawKeyPair,
|
|
23
19
|
log,
|
|
24
20
|
loginPayload,
|
|
25
|
-
|
|
21
|
+
pull,
|
|
26
22
|
push,
|
|
27
23
|
remote,
|
|
28
24
|
remoteAdd,
|
|
29
25
|
remoteSetUrl,
|
|
26
|
+
reset,
|
|
30
27
|
rpcInfo,
|
|
31
28
|
rpcSetUrl,
|
|
29
|
+
show,
|
|
32
30
|
sign,
|
|
33
|
-
signChallenge,
|
|
34
31
|
signEvmHash,
|
|
35
|
-
signMessage,
|
|
36
32
|
signSolanaBytes,
|
|
37
33
|
signTx,
|
|
38
34
|
status
|
|
39
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-445BLP4Q.js";
|
|
36
|
+
import {
|
|
37
|
+
NIT_NAMESPACE,
|
|
38
|
+
deriveAgentId,
|
|
39
|
+
fetchBranchCard,
|
|
40
|
+
formatPublicKeyField,
|
|
41
|
+
loadAgentId,
|
|
42
|
+
loadRawKeyPair,
|
|
43
|
+
parsePublicKeyField,
|
|
44
|
+
signChallenge,
|
|
45
|
+
signMessage
|
|
46
|
+
} from "./chunk-M6SR6QMR.js";
|
|
40
47
|
export {
|
|
41
48
|
NIT_NAMESPACE,
|
|
49
|
+
authSet,
|
|
50
|
+
authShow,
|
|
42
51
|
base58Encode,
|
|
43
52
|
branch,
|
|
44
53
|
broadcast,
|
|
@@ -61,12 +70,15 @@ export {
|
|
|
61
70
|
log,
|
|
62
71
|
loginPayload,
|
|
63
72
|
parsePublicKeyField,
|
|
73
|
+
pull,
|
|
64
74
|
push,
|
|
65
75
|
remote,
|
|
66
76
|
remoteAdd,
|
|
67
77
|
remoteSetUrl,
|
|
78
|
+
reset,
|
|
68
79
|
rpcInfo,
|
|
69
80
|
rpcSetUrl,
|
|
81
|
+
show,
|
|
70
82
|
sign,
|
|
71
83
|
signChallenge,
|
|
72
84
|
signEvmHash,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// nit — version control for agent cards
|
|
2
|
+
import {
|
|
3
|
+
deleteRemoteBranch,
|
|
4
|
+
fetchBranchCard,
|
|
5
|
+
listRemoteBranches,
|
|
6
|
+
pushAll,
|
|
7
|
+
pushBranch
|
|
8
|
+
} from "./chunk-M6SR6QMR.js";
|
|
9
|
+
export {
|
|
10
|
+
deleteRemoteBranch,
|
|
11
|
+
fetchBranchCard,
|
|
12
|
+
listRemoteBranches,
|
|
13
|
+
pushAll,
|
|
14
|
+
pushBranch
|
|
15
|
+
};
|