@@ -82,8 +82,9 @@ let usingExternalApi = false; // Track if using external API (skip daemon manage
8282
8383// Capability detected once per service.start() against `<apiUrl>/version`.
8484// `true` when the Hindsight API supports `update_mode: 'append'` (added in
85- // 0.5.0 — see vectorize-io/hindsight#932). When false, retain falls back to a
86- // per-turn document id so prior turns aren't silently overwritten.
85+ // 0.5.0 — see vectorize-io/hindsight#932) and stores document text. When false,
86+ // retain falls back to a per-turn document id so prior turns aren't silently
87+ // overwritten or rejected by text-disabled deployments.
8788let supportsUpdateModeAppend = false ;
8889let appendCapabilityProbed = false ;
8990const MIN_VERSION_FOR_UPDATE_MODE_APPEND = "0.5.0" ;
@@ -1382,16 +1383,52 @@ export function meetsMinimumVersion(actual: string, minimum: string): boolean {
13821383 return true ;
13831384}
13841385
1386+ export interface HindsightApiCapabilities {
1387+ version : string ;
1388+ storeDocumentText : boolean ;
1389+ }
1390+
1391+ function isRecord ( value : unknown ) : value is Record < string , unknown > {
1392+ return typeof value === "object" && value !== null ;
1393+ }
1394+
1395+ export function parseHindsightApiCapabilities ( payload : unknown ) : HindsightApiCapabilities | null {
1396+ if ( ! isRecord ( payload ) || typeof payload . api_version !== "string" ) {
1397+ return null ;
1398+ }
1399+
1400+ let storeDocumentText = true ;
1401+ if ( "features" in payload ) {
1402+ const features = payload . features ;
1403+ storeDocumentText = isRecord ( features ) && features . store_document_text === true ;
1404+ }
1405+
1406+ return {
1407+ version : payload . api_version ,
1408+ storeDocumentText,
1409+ } ;
1410+ }
1411+
1412+ export function supportsAppendFromCapabilities (
1413+ capabilities : HindsightApiCapabilities | null
1414+ ) : boolean {
1415+ return (
1416+ capabilities !== null &&
1417+ capabilities . storeDocumentText &&
1418+ meetsMinimumVersion ( capabilities . version , MIN_VERSION_FOR_UPDATE_MODE_APPEND )
1419+ ) ;
1420+ }
1421+
13851422/**
13861423 * Probe `<apiUrl>/version` once at service.start to learn the running
1387- * Hindsight API version . Returns `null` (treated as "no append support") if
1388- * the endpoint is unreachable or returns malformed payload — conservative
1424+ * Hindsight API capabilities . Returns `null` (treated as "no append support")
1425+ * if the endpoint is unreachable or returns malformed payload — conservative
13891426 * fallback path is the right call when we can't be sure.
13901427 */
1391- async function fetchHindsightApiVersion (
1428+ async function fetchHindsightApiCapabilities (
13921429 apiUrl : string ,
13931430 apiToken ?: string | null
1394- ) : Promise < string | null > {
1431+ ) : Promise < HindsightApiCapabilities | null > {
13951432 const versionUrl = `${ apiUrl . replace ( / \/ $ / , "" ) } /version` ;
13961433 try {
13971434 const headers : Record < string , string > = { "User-Agent" : USER_AGENT } ;
@@ -1404,12 +1441,12 @@ async function fetchHindsightApiVersion(
14041441 debug ( `[Hindsight] /version returned HTTP ${ response . status } ; assuming legacy` ) ;
14051442 return null ;
14061443 }
1407- const data = ( await response . json ( ) ) as { api_version ?: unknown } ;
1408- const v = typeof data . api_version === "string" ? data . api_version : null ;
1409- if ( ! v ) {
1444+ const data = await response . json ( ) ;
1445+ const capabilities = parseHindsightApiCapabilities ( data ) ;
1446+ if ( ! capabilities ) {
14101447 debug ( `[Hindsight] /version payload missing api_version; assuming legacy` ) ;
14111448 }
1412- return v ;
1449+ return capabilities ;
14131450 } catch ( error ) {
14141451 debug ( `[Hindsight] /version probe failed: ${ String ( error ) } ; assuming legacy` ) ;
14151452 return null ;
@@ -1419,32 +1456,42 @@ async function fetchHindsightApiVersion(
14191456/**
14201457 * Probe `/version` and update the module-level `supportsUpdateModeAppend`
14211458 * capability flag accordingly. Logs a one-time WARN block when the API is
1422- * older than 0.5.0 — without `update_mode: 'append'`, every retain on the
1423- * same session id silently overwrites prior turns server-side.
1459+ * older than 0.5.0 or cannot store document text — without
1460+ * `update_mode: 'append'`, every retain on the same session id silently
1461+ * overwrites prior turns server-side, and append itself requires stored
1462+ * document text.
14241463 *
14251464 * Called from the same code paths as the health check, so capability is
14261465 * always re-evaluated when the plugin (re)connects to the API.
14271466 */
14281467async function detectAppendCapability ( apiUrl : string , apiToken ?: string | null ) : Promise < void > {
1429- const version = await fetchHindsightApiVersion ( apiUrl , apiToken ) ;
1430- const supported =
1431- version !== null && meetsMinimumVersion ( version , MIN_VERSION_FOR_UPDATE_MODE_APPEND ) ;
1468+ const capabilities = await fetchHindsightApiCapabilities ( apiUrl , apiToken ) ;
1469+ const supported = supportsAppendFromCapabilities ( capabilities ) ;
14321470 const transitionedToUnsupported = supportsUpdateModeAppend && ! supported ;
14331471 const firstProbe = ! appendCapabilityProbed ;
14341472 appendCapabilityProbed = true ;
14351473 supportsUpdateModeAppend = supported ;
1436- if ( supported ) {
1437- debug ( `[Hindsight] API version ${ version } supports update_mode=append` ) ;
1474+ if ( supported && capabilities ) {
1475+ debug (
1476+ `[Hindsight] API version ${ capabilities . version } supports update_mode=append with stored document text`
1477+ ) ;
14381478 return ;
14391479 }
14401480 // Warn on the first probe when unsupported, and on any transition from
14411481 // supported -> unsupported. Stay silent on subsequent re-probes that
14421482 // confirm the same unsupported state.
14431483 if ( ! firstProbe && ! transitionedToUnsupported ) return ;
1484+ const version = capabilities ?. version ?? null ;
1485+ const reason =
1486+ capabilities !== null &&
1487+ meetsMinimumVersion ( capabilities . version , MIN_VERSION_FOR_UPDATE_MODE_APPEND ) &&
1488+ ! capabilities . storeDocumentText
1489+ ? `reports version "${ capabilities . version } " but has features.store_document_text disabled`
1490+ : `reports version "${ version ?? "unknown" } ", which is older than ${ MIN_VERSION_FOR_UPDATE_MODE_APPEND } ` ;
14441491 log . warn (
1445- `[Hindsight] ⚠️ API at ${ apiUrl } reports version " ${ version ?? "unknown" } ", which is older than ${ MIN_VERSION_FOR_UPDATE_MODE_APPEND } . ` +
1492+ `[Hindsight] ⚠️ API at ${ apiUrl } ${ reason } . ` +
14461493 `Falling back to per-turn document ids — each retain becomes its own document instead of accumulating into one per-session document. ` +
1447- `Upgrade Hindsight to ${ MIN_VERSION_FOR_UPDATE_MODE_APPEND } or newer to enable session-scoped retention with update_mode=append.`
1494+ `Enable document text storage on Hindsight ${ MIN_VERSION_FOR_UPDATE_MODE_APPEND } or newer to use session-scoped retention with update_mode=append.`
14481495 ) ;
14491496}
14501497
0 commit comments