agentic-drive 0.9.0 → 0.10.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/embed.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DriveApiError,
3
3
  createClient
4
- } from "./chunk-LELTSSZF.js";
4
+ } from "./chunk-SEHT5Q5L.js";
5
5
 
6
6
  // ui/embed.tsx
7
7
  import { useEffect as useEffect3, useState as useState3 } from "react";
@@ -35,10 +35,44 @@ import {
35
35
  useToast
36
36
  } from "agentic-design/react";
37
37
 
38
+ // ui/Activity.tsx
39
+ import { jsx, jsxs } from "react/jsx-runtime";
40
+ var VERBS = {
41
+ create: "created this item",
42
+ rename: "renamed it",
43
+ move: "moved it",
44
+ update: "replaced its content",
45
+ share: "shared it",
46
+ unshare: "stopped sharing it",
47
+ delete: "moved it to the trash",
48
+ restore: "restored it"
49
+ };
50
+ function detailText(e) {
51
+ const d = e.detail ?? {};
52
+ if (e.action === "rename") return d.from === void 0 ? "" : `from "${d.from}" to "${d.to}"`;
53
+ if (e.action === "share") return d.subjectId ? `with ${d.subjectId} as ${d.role}` : "";
54
+ if (e.action === "unshare") return d.subjectId ? `from ${d.subjectId}` : "";
55
+ return "";
56
+ }
57
+ var describe = (e) => e.action === "share" && e.detail?.via === "invite" ? e.detail.role === void 0 ? "accepted an invite" : `accepted an invite and now has the role ${e.detail.role}` : `${VERBS[e.action]} ${detailText(e)}`.trim();
58
+ var AgentLabel = ({ entry }) => entry.actor.kind === "agent" ? /* @__PURE__ */ jsx("span", { className: "agd-pill", children: "AI agent" }) : null;
59
+ function ActivityList({ entries }) {
60
+ if (entries.length === 0) return /* @__PURE__ */ jsx("p", { className: "drive-muted", children: "No activity yet." });
61
+ return /* @__PURE__ */ jsx("ol", { className: "drive-activity", "aria-label": "Activity", children: entries.map((e) => /* @__PURE__ */ jsxs("li", { children: [
62
+ /* @__PURE__ */ jsx("strong", { children: e.actor.id }),
63
+ " ",
64
+ /* @__PURE__ */ jsx(AgentLabel, { entry: e }),
65
+ " ",
66
+ describe(e),
67
+ " ",
68
+ /* @__PURE__ */ jsx("time", { dateTime: new Date(e.at).toISOString(), children: new Date(e.at).toLocaleString() })
69
+ ] }, e.id)) });
70
+ }
71
+
38
72
  // ui/browse.tsx
39
73
  import { useEffect, useRef, useState } from "react";
40
74
  import { Button, FileIcon, FolderIcon, PresenceChip } from "agentic-design/react";
41
- import { jsx, jsxs } from "react/jsx-runtime";
75
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
42
76
  function sortItems(items, { key, dir }, dateOf = (i) => i.updatedAt) {
43
77
  const sign = dir === "asc" ? 1 : -1;
44
78
  const by = key === "name" ? (a, b) => a.name.localeCompare(b.name, void 0, { numeric: true }) : (a, b) => dateOf(a) - dateOf(b);
@@ -46,7 +80,7 @@ function sortItems(items, { key, dir }, dateOf = (i) => i.updatedAt) {
46
80
  }
47
81
  function Stamp({ at }) {
48
82
  const d = new Date(at);
49
- return Number.isFinite(d.getTime()) ? /* @__PURE__ */ jsx("time", { dateTime: d.toISOString(), children: dateFormat.format(d) }) : /* @__PURE__ */ jsx("span", { children: "\u2014" });
83
+ return Number.isFinite(d.getTime()) ? /* @__PURE__ */ jsx2("time", { dateTime: d.toISOString(), children: dateFormat.format(d) }) : /* @__PURE__ */ jsx2("span", { children: "\u2014" });
50
84
  }
51
85
  var dateFormat = new Intl.DateTimeFormat(void 0, { dateStyle: "medium", timeStyle: "short" });
52
86
  function ExpandableSearch({ value, onChange }) {
@@ -68,10 +102,10 @@ function ExpandableSearch({ value, onChange }) {
68
102
  setOpen(false);
69
103
  };
70
104
  if (!shown) {
71
- return /* @__PURE__ */ jsx(Button, { ref: trigger, variant: "ghost", size: "sm", onClick: () => setOpen(true), children: "Search" });
105
+ return /* @__PURE__ */ jsx2(Button, { ref: trigger, variant: "ghost", size: "sm", onClick: () => setOpen(true), children: "Search" });
72
106
  }
73
- return /* @__PURE__ */ jsxs("div", { className: "drive-search", role: "search", children: [
74
- /* @__PURE__ */ jsx(
107
+ return /* @__PURE__ */ jsxs2("div", { className: "drive-search", role: "search", children: [
108
+ /* @__PURE__ */ jsx2(
75
109
  "input",
76
110
  {
77
111
  ref: input,
@@ -86,7 +120,7 @@ function ExpandableSearch({ value, onChange }) {
86
120
  }
87
121
  }
88
122
  ),
89
- /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: close, children: "Close search" })
123
+ /* @__PURE__ */ jsx2(Button, { variant: "ghost", size: "sm", onClick: close, children: "Close search" })
90
124
  ] });
91
125
  }
92
126
  function ItemTable({ label, items, sort, onSort, selected = /* @__PURE__ */ new Set(), onSelect, href, who: who2, actions, dateOf = (i) => i.updatedAt }) {
@@ -103,48 +137,48 @@ function ItemTable({ label, items, sort, onSort, selected = /* @__PURE__ */ new
103
137
  else next.delete(id);
104
138
  onSelect(next);
105
139
  };
106
- const th = (key, text, cls) => /* @__PURE__ */ jsx("th", { scope: "col", className: cls, "aria-sort": sort.key === key ? sort.dir === "asc" ? "ascending" : "descending" : "none", children: /* @__PURE__ */ jsxs("button", { type: "button", className: "drive-sort", onClick: () => onSort(key), children: [
140
+ const th = (key, text, cls) => /* @__PURE__ */ jsx2("th", { scope: "col", className: cls, "aria-sort": sort.key === key ? sort.dir === "asc" ? "ascending" : "descending" : "none", children: /* @__PURE__ */ jsxs2("button", { type: "button", className: "drive-sort", onClick: () => onSort(key), children: [
107
141
  text,
108
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: sort.key === key ? sort.dir === "asc" ? " \u2191" : " \u2193" : "" })
142
+ /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", children: sort.key === key ? sort.dir === "asc" ? " \u2191" : " \u2193" : "" })
109
143
  ] }) });
110
- return /* @__PURE__ */ jsxs("table", { className: "drive-table", "aria-label": label, children: [
111
- /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
112
- onSelect && /* @__PURE__ */ jsx("th", { scope: "col", className: "drive-table__check", children: /* @__PURE__ */ jsx("input", { ref: head, type: "checkbox", className: "agd-checkbox", "aria-label": "Select all items", checked: all, onChange: (e) => onSelect(e.target.checked ? new Set(items.map((i) => i.id)) : /* @__PURE__ */ new Set()) }) }),
144
+ return /* @__PURE__ */ jsxs2("table", { className: "drive-table", "aria-label": label, children: [
145
+ /* @__PURE__ */ jsx2("thead", { children: /* @__PURE__ */ jsxs2("tr", { children: [
146
+ onSelect && /* @__PURE__ */ jsx2("th", { scope: "col", className: "drive-table__check", children: /* @__PURE__ */ jsx2("input", { ref: head, type: "checkbox", className: "agd-checkbox", "aria-label": "Select all items", checked: all, onChange: (e) => onSelect(e.target.checked ? new Set(items.map((i) => i.id)) : /* @__PURE__ */ new Set()) }) }),
113
147
  th("name", "Name"),
114
- /* @__PURE__ */ jsx("th", { scope: "col", className: "drive-table__who", children: "Edited by" }),
148
+ /* @__PURE__ */ jsx2("th", { scope: "col", className: "drive-table__who", children: "Edited by" }),
115
149
  th("modified", "Modified", "drive-table__date"),
116
- /* @__PURE__ */ jsx("th", { scope: "col", children: /* @__PURE__ */ jsx("span", { className: "drive-sr", children: "Actions" }) })
150
+ /* @__PURE__ */ jsx2("th", { scope: "col", children: /* @__PURE__ */ jsx2("span", { className: "drive-sr", children: "Actions" }) })
117
151
  ] }) }),
118
- /* @__PURE__ */ jsx("tbody", { children: items.map((i) => /* @__PURE__ */ jsxs("tr", { className: "drive-row", "data-selected": selected.has(i.id) || void 0, children: [
119
- onSelect && /* @__PURE__ */ jsx("td", { className: "drive-table__check", children: /* @__PURE__ */ jsx("input", { type: "checkbox", className: "agd-checkbox", "aria-label": `Select ${i.name}`, checked: selected.has(i.id), onChange: (e) => toggle(i.id, e.target.checked) }) }),
120
- /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsxs("div", { className: "drive-table__name", children: [
121
- /* @__PURE__ */ jsx("span", { className: "drive-table__icon", "aria-hidden": "true", children: i.kind === "folder" ? /* @__PURE__ */ jsx(FolderIcon, {}) : /* @__PURE__ */ jsx(FileIcon, {}) }),
122
- /* @__PURE__ */ jsx("a", { href: href(i), children: i.name })
152
+ /* @__PURE__ */ jsx2("tbody", { children: items.map((i) => /* @__PURE__ */ jsxs2("tr", { className: "drive-row", "data-selected": selected.has(i.id) || void 0, children: [
153
+ onSelect && /* @__PURE__ */ jsx2("td", { className: "drive-table__check", children: /* @__PURE__ */ jsx2("input", { type: "checkbox", className: "agd-checkbox", "aria-label": `Select ${i.name}`, checked: selected.has(i.id), onChange: (e) => toggle(i.id, e.target.checked) }) }),
154
+ /* @__PURE__ */ jsx2("td", { children: /* @__PURE__ */ jsxs2("div", { className: "drive-table__name", children: [
155
+ /* @__PURE__ */ jsx2("span", { className: "drive-table__icon", "aria-hidden": "true", children: i.kind === "folder" ? /* @__PURE__ */ jsx2(FolderIcon, {}) : /* @__PURE__ */ jsx2(FileIcon, {}) }),
156
+ /* @__PURE__ */ jsx2("a", { href: href(i), children: i.name })
123
157
  ] }) }),
124
- /* @__PURE__ */ jsx("td", { className: "drive-table__who", children: /* @__PURE__ */ jsx(PresenceChip, { entry: who2(i.updatedBy, i.owner) }) }),
125
- /* @__PURE__ */ jsx("td", { className: "drive-table__date", children: /* @__PURE__ */ jsx(Stamp, { at: dateOf(i) }) }),
126
- /* @__PURE__ */ jsx("td", { className: "drive-table__actions", children: actions(i) })
158
+ /* @__PURE__ */ jsx2("td", { className: "drive-table__who", children: /* @__PURE__ */ jsx2(PresenceChip, { entry: who2(i.updatedBy, i.owner) }) }),
159
+ /* @__PURE__ */ jsx2("td", { className: "drive-table__date", children: /* @__PURE__ */ jsx2(Stamp, { at: dateOf(i) }) }),
160
+ /* @__PURE__ */ jsx2("td", { className: "drive-table__actions", children: actions(i) })
127
161
  ] }, i.id)) })
128
162
  ] });
129
163
  }
130
164
  function BulkBar({ count, busy, onTrash, onClear }) {
131
165
  if (count === 0) return null;
132
- return /* @__PURE__ */ jsxs("div", { role: "region", "aria-label": "Selected items", className: "drive-bulk", children: [
133
- /* @__PURE__ */ jsxs("span", { role: "status", children: [
166
+ return /* @__PURE__ */ jsxs2("div", { role: "region", "aria-label": "Selected items", className: "drive-bulk", children: [
167
+ /* @__PURE__ */ jsxs2("span", { role: "status", children: [
134
168
  count,
135
169
  " selected"
136
170
  ] }),
137
- /* @__PURE__ */ jsx(Button, { variant: "danger", size: "sm", onClick: onTrash, disabled: busy, children: "Move to trash" }),
138
- /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: onClear, children: "Clear selection" })
171
+ /* @__PURE__ */ jsx2(Button, { variant: "danger", size: "sm", onClick: onTrash, disabled: busy, children: "Move to trash" }),
172
+ /* @__PURE__ */ jsx2(Button, { variant: "ghost", size: "sm", onClick: onClear, children: "Clear selection" })
139
173
  ] });
140
174
  }
141
175
 
142
176
  // ui/App.tsx
143
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
177
+ import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
144
178
  var errorText = (e) => e instanceof DriveApiError ? `${e.message} (${e.code})` : e instanceof Error ? e.message : "Something went wrong";
145
179
  var byName = (a, b) => (a.kind === "folder" ? 0 : 1) - (b.kind === "folder" ? 0 : 1) || a.name.localeCompare(b.name);
146
180
  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 };
147
- var MachineLabel = ({ item }) => item.machineMade ? /* @__PURE__ */ jsx2("span", { className: "agd-pill", children: "Created by agent" }) : null;
181
+ var MachineLabel = ({ item }) => item.machineMade ? /* @__PURE__ */ jsx3("span", { className: "agd-pill", children: "Created by agent" }) : null;
148
182
  function useLoad(fn) {
149
183
  const [state, set] = useState2({ status: "loading" });
150
184
  const [tick, setTick] = useState2(0);
@@ -158,19 +192,24 @@ function useLoad(fn) {
158
192
  return [state, () => setTick((n) => n + 1)];
159
193
  }
160
194
  function Status({ state, retry, children }) {
161
- if (state.status === "loading") return /* @__PURE__ */ jsxs2("p", { role: "status", className: "drive-status", children: [
162
- /* @__PURE__ */ jsx2("span", { className: "agd-spinner", "aria-hidden": "true" }),
195
+ if (state.status === "loading") return /* @__PURE__ */ jsxs3("p", { role: "status", className: "drive-status", children: [
196
+ /* @__PURE__ */ jsx3("span", { className: "agd-spinner", "aria-hidden": "true" }),
163
197
  " Loading\u2026"
164
198
  ] });
165
- if (state.status === "error") return /* @__PURE__ */ jsx2("div", { role: "alert", children: /* @__PURE__ */ jsx2(EmptyState, { title: "Could not load this page", description: state.error, action: /* @__PURE__ */ jsx2(Button2, { onClick: retry, children: "Try again" }) }) });
166
- return /* @__PURE__ */ jsx2(Fragment, { children });
199
+ if (state.status === "error") return /* @__PURE__ */ jsx3("div", { role: "alert", children: /* @__PURE__ */ jsx3(EmptyState, { title: "Could not load this page", description: state.error, action: /* @__PURE__ */ jsx3(Button2, { onClick: retry, children: "Try again" }) }) });
200
+ return /* @__PURE__ */ jsx3(Fragment, { children });
167
201
  }
168
202
  var routeParts = (hash) => hash.replace(/^#\/?/, "").split("/");
203
+ var goHash = (loc) => {
204
+ history.replaceState(null, "", `#/${loc}`);
205
+ dispatchEvent(new HashChangeEvent("hashchange"));
206
+ };
169
207
  function Routes({ hash, client, origin, go }) {
170
208
  const parts = routeParts(hash);
171
- if (parts[0] === "trash") return /* @__PURE__ */ jsx2(TrashView, { client }, "trash");
172
- if (parts[0] === "f" && parts[1]) return /* @__PURE__ */ jsx2(Download, { client, id: parts[1], origin, go }, hash);
173
- return /* @__PURE__ */ jsx2(Browser, { client, loc: parts[0] || "/", origin }, hash);
209
+ if (parts[0] === "trash") return /* @__PURE__ */ jsx3(TrashView, { client }, "trash");
210
+ if (parts[0] === "a" && parts[1]) return /* @__PURE__ */ jsx3(ActivityView, { client, id: parts[1] }, hash);
211
+ if (parts[0] === "f" && parts[1]) return /* @__PURE__ */ jsx3(Download, { client, id: parts[1], origin, go }, hash);
212
+ return /* @__PURE__ */ jsx3(Browser, { client, loc: parts[0] || "/", origin }, hash);
174
213
  }
175
214
  function Browser({ client, loc, origin }) {
176
215
  const toast = useToast();
@@ -241,77 +280,78 @@ function Browser({ client, loc, origin }) {
241
280
  localStorage.setItem("agentic-drive-view", v);
242
281
  setView(v);
243
282
  };
244
- return /* @__PURE__ */ jsx2("section", { onDragOver: (e) => {
283
+ return /* @__PURE__ */ jsx3("section", { onDragOver: (e) => {
245
284
  e.preventDefault();
246
285
  setDrag(true);
247
286
  }, onDragLeave: (e) => {
248
287
  if (!e.currentTarget.contains(e.relatedTarget)) setDrag(false);
249
- }, onDrop, className: `drive-drop${drag ? " drive-drop--over" : ""}${view === "list" && selected.size ? " drive-drop--bulk" : ""}`, "aria-label": "Files", children: /* @__PURE__ */ jsx2(Status, { state, retry: reload, children: state.status === "ok" && (() => {
288
+ }, onDrop, className: `drive-drop${drag ? " drive-drop--over" : ""}${view === "list" && selected.size ? " drive-drop--bulk" : ""}`, "aria-label": "Files", children: /* @__PURE__ */ jsx3(Status, { state, retry: reload, children: state.status === "ok" && (() => {
250
289
  const { folder, root, crumbs, tree } = state.data;
251
290
  const needle = query.trim().toLowerCase();
252
291
  const items = sortItems(state.data.items.filter((i) => i.name.toLowerCase().includes(needle)), sort);
253
292
  const picked = items.filter((i) => selected.has(i.id)).map((i) => i.id);
254
- const actions = (item) => /* @__PURE__ */ jsxs2(Fragment, { children: [
255
- /* @__PURE__ */ jsx2(MachineLabel, { item }),
256
- /* @__PURE__ */ jsx2(Menu, { align: "end", trigger: /* @__PURE__ */ jsx2(IconButton, { label: `Actions for ${item.name}`, icon: /* @__PURE__ */ jsx2(MoreIcon, {}), variant: "ghost" }), items: [
293
+ const actions = (item) => /* @__PURE__ */ jsxs3(Fragment, { children: [
294
+ /* @__PURE__ */ jsx3(MachineLabel, { item }),
295
+ /* @__PURE__ */ jsx3(Menu, { align: "end", trigger: /* @__PURE__ */ jsx3(IconButton, { label: `Actions for ${item.name}`, icon: /* @__PURE__ */ jsx3(MoreIcon, {}), variant: "ghost" }), items: [
257
296
  { label: "Rename", onSelect: () => setDlg({ kind: "rename", item }) },
258
297
  { label: "Move", onSelect: () => setDlg({ kind: "move", item }) },
298
+ { label: "Activity", onSelect: () => goHash(`a/${item.id}`) },
259
299
  { label: "Share", onSelect: () => setDlg({ kind: "share", item }) },
260
300
  "separator",
261
301
  { label: "Move to trash", danger: true, onSelect: () => void act(() => client.trash(item.id), `Moved ${item.name} to trash`) }
262
302
  ] })
263
303
  ] });
264
304
  const href = (i) => i.kind === "folder" ? `#/${i.id}` : `#/f/${i.id}`;
265
- const level = (id) => /* @__PURE__ */ jsx2("ul", { className: "drive-tree", children: (tree.get(id) ?? []).map((n) => /* @__PURE__ */ jsxs2("li", { children: [
266
- /* @__PURE__ */ jsxs2("a", { href: `#/${n.id}`, "aria-current": n.id === folder.id ? "page" : void 0, children: [
267
- /* @__PURE__ */ jsx2(FolderIcon2, { "aria-hidden": "true" }),
305
+ const level = (id) => /* @__PURE__ */ jsx3("ul", { className: "drive-tree", children: (tree.get(id) ?? []).map((n) => /* @__PURE__ */ jsxs3("li", { children: [
306
+ /* @__PURE__ */ jsxs3("a", { href: `#/${n.id}`, "aria-current": n.id === folder.id ? "page" : void 0, children: [
307
+ /* @__PURE__ */ jsx3(FolderIcon2, { "aria-hidden": "true" }),
268
308
  " ",
269
309
  n.name
270
310
  ] }),
271
311
  tree.has(n.id) && level(n.id)
272
312
  ] }, n.id)) });
273
- return /* @__PURE__ */ jsxs2(Fragment, { children: [
274
- /* @__PURE__ */ jsx2("nav", { "aria-label": "Breadcrumb", className: "drive-crumbs", children: /* @__PURE__ */ jsxs2("ol", { children: [
275
- /* @__PURE__ */ jsx2("li", { children: crumbs.length ? /* @__PURE__ */ jsx2("a", { href: "#/", children: "My files" }) : /* @__PURE__ */ jsx2("span", { "aria-current": "page", children: "My files" }) }),
276
- crumbs.map((c, i) => /* @__PURE__ */ jsx2("li", { children: i === crumbs.length - 1 ? /* @__PURE__ */ jsx2("span", { "aria-current": "page", children: c.name }) : /* @__PURE__ */ jsx2("a", { href: `#/${c.id}`, children: c.name }) }, c.id))
313
+ return /* @__PURE__ */ jsxs3(Fragment, { children: [
314
+ /* @__PURE__ */ jsx3("nav", { "aria-label": "Breadcrumb", className: "drive-crumbs", children: /* @__PURE__ */ jsxs3("ol", { children: [
315
+ /* @__PURE__ */ jsx3("li", { children: crumbs.length ? /* @__PURE__ */ jsx3("a", { href: "#/", children: "My files" }) : /* @__PURE__ */ jsx3("span", { "aria-current": "page", children: "My files" }) }),
316
+ crumbs.map((c, i) => /* @__PURE__ */ jsx3("li", { children: i === crumbs.length - 1 ? /* @__PURE__ */ jsx3("span", { "aria-current": "page", children: c.name }) : /* @__PURE__ */ jsx3("a", { href: `#/${c.id}`, children: c.name }) }, c.id))
277
317
  ] }) }),
278
- /* @__PURE__ */ jsxs2("div", { className: "drive-bar", children: [
279
- /* @__PURE__ */ jsxs2("div", { className: "drive-title", children: [
280
- /* @__PURE__ */ jsx2("h1", { children: folder.id === root.id ? "My files" : folder.name }),
281
- folder.id !== root.id && /* @__PURE__ */ jsx2(Button2, { variant: "secondary", size: "sm", onClick: () => setDlg({ kind: "share", item: folder }), children: "Share" })
318
+ /* @__PURE__ */ jsxs3("div", { className: "drive-bar", children: [
319
+ /* @__PURE__ */ jsxs3("div", { className: "drive-title", children: [
320
+ /* @__PURE__ */ jsx3("h1", { children: folder.id === root.id ? "My files" : folder.name }),
321
+ folder.id !== root.id && /* @__PURE__ */ jsx3(Button2, { variant: "secondary", size: "sm", onClick: () => setDlg({ kind: "share", item: folder }), children: "Share" })
282
322
  ] }),
283
- /* @__PURE__ */ jsxs2(Toolbar, { label: "Folder actions", children: [
284
- /* @__PURE__ */ jsx2(ToolbarButton, { label: "New folder", icon: /* @__PURE__ */ jsx2(PlusIcon, {}), onClick: () => setDlg({ kind: "mkdir" }) }),
285
- /* @__PURE__ */ jsx2(ToolbarButton, { label: "Upload files", icon: /* @__PURE__ */ jsx2(FileIcon2, {}), onClick: () => input.current?.click(), disabled: busy }),
286
- /* @__PURE__ */ jsx2(ToolbarButton, { label: "List view", icon: /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", children: "\u2630" }), pressed: view === "list", onClick: () => setViewMode("list") }),
287
- /* @__PURE__ */ jsx2(ToolbarButton, { label: "Grid view", icon: /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", children: "\u25A6" }), pressed: view === "grid", onClick: () => setViewMode("grid") })
323
+ /* @__PURE__ */ jsxs3(Toolbar, { label: "Folder actions", children: [
324
+ /* @__PURE__ */ jsx3(ToolbarButton, { label: "New folder", icon: /* @__PURE__ */ jsx3(PlusIcon, {}), onClick: () => setDlg({ kind: "mkdir" }) }),
325
+ /* @__PURE__ */ jsx3(ToolbarButton, { label: "Upload files", icon: /* @__PURE__ */ jsx3(FileIcon2, {}), onClick: () => input.current?.click(), disabled: busy }),
326
+ /* @__PURE__ */ jsx3(ToolbarButton, { label: "List view", icon: /* @__PURE__ */ jsx3("span", { "aria-hidden": "true", children: "\u2630" }), pressed: view === "list", onClick: () => setViewMode("list") }),
327
+ /* @__PURE__ */ jsx3(ToolbarButton, { label: "Grid view", icon: /* @__PURE__ */ jsx3("span", { "aria-hidden": "true", children: "\u25A6" }), pressed: view === "grid", onClick: () => setViewMode("grid") })
288
328
  ] }),
289
- /* @__PURE__ */ jsx2("input", { ref: input, type: "file", multiple: true, hidden: true, "aria-label": "Choose files to upload", onChange: (e) => {
329
+ /* @__PURE__ */ jsx3("input", { ref: input, type: "file", multiple: true, hidden: true, "aria-label": "Choose files to upload", onChange: (e) => {
290
330
  if (e.target.files) void upload(e.target.files);
291
331
  e.target.value = "";
292
332
  } })
293
333
  ] }),
294
- /* @__PURE__ */ jsxs2("div", { className: "drive-split", children: [
295
- /* @__PURE__ */ jsx2("nav", { "aria-label": "Folders", className: "drive-folders", children: level(root.id) }),
296
- /* @__PURE__ */ jsxs2("div", { children: [
297
- /* @__PURE__ */ jsx2("div", { className: "drive-tools", children: /* @__PURE__ */ jsx2(ExpandableSearch, { value: query, onChange: setQuery }) }),
298
- /* @__PURE__ */ jsx2("p", { role: "status", className: "drive-sr", children: needle ? `${items.length} of ${state.data.items.length} items match` : "" }),
299
- state.data.items.length === 0 ? /* @__PURE__ */ jsx2(EmptyState, { title: "This folder is empty", description: "Drop files here, or use Upload files.", action: /* @__PURE__ */ jsx2(Button2, { onClick: () => input.current?.click(), disabled: busy, children: "Upload files" }) }) : items.length === 0 ? /* @__PURE__ */ jsx2(EmptyState, { title: "Nothing matches", description: `No item in this folder has \u201C${query.trim()}\u201D in its name.`, action: /* @__PURE__ */ jsx2(Button2, { onClick: () => setQuery(""), children: "Clear search" }) }) : view === "list" ? /* @__PURE__ */ jsx2(ItemTable, { label: `Items in ${folder.name || "My files"}`, items, sort, onSort, selected, onSelect: setSelected, href, who, actions }) : /* @__PURE__ */ jsx2("ul", { className: "drive-grid", "aria-label": `Items in ${folder.name || "My files"}`, children: items.map((i) => /* @__PURE__ */ jsxs2("li", { className: "drive-card", children: [
300
- /* @__PURE__ */ jsx2("span", { className: "drive-card__icon", "aria-hidden": "true", children: i.kind === "folder" ? /* @__PURE__ */ jsx2(FolderIcon2, {}) : /* @__PURE__ */ jsx2(FileIcon2, {}) }),
301
- /* @__PURE__ */ jsx2("a", { href: href(i), className: "drive-card__name", children: i.name }),
302
- /* @__PURE__ */ jsxs2("span", { className: "drive-card__meta", children: [
334
+ /* @__PURE__ */ jsxs3("div", { className: "drive-split", children: [
335
+ /* @__PURE__ */ jsx3("nav", { "aria-label": "Folders", className: "drive-folders", children: level(root.id) }),
336
+ /* @__PURE__ */ jsxs3("div", { children: [
337
+ /* @__PURE__ */ jsx3("div", { className: "drive-tools", children: /* @__PURE__ */ jsx3(ExpandableSearch, { value: query, onChange: setQuery }) }),
338
+ /* @__PURE__ */ jsx3("p", { role: "status", className: "drive-sr", children: needle ? `${items.length} of ${state.data.items.length} items match` : "" }),
339
+ state.data.items.length === 0 ? /* @__PURE__ */ jsx3(EmptyState, { title: "This folder is empty", description: "Drop files here, or use Upload files.", action: /* @__PURE__ */ jsx3(Button2, { onClick: () => input.current?.click(), disabled: busy, children: "Upload files" }) }) : items.length === 0 ? /* @__PURE__ */ jsx3(EmptyState, { title: "Nothing matches", description: `No item in this folder has \u201C${query.trim()}\u201D in its name.`, action: /* @__PURE__ */ jsx3(Button2, { onClick: () => setQuery(""), children: "Clear search" }) }) : view === "list" ? /* @__PURE__ */ jsx3(ItemTable, { label: `Items in ${folder.name || "My files"}`, items, sort, onSort, selected, onSelect: setSelected, href, who, actions }) : /* @__PURE__ */ jsx3("ul", { className: "drive-grid", "aria-label": `Items in ${folder.name || "My files"}`, children: items.map((i) => /* @__PURE__ */ jsxs3("li", { className: "drive-card", children: [
340
+ /* @__PURE__ */ jsx3("span", { className: "drive-card__icon", "aria-hidden": "true", children: i.kind === "folder" ? /* @__PURE__ */ jsx3(FolderIcon2, {}) : /* @__PURE__ */ jsx3(FileIcon2, {}) }),
341
+ /* @__PURE__ */ jsx3("a", { href: href(i), className: "drive-card__name", children: i.name }),
342
+ /* @__PURE__ */ jsxs3("span", { className: "drive-card__meta", children: [
303
343
  "Edited by ",
304
- /* @__PURE__ */ jsx2(PresenceChip2, { entry: who(i.updatedBy, i.owner) })
344
+ /* @__PURE__ */ jsx3(PresenceChip2, { entry: who(i.updatedBy, i.owner) })
305
345
  ] }),
306
- /* @__PURE__ */ jsx2("span", { className: "drive-card__actions", children: actions(i) })
346
+ /* @__PURE__ */ jsx3("span", { className: "drive-card__actions", children: actions(i) })
307
347
  ] }, i.id)) })
308
348
  ] })
309
349
  ] }),
310
- view === "list" && /* @__PURE__ */ jsx2(BulkBar, { count: picked.length, busy, onTrash: () => void trashSelected(picked), onClear: () => setSelected(/* @__PURE__ */ new Set()) }),
311
- dlg?.kind === "mkdir" && /* @__PURE__ */ jsx2(Prompt, { open: true, title: "New folder", label: "Folder name", initial: "", submit: "Create", onClose: () => setDlg(null), onSubmit: (name) => act(() => client.mkdir(folder.id === root.id ? `/${name}` : `${folder.id}/${name}`), `Created ${name}`) }),
312
- dlg?.kind === "rename" && /* @__PURE__ */ jsx2(Prompt, { open: true, title: "Rename", label: "New name", initial: dlg.item.name, submit: "Rename", onClose: () => setDlg(null), onSubmit: (name) => act(() => client.move(dlg.item.id, dlg.item.parentId, { name }), `Renamed to ${name}`) }),
313
- dlg?.kind === "move" && /* @__PURE__ */ jsx2(MoveDialog, { client, item: dlg.item, onClose: () => setDlg(null), onMove: (to) => act(() => client.move(dlg.item.id, to), `Moved ${dlg.item.name}`) }),
314
- dlg?.kind === "share" && /* @__PURE__ */ jsx2(Sharing, { client, item: dlg.item, origin, onClose: () => setDlg(null) })
350
+ view === "list" && /* @__PURE__ */ jsx3(BulkBar, { count: picked.length, busy, onTrash: () => void trashSelected(picked), onClear: () => setSelected(/* @__PURE__ */ new Set()) }),
351
+ dlg?.kind === "mkdir" && /* @__PURE__ */ jsx3(Prompt, { open: true, title: "New folder", label: "Folder name", initial: "", submit: "Create", onClose: () => setDlg(null), onSubmit: (name) => act(() => client.mkdir(folder.id === root.id ? `/${name}` : `${folder.id}/${name}`), `Created ${name}`) }),
352
+ dlg?.kind === "rename" && /* @__PURE__ */ jsx3(Prompt, { open: true, title: "Rename", label: "New name", initial: dlg.item.name, submit: "Rename", onClose: () => setDlg(null), onSubmit: (name) => act(() => client.move(dlg.item.id, dlg.item.parentId, { name }), `Renamed to ${name}`) }),
353
+ dlg?.kind === "move" && /* @__PURE__ */ jsx3(MoveDialog, { client, item: dlg.item, onClose: () => setDlg(null), onMove: (to) => act(() => client.move(dlg.item.id, to), `Moved ${dlg.item.name}`) }),
354
+ dlg?.kind === "share" && /* @__PURE__ */ jsx3(Sharing, { client, item: dlg.item, origin, onClose: () => setDlg(null) })
315
355
  ] });
316
356
  })() }) });
317
357
  }
@@ -328,16 +368,16 @@ function Prompt({ open, title, label, initial, submit, onClose, onSubmit }) {
328
368
  sent.current = false;
329
369
  });
330
370
  };
331
- return /* @__PURE__ */ jsx2(Dialog, { open: !!open, onOpenChange: (o) => {
371
+ return /* @__PURE__ */ jsx3(Dialog, { open: !!open, onOpenChange: (o) => {
332
372
  if (!o) onClose();
333
- }, title, children: /* @__PURE__ */ jsxs2("form", { onSubmit: (e) => {
373
+ }, title, children: /* @__PURE__ */ jsxs3("form", { onSubmit: (e) => {
334
374
  e.preventDefault();
335
375
  if (!sent.current) send(value.trim());
336
376
  }, className: "drive-form", children: [
337
- /* @__PURE__ */ jsx2(Input, { label, value, onChange: (e) => setValue(e.target.value), error: problem, required: true }),
338
- /* @__PURE__ */ jsxs2("div", { className: "drive-form__actions", children: [
339
- /* @__PURE__ */ jsx2(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx2(Button2, { variant: "ghost", type: "button", children: "Cancel" }) }),
340
- /* @__PURE__ */ jsx2(Button2, { type: "submit", children: submit })
377
+ /* @__PURE__ */ jsx3(Input, { label, value, onChange: (e) => setValue(e.target.value), error: problem, required: true }),
378
+ /* @__PURE__ */ jsxs3("div", { className: "drive-form__actions", children: [
379
+ /* @__PURE__ */ jsx3(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx3(Button2, { variant: "ghost", type: "button", children: "Cancel" }) }),
380
+ /* @__PURE__ */ jsx3(Button2, { type: "submit", children: submit })
341
381
  ] })
342
382
  ] }) });
343
383
  }
@@ -350,9 +390,9 @@ function MoveDialog({ client, item, onClose, onMove }) {
350
390
  });
351
391
  const [to, setTo] = useState2("/");
352
392
  const sent = useRef2(false);
353
- return /* @__PURE__ */ jsx2(Dialog, { open: true, onOpenChange: (o) => {
393
+ return /* @__PURE__ */ jsx3(Dialog, { open: true, onOpenChange: (o) => {
354
394
  if (!o) onClose();
355
- }, title: `Move ${item.name}`, children: /* @__PURE__ */ jsx2(Status, { state: folders, retry, children: folders.status === "ok" && /* @__PURE__ */ jsxs2("form", { onSubmit: (e) => {
395
+ }, title: `Move ${item.name}`, children: /* @__PURE__ */ jsx3(Status, { state: folders, retry, children: folders.status === "ok" && /* @__PURE__ */ jsxs3("form", { onSubmit: (e) => {
356
396
  e.preventDefault();
357
397
  if (sent.current) return;
358
398
  sent.current = true;
@@ -360,10 +400,10 @@ function MoveDialog({ client, item, onClose, onMove }) {
360
400
  sent.current = false;
361
401
  });
362
402
  }, className: "drive-form", children: [
363
- /* @__PURE__ */ jsx2(Select, { label: "Move to", value: to, onChange: (e) => setTo(e.target.value), children: folders.data.map((x) => /* @__PURE__ */ jsx2("option", { value: x.id, children: x.path === "/" ? "My files" : x.path }, x.id)) }),
364
- /* @__PURE__ */ jsxs2("div", { className: "drive-form__actions", children: [
365
- /* @__PURE__ */ jsx2(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx2(Button2, { variant: "ghost", type: "button", children: "Cancel" }) }),
366
- /* @__PURE__ */ jsx2(Button2, { type: "submit", children: "Move" })
403
+ /* @__PURE__ */ jsx3(Select, { label: "Move to", value: to, onChange: (e) => setTo(e.target.value), children: folders.data.map((x) => /* @__PURE__ */ jsx3("option", { value: x.id, children: x.path === "/" ? "My files" : x.path }, x.id)) }),
404
+ /* @__PURE__ */ jsxs3("div", { className: "drive-form__actions", children: [
405
+ /* @__PURE__ */ jsx3(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx3(Button2, { variant: "ghost", type: "button", children: "Cancel" }) }),
406
+ /* @__PURE__ */ jsx3(Button2, { type: "submit", children: "Move" })
367
407
  ] })
368
408
  ] }) }) });
369
409
  }
@@ -402,7 +442,7 @@ function Sharing({ client, item, origin, onClose }) {
402
442
  url: current.token ? `${origin}/#/s/${item.id}/${current.token}` : "Turn the link off and on to make a new one. The address shows once.",
403
443
  expiresAt: live?.expiresAt ? new Date(live.expiresAt) : null
404
444
  };
405
- return /* @__PURE__ */ jsx2(
445
+ return /* @__PURE__ */ jsx3(
406
446
  ShareDialog,
407
447
  {
408
448
  open: true,
@@ -445,14 +485,25 @@ function TrashView({ client }) {
445
485
  }
446
486
  reload();
447
487
  };
448
- return /* @__PURE__ */ jsxs2("section", { "aria-label": "Trash", children: [
449
- /* @__PURE__ */ jsx2("h1", { children: "Trash" }),
450
- /* @__PURE__ */ jsx2(Status, { state, retry: reload, children: state.status === "ok" && (state.data.length === 0 ? /* @__PURE__ */ jsx2(EmptyState, { title: "The trash is empty", description: "Items you move to the trash show up here." }) : /* @__PURE__ */ jsx2(ItemTable, { label: "Items in the trash", items: sortItems(state.data, sort, trashedAt), dateOf: trashedAt, sort, onSort, href: () => "#/trash", who, actions: (i) => /* @__PURE__ */ jsxs2(Fragment, { children: [
451
- /* @__PURE__ */ jsx2(MachineLabel, { item: i }),
452
- /* @__PURE__ */ jsx2(Button2, { size: "sm", onClick: () => void restore(i), children: `Restore ${i.name}` })
488
+ return /* @__PURE__ */ jsxs3("section", { "aria-label": "Trash", children: [
489
+ /* @__PURE__ */ jsx3("h1", { children: "Trash" }),
490
+ /* @__PURE__ */ jsx3(Status, { state, retry: reload, children: state.status === "ok" && (state.data.length === 0 ? /* @__PURE__ */ jsx3(EmptyState, { title: "The trash is empty", description: "Items you move to the trash show up here." }) : /* @__PURE__ */ jsx3(ItemTable, { label: "Items in the trash", items: sortItems(state.data, sort, trashedAt), dateOf: trashedAt, sort, onSort, href: () => "#/trash", who, actions: (i) => /* @__PURE__ */ jsxs3(Fragment, { children: [
491
+ /* @__PURE__ */ jsx3(MachineLabel, { item: i }),
492
+ /* @__PURE__ */ jsx3(Button2, { size: "sm", onClick: () => void restore(i), children: `Restore ${i.name}` })
453
493
  ] }) })) })
454
494
  ] });
455
495
  }
496
+ function ActivityView({ client, id }) {
497
+ const [state, retry] = useLoad(async () => ({ item: await client.stat(id), entries: await client.listActivity(id) }));
498
+ return /* @__PURE__ */ jsx3("section", { "aria-label": "Item activity", children: /* @__PURE__ */ jsx3(Status, { state, retry, children: state.status === "ok" && /* @__PURE__ */ jsxs3(Fragment, { children: [
499
+ /* @__PURE__ */ jsxs3("h1", { children: [
500
+ "Activity: ",
501
+ state.data.item.name
502
+ ] }),
503
+ /* @__PURE__ */ jsx3("p", { children: /* @__PURE__ */ jsx3("a", { href: state.data.item.kind === "folder" ? `#/${id}` : `#/${state.data.item.parentId === "root" ? "" : state.data.item.parentId}`, children: "Back to files" }) }),
504
+ /* @__PURE__ */ jsx3(ActivityList, { entries: state.data.entries })
505
+ ] }) }) });
506
+ }
456
507
  function Download({ client, id, origin, go }) {
457
508
  const [state, retry] = useLoad(async () => {
458
509
  const item = await client.stat(id);
@@ -465,11 +516,11 @@ function Download({ client, id, origin, go }) {
465
516
  go(item.parentId);
466
517
  return item;
467
518
  });
468
- return /* @__PURE__ */ jsx2(Status, { state, retry, children: null });
519
+ return /* @__PURE__ */ jsx3(Status, { state, retry, children: null });
469
520
  }
470
521
 
471
522
  // ui/embed.tsx
472
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
523
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
473
524
  var PLACEHOLDER = "from-get-token";
474
525
  function makeClient({ baseUrl, getToken }) {
475
526
  if (typeof getToken !== "function") throw new TypeError("getToken must be a function");
@@ -495,7 +546,7 @@ function DriveBrowser({ baseUrl, getToken }) {
495
546
  setMade({ id: ++clients, client: next.client, origin: new URL(baseUrl).origin });
496
547
  return () => next.close();
497
548
  }, [baseUrl, getToken]);
498
- return made ? /* @__PURE__ */ jsx3(DriveView, { client: made.client, origin: made.origin }, made.id) : null;
549
+ return made ? /* @__PURE__ */ jsx4(DriveView, { client: made.client, origin: made.origin }, made.id) : null;
499
550
  }
500
551
  function DriveView({ client, origin }) {
501
552
  const [hash, setHash] = useState3("#/");
@@ -508,12 +559,12 @@ function DriveView({ client, origin }) {
508
559
  setHash(link.getAttribute("href"));
509
560
  };
510
561
  const place = hash.startsWith("#/trash") ? "trash" : "files";
511
- return /* @__PURE__ */ jsxs3("div", { className: "drive-root", onClick: follow, children: [
512
- /* @__PURE__ */ jsx3(SidebarNav2, { label: "Places", items: [
513
- { href: "#/", label: "My files", icon: /* @__PURE__ */ jsx3(FolderIcon3, { "aria-hidden": "true" }), current: place === "files" },
562
+ return /* @__PURE__ */ jsxs4("div", { className: "drive-root", onClick: follow, children: [
563
+ /* @__PURE__ */ jsx4(SidebarNav2, { label: "Places", items: [
564
+ { href: "#/", label: "My files", icon: /* @__PURE__ */ jsx4(FolderIcon3, { "aria-hidden": "true" }), current: place === "files" },
514
565
  { href: "#/trash", label: "Trash", current: place === "trash" }
515
566
  ] }),
516
- /* @__PURE__ */ jsx3("div", { className: "drive-main", children: /* @__PURE__ */ jsx3(Routes, { hash, client, origin, go }) })
567
+ /* @__PURE__ */ jsx4("div", { className: "drive-main", children: /* @__PURE__ */ jsx4(Routes, { hash, client, origin, go }) })
517
568
  ] });
518
569
  }
519
570
  function mount(element, options) {
@@ -522,7 +573,7 @@ function mount(element, options) {
522
573
  let open = true;
523
574
  let version = 0;
524
575
  const render = (next, client) => root.render(
525
- /* @__PURE__ */ jsx3(TooltipProvider, { children: /* @__PURE__ */ jsx3(ToastProvider, { children: /* @__PURE__ */ jsx3(DriveView, { client, origin: new URL(next.baseUrl).origin }, version++) }) })
576
+ /* @__PURE__ */ jsx4(TooltipProvider, { children: /* @__PURE__ */ jsx4(ToastProvider, { children: /* @__PURE__ */ jsx4(DriveView, { client, origin: new URL(next.baseUrl).origin }, version++) }) })
526
577
  );
527
578
  render(options, current.client);
528
579
  return {
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
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';
1
+ import { O as OnConflict, D as Drive, C as Ctx, N as Node, b as Actor } from './drive-BhMTeQ-s.js';
2
+ export { c as ACTOR_KINDS, d as Action, a as ActivityAction, A as ActivityEntry, e as ActorKind, f as Can, g as DriveDeps, h as DriveError, i as ERROR_STATUS, E as ErrorCode, R as ROOT_ID, S as SearchQuery, j as createDrive, p as parseName, k as parseSubject, s as subjectKindOf } from './drive-BhMTeQ-s.js';
3
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
+ export { DriveAccount, DriveAccountDeps, driveAccount } from './account.js';
5
6
 
6
7
  declare const VERSION: string;
7
8
 
@@ -22,7 +23,7 @@ declare function upload(drive: Drive, ctx: Ctx, path: string, source: AsyncItera
22
23
  /**
23
24
  * Everything one owner has, as a zip. `manifest.json` names the person (id and kind), lists each item with its
24
25
  * metadata and, for a file, the entry that holds its bytes, and adds what the person made in other drives, the
25
- * shares they hold, the invites they sent, and the audit entries of what they did. Only the person in person gets
26
+ * shares they hold, the invites they sent, and the audit entries of what they did. It also adds the activity log entries of their changes to items. Each has the actor kind, `human` or `agent`. An entry in the drive of another person has no names. Only the person in person gets
26
27
  * those parts, and the items of their agents that have an identity of their own (no bytes). For an agent the
27
28
  * manifest says `partial: true`. Trashed items are included and flagged.
28
29
  * Entries are named by item id, never by file name. A file whose bytes are gone is marked `missing`.
package/dist/index.js CHANGED
@@ -1,35 +1,40 @@
1
+ import {
2
+ driveAccount
3
+ } from "./chunk-ECVUDAHL.js";
1
4
  import {
2
5
  importLegacyLocal
3
6
  } from "./chunk-AB2RTTHJ.js";
4
7
  import {
5
8
  VERSION
6
- } from "./chunk-IMWV5QEH.js";
9
+ } from "./chunk-NHHBNW64.js";
10
+ import {
11
+ DEFAULT_MAX_BYTES,
12
+ buildExport,
13
+ readZip,
14
+ sniffMime,
15
+ upload,
16
+ writeZip
17
+ } from "./chunk-HJXRMOUY.js";
7
18
  import {
8
19
  ACTOR_KINDS,
9
20
  AuthError,
10
- DEFAULT_MAX_BYTES,
11
21
  DriveError,
12
22
  ERROR_STATUS,
13
23
  ROOT_ID,
14
24
  addPrincipal,
15
25
  backfillAuthorIds,
16
26
  backfillResources,
17
- buildExport,
18
27
  createDrive,
19
28
  issueKey,
20
29
  openLocal,
21
30
  parseName,
22
31
  parseSubject,
23
32
  publicNode,
24
- readZip,
25
33
  resolveToken,
26
34
  revokeKey,
27
35
  revokePrincipal,
28
- sniffMime,
29
- subjectKindOf,
30
- upload,
31
- writeZip
32
- } from "./chunk-R2DUVOJT.js";
36
+ subjectKindOf
37
+ } from "./chunk-DB4F5EWD.js";
33
38
  export {
34
39
  ACTOR_KINDS,
35
40
  AuthError,
@@ -43,6 +48,7 @@ export {
43
48
  backfillResources,
44
49
  buildExport,
45
50
  createDrive,
51
+ driveAccount,
46
52
  importLegacyLocal,
47
53
  issueKey,
48
54
  openLocal,
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-Dxy0gL0_.js';
2
+ import { D as Drive, C as Ctx } from './drive-BhMTeQ-s.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,14 +1,16 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-IMWV5QEH.js";
3
+ } from "./chunk-NHHBNW64.js";
4
+ import {
5
+ buildExport,
6
+ upload
7
+ } from "./chunk-HJXRMOUY.js";
4
8
  import {
5
9
  ACTOR_KINDS,
6
10
  DriveError,
7
- buildExport,
8
11
  inviteIdentity,
9
- publicNode,
10
- upload
11
- } from "./chunk-R2DUVOJT.js";
12
+ publicNode
13
+ } from "./chunk-DB4F5EWD.js";
12
14
 
13
15
  // src/mcp.ts
14
16
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -40,6 +42,7 @@ function createMcpServer(drive, ctx, exportDir, store) {
40
42
  }));
41
43
  tool("drive_ls", "List a folder.", { path: loc.optional() }, async ({ path }) => (await drive.list(ctx, path ?? "/")).map((n) => publicNode(n)), { readOnlyHint: true });
42
44
  tool("drive_stat", "Show one item with its metadata and who made it.", { path: loc }, async ({ path }) => publicNode(await drive.stat(ctx, path)), { readOnlyHint: true });
45
+ tool("drive_activity", "List the changes to an item, newest first: who made each one (kind human or agent), what, and when.", { path: loc, limit: z.number().int().positive().optional() }, async ({ path, limit }) => drive.listActivity(ctx, path, { limit }), { readOnlyHint: true });
43
46
  tool("drive_mkdir", "Make a folder.", { path: z.string(), parents: z.boolean().optional() }, async ({ path, parents }) => publicNode(await drive.mkdir(ctx, path, { parents })));
44
47
  tool(
45
48
  "drive_upload",
package/dist/worker.d.ts CHANGED
@@ -1,8 +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-Dxy0gL0_.js';
5
- export { g as ERROR_STATUS, E as ErrorCode, N as Node } from './drive-Dxy0gL0_.js';
4
+ import { C as Ctx, D as Drive } from './drive-BhMTeQ-s.js';
5
+ export { i as ERROR_STATUS, E as ErrorCode, N as Node } from './drive-BhMTeQ-s.js';
6
6
  export { B as BackfillOptions, a as BackfillResult, b as backfillAuthorIds, c as backfillResources } from './migrate-B79gRPMu.js';
7
7
 
8
8
  /**