@vue-skuilder/db 0.2.2 → 0.2.3
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/{contentSource-Ht3N2f-y.d.ts → contentSource-Cplhv3bJ.d.ts} +1 -1
- package/dist/{contentSource-BMlMwSiG.d.cts → contentSource-kI9_jwTu.d.cts} +1 -1
- package/dist/core/index.d.cts +5 -5
- package/dist/core/index.d.ts +5 -5
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +2 -1
- package/dist/core/index.mjs.map +1 -1
- package/dist/{dataLayerProvider-BEqB8VBR.d.cts → dataLayerProvider-CiA2Rr0v.d.cts} +1 -1
- package/dist/{dataLayerProvider-DObSXjnf.d.ts → dataLayerProvider-DrBqOUa3.d.ts} +1 -1
- package/dist/impl/couch/index.d.cts +3 -3
- package/dist/impl/couch/index.d.ts +3 -3
- package/dist/impl/couch/index.js +2 -1
- package/dist/impl/couch/index.js.map +1 -1
- package/dist/impl/couch/index.mjs +2 -1
- package/dist/impl/couch/index.mjs.map +1 -1
- package/dist/impl/static/index.d.cts +4 -4
- package/dist/impl/static/index.d.ts +4 -4
- package/dist/impl/static/index.js +2 -1
- package/dist/impl/static/index.js.map +1 -1
- package/dist/impl/static/index.mjs +2 -1
- package/dist/impl/static/index.mjs.map +1 -1
- package/dist/{index-BWvO-_rJ.d.ts → index-BLLT5BYE.d.ts} +1 -1
- package/dist/{index-Ba7hYbHj.d.cts → index-k9NFHpS1.d.cts} +1 -1
- package/dist/index.d.cts +164 -10
- package/dist/index.d.ts +164 -10
- package/dist/index.js +141 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +141 -8
- package/dist/index.mjs.map +1 -1
- package/dist/{types-W8n-B6HG.d.cts → types-BFUa1pa3.d.cts} +1 -1
- package/dist/{types-CJrLM1Ew.d.ts → types-CHgpWQAY.d.ts} +1 -1
- package/dist/{types-legacy-JXDxinpU.d.cts → types-legacy-4tlwHnXo.d.cts} +1 -1
- package/dist/{types-legacy-JXDxinpU.d.ts → types-legacy-4tlwHnXo.d.ts} +1 -1
- package/dist/util/packer/index.d.cts +3 -3
- package/dist/util/packer/index.d.ts +3 -3
- package/package.json +3 -3
- package/src/core/navigators/Pipeline.ts +1 -1
- package/src/study/SessionController.ts +262 -13
package/dist/index.mjs
CHANGED
|
@@ -4184,7 +4184,8 @@ var init_orchestration = __esm({
|
|
|
4184
4184
|
// src/core/navigators/Pipeline.ts
|
|
4185
4185
|
var Pipeline_exports = {};
|
|
4186
4186
|
__export(Pipeline_exports, {
|
|
4187
|
-
Pipeline: () => Pipeline
|
|
4187
|
+
Pipeline: () => Pipeline,
|
|
4188
|
+
mergeHints: () => mergeHints2
|
|
4188
4189
|
});
|
|
4189
4190
|
import { toCourseElo as toCourseElo5 } from "@vue-skuilder/common";
|
|
4190
4191
|
function globToRegex(pattern) {
|
|
@@ -11242,6 +11243,7 @@ var ItemQueue = class {
|
|
|
11242
11243
|
|
|
11243
11244
|
// src/study/SessionController.ts
|
|
11244
11245
|
init_couch();
|
|
11246
|
+
init_core();
|
|
11245
11247
|
init_recording();
|
|
11246
11248
|
|
|
11247
11249
|
// src/util/index.ts
|
|
@@ -12668,6 +12670,7 @@ init_dataDirectory();
|
|
|
12668
12670
|
|
|
12669
12671
|
// src/study/SessionController.ts
|
|
12670
12672
|
init_navigators();
|
|
12673
|
+
init_Pipeline();
|
|
12671
12674
|
|
|
12672
12675
|
// src/study/SourceMixer.ts
|
|
12673
12676
|
var QuotaRoundRobinMixer = class {
|
|
@@ -13379,6 +13382,32 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13379
13382
|
* each nextCard() draw. Set by replans that include `minFollowUpCards`.
|
|
13380
13383
|
*/
|
|
13381
13384
|
_minCardsGuarantee = 0;
|
|
13385
|
+
/**
|
|
13386
|
+
* Session-durable scoring hints. Re-merged into every pipeline run for
|
|
13387
|
+
* the rest of the session (initial plan + every replan, including bare
|
|
13388
|
+
* auto-replans and the wedge-breaker), via `_applyHintsToSources`.
|
|
13389
|
+
*
|
|
13390
|
+
* Set by `setSessionHints()` (e.g. session-start post-lesson boost) or by
|
|
13391
|
+
* any replan carrying `ReplanOptions.sessionHints` (e.g. a just-failed
|
|
13392
|
+
* concept boost). Replace semantics, no decay — lives until overwritten
|
|
13393
|
+
* or session end. See `ReplanOptions.sessionHints` for rationale.
|
|
13394
|
+
*
|
|
13395
|
+
* Note: the controller-managed auto-excludes (current card, session
|
|
13396
|
+
* record, imminent draw) are intentionally NOT folded in here — those are
|
|
13397
|
+
* recomputed per-run in `_runReplan` and would otherwise go stale.
|
|
13398
|
+
*/
|
|
13399
|
+
_sessionHints = null;
|
|
13400
|
+
/**
|
|
13401
|
+
* Consumer-supplied hooks invoked after each question response is processed.
|
|
13402
|
+
* Seeded from constructor options (threaded from
|
|
13403
|
+
* `StudySessionConfig.outcomeObservers`). See {@link OutcomeObserver}.
|
|
13404
|
+
*/
|
|
13405
|
+
_outcomeObservers = [];
|
|
13406
|
+
/**
|
|
13407
|
+
* Lazily-built, stable capability object handed to observers. Bound to
|
|
13408
|
+
* `this`; constructed once so observers can rely on referential identity.
|
|
13409
|
+
*/
|
|
13410
|
+
_sessionControls = null;
|
|
13382
13411
|
startTime;
|
|
13383
13412
|
endTime;
|
|
13384
13413
|
_secondsRemaining;
|
|
@@ -13438,6 +13467,9 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13438
13467
|
if (options?.initialReviewCap !== void 0) {
|
|
13439
13468
|
this._initialReviewCap = options.initialReviewCap;
|
|
13440
13469
|
}
|
|
13470
|
+
if (options?.outcomeObservers?.length) {
|
|
13471
|
+
this._outcomeObservers = [...options.outcomeObservers];
|
|
13472
|
+
}
|
|
13441
13473
|
this.log(`Session constructed:
|
|
13442
13474
|
startTime: ${this.startTime}
|
|
13443
13475
|
endTime: ${this.endTime}
|
|
@@ -13565,6 +13597,7 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13565
13597
|
if (opts.minFollowUpCards !== void 0) return true;
|
|
13566
13598
|
if (opts.mode && opts.mode !== "replace") return true;
|
|
13567
13599
|
if (opts.hints && Object.keys(opts.hints).length > 0) return true;
|
|
13600
|
+
if (opts.sessionHints !== void 0) return true;
|
|
13568
13601
|
return false;
|
|
13569
13602
|
}
|
|
13570
13603
|
/**
|
|
@@ -13593,12 +13626,13 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13593
13626
|
excludeSet.add(this.newQ.peek(0).cardID);
|
|
13594
13627
|
}
|
|
13595
13628
|
hints.excludeCards = [...excludeSet];
|
|
13596
|
-
if (opts.
|
|
13597
|
-
|
|
13598
|
-
|
|
13599
|
-
|
|
13600
|
-
|
|
13629
|
+
if (opts.sessionHints !== void 0) {
|
|
13630
|
+
this._sessionHints = opts.sessionHints;
|
|
13631
|
+
this.log(
|
|
13632
|
+
`[Replan] Session hints ${opts.sessionHints ? "set" : "cleared"}: ${JSON.stringify(opts.sessionHints)}`
|
|
13633
|
+
);
|
|
13601
13634
|
}
|
|
13635
|
+
this._applyHintsToSources(opts.hints, opts.label);
|
|
13602
13636
|
const labelTag = opts.label ? ` [${opts.label}]` : "";
|
|
13603
13637
|
this.log(
|
|
13604
13638
|
`Mid-session replan requested${labelTag} (limit: ${opts.limit ?? "default"}, mode: ${opts.mode ?? "replace"}${opts.hints ? ", with hints" : ""})`
|
|
@@ -13609,6 +13643,100 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13609
13643
|
}
|
|
13610
13644
|
await this._executeReplan(opts);
|
|
13611
13645
|
}
|
|
13646
|
+
/**
|
|
13647
|
+
* Set the session-durable scoring hints (replace semantics, no decay).
|
|
13648
|
+
*
|
|
13649
|
+
* Unlike a one-shot replan hint, these are re-merged into every pipeline
|
|
13650
|
+
* run for the rest of the session — including the initial plan when set
|
|
13651
|
+
* before `prepareSession()`, every replan, the bare auto-replans, and the
|
|
13652
|
+
* wedge-breaker. Pass `null` to clear.
|
|
13653
|
+
*
|
|
13654
|
+
* Typical callers:
|
|
13655
|
+
* - `StudySession` at session start, threading `StudySessionConfig.initHints`
|
|
13656
|
+
* (e.g. a post-lesson concept boost) — so the boost outlives the first
|
|
13657
|
+
* queue rebuild instead of being clobbered by the first auto-replan.
|
|
13658
|
+
* - A consumer view on a failure, boosting the just-failed concept tag.
|
|
13659
|
+
*
|
|
13660
|
+
* Does not itself trigger a replan; the next plan/replan picks it up.
|
|
13661
|
+
*/
|
|
13662
|
+
setSessionHints(hints) {
|
|
13663
|
+
this._sessionHints = hints;
|
|
13664
|
+
this.log(`Session hints ${hints ? "set" : "cleared"}: ${JSON.stringify(hints)}`);
|
|
13665
|
+
}
|
|
13666
|
+
/**
|
|
13667
|
+
* Read the current session-durable hints (for read-modify-write callers,
|
|
13668
|
+
* e.g. an outcome observer that clamps a compounding boost).
|
|
13669
|
+
*/
|
|
13670
|
+
getSessionHints() {
|
|
13671
|
+
return this._sessionHints;
|
|
13672
|
+
}
|
|
13673
|
+
/**
|
|
13674
|
+
* Merge `hints` into the durable session hints via the pipeline's
|
|
13675
|
+
* `mergeHints` (boosts multiply, require/exclude lists concat-dedup).
|
|
13676
|
+
* Convenience over get-then-set for the common additive case. Note the
|
|
13677
|
+
* multiplicative, no-decay semantics — clamp boost factors at the call
|
|
13678
|
+
* site if a repeatedly-emphasised tag could compound unboundedly.
|
|
13679
|
+
*/
|
|
13680
|
+
mergeSessionHints(hints) {
|
|
13681
|
+
this._sessionHints = mergeHints2([this._sessionHints, hints]) ?? null;
|
|
13682
|
+
this.log(`Session hints merged: ${JSON.stringify(this._sessionHints)}`);
|
|
13683
|
+
}
|
|
13684
|
+
/**
|
|
13685
|
+
* Merge the durable `_sessionHints` with this run's one-shot hints and
|
|
13686
|
+
* push the result to every source for consumption on the next pipeline
|
|
13687
|
+
* run. Centralised so the initial plan and all replan paths apply session
|
|
13688
|
+
* emphasis identically. No-op when there are no hints of either kind.
|
|
13689
|
+
*/
|
|
13690
|
+
_applyHintsToSources(oneShot, label) {
|
|
13691
|
+
const oneShotWithLabel = oneShot && label ? { ...oneShot, _label: label } : oneShot;
|
|
13692
|
+
const merged = mergeHints2([this._sessionHints, oneShotWithLabel]);
|
|
13693
|
+
if (!merged) return;
|
|
13694
|
+
for (const source of this.sources) {
|
|
13695
|
+
source.setEphemeralHints?.(merged);
|
|
13696
|
+
}
|
|
13697
|
+
}
|
|
13698
|
+
/**
|
|
13699
|
+
* Build (once) the stable capability object handed to outcome observers.
|
|
13700
|
+
* Methods are bound to `this`; the object identity is stable across calls
|
|
13701
|
+
* so observers may key off it.
|
|
13702
|
+
*/
|
|
13703
|
+
_getSessionControls() {
|
|
13704
|
+
if (!this._sessionControls) {
|
|
13705
|
+
this._sessionControls = {
|
|
13706
|
+
getSessionHints: () => this.getSessionHints(),
|
|
13707
|
+
setSessionHints: (h) => this.setSessionHints(h),
|
|
13708
|
+
mergeSessionHints: (h) => this.mergeSessionHints(h),
|
|
13709
|
+
requestReplan: (opts) => this.requestReplan(opts)
|
|
13710
|
+
};
|
|
13711
|
+
}
|
|
13712
|
+
return this._sessionControls;
|
|
13713
|
+
}
|
|
13714
|
+
/**
|
|
13715
|
+
* Notify registered outcome observers about a processed response.
|
|
13716
|
+
*
|
|
13717
|
+
* Only question records are surfaced (non-question dismisses are skipped).
|
|
13718
|
+
* Observers run after ELO/SRS are recorded and before navigation. Each is
|
|
13719
|
+
* awaited but isolated in try/catch — a throwing observer is logged and
|
|
13720
|
+
* skipped, never wedging the session. Keep observers cheap and `void` any
|
|
13721
|
+
* long work (e.g. a triggered replan) to avoid stalling the draw.
|
|
13722
|
+
*/
|
|
13723
|
+
async _notifyOutcomeObservers(record, currentCard, result) {
|
|
13724
|
+
if (this._outcomeObservers.length === 0) return;
|
|
13725
|
+
if (!isQuestionRecord(record)) return;
|
|
13726
|
+
const outcome = {
|
|
13727
|
+
record,
|
|
13728
|
+
card: currentCard.card,
|
|
13729
|
+
result
|
|
13730
|
+
};
|
|
13731
|
+
const controls = this._getSessionControls();
|
|
13732
|
+
for (const observer of this._outcomeObservers) {
|
|
13733
|
+
try {
|
|
13734
|
+
await observer(outcome, controls);
|
|
13735
|
+
} catch (e) {
|
|
13736
|
+
this.error("[OutcomeObserver] observer threw; ignoring", e);
|
|
13737
|
+
}
|
|
13738
|
+
}
|
|
13739
|
+
}
|
|
13612
13740
|
/**
|
|
13613
13741
|
* Run a replan, bypassing requestReplan()'s coalesce logic.
|
|
13614
13742
|
*
|
|
@@ -13636,7 +13764,7 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13636
13764
|
*/
|
|
13637
13765
|
normalizeReplanOptions(input) {
|
|
13638
13766
|
if (!input) return {};
|
|
13639
|
-
const replanKeys = ["hints", "limit", "mode", "label", "minFollowUpCards"];
|
|
13767
|
+
const replanKeys = ["hints", "sessionHints", "limit", "mode", "label", "minFollowUpCards"];
|
|
13640
13768
|
const inputKeys = Object.keys(input);
|
|
13641
13769
|
if (inputKeys.some((k) => replanKeys.includes(k))) {
|
|
13642
13770
|
return input;
|
|
@@ -13788,6 +13916,9 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13788
13916
|
const additive = options?.additive ?? false;
|
|
13789
13917
|
const newLimit = options?.limit ?? this._defaultBatchLimit;
|
|
13790
13918
|
const fetchLimit = replan ? newLimit : newLimit + this._initialReviewCap;
|
|
13919
|
+
if (!replan) {
|
|
13920
|
+
this._applyHintsToSources();
|
|
13921
|
+
}
|
|
13791
13922
|
const batches = [];
|
|
13792
13923
|
for (let i = 0; i < this.sources.length; i++) {
|
|
13793
13924
|
const source = this.sources[i];
|
|
@@ -14068,7 +14199,7 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
14068
14199
|
const studySessionItem = {
|
|
14069
14200
|
...currentCard.item
|
|
14070
14201
|
};
|
|
14071
|
-
|
|
14202
|
+
const result = await this.services.response.processResponse(
|
|
14072
14203
|
cardRecord,
|
|
14073
14204
|
cardHistory,
|
|
14074
14205
|
studySessionItem,
|
|
@@ -14080,6 +14211,8 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
14080
14211
|
maxSessionViews,
|
|
14081
14212
|
sessionViews
|
|
14082
14213
|
);
|
|
14214
|
+
await this._notifyOutcomeObservers(cardRecord, currentCard, result);
|
|
14215
|
+
return result;
|
|
14083
14216
|
}
|
|
14084
14217
|
dismissCurrentCard(action = "dismiss-success") {
|
|
14085
14218
|
if (this._currentCard) {
|