dsh-diagnostic-tutor 0.1.1 → 0.2.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 +224 -59
- package/lib/api.js +178 -0
- package/lib/api.js.map +1 -1
- package/lib/block-types.js +25 -0
- package/lib/block-types.js.map +1 -0
- package/lib/client.js +9448 -1654
- package/lib/client.js.map +1 -1
- package/lib/diagnostics.js +170 -0
- package/lib/diagnostics.js.map +1 -0
- package/lib/index.js +75 -13
- package/lib/index.js.map +1 -1
- package/lib/insights.js +82 -0
- package/lib/insights.js.map +1 -0
- package/lib/interactions.js +70 -0
- package/lib/interactions.js.map +1 -0
- package/lib/journal.js +122 -0
- package/lib/journal.js.map +1 -0
- package/lib/lesson-markdown.js +72 -0
- package/lib/lesson-markdown.js.map +1 -0
- package/lib/lesson.js +152 -3
- package/lib/lesson.js.map +1 -1
- package/lib/math.js +126 -0
- package/lib/math.js.map +1 -0
- package/lib/path-api.js +140 -0
- package/lib/path-api.js.map +1 -0
- package/lib/path-runtime.js +361 -0
- package/lib/path-runtime.js.map +1 -0
- package/lib/path-tools.js +107 -0
- package/lib/path-tools.js.map +1 -0
- package/lib/path.js +179 -0
- package/lib/path.js.map +1 -0
- package/lib/plan-tools.js +89 -0
- package/lib/plan-tools.js.map +1 -0
- package/lib/plan.js +82 -0
- package/lib/plan.js.map +1 -0
- package/lib/project-session.js +48 -0
- package/lib/project-session.js.map +1 -0
- package/lib/prompt.js +4 -19
- package/lib/prompt.js.map +1 -1
- package/lib/review-sync.js +51 -0
- package/lib/review-sync.js.map +1 -0
- package/lib/review-tools.js +115 -0
- package/lib/review-tools.js.map +1 -0
- package/lib/review.js +103 -0
- package/lib/review.js.map +1 -0
- package/lib/source-schema.js +24 -0
- package/lib/source-schema.js.map +1 -0
- package/lib/source-tools.js +61 -0
- package/lib/source-tools.js.map +1 -0
- package/lib/sources.js +78 -0
- package/lib/sources.js.map +1 -0
- package/lib/state.js +148 -7
- package/lib/state.js.map +1 -1
- package/lib/tools.js +456 -40
- package/lib/tools.js.map +1 -1
- package/lib/types/api.d.ts +7 -0
- package/lib/types/api.d.ts.map +1 -1
- package/lib/types/block-types.d.ts +12 -0
- package/lib/types/block-types.d.ts.map +1 -0
- package/lib/types/contract.d.ts +33 -1
- package/lib/types/contract.d.ts.map +1 -1
- package/lib/types/diagnostics.d.ts +95 -0
- package/lib/types/diagnostics.d.ts.map +1 -0
- package/lib/types/handoff.d.ts +2 -2
- package/lib/types/index.d.ts +15 -9
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/insights.d.ts +57 -0
- package/lib/types/insights.d.ts.map +1 -0
- package/lib/types/interactions.d.ts +23 -0
- package/lib/types/interactions.d.ts.map +1 -0
- package/lib/types/journal.d.ts +57 -0
- package/lib/types/journal.d.ts.map +1 -0
- package/lib/types/lesson-markdown.d.ts +11 -0
- package/lib/types/lesson-markdown.d.ts.map +1 -0
- package/lib/types/lesson.d.ts +697 -5
- package/lib/types/lesson.d.ts.map +1 -1
- package/lib/types/math.d.ts +50 -0
- package/lib/types/math.d.ts.map +1 -0
- package/lib/types/path-api.d.ts +5 -0
- package/lib/types/path-api.d.ts.map +1 -0
- package/lib/types/path-runtime.d.ts +1558 -0
- package/lib/types/path-runtime.d.ts.map +1 -0
- package/lib/types/path-tools.d.ts +4 -0
- package/lib/types/path-tools.d.ts.map +1 -0
- package/lib/types/path.d.ts +744 -0
- package/lib/types/path.d.ts.map +1 -0
- package/lib/types/plan-tools.d.ts +4 -0
- package/lib/types/plan-tools.d.ts.map +1 -0
- package/lib/types/plan.d.ts +53 -0
- package/lib/types/plan.d.ts.map +1 -0
- package/lib/types/project-session.d.ts +33 -0
- package/lib/types/project-session.d.ts.map +1 -0
- package/lib/types/prompt.d.ts.map +1 -1
- package/lib/types/review-sync.d.ts +17 -0
- package/lib/types/review-sync.d.ts.map +1 -0
- package/lib/types/review-tools.d.ts +4 -0
- package/lib/types/review-tools.d.ts.map +1 -0
- package/lib/types/review.d.ts +65 -0
- package/lib/types/review.d.ts.map +1 -0
- package/lib/types/source-schema.d.ts +31 -0
- package/lib/types/source-schema.d.ts.map +1 -0
- package/lib/types/source-tools.d.ts +4 -0
- package/lib/types/source-tools.d.ts.map +1 -0
- package/lib/types/sources.d.ts +33 -0
- package/lib/types/sources.d.ts.map +1 -0
- package/lib/types/state.d.ts +516 -9
- package/lib/types/state.d.ts.map +1 -1
- package/lib/types/tools.d.ts +3 -1
- package/lib/types/tools.d.ts.map +1 -1
- package/lib/types/version.d.ts +11 -0
- package/lib/types/version.d.ts.map +1 -0
- package/lib/types/vocabulary.d.ts +2 -2
- package/lib/version.js +26 -0
- package/lib/version.js.map +1 -0
- package/package.json +20 -18
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
/** Validated planning operations. The Agent proposes; only UI acceptance activates a route. */
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { LessonSchema } from './lesson.js';
|
|
5
|
+
import { isKnownBlock } from './block-types.js';
|
|
6
|
+
import { activeAttempt, AssessmentSchema, briefReady, CurriculumInputSchema, emptyPath, EvidenceRefSchema, GoalBriefSchema, } from './path.js';
|
|
7
|
+
export function pathView(state, courseId, sessionId) {
|
|
8
|
+
if (!state.readCourse(courseId))
|
|
9
|
+
throw new Error('no-such-course');
|
|
10
|
+
return { ok: true, path: state.readPath(courseId) ?? emptyPath(courseId, new Date().toISOString()), run: sessionId ? state.readCourseRun(courseId, sessionId) ?? null : null, now: new Date().toISOString() };
|
|
11
|
+
}
|
|
12
|
+
export function selectedProject(state, courseId, sessionId) {
|
|
13
|
+
if (!sessionId)
|
|
14
|
+
throw new Error('missing-session-id: open a conversation to change its learning path');
|
|
15
|
+
const selected = state.resolveProject(sessionId);
|
|
16
|
+
if (selected.course?.id !== courseId || selected.selection !== 'project')
|
|
17
|
+
throw new Error('project-selection-changed: open this project in the current conversation first');
|
|
18
|
+
}
|
|
19
|
+
function evidenceRefs(state, courseId, refs) {
|
|
20
|
+
return refs.map((ref) => {
|
|
21
|
+
const node = state.readNode(ref.nodeId);
|
|
22
|
+
const entry = node?.evidence[ref.evidenceIndex];
|
|
23
|
+
if (!node || node.courseId !== courseId || !entry)
|
|
24
|
+
throw new Error('invalid-evidence-reference: use an actual observation in this project');
|
|
25
|
+
return { node, entry };
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function linkedNodes(state, courseId, route) {
|
|
29
|
+
for (const item of route.items)
|
|
30
|
+
for (const nodeId of item.nodeIds) {
|
|
31
|
+
if (state.readNode(nodeId)?.courseId !== courseId)
|
|
32
|
+
throw new Error('foreign-node-reference: planned topics can be labels; linked node IDs must exist in this project');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function currentAssessment(path) {
|
|
36
|
+
return briefReady(path.brief) && path.assessment && path.assessment.briefRevision === path.briefRevision && ['ready', 'skipped'].includes(path.assessment.status);
|
|
37
|
+
}
|
|
38
|
+
function assessmentEvidence(state, courseId, assessment) {
|
|
39
|
+
if (assessment.status === 'ready' && assessment.evidence.length === 0)
|
|
40
|
+
throw new Error('assessment-needs-evidence: self-report alone is not a diagnostic result');
|
|
41
|
+
evidenceRefs(state, courseId, assessment.evidence);
|
|
42
|
+
}
|
|
43
|
+
export async function saveBrief(state, courseId, sessionId, expectedRevision, raw) {
|
|
44
|
+
const brief = GoalBriefSchema.parse(raw);
|
|
45
|
+
return state.mutatePath(courseId, expectedRevision, (current) => {
|
|
46
|
+
selectedProject(state, courseId, sessionId);
|
|
47
|
+
return { ...current, brief, briefRevision: current.briefRevision + 1, updatedAt: new Date().toISOString() };
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
export async function saveAssessment(state, courseId, sessionId, expectedRevision, raw, allowSkip = false) {
|
|
51
|
+
const assessment = AssessmentSchema.parse(raw);
|
|
52
|
+
return state.mutatePath(courseId, expectedRevision, (current) => {
|
|
53
|
+
selectedProject(state, courseId, sessionId);
|
|
54
|
+
if (!briefReady(current.brief) || current.briefRevision !== assessment.briefRevision || assessment.sessionId !== sessionId)
|
|
55
|
+
throw new Error('stale-assessment: read the current goal brief and conversation');
|
|
56
|
+
if (assessment.status === 'skipped' && !allowSkip)
|
|
57
|
+
throw new Error('only-the-learner-can-skip-assessment');
|
|
58
|
+
if (assessment.status === 'ready' && assessment.evidence.length === 0)
|
|
59
|
+
throw new Error('assessment-needs-evidence: self-report alone is not a diagnostic result');
|
|
60
|
+
evidenceRefs(state, courseId, assessment.evidence);
|
|
61
|
+
return { ...current, assessment, assessmentRevision: current.assessmentRevision + 1, updatedAt: new Date().toISOString() };
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
export async function proposeCurriculum(state, courseId, sessionId, expectedRevision, raw) {
|
|
65
|
+
const proposal = CurriculumInputSchema.parse(raw);
|
|
66
|
+
return state.mutatePath(courseId, expectedRevision, (current) => {
|
|
67
|
+
selectedProject(state, courseId, sessionId);
|
|
68
|
+
if (!currentAssessment(current))
|
|
69
|
+
throw new Error('diagnosis-first: complete or explicitly skip the current initial assessment before proposing the route');
|
|
70
|
+
assessmentEvidence(state, courseId, current.assessment);
|
|
71
|
+
linkedNodes(state, courseId, proposal);
|
|
72
|
+
if (current.curricula.length >= 40)
|
|
73
|
+
throw new Error('curriculum-history-limit: export history before adding more versions; no versions were deleted');
|
|
74
|
+
const curriculum = { ...proposal, version: (current.curricula.at(-1)?.version ?? 0) + 1, briefRevision: current.briefRevision, assessmentRevision: current.assessmentRevision, createdAt: new Date().toISOString(), acceptedAt: null };
|
|
75
|
+
return { ...current, curricula: [...current.curricula, curriculum], updatedAt: curriculum.createdAt };
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
export async function acceptCurriculum(state, courseId, sessionId, expectedRevision, version) {
|
|
79
|
+
return state.mutatePath(courseId, expectedRevision, (current) => {
|
|
80
|
+
selectedProject(state, courseId, sessionId);
|
|
81
|
+
const route = current.curricula.find((entry) => entry.version === version);
|
|
82
|
+
if (!route || !currentAssessment(current) || route.briefRevision !== current.briefRevision || route.assessmentRevision !== current.assessmentRevision)
|
|
83
|
+
throw new Error('stale-curriculum: request a route for the current goal and assessment');
|
|
84
|
+
assessmentEvidence(state, courseId, current.assessment);
|
|
85
|
+
linkedNodes(state, courseId, route);
|
|
86
|
+
const now = new Date().toISOString();
|
|
87
|
+
return { ...current, acceptedVersion: version, curricula: current.curricula.map((entry) => entry.version === version ? { ...entry, acceptedAt: entry.acceptedAt ?? now } : entry), updatedAt: now };
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function briefContext(brief) {
|
|
91
|
+
return brief === null ? 'No goal brief saved yet.' : JSON.stringify(brief);
|
|
92
|
+
}
|
|
93
|
+
export async function reservePathRequest(state, input) {
|
|
94
|
+
const priorRequest = (path) => {
|
|
95
|
+
const prior = path?.requests.find((request) => request.id === input.operationId);
|
|
96
|
+
if (prior) {
|
|
97
|
+
selectedProject(state, input.courseId, input.sessionId);
|
|
98
|
+
if (path?.courseId !== input.courseId || prior.id !== input.operationId || prior.sessionId !== input.sessionId || prior.kind !== input.kind)
|
|
99
|
+
throw new Error('operation-id-conflict');
|
|
100
|
+
}
|
|
101
|
+
return prior;
|
|
102
|
+
};
|
|
103
|
+
const prior = priorRequest(state.readPath(input.courseId));
|
|
104
|
+
if (prior)
|
|
105
|
+
return { shouldPrompt: false, prompt: '', request: prior };
|
|
106
|
+
let replay = false;
|
|
107
|
+
let path;
|
|
108
|
+
try {
|
|
109
|
+
path = await state.mutatePath(input.courseId, input.expectedRevision, (path) => {
|
|
110
|
+
selectedProject(state, input.courseId, input.sessionId);
|
|
111
|
+
if (priorRequest(path)) {
|
|
112
|
+
replay = true;
|
|
113
|
+
return path;
|
|
114
|
+
}
|
|
115
|
+
if (!briefReady(path.brief))
|
|
116
|
+
throw new Error('missing-goal-outcome: save a purpose and an observable target first');
|
|
117
|
+
if (input.kind === 'plan' && !currentAssessment(path))
|
|
118
|
+
throw new Error('diagnosis-first');
|
|
119
|
+
return { ...path, requests: [...path.requests, { id: input.operationId, sessionId: input.sessionId, kind: input.kind, briefRevision: path.briefRevision, createdAt: new Date().toISOString(), prompted: false, reason: 'Queued for the tutor' }] };
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
if (!(error instanceof Error) || !error.message.startsWith('revision-conflict:'))
|
|
124
|
+
throw error;
|
|
125
|
+
// A competing reservation may have committed the same operation while we queued.
|
|
126
|
+
const committed = priorRequest(state.readPath(input.courseId));
|
|
127
|
+
if (!committed)
|
|
128
|
+
throw error;
|
|
129
|
+
return { shouldPrompt: false, prompt: '', request: committed };
|
|
130
|
+
}
|
|
131
|
+
const project = state.readCourse(input.courseId);
|
|
132
|
+
const prompt = input.kind === 'diagnosis'
|
|
133
|
+
? `Quick initial diagnosis for "${project.title}" (courseId=${input.courseId}). My saved goal: ${path.brief?.purpose ?? 'not saved yet'}. Read udt_path_get first.\nAsk 1-2 key questions with ask_user_question (options, plus free text when I should explain), then one or two short checks. Record actual observations with udt_map_update and save an evidence-referenced assessment with udt_path_update. If I do not know my level, help me work it out; do not dump a syllabus into the diagnosis map. When the evidence is enough, propose a complete route with udt_path_update op=propose; I will review and accept it in Learning map.`
|
|
134
|
+
: `Propose my full learning route for "${project.title}" (courseId=${input.courseId}). Read udt_path_get first, then use my goal, outcomes, deadline/time zone, weekly budget and initial assessment.\nIn udt_path_update op=propose, put the complete module/lesson outline and EVERY lesson Overview from the first lesson through the final check: observable outcomes, outline, practice, assessment method, time range and prerequisite edges. Size each lesson for my session-minutes budget when you can, and flag any lesson that genuinely needs a longer block. State assumptions and time-budget conflicts, and offer scope/time adjustments. This is a draft for me to accept in Learning map, not permission to mark mastery or pre-generate every lesson body. Keep planned topics separate from diagnosed knowledge nodes.`;
|
|
135
|
+
return { shouldPrompt: !replay, prompt, request: path.requests.find((request) => request.id === input.operationId) };
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Record that the tutor turn behind a path request failed.
|
|
139
|
+
*
|
|
140
|
+
* The browser's own session snapshot is memory-only, so it cannot explain a
|
|
141
|
+
* failed turn after a restart. This stamps the durable request record instead:
|
|
142
|
+
* only the newest prompted request from that conversation, and only while its
|
|
143
|
+
* result is still missing. A diagnosis that was already recorded, or another
|
|
144
|
+
* conversation's request, is never touched — a later unrelated agent error in
|
|
145
|
+
* the same chat must not mislabel a finished diagnosis.
|
|
146
|
+
*
|
|
147
|
+
* @param state - state handle.
|
|
148
|
+
* @param sessionId - the conversation whose turn failed.
|
|
149
|
+
* @param reason - the error message shown to the learner.
|
|
150
|
+
*/
|
|
151
|
+
export async function stampPathRequestFailure(state, sessionId, reason) {
|
|
152
|
+
const courseId = state.resolveProject(sessionId).course?.id;
|
|
153
|
+
if (courseId === undefined)
|
|
154
|
+
return;
|
|
155
|
+
for (let attempt = 0; attempt < 3; ++attempt) {
|
|
156
|
+
const path = state.readPath(courseId);
|
|
157
|
+
if (path === undefined)
|
|
158
|
+
return;
|
|
159
|
+
const request = path.requests.at(-1);
|
|
160
|
+
if (request === undefined || request.sessionId !== sessionId || !request.prompted || request.failure === reason)
|
|
161
|
+
return;
|
|
162
|
+
const resolved = request.kind === 'diagnosis'
|
|
163
|
+
? path.assessment !== null && path.assessment.status !== 'in-progress'
|
|
164
|
+
: path.curricula.some((entry) => entry.createdAt >= request.createdAt);
|
|
165
|
+
if (resolved)
|
|
166
|
+
return;
|
|
167
|
+
try {
|
|
168
|
+
await state.mutatePath(courseId, path.revision, (current) => ({
|
|
169
|
+
...current,
|
|
170
|
+
requests: current.requests.map((entry) => entry.id === request.id && entry.sessionId === sessionId ? { ...entry, failure: reason } : entry),
|
|
171
|
+
}));
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
if (!error.message.startsWith('revision-conflict'))
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
export async function stampPathRequest(state, courseId, sessionId, id, prompted, reason) {
|
|
181
|
+
// The Agent may already have updated the plan; retry a CAS stamp on latest only.
|
|
182
|
+
for (let attempt = 0; attempt < 3; ++attempt) {
|
|
183
|
+
const path = state.readPath(courseId);
|
|
184
|
+
if (!path || state.resolveProject(sessionId).course?.id !== courseId)
|
|
185
|
+
return;
|
|
186
|
+
try {
|
|
187
|
+
await state.mutatePath(courseId, path.revision, (current) => ({ ...current, requests: current.requests.map((request) => request.id === id && request.sessionId === sessionId ? { ...request, prompted, reason: reason ?? null } : request) }));
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
if (!error.message.startsWith('revision-conflict'))
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
export async function beginCourseItem(state, input) {
|
|
197
|
+
let shouldPrompt = false;
|
|
198
|
+
const now = new Date().toISOString();
|
|
199
|
+
const run = await state.mutateCourseRun(input.courseId, input.sessionId, (run) => {
|
|
200
|
+
selectedProject(state, input.courseId, input.sessionId);
|
|
201
|
+
const replay = run.attempts.find((attempt) => attempt.operations.includes(input.operationId));
|
|
202
|
+
if (replay) {
|
|
203
|
+
if (replay.version !== input.version || replay.itemId !== input.itemId)
|
|
204
|
+
throw new Error('operation-id-conflict');
|
|
205
|
+
return run;
|
|
206
|
+
}
|
|
207
|
+
const path = state.readPath(input.courseId);
|
|
208
|
+
if (!path || path.revision !== input.expectedRevision)
|
|
209
|
+
throw new Error('revision-conflict: refresh the learning path');
|
|
210
|
+
const plan = path.curricula.find((route) => route.version === input.version);
|
|
211
|
+
if (!plan?.items.some((item) => item.id === input.itemId))
|
|
212
|
+
throw new Error('no-such-course-item');
|
|
213
|
+
linkedNodes(state, input.courseId, plan);
|
|
214
|
+
const current = activeAttempt(run);
|
|
215
|
+
const continuing = current && current.version === input.version && current.itemId === input.itemId && ['requested', 'working', 'interrupted'].includes(current.status) && !input.review;
|
|
216
|
+
if (continuing) {
|
|
217
|
+
const paused = current.status === 'interrupted';
|
|
218
|
+
// A double click while a prompt is in flight is not a new teaching turn.
|
|
219
|
+
// A deliberate resume may come much later: if the learner left the
|
|
220
|
+
// conversation and came back, `prompted` is already true forever, so it
|
|
221
|
+
// must not block the follow-up. Teach-back and check-in are explicit
|
|
222
|
+
// learning actions and bypass the short cooldown once the prompt landed.
|
|
223
|
+
const inflight = current.dispatchId !== null && Date.parse(now) - Date.parse(current.updatedAt) < 3000;
|
|
224
|
+
const explicit = input.teachBack === true || input.checkin === true;
|
|
225
|
+
const cooling = !paused && (inflight || (!explicit && current.prompted && Date.parse(now) - Date.parse(current.updatedAt) < 3000));
|
|
226
|
+
if (cooling) {
|
|
227
|
+
return { ...run, attempts: run.attempts.map((attempt) => attempt.id === current.id ? { ...attempt, operations: [...attempt.operations, input.operationId] } : attempt) };
|
|
228
|
+
}
|
|
229
|
+
shouldPrompt = true;
|
|
230
|
+
return { ...run, activeAttemptId: current.id, attempts: run.attempts.map((attempt) => attempt.id === current.id ? { ...attempt, status: 'working', operations: [...attempt.operations, input.operationId], dispatchId: input.operationId, promptReason: null, updatedAt: now } : attempt), updatedAt: now };
|
|
231
|
+
}
|
|
232
|
+
if (path.acceptedVersion !== input.version || !plan.acceptedAt)
|
|
233
|
+
throw new Error('accept-the-current-route-before-starting');
|
|
234
|
+
if (!briefReady(path.brief) || plan.briefRevision !== path.briefRevision || plan.assessmentRevision !== path.assessmentRevision)
|
|
235
|
+
throw new Error('stale-curriculum: review a plan for the updated goal first');
|
|
236
|
+
const attempt = { id: randomUUID(), operationId: input.operationId, operations: [input.operationId], dispatchId: input.operationId, version: input.version, itemId: input.itemId, status: 'requested', nodeId: null, startedAt: now, updatedAt: now, prompted: false, promptReason: null, outcome: null, evidence: [], units: [] };
|
|
237
|
+
shouldPrompt = true;
|
|
238
|
+
return { ...run, activeAttemptId: attempt.id, attempts: [...run.attempts.map((entry) => ['requested', 'working'].includes(entry.status) ? { ...entry, status: 'interrupted', updatedAt: now } : entry), attempt], updatedAt: now };
|
|
239
|
+
});
|
|
240
|
+
const attempt = run.attempts.find((entry) => entry.operations.includes(input.operationId)) ?? activeAttempt(run);
|
|
241
|
+
const path = state.readPath(input.courseId);
|
|
242
|
+
const route = path.curricula.find((entry) => entry.version === attempt.version);
|
|
243
|
+
const item = route.items.find((entry) => entry.id === attempt.itemId);
|
|
244
|
+
const prompt = input.teachBack === true
|
|
245
|
+
? teachBackPrompt(input, path, route, item, attempt)
|
|
246
|
+
: input.checkin === true
|
|
247
|
+
? checkinPrompt(input, path, route, item, attempt)
|
|
248
|
+
: (attempt.units.length > 0 || attempt.status === 'interrupted' || input.resume === true)
|
|
249
|
+
? resumePrompt(input, path, route, item, attempt)
|
|
250
|
+
: startPrompt(input, path, route, item, attempt);
|
|
251
|
+
return { run, attempt, shouldPrompt, prompt };
|
|
252
|
+
}
|
|
253
|
+
function lastUnitCheck(attempt) {
|
|
254
|
+
const unit = attempt.units.at(-1);
|
|
255
|
+
if (unit === undefined)
|
|
256
|
+
return null;
|
|
257
|
+
const check = [...unit.lesson.blocks].reverse().find((block) => isKnownBlock(block) && block.type === 'check');
|
|
258
|
+
return check !== undefined && isKnownBlock(check) && check.type === 'check' ? check.content.prompt : null;
|
|
259
|
+
}
|
|
260
|
+
function lessonLine(input, route, item) {
|
|
261
|
+
return `${item.title}, lesson ${route.items.indexOf(item) + 1} of ${route.items.length} in ${route.title}.\nCourse context: courseId=${input.courseId}, version=${route.version}, itemId=${item.id}.`;
|
|
262
|
+
}
|
|
263
|
+
/** The first turn: make the chat the classroom, not a request to read the tab. */
|
|
264
|
+
function startPrompt(input, path, route, item, attempt) {
|
|
265
|
+
return `Let's start ${lessonLine(input, route, item)}\nMy goal and budget: ${briefContext(path.brief)}\nLesson Overview: ${JSON.stringify(item)}\n\nYou lead this lesson in the conversation. In the lesson tab, write only a reference snapshot of the unit you just taught; the tab is not the lecture.\n\nFirst turn:\n1. In the chat, say in one or two sentences what I will be able to do by the end of this lesson.\n2. Teach ONE small unit: a short explanation and one concrete example.\n3. Then stop and ask me ONE check question (use ask_user_question when the answer fits a short card), and wait for my answer. Never dump the whole lesson in one turn.\n\nRead udt_path_get. Diagnose relevant knowledge before teaching; reuse a diagnosed node or add a justified node with udt_map_update, never plant the course outline in the diagnosis graph. Explicitly bind the chosen node using udt_course_run_update(action=bind-node, attemptId=${attempt.id}), then write the same small unit with udt_lesson_update(attemptId=${attempt.id}) including its check block. Update actual evidence after my response. Finish a course item only using udt_course_run_update(action=complete, attemptId=${attempt.id}) with check/transfer evidence and a reason. After completion, compare that evidence with remaining prerequisites, outcomes and time budget; if it materially changes the route, reread udt_path_get and propose a revised draft with a concrete changeReason. Do not create a redundant revision when the route still fits. Explain the suggestion; the learner must accept any proposal. Completion is not mastery and never auto-starts another lesson.`;
|
|
266
|
+
}
|
|
267
|
+
/** Returning after a break: reconnect through the conversation, not by restarting. */
|
|
268
|
+
function resumePrompt(input, path, route, item, attempt) {
|
|
269
|
+
const last = attempt.units.at(-1);
|
|
270
|
+
const lastTitle = last?.lesson.title ?? item.title;
|
|
271
|
+
const check = lastUnitCheck(attempt);
|
|
272
|
+
return `Let's continue ${lessonLine(input, route, item)}\nThis is a resume, not a restart. Attempt id: ${attempt.id}. Already written units: ${attempt.units.length}. Last unit: "${lastTitle}".${check === null ? '' : ` Last check I was asked: "${check}".`}\nMy goal and budget: ${briefContext(path.brief)}\n\nRead udt_path_get and the conversation history. Do this in the conversation:\n1. In one sentence, say where we stopped, using the context you already have.\n2. Ask me ONE short check-in question about the last unit (prefer ask_user_question). If I already answered that check in this conversation, acknowledge it briefly and ask whether to continue instead.\n3. Wait for my answer. Do not write a new unit, do not repeat old teaching, and do not restart this lesson until I answer.\n\nWhen I answer, append the next small unit with udt_lesson_update(attemptId=${attempt.id}); never replace or rewrite earlier units. Keep teaching one small unit at a time in the chat, ending with one check, and use the lesson tab only as the reference snapshot.`;
|
|
273
|
+
}
|
|
274
|
+
/** The learner explains the unit back; the tutor must diagnose, not lecture. */
|
|
275
|
+
function teachBackPrompt(input, path, route, item, attempt) {
|
|
276
|
+
const last = attempt.units.at(-1);
|
|
277
|
+
const lastTitle = last?.lesson.title ?? item.title;
|
|
278
|
+
const check = lastUnitCheck(attempt);
|
|
279
|
+
const node = attempt.nodeId === null ? '' : ` Bound node id: ${attempt.nodeId}.`;
|
|
280
|
+
return `Let's do a teach-back of ${lessonLine(input, route, item)}\nAttempt id: ${attempt.id}. Last unit: "${lastTitle}".${check === null ? '' : ` The check I was asked: "${check}".`}${node}\nMy goal and budget: ${briefContext(path.brief)}\n\nDo NOT explain the unit again first. Invite me to explain it in my own words, as if I were teaching it to you. When I answer, do exactly this:\n1. Name one thing I got right, specifically.\n2. Name one specific gap, fuzzy phrase, or misconception — quote my words when you can.\n3. Ask ONE follow-up question: either "why does that work?" or a new-context application. Wait for my answer.\n4. Record what I showed with udt_map_update(op=add-evidence, ${attempt.nodeId === null ? "nodeId=<the bound node>" : `nodeId=${attempt.nodeId}`}, evidenceKind='explanation', evidenceNote=<what I actually explained>, readiness=<advance|advance-with-caution|review-first|more-practice>). Explanation alone never sets state to confirmed.\n\nDo not write a new lesson unit and do not continue with new material in this turn. The point is to make my thinking visible, not to deliver more content. After the follow-up, say in one sentence what we should do next and wait for me.`;
|
|
281
|
+
}
|
|
282
|
+
/** A deliberate pause-and-check before continuing. */
|
|
283
|
+
function checkinPrompt(input, path, route, item, attempt) {
|
|
284
|
+
const check = lastUnitCheck(attempt);
|
|
285
|
+
return `Let's check in on ${lessonLine(input, route, item)}\nAttempt id: ${attempt.id}. Written units: ${attempt.units.length}.${check === null ? '' : ` Last check I was asked: "${check}".`}\n\nPause new teaching. Read udt_path_get and the conversation history. Ask me ONE short check-in question about the current unit (prefer ask_user_question), then wait for my answer. Do not write a new unit and do not continue with new material until I answer.`;
|
|
286
|
+
}
|
|
287
|
+
/** Mark the current attempt paused without ending it. `interrupted` is the existing attempt state. */
|
|
288
|
+
export async function pauseCourseItem(state, input) {
|
|
289
|
+
selectedProject(state, input.courseId, input.sessionId);
|
|
290
|
+
const path = state.readPath(input.courseId);
|
|
291
|
+
if (path === undefined || path.revision !== input.expectedRevision)
|
|
292
|
+
throw new Error('revision-conflict: refresh the learning path');
|
|
293
|
+
const now = new Date().toISOString();
|
|
294
|
+
await state.mutateCourseRun(input.courseId, input.sessionId, (run) => {
|
|
295
|
+
const current = activeAttempt(run);
|
|
296
|
+
if (current === undefined || !['requested', 'working'].includes(current.status))
|
|
297
|
+
throw new Error('no-active-lesson: there is no lesson to pause');
|
|
298
|
+
return { ...run, attempts: run.attempts.map((attempt) => attempt.id === current.id ? { ...attempt, status: 'interrupted', dispatchId: null, updatedAt: now } : attempt), updatedAt: now };
|
|
299
|
+
});
|
|
300
|
+
return pathView(state, input.courseId, input.sessionId);
|
|
301
|
+
}
|
|
302
|
+
export async function stampCoursePrompt(state, input, attemptId, prompted, reason) {
|
|
303
|
+
if (!state.readCourse(input.courseId) || state.resolveProject(input.sessionId).course?.id !== input.courseId)
|
|
304
|
+
return;
|
|
305
|
+
await state.mutateCourseRun(input.courseId, input.sessionId, (run) => ({ ...run, attempts: run.attempts.map((entry) => entry.id === attemptId && entry.dispatchId === input.operationId ? { ...entry, dispatchId: null, prompted, promptReason: reason ?? null, updatedAt: new Date().toISOString() } : entry) }));
|
|
306
|
+
}
|
|
307
|
+
export function requireAttempt(state, courseId, sessionId, attemptId) {
|
|
308
|
+
selectedProject(state, courseId, sessionId);
|
|
309
|
+
const attempt = activeAttempt(state.readCourseRun(courseId, sessionId));
|
|
310
|
+
if (!attempt || attempt.id !== attemptId || !['requested', 'working'].includes(attempt.status))
|
|
311
|
+
throw new Error('stale-attempt: read udt_path_get; this attempt is no longer active');
|
|
312
|
+
return attempt;
|
|
313
|
+
}
|
|
314
|
+
export async function bindCourseNode(state, courseId, sessionId, attemptId, nodeId) {
|
|
315
|
+
if (state.readNode(nodeId)?.courseId !== courseId)
|
|
316
|
+
throw new Error('bind-an-existing-diagnosed-node-in-this-project');
|
|
317
|
+
await state.mutateCourseRun(courseId, sessionId, (run) => {
|
|
318
|
+
requireAttempt(state, courseId, sessionId, attemptId);
|
|
319
|
+
return { ...run, attempts: run.attempts.map((entry) => entry.id === attemptId ? { ...entry, nodeId, status: 'working', updatedAt: new Date().toISOString() } : entry) };
|
|
320
|
+
});
|
|
321
|
+
requireAttempt(state, courseId, sessionId, attemptId);
|
|
322
|
+
await state.startFocus(courseId, nodeId, new Date().toISOString(), sessionId);
|
|
323
|
+
}
|
|
324
|
+
function teachingSnapshot(run, attemptId, lesson) {
|
|
325
|
+
return { ...run, attempts: run.attempts.map((entry) => entry.id === attemptId ? { ...entry, status: 'working', updatedAt: lesson.updatedAt, units: [...entry.units, { id: randomUUID(), writtenAt: lesson.updatedAt, lesson }] } : entry) };
|
|
326
|
+
}
|
|
327
|
+
export async function recordCourseTeaching(state, courseId, sessionId, attemptId, lesson) {
|
|
328
|
+
return state.mutateCourseRun(courseId, sessionId, (run) => {
|
|
329
|
+
const attempt = requireAttempt(state, courseId, sessionId, attemptId);
|
|
330
|
+
if (attempt.nodeId !== lesson.nodeId || lesson.courseId !== courseId || state.readNode(lesson.nodeId)?.courseId !== courseId)
|
|
331
|
+
throw new Error('bind-the-node-before-writing-planned-teaching');
|
|
332
|
+
return teachingSnapshot(run, attemptId, LessonSchema.parse(lesson));
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
/** Merge against the latest committed unit while holding the run/project queue. The builder must not enqueue writes. */
|
|
336
|
+
export async function writeCourseTeaching(state, courseId, sessionId, attemptId, nodeId, build) {
|
|
337
|
+
const run = await state.mutateCourseRun(courseId, sessionId, (run) => {
|
|
338
|
+
const attempt = requireAttempt(state, courseId, sessionId, attemptId);
|
|
339
|
+
if (attempt.nodeId !== nodeId || state.readNode(nodeId)?.courseId !== courseId)
|
|
340
|
+
throw new Error('bind-the-node-before-writing-planned-teaching');
|
|
341
|
+
const existing = [...attempt.units].reverse().find((unit) => unit.lesson.nodeId === nodeId)?.lesson;
|
|
342
|
+
const lesson = LessonSchema.parse(build(existing));
|
|
343
|
+
if (lesson.nodeId !== nodeId || lesson.courseId !== courseId)
|
|
344
|
+
throw new Error('bind-the-node-before-writing-planned-teaching');
|
|
345
|
+
return teachingSnapshot(run, attemptId, lesson);
|
|
346
|
+
});
|
|
347
|
+
return run.attempts.find((entry) => entry.id === attemptId).units.at(-1).lesson;
|
|
348
|
+
}
|
|
349
|
+
export async function completeCourseItem(state, courseId, sessionId, attemptId, reason, rawRefs) {
|
|
350
|
+
const refs = z.array(EvidenceRefSchema).min(1).max(40).parse(rawRefs);
|
|
351
|
+
if (!reason.trim() || reason.length > 2000)
|
|
352
|
+
throw new Error('completion-needs-an-observed-reason');
|
|
353
|
+
return state.mutateCourseRun(courseId, sessionId, (run) => {
|
|
354
|
+
const attempt = requireAttempt(state, courseId, sessionId, attemptId);
|
|
355
|
+
const observations = evidenceRefs(state, courseId, refs);
|
|
356
|
+
if (!observations.every(({ node, entry }) => node.id === attempt.nodeId && entry.sessionId === sessionId && entry.attemptId === attemptId && Date.parse(entry.at) >= Date.parse(attempt.startedAt)) || !observations.some(({ entry }) => ['check', 'transfer'].includes(entry.kind)))
|
|
357
|
+
throw new Error('completion-needs-check-or-transfer-evidence-from-this-attempt');
|
|
358
|
+
return { ...run, attempts: run.attempts.map((entry) => entry.id === attemptId ? { ...entry, status: 'completed', evidence: refs, outcome: reason, updatedAt: new Date().toISOString() } : entry) };
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
//# sourceMappingURL=path-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-runtime.js","sourceRoot":"","sources":["../src/path-runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/** Model-facing planning tools: draft routes never activate themselves. */
|
|
2
|
+
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { AssessmentSchema, CurriculumInputSchema, GoalBriefSchema, EvidenceRefSchema } from './path.js';
|
|
5
|
+
import { bindCourseNode, completeCourseItem, pathView, proposeCurriculum, saveAssessment, saveBrief, } from './path-runtime.js';
|
|
6
|
+
/** Project supported schema shapes into the host DSL; semantic constraints remain Zod-validated. */
|
|
7
|
+
function toolSpec(schema) {
|
|
8
|
+
const project = (value) => {
|
|
9
|
+
const union = (value.anyOf ?? value.oneOf);
|
|
10
|
+
if (union)
|
|
11
|
+
return { oneOf: union.map(project) };
|
|
12
|
+
if (value.type === 'object') {
|
|
13
|
+
const required = (value.required ?? []);
|
|
14
|
+
const properties = {};
|
|
15
|
+
for (const [key, child] of Object.entries((value.properties ?? {}))) {
|
|
16
|
+
properties[key] = { ...project(child), ...(required.includes(key) ? { required: true } : {}) };
|
|
17
|
+
}
|
|
18
|
+
return { type: 'object', additionalProperties: false, properties };
|
|
19
|
+
}
|
|
20
|
+
if (value.type === 'array')
|
|
21
|
+
return { type: 'array', items: project(value.items) };
|
|
22
|
+
if (!['string', 'number', 'integer', 'boolean', 'null'].includes(value.type))
|
|
23
|
+
throw new Error('Unsupported planning tool schema');
|
|
24
|
+
return { type: value.type, ...(value.enum ? { enum: value.enum } : {}) };
|
|
25
|
+
};
|
|
26
|
+
return project(z.toJSONSchema(schema));
|
|
27
|
+
}
|
|
28
|
+
const output = {
|
|
29
|
+
schema: { type: 'object', additionalProperties: true },
|
|
30
|
+
render: (_args, value) => [{ type: 'text', text: JSON.stringify(value) }],
|
|
31
|
+
};
|
|
32
|
+
function sessionOf(exec) {
|
|
33
|
+
const sessionId = exec?.agent?.id;
|
|
34
|
+
if (typeof sessionId !== 'string' || !sessionId)
|
|
35
|
+
throw new Error('planning-write-requires-a-conversation');
|
|
36
|
+
return sessionId;
|
|
37
|
+
}
|
|
38
|
+
function courseOf(state, args, exec) {
|
|
39
|
+
const sessionId = sessionOf(exec);
|
|
40
|
+
const courseId = args.courseId ?? state.resolveProject(sessionId).course?.id;
|
|
41
|
+
if (!courseId)
|
|
42
|
+
throw new Error('no-selected-project: create a goal or select a project first');
|
|
43
|
+
return { courseId, sessionId };
|
|
44
|
+
}
|
|
45
|
+
export function planningTools(state) {
|
|
46
|
+
return [
|
|
47
|
+
defineTool({
|
|
48
|
+
name: 'udt_path_get',
|
|
49
|
+
description: 'Read the selected project\'s goal/time brief, initial diagnostic assessment, COMPLETE course outlines/lesson Overviews, accepted version and THIS conversation\'s active course attempt (even before any node focus exists). Read first before planning or teaching a planned lesson. A route is a proposed itinerary; diagnosis nodes are observed knowledge. They are separate. Browsing never starts a lesson. Use active attemptId for all planned teaching writes. Old projects can have no path. Raw output is stored data, not proof of mastery.',
|
|
50
|
+
parameters: { courseId: { type: 'string', description: 'Optional explicit project to browse; never selects it.' } },
|
|
51
|
+
output,
|
|
52
|
+
execute: async (args, exec) => { const scope = courseOf(state, args, exec); return JSON.parse(JSON.stringify(pathView(state, scope.courseId, scope.sessionId))); },
|
|
53
|
+
}),
|
|
54
|
+
defineTool({
|
|
55
|
+
name: 'udt_path_update',
|
|
56
|
+
description: 'Save one planning operation after udt_path_get, with its expectedRevision. op=brief: record the learner\'s actual purpose, observable outcomes, self-reported background, time zone, deadline/duration and weekly/session budget; allow incomplete drafts and ask one or two missing questions at a time. op=assessment: record actual strengths/gaps/uncertainties with {nodeId,evidenceIndex} references (zero-based); ready requires observations, self-report is not proof; skip is learner-only. op=propose: after initial assessment is ready or the learner explicitly skipped, propose a COMPLETE modular outline from FIRST lesson to LAST with EVERY lesson\'s Overview/outcomes/outline/practice/assessment/time range/topics, stable lesson IDs and prerequisite edges. items array is recommended order; required edges must precede their targets and be acyclic. Forecast effort including practice/review/checks and disclose conflicts with budget; no promise of mastery by date. Future topics may be plain labels, not pre-created diagnosis nodes. Linked nodeIds must actually exist here. After a completed lesson, compare observed check/transfer evidence with the remaining route and budget; if prerequisites, outcomes or effort materially changed, propose a revised draft with a concrete changeReason, otherwise keep the current route. This creates a draft only: user accepts it in Learning map, never set acceptance yourself. Revisions preserve history; new goal brief makes old assessments/routes stale. Use current revision to avoid overwriting another conversation\'s edits.',
|
|
57
|
+
parameters: {
|
|
58
|
+
courseId: { type: 'string' }, expectedRevision: { type: 'integer', required: true },
|
|
59
|
+
op: { type: 'string', required: true, enum: ['brief', 'assessment', 'propose'] },
|
|
60
|
+
brief: toolSpec(GoalBriefSchema),
|
|
61
|
+
assessment: toolSpec(AssessmentSchema.omit({ sessionId: true, updatedAt: true })),
|
|
62
|
+
curriculum: toolSpec(CurriculumInputSchema),
|
|
63
|
+
},
|
|
64
|
+
output,
|
|
65
|
+
execute: async (args, exec) => {
|
|
66
|
+
const input = args;
|
|
67
|
+
if (!Number.isInteger(input.expectedRevision) || input.expectedRevision < 0)
|
|
68
|
+
throw new Error('expectedRevision must be a nonnegative integer');
|
|
69
|
+
const { courseId, sessionId } = courseOf(state, input, exec);
|
|
70
|
+
if (input.op === 'brief')
|
|
71
|
+
await saveBrief(state, courseId, sessionId, input.expectedRevision, input.brief);
|
|
72
|
+
else if (input.op === 'assessment')
|
|
73
|
+
await saveAssessment(state, courseId, sessionId, input.expectedRevision, { ...input.assessment, sessionId, updatedAt: new Date().toISOString() });
|
|
74
|
+
else if (input.op === 'propose')
|
|
75
|
+
await proposeCurriculum(state, courseId, sessionId, input.expectedRevision, input.curriculum);
|
|
76
|
+
else
|
|
77
|
+
throw new Error('unknown planning operation');
|
|
78
|
+
return JSON.parse(JSON.stringify(pathView(state, courseId, sessionId)));
|
|
79
|
+
},
|
|
80
|
+
}),
|
|
81
|
+
defineTool({
|
|
82
|
+
name: 'udt_course_run_update',
|
|
83
|
+
description: 'Update THIS conversation\'s active planned course attempt, after udt_path_get. action=bind-node: explicitly attach an existing diagnosed node in the project to active attemptId (never fabricate a node from the syllabus); this records focus for teaching. Then use udt_lesson_update with that attemptId, which preserves its own teaching/history instead of overwriting another conversation. action=complete: record a reason and references to actual check/transfer evidence on the bound node, observed during this attempt. Completing a lesson is not mastery; this does NOT mark knowledge confirmed or auto-start the next item. Stale/replaced/completed attempts are refused. Browse/accept/start route actions belong to the learner UI, not this tool.',
|
|
84
|
+
parameters: {
|
|
85
|
+
courseId: { type: 'string' }, attemptId: { type: 'string', required: true },
|
|
86
|
+
action: { type: 'string', required: true, enum: ['bind-node', 'complete'] }, nodeId: { type: 'string' },
|
|
87
|
+
reason: { type: 'string' }, evidence: { type: 'array', items: toolSpec(EvidenceRefSchema) },
|
|
88
|
+
},
|
|
89
|
+
output,
|
|
90
|
+
execute: async (args, exec) => {
|
|
91
|
+
const input = args;
|
|
92
|
+
const { courseId, sessionId } = courseOf(state, input, exec);
|
|
93
|
+
if (input.action === 'bind-node') {
|
|
94
|
+
if (!input.nodeId)
|
|
95
|
+
throw new Error('nodeId is required');
|
|
96
|
+
await bindCourseNode(state, courseId, sessionId, input.attemptId, input.nodeId);
|
|
97
|
+
}
|
|
98
|
+
else if (input.action === 'complete')
|
|
99
|
+
await completeCourseItem(state, courseId, sessionId, input.attemptId, input.reason ?? '', input.evidence);
|
|
100
|
+
else
|
|
101
|
+
throw new Error('unknown course attempt action');
|
|
102
|
+
return JSON.parse(JSON.stringify(pathView(state, courseId, sessionId)));
|
|
103
|
+
},
|
|
104
|
+
}),
|
|
105
|
+
];
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=path-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-tools.js","sourceRoot":"","sources":["../src/path-tools.ts"],"names":[],"mappings":"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"}
|