Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
62cdce7
fix(sdk): tell a request timeout apart from a caller cancel
matej21 Aug 6, 2026
98d1abb
chore: drop three unreachable modules and five unused dependencies
matej21 Aug 6, 2026
208bdb2
docs: correct two claims that are false
matej21 Aug 6, 2026
7f83c07
ci: run the test suite before publishing, and let the e2e REST test run
matej21 Aug 6, 2026
5743727
test(sdk): make the service wait helpers fail loudly on timeout
matej21 Aug 6, 2026
23bfa76
chore: ignore .smellhunt/ audit scratch output
matej21 Aug 6, 2026
41bd221
fix: repair four defects in what actually gets published
matej21 Aug 6, 2026
05f6809
fix: stop four silent failure modes in shutdown, stdin, notifications…
matej21 Aug 6, 2026
0865c49
refactor: collapse three duplicated definitions onto one owner each
matej21 Aug 6, 2026
ce3bbb0
refactor(sdk): give the logger levels and the HTTP error envelope one…
matej21 Aug 6, 2026
f705c04
refactor(debug): lift the duplicated ResumeAgentButton into its own m…
matej21 Aug 6, 2026
4c434ae
refactor: import the file-upload wire contract instead of re-typing it
matej21 Aug 6, 2026
970643f
fix: declare @roj-ai/sdk where shared and debug actually need it
matej21 Aug 6, 2026
19f559a
refactor(sdk): remove all five import cycles
matej21 Aug 6, 2026
b8f57e7
fix(standalone-server): type the platform handlers against the shared…
matej21 Aug 6, 2026
ff9d6e1
fix(demo): make snapshot workflows explicit
matej21 Aug 6, 2026
43387bf
test(transport): cover send buffer overflow policy
matej21 Aug 6, 2026
aeedfa1
test(sdk): cover shell stdin EPIPE handling
matej21 Aug 6, 2026
b99e90e
fix(sdk): keep provider cancellation intact through body reads
matej21 Aug 6, 2026
472bf9b
test: cover rejected signal shutdowns
matej21 Aug 6, 2026
c2902fd
ci: validate all package artifacts before publishing
matej21 Aug 6, 2026
8381d94
fix(sdk): report a cancelled inference as aborted, not as the failure…
matej21 Aug 7, 2026
d29937d
fix(sdk): watch a service's exit and output from the moment it spawns
matej21 Aug 6, 2026
33b078f
fix: stop publishing test sources, and let the validator see them
matej21 Aug 7, 2026
6832e8d
fix(sdk): add shared zip archive inspection
matej21 Aug 11, 2026
cb243c7
fix(sdk): await session cleanup during shutdown
matej21 Aug 12, 2026
96ac977
fix(sdk): stop retry backoff promptly
matej21 Aug 12, 2026
5389ca6
fix(sdk): surface shell stdin delivery failures
matej21 Aug 12, 2026
5f64981
fix(sdk): contain served files within session roots
matej21 Aug 12, 2026
85c9d30
fix(sdk): validate resources before extraction
matej21 Aug 12, 2026
16b35d5
fix(standalone): secure session resource startup
matej21 Aug 12, 2026
f6da93a
fix(sdk): make service lifecycle replacement safe
matej21 Aug 12, 2026
24e2574
fix(release): validate packed artifacts before publish
matej21 Aug 12, 2026
906a9c2
ci: enforce release validation gates
matej21 Aug 12, 2026
b65f279
test(sdk): type-check test sources
matej21 Aug 12, 2026
c77e679
fix(sdk): make upload preprocessing abort-safe
matej21 Aug 6, 2026
dc95f69
fix(runtime): make server shutdown race-safe
matej21 Aug 12, 2026
a8ffc22
fix(sdk): make upload deletion durable
matej21 Aug 12, 2026
b0d4e06
fix(sdk): make archive limits configurable
matej21 Aug 12, 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
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,11 @@ jobs:
- name: Run TypeScript build
run: bun run ts:build

- name: Type-check SDK tests
run: bunx tsc -p packages/sdk/tsconfig.test.json --noEmit

- name: Run tests
run: bun run test

- name: Run release tooling tests
run: bun run test:release
23 changes: 22 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ permissions:
id-token: write
contents: read

concurrency:
group: publish-${{ github.repository }}
cancel-in-progress: false

jobs:
publish:
runs-on: ubuntu-latest
Expand All @@ -21,6 +25,9 @@ jobs:
with:
fetch-depth: 0

- name: Verify release ancestry
run: git merge-base --is-ancestor "${{ github.sha }}" origin/main

- uses: actions/setup-node@v4
with:
node-version: '24'
Expand All @@ -45,8 +52,22 @@ jobs:
- name: TypeScript build
run: bun run ts:build

- name: Type-check SDK tests
run: bunx tsc -p packages/sdk/tsconfig.test.json --noEmit

- name: Run tests
run: bun run test

- name: Run release tooling tests
run: bun run test:release

- name: Prepare package manifests
run: node ./scripts/npm-publish/prepare-packages.mjs "${{ github.ref_name }}"
run: node ./scripts/npm-publish/prepare-packages.mjs "$RELEASE_VERSION"
env:
RELEASE_VERSION: ${{ github.ref_name }}

- name: Pack and validate published artifacts
run: node ./scripts/npm-publish/pack-and-validate.mjs

- name: Publish NPM
run: bash ./scripts/npm-publish/run.sh
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,4 @@ buzola.gen.ts
# jj
.jj/
.claude/agent-canvas/
.smellhunt/
41 changes: 16 additions & 25 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"ts:watch": "tsc --build --watch",
"lint": "biome lint .",
"lint:fix": "biome lint . --write",
"test": "bun test packages/*/src packages/*/tests"
"test": "bun test packages/*/src packages/*/tests",
"test:release": "bun test scripts/npm-publish"
},
"devDependencies": {
"@biomejs/biome": "catalog:build",
Expand Down
3 changes: 3 additions & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
"version": "0.1.0",
"type": "module",
"main": "./dist/main.js",
"bin": {
"roj-cli": "./dist/main.js"
},
"files": [
"src",
"dist"
Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/usr/bin/env bun
import { SessionId } from '@roj-ai/shared'
import { RpcError } from '@roj-ai/shared/rpc'
import { createCliClient } from './client.js'
Expand Down
7 changes: 3 additions & 4 deletions packages/client-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,16 @@
"zustand": "5.0.11"
},
"devDependencies": {
"@roj-ai/sdk": "workspace:*",
"@types/react": "19.2.14",
"@types/react-dom": "19.2.3",
"react": "19.2.4",
"react-dom": "19.2.4",
"typescript": "5.9.3"
},
"peerDependencies": {
"lucide-react": "*",
"react": "19.2.4",
"react-dom": "19.2.4"
"lucide-react": ">=0.400.0 <1",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"types": "./dist/index.d.ts"
}
5 changes: 5 additions & 0 deletions packages/client/src/platform/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,10 @@ export type { BuildPreviewUrlOptions, BuildWsUrlOptions } from './urls.js'
export { createRojClient } from './rest-client.js'
export type { RojClient, RojClientOptions, SessionRpcInput } from './rest-client.js'

// File upload wire contract — shared with @roj-ai/platform-cli, which posts to
// the same /api/v1/files/upload endpoint against a server outside this repo.
export { postFile, sha256Hex } from './rest-client.js'
export type { PostFileArgs, PostFileResult } from './rest-client.js'

// Errors
export { RojApiError } from './errors.js'
8 changes: 4 additions & 4 deletions packages/client/src/platform/rest-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ export function createRojClient(options: RojClientOptions): RojClient {
}
}

interface PostFileArgs {
export interface PostFileArgs {
url: string
apiKey: string
contentHash: string
Expand All @@ -249,7 +249,7 @@ interface PostFileArgs {
body?: Blob
}

interface PostFileResult {
export interface PostFileResult {
status: number
body: {
ok?: boolean
Expand All @@ -263,7 +263,7 @@ interface PostFileResult {
} | null
}

async function postFile(args: PostFileArgs): Promise<PostFileResult> {
export async function postFile(args: PostFileArgs): Promise<PostFileResult> {
const formData = new FormData()
formData.append('contentHash', args.contentHash)
formData.append('filename', args.filename)
Expand All @@ -280,7 +280,7 @@ async function postFile(args: PostFileArgs): Promise<PostFileResult> {
return { status: response.status, body }
}

async function sha256Hex(buf: ArrayBuffer): Promise<string> {
export async function sha256Hex(buf: ArrayBuffer): Promise<string> {
const digest = await crypto.subtle.digest('SHA-256', buf)
const bytes = new Uint8Array(digest)
let hex = ''
Expand Down
8 changes: 4 additions & 4 deletions packages/debug/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,22 @@
},
"dependencies": {
"@roj-ai/client": "workspace:*",
"@roj-ai/sdk": "workspace:*",
"@roj-ai/shared": "workspace:*",
"tokenx": "1.3.0",
"zustand": "5.0.11"
},
"devDependencies": {
"@roj-ai/sdk": "workspace:*",
"@types/react": "19.2.14",
"@types/react-dom": "19.2.3",
"react": "19.2.4",
"react-dom": "19.2.4",
"typescript": "5.9.3"
},
"peerDependencies": {
"lucide-react": "*",
"react": "19.2.4",
"react-dom": "19.2.4"
"lucide-react": ">=0.400.0 <1",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"types": "./dist/index.d.ts"
}
48 changes: 48 additions & 0 deletions packages/debug/src/components/debug/ResumeAgentButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { api, unwrap } from "@roj-ai/client";
import { AgentId } from "@roj-ai/shared";
import { type FormEvent, useCallback, useState } from "react";

/**
* Resume a paused agent. Shared by DashboardPage and AgentDetailPage, which
* each carried a byte-identical copy.
*/
export function ResumeAgentButton({
sessionId,
agentId,
}: {
sessionId: string;
agentId: string;
}) {
const [resuming, setResuming] = useState(false);

const handleResume = useCallback(
async (e: FormEvent) => {
e.stopPropagation();
setResuming(true);
try {
unwrap(
await api.call("agents.resume", {
sessionId,
agentId: AgentId(agentId),
}),
);
} catch {
// Error is visible via state change (or lack thereof)
} finally {
setResuming(false);
}
},
[sessionId, agentId],
);

return (
<button
type="button"
onClick={handleResume}
disabled={resuming}
className="text-[11px] font-semibold text-white bg-red-600 hover:bg-red-700 px-2.5 py-1 rounded-lg disabled:opacity-50 disabled:cursor-not-allowed transition-colors shrink-0 cursor-pointer"
>
{resuming ? "Resuming..." : "Resume"}
</button>
);
}
Loading
Loading