mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-10 03:08:10 +02:00
codex/plugin-task-execution
3
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
aad97d93fe |
fix(hermes): surface real reasoning text from reasoning.available events (#9237)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - When an agent runs through the Hermes gateway adapter, its stdout is parsed line-by-line into transcript entries that the issue chat renders (the UI fetches the adapter's `./ui-parser` from `/api/adapters/:type/ui-parser.js` and runs `parseStdoutLine` client-side) > - Reasoning-capable models emit a `reasoning.available` gateway event carrying the model's reasoning text, and the chat renders `thinking` parts as expandable chain-of-thought > - The gateway parser mapped `reasoning.available` to a hardcoded `"Hermes reasoning available"` string and discarded the event payload, so the "thinking" part had no real content — the indicator looked static and expanding it revealed nothing (#9209) > - This pull request extracts the actual reasoning text from the event payload and uses it as the `thinking` part's text, keeping the old string only as a fallback for payloads that carry no text > - The benefit is that the "Hermes reasoning available" indicator now surfaces the model's real reasoning, which the existing expandable-thinking UI can display ## Linked Issues or Issue Description Fixes: #9209 ## What Changed - `packages/adapters/hermes/src/gateway/ui/parse-stdout.ts`: the `reasoning.available` handler now extracts the reasoning text from the event `data` via a small helper (`extractReasoningText`), checking the plausible field names (`reasoning`, `reasoning_text`, `thinking`, `text`, `summary`, `content`) and recursing one level into nested `data` / `payload` records, with ANSI stripped. The prior `"Hermes reasoning available"` string is kept only as a fallback when no text field is present. - `packages/adapters/hermes/gateway-ui-parser.cjs`: applied the identical logical change to the committed CommonJS mirror (exported as `./gateway/ui-parser`), keeping the two files in sync. - `packages/adapters/hermes/src/gateway/ui/parse-stdout.test.ts` (new): unit tests for the gateway parser (there were none) covering direct-field, `summary`, nested `data`/`payload` extraction, the no-text fallback, and regression guards for `message.delta` and plain stdout. ## Verification Ran from `packages/adapters/hermes`: - `node_modules/.bin/vitest run src/gateway/ui/parse-stdout.test.ts` → **8/8 passed**. - Negative control: stashed the source changes and re-ran the same test file against the current (pre-patch) parser → **4/8 failed** (exactly the reasoning-extraction assertions), then restored — confirming the tests are discriminating, not vacuous. - `npx tsc --noEmit -p .` → clean. Real-behavior proof (driving the actual shipped `gateway-ui-parser.cjs` `parseStdoutLine`) is in the block below. ## Risks - **Low risk.** Behavior is unchanged for events that carry no recognizable text field — the `"Hermes reasoning available"` fallback is preserved (verified). Only the `reasoning.available` branch changed; `message.delta`, `run.failed`/`run.error`, and the generic/system/stdout branches are untouched. - The exact field name in a real `reasoning.available` payload is defined by the external Hermes gateway and is not present anywhere in this repo, so the extraction is intentionally defensive across several plausible field names rather than pinned to one. If the real event nests the text differently than `data` / `payload`, it will fall back to the existing placeholder (i.e. no regression vs. today). Happy to tighten the field list against real gateway traffic if a maintainer can share a sample. ## Model Used Claude Sonnet 5 (`claude-sonnet-5`) via Claude Code, with tool use and local test execution (ran vitest/tsc against the change). Planning, code review, and the real-behavior proof were done with Claude (Opus 4.8) in the same session. ## Real behavior proof **Behavior addressed:** A `reasoning.available` Hermes gateway event now produces a `thinking` transcript part containing the model's real reasoning text, instead of a static `"Hermes reasoning available"` placeholder with no content behind it (#9209). **Real environment tested:** Drove the actual shipped production artifact — `packages/adapters/hermes/gateway-ui-parser.cjs`, the exact module the UI loads via `/api/adapters/hermes-gateway/ui-parser.js` and runs to parse gateway stdout — on Node v24.16.0, macOS. The input is a raw stdout line in the exact format emitted by `packages/adapters/hermes/src/gateway/server/execute.ts` (`[hermes-gateway:event] run=… event=reasoning.available data=…`). Only the external gateway boundary (the raw line) is synthesized; the parser code path is the real one. **Exact steps or command run after this patch:** ``` # BEFORE = git show HEAD:…/gateway-ui-parser.cjs ; AFTER = patched artifact node proof.cjs # requires each parser build and calls parseStdoutLine(line, ts) # line = [hermes-gateway:event] run=run-abc123 event=reasoning.available \ # data={"text":"Checking whether the cache key includes the tenant id before I refactor the lookup."} ``` **Evidence after fix:** ``` ===== BEFORE (master / old code) ===== [ { "kind": "thinking", "ts": "…", "text": "Hermes reasoning available" } ] thinking part carries real reasoning text? -> NO (static placeholder, nothing for the UI to expand) ===== AFTER (this patch) ===== [ { "kind": "thinking", "ts": "…", "text": "Checking whether the cache key includes the tenant id before I refactor the lookup." } ] thinking part carries real reasoning text? -> YES ``` Additional cases through the same shipped artifact after the patch: ``` -- nested payload (data.payload.reasoning) -- {"kind":"thinking","ts":"…","text":"Weighing two migration orders."} -- bare signal, no text field (regression guard) -- {"kind":"thinking","ts":"…","text":"Hermes reasoning available"} # fallback preserved -- message.delta still works (regression guard) -- {"kind":"assistant","ts":"…","text":"Hello","delta":true} ``` **Observed result after fix:** The `reasoning.available` event yields a `thinking` part carrying the model's real reasoning text (top-level or nested), which the existing expandable-thinking rendering in the chat can display. Events with no text field still yield the original placeholder, and unrelated events are unaffected. **What was not tested:** I did not run against a live Hermes gateway — Paperclip's Hermes gateway binary and its credentials aren't available on this machine, and no captured real `reasoning.available` payload exists in the repo, so the exact wire field name is inferred (hence the defensive multi-field extraction + safe fallback). I also did not render the full React chat component in jsdom; the change is confined to the parser, and the chat's expandable `thinking` rendering already exists (`ui/src/components/IssueChatThread.tsx`). CI / unit tests here are supplemental to the runtime proof above. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above (searched `9209 in:body` and keyword variants — none found) - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (`fix/hermes-reasoning-available-payload`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] I have updated relevant documentation to reflect my changes (no user-facing docs describe this behavior; none needed) - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green (will confirm once CI runs on the PR) - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups (will address on review) - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
70c86d2c73 |
fix(hermes): strip ANSI escape codes from terminal output in UI parsers (#8731)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Hermes adapter produces terminal output with ANSI color codes on
stdout
> - These escape sequences flow through the UI parsers untouched and
render as raw garbage text
> - This PR adds ANSI stripping at the entry point of all four Hermes
parse-stdout entry points
> - The same regex is already proven in claude-local adapter
> - The benefit is clean, readable terminal output for Hermes agents
## Linked Issues or Issue Description
No existing issue. This is a bug report:
**What happened**
Hermes terminal output displayed ANSI color codes as raw text in the
Paperclip UI, making agent output unreadable.
**Expected behavior**
Terminal output in run transcripts should be clean text without
invisible control characters.
**Steps to reproduce**
1. Connect a Hermes agent to Paperclip
2. Create and assign a task to the agent
3. View the run transcript — ANSI escape codes appear as raw garbage
**Paperclip version or commit**
|
||
|
|
fd2f82ac5b |
[codex] Add built-in Hermes adapters (#8543)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agent adapters are the boundary between the control plane and the runtimes that actually do work. > - Hermes support needs to be available as first-class local and gateway adapters while still preserving the adapter-manager override path for external packages. > - The adapter work touches runtime execution, UI adapter metadata, onboarding prompts, scoped credentials, release packaging, and smoke coverage, so the handoff needs concrete verification rather than only unit tests. > - This pull request adds built-in Hermes local and Hermes gateway support, keeps external adapter overrides compatible, and documents/tests the gateway flow end to end. > - The benefit is that operators can hire Hermes-backed agents without a manual plugin install, while self-hosted installs can still override/shadow the built-ins through Adapter manager packages. ## Linked Issues or Issue Description No public GitHub issue exists for this exact Hermes built-in adapter, gateway onboarding, and release-source work. Problem description: - Hermes local and gateway adapters need a public, reviewable source path in the monorepo so package artifacts and built-in adapter behavior match the application source. - Operators need built-in `hermes_local` and `hermes_gateway` adapter choices without losing the ability to install external Hermes packages as overrides. - Gateway onboarding needs secure defaults for API server URLs, API keys, and generated agent setup text. - Hermes-originated task bridge credentials need narrower API-key scope configuration. - Related public PRs found during duplicate search include #3027, #2363, #7544, #7950, #8095, and #8543. ## What Changed - Added the unified Hermes adapter package with local and gateway server/UI/CLI exports, config schemas, transcript parsing, model detection, and package metadata. - Registered `hermes_local` and `hermes_gateway` as built-in adapters across shared constants, server registries, CLI packaging, and UI adapter registries. - Kept the external adapter override path compatible so installed Hermes packages can shadow built-ins and restore the built-in parser when disabled. - Added Hermes gateway onboarding docs, board-operator docs, Docker smoke assets, and shell smoke harnesses for join/e2e validation. - Added scoped task-bridge API-key support, authorization checks, issue-origin handling, and tests for Hermes-created Paperclip tasks. - Hardened gateway transport and redaction behavior for API keys, headers, session data, and smoke diagnostics. - Updated release packaging/bootstrap checks for the Hermes packages while leaving `pnpm-lock.yaml` out of the PR per repository policy. ## Verification Targeted local verification recorded before PR handoff: - `pnpm --filter @paperclipai/hermes-paperclip-adapter exec vitest run src/gateway/server/execute.test.ts` — 14/14 passed. - `pnpm test:hermes-gateway-smoke` — 6/6 passed. - Hermes package typecheck/build checks passed. - Focused server/UI adapter tests passed — 31/31. - Release helper Node tests passed — 18/18. - `git diff --check origin/master..HEAD` passed. Fresh Docker E2E smoke evidence: - Ran `pnpm smoke:hermes-gateway-e2e` on 2026-06-26 with a fresh state directory and fresh Docker container against a live Paperclip dev server. - Hermes direct execution reached `completed`. - Hermes stop/cancel path reached `cancelled`. - Hermes gateway created a Paperclip task, Paperclip ran the Hermes agent, and the task reached `done` with the expected marker response. - Temporary board auth keys, token files, smoke state, and Docker containers were cleaned up after the run. PR checks on head `b5eae40ce`: - GitHub Actions passed: `policy`, `review`, `Typecheck + Release Registry`, all general test shards, all serialized server shards, `Build`, `Canary Dry Run`, `e2e`, and aggregate `verify`. - External checks passed: Snyk and Socket Project Report. - External Socket Pull Request Alerts remained pending after the first-party CI matrix completed. ## Risks - Medium risk: this spans adapter registration, package publishing, gateway execution, onboarding docs, API-key scoping, and UI adapter metadata. - Migration risk is low: the scope-config migration adds a nullable column and does not rewrite existing keys. - Gateway execution depends on operator-provided Hermes API configuration; the smoke covers the Docker gateway path but real deployments may differ by network/auth setup. - Direct Greptile review on the latest expanded diff is file-count limited, although the commitperclip review gate passed. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex, GPT-5 coding agent, tool use enabled in a local repository workspace. Context window size is not exposed in this environment. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Commitperclip review gate is green; direct Greptile review is file-count limited on the latest expanded diff - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |