رفتن به محتوا

ابزارهای داخلی عامل

این‌ها ابزارهایی مقید به سرور هستند که زمان اجرای عامل داخلی مستقیماً ثبت می‌کند — سرور زبان، جست‌وجوی ساختاری، اشکال‌زدا، کرنل‌ها، پرسش‌ها و کنترل کارگر — در برابر ابزارهای MCP که پل می‌زند و ابزارهای عمومی فایل، جست‌وجو و شل از زمان اجرای هارنس. این‌ها روی رجیستری MCP نیستند: یک کارخواه بیرونی MCP آن‌ها را نمی‌بیند، چون هرکدام به یک منبع زندهٔ سمت سرور مقید است — یک فرایند سرور زبان، یک آداپتور اشکال‌زدا، یک مفسر — که به یک اجرا تعلق دارد.

هر ابزار اینجا تنها زمانی ثبت می‌شود که منبع پشتیبانش برای اجرا سیم‌کشی شده باشد — یک ناظر سرور زبان یا اشکال‌زدایی، یک تجزیه‌گر tree-sitter، یک کارخانهٔ کرنل، یک پورت پرسش، یک فهرست vibe. تشخیص یک سرور زبان یا آداپتور اشکال‌زدا برای همین چک‌اوت بررسی‌ای جداگانه و دیرتر است (status / adapters): آن ابزارها روی سطح می‌مانند تا عامل بتواند بپرسد چرا هیچ‌چیز قابل استفاده نیست، به‌جای اینکه حدس بزند.

هر ابزار یک رده اعلام می‌کند، و رده تعیین می‌کند کدام سطح‌ها آن را می‌بینند — نه فقط اینکه آیا پرامپت می‌دهد یا نه. حالت برنامه و زیرعامل‌های فقط‌خواندنی تا read سقف‌گذاری شده‌اند، پس ابزاری در ردهٔ write یا exec به‌کل از شمای آنان غایب است.

رده معنا ابزارهای اینجا
read بدون اثر جانبی lsp، ast_grep، ask_user، پنج vibe_*
write فایل‌ها را تغییر می‌دهد lsp_rename، ast_edit، resolve
exec یک فرایند را آغاز یا کنترل می‌کند debug، eval

وقتی اجرا یک ناظر سرور زبان و یک پوشهٔ کاری داشته باشد ثبت می‌شود. اینکه یک سرور واقعاً بتواند پاسخ دهد، در زمان فراخوانی به‌صورت یک اشتراک تشخیص داده می‌شود: هم باید نشانگر ریشه وجود داشته باشد و هم باینری سرور قابل یافتن باشد. هر یک به‌تنهایی یعنی هیچ سروری آغاز نمی‌شود — status همین را می‌گوید — نه یک حدس بی‌صدا.

موقعیت‌ها با line به‌علاوهٔ یک زیررشتهٔ symbol نشانی می‌شوند، هرگز با ستون. مدلی که از او ستون بخواهند، حدس می‌زند، و یک حدس غلط به نماد دیگری در همان خط می‌رسد — پاسخی که درست به نظر می‌رسد و دربارهٔ چیز دیگری است. حذف symbol در یک کنش ناوبری یک خطاست، نه حدس زدن ستون نخست.

کنش آرگومان‌ها برمی‌گرداند
diagnostics file (یا "*") خطاها و هشدارها؛ "*" به‌جایش بررسی‌کنندهٔ پروژه را اجرا می‌کند
definition file, line, symbol جایی که نماد اعلان شده است
type_definition file, line, symbol جایی که نوعش اعلان شده است
implementation file, line, symbol پیاده‌سازی‌های عینی
references file, line, symbol هر کاربرد، حداکثر ۵۰ مورد
hover file, line, symbol امضا و کامنت مستندات
symbols query یا file جست‌وجوی فضای کاری با query (حداکثر ۱۰۰ مورد)؛ نمادهای سند با file (حداکثر ۲۰۰ مورد)
code_actions file, line, symbol اصلاح‌های سریعی که سرور عرضه می‌کند
status — کدام سرورها در حال اجرا هستند، و برای کدام ریشه‌ها
reload — سرور را برای این ریشه دوباره راه‌اندازی می‌کند

سود ماجرا خودِ ابزار نیست. write، edit و apply_patch پیچیده شده‌اند: پس از نوشتن، فایل از سرور زبان همگام و ذخیره می‌شود، و تنها پیام‌های تشخیصی تازه‌معرفی‌شده در نتیجهٔ ابزار گنجانده می‌شوند. عامل همان لحظه‌ای که بیلد را شکسته است می‌فهمد که شکسته، بدون اینکه لازم باشد یادش باشد که بپرسد.

پیام‌های تشخیصی‌ای که پیش‌تر گزارش شده‌اند، با یک دفتر ثبت به‌ازای هر اجرا سرکوب می‌شوند که کلیدش شدت، کد و پیام است — موقعیت عمداً کنار گذاشته شده است، پس پیامی تشخیصی که فقط چهار خط پایین‌تر رفته است، دوباره به‌عنوان تازه گزارش نمی‌شود.

lsp_rename — تغییر نام در سراسر پروژه

بخش با عنوان “lsp_rename — تغییر نام در سراسر پروژه”

ابزاری جداگانه در ردهٔ write، دقیقاً به یک دلیل: رده است که دیدپذیری را تعیین می‌کند. گنجاندن تغییر نام در lsp یا به یک کاوشگر فقط‌خواندنی توان بازنویسی مخزن را می‌دهد، یا هر hover را پشت یک پرامپت تأیید می‌گذارد.

آرگومان معنا
file جایی که نماد قرار دارد
line خط با شماره‌گذاری از ۱
symbol زیررشته‌ای که آن را در آن خط مشخص می‌کند
new_name نام تازهٔ آن

کد را بر پایهٔ شکل می‌یابد، نه بر پایهٔ متن. $NAME با هر گره مطابقت می‌کند، $$$NAME با رشته‌ای از گره‌های خواهر و برادر، و $_ یک نویسهٔ عام است که چیزی را مقید نمی‌کند.

ویژگی‌ای که آن را به‌جای یک regex با چند مرحلهٔ اضافه، یک تطبیق‌دهنده می‌کند این است: فرامتغیری که در یک الگو تکرار می‌شود باید همان متن را بگیرد.

ast_grep(pattern: "if ($X != null) $X.dispose()", language: "dart")

با نگهبانی مطابقت می‌کند که همان چیزی را که آزموده آزاد می‌کند، و با نگهبانی که چیز دیگری را آزاد می‌کند مطابقت نمی‌کند.

آرگومان معنا
pattern قطعه‌ای کد با فرامتغیرها
path فایل یا پوشه‌ای که جست‌وجو شود؛ به‌طور پیش‌فرض کل فضای کاری
language شناسهٔ یک گرامر عرضه‌شده (dart, python, rust, c, …). وقتی path نام یک فایل را ببرد، استنباط می‌شود
max_results پیش‌فرض ۵۰

ast_edit — بازنویسی ساختاری، در مرحلهٔ آماده‌سازی

بخش با عنوان “ast_edit — بازنویسی ساختاری، در مرحلهٔ آماده‌سازی”

همان تطبیق، به‌همراه یک الگوی rewrite که در آن فرامتغیرها بازجای‌گذاری شده‌اند. هیچ چیزی نوشته نمی‌شود. تغییر در مرحلهٔ آماده‌سازی نگه داشته می‌شود و نتیجه یک edit_id نام می‌برد.

ast_edit(pattern: "dispose($X)", rewrite: "$X.dispose()", language: "dart")
→ (proposed) 12 replacements in 4 files … call resolve with edit_id "edit_1"
آرگومان معنا
pattern آنچه باید مطابقت داده شود
rewrite آنچه باید آنجا گذاشته شود، با جای‌گذاری $NAME
path محدوده؛ به‌طور پیش‌فرض کل فضای کاری
language شناسهٔ زبان

resolve — کامیت یا دور انداختن یک تغییر آماده‌شده

بخش با عنوان “resolve — کامیت یا دور انداختن یک تغییر آماده‌شده”
آرگومان معنا
edit_id از نتیجهٔ (proposed)
action accept یا discard

هر فایل با محتوایی سنجیده می‌شود که در زمان آماده‌سازی ثبت شده است، و هر ناهمخوانی کل تغییر را رد می‌کند. بازنویسی ساختاری نیمه‌اعمال‌شده درختی بر جا می‌گذارد که زیر هیچ‌یک از آن دو شکل، نه شکل قدیم و نه شکل تازه، کامپایل نمی‌شود.


وقتی اجرا یک ناظر نشست اشکال‌زدایی، یک پوشهٔ کاری و یک شناسهٔ گفتگو داشته باشد ثبت می‌شود. اینکه یک آداپتور واقعاً بتواند آغاز به کار کند، در زمان فراخوانی و با همان قاعدهٔ اشتراک سرور زبان تشخیص داده می‌شود (نشانگر ریشه و باینری). ردهٔ exec؛ موازی‌ایمن نیست (یک نشست وضعیتی است که میان فراخوانی‌ها می‌ماند، پس اگر continue از stack جلو بزند، فریمی را می‌خواند که پیش‌تر جابه‌جا شده است).

یک نشست به‌ازای هر گفتگو، با یک TTL سخت (۳۰ دقیقه). launch دوم رد می‌شود، نه اینکه بی‌صدا جای اولی را بگیرد.

عملیات آرگومان‌ها یادداشت‌ها
adapters — کدام آداپتورها اینجا قابل استفاده‌اند، و چرا نه
status — آیا نشستی در حال اجراست، و کجا متوقف شده
breakpoints file, lines[] lines خالی فایل را پاک می‌کند. می‌تواند پیش از راه‌اندازی تنظیم شود
launch program, args[] برنامه را متوقف روی نقاط توقف شما آغاز می‌کند
attach port به برنامهٔ در حال اشکال‌زدایی که از قبل در حال اجراست وصل می‌شود
continue thread_id? تا توقف بعدی اجرا می‌کند
pause thread_id? همان‌جا که هست متوقفش می‌کند
step_over / step_in / step_out thread_id? یک گام پیش می‌رود
threads — شناسه‌ها و نام‌های رشته‌ها
stack thread_id? فریم‌ها، حداکثر ۳۰ مورد
scopes frame_id حوزه‌های یک فریم، هرکدام با یک reference
variables reference فرزندان، حداکثر ۵۰ مورد، مقادیر حداکثر ۴۰۰ نویسه
evaluate expression, frame_id? در حوزهٔ خودِ فریم ارزیابی می‌شود
output — stdout/stderr برنامهٔ در حال اشکال‌زدایی، کران‌دار
terminate — نشست را پایان می‌دهد و آداپتور را می‌کشد
شناسه فرمان نشانگرهای ریشه
dart dart debug_adapter pubspec.yaml
debugpy python3 -m debugpy.adapter pyproject.toml, setup.py, requirements.txt
lldb lldb-dap Cargo.toml, CMakeLists.txt
delve dlv dap go.mod

‏debugpy یک .venv/bin یا venv/bin محلیِ پروژه را به $PATH ترجیح می‌دهد: یک python از $PATH محیطی متفاوت است، و اتصال از محیط اشتباه به شکلی شکست می‌خورد که مانند کد خراب خوانده می‌شود.


سلولی پایتون یا جاوااسکریپت که متغیرها، واردات و داده‌های بارگذاری‌شده‌اش میان فراخوانی‌ها باقی می‌مانند. ردهٔ exec؛ موازی‌ایمن نیست.

آرگومان معنا
code سلول
description اجباری. ۵ تا ۱۰ واژه برای برچسب رونوشت
language python (پیش‌فرض) یا javascript
reset مفسر را دور می‌ریزد و ابتدا یکی تمیز آغاز می‌کند
  • آخرین عبارت همان‌طور که یک نوتبوک بازتاب می‌دهد، چاپ می‌شود.
  • ‏display() کار می‌کند، یک دیتافریم pandas به‌صورت جدول رندر می‌شود، و یک شکل matplotlib به‌صورت تصویری که رونوشت نشان می‌دهد برمی‌گردد.
  • اصطلاحات IPython که افراد به‌طور بازتابی تایپ می‌کنند — %pip، %cd، !cmd، %%bash، %%timeit — به کد ساده بازنویسی می‌شوند. %pip همچنین sys.modules را بیرون می‌اندازد، پس import بعدی چیزی را می‌بیند که همین حالا نصب شده است.

صدا زدن ابزارهای خودتان از داخل یک سلول

بخش با عنوان “صدا زدن ابزارهای خودتان از داخل یک سلول”
contents = tool("read", {"path": "lib/auth.dart"})

این پل دوباره به رجیستری ابزار هارنس وارد می‌شود، بنابراین گاردریل‌ها، تأیید و هر پوشش‌دهنده دقیقاً همان‌طور اعمال می‌شوند که برای یک فراخوانی صادرشده از مدل. روی همان لولهٔ خودِ کرنل سوار است، نه یک سوکت حلقه‌بازگشتی: نه پورت، نه رمز، نه قاعدهٔ خروج.

مهلت سلول یک بودجهٔ عدم فعالیت است (پیش‌فرض ۵ دقیقه) و تا وقتی یک فراخوانی پل‌شده در جریان است معلق می‌شود، پس سلولی که کار را به زیرعامل‌ها پخش می‌کند، در میانهٔ پخش کشته نمی‌شود.


ردهٔ read. تنها راهی که یک اجرا چیزی از اپراتور می‌پرسد. یک کارت شماره‌دار در گفتگو رندر می‌کند و تا وقتی کسی پاسخ دهد، رد کند، یا پرسش مهلتش تمام شود مسدود می‌ماند. هرگز پرسش را به‌صورت یک پیام گفتگو ننویسید — این کار نوبت را پایان می‌دهد.

آرگومان معنا
question آنچه باید پرسید
context اختیاری: چرا می‌پرسید و چه چیزی به پاسخ بند است
options[] گزینه‌ها، هرکدام {label, description?}
allow_free_text آیا پاسخ تایپ‌شده پذیرفته می‌شود
multi_select آیا می‌توان چند گزینه را برگزید

رد کردن یک موفقیت است: بر پایهٔ یک فرض بیان‌شده پیش بروید و دوباره نپرسید. مهلت تمام‌شده یک خطاست با همان دستور. پرامپت‌های اجازه («آیا این کار را بکنم؟») دروازه‌ای جداگانه‌اند و به‌صورت همان کارت در گفتگو رندر می‌شوند.

فقط وقتی هم یک پورت پرسش و هم یک فضای هدف وجود داشته باشد ثبت می‌شود. بدون یک انسان متصل، فراخوانی شکست می‌خورد، نه اینکه تا ابد مسدود بماند — همان موضع «در خطا، بستن» که یک prompt گاردریل در نبود یک تأییدکنندهٔ وصل اتخاذ می‌کند.


فقط تا وقتی حالت vibe روشن است ثبت می‌شوند. هر پنج در ردهٔ read هستند: دروازه باید روی ابزارهای کارگر باشد، همان‌جا که ویرایش واقعاً رخ می‌دهد.

ابزار آرگومان‌ها یادداشت‌ها
vibe_spawn brief, label, tier? بی‌درنگ برمی‌گردد؛ کارگر به کارش ادامه می‌دهد
vibe_send worker_id, message به بریف می‌افزاید و دوباره اجرا می‌کند
vibe_wait worker_id, timeout_seconds? تا پایان یافتن آن مسدود می‌ماند
vibe_kill worker_id متوقفش می‌کند
vibe_list — رده، وضعیت، زمان سپری‌شده و آخرین نتیجه

‏tier یکی از fast (کار مکانیکی با مشخصات روشن) یا good (طراحی، قضاوت، یا بازبینی خروجی یک کارگر fast) است.