flowviant 0.62.0 → 0.63.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/devResolve.mjs +13 -1
- package/bin/lib/work.mjs +65 -0
- package/package.json +1 -1
package/bin/lib/devResolve.mjs
CHANGED
|
@@ -115,7 +115,7 @@ export function pickCommand(text) {
|
|
|
115
115
|
* the caller's only job with a failure is to relay it, and an exception at this
|
|
116
116
|
* boundary would strand the row.
|
|
117
117
|
*/
|
|
118
|
-
export async function resolveDevCommandOnMachine({ cwd, model, log }) {
|
|
118
|
+
export async function resolveDevCommandOnMachine({ cwd, model, log, onActivity }) {
|
|
119
119
|
let sessionId = null;
|
|
120
120
|
let timer;
|
|
121
121
|
try {
|
|
@@ -127,6 +127,18 @@ export async function resolveDevCommandOnMachine({ cwd, model, log }) {
|
|
|
127
127
|
answerFromResult: true,
|
|
128
128
|
model,
|
|
129
129
|
label: 'dev',
|
|
130
|
+
/**
|
|
131
|
+
* THE TURN'S OWN HUMANIZED TAIL, forwarded so a browser can watch it.
|
|
132
|
+
*
|
|
133
|
+
* This is the only feature in the product where a Claude does work
|
|
134
|
+
* nobody can see — no transcript, by design — and the driver's answer
|
|
135
|
+
* to that is the right one: "we could have it stream the output for
|
|
136
|
+
* transparency on the menu." So the same `read …` / `+ npm install …`
|
|
137
|
+
* lines a tab relays are forwarded here. It is the CLI's own stdout
|
|
138
|
+
* humanized, never an inference about it, which is the standing rule
|
|
139
|
+
* for every activity readout in this product.
|
|
140
|
+
*/
|
|
141
|
+
onActivity,
|
|
130
142
|
onInit: (i) => {
|
|
131
143
|
if (i?.sessionId) sessionId = i.sessionId;
|
|
132
144
|
},
|
package/bin/lib/work.mjs
CHANGED
|
@@ -112,6 +112,7 @@ export function createWorkManager({ repoRoot, baseDir, baseRef, getMcpUrl, getLe
|
|
|
112
112
|
const DEV_RUN_CLAIM_URL = FLEET_URL.replace(/\/agents\/?$/, '/dev-run-claim');
|
|
113
113
|
const DEV_RUN_DONE_URL = FLEET_URL.replace(/\/agents\/?$/, '/dev-run-done');
|
|
114
114
|
const DEV_RUN_RESOLVED_URL = FLEET_URL.replace(/\/agents\/?$/, '/dev-run-resolved');
|
|
115
|
+
const DEV_RUN_PROGRESS_URL = FLEET_URL.replace(/\/agents\/?$/, '/dev-run-progress');
|
|
115
116
|
const SESSION_COMMANDS_URL = FLEET_URL.replace(/\/agents\/?$/, '/session-commands');
|
|
116
117
|
const ATTACHMENT_URL = FLEET_URL.replace(/\/agents\/?$/, '/attachment');
|
|
117
118
|
const workAnswering = new Set(); // turn ids currently queued/running here
|
|
@@ -784,6 +785,65 @@ export function createWorkManager({ repoRoot, baseDir, baseRef, getMcpUrl, getLe
|
|
|
784
785
|
* a second implementation of that policy inside the one component a deploy
|
|
785
786
|
* cannot upgrade is exactly the drift this product keeps closing.
|
|
786
787
|
*/
|
|
788
|
+
/**
|
|
789
|
+
* THE RESOLVE TURN'S OUTPUT, streamed while it happens.
|
|
790
|
+
*
|
|
791
|
+
* A headless turn is the one place in this product where a Claude works and
|
|
792
|
+
* nobody can see it — deliberately, since it must not reach the transcript —
|
|
793
|
+
* and the answer to that is transparency rather than a promise: "we could
|
|
794
|
+
* have it stream the output for transparency on the menu."
|
|
795
|
+
*
|
|
796
|
+
* THROTTLED, and the tail is BOUNDED at the machine. This is a per-line hook
|
|
797
|
+
* on a turn that may run for minutes; posting each line would be hundreds of
|
|
798
|
+
* requests, and sending the whole transcript would grow without limit. Same
|
|
799
|
+
* shape as the session activity relay, for the same reasons.
|
|
800
|
+
*/
|
|
801
|
+
const devProgress = new Map(); // sessionId → { lines, at, timer }
|
|
802
|
+
const DEV_PROGRESS_MS = 2_000;
|
|
803
|
+
const DEV_PROGRESS_LINES = 40;
|
|
804
|
+
|
|
805
|
+
const flushDevProgress = async (sessionId) => {
|
|
806
|
+
const st = devProgress.get(sessionId);
|
|
807
|
+
if (!st || !st.lines.length) return;
|
|
808
|
+
st.at = Date.now();
|
|
809
|
+
const logTail = st.lines.join('\n').slice(-4000);
|
|
810
|
+
try {
|
|
811
|
+
await fetch(DEV_RUN_PROGRESS_URL, {
|
|
812
|
+
method: 'POST',
|
|
813
|
+
headers: {
|
|
814
|
+
Authorization: `Bearer ${FLEET_TOKEN}`,
|
|
815
|
+
'User-Agent': USER_AGENT,
|
|
816
|
+
'Content-Type': 'application/json',
|
|
817
|
+
},
|
|
818
|
+
signal: AbortSignal.timeout(15_000),
|
|
819
|
+
body: JSON.stringify({ sessionId, instance: DAEMON_INSTANCE, logTail }),
|
|
820
|
+
});
|
|
821
|
+
} catch {
|
|
822
|
+
/* progress is best-effort — the row's own state is the truth */
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
|
|
826
|
+
const noteDevProgress = (sessionId, label) => {
|
|
827
|
+
if (!label) return;
|
|
828
|
+
const st = devProgress.get(sessionId) ?? { lines: [], at: 0, timer: null };
|
|
829
|
+
st.lines.push(String(label).slice(0, 300));
|
|
830
|
+
if (st.lines.length > DEV_PROGRESS_LINES) st.lines.splice(0, st.lines.length - DEV_PROGRESS_LINES);
|
|
831
|
+
devProgress.set(sessionId, st);
|
|
832
|
+
// Leading-edge post, then a trailing one — so the FIRST line appears at
|
|
833
|
+
// once (an empty panel for two seconds reads as nothing happening) and the
|
|
834
|
+
// last line is never left unsent.
|
|
835
|
+
if (Date.now() - st.at > DEV_PROGRESS_MS) {
|
|
836
|
+
void flushDevProgress(sessionId);
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
if (st.timer) return;
|
|
840
|
+
st.timer = setTimeout(() => {
|
|
841
|
+
st.timer = null;
|
|
842
|
+
void flushDevProgress(sessionId);
|
|
843
|
+
}, DEV_PROGRESS_MS);
|
|
844
|
+
st.timer.unref?.();
|
|
845
|
+
};
|
|
846
|
+
|
|
787
847
|
const postDevResolved = async (body) => {
|
|
788
848
|
try {
|
|
789
849
|
await fetch(DEV_RUN_RESOLVED_URL, {
|
|
@@ -865,6 +925,8 @@ export function createWorkManager({ repoRoot, baseDir, baseRef, getMcpUrl, getLe
|
|
|
865
925
|
log: (m) => note(`${sessionId.slice(0, 8)}: ${m}`),
|
|
866
926
|
})
|
|
867
927
|
);
|
|
928
|
+
// The last lines, before the row leaves the resolving state.
|
|
929
|
+
await flushDevProgress(sessionId);
|
|
868
930
|
await postDevResolved({
|
|
869
931
|
sessionId,
|
|
870
932
|
command: out?.command ?? null,
|
|
@@ -877,6 +939,9 @@ export function createWorkManager({ repoRoot, baseDir, baseRef, getMcpUrl, getLe
|
|
|
877
939
|
error: `the machine could not run that turn: ${e?.message ?? 'unknown error'}`,
|
|
878
940
|
});
|
|
879
941
|
} finally {
|
|
942
|
+
const st = devProgress.get(sessionId);
|
|
943
|
+
if (st?.timer) clearTimeout(st.timer);
|
|
944
|
+
devProgress.delete(sessionId);
|
|
880
945
|
devRunClaiming.delete(sessionId);
|
|
881
946
|
}
|
|
882
947
|
})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flowviant",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.63.0",
|
|
4
4
|
"description": "Run your own coding CLIs as build agents for Flowviant — 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": {
|