agentic-drive 0.4.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 +19 -0
- package/README.md +88 -15
- package/dist/{chunk-L7GASKBQ.js → chunk-BXFK3QXK.js} +1 -1
- package/dist/{chunk-DRACF66Y.js → chunk-ES3NZ7SX.js} +1 -1
- package/dist/chunk-S4AGCKXW.js +241 -0
- package/dist/{chunk-ATJDMCRV.js → chunk-WJZNXLTR.js} +202 -200
- package/dist/cli.js +2 -2
- package/dist/client.d.ts +5 -2
- 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 +5 -3
- 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-e_cefh0u.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,65 +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 { 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
|
-
return path === void 0 ? rest : { path, ...rest };
|
|
1343
|
-
}
|
|
1344
|
-
|
|
1345
1156
|
// src/upload.ts
|
|
1346
1157
|
var DEFAULT_MAX_BYTES = 25 * 1024 * 1024;
|
|
1347
1158
|
var SIGNATURES = [
|
|
@@ -1402,6 +1213,197 @@ async function upload(drive, ctx, path, source, opts = {}) {
|
|
|
1402
1213
|
return drive.putFile(ctx, path, data, { mime, parents: opts.parents, onConflict: opts.onConflict });
|
|
1403
1214
|
}
|
|
1404
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
|
+
|
|
1405
1407
|
export {
|
|
1406
1408
|
ROOT_ID,
|
|
1407
1409
|
ACTOR_KINDS,
|
|
@@ -1413,11 +1415,14 @@ export {
|
|
|
1413
1415
|
subjectKindOf,
|
|
1414
1416
|
parseSubject,
|
|
1415
1417
|
createDrive,
|
|
1418
|
+
createFileStore,
|
|
1419
|
+
createFileBlobs,
|
|
1420
|
+
DEFAULT_MAX_BYTES,
|
|
1421
|
+
sniffMime,
|
|
1422
|
+
upload,
|
|
1416
1423
|
writeZip,
|
|
1417
1424
|
readZip,
|
|
1418
1425
|
buildExport,
|
|
1419
|
-
createFileStore,
|
|
1420
|
-
createFileBlobs,
|
|
1421
1426
|
authenticate,
|
|
1422
1427
|
openLocal,
|
|
1423
1428
|
AuthError,
|
|
@@ -1427,8 +1432,5 @@ export {
|
|
|
1427
1432
|
revokePrincipal,
|
|
1428
1433
|
issueKey,
|
|
1429
1434
|
revokeKey,
|
|
1430
|
-
publicNode
|
|
1431
|
-
DEFAULT_MAX_BYTES,
|
|
1432
|
-
sniffMime,
|
|
1433
|
-
upload
|
|
1435
|
+
publicNode
|
|
1434
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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as ErrorCode, N as Node, S as SearchQuery } from './drive-
|
|
1
|
+
import { E as ErrorCode, N as Node, S as SearchQuery } from './drive-BtRyexUP.js';
|
|
2
2
|
import 'agentic-identity';
|
|
3
3
|
|
|
4
4
|
type Role = "viewer" | "commenter" | "editor" | "owner";
|
|
@@ -9,7 +9,10 @@ type Subject = {
|
|
|
9
9
|
id: string;
|
|
10
10
|
};
|
|
11
11
|
/** An item as the API prints it: no storage keys. */
|
|
12
|
-
|
|
12
|
+
/** `machineMade` is true when the creator is not a human principal. */
|
|
13
|
+
type Item = Omit<Node, "nameKey" | "blobKey" | "purging"> & {
|
|
14
|
+
machineMade: boolean;
|
|
15
|
+
};
|
|
13
16
|
/** A search hit, or a home item: an item with its path. */
|
|
14
17
|
type PathItem = Item & {
|
|
15
18
|
path: string;
|