agentic-drive 0.7.0 → 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.
@@ -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
 
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
+
54
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. */
55
- declare function openLocal(dir: string): {
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,19 +1,21 @@
1
+ import {
2
+ importLegacyLocal
3
+ } from "./chunk-AB2RTTHJ.js";
1
4
  import {
2
5
  VERSION
3
- } from "./chunk-EFO5PSJL.js";
6
+ } from "./chunk-6UQ6CDLJ.js";
4
7
  import {
5
8
  ACTOR_KINDS,
6
9
  AuthError,
7
10
  DEFAULT_MAX_BYTES,
8
11
  DriveError,
12
+ ERROR_STATUS,
9
13
  ROOT_ID,
10
14
  addPrincipal,
11
15
  backfillAuthorIds,
12
16
  backfillResources,
13
17
  buildExport,
14
18
  createDrive,
15
- createFileBlobs,
16
- createFileStore,
17
19
  issueKey,
18
20
  openLocal,
19
21
  parseName,
@@ -27,12 +29,13 @@ import {
27
29
  subjectKindOf,
28
30
  upload,
29
31
  writeZip
30
- } from "./chunk-PJQ3CRVL.js";
32
+ } from "./chunk-R2DUVOJT.js";
31
33
  export {
32
34
  ACTOR_KINDS,
33
35
  AuthError,
34
36
  DEFAULT_MAX_BYTES,
35
37
  DriveError,
38
+ ERROR_STATUS,
36
39
  ROOT_ID,
37
40
  VERSION,
38
41
  addPrincipal,
@@ -40,8 +43,7 @@ export {
40
43
  backfillResources,
41
44
  buildExport,
42
45
  createDrive,
43
- createFileBlobs,
44
- createFileStore,
46
+ importLegacyLocal,
45
47
  issueKey,
46
48
  openLocal,
47
49
  parseName,
package/dist/mcp.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { D as Drive, C as Ctx } from './drive-BtRyexUP.js';
2
+ import { D as Drive, C as Ctx } from './drive-Dxy0gL0_.js';
3
3
  import { Store } from 'agentic-identity';
4
4
 
5
5
  declare function createMcpServer(drive: Drive, ctx: Ctx, exportDir: string, store: Store): McpServer;
package/dist/mcp.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-EFO5PSJL.js";
3
+ } from "./chunk-6UQ6CDLJ.js";
4
4
  import {
5
5
  ACTOR_KINDS,
6
6
  DriveError,
@@ -8,7 +8,7 @@ import {
8
8
  inviteIdentity,
9
9
  publicNode,
10
10
  upload
11
- } from "./chunk-PJQ3CRVL.js";
11
+ } from "./chunk-R2DUVOJT.js";
12
12
 
13
13
  // src/mcp.ts
14
14
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -65,7 +65,7 @@ function createMcpServer(drive, ctx, exportDir, store) {
65
65
  }, { readOnlyHint: true });
66
66
  tool("drive_mv", "Move an item into a folder. Pass `name` to rename it.", { src: loc, folder: loc, name: z.string().optional(), onConflict: conflict }, async ({ src, folder, name, onConflict }) => publicNode(await drive.move(ctx, src, folder, { name, onConflict })));
67
67
  tool("drive_rm", "Move an item to the trash. It stays restorable.", { path: loc }, async ({ path }) => publicNode(await drive.trash(ctx, path)));
68
- tool("drive_trash", "List items in the trash.", {}, async () => (await drive.listTrash(ctx)).map((n) => publicNode(n)), { readOnlyHint: true });
68
+ tool("drive_trash", "List items in the trash. Pass `paths` to add the path each item had before.", { paths: z.boolean().optional() }, async ({ paths }) => paths ? (await drive.listTrashWithPaths(ctx)).map((r) => publicNode(r.node, r.path)) : (await drive.listTrash(ctx)).map((n) => publicNode(n)), { readOnlyHint: true });
69
69
  tool("drive_restore", "Put a trashed item back.", { id: z.string(), parentId: z.string().optional(), onConflict: conflict }, async ({ id, parentId, onConflict }) => publicNode(await drive.restore(ctx, id, { parentId, onConflict })));
70
70
  tool("drive_purge", "Delete a trashed item for good.", { id: z.string() }, async ({ id }) => drive.purge(ctx, id), { destructiveHint: true });
71
71
  tool(
@@ -91,6 +91,13 @@ function createMcpServer(drive, ctx, exportDir, store) {
91
91
  { ref: z.string(), name: z.string(), folder: z.string().optional() },
92
92
  async ({ ref, name, folder }) => publicNode(await drive.registerDocument(ctx, { ref, name, folder }))
93
93
  );
94
+ tool("drive_find_ref", "Find the live items that point at an app document such as docs:<id>, with their paths.", { ref: z.string() }, async ({ ref }) => (await drive.findByRef(ctx, ref)).map((r) => publicNode(r.node, r.path)), { readOnlyHint: true });
95
+ tool(
96
+ "drive_claim_ref",
97
+ "Put a reference such as docs:<id> at a path and give a person or an agent a role on it. If the share fails, the reference is removed again.",
98
+ { path: z.string(), ref: z.string(), subjectKind, subjectId: z.string(), role, parents: z.boolean().optional(), onConflict: conflict },
99
+ async ({ path, ref, subjectKind: subjectKind2, subjectId, role: role2, parents, onConflict }) => publicNode(await drive.claimRef(ctx, path, ref, { subject: { kind: subjectKind2, id: subjectId }, role: role2 }, { parents, onConflict }))
100
+ );
94
101
  tool("drive_forget_document", "Move every reference to an app document to the trash.", { ref: z.string() }, async ({ ref }) => drive.forgetDocument(ctx, ref));
95
102
  tool("drive_shares", "Show who can reach an item, and by which links and invites. Only an owner may look. Link tokens are never shown.", { path: loc }, async ({ path }) => drive.shares(ctx, path), { readOnlyHint: true });
96
103
  tool(
package/dist/worker.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { Hono } from 'hono';
2
2
  import { D1Like, R2Like } from 'agentic-identity/cloudflare';
3
3
  import { Store, Blobs } from 'agentic-identity';
4
- import { C as Ctx, D as Drive } from './drive-BtRyexUP.js';
4
+ import { C as Ctx, D as Drive } from './drive-Dxy0gL0_.js';
5
+ export { g as ERROR_STATUS, E as ErrorCode, N as Node } from './drive-Dxy0gL0_.js';
5
6
  export { B as BackfillOptions, a as BackfillResult, b as backfillAuthorIds, c as backfillResources } from './migrate-B79gRPMu.js';
6
7
 
7
8
  /**
package/dist/worker.js CHANGED
@@ -2,6 +2,7 @@ import {
2
2
  DEFAULT_MAX_BYTES,
3
3
  DEFAULT_URL_SECONDS,
4
4
  DriveError,
5
+ ERROR_STATUS,
5
6
  authenticate,
6
7
  backfillAuthorIds,
7
8
  backfillResources,
@@ -11,36 +12,12 @@ import {
11
12
  publicNode,
12
13
  safeMime,
13
14
  upload
14
- } from "./chunk-PJQ3CRVL.js";
15
+ } from "./chunk-R2DUVOJT.js";
15
16
 
16
17
  // src/worker.ts
17
18
  import { Hono } from "hono";
18
19
  import { D1_SCHEMA, createD1Store, createR2Blobs, verifySignedBlobUrl } from "agentic-identity/cloudflare";
19
20
  import { createSharing, parseRegion } from "agentic-identity";
20
- var STATUS = {
21
- CROSS_DRIVE: 409,
22
- INVALID_SHARE: 400,
23
- TOO_MANY_ITEMS: 409,
24
- TOO_DEEP: 400,
25
- INVALID_EXPIRY: 400,
26
- BUSY: 409,
27
- BLOB_EXISTS: 500,
28
- NOT_FOUND: 404,
29
- NAME_TAKEN: 409,
30
- INVALID_NAME: 400,
31
- INVALID_PATH: 400,
32
- INVALID_REF: 400,
33
- NOT_A_FOLDER: 400,
34
- NOT_A_FILE: 400,
35
- MOVE_INTO_SELF: 409,
36
- PARENT_GONE: 409,
37
- TRASHED: 409,
38
- NOT_TRASHED: 409,
39
- IS_ROOT: 400,
40
- FORBIDDEN: 403,
41
- BLOB_MISSING: 500,
42
- TOO_LARGE: 413
43
- };
44
21
  var fail = (code, message, status) => new Response(JSON.stringify({ error: { code, message } }), { status, headers: { "content-type": "application/json" } });
45
22
  var schemas = /* @__PURE__ */ new WeakMap();
46
23
  function settings(env, needUrl = true) {
@@ -175,6 +152,7 @@ function createApp(options = {}) {
175
152
  });
176
153
  api.post("/trash", async (c) => c.json(publicNode(await c.var.drive.trash(c.var.ctx, str((await body(c)).path, "path")))));
177
154
  api.get("/trash", async (c) => c.json((await c.var.drive.listTrash(c.var.ctx)).map((n) => publicNode(n))));
155
+ api.get("/trash/paths", async (c) => c.json((await c.var.drive.listTrashWithPaths(c.var.ctx)).map((r) => publicNode(r.node, r.path))));
178
156
  api.post("/restore", async (c) => {
179
157
  const b = await body(c);
180
158
  return c.json(publicNode(await c.var.drive.restore(c.var.ctx, str(b.id, "id"), { parentId: opt(b.parentId, "parentId"), onConflict: opt(b.onConflict, "onConflict") })));
@@ -206,6 +184,18 @@ function createApp(options = {}) {
206
184
  const b = await body(c);
207
185
  return c.json(publicNode(await c.var.drive.registerDocument(c.var.ctx, { ref: str(b.ref, "ref"), name: str(b.name, "name"), folder: opt(b.folder, "folder") })), 201);
208
186
  });
187
+ api.get("/refs", async (c) => c.json((await c.var.drive.findByRef(c.var.ctx, need(q(c, "ref"), "ref"))).map((r) => publicNode(r.node, r.path))));
188
+ api.post("/refs", async (c) => {
189
+ const b = await body(c);
190
+ const node = await c.var.drive.claimRef(
191
+ c.var.ctx,
192
+ str(b.path, "path"),
193
+ str(b.ref, "ref"),
194
+ { subject: { kind: b.subjectKind, id: str(b.subjectId, "subjectId") }, role: roleOf(b.role) },
195
+ { parents: b.parents === true, onConflict: opt(b.onConflict, "onConflict") }
196
+ );
197
+ return c.json(publicNode(node), 201);
198
+ });
209
199
  api.delete("/documents", async (c) => c.json(await c.var.drive.forgetDocument(c.var.ctx, need(q(c, "ref"), "ref"))));
210
200
  app2.get("/api/v1/drive/blob", async (c) => {
211
201
  const secret = secretOf(c.env);
@@ -305,7 +295,7 @@ function createApp(options = {}) {
305
295
  app2.route("/api/v1/drive", api);
306
296
  app2.notFound(() => fail("NOT_FOUND", "no such route", 404));
307
297
  app2.onError((error) => {
308
- if (error instanceof DriveError) return new Response(JSON.stringify({ error: { code: error.code, message: error.message } }), { status: STATUS[error.code], headers: { "content-type": "application/json" } });
298
+ if (error instanceof DriveError) return new Response(JSON.stringify({ error: { code: error.code, message: error.message } }), { status: ERROR_STATUS[error.code], headers: { "content-type": "application/json" } });
309
299
  console.error("internal error", error instanceof Error ? error.name : "unknown");
310
300
  return new Response(JSON.stringify({ error: { code: "INTERNAL", message: "the server could not finish the request" } }), { status: 500, headers: { "content-type": "application/json" } });
311
301
  });
@@ -314,6 +304,7 @@ function createApp(options = {}) {
314
304
  var app = createApp();
315
305
  var worker_default = { fetch: (request, env, ctx) => app.fetch(request, env, ctx) };
316
306
  export {
307
+ ERROR_STATUS,
317
308
  authenticate,
318
309
  backfillAuthorIds,
319
310
  backfillResources,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-drive",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Store, sort, and share files and folders.",
5
5
  "keywords": [
6
6
  "drive",
@@ -72,10 +72,10 @@
72
72
  },
73
73
  "dependencies": {
74
74
  "@modelcontextprotocol/sdk": "^1.12.0",
75
- "agentic-design": "^0.1.0",
75
+ "agentic-design": "^0.4.0",
76
76
  "agentic-identity": "^0.6.0",
77
77
  "hono": "^4.13.14",
78
- "zod": "^3.25.0"
78
+ "zod": "^4.6.6"
79
79
  },
80
80
  "devDependencies": {
81
81
  "@axe-core/playwright": "^4.14.0",
@@ -110,5 +110,10 @@
110
110
  "react-dom": {
111
111
  "optional": true
112
112
  }
113
+ },
114
+ "overrides": {
115
+ "agentic-design": {
116
+ "zod": "^4.6.6"
117
+ }
113
118
  }
114
119
  }
@@ -0,0 +1 @@
1
+ @font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2) format("woff2-variations");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-latin-wght-normal-Dx4kXJAl.woff2) format("woff2-variations");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2) format("woff2-variations");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2) format("woff2-variations");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root,[data-theme=light]{color-scheme:light;--agd-color-bg: #FAF9F7;--agd-color-surface: #FFFFFF;--agd-color-surface-raised: #FFFFFF;--agd-color-surface-sunken: #F3F1EE;--agd-color-surface-hover: #E9E6E1;--agd-color-text: #1D1C1A;--agd-color-text-muted: #5E5A53;--agd-color-text-on-accent: #FFFFFF;--agd-color-border: #DAD7D1;--agd-color-border-strong: #827D73;--agd-color-accent: #2B4BC4;--agd-color-accent-hover: #223D9F;--agd-color-accent-subtle: #E8EDFC;--agd-color-accent-text: #223D9F;--agd-color-agent: #8E2C86;--agd-color-agent-subtle: #F7E8F5;--agd-color-agent-text: #7A2273;--agd-color-danger: #B42318;--agd-color-danger-subtle: #FDECEA;--agd-color-danger-text: #A11D14;--agd-color-warning: #92520A;--agd-color-warning-subtle: #FDF1DC;--agd-color-warning-text: #7A4208;--agd-color-success: #1B6B3A;--agd-color-success-subtle: #E6F5EC;--agd-color-success-text: #175C32;--agd-color-focus: #2B4BC4;--agd-color-scrim: rgb(29 28 26 / .4);--agd-shadow-raised: 0 1px 2px rgb(29 28 26 / .06), 0 2px 16px rgb(29 28 26 / .08);--agd-shadow-floating: 0 2px 6px rgb(29 28 26 / .08), 0 8px 40px rgb(29 28 26 / .16)}:root{--agd-space-1: .25rem;--agd-space-2: .5rem;--agd-space-3: .75rem;--agd-space-4: 1rem;--agd-space-6: 1.5rem;--agd-space-8: 2rem;--agd-space-12: 3rem;--agd-space-16: 4rem;--agd-space-24: 6rem;--agd-radius-sm: .25rem;--agd-radius-md: .5rem;--agd-radius-lg: .75rem;--agd-radius-full: 9999px;--agd-font-family-sans: "Inter Variable", ui-sans-serif, system-ui, sans-serif;--agd-font-family-mono: "JetBrains Mono Variable", ui-monospace, "SF Mono", Menlo, monospace;--agd-font-size-xs: .75rem;--agd-font-size-sm: .875rem;--agd-font-size-md: 1rem;--agd-font-size-lg: 1.125rem;--agd-font-size-xl: 1.5rem;--agd-font-size-2xl: 2rem;--agd-line-height-tight: 1.25;--agd-line-height-snug: 1.4;--agd-line-height-normal: 1.55;--agd-font-weight-regular: 400;--agd-font-weight-medium: 500;--agd-font-weight-semibold: 600;--agd-duration-fast: .1s;--agd-duration-base: .16s;--agd-duration-slow: .24s;--agd-easing-out: cubic-bezier(.16, 1, .3, 1);--agd-size-control: 2rem;--agd-size-control-touch: 2.75rem;--agd-size-sidebar: 16rem;--agd-size-panel: 20rem;--agd-size-topbar: 3rem;--agd-size-content: 46rem}@media(prefers-color-scheme:dark){:root:not([data-theme]){color-scheme:dark;--agd-color-bg: #141311;--agd-color-surface: #1B1A18;--agd-color-surface-raised: #232220;--agd-color-surface-sunken: #100F0E;--agd-color-surface-hover: #2E2C29;--agd-color-text: #EDEBE7;--agd-color-text-muted: #A9A49A;--agd-color-text-on-accent: #0E1633;--agd-color-border: #2E2C29;--agd-color-border-strong: #7A756B;--agd-color-accent: #8EA4FF;--agd-color-accent-hover: #A9BAFF;--agd-color-accent-subtle: #1E2745;--agd-color-accent-text: #B3C2FF;--agd-color-agent: #E49BDC;--agd-color-agent-subtle: #3A1F37;--agd-color-agent-text: #F0B8E9;--agd-color-danger: #F2877D;--agd-color-danger-subtle: #3B1A17;--agd-color-danger-text: #F8A39B;--agd-color-warning: #E8B04A;--agd-color-warning-subtle: #3A2A0F;--agd-color-warning-text: #F0C677;--agd-color-success: #6FCF97;--agd-color-success-subtle: #14301F;--agd-color-success-text: #8BDBAC;--agd-color-focus: #A9BAFF;--agd-color-scrim: rgb(0 0 0 / .6);--agd-shadow-raised: 0 1px 2px rgb(0 0 0 / .3), 0 2px 16px rgb(0 0 0 / .3);--agd-shadow-floating: 0 2px 6px rgb(0 0 0 / .3), 0 8px 40px rgb(0 0 0 / .5)}}[data-theme=dark]{color-scheme:dark;--agd-color-bg: #141311;--agd-color-surface: #1B1A18;--agd-color-surface-raised: #232220;--agd-color-surface-sunken: #100F0E;--agd-color-surface-hover: #2E2C29;--agd-color-text: #EDEBE7;--agd-color-text-muted: #A9A49A;--agd-color-text-on-accent: #0E1633;--agd-color-border: #2E2C29;--agd-color-border-strong: #7A756B;--agd-color-accent: #8EA4FF;--agd-color-accent-hover: #A9BAFF;--agd-color-accent-subtle: #1E2745;--agd-color-accent-text: #B3C2FF;--agd-color-agent: #E49BDC;--agd-color-agent-subtle: #3A1F37;--agd-color-agent-text: #F0B8E9;--agd-color-danger: #F2877D;--agd-color-danger-subtle: #3B1A17;--agd-color-danger-text: #F8A39B;--agd-color-warning: #E8B04A;--agd-color-warning-subtle: #3A2A0F;--agd-color-warning-text: #F0C677;--agd-color-success: #6FCF97;--agd-color-success-subtle: #14301F;--agd-color-success-text: #8BDBAC;--agd-color-focus: #A9BAFF;--agd-color-scrim: rgb(0 0 0 / .6);--agd-shadow-raised: 0 1px 2px rgb(0 0 0 / .3), 0 2px 16px rgb(0 0 0 / .3);--agd-shadow-floating: 0 2px 6px rgb(0 0 0 / .3), 0 8px 40px rgb(0 0 0 / .5)}@media(prefers-reduced-motion:reduce){:root{--agd-duration-fast: .01ms;--agd-duration-base: .01ms;--agd-duration-slow: .01ms}}*,*:before,*:after{box-sizing:border-box}html{-webkit-text-size-adjust:100%;text-size-adjust:100%}body{margin:0;background:var(--agd-color-bg);color:var(--agd-color-text);font-family:var(--agd-font-family-sans);font-size:var(--agd-font-size-sm);line-height:var(--agd-line-height-normal);font-feature-settings:"cv11","ss03";-webkit-font-smoothing:antialiased}h1,h2,h3,h4{margin:0;line-height:var(--agd-line-height-tight);font-weight:var(--agd-font-weight-semibold);text-wrap:balance}h1{font-size:var(--agd-font-size-2xl)}h2{font-size:var(--agd-font-size-xl)}h3{font-size:var(--agd-font-size-lg)}h4{font-size:var(--agd-font-size-md)}p{margin:0;text-wrap:pretty}a{color:var(--agd-color-accent-text);text-underline-offset:.2em}code,kbd,pre{font-family:var(--agd-font-family-mono);font-size:.9em}:focus-visible{outline:2px solid var(--agd-color-focus);outline-offset:2px}::selection{background:var(--agd-color-accent-subtle);color:var(--agd-color-accent-text)}.agd-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.agd-skip-link{position:absolute;inset-block-start:var(--agd-space-2);inset-inline-start:var(--agd-space-2);z-index:100;padding:var(--agd-space-2) var(--agd-space-4);border-radius:var(--agd-radius-md);background:var(--agd-color-surface-raised);color:var(--agd-color-text);box-shadow:var(--agd-shadow-floating);transform:translateY(-200%)}.agd-skip-link:focus{transform:none}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important;transition-duration:.01ms!important}}:root{--agd-control-h: var(--agd-size-control)}@media(pointer:coarse){:root{--agd-control-h: var(--agd-size-control-touch)}}.agd-button{--button-bg: var(--agd-color-surface);--button-bg-hover: var(--agd-color-surface-hover);--button-bg-active: var(--agd-color-surface-sunken);--button-fg: var(--agd-color-text);--button-border: var(--agd-color-border-strong);display:inline-flex;align-items:center;justify-content:center;gap:var(--agd-space-2);min-height:var(--agd-control-h);padding:0 var(--agd-space-4);border:1px solid var(--button-border);border-radius:var(--agd-radius-md);background:var(--button-bg);color:var(--button-fg);font:inherit;font-weight:var(--agd-font-weight-medium);line-height:1;white-space:nowrap;cursor:pointer;transition:background-color var(--agd-duration-fast) var(--agd-easing-out)}.agd-button:hover{background:var(--button-bg-hover)}.agd-button:active{background:var(--button-bg-active)}.agd-button--sm{min-height:1.75rem;padding:0 var(--agd-space-3);font-size:var(--agd-font-size-xs)}@media(pointer:coarse){.agd-button--sm{min-height:var(--agd-control-h)}}.agd-button--primary{--button-bg: var(--agd-color-accent);--button-bg-hover: var(--agd-color-accent-hover);--button-bg-active: var(--agd-color-accent-hover);--button-fg: var(--agd-color-text-on-accent);--button-border: transparent}.agd-button--ghost{--button-bg: transparent;--button-border: transparent}.agd-button--danger{--button-bg-hover: var(--agd-color-danger-subtle);--button-bg-active: var(--agd-color-danger-subtle);--button-fg: var(--agd-color-danger-text);--button-border: var(--agd-color-danger)}.agd-button:disabled{--button-bg: var(--agd-color-surface-sunken);--button-bg-hover: var(--agd-color-surface-sunken);--button-fg: var(--agd-color-text-muted);--button-border: var(--agd-color-border);cursor:not-allowed}.agd-button[aria-busy=true]{cursor:progress}.agd-icon-button{width:var(--agd-control-h);padding:0}.agd-icon-button.agd-button--sm{width:1.75rem}@media(pointer:coarse){.agd-icon-button.agd-button--sm{width:var(--agd-control-h)}}.agd-spinner{width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:agd-spin .7s linear infinite}@keyframes agd-spin{to{transform:rotate(360deg)}}.agd-field{display:grid;gap:var(--agd-space-1)}.agd-field__label{font-weight:var(--agd-font-weight-medium)}.agd-field__hint{color:var(--agd-color-text-muted);font-size:var(--agd-font-size-xs)}.agd-field__error{display:flex;align-items:flex-start;gap:var(--agd-space-1);color:var(--agd-color-danger-text);font-size:var(--agd-font-size-xs)}.agd-field__error svg{flex:none;margin-top:-.1em}.agd-input{width:100%;min-height:var(--agd-control-h);padding:0 var(--agd-space-3);border:1px solid var(--agd-color-border-strong);border-radius:var(--agd-radius-md);background:var(--agd-color-surface);color:var(--agd-color-text);font:inherit}.agd-input::placeholder{color:var(--agd-color-text-muted);opacity:1}.agd-input:hover:not(:disabled){background:var(--agd-color-surface-sunken)}.agd-input[aria-invalid=true]{border-color:var(--agd-color-danger);box-shadow:inset 0 0 0 1px var(--agd-color-danger)}.agd-input:disabled{background:var(--agd-color-surface-sunken);border-color:var(--agd-color-border);color:var(--agd-color-text-muted);cursor:not-allowed}.agd-textarea{min-height:5rem;padding:var(--agd-space-2) var(--agd-space-3);resize:vertical}.agd-select{position:relative;display:block}.agd-select select{appearance:none;padding-inline-end:var(--agd-space-8);cursor:pointer}.agd-select:after{content:"";position:absolute;inset-inline-end:var(--agd-space-3);inset-block-start:50%;width:.45rem;height:.45rem;border:solid var(--agd-color-text-muted);border-width:0 2px 2px 0;transform:translateY(-75%) rotate(45deg);pointer-events:none}.agd-toggle{display:grid;gap:var(--agd-space-1)}.agd-toggle__row{display:flex;align-items:center;gap:var(--agd-space-3);min-height:var(--agd-control-h);cursor:pointer}.agd-checkbox,.agd-switch{appearance:none;flex:none;margin:0;border:1px solid var(--agd-color-border-strong);background:var(--agd-color-surface);cursor:pointer;transition:background-color var(--agd-duration-fast) var(--agd-easing-out)}.agd-checkbox{display:grid;place-items:center;width:1.25rem;height:1.25rem;border-radius:var(--agd-radius-sm)}.agd-checkbox:before{content:"";width:.75rem;height:.75rem;background:var(--agd-color-text-on-accent);clip-path:polygon(14% 52%,0 66%,38% 100%,100% 20%,86% 8%,38% 72%);transform:scale(0);transition:transform var(--agd-duration-fast) var(--agd-easing-out)}.agd-checkbox:checked{background:var(--agd-color-accent);border-color:var(--agd-color-accent)}.agd-checkbox:checked:before{transform:scale(1)}.agd-switch{position:relative;width:2.25rem;height:1.375rem;border-radius:var(--agd-radius-full);background:var(--agd-color-surface-sunken)}.agd-switch:before{content:"";position:absolute;inset-block-start:50%;inset-inline-start:.2rem;width:.875rem;height:.875rem;border-radius:var(--agd-radius-full);background:var(--agd-color-text-muted);transform:translateY(-50%);transition:inset-inline-start var(--agd-duration-base) var(--agd-easing-out)}.agd-switch:checked{background:var(--agd-color-accent);border-color:var(--agd-color-accent)}.agd-switch:checked:before{background:var(--agd-color-text-on-accent);inset-inline-start:calc(100% - 1.075rem)}.agd-checkbox:disabled,.agd-switch:disabled{background:var(--agd-color-surface-sunken);border-color:var(--agd-color-border);cursor:not-allowed}.agd-checkbox:disabled:before{background:var(--agd-color-text-muted)}.agd-switch:disabled:before{background:var(--agd-color-border)}@keyframes agd-fade-in{0%{opacity:0}}@keyframes agd-pop-in{0%{opacity:0;scale:.97}}.agd-overlay{position:fixed;z-index:50;inset:0;background:var(--agd-color-scrim);animation:agd-fade-in var(--agd-duration-base) var(--agd-easing-out)}.agd-dialog{position:fixed;z-index:50;inset:0;margin:auto;width:min(32rem,calc(100vw - 2rem));height:fit-content;max-height:calc(100vh - 2rem);overflow:auto;padding:var(--agd-space-6);border:1px solid var(--agd-color-border);border-radius:var(--agd-radius-lg);background:var(--agd-color-surface-raised);box-shadow:var(--agd-shadow-floating);animation:agd-pop-in var(--agd-duration-base) var(--agd-easing-out)}.agd-dialog__title{padding-inline-end:var(--agd-space-8);font-size:var(--agd-font-size-lg)}.agd-dialog__description{margin-top:var(--agd-space-2);color:var(--agd-color-text-muted)}.agd-dialog__body{margin-top:var(--agd-space-4)}.agd-dialog__footer{display:flex;justify-content:flex-end;gap:var(--agd-space-2);margin-top:var(--agd-space-6)}.agd-dialog__close{position:absolute;inset-block-start:var(--agd-space-3);inset-inline-end:var(--agd-space-3)}.agd-tooltip{z-index:60;max-width:16rem;padding:var(--agd-space-1) var(--agd-space-2);border-radius:var(--agd-radius-sm);background:var(--agd-color-text);color:var(--agd-color-bg);font-size:var(--agd-font-size-xs);animation:agd-fade-in var(--agd-duration-fast) var(--agd-easing-out)}.agd-menu{z-index:60;min-width:11rem;padding:var(--agd-space-1);border:1px solid var(--agd-color-border);border-radius:var(--agd-radius-md);background:var(--agd-color-surface-raised);box-shadow:var(--agd-shadow-floating);animation:agd-pop-in var(--agd-duration-fast) var(--agd-easing-out)}.agd-menu__item{display:flex;align-items:center;gap:var(--agd-space-2);min-height:var(--agd-control-h);padding:0 var(--agd-space-3);border-radius:var(--agd-radius-sm);color:var(--agd-color-text);cursor:pointer;outline:none;-webkit-user-select:none;user-select:none}.agd-menu__item[data-highlighted]{background:var(--agd-color-surface-hover)}.agd-menu__item[data-highlighted]:focus-visible,.agd-menu__item:focus-visible{outline:2px solid var(--agd-color-focus);outline-offset:-2px}.agd-menu__item[data-disabled]{color:var(--agd-color-text-muted);cursor:not-allowed}.agd-menu__item--danger{color:var(--agd-color-danger-text)}.agd-menu__shortcut{margin-inline-start:auto;color:var(--agd-color-text-muted);font-size:var(--agd-font-size-xs)}.agd-menu__separator{height:1px;margin:var(--agd-space-1) 0;background:var(--agd-color-border)}.agd-toast-viewport{position:fixed;inset-block-end:var(--agd-space-4);inset-inline-end:var(--agd-space-4);z-index:70;display:grid;gap:var(--agd-space-2);width:min(24rem,calc(100vw - 2rem));margin:0;padding:0;list-style:none}.agd-toast{display:grid;grid-template-columns:auto 1fr auto;align-items:start;gap:var(--agd-space-3);padding:var(--agd-space-3) var(--agd-space-3) var(--agd-space-3) var(--agd-space-4);border:1px solid var(--agd-color-border);border-radius:var(--agd-radius-md);background:var(--agd-color-surface-raised);box-shadow:var(--agd-shadow-floating)}.agd-toast[data-state=open]{animation:agd-pop-in var(--agd-duration-base) var(--agd-easing-out)}.agd-toast__icon{margin-top:var(--agd-space-1)}.agd-toast--info .agd-toast__icon{color:var(--agd-color-accent)}.agd-toast--success .agd-toast__icon{color:var(--agd-color-success)}.agd-toast--warning .agd-toast__icon{color:var(--agd-color-warning)}.agd-toast--danger .agd-toast__icon{color:var(--agd-color-danger)}.agd-toast__title{font-weight:var(--agd-font-weight-medium)}.agd-toast__description{margin-top:var(--agd-space-1);color:var(--agd-color-text-muted)}.agd-tabs__list{display:flex;gap:var(--agd-space-1);border-bottom:1px solid var(--agd-color-border)}.agd-tabs__trigger{position:relative;min-height:var(--agd-control-h);padding:0 var(--agd-space-3);border:0;background:transparent;color:var(--agd-color-text-muted);font:inherit;cursor:pointer}.agd-tabs__trigger:hover{color:var(--agd-color-text)}.agd-tabs__trigger[data-state=active]{color:var(--agd-color-text);font-weight:var(--agd-font-weight-semibold)}.agd-tabs__trigger[data-state=active]:after{content:"";position:absolute;inset:auto var(--agd-space-3) -1px;height:2px;background:var(--agd-color-accent)}.agd-tabs__panel{padding-top:var(--agd-space-4)}.agd-shell{display:grid;grid-template-columns:var(--agd-size-sidebar) minmax(0,1fr);grid-template-rows:auto 1fr;grid-template-areas:"sidebar topbar" "sidebar content";min-height:100vh}.agd-shell__sidebar{grid-area:sidebar;display:flex;flex-direction:column;gap:var(--agd-space-4);padding:var(--agd-space-4) var(--agd-space-3);border-inline-end:1px solid var(--agd-color-border);background:var(--agd-color-surface-sunken)}.agd-shell__brand{margin:0;font-weight:var(--agd-font-weight-semibold)}.agd-shell__topbar{grid-area:topbar;display:flex;align-items:center;gap:var(--agd-space-3);min-height:var(--agd-size-topbar);padding:0 var(--agd-space-6);border-bottom:1px solid var(--agd-color-border);background:var(--agd-color-bg)}.agd-shell__title{min-width:0;flex:0 1 auto}.agd-shell__actions{display:flex;align-items:center;gap:var(--agd-space-4);margin-inline-start:auto}.agd-shell__content{grid-area:content;min-width:0;padding:var(--agd-space-8) var(--agd-space-6) var(--agd-space-24);outline:none}.agd-shell__menu{display:none}.agd-shell[data-panel]{grid-template-rows:auto 1fr auto;grid-template-areas:"sidebar topbar" "sidebar content" "sidebar panel"}@media(min-width:64rem){.agd-shell[data-panel]{grid-template-columns:var(--agd-size-sidebar) minmax(0,1fr) var(--agd-size-panel);grid-template-rows:auto 1fr;grid-template-areas:"sidebar topbar topbar" "sidebar content panel"}}.agd-shell__panel{grid-area:panel;min-width:0;padding:var(--agd-space-6) var(--agd-space-4);border-block-start:1px solid var(--agd-color-border);background:var(--agd-color-surface-sunken)}@media(min-width:64rem){.agd-shell__panel{border-block-start:0;border-inline-start:1px solid var(--agd-color-border)}}@media(max-width:47.99rem){.agd-shell{grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto 1fr;grid-template-areas:"topbar" "sidebar" "content"}.agd-shell__menu{display:inline-flex}.agd-shell[data-panel]{grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto 1fr auto;grid-template-areas:"topbar" "sidebar" "content" "panel"}.agd-shell__sidebar[data-open=false]{display:none}.agd-shell__sidebar{border-inline-end:0;border-bottom:1px solid var(--agd-color-border)}.agd-shell__topbar,.agd-shell__content{padding-inline:var(--agd-space-4)}}.agd-sidebar-nav{display:grid;gap:var(--agd-space-1);margin:0;padding:0;list-style:none}.agd-sidebar-nav__link{display:flex;align-items:center;gap:var(--agd-space-2);min-height:var(--agd-control-h);padding:0 var(--agd-space-3);border-radius:var(--agd-radius-md);color:var(--agd-color-text);text-decoration:none}.agd-sidebar-nav__link:hover{background:var(--agd-color-surface-hover)}.agd-sidebar-nav__link[aria-current=page]{background:var(--agd-color-accent-subtle);color:var(--agd-color-accent-text);font-weight:var(--agd-font-weight-semibold)}.agd-toolbar{display:inline-flex;align-items:center;gap:var(--agd-space-1);padding:var(--agd-space-1);border:1px solid var(--agd-color-border);border-radius:var(--agd-radius-md);background:var(--agd-color-surface)}.agd-toolbar__separator{align-self:stretch;width:1px;margin:var(--agd-space-1);background:var(--agd-color-border)}.agd-toolbar__group{display:inline-flex;align-items:center;gap:var(--agd-space-1)}.agd-button[aria-pressed=true]{box-shadow:inset 0 0 0 1px var(--button-border);font-weight:var(--agd-font-weight-semibold);--button-bg: var(--agd-color-accent-subtle);--button-bg-hover: var(--agd-color-accent-subtle);--button-fg: var(--agd-color-accent-text);--button-border: var(--agd-color-accent)}.agd-empty{display:grid;justify-items:center;gap:var(--agd-space-3);padding:var(--agd-space-12) var(--agd-space-6);text-align:center}.agd-empty__title{font-size:var(--agd-font-size-lg)}.agd-empty__description{max-width:28rem;color:var(--agd-color-text-muted)}.agd-files{margin:0;padding:0;list-style:none;border-top:1px solid var(--agd-color-border)}.agd-file-row{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto auto;align-items:center;gap:var(--agd-space-4);min-height:3rem;padding:var(--agd-space-1) var(--agd-space-2);border-bottom:1px solid var(--agd-color-border)}.agd-file-row:hover{background:var(--agd-color-surface-sunken)}.agd-file-row__icon{display:inline-flex;color:var(--agd-color-text-muted)}.agd-file-row__name{min-height:1.5rem;overflow:hidden;color:var(--agd-color-text);font-weight:var(--agd-font-weight-medium);text-overflow:ellipsis;white-space:nowrap}.agd-file-row__meta,.agd-file-row__time{display:inline-flex;align-items:center;gap:var(--agd-space-2);color:var(--agd-color-text-muted);font-size:var(--agd-font-size-xs)}.agd-file-row__actions{display:inline-flex}@media(max-width:47.99rem){.agd-file-row{grid-template-columns:auto minmax(0,1fr) auto;grid-template-areas:"icon name actions" ". meta meta" ". time time"}.agd-file-row__icon{grid-area:icon}.agd-file-row__name{grid-area:name}.agd-file-row__meta{grid-area:meta}.agd-file-row__time{grid-area:time}.agd-file-row__actions{grid-area:actions}}.agd-filetable{width:100%;table-layout:fixed;border-collapse:collapse;border-top:1px solid var(--agd-color-border)}.agd-filetable th,.agd-filetable td{padding:var(--agd-space-1) var(--agd-space-3);border-bottom:1px solid var(--agd-color-border);text-align:start;vertical-align:middle}.agd-filetable th{color:var(--agd-color-text-muted);font-size:var(--agd-font-size-xs);font-weight:var(--agd-font-weight-semibold)}.agd-filetable th:nth-child(1){width:36%}.agd-filetable th:nth-child(2){width:36%}.agd-filetable th:nth-child(3){width:16%}.agd-filetable th:nth-child(4){width:12%}.agd-filetable td{height:3rem}.agd-filetable td:first-child{overflow:hidden}.agd-filetable .agd-chip{flex-wrap:wrap;row-gap:0}.agd-filetable tbody tr:hover{background:var(--agd-color-surface-sunken)}.agd-filetable__sort{display:inline-flex;align-items:center;gap:var(--agd-space-1);min-height:var(--agd-control-h);padding:0 var(--agd-space-2);border:0;border-radius:var(--agd-radius-md);background:none;color:inherit;font:inherit;cursor:pointer}.agd-filetable__sort:hover{background:var(--agd-color-surface-hover)}.agd-filetable__arrow{display:inline-block;min-width:1ch}.agd-filetable__name{display:flex;align-items:center;gap:var(--agd-space-3);min-width:0}.agd-filetable__name .agd-file-row__name{min-width:0;flex:1 1 auto}.agd-filetable td:has(.agd-skeleton){padding-block:var(--agd-space-3)}.agd-filegrid-wrap{display:grid;gap:var(--agd-space-4)}.agd-filegrid-wrap>.agd-field{max-width:16rem}.agd-filegrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(14rem,1fr));gap:var(--agd-space-4);margin:0;padding:0;list-style:none}.agd-filegrid__item{display:grid;align-content:start;gap:var(--agd-space-2);min-height:7rem;padding:var(--agd-space-3);border:1px solid var(--agd-color-border);border-radius:var(--agd-radius-md);background:var(--agd-color-surface)}.agd-filegrid__head{display:flex;align-items:center;gap:var(--agd-space-2);min-width:0}.agd-filegrid__item .agd-file-row__actions{justify-self:end}.agd-skeleton{display:block;height:1rem;border-radius:var(--agd-radius-sm);background:var(--agd-color-surface-hover);animation:agd-pulse 1.4s ease-in-out infinite}.agd-filegrid__item.agd-skeleton{height:auto;min-height:7rem;border:1px solid var(--agd-color-border);border-radius:var(--agd-radius-md)}@keyframes agd-pulse{50%{opacity:.5}}@media(max-width:47.99rem){.agd-filetable,.agd-filetable tbody,.agd-filetable tr,.agd-filetable thead{display:block}.agd-filetable thead tr{display:flex;flex-wrap:wrap}.agd-filetable thead th:last-child{display:none}.agd-filetable thead th{width:auto}.agd-filetable tbody tr{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"name actions" "owner owner" "time time";padding-block:var(--agd-space-1);border-bottom:1px solid var(--agd-color-border)}.agd-filetable tbody td{padding:var(--agd-space-1) var(--agd-space-3);border-bottom:0}.agd-filetable tbody td:nth-child(1){grid-area:name}.agd-filetable tbody td:nth-child(2){grid-area:owner}.agd-filetable tbody td:nth-child(3){grid-area:time}.agd-filetable tbody td:nth-child(4){grid-area:actions}}.agd-avatar{display:inline-grid;flex:none;place-items:center;width:1.5rem;height:1.5rem;border:1px solid var(--agd-color-border-strong);background:var(--agd-color-surface-sunken);color:var(--agd-color-text);font-size:var(--agd-font-size-xs);font-weight:var(--agd-font-weight-medium);line-height:1}.agd-avatar svg{width:.9rem;height:.9rem}.agd-avatar--person{border-radius:var(--agd-radius-full)}.agd-avatar--agent{border-color:var(--agd-color-agent);border-radius:var(--agd-radius-sm);background:var(--agd-color-agent-subtle);color:var(--agd-color-agent-text)}.agd-avatar--more{border-radius:var(--agd-radius-full);background:var(--agd-color-surface);color:var(--agd-color-text-muted)}.agd-chip{display:inline-flex;align-items:center;gap:var(--agd-space-2);max-width:100%;min-width:0}.agd-chip__name{overflow:hidden;color:var(--agd-color-text);font-weight:var(--agd-font-weight-medium);text-overflow:ellipsis;white-space:nowrap}.agd-chip__meta{color:var(--agd-color-text-muted);font-size:var(--agd-font-size-xs);white-space:nowrap}.agd-pill{flex:none;padding:.125rem var(--agd-space-2);border:1px solid var(--agd-color-agent);border-radius:var(--agd-radius-full);color:var(--agd-color-agent-text);font-size:var(--agd-font-size-xs);font-weight:var(--agd-font-weight-semibold);letter-spacing:.02em;line-height:1.2;text-transform:uppercase}.agd-agent-badge{display:inline-flex;align-items:center;gap:var(--agd-space-2);max-width:100%;padding:.125rem var(--agd-space-2) .125rem .125rem;border:1px solid var(--agd-color-agent);border-radius:var(--agd-radius-md);background:var(--agd-color-agent-subtle);color:var(--agd-color-agent-text);font-size:var(--agd-font-size-xs)}.agd-agent-badge--compact{padding:0;border:0;background:none}.agd-agent-badge__label{font-weight:var(--agd-font-weight-semibold);white-space:nowrap}.agd-agent-badge__meta{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.agd-title{display:inline-grid;min-width:0;max-width:100%}.agd-title__button,.agd-title__input,.agd-title__text{min-width:0;padding:var(--agd-space-1) var(--agd-space-2);font:inherit;font-size:var(--agd-font-size-lg);font-weight:var(--agd-font-weight-semibold)}.agd-title__button{border:1px solid transparent;border-radius:var(--agd-radius-md);background:none;color:var(--agd-color-text);cursor:text;text-align:start}.agd-title__button:hover{border-color:var(--agd-color-border-strong)}.agd-title__text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.agd-title__input{width:min(28rem,100%);border:1px solid var(--agd-color-border-strong);border-radius:var(--agd-radius-md);background:var(--agd-color-surface-raised);color:var(--agd-color-text)}.agd-title__input[aria-invalid=true]{border-color:var(--agd-color-danger-text)}.agd-title__error{padding-inline:var(--agd-space-2);color:var(--agd-color-danger-text);font-size:var(--agd-font-size-xs)}.agd-stack{display:inline-flex;align-items:center;gap:var(--agd-space-3)}.agd-stack__list{display:flex;margin:0;padding:0;list-style:none}.agd-stack__list li+li{margin-inline-start:-.25rem}.agd-stack__list .agd-avatar{width:1.75rem;height:1.75rem;box-shadow:0 0 0 2px var(--agd-color-bg)}.agd-stack__summary{color:var(--agd-color-text-muted);font-size:var(--agd-font-size-xs);white-space:nowrap}@media(forced-colors:active){.agd-checkbox:checked,.agd-switch:checked{background:Highlight;border-color:Highlight}.agd-checkbox:before{background:HighlightText}.agd-switch{background:Canvas;border-color:ButtonText}.agd-switch:before{background:ButtonText}.agd-switch:checked:before{background:HighlightText}.agd-button[aria-busy=true]{border-style:dashed}.agd-button[aria-pressed=true]{background:Highlight;color:HighlightText;border-color:Highlight}.agd-tabs__trigger[data-state=active]:after{background:Highlight}.agd-skeleton{background:GrayText}.agd-filegrid__item,.agd-agent-badge,.agd-title__button:hover,.agd-title__input{border-color:CanvasText}.agd-agent-badge--compact{border:0}.agd-menu__item[data-highlighted]{outline:2px solid Highlight;outline-offset:-2px}}.agd-dialog:has(.agd-share){width:min(36rem,calc(100vw - 2rem))}.agd-share{display:grid;gap:var(--agd-space-4)}.agd-share__invite{display:grid;grid-template-columns:minmax(0,1fr) auto auto;align-items:start;gap:var(--agd-space-3)}.agd-share__invite .agd-field:first-child{grid-column:1 / -1}.agd-share__invite .agd-button{align-self:end}.agd-share__sent{color:var(--agd-color-success-text);font-size:var(--agd-font-size-xs)}.agd-share__people{display:grid;margin:0;padding:0;list-style:none;border-top:1px solid var(--agd-color-border)}.agd-share__people li{display:flex;align-items:center;justify-content:space-between;gap:var(--agd-space-3);padding:var(--agd-space-2) 0;border-bottom:1px solid var(--agd-color-border)}.agd-share__people .agd-field{min-width:9rem}.agd-share__controls{display:inline-flex;align-items:center;gap:var(--agd-space-2)}.agd-share__owner{padding-inline:var(--agd-space-3);color:var(--agd-color-text-muted)}.agd-share__row{display:grid;grid-template-columns:1fr 1fr;gap:var(--agd-space-3)}.agd-share__copy{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:end;gap:var(--agd-space-3)}@media(max-width:30rem){.agd-share__invite,.agd-share__row,.agd-share__copy{grid-template-columns:1fr}}.agd-cursor{position:relative;display:inline-block;width:0;vertical-align:baseline;-webkit-user-select:none;user-select:none}.agd-cursor__caret{position:absolute;inset-block:-.2em -.15em;inset-inline-start:0;width:2px;background:var(--agd-color-accent)}.agd-cursor__tag{position:absolute;inset-block-end:1.45em;inset-inline-start:0;padding:.0625rem var(--agd-space-2);border:1px solid var(--agd-color-accent);border-radius:var(--agd-radius-sm) var(--agd-radius-sm) var(--agd-radius-sm) 0;background:var(--agd-color-accent);color:var(--agd-color-text-on-accent);font-size:var(--agd-font-size-xs);font-weight:var(--agd-font-weight-medium);line-height:1.3;white-space:nowrap}.agd-cursor--agent .agd-cursor__caret{background:var(--agd-color-agent)}.agd-cursor--agent .agd-cursor__tag{border-color:var(--agd-color-agent);border-radius:var(--agd-radius-sm);background:var(--agd-color-agent-subtle);color:var(--agd-color-agent-text)}.drive-main{max-width:72rem}.drive-muted{color:var(--agd-color-text-muted)}.drive-status{display:flex;align-items:center;gap:var(--agd-space-2);color:var(--agd-color-text-muted)}.drive-signin{display:grid;gap:var(--agd-space-4);max-width:24rem}.drive-form{display:grid;gap:var(--agd-space-4)}.drive-form__actions{display:flex;justify-content:flex-end;gap:var(--agd-space-2)}.drive-drop{min-height:60vh;border:2px dashed transparent;border-radius:var(--agd-radius-md);padding:var(--agd-space-2)}.drive-drop--over{border-color:var(--agd-color-accent);background:var(--agd-color-accent-subtle)}.drive-bar{display:flex;align-items:center;justify-content:space-between;gap:var(--agd-space-4);flex-wrap:wrap;margin-bottom:var(--agd-space-4)}.drive-bar h1{margin:0;font-size:var(--agd-font-size-xl);overflow-wrap:anywhere}.drive-crumbs ol{display:flex;flex-wrap:wrap;gap:var(--agd-space-2);list-style:none;margin:0 0 var(--agd-space-2);padding:0;color:var(--agd-color-text-muted)}.drive-crumbs li+li:before{content:"/";margin-right:var(--agd-space-2)}.drive-crumbs [aria-current=page]{color:var(--agd-color-text);font-weight:var(--agd-font-weight-semibold)}.drive-split{display:grid;grid-template-columns:14rem minmax(0,1fr);gap:var(--agd-space-6)}@media(max-width:48rem){.drive-split{grid-template-columns:1fr}}.drive-tree{list-style:none;margin:0;padding:0}.drive-tree .drive-tree{padding-left:var(--agd-space-4)}.drive-tree a{display:flex;align-items:center;gap:var(--agd-space-2);padding:var(--agd-space-1) var(--agd-space-2);border-radius:var(--agd-radius-sm);color:var(--agd-color-text);text-decoration:none}.drive-tree a:hover{background:var(--agd-color-surface-hover)}.drive-tree a[aria-current=page]{background:var(--agd-color-accent-subtle);color:var(--agd-color-accent-text);font-weight:var(--agd-font-weight-semibold)}.drive-tree svg{width:1rem;height:1rem;flex:none}.drive-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(12rem,1fr));gap:var(--agd-space-4);list-style:none;margin:0;padding:0}.drive-card{position:relative;display:grid;gap:var(--agd-space-2);padding:var(--agd-space-4);border:1px solid var(--agd-color-border);border-radius:var(--agd-radius-md);background:var(--agd-color-surface)}.drive-card__icon svg{width:2rem;height:2rem}.drive-card__name{overflow-wrap:anywhere;font-weight:var(--agd-font-weight-medium);color:var(--agd-color-text)}.drive-card__meta{font-size:var(--agd-font-size-sm);color:var(--agd-color-text-muted)}.drive-card__actions{display:flex;align-items:center;justify-content:space-between;gap:var(--agd-space-2)}.drive-root{display:grid;grid-template-columns:12rem minmax(0,1fr);gap:var(--agd-space-6);color:var(--agd-color-text)}@media(max-width:48rem){.drive-root{grid-template-columns:1fr}}