Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
web-build:
name: web build
runs-on: ubuntu-24.04
timeout-minutes: 15
timeout-minutes: 25

defaults:
run:
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,22 @@ jobs:
> SHA256SUMS
cat SHA256SUMS

- name: Select version-specific release notes
id: notes
shell: bash
run: |
notes="docs/releases/${{ needs.metadata.outputs.tag }}.md"
if [ -f "$notes" ]; then
echo "path=$notes" >> "$GITHUB_OUTPUT"
fi

- name: Publish GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.metadata.outputs.tag }}
name: Liaison ${{ needs.metadata.outputs.tag }}
generate_release_notes: true
body_path: ${{ steps.notes.outputs.path }}
prerelease: ${{ needs.metadata.outputs.prerelease == 'true' }}
files: |
liaison-${{ needs.metadata.outputs.version }}-linux-amd64.tar.gz
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ English | [简体中文](./README_zh.md) | [日本語](./README_ja.md) | [한국
Download the self-contained Docker bundle, extract it, and run the installer (Docker 20.10+ with Compose is required):

```bash
wget https://github.com/liaisonio/liaison/releases/download/v1.14.1/liaison-1.14.1-linux-amd64.tar.gz
tar -xzf liaison-1.14.1-linux-amd64.tar.gz
cd liaison-1.14.1-linux-amd64
wget https://github.com/liaisonio/liaison/releases/download/v1.15.0-rc.1/liaison-1.15.0-rc.1-linux-amd64.tar.gz
tar -xzf liaison-1.15.0-rc.1-linux-amd64.tar.gz
cd liaison-1.15.0-rc.1-linux-amd64
./install.sh
```

Expand Down
6 changes: 3 additions & 3 deletions README_de.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ Installiere das tar.gz-Serverpaket und anschließend einen Konnektor.
**1. Herunterladen**

```bash
wget https://github.com/liaisonio/liaison/releases/download/v1.14.1/liaison-1.14.1-linux-amd64.tar.gz
tar -xzf liaison-1.14.1-linux-amd64.tar.gz
cd liaison-1.14.1-linux-amd64
wget https://github.com/liaisonio/liaison/releases/download/v1.15.0-rc.1/liaison-1.15.0-rc.1-linux-amd64.tar.gz
tar -xzf liaison-1.15.0-rc.1-linux-amd64.tar.gz
cd liaison-1.15.0-rc.1-linux-amd64
```

**2. Installationsskript ausführen**
Expand Down
6 changes: 3 additions & 3 deletions README_es.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ Instala el paquete tar.gz del servidor y después instala un conector.
**1. Descargar**

```bash
wget https://github.com/liaisonio/liaison/releases/download/v1.14.1/liaison-1.14.1-linux-amd64.tar.gz
tar -xzf liaison-1.14.1-linux-amd64.tar.gz
cd liaison-1.14.1-linux-amd64
wget https://github.com/liaisonio/liaison/releases/download/v1.15.0-rc.1/liaison-1.15.0-rc.1-linux-amd64.tar.gz
tar -xzf liaison-1.15.0-rc.1-linux-amd64.tar.gz
cd liaison-1.15.0-rc.1-linux-amd64
```

**2. Ejecutar el script de instalación**
Expand Down
6 changes: 3 additions & 3 deletions README_fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ Installez le paquet tar.gz du serveur, puis installez un connecteur.
**1. Télécharger**

```bash
wget https://github.com/liaisonio/liaison/releases/download/v1.14.1/liaison-1.14.1-linux-amd64.tar.gz
tar -xzf liaison-1.14.1-linux-amd64.tar.gz
cd liaison-1.14.1-linux-amd64
wget https://github.com/liaisonio/liaison/releases/download/v1.15.0-rc.1/liaison-1.15.0-rc.1-linux-amd64.tar.gz
tar -xzf liaison-1.15.0-rc.1-linux-amd64.tar.gz
cd liaison-1.15.0-rc.1-linux-amd64
```

**2. Exécuter le script d'installation**
Expand Down
6 changes: 3 additions & 3 deletions README_ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@
**1. ダウンロード**

```bash
wget https://github.com/liaisonio/liaison/releases/download/v1.14.1/liaison-1.14.1-linux-amd64.tar.gz
tar -xzf liaison-1.14.1-linux-amd64.tar.gz
cd liaison-1.14.1-linux-amd64
wget https://github.com/liaisonio/liaison/releases/download/v1.15.0-rc.1/liaison-1.15.0-rc.1-linux-amd64.tar.gz
tar -xzf liaison-1.15.0-rc.1-linux-amd64.tar.gz
cd liaison-1.15.0-rc.1-linux-amd64
```

**2. インストールスクリプトを実行**
Expand Down
6 changes: 3 additions & 3 deletions README_ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@
**1. 다운로드**

```bash
wget https://github.com/liaisonio/liaison/releases/download/v1.14.1/liaison-1.14.1-linux-amd64.tar.gz
tar -xzf liaison-1.14.1-linux-amd64.tar.gz
cd liaison-1.14.1-linux-amd64
wget https://github.com/liaisonio/liaison/releases/download/v1.15.0-rc.1/liaison-1.15.0-rc.1-linux-amd64.tar.gz
tar -xzf liaison-1.15.0-rc.1-linux-amd64.tar.gz
cd liaison-1.15.0-rc.1-linux-amd64
```

**2. 설치 스크립트 실행**
Expand Down
6 changes: 3 additions & 3 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@
下载自带所有镜像的 Docker 离线包,解压后运行安装脚本(需要 Docker 20.10+ 及 Compose):

```bash
wget https://github.com/liaisonio/liaison/releases/download/v1.14.1/liaison-1.14.1-linux-amd64.tar.gz
tar -xzf liaison-1.14.1-linux-amd64.tar.gz
cd liaison-1.14.1-linux-amd64
wget https://github.com/liaisonio/liaison/releases/download/v1.15.0-rc.1/liaison-1.15.0-rc.1-linux-amd64.tar.gz
tar -xzf liaison-1.15.0-rc.1-linux-amd64.tar.gz
cd liaison-1.15.0-rc.1-linux-amd64
./install.sh
```

Expand Down
7 changes: 5 additions & 2 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Liaison uses one repository and two release tag families:
git push origin v1.6.0
```

4. GitHub Actions runs `Server Release` and uploads:
4. GitHub Actions runs `Release` and uploads:

```text
liaison-1.6.0-linux-amd64.tar.gz # default Docker bundle
Expand All @@ -36,7 +36,10 @@ The platform package already contains CLI edge packages for Linux, macOS, and Wi

The release workflow also runs the version sync in its checkout, so the README files embedded in the release tarball always match the tag.

The same workflow can also be started manually from GitHub Actions with a version input, but tag-based release is the normal path.
The workflow is tag-triggered. `vX.Y.Z-rc.N` uses the same packaging pipeline
and is automatically marked as a GitHub prerelease. Put version-specific
upgrade instructions and known limits in `docs/releases/<tag>.md`, and include
that document in the published release description.

## Desktop Release

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.14.1
1.15.0-rc.1
27 changes: 27 additions & 0 deletions api/agent_applications.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
syntax = "proto3";
package liaison.agent_applications;
option go_package = "github.com/liaisonio/liaison/api/agent_applications;agent_applications";
// Handwritten JSON transport, like edge_agent.proto. No generated service.
// GET /api/v1/agent-applications?page=1&page_size=20&edge_id=...
// POST /api/v1/agent-applications registers a discovered, owned installation.
// PUT /api/v1/agent-applications/{id} renames only; identity is immutable.
// DELETE /api/v1/agent-applications/{id} rejects referenced applications (409).
// Actor comes from authentication, never from the input.
message AgentApplicationInput {
string name = 1;
string kind = 2;
uint64 edge_id = 3;
string installation_id = 4;
}
message AgentApplication {
string id = 1;
string name = 2;
string kind = 3;
uint64 edge_id = 4;
string installation_id = 5;
int64 access_count = 6;
}
message AgentApplicationList { repeated AgentApplication items = 1; int64 total = 2; }
// Additive field for the existing handwritten AgentAccessInput JSON contract.
// application_id resolves the installation on the server. Supplied legacy
// kind/edge_id/installation_id fields must match, not override, that association.
33 changes: 31 additions & 2 deletions api/edge_agent.proto
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,19 @@ message EdgeAgentRequest {
string input_id = 18; // answer: opaque live request ID, not a native RPC ID.
repeated InputAnswer answers = 19;
string history_before = 20; // transcript: exclusive window cursor, one archived round per page.
AgentFileOperation file = 21; // file_* actions only; bounded chunks, never model content.
repeated string attachments = 22; // send: session-local relative attachment paths, max 8.
}
// file_list, file_begin, file_write, file_commit, file_cancel, file_read.
// Transfers require own access + session + connector on every chunk. Uploads
// create unique files under .liaison-attachments/<session>, never overwrite.
message AgentFileOperation {
string path = 1; string name = 2; string transfer_id = 3;
int64 offset = 4; int64 size = 5; bytes data = 6;
}
message AgentFile {
string name = 1; string path = 2; int64 size = 3; bool directory = 4;
string media_type = 5;
}
// Edge RPC name: edge_agent_v1. No raw RPC forwarding from HTTP clients.
message EdgeAgentRPCRequest {
Expand All @@ -59,7 +72,7 @@ message ResumeState {
bool truncated = 9;
}
message Installation { string id = 1; string kind = 2; string path = 3; string source = 4; }
message Message { string role = 1; string text = 2; }
message Message { string role = 1; string text = 2; repeated AgentFile attachments = 3; }
message EdgeAgentResult {
uint32 version = 1;
// ok, busy, unavailable, upgrade_required, not_found, unsupported_user,
Expand Down Expand Up @@ -101,8 +114,24 @@ message EdgeAgentResult {
repeated InputRequest input_requests = 35; // Live only; removed from persisted snapshots.
uint64 window = 36;
bool history_windowing = 37;
bool files_available = 38;
repeated AgentFile files = 39;
AgentFile file = 40;
string transfer_id = 41;
bytes file_data = 42;
int64 file_offset = 43;
bool file_done = 44;
bool files_upload_available = 45;
AgentTurnTiming turn_timing = 46; // Edge-local monotonic durations, not pure model/network latency.
optional int64 request_service_ms = 47; // send response only: Manager handler elapsed time, before JSON encoding.
}
// Last locally started turn only. Missing values mean not observed; zero is valid.
message AgentTurnTiming {
optional int64 dispatch_ms = 1; // Native send/control round trip from Edge.
optional int64 first_reply_ms = 2; // Edge turn start to first non-empty assistant text.
optional int64 finished_ms = 3; // Includes tools and approval waits.
}
message Approval { string id = 1; string command = 2; string directory = 3; string reason = 4; }
message Approval { string id = 1; string command = 2; string directory = 3; string reason = 4; string kind = 5; repeated FileChange changes = 6; }
message AgentModel { string id = 1; string name = 2; }
message SessionSummary {
string session_id = 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- Run only after returning to an older manager and backing up application metadata.
-- Access IDs, legacy installation fields and session history are preserved.
DROP INDEX IF EXISTS idx_agent_accesses_application_id;
ALTER TABLE agent_accesses DROP COLUMN application_id;
DROP TABLE IF EXISTS agent_applications;
24 changes: 24 additions & 0 deletions db/migrations/20260926010000_create_agent_applications.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
-- Apply once using the migration ledger, before starting the new manager.
CREATE TABLE IF NOT EXISTS agent_applications (
id TEXT PRIMARY KEY,
owner_id INTEGER NOT NULL,
edge_id INTEGER NOT NULL,
kind TEXT NOT NULL,
installation_id TEXT NOT NULL,
name TEXT NOT NULL,
created_at DATETIME,
updated_at DATETIME
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_agent_installation ON agent_applications(owner_id, edge_id, kind, installation_id);
ALTER TABLE agent_accesses ADD COLUMN `application_id` TEXT DEFAULT "";
CREATE INDEX IF NOT EXISTS idx_agent_accesses_application_id ON agent_accesses(application_id);
INSERT INTO agent_applications (id, owner_id, edge_id, kind, installation_id, name, created_at, updated_at)
SELECT lower(hex(randomblob(16))), owner_id, edge_id, kind, installation_id, 'Codex', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP
FROM agent_accesses
GROUP BY owner_id, edge_id, kind, installation_id
ON CONFLICT(owner_id, edge_id, kind, installation_id) DO NOTHING;
UPDATE agent_accesses SET application_id = (
SELECT id FROM agent_applications a WHERE a.owner_id = agent_accesses.owner_id
AND a.edge_id = agent_accesses.edge_id AND a.kind = agent_accesses.kind
AND a.installation_id = agent_accesses.installation_id
) WHERE application_id IS NULL OR application_id = '';
64 changes: 64 additions & 0 deletions docs/architecture/edge-agent-files.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Agent session files

The browser transfers files through Manager and the authenticated Edge RPC channel.
Codex does not transport file bytes. Each chunk reauthorizes the user, saved access,
connector ownership and file feature permissions. Edge independently verifies its
durable user/access/session binding and saved project.

## Boundaries and limits

- Content access is restricted to the session's working directory using `os.Root`.
Directory discovery's broader home-directory scope does not grant file access.
- Uploads create unique files in `.liaison-attachments/<session-id>/`, mode 0600.
They never replace existing project files. Removing a composer attachment only
detaches it from the pending message; it does not delete the uploaded file.
- Each file is limited to 20 MiB; each message to eight attachments. Native image
inputs support PNG, JPEG and GIF, up to 4 MiB and 40 million pixels per image.
- Transfers use 128 KiB chunks, with exact offsets and at most eight live transfers
per Edge. Abandoned transfers expire after two minutes. Partial uploads are hidden
and cannot be downloaded; commit publishes the complete file without overwrite.
- Downloads hold an open file descriptor and reject files changed during transfer.
They are saved as attachments, never rendered as HTML or executed.
- Image content is validated and copied into an Edge-owned temporary snapshot before
passing `localImage` to Codex. These exact snapshots are removed on the next turn
or session close. Original uploads remain in the project.
- Manager persists attachment names, paths and sizes with encrypted conversation
history. It does not persist transfer chunks or image bytes in SQLite.

## UI and compatibility

The composer supports file selection, image selection, file drop and image paste.
Uploads have progress/cancel, local image previews and removable attachment chips.
Project files can be browsed from the session header; clicking a file opens its
preview and a separate action downloads it. Sent attachment
chips also provide download actions. File content requires an online connector.

Conversation file links open a resizable right-side preview (full-screen on small
screens), with syntax highlighting, line numbers, line-range navigation, copying
and download. HTTP(S) links remain external links. Relative paths and absolute paths
inside the current project are converted to project-relative reads; invalid or
out-of-project paths do not trigger a read. Edge still enforces the actual boundary,
including symlink traversal, for every request. Directory links use the same scoped
file browser API. Previewing does not execute Codex commands or synchronize a repo.

Previews show current file contents, not historical revisions. UTF-8 text previews
are limited to 1 MiB and 10,000 lines; syntax highlighting is limited to 200,000
characters and is loaded on demand. Other files can be downloaded within the
existing transfer limit. Highlighting produces React text/span nodes, not raw HTML.
Closing a preview aborts reads; unfinished known transfers are cancelled. Preview
contents remain in browser memory, not conversation history or browser storage.

README (without an extension), `.md` and `.markdown` files default to the shared
safe Markdown preview, with a source toggle. Links with line targets default to
source so line navigation remains precise. Markdown rendering is capped at 200,000
characters; larger documents fall back to source. Raw HTML and embedded images are
not loaded. Project-relative document links, source line links and heading anchors
open inside the preview with back navigation. Parent segments are normalized only
within the project; paths escaping the project are rejected before a file read.
Heading navigation reuses the loaded contents and only scrolls the preview pane.
HTTP(S) links can be opened explicitly in a separate tab.

The optional `files_available` / `files_upload_available` capabilities gate controls.
Both Manager and Edge must be upgraded; older connectors remain usable for chat
without file controls. Native model/configuration selection is unchanged. The current
Agent runtime supports macOS and Linux; this does not add Windows Agent support.
Loading
Loading