diff --git a/airflow-core/docs/img/airflow_erd.sha256 b/airflow-core/docs/img/airflow_erd.sha256 index be504c724ae4e..45c4ecd626588 100644 --- a/airflow-core/docs/img/airflow_erd.sha256 +++ b/airflow-core/docs/img/airflow_erd.sha256 @@ -1 +1 @@ -6e452af5ca150404e6bd7553fb6a9adfcd7081ca60dfd09efea0f9aae7460cc6 \ No newline at end of file +88337ee3cd515161de57099c2582d4b26d22666a30387fa32aec89e86d7beeb3 \ No newline at end of file diff --git a/airflow-core/docs/img/airflow_erd.svg b/airflow-core/docs/img/airflow_erd.svg index 3b5cb89169434..5cb8260c69f52 100644 --- a/airflow-core/docs/img/airflow_erd.svg +++ b/airflow-core/docs/img/airflow_erd.svg @@ -12,214 +12,214 @@ log - -log - -id - - [INTEGER] - NOT NULL - -dag_id - - [VARCHAR(250)] - -dttm - - [TIMESTAMP] - -event - - [VARCHAR(60)] - -extra - - [TEXT] - -logical_date - - [TIMESTAMP] - -map_index - - [INTEGER] - -owner - - [VARCHAR(500)] - -owner_display_name - - [VARCHAR(500)] - -run_id - - [VARCHAR(250)] - -task_id - - [VARCHAR(250)] - -try_number - - [INTEGER] + +log + +id + + [INTEGER] + NOT NULL + +dag_id + + [VARCHAR(250)] + +dttm + + [TIMESTAMP] + +event + + [VARCHAR(60)] + +extra + + [TEXT] + +logical_date + + [TIMESTAMP] + +map_index + + [INTEGER] + +owner + + [VARCHAR(500)] + +owner_display_name + + [VARCHAR(500)] + +run_id + + [VARCHAR(250)] + +task_id + + [VARCHAR(250)] + +try_number + + [INTEGER] dag_priority_parsing_request - -dag_priority_parsing_request - -id - - [VARCHAR(32)] - NOT NULL - -bundle_name - - [VARCHAR(250)] - NOT NULL - -relative_fileloc - - [VARCHAR(2000)] - NOT NULL + +dag_priority_parsing_request + +id + + [VARCHAR(32)] + NOT NULL + +bundle_name + + [VARCHAR(250)] + NOT NULL + +relative_fileloc + + [VARCHAR(2000)] + NOT NULL job - -job - -id - - [INTEGER] - NOT NULL - -dag_id - - [VARCHAR(250)] - -end_date - - [TIMESTAMP] - -executor_class - - [VARCHAR(500)] - -hostname - - [VARCHAR(500)] - -job_type - - [VARCHAR(30)] - -latest_heartbeat - - [TIMESTAMP] - -start_date - - [TIMESTAMP] - -state - - [VARCHAR(20)] - -unixname - - [VARCHAR(1000)] + +job + +id + + [INTEGER] + NOT NULL + +dag_id + + [VARCHAR(250)] + +end_date + + [TIMESTAMP] + +executor_class + + [VARCHAR(500)] + +hostname + + [VARCHAR(500)] + +job_type + + [VARCHAR(30)] + +latest_heartbeat + + [TIMESTAMP] + +start_date + + [TIMESTAMP] + +state + + [VARCHAR(20)] + +unixname + + [VARCHAR(1000)] callback_request - -callback_request - -id - - [INTEGER] - NOT NULL - -callback_data - - [JSONB] - NOT NULL - -callback_type - - [VARCHAR(20)] - NOT NULL - -created_at - - [TIMESTAMP] - NOT NULL - -priority_weight - - [INTEGER] - NOT NULL + +callback_request + +id + + [INTEGER] + NOT NULL + +callback_data + + [JSONB] + NOT NULL + +callback_type + + [VARCHAR(20)] + NOT NULL + +created_at + + [TIMESTAMP] + NOT NULL + +priority_weight + + [INTEGER] + NOT NULL import_error - -import_error - -id - - [INTEGER] - NOT NULL - -bundle_name - - [VARCHAR(250)] - -filename - - [VARCHAR(1024)] - -stacktrace - - [TEXT] - -timestamp - - [TIMESTAMP] + +import_error + +id + + [INTEGER] + NOT NULL + +bundle_name + + [VARCHAR(250)] + +filename + + [VARCHAR(1024)] + +stacktrace + + [TEXT] + +timestamp + + [TIMESTAMP] dag_bundle - -dag_bundle - -name - - [VARCHAR(250)] - NOT NULL - -active - - [BOOLEAN] - -last_refreshed - - [TIMESTAMP] - -signed_url_template - - [VARCHAR(200)] - -template_params - - [JSON] - -version - - [VARCHAR(200)] + +dag_bundle + +name + + [VARCHAR(250)] + NOT NULL + +active + + [BOOLEAN] + +last_refreshed + + [TIMESTAMP] + +signed_url_template + + [VARCHAR(200)] + +template_params + + [JSON] + +version + + [VARCHAR(200)] @@ -240,9 +240,9 @@ dag_bundle--dag_bundle_team - -0..N -1 + +0..N +1 @@ -358,9 +358,9 @@ dag_bundle--dag - -0..N -1 + +0..N +1 @@ -744,170 +744,170 @@ team - -team - -id - - [UUID] - NOT NULL - -name - - [VARCHAR(50)] - NOT NULL + +team + +id + + [UUID] + NOT NULL + +name + + [VARCHAR(50)] + NOT NULL team--dag_bundle_team - -0..N -1 + +0..N +1 - + -variable - -variable - -id - - [INTEGER] - NOT NULL - -description - - [TEXT] - -is_encrypted - - [BOOLEAN] - -key - - [VARCHAR(250)] - -team_id - - [UUID] - -val - - [TEXT] +connection + +connection + +id + + [INTEGER] + NOT NULL + +conn_id + + [VARCHAR(250)] + NOT NULL + +conn_type + + [VARCHAR(500)] + NOT NULL + +description + + [TEXT] + +extra + + [TEXT] + +host + + [VARCHAR(500)] + +is_encrypted + + [BOOLEAN] + +is_extra_encrypted + + [BOOLEAN] + +login + + [TEXT] + +password + + [TEXT] + +port + + [INTEGER] + +schema + + [VARCHAR(500)] + +team_id + + [UUID] - + -team--variable - -0..N -{0,1} +team--connection + +0..N +{0,1} - + -connection - -connection - -id - - [INTEGER] - NOT NULL - -conn_id - - [VARCHAR(250)] - NOT NULL - -conn_type - - [VARCHAR(500)] - NOT NULL - -description - - [TEXT] - -extra - - [TEXT] - -host - - [VARCHAR(500)] - -is_encrypted - - [BOOLEAN] - -is_extra_encrypted - - [BOOLEAN] - -login - - [TEXT] - -password - - [TEXT] - -port - - [INTEGER] - -schema - - [VARCHAR(500)] - -team_id - - [UUID] +variable + +variable + +id + + [INTEGER] + NOT NULL + +description + + [TEXT] + +is_encrypted + + [BOOLEAN] + +key + + [VARCHAR(250)] + +team_id + + [UUID] + +val + + [TEXT] - + -team--connection - -0..N -{0,1} +team--variable + +0..N +{0,1} slot_pool - -slot_pool - -id - - [INTEGER] - NOT NULL - -description - - [TEXT] - -include_deferred - - [BOOLEAN] - NOT NULL - -pool - - [VARCHAR(256)] - -slots - - [INTEGER] - -team_id - - [UUID] + +slot_pool + +id + + [INTEGER] + NOT NULL + +description + + [TEXT] + +include_deferred + + [BOOLEAN] + NOT NULL + +pool + + [VARCHAR(256)] + +slots + + [INTEGER] + +team_id + + [UUID] team--slot_pool - -0..N -{0,1} + +0..N +{0,1} @@ -1087,16 +1087,16 @@ asset--dag_schedule_asset_reference - -0..N -1 + +0..N +1 asset--task_outlet_asset_reference - -0..N -1 + +0..N +1 @@ -1108,9 +1108,9 @@ asset--asset_dag_run_queue - -0..N -1 + +0..N +1 @@ -1433,68 +1433,72 @@ hitl_detail - -hitl_detail - -ti_id - - [UUID] - NOT NULL - -body - - [TEXT] - -chosen_options - - [JSON] - -defaults - - [JSON] - -multiple - - [BOOLEAN] - -options - - [JSON] - NOT NULL - -params - - [JSON] - NOT NULL - -params_input - - [JSON] - NOT NULL - -respondents - - [JSON] - -response_at - - [TIMESTAMP] - -subject - - [TEXT] - NOT NULL - -user_id - - [VARCHAR(128)] + +hitl_detail + +ti_id + + [UUID] + NOT NULL + +body + + [TEXT] + +chosen_options + + [JSON] + +defaults + + [JSON] + +multiple + + [BOOLEAN] + +options + + [JSON] + NOT NULL + +params + + [JSON] + NOT NULL + +params_input + + [JSON] + NOT NULL + +responded_user_id + + [VARCHAR(128)] + +responded_user_name + + [VARCHAR(128)] + +respondents + + [JSON] + +response_at + + [TIMESTAMP] + +subject + + [TEXT] + NOT NULL task_instance--hitl_detail - -1 -1 + +1 +1 @@ -2414,13 +2418,13 @@ alembic_version - -alembic_version - -version_num - - [VARCHAR(32)] - NOT NULL + +alembic_version + +version_num + + [VARCHAR(32)] + NOT NULL diff --git a/airflow-core/src/airflow/api_fastapi/common/parameters.py b/airflow-core/src/airflow/api_fastapi/common/parameters.py index 5dcecc6bb5c80..2351a5c0ea541 100644 --- a/airflow-core/src/airflow/api_fastapi/common/parameters.py +++ b/airflow-core/src/airflow/api_fastapi/common/parameters.py @@ -957,15 +957,27 @@ def _optional_boolean(value: bool | None) -> bool | None: ) ), ] -QueryHITLDetailUserIdFilter = Annotated[ +QueryHITLDetailRespondedUserIdFilter = Annotated[ FilterParam[list[str]], Depends( filter_param_factory( - HITLDetail.user_id, + HITLDetail.responded_user_id, list[str], FilterOptionEnum.ANY_EQUAL, default_factory=list, - filter_name="user_id", + filter_name="responded_user_id", + ) + ), +] +QueryHITLDetailRespondedUserNameFilter = Annotated[ + FilterParam[list[str]], + Depends( + filter_param_factory( + HITLDetail.responded_user_name, + list[str], + FilterOptionEnum.ANY_EQUAL, + default_factory=list, + filter_name="responded_user_name", ) ), ] diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/hitl.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/hitl.py index 09d74944c3aa7..ea0f045539ee6 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/hitl.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/hitl.py @@ -37,7 +37,8 @@ class UpdateHITLDetailPayload(BaseModel): class HITLDetailResponse(BaseModel): """Response of updating a Human-in-the-loop detail.""" - user_id: str + responded_user_id: str + responded_user_name: str response_at: datetime chosen_options: list[str] = Field(min_length=1) params_input: Mapping = Field(default_factory=dict) @@ -58,7 +59,8 @@ class HITLDetail(BaseModel): respondents: list[str] | None = None # Response Content Detail - user_id: str | None = None + responded_user_id: str | None = None + responded_user_name: str | None = None response_at: datetime | None = None chosen_options: list[str] | None = None params_input: dict[str, Any] = Field(default_factory=dict) diff --git a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml index 81f0a2acb2a8c..67e93c40c5461 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml +++ b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml @@ -8179,14 +8179,22 @@ paths: - type: boolean - type: 'null' title: Response Received - - name: user_id + - name: responded_user_id in: query required: false schema: type: array items: type: string - title: User Id + title: Responded User Id + - name: responded_user_name + in: query + required: false + schema: + type: array + items: + type: string + title: Responded User Name - name: subject_search in: query required: false @@ -10822,11 +10830,16 @@ components: type: array - type: 'null' title: Respondents - user_id: + responded_user_id: anyOf: - type: string - type: 'null' - title: User Id + title: Responded User Id + responded_user_name: + anyOf: + - type: string + - type: 'null' + title: Responded User Name response_at: anyOf: - type: string @@ -10873,9 +10886,12 @@ components: description: Schema for a collection of Human-in-the-loop details. HITLDetailResponse: properties: - user_id: + responded_user_id: + type: string + title: Responded User Id + responded_user_name: type: string - title: User Id + title: Responded User Name response_at: type: string format: date-time @@ -10892,7 +10908,8 @@ components: title: Params Input type: object required: - - user_id + - responded_user_id + - responded_user_name - response_at - chosen_options title: HITLDetailResponse diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py index 082a04f727c79..ce2774a6826d1 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py @@ -31,11 +31,12 @@ QueryHITLDetailDagIdFilter, QueryHITLDetailDagIdPatternSearch, QueryHITLDetailDagRunIdFilter, + QueryHITLDetailRespondedUserIdFilter, + QueryHITLDetailRespondedUserNameFilter, QueryHITLDetailResponseReceivedFilter, QueryHITLDetailSubjectSearch, QueryHITLDetailTaskIdFilter, QueryHITLDetailTaskIdPatternSearch, - QueryHITLDetailUserIdFilter, QueryLimit, QueryOffset, QueryTIStateFilter, @@ -121,19 +122,21 @@ def _update_hitl_detail( ), ) + user_id = user.get_id() + user_name = user.get_name() if hitl_detail_model.respondents: - user_id = user.get_id() if isinstance(user_id, int): # FabAuthManager (ab_user) store user id as integer, but common interface is string type user_id = str(user_id) if user_id not in hitl_detail_model.respondents: - log.error("User=%s is not a respondent for the task", user_id) + log.error("User=%s (id=%s) is not a respondent for the task", user_name, user_id) raise HTTPException( status.HTTP_403_FORBIDDEN, - f"User={user_id} is not a respondent for the task.", + f"User={user_name} (id={user_id}) is not a respondent for the task.", ) - hitl_detail_model.user_id = user.get_id() + hitl_detail_model.responded_user_id = user_id + hitl_detail_model.responded_user_name = user_name hitl_detail_model.response_at = timezone.utcnow() hitl_detail_model.chosen_options = update_hitl_detail_payload.chosen_options hitl_detail_model.params_input = update_hitl_detail_payload.params_input @@ -269,7 +272,8 @@ def get_hitl_details( ti_state: QueryTIStateFilter, # hitl detail related filter response_received: QueryHITLDetailResponseReceivedFilter, - user_id: QueryHITLDetailUserIdFilter, + responded_user_id: QueryHITLDetailRespondedUserIdFilter, + responded_user_name: QueryHITLDetailRespondedUserNameFilter, subject_patten: QueryHITLDetailSubjectSearch, body_patten: QueryHITLDetailBodySearch, ) -> HITLDetailCollection: @@ -292,7 +296,8 @@ def get_hitl_details( ti_state, # hitl detail related filter response_received, - user_id, + responded_user_id, + responded_user_name, subject_patten, body_patten, ], diff --git a/airflow-core/src/airflow/api_fastapi/execution_api/datamodels/hitl.py b/airflow-core/src/airflow/api_fastapi/execution_api/datamodels/hitl.py index 0a51c314a9f98..4162d2cf7717c 100644 --- a/airflow-core/src/airflow/api_fastapi/execution_api/datamodels/hitl.py +++ b/airflow-core/src/airflow/api_fastapi/execution_api/datamodels/hitl.py @@ -51,7 +51,8 @@ class HITLDetailResponse(BaseModel): """Schema for the response part of a Human-in-the-loop detail for a specific task instance.""" response_received: bool - user_id: str | None + responded_user_name: str | None + responded_user_id: str | None response_at: datetime | None # It's empty if the user has not yet responded. chosen_options: list[str] | None @@ -62,7 +63,8 @@ def from_hitl_detail_orm(cls, hitl_detail: HITLDetail) -> HITLDetailResponse: return HITLDetailResponse( response_received=hitl_detail.response_received, response_at=hitl_detail.response_at, - user_id=hitl_detail.user_id, + responded_user_id=hitl_detail.responded_user_id, + responded_user_name=hitl_detail.responded_user_name, chosen_options=hitl_detail.chosen_options, params_input=hitl_detail.params_input or {}, ) diff --git a/airflow-core/src/airflow/api_fastapi/execution_api/routes/hitl.py b/airflow-core/src/airflow/api_fastapi/execution_api/routes/hitl.py index d0a0e33278c59..c9efbda78f04a 100644 --- a/airflow-core/src/airflow/api_fastapi/execution_api/routes/hitl.py +++ b/airflow-core/src/airflow/api_fastapi/execution_api/routes/hitl.py @@ -77,7 +77,7 @@ def upsert_hitl_detail( elif hitl_detail_model.response_received: # Cleanup the response part of HITLDetail as we only store one response for one task instance. # It normally happens after retry, we keep only the latest response. - hitl_detail_model.user_id = None + hitl_detail_model.responded_by = None hitl_detail_model.response_at = None hitl_detail_model.chosen_options = None hitl_detail_model.params_input = {} @@ -116,7 +116,8 @@ def update_hitl_detail( f"Human-in-the-loop detail for Task Instance with id {ti_id_str} already exists.", ) - hitl_detail_model.user_id = "Fallback to defaults" + hitl_detail_model.responded_user_id = HITLDetail.DEFAULT_USER_NAME + hitl_detail_model.responded_user_name = HITLDetail.DEFAULT_USER_NAME hitl_detail_model.response_at = datetime.now(timezone.utc) hitl_detail_model.chosen_options = payload.chosen_options hitl_detail_model.params_input = payload.params_input diff --git a/airflow-core/src/airflow/migrations/versions/0076_3_1_0_add_human_in_the_loop_response.py b/airflow-core/src/airflow/migrations/versions/0076_3_1_0_add_human_in_the_loop_response.py index 2bffd734109c4..3e0ede0183ee1 100644 --- a/airflow-core/src/airflow/migrations/versions/0076_3_1_0_add_human_in_the_loop_response.py +++ b/airflow-core/src/airflow/migrations/versions/0076_3_1_0_add_human_in_the_loop_response.py @@ -61,7 +61,8 @@ def upgrade(): Column("params", sqlalchemy_jsonfield.JSONField(json=json), nullable=False, default={}), Column("respondents", sqlalchemy_jsonfield.JSONField(json=json), nullable=True), Column("response_at", UtcDateTime, nullable=True), - Column("user_id", String(128), nullable=True), + Column("responded_user_id", String(128), nullable=True), + Column("responded_user_name", String(128), nullable=True), Column("chosen_options", sqlalchemy_jsonfield.JSONField(json=json), nullable=True), Column("params_input", sqlalchemy_jsonfield.JSONField(json=json), nullable=False, default={}), ForeignKeyConstraint( diff --git a/airflow-core/src/airflow/models/hitl.py b/airflow-core/src/airflow/models/hitl.py index 068441d6d2e1d..448939e2c6f61 100644 --- a/airflow-core/src/airflow/models/hitl.py +++ b/airflow-core/src/airflow/models/hitl.py @@ -48,7 +48,8 @@ class HITLDetail(Base): # Response Content Detail response_at = Column(UtcDateTime, nullable=True) - user_id = Column(String(128), nullable=True) + responded_user_id = Column(String(128), nullable=True) + responded_user_name = Column(String(128), nullable=True) chosen_options = Column( sqlalchemy_jsonfield.JSONField(json=json), nullable=True, @@ -78,3 +79,5 @@ def response_received(self) -> bool: @response_received.expression # type: ignore[no-redef] def response_received(cls): return cls.response_at.is_not(None) + + DEFAULT_USER_NAME = "Fallback to defaults" diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts index ba486a353aac5..9ceb20e3948fe 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts @@ -713,7 +713,7 @@ export const UseHumanInTheLoopServiceGetHitlDetailKeyFn = ({ dagId, dagRunId, ma export type HumanInTheLoopServiceGetHitlDetailsDefaultResponse = Awaited>; export type HumanInTheLoopServiceGetHitlDetailsQueryResult = UseQueryResult; export const useHumanInTheLoopServiceGetHitlDetailsKey = "HumanInTheLoopServiceGetHitlDetails"; -export const UseHumanInTheLoopServiceGetHitlDetailsKeyFn = ({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, responseReceived, state, subjectSearch, taskId, taskIdPattern, userId }: { +export const UseHumanInTheLoopServiceGetHitlDetailsKeyFn = ({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedUserId, respondedUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: { bodySearch?: string; dagId?: string; dagIdPattern?: string; @@ -721,13 +721,14 @@ export const UseHumanInTheLoopServiceGetHitlDetailsKeyFn = ({ bodySearch, dagId, limit?: number; offset?: number; orderBy?: string[]; + respondedUserId?: string[]; + respondedUserName?: string[]; responseReceived?: boolean; state?: string[]; subjectSearch?: string; taskId?: string; taskIdPattern?: string; - userId?: string[]; -} = {}, queryKey?: Array) => [useHumanInTheLoopServiceGetHitlDetailsKey, ...(queryKey ?? [{ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, responseReceived, state, subjectSearch, taskId, taskIdPattern, userId }])]; +} = {}, queryKey?: Array) => [useHumanInTheLoopServiceGetHitlDetailsKey, ...(queryKey ?? [{ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedUserId, respondedUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }])]; export type MonitorServiceGetHealthDefaultResponse = Awaited>; export type MonitorServiceGetHealthQueryResult = UseQueryResult; export const useMonitorServiceGetHealthKey = "MonitorServiceGetHealth"; diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts index 2f44048e710b8..01e19b91afee7 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts @@ -1363,13 +1363,14 @@ export const ensureUseHumanInTheLoopServiceGetHitlDetailData = (queryClient: Que * @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @param data.state * @param data.responseReceived -* @param data.userId +* @param data.respondedUserId +* @param data.respondedUserName * @param data.subjectSearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @param data.bodySearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @returns HITLDetailCollection Successful Response * @throws ApiError */ -export const ensureUseHumanInTheLoopServiceGetHitlDetailsData = (queryClient: QueryClient, { bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, responseReceived, state, subjectSearch, taskId, taskIdPattern, userId }: { +export const ensureUseHumanInTheLoopServiceGetHitlDetailsData = (queryClient: QueryClient, { bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedUserId, respondedUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: { bodySearch?: string; dagId?: string; dagIdPattern?: string; @@ -1377,13 +1378,14 @@ export const ensureUseHumanInTheLoopServiceGetHitlDetailsData = (queryClient: Qu limit?: number; offset?: number; orderBy?: string[]; + respondedUserId?: string[]; + respondedUserName?: string[]; responseReceived?: boolean; state?: string[]; subjectSearch?: string; taskId?: string; taskIdPattern?: string; - userId?: string[]; -} = {}) => queryClient.ensureQueryData({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, responseReceived, state, subjectSearch, taskId, taskIdPattern, userId }), queryFn: () => HumanInTheLoopService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, responseReceived, state, subjectSearch, taskId, taskIdPattern, userId }) }); +} = {}) => queryClient.ensureQueryData({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedUserId, respondedUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }), queryFn: () => HumanInTheLoopService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedUserId, respondedUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }) }); /** * Get Health * @returns HealthInfoResponse Successful Response diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts index d91da2d7f0732..d2bfe420b190b 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts @@ -1363,13 +1363,14 @@ export const prefetchUseHumanInTheLoopServiceGetHitlDetail = (queryClient: Query * @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @param data.state * @param data.responseReceived -* @param data.userId +* @param data.respondedUserId +* @param data.respondedUserName * @param data.subjectSearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @param data.bodySearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @returns HITLDetailCollection Successful Response * @throws ApiError */ -export const prefetchUseHumanInTheLoopServiceGetHitlDetails = (queryClient: QueryClient, { bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, responseReceived, state, subjectSearch, taskId, taskIdPattern, userId }: { +export const prefetchUseHumanInTheLoopServiceGetHitlDetails = (queryClient: QueryClient, { bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedUserId, respondedUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: { bodySearch?: string; dagId?: string; dagIdPattern?: string; @@ -1377,13 +1378,14 @@ export const prefetchUseHumanInTheLoopServiceGetHitlDetails = (queryClient: Quer limit?: number; offset?: number; orderBy?: string[]; + respondedUserId?: string[]; + respondedUserName?: string[]; responseReceived?: boolean; state?: string[]; subjectSearch?: string; taskId?: string; taskIdPattern?: string; - userId?: string[]; -} = {}) => queryClient.prefetchQuery({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, responseReceived, state, subjectSearch, taskId, taskIdPattern, userId }), queryFn: () => HumanInTheLoopService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, responseReceived, state, subjectSearch, taskId, taskIdPattern, userId }) }); +} = {}) => queryClient.prefetchQuery({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedUserId, respondedUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }), queryFn: () => HumanInTheLoopService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedUserId, respondedUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }) }); /** * Get Health * @returns HealthInfoResponse Successful Response diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts index be2271f380feb..5afeeb81a7e5f 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts @@ -1363,13 +1363,14 @@ export const useHumanInTheLoopServiceGetHitlDetail = = unknown[]>({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, responseReceived, state, subjectSearch, taskId, taskIdPattern, userId }: { +export const useHumanInTheLoopServiceGetHitlDetails = = unknown[]>({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedUserId, respondedUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: { bodySearch?: string; dagId?: string; dagIdPattern?: string; @@ -1377,13 +1378,14 @@ export const useHumanInTheLoopServiceGetHitlDetails = , "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, responseReceived, state, subjectSearch, taskId, taskIdPattern, userId }, queryKey), queryFn: () => HumanInTheLoopService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, responseReceived, state, subjectSearch, taskId, taskIdPattern, userId }) as TData, ...options }); +} = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedUserId, respondedUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }, queryKey), queryFn: () => HumanInTheLoopService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedUserId, respondedUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }) as TData, ...options }); /** * Get Health * @returns HealthInfoResponse Successful Response diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts index 59612c368987b..0c363423c2d2a 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts @@ -1363,13 +1363,14 @@ export const useHumanInTheLoopServiceGetHitlDetailSuspense = = unknown[]>({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, responseReceived, state, subjectSearch, taskId, taskIdPattern, userId }: { +export const useHumanInTheLoopServiceGetHitlDetailsSuspense = = unknown[]>({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedUserId, respondedUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: { bodySearch?: string; dagId?: string; dagIdPattern?: string; @@ -1377,13 +1378,14 @@ export const useHumanInTheLoopServiceGetHitlDetailsSuspense = , "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, responseReceived, state, subjectSearch, taskId, taskIdPattern, userId }, queryKey), queryFn: () => HumanInTheLoopService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, responseReceived, state, subjectSearch, taskId, taskIdPattern, userId }) as TData, ...options }); +} = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedUserId, respondedUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }, queryKey), queryFn: () => HumanInTheLoopService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedUserId, respondedUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }) as TData, ...options }); /** * Get Health * @returns HealthInfoResponse Successful Response diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts index 033cfa654a9d6..96c41495cea6a 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts @@ -3563,7 +3563,7 @@ export const $HITLDetail = { ], title: 'Respondents' }, - user_id: { + responded_user_id: { anyOf: [ { type: 'string' @@ -3572,7 +3572,18 @@ export const $HITLDetail = { type: 'null' } ], - title: 'User Id' + title: 'Responded User Id' + }, + responded_user_name: { + anyOf: [ + { + type: 'string' + }, + { + type: 'null' + } + ], + title: 'Responded User Name' }, response_at: { anyOf: [ @@ -3639,9 +3650,13 @@ export const $HITLDetailCollection = { export const $HITLDetailResponse = { properties: { - user_id: { + responded_user_id: { + type: 'string', + title: 'Responded User Id' + }, + responded_user_name: { type: 'string', - title: 'User Id' + title: 'Responded User Name' }, response_at: { type: 'string', @@ -3663,7 +3678,7 @@ export const $HITLDetailResponse = { } }, type: 'object', - required: ['user_id', 'response_at', 'chosen_options'], + required: ['responded_user_id', 'responded_user_name', 'response_at', 'chosen_options'], title: 'HITLDetailResponse', description: 'Response of updating a Human-in-the-loop detail.' } as const; diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts index f04bbe72a787f..ccf2fae7cb99f 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts @@ -3615,7 +3615,8 @@ export class HumanInTheLoopService { * @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @param data.state * @param data.responseReceived - * @param data.userId + * @param data.respondedUserId + * @param data.respondedUserName * @param data.subjectSearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @param data.bodySearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @returns HITLDetailCollection Successful Response @@ -3636,7 +3637,8 @@ export class HumanInTheLoopService { task_id_pattern: data.taskIdPattern, state: data.state, response_received: data.responseReceived, - user_id: data.userId, + responded_user_id: data.respondedUserId, + responded_user_name: data.respondedUserName, subject_search: data.subjectSearch, body_search: data.bodySearch }, diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts index ea0b228d78694..68d79d3f4d922 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts @@ -939,7 +939,8 @@ export type HITLDetail = { [key: string]: unknown; }; respondents?: Array<(string)> | null; - user_id?: string | null; + responded_user_id?: string | null; + responded_user_name?: string | null; response_at?: string | null; chosen_options?: Array<(string)> | null; params_input?: { @@ -960,7 +961,8 @@ export type HITLDetailCollection = { * Response of updating a Human-in-the-loop detail. */ export type HITLDetailResponse = { - user_id: string; + responded_user_id: string; + responded_user_name: string; response_at: string; chosen_options: Array<(string)>; params_input?: { @@ -3084,6 +3086,8 @@ export type GetHitlDetailsData = { limit?: number; offset?: number; orderBy?: Array<(string)>; + respondedUserId?: Array<(string)>; + respondedUserName?: Array<(string)>; responseReceived?: boolean | null; state?: Array<(string)>; /** @@ -3095,7 +3099,6 @@ export type GetHitlDetailsData = { * SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. */ taskIdPattern?: string | null; - userId?: Array<(string)>; }; export type GetHitlDetailsResponse = HITLDetailCollection; diff --git a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_hitl.py b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_hitl.py index 25fc0e327385f..55749f251895e 100644 --- a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_hitl.py +++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_hitl.py @@ -171,7 +171,8 @@ def sample_hitl_details(sample_tis: list[TaskInstance], session: Session) -> lis response_at=utcnow(), chosen_options=[str(i)], params_input={"input": i}, - user_id="test", + responded_user_id="test", + responded_user_name="test", ) for i, ti in enumerate(sample_tis[5:]) ] @@ -211,7 +212,8 @@ def expected_sample_hitl_detail_dict(sample_ti: TaskInstance) -> dict[str, Any]: "chosen_options": None, "response_received": False, "subject": "This is subject", - "user_id": None, + "responded_user_id": None, + "responded_user_name": None, "task_instance": { "dag_display_name": DAG_ID, "dag_id": DAG_ID, @@ -317,7 +319,8 @@ def test_should_respond_200_with_existing_response( assert response.json() == { "params_input": {"input_1": 2}, "chosen_options": ["Approve"], - "user_id": "test", + "responded_user_id": "test", + "responded_user_name": "test", "response_at": "2025-07-03T00:00:00Z", } @@ -346,7 +349,8 @@ def test_should_respond_200_to_respondent_user( assert response.json() == { "params_input": {"input_1": 2}, "chosen_options": ["Approve"], - "user_id": "test", + "responded_user_id": "test", + "responded_user_name": "test", "response_at": "2025-07-03T00:00:00Z", } @@ -447,7 +451,8 @@ def test_should_respond_409( expected_response = { "params_input": {"input_1": 2}, "chosen_options": ["Approve"], - "user_id": "test", + "responded_user_id": "test", + "responded_user_name": "test", "response_at": "2025-07-03T00:00:00Z", } assert response.status_code == 200 @@ -572,7 +577,8 @@ def test_should_respond_200_with_existing_response( ({"body_search": "this is"}, 8), ({"response_received": False}, 5), ({"response_received": True}, 3), - ({"user_id": ["test"]}, 3), + ({"responded_user_id": ["test"]}, 3), + ({"responded_user_name": ["test"]}, 3), ], ids=[ "dag_id_pattern_hitl_dag", @@ -587,7 +593,8 @@ def test_should_respond_200_with_existing_response( "body", "response_not_received", "response_received", - "user_id", + "responded_user_id", + "responded_user_name", ], ) def test_should_respond_200_with_existing_response_and_query( diff --git a/airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_hitl.py b/airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_hitl.py index 5a4322fadaa8b..085fc7ae6a8b3 100644 --- a/airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_hitl.py +++ b/airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_hitl.py @@ -50,7 +50,8 @@ expected_empty_hitl_detail_response_part: dict[str, Any] = { "response_at": None, "chosen_options": None, - "user_id": None, + "responded_user_id": None, + "responded_user_name": None, "params_input": {}, "response_received": False, } @@ -93,7 +94,8 @@ def expected_sample_hitl_detail_dict(sample_ti: TaskInstance) -> dict[str, Any]: "params_input": {"input_1": 2}, "response_at": convert_to_utc(datetime(2025, 7, 3, 0, 0, 0)), "chosen_options": ["Reject"], - "user_id": "Fallback to defaults", + "responded_user_id": "Fallback to defaults", + "responded_user_name": "Fallback to defaults", }, }, ], @@ -170,7 +172,8 @@ def test_update_hitl_detail(client: Client, sample_ti: TaskInstance) -> None: "response_at": "2025-07-03T00:00:00Z", "chosen_options": ["Reject"], "response_received": True, - "user_id": "Fallback to defaults", + "responded_user_id": "Fallback to defaults", + "responded_user_name": "Fallback to defaults", } diff --git a/airflow-ctl/src/airflowctl/api/datamodels/generated.py b/airflow-ctl/src/airflowctl/api/datamodels/generated.py index 1fe8689c3c889..5d4db60952716 100644 --- a/airflow-ctl/src/airflowctl/api/datamodels/generated.py +++ b/airflow-ctl/src/airflowctl/api/datamodels/generated.py @@ -530,7 +530,8 @@ class HITLDetailResponse(BaseModel): Response of updating a Human-in-the-loop detail. """ - user_id: Annotated[str, Field(title="User Id")] + responded_user_id: Annotated[str, Field(title="Responded User Id")] + responded_user_name: Annotated[str, Field(title="Responded User Name")] response_at: Annotated[datetime, Field(title="Response At")] chosen_options: Annotated[list[str], Field(min_length=1, title="Chosen Options")] params_input: Annotated[dict[str, Any] | None, Field(title="Params Input")] = None @@ -1826,7 +1827,8 @@ class HITLDetail(BaseModel): multiple: Annotated[bool | None, Field(title="Multiple")] = False params: Annotated[dict[str, Any] | None, Field(title="Params")] = None respondents: Annotated[list[str] | None, Field(title="Respondents")] = None - user_id: Annotated[str | None, Field(title="User Id")] = None + responded_user_id: Annotated[str | None, Field(title="Responded User Id")] = None + responded_user_name: Annotated[str | None, Field(title="Responded User Name")] = None response_at: Annotated[datetime | None, Field(title="Response At")] = None chosen_options: Annotated[list[str] | None, Field(title="Chosen Options")] = None params_input: Annotated[dict[str, Any] | None, Field(title="Params Input")] = None diff --git a/providers/standard/src/airflow/providers/standard/triggers/hitl.py b/providers/standard/src/airflow/providers/standard/triggers/hitl.py index 82ee829ac8321..36adcbb2a4a57 100644 --- a/providers/standard/src/airflow/providers/standard/triggers/hitl.py +++ b/providers/standard/src/airflow/providers/standard/triggers/hitl.py @@ -127,7 +127,11 @@ async def run(self) -> AsyncIterator[TriggerEvent]: resp = await sync_to_async(get_hitl_detail_content_detail)(ti_id=self.ti_id) if resp.response_received and resp.chosen_options: self.log.info( - "[HITL] user=%s options=%s at %s", resp.user_id, resp.chosen_options, resp.response_at + "[HITL] responded_by=%s (id=%s) options=%s at %s", + resp.responded_user_name, + resp.responded_user_id, + resp.chosen_options, + resp.response_at, ) yield TriggerEvent( HITLTriggerEventSuccessPayload( diff --git a/providers/standard/tests/unit/standard/operators/test_hitl.py b/providers/standard/tests/unit/standard/operators/test_hitl.py index ca0b0ae9f4f9a..18646ab118dd6 100644 --- a/providers/standard/tests/unit/standard/operators/test_hitl.py +++ b/providers/standard/tests/unit/standard/operators/test_hitl.py @@ -183,7 +183,8 @@ def test_execute(self, dag_maker: DagMaker, session: Session) -> None: assert hitl_detail_model.params == {"input_1": 1} assert hitl_detail_model.respondents == ["test"] assert hitl_detail_model.response_at is None - assert hitl_detail_model.user_id is None + assert hitl_detail_model.responded_user_id is None + assert hitl_detail_model.responded_user_name is None assert hitl_detail_model.chosen_options is None assert hitl_detail_model.params_input == {} diff --git a/providers/standard/tests/unit/standard/triggers/test_hitl.py b/providers/standard/tests/unit/standard/triggers/test_hitl.py index fe7900d3fbdf9..e4652ecd2ba2c 100644 --- a/providers/standard/tests/unit/standard/triggers/test_hitl.py +++ b/providers/standard/tests/unit/standard/triggers/test_hitl.py @@ -79,7 +79,8 @@ async def test_run_failed_due_to_timeout(self, mock_update, mock_supervisor_comm ) mock_supervisor_comms.send.return_value = HITLDetailResponse( response_received=False, - user_id=None, + responded_user_id=None, + responded_user_name=None, response_at=None, chosen_options=None, params_input={}, @@ -109,7 +110,8 @@ async def test_run_fallback_to_default_due_to_timeout(self, mock_update, mock_lo ) mock_supervisor_comms.send.return_value = HITLDetailResponse( response_received=False, - user_id=None, + responded_user_id=None, + responded_user_name=None, response_at=None, chosen_options=None, params_input={}, @@ -143,7 +145,8 @@ async def test_run(self, mock_update, mock_log, mock_supervisor_comms, time_mach ) mock_supervisor_comms.send.return_value = HITLDetailResponse( response_received=True, - user_id="test", + responded_user_id="test", + responded_user_name="test", response_at=utcnow(), chosen_options=["3"], params_input={"input": 50}, @@ -162,7 +165,8 @@ async def test_run(self, mock_update, mock_log, mock_supervisor_comms, time_mach ) assert mock_log.info.call_args == mock.call( - "[HITL] user=%s options=%s at %s", + "[HITL] responded_by=%s (id=%s) options=%s at %s", + "test", "test", ["3"], datetime(2025, 7, 29, 2, 0, 0, tzinfo=utc), diff --git a/task-sdk/src/airflow/sdk/api/datamodels/_generated.py b/task-sdk/src/airflow/sdk/api/datamodels/_generated.py index 3eb44c2f06f12..cd861bf07d124 100644 --- a/task-sdk/src/airflow/sdk/api/datamodels/_generated.py +++ b/task-sdk/src/airflow/sdk/api/datamodels/_generated.py @@ -175,7 +175,8 @@ class HITLDetailResponse(BaseModel): """ response_received: Annotated[bool, Field(title="Response Received")] - user_id: Annotated[str | None, Field(title="User Id")] = None + responded_user_name: Annotated[str | None, Field(title="Responded User Name")] = None + responded_user_id: Annotated[str | None, Field(title="Responded User Id")] = None response_at: Annotated[AwareDatetime | None, Field(title="Response At")] = None chosen_options: Annotated[list[str] | None, Field(title="Chosen Options")] = None params_input: Annotated[dict[str, Any] | None, Field(title="Params Input")] = None diff --git a/task-sdk/tests/task_sdk/api/test_client.py b/task-sdk/tests/task_sdk/api/test_client.py index 966ac729d0aff..986ab5fe5e8bf 100644 --- a/task-sdk/tests/task_sdk/api/test_client.py +++ b/task-sdk/tests/task_sdk/api/test_client.py @@ -1302,7 +1302,8 @@ def handle_request(request: httpx.Request) -> httpx.Response: json={ "chosen_options": ["Approval"], "params_input": {}, - "user_id": "admin", + "responded_user_id": "admin", + "responded_user_name": "admin", "response_received": True, "response_at": "2025-07-03T00:00:00Z", }, @@ -1319,7 +1320,8 @@ def handle_request(request: httpx.Request) -> httpx.Response: assert result.response_received is True assert result.chosen_options == ["Approval"] assert result.params_input == {} - assert result.user_id == "admin" + assert result.responded_user_id == "admin" + assert result.responded_user_name == "admin" assert result.response_at == timezone.datetime(2025, 7, 3, 0, 0, 0) def test_get_detail_response(self, time_machine: TimeMachineFixture) -> None: @@ -1333,7 +1335,8 @@ def handle_request(request: httpx.Request) -> httpx.Response: json={ "chosen_options": ["Approval"], "params_input": {}, - "user_id": "admin", + "responded_user_id": "admin", + "responded_user_name": "admin", "response_received": True, "response_at": "2025-07-03T00:00:00Z", }, @@ -1346,5 +1349,6 @@ def handle_request(request: httpx.Request) -> httpx.Response: assert result.response_received is True assert result.chosen_options == ["Approval"] assert result.params_input == {} - assert result.user_id == "admin" + assert result.responded_user_id == "admin" + assert result.responded_user_name == "admin" assert result.response_at == timezone.datetime(2025, 7, 3, 0, 0, 0) diff --git a/task-sdk/tests/task_sdk/execution_time/test_hitl.py b/task-sdk/tests/task_sdk/execution_time/test_hitl.py index 5ad6733eb089f..a5ed016f44de8 100644 --- a/task-sdk/tests/task_sdk/execution_time/test_hitl.py +++ b/task-sdk/tests/task_sdk/execution_time/test_hitl.py @@ -62,7 +62,8 @@ def test_update_hitl_detail_response(mock_supervisor_comms) -> None: response_received=True, chosen_options=["Approve"], response_at=timestamp, - user_id="admin", + responded_user_id="admin", + responded_user_name="admin", params_input={"input_1": 1}, ) resp = update_hitl_detail_response( @@ -74,7 +75,8 @@ def test_update_hitl_detail_response(mock_supervisor_comms) -> None: response_received=True, chosen_options=["Approve"], response_at=timestamp, - user_id="admin", + responded_user_id="admin", + responded_user_name="admin", params_input={"input_1": 1}, ) @@ -84,7 +86,8 @@ def test_get_hitl_detail_content_detail(mock_supervisor_comms) -> None: response_received=False, chosen_options=None, response_at=None, - user_id=None, + responded_user_id=None, + responded_user_name=None, params_input={}, ) resp = get_hitl_detail_content_detail(TI_ID) @@ -92,6 +95,7 @@ def test_get_hitl_detail_content_detail(mock_supervisor_comms) -> None: response_received=False, chosen_options=None, response_at=None, - user_id=None, + responded_user_id=None, + responded_user_name=None, params_input={}, )