@playcademy/sdk 0.16.1-beta.9 → 0.17.0
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 +31 -8
- package/dist/contracts.d.ts +47 -0
- package/dist/contracts.js +23 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +333 -109
- package/dist/internal.d.ts +57 -3
- package/dist/internal.js +356 -112
- package/dist/server/edge.d.ts +17 -1
- package/dist/server/edge.js +5 -2
- package/dist/server.d.ts +17 -1
- package/dist/server.js +5 -2
- package/dist/types.d.ts +42 -1
- package/package.json +7 -1
package/README.md
CHANGED
|
@@ -122,21 +122,25 @@ Hosted assessments use the same methods locally and when deployed:
|
|
|
122
122
|
const attempt = await client.timeback.assessments.start({
|
|
123
123
|
activityId: 'math-diagnostic',
|
|
124
124
|
purpose: 'diagnostic',
|
|
125
|
+
diagnosticKey: 'math.grade-5-placement',
|
|
125
126
|
subject: 'Math',
|
|
126
127
|
grade: 5,
|
|
127
128
|
})
|
|
128
129
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
[attempt.assessment.items[0].identifier]: { RESPONSE: 'A' },
|
|
133
|
-
},
|
|
134
|
-
})
|
|
130
|
+
if (attempt.flow !== 'platform-routed-item-submit' || !attempt.routing.next) {
|
|
131
|
+
throw new Error('Expected an active routed diagnostic')
|
|
132
|
+
}
|
|
135
133
|
|
|
136
|
-
const
|
|
137
|
-
|
|
134
|
+
const current = attempt.routing.next
|
|
135
|
+
const committed = await client.timeback.assessments.submitItem(attempt.attemptId, {
|
|
136
|
+
expectedResponseVersion: attempt.responseVersion,
|
|
138
137
|
submissionId: crypto.randomUUID(),
|
|
138
|
+
routingNodeKey: current.nodeKey,
|
|
139
|
+
itemIdentifier: current.itemIdentifier,
|
|
140
|
+
responses: { RESPONSE: 'A' },
|
|
139
141
|
})
|
|
142
|
+
|
|
143
|
+
// Repeat with committed.routing.next. When routing is ready, submit() only finalizes.
|
|
140
144
|
```
|
|
141
145
|
|
|
142
146
|
`start()` resumes a compatible unfinished attempt or selects content for a fixed test or standards
|
|
@@ -144,6 +148,25 @@ review. Save payloads merge at both the item and response levels; omitted values
|
|
|
144
148
|
and `null` clears one response. Keep the returned `responseVersion` and send it with the next
|
|
145
149
|
mutation.
|
|
146
150
|
|
|
151
|
+
The returned `flow` is authoritative and is derived from the selected assessment; callers do not configure
|
|
152
|
+
navigation, feedback, and submission independently:
|
|
153
|
+
|
|
154
|
+
- `attempt-submit` is used for end-of-course and mastery attempts. Responses remain editable
|
|
155
|
+
through `save()` until `submit()` finalizes the whole attempt and returns feedback.
|
|
156
|
+
- `item-submit` is used for review attempts. Submit each administered item with `submitItem()`.
|
|
157
|
+
That operation atomically saves the item's responses, locks them, and returns safe immediate
|
|
158
|
+
feedback. Give each item request its own stable `submissionId` and reuse that ID for an ambiguous
|
|
159
|
+
retry; the returned canonical `itemSubmissions` ledger identifies committed items after retry or
|
|
160
|
+
resume.
|
|
161
|
+
- `platform-routed-item-submit` is used for adaptive diagnostics. Render only
|
|
162
|
+
`routing.next.itemIdentifier`, submit it with `routing.next.nodeKey`, and replace local state with
|
|
163
|
+
the returned canonical routing snapshot. Diagnostic receipts never reveal correctness or score,
|
|
164
|
+
and `submit()` becomes available only after routing reports `ready-to-complete`.
|
|
165
|
+
|
|
166
|
+
The host rejects the wrong mutation for each flow, rejects premature finalization, and enforces
|
|
167
|
+
`expectedResponseVersion` for every mutation. Hosted and local providers execute the same routing
|
|
168
|
+
manifest contract; game code never selects the provider.
|
|
169
|
+
|
|
147
170
|
For local development, import the current ordered catalog before starting the dev host:
|
|
148
171
|
|
|
149
172
|
```bash
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The child-catalog contract: what a child game publishes about its
|
|
3
|
+
* deliverable lessons, per lesson id and level. A parent course authority
|
|
4
|
+
* resolves its lesson references against this document at compile time and
|
|
5
|
+
* fails closed at runtime on anything not `ready` in production.
|
|
6
|
+
*
|
|
7
|
+
* Ownership and flow: each child repo generates `.playcademy/catalog.json`
|
|
8
|
+
* from its own registry (`playcademy catalog generate`); a sync workflow
|
|
9
|
+
* carries copies into parent repos. Children never read the parent's
|
|
10
|
+
* compiled authority — this file and the launch payload are the entire
|
|
11
|
+
* surface between them.
|
|
12
|
+
*
|
|
13
|
+
* The document deliberately carries no app identity. The consuming repo
|
|
14
|
+
* assigns the namespace key (e.g. 'form', 'math-cakes') from sync
|
|
15
|
+
* provenance via its own repo → app map, so a child cannot misdeclare
|
|
16
|
+
* who it is and a typo cannot mint a phantom namespace.
|
|
17
|
+
*/
|
|
18
|
+
/** Contract identifier carried by every catalog document. */
|
|
19
|
+
declare const CHILD_CATALOG_CONTRACT: 'playcademy-child-catalog-v1';
|
|
20
|
+
/** The completion-evidence contract a catalog declares its runs report. */
|
|
21
|
+
declare const CHILD_ATTEMPT_CONTRACT: 'playcademy-child-attempt-v1';
|
|
22
|
+
/** Delivery levels a catalog may declare (serving-id dialect, lowercase). */
|
|
23
|
+
declare const CATALOG_LEVELS: readonly ['e1', 'e2', 'e3', 'e4'];
|
|
24
|
+
type CatalogLevel = (typeof CATALOG_LEVELS)[number];
|
|
25
|
+
/**
|
|
26
|
+
* ready: real content. simulated: placeholder — playable for preview and
|
|
27
|
+
* simulation, never creditable in production. unavailable: intentionally
|
|
28
|
+
* absent at this level. Consumers must treat unknown values and missing
|
|
29
|
+
* levels as unavailable (fail closed).
|
|
30
|
+
*/
|
|
31
|
+
declare const CATALOG_READINESS: readonly ['ready', 'simulated', 'unavailable'];
|
|
32
|
+
type CatalogReadiness = (typeof CATALOG_READINESS)[number];
|
|
33
|
+
interface ChildCatalog {
|
|
34
|
+
/** The contract identifier. */
|
|
35
|
+
contract: typeof CHILD_CATALOG_CONTRACT;
|
|
36
|
+
/** The completion-evidence contract a catalog declares its runs report. */
|
|
37
|
+
evidence: typeof CHILD_ATTEMPT_CONTRACT;
|
|
38
|
+
/** The tool that generated this document (repo-relative path). */
|
|
39
|
+
generatedBy: string;
|
|
40
|
+
/** The in-repo source of truth the document was derived from. */
|
|
41
|
+
generatedFrom: string;
|
|
42
|
+
/** Lesson id → level → readiness. */
|
|
43
|
+
deliveries: Record<string, Partial<Record<CatalogLevel, CatalogReadiness>>>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { CATALOG_LEVELS, CATALOG_READINESS, CHILD_ATTEMPT_CONTRACT, CHILD_CATALOG_CONTRACT };
|
|
47
|
+
export type { CatalogLevel, CatalogReadiness, ChildCatalog };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, {
|
|
5
|
+
get: all[name],
|
|
6
|
+
enumerable: true,
|
|
7
|
+
configurable: true,
|
|
8
|
+
set: (newValue) => all[name] = () => newValue
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
12
|
+
|
|
13
|
+
// src/contracts/child-catalog.ts
|
|
14
|
+
var CHILD_CATALOG_CONTRACT = "playcademy-child-catalog-v1";
|
|
15
|
+
var CHILD_ATTEMPT_CONTRACT = "playcademy-child-attempt-v1";
|
|
16
|
+
var CATALOG_LEVELS = ["e1", "e2", "e3", "e4"];
|
|
17
|
+
var CATALOG_READINESS = ["ready", "simulated", "unavailable"];
|
|
18
|
+
export {
|
|
19
|
+
CHILD_CATALOG_CONTRACT,
|
|
20
|
+
CHILD_ATTEMPT_CONTRACT,
|
|
21
|
+
CATALOG_READINESS,
|
|
22
|
+
CATALOG_LEVELS
|
|
23
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1558,7 +1558,11 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
|
|
|
1558
1558
|
start: (input: _playcademy_types.StartAssessmentInput) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
|
|
1559
1559
|
latest: (options: _playcademy_types.GetLatestAssessmentOptions) => Promise<_playcademy_types.LatestAssessmentResult | null>;
|
|
1560
1560
|
get: (attemptId: string) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
|
|
1561
|
+
stop: (attemptId: string) => Promise<{
|
|
1562
|
+
attemptId: string;
|
|
1563
|
+
}>;
|
|
1561
1564
|
save: (attemptId: string, input: _playcademy_types.SaveAssessmentInput) => Promise<_playcademy_types.AssessmentSaveResult>;
|
|
1565
|
+
submitItem: (attemptId: string, input: _playcademy_types.SubmitAssessmentItemInput) => Promise<_playcademy_types.SubmitAssessmentItemResult>;
|
|
1562
1566
|
submit: (attemptId: string, input: _playcademy_types.SubmitAssessmentInput) => Promise<_playcademy_types.AssessmentSubmitResult>;
|
|
1563
1567
|
};
|
|
1564
1568
|
readonly user: TimebackUser;
|
|
@@ -1910,6 +1914,15 @@ type EmbedActivity = EmbedActivityCompleted | EmbedActivityAbandoned | EmbedActi
|
|
|
1910
1914
|
/** The child called `endActivity()` and its report was relayed. */
|
|
1911
1915
|
interface EmbedActivityCompleted {
|
|
1912
1916
|
status: 'completed';
|
|
1917
|
+
/**
|
|
1918
|
+
* The platform run this completion records under. One run ends in at
|
|
1919
|
+
* most one completion (the server dedupes on it), and a resumed launch
|
|
1920
|
+
* keeps the interrupted run's id — so this doubles as the completion's
|
|
1921
|
+
* attempt identity: feed it to whatever consumes the result and drop
|
|
1922
|
+
* anything you have seen before. Absent only for pure UX embeds
|
|
1923
|
+
* (launched without `timeback`), which record nothing.
|
|
1924
|
+
*/
|
|
1925
|
+
runId?: string;
|
|
1913
1926
|
/** Correct answers, from the child's report. */
|
|
1914
1927
|
correct: number;
|
|
1915
1928
|
/** Total questions, from the child's report. */
|
|
@@ -1938,6 +1951,12 @@ interface EmbedActivityCompleted {
|
|
|
1938
1951
|
*/
|
|
1939
1952
|
interface EmbedActivityAbandoned {
|
|
1940
1953
|
status: 'abandoned';
|
|
1954
|
+
/**
|
|
1955
|
+
* The platform run the launch was recording under, when one had
|
|
1956
|
+
* opened. Absent when the child never started an activity or the
|
|
1957
|
+
* launch was a pure UX embed.
|
|
1958
|
+
*/
|
|
1959
|
+
runId?: string;
|
|
1941
1960
|
timing: EmbedSessionTiming;
|
|
1942
1961
|
/**
|
|
1943
1962
|
* The final resume envelope, when the child checkpointed during the
|
|
@@ -1959,6 +1978,13 @@ interface EmbedActivityFailed {
|
|
|
1959
1978
|
interface EmbedSession {
|
|
1960
1979
|
/** The mounted child iframe. Useful for focus management. */
|
|
1961
1980
|
readonly iframe: HTMLIFrameElement;
|
|
1981
|
+
/**
|
|
1982
|
+
* The platform run this launch records under, or null before the run
|
|
1983
|
+
* opens (the child's first activity) and for pure UX embeds. Stable
|
|
1984
|
+
* once set; also echoed on the finished record, which is where most
|
|
1985
|
+
* callers should read it.
|
|
1986
|
+
*/
|
|
1987
|
+
readonly runId: string | null;
|
|
1962
1988
|
/**
|
|
1963
1989
|
* The latest resume envelope, live during play; null until the child
|
|
1964
1990
|
* first checkpoints. Read it on your own cadence to persist
|