agentic-comments 0.5.1 → 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/README.md +74 -13
- package/SKILL.md +5 -1
- package/dist/{chunk-QJXI3P5D.js → chunk-2NBFTJ47.js} +1 -1
- package/dist/{chunk-REFQNIEP.js → chunk-ES3NZ7SX.js} +1 -1
- package/dist/{chunk-TFRLOBJW.js → chunk-SR2A5OZW.js} +12 -5
- package/dist/{chunk-NQWRFKJ6.js → chunk-T77DPNIV.js} +21 -1
- package/dist/{chunk-BSNBDKR2.js → chunk-VAVKBAHM.js} +278 -6
- package/dist/cli.js +29 -8
- package/dist/client.d.ts +29 -4
- package/dist/client.js +17 -5
- package/dist/errors-C-xvp24-.d.ts +7 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +18 -3
- package/dist/local.d.ts +2 -2
- package/dist/local.js +3 -3
- package/dist/mcp-JX5L6VQW.js +11 -0
- package/dist/mcp-bin.js +5 -5
- package/dist/{service-hpWbnSmc.d.ts → service-BvIE6t5n.d.ts} +24 -1
- package/dist/{suggestions-CvJwo6r4.d.ts → suggestions-CnkEcTuY.d.ts} +128 -1
- package/dist/worker.d.ts +10 -5
- package/dist/worker.js +36 -6
- package/llms.txt +1 -0
- package/package.json +2 -2
- package/dist/errors-CNgWMVQT.d.ts +0 -7
- package/dist/mcp-XUV3RPOO.js +0 -11
package/dist/cli.js
CHANGED
|
@@ -3,17 +3,17 @@ import {
|
|
|
3
3
|
FileStore,
|
|
4
4
|
lockTimeoutFrom,
|
|
5
5
|
operatorActor
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2NBFTJ47.js";
|
|
7
7
|
import {
|
|
8
8
|
VERSION
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-ES3NZ7SX.js";
|
|
10
10
|
import {
|
|
11
11
|
CommentsService,
|
|
12
12
|
TEXT_ROOT
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-T77DPNIV.js";
|
|
14
14
|
import {
|
|
15
15
|
CommentsError
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-VAVKBAHM.js";
|
|
17
17
|
|
|
18
18
|
// src/cli.ts
|
|
19
19
|
import { readFileSync, realpathSync } from "fs";
|
|
@@ -24,6 +24,7 @@ var FLAGS = {
|
|
|
24
24
|
"--file": "value",
|
|
25
25
|
"--as": "value",
|
|
26
26
|
"--body": "value",
|
|
27
|
+
"--message": "value",
|
|
27
28
|
"--mention": "many",
|
|
28
29
|
"--text-quote": "value",
|
|
29
30
|
"--occurrence": "value",
|
|
@@ -50,14 +51,19 @@ var ALLOWED = {
|
|
|
50
51
|
resolve: SHARED,
|
|
51
52
|
reopen: SHARED,
|
|
52
53
|
relocate: SHARED,
|
|
54
|
+
"edit-message": [...SHARED, "--message", "--body", "--mention"],
|
|
55
|
+
"delete-message": [...SHARED, "--message"],
|
|
56
|
+
"delete-thread": SHARED,
|
|
57
|
+
"export-person": SHARED,
|
|
58
|
+
"erase-person": SHARED,
|
|
53
59
|
suggestions: [...SHARED, "--status", "--anchor-state"],
|
|
54
60
|
suggest: [...SHARED, ...ANCHOR, "--replace", "--value", "--summary"],
|
|
55
61
|
accept: SHARED,
|
|
56
62
|
reject: SHARED,
|
|
57
63
|
mcp: SHARED
|
|
58
64
|
};
|
|
59
|
-
var TAKES_ID = ["show", "reply", "resolve", "reopen", "relocate", "accept", "reject"];
|
|
60
|
-
var COMMANDS = ["init", "list", "show", "comment", "reply", "resolve", "reopen", "relocate", "suggestions", "suggest", "accept", "reject", "mcp"];
|
|
65
|
+
var TAKES_ID = ["show", "reply", "resolve", "reopen", "relocate", "accept", "reject", "edit-message", "delete-message", "delete-thread", "export-person", "erase-person"];
|
|
66
|
+
var COMMANDS = ["init", "list", "show", "comment", "reply", "resolve", "reopen", "relocate", "edit-message", "delete-message", "delete-thread", "export-person", "erase-person", "suggestions", "suggest", "accept", "reject", "mcp"];
|
|
61
67
|
function parseArgs(argv) {
|
|
62
68
|
const [command, ...rest] = argv;
|
|
63
69
|
if (command === void 0 || command === "--help" || command === "-h") return { command: "help", flags: {}, many: {} };
|
|
@@ -112,6 +118,15 @@ function need(p) {
|
|
|
112
118
|
if (p.id === void 0) throw new UsageError(`${p.command} needs an id`);
|
|
113
119
|
return p.id;
|
|
114
120
|
}
|
|
121
|
+
function needName(p) {
|
|
122
|
+
if (p.id === void 0) throw new UsageError(`${p.command} needs the name of a person`);
|
|
123
|
+
return p.id;
|
|
124
|
+
}
|
|
125
|
+
function flag(p, name) {
|
|
126
|
+
const value = p.flags[name];
|
|
127
|
+
if (value === void 0) throw new UsageError(`${p.command} needs ${name}`);
|
|
128
|
+
return value;
|
|
129
|
+
}
|
|
115
130
|
var HELP = `agentic-comments ${VERSION}
|
|
116
131
|
Comment threads and suggestions anchored to any content, from people and agents.
|
|
117
132
|
|
|
@@ -121,6 +136,7 @@ Setup:
|
|
|
121
136
|
--file <path> The store file. Or AGENTIC_COMMENTS_FILE. Default ./comments.ydoc.
|
|
122
137
|
--as <kind:name> Who acts. Or AGENTIC_COMMENTS_AS. Kinds: human, agent_of_human, agent_of_agent, agent, user_token.
|
|
123
138
|
Scopes come only from AGENTIC_COMMENTS_SCOPES, a comma list such as comments:accept.
|
|
139
|
+
Another person's message, thread, or data needs comments:moderate.
|
|
124
140
|
|
|
125
141
|
Commands:
|
|
126
142
|
init [--text <t> | --text-file <p>] Create the store.
|
|
@@ -129,6 +145,11 @@ Commands:
|
|
|
129
145
|
comment <anchor> --body <t> [--mention h] Start a thread.
|
|
130
146
|
reply <id> --body <t> [--mention h] Reply.
|
|
131
147
|
resolve <id> | reopen <id> | relocate <id>
|
|
148
|
+
edit-message <id> --message <mid> --body <t> [--mention h] Change a message you wrote.
|
|
149
|
+
delete-message <id> --message <mid> Delete a message you wrote.
|
|
150
|
+
delete-thread <id> Delete a thread. Needs every message to be yours.
|
|
151
|
+
export-person <name> Export what a person wrote.
|
|
152
|
+
erase-person <name> Replace what a person wrote with a tombstone.
|
|
132
153
|
suggestions [--status s] [--anchor-state s] List suggestions.
|
|
133
154
|
suggest <anchor> (--replace <t> | --value <json>) [--summary <t>]
|
|
134
155
|
accept <id> | reject <id>
|
|
@@ -155,7 +176,7 @@ async function runCli(argv, io) {
|
|
|
155
176
|
return 0;
|
|
156
177
|
}
|
|
157
178
|
if (p.command === "mcp") {
|
|
158
|
-
const { startMcp } = await import("./mcp-
|
|
179
|
+
const { startMcp } = await import("./mcp-JX5L6VQW.js");
|
|
159
180
|
await startMcp(store, operatorActor(p.flags["--as"] ?? io.env.AGENTIC_COMMENTS_AS, io.env.AGENTIC_COMMENTS_SCOPES));
|
|
160
181
|
return 0;
|
|
161
182
|
}
|
|
@@ -163,7 +184,7 @@ async function runCli(argv, io) {
|
|
|
163
184
|
const mentions = p.many["--mention"];
|
|
164
185
|
const filter = { status: p.flags["--status"], anchorState: p.flags["--anchor-state"], mentioning: p.flags["--mentioning"] };
|
|
165
186
|
const clean = Object.fromEntries(Object.entries(filter).filter(([, v]) => v !== void 0));
|
|
166
|
-
const result = p.command === "list" ? service.threads(clean) : p.command === "show" ? service.thread(need(p)) : p.command === "comment" ? service.comment({ anchor: anchorOf(p), body: p.flags["--body"], ...mentions ? { mentions } : {} }) : p.command === "reply" ? service.reply(need(p), { body: p.flags["--body"], ...mentions ? { mentions } : {} }) : p.command === "resolve" ? service.resolve(need(p)) : p.command === "reopen" ? service.reopen(need(p)) : p.command === "relocate" ? service.relocate(need(p)) : p.command === "suggestions" ? service.suggestions(Object.fromEntries(Object.entries(clean).filter(([k]) => k !== "mentioning"))) : p.command === "suggest" ? service.suggest({ anchor: anchorOf(p), change: changeOf(p), ...p.flags["--summary"] === void 0 ? {} : { summary: p.flags["--summary"] } }) : p.command === "accept" ? service.accept(need(p)) : service.reject(need(p));
|
|
187
|
+
const result = p.command === "list" ? service.threads(clean) : p.command === "show" ? service.thread(need(p)) : p.command === "comment" ? service.comment({ anchor: anchorOf(p), body: p.flags["--body"], ...mentions ? { mentions } : {} }) : p.command === "reply" ? service.reply(need(p), { body: p.flags["--body"], ...mentions ? { mentions } : {} }) : p.command === "edit-message" ? service.editMessage(need(p), flag(p, "--message"), { body: p.flags["--body"], ...mentions ? { mentions } : {} }) : p.command === "delete-message" ? service.deleteMessage(need(p), flag(p, "--message")) : p.command === "delete-thread" ? service.deleteThread(need(p)) : p.command === "export-person" ? service.exportPerson(needName(p)) : p.command === "erase-person" ? service.erasePerson(needName(p)) : p.command === "resolve" ? service.resolve(need(p)) : p.command === "reopen" ? service.reopen(need(p)) : p.command === "relocate" ? service.relocate(need(p)) : p.command === "suggestions" ? service.suggestions(Object.fromEntries(Object.entries(clean).filter(([k]) => k !== "mentioning"))) : p.command === "suggest" ? service.suggest({ anchor: anchorOf(p), change: changeOf(p), ...p.flags["--summary"] === void 0 ? {} : { summary: p.flags["--summary"] } }) : p.command === "accept" ? service.accept(need(p)) : service.reject(need(p));
|
|
167
188
|
io.out(JSON.stringify(result));
|
|
168
189
|
return 0;
|
|
169
190
|
} catch (error) {
|
package/dist/client.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { L as ListFilter, A as AnchorSpec } from './service-
|
|
2
|
-
import { C as CommentsErrorCode } from './errors-
|
|
1
|
+
import { L as ListFilter, A as AnchorSpec } from './service-BvIE6t5n.js';
|
|
2
|
+
import { C as CommentsErrorCode } from './errors-C-xvp24-.js';
|
|
3
3
|
import { PrincipalKind } from 'agentic-identity';
|
|
4
4
|
export { PrincipalKind } from 'agentic-identity';
|
|
5
|
-
import { T as Thread, N as NewReply, M as Message, S as Suggestion } from './suggestions-
|
|
5
|
+
import { T as Thread, N as NewReply, M as Message, P as PersonExport, a as PersonSuggestions, S as Suggestion } from './suggestions-CnkEcTuY.js';
|
|
6
6
|
import 'yjs';
|
|
7
7
|
|
|
8
8
|
/** Codes the comment rules return, plus the ones the Worker and its auth return. */
|
|
@@ -35,6 +35,18 @@ interface Me {
|
|
|
35
35
|
}
|
|
36
36
|
type ThreadFilter = ListFilter;
|
|
37
37
|
type SuggestionListFilter = Pick<ListFilter, "status" | "anchorState">;
|
|
38
|
+
/** What `exportPerson` returns: the messages and status changes of one person, and their suggestions. */
|
|
39
|
+
type PersonData = PersonExport & {
|
|
40
|
+
suggestions: PersonSuggestions;
|
|
41
|
+
};
|
|
42
|
+
/** What `erasePerson` changed in one document. */
|
|
43
|
+
interface Erased {
|
|
44
|
+
messages: number;
|
|
45
|
+
statuses: number;
|
|
46
|
+
edits: number;
|
|
47
|
+
suggestions: number;
|
|
48
|
+
decisions: number;
|
|
49
|
+
}
|
|
38
50
|
interface CommentsClient {
|
|
39
51
|
me(options?: CallOptions): Promise<Me>;
|
|
40
52
|
createDocument(input: {
|
|
@@ -58,6 +70,19 @@ interface CommentsClient {
|
|
|
58
70
|
resolve(docId: string, threadId: string, options?: CallOptions): Promise<Thread>;
|
|
59
71
|
reopen(docId: string, threadId: string, options?: CallOptions): Promise<Thread>;
|
|
60
72
|
relocate(docId: string, threadId: string, options?: CallOptions): Promise<Thread>;
|
|
73
|
+
editMessage(docId: string, threadId: string, messageId: string, input: {
|
|
74
|
+
body: string;
|
|
75
|
+
mentions?: string[];
|
|
76
|
+
}, options?: CallOptions): Promise<Message>;
|
|
77
|
+
deleteMessage(docId: string, threadId: string, messageId: string, options?: CallOptions): Promise<{
|
|
78
|
+
threadId: string;
|
|
79
|
+
messageId: string;
|
|
80
|
+
}>;
|
|
81
|
+
deleteThread(docId: string, threadId: string, options?: CallOptions): Promise<{
|
|
82
|
+
threadId: string;
|
|
83
|
+
}>;
|
|
84
|
+
exportPerson(docId: string, person: string, options?: CallOptions): Promise<PersonData>;
|
|
85
|
+
erasePerson(docId: string, person: string, options?: CallOptions): Promise<Erased>;
|
|
61
86
|
listSuggestions(docId: string, filter?: SuggestionListFilter, options?: CallOptions): Promise<Suggestion[]>;
|
|
62
87
|
suggest(docId: string, input: {
|
|
63
88
|
anchor: AnchorSpec;
|
|
@@ -69,4 +94,4 @@ interface CommentsClient {
|
|
|
69
94
|
}
|
|
70
95
|
declare function createClient(options: ClientOptions): CommentsClient;
|
|
71
96
|
|
|
72
|
-
export { AnchorSpec, type ApiErrorCode, type CallOptions, type ClientOptions, CommentsApiError, type CommentsClient, CommentsErrorCode, ListFilter, type Me, Message, NewReply, Suggestion, type SuggestionListFilter, Thread, type ThreadFilter, createClient };
|
|
97
|
+
export { AnchorSpec, type ApiErrorCode, type CallOptions, type ClientOptions, CommentsApiError, type CommentsClient, CommentsErrorCode, type Erased, ListFilter, type Me, Message, NewReply, type PersonData, PersonExport, PersonSuggestions, Suggestion, type SuggestionListFilter, Thread, type ThreadFilter, createClient };
|
package/dist/client.js
CHANGED
|
@@ -4,6 +4,7 @@ var CODES = {
|
|
|
4
4
|
INVALID_INPUT: true,
|
|
5
5
|
INVALID_ANCHOR: true,
|
|
6
6
|
NO_THREAD: true,
|
|
7
|
+
NO_MESSAGE: true,
|
|
7
8
|
THREAD_RESOLVED: true,
|
|
8
9
|
CORRUPT: true,
|
|
9
10
|
NO_SUGGESTION: true,
|
|
@@ -40,15 +41,21 @@ var CommentsApiError = class extends Error {
|
|
|
40
41
|
var KINDS = { human: true, agent_of_human: true, agent_of_agent: true, agent: true, user_token: true };
|
|
41
42
|
var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
42
43
|
var isString = (v) => typeof v === "string";
|
|
44
|
+
var isAuthor = (v) => isObject(v) && typeof v.kind === "string" && Object.hasOwn(KINDS, v.kind) && isString(v.name);
|
|
45
|
+
var personThread = (v) => isObject(v) && isString(v.threadId) && isObject(v.anchor) && Array.isArray(v.messages) && v.messages.every(SHAPES.message) && (v.statusChange === void 0 || isObject(v.statusChange) && (v.statusChange.status === "open" || v.statusChange.status === "resolved") && isString(v.statusChange.at) && isAuthor(v.statusChange.by));
|
|
43
46
|
var SHAPES = {
|
|
44
|
-
me: (v) => isObject(v) && (typeof v.kind === "string" && Object.hasOwn(KINDS, v.kind)) && isString(v.name) && Array.isArray(v.scopes),
|
|
47
|
+
me: (v) => isObject(v) && (typeof v.kind === "string" && Object.hasOwn(KINDS, v.kind)) && isString(v.name) && Array.isArray(v.scopes) && v.scopes.every(isString),
|
|
45
48
|
created: (v) => isObject(v) && isString(v.id),
|
|
46
49
|
document: (v) => isObject(v) && isString(v.id) && isString(v.text),
|
|
47
|
-
thread: (v) => isObject(v) && isString(v.id) && isObject(v.anchor) && (v.status === "open" || v.status === "resolved") && Array.isArray(v.messages),
|
|
50
|
+
thread: (v) => isObject(v) && isString(v.id) && isObject(v.anchor) && isObject(v.anchorState) && isString(v.anchorState.state) && (v.status === "open" || v.status === "resolved") && isAuthor(v.statusBy) && isString(v.statusAt) && Array.isArray(v.messages) && v.messages.every(SHAPES.message) && typeof v.skipped === "number",
|
|
48
51
|
threads: (v) => Array.isArray(v) && v.every(SHAPES.thread),
|
|
49
|
-
message: (v) => isObject(v) && isString(v.id) && isString(v.body) &&
|
|
50
|
-
suggestion: (v) => isObject(v) && isString(v.id) && isObject(v.anchor) && isString(v.status) &&
|
|
51
|
-
suggestions: (v) => Array.isArray(v) && v.every(SHAPES.suggestion)
|
|
52
|
+
message: (v) => isObject(v) && isString(v.id) && isString(v.at) && isString(v.body) && Array.isArray(v.mentions) && v.mentions.every(isString) && isAuthor(v.author) && (v.editedAt === void 0 || isString(v.editedAt)) && (v.editedBy === void 0 || isAuthor(v.editedBy)),
|
|
53
|
+
suggestion: (v) => isObject(v) && isString(v.id) && isObject(v.anchor) && isObject(v.anchorState) && isString(v.anchorState.state) && (v.status === "pending" || v.status === "accepted" || v.status === "rejected") && isAuthor(v.author) && isString(v.createdAt) && "change" in v && (v.summary === void 0 || isString(v.summary)) && (v.decidedBy === void 0 || isAuthor(v.decidedBy)) && (v.decidedAt === void 0 || isString(v.decidedAt)),
|
|
54
|
+
suggestions: (v) => Array.isArray(v) && v.every(SHAPES.suggestion),
|
|
55
|
+
deletedMessage: (v) => isObject(v) && isString(v.threadId) && isString(v.messageId),
|
|
56
|
+
deletedThread: (v) => isObject(v) && isString(v.threadId),
|
|
57
|
+
person: (v) => isObject(v) && isString(v.person) && isString(v.exportedAt) && Array.isArray(v.threads) && v.threads.every(personThread) && Array.isArray(v.edits) && v.edits.every((e) => isObject(e) && isString(e.threadId) && isString(e.messageId) && isString(e.at)) && typeof v.unread === "number" && isObject(v.suggestions) && Array.isArray(v.suggestions.authored) && v.suggestions.authored.every(SHAPES.suggestion) && Array.isArray(v.suggestions.decided) && v.suggestions.decided.every((d) => isObject(d) && isString(d.id) && (d.status === "accepted" || d.status === "rejected") && isString(d.at)) && typeof v.suggestions.unread === "number",
|
|
58
|
+
erased: (v) => isObject(v) && ["messages", "statuses", "edits", "suggestions", "decisions"].every((k) => typeof v[k] === "number")
|
|
52
59
|
};
|
|
53
60
|
function createClient(options) {
|
|
54
61
|
if (typeof options.baseUrl !== "string" || options.baseUrl === "") throw new TypeError("createClient needs a baseUrl");
|
|
@@ -120,6 +127,11 @@ function createClient(options) {
|
|
|
120
127
|
resolve: (id, threadId, o) => call("POST", `${thread(id, threadId)}/resolve`, void 0, o, "thread"),
|
|
121
128
|
reopen: (id, threadId, o) => call("POST", `${thread(id, threadId)}/reopen`, void 0, o, "thread"),
|
|
122
129
|
relocate: (id, threadId, o) => call("POST", `${thread(id, threadId)}/relocate`, void 0, o, "thread"),
|
|
130
|
+
editMessage: (id, threadId, messageId, input, o) => call("PATCH", `${thread(id, threadId)}/messages/${seg(messageId)}`, input, o, "message"),
|
|
131
|
+
deleteMessage: (id, threadId, messageId, o) => call("DELETE", `${thread(id, threadId)}/messages/${seg(messageId)}`, void 0, o, "deletedMessage"),
|
|
132
|
+
deleteThread: (id, threadId, o) => call("DELETE", thread(id, threadId), void 0, o, "deletedThread"),
|
|
133
|
+
exportPerson: (id, person, o) => call("GET", `${doc(id)}/people/${seg(person)}/export`, void 0, o, "person"),
|
|
134
|
+
erasePerson: (id, person, o) => call("DELETE", `${doc(id)}/people/${seg(person)}`, void 0, o, "erased"),
|
|
123
135
|
listSuggestions: (id, filter, o) => call("GET", `${doc(id)}/suggestions${query(filter)}`, void 0, o, "suggestions"),
|
|
124
136
|
suggest: (id, input, o) => call("POST", `${doc(id)}/suggestions`, input, o, "suggestion"),
|
|
125
137
|
accept: (id, suggestionId, o) => call("POST", `${suggestion(id, suggestionId)}/accept`, void 0, o, "suggestion"),
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type CommentsErrorCode = "INVALID_AUTHOR" | "INVALID_INPUT" | "INVALID_ANCHOR" | "NO_THREAD" | "NO_MESSAGE" | "THREAD_RESOLVED" | "CORRUPT" | "NO_SUGGESTION" | "FORBIDDEN" | "ALREADY_DECIDED" | "APPLY_FAILED" | "RELOCATE_FAILED" | "STORE_MISSING" | "STORE_EXISTS" | "STORE_CORRUPT" | "STORE_LOCKED" | "STORE_FULL" | "NO_DOCUMENT" | "DOCUMENT_EXISTS" | "CONFLICT" | "MISCONFIGURED" | "USAGE";
|
|
2
|
+
declare class CommentsError extends Error {
|
|
3
|
+
readonly code: CommentsErrorCode;
|
|
4
|
+
constructor(code: CommentsErrorCode, message: string);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export { type CommentsErrorCode as C, CommentsError as a };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
3
|
-
export { a as CommentsError, C as CommentsErrorCode } from './errors-
|
|
1
|
+
import { b as Author, C as Comments, c as Suggestions } from './suggestions-CnkEcTuY.js';
|
|
2
|
+
export { d as ACCEPT_SCOPE, A as Actor, e as Anchor, f as AnchorKind, g as AnchorState, h as ApplyContext, i as CanvasAnchor, j as CellAnchor, k as CommentsOptions, E as ERASED_BODY, l as ERASED_NAME, m as EditMessage, n as MODERATE_SCOPE, M as Message, N as NewReply, o as NewSuggestion, p as NewThread, P as PersonExport, R as RelativePositionJson, q as RevertContext, r as SlideAnchor, s as StampInput, S as Suggestion, t as SuggestionFilter, u as SuggestionHost, v as TextAnchor, T as Thread, w as ThreadFilter, x as authorLabel, y as stamp, z as textAnchor, B as textOf } from './suggestions-CnkEcTuY.js';
|
|
3
|
+
export { a as CommentsError, C as CommentsErrorCode } from './errors-C-xvp24-.js';
|
|
4
4
|
export { PRINCIPAL_KINDS, PrincipalKind } from 'agentic-identity';
|
|
5
5
|
import 'yjs';
|
|
6
6
|
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
VERSION
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ES3NZ7SX.js";
|
|
4
4
|
import {
|
|
5
5
|
ACCEPT_SCOPE,
|
|
6
6
|
Actor,
|
|
7
7
|
Comments,
|
|
8
8
|
CommentsError,
|
|
9
|
+
ERASED_BODY,
|
|
10
|
+
ERASED_NAME,
|
|
11
|
+
MODERATE_SCOPE,
|
|
9
12
|
PRINCIPAL_KINDS,
|
|
10
13
|
Suggestions,
|
|
11
14
|
authorLabel,
|
|
@@ -14,7 +17,7 @@ import {
|
|
|
14
17
|
textAnchor,
|
|
15
18
|
textOf,
|
|
16
19
|
validDate
|
|
17
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-VAVKBAHM.js";
|
|
18
21
|
|
|
19
22
|
// src/notifications.ts
|
|
20
23
|
import * as Y from "yjs";
|
|
@@ -134,7 +137,16 @@ var Notifications = class {
|
|
|
134
137
|
if (change) this.statusChanged(String(path[0]), change.oldValue, source);
|
|
135
138
|
} else if (path.length === 2 && path[1] === "messages" && event.target instanceof Y.Array) {
|
|
136
139
|
const ids = /* @__PURE__ */ new Set();
|
|
137
|
-
|
|
140
|
+
const changes = event.changes;
|
|
141
|
+
const replaced = /* @__PURE__ */ new Set();
|
|
142
|
+
for (const item of changes.deleted) for (const raw of item.content.getContent()) replaced.add(raw?.id);
|
|
143
|
+
const seen = /* @__PURE__ */ new Set();
|
|
144
|
+
for (const raw of event.target.toArray()) {
|
|
145
|
+
const id = raw?.id;
|
|
146
|
+
if (seen.has(id)) replaced.add(id);
|
|
147
|
+
seen.add(id);
|
|
148
|
+
}
|
|
149
|
+
for (const item of changes.added) for (const raw of item.content.getContent()) if (!replaced.has(raw?.id)) ids.add(raw?.id);
|
|
138
150
|
this.messagesAdded(String(path[0]), ids, source);
|
|
139
151
|
}
|
|
140
152
|
});
|
|
@@ -212,6 +224,9 @@ export {
|
|
|
212
224
|
Actor,
|
|
213
225
|
Comments,
|
|
214
226
|
CommentsError,
|
|
227
|
+
ERASED_BODY,
|
|
228
|
+
ERASED_NAME,
|
|
229
|
+
MODERATE_SCOPE,
|
|
215
230
|
Notifications,
|
|
216
231
|
PRINCIPAL_KINDS,
|
|
217
232
|
Suggestions,
|
package/dist/local.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as Y from 'yjs';
|
|
2
|
-
export { A as AnchorSpec, C as CommentsService, L as ListFilter } from './service-
|
|
3
|
-
import {
|
|
2
|
+
export { A as AnchorSpec, C as CommentsService, L as ListFilter } from './service-BvIE6t5n.js';
|
|
3
|
+
import { u as SuggestionHost, A as Actor } from './suggestions-CnkEcTuY.js';
|
|
4
4
|
import 'agentic-identity';
|
|
5
5
|
|
|
6
6
|
/** The most bytes a saved document holds. A save over this is refused, so a file never grows past what a load accepts. */
|
package/dist/local.js
CHANGED
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
MAX_FILE,
|
|
4
4
|
lockTimeoutFrom,
|
|
5
5
|
operatorActor
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2NBFTJ47.js";
|
|
7
7
|
import {
|
|
8
8
|
CommentsService,
|
|
9
9
|
TEXT_ROOT,
|
|
10
10
|
VALUES_ROOT,
|
|
11
11
|
localHost
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-T77DPNIV.js";
|
|
13
|
+
import "./chunk-VAVKBAHM.js";
|
|
14
14
|
export {
|
|
15
15
|
CommentsService,
|
|
16
16
|
FileStore,
|
package/dist/mcp-bin.js
CHANGED
|
@@ -3,15 +3,15 @@ import {
|
|
|
3
3
|
FileStore,
|
|
4
4
|
lockTimeoutFrom,
|
|
5
5
|
operatorActor
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2NBFTJ47.js";
|
|
7
7
|
import {
|
|
8
8
|
startMcp
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-SR2A5OZW.js";
|
|
10
10
|
import {
|
|
11
11
|
VERSION
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-ES3NZ7SX.js";
|
|
13
|
+
import "./chunk-T77DPNIV.js";
|
|
14
|
+
import "./chunk-VAVKBAHM.js";
|
|
15
15
|
|
|
16
16
|
// src/mcp-bin.ts
|
|
17
17
|
var MCP_HELP = `agentic-comments-mcp ${VERSION}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as Y from 'yjs';
|
|
2
|
-
import { A as Actor, T as Thread, M as Message, S as Suggestion } from './suggestions-
|
|
2
|
+
import { A as Actor, T as Thread, M as Message, P as PersonExport, a as PersonSuggestions, S as Suggestion } from './suggestions-CnkEcTuY.js';
|
|
3
3
|
|
|
4
4
|
/** Where a comment or suggestion points, in terms a person or agent can write down. */
|
|
5
5
|
type AnchorSpec = {
|
|
@@ -51,6 +51,29 @@ declare class CommentsService {
|
|
|
51
51
|
resolve(threadId: string): Thread;
|
|
52
52
|
reopen(threadId: string): Thread;
|
|
53
53
|
relocate(threadId: string): Thread;
|
|
54
|
+
editMessage(threadId: string, messageId: string, input: {
|
|
55
|
+
body: string;
|
|
56
|
+
mentions?: string[];
|
|
57
|
+
}): Message;
|
|
58
|
+
deleteMessage(threadId: string, messageId: string): {
|
|
59
|
+
threadId: string;
|
|
60
|
+
messageId: string;
|
|
61
|
+
};
|
|
62
|
+
deleteThread(threadId: string): {
|
|
63
|
+
threadId: string;
|
|
64
|
+
};
|
|
65
|
+
/** Everything the store holds that this person wrote: messages, status changes, and suggestions. */
|
|
66
|
+
exportPerson(person: string): PersonExport & {
|
|
67
|
+
suggestions: PersonSuggestions;
|
|
68
|
+
};
|
|
69
|
+
/** Tombstone everything this person wrote. Both parts are checked before either is written. */
|
|
70
|
+
erasePerson(person: string): {
|
|
71
|
+
messages: number;
|
|
72
|
+
statuses: number;
|
|
73
|
+
edits: number;
|
|
74
|
+
suggestions: number;
|
|
75
|
+
decisions: number;
|
|
76
|
+
};
|
|
54
77
|
suggestions(filter?: ListFilter): Suggestion[];
|
|
55
78
|
suggest(input: {
|
|
56
79
|
anchor: AnchorSpec;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as Y from 'yjs';
|
|
2
2
|
import { PrincipalKind } from 'agentic-identity';
|
|
3
3
|
|
|
4
|
+
/** The name an erased author shows. No principal may have it, so a tombstone belongs to no one. */
|
|
5
|
+
declare const ERASED_NAME = "erased";
|
|
6
|
+
|
|
4
7
|
/** What a thread keeps about who wrote a message. Scopes never reach storage. */
|
|
5
8
|
interface Author {
|
|
6
9
|
kind: PrincipalKind;
|
|
@@ -102,6 +105,11 @@ interface Message {
|
|
|
102
105
|
body: string;
|
|
103
106
|
/** Handles named in the body or listed on the input, without the `@`. */
|
|
104
107
|
mentions: string[];
|
|
108
|
+
/** Set when the message was edited. A message that was never edited has none. */
|
|
109
|
+
editedAt?: string;
|
|
110
|
+
editedBy?: Author;
|
|
111
|
+
/** True for a message that `erasePerson` replaced with a tombstone. */
|
|
112
|
+
erased?: true;
|
|
105
113
|
}
|
|
106
114
|
interface Thread {
|
|
107
115
|
id: string;
|
|
@@ -138,6 +146,34 @@ interface NewReply {
|
|
|
138
146
|
body: string;
|
|
139
147
|
mentions?: string[];
|
|
140
148
|
}
|
|
149
|
+
interface EditMessage {
|
|
150
|
+
body: string;
|
|
151
|
+
mentions?: string[];
|
|
152
|
+
}
|
|
153
|
+
/** What the store holds about one person in one document. It lists only that person's own words and acts. */
|
|
154
|
+
interface PersonExport {
|
|
155
|
+
person: string;
|
|
156
|
+
exportedAt: string;
|
|
157
|
+
threads: {
|
|
158
|
+
threadId: string;
|
|
159
|
+
anchor: Anchor;
|
|
160
|
+
messages: Message[];
|
|
161
|
+
/** Set when this person made the status change that stands now. */
|
|
162
|
+
statusChange?: {
|
|
163
|
+
status: Thread["status"];
|
|
164
|
+
at: string;
|
|
165
|
+
by: Author;
|
|
166
|
+
};
|
|
167
|
+
}[];
|
|
168
|
+
/** Messages by other people that this person edited. */
|
|
169
|
+
edits: {
|
|
170
|
+
threadId: string;
|
|
171
|
+
messageId: string;
|
|
172
|
+
at: string;
|
|
173
|
+
}[];
|
|
174
|
+
/** Stored entries with this person's name that the export cannot show. Not 0 means the export is not complete. */
|
|
175
|
+
unread: number;
|
|
176
|
+
}
|
|
141
177
|
interface ThreadFilter {
|
|
142
178
|
status?: Thread["status"];
|
|
143
179
|
anchorType?: string;
|
|
@@ -145,6 +181,11 @@ interface ThreadFilter {
|
|
|
145
181
|
mentioning?: string;
|
|
146
182
|
anchorState?: AnchorState["state"];
|
|
147
183
|
}
|
|
184
|
+
/** A scope that lets a principal edit, delete, export, or erase what another person wrote. A host gives it to an owner or admin. */
|
|
185
|
+
declare const MODERATE_SCOPE = "comments:moderate";
|
|
186
|
+
/** What an erased message shows in place of its body. The author shows `ERASED_NAME`. */
|
|
187
|
+
declare const ERASED_BODY = "[erased]";
|
|
188
|
+
|
|
148
189
|
/** Comment threads on a Yjs document. Replies and status merge across replicas. */
|
|
149
190
|
declare class Comments {
|
|
150
191
|
readonly ydoc: Y.Doc;
|
|
@@ -188,6 +229,62 @@ declare class Comments {
|
|
|
188
229
|
relocate(threadId: string, actor: Actor): Thread;
|
|
189
230
|
resolve(threadId: string, actor: Actor): Thread;
|
|
190
231
|
reopen(threadId: string, actor: Actor): Thread;
|
|
232
|
+
/** A principal may change what it wrote. A principal with the moderate scope may change what anyone wrote. A tombstone is nobody's. */
|
|
233
|
+
private mayChange;
|
|
234
|
+
private forbid;
|
|
235
|
+
/** Replace every stored copy of a message with `next`, or remove it when `next` is undefined. */
|
|
236
|
+
private rewrite;
|
|
237
|
+
private find;
|
|
238
|
+
/** Change the body of a message. Its author and time stay, and it records who edited it and when. */
|
|
239
|
+
editMessage(threadId: string, messageId: string, input: EditMessage, actor: Actor): Message;
|
|
240
|
+
private readEdited;
|
|
241
|
+
/**
|
|
242
|
+
* Remove one message, also from a resolved thread. The last message of a thread stays: delete the thread instead. Replicas that delete
|
|
243
|
+
* two messages at once can leave a thread with none. A moderator can still delete that thread.
|
|
244
|
+
*/
|
|
245
|
+
deleteMessage(threadId: string, messageId: string, actor: Actor): {
|
|
246
|
+
threadId: string;
|
|
247
|
+
messageId: string;
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* Remove a thread and all its messages. Its author may do it when every message is theirs. Once someone
|
|
251
|
+
* else replied, a message is erased, or a stored message cannot be read, it needs the moderate scope. A
|
|
252
|
+
* moderator can also remove a thread that cannot be read at all.
|
|
253
|
+
*/
|
|
254
|
+
deleteThread(threadId: string, actor: Actor): {
|
|
255
|
+
threadId: string;
|
|
256
|
+
};
|
|
257
|
+
/**
|
|
258
|
+
* Check who an export or erase is for, and that the actor may. A person may act on their own data: the same
|
|
259
|
+
* kind and name. A principal with the moderate scope may act on anyone's, and then every kind with that name is
|
|
260
|
+
* included. Returns the name and a test for an author. Used by `Suggestions`.
|
|
261
|
+
*/
|
|
262
|
+
checkPerson(person: unknown, actor: Actor): {
|
|
263
|
+
name: string;
|
|
264
|
+
match: (author: Author) => boolean;
|
|
265
|
+
};
|
|
266
|
+
/** The raw stored threads, for the code that must see data a read hides. `list` is missing when the message field is bad. */
|
|
267
|
+
private stored;
|
|
268
|
+
/**
|
|
269
|
+
* What a person wrote in this document: their messages, the status change of theirs that stands, and the
|
|
270
|
+
* edits they made to other people's messages. `unread` counts stored entries with their name that this read
|
|
271
|
+
* cannot show: a bad message, a thread that cannot be read, a message past the read limit, or a copy that
|
|
272
|
+
* lost a merge. When it is not 0 the export is not complete. A person may export their own data.
|
|
273
|
+
*/
|
|
274
|
+
exportPerson(person: string, actor: Actor): PersonExport;
|
|
275
|
+
/**
|
|
276
|
+
* Replace every message a person wrote with a tombstone: the body becomes "[erased]", the author name
|
|
277
|
+
* becomes "erased", and the mentions go. The author kind stays, so machine-made work stays marked. Thread
|
|
278
|
+
* shape, order, and times stay. A status change of theirs, and their name as the editor of another person's
|
|
279
|
+
* message, get the tombstone name. It works on the stored entries, so it reaches a bad message, a message past
|
|
280
|
+
* the read limit, a thread that cannot be read, and every copy that a merge hid. Names inside other people's
|
|
281
|
+
* messages are not touched. Returns how many messages, status changes, and edit stamps it erased.
|
|
282
|
+
*/
|
|
283
|
+
erasePerson(person: string, actor: Actor): {
|
|
284
|
+
messages: number;
|
|
285
|
+
statuses: number;
|
|
286
|
+
edits: number;
|
|
287
|
+
};
|
|
191
288
|
get(threadId: string): Thread;
|
|
192
289
|
/** Threads in the order they were started. A malformed thread is skipped; `problems()` names it. */
|
|
193
290
|
list(filter?: ThreadFilter): Thread[];
|
|
@@ -215,6 +312,17 @@ interface Suggestion {
|
|
|
215
312
|
decidedBy?: Author;
|
|
216
313
|
decidedAt?: string;
|
|
217
314
|
}
|
|
315
|
+
/** What a person wrote and decided among the suggestions of one document. */
|
|
316
|
+
interface PersonSuggestions {
|
|
317
|
+
authored: Suggestion[];
|
|
318
|
+
decided: {
|
|
319
|
+
id: string;
|
|
320
|
+
status: "accepted" | "rejected";
|
|
321
|
+
at: string;
|
|
322
|
+
}[];
|
|
323
|
+
/** Stored entries with this person's name that the export cannot show. Not 0 means it is not complete. */
|
|
324
|
+
unread: number;
|
|
325
|
+
}
|
|
218
326
|
interface ApplyContext {
|
|
219
327
|
suggestionId: string;
|
|
220
328
|
anchor: Anchor;
|
|
@@ -302,6 +410,25 @@ declare class Suggestions {
|
|
|
302
410
|
private index;
|
|
303
411
|
private read;
|
|
304
412
|
private fields;
|
|
413
|
+
/**
|
|
414
|
+
* The suggestions a person wrote, and the decisions they made, in this document. `unread` counts stored
|
|
415
|
+
* suggestions and decision records with their name that this export cannot show: a suggestion that cannot
|
|
416
|
+
* be read, a decision that lost a merge, a refused decision, or a decision with no suggestion. When it is not
|
|
417
|
+
* 0 the export is not complete. A person may export their own data.
|
|
418
|
+
*/
|
|
419
|
+
exportPerson(person: string, actor: Actor): PersonSuggestions;
|
|
420
|
+
private named;
|
|
421
|
+
/**
|
|
422
|
+
* Give every suggestion a person wrote a tombstone author and drop its summary. An accepted one keeps its
|
|
423
|
+
* change, because that change is already part of the content. A pending or rejected one loses its change, and
|
|
424
|
+
* can no longer be accepted. A decision they made gets a tombstone decider. A decision that a read refuses (a
|
|
425
|
+
* principal that decided its own work) is deleted, so erase never turns it into a valid one. Returns how many
|
|
426
|
+
* suggestions and decisions it changed.
|
|
427
|
+
*/
|
|
428
|
+
erasePerson(person: string, actor: Actor): {
|
|
429
|
+
suggestions: number;
|
|
430
|
+
decisions: number;
|
|
431
|
+
};
|
|
305
432
|
/** Propose a change. Anyone can suggest. The host stamps the author. */
|
|
306
433
|
add(input: NewSuggestion, actor: Actor): Suggestion;
|
|
307
434
|
/** A person decides. An agent needs the accept scope, and never decides its own suggestion. */
|
|
@@ -330,4 +457,4 @@ declare class Suggestions {
|
|
|
330
457
|
settle(): void;
|
|
331
458
|
}
|
|
332
459
|
|
|
333
|
-
export { Actor as A, Comments as C, type Message as M, type NewReply as N, type RelativePositionJson as R, type Suggestion as S, type Thread as T, type
|
|
460
|
+
export { Actor as A, textOf as B, Comments as C, ERASED_BODY as E, type Message as M, type NewReply as N, type PersonExport as P, type RelativePositionJson as R, type Suggestion as S, type Thread as T, type PersonSuggestions as a, type Author as b, Suggestions as c, ACCEPT_SCOPE as d, type Anchor as e, type AnchorKind as f, type AnchorState as g, type ApplyContext as h, type CanvasAnchor as i, type CellAnchor as j, type CommentsOptions as k, ERASED_NAME as l, type EditMessage as m, MODERATE_SCOPE as n, type NewSuggestion as o, type NewThread as p, type RevertContext as q, type SlideAnchor as r, type StampInput as s, type SuggestionFilter as t, type SuggestionHost as u, type TextAnchor as v, type ThreadFilter as w, authorLabel as x, stamp as y, textAnchor as z };
|
package/dist/worker.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { Hono } from 'hono';
|
|
|
2
2
|
import { Auth, Store, PrincipalContext, Region } from 'agentic-identity';
|
|
3
3
|
import { RequirePrincipalOptions } from 'agentic-identity/http';
|
|
4
4
|
import { D1Like } from 'agentic-identity/cloudflare';
|
|
5
|
-
import { A as Actor } from './suggestions-
|
|
6
|
-
import { C as CommentsService } from './service-
|
|
5
|
+
import { A as Actor } from './suggestions-CnkEcTuY.js';
|
|
6
|
+
import { C as CommentsService } from './service-BvIE6t5n.js';
|
|
7
7
|
import 'yjs';
|
|
8
8
|
|
|
9
9
|
interface WorkerEnv {
|
|
@@ -13,8 +13,10 @@ interface WorkerEnv {
|
|
|
13
13
|
AGENTIC_COMMENTS_UNSAFE_REGION?: string;
|
|
14
14
|
/** D1 database: each document, with its threads, as a Yjs update. */
|
|
15
15
|
DB?: D1Like;
|
|
16
|
+
/** Set to "1" to read `AGENTIC_COMMENTS_TOKENS`. Without it the list never signs anyone in, and a request gets 503 when the list is set. A dev fallback: never set it in production. */
|
|
17
|
+
AGENTIC_COMMENTS_UNSAFE_STATIC_TOKENS?: string;
|
|
16
18
|
/**
|
|
17
|
-
* JSON object: bearer token (32 to 512 bytes of A-Z a-z 0-9 _ -) to `kind:name` (the name uses A-Z a-z 0-9 . _ -), or to `{ "as": "kind:name", "scopes": ["comments:write"] }`.
|
|
19
|
+
* Dev fallback, read only when `AGENTIC_COMMENTS_UNSAFE_STATIC_TOKENS` is "1". It is tried after the identity credentials. JSON object: bearer token (32 to 512 bytes of A-Z a-z 0-9 _ -) to `kind:name` (the name uses A-Z a-z 0-9 . _ -), or to `{ "as": "kind:name", "scopes": ["comments:write"] }`.
|
|
18
20
|
* Set it as a secret. A short token or a bad entry refuses the whole config.
|
|
19
21
|
*/
|
|
20
22
|
AGENTIC_COMMENTS_TOKENS?: string;
|
|
@@ -26,7 +28,7 @@ interface WorkerEnv {
|
|
|
26
28
|
declare function createTokenAuth(raw: string | undefined): Auth;
|
|
27
29
|
/** The documents, on the `Store` port. Each write loads the document, runs the change, and saves in one transaction. */
|
|
28
30
|
declare class CommentsDocs {
|
|
29
|
-
|
|
31
|
+
readonly store: Store;
|
|
30
32
|
constructor(store: Store);
|
|
31
33
|
private id;
|
|
32
34
|
private load;
|
|
@@ -38,7 +40,10 @@ declare class CommentsDocs {
|
|
|
38
40
|
/** The docs, or a function that makes them from the Worker bindings. */
|
|
39
41
|
type DocsSource = CommentsDocs | ((env: WorkerEnv) => Promise<CommentsDocs>);
|
|
40
42
|
interface AppOptions {
|
|
41
|
-
/**
|
|
43
|
+
/**
|
|
44
|
+
* The credential check. The default reads credentials and principals from the Store of the documents (`createStoreAuth`),
|
|
45
|
+
* then the static list when `AGENTIC_COMMENTS_UNSAFE_STATIC_TOKENS=1`. Pass any `Auth` from agentic-identity to replace it.
|
|
46
|
+
*/
|
|
42
47
|
auth?: Auth | ((env: WorkerEnv) => Auth);
|
|
43
48
|
/** Origins that may send a write with a session cookie. A bearer token needs none. Passed to `requirePrincipal`. */
|
|
44
49
|
origins?: RequirePrincipalOptions["origins"];
|