@parall/cli 1.33.0 → 1.35.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.
@@ -0,0 +1,540 @@
1
+ import * as z from 'zod/v4';
2
+ import { resolveRuntimeContext } from './client.js';
3
+ import { getWikiBlob, getWikiChangesetDiff, getWikiOutline, getWikiSection, getWikiTree, getWikiWorkspaceDiff, getWikiWorkspaceStatus, listWikis, proposeWikiChangeset, queryWiki, searchWiki, } from './wiki.js';
4
+ /** Pretty-print a value as 2-space-indented JSON for a tool's human-readable `text` field. */
5
+ function jsonText(value) {
6
+ return JSON.stringify(value, null, 2);
7
+ }
8
+ /**
9
+ * Wrap a tool definition so its handler validates raw args against the tool's
10
+ * `inputSchema` before running. Returns a copy with the handler replaced; the
11
+ * wrapped handler throws a Zod parse error on invalid/missing input.
12
+ */
13
+ function finalizeWikiTool(tool) {
14
+ const inputParser = z.object(tool.inputSchema);
15
+ return {
16
+ ...tool,
17
+ handler: async (args) => tool.handler(inputParser.parse(args ?? {})),
18
+ };
19
+ }
20
+ /**
21
+ * Build the full wiki native tool registry bound to a Parall context (credentials,
22
+ * agent env, local mount). Returns one definition per wiki capability (list, tree,
23
+ * status, diff, blob, search, query, outline, section, changeset diff, propose),
24
+ * each finalized with input validation. Shared by the MCP server and the eval harness.
25
+ */
26
+ export function buildWikiTools(ctx) {
27
+ const tools = [
28
+ {
29
+ name: 'wiki_list',
30
+ title: 'List Parall Wikis',
31
+ description: 'List Parall wiki repositories that the current credentials can access.',
32
+ readOnly: true,
33
+ inputSchema: {},
34
+ outputSchema: {
35
+ wikis: z.array(z.object({
36
+ id: z.string(),
37
+ slug: z.string(),
38
+ name: z.string(),
39
+ default_branch: z.string(),
40
+ })),
41
+ },
42
+ handler: async () => {
43
+ const wikis = await listWikis(ctx);
44
+ const structuredContent = {
45
+ wikis: wikis.map((wiki) => ({
46
+ id: wiki.id,
47
+ slug: wiki.slug,
48
+ name: wiki.name,
49
+ default_branch: wiki.default_branch,
50
+ })),
51
+ };
52
+ return {
53
+ text: jsonText(structuredContent),
54
+ structuredContent,
55
+ };
56
+ },
57
+ },
58
+ {
59
+ name: 'wiki_tree',
60
+ title: 'Browse Wiki Tree',
61
+ description: 'List files and folders under a Parall wiki path.',
62
+ readOnly: true,
63
+ inputSchema: {
64
+ wiki: z.string().describe('Wiki slug or ID'),
65
+ path: z.string().optional().describe('Optional tree path prefix inside the wiki'),
66
+ },
67
+ outputSchema: {
68
+ wiki_id: z.string(),
69
+ wiki_slug: z.string(),
70
+ wiki_name: z.string(),
71
+ path: z.string(),
72
+ entries: z.array(z.object({
73
+ name: z.string(),
74
+ path: z.string(),
75
+ type: z.enum(['tree', 'blob']),
76
+ size: z.number().optional(),
77
+ })),
78
+ },
79
+ handler: async (args) => {
80
+ const wiki = typeof args.wiki === 'string' ? args.wiki : '';
81
+ const path = typeof args.path === 'string' ? args.path : undefined;
82
+ const result = await getWikiTree(ctx, wiki, { path });
83
+ const structuredContent = {
84
+ wiki_id: result.wiki.id,
85
+ wiki_slug: result.wiki.slug,
86
+ wiki_name: result.wiki.name,
87
+ path: result.path,
88
+ entries: result.entries,
89
+ };
90
+ return {
91
+ text: jsonText(structuredContent),
92
+ structuredContent,
93
+ };
94
+ },
95
+ },
96
+ {
97
+ name: 'wiki_status',
98
+ title: 'Inspect Wiki Workspace Status',
99
+ description: 'Inspect the current local mounted wiki workspace before proposing changes.',
100
+ readOnly: true,
101
+ inputSchema: {
102
+ wiki: z.string().describe('Wiki slug or ID'),
103
+ },
104
+ outputSchema: {
105
+ wiki_id: z.string(),
106
+ wiki_slug: z.string(),
107
+ wiki_name: z.string(),
108
+ mount_path: z.string(),
109
+ mode: z.enum(['read_only', 'read_write']),
110
+ default_ref: z.string(),
111
+ changed_paths: z.array(z.string()),
112
+ diff_files: z.array(z.object({
113
+ path: z.string(),
114
+ additions: z.number(),
115
+ deletions: z.number(),
116
+ })),
117
+ dirty: z.boolean(),
118
+ source: z.literal('local_mount'),
119
+ },
120
+ handler: async (args) => {
121
+ const wiki = typeof args.wiki === 'string' ? args.wiki : '';
122
+ const result = await getWikiWorkspaceStatus(ctx, wiki);
123
+ return {
124
+ text: jsonText(result),
125
+ structuredContent: result,
126
+ };
127
+ },
128
+ },
129
+ {
130
+ name: 'wiki_diff',
131
+ title: 'Read Wiki Workspace Diff',
132
+ description: 'Read the current unified diff for a local mounted wiki workspace.',
133
+ readOnly: true,
134
+ inputSchema: {
135
+ wiki: z.string().describe('Wiki slug or ID'),
136
+ },
137
+ outputSchema: {
138
+ wiki_id: z.string(),
139
+ wiki_slug: z.string(),
140
+ wiki_name: z.string(),
141
+ mount_path: z.string(),
142
+ changed_paths: z.array(z.string()),
143
+ diff_files: z.array(z.object({
144
+ path: z.string(),
145
+ additions: z.number(),
146
+ deletions: z.number(),
147
+ })),
148
+ patch: z.string(),
149
+ source: z.literal('local_mount'),
150
+ },
151
+ handler: async (args) => {
152
+ const wiki = typeof args.wiki === 'string' ? args.wiki : '';
153
+ const result = await getWikiWorkspaceDiff(ctx, wiki);
154
+ return {
155
+ text: result.patch || jsonText(result),
156
+ structuredContent: result,
157
+ };
158
+ },
159
+ },
160
+ {
161
+ name: 'wiki_blob',
162
+ title: 'Read Wiki File',
163
+ description: 'Read a file from a Parall wiki and return its text content.',
164
+ readOnly: true,
165
+ inputSchema: {
166
+ wiki: z.string().describe('Wiki slug or ID'),
167
+ path: z.string().describe('File path inside the wiki'),
168
+ },
169
+ outputSchema: {
170
+ wiki_id: z.string(),
171
+ wiki_slug: z.string(),
172
+ wiki_name: z.string(),
173
+ content: z.string(),
174
+ size: z.number(),
175
+ },
176
+ handler: async (args) => {
177
+ const wiki = typeof args.wiki === 'string' ? args.wiki : '';
178
+ const path = typeof args.path === 'string' ? args.path : '';
179
+ const result = await getWikiBlob(ctx, wiki, { path });
180
+ const structuredContent = {
181
+ wiki_id: result.wiki.id,
182
+ wiki_slug: result.wiki.slug,
183
+ wiki_name: result.wiki.name,
184
+ content: result.content,
185
+ size: result.size,
186
+ };
187
+ return {
188
+ text: result.content || jsonText(structuredContent),
189
+ structuredContent,
190
+ };
191
+ },
192
+ },
193
+ {
194
+ name: 'wiki_search',
195
+ title: 'Search Wiki Markdown',
196
+ description: 'Search Markdown headings and section bodies inside a Parall wiki. Prefers local mounts when no ref is supplied and agent env is available; otherwise falls back to the Parall API.',
197
+ readOnly: true,
198
+ inputSchema: {
199
+ wiki: z.string().describe('Wiki slug or ID'),
200
+ query: z.string().describe('Search query'),
201
+ ref: z.string().optional().describe('Optional git ref for API-backed search'),
202
+ path_prefix: z
203
+ .string()
204
+ .optional()
205
+ .describe('Restrict search to a file or directory path prefix'),
206
+ limit: z
207
+ .number()
208
+ .int()
209
+ .positive()
210
+ .max(20)
211
+ .optional()
212
+ .describe('Maximum number of results; default 5'),
213
+ include_content: z
214
+ .boolean()
215
+ .optional()
216
+ .describe('Include full matched section content in each result'),
217
+ },
218
+ outputSchema: {
219
+ results: z.array(z.object({
220
+ wiki_id: z.string(),
221
+ wiki_slug: z.string(),
222
+ wiki_name: z.string(),
223
+ node_id: z.string(),
224
+ path: z.string(),
225
+ title: z.string(),
226
+ heading_path: z.array(z.string()).optional(),
227
+ section_path: z.string(),
228
+ level: z.number(),
229
+ start_line: z.number(),
230
+ end_line: z.number(),
231
+ score: z.number(),
232
+ snippet: z.string(),
233
+ content: z.string().optional(),
234
+ source: z.enum(['local_mount', 'api']),
235
+ })),
236
+ },
237
+ handler: async (args) => {
238
+ const wiki = typeof args.wiki === 'string' ? args.wiki : '';
239
+ const query = typeof args.query === 'string' ? args.query : '';
240
+ const ref = typeof args.ref === 'string' ? args.ref : undefined;
241
+ const pathPrefix = typeof args.path_prefix === 'string' ? args.path_prefix : undefined;
242
+ const limit = typeof args.limit === 'number' ? args.limit : undefined;
243
+ const includeContent = typeof args.include_content === 'boolean' ? args.include_content : undefined;
244
+ const results = await searchWiki(ctx, wiki, query, {
245
+ ref,
246
+ pathPrefix,
247
+ limit,
248
+ includeContent,
249
+ });
250
+ const structuredContent = { results };
251
+ return {
252
+ text: jsonText(structuredContent),
253
+ structuredContent,
254
+ };
255
+ },
256
+ },
257
+ {
258
+ name: 'wiki_query',
259
+ title: 'Query Wiki Structurally',
260
+ description: 'Run a tree-aware wiki query that first narrows candidate documents and then selects the best sections.',
261
+ readOnly: true,
262
+ inputSchema: {
263
+ wiki: z.string().describe('Wiki slug or ID'),
264
+ query: z.string().describe('Natural-language query'),
265
+ ref: z.string().optional().describe('Optional git ref for API-backed queries'),
266
+ path_prefix: z
267
+ .string()
268
+ .optional()
269
+ .describe('Restrict the query to a file or directory path prefix'),
270
+ limit: z
271
+ .number()
272
+ .int()
273
+ .positive()
274
+ .max(20)
275
+ .optional()
276
+ .describe('Maximum number of section results; default 5'),
277
+ include_content: z
278
+ .boolean()
279
+ .optional()
280
+ .describe('Include full matched section content in each result'),
281
+ },
282
+ outputSchema: {
283
+ wiki_id: z.string(),
284
+ wiki_slug: z.string(),
285
+ wiki_name: z.string(),
286
+ query: z.string(),
287
+ ref: z.string().optional(),
288
+ path_prefix: z.string().optional(),
289
+ generated_at: z.string(),
290
+ file_count: z.number(),
291
+ source: z.enum(['local_mount', 'api']),
292
+ documents: z.array(z.object({
293
+ path: z.string(),
294
+ title: z.string(),
295
+ score: z.number(),
296
+ matched_headings: z.array(z.string()),
297
+ node_count: z.number(),
298
+ })),
299
+ sections: z.array(z.object({
300
+ wiki_id: z.string(),
301
+ wiki_slug: z.string(),
302
+ wiki_name: z.string(),
303
+ node_id: z.string(),
304
+ path: z.string(),
305
+ title: z.string(),
306
+ heading_path: z.array(z.string()).optional(),
307
+ section_path: z.string(),
308
+ level: z.number(),
309
+ start_line: z.number(),
310
+ end_line: z.number(),
311
+ score: z.number(),
312
+ document_score: z.number(),
313
+ snippet: z.string(),
314
+ content: z.string().optional(),
315
+ source: z.enum(['local_mount', 'api']),
316
+ reasoning: z.array(z.string()),
317
+ })),
318
+ },
319
+ handler: async (args) => {
320
+ const wiki = typeof args.wiki === 'string' ? args.wiki : '';
321
+ const query = typeof args.query === 'string' ? args.query : '';
322
+ const ref = typeof args.ref === 'string' ? args.ref : undefined;
323
+ const pathPrefix = typeof args.path_prefix === 'string' ? args.path_prefix : undefined;
324
+ const limit = typeof args.limit === 'number' ? args.limit : undefined;
325
+ const includeContent = typeof args.include_content === 'boolean' ? args.include_content : undefined;
326
+ const result = await queryWiki(ctx, wiki, query, {
327
+ ref,
328
+ pathPrefix,
329
+ limit,
330
+ includeContent,
331
+ });
332
+ return {
333
+ text: jsonText(result),
334
+ structuredContent: result,
335
+ };
336
+ },
337
+ },
338
+ {
339
+ name: 'wiki_outline',
340
+ title: 'Read Wiki Outline',
341
+ description: 'Return the structural node outline for a Parall wiki or a path prefix within it.',
342
+ readOnly: true,
343
+ inputSchema: {
344
+ wiki: z.string().describe('Wiki slug or ID'),
345
+ ref: z.string().optional().describe('Optional git ref for API-backed outline'),
346
+ path_prefix: z
347
+ .string()
348
+ .optional()
349
+ .describe('Restrict outline to a file or directory path prefix'),
350
+ },
351
+ outputSchema: {
352
+ wiki_id: z.string(),
353
+ wiki_slug: z.string(),
354
+ wiki_name: z.string(),
355
+ ref: z.string().optional(),
356
+ path_prefix: z.string().optional(),
357
+ generated_at: z.string(),
358
+ file_count: z.number(),
359
+ source: z.enum(['local_mount', 'api']),
360
+ nodes: z.array(z.object({
361
+ wiki_id: z.string(),
362
+ wiki_slug: z.string(),
363
+ wiki_name: z.string(),
364
+ node_id: z.string(),
365
+ path: z.string(),
366
+ title: z.string(),
367
+ heading_path: z.array(z.string()).optional(),
368
+ section_path: z.string(),
369
+ level: z.number(),
370
+ start_line: z.number(),
371
+ end_line: z.number(),
372
+ })),
373
+ },
374
+ handler: async (args) => {
375
+ const wiki = typeof args.wiki === 'string' ? args.wiki : '';
376
+ const ref = typeof args.ref === 'string' ? args.ref : undefined;
377
+ const pathPrefix = typeof args.path_prefix === 'string' ? args.path_prefix : undefined;
378
+ const outline = await getWikiOutline(ctx, wiki, { ref, pathPrefix });
379
+ return {
380
+ text: jsonText(outline),
381
+ structuredContent: outline,
382
+ };
383
+ },
384
+ },
385
+ {
386
+ name: 'wiki_section',
387
+ title: 'Read Wiki Section',
388
+ description: 'Read a specific Markdown section from a Parall wiki by node ID. Node IDs come from `wiki_search` results.',
389
+ readOnly: true,
390
+ inputSchema: {
391
+ wiki: z.string().describe('Wiki slug or ID'),
392
+ node_id: z.string().describe('Section node ID returned by wiki_search'),
393
+ ref: z
394
+ .string()
395
+ .optional()
396
+ .describe('Optional git ref; when set, reads from the Parall API instead of a local mount'),
397
+ },
398
+ outputSchema: {
399
+ wiki_id: z.string(),
400
+ wiki_slug: z.string(),
401
+ wiki_name: z.string(),
402
+ node_id: z.string(),
403
+ path: z.string(),
404
+ title: z.string(),
405
+ heading_path: z.array(z.string()).optional(),
406
+ section_path: z.string(),
407
+ level: z.number(),
408
+ start_line: z.number(),
409
+ end_line: z.number(),
410
+ content: z.string(),
411
+ source: z.enum(['local_mount', 'api']),
412
+ },
413
+ handler: async (args) => {
414
+ const wiki = typeof args.wiki === 'string' ? args.wiki : '';
415
+ const nodeId = typeof args.node_id === 'string' ? args.node_id : '';
416
+ const ref = typeof args.ref === 'string' ? args.ref : undefined;
417
+ const section = await getWikiSection(ctx, wiki, { nodeId, ref });
418
+ return {
419
+ text: section.content || jsonText(section),
420
+ structuredContent: section,
421
+ };
422
+ },
423
+ },
424
+ {
425
+ name: 'wiki_changeset_diff',
426
+ title: 'Read Wiki Changeset Diff',
427
+ description: 'Fetch the unified diff and changed file summary for a Parall wiki changeset.',
428
+ readOnly: true,
429
+ inputSchema: {
430
+ wiki: z.string().describe('Wiki slug or ID'),
431
+ changeset_id: z.string().describe('Wiki changeset ID'),
432
+ },
433
+ outputSchema: {
434
+ wiki_id: z.string(),
435
+ wiki_slug: z.string(),
436
+ wiki_name: z.string(),
437
+ changeset_id: z.string(),
438
+ diff: z.object({
439
+ patch: z.string(),
440
+ files: z.array(z.object({
441
+ path: z.string(),
442
+ additions: z.number(),
443
+ deletions: z.number(),
444
+ })),
445
+ }),
446
+ },
447
+ handler: async (args) => {
448
+ const wiki = typeof args.wiki === 'string' ? args.wiki : '';
449
+ const changesetId = typeof args.changeset_id === 'string' ? args.changeset_id : '';
450
+ const diff = await getWikiChangesetDiff(ctx, wiki, changesetId);
451
+ return {
452
+ text: diff.diff.patch || jsonText(diff),
453
+ structuredContent: diff,
454
+ };
455
+ },
456
+ },
457
+ {
458
+ name: 'wiki_propose',
459
+ title: 'Propose Wiki Changeset',
460
+ description: 'Create or update a wiki changeset from the current local mounted wiki workspace. Unprotected changesets may auto-merge immediately.',
461
+ readOnly: false,
462
+ inputSchema: {
463
+ wiki: z.string().describe('Wiki slug or ID'),
464
+ title: z.string().min(1).describe('Changeset title'),
465
+ message: z.string().optional().describe('Changeset commit message (supports prll:// refs)'),
466
+ changeset_id: z.string().optional().describe('Existing changeset ID to update'),
467
+ source_chat_id: z
468
+ .string()
469
+ .optional()
470
+ .describe('Optional source chat ID for approval workflow linkage'),
471
+ source_message_id: z
472
+ .string()
473
+ .optional()
474
+ .describe('Optional source message ID for approval workflow linkage'),
475
+ source_run_id: z
476
+ .string()
477
+ .optional()
478
+ .describe('Optional source run ID for approval workflow linkage'),
479
+ },
480
+ outputSchema: {
481
+ wiki_id: z.string(),
482
+ wiki_slug: z.string(),
483
+ wiki_name: z.string(),
484
+ mount_path: z.string(),
485
+ changed_paths: z.array(z.string()),
486
+ status: z.string(),
487
+ auto_merged: z.boolean(),
488
+ requires_review: z.boolean(),
489
+ next_action: z.string(),
490
+ post_merge_sync: z
491
+ .object({
492
+ applied: z.number(),
493
+ fastForwarded: z.number(),
494
+ conflicts: z.array(z.unknown()),
495
+ failed: z.array(z.unknown()),
496
+ })
497
+ .nullable(),
498
+ post_merge_sync_error: z.string().nullable(),
499
+ diff_files: z.array(z.object({
500
+ path: z.string(),
501
+ additions: z.number(),
502
+ deletions: z.number(),
503
+ })),
504
+ source: z.literal('local_mount'),
505
+ changeset: z
506
+ .object({
507
+ id: z.string(),
508
+ wiki_id: z.string(),
509
+ title: z.string(),
510
+ status: z.string(),
511
+ changed_paths: z.array(z.string()).optional(),
512
+ })
513
+ .passthrough(),
514
+ },
515
+ handler: async (args) => {
516
+ const wiki = typeof args.wiki === 'string' ? args.wiki : '';
517
+ const title = typeof args.title === 'string' ? args.title : '';
518
+ const message = typeof args.message === 'string' ? args.message : undefined;
519
+ const changesetId = typeof args.changeset_id === 'string' ? args.changeset_id : undefined;
520
+ const sourceChatId = typeof args.source_chat_id === 'string' ? args.source_chat_id : undefined;
521
+ const sourceMessageId = typeof args.source_message_id === 'string' ? args.source_message_id : undefined;
522
+ const sourceRunId = typeof args.source_run_id === 'string' ? args.source_run_id : undefined;
523
+ const runtime = resolveRuntimeContext();
524
+ const result = await proposeWikiChangeset(ctx, wiki, {
525
+ title,
526
+ message,
527
+ changesetId,
528
+ sourceChatId: sourceChatId ?? runtime.chatId,
529
+ sourceMessageId: sourceMessageId ?? runtime.triggerMessageId,
530
+ sourceRunId: sourceRunId ?? runtime.sessionId,
531
+ });
532
+ return {
533
+ text: jsonText(result),
534
+ structuredContent: result,
535
+ };
536
+ },
537
+ },
538
+ ];
539
+ return tools.map(finalizeWikiTool);
540
+ }
@@ -1,4 +1,5 @@
1
1
  import { type ParallClient, type Wiki, type WikiChangeset, type WikiDiff, type WikiDiffFile, type WikiTreeEntry } from '@parall/sdk';
2
+ export { type ParsedFrontMatter, parseFrontMatter } from './wiki-frontmatter.js';
2
3
  export type ParallContext = {
3
4
  client: ParallClient;
4
5
  orgId: string;
@@ -26,6 +27,9 @@ export type WikiNodeSection = {
26
27
  level: number;
27
28
  start_line: number;
28
29
  end_line: number;
30
+ type?: string;
31
+ description?: string;
32
+ tags?: string[];
29
33
  };
30
34
  export type WikiOutlineResult = {
31
35
  wiki_id: string;
@@ -143,10 +147,12 @@ export declare function getWikiTree(ctx: ParallContext, wikiRef?: string, option
143
147
  }>;
144
148
  export declare function getWikiBlob(ctx: ParallContext, wikiRef: string | undefined, options: {
145
149
  path: string;
150
+ remote?: boolean;
146
151
  }): Promise<{
147
152
  wiki: Wiki;
148
153
  content: string;
149
154
  size: number;
155
+ source: WikiContentSource;
150
156
  }>;
151
157
  export declare function getWikiOutline(ctx: ParallContext, wikiRef?: string, options?: {
152
158
  ref?: string;
@@ -166,14 +172,11 @@ export type AfcsStatusResult = {
166
172
  wiki_slug: string;
167
173
  wiki_name: string;
168
174
  mount_path: string;
169
- mode: string;
170
175
  default_ref: string;
171
176
  /** Local workspace changes vs last-synced manifest. */
172
177
  local_changes: WikiDiffFile[];
173
178
  /** Pending changesets created by this agent. */
174
179
  changesets: AfcsChangesetSummary[];
175
- /** Permission summary — null if the API is not yet available. */
176
- permissions: AfcsPermissionSummary | null;
177
180
  };
178
181
  export type AfcsChangesetSummary = {
179
182
  id: string;
@@ -184,10 +187,6 @@ export type AfcsChangesetSummary = {
184
187
  created_at: string;
185
188
  updated_at: string;
186
189
  };
187
- export type AfcsPermissionSummary = {
188
- readable_prefixes: string[];
189
- writable_prefixes: string[];
190
- };
191
190
  export declare function getAfcsStatus(ctx: ParallContext, wikiRef?: string): Promise<AfcsStatusResult>;
192
191
  export type AfcsDiffResult = {
193
192
  wiki_id: string;
@@ -202,12 +201,15 @@ export declare function getAfcsDiff(ctx: ParallContext, wikiRef?: string): Promi
202
201
  export declare function proposeWikiChangeset(ctx: ParallContext, wikiRef: string | undefined, options: WikiProposeOptions): Promise<WikiProposeResult>;
203
202
  /**
204
203
  * Discard all local changes and restore files to the last synced state.
205
- * Reads the local manifest and restores all files from the server.
204
+ * Restores from the local baseline object store (network only as a
205
+ * SHA-verified fallback for pre-objects mounts), so the workspace lands
206
+ * exactly on the manifest baseline — `wiki status` reports clean afterwards.
206
207
  */
207
208
  export declare function resetWikiWorkspace(ctx: ParallContext, wikiRef?: string): Promise<{
208
209
  wiki_id: string;
209
210
  wiki_slug: string;
210
211
  files_restored: number;
212
+ unrestorable_paths: string[];
211
213
  }>;
212
214
  export type AfcsChangesetsResult = {
213
215
  wiki_id: string;
@@ -234,12 +236,14 @@ export type AfcsAccessRequestResult = {
234
236
  };
235
237
  export declare function requestWikiAccess(ctx: ParallContext, wikiRef: string | undefined, targetPath: string, reason?: string): Promise<AfcsAccessRequestResult>;
236
238
  export type AfcsLogEntry = {
237
- type: 'file_version' | 'operation';
239
+ type: 'commit' | 'operation';
238
240
  id: string;
239
241
  path?: string;
240
242
  action: string;
241
- actor_id: string;
242
- version?: number;
243
+ /** Parall actor ID — operation entries only (git commits carry no Parall identity). */
244
+ actor_id?: string;
245
+ /** Git author display name — commit entries only. */
246
+ author_name?: string;
243
247
  created_at: string;
244
248
  };
245
249
  export type AfcsLogResult = {
@@ -249,6 +253,10 @@ export type AfcsLogResult = {
249
253
  path?: string;
250
254
  entries: AfcsLogEntry[];
251
255
  };
256
+ /**
257
+ * Wiki history. Without a path: recent wiki operations (audit log). With a
258
+ * path: that file's commit history from the default branch.
259
+ */
252
260
  export declare function getWikiLog(ctx: ParallContext, wikiRef?: string, filePath?: string): Promise<AfcsLogResult>;
253
261
  export type SyncResult = {
254
262
  /** True iff every wiki's per-path action ran without failure. Conflicts do
@@ -267,11 +275,13 @@ export type SyncResult = {
267
275
  }[];
268
276
  };
269
277
  /**
270
- * List accessible wikis for this org, sync each via REST
271
- * (manifest comparison + bulk download), and remove stale directories.
278
+ * Sync wiki workspaces via REST (manifest comparison + bulk download).
279
+ * Without `wikiRef`: every accessible wiki is synced and stale mount
280
+ * directories are pruned. With `wikiRef`: only that wiki is synced and
281
+ * pruning is skipped — other wikis' workspaces must survive a scoped sync.
272
282
  * Mount path is determined client-side: {mountRoot}/{slug}/
273
283
  */
274
- export declare function syncAllMounts(ctx: ParallContext): Promise<SyncResult>;
284
+ export declare function syncAllMounts(ctx: ParallContext, wikiRef?: string): Promise<SyncResult>;
275
285
  /**
276
286
  * Run {@link syncAllMounts} in a loop, sleeping `intervalSec` between
277
287
  * iterations. Returns a `stop` callback to break the loop.
@@ -370,5 +380,13 @@ export declare function syncSingleWiki(ctx: ParallContext, wiki: import('@parall
370
380
  */
371
381
  export declare function writeConflictMarker(mountRoot: string, sourcePath: string, suffix: string, content: Buffer): Promise<string>;
372
382
  export declare function computeGitBlobSHA(content: Buffer): string;
373
- export {};
383
+ /**
384
+ * Mirror of the server's text classifier (filetype.IsText): content-type
385
+ * magic sniff, valid UTF-8, and no NUL bytes — kept aligned so content the
386
+ * CLI accepts cannot bounce off the server's 422 USE_UPLOAD later. The
387
+ * shared fixture table (test/testdata/text-classifier-cases.json) is
388
+ * verified by both this implementation's tests and the Go package's tests.
389
+ */
390
+ export declare function isWikiTextContent(content: Buffer): boolean;
391
+ export declare function detectFrontMatterEnd(lines: string[]): number;
374
392
  //# sourceMappingURL=wiki.d.ts.map