@wahack/pi-coding-agent 15.11.0 → 15.11.2

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@wahack/pi-coding-agent",
4
- "version": "15.11.0",
4
+ "version": "15.11.2",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -44,7 +44,7 @@
44
44
  "generate-template": "bun scripts/generate-template.ts"
45
45
  },
46
46
  "dependencies": {
47
- "@agentclientprotocol/sdk": "^1.0.0",
47
+ "@agentclientprotocol/sdk": "^0.22.0",
48
48
  "@babel/parser": "^7.27.0",
49
49
  "@mozilla/readability": "^0.6.0",
50
50
  "@oh-my-pi/hashline": "^15.11.3",
@@ -72,6 +72,7 @@
72
72
  },
73
73
  "files": [
74
74
  "src",
75
+ "stubs",
75
76
  "dist/cli.js",
76
77
  "dist/*.node",
77
78
  "scripts",
@@ -1,4 +1,4 @@
1
- import { emergencyTerminalRestore } from './stubs/tui/index.ts';
1
+ import { emergencyTerminalRestore } from '../../stubs/tui/index.ts';
2
2
  import { postmortem } from "@oh-my-pi/pi-utils";
3
3
 
4
4
  /**
@@ -0,0 +1,814 @@
1
+ // Stub for @oh-my-pi/pi-natives — provides minimal native bindings for pi-coding-agent
2
+ // used in Vividra's SDK context. Real N-API binaries are not needed.
3
+
4
+ import type { Ellipsis } from "@oh-my-pi/pi-tui";
5
+
6
+ // ---------------------------------------------------------------------------
7
+ // countTokens — critical stub for agent-session.ts:6205
8
+ // ---------------------------------------------------------------------------
9
+ export function countTokens(input: string | string[], _encoding?: Encoding | null): number {
10
+ const text = Array.isArray(input) ? input.join(" ") : input;
11
+ return Math.ceil(text.length / 4);
12
+ }
13
+
14
+ export enum Encoding {
15
+ O200kBase = "O200kBase",
16
+ Cl100kBase = "Cl100kBase",
17
+ }
18
+
19
+ // ---------------------------------------------------------------------------
20
+ // MacOSPowerAssertion — macOS-only, no-op on other platforms
21
+ // ---------------------------------------------------------------------------
22
+ export class MacOSPowerAssertion {
23
+ static start(_options?: MacOSPowerAssertionOptions | null): MacOSPowerAssertion {
24
+ return new MacOSPowerAssertion();
25
+ }
26
+ stop(): void {}
27
+ }
28
+
29
+ export interface MacOSPowerAssertionOptions {
30
+ reason?: string;
31
+ idle?: boolean;
32
+ system?: boolean;
33
+ user?: boolean;
34
+ display?: boolean;
35
+ }
36
+
37
+ // ---------------------------------------------------------------------------
38
+ // MacAppearanceObserver
39
+ // ---------------------------------------------------------------------------
40
+ export class MacAppearanceObserver {
41
+ static start(_callback: (err: null | Error, appearance: MacOSAppearance) => void): MacAppearanceObserver {
42
+ return new MacAppearanceObserver();
43
+ }
44
+ stop(): void {}
45
+ }
46
+
47
+ export enum MacOSAppearance {
48
+ Dark = "dark",
49
+ Light = "light",
50
+ }
51
+
52
+ export function detectMacOSAppearance(): MacOSAppearance | null {
53
+ return null;
54
+ }
55
+
56
+ // ---------------------------------------------------------------------------
57
+ // Process
58
+ // ---------------------------------------------------------------------------
59
+ export class Process {
60
+ static fromPid(_pid: number): Process | null { return null; }
61
+ static fromPath(_path: string): Process[] { return []; }
62
+ get pid(): number { return 0; }
63
+ get ppid(): number | null { return null; }
64
+ args(): string[] { return []; }
65
+ killTree(_signal?: number | null): number { return 0; }
66
+ terminate(_options?: ProcessTerminateOptions | null): Promise<boolean> { return Promise.resolve(false); }
67
+ waitForExit(_options?: ProcessWaitOptions | null): Promise<boolean> { return Promise.resolve(false); }
68
+ groupId(): number | null { return null; }
69
+ children(): Process[] { return []; }
70
+ status(): ProcessStatus { return ProcessStatus.Exited; }
71
+ }
72
+
73
+ export enum ProcessStatus {
74
+ Running = "running",
75
+ Exited = "exited",
76
+ }
77
+
78
+ export interface ProcessTerminateOptions {
79
+ group?: boolean;
80
+ gracefulMs?: number;
81
+ timeoutMs?: number;
82
+ signal?: unknown;
83
+ }
84
+
85
+ export interface ProcessWaitOptions {
86
+ timeoutMs?: number;
87
+ signal?: unknown;
88
+ }
89
+
90
+ // ---------------------------------------------------------------------------
91
+ // PtySession
92
+ // ---------------------------------------------------------------------------
93
+ export class PtySession {
94
+ constructor() {}
95
+ async start(_options: PtyStartOptions, _onChunk?: ((error: Error | null, chunk: string) => void) | null): Promise<PtyRunResult> {
96
+ return { exitCode: 0, cancelled: false, timedOut: false };
97
+ }
98
+ write(_data: string): void {}
99
+ resize(_cols: number, _rows: number): void {}
100
+ kill(): void {}
101
+ }
102
+
103
+ export interface PtyStartOptions {
104
+ command: string;
105
+ cwd?: string;
106
+ env?: Record<string, string>;
107
+ timeoutMs?: number;
108
+ signal?: unknown;
109
+ cols?: number;
110
+ rows?: number;
111
+ shell?: string;
112
+ }
113
+
114
+ export interface PtyRunResult {
115
+ exitCode?: number;
116
+ cancelled: boolean;
117
+ timedOut: boolean;
118
+ }
119
+
120
+ // ---------------------------------------------------------------------------
121
+ // Shell
122
+ // ---------------------------------------------------------------------------
123
+ export class Shell {
124
+ constructor(_options?: ShellOptions | null) {}
125
+ async run(_options: ShellRunOptions, _onChunk?: ((error: Error | null, chunk: string) => void) | null): Promise<ShellRunResult> {
126
+ return { exitCode: 0, cancelled: false, timedOut: false };
127
+ }
128
+ abort(): Promise<void> { return Promise.resolve(); }
129
+ }
130
+
131
+ export interface ShellOptions {
132
+ sessionEnv?: Record<string, string>;
133
+ snapshotPath?: string;
134
+ minimizer?: MinimizerOptions;
135
+ }
136
+
137
+ export interface ShellRunOptions {
138
+ command: string;
139
+ cwd?: string;
140
+ env?: Record<string, string>;
141
+ timeoutMs?: number;
142
+ signal?: unknown;
143
+ }
144
+
145
+ export interface ShellRunResult {
146
+ exitCode?: number;
147
+ cancelled: boolean;
148
+ timedOut: boolean;
149
+ }
150
+
151
+ // ---------------------------------------------------------------------------
152
+ // executeShell
153
+ // ---------------------------------------------------------------------------
154
+ export async function executeShell(
155
+ _options: ShellExecuteOptions,
156
+ _onChunk?: ((error: Error | null, chunk: string) => void) | null
157
+ ): Promise<ShellRunResult> {
158
+ return { exitCode: 0, cancelled: false, timedOut: false };
159
+ }
160
+
161
+ export interface ShellExecuteOptions {
162
+ command: string;
163
+ cwd?: string;
164
+ env?: Record<string, string>;
165
+ sessionEnv?: Record<string, string>;
166
+ timeoutMs?: number;
167
+ snapshotPath?: string;
168
+ minimizer?: MinimizerOptions;
169
+ signal?: unknown;
170
+ }
171
+
172
+ // ---------------------------------------------------------------------------
173
+ // __piNativesV sentinel
174
+ // ---------------------------------------------------------------------------
175
+ export function __piNativesV15_11_0(): void {}
176
+
177
+ // ---------------------------------------------------------------------------
178
+ // applyBashFixups
179
+ // ---------------------------------------------------------------------------
180
+ export interface BashFixupResult {
181
+ command: string;
182
+ stripped: string[];
183
+ }
184
+
185
+ export function applyBashFixups(command: string): BashFixupResult {
186
+ return { command, stripped: [] };
187
+ }
188
+
189
+ // ---------------------------------------------------------------------------
190
+ // astEdit / astGrep / astMatch
191
+ // ---------------------------------------------------------------------------
192
+ export interface AstFindMatch {
193
+ path: string;
194
+ text: string;
195
+ byteStart: number;
196
+ byteEnd: number;
197
+ startLine: number;
198
+ startColumn: number;
199
+ endLine: number;
200
+ endColumn: number;
201
+ metaVariables?: Record<string, string>;
202
+ }
203
+
204
+ export interface AstFindOptions {
205
+ patterns?: string[];
206
+ lang?: string;
207
+ path?: string;
208
+ glob?: string;
209
+ selector?: string;
210
+ strictness?: AstMatchStrictness;
211
+ limit?: number;
212
+ offset?: number;
213
+ includeMeta?: boolean;
214
+ context?: number;
215
+ signal?: unknown;
216
+ timeoutMs?: number;
217
+ }
218
+
219
+ export interface AstFindResult {
220
+ matches: AstFindMatch[];
221
+ totalMatches: number;
222
+ filesWithMatches: number;
223
+ filesSearched: number;
224
+ limitReached: boolean;
225
+ parseErrors?: string[];
226
+ }
227
+
228
+ export function astGrep(_options: AstFindOptions): Promise<AstFindResult> {
229
+ return Promise.resolve({ matches: [], totalMatches: 0, filesWithMatches: 0, filesSearched: 0, limitReached: false });
230
+ }
231
+
232
+ export interface AstMatchOptions {
233
+ source: string;
234
+ lang: string;
235
+ patterns: string[];
236
+ selector?: string;
237
+ strictness?: AstMatchStrictness;
238
+ limit?: number;
239
+ offset?: number;
240
+ includeMeta?: boolean;
241
+ signal?: unknown;
242
+ timeoutMs?: number;
243
+ }
244
+
245
+ export interface AstMatchResult {
246
+ matches: AstFindMatch[];
247
+ totalMatches: number;
248
+ limitReached: boolean;
249
+ parseErrors?: string[];
250
+ }
251
+
252
+ export function astMatch(_options: AstMatchOptions): Promise<AstMatchResult> {
253
+ return Promise.resolve({ matches: [], totalMatches: 0, limitReached: false });
254
+ }
255
+
256
+ export interface AstReplaceChange {
257
+ path: string;
258
+ before: string;
259
+ after: string;
260
+ byteStart: number;
261
+ byteEnd: number;
262
+ deletedLength: number;
263
+ startLine: number;
264
+ startColumn: number;
265
+ endLine: number;
266
+ endColumn: number;
267
+ }
268
+
269
+ export interface AstReplaceFileChange {
270
+ path: string;
271
+ count: number;
272
+ }
273
+
274
+ export interface AstReplaceOptions {
275
+ rewrites?: Record<string, string>;
276
+ lang?: string;
277
+ path?: string;
278
+ glob?: string;
279
+ selector?: string;
280
+ strictness?: AstMatchStrictness;
281
+ dryRun?: boolean;
282
+ maxReplacements?: number;
283
+ maxFiles?: number;
284
+ failOnParseError?: boolean;
285
+ signal?: unknown;
286
+ timeoutMs?: number;
287
+ }
288
+
289
+ export interface AstReplaceResult {
290
+ changes: AstReplaceChange[];
291
+ fileChanges: AstReplaceFileChange[];
292
+ totalReplacements: number;
293
+ filesTouched: number;
294
+ filesSearched: number;
295
+ applied: boolean;
296
+ limitReached: boolean;
297
+ parseErrors?: string[];
298
+ }
299
+
300
+ export function astEdit(_options: AstReplaceOptions): Promise<AstReplaceResult> {
301
+ return Promise.resolve({
302
+ changes: [],
303
+ fileChanges: [],
304
+ totalReplacements: 0,
305
+ filesTouched: 0,
306
+ filesSearched: 0,
307
+ applied: false,
308
+ limitReached: false,
309
+ });
310
+ }
311
+
312
+ export enum AstMatchStrictness {
313
+ Cst = "cst",
314
+ Smart = "smart",
315
+ Ast = "ast",
316
+ Relaxed = "relaxed",
317
+ Signature = "signature",
318
+ Template = "template",
319
+ }
320
+
321
+ // ---------------------------------------------------------------------------
322
+ // blockRangeAt
323
+ // ---------------------------------------------------------------------------
324
+ export interface BlockRange {
325
+ startLine: number;
326
+ endLine: number;
327
+ }
328
+
329
+ export interface BlockRangeOptions {
330
+ code: string;
331
+ lang?: string;
332
+ path?: string;
333
+ line: number;
334
+ }
335
+
336
+ export function blockRangeAt(_options: BlockRangeOptions): BlockRange | null { return null; }
337
+
338
+ // ---------------------------------------------------------------------------
339
+ // ClipboardImage
340
+ // ---------------------------------------------------------------------------
341
+ export interface ClipboardImage {
342
+ data: Uint8Array;
343
+ mimeType: string;
344
+ }
345
+
346
+ export function copyToClipboard(_text: string): void {}
347
+ export async function readImageFromClipboard(): Promise<ClipboardImage | undefined | null> { return null; }
348
+
349
+ // ---------------------------------------------------------------------------
350
+ // enclosingBlockBoundaries
351
+ // ---------------------------------------------------------------------------
352
+ export interface EnclosingBoundaryOptions {
353
+ code: string;
354
+ lang?: string;
355
+ path?: string;
356
+ ranges: LineRange[];
357
+ }
358
+
359
+ export function enclosingBlockBoundaries(_options: EnclosingBoundaryOptions): number[] | null { return null; }
360
+
361
+ // ---------------------------------------------------------------------------
362
+ // encodeSixel
363
+ // ---------------------------------------------------------------------------
364
+ export function encodeSixel(_bytes: Uint8Array, _targetWidthPx: number, _targetHeightPx: number): string { return ""; }
365
+
366
+ // ---------------------------------------------------------------------------
367
+ // extractSegments
368
+ // ---------------------------------------------------------------------------
369
+ export interface ExtractSegmentsResult_ {
370
+ before: string;
371
+ beforeWidth: number;
372
+ after: string;
373
+ afterWidth: number;
374
+ }
375
+
376
+ export function extractSegments(_line: string, _beforeEnd: number, _afterStart: number, _afterLen: number, _strictAfter: boolean, _tabWidth: number): ExtractSegmentsResult_ {
377
+ return { before: "", beforeWidth: 0, after: "", afterWidth: 0 };
378
+ }
379
+
380
+ // ---------------------------------------------------------------------------
381
+ // FileType
382
+ // ---------------------------------------------------------------------------
383
+ export enum FileType {
384
+ File = 1,
385
+ Dir = 2,
386
+ Symlink = 3,
387
+ }
388
+
389
+ // ---------------------------------------------------------------------------
390
+ // FuzzyFind
391
+ // ---------------------------------------------------------------------------
392
+ export interface FuzzyFindMatch {
393
+ path: string;
394
+ isDirectory: boolean;
395
+ score: number;
396
+ }
397
+
398
+ export interface FuzzyFindOptions {
399
+ query: string;
400
+ path: string;
401
+ hidden?: boolean;
402
+ gitignore?: boolean;
403
+ cache?: boolean;
404
+ maxResults?: number;
405
+ signal?: unknown;
406
+ timeoutMs?: number;
407
+ }
408
+
409
+ export interface FuzzyFindResult {
410
+ matches: FuzzyFindMatch[];
411
+ totalMatches: number;
412
+ }
413
+
414
+ export function fuzzyFind(_options: FuzzyFindOptions): Promise<FuzzyFindResult> {
415
+ return Promise.resolve({ matches: [], totalMatches: 0 });
416
+ }
417
+
418
+ // ---------------------------------------------------------------------------
419
+ // getSupportedLanguages
420
+ // ---------------------------------------------------------------------------
421
+ export function getSupportedLanguages(): string[] { return []; }
422
+
423
+ // ---------------------------------------------------------------------------
424
+ // getWorkProfile
425
+ // ---------------------------------------------------------------------------
426
+ export interface WorkProfile {
427
+ folded: string;
428
+ summary: string;
429
+ svg?: string;
430
+ totalMs: number;
431
+ sampleCount: number;
432
+ }
433
+
434
+ export function getWorkProfile(_lastSeconds: number): WorkProfile {
435
+ return { folded: "", summary: "", totalMs: 0, sampleCount: 0 };
436
+ }
437
+
438
+ // ---------------------------------------------------------------------------
439
+ // glob
440
+ // ---------------------------------------------------------------------------
441
+ export interface GlobMatch {
442
+ path: string;
443
+ fileType: FileType;
444
+ mtime?: number;
445
+ size?: number;
446
+ }
447
+
448
+ export interface GlobOptions {
449
+ pattern: string;
450
+ path: string;
451
+ fileType?: FileType;
452
+ recursive?: boolean;
453
+ hidden?: boolean;
454
+ maxResults?: number;
455
+ gitignore?: boolean;
456
+ cache?: boolean;
457
+ sortByMtime?: boolean;
458
+ includeNodeModules?: boolean;
459
+ signal?: unknown;
460
+ timeoutMs?: number;
461
+ }
462
+
463
+ export interface GlobResult {
464
+ matches: GlobMatch[];
465
+ totalMatches: number;
466
+ }
467
+
468
+ export function glob(_options: GlobOptions, _onMatch?: ((error: Error | null, match: GlobMatch) => void) | null): Promise<GlobResult> {
469
+ return Promise.resolve({ matches: [], totalMatches: 0 });
470
+ }
471
+
472
+ // ---------------------------------------------------------------------------
473
+ // grep
474
+ // ---------------------------------------------------------------------------
475
+ export interface GrepMatch {
476
+ path: string;
477
+ lineNumber: number;
478
+ line: string;
479
+ contextBefore?: ContextLine[];
480
+ contextAfter?: ContextLine[];
481
+ truncated?: boolean;
482
+ matchCount?: number;
483
+ }
484
+
485
+ export interface ContextLine {
486
+ lineNumber: number;
487
+ line: string;
488
+ }
489
+
490
+ export interface GrepOptions {
491
+ pattern: string;
492
+ path: string;
493
+ glob?: string;
494
+ type?: string;
495
+ ignoreCase?: boolean;
496
+ multiline?: boolean;
497
+ hidden?: boolean;
498
+ gitignore?: boolean;
499
+ cache?: boolean;
500
+ maxCount?: number;
501
+ offset?: number;
502
+ contextBefore?: number;
503
+ contextAfter?: number;
504
+ context?: number;
505
+ maxColumns?: number;
506
+ mode?: GrepOutputMode;
507
+ maxCountPerFile?: number;
508
+ signal?: unknown;
509
+ timeoutMs?: number;
510
+ }
511
+
512
+ export enum GrepOutputMode {
513
+ Content = "content",
514
+ Count = "count",
515
+ FilesWithMatches = "filesWithMatches",
516
+ }
517
+
518
+ export interface GrepResult {
519
+ matches: GrepMatch[];
520
+ totalMatches: number;
521
+ filesWithMatches: number;
522
+ filesSearched: number;
523
+ limitReached?: boolean;
524
+ skippedOversized?: number;
525
+ }
526
+
527
+ export function grep(_options: GrepOptions, _onMatch?: ((error: Error | null, match: GrepMatch) => void) | null): Promise<GrepResult> {
528
+ return Promise.resolve({ matches: [], totalMatches: 0, filesWithMatches: 0, filesSearched: 0 });
529
+ }
530
+
531
+ // ---------------------------------------------------------------------------
532
+ // hasMatch
533
+ // ---------------------------------------------------------------------------
534
+ export function hasMatch(_content: string | Uint8Array, _pattern: string | Uint8Array, _ignoreCase?: boolean | null, _multiline?: boolean | null): boolean { return false; }
535
+
536
+ // ---------------------------------------------------------------------------
537
+ // highlightCode
538
+ // ---------------------------------------------------------------------------
539
+ export interface HighlightColors {
540
+ comment: string;
541
+ keyword: string;
542
+ function: string;
543
+ variable: string;
544
+ string: string;
545
+ number: string;
546
+ type: string;
547
+ operator: string;
548
+ punctuation: string;
549
+ inserted?: string;
550
+ deleted?: string;
551
+ }
552
+
553
+ export function highlightCode(_code: string, _lang: string | null, _colors: HighlightColors): string { return _code; }
554
+
555
+ // ---------------------------------------------------------------------------
556
+ // htmlToMarkdown
557
+ // ---------------------------------------------------------------------------
558
+ export interface HtmlToMarkdownOptions {
559
+ cleanContent?: boolean;
560
+ skipImages?: boolean;
561
+ }
562
+
563
+ export function htmlToMarkdown(_html: string, _options?: HtmlToMarkdownOptions | null): Promise<string> { return Promise.resolve(""); }
564
+
565
+ // ---------------------------------------------------------------------------
566
+ // invalidateFsScanCache
567
+ // ---------------------------------------------------------------------------
568
+ export function invalidateFsScanCache(_path?: string | null): void {}
569
+
570
+ // ---------------------------------------------------------------------------
571
+ // iso* functions
572
+ // ---------------------------------------------------------------------------
573
+ export enum IsoBackendKind {
574
+ Apfs = 0,
575
+ Btrfs = 1,
576
+ Zfs = 2,
577
+ LinuxReflink = 3,
578
+ Overlayfs = 4,
579
+ WindowsBlockClone = 5,
580
+ Projfs = 6,
581
+ Rcopy = 7,
582
+ }
583
+
584
+ export enum IsoChangeKind {
585
+ Added = 0,
586
+ Modified = 1,
587
+ Removed = 2,
588
+ }
589
+
590
+ export interface IsoDiff {
591
+ files: IsoFileChange[];
592
+ }
593
+
594
+ export interface IsoFileChange {
595
+ path: string;
596
+ op: IsoChangeKind;
597
+ diff?: string;
598
+ }
599
+
600
+ export interface IsoProbeResult {
601
+ available: boolean;
602
+ reason?: string;
603
+ kind: IsoBackendKind;
604
+ }
605
+
606
+ export interface IsoResolveResult {
607
+ kind: IsoBackendKind;
608
+ candidates: IsoBackendKind[];
609
+ fellBack: boolean;
610
+ reason?: string;
611
+ }
612
+
613
+ export function isoBackend(): IsoBackendKind { return IsoBackendKind.Projfs; }
614
+ export function isoDiff(_lower: string, _merged: string): Promise<IsoDiff> { return Promise.resolve({ files: [] }); }
615
+ export function isoIsUnavailableError(_message: string): boolean { return false; }
616
+ export function isoProbe(_kind?: IsoBackendKind | null): IsoProbeResult { return { available: false, kind: IsoBackendKind.Projfs }; }
617
+ export function isoResolve(_preferred?: IsoBackendKind | null): IsoResolveResult { return { kind: IsoBackendKind.Projfs, candidates: [IsoBackendKind.Projfs], fellBack: false }; }
618
+ export function isoStart(_kind: IsoBackendKind | null, _lower: string, _merged: string): Promise<void> { return Promise.resolve(); }
619
+ export function isoStop(_kind: IsoBackendKind | null, _merged: string): Promise<void> { return Promise.resolve(); }
620
+
621
+ // ---------------------------------------------------------------------------
622
+ // LineRange
623
+ // ---------------------------------------------------------------------------
624
+ export interface LineRange {
625
+ startLine: number;
626
+ endLine: number;
627
+ }
628
+
629
+ // ---------------------------------------------------------------------------
630
+ // listWorkspace
631
+ // ---------------------------------------------------------------------------
632
+ export interface ListWorkspaceOptions {
633
+ path: string;
634
+ maxDepth: number;
635
+ hidden?: boolean;
636
+ gitignore?: boolean;
637
+ collectAgentsMd?: boolean;
638
+ timeoutMs?: number;
639
+ signal?: unknown;
640
+ }
641
+
642
+ export interface ListWorkspaceResult {
643
+ entries: GlobMatch[];
644
+ agentsMdFiles: string[];
645
+ truncated: boolean;
646
+ }
647
+
648
+ export function listWorkspace(_options: ListWorkspaceOptions): Promise<ListWorkspaceResult> {
649
+ return Promise.resolve({ entries: [], agentsMdFiles: [], truncated: false });
650
+ }
651
+
652
+ // ---------------------------------------------------------------------------
653
+ // Match
654
+ // ---------------------------------------------------------------------------
655
+ export interface Match {
656
+ lineNumber: number;
657
+ line: string;
658
+ contextBefore?: ContextLine[];
659
+ contextAfter?: ContextLine[];
660
+ truncated?: boolean;
661
+ }
662
+
663
+ // ---------------------------------------------------------------------------
664
+ // matchesKey
665
+ // ---------------------------------------------------------------------------
666
+ export function matchesKey(_data: string, _keyId: string, _kittyProtocolActive: boolean): boolean { return false; }
667
+ export function matchesKittySequence(_data: string, _expectedCodepoint: number, _expectedModifier: number): boolean { return false; }
668
+ export function matchesLegacySequence(_data: string, _keyName: string): boolean { return false; }
669
+
670
+ // ---------------------------------------------------------------------------
671
+ // MinimizerOptions / MinimizerResult
672
+ // ---------------------------------------------------------------------------
673
+ export interface MinimizerOptions {
674
+ enabled?: boolean;
675
+ settingsPath?: string;
676
+ settingsHash?: string;
677
+ only?: string[];
678
+ except?: string[];
679
+ maxCaptureBytes?: number;
680
+ sourceOutlineLevel?: string;
681
+ legacyFilters?: boolean;
682
+ }
683
+
684
+ export interface MinimizerResult {
685
+ filter: string;
686
+ text: string;
687
+ originalText: string;
688
+ inputBytes: number;
689
+ outputBytes: number;
690
+ }
691
+
692
+ // ---------------------------------------------------------------------------
693
+ // parseKey / parseKittySequence
694
+ // ---------------------------------------------------------------------------
695
+ export interface ParsedKittyResult {
696
+ codepoint: number;
697
+ shiftedKey?: number;
698
+ baseLayoutKey?: number;
699
+ modifier: number;
700
+ eventType?: number;
701
+ }
702
+
703
+ export function parseKey(_data: string, _kittyProtocolActive: boolean): string | null { return null; }
704
+ export function parseKittySequence(_data: string): ParsedKittyResult | null { return null; }
705
+
706
+ // ---------------------------------------------------------------------------
707
+ // readImageFromClipboard — already defined above
708
+
709
+ // ---------------------------------------------------------------------------
710
+ // renderSnapcompactPng
711
+ // ---------------------------------------------------------------------------
712
+ export interface SnapcompactRenderOptions {
713
+ size: number;
714
+ font?: string;
715
+ cellWidth?: number;
716
+ cellHeight?: number;
717
+ variant?: string;
718
+ lineRepeat?: number;
719
+ }
720
+
721
+ export function renderSnapcompactPng(_text: string, _options: SnapcompactRenderOptions): string { return ""; }
722
+
723
+ // ---------------------------------------------------------------------------
724
+ // search
725
+ // ---------------------------------------------------------------------------
726
+ export interface SearchOptions {
727
+ pattern: string;
728
+ ignoreCase?: boolean;
729
+ multiline?: boolean;
730
+ maxCount?: number;
731
+ offset?: number;
732
+ contextBefore?: number;
733
+ contextAfter?: number;
734
+ context?: number;
735
+ maxColumns?: number;
736
+ mode?: GrepOutputMode;
737
+ }
738
+
739
+ export interface SearchResult {
740
+ matches: Match[];
741
+ matchCount: number;
742
+ limitReached: boolean;
743
+ error?: string;
744
+ }
745
+
746
+ export function search(_content: string | Uint8Array, _options: SearchOptions): SearchResult {
747
+ return { matches: [], matchCount: 0, limitReached: false };
748
+ }
749
+
750
+ // ---------------------------------------------------------------------------
751
+ // sliceWithWidth
752
+ // ---------------------------------------------------------------------------
753
+ export interface SliceResult {
754
+ text: string;
755
+ width: number;
756
+ }
757
+
758
+ export function sliceWithWidth(_line: string, _startCol: number, _length: number, _strict: boolean | null | undefined, _tabWidth: number): SliceResult {
759
+ return { text: "", width: 0 };
760
+ }
761
+
762
+ // ---------------------------------------------------------------------------
763
+ // summarizeCode
764
+ // ---------------------------------------------------------------------------
765
+ export interface SummaryOptions {
766
+ code: string;
767
+ lang?: string;
768
+ path?: string;
769
+ minBodyLines?: number;
770
+ minCommentLines?: number;
771
+ unfoldUntilLines?: number;
772
+ unfoldLimitLines?: number;
773
+ }
774
+
775
+ export interface SummaryResult {
776
+ language?: string;
777
+ parsed: boolean;
778
+ elided: boolean;
779
+ totalLines: number;
780
+ segments: SummarySegment[];
781
+ }
782
+
783
+ export interface SummarySegment {
784
+ kind: string;
785
+ startLine: number;
786
+ endLine: number;
787
+ text?: string;
788
+ }
789
+
790
+ export function summarizeCode(_options: SummaryOptions): SummaryResult {
791
+ return { parsed: false, elided: false, totalLines: 0, segments: [] };
792
+ }
793
+
794
+ // ---------------------------------------------------------------------------
795
+ // supportsLanguage
796
+ // ---------------------------------------------------------------------------
797
+ export function supportsLanguage(_lang: string): boolean { return false; }
798
+
799
+ // ---------------------------------------------------------------------------
800
+ // truncateToWidth
801
+ // ---------------------------------------------------------------------------
802
+ export function truncateToWidth(_text: string, _maxWidth: number, _ellipsisKind: Ellipsis | null | undefined, _pad: boolean | null | undefined, _tabWidth: number): string {
803
+ return _text;
804
+ }
805
+
806
+ // ---------------------------------------------------------------------------
807
+ // visibleWidth
808
+ // ---------------------------------------------------------------------------
809
+ export function visibleWidth(_text: string, _tabWidth: number): number { return _text.length; }
810
+
811
+ // ---------------------------------------------------------------------------
812
+ // wrapTextWithAnsi
813
+ // ---------------------------------------------------------------------------
814
+ export function wrapTextWithAnsi(_text: string, _width: number, _tabWidth: number): string[] { return [_text]; }
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "@oh-my-pi/pi-natives",
3
+ "version": "0.0.0",
4
+ "type": "module",
5
+ "main": "./index.ts",
6
+ "types": "./index.ts"
7
+ }
@@ -0,0 +1,282 @@
1
+ // Stub for @oh-my-pi/pi-tui — provides minimal UI primitives for pi-coding-agent
2
+ // used in Vividra's SDK context. Real TUI rendering is not needed.
3
+
4
+ export type AutocompleteItem = { label: string; detail?: string; kind?: string };
5
+
6
+ export interface BoxSymbols {
7
+ topLeft: string;
8
+ topRight: string;
9
+ bottomLeft: string;
10
+ bottomRight: string;
11
+ horizontal: string;
12
+ vertical: string;
13
+ teeDown: string;
14
+ teeUp: string;
15
+ teeLeft: string;
16
+ teeRight: string;
17
+ cross: string;
18
+ }
19
+
20
+ export interface SymbolTheme {
21
+ cursor: string;
22
+ inputCursor: string;
23
+ boxRound: Omit<BoxSymbols, "teeDown" | "teeUp" | "teeLeft" | "teeRight" | "cross">;
24
+ boxSharp: BoxSymbols;
25
+ table: BoxSymbols;
26
+ quoteBorder: string;
27
+ hrChar: string;
28
+ colorSwatch?: string;
29
+ spinnerFrames: string[];
30
+ }
31
+
32
+ export type KeyId = string;
33
+ export type Keybinding = string;
34
+
35
+ export interface KeybindingDefinition {
36
+ modes?: string[];
37
+ key?: string;
38
+ preventDefault?: boolean;
39
+ }
40
+
41
+ export type KeybindingsConfig = Record<string, KeyId | KeyId[] | undefined>;
42
+
43
+ export class KeybindingsManager {
44
+ constructor() {}
45
+ get(key: string): KeybindingDefinition | undefined { return undefined; }
46
+ all(): Record<string, KeybindingDefinition> { return {}; }
47
+ }
48
+
49
+ export function canonicalKeyId(key: string): string { return key; }
50
+ export function addKeyAliases(_keys: Set<string>, _key: KeyId): void {}
51
+ export function parseKey(_data: string, _kittyProtocolActive: boolean): string | null { return null; }
52
+ export function parseKittySequence(_data: string): ParsedKittyResult | null { return null; }
53
+ export function getKeybindings(): KeybindingsManager { return new KeybindingsManager(); }
54
+ export function setKeybindings(_manager: KeybindingsManager): void {}
55
+
56
+ export interface ParsedKittyResult {
57
+ codepoint: number;
58
+ shiftedKey?: number;
59
+ baseLayoutKey?: number;
60
+ modifier: number;
61
+ eventType?: KeyEventType;
62
+ }
63
+
64
+ export enum KeyEventType {
65
+ Press = 1,
66
+ Repeat = 2,
67
+ Release = 3,
68
+ }
69
+
70
+ export function matchesKey(_data: string, _keyId: string, _kittyProtocolActive: boolean): boolean { return false; }
71
+ export function matchesKittySequence(_data: string, _expectedCodepoint: number, _expectedModifier: number): boolean { return false; }
72
+ export function matchesLegacySequence(_data: string, _keyName: string): boolean { return false; }
73
+
74
+ export interface FuzzyMatch {
75
+ matches: boolean;
76
+ score: number;
77
+ }
78
+
79
+ export function fuzzyMatch(query: string, text: string): FuzzyMatch {
80
+ const ql = query.toLowerCase();
81
+ const tl = text.toLowerCase();
82
+ let qi = 0;
83
+ let score = 0;
84
+ let last = -1;
85
+ for (let i = 0; i < tl.length && qi < ql.length; i++) {
86
+ if (tl[i] === ql[qi]) {
87
+ if (last >= 0) score += (i - last - 1) * 2;
88
+ if (i === 0 || /[\s\-_./:]/.test(tl[i - 1]!)) score -= 10;
89
+ last = i;
90
+ qi++;
91
+ }
92
+ }
93
+ return { matches: qi === ql.length, score };
94
+ }
95
+
96
+ export function fuzzyFilter<T>(items: T[], query: string, getText: (item: T) => string): T[] {
97
+ if (!query.trim()) return items;
98
+ const tokens = query.trim().split(/\s+/).filter(t => t.length > 0);
99
+ const results: { item: T; totalScore: number }[] = [];
100
+ for (const item of items) {
101
+ const text = getText(item);
102
+ let totalScore = 0;
103
+ let allMatch = true;
104
+ for (const token of tokens) {
105
+ const match = fuzzyMatch(token, text);
106
+ if (match.matches) totalScore += match.score;
107
+ else { allMatch = false; break; }
108
+ }
109
+ if (allMatch) results.push({ item, totalScore });
110
+ }
111
+ results.sort((a, b) => a.totalScore - b.totalScore);
112
+ return results.map(r => r.item);
113
+ }
114
+
115
+ export function padding(n: number): string { return " ".repeat(n); }
116
+
117
+ export function replaceTabs(text: string, _file?: string): string { return text.replace(/\t/g, " "); }
118
+
119
+ export function sliceWithWidth(line: string, startCol: number, length: number, _strict?: boolean | null): SliceResult {
120
+ const text = line.slice(startCol, startCol + length);
121
+ return { text, width: text.length };
122
+ }
123
+
124
+ export function truncateToWidth(text: string, maxWidth: number, _ellipsisKind?: unknown | null, _pad?: boolean | null, _tabWidth?: number): string {
125
+ if (text.length <= maxWidth) return text;
126
+ return text.slice(0, Math.max(0, maxWidth - 1)) + "…";
127
+ }
128
+
129
+ export function visibleWidth(str: string, _tabWidth?: number): number {
130
+ return str.replace(/\x1b\[[0-9;]*m/g, "").length;
131
+ }
132
+
133
+ export function wrapTextWithAnsi(text: string, width: number, _tabWidth?: number): string[] {
134
+ const lines: string[] = [];
135
+ let start = 0;
136
+ while (start < text.length) {
137
+ lines.push(text.slice(start, start + width));
138
+ start += width;
139
+ }
140
+ return lines.length ? lines : [""];
141
+ }
142
+
143
+ export interface SliceResult {
144
+ text: string;
145
+ width: number;
146
+ }
147
+
148
+ export enum Ellipsis {
149
+ Unicode = 0,
150
+ Ascii = 1,
151
+ Omit = 2,
152
+ }
153
+
154
+ export interface ExtractSegmentsResult {
155
+ before: string;
156
+ beforeWidth: number;
157
+ after: string;
158
+ afterWidth: number;
159
+ }
160
+
161
+ export function extractSegments(_line: string, _beforeEnd: number, _afterStart: number, _afterLen: number, _strictAfter: boolean, _tabWidth: number): ExtractSegmentsResult {
162
+ return { before: "", beforeWidth: 0, after: "", afterWidth: 0 };
163
+ }
164
+
165
+ export type TextSizingScale = 1 | 2 | 3;
166
+ export type TextSizingVerticalAlign = "top" | "bottom" | "center";
167
+ export type TextSizingHorizontalAlign = "left" | "right" | "center";
168
+
169
+ export interface TextSizingOptions {
170
+ scale?: TextSizingScale;
171
+ widthCells?: number;
172
+ verticalAlign?: TextSizingVerticalAlign;
173
+ horizontalAlign?: TextSizingHorizontalAlign;
174
+ }
175
+
176
+ export function encodeTextSized(text: string, _options?: TextSizingOptions): string { return text; }
177
+
178
+ // ---------------------------------------------------------------------------
179
+ // Component types and stubs
180
+ // ---------------------------------------------------------------------------
181
+
182
+ export type Component = unknown;
183
+
184
+ export type TUI = unknown;
185
+
186
+ export type EditorTheme = unknown;
187
+ export type MarkdownTheme = unknown;
188
+ export type SelectListTheme = unknown;
189
+ export type SymbolTheme_Alias = unknown;
190
+
191
+ // Terminal ID — critical for session-manager.ts:876,898
192
+ export function getTerminalId(): string { return process.env.TERM_SESSION_ID ?? process.env.TMUX_PANE ?? "stub-terminal"; }
193
+ export const TERMINAL = { id: getTerminalId() };
194
+
195
+ // ---------------------------------------------------------------------------
196
+ // Box component
197
+ // ---------------------------------------------------------------------------
198
+ export function Box(_props: { children?: unknown; width?: number; height?: number } & Record<string, unknown>): unknown { return null; }
199
+
200
+ // ---------------------------------------------------------------------------
201
+ // CancellableLoader / Loader
202
+ // ---------------------------------------------------------------------------
203
+ export type Loader = unknown;
204
+ export function CancellableLoader(_props: { title?: string } & Record<string, unknown>): unknown { return null; }
205
+
206
+ // ---------------------------------------------------------------------------
207
+ // Container
208
+ // ---------------------------------------------------------------------------
209
+ export function Container(_props: { children?: unknown; direction?: string; gap?: number } & Record<string, unknown>): unknown { return null; }
210
+
211
+ // ---------------------------------------------------------------------------
212
+ // Editor
213
+ // ---------------------------------------------------------------------------
214
+ export interface EditorProps {
215
+ onKeystroke?: (key: string) => void;
216
+ onFocus?: () => void;
217
+ onBlur?: () => void;
218
+ text?: string;
219
+ placeholder?: string;
220
+ readonly?: boolean;
221
+ language?: string;
222
+ }
223
+
224
+ export const Editor = (_props: EditorProps): unknown => null;
225
+
226
+ // ---------------------------------------------------------------------------
227
+ // Image
228
+ // ---------------------------------------------------------------------------
229
+ export type ImageBudget = unknown;
230
+ export type ImageProtocol = unknown;
231
+ export const Image = (_props: { src?: string; alt?: string; budget?: ImageBudget; protocol?: ImageProtocol; width?: number; height?: number } & Record<string, unknown>): unknown => null;
232
+
233
+ // ---------------------------------------------------------------------------
234
+ // Input
235
+ // ---------------------------------------------------------------------------
236
+ export const Input = (_props: { value?: string; placeholder?: string; onInput?: (text: string) => void; readonly?: boolean; password?: boolean } & Record<string, unknown>): unknown => null;
237
+
238
+ // ---------------------------------------------------------------------------
239
+ // Markdown
240
+ // ---------------------------------------------------------------------------
241
+ export function Markdown(_props: { content?: string; theme?: MarkdownTheme } & Record<string, unknown>): unknown { return _props.content ?? ""; }
242
+
243
+ // ---------------------------------------------------------------------------
244
+ // ScrollView
245
+ // ---------------------------------------------------------------------------
246
+ export function ScrollView(_props: { children?: unknown; offset?: number } & Record<string, unknown>): unknown { return null; }
247
+
248
+ // ---------------------------------------------------------------------------
249
+ // SelectList / SelectItem
250
+ // ---------------------------------------------------------------------------
251
+ export type SelectItem = { label: string; value?: string; detail?: string };
252
+ export function SelectList(_props: { items?: SelectItem[]; selected?: number; onSelect?: (index: number) => void; theme?: SelectListTheme } & Record<string, unknown>): unknown { return null; }
253
+
254
+ // ---------------------------------------------------------------------------
255
+ // SettingsList
256
+ // ---------------------------------------------------------------------------
257
+ export function SettingsList(_props: { children?: unknown } & Record<string, unknown>): unknown { return null; }
258
+
259
+ // ---------------------------------------------------------------------------
260
+ // Spacer
261
+ // ---------------------------------------------------------------------------
262
+ export function Spacer(_props?: Record<string, unknown>): unknown { return null; }
263
+
264
+ // ---------------------------------------------------------------------------
265
+ // TabBar
266
+ // ---------------------------------------------------------------------------
267
+ export function TabBar(_props: { tabs?: string[]; selected?: number; onSelect?: (index: number) => void } & Record<string, unknown>): unknown { return null; }
268
+
269
+ // ---------------------------------------------------------------------------
270
+ // Text
271
+ // ---------------------------------------------------------------------------
272
+ export function Text(_props: { children?: string; color?: string; bold?: boolean; dim?: boolean; italic?: boolean; underline?: boolean; strikethrough?: boolean;ansi?: string; } & Record<string, unknown>): unknown { return _props.children ?? ""; }
273
+
274
+ // ---------------------------------------------------------------------------
275
+ // TruncatedText
276
+ // ---------------------------------------------------------------------------
277
+ export function TruncatedText(_props: { text?: string; maxWidth?: number; ellipsis?: string } & Record<string, unknown>): unknown { return _props.text ?? ""; }
278
+
279
+ // ---------------------------------------------------------------------------
280
+ // Editor component interface
281
+ // ---------------------------------------------------------------------------
282
+ export type EditorComponent = unknown;
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "@oh-my-pi/pi-tui",
3
+ "version": "0.0.0",
4
+ "type": "module",
5
+ "main": "./index.ts",
6
+ "types": "./index.ts"
7
+ }