Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 11 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,39 @@ on:

jobs:
verify:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/checkout@v7.0.1
- uses: pnpm/action-setup@v6.1.0
with:
version: 11.5.0
- uses: actions/setup-node@v4
- uses: actions/setup-node@v7.1.0
with:
node-version: 22.19.0
node-version: 24.22.2
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Install shells for installer tests
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends zsh fish
- run: pnpm release:audit
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7.0.2
with:
name: agentonweb-${{ github.sha }}
path: release/

dsh-latest:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
env:
DSH_TEST_PREFIX: /tmp/agentonweb-dsh-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/checkout@v7.0.1
- uses: pnpm/action-setup@v6.1.0
with:
version: 11.5.0
- uses: actions/setup-node@v4
- uses: actions/setup-node@v7.1.0
with:
node-version: 22.19.0
node-version: 24.22.2
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Build extension and pack the actual DSH plugin
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ permissions:

jobs:
release:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
env:
RELEASE_TAG: ${{ inputs.tag || github.ref_name }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7.0.1
with:
ref: ${{ inputs.tag || github.ref }}
- uses: pnpm/action-setup@v4
- uses: pnpm/action-setup@v6.1.0
with:
version: 11.5.0
- uses: actions/setup-node@v4
- uses: actions/setup-node@v7.1.0
with:
node-version: 22.19.0
node-version: 24.22.2
cache: pnpm
registry-url: https://registry.npmjs.org
- run: pnpm install --frozen-lockfile
Expand Down
4 changes: 2 additions & 2 deletions AMO-BUILD.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Reproduce the Firefox extension

This source archive contains the complete tracked source for AgentOnWeb 0.4.0.
Use Node.js 22.19.0 and pnpm 11.5.0 on Linux or macOS. No API keys, local
This source archive contains the complete tracked source for AgentOnWeb.
Use Node.js 24.22.2 and pnpm 11.5.0 on Linux or macOS. No API keys, local
terminal service, model credentials or private signing configuration are needed.

```sh
Expand Down
3 changes: 2 additions & 1 deletion docs/development.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Development

Use Node.js 22.19+ and pnpm 11.5.0.
Use Node.js 24.22.2 and pnpm 11.5.0 for builds and CI. The installed terminal
host continues to support Node.js 22.19+.

```sh
git clone https://github.com/HeftyKoo/AgentOnWeb.git
Expand Down
30 changes: 30 additions & 0 deletions docs/verification/ci-host-readiness-2026-10-29.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Host startup readiness and CI runtime

The previous CI run 40326913684 failed while parsing the first terminal registry
response. Extension release run 40802248815 initially failed at the same stage
of the authorized-browser revocation test. Both tests first open the one-time
launch URL and reuse the cookies it returns.

The host printed that URL before its initial `saveEndpoint()` completed.
Opening the URL immediately started another save to the same `endpoint.tmp`.
One rename could remove the other request's temporary file, causing `/launch`
to return HTTP 500 without cookies. The next protected API request returned
HTTP 403 with an empty body, producing `Unexpected end of JSON input`.

The regression test delays the first two endpoint writes in an isolated child
host. Before the fix, the launch request returned HTTP 500 instead of 200.
After moving the initial endpoint save before the readiness log, the launch
returns HTTP 200 with its admin cookie, and both protected JSON APIs respond
successfully. All 27 host integration tests and the complete release audit
passed locally: 428 tests passed and two optional tests were skipped.

CI and Release now use Node.js 24.22.2 on Ubuntu 24.04. Their actions are
checkout 7.0.1, setup-node 7.1.0, pnpm/action-setup 6.1.0 and upload-artifact
7.0.2; each upstream action manifest declares `runs.using: node24`. Pinning the
runner avoids the `ubuntu-latest` Ubuntu 26 migration notice. The terminal
runtime minimum remains Node.js 22.19.

The previously created `ext-v0.4.2` tag remains unchanged. Its second Release
attempt succeeded, and Chrome/Firefox 0.4.2 were submitted from its audited
packages. This follow-up changes future builds and CI; it does not republish
the existing terminal-host 0.4.3 npm package.
2 changes: 1 addition & 1 deletion packages/terminal-host/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -572,11 +572,11 @@ authority.onRevoke(() => {
for (const socket of sockets.clients) socket.close(4401, "Authorization revoked");
connector.refreshSurfaces();
});
await saveEndpoint();
console.log(
`${terminalUi().banner('LOCAL SHELL')}\nExecutable: ${executable}\nInitial directory: ${cwd}\nConnector: ${connector.port}\nOpen once: ${origin}/launch?token=${launchToken}`,
);
printStatus('info', 'Approve your browser through the private setup page.');
await saveEndpoint();
const stopUpdateChecks = updates.start(status => {
printStatus('warn', `AgentOnWeb ${status.latest} is available (running ${VERSION}). Run aow update after closing terminal sessions.`);
});
Expand Down
36 changes: 36 additions & 0 deletions packages/terminal-host/src/host.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,42 @@ it('restricts update status to admins and maintenance to the local CLI, preservi
await expect.poll(async () => (await (await control()).json()).activeTerminals).toBe(0);
expect((await control({ action: 'prepare' })).status).toBe(200);
});
it("persists its initial endpoint before publishing the one-time launch URL", async () => {
directory = await mkdtemp(join(tmpdir(), "aow-startup-readiness-test-"));
const guard = join(directory, "slow-endpoint-writes.mjs");
await writeFile(guard, `
import fs from "node:fs";
import { syncBuiltinESMExports } from "node:module";
const writeFile = fs.promises.writeFile;
let endpointWrites = 0;
fs.promises.writeFile = async (path, ...args) => {
const delay = String(path).endsWith("endpoint.tmp") ? (++endpointWrites === 1 ? 100 : 250) : 0;
await writeFile(path, ...args);
if (delay) await new Promise(resolveDelay => setTimeout(resolveDelay, delay));
};
syncBuiltinESMExports();
`);
host = spawn(process.execPath, ["--import", guard, resolve("packages/terminal-host/lib/cli.js"), "terminal"], {
env: { ...process.env, HOME: directory, SHELL: "/bin/sh", ENV: undefined, BASH_ENV: undefined, ZDOTDIR: undefined },
stdio: ["pipe", "pipe", "pipe"],
});
let output = "";
host.stdout!.on("data", chunk => { output += chunk; });
await expect.poll(() => output.includes("Open once:"), { timeout: 10000 }).toBe(true);
const launchUrl = /Open once: (http:\/\/[^\s]+)/u.exec(output)![1]!;
const origin = new URL(launchUrl).origin;
const launch = await fetch(launchUrl);
expect(launch.status, await launch.text()).toBe(200);
const cookies = launch.headers.getSetCookie().map(value => value.split(";")[0]!).join("; ");
expect(cookies).toContain("aow_admin_");
const headers = { Cookie: cookies, "X-AgentOnWeb-Terminal": "1", Origin: origin };
for (const path of ["/api/terminals", "/api/connections"]) {
const response = await fetch(origin + path, { headers });
expect(response.status).toBe(200);
expect(await response.json()).toBeTruthy();
}
});

it("preserves Unicode terminal names split across HTTP body chunks and publishes terminal registry changes", async () => {
directory = await mkdtemp(join(tmpdir(), "aow-unicode-test-"));
host = spawn(process.execPath, [resolve("packages/terminal-host/lib/cli.js"), "terminal"], {
Expand Down