Skip to content

Feature/browserlend2#1

Merged
iWedmak merged 52 commits into
feature/python-sdkfrom
feature/browserlend2
May 27, 2026
Merged

Feature/browserlend2#1
iWedmak merged 52 commits into
feature/python-sdkfrom
feature/browserlend2

Conversation

@iWedmak

@iWedmak iWedmak commented May 27, 2026

Copy link
Copy Markdown
Contributor

No description provided.

ceki-plugin added 30 commits May 5, 2026 06:53
- Browser: CDP roundtrip with pending futures, error code mapping
  (-1011/-1012/-1013/-1015/-1018/-1050), session lifecycle,
  on_event/on_tab_opened callbacks, switch_tab, configure, close
- BrowserChat: send/send_image with ack, on_message/on_read callbacks,
  REST history endpoint; mime autodetect (PNG/JPEG/WEBP magic bytes),
  5MB size limit
- Client._dispatch: chat routing (chat.message/read/send_ack),
  per-session error routing
- Tests: 25 new tests covering CDP happy path, error codes, multi-session
  routing, tab_opened, chat send/ack, image mime detection, history
- Examples: navigate.py, captcha_helper.py
- reddit_signup.py: full Reddit signup flow via CDP — navigate, form fill,
  captcha screenshot→chat→answer, IMAP confirm-link parse
- github_signup.py: GitHub signup with multi-round captcha loop
- imap_helper.py: wait_for_confirm_link with IMAP4_SSL poll + regex
  for Reddit and GitHub confirm URLs, plus-addressing support
- examples/SMOKE.md: runbook with pre-requisites, env vars, checklists
- test_examples_signature.py: import + signature checks via inspect
- README.md: Real-signup examples section with disclaimer
relay.ittribe.org / relay.ceki.me never existed — relay runs at
browser.<domain>/ws/agent. Mirrors the same fix done for extension
config.ts in plugin/142.
…tion nullable

BREAKING: connect(api_key, ConnectOptions(...)) replaces kwargs.
- _connect.py: ConnectOptions dataclass (api_url, relay_url, basic_auth, reconnect)
- _config.py: prod-only defaults + CEKI_API_URL/CEKI_RELAY_URL env override
- _client.py: api_url + basic_auth fields; search() uses /api/browsers/search (plural);
  basic_auth forwarded as httpx.BasicAuth + WS extra_headers for relay upgrade
- _models.py: BrowserOption geo/language nullable, language singular added, extra='ignore'
- __init__.py: exports ConnectOptions, version 2.2.0
httpx.BasicAuth passed as auth= to AsyncClient would overwrite the
explicit Authorization: Bearer header, causing 401 on dev/staging where
nginx basic-auth sits in front of Laravel API.
…helpers + provider_user_id

- ChatMessage: _id alias, sender_id, text, media, type, created_at (drop message_id/sender_type/sent_at)
- ChatMessage.is_system(): returns type == 'system'
- ChatMessage.is_from_provider(uid): returns sender_id == uid
- Match.provider_user_id: parsed from relay match payload
- Browser.provider_user_id: property from match
- examples: replace msg.sender_type == 'provider' with is_system()/is_from_provider()
- tests: update fixtures (chat_topic_id as str), new unit tests for all helpers
…fast, handshake 429+4403 (BUG-3..6)

- _config.py: DEFAULT_CHAT_URL, default_chat_url() for separate chat host
- _connect.py: ConnectOptions.chat_url passed through to Client
- _client.py: Client.chat_url attr; 429 → RateLimitExceeded; WS 4401/4403 → AuthFailed; rent.error → ProviderOffline; chat.error → ChatSendFailed
- _chat.py: history() uses client.chat_url, before param (not before_id); send_image payload: filename+data_b64 (was base64); _on_send_error()
- _exceptions.py: ChatSendFailed, ProviderOffline
- tests/test_chat_history.py: new tests for history URL/params
…allbacks

- ProviderDisconnected(CekiError) raised when session ends with reason provider_disconnected
- Browser.on_provider_disconnected(cb) / on_provider_reconnected(cb) callbacks
- Dispatch session.provider_disconnected and session.provider_reconnected relay events
- Export ProviderDisconnected from package __init__
…restore

BrowserProfile wraps CDP calls to export cookies (with optional domain filter),
localStorage, and sessionStorage into a plain dict. import_() restores them
into a new session before/after first navigation.

Profile data stays agent-side — relay and backend never see it.
Handles rent.error with event_id (post-rent_pending) by resolving via _pending_rents.
Adds test_provider_offline.py with 2 pytest cases.
…5, reason↔message fallback

_connect() probes with 1s recv after websockets.connect() to catch post-handshake
4401/4403 close before any rent is pending. _handle_error maps -1015 to ProviderOffline.
reason or message fallback everywhere so relay errors don't stringify as "None".
Replace broken mvp_smoke_p2p.py with new mvp_smoke_v2.py in examples/smoke/.
Scenarios A-K using current public API: connect(), client.rent(), browser.send()
with raw CDP commands. Window init via Page.navigate about:blank before
Page.enable. Scenario A verified PASS against schedule 240.
…E_ID

- github_signup.py / reddit_signup.py: drop required SCHEDULE_ID env, default
  to client.search({})[0].schedule_id; SCHEDULE_ID kept as optional pin.
  Empty result → graceful exit (no blocking on a single offline provider).
- imap_helper.py + github_signup.py: thread EMAIL_BASE env through plus-tag
  IMAP search so non-kom@ceki.me addresses work.
Add navigate(), click(), type(), scroll(), screenshot(), set_human()
to Browser class. Humanizer wraps actions with pre/post delays and
per-char typing with jitter. Supports profiles: natural (default),
careful, custom dict/file, or None to disable.
Client.rent() accepts human= kwarg. Env vars: CEKI_HUMAN_PROFILE,
CEKI_HUMAN_PROFILE_PATH, CEKI_HUMAN_DISABLE.
SDK version bumped to 2.3.0. 14 new tests, 89 total passing.
- Add _last_pointer tracking to Browser (set by click/scroll)
- type() calls click() at last known pointer before insertText when humanizer is on
- Debug log when no pointer available, graceful fallback to plain insertText
- 4 test cases covering all humanizer × pointer combinations
- Bump version 2.3.2 → 2.3.3
- CLI entry point `ceki-browser` with 9 subcommands: rent, snapshot,
  navigate, click, type, scroll, chat send/next, stop
- Client.resume(session_id) reconnects to existing session via relay
- Browser.snapshot() captures screenshot + new chat messages
- State files in ~/.ceki/sessions/ for cross-process persistence
- New exceptions: SessionNotFound, SessionExpired, NotOwner
- Snapshot model, since param for chat.history
- README: CLI section with 3 examples, subcommand table, exit codes
- Version 2.3.3 → 2.4.0
Root cause: chat.history(since=ts) passes 'since' as HTTP param but
chat-service may not implement server-side filtering. Second snapshot
in a new process loads last_seen_ts from state file correctly, but
gets the same messages back from the server.

Fix: add client-side filtering in Browser.snapshot() — messages with
created_at <= last_seen_ts are excluded regardless of server behavior.
Also persist last_seen_ts from browser object rather than snap.chat
to handle edge cases.

Version 2.4.0 → 2.4.1
profile export/import, search, chat history, chat send-image,
wait, screenshot, switch-tab, configure, cdp. All 138 tests pass.
Version bumped to 2.5.0.
New Browser.upload() method and CLI `ceki-browser upload` subcommand.
Injects file via base64 + DataTransfer + change event into any
input[type=file]. MIME detection by extension, supports path and bytes.
Bump to v2.6.0.
…print=...)

- profile.export() includes Browser.getFingerprint response
- profile.import_() backward-compat v1 (no fingerprint)
- client.rent(fingerprint=dict|False|True) sends session.configure
- CLI: rent --fingerprint-from PROFILE.json
- v2.6.0 -> v2.7.0

Задача: 253-profile-fingerprint-persist.md от main
ceki-plugin added 22 commits May 13, 2026 08:09
- tests/e2e/test_fingerprint_persistence.py — real rent against browser.ittribe.org
- tests/e2e/README.md — setup and run instructions
- skipped by default (requires CEKI_API_KEY env var)

Задача: 254-profile-fingerprint-commit-release-e2e.md от main
… 0.6.102)

- profile.export() catches exception, sets fingerprint=None
- E2E test skips gracefully when extension too old
- new unit test: export_fingerprint_fallback_on_old_extension

Задача: 254-profile-fingerprint-commit-release-e2e.md от main
- browser.screenshot(full_page=True) uses Page.getLayoutMetrics + captureBeyondViewport
- CLI: ceki-browser screenshot <sid> -o file.png --full
- Safety clamp at 16384px height with warning
- Default behavior unchanged (viewport-only)
- v2.7.0 → v2.7.1

Задача: 255-screenshot-full-page.md от main
Emit real keyDown/keyUp CDP events per character instead of insertText,
so reCAPTCHA/hCaptcha see genuine keyboard event timing and sequence.

- Add humanize/keymap.py with US keyboard layout mapping
- Add _send_keystroke() helper: keyDown+keyUp with Shift wrapping
- Non-ASCII chars fall back to Input.insertText
- Bump version to 2.8.0
Backend requires browser_id in POST /api/sessions. CLI --schedule
param preserved for UX, mapped to browser_id internally.
Closes WS without sending session.end for active browsers.
Prevents reconnect-loop spawn on CLI subprocess exit.
All 16 subcommands now use the public disconnect() API
which properly sets _closed flag and cancels background tasks.
After #289 the SDK sends browser_id in the rent WS message, but test
assertions still expected schedule_id. Added disconnect-not-close guard
test. Bump 2.8.1.
CLI: --mode incognito|main. SDK: rent(schedule_id, mode='main').
Default incognito. v2.12.0
When relay sends match with requires_ack=true, SDK immediately
responds with match_ack to confirm session readiness before
billing starts.
- Browser.request_captcha(acceptance_timeout, completion_timeout, auto_accept)
- CaptchaResult with accept_work/reject_work for double-acceptance model
- CaptchaError + CaptchaTimeoutError exception classes
- CLI: ceki-browser request-captcha <sid> [--acceptance N] [--completion M]
- Action queue in BrowserChat for intercepting action messages
- Hard min 30s on both timeouts, max 300/600
- 4 tests: happy path, acceptance timeout, provider declined, min timeout
- Version bump 2.12.0 → 2.13.0
- accept_work/reject_work vote via /api/agent/kal/event/{id}/vote
- event store/expire via /api/agent/kal/event/* endpoints
- correction_id is now public on CaptchaResult
- raise CaptchaError when correction_id missing (was silent no-op)
- CLI: --manual flag, correction_id in output
- bump v2.14.0
acceptance_deadline_at / completion_deadline_at now sent as integer
seconds instead of ISO datetime strings. Contract aligned with
backend (ceki-back/168).
…nt}/captcha-request

Minimal payload with acceptance_deadline_at and completion_deadline_at only.
Backend resolves price from schedule settings.
GET /api/agent/sessions?active=1&limit=50. Table output by default,
--json for raw. --all shows non-active too.
Mirror CLI documentation from browser.ceki.me/docs — install, env vars,
quick start with search→rent chain, 4 command groups, exit codes.
Remove dev/staging code block containing *.ittribe.org URLs and basic-auth credentials.
Production URLs are already documented in ConnectOptions defaults table.
@iWedmak iWedmak merged commit edd0856 into feature/python-sdk May 27, 2026
0 of 3 checks passed
iWedmak added a commit that referenced this pull request May 27, 2026
Merge pull request #1 from Ceki-me/feature/browserlend2
@iWedmak iWedmak deleted the feature/browserlend2 branch May 28, 2026 14:11
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