incremnt 0.7.1 → 0.7.2
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/package.json +1 -1
- package/src/coach-facts.js +14 -1
- package/src/contract.js +1 -1
- package/src/format.js +44 -1
- package/src/openrouter.js +25 -20
- package/src/plan-comparison.js +245 -0
- package/src/prompt-changelog.js +94 -0
- package/src/queries.js +830 -179
- package/src/summary-evals.js +522 -9
- package/src/sync-service.js +115 -6
package/src/sync-service.js
CHANGED
|
@@ -690,6 +690,42 @@ function parseLimit(value, { defaultValue, max }) {
|
|
|
690
690
|
return Number.isFinite(parsed) && parsed > 0 ? Math.min(parsed, max) : defaultValue;
|
|
691
691
|
}
|
|
692
692
|
|
|
693
|
+
function coachObservationSourceTriggerForScoreSnapshots(snapshots) {
|
|
694
|
+
if (!Array.isArray(snapshots)) return undefined;
|
|
695
|
+
const reasons = snapshots.map((snapshot) => snapshot?.triggerReason);
|
|
696
|
+
if (reasons.length === 0 || reasons.some((reason) => !reason)) return undefined;
|
|
697
|
+
if (reasons.includes('sessionSave')) return 'session_completed';
|
|
698
|
+
if (reasons.every((reason) => reason === 'historicalBackfill')) {
|
|
699
|
+
return 'manual_backfill';
|
|
700
|
+
}
|
|
701
|
+
if (reasons.every((reason) => reason === 'dailyRefresh')) {
|
|
702
|
+
return 'daily_refresh';
|
|
703
|
+
}
|
|
704
|
+
return undefined;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
function coachObservationGenerationMetadata(result, sourceTrigger) {
|
|
708
|
+
return {
|
|
709
|
+
attempted: true,
|
|
710
|
+
generated: Number(result?.generated ?? 0),
|
|
711
|
+
persisted: Number(result?.persisted ?? 0),
|
|
712
|
+
skippedReason: result?.skippedReason ?? null,
|
|
713
|
+
sourceTrigger: sourceTrigger ?? null
|
|
714
|
+
};
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
function normalizeAskCoachObservationFollowUp(value) {
|
|
718
|
+
if (!value || typeof value !== 'object') return null;
|
|
719
|
+
const id = String(value.id ?? '').trim();
|
|
720
|
+
return id ? { id: id.slice(0, 128) } : null;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
function selectAskCoachObservationFollowUp(requested, observations) {
|
|
724
|
+
if (!requested) return null;
|
|
725
|
+
return (Array.isArray(observations) ? observations : [])
|
|
726
|
+
.find((observation) => String(observation?.id ?? '') === requested.id);
|
|
727
|
+
}
|
|
728
|
+
|
|
693
729
|
function routeRequest(url, method) {
|
|
694
730
|
const pathname = url.pathname;
|
|
695
731
|
|
|
@@ -1064,7 +1100,13 @@ function routeRequest(url, method) {
|
|
|
1064
1100
|
}
|
|
1065
1101
|
|
|
1066
1102
|
if (pathname === '/cli/coach-observations/current') {
|
|
1067
|
-
return {
|
|
1103
|
+
return {
|
|
1104
|
+
command: 'coach-observations-current',
|
|
1105
|
+
options: {
|
|
1106
|
+
limit: url.searchParams.get('limit') ?? undefined,
|
|
1107
|
+
refresh: url.searchParams.get('refresh') ?? undefined
|
|
1108
|
+
}
|
|
1109
|
+
};
|
|
1068
1110
|
}
|
|
1069
1111
|
|
|
1070
1112
|
{
|
|
@@ -2037,6 +2079,7 @@ export function createSyncServiceRequestHandler({
|
|
|
2037
2079
|
insertScoreSnapshotsForAccount = null,
|
|
2038
2080
|
listScoreSnapshotsForAccount = null,
|
|
2039
2081
|
getCurrentWeeklyScoreDigestForAccount = null,
|
|
2082
|
+
generateCoachObservationsForAccount = null,
|
|
2040
2083
|
listCurrentCoachObservationsForAccount = null,
|
|
2041
2084
|
markCoachObservationSeenForAccount = null,
|
|
2042
2085
|
dismissCoachObservationForAccount = null,
|
|
@@ -2906,6 +2949,22 @@ export function createSyncServiceRequestHandler({
|
|
|
2906
2949
|
return;
|
|
2907
2950
|
}
|
|
2908
2951
|
const result = await insertScoreSnapshotsForAccount(account, body.snapshots);
|
|
2952
|
+
if (generateCoachObservationsForAccount) {
|
|
2953
|
+
const sourceTrigger = coachObservationSourceTriggerForScoreSnapshots(body.snapshots);
|
|
2954
|
+
try {
|
|
2955
|
+
const generationResult = await generateCoachObservationsForAccount(account, { sourceTrigger });
|
|
2956
|
+
result.coachObservations = coachObservationGenerationMetadata(generationResult, sourceTrigger);
|
|
2957
|
+
} catch (error) {
|
|
2958
|
+
console.error('Coach observation generation after score upload failed:', error.message);
|
|
2959
|
+
result.coachObservations = {
|
|
2960
|
+
attempted: true,
|
|
2961
|
+
generated: 0,
|
|
2962
|
+
persisted: 0,
|
|
2963
|
+
skippedReason: 'generation_failed',
|
|
2964
|
+
sourceTrigger
|
|
2965
|
+
};
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2909
2968
|
json(response, 200, result);
|
|
2910
2969
|
return;
|
|
2911
2970
|
} catch (error) {
|
|
@@ -3549,16 +3608,62 @@ export function createSyncServiceRequestHandler({
|
|
|
3549
3608
|
methodNotAllowed(response, 'Use GET for /cli/coach-observations/current.');
|
|
3550
3609
|
return;
|
|
3551
3610
|
}
|
|
3611
|
+
if (route.options.refresh && route.options.refresh !== 'morning_open') {
|
|
3612
|
+
badRequest(response, 'Unsupported coach observations refresh value.');
|
|
3613
|
+
return;
|
|
3614
|
+
}
|
|
3552
3615
|
if (!listCurrentCoachObservationsForAccount) {
|
|
3553
3616
|
json(response, 503, { error: 'Coach observations not available' });
|
|
3554
3617
|
return;
|
|
3555
3618
|
}
|
|
3556
3619
|
try {
|
|
3557
3620
|
const limit = parseLimit(route.options.limit, { defaultValue: 5, max: 20 });
|
|
3621
|
+
let refresh = null;
|
|
3622
|
+
if (route.options.refresh === 'morning_open') {
|
|
3623
|
+
const writeAccount = writeAuthenticator
|
|
3624
|
+
? await writeAuthenticator(requestToken)
|
|
3625
|
+
: requestToken === token
|
|
3626
|
+
? account
|
|
3627
|
+
: null;
|
|
3628
|
+
if (!writeAccount) {
|
|
3629
|
+
unauthorized(response, request);
|
|
3630
|
+
return;
|
|
3631
|
+
}
|
|
3632
|
+
const sourceTrigger = 'daily_refresh';
|
|
3633
|
+
if (generateCoachObservationsForAccount) {
|
|
3634
|
+
try {
|
|
3635
|
+
const generationResult = await generateCoachObservationsForAccount(writeAccount, {
|
|
3636
|
+
sourceTrigger,
|
|
3637
|
+
refresh: route.options.refresh
|
|
3638
|
+
});
|
|
3639
|
+
refresh = coachObservationGenerationMetadata(generationResult, sourceTrigger);
|
|
3640
|
+
} catch (error) {
|
|
3641
|
+
console.error('Coach observation generation on morning open failed:', error.message);
|
|
3642
|
+
refresh = {
|
|
3643
|
+
attempted: true,
|
|
3644
|
+
generated: 0,
|
|
3645
|
+
persisted: 0,
|
|
3646
|
+
skippedReason: 'generation_failed',
|
|
3647
|
+
sourceTrigger
|
|
3648
|
+
};
|
|
3649
|
+
}
|
|
3650
|
+
} else {
|
|
3651
|
+
refresh = {
|
|
3652
|
+
attempted: false,
|
|
3653
|
+
generated: 0,
|
|
3654
|
+
persisted: 0,
|
|
3655
|
+
skippedReason: 'generation_unavailable',
|
|
3656
|
+
sourceTrigger
|
|
3657
|
+
};
|
|
3658
|
+
}
|
|
3659
|
+
}
|
|
3558
3660
|
const observations = await listCurrentCoachObservationsForAccount(account, {
|
|
3559
3661
|
limit
|
|
3560
3662
|
});
|
|
3561
|
-
json(response, 200, {
|
|
3663
|
+
json(response, 200, {
|
|
3664
|
+
observations: observations ?? [],
|
|
3665
|
+
...(refresh ? { refresh } : {})
|
|
3666
|
+
});
|
|
3562
3667
|
} catch (err) {
|
|
3563
3668
|
console.error('Coach observations read error:', err.message);
|
|
3564
3669
|
json(response, 500, { error: 'Failed to read coach observations' });
|
|
@@ -4274,6 +4379,7 @@ export function createSyncServiceRequestHandler({
|
|
|
4274
4379
|
|
|
4275
4380
|
const queries = await import('./queries.js');
|
|
4276
4381
|
const exclude = parseExclude(body?.exclude);
|
|
4382
|
+
const requestedCoachObservation = normalizeAskCoachObservationFollowUp(body?.coachObservation);
|
|
4277
4383
|
let coachFacts = [];
|
|
4278
4384
|
if (listCoachFactsForAccount) {
|
|
4279
4385
|
try {
|
|
@@ -4303,15 +4409,18 @@ export function createSyncServiceRequestHandler({
|
|
|
4303
4409
|
let coachObservations = [];
|
|
4304
4410
|
if (listCurrentCoachObservationsForAccount) {
|
|
4305
4411
|
try {
|
|
4306
|
-
coachObservations = await listCurrentCoachObservationsForAccount(account, { limit: 3 }) ?? [];
|
|
4412
|
+
coachObservations = await listCurrentCoachObservationsForAccount(account, { limit: requestedCoachObservation ? 10 : 3 }) ?? [];
|
|
4307
4413
|
} catch (observationErr) {
|
|
4308
4414
|
console.error('Coach observations read error (ask):', observationErr.message);
|
|
4309
4415
|
}
|
|
4310
4416
|
}
|
|
4417
|
+
const coachObservationFollowUp = selectAskCoachObservationFollowUp(requestedCoachObservation, coachObservations);
|
|
4311
4418
|
|
|
4312
|
-
const routedContext = queries.
|
|
4313
|
-
? queries.
|
|
4314
|
-
:
|
|
4419
|
+
const routedContext = coachObservationFollowUp && queries.askObservationFollowUpContext
|
|
4420
|
+
? queries.askObservationFollowUpContext(snapshot, question, coachObservationFollowUp, { exclude, coachFacts })
|
|
4421
|
+
: queries.askRoutedContext
|
|
4422
|
+
? queries.askRoutedContext(snapshot, question, { exclude, coachFacts, coachObservations })
|
|
4423
|
+
: { context: queries.askContext(snapshot, { exclude }), metadata: { route: 'legacy' } };
|
|
4315
4424
|
const persistedKind = persistedConversation?.kind ?? (conversationId?.startsWith('weekly-checkin:') ? 'weekly-checkin' : 'ask');
|
|
4316
4425
|
const incrementScorePrelude = formatIncrementScorePrelude(scoreSnapshots);
|
|
4317
4426
|
|