@remixhq/core 0.1.36 → 0.1.37
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/dist/api.d.ts +48 -1
- package/dist/api.js +1 -1
- package/dist/{chunk-MNVBXTSV.js → chunk-QIESQM7X.js} +9 -0
- package/dist/collab.d.ts +2 -2
- package/dist/collab.js +473 -84
- package/dist/{contracts-BqC3Lj7W.d.ts → contracts-DTeSJnoC.d.ts} +43 -0
- package/dist/history.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/api.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CoreConfig } from './config.js';
|
|
2
2
|
import { T as TokenProvider } from './tokenProvider-B9so5Pm3.js';
|
|
3
|
-
import { T as TurnUsage } from './contracts-
|
|
3
|
+
import { T as TurnUsage } from './contracts-DTeSJnoC.js';
|
|
4
4
|
import 'zod';
|
|
5
5
|
|
|
6
6
|
type HistoryImportProvider = "claude_code" | "cursor";
|
|
@@ -264,6 +264,50 @@ type SyncLocalResponse = {
|
|
|
264
264
|
};
|
|
265
265
|
warnings: string[];
|
|
266
266
|
};
|
|
267
|
+
type LocalCheckoutRecommendedAction = "pull" | "reconcile" | "await_finalize" | "record" | "no_action";
|
|
268
|
+
type LocalAlignmentEventKind = "sync_local" | "reconcile_local";
|
|
269
|
+
type ReportLocalCheckoutStatePayload = {
|
|
270
|
+
checkoutId: string;
|
|
271
|
+
collabLaneId?: string;
|
|
272
|
+
branch?: string;
|
|
273
|
+
repoFingerprint?: string;
|
|
274
|
+
localState?: string;
|
|
275
|
+
recommendedAction: LocalCheckoutRecommendedAction;
|
|
276
|
+
materializationStatus?: string;
|
|
277
|
+
alignmentRequired?: string;
|
|
278
|
+
baselineRevisionId?: string | null;
|
|
279
|
+
localRevisionId?: string | null;
|
|
280
|
+
serverRevisionId?: string | null;
|
|
281
|
+
localHeadHash?: string;
|
|
282
|
+
serverHeadCommitId?: string | null;
|
|
283
|
+
serverHeadHash?: string;
|
|
284
|
+
hasLocalChanges?: boolean;
|
|
285
|
+
hasUnrecordedChanges?: boolean;
|
|
286
|
+
pendingFinalizeCount?: number;
|
|
287
|
+
lastSeenAt?: string;
|
|
288
|
+
metadata?: Record<string, unknown>;
|
|
289
|
+
};
|
|
290
|
+
type RecordLocalAlignmentEventPayload = {
|
|
291
|
+
eventKind: LocalAlignmentEventKind;
|
|
292
|
+
branch?: string;
|
|
293
|
+
collabLaneId?: string;
|
|
294
|
+
baseRevisionId?: string | null;
|
|
295
|
+
targetRevisionId?: string | null;
|
|
296
|
+
resultRevisionId?: string | null;
|
|
297
|
+
baseHeadCommitId?: string | null;
|
|
298
|
+
baseHeadHash?: string;
|
|
299
|
+
targetHeadCommitId?: string | null;
|
|
300
|
+
targetHeadHash?: string;
|
|
301
|
+
resultHeadCommitId?: string | null;
|
|
302
|
+
resultHeadHash?: string;
|
|
303
|
+
changedFilesCount?: number;
|
|
304
|
+
insertions?: number;
|
|
305
|
+
deletions?: number;
|
|
306
|
+
localCommitCount?: number;
|
|
307
|
+
summary?: string;
|
|
308
|
+
idempotencyKey?: string;
|
|
309
|
+
metadata?: Record<string, unknown>;
|
|
310
|
+
};
|
|
267
311
|
type SyncUpstreamResponse = {
|
|
268
312
|
status: "up-to-date" | "queued";
|
|
269
313
|
mergeRequestId?: string;
|
|
@@ -1110,6 +1154,9 @@ type ApiClient = {
|
|
|
1110
1154
|
defaultBranch?: string;
|
|
1111
1155
|
dryRun?: boolean;
|
|
1112
1156
|
}): Promise<Json>;
|
|
1157
|
+
reportLocalCheckoutState(appId: string, payload: ReportLocalCheckoutStatePayload): Promise<Json>;
|
|
1158
|
+
getLatestLocalCheckoutState(appId: string): Promise<Json>;
|
|
1159
|
+
recordLocalAlignmentEvent(appId: string, payload: RecordLocalAlignmentEventPayload): Promise<Json>;
|
|
1113
1160
|
initiateBundle(appId: string, payload: InitiateBundleRequest): Promise<Json>;
|
|
1114
1161
|
getBundle(appId: string, bundleId: string): Promise<Json>;
|
|
1115
1162
|
getBundleDownloadUrl(appId: string, bundleId: string, options?: {
|
package/dist/api.js
CHANGED
|
@@ -548,6 +548,15 @@ function createApiClient(config, opts) {
|
|
|
548
548
|
method: "POST",
|
|
549
549
|
body: JSON.stringify(payload)
|
|
550
550
|
}),
|
|
551
|
+
reportLocalCheckoutState: (appId, payload) => request(`/v1/apps/${encodeURIComponent(appId)}/local-alignment/checkout-state`, {
|
|
552
|
+
method: "POST",
|
|
553
|
+
body: JSON.stringify(payload)
|
|
554
|
+
}),
|
|
555
|
+
getLatestLocalCheckoutState: (appId) => request(`/v1/apps/${encodeURIComponent(appId)}/local-alignment/checkout-state/latest`, { method: "GET" }),
|
|
556
|
+
recordLocalAlignmentEvent: (appId, payload) => request(`/v1/apps/${encodeURIComponent(appId)}/local-alignment/events`, {
|
|
557
|
+
method: "POST",
|
|
558
|
+
body: JSON.stringify(payload)
|
|
559
|
+
}),
|
|
551
560
|
initiateBundle: (appId, payload) => request(`/v1/apps/${encodeURIComponent(appId)}/bundles`, { method: "POST", body: JSON.stringify(payload) }),
|
|
552
561
|
getBundle: (appId, bundleId) => request(`/v1/apps/${encodeURIComponent(appId)}/bundles/${encodeURIComponent(bundleId)}`, { method: "GET" }),
|
|
553
562
|
getBundleDownloadUrl: (appId, bundleId, options) => request(
|
package/dist/collab.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as CollabApiClient, a as TurnUsagePayload, b as CollabFinalizeTurnResult, c as CollabRecordingPreflight, d as CollabApproveMode, e as CollabApprovalStrategy, f as CollabApproveResult, M as MergeRequestQueue, g as MergeRequest, I as InvitationScopeType, h as CollabMember, A as AppProfileInput, J as JsonObject, i as AppDeltaResponse, j as CollabStatus, k as MergeRequestReview } from './contracts-
|
|
2
|
-
export { l as AppHeadResponse, m as AppMember, n as AppMemberRole, o as AppReconcileResponse, p as CollabFinalizeTurnAutoSync, q as CollabFinalizeTurnMode, r as CollabPendingFinalizeState, s as CollabPendingFinalizeSummary, t as CollabRecordingPreflightStatus, u as CollabRepoStateKind, v as CollabStatusBlockedReason, w as CollabStatusRecommendedAction, x as CollabTurn, y as MembershipScopeType, z as MergeRequestStatus, B as ModelCall, O as OrganizationMember, D as OrganizationMemberRole, P as ProjectMember, E as ProjectMemberRole, R as ReconcilePreflightResponse, S as ServerToolUsage, F as SyncLocalResponse, G as SyncUpstreamResponse, T as TurnUsage, H as TurnUsageCaptureSource, K as TurnUsageConfidence, L as TurnUsagePreviousPatch } from './contracts-
|
|
1
|
+
import { C as CollabApiClient, a as TurnUsagePayload, b as CollabFinalizeTurnResult, c as CollabRecordingPreflight, d as CollabApproveMode, e as CollabApprovalStrategy, f as CollabApproveResult, M as MergeRequestQueue, g as MergeRequest, I as InvitationScopeType, h as CollabMember, A as AppProfileInput, J as JsonObject, i as AppDeltaResponse, j as CollabStatus, k as MergeRequestReview } from './contracts-DTeSJnoC.js';
|
|
2
|
+
export { l as AppHeadResponse, m as AppMember, n as AppMemberRole, o as AppReconcileResponse, p as CollabFinalizeTurnAutoSync, q as CollabFinalizeTurnMode, r as CollabPendingFinalizeState, s as CollabPendingFinalizeSummary, t as CollabRecordingPreflightStatus, u as CollabRepoStateKind, v as CollabStatusBlockedReason, w as CollabStatusRecommendedAction, x as CollabTurn, y as MembershipScopeType, z as MergeRequestStatus, B as ModelCall, O as OrganizationMember, D as OrganizationMemberRole, P as ProjectMember, E as ProjectMemberRole, R as ReconcilePreflightResponse, S as ServerToolUsage, F as SyncLocalResponse, G as SyncUpstreamResponse, T as TurnUsage, H as TurnUsageCaptureSource, K as TurnUsageConfidence, L as TurnUsagePreviousPatch } from './contracts-DTeSJnoC.js';
|
|
3
3
|
import { B as BranchBindingMode } from './binding-WiIRI2fl.js';
|
|
4
4
|
|
|
5
5
|
declare function collabFinalizeTurn(params: {
|
package/dist/collab.js
CHANGED
|
@@ -952,6 +952,25 @@ function matchesJobScope(job, scope) {
|
|
|
952
952
|
if (scope.repoFingerprint && job.repoFingerprint && job.repoFingerprint !== scope.repoFingerprint) return false;
|
|
953
953
|
return true;
|
|
954
954
|
}
|
|
955
|
+
function isSameProcessingScope(left, right) {
|
|
956
|
+
return left.id !== right.id && left.repoRoot === right.repoRoot && left.currentAppId === right.currentAppId && (left.laneId ?? null) === (right.laneId ?? null) && (left.repoFingerprint ?? null) === (right.repoFingerprint ?? null);
|
|
957
|
+
}
|
|
958
|
+
async function hasFreshJobLock(jobId) {
|
|
959
|
+
try {
|
|
960
|
+
const stat = await fs4.stat(getJobLockPath2(jobId));
|
|
961
|
+
return Date.now() - stat.mtimeMs < FINALIZE_JOB_LOCK_STALE_MS;
|
|
962
|
+
} catch (error) {
|
|
963
|
+
if (error?.code === "ENOENT") {
|
|
964
|
+
return false;
|
|
965
|
+
}
|
|
966
|
+
throw error;
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
async function blocksFinalizeClaim(candidate, blocker) {
|
|
970
|
+
if (!isSameProcessingScope(candidate, blocker)) return false;
|
|
971
|
+
if (blocker.status === "processing") return hasFreshJobLock(blocker.id);
|
|
972
|
+
return blocker.status === "queued" && isPastDue(blocker.nextRetryAt) && blocker.capturedAt < candidate.capturedAt;
|
|
973
|
+
}
|
|
955
974
|
function createEmptyPendingFinalizeQueueSummary() {
|
|
956
975
|
return {
|
|
957
976
|
state: "idle",
|
|
@@ -1225,6 +1244,13 @@ async function claimPendingFinalizeJob(jobId) {
|
|
|
1225
1244
|
await release();
|
|
1226
1245
|
return null;
|
|
1227
1246
|
}
|
|
1247
|
+
const jobs = await listPendingFinalizeJobs();
|
|
1248
|
+
for (const job of jobs) {
|
|
1249
|
+
if (await blocksFinalizeClaim(existing, job)) {
|
|
1250
|
+
await release();
|
|
1251
|
+
return null;
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1228
1254
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1229
1255
|
const claimed = await updatePendingFinalizeJob(jobId, {
|
|
1230
1256
|
status: "processing",
|
|
@@ -2710,6 +2736,188 @@ function validateSucceededChangeStepForBaseline(params) {
|
|
|
2710
2736
|
};
|
|
2711
2737
|
}
|
|
2712
2738
|
|
|
2739
|
+
// src/infrastructure/collab/checkoutIdentityStore.ts
|
|
2740
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
2741
|
+
import fs5 from "fs/promises";
|
|
2742
|
+
import path6 from "path";
|
|
2743
|
+
function getCheckoutIdentityPath(params) {
|
|
2744
|
+
return path6.join(getCollabStateRoot(), "checkouts", `${buildLaneStateKey(params)}.json`);
|
|
2745
|
+
}
|
|
2746
|
+
async function getCheckoutIdentity(params) {
|
|
2747
|
+
const filePath = getCheckoutIdentityPath(params);
|
|
2748
|
+
try {
|
|
2749
|
+
const raw = await fs5.readFile(filePath, "utf8");
|
|
2750
|
+
const parsed = JSON.parse(raw);
|
|
2751
|
+
const checkoutId = typeof parsed?.checkoutId === "string" ? parsed.checkoutId.trim() : "";
|
|
2752
|
+
if (checkoutId) return checkoutId;
|
|
2753
|
+
} catch {
|
|
2754
|
+
}
|
|
2755
|
+
const next = {
|
|
2756
|
+
schemaVersion: 1,
|
|
2757
|
+
checkoutId: randomUUID4(),
|
|
2758
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2759
|
+
};
|
|
2760
|
+
await writeJsonAtomic(filePath, next);
|
|
2761
|
+
return next.checkoutId;
|
|
2762
|
+
}
|
|
2763
|
+
|
|
2764
|
+
// src/application/collab/localAlignmentReporting.ts
|
|
2765
|
+
function toCheckoutAction(action) {
|
|
2766
|
+
if (action === "pull" || action === "reconcile" || action === "await_finalize" || action === "record") return action;
|
|
2767
|
+
return "no_action";
|
|
2768
|
+
}
|
|
2769
|
+
function actionForRepoState(repoState) {
|
|
2770
|
+
if (repoState === "server_only_changed") return "pull";
|
|
2771
|
+
if (repoState === "both_changed" || repoState === "external_local_base_changed" || repoState === "baseline_missing") {
|
|
2772
|
+
return "reconcile";
|
|
2773
|
+
}
|
|
2774
|
+
if (repoState === "local_only_changed") return "record";
|
|
2775
|
+
return "no_action";
|
|
2776
|
+
}
|
|
2777
|
+
function alignmentRequiredForAction(action) {
|
|
2778
|
+
if (action === "pull") return "sync";
|
|
2779
|
+
if (action === "reconcile") return "reconcile";
|
|
2780
|
+
if (action === "await_finalize") return "finalize";
|
|
2781
|
+
if (action === "record") return "record";
|
|
2782
|
+
return void 0;
|
|
2783
|
+
}
|
|
2784
|
+
async function reportCheckoutState(params) {
|
|
2785
|
+
try {
|
|
2786
|
+
const checkoutId = await getCheckoutIdentity({
|
|
2787
|
+
repoRoot: params.repoRoot,
|
|
2788
|
+
repoFingerprint: params.repoFingerprint ?? null,
|
|
2789
|
+
laneId: params.laneId ?? null
|
|
2790
|
+
});
|
|
2791
|
+
await params.api.reportLocalCheckoutState(params.appId, {
|
|
2792
|
+
checkoutId,
|
|
2793
|
+
collabLaneId: params.laneId ?? void 0,
|
|
2794
|
+
branch: params.branch ?? void 0,
|
|
2795
|
+
repoFingerprint: params.repoFingerprint ?? void 0,
|
|
2796
|
+
localState: params.localState ?? void 0,
|
|
2797
|
+
recommendedAction: params.recommendedAction,
|
|
2798
|
+
materializationStatus: params.materializationStatus ?? void 0,
|
|
2799
|
+
alignmentRequired: params.alignmentRequired ?? alignmentRequiredForAction(params.recommendedAction),
|
|
2800
|
+
baselineRevisionId: params.baselineRevisionId,
|
|
2801
|
+
localRevisionId: params.localRevisionId,
|
|
2802
|
+
serverRevisionId: params.serverRevisionId,
|
|
2803
|
+
localHeadHash: params.localHeadHash ?? void 0,
|
|
2804
|
+
serverHeadCommitId: params.serverHeadCommitId,
|
|
2805
|
+
serverHeadHash: params.serverHeadHash ?? void 0,
|
|
2806
|
+
hasLocalChanges: params.hasLocalChanges,
|
|
2807
|
+
hasUnrecordedChanges: params.hasUnrecordedChanges,
|
|
2808
|
+
pendingFinalizeCount: params.pendingFinalizeCount,
|
|
2809
|
+
metadata: params.metadata
|
|
2810
|
+
});
|
|
2811
|
+
return { warnings: [] };
|
|
2812
|
+
} catch (err) {
|
|
2813
|
+
const message = err instanceof Error ? err.message : String(err ?? "unknown error");
|
|
2814
|
+
return { warnings: [`Failed to report local checkout state: ${message}`] };
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
async function reportCheckoutStateFromStatus(params) {
|
|
2818
|
+
const { api, status } = params;
|
|
2819
|
+
const repoRoot = status.repo.repoRoot;
|
|
2820
|
+
const appId = status.binding.currentAppId;
|
|
2821
|
+
if (!api || !repoRoot || !appId) return { warnings: [] };
|
|
2822
|
+
return reportCheckoutState({
|
|
2823
|
+
api,
|
|
2824
|
+
appId,
|
|
2825
|
+
repoRoot,
|
|
2826
|
+
repoFingerprint: status.binding.repoFingerprint,
|
|
2827
|
+
laneId: status.binding.laneId,
|
|
2828
|
+
branch: status.repo.branch ?? status.binding.branchName,
|
|
2829
|
+
localState: status.alignment.repoState,
|
|
2830
|
+
recommendedAction: toCheckoutAction(status.recommendedAction),
|
|
2831
|
+
materializationStatus: status.alignment.checked ? "checked" : void 0,
|
|
2832
|
+
baselineRevisionId: status.alignment.baseline.lastServerRevisionId,
|
|
2833
|
+
serverRevisionId: status.alignment.current.serverRevisionId,
|
|
2834
|
+
localHeadHash: status.alignment.current.localCommitHash ?? status.repo.headCommitHash,
|
|
2835
|
+
serverHeadCommitId: status.alignment.current.serverHeadCommitId,
|
|
2836
|
+
serverHeadHash: status.alignment.current.serverHeadHash,
|
|
2837
|
+
hasLocalChanges: status.alignment.repoState === "local_only_changed" || status.alignment.repoState === "both_changed",
|
|
2838
|
+
hasUnrecordedChanges: status.alignment.repoState === "local_only_changed" || status.alignment.repoState === "both_changed",
|
|
2839
|
+
pendingFinalizeCount: status.alignment.pendingFinalize.activeJobCount,
|
|
2840
|
+
metadata: {
|
|
2841
|
+
source: params.source,
|
|
2842
|
+
branchMismatch: status.repo.branchMismatch
|
|
2843
|
+
}
|
|
2844
|
+
});
|
|
2845
|
+
}
|
|
2846
|
+
async function reportAlignedCheckoutState(params) {
|
|
2847
|
+
return reportCheckoutState({
|
|
2848
|
+
api: params.api,
|
|
2849
|
+
appId: params.appId,
|
|
2850
|
+
repoRoot: params.repoRoot,
|
|
2851
|
+
repoFingerprint: params.repoFingerprint,
|
|
2852
|
+
laneId: params.laneId,
|
|
2853
|
+
branch: params.branch,
|
|
2854
|
+
localState: "idle",
|
|
2855
|
+
recommendedAction: "no_action",
|
|
2856
|
+
materializationStatus: "applied",
|
|
2857
|
+
baselineRevisionId: params.baselineRevisionId,
|
|
2858
|
+
serverRevisionId: params.serverRevisionId,
|
|
2859
|
+
localHeadHash: params.localHeadHash,
|
|
2860
|
+
serverHeadCommitId: params.serverHeadCommitId,
|
|
2861
|
+
serverHeadHash: params.serverHeadHash,
|
|
2862
|
+
hasLocalChanges: false,
|
|
2863
|
+
hasUnrecordedChanges: false,
|
|
2864
|
+
pendingFinalizeCount: 0,
|
|
2865
|
+
metadata: { source: params.source }
|
|
2866
|
+
});
|
|
2867
|
+
}
|
|
2868
|
+
async function reportCheckoutStateFromFinalize(params) {
|
|
2869
|
+
const recommendedAction = params.materializationStatus.startsWith("queued") ? "await_finalize" : actionForRepoState(params.repoState);
|
|
2870
|
+
const hasLocalChanges = params.repoState === "local_only_changed" || params.repoState === "both_changed";
|
|
2871
|
+
return reportCheckoutState({
|
|
2872
|
+
api: params.api,
|
|
2873
|
+
appId: params.appId,
|
|
2874
|
+
repoRoot: params.repoRoot,
|
|
2875
|
+
repoFingerprint: params.repoFingerprint,
|
|
2876
|
+
laneId: params.laneId,
|
|
2877
|
+
branch: params.branch,
|
|
2878
|
+
localState: params.repoState,
|
|
2879
|
+
recommendedAction,
|
|
2880
|
+
materializationStatus: params.materializationStatus,
|
|
2881
|
+
alignmentRequired: params.alignmentRequired,
|
|
2882
|
+
baselineRevisionId: params.baselineRevisionId,
|
|
2883
|
+
serverRevisionId: params.serverRevisionId,
|
|
2884
|
+
localHeadHash: params.localHeadHash,
|
|
2885
|
+
serverHeadCommitId: params.serverHeadCommitId,
|
|
2886
|
+
serverHeadHash: params.serverHeadHash,
|
|
2887
|
+
hasLocalChanges,
|
|
2888
|
+
hasUnrecordedChanges: recommendedAction === "record" || recommendedAction === "reconcile",
|
|
2889
|
+
pendingFinalizeCount: params.pendingFinalizeCount,
|
|
2890
|
+
metadata: { source: params.source }
|
|
2891
|
+
});
|
|
2892
|
+
}
|
|
2893
|
+
async function recordLocalAlignmentEvent(params) {
|
|
2894
|
+
try {
|
|
2895
|
+
await params.api.recordLocalAlignmentEvent(params.appId, {
|
|
2896
|
+
eventKind: params.eventKind,
|
|
2897
|
+
branch: params.branch,
|
|
2898
|
+
collabLaneId: params.collabLaneId ?? void 0,
|
|
2899
|
+
baseRevisionId: params.baseRevisionId,
|
|
2900
|
+
targetRevisionId: params.targetRevisionId,
|
|
2901
|
+
resultRevisionId: params.resultRevisionId,
|
|
2902
|
+
baseHeadHash: params.baseHeadHash ?? void 0,
|
|
2903
|
+
targetHeadCommitId: params.targetHeadCommitId,
|
|
2904
|
+
targetHeadHash: params.targetHeadHash ?? void 0,
|
|
2905
|
+
resultHeadHash: params.resultHeadHash ?? void 0,
|
|
2906
|
+
changedFilesCount: params.changedFilesCount,
|
|
2907
|
+
insertions: params.insertions,
|
|
2908
|
+
deletions: params.deletions,
|
|
2909
|
+
localCommitCount: params.localCommitCount,
|
|
2910
|
+
summary: params.summary,
|
|
2911
|
+
idempotencyKey: params.idempotencyKey,
|
|
2912
|
+
metadata: { source: params.eventKind }
|
|
2913
|
+
});
|
|
2914
|
+
return { warnings: [] };
|
|
2915
|
+
} catch (err) {
|
|
2916
|
+
const message = err instanceof Error ? err.message : String(err ?? "unknown error");
|
|
2917
|
+
return { warnings: [`Failed to record local alignment event: ${message}`] };
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2920
|
+
|
|
2713
2921
|
// src/application/collab/collabFinalizeProcessing.ts
|
|
2714
2922
|
var FINALIZE_RETRY_BASE_DELAY_MS = 15e3;
|
|
2715
2923
|
var FINALIZE_RETRY_MAX_DELAY_MS = 5 * 60 * 1e3;
|
|
@@ -2834,6 +3042,23 @@ async function writeBaselineFromSucceededChangeStep(params) {
|
|
|
2834
3042
|
lastSeenLocalCommitHash: params.snapshot.localCommitHash
|
|
2835
3043
|
});
|
|
2836
3044
|
}
|
|
3045
|
+
async function reportCompletedFinalizeCheckoutState(params) {
|
|
3046
|
+
const result = await reportAlignedCheckoutState({
|
|
3047
|
+
api: params.api,
|
|
3048
|
+
appId: params.job.currentAppId,
|
|
3049
|
+
repoRoot: params.job.repoRoot,
|
|
3050
|
+
repoFingerprint: params.job.repoFingerprint,
|
|
3051
|
+
laneId: params.job.laneId,
|
|
3052
|
+
branch: params.job.branchName,
|
|
3053
|
+
baselineRevisionId: params.serverRevisionId,
|
|
3054
|
+
serverRevisionId: params.serverRevisionId,
|
|
3055
|
+
localHeadHash: params.snapshot.localCommitHash,
|
|
3056
|
+
serverHeadCommitId: params.serverHeadCommitId,
|
|
3057
|
+
serverHeadHash: params.serverHeadHash,
|
|
3058
|
+
source: params.source
|
|
3059
|
+
});
|
|
3060
|
+
return result.warnings;
|
|
3061
|
+
}
|
|
2837
3062
|
async function harvestPreTurnEvents(repoRoot, fromCommit, toCommit) {
|
|
2838
3063
|
if (!toCommit) return null;
|
|
2839
3064
|
try {
|
|
@@ -3002,6 +3227,15 @@ async function processClaimedPendingFinalizeJobInner(params) {
|
|
|
3002
3227
|
status: "completed",
|
|
3003
3228
|
metadata: { collabTurnId: collabTurn.id }
|
|
3004
3229
|
});
|
|
3230
|
+
const reportWarnings2 = await reportCompletedFinalizeCheckoutState({
|
|
3231
|
+
api: params.api,
|
|
3232
|
+
job,
|
|
3233
|
+
snapshot,
|
|
3234
|
+
serverRevisionId: appHead.headRevisionId ?? null,
|
|
3235
|
+
serverHeadCommitId: appHead.headCommitId,
|
|
3236
|
+
serverHeadHash: appHead.headCommitHash,
|
|
3237
|
+
source: "finalize_no_diff_turn"
|
|
3238
|
+
});
|
|
3005
3239
|
return {
|
|
3006
3240
|
mode: "no_diff_turn",
|
|
3007
3241
|
idempotencyKey: job.idempotencyKey ?? "",
|
|
@@ -3011,7 +3245,7 @@ async function processClaimedPendingFinalizeJobInner(params) {
|
|
|
3011
3245
|
changeStep: null,
|
|
3012
3246
|
collabTurn,
|
|
3013
3247
|
autoSync: null,
|
|
3014
|
-
warnings:
|
|
3248
|
+
warnings: reportWarnings2
|
|
3015
3249
|
};
|
|
3016
3250
|
}
|
|
3017
3251
|
const localBaselineAdvanced = baseline.lastSnapshotId !== job.baselineSnapshotId;
|
|
@@ -3062,6 +3296,15 @@ async function processClaimedPendingFinalizeJobInner(params) {
|
|
|
3062
3296
|
changeStepId: String(changeStep2.id ?? "")
|
|
3063
3297
|
}
|
|
3064
3298
|
});
|
|
3299
|
+
const reportWarnings2 = await reportCompletedFinalizeCheckoutState({
|
|
3300
|
+
api: params.api,
|
|
3301
|
+
job,
|
|
3302
|
+
snapshot,
|
|
3303
|
+
serverRevisionId: String(changeStep2.resultRevisionId ?? "") || null,
|
|
3304
|
+
serverHeadCommitId: String(changeStep2.commitId ?? "") || null,
|
|
3305
|
+
serverHeadHash: String(changeStep2.headCommitHash ?? "") || null,
|
|
3306
|
+
source: "finalize_changed_turn"
|
|
3307
|
+
});
|
|
3065
3308
|
return {
|
|
3066
3309
|
mode: "changed_turn",
|
|
3067
3310
|
idempotencyKey: job.idempotencyKey ?? "",
|
|
@@ -3071,7 +3314,7 @@ async function processClaimedPendingFinalizeJobInner(params) {
|
|
|
3071
3314
|
changeStep: changeStep2,
|
|
3072
3315
|
collabTurn: null,
|
|
3073
3316
|
autoSync: null,
|
|
3074
|
-
warnings:
|
|
3317
|
+
warnings: reportWarnings2
|
|
3075
3318
|
};
|
|
3076
3319
|
}
|
|
3077
3320
|
}
|
|
@@ -3179,6 +3422,15 @@ async function processClaimedPendingFinalizeJobInner(params) {
|
|
|
3179
3422
|
changeStepId: String(changeStep.id ?? "")
|
|
3180
3423
|
}
|
|
3181
3424
|
});
|
|
3425
|
+
const reportWarnings = await reportCompletedFinalizeCheckoutState({
|
|
3426
|
+
api: params.api,
|
|
3427
|
+
job,
|
|
3428
|
+
snapshot,
|
|
3429
|
+
serverRevisionId: String(changeStep.resultRevisionId ?? "") || null,
|
|
3430
|
+
serverHeadCommitId: String(changeStep.commitId ?? "") || null,
|
|
3431
|
+
serverHeadHash: String(changeStep.headCommitHash ?? "") || null,
|
|
3432
|
+
source: "finalize_changed_turn"
|
|
3433
|
+
});
|
|
3182
3434
|
return {
|
|
3183
3435
|
mode: "changed_turn",
|
|
3184
3436
|
idempotencyKey: job.idempotencyKey ?? "",
|
|
@@ -3188,7 +3440,7 @@ async function processClaimedPendingFinalizeJobInner(params) {
|
|
|
3188
3440
|
changeStep,
|
|
3189
3441
|
collabTurn: null,
|
|
3190
3442
|
autoSync: null,
|
|
3191
|
-
warnings:
|
|
3443
|
+
warnings: reportWarnings
|
|
3192
3444
|
};
|
|
3193
3445
|
}
|
|
3194
3446
|
async function processPendingFinalizeJob(params) {
|
|
@@ -3396,6 +3648,23 @@ async function recordConversationOnlyTurn(params) {
|
|
|
3396
3648
|
idempotencyKey
|
|
3397
3649
|
});
|
|
3398
3650
|
const collabTurn = unwrapResponseObject(collabTurnResp, "collab turn");
|
|
3651
|
+
const reportResult = await reportCheckoutStateFromFinalize({
|
|
3652
|
+
api: params.api,
|
|
3653
|
+
appId: params.binding.currentAppId,
|
|
3654
|
+
repoRoot: params.repoRoot,
|
|
3655
|
+
repoFingerprint: params.binding.repoFingerprint,
|
|
3656
|
+
laneId: params.binding.laneId,
|
|
3657
|
+
branch: params.binding.branchName,
|
|
3658
|
+
repoState: params.repoState,
|
|
3659
|
+
materializationStatus: params.materializationStatus,
|
|
3660
|
+
alignmentRequired: params.alignmentRequired,
|
|
3661
|
+
baselineRevisionId: params.baselineServerRevisionId,
|
|
3662
|
+
serverRevisionId: params.currentServerRevisionId,
|
|
3663
|
+
localHeadHash: params.localCommitHash,
|
|
3664
|
+
serverHeadCommitId: params.currentServerHeadCommitId,
|
|
3665
|
+
serverHeadHash: params.currentServerHeadHash,
|
|
3666
|
+
source: "finalize_conversation_only"
|
|
3667
|
+
});
|
|
3399
3668
|
return {
|
|
3400
3669
|
mode: "conversation_only",
|
|
3401
3670
|
idempotencyKey,
|
|
@@ -3405,7 +3674,7 @@ async function recordConversationOnlyTurn(params) {
|
|
|
3405
3674
|
changeStep: null,
|
|
3406
3675
|
collabTurn,
|
|
3407
3676
|
autoSync: null,
|
|
3408
|
-
warnings: [CONVERSATION_ONLY_WARNING, ...collectWarnings(params.warnings ?? [])]
|
|
3677
|
+
warnings: [CONVERSATION_ONLY_WARNING, ...collectWarnings(params.warnings ?? []), ...reportResult.warnings]
|
|
3409
3678
|
};
|
|
3410
3679
|
}
|
|
3411
3680
|
async function collabFinalizeTurn(params) {
|
|
@@ -3668,6 +3937,24 @@ async function collabFinalizeTurn(params) {
|
|
|
3668
3937
|
},
|
|
3669
3938
|
nextRetryAt
|
|
3670
3939
|
});
|
|
3940
|
+
const reportResult = await reportCheckoutStateFromFinalize({
|
|
3941
|
+
api: params.api,
|
|
3942
|
+
appId: binding.currentAppId,
|
|
3943
|
+
repoRoot,
|
|
3944
|
+
repoFingerprint: binding.repoFingerprint,
|
|
3945
|
+
laneId: binding.laneId,
|
|
3946
|
+
branch: binding.branchName,
|
|
3947
|
+
repoState: detected.repoState,
|
|
3948
|
+
materializationStatus: "queued_finalize",
|
|
3949
|
+
alignmentRequired: "finalize",
|
|
3950
|
+
baselineRevisionId: baseline.lastServerRevisionId,
|
|
3951
|
+
serverRevisionId: detected.currentServerRevisionId,
|
|
3952
|
+
localHeadHash: snapshot.localCommitHash,
|
|
3953
|
+
serverHeadCommitId: detected.currentServerHeadCommitId,
|
|
3954
|
+
serverHeadHash: detected.currentServerHeadHash,
|
|
3955
|
+
pendingFinalizeCount: 1,
|
|
3956
|
+
source: "finalize_queue"
|
|
3957
|
+
});
|
|
3671
3958
|
return {
|
|
3672
3959
|
mode,
|
|
3673
3960
|
idempotencyKey,
|
|
@@ -3677,7 +3964,7 @@ async function collabFinalizeTurn(params) {
|
|
|
3677
3964
|
changeStep: null,
|
|
3678
3965
|
collabTurn: null,
|
|
3679
3966
|
autoSync: null,
|
|
3680
|
-
warnings: [FINALIZE_QUEUED_WARNING, ...collectWarnings([...pendingFinalizeDrainWarnings, ...detected.warnings])]
|
|
3967
|
+
warnings: [FINALIZE_QUEUED_WARNING, ...collectWarnings([...pendingFinalizeDrainWarnings, ...detected.warnings]), ...reportResult.warnings]
|
|
3681
3968
|
};
|
|
3682
3969
|
}
|
|
3683
3970
|
|
|
@@ -3773,9 +4060,9 @@ async function collabRecordingPreflight(params) {
|
|
|
3773
4060
|
}
|
|
3774
4061
|
|
|
3775
4062
|
// src/infrastructure/locking/repoMutationLock.ts
|
|
3776
|
-
import
|
|
4063
|
+
import fs6 from "fs/promises";
|
|
3777
4064
|
import os3 from "os";
|
|
3778
|
-
import
|
|
4065
|
+
import path7 from "path";
|
|
3779
4066
|
var DEFAULT_ACQUIRE_TIMEOUT_MS = 15e3;
|
|
3780
4067
|
var DEFAULT_STALE_MS = 45e3;
|
|
3781
4068
|
var DEFAULT_HEARTBEAT_MS = 5e3;
|
|
@@ -3798,12 +4085,12 @@ function createOwner(params) {
|
|
|
3798
4085
|
};
|
|
3799
4086
|
}
|
|
3800
4087
|
async function writeOwnerMetadata(ownerPath, owner) {
|
|
3801
|
-
await
|
|
4088
|
+
await fs6.writeFile(ownerPath, `${JSON.stringify(owner, null, 2)}
|
|
3802
4089
|
`, "utf8");
|
|
3803
4090
|
}
|
|
3804
4091
|
async function readOwnerMetadata(ownerPath) {
|
|
3805
4092
|
try {
|
|
3806
|
-
const raw = await
|
|
4093
|
+
const raw = await fs6.readFile(ownerPath, "utf8");
|
|
3807
4094
|
const parsed = JSON.parse(raw);
|
|
3808
4095
|
if (!parsed || typeof parsed !== "object") return null;
|
|
3809
4096
|
if (!parsed.operation || !parsed.repoRoot || typeof parsed.pid !== "number" || !parsed.startedAt || !parsed.heartbeatAt) {
|
|
@@ -3840,23 +4127,23 @@ async function getLastKnownUpdateMs(lockDir, ownerPath, owner) {
|
|
|
3840
4127
|
if (Number.isFinite(heartbeatMs)) return heartbeatMs;
|
|
3841
4128
|
const startedMs = owner ? Date.parse(owner.startedAt) : Number.NaN;
|
|
3842
4129
|
if (Number.isFinite(startedMs)) return startedMs;
|
|
3843
|
-
const stat = await
|
|
4130
|
+
const stat = await fs6.stat(ownerPath).catch(() => null);
|
|
3844
4131
|
if (stat) return stat.mtimeMs;
|
|
3845
|
-
const dirStat = await
|
|
4132
|
+
const dirStat = await fs6.stat(lockDir).catch(() => null);
|
|
3846
4133
|
if (dirStat) return dirStat.mtimeMs;
|
|
3847
4134
|
return 0;
|
|
3848
4135
|
}
|
|
3849
4136
|
async function ensureLockDir(lockDir) {
|
|
3850
|
-
await
|
|
4137
|
+
await fs6.mkdir(path7.dirname(lockDir), { recursive: true });
|
|
3851
4138
|
}
|
|
3852
4139
|
async function tryAcquireLock(lockDir, ownerPath, owner) {
|
|
3853
4140
|
try {
|
|
3854
4141
|
await ensureLockDir(lockDir);
|
|
3855
|
-
await
|
|
4142
|
+
await fs6.mkdir(lockDir);
|
|
3856
4143
|
try {
|
|
3857
4144
|
await writeOwnerMetadata(ownerPath, owner);
|
|
3858
4145
|
} catch (error) {
|
|
3859
|
-
await
|
|
4146
|
+
await fs6.rm(lockDir, { recursive: true, force: true }).catch(() => void 0);
|
|
3860
4147
|
throw error;
|
|
3861
4148
|
}
|
|
3862
4149
|
return true;
|
|
@@ -3906,7 +4193,7 @@ async function acquirePhysicalLock(lockDir, ownerPath, owner, options) {
|
|
|
3906
4193
|
const alive = await isProcessAlive(currentOwner2);
|
|
3907
4194
|
if (ageMs >= options.staleMs && alive !== true) {
|
|
3908
4195
|
notices.push(buildStaleRecoveryNotice(currentOwner2));
|
|
3909
|
-
await
|
|
4196
|
+
await fs6.rm(lockDir, { recursive: true, force: true }).catch(() => void 0);
|
|
3910
4197
|
continue;
|
|
3911
4198
|
}
|
|
3912
4199
|
await sleep2(RETRY_DELAY_MS);
|
|
@@ -3931,7 +4218,7 @@ function startHeartbeat(lockDir, ownerPath, owner, heartbeatMs) {
|
|
|
3931
4218
|
};
|
|
3932
4219
|
owner.heartbeatAt = nextOwner.heartbeatAt;
|
|
3933
4220
|
void writeOwnerMetadata(ownerPath, nextOwner).catch(() => void 0);
|
|
3934
|
-
void
|
|
4221
|
+
void fs6.utimes(lockDir, /* @__PURE__ */ new Date(), /* @__PURE__ */ new Date()).catch(() => void 0);
|
|
3935
4222
|
}, heartbeatMs);
|
|
3936
4223
|
}
|
|
3937
4224
|
async function releaseReentrantLock(lockDir) {
|
|
@@ -3941,12 +4228,12 @@ async function releaseReentrantLock(lockDir) {
|
|
|
3941
4228
|
if (held.count > 0) return;
|
|
3942
4229
|
clearInterval(held.heartbeatTimer);
|
|
3943
4230
|
heldLocks.delete(lockDir);
|
|
3944
|
-
await
|
|
4231
|
+
await fs6.rm(lockDir, { recursive: true, force: true }).catch(() => void 0);
|
|
3945
4232
|
}
|
|
3946
4233
|
async function withRepoMutationLock(options, fn) {
|
|
3947
4234
|
const repoRoot = await findGitRoot(options.cwd);
|
|
3948
4235
|
const gitCommonDir = await getGitCommonDir(repoRoot);
|
|
3949
|
-
const lockDir =
|
|
4236
|
+
const lockDir = path7.join(gitCommonDir, "remix", "locks", "repo-mutation.lock");
|
|
3950
4237
|
const owner = createOwner({
|
|
3951
4238
|
operation: options.operation,
|
|
3952
4239
|
repoRoot,
|
|
@@ -3958,11 +4245,11 @@ async function withRepoMutationLock(options, fn) {
|
|
|
3958
4245
|
const existing = heldLocks.get(lockDir);
|
|
3959
4246
|
let notices = [];
|
|
3960
4247
|
if (!existing) {
|
|
3961
|
-
notices = await acquirePhysicalLock(lockDir,
|
|
4248
|
+
notices = await acquirePhysicalLock(lockDir, path7.join(lockDir, "owner.json"), owner, {
|
|
3962
4249
|
acquireTimeoutMs,
|
|
3963
4250
|
staleMs
|
|
3964
4251
|
});
|
|
3965
|
-
const ownerPath =
|
|
4252
|
+
const ownerPath = path7.join(lockDir, "owner.json");
|
|
3966
4253
|
heldLocks.set(lockDir, {
|
|
3967
4254
|
count: 1,
|
|
3968
4255
|
lockDir,
|
|
@@ -4158,10 +4445,24 @@ async function collabSync(params) {
|
|
|
4158
4445
|
lastServerHeadHash: delta.targetHeadHash,
|
|
4159
4446
|
lastSeenLocalCommitHash: snapshot.localCommitHash
|
|
4160
4447
|
});
|
|
4448
|
+
const reportResult = await reportAlignedCheckoutState({
|
|
4449
|
+
api: params.api,
|
|
4450
|
+
appId: binding.currentAppId,
|
|
4451
|
+
repoRoot: lockedRepoRoot,
|
|
4452
|
+
repoFingerprint: binding.repoFingerprint,
|
|
4453
|
+
laneId: binding.laneId,
|
|
4454
|
+
branch,
|
|
4455
|
+
baselineRevisionId: delta.targetRevisionId ?? null,
|
|
4456
|
+
serverRevisionId: delta.targetRevisionId ?? null,
|
|
4457
|
+
localHeadHash: snapshot.localCommitHash,
|
|
4458
|
+
serverHeadCommitId: delta.targetHeadCommitId,
|
|
4459
|
+
serverHeadHash: delta.targetHeadHash,
|
|
4460
|
+
source: "sync_apply"
|
|
4461
|
+
});
|
|
4161
4462
|
return {
|
|
4162
4463
|
...previewResult,
|
|
4163
4464
|
localCommitHash: snapshot.localCommitHash,
|
|
4164
|
-
...warnings.length > 0 ? { warnings } : {}
|
|
4465
|
+
...[...warnings, ...reportResult.warnings].length > 0 ? { warnings: [...warnings, ...reportResult.warnings] } : {}
|
|
4165
4466
|
};
|
|
4166
4467
|
}
|
|
4167
4468
|
);
|
|
@@ -4218,13 +4519,56 @@ async function collabSync(params) {
|
|
|
4218
4519
|
lastServerHeadHash: delta.targetHeadHash,
|
|
4219
4520
|
lastSeenLocalCommitHash: snapshot.localCommitHash
|
|
4220
4521
|
});
|
|
4522
|
+
const reportResult = await reportAlignedCheckoutState({
|
|
4523
|
+
api: params.api,
|
|
4524
|
+
appId: binding.currentAppId,
|
|
4525
|
+
repoRoot: lockedRepoRoot,
|
|
4526
|
+
repoFingerprint: binding.repoFingerprint,
|
|
4527
|
+
laneId: binding.laneId,
|
|
4528
|
+
branch,
|
|
4529
|
+
baselineRevisionId: delta.targetRevisionId ?? null,
|
|
4530
|
+
serverRevisionId: delta.targetRevisionId ?? null,
|
|
4531
|
+
localHeadHash: snapshot.localCommitHash,
|
|
4532
|
+
serverHeadCommitId: delta.targetHeadCommitId,
|
|
4533
|
+
serverHeadHash: delta.targetHeadHash,
|
|
4534
|
+
source: "sync_apply"
|
|
4535
|
+
});
|
|
4536
|
+
const eventResult = await recordLocalAlignmentEvent({
|
|
4537
|
+
api: params.api,
|
|
4538
|
+
appId: binding.currentAppId,
|
|
4539
|
+
eventKind: "sync_local",
|
|
4540
|
+
branch,
|
|
4541
|
+
collabLaneId: binding.laneId,
|
|
4542
|
+
baseRevisionId: baselineServerRevisionId,
|
|
4543
|
+
targetRevisionId: delta.targetRevisionId ?? null,
|
|
4544
|
+
resultRevisionId: delta.targetRevisionId ?? null,
|
|
4545
|
+
baseHeadHash: baselineServerHeadHash,
|
|
4546
|
+
targetHeadCommitId: delta.targetHeadCommitId,
|
|
4547
|
+
targetHeadHash: delta.targetHeadHash,
|
|
4548
|
+
resultHeadHash: delta.targetHeadHash,
|
|
4549
|
+
changedFilesCount: delta.stats.changedFilesCount,
|
|
4550
|
+
insertions: delta.stats.insertions,
|
|
4551
|
+
deletions: delta.stats.deletions,
|
|
4552
|
+
localCommitCount: 0,
|
|
4553
|
+
summary: "Synced local checkout with Remix.",
|
|
4554
|
+
idempotencyKey: buildDeterministicIdempotencyKey({
|
|
4555
|
+
kind: "collab_sync_local_alignment_v1",
|
|
4556
|
+
appId: binding.currentAppId,
|
|
4557
|
+
laneId: binding.laneId,
|
|
4558
|
+
baseRevisionId: baselineServerRevisionId,
|
|
4559
|
+
targetRevisionId: delta.targetRevisionId ?? null,
|
|
4560
|
+
baseHeadHash: baselineServerHeadHash,
|
|
4561
|
+
targetHeadHash: delta.targetHeadHash,
|
|
4562
|
+
diffSha256: delta.diffSha256
|
|
4563
|
+
})
|
|
4564
|
+
});
|
|
4221
4565
|
return {
|
|
4222
4566
|
...previewResult,
|
|
4223
4567
|
status: "delta_ready",
|
|
4224
4568
|
localCommitHash: snapshot.localCommitHash,
|
|
4225
4569
|
applied: true,
|
|
4226
4570
|
dryRun: false,
|
|
4227
|
-
...warnings.length > 0 ? { warnings } : {}
|
|
4571
|
+
...[...warnings, ...reportResult.warnings, ...eventResult.warnings].length > 0 ? { warnings: [...warnings, ...reportResult.warnings, ...eventResult.warnings] } : {}
|
|
4228
4572
|
};
|
|
4229
4573
|
}
|
|
4230
4574
|
);
|
|
@@ -4322,38 +4666,38 @@ async function collabApprove(params) {
|
|
|
4322
4666
|
}
|
|
4323
4667
|
|
|
4324
4668
|
// src/application/collab/checkoutWorkspace.ts
|
|
4325
|
-
import
|
|
4669
|
+
import fs7 from "fs/promises";
|
|
4326
4670
|
import os4 from "os";
|
|
4327
|
-
import
|
|
4671
|
+
import path8 from "path";
|
|
4328
4672
|
async function pathExists(targetPath) {
|
|
4329
4673
|
try {
|
|
4330
|
-
await
|
|
4674
|
+
await fs7.access(targetPath);
|
|
4331
4675
|
return true;
|
|
4332
4676
|
} catch {
|
|
4333
4677
|
return false;
|
|
4334
4678
|
}
|
|
4335
4679
|
}
|
|
4336
4680
|
async function statIsDirectory(targetPath) {
|
|
4337
|
-
const stats = await
|
|
4681
|
+
const stats = await fs7.stat(targetPath).catch(() => null);
|
|
4338
4682
|
return Boolean(stats?.isDirectory());
|
|
4339
4683
|
}
|
|
4340
4684
|
async function findContainingGitRoot(startPath) {
|
|
4341
|
-
let current =
|
|
4685
|
+
let current = path8.resolve(startPath);
|
|
4342
4686
|
while (true) {
|
|
4343
|
-
if (await pathExists(
|
|
4344
|
-
const parent =
|
|
4687
|
+
if (await pathExists(path8.join(current, ".git"))) return current;
|
|
4688
|
+
const parent = path8.dirname(current);
|
|
4345
4689
|
if (parent === current) return null;
|
|
4346
4690
|
current = parent;
|
|
4347
4691
|
}
|
|
4348
4692
|
}
|
|
4349
4693
|
function isSubpath(parentPath, candidatePath) {
|
|
4350
|
-
const relative =
|
|
4351
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
4694
|
+
const relative = path8.relative(parentPath, candidatePath);
|
|
4695
|
+
return relative === "" || !relative.startsWith("..") && !path8.isAbsolute(relative);
|
|
4352
4696
|
}
|
|
4353
4697
|
async function resolveCheckoutDestination(params) {
|
|
4354
4698
|
if (params.outputDir?.trim()) {
|
|
4355
|
-
const preferredRepoRoot =
|
|
4356
|
-
const parentDir2 =
|
|
4699
|
+
const preferredRepoRoot = path8.resolve(params.outputDir.trim());
|
|
4700
|
+
const parentDir2 = path8.dirname(preferredRepoRoot);
|
|
4357
4701
|
if (!await statIsDirectory(parentDir2)) {
|
|
4358
4702
|
throw new RemixError("Remix output parent directory does not exist.", {
|
|
4359
4703
|
exitCode: 2,
|
|
@@ -4366,7 +4710,7 @@ async function resolveCheckoutDestination(params) {
|
|
|
4366
4710
|
explicitOutputDir: true
|
|
4367
4711
|
};
|
|
4368
4712
|
}
|
|
4369
|
-
const parentDir =
|
|
4713
|
+
const parentDir = path8.resolve(params.cwd);
|
|
4370
4714
|
if (!await statIsDirectory(parentDir)) {
|
|
4371
4715
|
throw new RemixError("Remix output parent directory does not exist.", {
|
|
4372
4716
|
exitCode: 2,
|
|
@@ -4374,7 +4718,7 @@ async function resolveCheckoutDestination(params) {
|
|
|
4374
4718
|
});
|
|
4375
4719
|
}
|
|
4376
4720
|
return {
|
|
4377
|
-
preferredRepoRoot:
|
|
4721
|
+
preferredRepoRoot: path8.join(parentDir, params.defaultDirName),
|
|
4378
4722
|
parentDir,
|
|
4379
4723
|
explicitOutputDir: false
|
|
4380
4724
|
};
|
|
@@ -4408,11 +4752,11 @@ async function materializeAppCheckout(params) {
|
|
|
4408
4752
|
explicitOutputDir: destination.explicitOutputDir
|
|
4409
4753
|
});
|
|
4410
4754
|
const repoRoot = destination.explicitOutputDir ? await reserveDirectory(destination.preferredRepoRoot) : await reserveAvailableDirPath(destination.preferredRepoRoot);
|
|
4411
|
-
const bundleTempDir = await
|
|
4412
|
-
const bundlePath =
|
|
4755
|
+
const bundleTempDir = await fs7.mkdtemp(path8.join(os4.tmpdir(), "remix-checkout-"));
|
|
4756
|
+
const bundlePath = path8.join(bundleTempDir, "repository.bundle");
|
|
4413
4757
|
try {
|
|
4414
4758
|
const bundle = await params.api.downloadAppBundle(params.appId);
|
|
4415
|
-
await
|
|
4759
|
+
await fs7.writeFile(bundlePath, bundle.data);
|
|
4416
4760
|
await cloneGitBundleToDirectory(bundlePath, repoRoot);
|
|
4417
4761
|
if (params.expectedBranchName?.trim()) {
|
|
4418
4762
|
await checkoutLocalBranch(repoRoot, params.expectedBranchName.trim());
|
|
@@ -4422,11 +4766,11 @@ async function materializeAppCheckout(params) {
|
|
|
4422
4766
|
}
|
|
4423
4767
|
await ensureGitInfoExcludeEntries(repoRoot, [".remix/"]);
|
|
4424
4768
|
} catch (err) {
|
|
4425
|
-
await
|
|
4769
|
+
await fs7.rm(repoRoot, { recursive: true, force: true }).catch(() => {
|
|
4426
4770
|
});
|
|
4427
4771
|
throw err;
|
|
4428
4772
|
} finally {
|
|
4429
|
-
await
|
|
4773
|
+
await fs7.rm(bundleTempDir, { recursive: true, force: true });
|
|
4430
4774
|
}
|
|
4431
4775
|
const branchName = await getCurrentBranch(repoRoot) ?? params.expectedBranchName?.trim() ?? null;
|
|
4432
4776
|
const remoteUrl = normalizeGitRemote(params.expectedRemoteUrl ?? await getRemoteOriginUrl(repoRoot));
|
|
@@ -4704,16 +5048,16 @@ async function collabUpdateMemberRole(params) {
|
|
|
4704
5048
|
}
|
|
4705
5049
|
|
|
4706
5050
|
// src/application/collab/collabInit.ts
|
|
4707
|
-
import
|
|
4708
|
-
import
|
|
5051
|
+
import fs12 from "fs/promises";
|
|
5052
|
+
import path11 from "path";
|
|
4709
5053
|
|
|
4710
5054
|
// src/shared/hash.ts
|
|
4711
5055
|
import crypto from "crypto";
|
|
4712
|
-
import
|
|
5056
|
+
import fs8 from "fs";
|
|
4713
5057
|
async function sha256FileHex(filePath) {
|
|
4714
5058
|
const hash = crypto.createHash("sha256");
|
|
4715
5059
|
await new Promise((resolve, reject) => {
|
|
4716
|
-
const stream =
|
|
5060
|
+
const stream = fs8.createReadStream(filePath);
|
|
4717
5061
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
4718
5062
|
stream.on("error", reject);
|
|
4719
5063
|
stream.on("end", () => resolve());
|
|
@@ -5024,11 +5368,11 @@ function branchBindingFromLane(lane, mode, fallback) {
|
|
|
5024
5368
|
}
|
|
5025
5369
|
|
|
5026
5370
|
// src/application/collab/collabInitAsync.ts
|
|
5027
|
-
import { randomUUID as
|
|
5371
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
5028
5372
|
|
|
5029
5373
|
// src/infrastructure/collab/drainerLog.ts
|
|
5030
|
-
import
|
|
5031
|
-
import
|
|
5374
|
+
import fs9 from "fs/promises";
|
|
5375
|
+
import path9 from "path";
|
|
5032
5376
|
async function logDrainerEvent(jobId, event, fields = {}) {
|
|
5033
5377
|
const entry = {
|
|
5034
5378
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -5037,8 +5381,8 @@ async function logDrainerEvent(jobId, event, fields = {}) {
|
|
|
5037
5381
|
...fields
|
|
5038
5382
|
};
|
|
5039
5383
|
try {
|
|
5040
|
-
await
|
|
5041
|
-
await
|
|
5384
|
+
await fs9.mkdir(getLogsRoot(), { recursive: true });
|
|
5385
|
+
await fs9.appendFile(getDrainerLogPath(), `${JSON.stringify(entry)}
|
|
5042
5386
|
`, "utf8");
|
|
5043
5387
|
} catch {
|
|
5044
5388
|
}
|
|
@@ -5118,7 +5462,7 @@ async function clearFailedAsyncInitJobs(params) {
|
|
|
5118
5462
|
}
|
|
5119
5463
|
async function enqueueInitPostJob(params) {
|
|
5120
5464
|
const job = await enqueueAsyncJob({
|
|
5121
|
-
id:
|
|
5465
|
+
id: randomUUID5(),
|
|
5122
5466
|
kind: "init_post",
|
|
5123
5467
|
status: "queued",
|
|
5124
5468
|
repoRoot: params.repoRoot,
|
|
@@ -5143,19 +5487,19 @@ async function enqueueInitPostJob(params) {
|
|
|
5143
5487
|
}
|
|
5144
5488
|
|
|
5145
5489
|
// src/application/collab/collabInitImport.ts
|
|
5146
|
-
import
|
|
5147
|
-
import
|
|
5490
|
+
import fs11 from "fs/promises";
|
|
5491
|
+
import path10 from "path";
|
|
5148
5492
|
|
|
5149
5493
|
// src/shared/upload.ts
|
|
5150
|
-
import
|
|
5494
|
+
import fs10 from "fs";
|
|
5151
5495
|
import { PassThrough } from "stream";
|
|
5152
5496
|
async function uploadPresigned(params) {
|
|
5153
|
-
const stats = await
|
|
5497
|
+
const stats = await fs10.promises.stat(params.filePath).catch(() => null);
|
|
5154
5498
|
if (!stats || !stats.isFile()) {
|
|
5155
5499
|
throw new RemixError("Upload file not found.", { exitCode: 2 });
|
|
5156
5500
|
}
|
|
5157
5501
|
const totalBytes = stats.size;
|
|
5158
|
-
const fileStream =
|
|
5502
|
+
const fileStream = fs10.createReadStream(params.filePath);
|
|
5159
5503
|
const pass = new PassThrough();
|
|
5160
5504
|
let sentBytes = 0;
|
|
5161
5505
|
fileStream.on("data", (chunk) => {
|
|
@@ -5182,8 +5526,8 @@ ${text}`.trim() || null
|
|
|
5182
5526
|
|
|
5183
5527
|
// src/application/collab/collabInitImport.ts
|
|
5184
5528
|
async function uploadInitBundle(params) {
|
|
5185
|
-
const bundleName = params.bundleName ??
|
|
5186
|
-
const bundleSize = (await
|
|
5529
|
+
const bundleName = params.bundleName ?? path10.basename(params.bundlePath);
|
|
5530
|
+
const bundleSize = (await fs11.stat(params.bundlePath)).size;
|
|
5187
5531
|
const presignResp = await params.api.presignImportUploadFirstParty({
|
|
5188
5532
|
file: {
|
|
5189
5533
|
name: bundleName,
|
|
@@ -5352,7 +5696,7 @@ async function collabInit(params) {
|
|
|
5352
5696
|
appId: boundCurrentAppId2,
|
|
5353
5697
|
dashboardUrl: buildDashboardAppUrl(boundCurrentAppId2),
|
|
5354
5698
|
upstreamAppId: boundUpstreamAppId2,
|
|
5355
|
-
bindingPath:
|
|
5699
|
+
bindingPath: path11.join(repoRoot, ".remix", "config.json"),
|
|
5356
5700
|
repoRoot,
|
|
5357
5701
|
repoFingerprint,
|
|
5358
5702
|
bindingMode: defaultBranch && branchName !== defaultBranch ? "lane" : "explicit_root",
|
|
@@ -5623,7 +5967,7 @@ async function collabInit(params) {
|
|
|
5623
5967
|
repoRoot,
|
|
5624
5968
|
"repository.bundle"
|
|
5625
5969
|
);
|
|
5626
|
-
const tmpBundleDir =
|
|
5970
|
+
const tmpBundleDir = path11.dirname(bundleFilePath);
|
|
5627
5971
|
try {
|
|
5628
5972
|
const bundleSha2 = await sha256FileHex(bundleFilePath);
|
|
5629
5973
|
const uploadId2 = await uploadInitBundle({
|
|
@@ -5635,7 +5979,7 @@ async function collabInit(params) {
|
|
|
5635
5979
|
const imported2 = await importUploadedInitBundle({
|
|
5636
5980
|
api: params.api,
|
|
5637
5981
|
uploadId: uploadId2,
|
|
5638
|
-
appName: params.appName?.trim() ||
|
|
5982
|
+
appName: params.appName?.trim() || path11.basename(repoRoot),
|
|
5639
5983
|
profile: params.profile ?? void 0,
|
|
5640
5984
|
branch: defaultBranch && branchName && branchName !== defaultBranch ? defaultBranch : currentBranch ?? void 0,
|
|
5641
5985
|
remoteUrl,
|
|
@@ -5794,7 +6138,7 @@ async function collabInit(params) {
|
|
|
5794
6138
|
...warnings.length > 0 ? { warnings } : {}
|
|
5795
6139
|
};
|
|
5796
6140
|
} finally {
|
|
5797
|
-
await
|
|
6141
|
+
await fs12.rm(tmpBundleDir, { recursive: true, force: true }).catch(() => void 0);
|
|
5798
6142
|
}
|
|
5799
6143
|
}
|
|
5800
6144
|
const { bundlePath, headCommitHash } = await createGitBundle(repoRoot, "repository.bundle");
|
|
@@ -5808,7 +6152,7 @@ async function collabInit(params) {
|
|
|
5808
6152
|
const imported = await importUploadedInitBundle({
|
|
5809
6153
|
api: params.api,
|
|
5810
6154
|
uploadId,
|
|
5811
|
-
appName: params.appName?.trim() ||
|
|
6155
|
+
appName: params.appName?.trim() || path11.basename(repoRoot),
|
|
5812
6156
|
path: params.path?.trim() || void 0,
|
|
5813
6157
|
profile: params.profile ?? void 0,
|
|
5814
6158
|
branch: defaultBranch && branchName && branchName !== defaultBranch ? defaultBranch : currentBranch ?? void 0,
|
|
@@ -6017,9 +6361,9 @@ async function collabList(params) {
|
|
|
6017
6361
|
}
|
|
6018
6362
|
|
|
6019
6363
|
// src/application/collab/collabReconcile.ts
|
|
6020
|
-
import
|
|
6364
|
+
import fs13 from "fs/promises";
|
|
6021
6365
|
import os5 from "os";
|
|
6022
|
-
import
|
|
6366
|
+
import path12 from "path";
|
|
6023
6367
|
import { execa as execa2 } from "execa";
|
|
6024
6368
|
|
|
6025
6369
|
// src/application/collab/pendingFinalize.ts
|
|
@@ -6187,12 +6531,12 @@ async function reconcileBothChanged(params) {
|
|
|
6187
6531
|
const replay = await pollChangeStepReplay(params.api, binding.currentAppId, String(replayStart.id));
|
|
6188
6532
|
const replayDiffResp = await params.api.getChangeStepReplayDiff(binding.currentAppId, replay.id);
|
|
6189
6533
|
const replayDiff = unwrapResponseObject(replayDiffResp, "change step replay diff");
|
|
6190
|
-
const tempRoot = await
|
|
6534
|
+
const tempRoot = await fs13.mkdtemp(path12.join(os5.tmpdir(), "remix-reconcile-"));
|
|
6191
6535
|
let serverHeadSnapshot = null;
|
|
6192
6536
|
let mergedSnapshot = null;
|
|
6193
6537
|
try {
|
|
6194
|
-
const tempRepoRoot =
|
|
6195
|
-
await
|
|
6538
|
+
const tempRepoRoot = path12.join(tempRoot, "repo");
|
|
6539
|
+
await fs13.mkdir(tempRepoRoot, { recursive: true });
|
|
6196
6540
|
await execa2("git", ["init"], { cwd: tempRepoRoot, stderr: "ignore" });
|
|
6197
6541
|
await materializeLocalSnapshot(baseline.lastSnapshotId, tempRepoRoot);
|
|
6198
6542
|
if (shouldApplyServerDeltaBeforeReplay({ deltaStatus: delta.status, diff: delta.diff })) {
|
|
@@ -6214,7 +6558,7 @@ async function reconcileBothChanged(params) {
|
|
|
6214
6558
|
branchName: binding.branchName
|
|
6215
6559
|
});
|
|
6216
6560
|
} finally {
|
|
6217
|
-
await
|
|
6561
|
+
await fs13.rm(tempRoot, { recursive: true, force: true }).catch(() => void 0);
|
|
6218
6562
|
}
|
|
6219
6563
|
if (!serverHeadSnapshot || !mergedSnapshot) {
|
|
6220
6564
|
throw new RemixError("Failed to materialize the reconciled local workspace.", { exitCode: 1 });
|
|
@@ -6256,15 +6600,58 @@ async function reconcileBothChanged(params) {
|
|
|
6256
6600
|
lastServerHeadHash: appHead.headCommitHash,
|
|
6257
6601
|
lastSeenLocalCommitHash: restoredSnapshot.localCommitHash
|
|
6258
6602
|
});
|
|
6603
|
+
const reportResult = await reportAlignedCheckoutState({
|
|
6604
|
+
api: params.api,
|
|
6605
|
+
appId: binding.currentAppId,
|
|
6606
|
+
repoRoot: lockedRepoRoot,
|
|
6607
|
+
repoFingerprint: binding.repoFingerprint,
|
|
6608
|
+
laneId: binding.laneId,
|
|
6609
|
+
branch,
|
|
6610
|
+
baselineRevisionId: appHead.headRevisionId ?? null,
|
|
6611
|
+
serverRevisionId: appHead.headRevisionId ?? null,
|
|
6612
|
+
localHeadHash: restoredSnapshot.localCommitHash,
|
|
6613
|
+
serverHeadCommitId: appHead.headCommitId,
|
|
6614
|
+
serverHeadHash: appHead.headCommitHash,
|
|
6615
|
+
source: "reconcile_apply"
|
|
6616
|
+
});
|
|
6617
|
+
const eventResult = await recordLocalAlignmentEvent({
|
|
6618
|
+
api: params.api,
|
|
6619
|
+
appId: binding.currentAppId,
|
|
6620
|
+
eventKind: "reconcile_local",
|
|
6621
|
+
branch,
|
|
6622
|
+
collabLaneId: binding.laneId,
|
|
6623
|
+
baseRevisionId: baseline.lastServerRevisionId,
|
|
6624
|
+
targetRevisionId: appHead.headRevisionId ?? null,
|
|
6625
|
+
resultRevisionId: appHead.headRevisionId ?? null,
|
|
6626
|
+
baseHeadHash: baseline.lastServerHeadHash,
|
|
6627
|
+
targetHeadCommitId: appHead.headCommitId,
|
|
6628
|
+
targetHeadHash: appHead.headCommitHash,
|
|
6629
|
+
resultHeadHash: appHead.headCommitHash,
|
|
6630
|
+
changedFilesCount: diffResult.stats.changedFilesCount,
|
|
6631
|
+
insertions: diffResult.stats.insertions,
|
|
6632
|
+
deletions: diffResult.stats.deletions,
|
|
6633
|
+
localCommitCount: 0,
|
|
6634
|
+
summary: "Reconciled local checkout with Remix.",
|
|
6635
|
+
idempotencyKey: buildDeterministicIdempotencyKey({
|
|
6636
|
+
kind: "collab_reconcile_local_alignment_v1",
|
|
6637
|
+
appId: binding.currentAppId,
|
|
6638
|
+
laneId: binding.laneId,
|
|
6639
|
+
baseRevisionId: baseline.lastServerRevisionId,
|
|
6640
|
+
targetRevisionId: appHead.headRevisionId ?? null,
|
|
6641
|
+
baseHeadHash: baseline.lastServerHeadHash,
|
|
6642
|
+
targetHeadHash: appHead.headCommitHash,
|
|
6643
|
+
localDiffSha256: diffResult.diffSha256,
|
|
6644
|
+
replayId: replay.id
|
|
6645
|
+
})
|
|
6646
|
+
});
|
|
6647
|
+
const mergedWarnings = Array.from(/* @__PURE__ */ new Set([...delta.warnings, ...warnings, ...reportResult.warnings, ...eventResult.warnings]));
|
|
6259
6648
|
return {
|
|
6260
6649
|
...preview,
|
|
6261
6650
|
status: "reconciled",
|
|
6262
6651
|
localHeadCommitHash: restoredSnapshot.localCommitHash,
|
|
6263
6652
|
applied: workspaceChanged,
|
|
6264
6653
|
dryRun: false,
|
|
6265
|
-
...
|
|
6266
|
-
warnings: Array.from(/* @__PURE__ */ new Set([...delta.warnings, ...warnings]))
|
|
6267
|
-
} : {}
|
|
6654
|
+
...mergedWarnings.length > 0 ? { warnings: mergedWarnings } : {}
|
|
6268
6655
|
};
|
|
6269
6656
|
}
|
|
6270
6657
|
);
|
|
@@ -6842,6 +7229,8 @@ async function collabStatus(params) {
|
|
|
6842
7229
|
if ((status.remote.incomingOpenMergeRequestCount ?? 0) > 0 && status.recommendedAction === "no_action") {
|
|
6843
7230
|
status.recommendedAction = "review_queue";
|
|
6844
7231
|
}
|
|
7232
|
+
const reportResult = await reportCheckoutStateFromStatus({ api: params.api, status, source: "status" });
|
|
7233
|
+
for (const warning of reportResult.warnings) addWarning(status, warning);
|
|
6845
7234
|
return status;
|
|
6846
7235
|
}
|
|
6847
7236
|
|
|
@@ -6945,11 +7334,11 @@ async function collabView(params) {
|
|
|
6945
7334
|
}
|
|
6946
7335
|
|
|
6947
7336
|
// src/application/collab/collabAsyncProcessing.ts
|
|
6948
|
-
import
|
|
6949
|
-
import
|
|
7337
|
+
import fs14 from "fs/promises";
|
|
7338
|
+
import path13 from "path";
|
|
6950
7339
|
|
|
6951
7340
|
// src/application/collab/collabDependencies.ts
|
|
6952
|
-
import { randomUUID as
|
|
7341
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
6953
7342
|
function isFullLocalStateRepository(value) {
|
|
6954
7343
|
return typeof value.bindings?.getPath === "function" && typeof value.bindings.read === "function" && typeof value.bindings.readState === "function" && typeof value.bindings.write === "function" && typeof value.bindings.writeSnapshot === "function" && typeof value.baselines?.read === "function" && typeof value.baselines.write === "function" && typeof value.baselines.clear === "function" && typeof value.snapshots?.inspect === "function" && typeof value.snapshots.capture === "function" && typeof value.snapshots.read === "function" && typeof value.snapshots.materialize === "function" && typeof value.snapshots.restoreToWorktree === "function" && typeof value.snapshots.diff === "function" && typeof value.asyncJobs?.enqueue === "function" && typeof value.asyncJobs.read === "function" && typeof value.asyncJobs.list === "function" && typeof value.asyncJobs.listForRepo === "function" && typeof value.asyncJobs.findPending === "function" && typeof value.asyncJobs.findFailed === "function" && typeof value.asyncJobs.update === "function" && typeof value.asyncJobs.delete === "function" && typeof value.asyncJobs.claim === "function" && typeof value.asyncJobs.summarize === "function" && typeof value.asyncJobs.pruneTerminal === "function" && typeof value.asyncJobs.getBundleFilePath === "function" && typeof value.asyncJobs.await === "function" && typeof value.finalizeJobs?.enqueue === "function" && typeof value.finalizeJobs.read === "function" && typeof value.finalizeJobs.list === "function" && typeof value.finalizeJobs.update === "function" && typeof value.finalizeJobs.claim === "function" && typeof value.finalizeJobs.remove === "function" && typeof value.finalizeJobs.forget === "function" && typeof value.finalizeJobs.requeue === "function" && typeof value.finalizeJobs.heartbeatLock === "function" && typeof value.finalizeJobs.cleanStaleLocks === "function" && typeof value.finalizeJobs.prune === "function" && typeof value.finalizeJobs.summarize === "function";
|
|
6955
7344
|
}
|
|
@@ -6964,7 +7353,7 @@ function createCollabDependencies(overrides = {}) {
|
|
|
6964
7353
|
const localState3 = overrides.localState ? isFullLocalStateRepository(overrides.localState) ? overrides.localState : createLocalStateRepository(overrides.localState) : createLocalStateRepository();
|
|
6965
7354
|
return {
|
|
6966
7355
|
clock: { ...defaultClock, ...overrides.clock },
|
|
6967
|
-
ids: { randomUUID:
|
|
7356
|
+
ids: { randomUUID: randomUUID6, ...overrides.ids },
|
|
6968
7357
|
timers: { ...defaultTimers, ...overrides.timers },
|
|
6969
7358
|
git: overrides.git ?? createSystemGitAdapter(),
|
|
6970
7359
|
localState: localState3,
|
|
@@ -7086,10 +7475,10 @@ async function processInitJob(job, api) {
|
|
|
7086
7475
|
try {
|
|
7087
7476
|
await localState2.asyncJobs.update(job.id, { status: "submitting", error: null });
|
|
7088
7477
|
await logDrainerWorkflowEvent(job.id, "claimed", { kind: "init" });
|
|
7089
|
-
const bundleStat = await
|
|
7478
|
+
const bundleStat = await fs14.stat(job.payload.bundlePath);
|
|
7090
7479
|
const presignResp = await api.presignImportUploadFirstParty({
|
|
7091
7480
|
file: {
|
|
7092
|
-
name:
|
|
7481
|
+
name: path13.basename(job.payload.bundlePath),
|
|
7093
7482
|
mimeType: "application/x-git-bundle",
|
|
7094
7483
|
size: bundleStat.size,
|
|
7095
7484
|
checksumSha256: job.payload.bundleSha256
|
|
@@ -7106,7 +7495,7 @@ async function processInitJob(job, api) {
|
|
|
7106
7495
|
await localState2.asyncJobs.update(job.id, { status: "server_processing" });
|
|
7107
7496
|
const importResp = await api.importFromUploadFirstParty({
|
|
7108
7497
|
uploadId: String(presign.uploadId),
|
|
7109
|
-
appName: job.payload.appName?.trim() ||
|
|
7498
|
+
appName: job.payload.appName?.trim() || path13.basename(job.repoRoot),
|
|
7110
7499
|
platform: "generic",
|
|
7111
7500
|
isPublic: false,
|
|
7112
7501
|
branch: job.payload.defaultBranch && job.branchName && job.branchName !== job.payload.defaultBranch ? job.payload.defaultBranch : job.branchName ?? void 0,
|
|
@@ -7312,7 +7701,7 @@ async function processInitPostJob(job, api) {
|
|
|
7312
7701
|
if (outcome.status === "failed") {
|
|
7313
7702
|
const bindingPath = localState2.bindings.getPath(job.repoRoot);
|
|
7314
7703
|
try {
|
|
7315
|
-
await
|
|
7704
|
+
await fs14.unlink(bindingPath);
|
|
7316
7705
|
await logDrainerWorkflowEvent(job.id, "binding_cleared", {
|
|
7317
7706
|
kind: "init_post",
|
|
7318
7707
|
appId: job.payload.appId,
|
|
@@ -7364,9 +7753,9 @@ async function collabInitPostProcess(jobId, opts) {
|
|
|
7364
7753
|
}
|
|
7365
7754
|
async function acquireDrainerPidLock() {
|
|
7366
7755
|
const pidPath = getDrainerPidPath();
|
|
7367
|
-
await
|
|
7756
|
+
await fs14.mkdir(path13.dirname(pidPath), { recursive: true });
|
|
7368
7757
|
try {
|
|
7369
|
-
const existing = await
|
|
7758
|
+
const existing = await fs14.readFile(pidPath, "utf8").catch(() => "");
|
|
7370
7759
|
const existingPid = parseInt(existing.trim(), 10);
|
|
7371
7760
|
if (Number.isFinite(existingPid) && existingPid > 0 && existingPid !== process.pid) {
|
|
7372
7761
|
try {
|
|
@@ -7376,13 +7765,13 @@ async function acquireDrainerPidLock() {
|
|
|
7376
7765
|
if (error?.code !== "ESRCH") return null;
|
|
7377
7766
|
}
|
|
7378
7767
|
}
|
|
7379
|
-
await
|
|
7768
|
+
await fs14.writeFile(pidPath, String(process.pid), "utf8");
|
|
7380
7769
|
return {
|
|
7381
7770
|
release: async () => {
|
|
7382
7771
|
try {
|
|
7383
|
-
const current = (await
|
|
7772
|
+
const current = (await fs14.readFile(pidPath, "utf8")).trim();
|
|
7384
7773
|
if (current === String(process.pid)) {
|
|
7385
|
-
await
|
|
7774
|
+
await fs14.unlink(pidPath).catch(() => void 0);
|
|
7386
7775
|
}
|
|
7387
7776
|
} catch {
|
|
7388
7777
|
}
|
|
@@ -732,6 +732,49 @@ type CollabApiClient = {
|
|
|
732
732
|
defaultBranch?: string;
|
|
733
733
|
dryRun?: boolean;
|
|
734
734
|
}): Promise<unknown>;
|
|
735
|
+
reportLocalCheckoutState(appId: string, payload: {
|
|
736
|
+
checkoutId: string;
|
|
737
|
+
collabLaneId?: string;
|
|
738
|
+
branch?: string;
|
|
739
|
+
repoFingerprint?: string;
|
|
740
|
+
localState?: string;
|
|
741
|
+
recommendedAction: "pull" | "reconcile" | "await_finalize" | "record" | "no_action";
|
|
742
|
+
materializationStatus?: string;
|
|
743
|
+
alignmentRequired?: string;
|
|
744
|
+
baselineRevisionId?: string | null;
|
|
745
|
+
localRevisionId?: string | null;
|
|
746
|
+
serverRevisionId?: string | null;
|
|
747
|
+
localHeadHash?: string;
|
|
748
|
+
serverHeadCommitId?: string | null;
|
|
749
|
+
serverHeadHash?: string;
|
|
750
|
+
hasLocalChanges?: boolean;
|
|
751
|
+
hasUnrecordedChanges?: boolean;
|
|
752
|
+
pendingFinalizeCount?: number;
|
|
753
|
+
lastSeenAt?: string;
|
|
754
|
+
metadata?: Record<string, unknown>;
|
|
755
|
+
}): Promise<unknown>;
|
|
756
|
+
getLatestLocalCheckoutState(appId: string): Promise<unknown>;
|
|
757
|
+
recordLocalAlignmentEvent(appId: string, payload: {
|
|
758
|
+
eventKind: "sync_local" | "reconcile_local";
|
|
759
|
+
branch?: string;
|
|
760
|
+
collabLaneId?: string;
|
|
761
|
+
baseRevisionId?: string | null;
|
|
762
|
+
targetRevisionId?: string | null;
|
|
763
|
+
resultRevisionId?: string | null;
|
|
764
|
+
baseHeadCommitId?: string | null;
|
|
765
|
+
baseHeadHash?: string;
|
|
766
|
+
targetHeadCommitId?: string | null;
|
|
767
|
+
targetHeadHash?: string;
|
|
768
|
+
resultHeadCommitId?: string | null;
|
|
769
|
+
resultHeadHash?: string;
|
|
770
|
+
changedFilesCount?: number;
|
|
771
|
+
insertions?: number;
|
|
772
|
+
deletions?: number;
|
|
773
|
+
localCommitCount?: number;
|
|
774
|
+
summary?: string;
|
|
775
|
+
idempotencyKey?: string;
|
|
776
|
+
metadata?: Record<string, unknown>;
|
|
777
|
+
}): Promise<unknown>;
|
|
735
778
|
};
|
|
736
779
|
|
|
737
780
|
export type { AppProfileInput as A, ModelCall as B, CollabApiClient as C, OrganizationMemberRole as D, ProjectMemberRole as E, SyncLocalResponse as F, SyncUpstreamResponse as G, TurnUsageCaptureSource as H, InvitationScopeType as I, JsonObject as J, TurnUsageConfidence as K, TurnUsagePreviousPatch as L, MergeRequestQueue as M, OrganizationMember as O, ProjectMember as P, ReconcilePreflightResponse as R, ServerToolUsage as S, TurnUsage as T, TurnUsagePayload as a, CollabFinalizeTurnResult as b, CollabRecordingPreflight as c, CollabApproveMode as d, CollabApprovalStrategy as e, CollabApproveResult as f, MergeRequest as g, CollabMember as h, AppDeltaResponse as i, CollabStatus as j, MergeRequestReview as k, AppHeadResponse as l, AppMember as m, AppMemberRole as n, AppReconcileResponse as o, CollabFinalizeTurnAutoSync as p, CollabFinalizeTurnMode as q, CollabPendingFinalizeState as r, CollabPendingFinalizeSummary as s, CollabRecordingPreflightStatus as t, CollabRepoStateKind as u, CollabStatusBlockedReason as v, CollabStatusRecommendedAction as w, CollabTurn as x, MembershipScopeType as y, MergeRequestStatus as z };
|
package/dist/history.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -4,4 +4,4 @@ export { S as SessionStore, a as StoredSession, W as WithRefreshLock, c as creat
|
|
|
4
4
|
export { createDefaultRefreshLock, createLocalSessionStore, createSupabaseAuthHelpers, defaultSessionFilePath, isInvalidGrantError, isNetworkError } from './auth.js';
|
|
5
5
|
export { AgentMemoryItem, AgentMemoryKind, AgentMemorySearchItem, AgentMemorySearchResponse, AgentMemorySummary, AgentMemoryTimelineResponse, ApiClient, AppContext, AppContextAccessPath, AppPreviewExpectedKind, AppPreviewProcessStatus, AppPreviewQuery, AppPreviewResponse, AppReconcileResponse, AppSandboxCommandRun, AppShareLinkSummary, Bundle, BundlePlatform, BundleStatus, ChangeStepDiffResponse, CreateAppShareLinkPayload, DetectProjectRuntimeTargetsPayload, ImportProjectRuntimeEnvPayload, InitiateBundleRequest, InvitationRecord, MergeRequest, MergeRequestReview, MergeRequestStatus, ProjectRuntimeEnvMetadata, ProjectRuntimeEnvScope, ProjectRuntimeTargetMetadata, ProjectRuntimeTargetScope, ProjectTrigger, ProjectTriggerPayload, ProjectTriggerScope, ProjectTriggerStep, ProjectTriggerStepPayload, ReconcilePreflightResponse, ResolveProjectRuntimeEnvForLocalPullResponse, RunAppRuntimeTargetPayload, RunAppSandboxCommandPayload, RunAppTriggerEventPayload, RunAppTriggerPayload, RuntimeCommandKind, RuntimeTargetKind, SetProjectRuntimeEnvPayload, SetProjectRuntimeTargetPayload, SyncLocalResponse, SyncUpstreamResponse, TriggerEventMetadata, TriggerEventSource, TriggerIntegrationStatus, TriggerMode, TriggerRun, TriggerStepRun, TriggerStepType, UpdateProjectTriggerPayload, createApiClient } from './api.js';
|
|
6
6
|
import 'zod';
|
|
7
|
-
import './contracts-
|
|
7
|
+
import './contracts-DTeSJnoC.js';
|
package/dist/index.js
CHANGED