Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "papervizagent",
"version": "0.4.0",
"version": "0.5.0",
"description": "Scientific figures with upstream PaperVizAgent, separate roles, configurable model providers and Codex subscription fallback. Host-native defaults where tools are available.",
"author": {
"name": "GoatInAHat"
Expand Down Expand Up @@ -57,7 +57,7 @@
"command": "uvx",
"args": [
"--from",
"papervizagent==0.4.0",
"papervizagent==0.5.0",
"papervizagent",
"mcp"
],
Expand Down
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "papervizagent",
"version": "0.4.0",
"version": "0.5.0",
"description": "Scientific figures with upstream PaperVizAgent, separate roles, configurable model providers and Codex subscription fallback. Host-native defaults where tools are available.",
"author": {
"name": "GoatInAHat"
Expand Down
2 changes: 1 addition & 1 deletion .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "papervizagent",
"version": "0.4.0",
"version": "0.5.0",
"description": "Scientific figures with upstream PaperVizAgent, separate roles, configurable model providers and Codex subscription fallback. Host-native defaults where tools are available.",
"author": {
"name": "GoatInAHat"
Expand Down
101 changes: 79 additions & 22 deletions CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,69 @@ skill and managed Codex sign-in in the standalone runtime. No model IDs are
hardcoded into automatic selection.

```yaml
models:
llm: {provider: codex}
vlm: {provider: codex}
image: {provider: codex}
roles:
critic:
options: {effort: high}
model_policy: balanced
pipeline:
task_name: diagram
exp_mode: demo_full
retrieval_setting: none
max_critic_rounds: 3
num_candidates: 1
max_concurrent: 4
codex:
access_token_env: CODEX_OAUTH_TOKEN
account_id_env: CODEX_ACCOUNT_ID
timeout: 600
```

This example explicitly assigns all modalities to Codex. To keep the host's
tools as defaults, omit `models` and configure only the roles you want to
override. `status` accepts the native capabilities the host has verified;
`models` reads the actual subscription catalog, including vision eligibility.
Copy an available model ID into any modality or role's `model` field to select
it. An explicit override that fails is an error; it does not silently switch
providers. A role's fields merge over its modality's fields. Native role options are
limited by the host's own controls; `status` exposes common scalar generation
controls and reports other keys as unavailable, without exposing SDK options
or credentials. Use a configured provider for its full SDK option set.
This example preserves verified host-native tools, with managed Codex sign-in
for missing modalities. `status` accepts the native capabilities the host has
verified. `models` reads the actual subscription catalog and reports automatic
choices and selection reasons without making an inference request.

`model_policy` is `balanced` by default; choose `quality` for highest-quality
work. The `status`, `infer`, and `generate` operations also accept a per-request
`model_policy` override. Native skill roles use a supported current mid-tier
alias or live catalog; Claude Code uses `sonnet`, or `opus` for quality. Hosts
without tier information use their own default and record the fallback.

The Codex runtime discovers models at connection time. Automatic selection
excludes hidden and specialized entries, requires vision support for image
inputs, and prefers entries without retirement/upgrade hints. It uses the
provider's balanced/mid-tier or flagship/most-capable descriptions, then the
provider default, then catalog order. These advisory labels cannot guarantee
lowest cost or benchmark ranking. Model IDs and version numbers are never
hardcoded or guessed. Selection reasons are recorded in traces, so a changed
catalog remains inspectable. Balanced effort is medium for text/vision and low
for the image-tool coordinator where supported; quality prefers high effort.

Copy an available model ID into a modality or role's `model` field to override
automatic selection. Set `provider` to explicitly override native-first routing.
For example, `models.image: {provider: codex, model: YOUR_AVAILABLE_MODEL}` pins
the Codex coordinator while leaving native text and vision available. An
explicit override that fails is an error; it does not silently switch providers
or models. A role's fields merge over its modality's fields. Explicit effort
options also win over the policy defaults.

Native role options are limited by the host's own controls; `status` exposes
common scalar generation controls and reports other keys as unavailable,
without exposing SDK options or credentials. Use a configured provider for its
full SDK option set.

Supported roles: `retriever`, `planner`, `stylist`, `visualizer`, `critic`,
`vanilla`, `polish`. Text-producing roles use `vlm` when their actual inputs
contain images, otherwise `llm`. Render calls use `image`. This includes the two
different modalities used by polish.

## Native Python callbacks in 0.5.0

Version 0.5.0 extends the embedded `Backend(native={...})` callback contract.
Callbacks with an explicit signature must add the keyword arguments `model`
and `model_policy` alongside `role`, `modality`, `system`, `contents`, and
`options`. `model` is `None` when unconfigured; otherwise apply that exact
model. When it is absent, resolve `model_policy` through the host's supported
aliases/catalog. Preserve explicit controls in `options`. Returning a result
without applying an explicit model is not a valid native adapter.

This is a breaking change for callbacks with the old five-argument signature;
update the adapter before upgrading. Skills and generated CLI/MCP/host adapters
already share the updated policy and do not need callback code.

## Providers

Each model/role entry accepts `provider`, `model`, `api_key_env`, `api_key`,
Expand Down Expand Up @@ -86,7 +113,10 @@ same Gemini path and `gpt-image` image path as upstream. Portable `models`,
take precedence. Select Anthropic explicitly to use its text adapter.

Codex image `model` selects the coordinator, not the service-managed image
generator. Image size/aspect/quality/background are requested in the prompt,
generator. The subscription interface does not expose or report its underlying
image-model ID, so it cannot guarantee a `gpt-image-2` pin. Existing Codex login
is reused through the official SDK without copying OAuth credentials.
Image size/aspect/quality/background are requested in the prompt,
not guaranteed API dimensions. Its upstream temperature/token/count defaults
are recorded as unavailable in traces. Explicit unsupported Codex options
fail. Select Gemini or OpenAI image models for their direct API controls.
Expand All @@ -96,6 +126,33 @@ polish selects editing automatically. Ordinary Visualizer calls are fresh
generation from the revised text description. Gemini and Codex can condition
on reference image inputs through their native multimodal interfaces.

## Claude Code with existing Codex sign-in

Install the shared skill and an MCP server. While PyPI publication is pending,
use Git source for the runtime too; the generated marketplace plugin's PyPI
command requires that publication. These commands install the current main
branch; replace `main` with a reviewed commit for a reproducible installation.

```sh
npx skills add GoatInAHat/PaperVizAgent --skill papervizagent --agent claude-code --global --yes
claude mcp add --scope user papervizagent -- uvx --from git+https://github.com/GoatInAHat/PaperVizAgent@main papervizagent mcp
claude --model sonnet
```

Claude and Codex each use their own existing login (`claude auth login` and
`codex login` if needed). Do not move Codex OAuth tokens into Claude. Ask Claude
to use the PaperVizAgent skill: fresh Claude roles plan and inspect images;
`infer` invokes the Codex image bridge only when that modality is absent.
The Codex image bridge necessarily includes a small coordinating LLM request,
with low effort under the balanced policy; it is not a direct image-only API.

For an unattended demonstration, constrain built-in tools with `--tools` and
use `--strict-mcp-config` with an explicit server file. Allow Read, Write, Agent
and the needed MCP operations; omit scheduler/polling tools. Resume on Claude's
automatic role-completion notifications. Record the resolved model metadata,
actual artifact inspection and any failed stages rather than assuming a host
integration implies success.

## External Codex tokens

Supply `CODEX_OAUTH_TOKEN` through the host's secret field or environment. An
Expand Down
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ Scientific figures using [Google Research’s official PaperVizAgent](https://gi

The Python processor, seven agent implementations and complete style guides are reused from pinned upstream source. [ToolFactory](https://github.com/GoatInAHat/toolfactory) generates the integrations and release packages from that one runtime.

**Release status:** GitHub/source installation is available; the PyPI, npm, ClawHub and browser-store commands below require the publisher setup described in [RELEASING.md](RELEASING.md). Until PyPI is published, run the runtime from the release source:
**Release status:** GitHub/source installation is available; the PyPI, npm, ClawHub and browser-store commands below require the publisher setup described in [RELEASING.md](RELEASING.md). Until PyPI is published, run the runtime from source:

```sh
uvx --from git+https://github.com/GoatInAHat/PaperVizAgent@v0.4.0 papervizagent mcp
uvx --from git+https://github.com/GoatInAHat/PaperVizAgent@main papervizagent mcp
```

<!-- tf:install -->
Expand All @@ -23,18 +23,18 @@ uvx --from git+https://github.com/GoatInAHat/PaperVizAgent@v0.4.0 papervizagent
- **Gemini CLI extension** — `gemini extensions install https://github.com/GoatInAHat/PaperVizAgent`
- **OpenClaw plugin** — `openclaw plugins install --link hosts/openclaw` from a checkout; published: `openclaw plugins install clawhub:openclaw-plugin-papervizagent`
- **Hermes plugin** — `hermes plugins install https://github.com/GoatInAHat/PaperVizAgent#hosts/hermes/papervizagent_hermes`
- **DSH plugin** (experimental) — `dsh plugin --profile <profile> add ./hosts/dsh` from a checkout, or the release tarball `papervizagent-dsh-0.4.0.tgz`
- **DSH plugin** (experimental) — `dsh plugin --profile <profile> add ./hosts/dsh` from a checkout, or the release tarball `papervizagent-dsh-0.5.0.tgz`
- **Browser extension** — from a checkout: `npm --prefix hosts/browser install && npm --prefix hosts/browser exec --no -- wxt build`,
then `chrome://extensions` → developer mode → Load unpacked → `hosts/browser/.output/chrome-mv3`
(Firefox: `npm --prefix hosts/browser exec --no -- web-ext run`). Each GitHub Release attaches the
store uploads `papervizagent-0.4.0-chrome.zip`, `papervizagent-0.4.0-firefox.zip`, `papervizagent-0.4.0-edge.zip`. When Firefox signing credentials are configured, it also attaches a
store uploads `papervizagent-0.5.0-chrome.zip`, `papervizagent-0.5.0-firefox.zip`, `papervizagent-0.5.0-edge.zip`. When Firefox signing credentials are configured, it also attaches a
Mozilla-signed `.xpi`; the Chrome Web Store, Firefox Add-ons and Edge Add-ons listings appear once the release's
submit step has each store's credentials. Then pair it: `uvx papervizagent mcp --http --pair`
prints the `<url>#<token>` the extension's options page accepts.
- **Web app** — `uvx papervizagent mcp --http --open` serves the operations page beside the
MCP endpoint on one port and opens it; over MCP or a skill, the `web` operation does the same and
returns the URL.
- **npm package** — `npm install papervizagent`; requires `uv`, and `papervizagent` delegates to `uvx --from papervizagent==0.4.0 papervizagent`
- **npm package** — `npm install papervizagent`; requires `uv`, and `papervizagent` delegates to `uvx --from papervizagent==0.5.0 papervizagent`
- **PyPI package** — `uv add papervizagent`

<!-- /tf:install -->
Expand All @@ -45,11 +45,19 @@ The npm package is a small launcher for the same version on PyPI and requires [u

The skill resolves each role independently: **explicit role setting → modality setting → available host tool → Codex fallback**. It checks actual tools; a host name does not guarantee vision or image generation.

The shared `model_policy` defaults to `balanced`: native roles use a current
mid-tier alias or live catalog, and Codex selects from its current account
catalog with a recorded reason. Claude Code uses `sonnet` for planning and
image inspection, keeping Codex fallback confined to missing image generation.
Choose `quality` for a highest-quality request (`opus` in Claude); explicit
model and effort choices still win. Catalog tier labels are advisory, with
transparent provider-default fallbacks. See [configuration](CONFIGURATION.md).

On Codex, the skill uses native subagents, vision and image generation without API keys or a Python server. The Codex plugin does not eagerly start MCP. Custom overrides use the optional runtime through the CLI or an explicitly connected MCP server.

On other hosts, use available native capabilities and supply `CODEX_OAUTH_TOKEN` for missing capabilities, or use an existing Codex sign-in. `CODEX_ACCOUNT_ID` is needed only if the supplied token does not contain its account identifier. Tokens stay in environment/host secret settings or an explicitly selected token file; never paste them into prompts or tool arguments. Static access tokens expire: their owner must refresh them. The SDK manages refresh for its own sign-in.

A standalone CLI/MCP/web server cannot directly invoke another app’s private tools. Its `generate` operation uses configured SDK providers or Codex. The portable skill is the bridge to host-native tools; embedded Python integrations can also supply native callbacks to `Backend(native={...})`. An unavailable capability produces an error.
A standalone CLI/MCP/web server cannot directly invoke another app’s private tools. Its `generate` operation uses configured SDK providers or Codex. The portable skill is the bridge to host-native tools; embedded Python integrations can also supply native callbacks to `Backend(native={...})`. A callback is awaited with keyword arguments `role`, `modality`, `system`, `contents`, `options`, `model`, and `model_policy`; it must apply a configured `model` when present and return the role output. An unavailable capability produces an error.

The official [Codex SDK](https://github.com/openai/codex/tree/main/sdk/python) discovers subscription models and starts a fresh, ephemeral thread for every role call. `models.image.model` selects the Codex **coordinating model**; Codex manages the built-in image generator. Arbitrary image-model selection uses an image API provider. Codex does not expose API controls such as temperature or maximum output tokens; explicit unsupported overrides fail, and unavailable upstream defaults are listed in the trace. Aspect/size requests are prompt guidance on Codex. See [configuration](CONFIGURATION.md).

Expand Down
2 changes: 1 addition & 1 deletion RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ and MCPB do not require an existing PyPI package.

## Current publication status

The v0.4.0 GitHub release provides downloadable integrations independently of
GitHub release bundles provide downloadable integrations independently of
registry accounts. PyPI and npm publication, ClawHub listings and browser-store
submission remain pending their publisher setup. The GitHub `pypi` environment
and Pages source are configured; the PyPI trusted-publisher record must still be
Expand Down
2 changes: 1 addition & 1 deletion bin/papervizagent.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env node
import { spawnSync } from "node:child_process";

const child = spawnSync("uvx", ["--from", "papervizagent==0.4.0", "papervizagent", ...process.argv.slice(2)], {
const child = spawnSync("uvx", ["--from", "papervizagent==0.5.0", "papervizagent", ...process.argv.slice(2)], {
stdio: "inherit",
});
if (child.error) throw child.error;
Expand Down
Loading
Loading