تصور کنید یک برنامهنویس اسکریپتی را برای خودکارسازی تغییرات کد مینویسد، اما عامل هوش مصنوعی بهجای اجرای دستور، در سکوتی مطلق متوقف میشود. این اتفاق دقیقاً همان جایی است که یک تفاوت فنی کوچک در محیط ترمینال، سرنوشت اجرای کد شما را تعیین میکند.
طبق بررسیهای فنی، در نسخه ۰.۶۳ ابزار Gemini CLI، به محض اینکه ابزار تشخیص دهد در یک ترمینال تعاملی (TTY) اجرا میشود، ۱۲۳۱ کاراکتر اضافی به پرامپت سیستمی (System Prompt) — دستورالعملهای بنیادینی که رفتار مدل را تعریف میکنند — تزریق میشود. این گیت منطقی پنهان تعیین میکند که عامل (Agent) — سیستمی که میتواند برای رسیدن به هدف، بهطور مستقل تصمیم بگیرد و ابزارها را فراخوانی کند — بهصورت خودکار عمل کند یا بر اساس یک جزئیات فنی ساده از نوع ترمینال شما، صراحتاً دستور بگیرد که متوقف شود و منتظر تایید انسانی بماند.
این رفتار به عنوان راهکاری برای رفع مشکل شماره ۲۸۹۱۳ (Issue #28913) ارائه شده است؛ وضعیتی که در آن عاملها در اسکریپتهای غیرتعاملی به اشتباه وارد «حالت برنامهریزی» (Plan Mode) میشدند و سپس بدون هیچ خطایی بسته میشدند. در این حالت هیچ کرشی (Crash) رخ نمیداد؛ مدل صرفاً یک پاراگراف متن تولید میکرد، هیچ ابزاری را فراخوانی نمیکرد و پردازش به سادگی خاتمه مییافت. دلیل این اتفاق این بود که در حالت غیرتعاملی، هر پاسخی که فقط شامل متن باشد، به عنوان سیگنال پایان پردازش تلقی میشود. بنابراین وقتی مدل با لحنی مودبانه از کاربر اجازه میگرفت، CLI این سکوت را به عنوان پایان فرآیند تفسیر میکرد.
همانطور که در تحلیل قبلی ما دربارهی Gemini 4 Argon و اکوسیستم گستردهتر مدلهای گوگل اشاره کردیم، این بهروزرسانی نشان میدهد که مرز بین پرامپتنویسی LLM و اجرای محیط شل (Shell) چقدر شکننده است. برای توسعهدهندگان، تفاوت بین یک خط لوله CI/CD موفق و یک پردازش متوقفشده، اکنون به نحوه ایجاد (Spawn) شدن آن پردازش وابسته است. این حساسیتها یادآور چالشهای اتصال Gemini به Claude Code است که در آن تداخلهای لایههای ارتباطی منجر به شکستهای بحرانی میشد.
واگرایی پرامپتها
برای تحلیل این موضوع، CLI به یک سرور HTTP محلی (Mock Server) متصل شد. با رصد systemInstruction ارسالی به مدل gemini-3.1-pro-preview-customtools:streamGenerateContent و در حالی که تنظیمات روی --approval-mode plan بود، تحلیل فنی نشان داد که برای یک فایل باینری یکسان، دو دستورالعمل سیستمی کاملاً متفاوت ارسال میشد:
- حالت غیرتعاملی (بدون TTY): ۲۹,۱۳۹ کاراکتر. هدف در اینجا «ایجاد یک سند طراحی پیش از پیشروی بهصورت خودکار» است.
- حالت تعاملی (داخل PTY): ۳۰,۳۷۰ کاراکتر. هدف در اینجا به «دریافت تایید کاربر پیش از ویرایش کد منبع» تغییر میکند.

متدولوژی استخراج
این تحلیل بدون نیاز به کلید API واقعی و با تغییر GOOGLE_GEMINI_BASE_URL به یک سرور محلی که بدنه درخواستها را Dump میکند، تایید شد. دو اجرای متفاوت به شرح زیر صورت گرفت:
- اجرای اول (بدون TTY): دستور
gemini -p "Plan a small refactor of this repo" --approval-mode plan --skip-trustاجرا شد. - اجرای دوم (با PTY): از دستور
script -qec "gemini -i 'Plan a small refactor of this repo' --approval-mode plan --skip-trust" /dev/nullاستفاده شد.
استفاده از دستور script -qec ترفند کلیدی در اینجا است؛ این دستور یک pty تخصیص میدهد و CLI را فریب میدهد تا تصور کند در محیطی تعاملی است و در نتیجه پرامپت بزرگتر را فعال میکند.
سازوکار اصلاح خطا
این واگرایی در تابع renderPlanningWorkflow() در مسیر packages/core/src/prompts/snippets.ts رخ میدهد. ابزار بر اساس پرچم options.interactive مسیر خود را تغییر داده و قوانین عملیاتی عامل را تغییر میدهد. این ساختار پیچیده از مدیریت دستورات، بسیار شبیه به نحوه کنترل سرورها از طریق لایه MCP در Gemini CLI است که لایههای انتزاعی را برای مدیریت ابزارها به کار میگیرد:
- منطق گام ۲:
- در حالت غیرتعاملی: عنوان بخش «### 2. Determine Strategy» است. بدنه دستور میدهد: «شما بهصورت غیرتعاملی در حال اجرا هستید، مستقیماً به گام ۳ (پیشنویس) بروید و بهطور خودکار بدون توقف یا انتظار برای تایید کاربر پیش بروید.»
- در حالت تعاملی: عنوان بخش «### 2. Consult» است. بدنه دستور میدهد که مدل باید «متوقف شود و منتظر بماند تا کاربر موافقت خود را پیش از تدوین برنامه تایید کند.»
- گام ۳ (بررسی همراستاسازی): این بخش در پرامپت غیرتعاملی بهطور کامل حذف شده است. در حالت تعاملی، این بخش وجود دارد و به عامل دستور میدهد پیشنویس را ارائه کرده و «درخواست بازخورد یا تایید» کند.
- منطق گام ۴:
- در حالت غیرتعاملی: به مدل دستور میدهد: «از ابزار داخلی
exit_plan_modeبرای نهایی کردن برنامه استفاده کنید... هنگام فراخوانی، این ابزار برنامه را ارائه کرده و پیادهسازی را آغاز میکند.» - در حالت تعاملی: به عامل دستور میدهد: «تنها زمانی از ابزار داخلی
exit_plan_modeاستفاده کنید... که به یک توافق غیررسمی رسیده باشید.»
- در حالت غیرتعاملی: به مدل دستور میدهد: «از ابزار داخلی
- قوانین تحویل (Handoff):
- در حالت غیرتعاملی: «برای دستورات (Directives)، باید بهطور خودکار عمل کنید زیرا هیچ ورودی دیگری از کاربر در دسترس نیست.»
- در حالت تعاملی: «برای دستورات، تنها در صورتی که جزئیات بهطور بحرانی ناقص باشد شفافسازی کنید؛ در غیر این صورت، بهطور خودکار عمل کنید.»
- دسترسی به ابزارها: پرامپت تعاملی شامل ۱۳ ابزار در جدول خود است، در حالی که نسخه غیرتعاملی تنها ۱۰ ابزار دارد. ابزارهای اضافی عبارتند از:
activate_skill،ask_userوweb_fetch. همچنین در پرامپت غیرتعاملی، هرگونه اشاره بهask_userدر قوانین مربوط به دستورات شل حذف شده است.
جمله مرگبار
در پرامپت تعاملی یک محدودیت حیاتی وجود دارد: «بسیار مهم: شما نباید در همان نوبتی که استراتژی اولیه را پیشنهاد میدهید، به گام ۳ (پیشنویس) یا گام ۴ (بررسی و تایید) بروید. شما باید منتظر بازخورد کاربر بمانید.»
این خط خاص، در ترکیب با تمایل CLI به بستن پردازش در پاسخهای متنی، ریشه اصلی مشکل شماره ۲۸۹۱۳ بود. از آنجایی که ابزار ask_user در جلسات بدون رابط کاربری (Headless) بهطور کلی رد میشود، رفتار مسدودکننده هرگز از طریق یک فراخوانی ابزار (Tool Call) اتفاق نمیافتاد، بلکه از طریق یک پاسخ متنی ساده رخ میداد که هیچ مکانیزمی آن را متوقف نمیکرد و باعث میشد پردازش بلافاصله خاتمه یابد.
تلههای CI/CD برای توسعهدهندگان
این موضوع یک «لبه تیز» برای هر کسی است که در حال نوشتن اسکریپت برای این ابزار است. فراخوانیهای استاندارد مانند gemini -p "..." یا انتقال ورودی از طریق echo "..." | gemini باعث فعال شدن پرامپت خودکار میشود. اما هر پوششی (Wrapper) که یک ترمینال مجازی (pty) تخصیص دهد — مانند script ،pty.fork() ،expect یا docker run -it — پرامپت تعاملی را فعال میکند.
اگر از این پوششها در یک محیط بدون کاربر (Headless) استفاده کنید، عامل دستوراتی را دریافت میکند که او را مجبور میکند منتظر انسانی بماند که در آنجا حضور ندارد. در نتیجه، پردازش یا زودتر از موعد بسته میشود یا به حالت تعلیق (Hang) میرود؛ یعنی دقیقاً همان باگی که نسخه ۰.۶۳ قصد حل آن را داشت. این موضوع توسط بررسی بسته ارسالی در @google/[email protected] تایید شده است، جایی که هر دو نسخه پرامپت در بایتهای کد موجود هستند. این تغییرات در لایههای پنهان، یادآور بهروزرسانیهای خاموش مدلهاست که میتواند بدون اطلاع توسعهدهنده، پایداری پرامپتهای از پیش تستشده را به خطر بیندازد.
نکات پیادهسازی
برای کسانی که قصد بازتولید این تحلیل را دارند، باید از دو تله آگاه باشند:
۱. تنظیمات احراز هویت: داشتن GEMINI_API_KEY به تنهایی کافی نیست. CLI نیاز دارد که security.auth.selectedType در فایل settings.json روی یک متد معتبر مانند gemini-api-key ،oauth-personal ،compute-default-credentials یا vertex-ai تنظیم شده باشد. استفاده از مقدار "gateway" منجر به کد خروجی ۴۱ میشود.
۲. حالت YOLO: هنگام استخراج پرامپتها از سوئیچ -y استفاده نکنید. حالت YOLO یک فراخوانی جداگانه به مدل gemini-3.5-flash-lite برای امتیازدهی پیچیدگی از طریق یک «هوش مصنوعی مسیریاب وظایف» (Task Routing AI) پیش از درخواست اصلی ایجاد میکند که میتواند باعث شود سرورهای Mock متوقف شوند یا بهطور نامحدود تلاش به اتصال (Retry) کنند.
این تغییر ثابت میکند که «شخصیت» و میزان استقلال یک عامل، صرفاً ویژگیهای سمت مدل نیستند، بلکه بهطور پویا توسط CLI و بر اساس محیط اجرا ساخته میشوند. این امر بار مسئولیت پایداری را از استدلال مدل به پیکربندی محیط توسعهدهنده منتقل میکند. اگر Runner بدون رابط کاربری شما در وظایف برنامهریزی شکست میخورد، پیش از بررسی پرامپتها، تخصیص TTY خود را بررسی کنید.
گام بعدی شما
- اگر در محیطهای CI/CD با توقفهای ناگهانی Gemini CLI مواجه شدید، نحوه تخصیص TTY در Runner خود را بررسی کنید.
- برای اطمینان از اجرای خودکار، از محیطهای بدون PTY استفاده کنید یا پرچمهای تعاملی را غیرفعال نمایید.
- در صورت نیاز به تحلیل پرامپتهای ارسالی، از یک سرور Mock برای رصد
systemInstructionاستفاده کنید.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو