feat(cloud-agent): event-driven agent host + message-first CLI#1
feat(cloud-agent): event-driven agent host + message-first CLI#1SarkarShubhdeep wants to merge 6 commits into
Conversation
- 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>
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>
|
| 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, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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-agenthost wiring (hostAgent, session DO) and a D1/SQLite-compatible storage layer with initial tests. - Added
@mieweb/cloud-agent-cliwith 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.
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>
✅
|
| 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).
- 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>
- alarm(): create the scheduled_wake event first and reuse its eventId for the queued wake job, and only delete alarm_payload after JOBS.send() succeeds so a failed enqueue can be retried. - insertEvent(): only store NULL when payload is undefined, so falsy payloads (0, false, "") are persisted instead of silently dropped. Co-authored-by: Cursor <cursoragent@cursor.com>
Summary
Adds
@mieweb/cloud-agentand@mieweb/cloud-agent-cli— the L2 event shell that binds anAgentDefinition+AgentRuntimeto a Durable Object with queue-driven turns, suspend/resume, and alarms.Developed and exercised by the Jerry project (Phase 1 MVP) via the
vendor/cloudsubmodule pin atecb8aa7.@mieweb/cloud-agenthostAgent()— returnsSessionClass,handleFetch,handleQueue, and optionalhandleScheduledTurnJobmessages one at a timeCloudDatabase)createTools(ctx)factory — optional per-turn tool injection (used by Jerry for DB/vector/alarm-bound tools)POST /v1/sessions/:id/messagesruns turns synchronously for--callCLI ergonomics;/enqueuekeeps the async path@mieweb/cloud-agent-cli--call(streaming fetch),-txt/--put(fire-and-forget enqueue)basename(argv[0]); agent-specific packages (jerry, etc.) wrap with configJerry consumer
vendor/cloud@ecb8aa7ondevelopmentpackages/jerry-appuseshostAgent()+createJerryToolspackages/clithin wrapper over@mieweb/cloud-agent-cliCommits
c154c39— initialcloud-agent+cloud-agent-clipackagesecb8aa7— synchronous--callturns;createToolsinjection; profile passthroughTest plan
storage.test.ts— schema init, session/event/message CRUDparse.test.ts— CLI flag/message parsinglocaltarget (pnpm dev+jerry --call …)mieweb(libSQL + Valkey + MinIO) — tracked in Jerry Phase 1Made with Cursor