feat(builder): conversational AI intent builder shell - #6610
Merged
Conversation
Add `resources-builder`, a standalone Harmonia shell at /services/web/builder/ where you describe an application in plain language and one button turns the conversation into a running app. It adds no backend: the whole feature is a frontend orchestration over endpoints that already ship (the intent engine's agent/parse/generate, the workspace, the publisher, the health and problems feeds), reusing the shared application-core runtime by absolute URL. The loop is chat -> agent -> re-validate the proposal client-side through /parse -> auto-apply -> redraw the canvas. The re-validation is load-bearing rather than defensive: the agent answers 200 even when its proposal still fails validation (the server's two repair rounds were exhausted), signalling it only as trailing prose in the reply, so an invalid proposal is surfaced as issues and never reaches the buffer. Project and file management stay invisible. The project id is a slug of the intent's name, created lazily on the first accepted proposal and never renamed; every accepted proposal is auto-saved, so a reload restores the app from disk rather than from browser memory. Publish runs a staged pipeline: save, snapshot the Problems feed, generate the models, replay the code generations, publish, then poll healthcheck and diff Problems for this project. That diff is the only honest "published clean" signal - publishing is synchronous but says nothing about what the synchronizers made of the artefacts, so a client-Java compile error or a failed CSVIM seed surfaces there and nowhere else. The "try it here" links are discovered from the platform-shells and application-perspectives services, never assembled from a guessed gen-folder convention. The mxGraph rendering is extracted from the Intent Editor's controller into the framework-free IntentDiagrams module and shared, not copied - the editor keeps rendering through it (IntentEditorLoadsIT covers that) and the shell loads the same file by URL. IntentBuilderShellIT drives the journey against a local HTTP stub of the Anthropic upstream via DIRIGIBLE_INTENT_AI_BASE_URL, so it needs no API key and no network; a @tag("smoke") bootstrap check runs on every PR. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nt is unavailable before the first message
Add `GET /services/ide/intent/agent/status` -> `{configured}`, backed by
`IntentAgentService.isConfigured()`. It reads configuration only and
never calls the model, which is the whole point: the Builder shell
probes it on load, so an instance with no API key says so before the
user types instead of letting the first message fail with 412.
The alternative the plan proposed - firing a throwaway /agent turn on
load - would have burned a real Anthropic round-trip on every page load
of a working instance. This endpoint is the cheap way to get the banner
up front.
The key is read live rather than cached, so a key set after start-up is
picked up; an unreachable status endpoint is treated as configured, so a
probe failure never puts a false "not configured" banner over a working
shell.
Covered by IntentEngineIT (200 + configured=false in the key-less test
environment, network-free, so it runs on every PR) and by two
IntentBuilderShellIT assertions: the banner appears with no key, and
does not appear when the assistant is configured.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
delchev
added a commit
that referenced
this pull request
Aug 7, 2026
Master gained the Builder shell (#6610), which registers itself on the Home launchpad exactly where this branch registers Monitoring - so both sides added an entry to the same two constants in home.js. Resolved additively, keeping both shells. SECONDARY stays ordered least-technical-first per its own comment: the two operations tools (Admin, Monitoring) then the two building tools (Builder, Workbench). The Maven wiring in components/pom.xml and group-ui merged cleanly and was verified to carry both modules.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A new standalone Harmonia shell — a conversational AI intent builder. You describe the application you want; an
app.intentis created and evolved underneath; a canvas visualises the entities, processes and glue live; one button turns the conversation into a running application, ending on a success state that links you to the shells where you can try it.Served at
/services/web/builder/(shell idbuilder),.access-gated toADMINISTRATOR/DEVELOPERlike the intent endpoints it drives.Almost no new backend
The feature is a frontend orchestration over endpoints that already ship — the intent engine's
agent/parse/generate, the workspace, the publisher, and the health + problems feeds — reusing the sharedapplication-coreruntime (theme, notifications, branding, i18n) by absolute URL, with no per-shell copies. It is one screen, so there is deliberately no Pinecone router.The single addition is
GET /services/ide/intent/agent/status→{configured}(configuration-only, never an upstream call). The shell probes it on load so an instance with no API key says so before the user types, instead of letting the first message fail with 412. The plan proposed firing a throwaway/agentturn for this, which would have burned a real Anthropic round-trip on every page load of a working instance; the endpoint is the cheap way to get the banner up front.The conversation loop
chat →
POST /services/ide/intent/agent→ re-validate the proposal client-side through/parse→ auto-apply → redraw.The re-validation is load-bearing, not belt-and-braces: the agent returns 200 even when its proposal still fails validation (the server's two repair rounds were exhausted), signalling it only as trailing prose in
reply. An invalid proposal is rendered as issues and never reaches the buffer. There is no diff/Accept step — a valid proposal auto-applies and the assistant's own text is the change narration; the raw YAML stays available read-only in a drawer, and the Intent Editor in the IDE remains the authoring surface.Hidden persistence
The project id is a slug of the intent's
name, created lazily on the first accepted proposal and never renamed (a rename would mean delete + recreate + republish). Every accepted proposal is auto-saved, so reloading restores the app from disk, not from browser memory. An app switcher lists the workspace projects carrying a rootapp.intent; chat history is per-projectlocalStorage(the agent endpoint is stateless).The one button
save → Problems baseline → generate models → replay codeGenerations → publish → healthcheck poll + Problems diff, each step ticking green.The Problems diff is the only honest "published clean" signal: publishing is synchronous but reports nothing about what the synchronizers then made of the artefacts, so a client-Java compile error or a failed CSVIM seed surfaces there and nowhere else. Without it a broken app would be reported as a success. The success panel's "try it here" links are discovered (
platform-shells+ the app's own perspective path fromapplication-perspectives) rather than assembled from a guessedgen/<model>convention that would 404 the moment a template changed its layout.Shared diagram renderer (the only change to shipped code)
The Intent Editor's ~310 lines of mxGraph rendering are extracted from its AngularJS controller into a framework-free
window.IntentDiagrams.render(model, host)/.dispose(host)(editor-intent/js/intent-diagrams.js). Mechanical extraction only — the editor renders through it unchanged (editor.jsdrops from 824 to 491 lines) and the shell loads the same file by URL.IntentEditorLoadsITguards it.Gotchas this paid for
Each of these was found by the integration test, not by review:
<i x-h-lucide>. The plugin replaces the<i>with the rendered svg, so a binding would be lost — it throws instead, and the uncaught throw aborts Alpine's walk over everything below it (the toolbar rendered; the entire split pane did not). Use an<svg x-h-lucide>placeholder.304, andresponse.okis 2xx-only — so a naive!response.okthrow made the second save fail while the first succeeded.Tests
IntentBuilderShellITdrives the journey against a local HTTP stub of the Anthropic upstream (DIRIGIBLE_INTENT_AI_BASE_URL, the same overrideIntentAgentServiceTestuses in-process), so it needs no API key and no network:@Tag("smoke")— the shell bootstraps (stores + renderer registered, first-run surface renders). Runs on every PR; this is the regression class services-level tests cannot catch, where every endpoint stays green while the page is dead..modelin the workspace, the project in the registry), so it stays honest if the success panel is ever reworked.Verified locally:
IntentBuilderShellIT(both) green,IntentEditorLoadsITgreen,formatter:validateBUILD SUCCESS, full reactor build SUCCESS, unit suite 1483 tests / 0 failures (the 5 errors areFtpRepositoryTest+DirigibleApplicationTestBindException: Address already in usefrom another local instance holding the ports).Deliberately not in v1
No raw YAML editing (read-only drawer), no diff/Accept, no server-side conversation persistence, and no multi-model (
uses:) orchestration.🤖 Generated with Claude Code