mirror of
https://github.com/forcedotcom/afv-library.git
synced 2026-08-05 06:41:42 +08:00
Data Cloud 360° view of a single Agentforce session — DC-only, zero
Splunk dependency. Pulls 24 STDM + GenAI DMOs via the Data Cloud Query
REST API, assembles a hierarchical session tree (Interaction → Step →
Generation → GatewayRequest), and renders a human-readable markdown
summary with transcript + per-turn topic/action invocations + LLM
generations + tool calls + audit chain.
Migrated as a standalone Apache-2.0 skill from an internal hub plugin —
self-contained, no sibling-skill or plugin dependencies.
What this skill answers:
- "Trace session <uuid>" / "Summarize what happened in <0Mw…>"
- "Find escalated sessions today on Messaging in <org>"
- Session discovery by time / agent / channel / outcome / conversation
text when the user has no session id
What it does NOT answer (use a different surface):
- Design-time architecture — use investigating-agentforce-architecture
- Runtime planner availability — DC alone can't tell you which
topic/action was eligible for the classifier on a given turn
Skill layout:
- 8 Python pipeline modules (fetch_dc, assemble_dc, render_dc,
discover_sessions, resolve_session, dc, storage, config)
- 4 _shared helpers (paths, fs_guard, sql, __init__) with skill-scoped
DATA_ROOT (~/.claude/data/investigating-agentforce-d360/)
- 26 SQL templates under assets/dc/
- 27 test files (367 tests + 18 subtests, 100% passing)
- 3 reference docs (artifacts.md, dc_dmo_fields.md,
dc_pipeline_contract.md)
- SKILL.md (sf-skills frontmatter, license: Apache-2.0,
metadata.version: "1.0")
- README.md (external-facing quick-start)
- tools/grant_allowlist.py (idempotent first-run permission grant)
- tools/archive_data_dir.sh (opt-in stop-hook tarballer)
Quality gates:
- pytest scripts/tests/: 367 passed + 18 subtests, 0 failures
- npm run validate:skills: 62 of 62 skill(s) checked, 0 errors
- Live end-to-end runs against 3 real Salesforce sessions exercising
both the full-tree and STDM-lag gateway-direct render branches
- 4 independent code-review rounds (correctness, security, markdown,
architecture-critic) — all findings addressed
Customer-data hygiene: no live tenant ids, no internal sprint markers,
no hub/sibling-skill references. Synthetic fixtures look obviously
synthetic (`019dface-…` UUIDs, `0MwTESTMSG…` MessagingSession ids,
`00DTESTORG…` org ids, `MyAgent` placeholder agent name).
Sibling skill: investigating-agentforce-architecture (PR #278) — same
migration pattern, design-time metadata; complementary scope.
79 lines
3.1 KiB
Bash
Executable File
79 lines
3.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Stop-hook helper — archive the most-recently-modified session dir under
|
|
# ~/.claude/data/investigating-agentforce-d360/ into a tarball for
|
|
# compliance / retro purposes.
|
|
#
|
|
# This is a USER-LEVEL hook (in ~/.claude/settings.json), opt-in.
|
|
# Archiving sessions is a per-team preference; users who want it wire it
|
|
# up, users who don't, don't.
|
|
#
|
|
# Behavior:
|
|
# - Find the most-recently-touched <sid>/ directory under DATA_ROOT
|
|
# - Tar + gzip it into ~/.claude/data/investigating-agentforce-d360-archive/
|
|
# with filename <sid>-<YYYY-MM-DD-HHMMSS>.tar.gz
|
|
# - Silent no-op if no session dir exists, or the latest is already
|
|
# archived (same mtime as the most-recent archive)
|
|
# - Never deletes the source; archiving only
|
|
#
|
|
# Exit codes: always 0 — Stop hooks block session exit only if non-zero.
|
|
#
|
|
set -eu
|
|
|
|
DATA_ROOT="$HOME/.claude/data/investigating-agentforce-d360"
|
|
ARCHIVE_ROOT="$HOME/.claude/data/investigating-agentforce-d360-archive"
|
|
|
|
[ -d "$DATA_ROOT" ] || exit 0
|
|
|
|
# Find the most-recently-modified session dir.
|
|
#
|
|
# Layout (per scripts/_shared/paths.py):
|
|
# DATA_ROOT/<org_id_15>/<agent_api_name>__<agent_version>/<session_id>/
|
|
# That's three levels deep — using `find -mindepth 3 -maxdepth 3` is the
|
|
# portable way to address the right level without globbing the org-id or
|
|
# agent levels (which would archive an entire org's worth of sessions
|
|
# under a filename pretending to be one session id).
|
|
#
|
|
# `find -printf` is GNU-only, so we sort by mtime via `stat` for portability.
|
|
# `find ... -depth 3 -type d` lists the right level on both macOS (BSD find)
|
|
# and Linux (GNU find).
|
|
LATEST=""
|
|
LATEST_MTIME=0
|
|
while IFS= read -r d; do
|
|
[ -d "$d" ] || continue
|
|
mt=$(stat -f %m "$d" 2>/dev/null || stat -c %Y "$d" 2>/dev/null || echo 0)
|
|
if [ "$mt" -gt "$LATEST_MTIME" ]; then
|
|
LATEST_MTIME=$mt
|
|
LATEST="$d"
|
|
fi
|
|
done < <(find "$DATA_ROOT" -mindepth 3 -maxdepth 3 -type d 2>/dev/null)
|
|
|
|
[ -n "$LATEST" ] || exit 0
|
|
[ -d "$LATEST" ] || exit 0
|
|
|
|
SID=$(basename "$LATEST")
|
|
TS=$(date +"%Y-%m-%d-%H%M%S")
|
|
mkdir -p "$ARCHIVE_ROOT"
|
|
TARBALL="$ARCHIVE_ROOT/${SID}-${TS}.tar.gz"
|
|
|
|
# Skip if an archive for this sid created within the last minute already
|
|
# exists — avoids redundant tarring on rapid session starts/stops.
|
|
#
|
|
# `-mmin -1` is the portable "modified within the last 1 minute" form on
|
|
# both BSD find (macOS) and GNU find (Linux). Earlier `-mtime -1m` was a
|
|
# silent foot-gun: BSD interpreted `m` as MONTHS (matched ~30 days), and
|
|
# GNU rejected the unit suffix entirely.
|
|
RECENT=$(find "$ARCHIVE_ROOT" -name "${SID}-*.tar.gz" -mmin -1 2>/dev/null | head -1)
|
|
[ -n "$RECENT" ] && exit 0
|
|
|
|
# Tar the session dir relative to its parent (the agent dir) so the archive
|
|
# unpacks as just `<session_id>/` without the org/agent path prefix. `--`
|
|
# guards against any future SID that ever started with `-`. On failure,
|
|
# remove the partial tarball so the next hook invocation retries cleanly
|
|
# instead of treating a corrupt 0-byte file as a recent dedup hit.
|
|
PARENT=$(dirname "$LATEST")
|
|
if ! tar --no-absolute-names -C "$PARENT" -czf "$TARBALL" -- "$SID" 2>/dev/null; then
|
|
rm -f "$TARBALL" 2>/dev/null
|
|
fi
|
|
exit 0
|