@thegitai/cli 1.0.0-preview.7 → 1.0.0-preview.8

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.
@@ -79,7 +79,7 @@ const HELP_MARKDOWN = [
79
79
  ' browse them, press Enter to expand one and read its output, k to stop it',
80
80
  '- `/jobs output <id>` — print one job\'s full captured output',
81
81
  '- `/jobs kill <id>` — stop one background job',
82
- '- `/clear` — clear the current conversation history',
82
+ '- `/new` — start a new conversation; this session remains saved',
83
83
  '- `/exit` — quit the session',
84
84
  '',
85
85
  '## Safety & approvals',
@@ -69,6 +69,14 @@ export function createSession({ rootDir, autoYes = false, agentMode, modelId, ma
69
69
  serverState: cloneOpaqueState(serverState),
70
70
  };
71
71
  }
72
+ export function startNewConversation(session) {
73
+ clearConversation(session);
74
+ const createdAt = new Date().toISOString();
75
+ session.sessionId = createSessionId();
76
+ session.sessionName = null;
77
+ session.sessionCreatedAt = createdAt;
78
+ session.sessionUpdatedAt = createdAt;
79
+ }
72
80
  export function clearConversation(session) {
73
81
  session.history = [];
74
82
  session.serverState = preserveProviderSelection(session.serverState);
@@ -15,7 +15,7 @@ import { clearCliAuthConfig } from '../api/auth.js';
15
15
  import { authenticationErrorMessage, isAuthenticationError, } from '../api/http.js';
16
16
  import { setCommandOutputHook, withTuiMode } from '../runtime-mode.js';
17
17
  import { collectBackgroundJobUiKillMutations, collectBackgroundJobUiOutputMutations, } from '../tool-executor.js';
18
- import { clearConversation, } from '../session.js';
18
+ import { startNewConversation, } from '../session.js';
19
19
  import { applySessionSnapshot, listSessionMetadata, loadSessionSnapshot, saveSessionState, } from '../session-store.js';
20
20
  import { truncate } from '../utils.js';
21
21
  import { writeClipboardText } from '../core/clipboard.js';
@@ -116,8 +116,8 @@ export const SLASH_COMMANDS = [
116
116
  description: 'Background jobs: pick to view output or kill',
117
117
  },
118
118
  {
119
- command: '/clear',
120
- description: 'Clear conversation history',
119
+ command: '/new',
120
+ description: 'start a new conversation; this session remains saved',
121
121
  },
122
122
  {
123
123
  command: '/exit',
@@ -1320,6 +1320,7 @@ export async function runClientInteractive({ appendPromptHistory, authConfig, de
1320
1320
  let latestUsageSummary = null;
1321
1321
  let pendingTurnEntries = [];
1322
1322
  let activeTurnAbort = null;
1323
+ let newConversationInFlight = false;
1323
1324
  let todosTouchedThisTurn = false;
1324
1325
  const syncTodosState = () => {
1325
1326
  store.update((current) => ({ ...current, todos: listTodos() }));
@@ -1521,7 +1522,7 @@ export async function runClientInteractive({ appendPromptHistory, authConfig, de
1521
1522
  }));
1522
1523
  };
1523
1524
  const cancelActiveTurn = () => {
1524
- if (!store.getState().busy)
1525
+ if (!store.getState().busy || newConversationInFlight)
1525
1526
  return;
1526
1527
  disarmExitConfirm();
1527
1528
  dismissPendingApproval();
@@ -1677,6 +1678,18 @@ export async function runClientInteractive({ appendPromptHistory, authConfig, de
1677
1678
  return true;
1678
1679
  }
1679
1680
  };
1681
+ const saveActiveSessionOrAbort = async () => {
1682
+ try {
1683
+ await saveSessionBoth({ serverSessionClient, session });
1684
+ return true;
1685
+ }
1686
+ catch (error) {
1687
+ if (exitForAuthenticationError(error))
1688
+ return false;
1689
+ appendError(`Session save failed: ${error.message}`);
1690
+ return false;
1691
+ }
1692
+ };
1680
1693
  const openSudoPasswordPrompt = (command, prompt, signal) => new Promise((resolve) => {
1681
1694
  if (exiting || signal?.aborted) {
1682
1695
  resolve(null);
@@ -2243,23 +2256,53 @@ export async function runClientInteractive({ appendPromptHistory, authConfig, de
2243
2256
  }
2244
2257
  return;
2245
2258
  }
2246
- if (input === '/clear') {
2247
- clearConversation(session);
2259
+ if (input === '/new') {
2260
+ newConversationInFlight = true;
2261
+ store.update((current) => ({
2262
+ ...current,
2263
+ busy: true,
2264
+ busySince: Date.now(),
2265
+ imageAttachments: [],
2266
+ queuedMessage: null,
2267
+ status: 'Starting a new conversation...',
2268
+ }));
2269
+ if (!(await saveActiveSessionOrAbort())) {
2270
+ newConversationInFlight = false;
2271
+ store.update((current) => ({
2272
+ ...current,
2273
+ busy: false,
2274
+ busySince: null,
2275
+ status: 'Ready',
2276
+ }));
2277
+ await flushQueuedMessage();
2278
+ return;
2279
+ }
2280
+ startNewConversation(session);
2281
+ setBackgroundJobSession(session.sessionId);
2282
+ setScratchSession(session.sessionId);
2283
+ setTodoSession(session.sessionId);
2248
2284
  clearTodos();
2285
+ syncBackgroundJobsState();
2249
2286
  syncTodosState();
2250
2287
  latestUsageSummary = null;
2251
- if (!(await saveActiveSession()))
2252
- return;
2253
2288
  store.replaceTranscript([
2254
2289
  {
2255
- body: 'Conversation cleared.',
2290
+ body: 'Started a new conversation. The previous session remains saved.',
2256
2291
  kind: 'system',
2257
- title: 'System',
2292
+ title: 'Session',
2258
2293
  },
2259
2294
  ]);
2295
+ await saveActiveSession();
2260
2296
  syncShellStateFromSession();
2261
- store.update((current) => ({ ...current, queuedMessage: null }));
2297
+ newConversationInFlight = false;
2298
+ store.update((current) => ({
2299
+ ...current,
2300
+ busy: false,
2301
+ busySince: null,
2302
+ status: 'Ready',
2303
+ }));
2262
2304
  await remountTui();
2305
+ await flushQueuedMessage();
2263
2306
  return;
2264
2307
  }
2265
2308
  latestUsageSummary = null;
@@ -163,7 +163,7 @@ const CLIENT_SLASH_COMMANDS = [
163
163
  { command: '/model', description: 'Switch the active model' },
164
164
  { command: '/resume', description: 'Open the session picker to resume a previous session' },
165
165
  { command: '/jobs', description: 'Background jobs: pick to view output or kill' },
166
- { command: '/clear', description: 'Clear conversation history' },
166
+ { command: '/new', description: 'start a new conversation; this session remains saved' },
167
167
  { command: '/exit', description: 'Quit the current session' },
168
168
  ];
169
169
  function buildModelPickerOptions(currentModelId, serverModels) {
@@ -923,7 +923,10 @@ export function buildTuiFrame(state, cols, rows, spinnerFrame, elapsedSeconds, n
923
923
  const overlayActive = Boolean(state.approvalPrompt || state.sudoPrompt);
924
924
  if (!state.resumePickerOpen && !state.modelPickerOpen && !state.jobsPickerOpen && !overlayActive) {
925
925
  const composerLines = [];
926
- if (state.queuedMessage) {
926
+ if (state.busy && state.status === 'Starting a new conversation...') {
927
+ composerLines.push(line(span('Starting a new conversation…', { color: 'gray', dim: true })));
928
+ }
929
+ else if (state.queuedMessage) {
927
930
  const preview = truncate(state.queuedMessage.body.trim().replace(/\s+/g, ' '), 60);
928
931
  const imageCount = state.queuedMessage.imageAttachments.length;
929
932
  composerLines.push(line(span(`↳ Queued · "${preview}"`, { color: 'gray', dim: true }), ...(imageCount > 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thegitai/cli",
3
- "version": "1.0.0-preview.7",
3
+ "version": "1.0.0-preview.8",
4
4
  "description": "TheGitAI is an AI coding agent for your terminal. It indexes your repository, writes and edits files, runs commands, and builds features with you.",
5
5
  "keywords": [
6
6
  "ai",
@@ -37,10 +37,10 @@
37
37
  "@lydell/node-pty-linux-x64": "1.1.0",
38
38
  "@lydell/node-pty-win32-arm64": "1.1.0",
39
39
  "@lydell/node-pty-win32-x64": "1.1.0",
40
- "@thegitai/tui-darwin-arm64": "1.0.0-preview.7",
41
- "@thegitai/tui-darwin-x64": "1.0.0-preview.7",
42
- "@thegitai/tui-linux-x64": "1.0.0-preview.7",
43
- "@thegitai/tui-win32-x64": "1.0.0-preview.7",
40
+ "@thegitai/tui-darwin-arm64": "1.0.0-preview.8",
41
+ "@thegitai/tui-darwin-x64": "1.0.0-preview.8",
42
+ "@thegitai/tui-linux-x64": "1.0.0-preview.8",
43
+ "@thegitai/tui-win32-x64": "1.0.0-preview.8",
44
44
  "@vscode/ripgrep": "1.18.0"
45
45
  },
46
46
  "publishConfig": {