Skip to content

feat(tui): lazy-create the session on first use with the v2 engine - #2458

Open
liruifengv wants to merge 7 commits into
mainfrom
feat/lazy-session-creation
Open

feat(tui): lazy-create the session on first use with the v2 engine#2458
liruifengv wants to merge 7 commits into
mainfrom
feat/lazy-session-creation

Conversation

@liruifengv

Copy link
Copy Markdown
Collaborator

Related Issue

No linked issue — this is part of the ongoing agent-core-v2 engine rollout for the interactive TUI.

Problem

The TUI eagerly creates a session at startup (KimiTUI.init calls harness.createSession even when the user has not sent anything yet). Under the v2 engine this is unnecessary: a workspace handler can exist without a session, the main agent is only materialized on first use, and skills live on the workspace rather than the session. Eager creation also means the session appears in the picker / persisted session store before the user has done anything.

What changed

With the v2 engine (KIMI_CODE_EXPERIMENTAL_FLAG), the TUI now starts session-less and creates the session on first use:

  • Startup: non-resume startups no longer create a session; --session / --continue resume and the --session "" picker behave as before. The footer shows the config defaults the engine would apply at createSession time (model, defaultPermissionMode, defaultPlanMode, thinking effort, context cap) so nothing goes blank while waiting.
  • First use triggers creation: sending a message, a bash-mode command, or a session-requiring slash command (/plan /yolo /auto /compact /goal /permission /settings /undo /web /fork /export-* /init /btw /swarm /add-dir /plugins /mcp /usage /status /title) and skill/plugin commands all lazy-create the session via a shared ensureSession() path. /login, /model, /logout, /provider, /reload, /copy, /theme and other session-independent commands never trigger creation; activateModelAfterLogin no longer creates a session after login/model switch.
  • Skills without a session: refreshSkillCommands falls back to harness.listWorkspaceSkills(workDir) when no session exists (plugin skills are missing from that list until the session is created and refreshed). Plugin commands are already app-global under v2, so a new KimiHarness.listPluginCommands() exposes them session-less (the base RPC returns an empty list for v1).
  • --agent / --agent-file: the startup agent binding is carried in appState and applied to the first lazy-created session, instead of being lost when session creation moves out of init().
  • /plugins: fixed a latent unhandled-rejection when the command runs without an active session (its internal requireSession throw was dispatched via void).
  • The v1 engine path is unchanged: all lazy-creation branches are guarded by the v2 flag, so v1 keeps its historical eager-creation behavior.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

Start the interactive TUI session-less under the v2 engine and create the
session on first use (message, bash input, or a session-requiring slash
command) instead of at startup. Skills and plugin commands are resolved
from the workspace/app-global catalogs without a session, and the footer
shows config defaults (model, permission, plan mode, thinking effort,
context cap) until the session exists.
@changeset-bot

changeset-bot Bot commented Jul 31, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: c7392b6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 31, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@c7392b6
npx https://pkg.pr.new/@moonshot-ai/kimi-code@c7392b6

commit: c7392b6

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d3755653bd

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/kimi-code/src/tui/kimi-tui.ts
Comment thread apps/kimi-code/src/tui/kimi-tui.ts
…king

Concurrent first-use triggers (double Enter, a slash command right after a
prompt) both observed `session === undefined` and created their own
session, letting the later setSession close the first one mid-dispatch.
Share an in-flight creation promise instead.

A session-only thinking choice (model picker Alt+S) made before the first
session exists only updated appState, so the lazy-created session fell back
to the engine default while the footer showed the chosen effort. Carry it
as a first-session thinking override and clear it on creation.
@liruifengv

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 79fe2a18cb

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/kimi-code/src/tui/kimi-tui.ts
The v2 engine applies config.defaultPlanMode at session create time
(sessionLifecycleService), so passing the pre-filled appState.planMode as
the create override entered plan mode twice and threw 'Already in plan
mode' on the first message. Pass only the explicit CLI --plan intent for
session-less v2 creation; the config default stays footer-only.
@liruifengv

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cd52d72a04

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/kimi-code/src/tui/kimi-tui.ts
Comment thread apps/kimi-code/src/tui/commands/dispatch.ts Outdated
…ings session-less

A bash command submitted while the first prompt is still being
lazy-created shared the in-flight creation promise but resumed past
handleUserInput's busy check, running runShellCommand concurrently with
the prompt. Re-check streamingPhase after the await and queue instead.

/settings is a local settings entry point: opening it must not require or
create a session, so it no longer triggers lazy creation; its
session-requiring sub-items keep their own errors.
@liruifengv

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2e21d4cfa3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/kimi-code/src/tui/commands/dispatch.ts
Comment thread apps/kimi-code/src/tui/commands/dispatch.ts Outdated
…ins session-free

A skill/plugin or idle-only slash command submitted while the first prompt
was still being lazy-created shared the in-flight creation promise but
resumed past the availability check resolved before the await, running
concurrently with the prompt's turn. Re-check the busy gate after the
shared await in the skill, plugin-command and builtin dispatch paths.

/plugins is app-global on the v2 engine, so a session-less startup no
longer creates a session (or fails with LLM-not-set) just to manage
plugins: the harness now exposes the global plugin API and the command
routes through it until a session exists.
@liruifengv

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c5e87a1ccd

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/kimi-code/src/tui/commands/dispatch.ts Outdated
The bare and `list` forms already tolerate a missing session, but the
blanket lazy-create gate forced a session (or failed with LLM-not-set)
before they could run. Only the path-adding form needs a live session, so
it now lazy-creates inside the handler instead of in the dispatch
preflight.
@liruifengv

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c7392b65bf

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +9 to 12
let session = host.session;

if (input.length === 0 || input.toLowerCase() === 'list') {
const additionalDirs = session?.summary?.additionalDirs ?? [];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use pending dirs when listing before lazy session

When v2 starts session-less and startupInput.additionalDirs is already populated, host.session is still undefined but appState.additionalDirs contains the directories that will be passed into the lazy-created session. This read-only branch only looks at session?.summary, so /add-dir or /add-dir list incorrectly reports that no additional directories are configured until some other action creates the session; fall back to the app state when there is no active session.

Useful? React with 👍 / 👎.

Comment on lines 594 to 598
async function reloadPlugins(host: SlashCommandHost): Promise<void> {
const summary = await host.requireSession().reloadPlugins();
const summary = await (await resolvePluginApi(host)).reloadPlugins();
const line = `Reload: +${summary.added.length} -${summary.removed.length}` +
(summary.errors.length > 0 ? ` (${summary.errors.length} errors)` : '');
host.showStatus(line);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Refresh plugin slash commands after global reloads

When /plugins reload runs before the first v2 session exists, this now reloads the app-global plugin service, but the TUI's pluginCommandMap is still the snapshot fetched at startup and is not rebuilt here. Any newly added or enabled plugin slash command continues to be parsed as a normal prompt until a session is created or the TUI restarts, so the sessionless reload path does not actually apply command changes in the current UI.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant