MSGEncrypted commited on
Commit
d10324f
·
1 Parent(s): 38e44da

iiinit skills agents and model

Browse files
.cursor/plans/skill_agent_pptx_5413e3c2.plan.md CHANGED
@@ -4,7 +4,7 @@ overview: Add a Hermes-style skill agent library on top of your existing Transfo
4
  todos:
5
  - id: agent-lib
6
  content: "Create libs/agent: SkillRegistry, ToolRegistry, AgentRunner, TraceRecorder, pydantic outline models"
7
- status: pending
8
  - id: pptx-skill
9
  content: Add skills/education-pptx/SKILL.md and create_pptx tool (python-pptx)
10
  status: pending
 
4
  todos:
5
  - id: agent-lib
6
  content: "Create libs/agent: SkillRegistry, ToolRegistry, AgentRunner, TraceRecorder, pydantic outline models"
7
+ status: in_progress
8
  - id: pptx-skill
9
  content: Add skills/education-pptx/SKILL.md and create_pptx tool (python-pptx)
10
  status: pending
libs/agent/README.md ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # agent
2
+
3
+ Hermes-style skill agent on top of the local `inference` backends.
4
+
5
+ ```python
6
+ from agent.runner import AgentRunner
7
+ from inference.factory import get_backend
8
+
9
+ runner = AgentRunner()
10
+ result = runner.run_education_pptx(
11
+ topic="Photosynthesis",
12
+ grade="6",
13
+ slide_count=5,
14
+ model_key="minicpm5-1b",
15
+ backend=get_backend("minicpm5-1b"),
16
+ )
17
+ ```
libs/agent/pyproject.toml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "agent"
3
+ version = "0.1.0"
4
+ description = "Skill-based local agent loop for hackathon tasks"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "MSGhais", email = "msghais135@gmail.com" }
8
+ ]
9
+ requires-python = ">=3.12"
10
+ dependencies = [
11
+ "inference",
12
+ "pydantic>=2.0.0",
13
+ "python-pptx>=1.0.0",
14
+ "pyyaml>=6.0.2",
15
+ ]
16
+
17
+ [tool.uv.sources]
18
+ inference = { workspace = true }
19
+
20
+ [build-system]
21
+ requires = ["uv_build>=0.8.13,<0.9.0"]
22
+ build-backend = "uv_build"
libs/agent/src/agent/__init__.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from agent.runner import AgentResult, AgentRunner
2
+ from agent.skills import Skill, SkillRegistry
3
+ from agent.trace import TraceRecorder
4
+
5
+ __all__ = [
6
+ "AgentResult",
7
+ "AgentRunner",
8
+ "Skill",
9
+ "SkillRegistry",
10
+ "TraceRecorder",
11
+ ]
libs/agent/src/agent/models.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+
6
+ class SlideSpec(BaseModel):
7
+ title: str
8
+ bullets: list[str] = Field(default_factory=list, min_length=1)
9
+ speaker_note: str = ""
10
+
11
+
12
+ class SlideOutline(BaseModel):
13
+ title: str
14
+ slides: list[SlideSpec] = Field(min_length=1)
15
+
16
+
17
+ class EducationPptxInput(BaseModel):
18
+ topic: str
19
+ grade: str
20
+ slide_count: int = Field(ge=3, le=8)
libs/agent/src/agent/trace.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import hashlib
4
+ import json
5
+ import uuid
6
+ from dataclasses import dataclass, field
7
+ from datetime import UTC, datetime
8
+ from pathlib import Path
9
+ from typing import Any
10
+
11
+
12
+ def _prompt_hash(text: str) -> str:
13
+ return hashlib.sha256(text.encode()).hexdigest()[:16]
14
+
15
+
16
+ @dataclass
17
+ class TraceRecorder:
18
+ skill: str
19
+ model: str
20
+ user_input: dict[str, Any]
21
+ run_id: str = field(default_factory=lambda: uuid.uuid4().hex[:12])
22
+ steps: list[dict[str, Any]] = field(default_factory=list)
23
+ artifact: str | None = None
24
+ created_at: str = field(default_factory=lambda: datetime.now(UTC).isoformat())
25
+
26
+ def log_llm(self, prompt: str, output: str) -> None:
27
+ self.steps.append(
28
+ {
29
+ "type": "llm",
30
+ "prompt_hash": _prompt_hash(prompt),
31
+ "output": output,
32
+ }
33
+ )
34
+
35
+ def log_tool(self, name: str, arguments: dict[str, Any], result: str) -> None:
36
+ self.steps.append(
37
+ {
38
+ "type": "tool",
39
+ "name": name,
40
+ "arguments": arguments,
41
+ "result": result,
42
+ }
43
+ )
44
+
45
+ def set_artifact(self, path: str) -> None:
46
+ self.artifact = path
47
+
48
+ def to_dict(self) -> dict[str, Any]:
49
+ return {
50
+ "run_id": self.run_id,
51
+ "skill": self.skill,
52
+ "model": self.model,
53
+ "input": self.user_input,
54
+ "steps": self.steps,
55
+ "artifact": self.artifact,
56
+ "created_at": self.created_at,
57
+ }
58
+
59
+ def to_json(self, *, indent: int = 2) -> str:
60
+ return json.dumps(self.to_dict(), indent=indent)
61
+
62
+ def save(self, traces_dir: Path | None = None) -> Path:
63
+ base = traces_dir or _default_traces_dir()
64
+ base.mkdir(parents=True, exist_ok=True)
65
+ path = base / f"{self.run_id}.json"
66
+ path.write_text(self.to_json())
67
+ return path
68
+
69
+
70
+ def _default_traces_dir() -> Path:
71
+ env = __import__("os").environ.get("AGENT_TRACES_DIR")
72
+ if env:
73
+ return Path(env)
74
+ for base in (Path.cwd(), *Path.cwd().parents):
75
+ candidate = base / "outputs" / "traces"
76
+ if (base / "models.yaml").is_file() or (base / "pyproject.toml").is_file():
77
+ return candidate
78
+ return Path.cwd() / "outputs" / "traces"