graph context: a separate marker message before the first user turn
The map picks no longer glue into the opening prompt as seed text
(owner, 2026-10-04 late). POST /api/chats accepts graphContext
{propositions}; the route resolves the picks against the live graph,
derives the reasoning chains among them (chainsForSelection →
formatChainLine), and writes a graph-context custom marker as
message[0] — before the learner's first user message, in either mode.
- Core: newGraphContextMessage (model-facing content = the
contextualization framing + proposition lines + chain lines;
details = the structured pick); toLlmMessages flattens it to a user
message like every marker, so the model reads it for free.
- View: projects to a user-side data-graph-context part.
- UI: GraphContextCard — minimal, muted, dashed, collapsed by default
(counts only); expand reveals name — statement rows and the chain
lines. Same compact-expandable pattern as the practice cards.
- Home: sends graphContext with the creation whenever picks exist;
the prompt param carries the learner's own words only.
This commit is contained in:
@@ -65,6 +65,7 @@ export interface LhMarkerMessage {
|
||||
id: string;
|
||||
role: "custom";
|
||||
customType:
|
||||
| "graph-context"
|
||||
| "probe-handoff"
|
||||
| "subagent-steer"
|
||||
| "subagent-abort"
|
||||
@@ -187,6 +188,42 @@ export function newPlanBlockMessage(
|
||||
export const PRACTICE_PROBLEM_TOOL = "problem";
|
||||
export const PRACTICE_CONCLUDE_TOOL = "conclude";
|
||||
|
||||
/** One picked proposition of the graph-context marker (the learner's map
|
||||
* pick — name + statement as the learner SAW them at pick time). */
|
||||
export interface GraphContextPick {
|
||||
id: string;
|
||||
name: string;
|
||||
statement: string;
|
||||
}
|
||||
|
||||
/** The session's map context (owner, 2026-10-04): a SEPARATE custom
|
||||
* message BEFORE the learner's first user message — the picked
|
||||
* propositions plus the reasoning chains among them (pre-formatted
|
||||
* lines, formatChainLine shape). The model reads `content` (flattened
|
||||
* to a user message by toLlmMessages like every marker); `details`
|
||||
* feeds the transcript's collapsible GraphContextCard. No more seed
|
||||
* text glued into the first prompt. */
|
||||
export function newGraphContextMessage(picks: readonly GraphContextPick[], chains: readonly string[]): LhMarkerMessage {
|
||||
const lines = [
|
||||
"Contextualization — the learner picked these propositions from their knowledge map when starting this session:",
|
||||
"",
|
||||
"Propositions:",
|
||||
...picks.map((p) => `- ${p.name}: ${p.statement}`),
|
||||
];
|
||||
if (chains.length > 0) {
|
||||
lines.push("", "Reasoning chains among them (premises → conclusion):", ...chains.map((c) => `- ${c}`));
|
||||
}
|
||||
return {
|
||||
id: newMessageId(),
|
||||
role: "custom",
|
||||
customType: "graph-context",
|
||||
content: lines.join("\n"),
|
||||
display: true,
|
||||
details: { propositions: picks, chains },
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
}
|
||||
|
||||
/** The learner's thinking submission (the practice dock's two buttons):
|
||||
* a user-register message the model reads WITH its label (hint vs
|
||||
* commit — the register is the whole difference), while `details` keeps
|
||||
|
||||
@@ -290,6 +290,17 @@ function applyResultTo(part: LhViewPart | undefined, result: ToolResultMessage):
|
||||
/** A marker's projected message (handoff/steers) or splice (plan block). */
|
||||
function projectMarker(marker: LhMarkerMessage, out: LhViewMessage[]): void {
|
||||
switch (marker.customType) {
|
||||
case "graph-context": {
|
||||
// The session's map context (owner, 2026-10-04): user-side —
|
||||
// a minimal collapsible card ABOVE the first user message;
|
||||
// never a text bubble (scaffolding, like the thinking card).
|
||||
out.push({
|
||||
id: marker.id,
|
||||
role: "user",
|
||||
parts: [{ type: "data-graph-context", id: `gc_${marker.id}`, data: marker.details }],
|
||||
});
|
||||
return;
|
||||
}
|
||||
case "probe-handoff": {
|
||||
out.push({
|
||||
id: marker.id,
|
||||
|
||||
Reference in New Issue
Block a user