Expose adapter-discovered user-installed skills with provenance metadata, share persistent skill snapshot classification across local adapters, and render unmanaged skills as a read-only section in the agent skills UI.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Address Greptile review feedback:
1. Wrap os.userInfo() in try/catch — it throws SystemError when the
current UID has no /etc/passwd entry (e.g. `docker run --user 1234`
with a minimal image). Falls back to process.env.HOME gracefully.
2. Add HOME to VOLATILE_ENV_KEY_EXACT so the discovery cache key is
not affected by the caller-supplied HOME vs the resolved HOME.
os.userInfo().homedir is constant for the process lifetime, so
HOME adds no useful cache differentiation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When Paperclip's server is started via `runuser -u node` (common in
Docker/Fly.io deployments), the HOME environment variable retains the
parent process's value (e.g. /root) instead of the target user's home
directory (/home/node). This causes `opencode models` to miss provider
auth credentials stored under the actual user's home, resulting in
"Configured OpenCode model is unavailable" errors for providers that
require API keys (e.g. zai/zhipuai).
Fix: use `os.userInfo().homedir` (reads from /etc/passwd, not env) to
ensure the child process always sees the correct HOME, regardless of
how the server was launched.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract all Anthropic credential/API logic into claude-local/src/server/quota.ts
- Extract all OpenAI/WHAM credential/API logic into codex-local/src/server/quota.ts
- Add optional getQuotaWindows() to ServerAdapterModule in adapter-utils
- Rewrite quota-windows.ts as a 29-line thin aggregator with zero provider knowledge
- Wire getQuotaWindows into adapter registry for claude-local and codex-local
- Add 47 unit tests covering toPercent, secondsToWindowLabel, WHAM normalization,
readClaudeToken, readCodexToken, fetchClaudeQuota, fetchCodexQuota, fetchWithTimeout
- Add 8 unit tests covering parseDateRange validation and byProvider pro-rata math
Adding a third provider now requires only touching that provider's adapter.
The $AGENT_HOME environment variable was referenced by skills (e.g.
para-memory-files) but never actually set, causing runtime errors like
"/HEARTBEAT.md: No such file or directory" when agents tried to resolve
paths relative to their home directory.
Add agentHome to the paperclipWorkspace context in the heartbeat service
and propagate it as the AGENT_HOME env var in all local adapters.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- reapOrphanedRuns() now only scans running runs; queued runs are
legitimately absent from runningProcesses (waiting on concurrency
limits or issue locks) so including them caused false process_lost
failures (closes#90)
- Add module-level activeRunExecutions set so non-child-process adapters
(http, openclaw) are protected from the reaper during execution
- Add resumeQueuedRuns() to restart persisted queued runs after a server
restart, called at startup and each periodic tick
- Add outer catch in executeRun() so setup failures (ensureRuntimeState,
resolveWorkspaceForRun, etc.) are recorded as failed runs instead of
leaving them stuck in running state
- Guard resumeQueuedRuns() against paused/terminated/pending_approval agents
- Increase opencode models discovery timeout from 20s to 45s
* public-gh/master:
Default Gemini adapter to yolo mode and add API access prompt note
fix: remove Cmd+1..9 company-switch shortcut
fix(ui): prevent IME composition Enter from moving focus in new issue title
fix(cli): add restart hint after allowed-hostname change
docs: remove obsolete TODO for CONTRIBUTING.md
fix: default dangerouslySkipPermissions to true for unattended agents
fix: route heartbeat cost recording through costService
Show issue creator in properties sidebar
Gemini CLI only registers run_shell_command in --approval-mode yolo.
Non-yolo modes don't expose it at all, making Paperclip API calls
impossible. Always pass --approval-mode yolo and remove the now-unused
policy engine code, approval mode config, and UI toggles.
Add a "Paperclip API access note" to the prompt with curl examples
via run_shell_command, since the universal SKILL.md is tool-agnostic.
Also extract structured question events from Gemini assistant messages
to support interactive approval flows.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The OpenClaw Gateway's agent method has strict parameter validation
that rejects unknown properties. The paperclip property was being
sent at the root level of agentParams, causing validation failures
with error: "invalid agent params: at root: unexpected property 'paperclip'"
The paperclip metadata is already included in the message field
via wakeText, so removing the separate paperclip property resolves
the validation error while preserving the necessary information.
Fixes#606
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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.