@gramatr/client 0.6.19 → 0.6.20
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.
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* - Token savings metadata
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
import { readFileSync } from 'fs';
|
|
23
|
+
import { readFileSync, appendFileSync } from 'fs';
|
|
24
24
|
import { getGitContext } from './lib/gmtr-hook-utils.ts';
|
|
25
25
|
import {
|
|
26
26
|
persistClassificationResult,
|
|
@@ -29,6 +29,12 @@ import {
|
|
|
29
29
|
} from '../core/routing.ts';
|
|
30
30
|
import type { RouteResponse } from '../core/types.ts';
|
|
31
31
|
|
|
32
|
+
// ── Turn Tracking (Issue #594) ──
|
|
33
|
+
// Module-level counter incremented per prompt in this process.
|
|
34
|
+
// Reset on process restart (acceptable — session-end flushes).
|
|
35
|
+
let turnCounter = 0;
|
|
36
|
+
const TURNS_JSONL_PATH = '/tmp/gramatr-turns.jsonl';
|
|
37
|
+
|
|
32
38
|
// ── Types ──
|
|
33
39
|
|
|
34
40
|
interface HookInput {
|
|
@@ -337,6 +343,10 @@ function formatIntelligence(data: RouteResponse): string {
|
|
|
337
343
|
lines.push('The ISC prefix is REQUIRED — it signals to the user that GMTR intelligence is driving the criteria.');
|
|
338
344
|
lines.push('This is a HARD GATE — do NOT proceed to any work until TaskCreate calls are complete.');
|
|
339
345
|
|
|
346
|
+
// ── grā identity — server-generated content marker ──
|
|
347
|
+
lines.push('');
|
|
348
|
+
lines.push('When presenting gramatr intelligence (ISC scaffolds, search results, agent recommendations, summaries), prefix with **grā:** in bold. This distinguishes server-pre-computed content from your own reasoning. Example: "**grā:** ISC scaffold suggests 6 criteria for this migration task."');
|
|
349
|
+
|
|
340
350
|
// ── Effort-level-scaled format ──
|
|
341
351
|
if (effort === 'instant') {
|
|
342
352
|
lines.push('');
|
|
@@ -614,6 +624,23 @@ async function main() {
|
|
|
614
624
|
|
|
615
625
|
persistLastClassification(prompt, session_id, result, downstreamModel);
|
|
616
626
|
|
|
627
|
+
// Accumulate turn data for batch flush at session end (Issue #594)
|
|
628
|
+
try {
|
|
629
|
+
const cl = result?.classification || {};
|
|
630
|
+
const es = result?.execution_summary || {};
|
|
631
|
+
const turnData = {
|
|
632
|
+
turn_number: turnCounter++,
|
|
633
|
+
timestamp: new Date().toISOString(),
|
|
634
|
+
prompt: prompt.substring(0, 500),
|
|
635
|
+
effort_level: cl.effort_level || null,
|
|
636
|
+
intent_type: cl.intent_type || null,
|
|
637
|
+
confidence: cl.confidence || null,
|
|
638
|
+
memory_tier: cl.memory_tier || null,
|
|
639
|
+
classifier_model: es.classifier_model || null,
|
|
640
|
+
};
|
|
641
|
+
appendFileSync(TURNS_JSONL_PATH, JSON.stringify(turnData) + '\n');
|
|
642
|
+
} catch { /* never block the hook */ }
|
|
643
|
+
|
|
617
644
|
// If no result — DO NOT silently pass through. Tell the user what's broken.
|
|
618
645
|
if (!result || !result.classification) {
|
|
619
646
|
if (lastFailure) {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* ZERO external CLI dependencies — no jq, sed, curl, awk.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { writeFileSync } from 'fs';
|
|
14
|
+
import { writeFileSync, readFileSync, existsSync, unlinkSync } from 'fs';
|
|
15
15
|
import { join } from 'path';
|
|
16
16
|
import {
|
|
17
17
|
readHookInput,
|
|
@@ -129,6 +129,32 @@ async function main(): Promise<void> {
|
|
|
129
129
|
log('');
|
|
130
130
|
log('Saving session state to gramatr...');
|
|
131
131
|
|
|
132
|
+
// ── Flush accumulated turns to server (Issue #594) ──
|
|
133
|
+
try {
|
|
134
|
+
const turnsFile = '/tmp/gramatr-turns.jsonl';
|
|
135
|
+
if (existsSync(turnsFile)) {
|
|
136
|
+
const lines = readFileSync(turnsFile, 'utf8').trim().split('\n').filter(Boolean);
|
|
137
|
+
const turns = lines.map(line => JSON.parse(line));
|
|
138
|
+
if (turns.length > 0) {
|
|
139
|
+
log(` Flushing ${turns.length} turns to gramatr...`);
|
|
140
|
+
const interactionId = config?.current_session?.interaction_id || '';
|
|
141
|
+
const flushResult = await callMcpToolRaw('gramatr_batch_save_turns', {
|
|
142
|
+
session_id: sessionEntityId || sessionId,
|
|
143
|
+
project_id: projectId,
|
|
144
|
+
turns,
|
|
145
|
+
});
|
|
146
|
+
if (flushResult && flushResult.includes('"turns_saved"')) {
|
|
147
|
+
log(` Turns flushed successfully`);
|
|
148
|
+
} else {
|
|
149
|
+
log(' Turn flush uncertain (server may be unavailable)');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
unlinkSync(turnsFile);
|
|
153
|
+
}
|
|
154
|
+
} catch {
|
|
155
|
+
log(' Turn flush failed (non-critical)');
|
|
156
|
+
}
|
|
157
|
+
|
|
132
158
|
// Session lifecycle only — gramatr_session_end records git summary on the session entity.
|
|
133
159
|
// Handoffs are saved by the AGENT in the LEARN phase via gramatr_save_handoff (HARD GATE).
|
|
134
160
|
// The hook does NOT save handoffs — it lacks conversation context.
|