hal 0.1.4
Plot vision: the model can now see your plots. When
eval_rcode draws a plot – base graphics or a returned ggplot/lattice object – hal captures it as PNG and attaches it to the tool result as an image, so the model can describe, critique, and iterate on actual visual output (“make this plot publication-ready” now works on what the plot looks like). Supported on the vscode backend (requires the bundled hal-bridge 0.1.4) and the claude backend (MCP image content blocks). The copilot backend stays text-only until its CLI’s image forwarding is verified. Disable withhal_configure(plot_vision = FALSE). Notes: returned ggplot objects are also printed to your device (they now appear in the Positron plots pane); render errors surface to the model as a## Plot render errorsection; plots written to file devices the code opens itself are not echoed; one image per eval (the final page); images larger than 5 MB are skipped.hal-bridge 0.1.4 (bundled): tool results can carry an image part (
LanguageModelDataPart.image); if the selected model rejects image input at runtime, the bridge strips images and retries once text-only; request bodies are capped at 20 MB (413 beyond); minimum Positron/VS Code engine raised to 1.103 (first stable release with the image API). The vscode client also prunes all but the newest 2 images from the resent history so long sessions don’t re-bill every old plot.hal_do()now verifies its transforms. After a successful pipe-mode transform, hal compares input and output and prints a one-line structural report – row deltas, columns added/removed, class changes, introduced NAs (hal_do: 32 -> 14 rows | +1 col (kpl)). The full report is attached asattr(result, "hal_verify")(print it for details). Suspicious patterns – output identical to input, or 0-row output – raise a classedhal_do_warning. Report-only by design: deltas are often intentional (“filter mpg > 20” should shrink the data), so verification never triggers retries or changes values. Disable with.verify = FALSEorhal_configure(verify = FALSE).Fixed: the default model on the copilot and vscode backends no longer exists. Both defaulted to
"claude-sonnet-4.6", which GitHub Copilot andvscode.lmhave since dropped from their catalogs — neither backend serves that id any more. Both now default to"claude-sonnet-5", verified present in both live catalogs. The claude backend was unaffected: it passes the"sonnet"alias, which the CLI resolves server-side and which cannot go stale this way.Fixed: stale model metadata. The Claude backend’s alias descriptions still named Sonnet 4.6 and Opus 4.8 as the current tiers (now Sonnet 5 and Opus 5), and reported a 200K context window for all three aliases — Sonnet and Opus are 1M natively, and only Haiku is 200K. Context windows for the newer Copilot/
vscode.lmids (claude-opus-4.8,claude-opus-5,claude-sonnet-5) were missing and reported asNA. Documentation examples naming retired ids were updated.Missing Copilot? hal now points you at Claude if you have it. When hal falls back to the copilot backend and can’t find the Copilot CLI, but Claude Code is installed, the error,
hal_status(), andhal_setup()now say so and give the one command that gets you working:hal_configure(backend = "claude"). The install instructions are still shown. Default backends are unchanged — this only changes the message in a case that already failed. Detection checks thePATHandCLAUDE_CLI_PATHonly; it never runs a subprocess.Fixed: slow
eval_rcalls could abort a healthy Claude turn. Tool calls execute synchronously inside the Claude client’s response loop, but the prompt deadline only reset when the CLI produced output – so time spent running your R code counted as the model stalling. A single slow eval (eval_timeoutdefaults to 30s, roughly double that when plot vision re-renders) could exhaust the 60sprompt_timeoutand abort a turn that was progressing normally. Time spent servicing tool calls is now credited back to the deadline.Fixed: a failed Claude turn wedged the session. The client marked a session as created only after a successful turn. If a turn timed out or the CLI died mid-stream, the session already existed in Claude Code’s store but hal did not know it – so every subsequent prompt re-sent
--session-idwith a live uuid and was rejected, untilhal_reset(). The session is now latched as soon as the CLI announces it, so a failed turn is simply retried with--resume. Timeout messages say so.Fixed:
hal_setup(backend = "claude")installed the Copilot CLI. The documented"claude"value had no branch inhal_setup(), so it fell through to the Copilot path and either mislabelled Claude as Copilot or rannpm install -g @github/copilot. There is now a real Claude branch that verifies theclaudebinary, reports its version, and points at the download plus one-time OAuth step. It deliberately does not auto-install: Claude Code’s sign-in is interactive, and an npm install produces exactly the.cmdshim whose stdio processx drops on Windows.Fixed: MCP subprocess crash on R 4.1–4.3. The generated MCP server script used
%||%without defining it; base R only gained%||%in 4.4.0. The script now defines it, matching the package’s declared R >= 4.1 support.Fixed: blank destination in the first-run data notice on the vscode backend. The one-time “hal sends prompts and tool results to the …” notice had no vscode branch and rendered an empty slot; it now names the model behind your Positron Copilot sign-in.
-
CRAN preparation.
-
hal()now asks before creatinghal.md. Previously it wrote the project memory file into your working directory on first use and told you afterwards. It now offers — “Create hal.md?”, default no — and writes only on an explicit yes. It never asks in a non-interactive session, asks at most once per folder per R session, and a decline is not undone byhal_reset(). Turn the offer off withoptions(hal.memory_prompt = FALSE). An existinghal.mdis still read in any context, whatever you answered. - Removed the never-shipped
hal_query_mapsurface: thehal_configure(max_spawn =)parameter andhal.max_spawnoption documented a function that does not exist. - Mock-CLI tests (which spawn local
Rscriptsubprocesses) are skipped on CRAN; the rest of the suite runs there. -
DESCRIPTIONrewritten per CRAN conventions; staleLICENSEcopyright holder fixed;.vscode/excluded from the build.
-
hal 0.1.3
excelR()is nowhal_excel(). Clean rename (no alias) to match thehal_prefix convention before anyone depends on it. The result class ishal_excel_codeand the verification report attribute isattr(x, "hal_excel"). Functionality is unchanged.New
hal_status(): one traffic-light diagnostic for the whole stack. Reports the resolved backend (and why), whether its transport is reachable, session state, and — when something is wrong — the single next step to fix it. Returns a structured list invisibly for programmatic use. This is the first thing to run when hal misbehaves, and the thing to paste into a bug report.Positron setup no longer requires the GitHub CLI.
hal_setup()was still gating the vscode path onghbeing installed andgh auth statuspassing — a leftover from before the bridge VSIX was bundled (0.1.1). The gate is gone; the only external requirement (a Copilot sign-in inside Positron itself) is now surfaced as a reminder in the next-step bullets, since hal cannot verify it from R.hal_do()now aborts on failure in non-interactive contexts. Previously a failed generation warned and passed.datathrough unchanged everywhere — in a script or R Markdown pipeline that means silently continuing with untransformed data. Interactive sessions keep the forgiving warn-and-passthrough; scripts get an error. Override either way withhal_configure(do_on_fail = "warn"|"abort").Default
hal_do()retries raised from 1 to 2 (hal.do_retries), matching the default-on edit-in-place behavior: more self-correction before giving up.hal_excel()inherits the same default.hal failures now signal classed conditions.
hal()transport failures abort withhal_transport_errorin non-interactive contexts;hal_do()signalshal_do_error/hal_do_warning;hal_ask()signalshal_ask_warning. All inherit fromhal_error/hal_warning, so programmatic callers cantryCatch(..., hal_error = ...)instead of string-matching messages.Environment auto-detect is harder to false-positive.
hal()’suse_env = NULLauto-detection no longer injects your environment when a prompt merely contains English function words that collide with object names (“show me all the columns on that table” with objectsall/on). Backtick-quoting,$/[subsetting, or calling the object still triggers injection deliberately. Data-science nouns (data,model,fit, …) still match by name — missing real context costs more than a small extra snapshot.Website URL fixed.
DESCRIPTION,_pkgdown.yml, and the README pointed atd-m4rk.github.io/hal(404); the site deploys atarclite-red.github.io/hal.
hal 0.1.2
hal-bridge discovery file moved out of the system temp dir (bridge 0.1.2). The bridge previously wrote its port + token to
%TEMP%\hal-bridge.port, which the OS garbage-collects (e.g. Windows Storage Sense). After a day or two the file was swept while the bridge was still listening, sohal_bridge_status()reported the bridge as gone and users reinstalled needlessly. The discovery file now lives in a durable per-user app-data dir —%LOCALAPPDATA%\hal-bridge\port.jsonon Windows,$XDG_RUNTIME_DIR/hal-bridge/port.json(else~/.cache/hal-bridge/port.json) on POSIX. Requires the bundled bridge 0.1.2; older bridges write the old location and won’t be found — reinstall withhal_install_bridge(force = TRUE)and cold-restart Positron.hal_config()$backendnow reports the resolved backend, not the raw option. Previously it readgetOption("hal.backend", "copilot")with a hardcoded literal fallback, so in Positron it lied and said"copilot"even thoughhal()would actually route to"vscode". Now uses.hal_backend()— the same resolverhal()uses — so the reporter and the router agree.Bridge install messaging now tells users to fully quit Positron, not just “Reload Window”. On a fresh extension install the extension host only loads new extensions on a cold start; “Reload Window” is insufficient and leaves users stuck at
hal_bridge_status()reporting the bridge as not installed. Updated in:hal_install_bridge()success message,.hal_bridge_discover()not-found error,hal_setup()next- step bullets, and thebackendsvignette install snippet. Runtime reload prompts (crashed bridge, 401 token rotation) still say “reload Positron” since Reload Window is sufficient there.
hal 0.1.1
hal_install_bridge()now installs from a bundled VSIX. The hal-bridge extension (7 KB) ships ininst/extdata/and is installed directly into Positron — no GitHub download, no auth token, no SHA pin. Removes the install-timegh auth login/GITHUB_PATrequirement that broke fresh installs on machines without a token.local_path = "..."still works for testing dev builds;versionandverifyarguments are gone (no longer meaningful). To bump the bridge, ship a new hal release with the updated VSIX ininst/extdata/.Internal: deleted
.hal_download_bridge_vsix,.hal_github_token,.hal_github_api_get,.hal_github_download_asset,.hal_sha256_file, and theBRIDGE_SHA256/BRIDGE_REPOconstants. DroppeddigestandopensslfromSuggests.
hal 0.1.0
Initial public release.
-
New
vscodebackend – talks to Positron’s built-invscode.lmAPI via a small localhost HTTP bridge (thehal-bridgePositron extension). Skips the Copilot CLI entirely: no Node.js, no@github/copilotpackage, no--additional-mcp-configplumbing. Tool calls round-trip directly through R, soeval_rruns without an MCP subprocess.-
hal_install_bridge()– downloads the pinned VSIX from thehal-bridgeprivate GitHub release and installs it into Positron. GitHub auth comes fromgh auth token, git credential helper, orGITHUB_PAT(in that order); no separate token setup needed for most users. -
hal_bridge_status()– ping/version/port diagnostics. -
hal_setup()now detects Positron and walks through the bridge install path automatically; passbackend = "copilot"to force the legacy CLI flow. -
hal_models()queries the bridge’s/modelsendpoint and returns whatevervscode.lmexposes to your Copilot session. -
hal_available()is backend-aware: takesbackend = "..."to probe a specific transport without changing the session default. -
permission_policyis now honored on the vscode backend (previously accepted for API parity but silently always auto-allowed). Supports"auto-allow"(default),"auto-deny","ask"(interactive prompt; denies in non-interactive sessions), or a function receivinglist(backend = "vscode", tool_name, input)and returning a string containing"allow"or"deny". Denied calls are surfaced to the model as a tool error and recorded withstatus = "denied".
-
Smart-default backend – when
hal.backendis unset, hal now resolves to"vscode"inside Positron (POSITRON_VERSIONset) and"copilot"everywhere else. Existing users withoptions(hal.backend = "...")are unaffected.BREAKING: Removed the blackboard API (
hal_bb_put(),hal_bb_get(),hal_bb_list(),hal_bb_rm(),hal_bb_clear(),hal_bb()). Replaced withuse_envparameter onhal()that auto-injects the caller’s environment snapshot so the model useseval_rdirectly on your objects. No manual staging needed —hal("analyze df", use_env = TRUE)just works.BREAKING: Removed
allow_evalparameter fromhal()andhal_ask().eval_rtool is now always registered at session init. It is inert without theuse_envsystem prompt nudge.write_r_scriptremoved (redundant with the SDK’s built-increatetool).Bidirectional IPC:
eval_rtool calls execute in the user’s live R session via file-based message passing between the MCP subprocess and parent R session. Model can inspect and modify caller environment objects.hal_do()retry mechanism: automatic retry on code parse/execution failure, model self-corrects within the same disposable session. Configurable viahal_configure(do_retries = N).Enhanced environment descriptions in
hal_do()standalone mode: data frame column names/types, function bodies for small functions.hal_configure()now acceptspermission_policyandsession_quietfor controlling the global session without using the R6 API.hal_chat()andhal_client()wrappers now acceptpermission_policyandquietdirectly.hal_setup()– guided CLI installation and authentication helper. Checks for Node.js, installs the Copilot CLI via npm, and walks throughcopilot login.Full functional API:
hal(),hal_ask(),hal_do(),hal_history(),hal_reset().Pipe-friendly verbs:
hal_ask()for data-aware analysis,hal_do()for code generation (pipe and standalone modes).Edit-in-place:
hal_do()replaces itself in the editor with generated code when running from an IDE script.Configuration via
hal_configure()/hal_config()withhal.*options.Custom tool calling via MCP:
hal_tool(),hal_register_tool(),hal_register_package_tools(),hal_register_tool_specs().Governance layer: eval_r denylist (AST walker), credential scanner, eval timeout, spawn cap.
ANSI-colored output formatting with optional typewriter streaming.
High-level chat API via
HalChatR6 class, mirroring theellmer::Chatinterface.Low-level ACP transport via
HalClientR6 class (NDJSON over stdio).S3 data objects:
hal_response,hal_turn,hal_tool_callwith print/format methods.Mid-session model switching via
$switch_model().Session modes:
$set_mode("agent")or$set_mode("plan").Cancel support: Ctrl+C interrupt +
$cancel()method.Streaming callbacks:
on_text,on_tool_call,on_thought.Permission handling for built-in tool calls (
"auto-allow","auto-deny", or custom function).hal_available()checks for a working Copilot CLI installation.hal_models()lists available models and usage multipliers.CLI discovery via standalone
copilotbinary,gh copilot --, orCOPILOT_CLI_PATHenv var.Tool registration compatible with
ellmer::ToolDef.
