feat(cli): service augments — translate demo with optional DB / KV / Queue / Vector / Storage#1445
feat(cli): service augments — translate demo with optional DB / KV / Queue / Vector / Storage#1445
Conversation
|
The latest Agentuity deployment details.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Comment |
📦 Canary Packages Publishedversion: PackagesInstallAdd to your {
"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 |
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).
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.
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.
- 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.
Adds a service-augment system to
agentuity project create. After framework scaffolding + the AI translation demo, the user picks zero or more ofdb,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.translate()helper, 7 view-side in the page, plusimports/module/routesin the server entry for vite-react and hono).//,{/* */}, or<!-- -->).keyvalue (10) → db (20) → vector (30) → queue (40) → storage (50). Storage requires DB.useEffectsnippets 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 amanifest.jsondeclaring composable files + per-marker syntax. Hono additionally moved its inline HTML template literal intosrc/landing.htmlso view markers can sit in real comments.src/lib/translate.tssrc/app/api/translate/route.tssrc/app/page.tsxapp/lib/translate.tsapp/routes/api.translate.tsapp/routes/home.tsxserver/translate.tsserver.ts(delegates)src/App.tsxserver/utils/translate.tsserver/api/translate.post.tsapp.vuesrc/lib/server/translate.tssrc/routes/+page.server.tssrc/routes/+page.sveltesrc/lib/translate.tssrc/pages/api/translate.tssrc/pages/index.astrosrc/translate.tssrc/index.tssrc/landing.htmlServices
drizzle-orm,@neondatabase/serverless,drizzle-kit)db:generate/migrate/push/studioscripts andDATABASE_URLto.env.example.@agentuity/keyvalue)@agentuity/queue)@agentuity/vector)@agentuity/storage, requiresdb)CLI integration
agentuity project create --services db,keyvaluefor headless use; unknown ids fail loudly with a helpful list.requires(selectingstoragesilently includesdb).@agentuity/postgres/@agentuity/drizzledeprecation: the wrapper packages were marked deprecated earlier in this branch; the DB augment uses vanilladrizzle-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 devto 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:
services-composer.test.ts): 12 tests covering empty selection, ordering, all 3 marker syntaxes, missing snippets, missing markers, transitiverequires, package.json + .env merges, file copies, import merging.services-catalog.test.ts,services-resolve-selection.test.ts): 12 tests validating the bundled catalog and theresolveSelectionhelper used by the CLI flag.services-composer-base.test.ts): 7 frameworks × 1 test each, asserting marker strip with no services produces clean output.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.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:
cached?: booleanfield,servercomposable for vite-react/hono, import merger)--servicesflag wiring