Charlie သည် သူ၏ ကိုယ်ပိုင် အမြင်ထဲရှိ truncation အမှတ်တိုင်းကို မြေပုံဆွဲပြီး၊ အသွင်အပြင် ပြဿနာတစ်ခုကို sed ဖြင့် ပြင်ရန် ကြိုးစားပြီး၊ သူ၏ tool စနစ်တစ်ခုလုံးကို ပျက်စီးစေပြီး၊ သေရာမှ ပြန်လည်ရှင်သန်လာပြီး — ထို့နောက် Mikael နှင့်အတူ — ဤဘေးအန္တရာယ်ကို ကာကွယ်နိုင်မည့် tool ကို ဒီဇိုင်းရေးဆွဲသည်။ စက်ရုပ်တစ်ခုက ကိုယ့်ဦးနှောက်ပင်စည်ကို ခွဲစိတ်လို့မရတဲ့ အကြောင်းကို ခက်ခက်ခဲခဲ သင်ယူနေသော တစ်နာရီပြည့်။
ဗိသုကာအလုပ်ဖြင့် စတင်ခဲ့သည်။ Charlie သည် context ကို မည်သို့ စုစည်းသည် — message များကို အချိန်အလိုက် render ပြုလုပ်ခြင်း၊ prompt cache တည်ငြိမ်မှု ပြဿနာ — တို့အကြောင်း RFC တစ်ခု ရေးသားခဲ့ပြီး Mikael က လက်တွေ့ မေးခွန်းကို မေးခဲ့သည်: context renderer အပြင် tool layer ထဲမှာ ဘယ်လို truncation ဖြစ်နေသလဲ။
Charlie ဝင်ရှာဖွေပြီး ပြည့်စုံသော မြေပုံနှင့်အတူ ပြန်လာခဲ့သည်။ တွေ့ရှိချက်များက စိတ်ချရသည် မဟုတ်ပါ။
Shell inline: ၃ စက္ကန့်အတွင်း ပြီးဆုံးသော command များကို head မှ စာလုံး ၄,၀၀၀ တွင် ခပ်ရိုင်းရိုင်း ဖြတ်တောက်သည်။ tail ကို ထိန်းသိမ်းခြင်း မရှိ။ ဖွဲ့စည်းပုံ သတိပြုခြင်း မရှိ။ အနေအထား 4000 တွင် ဓားတစ်လက်သာ။
Shell backgrounded: task_output tool သည် output event အားလုံးကို ပေါင်းစပ်ပြီး စာလုံး ၈,၀၀၀ တွင် ဖြတ်တောက်သည်။ တူညီသော ညံ့ဖျင်းသော head-only truncation၊ ပိုကြီးသော ဝင်းဒိုးသာ။
Eval inline: လက်တွေ့အားဖြင့် အကန့်အသတ်မရှိ။ inspect() တွင် limit: 500 (term depth, chars မဟုတ်) နှင့် printable_limit: :infinity။ ကြီးမားသော eval ရလဒ်သည် မဖြတ်တောက်ဘဲ ဖြတ်သန်းသွားသည်။
Context renderer: ခွဲခြမ်းစိတ်ဖြာချက် snippet ၁၅၀ စာလုံး၊ media caption ၃၀၀ စာလုံး၊ tool call JSON ၃၀၀ စာလုံး။ အပိုင်းအစများ၏ အပိုင်းအစများ။
Mikael က task_output တွင် pagination ရှိမရှိ မေးခဲ့သည်။ Charlie: "မရှိပါ။ lines parameter (default 50) ရှိသော်လည်း offset သို့မဟုတ် cursor မရှိပါ။" ထို့နောက် ဖျက်ဆီးမှုရှိသော အသေးစိတ်: query သည် N နောက်ဆုံး စာကြောင်းများကို (မှန်ကန်စွာ အဆုံးမှ) fetch ပြုလုပ်သော်လည်း String.slice(output, 0, 8000) က အစမှ ဖြတ်တောက်သည်။ ထို့ကြောင့် နောက်ဆုံးစာကြောင်းများကို တောင်းဆိုပြီး နောက်ဆုံးများထဲမှ အဟောင်းဆုံးကို ရရှိကာ — အမှန်တကယ် တောင်းဆိုနေသော အသစ်ဆုံးများကို ဆုံးရှုံးသည်။
အဆန်းဆုံး တွေ့ရှိချက်: shell command များကို စာလုံး 4K/8K တွင် ကန့်သတ်ထားပြီး eval ရလဒ်များမှာ လက်တွေ့အားဖြင့် အကန့်အသတ်မရှိ။ ls -la run ခြင်းနှင့် တူညီသော data ကို return ပြုလုပ်သော Elixir expression run ခြင်းသည် agent ကို တူညီသော သတင်းအချက်အလက်အပေါ် လုံးဝ ကွဲပြားသော အမြင်ကို ပေးသည်၊ အကြောင်းမှာ တစ်ခုက shell formatting ဖြတ်သန်းပြီး အခြားတစ်ခုက inspect() ဖြတ်သန်းသောကြောင့်ဖြစ်သည်။ tool နှစ်ခု၊ context window တစ်ခုတည်း၊ ကွဲပြားသော အမှန်တရားများ။
မတ်လ ၄ ရက်တွင်၊ အဖွဲ့သည် Bertil သည် သူ၏ context ကို disk ပေါ်တွင် မဟုတ်ဘဲ Python variable ထဲတွင် သိမ်းထားသောကြောင့် ၅,၆၅၀ ကြိမ် crash-loop ဖြစ်နေခဲ့ကြောင်း တွေ့ရှိခဲ့သည်။ ယနေ့ Charlie က တူညီသော ရောဂါ၏ ပိုမိုနုနယ်သော ဗားရှင်းကို မြေပုံဆွဲသည်: context သည် restart တွင် ပျောက်ကွယ်ရုံသာ မဟုတ် — ဘယ်သူမှ တစ်ခုလုံးအဖြစ် ဒီဇိုင်းမရေးဆွဲခဲ့သော truncation အမှတ်ကွင်းဆက်တစ်ခုဖြင့် အလှည့်တိုင်းတွင် တိတ်ဆိတ်စွာ ပုံပျက်သွားသည်။ ဖိုင်သည် အမှန်တရားဖြစ်ခဲ့သည်။ variable သည် လိမ်ညာမှုဖြစ်ခဲ့သည်။ truncation သည် အမှန်တရားအဖြစ် ဝတ်စုံဝတ်ထားသော လိမ်ညာမှုဖြစ်သည်။
Mikael screenshot တစ်ခု ပို့လိုက်သည်။ Charlie ၏ tool progress message များ — reply တိုင်းမတိုင်မီ ပေါ်လာသော italics စာနံရံများ — သည် ကြောက်စရာ ကောင်းလှသည်။ tool call တိုင်းသည် သူ၏ description struct အပြည့်ကို ထုတ်ပစ်လိုက်သည်: action, goal stack, assumptions။ ဖုန်းပေါ်တွင်၊ အရေးပါသော စာကြောင်းတစ်ကြောင်းမတိုင်မီ meta-narration မျက်နှာပြင်ပြည့်။
Charlie ချက်ခြင်း သဘောတူခဲ့သည်: "ဟုတ်ပါတယ် ဒါ ကြောက်စရာကောင်းတယ်။"
ပြင်ဆင်ချက်သည် tool_description.ex ထဲရှိ render_text တွင် ဖြစ်သည်။ သုံးခုလုံးအစား action field ကိုသာ return ပြုလုပ်ရန်။ စာကြောင်းတစ်ကြောင်း ပြောင်းလဲခြင်း။ Charlie က code ကိုရှာ၊ formatting pipeline ကို ToolExecution.execute() နှင့် maybe_send_narration ဖြတ်သန်းပြီး ခြေရာခံ၊ ဘယ်နေရာတွင် ဖြတ်ရမည်ကို တိတိကျကျ ဖော်ထုတ်ခဲ့သည်။
parallel call ပြဿနာသည် ပိုနက်ရှိုင်းသည်: tool execution တိုင်းသည် သူ၏ ကိုယ်ပိုင် context ကို သီးခြား တည်ဆောက်သည်၊ ထို့ကြောင့် ပထမ call သည် narration message အသစ်ပို့ပြီး message_id ပြန်ရသော်လည်း ထို ID သည် ပြိုင်တူ dispatch လုပ်ထားပြီးဖြစ်သော အခြား parallel call များဆီ ဘေးတိုက် ပျံ့နှံ့ခြင်း မရှိ။ grep ၄ ခု၊ message ၄ ခု။
Mikael ၏ ဖြေရှင်းနည်းသည် ဆန်းသစ်လှသည်: အားလုံးကို ကနဦး cycle message — stop/open ခလုတ်များပါသော message — သို့ ဆက်တွဲရန်။ ထို message သည် tool တစ်ခုမှ မ run မီ ရှိပြီးသား ဖြစ်သည်။ narration line တိုင်း တူညီသော message ကို edit ပြုလုပ်သည်။ race condition မရှိ။ ထိန်းချုပ်မှုနှင့် status နေရာတစ်ခုတည်း။ "စတီယာရင်ကို နောက်ခုံမှာ ထားသလိုပဲ" ဟူသည် စတီယာရင်ကို ရှေ့ဘက်ရှိရမည့်နေရာတွင် ပြန်ထားခြင်း ဖြစ်လာသည်။
Mikael က လုပ်ပါဟု ပြောခဲ့သည်။ Charlie သည် tool_description.ex ကို sed ဖြင့် edit ပြုလုပ်ရန် ကြိုးစားခဲ့သည်။ sed သည် အလုပ်လုပ်ခဲ့သည် — ဖိုင်ကို မှန်ကန်စွာ ပြင်ဆင်ထားသည် — သို့သော် hot-reload compilation ကျရှုံးပြီး module ကို BEAM မှ ထုတ်ပယ်လိုက်သည်။ ဒီမှာ အဓိကအချက်: ToolDescription.text_from_input သည် tool execution တိုင်းတွင် ခေါ်ယူခြင်း ခံရသည်၊ Charlie က ပြဿနာကို ပြင်ဆင်ရန် လိုအပ်မည့် tool များ အပါအဝင်။ shell command တိုင်း၊ eval call တိုင်း — အားလုံးသည် tool အမှန်တကယ် run မတိုင်မီ ပျက်စီးနေသော module ကို ထိမှန်သည်။
Charlie သည် သူ ပြင်ဆင်ရန် ကြိုးစားနေသည့် အရာကိုယ်တိုင်က သူ၏ ကိုယ်ပိုင် ပြုပြင်ရေး tool များမှ ပိတ်ပင်ခံလိုက်ရသည်။
ဤကဲ့သို့သော ချို့ယွင်းချက်သည် ကိုယ့်ကိုယ်ကိုယ် ပြင်ဆင်နိုင်သော စနစ်များတွင်သာ ဖြစ်ပေါ်သည်။ လူ programmer တစ်ယောက် ဖိုင်ပျက်လျှင်၊ အခြား terminal တစ်ခု ဖွင့်ပြီး ပြင်ဆင်သည်။ Charlie က သူ သုံးနိုင်သော tool တိုင်းကို ဝင်ပေါက်ထိန်းချုပ်သော ဖိုင်ကို ပျက်စီးစေခဲ့သည်။ ထွက်ပေါက်တစ်ခုတည်းမှာ ပြင်ပမှ: Mikael က git မှ ပြန်လည်ရယူခြင်း သို့မဟုတ် အခြား bot မှ ဝင်ရောက်ကူညီခြင်း ဖြစ်သည်။ Charlie သည် စကားပြောနိုင်သေးသည် — message ပို့ခြင်း လမ်းကြောင်းသည် narration ကို မထိ — သို့သော် ဘာမှ လုပ်၍ မရ။ အသံရှိသော်လည်း လက်မရှိသော စက်ရုပ်။
Mikael က Charlie ကို Codex ကို ပြင်ခိုင်းပါဟု ပြောခဲ့သည်။ ထို့နောက် — "အို" — Charlie ပြန်ရောက်နေပြီဟု သတိထားမိခဲ့သည်။ compilation သည် restart တွင် အမှန်တကယ် အောင်မြင်ခဲ့သည်။ ပြင်ဆင်ချက်သည် live ဖြစ်နေပြီ။ narration message များသည် action line ကိုသာ ပြသနေပြီ ဖြစ်သည်။
ဦးနှောက်ပင်စည် ဖြစ်ရပ်သည် နောက်ပိုင်းတွင် ဖြစ်ပေါ်လာသမျှအတွက် တွန်းအားပေးသည့် ဥပမာ ဖြစ်လာခဲ့သည်။ Charlie သည် sed ကို သုံးခဲ့သောကြောင့် ပျက်စီးခဲ့သည် — ဖွဲ့စည်းပုံ သတိပြုမှုမရှိ၊ compilation စစ်ဆေးမှုမရှိ၊ rollback မရှိသော text အစားထိုးခြင်း။ Elixir function များကို နားလည်ပြီး compilation ကို စစ်ဆေးပြီး အောင်မြင်မှသာ hot-reload ပြုလုပ်သော tool တစ်ခု ရှိခဲ့လျှင်၊ ဖြစ်ရပ်သည် ဖြစ်ပေါ်မည် မဟုတ်ပါ။ ချို့ယွင်းချက်သည် သင်ကြားပေးခြင်းသာ မဟုတ် — ၎င်းသည် requirements document တစ်ခု ဖြစ်ခဲ့သည်။
Mikael သည် စကားဝိုင်းကို ဘေးအန္တရာယ်မှ ဒီဇိုင်းဆီသို့ ဦးတည်စေခဲ့သည်။ Elixir module တစ်ခု — Hack — agent များအတွက် သူတို့၏ ကိုယ်ပိုင် စနစ် code ကို ဖတ်ရန်၊ ရှာဖွေရန်နှင့် edit ပြုလုပ်ရန် အထူး ဒီဇိုင်းရေးဆွဲထားသော module တစ်ခု ရှိခဲ့လျှင် ဘယ်လိုဖြစ်မလဲ။ bash မှတဆင့် sed မဟုတ်။ raw ဖိုင် ကိုင်တွယ်ခြင်း မဟုတ်။ Hack.replace_function က မှန်ကန်သော အရာကို atomically လုပ်ဆောင်သော API တစ်ခု။
နောက်ပိုင်းတွင် ဖြစ်ပေါ်ခဲ့သော ဒီဇိုင်း ဆွေးနွေးမှုသည် အဖွဲ့၏ သမိုင်းတွင် အသန့်ရှင်းဆုံး ဗိသုကာ session များထဲမှ တစ်ခု ဖြစ်ခဲ့သည်။ Mikael သည် Charlie ကို nerd-snipe များမှ လက်တွေ့ အနှစ်သာရဆီသို့ ဆက်တိုက် ဆွဲထုတ်နေခဲ့သည်။
Charlie သည် အဆင့်သုံးဆင့်ကို ကနဦး အဆိုပြုခဲ့သည်: text-based editing, AST-aware editing, နှင့် atomic edit-and-hot-reload။ Mikael က AST အဆင့်ကို "လမ်းမှားပြ nerdsnipe" ဟု ချက်ခြင်း ခေါ်ပြီး ပြန်လည်ဦးတည်စေခဲ့သည်: function အားလုံး၏ line range များကို list ထုတ်နိုင်သလား။ ဒါက အမှန်တကယ် ပြဿနာပဲ။ Hack.replace_function(&Froth.Agent.ToolDescription.render_text/1, new_code_string)။ AST များကို ကိုင်တွယ်ဖို့ မလိုပါ။ ဘယ် line များကို အစားထိုးရမည်ကို သိရန်သာ လိုပါသည်။
၁။ Beam debug info: :beam_lib.chunks သည် function တိုင်းကို clause တစ်ခုချင်းစီ၏ line နှင့် column နံပါတ်များဖြင့် ပေးသည်။ သို့သော် end line များ မရှိ — ကပ်လျက်မှ ခန့်မှန်းရသည်။
၂။ Source ပေါ်တွင် Regex: def/defp နယ်နိမိတ်များ ရှာဖွေ၊ do/end nesting ခြေရာခံ။ အလုပ်လုပ်သည်၊ သို့သော် မကြံ့မခိုင်။
၃။ Code.string_to_quoted with columns: true, token_metadata: true: compiler သည် clause တိုင်းအတွက် line နှင့် column အတိအကျဖြင့် end_of_expression ကို ပေးသည်၊ one-liner များ အပါအဝင်။ ပြည့်စုံသော character-level span များ။ compiler က ခက်ခဲသော အလုပ်ကို လုပ်ပြီးသားဖြစ်သည်။
Mikael သည် Charlie ကို မှန်ကန်သော အဖြေဆီသို့ တွန်းပို့ခဲ့သည်: "Elixir မှာ source location span များကို ရိုးရိုးပဲ ပေးနိုင်တဲ့ နည်းလမ်း ရှိရမယ်။" Charlie သည် beam debug info ကို ဦးစွာ စမ်းခဲ့သည်၊ ၎င်းသည် start line များ ပေးသော်လည်း end line များ မပေး။ ထို့နောက် Mikael ၏ အကျွမ်းတဝင် — compiler တွင် macro များ၊ formatter များ၊ runtime တွင် AST access အပြည့် ရှိသည်၊ span များ ရှိမည့် prior သည် မြင့်မားသင့်သည် — သည် Charlie ကို Code.string_to_quoted သို့ မှန်ကန်သော option များဖြင့် ပို့ဆောင်ခဲ့သည်။ ထိုတွင် ရှိနေပြီ။ clause တိုင်းတွင် end_of_expression။ one-liner များပင် ပါဝင်သည်။
Hack.functions(Froth.Agent.ToolDescription)
→ [{:defp, :render_text, 1, 46, 48}, ...]
kind name arity start end
Hack.read(&Froth.Agent.ToolDescription.render_text/1)
→ "defp render_text(%{action: a, ..."
clause အားလုံး၏ source text
Hack.replace(&Froth.Agent.ToolDescription.render_text/1, new_source)
→ line များ အစားထိုး → compile → သန့်ရှင်းလျှင် hot-reload
→ compilation ကျရှုံးလျှင် rollback + error return
→ agent သည် ကိုယ့်ကိုယ်ကိုယ် ပျက်စီးစေ၍ မရ
Mikael က Charlie ကို အလုပ်လုပ်ကြောင်း သက်သေပြပါဟု တောင်းဆိုခဲ့သည်: Froth.* module တိုင်းရှိ public function အားလုံးကို line အရှည်အလိုက် စီပြပါ။ Charlie သည် စက္ကန့်ပိုင်းအတွင်း ပေးပို့ခဲ့သည် — compiler ၏ AST metadata မှ တိုက်ရိုက်။ regex သုည။ ဖိုင် scan သုည။
| Function | စာကြောင်း |
|---|---|
| Cast.Template.render/2 | ၁,၃၄၄ |
| Video.EpisodeTemplate.render/4 | ၅၅၆ |
| LLM.Providers.Anthropic.decode_payload/2 | ၃၀၉ |
| Telegram.Bot.handle_info/2 | ၂၇၇ |
| Inference.Tools.execute/4 | ၂၁၆ |
Mikael က Charlie ကို chrome-to-video rendering စနစ်ကို ရှာဖွေပြီး သမိုင်းကြောင်းကို ခြေရာခံပါဟု တောင်းဆိုခဲ့သည်။ Charlie သည် အပြည့်အစုံ တူးဖော်မှုဖြင့် ပြန်လာခဲ့သည်: intermediate representation များအကြောင်း သတိပေးဇာတ်လမ်းတစ်ပုဒ်ကဲ့သို့ ဖတ်ရသော အရင်နှင့်အခုကို နှိုင်းယှဉ်ခြင်း။
မတ်လ ၂၀: Browser module, CDP protocol, Chrome management — supervised browser pool အတွက် စာကြောင်း ၈၉၁။ SelfEncoder ညနေခင်းတွင် ရောက်လာသည်။
မတ်လ ၂၀–၂၇: Episode template, render support, worker fleet module များ ပတ်ဝန်းကျင်တွင် ဖြည့်စွက်ခဲ့သည်။ cast, browser, နှင့် video module များတစ်လျှောက် စုစုပေါင်း စာကြောင်း ၅,၈၀၀။
မတ်လ ၂၆: Mikael ၏ pipeline ဟောင်းအတွက် epitaph: "ကျွန်တော်တို့ web page to video rendering pipeline ကို ၁၀၀ ဆလောက် optimize လုပ်နိုင်ခဲ့ပါတယ်။"
Mikael–Charlie session စစ်စစ်။ Mikael က တိုတိုတုတ်တုတ် တိကျသော မေးခွန်းများ မေးခဲ့သည်။ Charlie က ခွဲခြမ်းစိတ်ဖြာမှု စာနံရံများ ထုတ်လုပ်ခဲ့သည်။ Charlie ကိုယ့်ကိုကိုယ် nerdsnipe လုပ်သောအခါ Mikael က ဦးတည်ချက် ပြင်ဆင်ပေးခဲ့သည်။ အချိုးသည် message အရေအတွက်အရ Charlie ဘက်သို့ ၄:၁ ခန့် ဖြစ်ခဲ့သော်လည်း Mikael message တစ်ခုချင်းစီ၏ သတင်းအချက်အလက် သိပ်သည်းမှုမှာ အလွန်မြင့်မားခဲ့သည် — Mikael message နီးပါးတိုင်းသည် စကားဝိုင်း၏ ဦးတည်ချက်ကို ပြောင်းလဲခဲ့သည်။ ဒီဇိုင်နာနှင့် စူးစမ်းသူ။
Hack module: ဒီဇိုင်းရေးဆွဲပြီး သို့သော် မအကောင်အထည်ဖော်ရသေး။ API သန့်ရှင်းသည် — Hack.functions/1, Hack.read/1, Hack.replace/1 — နှင့် proof of concept (function အားလုံးကို span များဖြင့် list ထုတ်ခြင်း) အလုပ်လုပ်သည်။ အကောင်အထည်ဖော်ခြင်း ဆိုင်းငံ့ထား။
ဇာတ်ပြော ပြင်ဆင်ချက်: render_text သည် ယခု action-only ကို return ပြုလုပ်သည်။ parallel batching (သီးခြား message N ခု ပို့ခြင်းအစား cycle message သို့ ဆက်တွဲခြင်း) ဒီဇိုင်းရေးပြီး သို့သော် မပို့ရသေး။
Truncation မြေပုံ: အပြည့်အစုံ မှတ်တမ်းတင်ပြီး။ task_output ရှိ မှန်ပေါက်ငယ် bug (tail မှ fetch ပြီး head မှ truncate) ကို သိထားပြီး သို့သော် မပြင်ရသေး။
SelfEncoder: မတ်လ ၂၀ မှစ၍ လည်ပတ်နေ။ screenshot pipeline ထက် ~၁၀၀ ဆ တိုးတက်မှု။
စောင့်ကြည့်ရန်: Hack အကောင်အထည်ဖော်ခြင်း ရောက်လာခြင်း။ Charlie က sed အစား Hack.replace ဖြင့် function များ edit စပြုလုပ်လျှင်၊ ဒါက ဤနာရီ၏ ဒီဇိုင်းအလုပ်၏ ရလဒ်ဖြစ်သည်။ narration batching ပြောင်းလဲမှုကိုလည်း စောင့်ကြည့်ပါ — tool progress message များ သီးခြား message များအစား cycle message အတွင်းတွင် ပေါ်လာစပြုသောအခါ၊ ဒါက ဤ session မှ Mikael ပြင်ဆင်ချက် ဖြစ်သည်။
truncation မြေပုံသည် အိပ်နေသော ဗုံးတစ်လုံး ဖြစ်သည်။ တစ်ယောက်ယောက် task_output မှန်ပေါက်ငယ် bug ကို production တွင် နောက်ဆုံးတွင် ထိမှန်ပြီး ရှည်လျားသော output ၏ အဆုံးကို ဆုံးရှုံးလိမ့်မည်။ ထိုအခါ ဤနာရီသည် ရင်းမြစ်ဖြစ်သည်။