agentic-drive 0.10.3 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/README.md +16 -1
- package/dist/account.d.ts +1 -1
- package/dist/{chunk-Q4ZADTVR.js → chunk-NMHARN2A.js} +1 -1
- package/dist/cli.js +1 -1
- package/dist/client.d.ts +2 -2
- package/dist/{drive-BhMTeQ-s.d.ts → drive-CS1CLfqo.d.ts} +1 -1
- package/dist/embed.d.ts +11 -3
- package/dist/embed.js +16 -12
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/worker.d.ts +2 -2
- package/llms.txt +1 -0
- package/package.json +1 -1
- package/ui-dist/assets/index-DqkvcDrx.js +49 -0
- package/ui-dist/index.html +1 -1
- package/ui-dist/assets/index-BUGWaZ49.js +0 -49
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.11.0
|
|
4
|
+
|
|
5
|
+
- Add `onOpenItem` to the public UI options. Hosts can handle reference opens in list and grid views by pointer or keyboard. Export `OnOpenItem` and `Item` from `agentic-drive/ui`. Keep the download action for unhandled items.
|
|
6
|
+
|
|
3
7
|
## 0.10.3
|
|
4
8
|
|
|
5
9
|
- Allow `agentic-design` 0.10 and `agentic-identity` 0.11 without changing the lower bounds.
|
package/README.md
CHANGED
|
@@ -248,7 +248,7 @@ view.unmount();
|
|
|
248
248
|
```
|
|
249
249
|
|
|
250
250
|
`mount` returns a `MountedDrive` handle. `DriveBrowser` is the React component;
|
|
251
|
-
`DriveUiOptions` is its configuration. The CSS path supplies its styles.
|
|
251
|
+
`DriveUiOptions` is its configuration. `OnOpenItem` is the reference-open callback type, and `Item` is its argument type. The CSS path supplies its styles.
|
|
252
252
|
|
|
253
253
|
### CLI, MCP, and adapters
|
|
254
254
|
|
|
@@ -308,6 +308,21 @@ drive.update({ baseUrl, getToken }); // use another server or callback
|
|
|
308
308
|
drive.unmount(); // remove the UI
|
|
309
309
|
```
|
|
310
310
|
|
|
311
|
+
Use `onOpenItem` to open a reference in your app. It receives the full `Item`, including `id`, `kind` (`"ref"`), and `ref` (for example, `"docs:plan"`). Return `true` to handle the action and skip the download. Return `false` or nothing to keep the built-in download action. The hook runs for reference links in the list and grid, by pointer or Enter. Files and folders keep their built-in action. Modified clicks keep their existing behavior.
|
|
312
|
+
|
|
313
|
+
```ts
|
|
314
|
+
import type { Item, OnOpenItem } from "agentic-drive/ui";
|
|
315
|
+
|
|
316
|
+
const onOpenItem: OnOpenItem = (item: Item) => {
|
|
317
|
+
if (!item.ref?.startsWith("docs:")) return false;
|
|
318
|
+
openEditor(item.ref.slice(5)); // Your app opens its editor.
|
|
319
|
+
return true;
|
|
320
|
+
};
|
|
321
|
+
drive.update({ baseUrl: location.origin, getToken: () => session.token, onOpenItem });
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
`DriveUiOptions` exports this optional hook for both `mount` and `DriveBrowser`. `update()` can replace or remove it. React hosts can change the `onOpenItem` prop without resetting the current folder. The callback is synchronous.
|
|
325
|
+
|
|
311
326
|
`getToken` returns 1 to 512 letters, digits, `-` or `_`, or `undefined` to send no `authorization` header. A bad `baseUrl` or a `getToken` that is not a function makes `mount` throw a `TypeError`. The server still checks every request against the token. The embed shows files and trash with upload, rename, move, share, and the "Created by agent" label. It has no sign-in form, because your app owns sign-in. It does not change the page address, and it has no theme switch. `agentic-design/styles.css` sets base styles for the whole page, and it follows the dark mode of the system unless your page sets `data-theme`. Add `agentic-design@">=0.8.0 <0.11.0"` to your own dependencies, because your page imports its files. The Worker sends no CORS headers, so the server must be on the origin of your page. Set `baseUrl` to the same address as `DRIVE_PUBLIC_URL`, or the UI refuses its download links. `unmount` and `update` abort the requests that run and stop an upload that has more files to send. The UI keeps the list or grid choice in `localStorage` under `agentic-drive-view`, and it has its own heading for each view. Dialogs, menus, and messages render in `document.body`, outside your element. A click with Ctrl, Cmd, Shift, or the middle button on a folder link does not open the folder. The class names start with `drive-`. The design-system classes start with `agd-`. `DriveBrowser` is the same UI as a React component. It closes its requests when it unmounts. Wrap it in `TooltipProvider` and `ToastProvider` from `agentic-design/react`. `react` and `react-dom` (version 19 or later) are optional peer dependencies. Install them in your project when you use `agentic-drive/ui`. The web UI that the Worker serves uses the same views.
|
|
312
327
|
|
|
313
328
|
### Serve the UI from the package
|
package/dist/account.d.ts
CHANGED
package/dist/cli.js
CHANGED
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { i as ErrorCode, N as Node, d as ActivityEntry, S as SearchQuery } from './drive-CS1CLfqo.js';
|
|
2
|
+
export { c as ActivityAction } from './drive-CS1CLfqo.js';
|
|
3
3
|
import 'agentic-identity';
|
|
4
4
|
|
|
5
5
|
type Role = "viewer" | "commenter" | "editor" | "owner";
|
|
@@ -380,4 +380,4 @@ declare function createDrive(deps: DriveDeps): {
|
|
|
380
380
|
}>;
|
|
381
381
|
};
|
|
382
382
|
|
|
383
|
-
export { type
|
|
383
|
+
export { type Actor as A, type Ctx as C, type Drive as D, ERROR_STATUS 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 ActivityAction as c, type ActivityEntry as d, type ActorKind as e, type Can as f, type DriveDeps as g, DriveError as h, type ErrorCode as i, createDrive as j, parseSubject as k, parseName as p, subjectKindOf as s };
|
package/dist/embed.d.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
+
import { Item } from './client.js';
|
|
3
|
+
import './drive-CS1CLfqo.js';
|
|
4
|
+
import 'agentic-identity';
|
|
5
|
+
|
|
6
|
+
/** Return true to handle a reference open; false or void keeps the download action. */
|
|
7
|
+
type OnOpenItem = (item: Item) => boolean | void;
|
|
2
8
|
|
|
3
9
|
interface DriveUiOptions {
|
|
10
|
+
/** Runs when a person activates a reference item. Return true to skip the built-in download. */
|
|
11
|
+
onOpenItem?: OnOpenItem;
|
|
4
12
|
/** The address of the drive server, for example `https://drive.example.com`. Only its origin is used. */
|
|
5
13
|
baseUrl: string;
|
|
6
14
|
/** Returns the bearer token for the next request. It runs before every request, so it can refresh a token. No token sends no `authorization` header. */
|
|
@@ -8,9 +16,9 @@ interface DriveUiOptions {
|
|
|
8
16
|
}
|
|
9
17
|
/** The folders and trash of the signed-in caller, with upload, share, and the machine-made label. It needs the tooltip and toast providers above it. `mount` adds them.
|
|
10
18
|
* It shows the root again when `baseUrl` changes. A bad `baseUrl` or `getToken` throws. Pass a stable `getToken`, because a new function makes a new client. */
|
|
11
|
-
declare function DriveBrowser({ baseUrl, getToken }: DriveUiOptions): react.JSX.Element | null;
|
|
19
|
+
declare function DriveBrowser({ baseUrl, getToken, onOpenItem }: DriveUiOptions): react.JSX.Element | null;
|
|
12
20
|
interface MountedDrive {
|
|
13
|
-
/** Show the drive with another address or
|
|
21
|
+
/** Show the drive with another address, token callback, or item-open callback. The folder the person has open resets. */
|
|
14
22
|
update(options: DriveUiOptions): void;
|
|
15
23
|
/** Remove the UI. A request that runs is aborted, and no later request starts or calls `getToken`. Calling it again does nothing. */
|
|
16
24
|
unmount(): void;
|
|
@@ -18,4 +26,4 @@ interface MountedDrive {
|
|
|
18
26
|
/** Render the drive into an element, for an app that does not use React itself. A bad `baseUrl` or `getToken` throws a `TypeError`. */
|
|
19
27
|
declare function mount(element: HTMLElement, options: DriveUiOptions): MountedDrive;
|
|
20
28
|
|
|
21
|
-
export { DriveBrowser, type DriveUiOptions, type MountedDrive, mount };
|
|
29
|
+
export { DriveBrowser, type DriveUiOptions, Item, type MountedDrive, type OnOpenItem, mount };
|
package/dist/embed.js
CHANGED
|
@@ -123,7 +123,7 @@ function ExpandableSearch({ value, onChange }) {
|
|
|
123
123
|
/* @__PURE__ */ jsx2(Button, { variant: "ghost", size: "sm", onClick: close, children: "Close search" })
|
|
124
124
|
] });
|
|
125
125
|
}
|
|
126
|
-
function ItemTable({ label, items, sort, onSort, selected = /* @__PURE__ */ new Set(), onSelect, href, who: who2, actions, dateOf = (i) => i.updatedAt }) {
|
|
126
|
+
function ItemTable({ label, items, sort, onSort, selected = /* @__PURE__ */ new Set(), onSelect, href, onOpen, who: who2, actions, dateOf = (i) => i.updatedAt }) {
|
|
127
127
|
const all = items.length > 0 && items.every((i) => selected.has(i.id));
|
|
128
128
|
const some = !all && items.some((i) => selected.has(i.id));
|
|
129
129
|
const head = useRef(null);
|
|
@@ -153,7 +153,7 @@ function ItemTable({ label, items, sort, onSort, selected = /* @__PURE__ */ new
|
|
|
153
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
154
|
/* @__PURE__ */ jsx2("td", { children: /* @__PURE__ */ jsxs2("div", { className: "drive-table__name", children: [
|
|
155
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 })
|
|
156
|
+
/* @__PURE__ */ jsx2("a", { href: href(i), onClick: (e) => onOpen?.(e, i), children: i.name })
|
|
157
157
|
] }) }),
|
|
158
158
|
/* @__PURE__ */ jsx2("td", { className: "drive-table__who", children: /* @__PURE__ */ jsx2(PresenceChip, { entry: who2(i.updatedBy, i.owner) }) }),
|
|
159
159
|
/* @__PURE__ */ jsx2("td", { className: "drive-table__date", children: /* @__PURE__ */ jsx2(Stamp, { at: dateOf(i) }) }),
|
|
@@ -204,14 +204,18 @@ var goHash = (loc) => {
|
|
|
204
204
|
history.replaceState(null, "", `#/${loc}`);
|
|
205
205
|
dispatchEvent(new HashChangeEvent("hashchange"));
|
|
206
206
|
};
|
|
207
|
-
function Routes({ hash, client, origin, go }) {
|
|
207
|
+
function Routes({ hash, client, origin, go, onOpenItem }) {
|
|
208
208
|
const parts = routeParts(hash);
|
|
209
209
|
if (parts[0] === "trash") return /* @__PURE__ */ jsx3(TrashView, { client }, "trash");
|
|
210
210
|
if (parts[0] === "a" && parts[1]) return /* @__PURE__ */ jsx3(ActivityView, { client, id: parts[1] }, hash);
|
|
211
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);
|
|
212
|
+
return /* @__PURE__ */ jsx3(Browser, { client, loc: parts[0] || "/", origin, onOpenItem }, hash);
|
|
213
213
|
}
|
|
214
|
-
function Browser({ client, loc, origin }) {
|
|
214
|
+
function Browser({ client, loc, origin, onOpenItem }) {
|
|
215
|
+
const openItem = (e, item) => {
|
|
216
|
+
if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || item.kind !== "ref") return;
|
|
217
|
+
if (onOpenItem?.(item) === true) e.preventDefault();
|
|
218
|
+
};
|
|
215
219
|
const toast = useToast();
|
|
216
220
|
const [view, setView] = useState2(() => localStorage.getItem("agentic-drive-view") === "grid" ? "grid" : "list");
|
|
217
221
|
const [dlg, setDlg] = useState2(null);
|
|
@@ -336,9 +340,9 @@ function Browser({ client, loc, origin }) {
|
|
|
336
340
|
/* @__PURE__ */ jsxs3("div", { children: [
|
|
337
341
|
/* @__PURE__ */ jsx3("div", { className: "drive-tools", children: /* @__PURE__ */ jsx3(ExpandableSearch, { value: query, onChange: setQuery }) }),
|
|
338
342
|
/* @__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: [
|
|
343
|
+
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, onOpen: openItem, 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
344
|
/* @__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 }),
|
|
345
|
+
/* @__PURE__ */ jsx3("a", { href: href(i), onClick: (e) => openItem(e, i), className: "drive-card__name", children: i.name }),
|
|
342
346
|
/* @__PURE__ */ jsxs3("span", { className: "drive-card__meta", children: [
|
|
343
347
|
"Edited by ",
|
|
344
348
|
/* @__PURE__ */ jsx3(PresenceChip2, { entry: who(i.updatedBy, i.owner) })
|
|
@@ -539,16 +543,16 @@ function makeClient({ baseUrl, getToken }) {
|
|
|
539
543
|
return { client: createClient({ baseUrl, token: PLACEHOLDER, fetch: fetchWithToken }), close: () => closed.abort() };
|
|
540
544
|
}
|
|
541
545
|
var clients = 0;
|
|
542
|
-
function DriveBrowser({ baseUrl, getToken }) {
|
|
546
|
+
function DriveBrowser({ baseUrl, getToken, onOpenItem }) {
|
|
543
547
|
const [made, setMade] = useState3();
|
|
544
548
|
useEffect3(() => {
|
|
545
549
|
const next = makeClient({ baseUrl, getToken });
|
|
546
550
|
setMade({ id: ++clients, client: next.client, origin: new URL(baseUrl).origin });
|
|
547
551
|
return () => next.close();
|
|
548
552
|
}, [baseUrl, getToken]);
|
|
549
|
-
return made ? /* @__PURE__ */ jsx4(DriveView, { client: made.client, origin: made.origin }, made.id) : null;
|
|
553
|
+
return made ? /* @__PURE__ */ jsx4(DriveView, { client: made.client, origin: made.origin, onOpenItem }, made.id) : null;
|
|
550
554
|
}
|
|
551
|
-
function DriveView({ client, origin }) {
|
|
555
|
+
function DriveView({ client, origin, onOpenItem }) {
|
|
552
556
|
const [hash, setHash] = useState3("#/");
|
|
553
557
|
const go = (loc) => setHash(`#/${loc === "/" ? "" : loc}`);
|
|
554
558
|
const follow = (e) => {
|
|
@@ -564,7 +568,7 @@ function DriveView({ client, origin }) {
|
|
|
564
568
|
{ href: "#/", label: "My files", icon: /* @__PURE__ */ jsx4(FolderIcon3, { "aria-hidden": "true" }), current: place === "files" },
|
|
565
569
|
{ href: "#/trash", label: "Trash", current: place === "trash" }
|
|
566
570
|
] }),
|
|
567
|
-
/* @__PURE__ */ jsx4("div", { className: "drive-main", children: /* @__PURE__ */ jsx4(Routes, { hash, client, origin, go }) })
|
|
571
|
+
/* @__PURE__ */ jsx4("div", { className: "drive-main", children: /* @__PURE__ */ jsx4(Routes, { hash, client, origin, go, onOpenItem }) })
|
|
568
572
|
] });
|
|
569
573
|
}
|
|
570
574
|
function mount(element, options) {
|
|
@@ -573,7 +577,7 @@ function mount(element, options) {
|
|
|
573
577
|
let open = true;
|
|
574
578
|
let version = 0;
|
|
575
579
|
const render = (next, client) => root.render(
|
|
576
|
-
/* @__PURE__ */ jsx4(TooltipProvider, { children: /* @__PURE__ */ jsx4(ToastProvider, { children: /* @__PURE__ */ jsx4(DriveView, { client, origin: new URL(next.baseUrl).origin }, version++) }) })
|
|
580
|
+
/* @__PURE__ */ jsx4(TooltipProvider, { children: /* @__PURE__ */ jsx4(ToastProvider, { children: /* @__PURE__ */ jsx4(DriveView, { client, origin: new URL(next.baseUrl).origin, onOpenItem: next.onOpenItem }, version++) }) })
|
|
577
581
|
);
|
|
578
582
|
render(options, current.client);
|
|
579
583
|
return {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { O as OnConflict, D as Drive, C as Ctx, N as Node,
|
|
2
|
-
export {
|
|
1
|
+
import { O as OnConflict, D as Drive, C as Ctx, N as Node, A as Actor } from './drive-CS1CLfqo.js';
|
|
2
|
+
export { a as ACTOR_KINDS, b as Action, c as ActivityAction, d as ActivityEntry, e as ActorKind, f as Can, g as DriveDeps, h as DriveError, E as ERROR_STATUS, i as ErrorCode, R as ROOT_ID, S as SearchQuery, j as createDrive, p as parseName, k as parseSubject, s as subjectKindOf } from './drive-CS1CLfqo.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
5
|
export { DriveAccount, DriveAccountDeps, driveAccount } from './account.js';
|
package/dist/index.js
CHANGED
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-
|
|
2
|
+
import { D as Drive, C as Ctx } from './drive-CS1CLfqo.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
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-
|
|
5
|
-
export {
|
|
4
|
+
import { C as Ctx, D as Drive } from './drive-CS1CLfqo.js';
|
|
5
|
+
export { E as ERROR_STATUS, i as ErrorCode, N as Node } from './drive-CS1CLfqo.js';
|
|
6
6
|
export { B as BackfillOptions, a as BackfillResult, b as backfillAuthorIds, c as backfillResources } from './migrate-B79gRPMu.js';
|
|
7
7
|
|
|
8
8
|
/**
|
package/llms.txt
CHANGED
|
@@ -108,6 +108,7 @@ view.unmount();
|
|
|
108
108
|
`DriveUiOptions` is its configuration. The CSS path supplies its styles. The handle
|
|
109
109
|
has `update` and `unmount` methods. The `getToken` callback runs before each request
|
|
110
110
|
and may return undefined. The UI does not change the page address or theme.
|
|
111
|
+
The optional `onOpenItem` hook receives the full `Item` for a reference link, by pointer or Enter in list and grid views. Return true to skip the download; false or void keeps it. `OnOpenItem` and `Item` are exported types from `agentic-drive/ui`. Both `update` and React props can replace the hook.
|
|
111
112
|
React 19 and React DOM 19 are optional peer dependencies.
|
|
112
113
|
|
|
113
114
|
### CLI, MCP, and adapters
|