gecko-surf 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gecko_surf-0.1.0/.dockerignore +19 -0
- gecko_surf-0.1.0/.env.example +287 -0
- gecko_surf-0.1.0/.gitignore +33 -0
- gecko_surf-0.1.0/.mcp.json.example +21 -0
- gecko_surf-0.1.0/Dockerfile +56 -0
- gecko_surf-0.1.0/LICENSE +21 -0
- gecko_surf-0.1.0/PKG-INFO +14 -0
- gecko_surf-0.1.0/README.md +250 -0
- gecko_surf-0.1.0/examples/__init__.py +0 -0
- gecko_surf-0.1.0/examples/_starter/README.md +45 -0
- gecko_surf-0.1.0/examples/_starter/__init__.py +1 -0
- gecko_surf-0.1.0/examples/_starter/app.py +71 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/README.md +80 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/__init__.py +0 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/__main__.py +6 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/agent.py +76 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/bot.py +234 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/config.py +90 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/providers.py +170 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/serve_sos_mcp.py +32 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/spec/sosvenezuela_openapi.json +212 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/surfcall_tools.py +90 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/tests/__init__.py +0 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/tests/test_agent_loop.py +124 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/tests/test_bot_handlers.py +52 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/tests/test_commands.py +81 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/tests/test_first_call_correct.py +24 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/tests/test_format.py +31 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/tests/test_providers.py +171 -0
- gecko_surf-0.1.0/examples/sos_vzla_bot/tests/test_surfcall_tools.py +66 -0
- gecko_surf-0.1.0/gecko/__init__.py +34 -0
- gecko_surf-0.1.0/gecko/access.py +143 -0
- gecko_surf-0.1.0/gecko/binding.py +76 -0
- gecko_surf-0.1.0/gecko/caller.py +103 -0
- gecko_surf-0.1.0/gecko/catalog.py +75 -0
- gecko_surf-0.1.0/gecko/client.py +110 -0
- gecko_surf-0.1.0/gecko/corpus.py +203 -0
- gecko_surf-0.1.0/gecko/deeplinks.py +48 -0
- gecko_surf-0.1.0/gecko/demo.py +148 -0
- gecko_surf-0.1.0/gecko/entitlements.py +92 -0
- gecko_surf-0.1.0/gecko/evaluate.py +61 -0
- gecko_surf-0.1.0/gecko/http_server.py +259 -0
- gecko_surf-0.1.0/gecko/ingest.py +154 -0
- gecko_surf-0.1.0/gecko/mcp_server.py +74 -0
- gecko_surf-0.1.0/gecko/netguard.py +159 -0
- gecko_surf-0.1.0/gecko/sample.py +53 -0
- gecko_surf-0.1.0/gecko/serve.py +148 -0
- gecko_surf-0.1.0/gecko/serve_mcp.py +52 -0
- gecko_surf-0.1.0/gecko/surfaces.py +82 -0
- gecko_surf-0.1.0/gecko/tools.py +121 -0
- gecko_surf-0.1.0/gecko/validator.py +52 -0
- gecko_surf-0.1.0/infra/cleanup-orphaned-stacks.sh +102 -0
- gecko_surf-0.1.0/infra/deploy.sh +153 -0
- gecko_surf-0.1.0/infra/ecs-stack.yml +431 -0
- gecko_surf-0.1.0/pyproject.toml +53 -0
- gecko_surf-0.1.0/scripts/SUBSCRIBE.md +28 -0
- gecko_surf-0.1.0/scripts/pegana_eval.py +110 -0
- gecko_surf-0.1.0/scripts/subscribe.py +208 -0
- gecko_surf-0.1.0/scripts/subscribe.ts +83 -0
- gecko_surf-0.1.0/tests/fixtures/pegana_openapi.json +1 -0
- gecko_surf-0.1.0/tests/fixtures/txodds_docs.yaml +3346 -0
- gecko_surf-0.1.0/tests/test_access.py +50 -0
- gecko_surf-0.1.0/tests/test_binding.py +127 -0
- gecko_surf-0.1.0/tests/test_caller.py +48 -0
- gecko_surf-0.1.0/tests/test_catalog.py +38 -0
- gecko_surf-0.1.0/tests/test_client_mcp.py +54 -0
- gecko_surf-0.1.0/tests/test_corpus_controlplane.py +175 -0
- gecko_surf-0.1.0/tests/test_deeplinks.py +43 -0
- gecko_surf-0.1.0/tests/test_entitlements.py +79 -0
- gecko_surf-0.1.0/tests/test_healthz.py +50 -0
- gecko_surf-0.1.0/tests/test_http_server.py +239 -0
- gecko_surf-0.1.0/tests/test_ingest.py +61 -0
- gecko_surf-0.1.0/tests/test_netguard.py +104 -0
- gecko_surf-0.1.0/tests/test_pegana.py +99 -0
- gecko_surf-0.1.0/tests/test_public_api.py +54 -0
- gecko_surf-0.1.0/tests/test_sample.py +35 -0
- gecko_surf-0.1.0/tests/test_security.py +102 -0
- gecko_surf-0.1.0/tests/test_serve.py +55 -0
- gecko_surf-0.1.0/tests/test_starter.py +57 -0
- gecko_surf-0.1.0/tests/test_surfaces.py +86 -0
- gecko_surf-0.1.0/tests/test_tools.py +50 -0
- gecko_surf-0.1.0/tests/test_validator_demo.py +28 -0
- gecko_surf-0.1.0/uv.lock +1332 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Keep the build context small and secrets out of the image (invariant #1).
|
|
2
|
+
.git
|
|
3
|
+
.venv
|
|
4
|
+
__pycache__
|
|
5
|
+
*.pyc
|
|
6
|
+
.pytest_cache
|
|
7
|
+
.mypy_cache
|
|
8
|
+
.ruff_cache
|
|
9
|
+
# secrets / local env — must never enter the image
|
|
10
|
+
.env
|
|
11
|
+
.env.*
|
|
12
|
+
.env.tgbot
|
|
13
|
+
private/
|
|
14
|
+
# not needed at runtime
|
|
15
|
+
tests/
|
|
16
|
+
docs/
|
|
17
|
+
.github/
|
|
18
|
+
*.md
|
|
19
|
+
!README.md
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# Gecko — environment variables (gecko-api side)
|
|
3
|
+
# =============================================================================
|
|
4
|
+
#
|
|
5
|
+
# Two consumers read this file:
|
|
6
|
+
#
|
|
7
|
+
# 1. Local dev: `uv run uvicorn gecko_api.main:app` reads from .env via
|
|
8
|
+
# set -a; source .env; set +a (Settings.from_env() reads os.environ).
|
|
9
|
+
#
|
|
10
|
+
# 2. Deploy: ./infra/push-ssm-params.sh maps each non-empty value into
|
|
11
|
+
# /gecko-api/<NAME> as a SecureString in AWS SSM. ECS tasks then read
|
|
12
|
+
# these via the `secrets:` block in the CloudFormation task definition.
|
|
13
|
+
#
|
|
14
|
+
# End users (Claude Code skill) never touch this file. Their wallet lives at
|
|
15
|
+
# ~/.agentwallet/config.json (frames.ag) and gecko-mcp talks to the deployed
|
|
16
|
+
# gecko-api at https://api.geckovision.tech — no local secrets needed.
|
|
17
|
+
# =============================================================================
|
|
18
|
+
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
# Required — database + ingestion
|
|
21
|
+
# ---------------------------------------------------------------------------
|
|
22
|
+
SUPABASE_URL=
|
|
23
|
+
SUPABASE_SERVICE_ROLE_KEY=
|
|
24
|
+
TAVILY_API_KEY=
|
|
25
|
+
OPENAI_API_KEY=
|
|
26
|
+
|
|
27
|
+
# Optional — only needed for `tests/eval/runner.py --live`.
|
|
28
|
+
# The eval harness uses Claude Sonnet 4.6 as the rubric judge (cross-family
|
|
29
|
+
# scoring reduces same-family bias). Mock mode does not need this.
|
|
30
|
+
ANTHROPIC_API_KEY=
|
|
31
|
+
|
|
32
|
+
# ---------------------------------------------------------------------------
|
|
33
|
+
# Required — LLM routing
|
|
34
|
+
# ---------------------------------------------------------------------------
|
|
35
|
+
# Two paths — pick one (uncomment the block):
|
|
36
|
+
#
|
|
37
|
+
# Path A: OpenAI direct (recommended for deploy until ClawRouter is hosted).
|
|
38
|
+
# GECKO_LLM_ENDPOINT=https://api.openai.com/v1
|
|
39
|
+
# GECKO_LLM_API_KEY=${OPENAI_API_KEY}
|
|
40
|
+
# CHAT_MODEL=gpt-4o-mini
|
|
41
|
+
#
|
|
42
|
+
# Path B: ClawRouter local proxy (v3 demo path; not viable on Fargate yet
|
|
43
|
+
# unless we run ClawRouter as a sidecar — defer post-MVP).
|
|
44
|
+
# GECKO_LLM_ENDPOINT=http://localhost:8402/v1
|
|
45
|
+
# GECKO_LLM_API_KEY=x402
|
|
46
|
+
# CHAT_MODEL=openai/gpt-4o
|
|
47
|
+
GECKO_LLM_ENDPOINT=https://api.openai.com/v1
|
|
48
|
+
GECKO_LLM_API_KEY=
|
|
49
|
+
CHAT_MODEL=gpt-4o-mini
|
|
50
|
+
|
|
51
|
+
# ---------------------------------------------------------------------------
|
|
52
|
+
# Pro tier — LLM routing (S1-01)
|
|
53
|
+
# ---------------------------------------------------------------------------
|
|
54
|
+
# Selects the OpenAI-compatible base URL the AG2 GroupChat hits. Per-agent
|
|
55
|
+
# model strings come from `gecko_core.orchestration.pro.router.model_matrix`.
|
|
56
|
+
# openai — direct api.openai.com (uses OPENAI_API_KEY)
|
|
57
|
+
# openrouter — https://openrouter.ai/api/v1 (uses OPENROUTER_API_KEY)
|
|
58
|
+
# clawrouter — http://localhost:8402/v1 (no auth; CLAWROUTER_URL overrides)
|
|
59
|
+
LLM_ROUTER=openai
|
|
60
|
+
# Required when LLM_ROUTER=openrouter. Ignored otherwise.
|
|
61
|
+
OPENROUTER_API_KEY=
|
|
62
|
+
# Optional — only used when LLM_ROUTER=clawrouter.
|
|
63
|
+
# CLAWROUTER_URL=http://localhost:8402/v1
|
|
64
|
+
|
|
65
|
+
# ---------------------------------------------------------------------------
|
|
66
|
+
# Required — x402 payments (devnet ↔ mainnet via SSM, no code changes)
|
|
67
|
+
# ---------------------------------------------------------------------------
|
|
68
|
+
# Mode:
|
|
69
|
+
# stub — local dev only; auto-settles, no real payment. NEVER deploy stub.
|
|
70
|
+
# live — real facilitator + on-chain settlement.
|
|
71
|
+
# x402 mode controls payment behavior:
|
|
72
|
+
# stub - synthetic receipts, no real USDC moved (DEFAULT for local dev)
|
|
73
|
+
# live - real Solana mainnet/devnet payments via x402 facilitator
|
|
74
|
+
# Flip to `live` only after:
|
|
75
|
+
# 1. Funding your client wallet with ~$1 SOL for gas
|
|
76
|
+
# 2. Setting GECKO_WALLET_ADDRESS to a treasury YOU control
|
|
77
|
+
# 3. Reading docs/test-plan.md → "Live-mode pre-flight"
|
|
78
|
+
# For one-off live calls, prefer: X402_MODE=live <command> (override per-call)
|
|
79
|
+
X402_MODE=stub
|
|
80
|
+
|
|
81
|
+
# Network. Friendly names — devnet for testing, mainnet for production.
|
|
82
|
+
# The CAIP-2 chain id, facilitator URL, and Solana cluster are all derived
|
|
83
|
+
# from this value (see gecko_core.payments.networks). Legacy CAIP-2 form
|
|
84
|
+
# (solana:EtW... / solana:5eyk...) is still accepted with a deprecation
|
|
85
|
+
# warning so existing SSM values don't break across one deploy.
|
|
86
|
+
X402_NETWORK=solana-devnet
|
|
87
|
+
|
|
88
|
+
# x402 facilitator URL. OPTIONAL — defaults to the per-network value:
|
|
89
|
+
# solana-devnet → https://www.x402.org/facilitator (free, no auth)
|
|
90
|
+
# solana-mainnet → https://api.cdp.coinbase.com/platform/v2/x402 (CDP)
|
|
91
|
+
# Set this only to override (e.g. staging, private gateway, PayAI fallback).
|
|
92
|
+
X402_FACILITATOR_URL=
|
|
93
|
+
|
|
94
|
+
# CDP credentials — REQUIRED when X402_NETWORK=solana-mainnet, ignored on
|
|
95
|
+
# devnet. Generate at https://portal.cdp.coinbase.com/access/api → "Create
|
|
96
|
+
# API Key". `KEY_ID` is public-ish; `KEY_SECRET` is the Ed25519 (or ES256)
|
|
97
|
+
# private key — keep it in 1Password, never commit. SSM holds both as
|
|
98
|
+
# SecureString. Sentinel `__unset__` triggers a clean startup error on
|
|
99
|
+
# mainnet rather than a confusing 401 at first paid request.
|
|
100
|
+
CDP_API_KEY_ID=
|
|
101
|
+
CDP_API_KEY_SECRET=
|
|
102
|
+
|
|
103
|
+
# Privy v2 server-side wallet credentials — REQUIRED for per-project wallet
|
|
104
|
+
# provisioning (S2-05). On `POST /projects` we create a Solana embedded
|
|
105
|
+
# wallet via Privy and persist its id/address on the project row. Without
|
|
106
|
+
# these set, `Settings.is_privy_configured()` returns False and provisioning
|
|
107
|
+
# is silently skipped — devnet without Privy keys still serves users without
|
|
108
|
+
# `project_id`. Generate at https://dashboard.privy.io → "Settings" → "API
|
|
109
|
+
# keys"; `APP_ID` (~26 chars, public-ish) and `APP_SECRET` (~105 chars,
|
|
110
|
+
# secret — keep in 1Password). SSM holds both as SecureString. Sentinel
|
|
111
|
+
# `__unset__` triggers the lazy-skip path rather than a hard boot error.
|
|
112
|
+
PRIVY_APP_ID=
|
|
113
|
+
PRIVY_APP_SECRET=
|
|
114
|
+
|
|
115
|
+
# ---------------------------------------------------------------------------
|
|
116
|
+
# twit.sh — X/Twitter data via x402 micropayments
|
|
117
|
+
# ---------------------------------------------------------------------------
|
|
118
|
+
# https://twit.sh — Pay $0.0025-$0.01 per X read via x402 on Base.
|
|
119
|
+
# The Gecko-owned wallet is server-managed (you fund it with USDC on Base).
|
|
120
|
+
# Disabled by default (TWITSH_ENABLED=false) — flip to "true" once funded.
|
|
121
|
+
# Sentinel "__unset__" on private key disables the integration silently
|
|
122
|
+
# regardless of TWITSH_ENABLED, so misconfigured deploys don't burn calls.
|
|
123
|
+
TWITSH_ENABLED=false
|
|
124
|
+
TWITSH_WALLET_PRIVATE_KEY=
|
|
125
|
+
TWITSH_WALLET_ADDRESS=
|
|
126
|
+
TWITSH_BASE_URL=https://x402.twit.sh
|
|
127
|
+
|
|
128
|
+
# Treasury address — Solana pubkey that RECEIVES USDC. Generate fresh for
|
|
129
|
+
# production (we only need the public key here; keep the secret in 1Password):
|
|
130
|
+
# uv run python -c "from solders.keypair import Keypair; kp=Keypair(); print(kp.pubkey())"
|
|
131
|
+
# Then send a tiny USDC transfer to it once so the SPL token account exists.
|
|
132
|
+
GECKO_WALLET_ADDRESS=
|
|
133
|
+
|
|
134
|
+
# Pricing (single quotes to keep the literal `$`, otherwise bash expands $0)
|
|
135
|
+
# '$0.10' — devnet/demo
|
|
136
|
+
# '$0.50' — mainnet starter
|
|
137
|
+
# '$20.00' — production target
|
|
138
|
+
RESEARCH_BASIC_PRICE='$0.10'
|
|
139
|
+
RESEARCH_PRO_PRICE='$0.75'
|
|
140
|
+
|
|
141
|
+
# ---------------------------------------------------------------------------
|
|
142
|
+
# Optional — V1 Decision Receipt (on-chain verdict-hash anchor, DEVNET ONLY)
|
|
143
|
+
# ---------------------------------------------------------------------------
|
|
144
|
+
# Anchors sha256(canonical_json(verdict_envelope)) as an SPL Memo on Solana
|
|
145
|
+
# devnet so a third party can verify "this agent checked before it acted".
|
|
146
|
+
# v0 = SPL Memo, devnet, NO real money (devnet airdrop pays the ~5000-lamport
|
|
147
|
+
# fee). DEFAULT OFF — the anchor signs + broadcasts a tx, so it is gated hard.
|
|
148
|
+
# Mainnet anchoring is the v1 PDA program, not this path.
|
|
149
|
+
#
|
|
150
|
+
# Enable the ANCHOR side (server that posts receipts):
|
|
151
|
+
# GECKO_RECEIPT_ENABLED=1
|
|
152
|
+
# GECKO_RECEIPT_RPC_URL=https://api.devnet.solana.com (must be devnet)
|
|
153
|
+
# GECKO_RECEIPT_ORACLE_KEYPAIR=/abs/path/devnet-oracle.json (gitignored)
|
|
154
|
+
# Generate the devnet keypair with: solana-keygen new -o devnet-oracle.json
|
|
155
|
+
# then `solana airdrop 1 <pubkey> --url devnet`. NEVER commit the keypair.
|
|
156
|
+
GECKO_RECEIPT_ENABLED=
|
|
157
|
+
GECKO_RECEIPT_RPC_URL=
|
|
158
|
+
GECKO_RECEIPT_ORACLE_KEYPAIR=
|
|
159
|
+
#
|
|
160
|
+
# Enable the VERIFIER side (public POST /v1/receipt/verify route). The PUBLIC
|
|
161
|
+
# key is safe to publish — it is the verification anchor. Set it + the devnet
|
|
162
|
+
# RPC so the route checks against the right oracle; unset → route returns 503.
|
|
163
|
+
GECKO_RECEIPT_ORACLE_PUBKEY=
|
|
164
|
+
|
|
165
|
+
# ---------------------------------------------------------------------------
|
|
166
|
+
# Optional — YouTube caption fallback
|
|
167
|
+
# ---------------------------------------------------------------------------
|
|
168
|
+
# Enables Deepgram nova-3 transcription when a YouTube video has no captions.
|
|
169
|
+
# Without it, those sources are silently skipped (~$0.0043/minute when used).
|
|
170
|
+
# DEEPGRAM_API_KEY=
|
|
171
|
+
# DEEPGRAM_MAX_AUDIO_MIN=30
|
|
172
|
+
|
|
173
|
+
# ---------------------------------------------------------------------------
|
|
174
|
+
# Client-side (gecko-mcp talking to gecko-api) — NOT pushed to SSM
|
|
175
|
+
# ---------------------------------------------------------------------------
|
|
176
|
+
# Lives in ~/.gecko/.env on the user's machine, not here. Default once
|
|
177
|
+
# deployed: https://api.geckovision.tech. Override only for local dev.
|
|
178
|
+
# GECKO_API_URL=http://localhost:8000
|
|
179
|
+
|
|
180
|
+
# ---------------------------------------------------------------------------
|
|
181
|
+
# Defaults — NOT pushed to SSM (pure code default)
|
|
182
|
+
# ---------------------------------------------------------------------------
|
|
183
|
+
GECKO_DEFAULT_TIER=basic
|
|
184
|
+
|
|
185
|
+
# ---------------------------------------------------------------------------
|
|
186
|
+
# Production judge transcript capture (S12-HARDEN-03)
|
|
187
|
+
# ---------------------------------------------------------------------------
|
|
188
|
+
# Every successful /research and /plan call writes one transcript record to
|
|
189
|
+
# disk for audit (compliance + post-hoc review of misranked verdicts surfaced
|
|
190
|
+
# by CDP Bazaar). Schema mirrors the eval-side capture in tests/eval/runner.
|
|
191
|
+
#
|
|
192
|
+
# Default: enabled in production, disabled under pytest (see tests/conftest.py).
|
|
193
|
+
# See docs/runbooks/cdp-bazaar.md § "Inspect public verdicts" for queries.
|
|
194
|
+
# GECKO_TRANSCRIPT_CAPTURE=true
|
|
195
|
+
#
|
|
196
|
+
# S12-HARDEN-05 — backend selection. Three modes:
|
|
197
|
+
# mongo → judge_transcripts collection in MongoDB (production default
|
|
198
|
+
# when MONGODB_URI is set; ECS Fargate has ephemeral disk so
|
|
199
|
+
# Mongo is the only durable store). Reuses MONGODB_URI and
|
|
200
|
+
# MONGODB_DB env vars already required for the twit.sh cache.
|
|
201
|
+
# If a write fails (network blip, auth fail), the dispatcher
|
|
202
|
+
# logs WARN and falls through to the filesystem store so a
|
|
203
|
+
# verdict is never lost.
|
|
204
|
+
# filesystem → one JSON file per session_id at GECKO_TRANSCRIPT_DIR (or
|
|
205
|
+
# /var/lib/gecko/judge_transcripts when writable, else
|
|
206
|
+
# /tmp/gecko/transcripts). Local dev / CI / fallback.
|
|
207
|
+
# noop → drop on the floor. Rare; differs from CAPTURE=false in
|
|
208
|
+
# intent only.
|
|
209
|
+
#
|
|
210
|
+
# Default when GECKO_TRANSCRIPT_STORE is unset: "mongo" if MONGODB_URI is set,
|
|
211
|
+
# otherwise "filesystem".
|
|
212
|
+
# GECKO_TRANSCRIPT_STORE=mongo
|
|
213
|
+
# GECKO_TRANSCRIPT_DIR=/var/lib/gecko/judge_transcripts # filesystem mode only
|
|
214
|
+
# MONGODB_URI=mongodb+srv://... # required for mongo mode
|
|
215
|
+
# MONGODB_DB=gecko_cache # default; shared with twit.sh cache
|
|
216
|
+
|
|
217
|
+
# ---------------------------------------------------------------------------
|
|
218
|
+
# S18-MONGO — chunk store (chunks + chunk_embedding_cache + chunks_write_audit)
|
|
219
|
+
# ---------------------------------------------------------------------------
|
|
220
|
+
# Cutover from Supabase pgvector to MongoDB Atlas Vector Search. Solo-user
|
|
221
|
+
# fresh-start cutover (no backfill). See docs/strategy/2026-05-02-s18-plan.md.
|
|
222
|
+
#
|
|
223
|
+
# GECKO_CHUNK_STORE selects the active store:
|
|
224
|
+
# supabase → legacy Postgres + pgvector (default during S18 dev)
|
|
225
|
+
# mongo → MongoDB Atlas (gecko_rag DB; flip after M5 cutover)
|
|
226
|
+
#
|
|
227
|
+
# MONGODB_URI is reused from the transcript store above. The chunk store lives
|
|
228
|
+
# in its own database (gecko_rag) and uses these collections:
|
|
229
|
+
# - chunks (vector + Atlas Search indexes; M1 schema)
|
|
230
|
+
# - chunk_embedding_cache (content-addressed embed cache)
|
|
231
|
+
# - chunks_write_audit (per-batch ingest observability)
|
|
232
|
+
#
|
|
233
|
+
# GECKO_CHUNK_STORE=supabase
|
|
234
|
+
# MONGODB_CHUNK_DB=gecko_rag # default for chunk store
|
|
235
|
+
|
|
236
|
+
# ---------------------------------------------------------------------------
|
|
237
|
+
# S22-VOYAGE-EMBED — embedding provider (default: voyage)
|
|
238
|
+
# ---------------------------------------------------------------------------
|
|
239
|
+
EMBED_PROVIDER=voyage
|
|
240
|
+
VOYAGE_API_KEY= # required when EMBED_PROVIDER=voyage
|
|
241
|
+
# EMBED_MODEL=voyage-context-3 # default — RAG-optimal context-aware embedding model
|
|
242
|
+
# # legacy voyage-3 still supported (same 1024 dim)
|
|
243
|
+
|
|
244
|
+
# ---------------------------------------------------------------------------
|
|
245
|
+
# S28 #25 — Cohere Rerank (post-retrieval semantic reranker).
|
|
246
|
+
# Wired into orchestration/trade_panel/retrieve_trade_corpus_chunks between
|
|
247
|
+
# `_apply_retrieval_boosts` and `_provider_quota_floor`. When unset, the
|
|
248
|
+
# rerank step degrades gracefully and the trade-panel falls through to the
|
|
249
|
+
# Path D baseline slate (still functional, no crash). Model: rerank-v3.5.
|
|
250
|
+
# Cost: ~$1.20 per 1000 verdicts at 180-doc pool.
|
|
251
|
+
# ---------------------------------------------------------------------------
|
|
252
|
+
COHERE_API_KEY= # optional — enables Cohere rerank-v3.5 in trade-panel retrieval
|
|
253
|
+
|
|
254
|
+
# ---------------------------------------------------------------------------
|
|
255
|
+
# OKX OnchainOS Market — developer key (OK-ACCESS-KEY header).
|
|
256
|
+
# Drives gecko_core.sources.okx_onchainos_market: token metrics (mcap /
|
|
257
|
+
# liquidity / 24h volume / holders count), top-20 holder concentration, and
|
|
258
|
+
# the manipulation-resistant composite index price. Distinct from OKX_API_KEY
|
|
259
|
+
# (the Bearer-token news adapter). Unset → client disabled, all methods
|
|
260
|
+
# fail-OPEN to None/[]. Base: https://web3.okx.com (override OKX_BASE_URL N/A;
|
|
261
|
+
# base is a client kwarg).
|
|
262
|
+
# ---------------------------------------------------------------------------
|
|
263
|
+
OKX_ONCHAINOS_API_KEY= # optional — OnchainOS Market developer key
|
|
264
|
+
|
|
265
|
+
# Helius API — get a key at https://dev.helius.xyz
|
|
266
|
+
HELIUS_API_KEY=
|
|
267
|
+
# Colosseum Copilot (optional) — for startup research skill
|
|
268
|
+
# Get a PAT at https://arena.colosseum.org/copilot
|
|
269
|
+
COLOSSEUM_COPILOT_PAT=
|
|
270
|
+
COLOSSEUM_COPILOT_API_BASE=https://copilot.colosseum.com/api/v1
|
|
271
|
+
# QEDGen formal verification (optional) — requires qedgen CLI
|
|
272
|
+
# Get a key at https://console.mistral.ai
|
|
273
|
+
MISTRAL_API_KEY=
|
|
274
|
+
# TheGrid (optional) — for Colosseum project graph queries
|
|
275
|
+
# Get a key at https://thegrid.id
|
|
276
|
+
THEGRID_API_KEY=
|
|
277
|
+
THEGRID_GRAPHQL_ENDPOINT=https://beta.node.thegrid.id/graphql
|
|
278
|
+
# QuickNode (optional) — for QuickNode RPC/Streams/DAS
|
|
279
|
+
# Get endpoints at https://www.quicknode.com
|
|
280
|
+
QUICKNODE_RPC_URL=
|
|
281
|
+
QUICKNODE_WSS_URL=
|
|
282
|
+
QUICKNODE_API_KEY=
|
|
283
|
+
# X/Twitter (optional) — for CT alpha research skill
|
|
284
|
+
# Get a bearer token at https://developer.x.com
|
|
285
|
+
X_BEARER_TOKEN=
|
|
286
|
+
# DFlow (optional) — for DFlow order flow integration
|
|
287
|
+
DFLOW_API_KEY=
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
.venv/
|
|
5
|
+
*.egg-info/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
|
|
9
|
+
# Test / tooling
|
|
10
|
+
.pytest_cache/
|
|
11
|
+
.ruff_cache/
|
|
12
|
+
.mypy_cache/
|
|
13
|
+
|
|
14
|
+
# Env / secrets — ship .env.example only
|
|
15
|
+
.env
|
|
16
|
+
.env.*
|
|
17
|
+
!.env.example
|
|
18
|
+
|
|
19
|
+
# OS / editor
|
|
20
|
+
.DS_Store
|
|
21
|
+
.idea/
|
|
22
|
+
*.swp
|
|
23
|
+
|
|
24
|
+
# Strategy / business docs — never in the public tree (canonical set lives in Notion)
|
|
25
|
+
private/
|
|
26
|
+
docs/
|
|
27
|
+
CLAUDE.md
|
|
28
|
+
|
|
29
|
+
# Claude Code local config, agents, and skills (internal)
|
|
30
|
+
.claude/
|
|
31
|
+
|
|
32
|
+
# MCP — real config carries a token; ship .mcp.json.example instead
|
|
33
|
+
.mcp.json
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"context7": {
|
|
4
|
+
"command": "npx",
|
|
5
|
+
"args": [
|
|
6
|
+
"-y",
|
|
7
|
+
"@upstash/context7-mcp@latest"
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
"github": {
|
|
11
|
+
"command": "npx",
|
|
12
|
+
"args": [
|
|
13
|
+
"-y",
|
|
14
|
+
"@modelcontextprotocol/server-github"
|
|
15
|
+
],
|
|
16
|
+
"env": {
|
|
17
|
+
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# surfcall — MCP Streamable-HTTP container (Python + uv + uvicorn on port 8000)
|
|
3
|
+
#
|
|
4
|
+
# Single-package repo (NOT a uv workspace). Stage 1 builds the venv with the
|
|
5
|
+
# `serve` extra (mcp[cli] + uvicorn -> pulls starlette). Stage 2 copies the venv
|
|
6
|
+
# + the surfcall package + the one local OpenAPI spec the container serves.
|
|
7
|
+
# Stateless: no DB/SSM/secrets at build or run time (control plane only).
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
FROM python:3.12-slim AS builder
|
|
11
|
+
|
|
12
|
+
# uv (Astral): static binary from the official image (slim has no curl/wget).
|
|
13
|
+
COPY --from=ghcr.io/astral-sh/uv:0.5.30 /uv /usr/local/bin/uv
|
|
14
|
+
|
|
15
|
+
WORKDIR /app
|
|
16
|
+
|
|
17
|
+
# Manifests + source first, so `uv sync` can build the flat-layout package.
|
|
18
|
+
COPY pyproject.toml uv.lock README.md ./
|
|
19
|
+
COPY surfcall ./surfcall
|
|
20
|
+
|
|
21
|
+
# Engine + the serve extra (mcp[cli], uvicorn, starlette). --no-dev drops
|
|
22
|
+
# mypy/pytest/ruff; --frozen pins to uv.lock (must resolve the serve extra).
|
|
23
|
+
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
24
|
+
uv sync --frozen --no-dev --extra serve
|
|
25
|
+
|
|
26
|
+
# -----------------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
FROM python:3.12-slim AS runner
|
|
29
|
+
|
|
30
|
+
RUN useradd --create-home --shell /bin/bash surfcall
|
|
31
|
+
|
|
32
|
+
WORKDIR /app
|
|
33
|
+
|
|
34
|
+
COPY --from=builder /app/.venv ./.venv
|
|
35
|
+
COPY --from=builder /app/pyproject.toml /app/uv.lock /app/README.md ./
|
|
36
|
+
COPY surfcall ./surfcall
|
|
37
|
+
# The one OpenAPI spec the container comprehends + serves. Control plane only:
|
|
38
|
+
# no payloads, no secrets.
|
|
39
|
+
COPY examples/sos_vzla_bot/spec ./examples/sos_vzla_bot/spec
|
|
40
|
+
|
|
41
|
+
RUN chown -R surfcall:surfcall /app
|
|
42
|
+
USER surfcall
|
|
43
|
+
|
|
44
|
+
ENV PATH="/app/.venv/bin:$PATH" \
|
|
45
|
+
PYTHONUNBUFFERED=1 \
|
|
46
|
+
PYTHONDONTWRITEBYTECODE=1 \
|
|
47
|
+
PORT=8000
|
|
48
|
+
|
|
49
|
+
EXPOSE 8000
|
|
50
|
+
|
|
51
|
+
# Mirror the ALB target-group health check (GET /healthz, matcher 200) locally.
|
|
52
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
|
|
53
|
+
CMD python -c "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8000/healthz', timeout=3).status==200 else 1)" || exit 1
|
|
54
|
+
|
|
55
|
+
# Bind 0.0.0.0:$PORT, mode=live, allowlist mcp.geckovision.tech.
|
|
56
|
+
CMD ["python", "-m", "surfcall.serve_mcp"]
|
gecko_surf-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gecko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gecko-surf
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Make any API agent-usable without integration code. V1: comprehension layer — turn a human-shaped OpenAPI surface into question-shaped, first-call-correct agent tools. (Working name; rename on brand pick.)
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: pyyaml>=6.0
|
|
8
|
+
Provides-Extra: serve
|
|
9
|
+
Requires-Dist: mcp[cli]>=1.28.1; extra == 'serve'
|
|
10
|
+
Requires-Dist: uvicorn>=0.49.0; extra == 'serve'
|
|
11
|
+
Provides-Extra: sosbot
|
|
12
|
+
Requires-Dist: anthropic>=0.40; extra == 'sosbot'
|
|
13
|
+
Requires-Dist: openai>=1.40; extra == 'sosbot'
|
|
14
|
+
Requires-Dist: python-telegram-bot>=21; extra == 'sosbot'
|