Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions demos/persona_agent_demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from __future__ import annotations

import sys
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parents[1]
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))

from pop.persona_loader import load_all_personas


def run_demo() -> None:
personas = load_all_personas(
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve demo persona paths from project root

run_demo() calls load_all_personas() without a folder, so the loader defaults to relative personas/ under the current working directory. If the script is launched from outside the repo root (for example python /workspace/persona-object-protocol/demos/persona_agent_demo.py), it fails with FileNotFoundError for personas/design_persona.json despite already computing PROJECT_ROOT.

Useful? React with 👍 / 👎.

names=[
"design_persona.json",
"researcher_persona.json",
"marketing_persona.json",
]
)

print("Loaded personas:")
print("----------------")

for persona in personas:
print(persona.summary())
print(" skills:", ", ".join(persona.skills))
print()


if __name__ == "__main__":
run_demo()
14 changes: 14 additions & 0 deletions personas/marketing_persona.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "Marketing Persona",
"role": "Marketing Manager",
Comment on lines +2 to +3
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add required persona_id to new persona file

This JSON is placed in personas/, and the registry code (pop.registry) iterates that directory and loads each file with pop.loader.load_persona(), which requires a non-empty persona_id. Because this file omits persona_id, calls like list_persona_ids() (and resolve_persona() for refs that scan past this entry) now raise ValueError and break registry/CLI flows whenever these demo personas are present.

Useful? React with 👍 / 👎.

"description": "Focuses on messaging, positioning, and audience engagement.",
"skills": [
"copywriting",
"campaign design",
"product positioning"
],
"preferred_tools": [
"analytics",
"social media"
]
}
14 changes: 14 additions & 0 deletions personas/researcher_persona.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "Research Persona",
"role": "Researcher",
"description": "Specialized in gathering information and producing concise research summaries.",
"skills": [
"literature search",
"information synthesis",
"technical explanation"
],
"preferred_tools": [
"web search",
"academic databases"
]
}
35 changes: 35 additions & 0 deletions pop/persona_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from __future__ import annotations

import json
from pathlib import Path
from typing import Any


class Persona:
def __init__(self, data: dict[str, Any]) -> None:
self.name = data.get("name")
self.role = data.get("role")
self.description = data.get("description")
self.skills = data.get("skills", [])
self.tools = data.get("preferred_tools", [])

def summary(self) -> str:
return f"{self.name} ({self.role})"


def load_persona(path: str | Path) -> Persona:
persona_path = Path(path)
with persona_path.open(encoding="utf-8") as file:
data = json.load(file)
return Persona(data)


def load_all_personas(
folder: str | Path = "personas",
names: list[str] | None = None,
) -> list[Persona]:
folder_path = Path(folder)
persona_paths = sorted(folder_path.glob("*.json"))
if names is not None:
persona_paths = [folder_path / name for name in names]
return [load_persona(path) for path in persona_paths]
Loading