@caupulican/pi-adaptative 0.76.2 → 0.78.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/README.md +9 -0
  3. package/dist/cli/args.d.ts +2 -0
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +23 -0
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/core/agent-session-services.d.ts +1 -0
  8. package/dist/core/agent-session-services.d.ts.map +1 -1
  9. package/dist/core/agent-session-services.js +1 -0
  10. package/dist/core/agent-session-services.js.map +1 -1
  11. package/dist/core/agent-session.d.ts +4 -1
  12. package/dist/core/agent-session.d.ts.map +1 -1
  13. package/dist/core/agent-session.js +23 -4
  14. package/dist/core/agent-session.js.map +1 -1
  15. package/dist/core/extensions/runner.d.ts +1 -1
  16. package/dist/core/extensions/runner.d.ts.map +1 -1
  17. package/dist/core/extensions/runner.js +8 -2
  18. package/dist/core/extensions/runner.js.map +1 -1
  19. package/dist/core/extensions/types.d.ts +7 -5
  20. package/dist/core/extensions/types.d.ts.map +1 -1
  21. package/dist/core/extensions/types.js.map +1 -1
  22. package/dist/core/model-registry.d.ts.map +1 -1
  23. package/dist/core/model-registry.js +65 -13
  24. package/dist/core/model-registry.js.map +1 -1
  25. package/dist/core/model-resolver.d.ts.map +1 -1
  26. package/dist/core/model-resolver.js +1 -1
  27. package/dist/core/model-resolver.js.map +1 -1
  28. package/dist/core/resolve-config-value.d.ts +9 -1
  29. package/dist/core/resolve-config-value.d.ts.map +1 -1
  30. package/dist/core/resolve-config-value.js +134 -11
  31. package/dist/core/resolve-config-value.js.map +1 -1
  32. package/dist/core/sdk.d.ts +2 -0
  33. package/dist/core/sdk.d.ts.map +1 -1
  34. package/dist/core/sdk.js +4 -5
  35. package/dist/core/sdk.js.map +1 -1
  36. package/dist/core/session-manager.d.ts +3 -5
  37. package/dist/core/session-manager.d.ts.map +1 -1
  38. package/dist/core/session-manager.js +42 -17
  39. package/dist/core/session-manager.js.map +1 -1
  40. package/dist/core/system-prompt.d.ts.map +1 -1
  41. package/dist/core/system-prompt.js +0 -3
  42. package/dist/core/system-prompt.js.map +1 -1
  43. package/dist/core/tools/edit.d.ts.map +1 -1
  44. package/dist/core/tools/edit.js +7 -10
  45. package/dist/core/tools/edit.js.map +1 -1
  46. package/dist/core/tools/find.d.ts.map +1 -1
  47. package/dist/core/tools/find.js.map +1 -1
  48. package/dist/core/tools/grep.d.ts.map +1 -1
  49. package/dist/core/tools/grep.js.map +1 -1
  50. package/dist/core/tools/ls.d.ts.map +1 -1
  51. package/dist/core/tools/ls.js +5 -7
  52. package/dist/core/tools/ls.js.map +1 -1
  53. package/dist/core/tools/read.d.ts.map +1 -1
  54. package/dist/core/tools/read.js +6 -7
  55. package/dist/core/tools/read.js.map +1 -1
  56. package/dist/core/tools/render-utils.d.ts +5 -2
  57. package/dist/core/tools/render-utils.d.ts.map +1 -1
  58. package/dist/core/tools/render-utils.js +17 -1
  59. package/dist/core/tools/render-utils.js.map +1 -1
  60. package/dist/core/tools/write.d.ts.map +1 -1
  61. package/dist/core/tools/write.js +5 -6
  62. package/dist/core/tools/write.js.map +1 -1
  63. package/dist/index.d.ts +2 -0
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +2 -0
  66. package/dist/index.js.map +1 -1
  67. package/dist/main.d.ts.map +1 -1
  68. package/dist/main.js +15 -2
  69. package/dist/main.js.map +1 -1
  70. package/dist/migrations.d.ts.map +1 -1
  71. package/dist/migrations.js +118 -1
  72. package/dist/migrations.js.map +1 -1
  73. package/dist/modes/interactive/components/login-dialog.d.ts +1 -3
  74. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  75. package/dist/modes/interactive/components/login-dialog.js +2 -4
  76. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  77. package/dist/modes/interactive/interactive-mode.d.ts +3 -0
  78. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  79. package/dist/modes/interactive/interactive-mode.js +59 -6
  80. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  81. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  82. package/dist/modes/interactive/theme/theme.js +10 -0
  83. package/dist/modes/interactive/theme/theme.js.map +1 -1
  84. package/dist/utils/deprecation.d.ts +4 -0
  85. package/dist/utils/deprecation.d.ts.map +1 -0
  86. package/dist/utils/deprecation.js +13 -0
  87. package/dist/utils/deprecation.js.map +1 -0
  88. package/dist/utils/json.d.ts +3 -0
  89. package/dist/utils/json.d.ts.map +1 -0
  90. package/dist/utils/json.js +7 -0
  91. package/dist/utils/json.js.map +1 -0
  92. package/docs/custom-provider.md +13 -10
  93. package/docs/extensions.md +12 -6
  94. package/docs/models.md +25 -12
  95. package/docs/providers.md +13 -5
  96. package/docs/quickstart.md +1 -0
  97. package/docs/rpc.md +2 -1
  98. package/docs/sdk.md +6 -0
  99. package/docs/session-format.md +1 -1
  100. package/docs/sessions.md +8 -0
  101. package/docs/settings.md +1 -1
  102. package/docs/terminal-setup.md +2 -0
  103. package/docs/tui.md +2 -2
  104. package/docs/usage.md +9 -0
  105. package/examples/extensions/README.md +1 -0
  106. package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
  107. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  108. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  109. package/examples/extensions/custom-provider-gitlab-duo/index.ts +54 -3
  110. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  111. package/examples/extensions/git-merge-and-resolve.ts +115 -0
  112. package/examples/extensions/input-transform-streaming.ts +39 -0
  113. package/examples/extensions/sandbox/package-lock.json +2 -2
  114. package/examples/extensions/sandbox/package.json +1 -1
  115. package/examples/extensions/with-deps/package-lock.json +2 -2
  116. package/examples/extensions/with-deps/package.json +1 -1
  117. package/npm-shrinkwrap.json +56 -56
  118. package/package.json +5 -5
@@ -8,6 +8,7 @@ import * as os from "node:os";
8
8
  import * as path from "node:path";
9
9
  import { getProviders, } from "@earendil-works/pi-ai";
10
10
  import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Loader, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TUI, visibleWidth, } from "@earendil-works/pi-tui";
11
+ import chalk from "chalk";
11
12
  import { spawn, spawnSync } from "child_process";
12
13
  import { APP_NAME, APP_TITLE, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, getShareViewerUrl, VERSION, } from "../../config.js";
13
14
  import { parseSkillBlock } from "../../core/agent-session.js";
@@ -91,6 +92,27 @@ function isAnthropicSubscriptionAuthKey(apiKey) {
91
92
  function isUnknownModel(model) {
92
93
  return !!model && model.provider === "unknown" && model.id === "unknown" && model.api === "unknown";
93
94
  }
95
+ function quoteIfNeeded(value) {
96
+ if (value.length > 0 && !/[^a-zA-Z0-9_\-./~:@]/.test(value)) {
97
+ return value;
98
+ }
99
+ return `'${value.replace(/'/g, `'\\''`)}'`;
100
+ }
101
+ export function formatResumeCommand(sessionManager) {
102
+ if (!process.stdout.isTTY)
103
+ return undefined;
104
+ if (!sessionManager.isPersisted())
105
+ return undefined;
106
+ const sessionFile = sessionManager.getSessionFile();
107
+ if (!sessionFile || !fs.existsSync(sessionFile))
108
+ return undefined;
109
+ const args = [APP_NAME];
110
+ if (!sessionManager.usesDefaultSessionDir()) {
111
+ args.push("--session-dir", quoteIfNeeded(sessionManager.getSessionDir()));
112
+ }
113
+ args.push("--session", sessionManager.getSessionId());
114
+ return args.join(" ");
115
+ }
94
116
  function hasDefaultModelProvider(providerId) {
95
117
  return providerId in defaultModelPerProvider;
96
118
  }
@@ -125,6 +147,7 @@ export class InteractiveMode {
125
147
  version;
126
148
  isInitialized = false;
127
149
  onInputCallback;
150
+ pendingUserInputs = [];
128
151
  loadingAnimation = undefined;
129
152
  workingMessage = undefined;
130
153
  workingVisible = true;
@@ -2133,6 +2156,9 @@ export class InteractiveMode {
2133
2156
  if (this.onInputCallback) {
2134
2157
  this.onInputCallback(text);
2135
2158
  }
2159
+ else {
2160
+ this.pendingUserInputs.push(text);
2161
+ }
2136
2162
  this.editor.addToHistory?.(text);
2137
2163
  };
2138
2164
  }
@@ -2611,6 +2637,10 @@ export class InteractiveMode {
2611
2637
  }
2612
2638
  }
2613
2639
  async getUserInput() {
2640
+ const queuedInput = this.pendingUserInputs.shift();
2641
+ if (queuedInput !== undefined) {
2642
+ return queuedInput;
2643
+ }
2614
2644
  return new Promise((resolve) => {
2615
2645
  this.onInputCallback = (text) => {
2616
2646
  this.onInputCallback = undefined;
@@ -2646,16 +2676,36 @@ export class InteractiveMode {
2646
2676
  * repaint the final frame while the process is exiting.
2647
2677
  */
2648
2678
  isShuttingDown = false;
2649
- async shutdown() {
2679
+ async shutdown(options) {
2650
2680
  if (this.isShuttingDown)
2651
2681
  return;
2652
2682
  this.isShuttingDown = true;
2653
2683
  this.unregisterSignalHandlers();
2684
+ if (options?.fromSignal) {
2685
+ // Signal-triggered shutdown (SIGTERM/SIGHUP). Emit extension cleanup
2686
+ // (session_shutdown) BEFORE touching the terminal. Extension teardown
2687
+ // such as removing sockets does not write to the tty, so it must not be
2688
+ // skipped if a later terminal-restore write fails on a dead or stalled
2689
+ // terminal. If the terminal is gone, the restore writes below emit EIO,
2690
+ // which the stdout/stderr error handler turns into emergencyTerminalExit;
2691
+ // the render loop is already idle, so this cannot hot-spin (see #4144).
2692
+ await this.runtimeHost.dispose();
2693
+ await this.ui.terminal.drainInput(1000);
2694
+ this.stop();
2695
+ process.exit(0);
2696
+ }
2697
+ // Interactive quit (Ctrl+D, Ctrl+C, /quit, extension shutdown()). Stop the
2698
+ // TUI before emitting shutdown events so extension UI cleanup cannot repaint
2699
+ // the final frame while the process is exiting.
2654
2700
  // Drain any in-flight Kitty key release events before stopping.
2655
2701
  // This prevents escape sequences from leaking to the parent shell over slow SSH.
2656
2702
  await this.ui.terminal.drainInput(1000);
2657
2703
  this.stop();
2658
2704
  await this.runtimeHost.dispose();
2705
+ const resumeCommand = formatResumeCommand(this.sessionManager);
2706
+ if (resumeCommand) {
2707
+ process.stdout.write(`${chalk.dim("To resume this session:")} ${resumeCommand}\n`);
2708
+ }
2659
2709
  process.exit(0);
2660
2710
  }
2661
2711
  emergencyTerminalExit() {
@@ -2714,11 +2764,12 @@ export class InteractiveMode {
2714
2764
  }
2715
2765
  for (const signal of signals) {
2716
2766
  const handler = () => {
2717
- if (signal === "SIGHUP") {
2718
- this.emergencyTerminalExit();
2719
- }
2767
+ // SIGHUP no longer hard-exits: graceful shutdown emits session_shutdown
2768
+ // first, then attempts terminal restore. A genuinely dead terminal
2769
+ // surfaces as an EIO on the restore writes, which the stdout/stderr
2770
+ // error handler converts into emergencyTerminalExit (see #4144, #5080).
2720
2771
  killTrackedDetachedChildren();
2721
- void this.shutdown();
2772
+ void this.shutdown({ fromSignal: true });
2722
2773
  };
2723
2774
  process.prependListener(signal, handler);
2724
2775
  this.signalCleanupHandlers.push(() => process.off(signal, handler));
@@ -3646,7 +3697,9 @@ export class InteractiveMode {
3646
3697
  }
3647
3698
  showSessionSelector() {
3648
3699
  this.showSelector((done) => {
3649
- const selector = new SessionSelectorComponent((onProgress) => SessionManager.list(this.sessionManager.getCwd(), this.sessionManager.getSessionDir(), onProgress), SessionManager.listAll, async (sessionPath) => {
3700
+ const selector = new SessionSelectorComponent((onProgress) => SessionManager.list(this.sessionManager.getCwd(), this.sessionManager.getSessionDir(), onProgress), (onProgress) => this.sessionManager.usesDefaultSessionDir()
3701
+ ? SessionManager.listAll(onProgress)
3702
+ : SessionManager.listAll(this.sessionManager.getSessionDir(), onProgress), async (sessionPath) => {
3650
3703
  done();
3651
3704
  await this.handleResumeSession(sessionPath);
3652
3705
  }, () => {