From e7978d5e1d76a93db878243bf2ff8c6738ca6d02 Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Tue, 4 Aug 2026 15:32:01 -0700 Subject: [PATCH] feat: export session insights in export-agent scripts Read session insights from GET /api/v1/threads/insights and write them to data/session-insights/ as individual .md files (insight content) + .yaml files (metadata). Both bash and PowerShell scripts updated. Session insights capture learned patterns from past agent sessions including investigation trajectories, root causes, and key learnings. --- sreagent-templates/bin/export-agent.sh | 43 +++++++++++++++++++- sreagent-templates/bin/ps/Export-Agent.ps1 | 47 +++++++++++++++++++++- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/sreagent-templates/bin/export-agent.sh b/sreagent-templates/bin/export-agent.sh index 10e0e4698..14406b3a6 100755 --- a/sreagent-templates/bin/export-agent.sh +++ b/sreagent-templates/bin/export-agent.sh @@ -814,6 +814,26 @@ else _log "Skipping repo instructions (use --include-repo-instructions to include)" fi +# Session Insights (data-plane — learned patterns from past sessions) +_log "Reading session insights..." +RAW_SESSION_INSIGHTS=$(dp_get "/api/v1/threads/insights?skip=0&take=1000") +if [[ "$RAW_SESSION_INSIGHTS" != "null" ]]; then + SESSION_INSIGHTS=$(echo "$RAW_SESSION_INSIGHTS" | jq -c '[(.insights // [])[] | { + id: .id, + threadId: .threadId, + title: .title, + generatedTimestamp: .generatedTimestamp, + insightMarkdown: .insightMarkdown, + feedbackCount: (.feedbackCount // 0), + positiveFeedbackCount: (.positiveFeedbackCount // 0), + negativeFeedbackCount: (.negativeFeedbackCount // 0) + }]' 2>/dev/null || echo "[]") +else + SESSION_INSIGHTS="[]" +fi +SESSION_INSIGHT_COUNT=$(echo "$SESSION_INSIGHTS" | jq 'length') +_log " Found ${SESSION_INSIGHT_COUNT} session insight(s)" + echo # ────────────────────── Phase 4: Dry-run summary ────────────────────── @@ -848,6 +868,7 @@ echo " Webhook bridge: $([[ "$BRIDGE_EXISTS" == true ]] && echo "yes" || ec echo " Incident platforms: ${INCIDENT_PLATFORM_COUNT}" echo " Scheduled tasks: ${TASK_COUNT}" echo " Incident filters: ${FILTER_COUNT}" +echo " Session insights: ${SESSION_INSIGHT_COUNT}" if [[ "$DRY_RUN" == "true" ]]; then echo @@ -1400,7 +1421,7 @@ if [[ $(echo "$PLUGIN_INSTALLATIONS" | jq 'length') -gt 0 ]]; then done fi -# ═══════ 4. data/ — knowledge, memories, repo instructions ═══════ +# ═══════ 4. data/ — knowledge, memories, repo instructions, session insights ═══════ _info "Writing data/ files" @@ -1412,6 +1433,26 @@ mkdir -p "${DATA_DIR}/synthesized-knowledge" touch "${DATA_DIR}/knowledge/.gitkeep" touch "${DATA_DIR}/synthesized-knowledge/.gitkeep" +# Session insights → individual .md files + metadata YAML +if [[ "$SESSION_INSIGHT_COUNT" -gt 0 ]]; then + SI_DIR="${DATA_DIR}/session-insights" + mkdir -p "$SI_DIR" + for i in $(seq 0 $((SESSION_INSIGHT_COUNT - 1))); do + si_id=$(echo "$SESSION_INSIGHTS" | jq -r --argjson i "$i" '.[$i].id') + si_title=$(echo "$SESSION_INSIGHTS" | jq -r --argjson i "$i" '.[$i].title') + # Sanitize title for filename + si_fname=$(echo "$si_title" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//' | head -c 80) + [[ -z "$si_fname" ]] && si_fname="$si_id" + # Write insight markdown content + si_md=$(echo "$SESSION_INSIGHTS" | jq -r --argjson i "$i" '.[$i].insightMarkdown // ""') + [[ -n "$si_md" ]] && printf '%s' "$si_md" > "${SI_DIR}/${si_fname}.md" + # Write metadata YAML (without the large markdown blob) + echo "$SESSION_INSIGHTS" | jq --argjson i "$i" '.[$i] | del(.insightMarkdown) | . + {insightMarkdown: ("session-insights/" + $fname + ".md")}' \ + --arg fname "$si_fname" | json2yaml > "${SI_DIR}/${si_fname}.yaml" + done + _log " session-insights: ${SESSION_INSIGHT_COUNT} file(s)" +fi + if [[ $(echo "$KNOWLEDGE" | jq 'length') -gt 0 ]]; then mkdir -p "${DATA_DIR}" echo "$KNOWLEDGE" | jq '.' > "${DATA_DIR}/knowledge.json" diff --git a/sreagent-templates/bin/ps/Export-Agent.ps1 b/sreagent-templates/bin/ps/Export-Agent.ps1 index 35b7178d4..a9b47ee8a 100644 --- a/sreagent-templates/bin/ps/Export-Agent.ps1 +++ b/sreagent-templates/bin/ps/Export-Agent.ps1 @@ -961,6 +961,27 @@ if ($INCLUDE_REPO_INSTRUCTIONS -and $REPO_COUNT -gt 0) { _log 'Skipping repo instructions (use -IncludeRepoInstructions to include)' } +# Session Insights (data-plane — learned patterns from past sessions) +_log 'Reading session insights...' +$RAW_SESSION_INSIGHTS = Invoke-DpGet '/api/v1/threads/insights?skip=0&take=1000' +if ($RAW_SESSION_INSIGHTS -ne 'null') { + $SESSION_INSIGHTS = $RAW_SESSION_INSIGHTS | Invoke-Jq -Compact -Filter '[(.insights // [])[] | { + id: .id, + threadId: .threadId, + title: .title, + generatedTimestamp: .generatedTimestamp, + insightMarkdown: .insightMarkdown, + feedbackCount: (.feedbackCount // 0), + positiveFeedbackCount: (.positiveFeedbackCount // 0), + negativeFeedbackCount: (.negativeFeedbackCount // 0) + }]' + if (-not $SESSION_INSIGHTS) { $SESSION_INSIGHTS = '[]' } +} else { + $SESSION_INSIGHTS = '[]' +} +$SESSION_INSIGHT_COUNT = ($SESSION_INSIGHTS | jq 'length') -as [int] +_log " Found ${SESSION_INSIGHT_COUNT} session insight(s)" + Write-Host '' # ═══════════════════════════════════════════════════════════════════ @@ -998,6 +1019,7 @@ Write-Host " Webhook bridge: $(if ($BRIDGE_EXISTS) { 'yes' } else { 'no' }) Write-Host " Incident platforms: ${INCIDENT_PLATFORM_COUNT}" Write-Host " Scheduled tasks: ${TASK_COUNT}" Write-Host " Incident filters: ${FILTER_COUNT}" +Write-Host " Session insights: ${SESSION_INSIGHT_COUNT}" if ($DryRun) { Write-Host '' @@ -1542,7 +1564,7 @@ if ($piCount -gt 0) { } } -# ═══════ 4. data/ — knowledge, memories, repo instructions ═══════ +# ═══════ 4. data/ — knowledge, memories, repo instructions, session insights ═══════ _info 'Writing data/ files' @@ -1554,6 +1576,29 @@ foreach ($subDir in @('knowledge', 'synthesized-knowledge')) { if (-not (Test-Path $gitkeep)) { '' | Set-Content $gitkeep } } +# Session insights → individual .md files + metadata YAML +if ($SESSION_INSIGHT_COUNT -gt 0) { + $siDir = Join-Path $DATA_DIR 'session-insights' + if (-not (Test-Path $siDir)) { New-Item -ItemType Directory -Path $siDir -Force | Out-Null } + for ($i = 0; $i -lt $SESSION_INSIGHT_COUNT; $i++) { + $siId = $SESSION_INSIGHTS | jq -r --argjson i $i '.[$i].id' + $siTitle = $SESSION_INSIGHTS | jq -r --argjson i $i '.[$i].title' + # Sanitize title for filename + $siFname = ($siTitle -replace '[^a-zA-Z0-9]', '-' -replace '-+', '-' -replace '^-|-$', '').ToLower() + if ($siFname.Length -gt 80) { $siFname = $siFname.Substring(0, 80) } + if (-not $siFname) { $siFname = $siId } + # Write insight markdown content + $siMd = $SESSION_INSIGHTS | Invoke-Jq -Raw -Filter '.[$i].insightMarkdown // ""' -ExtraArgs @('--argjson', 'i', "$i") + if ($siMd) { + [System.IO.File]::WriteAllText((Join-Path $siDir "${siFname}.md"), $siMd) + } + # Write metadata YAML (without the large markdown blob) + $SESSION_INSIGHTS | Invoke-Jq -Filter '.[$i] | del(.insightMarkdown) | . + {insightMarkdown: ("session-insights/" + $fname + ".md")}' -ExtraArgs @('--argjson', 'i', "$i", '--arg', 'fname', $siFname) | + ConvertTo-Yaml | Set-Content -Path (Join-Path $siDir "${siFname}.yaml") -NoNewline -Encoding utf8 + } + _log " session-insights: ${SESSION_INSIGHT_COUNT} file(s)" +} + $knowledgeCount = ($KNOWLEDGE | jq 'length') -as [int] if ($knowledgeCount -gt 0) { $KNOWLEDGE | jq '.' | Set-Content -Path (Join-Path $DATA_DIR 'knowledge.json') -Encoding utf8