Skip to content

feat(cloud-agent): event-driven agent host + message-first CLI#1

Open
SarkarShubhdeep wants to merge 5 commits into
mainfrom
feature/cloud-agent
Open

feat(cloud-agent): event-driven agent host + message-first CLI#1
SarkarShubhdeep wants to merge 5 commits into
mainfrom
feature/cloud-agent

Conversation

@SarkarShubhdeep

@SarkarShubhdeep SarkarShubhdeep commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds @mieweb/cloud-agent and @mieweb/cloud-agent-cli — the L2 event shell that binds an AgentDefinition + AgentRuntime to a Durable Object with queue-driven turns, suspend/resume, and alarms.

Developed and exercised by the Jerry project (Phase 1 MVP) via the vendor/cloud submodule pin at ecb8aa7.

@mieweb/cloud-agent

  • hostAgent() — returns SessionClass, handleFetch, handleQueue, and optional handleScheduled
  • Session DO: one instance per session key; drains TurnJob messages one at a time
  • Storage layer: sessions, events, messages, activity_events, summaries (D1/SQLite via CloudDatabase)
  • createTools(ctx) factory — optional per-turn tool injection (used by Jerry for DB/vector/alarm-bound tools)
  • POST /v1/sessions/:id/messages runs turns synchronously for --call CLI ergonomics; /enqueue keeps the async path

@mieweb/cloud-agent-cli

  • Message-first dispatcher: --call (streaming fetch), -txt / --put (fire-and-forget enqueue)
  • Agent identity from basename(argv[0]); agent-specific packages (jerry, etc.) wrap with config
  • Parse tests + HTTP client

Jerry consumer

Jerry repo Detail
Submodule pin vendor/cloud @ ecb8aa7 on development
Consumer packages/jerry-app uses hostAgent() + createJerryTools
CLI packages/cli thin wrapper over @mieweb/cloud-agent-cli

Commits

  • c154c39 — initial cloud-agent + cloud-agent-cli packages
  • ecb8aa7 — synchronous --call turns; createTools injection; profile passthrough

Test plan

  • storage.test.ts — schema init, session/event/message CRUD
  • parse.test.ts — CLI flag/message parsing
  • Jerry integration on local target (pnpm dev + jerry --call …)
  • Conformance on mieweb (libSQL + Valkey + MinIO) — tracked in Jerry Phase 1

Made with Cursor

SarkarShubhdeep and others added 2 commits June 30, 2026 16:49
- Add @mieweb/cloud-agent with hostAgent() API
- Session DO for queue-driven turns, suspend/resume, alarms
- Storage module for sessions, events, messages, activity_events, summaries
- Add @mieweb/cloud-agent-cli with message-first dispatcher
- Support --call (streaming) and -txt/--put (fire-and-forget) modes
- Update README with new packages

Co-authored-by: Cursor <cursoragent@cursor.com>
…a createTools

POST /messages now executes the turn inline instead of only enqueueing, and
hostAgent accepts an optional createTools(ctx) factory so agents like Jerry
can bind runtime tools with DB/vector/alarm context.

Co-authored-by: Cursor <cursoragent@cursor.com>
@SarkarShubhdeep SarkarShubhdeep moved this to Review in Scrum Team Jerry Jul 1, 2026
@SarkarShubhdeep SarkarShubhdeep self-assigned this Jul 1, 2026
SarkarShubhdeep added a commit to mieweb/jerry that referenced this pull request Jul 1, 2026
Document the feature/cloud-agent PR opened on mieweb/cloud and track
Jerry's vendor/cloud pin (ecb8aa7) in phase-1 plan, README, and chat10.

Co-authored-by: Cursor <cursoragent@cursor.com>
@wreiske wreiske requested a review from Copilot July 1, 2026 19:38
@wreiske

wreiske commented Jul 1, 2026

Copy link
Copy Markdown
Member
  • fix broken CI failures
  • resolve any open copilot code review comments
  • add a video on the PR description showing what this is doing, why, who's going to use it, etc.

Comment on lines +28 to +42
export async function initSchema(db: CloudDatabase): Promise<void> {
await db.exec(`
CREATE TABLE IF NOT EXISTS sessions (
id TEXT PRIMARY KEY,
user_id TEXT,
status TEXT NOT NULL DEFAULT 'idle',
conversation_id TEXT,
continuation TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS events (
id TEXT PRIMARY KEY,
session_id TEXT NOT NULL,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if this should be using https://orm.drizzle.team/

Take a look and see if this makes more sense. it might be more of a mieweb/cloud thing that we should support drizzle.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an event-driven “agent host” package (@mieweb/cloud-agent) that wires an AgentDefinition + AgentRuntime into a Durable Object with queue-driven turns, plus a message-first CLI dispatcher package (@mieweb/cloud-agent-cli) for synchronous --call and async enqueue usage.

Changes:

  • Added @mieweb/cloud-agent host wiring (hostAgent, session DO) and a D1/SQLite-compatible storage layer with initial tests.
  • Added @mieweb/cloud-agent-cli with argument parsing, HTTP client (streaming-or-JSON), and a generic bin dispatcher.
  • Updated the packages README to document the new packages.

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
packages/README.md Documents the new cloud-agent and cloud-agent-cli packages in the monorepo index.
packages/cloud-agent/src/types.ts Defines host/session/storage/runtime types for the agent host.
packages/cloud-agent/src/storage.ts Implements schema init + CRUD helpers for sessions/events/messages/activity/summaries.
packages/cloud-agent/src/storage.test.ts Adds basic tests for storage helpers using a mock DB.
packages/cloud-agent/src/session.ts Implements the session Durable Object turn lifecycle, suspend/resume, and alarm handling.
packages/cloud-agent/src/index.ts Public exports for the cloud-agent package.
packages/cloud-agent/src/host.ts Worker wiring: HTTP routes (/v1/sessions/...) + queue forwarding into the session DO.
packages/cloud-agent/package.json Declares the new @mieweb/cloud-agent package metadata/exports/scripts.
packages/cloud-agent-cli/src/types.ts Defines CLI config/options and streamed event types.
packages/cloud-agent-cli/src/run.ts Implements CLI command dispatch and help/version output.
packages/cloud-agent-cli/src/parse.ts Implements message-first CLI argument parsing.
packages/cloud-agent-cli/src/parse.test.ts Adds tests for CLI parsing behavior.
packages/cloud-agent-cli/src/index.ts Public exports for the cloud-agent-cli package.
packages/cloud-agent-cli/src/client.ts Implements HTTP client for /messages (call) and /enqueue (put).
packages/cloud-agent-cli/package.json Declares the new @mieweb/cloud-agent-cli package metadata/bin/scripts.
packages/cloud-agent-cli/bin/agent-cli.js Adds a generic agent CLI bin entrypoint.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/cloud-agent/src/host.ts Outdated
}

if (path.endsWith("/enqueue") && request.method === "POST") {
const body = await request.json() as { message: string };
Comment on lines +116 to +120
await env.JOBS.send({
sessionId,
eventId,
message: body.message,
});
Comment thread packages/cloud-agent/src/session.ts Outdated
Comment on lines +181 to +185
// Read job from request (used for context, e.g. scheduledPayload)
const job = await request.json() as TurnJob;
void job; // Used in future for scheduledPayload handling
// Ensure session exists (also validates sessionId)
await getOrCreateSession(this.env.DB, sessionId);
Comment on lines +281 to +283
} finally {
this.turnInProgress = false;
}
console.error(`Turn failed for session ${job.sessionId}:`, error);
}

message.ack();
Comment thread packages/cloud-agent/src/host.ts Outdated
message.ack();
} catch (err) {
console.error(`Queue processing error for session ${job.sessionId}:`, err);
message.ack();
Comment thread packages/cloud-agent/package.json
Comment thread packages/cloud-agent-cli/package.json
SarkarShubhdeep and others added 2 commits July 1, 2026 16:16
Add lockfile entries for @types/node@^20.0.0 in cloud-agent and
cloud-agent-cli so CI pnpm install --frozen-lockfile succeeds.

Co-authored-by: Cursor <cursoragent@cursor.com>
Tests use `node --import tsx` but tsx was not declared, causing CI unit
job failures on a clean install.

Co-authored-by: Cursor <cursoragent@cursor.com>
@SarkarShubhdeep

Copy link
Copy Markdown
Collaborator Author

mieweb conformance verified (libSQL + Valkey + MinIO)

Ran the conformance checklist item locally against the real @mieweb/cloud-os docker stack — no changes to vendor/cloud required.

Infrastructure (pnpm --filter @mieweb/cloud-os infra:up)

libSQL (:8080), MinIO (:9000), Valkey (:6379) — all healthy.

1. Adapter conformance (pnpm --filter @mieweb/cloud-os test)

Contract Backend Result
D1 libSQL ✅ pass
Vectorize libsql-vec ✅ pass
R2 MinIO (S3) ✅ pass
KV Valkey ✅ pass
Queue valkey-queue ✅ pass

5/5 passed.

2. Jerry on mieweb target (mieweb --target mieweb dev)

Check Binding exercised Result
GET /health worker on mieweb target ✅ pass
GET /v1/sessions/:id/status libSQL + inproc DO ✅ pass
POST /v1/events libSQL (activity_events) ✅ pass
POST /v1/sessions/:id/enqueue Valkey queue + DO ✅ pass
session alive after queue turn queue consumer ✅ pass

Persistence confirmed in libSQL: sessions = 2 rows, activity_events = 2 rows.

Note

Full end-to-end agent turns (jerry --call … / sync /messages) require a running Ollama (:11434), which is application-level and outside target/infra conformance. The DB / KV / queue / object-storage contracts all pass on the mieweb backends.

CI status on the branch: unit ✅ + conformance ✅ (after the lockfile + tsx devDependency fixes).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 17 changed files in this pull request and generated 8 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread packages/cloud-agent/src/host.ts
Comment thread packages/cloud-agent/src/session.ts Outdated
Comment on lines +86 to +98
async alarm(): Promise<void> {
const sessionId = this.state.id.toString();
const payload = await this.state.storage.get<unknown>("alarm_payload");
await this.state.storage.delete("alarm_payload");

await insertEvent(this.env.DB, sessionId, "scheduled_wake", payload);

await this.env.JOBS.send({
sessionId,
eventId: crypto.randomUUID(),
scheduledPayload: payload,
});
}
Comment thread packages/cloud-agent/src/host.ts
`INSERT INTO events (id, session_id, type, payload, created_at)
VALUES (?, ?, ?, ?, ?)`
)
.bind(id, sessionId, type, payload ? JSON.stringify(payload) : null, now)
Comment thread packages/cloud-agent/src/host.ts
Comment thread packages/cloud-agent/src/host.ts
Comment on lines +220 to +240
for await (const event of runtime.runTurn({
messages: coreMessages,
tools,
system: agent.instructions,
maxSteps: 10,
})) {
if (event.type === "text-delta") {
assistantContent += event.text;
} else if (event.type === "finish") {
finishReason = event.finishReason;
} else if (event.type === "suspend") {
this.suspendReason = event.reason;
this.suspendMessage = event.message ?? null;
} else if (event.type === "error") {
await insertEvent(this.env.DB, sessionId, "error", {
message: event.message,
});
await updateSessionStatus(this.env.DB, sessionId, "idle");
return json({ error: event.message }, 500);
}
}
- Forward profile and userId through the /enqueue path into TurnJob so
  async turns honor the per-request privacy profile.
- Persist the enqueued user message and status transitions inside
  handleTurn so queued turns actually consume the new message; slim
  handleMessage to delegate and avoid double-inserts.
- Reset session status to idle (and log an error event) when a turn
  throws, preventing sessions from getting stuck in "running".
- Retry failed/exception queue jobs instead of ack-ing them so
  transient failures are not dropped permanently.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Review

Development

Successfully merging this pull request may close these issues.

3 participants