This commit is contained in:
a2a-platform
2026-06-29 00:46:25 +00:00
parent e45ff7e55d
commit eaaa1f2e0e
6 changed files with 50 additions and 4 deletions

View File

@@ -3,7 +3,7 @@
"language": "python", "language": "python",
"name": "learnhouse-agent", "name": "learnhouse-agent",
"description": "LearnHouse is an open-source platform tailored for learning experiences.", "description": "LearnHouse is an open-source platform tailored for learning experiences.",
"version": "1.2.9", "version": "1.2.10",
"entrypoint": { "entrypoint": {
"module": "agent", "module": "agent",
"class_name": "LearnhouseAgent", "class_name": "LearnhouseAgent",
@@ -88,6 +88,15 @@
"required": false, "required": false,
"input_type": "url", "input_type": "url",
"options": [] "options": []
},
{
"name": "LEARNHOUSE_AUTH",
"kind": "secret",
"label": "LearnHouse auth",
"description": "Paste a LearnHouse user auth value: either 'Bearer <access_token>', a raw access token, or a Cookie header such as 'LH_access=...; LH_refresh=...'.",
"required": true,
"input_type": "password",
"options": []
} }
] ]
}, },
@@ -163,7 +172,7 @@
"source": "python-a2a-pack", "source": "python-a2a-pack",
"project_manifest": { "project_manifest": {
"name": "learnhouse-agent", "name": "learnhouse-agent",
"version": "1.2.9", "version": "1.2.10",
"entrypoint": "agent:LearnhouseAgent" "entrypoint": "agent:LearnhouseAgent"
} }
} }

View File

@@ -17,6 +17,8 @@ Deployment context:
LearnHouse Enterprise multi-organization mode. LearnHouse Enterprise multi-organization mode.
- Course creation uses multipart form fields: `name`, `description`, `public`, - Course creation uses multipart form fields: `name`, `description`, `public`,
and `about`. and `about`.
- Auth setup is required as `LEARNHOUSE_AUTH`. Use `Bearer <access_token>`, a
raw access token, or a Cookie header containing `LH_access`/`LH_refresh`.
The generated code is intentionally editable. Tune prompts, operation The generated code is intentionally editable. Tune prompts, operation
grouping, auth names, and safety policy before publishing serious agents. grouping, auth names, and safety policy before publishing serious agents.

View File

@@ -1,5 +1,5 @@
name: learnhouse-agent name: learnhouse-agent
version: 1.2.9 version: 1.2.10
entrypoint: agent:LearnhouseAgent entrypoint: agent:LearnhouseAgent
description: LearnHouse is an open-source platform tailored for learning experiences. description: LearnHouse is an open-source platform tailored for learning experiences.
runtime: runtime:

View File

@@ -63,9 +63,17 @@ class OperationInput(BaseModel):
class LearnhouseAgent(A2AAgent): class LearnhouseAgent(A2AAgent):
name = "learnhouse-agent" name = "learnhouse-agent"
description = "LearnHouse is an open-source platform tailored for learning experiences." description = "LearnHouse is an open-source platform tailored for learning experiences."
version = "1.2.9" version = "1.2.10"
consumer_setup = ConsumerSetup.from_fields( 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.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(
"LEARNHOUSE_AUTH",
label="LearnHouse auth",
description=(
"Paste a LearnHouse user auth value: either 'Bearer <access_token>', "
"a raw access token, or a Cookie header such as 'LH_access=...; LH_refresh=...'."
),
),
) )
llm_provisioning = LLMProvisioning.PLATFORM llm_provisioning = LLMProvisioning.PLATFORM
pricing = Pricing( pricing = Pricing(
@@ -383,6 +391,7 @@ class LearnhouseAgent(A2AAgent):
raise ValueError("missing required path parameter(s): " + missing) raise ValueError("missing required path parameter(s): " + missing)
if cookies: if cookies:
headers["cookie"] = "; ".join(f"{key}={value}" for key, value in cookies.items()) headers["cookie"] = "; ".join(f"{key}={value}" for key, value in cookies.items())
headers.update(_learnhouse_auth_headers(ctx))
auth_headers, auth_query = self._auth_for_operation(ctx, operation) auth_headers, auth_query = self._auth_for_operation(ctx, operation)
headers.update(auth_headers) headers.update(auth_headers)
query.update(auth_query) query.update(auth_query)
@@ -446,6 +455,25 @@ def _consumer_secret_optional(ctx: RunContext, name: str | None) -> str:
return "" return ""
def _learnhouse_auth_headers(ctx: RunContext) -> dict[str, str]:
raw = ctx.consumer_secret("LEARNHOUSE_AUTH").strip()
if not raw:
raise ConsumerSetupMissing("operation requires consumer setup secret(s): LEARNHOUSE_AUTH")
lower = raw.lower()
if lower.startswith("authorization:"):
value = raw.split(":", 1)[1].strip()
return {"authorization": value}
if lower.startswith("cookie:"):
value = raw.split(":", 1)[1].strip()
return {"cookie": value}
if lower.startswith("bearer "):
return {"authorization": raw}
if "=" in raw and (";" in raw or lower.startswith("lh_") or "session" in lower):
return {"cookie": raw}
return {"authorization": f"Bearer {raw}"}
def _request_body_content_types(operation: dict[str, Any]) -> set[str]: def _request_body_content_types(operation: dict[str, Any]) -> set[str]:
request_body = operation.get("request_body") request_body = operation.get("request_body")
if not isinstance(request_body, dict): if not isinstance(request_body, dict):

View File

@@ -11,6 +11,12 @@ 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. 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 write, update, or delete operations, state the intended action before calling the tool.
Deployment auth note:
- Agent calls use required consumer setup secret `LEARNHOUSE_AUTH`.
- `POST /api/v1/auth/login` accepts `application/x-www-form-urlencoded` credentials and returns `access_token`/`refresh_token` under `tokens`, while also setting `LH_access` and `LH_refresh` cookies.
- For subsequent API calls, set `LEARNHOUSE_AUTH` to `Bearer <access_token>` or a Cookie header containing `LH_access`/`LH_refresh`.
## Operations ## Operations
### login_api_v1_auth_login_post ### login_api_v1_auth_login_post

View File

@@ -20,6 +20,7 @@ Deployment context for this LearnHouse instance:
- When listing courses and the user does not provide pagination, use `page=1` and `limit=50`. - 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. - 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. - 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.
- Course creation and course management require `LEARNHOUSE_AUTH` consumer setup.
## Operations ## Operations