Skip to content

fix(hermes-gateway): compact over-length session keys for prompt_cache_key (64-char limit) - #8714

Closed
rsaulo wants to merge 1 commit into
paperclipai:masterfrom
rsaulo:fix/hermes-gateway-session-key-length
Closed

rsaulo wants to merge 1 commit into
paperclipai:masterfrom
rsaulo:fix/hermes-gateway-session-key-length

Conversation

@rsaulo

@rsaulo rsaulo commented Jun 28, 2026

Copy link
Copy Markdown

Thinking Path

  • Paperclip is the open source app people use to manage AI agents for work
  • Agents can run remotely through the hermes_gateway adapter, which resumes a per-issue Hermes session via a session key forwarded as X-Hermes-Session-Key / session_id
  • Hermes in turn passes that session key to its Codex/OpenAI transport as the prompt_cache_key, which has a hard 64-character maximum
  • But resolveSessionKey emits keys up to 140 chars for the issue strategy (the default) and 97 for agent — both overflow the limit
  • Over-length keys are silently rejected/ignored downstream, so prompt caching and per-issue session continuity are lost; the only workaround, sessionKeyStrategy: "none", disables continuity entirely
  • This PR adds compactSessionKey(), which deterministically rehashes only over-length keys into a stable, namespaced ≤64-char form
  • The benefit is that the issue and agent strategies keep working over the gateway without losing session continuity or per-issue isolation

Linked Issues or Issue Description

Fixes #8713.

Related (add the hermes_gateway adapter; neither addresses the key-length issue): #2363, #4359.

What Changed

  • Add compactSessionKey() in packages/adapters/hermes/src/gateway/server/execute.ts: when a key exceeds 64 chars, return paperclip:h:<first-48-hex-of-sha256> (60 chars); otherwise return the key unchanged.
  • Apply it to every non-null resolveSessionKey return path (agent, run, and the issue/run fallback).
  • Add five unit tests to the existing resolveSessionKey suite covering: over-length issue and agent keys compacting to ≤64 and matching ^paperclip:h:[0-9a-f]{48}$, stability (same scope → same key), isolation (distinct issues → distinct keys), and pass-through for within-limit keys.

Verification

# from packages/adapters/hermes
pnpm exec vitest run src/gateway/server/execute.test.ts
#  Test Files  1 passed (1)
#       Tests  26 passed (26)

npx tsc --noEmit -p tsconfig.json   # clean, no output

Character counts that motivate the fix (UUID company/agent/issue ids): issue = 140, agent = 97, run = 50, none = null. After the change all emitted keys are ≤ 64.

Risks

Low. Keys already within the limit — including the run strategy and short ids — pass through byte-for-byte, so existing behavior is unchanged for them. Only over-length keys change shape; any live session keyed off an over-length value re-keys once on its next wake, which is harmless (a single fresh session, no data loss). No schema migration, no API surface change, no config change.

Model Used

  • Provider / model: Anthropic — Claude Opus 4.8 (claude-opus-4-8)
  • Harness: Claude Code (agentic tool use: repo read, edits, local test/typecheck execution)
  • Reasoning mode: extended thinking enabled
  • Context window: 200K tokens

The change was authored and locally verified by the model; a human operator reviewed and approved opening the PR.

Checklist

  • I have included a thinking path that traces from project context to this change
  • I have specified the model used (with version and capability details)
  • I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work
  • I have searched GitHub for duplicate or related PRs and linked them above
  • I have either (a) linked existing issues with Fixes: # / Closes # / Refs # OR (b) described the issue in-PR following the relevant issue template
  • I have not referenced internal/instance-local Paperclip issues or links (only public GitHub #NNN / github.com/paperclipai/paperclip URLs)
  • My branch name describes the change (e.g. docs/..., fix/...) and contains no internal Paperclip ticket id or instance-derived details
  • I have run tests locally and they pass
  • I have added or updated tests where applicable
  • I have updated relevant documentation to reflect my changes — N/A, no user-facing docs cover this internal session-key behavior
  • I have considered and documented any risks above
  • All Paperclip CI gates are green — pending CI
  • Greptile is 5/5 with no open P2s, recommendations, or follow-ups — this update resolves the only open P2 (missing template sections); awaiting re-review
  • I will address all Greptile and reviewer comments before requesting merge

🤖 Generated with Claude Code

…e_key

resolveSessionKey could emit keys up to 140 chars (issue strategy) / 97
(agent), but Hermes forwards them as the Codex/OpenAI prompt_cache_key
which caps at 64 — silently losing prompt caching and session continuity.
Compact over-length keys to a stable, namespaced sha256 hash so continuity
and per-issue isolation are preserved; within-limit keys pass through
unchanged.

Fixes #8713

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@commitperclip

commitperclip Bot commented Jun 28, 2026

Copy link
Copy Markdown

Hey @rsaulo! Before this PR can be reviewed, a few things need attention:

Missing or incomplete:

  • Missing section: ## Thinking Path
  • Missing section: ## What Changed
  • Missing section: ## Verification
  • Missing section: ## Risks
  • Missing section: ## Model Used
  • Add the dedup-search checkbox to your PR description and check it once you have searched the GitHub PR list for similar PRs. See the PR template at .github/PULL_REQUEST_TEMPLATE.md and CONTRIBUTING.md → "Before You Start: Search First".

Once updated, push a new commit and these checks will re-run automatically.

— commitperclip

@superagent-security

Copy link
Copy Markdown

Superagent didn't find any vulnerabilities or security issues in this PR.

@greptile-apps

greptile-apps Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes silent prompt-cache loss in the hermes-gateway adapter by compacting over-length session keys before they are forwarded as prompt_cache_key to the Codex/OpenAI transport. The fix is minimal, deterministic, and non-invasive.

  • Adds compactSessionKey() which applies SHA-256 and returns a stable paperclip:h:<48-hex-chars> key (60 chars) only when the raw key exceeds the 64-char limit; within-limit keys pass through unchanged.
  • Wraps all three over-length-prone strategies (issue, agent, run) uniformly, though run keys (~50 chars) never actually trigger compaction.
  • Test suite adds five cases covering compaction output format, stability, per-issue isolation, and pass-through behaviour.

Confidence Score: 4/5

The code change is correct and safe to merge; the only outstanding item is the missing PR template sections (Thinking Path, Model Used, Checklist).

The compaction logic is mathematically sound: SHA-256 hex truncated to 48 chars gives a 60-char output that reliably fits the 64-char limit, is stable for the same input, and distinguishes different scopes. Tests cover all the meaningful cases. Existing live sessions re-key once on the next wake, which the PR author correctly calls out as harmless. The only gap is that the PR description doesn't follow the required template format — Thinking Path, Model Used, and the Checklist are absent.

No files require special attention; both changed files are straightforward and correct.

Important Files Changed

Filename Overview
packages/adapters/hermes/src/gateway/server/execute.ts Adds compactSessionKey() using SHA-256 to truncate over-length session keys to ≤60 chars; applied to all resolveSessionKey strategies
packages/adapters/hermes/src/gateway/server/execute.test.ts Adds five targeted tests covering over-length compaction (issue/agent), stability, isolation, and pass-through for within-limit keys
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
packages/adapters/hermes/src/gateway/server/execute.ts:159-163
**PR template sections missing**

The PR description doesn't follow the required template from `CONTRIBUTING.md`. Specifically, it's missing:
- A **Thinking Path** in blockquote format tracing from project context down to this change (e.g., `> - Paperclip is… > - The hermes-gateway adapter… > - Session keys up to 140 chars exceed the 64-char prompt_cache_key limit… > - This PR adds compactSessionKey()… > - The benefit is…`)
- A **Model Used** section (the footer says "Generated with Claude Code" but the template requires the provider, model ID/version, and capability details)
- The **Checklist** from the template

Please update the PR description to follow the template at `.github/PULL_REQUEST_TEMPLATE.md`.

Reviews (1): Last reviewed commit: "fix(hermes-gateway): compact over-length..." | Re-trigger Greptile

Comment on lines +159 to +163
function compactSessionKey(key: string): string {
if (key.length <= MAX_SESSION_KEY_CHARS) return key;
const digest = createHash("sha256").update(key).digest("hex").slice(0, 48);
return `paperclip:h:${digest}`;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 PR template sections missing

The PR description doesn't follow the required template from CONTRIBUTING.md. Specifically, it's missing:

  • A Thinking Path in blockquote format tracing from project context down to this change (e.g., > - Paperclip is… > - The hermes-gateway adapter… > - Session keys up to 140 chars exceed the 64-char prompt_cache_key limit… > - This PR adds compactSessionKey()… > - The benefit is…)
  • A Model Used section (the footer says "Generated with Claude Code" but the template requires the provider, model ID/version, and capability details)
  • The Checklist from the template

Please update the PR description to follow the template at .github/PULL_REQUEST_TEMPLATE.md.

Context Used: Contribution guidelines (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/adapters/hermes/src/gateway/server/execute.ts
Line: 159-163

Comment:
**PR template sections missing**

The PR description doesn't follow the required template from `CONTRIBUTING.md`. Specifically, it's missing:
- A **Thinking Path** in blockquote format tracing from project context down to this change (e.g., `> - Paperclip is… > - The hermes-gateway adapter… > - Session keys up to 140 chars exceed the 64-char prompt_cache_key limit… > - This PR adds compactSessionKey()… > - The benefit is…`)
- A **Model Used** section (the footer says "Generated with Claude Code" but the template requires the provider, model ID/version, and capability details)
- The **Checklist** from the template

Please update the PR description to follow the template at `.github/PULL_REQUEST_TEMPLATE.md`.

**Context Used:** Contribution guidelines ([source](https://app.greptile.com/paperclip-org-3/-/custom-context?memory=a595932a-f6ed-448b-899b-5ccac43f9148))

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@rsaulo

rsaulo commented Jun 28, 2026

Copy link
Copy Markdown
Author

Thanks for the review! Updated the PR description to follow .github/PULL_REQUEST_TEMPLATE.md — added the Thinking Path (blockquote), Model Used, and the Checklist, which were the open P2. No code changes; the compaction logic and tests are unchanged. Requesting a Greptile re-review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hermes_gateway: resolveSessionKey emits keys >64 chars, breaking prompt_cache_key / session continuity

1 participant