Adds support for Hermes Agent (https://github.com/NousResearch/hermes-agent)
as a managed employee in Paperclip companies.
Hermes Agent is a full-featured AI agent by Nous Research with 30+ native
tools, persistent memory, session persistence, 80+ skills, MCP support,
and multi-provider model access.
Changes:
- Add 'hermes_local' to AGENT_ADAPTER_TYPES (packages/shared)
- Add @nousresearch/paperclip-adapter-hermes dependency (server)
- Register hermesLocalAdapter in the adapter registry (server)
The adapter package is maintained at:
https://github.com/NousResearch/hermes-paperclip-adapter
- Update stale doc comment in index.ts to reflect direct ~/.gemini/skills/
injection instead of tmpdir approach
- Remove bare GEMINI_API_KEY/GOOGLE_API_KEY from auth regex to prevent
false positives when those strings appear in assistant output
- Align hello probe sandbox/approvalMode flags with execute.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GEMINI_CLI_HOME pointed to a tmpdir which broke OAuth auth since the CLI
couldn't find credentials in the real home directory.
Instead, inject Paperclip skills directly into ~/.gemini/skills/ (matching
the pattern used by cursor, codex, pi, and opencode adapters). This lets
the Gemini CLI find both auth credentials and skills in their natural
location without any GEMINI_CLI_HOME override.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Gemini CLI supports OAuth login via `gemini auth login` which stores
credentials locally without setting any env vars. The previous warn-level
check on missing GEMINI_API_KEY caused false alarms when CLI-based OAuth
was used. The hello probe that follows is the real auth authority — if
auth is actually broken, it will catch it and report appropriately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Incorporate improvements from PR #13 and #105 into the gemini-local adapter:
- Add detectGeminiAuthRequired() for runtime auth failure detection with
errorCode: "gemini_auth_required" on execution results
- Add isGeminiTurnLimitResult() to detect exit code 53 / turn_limit status
and clear session to prevent stuck sessions on next heartbeat
- Add describeGeminiFailure() for structured error messages from parsed
result events including errors array extraction
- Return parsed resultEvent in resultJson instead of raw stdout/stderr
- Add isRetry guard to prevent stale session ID fallback after retry
- Replace boolean yolo with approvalMode string (default/auto_edit/yolo)
with backwards-compatible config.yolo fallback
- Add sandbox config option (--sandbox / --sandbox=none)
- Add GOOGLE_GENAI_USE_GCA auth detection in environment test
- Consolidate auth detection regex into shared detectGeminiAuthRequired()
- Add gemini-2.0-flash and gemini-2.0-flash-lite model IDs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Isolate skills injection using a temporary directory mapped via
GEMINI_CLI_HOME, mirroring the claude-local sandbox approach
instead of polluting the global ~/.gemini/skills directory.
- Update the environment probe to use `--output-format stream-json`
so the payload matches the downstream parseGeminiJsonl parser.
- Deduplicate `firstNonEmptyLine` helper by extracting it to a
shared `utils.ts` module.
- Clean up orphaned internal exports and update adapter documentation.
When the Paperclip server is started from within a Claude Code session
(e.g. `npx paperclipai run` in a Claude Code terminal), the `CLAUDECODE`
and related env vars (`CLAUDE_CODE_ENTRYPOINT`, `CLAUDE_CODE_SESSION`,
`CLAUDE_CODE_PARENT_SESSION`) leak into `process.env`. Since
`runChildProcess()` spreads `process.env` into the child environment,
every spawned `claude` CLI process inherits these vars and immediately
exits with: "Claude Code cannot be launched inside another Claude Code
session."
This is particularly disruptive for the `claude-local` adapter, where
every agent run spawns a `claude` child process. A single contaminated
server start (or cron job that inherits the env) silently breaks all
agent executions until the server is restarted in a clean environment.
The fix deletes the four known Claude Code nesting-guard env vars from
the merged environment before passing it to `spawn()`.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Added disableSignUp to authConfigSchema in config-schema.ts
- Added authDisableSignUp to Config interface
- Added parsing from PAPERCLIP_AUTH_DISABLE_SIGN_UP env or config file
- Passed to better-auth emailAndPassword.disableSignUp
When true, blocks new user registrations on public instances.
Defaults to false (backward compatible).
Fixes#241
Move duplicated roleLabels map from AgentProperties.tsx, Agents.tsx,
OrgChart.tsx, and agent-config-primitives.tsx into AGENT_ROLE_LABELS
in packages/shared/src/constants.ts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The local migrationsFolder variable in migratePostgresIfEmpty duplicated
the module-level MIGRATIONS_FOLDER constant. Reuse the constant to keep
a single source of truth for the migration path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
URL.pathname returns /C:/... on Windows, causing doubled drive letters
when Node prepends the current drive. fileURLToPath handles this
correctly across platforms.
Fixes#132
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update cwd test to expect an error for missing directories (matches
createIfMissing: false accepted from review)
- Add warn-level check for non-ProviderModelNotFoundError failures
during best-effort model discovery when no model is configured
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move costUsd to top-level return field in parseOpenCodeJsonl (out of usage)
- Fix session-not-found regex to match "Session not found" pattern
- Use callID for toolUseId in UI stdout parser, add status/metadata header
- Fix CLI formatter: separate tool_call/tool_result lines, split step_finish
- Enable createIfMissing for cwd validation in environment tests
- Add empty OPENAI_API_KEY override detection
- Classify ProviderModelNotFoundError as warning during model discovery
- Make model discovery best-effort when no model is configured
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update cwd test to expect an error for missing directories (matches
createIfMissing: false accepted from review)
- Add warn-level check for non-ProviderModelNotFoundError failures
during best-effort model discovery when no model is configured
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move costUsd to top-level return field in parseOpenCodeJsonl (out of usage)
- Fix session-not-found regex to match "Session not found" pattern
- Use callID for toolUseId in UI stdout parser, add status/metadata header
- Fix CLI formatter: separate tool_call/tool_result lines, split step_finish
- Enable createIfMissing for cwd validation in environment tests
- Add empty OPENAI_API_KEY override detection
- Classify ProviderModelNotFoundError as warning during model discovery
- Make model discovery best-effort when no model is configured
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document observed failures before wake-text fix and successful
stock-clean lane pass after fix. Note instrumentation lane limitations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Include the full Paperclip API workflow (checkout, fetch, update) and
endpoint bans in the wake text sent to OpenClaw agents, preventing
them from guessing non-existent endpoints. Applied to both openclaw
and openclaw_gateway adapters.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Major improvements to the Pi local adapter:
Bug Fixes (Greptile-identified):
- Fix string interpolation in models.ts error message (was showing literal ${detail})
- Fix tool matching in parse.ts to use toolCallId instead of toolName for correct
multi-call handling and result assignment
- Fix dead code in execute.ts by tracking instructionsReadFailed flag
Feature Improvements:
- Switch from print mode (-p) to RPC mode (--mode rpc) to prevent agent from
exiting prematurely and ensure proper lifecycle completion
- Add stdin command sending via JSON-RPC format for prompt delivery
- Add line buffering in execute.ts to handle partial JSON chunks correctly
- Filter RPC protocol messages (response, extension_ui_request, etc.) from transcript
Cost Tracking:
- Extract cost and usage data from turn_end assistant messages
- Support both Pi format (input/output/cacheRead/cost.total) and generic format
- Add tests for cost extraction and accumulation across multiple turns
All tests pass (12/12), typecheck clean, server builds successfully.