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
an optional deterministic ALDashboard lint that always passes `include_llm=False`.
91
+
An error-severity diagnostic blocks acceptance; warnings and infos are reported
92
+
to both the developer and the agent without blocking. The patch API, the agent's
93
+
tools and the editor's unsaved-source check all call it, so agent editing can
94
+
never acquire a weaker standard than ordinary editing.
70
95
71
96
`source_document.py`retains the original text and exact document offsets as the
72
97
authoritative representation. Parsed mappings and top-level property ranges are
@@ -92,6 +117,77 @@ token into bootstrap state, and the centralized client sends it on every write.
92
117
No editor route is CSRF-exempt and no wildcard CORS policy is installed. Any
93
118
separate API-key integration remains outside the browser editor route family.
94
119
120
+
The editing assistant is on unless `weaver: assistant: False` turns it off. It
121
+
does not depend on the source-patch API: the agent compiles its own range
122
+
operations in process and never calls that endpoint. What it does need is a
123
+
language model, so the page bootstrap carries an `assistant_status` saying
124
+
whether one is reachable — ALToolbox leaves its client as `None` when it finds
125
+
no credentials, which is the signal used rather than a guess at config key
126
+
names. When no model is configured the panel is still offered but explains what
127
+
is missing instead of showing a composer that would fail on submit, and the
128
+
endpoints answer 503 rather than pretending the feature does not exist.
129
+
130
+
Its fundamental invariant is that the LLM proposes semantic
131
+
actions, while Weaver produces source, validates source and controls
132
+
persistence. The browser sends a working-source snapshot — the saved file with
133
+
every unsaved buffer folded in, built by `editor_validation_source.js` — and the
134
+
server binds the resulting session to one owner, project and filename. No tool
135
+
argument can change that target; unknown properties in a tool call are a schema
136
+
error precisely so a model cannot smuggle in a `project` or `filename`.
137
+
138
+
Each turn runs a bounded server-side loop: the model returns one JSON action,
139
+
`editor_agent_tools.py`compiles it into an exact source replacement against an
140
+
in-memory candidate, and the whole candidate is validated before the mutation is
141
+
kept. Rejected mutations return structured diagnostics to the model and leave the
142
+
candidate at its last valid revision, so candidate validity is monotonic. Only
143
+
low-risk tools and a small set of deliberately implemented medium-risk ones are
144
+
registered; blocks that `source_document.py` marks unsupported are readable but
145
+
never rewritten. Runtime tools require `WEAVER_ENABLE_RUNTIME_INSPECTOR`, wrap
146
+
the existing allowlisted `al_weaver.inspect_*` actions, and label their results
147
+
`observed_runtime`so the model cannot present a static prediction — or a seeded
148
+
scenario fixture — as observed behaviour.
149
+
150
+
Two deterministic operations are worth calling out because neither is safe as
151
+
free-text editing. `editor_agent_repair.py` fixes the two blocking diagnostics
152
+
that dominate real files — a question block with no `id`, and two blocks sharing
153
+
one — by patching exact ranges and re-validating; a repair pass is kept only if
154
+
it leaves strictly fewer blocking diagnostics. It is offered at session creation
155
+
behind an explicit `auto_heal` flag, the repairs become part of the candidate so
156
+
they appear in the diff, and Reset returns to the repaired baseline rather than
157
+
to source the validator would reject. `editor_agent_rename.py` renames variables
158
+
by classifying every appearance of a name: a reference it recognises is
159
+
rewritten, prose is left alone and reported, and anything it cannot tell apart
160
+
from a reference — a name inside a string, a call, a longer path built on the
161
+
name, an `objects:` declaration that would become an attribute path — refuses
162
+
the whole batch. `suggest_object_conversion` maps a flat family such as
163
+
`persons1_name`onto `persons[0].name.first` using the same table the Weaver
164
+
uses for PDF fields, skipping targets that are display expressions or that would
165
+
collapse two variables into one.
166
+
167
+
A turn outlives any HTTP request — the editor's own client gives up first, and
168
+
nginx closes an idle upstream read at sixty seconds by default — so it runs as
169
+
the named `weaver_editor_agent_turn_task` in Docassemble's Celery worker,
170
+
alongside project generation, and never in an in-process thread. Starting a turn
171
+
returns 202 immediately. The loop publishes each event to a short-lived,
172
+
owner-scoped progress record as it happens, and the finished turn's result lands
173
+
there too, because that is the only place the browser can still read it. That
174
+
record has its own Redis key rather than living in the session, because Stop and
175
+
the polling reads touch the session concurrently and would otherwise clobber the
176
+
turn's own writes. A record nothing has written to for two minutes is treated as
177
+
abandoned rather than believed forever.
178
+
179
+
The assistant is for small, discrete edits, so a chat is capped at ten requests
180
+
and counts down toward a prompt to apply and start a fresh one; a long
181
+
conversation makes each turn slower and vaguer and its candidate harder to
182
+
review as a single diff.
183
+
184
+
No agent step writes to the Playground. Apply re-checks that the saved file has
185
+
not moved on, re-validates the candidate, and hands the source back to the
186
+
browser as unsaved editor state that stays dirty against the revision actually on
187
+
disk; the existing Save path is what persists it. Sessions live in owner-scoped
188
+
expiring Redis records, and server logs record tool names, revisions and
189
+
validator counts but never interview text, prompts or runtime variable values.
190
+
95
191
Unsaved interview edits are tracked by `editor_dirty_state.js` per filename and
96
192
block ID, with separate source-dirty and pending-command state. Each loaded file
97
193
also has a deep-cloned saved model. Discard restores that model, while a
@@ -172,6 +268,14 @@ kinds of interviews that the Weaver can produce.
172
268
- `draggable_table.py`is used by the Weaver frontend to allow rearranging long lists of fields
173
269
- `field_grouping.py`is a copy of some features from [FormyFyxer](https://github.com/SuffolkLITLab/FormFyxer) that power the "I'm feeling lucky" button (should be deprecated)
174
270
- `generator_constants.py`contains several lists of rules for how to transform PDF field names like `users_name_full` into Docassemble objects like `users[0].name`, as well as indicating reserved DOCX variable names that are handled by questions in the AssemblyLine's question library
271
+
- `api_editor.py`is HTTP orchestration for the graphical editor; the editing business logic lives in the modules below
272
+
- `editor_agent_validation.py`is the one whole-candidate validator, plus the diagnostic normalisation the editor's error drawer consumes
273
+
- `editor_agent_models.py`holds the agent session, candidate, turn and tool-result records and their owner-scoped Redis persistence
274
+
- `editor_agent_tools.py`is the semantic tool registry — the security and accuracy boundary for everything the model can do
275
+
- `editor_agent_repair.py`deterministically fixes missing and duplicate block ids so a mechanical problem does not stop the assistant from starting
276
+
- `editor_agent_rename.py`classifies every appearance of a variable name and renames only the references it can positively recognise
277
+
- `editor_agent_context.py`assembles the compact interview context a turn is given, fencing untrusted reference material
278
+
- `editor_agent.py`runs the bounded agent loop and the explicit final validation pass
0 commit comments