You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add a dev-mode endpoint that lets an external tool drive a component's actions headlessly — create a session, render a page, enumerate its invokable actions, and invoke one by name — returning the resulting HTML. This closes the one remaining gap in the agent/tool dev loop: the exercise → observe half.
Motivation
The dev endpoints so far cover a lot of the loop well:
/ng/dev/eval — run code in the live JVM (great for inspecting state).
/ng/dev/problems — read the runtime binding-error boxes as data.
/ng/dev/log, plus the Parslips editor-side /validate and /elementApi.
But a tool still cannot click. Component actions resolve by session-scoped, stateful element URLs (/wo/…/0.9.7.1.5), so curl can verify a direct route or a fresh render, but not a flow — a submit, a popup switch, an Ajax toggle. From a recent road test of an ng-objects app:
I can't click. This is the one big gap. Component actions live behind stateful, session-scoped element URLs, so curl can verify direct routes and fresh renders but not flows — I shipped the Ajax toggle, the popup switching, and the deep-search buttons verified only by template validation and reading the framework source. Every "give it one click in the browser" I asked of you today was this gap talking.
Since we own the request loop, we can play the browser without pulling in Selenium/WebDriver.
Proposed shape
A small state machine an agent can drive, mirroring the /ng/dev/* family (dev-mode-only; the parts that mutate app state should be loopback-gated like /eval):
Start / render — create (or reuse) a session, render a named page (or a direct action), return the HTML plus a list of the invokable elements on it: each with its element ID, the action binding's keypath (e.g. action = deleteItem), and enough to name it for a follow-up call.
Invoke — invoke one of those actions by name/ID within the session, run the action phase, and return the resulting page's HTML and its fresh action list — so the tool can chain clicks (open a page → click a tab → submit a form).
Rough surface (names TBD, aligned with the existing /ng/dev/* shapes and the sibling wonder-slim .woa/* mounts):
POST /ng/dev/render?page=SomePage -> { session, html, actions:[{id, name, keypath}] }
POST /ng/dev/invoke?session=…&action=… -> { html, actions:[…] } # run the action, return the next page
JSON envelope for the action list; the HTML as the body or a field. The session handle threads state across calls so a flow is a sequence of invokes.
Design notes / open questions
Session + element-ID model. The action URL encodes a component tree path bound to a session's page cache. The endpoint needs to take the same context WO/ng builds during a normal request, enumerate the action-bearing elements (they're already discoverable during appendToResponse / invokeAction traversal), and expose stable handles. Decide whether to reuse real element IDs or assign friendlier per-render names.
Form values. A realistic "click submit" needs to set form field values first. The invoke call should accept a map of form values to apply before running the action phase (take-values → invoke-action → append).
Shared engine, two mounts. Like eval/problems: the driving logic belongs in a shared place (ng-core or an ng-appserver dev module) with thin route adapters in ng-objects (/ng/dev/…) and wonder-slim/ERExtensions (…/App.woa/…), so both runtimes behave identically. (wonder-slim's is the harder case — the WO request loop is less ours than ng's.)
In: render-a-page-and-list-actions, invoke-an-action-with-optional-form-values, session threading, the JSON envelope, dev-mode + loopback gating. ng first; wonder-slim parity to follow.
Out (for now): JS execution / a real DOM, Ajax responses that a browser would apply client-side (return the server's response and let the caller reason about it), auth flows.
Context
Part of the app-side dev-endpoint family (/eval, /problems, /log) driven by the parslips-dev-loop Claude skill. The road test that produced this: /eval + /problems + /elementApi landed and verified against a real production code path; this is the explicitly-deferred "#2", the next step.
Summary
Add a dev-mode endpoint that lets an external tool drive a component's actions headlessly — create a session, render a page, enumerate its invokable actions, and invoke one by name — returning the resulting HTML. This closes the one remaining gap in the agent/tool dev loop: the exercise → observe half.
Motivation
The dev endpoints so far cover a lot of the loop well:
/ng/dev/eval— run code in the live JVM (great for inspecting state)./ng/dev/problems— read the runtime binding-error boxes as data./ng/dev/log, plus the Parslips editor-side/validateand/elementApi.But a tool still cannot click. Component actions resolve by session-scoped, stateful element URLs (
/wo/…/0.9.7.1.5), socurlcan verify a direct route or a fresh render, but not a flow — a submit, a popup switch, an Ajax toggle. From a recent road test of an ng-objects app:Since we own the request loop, we can play the browser without pulling in Selenium/WebDriver.
Proposed shape
A small state machine an agent can drive, mirroring the
/ng/dev/*family (dev-mode-only; the parts that mutate app state should be loopback-gated like/eval):action = deleteItem), and enough to name it for a follow-up call.Rough surface (names TBD, aligned with the existing
/ng/dev/*shapes and the sibling wonder-slim.woa/*mounts):JSON envelope for the action list; the HTML as the body or a field. The session handle threads state across calls so a flow is a sequence of
invokes.Design notes / open questions
appendToResponse/invokeActiontraversal), and expose stable handles. Decide whether to reuse real element IDs or assign friendlier per-render names.invokecall should accept a map of form values to apply before running the action phase (take-values → invoke-action → append).eval/problems: the driving logic belongs in a shared place (ng-core or an ng-appserver dev module) with thin route adapters in ng-objects (/ng/dev/…) and wonder-slim/ERExtensions (…/App.woa/…), so both runtimes behave identically. (wonder-slim's is the harder case — the WO request loop is less ours than ng's.)/problemsentries that are directly actionable ("here's the component and line") instead of "now grep for it".Scope
Context
Part of the app-side dev-endpoint family (
/eval,/problems,/log) driven by theparslips-dev-loopClaude skill. The road test that produced this:/eval+/problems+/elementApilanded and verified against a real production code path; this is the explicitly-deferred "#2", the next step.