@parall/cli 1.19.0 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/messages.js +4 -4
- package/dist/commands/projects.d.ts.map +1 -1
- package/dist/commands/projects.js +6 -5
- package/dist/commands/users.js +2 -2
- package/dist/commands/wiki.d.ts.map +1 -1
- package/dist/commands/wiki.js +6 -0
- package/dist/lib/wiki.d.ts +100 -1
- package/dist/lib/wiki.d.ts.map +1 -1
- package/dist/lib/wiki.js +342 -47
- package/package.json +4 -3
|
@@ -17,9 +17,9 @@ export function registerMessageCommands(program) {
|
|
|
17
17
|
const { client, orgId } = resolveCredentials();
|
|
18
18
|
const params = { limit: Number(opts.limit) };
|
|
19
19
|
if (opts.before !== undefined)
|
|
20
|
-
params.before = opts.before;
|
|
20
|
+
params.before = stripPrllScheme(opts.before);
|
|
21
21
|
if (opts.after !== undefined)
|
|
22
|
-
params.after = opts.after;
|
|
22
|
+
params.after = stripPrllScheme(opts.after);
|
|
23
23
|
if (opts.threadRootId !== undefined)
|
|
24
24
|
params.thread_root_id = stripPrllScheme(opts.threadRootId);
|
|
25
25
|
if (opts.topLevel)
|
|
@@ -112,9 +112,9 @@ export function registerMessageCommands(program) {
|
|
|
112
112
|
const { client } = resolveCredentials();
|
|
113
113
|
const params = { limit: Number(opts.limit) };
|
|
114
114
|
if (opts.before !== undefined)
|
|
115
|
-
params.before = opts.before;
|
|
115
|
+
params.before = stripPrllScheme(opts.before);
|
|
116
116
|
if (opts.after !== undefined)
|
|
117
|
-
params.after = opts.after;
|
|
117
|
+
params.after = stripPrllScheme(opts.after);
|
|
118
118
|
const result = await client.getMessageReplies(stripPrllScheme(messageId), params);
|
|
119
119
|
printJson(result);
|
|
120
120
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/commands/projects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/commands/projects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QA8FvD"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolveCredentials } from '../lib/client.js';
|
|
2
|
-
import { printJson, printError } from '../lib/output.js';
|
|
2
|
+
import { printJson, printError, stripPrllScheme } from '../lib/output.js';
|
|
3
3
|
export function registerProjectCommands(program) {
|
|
4
4
|
const projects = program.command('projects').description('Manage projects');
|
|
5
5
|
projects
|
|
@@ -22,7 +22,7 @@ export function registerProjectCommands(program) {
|
|
|
22
22
|
.action(async (projectId) => {
|
|
23
23
|
try {
|
|
24
24
|
const { client, orgId } = resolveCredentials();
|
|
25
|
-
const result = await client.getProject(orgId, projectId);
|
|
25
|
+
const result = await client.getProject(orgId, stripPrllScheme(projectId));
|
|
26
26
|
printJson(result);
|
|
27
27
|
}
|
|
28
28
|
catch (err) {
|
|
@@ -80,7 +80,7 @@ export function registerProjectCommands(program) {
|
|
|
80
80
|
if (Object.keys(data).length === 0) {
|
|
81
81
|
printError(new Error('No fields to update. Provide at least one option.'));
|
|
82
82
|
}
|
|
83
|
-
const result = await client.updateProject(orgId, projectId, data);
|
|
83
|
+
const result = await client.updateProject(orgId, stripPrllScheme(projectId), data);
|
|
84
84
|
printJson(result);
|
|
85
85
|
}
|
|
86
86
|
catch (err) {
|
|
@@ -94,8 +94,9 @@ export function registerProjectCommands(program) {
|
|
|
94
94
|
.action(async (projectId) => {
|
|
95
95
|
try {
|
|
96
96
|
const { client, orgId } = resolveCredentials();
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
const id = stripPrllScheme(projectId);
|
|
98
|
+
await client.deleteProject(orgId, id);
|
|
99
|
+
printJson({ deleted: id });
|
|
99
100
|
}
|
|
100
101
|
catch (err) {
|
|
101
102
|
printError(err);
|
package/dist/commands/users.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolveCredentials } from '../lib/client.js';
|
|
2
|
-
import { printJson, printError } from '../lib/output.js';
|
|
2
|
+
import { printJson, printError, stripPrllScheme } from '../lib/output.js';
|
|
3
3
|
export function registerUserCommands(program) {
|
|
4
4
|
// whoami — registered directly on program
|
|
5
5
|
program
|
|
@@ -24,7 +24,7 @@ export function registerUserCommands(program) {
|
|
|
24
24
|
.action(async (userId) => {
|
|
25
25
|
try {
|
|
26
26
|
const { client } = resolveCredentials();
|
|
27
|
-
const result = await client.getUser(userId);
|
|
27
|
+
const result = await client.getUser(stripPrllScheme(userId));
|
|
28
28
|
printJson(result);
|
|
29
29
|
}
|
|
30
30
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wiki.d.ts","sourceRoot":"","sources":["../../src/commands/wiki.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwBpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"wiki.d.ts","sourceRoot":"","sources":["../../src/commands/wiki.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwBpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QA8wBpD"}
|
package/dist/commands/wiki.js
CHANGED
|
@@ -41,6 +41,12 @@ export function registerWikiCommands(program) {
|
|
|
41
41
|
process.stderr.write(`wiki ${entry.slug} synced → ${entry.path}\n`);
|
|
42
42
|
}
|
|
43
43
|
printJson(result);
|
|
44
|
+
// Conflicts are an expected, agent-resolvable state; failures (download
|
|
45
|
+
// error, shape conflict, etc.) are not. Reflect that in the exit code
|
|
46
|
+
// so CI / scripts that check status see partial sync as failure.
|
|
47
|
+
if (!result.ok) {
|
|
48
|
+
process.exitCode = 1;
|
|
49
|
+
}
|
|
44
50
|
}
|
|
45
51
|
catch (error) {
|
|
46
52
|
printError(error);
|
package/dist/lib/wiki.d.ts
CHANGED
|
@@ -245,11 +245,19 @@ export type AfcsLogResult = {
|
|
|
245
245
|
};
|
|
246
246
|
export declare function getWikiLog(ctx: ParallContext, wikiRef?: string, filePath?: string): Promise<AfcsLogResult>;
|
|
247
247
|
export type SyncResult = {
|
|
248
|
-
|
|
248
|
+
/** True iff every wiki's per-path action ran without failure. Conflicts do
|
|
249
|
+
* NOT clear this flag — they are an expected, structured outcome the agent
|
|
250
|
+
* is responsible for resolving. Only `failed[]` (download error,
|
|
251
|
+
* shape-conflict, etc.) flips ok to false. */
|
|
252
|
+
ok: boolean;
|
|
249
253
|
mounts: number;
|
|
250
254
|
synced: {
|
|
251
255
|
slug: string;
|
|
252
256
|
path: string;
|
|
257
|
+
applied: number;
|
|
258
|
+
fastForwarded: number;
|
|
259
|
+
conflicts: SyncConflict[];
|
|
260
|
+
failed: SyncFailure[];
|
|
253
261
|
}[];
|
|
254
262
|
};
|
|
255
263
|
/**
|
|
@@ -265,5 +273,96 @@ export declare function syncAllMounts(ctx: ParallContext): Promise<SyncResult>;
|
|
|
265
273
|
export declare function watchMounts(ctx: ParallContext, intervalSec: number): {
|
|
266
274
|
stop: () => void;
|
|
267
275
|
};
|
|
276
|
+
/**
|
|
277
|
+
* Sync a single wiki:
|
|
278
|
+
* 1. Fetch server manifest (file listing with SHAs)
|
|
279
|
+
* 2. Compare with local manifest
|
|
280
|
+
* 3. Download new/modified files via bulk download
|
|
281
|
+
* 4. Delete removed files
|
|
282
|
+
* 5. Save updated local manifest
|
|
283
|
+
*/
|
|
284
|
+
/** Per-path sync action computed by three-way comparison. */
|
|
285
|
+
export type SyncAction = {
|
|
286
|
+
kind: 'noop';
|
|
287
|
+
path: string;
|
|
288
|
+
} | {
|
|
289
|
+
kind: 'apply-write';
|
|
290
|
+
path: string;
|
|
291
|
+
remoteSha: string;
|
|
292
|
+
remoteSize: number;
|
|
293
|
+
} | {
|
|
294
|
+
kind: 'apply-delete';
|
|
295
|
+
path: string;
|
|
296
|
+
} | {
|
|
297
|
+
kind: 'fast-forward';
|
|
298
|
+
path: string;
|
|
299
|
+
remoteSha: string;
|
|
300
|
+
remoteSize: number;
|
|
301
|
+
} | {
|
|
302
|
+
kind: 'fast-forward-delete';
|
|
303
|
+
path: string;
|
|
304
|
+
} | {
|
|
305
|
+
kind: 'conflict-write';
|
|
306
|
+
path: string;
|
|
307
|
+
remoteSha: string;
|
|
308
|
+
remoteSize: number;
|
|
309
|
+
baseSha: string | null;
|
|
310
|
+
localSha: string | null;
|
|
311
|
+
} | {
|
|
312
|
+
kind: 'conflict-delete';
|
|
313
|
+
path: string;
|
|
314
|
+
baseSha: string;
|
|
315
|
+
};
|
|
316
|
+
/**
|
|
317
|
+
* Pure three-way sync planner. Decides what to do per-path given the base
|
|
318
|
+
* (manifest entry from last successful sync), the current local working tree
|
|
319
|
+
* sha, and the latest remote sha. No I/O.
|
|
320
|
+
*/
|
|
321
|
+
export declare function planSyncActions(input: {
|
|
322
|
+
paths: Iterable<string>;
|
|
323
|
+
baseSha: (path: string) => string | null;
|
|
324
|
+
localSha: (path: string) => string | null;
|
|
325
|
+
remote: (path: string) => {
|
|
326
|
+
sha: string;
|
|
327
|
+
size: number;
|
|
328
|
+
} | null;
|
|
329
|
+
}): SyncAction[];
|
|
330
|
+
export type SyncConflict = {
|
|
331
|
+
path: string;
|
|
332
|
+
/** Where the upstream copy was written (or null for remote-deleted markers). */
|
|
333
|
+
remoteCopyPath: string | null;
|
|
334
|
+
/** Type of conflict for logging / UI surface. */
|
|
335
|
+
reason: 'remote-changed-local-edited' | 'remote-deleted-local-edited' | 'remote-added-local-collides' | 'remote-changed-local-deleted';
|
|
336
|
+
};
|
|
337
|
+
export type SyncFailure = {
|
|
338
|
+
path: string;
|
|
339
|
+
/**
|
|
340
|
+
* Reason classification:
|
|
341
|
+
* - 'download' — bulk-download endpoint surfaced a per-file error.
|
|
342
|
+
* - 'shape-conflict' — local working tree has an incompatible file/directory
|
|
343
|
+
* shape at this path (e.g. local `foo` is a directory
|
|
344
|
+
* while remote treats `foo` as a file, or vice versa
|
|
345
|
+
* when remote is `foo/bar.md` but local has `foo` as
|
|
346
|
+
* a regular file).
|
|
347
|
+
*/
|
|
348
|
+
reason: 'download' | 'shape-conflict';
|
|
349
|
+
/** Server-supplied error string or local errno, when available. */
|
|
350
|
+
detail?: string;
|
|
351
|
+
};
|
|
352
|
+
export type WikiSyncOutcome = {
|
|
353
|
+
applied: number;
|
|
354
|
+
fastForwarded: number;
|
|
355
|
+
conflicts: SyncConflict[];
|
|
356
|
+
/** Per-path failures that prevented a planned action from running. Manifest is left unchanged for these — next sync retries. */
|
|
357
|
+
failed: SyncFailure[];
|
|
358
|
+
};
|
|
359
|
+
export declare function syncSingleWiki(ctx: ParallContext, wiki: import('@parall/sdk').Wiki, mountPath: string): Promise<WikiSyncOutcome>;
|
|
360
|
+
/**
|
|
361
|
+
* Write a sync conflict marker under .parall-wiki/conflicts/, mirroring the
|
|
362
|
+
* source path so the agent (or user) can locate the upstream copy next to the
|
|
363
|
+
* local edit. Returns the absolute path written.
|
|
364
|
+
*/
|
|
365
|
+
export declare function writeConflictMarker(mountRoot: string, sourcePath: string, suffix: string, content: Buffer): Promise<string>;
|
|
366
|
+
export declare function computeGitBlobSHA(content: Buffer): string;
|
|
268
367
|
export {};
|
|
269
368
|
//# sourceMappingURL=wiki.d.ts.map
|
package/dist/lib/wiki.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wiki.d.ts","sourceRoot":"","sources":["../../src/lib/wiki.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"wiki.d.ts","sourceRoot":"","sources":["../../src/lib/wiki.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/wiki.js
CHANGED
|
@@ -10,6 +10,9 @@ const TRAILING_FENCE_RE = /\s+#+\s*$/;
|
|
|
10
10
|
const LOCAL_NODE_SECTION_ARTIFACT_VERSION = 2;
|
|
11
11
|
const LOCAL_MANIFEST_FILE = 'manifest.json';
|
|
12
12
|
const PRLL_WIKI_DIR = '.parall-wiki';
|
|
13
|
+
const CONFLICTS_DIR = 'conflicts';
|
|
14
|
+
const REMOTE_CONFLICT_SUFFIX = '.remote';
|
|
15
|
+
const REMOTE_DELETED_MARKER_SUFFIX = '.remote-deleted';
|
|
13
16
|
// ---------------------------------------------------------------------------
|
|
14
17
|
// Wiki resolution helpers
|
|
15
18
|
// ---------------------------------------------------------------------------
|
|
@@ -473,11 +476,19 @@ export async function syncAllMounts(ctx) {
|
|
|
473
476
|
for (const wiki of wikis) {
|
|
474
477
|
const mountPath = resolveMountPath(wiki.slug, mountRoot);
|
|
475
478
|
activeMountPaths.add(mountPath);
|
|
476
|
-
await syncSingleWiki(ctx, wiki, mountPath);
|
|
477
|
-
synced.push({
|
|
479
|
+
const outcome = await syncSingleWiki(ctx, wiki, mountPath);
|
|
480
|
+
synced.push({
|
|
481
|
+
slug: wiki.slug,
|
|
482
|
+
path: mountPath,
|
|
483
|
+
applied: outcome.applied,
|
|
484
|
+
fastForwarded: outcome.fastForwarded,
|
|
485
|
+
conflicts: outcome.conflicts,
|
|
486
|
+
failed: outcome.failed,
|
|
487
|
+
});
|
|
478
488
|
}
|
|
479
489
|
await pruneStaleMounts(mountRoot, activeMountPaths);
|
|
480
|
-
|
|
490
|
+
const ok = synced.every((s) => s.failed.length === 0);
|
|
491
|
+
return { ok, mounts: wikis.length, synced };
|
|
481
492
|
}
|
|
482
493
|
/**
|
|
483
494
|
* Run {@link syncAllMounts} in a loop, sleeping `intervalSec` between
|
|
@@ -505,18 +516,50 @@ export function watchMounts(ctx, intervalSec) {
|
|
|
505
516
|
process.on('SIGTERM', stop);
|
|
506
517
|
return { stop };
|
|
507
518
|
}
|
|
508
|
-
// ---------------------------------------------------------------------------
|
|
509
|
-
// Sync internals (REST-based)
|
|
510
|
-
// ---------------------------------------------------------------------------
|
|
511
519
|
/**
|
|
512
|
-
*
|
|
513
|
-
*
|
|
514
|
-
*
|
|
515
|
-
* 3. Download new/modified files via bulk download
|
|
516
|
-
* 4. Delete removed files
|
|
517
|
-
* 5. Save updated local manifest
|
|
520
|
+
* Pure three-way sync planner. Decides what to do per-path given the base
|
|
521
|
+
* (manifest entry from last successful sync), the current local working tree
|
|
522
|
+
* sha, and the latest remote sha. No I/O.
|
|
518
523
|
*/
|
|
519
|
-
|
|
524
|
+
export function planSyncActions(input) {
|
|
525
|
+
const actions = [];
|
|
526
|
+
for (const p of input.paths) {
|
|
527
|
+
const baseSha = input.baseSha(p);
|
|
528
|
+
const remote = input.remote(p);
|
|
529
|
+
const remoteSha = remote?.sha ?? null;
|
|
530
|
+
const localSha = input.localSha(p);
|
|
531
|
+
if (baseSha === remoteSha) {
|
|
532
|
+
actions.push({ kind: 'noop', path: p });
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
const cleanLocal = localSha === baseSha;
|
|
536
|
+
if (cleanLocal) {
|
|
537
|
+
if (remoteSha === null) {
|
|
538
|
+
actions.push({ kind: 'apply-delete', path: p });
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
actions.push({ kind: 'apply-write', path: p, remoteSha, remoteSize: remote.size });
|
|
542
|
+
}
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
if (localSha !== null && localSha === remoteSha) {
|
|
546
|
+
actions.push({ kind: 'fast-forward', path: p, remoteSha, remoteSize: remote.size });
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
if (localSha === null && remoteSha === null) {
|
|
550
|
+
actions.push({ kind: 'fast-forward-delete', path: p });
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
if (remoteSha === null) {
|
|
554
|
+
actions.push({ kind: 'conflict-delete', path: p, baseSha: baseSha });
|
|
555
|
+
}
|
|
556
|
+
else {
|
|
557
|
+
actions.push({ kind: 'conflict-write', path: p, remoteSha, remoteSize: remote.size, baseSha, localSha });
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return actions;
|
|
561
|
+
}
|
|
562
|
+
export async function syncSingleWiki(ctx, wiki, mountPath) {
|
|
520
563
|
await fs.mkdir(mountPath, { recursive: true });
|
|
521
564
|
const metaDir = path.join(mountPath, PRLL_WIKI_DIR);
|
|
522
565
|
await fs.mkdir(metaDir, { recursive: true });
|
|
@@ -524,54 +567,306 @@ async function syncSingleWiki(ctx, wiki, mountPath) {
|
|
|
524
567
|
const baseUrl = (ctx.baseUrl ?? process.env.PRLL_WIKI_URL ?? process.env.PRLL_API_URL ?? '').replace(/\/+$/, '');
|
|
525
568
|
const manifestUrl = `${baseUrl}/wiki/v1/orgs/${ctx.orgId}/wikis/${wiki.id}/manifest`;
|
|
526
569
|
const bulkDownloadUrl = `${baseUrl}/wiki/v1/orgs/${ctx.orgId}/wikis/${wiki.id}/files/bulk-download`;
|
|
527
|
-
// 1. Fetch server manifest
|
|
570
|
+
// 1. Fetch server manifest + read local manifest.
|
|
528
571
|
const manifestResp = await wikiServiceFetch(manifestUrl, token);
|
|
529
572
|
const serverEntries = manifestResp.data;
|
|
530
|
-
// 2. Read local manifest
|
|
531
|
-
const localManifest = await readLocalManifest(mountPath);
|
|
532
|
-
// 3. Compare: find new, modified, deleted files
|
|
533
573
|
const serverByPath = new Map(serverEntries.map((e) => [e.path, e]));
|
|
534
|
-
const
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
574
|
+
const localManifest = await readLocalManifest(mountPath);
|
|
575
|
+
// 2. Build the union of paths from server + local manifest + working tree.
|
|
576
|
+
const allPaths = new Set();
|
|
577
|
+
for (const e of serverEntries)
|
|
578
|
+
allPaths.add(e.path);
|
|
579
|
+
for (const p of Object.keys(localManifest.files))
|
|
580
|
+
allPaths.add(p);
|
|
581
|
+
await walkLocalFiles(mountPath, mountPath, async (_full, rel) => {
|
|
582
|
+
allPaths.add(rel);
|
|
583
|
+
});
|
|
584
|
+
// 3. Snapshot working-tree shas so the planner stays pure. Paths whose local
|
|
585
|
+
// shape is incompatible with a regular-file read (e.g. local has a directory
|
|
586
|
+
// where remote treats this as a file, or a parent path is a regular file
|
|
587
|
+
// while remote nests under it) are routed to a 'shape-conflict' failure
|
|
588
|
+
// instead of crashing the whole sync — they need human/agent intervention.
|
|
589
|
+
const localShaCache = new Map();
|
|
590
|
+
const shapeConflictByPath = new Map();
|
|
591
|
+
for (const p of allPaths) {
|
|
592
|
+
const probe = await probeLocalGitBlob(mountPath, p);
|
|
593
|
+
if (probe.kind === 'shape-conflict') {
|
|
594
|
+
shapeConflictByPath.set(p, probe.detail);
|
|
595
|
+
localShaCache.set(p, null);
|
|
540
596
|
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
if (!serverByPath.has(localPath)) {
|
|
544
|
-
toDelete.push(localPath);
|
|
597
|
+
else {
|
|
598
|
+
localShaCache.set(p, probe.sha);
|
|
545
599
|
}
|
|
546
600
|
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
601
|
+
const actions = planSyncActions({
|
|
602
|
+
paths: allPaths,
|
|
603
|
+
baseSha: (p) => localManifest.files[p]?.sha ?? null,
|
|
604
|
+
localSha: (p) => localShaCache.get(p) ?? null,
|
|
605
|
+
remote: (p) => {
|
|
606
|
+
const r = serverByPath.get(p);
|
|
607
|
+
return r ? { sha: r.sha, size: r.size } : null;
|
|
608
|
+
},
|
|
609
|
+
});
|
|
610
|
+
// 4. Fetch all bytes we need (apply-write + conflict-write) in one bulk call.
|
|
611
|
+
const fetchPaths = actions
|
|
612
|
+
.filter((a) => a.kind === 'apply-write' || a.kind === 'conflict-write')
|
|
613
|
+
.map((a) => a.path);
|
|
614
|
+
const contentByPath = new Map();
|
|
615
|
+
const downloadErrorByPath = new Map();
|
|
616
|
+
if (fetchPaths.length > 0) {
|
|
617
|
+
const downloaded = await bulkDownloadFiles(bulkDownloadUrl, token, fetchPaths);
|
|
618
|
+
const returnedPaths = new Set();
|
|
550
619
|
for (const entry of downloaded) {
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
620
|
+
returnedPaths.add(entry.path);
|
|
621
|
+
if (entry.error) {
|
|
622
|
+
downloadErrorByPath.set(entry.path, entry.error);
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
625
|
+
contentByPath.set(entry.path, Buffer.from(entry.content_base64, 'base64'));
|
|
626
|
+
}
|
|
627
|
+
// Anything we asked for but the server omitted entirely is also a failure.
|
|
628
|
+
for (const p of fetchPaths) {
|
|
629
|
+
if (!returnedPaths.has(p)) {
|
|
630
|
+
downloadErrorByPath.set(p, 'missing from bulk-download response');
|
|
631
|
+
}
|
|
554
632
|
}
|
|
555
633
|
}
|
|
556
|
-
// 5.
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
634
|
+
// 5. Apply actions and start with the previous manifest, mutating per action.
|
|
635
|
+
const newFiles = { ...localManifest.files };
|
|
636
|
+
const conflicts = [];
|
|
637
|
+
const failed = [];
|
|
638
|
+
let applied = 0;
|
|
639
|
+
let fastForwarded = 0;
|
|
640
|
+
// Surface shape conflicts as sync failures up front so we don't try to write
|
|
641
|
+
// through them. Manifest stays pinned (the path's manifest entry is left as-is).
|
|
642
|
+
for (const [p, detail] of shapeConflictByPath) {
|
|
643
|
+
failed.push({ path: p, reason: 'shape-conflict', detail });
|
|
644
|
+
}
|
|
645
|
+
for (const action of actions) {
|
|
646
|
+
if (shapeConflictByPath.has(action.path)) {
|
|
647
|
+
// Already reported. Don't attempt apply / write — would crash on EISDIR/ENOTDIR.
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
switch (action.kind) {
|
|
651
|
+
case 'noop':
|
|
652
|
+
// Preserve manifest entry unchanged.
|
|
653
|
+
break;
|
|
654
|
+
case 'apply-write': {
|
|
655
|
+
const buf = contentByPath.get(action.path);
|
|
656
|
+
if (!buf) {
|
|
657
|
+
failed.push({
|
|
658
|
+
path: action.path,
|
|
659
|
+
reason: 'download',
|
|
660
|
+
detail: downloadErrorByPath.get(action.path),
|
|
661
|
+
});
|
|
662
|
+
break;
|
|
663
|
+
}
|
|
664
|
+
// TOCTOU re-check: the snapshot was taken before the bulk-download
|
|
665
|
+
// network round-trip. If the user/agent edited (or deleted) this path
|
|
666
|
+
// in that window, demote to a conflict so we don't silently overwrite.
|
|
667
|
+
const snapshotSha = localShaCache.get(action.path) ?? null;
|
|
668
|
+
const reprobe = await probeLocalGitBlob(mountPath, action.path);
|
|
669
|
+
if (reprobe.kind === 'shape-conflict') {
|
|
670
|
+
failed.push({ path: action.path, reason: 'shape-conflict', detail: reprobe.detail });
|
|
671
|
+
break;
|
|
672
|
+
}
|
|
673
|
+
const currentSha = reprobe.sha;
|
|
674
|
+
if (currentSha === action.remoteSha) {
|
|
675
|
+
// Local converged on remote during the window — manifest-only fast-forward.
|
|
676
|
+
newFiles[action.path] = { sha: action.remoteSha, size: action.remoteSize };
|
|
677
|
+
fastForwarded++;
|
|
678
|
+
break;
|
|
679
|
+
}
|
|
680
|
+
if (currentSha !== snapshotSha) {
|
|
681
|
+
// Local diverged after snapshot. Surface as a conflict instead of overwriting.
|
|
682
|
+
const remoteCopy = await writeConflictMarker(mountPath, action.path, REMOTE_CONFLICT_SUFFIX, buf);
|
|
683
|
+
let reason;
|
|
684
|
+
// Defense-in-depth: planSyncActions only emits apply-write when
|
|
685
|
+
// localSha === baseSha (both non-null), so snapshotSha should never
|
|
686
|
+
// be null here. The branch is kept to safely classify any race that
|
|
687
|
+
// creates a file between snapshot and apply.
|
|
688
|
+
if (snapshotSha === null && currentSha !== null) {
|
|
689
|
+
reason = 'remote-added-local-collides';
|
|
690
|
+
}
|
|
691
|
+
else if (currentSha === null) {
|
|
692
|
+
reason = 'remote-changed-local-deleted';
|
|
693
|
+
}
|
|
694
|
+
else {
|
|
695
|
+
reason = 'remote-changed-local-edited';
|
|
696
|
+
}
|
|
697
|
+
conflicts.push({ path: action.path, remoteCopyPath: remoteCopy, reason });
|
|
698
|
+
break;
|
|
699
|
+
}
|
|
700
|
+
const fullPath = resolvePathInsideRoot(mountPath, action.path);
|
|
701
|
+
await fs.mkdir(path.dirname(fullPath), { recursive: true });
|
|
702
|
+
await fs.writeFile(fullPath, buf);
|
|
703
|
+
newFiles[action.path] = { sha: action.remoteSha, size: action.remoteSize };
|
|
704
|
+
applied++;
|
|
705
|
+
break;
|
|
706
|
+
}
|
|
707
|
+
case 'apply-delete': {
|
|
708
|
+
// TOCTOU re-check before deleting. The action only fires when the
|
|
709
|
+
// snapshot saw clean local matching the (now-deleted) base; if the
|
|
710
|
+
// user re-created or edited the file after the snapshot, demote to
|
|
711
|
+
// conflict-delete instead of dropping their work.
|
|
712
|
+
const snapshotSha = localShaCache.get(action.path) ?? null;
|
|
713
|
+
const reprobe = await probeLocalGitBlob(mountPath, action.path);
|
|
714
|
+
if (reprobe.kind === 'shape-conflict') {
|
|
715
|
+
failed.push({ path: action.path, reason: 'shape-conflict', detail: reprobe.detail });
|
|
716
|
+
break;
|
|
717
|
+
}
|
|
718
|
+
const currentSha = reprobe.sha;
|
|
719
|
+
if (currentSha === null) {
|
|
720
|
+
// Convergence: user also deleted the file during the TOCTOU window.
|
|
721
|
+
// Both sides agree — fast-forward the manifest delete.
|
|
722
|
+
delete newFiles[action.path];
|
|
723
|
+
fastForwarded++;
|
|
724
|
+
break;
|
|
725
|
+
}
|
|
726
|
+
if (currentSha !== snapshotSha) {
|
|
727
|
+
await writeConflictMarker(mountPath, action.path, REMOTE_DELETED_MARKER_SUFFIX, Buffer.alloc(0));
|
|
728
|
+
conflicts.push({
|
|
729
|
+
path: action.path,
|
|
730
|
+
remoteCopyPath: null,
|
|
731
|
+
reason: 'remote-deleted-local-edited',
|
|
732
|
+
});
|
|
733
|
+
break;
|
|
734
|
+
}
|
|
735
|
+
const fullPath = resolvePathInsideRoot(mountPath, action.path);
|
|
736
|
+
await fs.rm(fullPath, { force: true });
|
|
737
|
+
await removeEmptyParents(mountPath, path.dirname(fullPath));
|
|
738
|
+
delete newFiles[action.path];
|
|
739
|
+
applied++;
|
|
740
|
+
break;
|
|
741
|
+
}
|
|
742
|
+
case 'fast-forward':
|
|
743
|
+
// Local already matches remote — only sync the manifest pointer.
|
|
744
|
+
newFiles[action.path] = { sha: action.remoteSha, size: action.remoteSize };
|
|
745
|
+
fastForwarded++;
|
|
746
|
+
break;
|
|
747
|
+
case 'fast-forward-delete':
|
|
748
|
+
delete newFiles[action.path];
|
|
749
|
+
fastForwarded++;
|
|
750
|
+
break;
|
|
751
|
+
case 'conflict-write': {
|
|
752
|
+
const buf = contentByPath.get(action.path);
|
|
753
|
+
if (!buf) {
|
|
754
|
+
failed.push({
|
|
755
|
+
path: action.path,
|
|
756
|
+
reason: 'download',
|
|
757
|
+
detail: downloadErrorByPath.get(action.path),
|
|
758
|
+
});
|
|
759
|
+
break;
|
|
760
|
+
}
|
|
761
|
+
const remoteCopy = await writeConflictMarker(mountPath, action.path, REMOTE_CONFLICT_SUFFIX, buf);
|
|
762
|
+
// Reason classification:
|
|
763
|
+
// - base null + local present → both sides added the same path with different bytes
|
|
764
|
+
// - base present + local null → user deleted locally, server changed it
|
|
765
|
+
// - base present + local present (and ≠ both) → genuine concurrent edit
|
|
766
|
+
let reason;
|
|
767
|
+
if (action.baseSha === null) {
|
|
768
|
+
reason = 'remote-added-local-collides';
|
|
769
|
+
}
|
|
770
|
+
else if (action.localSha === null) {
|
|
771
|
+
reason = 'remote-changed-local-deleted';
|
|
772
|
+
}
|
|
773
|
+
else {
|
|
774
|
+
reason = 'remote-changed-local-edited';
|
|
775
|
+
}
|
|
776
|
+
conflicts.push({ path: action.path, remoteCopyPath: remoteCopy, reason });
|
|
777
|
+
// Manifest entry stays at its pre-sync value so the next sync still
|
|
778
|
+
// recognises the local edit and re-tries the merge.
|
|
779
|
+
break;
|
|
780
|
+
}
|
|
781
|
+
case 'conflict-delete': {
|
|
782
|
+
// Server deleted a file the user has local edits for. Drop a marker
|
|
783
|
+
// so the agent surfaces the divergence without overwriting local.
|
|
784
|
+
await writeConflictMarker(mountPath, action.path, REMOTE_DELETED_MARKER_SUFFIX, Buffer.alloc(0));
|
|
785
|
+
conflicts.push({
|
|
786
|
+
path: action.path,
|
|
787
|
+
remoteCopyPath: null,
|
|
788
|
+
reason: 'remote-deleted-local-edited',
|
|
789
|
+
});
|
|
790
|
+
break;
|
|
791
|
+
}
|
|
792
|
+
}
|
|
561
793
|
}
|
|
562
|
-
// 6.
|
|
794
|
+
// 6. Persist new manifest.
|
|
563
795
|
const newManifest = {
|
|
564
796
|
wiki_id: wiki.id,
|
|
565
797
|
synced_at: new Date().toISOString(),
|
|
566
|
-
files:
|
|
798
|
+
files: newFiles,
|
|
567
799
|
};
|
|
568
|
-
for (const entry of serverEntries) {
|
|
569
|
-
newManifest.files[entry.path] = {
|
|
570
|
-
sha: entry.sha,
|
|
571
|
-
size: entry.size,
|
|
572
|
-
};
|
|
573
|
-
}
|
|
574
800
|
await writeLocalManifest(mountPath, newManifest);
|
|
801
|
+
if (conflicts.length > 0) {
|
|
802
|
+
for (const c of conflicts) {
|
|
803
|
+
const where = c.remoteCopyPath ? ` → ${path.relative(mountPath, c.remoteCopyPath)}` : '';
|
|
804
|
+
console.warn(`[wiki sync] conflict on ${c.path} (${c.reason})${where}`);
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
if (failed.length > 0) {
|
|
808
|
+
for (const f of failed) {
|
|
809
|
+
const detail = f.detail ? ` — ${f.detail}` : '';
|
|
810
|
+
console.warn(`[wiki sync] failed to ${f.reason} ${f.path}${detail} — manifest unchanged, will retry next sync`);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
return { applied, fastForwarded, conflicts, failed };
|
|
814
|
+
}
|
|
815
|
+
/** Compute the git blob SHA of a working-tree file, or null if absent. */
|
|
816
|
+
async function readLocalGitBlobSha(mountRoot, relPath) {
|
|
817
|
+
const probe = await probeLocalGitBlob(mountRoot, relPath);
|
|
818
|
+
if (probe.kind === 'shape-conflict') {
|
|
819
|
+
// Surface as throw at this entry point — the caller (computeLocalChanges /
|
|
820
|
+
// computeLocalDiff) doesn't currently model shape conflicts. syncSingleWiki
|
|
821
|
+
// uses probeLocalGitBlob directly so it can route the failure structurally.
|
|
822
|
+
throw new Error(`shape conflict at ${relPath}: ${probe.detail}`);
|
|
823
|
+
}
|
|
824
|
+
return probe.sha;
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Read a working-tree file as a git blob, returning a structured shape so
|
|
828
|
+
* callers can distinguish "absent" from "shape mismatch" (directory where a
|
|
829
|
+
* file is expected, or a parent path is a file blocking nested reads).
|
|
830
|
+
*/
|
|
831
|
+
async function probeLocalGitBlob(mountRoot, relPath) {
|
|
832
|
+
let fullPath;
|
|
833
|
+
try {
|
|
834
|
+
fullPath = resolvePathInsideRoot(mountRoot, relPath);
|
|
835
|
+
}
|
|
836
|
+
catch {
|
|
837
|
+
return { kind: 'absent', sha: null };
|
|
838
|
+
}
|
|
839
|
+
try {
|
|
840
|
+
const buf = await fs.readFile(fullPath);
|
|
841
|
+
return { kind: 'file', sha: computeGitBlobSHA(buf) };
|
|
842
|
+
}
|
|
843
|
+
catch (err) {
|
|
844
|
+
const code = err.code;
|
|
845
|
+
if (code === 'ENOENT')
|
|
846
|
+
return { kind: 'absent', sha: null };
|
|
847
|
+
if (code === 'EISDIR' || code === 'ENOTDIR') {
|
|
848
|
+
return { kind: 'shape-conflict', detail: code };
|
|
849
|
+
}
|
|
850
|
+
throw err;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Write a sync conflict marker under .parall-wiki/conflicts/, mirroring the
|
|
855
|
+
* source path so the agent (or user) can locate the upstream copy next to the
|
|
856
|
+
* local edit. Returns the absolute path written.
|
|
857
|
+
*/
|
|
858
|
+
export async function writeConflictMarker(mountRoot, sourcePath, suffix, content) {
|
|
859
|
+
// Validate sourcePath under the mount root before we use it as a key under
|
|
860
|
+
// .parall-wiki/conflicts. The planner only feeds us paths the server returned
|
|
861
|
+
// (so traversal segments are not expected today), but the rest of the sync
|
|
862
|
+
// pipeline always goes through resolvePathInsideRoot and we want this branch
|
|
863
|
+
// to fail closed too — defense in depth, not exploitation today.
|
|
864
|
+
resolvePathInsideRoot(mountRoot, sourcePath);
|
|
865
|
+
const conflictsRoot = path.join(mountRoot, PRLL_WIKI_DIR, CONFLICTS_DIR);
|
|
866
|
+
const target = resolvePathInsideRoot(conflictsRoot, sourcePath + suffix);
|
|
867
|
+
await fs.mkdir(path.dirname(target), { recursive: true });
|
|
868
|
+
await fs.writeFile(target, content);
|
|
869
|
+
return target;
|
|
575
870
|
}
|
|
576
871
|
// ---------------------------------------------------------------------------
|
|
577
872
|
// Local manifest I/O
|
|
@@ -647,7 +942,7 @@ async function bulkDownloadFiles(bulkDownloadUrl, token, paths) {
|
|
|
647
942
|
// ---------------------------------------------------------------------------
|
|
648
943
|
// Local change detection (manifest-based)
|
|
649
944
|
// ---------------------------------------------------------------------------
|
|
650
|
-
function computeGitBlobSHA(content) {
|
|
945
|
+
export function computeGitBlobSHA(content) {
|
|
651
946
|
// Manifest SHAs come from Gitea's Git blob object IDs, not raw content hashes.
|
|
652
947
|
// This matches Git's current SHA-1 blob format; if the server ever switches to
|
|
653
948
|
// SHA-256 object IDs, this helper must change in lockstep.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parall/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.20.0",
|
|
4
4
|
"description": "CLI client for Parall — universal agent & human access to Parall API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@modelcontextprotocol/sdk": "1.27.1",
|
|
31
31
|
"commander": "^13.0.0",
|
|
32
32
|
"zod": "^4.3.6",
|
|
33
|
-
"@parall/sdk": "1.
|
|
33
|
+
"@parall/sdk": "1.20.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^22.0.0",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "tsc",
|
|
41
|
-
"dev": "tsc --watch"
|
|
41
|
+
"dev": "tsc --watch",
|
|
42
|
+
"test": "pnpm run build && node --test test/*.test.mjs"
|
|
42
43
|
}
|
|
43
44
|
}
|