Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
368ab1f
fix(STU-380): truthful outcomes for unreachable push/provision paths
devin-ai-integration[bot] Sep 27, 2026
33f5880
fix(STU-380): classify dropped bodies on their status, not their read…
devin-ai-integration[bot] Sep 27, 2026
eafd7ff
fix(STU-380): drop the cached project snapshot on unconfirmed provisi…
devin-ai-integration[bot] Sep 27, 2026
c74d7cf
test(STU-380): deliver the phase chunk before the mid-stream drop
devin-ai-integration[bot] Sep 27, 2026
606aaa6
fix(STU-380): surface definitive deploy failures in the terminal modal
devin-ai-integration[bot] Sep 27, 2026
a2a5dbd
fix(STU-380): treat push 5xx as uncertain; refusal after an uncertain…
devin-ai-integration[bot] Sep 27, 2026
0454196
fix(STU-380): bound the sync push so a stalled FlutterFlow cannot han…
devin-ai-integration[bot] Sep 27, 2026
0dfb761
fix(STU-380): keep the HTTP status on a provisioning refusal whose bo…
devin-ai-integration[bot] Sep 27, 2026
de67238
fix(STU-380): stop retries after UI timeout; label failure terminal c…
devin-ai-integration[bot] Sep 27, 2026
bd605a1
fix(deploy): runner failures after deploy begins are unconfirmed, not…
devin-ai-integration[bot] Sep 27, 2026
ffe5e91
fix(deploy): keep provisional cache + honest provenance on post-start…
devin-ai-integration[bot] Sep 27, 2026
5fff0ff
fix(deploy): cancel stalled diagnostic body reads instead of leaking …
devin-ai-integration[bot] Sep 27, 2026
c32e91c
fix(deploy): scope preWrite to parse errors, drain discarded bodies, …
devin-ai-integration[bot] Sep 27, 2026
f6649b6
fix(deploy): track possibly-written files as dirty until an export pr…
devin-ai-integration[bot] Sep 27, 2026
2c50390
fix(deploy): key dirty writes by content so overlapping provisions st…
devin-ai-integration[bot] Sep 27, 2026
635cbe1
fix(deploy): account writes per attempt; hold exports while a push is…
devin-ai-integration[bot] Sep 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
660 changes: 550 additions & 110 deletions app.js

Large diffs are not rendered by default.

65 changes: 47 additions & 18 deletions cloud-run/ffai-runner/bin/server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,23 +52,46 @@ Future<void> _handle(HttpRequest request) async {
await channel.result(HttpStatus.notFound, {
'success': false,
'error': 'Not found.',
'preWrite': true,
});
return;
}

final payload = await _readJson(request);
final apiKey = _stringField(payload, 'apiKey', maxLength: 10000);
final projectId = _stringField(payload, 'projectId', maxLength: 200);
final baseUrl = _stringField(payload, 'baseUrl', maxLength: 500, required: false);
final commitMessage = _stringField(
payload,
'commitMessage',
maxLength: 300,
required: false,
);
final dryRun = payload['dryRun'] == true;
final classes = _normalizeClasses(payload['customClasses']);
final verification = _normalizeVerification(payload['verification']);
// Only request parsing/validation throws FormatException here — those are
// provably pre-write. Decoding CLI output can raise the same exception
// AFTER the deploy began, so it must fall to the generic catch below,
// which does not claim preWrite.
Map<String, dynamic> payload;
String apiKey;
String projectId;
String baseUrl;
String commitMessage;
bool dryRun;
List<CustomClassEntry> classes;
_VerificationRequest? verification;
try {
payload = await _readJson(request);
apiKey = _stringField(payload, 'apiKey', maxLength: 10000);
projectId = _stringField(payload, 'projectId', maxLength: 200);
baseUrl = _stringField(payload, 'baseUrl', maxLength: 500, required: false);
commitMessage = _stringField(
payload,
'commitMessage',
maxLength: 300,
required: false,
);
dryRun = payload['dryRun'] == true;
classes = _normalizeClasses(payload['customClasses']);
verification = _normalizeVerification(payload['verification']);
} on FormatException catch (error) {
await channel.result(HttpStatus.badRequest, {
'success': false,
'error': error.message,
// Request validation precedes any work against the project.
'preWrite': true,
});
return;
}

// Only stream for callers that asked for it, so older clients keep getting
// the single JSON response they parse.
Expand All @@ -89,6 +112,8 @@ Future<void> _handle(HttpRequest request) async {
: 'FlutterFlow AI workspace initialization failed.',
'details': _trimOutput(initResult.output),
'exitCode': initResult.exitCode,
// Workspace setup precedes any write to FlutterFlow.
'preWrite': true,
});
return;
}
Expand All @@ -106,6 +131,8 @@ Future<void> _handle(HttpRequest request) async {
'deployed to FlutterFlow.',
'details': analysis.report,
'analyzerErrors': analysis.errors,
// The compile gate runs before the deploy script starts.
'preWrite': true,
});
return;
}
Expand Down Expand Up @@ -153,6 +180,8 @@ Future<void> _handle(HttpRequest request) async {
'success': false,
'error': 'FlutterFlow AI DSL deploy timed out.',
'details': _trimOutput(result.output),
// The CLI may already have uploaded classes before timing out.
'preWrite': false,
});
return;
}
Expand All @@ -163,6 +192,7 @@ Future<void> _handle(HttpRequest request) async {
'error': 'FlutterFlow AI DSL deploy failed.',
'details': _trimOutput(result.output),
'exitCode': result.exitCode,
'preWrite': false,
});
return;
}
Expand All @@ -180,17 +210,16 @@ Future<void> _handle(HttpRequest request) async {
'verified': analysis?.verifiedFiles ?? const <String>[],
'verificationSkipped': analysis?.skippedReason,
});
} on FormatException catch (error) {
await channel.result(HttpStatus.badRequest, {
'success': false,
'error': error.message,
});
} catch (error, stackTrace) {
stderr.writeln(error);
stderr.writeln(stackTrace);
await channel.result(HttpStatus.internalServerError, {
'success': false,
'error': '$error',
// The stage is unknown — a FormatException from decoding CLI output can
// land here after the upload began — so the write cannot be proven not
// to have run.
'preWrite': false,
});
}
}
Expand Down
188 changes: 94 additions & 94 deletions dist/assets/index-CUvr1G9X.js → dist/assets/index-Dd8Pj96z.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3313,7 +3313,7 @@
.send.is-busy .send-spin { animation: none; opacity: 0.6; }
}
</style>
<script type="module" crossorigin src="/assets/index-CUvr1G9X.js"></script>
<script type="module" crossorigin src="/assets/index-Dd8Pj96z.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DcLSblVK.css">
</head>
<body>
Expand Down
Loading
Loading