PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
← All changes | inc/AI/Assistant/Agent.php +54 -6 4.4.04.4.8 View file →
@@ -39,14 +39,20 @@
39 39
40 40 /**
41 41 * Run the assistant agent loop.
42 42 *
43 + * Callers must pass an $item_type already resolved and authorized by
44 + * AIAssistantController::resolve_item_access(). This method routes on it but does
45 + * not authorize — it is not a security boundary.
46 + *
43 47 * @param string $user_message The learner's message.
44 - * @param int $item_id Current lesson ID.
48 + * @param int $item_id Current course item ID, type proven by $item_type.
49 + * @param string $item_type Resolved curriculum type: LP_LESSON_CPT or LP_QUIZ_CPT.
45 50 * @param int $course_id Current course ID.
46 51 * @param int $user_id Current user ID.
47 52 * @param array $history Previous conversation messages (role/content pairs).
48 53 * @param array $active_quiz Active quiz state for quiz-mode continuation.
54 + * @param string $action_hint Optional validated quick-action hint.
49 55 *
50 56 * @return array{type: string, message: string, quiz: array|null}
51 57 */
52 58 public function run(
@@ -51,8 +57,9 @@
51 57 */
52 58 public function run(
53 59 string $user_message,
54 60 int $item_id,
61 + string $item_type,
55 62 int $course_id,
56 63 int $user_id,
57 64 array $history = array(),
58 65 array $active_quiz = array(),
@@ -61,10 +68,24 @@
61 68
62 69 $this->quota_guard->reset();
63 70 $data_loaders = new DataLoaders();
64 71
65 - // Resume active quiz session.
72 + $is_lesson = LP_LESSON_CPT === $item_type;
73 + $is_quiz = LP_QUIZ_CPT === $item_type;
74 +
75 + if ( ! $is_lesson && ! $is_quiz ) {
76 + return $this->normalizer->build_response(
77 + __( 'The AI Assistant is not available for this type of course item.', 'learnpress' )
78 + );
79 + }
80 +
81 + // Resume active quiz session. Quick quiz is generated from lesson content, so a
82 + // session may only continue while the authorized context is still a lesson.
66 83 if ( ! empty( $active_quiz['is_active'] ) && empty( $active_quiz['completed'] ) ) {
84 + if ( ! $is_lesson ) {
85 + return $this->get_lesson_only_response();
86 + }
87 +
67 88 if ( ! AIAssistantController::is_action_enabled( IntentClassifier::INTENT_QUICK_QUIZ ) ) {
68 89 return $this->get_disabled_action_response( IntentClassifier::INTENT_QUICK_QUIZ );
69 90 }
70 91
@@ -81,8 +102,27 @@
81 102 if ( $this->requires_action_gate( $intent ) && ! AIAssistantController::is_action_enabled( $intent ) ) {
82 103 return $this->get_disabled_action_response( $intent );
83 104 }
84 105
106 + /**
107 + * Typed routing. Smart Review reads a quiz attempt; every other intent is
108 + * grounded in lesson content. $item_id is only renamed to $quiz_id/$lesson_id
109 + * once the corresponding type check has passed.
110 + */
111 + if ( IntentClassifier::INTENT_SMART_REVIEW === $intent ) {
112 + if ( ! $is_quiz ) {
113 + return $this->normalizer->build_response(
114 + __( 'Smart Review is only available on a quiz you have completed.', 'learnpress' )
115 + );
116 + }
117 +
118 + return $this->handle_smart_review( $data_loaders, $user_message, $user_id, $course_id, $item_id, $history );
119 + }
120 +
121 + if ( ! $is_lesson ) {
122 + return $this->get_lesson_only_response();
123 + }
124 +
85 125 switch ( $intent ) {
86 126 case IntentClassifier::INTENT_SUMMARIZE:
87 127 return $this->handle_summarize( $data_loaders, $user_message, $item_id, $user_id, $history );
88 128
@@ -88,11 +128,8 @@
88 128
89 129 case IntentClassifier::INTENT_EXPLAIN:
90 130 return $this->handle_explain( $data_loaders, $user_message, $item_id, $user_id, $history );
91 131
92 - case IntentClassifier::INTENT_SMART_REVIEW:
93 - return $this->handle_smart_review( $data_loaders, $user_message, $user_id, $course_id, $item_id, $history );
94 -
95 132 case IntentClassifier::INTENT_QUICK_QUIZ:
96 133 return $this->quiz_engine->start( $data_loaders, $user_message, $item_id, $user_id, $history );
97 134
98 135 case IntentClassifier::INTENT_GENERAL:
@@ -105,9 +142,9 @@
105 142 * Resolve final intent, prioritizing an explicit validated action hint.
106 143 *
107 144 * @param string $user_message Learner input.
108 145 * @param array $history Conversation history.
109 - * @param int $item_id Current lesson ID.
146 + * @param int $item_id Current course item ID (lesson or quiz).
110 147 * @param int $course_id Current course ID.
111 148 * @param int $user_id Current user ID.
112 149 * @param string|null $action_hint Optional quick-action hint from frontend.
113 150 *
@@ -368,8 +405,19 @@
368 405 IntentClassifier::INTENT_QUICK_QUIZ,
369 406 IntentClassifier::INTENT_SMART_REVIEW,
370 407 ),
371 408 true
409 + );
410 + }
411 +
412 + /**
413 + * Build a user-facing response for an action that requires a lesson context.
414 + *
415 + * @return array{type: string, message: string, quiz: array|null}
416 + */
417 + private function get_lesson_only_response(): array {
418 + return $this->normalizer->build_response(
419 + __( 'This assistant action is only available on a lesson.', 'learnpress' )
372 420 );
373 421 }
374 422
375 423 /**