@oh-my-pi/pi-natives 18.0.8 → 18.0.10

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/native/index.d.ts CHANGED
@@ -331,6 +331,203 @@ export declare class TtyWriter {
331
331
  stop(flushTimeoutMs: number): void
332
332
  }
333
333
 
334
+ /** In-process Git repository handle. */
335
+ export declare class VcsGitRepo {
336
+ /** Repository metadata. */
337
+ info(): VcsGitRepoInfo
338
+ /** Primary checkout root. */
339
+ primaryRoot(): string
340
+ /** Linked-worktree metadata. */
341
+ linkedWorktree(): VcsLinkedWorktree | null
342
+ /** Resolve HEAD synchronously. */
343
+ headSync(): VcsHeadState
344
+ /** Worktree-relative prefix of a directory. */
345
+ prefixOf(dir: string): string | null
346
+ /** Resolve HEAD. */
347
+ head(signal?: unknown | undefined | null): Promise<VcsHeadState>
348
+ /** Resolve HEAD SHA. */
349
+ headSha(signal?: unknown | undefined | null): Promise<string | undefined | null>
350
+ /** Current branch. */
351
+ currentBranch(signal?: unknown | undefined | null): Promise<string | undefined | null>
352
+ /** Default remote branch. */
353
+ defaultBranch(signal?: unknown | undefined | null): Promise<string | undefined | null>
354
+ /** Resolve a revision. */
355
+ resolveRef(name: string, signal?: unknown | undefined | null): Promise<string | undefined | null>
356
+ /** Test revision existence. */
357
+ refExists(name: string, signal?: unknown | undefined | null): Promise<boolean>
358
+ /** Tags pointing at a revision. */
359
+ tagsAt(rev: string, signal?: unknown | undefined | null): Promise<Array<string>>
360
+ /** List branches. */
361
+ listBranches(all: boolean, signal?: unknown | undefined | null): Promise<Array<string>>
362
+ /**
363
+ * Whether default porcelain status reports a staged, unstaged, or untracked
364
+ * change.
365
+ */
366
+ isDirty(signal?: unknown | undefined | null): Promise<boolean>
367
+ /** Porcelain status. */
368
+ statusPorcelain(options: VcsStatusOptions, signal?: unknown | undefined | null): Promise<string>
369
+ /** Status counts. */
370
+ statusSummary(signal?: unknown | undefined | null): Promise<VcsStatusSummary>
371
+ /** Read config. */
372
+ configGet(key: string, signal?: unknown | undefined | null): Promise<string | undefined | null>
373
+ /** Set config. */
374
+ configSet(key: string, value: string, signal?: unknown | undefined | null): Promise<undefined>
375
+ /** List remotes. */
376
+ remoteList(signal?: unknown | undefined | null): Promise<Array<string>>
377
+ /** Remote URL. */
378
+ remoteUrl(name: string, signal?: unknown | undefined | null): Promise<string | undefined | null>
379
+ /** Add remote. */
380
+ remoteAdd(name: string, url: string, signal?: unknown | undefined | null): Promise<undefined>
381
+ /** List worktrees. */
382
+ worktrees(signal?: unknown | undefined | null): Promise<Array<VcsWorktreeEntry>>
383
+ /** Add worktree. */
384
+ worktreeAdd(path: string, refName: string, detach: boolean, signal?: unknown | undefined | null): Promise<undefined>
385
+ /** Remove worktree. */
386
+ worktreeRemove(path: string, force: boolean, signal?: unknown | undefined | null): Promise<boolean>
387
+ /** Prune worktrees. */
388
+ worktreePrune(signal?: unknown | undefined | null): Promise<undefined>
389
+ /** Recent subjects. */
390
+ logSubjects(count: number, signal?: unknown | undefined | null): Promise<Array<string>>
391
+ /** Recent one-line commits. */
392
+ logOnelines(count: number, signal?: unknown | undefined | null): Promise<Array<string>>
393
+ /** Commits in a range. */
394
+ revListRange(base: string, head: string, signal?: unknown | undefined | null): Promise<Array<string>>
395
+ /** Best common ancestor of two revisions. */
396
+ mergeBase(a: string, b: string, signal?: unknown | undefined | null): Promise<string | undefined | null>
397
+ /** Commits touching a file. */
398
+ revListTouching(rev: string, file: string, limit: number, signal?: unknown | undefined | null): Promise<Array<string>>
399
+ /** Commit details. */
400
+ commitDetails(rev: string, signal?: unknown | undefined | null): Promise<VcsCommitDetails>
401
+ /** List index or untracked paths. */
402
+ lsFiles(others: boolean, excludeStandard: boolean, signal?: unknown | undefined | null): Promise<Array<string>>
403
+ /** List tree paths. */
404
+ lsTree(rev: string, paths: Array<string>, signal?: unknown | undefined | null): Promise<Array<string>>
405
+ /** List submodule paths. */
406
+ submodulePaths(signal?: unknown | undefined | null): Promise<Array<string>>
407
+ /** Read blob bytes. */
408
+ showBlob(spec: string, maxBytes?: number | undefined | null, signal?: unknown | undefined | null): Promise<VcsShowResult>
409
+ /** Read commit and patch bytes. */
410
+ showCommit(rev: string, maxBytes?: number | undefined | null, signal?: unknown | undefined | null): Promise<VcsShowResult>
411
+ /** Local LFS media directory. */
412
+ lfsMediaDir(signal?: unknown | undefined | null): Promise<string | undefined | null>
413
+ /** Render a patch. */
414
+ diffText(options: VcsDiffOptions, signal?: unknown | undefined | null): Promise<string>
415
+ /** Render a no-index patch between two filesystem paths. */
416
+ diffNoIndex(left: string, right: string, binary: boolean, signal?: unknown | undefined | null): Promise<string>
417
+ /** Changed paths. */
418
+ changedFiles(options: VcsDiffOptions, signal?: unknown | undefined | null): Promise<Array<string>>
419
+ /** Per-file line counts. */
420
+ numstat(options: VcsDiffOptions, signal?: unknown | undefined | null): Promise<Array<VcsNumstatEntry>>
421
+ /** Test for a diff. */
422
+ hasDiff(options: VcsDiffOptions, signal?: unknown | undefined | null): Promise<boolean>
423
+ /** Diff two trees. */
424
+ diffTree(base: string, head: string, binary: boolean, signal?: unknown | undefined | null): Promise<string>
425
+ /** Stage paths. */
426
+ stageFiles(files: Array<string>, signal?: unknown | undefined | null): Promise<undefined>
427
+ /** Unstage paths. */
428
+ unstage(files: Array<string>, signal?: unknown | undefined | null): Promise<undefined>
429
+ /** Stage selected hunks. */
430
+ stageHunks(selections: Array<VcsHunkSelection>, rawDiff?: string | undefined | null, signal?: unknown | undefined | null): Promise<undefined>
431
+ /** Create commit. */
432
+ commitCreate(message: string, options: VcsCommitOptions, signal?: unknown | undefined | null): Promise<string>
433
+ /** Checkout revision. */
434
+ checkout(rev: string, signal?: unknown | undefined | null): Promise<undefined>
435
+ /** Create branch. */
436
+ createBranch(name: string, start: string, force: boolean, signal?: unknown | undefined | null): Promise<undefined>
437
+ /** Delete branch. */
438
+ deleteBranch(name: string, force: boolean, signal?: unknown | undefined | null): Promise<boolean>
439
+ /** Create and checkout branch. */
440
+ checkoutNewBranch(name: string, signal?: unknown | undefined | null): Promise<undefined>
441
+ /** Restore paths. */
442
+ restore(options: VcsRestoreOptions, signal?: unknown | undefined | null): Promise<undefined>
443
+ /** Reset repository state. */
444
+ reset(mode: string, target?: string | undefined | null, signal?: unknown | undefined | null): Promise<undefined>
445
+ /** Clean untracked paths. */
446
+ clean(options: VcsCleanOptions, signal?: unknown | undefined | null): Promise<undefined>
447
+ /** Read tree into index. */
448
+ readTree(treeish: string, indexPath?: string | undefined | null, signal?: unknown | undefined | null): Promise<undefined>
449
+ /** Write index tree. */
450
+ writeTree(indexPath?: string | undefined | null, signal?: unknown | undefined | null): Promise<string>
451
+ /** Apply patch. */
452
+ applyPatch(patch: string, options: VcsApplyOptions, signal?: unknown | undefined | null): Promise<undefined>
453
+ /** Check patch applicability. */
454
+ canApplyPatch(patch: string, options: VcsApplyOptions, signal?: unknown | undefined | null): Promise<boolean>
455
+ /** Cherry-pick commit. */
456
+ cherryPick(rev: string, signal?: unknown | undefined | null): Promise<undefined>
457
+ /** Abort cherry-pick. */
458
+ cherryPickAbort(signal?: unknown | undefined | null): Promise<undefined>
459
+ /** Skip cherry-pick. */
460
+ cherryPickSkip(signal?: unknown | undefined | null): Promise<undefined>
461
+ /** Push stash. */
462
+ stashPush(message?: string | undefined | null, signal?: unknown | undefined | null): Promise<boolean>
463
+ /** Pop stash if cleanly applicable. */
464
+ stashTryPop(reinstateIndex: boolean, signal?: unknown | undefined | null): Promise<boolean>
465
+ /** Push via Git CLI. */
466
+ push(options: VcsPushOptions, signal?: unknown | undefined | null): Promise<void>
467
+ /** Fetch a refspec via Git CLI. */
468
+ fetch(remote: string, source: string, target: string, timeoutMs?: number | undefined | null, signal?: unknown | undefined | null): Promise<void>
469
+ }
470
+
471
+ /** In-process Jujutsu workspace handle. */
472
+ export declare class VcsJjWorkspace {
473
+ /** Workspace root. */
474
+ root(): string
475
+ /** Shared store directory. */
476
+ storeDir(): string
477
+ /** Working-copy label. */
478
+ workingCopyLabel(signal?: unknown | undefined | null): Promise<string | undefined | null>
479
+ /** Status counts. */
480
+ statusSummary(signal?: unknown | undefined | null): Promise<VcsStatusSummary>
481
+ /** Render working-copy patch. */
482
+ diffText(files: Array<string>, snapshot: boolean, signal?: unknown | undefined | null): Promise<string>
483
+ /** List changed paths. */
484
+ changedFiles(files: Array<string>, snapshot: boolean, signal?: unknown | undefined | null): Promise<Array<string>>
485
+ }
486
+
487
+ /** Backend-agnostic repository handle for portable VCS reads. */
488
+ export declare class VcsRepo {
489
+ /** Backend kind (`"git"` or `"jj"`). */
490
+ kind(): string
491
+ /** Checkout or workspace root. */
492
+ root(): string
493
+ /** Primary checkout or default workspace root. */
494
+ primaryRoot(): string
495
+ /** Worktree-relative prefix of a directory. */
496
+ prefixOf(dir: string): string | null
497
+ /** Filesystem target to watch for repository-head changes. */
498
+ watchTarget(): string
499
+ /** Whether this backend implements a portable feature. */
500
+ supports(feature: string): boolean
501
+ /** Git-specific handle when this repository is backed by Git. */
502
+ asGit(): VcsGitRepo | null
503
+ /** Jujutsu-specific handle when this repository is backed by Jujutsu. */
504
+ asJj(): VcsJjWorkspace | null
505
+ /** Human label for the working copy. */
506
+ label(signal?: unknown | undefined | null): Promise<string | undefined | null>
507
+ /** Working-copy commit id. */
508
+ headId(signal?: unknown | undefined | null): Promise<string | undefined | null>
509
+ /** Status counts. */
510
+ statusSummary(signal?: unknown | undefined | null): Promise<VcsStatusSummary>
511
+ /** Porcelain status. */
512
+ statusPorcelain(options: VcsStatusOptions, signal?: unknown | undefined | null): Promise<string>
513
+ /** Render a patch. */
514
+ diffText(options: VcsDiffOptions, signal?: unknown | undefined | null): Promise<string>
515
+ /** Changed paths. */
516
+ changedFiles(options: VcsDiffOptions, signal?: unknown | undefined | null): Promise<Array<string>>
517
+ /** Per-file line counts. */
518
+ numstat(options: VcsDiffOptions, signal?: unknown | undefined | null): Promise<Array<VcsNumstatEntry>>
519
+ /** Every working-copy change since the last commit. */
520
+ uncommittedDiff(files: Array<string>, signal?: unknown | undefined | null): Promise<string>
521
+ /** Recent subjects. */
522
+ logSubjects(count: number, signal?: unknown | undefined | null): Promise<Array<string>>
523
+ /** Recent one-line commits. */
524
+ logOnelines(count: number, signal?: unknown | undefined | null): Promise<Array<string>>
525
+ /** Commit details. */
526
+ commitDetails(rev: string, signal?: unknown | undefined | null): Promise<VcsCommitDetails>
527
+ /** List tracked or untracked paths. */
528
+ lsFiles(others: boolean, excludeStandard: boolean, signal?: unknown | undefined | null): Promise<Array<string>>
529
+ }
530
+
334
531
  /**
335
532
  * Install the bounded Tokio runtime napi-rs adopts for async exports and the
336
533
  * bounded Rayon global pool used by native parallel iterators.
@@ -376,7 +573,7 @@ export declare function __ompInstallTokioRuntime(): void
376
573
  * `packages/natives/native/index.js` (which derives the name from
377
574
  * `package.json#version`).
378
575
  */
379
- export declare function __piNativesV18_0_8(): void
576
+ export declare function __piNativesV18_0_10(): void
380
577
 
381
578
  /**
382
579
  * Apply ast-grep rewrite rules to matching files; honors `dryRun` and returns
@@ -1009,6 +1206,22 @@ export declare enum Encoding {
1009
1206
  Glm5 = 'Glm5'
1010
1207
  }
1011
1208
 
1209
+ /**
1210
+ * Replace the current process image via `execvp(3)`.
1211
+ *
1212
+ * On success this never returns: the kernel tears down every other thread and
1213
+ * the new program takes over this PID, controlling terminal, and inherited
1214
+ * (non-`CLOEXEC`) file descriptors. Callers must flush logs and restore the
1215
+ * terminal first — no JS or native cleanup runs after a successful call.
1216
+ *
1217
+ * # Errors
1218
+ * Returns an error, leaving the process untouched, when `argv` is empty, an
1219
+ * argument contains an interior NUL byte, or the exec itself fails (e.g.
1220
+ * executable not found). Windows has no exec-replace semantics, so this
1221
+ * always errors there; callers fall back to spawn-and-wait.
1222
+ */
1223
+ export declare function execReplace(argv: Array<string>): void
1224
+
1012
1225
  /**
1013
1226
  * Execute a brush shell command.
1014
1227
  *
@@ -2213,6 +2426,177 @@ export declare function supportsLanguage(lang: string): boolean
2213
2426
  */
2214
2427
  export declare function truncateToWidth(text: string, maxWidth: number, ellipsisKind: Ellipsis | undefined | null, pad: boolean | undefined | null, tabWidth: number): string
2215
2428
 
2429
+ /** Patch application options. */
2430
+ export interface VcsApplyOptions {
2431
+ cached?: boolean
2432
+ indexPath?: string
2433
+ reverse?: boolean
2434
+ threeWay?: boolean
2435
+ }
2436
+
2437
+ /** Clean options. */
2438
+ export interface VcsCleanOptions {
2439
+ ignoredOnly?: boolean
2440
+ includeIgnored?: boolean
2441
+ paths?: Array<string>
2442
+ }
2443
+
2444
+ /** Clone options. */
2445
+ export interface VcsCloneOptions {
2446
+ refName?: string
2447
+ sha?: string
2448
+ timeoutMs?: number
2449
+ }
2450
+
2451
+ /** Commit author identity. */
2452
+ export interface VcsCommitAuthor {
2453
+ name: string
2454
+ email: string
2455
+ date?: string
2456
+ }
2457
+
2458
+ /** Commit metadata. */
2459
+ export interface VcsCommitDetails {
2460
+ sha: string
2461
+ parents: Array<string>
2462
+ author: VcsCommitAuthor
2463
+ message: string
2464
+ }
2465
+
2466
+ /** Commit creation options. */
2467
+ export interface VcsCommitOptions {
2468
+ author?: VcsCommitAuthor
2469
+ allowEmpty?: boolean
2470
+ amend?: boolean
2471
+ files?: Array<string>
2472
+ }
2473
+
2474
+ /** Detach copied Git metadata. */
2475
+ export declare function vcsDetachGitDir(worktreeRoot: string, sourceCommonDir: string, signal?: unknown | undefined | null): Promise<string>
2476
+
2477
+ /** Diff generation options. */
2478
+ export interface VcsDiffOptions {
2479
+ cached?: boolean
2480
+ base?: string
2481
+ head?: string
2482
+ files?: Array<string>
2483
+ context?: number
2484
+ binary?: boolean
2485
+ }
2486
+
2487
+ /** Discover the repository owning a directory. */
2488
+ export declare function vcsDiscover(dir: string): VcsRepo | null
2489
+
2490
+ /** Clone a Git repository. */
2491
+ export declare function vcsGitClone(url: string, target: string, options: VcsCloneOptions, signal?: unknown | undefined | null): Promise<void>
2492
+
2493
+ /** Discover the Git checkout containing a directory. */
2494
+ export declare function vcsGitDiscover(dir: string): VcsGitRepo | null
2495
+
2496
+ /** Discover Git metadata without opening the repository. */
2497
+ export declare function vcsGitRepoInfo(dir: string): VcsGitRepoInfo | null
2498
+
2499
+ /** Discovered Git repository paths. */
2500
+ export interface VcsGitRepoInfo {
2501
+ repoRoot: string
2502
+ gitEntryPath: string
2503
+ gitDir: string
2504
+ commonDir: string
2505
+ headPath: string
2506
+ isReftable: boolean
2507
+ }
2508
+
2509
+ /** Resolved HEAD state. */
2510
+ export interface VcsHeadState {
2511
+ kind: string
2512
+ refName?: string
2513
+ branch?: string
2514
+ commit?: string
2515
+ }
2516
+
2517
+ /** Selected hunks or line range for a path. */
2518
+ export interface VcsHunkSelection {
2519
+ path: string
2520
+ kind: string
2521
+ indices?: Array<number>
2522
+ start?: number
2523
+ end?: number
2524
+ }
2525
+
2526
+ /** Invalid hunk selection. */
2527
+ export interface VcsHunkSelectionError {
2528
+ path: string
2529
+ message: string
2530
+ }
2531
+
2532
+ /** Test whether a directory is a pure jj workspace. */
2533
+ export declare function vcsIsPureJj(dir: string): boolean
2534
+
2535
+ /** Discover a Jujutsu workspace. */
2536
+ export declare function vcsJjDiscover(dir: string): VcsJjWorkspace | null
2537
+
2538
+ /** Join patch fragments. */
2539
+ export declare function vcsJoinPatches(parts: Array<string>): string
2540
+
2541
+ /** Linked worktree metadata. */
2542
+ export interface VcsLinkedWorktree {
2543
+ root: string
2544
+ primaryRoot: string
2545
+ }
2546
+
2547
+ /** Per-file line counts. */
2548
+ export interface VcsNumstatEntry {
2549
+ path: string
2550
+ added?: number
2551
+ removed?: number
2552
+ }
2553
+
2554
+ /** Push options. */
2555
+ export interface VcsPushOptions {
2556
+ remote?: string
2557
+ refspec?: string
2558
+ forceWithLease?: boolean
2559
+ }
2560
+
2561
+ /** Restore options. */
2562
+ export interface VcsRestoreOptions {
2563
+ source?: string
2564
+ staged?: boolean
2565
+ worktree?: boolean
2566
+ files?: Array<string>
2567
+ }
2568
+
2569
+ /** Bounded object contents. */
2570
+ export interface VcsShowResult {
2571
+ data: Buffer
2572
+ truncated: boolean
2573
+ }
2574
+
2575
+ /** Status query options. */
2576
+ export interface VcsStatusOptions {
2577
+ untracked?: string
2578
+ pathspecs?: Array<string>
2579
+ nulTerminated?: boolean
2580
+ }
2581
+
2582
+ /** Git status counts. */
2583
+ export interface VcsStatusSummary {
2584
+ staged: number
2585
+ unstaged: number
2586
+ untracked: number
2587
+ }
2588
+
2589
+ /** Validate hunk selections. */
2590
+ export declare function vcsValidateHunkSelections(rawDiff: string, selections: Array<VcsHunkSelection>): Array<VcsHunkSelectionError>
2591
+
2592
+ /** One worktree listing row. */
2593
+ export interface VcsWorktreeEntry {
2594
+ path: string
2595
+ head?: string
2596
+ branch?: string
2597
+ detached: boolean
2598
+ }
2599
+
2216
2600
  /**
2217
2601
  * Score every row of a normalized `f32` matrix against `query` and return
2218
2602
  * the top `limit` rows.
package/native/index.js CHANGED
@@ -30,10 +30,13 @@ export const Process = nativeBindings.Process;
30
30
  export const PtySession = nativeBindings.PtySession;
31
31
  export const Shell = nativeBindings.Shell;
32
32
  export const TtyWriter = nativeBindings.TtyWriter;
33
+ export const VcsGitRepo = nativeBindings.VcsGitRepo;
34
+ export const VcsJjWorkspace = nativeBindings.VcsJjWorkspace;
35
+ export const VcsRepo = nativeBindings.VcsRepo;
33
36
 
34
37
  // functions
35
38
  export const __ompInstallTokioRuntime = nativeBindings.__ompInstallTokioRuntime;
36
- export const __piNativesV18_0_8 = nativeBindings.__piNativesV18_0_8;
39
+ export const __piNativesV18_0_10 = nativeBindings.__piNativesV18_0_10;
37
40
  export const astEdit = nativeBindings.astEdit;
38
41
  export const astGrep = nativeBindings.astGrep;
39
42
  export const astMatch = nativeBindings.astMatch;
@@ -48,6 +51,7 @@ export const diffLines = nativeBindings.diffLines;
48
51
  export const diffWords = nativeBindings.diffWords;
49
52
  export const enclosingBlockBoundaries = nativeBindings.enclosingBlockBoundaries;
50
53
  export const encodeSixel = nativeBindings.encodeSixel;
54
+ export const execReplace = nativeBindings.execReplace;
51
55
  export const executeShell = nativeBindings.executeShell;
52
56
  export const extractSegments = nativeBindings.extractSegments;
53
57
  export const fuzzyFind = nativeBindings.fuzzyFind;
@@ -91,6 +95,15 @@ export const structuredPatchHunks = nativeBindings.structuredPatchHunks;
91
95
  export const summarizeCode = nativeBindings.summarizeCode;
92
96
  export const supportsLanguage = nativeBindings.supportsLanguage;
93
97
  export const truncateToWidth = nativeBindings.truncateToWidth;
98
+ export const vcsDetachGitDir = nativeBindings.vcsDetachGitDir;
99
+ export const vcsDiscover = nativeBindings.vcsDiscover;
100
+ export const vcsGitClone = nativeBindings.vcsGitClone;
101
+ export const vcsGitDiscover = nativeBindings.vcsGitDiscover;
102
+ export const vcsGitRepoInfo = nativeBindings.vcsGitRepoInfo;
103
+ export const vcsIsPureJj = nativeBindings.vcsIsPureJj;
104
+ export const vcsJjDiscover = nativeBindings.vcsJjDiscover;
105
+ export const vcsJoinPatches = nativeBindings.vcsJoinPatches;
106
+ export const vcsValidateHunkSelections = nativeBindings.vcsValidateHunkSelections;
94
107
  export const vectorIndexTopK = nativeBindings.vectorIndexTopK;
95
108
  export const visibleWidth = nativeBindings.visibleWidth;
96
109
  export const warmHighlighter = nativeBindings.warmHighlighter;
@@ -0,0 +1,94 @@
1
+ import type {
2
+ VcsCloneOptions,
3
+ VcsGitRepo,
4
+ VcsGitRepoInfo,
5
+ VcsHunkSelection,
6
+ VcsHunkSelectionError,
7
+ VcsJjWorkspace,
8
+ VcsRepo,
9
+ } from "./index.js";
10
+ /** Portable capabilities that differ between Git and Jujutsu. */
11
+ export type VcsFeature = "stagedDiff" | "revDiff";
12
+
13
+ /**
14
+ * A native VCS failure: a real `Error` constructed by the Rust layer on the
15
+ * JS thread, carrying a machine-readable `code` and the CLI result fields.
16
+ * Non-CLI failures synthesize `exitCode: 1` and mirror `message` into
17
+ * `stderr`. Identify with {@link isVcsError} — `instanceof` cannot work for
18
+ * foreign-constructed errors.
19
+ */
20
+ export interface VcsError extends Error {
21
+ name: "VcsError";
22
+ code:
23
+ | "NotARepository"
24
+ | "RefNotFound"
25
+ | "ObjectNotFound"
26
+ | "EmptyCherryPick"
27
+ | "Conflict"
28
+ | "PatchFailed"
29
+ | "Cli"
30
+ | "CliTimeout"
31
+ | "Io"
32
+ | "Backend"
33
+ | "Canceled"
34
+ | "Unsupported";
35
+ exitCode: number;
36
+ stdout: string;
37
+ stderr: string;
38
+ }
39
+
40
+ /** True when `error` is a native VCS failure. */
41
+ export declare function isVcsError(error: unknown): error is VcsError;
42
+
43
+ /** True when a cherry-pick failed because the commit is already applied. */
44
+ export declare function isEmptyCherryPick(error: unknown): error is VcsError & { code: "EmptyCherryPick" };
45
+
46
+ /** Discover the git repository containing `dir`; `null` outside any checkout. */
47
+ export declare function git(dir: string): VcsGitRepo | null;
48
+ /** Discover the repository owning `dir`; `null` outside any repository. */
49
+ export declare function repo(dir: string): VcsRepo | null;
50
+
51
+ /** Like {@link repo}, asserting any requested backend capabilities. */
52
+ export declare function require(dir: string, ...features: VcsFeature[]): VcsRepo;
53
+
54
+ /** Like {@link git}, but throws a `NotARepository` {@link VcsError}. */
55
+ export declare function requireGit(dir: string): VcsGitRepo;
56
+
57
+ /** Repository metadata only (cheap fs walk) — for synchronous render paths. */
58
+ export declare function gitInfo(dir: string): VcsGitRepoInfo | null;
59
+
60
+ /** Discover the Jujutsu workspace containing `dir`; `null` when absent. */
61
+ export declare function jj(dir: string): VcsJjWorkspace | null;
62
+
63
+ /** Whether jj is the nearest VCS ancestor, making git automation unsafe. */
64
+ export declare function isPureJj(dir: string): boolean;
65
+
66
+ /** Clone a repository (git CLI under the hood for credential parity). */
67
+ export declare function clone(
68
+ url: string,
69
+ target: string,
70
+ options?: VcsCloneOptions,
71
+ signal?: AbortSignal,
72
+ ): Promise<void>;
73
+
74
+ /** Sever a copied working tree from shared git metadata. */
75
+ export declare function detachGitDir(
76
+ worktreeRoot: string,
77
+ sourceCommonDir: string,
78
+ signal?: AbortSignal,
79
+ ): Promise<"no-git" | "independent" | "detached">;
80
+
81
+ /** Join patch fragments, preserving each part's trailing newline. */
82
+ export declare function joinPatches(parts: string[]): string;
83
+
84
+ /** Validate hunk selections against a raw diff. */
85
+ export declare function validateHunkSelections(
86
+ rawDiff: string,
87
+ selections: VcsHunkSelection[],
88
+ ): VcsHunkSelectionError[];
89
+
90
+ /** Stat-poll interval for {@link watch}. */
91
+ export declare const HEAD_WATCH_INTERVAL_MS: number;
92
+
93
+ /** Watch a repository for head changes; returns a disposer. */
94
+ export declare function watch(repo: VcsRepo, onChange: () => void, intervalMs?: number): () => void;
package/native/vcs.js ADDED
@@ -0,0 +1,119 @@
1
+ import * as fs from "node:fs";
2
+ import { loadNative } from "./loader-state.js";
3
+
4
+ let native;
5
+ function api() {
6
+ native ??= loadNative();
7
+ return native;
8
+ }
9
+ function vcsError(code, message) {
10
+ const error = new Error(message);
11
+ error.name = "VcsError";
12
+ error.code = code;
13
+ error.exitCode = 1;
14
+ error.stdout = "";
15
+ error.stderr = message;
16
+ return error;
17
+ }
18
+
19
+ /**
20
+ * True when `error` is a native VCS failure. The native layer constructs these
21
+ * on the JS thread as real `Error` objects with `name: "VcsError"`, a
22
+ * machine-readable `code`, and `exitCode`/`stdout`/`stderr` properties — an
23
+ * `instanceof` check is impossible for foreign-constructed errors, so identity
24
+ * rides on `name`.
25
+ */
26
+ export function isVcsError(error) {
27
+ return error instanceof Error && error.name === "VcsError";
28
+ }
29
+
30
+ /** True when a cherry-pick failed because the commit is already applied. */
31
+ export function isEmptyCherryPick(error) {
32
+ return isVcsError(error) && error.code === "EmptyCherryPick";
33
+ }
34
+
35
+ /** Discover the git repository containing `dir`; `null` outside any checkout. */
36
+ export function git(dir) {
37
+ return api().vcsGitDiscover(dir);
38
+ }
39
+ /** Discover the repository owning `dir`; `null` outside any repository. */
40
+ export function repo(dir) {
41
+ return api().vcsDiscover(dir);
42
+ }
43
+
44
+ /** Like {@link repo}, asserting any requested backend capabilities. */
45
+ export function require(dir, ...features) {
46
+ const discovered = repo(dir);
47
+ if (!discovered) throw vcsError("NotARepository", `not a repository: ${dir}`);
48
+ for (const feature of features) {
49
+ if (!discovered.supports(feature)) {
50
+ throw vcsError(
51
+ "Unsupported",
52
+ `\`${feature}\` is not supported on a ${discovered.kind()} repository`,
53
+ );
54
+ }
55
+ }
56
+ return discovered;
57
+ }
58
+
59
+ /** Like {@link git}, but throws a `NotARepository` VcsError. */
60
+ export function requireGit(dir) {
61
+ const repo = git(dir);
62
+ if (!repo) {
63
+ throw vcsError("NotARepository", `not a repository: ${dir}`);
64
+ }
65
+ return repo;
66
+ }
67
+
68
+ /** Repository metadata only (cheap fs walk) — for synchronous render paths. */
69
+ export function gitInfo(dir) {
70
+ return api().vcsGitRepoInfo(dir);
71
+ }
72
+
73
+ /** Discover the Jujutsu workspace containing `dir`; `null` when absent. */
74
+ export function jj(dir) {
75
+ return api().vcsJjDiscover(dir);
76
+ }
77
+
78
+ /** Whether jj is the nearest VCS ancestor, making git automation unsafe. */
79
+ export function isPureJj(dir) {
80
+ return api().vcsIsPureJj(dir);
81
+ }
82
+
83
+ /** Clone a repository (git CLI under the hood for credential parity). */
84
+ export function clone(url, target, options = {}, signal) {
85
+ return api().vcsGitClone(url, target, options, signal);
86
+ }
87
+
88
+ /** Sever a copied working tree from shared git metadata. */
89
+ export function detachGitDir(worktreeRoot, sourceCommonDir, signal) {
90
+ return api().vcsDetachGitDir(worktreeRoot, sourceCommonDir, signal);
91
+ }
92
+
93
+ /** Join patch fragments, preserving each part's trailing newline. */
94
+ export function joinPatches(parts) {
95
+ return api().vcsJoinPatches(parts);
96
+ }
97
+
98
+ /** Validate hunk selections against a raw diff. */
99
+ export function validateHunkSelections(rawDiff, selections) {
100
+ return api().vcsValidateHunkSelections(rawDiff, selections);
101
+ }
102
+
103
+ /** Stat-poll interval for {@link watch}. */
104
+ export const HEAD_WATCH_INTERVAL_MS = 1000;
105
+
106
+ /**
107
+ * Watch a repository for head changes; returns a disposer.
108
+ *
109
+ * Stat-polls via `fs.watchFile` instead of `fs.watch`: backends may atomically
110
+ * replace the watched entry, permanently silencing inotify-backed watchers.
111
+ */
112
+ export function watch(repo, onChange, intervalMs = HEAD_WATCH_INTERVAL_MS) {
113
+ const target = repo.watchTarget();
114
+ const listener = (curr, prev) => {
115
+ if (curr.mtimeMs !== prev.mtimeMs || curr.ino !== prev.ino || curr.size !== prev.size) onChange();
116
+ };
117
+ fs.watchFile(target, { interval: intervalMs }, listener).unref();
118
+ return () => fs.unwatchFile(target, listener);
119
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oh-my-pi/pi-natives",
3
- "version": "18.0.8",
3
+ "version": "18.0.10",
4
4
  "description": "Native Rust bindings for PDF conversion, audio, WebRTC, grep, clipboard, image processing, syntax highlighting, PTY, and shell operations via N-API",
5
5
  "type": "module",
6
6
  "homepage": "https://omp.sh",
@@ -72,6 +72,8 @@
72
72
  "native/desktop-adapter.d.ts",
73
73
  "native/loader-state.js",
74
74
  "native/loader-state.d.ts",
75
+ "native/vcs.js",
76
+ "native/vcs.d.ts",
75
77
  "native/embedded-addon.js",
76
78
  "README.md",
77
79
  "LICENSE",
@@ -89,13 +91,17 @@
89
91
  "./clipboard": {
90
92
  "types": "./native/clipboard.d.ts",
91
93
  "import": "./native/clipboard.js"
94
+ },
95
+ "./vcs": {
96
+ "types": "./native/vcs.d.ts",
97
+ "import": "./native/vcs.js"
92
98
  }
93
99
  },
94
100
  "optionalDependencies": {
95
- "@oh-my-pi/pi-natives-linux-x64": "18.0.8",
96
- "@oh-my-pi/pi-natives-linux-arm64": "18.0.8",
97
- "@oh-my-pi/pi-natives-darwin-x64": "18.0.8",
98
- "@oh-my-pi/pi-natives-darwin-arm64": "18.0.8",
99
- "@oh-my-pi/pi-natives-win32-x64": "18.0.8"
101
+ "@oh-my-pi/pi-natives-linux-x64": "18.0.10",
102
+ "@oh-my-pi/pi-natives-linux-arm64": "18.0.10",
103
+ "@oh-my-pi/pi-natives-darwin-x64": "18.0.10",
104
+ "@oh-my-pi/pi-natives-darwin-arm64": "18.0.10",
105
+ "@oh-my-pi/pi-natives-win32-x64": "18.0.10"
100
106
  }
101
107
  }