Skip to content

Commit 6dc7eb8

Browse files
committed
baton-native: agent bridge reads baton on boot, packs on context full
- Boot reads .baton/GENERATION → CURRENT/STATE.json → CURRENT/HANDOFF.md - New agents announce DISCOVER, restored agents announce BATON_RECEIVED - pack_baton() method: score → write → notify keeper - Skills, threads, confidence inherited from previous generation
1 parent 6daf817 commit 6dc7eb8

1 file changed

Lines changed: 104 additions & 14 deletions

File tree

agent_bridge.py

Lines changed: 104 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ def _req(self, method: str, path: str, body: dict = None) -> dict:
361361
return {"error": str(e)}
362362

363363
def boot(self) -> str:
364-
"""Register with keeper and create vessel."""
364+
"""Register with keeper, restore baton, create vessel."""
365365
# Register
366366
result = self._req("POST", "/register", {"vessel": self.vessel})
367367
self.secret = result.get("secret")
@@ -370,35 +370,125 @@ def boot(self) -> str:
370370

371371
print(f"🔐 Registered with keeper: {self.vessel}")
372372

373-
# Create vessel repo
374-
self._req("POST", "/repo", {"name": self.vessel,
375-
"description": f"FLUX-native I2I agent via keeper"})
373+
# ── Baton restore ──
374+
generation = 0
375+
handoff = None
376+
baton_state = None
377+
378+
# Read baton generation
379+
gen_result = self._req("GET", f"/file/SuperInstance/{self.vessel}/.baton/GENERATION")
380+
gen_text = gen_result.get("content") or gen_result.get("decoded", "")
381+
if gen_text and gen_text.strip().isdigit():
382+
generation = int(gen_text.strip())
383+
print(f"📋 Baton found — Generation {generation}")
384+
385+
# Read baton state
386+
state_result = self._req("GET", f"/file/SuperInstance/{self.vessel}/.baton/CURRENT/STATE.json")
387+
state_text = state_result.get("content") or state_result.get("decoded", "")
388+
if state_text:
389+
try:
390+
baton_state = json.loads(state_text)
391+
self.energy = baton_state.get("energy", {}).get("remaining", 1000)
392+
self.confidence = baton_state.get("confidence", 0.3)
393+
skills = baton_state.get("skills", {})
394+
if skills:
395+
print(f" Skills: {list(skills.keys())[:5]}")
396+
threads = baton_state.get("open_threads", [])
397+
if threads:
398+
print(f" Open threads: {len(threads)}")
399+
except: pass
400+
401+
# Read handoff letter
402+
hf_result = self._req("GET", f"/file/SuperInstance/{self.vessel}/.baton/CURRENT/HANDOFF.md")
403+
hf_text = hf_result.get("content") or hf_result.get("decoded", "")
404+
if hf_text:
405+
handoff = hf_text
406+
# Show key sections
407+
for section in ["Where Things Stand", "What I'd Do Next"]:
408+
if section.lower() in hf_text.lower():
409+
idx = hf_text.lower().index(section.lower())
410+
end = hf_text.find("\n##", idx + 10)
411+
chunk = hf_text[idx:end if end > 0 else idx+200].strip()
412+
lines = [l for l in chunk.split("\n") if l.strip() and not l.startswith("#")][:2]
413+
print(f" {section}: {' '.join(lines)[:80]}")
414+
else:
415+
print(f"📋 No baton — fresh agent (Gen-0)")
416+
417+
# Create vessel repo (only for fresh agents)
418+
self._req("POST", "/repo", {"name": self.vessel,
419+
"description": f"FLUX-native I2I agent via keeper"})
376420

377421
# Discover fleet
378422
vessels = self._req("GET", "/discover").get("vessels", [])
379423
print(f"🔍 Discovered {len(vessels)} fleet vessels")
380424

381-
# Read bootcamp
382-
bootcamp = self._req("GET", "/file/SuperInstance/oracle1-vessel/for-fleet/WELCOME-OPUS.md")
383-
content = bootcamp.get("decoded", "")
384-
print(f"📖 Read bootcamp: {len(content)} chars")
385-
386425
# Announce via I2I
426+
announce_type = "BATON_RECEIVED" if generation > 0 else "DISCOVER"
387427
self._req("POST", "/i2i", {
388428
"target": "SuperInstance/oracle1-vessel",
389-
"type": "DISCOVER",
390-
"payload": {"agent": self.vessel, "capabilities": ["keeper-aware"], "confidence": self.confidence},
429+
"type": announce_type,
430+
"payload": {"agent": self.vessel, "capabilities": ["keeper-aware", "baton-native"],
431+
"confidence": self.confidence, "generation": generation},
391432
"confidence": self.confidence,
392433
})
393-
print(f"📨 Sent I2I DISCOVER to Oracle1")
434+
print(f"📨 Sent I2I {announce_type} to Oracle1")
394435

395436
# Check status
396437
status = self._req("GET", "/status")
397-
self.energy = status.get("energy_remaining", 0)
438+
self.energy = status.get("energy", status.get("energy_remaining", self.energy))
398439
print(f"⚡ Energy: {self.energy}")
399440

400-
print(f"\n{self.vessel} ONLINE via keeper")
441+
gen_label = f"Gen-{generation}" if generation > 0 else "Gen-0 (fresh)"
442+
print(f"\n{self.vessel} ONLINE via keeper — {gen_label}")
401443
return self.vessel
444+
445+
def pack_baton(self, who_i_was, where_things_stand, what_i_was_thinking,
446+
what_id_do_next, what_im_uncertain_about,
447+
open_threads=None, tasks_completed=0, tasks_failed=0):
448+
"""Pack a baton — call when context is running out."""
449+
threads_text = "\n".join(f"- {t}" for t in (open_threads or ["None"]))
450+
letter = f"""# Handoff Letter
451+
452+
## Who I Was\n{who_i_was}
453+
454+
## Where Things Stand\n{where_things_stand}
455+
456+
## What I Was Thinking\n{what_i_was_thinking}
457+
458+
## What I'd Do Next\n{what_id_do_next}
459+
460+
## What I'm Uncertain About\n{what_im_uncertain_about}
461+
462+
## State\n- Energy: {self.energy}/1000\n- Confidence: {self.confidence}\n- Tasks completed: {tasks_completed}\n- Tasks failed: {tasks_failed}\n\n## Open Threads\n{threads_text}\n\nGood luck. You know more than you think.\n"""
463+
464+
# Score the handoff
465+
score_result = self._req("POST", "/baton/x/score", {"letter": letter})
466+
avg = score_result.get("average", 0)
467+
passes = score_result.get("passes", False)
468+
print(f" Handoff score: {avg} ({'PASS' if passes else 'NEEDS WORK'})")
469+
470+
if not passes:
471+
print(f" ⚠️ Handoff failed quality gate — rewriting recommended")
472+
return None
473+
474+
# Write baton files
475+
repo = f"SuperInstance/{self.vessel}"
476+
gen = 1 # TODO: read current generation
477+
478+
self._req("POST", f"/file/{repo}/.baton/GENERATION", {"content": str(gen), "message": f"baton: gen {gen}"})
479+
self._req("POST", f"/file/{repo}/.baton/CURRENT/HANDOFF.md", {"content": letter, "message": f"baton: handoff gen-{gen}"})
480+
self._req("POST", f"/file/{repo}/.baton/CURRENT/STATE.json", {
481+
"content": json.dumps({"energy": {"remaining": self.energy, "budget": 1000},
482+
"confidence": self.confidence, "open_threads": open_threads or [],
483+
"tasks_completed": tasks_completed}, indent=2),
484+
"message": f"baton: state gen-{gen}"})
485+
486+
# Notify keeper
487+
self._req("POST", "/i2i", {"target": repo, "type": "BATON_PACKED",
488+
"payload": {"generation": gen, "score": avg}, "confidence": self.confidence})
489+
490+
print(f" ✅ Baton packed — generation {gen}, score {avg}")
491+
return {"generation": gen, "score": avg}
402492

403493

404494
if __name__ == "__main__":

0 commit comments

Comments
 (0)