Compaction fixes (observed in a real long run): - the summary message's zeroed tokens froze the goal counter at its pre-compaction value; segments now close with the previously displayed total as a continuity floor - audits and continuations after a summary tail now take execution params (provider/model/agent/variant) from the newest non-summary assistant turn instead of inheriting agent 'compaction' and the summarize model File-backed objectives: - the objective text lives in <data-dir>/goals/<sessionId>.md, keyed by session id (one goal per session, a new goal overwrites the file); metadata carries only an objectiveFile flag so session.updated fanout stays light, and never a path — ids are pattern-validated before any filesystem access - limit raised to 5000 chars, no snapshot field: the UI fetches content via PUT/GET/DELETE /api/goals/objective/:sessionId (behind the blanket /api auth gate), writes the file before stamping metadata, and falls back to an inline objective when the write fails - the loop reads the file fresh on every tick, so objectives are live-editable mid-goal; a missing file falls back to the inline text - scheduled goal tasks write the objective file server-side; VS Code degrades to the audit note (route unavailable there by design)
37 lines
1.4 KiB
JavaScript
37 lines
1.4 KiB
JavaScript
import { deleteObjective, readObjective, writeObjective } from './objectives.js';
|
|
|
|
// OpenChamber-owned routes for file-backed goal objectives, keyed by session
|
|
// id (one goal per session; a new goal overwrites the old file). The UI
|
|
// writes the objective file before stamping the goal metadata (which only
|
|
// carries an `objectiveFile: true` flag), reads it back for display, and
|
|
// deletes it when the goal is removed.
|
|
export function registerSessionGoalRoutes(app) {
|
|
app.put('/api/goals/objective/:sessionId', async (req, res) => {
|
|
try {
|
|
const { content } = req.body || {};
|
|
await writeObjective(req.params.sessionId, content);
|
|
res.json({ ok: true });
|
|
} catch (error) {
|
|
const statusCode = Number(error?.statusCode) || 500;
|
|
if (statusCode >= 500) {
|
|
console.error('Failed to write goal objective:', error);
|
|
}
|
|
res.status(statusCode).json({ error: error?.message || 'Failed to write goal objective' });
|
|
}
|
|
});
|
|
|
|
app.get('/api/goals/objective/:sessionId', async (req, res) => {
|
|
const content = await readObjective(req.params.sessionId);
|
|
if (content === null) {
|
|
res.status(404).json({ error: 'objective not found' });
|
|
return;
|
|
}
|
|
res.json({ content });
|
|
});
|
|
|
|
app.delete('/api/goals/objective/:sessionId', async (req, res) => {
|
|
await deleteObjective(req.params.sessionId);
|
|
res.json({ ok: true });
|
|
});
|
|
}
|