agentic-drive 0.6.1 → 0.8.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/dist/cli.js CHANGED
@@ -1,13 +1,18 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ importLegacyLocal
4
+ } from "./chunk-AB2RTTHJ.js";
2
5
  import {
3
6
  VERSION
4
- } from "./chunk-H6JK62SP.js";
7
+ } from "./chunk-6UQ6CDLJ.js";
5
8
  import {
6
9
  AuthError,
7
10
  DriveError,
8
11
  NO_TOKEN,
9
12
  addPrincipal,
10
13
  buildExport,
14
+ ensureSharing,
15
+ inviteIdentity,
11
16
  issueKey,
12
17
  openLocal,
13
18
  publicNode,
@@ -15,13 +20,14 @@ import {
15
20
  revokeKey,
16
21
  revokePrincipal,
17
22
  upload
18
- } from "./chunk-EAKQK7ST.js";
23
+ } from "./chunk-R2DUVOJT.js";
19
24
 
20
25
  // src/cli.ts
21
26
  import { createReadStream, realpathSync, writeFileSync } from "fs";
22
27
  import { basename, join, resolve } from "path";
23
28
  import { pathToFileURL } from "url";
24
29
  import { parseArgs } from "util";
30
+ import { ROLES, SUBJECT_KINDS } from "agentic-identity";
25
31
  var HELP = `agentic-drive ${VERSION}
26
32
  Store, sort, and share files and folders.
27
33
 
@@ -35,14 +41,23 @@ Commands:
35
41
  download <remote> [out] Save a file. Use "-" for stdout.
36
42
  mv <src> <folder> Move an item. Use --name to rename it.
37
43
  rm <path|id> Move an item to the trash.
38
- trash List the trash.
44
+ trash [--paths] List the trash. With --paths, each item shows the path it had.
39
45
  restore <id> Put a trashed item back.
40
46
  purge <id> Delete a trashed item for good.
41
47
  search Find items. Flags: --name --mime --kind --min-size --max-size --created-by-kind --limit
42
48
  export <out.zip> Write everything you own to a zip with a JSON manifest.
43
49
  home [--app <name>] List files and app documents, newest change first.
44
50
  register <ref> <name> Put an app document in the drive. Flag: --parent <folder>
51
+ find-ref <ref> List the live items that point at an app document, with paths.
52
+ claim-ref <ref> <path> <subject> Put a reference and give a role on it, or do neither. Flags: --role <r> --subject-kind <human|agent>
45
53
  forget <ref> Move the references to an app document to the trash.
54
+ shares <path|id> Show who can reach an item, and by which links and invites. Owner only.
55
+ share <path|id> <subject> Give a role to a person or agent. Flags: --role <r> --subject-kind <human|agent>
56
+ unshare <path|id> <subject> Take a role away. Flag: --subject-kind <human|agent>
57
+ invite <path|id> Invite by --email (a person) or --handle (an agent). Flags: --role <r> --expires-in-ms <n>. Sends no message.
58
+ accept-invite <id> Accept an invite that names your verified email or agent handle.
59
+ link-create <path|id> Make a share link. The token shows once. Flags: --role <r> --expires-in-ms <n> --signed-in-only
60
+ link-revoke <id> Stop a share link.
46
61
  delete-all --yes Erase you for good: your drive, and what you shared or held.
47
62
  principal add <id> Make a person, or an agent with --of <person>. Flag: --scope <s> (repeat). No key needed.
48
63
  principal revoke <id> Stop a principal, and every agent below it. No key needed.
@@ -57,12 +72,13 @@ Flags:
57
72
  The key names a principal, found through agentic-identity. The drive belongs to
58
73
  the person at the top of that principal's chain. An agent key marks items as
59
74
  made by a machine. If the key is missing or not valid, the command exits with 3.
75
+ --role <r> share: owner, editor, commenter, or viewer. invite and link-create: editor, commenter, or viewer.
60
76
  --on-conflict <m> fail, rename, or replace
61
77
  -p, --parents Create missing parent folders
62
78
 
63
79
  Exit codes: 0 done, 1 error, 2 bad usage, 3 no principal or an invalid key.
64
80
  `;
65
- var COMMANDS = ["ls", "stat", "mkdir", "upload", "download", "mv", "rm", "trash", "restore", "purge", "search", "export", "home", "register", "forget", "delete-all", "mcp", "principal", "key"];
81
+ var COMMANDS = ["ls", "stat", "mkdir", "upload", "download", "mv", "rm", "trash", "restore", "purge", "search", "export", "home", "register", "find-ref", "claim-ref", "forget", "shares", "share", "unshare", "invite", "accept-invite", "link-create", "link-revoke", "delete-all", "mcp", "principal", "key"];
66
82
  var UsageError = class extends Error {
67
83
  };
68
84
  var options = {
@@ -72,6 +88,7 @@ var options = {
72
88
  scope: { type: "string", multiple: true },
73
89
  label: { type: "string" },
74
90
  "on-conflict": { type: "string" },
91
+ paths: { type: "boolean" },
75
92
  parents: { type: "boolean", short: "p" },
76
93
  mime: { type: "string" },
77
94
  "max-bytes": { type: "string" },
@@ -81,18 +98,35 @@ var options = {
81
98
  "min-size": { type: "string" },
82
99
  "max-size": { type: "string" },
83
100
  "created-by-kind": { type: "string" },
101
+ role: { type: "string" },
102
+ "subject-kind": { type: "string" },
103
+ email: { type: "string" },
104
+ handle: { type: "string" },
105
+ "expires-in-ms": { type: "string" },
106
+ "signed-in-only": { type: "boolean" },
84
107
  limit: { type: "string" },
85
108
  app: { type: "string" },
86
109
  yes: { type: "boolean" },
87
110
  help: { type: "boolean", short: "h" },
88
111
  version: { type: "boolean", short: "V" }
89
112
  };
113
+ function lifetime(value, flag) {
114
+ if (value === void 0) return void 0;
115
+ const n = Number(value);
116
+ if (value.trim() === "" || !Number.isSafeInteger(n) || n <= 0) throw new UsageError(`--${flag} needs a whole number above 0`);
117
+ return n;
118
+ }
90
119
  function num(value, flag) {
91
120
  if (value === void 0) return void 0;
92
121
  const n = Number(value);
93
122
  if (!Number.isFinite(n) || n < 0) throw new UsageError(`--${flag} needs a number of 0 or more`);
94
123
  return n;
95
124
  }
125
+ var LINK_ROLES = ROLES.filter((r) => r !== "owner");
126
+ function pick(value, allowed, flag) {
127
+ if (value === void 0 || !allowed.includes(value)) throw new UsageError(`--${flag} needs ${allowed.join(", ")}`);
128
+ return value;
129
+ }
96
130
  async function runCli(argv, io) {
97
131
  try {
98
132
  const { values, positionals } = parseArgs({ args: argv, options, allowPositionals: true, strict: true });
@@ -108,7 +142,8 @@ async function runCli(argv, io) {
108
142
  const admin = command === "principal" || command === "key";
109
143
  const token = values.token ?? env.AGENTIC_DRIVE_TOKEN;
110
144
  if (!admin && !token) throw new AuthError(NO_TOKEN);
111
- const { drive, store } = openLocal(dir);
145
+ const { drive, store, blobs } = openLocal(dir, { beforeImport: true });
146
+ await importLegacyLocal(dir, store, blobs);
112
147
  if (admin || command === "key") {
113
148
  const [sub, target] = args;
114
149
  const out = (value) => io.out(JSON.stringify(value));
@@ -119,6 +154,7 @@ async function runCli(argv, io) {
119
154
  throw new UsageError("usage: agentic-drive principal add <id> [--of <person>] [--scope <s>] | principal revoke <id> | key issue <principal> | key revoke <key>");
120
155
  }
121
156
  const ctx = await resolveToken(store, token);
157
+ await ensureSharing(store);
122
158
  const onConflict = values["on-conflict"];
123
159
  if (onConflict && !["fail", "rename", "replace"].includes(onConflict)) throw new UsageError("--on-conflict needs fail, rename, or replace");
124
160
  const print = (value) => io.out(JSON.stringify(value));
@@ -166,7 +202,7 @@ async function runCli(argv, io) {
166
202
  print(publicNode(await drive.trash(ctx, args[0])));
167
203
  break;
168
204
  case "trash":
169
- print((await drive.listTrash(ctx)).map((n) => publicNode(n)));
205
+ print(values.paths ? (await drive.listTrashWithPaths(ctx)).map((r) => publicNode(r.node, r.path)) : (await drive.listTrash(ctx)).map((n) => publicNode(n)));
170
206
  break;
171
207
  case "restore":
172
208
  need(1, "restore <id>");
@@ -203,17 +239,73 @@ async function runCli(argv, io) {
203
239
  need(2, "register <ref> <name>");
204
240
  print(publicNode(await drive.registerDocument(ctx, { ref: args[0], name: args[1], folder: values.parent })));
205
241
  break;
242
+ case "find-ref":
243
+ need(1, "find-ref <ref>");
244
+ print((await drive.findByRef(ctx, args[0])).map((r) => publicNode(r.node, r.path)));
245
+ break;
246
+ case "claim-ref":
247
+ need(3, "claim-ref <ref> <path> <subject> --role <r> --subject-kind <human|agent>");
248
+ print(publicNode(await drive.claimRef(ctx, args[1], args[0], {
249
+ subject: { kind: pick(values["subject-kind"], SUBJECT_KINDS, "subject-kind"), id: args[2] },
250
+ role: pick(values.role, ROLES, "role")
251
+ }, { parents: values.parents, onConflict })));
252
+ break;
206
253
  case "forget":
207
254
  need(1, "forget <ref>");
208
255
  print(await drive.forgetDocument(ctx, args[0]));
209
256
  break;
257
+ case "shares":
258
+ need(1, "shares <path|id>");
259
+ print(await drive.shares(ctx, args[0]));
260
+ break;
261
+ case "share":
262
+ need(2, "share <path|id> <subject> --role <r> --subject-kind <human|agent>");
263
+ await drive.shareWith(ctx, args[0], { kind: pick(values["subject-kind"], SUBJECT_KINDS, "subject-kind"), id: args[1] }, pick(values.role, ROLES, "role"));
264
+ print({ ok: true });
265
+ break;
266
+ case "unshare":
267
+ need(2, "unshare <path|id> <subject> --subject-kind <human|agent>");
268
+ await drive.unshare(ctx, args[0], { kind: pick(values["subject-kind"], SUBJECT_KINDS, "subject-kind"), id: args[1] });
269
+ print({ ok: true });
270
+ break;
271
+ case "invite": {
272
+ need(1, "invite <path|id> --role <r> (--email <e> | --handle <h>)");
273
+ const expiresInMs = lifetime(values["expires-in-ms"], "expires-in-ms");
274
+ print(await drive.invite(ctx, args[0], {
275
+ role: pick(values.role, LINK_ROLES, "role"),
276
+ ...values.email === void 0 ? {} : { email: values.email },
277
+ ...values.handle === void 0 ? {} : { handle: values.handle },
278
+ ...expiresInMs === void 0 ? {} : { expiresInMs }
279
+ }));
280
+ break;
281
+ }
282
+ case "accept-invite":
283
+ need(1, "accept-invite <id>");
284
+ await drive.acceptInvite(ctx, args[0], await inviteIdentity(store, ctx.actor.id));
285
+ print({ ok: true });
286
+ break;
287
+ case "link-create": {
288
+ need(1, "link-create <path|id> --role <r>");
289
+ const expiresInMs = lifetime(values["expires-in-ms"], "expires-in-ms");
290
+ print(await drive.createLink(ctx, args[0], {
291
+ role: pick(values.role, LINK_ROLES, "role"),
292
+ signedInOnly: values["signed-in-only"] === true,
293
+ ...expiresInMs === void 0 ? {} : { expiresAt: Date.now() + expiresInMs }
294
+ }));
295
+ break;
296
+ }
297
+ case "link-revoke":
298
+ need(1, "link-revoke <id>");
299
+ await drive.revokeLink(ctx, args[0]);
300
+ print({ ok: true });
301
+ break;
210
302
  case "delete-all":
211
303
  if (!values.yes) throw new UsageError("delete-all erases you for good. Add --yes to confirm.");
212
304
  print(await drive.erasePerson(ctx));
213
305
  break;
214
306
  case "mcp": {
215
307
  const { startMcp } = await import("./mcp.js");
216
- await startMcp({ drive, ctx, exportDir: join(dir, "exports") });
308
+ await startMcp({ drive, ctx, exportDir: join(dir, "exports"), store });
217
309
  return 0;
218
310
  }
219
311
  default:
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { E as ErrorCode, N as Node, S as SearchQuery } from './drive-BtRyexUP.js';
1
+ import { E as ErrorCode, N as Node, S as SearchQuery } from './drive-Dxy0gL0_.js';
2
2
  import 'agentic-identity';
3
3
 
4
4
  type Role = "viewer" | "commenter" | "editor" | "owner";
@@ -100,6 +100,19 @@ declare function createClient(options: ClientOptions): {
100
100
  app: string | null;
101
101
  })[];
102
102
  }>;
103
+ /** The live references to `ref`, with their paths. */
104
+ findByRef: (ref: string, o?: CallOptions) => Promise<PathItem[]>;
105
+ /** Items in the trash, newest first, each with the path it had before. */
106
+ listTrashWithPaths: (o?: CallOptions) => Promise<PathItem[]>;
107
+ /** Puts a reference and gives the subject a role on it, or does neither. Needs sharing. */
108
+ claimRef: (input: {
109
+ path: string;
110
+ ref: string;
111
+ subject: Subject;
112
+ role: Role;
113
+ parents?: boolean;
114
+ onConflict?: OnConflict;
115
+ }, o?: CallOptions) => Promise<Item>;
103
116
  registerDocument: (input: {
104
117
  ref: string;
105
118
  name: string;
@@ -173,4 +186,4 @@ declare function createClient(options: ClientOptions): {
173
186
  };
174
187
  type DriveClient = ReturnType<typeof createClient>;
175
188
 
176
- export { type ApiErrorCode, type CallOptions, type ClientErrorCode, type ClientOptions, type Downloaded, DriveApiError, type DriveClient, type Item, type OnConflict, type PathItem, type Role, type Subject, type SubjectKind, type UploadBody, createClient };
189
+ export { type ApiErrorCode, type CallOptions, type ClientErrorCode, type ClientOptions, type Downloaded, DriveApiError, type DriveClient, ErrorCode, type Item, Node, type OnConflict, type PathItem, type Role, type Subject, type SubjectKind, type UploadBody, createClient };
package/dist/client.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DriveApiError,
3
3
  createClient
4
- } from "./chunk-S4AGCKXW.js";
4
+ } from "./chunk-LELTSSZF.js";
5
5
  export {
6
6
  DriveApiError,
7
7
  createClient
@@ -48,6 +48,8 @@ type Node = {
48
48
  purging: boolean;
49
49
  };
50
50
  type ErrorCode = "NOT_FOUND" | "NAME_TAKEN" | "BLOB_EXISTS" | "INVALID_NAME" | "INVALID_PATH" | "INVALID_REF" | "NOT_A_FOLDER" | "NOT_A_FILE" | "MOVE_INTO_SELF" | "TOO_DEEP" | "PARENT_GONE" | "TRASHED" | "NOT_TRASHED" | "IS_ROOT" | "FORBIDDEN" | "BLOB_MISSING" | "TOO_LARGE" | "INVALID_EXPIRY" | "BUSY" | "CROSS_DRIVE" | "INVALID_SHARE" | "TOO_MANY_ITEMS";
51
+ /** The HTTP status of each error code. A host that serves the drive reuses it. */
52
+ declare const ERROR_STATUS: Readonly<Record<ErrorCode, 400 | 403 | 404 | 409 | 413 | 500>>;
51
53
  declare class DriveError extends Error {
52
54
  readonly code: ErrorCode;
53
55
  constructor(code: ErrorCode, message: string);
@@ -135,6 +137,11 @@ declare function createDrive(deps: DriveDeps): {
135
137
  trash(ctx: Ctx, loc: string): Promise<Node>;
136
138
  /** Items trashed on their own, newest first. */
137
139
  listTrash(ctx: Ctx): Promise<Node[]>;
140
+ /** Everything that is in the trash, newest first, each with the path it had before. It reads the whole drive, so a big drive costs more than `listTrash`. */
141
+ listTrashWithPaths(ctx: Ctx): Promise<{
142
+ node: Node;
143
+ path: string;
144
+ }[]>;
138
145
  /** Puts a trashed item back. It needs a live parent folder. */
139
146
  restore(ctx: Ctx, id: string, opts?: {
140
147
  parentId?: string;
@@ -186,6 +193,24 @@ declare function createDrive(deps: DriveDeps): {
186
193
  name: string;
187
194
  folder?: string;
188
195
  }): Promise<Node>;
196
+ /** The live references to `ref` in the caller's own drive that the caller can read, with their paths, sorted by path. */
197
+ findByRef(ctx: Ctx, ref: string): Promise<{
198
+ node: Node;
199
+ path: string;
200
+ }[]>;
201
+ /**
202
+ * Puts a reference at `path` and gives `claim.subject` the role `claim.role` on it, as one step. If the
203
+ * grant fails (the caller is not an owner of the item, or the subject is invalid), the reference is
204
+ * deleted again and the error is thrown, so no half-made item stays. Needs `sharing`. Folders that
205
+ * `parents` made stay, `onConflict: "replace"` acts as `"fail"` (a rollback could not bring back a replaced item), and an invalid role or subject is refused before anything is written.
206
+ */
207
+ claimRef(ctx: Ctx, path: string, ref: string, claim: {
208
+ subject: Subject;
209
+ role: Role;
210
+ }, opts?: {
211
+ parents?: boolean;
212
+ onConflict?: OnConflict;
213
+ }): Promise<Node>;
189
214
  /** An app deleted a document. Its references in this drive go to the trash. Returns how many. */
190
215
  forgetDocument(ctx: Ctx, ref: string): Promise<{
191
216
  trashed: number;
@@ -331,4 +356,4 @@ declare function createDrive(deps: DriveDeps): {
331
356
  }>;
332
357
  };
333
358
 
334
- export { type Actor as A, type Ctx as C, type Drive as D, type ErrorCode as E, type Node as N, type OnConflict as O, ROOT_ID as R, type SearchQuery as S, ACTOR_KINDS as a, type Action as b, type ActorKind as c, type Can as d, type DriveDeps as e, DriveError as f, createDrive as g, parseSubject as h, parseName as p, subjectKindOf as s };
359
+ export { type Actor as A, type Ctx as C, type Drive as D, type ErrorCode as E, type Node as N, type OnConflict as O, ROOT_ID as R, type SearchQuery as S, ACTOR_KINDS as a, type Action as b, type ActorKind as c, type Can as d, type DriveDeps as e, DriveError as f, ERROR_STATUS as g, createDrive as h, parseSubject as i, parseName as p, subjectKindOf as s };
package/dist/embed.css CHANGED
@@ -3,72 +3,72 @@
3
3
  max-width: 72rem;
4
4
  }
5
5
  .drive-muted {
6
- color: var(--ad-color-text-muted);
6
+ color: var(--agd-color-text-muted);
7
7
  }
8
8
  .drive-status {
9
9
  display: flex;
10
10
  align-items: center;
11
- gap: var(--ad-space-2);
12
- color: var(--ad-color-text-muted);
11
+ gap: var(--agd-space-2);
12
+ color: var(--agd-color-text-muted);
13
13
  }
14
14
  .drive-signin {
15
15
  display: grid;
16
- gap: var(--ad-space-4);
16
+ gap: var(--agd-space-4);
17
17
  max-width: 24rem;
18
18
  }
19
19
  .drive-form {
20
20
  display: grid;
21
- gap: var(--ad-space-4);
21
+ gap: var(--agd-space-4);
22
22
  }
23
23
  .drive-form__actions {
24
24
  display: flex;
25
25
  justify-content: flex-end;
26
- gap: var(--ad-space-2);
26
+ gap: var(--agd-space-2);
27
27
  }
28
28
  .drive-drop {
29
29
  min-height: 60vh;
30
30
  border: 2px dashed transparent;
31
- border-radius: var(--ad-radius-md);
32
- padding: var(--ad-space-2);
31
+ border-radius: var(--agd-radius-md);
32
+ padding: var(--agd-space-2);
33
33
  }
34
34
  .drive-drop--over {
35
- border-color: var(--ad-color-accent);
36
- background: var(--ad-color-accent-subtle);
35
+ border-color: var(--agd-color-accent);
36
+ background: var(--agd-color-accent-subtle);
37
37
  }
38
38
  .drive-bar {
39
39
  display: flex;
40
40
  align-items: center;
41
41
  justify-content: space-between;
42
- gap: var(--ad-space-4);
42
+ gap: var(--agd-space-4);
43
43
  flex-wrap: wrap;
44
- margin-bottom: var(--ad-space-4);
44
+ margin-bottom: var(--agd-space-4);
45
45
  }
46
46
  .drive-bar h1 {
47
47
  margin: 0;
48
- font-size: var(--ad-font-size-xl);
48
+ font-size: var(--agd-font-size-xl);
49
49
  overflow-wrap: anywhere;
50
50
  }
51
51
  .drive-crumbs ol {
52
52
  display: flex;
53
53
  flex-wrap: wrap;
54
- gap: var(--ad-space-2);
54
+ gap: var(--agd-space-2);
55
55
  list-style: none;
56
- margin: 0 0 var(--ad-space-2);
56
+ margin: 0 0 var(--agd-space-2);
57
57
  padding: 0;
58
- color: var(--ad-color-text-muted);
58
+ color: var(--agd-color-text-muted);
59
59
  }
60
60
  .drive-crumbs li + li::before {
61
61
  content: "/";
62
- margin-right: var(--ad-space-2);
62
+ margin-right: var(--agd-space-2);
63
63
  }
64
64
  .drive-crumbs [aria-current=page] {
65
- color: var(--ad-color-text);
66
- font-weight: var(--ad-font-weight-semibold);
65
+ color: var(--agd-color-text);
66
+ font-weight: var(--agd-font-weight-semibold);
67
67
  }
68
68
  .drive-split {
69
69
  display: grid;
70
70
  grid-template-columns: 14rem minmax(0, 1fr);
71
- gap: var(--ad-space-6);
71
+ gap: var(--agd-space-6);
72
72
  }
73
73
  @media (max-width: 48rem) {
74
74
  .drive-split {
@@ -81,24 +81,24 @@
81
81
  padding: 0;
82
82
  }
83
83
  .drive-tree .drive-tree {
84
- padding-left: var(--ad-space-4);
84
+ padding-left: var(--agd-space-4);
85
85
  }
86
86
  .drive-tree a {
87
87
  display: flex;
88
88
  align-items: center;
89
- gap: var(--ad-space-2);
90
- padding: var(--ad-space-1) var(--ad-space-2);
91
- border-radius: var(--ad-radius-sm);
92
- color: var(--ad-color-text);
89
+ gap: var(--agd-space-2);
90
+ padding: var(--agd-space-1) var(--agd-space-2);
91
+ border-radius: var(--agd-radius-sm);
92
+ color: var(--agd-color-text);
93
93
  text-decoration: none;
94
94
  }
95
95
  .drive-tree a:hover {
96
- background: var(--ad-color-surface-hover);
96
+ background: var(--agd-color-surface-hover);
97
97
  }
98
98
  .drive-tree a[aria-current=page] {
99
- background: var(--ad-color-accent-subtle);
100
- color: var(--ad-color-accent-text);
101
- font-weight: var(--ad-font-weight-semibold);
99
+ background: var(--agd-color-accent-subtle);
100
+ color: var(--agd-color-accent-text);
101
+ font-weight: var(--agd-font-weight-semibold);
102
102
  }
103
103
  .drive-tree svg {
104
104
  width: 1rem;
@@ -108,7 +108,7 @@
108
108
  .drive-grid {
109
109
  display: grid;
110
110
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
111
- gap: var(--ad-space-4);
111
+ gap: var(--agd-space-4);
112
112
  list-style: none;
113
113
  margin: 0;
114
114
  padding: 0;
@@ -116,11 +116,11 @@
116
116
  .drive-card {
117
117
  position: relative;
118
118
  display: grid;
119
- gap: var(--ad-space-2);
120
- padding: var(--ad-space-4);
121
- border: 1px solid var(--ad-color-border);
122
- border-radius: var(--ad-radius-md);
123
- background: var(--ad-color-surface);
119
+ gap: var(--agd-space-2);
120
+ padding: var(--agd-space-4);
121
+ border: 1px solid var(--agd-color-border);
122
+ border-radius: var(--agd-radius-md);
123
+ background: var(--agd-color-surface);
124
124
  }
125
125
  .drive-card__icon svg {
126
126
  width: 2rem;
@@ -128,24 +128,24 @@
128
128
  }
129
129
  .drive-card__name {
130
130
  overflow-wrap: anywhere;
131
- font-weight: var(--ad-font-weight-medium);
132
- color: var(--ad-color-text);
131
+ font-weight: var(--agd-font-weight-medium);
132
+ color: var(--agd-color-text);
133
133
  }
134
134
  .drive-card__meta {
135
- font-size: var(--ad-font-size-sm);
136
- color: var(--ad-color-text-muted);
135
+ font-size: var(--agd-font-size-sm);
136
+ color: var(--agd-color-text-muted);
137
137
  }
138
138
  .drive-card__actions {
139
139
  display: flex;
140
140
  align-items: center;
141
141
  justify-content: space-between;
142
- gap: var(--ad-space-2);
142
+ gap: var(--agd-space-2);
143
143
  }
144
144
  .drive-root {
145
145
  display: grid;
146
146
  grid-template-columns: 12rem minmax(0, 1fr);
147
- gap: var(--ad-space-6);
148
- color: var(--ad-color-text);
147
+ gap: var(--agd-space-6);
148
+ color: var(--agd-color-text);
149
149
  }
150
150
  @media (max-width: 48rem) {
151
151
  .drive-root {
package/dist/embed.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DriveApiError,
3
3
  createClient
4
- } from "./chunk-S4AGCKXW.js";
4
+ } from "./chunk-LELTSSZF.js";
5
5
 
6
6
  // ui/embed.tsx
7
7
  import { useEffect as useEffect2, useState as useState2 } from "react";
@@ -38,7 +38,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
38
38
  var errorText = (e) => e instanceof DriveApiError ? `${e.message} (${e.code})` : e instanceof Error ? e.message : "Something went wrong";
39
39
  var byName = (a, b) => (a.kind === "folder" ? 0 : 1) - (b.kind === "folder" ? 0 : 1) || a.name.localeCompare(b.name);
40
40
  var who = (a, owner) => a.kind === "human" ? { id: a.id, name: a.id, kind: "person" } : { id: a.id, name: a.id, kind: "agent", actingFor: owner };
41
- var MachineLabel = ({ item }) => item.machineMade ? /* @__PURE__ */ jsx("span", { className: "ad-pill", children: "Created by agent" }) : null;
41
+ var MachineLabel = ({ item }) => item.machineMade ? /* @__PURE__ */ jsx("span", { className: "agd-pill", children: "Created by agent" }) : null;
42
42
  function useLoad(fn) {
43
43
  const [state, set] = useState({ status: "loading" });
44
44
  const [tick, setTick] = useState(0);
@@ -53,7 +53,7 @@ function useLoad(fn) {
53
53
  }
54
54
  function Status({ state, retry, children }) {
55
55
  if (state.status === "loading") return /* @__PURE__ */ jsxs("p", { role: "status", className: "drive-status", children: [
56
- /* @__PURE__ */ jsx("span", { className: "ad-spinner", "aria-hidden": "true" }),
56
+ /* @__PURE__ */ jsx("span", { className: "agd-spinner", "aria-hidden": "true" }),
57
57
  " Loading\u2026"
58
58
  ] });
59
59
  if (state.status === "error") return /* @__PURE__ */ jsx("div", { role: "alert", children: /* @__PURE__ */ jsx(EmptyState, { title: "Could not load this page", description: state.error, action: /* @__PURE__ */ jsx(Button, { onClick: retry, children: "Try again" }) }) });
package/dist/index.d.ts CHANGED
@@ -1,24 +1,10 @@
1
- import { O as OnConflict, D as Drive, C as Ctx, N as Node, A as Actor } from './drive-BtRyexUP.js';
2
- export { a as ACTOR_KINDS, b as Action, c as ActorKind, d as Can, e as DriveDeps, f as DriveError, E as ErrorCode, R as ROOT_ID, S as SearchQuery, g as createDrive, p as parseName, h as parseSubject, s as subjectKindOf } from './drive-BtRyexUP.js';
3
- import { AdapterOptions, Blobs, Store, Doc } from 'agentic-identity';
1
+ import { O as OnConflict, D as Drive, C as Ctx, N as Node, A as Actor } from './drive-Dxy0gL0_.js';
2
+ export { a as ACTOR_KINDS, b as Action, c as ActorKind, d as Can, e as DriveDeps, f as DriveError, g as ERROR_STATUS, E as ErrorCode, R as ROOT_ID, S as SearchQuery, h as createDrive, p as parseName, i as parseSubject, s as subjectKindOf } from './drive-Dxy0gL0_.js';
3
+ import { Store, Blobs, Doc } from 'agentic-identity';
4
4
  export { B as BackfillOptions, a as BackfillResult, b as backfillAuthorIds, c as backfillResources } from './migrate-B79gRPMu.js';
5
5
 
6
6
  declare const VERSION: string;
7
7
 
8
- /**
9
- * A Store kept in a journal file: one JSON line per committed write set, replayed on open.
10
- * It is the shared memory store plus the journal, so it follows the same rules. One process at a time.
11
- * A half-written last line (a crash during an append) is cut off on open. A bad line anywhere else
12
- * throws, because the data cannot be trusted. If an append fails, the store refuses every later call.
13
- * `shared` exists for the contract suites: stores that share a name share one live dataset, so do not
14
- * open the same directory twice with it in production.
15
- */
16
- declare function createFileStore(dir: string, options?: AdapterOptions & {
17
- shared?: string;
18
- }): Store;
19
- /** Blobs kept as files under `dir`. One process at a time: a conditional put is atomic only inside one process. File names are key hashes, so no key escapes the folder. */
20
- declare function createFileBlobs(dir: string, options?: AdapterOptions): Blobs;
21
-
22
8
  declare const DEFAULT_MAX_BYTES: number;
23
9
  /** The type named by the first bytes, or null when they match no known signature. */
24
10
  declare function sniffMime(head: Uint8Array): string | null;
@@ -51,10 +37,21 @@ declare function writeZip(entries: ZipEntry[], at: number): Uint8Array;
51
37
  /** Reads a zip made by `writeZip`. It checks every CRC. */
52
38
  declare function readZip(bytes: Uint8Array): Map<string, Uint8Array>;
53
39
 
54
- /** The drive and the store behind it, both kept in `dir`. The store holds the principals and keys too. */
55
- declare function openLocal(dir: string): {
40
+ /**
41
+ * Copies the data that the old local store kept (`db/store.jsonl` and hashed files in `blobs/`) into the shared
42
+ * file store, once. A marker in the store records it. The old files stay, so nothing is lost if a copy fails:
43
+ * a run that stops runs again, and it writes the same data. A torn last line of the journal was never
44
+ * acknowledged, so it is dropped. A bad line anywhere else throws, because the data cannot be trusted.
45
+ */
46
+ declare function importLegacyLocal(dir: string, store: Store, blobs: Blobs): Promise<void>;
47
+
48
+ /** The drive and the store behind it, both kept in `dir`. The store holds the principals and keys too. Sharing is on, as in the Worker. */
49
+ declare function openLocal(dir: string, opts?: {
50
+ beforeImport?: boolean;
51
+ }): {
56
52
  drive: Drive;
57
53
  store: Store;
54
+ blobs: Blobs;
58
55
  };
59
56
  /** Why no caller could be named. The CLI turns it into exit code 3. */
60
57
  declare class AuthError extends Error {
@@ -117,4 +114,4 @@ declare function publicNode(node: Node, path?: string): {
117
114
  path: string;
118
115
  };
119
116
 
120
- export { Actor, AuthError, Ctx, DEFAULT_MAX_BYTES, Drive, Node, OnConflict, type UploadOptions, VERSION, addPrincipal, buildExport, createFileBlobs, createFileStore, issueKey, openLocal, publicNode, readZip, resolveToken, revokeKey, revokePrincipal, sniffMime, upload, writeZip };
117
+ export { Actor, AuthError, Ctx, DEFAULT_MAX_BYTES, Drive, Node, OnConflict, type UploadOptions, VERSION, addPrincipal, buildExport, importLegacyLocal, issueKey, openLocal, publicNode, readZip, resolveToken, revokeKey, revokePrincipal, sniffMime, upload, writeZip };
package/dist/index.js CHANGED
@@ -1,21 +1,21 @@
1
1
  import {
2
- VERSION
3
- } from "./chunk-H6JK62SP.js";
2
+ importLegacyLocal
3
+ } from "./chunk-AB2RTTHJ.js";
4
4
  import {
5
- backfillAuthorIds,
6
- backfillResources
7
- } from "./chunk-5Z3SFBUK.js";
5
+ VERSION
6
+ } from "./chunk-6UQ6CDLJ.js";
8
7
  import {
9
8
  ACTOR_KINDS,
10
9
  AuthError,
11
10
  DEFAULT_MAX_BYTES,
12
11
  DriveError,
12
+ ERROR_STATUS,
13
13
  ROOT_ID,
14
14
  addPrincipal,
15
+ backfillAuthorIds,
16
+ backfillResources,
15
17
  buildExport,
16
18
  createDrive,
17
- createFileBlobs,
18
- createFileStore,
19
19
  issueKey,
20
20
  openLocal,
21
21
  parseName,
@@ -29,12 +29,13 @@ import {
29
29
  subjectKindOf,
30
30
  upload,
31
31
  writeZip
32
- } from "./chunk-EAKQK7ST.js";
32
+ } from "./chunk-R2DUVOJT.js";
33
33
  export {
34
34
  ACTOR_KINDS,
35
35
  AuthError,
36
36
  DEFAULT_MAX_BYTES,
37
37
  DriveError,
38
+ ERROR_STATUS,
38
39
  ROOT_ID,
39
40
  VERSION,
40
41
  addPrincipal,
@@ -42,8 +43,7 @@ export {
42
43
  backfillResources,
43
44
  buildExport,
44
45
  createDrive,
45
- createFileBlobs,
46
- createFileStore,
46
+ importLegacyLocal,
47
47
  issueKey,
48
48
  openLocal,
49
49
  parseName,
package/dist/mcp.d.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { D as Drive, C as Ctx } from './drive-BtRyexUP.js';
3
- import 'agentic-identity';
2
+ import { D as Drive, C as Ctx } from './drive-Dxy0gL0_.js';
3
+ import { Store } from 'agentic-identity';
4
4
 
5
- declare function createMcpServer(drive: Drive, ctx: Ctx, exportDir: string): McpServer;
5
+ declare function createMcpServer(drive: Drive, ctx: Ctx, exportDir: string, store: Store): McpServer;
6
6
  declare function startMcp(deps: {
7
7
  drive: Drive;
8
8
  ctx: Ctx;
9
9
  exportDir: string;
10
+ store: Store;
10
11
  }): Promise<void>;
11
12
 
12
13
  export { createMcpServer, startMcp };