Skip to content

c-api: expose liblightpanda.so and C header for embedding - #3096

Draft
arrufat wants to merge 21 commits into
mainfrom
c-api
Draft

c-api: expose liblightpanda.so and C header for embedding#3096
arrufat wants to merge 21 commits into
mainfrom
c-api

Conversation

@arrufat

@arrufat arrufat commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

A C ABI (include/lightpanda.h + src/c_api.zig) over the browser tool surface: lp_init/lp_shutdown, lp_fetch, sessions with lp_call/pump/ cancel, lp_tools_json. Built as a shared library only; the version script keeps everything but lp_* internal so the bundled OpenSSL/curl/ sqlite cannot collide with a host's own.

Embedders get a hidden 'embed' Config mode (not parseable from the CLI) with telemetry defaulting off; crash reports honor the same opt-out. ToolSession in lightpanda.zig owns the browser/session/ registry lifecycle the C API drives.

Build: C deps are always PIC (like boringssl's force_pic) and the pinned zig-v8-fork always builds V8 library-safe, so 'zig build lib' needs no flags. It only refuses -Dprebuilt_v8_path: today's published archives are exe-only (local-exec TLS, malloc shim); the guard goes away once a fork release ships library-safe archives. make lib-shared / lib-test / lib-shared-example drive it.

arrufat added 2 commits July 31, 2026 17:49
A C ABI (include/lightpanda.h + src/c_api.zig) over the browser tool
surface: lp_init/lp_shutdown, lp_fetch, sessions with lp_call/pump/
cancel, lp_tools_json. Built as a shared library only; the version
script keeps everything but lp_* internal so the bundled OpenSSL/curl/
sqlite cannot collide with a host's own.

Embedders get a hidden 'embed' Config mode (not parseable from the
CLI) with telemetry defaulting off; crash reports honor the same
opt-out. ToolSession in lightpanda.zig owns the browser/session/
registry lifecycle the C API drives.

Build: C deps are always PIC (like boringssl's force_pic) and the
pinned zig-v8-fork always builds V8 library-safe, so 'zig build
shared-lib' needs no flags. It only refuses -Dprebuilt_v8_path:
today's published archives are exe-only (local-exec TLS, malloc
shim); the guard goes away once a fork release ships library-safe
archives. make lib-shared / lib-test / lib-shared-example drive it.
@arrufat arrufat mentioned this pull request Aug 1, 2026

@karlseguin karlseguin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm building on MacOS now. Will update if there's an issue.

Three things (+ the telemetry-off decision that needs to be OKd)
1 - Consuming a C API from a non-C language is often tedious because of the null-terminated strings. I always prefer APIs that support both the ability to pass a null-terminated string OR a ptr + len
2 - All the error codes are opaque. You have an arena, so an lp_last_error that takes a SessionHandle woudl be nice
3 - Would be nice if the CI could build this, build an example, and verify its output.

Comment thread src/c_api.zig
Comment thread src/c_api.zig Outdated
Comment thread src/c_api.zig
Comment thread src/c_api.zig
Comment thread src/c_api.zig
karlseguin and others added 7 commits August 3, 2026 13:46
This was all Claude. I'm not good enough at builds. But the issue appears to be
that the MacOS build exports everything and the only solution is to hide them
at compile time. This does not work for v8 (which goes through its own build
system), but Claude says it's fine since those are mangled and would only
conflict if the user embedded v8 directly also.
Expose `lp_last_error` and `lp_browser_last_error` in the C API to
retrieve the error name of the most recent failing call.
Remove the `enable_telemetry` option from `lp_options` and `Config`. Telemetry opt-out is now managed solely via the `LIGHTPANDA_DISABLE_TELEMETRY` environment variable.
@arrufat

arrufat commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

@karlseguin regarding the example, I will add it once we provide pre-built v8 binaries with the latest changes.

arrufat and others added 4 commits August 3, 2026 09:57
Limit exported symbols to lp_* on MacOS
Ensure lp.Browser remains pointer-stable as it uses self-pointers.
Also simplify ToolSession cancel hooks and pkgconfig file generation.
@arrufat

arrufat commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Thank you, maybe we should wait for @krichprollsch in case he has some ideas on what the C API should look like.
Ah, and it needs to be coordinated with a new release of v8, and the telemetry server, too.

@arrufat
arrufat requested a review from krichprollsch August 14, 2026 06:15
@arrufat

arrufat commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Note from the ToolSession follow-up (#3312): a reuse pass flagged that writeToolsJson here and Tool.jsonStringify in mcp/protocol.zig duplicate the tools/list serializer. What they actually share is the three raw-JSON lines for inputSchema; the rest differs on purpose (MCP emits title and the annotations, plus the save/session_* extras). So the question is whether lp_tools_json should carry title and annotations too. If yes, one shared struct falls out naturally; if no, the two writers should stay separate. Leaving that to this PR rather than a dedup change.

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.

2 participants