codeep 2.4.1 → 2.4.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.
@@ -825,6 +825,43 @@ async function gracefulShutdown() {
825
825
  }),
826
826
  ]);
827
827
  }
828
+ // ─── Last-resort crash handlers ───────────────────────────────────────────────
829
+ // Without these, a stray throw or rejected promise (deep in the agent loop or a
830
+ // background cloud sync) crashes Node with the terminal still in raw mode +
831
+ // alternate screen — leaving the user's shell garbled — or vanishes silently.
832
+ process.on('uncaughtException', (error) => {
833
+ logAppError(error instanceof Error ? error : new Error(String(error)), 'uncaughtException');
834
+ // After an uncaught exception the process state is undefined; Node's guidance
835
+ // is to clean up synchronously and exit rather than limp on. Restore the
836
+ // terminal and best-effort save the conversation so the crash doesn't lose it.
837
+ try {
838
+ if (app)
839
+ app.stop();
840
+ }
841
+ catch { /* ignore */ }
842
+ try {
843
+ process.stdout.write('\x1b[2J\x1b[3J\x1b[H');
844
+ }
845
+ catch { /* ignore */ }
846
+ console.error('Fatal error:', error);
847
+ try {
848
+ if (app)
849
+ autoSaveSession(app.getMessages(), projectPath);
850
+ }
851
+ catch { /* ignore */ }
852
+ process.exit(1);
853
+ });
854
+ process.on('unhandledRejection', (reason) => {
855
+ logAppError(reason instanceof Error ? reason : new Error(String(reason)), 'unhandledRejection');
856
+ // A rejected promise is usually recoverable (failed background sync, network
857
+ // blip), so surface it and keep the TUI alive instead of tearing it down.
858
+ // Fall back to stderr if the app isn't up yet.
859
+ const message = reason instanceof Error ? reason.message : String(reason);
860
+ if (app)
861
+ app.notifyWarn(`Background error: ${message}`);
862
+ else
863
+ console.error('Unhandled rejection:', reason);
864
+ });
828
865
  process.on('SIGINT', () => {
829
866
  gracefulShutdown().finally(() => process.exit(0));
830
867
  });
@@ -68,10 +68,13 @@ export async function runAccountFlow() {
68
68
  if (!res.ok)
69
69
  continue;
70
70
  const data = await res.json();
71
- if (data.status === 'authorized' && data.github_id) {
71
+ // Require the sync token, not just github_id: the server can briefly
72
+ // report authorized after claiming the code but before the token is
73
+ // issued. Linking without it leaves `account sync` broken ("Not linked"),
74
+ // so keep polling until the token is present.
75
+ if (data.status === 'authorized' && data.github_id && data.sync_token) {
72
76
  setGithubAccount(data.github_id, data.username ?? '');
73
- if (data.sync_token)
74
- setSyncToken(data.sync_token);
77
+ setSyncToken(data.sync_token);
75
78
  // Register device info
76
79
  try {
77
80
  await fetch(`${API_BASE}/api/auth/cli/device`, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeep",
3
- "version": "2.4.1",
3
+ "version": "2.4.2",
4
4
  "description": "AI-powered coding assistant built for the terminal. Multiple LLM providers, project-aware context, and a seamless development workflow.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",