examples/plugin/jshandler/README.md
A CLIProxyAPI plugin that executes external JavaScript scripts to intercept and modify requests, responses, and streaming chunks using the Goja VM engine.
on_before_request): Modify request payloads and headers before upstream delivery.on_after_nonstream_response): Modify non-streaming response bodies and headers.on_after_stream_response): Modify individual streaming chunks with read-only history_chunks context.plugins:
enabled: true
dir: "plugins-dir"
configs:
jshandler:
enabled: true
script_paths:
- /path/to/custom_handler.js
- ./relative_handler.js
timeout: 1s
| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Enable or disable the plugin |
script_paths | array | [] | JS script file paths (absolute or relative to plugin directory) |
timeout | string | 1s | Execution timeout per JS hook call |
Scripts can export these global functions:
on_before_request(ctx)Called before the request is sent upstream.
ctx structure:
{
"id": "request-id",
"body": "...", // Request body string
"headers": {}, // Request headers
"url": "",
"model": "gpt-4",
"protocol": "openai"
}
on_after_nonstream_response(ctx)Called after a non-streaming response is received from upstream.
ctx structure (non-streaming):
{
"id": "request-id",
"body": "...", // Full response body
"req": { "body": "...", "headers": {}, "url": "" },
"protocol": "openai",
"headers": {},
"chunk": null,
"history_chunks": null
}
on_after_stream_response(ctx)Called after each streaming response chunk is received from upstream.
ctx structure:
{
"id": "request-id",
"body": null,
"req": { "body": "...", "headers": {}, "url": "" },
"protocol": "openai",
"headers": {},
"chunk": "...", // Current writable chunk
"history_chunks": ["..."] // Read-only frozen array
}
Return the modified ctx object, or a plain string to replace the body/chunk.
The scripts/ directory contains built-in scripts loaded automatically:
copilot_handler.js: Fixes tool-call finish_reason for GitHub Copilot compatibility.make build
The Makefile chooses the plugin extension from the target platform:
| GOOS | Output |
|---|---|
linux / freebsd | jshandler.so |
darwin | jshandler.dylib |
windows | jshandler.dll |
You can override the target and output directory:
make build GOOS=darwin GOARCH=arm64 BUILD_DIR=/path/to/plugins/darwin/arm64