Skip to content

feat(docker): add Claude CLI for claude-code LLM provider#301

Closed
slayoffer wants to merge 72 commits intovectorize-io:mainfrom
slayoffer:develop
Closed

feat(docker): add Claude CLI for claude-code LLM provider#301
slayoffer wants to merge 72 commits intovectorize-io:mainfrom
slayoffer:develop

Conversation

@slayoffer
Copy link
Contributor

Summary

  • Add Claude CLI (@anthropic-ai/claude-code) to Docker image for claude-code LLM provider support
  • Create /home/hindsight/.claude/ directory for credentials mount
  • Enable using Claude Pro/Max subscriptions via Agent SDK authentication in Docker containers

Changes

  • docker/standalone/Dockerfile: Install Claude CLI globally and create user directory

Test plan

  • Docker image builds successfully (verified via CI/CD)
  • Claude CLI accessible in container (claude --version returns 2.1.31)
  • Memory operations work with claude-code LLM provider (tested retain/recall on VM deployment)

Usage

Mount credentials file to container:

volumes:
  - ~/.claude/.credentials.json:/home/hindsight/.claude/.credentials.json:ro
environment:
  HINDSIGHT_API_LLM_PROVIDER: claude-code
  HINDSIGHT_API_LLM_MODEL: claude-sonnet-4-20250514
  CLAUDE_CODE_OAUTH_TOKEN: <your-oauth-token>  # Optional: pass token via env var

🤖 Generated with Claude Code

slayoffer and others added 30 commits January 16, 2026 07:10
All flagged text() calls use schema names from internal config
(Alembic context, test fixtures), not user input.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add HINDSIGHT_API_MCP_AUTH_TOKEN environment variable to enable
authentication for MCP endpoint. When set, all requests must include
a valid Authorization header (Bearer token or direct token).

If not set, MCP endpoint remains open for backwards compatibility
with local development environments.
Add GitHub Actions workflow to build and push Docker images to GCP Artifact Registry.

- Triggers on push to main or manual dispatch
- Builds standalone image with API + Control Plane + ML models
- Tags with :latest and commit SHA
- Uses GHA cache for faster rebuilds
- Frees disk space for large image build (~9GB)

Requires GCP_SA_KEY secret with Artifact Registry Writer role.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
feat: GCP Artifact Registry deployment + MCP Bearer auth
Fixes 'invalid byte sequence for encoding UTF8: 0x00' error during batch retain

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
MCP tools were creating RequestContext() without api_key, causing
"Invalid API key" errors when tenant extension validates requests.
Now the Bearer token is extracted in middleware, stored in a context
variable, and passed through to all MCP tool RequestContext instances.
fix: propagate Bearer token from MCP middleware to tools for tenant auth
Add 3 steps to deploy-gcp workflow: GCP auth, get-gke-credentials,
and kubectl rollout restart. Uses existing imagePullPolicy: Always
so a rollout restart pulls the freshly pushed :latest image.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
feat: sync with upstream + GKE auto-deploy
Split deploy into separate job with `environment: production`
so it requires manual approval before kubectl rollout restart.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously, _authenticate_tenant only skipped extension auth for
internal requests when _current_schema was set to a non-public schema.
This caused async HTTP retain (document upload with async_processing=True)
to fail with AuthenticationError because the worker had no API key and
the schema was "public".

Remove the public-schema guard since internal tasks were already
authenticated at submission time. The worker sets _current_schema from
the task's _schema field for tenant schemas, and it defaults to "public"
for public schema tasks — both are valid.
When the backend graph API returns an error, the SDK sets response.data
to undefined. NextResponse.json(undefined) throws "Value is not JSON
serializable". Check for error/missing data before serializing.
The control plane proxy routes never sent an Authorization header to
the dataplane API. With the tenant extension active, all GUI requests
failed with "Invalid API key".

Add HINDSIGHT_CP_DATAPLANE_API_KEY env var support to hindsight-client.ts
and propagate auth headers to both SDK clients and all direct fetch routes.
Deploy to hindsight-dev namespace on develop branch push.
Uses beta/beta-{sha} image tags, auto-deploys without approval.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move Docker image builds from GitHub Actions to Cloud Build for:
- Faster push to Artifact Registry (internal network vs internet)
- Unified pipeline (build + push + deploy in single Cloud Build)
- No more disk space hacks on GHA runners

Changes:
- Add cloudbuild.yaml with build/push/deploy steps
- Simplify deploy-gcp.yml and deploy-gcp-dev.yml to just trigger Cloud Build
- Use E2_HIGHCPU_8 machine type for faster builds

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The SA lacks serviceusage.services.use permission to upload source
to the Cloud Build bucket. Instead of granting broad permissions,
use --no-source and have Cloud Build clone the repo directly.

Changes:
- Pass Cloud Build config inline via heredoc
- Add git clone step to fetch repo from GitHub
- Checkout specific commit SHA for reproducibility
- Remove cloudbuild.yaml (config is now inline in workflows)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
gcloud builds submit --config - doesn't properly read from heredoc.
Write config to /tmp/cloudbuild.yaml first, then reference it.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Cloud Build requires full resource path format:
projects/PROJECT/serviceAccounts/SA@PROJECT.iam.gserviceaccount.com

Not just the email address.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove --no-source and git clone steps
- Upload source directly from GHA checkout
- Use $COMMIT_SHA substitution for image tags

Also granted:
- roles/serviceusage.serviceUsageConsumer (bucket access)
- roles/logging.logWriter (Cloud Build logs)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Build job: uses private worker pool for fast push to Artifact Registry
- Deploy job: uses default Cloud Build (no worker pool) which can reach GKE
- Private worker pool can't reach GKE control plane (network isolation)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
slayoffer and others added 28 commits February 2, 2026 10:52
feat: sync with upstream v0.4.6
Merged upstream/main bringing:
- Mental model extension hooks (billing/quota validation)
- hindsight-embed external API support
- OpenClaw fixes (port, daemon recovery, OpenRouter, macOS)
- Our PRs merged: null bytes (vectorize-io#238), tiktoken (vectorize-io#249)
- Worker default schema fix

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Upstream v0.4.7 sync

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
feat: sync with upstream v0.4.7
Document the new operation_validator extension hooks added in v0.4.7
for mental model billing/quota validation in SaaS deployments.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add exponential backoff retry (10s/20s/40s, 3 attempts) to
SentenceTransformer and CrossEncoder initialization to handle
transient network issues during model downloads (VPN instability,
HuggingFace Hub rate limits, connection drops).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
feat: add retry logic for ML model downloads at startup
Add Display Build Info and Verify Pushed Images steps to show:
- Commit SHA and branch being built
- Image tags being created
- Latest images in Artifact Registry after build

Helps debugging by showing image info directly in GHA logs instead
of requiring Cloud Logging access.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Show commit SHA and expected image tag before deploy
- After rollout completes, display running pod's imageID (digest)
- Remove CLOUD_LOGGING_ONLY from deploy step to stream logs to GHA
- Enables verification that correct image is deployed

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Merged 7 upstream commits:
- Fix: load operation validator extension in worker process (vectorize-io#280)
- fix: custom pg schema is not reliable (vectorize-io#278)
- feat(embed): add hindsight-embed profiles (vectorize-io#277)
- feat: support for codex and claude-code as llm (vectorize-io#276)
- feat: print version during startup (vectorize-io#275)
- feat(openclaw): add llmProvider/llmModel plugin config options (vectorize-io#274)
- Propagate request context through async task payloads (vectorize-io#273)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Cloud Build substitutions must start with underscore: _COMMIT_SHA

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ability to connect to an external/central Hindsight API instead of
running a local hindsight-embed daemon with embedded PostgreSQL.

Configuration options:
- HINDSIGHT_EMBED_API_URL env var or hindsightApiUrl config
- HINDSIGHT_EMBED_API_TOKEN env var or hindsightApiToken config

When external API is configured:
- Skip local daemon startup
- Set env vars for CLI commands to use external API
- Health check external API instead of local daemon
- Service lifecycle management adjusted for external mode

This allows unified memory across multiple OpenClaw instances by
connecting to a shared Hindsight server.

Also removes unused node-fetch import from client.ts.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add escapeShellArg() helper function for robust shell argument escaping
when executing CLI commands via exec().

The function properly escapes single quotes using the '\'' pattern,
which is the correct approach for single-quoted shell arguments where
all other characters (including ?, !, $, `, etc.) are literal.

Changes:
- Add well-documented escapeShellArg() function explaining the approach
- Apply escaping to all three locations: setBankMission, retain, recall
- Also escape docId parameter in retain() for completeness
- Add comprehensive tests covering all shell-special characters

Test coverage includes:
- Question marks, exclamation marks (history expansion)
- Backticks, dollar signs (command/variable substitution)
- Double quotes, backslashes, newlines
- Glob patterns (*, ?, [])
- Shell control chars (|, &, ;, <, >, etc.)
- Subshell/brace expansion characters
- Complex strings combining multiple special chars

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added vitest dependencies for running tests locally.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Each channel now gets isolated memory via bank ID derivation:
- Bank format: {messageProvider}-{channelId} (e.g., slack-C123)
- dynamicBankId config option (default: true)
- bankIdPrefix for namespace prefixing
- Bank mission auto-set on first use per bank
- Hook handlers updated to (event, ctx) signature
Custom service account requires logging option. Added Display Deploy Info
step in GHA to show expected image digest before Cloud Build deploy runs.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Custom service account requires logging option. Added Display Deploy Info
step in GHA to show expected image digest before Cloud Build deploy runs.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Merged upstream changes while preserving fork customizations:
- Upstream: embed UX improvements with rich logging and profile isolation
- Upstream: security dependency upgrades
- Upstream: embedPackagePath for local development
- Upstream: apiPort config for openclaw profile daemon
- Preserved: external Hindsight API support (hindsightApiUrl/hindsightApiToken)
- Preserved: dynamic per-channel memory banks (dynamicBankId/bankIdPrefix)
- Preserved: shell argument escaping with escapeShellArg()
Sync main with develop (v0.4.8)
# Conflicts:
#	hindsight-api/hindsight_api/engine/cross_encoder.py
#	hindsight-api/hindsight_api/engine/embeddings.py
#	hindsight-integrations/openclaw/openclaw.plugin.json
#	hindsight-integrations/openclaw/src/client.test.ts
#	hindsight-integrations/openclaw/src/types.ts
- Install @anthropic-ai/claude-code npm package globally
- Create .claude directory for hindsight user for credentials mount
- Enables claude-code LLM provider in Docker deployments

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
On ARM64 Linux (e.g., Docker on Apple Silicon), uvx hindsight-embed
triggers the CLI installer which tries to download a native binary
for linux-arm64 that doesn't exist (404 error).

Using the pre-installed hindsight-embed command directly (from
`uv tool install hindsight-embed`) avoids this issue and also
improves performance by skipping fresh environment creation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@slayoffer
Copy link
Contributor Author

Closing - PR contained too many unrelated commits. Will recreate with clean branch.

@slayoffer slayoffer closed this Feb 5, 2026
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.

1 participant