@burdenoff/microfe-buildmyiq 2026.1028.1 → 2026.1029.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"useBuildmyiqApi.d.ts","sourceRoot":"","sources":["../../../src/buildmyiq/hooks/useBuildmyiqApi.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useBuildmyiqApi.d.ts","sourceRoot":"","sources":["../../../src/buildmyiq/hooks/useBuildmyiqApi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,EAA0B,KAAK,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAChG,OAAO,KAAK,EACV,aAAa,EACb,SAAS,EACT,cAAc,EACd,eAAe,EACf,SAAS,EACT,SAAS,EACT,aAAa,EACb,mBAAmB,EACnB,WAAW,EACX,aAAa,EACb,mBAAmB,EACnB,aAAa,EACb,mBAAmB,EACnB,SAAS,EACT,eAAe,EACf,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,yBAAyB,EACzB,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,4BAA4B,EAC5B,wBAAwB,EACxB,uBAAuB,EACvB,wBAAwB,EACxB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,yBAAyB,EACzB,kBAAkB,EAClB,uBAAuB,EACvB,0BAA0B,EAC1B,0BAA0B,EAC1B,4BAA4B,EAC5B,4BAA4B,EAC5B,8BAA8B,EAC9B,yBAAyB,EACzB,2BAA2B,EAC3B,qBAAqB,EACrB,wBAAwB,EACxB,6BAA6B,EAC7B,wBAAwB,EACxB,sBAAsB,EACtB,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EAClB,2BAA2B,EAC3B,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,2BAA2B,EAC3B,wBAAwB,EAEzB,MAAM,UAAU,CAAC;AA6QlB,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,aAAa,GAAI,OAAM,iBAAsB;;iBAoCT,SAAS,EAAE;iBACX,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;UAM3D,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,IAAI,MAAM,GAAG,SAAS,qFAgBlD,CAAC;AAEF,eAAO,MAAM,kBAAkB,0GAgB9B,CAAC;AAEF,eAAO,MAAM,kBAAkB;QAII,MAAM;WAAS,oBAAoB;WAerE,CAAC;AAEF,eAAO,MAAM,mBAAmB,4FAmB/B,CAAC;AAEF,eAAO,MAAM,mBAAmB,0FAiB/B,CAAC;AAMF,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,GAAG,SAAS;;;;;;;;;;YAkBzD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,GAAG,SAAS,EAAE,WAAW,MAAM,gFAgB5E,CAAC;AAEF,eAAO,MAAM,kBAAkB,0GAmB9B,CAAC;AAEF,eAAO,MAAM,kBAAkB,0GAoB9B,CAAC;AAMF,eAAO,MAAM,iBAAiB,GAAI,UAAU,MAAM,GAAG,SAAS,EAAE,SAAS,mBAAmB;eA8BzC,WAAW,EAAE;;;;;;;;;;;;;;;YAI/D,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,IAAI,MAAM,GAAG,SAAS,yFAgBtD,CAAC;AAEF,eAAO,MAAM,sBAAsB,kHAgBlC,CAAC;AAEF,eAAO,MAAM,uBAAuB,gGAmBnC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB;QAID,MAAM;cAAY,MAAM;WAa1D,CAAC;AAEF,eAAO,MAAM,oBAAoB,8GAgBhC,CAAC;AAMF,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,iBAAiB,GAAI,OAAM,qBAA0B,iGAoBjE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAM,qBAA0B,iGAoBnE,CAAC;AAEF,kGAAkG;AAClG,eAAO,MAAM,gBAAgB,GAAI,IAAI,MAAM,GAAG,SAAS,yFAgBtD,CAAC;AAEF,eAAO,MAAM,sBAAsB,kHAgBlC,CAAC;AAEF,eAAO,MAAM,qBAAqB;QAIC,MAAM;WAAS,uBAAuB;WAYxE,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,gGAmBrC,CAAC;AAMF,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAM,qBAA0B,iGAoBjE,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,GAAI,OAAM,qBAA0B,iGAoBnE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,IAAI,MAAM,GAAG,SAAS,yFAgBtD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,IAAI,MAAM,GAAG,SAAS,yFAkBxD,CAAC;AAEF,eAAO,MAAM,YAAY,wGAgBxB,CAAC;AAEF,eAAO,MAAM,0BAA0B;QAIJ,MAAM;WAexC,CAAC;AAEF,eAAO,MAAM,4BAA4B,0HAmBxC,CAAC;AAMF,eAAO,MAAM,aAAa,GAAI,WAAW,MAAM,EAAE,SAAS,eAAe,gFAexE,CAAC;AAEF,eAAO,MAAM,kBAAkB,0GAgB9B,CAAC;AAMF,eAAO,MAAM,YAAY,GAAI,WAAW,gBAAgB,+EAevD,CAAC;AAEF,eAAO,MAAM,iBAAiB,wGAgB7B,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,SAAS,gBAAgB,CAAC,QAAQ,CAAC,EACnC,WAAW,gBAAgB,EAC3B,iBAAc,uFAiBf,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,OAAO,gBAAgB,CAAC,MAAM,CAAC,EAAE,iBAAc,uFAgBnF,CAAC;AAEF,eAAO,MAAM,0BAA0B,GAAI,MAAM,MAAM,EAAE,cAAc,MAAM,EAAE,iBAAc,gGAoB5F,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,WAAW,MAAM,EAAE,iBAAc,qFAgBnE,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,GAAI,WAAW,MAAM,EAAE,iBAAc,qFAgBrE,CAAC;AAEF,eAAO,MAAM,sBAAsB,mHAgBlC,CAAC;AAEF,eAAO,MAAM,uBAAuB,iGAgBnC,CAAC;AAMF;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEhD;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,cAAc,MAAM,GAAG,SAAS,wEA2B/D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,GAAI,UAAU,MAAM,GAAG,SAAS,sFAgBjE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,+GAsB1B,CAAC;AAMF,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,GAAI,OAAM,6BAAkC,mGAsBjF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,qHAoBnC,CAAC;AAeF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,qGAc9B,CAAC;AAEF,2GAA2G;AAC3G,eAAO,MAAM,2BAA2B;QAGL,MAAM;aAAW,sBAAsB;WAWzE,CAAC;AAOF;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,0GAcnC,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,gCAAgC;QAGV,MAAM;aAAW,sBAAsB;WAWzE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,0BAA0B;WAI1B,MAAM;oBACG,MAAM,GAAG,IAAI;kBACf,MAAM,GAAG,IAAI;mBACZ,MAAM,EAAE,GAAG,IAAI;WAgBnC,CAAC;AAEF,2FAA2F;AAC3F,eAAO,MAAM,wBAAwB,gHAgBpC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,uIAmBxC,CAAC;AAEF,mFAAmF;AACnF,eAAO,MAAM,0BAA0B,sHAgBtC,CAAC;AAgBF,eAAO,MAAM,qBAAqB;cAIO,MAAM;aAAW,wBAAwB,EAAE;WAmBnF,CAAC;AAEF,0FAA0F;AAC1F,eAAO,MAAM,yBAAyB,GAAI,SAAS,2BAA2B,EAAE,cAAU,oGAezF,CAAC;AASF;;;GAGG;AACH,eAAO,MAAM,+BAA+B;cAIH,MAAM;UAAQ,yBAAyB;WA0B/E,CAAC;AAEF,eAAO,MAAM,+BAA+B,gHAgB3C,CAAC;AAWF,eAAO,MAAM,kBAAkB,wFAa9B,CAAC;AAEF,eAAO,MAAM,yBAAyB,sHAgBrC,CAAC;AAEF,eAAO,MAAM,2BAA2B,0FAcvC,CAAC;AAWF,wEAAwE;AACxE,eAAO,MAAM,sBAAsB,GAAI,aAAa,MAAM,yFAezD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GAAI,UAAU,MAAM,GAAG,SAAS,+FAqBlE,CAAC;AAEF,gGAAgG;AAChG,eAAO,MAAM,qBAAqB,qGAgBjC,CAAC;AAEF,qFAAqF;AACrF,eAAO,MAAM,yBAAyB;cAGG,MAAM;kBAAgB,MAAM;WAWpE,CAAC;AAOF,eAAO,MAAM,mBAAmB,GAAI,gBAAgB,MAAM,GAAG,SAAS,sFAkBrE,CAAC;AAEF,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB;oBAIgB,MAAM;kBAAgB,MAAM;WAc1E,CAAC;AAIF,eAAO,MAAM,eAAe,GAAI,gBAAgB,MAAM,GAAG,SAAS,yFAgBjE,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,mBAAmB,uGAgB/B,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,YAAY,EAAE,eAAe,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AACD,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,MAAM,8FAkB7D;AACD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,0FA8BxD;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;;;gBAQ5C,MAAM;kBAAQ,MAAM;qBAAW,MAAM;;;gBAArC,MAAM;kBAAQ,MAAM;qBAAW,MAAM;;;gBAoBhC,MAAM;kBAAQ,MAAM;;;;EAqExD;AAgBD,iEAAiE;AACjE,eAAO,MAAM,iBAAiB,uFAa7B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,GAAI,WAAW,qBAAqB,EAAE,cAAU;WAOhE,gBAAgB,EAAE;cACf;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;UAmB9D,CAAC;AAEF,eAAO,MAAM,yBAAyB,qHAgBrC,CAAC;AAEF,eAAO,MAAM,sBAAsB,kHAmBlC,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,0BAA0B;QAIJ,MAAM;WAAS,MAAM,GAAG,IAAI;WAY9D,CAAC;AAUF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,iBAAc,kFAc9C,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,sBAAsB,kHAgBlC,CAAC"}
@@ -747,7 +747,7 @@ var o = () => {
747
747
  }`, { input: t }, e)).buiApplyAssessmentDraft,
748
748
  onSuccess: (e) => t.invalidateQueries({ queryKey: c.assessments(e.courseId) })
749
749
  });
750
- }, G = "\n id kind status title rationale summary question\n courseId courseTitle cohortId cohortName sourceLabel\n affectedCount truncated reminderMessage inactiveDays statusFilter\n result { enrolledCount skippedCount notifiedCount failedCount rowCount }\n errorMessage expiresAt createdAt createdBy confirmedBy confirmedAt executedAt dismissedAt\n", Ue = () => {
750
+ }, G = "\n id kind status title rationale summary question\n courseId courseTitle cohortId cohortName sourceLabel\n affectedCount truncated reminderMessage inactiveDays statusFilter\n automationTemplate automationName automationEnabled automationWasEnabled automationConfig evidence\n result { enrolledCount skippedCount notifiedCount failedCount rowCount automationEnabled }\n errorMessage expiresAt createdAt createdBy confirmedBy confirmedAt executedAt dismissedAt\n", Ue = () => {
751
751
  let e = E(), t = i();
752
752
  return n({
753
753
  mutationFn: async (t) => (await s(`mutation BuiAdminCopilotAsk($question: String!, $history: [BuiAdminCopilotTurnInput!]) {
@@ -778,7 +778,8 @@ var o = () => {
778
778
  }, Ge = {
779
779
  ENROLL_LEARNERS: "buiAdminCopilotExecuteEnrollAction",
780
780
  SEND_REMINDER: "buiAdminCopilotExecuteReminderAction",
781
- EXPORT_REPORT: "buiAdminCopilotExecuteReportAction"
781
+ EXPORT_REPORT: "buiAdminCopilotExecuteReportAction",
782
+ CONFIGURE_AUTOMATION: "buiAdminCopilotExecuteAutomationAction"
782
783
  }, Ke = () => {
783
784
  let e = E(), t = i();
784
785
  return n({
@@ -793,7 +794,7 @@ var o = () => {
793
794
  return r;
794
795
  },
795
796
  onSuccess: (e) => {
796
- t.invalidateQueries({ queryKey: c.adminCopilotActions }), e.action.kind === "ENROLL_LEARNERS" && t.invalidateQueries({ queryKey: c.enrollments });
797
+ t.invalidateQueries({ queryKey: c.adminCopilotActions }), e.action.kind === "ENROLL_LEARNERS" && t.invalidateQueries({ queryKey: c.enrollments }), e.action.kind === "CONFIGURE_AUTOMATION" && t.invalidateQueries({ queryKey: c.automations });
797
798
  }
798
799
  });
799
800
  }, qe = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"useBuildmyiqApi.js","names":[],"sources":["../../../src/buildmyiq/hooks/useBuildmyiqApi.ts"],"sourcesContent":["/**\n * Buildmyiq API hooks\n * @module buildmyiq/hooks\n *\n * React-Query hooks wired DIRECTLY to the real `wspace-buildmyiq-svc`\n * federated GraphQL contract (the `bui*` operations). Every query/mutation\n * below uses an inline gql string whose fields match the svc\n * `.hive-schema.graphql` exactly. No mock data, no codegen.\n *\n * Transport: `graphqlFetch({ gateway: 'workspace', workspaceToken: true })` —\n * the host shell supplies the gateway base URL + a workspace-scoped token.\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\n\nimport { useBuildmyiq } from '../context';\nimport { provisionCourseTeacher, type CourseTeacherSetupSelection } from './courseTeacherSetup';\nimport type {\n BuiConnection,\n BuiCourse,\n BuiCourseLevel,\n BuiCourseStatus,\n BuiModule,\n BuiLesson,\n BuiAssessment,\n BuiAssessmentStatus,\n BuiQuestion,\n BuiSubmission,\n BuiSubmissionStatus,\n BuiEnrollment,\n BuiEnrollmentStatus,\n BuiCohort,\n BuiCohortStatus,\n BuiSkill,\n BuiSkillCategory,\n BuiSkillStandard,\n BuiCertification,\n BuiSkillMappingSuggestion,\n BuiCertificate,\n BuiLessonProgress,\n BuiCreateCourseInput,\n BuiUpdateCourseInput,\n BuiCreateModuleInput,\n BuiCreateLessonInput,\n BuiCreateAssessmentInput,\n BuiCreateQuestionInput,\n BuiCreateSkillInput,\n BuiCreateCohortInput,\n BuiEnrollInput,\n BuiRecordLessonProgressInput,\n BuiSubmitAssessmentInput,\n BuiGradeSubmissionInput,\n BuiIssueCertificateInput,\n BuiTutorAskInput,\n BuiTutorAskPayload,\n BuiTutorSession,\n BuiTutorMessage,\n BuiReviewTutorAnswerInput,\n BuiGradeSuggestion,\n BuiNextLessonSuggestion,\n BuiCourseOutlineSuggestion,\n BuiApplyCourseOutlineInput,\n BuiApplyAssessmentDraftInput,\n BuiAssessmentDraftSuggestion,\n BuiSuggestAssessmentDraftInput,\n BuiAdminCopilotActionKind,\n BuiAdminCopilotActionStatus,\n BuiAdminCopilotAnswer,\n BuiAdminCopilotExecution,\n BuiAdminCopilotProposedAction,\n BuiAdminCopilotTurnInput,\n BuiAiSuggestionOutcome,\n BuiLtiPlatform,\n BuiLtiResourceLink,\n BuiLtiLaunchContext,\n BuiLtiDeepLinkResult,\n BuiLtiGradeSync,\n BuiLtiRosterMember,\n BuiRegisterLtiPlatformInput,\n BuiAiSettings,\n BuiAutomation,\n BuiAutomationRun,\n BuiAutomationTemplate,\n BuiConfigureAutomationInput,\n BuiUpdateAiSettingsInput,\n PaginationInput,\n} from '../types';\n\n// ============================================================================\n// Transport\n// ============================================================================\n\n/**\n * fe-libs `graphqlFetch` coalesces `query` responses in an in-memory cache keyed\n * by operationName+variables for ~15s (mutations are never cached). A read\n * issued right after a write (e.g. the React-Query refetch triggered by our\n * `invalidateQueries`) would otherwise return the PRE-mutation response until the\n * TTL expires — making just-created/updated rows invisible until a full reload.\n * We clear those caches after every buildmyiq mutation so every follow-up read\n * is fresh.\n */\ntype GraphqlReadCacheGlobals = {\n __graphqlFetchResponseCache?: { clear: () => void };\n __graphqlFetchPendingResponses?: { clear: () => void };\n __boffGraphQLResponseCache?: { clear: () => void };\n};\n\nconst clearGraphqlReadCaches = (): void => {\n const g = globalThis as GraphqlReadCacheGlobals;\n g.__graphqlFetchResponseCache?.clear();\n g.__graphqlFetchPendingResponses?.clear();\n g.__boffGraphQLResponseCache?.clear();\n};\n\nconst buiQuery = async <TData>(\n query: string,\n variables: Record<string, unknown>,\n baseUrl?: string\n): Promise<TData> => {\n const response = await graphqlFetch<TData>({\n gateway: 'workspace',\n baseUrl,\n query,\n variables,\n workspaceToken: true,\n });\n\n if (response.errors?.length) {\n throw new Error(response.errors[0]?.message ?? 'GraphQL request failed');\n }\n if (!response.data) {\n throw new Error('GraphQL response did not include data');\n }\n if (/^\\s*mutation\\b/.test(query)) {\n clearGraphqlReadCaches();\n }\n return response.data;\n};\n\n// React-Query key roots (one namespace per domain entity).\nconst KEY = {\n courses: ['buildmyiq', 'courses'] as const,\n course: (id: string) => ['buildmyiq', 'course', id] as const,\n modules: (courseId: string) => ['buildmyiq', 'modules', courseId] as const,\n lessons: (courseId: string) => ['buildmyiq', 'lessons', courseId] as const,\n assessments: (courseId: string) => ['buildmyiq', 'assessments', courseId] as const,\n assessment: (id: string) => ['buildmyiq', 'assessment', id] as const,\n enrollments: ['buildmyiq', 'enrollments'] as const,\n enrollment: (id: string) => ['buildmyiq', 'enrollment', id] as const,\n certificates: ['buildmyiq', 'certificates'] as const,\n cohorts: ['buildmyiq', 'cohorts'] as const,\n skills: ['buildmyiq', 'skills'] as const,\n submissions: ['buildmyiq', 'submissions'] as const,\n submission: (id: string) => ['buildmyiq', 'submission', id] as const,\n tutorSessions: (lessonId: string) => ['buildmyiq', 'tutorSessions', lessonId] as const,\n tutorReview: ['buildmyiq', 'tutorReview'] as const,\n tutorMode: (enrollmentId: string) => ['buildmyiq', 'tutorMode', enrollmentId] as const,\n ltiPlatforms: ['buildmyiq', 'ltiPlatforms'] as const,\n ltiResourceLinks: ['buildmyiq', 'ltiResourceLinks'] as const,\n ltiGradeSyncs: (resourceLinkId: string) =>\n ['buildmyiq', 'ltiGradeSyncs', resourceLinkId] as const,\n ltiRoster: (resourceLinkId: string) => ['buildmyiq', 'ltiRoster', resourceLinkId] as const,\n adminCopilotActions: ['buildmyiq', 'adminCopilotActions'] as const,\n automations: ['buildmyiq', 'automations'] as const,\n automationRuns: ['buildmyiq', 'automationRuns'] as const,\n aiSettings: ['buildmyiq', 'aiSettings'] as const,\n};\n\nconst DEFAULT_PAGE_SIZE = 24;\n\n/**\n * Build a `PaginationInput` for a list query. The FIRST page (undefined cursor)\n * OMITS the cursor key entirely — the svc rejects an explicit `cursor: null`.\n */\nconst pageVars = (cursor?: string, limit = DEFAULT_PAGE_SIZE): PaginationInput =>\n cursor ? { limit, cursor } : { limit };\n\n// ============================================================================\n// Reusable gql field selections (codegen-free strictness)\n// ============================================================================\n\nconst FILE_FIELDS = `id name downloadUrl mimeType`;\n\nconst SKILL_FIELDS = `\n id workspaceId name category description isActive\n onetCode escoUri socCodes certificationIds taxonomyMetadata\n createdAt updatedAt\n`;\n\nconst SKILL_STANDARD_FIELDS = `\n id workspaceId source code title description category uri socCodes metadata isActive createdAt updatedAt\n`;\n\nconst CERTIFICATION_FIELDS = `\n id workspaceId body code name description url isActive createdAt updatedAt\n`;\n\nconst COURSE_CORE_FIELDS = `\n id workspaceId title slug summary description status level language\n estimatedHours isPublic tags skillId instructorId publishedAt createdAt updatedAt\n cover { ${FILE_FIELDS} }\n skill { id name category }\n`;\n\nconst MODULE_FIELDS = `\n id workspaceId courseId title description position createdAt updatedAt\n`;\n\nconst LESSON_FIELDS = `\n id workspaceId courseId moduleId title type content durationMin position isPreview\n createdAt updatedAt\n media { ${FILE_FIELDS} }\n`;\n\n// NOTE: `modules`/`lessons` are `Bui*Connection!` on the svc schema (paginated),\n// NOT plain lists — every nested selection below must go through `items { }` or\n// the gateway rejects the whole query with GRAPHQL_VALIDATION_FAILED (BOFF-4703\n// Connection-shape drift). See `flattenCourse` for the matching unwrap.\nconst COURSE_FULL_FIELDS = `\n ${COURSE_CORE_FIELDS}\n modules { items { ${MODULE_FIELDS} lessons { items { ${LESSON_FIELDS} } } } }\n lessons { items { ${LESSON_FIELDS} } }\n`;\n\nconst ASSESSMENT_FIELDS = `\n id workspaceId courseId title description type status passingScore maxAttempts\n timeLimitMin isGraded requiresProctoring createdAt updatedAt\n`;\n\n// NOTE: BuiQuestion has NO `answerKey` on the type (create-input only).\nconst QUESTION_FIELDS = `\n id workspaceId assessmentId prompt type options points position explanation\n createdAt updatedAt\n`;\n\n// `questions` is `BuiQuestionConnection!` — see COURSE_FULL_FIELDS note above.\nconst ASSESSMENT_FULL_FIELDS = `\n ${ASSESSMENT_FIELDS}\n questions { items { ${QUESTION_FIELDS} } }\n`;\n\nconst SUBMISSION_FIELDS = `\n id workspaceId assessmentId enrollmentId learnerId attempt answers status score\n passed feedback gradedById gradedAt submittedAt createdAt updatedAt\n`;\n\nconst COHORT_FIELDS = `\n id workspaceId courseId name capacity facilitatorId startDate endDate status\n createdAt updatedAt\n`;\n\nconst LESSON_PROGRESS_FIELDS = `\n id workspaceId enrollmentId lessonId status secondsSpent completedAt createdAt updatedAt\n`;\n\nconst ENROLLMENT_FIELDS = `\n id workspaceId courseId learnerId cohortId status progressPct enrolledAt startedAt\n completedAt lastActiveAt expiresAt dueAt createdAt updatedAt\n`;\n\n// `lessonProgress` is `BuiLessonProgressConnection!` — see COURSE_FULL_FIELDS note above.\nconst ENROLLMENT_FULL_FIELDS = `\n ${ENROLLMENT_FIELDS}\n cohort { ${COHORT_FIELDS} }\n lessonProgress { items { ${LESSON_PROGRESS_FIELDS} } }\n`;\n\n// `file` selects ONLY `id` (the page renders it through FileLink/getFile):\n// a federated File stub cannot resolve any other field, and selecting one\n// fails every certificate read once a certificate carries a PDF.\nconst CERTIFICATE_FIELDS = `\n id workspaceId courseId learnerId enrollmentId serial status issuedAt expiresAt\n revokedAt finalScore verificationCode recipientNameSnapshot createdAt updatedAt\n file { id }\n`;\n\n// `content` is what the learner should see: the instructor's corrected text\n// or a removal notice once an answer is reviewed (BOFF-9663); `review` drives\n// the \"reviewed by your instructor\" marker.\nconst TUTOR_MESSAGE_FIELDS = `\n id workspaceId sessionId role content groundingLessonIds adaptiveLevel createdAt\n review { status note reviewedAt }\n`;\n\n// Educator review surface (BOFF-9663): the original answer, the reviewer and the\n// full audit trail resolve only through `buiListTutorSessions` and\n// `buiReviewTutorAnswer`.\nconst TUTOR_REVIEW_MESSAGE_FIELDS = `\n id workspaceId sessionId role content groundingLessonIds adaptiveLevel createdAt\n originalContent\n review { status note reviewedAt reviewedBy }\n reviewHistory { id action previousStatus content note reviewerId createdAt }\n`;\n\nconst TUTOR_SESSION_FIELDS = `\n id workspaceId courseId lessonId learnerId createdAt updatedAt\n messages { ${TUTOR_MESSAGE_FIELDS} }\n`;\n\n// ============================================================================\n// Connection-shape unwrap (BOFF-4703)\n// ============================================================================\n// Every `Bui*Connection` field on the wire is `{ items: T[]; pageInfo }`, never\n// a bare list — including NESTED fields like `BuiCourse.modules` or\n// `BuiAssessment.questions`. The hooks below keep returning plain flat arrays\n// to consumers (that's the shape every page in this MFE is written against),\n// so raw wire responses are unwrapped once here rather than pushing the\n// Connection shape out to every page.\n\n/** Wire shape of a `BuiModule` fetched via `COURSE_FULL_FIELDS` (nested `lessons` is a Connection). */\ntype BuiModuleWire = Omit<BuiModule, 'lessons'> & { lessons: { items: BuiLesson[] } };\n\n/** Wire shape of a `BuiCourse` fetched via `COURSE_FULL_FIELDS`. */\ntype BuiCourseWire = Omit<BuiCourse, 'modules' | 'lessons'> & {\n modules: { items: BuiModuleWire[] };\n lessons: { items: BuiLesson[] };\n};\n\nconst flattenCourse = (c: BuiCourseWire): BuiCourse => ({\n ...c,\n modules: c.modules.items.map((m) => ({ ...m, lessons: m.lessons.items })),\n lessons: c.lessons.items,\n});\n\n/** Wire shape of a `BuiAssessment` fetched via `ASSESSMENT_FULL_FIELDS`. */\ntype BuiAssessmentWire = Omit<BuiAssessment, 'questions'> & { questions: { items: BuiQuestion[] } };\n\nconst flattenAssessment = (a: BuiAssessmentWire): BuiAssessment => ({\n ...a,\n questions: a.questions.items,\n});\n\n/** Wire shape of a `BuiEnrollment` fetched via `ENROLLMENT_FULL_FIELDS`. */\ntype BuiEnrollmentWire = Omit<BuiEnrollment, 'lessonProgress'> & {\n lessonProgress: { items: BuiLessonProgress[] };\n};\n\nconst flattenEnrollment = (e: BuiEnrollmentWire): BuiEnrollment => ({\n ...e,\n lessonProgress: e.lessonProgress.items,\n});\n\n// ============================================================================\n// Shared hook helper: resolve gateway URL from context\n// ============================================================================\n\nconst useGateway = (): string | undefined => {\n const { apiGatewayUrl } = useBuildmyiq();\n return apiGatewayUrl;\n};\n\n// ============================================================================\n// Courses\n// ============================================================================\n\nexport interface UseBuiCoursesArgs {\n level?: BuiCourseLevel;\n status?: BuiCourseStatus;\n cursor?: string;\n limit?: number;\n enabled?: boolean;\n}\n\nexport const useBuiCourses = (args: UseBuiCoursesArgs = {}) => {\n const baseUrl = useGateway();\n const { level, status, cursor, limit, enabled = true } = args;\n return useQuery({\n queryKey: [...KEY.courses, { level, status, cursor, limit }],\n enabled,\n queryFn: async () => {\n // Only `id` is needed here (list view shows module/lesson COUNTS, not\n // full records — see CourseCard.tsx) so we intentionally under-select\n // vs. the full `BuiModule`/`BuiLesson` shape; still must go through\n // `items { }` since both fields are Connections (BOFF-4703).\n const data = await buiQuery<{\n buiListCourses: {\n items: Array<\n Omit<BuiCourse, 'modules' | 'lessons'> & {\n modules: { items: Array<{ id: string }> };\n lessons: { items: Array<{ id: string }> };\n }\n >;\n pageInfo: BuiConnection<BuiCourse>['pageInfo'];\n };\n }>(\n `query BuiListCourses($level: BuiCourseLevel, $status: BuiCourseStatus, $pagination: PaginationInput) {\n buiListCourses(level: $level, status: $status, pagination: $pagination) {\n items { ${COURSE_CORE_FIELDS} modules { items { id } } lessons { items { id } } }\n pageInfo { cursor hasMore }\n }\n }`,\n { level, status, pagination: pageVars(cursor, limit) },\n baseUrl\n );\n return {\n items: data.buiListCourses.items.map((c) => ({\n ...c,\n // Partial `{ id }`-only records are cast to the full type — safe here\n // because every consumer of the list view only reads `.length`.\n modules: c.modules.items as unknown as BuiModule[],\n lessons: c.lessons.items as unknown as BuiLesson[],\n })),\n pageInfo: data.buiListCourses.pageInfo,\n };\n },\n });\n};\n\nexport const useBuiCourse = (id: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: id ? KEY.course(id) : ['buildmyiq', 'course', 'nil'],\n enabled: Boolean(id),\n queryFn: async () => {\n const data = await buiQuery<{ buiCourse: BuiCourseWire | null }>(\n `query BuiCourse($id: ID!) {\n buiCourse(id: $id) { ${COURSE_FULL_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiCourse ? flattenCourse(data.buiCourse) : null;\n },\n });\n};\n\nexport const useBuiCreateCourse = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiCreateCourseInput) => {\n const data = await buiQuery<{ buiCreateCourse: BuiCourse }>(\n `mutation BuiCreateCourse($input: BuiCreateCourseInput!) {\n buiCreateCourse(input: $input) { ${COURSE_CORE_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiCreateCourse;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.courses }),\n });\n};\n\nexport const useBuiUpdateCourse = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (args: { id: string; input: BuiUpdateCourseInput }) => {\n const data = await buiQuery<{ buiUpdateCourse: BuiCourse }>(\n `mutation BuiUpdateCourse($id: ID!, $input: BuiUpdateCourseInput!) {\n buiUpdateCourse(id: $id, input: $input) { ${COURSE_CORE_FIELDS} }\n }`,\n args,\n baseUrl\n );\n return data.buiUpdateCourse;\n },\n onSuccess: (course) => {\n qc.invalidateQueries({ queryKey: KEY.courses });\n qc.invalidateQueries({ queryKey: KEY.course(course.id) });\n },\n });\n};\n\nexport const useBuiPublishCourse = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await buiQuery<{ buiPublishCourse: BuiCourse }>(\n `mutation BuiPublishCourse($id: ID!) {\n buiPublishCourse(id: $id) { ${COURSE_CORE_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiPublishCourse;\n },\n onSuccess: (course) => {\n qc.invalidateQueries({ queryKey: KEY.courses });\n qc.invalidateQueries({ queryKey: KEY.course(course.id) });\n },\n });\n};\n\nexport const useBuiArchiveCourse = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await buiQuery<{ buiArchiveCourse: boolean }>(\n `mutation BuiArchiveCourse($id: ID!) { buiArchiveCourse(id: $id) }`,\n { id },\n baseUrl\n );\n return data.buiArchiveCourse;\n },\n onSuccess: (_r, id) => {\n qc.invalidateQueries({ queryKey: KEY.courses });\n qc.invalidateQueries({ queryKey: KEY.course(id) });\n },\n });\n};\n\n// ============================================================================\n// Modules & lessons\n// ============================================================================\n\nexport const useBuiModules = (courseId: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: courseId ? KEY.modules(courseId) : ['buildmyiq', 'modules', 'nil'],\n enabled: Boolean(courseId),\n queryFn: async () => {\n const data = await buiQuery<{ buiListModules: { items: BuiModuleWire[] } }>(\n `query BuiListModules($courseId: ID!) {\n buiListModules(courseId: $courseId) {\n items { ${MODULE_FIELDS} lessons { items { ${LESSON_FIELDS} } } }\n }\n }`,\n { courseId },\n baseUrl\n );\n return data.buiListModules.items.map((m) => ({ ...m, lessons: m.lessons.items }));\n },\n });\n};\n\nexport const useBuiLessons = (courseId: string | undefined, moduleId?: string) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: courseId ? [...KEY.lessons(courseId), { moduleId }] : ['buildmyiq', 'lessons', 'nil'],\n enabled: Boolean(courseId),\n queryFn: async () => {\n const data = await buiQuery<{ buiListLessons: { items: BuiLesson[] } }>(\n `query BuiListLessons($courseId: ID!, $moduleId: ID) {\n buiListLessons(courseId: $courseId, moduleId: $moduleId) { items { ${LESSON_FIELDS} } }\n }`,\n { courseId, moduleId },\n baseUrl\n );\n return data.buiListLessons.items;\n },\n });\n};\n\nexport const useBuiCreateModule = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiCreateModuleInput) => {\n const data = await buiQuery<{ buiCreateModule: BuiModule }>(\n `mutation BuiCreateModule($input: BuiCreateModuleInput!) {\n buiCreateModule(input: $input) { ${MODULE_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiCreateModule;\n },\n onSuccess: (m) => {\n qc.invalidateQueries({ queryKey: KEY.modules(m.courseId) });\n qc.invalidateQueries({ queryKey: KEY.course(m.courseId) });\n },\n });\n};\n\nexport const useBuiCreateLesson = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiCreateLessonInput) => {\n const data = await buiQuery<{ buiCreateLesson: BuiLesson }>(\n `mutation BuiCreateLesson($input: BuiCreateLessonInput!) {\n buiCreateLesson(input: $input) { ${LESSON_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiCreateLesson;\n },\n onSuccess: (l) => {\n qc.invalidateQueries({ queryKey: KEY.lessons(l.courseId) });\n qc.invalidateQueries({ queryKey: KEY.modules(l.courseId) });\n qc.invalidateQueries({ queryKey: KEY.course(l.courseId) });\n },\n });\n};\n\n// ============================================================================\n// Assessments & questions\n// ============================================================================\n\nexport const useBuiAssessments = (courseId: string | undefined, status?: BuiAssessmentStatus) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: courseId\n ? [...KEY.assessments(courseId), { status }]\n : ['buildmyiq', 'assessments', 'nil'],\n enabled: Boolean(courseId),\n queryFn: async () => {\n // Only `id` is needed here (list view shows a question COUNT, not full\n // records — see AssessmentsPage.tsx); still must go through `items { }`\n // since `questions` is a Connection (BOFF-4703).\n const data = await buiQuery<{\n buiListAssessments: {\n items: Array<\n Omit<BuiAssessment, 'questions'> & { questions: { items: Array<{ id: string }> } }\n >;\n };\n }>(\n `query BuiListAssessments($courseId: ID!, $status: BuiAssessmentStatus) {\n buiListAssessments(courseId: $courseId, status: $status) {\n items { ${ASSESSMENT_FIELDS} questions { items { id } } }\n }\n }`,\n { courseId, status },\n baseUrl\n );\n return data.buiListAssessments.items.map((a) => ({\n ...a,\n // Partial `{ id }`-only records are cast to the full type — safe here\n // because every consumer of the list view only reads `.length`.\n questions: a.questions.items as unknown as BuiQuestion[],\n }));\n },\n });\n};\n\nexport const useBuiAssessment = (id: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: id ? KEY.assessment(id) : ['buildmyiq', 'assessment', 'nil'],\n enabled: Boolean(id),\n queryFn: async () => {\n const data = await buiQuery<{ buiAssessment: BuiAssessmentWire | null }>(\n `query BuiAssessment($id: ID!) {\n buiAssessment(id: $id) { ${ASSESSMENT_FULL_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiAssessment ? flattenAssessment(data.buiAssessment) : null;\n },\n });\n};\n\nexport const useBuiCreateAssessment = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiCreateAssessmentInput) => {\n const data = await buiQuery<{ buiCreateAssessment: BuiAssessment }>(\n `mutation BuiCreateAssessment($input: BuiCreateAssessmentInput!) {\n buiCreateAssessment(input: $input) { ${ASSESSMENT_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiCreateAssessment;\n },\n onSuccess: (a) => qc.invalidateQueries({ queryKey: KEY.assessments(a.courseId) }),\n });\n};\n\nexport const useBuiPublishAssessment = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await buiQuery<{ buiPublishAssessment: BuiAssessment }>(\n `mutation BuiPublishAssessment($id: ID!) {\n buiPublishAssessment(id: $id) { ${ASSESSMENT_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiPublishAssessment;\n },\n onSuccess: (a) => {\n qc.invalidateQueries({ queryKey: KEY.assessment(a.id) });\n qc.invalidateQueries({ queryKey: KEY.assessments(a.courseId) });\n },\n });\n};\n\n/**\n * Archive an assessment (soft-delete) — releases its reusable\n * `buildmyiq.assessments.count` quota slot server-side (BOFF-4722) so the\n * workspace can create a replacement without hitting the plan limit.\n * `buiArchiveAssessment` returns only a `Boolean!`, not the record, so the\n * caller supplies `courseId` (already in hand from the loaded assessment)\n * to invalidate the right list query.\n */\nexport const useBuiArchiveAssessment = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (args: { id: string; courseId: string }) => {\n const data = await buiQuery<{ buiArchiveAssessment: boolean }>(\n `mutation BuiArchiveAssessment($id: ID!) { buiArchiveAssessment(id: $id) }`,\n { id: args.id },\n baseUrl\n );\n return data.buiArchiveAssessment;\n },\n onSuccess: (_r, args) => {\n qc.invalidateQueries({ queryKey: KEY.assessment(args.id) });\n qc.invalidateQueries({ queryKey: KEY.assessments(args.courseId) });\n },\n });\n};\n\nexport const useBuiCreateQuestion = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiCreateQuestionInput) => {\n const data = await buiQuery<{ buiCreateQuestion: BuiQuestion }>(\n `mutation BuiCreateQuestion($input: BuiCreateQuestionInput!) {\n buiCreateQuestion(input: $input) { ${QUESTION_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiCreateQuestion;\n },\n onSuccess: (q) => qc.invalidateQueries({ queryKey: KEY.assessment(q.assessmentId) }),\n });\n};\n\n// ============================================================================\n// Submissions & grading\n// ============================================================================\n\nexport interface UseBuiSubmissionsArgs {\n assessmentId?: string;\n status?: BuiSubmissionStatus;\n cursor?: string;\n limit?: number;\n enabled?: boolean;\n}\n\nexport const useBuiSubmissions = (args: UseBuiSubmissionsArgs = {}) => {\n const baseUrl = useGateway();\n const { assessmentId, status, cursor, limit, enabled = true } = args;\n return useQuery({\n queryKey: [...KEY.submissions, { assessmentId, status, cursor, limit }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiListSubmissions: BuiConnection<BuiSubmission> }>(\n `query BuiListSubmissions($assessmentId: ID, $status: BuiSubmissionStatus, $pagination: PaginationInput) {\n buiListSubmissions(assessmentId: $assessmentId, status: $status, pagination: $pagination) {\n items { ${SUBMISSION_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { assessmentId, status, pagination: pageVars(cursor, limit) },\n baseUrl\n );\n return data.buiListSubmissions;\n },\n });\n};\n\n/**\n * The signed-in learner's own submissions (self-scoped). The backend dropped\n * the `learnerId` arg from `buiListSubmissions` in the FERPA/IDOR hardening;\n * a learner's own results come from `buiMySubmissions` instead.\n */\nexport const useBuiMySubmissions = (args: UseBuiSubmissionsArgs = {}) => {\n const baseUrl = useGateway();\n const { assessmentId, status, cursor, limit, enabled = true } = args;\n return useQuery({\n queryKey: [...KEY.submissions, 'mine', { assessmentId, status, cursor, limit }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiMySubmissions: BuiConnection<BuiSubmission> }>(\n `query BuiMySubmissions($assessmentId: ID, $status: BuiSubmissionStatus, $pagination: PaginationInput) {\n buiMySubmissions(assessmentId: $assessmentId, status: $status, pagination: $pagination) {\n items { ${SUBMISSION_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { assessmentId, status, pagination: pageVars(cursor, limit) },\n baseUrl\n );\n return data.buiMySubmissions;\n },\n });\n};\n\n/** Single-submission lookup — used for deep-linking to `/buildmyiq/submissions/:submissionId`. */\nexport const useBuiSubmission = (id: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: id ? KEY.submission(id) : ['buildmyiq', 'submission', 'nil'],\n enabled: Boolean(id),\n queryFn: async () => {\n const data = await buiQuery<{ buiSubmission: BuiSubmission | null }>(\n `query BuiSubmission($id: ID!) {\n buiSubmission(id: $id) { ${SUBMISSION_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiSubmission;\n },\n });\n};\n\nexport const useBuiSubmitAssessment = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiSubmitAssessmentInput) => {\n const data = await buiQuery<{ buiSubmitAssessment: BuiSubmission }>(\n `mutation BuiSubmitAssessment($input: BuiSubmitAssessmentInput!) {\n buiSubmitAssessment(input: $input) { ${SUBMISSION_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiSubmitAssessment;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.submissions }),\n });\n};\n\nexport const useBuiGradeSubmission = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (args: { id: string; input: BuiGradeSubmissionInput }) => {\n const data = await buiQuery<{ buiGradeSubmission: BuiSubmission }>(\n `mutation BuiGradeSubmission($id: ID!, $input: BuiGradeSubmissionInput!) {\n buiGradeSubmission(id: $id, input: $input) { ${SUBMISSION_FIELDS} }\n }`,\n args,\n baseUrl\n );\n return data.buiGradeSubmission;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.submissions }),\n });\n};\n\n/**\n * Deterministically grades a submission whose assessment is made up ENTIRELY of\n * objective questions (SINGLE_CHOICE / MULTIPLE_CHOICE / TRUE_FALSE) by\n * comparing the learner's answers against each question's answer key — no LLM\n * and no human judgement involved. Unlike `useBuiSuggestGrade` this DOES write\n * the submission. The svc throws when the assessment contains any\n * SHORT_ANSWER / ESSAY / CODE question; callers gate the action on the\n * assessment's question types and surface the error honestly if it still fails.\n */\nexport const useBuiAutoScoreSubmission = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await buiQuery<{ buiAutoScoreSubmission: BuiSubmission }>(\n `mutation BuiAutoScoreSubmission($id: ID!) {\n buiAutoScoreSubmission(id: $id) { ${SUBMISSION_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiAutoScoreSubmission;\n },\n onSuccess: (s) => {\n qc.invalidateQueries({ queryKey: KEY.submissions });\n qc.invalidateQueries({ queryKey: KEY.submission(s.id) });\n },\n });\n};\n\n// ============================================================================\n// Enrollments & progress\n// ============================================================================\n\nexport interface UseBuiEnrollmentsArgs {\n courseId?: string;\n status?: BuiEnrollmentStatus;\n cursor?: string;\n limit?: number;\n enabled?: boolean;\n}\n\n/**\n * Workspace-wide enrollment list (instructor/admin). The backend dropped the\n * `learnerId` arg in the FERPA/IDOR hardening — a learner's OWN enrollments\n * come from the self-scoped `useBuiMyEnrollments` instead.\n */\nexport const useBuiEnrollments = (args: UseBuiEnrollmentsArgs = {}) => {\n const baseUrl = useGateway();\n const { courseId, status, cursor, limit, enabled = true } = args;\n return useQuery({\n queryKey: [...KEY.enrollments, { courseId, status, cursor, limit }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiListEnrollments: BuiConnection<BuiEnrollment> }>(\n `query BuiListEnrollments($courseId: ID, $status: BuiEnrollmentStatus, $pagination: PaginationInput) {\n buiListEnrollments(courseId: $courseId, status: $status, pagination: $pagination) {\n items { ${ENROLLMENT_FIELDS} cohort { ${COHORT_FIELDS} } }\n pageInfo { cursor hasMore }\n }\n }`,\n { courseId, status, pagination: pageVars(cursor, limit) },\n baseUrl\n );\n return data.buiListEnrollments;\n },\n });\n};\n\n/** The signed-in learner's own enrollments (self-scoped, no learnerId arg). */\nexport const useBuiMyEnrollments = (args: UseBuiEnrollmentsArgs = {}) => {\n const baseUrl = useGateway();\n const { courseId, status, cursor, limit, enabled = true } = args;\n return useQuery({\n queryKey: [...KEY.enrollments, 'mine', { courseId, status, cursor, limit }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiMyEnrollments: BuiConnection<BuiEnrollment> }>(\n `query BuiMyEnrollments($courseId: ID, $status: BuiEnrollmentStatus, $pagination: PaginationInput) {\n buiMyEnrollments(courseId: $courseId, status: $status, pagination: $pagination) {\n items { ${ENROLLMENT_FIELDS} cohort { ${COHORT_FIELDS} } }\n pageInfo { cursor hasMore }\n }\n }`,\n { courseId, status, pagination: pageVars(cursor, limit) },\n baseUrl\n );\n return data.buiMyEnrollments;\n },\n });\n};\n\nexport const useBuiEnrollment = (id: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: id ? KEY.enrollment(id) : ['buildmyiq', 'enrollment', 'nil'],\n enabled: Boolean(id),\n queryFn: async () => {\n const data = await buiQuery<{ buiEnrollment: BuiEnrollmentWire | null }>(\n `query BuiEnrollment($id: ID!) {\n buiEnrollment(id: $id) { ${ENROLLMENT_FULL_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiEnrollment ? flattenEnrollment(data.buiEnrollment) : null;\n },\n });\n};\n\n/**\n * The signed-in learner's OWN enrollment by id, with its full lesson-progress\n * history. Self-scoped (`buiMyEnrollment`) — the resolver owner-filters by the\n * authenticated actor and returns null for someone else's enrollment, so this\n * is the read a learner-facing surface must use; `useBuiEnrollment` above is\n * the workspace-scoped instructor/admin equivalent.\n */\nexport const useBuiMyEnrollment = (id: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n // Nested under KEY.enrollment(id) so the progress-recording invalidation\n // (which invalidates that prefix) refreshes this query too.\n queryKey: id ? [...KEY.enrollment(id), 'mine'] : ['buildmyiq', 'enrollment', 'nil', 'mine'],\n enabled: Boolean(id),\n queryFn: async () => {\n const data = await buiQuery<{ buiMyEnrollment: BuiEnrollmentWire | null }>(\n `query BuiMyEnrollment($id: ID!) {\n buiMyEnrollment(id: $id) { ${ENROLLMENT_FULL_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiMyEnrollment ? flattenEnrollment(data.buiMyEnrollment) : null;\n },\n });\n};\n\nexport const useBuiEnroll = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiEnrollInput) => {\n const data = await buiQuery<{ buiEnroll: BuiEnrollment }>(\n `mutation BuiEnroll($input: BuiEnrollInput!) {\n buiEnroll(input: $input) { ${ENROLLMENT_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiEnroll;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.enrollments }),\n });\n};\n\nexport const useBuiCompleteMyEnrollment = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (args: { id: string }) => {\n const data = await buiQuery<{ buiCompleteMyEnrollment: BuiEnrollment }>(\n `mutation BuiCompleteMyEnrollment($id: ID!) {\n buiCompleteMyEnrollment(id: $id) { ${ENROLLMENT_FIELDS} }\n }`,\n args,\n baseUrl\n );\n return data.buiCompleteMyEnrollment;\n },\n onSuccess: (e) => {\n qc.invalidateQueries({ queryKey: KEY.enrollments });\n qc.invalidateQueries({ queryKey: KEY.enrollment(e.id) });\n },\n });\n};\n\nexport const useBuiRecordMyLessonProgress = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiRecordLessonProgressInput) => {\n const data = await buiQuery<{ buiRecordMyLessonProgress: BuiLessonProgress }>(\n `mutation BuiRecordMyLessonProgress($input: BuiRecordLessonProgressInput!) {\n buiRecordMyLessonProgress(input: $input) { ${LESSON_PROGRESS_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiRecordMyLessonProgress;\n },\n onSuccess: (p) => {\n qc.invalidateQueries({ queryKey: KEY.enrollment(p.enrollmentId) });\n qc.invalidateQueries({ queryKey: KEY.enrollments });\n },\n });\n};\n\n// ============================================================================\n// Cohorts\n// ============================================================================\n\nexport const useBuiCohorts = (courseId?: string, status?: BuiCohortStatus) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: [...KEY.cohorts, { courseId, status }],\n queryFn: async () => {\n const data = await buiQuery<{ buiListCohorts: { items: BuiCohort[] } }>(\n `query BuiListCohorts($courseId: ID, $status: BuiCohortStatus) {\n buiListCohorts(courseId: $courseId, status: $status) { items { ${COHORT_FIELDS} } }\n }`,\n { courseId, status },\n baseUrl\n );\n return data.buiListCohorts.items;\n },\n });\n};\n\nexport const useBuiCreateCohort = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiCreateCohortInput) => {\n const data = await buiQuery<{ buiCreateCohort: BuiCohort }>(\n `mutation BuiCreateCohort($input: BuiCreateCohortInput!) {\n buiCreateCohort(input: $input) { ${COHORT_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiCreateCohort;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.cohorts }),\n });\n};\n\n// ============================================================================\n// Skills\n// ============================================================================\n\nexport const useBuiSkills = (category?: BuiSkillCategory) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: [...KEY.skills, { category }],\n queryFn: async () => {\n const data = await buiQuery<{ buiListSkills: { items: BuiSkill[] } }>(\n `query BuiListSkills($category: BuiSkillCategory) {\n buiListSkills(category: $category) { items { ${SKILL_FIELDS} } }\n }`,\n { category },\n baseUrl\n );\n return data.buiListSkills.items;\n },\n });\n};\n\nexport const useBuiCreateSkill = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiCreateSkillInput) => {\n const data = await buiQuery<{ buiCreateSkill: BuiSkill }>(\n `mutation BuiCreateSkill($input: BuiCreateSkillInput!) {\n buiCreateSkill(input: $input) { ${SKILL_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiCreateSkill;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.skills }),\n });\n};\n\nexport const useBuiSkillStandards = (\n source?: BuiSkillStandard['source'],\n category?: BuiSkillCategory,\n enabled = true\n) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: ['buildmyiq', 'skillStandards', { source, category }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiListSkillStandards: { items: BuiSkillStandard[] } }>(\n `query BuiListSkillStandards($source: BuiSkillStandardSource, $category: BuiSkillCategory) {\n buiListSkillStandards(source: $source, category: $category) { items { ${SKILL_STANDARD_FIELDS} } }\n }`,\n { source, category },\n baseUrl\n );\n return data.buiListSkillStandards.items;\n },\n });\n};\n\nexport const useBuiCertifications = (body?: BuiCertification['body'], enabled = true) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: ['buildmyiq', 'certifications', { body }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiListCertifications: { items: BuiCertification[] } }>(\n `query BuiListCertifications($body: BuiCertificationBody) {\n buiListCertifications(body: $body) { items { ${CERTIFICATION_FIELDS} } }\n }`,\n { body },\n baseUrl\n );\n return data.buiListCertifications.items;\n },\n });\n};\n\nexport const useBuiSuggestSkillMappings = (name: string, description?: string, enabled = true) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: ['buildmyiq', 'skillMappingSuggestions', { name, description }],\n enabled: enabled && name.trim().length > 0,\n queryFn: async () => {\n const data = await buiQuery<{ buiSuggestSkillMappings: BuiSkillMappingSuggestion[] }>(\n `query BuiSuggestSkillMappings($name: String!, $description: String, $limit: Int) {\n buiSuggestSkillMappings(name: $name, description: $description, limit: $limit) {\n skillStandard { ${SKILL_STANDARD_FIELDS} }\n confidence\n reason\n }\n }`,\n { name, description, limit: 5 },\n baseUrl\n );\n return data.buiSuggestSkillMappings;\n },\n });\n};\n\n// ============================================================================\n// Certificates\n// ============================================================================\n\n/**\n * Workspace-wide certificate list (instructor/admin). The backend dropped the\n * `learnerId` arg in the FERPA/IDOR hardening — a learner's OWN certificates\n * come from the self-scoped `useBuiMyCertificates` instead.\n */\nexport const useBuiCertificates = (courseId?: string, enabled = true) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: [...KEY.certificates, { courseId }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiListCertificates: { items: BuiCertificate[] } }>(\n `query BuiListCertificates($courseId: ID) {\n buiListCertificates(courseId: $courseId) { items { ${CERTIFICATE_FIELDS} } }\n }`,\n { courseId },\n baseUrl\n );\n return data.buiListCertificates.items;\n },\n });\n};\n\n/** The signed-in learner's own certificates (self-scoped, no learnerId arg). */\nexport const useBuiMyCertificates = (courseId?: string, enabled = true) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: [...KEY.certificates, 'mine', { courseId }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiMyCertificates: { items: BuiCertificate[] } }>(\n `query BuiMyCertificates($courseId: ID) {\n buiMyCertificates(courseId: $courseId) { items { ${CERTIFICATE_FIELDS} } }\n }`,\n { courseId },\n baseUrl\n );\n return data.buiMyCertificates.items;\n },\n });\n};\n\nexport const useBuiIssueCertificate = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiIssueCertificateInput) => {\n const data = await buiQuery<{ buiIssueCertificate: BuiCertificate }>(\n `mutation BuiIssueCertificate($input: BuiIssueCertificateInput!) {\n buiIssueCertificate(input: $input) { ${CERTIFICATE_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiIssueCertificate;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.certificates }),\n });\n};\n\nexport const useBuiRevokeCertificate = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await buiQuery<{ buiRevokeCertificate: BuiCertificate }>(\n `mutation BuiRevokeCertificate($id: ID!) {\n buiRevokeCertificate(id: $id) { ${CERTIFICATE_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiRevokeCertificate;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.certificates }),\n });\n};\n\n// ============================================================================\n// AI Tutor (BOFF-4426) — grounded lesson Q&A chat\n// ============================================================================\n\n/**\n * Which tutor the lesson player shows for an enrollment.\n * - `teacher`: an educator bound a course teacher (course assistant) to the\n * course, so the Fluidgrids workflow assistant answers from its knowledge base.\n * - `native`: no course teacher is bound, so the built-in grounded tutor\n * (`buiTutorAsk`) answers from the lesson content. This keeps a working tutor\n * on every course without per-course setup.\n */\nexport type BuiTutorMode = 'teacher' | 'native';\n\n/**\n * Resolves the tutor mode through the learner-scoped `buiMyCourseAssistantTarget`\n * query: it returns the course only when an enabled binding exists and fails\n * with FAILED_PRECONDITION otherwise. Any failure resolves to `native`, because\n * the native tutor enforces its own access checks and needs no binding.\n */\nexport const useBuiTutorMode = (enrollmentId: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery<BuiTutorMode>({\n queryKey: enrollmentId ? KEY.tutorMode(enrollmentId) : ['buildmyiq', 'tutorMode', 'nil'],\n enabled: Boolean(enrollmentId),\n staleTime: 60_000,\n queryFn: async () => {\n try {\n const response = await graphqlFetch<{\n buiMyCourseAssistantTarget: { courseId: string } | null;\n }>({\n gateway: 'workspace',\n baseUrl,\n query: `query BuiMyCourseAssistantTarget($enrollmentId: ID!) {\n buiMyCourseAssistantTarget(enrollmentId: $enrollmentId) { courseId }\n }`,\n variables: { enrollmentId },\n workspaceToken: true,\n });\n return response.data?.buiMyCourseAssistantTarget?.courseId ? 'teacher' : 'native';\n } catch (err) {\n if (import.meta.env.DEV)\n console.warn('[useBuiTutorMode] falling back to the native tutor', err);\n return 'native';\n }\n },\n });\n};\n\n/**\n * The calling learner's own tutor sessions for a lesson (Type-C self-scoped\n * query — no `learnerId` arg on the wire; identity comes from the\n * authenticated actor server-side). Sessions come back newest-first with\n * their full message history, so the panel can restore an in-progress\n * conversation on mount.\n */\nexport const useBuiMyTutorSessions = (lessonId: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: lessonId ? KEY.tutorSessions(lessonId) : ['buildmyiq', 'tutorSessions', 'nil'],\n enabled: Boolean(lessonId),\n queryFn: async () => {\n const data = await buiQuery<{ buiMyTutorSessions: { items: BuiTutorSession[] } }>(\n `query BuiMyTutorSessions($lessonId: ID) {\n buiMyTutorSessions(lessonId: $lessonId) { items { ${TUTOR_SESSION_FIELDS} } }\n }`,\n { lessonId },\n baseUrl\n );\n return data.buiMyTutorSessions.items;\n },\n });\n};\n\n/**\n * Ask the AI tutor a question about a lesson. Omit `sessionId` to start a\n * new session for that lesson; pass the current session's id to continue\n * the same conversation (multi-turn). Invalidates the lesson's tutor-session\n * query so the panel picks up the new USER + ASSISTANT turns.\n */\nexport const useBuiTutorAsk = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiTutorAskInput) => {\n const data = await buiQuery<{ buiTutorAsk: BuiTutorAskPayload }>(\n `mutation BuiTutorAsk($input: BuiTutorAskInput!) {\n buiTutorAsk(input: $input) {\n session { ${TUTOR_SESSION_FIELDS} }\n answer { ${TUTOR_MESSAGE_FIELDS} }\n }\n }`,\n { input },\n baseUrl\n );\n return data.buiTutorAsk;\n },\n // Returned so `mutateAsync` resolves only after the transcript is refetched,\n // which lets the panel drop its optimistic echo without a visible gap.\n onSuccess: (payload) =>\n qc.invalidateQueries({ queryKey: KEY.tutorSessions(payload.session.lessonId) }),\n });\n};\n\n// ============================================================================\n// Educator review of AI tutor answers (BOFF-9663)\n// ============================================================================\n\nexport interface UseBuiTutorReviewSessionsArgs {\n courseId?: string;\n lessonId?: string;\n cursor?: string;\n limit?: number;\n}\n\n/**\n * Workspace-wide tutor conversations for educator review\n * (`buiListTutorSessions`, EDITOR+ via `buildmyiq-tutor:list`), newest first,\n * with each answer's original text, current review and audit trail.\n */\nexport const useBuiTutorReviewSessions = (args: UseBuiTutorReviewSessionsArgs = {}) => {\n const baseUrl = useGateway();\n const { courseId, lessonId, cursor, limit } = args;\n return useQuery({\n queryKey: [...KEY.tutorReview, { courseId, lessonId, cursor, limit }],\n queryFn: async () => {\n const data = await buiQuery<{ buiListTutorSessions: BuiConnection<BuiTutorSession> }>(\n `query BuiListTutorSessions($courseId: ID, $lessonId: ID, $pagination: PaginationInput) {\n buiListTutorSessions(courseId: $courseId, lessonId: $lessonId, pagination: $pagination) {\n items {\n id workspaceId courseId lessonId learnerId createdAt updatedAt\n messages { ${TUTOR_REVIEW_MESSAGE_FIELDS} }\n }\n pageInfo { cursor hasMore }\n }\n }`,\n { courseId, lessonId, pagination: pageVars(cursor, limit) },\n baseUrl\n );\n return data.buiListTutorSessions;\n },\n });\n};\n\n/**\n * Annotate, correct, redact or clear one tutor answer\n * (`buiReviewTutorAnswer`, EDITOR+ via `buildmyiq-tutor:update`). Refetches the\n * review list and any open learner transcript so both show the new state.\n */\nexport const useBuiReviewTutorAnswer = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiReviewTutorAnswerInput) => {\n const data = await buiQuery<{ buiReviewTutorAnswer: BuiTutorMessage }>(\n `mutation BuiReviewTutorAnswer($input: BuiReviewTutorAnswerInput!) {\n buiReviewTutorAnswer(input: $input) { ${TUTOR_REVIEW_MESSAGE_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiReviewTutorAnswer;\n },\n onSuccess: () =>\n Promise.all([\n qc.invalidateQueries({ queryKey: KEY.tutorReview }),\n qc.invalidateQueries({ queryKey: ['buildmyiq', 'tutorSessions'] }),\n ]),\n });\n};\n\n// ============================================================================\n// AI grading assist + admin copilot + AI course builder (BOFF-3724/4429/4434)\n// ============================================================================\n\nconst GRADE_SUGGESTION_FIELDS = `\n id submissionId proposedScore\n perQuestionFeedback {\n questionId feedback suggestedPoints\n criterionScores { criterionId title maxPoints suggestedPoints comment }\n }\n rubricRefs confidence inputRefs outcome createdAt\n`;\n\n/**\n * Proposes an AI-assisted score for a submission's open-ended questions —\n * NEVER writes the submission itself. The caller reviews/edits the result\n * and still commits via `useBuiGradeSubmission`. Throws (honest fail-clear)\n * when the backend has no LLM provider configured or the assessment has no\n * open-ended questions.\n */\nexport const useBuiSuggestGrade = () => {\n const baseUrl = useGateway();\n return useMutation({\n mutationFn: async (submissionId: string) => {\n const data = await buiQuery<{ buiSuggestGrade: BuiGradeSuggestion }>(\n `mutation BuiSuggestGrade($submissionId: ID!) {\n buiSuggestGrade(submissionId: $submissionId) { ${GRADE_SUGGESTION_FIELDS} }\n }`,\n { submissionId },\n baseUrl\n );\n return data.buiSuggestGrade;\n },\n });\n};\n\n/** Records whether the educator accepted or rejected a grading suggestion (measurable acceptance rate). */\nexport const useBuiReviewGradeSuggestion = () => {\n const baseUrl = useGateway();\n return useMutation({\n mutationFn: async (args: { id: string; outcome: BuiAiSuggestionOutcome }) => {\n const data = await buiQuery<{ buiReviewGradeSuggestion: BuiGradeSuggestion }>(\n `mutation BuiReviewGradeSuggestion($id: ID!, $outcome: BuiAiSuggestionOutcome!) {\n buiReviewGradeSuggestion(id: $id, outcome: $outcome) { ${GRADE_SUGGESTION_FIELDS} }\n }`,\n args,\n baseUrl\n );\n return data.buiReviewGradeSuggestion;\n },\n });\n};\n\nconst NEXT_LESSON_SUGGESTION_FIELDS = `\n id enrollmentId lessonId lessonTitle moduleId moduleTitle\n rationale confidence pacingHint inputRefs outcome createdAt\n`;\n\n/**\n * Proposes the lesson the learner should take next in one of their own\n * enrollments — a deterministic curriculum-order \"resume where you left off\"\n * walk plus a pacing hint derived from their recent graded scores (not an LLM\n * call). It persists an auditable suggestion record but NEVER writes\n * `BuiLessonProgress` / `BuiEnrollment`, so acting on it is entirely the\n * learner's choice. Type-B self-scoped: `enrollmentId` is a client arg but the\n * resolver owner-filters by the authenticated actor.\n */\nexport const useBuiSuggestNextLesson = () => {\n const baseUrl = useGateway();\n return useMutation({\n mutationFn: async (enrollmentId: string) => {\n const data = await buiQuery<{ buiSuggestNextLesson: BuiNextLessonSuggestion }>(\n `mutation BuiSuggestNextLesson($enrollmentId: ID!) {\n buiSuggestNextLesson(enrollmentId: $enrollmentId) { ${NEXT_LESSON_SUGGESTION_FIELDS} }\n }`,\n { enrollmentId },\n baseUrl\n );\n return data.buiSuggestNextLesson;\n },\n });\n};\n\n/** Records whether the learner accepted or dismissed a next-lesson suggestion. */\nexport const useBuiReviewNextLessonSuggestion = () => {\n const baseUrl = useGateway();\n return useMutation({\n mutationFn: async (args: { id: string; outcome: BuiAiSuggestionOutcome }) => {\n const data = await buiQuery<{ buiReviewNextLessonSuggestion: BuiNextLessonSuggestion }>(\n `mutation BuiReviewNextLessonSuggestion($id: ID!, $outcome: BuiAiSuggestionOutcome!) {\n buiReviewNextLessonSuggestion(id: $id, outcome: $outcome) { ${NEXT_LESSON_SUGGESTION_FIELDS} }\n }`,\n args,\n baseUrl\n );\n return data.buiReviewNextLessonSuggestion;\n },\n });\n};\n\n/**\n * AI-drafted course outline from a topic — an EPHEMERAL suggestion (not\n * persisted server-side); the instructor reviews/edits it before\n * `useBuiApplyCourseOutline` creates anything real.\n */\nexport const useBuiSuggestCourseOutline = () => {\n const baseUrl = useGateway();\n return useMutation({\n mutationFn: async (args: {\n topic: string;\n audienceLevel?: string | null;\n moduleCount?: number | null;\n blockedTerms?: string[] | null;\n }) => {\n const data = await buiQuery<{ buiSuggestCourseOutline: BuiCourseOutlineSuggestion }>(\n `mutation BuiSuggestCourseOutline($topic: String!, $audienceLevel: String, $moduleCount: Int, $blockedTerms: [String!]) {\n buiSuggestCourseOutline(topic: $topic, audienceLevel: $audienceLevel, moduleCount: $moduleCount, blockedTerms: $blockedTerms) {\n rationale confidence\n modules { title description lessons { title description } }\n filteredOutCount blockedTermsMatched\n }\n }`,\n args,\n baseUrl\n );\n return data.buiSuggestCourseOutline;\n },\n });\n};\n\n/** Creates a real DRAFT course + modules + lessons from a (possibly-edited) AI outline. */\nexport const useBuiApplyCourseOutline = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiApplyCourseOutlineInput) => {\n const data = await buiQuery<{ buiApplyCourseOutline: BuiCourse }>(\n `mutation BuiApplyCourseOutline($input: BuiApplyCourseOutlineInput!) {\n buiApplyCourseOutline(input: $input) { ${COURSE_CORE_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiApplyCourseOutline;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.courses }),\n });\n};\n\n/**\n * AI assessment draft (BOFF-4434): questions grounded in the course (or one\n * lesson's) content. Ephemeral — nothing is written until\n * `useBuiApplyAssessmentDraft` runs on the educator-reviewed draft.\n */\nexport const useBuiSuggestAssessmentDraft = () => {\n const baseUrl = useGateway();\n return useMutation({\n mutationFn: async (input: BuiSuggestAssessmentDraftInput) => {\n const data = await buiQuery<{ buiSuggestAssessmentDraft: BuiAssessmentDraftSuggestion }>(\n `mutation BuiSuggestAssessmentDraft($input: BuiSuggestAssessmentDraftInput!) {\n buiSuggestAssessmentDraft(input: $input) {\n courseId lessonId rationale confidence\n questions { prompt type points options answerKey explanation confidence }\n filteredOutCount lowConfidenceFilteredCount discardedInvalidCount\n blockedTermsMatched groundingRefs\n }\n }`,\n { input },\n baseUrl\n );\n return data.buiSuggestAssessmentDraft;\n },\n });\n};\n\n/** Creates a DRAFT assessment + questions from a reviewed AI draft (BOFF-4434). */\nexport const useBuiApplyAssessmentDraft = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiApplyAssessmentDraftInput) => {\n const data = await buiQuery<{ buiApplyAssessmentDraft: BuiAssessment }>(\n `mutation BuiApplyAssessmentDraft($input: BuiApplyAssessmentDraftInput!) {\n buiApplyAssessmentDraft(input: $input) { ${ASSESSMENT_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiApplyAssessmentDraft;\n },\n onSuccess: (a) => qc.invalidateQueries({ queryKey: KEY.assessments(a.courseId) }),\n });\n};\n\n/**\n * Read-only admin Q&A grounded in real workspace stats — NEVER executes an\n * admin action. Stateless per call; the caller resends prior turns as\n * `history` for multi-turn context.\n */\nconst ADMIN_COPILOT_ACTION_FIELDS = `\n id kind status title rationale summary question\n courseId courseTitle cohortId cohortName sourceLabel\n affectedCount truncated reminderMessage inactiveDays statusFilter\n result { enrolledCount skippedCount notifiedCount failedCount rowCount }\n errorMessage expiresAt createdAt createdBy confirmedBy confirmedAt executedAt dismissedAt\n`;\n\nexport const useBuiAdminCopilotAsk = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (args: { question: string; history: BuiAdminCopilotTurnInput[] }) => {\n const data = await buiQuery<{ buiAdminCopilotAsk: BuiAdminCopilotAnswer }>(\n `mutation BuiAdminCopilotAsk($question: String!, $history: [BuiAdminCopilotTurnInput!]) {\n buiAdminCopilotAsk(question: $question, history: $history) {\n answer contextCourseIds discardedActionCount generatedAt\n proposedActions { ${ADMIN_COPILOT_ACTION_FIELDS} }\n }\n }`,\n args,\n baseUrl\n );\n return data.buiAdminCopilotAsk;\n },\n onSuccess: (answer) => {\n if (answer.proposedActions.length > 0) {\n void qc.invalidateQueries({ queryKey: KEY.adminCopilotActions });\n }\n },\n });\n};\n\n/** The workspace's copilot proposals and their outcomes — the audit trail (BOFF-9687). */\nexport const useBuiAdminCopilotActions = (status?: BuiAdminCopilotActionStatus, limit = 20) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: [...KEY.adminCopilotActions, status ?? 'all', limit],\n queryFn: async () => {\n const data = await buiQuery<{ buiAdminCopilotActions: BuiAdminCopilotProposedAction[] }>(\n `query BuiAdminCopilotActions($status: BuiAdminCopilotActionStatus, $limit: Int) {\n buiAdminCopilotActions(status: $status, limit: $limit) { ${ADMIN_COPILOT_ACTION_FIELDS} }\n }`,\n status ? { status, limit } : { limit },\n baseUrl\n );\n return data.buiAdminCopilotActions;\n },\n });\n};\n\nconst EXECUTE_MUTATION_BY_KIND: Record<BuiAdminCopilotActionKind, string> = {\n ENROLL_LEARNERS: 'buiAdminCopilotExecuteEnrollAction',\n SEND_REMINDER: 'buiAdminCopilotExecuteReminderAction',\n EXPORT_REPORT: 'buiAdminCopilotExecuteReportAction',\n};\n\n/**\n * Confirm and run a proposed action. Each kind has its own mutation so the\n * gateway checks the permission that kind needs.\n */\nexport const useBuiAdminCopilotExecuteAction = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (args: { actionId: string; kind: BuiAdminCopilotActionKind }) => {\n const field = EXECUTE_MUTATION_BY_KIND[args.kind];\n const data = await buiQuery<Record<string, BuiAdminCopilotExecution>>(\n `mutation BuiAdminCopilotExecuteAction($actionId: ID!) {\n ${field}(actionId: $actionId) {\n reportCsv reportFileName\n action { ${ADMIN_COPILOT_ACTION_FIELDS} }\n }\n }`,\n { actionId: args.actionId },\n baseUrl\n );\n const execution = data[field];\n if (!execution) throw new Error('The action response was empty.');\n return execution;\n },\n onSuccess: (execution) => {\n void qc.invalidateQueries({ queryKey: KEY.adminCopilotActions });\n if (execution.action.kind === 'ENROLL_LEARNERS') {\n void qc.invalidateQueries({ queryKey: KEY.enrollments });\n }\n },\n });\n};\n\nexport const useBuiAdminCopilotDismissAction = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (actionId: string) => {\n const data = await buiQuery<{ buiAdminCopilotDismissAction: BuiAdminCopilotProposedAction }>(\n `mutation BuiAdminCopilotDismissAction($actionId: ID!) {\n buiAdminCopilotDismissAction(actionId: $actionId) { ${ADMIN_COPILOT_ACTION_FIELDS} }\n }`,\n { actionId },\n baseUrl\n );\n return data.buiAdminCopilotDismissAction;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.adminCopilotActions }),\n });\n};\n\n// ============================================================================\n// LTI 1.3 Advantage — platform registry (BOFF-4419)\n// ============================================================================\n\nconst LTI_PLATFORM_FIELDS = `\n id workspaceId name issuer clientId deploymentIds\n authLoginUrl authTokenUrl keySetUrl active createdAt updatedAt\n`;\n\nexport const useBuiLtiPlatforms = () => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: KEY.ltiPlatforms,\n queryFn: async () => {\n const data = await buiQuery<{ buiLtiPlatforms: BuiLtiPlatform[] }>(\n `query BuiLtiPlatforms { buiLtiPlatforms { ${LTI_PLATFORM_FIELDS} } }`,\n {},\n baseUrl\n );\n return data.buiLtiPlatforms;\n },\n });\n};\n\nexport const useBuiRegisterLtiPlatform = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiRegisterLtiPlatformInput) => {\n const data = await buiQuery<{ buiRegisterLtiPlatform: BuiLtiPlatform }>(\n `mutation BuiRegisterLtiPlatform($input: BuiRegisterLtiPlatformInput!) {\n buiRegisterLtiPlatform(input: $input) { ${LTI_PLATFORM_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiRegisterLtiPlatform;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.ltiPlatforms }),\n });\n};\n\nexport const useBuiDeactivateLtiPlatform = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await buiQuery<{ buiDeactivateLtiPlatform: boolean }>(\n `mutation BuiDeactivateLtiPlatform($id: ID!) { buiDeactivateLtiPlatform(id: $id) }`,\n { id },\n baseUrl\n );\n return data.buiDeactivateLtiPlatform;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.ltiPlatforms }),\n });\n};\n\n// ============================================================================\n// LTI 1.3 Advantage — launch handoff, placements, grade and roster sync (BOFF-9680)\n// ============================================================================\n\nconst LTI_RESOURCE_LINK_FIELDS = `\n id workspaceId platformId deploymentId resourceLinkId contextId contextTitle\n assessmentId lineItemUrl nrpsUrl createdAt updatedAt\n`;\n\n/** LMS placements recorded by launches, optionally for one platform. */\nexport const useBuiLtiResourceLinks = (platformId?: string) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: [...KEY.ltiResourceLinks, { platformId: platformId ?? null }],\n queryFn: async () => {\n const data = await buiQuery<{ buiLtiResourceLinks: BuiLtiResourceLink[] }>(\n `query BuiLtiResourceLinks($platformId: ID) {\n buiLtiResourceLinks(platformId: $platformId) { ${LTI_RESOURCE_LINK_FIELDS} }\n }`,\n { platformId: platformId ?? null },\n baseUrl\n );\n return data.buiLtiResourceLinks;\n },\n });\n};\n\n/**\n * The pending launch an LMS just redirected the browser here with. `null`\n * means the ticket is unknown, expired, or belongs to another workspace.\n * Never refetched in the background: a ticket is single-purpose and short-lived.\n */\nexport const useBuiLtiLaunchContext = (ticketId: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: ['buildmyiq', 'ltiLaunchContext', ticketId ?? 'nil'],\n enabled: Boolean(ticketId),\n retry: false,\n staleTime: Infinity,\n refetchOnWindowFocus: false,\n queryFn: async () => {\n const data = await buiQuery<{ buiLtiLaunchContext: BuiLtiLaunchContext | null }>(\n `query BuiLtiLaunchContext($ticketId: ID!) {\n buiLtiLaunchContext(ticketId: $ticketId) {\n ticketId messageType platformId contextTitle assessmentId deepLinkAcceptTypes\n }\n }`,\n { ticketId },\n baseUrl\n );\n return data.buiLtiLaunchContext;\n },\n });\n};\n\n/** Resource-link launch: links the signed-in user to the LMS user and records the placement. */\nexport const useBuiCompleteLtiLink = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (ticketId: string) => {\n const data = await buiQuery<{ buiCompleteLtiLink: { resourceLink: BuiLtiResourceLink } }>(\n `mutation BuiCompleteLtiLink($ticketId: ID!) {\n buiCompleteLtiLink(ticketId: $ticketId) { resourceLink { ${LTI_RESOURCE_LINK_FIELDS} } }\n }`,\n { ticketId },\n baseUrl\n );\n return data.buiCompleteLtiLink.resourceLink;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.ltiResourceLinks }),\n });\n};\n\n/** Deep Linking: signs the response that places `assessmentId` in the LMS course. */\nexport const useBuiCompleteLtiDeepLink = () => {\n const baseUrl = useGateway();\n return useMutation({\n mutationFn: async (vars: { ticketId: string; assessmentId: string }) => {\n const data = await buiQuery<{ buiCompleteLtiDeepLink: BuiLtiDeepLinkResult }>(\n `mutation BuiCompleteLtiDeepLink($ticketId: ID!, $assessmentId: ID!) {\n buiCompleteLtiDeepLink(ticketId: $ticketId, assessmentId: $assessmentId) { jwt returnUrl }\n }`,\n vars,\n baseUrl\n );\n return data.buiCompleteLtiDeepLink;\n },\n });\n};\n\nconst LTI_GRADE_SYNC_FIELDS = `\n id resourceLinkId submissionId learnerId scoreGiven scoreMaximum status\n httpStatus errorMessage attemptedAt respondedAt\n`;\n\nexport const useBuiLtiGradeSyncs = (resourceLinkId: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: resourceLinkId\n ? KEY.ltiGradeSyncs(resourceLinkId)\n : ['buildmyiq', 'ltiGradeSyncs', 'nil'],\n enabled: Boolean(resourceLinkId),\n queryFn: async () => {\n const data = await buiQuery<{ buiLtiGradeSyncs: BuiLtiGradeSync[] }>(\n `query BuiLtiGradeSyncs($resourceLinkId: ID!) {\n buiLtiGradeSyncs(resourceLinkId: $resourceLinkId) { ${LTI_GRADE_SYNC_FIELDS} }\n }`,\n { resourceLinkId },\n baseUrl\n );\n return data.buiLtiGradeSyncs;\n },\n });\n};\n\n/** Publishes one graded submission's score to the LMS gradebook (AGS). */\nexport const useBuiSyncLtiGrade = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { resourceLinkId: string; submissionId: string }) => {\n const data = await buiQuery<{ buiSyncLtiGrade: BuiLtiGradeSync }>(\n `mutation BuiSyncLtiGrade($resourceLinkId: ID!, $submissionId: ID!) {\n buiSyncLtiGrade(resourceLinkId: $resourceLinkId, submissionId: $submissionId) { ${LTI_GRADE_SYNC_FIELDS} }\n }`,\n vars,\n baseUrl\n );\n return data.buiSyncLtiGrade;\n },\n // A failed publish is recorded too, so refresh the history either way.\n onSettled: (_data, _error, vars) =>\n qc.invalidateQueries({ queryKey: KEY.ltiGradeSyncs(vars.resourceLinkId) }),\n });\n};\n\nconst LTI_ROSTER_FIELDS = `id ltiSub email displayName roles status syncedAt`;\n\nexport const useBuiLtiRoster = (resourceLinkId: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: resourceLinkId ? KEY.ltiRoster(resourceLinkId) : ['buildmyiq', 'ltiRoster', 'nil'],\n enabled: Boolean(resourceLinkId),\n queryFn: async () => {\n const data = await buiQuery<{ buiLtiRoster: BuiLtiRosterMember[] }>(\n `query BuiLtiRoster($resourceLinkId: ID!) {\n buiLtiRoster(resourceLinkId: $resourceLinkId) { ${LTI_ROSTER_FIELDS} }\n }`,\n { resourceLinkId },\n baseUrl\n );\n return data.buiLtiRoster;\n },\n });\n};\n\n/** Pulls the course roster from the LMS (NRPS) and stores it. */\nexport const useBuiSyncLtiRoster = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (resourceLinkId: string) => {\n const data = await buiQuery<{ buiSyncLtiRoster: BuiLtiRosterMember[] }>(\n `mutation BuiSyncLtiRoster($resourceLinkId: ID!) {\n buiSyncLtiRoster(resourceLinkId: $resourceLinkId) { ${LTI_ROSTER_FIELDS} }\n }`,\n { resourceLinkId },\n baseUrl\n );\n return data.buiSyncLtiRoster;\n },\n onSuccess: (members, resourceLinkId) => qc.setQueryData(KEY.ltiRoster(resourceLinkId), members),\n });\n};\n\nexport interface BuiCourseAssistantSettings {\n enabled: boolean;\n agentId: string | null;\n candidates: Array<{ id: string; name: string }>;\n courseStatus: BuiCourseStatus;\n configured: boolean;\n ready: boolean;\n ingestionStatus: string;\n sourceCount: number;\n processedCount: number;\n}\nexport function useBuiCourseAssistantSettings(courseId: string) {\n const { workspaceId, currentUser, apiGatewayUrl } = useBuildmyiq();\n return useQuery({\n queryKey: ['buildmyiq', 'course-assistant-settings', workspaceId, currentUser?.id, courseId],\n enabled: Boolean(workspaceId && currentUser?.id && courseId),\n retry: false,\n refetchInterval: 15000,\n queryFn: async () => {\n const data = await buiQuery<{ buiCourseAssistantSettings: BuiCourseAssistantSettings }>(\n `query BuiCourseAssistantSettings($courseId: ID!) { buiCourseAssistantSettings(courseId: $courseId) {\n enabled agentId candidates { id name } courseStatus configured ready ingestionStatus sourceCount processedCount\n } }`,\n { courseId },\n apiGatewayUrl\n );\n return data.buiCourseAssistantSettings;\n },\n });\n}\nexport function useBuiSetCourseAssistant(courseId: string) {\n const { workspaceId, currentUser, apiGatewayUrl } = useBuildmyiq();\n const queries = useQueryClient();\n return useMutation({\n retry: false,\n mutationFn: async (agentId: string | null) => {\n if (agentId)\n await buiQuery(\n 'mutation BuiConfigureCourseAssistant($courseId: ID!, $agentId: ID!) { buiConfigureCourseAssistant(courseId: $courseId, agentId: $agentId) { id } }',\n { courseId, agentId },\n apiGatewayUrl\n );\n else\n await buiQuery(\n 'mutation BuiDisableCourseAssistant($courseId: ID!) { buiDisableCourseAssistant(courseId: $courseId) }',\n { courseId },\n apiGatewayUrl\n );\n },\n onSuccess: () =>\n queries.invalidateQueries({\n queryKey: [\n 'buildmyiq',\n 'course-assistant-settings',\n workspaceId,\n currentUser?.id,\n courseId,\n ],\n }),\n });\n}\n\nexport function useBuiCreateCourseTeacher(courseId: string, enabled: boolean) {\n const { workspaceId, currentUser, apiGatewayUrl } = useBuildmyiq();\n const queries = useQueryClient();\n const options = useQuery({\n queryKey: ['buildmyiq', 'teacher-setup-options', workspaceId, currentUser?.id],\n enabled: enabled && Boolean(workspaceId && currentUser?.id),\n retry: false,\n queryFn: async () => {\n const models: Array<{ id: string; name: string; modelId: string }> = [];\n for (let offset = 0; offset < 500; offset += 100) {\n const page = await buiQuery<{\n listLLMModels: Array<{ id: string; name: string; modelId: string }>;\n }>(\n 'query BuiTeacherModels($offset: Int!) { listLLMModels(filters: { isActive: true }, pagination: { limit: 100, offset: $offset }) { id name modelId } }',\n { offset },\n apiGatewayUrl\n );\n if (!Array.isArray(page.listLLMModels) || page.listLLMModels.length > 100)\n throw new Error('Models unavailable');\n models.push(...page.listLLMModels);\n if (page.listLLMModels.length < 100) break;\n if (offset === 400) throw new Error('Too many models');\n }\n const provider = await buiQuery<{ getProviderByKey: { id: string } | null }>(\n 'query BuiTeacherWorkflowProvider { getProviderByKey(key: \"botmanor-runtime\") { id } }',\n {},\n apiGatewayUrl\n );\n const connections: Array<{ id: string; name: string }> = [];\n if (provider.getProviderByKey) {\n for (let offset = 0; offset < 500; offset += 100) {\n const page = await buiQuery<{\n getConnections: {\n hasMore: boolean;\n items: Array<{\n id: string;\n name: string;\n workspaceId: string | null;\n status: string;\n provider: { key: string };\n authMethod: { authType: string; isEnabled: boolean; isConfigured: boolean } | null;\n }>;\n };\n }>(\n 'query BuiTeacherConnections($providerId: ID!, $offset: Int!) { getConnections(filter: { providerId: $providerId, status: ACTIVE }, pagination: { limit: 100, offset: $offset }) { hasMore items { id name workspaceId status provider { key } authMethod { authType isEnabled isConfigured } } } }',\n { providerId: provider.getProviderByKey.id, offset },\n apiGatewayUrl\n );\n if (!page.getConnections || page.getConnections.items.length > 100)\n throw new Error('Connections unavailable');\n for (const connection of page.getConnections.items)\n if (\n connection.workspaceId === workspaceId &&\n connection.status === 'ACTIVE' &&\n connection.provider.key === 'botmanor-runtime' &&\n connection.authMethod?.authType === 'WORKSPACE_APP_TOKEN' &&\n connection.authMethod.isConfigured &&\n connection.authMethod.isEnabled\n )\n connections.push({ id: connection.id, name: connection.name });\n if (!page.getConnections.hasMore) break;\n if (offset === 400) throw new Error('Too many connections');\n }\n }\n const embeddingNames = [\n 'amazon.titan-embed-text-v2:0',\n 'text-embedding-3-small',\n 'text-embedding-3-large',\n 'text-embedding-ada-002',\n ];\n return {\n embeddingModels: models.filter((model) => embeddingNames.includes(model.modelId)),\n chatModels: models.filter((model) => !embeddingNames.includes(model.modelId)),\n connections,\n };\n },\n });\n const create = useMutation({\n retry: false,\n mutationFn: async (selection: CourseTeacherSetupSelection) => {\n if (!workspaceId || !currentUser?.id) throw new Error('Sign in to set up the teacher');\n return provisionCourseTeacher(courseId, selection, (query, variables) =>\n buiQuery(query, variables, apiGatewayUrl)\n );\n },\n onSettled: () =>\n queries.invalidateQueries({\n queryKey: [\n 'buildmyiq',\n 'course-assistant-settings',\n workspaceId,\n currentUser?.id,\n courseId,\n ],\n }),\n });\n return { options, create };\n}\n\n// ============================================================================\n// L&D workflow automation via FluidGrids (BOFF-9688)\n// ============================================================================\n\nconst AUTOMATION_FIELDS = `\n id template name description triggerKind triggerDescription actionDescription enabled\n config defaultConfig workflowKey workflowVersion workflowDefinitionId\n lastRunAt lastRunStatus lastError updatedAt\n`;\n\nconst AUTOMATION_RUN_FIELDS = `\n id template triggerSource status fluidgridsRunId subject action result error createdAt completedAt\n`;\n\n/** Every automation template and its state in this workspace. */\nexport const useBuiAutomations = () => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: KEY.automations,\n queryFn: async () => {\n const data = await buiQuery<{ buiAutomations: BuiAutomation[] }>(\n `query BuiAutomations { buiAutomations { ${AUTOMATION_FIELDS} } }`,\n {},\n baseUrl\n );\n return data.buiAutomations;\n },\n });\n};\n\n/**\n * Recent automation runs, newest first. Polls while any run is still waiting\n * on FluidGrids so a \"Run now\" result appears without a reload.\n */\nexport const useBuiAutomationRuns = (template?: BuiAutomationTemplate, limit = 20) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: [...KEY.automationRuns, { template: template ?? null, limit }],\n queryFn: async () => {\n const data = await buiQuery<{\n buiAutomationRuns: {\n items: BuiAutomationRun[];\n pageInfo: { hasMore: boolean; cursor: string | null };\n };\n }>(\n `query BuiAutomationRuns($template: BuiAutomationTemplate, $pagination: PaginationInput) {\n buiAutomationRuns(template: $template, pagination: $pagination) {\n items { ${AUTOMATION_RUN_FIELDS} }\n pageInfo { hasMore cursor }\n }\n }`,\n { template: template ?? null, pagination: { limit } },\n baseUrl\n );\n return data.buiAutomationRuns;\n },\n refetchInterval: (query) =>\n query.state.data?.items.some((run) => run.status === 'PENDING' || run.status === 'APPLYING')\n ? 4000\n : false,\n });\n};\n\nexport const useBuiConfigureAutomation = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiConfigureAutomationInput) => {\n const data = await buiQuery<{ buiConfigureAutomation: BuiAutomation }>(\n `mutation BuiConfigureAutomation($input: BuiConfigureAutomationInput!) {\n buiConfigureAutomation(input: $input) { ${AUTOMATION_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiConfigureAutomation;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.automations }),\n });\n};\n\nexport const useBuiRunAutomationNow = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (template: BuiAutomationTemplate) => {\n const data = await buiQuery<{ buiRunAutomationNow: BuiAutomationRun }>(\n `mutation BuiRunAutomationNow($template: BuiAutomationTemplate!) {\n buiRunAutomationNow(template: $template) { ${AUTOMATION_RUN_FIELDS} }\n }`,\n { template },\n baseUrl\n );\n return data.buiRunAutomationNow;\n },\n onSuccess: () => {\n void qc.invalidateQueries({ queryKey: KEY.automationRuns });\n void qc.invalidateQueries({ queryKey: KEY.automations });\n },\n });\n};\n\n/** Set or clear an enrollment's due date (instructors/admins). */\nexport const useBuiSetEnrollmentDueDate = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (args: { id: string; dueAt: string | null }) => {\n const data = await buiQuery<{ buiSetEnrollmentDueDate: BuiEnrollment }>(\n `mutation BuiSetEnrollmentDueDate($id: ID!, $dueAt: DateTime) {\n buiSetEnrollmentDueDate(id: $id, dueAt: $dueAt) { ${ENROLLMENT_FIELDS} }\n }`,\n args,\n baseUrl\n );\n return data.buiSetEnrollmentDueDate;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.enrollments }),\n });\n};\n\n// ============================================================================\n// Workspace AI content controls (BOFF-9689)\n// ============================================================================\n\nconst AI_SETTINGS_FIELDS = `\n workspaceId blockedTerms applyToTutor maxBlockedTerms maxBlockedTermLength updatedAt updatedBy\n`;\n\n/**\n * The workspace's saved AI block-list. The server merges it into every AI\n * authoring call, so the dialogs only display it.\n */\nexport const useBuiAiSettings = (enabled = true) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: KEY.aiSettings,\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiAiSettings: BuiAiSettings }>(\n `query BuiAiSettings { buiAiSettings { ${AI_SETTINGS_FIELDS} } }`,\n {},\n baseUrl\n );\n return data.buiAiSettings;\n },\n });\n};\n\n/** Save the workspace's AI content controls (admin only). */\nexport const useBuiUpdateAiSettings = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiUpdateAiSettingsInput) => {\n const data = await buiQuery<{ buiUpdateAiSettings: BuiAiSettings }>(\n `mutation BuiUpdateAiSettings($input: BuiUpdateAiSettingsInput!) {\n buiUpdateAiSettings(input: $input) { ${AI_SETTINGS_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiUpdateAiSettings;\n },\n onSuccess: (settings) => qc.setQueryData(KEY.aiSettings, settings),\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"useBuildmyiqApi.js","names":[],"sources":["../../../src/buildmyiq/hooks/useBuildmyiqApi.ts"],"sourcesContent":["/**\n * Buildmyiq API hooks\n * @module buildmyiq/hooks\n *\n * React-Query hooks wired DIRECTLY to the real `wspace-buildmyiq-svc`\n * federated GraphQL contract (the `bui*` operations). Every query/mutation\n * below uses an inline gql string whose fields match the svc\n * `.hive-schema.graphql` exactly. No mock data, no codegen.\n *\n * Transport: `graphqlFetch({ gateway: 'workspace', workspaceToken: true })` —\n * the host shell supplies the gateway base URL + a workspace-scoped token.\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\n\nimport { useBuildmyiq } from '../context';\nimport { provisionCourseTeacher, type CourseTeacherSetupSelection } from './courseTeacherSetup';\nimport type {\n BuiConnection,\n BuiCourse,\n BuiCourseLevel,\n BuiCourseStatus,\n BuiModule,\n BuiLesson,\n BuiAssessment,\n BuiAssessmentStatus,\n BuiQuestion,\n BuiSubmission,\n BuiSubmissionStatus,\n BuiEnrollment,\n BuiEnrollmentStatus,\n BuiCohort,\n BuiCohortStatus,\n BuiSkill,\n BuiSkillCategory,\n BuiSkillStandard,\n BuiCertification,\n BuiSkillMappingSuggestion,\n BuiCertificate,\n BuiLessonProgress,\n BuiCreateCourseInput,\n BuiUpdateCourseInput,\n BuiCreateModuleInput,\n BuiCreateLessonInput,\n BuiCreateAssessmentInput,\n BuiCreateQuestionInput,\n BuiCreateSkillInput,\n BuiCreateCohortInput,\n BuiEnrollInput,\n BuiRecordLessonProgressInput,\n BuiSubmitAssessmentInput,\n BuiGradeSubmissionInput,\n BuiIssueCertificateInput,\n BuiTutorAskInput,\n BuiTutorAskPayload,\n BuiTutorSession,\n BuiTutorMessage,\n BuiReviewTutorAnswerInput,\n BuiGradeSuggestion,\n BuiNextLessonSuggestion,\n BuiCourseOutlineSuggestion,\n BuiApplyCourseOutlineInput,\n BuiApplyAssessmentDraftInput,\n BuiAssessmentDraftSuggestion,\n BuiSuggestAssessmentDraftInput,\n BuiAdminCopilotActionKind,\n BuiAdminCopilotActionStatus,\n BuiAdminCopilotAnswer,\n BuiAdminCopilotExecution,\n BuiAdminCopilotProposedAction,\n BuiAdminCopilotTurnInput,\n BuiAiSuggestionOutcome,\n BuiLtiPlatform,\n BuiLtiResourceLink,\n BuiLtiLaunchContext,\n BuiLtiDeepLinkResult,\n BuiLtiGradeSync,\n BuiLtiRosterMember,\n BuiRegisterLtiPlatformInput,\n BuiAiSettings,\n BuiAutomation,\n BuiAutomationRun,\n BuiAutomationTemplate,\n BuiConfigureAutomationInput,\n BuiUpdateAiSettingsInput,\n PaginationInput,\n} from '../types';\n\n// ============================================================================\n// Transport\n// ============================================================================\n\n/**\n * fe-libs `graphqlFetch` coalesces `query` responses in an in-memory cache keyed\n * by operationName+variables for ~15s (mutations are never cached). A read\n * issued right after a write (e.g. the React-Query refetch triggered by our\n * `invalidateQueries`) would otherwise return the PRE-mutation response until the\n * TTL expires — making just-created/updated rows invisible until a full reload.\n * We clear those caches after every buildmyiq mutation so every follow-up read\n * is fresh.\n */\ntype GraphqlReadCacheGlobals = {\n __graphqlFetchResponseCache?: { clear: () => void };\n __graphqlFetchPendingResponses?: { clear: () => void };\n __boffGraphQLResponseCache?: { clear: () => void };\n};\n\nconst clearGraphqlReadCaches = (): void => {\n const g = globalThis as GraphqlReadCacheGlobals;\n g.__graphqlFetchResponseCache?.clear();\n g.__graphqlFetchPendingResponses?.clear();\n g.__boffGraphQLResponseCache?.clear();\n};\n\nconst buiQuery = async <TData>(\n query: string,\n variables: Record<string, unknown>,\n baseUrl?: string\n): Promise<TData> => {\n const response = await graphqlFetch<TData>({\n gateway: 'workspace',\n baseUrl,\n query,\n variables,\n workspaceToken: true,\n });\n\n if (response.errors?.length) {\n throw new Error(response.errors[0]?.message ?? 'GraphQL request failed');\n }\n if (!response.data) {\n throw new Error('GraphQL response did not include data');\n }\n if (/^\\s*mutation\\b/.test(query)) {\n clearGraphqlReadCaches();\n }\n return response.data;\n};\n\n// React-Query key roots (one namespace per domain entity).\nconst KEY = {\n courses: ['buildmyiq', 'courses'] as const,\n course: (id: string) => ['buildmyiq', 'course', id] as const,\n modules: (courseId: string) => ['buildmyiq', 'modules', courseId] as const,\n lessons: (courseId: string) => ['buildmyiq', 'lessons', courseId] as const,\n assessments: (courseId: string) => ['buildmyiq', 'assessments', courseId] as const,\n assessment: (id: string) => ['buildmyiq', 'assessment', id] as const,\n enrollments: ['buildmyiq', 'enrollments'] as const,\n enrollment: (id: string) => ['buildmyiq', 'enrollment', id] as const,\n certificates: ['buildmyiq', 'certificates'] as const,\n cohorts: ['buildmyiq', 'cohorts'] as const,\n skills: ['buildmyiq', 'skills'] as const,\n submissions: ['buildmyiq', 'submissions'] as const,\n submission: (id: string) => ['buildmyiq', 'submission', id] as const,\n tutorSessions: (lessonId: string) => ['buildmyiq', 'tutorSessions', lessonId] as const,\n tutorReview: ['buildmyiq', 'tutorReview'] as const,\n tutorMode: (enrollmentId: string) => ['buildmyiq', 'tutorMode', enrollmentId] as const,\n ltiPlatforms: ['buildmyiq', 'ltiPlatforms'] as const,\n ltiResourceLinks: ['buildmyiq', 'ltiResourceLinks'] as const,\n ltiGradeSyncs: (resourceLinkId: string) =>\n ['buildmyiq', 'ltiGradeSyncs', resourceLinkId] as const,\n ltiRoster: (resourceLinkId: string) => ['buildmyiq', 'ltiRoster', resourceLinkId] as const,\n adminCopilotActions: ['buildmyiq', 'adminCopilotActions'] as const,\n automations: ['buildmyiq', 'automations'] as const,\n automationRuns: ['buildmyiq', 'automationRuns'] as const,\n aiSettings: ['buildmyiq', 'aiSettings'] as const,\n};\n\nconst DEFAULT_PAGE_SIZE = 24;\n\n/**\n * Build a `PaginationInput` for a list query. The FIRST page (undefined cursor)\n * OMITS the cursor key entirely — the svc rejects an explicit `cursor: null`.\n */\nconst pageVars = (cursor?: string, limit = DEFAULT_PAGE_SIZE): PaginationInput =>\n cursor ? { limit, cursor } : { limit };\n\n// ============================================================================\n// Reusable gql field selections (codegen-free strictness)\n// ============================================================================\n\nconst FILE_FIELDS = `id name downloadUrl mimeType`;\n\nconst SKILL_FIELDS = `\n id workspaceId name category description isActive\n onetCode escoUri socCodes certificationIds taxonomyMetadata\n createdAt updatedAt\n`;\n\nconst SKILL_STANDARD_FIELDS = `\n id workspaceId source code title description category uri socCodes metadata isActive createdAt updatedAt\n`;\n\nconst CERTIFICATION_FIELDS = `\n id workspaceId body code name description url isActive createdAt updatedAt\n`;\n\nconst COURSE_CORE_FIELDS = `\n id workspaceId title slug summary description status level language\n estimatedHours isPublic tags skillId instructorId publishedAt createdAt updatedAt\n cover { ${FILE_FIELDS} }\n skill { id name category }\n`;\n\nconst MODULE_FIELDS = `\n id workspaceId courseId title description position createdAt updatedAt\n`;\n\nconst LESSON_FIELDS = `\n id workspaceId courseId moduleId title type content durationMin position isPreview\n createdAt updatedAt\n media { ${FILE_FIELDS} }\n`;\n\n// NOTE: `modules`/`lessons` are `Bui*Connection!` on the svc schema (paginated),\n// NOT plain lists — every nested selection below must go through `items { }` or\n// the gateway rejects the whole query with GRAPHQL_VALIDATION_FAILED (BOFF-4703\n// Connection-shape drift). See `flattenCourse` for the matching unwrap.\nconst COURSE_FULL_FIELDS = `\n ${COURSE_CORE_FIELDS}\n modules { items { ${MODULE_FIELDS} lessons { items { ${LESSON_FIELDS} } } } }\n lessons { items { ${LESSON_FIELDS} } }\n`;\n\nconst ASSESSMENT_FIELDS = `\n id workspaceId courseId title description type status passingScore maxAttempts\n timeLimitMin isGraded requiresProctoring createdAt updatedAt\n`;\n\n// NOTE: BuiQuestion has NO `answerKey` on the type (create-input only).\nconst QUESTION_FIELDS = `\n id workspaceId assessmentId prompt type options points position explanation\n createdAt updatedAt\n`;\n\n// `questions` is `BuiQuestionConnection!` — see COURSE_FULL_FIELDS note above.\nconst ASSESSMENT_FULL_FIELDS = `\n ${ASSESSMENT_FIELDS}\n questions { items { ${QUESTION_FIELDS} } }\n`;\n\nconst SUBMISSION_FIELDS = `\n id workspaceId assessmentId enrollmentId learnerId attempt answers status score\n passed feedback gradedById gradedAt submittedAt createdAt updatedAt\n`;\n\nconst COHORT_FIELDS = `\n id workspaceId courseId name capacity facilitatorId startDate endDate status\n createdAt updatedAt\n`;\n\nconst LESSON_PROGRESS_FIELDS = `\n id workspaceId enrollmentId lessonId status secondsSpent completedAt createdAt updatedAt\n`;\n\nconst ENROLLMENT_FIELDS = `\n id workspaceId courseId learnerId cohortId status progressPct enrolledAt startedAt\n completedAt lastActiveAt expiresAt dueAt createdAt updatedAt\n`;\n\n// `lessonProgress` is `BuiLessonProgressConnection!` — see COURSE_FULL_FIELDS note above.\nconst ENROLLMENT_FULL_FIELDS = `\n ${ENROLLMENT_FIELDS}\n cohort { ${COHORT_FIELDS} }\n lessonProgress { items { ${LESSON_PROGRESS_FIELDS} } }\n`;\n\n// `file` selects ONLY `id` (the page renders it through FileLink/getFile):\n// a federated File stub cannot resolve any other field, and selecting one\n// fails every certificate read once a certificate carries a PDF.\nconst CERTIFICATE_FIELDS = `\n id workspaceId courseId learnerId enrollmentId serial status issuedAt expiresAt\n revokedAt finalScore verificationCode recipientNameSnapshot createdAt updatedAt\n file { id }\n`;\n\n// `content` is what the learner should see: the instructor's corrected text\n// or a removal notice once an answer is reviewed (BOFF-9663); `review` drives\n// the \"reviewed by your instructor\" marker.\nconst TUTOR_MESSAGE_FIELDS = `\n id workspaceId sessionId role content groundingLessonIds adaptiveLevel createdAt\n review { status note reviewedAt }\n`;\n\n// Educator review surface (BOFF-9663): the original answer, the reviewer and the\n// full audit trail resolve only through `buiListTutorSessions` and\n// `buiReviewTutorAnswer`.\nconst TUTOR_REVIEW_MESSAGE_FIELDS = `\n id workspaceId sessionId role content groundingLessonIds adaptiveLevel createdAt\n originalContent\n review { status note reviewedAt reviewedBy }\n reviewHistory { id action previousStatus content note reviewerId createdAt }\n`;\n\nconst TUTOR_SESSION_FIELDS = `\n id workspaceId courseId lessonId learnerId createdAt updatedAt\n messages { ${TUTOR_MESSAGE_FIELDS} }\n`;\n\n// ============================================================================\n// Connection-shape unwrap (BOFF-4703)\n// ============================================================================\n// Every `Bui*Connection` field on the wire is `{ items: T[]; pageInfo }`, never\n// a bare list — including NESTED fields like `BuiCourse.modules` or\n// `BuiAssessment.questions`. The hooks below keep returning plain flat arrays\n// to consumers (that's the shape every page in this MFE is written against),\n// so raw wire responses are unwrapped once here rather than pushing the\n// Connection shape out to every page.\n\n/** Wire shape of a `BuiModule` fetched via `COURSE_FULL_FIELDS` (nested `lessons` is a Connection). */\ntype BuiModuleWire = Omit<BuiModule, 'lessons'> & { lessons: { items: BuiLesson[] } };\n\n/** Wire shape of a `BuiCourse` fetched via `COURSE_FULL_FIELDS`. */\ntype BuiCourseWire = Omit<BuiCourse, 'modules' | 'lessons'> & {\n modules: { items: BuiModuleWire[] };\n lessons: { items: BuiLesson[] };\n};\n\nconst flattenCourse = (c: BuiCourseWire): BuiCourse => ({\n ...c,\n modules: c.modules.items.map((m) => ({ ...m, lessons: m.lessons.items })),\n lessons: c.lessons.items,\n});\n\n/** Wire shape of a `BuiAssessment` fetched via `ASSESSMENT_FULL_FIELDS`. */\ntype BuiAssessmentWire = Omit<BuiAssessment, 'questions'> & { questions: { items: BuiQuestion[] } };\n\nconst flattenAssessment = (a: BuiAssessmentWire): BuiAssessment => ({\n ...a,\n questions: a.questions.items,\n});\n\n/** Wire shape of a `BuiEnrollment` fetched via `ENROLLMENT_FULL_FIELDS`. */\ntype BuiEnrollmentWire = Omit<BuiEnrollment, 'lessonProgress'> & {\n lessonProgress: { items: BuiLessonProgress[] };\n};\n\nconst flattenEnrollment = (e: BuiEnrollmentWire): BuiEnrollment => ({\n ...e,\n lessonProgress: e.lessonProgress.items,\n});\n\n// ============================================================================\n// Shared hook helper: resolve gateway URL from context\n// ============================================================================\n\nconst useGateway = (): string | undefined => {\n const { apiGatewayUrl } = useBuildmyiq();\n return apiGatewayUrl;\n};\n\n// ============================================================================\n// Courses\n// ============================================================================\n\nexport interface UseBuiCoursesArgs {\n level?: BuiCourseLevel;\n status?: BuiCourseStatus;\n cursor?: string;\n limit?: number;\n enabled?: boolean;\n}\n\nexport const useBuiCourses = (args: UseBuiCoursesArgs = {}) => {\n const baseUrl = useGateway();\n const { level, status, cursor, limit, enabled = true } = args;\n return useQuery({\n queryKey: [...KEY.courses, { level, status, cursor, limit }],\n enabled,\n queryFn: async () => {\n // Only `id` is needed here (list view shows module/lesson COUNTS, not\n // full records — see CourseCard.tsx) so we intentionally under-select\n // vs. the full `BuiModule`/`BuiLesson` shape; still must go through\n // `items { }` since both fields are Connections (BOFF-4703).\n const data = await buiQuery<{\n buiListCourses: {\n items: Array<\n Omit<BuiCourse, 'modules' | 'lessons'> & {\n modules: { items: Array<{ id: string }> };\n lessons: { items: Array<{ id: string }> };\n }\n >;\n pageInfo: BuiConnection<BuiCourse>['pageInfo'];\n };\n }>(\n `query BuiListCourses($level: BuiCourseLevel, $status: BuiCourseStatus, $pagination: PaginationInput) {\n buiListCourses(level: $level, status: $status, pagination: $pagination) {\n items { ${COURSE_CORE_FIELDS} modules { items { id } } lessons { items { id } } }\n pageInfo { cursor hasMore }\n }\n }`,\n { level, status, pagination: pageVars(cursor, limit) },\n baseUrl\n );\n return {\n items: data.buiListCourses.items.map((c) => ({\n ...c,\n // Partial `{ id }`-only records are cast to the full type — safe here\n // because every consumer of the list view only reads `.length`.\n modules: c.modules.items as unknown as BuiModule[],\n lessons: c.lessons.items as unknown as BuiLesson[],\n })),\n pageInfo: data.buiListCourses.pageInfo,\n };\n },\n });\n};\n\nexport const useBuiCourse = (id: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: id ? KEY.course(id) : ['buildmyiq', 'course', 'nil'],\n enabled: Boolean(id),\n queryFn: async () => {\n const data = await buiQuery<{ buiCourse: BuiCourseWire | null }>(\n `query BuiCourse($id: ID!) {\n buiCourse(id: $id) { ${COURSE_FULL_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiCourse ? flattenCourse(data.buiCourse) : null;\n },\n });\n};\n\nexport const useBuiCreateCourse = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiCreateCourseInput) => {\n const data = await buiQuery<{ buiCreateCourse: BuiCourse }>(\n `mutation BuiCreateCourse($input: BuiCreateCourseInput!) {\n buiCreateCourse(input: $input) { ${COURSE_CORE_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiCreateCourse;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.courses }),\n });\n};\n\nexport const useBuiUpdateCourse = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (args: { id: string; input: BuiUpdateCourseInput }) => {\n const data = await buiQuery<{ buiUpdateCourse: BuiCourse }>(\n `mutation BuiUpdateCourse($id: ID!, $input: BuiUpdateCourseInput!) {\n buiUpdateCourse(id: $id, input: $input) { ${COURSE_CORE_FIELDS} }\n }`,\n args,\n baseUrl\n );\n return data.buiUpdateCourse;\n },\n onSuccess: (course) => {\n qc.invalidateQueries({ queryKey: KEY.courses });\n qc.invalidateQueries({ queryKey: KEY.course(course.id) });\n },\n });\n};\n\nexport const useBuiPublishCourse = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await buiQuery<{ buiPublishCourse: BuiCourse }>(\n `mutation BuiPublishCourse($id: ID!) {\n buiPublishCourse(id: $id) { ${COURSE_CORE_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiPublishCourse;\n },\n onSuccess: (course) => {\n qc.invalidateQueries({ queryKey: KEY.courses });\n qc.invalidateQueries({ queryKey: KEY.course(course.id) });\n },\n });\n};\n\nexport const useBuiArchiveCourse = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await buiQuery<{ buiArchiveCourse: boolean }>(\n `mutation BuiArchiveCourse($id: ID!) { buiArchiveCourse(id: $id) }`,\n { id },\n baseUrl\n );\n return data.buiArchiveCourse;\n },\n onSuccess: (_r, id) => {\n qc.invalidateQueries({ queryKey: KEY.courses });\n qc.invalidateQueries({ queryKey: KEY.course(id) });\n },\n });\n};\n\n// ============================================================================\n// Modules & lessons\n// ============================================================================\n\nexport const useBuiModules = (courseId: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: courseId ? KEY.modules(courseId) : ['buildmyiq', 'modules', 'nil'],\n enabled: Boolean(courseId),\n queryFn: async () => {\n const data = await buiQuery<{ buiListModules: { items: BuiModuleWire[] } }>(\n `query BuiListModules($courseId: ID!) {\n buiListModules(courseId: $courseId) {\n items { ${MODULE_FIELDS} lessons { items { ${LESSON_FIELDS} } } }\n }\n }`,\n { courseId },\n baseUrl\n );\n return data.buiListModules.items.map((m) => ({ ...m, lessons: m.lessons.items }));\n },\n });\n};\n\nexport const useBuiLessons = (courseId: string | undefined, moduleId?: string) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: courseId ? [...KEY.lessons(courseId), { moduleId }] : ['buildmyiq', 'lessons', 'nil'],\n enabled: Boolean(courseId),\n queryFn: async () => {\n const data = await buiQuery<{ buiListLessons: { items: BuiLesson[] } }>(\n `query BuiListLessons($courseId: ID!, $moduleId: ID) {\n buiListLessons(courseId: $courseId, moduleId: $moduleId) { items { ${LESSON_FIELDS} } }\n }`,\n { courseId, moduleId },\n baseUrl\n );\n return data.buiListLessons.items;\n },\n });\n};\n\nexport const useBuiCreateModule = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiCreateModuleInput) => {\n const data = await buiQuery<{ buiCreateModule: BuiModule }>(\n `mutation BuiCreateModule($input: BuiCreateModuleInput!) {\n buiCreateModule(input: $input) { ${MODULE_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiCreateModule;\n },\n onSuccess: (m) => {\n qc.invalidateQueries({ queryKey: KEY.modules(m.courseId) });\n qc.invalidateQueries({ queryKey: KEY.course(m.courseId) });\n },\n });\n};\n\nexport const useBuiCreateLesson = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiCreateLessonInput) => {\n const data = await buiQuery<{ buiCreateLesson: BuiLesson }>(\n `mutation BuiCreateLesson($input: BuiCreateLessonInput!) {\n buiCreateLesson(input: $input) { ${LESSON_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiCreateLesson;\n },\n onSuccess: (l) => {\n qc.invalidateQueries({ queryKey: KEY.lessons(l.courseId) });\n qc.invalidateQueries({ queryKey: KEY.modules(l.courseId) });\n qc.invalidateQueries({ queryKey: KEY.course(l.courseId) });\n },\n });\n};\n\n// ============================================================================\n// Assessments & questions\n// ============================================================================\n\nexport const useBuiAssessments = (courseId: string | undefined, status?: BuiAssessmentStatus) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: courseId\n ? [...KEY.assessments(courseId), { status }]\n : ['buildmyiq', 'assessments', 'nil'],\n enabled: Boolean(courseId),\n queryFn: async () => {\n // Only `id` is needed here (list view shows a question COUNT, not full\n // records — see AssessmentsPage.tsx); still must go through `items { }`\n // since `questions` is a Connection (BOFF-4703).\n const data = await buiQuery<{\n buiListAssessments: {\n items: Array<\n Omit<BuiAssessment, 'questions'> & { questions: { items: Array<{ id: string }> } }\n >;\n };\n }>(\n `query BuiListAssessments($courseId: ID!, $status: BuiAssessmentStatus) {\n buiListAssessments(courseId: $courseId, status: $status) {\n items { ${ASSESSMENT_FIELDS} questions { items { id } } }\n }\n }`,\n { courseId, status },\n baseUrl\n );\n return data.buiListAssessments.items.map((a) => ({\n ...a,\n // Partial `{ id }`-only records are cast to the full type — safe here\n // because every consumer of the list view only reads `.length`.\n questions: a.questions.items as unknown as BuiQuestion[],\n }));\n },\n });\n};\n\nexport const useBuiAssessment = (id: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: id ? KEY.assessment(id) : ['buildmyiq', 'assessment', 'nil'],\n enabled: Boolean(id),\n queryFn: async () => {\n const data = await buiQuery<{ buiAssessment: BuiAssessmentWire | null }>(\n `query BuiAssessment($id: ID!) {\n buiAssessment(id: $id) { ${ASSESSMENT_FULL_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiAssessment ? flattenAssessment(data.buiAssessment) : null;\n },\n });\n};\n\nexport const useBuiCreateAssessment = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiCreateAssessmentInput) => {\n const data = await buiQuery<{ buiCreateAssessment: BuiAssessment }>(\n `mutation BuiCreateAssessment($input: BuiCreateAssessmentInput!) {\n buiCreateAssessment(input: $input) { ${ASSESSMENT_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiCreateAssessment;\n },\n onSuccess: (a) => qc.invalidateQueries({ queryKey: KEY.assessments(a.courseId) }),\n });\n};\n\nexport const useBuiPublishAssessment = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await buiQuery<{ buiPublishAssessment: BuiAssessment }>(\n `mutation BuiPublishAssessment($id: ID!) {\n buiPublishAssessment(id: $id) { ${ASSESSMENT_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiPublishAssessment;\n },\n onSuccess: (a) => {\n qc.invalidateQueries({ queryKey: KEY.assessment(a.id) });\n qc.invalidateQueries({ queryKey: KEY.assessments(a.courseId) });\n },\n });\n};\n\n/**\n * Archive an assessment (soft-delete) — releases its reusable\n * `buildmyiq.assessments.count` quota slot server-side (BOFF-4722) so the\n * workspace can create a replacement without hitting the plan limit.\n * `buiArchiveAssessment` returns only a `Boolean!`, not the record, so the\n * caller supplies `courseId` (already in hand from the loaded assessment)\n * to invalidate the right list query.\n */\nexport const useBuiArchiveAssessment = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (args: { id: string; courseId: string }) => {\n const data = await buiQuery<{ buiArchiveAssessment: boolean }>(\n `mutation BuiArchiveAssessment($id: ID!) { buiArchiveAssessment(id: $id) }`,\n { id: args.id },\n baseUrl\n );\n return data.buiArchiveAssessment;\n },\n onSuccess: (_r, args) => {\n qc.invalidateQueries({ queryKey: KEY.assessment(args.id) });\n qc.invalidateQueries({ queryKey: KEY.assessments(args.courseId) });\n },\n });\n};\n\nexport const useBuiCreateQuestion = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiCreateQuestionInput) => {\n const data = await buiQuery<{ buiCreateQuestion: BuiQuestion }>(\n `mutation BuiCreateQuestion($input: BuiCreateQuestionInput!) {\n buiCreateQuestion(input: $input) { ${QUESTION_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiCreateQuestion;\n },\n onSuccess: (q) => qc.invalidateQueries({ queryKey: KEY.assessment(q.assessmentId) }),\n });\n};\n\n// ============================================================================\n// Submissions & grading\n// ============================================================================\n\nexport interface UseBuiSubmissionsArgs {\n assessmentId?: string;\n status?: BuiSubmissionStatus;\n cursor?: string;\n limit?: number;\n enabled?: boolean;\n}\n\nexport const useBuiSubmissions = (args: UseBuiSubmissionsArgs = {}) => {\n const baseUrl = useGateway();\n const { assessmentId, status, cursor, limit, enabled = true } = args;\n return useQuery({\n queryKey: [...KEY.submissions, { assessmentId, status, cursor, limit }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiListSubmissions: BuiConnection<BuiSubmission> }>(\n `query BuiListSubmissions($assessmentId: ID, $status: BuiSubmissionStatus, $pagination: PaginationInput) {\n buiListSubmissions(assessmentId: $assessmentId, status: $status, pagination: $pagination) {\n items { ${SUBMISSION_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { assessmentId, status, pagination: pageVars(cursor, limit) },\n baseUrl\n );\n return data.buiListSubmissions;\n },\n });\n};\n\n/**\n * The signed-in learner's own submissions (self-scoped). The backend dropped\n * the `learnerId` arg from `buiListSubmissions` in the FERPA/IDOR hardening;\n * a learner's own results come from `buiMySubmissions` instead.\n */\nexport const useBuiMySubmissions = (args: UseBuiSubmissionsArgs = {}) => {\n const baseUrl = useGateway();\n const { assessmentId, status, cursor, limit, enabled = true } = args;\n return useQuery({\n queryKey: [...KEY.submissions, 'mine', { assessmentId, status, cursor, limit }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiMySubmissions: BuiConnection<BuiSubmission> }>(\n `query BuiMySubmissions($assessmentId: ID, $status: BuiSubmissionStatus, $pagination: PaginationInput) {\n buiMySubmissions(assessmentId: $assessmentId, status: $status, pagination: $pagination) {\n items { ${SUBMISSION_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { assessmentId, status, pagination: pageVars(cursor, limit) },\n baseUrl\n );\n return data.buiMySubmissions;\n },\n });\n};\n\n/** Single-submission lookup — used for deep-linking to `/buildmyiq/submissions/:submissionId`. */\nexport const useBuiSubmission = (id: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: id ? KEY.submission(id) : ['buildmyiq', 'submission', 'nil'],\n enabled: Boolean(id),\n queryFn: async () => {\n const data = await buiQuery<{ buiSubmission: BuiSubmission | null }>(\n `query BuiSubmission($id: ID!) {\n buiSubmission(id: $id) { ${SUBMISSION_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiSubmission;\n },\n });\n};\n\nexport const useBuiSubmitAssessment = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiSubmitAssessmentInput) => {\n const data = await buiQuery<{ buiSubmitAssessment: BuiSubmission }>(\n `mutation BuiSubmitAssessment($input: BuiSubmitAssessmentInput!) {\n buiSubmitAssessment(input: $input) { ${SUBMISSION_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiSubmitAssessment;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.submissions }),\n });\n};\n\nexport const useBuiGradeSubmission = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (args: { id: string; input: BuiGradeSubmissionInput }) => {\n const data = await buiQuery<{ buiGradeSubmission: BuiSubmission }>(\n `mutation BuiGradeSubmission($id: ID!, $input: BuiGradeSubmissionInput!) {\n buiGradeSubmission(id: $id, input: $input) { ${SUBMISSION_FIELDS} }\n }`,\n args,\n baseUrl\n );\n return data.buiGradeSubmission;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.submissions }),\n });\n};\n\n/**\n * Deterministically grades a submission whose assessment is made up ENTIRELY of\n * objective questions (SINGLE_CHOICE / MULTIPLE_CHOICE / TRUE_FALSE) by\n * comparing the learner's answers against each question's answer key — no LLM\n * and no human judgement involved. Unlike `useBuiSuggestGrade` this DOES write\n * the submission. The svc throws when the assessment contains any\n * SHORT_ANSWER / ESSAY / CODE question; callers gate the action on the\n * assessment's question types and surface the error honestly if it still fails.\n */\nexport const useBuiAutoScoreSubmission = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await buiQuery<{ buiAutoScoreSubmission: BuiSubmission }>(\n `mutation BuiAutoScoreSubmission($id: ID!) {\n buiAutoScoreSubmission(id: $id) { ${SUBMISSION_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiAutoScoreSubmission;\n },\n onSuccess: (s) => {\n qc.invalidateQueries({ queryKey: KEY.submissions });\n qc.invalidateQueries({ queryKey: KEY.submission(s.id) });\n },\n });\n};\n\n// ============================================================================\n// Enrollments & progress\n// ============================================================================\n\nexport interface UseBuiEnrollmentsArgs {\n courseId?: string;\n status?: BuiEnrollmentStatus;\n cursor?: string;\n limit?: number;\n enabled?: boolean;\n}\n\n/**\n * Workspace-wide enrollment list (instructor/admin). The backend dropped the\n * `learnerId` arg in the FERPA/IDOR hardening — a learner's OWN enrollments\n * come from the self-scoped `useBuiMyEnrollments` instead.\n */\nexport const useBuiEnrollments = (args: UseBuiEnrollmentsArgs = {}) => {\n const baseUrl = useGateway();\n const { courseId, status, cursor, limit, enabled = true } = args;\n return useQuery({\n queryKey: [...KEY.enrollments, { courseId, status, cursor, limit }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiListEnrollments: BuiConnection<BuiEnrollment> }>(\n `query BuiListEnrollments($courseId: ID, $status: BuiEnrollmentStatus, $pagination: PaginationInput) {\n buiListEnrollments(courseId: $courseId, status: $status, pagination: $pagination) {\n items { ${ENROLLMENT_FIELDS} cohort { ${COHORT_FIELDS} } }\n pageInfo { cursor hasMore }\n }\n }`,\n { courseId, status, pagination: pageVars(cursor, limit) },\n baseUrl\n );\n return data.buiListEnrollments;\n },\n });\n};\n\n/** The signed-in learner's own enrollments (self-scoped, no learnerId arg). */\nexport const useBuiMyEnrollments = (args: UseBuiEnrollmentsArgs = {}) => {\n const baseUrl = useGateway();\n const { courseId, status, cursor, limit, enabled = true } = args;\n return useQuery({\n queryKey: [...KEY.enrollments, 'mine', { courseId, status, cursor, limit }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiMyEnrollments: BuiConnection<BuiEnrollment> }>(\n `query BuiMyEnrollments($courseId: ID, $status: BuiEnrollmentStatus, $pagination: PaginationInput) {\n buiMyEnrollments(courseId: $courseId, status: $status, pagination: $pagination) {\n items { ${ENROLLMENT_FIELDS} cohort { ${COHORT_FIELDS} } }\n pageInfo { cursor hasMore }\n }\n }`,\n { courseId, status, pagination: pageVars(cursor, limit) },\n baseUrl\n );\n return data.buiMyEnrollments;\n },\n });\n};\n\nexport const useBuiEnrollment = (id: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: id ? KEY.enrollment(id) : ['buildmyiq', 'enrollment', 'nil'],\n enabled: Boolean(id),\n queryFn: async () => {\n const data = await buiQuery<{ buiEnrollment: BuiEnrollmentWire | null }>(\n `query BuiEnrollment($id: ID!) {\n buiEnrollment(id: $id) { ${ENROLLMENT_FULL_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiEnrollment ? flattenEnrollment(data.buiEnrollment) : null;\n },\n });\n};\n\n/**\n * The signed-in learner's OWN enrollment by id, with its full lesson-progress\n * history. Self-scoped (`buiMyEnrollment`) — the resolver owner-filters by the\n * authenticated actor and returns null for someone else's enrollment, so this\n * is the read a learner-facing surface must use; `useBuiEnrollment` above is\n * the workspace-scoped instructor/admin equivalent.\n */\nexport const useBuiMyEnrollment = (id: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n // Nested under KEY.enrollment(id) so the progress-recording invalidation\n // (which invalidates that prefix) refreshes this query too.\n queryKey: id ? [...KEY.enrollment(id), 'mine'] : ['buildmyiq', 'enrollment', 'nil', 'mine'],\n enabled: Boolean(id),\n queryFn: async () => {\n const data = await buiQuery<{ buiMyEnrollment: BuiEnrollmentWire | null }>(\n `query BuiMyEnrollment($id: ID!) {\n buiMyEnrollment(id: $id) { ${ENROLLMENT_FULL_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiMyEnrollment ? flattenEnrollment(data.buiMyEnrollment) : null;\n },\n });\n};\n\nexport const useBuiEnroll = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiEnrollInput) => {\n const data = await buiQuery<{ buiEnroll: BuiEnrollment }>(\n `mutation BuiEnroll($input: BuiEnrollInput!) {\n buiEnroll(input: $input) { ${ENROLLMENT_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiEnroll;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.enrollments }),\n });\n};\n\nexport const useBuiCompleteMyEnrollment = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (args: { id: string }) => {\n const data = await buiQuery<{ buiCompleteMyEnrollment: BuiEnrollment }>(\n `mutation BuiCompleteMyEnrollment($id: ID!) {\n buiCompleteMyEnrollment(id: $id) { ${ENROLLMENT_FIELDS} }\n }`,\n args,\n baseUrl\n );\n return data.buiCompleteMyEnrollment;\n },\n onSuccess: (e) => {\n qc.invalidateQueries({ queryKey: KEY.enrollments });\n qc.invalidateQueries({ queryKey: KEY.enrollment(e.id) });\n },\n });\n};\n\nexport const useBuiRecordMyLessonProgress = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiRecordLessonProgressInput) => {\n const data = await buiQuery<{ buiRecordMyLessonProgress: BuiLessonProgress }>(\n `mutation BuiRecordMyLessonProgress($input: BuiRecordLessonProgressInput!) {\n buiRecordMyLessonProgress(input: $input) { ${LESSON_PROGRESS_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiRecordMyLessonProgress;\n },\n onSuccess: (p) => {\n qc.invalidateQueries({ queryKey: KEY.enrollment(p.enrollmentId) });\n qc.invalidateQueries({ queryKey: KEY.enrollments });\n },\n });\n};\n\n// ============================================================================\n// Cohorts\n// ============================================================================\n\nexport const useBuiCohorts = (courseId?: string, status?: BuiCohortStatus) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: [...KEY.cohorts, { courseId, status }],\n queryFn: async () => {\n const data = await buiQuery<{ buiListCohorts: { items: BuiCohort[] } }>(\n `query BuiListCohorts($courseId: ID, $status: BuiCohortStatus) {\n buiListCohorts(courseId: $courseId, status: $status) { items { ${COHORT_FIELDS} } }\n }`,\n { courseId, status },\n baseUrl\n );\n return data.buiListCohorts.items;\n },\n });\n};\n\nexport const useBuiCreateCohort = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiCreateCohortInput) => {\n const data = await buiQuery<{ buiCreateCohort: BuiCohort }>(\n `mutation BuiCreateCohort($input: BuiCreateCohortInput!) {\n buiCreateCohort(input: $input) { ${COHORT_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiCreateCohort;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.cohorts }),\n });\n};\n\n// ============================================================================\n// Skills\n// ============================================================================\n\nexport const useBuiSkills = (category?: BuiSkillCategory) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: [...KEY.skills, { category }],\n queryFn: async () => {\n const data = await buiQuery<{ buiListSkills: { items: BuiSkill[] } }>(\n `query BuiListSkills($category: BuiSkillCategory) {\n buiListSkills(category: $category) { items { ${SKILL_FIELDS} } }\n }`,\n { category },\n baseUrl\n );\n return data.buiListSkills.items;\n },\n });\n};\n\nexport const useBuiCreateSkill = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiCreateSkillInput) => {\n const data = await buiQuery<{ buiCreateSkill: BuiSkill }>(\n `mutation BuiCreateSkill($input: BuiCreateSkillInput!) {\n buiCreateSkill(input: $input) { ${SKILL_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiCreateSkill;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.skills }),\n });\n};\n\nexport const useBuiSkillStandards = (\n source?: BuiSkillStandard['source'],\n category?: BuiSkillCategory,\n enabled = true\n) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: ['buildmyiq', 'skillStandards', { source, category }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiListSkillStandards: { items: BuiSkillStandard[] } }>(\n `query BuiListSkillStandards($source: BuiSkillStandardSource, $category: BuiSkillCategory) {\n buiListSkillStandards(source: $source, category: $category) { items { ${SKILL_STANDARD_FIELDS} } }\n }`,\n { source, category },\n baseUrl\n );\n return data.buiListSkillStandards.items;\n },\n });\n};\n\nexport const useBuiCertifications = (body?: BuiCertification['body'], enabled = true) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: ['buildmyiq', 'certifications', { body }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiListCertifications: { items: BuiCertification[] } }>(\n `query BuiListCertifications($body: BuiCertificationBody) {\n buiListCertifications(body: $body) { items { ${CERTIFICATION_FIELDS} } }\n }`,\n { body },\n baseUrl\n );\n return data.buiListCertifications.items;\n },\n });\n};\n\nexport const useBuiSuggestSkillMappings = (name: string, description?: string, enabled = true) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: ['buildmyiq', 'skillMappingSuggestions', { name, description }],\n enabled: enabled && name.trim().length > 0,\n queryFn: async () => {\n const data = await buiQuery<{ buiSuggestSkillMappings: BuiSkillMappingSuggestion[] }>(\n `query BuiSuggestSkillMappings($name: String!, $description: String, $limit: Int) {\n buiSuggestSkillMappings(name: $name, description: $description, limit: $limit) {\n skillStandard { ${SKILL_STANDARD_FIELDS} }\n confidence\n reason\n }\n }`,\n { name, description, limit: 5 },\n baseUrl\n );\n return data.buiSuggestSkillMappings;\n },\n });\n};\n\n// ============================================================================\n// Certificates\n// ============================================================================\n\n/**\n * Workspace-wide certificate list (instructor/admin). The backend dropped the\n * `learnerId` arg in the FERPA/IDOR hardening — a learner's OWN certificates\n * come from the self-scoped `useBuiMyCertificates` instead.\n */\nexport const useBuiCertificates = (courseId?: string, enabled = true) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: [...KEY.certificates, { courseId }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiListCertificates: { items: BuiCertificate[] } }>(\n `query BuiListCertificates($courseId: ID) {\n buiListCertificates(courseId: $courseId) { items { ${CERTIFICATE_FIELDS} } }\n }`,\n { courseId },\n baseUrl\n );\n return data.buiListCertificates.items;\n },\n });\n};\n\n/** The signed-in learner's own certificates (self-scoped, no learnerId arg). */\nexport const useBuiMyCertificates = (courseId?: string, enabled = true) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: [...KEY.certificates, 'mine', { courseId }],\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiMyCertificates: { items: BuiCertificate[] } }>(\n `query BuiMyCertificates($courseId: ID) {\n buiMyCertificates(courseId: $courseId) { items { ${CERTIFICATE_FIELDS} } }\n }`,\n { courseId },\n baseUrl\n );\n return data.buiMyCertificates.items;\n },\n });\n};\n\nexport const useBuiIssueCertificate = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiIssueCertificateInput) => {\n const data = await buiQuery<{ buiIssueCertificate: BuiCertificate }>(\n `mutation BuiIssueCertificate($input: BuiIssueCertificateInput!) {\n buiIssueCertificate(input: $input) { ${CERTIFICATE_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiIssueCertificate;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.certificates }),\n });\n};\n\nexport const useBuiRevokeCertificate = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await buiQuery<{ buiRevokeCertificate: BuiCertificate }>(\n `mutation BuiRevokeCertificate($id: ID!) {\n buiRevokeCertificate(id: $id) { ${CERTIFICATE_FIELDS} }\n }`,\n { id },\n baseUrl\n );\n return data.buiRevokeCertificate;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.certificates }),\n });\n};\n\n// ============================================================================\n// AI Tutor (BOFF-4426) — grounded lesson Q&A chat\n// ============================================================================\n\n/**\n * Which tutor the lesson player shows for an enrollment.\n * - `teacher`: an educator bound a course teacher (course assistant) to the\n * course, so the Fluidgrids workflow assistant answers from its knowledge base.\n * - `native`: no course teacher is bound, so the built-in grounded tutor\n * (`buiTutorAsk`) answers from the lesson content. This keeps a working tutor\n * on every course without per-course setup.\n */\nexport type BuiTutorMode = 'teacher' | 'native';\n\n/**\n * Resolves the tutor mode through the learner-scoped `buiMyCourseAssistantTarget`\n * query: it returns the course only when an enabled binding exists and fails\n * with FAILED_PRECONDITION otherwise. Any failure resolves to `native`, because\n * the native tutor enforces its own access checks and needs no binding.\n */\nexport const useBuiTutorMode = (enrollmentId: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery<BuiTutorMode>({\n queryKey: enrollmentId ? KEY.tutorMode(enrollmentId) : ['buildmyiq', 'tutorMode', 'nil'],\n enabled: Boolean(enrollmentId),\n staleTime: 60_000,\n queryFn: async () => {\n try {\n const response = await graphqlFetch<{\n buiMyCourseAssistantTarget: { courseId: string } | null;\n }>({\n gateway: 'workspace',\n baseUrl,\n query: `query BuiMyCourseAssistantTarget($enrollmentId: ID!) {\n buiMyCourseAssistantTarget(enrollmentId: $enrollmentId) { courseId }\n }`,\n variables: { enrollmentId },\n workspaceToken: true,\n });\n return response.data?.buiMyCourseAssistantTarget?.courseId ? 'teacher' : 'native';\n } catch (err) {\n if (import.meta.env.DEV)\n console.warn('[useBuiTutorMode] falling back to the native tutor', err);\n return 'native';\n }\n },\n });\n};\n\n/**\n * The calling learner's own tutor sessions for a lesson (Type-C self-scoped\n * query — no `learnerId` arg on the wire; identity comes from the\n * authenticated actor server-side). Sessions come back newest-first with\n * their full message history, so the panel can restore an in-progress\n * conversation on mount.\n */\nexport const useBuiMyTutorSessions = (lessonId: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: lessonId ? KEY.tutorSessions(lessonId) : ['buildmyiq', 'tutorSessions', 'nil'],\n enabled: Boolean(lessonId),\n queryFn: async () => {\n const data = await buiQuery<{ buiMyTutorSessions: { items: BuiTutorSession[] } }>(\n `query BuiMyTutorSessions($lessonId: ID) {\n buiMyTutorSessions(lessonId: $lessonId) { items { ${TUTOR_SESSION_FIELDS} } }\n }`,\n { lessonId },\n baseUrl\n );\n return data.buiMyTutorSessions.items;\n },\n });\n};\n\n/**\n * Ask the AI tutor a question about a lesson. Omit `sessionId` to start a\n * new session for that lesson; pass the current session's id to continue\n * the same conversation (multi-turn). Invalidates the lesson's tutor-session\n * query so the panel picks up the new USER + ASSISTANT turns.\n */\nexport const useBuiTutorAsk = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiTutorAskInput) => {\n const data = await buiQuery<{ buiTutorAsk: BuiTutorAskPayload }>(\n `mutation BuiTutorAsk($input: BuiTutorAskInput!) {\n buiTutorAsk(input: $input) {\n session { ${TUTOR_SESSION_FIELDS} }\n answer { ${TUTOR_MESSAGE_FIELDS} }\n }\n }`,\n { input },\n baseUrl\n );\n return data.buiTutorAsk;\n },\n // Returned so `mutateAsync` resolves only after the transcript is refetched,\n // which lets the panel drop its optimistic echo without a visible gap.\n onSuccess: (payload) =>\n qc.invalidateQueries({ queryKey: KEY.tutorSessions(payload.session.lessonId) }),\n });\n};\n\n// ============================================================================\n// Educator review of AI tutor answers (BOFF-9663)\n// ============================================================================\n\nexport interface UseBuiTutorReviewSessionsArgs {\n courseId?: string;\n lessonId?: string;\n cursor?: string;\n limit?: number;\n}\n\n/**\n * Workspace-wide tutor conversations for educator review\n * (`buiListTutorSessions`, EDITOR+ via `buildmyiq-tutor:list`), newest first,\n * with each answer's original text, current review and audit trail.\n */\nexport const useBuiTutorReviewSessions = (args: UseBuiTutorReviewSessionsArgs = {}) => {\n const baseUrl = useGateway();\n const { courseId, lessonId, cursor, limit } = args;\n return useQuery({\n queryKey: [...KEY.tutorReview, { courseId, lessonId, cursor, limit }],\n queryFn: async () => {\n const data = await buiQuery<{ buiListTutorSessions: BuiConnection<BuiTutorSession> }>(\n `query BuiListTutorSessions($courseId: ID, $lessonId: ID, $pagination: PaginationInput) {\n buiListTutorSessions(courseId: $courseId, lessonId: $lessonId, pagination: $pagination) {\n items {\n id workspaceId courseId lessonId learnerId createdAt updatedAt\n messages { ${TUTOR_REVIEW_MESSAGE_FIELDS} }\n }\n pageInfo { cursor hasMore }\n }\n }`,\n { courseId, lessonId, pagination: pageVars(cursor, limit) },\n baseUrl\n );\n return data.buiListTutorSessions;\n },\n });\n};\n\n/**\n * Annotate, correct, redact or clear one tutor answer\n * (`buiReviewTutorAnswer`, EDITOR+ via `buildmyiq-tutor:update`). Refetches the\n * review list and any open learner transcript so both show the new state.\n */\nexport const useBuiReviewTutorAnswer = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiReviewTutorAnswerInput) => {\n const data = await buiQuery<{ buiReviewTutorAnswer: BuiTutorMessage }>(\n `mutation BuiReviewTutorAnswer($input: BuiReviewTutorAnswerInput!) {\n buiReviewTutorAnswer(input: $input) { ${TUTOR_REVIEW_MESSAGE_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiReviewTutorAnswer;\n },\n onSuccess: () =>\n Promise.all([\n qc.invalidateQueries({ queryKey: KEY.tutorReview }),\n qc.invalidateQueries({ queryKey: ['buildmyiq', 'tutorSessions'] }),\n ]),\n });\n};\n\n// ============================================================================\n// AI grading assist + admin copilot + AI course builder (BOFF-3724/4429/4434)\n// ============================================================================\n\nconst GRADE_SUGGESTION_FIELDS = `\n id submissionId proposedScore\n perQuestionFeedback {\n questionId feedback suggestedPoints\n criterionScores { criterionId title maxPoints suggestedPoints comment }\n }\n rubricRefs confidence inputRefs outcome createdAt\n`;\n\n/**\n * Proposes an AI-assisted score for a submission's open-ended questions —\n * NEVER writes the submission itself. The caller reviews/edits the result\n * and still commits via `useBuiGradeSubmission`. Throws (honest fail-clear)\n * when the backend has no LLM provider configured or the assessment has no\n * open-ended questions.\n */\nexport const useBuiSuggestGrade = () => {\n const baseUrl = useGateway();\n return useMutation({\n mutationFn: async (submissionId: string) => {\n const data = await buiQuery<{ buiSuggestGrade: BuiGradeSuggestion }>(\n `mutation BuiSuggestGrade($submissionId: ID!) {\n buiSuggestGrade(submissionId: $submissionId) { ${GRADE_SUGGESTION_FIELDS} }\n }`,\n { submissionId },\n baseUrl\n );\n return data.buiSuggestGrade;\n },\n });\n};\n\n/** Records whether the educator accepted or rejected a grading suggestion (measurable acceptance rate). */\nexport const useBuiReviewGradeSuggestion = () => {\n const baseUrl = useGateway();\n return useMutation({\n mutationFn: async (args: { id: string; outcome: BuiAiSuggestionOutcome }) => {\n const data = await buiQuery<{ buiReviewGradeSuggestion: BuiGradeSuggestion }>(\n `mutation BuiReviewGradeSuggestion($id: ID!, $outcome: BuiAiSuggestionOutcome!) {\n buiReviewGradeSuggestion(id: $id, outcome: $outcome) { ${GRADE_SUGGESTION_FIELDS} }\n }`,\n args,\n baseUrl\n );\n return data.buiReviewGradeSuggestion;\n },\n });\n};\n\nconst NEXT_LESSON_SUGGESTION_FIELDS = `\n id enrollmentId lessonId lessonTitle moduleId moduleTitle\n rationale confidence pacingHint inputRefs outcome createdAt\n`;\n\n/**\n * Proposes the lesson the learner should take next in one of their own\n * enrollments — a deterministic curriculum-order \"resume where you left off\"\n * walk plus a pacing hint derived from their recent graded scores (not an LLM\n * call). It persists an auditable suggestion record but NEVER writes\n * `BuiLessonProgress` / `BuiEnrollment`, so acting on it is entirely the\n * learner's choice. Type-B self-scoped: `enrollmentId` is a client arg but the\n * resolver owner-filters by the authenticated actor.\n */\nexport const useBuiSuggestNextLesson = () => {\n const baseUrl = useGateway();\n return useMutation({\n mutationFn: async (enrollmentId: string) => {\n const data = await buiQuery<{ buiSuggestNextLesson: BuiNextLessonSuggestion }>(\n `mutation BuiSuggestNextLesson($enrollmentId: ID!) {\n buiSuggestNextLesson(enrollmentId: $enrollmentId) { ${NEXT_LESSON_SUGGESTION_FIELDS} }\n }`,\n { enrollmentId },\n baseUrl\n );\n return data.buiSuggestNextLesson;\n },\n });\n};\n\n/** Records whether the learner accepted or dismissed a next-lesson suggestion. */\nexport const useBuiReviewNextLessonSuggestion = () => {\n const baseUrl = useGateway();\n return useMutation({\n mutationFn: async (args: { id: string; outcome: BuiAiSuggestionOutcome }) => {\n const data = await buiQuery<{ buiReviewNextLessonSuggestion: BuiNextLessonSuggestion }>(\n `mutation BuiReviewNextLessonSuggestion($id: ID!, $outcome: BuiAiSuggestionOutcome!) {\n buiReviewNextLessonSuggestion(id: $id, outcome: $outcome) { ${NEXT_LESSON_SUGGESTION_FIELDS} }\n }`,\n args,\n baseUrl\n );\n return data.buiReviewNextLessonSuggestion;\n },\n });\n};\n\n/**\n * AI-drafted course outline from a topic — an EPHEMERAL suggestion (not\n * persisted server-side); the instructor reviews/edits it before\n * `useBuiApplyCourseOutline` creates anything real.\n */\nexport const useBuiSuggestCourseOutline = () => {\n const baseUrl = useGateway();\n return useMutation({\n mutationFn: async (args: {\n topic: string;\n audienceLevel?: string | null;\n moduleCount?: number | null;\n blockedTerms?: string[] | null;\n }) => {\n const data = await buiQuery<{ buiSuggestCourseOutline: BuiCourseOutlineSuggestion }>(\n `mutation BuiSuggestCourseOutline($topic: String!, $audienceLevel: String, $moduleCount: Int, $blockedTerms: [String!]) {\n buiSuggestCourseOutline(topic: $topic, audienceLevel: $audienceLevel, moduleCount: $moduleCount, blockedTerms: $blockedTerms) {\n rationale confidence\n modules { title description lessons { title description } }\n filteredOutCount blockedTermsMatched\n }\n }`,\n args,\n baseUrl\n );\n return data.buiSuggestCourseOutline;\n },\n });\n};\n\n/** Creates a real DRAFT course + modules + lessons from a (possibly-edited) AI outline. */\nexport const useBuiApplyCourseOutline = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiApplyCourseOutlineInput) => {\n const data = await buiQuery<{ buiApplyCourseOutline: BuiCourse }>(\n `mutation BuiApplyCourseOutline($input: BuiApplyCourseOutlineInput!) {\n buiApplyCourseOutline(input: $input) { ${COURSE_CORE_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiApplyCourseOutline;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.courses }),\n });\n};\n\n/**\n * AI assessment draft (BOFF-4434): questions grounded in the course (or one\n * lesson's) content. Ephemeral — nothing is written until\n * `useBuiApplyAssessmentDraft` runs on the educator-reviewed draft.\n */\nexport const useBuiSuggestAssessmentDraft = () => {\n const baseUrl = useGateway();\n return useMutation({\n mutationFn: async (input: BuiSuggestAssessmentDraftInput) => {\n const data = await buiQuery<{ buiSuggestAssessmentDraft: BuiAssessmentDraftSuggestion }>(\n `mutation BuiSuggestAssessmentDraft($input: BuiSuggestAssessmentDraftInput!) {\n buiSuggestAssessmentDraft(input: $input) {\n courseId lessonId rationale confidence\n questions { prompt type points options answerKey explanation confidence }\n filteredOutCount lowConfidenceFilteredCount discardedInvalidCount\n blockedTermsMatched groundingRefs\n }\n }`,\n { input },\n baseUrl\n );\n return data.buiSuggestAssessmentDraft;\n },\n });\n};\n\n/** Creates a DRAFT assessment + questions from a reviewed AI draft (BOFF-4434). */\nexport const useBuiApplyAssessmentDraft = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiApplyAssessmentDraftInput) => {\n const data = await buiQuery<{ buiApplyAssessmentDraft: BuiAssessment }>(\n `mutation BuiApplyAssessmentDraft($input: BuiApplyAssessmentDraftInput!) {\n buiApplyAssessmentDraft(input: $input) { ${ASSESSMENT_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiApplyAssessmentDraft;\n },\n onSuccess: (a) => qc.invalidateQueries({ queryKey: KEY.assessments(a.courseId) }),\n });\n};\n\n/**\n * Read-only admin Q&A grounded in real workspace stats — NEVER executes an\n * admin action. Stateless per call; the caller resends prior turns as\n * `history` for multi-turn context.\n */\nconst ADMIN_COPILOT_ACTION_FIELDS = `\n id kind status title rationale summary question\n courseId courseTitle cohortId cohortName sourceLabel\n affectedCount truncated reminderMessage inactiveDays statusFilter\n automationTemplate automationName automationEnabled automationWasEnabled automationConfig evidence\n result { enrolledCount skippedCount notifiedCount failedCount rowCount automationEnabled }\n errorMessage expiresAt createdAt createdBy confirmedBy confirmedAt executedAt dismissedAt\n`;\n\nexport const useBuiAdminCopilotAsk = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (args: { question: string; history: BuiAdminCopilotTurnInput[] }) => {\n const data = await buiQuery<{ buiAdminCopilotAsk: BuiAdminCopilotAnswer }>(\n `mutation BuiAdminCopilotAsk($question: String!, $history: [BuiAdminCopilotTurnInput!]) {\n buiAdminCopilotAsk(question: $question, history: $history) {\n answer contextCourseIds discardedActionCount generatedAt\n proposedActions { ${ADMIN_COPILOT_ACTION_FIELDS} }\n }\n }`,\n args,\n baseUrl\n );\n return data.buiAdminCopilotAsk;\n },\n onSuccess: (answer) => {\n if (answer.proposedActions.length > 0) {\n void qc.invalidateQueries({ queryKey: KEY.adminCopilotActions });\n }\n },\n });\n};\n\n/** The workspace's copilot proposals and their outcomes — the audit trail (BOFF-9687). */\nexport const useBuiAdminCopilotActions = (status?: BuiAdminCopilotActionStatus, limit = 20) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: [...KEY.adminCopilotActions, status ?? 'all', limit],\n queryFn: async () => {\n const data = await buiQuery<{ buiAdminCopilotActions: BuiAdminCopilotProposedAction[] }>(\n `query BuiAdminCopilotActions($status: BuiAdminCopilotActionStatus, $limit: Int) {\n buiAdminCopilotActions(status: $status, limit: $limit) { ${ADMIN_COPILOT_ACTION_FIELDS} }\n }`,\n status ? { status, limit } : { limit },\n baseUrl\n );\n return data.buiAdminCopilotActions;\n },\n });\n};\n\nconst EXECUTE_MUTATION_BY_KIND: Record<BuiAdminCopilotActionKind, string> = {\n ENROLL_LEARNERS: 'buiAdminCopilotExecuteEnrollAction',\n SEND_REMINDER: 'buiAdminCopilotExecuteReminderAction',\n EXPORT_REPORT: 'buiAdminCopilotExecuteReportAction',\n CONFIGURE_AUTOMATION: 'buiAdminCopilotExecuteAutomationAction',\n};\n\n/**\n * Confirm and run a proposed action. Each kind has its own mutation so the\n * gateway checks the permission that kind needs.\n */\nexport const useBuiAdminCopilotExecuteAction = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (args: { actionId: string; kind: BuiAdminCopilotActionKind }) => {\n const field = EXECUTE_MUTATION_BY_KIND[args.kind];\n const data = await buiQuery<Record<string, BuiAdminCopilotExecution>>(\n `mutation BuiAdminCopilotExecuteAction($actionId: ID!) {\n ${field}(actionId: $actionId) {\n reportCsv reportFileName\n action { ${ADMIN_COPILOT_ACTION_FIELDS} }\n }\n }`,\n { actionId: args.actionId },\n baseUrl\n );\n const execution = data[field];\n if (!execution) throw new Error('The action response was empty.');\n return execution;\n },\n onSuccess: (execution) => {\n void qc.invalidateQueries({ queryKey: KEY.adminCopilotActions });\n if (execution.action.kind === 'ENROLL_LEARNERS') {\n void qc.invalidateQueries({ queryKey: KEY.enrollments });\n }\n if (execution.action.kind === 'CONFIGURE_AUTOMATION') {\n void qc.invalidateQueries({ queryKey: KEY.automations });\n }\n },\n });\n};\n\nexport const useBuiAdminCopilotDismissAction = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (actionId: string) => {\n const data = await buiQuery<{ buiAdminCopilotDismissAction: BuiAdminCopilotProposedAction }>(\n `mutation BuiAdminCopilotDismissAction($actionId: ID!) {\n buiAdminCopilotDismissAction(actionId: $actionId) { ${ADMIN_COPILOT_ACTION_FIELDS} }\n }`,\n { actionId },\n baseUrl\n );\n return data.buiAdminCopilotDismissAction;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.adminCopilotActions }),\n });\n};\n\n// ============================================================================\n// LTI 1.3 Advantage — platform registry (BOFF-4419)\n// ============================================================================\n\nconst LTI_PLATFORM_FIELDS = `\n id workspaceId name issuer clientId deploymentIds\n authLoginUrl authTokenUrl keySetUrl active createdAt updatedAt\n`;\n\nexport const useBuiLtiPlatforms = () => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: KEY.ltiPlatforms,\n queryFn: async () => {\n const data = await buiQuery<{ buiLtiPlatforms: BuiLtiPlatform[] }>(\n `query BuiLtiPlatforms { buiLtiPlatforms { ${LTI_PLATFORM_FIELDS} } }`,\n {},\n baseUrl\n );\n return data.buiLtiPlatforms;\n },\n });\n};\n\nexport const useBuiRegisterLtiPlatform = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiRegisterLtiPlatformInput) => {\n const data = await buiQuery<{ buiRegisterLtiPlatform: BuiLtiPlatform }>(\n `mutation BuiRegisterLtiPlatform($input: BuiRegisterLtiPlatformInput!) {\n buiRegisterLtiPlatform(input: $input) { ${LTI_PLATFORM_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiRegisterLtiPlatform;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.ltiPlatforms }),\n });\n};\n\nexport const useBuiDeactivateLtiPlatform = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await buiQuery<{ buiDeactivateLtiPlatform: boolean }>(\n `mutation BuiDeactivateLtiPlatform($id: ID!) { buiDeactivateLtiPlatform(id: $id) }`,\n { id },\n baseUrl\n );\n return data.buiDeactivateLtiPlatform;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.ltiPlatforms }),\n });\n};\n\n// ============================================================================\n// LTI 1.3 Advantage — launch handoff, placements, grade and roster sync (BOFF-9680)\n// ============================================================================\n\nconst LTI_RESOURCE_LINK_FIELDS = `\n id workspaceId platformId deploymentId resourceLinkId contextId contextTitle\n assessmentId lineItemUrl nrpsUrl createdAt updatedAt\n`;\n\n/** LMS placements recorded by launches, optionally for one platform. */\nexport const useBuiLtiResourceLinks = (platformId?: string) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: [...KEY.ltiResourceLinks, { platformId: platformId ?? null }],\n queryFn: async () => {\n const data = await buiQuery<{ buiLtiResourceLinks: BuiLtiResourceLink[] }>(\n `query BuiLtiResourceLinks($platformId: ID) {\n buiLtiResourceLinks(platformId: $platformId) { ${LTI_RESOURCE_LINK_FIELDS} }\n }`,\n { platformId: platformId ?? null },\n baseUrl\n );\n return data.buiLtiResourceLinks;\n },\n });\n};\n\n/**\n * The pending launch an LMS just redirected the browser here with. `null`\n * means the ticket is unknown, expired, or belongs to another workspace.\n * Never refetched in the background: a ticket is single-purpose and short-lived.\n */\nexport const useBuiLtiLaunchContext = (ticketId: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: ['buildmyiq', 'ltiLaunchContext', ticketId ?? 'nil'],\n enabled: Boolean(ticketId),\n retry: false,\n staleTime: Infinity,\n refetchOnWindowFocus: false,\n queryFn: async () => {\n const data = await buiQuery<{ buiLtiLaunchContext: BuiLtiLaunchContext | null }>(\n `query BuiLtiLaunchContext($ticketId: ID!) {\n buiLtiLaunchContext(ticketId: $ticketId) {\n ticketId messageType platformId contextTitle assessmentId deepLinkAcceptTypes\n }\n }`,\n { ticketId },\n baseUrl\n );\n return data.buiLtiLaunchContext;\n },\n });\n};\n\n/** Resource-link launch: links the signed-in user to the LMS user and records the placement. */\nexport const useBuiCompleteLtiLink = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (ticketId: string) => {\n const data = await buiQuery<{ buiCompleteLtiLink: { resourceLink: BuiLtiResourceLink } }>(\n `mutation BuiCompleteLtiLink($ticketId: ID!) {\n buiCompleteLtiLink(ticketId: $ticketId) { resourceLink { ${LTI_RESOURCE_LINK_FIELDS} } }\n }`,\n { ticketId },\n baseUrl\n );\n return data.buiCompleteLtiLink.resourceLink;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.ltiResourceLinks }),\n });\n};\n\n/** Deep Linking: signs the response that places `assessmentId` in the LMS course. */\nexport const useBuiCompleteLtiDeepLink = () => {\n const baseUrl = useGateway();\n return useMutation({\n mutationFn: async (vars: { ticketId: string; assessmentId: string }) => {\n const data = await buiQuery<{ buiCompleteLtiDeepLink: BuiLtiDeepLinkResult }>(\n `mutation BuiCompleteLtiDeepLink($ticketId: ID!, $assessmentId: ID!) {\n buiCompleteLtiDeepLink(ticketId: $ticketId, assessmentId: $assessmentId) { jwt returnUrl }\n }`,\n vars,\n baseUrl\n );\n return data.buiCompleteLtiDeepLink;\n },\n });\n};\n\nconst LTI_GRADE_SYNC_FIELDS = `\n id resourceLinkId submissionId learnerId scoreGiven scoreMaximum status\n httpStatus errorMessage attemptedAt respondedAt\n`;\n\nexport const useBuiLtiGradeSyncs = (resourceLinkId: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: resourceLinkId\n ? KEY.ltiGradeSyncs(resourceLinkId)\n : ['buildmyiq', 'ltiGradeSyncs', 'nil'],\n enabled: Boolean(resourceLinkId),\n queryFn: async () => {\n const data = await buiQuery<{ buiLtiGradeSyncs: BuiLtiGradeSync[] }>(\n `query BuiLtiGradeSyncs($resourceLinkId: ID!) {\n buiLtiGradeSyncs(resourceLinkId: $resourceLinkId) { ${LTI_GRADE_SYNC_FIELDS} }\n }`,\n { resourceLinkId },\n baseUrl\n );\n return data.buiLtiGradeSyncs;\n },\n });\n};\n\n/** Publishes one graded submission's score to the LMS gradebook (AGS). */\nexport const useBuiSyncLtiGrade = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { resourceLinkId: string; submissionId: string }) => {\n const data = await buiQuery<{ buiSyncLtiGrade: BuiLtiGradeSync }>(\n `mutation BuiSyncLtiGrade($resourceLinkId: ID!, $submissionId: ID!) {\n buiSyncLtiGrade(resourceLinkId: $resourceLinkId, submissionId: $submissionId) { ${LTI_GRADE_SYNC_FIELDS} }\n }`,\n vars,\n baseUrl\n );\n return data.buiSyncLtiGrade;\n },\n // A failed publish is recorded too, so refresh the history either way.\n onSettled: (_data, _error, vars) =>\n qc.invalidateQueries({ queryKey: KEY.ltiGradeSyncs(vars.resourceLinkId) }),\n });\n};\n\nconst LTI_ROSTER_FIELDS = `id ltiSub email displayName roles status syncedAt`;\n\nexport const useBuiLtiRoster = (resourceLinkId: string | undefined) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: resourceLinkId ? KEY.ltiRoster(resourceLinkId) : ['buildmyiq', 'ltiRoster', 'nil'],\n enabled: Boolean(resourceLinkId),\n queryFn: async () => {\n const data = await buiQuery<{ buiLtiRoster: BuiLtiRosterMember[] }>(\n `query BuiLtiRoster($resourceLinkId: ID!) {\n buiLtiRoster(resourceLinkId: $resourceLinkId) { ${LTI_ROSTER_FIELDS} }\n }`,\n { resourceLinkId },\n baseUrl\n );\n return data.buiLtiRoster;\n },\n });\n};\n\n/** Pulls the course roster from the LMS (NRPS) and stores it. */\nexport const useBuiSyncLtiRoster = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (resourceLinkId: string) => {\n const data = await buiQuery<{ buiSyncLtiRoster: BuiLtiRosterMember[] }>(\n `mutation BuiSyncLtiRoster($resourceLinkId: ID!) {\n buiSyncLtiRoster(resourceLinkId: $resourceLinkId) { ${LTI_ROSTER_FIELDS} }\n }`,\n { resourceLinkId },\n baseUrl\n );\n return data.buiSyncLtiRoster;\n },\n onSuccess: (members, resourceLinkId) => qc.setQueryData(KEY.ltiRoster(resourceLinkId), members),\n });\n};\n\nexport interface BuiCourseAssistantSettings {\n enabled: boolean;\n agentId: string | null;\n candidates: Array<{ id: string; name: string }>;\n courseStatus: BuiCourseStatus;\n configured: boolean;\n ready: boolean;\n ingestionStatus: string;\n sourceCount: number;\n processedCount: number;\n}\nexport function useBuiCourseAssistantSettings(courseId: string) {\n const { workspaceId, currentUser, apiGatewayUrl } = useBuildmyiq();\n return useQuery({\n queryKey: ['buildmyiq', 'course-assistant-settings', workspaceId, currentUser?.id, courseId],\n enabled: Boolean(workspaceId && currentUser?.id && courseId),\n retry: false,\n refetchInterval: 15000,\n queryFn: async () => {\n const data = await buiQuery<{ buiCourseAssistantSettings: BuiCourseAssistantSettings }>(\n `query BuiCourseAssistantSettings($courseId: ID!) { buiCourseAssistantSettings(courseId: $courseId) {\n enabled agentId candidates { id name } courseStatus configured ready ingestionStatus sourceCount processedCount\n } }`,\n { courseId },\n apiGatewayUrl\n );\n return data.buiCourseAssistantSettings;\n },\n });\n}\nexport function useBuiSetCourseAssistant(courseId: string) {\n const { workspaceId, currentUser, apiGatewayUrl } = useBuildmyiq();\n const queries = useQueryClient();\n return useMutation({\n retry: false,\n mutationFn: async (agentId: string | null) => {\n if (agentId)\n await buiQuery(\n 'mutation BuiConfigureCourseAssistant($courseId: ID!, $agentId: ID!) { buiConfigureCourseAssistant(courseId: $courseId, agentId: $agentId) { id } }',\n { courseId, agentId },\n apiGatewayUrl\n );\n else\n await buiQuery(\n 'mutation BuiDisableCourseAssistant($courseId: ID!) { buiDisableCourseAssistant(courseId: $courseId) }',\n { courseId },\n apiGatewayUrl\n );\n },\n onSuccess: () =>\n queries.invalidateQueries({\n queryKey: [\n 'buildmyiq',\n 'course-assistant-settings',\n workspaceId,\n currentUser?.id,\n courseId,\n ],\n }),\n });\n}\n\nexport function useBuiCreateCourseTeacher(courseId: string, enabled: boolean) {\n const { workspaceId, currentUser, apiGatewayUrl } = useBuildmyiq();\n const queries = useQueryClient();\n const options = useQuery({\n queryKey: ['buildmyiq', 'teacher-setup-options', workspaceId, currentUser?.id],\n enabled: enabled && Boolean(workspaceId && currentUser?.id),\n retry: false,\n queryFn: async () => {\n const models: Array<{ id: string; name: string; modelId: string }> = [];\n for (let offset = 0; offset < 500; offset += 100) {\n const page = await buiQuery<{\n listLLMModels: Array<{ id: string; name: string; modelId: string }>;\n }>(\n 'query BuiTeacherModels($offset: Int!) { listLLMModels(filters: { isActive: true }, pagination: { limit: 100, offset: $offset }) { id name modelId } }',\n { offset },\n apiGatewayUrl\n );\n if (!Array.isArray(page.listLLMModels) || page.listLLMModels.length > 100)\n throw new Error('Models unavailable');\n models.push(...page.listLLMModels);\n if (page.listLLMModels.length < 100) break;\n if (offset === 400) throw new Error('Too many models');\n }\n const provider = await buiQuery<{ getProviderByKey: { id: string } | null }>(\n 'query BuiTeacherWorkflowProvider { getProviderByKey(key: \"botmanor-runtime\") { id } }',\n {},\n apiGatewayUrl\n );\n const connections: Array<{ id: string; name: string }> = [];\n if (provider.getProviderByKey) {\n for (let offset = 0; offset < 500; offset += 100) {\n const page = await buiQuery<{\n getConnections: {\n hasMore: boolean;\n items: Array<{\n id: string;\n name: string;\n workspaceId: string | null;\n status: string;\n provider: { key: string };\n authMethod: { authType: string; isEnabled: boolean; isConfigured: boolean } | null;\n }>;\n };\n }>(\n 'query BuiTeacherConnections($providerId: ID!, $offset: Int!) { getConnections(filter: { providerId: $providerId, status: ACTIVE }, pagination: { limit: 100, offset: $offset }) { hasMore items { id name workspaceId status provider { key } authMethod { authType isEnabled isConfigured } } } }',\n { providerId: provider.getProviderByKey.id, offset },\n apiGatewayUrl\n );\n if (!page.getConnections || page.getConnections.items.length > 100)\n throw new Error('Connections unavailable');\n for (const connection of page.getConnections.items)\n if (\n connection.workspaceId === workspaceId &&\n connection.status === 'ACTIVE' &&\n connection.provider.key === 'botmanor-runtime' &&\n connection.authMethod?.authType === 'WORKSPACE_APP_TOKEN' &&\n connection.authMethod.isConfigured &&\n connection.authMethod.isEnabled\n )\n connections.push({ id: connection.id, name: connection.name });\n if (!page.getConnections.hasMore) break;\n if (offset === 400) throw new Error('Too many connections');\n }\n }\n const embeddingNames = [\n 'amazon.titan-embed-text-v2:0',\n 'text-embedding-3-small',\n 'text-embedding-3-large',\n 'text-embedding-ada-002',\n ];\n return {\n embeddingModels: models.filter((model) => embeddingNames.includes(model.modelId)),\n chatModels: models.filter((model) => !embeddingNames.includes(model.modelId)),\n connections,\n };\n },\n });\n const create = useMutation({\n retry: false,\n mutationFn: async (selection: CourseTeacherSetupSelection) => {\n if (!workspaceId || !currentUser?.id) throw new Error('Sign in to set up the teacher');\n return provisionCourseTeacher(courseId, selection, (query, variables) =>\n buiQuery(query, variables, apiGatewayUrl)\n );\n },\n onSettled: () =>\n queries.invalidateQueries({\n queryKey: [\n 'buildmyiq',\n 'course-assistant-settings',\n workspaceId,\n currentUser?.id,\n courseId,\n ],\n }),\n });\n return { options, create };\n}\n\n// ============================================================================\n// L&D workflow automation via FluidGrids (BOFF-9688)\n// ============================================================================\n\nconst AUTOMATION_FIELDS = `\n id template name description triggerKind triggerDescription actionDescription enabled\n config defaultConfig workflowKey workflowVersion workflowDefinitionId\n lastRunAt lastRunStatus lastError updatedAt\n`;\n\nconst AUTOMATION_RUN_FIELDS = `\n id template triggerSource status fluidgridsRunId subject action result error createdAt completedAt\n`;\n\n/** Every automation template and its state in this workspace. */\nexport const useBuiAutomations = () => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: KEY.automations,\n queryFn: async () => {\n const data = await buiQuery<{ buiAutomations: BuiAutomation[] }>(\n `query BuiAutomations { buiAutomations { ${AUTOMATION_FIELDS} } }`,\n {},\n baseUrl\n );\n return data.buiAutomations;\n },\n });\n};\n\n/**\n * Recent automation runs, newest first. Polls while any run is still waiting\n * on FluidGrids so a \"Run now\" result appears without a reload.\n */\nexport const useBuiAutomationRuns = (template?: BuiAutomationTemplate, limit = 20) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: [...KEY.automationRuns, { template: template ?? null, limit }],\n queryFn: async () => {\n const data = await buiQuery<{\n buiAutomationRuns: {\n items: BuiAutomationRun[];\n pageInfo: { hasMore: boolean; cursor: string | null };\n };\n }>(\n `query BuiAutomationRuns($template: BuiAutomationTemplate, $pagination: PaginationInput) {\n buiAutomationRuns(template: $template, pagination: $pagination) {\n items { ${AUTOMATION_RUN_FIELDS} }\n pageInfo { hasMore cursor }\n }\n }`,\n { template: template ?? null, pagination: { limit } },\n baseUrl\n );\n return data.buiAutomationRuns;\n },\n refetchInterval: (query) =>\n query.state.data?.items.some((run) => run.status === 'PENDING' || run.status === 'APPLYING')\n ? 4000\n : false,\n });\n};\n\nexport const useBuiConfigureAutomation = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiConfigureAutomationInput) => {\n const data = await buiQuery<{ buiConfigureAutomation: BuiAutomation }>(\n `mutation BuiConfigureAutomation($input: BuiConfigureAutomationInput!) {\n buiConfigureAutomation(input: $input) { ${AUTOMATION_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiConfigureAutomation;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.automations }),\n });\n};\n\nexport const useBuiRunAutomationNow = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (template: BuiAutomationTemplate) => {\n const data = await buiQuery<{ buiRunAutomationNow: BuiAutomationRun }>(\n `mutation BuiRunAutomationNow($template: BuiAutomationTemplate!) {\n buiRunAutomationNow(template: $template) { ${AUTOMATION_RUN_FIELDS} }\n }`,\n { template },\n baseUrl\n );\n return data.buiRunAutomationNow;\n },\n onSuccess: () => {\n void qc.invalidateQueries({ queryKey: KEY.automationRuns });\n void qc.invalidateQueries({ queryKey: KEY.automations });\n },\n });\n};\n\n/** Set or clear an enrollment's due date (instructors/admins). */\nexport const useBuiSetEnrollmentDueDate = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (args: { id: string; dueAt: string | null }) => {\n const data = await buiQuery<{ buiSetEnrollmentDueDate: BuiEnrollment }>(\n `mutation BuiSetEnrollmentDueDate($id: ID!, $dueAt: DateTime) {\n buiSetEnrollmentDueDate(id: $id, dueAt: $dueAt) { ${ENROLLMENT_FIELDS} }\n }`,\n args,\n baseUrl\n );\n return data.buiSetEnrollmentDueDate;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.enrollments }),\n });\n};\n\n// ============================================================================\n// Workspace AI content controls (BOFF-9689)\n// ============================================================================\n\nconst AI_SETTINGS_FIELDS = `\n workspaceId blockedTerms applyToTutor maxBlockedTerms maxBlockedTermLength updatedAt updatedBy\n`;\n\n/**\n * The workspace's saved AI block-list. The server merges it into every AI\n * authoring call, so the dialogs only display it.\n */\nexport const useBuiAiSettings = (enabled = true) => {\n const baseUrl = useGateway();\n return useQuery({\n queryKey: KEY.aiSettings,\n enabled,\n queryFn: async () => {\n const data = await buiQuery<{ buiAiSettings: BuiAiSettings }>(\n `query BuiAiSettings { buiAiSettings { ${AI_SETTINGS_FIELDS} } }`,\n {},\n baseUrl\n );\n return data.buiAiSettings;\n },\n });\n};\n\n/** Save the workspace's AI content controls (admin only). */\nexport const useBuiUpdateAiSettings = () => {\n const baseUrl = useGateway();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: BuiUpdateAiSettingsInput) => {\n const data = await buiQuery<{ buiUpdateAiSettings: BuiAiSettings }>(\n `mutation BuiUpdateAiSettings($input: BuiUpdateAiSettingsInput!) {\n buiUpdateAiSettings(input: $input) { ${AI_SETTINGS_FIELDS} }\n }`,\n { input },\n baseUrl\n );\n return data.buiUpdateAiSettings;\n },\n onSuccess: (settings) => qc.setQueryData(KEY.aiSettings, settings),\n });\n};\n"],"mappings":"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"}
@@ -9,6 +9,8 @@ export interface AdminCopilotActionCardProps {
9
9
  onDismiss: (action: BuiAdminCopilotProposedAction) => void;
10
10
  /** Present once an executed report's CSV is available in this session. */
11
11
  onDownload?: () => void;
12
+ /** Opens BuildMyIQ > Automations (CONFIGURE_AUTOMATION cards). */
13
+ onOpenAutomations?: () => void;
12
14
  }
13
15
  export declare const AdminCopilotActionCard: FC<AdminCopilotActionCardProps>;
14
16
  //# sourceMappingURL=AdminCopilotActionCard.d.ts.map