Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 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
b3fa4c2
fix(cli): recover verified legacy daemons during explicit restart
Haz3-jolt Sep 8, 2026
05a234c
fix(ai): retain curated Azure models including GPT-6 Astra
Haz3-jolt Sep 8, 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
13 changes: 12 additions & 1 deletion SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,18 @@ axl daemon stop --force --yes

Force is accepted only after graceful shutdown has begun, and only by the same daemon instance. It asks the trusted process host to terminate itself. It never signals a PID taken from a lock file. Forced termination may lose unflushed data or leave tool processes running. If the process cannot service control requests at all, force through this channel is unavailable.

Daemons from builds before host control cannot be recovered through these new commands. For that one-time transition, inspect the old process with operating-system tools, verify its command, owner, and socket, then send SIGTERM to that verified process. A PID in `.axl-data.lock` alone is not proof. Do not delete an active lock or kill every Node process. Once the old process has exited, normal startup reclaims its stale socket and lock. Preserved sessions remain resumable.
For older daemons without host control, Linux hosts can use verified OS recovery:

```bash
axl daemon status
axl daemon restart --interrupt --yes
```

Use `restart`, not `--restart`, and keep the same placement flags as the old daemon. Recovery requires Linux pidfs, readable `/proc`, and `/usr/bin/getino`, `/usr/bin/kill`, and `/usr/bin/waitpid` with `PID:inode` support. Status verifies the owner-only data directory, socket and lock, process owner, Node executable, Axl entry point, command arguments, process HOME, and listening socket ownership. The old daemon must use the same Node executable and Axl entry point as the current CLI. Its active work and clients remain unknown, so both `--interrupt` and `--yes` are mandatory even for an apparently idle daemon.

The CLI rechecks the snapshot, sends SIGTERM only to the verified non-reusable process identity with an installed SIGTERM handler, and waits for exit before restarting. It never falls back to signaling a bare PID, deletes an active lock, or escalates to SIGKILL. `--force` remains available only through host control. Ordinary startup still refuses incompatible daemons without replacing them.

If OS verification or the required utilities are unavailable, recovery fails closed. Manually inspect the old process with operating-system tools and verify its command, owner, and socket before sending SIGTERM. A PID in `.axl-data.lock` alone is not proof. Do not kill every Node process. Once the old process has exited, normal startup reclaims its stale socket and lock. Preserved sessions remain resumable.

### Model request limits

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
2 changes: 2 additions & 0 deletions docs/architecture/client-boundaries.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ Shutdown closes admission synchronously, interrupts active operations, prevents

A single-session `/quit` authorizes interruption. Other attached clients or work require confirmation against the daemon's current preview. CLI stop and restart require `--interrupt` for busy daemons and `--yes` for affected clients. Version mismatch alone never authorizes termination. Forced termination requires a prior shutdown and the exact instance identity, and invokes the process host's termination callback rather than signaling a stored PID.

For legacy daemons without host control, the CLI process host may perform explicit Linux OS recovery. It verifies the executable, entry point, owner, placement, lock, and listening socket against a non-reusable pidfs identity. Unknown activity always requires both `--interrupt` and `--yes`. It rechecks identity, sends SIGTERM only through PID:inode-aware utilities, and waits for exit before restart. Missing verification support fails closed. This recovery does not bypass the session handshake, add PID signaling to the SDK or TUI, enable legacy `--force`, or replace incompatible daemons during ordinary startup.


## Package boundaries

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
Loading
Loading