PlanOpticon
| 0981a08… | noreply | 1 | """Skill: Generate a structured project plan from knowledge graph.""" |
| 0981a08… | noreply | 2 | |
| 0981a08… | noreply | 3 | from video_processor.agent.skills.base import ( |
| 0981a08… | noreply | 4 | AgentContext, |
| 0981a08… | noreply | 5 | Artifact, |
| 0981a08… | noreply | 6 | Skill, |
| 0981a08… | noreply | 7 | register_skill, |
| 0981a08… | noreply | 8 | ) |
| 0981a08… | noreply | 9 | |
| 0981a08… | noreply | 10 | |
| 0981a08… | noreply | 11 | def _group_entities_by_type(entities): |
| 0981a08… | noreply | 12 | """Group planning entities by their type.""" |
| 0981a08… | noreply | 13 | grouped = {} |
| 0981a08… | noreply | 14 | for e in entities: |
| 0981a08… | noreply | 15 | etype = getattr(e, "type", "unknown") |
| 0981a08… | noreply | 16 | grouped.setdefault(etype, []).append(e) |
| 0981a08… | noreply | 17 | return grouped |
| 0981a08… | noreply | 18 | |
| 0981a08… | noreply | 19 | |
| 0981a08… | noreply | 20 | class ProjectPlanSkill(Skill): |
| 0981a08… | noreply | 21 | name = "project_plan" |
| 0981a08… | noreply | 22 | description = "Generate a structured project plan from knowledge graph" |
| 0981a08… | noreply | 23 | |
| 0981a08… | noreply | 24 | def execute(self, context: AgentContext, **kwargs) -> Artifact: |
| 0981a08… | noreply | 25 | stats = context.query_engine.stats() |
| 0981a08… | noreply | 26 | entities = context.query_engine.entities() |
| 0981a08… | noreply | 27 | relationships = context.query_engine.relationships() |
| 0981a08… | noreply | 28 | grouped = _group_entities_by_type(context.planning_entities) |
| 0981a08… | noreply | 29 | |
| 0981a08… | noreply | 30 | parts = [ |
| 0981a08… | noreply | 31 | "You are a project planning expert. Using the following " |
| 0981a08… | noreply | 32 | "knowledge graph context, generate a comprehensive " |
| 0981a08… | noreply | 33 | "project plan in markdown.", |
| 0981a08… | noreply | 34 | "", |
| 0981a08… | noreply | 35 | "## Knowledge Graph Overview", |
| 0981a08… | noreply | 36 | stats.to_text(), |
| 0981a08… | noreply | 37 | "", |
| 0981a08… | noreply | 38 | "## Entities", |
| 0981a08… | noreply | 39 | entities.to_text(), |
| 0981a08… | noreply | 40 | "", |
| 0981a08… | noreply | 41 | "## Relationships", |
| 0981a08… | noreply | 42 | relationships.to_text(), |
| 0981a08… | noreply | 43 | "", |
| 0981a08… | noreply | 44 | "## Planning Entities (by type)", |
| 0981a08… | noreply | 45 | ] |
| 0981a08… | noreply | 46 | for etype, elist in grouped.items(): |
| 0981a08… | noreply | 47 | parts.append(f"\n### {etype}") |
| 0981a08… | noreply | 48 | for e in elist: |
| 0981a08… | noreply | 49 | parts.append(f"- {e}") |
| 0981a08… | noreply | 50 | |
| 0981a08… | noreply | 51 | parts.append( |
| 0981a08… | noreply | 52 | "\nGenerate a markdown project plan with:\n" |
| 0981a08… | noreply | 53 | "1. Executive Summary\n" |
| 0981a08… | noreply | 54 | "2. Goals & Objectives\n" |
| 0981a08… | noreply | 55 | "3. Scope\n" |
| 0981a08… | noreply | 56 | "4. Phases & Milestones\n" |
| 0981a08… | noreply | 57 | "5. Resource Requirements\n" |
| 0981a08… | noreply | 58 | "6. Risks & Mitigations\n" |
| 0981a08… | noreply | 59 | "7. Success Criteria\n\n" |
| 0981a08… | noreply | 60 | "Return ONLY the markdown." |
| 0981a08… | noreply | 61 | ) |
| 0981a08… | noreply | 62 | |
| 0981a08… | noreply | 63 | prompt = "\n".join(parts) |
| 0981a08… | noreply | 64 | response = context.provider_manager.chat(messages=[{"role": "user", "content": prompt}]) |
| 0981a08… | noreply | 65 | |
| 0981a08… | noreply | 66 | return Artifact( |
| 0981a08… | noreply | 67 | name="Project Plan", |
| 0981a08… | noreply | 68 | content=response, |
| 0981a08… | noreply | 69 | artifact_type="project_plan", |
| 0981a08… | noreply | 70 | format="markdown", |
| 0981a08… | noreply | 71 | ) |
| 0981a08… | noreply | 72 | |
| 0981a08… | noreply | 73 | |
| 0981a08… | noreply | 74 | register_skill(ProjectPlanSkill()) |