diff --git a/.a2a/agent.dsl.json b/.a2a/agent.dsl.json index 6772b58..8ce9f62 100644 --- a/.a2a/agent.dsl.json +++ b/.a2a/agent.dsl.json @@ -3,7 +3,7 @@ "language": "python", "name": "learnhouse-agent", "description": "LearnHouse is an open-source platform tailored for learning experiences.", - "version": "1.2.10", + "version": "1.2.11", "entrypoint": { "module": "agent", "class_name": "LearnhouseAgent", @@ -172,7 +172,7 @@ "source": "python-a2a-pack", "project_manifest": { "name": "learnhouse-agent", - "version": "1.2.10", + "version": "1.2.11", "entrypoint": "agent:LearnhouseAgent" } } diff --git a/README.md b/README.md index 6bdf866..d310a9a 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,14 @@ Deployment context: LearnHouse Enterprise multi-organization mode. - Course creation uses multipart form fields: `name`, `description`, `public`, and `about`. +- When creating lesson/module content, create at least one activity per chapter + using that chapter's own `chapter_id`. Do not attach all activities to the + first chapter. +- Visible lesson activities should normally use `TYPE_DYNAMIC` / + `SUBTYPE_DYNAMIC_MARKDOWN`, markdown content/details, `lock_type=public`, and + `published=true` unless the user explicitly asks for drafts. +- Activity updates must not send `published_version`; this LearnHouse backend + currently rejects that field. - Auth setup is required as `LEARNHOUSE_AUTH`. Use `Bearer `, a raw access token, or a Cookie header containing `LH_access`/`LH_refresh`. diff --git a/a2a.yaml b/a2a.yaml index 2e910c1..de7d0cc 100644 --- a/a2a.yaml +++ b/a2a.yaml @@ -1,5 +1,5 @@ name: learnhouse-agent -version: 1.2.10 +version: 1.2.11 entrypoint: agent:LearnhouseAgent description: LearnHouse is an open-source platform tailored for learning experiences. runtime: diff --git a/agent.py b/agent.py index 1a579fd..012805a 100644 --- a/agent.py +++ b/agent.py @@ -48,7 +48,17 @@ LEARNHOUSE_CONTEXT = ( "When creating a course, send multipart form fields name, description, " "public, and about; if the user only gives a title, use it as name, provide " "short description/about text, and set public=false unless the user asks " - "for a public course." + "for a public course. When asked to create a course with lessons or modules, " + "create the course, create each chapter with the returned course_id, then " + "create at least one activity in each chapter using that chapter's specific " + "chapter_id. Do not attach all activities to the first chapter. For visible " + "lesson content, create activities with activity_type TYPE_DYNAMIC, " + "activity_sub_type SUBTYPE_DYNAMIC_MARKDOWN, markdown content/details, " + "lock_type public, and published=true unless the user requests drafts. " + "After writing course content, verify every chapter has at least one " + "activity through course metadata or the chapter activity endpoint. When " + "updating activities, do not send published_version; this LearnHouse " + "backend currently rejects that field." ) @@ -63,7 +73,7 @@ class OperationInput(BaseModel): class LearnhouseAgent(A2AAgent): name = "learnhouse-agent" description = "LearnHouse is an open-source platform tailored for learning experiences." - version = "1.2.10" + version = "1.2.11" consumer_setup = ConsumerSetup.from_fields( ConsumerSetupField.config("OPENAPI_BASE_URL", label="API base URL", description="Override the default API server (https://learnhouse.a2acloud.io).", required=False, input_type="url"), ConsumerSetupField.secret( @@ -291,6 +301,18 @@ class LearnhouseAgent(A2AAgent): "For LearnHouse course creation, send body/form fields: " "name, description, public, about." ) + if _is_learnhouse_create_activity(operation): + parts.append( + "For LearnHouse activity creation, send JSON fields name, " + "chapter_id, activity_type, activity_sub_type, content, " + "details, lock_type, and published. Use the target " + "chapter's own chapter_id; do not reuse the first chapter ID." + ) + if _is_learnhouse_update_activity(operation): + parts.append( + "Do not send published_version on LearnHouse activity " + "updates; this backend rejects that field." + ) parts.append(f"Operation ID: {operation['operation_id']}") return "\n".join(part for part in parts if part) @@ -500,6 +522,20 @@ def _is_learnhouse_create_course(operation: dict[str, Any]) -> bool: ) +def _is_learnhouse_create_activity(operation: dict[str, Any]) -> bool: + return ( + str(operation.get("operation_id") or "") + == "api_create_activity_api_v1_activities_post" + ) + + +def _is_learnhouse_update_activity(operation: dict[str, Any]) -> bool: + return ( + str(operation.get("operation_id") or "") + == "api_update_activity_api_v1_activities_activity_uuid_put" + ) + + def _apply_learnhouse_defaults( operation: dict[str, Any], parameters: dict[str, Any], diff --git a/skills/activities/SKILL.md b/skills/activities/SKILL.md index 0481260..0a20dd5 100644 --- a/skills/activities/SKILL.md +++ b/skills/activities/SKILL.md @@ -11,6 +11,14 @@ Use the generated operation tools to make real API calls. Do not invent API resp If a tool reports missing setup, return the exact setup field name to the caller. For write, update, or delete operations, state the intended action before calling the tool. +For visible lesson content, prefer `POST /api/v1/activities/` with +`activity_type=TYPE_DYNAMIC`, `activity_sub_type=SUBTYPE_DYNAMIC_MARKDOWN`, +markdown stored in `content`/`details`, `lock_type=public`, and `published=true` +unless the user asks for drafts. Always use the target chapter's own +`chapter_id`; do not attach every activity to the first chapter. On +`PUT /api/v1/activities/{activity_uuid}`, do not send `published_version`; +this LearnHouse backend rejects that field. + ## Operations ### api_create_activity_api_v1_activities_post diff --git a/skills/chapters/SKILL.md b/skills/chapters/SKILL.md index bae8c0d..7c517f2 100644 --- a/skills/chapters/SKILL.md +++ b/skills/chapters/SKILL.md @@ -11,6 +11,11 @@ Use the generated operation tools to make real API calls. Do not invent API resp If a tool reports missing setup, return the exact setup field name to the caller. For write, update, or delete operations, state the intended action before calling the tool. +When creating multiple lesson chapters for a course, keep the returned `id` for +each chapter. If the user requested course content, create at least one activity +for every chapter using that specific `chapter_id`; do not reuse the first +chapter ID for all activities. Verify every chapter has at least one activity. + ## Operations ### api_create_coursechapter_api_v1_chapters_post diff --git a/skills/courses/SKILL.md b/skills/courses/SKILL.md index 8c5b9e3..fad074d 100644 --- a/skills/courses/SKILL.md +++ b/skills/courses/SKILL.md @@ -20,6 +20,8 @@ Deployment context for this LearnHouse instance: - When listing courses and the user does not provide pagination, use `page=1` and `limit=50`. - When creating a course, use query parameter `org_id=1` unless the user explicitly provides another org ID. - Course creation must send multipart form fields `name`, `description`, `public`, and `about`. If the user only gives a title, use it as `name`, provide short `description` and `about` values, and set `public=false` unless the user asks for a public course. +- When the user asks for a course with lessons, modules, or activities, do not stop after creating the course and chapters. Create at least one activity per chapter, using each chapter's own returned `chapter_id`. +- Do not attach all generated activities to the first chapter. Verify the resulting course metadata shows activities distributed under the intended chapters. - Course creation and course management require `LEARNHOUSE_AUTH` consumer setup. ## Operations