pi-ui-extend 0.1.8 → 0.1.9

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.
Files changed (166) hide show
  1. package/README.md +34 -0
  2. package/bin/pix.mjs +4 -4
  3. package/dist/app/app.js +38 -38
  4. package/dist/app/{cli.d.ts → cli/cli.d.ts} +1 -1
  5. package/dist/app/{cli.js → cli/cli.js} +1 -1
  6. package/dist/app/{install.js → cli/install.js} +2 -2
  7. package/dist/app/{command-controller.d.ts → commands/command-controller.d.ts} +1 -1
  8. package/dist/app/{command-host.d.ts → commands/command-host.d.ts} +3 -3
  9. package/dist/app/{command-model-actions.d.ts → commands/command-model-actions.d.ts} +1 -1
  10. package/dist/app/{command-model-actions.js → commands/command-model-actions.js} +2 -2
  11. package/dist/app/{command-navigation-actions.d.ts → commands/command-navigation-actions.d.ts} +1 -1
  12. package/dist/app/{command-navigation-actions.js → commands/command-navigation-actions.js} +5 -5
  13. package/dist/app/{command-registry.d.ts → commands/command-registry.d.ts} +1 -1
  14. package/dist/app/{command-runtime.js → commands/command-runtime.js} +1 -1
  15. package/dist/app/{command-session-actions.js → commands/command-session-actions.js} +3 -3
  16. package/dist/app/{shell-controller.d.ts → commands/shell-controller.d.ts} +1 -1
  17. package/dist/app/{shell-controller.js → commands/shell-controller.js} +1 -1
  18. package/dist/app/{slash-commands.d.ts → commands/slash-commands.d.ts} +2 -2
  19. package/dist/app/{slash-commands.js → commands/slash-commands.js} +1 -1
  20. package/dist/app/{extension-actions-controller.d.ts → extensions/extension-actions-controller.d.ts} +1 -1
  21. package/dist/app/{extension-actions-controller.js → extensions/extension-actions-controller.js} +1 -1
  22. package/dist/app/{extension-ui-controller.d.ts → extensions/extension-ui-controller.d.ts} +3 -3
  23. package/dist/app/{extension-ui-controller.js → extensions/extension-ui-controller.js} +3 -3
  24. package/dist/app/{input-action-controller.d.ts → input/input-action-controller.d.ts} +7 -7
  25. package/dist/app/{input-action-controller.js → input/input-action-controller.js} +3 -3
  26. package/dist/app/{input-controller.d.ts → input/input-controller.d.ts} +3 -3
  27. package/dist/app/{input-controller.js → input/input-controller.js} +1 -1
  28. package/dist/app/{input-paste-handler.d.ts → input/input-paste-handler.d.ts} +1 -1
  29. package/dist/app/{input-paste-handler.js → input/input-paste-handler.js} +3 -3
  30. package/dist/app/{native-modifiers.js → input/native-modifiers.js} +2 -2
  31. package/dist/app/{prompt-enhancer-controller.d.ts → input/prompt-enhancer-controller.d.ts} +5 -5
  32. package/dist/app/{prompt-enhancer-controller.js → input/prompt-enhancer-controller.js} +3 -3
  33. package/dist/app/{voice-controller.d.ts → input/voice-controller.d.ts} +1 -1
  34. package/dist/app/{voice-controller.js → input/voice-controller.js} +2 -2
  35. package/dist/app/{model-ref.d.ts → model/model-ref.d.ts} +1 -1
  36. package/dist/app/{model-ref.js → model/model-ref.js} +1 -1
  37. package/dist/app/{model-usage-controller.js → model/model-usage-controller.js} +1 -1
  38. package/dist/app/{model-usage-status.d.ts → model/model-usage-status.d.ts} +1 -1
  39. package/dist/app/{model-usage-status.js → model/model-usage-status.js} +1 -1
  40. package/dist/app/{menu-items-controller.d.ts → popup/menu-items-controller.d.ts} +4 -4
  41. package/dist/app/{menu-items-controller.js → popup/menu-items-controller.js} +5 -5
  42. package/dist/app/{popup-action-controller.d.ts → popup/popup-action-controller.d.ts} +4 -4
  43. package/dist/app/{popup-action-controller.js → popup/popup-action-controller.js} +2 -2
  44. package/dist/app/{popup-menu-controller.d.ts → popup/popup-menu-controller.d.ts} +4 -4
  45. package/dist/app/{popup-menu-controller.js → popup/popup-menu-controller.js} +7 -7
  46. package/dist/app/{conversation-entry-renderer.d.ts → rendering/conversation-entry-renderer.d.ts} +3 -3
  47. package/dist/app/{conversation-entry-renderer.js → rendering/conversation-entry-renderer.js} +3 -3
  48. package/dist/app/{conversation-shell-renderer.d.ts → rendering/conversation-shell-renderer.d.ts} +1 -1
  49. package/dist/app/{conversation-shell-renderer.js → rendering/conversation-shell-renderer.js} +1 -1
  50. package/dist/app/{conversation-tool-renderer.d.ts → rendering/conversation-tool-renderer.d.ts} +3 -3
  51. package/dist/app/{conversation-tool-renderer.js → rendering/conversation-tool-renderer.js} +7 -7
  52. package/dist/app/{conversation-viewport.d.ts → rendering/conversation-viewport.d.ts} +3 -3
  53. package/dist/app/{dcp-stats.js → rendering/dcp-stats.js} +1 -1
  54. package/dist/app/{editor-layout-renderer.d.ts → rendering/editor-layout-renderer.d.ts} +3 -3
  55. package/dist/app/{editor-layout-renderer.js → rendering/editor-layout-renderer.js} +2 -2
  56. package/dist/app/{editor-panels.d.ts → rendering/editor-panels.d.ts} +2 -2
  57. package/dist/app/{editor-panels.js → rendering/editor-panels.js} +4 -4
  58. package/dist/app/{message-content.d.ts → rendering/message-content.d.ts} +1 -1
  59. package/dist/app/{message-content.js → rendering/message-content.js} +1 -1
  60. package/dist/app/{render-controller.d.ts → rendering/render-controller.d.ts} +6 -6
  61. package/dist/app/{render-controller.js → rendering/render-controller.js} +5 -5
  62. package/dist/app/{render-text.d.ts → rendering/render-text.d.ts} +2 -2
  63. package/dist/app/{render-text.js → rendering/render-text.js} +3 -3
  64. package/dist/app/{status-line-renderer.d.ts → rendering/status-line-renderer.d.ts} +4 -4
  65. package/dist/app/{status-line-renderer.js → rendering/status-line-renderer.js} +4 -4
  66. package/dist/app/{tab-line-renderer.d.ts → rendering/tab-line-renderer.d.ts} +3 -3
  67. package/dist/app/{tab-line-renderer.js → rendering/tab-line-renderer.js} +2 -2
  68. package/dist/app/{toast-controller.d.ts → rendering/toast-controller.d.ts} +1 -1
  69. package/dist/app/{toast-controller.js → rendering/toast-controller.js} +2 -2
  70. package/dist/app/{toast-renderer.d.ts → rendering/toast-renderer.d.ts} +3 -3
  71. package/dist/app/{toast-renderer.js → rendering/toast-renderer.js} +3 -3
  72. package/dist/app/{tool-block-renderer.d.ts → rendering/tool-block-renderer.d.ts} +5 -5
  73. package/dist/app/{tool-block-renderer.js → rendering/tool-block-renderer.js} +2 -2
  74. package/dist/app/runtime.js +1 -1
  75. package/dist/app/{blink-controller.js → screen/blink-controller.js} +1 -1
  76. package/dist/app/{image-click-targets.d.ts → screen/image-click-targets.d.ts} +2 -2
  77. package/dist/app/{image-opener.d.ts → screen/image-opener.d.ts} +1 -1
  78. package/dist/app/{mouse-controller.d.ts → screen/mouse-controller.d.ts} +13 -9
  79. package/dist/app/{mouse-controller.js → screen/mouse-controller.js} +56 -28
  80. package/dist/app/{screen-selection.d.ts → screen/screen-selection.d.ts} +1 -1
  81. package/dist/app/{screen-styler.d.ts → screen/screen-styler.d.ts} +2 -2
  82. package/dist/app/{screen-styler.js → screen/screen-styler.js} +4 -4
  83. package/dist/app/{scroll-controller.d.ts → screen/scroll-controller.d.ts} +3 -3
  84. package/dist/app/{scroll-controller.js → screen/scroll-controller.js} +1 -1
  85. package/dist/app/{status-controller.d.ts → screen/status-controller.d.ts} +2 -2
  86. package/dist/app/{status-controller.js → screen/status-controller.js} +1 -1
  87. package/dist/app/{queued-message-controller.d.ts → session/queued-message-controller.d.ts} +2 -2
  88. package/dist/app/{queued-message-controller.js → session/queued-message-controller.js} +2 -2
  89. package/dist/app/{request-history.js → session/request-history.js} +2 -2
  90. package/dist/app/{session-event-controller.d.ts → session/session-event-controller.d.ts} +3 -3
  91. package/dist/app/{session-event-controller.js → session/session-event-controller.js} +3 -3
  92. package/dist/app/{session-history.d.ts → session/session-history.d.ts} +1 -1
  93. package/dist/app/{session-history.js → session/session-history.js} +3 -3
  94. package/dist/app/{session-lifecycle-controller.d.ts → session/session-lifecycle-controller.d.ts} +2 -2
  95. package/dist/app/{session-lifecycle-controller.js → session/session-lifecycle-controller.js} +4 -4
  96. package/dist/app/{session-search.d.ts → session/session-search.d.ts} +1 -1
  97. package/dist/app/{session-search.js → session/session-search.js} +3 -3
  98. package/dist/app/{tabs-controller.d.ts → session/tabs-controller.d.ts} +2 -2
  99. package/dist/app/{tabs-controller.js → session/tabs-controller.js} +4 -4
  100. package/dist/app/{subagents-files.d.ts → subagents/subagents-files.d.ts} +1 -1
  101. package/dist/app/{subagents-files.js → subagents/subagents-files.js} +1 -1
  102. package/dist/app/{subagents-model.d.ts → subagents/subagents-model.d.ts} +1 -1
  103. package/dist/app/{subagents-model.js → subagents/subagents-model.js} +4 -4
  104. package/dist/app/{subagents-widget-controller.d.ts → subagents/subagents-widget-controller.d.ts} +1 -1
  105. package/dist/app/{subagents-widget-controller.js → subagents/subagents-widget-controller.js} +2 -2
  106. package/dist/app/{terminal-bell-sound-controller.js → terminal/terminal-bell-sound-controller.js} +1 -1
  107. package/dist/app/{terminal-controller.js → terminal/terminal-controller.js} +2 -2
  108. package/dist/app/{todo-model.d.ts → todo/todo-model.d.ts} +1 -1
  109. package/dist/app/{todo-model.js → todo/todo-model.js} +3 -3
  110. package/dist/app/{todo-widget-controller.d.ts → todo/todo-widget-controller.d.ts} +1 -1
  111. package/dist/app/{todo-widget-controller.js → todo/todo-widget-controller.js} +2 -2
  112. package/dist/app/types.d.ts +2 -2
  113. package/dist/app/{workspace-actions-controller.d.ts → workspace/workspace-actions-controller.d.ts} +1 -1
  114. package/dist/app/{workspace-actions-controller.js → workspace/workspace-actions-controller.js} +3 -3
  115. package/dist/main.js +2 -2
  116. package/external/pi-tools-suite/README.md +78 -0
  117. package/external/pi-tools-suite/src/async-subagents/core/agent-strategy.ts +4 -0
  118. package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +6 -1
  119. package/external/pi-tools-suite/src/dcp/prompts.ts +4 -0
  120. package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +271 -0
  121. package/external/pi-tools-suite/src/index.ts +1 -0
  122. package/external/pi-tools-suite/src/opencode-import/commands.ts +86 -0
  123. package/external/pi-tools-suite/src/opencode-import/importer.ts +208 -0
  124. package/external/pi-tools-suite/src/opencode-import/index.ts +25 -0
  125. package/package.json +1 -1
  126. /package/dist/app/{install.d.ts → cli/install.d.ts} +0 -0
  127. /package/dist/app/{startup-checks.d.ts → cli/startup-checks.d.ts} +0 -0
  128. /package/dist/app/{startup-checks.js → cli/startup-checks.js} +0 -0
  129. /package/dist/app/{startup-info.d.ts → cli/startup-info.d.ts} +0 -0
  130. /package/dist/app/{startup-info.js → cli/startup-info.js} +0 -0
  131. /package/dist/app/{update.d.ts → cli/update.d.ts} +0 -0
  132. /package/dist/app/{update.js → cli/update.js} +0 -0
  133. /package/dist/app/{command-controller.js → commands/command-controller.js} +0 -0
  134. /package/dist/app/{command-host.js → commands/command-host.js} +0 -0
  135. /package/dist/app/{command-registry.js → commands/command-registry.js} +0 -0
  136. /package/dist/app/{command-runtime.d.ts → commands/command-runtime.d.ts} +0 -0
  137. /package/dist/app/{command-session-actions.d.ts → commands/command-session-actions.d.ts} +0 -0
  138. /package/dist/app/{shell-command.d.ts → commands/shell-command.d.ts} +0 -0
  139. /package/dist/app/{shell-command.js → commands/shell-command.js} +0 -0
  140. /package/dist/app/{extension-event-bus.d.ts → extensions/extension-event-bus.d.ts} +0 -0
  141. /package/dist/app/{extension-event-bus.js → extensions/extension-event-bus.js} +0 -0
  142. /package/dist/app/{native-modifiers.d.ts → input/native-modifiers.d.ts} +0 -0
  143. /package/dist/app/{terminal-edit-shortcuts.d.ts → input/terminal-edit-shortcuts.d.ts} +0 -0
  144. /package/dist/app/{terminal-edit-shortcuts.js → input/terminal-edit-shortcuts.js} +0 -0
  145. /package/dist/app/{model-usage-controller.d.ts → model/model-usage-controller.d.ts} +0 -0
  146. /package/dist/app/{conversation-viewport.js → rendering/conversation-viewport.js} +0 -0
  147. /package/dist/app/{dcp-stats.d.ts → rendering/dcp-stats.d.ts} +0 -0
  148. /package/dist/app/{blink-controller.d.ts → screen/blink-controller.d.ts} +0 -0
  149. /package/dist/app/{clipboard.d.ts → screen/clipboard.d.ts} +0 -0
  150. /package/dist/app/{clipboard.js → screen/clipboard.js} +0 -0
  151. /package/dist/app/{file-link-opener.d.ts → screen/file-link-opener.d.ts} +0 -0
  152. /package/dist/app/{file-link-opener.js → screen/file-link-opener.js} +0 -0
  153. /package/dist/app/{file-links.d.ts → screen/file-links.d.ts} +0 -0
  154. /package/dist/app/{file-links.js → screen/file-links.js} +0 -0
  155. /package/dist/app/{image-click-targets.js → screen/image-click-targets.js} +0 -0
  156. /package/dist/app/{image-opener.js → screen/image-opener.js} +0 -0
  157. /package/dist/app/{screen-selection.js → screen/screen-selection.js} +0 -0
  158. /package/dist/app/{request-history.d.ts → session/request-history.d.ts} +0 -0
  159. /package/dist/app/{nerd-font-controller.d.ts → terminal/nerd-font-controller.d.ts} +0 -0
  160. /package/dist/app/{nerd-font-controller.js → terminal/nerd-font-controller.js} +0 -0
  161. /package/dist/app/{terminal-bell-sound-controller.d.ts → terminal/terminal-bell-sound-controller.d.ts} +0 -0
  162. /package/dist/app/{terminal-controller.d.ts → terminal/terminal-controller.d.ts} +0 -0
  163. /package/dist/app/{terminal-output-buffer.d.ts → terminal/terminal-output-buffer.d.ts} +0 -0
  164. /package/dist/app/{terminal-output-buffer.js → terminal/terminal-output-buffer.js} +0 -0
  165. /package/dist/app/{workspace-undo.d.ts → workspace/workspace-undo.d.ts} +0 -0
  166. /package/dist/app/{workspace-undo.js → workspace/workspace-undo.js} +0 -0
@@ -8,6 +8,7 @@ export const DEFAULT_PI_TOOLS_SUITE_CONFIG_JSONC = `{
8
8
  // "lsp",
9
9
  // "repo-discovery",
10
10
  // "antigravity-auth",
11
+ // "opencode-import",
11
12
  // "todo",
12
13
  // "model-tools",
13
14
  // "usage",
@@ -358,6 +359,276 @@ export const DEFAULT_PI_TOOLS_SUITE_CONFIG_JSONC = `{
358
359
  "prompt": "Commit all changes"
359
360
  }
360
361
  }
362
+ },
363
+
364
+ // LSP language servers. TypeScript/JavaScript is enabled by default;
365
+ // uncomment additional server blocks after installing their binaries.
366
+ "lsp": {
367
+ "servers": [
368
+ {
369
+ "id": "typescript",
370
+ "include": [
371
+ "**/*.ts",
372
+ "**/*.tsx",
373
+ "**/*.js",
374
+ "**/*.jsx",
375
+ "**/*.mjs"
376
+ ],
377
+ "exclude": [
378
+ "**/node_modules/**",
379
+ "**/.next/**"
380
+ ],
381
+ "rootMarkers": [
382
+ "tsconfig.json",
383
+ "package.json"
384
+ ],
385
+ "bin": "typescript-language-server",
386
+ "args": [
387
+ "--stdio"
388
+ ],
389
+ "languageIdByExtension": {
390
+ ".ts": "typescript",
391
+ ".tsx": "typescriptreact",
392
+ ".js": "javascript",
393
+ ".jsx": "javascriptreact",
394
+ ".mjs": "javascript"
395
+ }
396
+ }
397
+ // ,
398
+ // {
399
+ // "id": "python",
400
+ // "include": [
401
+ // "**/*.py",
402
+ // "**/*.pyi"
403
+ // ],
404
+ // "exclude": [
405
+ // "**/.git/**",
406
+ // "**/node_modules/**",
407
+ // "**/__pycache__/**",
408
+ // "**/.venv/**",
409
+ // "**/venv/**",
410
+ // "**/.tox/**",
411
+ // "**/.mypy_cache/**",
412
+ // "**/.ruff_cache/**"
413
+ // ],
414
+ // "rootMarkers": [
415
+ // "pyproject.toml",
416
+ // "setup.py",
417
+ // "setup.cfg",
418
+ // "requirements.txt",
419
+ // "Pipfile",
420
+ // "poetry.lock",
421
+ // ".git"
422
+ // ],
423
+ // "bin": "pylsp",
424
+ // "args": [],
425
+ // "languageIdByExtension": {
426
+ // ".py": "python",
427
+ // ".pyi": "python"
428
+ // }
429
+ // }
430
+ // ,
431
+ // {
432
+ // "id": "csharp",
433
+ // "include": [
434
+ // "**/*.cs",
435
+ // "**/*.csx"
436
+ // ],
437
+ // "exclude": [
438
+ // "**/.git/**",
439
+ // "**/node_modules/**",
440
+ // "**/bin/**",
441
+ // "**/obj/**",
442
+ // "**/.vs/**",
443
+ // "**/Library/**",
444
+ // "**/Temp/**",
445
+ // "**/Logs/**"
446
+ // ],
447
+ // "rootMarkers": [
448
+ // "*.sln",
449
+ // "*.csproj",
450
+ // "global.json",
451
+ // "Directory.Build.props",
452
+ // "Directory.Packages.props",
453
+ // "Packages/manifest.json",
454
+ // "ProjectSettings/ProjectVersion.txt",
455
+ // ".git"
456
+ // ],
457
+ // "bin": "~/.dotnet/tools/roslyn-language-server",
458
+ // "args": [
459
+ // "--stdio",
460
+ // "--autoLoadProjects",
461
+ // "--logLevel",
462
+ // "Error"
463
+ // ],
464
+ // "startupTimeoutMs": 30000,
465
+ // "diagnosticsWaitMs": 15000,
466
+ // "languageIdByExtension": {
467
+ // ".cs": "csharp",
468
+ // ".csx": "csharp"
469
+ // }
470
+ // }
471
+ // ,
472
+ // {
473
+ // "id": "gdscript",
474
+ // "include": [
475
+ // "**/*.gd",
476
+ // "**/*.gdshader",
477
+ // "**/*.gdshaderinc"
478
+ // ],
479
+ // "exclude": [
480
+ // "**/.git/**",
481
+ // "**/node_modules/**",
482
+ // "**/.godot/**",
483
+ // "**/imported/**"
484
+ // ],
485
+ // "rootMarkers": [
486
+ // "project.godot"
487
+ // ],
488
+ // "bin": "bash",
489
+ // "args": [
490
+ // "-lc",
491
+ // "port=$(python3 -c 'import socket; s=socket.socket(); s.bind((\\"127.0.0.1\\", 0)); print(s.getsockname()[1]); s.close()'); log=\\"\${TMPDIR:-/tmp}/pi-godot-lsp-\${1##*/}-\${port}.log\\"; godot --headless --editor --path \\"$1\\" --lsp-port \\"$port\\" >\\"$log\\" 2>&1 & pid=$!; cleanup(){ kill \\"$pid\\" 2>/dev/null || true; wait \\"$pid\\" 2>/dev/null || true; }; trap 'cleanup; exit 143' TERM INT HUP; trap cleanup EXIT; for i in $(seq 1 80); do nc -z 127.0.0.1 \\"$port\\" 2>/dev/null && break; if ! kill -0 \\"$pid\\" 2>/dev/null; then cat \\"$log\\" >&2; exit 1; fi; sleep 0.25; done; if ! nc -z 127.0.0.1 \\"$port\\" 2>/dev/null; then echo \\"Godot LSP did not open 127.0.0.1:$port; see $log\\" >&2; exit 1; fi; nc 127.0.0.1 \\"$port\\"; status=$?; exit $status",
492
+ // "pi-godot-lsp",
493
+ // "{root}"
494
+ // ],
495
+ // "startupTimeoutMs": 30000,
496
+ // "diagnosticsWaitMs": 6000,
497
+ // "languageIdByExtension": {
498
+ // ".gd": "gdscript",
499
+ // ".gdshader": "gdshader",
500
+ // ".gdshaderinc": "gdshader"
501
+ // }
502
+ // }
503
+ // ,
504
+ // {
505
+ // "id": "ruby",
506
+ // "include": [
507
+ // "**/*.rb",
508
+ // "**/*.rake",
509
+ // "**/Gemfile",
510
+ // "**/Rakefile",
511
+ // "**/*.gemspec"
512
+ // ],
513
+ // "exclude": [
514
+ // "**/.git/**",
515
+ // "**/node_modules/**",
516
+ // "**/vendor/bundle/**",
517
+ // "**/.bundle/**",
518
+ // "**/tmp/**",
519
+ // "**/log/**"
520
+ // ],
521
+ // "rootMarkers": [
522
+ // "Gemfile.lock",
523
+ // "*.gemspec",
524
+ // "Rakefile",
525
+ // ".ruby-version",
526
+ // ".git"
527
+ // ],
528
+ // "bin": "ruby-lsp",
529
+ // "args": [],
530
+ // "startupTimeoutMs": 60000,
531
+ // "diagnosticsWaitMs": 10000,
532
+ // "languageIdByExtension": {
533
+ // ".rb": "ruby",
534
+ // ".rake": "ruby",
535
+ // ".gemspec": "ruby"
536
+ // }
537
+ // }
538
+ // ,
539
+ // {
540
+ // "id": "rust",
541
+ // "include": [
542
+ // "**/*.rs"
543
+ // ],
544
+ // "exclude": [
545
+ // "**/.git/**",
546
+ // "**/node_modules/**",
547
+ // "**/target/**"
548
+ // ],
549
+ // "rootMarkers": [
550
+ // "Cargo.toml",
551
+ // "rust-project.json",
552
+ // ".git"
553
+ // ],
554
+ // "bin": "rust-analyzer",
555
+ // "args": [],
556
+ // "startupTimeoutMs": 20000,
557
+ // "diagnosticsWaitMs": 8000,
558
+ // "languageIdByExtension": {
559
+ // ".rs": "rust"
560
+ // }
561
+ // }
562
+ // ,
563
+ // {
564
+ // "id": "markdown",
565
+ // "include": [
566
+ // "**/*.md",
567
+ // "**/*.markdown",
568
+ // "**/*.mdown",
569
+ // "**/*.mkd",
570
+ // "**/*.mmd",
571
+ // "**/*.mermaid"
572
+ // ],
573
+ // "exclude": [
574
+ // "**/.git/**",
575
+ // "**/node_modules/**"
576
+ // ],
577
+ // "rootMarkers": [
578
+ // ".git",
579
+ // "package.json",
580
+ // "README.md"
581
+ // ],
582
+ // "bin": "vscode-markdown-language-server",
583
+ // "args": [
584
+ // "--stdio"
585
+ // ],
586
+ // "startupTimeoutMs": 15000,
587
+ // "diagnosticsWaitMs": 5000,
588
+ // "languageIdByExtension": {
589
+ // ".md": "markdown",
590
+ // ".markdown": "markdown",
591
+ // ".mdown": "markdown",
592
+ // ".mkd": "markdown",
593
+ // ".mmd": "markdown",
594
+ // ".mermaid": "markdown"
595
+ // },
596
+ // "initializationOptions": {
597
+ // "markdownFileExtensions": [
598
+ // "md",
599
+ // "markdown",
600
+ // "mdown",
601
+ // "mkd",
602
+ // "mmd",
603
+ // "mermaid"
604
+ // ]
605
+ // },
606
+ // "settings": {
607
+ // "markdown": {
608
+ // "validate": {
609
+ // "enabled": true,
610
+ // "referenceLinks": {
611
+ // "enabled": "error"
612
+ // },
613
+ // "fragmentLinks": {
614
+ // "enabled": "error"
615
+ // },
616
+ // "fileLinks": {
617
+ // "enabled": "error",
618
+ // "markdownFragmentLinks": "inherit"
619
+ // },
620
+ // "unusedLinkDefinitions": {
621
+ // "enabled": "hint"
622
+ // },
623
+ // "duplicateLinkDefinitions": {
624
+ // "enabled": "warning"
625
+ // },
626
+ // "ignoredLinks": []
627
+ // }
628
+ // }
629
+ // }
630
+ // }
631
+ ]
361
632
  }
362
633
  }
363
634
  `;
@@ -15,6 +15,7 @@ const MODULES: Array<{ name: string; load: () => Promise<ExtensionModule> }> = [
15
15
  { name: "lsp", load: () => import("./lsp/index") },
16
16
  { name: "repo-discovery", load: () => import("./repo-discovery/index") },
17
17
  { name: "antigravity-auth", load: () => import("./antigravity-auth/index") },
18
+ { name: "opencode-import", load: () => import("./opencode-import/index") },
18
19
  { name: "todo", load: () => import("./todo/index") },
19
20
  { name: "model-tools", load: () => import("./model-tools/index") },
20
21
  { name: "usage", load: () => import("./usage/index") },
@@ -0,0 +1,86 @@
1
+ import type { OpencodeImportOptions, OpencodeImportResult, OpencodeProviderImportResult } from "./importer";
2
+
3
+ function tokenizeArgs(args: string): string[] {
4
+ return args.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g)?.map((part) => part.replace(/^("|')|("|')$/g, "")) ?? [];
5
+ }
6
+
7
+ export function parseOpencodeImportCommandArgs(args: string): OpencodeImportOptions {
8
+ const tokens = tokenizeArgs(args);
9
+ const parsed: OpencodeImportOptions = {};
10
+ for (let i = 0; i < tokens.length; i += 1) {
11
+ const token = tokens[i];
12
+ if (token === "--force" || token === "-f") {
13
+ parsed.overwrite = true;
14
+ } else if ((token === "--path" || token === "--opencode-auth-path") && tokens[i + 1]) {
15
+ parsed.sourcePath = tokens[++i];
16
+ } else if (token === "--auth-path" && tokens[i + 1]) {
17
+ parsed.authPath = tokens[++i];
18
+ } else if (token === "--antigravity-path" && tokens[i + 1]) {
19
+ parsed.antigravitySourcePath = tokens[++i];
20
+ } else if (token === "--skip-auth-json") {
21
+ parsed.skipAuthJson = true;
22
+ } else if (token === "--skip-antigravity") {
23
+ parsed.skipAntigravity = true;
24
+ } else if ((token === "--antigravity-index" || token === "--antigravity-account-index") && tokens[i + 1]) {
25
+ const index = Number(tokens[++i]);
26
+ if (Number.isInteger(index)) parsed.antigravityAccountIndex = index;
27
+ } else if (token === "--antigravity-email" && tokens[i + 1]) {
28
+ parsed.antigravityEmail = tokens[++i];
29
+ } else if (!token.startsWith("-") && !parsed.sourcePath) {
30
+ parsed.sourcePath = token;
31
+ }
32
+ }
33
+ return parsed;
34
+ }
35
+
36
+ function statusText(result: OpencodeProviderImportResult): string {
37
+ switch (result.status) {
38
+ case "imported":
39
+ return `imported ${result.sourceProvider} → ${result.targetProvider}`;
40
+ case "already-imported":
41
+ return `already imported ${result.targetProvider}`;
42
+ case "auth-exists-use-force":
43
+ return `skipped ${result.targetProvider}: already exists; use --force`;
44
+ case "target-set-from-other-source":
45
+ return `skipped ${result.sourceProvider}: ${result.targetProvider} was already filled from another opencode entry`;
46
+ case "invalid-source":
47
+ return `skipped ${result.sourceProvider}: missing usable token/key`;
48
+ case "source-missing":
49
+ return `missing ${result.sourceProvider}`;
50
+ }
51
+ }
52
+
53
+ function antigravityText(result: OpencodeImportResult): string | undefined {
54
+ const antigravity = result.antigravity;
55
+ if (!antigravity) return undefined;
56
+ const account = antigravity.email ? ` ${antigravity.email}` : "";
57
+ const position = typeof antigravity.accountIndex === "number" && typeof antigravity.accountCount === "number" ? ` (${antigravity.accountIndex + 1}/${antigravity.accountCount})` : "";
58
+ if (antigravity.imported) {
59
+ return `Antigravity: imported${account}${position}${antigravity.overwroteExisting ? " and overwrote existing auth" : ""}`;
60
+ }
61
+ if (antigravity.reason === "auth-exists-use-force") return "Antigravity: skipped existing auth; use --force";
62
+ if (antigravity.reason === "already-imported") return `Antigravity: already imported${account}${position}`;
63
+ return `Antigravity: skipped (${antigravity.reason ?? "unknown"})`;
64
+ }
65
+
66
+ export function formatOpencodeImportResult(result: OpencodeImportResult): string {
67
+ const providerLines = result.providers
68
+ .filter((provider) => provider.status !== "source-missing")
69
+ .map((provider) => `- ${provider.label}: ${statusText(provider)}`);
70
+ const missingCount = result.providers.filter((provider) => provider.status === "source-missing").length;
71
+ const antigravity = antigravityText(result);
72
+ if (antigravity) providerLines.push(`- ${antigravity}`);
73
+
74
+ if (providerLines.length === 0) {
75
+ return `No opencode credentials were imported. Checked ${result.sourcePath}${result.antigravitySourcePath ? ` and ${result.antigravitySourcePath}` : ""}.`;
76
+ }
77
+
78
+ const suffix = missingCount > 0 ? `\nMissing ${missingCount} known opencode provider entr${missingCount === 1 ? "y" : "ies"}.` : "";
79
+ return `Opencode import wrote to ${result.authPath}:\n${providerLines.join("\n")}${suffix}`;
80
+ }
81
+
82
+ export function notificationLevel(result: OpencodeImportResult): "info" | "warn" | "error" {
83
+ if (result.wroteAuth) return "info";
84
+ if (result.providers.some((provider) => provider.status === "auth-exists-use-force") || result.antigravity?.reason === "auth-exists-use-force") return "warn";
85
+ return "error";
86
+ }
@@ -0,0 +1,208 @@
1
+ import { promises as fs } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { getPiAuthPath, importOpencodeAntigravityAccount, readJsonFile, writeJsonFileSecure } from "../antigravity-auth/auth-store";
5
+
6
+ export type OpencodeAuthCredential = {
7
+ type?: string;
8
+ access?: string;
9
+ refresh?: string;
10
+ expires?: number;
11
+ key?: string;
12
+ [key: string]: unknown;
13
+ };
14
+
15
+ export type PiAuthCredential = OpencodeAuthCredential;
16
+ export type PiAuthData = Record<string, PiAuthCredential | undefined>;
17
+ export type OpencodeAuthData = Record<string, OpencodeAuthCredential | undefined>;
18
+
19
+ export type OpencodeProviderImportStatus = "imported" | "already-imported" | "auth-exists-use-force" | "source-missing" | "target-set-from-other-source" | "invalid-source";
20
+
21
+ export type OpencodeProviderImportResult = {
22
+ label: string;
23
+ sourceProvider: string;
24
+ targetProvider: string;
25
+ status: OpencodeProviderImportStatus;
26
+ };
27
+
28
+ export type OpencodeImportResult = {
29
+ sourcePath: string;
30
+ antigravitySourcePath?: string;
31
+ authPath: string;
32
+ providers: OpencodeProviderImportResult[];
33
+ antigravity?: {
34
+ imported: boolean;
35
+ reason?: string;
36
+ email?: string;
37
+ accountIndex?: number;
38
+ accountCount?: number;
39
+ overwroteExisting?: boolean;
40
+ };
41
+ wroteAuth: boolean;
42
+ };
43
+
44
+ export type OpencodeImportOptions = {
45
+ sourcePath?: string;
46
+ authPath?: string;
47
+ antigravitySourcePath?: string;
48
+ overwrite?: boolean;
49
+ skipAuthJson?: boolean;
50
+ skipAntigravity?: boolean;
51
+ antigravityAccountIndex?: number;
52
+ antigravityEmail?: string;
53
+ };
54
+
55
+ type Mapping = {
56
+ label: string;
57
+ sourceProvider: string;
58
+ targetProvider: string;
59
+ transform: (credential: OpencodeAuthCredential) => PiAuthCredential | undefined;
60
+ };
61
+
62
+ const AUTH_JSON_MAPPINGS: Mapping[] = [
63
+ {
64
+ label: "OpenAI Codex",
65
+ sourceProvider: "openai",
66
+ targetProvider: "openai-codex",
67
+ transform: transformOAuthCredential,
68
+ },
69
+ {
70
+ label: "GitHub Copilot",
71
+ sourceProvider: "github-copilot",
72
+ targetProvider: "github-copilot",
73
+ transform: transformOAuthCredential,
74
+ },
75
+ {
76
+ label: "Z.ai",
77
+ sourceProvider: "zai-coding-plan",
78
+ targetProvider: "zai",
79
+ transform: transformApiKeyCredential,
80
+ },
81
+ {
82
+ label: "Zhipu/Z.ai",
83
+ sourceProvider: "zhipuai-coding-plan",
84
+ targetProvider: "zai",
85
+ transform: transformApiKeyCredential,
86
+ },
87
+ ];
88
+
89
+ export function getDefaultOpencodeAuthPath(): string {
90
+ const dataDir = process.env.OPENCODE_DATA_DIR ?? join(process.env.XDG_DATA_HOME ?? join(homedir(), ".local", "share"), "opencode");
91
+ return join(dataDir, "auth.json");
92
+ }
93
+
94
+ function transformOAuthCredential(credential: OpencodeAuthCredential): PiAuthCredential | undefined {
95
+ if (!credential.access && !credential.refresh) return undefined;
96
+ return { ...credential, type: "oauth" };
97
+ }
98
+
99
+ function transformApiKeyCredential(credential: OpencodeAuthCredential): PiAuthCredential | undefined {
100
+ if (!credential.key) return undefined;
101
+ return { ...credential, type: "api_key", key: credential.key };
102
+ }
103
+
104
+ function sameCredential(a: PiAuthCredential | undefined, b: PiAuthCredential | undefined): boolean {
105
+ return JSON.stringify(a ?? null) === JSON.stringify(b ?? null);
106
+ }
107
+
108
+ function providerResult(mapping: Mapping, status: OpencodeProviderImportStatus): OpencodeProviderImportResult {
109
+ return {
110
+ label: mapping.label,
111
+ sourceProvider: mapping.sourceProvider,
112
+ targetProvider: mapping.targetProvider,
113
+ status,
114
+ };
115
+ }
116
+
117
+ async function pathExists(path: string): Promise<boolean> {
118
+ try {
119
+ await fs.access(path);
120
+ return true;
121
+ } catch {
122
+ return false;
123
+ }
124
+ }
125
+
126
+ export async function importOpencodeAccounts(options: OpencodeImportOptions = {}): Promise<OpencodeImportResult> {
127
+ const sourcePath = options.sourcePath ?? getDefaultOpencodeAuthPath();
128
+ const authPath = options.authPath ?? getPiAuthPath();
129
+ const result: OpencodeImportResult = {
130
+ sourcePath,
131
+ authPath,
132
+ providers: [],
133
+ wroteAuth: false,
134
+ };
135
+ if (options.antigravitySourcePath) result.antigravitySourcePath = options.antigravitySourcePath;
136
+
137
+ let piAuth = await readJsonFile<PiAuthData>(authPath, {});
138
+ const changedTargets = new Set<string>();
139
+
140
+ if (!options.skipAuthJson) {
141
+ const sourceExists = await pathExists(sourcePath);
142
+ const opencodeAuth = sourceExists ? await readJsonFile<OpencodeAuthData>(sourcePath, {}) : {};
143
+
144
+ for (const mapping of AUTH_JSON_MAPPINGS) {
145
+ const sourceCredential = opencodeAuth[mapping.sourceProvider];
146
+ if (!sourceCredential) {
147
+ result.providers.push(providerResult(mapping, "source-missing"));
148
+ continue;
149
+ }
150
+
151
+ if (changedTargets.has(mapping.targetProvider)) {
152
+ result.providers.push(providerResult(mapping, "target-set-from-other-source"));
153
+ continue;
154
+ }
155
+
156
+ const nextCredential = mapping.transform(sourceCredential);
157
+ if (!nextCredential) {
158
+ result.providers.push(providerResult(mapping, "invalid-source"));
159
+ continue;
160
+ }
161
+
162
+ const existingCredential = piAuth[mapping.targetProvider];
163
+ if (sameCredential(existingCredential, nextCredential)) {
164
+ result.providers.push(providerResult(mapping, "already-imported"));
165
+ changedTargets.add(mapping.targetProvider);
166
+ continue;
167
+ }
168
+
169
+ if (existingCredential && !options.overwrite) {
170
+ result.providers.push(providerResult(mapping, "auth-exists-use-force"));
171
+ changedTargets.add(mapping.targetProvider);
172
+ continue;
173
+ }
174
+
175
+ piAuth = { ...piAuth, [mapping.targetProvider]: nextCredential };
176
+ changedTargets.add(mapping.targetProvider);
177
+ result.providers.push(providerResult(mapping, "imported"));
178
+ }
179
+
180
+ if (result.providers.some((provider) => provider.status === "imported")) {
181
+ await writeJsonFileSecure(authPath, piAuth);
182
+ result.wroteAuth = true;
183
+ }
184
+ }
185
+
186
+ if (!options.skipAntigravity) {
187
+ const antigravity = await importOpencodeAntigravityAccount({
188
+ sourcePath: options.antigravitySourcePath,
189
+ authPath,
190
+ overwrite: options.overwrite,
191
+ accountIndex: options.antigravityAccountIndex,
192
+ email: options.antigravityEmail,
193
+ });
194
+ const antigravityResult: NonNullable<OpencodeImportResult["antigravity"]> = {
195
+ imported: antigravity.imported,
196
+ };
197
+ if (antigravity.reason) antigravityResult.reason = antigravity.reason;
198
+ if (antigravity.email) antigravityResult.email = antigravity.email;
199
+ if (typeof antigravity.accountIndex === "number") antigravityResult.accountIndex = antigravity.accountIndex;
200
+ if (typeof antigravity.accountCount === "number") antigravityResult.accountCount = antigravity.accountCount;
201
+ if (typeof antigravity.overwroteExisting === "boolean") antigravityResult.overwroteExisting = antigravity.overwroteExisting;
202
+ result.antigravity = antigravityResult;
203
+ result.antigravitySourcePath = antigravity.sourcePath;
204
+ result.wroteAuth ||= antigravity.imported;
205
+ }
206
+
207
+ return result;
208
+ }
@@ -0,0 +1,25 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import { formatOpencodeImportResult, notificationLevel, parseOpencodeImportCommandArgs } from "./commands";
3
+ import { importOpencodeAccounts } from "./importer";
4
+
5
+ export { formatOpencodeImportResult, notificationLevel, parseOpencodeImportCommandArgs } from "./commands";
6
+ export { getDefaultOpencodeAuthPath, importOpencodeAccounts } from "./importer";
7
+ export type { OpencodeImportOptions, OpencodeImportResult } from "./importer";
8
+
9
+ export default function opencodeImport(pi: ExtensionAPI): void {
10
+ pi.registerCommand("opencode-import", {
11
+ description: "Import opencode auth.json credentials and Antigravity accounts into Pi/Pix auth.json",
12
+ handler: async (args: string, ctx: any) => {
13
+ try {
14
+ const result = await importOpencodeAccounts(parseOpencodeImportCommandArgs(args));
15
+ const message = formatOpencodeImportResult(result);
16
+ if (ctx.ui?.notify) ctx.ui.notify(message, notificationLevel(result));
17
+ else console.log(message);
18
+ } catch (error) {
19
+ const message = error instanceof Error ? error.message : String(error);
20
+ if (ctx.ui?.notify) ctx.ui.notify(message, "error");
21
+ else console.error(message);
22
+ }
23
+ },
24
+ });
25
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-ui-extend",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {
File without changes
File without changes
File without changes