nc://apple

v0.1.0Pinned
Backnodecode-ai
pomterrecells: thirty-three cells, ported from oh-my-pi -- providers oh-my-pi carries (can1357/oh-my-pi at c9383c1, MIT, credited in each folder's NOTICE), each as a cell of its own: Alibaba's Coding and Token Plans, Amazon Bedrock, Anthropic's Pro/Max sign-in, Apple's on-device Foundation Models (macOS), Azure OpenAI, ClinePass, Cloudflare AI Gateway, Cursor, Devin, Factory Droid, GitHub Copilot, GitLab Duo and its agent, Antigravity, the Gemini CLI's Cloud Code Assist, Vertex AI, Kilo, Kimi Code, local ONNX and MLX workers, Muse Code, Ollama Cloud, ChatGPT's Codex sign-in and its device-code variant, OpenRouter, Snowflake Cortex, xAI's SuperGrok sign-in, Xiaomi MiMo and Z.AI's Coding Plan; and four that are not chat providers: language servers (nodecode-lsp), Perplexity search, keyless web search engines (nodecode-web-provider) and TypeSafe judgments. Each stands alone: it loads, starts, stops and tests by itself, depends only on nodecode, and shares no code with another; one whose wire none of the four lanes speaks registers a lane of its own. Written against the cell contract (src/CELLS.md) at nodecode fb4bdabc1. Their tests ran green against that tree with no network (~/nodecode-cells/tools/test-cell.sh, 663 tests over the 33, 0 failed).914a3fe· 8 Oct1 commit
bridge3 filestest1 filecell.lisp5.7 KBprovider.lisp7.0 KBschema.lisp12.3 KBwire.lisp16.9 KB

nodecode-apple

A Nodecode cell for Apple Foundation Models, the language model macOS 27 runs on the machine (Apple silicon, Apple Intelligence on). On such a Mac, /models lists apple/on-device once the model says it is available, and a turn on it runs on the machine, tool calls included. On any other machine the cell says once that it does nothing there, and registers nothing.

Ported from oh-my-pi's apple provider (api apple-foundation-models). See NOTICE.

The bridge

omp reaches the model through a Swift bridge, crates/pi-natives/src/applefm/bridge.swift: built into a dylib with build-bridge.sh, embedded in omp's native addon, and dlopened on macOS 27 behind a four-function C ABI (omp_applefm_availability, omp_applefm_generate, omp_applefm_cancel, omp_applefm_free). Every request lowers the whole conversation into a Foundation Models transcript, and the bridge streams exactly one model turn back as JSON events on Swift's own threads.

The cell drives the same bridge. It carries bridge.swift verbatim and a main.swift of its own that wraps the C ABI in a small executable, and builds the two into one helper with bridge/build.sh (omp's toolchain detection: Swift 6.4+ with the macOS 27 SDK, from $OMP_APPLEFM_SWIFTC, the selected Xcode, or the Command Line Tools). A Lisp image cannot take the bridge's callbacks on Swift's threads, so the helper runs as a child, one request per process:

  • helper availability prints the availability event
  • helper generate reads the request on stdin and prints each event as a line; ending the process cancels the generation

The helper is built on first use into the user cache (~/.cache/nodecode-apple/nodecode-apple-bridge-<hash of the sources>), or named with helper. The lane (wire.lisp) ports omp's transport:

  • the request: the system prompt as instructions; user and history system messages as prompt entries, an assistant turn as a response (its text) and a toolCalls entry (each call's id, name and arguments as a JSON text), a tool result as a toolOutput naming its call and tool; images as base64 parts labelled image-1, image-2, ... across the conversation (a placeholder for a model without vision); temperature, topP, maxTokens; greedy for temperature 0 with no bounds; toolChoice none or required when there are tools; reasoningLevel (minimal and low light, medium moderate, high and above deep) for a model that reasons
  • tool parameters lowered into the dialect GenerationSchema decodes (omp's foundation-models.ts): every object titled, ordered (x-order), closed and listing what it requires; string literals as an enum, a nullable type as its one type, local $refs inlined; what the decoder cannot express (a free-form map, an open schema, a tuple, a mixed enum) asked for as a JSON-encoded string and parsed back out of the call's arguments
  • the events: text and reasoning stream, toolCall fragments gather per call id, usage splits the cached part of the prompt, done ends the turn; a turn with calls is a tool round, one whose output reached maxTokens is a length finish
  • a bridge error is said with its code: a guardrail or a refusal is final, a context overflow is the one the core evicts on, rate_limited waits, an unavailable model says why

The model is offered as omp offers it: on-device, named Apple <variant>, its window the bridge's contextSize (else 128,000), its output ceiling the smaller of that and 32,768, images and reasoning as the bridge reports them. While the bridge says the model is unavailable (not eligible, Apple Intelligence off, assets not ready, macOS older than 27), the row lists no model and a notice names the reason.

Install

On a Mac with Apple silicon and macOS 27, with Xcode 27 or its Command Line Tools: copy this folder into ~/.nodecode/cells/nodecode-apple/ and restart Nodecode, or run (restart-cells). The first start builds the helper (a minute or so) and asks the model whether it is available.

Configure

Optional. The section is on unless it says "enabled": false:

{
  "apple": {
    // a helper already built (sh bridge/build.sh OUT); empty builds one
    "helper": ""
  }
}

Test

From this repository's root:

tools/test-cell.sh nodecode-apple

The tests run on Linux: the Mac is a stubbed mac-p, and the helper a /bin/sh script that keeps the request it was sent and prints canned bridge events, so the request bytes, the fold and the process plumbing are the real ones. The Swift (bridge.swift, main.swift) is not compiled here; it is compiled on the Mac at first use.

Gaps

  • main.swift is untested. Nothing in this repository can compile against the macOS 27 SDK; the shim is small (it calls the bridge's own C functions and prints what they emit), but its first compile is on the operator's Mac.

Not ported

  • omp's in-process load (the dylib behind the addon) and its handle-based cancel: here a generation is one helper process, cancelled by ending it.
  • topK (the core's config carries no top-k), and a named tool choice (the core's tool choice is a mode, not a tool).
  • the tool-result error flag omp prefixes with Tool call failed: (a Nodecode tool result carries no such flag).
  • omp's message normalization (transform-messages.ts).

MIT licensed.

Add nc://apple

  1. 1

    Install Nodecode

    Once per machine.

    $ curl -fsSL https://nodecode.ai/install.sh | sh
  2. 2

    Add the cell

    Pinned at 914a3fe.

    $ nodecode add nc://apple

    Or tell the agent add the apple cell.

  3. 3

    Pick its model

    On a Mac with Apple silicon and macOS 27, pick the on-device model in /models.