@playcademy/sdk 0.18.1-beta.2 → 0.18.1-beta.4

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/README.md CHANGED
@@ -151,6 +151,8 @@ if (attempt.flow !== 'platform-routed-item-submit' || !attempt.routing.next) {
151
151
 
152
152
  const current = attempt.routing.next
153
153
  const committed = await client.timeback.assessments.submitItem(attempt.attemptId, {
154
+ assessmentToken: attempt.assessmentToken,
155
+ transcript: attempt.transcript,
154
156
  expectedResponseVersion: attempt.responseVersion,
155
157
  submissionId: crypto.randomUUID(),
156
158
  routingNodeKey: current.nodeKey,
@@ -158,24 +160,28 @@ const committed = await client.timeback.assessments.submitItem(attempt.attemptId
158
160
  responses: { RESPONSE: 'A' },
159
161
  })
160
162
 
161
- // Repeat with committed.routing.next. When routing is ready, submit() only finalizes.
163
+ // Retain committed.transcript and repeat with committed.routing.next.
164
+ // When routing is ready, submit the complete transcript, then finalize the award.
162
165
  ```
163
166
 
164
167
  `start()` resumes a compatible unfinished attempt or selects content for a fixed test or standards
165
- review. Save payloads merge at both the item and response levels; omitted values remain unchanged,
166
- and `null` clears one response. Keep the returned `responseVersion` and send it with the next
167
- mutation.
168
+ review. Keep the raw `transcript` in storage chosen by your game (renderer memory is sufficient for
169
+ an uninterrupted attempt). The SDK does not automatically store active drafts locally.
170
+ `resume(attemptId, { transcript })` validates a supplied draft; without one, resume uses the saved
171
+ parent checkpoint, or best-effort child progress if no checkpoint exists. Start and resume also
172
+ issue an attempt-scoped `assessmentToken` using the existing JWT infrastructure.
168
173
 
169
174
  The returned `flow` is authoritative and is derived from the selected assessment; callers do not configure
170
175
  navigation, feedback, and submission independently:
171
176
 
172
177
  - `attempt-submit` is used for end-of-course and mastery attempts. Responses remain editable
173
- through `save()` until `submit()` finalizes the whole attempt and returns feedback.
178
+ in the game until `submit()` validates the complete transcript and returns feedback.
179
+ Mastery renderers may call `recordProgress()` without awaiting it on navigation to project the
180
+ current answer as best-effort child progress. It returns no grades and never writes the parent.
174
181
  - `item-submit` is used for review attempts. Submit each administered item with `submitItem()`.
175
- That operation atomically saves the item's responses, locks them, and returns safe immediate
176
- feedback. Give each item request its own stable `submissionId` and reuse that ID for an ambiguous
177
- retry; the returned canonical `itemSubmissions` ledger identifies committed items after retry or
178
- resume.
182
+ That operation grades the raw transcript without a parent read or enrollment lookup. Give each
183
+ administration a stable `submissionId`, retain the returned `transcript`, and reuse both on retry.
184
+ Child persistence is best-effort and does not block feedback.
179
185
  - `platform-routed-item-submit` is used for adaptive diagnostics. Render only
180
186
  `routing.next.itemIdentifier`, submit it with `routing.next.nodeKey`, and replace local state with
181
187
  the returned canonical routing snapshot. Each receipt includes the trusted item `score` and
@@ -184,9 +190,21 @@ navigation, feedback, and submission independently:
184
190
  `ready-to-complete`.
185
191
 
186
192
  The host rejects the wrong mutation for each flow, rejects premature finalization, and enforces
187
- `expectedResponseVersion` for every mutation. Hosted and local providers execute the same routing
193
+ `expectedResponseVersion` as the supplied administration count (the prefix count for new item feedback).
194
+ Hosted and local providers execute the same routing
188
195
  manifest contract; game code never selects the provider.
189
196
 
197
+ Use `save(attemptId, { transcript, expectedResponseVersion })` only for an explicit checkpoint such
198
+ as Save and exit, and await its acknowledgement. Success means the validated draft was saved on the
199
+ existing parent without completing it; late or stale child writes cannot replace that checkpoint.
200
+ Children remain replaceable, best-effort progress and never gate saving or completion. `submit()`
201
+ regrades the full transcript and writes the authoritative score once without waiting for child repair.
202
+ Without a game-supplied draft, a saved checkpoint still takes precedence over newer background
203
+ progress. Background writes are not guaranteed to finish on tab close.
204
+ The existing `awaiting_award` →
205
+ `finalize()` lifecycle is unchanged. Retries must preserve the completion identity, transcript,
206
+ and timing; the SDK keeps an in-flight completion request in memory until its outcome is known.
207
+
190
208
  For local development, import the current ordered catalog before starting the dev host:
191
209
 
192
210
  ```bash
package/dist/index.d.ts CHANGED
@@ -1562,7 +1562,11 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
1562
1562
  stop: (attemptId: string) => Promise<{
1563
1563
  attemptId: string;
1564
1564
  }>;
1565
+ resume: (attemptId: string, input?: _playcademy_types.ResumeAssessmentInput) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
1565
1566
  save: (attemptId: string, input: _playcademy_types.SaveAssessmentInput) => Promise<_playcademy_types.AssessmentSaveResult>;
1567
+ recordProgress: (attemptId: string, input: _playcademy_types.RecordAssessmentProgressInput) => Promise<{
1568
+ attemptId: string;
1569
+ }>;
1566
1570
  submitItem: (attemptId: string, input: _playcademy_types.SubmitAssessmentItemInput) => Promise<_playcademy_types.SubmitAssessmentItemResult>;
1567
1571
  submit: (attemptId: string, input: _playcademy_types.SubmitAssessmentInput) => Promise<_playcademy_types.AssessmentSubmitResult>;
1568
1572
  finalize: (attemptId: string, input: _playcademy_types.FinalizeAssessmentInput) => Promise<_playcademy_types.AssessmentFinalizeResult>;
package/dist/index.js CHANGED
@@ -3122,7 +3122,7 @@ function createTimebackNamespace(client) {
3122
3122
  console.warn(`[Playcademy SDK] timeback.assessments: active-time tracking was not attached to assessment ${attemptId} (${reason}). ${remedy}`);
3123
3123
  }
3124
3124
  function releasePendingSubmission(attemptId, submissionId) {
3125
- if (pendingAssessmentSubmissions.get(attemptId)?.submissionId === submissionId) {
3125
+ if (pendingAssessmentSubmissions.get(attemptId)?.request.submissionId === submissionId) {
3126
3126
  pendingAssessmentSubmissions.delete(attemptId);
3127
3127
  }
3128
3128
  }
@@ -3150,7 +3150,7 @@ function createTimebackNamespace(client) {
3150
3150
  return snapshot;
3151
3151
  }
3152
3152
  async function resumeAfterDefinitiveFailure(attemptId, submissionId) {
3153
- if (pendingAssessmentSubmissions.get(attemptId)?.submissionId !== submissionId) {
3153
+ if (pendingAssessmentSubmissions.get(attemptId)?.request.submissionId !== submissionId) {
3154
3154
  return;
3155
3155
  }
3156
3156
  pendingAssessmentSubmissions.delete(attemptId);
@@ -3158,18 +3158,24 @@ function createTimebackNamespace(client) {
3158
3158
  await syncAssessmentTracking(await loadAttemptSnapshot(attemptId));
3159
3159
  } catch {}
3160
3160
  }
3161
- async function assessmentSubmissionContext(attemptId, submissionId) {
3161
+ async function assessmentSubmissionContext(attemptId, input) {
3162
+ const { submissionId } = input;
3162
3163
  const pending = pendingAssessmentSubmissions.get(attemptId);
3163
3164
  if (pending) {
3164
- if (pending.submissionId !== submissionId && !pending.detached) {
3165
+ if (pending.request.submissionId !== submissionId && !pending.detached) {
3165
3166
  throw new Error(`Assessment ${attemptId} already has a pending submission. Retry with the original submissionId.`);
3166
3167
  }
3167
3168
  pending.detached = false;
3168
3169
  return {
3169
- submissionId: pending.submissionId,
3170
+ request: pending.request,
3170
3171
  session: await pending.session
3171
3172
  };
3172
3173
  }
3174
+ const request = {
3175
+ submissionId,
3176
+ expectedResponseVersion: input.expectedResponseVersion,
3177
+ transcript: structuredClone(input.transcript)
3178
+ };
3173
3179
  const session = engine.activity.finishAssessment(attemptId).then((finished) => finished ? {
3174
3180
  runId: finished.runId,
3175
3181
  resumeId: finished.resumeId,
@@ -3179,11 +3185,11 @@ function createTimebackNamespace(client) {
3179
3185
  throw error;
3180
3186
  });
3181
3187
  pendingAssessmentSubmissions.set(attemptId, {
3182
- submissionId,
3188
+ request,
3183
3189
  session,
3184
3190
  detached: false
3185
3191
  });
3186
- return { submissionId, session: await session };
3192
+ return { request, session: await session };
3187
3193
  }
3188
3194
  registerPauseProbe(client, () => engine.activity.isManuallyPaused());
3189
3195
  return {
@@ -3238,6 +3244,14 @@ function createTimebackNamespace(client) {
3238
3244
  clearAssessmentTrackingWarnings(attemptId);
3239
3245
  return { attemptId };
3240
3246
  },
3247
+ resume: async (attemptId, input = {}) => {
3248
+ assertPlatformMode(client, "timeback.assessments.resume()");
3249
+ if (!attemptId?.trim()) {
3250
+ throw new Error("attemptId is required");
3251
+ }
3252
+ const snapshot = await client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}/resume`, "POST", input);
3253
+ return syncAssessmentTracking(snapshot);
3254
+ },
3241
3255
  save: async (attemptId, input) => {
3242
3256
  assertPlatformMode(client, "timeback.assessments.save()");
3243
3257
  if (!attemptId?.trim()) {
@@ -3248,6 +3262,22 @@ function createTimebackNamespace(client) {
3248
3262
  }
3249
3263
  return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}/save`, "POST", input);
3250
3264
  },
3265
+ recordProgress: async (attemptId, input) => {
3266
+ assertPlatformMode(client, "timeback.assessments.recordProgress()");
3267
+ if (!attemptId?.trim()) {
3268
+ throw new Error("attemptId is required");
3269
+ }
3270
+ if (!Number.isInteger(input.expectedResponseVersion) || input.expectedResponseVersion < 0) {
3271
+ throw new Error("expectedResponseVersion must be a non-negative integer");
3272
+ }
3273
+ if (!input.assessmentToken?.trim()) {
3274
+ throw new Error("assessmentToken is required");
3275
+ }
3276
+ if (!input.itemIdentifier?.trim()) {
3277
+ throw new Error("itemIdentifier is required");
3278
+ }
3279
+ return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}/progress`, "POST", input);
3280
+ },
3251
3281
  submitItem: async (attemptId, input) => {
3252
3282
  assertPlatformMode(client, "timeback.assessments.submitItem()");
3253
3283
  if (!attemptId?.trim()) {
@@ -3278,12 +3308,11 @@ function createTimebackNamespace(client) {
3278
3308
  if (!input.submissionId?.trim()) {
3279
3309
  throw new Error("submissionId is required");
3280
3310
  }
3281
- const { expectedResponseVersion } = input;
3282
- const { submissionId, session } = await assessmentSubmissionContext(attemptId, input.submissionId);
3311
+ const context = await assessmentSubmissionContext(attemptId, input);
3312
+ const { submissionId } = context.request;
3283
3313
  const request = {
3284
- expectedResponseVersion,
3285
- submissionId,
3286
- ...session ? { session } : {}
3314
+ ...context.request,
3315
+ ...context.session ? { session: context.session } : {}
3287
3316
  };
3288
3317
  try {
3289
3318
  const result = await client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}/submit`, "POST", request, undefined, { retryPolicy: ASSESSMENT_SUBMIT_RETRY_POLICY });
@@ -3725,7 +3754,7 @@ async function request({
3725
3754
  return rawText && rawText.length > 0 ? rawText : undefined;
3726
3755
  }
3727
3756
  // src/version.ts
3728
- var SDK_VERSION = "0.18.1-beta.2";
3757
+ var SDK_VERSION = "0.18.1-beta.4";
3729
3758
 
3730
3759
  // src/clients/base.ts
3731
3760
  class PlaycademyBaseClient {
@@ -1,7 +1,7 @@
1
1
  import { SchemaInfo } from '@playcademy/cloudflare';
2
2
  import { GamePermission, AUTH_PROVIDER_IDS } from '@playcademy/constants';
3
3
  import { TimebackGrade, TimebackSubject, ELevel, HeartbeatRequest, EndActivityRequest, EndActivityScoreData, EndActivityResponse, TimebackCourseConfig, CourseConfig, OrganizationConfig, ComponentConfig, ResourceConfig, ComponentResourceConfig } from '@playcademy/types/timeback';
4
- export { AssessmentAttemptSnapshot, AssessmentAwardRecord, AssessmentFinalizeResult, AssessmentFlow, AssessmentItemGrading, AssessmentItemSubmission, AssessmentMasteryAward, AssessmentPreparationResult, AssessmentResponseUpdate, AssessmentResponseValue, AssessmentResponses, AssessmentSaveResult, AssessmentScore, AssessmentStandardRef, AssessmentSubmitResult, ConventionalAssessmentAttemptSnapshot, ConventionalAssessmentSubmitResult, DiagnosticAssessmentItemReceipt, DiagnosticAssessmentSubmitResult, DiagnosticRoutingSnapshot, DiagnosticRoutingTrackSnapshot, ELevel, FinalizeAssessmentInput, PlatformRoutedDiagnosticAttemptSnapshot, PlatformRoutedDiagnosticSelectionContext, PlayableAssessment, PlayableAssessmentAttemptSnapshot, PlayableAssessmentChoice, PlayableAssessmentGraphic, PlayableAssessmentHotspot, PlayableAssessmentInteraction, PlayableAssessmentItem, PlayableContentNode, SaveAssessmentInput, SettledAssessmentAttemptSnapshot, StartAssessmentInput, StartAssessmentOptions, StartDiagnosticAssessmentInput, SubmitAssessmentInput, SubmitAssessmentItemInput, SubmitAssessmentItemResult, SubmitDiagnosticAssessmentItemInput, SubmitDiagnosticAssessmentItemResult } from '@playcademy/types/timeback';
4
+ export { AssessmentAttemptSnapshot, AssessmentAwardRecord, AssessmentFinalizeResult, AssessmentFlow, AssessmentItemGrading, AssessmentItemSubmission, AssessmentMasteryAward, AssessmentPreparationResult, AssessmentResponseUpdate, AssessmentResponseValue, AssessmentResponses, AssessmentSaveResult, AssessmentScore, AssessmentStandardRef, AssessmentSubmitResult, AssessmentTranscript, ConventionalAssessmentAttemptSnapshot, ConventionalAssessmentSubmitResult, DiagnosticAssessmentItemReceipt, DiagnosticAssessmentSubmitResult, DiagnosticRoutingSnapshot, DiagnosticRoutingTrackSnapshot, ELevel, FinalizeAssessmentInput, PlatformRoutedDiagnosticAttemptSnapshot, PlatformRoutedDiagnosticSelectionContext, PlayableAssessment, PlayableAssessmentAttemptSnapshot, PlayableAssessmentChoice, PlayableAssessmentGraphic, PlayableAssessmentHotspot, PlayableAssessmentInteraction, PlayableAssessmentItem, PlayableContentNode, RecordAssessmentProgressInput, ResumeAssessmentInput, SaveAssessmentInput, SettledAssessmentAttemptSnapshot, StartAssessmentInput, StartAssessmentOptions, StartDiagnosticAssessmentInput, SubmitAssessmentInput, SubmitAssessmentItemInput, SubmitAssessmentItemResult, SubmitDiagnosticAssessmentItemInput, SubmitDiagnosticAssessmentItemResult } from '@playcademy/types/timeback';
5
5
  import * as _playcademy_types from '@playcademy/types';
6
6
  import { GameManifest, LocalDayContext } from '@playcademy/types';
7
7
  export { AuthenticatedUser, DeveloperStatusEnumType, DeveloperStatusResponse, DeveloperStatusValue, GameCourseMetrics, GameLeaderboardEntry, GameManifest, GameMetricComparisonKind, GameMetricComparisonMetric, GameMetricComparisonRow, GameMetricComparisonRowStatus, GameMetricsProxyResponse, GameMetricsResponse, GameMetricsUnsupportedReason, GamePlatform, GameRunMetrics, GameRunMetricsComparison, GameRunMetricsComparisonStatus, GameRunMetricsComparisonSummary, GameTimebackIntegration, GameType, GameUser, LeaderboardEntry, LeaderboardOptions, LeaderboardTimeframe, LocalDayContext, LocalDaySource, ManifestV1, ManifestV2, ManifestVersions, PopulateStudentResponse, UserEnrollment, UserInfo, UserOrganization, UserRank, UserRankResponse, UserRoleEnumType, UserScore, UserTimebackData } from '@playcademy/types';
package/dist/internal.js CHANGED
@@ -3122,7 +3122,7 @@ function createTimebackNamespace(client) {
3122
3122
  console.warn(`[Playcademy SDK] timeback.assessments: active-time tracking was not attached to assessment ${attemptId} (${reason}). ${remedy}`);
3123
3123
  }
3124
3124
  function releasePendingSubmission(attemptId, submissionId) {
3125
- if (pendingAssessmentSubmissions.get(attemptId)?.submissionId === submissionId) {
3125
+ if (pendingAssessmentSubmissions.get(attemptId)?.request.submissionId === submissionId) {
3126
3126
  pendingAssessmentSubmissions.delete(attemptId);
3127
3127
  }
3128
3128
  }
@@ -3150,7 +3150,7 @@ function createTimebackNamespace(client) {
3150
3150
  return snapshot;
3151
3151
  }
3152
3152
  async function resumeAfterDefinitiveFailure(attemptId, submissionId) {
3153
- if (pendingAssessmentSubmissions.get(attemptId)?.submissionId !== submissionId) {
3153
+ if (pendingAssessmentSubmissions.get(attemptId)?.request.submissionId !== submissionId) {
3154
3154
  return;
3155
3155
  }
3156
3156
  pendingAssessmentSubmissions.delete(attemptId);
@@ -3158,18 +3158,24 @@ function createTimebackNamespace(client) {
3158
3158
  await syncAssessmentTracking(await loadAttemptSnapshot(attemptId));
3159
3159
  } catch {}
3160
3160
  }
3161
- async function assessmentSubmissionContext(attemptId, submissionId) {
3161
+ async function assessmentSubmissionContext(attemptId, input) {
3162
+ const { submissionId } = input;
3162
3163
  const pending = pendingAssessmentSubmissions.get(attemptId);
3163
3164
  if (pending) {
3164
- if (pending.submissionId !== submissionId && !pending.detached) {
3165
+ if (pending.request.submissionId !== submissionId && !pending.detached) {
3165
3166
  throw new Error(`Assessment ${attemptId} already has a pending submission. Retry with the original submissionId.`);
3166
3167
  }
3167
3168
  pending.detached = false;
3168
3169
  return {
3169
- submissionId: pending.submissionId,
3170
+ request: pending.request,
3170
3171
  session: await pending.session
3171
3172
  };
3172
3173
  }
3174
+ const request = {
3175
+ submissionId,
3176
+ expectedResponseVersion: input.expectedResponseVersion,
3177
+ transcript: structuredClone(input.transcript)
3178
+ };
3173
3179
  const session = engine.activity.finishAssessment(attemptId).then((finished) => finished ? {
3174
3180
  runId: finished.runId,
3175
3181
  resumeId: finished.resumeId,
@@ -3179,11 +3185,11 @@ function createTimebackNamespace(client) {
3179
3185
  throw error;
3180
3186
  });
3181
3187
  pendingAssessmentSubmissions.set(attemptId, {
3182
- submissionId,
3188
+ request,
3183
3189
  session,
3184
3190
  detached: false
3185
3191
  });
3186
- return { submissionId, session: await session };
3192
+ return { request, session: await session };
3187
3193
  }
3188
3194
  registerPauseProbe(client, () => engine.activity.isManuallyPaused());
3189
3195
  return {
@@ -3238,6 +3244,14 @@ function createTimebackNamespace(client) {
3238
3244
  clearAssessmentTrackingWarnings(attemptId);
3239
3245
  return { attemptId };
3240
3246
  },
3247
+ resume: async (attemptId, input = {}) => {
3248
+ assertPlatformMode(client, "timeback.assessments.resume()");
3249
+ if (!attemptId?.trim()) {
3250
+ throw new Error("attemptId is required");
3251
+ }
3252
+ const snapshot = await client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}/resume`, "POST", input);
3253
+ return syncAssessmentTracking(snapshot);
3254
+ },
3241
3255
  save: async (attemptId, input) => {
3242
3256
  assertPlatformMode(client, "timeback.assessments.save()");
3243
3257
  if (!attemptId?.trim()) {
@@ -3248,6 +3262,22 @@ function createTimebackNamespace(client) {
3248
3262
  }
3249
3263
  return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}/save`, "POST", input);
3250
3264
  },
3265
+ recordProgress: async (attemptId, input) => {
3266
+ assertPlatformMode(client, "timeback.assessments.recordProgress()");
3267
+ if (!attemptId?.trim()) {
3268
+ throw new Error("attemptId is required");
3269
+ }
3270
+ if (!Number.isInteger(input.expectedResponseVersion) || input.expectedResponseVersion < 0) {
3271
+ throw new Error("expectedResponseVersion must be a non-negative integer");
3272
+ }
3273
+ if (!input.assessmentToken?.trim()) {
3274
+ throw new Error("assessmentToken is required");
3275
+ }
3276
+ if (!input.itemIdentifier?.trim()) {
3277
+ throw new Error("itemIdentifier is required");
3278
+ }
3279
+ return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}/progress`, "POST", input);
3280
+ },
3251
3281
  submitItem: async (attemptId, input) => {
3252
3282
  assertPlatformMode(client, "timeback.assessments.submitItem()");
3253
3283
  if (!attemptId?.trim()) {
@@ -3278,12 +3308,11 @@ function createTimebackNamespace(client) {
3278
3308
  if (!input.submissionId?.trim()) {
3279
3309
  throw new Error("submissionId is required");
3280
3310
  }
3281
- const { expectedResponseVersion } = input;
3282
- const { submissionId, session } = await assessmentSubmissionContext(attemptId, input.submissionId);
3311
+ const context = await assessmentSubmissionContext(attemptId, input);
3312
+ const { submissionId } = context.request;
3283
3313
  const request = {
3284
- expectedResponseVersion,
3285
- submissionId,
3286
- ...session ? { session } : {}
3314
+ ...context.request,
3315
+ ...context.session ? { session: context.session } : {}
3287
3316
  };
3288
3317
  try {
3289
3318
  const result = await client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}/submit`, "POST", request, undefined, { retryPolicy: ASSESSMENT_SUBMIT_RETRY_POLICY });
@@ -4617,7 +4646,7 @@ async function request({
4617
4646
  return rawText && rawText.length > 0 ? rawText : undefined;
4618
4647
  }
4619
4648
  // src/version.ts
4620
- var SDK_VERSION = "0.18.1-beta.2";
4649
+ var SDK_VERSION = "0.18.1-beta.4";
4621
4650
 
4622
4651
  // src/clients/base.ts
4623
4652
  class PlaycademyBaseClient {
@@ -375,6 +375,10 @@ declare class PlaycademyClient {
375
375
  latest: (studentId: string, options: _playcademy_types.GetLatestAssessmentOptions) => Promise<_playcademy_types.LatestAssessmentResult | null>;
376
376
  get: (studentId: string, attemptId: string) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
377
377
  save: (studentId: string, attemptId: string, input: _playcademy_types.SaveAssessmentInput) => Promise<_playcademy_types.AssessmentSaveResult>;
378
+ resume: (studentId: string, attemptId: string, input?: _playcademy_types.ResumeAssessmentInput) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
379
+ recordProgress: (studentId: string, attemptId: string, input: _playcademy_types.RecordAssessmentProgressInput) => Promise<{
380
+ attemptId: string;
381
+ }>;
378
382
  submitItem: (studentId: string, attemptId: string, input: _playcademy_types.SubmitAssessmentItemInput) => Promise<_playcademy_types.SubmitAssessmentItemResult>;
379
383
  submit: (studentId: string, attemptId: string, input: _playcademy_types.SubmitAssessmentRequest, context: {
380
384
  sensorUrl: string;
@@ -123,6 +123,8 @@ function createTimebackNamespace(client) {
123
123
  return client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}?${params.toString()}`, "GET");
124
124
  },
125
125
  save: (studentId, attemptId, input) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/save`, "POST", { ...input, gameId: client.gameId, studentId }),
126
+ resume: (studentId, attemptId, input = {}) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/resume`, "POST", { ...input, gameId: client.gameId, studentId }),
127
+ recordProgress: (studentId, attemptId, input) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/progress`, "POST", { ...input, gameId: client.gameId, studentId }),
126
128
  submitItem: (studentId, attemptId, input) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/submit-item`, "POST", { ...input, gameId: client.gameId, studentId }),
127
129
  submit: (studentId, attemptId, input, context) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/submit`, "POST", {
128
130
  ...input,
@@ -335,7 +337,7 @@ function extractApiErrorInfo(error) {
335
337
  }
336
338
 
337
339
  // src/version.ts
338
- var SDK_VERSION = "0.18.1-beta.2";
340
+ var SDK_VERSION = "0.18.1-beta.4";
339
341
 
340
342
  // src/server/request.ts
341
343
  async function makeApiRequest(opts) {
package/dist/server.d.ts CHANGED
@@ -375,6 +375,10 @@ declare class PlaycademyClient$1 {
375
375
  latest: (studentId: string, options: _playcademy_types.GetLatestAssessmentOptions) => Promise<_playcademy_types.LatestAssessmentResult | null>;
376
376
  get: (studentId: string, attemptId: string) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
377
377
  save: (studentId: string, attemptId: string, input: _playcademy_types.SaveAssessmentInput) => Promise<_playcademy_types.AssessmentSaveResult>;
378
+ resume: (studentId: string, attemptId: string, input?: _playcademy_types.ResumeAssessmentInput) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
379
+ recordProgress: (studentId: string, attemptId: string, input: _playcademy_types.RecordAssessmentProgressInput) => Promise<{
380
+ attemptId: string;
381
+ }>;
378
382
  submitItem: (studentId: string, attemptId: string, input: _playcademy_types.SubmitAssessmentItemInput) => Promise<_playcademy_types.SubmitAssessmentItemResult>;
379
383
  submit: (studentId: string, attemptId: string, input: _playcademy_types.SubmitAssessmentRequest, context: {
380
384
  sensorUrl: string;
package/dist/server.js CHANGED
@@ -312,6 +312,8 @@ function createTimebackNamespace(client) {
312
312
  return client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}?${params.toString()}`, "GET");
313
313
  },
314
314
  save: (studentId, attemptId, input) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/save`, "POST", { ...input, gameId: client.gameId, studentId }),
315
+ resume: (studentId, attemptId, input = {}) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/resume`, "POST", { ...input, gameId: client.gameId, studentId }),
316
+ recordProgress: (studentId, attemptId, input) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/progress`, "POST", { ...input, gameId: client.gameId, studentId }),
315
317
  submitItem: (studentId, attemptId, input) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/submit-item`, "POST", { ...input, gameId: client.gameId, studentId }),
316
318
  submit: (studentId, attemptId, input, context) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/submit`, "POST", {
317
319
  ...input,
@@ -524,7 +526,7 @@ function extractApiErrorInfo(error) {
524
526
  }
525
527
 
526
528
  // src/version.ts
527
- var SDK_VERSION = "0.18.1-beta.2";
529
+ var SDK_VERSION = "0.18.1-beta.4";
528
530
 
529
531
  // src/server/request.ts
530
532
  async function makeApiRequest(opts) {
package/dist/types.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as _playcademy_types from '@playcademy/types';
2
2
  import { GameManifest, LocalDayContext } from '@playcademy/types';
3
3
  export { AuthenticatedUser, DeveloperStatusEnumType, DeveloperStatusResponse, DeveloperStatusValue, GameCourseMetrics, GameLeaderboardEntry, GameManifest, GameMetricComparisonKind, GameMetricComparisonMetric, GameMetricComparisonRow, GameMetricComparisonRowStatus, GameMetricsProxyResponse, GameMetricsResponse, GameMetricsUnsupportedReason, GamePlatform, GameRunMetrics, GameRunMetricsComparison, GameRunMetricsComparisonStatus, GameRunMetricsComparisonSummary, GameTimebackIntegration, GameType, GameUser, LeaderboardEntry, LeaderboardOptions, LeaderboardTimeframe, LocalDayContext, LocalDaySource, ManifestV1, ManifestV2, ManifestVersions, PopulateStudentResponse, UserEnrollment, UserInfo, UserOrganization, UserRank, UserRankResponse, UserRoleEnumType, UserScore, UserTimebackData } from '@playcademy/types';
4
4
  import { TimebackCourseConfig, CourseConfig, OrganizationConfig, ComponentConfig, ResourceConfig, ComponentResourceConfig, TimebackGrade, TimebackSubject, ELevel, EndActivityRequest, HeartbeatRequest, EndActivityScoreData, EndActivityResponse } from '@playcademy/types/timeback';
5
- export { AssessmentAttemptSnapshot, AssessmentAwardRecord, AssessmentFinalizeResult, AssessmentFlow, AssessmentItemGrading, AssessmentItemSubmission, AssessmentMasteryAward, AssessmentPreparationResult, AssessmentResponseUpdate, AssessmentResponseValue, AssessmentResponses, AssessmentSaveResult, AssessmentScore, AssessmentStandardRef, AssessmentSubmitResult, ConventionalAssessmentAttemptSnapshot, ConventionalAssessmentSubmitResult, DiagnosticAssessmentItemReceipt, DiagnosticAssessmentSubmitResult, DiagnosticRoutingSnapshot, DiagnosticRoutingTrackSnapshot, ELevel, FinalizeAssessmentInput, PlatformRoutedDiagnosticAttemptSnapshot, PlatformRoutedDiagnosticSelectionContext, PlayableAssessment, PlayableAssessmentAttemptSnapshot, PlayableAssessmentChoice, PlayableAssessmentGraphic, PlayableAssessmentHotspot, PlayableAssessmentInteraction, PlayableAssessmentItem, PlayableContentNode, SaveAssessmentInput, SettledAssessmentAttemptSnapshot, StartAssessmentInput, StartAssessmentOptions, StartDiagnosticAssessmentInput, SubmitAssessmentInput, SubmitAssessmentItemInput, SubmitAssessmentItemResult, SubmitDiagnosticAssessmentItemInput, SubmitDiagnosticAssessmentItemResult } from '@playcademy/types/timeback';
5
+ export { AssessmentAttemptSnapshot, AssessmentAwardRecord, AssessmentFinalizeResult, AssessmentFlow, AssessmentItemGrading, AssessmentItemSubmission, AssessmentMasteryAward, AssessmentPreparationResult, AssessmentResponseUpdate, AssessmentResponseValue, AssessmentResponses, AssessmentSaveResult, AssessmentScore, AssessmentStandardRef, AssessmentSubmitResult, AssessmentTranscript, ConventionalAssessmentAttemptSnapshot, ConventionalAssessmentSubmitResult, DiagnosticAssessmentItemReceipt, DiagnosticAssessmentSubmitResult, DiagnosticRoutingSnapshot, DiagnosticRoutingTrackSnapshot, ELevel, FinalizeAssessmentInput, PlatformRoutedDiagnosticAttemptSnapshot, PlatformRoutedDiagnosticSelectionContext, PlayableAssessment, PlayableAssessmentAttemptSnapshot, PlayableAssessmentChoice, PlayableAssessmentGraphic, PlayableAssessmentHotspot, PlayableAssessmentInteraction, PlayableAssessmentItem, PlayableContentNode, RecordAssessmentProgressInput, ResumeAssessmentInput, SaveAssessmentInput, SettledAssessmentAttemptSnapshot, StartAssessmentInput, StartAssessmentOptions, StartDiagnosticAssessmentInput, SubmitAssessmentInput, SubmitAssessmentItemInput, SubmitAssessmentItemResult, SubmitDiagnosticAssessmentItemInput, SubmitDiagnosticAssessmentItemResult } from '@playcademy/types/timeback';
6
6
  import { TimebackUserRole, UserEnrollment, UserOrganization, UserInfo } from '@playcademy/types/user';
7
7
  import { GamePermission, AUTH_PROVIDER_IDS } from '@playcademy/constants';
8
8
  import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
@@ -2018,7 +2018,11 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
2018
2018
  stop: (attemptId: string) => Promise<{
2019
2019
  attemptId: string;
2020
2020
  }>;
2021
+ resume: (attemptId: string, input?: _playcademy_types.ResumeAssessmentInput) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
2021
2022
  save: (attemptId: string, input: _playcademy_types.SaveAssessmentInput) => Promise<_playcademy_types.AssessmentSaveResult>;
2023
+ recordProgress: (attemptId: string, input: _playcademy_types.RecordAssessmentProgressInput) => Promise<{
2024
+ attemptId: string;
2025
+ }>;
2022
2026
  submitItem: (attemptId: string, input: _playcademy_types.SubmitAssessmentItemInput) => Promise<_playcademy_types.SubmitAssessmentItemResult>;
2023
2027
  submit: (attemptId: string, input: _playcademy_types.SubmitAssessmentInput) => Promise<_playcademy_types.AssessmentSubmitResult>;
2024
2028
  finalize: (attemptId: string, input: _playcademy_types.FinalizeAssessmentInput) => Promise<_playcademy_types.AssessmentFinalizeResult>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcademy/sdk",
3
- "version": "0.18.1-beta.2",
3
+ "version": "0.18.1-beta.4",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {