@remixhq/core 0.1.34 → 0.1.36

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 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-WCYiMqwB.js';
3
+ import { T as TurnUsage } from './contracts-BqC3Lj7W.js';
4
4
  import 'zod';
5
5
 
6
6
  type HistoryImportProvider = "claude_code" | "cursor";
@@ -373,6 +373,14 @@ type AppPreviewQuery = {
373
373
  autostart?: boolean;
374
374
  probe?: "metadata" | "full";
375
375
  };
376
+ type AppShareLinkSummary = {
377
+ id: string;
378
+ url: string;
379
+ };
380
+ type CreateAppShareLinkPayload = {
381
+ targetId?: string;
382
+ autostart?: boolean;
383
+ };
376
384
  type AppPreviewProcessStatus = "running" | "starting" | "stopped" | "exited";
377
385
  type AppPreviewExpectedKind = "url" | "qr" | "api" | "logs";
378
386
  type AppPreviewResponse = {
@@ -697,6 +705,7 @@ type ApiClient = {
697
705
  environment?: string;
698
706
  }): Promise<Json>;
699
707
  getAppPreview(appId: string, params?: AppPreviewQuery): Promise<Json>;
708
+ createAppShareLink(appId: string, payload?: CreateAppShareLinkPayload): Promise<Json>;
700
709
  runAppSandboxCommand(appId: string, payload: RunAppSandboxCommandPayload): Promise<Json>;
701
710
  listAppSandboxCommandHistory(appId: string, params?: {
702
711
  limit?: number;
@@ -1126,6 +1135,12 @@ type ApiClient = {
1126
1135
  createdBefore?: string;
1127
1136
  }): Promise<Json>;
1128
1137
  getSandboxStatus(appId: string): Promise<Json>;
1138
+ editAgentApp(payload: {
1139
+ app_id: string;
1140
+ thread_id: string;
1141
+ prompt: string;
1142
+ idempotencyKey?: string;
1143
+ }): Promise<Json>;
1129
1144
  importHistory(payload: ImportHistoryRequest): Promise<ImportHistoryResponse>;
1130
1145
  };
1131
1146
  declare function createApiClient(config: CoreConfig, opts?: {
@@ -1147,4 +1162,4 @@ declare function createApiClient(config: CoreConfig, opts?: {
1147
1162
  defaultRequestTimeoutMs?: number;
1148
1163
  }): ApiClient;
1149
1164
 
1150
- export { type AgentMemoryItem, type AgentMemoryKind, type AgentMemorySearchItem, type AgentMemorySearchResponse, type AgentMemorySummary, type AgentMemoryTimelineResponse, type ApiClient, type AppContext, type AppContextAccessPath, type AppPreviewExpectedKind, type AppPreviewProcessStatus, type AppPreviewQuery, type AppPreviewResponse, type AppProfileInput, type AppReconcileResponse, type AppSandboxCommandRun, type Bundle, type BundlePlatform, type BundleStatus, type ChangeStepDiffResponse, type DetectProjectRuntimeTargetsPayload, type HistoricalTurnRecord, type HistoryImportCaptureSource, type HistoryImportProvider, type HistoryImportRecordMetadata, type HistoryImportWorkspaceMetadata, type ImportHistoryRecordOutcome, type ImportHistoryRequest, type ImportHistoryResponse, type ImportProjectRuntimeEnvPayload, type InitiateBundleRequest, type InvitationRecord, type MergeRequest, type MergeRequestReview, type MergeRequestStatus, type ProjectRuntimeEnvMetadata, type ProjectRuntimeEnvScope, type ProjectRuntimeTargetMetadata, type ProjectRuntimeTargetScope, type ProjectTrigger, type ProjectTriggerPayload, type ProjectTriggerScope, type ProjectTriggerStep, type ProjectTriggerStepPayload, type ReconcilePreflightResponse, type ResolveProjectRuntimeEnvForLocalPullResponse, type RunAppRuntimeTargetPayload, type RunAppSandboxCommandPayload, type RunAppTriggerEventPayload, type RunAppTriggerPayload, type RuntimeCommandKind, type RuntimeTargetKind, type SetProjectRuntimeEnvPayload, type SetProjectRuntimeTargetPayload, type SyncLocalResponse, type SyncUpstreamResponse, type TriggerEventMetadata, type TriggerEventSource, type TriggerIntegrationStatus, type TriggerMode, type TriggerRun, type TriggerStepRun, type TriggerStepType, type UpdateProjectTriggerPayload, createApiClient };
1165
+ export { type AgentMemoryItem, type AgentMemoryKind, type AgentMemorySearchItem, type AgentMemorySearchResponse, type AgentMemorySummary, type AgentMemoryTimelineResponse, type ApiClient, type AppContext, type AppContextAccessPath, type AppPreviewExpectedKind, type AppPreviewProcessStatus, type AppPreviewQuery, type AppPreviewResponse, type AppProfileInput, type AppReconcileResponse, type AppSandboxCommandRun, type AppShareLinkSummary, type Bundle, type BundlePlatform, type BundleStatus, type ChangeStepDiffResponse, type CreateAppShareLinkPayload, type DetectProjectRuntimeTargetsPayload, type HistoricalTurnRecord, type HistoryImportCaptureSource, type HistoryImportProvider, type HistoryImportRecordMetadata, type HistoryImportWorkspaceMetadata, type ImportHistoryRecordOutcome, type ImportHistoryRequest, type ImportHistoryResponse, type ImportProjectRuntimeEnvPayload, type InitiateBundleRequest, type InvitationRecord, type MergeRequest, type MergeRequestReview, type MergeRequestStatus, type ProjectRuntimeEnvMetadata, type ProjectRuntimeEnvScope, type ProjectRuntimeTargetMetadata, type ProjectRuntimeTargetScope, type ProjectTrigger, type ProjectTriggerPayload, type ProjectTriggerScope, type ProjectTriggerStep, type ProjectTriggerStepPayload, type ReconcilePreflightResponse, type ResolveProjectRuntimeEnvForLocalPullResponse, type RunAppRuntimeTargetPayload, type RunAppSandboxCommandPayload, type RunAppTriggerEventPayload, type RunAppTriggerPayload, type RuntimeCommandKind, type RuntimeTargetKind, type SetProjectRuntimeEnvPayload, type SetProjectRuntimeTargetPayload, type SyncLocalResponse, type SyncUpstreamResponse, type TriggerEventMetadata, type TriggerEventSource, type TriggerIntegrationStatus, type TriggerMode, type TriggerRun, type TriggerStepRun, type TriggerStepType, type UpdateProjectTriggerPayload, createApiClient };
package/dist/api.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createApiClient
3
- } from "./chunk-KURN7YZ5.js";
3
+ } from "./chunk-MNVBXTSV.js";
4
4
  import "./chunk-7XJGOKEO.js";
5
5
  export {
6
6
  createApiClient
@@ -279,6 +279,10 @@ function createApiClient(config, opts) {
279
279
  body: JSON.stringify(payload ?? {})
280
280
  }),
281
281
  getAppPreview: (appId, params) => request(`/v1/apps/${encodeURIComponent(appId)}/preview${buildAppPreviewQuery(params)}`, { method: "GET" }),
282
+ createAppShareLink: (appId, payload) => request(`/v1/apps/${encodeURIComponent(appId)}/share-links`, {
283
+ method: "POST",
284
+ body: JSON.stringify(payload ?? {})
285
+ }),
282
286
  runAppSandboxCommand: (appId, payload) => request(`/v1/apps/${encodeURIComponent(appId)}/sandbox/commands/run`, {
283
287
  method: "POST",
284
288
  body: JSON.stringify(payload)
@@ -584,6 +588,10 @@ function createApiClient(config, opts) {
584
588
  });
585
589
  },
586
590
  getSandboxStatus: (appId) => request(`/v1/apps/${encodeURIComponent(appId)}/sandbox/status`, { method: "GET" }),
591
+ editAgentApp: (payload) => request("/v1/agent/editApp", {
592
+ method: "POST",
593
+ body: JSON.stringify(payload)
594
+ }),
587
595
  importHistory: async (payload) => {
588
596
  const res = await request("/v1/history/import", {
589
597
  method: "POST",
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-WCYiMqwB.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-WCYiMqwB.js';
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-BqC3Lj7W.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-BqC3Lj7W.js';
3
3
  import { B as BranchBindingMode } from './binding-WiIRI2fl.js';
4
4
 
5
5
  declare function collabFinalizeTurn(params: {
package/dist/collab.js CHANGED
@@ -3240,11 +3240,174 @@ async function drainPendingFinalizeQueue(params) {
3240
3240
 
3241
3241
  // src/application/collab/collabFinalizeTurn.ts
3242
3242
  var FINALIZE_AWAIT_INIT_POST_TIMEOUT_MS = 6e4;
3243
+ var FINALIZE_UNALIGNED_DRAIN_TIMEOUT_MS = 1e4;
3243
3244
  function collectWarnings(value) {
3244
3245
  if (!Array.isArray(value)) return [];
3245
3246
  return value.filter((entry) => typeof entry === "string" && entry.trim().length > 0);
3246
3247
  }
3248
+ function throwBlockingDetectedStatus(detected) {
3249
+ if (detected.status === "not_bound") {
3250
+ throw new RemixError("Repository is not bound to Remix.", {
3251
+ code: "not_bound",
3252
+ exitCode: 2,
3253
+ hint: detected.hint
3254
+ });
3255
+ }
3256
+ if (detected.status === "branch_binding_missing") {
3257
+ throw new RemixError(detected.hint || "Current branch is not ready for Remix recording.", {
3258
+ code: detected.status,
3259
+ exitCode: 2,
3260
+ hint: detected.hint
3261
+ });
3262
+ }
3263
+ if (detected.status === "family_ambiguous") {
3264
+ throw new RemixError(detected.hint || "Current branch is not ready for Remix recording.", {
3265
+ code: detected.status,
3266
+ exitCode: 2,
3267
+ hint: detected.hint
3268
+ });
3269
+ }
3270
+ if (detected.status === "metadata_conflict" || detected.status === "branch_mismatch") {
3271
+ throw new RemixError("Repository must be realigned before finalizing the turn.", {
3272
+ code: detected.status,
3273
+ exitCode: 2,
3274
+ hint: detected.hint
3275
+ });
3276
+ }
3277
+ if (detected.status === "remote_error") {
3278
+ const message = detected.hint || "Failed to determine the current repo state.";
3279
+ throw new RemixError(message, {
3280
+ code: detected.status,
3281
+ exitCode: 1,
3282
+ hint: detected.hint
3283
+ });
3284
+ }
3285
+ }
3286
+ function withTimeout(work, timeoutMs, message) {
3287
+ let timer;
3288
+ const timeout = new Promise((_, reject) => {
3289
+ timer = setTimeout(() => reject(new Error(message)), timeoutMs);
3290
+ timer.unref?.();
3291
+ });
3292
+ return Promise.race([work, timeout]).finally(() => {
3293
+ if (timer) clearTimeout(timer);
3294
+ });
3295
+ }
3296
+ async function drainPendingFinalizeBeforeUnalignedFallback(params) {
3297
+ const summary = await summarizePendingFinalizeJobs({
3298
+ repoRoot: params.repoRoot,
3299
+ repoFingerprint: params.repoFingerprint,
3300
+ currentAppId: params.currentAppId,
3301
+ laneId: params.laneId
3302
+ });
3303
+ if (summary.activeJobCount <= 0) {
3304
+ return { attempted: false, warnings: [] };
3305
+ }
3306
+ const warnings = [];
3307
+ try {
3308
+ await withTimeout(
3309
+ drainPendingFinalizeQueue({ api: params.api }),
3310
+ FINALIZE_UNALIGNED_DRAIN_TIMEOUT_MS,
3311
+ `Timed out waiting ${Math.round(
3312
+ FINALIZE_UNALIGNED_DRAIN_TIMEOUT_MS / 1e3
3313
+ )}s for pending Remix turn recording to advance the local baseline.`
3314
+ );
3315
+ } catch (error) {
3316
+ const message = error instanceof Error ? error.message : String(error);
3317
+ warnings.push(`Pending Remix turn recording could not be drained before this turn was captured: ${message}`);
3318
+ } finally {
3319
+ invalidateAppHeadCache(params.currentAppId);
3320
+ invalidateAppDeltaCacheForApp(params.currentAppId);
3321
+ }
3322
+ return { attempted: true, warnings };
3323
+ }
3247
3324
  var FINALIZE_QUEUED_WARNING = "Queued only: the local Remix turn was captured, but no remote change step or collab turn exists yet. Drain or await finalize before merge-related flows.";
3325
+ var CONVERSATION_ONLY_WARNING = "Recorded conversation only: this turn was not materialized into a change step.";
3326
+ function buildConversationOnlyWorkspaceMetadata(params) {
3327
+ const metadata = {
3328
+ branch: params.branchName,
3329
+ repoRoot: params.repoRoot,
3330
+ remoteUrl: params.remoteUrl,
3331
+ defaultBranch: params.defaultBranch,
3332
+ recordingMode: "conversation_only",
3333
+ materializationStatus: params.materializationStatus,
3334
+ alignmentRequired: params.alignmentRequired,
3335
+ baselineSnapshotId: params.baselineSnapshotId,
3336
+ baselineServerRevisionId: params.baselineServerRevisionId,
3337
+ baselineServerHeadHash: params.baselineServerHeadHash,
3338
+ currentServerRevisionId: params.currentServerRevisionId,
3339
+ currentServerHeadHash: params.currentServerHeadHash,
3340
+ currentServerHeadCommitId: params.currentServerHeadCommitId,
3341
+ localCommitHash: params.localCommitHash,
3342
+ repoStateAtCapture: params.repoState,
3343
+ actor: params.actor ?? null
3344
+ };
3345
+ if (params.turnUsage) {
3346
+ metadata.turnUsage = params.turnUsage;
3347
+ }
3348
+ if (typeof params.promptedAt === "string" && params.promptedAt.trim()) {
3349
+ metadata.promptedAt = params.promptedAt.trim();
3350
+ }
3351
+ return metadata;
3352
+ }
3353
+ async function recordConversationOnlyTurn(params) {
3354
+ const idempotencyKey = params.explicitIdempotencyKey?.trim() || buildDeterministicIdempotencyKey({
3355
+ kind: "collab_finalize_turn_conversation_only_v1",
3356
+ appId: params.binding.currentAppId,
3357
+ laneId: params.binding.laneId,
3358
+ materializationStatus: params.materializationStatus,
3359
+ alignmentRequired: params.alignmentRequired,
3360
+ baselineSnapshotId: params.baselineSnapshotId ?? null,
3361
+ baselineServerRevisionId: params.baselineServerRevisionId ?? null,
3362
+ baselineServerHeadHash: params.baselineServerHeadHash ?? null,
3363
+ currentServerRevisionId: params.currentServerRevisionId ?? null,
3364
+ currentServerHeadHash: params.currentServerHeadHash ?? null,
3365
+ currentServerHeadCommitId: params.currentServerHeadCommitId ?? null,
3366
+ localCommitHash: params.localCommitHash ?? null,
3367
+ repoState: params.repoState,
3368
+ prompt: params.prompt,
3369
+ assistantResponse: params.assistantResponse
3370
+ });
3371
+ const collabTurnResp = await params.api.createCollabTurn(params.binding.currentAppId, {
3372
+ threadId: params.binding.threadId ?? void 0,
3373
+ collabLaneId: params.binding.laneId ?? void 0,
3374
+ prompt: params.prompt,
3375
+ assistantResponse: params.assistantResponse,
3376
+ actor: params.actor,
3377
+ workspaceMetadata: buildConversationOnlyWorkspaceMetadata({
3378
+ repoRoot: params.repoRoot,
3379
+ branchName: params.binding.branchName,
3380
+ remoteUrl: params.binding.remoteUrl,
3381
+ defaultBranch: params.binding.defaultBranch,
3382
+ baselineSnapshotId: params.baselineSnapshotId ?? null,
3383
+ baselineServerRevisionId: params.baselineServerRevisionId ?? null,
3384
+ baselineServerHeadHash: params.baselineServerHeadHash ?? null,
3385
+ currentServerRevisionId: params.currentServerRevisionId ?? null,
3386
+ currentServerHeadHash: params.currentServerHeadHash ?? null,
3387
+ currentServerHeadCommitId: params.currentServerHeadCommitId ?? null,
3388
+ localCommitHash: params.localCommitHash ?? null,
3389
+ repoState: params.repoState,
3390
+ materializationStatus: params.materializationStatus,
3391
+ alignmentRequired: params.alignmentRequired,
3392
+ actor: params.actor ?? null,
3393
+ turnUsage: params.turnUsage ?? null,
3394
+ promptedAt: params.promptedAt
3395
+ }),
3396
+ idempotencyKey
3397
+ });
3398
+ const collabTurn = unwrapResponseObject(collabTurnResp, "collab turn");
3399
+ return {
3400
+ mode: "conversation_only",
3401
+ idempotencyKey,
3402
+ queued: false,
3403
+ jobId: null,
3404
+ repoState: params.repoState,
3405
+ changeStep: null,
3406
+ collabTurn,
3407
+ autoSync: null,
3408
+ warnings: [CONVERSATION_ONLY_WARNING, ...collectWarnings(params.warnings ?? [])]
3409
+ };
3410
+ }
3248
3411
  async function collabFinalizeTurn(params) {
3249
3412
  const repoRoot = await findGitRoot(params.cwd);
3250
3413
  const binding = await ensureActiveLaneBinding({
@@ -3313,6 +3476,24 @@ async function collabFinalizeTurn(params) {
3313
3476
  ` : "") + "Run `remix collab init` again to retry \u2014 the post-init drainer cleared the local binding so this is safe."
3314
3477
  });
3315
3478
  }
3479
+ try {
3480
+ return await recordConversationOnlyTurn({
3481
+ api: params.api,
3482
+ binding,
3483
+ repoRoot,
3484
+ prompt,
3485
+ assistantResponse,
3486
+ explicitIdempotencyKey: params.idempotencyKey,
3487
+ actor: params.actor,
3488
+ turnUsage: params.turnUsage,
3489
+ promptedAt: params.promptedAt,
3490
+ repoState: "init_post_pending",
3491
+ materializationStatus: "skipped_init_post_pending",
3492
+ alignmentRequired: "init_post",
3493
+ warnings: [`Init post job ${pendingInitPost.id} is still pending; recorded conversation only.`]
3494
+ });
3495
+ } catch {
3496
+ }
3316
3497
  throw new RemixError("Timed out waiting for the initial Remix import to finish provisioning.", {
3317
3498
  exitCode: 2,
3318
3499
  hint: `Init post job ${pendingInitPost.id} did not complete within ${Math.round(
@@ -3321,67 +3502,95 @@ async function collabFinalizeTurn(params) {
3321
3502
  });
3322
3503
  }
3323
3504
  }
3324
- const detected = await collabDetectRepoState({
3505
+ let detected = await collabDetectRepoState({
3325
3506
  api: params.api,
3326
3507
  cwd: repoRoot,
3327
3508
  allowBranchMismatch: params.allowBranchMismatch
3328
3509
  });
3329
- if (detected.status === "not_bound") {
3330
- throw new RemixError("Repository is not bound to Remix.", {
3331
- code: "not_bound",
3332
- exitCode: 2,
3333
- hint: detected.hint
3334
- });
3335
- }
3336
- if (detected.status === "branch_binding_missing") {
3337
- throw new RemixError(detected.hint || "Current branch is not ready for Remix recording.", {
3338
- code: detected.status,
3339
- exitCode: 2,
3340
- hint: detected.hint
3341
- });
3342
- }
3343
- if (detected.status === "family_ambiguous") {
3344
- throw new RemixError(detected.hint || "Current branch is not ready for Remix recording.", {
3345
- code: detected.status,
3346
- exitCode: 2,
3347
- hint: detected.hint
3348
- });
3349
- }
3350
- if (detected.status === "metadata_conflict" || detected.status === "branch_mismatch") {
3351
- throw new RemixError("Repository must be realigned before finalizing the turn.", {
3352
- code: detected.status,
3353
- exitCode: 2,
3354
- hint: detected.hint
3355
- });
3356
- }
3357
- if (detected.status === "missing_head" || detected.status === "remote_error") {
3358
- const message = detected.hint || "Failed to determine the current repo state.";
3359
- throw new RemixError(message, {
3360
- code: detected.status,
3361
- exitCode: 1,
3362
- hint: detected.hint
3510
+ throwBlockingDetectedStatus(detected);
3511
+ let pendingFinalizeDrainWarnings = [];
3512
+ if (detected.repoState === "server_only_changed" || detected.repoState === "both_changed") {
3513
+ const recovery = await drainPendingFinalizeBeforeUnalignedFallback({
3514
+ api: params.api,
3515
+ repoRoot,
3516
+ repoFingerprint: binding.repoFingerprint,
3517
+ currentAppId: binding.currentAppId,
3518
+ laneId: binding.laneId
3363
3519
  });
3520
+ if (recovery.attempted) {
3521
+ pendingFinalizeDrainWarnings = recovery.warnings;
3522
+ detected = await collabDetectRepoState({
3523
+ api: params.api,
3524
+ cwd: repoRoot,
3525
+ allowBranchMismatch: params.allowBranchMismatch
3526
+ });
3527
+ throwBlockingDetectedStatus(detected);
3528
+ }
3364
3529
  }
3365
- if (detected.repoState === "server_only_changed") {
3366
- throw new RemixError("Server changes must be pulled locally before finalizing this turn.", {
3367
- code: "pull_required",
3368
- exitCode: 2,
3369
- hint: detected.hint
3530
+ if (detected.status === "missing_head") {
3531
+ return recordConversationOnlyTurn({
3532
+ api: params.api,
3533
+ binding,
3534
+ repoRoot,
3535
+ prompt,
3536
+ assistantResponse,
3537
+ explicitIdempotencyKey: params.idempotencyKey,
3538
+ actor: params.actor,
3539
+ turnUsage: params.turnUsage,
3540
+ promptedAt: params.promptedAt,
3541
+ repoState: "missing_head",
3542
+ materializationStatus: "skipped_missing_head",
3543
+ alignmentRequired: "head",
3544
+ localCommitHash: null,
3545
+ warnings: [...pendingFinalizeDrainWarnings, ...detected.warnings]
3370
3546
  });
3371
3547
  }
3372
- if (detected.repoState === "both_changed") {
3373
- const hint = detected.hint || "Run `remix collab reconcile --dry-run` to inspect recovery options before retrying.";
3374
- throw new RemixError("Local and server changes must be reconciled before finalizing this turn.", {
3375
- code: "reconcile_required",
3376
- exitCode: 2,
3377
- hint
3548
+ if (detected.repoState === "server_only_changed" || detected.repoState === "both_changed") {
3549
+ return recordConversationOnlyTurn({
3550
+ api: params.api,
3551
+ binding,
3552
+ repoRoot,
3553
+ prompt,
3554
+ assistantResponse,
3555
+ explicitIdempotencyKey: params.idempotencyKey,
3556
+ actor: params.actor,
3557
+ turnUsage: params.turnUsage,
3558
+ promptedAt: params.promptedAt,
3559
+ repoState: detected.repoState,
3560
+ materializationStatus: "skipped_unaligned",
3561
+ alignmentRequired: detected.repoState === "both_changed" ? "reconcile" : "sync",
3562
+ baselineSnapshotId: detected.baseline.lastSnapshotId,
3563
+ baselineServerRevisionId: detected.baseline.lastServerRevisionId,
3564
+ baselineServerHeadHash: detected.baseline.lastServerHeadHash,
3565
+ currentServerRevisionId: detected.currentServerRevisionId,
3566
+ currentServerHeadHash: detected.currentServerHeadHash,
3567
+ currentServerHeadCommitId: detected.currentServerHeadCommitId,
3568
+ localCommitHash: detected.localCommitHash,
3569
+ warnings: [...pendingFinalizeDrainWarnings, ...detected.warnings]
3378
3570
  });
3379
3571
  }
3380
3572
  if (detected.repoState === "external_local_base_changed") {
3381
- throw new RemixError("The local checkout is missing a Remix revision baseline for this lane.", {
3382
- code: "baseline_missing",
3383
- exitCode: 2,
3384
- hint: detected.hint
3573
+ return recordConversationOnlyTurn({
3574
+ api: params.api,
3575
+ binding,
3576
+ repoRoot,
3577
+ prompt,
3578
+ assistantResponse,
3579
+ explicitIdempotencyKey: params.idempotencyKey,
3580
+ actor: params.actor,
3581
+ turnUsage: params.turnUsage,
3582
+ promptedAt: params.promptedAt,
3583
+ repoState: "external_local_base_changed",
3584
+ materializationStatus: "skipped_baseline_missing",
3585
+ alignmentRequired: "baseline",
3586
+ baselineSnapshotId: detected.baseline.lastSnapshotId,
3587
+ baselineServerRevisionId: detected.baseline.lastServerRevisionId,
3588
+ baselineServerHeadHash: detected.baseline.lastServerHeadHash,
3589
+ currentServerRevisionId: detected.currentServerRevisionId,
3590
+ currentServerHeadHash: detected.currentServerHeadHash,
3591
+ currentServerHeadCommitId: detected.currentServerHeadCommitId,
3592
+ localCommitHash: detected.localCommitHash,
3593
+ warnings: [...pendingFinalizeDrainWarnings, ...detected.warnings]
3385
3594
  });
3386
3595
  }
3387
3596
  const baseline = await readLocalBaseline({
@@ -3390,10 +3599,27 @@ async function collabFinalizeTurn(params) {
3390
3599
  repoRoot
3391
3600
  });
3392
3601
  if (!baseline) {
3393
- throw new RemixError("Local Remix baseline is missing for this lane.", {
3394
- code: "baseline_missing",
3395
- exitCode: 2,
3396
- hint: "Run `remix collab init` or sync this lane to create a fresh revision baseline."
3602
+ return recordConversationOnlyTurn({
3603
+ api: params.api,
3604
+ binding,
3605
+ repoRoot,
3606
+ prompt,
3607
+ assistantResponse,
3608
+ explicitIdempotencyKey: params.idempotencyKey,
3609
+ actor: params.actor,
3610
+ turnUsage: params.turnUsage,
3611
+ promptedAt: params.promptedAt,
3612
+ repoState: "baseline_missing",
3613
+ materializationStatus: "skipped_baseline_missing",
3614
+ alignmentRequired: "baseline",
3615
+ baselineSnapshotId: detected.baseline.lastSnapshotId,
3616
+ baselineServerRevisionId: detected.baseline.lastServerRevisionId,
3617
+ baselineServerHeadHash: detected.baseline.lastServerHeadHash,
3618
+ currentServerRevisionId: detected.currentServerRevisionId,
3619
+ currentServerHeadHash: detected.currentServerHeadHash,
3620
+ currentServerHeadCommitId: detected.currentServerHeadCommitId,
3621
+ localCommitHash: detected.localCommitHash,
3622
+ warnings: [...pendingFinalizeDrainWarnings, ...detected.warnings]
3397
3623
  });
3398
3624
  }
3399
3625
  const snapshot = await captureLocalSnapshot({
@@ -3451,7 +3677,7 @@ async function collabFinalizeTurn(params) {
3451
3677
  changeStep: null,
3452
3678
  collabTurn: null,
3453
3679
  autoSync: null,
3454
- warnings: [FINALIZE_QUEUED_WARNING, ...collectWarnings(detected.warnings)]
3680
+ warnings: [FINALIZE_QUEUED_WARNING, ...collectWarnings([...pendingFinalizeDrainWarnings, ...detected.warnings])]
3455
3681
  };
3456
3682
  }
3457
3683
 
@@ -135,7 +135,7 @@ type MergeRequestReview = {
135
135
  type CollabApproveMode = "remote-only" | "sync-target-repo";
136
136
  type CollabApprovalStrategy = "ai_patch_apply" | "git_merge_auto_resolve" | "git_merge_manual_resolution";
137
137
  type CollabStatusBlockedReason = "not_git_repo" | "not_bound" | "branch_binding_missing" | "family_ambiguous" | "missing_head" | "detached_head" | "branch_mismatch" | "dirty_worktree" | "baseline_missing" | "metadata_conflict" | "remote_error";
138
- type CollabRepoStateKind = "idle" | "local_only_changed" | "server_only_changed" | "both_changed" | "external_local_base_changed" | "metadata_conflict" | "binding_problem";
138
+ type CollabRepoStateKind = "idle" | "local_only_changed" | "server_only_changed" | "both_changed" | "external_local_base_changed" | "baseline_missing" | "missing_head" | "init_post_pending" | "metadata_conflict" | "binding_problem";
139
139
  type CollabPendingFinalizeState = "idle" | "queued" | "processing" | "retry_scheduled" | "awaiting_usage" | "failed";
140
140
  type CollabPendingFinalizeSummary = {
141
141
  state: CollabPendingFinalizeState;
@@ -382,7 +382,7 @@ type CollabTurn = {
382
382
  prompt: string | null;
383
383
  assistantResponse: string | null;
384
384
  };
385
- type CollabFinalizeTurnMode = "changed_turn" | "no_diff_turn";
385
+ type CollabFinalizeTurnMode = "changed_turn" | "no_diff_turn" | "conversation_only";
386
386
  type CollabFinalizeTurnAutoSync = {
387
387
  requested: boolean;
388
388
  eligible: boolean;
package/dist/history.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { T as TurnUsage } from './contracts-WCYiMqwB.js';
1
+ import { T as TurnUsage } from './contracts-BqC3Lj7W.js';
2
2
 
3
3
  type TranscriptEvent = Record<string, unknown>;
4
4
  type ReadTranscriptResult = {
package/dist/index.d.ts CHANGED
@@ -2,6 +2,6 @@ export { CliError, REMIX_ERROR_CODES, CliError as RemixError, RemixErrorCode } f
2
2
  export { CoreConfig, ResolveConfigOptions, configSchema, resolveConfig } from './config.js';
3
3
  export { S as SessionStore, a as StoredSession, W as WithRefreshLock, c as createRefreshLock, b as createStoredSessionTokenProvider, s as shouldRefreshSoon, d as storedSessionSchema } from './tokenProvider-B9so5Pm3.js';
4
4
  export { createDefaultRefreshLock, createLocalSessionStore, createSupabaseAuthHelpers, defaultSessionFilePath, isInvalidGrantError, isNetworkError } from './auth.js';
5
- export { AgentMemoryItem, AgentMemoryKind, AgentMemorySearchItem, AgentMemorySearchResponse, AgentMemorySummary, AgentMemoryTimelineResponse, ApiClient, AppContext, AppContextAccessPath, AppPreviewExpectedKind, AppPreviewProcessStatus, AppPreviewQuery, AppPreviewResponse, AppReconcileResponse, AppSandboxCommandRun, Bundle, BundlePlatform, BundleStatus, ChangeStepDiffResponse, 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';
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-WCYiMqwB.js';
7
+ import './contracts-BqC3Lj7W.js';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createApiClient
3
- } from "./chunk-KURN7YZ5.js";
3
+ } from "./chunk-MNVBXTSV.js";
4
4
  import {
5
5
  createDefaultRefreshLock,
6
6
  createLocalSessionStore,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remixhq/core",
3
- "version": "0.1.34",
3
+ "version": "0.1.36",
4
4
  "description": "Remix core library",
5
5
  "homepage": "https://github.com/RemixDotOne/remix-core",
6
6
  "license": "MIT",