v2.0.2
Co-Authored-By: Vincent Guilloux <vincent.guilloux@mistral.ai> Co-Authored-By: Clément Siriex <clement.sirieix@mistral.ai> Co-Authored-By: Kim-Adeline Miguel <kimadeline.miguel@mistral.ai>
This commit is contained in:
parent
bd3497b1c0
commit
9809cfc831
32 changed files with 622 additions and 305 deletions
|
|
@ -12,7 +12,7 @@ from vibe.core.config import (
|
|||
MissingAPIKeyError,
|
||||
MissingPromptFileError,
|
||||
VibeConfig,
|
||||
load_api_keys_from_env,
|
||||
load_dotenv_values,
|
||||
)
|
||||
from vibe.core.paths.config_paths import CONFIG_FILE, HISTORY_FILE
|
||||
from vibe.core.programmatic import run_programmatic
|
||||
|
|
@ -122,7 +122,7 @@ def _load_messages_from_previous_session(
|
|||
|
||||
|
||||
def run_cli(args: argparse.Namespace) -> None:
|
||||
load_api_keys_from_env()
|
||||
load_dotenv_values()
|
||||
bootstrap_config_files()
|
||||
|
||||
if args.setup:
|
||||
|
|
|
|||
|
|
@ -29,28 +29,36 @@ ACTION_TO_URL: dict[PlanOfferAction, str] = {
|
|||
}
|
||||
|
||||
|
||||
class PlanType(StrEnum):
|
||||
FREE = "free"
|
||||
PRO = "pro"
|
||||
UNKNOWN = "unknown"
|
||||
|
||||
|
||||
async def decide_plan_offer(
|
||||
api_key: str | None, gateway: WhoAmIGateway
|
||||
) -> PlanOfferAction:
|
||||
) -> tuple[PlanOfferAction, PlanType]:
|
||||
if not api_key:
|
||||
return PlanOfferAction.UPGRADE
|
||||
return PlanOfferAction.UPGRADE, PlanType.FREE
|
||||
try:
|
||||
response = await gateway.whoami(api_key)
|
||||
except WhoAmIGatewayUnauthorized:
|
||||
return PlanOfferAction.UPGRADE
|
||||
return PlanOfferAction.UPGRADE, PlanType.FREE
|
||||
except WhoAmIGatewayError:
|
||||
logger.warning("Failed to fetch plan status.", exc_info=True)
|
||||
return PlanOfferAction.NONE
|
||||
return _action_from_response(response)
|
||||
return PlanOfferAction.NONE, PlanType.UNKNOWN
|
||||
return _action_and_plan_from_response(response)
|
||||
|
||||
|
||||
def _action_from_response(response: WhoAmIResponse) -> PlanOfferAction:
|
||||
def _action_and_plan_from_response(
|
||||
response: WhoAmIResponse,
|
||||
) -> tuple[PlanOfferAction, PlanType]:
|
||||
match response:
|
||||
case WhoAmIResponse(is_pro_plan=True):
|
||||
return PlanOfferAction.NONE
|
||||
return PlanOfferAction.NONE, PlanType.PRO
|
||||
case WhoAmIResponse(prompt_switching_to_pro_plan=True):
|
||||
return PlanOfferAction.SWITCH_TO_PRO_KEY
|
||||
return PlanOfferAction.SWITCH_TO_PRO_KEY, PlanType.PRO
|
||||
case WhoAmIResponse(advertise_pro_plan=True):
|
||||
return PlanOfferAction.UPGRADE
|
||||
return PlanOfferAction.UPGRADE, PlanType.FREE
|
||||
case _:
|
||||
return PlanOfferAction.NONE
|
||||
return PlanOfferAction.NONE, PlanType.UNKNOWN
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ from vibe.cli.plan_offer.adapters.http_whoami_gateway import HttpWhoAmIGateway
|
|||
from vibe.cli.plan_offer.decide_plan_offer import (
|
||||
ACTION_TO_URL,
|
||||
PlanOfferAction,
|
||||
PlanType,
|
||||
decide_plan_offer,
|
||||
)
|
||||
from vibe.cli.plan_offer.ports.whoami_gateway import WhoAmIGateway
|
||||
|
|
@ -74,12 +75,19 @@ from vibe.core.agents import AgentProfile
|
|||
from vibe.core.autocompletion.path_prompt_adapter import render_path_prompt
|
||||
from vibe.core.config import VibeConfig
|
||||
from vibe.core.paths.config_paths import HISTORY_FILE
|
||||
from vibe.core.session.session_loader import SessionLoader
|
||||
from vibe.core.tools.base import ToolPermission
|
||||
from vibe.core.tools.builtins.ask_user_question import (
|
||||
AskUserQuestionArgs,
|
||||
AskUserQuestionResult,
|
||||
)
|
||||
from vibe.core.types import AgentStats, ApprovalResponse, LLMMessage, Role
|
||||
from vibe.core.types import (
|
||||
AgentStats,
|
||||
ApprovalResponse,
|
||||
LLMMessage,
|
||||
RateLimitError,
|
||||
Role,
|
||||
)
|
||||
from vibe.core.utils import (
|
||||
CancellationReason,
|
||||
get_user_cancellation_message,
|
||||
|
|
@ -594,8 +602,16 @@ class VibeApp(App): # noqa: PLR0904
|
|||
await self._loading_widget.remove()
|
||||
if self.event_handler:
|
||||
self.event_handler.stop_current_tool_call()
|
||||
|
||||
message = str(e)
|
||||
if isinstance(e, RateLimitError):
|
||||
if self.plan_type == PlanType.FREE:
|
||||
message = "Rate limits exceeded. Please wait a moment before trying again, or upgrade to Pro for higher rate limits and uninterrupted access."
|
||||
else:
|
||||
message = "Rate limits exceeded. Please wait a moment before trying again."
|
||||
|
||||
await self._mount_and_scroll(
|
||||
ErrorMessage(str(e), collapsed=self._tools_collapsed)
|
||||
ErrorMessage(message, collapsed=self._tools_collapsed)
|
||||
)
|
||||
finally:
|
||||
self._agent_running = False
|
||||
|
|
@ -773,6 +789,12 @@ class VibeApp(App): # noqa: PLR0904
|
|||
return None
|
||||
if not self.agent_loop.session_logger.session_id:
|
||||
return None
|
||||
session_config = self.agent_loop.session_logger.session_config
|
||||
session_path = SessionLoader.does_session_exist(
|
||||
self.agent_loop.session_logger.session_id, session_config
|
||||
)
|
||||
if session_path is None:
|
||||
return None
|
||||
return self.agent_loop.session_logger.session_id[:8]
|
||||
|
||||
async def _exit_app(self) -> None:
|
||||
|
|
@ -1023,7 +1045,8 @@ class VibeApp(App): # noqa: PLR0904
|
|||
async def _maybe_show_plan_offer(self) -> None:
|
||||
if self._plan_offer_shown:
|
||||
return
|
||||
action = await self._resolve_plan_offer_action()
|
||||
action, plan_type = await self._resolve_plan_offer_action()
|
||||
self.plan_type = plan_type
|
||||
if action is PlanOfferAction.NONE:
|
||||
return
|
||||
url = ACTION_TO_URL[action]
|
||||
|
|
@ -1035,12 +1058,12 @@ class VibeApp(App): # noqa: PLR0904
|
|||
await self._mount_and_scroll(PlanOfferMessage(text))
|
||||
self._plan_offer_shown = True
|
||||
|
||||
async def _resolve_plan_offer_action(self) -> PlanOfferAction:
|
||||
async def _resolve_plan_offer_action(self) -> tuple[PlanOfferAction, PlanType]:
|
||||
try:
|
||||
active_model = self.config.get_active_model()
|
||||
provider = self.config.get_provider_for_model(active_model)
|
||||
except ValueError:
|
||||
return PlanOfferAction.NONE
|
||||
return PlanOfferAction.NONE, PlanType.UNKNOWN
|
||||
|
||||
api_key_env = provider.api_key_env_var
|
||||
api_key = getenv(api_key_env) if api_key_env else None
|
||||
|
|
@ -1051,7 +1074,7 @@ class VibeApp(App): # noqa: PLR0904
|
|||
logger.warning(
|
||||
"Plan-offer check failed (%s).", type(exc).__name__, exc_info=True
|
||||
)
|
||||
return PlanOfferAction.NONE
|
||||
return PlanOfferAction.NONE, PlanType.UNKNOWN
|
||||
|
||||
async def _finalize_current_streaming_message(self) -> None:
|
||||
if self._current_streaming_reasoning is not None:
|
||||
|
|
|
|||
|
|
@ -949,21 +949,24 @@ WelcomeBanner {
|
|||
.whats-new-message {
|
||||
background: $surface;
|
||||
border-left: solid $warning;
|
||||
margin-bottom: 1;
|
||||
}
|
||||
|
||||
.plan-offer-message {
|
||||
background: $surface;
|
||||
border-left: solid $warning;
|
||||
background: transparent;
|
||||
border: none;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
content-align: center middle;
|
||||
padding: 1 2;
|
||||
margin-top: 1;
|
||||
padding: 0;
|
||||
margin-top: 0;
|
||||
color: $foreground-muted;
|
||||
text-style: dim;
|
||||
|
||||
Markdown > *:last-child {
|
||||
margin-bottom: 0;
|
||||
link-style: bold underline;
|
||||
link-style: none;
|
||||
link-color: $foreground-muted;
|
||||
link-background-hover: transparent;
|
||||
link-style-hover: underline;
|
||||
link-color-hover: $warning;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue