| STAGES = [ |
| { |
| "name": "Spark", |
| "avatar": "spark", |
| "size": 0.55, |
| "min_points": 0, |
| "description": "A new signal forming its first memories.", |
| }, |
| { |
| "name": "Seed", |
| "avatar": "seed", |
| "size": 0.68, |
| "min_points": 12, |
| "description": "A small companion starting to root ideas.", |
| }, |
| { |
| "name": "Sprout", |
| "avatar": "sprout", |
| "size": 0.82, |
| "min_points": 28, |
| "description": "Growing patterns from repeated conversations.", |
| }, |
| { |
| "name": "Bloom", |
| "avatar": "bloom", |
| "size": 1.0, |
| "min_points": 55, |
| "description": "A fuller companion with useful recall and reflection.", |
| }, |
| { |
| "name": "Lantern", |
| "avatar": "lantern", |
| "size": 1.14, |
| "min_points": 90, |
| "description": "Knowledge has become a steady light for guidance.", |
| }, |
| { |
| "name": "Constellation", |
| "avatar": "constellation", |
| "size": 1.28, |
| "min_points": 140, |
| "description": "Many memories connect into a broader inner map.", |
| }, |
| ] |
|
|
|
|
| def _count_type(memory, record_type): |
| try: |
| return memory.unified_manager.count_sync(record_type) |
| except Exception: |
| return 0 |
|
|
|
|
| def growth_profile(memory, turns=0): |
| interactions = _count_type(memory, "interaction") |
| concepts = _count_type(memory, "learned_knowledge") |
| reflections = _count_type(memory, "reflection") |
| total_memories = memory.count() |
| points = interactions + concepts * 3 + reflections * 5 + int(turns) * 2 |
|
|
| stage_index = 0 |
| for index, stage in enumerate(STAGES): |
| if points >= stage["min_points"]: |
| stage_index = index |
| else: |
| break |
|
|
| stage = STAGES[stage_index] |
| next_stage = STAGES[stage_index + 1] if stage_index + 1 < len(STAGES) else None |
| if next_stage: |
| span = next_stage["min_points"] - stage["min_points"] |
| progress = (points - stage["min_points"]) / span |
| points_to_next = next_stage["min_points"] - points |
| else: |
| progress = 1.0 |
| points_to_next = 0 |
|
|
| return { |
| "stage": stage["name"], |
| "avatar": stage["avatar"], |
| "size": stage["size"], |
| "description": stage["description"], |
| "points": points, |
| "progress": max(0.0, min(1.0, progress)), |
| "points_to_next": max(0, points_to_next), |
| "next_stage": next_stage["name"] if next_stage else None, |
| "stats": { |
| "total_memories": total_memories, |
| "interactions": interactions, |
| "concepts": concepts, |
| "reflections": reflections, |
| "turns": int(turns), |
| }, |
| } |
|
|
|
|
| def format_growth(profile): |
| stats = profile["stats"] |
| lines = [ |
| f"Growth stage: {profile['stage']}", |
| profile["description"], |
| f"Growth points: {profile['points']}", |
| f"Memories: {stats['total_memories']} total | {stats['interactions']} chats | {stats['concepts']} concepts | {stats['reflections']} reflections", |
| ] |
| if profile["next_stage"]: |
| lines.append( |
| f"Next stage: {profile['next_stage']} in {profile['points_to_next']} points" |
| ) |
| else: |
| lines.append("Next stage: fully grown for now") |
| return "\n".join(lines) |
|
|