flowviant 0.92.1 → 0.93.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/lib/agentPlan.mjs +53 -1
- package/bin/lib/prompts.mjs +9 -1
- package/bin/lib/work.mjs +26 -0
- package/package.json +1 -1
package/bin/lib/agentPlan.mjs
CHANGED
|
@@ -157,6 +157,35 @@ export function parseProposal(text) {
|
|
|
157
157
|
};
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
/**
|
|
161
|
+
* The running account, off whichever shape the turn ended with — `{ progress }`
|
|
162
|
+
* or nothing at all.
|
|
163
|
+
*
|
|
164
|
+
* A SPREAD RATHER THAN A FIELD, so an absent account produces no key on the
|
|
165
|
+
* result and therefore no key on the settle body. That is the whole contract
|
|
166
|
+
* with the server: absence means KEEP the last account, and an empty string
|
|
167
|
+
* sent instead would be indistinguishable from an agent saying the branch now
|
|
168
|
+
* amounts to nothing.
|
|
169
|
+
*
|
|
170
|
+
* AN ABSURDITY BOUND HERE, NOT THE DISPLAY CAP (corrected 2026-09-22, in
|
|
171
|
+
* review). This sliced to the wire's own 1000 first, which quietly INVERTED the
|
|
172
|
+
* order the caller's own comment claims to keep: `envScrub` replaces EXACT
|
|
173
|
+
* values, so handing it a paragraph already cut at 1000 hands it a credential
|
|
174
|
+
* cut in half — it matches nothing and the surviving prefix ships. The scrub is
|
|
175
|
+
* the only thing standing between a model that pasted a secret into its own
|
|
176
|
+
* summary and the wire, and a cap must never run ahead of it. So this is the
|
|
177
|
+
* same absurdity bound `summary` takes one line up (8000): enough that nothing
|
|
178
|
+
* a model writes reaches the caller unbounded, far enough above the 1000 the
|
|
179
|
+
* wire cuts to that the scrub always sees whole values. `work.mjs` scrubs and
|
|
180
|
+
* THEN cuts to 1000, and the server clamps again because the wire never trusts
|
|
181
|
+
* a machine to have clamped.
|
|
182
|
+
*/
|
|
183
|
+
const MAX_PROGRESS = 8000;
|
|
184
|
+
const progressOf = (v) => {
|
|
185
|
+
const t = typeof v.progress === 'string' ? v.progress.trim() : '';
|
|
186
|
+
return t ? { progress: t.slice(0, MAX_PROGRESS) } : {};
|
|
187
|
+
};
|
|
188
|
+
|
|
160
189
|
/**
|
|
161
190
|
* READING AN AGENT'S ANSWER at the end of a turn.
|
|
162
191
|
*
|
|
@@ -170,6 +199,28 @@ export function parseProposal(text) {
|
|
|
170
199
|
* `nothing`, which sends the agent to Stuck. Optimistic status from a machine
|
|
171
200
|
* that quit is the one lie this board cannot afford, so anything ambiguous ends
|
|
172
201
|
* up here rather than being read as success.
|
|
202
|
+
*
|
|
203
|
+
* ── AND IT CARRIES THE AGENT'S RUNNING ACCOUNT OF ITSELF (2026-09-22) ─────
|
|
204
|
+
*
|
|
205
|
+
* The owner: "we should add a brief summary of what the agent has done overall
|
|
206
|
+
* at the top that updates." `progress` is one more key on the SAME object —
|
|
207
|
+
* two or three cumulative sentences about the whole branch, rewritten fresh
|
|
208
|
+
* every turn — and it is read here because this is where everything the agent
|
|
209
|
+
* SAYS is already read. Nothing derives it: this file parses, it does not
|
|
210
|
+
* summarise, and a daemon that read the turn log and wrote its own paragraph
|
|
211
|
+
* would be the second brain the product forbids.
|
|
212
|
+
*
|
|
213
|
+
* ON BOTH SHAPES, because a turn that stopped to ask has still done work — an
|
|
214
|
+
* agent that built three quarters of a feature and then needed a decision is
|
|
215
|
+
* exactly the run whose account a person wants. It is NOT read off an
|
|
216
|
+
* unparseable turn, and that is not an omission: there is no object to read it
|
|
217
|
+
* from, and a `nothing` outcome means the CLI never got as far as saying
|
|
218
|
+
* anything about itself.
|
|
219
|
+
*
|
|
220
|
+
* MISSING IS MISSING. An older prompt, a resumed conversation that never saw
|
|
221
|
+
* the key, a model that dropped it — all of them leave it absent, and the
|
|
222
|
+
* caller omits the field rather than sending an empty string, so the server
|
|
223
|
+
* keeps the last account that was true instead of blanking the head.
|
|
173
224
|
*/
|
|
174
225
|
export function parseTurnResult(text) {
|
|
175
226
|
for (const v of candidateObjects(String(text ?? ''))) {
|
|
@@ -179,12 +230,13 @@ export function parseTurnResult(text) {
|
|
|
179
230
|
// parks an agent with nothing to reply to. Treated as `nothing`, which
|
|
180
231
|
// at least says truthfully that the machine went quiet.
|
|
181
232
|
if (!question) continue;
|
|
182
|
-
return { outcome: 'question', answer: question.slice(0, 8000) };
|
|
233
|
+
return { outcome: 'question', answer: question.slice(0, 8000), ...progressOf(v) };
|
|
183
234
|
}
|
|
184
235
|
if (v.status === 'delivered') {
|
|
185
236
|
return {
|
|
186
237
|
outcome: 'delivered',
|
|
187
238
|
answer: (typeof v.summary === 'string' ? v.summary : '').slice(0, 8000),
|
|
239
|
+
...progressOf(v),
|
|
188
240
|
raised: Array.isArray(v.raised)
|
|
189
241
|
? v.raised
|
|
190
242
|
.filter((r) => r && typeof r.title === 'string' && r.title.trim())
|
package/bin/lib/prompts.mjs
CHANGED
|
@@ -777,6 +777,7 @@ END YOUR TURN WITH ONE JSON OBJECT AND NOTHING AFTER IT, in a \`\`\`json fence:
|
|
|
777
777
|
{
|
|
778
778
|
"status": "delivered",
|
|
779
779
|
"summary": "one or two sentences on what you actually changed",
|
|
780
|
+
"progress": "two or three sentences on what you have done on this branch SO FAR, across every card",
|
|
780
781
|
"raised": [{ "title": "short title", "brief": "what is wrong and what you did" }]
|
|
781
782
|
}
|
|
782
783
|
\`\`\`
|
|
@@ -786,13 +787,20 @@ or, if you are stopping to ask:
|
|
|
786
787
|
\`\`\`json
|
|
787
788
|
{
|
|
788
789
|
"status": "blocked",
|
|
790
|
+
"progress": "two or three sentences on what you have done on this branch SO FAR, across every card",
|
|
789
791
|
"question": "the specific thing you need decided, in one or two sentences"
|
|
790
792
|
}
|
|
791
793
|
\`\`\`
|
|
792
794
|
|
|
793
795
|
"raised" is optional and only for work you did that was NOT this card. Do not
|
|
794
796
|
list the card itself there. Do not put commit shas in the summary — they are
|
|
795
|
-
read from git
|
|
797
|
+
read from git.
|
|
798
|
+
|
|
799
|
+
"progress" is REQUIRED on both shapes. It is the running account a person reads
|
|
800
|
+
at the top of this run, and it REPLACES the previous one whole — so write it
|
|
801
|
+
fresh every turn, covering everything you have done on this branch so far and
|
|
802
|
+
not only this card. Past tense, plain sentences, no commit shas and no card ids.
|
|
803
|
+
"summary" is about this one card; "progress" is about the branch.`;
|
|
796
804
|
|
|
797
805
|
/**
|
|
798
806
|
* The turn itself.
|
package/bin/lib/work.mjs
CHANGED
|
@@ -5062,6 +5062,32 @@ export function createWorkManager({
|
|
|
5062
5062
|
...(commits.length ? { commits } : {}),
|
|
5063
5063
|
...(res.raised?.length ? { raised: res.raised } : {}),
|
|
5064
5064
|
...(usage ? { usage } : {}),
|
|
5065
|
+
/**
|
|
5066
|
+
* THE AGENT'S RUNNING ACCOUNT OF THIS BRANCH (2026-09-22).
|
|
5067
|
+
*
|
|
5068
|
+
* The owner: "we should add a brief summary of what the agent has done
|
|
5069
|
+
* overall at the top that updates." A RELAY — the agent wrote it in its
|
|
5070
|
+
* own final JSON object and nothing here composes, narrows or infers
|
|
5071
|
+
* one. It rides only this settle, which is the one that follows a
|
|
5072
|
+
* PARSED result: the two `nothing` settles above it come from a turn
|
|
5073
|
+
* that declared no outcome at all, so there is no account to carry and
|
|
5074
|
+
* inventing one would be the machine speaking for the agent.
|
|
5075
|
+
*
|
|
5076
|
+
* SCRUBBED BEFORE IT IS CUT, the order that matters and the one the
|
|
5077
|
+
* check's output lane learned the expensive way: `envScrub` replaces
|
|
5078
|
+
* EXACT values, so a paragraph capped first hands the scrub a
|
|
5079
|
+
* credential already cut in half — it matches nothing and the surviving
|
|
5080
|
+
* prefix ships. `parseTurnResult` trims it and bounds it for absurdity
|
|
5081
|
+
* at 8000, DELIBERATELY above the 1000 below, so this slice is the
|
|
5082
|
+
* first one a value of any interest meets and the scrub has already
|
|
5083
|
+
* run when it does. The first cut of this feature bounded the parser at
|
|
5084
|
+
* 1000 as well, which read identically and quietly put the cap first.
|
|
5085
|
+
*
|
|
5086
|
+
* OMITTED WHEN THE TURN DID NOT WRITE ONE, never sent empty. Absence is
|
|
5087
|
+
* the server's signal to KEEP the last account that was true; an empty
|
|
5088
|
+
* string would blank the head because a model dropped a key.
|
|
5089
|
+
*/
|
|
5090
|
+
...(res.progress ? { progress: envScrub(res.progress).slice(0, 1000) } : {}),
|
|
5065
5091
|
branch,
|
|
5066
5092
|
worktree: wt,
|
|
5067
5093
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flowviant",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.93.0",
|
|
4
4
|
"description": "Run your own coding CLIs as build agents for Flowviant \u2014 Claude Code, Codex or Antigravity, on your own credentials. Holds your sessions, keeps a worktree per tab, and ships branches on your word.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|