Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
3c7e244
feat(ai): extend model provider contract
Kaushik-Kumar-CEG Sep 5, 2026
c8f27b1
feat(ai): coordinate providers and models
Kaushik-Kumar-CEG Sep 5, 2026
f4df278
feat(ai): generate static model catalog
Kaushik-Kumar-CEG Sep 5, 2026
e327c5a
feat(ai): prepare provider requests
Kaushik-Kumar-CEG Sep 5, 2026
61e3477
feat(ai): add OpenAI Chat codec
Kaushik-Kumar-CEG Sep 5, 2026
1c938a8
feat(ai): add Anthropic Messages codec
Kaushik-Kumar-CEG Sep 5, 2026
a5bfcaa
feat(ai): add Bedrock Converse Stream codec
Kaushik-Kumar-CEG Sep 5, 2026
4345001
feat(ai): register DeepSeek provider
Kaushik-Kumar-CEG Sep 6, 2026
8b9e891
feat(ai): register all built in providers
Kaushik-Kumar-CEG Sep 6, 2026
05604b7
feat(ai): add subscription oauth providers
Kaushik-Kumar-CEG Sep 6, 2026
eec142c
feat(runtime): select canonical model providers
Kaushik-Kumar-CEG Sep 6, 2026
036b75a
feat(cli): integrate provider management surfaces
Kaushik-Kumar-CEG Sep 6, 2026
7531f53
test(ai): complete native dialect fixtures
Kaushik-Kumar-CEG Sep 6, 2026
8faf8f7
docs(ai): complete provider setup reference
Kaushik-Kumar-CEG Sep 6, 2026
2355558
refactor(ai): compact static model catalog
Kaushik-Kumar-CEG Sep 6, 2026
d55d69b
fix(ai): bound provider URL normalization
Kaushik-Kumar-CEG Sep 6, 2026
1eb5a22
fix: resolve provider support merge readiness
Kaushik-Kumar-CEG Sep 6, 2026
0199311
fix: address provider support audit findings
Kaushik-Kumar-CEG Sep 6, 2026
22f65de
feat(ai): add native model config, catalog refresh, and inline login
Haz3-jolt Sep 7, 2026
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
11 changes: 11 additions & 0 deletions LICENSES/MIT.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
SPDX-License-Identifier: MIT

MIT License

Copyright (c) <year> <copyright holders>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2 changes: 2 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Axl uses highlight.js 11.12.0 as an external dependency for syntax highlighting.

Axl uses grok-mermaid 0.2.2 as an external dependency for Unicode Mermaid rendering. It is distributed under its own Apache-2.0 license.

Axl's generated model catalog includes factual metadata derived from models.dev, retrieved from https://models.dev/api.json. Models.dev is Copyright 2025 models.dev contributors and is distributed under the MIT license.

Axl uses `@deepseek-ai/node-addon-landlock-run` 0.1.1 from DeepSeek Harness.
Its JavaScript package includes an MIT notice, and its platform launcher packages
are distributed under BSD-3-Clause. Those notices remain in the installed dependency
Expand Down
31 changes: 20 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Axl is not yet a hosted service, remote collaboration product, browser applicati
| Durability | Append-only canonical JSONL, operation IDs, crash-safe mutation journal, restart reconciliation, and deterministic replay |
| Multi-client behavior | Independent attachments, paged snapshots, acknowledged cursors, presence, reconnect recovery, and shared deterministic projection |
| Automation | One-shot text and canonical JSONL output with `axl print` and `axl json`, plus native daemon RPC with `axl rpc` |
| Model interaction | Azure OpenAI model catalog, model selection, thinking levels, streaming text and reasoning, tool calls, steering, and follow-ups |
| Model interaction | Provider-grouped text-model catalog, provider-qualified model selection, authentication management, usage and costs, streaming text and reasoning, tool calls, steering, and follow-ups |
| Built-in tools | `read`, `write`, `edit`, `bash`, `web_fetch`, and `web_search` |
| Extensions | Public extension API, prompt templates, Agent Skills, and MCP 2025-11-25 over stdio and Streamable HTTP |
| Workspace review | Bounded file listing and reads, Git status, structured diffs, and daemon-owned last-turn checkpoints |
Expand Down Expand Up @@ -180,13 +180,17 @@ pnpm run install:cli

## Quick start

Configure Azure OpenAI and start a session:
Inspect providers, authenticate one, choose its model, and start a session:

```bash
axl login
axl providers
axl models openai
axl login openai api_key
axl
```

The `provider` and `model` startup options select a canonical pair for a new session. In the TUI, use `/model` to choose a grouped provider and model pair.

Common entry points:

```bash
Expand All @@ -206,17 +210,22 @@ axl rpc # bridge JSONL RPC over stdin and stdout

The CLI connects to the matching local daemon and starts one in the background when necessary. Native, OCI, and unsafe placements use separate state and are labeled in the resume picker.

## Provider authentication
## Model providers

Use `axl providers` for explicit authentication and catalog status, `axl models` for grouped text models, `axl login` and `axl logout` for stored authentication, and `axl refresh` for explicit catalog refresh. These commands report actionable authentication, entitlement, region, catalog, model, and configuration failures. Add named local or hosted endpoints in `~/.axl/models.json`; see the [native configuration example](docs/provider-support/provider-reference.md#user-configured-endpoints).

Inside the TUI, `/model` selects a provider-qualified model. `/providers`, `/login`, `/logout`, and `/refresh` expose the same daemon-owned operations. Escape cancels an active provider operation. The editor reports last-turn and cumulative token usage and USD cost when available.

Provider secrets never pass through the TUI or SDK projection.
Provider secrets never pass through daemon RPC or SDK projection.

1. The CLI collects login input and writes the credential store with restrictive permissions.
2. `packages/ai` implements provider-specific credential parsing, verification, model metadata, and request behavior.
3. `packages/runtime` resolves the selected provider inside the daemon process.
4. The TUI receives only a provider-neutral login dialog definition from the CLI process host.
5. Canonical events, SDK cursors, and client projections never contain live credentials.
1. The daemon owns provider and session operations.
2. `packages/ai` owns provider-specific credentials, authentication, model metadata, API dialects, and request behavior.
3. The trusted CLI process-host adapter renders provider prompts and collects answers inside the daemon process.
4. Login RPC carries only the provider ID and login method.
5. Authorization launch is restricted to HTTPS URLs without embedded credentials.
6. Canonical events, SDK cursors, catalogs, and client projections never contain credential values, OAuth codes, or prompt answers.

Azure OpenAI is the built-in provider today. Provider-specific behavior does not belong in the kernel, protocol, SDK, or presentation clients.
Provider listing is offline and side-effect free. Authentication status and catalog refresh are separate explicit operations. API dialect is model metadata, not user-selectable configuration. See the [provider setup and compatibility reference](docs/provider-support/provider-reference.md) for every provider, environment variable, endpoint, region, authentication method, catalog type, custom-endpoint boundary, limitation, and opt-in smoke procedure. Provider authority and client responsibilities follow [`docs/architecture/client-boundaries.md`](docs/architecture/client-boundaries.md).

## Session profiles

Expand Down
13 changes: 13 additions & 0 deletions REUSE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,19 @@ SPDX-FileCopyrightText = [
]
SPDX-License-Identifier = "Apache-2.0"

[[annotations]]
path = ["packages/ai/catalog/sources/models-dev/**"]
SPDX-FileCopyrightText = "2025 models.dev contributors"
SPDX-License-Identifier = "MIT"

[[annotations]]
path = [
"packages/ai/catalog/semantic-baseline.json",
"packages/ai/catalog/sources/ant-ling/**",
]
SPDX-FileCopyrightText = "2026 Kaushik Kumar"
SPDX-License-Identifier = "Apache-2.0"

# Build output is disposable and inherits its source license.
[[annotations]]
path = ["packages/*/dist/**", "packages/extensions/*/dist/**"]
Expand Down
8 changes: 7 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.5/schema.json",
"files": {
"includes": ["**/*.{ts,json}", "!**/{dist,node_modules}", "!.release"]
"includes": [
"**/*.{ts,json}",
"!**/{dist,node_modules}",
"!.release",
"!packages/ai/src/catalog.generated.ts",
"!packages/ai/src/catalog.generated"
]
},
"formatter": {
"enabled": true,
Expand Down
6 changes: 3 additions & 3 deletions docs/architecture/web-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ This document specifies typed RPC, negotiation, errors, package ownership, and t

## Current baseline

Wire version 11 uses newline-delimited JSON over a Unix socket. It includes typed request and result envelopes, initialization, capability negotiation, structured errors, idempotency keys, subscription identities, paged snapshots, acknowledged opaque cursors, presence, daemon security reporting, direct shell events, transient activity, session-bound blobs, workspace review, session profiles, web-tool selection, manual compaction, steering, follow-ups, and canonical model-retry attempts.
Wire version 12 uses newline-delimited JSON over a Unix socket. It includes typed request and result envelopes, initialization, capability negotiation, structured errors, idempotency keys, subscription identities, paged snapshots, acknowledged opaque cursors, presence, daemon security reporting, direct shell events, transient activity, session-bound blobs, workspace review, session profiles, web-tool selection, manual compaction, steering, follow-ups, canonical model-retry attempts, provider management, and model-request configuration.

The TUI consumes these contracts through `packages/sdk`. Version 11 adds daemon-owned model request settings plus canonical effective-request events. Host-control version 1 remains separate from session wire negotiation and is available only to trusted process hosts.
The TUI consumes these contracts through `packages/sdk`. The two former branch tips both used version 11 for incompatible additions: provider management on the feature branch and daemon-owned request settings on `main`. Version 12 combines both surfaces. Host-control version 1 remains separate from session wire negotiation and is available only to trusted process hosts.

## Versioning

The current wire version is 11. Version 8 introduced typed envelopes, initialization, errors, retry metadata, subscriptions, cursors, acknowledgements, and presence. Version 9 adds the canonical `model.retry_scheduled` event. Version 10 adds `daemon_stopping` as a pre-RPC and universal RPC error. Version 11 adds `config.request` and `model.request_configured` events and request settings in session create and configure RPCs. Compatible capability additions that do not alter accepted wire data do not require a bump. Pre-1.0 clients require an exact wire-version match.
The current wire version is 12. Version 8 introduced typed envelopes, initialization, errors, retry metadata, subscriptions, cursors, acknowledgements, and presence. Version 9 adds the canonical `model.retry_scheduled` event. Version 10 adds `daemon_stopping` as a pre-RPC and universal RPC error. The two incompatible version-11 development surfaces are superseded. Version 12 combines provider-management RPCs with `config.request`, `model.request_configured`, and request settings in session create and configure RPCs. Compatible capability additions that do not alter accepted wire data do not require a bump. Pre-1.0 clients require an exact wire-version match.

The daemon sends `hello` first:

Expand Down
35 changes: 35 additions & 0 deletions docs/model-provider-protocol-compatibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!-- SPDX-FileCopyrightText: 2026 Kaushik Kumar -->
<!-- SPDX-License-Identifier: Apache-2.0 -->

# Model provider protocol compatibility

## Scope

The issue 10 provider contract extends the in-process model stream shared by `packages/protocol`, `packages/ai`, and `packages/kernel`. Provider-management RPCs changed the daemon wire surface. Current `main` independently added model-request configuration under wire version 11. The combined surface therefore uses wire version 12. The persisted JSONL event format remains version 1.

## Additive stream behavior

Existing providers and consumers remain valid. `ModelProvider.refreshModels(): Promise<readonly ModelInfo[]>` remains the legacy additive refresh hook. Context-aware providers use `refreshModelCatalog(context)`, which returns `ModelCatalogRefreshResult`. Legacy string dialect identifiers and boolean compatibility maps remain assignable; built-in codecs still require and validate their typed dialect records.

- Text and thinking deltas may omit `contentIndex`.
- A complete `tool_call` remains the authoritative instruction consumed by the kernel.
- `tool_call_start` and `tool_call_delta` provide optional progress without replacing the complete call.
- Completion, error, and abort remain the only terminal variants, and exactly one terminal event is still required.
- Response attribution, partial-content status, retry guidance, and diagnostics are optional terminal metadata.
- `replay_metadata` is optional nonterminal metadata for one positioned thinking, text, or tool-call block. It does not replace visible content or a complete `tool_call`. Signed thinking may additionally set `redacted: true` when its opaque signature must be replayed as a provider redacted-thinking block rather than ordinary signed thinking.

New codecs should provide stable `contentIndex` values whenever the upstream protocol can interleave text, thinking, and tool blocks. Consumers that do not render incremental tool arguments may ignore progress events and wait for `tool_call`. Consumers that retain provider replay metadata must bind it to the identified content block and exact provider, dialect, and model.

## Trust boundary

`parseModelStreamEvent` validates provider events before normalized streams enter the kernel. The safe diagnostic contract accepts only a code, message, and severity. It intentionally has no arbitrary details, headers, request bodies, stack traces, or credential fields.

Response metadata may contain provider identity, requested and routed model identity, a response ID, native stop detail, and latency. A `replay_metadata` event may contain only exact issuing provider, dialect, and model identity, a content position, an optional tool-call ID, the narrow opaque signature or continuation fields needed for same-model replay, and an optional redacted-thinking marker. That marker is valid only for a thinking target with a signature. Replay metadata cannot carry headers, credentials, arbitrary provider objects, or diagnostics. Empty replay metadata, malformed identities, and mismatched targets fail validation.

The OpenAI Responses codec emits these events for completed reasoning, text, and tool-call items. Azure OpenAI uses the same stream grammar and records the canonical `azure-openai-responses` provider and dialect identity. OpenAI Codex records the `openai-codex-responses` dialect and replays the complete prepared history for stateless SSE requests. It does not infer `previous_response_id` from history because the reviewed Codex continuation is scoped to a proven live connection, account, request baseline, and response prefix. Anthropic Messages emits signed-thinking replay metadata and marks opaque redacted-thinking signatures so the next request reconstructs the correct Anthropic block type. Google Generative AI may attach a thought signature to text, thinking, or tool-call parts. The signature does not classify a part as thinking, only the native `thought` marker does that. Session model-port adapters retain Google signatures on their matching block without inventing continuation state when no continuation identifier was emitted. Google Vertex AI uses the same event conversion but binds replay metadata to the distinct `google-vertex` dialect and provider identity. Bedrock Converse Stream emits signed or encrypted reasoning replay metadata under the `bedrock-converse-stream` dialect and retains provider event positions across interleaved text, thinking, and tool calls. Mistral Conversations replays native visible thinking without opaque replay metadata, preserves positions across interleaved thinking, text, and fragmented tool calls, and reports the native finish reason with requested and routed model identity. Gateway messages carries prepared context to a dynamically routed backend, preserves text, thinking, and tool signatures only for the exact gateway model, accepts gateway-reported usage and cost rather than applying one guessed route price, and reports requested and routed model identity plus the native stop reason. Session model-port adapters retain replay events in memory and attach them to matching assistant history before the next prepared dispatch. Retention is limited to the live port instance and exact issuing model identity. Persisted JSONL events and daemon wire versions remain unchanged, so restart and history reconstruction intentionally do not restore this metadata.

## Model and request metadata

The `packages/ai` additions are optional for existing callers. API dialects, compatibility controls, endpoint policy, cache policy, availability, tiered prices, sampling, cache preferences, timeout, and bounded retry controls are interpreted by provider adapters. The kernel remains provider independent.

Native image generation is an optional capability on `ModelProvider`. Image bytes travel through blob reader and writer callbacks, while results contain content-addressed blob references rather than inline bytes. The OpenRouter image codec keeps this operation outside the canonical text stream: it validates and reads content-addressed reference images, stores each generated image through `writeBlob`, and returns provider, requested model, optional routed model and response identity, revised prompt, usage, cost, and blob references. Cancellation and codec or provider failures reject the image operation with typed, redacted errors rather than inventing text-stream terminal events.
Loading
Loading