agentic-documents 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/README.md +161 -11
- package/dist/{chunk-TFCRPEEM.js → chunk-34C47PDC.js} +1 -1
- package/dist/chunk-5IQX2W52.js +195 -0
- package/dist/chunk-6UYJV2EJ.js +163 -0
- package/dist/{chunk-R5XUTBC3.js → chunk-CN6UAW7B.js} +32 -9
- package/dist/chunk-DWVJIKVT.js +8 -0
- package/dist/{chunk-YBBQNCMC.js → chunk-GQ5E6T7Z.js} +18 -191
- package/dist/{chunk-FZA5LQV3.js → chunk-JBAQEIOH.js} +89 -12
- package/dist/chunk-KC5KFB5R.js +354 -0
- package/dist/{chunk-IU3YIQ4Y.js → chunk-V6TBTOHW.js} +38 -13
- package/dist/cli.js +16 -12
- package/dist/client.d.ts +23 -6
- package/dist/client.js +9 -2
- package/dist/{doc-C_8kCsl7.d.ts → doc-BXG9qG5X.d.ts} +8 -2
- package/dist/editor.css +37 -0
- package/dist/embed.d.ts +86 -0
- package/dist/embed.js +431 -0
- package/dist/formats.d.ts +52 -0
- package/dist/formats.js +24 -0
- package/dist/index.d.ts +12 -10
- package/dist/index.js +15 -9
- package/dist/live-worker.d.ts +2 -2
- package/dist/live-worker.js +7 -4
- package/dist/live.d.ts +6 -2
- package/dist/live.js +5 -3
- package/dist/{mcp-P2C75IIG.js → mcp-ZTUTC4CS.js} +5 -2
- package/dist/render-463xHb-x.d.ts +16 -0
- package/dist/{review-BQW2Ci2h.d.ts → review-Ds-i5Vnc.d.ts} +2 -16
- package/dist/{service-Do2Jwb5U.d.ts → service-Ck6oX-Kq.d.ts} +38 -5
- package/dist/ui/_headers +4 -0
- package/dist/ui/app.css +1 -0
- package/dist/ui/app.js +270 -0
- package/dist/ui/assets/inter-latin-ext-wght-normal-HA22NDSG.woff2 +0 -0
- package/dist/ui/assets/inter-latin-wght-normal-NRMW37G5.woff2 +0 -0
- package/dist/ui/assets/jetbrains-mono-latin-ext-wght-normal-TSLVDSQR.woff2 +0 -0
- package/dist/ui/assets/jetbrains-mono-latin-wght-normal-VBS632QH.woff2 +0 -0
- package/dist/ui/index.html +13 -0
- package/dist/worker.d.ts +2 -2
- package/dist/worker.js +7 -4
- package/llms.txt +1 -0
- package/package.json +43 -10
- package/dist/chunk-GYQFTF2E.js +0 -389
package/dist/editor.css
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/* The editor that `agentic-documents/ui` renders. Every rule sits under `.adoc`, so it does not touch the page around it.
|
|
2
|
+
Color, type, and space come from the agentic-design tokens: load `agentic-design/styles.css` first. */
|
|
3
|
+
.adoc.muted, .adoc .muted { color: var(--ad-color-text-muted); font-size: var(--ad-font-size-sm); margin: 0; }
|
|
4
|
+
.adoc.notice, .adoc .notice { max-width: var(--ad-size-content); }
|
|
5
|
+
.adoc.form { display: grid; gap: var(--ad-space-4); }
|
|
6
|
+
.adoc.form .form-actions { display: flex; gap: var(--ad-space-2); align-items: center; justify-content: flex-end; flex-wrap: wrap; }
|
|
7
|
+
.adoc .editor-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--ad-space-4); flex-wrap: wrap; max-width: var(--ad-size-content); margin-block-end: var(--ad-space-3); }
|
|
8
|
+
.adoc .editor-meta { display: flex; align-items: center; gap: var(--ad-space-4); flex-wrap: wrap; }
|
|
9
|
+
.adoc .glyph { font-weight: var(--ad-font-weight-semibold); min-width: 1.25rem; text-align: center; }
|
|
10
|
+
.adoc .glyph--b { font-weight: 800; }
|
|
11
|
+
.adoc .glyph--i { font-style: italic; font-family: serif; }
|
|
12
|
+
.adoc .editor-host { max-width: var(--ad-size-content); background: var(--ad-color-surface); border: 1px solid var(--ad-color-border); border-radius: var(--ad-radius-md); }
|
|
13
|
+
.adoc .editor-host:focus-within { outline: 2px solid var(--ad-color-focus); outline-offset: 2px; }
|
|
14
|
+
.adoc .prose { min-height: 20rem; padding: var(--ad-space-6); outline: none; line-height: var(--ad-line-height-normal); overflow-wrap: anywhere; }
|
|
15
|
+
.adoc .prose > :first-child { margin-top: 0; }
|
|
16
|
+
.adoc .prose h1 { font-size: var(--ad-font-size-2xl); line-height: var(--ad-line-height-tight); }
|
|
17
|
+
.adoc .prose h2 { font-size: var(--ad-font-size-xl); line-height: var(--ad-line-height-tight); }
|
|
18
|
+
.adoc .prose h3 { font-size: var(--ad-font-size-lg); }
|
|
19
|
+
.adoc .prose a { color: var(--ad-color-accent-text); text-decoration: underline; }
|
|
20
|
+
.adoc .prose blockquote { margin-inline: 0; padding-inline-start: var(--ad-space-4); border-inline-start: 3px solid var(--ad-color-border-strong); }
|
|
21
|
+
.adoc .prose code { font-family: var(--ad-font-family-mono); background: var(--ad-color-surface-sunken); padding: 0 0.25em; border-radius: var(--ad-radius-sm); }
|
|
22
|
+
.adoc .prose pre { background: var(--ad-color-surface-sunken); padding: var(--ad-space-3); border-radius: var(--ad-radius-md); overflow-x: auto; }
|
|
23
|
+
.adoc .prose table { border-collapse: collapse; }
|
|
24
|
+
.adoc .prose th, .adoc .prose td { border: 1px solid var(--ad-color-border-strong); padding: var(--ad-space-1) var(--ad-space-2); }
|
|
25
|
+
.adoc .prose img { max-width: 100%; }
|
|
26
|
+
.adoc .prose ul[data-type="taskList"] { list-style: none; padding-inline-start: var(--ad-space-2); }
|
|
27
|
+
.adoc .prose ul[data-type="taskList"] li { display: flex; gap: var(--ad-space-2); }
|
|
28
|
+
|
|
29
|
+
/* Text an agent wrote: a dotted underline in the agent color and a tint. The legend and the title say it in words. */
|
|
30
|
+
.adoc .agent-text { text-decoration: underline dotted 2px var(--ad-color-agent); text-underline-offset: 3px; background: var(--ad-color-agent-subtle); border-radius: 2px; }
|
|
31
|
+
.adoc .legend { margin-block-start: var(--ad-space-3); }
|
|
32
|
+
|
|
33
|
+
/* The caret of another person or agent. */
|
|
34
|
+
.adoc .caret { position: relative; border-inline-start: 2px solid var(--ad-color-accent); margin-inline: -1px; pointer-events: none; word-break: normal; }
|
|
35
|
+
.adoc .caret--agent { border-inline-start: 2px dashed var(--ad-color-agent); }
|
|
36
|
+
.adoc .caret__tag { position: absolute; top: -1.45em; inset-inline-start: -2px; white-space: nowrap; font-size: var(--ad-font-size-xs); line-height: 1.3; padding: 0 var(--ad-space-1); border-radius: var(--ad-radius-sm) var(--ad-radius-sm) var(--ad-radius-sm) 0; background: var(--ad-color-accent); color: var(--ad-color-text-on-accent); user-select: none; }
|
|
37
|
+
.adoc .caret--agent .caret__tag { background: var(--ad-color-surface); color: var(--ad-color-agent-text); border: 1px solid var(--ad-color-agent); border-radius: 0; }
|
package/dist/embed.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { e as PrincipalKind } from './doc-BXG9qG5X.js';
|
|
3
|
+
import { SyncClient, Status } from 'agentic-realtime/client';
|
|
4
|
+
import * as Y from 'yjs';
|
|
5
|
+
import { DocsClient } from './client.js';
|
|
6
|
+
import './render-463xHb-x.js';
|
|
7
|
+
import './review-Ds-i5Vnc.js';
|
|
8
|
+
import './service-Ck6oX-Kq.js';
|
|
9
|
+
import 'agentic-identity';
|
|
10
|
+
|
|
11
|
+
/** The calls the editor makes. A `DocsClient` from `agentic-documents/client` has them. */
|
|
12
|
+
type EditorClient = Pick<DocsClient, "state" | "checkpoint">;
|
|
13
|
+
/** A live room of agentic-realtime for one document. */
|
|
14
|
+
interface EditorRoom {
|
|
15
|
+
/** The WebSocket address of the room, such as `wss://docs.example.com/api/v1/docs/plan/ws`. */
|
|
16
|
+
url: string;
|
|
17
|
+
/** A bearer token for the room. In a browser it goes in a WebSocket subprotocol. */
|
|
18
|
+
token?: string;
|
|
19
|
+
/** Your own WebSocket class, for a room that takes its token another way. */
|
|
20
|
+
WebSocket?: new (url: string, options?: {
|
|
21
|
+
headers?: Record<string, string>;
|
|
22
|
+
}) => WebSocket;
|
|
23
|
+
}
|
|
24
|
+
interface LiveSession {
|
|
25
|
+
/** The room, or undefined when the document is open without one. */
|
|
26
|
+
sync?: SyncClient;
|
|
27
|
+
doc: Y.Doc;
|
|
28
|
+
/** The socket state now, and a way to hear when it changes. */
|
|
29
|
+
status: () => Status;
|
|
30
|
+
onStatus: (listener: (status: Status) => void) => () => void;
|
|
31
|
+
/** True when this tab changed the text since the last save that worked. */
|
|
32
|
+
readonly dirty: boolean;
|
|
33
|
+
/** Call it when this tab changes the text. */
|
|
34
|
+
touch(): void;
|
|
35
|
+
/** Merge the room into the stored document. It never makes a document: a removed one fails with NO_DOCUMENT. */
|
|
36
|
+
save(): Promise<void>;
|
|
37
|
+
close(): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Who uses the editor. The server still checks every write against its own token. */
|
|
41
|
+
interface EmbedPrincipal {
|
|
42
|
+
kind: PrincipalKind;
|
|
43
|
+
name: string;
|
|
44
|
+
/** Only `editor` can change the text. Any other value, or no value, opens it read only. */
|
|
45
|
+
role?: "editor" | "viewer";
|
|
46
|
+
}
|
|
47
|
+
interface DocumentEditorOptions {
|
|
48
|
+
/** The document id. */
|
|
49
|
+
id: string;
|
|
50
|
+
/** Loads and saves the document. A client from `createClient` in `agentic-documents/client` works. */
|
|
51
|
+
client: EditorClient;
|
|
52
|
+
principal: EmbedPrincipal;
|
|
53
|
+
/** The live room. With one, people and agents edit together and see each other. Without one, the editor saves alone. */
|
|
54
|
+
room?: EditorRoom;
|
|
55
|
+
/** Called when the document cannot open, with the error. */
|
|
56
|
+
onError?: (error: unknown) => void;
|
|
57
|
+
/** Called when the editor closes a document, with a promise that settles when the last save and the leave are done. It rejects when that save fails. */
|
|
58
|
+
onLeave?: (done: Promise<void>) => void;
|
|
59
|
+
}
|
|
60
|
+
type SessionState = {
|
|
61
|
+
state: "loading";
|
|
62
|
+
} | {
|
|
63
|
+
state: "error";
|
|
64
|
+
error: unknown;
|
|
65
|
+
} | {
|
|
66
|
+
state: "ready";
|
|
67
|
+
live: LiveSession;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Open a document for an editor, and close it when the component goes. On leave it saves first, but only when this tab
|
|
71
|
+
* changed something and may write. A save never makes a document, so a removed document stays removed. `onLeave` gets a
|
|
72
|
+
* promise that settles when the leave is done. It rejects when the save fails. With no `onLeave`, a failure is dropped.
|
|
73
|
+
*/
|
|
74
|
+
declare function useEditorSession(client: EditorClient, id: string, name: string, editable: boolean, room: EditorRoom | undefined, attempt: number, onLeave?: (done: Promise<void>) => void): SessionState;
|
|
75
|
+
/** The editor for one document, with its toolbar, presence, and save state. */
|
|
76
|
+
declare function DocumentEditor({ id, client, principal, room, onError, onLeave }: DocumentEditorOptions): react.JSX.Element;
|
|
77
|
+
interface MountedEditor {
|
|
78
|
+
/** Show another document, principal, or room in the same place. A bad principal throws and keeps the editor as it is. */
|
|
79
|
+
update(options: DocumentEditorOptions): void;
|
|
80
|
+
/** Remove the editor. It saves this tab's changes, then leaves the room. The promise rejects when that save fails. */
|
|
81
|
+
unmount(): Promise<void>;
|
|
82
|
+
}
|
|
83
|
+
/** Render the editor into an element, for an app that does not use React itself. */
|
|
84
|
+
declare function mountEditor(element: HTMLElement, options: DocumentEditorOptions): MountedEditor;
|
|
85
|
+
|
|
86
|
+
export { DocumentEditor, type DocumentEditorOptions, type EditorClient, type EditorRoom, type EmbedPrincipal, type LiveSession, type MountedEditor, type SessionState, mountEditor, useEditorSession };
|
package/dist/embed.js
ADDED
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PRINCIPAL_KINDS,
|
|
3
|
+
isMachine
|
|
4
|
+
} from "./chunk-DWVJIKVT.js";
|
|
5
|
+
|
|
6
|
+
// ui/embed.tsx
|
|
7
|
+
import { Button as Button2, EmptyState as EmptyState2 } from "agentic-design/react";
|
|
8
|
+
import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
9
|
+
import { createRoot } from "react-dom/client";
|
|
10
|
+
|
|
11
|
+
// ui/live.ts
|
|
12
|
+
import { SyncClient } from "agentic-realtime/client";
|
|
13
|
+
import * as Y from "yjs";
|
|
14
|
+
var base64url = (text) => btoa(String.fromCharCode(...new TextEncoder().encode(text))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
15
|
+
var TokenSocket = class extends WebSocket {
|
|
16
|
+
constructor(url, options) {
|
|
17
|
+
const token = /^Bearer (.+)$/.exec(options?.headers?.authorization ?? "")?.[1];
|
|
18
|
+
super(url, token ? ["agentic-docs", `agentic-docs.bearer.${base64url(token)}`] : void 0);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
async function openSession(client, id, name, room) {
|
|
22
|
+
let status = room ? "connecting" : "connected";
|
|
23
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
24
|
+
const doc = new Y.Doc();
|
|
25
|
+
Y.applyUpdate(doc, await client.state(id));
|
|
26
|
+
const sync = room ? await SyncClient.connect({
|
|
27
|
+
url: room.url,
|
|
28
|
+
headers: room.token ? { authorization: `Bearer ${room.token}` } : void 0,
|
|
29
|
+
WebSocket: room.WebSocket ?? TokenSocket,
|
|
30
|
+
doc,
|
|
31
|
+
presence: { name },
|
|
32
|
+
reconnect: {},
|
|
33
|
+
onStatus: (next) => {
|
|
34
|
+
status = next;
|
|
35
|
+
for (const listener of listeners) listener(next);
|
|
36
|
+
}
|
|
37
|
+
}) : void 0;
|
|
38
|
+
await sync?.whenSynced().catch(() => void 0);
|
|
39
|
+
let changes = 0;
|
|
40
|
+
let saved = 0;
|
|
41
|
+
const session = {
|
|
42
|
+
sync,
|
|
43
|
+
doc,
|
|
44
|
+
status: () => status,
|
|
45
|
+
onStatus: (listener) => (listeners.add(listener), () => void listeners.delete(listener)),
|
|
46
|
+
get dirty() {
|
|
47
|
+
return changes !== saved;
|
|
48
|
+
},
|
|
49
|
+
touch: () => void changes++,
|
|
50
|
+
async save() {
|
|
51
|
+
const mark = changes;
|
|
52
|
+
await sync?.flush();
|
|
53
|
+
await client.checkpoint(id, Y.encodeStateAsUpdate(doc), { create: false });
|
|
54
|
+
saved = mark;
|
|
55
|
+
},
|
|
56
|
+
close: async () => await sync?.disconnect()
|
|
57
|
+
};
|
|
58
|
+
return session;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ui/editor.tsx
|
|
62
|
+
import { Editor, Extension as Extension2 } from "@tiptap/core";
|
|
63
|
+
import Collaboration from "@tiptap/extension-collaboration";
|
|
64
|
+
import Image from "@tiptap/extension-image";
|
|
65
|
+
import { TaskItem, TaskList } from "@tiptap/extension-list";
|
|
66
|
+
import { Table, TableCell, TableHeader, TableRow } from "@tiptap/extension-table";
|
|
67
|
+
import StarterKit from "@tiptap/starter-kit";
|
|
68
|
+
import { ySyncPluginKey as ySyncPluginKey2, yCursorPlugin } from "@tiptap/y-tiptap";
|
|
69
|
+
import { Component, useEffect, useReducer, useRef, useState } from "react";
|
|
70
|
+
import { Button, Dialog, DialogClose, EmptyState, Input, PresenceStack, Toolbar, ToolbarButton, ToolbarSeparator, usableName } from "agentic-design/react";
|
|
71
|
+
|
|
72
|
+
// ui/marks.ts
|
|
73
|
+
import { Extension } from "@tiptap/core";
|
|
74
|
+
import { Plugin, PluginKey } from "@tiptap/pm/state";
|
|
75
|
+
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
76
|
+
import { relativePositionToAbsolutePosition, ySyncPluginKey } from "@tiptap/y-tiptap";
|
|
77
|
+
import * as Y2 from "yjs";
|
|
78
|
+
function agentRuns(doc) {
|
|
79
|
+
const agents = /* @__PURE__ */ new Set();
|
|
80
|
+
for (const entry of doc.getArray("edits").toArray()) {
|
|
81
|
+
if (typeof entry !== "object" || entry === null) continue;
|
|
82
|
+
if (typeof entry.client === "number" && entry.author?.kind !== void 0 && entry.author.kind !== "human") agents.add(entry.client);
|
|
83
|
+
}
|
|
84
|
+
const runs = [];
|
|
85
|
+
if (agents.size === 0) return runs;
|
|
86
|
+
const walk = (node) => {
|
|
87
|
+
for (const child of node.toArray()) {
|
|
88
|
+
if (child instanceof Y2.XmlElement) walk(child);
|
|
89
|
+
else if (child instanceof Y2.XmlText) {
|
|
90
|
+
let index = 0;
|
|
91
|
+
for (let item = child._start; item; item = item.right) {
|
|
92
|
+
if (item.deleted || !item.countable) continue;
|
|
93
|
+
if (agents.has(item.id.client)) runs.push({ text: child, from: index, to: index + item.length });
|
|
94
|
+
index += item.length;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
walk(doc.getXmlFragment("default"));
|
|
100
|
+
return runs;
|
|
101
|
+
}
|
|
102
|
+
var key = new PluginKey("agentText");
|
|
103
|
+
var AgentText = Extension.create({
|
|
104
|
+
name: "agentText",
|
|
105
|
+
addProseMirrorPlugins() {
|
|
106
|
+
return [
|
|
107
|
+
new Plugin({
|
|
108
|
+
key,
|
|
109
|
+
state: {
|
|
110
|
+
init: () => DecorationSet.empty,
|
|
111
|
+
apply: (tr, old) => tr.getMeta(key) ?? old.map(tr.mapping, tr.doc)
|
|
112
|
+
},
|
|
113
|
+
props: { decorations: (state) => key.getState(state) },
|
|
114
|
+
view(view) {
|
|
115
|
+
const sync = ySyncPluginKey.getState(view.state);
|
|
116
|
+
if (!sync) return {};
|
|
117
|
+
let timer;
|
|
118
|
+
let drawn = "";
|
|
119
|
+
const refresh = () => {
|
|
120
|
+
timer = void 0;
|
|
121
|
+
try {
|
|
122
|
+
const mapping = ySyncPluginKey.getState(view.state).binding?.mapping;
|
|
123
|
+
if (!mapping) return;
|
|
124
|
+
const size = view.state.doc.content.size;
|
|
125
|
+
const marks = [];
|
|
126
|
+
for (const { text, from, to } of agentRuns(sync.doc)) {
|
|
127
|
+
const a = relativePositionToAbsolutePosition(sync.doc, sync.type, Y2.createRelativePositionFromTypeIndex(text, from), mapping);
|
|
128
|
+
const b = relativePositionToAbsolutePosition(sync.doc, sync.type, Y2.createRelativePositionFromTypeIndex(text, to), mapping);
|
|
129
|
+
if (a !== null && b !== null && a < b && b <= size) marks.push(Decoration.inline(a, b, { class: "agent-text", title: "Written by an agent" }));
|
|
130
|
+
}
|
|
131
|
+
const signature = marks.map((m) => `${m.from}-${m.to}`).join(",");
|
|
132
|
+
if (signature === drawn) return;
|
|
133
|
+
drawn = signature;
|
|
134
|
+
view.dispatch(view.state.tr.setMeta(key, DecorationSet.create(view.state.doc, marks)).setMeta("addToHistory", false));
|
|
135
|
+
} catch {
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
const schedule = () => {
|
|
139
|
+
timer ??= setTimeout(refresh, 60);
|
|
140
|
+
};
|
|
141
|
+
sync.doc.on("update", schedule);
|
|
142
|
+
schedule();
|
|
143
|
+
return {
|
|
144
|
+
destroy() {
|
|
145
|
+
sync.doc.off("update", schedule);
|
|
146
|
+
if (timer) clearTimeout(timer);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
})
|
|
151
|
+
];
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// ui/editor.tsx
|
|
156
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
157
|
+
var SAVE_AFTER_MS = 1500;
|
|
158
|
+
var entryOf = (peer) => ({ id: String(peer.clientId), name: usableName(peer.name) ?? "Unnamed", kind: peer.machine ? "agent" : "person" });
|
|
159
|
+
var isRemoved = (error) => typeof error === "object" && error !== null && error.code === "NO_DOCUMENT";
|
|
160
|
+
function carets(sync) {
|
|
161
|
+
return Extension2.create({
|
|
162
|
+
name: "remoteCarets",
|
|
163
|
+
addProseMirrorPlugins: () => [
|
|
164
|
+
yCursorPlugin(sync.awareness, {
|
|
165
|
+
cursorBuilder: (_user, clientId) => {
|
|
166
|
+
const caret = document.createElement("span");
|
|
167
|
+
const peer = sync.peers.find((p) => p.clientId === clientId);
|
|
168
|
+
if (!peer) return caret;
|
|
169
|
+
caret.className = `caret${peer.machine ? " caret--agent" : ""}`;
|
|
170
|
+
const tag = document.createElement("span");
|
|
171
|
+
tag.className = "caret__tag";
|
|
172
|
+
tag.textContent = `${usableName(peer.name) ?? "Unnamed"}${peer.machine ? " \xB7 Agent" : ""}`;
|
|
173
|
+
caret.append(tag);
|
|
174
|
+
return caret;
|
|
175
|
+
},
|
|
176
|
+
selectionBuilder: () => ({})
|
|
177
|
+
})
|
|
178
|
+
]
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
var Boundary = class extends Component {
|
|
182
|
+
state = { failed: false };
|
|
183
|
+
static getDerivedStateFromError() {
|
|
184
|
+
return { failed: true };
|
|
185
|
+
}
|
|
186
|
+
render() {
|
|
187
|
+
return this.state.failed ? /* @__PURE__ */ jsx("div", { role: "alert", className: "adoc notice", children: /* @__PURE__ */ jsx(EmptyState, { title: "The editor stopped", description: "The document has content this page cannot show. Reload to try again." }) }) : this.props.children;
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
function Surface({ live, editable, principal: me }) {
|
|
191
|
+
const host = useRef(null);
|
|
192
|
+
const [editor, setEditor] = useState();
|
|
193
|
+
const [, refresh] = useReducer((n) => n + 1, 0);
|
|
194
|
+
const [peers, setPeers] = useState([]);
|
|
195
|
+
const [saved, setSaved] = useState("saved");
|
|
196
|
+
const [connection, setConnection] = useState("connecting");
|
|
197
|
+
const [agentText, setAgentText] = useState(false);
|
|
198
|
+
const [linking, setLinking] = useState(false);
|
|
199
|
+
const [href, setHref] = useState("");
|
|
200
|
+
const [linkError, setLinkError] = useState();
|
|
201
|
+
const refocus = useRef(false);
|
|
202
|
+
useEffect(() => {
|
|
203
|
+
const editor2 = new Editor({
|
|
204
|
+
element: host.current,
|
|
205
|
+
editable,
|
|
206
|
+
extensions: [
|
|
207
|
+
StarterKit.configure({ undoRedo: false, underline: false, link: { openOnClick: false, autolink: true, defaultProtocol: "https", isAllowedUri: (url) => /^(https?:\/\/|mailto:)\S+$/i.test(url) } }),
|
|
208
|
+
Image,
|
|
209
|
+
TaskList,
|
|
210
|
+
TaskItem,
|
|
211
|
+
Table,
|
|
212
|
+
TableRow,
|
|
213
|
+
TableCell,
|
|
214
|
+
TableHeader,
|
|
215
|
+
Collaboration.configure({ document: live.doc, field: "default" }),
|
|
216
|
+
...live.sync ? [carets(live.sync)] : [],
|
|
217
|
+
AgentText
|
|
218
|
+
],
|
|
219
|
+
editorProps: { attributes: { role: "textbox", "aria-multiline": "true", "aria-label": "Document text", class: "prose" } }
|
|
220
|
+
});
|
|
221
|
+
setEditor(editor2);
|
|
222
|
+
editor2.on("transaction", () => (setAgentText(host.current?.querySelector(".agent-text") != null), refresh()));
|
|
223
|
+
const offPeers = live.sync?.onPeers(setPeers);
|
|
224
|
+
setPeers(live.sync?.peers ?? []);
|
|
225
|
+
let timer;
|
|
226
|
+
let stopped = false;
|
|
227
|
+
let gone = false;
|
|
228
|
+
const save = () => {
|
|
229
|
+
timer = void 0;
|
|
230
|
+
setSaved("saving");
|
|
231
|
+
live.save().then(
|
|
232
|
+
() => !stopped && setSaved("saved"),
|
|
233
|
+
(error) => {
|
|
234
|
+
if (stopped) return;
|
|
235
|
+
if (isRemoved(error)) {
|
|
236
|
+
gone = true;
|
|
237
|
+
editor2.setEditable(false);
|
|
238
|
+
return setSaved("removed");
|
|
239
|
+
}
|
|
240
|
+
setSaved("failed");
|
|
241
|
+
timer = setTimeout(save, 5e3);
|
|
242
|
+
}
|
|
243
|
+
);
|
|
244
|
+
};
|
|
245
|
+
let labeled = false;
|
|
246
|
+
const changed = (_update, origin) => {
|
|
247
|
+
if (editable && !gone && origin === ySyncPluginKey2) {
|
|
248
|
+
if (!labeled && isMachine(me.kind)) {
|
|
249
|
+
labeled = true;
|
|
250
|
+
live.doc.getArray("edits").push([{ op: "live", at: (/* @__PURE__ */ new Date()).toISOString(), author: { kind: me.kind, name: me.name }, client: live.doc.clientID, inserted: 0, deleted: 0 }]);
|
|
251
|
+
}
|
|
252
|
+
live.touch();
|
|
253
|
+
setSaved("saving");
|
|
254
|
+
clearTimeout(timer);
|
|
255
|
+
timer = setTimeout(save, SAVE_AFTER_MS);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
live.doc.on("update", changed);
|
|
259
|
+
setConnection(live.status());
|
|
260
|
+
const offStatus = live.onStatus(setConnection);
|
|
261
|
+
return () => {
|
|
262
|
+
stopped = true;
|
|
263
|
+
live.doc.off("update", changed);
|
|
264
|
+
offStatus();
|
|
265
|
+
if (timer) clearTimeout(timer);
|
|
266
|
+
offPeers?.();
|
|
267
|
+
editor2.destroy();
|
|
268
|
+
};
|
|
269
|
+
}, [live, editable, me.name, me.kind]);
|
|
270
|
+
const entries = [{ id: "me", name: me.name, kind: isMachine(me.kind) ? "agent" : "person" }, ...peers.map(entryOf)];
|
|
271
|
+
const pressed = (name, attrs) => editor?.isActive(name, attrs) ?? false;
|
|
272
|
+
const chain = () => (editor.view.focus(), editor.chain().focus());
|
|
273
|
+
const glyph = (text, style) => /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: `glyph glyph--${style ?? "plain"}`, children: text });
|
|
274
|
+
const listIcon = (numbered) => /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", focusable: "false", viewBox: "0 0 20 20", width: "1.25em", height: "1.25em", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", children: [
|
|
275
|
+
/* @__PURE__ */ jsx("path", { d: "M8 5h9M8 10h9M8 15h9" }),
|
|
276
|
+
numbered ? /* @__PURE__ */ jsx("path", { d: "M3 4.5l1-.5v4M3 11.5h2l-2 2.5h2.2", strokeLinejoin: "round" }) : /* @__PURE__ */ jsx("path", { d: "M3.5 5h.01M3.5 10h.01M3.5 15h.01", strokeWidth: "2.6" })
|
|
277
|
+
] });
|
|
278
|
+
const tool = (label, icon, active, run) => /* @__PURE__ */ jsx(ToolbarButton, { label, icon, pressed: active, onClick: run, disabled: !editable });
|
|
279
|
+
function openLink() {
|
|
280
|
+
setHref(editor?.getAttributes("link").href ?? "");
|
|
281
|
+
setLinkError(void 0);
|
|
282
|
+
setLinking(true);
|
|
283
|
+
}
|
|
284
|
+
function applyLink() {
|
|
285
|
+
const value = href.trim();
|
|
286
|
+
if (value === "") chain().extendMarkRange("link").unsetLink().run();
|
|
287
|
+
else if (!/^(https?:\/\/|mailto:)\S+$/i.test(value)) return setLinkError("Use a web address that starts with https:// or http://, or a mailto: address.");
|
|
288
|
+
else chain().extendMarkRange("link").setLink({ href: value }).run();
|
|
289
|
+
if (editor && !editor.state.selection.empty) editor.chain().setTextSelection(editor.state.selection.to).unsetMark("link").run();
|
|
290
|
+
refocus.current = true;
|
|
291
|
+
setLinking(false);
|
|
292
|
+
}
|
|
293
|
+
useEffect(() => {
|
|
294
|
+
if (linking || !refocus.current) return;
|
|
295
|
+
refocus.current = false;
|
|
296
|
+
let tries = 0;
|
|
297
|
+
const timer = setInterval(() => {
|
|
298
|
+
if (editor?.isFocused || ++tries > 10) return clearInterval(timer);
|
|
299
|
+
editor?.view.focus();
|
|
300
|
+
}, 40);
|
|
301
|
+
return () => clearInterval(timer);
|
|
302
|
+
}, [linking, editor]);
|
|
303
|
+
return /* @__PURE__ */ jsxs("section", { "aria-label": "Editor", className: "adoc", children: [
|
|
304
|
+
/* @__PURE__ */ jsxs("div", { className: "editor-bar", children: [
|
|
305
|
+
/* @__PURE__ */ jsxs(Toolbar, { label: "Formatting", children: [
|
|
306
|
+
tool("Bold", glyph("B", "b"), pressed("bold"), () => chain().toggleBold().run()),
|
|
307
|
+
tool("Italic", glyph("I", "i"), pressed("italic"), () => chain().toggleItalic().run()),
|
|
308
|
+
/* @__PURE__ */ jsx(ToolbarSeparator, {}),
|
|
309
|
+
tool("H1 heading", glyph("H1"), pressed("heading", { level: 1 }), () => chain().toggleHeading({ level: 1 }).run()),
|
|
310
|
+
tool("H2 heading", glyph("H2"), pressed("heading", { level: 2 }), () => chain().toggleHeading({ level: 2 }).run()),
|
|
311
|
+
/* @__PURE__ */ jsx(ToolbarSeparator, {}),
|
|
312
|
+
tool("Bulleted list", listIcon(false), pressed("bulletList"), () => chain().toggleBulletList().run()),
|
|
313
|
+
tool("Numbered list", listIcon(true), pressed("orderedList"), () => chain().toggleOrderedList().run()),
|
|
314
|
+
/* @__PURE__ */ jsx(ToolbarSeparator, {}),
|
|
315
|
+
tool("Link", glyph("\u2197"), pressed("link"), openLink)
|
|
316
|
+
] }),
|
|
317
|
+
/* @__PURE__ */ jsxs("div", { className: "editor-meta", children: [
|
|
318
|
+
/* @__PURE__ */ jsx(PresenceStack, { entries, label: "People and agents here" }),
|
|
319
|
+
/* @__PURE__ */ jsxs("span", { role: "status", className: "muted", children: [
|
|
320
|
+
!editable ? "Read only. " : "",
|
|
321
|
+
connection === "disconnected" ? "Offline: changes are kept and sync when you are back. " : "",
|
|
322
|
+
saved === "saving" ? "Saving\u2026" : saved === "failed" ? "Not saved. Will try again." : saved === "removed" ? "This document was removed. Your changes are not saved." : "Saved"
|
|
323
|
+
] })
|
|
324
|
+
] })
|
|
325
|
+
] }),
|
|
326
|
+
/* @__PURE__ */ jsx("div", { ref: host, className: "editor-host" }),
|
|
327
|
+
/* @__PURE__ */ jsx("p", { className: "muted legend", children: agentText ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
328
|
+
/* @__PURE__ */ jsx("span", { className: "agent-text", children: "Dotted text" }),
|
|
329
|
+
" was written by an agent."
|
|
330
|
+
] }) : "Text that an agent writes shows with a dotted underline." }),
|
|
331
|
+
/* @__PURE__ */ jsx(Dialog, { open: linking, onOpenChange: setLinking, title: "Link", description: "Leave it empty to remove the link.", children: /* @__PURE__ */ jsxs("form", { className: "adoc form", onSubmit: (e) => (e.preventDefault(), applyLink()), children: [
|
|
332
|
+
/* @__PURE__ */ jsx(Input, { label: "Address", value: href, onChange: (e) => setHref(e.target.value), error: linkError, placeholder: "https://", autoComplete: "off" }),
|
|
333
|
+
/* @__PURE__ */ jsxs("div", { className: "form-actions", children: [
|
|
334
|
+
/* @__PURE__ */ jsx(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", children: "Cancel" }) }),
|
|
335
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", children: "Apply" })
|
|
336
|
+
] })
|
|
337
|
+
] }) })
|
|
338
|
+
] });
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// ui/embed.tsx
|
|
342
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
343
|
+
function checkPrincipal(principal) {
|
|
344
|
+
if (!principal || !PRINCIPAL_KINDS.includes(principal.kind) || typeof principal.name !== "string" || principal.name.trim() === "") {
|
|
345
|
+
throw new TypeError(`the editor needs a principal with a kind (${PRINCIPAL_KINDS.join(", ")}) and a name`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
function useEditorSession(client, id, name, editable, room, attempt, onLeave) {
|
|
349
|
+
const [load, setLoad] = useState2({ state: "loading" });
|
|
350
|
+
const roomKey = room ? JSON.stringify([room.url, room.token ?? ""]) : "";
|
|
351
|
+
const roomRef = useRef2(room);
|
|
352
|
+
roomRef.current = room;
|
|
353
|
+
const leaveRef = useRef2(onLeave);
|
|
354
|
+
leaveRef.current = onLeave;
|
|
355
|
+
useEffect2(() => {
|
|
356
|
+
let cancelled = false;
|
|
357
|
+
let live;
|
|
358
|
+
setLoad({ state: "loading" });
|
|
359
|
+
openSession(client, id, name, roomRef.current).then(
|
|
360
|
+
(found) => {
|
|
361
|
+
live = found;
|
|
362
|
+
if (cancelled) return void found.close();
|
|
363
|
+
setLoad({ state: "ready", live: found });
|
|
364
|
+
},
|
|
365
|
+
(error) => !cancelled && setLoad({ state: "error", error })
|
|
366
|
+
);
|
|
367
|
+
return () => {
|
|
368
|
+
cancelled = true;
|
|
369
|
+
const open = live;
|
|
370
|
+
if (!open) return;
|
|
371
|
+
const done = (async () => {
|
|
372
|
+
try {
|
|
373
|
+
if (editable && open.dirty) await open.save();
|
|
374
|
+
} finally {
|
|
375
|
+
await open.close();
|
|
376
|
+
}
|
|
377
|
+
})();
|
|
378
|
+
if (leaveRef.current) leaveRef.current(done);
|
|
379
|
+
else done.catch(() => void 0);
|
|
380
|
+
};
|
|
381
|
+
}, [client, id, name, editable, roomKey, room?.WebSocket, attempt]);
|
|
382
|
+
return load;
|
|
383
|
+
}
|
|
384
|
+
var describe = (error) => {
|
|
385
|
+
if (isRemoved(error)) return "This document does not exist. It may have been removed.";
|
|
386
|
+
const code = typeof error === "object" && error !== null ? error.code : void 0;
|
|
387
|
+
if (code === "UNAUTHENTICATED") return "The server did not accept the token.";
|
|
388
|
+
if (code === "FORBIDDEN") return "You may not open this document.";
|
|
389
|
+
return error instanceof Error ? error.message : "Something went wrong.";
|
|
390
|
+
};
|
|
391
|
+
function DocumentEditor({ id, client, principal, room, onError, onLeave }) {
|
|
392
|
+
checkPrincipal(principal);
|
|
393
|
+
const editable = principal.role === "editor";
|
|
394
|
+
const [attempt, setAttempt] = useState2(0);
|
|
395
|
+
const load = useEditorSession(client, id, principal.name, editable, room, attempt, onLeave);
|
|
396
|
+
const reported = useRef2(void 0);
|
|
397
|
+
useEffect2(() => {
|
|
398
|
+
if (load.state === "error" && reported.current !== load.error) {
|
|
399
|
+
reported.current = load.error;
|
|
400
|
+
onError?.(load.error);
|
|
401
|
+
}
|
|
402
|
+
}, [load, onError]);
|
|
403
|
+
if (load.state === "loading") return /* @__PURE__ */ jsx2("p", { role: "status", className: "adoc muted", children: "Opening document\u2026" });
|
|
404
|
+
if (load.state === "error") {
|
|
405
|
+
return /* @__PURE__ */ jsx2("div", { role: "alert", className: "adoc notice", children: /* @__PURE__ */ jsx2(EmptyState2, { title: "Could not open this document", description: describe(load.error), action: /* @__PURE__ */ jsx2(Button2, { onClick: () => setAttempt(attempt + 1), children: "Try again" }) }) });
|
|
406
|
+
}
|
|
407
|
+
return /* @__PURE__ */ jsx2(Boundary, { children: /* @__PURE__ */ jsx2(Surface, { live: load.live, editable, principal }) });
|
|
408
|
+
}
|
|
409
|
+
function mountEditor(element, options) {
|
|
410
|
+
checkPrincipal(options.principal);
|
|
411
|
+
const root = createRoot(element);
|
|
412
|
+
const leaving = /* @__PURE__ */ new Set();
|
|
413
|
+
const track = (done) => {
|
|
414
|
+
leaving.add(done);
|
|
415
|
+
void done.catch(() => void 0).finally(() => leaving.delete(done));
|
|
416
|
+
};
|
|
417
|
+
const render = (next) => root.render(/* @__PURE__ */ jsx2(DocumentEditor, { ...next, onLeave: (done) => (track(done), next.onLeave?.(done)) }, next.id));
|
|
418
|
+
render(options);
|
|
419
|
+
return {
|
|
420
|
+
update: (next) => (checkPrincipal(next.principal), render(next)),
|
|
421
|
+
unmount: async () => {
|
|
422
|
+
root.unmount();
|
|
423
|
+
await Promise.all(leaving);
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
export {
|
|
428
|
+
DocumentEditor,
|
|
429
|
+
mountEditor,
|
|
430
|
+
useEditorSession
|
|
431
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Limits, TextDoc } from 'agentic-formats';
|
|
2
|
+
import { D as DocOptions, A as AgenticDoc, d as PmNode, P as Principal } from './doc-BXG9qG5X.js';
|
|
3
|
+
import { a as ExportOptions } from './render-463xHb-x.js';
|
|
4
|
+
import 'yjs';
|
|
5
|
+
|
|
6
|
+
declare const IMPORT_FORMATS: readonly ["md", "odt", "docx"];
|
|
7
|
+
type ImportFormat = (typeof IMPORT_FORMATS)[number];
|
|
8
|
+
declare const FILE_FORMATS: readonly ["md", "html", "odt", "docx"];
|
|
9
|
+
type FileFormat = (typeof FILE_FORMATS)[number];
|
|
10
|
+
declare const DOCX_MIME = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
11
|
+
interface ImportOptions {
|
|
12
|
+
/** Caps for the file. A file that goes past one is refused, never trimmed. The defaults are those of agentic-formats. */
|
|
13
|
+
limits?: Partial<Limits>;
|
|
14
|
+
doc?: DocOptions;
|
|
15
|
+
}
|
|
16
|
+
interface ImportResult {
|
|
17
|
+
doc: AgenticDoc;
|
|
18
|
+
/** The title the file holds, if any. */
|
|
19
|
+
title?: string;
|
|
20
|
+
/** One line for each part of the file that the document cannot hold. Empty when nothing was lost. */
|
|
21
|
+
warnings: string[];
|
|
22
|
+
}
|
|
23
|
+
interface FileResult {
|
|
24
|
+
format: FileFormat;
|
|
25
|
+
contentType: string;
|
|
26
|
+
/** Text for `md` and `html`. File bytes for `odt` and `docx`. */
|
|
27
|
+
data: string | Uint8Array;
|
|
28
|
+
/** One line for each part of the document that the format cannot hold. Empty when nothing was lost. */
|
|
29
|
+
warnings: string[];
|
|
30
|
+
}
|
|
31
|
+
/** Map document blocks to the neutral text model. A part the model cannot hold keeps its text and adds a warning. */
|
|
32
|
+
declare function toTextDoc(blocks: PmNode[], title?: string): {
|
|
33
|
+
model: TextDoc;
|
|
34
|
+
warnings: string[];
|
|
35
|
+
};
|
|
36
|
+
/** Map the neutral text model to document blocks. A part the editor cannot hold keeps its text and adds a warning. */
|
|
37
|
+
declare function fromTextDoc(model: TextDoc): {
|
|
38
|
+
blocks: PmNode[];
|
|
39
|
+
title?: string;
|
|
40
|
+
warnings: string[];
|
|
41
|
+
};
|
|
42
|
+
/** Read a file into a new document. The author makes the one `create` edit, so text from an agent stays labeled. */
|
|
43
|
+
declare function importFile(input: string | Uint8Array, format: ImportFormat, author: Principal, options?: ImportOptions): ImportResult;
|
|
44
|
+
declare const ODT_MIME: string;
|
|
45
|
+
/** Write blocks as an OpenDocument text file (.odt). It drops the warnings; use `exportFile` or `exportDoc` to read what the file cannot hold. */
|
|
46
|
+
declare function exportOdt(blocks: PmNode[]): Uint8Array;
|
|
47
|
+
/** Write a document as a file. `title` goes into the ODT and DOCX metadata. */
|
|
48
|
+
declare function exportFile(doc: AgenticDoc, format: FileFormat, options?: ExportOptions & {
|
|
49
|
+
title?: string;
|
|
50
|
+
}): FileResult;
|
|
51
|
+
|
|
52
|
+
export { DOCX_MIME, FILE_FORMATS, type FileFormat, type FileResult, IMPORT_FORMATS, type ImportFormat, type ImportOptions, type ImportResult, ODT_MIME, exportFile, exportOdt, fromTextDoc, importFile, toTextDoc };
|
package/dist/formats.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DOCX_MIME,
|
|
3
|
+
FILE_FORMATS,
|
|
4
|
+
IMPORT_FORMATS,
|
|
5
|
+
ODT_MIME,
|
|
6
|
+
exportFile,
|
|
7
|
+
exportOdt,
|
|
8
|
+
fromTextDoc,
|
|
9
|
+
importFile,
|
|
10
|
+
toTextDoc
|
|
11
|
+
} from "./chunk-KC5KFB5R.js";
|
|
12
|
+
import "./chunk-GQ5E6T7Z.js";
|
|
13
|
+
import "./chunk-DWVJIKVT.js";
|
|
14
|
+
export {
|
|
15
|
+
DOCX_MIME,
|
|
16
|
+
FILE_FORMATS,
|
|
17
|
+
IMPORT_FORMATS,
|
|
18
|
+
ODT_MIME,
|
|
19
|
+
exportFile,
|
|
20
|
+
exportOdt,
|
|
21
|
+
fromTextDoc,
|
|
22
|
+
importFile,
|
|
23
|
+
toTextDoc
|
|
24
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { A as AgenticDoc, P as Principal } from './doc-BXG9qG5X.js';
|
|
2
|
+
export { a as Anchor, b as AnchorTarget, D as DocOptions, E as EditEntry, c as PRINCIPAL_KINDS, d as PmNode, e as PrincipalKind, S as Section, f as SectionTarget, T as Target, g as TextTarget, h as blocksToMarkdown, m as markdownToBlocks, p as parseAuthor } from './doc-BXG9qG5X.js';
|
|
3
3
|
import { Schema } from 'prosemirror-model';
|
|
4
|
-
export {
|
|
4
|
+
export { D as DocError, a as DocErrorCode, M as Message, S as Suggestion, b as Suggestions, T as Thread, c as Threads } from './review-Ds-i5Vnc.js';
|
|
5
5
|
import { z } from 'zod';
|
|
6
|
-
import { D as DocAccess } from './service-
|
|
7
|
-
export { a as DocInfo, b as DocsPorts, c as DocsService } from './service-
|
|
6
|
+
import { D as DocAccess } from './service-Ck6oX-Kq.js';
|
|
7
|
+
export { a as DocInfo, b as DocsPorts, c as DocsService } from './service-Ck6oX-Kq.js';
|
|
8
|
+
import { E as ExportFormat, a as ExportOptions, b as ExportResult } from './render-463xHb-x.js';
|
|
9
|
+
export { c as EXPORT_FORMATS } from './render-463xHb-x.js';
|
|
8
10
|
import { AdapterOptions, Blobs, Store } from 'agentic-identity';
|
|
11
|
+
export { ODT_MIME, exportOdt } from './formats.js';
|
|
9
12
|
import 'yjs';
|
|
13
|
+
import 'agentic-formats';
|
|
14
|
+
|
|
15
|
+
declare function exportDoc(doc: AgenticDoc, format: ExportFormat, options?: ExportOptions): ExportResult;
|
|
10
16
|
|
|
11
17
|
declare const schema: Schema<string, string>;
|
|
12
18
|
|
|
@@ -45,8 +51,4 @@ declare function createFileStore(dir: string, options?: AdapterOptions & Pick<Fi
|
|
|
45
51
|
shared?: string;
|
|
46
52
|
}): Store;
|
|
47
53
|
|
|
48
|
-
|
|
49
|
-
/** Write blocks as an OpenDocument text file (.odt): content, styles, and images as embedded files. */
|
|
50
|
-
declare function exportOdt(blocks: PmNode[]): Uint8Array;
|
|
51
|
-
|
|
52
|
-
export { type Command, type FileBlobsOptions, ODT_MIME, PmNode, Principal, commands, createFileBlobs, createFileStore, exportOdt, schema };
|
|
54
|
+
export { AgenticDoc, type Command, ExportFormat, ExportOptions, ExportResult, type FileBlobsOptions, Principal, commands, createFileBlobs, createFileStore, exportDoc, schema };
|