fix(ai): sync auto-commit with streamed result to surface commit SHA to UI (Fix 10)
This commit is contained in:
@@ -872,55 +872,70 @@ export async function POST(request: Request) {
|
||||
// view — without it, every fs.write / shell.exec mutation
|
||||
// stays trapped in the dev container's volume.
|
||||
//
|
||||
// Run AFTER the assistant message is persisted because the
|
||||
// user already saw the reply; a slow push shouldn't block
|
||||
// the chat. If there's nothing to commit, the helper short-
|
||||
// circuits with reason='clean' in <1s.
|
||||
// Run BEFORE the final done event so we can surface the commit
|
||||
// result in the UI (Fix 10).
|
||||
if (
|
||||
activeProject?.id &&
|
||||
activeProject?.slug &&
|
||||
typeof activeProject?.giteaCloneUrl === "string"
|
||||
) {
|
||||
(async () => {
|
||||
try {
|
||||
// Best-effort clone in case the pre-loop kick-off was
|
||||
// racing with container provisioning and never landed.
|
||||
await ensureProjectRepoCloned({
|
||||
projectId: activeProject.id,
|
||||
projectSlug: activeProject.slug,
|
||||
giteaCloneUrl: activeProject.giteaCloneUrl,
|
||||
}).catch(() => null);
|
||||
// Commit message: prefer the assistant's own first
|
||||
// sentence (one line, ≤200 chars). Falls back to a
|
||||
// generic checkpoint when the assistant only made
|
||||
// tool calls without prose.
|
||||
const firstSentence = (assistantText || "")
|
||||
.split(/(?<=[.!?])\s+/)[0]
|
||||
?.trim()
|
||||
?.slice(0, 180);
|
||||
const message = firstSentence || "AI checkpoint";
|
||||
const result = await commitAndPushIfDirty({
|
||||
projectId: activeProject.id,
|
||||
projectSlug: activeProject.slug,
|
||||
message,
|
||||
});
|
||||
if (result.committed) {
|
||||
console.log(
|
||||
`[chat] auto-commit project=${activeProject.slug} sha=${result.sha} pushed=${result.pushed}`,
|
||||
);
|
||||
} else if (
|
||||
result.reason &&
|
||||
result.reason !== "clean" &&
|
||||
result.reason !== "no_repo"
|
||||
) {
|
||||
console.warn(
|
||||
`[chat] auto-commit failed project=${activeProject.slug} reason=${result.reason}`,
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn("[chat] auto-commit fire-and-forget failed", err);
|
||||
try {
|
||||
// Best-effort clone in case the pre-loop kick-off was
|
||||
// racing with container provisioning and never landed.
|
||||
await ensureProjectRepoCloned({
|
||||
projectId: activeProject.id,
|
||||
projectSlug: activeProject.slug,
|
||||
giteaCloneUrl: activeProject.giteaCloneUrl,
|
||||
}).catch(() => null);
|
||||
// Commit message: prefer the assistant's own first
|
||||
// sentence (one line, ≤200 chars). Falls back to a
|
||||
// generic checkpoint when the assistant only made
|
||||
// tool calls without prose.
|
||||
const firstSentence = (assistantText || "")
|
||||
.split(/(?<=[.!?])\s+/)[0]
|
||||
?.trim()
|
||||
?.slice(0, 180);
|
||||
const commitMessage = firstSentence || "AI checkpoint";
|
||||
|
||||
const commitPromise = commitAndPushIfDirty({
|
||||
projectId: activeProject.id,
|
||||
projectSlug: activeProject.slug,
|
||||
message: commitMessage,
|
||||
});
|
||||
const timeoutPromise = new Promise<{
|
||||
committed: false;
|
||||
reason: string;
|
||||
}>((resolve) =>
|
||||
setTimeout(
|
||||
() => resolve({ committed: false, reason: "timeout" }),
|
||||
8000,
|
||||
),
|
||||
);
|
||||
|
||||
const result = (await Promise.race([
|
||||
commitPromise,
|
||||
timeoutPromise,
|
||||
])) as any;
|
||||
|
||||
if (result.committed) {
|
||||
emit({ type: "commit", sha: result.sha, pushed: result.pushed });
|
||||
console.log(
|
||||
`[chat] auto-commit project=${activeProject.slug} sha=${result.sha} pushed=${result.pushed}`,
|
||||
);
|
||||
} else if (
|
||||
result.reason &&
|
||||
result.reason !== "clean" &&
|
||||
result.reason !== "no_repo"
|
||||
) {
|
||||
emit({ type: "commit_failed", reason: result.reason });
|
||||
console.warn(
|
||||
`[chat] auto-commit failed project=${activeProject.slug} reason=${result.reason}`,
|
||||
);
|
||||
}
|
||||
})();
|
||||
} catch (err) {
|
||||
emit({ type: "commit_failed", reason: String(err) });
|
||||
console.warn("[chat] auto-commit failed", err);
|
||||
}
|
||||
}
|
||||
|
||||
// Fire-and-forget: ask Gemini for a 1-2 sentence "what got done"
|
||||
|
||||
Reference in New Issue
Block a user