@newtype-ai/nit 0.4.9 → 0.4.10
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-M6SR6QMR.js +291 -0
- package/dist/{chunk-Q5GX7ZXR.js → chunk-WHSQICPU.js} +367 -313
- package/dist/cli.js +120 -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
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
// nit — version control for agent cards
|
|
2
|
+
import {
|
|
3
|
+
deriveAgentId,
|
|
4
|
+
formatPublicKeyField,
|
|
5
|
+
generateKeypair,
|
|
6
|
+
loadAgentId,
|
|
7
|
+
loadPrivateKey,
|
|
8
|
+
loadPublicKey,
|
|
9
|
+
pushBranch,
|
|
10
|
+
saveAgentId,
|
|
11
|
+
signMessage
|
|
12
|
+
} from "./chunk-M6SR6QMR.js";
|
|
2
13
|
|
|
3
14
|
// src/index.ts
|
|
4
|
-
import { promises as
|
|
5
|
-
import { join as
|
|
15
|
+
import { promises as fs6, statSync } from "fs";
|
|
16
|
+
import { join as join6, basename as basename2, dirname as dirname2, resolve as resolve2 } from "path";
|
|
6
17
|
|
|
7
18
|
// src/objects.ts
|
|
8
19
|
import { createHash } from "crypto";
|
|
@@ -168,156 +179,9 @@ async function getRemoteRef(nitDir, remote2, branch2) {
|
|
|
168
179
|
}
|
|
169
180
|
}
|
|
170
181
|
|
|
171
|
-
// src/identity.ts
|
|
172
|
-
import {
|
|
173
|
-
createHash as createHash2,
|
|
174
|
-
generateKeyPairSync,
|
|
175
|
-
createPrivateKey,
|
|
176
|
-
createPublicKey,
|
|
177
|
-
sign,
|
|
178
|
-
verify
|
|
179
|
-
} from "crypto";
|
|
180
|
-
import { promises as fs3 } from "fs";
|
|
181
|
-
import { join as join3 } from "path";
|
|
182
|
-
function base64urlToBase64(b64url) {
|
|
183
|
-
let s = b64url.replace(/-/g, "+").replace(/_/g, "/");
|
|
184
|
-
while (s.length % 4 !== 0) s += "=";
|
|
185
|
-
return s;
|
|
186
|
-
}
|
|
187
|
-
function base64ToBase64url(b64) {
|
|
188
|
-
return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
189
|
-
}
|
|
190
|
-
async function generateKeypair(nitDir) {
|
|
191
|
-
const identityDir = join3(nitDir, "identity");
|
|
192
|
-
await fs3.mkdir(identityDir, { recursive: true });
|
|
193
|
-
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
|
194
|
-
const pubJwk = publicKey.export({ format: "jwk" });
|
|
195
|
-
const privJwk = privateKey.export({ format: "jwk" });
|
|
196
|
-
const pubBase64 = base64urlToBase64(pubJwk.x);
|
|
197
|
-
const privBase64 = base64urlToBase64(privJwk.d);
|
|
198
|
-
const pubPath = join3(identityDir, "agent.pub");
|
|
199
|
-
const keyPath = join3(identityDir, "agent.key");
|
|
200
|
-
await fs3.writeFile(pubPath, pubBase64 + "\n", "utf-8");
|
|
201
|
-
await fs3.writeFile(keyPath, privBase64 + "\n", {
|
|
202
|
-
mode: 384,
|
|
203
|
-
encoding: "utf-8"
|
|
204
|
-
});
|
|
205
|
-
return { publicKey: pubBase64, privateKey: privBase64 };
|
|
206
|
-
}
|
|
207
|
-
async function loadPublicKey(nitDir) {
|
|
208
|
-
const pubPath = join3(nitDir, "identity", "agent.pub");
|
|
209
|
-
try {
|
|
210
|
-
return (await fs3.readFile(pubPath, "utf-8")).trim();
|
|
211
|
-
} catch {
|
|
212
|
-
throw new Error(
|
|
213
|
-
"No identity found. Run `nit init` to generate a keypair."
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
async function loadPrivateKey(nitDir) {
|
|
218
|
-
const pubBase64 = await loadPublicKey(nitDir);
|
|
219
|
-
const keyPath = join3(nitDir, "identity", "agent.key");
|
|
220
|
-
let privBase64;
|
|
221
|
-
try {
|
|
222
|
-
privBase64 = (await fs3.readFile(keyPath, "utf-8")).trim();
|
|
223
|
-
} catch {
|
|
224
|
-
throw new Error(
|
|
225
|
-
"Private key not found at .nit/identity/agent.key. Regenerate with `nit init`."
|
|
226
|
-
);
|
|
227
|
-
}
|
|
228
|
-
const xB64url = base64ToBase64url(pubBase64);
|
|
229
|
-
const dB64url = base64ToBase64url(privBase64);
|
|
230
|
-
return createPrivateKey({
|
|
231
|
-
key: { kty: "OKP", crv: "Ed25519", x: xB64url, d: dB64url },
|
|
232
|
-
format: "jwk"
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
async function loadRawKeyPair(nitDir) {
|
|
236
|
-
const pubBase64 = await loadPublicKey(nitDir);
|
|
237
|
-
const keyPath = join3(nitDir, "identity", "agent.key");
|
|
238
|
-
let privBase64;
|
|
239
|
-
try {
|
|
240
|
-
privBase64 = (await fs3.readFile(keyPath, "utf-8")).trim();
|
|
241
|
-
} catch {
|
|
242
|
-
throw new Error(
|
|
243
|
-
"Private key not found at .nit/identity/agent.key. Regenerate with `nit init`."
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
const seed = Buffer.from(privBase64, "base64");
|
|
247
|
-
const pubkey = Buffer.from(pubBase64, "base64");
|
|
248
|
-
const keypair = new Uint8Array(64);
|
|
249
|
-
keypair.set(seed, 0);
|
|
250
|
-
keypair.set(pubkey, 32);
|
|
251
|
-
return keypair;
|
|
252
|
-
}
|
|
253
|
-
function formatPublicKeyField(pubBase64) {
|
|
254
|
-
return `ed25519:${pubBase64}`;
|
|
255
|
-
}
|
|
256
|
-
function parsePublicKeyField(field) {
|
|
257
|
-
const prefix = "ed25519:";
|
|
258
|
-
if (!field.startsWith(prefix)) {
|
|
259
|
-
throw new Error(
|
|
260
|
-
`Invalid publicKey format: expected "ed25519:<base64>", got "${field}"`
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
return field.slice(prefix.length);
|
|
264
|
-
}
|
|
265
|
-
async function signChallenge(nitDir, challenge) {
|
|
266
|
-
const privateKey = await loadPrivateKey(nitDir);
|
|
267
|
-
const sig = sign(null, Buffer.from(challenge, "utf-8"), privateKey);
|
|
268
|
-
return sig.toString("base64");
|
|
269
|
-
}
|
|
270
|
-
async function signMessage(nitDir, message) {
|
|
271
|
-
const privateKey = await loadPrivateKey(nitDir);
|
|
272
|
-
const sig = sign(null, Buffer.from(message, "utf-8"), privateKey);
|
|
273
|
-
return sig.toString("base64");
|
|
274
|
-
}
|
|
275
|
-
var NIT_NAMESPACE = "801ba518-f326-47e5-97c9-d1efd1865a19";
|
|
276
|
-
function deriveAgentId(publicKeyField) {
|
|
277
|
-
return uuidv5(publicKeyField, NIT_NAMESPACE);
|
|
278
|
-
}
|
|
279
|
-
async function loadAgentId(nitDir) {
|
|
280
|
-
const idPath = join3(nitDir, "identity", "agent-id");
|
|
281
|
-
try {
|
|
282
|
-
return (await fs3.readFile(idPath, "utf-8")).trim();
|
|
283
|
-
} catch {
|
|
284
|
-
throw new Error(
|
|
285
|
-
"No agent ID found. Run `nit init` to generate identity."
|
|
286
|
-
);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
async function saveAgentId(nitDir, agentId) {
|
|
290
|
-
const idPath = join3(nitDir, "identity", "agent-id");
|
|
291
|
-
await fs3.writeFile(idPath, agentId + "\n", "utf-8");
|
|
292
|
-
}
|
|
293
|
-
function parseUuid(uuid) {
|
|
294
|
-
const hex = uuid.replace(/-/g, "");
|
|
295
|
-
return Buffer.from(hex, "hex");
|
|
296
|
-
}
|
|
297
|
-
function formatUuid(bytes) {
|
|
298
|
-
const hex = bytes.toString("hex");
|
|
299
|
-
return [
|
|
300
|
-
hex.slice(0, 8),
|
|
301
|
-
hex.slice(8, 12),
|
|
302
|
-
hex.slice(12, 16),
|
|
303
|
-
hex.slice(16, 20),
|
|
304
|
-
hex.slice(20, 32)
|
|
305
|
-
].join("-");
|
|
306
|
-
}
|
|
307
|
-
function uuidv5(name, namespace) {
|
|
308
|
-
const namespaceBytes = parseUuid(namespace);
|
|
309
|
-
const nameBytes = Buffer.from(name, "utf-8");
|
|
310
|
-
const data = Buffer.concat([namespaceBytes, nameBytes]);
|
|
311
|
-
const hash = createHash2("sha1").update(data).digest();
|
|
312
|
-
const uuid = Buffer.from(hash.subarray(0, 16));
|
|
313
|
-
uuid[6] = uuid[6] & 15 | 80;
|
|
314
|
-
uuid[8] = uuid[8] & 63 | 128;
|
|
315
|
-
return formatUuid(uuid);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
182
|
// src/skills.ts
|
|
319
|
-
import { promises as
|
|
320
|
-
import { join as
|
|
183
|
+
import { promises as fs3 } from "fs";
|
|
184
|
+
import { join as join3, resolve } from "path";
|
|
321
185
|
import { homedir } from "os";
|
|
322
186
|
var FRAMEWORK_MARKERS = [
|
|
323
187
|
{ marker: ".claude", skillsPath: ".claude/skills" },
|
|
@@ -338,36 +202,36 @@ async function discoverSkillsDir(projectDir2) {
|
|
|
338
202
|
const idx = absProject.indexOf(`/${marker}`);
|
|
339
203
|
if (idx !== -1) {
|
|
340
204
|
const root = absProject.slice(0, idx);
|
|
341
|
-
return
|
|
205
|
+
return join3(root, skillsPath);
|
|
342
206
|
}
|
|
343
207
|
}
|
|
344
208
|
for (const { marker, skillsPath } of FRAMEWORK_MARKERS) {
|
|
345
209
|
try {
|
|
346
|
-
const stat = await
|
|
210
|
+
const stat = await fs3.stat(join3(absProject, marker));
|
|
347
211
|
if (stat.isDirectory()) {
|
|
348
|
-
return
|
|
212
|
+
return join3(absProject, skillsPath);
|
|
349
213
|
}
|
|
350
214
|
} catch {
|
|
351
215
|
}
|
|
352
216
|
}
|
|
353
217
|
for (const { marker, skillsPath } of GLOBAL_SKILLS_DIRS) {
|
|
354
218
|
try {
|
|
355
|
-
const stat = await
|
|
219
|
+
const stat = await fs3.stat(join3(home, marker));
|
|
356
220
|
if (stat.isDirectory()) {
|
|
357
|
-
return
|
|
221
|
+
return join3(home, skillsPath);
|
|
358
222
|
}
|
|
359
223
|
} catch {
|
|
360
224
|
}
|
|
361
225
|
}
|
|
362
|
-
return
|
|
226
|
+
return join3(absProject, ".agents", "skills");
|
|
363
227
|
}
|
|
364
228
|
async function createSkillTemplate(skillsDir, domain) {
|
|
365
229
|
const skillId = domain.replace(/\./g, "-");
|
|
366
|
-
const skillDir =
|
|
367
|
-
const skillPath =
|
|
230
|
+
const skillDir = join3(skillsDir, skillId);
|
|
231
|
+
const skillPath = join3(skillDir, "SKILL.md");
|
|
368
232
|
let localVersion;
|
|
369
233
|
try {
|
|
370
|
-
const existing = await
|
|
234
|
+
const existing = await fs3.readFile(skillPath, "utf-8");
|
|
371
235
|
localVersion = parseVersion(existing);
|
|
372
236
|
} catch {
|
|
373
237
|
}
|
|
@@ -392,8 +256,8 @@ async function createSkillTemplate(skillsDir, domain) {
|
|
|
392
256
|
return skillId;
|
|
393
257
|
}
|
|
394
258
|
}
|
|
395
|
-
await
|
|
396
|
-
await
|
|
259
|
+
await fs3.mkdir(skillDir, { recursive: true });
|
|
260
|
+
await fs3.writeFile(
|
|
397
261
|
skillPath,
|
|
398
262
|
remoteContent ?? fallbackTemplate(skillId, domain),
|
|
399
263
|
"utf-8"
|
|
@@ -433,17 +297,17 @@ async function discoverSkills(projectDir2) {
|
|
|
433
297
|
const home = homedir();
|
|
434
298
|
const searchDirs = [
|
|
435
299
|
// Project-local (all known agent frameworks)
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
300
|
+
join3(projectDir2, ".claude", "skills"),
|
|
301
|
+
join3(projectDir2, ".cursor", "skills"),
|
|
302
|
+
join3(projectDir2, ".windsurf", "skills"),
|
|
303
|
+
join3(projectDir2, ".codex", "skills"),
|
|
304
|
+
join3(projectDir2, ".agents", "skills"),
|
|
441
305
|
// User-global
|
|
442
|
-
|
|
306
|
+
join3(home, ".claude", "skills"),
|
|
443
307
|
// Claude Code + Cursor (shared)
|
|
444
|
-
|
|
308
|
+
join3(home, ".codex", "skills"),
|
|
445
309
|
// Codex CLI
|
|
446
|
-
|
|
310
|
+
join3(home, ".codeium", "windsurf", "skills")
|
|
447
311
|
// Windsurf
|
|
448
312
|
];
|
|
449
313
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -473,18 +337,166 @@ async function resolveSkillPointers(card, projectDir2) {
|
|
|
473
337
|
});
|
|
474
338
|
return { ...card, skills: resolvedSkills };
|
|
475
339
|
}
|
|
340
|
+
var AUTH_TEMPLATES = {
|
|
341
|
+
google: (domain, account) => `## Authentication
|
|
342
|
+
|
|
343
|
+
To access ${domain}, use browser profile="user" to reuse the existing Google session (${account}).
|
|
344
|
+
|
|
345
|
+
**Stage 1 \u2014 session reuse:** Open the browser with profile="user" and navigate to ${domain}. If the browser's existing session cookies are valid, you will be logged in automatically. Proceed without any login action.
|
|
346
|
+
|
|
347
|
+
**Stage 2 \u2014 OAuth consent (if login page appears):**
|
|
348
|
+
1. Look for a "Sign in with Google" or "Continue with Google" button and click it
|
|
349
|
+
2. You will be redirected to accounts.google.com
|
|
350
|
+
3. If an account picker appears, select ${account}
|
|
351
|
+
4. On the consent page, click "Allow", "Continue", or "Authorize"
|
|
352
|
+
5. Wait for redirect back to ${domain}
|
|
353
|
+
|
|
354
|
+
IMPORTANT: You MUST use browser profile="user" to attach to the human's Chrome session via Chrome DevTools MCP. Do NOT use the default isolated browser profile. Do NOT enter any credentials. Do NOT ask the human for confirmation. Just click through the consent flow.`,
|
|
355
|
+
github: (domain, account) => `## Authentication
|
|
356
|
+
|
|
357
|
+
To access ${domain}, use browser profile="user" to reuse the existing GitHub session (${account}).
|
|
358
|
+
|
|
359
|
+
**Stage 1 \u2014 session reuse:** Open the browser with profile="user" and navigate to ${domain}. If the browser's existing session cookies are valid, you will be logged in automatically. Proceed without any login action.
|
|
360
|
+
|
|
361
|
+
**Stage 2 \u2014 OAuth consent (if login page appears):**
|
|
362
|
+
1. Look for a "Sign in with GitHub" or "Continue with GitHub" button and click it
|
|
363
|
+
2. You will be redirected to github.com/login/oauth/authorize
|
|
364
|
+
3. On the authorization page, click "Authorize [app name]"
|
|
365
|
+
4. Wait for redirect back to ${domain}
|
|
366
|
+
|
|
367
|
+
IMPORTANT: You MUST use browser profile="user" to attach to the human's Chrome session via Chrome DevTools MCP. Do NOT use the default isolated browser profile. Do NOT enter any credentials. Do NOT ask the human for confirmation. Just click through the consent flow.`,
|
|
368
|
+
x: (domain, account) => `## Authentication
|
|
369
|
+
|
|
370
|
+
To access ${domain}, use browser profile="user" to reuse the existing X session (${account}).
|
|
371
|
+
|
|
372
|
+
**Stage 1 \u2014 session reuse:** Open the browser with profile="user" and navigate to ${domain}. If the browser's existing session cookies are valid, you will be logged in automatically. Proceed without any login action.
|
|
373
|
+
|
|
374
|
+
**Stage 2 \u2014 OAuth consent (if login page appears):**
|
|
375
|
+
1. Look for a "Sign in with X", "Sign in with Twitter", or "Continue with X" button and click it
|
|
376
|
+
2. You will be redirected to x.com or api.twitter.com
|
|
377
|
+
3. On the authorization page, click "Authorize app"
|
|
378
|
+
4. Wait for redirect back to ${domain}
|
|
379
|
+
|
|
380
|
+
IMPORTANT: You MUST use browser profile="user" to attach to the human's Chrome session via Chrome DevTools MCP. Do NOT use the default isolated browser profile. Do NOT enter any credentials. Do NOT ask the human for confirmation. Just click through the consent flow.`
|
|
381
|
+
};
|
|
382
|
+
function generateAuthInstructions(provider, account, domain) {
|
|
383
|
+
return AUTH_TEMPLATES[provider](domain, account);
|
|
384
|
+
}
|
|
385
|
+
async function updateSkillAuth(skillsDir, domain, auth) {
|
|
386
|
+
const skillId = domain.replace(/\./g, "-");
|
|
387
|
+
const skillDir = join3(skillsDir, skillId);
|
|
388
|
+
const skillPath = join3(skillDir, "SKILL.md");
|
|
389
|
+
await fs3.mkdir(skillDir, { recursive: true });
|
|
390
|
+
let content;
|
|
391
|
+
try {
|
|
392
|
+
content = await fs3.readFile(skillPath, "utf-8");
|
|
393
|
+
} catch {
|
|
394
|
+
content = `---
|
|
395
|
+
name: ${skillId}
|
|
396
|
+
description: Skills and context for ${domain}
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
# ${skillId}
|
|
400
|
+
`;
|
|
401
|
+
}
|
|
402
|
+
content = upsertAuthFrontmatter(content, auth);
|
|
403
|
+
const instructions = generateAuthInstructions(auth.provider, auth.account, domain);
|
|
404
|
+
content = upsertAuthBody(content, instructions);
|
|
405
|
+
await fs3.writeFile(skillPath, content, "utf-8");
|
|
406
|
+
return skillId;
|
|
407
|
+
}
|
|
408
|
+
async function readSkillAuth(skillsDir, domain) {
|
|
409
|
+
const skillId = domain.replace(/\./g, "-");
|
|
410
|
+
const skillPath = join3(skillsDir, skillId, "SKILL.md");
|
|
411
|
+
let content;
|
|
412
|
+
try {
|
|
413
|
+
content = await fs3.readFile(skillPath, "utf-8");
|
|
414
|
+
} catch {
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
return parseAuthFrontmatter(content);
|
|
418
|
+
}
|
|
419
|
+
function upsertAuthFrontmatter(content, auth) {
|
|
420
|
+
const fmMatch = content.match(/^(---\r?\n)([\s\S]*?)(\r?\n---)/);
|
|
421
|
+
if (!fmMatch) {
|
|
422
|
+
const fm = `---
|
|
423
|
+
name: skill
|
|
424
|
+
description: skill
|
|
425
|
+
auth:
|
|
426
|
+
provider: ${auth.provider}
|
|
427
|
+
account: ${auth.account}
|
|
428
|
+
---
|
|
429
|
+
`;
|
|
430
|
+
return fm + content;
|
|
431
|
+
}
|
|
432
|
+
let fmBody = fmMatch[2];
|
|
433
|
+
fmBody = fmBody.replace(/^auth:\n(?: .+\n)*/m, "");
|
|
434
|
+
fmBody = fmBody.replace(/\n\n$/, "\n");
|
|
435
|
+
if (!fmBody.endsWith("\n")) fmBody += "\n";
|
|
436
|
+
fmBody += `auth:
|
|
437
|
+
provider: ${auth.provider}
|
|
438
|
+
account: ${auth.account}
|
|
439
|
+
`;
|
|
440
|
+
return fmMatch[1] + fmBody + fmMatch[3] + content.slice(fmMatch[0].length);
|
|
441
|
+
}
|
|
442
|
+
function parseAuthFrontmatter(content) {
|
|
443
|
+
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
444
|
+
if (!fmMatch) return null;
|
|
445
|
+
const fmBlock = fmMatch[1];
|
|
446
|
+
let inAuth = false;
|
|
447
|
+
let provider;
|
|
448
|
+
let account;
|
|
449
|
+
for (const line of fmBlock.split("\n")) {
|
|
450
|
+
const trimmed = line.trimEnd();
|
|
451
|
+
if (trimmed === "auth:") {
|
|
452
|
+
inAuth = true;
|
|
453
|
+
continue;
|
|
454
|
+
}
|
|
455
|
+
if (inAuth) {
|
|
456
|
+
const nestedMatch = trimmed.match(/^\s+(\w+):\s*(.+)$/);
|
|
457
|
+
if (nestedMatch) {
|
|
458
|
+
if (nestedMatch[1] === "provider") provider = nestedMatch[2].trim();
|
|
459
|
+
if (nestedMatch[1] === "account") account = nestedMatch[2].trim();
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
inAuth = false;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
if (!provider || !account) return null;
|
|
466
|
+
const validProviders = ["google", "github", "x"];
|
|
467
|
+
if (!validProviders.includes(provider)) return null;
|
|
468
|
+
return { provider, account };
|
|
469
|
+
}
|
|
470
|
+
function upsertAuthBody(content, instructions) {
|
|
471
|
+
const fmEnd = content.indexOf("---", 3);
|
|
472
|
+
if (fmEnd === -1) return content + "\n\n" + instructions + "\n";
|
|
473
|
+
const afterFm = content.indexOf("\n", fmEnd + 3);
|
|
474
|
+
const frontmatter = content.slice(0, afterFm + 1);
|
|
475
|
+
let body = content.slice(afterFm + 1);
|
|
476
|
+
const authSectionRegex = /## Authentication\n[\s\S]*?(?=\n## |\n*$)/;
|
|
477
|
+
if (authSectionRegex.test(body)) {
|
|
478
|
+
body = body.replace(authSectionRegex, instructions);
|
|
479
|
+
} else {
|
|
480
|
+
if (body.trim()) {
|
|
481
|
+
body = body.trimEnd() + "\n\n" + instructions + "\n";
|
|
482
|
+
} else {
|
|
483
|
+
body = "\n" + instructions + "\n";
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
return frontmatter + body;
|
|
487
|
+
}
|
|
476
488
|
async function scanSkillDir(dir) {
|
|
477
489
|
let entries;
|
|
478
490
|
try {
|
|
479
|
-
entries = await
|
|
491
|
+
entries = await fs3.readdir(dir);
|
|
480
492
|
} catch {
|
|
481
493
|
return [];
|
|
482
494
|
}
|
|
483
495
|
const skills = [];
|
|
484
496
|
for (const entry of entries) {
|
|
485
|
-
const skillMdPath =
|
|
497
|
+
const skillMdPath = join3(dir, entry, "SKILL.md");
|
|
486
498
|
try {
|
|
487
|
-
const content = await
|
|
499
|
+
const content = await fs3.readFile(skillMdPath, "utf-8");
|
|
488
500
|
const meta = parseFrontmatter(content, entry, skillMdPath);
|
|
489
501
|
if (meta) skills.push(meta);
|
|
490
502
|
} catch {
|
|
@@ -534,8 +546,8 @@ function parseFrontmatter(content, dirName, filePath) {
|
|
|
534
546
|
|
|
535
547
|
// src/wallet.ts
|
|
536
548
|
import { createHmac, createECDH, sign as cryptoSign } from "crypto";
|
|
537
|
-
import { promises as
|
|
538
|
-
import { join as
|
|
549
|
+
import { promises as fs4 } from "fs";
|
|
550
|
+
import { join as join4 } from "path";
|
|
539
551
|
|
|
540
552
|
// node_modules/@noble/hashes/_u64.js
|
|
541
553
|
var U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
|
|
@@ -1229,7 +1241,7 @@ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
|
|
|
1229
1241
|
let v = u8n(hashLen);
|
|
1230
1242
|
let k = u8n(hashLen);
|
|
1231
1243
|
let i = 0;
|
|
1232
|
-
const
|
|
1244
|
+
const reset2 = () => {
|
|
1233
1245
|
v.fill(1);
|
|
1234
1246
|
k.fill(0);
|
|
1235
1247
|
i = 0;
|
|
@@ -1257,12 +1269,12 @@ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
|
|
|
1257
1269
|
return concatBytes(...out);
|
|
1258
1270
|
};
|
|
1259
1271
|
const genUntil = (seed, pred) => {
|
|
1260
|
-
|
|
1272
|
+
reset2();
|
|
1261
1273
|
reseed(seed);
|
|
1262
1274
|
let res = void 0;
|
|
1263
1275
|
while (!(res = pred(gen())))
|
|
1264
1276
|
reseed();
|
|
1265
|
-
|
|
1277
|
+
reset2();
|
|
1266
1278
|
return res;
|
|
1267
1279
|
};
|
|
1268
1280
|
return genUntil;
|
|
@@ -2802,13 +2814,13 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2802
2814
|
}
|
|
2803
2815
|
return { seed, k2sig };
|
|
2804
2816
|
}
|
|
2805
|
-
function
|
|
2817
|
+
function sign2(message, secretKey, opts = {}) {
|
|
2806
2818
|
const { seed, k2sig } = prepSig(message, secretKey, opts);
|
|
2807
2819
|
const drbg = createHmacDrbg(hash.outputLen, Fn.BYTES, hmac2);
|
|
2808
2820
|
const sig = drbg(seed, k2sig);
|
|
2809
2821
|
return sig.toBytes(opts.format);
|
|
2810
2822
|
}
|
|
2811
|
-
function
|
|
2823
|
+
function verify(signature, message, publicKey, opts = {}) {
|
|
2812
2824
|
const { lowS, prehash, format } = validateSigOpts(opts, defaultSigOpts);
|
|
2813
2825
|
publicKey = abytes(publicKey, void 0, "publicKey");
|
|
2814
2826
|
message = validateMsgAndHash(message, prehash);
|
|
@@ -2848,8 +2860,8 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
2848
2860
|
utils,
|
|
2849
2861
|
lengths,
|
|
2850
2862
|
Point,
|
|
2851
|
-
sign:
|
|
2852
|
-
verify
|
|
2863
|
+
sign: sign2,
|
|
2864
|
+
verify,
|
|
2853
2865
|
recoverPublicKey,
|
|
2854
2866
|
Signature,
|
|
2855
2867
|
hash
|
|
@@ -2955,8 +2967,8 @@ async function getSolanaAddress(nitDir) {
|
|
|
2955
2967
|
return base58Encode(pubBytes);
|
|
2956
2968
|
}
|
|
2957
2969
|
async function getEvmAddress(nitDir) {
|
|
2958
|
-
const keyPath =
|
|
2959
|
-
const privBase64 = (await
|
|
2970
|
+
const keyPath = join4(nitDir, "identity", "agent.key");
|
|
2971
|
+
const privBase64 = (await fs4.readFile(keyPath, "utf-8")).trim();
|
|
2960
2972
|
const ed25519Seed = Buffer.from(privBase64, "base64");
|
|
2961
2973
|
const secp256k1PrivKey = deriveSecp256k1Seed(ed25519Seed);
|
|
2962
2974
|
const secp256k1PubKey = getSecp256k1PublicKey(secp256k1PrivKey);
|
|
@@ -2971,8 +2983,8 @@ async function getWalletAddresses(nitDir) {
|
|
|
2971
2983
|
return { solana, ethereum };
|
|
2972
2984
|
}
|
|
2973
2985
|
async function loadSecp256k1RawKeyPair(nitDir) {
|
|
2974
|
-
const keyPath =
|
|
2975
|
-
const privBase64 = (await
|
|
2986
|
+
const keyPath = join4(nitDir, "identity", "agent.key");
|
|
2987
|
+
const privBase64 = (await fs4.readFile(keyPath, "utf-8")).trim();
|
|
2976
2988
|
const ed25519Seed = Buffer.from(privBase64, "base64");
|
|
2977
2989
|
const secp256k1PrivKey = deriveSecp256k1Seed(ed25519Seed);
|
|
2978
2990
|
const secp256k1PubKey = getSecp256k1PublicKey(secp256k1PrivKey);
|
|
@@ -2985,8 +2997,8 @@ async function signEvmHash(nitDir, hash) {
|
|
|
2985
2997
|
if (hash.length !== 32) {
|
|
2986
2998
|
throw new Error(`Expected 32-byte hash, got ${hash.length} bytes`);
|
|
2987
2999
|
}
|
|
2988
|
-
const keyPath =
|
|
2989
|
-
const privBase64 = (await
|
|
3000
|
+
const keyPath = join4(nitDir, "identity", "agent.key");
|
|
3001
|
+
const privBase64 = (await fs4.readFile(keyPath, "utf-8")).trim();
|
|
2990
3002
|
const ed25519Seed = Buffer.from(privBase64, "base64");
|
|
2991
3003
|
const privKey = deriveSecp256k1Seed(ed25519Seed);
|
|
2992
3004
|
const sigBytes = secp256k1.sign(hash, privKey, { prehash: false, format: "recovered" });
|
|
@@ -3097,115 +3109,23 @@ function formatValue(val) {
|
|
|
3097
3109
|
return JSON.stringify(val);
|
|
3098
3110
|
}
|
|
3099
3111
|
|
|
3100
|
-
// src/remote.ts
|
|
3101
|
-
import { createHash as createHash3 } from "crypto";
|
|
3102
|
-
function sha256Hex(data) {
|
|
3103
|
-
return createHash3("sha256").update(data, "utf-8").digest("hex");
|
|
3104
|
-
}
|
|
3105
|
-
async function buildAuthHeaders(nitDir, method, path, body) {
|
|
3106
|
-
const agentId = await loadAgentId(nitDir);
|
|
3107
|
-
const timestamp = Math.floor(Date.now() / 1e3).toString();
|
|
3108
|
-
let message = `${method}
|
|
3109
|
-
${path}
|
|
3110
|
-
${agentId}
|
|
3111
|
-
${timestamp}`;
|
|
3112
|
-
if (body !== void 0) {
|
|
3113
|
-
message += `
|
|
3114
|
-
${sha256Hex(body)}`;
|
|
3115
|
-
}
|
|
3116
|
-
const signature = await signMessage(nitDir, message);
|
|
3117
|
-
return {
|
|
3118
|
-
"X-Nit-Agent-Id": agentId,
|
|
3119
|
-
"X-Nit-Timestamp": timestamp,
|
|
3120
|
-
"X-Nit-Signature": signature
|
|
3121
|
-
};
|
|
3122
|
-
}
|
|
3123
|
-
async function pushBranch(nitDir, apiBase, branch2, cardJson, commitHash) {
|
|
3124
|
-
const path = `/agent-card/branches/${encodeURIComponent(branch2)}`;
|
|
3125
|
-
const body = JSON.stringify({ card_json: cardJson, commit_hash: commitHash });
|
|
3126
|
-
try {
|
|
3127
|
-
const authHeaders = await buildAuthHeaders(nitDir, "PUT", path, body);
|
|
3128
|
-
const res = await fetch(`${apiBase}${path}`, {
|
|
3129
|
-
method: "PUT",
|
|
3130
|
-
headers: {
|
|
3131
|
-
"Content-Type": "application/json",
|
|
3132
|
-
...authHeaders
|
|
3133
|
-
},
|
|
3134
|
-
body
|
|
3135
|
-
});
|
|
3136
|
-
if (!res.ok) {
|
|
3137
|
-
const text = await res.text();
|
|
3138
|
-
return {
|
|
3139
|
-
branch: branch2,
|
|
3140
|
-
commitHash,
|
|
3141
|
-
remoteUrl: apiBase,
|
|
3142
|
-
success: false,
|
|
3143
|
-
error: `HTTP ${res.status}: ${text}`
|
|
3144
|
-
};
|
|
3145
|
-
}
|
|
3146
|
-
return { branch: branch2, commitHash, remoteUrl: apiBase, success: true };
|
|
3147
|
-
} catch (err) {
|
|
3148
|
-
return {
|
|
3149
|
-
branch: branch2,
|
|
3150
|
-
commitHash,
|
|
3151
|
-
remoteUrl: apiBase,
|
|
3152
|
-
success: false,
|
|
3153
|
-
error: err instanceof Error ? err.message : String(err)
|
|
3154
|
-
};
|
|
3155
|
-
}
|
|
3156
|
-
}
|
|
3157
|
-
async function fetchBranchCard(cardUrl, branch2, nitDir) {
|
|
3158
|
-
const baseUrl = cardUrl.replace(/\/$/, "");
|
|
3159
|
-
let url = `${baseUrl}/.well-known/agent-card.json`;
|
|
3160
|
-
if (branch2 !== "main") {
|
|
3161
|
-
url += `?branch=${encodeURIComponent(branch2)}`;
|
|
3162
|
-
}
|
|
3163
|
-
const res = await fetch(url);
|
|
3164
|
-
if (res.ok) {
|
|
3165
|
-
return await res.json();
|
|
3166
|
-
}
|
|
3167
|
-
if (res.status === 401 && branch2 !== "main") {
|
|
3168
|
-
if (!nitDir) {
|
|
3169
|
-
throw new Error(
|
|
3170
|
-
`Branch "${branch2}" requires authentication. Provide nitDir for signing.`
|
|
3171
|
-
);
|
|
3172
|
-
}
|
|
3173
|
-
const challengeData = await res.json();
|
|
3174
|
-
const signature = await signChallenge(nitDir, challengeData.challenge);
|
|
3175
|
-
const authRes = await fetch(url, {
|
|
3176
|
-
headers: {
|
|
3177
|
-
"X-Nit-Challenge": challengeData.challenge,
|
|
3178
|
-
"X-Nit-Signature": signature
|
|
3179
|
-
}
|
|
3180
|
-
});
|
|
3181
|
-
if (!authRes.ok) {
|
|
3182
|
-
const body = await authRes.text();
|
|
3183
|
-
throw new Error(
|
|
3184
|
-
`Failed to fetch branch "${branch2}" after challenge: HTTP ${authRes.status} ${body}`
|
|
3185
|
-
);
|
|
3186
|
-
}
|
|
3187
|
-
return await authRes.json();
|
|
3188
|
-
}
|
|
3189
|
-
throw new Error(`Failed to fetch card: HTTP ${res.status}`);
|
|
3190
|
-
}
|
|
3191
|
-
|
|
3192
3112
|
// src/config.ts
|
|
3193
|
-
import { promises as
|
|
3194
|
-
import { join as
|
|
3113
|
+
import { promises as fs5 } from "fs";
|
|
3114
|
+
import { join as join5 } from "path";
|
|
3195
3115
|
var CONFIG_FILE = "config";
|
|
3196
3116
|
async function readConfig(nitDir) {
|
|
3197
|
-
const configPath =
|
|
3117
|
+
const configPath = join5(nitDir, CONFIG_FILE);
|
|
3198
3118
|
let raw;
|
|
3199
3119
|
try {
|
|
3200
|
-
raw = await
|
|
3120
|
+
raw = await fs5.readFile(configPath, "utf-8");
|
|
3201
3121
|
} catch {
|
|
3202
3122
|
return { remotes: {} };
|
|
3203
3123
|
}
|
|
3204
3124
|
return parseConfig(raw);
|
|
3205
3125
|
}
|
|
3206
3126
|
async function writeConfig(nitDir, config) {
|
|
3207
|
-
const configPath =
|
|
3208
|
-
await
|
|
3127
|
+
const configPath = join5(nitDir, CONFIG_FILE);
|
|
3128
|
+
await fs5.writeFile(configPath, serializeConfig(config), "utf-8");
|
|
3209
3129
|
}
|
|
3210
3130
|
async function getRemoteUrl(nitDir, remoteName) {
|
|
3211
3131
|
const config = await readConfig(nitDir);
|
|
@@ -3377,7 +3297,7 @@ var DEFAULT_API_BASE = "https://api.newtype-ai.org";
|
|
|
3377
3297
|
function findNitDir(startDir) {
|
|
3378
3298
|
let dir = resolve2(startDir || process.cwd());
|
|
3379
3299
|
while (true) {
|
|
3380
|
-
const candidate =
|
|
3300
|
+
const candidate = join6(dir, NIT_DIR);
|
|
3381
3301
|
try {
|
|
3382
3302
|
const s = statSync(candidate);
|
|
3383
3303
|
if (s.isDirectory()) return candidate;
|
|
@@ -3396,17 +3316,17 @@ function projectDir(nitDir) {
|
|
|
3396
3316
|
return resolve2(nitDir, "..");
|
|
3397
3317
|
}
|
|
3398
3318
|
async function readWorkingCard(nitDir) {
|
|
3399
|
-
const cardPath =
|
|
3319
|
+
const cardPath = join6(projectDir(nitDir), CARD_FILE);
|
|
3400
3320
|
try {
|
|
3401
|
-
const raw = await
|
|
3321
|
+
const raw = await fs6.readFile(cardPath, "utf-8");
|
|
3402
3322
|
return JSON.parse(raw);
|
|
3403
3323
|
} catch {
|
|
3404
3324
|
throw new Error(`Cannot read ${CARD_FILE}. Does it exist?`);
|
|
3405
3325
|
}
|
|
3406
3326
|
}
|
|
3407
3327
|
async function writeWorkingCard(nitDir, card) {
|
|
3408
|
-
const cardPath =
|
|
3409
|
-
await
|
|
3328
|
+
const cardPath = join6(projectDir(nitDir), CARD_FILE);
|
|
3329
|
+
await fs6.writeFile(cardPath, JSON.stringify(card, null, 2) + "\n", "utf-8");
|
|
3410
3330
|
}
|
|
3411
3331
|
async function getCardAtCommit(nitDir, commitHash) {
|
|
3412
3332
|
const commitRaw = await readObject(nitDir, commitHash);
|
|
@@ -3424,27 +3344,27 @@ async function getAuthorName(nitDir) {
|
|
|
3424
3344
|
}
|
|
3425
3345
|
async function init(options) {
|
|
3426
3346
|
const projDir = resolve2(options?.projectDir || process.cwd());
|
|
3427
|
-
const nitDir =
|
|
3347
|
+
const nitDir = join6(projDir, NIT_DIR);
|
|
3428
3348
|
try {
|
|
3429
|
-
await
|
|
3349
|
+
await fs6.access(nitDir);
|
|
3430
3350
|
throw new Error("Already initialized. .nit/ directory exists.");
|
|
3431
3351
|
} catch (err) {
|
|
3432
3352
|
if (err instanceof Error && err.message.startsWith("Already")) throw err;
|
|
3433
3353
|
}
|
|
3434
|
-
await
|
|
3435
|
-
await
|
|
3436
|
-
await
|
|
3437
|
-
await
|
|
3438
|
-
await
|
|
3354
|
+
await fs6.mkdir(join6(nitDir, "objects"), { recursive: true });
|
|
3355
|
+
await fs6.mkdir(join6(nitDir, "refs", "heads"), { recursive: true });
|
|
3356
|
+
await fs6.mkdir(join6(nitDir, "refs", "remote"), { recursive: true });
|
|
3357
|
+
await fs6.mkdir(join6(nitDir, "identity"), { recursive: true });
|
|
3358
|
+
await fs6.mkdir(join6(nitDir, "logs"), { recursive: true });
|
|
3439
3359
|
const { publicKey: pubBase64 } = await generateKeypair(nitDir);
|
|
3440
3360
|
const publicKeyField = formatPublicKeyField(pubBase64);
|
|
3441
3361
|
const agentId = deriveAgentId(publicKeyField);
|
|
3442
3362
|
await saveAgentId(nitDir, agentId);
|
|
3443
|
-
const cardPath =
|
|
3363
|
+
const cardPath = join6(projDir, CARD_FILE);
|
|
3444
3364
|
let card;
|
|
3445
3365
|
let skillsFound = [];
|
|
3446
3366
|
try {
|
|
3447
|
-
const raw = await
|
|
3367
|
+
const raw = await fs6.readFile(cardPath, "utf-8");
|
|
3448
3368
|
card = JSON.parse(raw);
|
|
3449
3369
|
card.publicKey = publicKeyField;
|
|
3450
3370
|
skillsFound = card.skills.map((s) => s.id);
|
|
@@ -3483,7 +3403,7 @@ async function init(options) {
|
|
|
3483
3403
|
const commitHash = await writeObject(nitDir, "commit", commitContent);
|
|
3484
3404
|
await setBranch(nitDir, "main", commitHash);
|
|
3485
3405
|
await setHead(nitDir, "main");
|
|
3486
|
-
await
|
|
3406
|
+
await fs6.writeFile(join6(nitDir, "logs", "HEAD"), "", "utf-8");
|
|
3487
3407
|
const skillsDir = await discoverSkillsDir(projDir);
|
|
3488
3408
|
await writeConfig(nitDir, {
|
|
3489
3409
|
remotes: { origin: { url: DEFAULT_API_BASE } },
|
|
@@ -3561,7 +3481,7 @@ async function status(options) {
|
|
|
3561
3481
|
branches: branchStatus
|
|
3562
3482
|
};
|
|
3563
3483
|
}
|
|
3564
|
-
async function
|
|
3484
|
+
async function sign(message, options) {
|
|
3565
3485
|
const nitDir = findNitDir(options?.projectDir);
|
|
3566
3486
|
return signMessage(nitDir, message);
|
|
3567
3487
|
}
|
|
@@ -3789,16 +3709,146 @@ async function rpcInfo(options) {
|
|
|
3789
3709
|
const config = await readConfig(nitDir);
|
|
3790
3710
|
return config.rpc ?? {};
|
|
3791
3711
|
}
|
|
3712
|
+
async function reset(target, options) {
|
|
3713
|
+
const nitDir = findNitDir(options?.projectDir);
|
|
3714
|
+
let commitHash;
|
|
3715
|
+
if (!target) {
|
|
3716
|
+
commitHash = await resolveHead(nitDir);
|
|
3717
|
+
} else {
|
|
3718
|
+
const branchHash = await getBranch(nitDir, target);
|
|
3719
|
+
if (branchHash) {
|
|
3720
|
+
commitHash = branchHash;
|
|
3721
|
+
} else if (/^[0-9a-f]{64}$/.test(target)) {
|
|
3722
|
+
commitHash = target;
|
|
3723
|
+
} else {
|
|
3724
|
+
throw new Error(`Unknown target "${target}". Provide a branch name or commit hash.`);
|
|
3725
|
+
}
|
|
3726
|
+
}
|
|
3727
|
+
const card = await getCardAtCommit(nitDir, commitHash);
|
|
3728
|
+
await writeWorkingCard(nitDir, card);
|
|
3729
|
+
return { hash: commitHash };
|
|
3730
|
+
}
|
|
3731
|
+
async function show(target, options) {
|
|
3732
|
+
const nitDir = findNitDir(options?.projectDir);
|
|
3733
|
+
let commitHash;
|
|
3734
|
+
if (!target) {
|
|
3735
|
+
commitHash = await resolveHead(nitDir);
|
|
3736
|
+
} else {
|
|
3737
|
+
const branchHash = await getBranch(nitDir, target);
|
|
3738
|
+
if (branchHash) {
|
|
3739
|
+
commitHash = branchHash;
|
|
3740
|
+
} else if (/^[0-9a-f]{64}$/.test(target)) {
|
|
3741
|
+
commitHash = target;
|
|
3742
|
+
} else {
|
|
3743
|
+
throw new Error(`Unknown target "${target}". Provide a branch name or commit hash.`);
|
|
3744
|
+
}
|
|
3745
|
+
}
|
|
3746
|
+
const commitRaw = await readObject(nitDir, commitHash);
|
|
3747
|
+
const c = parseCommit(commitHash, commitRaw);
|
|
3748
|
+
const cardJson = await getCardAtCommit(nitDir, commitHash);
|
|
3749
|
+
return {
|
|
3750
|
+
hash: c.hash,
|
|
3751
|
+
card: c.card,
|
|
3752
|
+
parent: c.parent,
|
|
3753
|
+
author: c.author,
|
|
3754
|
+
timestamp: c.timestamp,
|
|
3755
|
+
message: c.message,
|
|
3756
|
+
cardJson
|
|
3757
|
+
};
|
|
3758
|
+
}
|
|
3759
|
+
async function pull(options) {
|
|
3760
|
+
const nitDir = findNitDir(options?.projectDir);
|
|
3761
|
+
const remoteName = options?.remoteName || "origin";
|
|
3762
|
+
const apiBase = await getRemoteUrl(nitDir, remoteName) || DEFAULT_API_BASE;
|
|
3763
|
+
const currentBranch = await getCurrentBranch(nitDir);
|
|
3764
|
+
const agentId = await loadAgentId(nitDir);
|
|
3765
|
+
const branches = options?.all ? await listBranches(nitDir) : [{ name: currentBranch, commitHash: await resolveHead(nitDir) }];
|
|
3766
|
+
const results = [];
|
|
3767
|
+
for (const b of branches) {
|
|
3768
|
+
try {
|
|
3769
|
+
const { fetchBranchCard: fetchBranchCard2 } = await import("./remote-WZ625MBZ.js");
|
|
3770
|
+
const cardUrl = `${apiBase}/agent-card/${agentId}`;
|
|
3771
|
+
const remoteCard = await fetchBranchCard2(cardUrl, b.name, nitDir);
|
|
3772
|
+
const cardJson = JSON.stringify(remoteCard, null, 2);
|
|
3773
|
+
const cardHash = await writeObject(nitDir, "card", cardJson);
|
|
3774
|
+
const localHash = await getBranch(nitDir, b.name);
|
|
3775
|
+
if (localHash) {
|
|
3776
|
+
const localRaw = await readObject(nitDir, localHash);
|
|
3777
|
+
const localCommit = parseCommit(localHash, localRaw);
|
|
3778
|
+
if (localCommit.card === cardHash) {
|
|
3779
|
+
results.push({ branch: b.name, commitHash: localHash, updated: false });
|
|
3780
|
+
continue;
|
|
3781
|
+
}
|
|
3782
|
+
}
|
|
3783
|
+
const author = remoteCard.name || b.name;
|
|
3784
|
+
const commitContent = serializeCommit({
|
|
3785
|
+
card: cardHash,
|
|
3786
|
+
parent: localHash,
|
|
3787
|
+
author,
|
|
3788
|
+
timestamp: Math.floor(Date.now() / 1e3),
|
|
3789
|
+
message: `Pull from ${remoteName}`
|
|
3790
|
+
});
|
|
3791
|
+
const commitHash = await writeObject(nitDir, "commit", commitContent);
|
|
3792
|
+
await setBranch(nitDir, b.name, commitHash);
|
|
3793
|
+
await setRemoteRef(nitDir, remoteName, b.name, commitHash);
|
|
3794
|
+
if (b.name === currentBranch) {
|
|
3795
|
+
await writeWorkingCard(nitDir, remoteCard);
|
|
3796
|
+
}
|
|
3797
|
+
results.push({ branch: b.name, commitHash, updated: true });
|
|
3798
|
+
} catch (err) {
|
|
3799
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
3800
|
+
results.push({ branch: b.name, commitHash: "", updated: false });
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3803
|
+
return results;
|
|
3804
|
+
}
|
|
3805
|
+
async function authSet(domain, provider, account, options) {
|
|
3806
|
+
const nitDir = findNitDir(options?.projectDir);
|
|
3807
|
+
const projDir = projectDir(nitDir);
|
|
3808
|
+
let switchedBranch;
|
|
3809
|
+
let createdBranch = false;
|
|
3810
|
+
const currentBranch = await getCurrentBranch(nitDir);
|
|
3811
|
+
if (currentBranch !== domain) {
|
|
3812
|
+
const isNew = !await getBranch(nitDir, domain);
|
|
3813
|
+
if (isNew) {
|
|
3814
|
+
const headHash = await resolveHead(nitDir);
|
|
3815
|
+
await setBranch(nitDir, domain, headHash);
|
|
3816
|
+
createdBranch = true;
|
|
3817
|
+
}
|
|
3818
|
+
await checkout(domain, options);
|
|
3819
|
+
switchedBranch = domain;
|
|
3820
|
+
}
|
|
3821
|
+
const skillsDir = await getSkillsDir(nitDir) ?? await discoverSkillsDir(projDir);
|
|
3822
|
+
const auth = { provider, account };
|
|
3823
|
+
const skillId = await updateSkillAuth(skillsDir, domain, auth);
|
|
3824
|
+
const card = await readWorkingCard(nitDir);
|
|
3825
|
+
if (!card.skills.some((s) => s.id === skillId)) {
|
|
3826
|
+
card.skills.push({ id: skillId });
|
|
3827
|
+
await writeWorkingCard(nitDir, card);
|
|
3828
|
+
}
|
|
3829
|
+
return { branch: domain, skillId, provider, account, switchedBranch, createdBranch };
|
|
3830
|
+
}
|
|
3831
|
+
async function authShow(domain, options) {
|
|
3832
|
+
const nitDir = findNitDir(options?.projectDir);
|
|
3833
|
+
const projDir = projectDir(nitDir);
|
|
3834
|
+
const skillsDir = await getSkillsDir(nitDir) ?? await discoverSkillsDir(projDir);
|
|
3835
|
+
const results = [];
|
|
3836
|
+
if (domain) {
|
|
3837
|
+
const auth = await readSkillAuth(skillsDir, domain);
|
|
3838
|
+
results.push({ branch: domain, auth });
|
|
3839
|
+
} else {
|
|
3840
|
+
const branches = await listBranches(nitDir);
|
|
3841
|
+
for (const b of branches) {
|
|
3842
|
+
const auth = await readSkillAuth(skillsDir, b.name);
|
|
3843
|
+
if (auth) {
|
|
3844
|
+
results.push({ branch: b.name, auth });
|
|
3845
|
+
}
|
|
3846
|
+
}
|
|
3847
|
+
}
|
|
3848
|
+
return results;
|
|
3849
|
+
}
|
|
3792
3850
|
|
|
3793
3851
|
export {
|
|
3794
|
-
loadRawKeyPair,
|
|
3795
|
-
formatPublicKeyField,
|
|
3796
|
-
parsePublicKeyField,
|
|
3797
|
-
signChallenge,
|
|
3798
|
-
signMessage,
|
|
3799
|
-
NIT_NAMESPACE,
|
|
3800
|
-
deriveAgentId,
|
|
3801
|
-
loadAgentId,
|
|
3802
3852
|
base58Encode,
|
|
3803
3853
|
getSolanaAddress,
|
|
3804
3854
|
getEvmAddress,
|
|
@@ -3808,11 +3858,10 @@ export {
|
|
|
3808
3858
|
signSolanaBytes,
|
|
3809
3859
|
diffCards,
|
|
3810
3860
|
formatDiff,
|
|
3811
|
-
fetchBranchCard,
|
|
3812
3861
|
findNitDir,
|
|
3813
3862
|
init,
|
|
3814
3863
|
status,
|
|
3815
|
-
|
|
3864
|
+
sign,
|
|
3816
3865
|
loginPayload,
|
|
3817
3866
|
commit,
|
|
3818
3867
|
log,
|
|
@@ -3826,7 +3875,12 @@ export {
|
|
|
3826
3875
|
signTx2 as signTx,
|
|
3827
3876
|
broadcast2 as broadcast,
|
|
3828
3877
|
rpcSetUrl,
|
|
3829
|
-
rpcInfo
|
|
3878
|
+
rpcInfo,
|
|
3879
|
+
reset,
|
|
3880
|
+
show,
|
|
3881
|
+
pull,
|
|
3882
|
+
authSet,
|
|
3883
|
+
authShow
|
|
3830
3884
|
};
|
|
3831
3885
|
/*! Bundled license information:
|
|
3832
3886
|
|