agentic-drive 0.5.0 → 0.6.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/CHANGELOG.md +7 -0
- package/README.md +88 -15
- package/dist/{chunk-B7E2Q3RB.js → chunk-BXFK3QXK.js} +1 -1
- package/dist/{chunk-WQHJNHAR.js → chunk-ES3NZ7SX.js} +1 -1
- package/dist/chunk-S4AGCKXW.js +241 -0
- package/dist/{chunk-T6C5Y2WA.js → chunk-WJZNXLTR.js} +202 -201
- package/dist/cli.js +2 -2
- package/dist/client.d.ts +1 -1
- package/dist/client.js +4 -236
- package/dist/{drive-Cn3mpuDW.d.ts → drive-BtRyexUP.d.ts} +1 -1
- package/dist/embed.css +154 -0
- package/dist/embed.d.ts +21 -0
- package/dist/embed.js +412 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +2 -2
- package/dist/worker.d.ts +23 -4
- package/dist/worker.js +48 -23
- package/llms.txt +5 -0
- package/package.json +23 -3
- package/ui-dist/assets/{index-xUEd8lQS.css → index-B9nizMSQ.css} +1 -1
- package/ui-dist/assets/index-DQzn7NQP.js +49 -0
- package/ui-dist/index.html +2 -2
- package/ui-dist/assets/index-BiU4TGuq.js +0 -49
|
@@ -94,7 +94,8 @@ function parseSubject(input) {
|
|
|
94
94
|
var SHARE_ERROR = /^(invalid|give an|expiresAt|expiresInMs|resource exists|the last owner)/;
|
|
95
95
|
function createDrive(deps) {
|
|
96
96
|
const { store, blobs } = deps;
|
|
97
|
-
|
|
97
|
+
let last = 0;
|
|
98
|
+
const now = deps.now ?? (() => last = Math.max(Date.now(), last + 1));
|
|
98
99
|
const newId = deps.newId ?? (() => globalThis.crypto.randomUUID());
|
|
99
100
|
const maxDepth = deps.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
100
101
|
const onOrphan = deps.onOrphan ?? ((key, error) => console.error(`orphan blob ${key}: ${error instanceof Error ? error.name : "delete failed"}`));
|
|
@@ -314,9 +315,9 @@ function createDrive(deps) {
|
|
|
314
315
|
}
|
|
315
316
|
async function parentAndName(ops, w, ctx, path, parents) {
|
|
316
317
|
const { start, segs } = await startOf(ops, ctx, path);
|
|
317
|
-
const
|
|
318
|
-
if (!
|
|
319
|
-
return { parent: await folderAt(ops, w, ctx, start, segs, parents), name:
|
|
318
|
+
const last2 = segs.pop();
|
|
319
|
+
if (!last2) throw start.id === ROOT_ID ? new DriveError("IS_ROOT", "the root already exists") : new DriveError("INVALID_PATH", "name an item inside the folder");
|
|
320
|
+
return { parent: await folderAt(ops, w, ctx, start, segs, parents), name: last2.name };
|
|
320
321
|
}
|
|
321
322
|
async function relocate(ops, w, ctx, node, destLoc, opts) {
|
|
322
323
|
if (node.id === ROOT_ID) throw new DriveError("IS_ROOT", "cannot change the root");
|
|
@@ -991,137 +992,6 @@ function createDrive(deps) {
|
|
|
991
992
|
return Object.fromEntries(Object.entries(api).map(([name, call]) => [name, open.has(name) ? call : guarded(call)]));
|
|
992
993
|
}
|
|
993
994
|
|
|
994
|
-
// src/zip.ts
|
|
995
|
-
var CRC_TABLE = Array.from({ length: 256 }, (_, n) => {
|
|
996
|
-
let c = n;
|
|
997
|
-
for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
998
|
-
return c >>> 0;
|
|
999
|
-
});
|
|
1000
|
-
function crc32(data) {
|
|
1001
|
-
let crc = 4294967295;
|
|
1002
|
-
for (const byte of data) crc = CRC_TABLE[(crc ^ byte) & 255] ^ crc >>> 8;
|
|
1003
|
-
return (crc ^ 4294967295) >>> 0;
|
|
1004
|
-
}
|
|
1005
|
-
function safeEntryName(name) {
|
|
1006
|
-
if (name === "" || /[\\\u0000]/.test(name) || name.startsWith("/") || /^[a-zA-Z]:/.test(name)) return false;
|
|
1007
|
-
return name.split("/").every((part) => part !== "" && part !== "." && part !== "..");
|
|
1008
|
-
}
|
|
1009
|
-
function writeZip(entries, at) {
|
|
1010
|
-
for (const { name } of entries) if (!safeEntryName(name)) throw new Error(`zip: unsafe entry name ${JSON.stringify(name)}`);
|
|
1011
|
-
const d = new Date(at);
|
|
1012
|
-
const time = d.getUTCHours() << 11 | d.getUTCMinutes() << 5 | d.getUTCSeconds() >> 1;
|
|
1013
|
-
const date = Math.max(d.getUTCFullYear(), 1980) - 1980 << 9 | d.getUTCMonth() + 1 << 5 | d.getUTCDate();
|
|
1014
|
-
const parts = [];
|
|
1015
|
-
const central = [];
|
|
1016
|
-
let offset = 0;
|
|
1017
|
-
const u16 = (v, o, n) => v.setUint16(o, n, true);
|
|
1018
|
-
const u32 = (v, o, n) => v.setUint32(o, n, true);
|
|
1019
|
-
for (const entry of entries) {
|
|
1020
|
-
const name = new TextEncoder().encode(entry.name);
|
|
1021
|
-
const crc = crc32(entry.data);
|
|
1022
|
-
if (entry.data.byteLength >= 4294967295 || offset >= 4294967295 || entries.length >= 65535) throw new Error("zip: export is too large for a plain zip");
|
|
1023
|
-
const local = new DataView(new ArrayBuffer(30));
|
|
1024
|
-
u32(local, 0, 67324752);
|
|
1025
|
-
u16(local, 4, 20);
|
|
1026
|
-
u16(local, 6, 2048);
|
|
1027
|
-
u16(local, 8, 0);
|
|
1028
|
-
u16(local, 10, time);
|
|
1029
|
-
u16(local, 12, date);
|
|
1030
|
-
u32(local, 14, crc);
|
|
1031
|
-
u32(local, 18, entry.data.byteLength);
|
|
1032
|
-
u32(local, 22, entry.data.byteLength);
|
|
1033
|
-
u16(local, 26, name.length);
|
|
1034
|
-
u16(local, 28, 0);
|
|
1035
|
-
const head = new DataView(new ArrayBuffer(46));
|
|
1036
|
-
u32(head, 0, 33639248);
|
|
1037
|
-
u16(head, 4, 20);
|
|
1038
|
-
u16(head, 6, 20);
|
|
1039
|
-
u16(head, 8, 2048);
|
|
1040
|
-
u16(head, 10, 0);
|
|
1041
|
-
u16(head, 12, time);
|
|
1042
|
-
u16(head, 14, date);
|
|
1043
|
-
u32(head, 16, crc);
|
|
1044
|
-
u32(head, 20, entry.data.byteLength);
|
|
1045
|
-
u32(head, 24, entry.data.byteLength);
|
|
1046
|
-
u16(head, 28, name.length);
|
|
1047
|
-
u32(head, 42, offset);
|
|
1048
|
-
parts.push(new Uint8Array(local.buffer), name, entry.data);
|
|
1049
|
-
central.push(new Uint8Array(head.buffer), name);
|
|
1050
|
-
offset += 30 + name.length + entry.data.byteLength;
|
|
1051
|
-
}
|
|
1052
|
-
const size = central.reduce((n, p) => n + p.byteLength, 0);
|
|
1053
|
-
const end = new DataView(new ArrayBuffer(22));
|
|
1054
|
-
u32(end, 0, 101010256);
|
|
1055
|
-
u16(end, 8, entries.length);
|
|
1056
|
-
u16(end, 10, entries.length);
|
|
1057
|
-
u32(end, 12, size);
|
|
1058
|
-
u32(end, 16, offset);
|
|
1059
|
-
const all = [...parts, ...central, new Uint8Array(end.buffer)];
|
|
1060
|
-
const out = new Uint8Array(all.reduce((n, p) => n + p.byteLength, 0));
|
|
1061
|
-
let at2 = 0;
|
|
1062
|
-
for (const p of all) {
|
|
1063
|
-
out.set(p, at2);
|
|
1064
|
-
at2 += p.byteLength;
|
|
1065
|
-
}
|
|
1066
|
-
return out;
|
|
1067
|
-
}
|
|
1068
|
-
function readZip(bytes) {
|
|
1069
|
-
const v = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
1070
|
-
let end = bytes.byteLength - 22;
|
|
1071
|
-
while (end >= 0 && v.getUint32(end, true) !== 101010256) end--;
|
|
1072
|
-
if (end < 0) throw new Error("zip: no end signature");
|
|
1073
|
-
const count = v.getUint16(end + 10, true);
|
|
1074
|
-
const out = /* @__PURE__ */ new Map();
|
|
1075
|
-
for (let i = 0, at = v.getUint32(end + 16, true); i < count; i++) {
|
|
1076
|
-
if (v.getUint32(at, true) !== 33639248) throw new Error("zip: bad central signature");
|
|
1077
|
-
if (v.getUint16(at + 10, true) !== 0) throw new Error("zip: compressed entries are not supported");
|
|
1078
|
-
const crc = v.getUint32(at + 16, true);
|
|
1079
|
-
const size = v.getUint32(at + 24, true);
|
|
1080
|
-
const nameLen = v.getUint16(at + 28, true);
|
|
1081
|
-
const local = v.getUint32(at + 42, true);
|
|
1082
|
-
const name = new TextDecoder().decode(bytes.subarray(at + 46, at + 46 + nameLen));
|
|
1083
|
-
if (v.getUint32(local, true) !== 67324752) throw new Error("zip: bad local signature");
|
|
1084
|
-
const start = local + 30 + v.getUint16(local + 26, true) + v.getUint16(local + 28, true);
|
|
1085
|
-
const data = bytes.slice(start, start + size);
|
|
1086
|
-
if (crc32(data) !== crc) throw new Error(`zip: crc mismatch in ${name}`);
|
|
1087
|
-
out.set(name, data);
|
|
1088
|
-
at += 46 + nameLen + v.getUint16(at + 30, true) + v.getUint16(at + 32, true);
|
|
1089
|
-
}
|
|
1090
|
-
return out;
|
|
1091
|
-
}
|
|
1092
|
-
|
|
1093
|
-
// src/export.ts
|
|
1094
|
-
async function buildExport(drive, ctx, now = Date.now) {
|
|
1095
|
-
const entries = [];
|
|
1096
|
-
const items = (await drive.exportData(ctx)).map(({ node, path, data, missing }) => {
|
|
1097
|
-
const file = data ? `files/${node.id}` : null;
|
|
1098
|
-
if (data && file) entries.push({ name: file, data });
|
|
1099
|
-
return {
|
|
1100
|
-
id: node.id,
|
|
1101
|
-
owner: node.owner,
|
|
1102
|
-
path,
|
|
1103
|
-
parentId: node.parentId,
|
|
1104
|
-
kind: node.kind,
|
|
1105
|
-
name: node.name,
|
|
1106
|
-
size: node.size,
|
|
1107
|
-
mime: node.mime,
|
|
1108
|
-
hash: node.hash,
|
|
1109
|
-
ref: node.ref,
|
|
1110
|
-
createdAt: node.createdAt,
|
|
1111
|
-
updatedAt: node.updatedAt,
|
|
1112
|
-
createdBy: node.createdBy,
|
|
1113
|
-
updatedBy: node.updatedBy,
|
|
1114
|
-
trashed: node.trashed,
|
|
1115
|
-
trashedAt: node.trashedAt,
|
|
1116
|
-
file,
|
|
1117
|
-
...missing ? { missing: true } : {}
|
|
1118
|
-
};
|
|
1119
|
-
});
|
|
1120
|
-
const person = await drive.exportPerson(ctx);
|
|
1121
|
-
const manifest = { format: "agentic-drive-export", version: 2, exportedAt: now(), owner: ctx.owner, subject: person.subject, partial: person.partial, items, authored: person.authored, agents: person.agents, shares: person.shares, audit: person.audit };
|
|
1122
|
-
return writeZip([{ name: "manifest.json", data: new TextEncoder().encode(JSON.stringify(manifest, null, 2)) }, ...entries], now());
|
|
1123
|
-
}
|
|
1124
|
-
|
|
1125
995
|
// src/adapters/fs.ts
|
|
1126
996
|
import { createHash } from "crypto";
|
|
1127
997
|
import { appendFileSync, closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, truncateSync, writeFileSync, writeSync } from "fs";
|
|
@@ -1283,66 +1153,6 @@ function createFileBlobs(dir, options = {}) {
|
|
|
1283
1153
|
};
|
|
1284
1154
|
}
|
|
1285
1155
|
|
|
1286
|
-
// src/auth.ts
|
|
1287
|
-
import { createStoreAuth } from "agentic-identity";
|
|
1288
|
-
async function authenticate(request, store, now) {
|
|
1289
|
-
if (!/^Bearer [A-Za-z0-9_-]{1,512}$/.test(request.headers.get("authorization") ?? "")) return null;
|
|
1290
|
-
const principal = await createStoreAuth(store, now ? { now } : {}).authenticate(request);
|
|
1291
|
-
return principal ? { owner: principal.chain[0].id, actor: { id: principal.principalId, kind: principal.kind }, principal } : null;
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
|
-
// src/local.ts
|
|
1295
|
-
import { createHash as createHash2 } from "crypto";
|
|
1296
|
-
import { join as join2 } from "path";
|
|
1297
|
-
import { isMachineMade, isScope, issueCredential, revokeCredential } from "agentic-identity";
|
|
1298
|
-
function openLocal(dir) {
|
|
1299
|
-
const store = createFileStore(join2(dir, "db"));
|
|
1300
|
-
return { store, drive: createDrive({ store, blobs: createFileBlobs(join2(dir, "blobs")) }) };
|
|
1301
|
-
}
|
|
1302
|
-
var AuthError = class extends Error {
|
|
1303
|
-
code = "UNAUTHENTICATED";
|
|
1304
|
-
};
|
|
1305
|
-
var NO_TOKEN = "no principal: pass --token <key> or set AGENTIC_DRIVE_TOKEN to an API key";
|
|
1306
|
-
var BAD_TOKEN = "the key is not valid: it is unknown, revoked, or expired, or its principal is revoked";
|
|
1307
|
-
async function resolveToken(store, token) {
|
|
1308
|
-
if (!token) throw new AuthError(NO_TOKEN);
|
|
1309
|
-
if (!/^[A-Za-z0-9_-]{1,512}$/.test(token)) throw new AuthError(BAD_TOKEN);
|
|
1310
|
-
const ctx = await authenticate(new Request("http://local", { headers: { authorization: `Bearer ${token}` } }), store);
|
|
1311
|
-
if (!ctx) throw new AuthError(BAD_TOKEN);
|
|
1312
|
-
return ctx;
|
|
1313
|
-
}
|
|
1314
|
-
async function addPrincipal(store, id, opts) {
|
|
1315
|
-
if (!/^[A-Za-z0-9_.@-]{1,128}$/.test(id)) throw new Error(`invalid principal id "${id}"`);
|
|
1316
|
-
const scopes = opts.scopes?.length ? opts.scopes : [opts.parent ? "drive:write" : "drive:admin"];
|
|
1317
|
-
const bad = scopes.find((s) => !isScope(s));
|
|
1318
|
-
if (bad !== void 0) throw new Error(`invalid scope "${bad}"`);
|
|
1319
|
-
if (await store.get("principals", id)) throw new Error(`principal "${id}" exists`);
|
|
1320
|
-
if (opts.parent && !await store.get("principals", opts.parent)) throw new Error(`parent "${opts.parent}" does not exist`);
|
|
1321
|
-
const parent = opts.parent ? await store.get("principals", opts.parent) : null;
|
|
1322
|
-
if (parent && parent.kind !== "human") throw new Error(`parent "${opts.parent}" is not a person`);
|
|
1323
|
-
const doc = opts.parent ? { id, kind: "agent_of_human", parentId: opts.parent, scopes } : { id, kind: "human", scopes };
|
|
1324
|
-
await store.put("principals", id, doc);
|
|
1325
|
-
return doc;
|
|
1326
|
-
}
|
|
1327
|
-
async function revokePrincipal(store, id) {
|
|
1328
|
-
const doc = await store.get("principals", id);
|
|
1329
|
-
if (!doc) throw new DriveError("NOT_FOUND", `principal "${id}" does not exist`);
|
|
1330
|
-
await store.put("principals", id, { ...doc, revokedAt: Date.now() });
|
|
1331
|
-
}
|
|
1332
|
-
async function issueKey(store, principalId, label) {
|
|
1333
|
-
if (!await store.get("principals", principalId)) throw new Error(`principal "${principalId}" does not exist`);
|
|
1334
|
-
return issueCredential(store, { principalId, kind: "api_key", ...label ? { label } : {} });
|
|
1335
|
-
}
|
|
1336
|
-
async function revokeKey(store, token) {
|
|
1337
|
-
if (!await store.get("credentials", createHash2("sha256").update(token).digest("hex"))) throw new DriveError("NOT_FOUND", "no such key");
|
|
1338
|
-
await revokeCredential(store, token, Date.now());
|
|
1339
|
-
}
|
|
1340
|
-
function publicNode(node, path) {
|
|
1341
|
-
const { nameKey: _nameKey, blobKey: _blobKey, purging: _purging, ...rest } = node;
|
|
1342
|
-
const shown = { ...rest, machineMade: isMachineMade(node.createdBy.kind) };
|
|
1343
|
-
return path === void 0 ? shown : { path, ...shown };
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
1156
|
// src/upload.ts
|
|
1347
1157
|
var DEFAULT_MAX_BYTES = 25 * 1024 * 1024;
|
|
1348
1158
|
var SIGNATURES = [
|
|
@@ -1403,6 +1213,197 @@ async function upload(drive, ctx, path, source, opts = {}) {
|
|
|
1403
1213
|
return drive.putFile(ctx, path, data, { mime, parents: opts.parents, onConflict: opts.onConflict });
|
|
1404
1214
|
}
|
|
1405
1215
|
|
|
1216
|
+
// src/zip.ts
|
|
1217
|
+
var CRC_TABLE = Array.from({ length: 256 }, (_, n) => {
|
|
1218
|
+
let c = n;
|
|
1219
|
+
for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
1220
|
+
return c >>> 0;
|
|
1221
|
+
});
|
|
1222
|
+
function crc32(data) {
|
|
1223
|
+
let crc = 4294967295;
|
|
1224
|
+
for (const byte of data) crc = CRC_TABLE[(crc ^ byte) & 255] ^ crc >>> 8;
|
|
1225
|
+
return (crc ^ 4294967295) >>> 0;
|
|
1226
|
+
}
|
|
1227
|
+
function safeEntryName(name) {
|
|
1228
|
+
if (name === "" || /[\\\u0000]/.test(name) || name.startsWith("/") || /^[a-zA-Z]:/.test(name)) return false;
|
|
1229
|
+
return name.split("/").every((part) => part !== "" && part !== "." && part !== "..");
|
|
1230
|
+
}
|
|
1231
|
+
function writeZip(entries, at) {
|
|
1232
|
+
for (const { name } of entries) if (!safeEntryName(name)) throw new Error(`zip: unsafe entry name ${JSON.stringify(name)}`);
|
|
1233
|
+
const d = new Date(at);
|
|
1234
|
+
const time = d.getUTCHours() << 11 | d.getUTCMinutes() << 5 | d.getUTCSeconds() >> 1;
|
|
1235
|
+
const date = Math.max(d.getUTCFullYear(), 1980) - 1980 << 9 | d.getUTCMonth() + 1 << 5 | d.getUTCDate();
|
|
1236
|
+
const parts = [];
|
|
1237
|
+
const central = [];
|
|
1238
|
+
let offset = 0;
|
|
1239
|
+
const u16 = (v, o, n) => v.setUint16(o, n, true);
|
|
1240
|
+
const u32 = (v, o, n) => v.setUint32(o, n, true);
|
|
1241
|
+
for (const entry of entries) {
|
|
1242
|
+
const name = new TextEncoder().encode(entry.name);
|
|
1243
|
+
const crc = crc32(entry.data);
|
|
1244
|
+
if (entry.data.byteLength >= 4294967295 || offset >= 4294967295 || entries.length >= 65535) throw new Error("zip: export is too large for a plain zip");
|
|
1245
|
+
const local = new DataView(new ArrayBuffer(30));
|
|
1246
|
+
u32(local, 0, 67324752);
|
|
1247
|
+
u16(local, 4, 20);
|
|
1248
|
+
u16(local, 6, 2048);
|
|
1249
|
+
u16(local, 8, 0);
|
|
1250
|
+
u16(local, 10, time);
|
|
1251
|
+
u16(local, 12, date);
|
|
1252
|
+
u32(local, 14, crc);
|
|
1253
|
+
u32(local, 18, entry.data.byteLength);
|
|
1254
|
+
u32(local, 22, entry.data.byteLength);
|
|
1255
|
+
u16(local, 26, name.length);
|
|
1256
|
+
u16(local, 28, 0);
|
|
1257
|
+
const head = new DataView(new ArrayBuffer(46));
|
|
1258
|
+
u32(head, 0, 33639248);
|
|
1259
|
+
u16(head, 4, 20);
|
|
1260
|
+
u16(head, 6, 20);
|
|
1261
|
+
u16(head, 8, 2048);
|
|
1262
|
+
u16(head, 10, 0);
|
|
1263
|
+
u16(head, 12, time);
|
|
1264
|
+
u16(head, 14, date);
|
|
1265
|
+
u32(head, 16, crc);
|
|
1266
|
+
u32(head, 20, entry.data.byteLength);
|
|
1267
|
+
u32(head, 24, entry.data.byteLength);
|
|
1268
|
+
u16(head, 28, name.length);
|
|
1269
|
+
u32(head, 42, offset);
|
|
1270
|
+
parts.push(new Uint8Array(local.buffer), name, entry.data);
|
|
1271
|
+
central.push(new Uint8Array(head.buffer), name);
|
|
1272
|
+
offset += 30 + name.length + entry.data.byteLength;
|
|
1273
|
+
}
|
|
1274
|
+
const size = central.reduce((n, p) => n + p.byteLength, 0);
|
|
1275
|
+
const end = new DataView(new ArrayBuffer(22));
|
|
1276
|
+
u32(end, 0, 101010256);
|
|
1277
|
+
u16(end, 8, entries.length);
|
|
1278
|
+
u16(end, 10, entries.length);
|
|
1279
|
+
u32(end, 12, size);
|
|
1280
|
+
u32(end, 16, offset);
|
|
1281
|
+
const all = [...parts, ...central, new Uint8Array(end.buffer)];
|
|
1282
|
+
const out = new Uint8Array(all.reduce((n, p) => n + p.byteLength, 0));
|
|
1283
|
+
let at2 = 0;
|
|
1284
|
+
for (const p of all) {
|
|
1285
|
+
out.set(p, at2);
|
|
1286
|
+
at2 += p.byteLength;
|
|
1287
|
+
}
|
|
1288
|
+
return out;
|
|
1289
|
+
}
|
|
1290
|
+
function readZip(bytes) {
|
|
1291
|
+
const v = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
1292
|
+
let end = bytes.byteLength - 22;
|
|
1293
|
+
while (end >= 0 && v.getUint32(end, true) !== 101010256) end--;
|
|
1294
|
+
if (end < 0) throw new Error("zip: no end signature");
|
|
1295
|
+
const count = v.getUint16(end + 10, true);
|
|
1296
|
+
const out = /* @__PURE__ */ new Map();
|
|
1297
|
+
for (let i = 0, at = v.getUint32(end + 16, true); i < count; i++) {
|
|
1298
|
+
if (v.getUint32(at, true) !== 33639248) throw new Error("zip: bad central signature");
|
|
1299
|
+
if (v.getUint16(at + 10, true) !== 0) throw new Error("zip: compressed entries are not supported");
|
|
1300
|
+
const crc = v.getUint32(at + 16, true);
|
|
1301
|
+
const size = v.getUint32(at + 24, true);
|
|
1302
|
+
const nameLen = v.getUint16(at + 28, true);
|
|
1303
|
+
const local = v.getUint32(at + 42, true);
|
|
1304
|
+
const name = new TextDecoder().decode(bytes.subarray(at + 46, at + 46 + nameLen));
|
|
1305
|
+
if (v.getUint32(local, true) !== 67324752) throw new Error("zip: bad local signature");
|
|
1306
|
+
const start = local + 30 + v.getUint16(local + 26, true) + v.getUint16(local + 28, true);
|
|
1307
|
+
const data = bytes.slice(start, start + size);
|
|
1308
|
+
if (crc32(data) !== crc) throw new Error(`zip: crc mismatch in ${name}`);
|
|
1309
|
+
out.set(name, data);
|
|
1310
|
+
at += 46 + nameLen + v.getUint16(at + 30, true) + v.getUint16(at + 32, true);
|
|
1311
|
+
}
|
|
1312
|
+
return out;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
// src/export.ts
|
|
1316
|
+
async function buildExport(drive, ctx, now = Date.now) {
|
|
1317
|
+
const entries = [];
|
|
1318
|
+
const items = (await drive.exportData(ctx)).map(({ node, path, data, missing }) => {
|
|
1319
|
+
const file = data ? `files/${node.id}` : null;
|
|
1320
|
+
if (data && file) entries.push({ name: file, data });
|
|
1321
|
+
return {
|
|
1322
|
+
id: node.id,
|
|
1323
|
+
owner: node.owner,
|
|
1324
|
+
path,
|
|
1325
|
+
parentId: node.parentId,
|
|
1326
|
+
kind: node.kind,
|
|
1327
|
+
name: node.name,
|
|
1328
|
+
size: node.size,
|
|
1329
|
+
mime: node.mime,
|
|
1330
|
+
hash: node.hash,
|
|
1331
|
+
ref: node.ref,
|
|
1332
|
+
createdAt: node.createdAt,
|
|
1333
|
+
updatedAt: node.updatedAt,
|
|
1334
|
+
createdBy: node.createdBy,
|
|
1335
|
+
updatedBy: node.updatedBy,
|
|
1336
|
+
trashed: node.trashed,
|
|
1337
|
+
trashedAt: node.trashedAt,
|
|
1338
|
+
file,
|
|
1339
|
+
...missing ? { missing: true } : {}
|
|
1340
|
+
};
|
|
1341
|
+
});
|
|
1342
|
+
const person = await drive.exportPerson(ctx);
|
|
1343
|
+
const manifest = { format: "agentic-drive-export", version: 2, exportedAt: now(), owner: ctx.owner, subject: person.subject, partial: person.partial, items, authored: person.authored, agents: person.agents, shares: person.shares, audit: person.audit };
|
|
1344
|
+
return writeZip([{ name: "manifest.json", data: new TextEncoder().encode(JSON.stringify(manifest, null, 2)) }, ...entries], now());
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
// src/auth.ts
|
|
1348
|
+
import { createStoreAuth } from "agentic-identity";
|
|
1349
|
+
async function authenticate(request, store, now) {
|
|
1350
|
+
if (!/^Bearer [A-Za-z0-9_-]{1,512}$/.test(request.headers.get("authorization") ?? "")) return null;
|
|
1351
|
+
const principal = await createStoreAuth(store, now ? { now } : {}).authenticate(request);
|
|
1352
|
+
return principal ? { owner: principal.chain[0].id, actor: { id: principal.principalId, kind: principal.kind }, principal } : null;
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
// src/local.ts
|
|
1356
|
+
import { createHash as createHash2 } from "crypto";
|
|
1357
|
+
import { join as join2 } from "path";
|
|
1358
|
+
import { isMachineMade, isScope, issueCredential, revokeCredential } from "agentic-identity";
|
|
1359
|
+
function openLocal(dir) {
|
|
1360
|
+
const store = createFileStore(join2(dir, "db"));
|
|
1361
|
+
return { store, drive: createDrive({ store, blobs: createFileBlobs(join2(dir, "blobs")) }) };
|
|
1362
|
+
}
|
|
1363
|
+
var AuthError = class extends Error {
|
|
1364
|
+
code = "UNAUTHENTICATED";
|
|
1365
|
+
};
|
|
1366
|
+
var NO_TOKEN = "no principal: pass --token <key> or set AGENTIC_DRIVE_TOKEN to an API key";
|
|
1367
|
+
var BAD_TOKEN = "the key is not valid: it is unknown, revoked, or expired, or its principal is revoked";
|
|
1368
|
+
async function resolveToken(store, token) {
|
|
1369
|
+
if (!token) throw new AuthError(NO_TOKEN);
|
|
1370
|
+
if (!/^[A-Za-z0-9_-]{1,512}$/.test(token)) throw new AuthError(BAD_TOKEN);
|
|
1371
|
+
const ctx = await authenticate(new Request("http://local", { headers: { authorization: `Bearer ${token}` } }), store);
|
|
1372
|
+
if (!ctx) throw new AuthError(BAD_TOKEN);
|
|
1373
|
+
return ctx;
|
|
1374
|
+
}
|
|
1375
|
+
async function addPrincipal(store, id, opts) {
|
|
1376
|
+
if (!/^[A-Za-z0-9_.@-]{1,128}$/.test(id)) throw new Error(`invalid principal id "${id}"`);
|
|
1377
|
+
const scopes = opts.scopes?.length ? opts.scopes : [opts.parent ? "drive:write" : "drive:admin"];
|
|
1378
|
+
const bad = scopes.find((s) => !isScope(s));
|
|
1379
|
+
if (bad !== void 0) throw new Error(`invalid scope "${bad}"`);
|
|
1380
|
+
if (await store.get("principals", id)) throw new Error(`principal "${id}" exists`);
|
|
1381
|
+
if (opts.parent && !await store.get("principals", opts.parent)) throw new Error(`parent "${opts.parent}" does not exist`);
|
|
1382
|
+
const parent = opts.parent ? await store.get("principals", opts.parent) : null;
|
|
1383
|
+
if (parent && parent.kind !== "human") throw new Error(`parent "${opts.parent}" is not a person`);
|
|
1384
|
+
const doc = opts.parent ? { id, kind: "agent_of_human", parentId: opts.parent, scopes } : { id, kind: "human", scopes };
|
|
1385
|
+
await store.put("principals", id, doc);
|
|
1386
|
+
return doc;
|
|
1387
|
+
}
|
|
1388
|
+
async function revokePrincipal(store, id) {
|
|
1389
|
+
const doc = await store.get("principals", id);
|
|
1390
|
+
if (!doc) throw new DriveError("NOT_FOUND", `principal "${id}" does not exist`);
|
|
1391
|
+
await store.put("principals", id, { ...doc, revokedAt: Date.now() });
|
|
1392
|
+
}
|
|
1393
|
+
async function issueKey(store, principalId, label) {
|
|
1394
|
+
if (!await store.get("principals", principalId)) throw new Error(`principal "${principalId}" does not exist`);
|
|
1395
|
+
return issueCredential(store, { principalId, kind: "api_key", ...label ? { label } : {} });
|
|
1396
|
+
}
|
|
1397
|
+
async function revokeKey(store, token) {
|
|
1398
|
+
if (!await store.get("credentials", createHash2("sha256").update(token).digest("hex"))) throw new DriveError("NOT_FOUND", "no such key");
|
|
1399
|
+
await revokeCredential(store, token, Date.now());
|
|
1400
|
+
}
|
|
1401
|
+
function publicNode(node, path) {
|
|
1402
|
+
const { nameKey: _nameKey, blobKey: _blobKey, purging: _purging, ...rest } = node;
|
|
1403
|
+
const shown = { ...rest, machineMade: isMachineMade(node.createdBy.kind) };
|
|
1404
|
+
return path === void 0 ? shown : { path, ...shown };
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1406
1407
|
export {
|
|
1407
1408
|
ROOT_ID,
|
|
1408
1409
|
ACTOR_KINDS,
|
|
@@ -1414,11 +1415,14 @@ export {
|
|
|
1414
1415
|
subjectKindOf,
|
|
1415
1416
|
parseSubject,
|
|
1416
1417
|
createDrive,
|
|
1418
|
+
createFileStore,
|
|
1419
|
+
createFileBlobs,
|
|
1420
|
+
DEFAULT_MAX_BYTES,
|
|
1421
|
+
sniffMime,
|
|
1422
|
+
upload,
|
|
1417
1423
|
writeZip,
|
|
1418
1424
|
readZip,
|
|
1419
1425
|
buildExport,
|
|
1420
|
-
createFileStore,
|
|
1421
|
-
createFileBlobs,
|
|
1422
1426
|
authenticate,
|
|
1423
1427
|
openLocal,
|
|
1424
1428
|
AuthError,
|
|
@@ -1428,8 +1432,5 @@ export {
|
|
|
1428
1432
|
revokePrincipal,
|
|
1429
1433
|
issueKey,
|
|
1430
1434
|
revokeKey,
|
|
1431
|
-
publicNode
|
|
1432
|
-
DEFAULT_MAX_BYTES,
|
|
1433
|
-
sniffMime,
|
|
1434
|
-
upload
|
|
1435
|
+
publicNode
|
|
1435
1436
|
};
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
VERSION
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ES3NZ7SX.js";
|
|
5
5
|
import {
|
|
6
6
|
AuthError,
|
|
7
7
|
DriveError,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
revokeKey,
|
|
16
16
|
revokePrincipal,
|
|
17
17
|
upload
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-WJZNXLTR.js";
|
|
19
19
|
|
|
20
20
|
// src/cli.ts
|
|
21
21
|
import { createReadStream, realpathSync, writeFileSync } from "fs";
|
package/dist/client.d.ts
CHANGED