@pie-players/pie-assessment-toolkit 0.3.47 → 0.3.48
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.
- package/dist/attempt/AssessmentSession.js +2 -1
- package/dist/attempt/AssessmentSession.js.map +1 -1
- package/dist/attempt/adapters/activity-to-test-attempt-session.js +12 -8
- package/dist/attempt/adapters/activity-to-test-attempt-session.js.map +1 -1
- package/dist/components/ItemToolBar.custom-element.js +56 -17
- package/dist/components/PieAssessmentToolkit.custom-element.js +84 -29
- package/dist/components/SectionToolBar.custom-element.js +55 -17
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/policy/core/pnp-policy-inputs.js +1 -2
- package/dist/policy/core/pnp-policy-inputs.js.map +1 -1
- package/dist/policy/core/provenance.js.map +1 -1
- package/dist/runtime/SectionRuntimeEngine.js +1 -1
- package/dist/runtime/SectionRuntimeEngine.js.map +1 -1
- package/dist/runtime/core/cohort.js.map +1 -1
- package/dist/runtime/core/engine-input.js.map +1 -1
- package/dist/runtime/core/engine-readiness.js.map +1 -1
- package/dist/runtime/core/engine-resolver.js.map +1 -1
- package/dist/runtime/core/engine-transition.js +1 -3
- package/dist/runtime/core/engine-transition.js.map +1 -1
- package/dist/runtime/registration-events.js.map +1 -1
- package/dist/runtime/session-event-emitter-policy.js.map +1 -1
- package/dist/services/HighlightCoordinator.js +2 -1
- package/dist/services/HighlightCoordinator.js.map +1 -1
- package/dist/services/I18nService.d.ts +1 -1
- package/dist/services/I18nService.js.map +1 -1
- package/dist/services/SSMLExtractor.js.map +1 -1
- package/dist/services/TTSService.js +5 -2
- package/dist/services/TTSService.js.map +1 -1
- package/dist/services/ThemeProvider.js.map +1 -1
- package/dist/services/ToolRegistry.d.ts +1 -1
- package/dist/services/ToolRegistry.js.map +1 -1
- package/dist/services/ToolkitCoordinator.js +21 -11
- package/dist/services/ToolkitCoordinator.js.map +1 -1
- package/dist/services/createDefaultToolRegistry.js +4 -2
- package/dist/services/createDefaultToolRegistry.js.map +1 -1
- package/dist/services/framework-error-bus.js.map +1 -1
- package/dist/services/framework-error.js.map +1 -1
- package/dist/services/interfaces.js.map +1 -1
- package/dist/services/section-controller-types.js.map +1 -1
- package/dist/services/tool-config-defaults.js +7 -1
- package/dist/services/tool-config-defaults.js.map +1 -1
- package/dist/services/tool-config-validation.js +3 -1
- package/dist/services/tool-config-validation.js.map +1 -1
- package/dist/services/tool-instance-id.js.map +1 -1
- package/dist/services/tool-providers/DesmosToolProvider.js.map +1 -1
- package/dist/services/tool-providers/TTSToolProvider.js.map +1 -1
- package/dist/services/toolbar-items.js.map +1 -1
- package/dist/services/tools-config-normalizer.js +1 -2
- package/dist/services/tools-config-normalizer.js.map +1 -1
- package/dist/services/tts/browser-provider.js +60 -18
- package/dist/services/tts/browser-provider.js.map +1 -1
- package/dist/services/tts/catalog-span-alignment.js +8 -3
- package/dist/services/tts/catalog-span-alignment.js.map +1 -1
- package/dist/services/tts/generated-speech/assemble-plan.js.map +1 -1
- package/dist/services/tts/generated-speech/index.d.ts +1 -1
- package/dist/services/tts/generated-speech/index.js +1 -1
- package/dist/services/tts/generated-speech/index.js.map +1 -1
- package/dist/services/tts/generated-speech/math-speech-cache.js +3 -1
- package/dist/services/tts/generated-speech/math-speech-cache.js.map +1 -1
- package/dist/services/tts/highlight-pipeline/boundary-normalizer.js.map +1 -1
- package/dist/services/tts/highlight-pipeline/create-highlight-plan.js.map +1 -1
- package/dist/services/tts/math-alignment/mathml-tokenizer.js.map +1 -1
- package/dist/services/tts/math-alignment/sequence-aligner.js.map +1 -1
- package/dist/services/tts/math-alignment/speech-tokenizer.js.map +1 -1
- package/dist/services/tts/math-aware-text-processing.js +6 -3
- package/dist/services/tts/math-aware-text-processing.js.map +1 -1
- package/dist/services/tts/math-speech.js +3 -1
- package/dist/services/tts/math-speech.js.map +1 -1
- package/dist/services/tts/visual-line-ranges.js.map +1 -1
- package/dist/services/tts-runtime-config.js +6 -2
- package/dist/services/tts-runtime-config.js.map +1 -1
- package/dist/tools/calculators/desmos-provider.js.map +1 -1
- package/dist/tools/default-tool-module-loaders.js.map +1 -1
- package/dist/tools/registrations/accessibility-tools.js.map +1 -1
- package/dist/tools/registrations/calculator.js +1 -1
- package/dist/tools/registrations/calculator.js.map +1 -1
- package/dist/tools/registrations/interaction-tools.js.map +1 -1
- package/dist/tools/registrations/measurement-tools.js.map +1 -1
- package/dist/tools/registrations/subject-specific-tools.js +1 -1
- package/dist/tools/registrations/subject-specific-tools.js.map +1 -1
- package/dist/tools/registrations/tts.js +4 -2
- package/dist/tools/registrations/tts.js.map +1 -1
- package/dist/tools/types.js.map +1 -1
- package/dist/tools/variant-resolver.js.map +1 -1
- package/package.json +7 -7
|
@@ -14,7 +14,8 @@ export function loadAssessmentSession(storage, assessmentAttemptSessionIdentifie
|
|
|
14
14
|
const parsed = JSON.parse(raw);
|
|
15
15
|
if (!parsed || parsed.version !== ASSESSMENT_SESSION_VERSION)
|
|
16
16
|
return null;
|
|
17
|
-
if (parsed.assessmentAttemptSessionIdentifier !==
|
|
17
|
+
if (parsed.assessmentAttemptSessionIdentifier !==
|
|
18
|
+
assessmentAttemptSessionIdentifier) {
|
|
18
19
|
return null;
|
|
19
20
|
}
|
|
20
21
|
return parsed;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssessmentSession.js","sourceRoot":"","sources":["../../src/attempt/AssessmentSession.ts"],"names":[],"mappings":"AAiCA,MAAM,0BAA0B,GAAG,CAAU,CAAC;AAC9C,MAAM,cAAc,GAAG,4BAA4B,CAAC;AAEpD,SAAS,MAAM;IACd,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC7C,kCAA0C;IAE1C,OAAO,GAAG,cAAc,GAAG,kCAAkC,EAAE,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,qBAAqB,CACpC,OAAoB,EACpB,kCAA0C;IAE1C,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAC1B,8BAA8B,CAAC,kCAAkC,CAAC,CAClE,CAAC;IACF,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAsB,CAAC;QACpD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,0BAA0B;YAAE,OAAO,IAAI,CAAC;QAC1E,IACC,MAAM,CAAC,kCAAkC,
|
|
1
|
+
{"version":3,"file":"AssessmentSession.js","sourceRoot":"","sources":["../../src/attempt/AssessmentSession.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SectionControllerSessionState } from \"../services/section-controller-types.js\";\nimport type { StorageLike } from \"./TestSession.js\";\n\nexport interface AssessmentSessionNavigationState {\n\tcurrentSectionIndex: number;\n\tvisitedSectionIdentifiers: string[];\n\tcurrentSectionIdentifier?: string;\n}\n\nexport interface AssessmentSessionRealization {\n\tseed: string;\n\tsectionIdentifiers: string[];\n}\n\nexport interface AssessmentSectionSessionState {\n\tsectionIdentifier: string;\n\tupdatedAt: string;\n\tsession: SectionControllerSessionState | null;\n}\n\nexport interface AssessmentSession {\n\tversion: 1;\n\tassessmentAttemptSessionIdentifier: string;\n\tassessmentId: string;\n\tstartedAt: string;\n\tupdatedAt: string;\n\tcompletedAt?: string;\n\tnavigationState: AssessmentSessionNavigationState;\n\trealization: AssessmentSessionRealization;\n\tsectionSessions: Record<string, AssessmentSectionSessionState>;\n\tcontextVariables?: Record<string, unknown>;\n}\n\nconst ASSESSMENT_SESSION_VERSION = 1 as const;\nconst STORAGE_PREFIX = \"pie:assessment-session:v1:\";\n\nfunction nowIso(): string {\n\treturn new Date().toISOString();\n}\n\nexport function getAssessmentSessionStorageKey(\n\tassessmentAttemptSessionIdentifier: string,\n): string {\n\treturn `${STORAGE_PREFIX}${assessmentAttemptSessionIdentifier}`;\n}\n\nexport function loadAssessmentSession(\n\tstorage: StorageLike,\n\tassessmentAttemptSessionIdentifier: string,\n): AssessmentSession | null {\n\tconst raw = storage.getItem(\n\t\tgetAssessmentSessionStorageKey(assessmentAttemptSessionIdentifier),\n\t);\n\tif (!raw) return null;\n\ttry {\n\t\tconst parsed = JSON.parse(raw) as AssessmentSession;\n\t\tif (!parsed || parsed.version !== ASSESSMENT_SESSION_VERSION) return null;\n\t\tif (\n\t\t\tparsed.assessmentAttemptSessionIdentifier !==\n\t\t\tassessmentAttemptSessionIdentifier\n\t\t) {\n\t\t\treturn null;\n\t\t}\n\t\treturn parsed;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function saveAssessmentSession(\n\tstorage: StorageLike,\n\tsession: AssessmentSession,\n): void {\n\tconst updated: AssessmentSession = {\n\t\t...session,\n\t\tupdatedAt: nowIso(),\n\t};\n\tstorage.setItem(\n\t\tgetAssessmentSessionStorageKey(session.assessmentAttemptSessionIdentifier),\n\t\tJSON.stringify(updated),\n\t);\n}\n\nexport function createNewAssessmentSession(args: {\n\tassessmentAttemptSessionIdentifier: string;\n\tassessmentId: string;\n\tseed: string;\n\tsectionIdentifiers: string[];\n}): AssessmentSession {\n\tconst startedAt = nowIso();\n\tconst initialSectionIdentifier = args.sectionIdentifiers[0];\n\treturn {\n\t\tversion: ASSESSMENT_SESSION_VERSION,\n\t\tassessmentAttemptSessionIdentifier: args.assessmentAttemptSessionIdentifier,\n\t\tassessmentId: args.assessmentId,\n\t\tstartedAt,\n\t\tupdatedAt: startedAt,\n\t\tnavigationState: {\n\t\t\tcurrentSectionIndex: 0,\n\t\t\tvisitedSectionIdentifiers: initialSectionIdentifier\n\t\t\t\t? [initialSectionIdentifier]\n\t\t\t\t: [],\n\t\t\tcurrentSectionIdentifier: initialSectionIdentifier,\n\t\t},\n\t\trealization: {\n\t\t\tseed: args.seed,\n\t\t\tsectionIdentifiers: args.sectionIdentifiers,\n\t\t},\n\t\tsectionSessions: {},\n\t};\n}\n\nexport function upsertSectionSession(\n\tsession: AssessmentSession,\n\targs: {\n\t\tsectionIdentifier: string;\n\t\tsectionSession: SectionControllerSessionState | null;\n\t},\n): AssessmentSession {\n\tif (!args.sectionIdentifier) return session;\n\tconst updatedAt = nowIso();\n\treturn {\n\t\t...session,\n\t\tupdatedAt,\n\t\tsectionSessions: {\n\t\t\t...session.sectionSessions,\n\t\t\t[args.sectionIdentifier]: {\n\t\t\t\tsectionIdentifier: args.sectionIdentifier,\n\t\t\t\tupdatedAt,\n\t\t\t\tsession: args.sectionSession,\n\t\t\t},\n\t\t},\n\t};\n}\n\nexport function setCurrentSectionPosition(\n\tsession: AssessmentSession,\n\targs: {\n\t\tcurrentSectionIndex: number;\n\t\tcurrentSectionIdentifier?: string;\n\t},\n): AssessmentSession {\n\tconst visited = new Set(\n\t\tsession.navigationState.visitedSectionIdentifiers || [],\n\t);\n\tif (args.currentSectionIdentifier) {\n\t\tvisited.add(args.currentSectionIdentifier);\n\t}\n\treturn {\n\t\t...session,\n\t\tnavigationState: {\n\t\t\t...session.navigationState,\n\t\t\tcurrentSectionIndex: args.currentSectionIndex,\n\t\t\tcurrentSectionIdentifier: args.currentSectionIdentifier,\n\t\t\tvisitedSectionIdentifiers: Array.from(visited),\n\t\t},\n\t};\n}\n"]}
|
|
@@ -2,10 +2,7 @@ function nowIso() {
|
|
|
2
2
|
return new Date().toISOString();
|
|
3
3
|
}
|
|
4
4
|
function getItemIdentifier(itemRef) {
|
|
5
|
-
return (itemRef.identifier ||
|
|
6
|
-
itemRef.item?.identifier ||
|
|
7
|
-
itemRef.item?.id ||
|
|
8
|
-
null);
|
|
5
|
+
return (itemRef.identifier || itemRef.item?.identifier || itemRef.item?.id || null);
|
|
9
6
|
}
|
|
10
7
|
function resolveItemIdentifiers(args) {
|
|
11
8
|
const refs = args.itemRefs || args.activityDefinition?.assessmentItemRefs || [];
|
|
@@ -39,7 +36,8 @@ function mapItemSessions(itemIdentifiers, backendItemSessions) {
|
|
|
39
36
|
if (!rawSession)
|
|
40
37
|
return acc;
|
|
41
38
|
const pieSessionId = typeof rawSession.id === "string" ? rawSession.id : undefined;
|
|
42
|
-
const attemptCount = typeof rawSession.attemptCount === "number" &&
|
|
39
|
+
const attemptCount = typeof rawSession.attemptCount === "number" &&
|
|
40
|
+
rawSession.attemptCount > 0
|
|
43
41
|
? rawSession.attemptCount
|
|
44
42
|
: pieSessionId
|
|
45
43
|
? 1
|
|
@@ -47,8 +45,12 @@ function mapItemSessions(itemIdentifiers, backendItemSessions) {
|
|
|
47
45
|
const isCompleted = typeof rawSession.isCompleted === "boolean"
|
|
48
46
|
? rawSession.isCompleted
|
|
49
47
|
: Boolean(rawSession.complete);
|
|
50
|
-
const startedAt = typeof rawSession.startedAt === "string"
|
|
51
|
-
|
|
48
|
+
const startedAt = typeof rawSession.startedAt === "string"
|
|
49
|
+
? rawSession.startedAt
|
|
50
|
+
: undefined;
|
|
51
|
+
const updatedAt = typeof rawSession.updatedAt === "string"
|
|
52
|
+
? rawSession.updatedAt
|
|
53
|
+
: undefined;
|
|
52
54
|
const completedAt = typeof rawSession.completedAt === "string"
|
|
53
55
|
? rawSession.completedAt
|
|
54
56
|
: undefined;
|
|
@@ -128,7 +130,9 @@ export function buildActivitySessionItemUpdate(testAttemptSession, itemIdentifie
|
|
|
128
130
|
visitedItemIdentifiers: [
|
|
129
131
|
...testAttemptSession.navigationState.visitedItemIdentifiers,
|
|
130
132
|
],
|
|
131
|
-
itemSessions: itemSession?.session
|
|
133
|
+
itemSessions: itemSession?.session
|
|
134
|
+
? { [itemIdentifier]: itemSession.session }
|
|
135
|
+
: {},
|
|
132
136
|
},
|
|
133
137
|
};
|
|
134
138
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity-to-test-attempt-session.js","sourceRoot":"","sources":["../../../src/attempt/adapters/activity-to-test-attempt-session.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tTestAttemptItemSession,\n\tTestAttemptSession,\n} from \"../TestSession.js\";\n\nexport interface PieBackendActivityItemRef {\n\tidentifier?: string;\n\titem?: {\n\t\tid?: string;\n\t\tidentifier?: string;\n\t};\n}\n\nexport interface PieBackendActivityDefinition {\n\tid?: string;\n\tidentifier?: string;\n\tassessmentId?: string;\n\tassessmentItemRefs?: PieBackendActivityItemRef[];\n}\n\nexport interface PieBackendActivitySession {\n\tid?: string;\n\tactivitySessionId?: string;\n\tstartedAt?: string;\n\tupdatedAt?: string;\n\tcompletedAt?: string;\n\tcurrentItemIndex?: number;\n\tcurrentSectionIdentifier?: string;\n\tvisitedItemIdentifiers?: string[];\n\titemSessions?: Record<string, unknown>;\n}\n\nexport interface MapActivityToTestAttemptSessionArgs {\n\tactivityDefinition?: PieBackendActivityDefinition | null;\n\tactivitySession?: PieBackendActivitySession | null;\n\titemRefs?: PieBackendActivityItemRef[];\n\titemSessionsByItemIdentifier?: Record<string, unknown>;\n\tassessmentId?: string;\n\ttestAttemptSessionIdentifier?: string;\n}\n\nexport interface ActivitySessionPatchPayload {\n\tactivitySession: {\n\t\tid: string;\n\t\tstartedAt?: string;\n\t\tupdatedAt?: string;\n\t\tcompletedAt?: string;\n\t\tcurrentItemIndex: number;\n\t\tcurrentSectionIdentifier?: string;\n\t\tvisitedItemIdentifiers: string[];\n\t\titemSessions: Record<string, unknown>;\n\t};\n}\n\nfunction nowIso(): string {\n\treturn new Date().toISOString();\n}\n\nfunction getItemIdentifier(itemRef: PieBackendActivityItemRef): string | null {\n\treturn (\n\t\titemRef.identifier ||\n\t\titemRef.item?.identifier ||\n\t\titemRef.item?.id ||\n\t\tnull\n\t);\n}\n\nfunction resolveItemIdentifiers(args: MapActivityToTestAttemptSessionArgs): string[] {\n\tconst refs = args.itemRefs || args.activityDefinition?.assessmentItemRefs || [];\n\tconst identifiers = refs\n\t\t.map((itemRef) => getItemIdentifier(itemRef))\n\t\t.filter((itemIdentifier): itemIdentifier is string => !!itemIdentifier);\n\treturn Array.from(new Set(identifiers));\n}\n\nfunction resolveAssessmentId(args: MapActivityToTestAttemptSessionArgs): string {\n\treturn (\n\t\targs.assessmentId ||\n\t\targs.activityDefinition?.assessmentId ||\n\t\targs.activityDefinition?.identifier ||\n\t\targs.activityDefinition?.id ||\n\t\t\"unknown-assessment\"\n\t);\n}\n\nfunction resolveTestAttemptSessionIdentifier(\n\targs: MapActivityToTestAttemptSessionArgs,\n\tassessmentId: string,\n): string {\n\treturn (\n\t\targs.testAttemptSessionIdentifier ||\n\t\targs.activitySession?.activitySessionId ||\n\t\targs.activitySession?.id ||\n\t\t`tas_${assessmentId}`\n\t);\n}\n\nfunction resolveBackendItemSessions(\n\targs: MapActivityToTestAttemptSessionArgs,\n): Record<string, unknown> {\n\treturn {\n\t\t...(args.activitySession?.itemSessions || {}),\n\t\t...(args.itemSessionsByItemIdentifier || {}),\n\t};\n}\n\nfunction mapItemSessions(\n\titemIdentifiers: string[],\n\tbackendItemSessions: Record<string, unknown>,\n): Record<string, TestAttemptItemSession> {\n\treturn itemIdentifiers.reduce<Record<string, TestAttemptItemSession>>(\n\t\t(acc, itemIdentifier) => {\n\t\t\tconst rawSession = backendItemSessions[itemIdentifier] as\n\t\t\t\t| Record<string, unknown>\n\t\t\t\t| undefined;\n\t\t\tif (!rawSession) return acc;\n\n\t\t\tconst pieSessionId =\n\t\t\t\ttypeof rawSession.id === \"string\" ? rawSession.id : undefined;\n\t\t\tconst attemptCount =\n\t\t\t\ttypeof rawSession.attemptCount === \"number\" && rawSession.attemptCount > 0\n\t\t\t\t\t? rawSession.attemptCount\n\t\t\t\t\t: pieSessionId\n\t\t\t\t\t\t? 1\n\t\t\t\t\t\t: 0;\n\t\t\tconst isCompleted =\n\t\t\t\ttypeof rawSession.isCompleted === \"boolean\"\n\t\t\t\t\t? rawSession.isCompleted\n\t\t\t\t\t: Boolean(rawSession.complete);\n\t\t\tconst startedAt =\n\t\t\t\ttypeof rawSession.startedAt === \"string\" ? rawSession.startedAt : undefined;\n\t\t\tconst updatedAt =\n\t\t\t\ttypeof rawSession.updatedAt === \"string\" ? rawSession.updatedAt : undefined;\n\t\t\tconst completedAt =\n\t\t\t\ttypeof rawSession.completedAt === \"string\"\n\t\t\t\t\t? rawSession.completedAt\n\t\t\t\t\t: undefined;\n\n\t\t\tacc[itemIdentifier] = {\n\t\t\t\titemIdentifier,\n\t\t\t\tpieSessionId,\n\t\t\t\tattemptCount,\n\t\t\t\tisCompleted,\n\t\t\t\tstartedAt,\n\t\t\t\tupdatedAt,\n\t\t\t\tcompletedAt,\n\t\t\t\tsession: rawSession,\n\t\t\t};\n\t\t\treturn acc;\n\t\t},\n\t\t{},\n\t);\n}\n\nexport function mapActivityToTestAttemptSession(\n\targs: MapActivityToTestAttemptSessionArgs,\n): TestAttemptSession {\n\tconst assessmentId = resolveAssessmentId(args);\n\tconst itemIdentifiers = resolveItemIdentifiers(args);\n\tconst testAttemptSessionIdentifier = resolveTestAttemptSessionIdentifier(\n\t\targs,\n\t\tassessmentId,\n\t);\n\tconst backendItemSessions = resolveBackendItemSessions(args);\n\tconst now = nowIso();\n\tconst startedAt = args.activitySession?.startedAt || now;\n\tconst updatedAt = args.activitySession?.updatedAt || startedAt;\n\n\treturn {\n\t\tversion: 1,\n\t\ttestAttemptSessionIdentifier,\n\t\tassessmentId,\n\t\tstartedAt,\n\t\tupdatedAt,\n\t\tcompletedAt: args.activitySession?.completedAt,\n\t\tnavigationState: {\n\t\t\tcurrentItemIndex: args.activitySession?.currentItemIndex ?? -1,\n\t\t\tvisitedItemIdentifiers: [\n\t\t\t\t...(args.activitySession?.visitedItemIdentifiers || []),\n\t\t\t],\n\t\t\tcurrentSectionIdentifier: args.activitySession?.currentSectionIdentifier,\n\t\t},\n\t\trealization: {\n\t\t\tseed: testAttemptSessionIdentifier,\n\t\t\titemIdentifiers,\n\t\t},\n\t\titemSessions: mapItemSessions(itemIdentifiers, backendItemSessions),\n\t};\n}\n\nexport function toItemSessionsRecord(\n\ttestAttemptSession: TestAttemptSession,\n): Record<string, unknown> {\n\treturn Object.entries(testAttemptSession.itemSessions).reduce<\n\t\tRecord<string, unknown>\n\t>((acc, [itemIdentifier, itemSession]) => {\n\t\tif (itemSession.session) {\n\t\t\tacc[itemIdentifier] = itemSession.session;\n\t\t}\n\t\treturn acc;\n\t}, {});\n}\n\nexport function buildActivitySessionPatchFromTestAttemptSession(\n\ttestAttemptSession: TestAttemptSession,\n): ActivitySessionPatchPayload {\n\treturn {\n\t\tactivitySession: {\n\t\t\tid: testAttemptSession.testAttemptSessionIdentifier,\n\t\t\tstartedAt: testAttemptSession.startedAt,\n\t\t\tupdatedAt: testAttemptSession.updatedAt,\n\t\t\tcompletedAt: testAttemptSession.completedAt,\n\t\t\tcurrentItemIndex: testAttemptSession.navigationState.currentItemIndex,\n\t\t\tcurrentSectionIdentifier:\n\t\t\t\ttestAttemptSession.navigationState.currentSectionIdentifier,\n\t\t\tvisitedItemIdentifiers: [\n\t\t\t\t...testAttemptSession.navigationState.visitedItemIdentifiers,\n\t\t\t],\n\t\t\titemSessions: toItemSessionsRecord(testAttemptSession),\n\t\t},\n\t};\n}\n\nexport function buildActivitySessionItemUpdate(\n\ttestAttemptSession: TestAttemptSession,\n\titemIdentifier: string,\n): ActivitySessionPatchPayload {\n\tconst itemSession = testAttemptSession.itemSessions[itemIdentifier];\n\treturn {\n\t\tactivitySession: {\n\t\t\tid: testAttemptSession.testAttemptSessionIdentifier,\n\t\t\tcurrentItemIndex: testAttemptSession.navigationState.currentItemIndex,\n\t\t\tcurrentSectionIdentifier:\n\t\t\t\ttestAttemptSession.navigationState.currentSectionIdentifier,\n\t\t\tvisitedItemIdentifiers: [\n\t\t\t\t...testAttemptSession.navigationState.visitedItemIdentifiers,\n\t\t\t],\n\t\t\titemSessions: itemSession?.session ? { [itemIdentifier]: itemSession.session } : {},\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"activity-to-test-attempt-session.js","sourceRoot":"","sources":["../../../src/attempt/adapters/activity-to-test-attempt-session.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tTestAttemptItemSession,\n\tTestAttemptSession,\n} from \"../TestSession.js\";\n\nexport interface PieBackendActivityItemRef {\n\tidentifier?: string;\n\titem?: {\n\t\tid?: string;\n\t\tidentifier?: string;\n\t};\n}\n\nexport interface PieBackendActivityDefinition {\n\tid?: string;\n\tidentifier?: string;\n\tassessmentId?: string;\n\tassessmentItemRefs?: PieBackendActivityItemRef[];\n}\n\nexport interface PieBackendActivitySession {\n\tid?: string;\n\tactivitySessionId?: string;\n\tstartedAt?: string;\n\tupdatedAt?: string;\n\tcompletedAt?: string;\n\tcurrentItemIndex?: number;\n\tcurrentSectionIdentifier?: string;\n\tvisitedItemIdentifiers?: string[];\n\titemSessions?: Record<string, unknown>;\n}\n\nexport interface MapActivityToTestAttemptSessionArgs {\n\tactivityDefinition?: PieBackendActivityDefinition | null;\n\tactivitySession?: PieBackendActivitySession | null;\n\titemRefs?: PieBackendActivityItemRef[];\n\titemSessionsByItemIdentifier?: Record<string, unknown>;\n\tassessmentId?: string;\n\ttestAttemptSessionIdentifier?: string;\n}\n\nexport interface ActivitySessionPatchPayload {\n\tactivitySession: {\n\t\tid: string;\n\t\tstartedAt?: string;\n\t\tupdatedAt?: string;\n\t\tcompletedAt?: string;\n\t\tcurrentItemIndex: number;\n\t\tcurrentSectionIdentifier?: string;\n\t\tvisitedItemIdentifiers: string[];\n\t\titemSessions: Record<string, unknown>;\n\t};\n}\n\nfunction nowIso(): string {\n\treturn new Date().toISOString();\n}\n\nfunction getItemIdentifier(itemRef: PieBackendActivityItemRef): string | null {\n\treturn (\n\t\titemRef.identifier || itemRef.item?.identifier || itemRef.item?.id || null\n\t);\n}\n\nfunction resolveItemIdentifiers(\n\targs: MapActivityToTestAttemptSessionArgs,\n): string[] {\n\tconst refs =\n\t\targs.itemRefs || args.activityDefinition?.assessmentItemRefs || [];\n\tconst identifiers = refs\n\t\t.map((itemRef) => getItemIdentifier(itemRef))\n\t\t.filter((itemIdentifier): itemIdentifier is string => !!itemIdentifier);\n\treturn Array.from(new Set(identifiers));\n}\n\nfunction resolveAssessmentId(\n\targs: MapActivityToTestAttemptSessionArgs,\n): string {\n\treturn (\n\t\targs.assessmentId ||\n\t\targs.activityDefinition?.assessmentId ||\n\t\targs.activityDefinition?.identifier ||\n\t\targs.activityDefinition?.id ||\n\t\t\"unknown-assessment\"\n\t);\n}\n\nfunction resolveTestAttemptSessionIdentifier(\n\targs: MapActivityToTestAttemptSessionArgs,\n\tassessmentId: string,\n): string {\n\treturn (\n\t\targs.testAttemptSessionIdentifier ||\n\t\targs.activitySession?.activitySessionId ||\n\t\targs.activitySession?.id ||\n\t\t`tas_${assessmentId}`\n\t);\n}\n\nfunction resolveBackendItemSessions(\n\targs: MapActivityToTestAttemptSessionArgs,\n): Record<string, unknown> {\n\treturn {\n\t\t...(args.activitySession?.itemSessions || {}),\n\t\t...(args.itemSessionsByItemIdentifier || {}),\n\t};\n}\n\nfunction mapItemSessions(\n\titemIdentifiers: string[],\n\tbackendItemSessions: Record<string, unknown>,\n): Record<string, TestAttemptItemSession> {\n\treturn itemIdentifiers.reduce<Record<string, TestAttemptItemSession>>(\n\t\t(acc, itemIdentifier) => {\n\t\t\tconst rawSession = backendItemSessions[itemIdentifier] as\n\t\t\t\t| Record<string, unknown>\n\t\t\t\t| undefined;\n\t\t\tif (!rawSession) return acc;\n\n\t\t\tconst pieSessionId =\n\t\t\t\ttypeof rawSession.id === \"string\" ? rawSession.id : undefined;\n\t\t\tconst attemptCount =\n\t\t\t\ttypeof rawSession.attemptCount === \"number\" &&\n\t\t\t\trawSession.attemptCount > 0\n\t\t\t\t\t? rawSession.attemptCount\n\t\t\t\t\t: pieSessionId\n\t\t\t\t\t\t? 1\n\t\t\t\t\t\t: 0;\n\t\t\tconst isCompleted =\n\t\t\t\ttypeof rawSession.isCompleted === \"boolean\"\n\t\t\t\t\t? rawSession.isCompleted\n\t\t\t\t\t: Boolean(rawSession.complete);\n\t\t\tconst startedAt =\n\t\t\t\ttypeof rawSession.startedAt === \"string\"\n\t\t\t\t\t? rawSession.startedAt\n\t\t\t\t\t: undefined;\n\t\t\tconst updatedAt =\n\t\t\t\ttypeof rawSession.updatedAt === \"string\"\n\t\t\t\t\t? rawSession.updatedAt\n\t\t\t\t\t: undefined;\n\t\t\tconst completedAt =\n\t\t\t\ttypeof rawSession.completedAt === \"string\"\n\t\t\t\t\t? rawSession.completedAt\n\t\t\t\t\t: undefined;\n\n\t\t\tacc[itemIdentifier] = {\n\t\t\t\titemIdentifier,\n\t\t\t\tpieSessionId,\n\t\t\t\tattemptCount,\n\t\t\t\tisCompleted,\n\t\t\t\tstartedAt,\n\t\t\t\tupdatedAt,\n\t\t\t\tcompletedAt,\n\t\t\t\tsession: rawSession,\n\t\t\t};\n\t\t\treturn acc;\n\t\t},\n\t\t{},\n\t);\n}\n\nexport function mapActivityToTestAttemptSession(\n\targs: MapActivityToTestAttemptSessionArgs,\n): TestAttemptSession {\n\tconst assessmentId = resolveAssessmentId(args);\n\tconst itemIdentifiers = resolveItemIdentifiers(args);\n\tconst testAttemptSessionIdentifier = resolveTestAttemptSessionIdentifier(\n\t\targs,\n\t\tassessmentId,\n\t);\n\tconst backendItemSessions = resolveBackendItemSessions(args);\n\tconst now = nowIso();\n\tconst startedAt = args.activitySession?.startedAt || now;\n\tconst updatedAt = args.activitySession?.updatedAt || startedAt;\n\n\treturn {\n\t\tversion: 1,\n\t\ttestAttemptSessionIdentifier,\n\t\tassessmentId,\n\t\tstartedAt,\n\t\tupdatedAt,\n\t\tcompletedAt: args.activitySession?.completedAt,\n\t\tnavigationState: {\n\t\t\tcurrentItemIndex: args.activitySession?.currentItemIndex ?? -1,\n\t\t\tvisitedItemIdentifiers: [\n\t\t\t\t...(args.activitySession?.visitedItemIdentifiers || []),\n\t\t\t],\n\t\t\tcurrentSectionIdentifier: args.activitySession?.currentSectionIdentifier,\n\t\t},\n\t\trealization: {\n\t\t\tseed: testAttemptSessionIdentifier,\n\t\t\titemIdentifiers,\n\t\t},\n\t\titemSessions: mapItemSessions(itemIdentifiers, backendItemSessions),\n\t};\n}\n\nexport function toItemSessionsRecord(\n\ttestAttemptSession: TestAttemptSession,\n): Record<string, unknown> {\n\treturn Object.entries(testAttemptSession.itemSessions).reduce<\n\t\tRecord<string, unknown>\n\t>((acc, [itemIdentifier, itemSession]) => {\n\t\tif (itemSession.session) {\n\t\t\tacc[itemIdentifier] = itemSession.session;\n\t\t}\n\t\treturn acc;\n\t}, {});\n}\n\nexport function buildActivitySessionPatchFromTestAttemptSession(\n\ttestAttemptSession: TestAttemptSession,\n): ActivitySessionPatchPayload {\n\treturn {\n\t\tactivitySession: {\n\t\t\tid: testAttemptSession.testAttemptSessionIdentifier,\n\t\t\tstartedAt: testAttemptSession.startedAt,\n\t\t\tupdatedAt: testAttemptSession.updatedAt,\n\t\t\tcompletedAt: testAttemptSession.completedAt,\n\t\t\tcurrentItemIndex: testAttemptSession.navigationState.currentItemIndex,\n\t\t\tcurrentSectionIdentifier:\n\t\t\t\ttestAttemptSession.navigationState.currentSectionIdentifier,\n\t\t\tvisitedItemIdentifiers: [\n\t\t\t\t...testAttemptSession.navigationState.visitedItemIdentifiers,\n\t\t\t],\n\t\t\titemSessions: toItemSessionsRecord(testAttemptSession),\n\t\t},\n\t};\n}\n\nexport function buildActivitySessionItemUpdate(\n\ttestAttemptSession: TestAttemptSession,\n\titemIdentifier: string,\n): ActivitySessionPatchPayload {\n\tconst itemSession = testAttemptSession.itemSessions[itemIdentifier];\n\treturn {\n\t\tactivitySession: {\n\t\t\tid: testAttemptSession.testAttemptSessionIdentifier,\n\t\t\tcurrentItemIndex: testAttemptSession.navigationState.currentItemIndex,\n\t\t\tcurrentSectionIdentifier:\n\t\t\t\ttestAttemptSession.navigationState.currentSectionIdentifier,\n\t\t\tvisitedItemIdentifiers: [\n\t\t\t\t...testAttemptSession.navigationState.visitedItemIdentifiers,\n\t\t\t],\n\t\t\titemSessions: itemSession?.session\n\t\t\t\t? { [itemIdentifier]: itemSession.session }\n\t\t\t\t: {},\n\t\t},\n\t};\n}\n"]}
|
|
@@ -6223,6 +6223,39 @@ var segmentSentences = (text2, options) => {
|
|
|
6223
6223
|
};
|
|
6224
6224
|
|
|
6225
6225
|
// dist/services/tts/browser-provider.js
|
|
6226
|
+
var normalizeLanguageCode = (value) => String(value || "").trim().toLowerCase();
|
|
6227
|
+
var browserLanguage = () => {
|
|
6228
|
+
const navigatorLanguage = typeof navigator !== "undefined" ? navigator.language || navigator.languages?.[0] : "";
|
|
6229
|
+
return normalizeLanguageCode(navigatorLanguage || "en-US");
|
|
6230
|
+
};
|
|
6231
|
+
var findBrowserVoice = (voices, preferredName) => {
|
|
6232
|
+
if (preferredName) {
|
|
6233
|
+
const explicit = voices.find((voice) => voice.name === preferredName);
|
|
6234
|
+
if (explicit)
|
|
6235
|
+
return explicit;
|
|
6236
|
+
}
|
|
6237
|
+
const language = browserLanguage();
|
|
6238
|
+
const languagePrefix = language.split("-")[0] || "en";
|
|
6239
|
+
const matchesLanguage = (voice) => {
|
|
6240
|
+
const voiceLanguage = normalizeLanguageCode(voice.lang);
|
|
6241
|
+
return voiceLanguage === language || voiceLanguage.startsWith(`${languagePrefix}-`);
|
|
6242
|
+
};
|
|
6243
|
+
const ranked = [
|
|
6244
|
+
(voice) => voice.localService && matchesLanguage(voice),
|
|
6245
|
+
(voice) => voice.default && matchesLanguage(voice),
|
|
6246
|
+
(voice) => matchesLanguage(voice),
|
|
6247
|
+
(voice) => voice.localService,
|
|
6248
|
+
(voice) => voice.default
|
|
6249
|
+
];
|
|
6250
|
+
for (const predicate of ranked) {
|
|
6251
|
+
const voice = voices.find(predicate);
|
|
6252
|
+
if (voice)
|
|
6253
|
+
return voice;
|
|
6254
|
+
}
|
|
6255
|
+
return voices[0] || null;
|
|
6256
|
+
};
|
|
6257
|
+
var shouldAssignBrowserVoice = (voice) => !voice.default;
|
|
6258
|
+
|
|
6226
6259
|
class BrowserTTSProvider {
|
|
6227
6260
|
providerId = "browser";
|
|
6228
6261
|
providerName = "Browser Speech Synthesis";
|
|
@@ -6377,24 +6410,28 @@ class BrowserTTSProviderImpl {
|
|
|
6377
6410
|
resolve(false);
|
|
6378
6411
|
return;
|
|
6379
6412
|
}
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
this.utterance.voice = voice;
|
|
6386
|
-
}
|
|
6413
|
+
const utterance = new SpeechSynthesisUtterance(chunkText);
|
|
6414
|
+
this.utterance = utterance;
|
|
6415
|
+
const voice = findBrowserVoice(speechSynthesis.getVoices(), this.config?.voice);
|
|
6416
|
+
if (voice && shouldAssignBrowserVoice(voice))
|
|
6417
|
+
utterance.voice = voice;
|
|
6387
6418
|
if (this.config?.rate)
|
|
6388
|
-
|
|
6419
|
+
utterance.rate = this.config.rate;
|
|
6389
6420
|
if (this.config?.pitch)
|
|
6390
|
-
|
|
6391
|
-
|
|
6421
|
+
utterance.pitch = this.config.pitch;
|
|
6422
|
+
const clearOwnedUtterance = () => {
|
|
6423
|
+
if (this.utterance === utterance) {
|
|
6424
|
+
this.utterance = null;
|
|
6425
|
+
}
|
|
6426
|
+
};
|
|
6427
|
+
utterance.onstart = () => {
|
|
6392
6428
|
if (runId !== this.speakRunId)
|
|
6393
6429
|
return;
|
|
6394
6430
|
this._isPlaying = true;
|
|
6395
6431
|
this._isPaused = false;
|
|
6396
6432
|
};
|
|
6397
|
-
|
|
6433
|
+
utterance.onend = () => {
|
|
6434
|
+
clearOwnedUtterance();
|
|
6398
6435
|
if (runId !== this.speakRunId) {
|
|
6399
6436
|
resolve(false);
|
|
6400
6437
|
return;
|
|
@@ -6403,7 +6440,8 @@ class BrowserTTSProviderImpl {
|
|
|
6403
6440
|
this._isPaused = false;
|
|
6404
6441
|
resolve(true);
|
|
6405
6442
|
};
|
|
6406
|
-
|
|
6443
|
+
utterance.onerror = (event2) => {
|
|
6444
|
+
clearOwnedUtterance();
|
|
6407
6445
|
if (runId !== this.speakRunId) {
|
|
6408
6446
|
resolve(false);
|
|
6409
6447
|
return;
|
|
@@ -6416,17 +6454,17 @@ class BrowserTTSProviderImpl {
|
|
|
6416
6454
|
}
|
|
6417
6455
|
reject(new Error(`Speech synthesis error: ${event2.error}`));
|
|
6418
6456
|
};
|
|
6419
|
-
|
|
6457
|
+
utterance.onpause = () => {
|
|
6420
6458
|
if (runId !== this.speakRunId)
|
|
6421
6459
|
return;
|
|
6422
6460
|
this._isPaused = true;
|
|
6423
6461
|
};
|
|
6424
|
-
|
|
6462
|
+
utterance.onresume = () => {
|
|
6425
6463
|
if (runId !== this.speakRunId)
|
|
6426
6464
|
return;
|
|
6427
6465
|
this._isPaused = false;
|
|
6428
6466
|
};
|
|
6429
|
-
|
|
6467
|
+
utterance.onboundary = (event2) => {
|
|
6430
6468
|
if (runId !== this.speakRunId)
|
|
6431
6469
|
return;
|
|
6432
6470
|
console.log("[BrowserProvider] Boundary event:", event2.name, "charIndex:", event2.charIndex, "charLength:", event2.charLength);
|
|
@@ -6444,7 +6482,7 @@ class BrowserTTSProviderImpl {
|
|
|
6444
6482
|
console.log("[BrowserProvider] Calling onWordBoundary with word:", word, "at position:", absoluteBoundaryStart);
|
|
6445
6483
|
this.onWordBoundary(word, absoluteBoundaryStart, wordLength);
|
|
6446
6484
|
};
|
|
6447
|
-
speechSynthesis.speak(
|
|
6485
|
+
speechSynthesis.speak(utterance);
|
|
6448
6486
|
});
|
|
6449
6487
|
}
|
|
6450
6488
|
pause() {
|
|
@@ -6459,9 +6497,10 @@ class BrowserTTSProviderImpl {
|
|
|
6459
6497
|
}
|
|
6460
6498
|
stop() {
|
|
6461
6499
|
this.speakRunId += 1;
|
|
6462
|
-
if (this._isPlaying) {
|
|
6500
|
+
if (this._isPlaying || this.utterance) {
|
|
6463
6501
|
speechSynthesis.cancel();
|
|
6464
6502
|
}
|
|
6503
|
+
this.utterance = null;
|
|
6465
6504
|
this._isPlaying = false;
|
|
6466
6505
|
this._isPaused = false;
|
|
6467
6506
|
}
|
|
@@ -39,7 +39,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
39
39
|
|
|
40
40
|
// ../../node_modules/.bun/speech-rule-engine@5.0.0-rc.1/node_modules/speech-rule-engine/lib/sre.js
|
|
41
41
|
var require_sre = __commonJS((exports, module) => {
|
|
42
|
-
var __dirname = "/
|
|
42
|
+
var __dirname = "/Users/eelco.hillenius/dev/prj/pie/pie-players/node_modules/.bun/speech-rule-engine@5.0.0-rc.1/node_modules/speech-rule-engine/lib";
|
|
43
43
|
(function(t, e) {
|
|
44
44
|
typeof exports == "object" && typeof module == "object" ? module.exports = e() : typeof define == "function" && define.amd ? define([], e) : typeof exports == "object" ? exports.SRE = e() : t.SRE = e();
|
|
45
45
|
})(exports, () => (() => {
|
|
@@ -18080,6 +18080,39 @@ var segmentSentences = (text2, options) => {
|
|
|
18080
18080
|
};
|
|
18081
18081
|
|
|
18082
18082
|
// dist/services/tts/browser-provider.js
|
|
18083
|
+
var normalizeLanguageCode = (value) => String(value || "").trim().toLowerCase();
|
|
18084
|
+
var browserLanguage = () => {
|
|
18085
|
+
const navigatorLanguage = typeof navigator !== "undefined" ? navigator.language || navigator.languages?.[0] : "";
|
|
18086
|
+
return normalizeLanguageCode(navigatorLanguage || "en-US");
|
|
18087
|
+
};
|
|
18088
|
+
var findBrowserVoice = (voices, preferredName) => {
|
|
18089
|
+
if (preferredName) {
|
|
18090
|
+
const explicit = voices.find((voice) => voice.name === preferredName);
|
|
18091
|
+
if (explicit)
|
|
18092
|
+
return explicit;
|
|
18093
|
+
}
|
|
18094
|
+
const language = browserLanguage();
|
|
18095
|
+
const languagePrefix = language.split("-")[0] || "en";
|
|
18096
|
+
const matchesLanguage = (voice) => {
|
|
18097
|
+
const voiceLanguage = normalizeLanguageCode(voice.lang);
|
|
18098
|
+
return voiceLanguage === language || voiceLanguage.startsWith(`${languagePrefix}-`);
|
|
18099
|
+
};
|
|
18100
|
+
const ranked = [
|
|
18101
|
+
(voice) => voice.localService && matchesLanguage(voice),
|
|
18102
|
+
(voice) => voice.default && matchesLanguage(voice),
|
|
18103
|
+
(voice) => matchesLanguage(voice),
|
|
18104
|
+
(voice) => voice.localService,
|
|
18105
|
+
(voice) => voice.default
|
|
18106
|
+
];
|
|
18107
|
+
for (const predicate of ranked) {
|
|
18108
|
+
const voice = voices.find(predicate);
|
|
18109
|
+
if (voice)
|
|
18110
|
+
return voice;
|
|
18111
|
+
}
|
|
18112
|
+
return voices[0] || null;
|
|
18113
|
+
};
|
|
18114
|
+
var shouldAssignBrowserVoice = (voice) => !voice.default;
|
|
18115
|
+
|
|
18083
18116
|
class BrowserTTSProvider {
|
|
18084
18117
|
providerId = "browser";
|
|
18085
18118
|
providerName = "Browser Speech Synthesis";
|
|
@@ -18234,24 +18267,28 @@ class BrowserTTSProviderImpl {
|
|
|
18234
18267
|
resolve(false);
|
|
18235
18268
|
return;
|
|
18236
18269
|
}
|
|
18237
|
-
|
|
18238
|
-
|
|
18239
|
-
|
|
18240
|
-
|
|
18241
|
-
|
|
18242
|
-
this.utterance.voice = voice;
|
|
18243
|
-
}
|
|
18270
|
+
const utterance = new SpeechSynthesisUtterance(chunkText);
|
|
18271
|
+
this.utterance = utterance;
|
|
18272
|
+
const voice = findBrowserVoice(speechSynthesis.getVoices(), this.config?.voice);
|
|
18273
|
+
if (voice && shouldAssignBrowserVoice(voice))
|
|
18274
|
+
utterance.voice = voice;
|
|
18244
18275
|
if (this.config?.rate)
|
|
18245
|
-
|
|
18276
|
+
utterance.rate = this.config.rate;
|
|
18246
18277
|
if (this.config?.pitch)
|
|
18247
|
-
|
|
18248
|
-
|
|
18278
|
+
utterance.pitch = this.config.pitch;
|
|
18279
|
+
const clearOwnedUtterance = () => {
|
|
18280
|
+
if (this.utterance === utterance) {
|
|
18281
|
+
this.utterance = null;
|
|
18282
|
+
}
|
|
18283
|
+
};
|
|
18284
|
+
utterance.onstart = () => {
|
|
18249
18285
|
if (runId !== this.speakRunId)
|
|
18250
18286
|
return;
|
|
18251
18287
|
this._isPlaying = true;
|
|
18252
18288
|
this._isPaused = false;
|
|
18253
18289
|
};
|
|
18254
|
-
|
|
18290
|
+
utterance.onend = () => {
|
|
18291
|
+
clearOwnedUtterance();
|
|
18255
18292
|
if (runId !== this.speakRunId) {
|
|
18256
18293
|
resolve(false);
|
|
18257
18294
|
return;
|
|
@@ -18260,7 +18297,8 @@ class BrowserTTSProviderImpl {
|
|
|
18260
18297
|
this._isPaused = false;
|
|
18261
18298
|
resolve(true);
|
|
18262
18299
|
};
|
|
18263
|
-
|
|
18300
|
+
utterance.onerror = (event2) => {
|
|
18301
|
+
clearOwnedUtterance();
|
|
18264
18302
|
if (runId !== this.speakRunId) {
|
|
18265
18303
|
resolve(false);
|
|
18266
18304
|
return;
|
|
@@ -18273,17 +18311,17 @@ class BrowserTTSProviderImpl {
|
|
|
18273
18311
|
}
|
|
18274
18312
|
reject(new Error(`Speech synthesis error: ${event2.error}`));
|
|
18275
18313
|
};
|
|
18276
|
-
|
|
18314
|
+
utterance.onpause = () => {
|
|
18277
18315
|
if (runId !== this.speakRunId)
|
|
18278
18316
|
return;
|
|
18279
18317
|
this._isPaused = true;
|
|
18280
18318
|
};
|
|
18281
|
-
|
|
18319
|
+
utterance.onresume = () => {
|
|
18282
18320
|
if (runId !== this.speakRunId)
|
|
18283
18321
|
return;
|
|
18284
18322
|
this._isPaused = false;
|
|
18285
18323
|
};
|
|
18286
|
-
|
|
18324
|
+
utterance.onboundary = (event2) => {
|
|
18287
18325
|
if (runId !== this.speakRunId)
|
|
18288
18326
|
return;
|
|
18289
18327
|
console.log("[BrowserProvider] Boundary event:", event2.name, "charIndex:", event2.charIndex, "charLength:", event2.charLength);
|
|
@@ -18301,7 +18339,7 @@ class BrowserTTSProviderImpl {
|
|
|
18301
18339
|
console.log("[BrowserProvider] Calling onWordBoundary with word:", word, "at position:", absoluteBoundaryStart);
|
|
18302
18340
|
this.onWordBoundary(word, absoluteBoundaryStart, wordLength);
|
|
18303
18341
|
};
|
|
18304
|
-
speechSynthesis.speak(
|
|
18342
|
+
speechSynthesis.speak(utterance);
|
|
18305
18343
|
});
|
|
18306
18344
|
}
|
|
18307
18345
|
pause() {
|
|
@@ -18316,9 +18354,10 @@ class BrowserTTSProviderImpl {
|
|
|
18316
18354
|
}
|
|
18317
18355
|
stop() {
|
|
18318
18356
|
this.speakRunId += 1;
|
|
18319
|
-
if (this._isPlaying) {
|
|
18357
|
+
if (this._isPlaying || this.utterance) {
|
|
18320
18358
|
speechSynthesis.cancel();
|
|
18321
18359
|
}
|
|
18360
|
+
this.utterance = null;
|
|
18322
18361
|
this._isPlaying = false;
|
|
18323
18362
|
this._isPaused = false;
|
|
18324
18363
|
}
|
|
@@ -21831,7 +21870,10 @@ var resolvePlainBoundaryOffset = (alignment, position, safeLength) => {
|
|
|
21831
21870
|
const token = findTokenAtOffset(alignment.spokenTokens, position);
|
|
21832
21871
|
if (!token)
|
|
21833
21872
|
return null;
|
|
21834
|
-
return {
|
|
21873
|
+
return {
|
|
21874
|
+
start: position,
|
|
21875
|
+
length: Math.min(safeLength, token.end - position)
|
|
21876
|
+
};
|
|
21835
21877
|
};
|
|
21836
21878
|
var resolveSpokenBoundaryOffset = (alignment, position, length = 1, boundaryWord) => {
|
|
21837
21879
|
if (alignment.boundaryOffsetMode === "unsupported" || !Number.isFinite(position)) {
|
|
@@ -22861,7 +22903,11 @@ var collectMathAware = (root, options) => {
|
|
|
22861
22903
|
const flushTextChunk = () => {
|
|
22862
22904
|
const text2 = normalizeTextForSpeech(acc.chars.slice(textChunkStart, acc.chars.length).join(""));
|
|
22863
22905
|
if (text2) {
|
|
22864
|
-
chunks.push({
|
|
22906
|
+
chunks.push({
|
|
22907
|
+
type: "text",
|
|
22908
|
+
text: text2,
|
|
22909
|
+
sourceElement: textChunkSourceElement
|
|
22910
|
+
});
|
|
22865
22911
|
}
|
|
22866
22912
|
textChunkStart = acc.chars.length;
|
|
22867
22913
|
textChunkSourceElement = undefined;
|
|
@@ -26896,27 +26942,36 @@ class ToolkitCoordinator {
|
|
|
26896
26942
|
return;
|
|
26897
26943
|
await new Promise((resolve) => {
|
|
26898
26944
|
let settled2 = false;
|
|
26945
|
+
const canUseEventTarget = typeof synth.addEventListener === "function" && typeof synth.removeEventListener === "function";
|
|
26946
|
+
const canUseHandler = !canUseEventTarget && "onvoiceschanged" in synth;
|
|
26947
|
+
const previousHandler = canUseHandler ? synth.onvoiceschanged : null;
|
|
26948
|
+
let assignedHandler = false;
|
|
26899
26949
|
const finish = () => {
|
|
26900
26950
|
if (settled2)
|
|
26901
26951
|
return;
|
|
26902
26952
|
settled2 = true;
|
|
26903
|
-
resolve();
|
|
26904
|
-
};
|
|
26905
|
-
const timeoutId = window.setTimeout(() => {
|
|
26906
|
-
synth.removeEventListener("voiceschanged", onVoicesChanged);
|
|
26907
|
-
finish();
|
|
26908
|
-
}, timeoutMs);
|
|
26909
|
-
const onVoicesChanged = () => {
|
|
26910
26953
|
window.clearTimeout(timeoutId);
|
|
26911
|
-
if (
|
|
26954
|
+
if (canUseEventTarget) {
|
|
26912
26955
|
synth.removeEventListener("voiceschanged", onVoicesChanged);
|
|
26956
|
+
} else if (assignedHandler && synth.onvoiceschanged === onVoicesChanged) {
|
|
26957
|
+
synth.onvoiceschanged = previousHandler;
|
|
26958
|
+
}
|
|
26959
|
+
resolve();
|
|
26960
|
+
};
|
|
26961
|
+
const onVoicesChanged = (event2) => {
|
|
26962
|
+
if (!canUseEventTarget && typeof previousHandler === "function" && event2) {
|
|
26963
|
+
previousHandler.call(synth, event2);
|
|
26913
26964
|
}
|
|
26914
26965
|
finish();
|
|
26915
26966
|
};
|
|
26916
|
-
|
|
26967
|
+
const timeoutId = window.setTimeout(finish, timeoutMs);
|
|
26968
|
+
if (canUseEventTarget) {
|
|
26917
26969
|
synth.addEventListener("voiceschanged", onVoicesChanged, {
|
|
26918
26970
|
once: true
|
|
26919
26971
|
});
|
|
26972
|
+
} else if (canUseHandler) {
|
|
26973
|
+
synth.onvoiceschanged = onVoicesChanged;
|
|
26974
|
+
assignedHandler = true;
|
|
26920
26975
|
}
|
|
26921
26976
|
});
|
|
26922
26977
|
const voicesAfterWait = synth.getVoices();
|
|
@@ -10415,6 +10415,38 @@ var segmentSentences = (text2, options) => {
|
|
|
10415
10415
|
}
|
|
10416
10416
|
return parsed.length > 0 ? parsed : [{ text: text2, offset: 0 }];
|
|
10417
10417
|
};
|
|
10418
|
+
var normalizeLanguageCode = (value) => String(value || "").trim().toLowerCase();
|
|
10419
|
+
var browserLanguage = () => {
|
|
10420
|
+
const navigatorLanguage = typeof navigator !== "undefined" ? navigator.language || navigator.languages?.[0] : "";
|
|
10421
|
+
return normalizeLanguageCode(navigatorLanguage || "en-US");
|
|
10422
|
+
};
|
|
10423
|
+
var findBrowserVoice = (voices, preferredName) => {
|
|
10424
|
+
if (preferredName) {
|
|
10425
|
+
const explicit = voices.find((voice) => voice.name === preferredName);
|
|
10426
|
+
if (explicit)
|
|
10427
|
+
return explicit;
|
|
10428
|
+
}
|
|
10429
|
+
const language = browserLanguage();
|
|
10430
|
+
const languagePrefix = language.split("-")[0] || "en";
|
|
10431
|
+
const matchesLanguage = (voice) => {
|
|
10432
|
+
const voiceLanguage = normalizeLanguageCode(voice.lang);
|
|
10433
|
+
return voiceLanguage === language || voiceLanguage.startsWith(`${languagePrefix}-`);
|
|
10434
|
+
};
|
|
10435
|
+
const ranked = [
|
|
10436
|
+
(voice) => voice.localService && matchesLanguage(voice),
|
|
10437
|
+
(voice) => voice.default && matchesLanguage(voice),
|
|
10438
|
+
(voice) => matchesLanguage(voice),
|
|
10439
|
+
(voice) => voice.localService,
|
|
10440
|
+
(voice) => voice.default
|
|
10441
|
+
];
|
|
10442
|
+
for (const predicate of ranked) {
|
|
10443
|
+
const voice = voices.find(predicate);
|
|
10444
|
+
if (voice)
|
|
10445
|
+
return voice;
|
|
10446
|
+
}
|
|
10447
|
+
return voices[0] || null;
|
|
10448
|
+
};
|
|
10449
|
+
var shouldAssignBrowserVoice = (voice) => !voice.default;
|
|
10418
10450
|
|
|
10419
10451
|
class BrowserTTSProvider {
|
|
10420
10452
|
providerId = "browser";
|
|
@@ -10570,24 +10602,28 @@ class BrowserTTSProviderImpl {
|
|
|
10570
10602
|
resolve(false);
|
|
10571
10603
|
return;
|
|
10572
10604
|
}
|
|
10573
|
-
|
|
10574
|
-
|
|
10575
|
-
|
|
10576
|
-
|
|
10577
|
-
|
|
10578
|
-
this.utterance.voice = voice;
|
|
10579
|
-
}
|
|
10605
|
+
const utterance = new SpeechSynthesisUtterance(chunkText);
|
|
10606
|
+
this.utterance = utterance;
|
|
10607
|
+
const voice = findBrowserVoice(speechSynthesis.getVoices(), this.config?.voice);
|
|
10608
|
+
if (voice && shouldAssignBrowserVoice(voice))
|
|
10609
|
+
utterance.voice = voice;
|
|
10580
10610
|
if (this.config?.rate)
|
|
10581
|
-
|
|
10611
|
+
utterance.rate = this.config.rate;
|
|
10582
10612
|
if (this.config?.pitch)
|
|
10583
|
-
|
|
10584
|
-
|
|
10613
|
+
utterance.pitch = this.config.pitch;
|
|
10614
|
+
const clearOwnedUtterance = () => {
|
|
10615
|
+
if (this.utterance === utterance) {
|
|
10616
|
+
this.utterance = null;
|
|
10617
|
+
}
|
|
10618
|
+
};
|
|
10619
|
+
utterance.onstart = () => {
|
|
10585
10620
|
if (runId !== this.speakRunId)
|
|
10586
10621
|
return;
|
|
10587
10622
|
this._isPlaying = true;
|
|
10588
10623
|
this._isPaused = false;
|
|
10589
10624
|
};
|
|
10590
|
-
|
|
10625
|
+
utterance.onend = () => {
|
|
10626
|
+
clearOwnedUtterance();
|
|
10591
10627
|
if (runId !== this.speakRunId) {
|
|
10592
10628
|
resolve(false);
|
|
10593
10629
|
return;
|
|
@@ -10596,7 +10632,8 @@ class BrowserTTSProviderImpl {
|
|
|
10596
10632
|
this._isPaused = false;
|
|
10597
10633
|
resolve(true);
|
|
10598
10634
|
};
|
|
10599
|
-
|
|
10635
|
+
utterance.onerror = (event2) => {
|
|
10636
|
+
clearOwnedUtterance();
|
|
10600
10637
|
if (runId !== this.speakRunId) {
|
|
10601
10638
|
resolve(false);
|
|
10602
10639
|
return;
|
|
@@ -10609,17 +10646,17 @@ class BrowserTTSProviderImpl {
|
|
|
10609
10646
|
}
|
|
10610
10647
|
reject(new Error(`Speech synthesis error: ${event2.error}`));
|
|
10611
10648
|
};
|
|
10612
|
-
|
|
10649
|
+
utterance.onpause = () => {
|
|
10613
10650
|
if (runId !== this.speakRunId)
|
|
10614
10651
|
return;
|
|
10615
10652
|
this._isPaused = true;
|
|
10616
10653
|
};
|
|
10617
|
-
|
|
10654
|
+
utterance.onresume = () => {
|
|
10618
10655
|
if (runId !== this.speakRunId)
|
|
10619
10656
|
return;
|
|
10620
10657
|
this._isPaused = false;
|
|
10621
10658
|
};
|
|
10622
|
-
|
|
10659
|
+
utterance.onboundary = (event2) => {
|
|
10623
10660
|
if (runId !== this.speakRunId)
|
|
10624
10661
|
return;
|
|
10625
10662
|
console.log("[BrowserProvider] Boundary event:", event2.name, "charIndex:", event2.charIndex, "charLength:", event2.charLength);
|
|
@@ -10637,7 +10674,7 @@ class BrowserTTSProviderImpl {
|
|
|
10637
10674
|
console.log("[BrowserProvider] Calling onWordBoundary with word:", word, "at position:", absoluteBoundaryStart);
|
|
10638
10675
|
this.onWordBoundary(word, absoluteBoundaryStart, wordLength);
|
|
10639
10676
|
};
|
|
10640
|
-
speechSynthesis.speak(
|
|
10677
|
+
speechSynthesis.speak(utterance);
|
|
10641
10678
|
});
|
|
10642
10679
|
}
|
|
10643
10680
|
pause() {
|
|
@@ -10652,9 +10689,10 @@ class BrowserTTSProviderImpl {
|
|
|
10652
10689
|
}
|
|
10653
10690
|
stop() {
|
|
10654
10691
|
this.speakRunId += 1;
|
|
10655
|
-
if (this._isPlaying) {
|
|
10692
|
+
if (this._isPlaying || this.utterance) {
|
|
10656
10693
|
speechSynthesis.cancel();
|
|
10657
10694
|
}
|
|
10695
|
+
this.utterance = null;
|
|
10658
10696
|
this._isPlaying = false;
|
|
10659
10697
|
this._isPaused = false;
|
|
10660
10698
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -43,7 +43,7 @@ export { ToolkitCoordinator } from "./services/ToolkitCoordinator.js";
|
|
|
43
43
|
export type { CanonicalToolsConfig, ToolPlacementConfig, ToolPlacementLevel, ToolPolicyConfig, ToolProvidersConfig, } from "./services/tools-config-normalizer.js";
|
|
44
44
|
export type { FrameworkErrorKind, FrameworkErrorModel, FrameworkErrorSeverity, } from "./services/framework-error.js";
|
|
45
45
|
export { formatFrameworkErrorForConsole, frameworkErrorFromToolConfigDiagnostics, frameworkErrorFromUnknown, toFrameworkErrorModel, } from "./services/framework-error.js";
|
|
46
|
-
export type { FrameworkErrorListener
|
|
46
|
+
export type { FrameworkErrorListener } from "./services/framework-error-bus.js";
|
|
47
47
|
export type { ToolConfigDiagnostic, ToolConfigDiagnosticSeverity, ToolConfigStrictness, ToolConfigValidationOptions, ToolConfigValidationResult, } from "./services/tool-config-validation.js";
|
|
48
48
|
export type { ToolbarButtonItem, ToolbarItem, ToolbarItemBase, ToolbarLinkItem, } from "./services/toolbar-items.js";
|
|
49
49
|
export { isExternalIconUrl, isInlineSvgIcon, isToolbarLinkItem, isValidToolbarItemShape, } from "./services/toolbar-items.js";
|