Skip to content

feat(cli): service augments — translate demo with optional DB / KV / Queue / Vector / Storage#1445

Merged
Huijiro merged 26 commits intov3from
cli/service-augments-plan
May 5, 2026
Merged

feat(cli): service augments — translate demo with optional DB / KV / Queue / Vector / Storage#1445
Huijiro merged 26 commits intov3from
cli/service-augments-plan

Conversation

@Huijiro
Copy link
Copy Markdown
Member

@Huijiro Huijiro commented May 4, 2026

Adds a service-augment system to agentuity project create. After framework scaffolding + the AI translation demo, the user picks zero or more of db, keyvalue, queue, vector, storage. Each selected service splices code into the existing translate page and adds the routes/files it owns. The output looks hand-written: no commented-out code, no feature flags, no dead imports.

Composition strategy

Insertion-point comment markers, single-line, no conditionals. Each composable file in the base template carries comment markers like // @agentuity:translate-pre. Each service ships per-framework snippets keyed by marker. The composer concatenates contributions in catalog-defined order, re-indents to match the marker line's leading whitespace, and strips the markers. Pure text, no AST.

  • 11+ markers per framework (4 server-side in the translate() helper, 7 view-side in the page, plus imports/module/routes in the server entry for vite-react and hono).
  • Per-framework manifest declares marker syntax (//, {/* */}, or <!-- -->).
  • Whole files (drizzle config, schema, dedicated routes) are owned by one service and copied verbatim.
  • Catalog order is fixed: keyvalue (10) → db (20) → vector (30) → queue (40) → storage (50). Storage requires DB.
  • Adjacent same-module imports are merged post-compose so React + service useEffect snippets land as a single statement.

Frameworks

All 7 framework templates were refactored to extract translate() into a helper file and slim the route/action to a thin caller. Each gains a manifest.json declaring composable files + per-marker syntax. Hono additionally moved its inline HTML template literal into src/landing.html so view markers can sit in real comments.

Framework helper route/action view
Next.js src/lib/translate.ts src/app/api/translate/route.ts src/app/page.tsx
Remix app/lib/translate.ts app/routes/api.translate.ts app/routes/home.tsx
Vite+React server/translate.ts server.ts (delegates) src/App.tsx
Nuxt server/utils/translate.ts server/api/translate.post.ts app.vue
SvelteKit src/lib/server/translate.ts src/routes/+page.server.ts src/routes/+page.svelte
Astro src/lib/translate.ts src/pages/api/translate.ts src/pages/index.astro
Hono src/translate.ts src/index.ts src/landing.html

Services

Service Behavior in the augmented translate demo
DB (drizzle-orm, @neondatabase/serverless, drizzle-kit) Cache translations in PostgreSQL; show last 10 entries in a History panel under the form. Adds db:generate/migrate/push/studio scripts and DATABASE_URL to .env.example.
KeyValue (@agentuity/keyvalue) Persist user's last language/model. Loaded on mount, saved after each result.
Queue (@agentuity/queue) "Translate later" button enqueues translation jobs; pending-jobs panel shows what's been enqueued in the session.
Vector (@agentuity/vector) Upsert each translation into a vector namespace; show "Similar past translations" panel with top-5 nearest neighbours under each result.
Storage (@agentuity/storage, requires db) "Export history" button bundles DB history as JSON, uploads to S3-compatible bucket, reports filename + size.

CLI integration

  • agentuity project create --services db,keyvalue for headless use; unknown ids fail loudly with a helpful list.
  • Interactive multi-select prompt when no flag is passed.
  • Auto-resolves transitive requires (selecting storage silently includes db).
  • DB and @agentuity/postgres/@agentuity/drizzle deprecation: the wrapper packages were marked deprecated earlier in this branch; the DB augment uses vanilla drizzle-orm + @neondatabase/serverless.

Cloud-resource provisioning for KV / Queue / Vector is not wired into this PR — the existing DB + storage prompts still drive their own provisioning paths. Service code lands in either case; users run agentuity dev to wire up the missing env vars. Provisioning the new resource types is a separate follow-up.

Tests

73 service-related tests across 10 files, all pass:

  • Composer unit tests (services-composer.test.ts): 12 tests covering empty selection, ordering, all 3 marker syntaxes, missing snippets, missing markers, transitive requires, package.json + .env merges, file copies, import merging.
  • Catalog tests (services-catalog.test.ts, services-resolve-selection.test.ts): 12 tests validating the bundled catalog and the resolveSelection helper used by the CLI flag.
  • Per-framework base composition (services-composer-base.test.ts): 7 frameworks × 1 test each, asserting marker strip with no services produces clean output.
  • Per-service composition (services-composer-{db,keyvalue,queue,vector,storage}.test.ts): 7 frameworks × 5 services = 35 tests asserting whole files land at expected paths, snippets splice into the right markers, and package.json / .env.example pick up deps + vars.
  • All-services smoke (services-composer-all.test.ts): 7 frameworks × every service together, asserting no marker leaks.

Pre-existing test/cmd/dev/backend-proxy.test.ts (stale v2 dev-server tests) failures are unrelated.

Commits

The branch is structured for review:

  1. PLAN.md (the design doc)
  2. M1: composer infra + Next.js base refactor
  3. M2: 6 commits, one per remaining framework refactor
  4. Cross-cutting changes (cached?: boolean field, server composable for vite-react/hono, import merger)
  5. M3–M7: one commit per service
  6. M8: --services flag wiring

@agentuity-agent
Copy link
Copy Markdown

agentuity-agent Bot commented May 4, 2026

The latest Agentuity deployment details.

Project Deployment Preview Updated (UTC)
docs 🔴 Failed (deploy_499d9a3428d98e678f22cb08f1686fd7) - 2026-05-05T00:03:50Z

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 4, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: decdbe1f-0ffd-45f8-89cb-9233fa9c3bcc

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

📦 Canary Packages Published

version: 3.0.0-alpha.7-1bdfcee

Packages
Package Version URL
@agentuity/core 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-core-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/coder 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-coder-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/runtime 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-runtime-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/sandbox 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-sandbox-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/server 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-server-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/db 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-db-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/adapter 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-adapter-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/claude-code 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-claude-code-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/postgres 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-postgres-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/stream 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-stream-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/vector 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-vector-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/webhook 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-webhook-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/migrate 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-migrate-3.0.0-alpha.7-1bdfcee.tgz
create-agentuity 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/create-agentuity-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/local 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-local-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/schema 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-schema-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/hono 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-hono-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/drizzle 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-drizzle-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/opencode 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-opencode-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/queue 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-queue-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/storage 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-storage-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/task 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-task-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/schedule 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-schedule-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/keyvalue 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-keyvalue-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/telemetry 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-telemetry-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/analytics 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-analytics-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/email 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-email-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/coder-tui 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-coder-tui-3.0.0-alpha.7-1bdfcee.tgz
@agentuity/cli 3.0.0-alpha.7-1bdfcee https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-cli-3.0.0-alpha.7-1bdfcee.tgz
Install

Add to your package.json:

{
  "dependencies": {
    "@agentuity/core": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-core-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/coder": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-coder-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/runtime": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-runtime-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/sandbox": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-sandbox-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/server": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-server-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/db": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-db-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/adapter": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-adapter-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/claude-code": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-claude-code-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/postgres": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-postgres-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/stream": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-stream-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/vector": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-vector-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/webhook": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-webhook-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/migrate": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-migrate-3.0.0-alpha.7-1bdfcee.tgz",
    "create-agentuity": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/create-agentuity-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/local": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-local-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/schema": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-schema-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/hono": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-hono-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/drizzle": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-drizzle-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/opencode": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-opencode-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/queue": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-queue-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/storage": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-storage-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/task": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-task-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/schedule": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-schedule-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/keyvalue": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-keyvalue-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/telemetry": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-telemetry-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/analytics": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-analytics-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/email": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-email-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/coder-tui": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-coder-tui-3.0.0-alpha.7-1bdfcee.tgz",
    "@agentuity/cli": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-cli-3.0.0-alpha.7-1bdfcee.tgz"
  }
}

Or install directly:

bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-core-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-coder-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-runtime-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-sandbox-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-server-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-db-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-adapter-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-claude-code-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-postgres-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-stream-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-vector-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-webhook-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-migrate-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/create-agentuity-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-local-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-schema-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-hono-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-drizzle-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-opencode-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-queue-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-storage-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-task-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-schedule-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-keyvalue-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-telemetry-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-analytics-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-email-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-coder-tui-3.0.0-alpha.7-1bdfcee.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.0-alpha.7-1bdfcee/agentuity-cli-3.0.0-alpha.7-1bdfcee.tgz

Huijiro added 2 commits May 4, 2026 10:36
Extract translate() into src/lib/translate.ts and slim the API route to a
thin caller. Add insertion-marker comments at 11 named positions across
the two composable files (4 server-side in translate.ts, 7 view-side in
page.tsx). Add templates/nextjs/manifest.json declaring the composable
files and the comment syntax for each marker.

This is a one-time refactor that improves the base regardless of
services. With no services selected, the composer (next commit) strips
all marker comments so the user-facing output is unchanged.

Part of M1 of the service augments plan (PLAN.md).
services-catalog.ts loads service manifests from
templates/services/<id>/manifest.json into a typed array, validates
`requires` references, and supports test-injected catalog dirs.

services-composer.ts is a pure-text composer that:
- Copies whole files a service owns (templates/services/<id>/files/<framework>/)
- Splices snippets into composable base files at named comment markers
- Re-indents zero-indented snippets to match the marker line's leading
  whitespace
- Merges package.json (deps, devDeps, scripts) and .env.example
- Treats unknown frameworks as no-op so template-flow can call it
  unconditionally during the rollout to all 7 frameworks

Markers are insertion-only (no conditionals, no replacement). Service
order is fixed by manifest.order, so output is deterministic regardless
of how the user picks services in the multi-select.

Wired into template-flow.ts after scaffoldFramework: composer runs with
`selectedServices: []` for now, which strips marker comments from the
freshly-overlaid Next.js base so user-facing output is clean.

Tests:
- services-composer.test.ts: 11 unit tests against synthetic templates
  (empty selection, ordering, syntax variants, missing snippets, missing
  markers, transitive requires, package.json/.env merges, file copies)
- services-composer-nextjs-base.test.ts: end-to-end check that the real
  Next.js base composes cleanly with no services selected

Completes M1 of the service augments plan (PLAN.md).
@Huijiro Huijiro changed the title docs: service augments plan (insertion-marker composition) feat(cli): service augments plan + M1 (Next.js base + composer) May 4, 2026
Huijiro added 17 commits May 4, 2026 10:46
Extract translate() into app/lib/translate.ts and slim the action.
Add 11 markers across translate.ts + home.tsx. Add manifest.json.

Same shape as Next.js (Step 1 of M2).
Extract translate() into server/translate.ts. server.ts retains its role
as Bun.serve entry + Vite proxy but delegates the AI call. Add 11
markers across server/translate.ts + src/App.tsx. Add manifest.json.
Extract translate() into server/utils/translate.ts (Nuxt auto-imports
this). Slim the event handler. Add 11 markers across translate.ts +
app.vue (script + template, mixed comment syntax). Add manifest.json.
Extract translate() into src/lib/server/translate.ts (SvelteKit's
server-only convention). Slim the form action. Add 11 markers across
translate.ts + +page.svelte (script + template, mixed comment syntax).
Add manifest.json.
Extract translate() into src/lib/translate.ts. Slim the API route. Add
11 markers across translate.ts + index.astro. The page file has three
regions (frontmatter, HTML body, bottom <script>); markers use // in
JS regions and <!-- --> in HTML body. Add manifest.json.
Extract translate() into src/translate.ts. Move the inline HTML template
literal out of c.html(`...`) into src/landing.html, loaded with
readFileSync at startup. This unlocks marker-based composition of view
contributions, which can't reach into a JS template literal cleanly.

Slim src/index.ts to import translate() and read the landing file. Add
11 markers across translate.ts + landing.html. Add manifest.json.
Rename services-composer-nextjs-base.test.ts to services-composer-base.test.ts
and parameterize the test loop over each framework with a manifest.

Each framework's test cps the real templates/<fw> tree to a tempdir,
runs the composer with no services, and asserts the expected files are
marker-free and still contain framework-distinguishing landmarks.
…works

Added an optional cached field to the base TranslateResult type so DB
service snippets can mark cached responses without needing inline type
substitution. The field is documented and stays undefined when no
service populates it.

Also updates Remix's home.tsx to type its result state as TranslateResult
instead of an inline shape, so DB's after-result snippet can read
result?.cached without a cast.
Both frameworks have a single server entry that owns API route
registration: server.ts for vite-react, src/index.ts for hono. Add
'imports' and 'routes' markers so services that need to add HTTP routes
(starting with DB's /api/history) can splice in via the existing
composer machinery rather than each shipping their own modification
strategy.

Both base files retain the existing translate route and just gain two
inert marker comments before composition.
A service contributing an 'imports' snippet that uses a binding the base
already pulls from the same module (commonly 'react') would otherwise
land as two separate import statements. The composer now scans the
leading import block of each composable file and folds same-module
named-import statements into a single line.

Default, namespace, and side-effect imports are left alone. Type-only
and value imports stay distinct so semantics aren't silently changed.
Test added covering useState + useEffect collapse with intervening
type-only imports.
First service augment: a SQL database via vanilla drizzle-orm and
@neondatabase/serverless (no @agentuity/postgres / @agentuity/drizzle
dependency). The service:

  * Adds drizzle-orm + @neondatabase/serverless deps and drizzle-kit dev
    dep, plus db:generate/db:migrate/db:push/db:studio scripts.
  * Adds DATABASE_URL to .env.example.
  * Drops a translations schema, drizzle config, and a typed db client
    into framework-idiomatic locations:
      nextjs / astro      src/db/
      remix               app/db/
      vite-react / nuxt   server/db/
      sveltekit           src/lib/server/db/
      hono                src/db/
  * Adds an /api/history route per framework (or for vite-react/hono
    contributes a route handler via the new 'server' composable file).
  * Splices cache-lookup-then-AI logic into the translate() helper:
    pre-AI, query the table for an existing row; on hit, short-circuit
    with cached: true. Post-AI, persist the fresh translation.
  * Splices a History panel after the translate form, with on-mount
    fetch and on-result refetch.

Catalog order is 20; storage will require db at order 50.

Tests:
  * services-catalog.test.ts validates the bundled catalog (unique ids,
    unique orders, ordered ascending, requires references resolve).
  * services-composer-db.test.ts cps each real framework template, runs
    composeServices(['db']), and asserts whole files land at expected
    paths, the translate helper has cache logic, the page has a History
    panel, package.json gained the deps + scripts, and .env.example has
    DATABASE_URL.

  All 32 composer tests pass.
Adds @agentuity/keyvalue. The service persists the user's last selected
language and model in a 'preferences/translate' key, loaded on page
mount and saved after each successful translation. Defaults still
apply when nothing's been saved yet.

  * Each framework gets a /api/preferences (GET/POST) endpoint, except
    vite-react and hono which mount the route in their server file via
    the existing 'server' composable.
  * Page snippets contribute on-mount (load + apply prefs) and
    on-result (save prefs) using framework-idiomatic patterns:
      React frameworks       useEffect
      Nuxt                   onMounted + watch
      SvelteKit              onMount + $effect
      Astro                  module-scope await
      Hono                   IIFE wrapper (no top-level await
                             in inline <script>)
  * Catalog order 10, runs before db.

Adds 'module' marker to vite-react server.ts and hono index.ts so KV
can instantiate the client at module scope rather than per-request.

Tests: services-composer-keyvalue.test.ts (7/7 frameworks pass).
Adds @agentuity/queue. The service contributes a 'Translate later'
button next to the Translate button. Clicking it enqueues a translation
job and adds the message id to a session-local pending-jobs panel. The
demo deliberately stops at enqueue (no worker / status polling) to keep
the queue API surface visible without bringing extra moving parts into
the scaffold.

  * /api/jobs (POST) per framework. vite-react and hono use their
    'server' composable; everyone else gets a dedicated route file.
  * Page contributes inside-form-buttons (the new button) and
    after-form (the jobs panel) plus 'state' for the jobs list.

Catalog order 40, no requires.

Tests: services-composer-queue.test.ts covers all 7 frameworks.
Adds @agentuity/vector. After each translation the source text is
upserted into a 'translations' vector namespace. A 'Similar past
translations' panel under the result fetches up to 5 nearest
neighbors via /api/similar.

  * Translate helper gains 'imports', 'module' (vector client +
    namespace constant), and 'translate-post' (the upsert call).
  * /api/similar (GET ?q=) per framework. vite-react and hono use the
    'server' composable.
  * Page snippet contributes 'state' for the similar list and
    'on-result' to fetch + render after each translation. Panel lives
    in 'after-result'.

Catalog order 30. Astro uses the same vector client across frontmatter
import and bottom <script> via separate instantiation; same for hono.

Tests: services-composer-vector.test.ts covers all 7 frameworks.
Adds @agentuity/storage. The service contributes an 'Export history'
button below the form. Clicking it bundles the DB-backed translation
history into JSON, uploads to an S3-compatible bucket, and reports the
filename + size.

Storage requires DB (declared via manifest.requires=['db']) so the
composer auto-pulls DB when only storage is selected. Both services'
package contributions, env vars, and snippets land in catalog order
(db before storage).

  * Storage client helper at framework-idiomatic locations.
  * /api/export (POST) per framework, server-composed for vite-react
    and hono.
  * Page snippet contributes 'state' (export request state) and
    'after-form' (the export button), placed after the History panel
    contributed by db.

Adds AGENTUITY_BUCKET_* env vars to .env.example.

Tests: services-composer-storage.test.ts asserts both storage and the
auto-pulled db land cleanly across all 7 frameworks.
End-to-end check that selecting every service together (kv + db + vector
+ queue + storage) composes cleanly across all 7 frameworks. Asserts
no markers leak into any output file and that each service's package
deps and env vars land in package.json / .env.example.

This catches snippet conflicts that wouldn't show up in single-service
tests \u2014 e.g., two services contributing colliding identifiers to the
same marker, or a service's snippet body inadvertently containing the
marker syntax of another. Currently 7 tests, all pass.
Adds --services <list> CLI flag and an interactive multi-select prompt
to `agentuity project create`. The chosen services are passed through
to the composer.

Behavior:
  * --services explicit: validates ids loudly against the catalog,
    rejects unknown ids with a helpful list of options for the chosen
    framework.
  * Interactive without flag: shows a multi-select with all services
    available for the chosen framework. Auto-pulls dependencies
    (e.g. selecting 'storage' silently includes 'db') and informs the
    user.
  * Headless without flag: empty selection. No services applied.

resolveSelection (catalog helper) handles transitive requires and
catalog-order normalization, so output is deterministic regardless of
how the user picked.

Cloud-resource provisioning for KV / Queue / Vector is not yet wired
in \u2014 the existing DB and storage prompts still drive cloud
provisioning. Service code lands in either case; users run
`agentuity dev` to wire up KV/Queue/Vector env vars.

Tests:
  * services-resolve-selection.test.ts \u2014 unit-tests resolveSelection
    against the bundled catalog.
  * Composer suite (67 tests) still passes.
@Huijiro Huijiro changed the title feat(cli): service augments plan + M1 (Next.js base + composer) feat(cli): service augments — translate demo with optional DB / KV / Queue / Vector / Storage May 4, 2026
Huijiro added 5 commits May 4, 2026 11:37
Five test files were testing code that no longer exists in v3:

  * test/cmd/dev/backend-proxy.test.ts \u2014 v2 dev-server / Vite proxy
    behavior. The src/cmd/build/vite/vite-asset-server-config.ts module
    they import was removed when v3 dropped the v2 build pipeline.

  * test/cmd/build/vite/public-folder.test.ts \u2014 same root cause as
    backend-proxy.test.ts.

  * test/coder-config.test.ts \u2014 imports src/coder-config.ts (removed
    in v3).

  * test/hub-url.test.ts \u2014 imports src/cmd/coder/hub-url.ts (removed
    in v3).

  * test/cmd/coder/workspace.test.ts \u2014 main PR #1432 expanded this
    file to cover refresh / update / validate-dependencies subcommands
    + setup-script / dependency options on create. None of those landed
    in v3 (the subcommand source files were intentionally removed
    during the merge because they reference @agentuity/core types that
    don't exist in v3 yet). Reverted to the pre-merge version that
    matches v3's create.ts.

After this change: 619 tests pass, 0 fail (was 617 pass, 13 fail). The
removed tests were filed by the test runner as failures every PR
build; this clears that noise so the remaining suite is meaningful.
Refactors runCreateFlow's provisioning section to only prompt for a
database or storage bucket when the user actually opted in \u2014 either
via the service multi-select earlier in the flow or via an explicit
--database / --storage flag. The previous behavior asked 'Create SQL
Database?' and 'Create Storage Bucket?' on every interactive scaffold
regardless of intent.

Selection rules for each resource:
  * Flag set to 'skip'        \u2192 skip (overrides service selection)
  * Flag set to anything else \u2192 prompt
  * Service in selection      \u2192 prompt
  * Otherwise                 \u2192 skip

Other improvements ported from main:
  * Single-resource prompt (no menu) with 'Create New' implicit when
    no existing resources exist.
  * Suggested names via suggestDatabaseName / suggestBucketName from
    random-name.ts, shown as placeholders.
  * Custom-domain prompt now stands alone (not gated by db/storage
    selection) since domains are a deployment concern, not a service.
  * Resource-list fetch + flag-name validation only run when we'll
    actually use them.

Decision logic extracted into provisioning-decisions.ts (resolveFlagAction,
shouldPromptForResource, flagRequiresProvisioning) so the gating can be
unit-tested without standing up a full prompt/auth harness. 12 new
tests; 631 total in the cli package, all pass.
Two source files came in from main during the v3 merge with bare
relative imports (no extension). Bun resolves them fine; Node ESM
does not, and the dist build emits .js → bare specifier without an
extension, which breaks at runtime.

  * src/composite-logger.ts:
      from './errors' → from './errors.ts'

  * src/cmd/project/detect-existing.ts:
      from '../build/detect' → from '../build/detect/index.ts'
    (build/detect is a directory; explicit /index.ts since Node ESM
    doesn't do directory-resolution.)

Verified by running the built dist under `node packages/cli/bin/cli.js`
locally — auth whoami now succeeds. Unblocks all five CI failures on
PR #1445 that share the message:

    ERR_MODULE_NOT_FOUND: Cannot find module '.../dist/errors'
    imported from .../dist/composite-logger.js

(Service Client Smoke Tests is the only remaining failure and is an
expected environmental failure, unrelated.)
Each service-client smoke test now runs with continue-on-error so a
single failure (e.g. db Unauthorized when secrets aren't set on a
fork build) doesn't mask the rest of the suite.

A final 'Service smoke results' step prints a single outcome table for
all nine services and fails the job if any of the steps failed, so the
job conclusion stays correct \u2014 only the early-abort behavior changes.

Output looks like:

  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
  \u2502 Service     \u2502 Outcome \u2502
  \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524
  \u2502 KEYVALUE    \u2502 success \u2502
  \u2502 VECTOR      \u2502 success \u2502
  ...
  \u2502 DB          \u2502 failure \u2502
  ...
  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
…s resources

Six of the ten service smoke tests created cloud resources without\nguaranteed cleanup. A failure mid-test would leave behind real billable\nartifacts (sandboxes, vector namespaces, webhooks, tasks, email\naddresses, keyvalue keys). Now that the workflow runs every smoke step\neven when an earlier step fails (continue-on-error), this leakage is\nmuch more likely to bite us in CI.

For each affected test, wrap the body in try/finally and best-effort\ndelete in the finally block. Failures inside cleanup are logged and\nswallowed \u2014 the test's outcome stays driven by the body, not the\ncleanup.

Specifics:

  * email     \u2192 collect created address ids, deleteAddress(id) on each\n  * keyvalue  \u2192 needsCleanup flag, delete the test key on failure\n  * sandbox   \u2192 createdSandboxId tracker, client.destroy(id) on failure\n                (sandboxes are the most expensive resource here)\n  * task      \u2192 collect ids, softDelete(id) on each\n  * vector    \u2192 needsCleanup flag, deleteNamespace(name) at the end\n                (single call drops all upserted documents)\n  * webhook   \u2192 collect ids, delete(id) on each\n                (destinations clean up transitively with the webhook)

The four already-clean tests (db is read-only; queue, schedule, storage\nalready have try/finally) are untouched.

Verified: typecheck clean across all six test apps; cli unit tests\nunchanged at 631/0.
Database names in the catalyst service can't contain hyphens, so the
fallback default could never resolve to a real database. Update to a
valid identifier so a developer running the smoke test without
AGENTUITY_DB_DATABASE set gets a closer-to-real failure (auth or
not-found on a valid name) instead of a name-validation rejection.
@Huijiro Huijiro merged commit 94d4d26 into v3 May 5, 2026
14 of 16 checks passed
@Huijiro Huijiro deleted the cli/service-augments-plan branch May 5, 2026 15:03
Huijiro added a commit that referenced this pull request May 5, 2026
- Delete PLAN.md (Service Augments plan — fully implemented in #1445).
- packages/cli/src/cmd/node-compat/crypto.ts: replace dead reference to
  PLAN.md §8 with the actual cache-invalidation note inline.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant