@aloth/olcli 0.14.0 → 0.15.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 +5 -1
- package/dist/cli.js +103 -3
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +83 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +205 -2
- package/dist/client.js.map +1 -1
- package/dist/mcp.js +45 -5
- package/dist/mcp.js.map +1 -1
- package/dist/tracked-changes.d.ts +136 -0
- package/dist/tracked-changes.d.ts.map +1 -0
- package/dist/tracked-changes.js +250 -0
- package/dist/tracked-changes.js.map +1 -0
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* Read docs/ARCHITECTURE.md before changing anything in this file.
|
|
16
16
|
*/
|
|
17
|
+
import { RejectConflictError, type ShareJsTextOp, type TrackedChangeAuthor, type TrackedChangeKind } from './tracked-changes.js';
|
|
17
18
|
export interface Project {
|
|
18
19
|
id: string;
|
|
19
20
|
name: string;
|
|
@@ -104,6 +105,48 @@ export declare const MAX_COMMENT_CONCURRENCY = 8;
|
|
|
104
105
|
* then the default. Throws on anything that is not an integer from 1 to 8.
|
|
105
106
|
*/
|
|
106
107
|
export declare function resolveCommentConcurrency(value?: number | string, env?: NodeJS.ProcessEnv): number;
|
|
108
|
+
/** A tracked change (suggested edit) with its project location. */
|
|
109
|
+
export interface TrackedChange {
|
|
110
|
+
id: string;
|
|
111
|
+
docId: string;
|
|
112
|
+
path: string;
|
|
113
|
+
kind: TrackedChangeKind;
|
|
114
|
+
/** Offset into the visible text of the doc, tracked deletes excluded. */
|
|
115
|
+
position: number;
|
|
116
|
+
line: number;
|
|
117
|
+
column: number;
|
|
118
|
+
/** Inserted text for an insert, removed text for a delete. */
|
|
119
|
+
text: string;
|
|
120
|
+
author: TrackedChangeAuthor;
|
|
121
|
+
timestamp?: string;
|
|
122
|
+
context?: CommentContext;
|
|
123
|
+
}
|
|
124
|
+
export interface ListTrackedChangesOptions {
|
|
125
|
+
contextLines?: number;
|
|
126
|
+
/** Sockets used to join docs in parallel (1-8). Defaults to OLCLI_CONCURRENCY, else 4. */
|
|
127
|
+
concurrency?: number;
|
|
128
|
+
}
|
|
129
|
+
/** Comments and tracked changes from a single pass over the project's docs. */
|
|
130
|
+
export interface ProjectReview {
|
|
131
|
+
comments: ProjectComment[];
|
|
132
|
+
changes: TrackedChange[];
|
|
133
|
+
}
|
|
134
|
+
export interface RejectionDocPlan {
|
|
135
|
+
docId: string;
|
|
136
|
+
path: string;
|
|
137
|
+
/** Doc version the plan was computed at. */
|
|
138
|
+
version: number;
|
|
139
|
+
changes: TrackedChange[];
|
|
140
|
+
/** ShareJS ops in the order they are sent, highest position first. */
|
|
141
|
+
ops: ShareJsTextOp[];
|
|
142
|
+
/** Unified diff of the doc before and after the rejection. */
|
|
143
|
+
diff: string;
|
|
144
|
+
}
|
|
145
|
+
export interface RejectionPlan {
|
|
146
|
+
changes: TrackedChange[];
|
|
147
|
+
docs: RejectionDocPlan[];
|
|
148
|
+
}
|
|
149
|
+
export { RejectConflictError };
|
|
107
150
|
export interface AddCommentOptions {
|
|
108
151
|
filePath: string;
|
|
109
152
|
content: string;
|
|
@@ -403,6 +446,46 @@ export declare class OverleafClient {
|
|
|
403
446
|
*/
|
|
404
447
|
private joinDocuments;
|
|
405
448
|
listComments(projectId: string, options?: ListCommentsOptions): Promise<ProjectComment[]>;
|
|
449
|
+
/** Comments and tracked changes from a single pass over the project's docs. */
|
|
450
|
+
listReview(projectId: string, options?: ListCommentsOptions): Promise<ProjectReview>;
|
|
451
|
+
private commentsFromDocs;
|
|
452
|
+
/**
|
|
453
|
+
* Users who made tracked changes, including people no longer on the
|
|
454
|
+
* project. Best effort: an error here only costs author names.
|
|
455
|
+
*/
|
|
456
|
+
private getChangesUsers;
|
|
457
|
+
/** Tracked changes of one joined doc, with the visible text their positions refer to. */
|
|
458
|
+
private docTrackedChanges;
|
|
459
|
+
/**
|
|
460
|
+
* List tracked changes (suggested insertions and deletions) across the
|
|
461
|
+
* project, sorted by path and position.
|
|
462
|
+
*/
|
|
463
|
+
listTrackedChanges(projectId: string, options?: ListTrackedChangesOptions): Promise<TrackedChange[]>;
|
|
464
|
+
private changesFromDocs;
|
|
465
|
+
/**
|
|
466
|
+
* Accept tracked changes: the suggested text stays and the suggestion
|
|
467
|
+
* markers go. Ids come from `listTrackedChanges`. Every id must resolve
|
|
468
|
+
* before anything is sent; changes are accepted per doc with one request
|
|
469
|
+
* each (POST /project/<id>/doc/<doc>/changes/accept, the editor's route).
|
|
470
|
+
* Afterwards the project is re-read and any id still present is an error.
|
|
471
|
+
*/
|
|
472
|
+
acceptTrackedChanges(projectId: string, ids: string[]): Promise<TrackedChange[]>;
|
|
473
|
+
private selectTrackedChanges;
|
|
474
|
+
/**
|
|
475
|
+
* Work out what rejecting `ids` would do, without writing anything:
|
|
476
|
+
* per doc the ops to send and a diff of the result. Fails with
|
|
477
|
+
* RejectConflictError if a change no longer matches the text, and refuses
|
|
478
|
+
* history-ot docs, whose rejection path is not implemented.
|
|
479
|
+
*/
|
|
480
|
+
planTrackedChangeRejection(projectId: string, ids: string[]): Promise<RejectionPlan>;
|
|
481
|
+
/**
|
|
482
|
+
* Reject tracked changes: inserted text is removed, deleted text is put
|
|
483
|
+
* back. The plan is recomputed per doc right before writing, and a doc
|
|
484
|
+
* whose version moved since `plan` was made is refused, so the user never
|
|
485
|
+
* applies something other than the preview they saw. Afterwards the
|
|
486
|
+
* project is re-read and any id still present is an error.
|
|
487
|
+
*/
|
|
488
|
+
rejectTrackedChanges(projectId: string, plan: RejectionPlan): Promise<RejectionPlan>;
|
|
406
489
|
resolveComment(projectId: string, threadId: string): Promise<ProjectComment>;
|
|
407
490
|
reopenComment(projectId: string, threadId: string): Promise<ProjectComment>;
|
|
408
491
|
deleteComment(projectId: string, threadId: string): Promise<ProjectComment>;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
CHANGED
|
@@ -20,6 +20,7 @@ import { dirname, join } from 'node:path';
|
|
|
20
20
|
import { fileURLToPath } from 'node:url';
|
|
21
21
|
import * as https from 'node:https';
|
|
22
22
|
import * as http from 'node:http';
|
|
23
|
+
import { RejectConflictError, buildUserDirectory, planRejection, renderRejectionDiff, describeAuthor, parseHistoryOtChanges, parseShareJsChanges } from './tracked-changes.js';
|
|
23
24
|
// Read version from package.json
|
|
24
25
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
25
26
|
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
@@ -43,6 +44,7 @@ export function resolveCommentConcurrency(value, env = process.env) {
|
|
|
43
44
|
}
|
|
44
45
|
return parsed;
|
|
45
46
|
}
|
|
47
|
+
export { RejectConflictError };
|
|
46
48
|
export class OverleafClient {
|
|
47
49
|
cookies;
|
|
48
50
|
csrf;
|
|
@@ -1017,6 +1019,12 @@ export class OverleafClient {
|
|
|
1017
1019
|
comment.op.c = this.decodeOverleafUtf8(comment.op.c);
|
|
1018
1020
|
}
|
|
1019
1021
|
}
|
|
1022
|
+
for (const change of decodedRanges.changes || []) {
|
|
1023
|
+
if (typeof change?.op?.i === 'string')
|
|
1024
|
+
change.op.i = this.decodeOverleafUtf8(change.op.i);
|
|
1025
|
+
if (typeof change?.op?.d === 'string')
|
|
1026
|
+
change.op.d = this.decodeOverleafUtf8(change.op.d);
|
|
1027
|
+
}
|
|
1020
1028
|
return {
|
|
1021
1029
|
docId,
|
|
1022
1030
|
lines: decodedLines,
|
|
@@ -1758,13 +1766,26 @@ export class OverleafClient {
|
|
|
1758
1766
|
return joined;
|
|
1759
1767
|
}
|
|
1760
1768
|
async listComments(projectId, options = {}) {
|
|
1761
|
-
const
|
|
1769
|
+
const projectInfo = await this.getProjectInfo(projectId);
|
|
1770
|
+
const docs = this.collectProjectDocs(projectInfo);
|
|
1771
|
+
const threads = await this.getCommentThreads(projectId);
|
|
1772
|
+
const joinedDocs = await this.joinDocuments(projectId, docs, resolveCommentConcurrency(options.concurrency));
|
|
1773
|
+
return this.commentsFromDocs(docs, joinedDocs, threads, options.status || 'all', options.contextLines || 0);
|
|
1774
|
+
}
|
|
1775
|
+
/** Comments and tracked changes from a single pass over the project's docs. */
|
|
1776
|
+
async listReview(projectId, options = {}) {
|
|
1762
1777
|
const contextLines = options.contextLines || 0;
|
|
1763
1778
|
const projectInfo = await this.getProjectInfo(projectId);
|
|
1764
1779
|
const docs = this.collectProjectDocs(projectInfo);
|
|
1765
1780
|
const threads = await this.getCommentThreads(projectId);
|
|
1766
|
-
const comments = [];
|
|
1767
1781
|
const joinedDocs = await this.joinDocuments(projectId, docs, resolveCommentConcurrency(options.concurrency));
|
|
1782
|
+
return {
|
|
1783
|
+
comments: this.commentsFromDocs(docs, joinedDocs, threads, options.status || 'all', contextLines),
|
|
1784
|
+
changes: await this.changesFromDocs(projectId, projectInfo, docs, joinedDocs, contextLines)
|
|
1785
|
+
};
|
|
1786
|
+
}
|
|
1787
|
+
commentsFromDocs(docs, joinedDocs, threads, status, contextLines) {
|
|
1788
|
+
const comments = [];
|
|
1768
1789
|
for (const [index, doc] of docs.entries()) {
|
|
1769
1790
|
const joinedDoc = joinedDocs[index];
|
|
1770
1791
|
if (joinedDoc.type === 'history-ot') {
|
|
@@ -1827,6 +1848,188 @@ export class OverleafClient {
|
|
|
1827
1848
|
})
|
|
1828
1849
|
.sort((a, b) => a.path.localeCompare(b.path) || a.position - b.position);
|
|
1829
1850
|
}
|
|
1851
|
+
/**
|
|
1852
|
+
* Users who made tracked changes, including people no longer on the
|
|
1853
|
+
* project. Best effort: an error here only costs author names.
|
|
1854
|
+
*/
|
|
1855
|
+
async getChangesUsers(projectId) {
|
|
1856
|
+
try {
|
|
1857
|
+
const response = await this.httpRequest(`${this.baseUrl}/project/${projectId}/changes/users`, {
|
|
1858
|
+
headers: this.getHeaders(),
|
|
1859
|
+
expect: 'json'
|
|
1860
|
+
});
|
|
1861
|
+
if (!response.ok || !Array.isArray(response.body))
|
|
1862
|
+
return [];
|
|
1863
|
+
return response.body;
|
|
1864
|
+
}
|
|
1865
|
+
catch {
|
|
1866
|
+
return [];
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
/** Tracked changes of one joined doc, with the visible text their positions refer to. */
|
|
1870
|
+
docTrackedChanges(joinedDoc) {
|
|
1871
|
+
if (joinedDoc.type === 'history-ot')
|
|
1872
|
+
return parseHistoryOtChanges(joinedDoc.ranges);
|
|
1873
|
+
return { changes: parseShareJsChanges(joinedDoc.ranges), visibleContent: joinedDoc.content };
|
|
1874
|
+
}
|
|
1875
|
+
/**
|
|
1876
|
+
* List tracked changes (suggested insertions and deletions) across the
|
|
1877
|
+
* project, sorted by path and position.
|
|
1878
|
+
*/
|
|
1879
|
+
async listTrackedChanges(projectId, options = {}) {
|
|
1880
|
+
const projectInfo = await this.getProjectInfo(projectId);
|
|
1881
|
+
const docs = this.collectProjectDocs(projectInfo);
|
|
1882
|
+
const joinedDocs = await this.joinDocuments(projectId, docs, resolveCommentConcurrency(options.concurrency));
|
|
1883
|
+
return this.changesFromDocs(projectId, projectInfo, docs, joinedDocs, options.contextLines || 0);
|
|
1884
|
+
}
|
|
1885
|
+
async changesFromDocs(projectId, projectInfo, docs, joinedDocs, contextLines) {
|
|
1886
|
+
const perDoc = joinedDocs.map(doc => this.docTrackedChanges(doc));
|
|
1887
|
+
const anyChanges = perDoc.some(doc => doc.changes.length > 0);
|
|
1888
|
+
const users = buildUserDirectory(projectInfo, anyChanges ? await this.getChangesUsers(projectId) : []);
|
|
1889
|
+
const result = [];
|
|
1890
|
+
for (const [index, doc] of docs.entries()) {
|
|
1891
|
+
const { changes, visibleContent } = perDoc[index];
|
|
1892
|
+
for (const change of changes) {
|
|
1893
|
+
const location = this.positionToLineColumn(visibleContent, change.position);
|
|
1894
|
+
result.push({
|
|
1895
|
+
id: change.id,
|
|
1896
|
+
docId: doc.id,
|
|
1897
|
+
path: doc.path,
|
|
1898
|
+
kind: change.kind,
|
|
1899
|
+
position: change.position,
|
|
1900
|
+
line: location.line,
|
|
1901
|
+
column: location.column,
|
|
1902
|
+
text: change.text,
|
|
1903
|
+
author: describeAuthor(change.userId, users),
|
|
1904
|
+
...(change.timestamp ? { timestamp: change.timestamp } : {}),
|
|
1905
|
+
...(contextLines > 0 ? { context: this.buildCommentContext(visibleContent, location.line, contextLines) } : {})
|
|
1906
|
+
});
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
return result.sort((a, b) => a.path.localeCompare(b.path) || a.position - b.position);
|
|
1910
|
+
}
|
|
1911
|
+
/**
|
|
1912
|
+
* Accept tracked changes: the suggested text stays and the suggestion
|
|
1913
|
+
* markers go. Ids come from `listTrackedChanges`. Every id must resolve
|
|
1914
|
+
* before anything is sent; changes are accepted per doc with one request
|
|
1915
|
+
* each (POST /project/<id>/doc/<doc>/changes/accept, the editor's route).
|
|
1916
|
+
* Afterwards the project is re-read and any id still present is an error.
|
|
1917
|
+
*/
|
|
1918
|
+
async acceptTrackedChanges(projectId, ids) {
|
|
1919
|
+
const selected = this.selectTrackedChanges(await this.listTrackedChanges(projectId), ids);
|
|
1920
|
+
const byDoc = new Map();
|
|
1921
|
+
for (const change of selected)
|
|
1922
|
+
byDoc.set(change.docId, [...(byDoc.get(change.docId) ?? []), change]);
|
|
1923
|
+
for (const [docId, changes] of byDoc) {
|
|
1924
|
+
const response = await this.httpRequest(`${this.baseUrl}/project/${projectId}/doc/${docId}/changes/accept`, {
|
|
1925
|
+
method: 'POST',
|
|
1926
|
+
headers: this.getHeaders(true),
|
|
1927
|
+
body: JSON.stringify({ change_ids: changes.map(change => change.id) }),
|
|
1928
|
+
expect: 'text'
|
|
1929
|
+
});
|
|
1930
|
+
if (!response.ok) {
|
|
1931
|
+
throw new Error(`Failed to accept tracked changes in ${changes[0].path}: ${response.status}`);
|
|
1932
|
+
}
|
|
1933
|
+
this.applySetCookieHeaders(response.headers['set-cookie']);
|
|
1934
|
+
}
|
|
1935
|
+
const after = await this.listTrackedChanges(projectId);
|
|
1936
|
+
const remaining = selected.filter(change => after.some(other => other.docId === change.docId && other.id === change.id));
|
|
1937
|
+
if (remaining.length > 0) {
|
|
1938
|
+
throw new Error(`Overleaf did not accept: ${remaining.map(change => change.id).join(', ')}`);
|
|
1939
|
+
}
|
|
1940
|
+
return selected;
|
|
1941
|
+
}
|
|
1942
|
+
selectTrackedChanges(all, ids) {
|
|
1943
|
+
const wanted = [...new Set(ids)];
|
|
1944
|
+
if (wanted.length === 0)
|
|
1945
|
+
throw new Error('No tracked change id given');
|
|
1946
|
+
const selected = [];
|
|
1947
|
+
const missing = [];
|
|
1948
|
+
for (const id of wanted) {
|
|
1949
|
+
const matches = all.filter(change => change.id === id);
|
|
1950
|
+
if (matches.length === 0)
|
|
1951
|
+
missing.push(id);
|
|
1952
|
+
else if (matches.length > 1)
|
|
1953
|
+
throw new Error(`Tracked change id ${id} is ambiguous: it occurs in ${matches.map(m => m.path).join(', ')}`);
|
|
1954
|
+
else
|
|
1955
|
+
selected.push(matches[0]);
|
|
1956
|
+
}
|
|
1957
|
+
if (missing.length > 0) {
|
|
1958
|
+
const hint = all.length === 0
|
|
1959
|
+
? ' (this project has no tracked changes; track changes requires the project owner to have an Overleaf premium plan)'
|
|
1960
|
+
: '';
|
|
1961
|
+
throw new Error(`Tracked change${missing.length === 1 ? '' : 's'} not found: ${missing.join(', ')}${hint}`);
|
|
1962
|
+
}
|
|
1963
|
+
return selected;
|
|
1964
|
+
}
|
|
1965
|
+
/**
|
|
1966
|
+
* Work out what rejecting `ids` would do, without writing anything:
|
|
1967
|
+
* per doc the ops to send and a diff of the result. Fails with
|
|
1968
|
+
* RejectConflictError if a change no longer matches the text, and refuses
|
|
1969
|
+
* history-ot docs, whose rejection path is not implemented.
|
|
1970
|
+
*/
|
|
1971
|
+
async planTrackedChangeRejection(projectId, ids) {
|
|
1972
|
+
const projectInfo = await this.getProjectInfo(projectId);
|
|
1973
|
+
const docs = this.collectProjectDocs(projectInfo);
|
|
1974
|
+
const joinedDocs = await this.joinDocuments(projectId, docs);
|
|
1975
|
+
const all = await this.changesFromDocs(projectId, projectInfo, docs, joinedDocs, 0);
|
|
1976
|
+
const selected = this.selectTrackedChanges(all, ids);
|
|
1977
|
+
const plans = [];
|
|
1978
|
+
for (const [index, doc] of docs.entries()) {
|
|
1979
|
+
const changes = selected.filter(change => change.docId === doc.id);
|
|
1980
|
+
if (changes.length === 0)
|
|
1981
|
+
continue;
|
|
1982
|
+
const joinedDoc = joinedDocs[index];
|
|
1983
|
+
if (joinedDoc.type !== 'sharejs-text-ot') {
|
|
1984
|
+
throw new Error(`Rejecting tracked changes is not supported for ${doc.path} (doc type ${joinedDoc.type}); nothing was changed`);
|
|
1985
|
+
}
|
|
1986
|
+
// Keep the tracker's order: filter the parsed list rather than the sorted one.
|
|
1987
|
+
const wantedIds = new Set(changes.map(change => change.id));
|
|
1988
|
+
const ordered = parseShareJsChanges(joinedDoc.ranges).filter(change => wantedIds.has(change.id));
|
|
1989
|
+
const result = planRejection(joinedDoc.content, ordered);
|
|
1990
|
+
plans.push({
|
|
1991
|
+
docId: doc.id,
|
|
1992
|
+
path: doc.path,
|
|
1993
|
+
version: joinedDoc.version,
|
|
1994
|
+
changes,
|
|
1995
|
+
ops: result.ops,
|
|
1996
|
+
diff: renderRejectionDiff(doc.path, joinedDoc.content, result.content)
|
|
1997
|
+
});
|
|
1998
|
+
}
|
|
1999
|
+
return { changes: selected, docs: plans };
|
|
2000
|
+
}
|
|
2001
|
+
/**
|
|
2002
|
+
* Reject tracked changes: inserted text is removed, deleted text is put
|
|
2003
|
+
* back. The plan is recomputed per doc right before writing, and a doc
|
|
2004
|
+
* whose version moved since `plan` was made is refused, so the user never
|
|
2005
|
+
* applies something other than the preview they saw. Afterwards the
|
|
2006
|
+
* project is re-read and any id still present is an error.
|
|
2007
|
+
*/
|
|
2008
|
+
async rejectTrackedChanges(projectId, plan) {
|
|
2009
|
+
for (const docPlan of plan.docs) {
|
|
2010
|
+
const session = await this.openProjectSocket(projectId);
|
|
2011
|
+
try {
|
|
2012
|
+
const joinedDoc = await this.joinDocument(session, docPlan.docId);
|
|
2013
|
+
if (joinedDoc.version !== docPlan.version) {
|
|
2014
|
+
throw new RejectConflictError(`${docPlan.path} changed since the preview (version ${docPlan.version} -> ${joinedDoc.version}); nothing more was written, run the command again`);
|
|
2015
|
+
}
|
|
2016
|
+
await this.socketRpc(session, 'applyOtUpdate', [docPlan.docId, {
|
|
2017
|
+
doc: docPlan.docId,
|
|
2018
|
+
op: docPlan.ops,
|
|
2019
|
+
v: docPlan.version
|
|
2020
|
+
}]);
|
|
2021
|
+
}
|
|
2022
|
+
finally {
|
|
2023
|
+
await this.closeProjectSocket(session);
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
const after = await this.listTrackedChanges(projectId);
|
|
2027
|
+
const remaining = plan.changes.filter(change => after.some(other => other.docId === change.docId && other.id === change.id));
|
|
2028
|
+
if (remaining.length > 0) {
|
|
2029
|
+
throw new Error(`Overleaf did not reject: ${remaining.map(change => change.id).join(', ')}`);
|
|
2030
|
+
}
|
|
2031
|
+
return plan;
|
|
2032
|
+
}
|
|
1830
2033
|
async resolveComment(projectId, threadId) {
|
|
1831
2034
|
const comment = await this.findComment(projectId, threadId);
|
|
1832
2035
|
const response = await this.httpRequest(`${this.baseUrl}/project/${projectId}/doc/${comment.docId}/thread/${threadId}/resolve`, {
|