repomind 0.3.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +1512 -835
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -9638,14 +9638,14 @@ var require_react_reconciler_production = __commonJS({
9638
9638
  }
9639
9639
  var exports2 = {};
9640
9640
  "use strict";
9641
- var React19 = require_react(), Scheduler2 = require_scheduler(), assign = Object.assign, REACT_LEGACY_ELEMENT_TYPE = Symbol.for("react.element"), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy");
9641
+ var React20 = require_react(), Scheduler2 = require_scheduler(), assign = Object.assign, REACT_LEGACY_ELEMENT_TYPE = Symbol.for("react.element"), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy");
9642
9642
  Symbol.for("react.scope");
9643
9643
  var REACT_ACTIVITY_TYPE = Symbol.for("react.activity");
9644
9644
  Symbol.for("react.legacy_hidden");
9645
9645
  Symbol.for("react.tracing_marker");
9646
9646
  var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel");
9647
9647
  Symbol.for("react.view_transition");
9648
- var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals = React19.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, rendererVersion = $$$config.rendererVersion, rendererPackageName = $$$config.rendererPackageName, extraDevToolsConfig = $$$config.extraDevToolsConfig, getPublicInstance = $$$config.getPublicInstance, getRootHostContext = $$$config.getRootHostContext, getChildHostContext = $$$config.getChildHostContext, prepareForCommit = $$$config.prepareForCommit, resetAfterCommit = $$$config.resetAfterCommit, createInstance = $$$config.createInstance;
9648
+ var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals = React20.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, rendererVersion = $$$config.rendererVersion, rendererPackageName = $$$config.rendererPackageName, extraDevToolsConfig = $$$config.extraDevToolsConfig, getPublicInstance = $$$config.getPublicInstance, getRootHostContext = $$$config.getRootHostContext, getChildHostContext = $$$config.getChildHostContext, prepareForCommit = $$$config.prepareForCommit, resetAfterCommit = $$$config.resetAfterCommit, createInstance = $$$config.createInstance;
9649
9649
  $$$config.cloneMutableInstance;
9650
9650
  var appendInitialChild = $$$config.appendInitialChild, finalizeInitialChildren = $$$config.finalizeInitialChildren, shouldSetTextContent = $$$config.shouldSetTextContent, createTextInstance = $$$config.createTextInstance;
9651
9651
  $$$config.cloneMutableTextInstance;
@@ -22238,14 +22238,14 @@ var require_react_reconciler_development = __commonJS({
22238
22238
  }
22239
22239
  var exports2 = {};
22240
22240
  "use strict";
22241
- var React19 = require_react(), Scheduler2 = require_scheduler(), assign = Object.assign, REACT_LEGACY_ELEMENT_TYPE = Symbol.for("react.element"), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy");
22241
+ var React20 = require_react(), Scheduler2 = require_scheduler(), assign = Object.assign, REACT_LEGACY_ELEMENT_TYPE = Symbol.for("react.element"), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy");
22242
22242
  Symbol.for("react.scope");
22243
22243
  var REACT_ACTIVITY_TYPE = Symbol.for("react.activity");
22244
22244
  Symbol.for("react.legacy_hidden");
22245
22245
  Symbol.for("react.tracing_marker");
22246
22246
  var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel");
22247
22247
  Symbol.for("react.view_transition");
22248
- var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals = React19.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, rendererVersion = $$$config.rendererVersion, rendererPackageName = $$$config.rendererPackageName, extraDevToolsConfig = $$$config.extraDevToolsConfig, getPublicInstance = $$$config.getPublicInstance, getRootHostContext = $$$config.getRootHostContext, getChildHostContext = $$$config.getChildHostContext, prepareForCommit = $$$config.prepareForCommit, resetAfterCommit = $$$config.resetAfterCommit, createInstance = $$$config.createInstance;
22248
+ var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals = React20.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, rendererVersion = $$$config.rendererVersion, rendererPackageName = $$$config.rendererPackageName, extraDevToolsConfig = $$$config.extraDevToolsConfig, getPublicInstance = $$$config.getPublicInstance, getRootHostContext = $$$config.getRootHostContext, getChildHostContext = $$$config.getChildHostContext, prepareForCommit = $$$config.prepareForCommit, resetAfterCommit = $$$config.resetAfterCommit, createInstance = $$$config.createInstance;
22249
22249
  $$$config.cloneMutableInstance;
22250
22250
  var appendInitialChild = $$$config.appendInitialChild, finalizeInitialChildren = $$$config.finalizeInitialChildren, shouldSetTextContent = $$$config.shouldSetTextContent, createTextInstance = $$$config.createTextInstance;
22251
22251
  $$$config.cloneMutableTextInstance;
@@ -30234,18 +30234,18 @@ var require_react_jsx_runtime_development = __commonJS({
30234
30234
  function isValidElement(object) {
30235
30235
  return "object" === typeof object && null !== object && object.$$typeof === REACT_ELEMENT_TYPE;
30236
30236
  }
30237
- var React19 = require_react(), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React19.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
30237
+ var React20 = require_react(), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React20.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
30238
30238
  return null;
30239
30239
  };
30240
- React19 = {
30240
+ React20 = {
30241
30241
  react_stack_bottom_frame: function(callStackForError) {
30242
30242
  return callStackForError();
30243
30243
  }
30244
30244
  };
30245
30245
  var specialPropKeyWarningShown;
30246
30246
  var didWarnAboutElementRef = {};
30247
- var unknownOwnerDebugStack = React19.react_stack_bottom_frame.bind(
30248
- React19,
30247
+ var unknownOwnerDebugStack = React20.react_stack_bottom_frame.bind(
30248
+ React20,
30249
30249
  UnknownOwner
30250
30250
  )();
30251
30251
  var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
@@ -30322,6 +30322,26 @@ function parseNumstat(line) {
30322
30322
  };
30323
30323
  }
30324
30324
  var HUNK_HEADER_RE = /^@@\s+-(\d+)(?:,(\d+))?\s+\+(\d+)(?:,(\d+))?\s+@@\s*(.*)/;
30325
+ function annotatePairs(lines) {
30326
+ let pairIdx = 0;
30327
+ let i = 0;
30328
+ while (i < lines.length) {
30329
+ if (lines[i].type !== "deletion") {
30330
+ i++;
30331
+ continue;
30332
+ }
30333
+ const delStart = i;
30334
+ while (i < lines.length && lines[i].type === "deletion") i++;
30335
+ const addStart = i;
30336
+ while (i < lines.length && lines[i].type === "addition") i++;
30337
+ if (addStart < i) {
30338
+ for (let j = delStart; j < i; j++) {
30339
+ lines[j].pairIndex = pairIdx;
30340
+ }
30341
+ pairIdx++;
30342
+ }
30343
+ }
30344
+ }
30325
30345
  function parseHunks(patch) {
30326
30346
  if (!patch.trim()) return [];
30327
30347
  const hunks = [];
@@ -30335,6 +30355,7 @@ function parseHunks(patch) {
30335
30355
  const headerMatch = line.match(HUNK_HEADER_RE);
30336
30356
  if (headerMatch) {
30337
30357
  if (currentHunk) {
30358
+ annotatePairs(currentHunk.lines);
30338
30359
  currentHunk.content = hunkLines.join("\n");
30339
30360
  hunks.push(currentHunk);
30340
30361
  }
@@ -30387,6 +30408,7 @@ function parseHunks(patch) {
30387
30408
  }
30388
30409
  }
30389
30410
  if (currentHunk) {
30411
+ annotatePairs(currentHunk.lines);
30390
30412
  currentHunk.content = hunkLines.join("\n");
30391
30413
  hunks.push(currentHunk);
30392
30414
  }
@@ -30736,7 +30758,21 @@ async function applyPatch(patch) {
30736
30758
  throw new GitError(`Failed to apply patch: ${stderr.trim()}`);
30737
30759
  }
30738
30760
  }
30739
- function buildSelectivePatch(fullPatch, lineSelections) {
30761
+ function expandForPairs(selectedIndices, hunkLines) {
30762
+ const pairsNeeded = /* @__PURE__ */ new Set();
30763
+ for (const idx of selectedIndices) {
30764
+ const pi = hunkLines[idx]?.pairIndex;
30765
+ if (pi !== void 0) pairsNeeded.add(pi);
30766
+ }
30767
+ if (pairsNeeded.size === 0) return selectedIndices;
30768
+ const expanded = new Set(selectedIndices);
30769
+ for (let i = 0; i < hunkLines.length; i++) {
30770
+ const pi = hunkLines[i].pairIndex;
30771
+ if (pi !== void 0 && pairsNeeded.has(pi)) expanded.add(i);
30772
+ }
30773
+ return expanded;
30774
+ }
30775
+ function buildSelectivePatch(fullPatch, lineSelections, parsedHunks) {
30740
30776
  const selectionMap = /* @__PURE__ */ new Map();
30741
30777
  for (const sel of lineSelections) {
30742
30778
  const existing = selectionMap.get(sel.hunkIndex);
@@ -30748,37 +30784,48 @@ function buildSelectivePatch(fullPatch, lineSelections) {
30748
30784
  }
30749
30785
  const fileDiffs = parseDiff(fullPatch);
30750
30786
  if (fileDiffs.length === 0) return "";
30787
+ const hunks = parsedHunks ?? parseHunks(fullPatch);
30751
30788
  const fullHunkIds = [];
30752
30789
  const linePatches = [];
30790
+ let globalHunkIdx = 0;
30753
30791
  for (const file of fileDiffs) {
30754
30792
  for (let i = 0; i < file.hunks.length; i++) {
30755
30793
  const hunk = file.hunks[i];
30756
- const selectedIndices = selectionMap.get(i);
30757
- if (!selectedIndices) continue;
30758
- const changeLineIndices = [];
30759
- let changeIdx = 0;
30760
- for (let li = 0; li < hunk.lines.length; li++) {
30761
- const line = hunk.lines[li];
30762
- if (line.type === "added" || line.type === "removed") {
30763
- changeIdx++;
30764
- if (selectedIndices.has(li)) {
30765
- changeLineIndices.push(changeIdx);
30766
- }
30767
- }
30768
- }
30769
- const totalChangeLines = hunk.lines.filter(
30770
- (l) => l.type === "added" || l.type === "removed"
30771
- ).length;
30772
- if (changeLineIndices.length === totalChangeLines) {
30773
- fullHunkIds.push(hunk.id);
30774
- } else if (changeLineIndices.length > 0) {
30775
- const patch = buildPatchFromLines(
30776
- fileDiffs,
30777
- hunk.id,
30778
- changeLineIndices
30779
- );
30780
- linePatches.push(patch);
30794
+ let selectedIndices = selectionMap.get(globalHunkIdx);
30795
+ if (selectedIndices) {
30796
+ const hunkFromParser = hunks.find((h) => h.index === globalHunkIdx);
30797
+ if (hunkFromParser) {
30798
+ selectedIndices = expandForPairs(
30799
+ selectedIndices,
30800
+ hunkFromParser.lines
30801
+ );
30802
+ }
30803
+ const changeLineIndices = [];
30804
+ let changeIdx = 0;
30805
+ for (let li = 0; li < hunk.lines.length; li++) {
30806
+ const line = hunk.lines[li];
30807
+ if (line.type === "added" || line.type === "removed") {
30808
+ changeIdx++;
30809
+ if (selectedIndices.has(li)) {
30810
+ changeLineIndices.push(changeIdx);
30811
+ }
30812
+ }
30813
+ }
30814
+ const totalChangeLines = hunk.lines.filter(
30815
+ (l) => l.type === "added" || l.type === "removed"
30816
+ ).length;
30817
+ if (changeLineIndices.length === totalChangeLines) {
30818
+ fullHunkIds.push(hunk.id);
30819
+ } else if (changeLineIndices.length > 0) {
30820
+ const patch = buildPatchFromLines(
30821
+ fileDiffs,
30822
+ hunk.id,
30823
+ changeLineIndices
30824
+ );
30825
+ linePatches.push(patch);
30826
+ }
30781
30827
  }
30828
+ globalHunkIdx++;
30782
30829
  }
30783
30830
  }
30784
30831
  let result = "";
@@ -30812,12 +30859,15 @@ async function stageHunks(fullPatch, hunkIndices) {
30812
30859
  }
30813
30860
  async function stageLines(fullPatch, lineSelections) {
30814
30861
  const patch = buildSelectivePatch(fullPatch, lineSelections);
30815
- if (!patch) return;
30862
+ if (!patch) return { usedFallback: false };
30816
30863
  const valid = await validatePatch(patch);
30817
30864
  if (!valid) {
30818
- throw new GitError("Generated patch is invalid");
30865
+ const affectedHunks = [...new Set(lineSelections.map((s) => s.hunkIndex))];
30866
+ await stageHunks(fullPatch, affectedHunks);
30867
+ return { usedFallback: true };
30819
30868
  }
30820
30869
  await applyPatch(patch);
30870
+ return { usedFallback: false };
30821
30871
  }
30822
30872
 
30823
30873
  // ../../packages/git/src/index.ts
@@ -30937,6 +30987,7 @@ async function readStagedFiles(files) {
30937
30987
 
30938
30988
  // src/lib/api-client.ts
30939
30989
  var FETCH_TIMEOUT_MS = 3e4;
30990
+ var STREAM_TIMEOUT_MS = 3e5;
30940
30991
  var DEFAULT_BASE_URL = "https://api.repomind.dev";
30941
30992
  var DEBUG = process.argv.includes("--verbose") || process.argv.includes("-v") || !!process.env.REPOMIND_DEBUG;
30942
30993
  var ApiError = class extends Error {
@@ -30956,7 +31007,7 @@ var PlanLimitError = class extends Error {
30956
31007
  }
30957
31008
  };
30958
31009
  function createApiClient(baseUrl = DEFAULT_BASE_URL, fetchFn = fetch) {
30959
- async function request(method, path, token, body) {
31010
+ async function request(method, path, token, body, timeoutMs) {
30960
31011
  let res;
30961
31012
  try {
30962
31013
  res = await fetchFn(`${baseUrl}${path}`, {
@@ -30966,7 +31017,7 @@ function createApiClient(baseUrl = DEFAULT_BASE_URL, fetchFn = fetch) {
30966
31017
  ...token ? { Authorization: `Bearer ${token}` } : {}
30967
31018
  },
30968
31019
  ...body !== void 0 ? { body: JSON.stringify(body) } : {},
30969
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
31020
+ signal: AbortSignal.timeout(timeoutMs ?? FETCH_TIMEOUT_MS)
30970
31021
  });
30971
31022
  } catch (err) {
30972
31023
  if (DEBUG) console.error("[api-client] network error:", err);
@@ -30994,13 +31045,50 @@ function createApiClient(baseUrl = DEFAULT_BASE_URL, fetchFn = fetch) {
30994
31045
  }
30995
31046
  return res.json();
30996
31047
  }
31048
+ async function postStream(path, body, token, timeoutMs) {
31049
+ let res;
31050
+ try {
31051
+ res = await fetchFn(`${baseUrl}${path}`, {
31052
+ method: "POST",
31053
+ headers: {
31054
+ "Content-Type": "application/json",
31055
+ Accept: "text/event-stream",
31056
+ ...token ? { Authorization: `Bearer ${token}` } : {}
31057
+ },
31058
+ body: JSON.stringify(body),
31059
+ signal: AbortSignal.timeout(timeoutMs ?? STREAM_TIMEOUT_MS)
31060
+ });
31061
+ } catch (err) {
31062
+ if (DEBUG) console.error("[api-client] postStream network error:", err);
31063
+ throw new ApiError(
31064
+ 0,
31065
+ err instanceof Error ? err.message : "network error"
31066
+ );
31067
+ }
31068
+ if (!res.ok) {
31069
+ const errBody = await res.json().catch(() => ({}));
31070
+ if (DEBUG)
31071
+ console.error(`[api-client] POST ${path} \u2192 ${res.status}`, errBody);
31072
+ if (res.status === 402 && errBody.error === "plan_limit_reached") {
31073
+ throw new PlanLimitError(
31074
+ String(errBody.plan ?? "free"),
31075
+ Number(errBody.used ?? 0),
31076
+ Number(errBody.limit ?? 0)
31077
+ );
31078
+ }
31079
+ const msg = errBody.detail ? `${errBody.error}: ${errBody.detail}` : String(errBody.error ?? "request failed");
31080
+ throw new ApiError(res.status, msg);
31081
+ }
31082
+ return res;
31083
+ }
30997
31084
  return {
30998
- post(path, body, token) {
30999
- return request("POST", path, token, body);
31085
+ post(path, body, token, timeoutMs) {
31086
+ return request("POST", path, token, body, timeoutMs);
31000
31087
  },
31001
31088
  get(path, token) {
31002
31089
  return request("GET", path, token);
31003
- }
31090
+ },
31091
+ postStream
31004
31092
  };
31005
31093
  }
31006
31094
  var apiClient = createApiClient();
@@ -31463,12 +31551,12 @@ var loadYoga = (() => {
31463
31551
  }
31464
31552
  return d;
31465
31553
  }
31466
- var ia, ja, A, C, ka, D, E, la, ma;
31554
+ var ia, ja, A, C2, ka, D, E, la, ma;
31467
31555
  function na() {
31468
31556
  var a = fa.buffer;
31469
31557
  ia = a;
31470
31558
  h.HEAP8 = ja = new Int8Array(a);
31471
- h.HEAP16 = C = new Int16Array(a);
31559
+ h.HEAP16 = C2 = new Int16Array(a);
31472
31560
  h.HEAP32 = D = new Int32Array(a);
31473
31561
  h.HEAPU8 = A = new Uint8Array(a);
31474
31562
  h.HEAPU16 = ka = new Uint16Array(a);
@@ -31899,7 +31987,7 @@ var loadYoga = (() => {
31899
31987
  };
31900
31988
  case 1:
31901
31989
  return c ? function(d) {
31902
- return C[d >> 1];
31990
+ return C2[d >> 1];
31903
31991
  } : function(d) {
31904
31992
  return ka[d >> 1];
31905
31993
  };
@@ -31915,7 +32003,7 @@ var loadYoga = (() => {
31915
32003
  }
31916
32004
  function tb(a, b) {
31917
32005
  for (var c = "", d = 0; !(d >= b / 2); ++d) {
31918
- var e = C[a + 2 * d >> 1];
32006
+ var e = C2[a + 2 * d >> 1];
31919
32007
  if (0 == e) break;
31920
32008
  c += String.fromCharCode(e);
31921
32009
  }
@@ -31927,8 +32015,8 @@ var loadYoga = (() => {
31927
32015
  c -= 2;
31928
32016
  var d = b;
31929
32017
  c = c < 2 * a.length ? c / 2 : a.length;
31930
- for (var e = 0; e < c; ++e) C[b >> 1] = a.charCodeAt(e), b += 2;
31931
- C[b >> 1] = 0;
32018
+ for (var e = 0; e < c; ++e) C2[b >> 1] = a.charCodeAt(e), b += 2;
32019
+ C2[b >> 1] = 0;
31932
32020
  return b - d;
31933
32021
  }
31934
32022
  function vb(a) {
@@ -32182,7 +32270,7 @@ var loadYoga = (() => {
32182
32270
  argPackAdvance: 8,
32183
32271
  readValueFromPointer: function(g) {
32184
32272
  if (1 === c) var k = ja;
32185
- else if (2 === c) k = C;
32273
+ else if (2 === c) k = C2;
32186
32274
  else if (4 === c) k = D;
32187
32275
  else throw new TypeError("Unknown boolean type size: " + b);
32188
32276
  return this.fromWireType(k[g >> f]);
@@ -39162,7 +39250,7 @@ var import_react27 = __toESM(require_react(), 1);
39162
39250
  var import_react28 = __toESM(require_react(), 1);
39163
39251
 
39164
39252
  // src/commands/commit.ts
39165
- var import_react31 = __toESM(require_react(), 1);
39253
+ var import_react34 = __toESM(require_react(), 1);
39166
39254
 
39167
39255
  // src/lib/auth.ts
39168
39256
  import { mkdirSync, readFileSync as readFileSync2, rmSync, writeFileSync } from "node:fs";
@@ -39215,6 +39303,22 @@ function saveTokenToPath(path, token, expiresAt) {
39215
39303
  writeFileSync(path, JSON.stringify(data), { mode: 384 });
39216
39304
  }
39217
39305
 
39306
+ // src/lib/immersive.ts
39307
+ var ENTER_ALT = "\x1B[?1049h";
39308
+ var EXIT_ALT = "\x1B[?1049l";
39309
+ var CLEAR = "\x1B[2J\x1B[H";
39310
+ function onProcessExit() {
39311
+ process.stdout.write(EXIT_ALT);
39312
+ }
39313
+ function enterImmersive() {
39314
+ process.stdout.write(ENTER_ALT + CLEAR);
39315
+ process.once("exit", onProcessExit);
39316
+ }
39317
+ function exitImmersive() {
39318
+ process.off("exit", onProcessExit);
39319
+ process.stdout.write(EXIT_ALT);
39320
+ }
39321
+
39218
39322
  // src/lib/repo-config.ts
39219
39323
  import { readFile } from "node:fs/promises";
39220
39324
  import { join as join2 } from "node:path";
@@ -39252,30 +39356,410 @@ function Spinner({ type = "dots" }) {
39252
39356
  var build_default = Spinner;
39253
39357
 
39254
39358
  // src/ui/commit-app.tsx
39359
+ var import_react32 = __toESM(require_react(), 1);
39360
+
39361
+ // src/hooks/use-pipeline-stream.ts
39255
39362
  var import_react30 = __toESM(require_react(), 1);
39256
39363
 
39257
- // src/ui/components/header.tsx
39364
+ // src/lib/sse-parser.ts
39365
+ async function* parseSSEStream(stream) {
39366
+ const reader = stream.getReader();
39367
+ const decoder = new TextDecoder();
39368
+ let buffer = "";
39369
+ try {
39370
+ while (true) {
39371
+ const { done, value } = await reader.read();
39372
+ if (done) break;
39373
+ buffer += decoder.decode(value, { stream: true });
39374
+ const parts = buffer.split("\n\n");
39375
+ buffer = parts.pop() ?? "";
39376
+ for (const part of parts) {
39377
+ const trimmed = part.trim();
39378
+ if (!trimmed || trimmed.startsWith(":")) continue;
39379
+ let data;
39380
+ for (const line of trimmed.split("\n")) {
39381
+ if (line.startsWith("data: ")) {
39382
+ data = line.slice(6);
39383
+ }
39384
+ }
39385
+ if (data) {
39386
+ try {
39387
+ yield JSON.parse(data);
39388
+ } catch {
39389
+ }
39390
+ }
39391
+ }
39392
+ }
39393
+ } finally {
39394
+ reader.releaseLock();
39395
+ }
39396
+ }
39397
+
39398
+ // src/hooks/use-pipeline-stream.ts
39399
+ function usePipelineStream(options) {
39400
+ const [steps, setSteps] = (0, import_react30.useState)([]);
39401
+ const [result, setResult] = (0, import_react30.useState)(null);
39402
+ const [error, setError] = (0, import_react30.useState)(null);
39403
+ const [isStreaming, setIsStreaming] = (0, import_react30.useState)(false);
39404
+ const activeStepIndexRef = (0, import_react30.useRef)(null);
39405
+ const stepStartTimeRef = (0, import_react30.useRef)(0);
39406
+ const elapsedIntervalRef = (0, import_react30.useRef)(
39407
+ null
39408
+ );
39409
+ const abortRef = (0, import_react30.useRef)(null);
39410
+ function clearElapsedInterval() {
39411
+ if (elapsedIntervalRef.current !== null) {
39412
+ clearInterval(elapsedIntervalRef.current);
39413
+ elapsedIntervalRef.current = null;
39414
+ }
39415
+ }
39416
+ function startElapsedTimer(stepIdx) {
39417
+ clearElapsedInterval();
39418
+ activeStepIndexRef.current = stepIdx;
39419
+ stepStartTimeRef.current = Date.now();
39420
+ elapsedIntervalRef.current = setInterval(() => {
39421
+ const elapsed = (Date.now() - stepStartTimeRef.current) / 1e3;
39422
+ const detail = `${elapsed.toFixed(1)}s`;
39423
+ setSteps(
39424
+ (prev) => prev.map(
39425
+ (s, i) => i === activeStepIndexRef.current ? { ...s, detail } : s
39426
+ )
39427
+ );
39428
+ }, 100);
39429
+ }
39430
+ (0, import_react30.useEffect)(() => {
39431
+ if (!options) return;
39432
+ let cancelled = false;
39433
+ const controller = new AbortController();
39434
+ abortRef.current = controller;
39435
+ setIsStreaming(true);
39436
+ setSteps([]);
39437
+ setResult(null);
39438
+ setError(null);
39439
+ async function run2() {
39440
+ if (!options) return;
39441
+ let response;
39442
+ try {
39443
+ response = await options.postStream(
39444
+ options.path,
39445
+ options.body,
39446
+ options.token,
39447
+ options.timeoutMs
39448
+ );
39449
+ } catch (err) {
39450
+ if (cancelled) return;
39451
+ setError(err instanceof Error ? err.message : "request failed");
39452
+ setIsStreaming(false);
39453
+ return;
39454
+ }
39455
+ if (cancelled) return;
39456
+ const contentType = response.headers.get("Content-Type") ?? "";
39457
+ if (contentType.includes("application/json")) {
39458
+ try {
39459
+ const data = await response.json();
39460
+ if (!cancelled) {
39461
+ setResult(data);
39462
+ setIsStreaming(false);
39463
+ }
39464
+ } catch (err) {
39465
+ if (!cancelled) {
39466
+ setError(
39467
+ err instanceof Error ? err.message : "failed to parse JSON"
39468
+ );
39469
+ setIsStreaming(false);
39470
+ }
39471
+ }
39472
+ return;
39473
+ }
39474
+ if (!response.body) {
39475
+ if (!cancelled) {
39476
+ setError("response body is null");
39477
+ setIsStreaming(false);
39478
+ }
39479
+ return;
39480
+ }
39481
+ try {
39482
+ for await (const event of parseSSEStream(response.body)) {
39483
+ if (cancelled) break;
39484
+ if (event.type === "step:start") {
39485
+ const newStep = {
39486
+ label: options.stepLabels[event.step] ?? event.step,
39487
+ status: "active"
39488
+ };
39489
+ setSteps((prev) => {
39490
+ const updated = prev.map(
39491
+ (s) => s.status === "active" ? { ...s, status: "done" } : s
39492
+ );
39493
+ return [...updated, newStep];
39494
+ });
39495
+ startElapsedTimer(event.index);
39496
+ } else if (event.type === "step:complete") {
39497
+ clearElapsedInterval();
39498
+ activeStepIndexRef.current = null;
39499
+ const detail = `${(event.durationMs / 1e3).toFixed(1)}s`;
39500
+ setSteps(
39501
+ (prev) => prev.map(
39502
+ (s, i) => i === event.index ? { ...s, status: "done", detail } : s
39503
+ )
39504
+ );
39505
+ } else if (event.type === "result") {
39506
+ clearElapsedInterval();
39507
+ setResult(event.data);
39508
+ setIsStreaming(false);
39509
+ } else if (event.type === "error") {
39510
+ clearElapsedInterval();
39511
+ setSteps(
39512
+ (prev) => prev.map(
39513
+ (s) => s.status === "active" ? { ...s, status: "error" } : s
39514
+ )
39515
+ );
39516
+ setError(event.message);
39517
+ setIsStreaming(false);
39518
+ }
39519
+ }
39520
+ } catch (err) {
39521
+ if (!cancelled) {
39522
+ clearElapsedInterval();
39523
+ setError(err instanceof Error ? err.message : "stream error");
39524
+ setIsStreaming(false);
39525
+ }
39526
+ }
39527
+ }
39528
+ run2();
39529
+ return () => {
39530
+ cancelled = true;
39531
+ clearElapsedInterval();
39532
+ controller.abort();
39533
+ abortRef.current = null;
39534
+ };
39535
+ }, [options]);
39536
+ return { steps, result, error, isStreaming };
39537
+ }
39538
+
39539
+ // src/ui/colors.ts
39540
+ var C = {
39541
+ cyan: "#22d3ee",
39542
+ green: "#4ade80",
39543
+ yellow: "#facc15",
39544
+ red: "#f87171",
39545
+ white: "#f9fafb",
39546
+ dim: "#6b7280",
39547
+ cyanBg: "#0891b2",
39548
+ grayBg: "#374151",
39549
+ blueBg: "#1d4ed8"
39550
+ };
39551
+ var TYPE_BG = {
39552
+ feat: "#0891b2",
39553
+ fix: "#dc2626",
39554
+ refactor: "#ca8a04",
39555
+ docs: "#1d4ed8",
39556
+ test: "#7e22ce",
39557
+ chore: "#374151",
39558
+ style: "#15803d",
39559
+ ci: "#1d4ed8",
39560
+ perf: "#ca8a04",
39561
+ build: "#374151",
39562
+ revert: "#dc2626"
39563
+ };
39564
+ var TYPE_FG = {
39565
+ feat: "#000",
39566
+ fix: "#fff",
39567
+ refactor: "#000",
39568
+ docs: "#fff",
39569
+ test: "#fff",
39570
+ chore: "#fff",
39571
+ style: "#000",
39572
+ ci: "#fff",
39573
+ perf: "#000",
39574
+ build: "#fff",
39575
+ revert: "#fff"
39576
+ };
39577
+
39578
+ // src/ui/commit-utils.ts
39579
+ var TERMINAL_PHASES = [
39580
+ "done",
39581
+ "aborted",
39582
+ "error-auth",
39583
+ "error-empty",
39584
+ "error-git",
39585
+ "error-api",
39586
+ "error-commit",
39587
+ "error-plan"
39588
+ ];
39589
+ function parseCommitType(msg) {
39590
+ const match = msg.match(/^(\w+)(?:\(([^)]+)\))?!?:\s*(.+)/);
39591
+ if (!match) return { type: "chore", scope: null, description: msg };
39592
+ return { type: match[1], scope: match[2] ?? null, description: match[3] };
39593
+ }
39594
+
39595
+ // src/ui/components/diff-viewer.tsx
39596
+ var import_react31 = __toESM(require_react(), 1);
39258
39597
  var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
39259
- function Header({ title = "RepoMind Split" }) {
39260
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
39261
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { gap: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { backgroundColor: "cyan", color: "black", bold: true, children: [
39262
- " ",
39263
- "\u26A1 ",
39264
- title,
39265
- " "
39266
- ] }) }),
39267
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: "\u2500".repeat(40) })
39598
+ function DiffViewer({ filePath, patch, onClose }) {
39599
+ const [scrollOffset, setScrollOffset] = (0, import_react31.useState)(0);
39600
+ const termHeight = process.stdout.rows || 24;
39601
+ use_input_default((input, key) => {
39602
+ if (input === "q" || input === "d" || key.escape) {
39603
+ onClose();
39604
+ return;
39605
+ }
39606
+ if (key.upArrow || input === "k") {
39607
+ setScrollOffset((prev) => Math.max(0, prev - 1));
39608
+ }
39609
+ if (key.downArrow || input === "j") {
39610
+ setScrollOffset((prev) => prev + 1);
39611
+ }
39612
+ if (input === " " || key.pageDown) {
39613
+ setScrollOffset((prev) => prev + (termHeight - 5));
39614
+ }
39615
+ if (input === "u" || key.pageUp) {
39616
+ setScrollOffset((prev) => Math.max(0, prev - (termHeight - 5)));
39617
+ }
39618
+ if (input === "g") {
39619
+ setScrollOffset(0);
39620
+ }
39621
+ });
39622
+ const allLines = patch.split("\n");
39623
+ const contentLines = [];
39624
+ for (const line of allLines) {
39625
+ if (line.startsWith("diff --git")) {
39626
+ const match = line.match(/^diff --git a\/.+ b\/(.+)$/);
39627
+ const file = match?.[1] ?? line;
39628
+ contentLines.push(`__FILE__${file}`);
39629
+ } else if (line.startsWith("index ") || line.startsWith("--- ") || line.startsWith("+++ ") || line.startsWith("old mode") || line.startsWith("new mode") || line.startsWith("new file") || line.startsWith("deleted file") || line.startsWith("similarity")) {
39630
+ } else {
39631
+ contentLines.push(line);
39632
+ }
39633
+ }
39634
+ const totalLines = contentLines.length;
39635
+ const viewportHeight = Math.max(1, termHeight - 5);
39636
+ const maxScroll = Math.max(0, totalLines - viewportHeight);
39637
+ const clamped = Math.min(scrollOffset, maxScroll);
39638
+ const visibleLines = contentLines.slice(clamped, clamped + viewportHeight);
39639
+ const scrollPercent = maxScroll > 0 ? Math.round(clamped / maxScroll * 100) : 100;
39640
+ const safeWidth = Math.max(20, (process.stdout.columns ?? 80) - 3);
39641
+ const fileCount = contentLines.filter((l) => l.startsWith("__FILE__")).length;
39642
+ const footerHints = [
39643
+ { key: "\u2191\u2193", label: "rolar" },
39644
+ { key: "space", label: "p\xE1gina" },
39645
+ { key: "g", label: "topo" },
39646
+ { key: "q", label: "sair" }
39647
+ ];
39648
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { flexDirection: "column", children: [
39649
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { children: [
39650
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { backgroundColor: C.cyanBg, color: "#000", bold: true, children: [
39651
+ " ",
39652
+ "DIFF",
39653
+ " "
39654
+ ] }),
39655
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { bold: true, children: [
39656
+ " ",
39657
+ filePath,
39658
+ " "
39659
+ ] }),
39660
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color: C.dim, children: [
39661
+ "\xB7 ",
39662
+ fileCount > 1 ? `${fileCount} arquivos \xB7 ` : "",
39663
+ totalLines,
39664
+ " linhas \xB7 ",
39665
+ scrollPercent,
39666
+ "%"
39667
+ ] })
39668
+ ] }),
39669
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: C.dim, children: "\u2500".repeat(safeWidth) }),
39670
+ visibleLines.map((line, i) => {
39671
+ const key = `dl-${clamped + i}`;
39672
+ if (line.startsWith("__FILE__")) {
39673
+ const file = line.slice(8);
39674
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { flexDirection: "column", marginTop: i > 0 ? 1 : 0, children: [
39675
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: C.dim, children: "\u2500".repeat(safeWidth) }),
39676
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { gap: 1, children: [
39677
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { backgroundColor: C.blueBg, color: C.white, bold: true, children: [
39678
+ " ",
39679
+ "FILE",
39680
+ " "
39681
+ ] }),
39682
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { bold: true, color: C.white, children: file })
39683
+ ] }),
39684
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: C.dim, children: "\u2500".repeat(safeWidth) })
39685
+ ] }, key);
39686
+ }
39687
+ const num = String(clamped + i + 1).padStart(4);
39688
+ if (line.startsWith("@@")) {
39689
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color: C.cyan, dimColor: true, children: [
39690
+ " ",
39691
+ " ",
39692
+ line
39693
+ ] }, key);
39694
+ }
39695
+ if (line.startsWith("+")) {
39696
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color: C.green, children: [
39697
+ num,
39698
+ " ",
39699
+ line
39700
+ ] }, key);
39701
+ }
39702
+ if (line.startsWith("-")) {
39703
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color: C.red, children: [
39704
+ num,
39705
+ " ",
39706
+ line
39707
+ ] }, key);
39708
+ }
39709
+ if (line.startsWith("\\")) {
39710
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color: C.dim, children: [
39711
+ " ",
39712
+ line
39713
+ ] }, key);
39714
+ }
39715
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color: C.dim, children: [
39716
+ num,
39717
+ " ",
39718
+ line
39719
+ ] }, key);
39720
+ }),
39721
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: C.dim, children: "\u2500".repeat(safeWidth) }),
39722
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { justifyContent: "space-between", children: [
39723
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { gap: 1, flexWrap: "wrap", children: footerHints.map(({ key, label }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { gap: 0, children: [
39724
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { backgroundColor: C.grayBg, color: C.white, bold: true, children: ` ${key} ` }),
39725
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color: C.dim, children: [
39726
+ " ",
39727
+ label,
39728
+ " "
39729
+ ] })
39730
+ ] }, key)) }),
39731
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color: C.dim, children: [
39732
+ clamped + 1,
39733
+ "-",
39734
+ Math.min(clamped + viewportHeight, totalLines),
39735
+ "/",
39736
+ totalLines
39737
+ ] })
39738
+ ] })
39268
39739
  ] });
39269
39740
  }
39270
39741
 
39271
- // src/ui/components/key-hints.tsx
39742
+ // src/ui/components/header.tsx
39272
39743
  var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
39744
+ function Header({ title = "repomind" }) {
39745
+ const safeWidth = Math.max(20, (process.stdout.columns ?? 80) - 3);
39746
+ const inner = `\u26A1 ${title}`;
39747
+ const padded = ` ${inner}${" ".repeat(Math.max(0, safeWidth - inner.length - 1))}`;
39748
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
39749
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { backgroundColor: C.cyanBg, color: "#000", bold: true, children: padded }),
39750
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: C.dim, children: "\u2500".repeat(safeWidth) })
39751
+ ] });
39752
+ }
39753
+
39754
+ // src/ui/components/key-hints.tsx
39755
+ var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
39273
39756
  function KeyHints({ hints }) {
39274
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { marginTop: 1, gap: 0, flexWrap: "wrap", children: [
39275
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: "\u2500".repeat(40) }),
39276
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box_default, { gap: 1, marginTop: 0, children: hints.map((hint) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { gap: 0, children: [
39277
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { backgroundColor: "gray", color: "white", bold: true, children: ` ${hint.key} ` }),
39278
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { dimColor: true, children: [
39757
+ const safeWidth = Math.max(20, (process.stdout.columns ?? 80) - 3);
39758
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "column", marginTop: 0, children: [
39759
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: C.dim, children: "\u2500".repeat(safeWidth) }),
39760
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { gap: 1, flexWrap: "wrap", children: hints.map((hint) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { gap: 0, children: [
39761
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { backgroundColor: C.grayBg, color: C.white, bold: true, children: ` ${hint.key} ` }),
39762
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: C.dim, children: [
39279
39763
  " ",
39280
39764
  hint.label,
39281
39765
  " "
@@ -39285,107 +39769,95 @@ function KeyHints({ hints }) {
39285
39769
  }
39286
39770
 
39287
39771
  // src/ui/components/step-list.tsx
39288
- var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
39289
- var STATUS_ICONS = {
39290
- done: "\u25CF",
39291
- active: "",
39292
- pending: "\u25CB",
39293
- error: "\u2717"
39294
- };
39295
- var STATUS_COLORS = {
39296
- done: "green",
39297
- active: "cyan",
39298
- pending: void 0,
39299
- error: "red"
39300
- };
39772
+ var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
39301
39773
  function StepList({ steps }) {
39302
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { flexDirection: "column", gap: 0, marginLeft: 1, children: steps.map((step, idx) => {
39774
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { flexDirection: "column", gap: 0, marginLeft: 1, children: steps.map((step, idx) => {
39303
39775
  const isLast = idx === steps.length - 1;
39304
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "column", children: [
39305
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { gap: 1, children: [
39306
- step.status === "active" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: "cyan", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(build_default, { type: "dots" }) }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
39307
- Text,
39308
- {
39309
- color: STATUS_COLORS[step.status],
39310
- dimColor: step.status === "pending",
39311
- children: STATUS_ICONS[step.status]
39312
- }
39313
- ),
39314
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
39776
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { flexDirection: "column", children: [
39777
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { gap: 1, children: [
39778
+ step.status === "active" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: C.cyan, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(build_default, { type: "dots" }) }) : step.status === "done" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: C.green, children: "\u25CF" }) : step.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: C.red, children: "\u2717" }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: C.dim, children: "\u25CB" }),
39779
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
39315
39780
  Text,
39316
39781
  {
39317
- color: STATUS_COLORS[step.status],
39318
- dimColor: step.status === "pending",
39782
+ color: step.status === "done" ? C.green : step.status === "active" ? C.cyan : step.status === "error" ? C.red : C.dim,
39319
39783
  bold: step.status === "active",
39320
39784
  children: step.label
39321
39785
  }
39322
39786
  ),
39323
- step.detail && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { dimColor: true, children: [
39787
+ step.detail && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: C.dim, children: [
39324
39788
  "\xB7 ",
39325
39789
  step.detail
39326
39790
  ] })
39327
39791
  ] }),
39328
- !isLast && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { marginLeft: 0, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "\u2502" }) })
39792
+ !isLast && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { marginLeft: 0, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: C.dim, children: "\u2502" }) })
39329
39793
  ] }, step.label);
39330
39794
  }) });
39331
39795
  }
39332
39796
 
39333
39797
  // src/ui/components/type-badge.tsx
39334
- var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
39335
- var TYPE_STYLES = {
39336
- feat: { bg: "cyan", fg: "black" },
39337
- fix: { bg: "red", fg: "white" },
39338
- refactor: { bg: "yellow", fg: "black" },
39339
- docs: { bg: "blue", fg: "white" },
39340
- test: { bg: "magenta", fg: "white" },
39341
- chore: { bg: "gray", fg: "white" },
39342
- style: { bg: "green", fg: "black" },
39343
- ci: { bg: "blue", fg: "white" },
39344
- perf: { bg: "yellow", fg: "black" },
39345
- build: { bg: "gray", fg: "white" },
39346
- revert: { bg: "red", fg: "white" }
39347
- };
39798
+ var import_jsx_runtime5 = __toESM(require_jsx_runtime(), 1);
39348
39799
  function TypeBadge({ type }) {
39349
- const style = TYPE_STYLES[type] ?? { bg: "gray", fg: "white" };
39350
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { backgroundColor: style.bg, color: style.fg, bold: true, children: ` ${type} ` });
39800
+ const bg = TYPE_BG[type] ?? "#374151";
39801
+ const fg = TYPE_FG[type] ?? "#fff";
39802
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { backgroundColor: bg, color: fg, bold: true, children: ` ${type} ` });
39351
39803
  }
39352
39804
 
39353
39805
  // src/ui/commit-app.tsx
39354
- var import_jsx_runtime5 = __toESM(require_jsx_runtime(), 1);
39355
- var TERMINAL_PHASES = [
39356
- "done",
39357
- "aborted",
39358
- "error-auth",
39359
- "error-empty",
39360
- "error-git",
39361
- "error-api",
39362
- "error-commit",
39363
- "error-plan"
39364
- ];
39365
- function parseCommitType(msg) {
39366
- const match = msg.match(/^(\w+)(?:\(([^)]+)\))?!?:\s*(.+)/);
39367
- if (!match) return { type: "chore", scope: null, description: msg };
39368
- return { type: match[1], scope: match[2] ?? null, description: match[3] };
39369
- }
39806
+ var import_jsx_runtime6 = __toESM(require_jsx_runtime(), 1);
39807
+ var STEP_LABELS = {
39808
+ understand: "Entendendo diff",
39809
+ classify: "Classificando mudan\xE7as",
39810
+ group: "Agrupando commits",
39811
+ generate: "Gerando mensagem"
39812
+ };
39370
39813
  function CommitApp({
39371
39814
  deps,
39372
39815
  onExit
39373
39816
  }) {
39374
39817
  const { exit } = use_app_default();
39375
- const [phase, setPhase] = (0, import_react30.useState)("analyzing");
39376
- const [message, setMessage] = (0, import_react30.useState)("");
39377
- const [issueRef, setIssueRef] = (0, import_react30.useState)("");
39378
- const [errorMsg, setErrorMsg] = (0, import_react30.useState)("");
39379
- const [fileCount, setFileCount] = (0, import_react30.useState)(0);
39380
- const [additions, setAdditions] = (0, import_react30.useState)(0);
39381
- const [deletions, setDeletions] = (0, import_react30.useState)(0);
39382
- (0, import_react30.useEffect)(() => {
39818
+ const committedMessageRef = (0, import_react32.useRef)("");
39819
+ const [phase, setPhase] = (0, import_react32.useState)("analyzing");
39820
+ const [message, setMessage] = (0, import_react32.useState)("");
39821
+ const [issueRef, setIssueRef] = (0, import_react32.useState)("");
39822
+ const [errorMsg, setErrorMsg] = (0, import_react32.useState)("");
39823
+ const [fileCount, setFileCount] = (0, import_react32.useState)(0);
39824
+ const [additions, setAdditions] = (0, import_react32.useState)(0);
39825
+ const [deletions, setDeletions] = (0, import_react32.useState)(0);
39826
+ const [rawDiff, setRawDiff] = (0, import_react32.useState)("");
39827
+ const [editBuffer, setEditBuffer] = (0, import_react32.useState)("");
39828
+ const [streamPayload, setStreamPayload] = (0, import_react32.useState)(
39829
+ null
39830
+ );
39831
+ const streamOptions = streamPayload && phase === "streaming" ? {
39832
+ path: streamPayload.path,
39833
+ body: streamPayload.body,
39834
+ token: streamPayload.token,
39835
+ postStream: deps.postStream,
39836
+ stepLabels: STEP_LABELS
39837
+ } : null;
39838
+ const stream = usePipelineStream(streamOptions);
39839
+ (0, import_react32.useEffect)(() => {
39383
39840
  if (!TERMINAL_PHASES.includes(phase)) return;
39384
39841
  const code = phase === "done" || phase === "aborted" ? 0 : 1;
39385
39842
  exit();
39386
- onExit(code);
39843
+ onExit(code, phase === "done" ? committedMessageRef.current : void 0);
39387
39844
  }, [phase]);
39388
- (0, import_react30.useEffect)(() => {
39845
+ (0, import_react32.useEffect)(() => {
39846
+ if (phase !== "streaming") return;
39847
+ if (stream.result) {
39848
+ setMessage(stream.result.message);
39849
+ setPhase("link-issue");
39850
+ return;
39851
+ }
39852
+ if (stream.error) {
39853
+ const verbose2 = process.argv.includes("--verbose") || process.argv.includes("-v") || !!process.env.REPOMIND_DEBUG;
39854
+ setErrorMsg(
39855
+ verbose2 ? `Falha ao gerar mensagem: ${stream.error}` : "Falha ao gerar mensagem. Tente novamente."
39856
+ );
39857
+ setPhase("error-api");
39858
+ }
39859
+ }, [stream.result, stream.error, phase]);
39860
+ (0, import_react32.useEffect)(() => {
39389
39861
  async function run2() {
39390
39862
  const token = deps.readToken();
39391
39863
  if (!token) {
@@ -39413,7 +39885,7 @@ function CommitApp({
39413
39885
  setFileCount(changes.files.length);
39414
39886
  setAdditions(changes.files.reduce((s, f) => s + f.additions, 0));
39415
39887
  setDeletions(changes.files.reduce((s, f) => s + f.deletions, 0));
39416
- setPhase("generating");
39888
+ setRawDiff(changes.rawDiff);
39417
39889
  try {
39418
39890
  const stagedFiles = await deps.readStagedFiles(changes.files);
39419
39891
  const body = {
@@ -39423,13 +39895,8 @@ function CommitApp({
39423
39895
  if (deps.fileConfig && Object.keys(deps.fileConfig).length > 0) {
39424
39896
  body.config = deps.fileConfig;
39425
39897
  }
39426
- const result = await deps.apiPost(
39427
- "/commit/generate",
39428
- body,
39429
- token
39430
- );
39431
- setMessage(result.message);
39432
- setPhase("link-issue");
39898
+ setStreamPayload({ path: "/commit/generate", body, token });
39899
+ setPhase("streaming");
39433
39900
  } catch (e) {
39434
39901
  if (e instanceof PlanLimitError) {
39435
39902
  setErrorMsg(
@@ -39475,6 +39942,16 @@ ${issueRef.trim()}`);
39475
39942
  use_input_default(
39476
39943
  async (input, key) => {
39477
39944
  if (phase !== "confirm") return;
39945
+ const parsed2 = parseCommitType(message);
39946
+ if (input === "e") {
39947
+ setEditBuffer(parsed2.description);
39948
+ setPhase("editing");
39949
+ return;
39950
+ }
39951
+ if (input === "d") {
39952
+ setPhase("viewing-diff");
39953
+ return;
39954
+ }
39478
39955
  const confirmed = key.return || input.toLowerCase() === "y" || input === "";
39479
39956
  const denied = input.toLowerCase() === "n";
39480
39957
  if (confirmed) {
@@ -39484,6 +39961,7 @@ ${issueRef.trim()}`);
39484
39961
  setErrorMsg("git commit falhou. Verifique os hooks do reposit\xF3rio.");
39485
39962
  setPhase("error-commit");
39486
39963
  } else {
39964
+ committedMessageRef.current = message;
39487
39965
  setPhase("done");
39488
39966
  }
39489
39967
  } else if (denied) {
@@ -39492,10 +39970,48 @@ ${issueRef.trim()}`);
39492
39970
  },
39493
39971
  { isActive: phase === "confirm" }
39494
39972
  );
39973
+ use_input_default(
39974
+ (input, key) => {
39975
+ if (key.return) {
39976
+ const parsed2 = parseCommitType(message);
39977
+ const newMsg = parsed2.scope ? `${parsed2.type}(${parsed2.scope}): ${editBuffer}` : `${parsed2.type}: ${editBuffer}`;
39978
+ const bodyParts = message.split("\n\n").slice(1);
39979
+ setMessage(
39980
+ bodyParts.length > 0 ? `${newMsg}
39981
+
39982
+ ${bodyParts.join("\n\n")}` : newMsg
39983
+ );
39984
+ setPhase("confirm");
39985
+ return;
39986
+ }
39987
+ if (key.escape) {
39988
+ setPhase("confirm");
39989
+ return;
39990
+ }
39991
+ if (key.backspace || key.delete) {
39992
+ setEditBuffer((prev) => prev.slice(0, -1));
39993
+ return;
39994
+ }
39995
+ if (input && !key.ctrl && !key.meta) {
39996
+ setEditBuffer((prev) => prev + input);
39997
+ }
39998
+ },
39999
+ { isActive: phase === "editing" }
40000
+ );
40001
+ if (phase === "viewing-diff") {
40002
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
40003
+ DiffViewer,
40004
+ {
40005
+ filePath: `${fileCount} arquivo${fileCount !== 1 ? "s" : ""}`,
40006
+ patch: rawDiff,
40007
+ onClose: () => setPhase("confirm")
40008
+ }
40009
+ );
40010
+ }
39495
40011
  const steps = [];
39496
40012
  const phaseOrder = [
39497
40013
  "analyzing",
39498
- "generating",
40014
+ "streaming",
39499
40015
  "link-issue",
39500
40016
  "confirm",
39501
40017
  "committing",
@@ -39507,40 +40023,60 @@ ${issueRef.trim()}`);
39507
40023
  status: phase === "analyzing" ? "active" : phaseIdx > 0 || TERMINAL_PHASES.includes(phase) ? "done" : "pending",
39508
40024
  detail: phaseIdx > 0 || TERMINAL_PHASES.includes(phase) ? `${fileCount} arquivos \xB7 +${additions} -${deletions}` : void 0
39509
40025
  });
39510
- steps.push({
39511
- label: "Gerando mensagem com IA",
39512
- status: phase === "generating" ? "active" : phaseIdx > 1 || TERMINAL_PHASES.includes(phase) ? message ? "done" : phase.startsWith("error") ? "error" : "pending" : "pending"
39513
- });
40026
+ if (phase === "streaming") {
40027
+ if (stream.steps.length > 0) {
40028
+ steps.push(...stream.steps);
40029
+ } else {
40030
+ steps.push({
40031
+ label: "Gerando mensagem com IA",
40032
+ status: "active"
40033
+ });
40034
+ }
40035
+ } else if (phaseIdx > 1 || TERMINAL_PHASES.includes(phase)) {
40036
+ if (stream.steps.length > 0) {
40037
+ steps.push(...stream.steps);
40038
+ } else {
40039
+ steps.push({
40040
+ label: "Gerando mensagem com IA",
40041
+ status: message ? "done" : phase.startsWith("error") ? "error" : "pending"
40042
+ });
40043
+ }
40044
+ } else {
40045
+ steps.push({
40046
+ label: "Gerando mensagem com IA",
40047
+ status: "pending"
40048
+ });
40049
+ }
39514
40050
  const parsed = parseCommitType(message);
39515
- const hasMessage = phase === "link-issue" || phase === "confirm" || phase === "committing" || phase === "done" || phase === "aborted";
39516
- const commitCard = hasMessage ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { flexDirection: "column", marginTop: 1, marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
40051
+ const hasMessage = phase === "link-issue" || phase === "confirm" || phase === "editing" || phase === "committing" || phase === "done" || phase === "aborted";
40052
+ const commitCard = hasMessage ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Box_default, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
39517
40053
  Box_default,
39518
40054
  {
39519
- borderStyle: "bold",
39520
- borderColor: phase === "done" ? "green" : "cyan",
39521
- paddingX: 2,
39522
- paddingY: 1,
40055
+ borderStyle: "round",
40056
+ borderColor: phase === "confirm" || phase === "editing" || phase === "committing" || phase === "done" ? C.green : C.cyan,
40057
+ paddingX: 1,
40058
+ paddingY: 0,
39523
40059
  flexDirection: "column",
39524
40060
  children: [
39525
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { gap: 1, marginBottom: message.includes("\n\n") ? 1 : 0, children: [
39526
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TypeBadge, { type: parsed.type }),
39527
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { bold: true, children: parsed.description })
40061
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { gap: 1, alignItems: "center", children: [
40062
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TypeBadge, { type: parsed.type }),
40063
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { bold: true, children: parsed.description })
39528
40064
  ] }),
39529
- parsed.scope && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { marginBottom: message.includes("\n\n") ? 0 : 0, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, children: [
40065
+ parsed.scope && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { color: C.dim, children: [
39530
40066
  "scope: ",
39531
40067
  parsed.scope
39532
40068
  ] }) }),
39533
- message.includes("\n\n") && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: message.split("\n\n").slice(1).join("\n\n") }) }),
39534
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { marginTop: 1, gap: 1, children: [
39535
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "green", bold: true, children: [
40069
+ message.includes("\n\n") && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.dim, children: message.split("\n\n").slice(1).join("\n\n") }) }),
40070
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { gap: 1, children: [
40071
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { color: C.green, bold: true, children: [
39536
40072
  "+",
39537
40073
  additions
39538
40074
  ] }),
39539
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "red", bold: true, children: [
40075
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { color: C.red, bold: true, children: [
39540
40076
  "-",
39541
40077
  deletions
39542
40078
  ] }),
39543
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, children: [
40079
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { color: C.dim, children: [
39544
40080
  "\xB7 ",
39545
40081
  fileCount,
39546
40082
  " arquivos"
@@ -39549,71 +40085,130 @@ ${issueRef.trim()}`);
39549
40085
  ]
39550
40086
  }
39551
40087
  ) }) : null;
39552
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", children: [
39553
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Header, { title: "RepoMind Commit" }),
39554
- !hasMessage && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(StepList, { steps }),
39555
- commitCard,
39556
- phase === "link-issue" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { gap: 1, children: [
39557
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { backgroundColor: "blue", color: "white", bold: true, children: [
39558
- " ",
39559
- "?",
39560
- " "
39561
- ] }),
39562
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { children: " Link issue " }),
39563
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "cyan", children: issueRef }),
39564
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "cyan", children: "\u258C" }),
39565
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: " (ex: Closes #42, Enter para pular)" })
39566
- ] }),
39567
- phase === "confirm" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { gap: 1, children: [
39568
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { backgroundColor: "cyan", color: "black", bold: true, children: [
39569
- " ",
39570
- "?",
39571
- " "
39572
- ] }),
39573
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { bold: true, children: " Confirmar este commit? " }),
39574
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "[Y/n]" })
39575
- ] }),
39576
- phase === "committing" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { gap: 1, children: [
39577
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "cyan", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(build_default, { type: "dots" }) }),
39578
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "Fazendo commit..." })
39579
- ] }),
39580
- phase === "done" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { gap: 1, children: [
39581
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "green", children: "\u2728" }),
39582
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { bold: true, children: "Commit realizado com sucesso" })
39583
- ] }),
39584
- phase === "aborted" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { gap: 1, children: [
39585
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "yellow", children: "\u25C6" }),
39586
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "Abortado. Nenhum commit foi feito." })
39587
- ] }),
39588
- phase === "error-empty" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", marginTop: 1, children: [
39589
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { gap: 1, children: [
39590
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "yellow", children: "\u25B2" }),
39591
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "yellow", children: errorMsg })
40088
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { flexDirection: "column", children: [
40089
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Header, { title: "repomind commit" }),
40090
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 1, children: [
40091
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StepList, { steps }),
40092
+ commitCard,
40093
+ phase === "link-issue" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { gap: 1, children: [
40094
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { backgroundColor: C.blueBg, color: C.white, bold: true, children: [
40095
+ " ",
40096
+ "?",
40097
+ " "
40098
+ ] }),
40099
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { children: " Link issue " }),
40100
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.cyan, children: issueRef }),
40101
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.cyan, children: "\u258C" }),
40102
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.dim, children: " (ex: Closes #42, Enter para pular)" })
39592
40103
  ] }),
39593
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
40104
+ phase === "confirm" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
39594
40105
  KeyHints,
39595
40106
  {
39596
40107
  hints: [
39597
- { key: "git add .", label: "stage todos os arquivos" },
39598
- { key: "git add -p", label: "stage interativo" }
40108
+ { key: "enter", label: "confirmar" },
40109
+ { key: "e", label: "editar" },
40110
+ { key: "d", label: "diff" },
40111
+ { key: "n", label: "cancelar" }
39599
40112
  ]
39600
40113
  }
39601
- )
39602
- ] }),
39603
- (phase === "error-auth" || phase === "error-git" || phase === "error-api" || phase === "error-commit") && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { gap: 1, children: [
39604
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "red", children: "\u2717" }),
39605
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "red", children: errorMsg })
39606
- ] }) }),
39607
- phase === "error-plan" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", marginTop: 1, children: [
39608
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { gap: 1, children: [
39609
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "yellow", children: "\u25B2" }),
39610
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "yellow", children: errorMsg.split("\n")[0] })
40114
+ ),
40115
+ phase === "editing" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { gap: 1, marginTop: 1, children: [
40116
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.cyan, children: "Editar:" }),
40117
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.cyan, children: editBuffer }),
40118
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.cyan, children: "\u258C" }),
40119
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.dim, children: "(Enter salvar, Esc cancelar)" })
39611
40120
  ] }),
39612
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: errorMsg.split("\n")[1] }) })
40121
+ phase === "committing" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { gap: 1, children: [
40122
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.cyan, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(build_default, { type: "dots" }) }),
40123
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.dim, children: "Fazendo commit..." })
40124
+ ] }),
40125
+ phase === "done" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { gap: 1, children: [
40126
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.green, children: "\u2728" }),
40127
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { bold: true, children: "Commit realizado com sucesso" })
40128
+ ] }),
40129
+ phase === "aborted" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { gap: 1, children: [
40130
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.yellow, children: "\u25C6" }),
40131
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.dim, children: "Abortado. Nenhum commit foi feito." })
40132
+ ] }),
40133
+ phase === "error-empty" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { flexDirection: "column", marginTop: 1, children: [
40134
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { gap: 1, children: [
40135
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.yellow, children: "\u25B2" }),
40136
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.yellow, children: errorMsg })
40137
+ ] }),
40138
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
40139
+ KeyHints,
40140
+ {
40141
+ hints: [
40142
+ { key: "git add .", label: "stage todos os arquivos" },
40143
+ { key: "git add -p", label: "stage interativo" }
40144
+ ]
40145
+ }
40146
+ )
40147
+ ] }),
40148
+ (phase === "error-auth" || phase === "error-git" || phase === "error-api" || phase === "error-commit") && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Box_default, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { gap: 1, children: [
40149
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.red, children: "\u2717" }),
40150
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.red, children: errorMsg })
40151
+ ] }) }),
40152
+ phase === "error-plan" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { flexDirection: "column", marginTop: 1, children: [
40153
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { gap: 1, children: [
40154
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.yellow, children: "\u25B2" }),
40155
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.yellow, children: errorMsg.split("\n")[0] })
40156
+ ] }),
40157
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Box_default, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: C.dim, children: errorMsg.split("\n")[1] }) })
40158
+ ] })
39613
40159
  ] })
39614
40160
  ] });
39615
40161
  }
39616
40162
 
40163
+ // src/ui/done-summary.tsx
40164
+ var import_react33 = __toESM(require_react(), 1);
40165
+ var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
40166
+ function parseType(msg) {
40167
+ const match = msg.match(/^(\w+)(?:\([^)]+\))?!?:\s*(.+)/);
40168
+ return { type: match?.[1] ?? "chore", description: match?.[2] ?? msg };
40169
+ }
40170
+ function SplitDoneSummary({ commits }) {
40171
+ const { exit } = use_app_default();
40172
+ (0, import_react33.useEffect)(() => {
40173
+ exit();
40174
+ }, []);
40175
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 1, children: [
40176
+ commits.map((msg, i) => {
40177
+ const { type, description } = parseType(msg);
40178
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { flexDirection: "column", children: [
40179
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { gap: 1, alignItems: "center", children: [
40180
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: C.green, children: "\u2713" }),
40181
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TypeBadge, { type }),
40182
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: C.green, children: description })
40183
+ ] }),
40184
+ i < commits.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: C.dim, children: "\u2502" })
40185
+ ] }, `${i}-${msg}`);
40186
+ }),
40187
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { marginTop: 1, gap: 1, children: [
40188
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: C.green, children: "\u2728" }),
40189
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Text, { bold: true, color: C.green, children: [
40190
+ commits.length,
40191
+ " commit",
40192
+ commits.length !== 1 ? "s" : "",
40193
+ " realizado",
40194
+ commits.length !== 1 ? "s" : ""
40195
+ ] })
40196
+ ] })
40197
+ ] });
40198
+ }
40199
+ function CommitDoneSummary({ message }) {
40200
+ const { exit } = use_app_default();
40201
+ (0, import_react33.useEffect)(() => {
40202
+ exit();
40203
+ }, []);
40204
+ const { type, description } = parseType(message);
40205
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { paddingLeft: 1, gap: 1, alignItems: "center", children: [
40206
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: C.green, children: "\u2713" }),
40207
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TypeBadge, { type }),
40208
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: C.green, children: description })
40209
+ ] });
40210
+ }
40211
+
39617
40212
  // src/commands/commit.ts
39618
40213
  async function runGitCommit(message) {
39619
40214
  const proc = Bun.spawn(["git", "commit", "-m", message], {
@@ -39625,117 +40220,120 @@ async function runGitCommit(message) {
39625
40220
  async function commitCommand() {
39626
40221
  const fileConfig = await readRepoConfig();
39627
40222
  let exitCode = 0;
40223
+ let completedMessage = "";
40224
+ enterImmersive();
39628
40225
  const { waitUntilExit } = render_default(
39629
- import_react31.default.createElement(CommitApp, {
40226
+ import_react34.default.createElement(CommitApp, {
39630
40227
  deps: {
39631
40228
  readToken,
39632
40229
  getStagedChanges,
39633
40230
  readStagedFiles,
39634
40231
  apiPost: (path, body, tkn) => apiClient.post(path, body, tkn),
40232
+ postStream: (path, body, tkn, timeoutMs) => apiClient.postStream(path, body, tkn, timeoutMs),
39635
40233
  runGitCommit,
39636
40234
  fileConfig
39637
40235
  },
39638
- onExit: (code) => {
40236
+ onExit: (code, message) => {
39639
40237
  exitCode = code;
40238
+ completedMessage = message ?? "";
39640
40239
  }
39641
40240
  })
39642
40241
  );
39643
40242
  await waitUntilExit();
40243
+ exitImmersive();
40244
+ if (completedMessage) {
40245
+ const { waitUntilExit: waitUntilExit2 } = render_default(
40246
+ import_react34.default.createElement(CommitDoneSummary, { message: completedMessage })
40247
+ );
40248
+ await waitUntilExit2();
40249
+ }
39644
40250
  process.exit(exitCode);
39645
40251
  }
39646
40252
 
39647
40253
  // src/commands/help.tsx
39648
- var import_react32 = __toESM(require_react(), 1);
39649
- var import_jsx_runtime6 = __toESM(require_jsx_runtime(), 1);
40254
+ var import_react35 = __toESM(require_react(), 1);
40255
+ var import_jsx_runtime8 = __toESM(require_jsx_runtime(), 1);
39650
40256
  var COMMANDS = [
39651
40257
  {
39652
40258
  name: "commit",
39653
40259
  description: "Gerar mensagem de commit com IA",
39654
40260
  icon: "\u2726",
39655
- color: "cyan"
40261
+ color: C.cyan
39656
40262
  },
39657
40263
  {
39658
40264
  name: "split",
39659
40265
  description: "Dividir altera\xE7\xF5es em commits at\xF4micos",
39660
40266
  icon: "\u25C8",
39661
- color: "magenta"
40267
+ color: "#c084fc"
39662
40268
  },
39663
40269
  {
39664
40270
  name: "login",
39665
40271
  description: "Autenticar com sua conta RepoMind",
39666
40272
  icon: "\u2192",
39667
- color: "green"
40273
+ color: C.green
39668
40274
  },
39669
40275
  {
39670
40276
  name: "logout",
39671
40277
  description: "Encerrar sess\xE3o atual",
39672
40278
  icon: "\u2190",
39673
- color: "yellow"
40279
+ color: C.yellow
39674
40280
  },
39675
40281
  {
39676
40282
  name: "whoami",
39677
40283
  description: "Exibir usu\xE1rio autenticado",
39678
40284
  icon: "\u25CF",
39679
- color: "blue"
40285
+ color: C.dim
39680
40286
  }
39681
40287
  ];
39682
40288
  function HelpApp() {
39683
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { flexDirection: "column", children: [
39684
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Header, { title: "RepoMind" }),
39685
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Box_default, { flexDirection: "column", gap: 0, marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { paddingLeft: 1, gap: 1, children: [
39686
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { dimColor: true, children: "Uso:" }),
39687
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { bold: true, children: "repomind" }),
39688
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: "cyan", children: "<comando>" }),
39689
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { dimColor: true, children: "[op\xE7\xF5es]" })
40289
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { flexDirection: "column", children: [
40290
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Header, { title: "RepoMind" }),
40291
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Box_default, { flexDirection: "column", gap: 0, marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { paddingLeft: 1, gap: 1, children: [
40292
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: C.dim, children: "Uso:" }),
40293
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { bold: true, children: "repomind" }),
40294
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: C.cyan, children: "<comando>" }),
40295
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: C.dim, children: "[op\xE7\xF5es]" })
39690
40296
  ] }) }),
39691
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
40297
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
39692
40298
  Box_default,
39693
40299
  {
39694
40300
  flexDirection: "column",
39695
40301
  paddingLeft: 1,
39696
40302
  marginBottom: 1,
39697
40303
  borderStyle: "round",
39698
- borderColor: "gray",
40304
+ borderColor: C.dim,
39699
40305
  paddingX: 2,
39700
- paddingY: 1,
39701
- children: COMMANDS.map((cmd, idx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
39702
- Box_default,
39703
- {
39704
- gap: 1,
39705
- marginBottom: idx < COMMANDS.length - 1 ? 0 : 0,
39706
- children: [
39707
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: cmd.color, children: cmd.icon }),
39708
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Box_default, { width: 10, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { bold: true, color: cmd.color, children: cmd.name }) }),
39709
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { dimColor: true, children: cmd.description })
39710
- ]
39711
- },
39712
- cmd.name
39713
- ))
40306
+ paddingY: 0,
40307
+ children: COMMANDS.map((cmd) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { gap: 1, children: [
40308
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: cmd.color, children: cmd.icon }),
40309
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Box_default, { width: 10, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { bold: true, color: cmd.color, children: cmd.name }) }),
40310
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: C.dim, children: cmd.description })
40311
+ ] }, cmd.name))
39714
40312
  }
39715
40313
  ),
39716
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { paddingLeft: 1, flexDirection: "column", gap: 0, children: [
39717
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { gap: 1, children: [
39718
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { backgroundColor: "gray", color: "white", bold: true, children: [
40314
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { paddingLeft: 1, flexDirection: "column", gap: 0, children: [
40315
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { gap: 1, children: [
40316
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { backgroundColor: C.grayBg, color: C.white, bold: true, children: [
39719
40317
  " ",
39720
40318
  "--version",
39721
40319
  " "
39722
40320
  ] }),
39723
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { dimColor: true, children: "Exibir vers\xE3o instalada" })
40321
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: C.dim, children: "Exibir vers\xE3o instalada" })
39724
40322
  ] }),
39725
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { gap: 1, children: [
39726
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { backgroundColor: "gray", color: "white", bold: true, children: [
40323
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { gap: 1, children: [
40324
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { backgroundColor: C.grayBg, color: C.white, bold: true, children: [
39727
40325
  " ",
39728
40326
  "--verbose",
39729
40327
  " "
39730
40328
  ] }),
39731
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { dimColor: true, children: "Exibir detalhes de erro" })
40329
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: C.dim, children: "Exibir detalhes de erro" })
39732
40330
  ] })
39733
40331
  ] }),
39734
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Box_default, { marginTop: 1, paddingLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { dimColor: true, children: "Docs: https://repomind.dev \xB7 Dashboard: https://app.repomind.dev" }) })
40332
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Box_default, { marginTop: 1, paddingLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: C.dim, children: "Docs: https://repomind.dev \xB7 Dashboard: https://app.repomind.dev" }) })
39735
40333
  ] });
39736
40334
  }
39737
40335
  async function helpCommand() {
39738
- const { waitUntilExit } = render_default(import_react32.default.createElement(HelpApp));
40336
+ const { waitUntilExit } = render_default(import_react35.default.createElement(HelpApp));
39739
40337
  setTimeout(() => process.exit(0), 50);
39740
40338
  await waitUntilExit();
39741
40339
  }
@@ -39826,11 +40424,11 @@ async function openBrowser(url) {
39826
40424
  }
39827
40425
 
39828
40426
  // src/commands/login.ts
39829
- var import_react34 = __toESM(require_react(), 1);
40427
+ var import_react37 = __toESM(require_react(), 1);
39830
40428
 
39831
40429
  // src/ui/login-app.tsx
39832
- var import_react33 = __toESM(require_react(), 1);
39833
- var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
40430
+ var import_react36 = __toESM(require_react(), 1);
40431
+ var import_jsx_runtime9 = __toESM(require_jsx_runtime(), 1);
39834
40432
  var TERMINAL_PHASES2 = [
39835
40433
  "done",
39836
40434
  "error-timeout",
@@ -39843,17 +40441,17 @@ function LoginApp({
39843
40441
  onExit
39844
40442
  }) {
39845
40443
  const { exit } = use_app_default();
39846
- const [phase, setPhase] = (0, import_react33.useState)("opening");
39847
- const [authUrl, setAuthUrl] = (0, import_react33.useState)("");
39848
- const [email, setEmail] = (0, import_react33.useState)("");
39849
- const [errorMsg, setErrorMsg] = (0, import_react33.useState)("");
39850
- (0, import_react33.useEffect)(() => {
40444
+ const [phase, setPhase] = (0, import_react36.useState)("opening");
40445
+ const [authUrl, setAuthUrl] = (0, import_react36.useState)("");
40446
+ const [email, setEmail] = (0, import_react36.useState)("");
40447
+ const [errorMsg, setErrorMsg] = (0, import_react36.useState)("");
40448
+ (0, import_react36.useEffect)(() => {
39851
40449
  if (!TERMINAL_PHASES2.includes(phase)) return;
39852
40450
  const code = phase === "done" ? 0 : 1;
39853
40451
  exit();
39854
40452
  onExit(code);
39855
40453
  }, [phase]);
39856
- (0, import_react33.useEffect)(() => {
40454
+ (0, import_react36.useEffect)(() => {
39857
40455
  async function run2() {
39858
40456
  const port = await deps.getAvailablePort();
39859
40457
  const baseUrl = "https://repomind.dev";
@@ -39894,37 +40492,37 @@ function LoginApp({
39894
40492
  }
39895
40493
  run2();
39896
40494
  }, []);
39897
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { flexDirection: "column", gap: 0, paddingTop: 1, children: [
39898
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Box_default, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { bold: true, color: "cyan", children: "RepoMind Login" }) }),
39899
- phase === "opening" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { gap: 1, children: [
39900
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "green", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(build_default, { type: "dots" }) }),
39901
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { dimColor: true, children: "Abrindo browser..." })
40495
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { flexDirection: "column", gap: 0, paddingTop: 1, children: [
40496
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Box_default, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { bold: true, color: C.cyan, children: "RepoMind Login" }) }),
40497
+ phase === "opening" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { gap: 1, children: [
40498
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: C.cyan, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(build_default, { type: "dots" }) }),
40499
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: C.dim, children: "Abrindo browser..." })
39902
40500
  ] }),
39903
- authUrl !== "" && phase !== "opening" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
39904
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { dimColor: true, children: "Se n\xE3o abrir automaticamente, acesse:" }),
39905
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "blue", children: authUrl })
40501
+ authUrl !== "" && phase !== "opening" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
40502
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: C.dim, children: "Se n\xE3o abrir automaticamente, acesse:" }),
40503
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: C.cyan, children: authUrl })
39906
40504
  ] }),
39907
- phase === "waiting" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { gap: 1, children: [
39908
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "green", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(build_default, { type: "dots" }) }),
39909
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { dimColor: true, children: "Aguardando autentica\xE7\xE3o no browser..." })
40505
+ phase === "waiting" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { gap: 1, children: [
40506
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: C.cyan, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(build_default, { type: "dots" }) }),
40507
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: C.dim, children: "Aguardando autentica\xE7\xE3o no browser..." })
39910
40508
  ] }),
39911
- phase === "exchanging" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { gap: 1, children: [
39912
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "green", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(build_default, { type: "dots" }) }),
39913
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { dimColor: true, children: "Validando credenciais..." })
40509
+ phase === "exchanging" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { gap: 1, children: [
40510
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: C.cyan, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(build_default, { type: "dots" }) }),
40511
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: C.dim, children: "Validando credenciais..." })
39914
40512
  ] }),
39915
- phase === "done" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { gap: 1, children: [
39916
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "green", children: "\u2713" }),
39917
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Text, { children: [
40513
+ phase === "done" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { gap: 1, children: [
40514
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: C.green, children: "\u2713" }),
40515
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { children: [
39918
40516
  "Autenticado como",
39919
40517
  " ",
39920
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { bold: true, color: "white", children: email })
40518
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { bold: true, color: C.white, children: email })
39921
40519
  ] })
39922
40520
  ] }),
39923
- (phase === "error-timeout" || phase === "error-auth" || phase === "error-api") && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { gap: 1, children: [
39924
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "red", children: "\u2717" }),
39925
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "red", children: errorMsg })
40521
+ (phase === "error-timeout" || phase === "error-auth" || phase === "error-api") && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { gap: 1, children: [
40522
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: C.red, children: "\u2717" }),
40523
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: C.red, children: errorMsg })
39926
40524
  ] }),
39927
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Box_default, { marginTop: 1 })
40525
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Box_default, { marginTop: 1 })
39928
40526
  ] });
39929
40527
  }
39930
40528
 
@@ -39934,7 +40532,7 @@ var apiClient2 = createApiClient();
39934
40532
  async function loginCommand() {
39935
40533
  let exitCode = 0;
39936
40534
  const { waitUntilExit } = render_default(
39937
- import_react34.default.createElement(LoginApp, {
40535
+ import_react37.default.createElement(LoginApp, {
39938
40536
  deps: {
39939
40537
  getAvailablePort,
39940
40538
  startCallbackServer,
@@ -39953,29 +40551,29 @@ async function loginCommand() {
39953
40551
  }
39954
40552
 
39955
40553
  // src/commands/logout.tsx
39956
- var import_react35 = __toESM(require_react(), 1);
39957
- var import_jsx_runtime8 = __toESM(require_jsx_runtime(), 1);
40554
+ var import_react38 = __toESM(require_react(), 1);
40555
+ var import_jsx_runtime10 = __toESM(require_jsx_runtime(), 1);
39958
40556
  function LogoutApp({ onExit }) {
39959
40557
  const wasLoggedIn = readToken() !== null;
39960
40558
  const deleted = deleteToken();
39961
- (0, import_react35.useEffect)(() => {
40559
+ (0, import_react38.useEffect)(() => {
39962
40560
  onExit(0);
39963
40561
  }, [onExit]);
39964
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { flexDirection: "column", paddingTop: 1, marginBottom: 1, children: [
39965
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Box_default, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { bold: true, color: "cyan", children: "RepoMind Logout" }) }),
39966
- wasLoggedIn && deleted ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { gap: 1, children: [
39967
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: "green", children: "\u2713" }),
39968
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { children: "Sess\xE3o encerrada com sucesso." })
39969
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { gap: 1, children: [
39970
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: "yellow", children: "\u25C6" }),
39971
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { dimColor: true, children: "Nenhuma sess\xE3o ativa." })
40562
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: "column", paddingTop: 1, marginBottom: 1, children: [
40563
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { bold: true, color: C.cyan, children: "RepoMind Logout" }) }),
40564
+ wasLoggedIn && deleted ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { gap: 1, children: [
40565
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: C.green, children: "\u2713" }),
40566
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { children: "Sess\xE3o encerrada com sucesso." })
40567
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { gap: 1, children: [
40568
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: C.yellow, children: "\u25C6" }),
40569
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: C.dim, children: "Nenhuma sess\xE3o ativa." })
39972
40570
  ] })
39973
40571
  ] });
39974
40572
  }
39975
40573
  async function logoutCommand() {
39976
40574
  let exitCode = 0;
39977
40575
  const { waitUntilExit } = render_default(
39978
- import_react35.default.createElement(LogoutApp, {
40576
+ import_react38.default.createElement(LogoutApp, {
39979
40577
  onExit: (code) => {
39980
40578
  exitCode = code;
39981
40579
  }
@@ -39985,321 +40583,377 @@ async function logoutCommand() {
39985
40583
  process.exit(exitCode);
39986
40584
  }
39987
40585
 
39988
- // src/commands/split.ts
39989
- var import_react38 = __toESM(require_react(), 1);
39990
-
39991
- // src/ui/split-app.tsx
39992
- var import_react37 = __toESM(require_react(), 1);
39993
-
39994
- // src/ui/components/diff-stats.tsx
39995
- var import_jsx_runtime9 = __toESM(require_jsx_runtime(), 1);
39996
- function DiffStats({
39997
- additions,
39998
- deletions,
39999
- showBar = false
40000
- }) {
40001
- if (!showBar) {
40002
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { gap: 0, children: [
40003
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { color: "green", bold: true, children: [
40004
- "+",
40005
- additions
40006
- ] }),
40007
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { dimColor: true, children: " / " }),
40008
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { color: "red", bold: true, children: [
40009
- "-",
40010
- deletions
40011
- ] })
40012
- ] });
40013
- }
40014
- const total = additions + deletions;
40015
- const barWidth = Math.min(total, 20);
40016
- const addBar = total > 0 ? Math.max(1, Math.round(additions / total * barWidth)) : 0;
40017
- const delBar = Math.max(0, barWidth - addBar);
40018
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { gap: 1, children: [
40019
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { color: "green", bold: true, children: [
40020
- "+",
40021
- additions
40022
- ] }),
40023
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { color: "red", bold: true, children: [
40024
- "-",
40025
- deletions
40026
- ] }),
40027
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { gap: 0, children: [
40028
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "green", children: "\u2588".repeat(addBar) }),
40029
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "red", children: "\u2588".repeat(delBar) })
40030
- ] })
40031
- ] });
40032
- }
40033
-
40034
- // src/ui/components/commit-card.tsx
40035
- var import_jsx_runtime10 = __toESM(require_jsx_runtime(), 1);
40036
- function formatSelection(f) {
40037
- if (f.selection === "all") return "all";
40038
- return f.selection.map((h) => `h${h.hunkIndex}`).join(",");
40039
- }
40040
- function CommitCard(props) {
40041
- const borderColor = props.isSkipped ? "yellow" : "cyan";
40042
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
40043
- Box_default,
40044
- {
40045
- flexDirection: "column",
40046
- borderStyle: "bold",
40047
- borderColor,
40048
- paddingX: 2,
40049
- paddingY: 1,
40050
- marginBottom: 0,
40051
- children: [
40052
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { gap: 1, alignItems: "center", children: [
40053
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { dimColor: true, bold: true, children: [
40054
- String(props.index).padStart(String(props.total).length),
40055
- "/",
40056
- props.total
40057
- ] }),
40058
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TypeBadge, { type: props.type }),
40059
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { bold: true, color: "white", children: props.description })
40060
- ] }),
40061
- props.scope && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { marginLeft: 5, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { dimColor: true, italic: true, children: [
40062
- "scope: ",
40063
- props.scope
40064
- ] }) }),
40065
- props.isSkipped && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { backgroundColor: "yellow", color: "black", bold: true, children: [
40066
- " ",
40067
- "PULADO",
40068
- " "
40069
- ] }) }),
40070
- !props.isSkipped && props.body && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { marginTop: 1, marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: "white", children: props.body }) }),
40071
- !props.isSkipped && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { flexDirection: "column", marginTop: 1, children: props.files.map((f) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { gap: 1, marginLeft: 1, children: [
40072
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: "cyan", bold: true, children: "\u25B8" }),
40073
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { children: f.path }),
40074
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { dimColor: true, children: [
40075
- "[",
40076
- formatSelection(f),
40077
- "]"
40078
- ] })
40079
- ] }, f.path)) }),
40080
- !props.isSkipped && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { marginTop: 1, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
40081
- DiffStats,
40082
- {
40083
- additions: props.additions,
40084
- deletions: props.deletions,
40085
- showBar: true
40086
- }
40087
- ) })
40088
- ]
40089
- }
40090
- );
40091
- }
40586
+ // src/commands/pr.ts
40587
+ var import_react40 = __toESM(require_react(), 1);
40092
40588
 
40093
- // src/ui/components/commit-row.tsx
40589
+ // src/ui/pr-app.tsx
40590
+ var import_react39 = __toESM(require_react(), 1);
40094
40591
  var import_jsx_runtime11 = __toESM(require_jsx_runtime(), 1);
40095
- function CommitRow(props) {
40096
- const pad = String(props.total).length;
40097
- const num = `${String(props.index).padStart(pad)}/${props.total}`;
40098
- if (props.isSkipped) {
40099
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { gap: 1, marginLeft: 2, children: [
40100
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { dimColor: true, children: num }),
40101
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { dimColor: true, strikethrough: true, children: props.description }),
40102
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { backgroundColor: "yellow", color: "black", children: [
40103
- " ",
40104
- "skip",
40105
- " "
40106
- ] })
40107
- ] });
40108
- }
40109
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { gap: 1, marginLeft: 2, children: [
40110
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { dimColor: true, children: num }),
40111
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TypeBadge, { type: props.type }),
40112
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { dimColor: true, children: props.description }),
40113
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(DiffStats, { additions: props.additions, deletions: props.deletions })
40114
- ] });
40115
- }
40116
-
40117
- // src/ui/components/diff-viewer.tsx
40118
- var import_react36 = __toESM(require_react(), 1);
40119
- var import_jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
40120
- function DiffViewer({ filePath, patch, onClose }) {
40121
- const [scrollOffset, setScrollOffset] = (0, import_react36.useState)(0);
40122
- const termHeight = process.stdout.rows || 24;
40123
- use_input_default((input, key) => {
40124
- if (input === "q" || input === "d" || key.escape) {
40125
- onClose();
40592
+ var TERMINAL_PHASES3 = [
40593
+ "aborted",
40594
+ "error-auth",
40595
+ "error-api",
40596
+ "error-git",
40597
+ "error-plan"
40598
+ ];
40599
+ function PrApp({
40600
+ deps,
40601
+ onExit
40602
+ }) {
40603
+ const { exit } = use_app_default();
40604
+ const [phase, setPhase] = (0, import_react39.useState)("collecting");
40605
+ const [prTitle, setPrTitle] = (0, import_react39.useState)("");
40606
+ const [prBody, setPrBody] = (0, import_react39.useState)("");
40607
+ const [errorMsg, setErrorMsg] = (0, import_react39.useState)("");
40608
+ (0, import_react39.useEffect)(() => {
40609
+ if (!TERMINAL_PHASES3.includes(phase) && phase !== "copied" && phase !== "aborted")
40126
40610
  return;
40127
- }
40128
- if (key.upArrow || input === "k") {
40129
- setScrollOffset((prev) => Math.max(0, prev - 1));
40130
- }
40131
- if (key.downArrow || input === "j") {
40132
- setScrollOffset((prev) => prev + 1);
40133
- }
40134
- if (input === " " || key.pageDown) {
40135
- setScrollOffset((prev) => prev + (termHeight - 5));
40136
- }
40137
- if (input === "u" || key.pageUp) {
40138
- setScrollOffset((prev) => Math.max(0, prev - (termHeight - 5)));
40139
- }
40140
- if (input === "g") {
40141
- setScrollOffset(0);
40142
- }
40143
- });
40144
- const allLines = patch.split("\n");
40145
- const contentLines = [];
40146
- for (const line of allLines) {
40147
- if (line.startsWith("diff --git")) {
40148
- const match = line.match(/^diff --git a\/.+ b\/(.+)$/);
40149
- const file = match?.[1] ?? line;
40150
- contentLines.push(`__FILE__${file}`);
40151
- } else if (line.startsWith("index ") || line.startsWith("--- ") || line.startsWith("+++ ") || line.startsWith("old mode") || line.startsWith("new mode") || line.startsWith("new file") || line.startsWith("deleted file") || line.startsWith("similarity")) {
40152
- } else {
40153
- contentLines.push(line);
40154
- }
40155
- }
40156
- const totalLines = contentLines.length;
40157
- const viewportHeight = Math.max(1, termHeight - 5);
40158
- const maxScroll = Math.max(0, totalLines - viewportHeight);
40159
- const clamped = Math.min(scrollOffset, maxScroll);
40160
- const visibleLines = contentLines.slice(clamped, clamped + viewportHeight);
40161
- const scrollPercent = maxScroll > 0 ? Math.round(clamped / maxScroll * 100) : 100;
40162
- const termWidth = process.stdout.columns || 80;
40163
- const fileCount = contentLines.filter((l) => l.startsWith("__FILE__")).length;
40164
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { flexDirection: "column", children: [
40165
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { children: [
40166
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { backgroundColor: "cyan", color: "black", bold: true, children: [
40167
- " ",
40168
- "DIFF",
40169
- " "
40170
- ] }),
40171
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { bold: true, children: [
40172
- " ",
40173
- filePath,
40174
- " "
40175
- ] }),
40176
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { dimColor: true, children: [
40177
- "\xB7 ",
40178
- fileCount > 1 ? `${fileCount} arquivos \xB7 ` : "",
40179
- totalLines,
40180
- " linhas \xB7 ",
40181
- scrollPercent,
40182
- "%"
40183
- ] })
40184
- ] }),
40185
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { dimColor: true, children: "\u2500".repeat(Math.min(termWidth, 80)) }),
40186
- visibleLines.map((line, i) => {
40187
- const key = `dl-${clamped + i}`;
40188
- if (line.startsWith("__FILE__")) {
40189
- const file = line.slice(8);
40190
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { flexDirection: "column", marginTop: i > 0 ? 1 : 0, children: [
40191
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { dimColor: true, children: "\u2500".repeat(Math.min(termWidth, 80)) }),
40192
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { gap: 1, children: [
40193
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { backgroundColor: "blue", color: "white", bold: true, children: [
40194
- " ",
40195
- "FILE",
40196
- " "
40197
- ] }),
40198
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { bold: true, color: "white", children: file })
40199
- ] }),
40200
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { dimColor: true, children: "\u2500".repeat(Math.min(termWidth, 80)) })
40201
- ] }, key);
40611
+ const code = phase === "copied" || phase === "aborted" ? 0 : 1;
40612
+ exit();
40613
+ onExit(code);
40614
+ }, [phase]);
40615
+ (0, import_react39.useEffect)(() => {
40616
+ async function run2() {
40617
+ const token = deps.readToken();
40618
+ if (!token) {
40619
+ setErrorMsg("N\xE3o autenticado. Execute repomind login primeiro.");
40620
+ setPhase("error-auth");
40621
+ return;
40202
40622
  }
40203
- const num = String(clamped + i + 1).padStart(4);
40204
- if (line.startsWith("@@")) {
40205
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { color: "cyan", dimColor: true, children: [
40206
- " ",
40207
- " ",
40208
- line
40209
- ] }, key);
40623
+ let diff2;
40624
+ try {
40625
+ diff2 = await deps.getDiffBetweenBranches();
40626
+ } catch (e) {
40627
+ const msg = e instanceof Error ? e.message : "Erro ao obter diff entre branches.";
40628
+ setErrorMsg(msg);
40629
+ setPhase("error-git");
40630
+ return;
40210
40631
  }
40211
- if (line.startsWith("+")) {
40212
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { color: "green", children: [
40213
- num,
40214
- " ",
40215
- line
40216
- ] }, key);
40632
+ if (!diff2 || diff2.trim() === "") {
40633
+ setErrorMsg(
40634
+ "Nenhuma diferen\xE7a encontrada entre esta branch e a base (main/master)."
40635
+ );
40636
+ setPhase("error-git");
40637
+ return;
40217
40638
  }
40218
- if (line.startsWith("-")) {
40219
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { color: "red", children: [
40220
- num,
40221
- " ",
40222
- line
40223
- ] }, key);
40639
+ setPhase("generating");
40640
+ try {
40641
+ const result = await deps.apiPost(
40642
+ "/pr/generate",
40643
+ { diff: diff2 },
40644
+ token
40645
+ );
40646
+ setPrTitle(result.title);
40647
+ setPrBody(result.body);
40648
+ setPhase("result");
40649
+ } catch (e) {
40650
+ if (e instanceof PlanLimitError) {
40651
+ setErrorMsg(
40652
+ `Limite do plano ${e.plan === "free" ? "Free" : "Pro"} atingido (${e.used}/${e.limit} commits este m\xEAs)
40653
+ \u2192 Fa\xE7a upgrade em https://app.repomind.dev/pricing`
40654
+ );
40655
+ setPhase("error-plan");
40656
+ } else if (e instanceof ApiError && e.status === 401) {
40657
+ setErrorMsg("Sess\xE3o expirada. Execute repomind login novamente.");
40658
+ setPhase("error-api");
40659
+ } else {
40660
+ const detail = e instanceof Error ? e.message : "Erro desconhecido";
40661
+ const verbose2 = process.argv.includes("--verbose") || process.argv.includes("-v") || !!process.env.REPOMIND_DEBUG;
40662
+ setErrorMsg(
40663
+ verbose2 ? `Falha ao gerar PR description: ${detail}` : "Falha ao gerar PR description. Tente novamente."
40664
+ );
40665
+ if (verbose2 && e instanceof Error && e.stack) {
40666
+ console.error(e.stack);
40667
+ }
40668
+ setPhase("error-api");
40669
+ }
40224
40670
  }
40225
- if (line.startsWith("\\")) {
40226
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { dimColor: true, children: [
40227
- " ",
40228
- line
40229
- ] }, key);
40671
+ }
40672
+ run2();
40673
+ }, []);
40674
+ use_input_default(
40675
+ async (input) => {
40676
+ if (phase !== "result") return;
40677
+ if (input.toLowerCase() === "c") {
40678
+ const fullText = `${prTitle}
40679
+
40680
+ ${prBody}`;
40681
+ await deps.copyToClipboard(fullText);
40682
+ setPhase("copied");
40683
+ } else if (input.toLowerCase() === "q") {
40684
+ setPhase("aborted");
40230
40685
  }
40231
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { dimColor: true, children: [
40232
- num,
40233
- " ",
40234
- line
40235
- ] }, key);
40236
- }),
40237
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { dimColor: true, children: "\u2500".repeat(Math.min(termWidth, 80)) }),
40238
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { gap: 1, children: [
40239
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { backgroundColor: "gray", color: "white", bold: true, children: [
40240
- " ",
40241
- "\u2191\u2193",
40242
- " "
40686
+ },
40687
+ { isActive: phase === "result" }
40688
+ );
40689
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { flexDirection: "column", children: [
40690
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Header, { title: "repomind pr" }),
40691
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 1, children: [
40692
+ phase === "collecting" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { gap: 1, marginTop: 1, children: [
40693
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.cyan, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(build_default, { type: "dots" }) }),
40694
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.dim, children: "Coletando diff entre branches..." })
40243
40695
  ] }),
40244
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { dimColor: true, children: "rolar" }),
40245
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { backgroundColor: "gray", color: "white", bold: true, children: [
40246
- " ",
40247
- "space",
40248
- " "
40696
+ phase === "generating" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { gap: 1, marginTop: 1, children: [
40697
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.cyan, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(build_default, { type: "dots" }) }),
40698
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.dim, children: "Gerando PR description com IA..." })
40249
40699
  ] }),
40250
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { dimColor: true, children: "p\xE1gina" }),
40251
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { backgroundColor: "gray", color: "white", bold: true, children: [
40252
- " ",
40253
- "g",
40254
- " "
40700
+ phase === "result" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { flexDirection: "column", marginTop: 1, children: [
40701
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
40702
+ Box_default,
40703
+ {
40704
+ flexDirection: "column",
40705
+ borderStyle: "round",
40706
+ borderColor: C.cyan,
40707
+ paddingX: 1,
40708
+ children: [
40709
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { bold: true, color: C.white, children: prTitle }),
40710
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.dim, children: prBody }) })
40711
+ ]
40712
+ }
40713
+ ),
40714
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
40715
+ KeyHints,
40716
+ {
40717
+ hints: [
40718
+ { key: "c", label: "copiar" },
40719
+ { key: "q", label: "sair" }
40720
+ ]
40721
+ }
40722
+ )
40255
40723
  ] }),
40256
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { dimColor: true, children: "topo" }),
40257
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { backgroundColor: "gray", color: "white", bold: true, children: [
40258
- " ",
40259
- "q",
40260
- " "
40724
+ phase === "copied" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { gap: 1, marginTop: 1, children: [
40725
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.green, children: "\u2713" }),
40726
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { bold: true, children: "PR description copiada para o clipboard!" })
40727
+ ] }),
40728
+ phase === "aborted" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Box_default, { gap: 1, marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.dim, children: "Saindo..." }) }),
40729
+ phase === "error-auth" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Box_default, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { gap: 1, children: [
40730
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.red, children: "\u2717" }),
40731
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.red, children: errorMsg })
40732
+ ] }) }),
40733
+ phase === "error-git" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Box_default, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { gap: 1, children: [
40734
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.yellow, children: "\u25B2" }),
40735
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.yellow, children: errorMsg })
40736
+ ] }) }),
40737
+ phase === "error-api" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Box_default, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { gap: 1, children: [
40738
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.red, children: "\u2717" }),
40739
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.red, children: errorMsg })
40740
+ ] }) }),
40741
+ phase === "error-plan" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { flexDirection: "column", marginTop: 1, children: [
40742
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { gap: 1, children: [
40743
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.yellow, children: "\u25B2" }),
40744
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.yellow, children: errorMsg.split("\n")[0] })
40745
+ ] }),
40746
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Box_default, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: C.dim, children: errorMsg.split("\n")[1] }) })
40747
+ ] })
40748
+ ] })
40749
+ ] });
40750
+ }
40751
+
40752
+ // src/commands/pr.ts
40753
+ async function detectBaseBranch() {
40754
+ const proc = Bun.spawn(["git", "rev-parse", "--verify", "main"], {
40755
+ stdout: "pipe",
40756
+ stderr: "pipe"
40757
+ });
40758
+ const code = await proc.exited;
40759
+ return code === 0 ? "main" : "master";
40760
+ }
40761
+ async function getDiffBetweenBranches() {
40762
+ const baseBranch = await detectBaseBranch();
40763
+ const mergeBaseProc = Bun.spawn(["git", "merge-base", "HEAD", baseBranch], {
40764
+ stdout: "pipe",
40765
+ stderr: "pipe"
40766
+ });
40767
+ const mergeBaseCode = await mergeBaseProc.exited;
40768
+ if (mergeBaseCode !== 0) {
40769
+ throw new Error(
40770
+ `N\xE3o foi poss\xEDvel encontrar merge-base entre HEAD e ${baseBranch}.`
40771
+ );
40772
+ }
40773
+ const mergeBase = (await new Response(mergeBaseProc.stdout).text()).trim();
40774
+ const diffProc = Bun.spawn(["git", "diff", `${mergeBase}...HEAD`], {
40775
+ stdout: "pipe",
40776
+ stderr: "pipe"
40777
+ });
40778
+ return new Response(diffProc.stdout).text();
40779
+ }
40780
+ async function copyToClipboard(text) {
40781
+ const cmd = process.platform === "darwin" ? "pbcopy" : "xclip";
40782
+ try {
40783
+ const proc = Bun.spawn([cmd], {
40784
+ stdin: new ReadableStream({
40785
+ start(ctrl) {
40786
+ ctrl.enqueue(new TextEncoder().encode(text));
40787
+ ctrl.close();
40788
+ }
40789
+ })
40790
+ });
40791
+ await proc.exited;
40792
+ } catch {
40793
+ console.log(
40794
+ "\n(Clipboard n\xE3o dispon\xEDvel \u2014 copie o texto acima manualmente)"
40795
+ );
40796
+ }
40797
+ }
40798
+ async function prCommand() {
40799
+ let exitCode = 0;
40800
+ enterImmersive();
40801
+ const { waitUntilExit } = render_default(
40802
+ import_react40.default.createElement(PrApp, {
40803
+ deps: {
40804
+ readToken,
40805
+ getDiffBetweenBranches,
40806
+ apiPost: (path, body, token) => apiClient.post(path, body, token),
40807
+ copyToClipboard
40808
+ },
40809
+ onExit: (code) => {
40810
+ exitCode = code;
40811
+ }
40812
+ })
40813
+ );
40814
+ await waitUntilExit();
40815
+ exitImmersive();
40816
+ process.exit(exitCode);
40817
+ }
40818
+
40819
+ // src/commands/split.ts
40820
+ var import_react42 = __toESM(require_react(), 1);
40821
+
40822
+ // src/ui/split-app.tsx
40823
+ var import_react41 = __toESM(require_react(), 1);
40824
+
40825
+ // src/ui/components/diff-stats.tsx
40826
+ var import_jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
40827
+ function DiffStats({
40828
+ additions,
40829
+ deletions,
40830
+ showBar = false
40831
+ }) {
40832
+ if (!showBar) {
40833
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { gap: 0, children: [
40834
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { color: C.green, bold: true, children: [
40835
+ "+",
40836
+ additions
40261
40837
  ] }),
40262
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { dimColor: true, children: "sair" }),
40263
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { dimColor: true, children: [
40264
- " ",
40265
- "\u2502 ",
40266
- clamped + 1,
40838
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: C.dim, children: " / " }),
40839
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { color: C.red, bold: true, children: [
40267
40840
  "-",
40268
- Math.min(clamped + viewportHeight, totalLines),
40269
- "/",
40270
- totalLines
40841
+ deletions
40271
40842
  ] })
40843
+ ] });
40844
+ }
40845
+ const total = additions + deletions;
40846
+ const barWidth = Math.min(total, 20);
40847
+ const addBar = total > 0 ? Math.max(1, Math.round(additions / total * barWidth)) : 0;
40848
+ const delBar = Math.max(0, barWidth - addBar);
40849
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { gap: 1, children: [
40850
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { color: C.green, bold: true, children: [
40851
+ "+",
40852
+ additions
40853
+ ] }),
40854
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { color: C.red, bold: true, children: [
40855
+ "-",
40856
+ deletions
40857
+ ] }),
40858
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { gap: 0, children: [
40859
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: C.green, children: "\u2588".repeat(addBar) }),
40860
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: C.red, children: "\u2588".repeat(delBar) })
40272
40861
  ] })
40273
40862
  ] });
40274
40863
  }
40275
40864
 
40276
- // src/ui/components/progress-bar.tsx
40865
+ // src/ui/components/commit-card.tsx
40277
40866
  var import_jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
40278
- function ProgressBar({ current, total, width = 24 }) {
40279
- const ratio = total > 0 ? current / total : 0;
40280
- const filled = Math.round(ratio * width);
40281
- const empty = width - filled;
40282
- const percent = Math.round(ratio * 100);
40283
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Box_default, { gap: 1, children: [
40284
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { color: "cyan", bold: true, children: "\u2501".repeat(filled) }),
40285
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { dimColor: true, children: "\u2500".repeat(empty) }),
40286
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text, { bold: true, color: ratio >= 1 ? "green" : "cyan", children: [
40287
- percent,
40288
- "%"
40289
- ] }),
40290
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text, { dimColor: true, children: [
40291
- "(",
40292
- current,
40293
- "/",
40294
- total,
40295
- ")"
40296
- ] })
40867
+ function formatSelection(f) {
40868
+ if (f.selection === "all") return "all";
40869
+ return f.selection.map((h) => `h${h.hunkIndex}`).join(",");
40870
+ }
40871
+ function CommitCard(props) {
40872
+ const borderColor = props.isSkipped ? C.yellow : C.cyan;
40873
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
40874
+ Box_default,
40875
+ {
40876
+ flexDirection: "column",
40877
+ borderStyle: "round",
40878
+ borderColor,
40879
+ paddingX: 1,
40880
+ paddingY: 0,
40881
+ marginBottom: 0,
40882
+ children: [
40883
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Box_default, { gap: 1, alignItems: "center", children: [
40884
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text, { color: C.dim, bold: true, children: [
40885
+ String(props.index).padStart(String(props.total).length),
40886
+ "/",
40887
+ props.total
40888
+ ] }),
40889
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TypeBadge, { type: props.type }),
40890
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { bold: true, color: C.white, children: props.description })
40891
+ ] }),
40892
+ props.scope && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Box_default, { marginLeft: 5, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text, { color: C.dim, italic: true, children: [
40893
+ "scope: ",
40894
+ props.scope
40895
+ ] }) }),
40896
+ props.isSkipped && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text, { backgroundColor: C.yellow, color: "#000", bold: true, children: [
40897
+ " ",
40898
+ "PULADO",
40899
+ " "
40900
+ ] }) }),
40901
+ !props.isSkipped && props.body && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Box_default, { marginTop: 1, marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { color: C.white, children: props.body }) }),
40902
+ !props.isSkipped && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Box_default, { flexDirection: "column", marginTop: 1, children: props.files.map((f) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Box_default, { gap: 1, marginLeft: 1, children: [
40903
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { color: C.cyan, bold: true, children: "\u25B8" }),
40904
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { children: f.path }),
40905
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text, { color: C.dim, children: [
40906
+ "[",
40907
+ formatSelection(f),
40908
+ "]"
40909
+ ] })
40910
+ ] }, f.path)) }),
40911
+ !props.isSkipped && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Box_default, { marginTop: 1, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
40912
+ DiffStats,
40913
+ {
40914
+ additions: props.additions,
40915
+ deletions: props.deletions,
40916
+ showBar: true
40917
+ }
40918
+ ) })
40919
+ ]
40920
+ }
40921
+ );
40922
+ }
40923
+
40924
+ // src/ui/components/commit-row.tsx
40925
+ var import_jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
40926
+ function CommitRow(props) {
40927
+ const pad = String(props.total).length;
40928
+ const num = `${String(props.index).padStart(pad)}/${props.total}`;
40929
+ if (props.isSkipped) {
40930
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Box_default, { gap: 1, marginLeft: 2, children: [
40931
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { color: C.dim, children: num }),
40932
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { color: C.dim, strikethrough: true, children: props.description }),
40933
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Text, { backgroundColor: C.yellow, color: "#000", children: [
40934
+ " ",
40935
+ "skip",
40936
+ " "
40937
+ ] })
40938
+ ] });
40939
+ }
40940
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Box_default, { gap: 1, marginLeft: 2, children: [
40941
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { color: C.dim, children: num }),
40942
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TypeBadge, { type: props.type }),
40943
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { color: C.dim, children: props.description }),
40944
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DiffStats, { additions: props.additions, deletions: props.deletions })
40297
40945
  ] });
40298
40946
  }
40299
40947
 
40300
40948
  // src/ui/split-app.tsx
40301
- var import_jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
40302
- var TERMINAL_PHASES3 = [
40949
+ var import_jsx_runtime15 = __toESM(require_jsx_runtime(), 1);
40950
+ var STEP_LABELS2 = {
40951
+ understand: "Entendendo altera\xE7\xF5es",
40952
+ classify: "Classificando contextos",
40953
+ group: "Agrupando em commits",
40954
+ generate: "Gerando mensagens"
40955
+ };
40956
+ var TERMINAL_PHASES4 = [
40303
40957
  "done",
40304
40958
  "aborted",
40305
40959
  "error-auth",
@@ -40346,23 +41000,54 @@ function SplitApp({
40346
41000
  onExit
40347
41001
  }) {
40348
41002
  const { exit } = use_app_default();
40349
- const [phase, setPhase] = (0, import_react37.useState)("collecting");
40350
- const [groups, setGroups] = (0, import_react37.useState)([]);
40351
- const [selectedIndex, setSelectedIndex] = (0, import_react37.useState)(0);
40352
- const [skippedGroups, setSkippedGroups] = (0, import_react37.useState)(/* @__PURE__ */ new Set());
40353
- const [commitProgress, setCommitProgress] = (0, import_react37.useState)(0);
40354
- const [errorMsg, setErrorMsg] = (0, import_react37.useState)("");
40355
- const [originalFiles, setOriginalFiles] = (0, import_react37.useState)([]);
40356
- const [hunksMap, setHunksMap] = (0, import_react37.useState)(/* @__PURE__ */ new Map());
40357
- const [patchMap, setPatchMap] = (0, import_react37.useState)(/* @__PURE__ */ new Map());
40358
- const [authToken, setAuthToken] = (0, import_react37.useState)("");
40359
- (0, import_react37.useEffect)(() => {
40360
- if (!TERMINAL_PHASES3.includes(phase)) return;
41003
+ const committedMessagesRef = (0, import_react41.useRef)([]);
41004
+ const [phase, setPhase] = (0, import_react41.useState)("collecting");
41005
+ const [groups, setGroups] = (0, import_react41.useState)([]);
41006
+ const [selectedIndex, setSelectedIndex] = (0, import_react41.useState)(0);
41007
+ const [skippedGroups, setSkippedGroups] = (0, import_react41.useState)(/* @__PURE__ */ new Set());
41008
+ const [commitProgress, setCommitProgress] = (0, import_react41.useState)(0);
41009
+ const [errorMsg, setErrorMsg] = (0, import_react41.useState)("");
41010
+ const [originalFiles, setOriginalFiles] = (0, import_react41.useState)([]);
41011
+ const [hunksMap, setHunksMap] = (0, import_react41.useState)(/* @__PURE__ */ new Map());
41012
+ const [patchMap, setPatchMap] = (0, import_react41.useState)(/* @__PURE__ */ new Map());
41013
+ const [authToken, setAuthToken] = (0, import_react41.useState)("");
41014
+ const [streamPayload, setStreamPayload] = (0, import_react41.useState)(
41015
+ null
41016
+ );
41017
+ const streamOptions = streamPayload && phase === "analyzing" ? {
41018
+ path: streamPayload.path,
41019
+ body: streamPayload.body,
41020
+ token: streamPayload.token,
41021
+ postStream: deps.postStream,
41022
+ stepLabels: STEP_LABELS2,
41023
+ timeoutMs: 3e5
41024
+ } : null;
41025
+ const stream = usePipelineStream(streamOptions);
41026
+ (0, import_react41.useEffect)(() => {
41027
+ if (!TERMINAL_PHASES4.includes(phase)) return;
40361
41028
  const code = phase === "done" || phase === "aborted" ? 0 : 1;
40362
41029
  exit();
40363
- onExit(code);
41030
+ onExit(code, phase === "done" ? committedMessagesRef.current : void 0);
40364
41031
  }, [phase]);
40365
- (0, import_react37.useEffect)(() => {
41032
+ (0, import_react41.useEffect)(() => {
41033
+ if (phase !== "analyzing") return;
41034
+ if (stream.result) {
41035
+ const sortedGroups = stream.result.groups.sort(
41036
+ (a, b) => a.order - b.order
41037
+ );
41038
+ setGroups(sortedGroups);
41039
+ setPhase("review");
41040
+ return;
41041
+ }
41042
+ if (stream.error) {
41043
+ const verbose2 = process.argv.includes("--verbose") || process.argv.includes("-v") || !!process.env.REPOMIND_DEBUG;
41044
+ setErrorMsg(
41045
+ verbose2 ? `Falha ao analisar altera\xE7\xF5es: ${stream.error}` : "Falha ao analisar altera\xE7\xF5es. Tente novamente."
41046
+ );
41047
+ setPhase("error-api");
41048
+ }
41049
+ }, [stream.result, stream.error, phase]);
41050
+ (0, import_react41.useEffect)(() => {
40366
41051
  async function run2() {
40367
41052
  const token = deps.readToken();
40368
41053
  if (!token) {
@@ -40427,42 +41112,12 @@ function SplitApp({
40427
41112
  setHunksMap(hMap);
40428
41113
  setPatchMap(pMap);
40429
41114
  const manifest = deps.buildSplitManifest(files, hMap);
40430
- setPhase("analyzing");
40431
- try {
40432
- const body = { manifest };
40433
- if (deps.fileConfig && Object.keys(deps.fileConfig).length > 0) {
40434
- body.config = deps.fileConfig;
40435
- }
40436
- const result = await deps.apiPost(
40437
- "/split/analyze",
40438
- body,
40439
- token
40440
- );
40441
- const sortedGroups = result.groups.sort((a, b) => a.order - b.order);
40442
- setGroups(sortedGroups);
40443
- setPhase("review");
40444
- } catch (e) {
40445
- if (e instanceof PlanLimitError) {
40446
- setErrorMsg(
40447
- `Limite do plano ${e.plan === "free" ? "Free" : "Pro"} atingido (${e.used}/${e.limit} commits este m\xEAs)
40448
- \u2192 Fa\xE7a upgrade em https://app.repomind.dev/pricing`
40449
- );
40450
- setPhase("error-plan");
40451
- } else if (e instanceof ApiError && e.status === 401) {
40452
- setErrorMsg("Sess\xE3o expirada. Execute repomind login novamente.");
40453
- setPhase("error-api");
40454
- } else {
40455
- const detail = e instanceof Error ? e.message : "Erro desconhecido";
40456
- const verbose2 = process.argv.includes("--verbose") || process.argv.includes("-v") || !!process.env.REPOMIND_DEBUG;
40457
- setErrorMsg(
40458
- verbose2 ? `Falha ao analisar altera\xE7\xF5es: ${detail}` : "Falha ao analisar altera\xE7\xF5es. Tente novamente."
40459
- );
40460
- if (verbose2 && e instanceof Error && e.stack) {
40461
- console.error(e.stack);
40462
- }
40463
- setPhase("error-api");
40464
- }
41115
+ const body = { manifest };
41116
+ if (deps.fileConfig && Object.keys(deps.fileConfig).length > 0) {
41117
+ body.config = deps.fileConfig;
40465
41118
  }
41119
+ setStreamPayload({ path: "/split/analyze", body, token });
41120
+ setPhase("analyzing");
40466
41121
  }
40467
41122
  run2();
40468
41123
  }, []);
@@ -40554,9 +41209,9 @@ function SplitApp({
40554
41209
  });
40555
41210
  }
40556
41211
  }
40557
- }
40558
- if (lineSelections.length > 0) {
40559
- await deps.stageLines(currentDiff, lineSelections);
41212
+ if (lineSelections.length > 0) {
41213
+ await deps.stageLines(currentDiff, lineSelections);
41214
+ }
40560
41215
  }
40561
41216
  }
40562
41217
  }
@@ -40581,184 +41236,179 @@ function SplitApp({
40581
41236
  return;
40582
41237
  }
40583
41238
  }
41239
+ committedMessagesRef.current = activeGroups2.map((g) => g.message);
40584
41240
  setPhase("done");
40585
41241
  }
40586
41242
  const activeGroups = groups.filter((g) => !skippedGroups.has(g.groupId));
40587
41243
  const activeGroupCount = activeGroups.length;
40588
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Box_default, { flexDirection: "column", gap: 0, paddingTop: 1, children: [
40589
- phase === "collecting" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
40590
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Header, {}),
40591
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
40592
- StepList,
41244
+ if (phase === "viewing-diff") {
41245
+ const group = groups[selectedIndex];
41246
+ if (group) {
41247
+ const combinedPatch = group.files.map((f) => patchMap.get(f.path) ?? "").filter(Boolean).join("\n");
41248
+ const mainFile = group.files[0]?.path ?? "diff";
41249
+ const label = group.files.length > 1 ? `${mainFile} (+${group.files.length - 1} arquivos)` : mainFile;
41250
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
41251
+ DiffViewer,
40593
41252
  {
40594
- steps: [{ label: "Coletando altera\xE7\xF5es", status: "active" }]
41253
+ filePath: label,
41254
+ patch: combinedPatch,
41255
+ onClose: () => setPhase("review")
40595
41256
  }
40596
- )
40597
- ] }),
40598
- phase === "analyzing" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
40599
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Header, {}),
40600
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
41257
+ );
41258
+ }
41259
+ }
41260
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { flexDirection: "column", gap: 0, children: [
41261
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Header, { title: "repomind split" }),
41262
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 1, children: [
41263
+ (phase === "collecting" || phase === "analyzing") && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
40601
41264
  StepList,
40602
41265
  {
40603
41266
  steps: [
40604
41267
  {
40605
- label: "Altera\xE7\xF5es coletadas",
40606
- status: "done",
40607
- detail: `${originalFiles.length} arquivos`
41268
+ label: "Coletando altera\xE7\xF5es",
41269
+ status: phase === "collecting" ? "active" : "done",
41270
+ detail: phase !== "collecting" ? `${originalFiles.length} arquivos` : void 0
40608
41271
  },
40609
- { label: "Analisando com IA", status: "active" }
41272
+ // Steps dinâmicos do SSE (aparecem quando pipeline anuncia step:start)
41273
+ ...stream.steps,
41274
+ // Fallback: se stream ainda não tem steps e está analisando, exibir step genérico
41275
+ ...phase === "analyzing" && stream.steps.length === 0 ? [
41276
+ {
41277
+ label: "Analisando com IA",
41278
+ status: "active"
41279
+ }
41280
+ ] : []
40610
41281
  ]
40611
41282
  }
40612
- )
40613
- ] }),
40614
- phase === "review" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
40615
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Header, {}),
40616
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Box_default, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Text, { bold: true, children: [
40617
- groups.length,
40618
- " commits sugeridos"
40619
- ] }) }),
40620
- groups.map((group, idx) => {
40621
- const isSelected = idx === selectedIndex;
40622
- const isSkipped = skippedGroups.has(group.groupId);
40623
- const stats = computeGroupStats(group.files, originalFiles);
40624
- if (isSelected) {
40625
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
40626
- CommitCard,
41283
+ ),
41284
+ phase === "review" && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
41285
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Box_default, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Text, { bold: true, children: [
41286
+ groups.length,
41287
+ " commits sugeridos"
41288
+ ] }) }),
41289
+ groups.map((group, idx) => {
41290
+ const isSelected = idx === selectedIndex;
41291
+ const isSkipped = skippedGroups.has(group.groupId);
41292
+ const stats = computeGroupStats(group.files, originalFiles);
41293
+ if (isSelected) {
41294
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
41295
+ CommitCard,
41296
+ {
41297
+ index: idx + 1,
41298
+ total: groups.length,
41299
+ type: group.type,
41300
+ scope: group.scope,
41301
+ description: group.description,
41302
+ body: group.body,
41303
+ files: group.files,
41304
+ additions: stats.additions,
41305
+ deletions: stats.deletions,
41306
+ isSkipped
41307
+ },
41308
+ group.groupId
41309
+ );
41310
+ }
41311
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
41312
+ CommitRow,
40627
41313
  {
40628
41314
  index: idx + 1,
40629
41315
  total: groups.length,
40630
41316
  type: group.type,
40631
- scope: group.scope,
40632
41317
  description: group.description,
40633
- body: group.body,
40634
- files: group.files,
40635
41318
  additions: stats.additions,
40636
41319
  deletions: stats.deletions,
40637
- isSkipped
41320
+ isSkipped,
41321
+ isSelected: false
40638
41322
  },
40639
41323
  group.groupId
40640
41324
  );
40641
- }
40642
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
40643
- CommitRow,
41325
+ }),
41326
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
41327
+ KeyHints,
40644
41328
  {
40645
- index: idx + 1,
40646
- total: groups.length,
40647
- type: group.type,
40648
- description: group.description,
40649
- additions: stats.additions,
40650
- deletions: stats.deletions,
40651
- isSkipped,
40652
- isSelected: false
40653
- },
40654
- group.groupId
40655
- );
40656
- }),
40657
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
40658
- KeyHints,
40659
- {
40660
- hints: [
40661
- { key: "\u2191\u2193", label: "navegar" },
40662
- { key: "d", label: "diff" },
40663
- { key: "enter", label: "confirmar" },
40664
- { key: "s", label: "pular" },
40665
- { key: "q", label: "abortar" }
40666
- ]
40667
- }
40668
- )
40669
- ] }),
40670
- phase === "viewing-diff" && (() => {
40671
- const group = groups[selectedIndex];
40672
- if (!group) return null;
40673
- const combinedPatch = group.files.map((f) => patchMap.get(f.path) ?? "").filter(Boolean).join("\n");
40674
- const mainFile = group.files[0]?.path ?? "diff";
40675
- const label = group.files.length > 1 ? `${mainFile} (+${group.files.length - 1} arquivos)` : mainFile;
40676
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
40677
- DiffViewer,
40678
- {
40679
- filePath: label,
40680
- patch: combinedPatch,
40681
- onClose: () => setPhase("review")
40682
- }
40683
- );
40684
- })(),
40685
- phase === "committing" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
40686
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Header, {}),
40687
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
40688
- StepList,
40689
- {
40690
- steps: activeGroups.map((g, i) => ({
40691
- label: g.message,
40692
- status: i < commitProgress ? "done" : i === commitProgress ? "active" : "pending"
40693
- }))
40694
- }
40695
- ),
40696
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Box_default, { marginTop: 1, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ProgressBar, { current: commitProgress, total: activeGroupCount }) })
40697
- ] }),
40698
- phase === "done" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
40699
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Header, {}),
40700
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
40701
- StepList,
40702
- {
40703
- steps: activeGroups.map((g) => ({
40704
- label: g.message,
40705
- status: "done"
40706
- }))
40707
- }
40708
- ),
40709
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Box_default, { marginTop: 1, gap: 1, children: [
40710
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { color: "green", children: "\u2728" }),
40711
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Text, { bold: true, color: "green", children: [
40712
- activeGroupCount,
40713
- " commit",
40714
- activeGroupCount !== 1 ? "s" : "",
40715
- " ",
40716
- "realizado",
40717
- activeGroupCount !== 1 ? "s" : "",
40718
- " com sucesso"
40719
- ] })
40720
- ] })
40721
- ] }),
40722
- phase === "aborted" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
40723
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Header, {}),
40724
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Box_default, { gap: 1, children: [
40725
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { color: "yellow", children: "\u25C6" }),
40726
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { dimColor: true, children: "Abortado. Nenhum commit foi feito." })
40727
- ] })
40728
- ] }),
40729
- phase === "error-commit" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
40730
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Header, {}),
40731
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
40732
- StepList,
40733
- {
40734
- steps: activeGroups.map((g, i) => ({
40735
- label: g.message,
40736
- status: i < commitProgress ? "done" : i === commitProgress ? "error" : "pending"
40737
- }))
40738
- }
40739
- ),
40740
- commitProgress > 0 && commitProgress < activeGroupCount && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Box_default, { marginTop: 1, gap: 1, children: [
40741
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { color: "yellow", children: "\u25B2" }),
40742
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Text, { color: "yellow", children: [
41329
+ hints: [
41330
+ { key: "\u2191\u2193", label: "navegar" },
41331
+ { key: "d", label: "diff" },
41332
+ { key: "enter", label: "confirmar" },
41333
+ { key: "s", label: "pular" },
41334
+ { key: "q", label: "abortar" }
41335
+ ]
41336
+ }
41337
+ )
41338
+ ] }),
41339
+ phase === "committing" && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
41340
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Box_default, { flexDirection: "column", marginTop: 1, children: activeGroups.map((g, i) => {
41341
+ const isDone = i < commitProgress;
41342
+ const isActive = i === commitProgress;
41343
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { flexDirection: "column", children: [
41344
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { gap: 1, alignItems: "center", children: [
41345
+ isDone ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.green, children: "\u2713" }) : isActive ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.cyan, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(build_default, { type: "dots" }) }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.dim, children: "\u25CB" }),
41346
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TypeBadge, { type: g.type }),
41347
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
41348
+ Text,
41349
+ {
41350
+ color: isDone ? C.green : isActive ? C.white : C.dim,
41351
+ bold: isActive,
41352
+ children: g.description
41353
+ }
41354
+ )
41355
+ ] }),
41356
+ i < activeGroups.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.dim, children: "\u2502" })
41357
+ ] }, g.groupId);
41358
+ }) }),
41359
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Text, { color: C.dim, children: [
40743
41360
  commitProgress,
40744
41361
  "/",
40745
41362
  activeGroupCount,
40746
- " commits realizados antes do erro"
41363
+ " commit",
41364
+ activeGroupCount !== 1 ? "s" : ""
41365
+ ] }) })
41366
+ ] }),
41367
+ phase === "done" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Box_default, { flexDirection: "column", marginTop: 1, children: activeGroups.map((g, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { flexDirection: "column", children: [
41368
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { gap: 1, alignItems: "center", children: [
41369
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.green, children: "\u2713" }),
41370
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TypeBadge, { type: g.type }),
41371
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.green, children: g.description })
41372
+ ] }),
41373
+ i < activeGroups.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.dim, children: "\u2502" })
41374
+ ] }, g.groupId)) }),
41375
+ phase === "aborted" && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { gap: 1, marginTop: 1, children: [
41376
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.yellow, children: "\u25C6" }),
41377
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { dimColor: true, children: "Abortado. Nenhum commit foi feito." })
41378
+ ] }),
41379
+ phase === "error-commit" && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
41380
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Box_default, { flexDirection: "column", marginTop: 1, children: activeGroups.map((g, i) => {
41381
+ const isDone = i < commitProgress;
41382
+ const isError = i === commitProgress;
41383
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { flexDirection: "column", children: [
41384
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { gap: 1, alignItems: "center", children: [
41385
+ isDone ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.green, children: "\u2713" }) : isError ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.red, children: "\u2717" }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.dim, children: "\u25CB" }),
41386
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TypeBadge, { type: g.type }),
41387
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: isDone ? C.green : isError ? C.red : C.dim, children: g.description })
41388
+ ] }),
41389
+ i < activeGroups.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.dim, children: "\u2502" })
41390
+ ] }, g.groupId);
41391
+ }) }),
41392
+ commitProgress > 0 && commitProgress < activeGroupCount && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { marginTop: 1, gap: 1, children: [
41393
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.yellow, children: "\u25B2" }),
41394
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Text, { color: C.yellow, children: [
41395
+ commitProgress,
41396
+ "/",
41397
+ activeGroupCount,
41398
+ " commits realizados antes do erro"
41399
+ ] })
41400
+ ] }),
41401
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { gap: 1, marginTop: 1, children: [
41402
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.red, children: "\u2717" }),
41403
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.red, children: errorMsg })
40747
41404
  ] })
40748
41405
  ] }),
40749
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Box_default, { gap: 1, marginTop: commitProgress > 0 ? 0 : 1, children: [
40750
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { color: "red", children: "\u2717" }),
40751
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { color: "red", children: errorMsg })
40752
- ] })
40753
- ] }),
40754
- (phase === "error-auth" || phase === "error-empty" || phase === "error-git" || phase === "error-api" || phase === "error-plan") && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
40755
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Header, {}),
40756
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Box_default, { gap: 1, children: [
40757
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { color: "red", children: "\u2717" }),
40758
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { color: "red", children: errorMsg })
40759
- ] })
40760
- ] }),
40761
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Box_default, { marginTop: 1 })
41406
+ (phase === "error-auth" || phase === "error-empty" || phase === "error-git" || phase === "error-api" || phase === "error-plan") && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { gap: 1, marginTop: 1, children: [
41407
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.red, children: "\u2717" }),
41408
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: C.red, children: errorMsg })
41409
+ ] }),
41410
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Box_default, { marginTop: 1 })
41411
+ ] })
40762
41412
  ] });
40763
41413
  }
40764
41414
 
@@ -40774,8 +41424,10 @@ async function splitCommand() {
40774
41424
  const fileConfig = await readRepoConfig();
40775
41425
  const useStaged = !process.argv.includes("--all");
40776
41426
  let exitCode = 0;
41427
+ let completedCommits = [];
41428
+ enterImmersive();
40777
41429
  const { waitUntilExit } = render_default(
40778
- import_react38.default.createElement(SplitApp, {
41430
+ import_react42.default.createElement(SplitApp, {
40779
41431
  deps: {
40780
41432
  readToken,
40781
41433
  getAllChanges,
@@ -40791,27 +41443,36 @@ async function splitCommand() {
40791
41443
  applyPatch,
40792
41444
  validatePatch,
40793
41445
  getFileDiff,
40794
- apiPost: (path, body, tkn) => apiClient.post(path, body, tkn),
41446
+ apiPost: (path, body, tkn, timeoutMs) => apiClient.post(path, body, tkn, timeoutMs),
41447
+ postStream: (path, body, tkn, timeoutMs) => apiClient.postStream(path, body, tkn, timeoutMs),
40795
41448
  runGitCommit: runGitCommit2,
40796
41449
  fileConfig,
40797
41450
  useStaged
40798
41451
  },
40799
- onExit: (code) => {
41452
+ onExit: (code, commits) => {
40800
41453
  exitCode = code;
41454
+ completedCommits = commits ?? [];
40801
41455
  }
40802
41456
  })
40803
41457
  );
40804
41458
  await waitUntilExit();
41459
+ exitImmersive();
41460
+ if (completedCommits.length > 0) {
41461
+ const { waitUntilExit: waitUntilExit2 } = render_default(
41462
+ import_react42.default.createElement(SplitDoneSummary, { commits: completedCommits })
41463
+ );
41464
+ await waitUntilExit2();
41465
+ }
40805
41466
  process.exit(exitCode);
40806
41467
  }
40807
41468
 
40808
41469
  // src/commands/whoami.tsx
40809
- var import_react39 = __toESM(require_react(), 1);
40810
- var import_jsx_runtime15 = __toESM(require_jsx_runtime(), 1);
41470
+ var import_react43 = __toESM(require_react(), 1);
41471
+ var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
40811
41472
  function WhoamiApp({ onExit }) {
40812
41473
  const token = readToken();
40813
41474
  const payload = token ? decodeTokenPayload(token) : null;
40814
- (0, import_react39.useEffect)(() => {
41475
+ (0, import_react43.useEffect)(() => {
40815
41476
  onExit(payload ? 0 : 1);
40816
41477
  }, [onExit, payload]);
40817
41478
  const expiresDate = payload ? new Date(payload.exp * 1e3).toLocaleDateString("pt-BR", {
@@ -40819,26 +41480,26 @@ function WhoamiApp({ onExit }) {
40819
41480
  month: "2-digit",
40820
41481
  year: "numeric"
40821
41482
  }) : null;
40822
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { flexDirection: "column", paddingTop: 1, marginBottom: 1, children: [
40823
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Box_default, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { bold: true, color: "cyan", children: "RepoMind" }) }),
40824
- payload ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { flexDirection: "column", gap: 0, children: [
40825
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { gap: 1, children: [
40826
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: "green", children: "\u2713" }),
40827
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Text, { children: [
41483
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Box_default, { flexDirection: "column", paddingTop: 1, marginBottom: 1, children: [
41484
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Box_default, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { bold: true, color: C.cyan, children: "RepoMind" }) }),
41485
+ payload ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Box_default, { flexDirection: "column", gap: 0, children: [
41486
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Box_default, { gap: 1, children: [
41487
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { color: C.green, children: "\u2713" }),
41488
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Text, { children: [
40828
41489
  "Autenticado como",
40829
41490
  " ",
40830
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { bold: true, color: "white", children: payload.email })
41491
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { bold: true, color: C.white, children: payload.email })
40831
41492
  ] })
40832
41493
  ] }),
40833
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Box_default, { gap: 1, paddingLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Text, { dimColor: true, children: [
41494
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Box_default, { gap: 1, paddingLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Text, { color: C.dim, children: [
40834
41495
  "Sess\xE3o v\xE1lida at\xE9 ",
40835
41496
  expiresDate
40836
41497
  ] }) })
40837
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { gap: 1, children: [
40838
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: "yellow", children: "\u25C6" }),
40839
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Text, { dimColor: true, children: [
41498
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Box_default, { gap: 1, children: [
41499
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { color: C.yellow, children: "\u25C6" }),
41500
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Text, { color: C.dim, children: [
40840
41501
  "N\xE3o autenticado. Execute ",
40841
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: "white", children: "repomind login" }),
41502
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { color: C.white, children: "repomind login" }),
40842
41503
  "."
40843
41504
  ] })
40844
41505
  ] })
@@ -40847,7 +41508,7 @@ function WhoamiApp({ onExit }) {
40847
41508
  async function whoamiCommand() {
40848
41509
  let exitCode = 0;
40849
41510
  const { waitUntilExit } = render_default(
40850
- import_react39.default.createElement(WhoamiApp, {
41511
+ import_react43.default.createElement(WhoamiApp, {
40851
41512
  onExit: (code) => {
40852
41513
  exitCode = code;
40853
41514
  }
@@ -40859,10 +41520,10 @@ async function whoamiCommand() {
40859
41520
 
40860
41521
  // src/index.ts
40861
41522
  import { createRequire } from "node:module";
40862
- var import_react40 = __toESM(require_react(), 1);
41523
+ var import_react44 = __toESM(require_react(), 1);
40863
41524
 
40864
41525
  // src/ui/components/command-help.tsx
40865
- var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
41526
+ var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
40866
41527
  function CommandHelp({
40867
41528
  command: command2,
40868
41529
  usage,
@@ -40870,39 +41531,39 @@ function CommandHelp({
40870
41531
  details,
40871
41532
  flags
40872
41533
  }) {
40873
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Box_default, { flexDirection: "column", children: [
40874
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Header, { title: `RepoMind ${command2}` }),
40875
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Box_default, { paddingLeft: 1, marginBottom: 1, gap: 1, children: [
40876
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { dimColor: true, children: "Uso:" }),
40877
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { bold: true, children: usage })
41534
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Box_default, { flexDirection: "column", children: [
41535
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Header, { title: `RepoMind ${command2}` }),
41536
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Box_default, { paddingLeft: 1, marginBottom: 1, gap: 1, children: [
41537
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { color: C.dim, children: "Uso:" }),
41538
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { bold: true, children: usage })
40878
41539
  ] }),
40879
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
41540
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
40880
41541
  Box_default,
40881
41542
  {
40882
41543
  paddingLeft: 1,
40883
41544
  marginBottom: 1,
40884
41545
  borderStyle: "round",
40885
- borderColor: "gray",
41546
+ borderColor: C.dim,
40886
41547
  paddingX: 2,
40887
- paddingY: 1,
41548
+ paddingY: 0,
40888
41549
  flexDirection: "column",
40889
41550
  children: [
40890
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { children: description }),
40891
- details?.map((detail) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { dimColor: true, children: detail }, detail))
41551
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { children: description }),
41552
+ details?.map((detail) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { color: C.dim, children: detail }, detail))
40892
41553
  ]
40893
41554
  }
40894
41555
  ),
40895
- flags && flags.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 1, children: [
40896
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { dimColor: true, marginBottom: 0, children: "Flags:" }),
40897
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Box_default, { flexDirection: "column", marginTop: 0, paddingLeft: 1, children: flags.map((flag) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Box_default, { gap: 1, children: [
40898
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Box_default, { width: 20, children: [
40899
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { color: "cyan", bold: true, children: flag.name }),
40900
- flag.alias && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Text, { dimColor: true, children: [
41556
+ flags && flags.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 1, children: [
41557
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { color: C.dim, children: "Flags:" }),
41558
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Box_default, { flexDirection: "column", marginTop: 0, paddingLeft: 1, children: flags.map((flag) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Box_default, { gap: 1, children: [
41559
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Box_default, { width: 20, children: [
41560
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { color: C.cyan, bold: true, children: flag.name }),
41561
+ flag.alias && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Text, { color: C.dim, children: [
40901
41562
  ", ",
40902
41563
  flag.alias
40903
41564
  ] })
40904
41565
  ] }),
40905
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { dimColor: true, children: flag.description })
41566
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { color: C.dim, children: flag.description })
40906
41567
  ] }, flag.name)) })
40907
41568
  ] })
40908
41569
  ] });
@@ -40961,6 +41622,19 @@ var COMMAND_HELP = {
40961
41622
  { name: "--help", alias: "-h", description: "Exibir esta ajuda" }
40962
41623
  ]
40963
41624
  },
41625
+ pr: {
41626
+ usage: "repomind pr",
41627
+ description: "Gera uma PR description inteligente a partir do diff entre branches.",
41628
+ details: ["Compara HEAD com a branch base (main/master)."],
41629
+ flags: [
41630
+ {
41631
+ name: "--verbose",
41632
+ alias: "-v",
41633
+ description: "Exibir detalhes de erro"
41634
+ },
41635
+ { name: "--help", alias: "-h", description: "Exibir esta ajuda" }
41636
+ ]
41637
+ },
40964
41638
  login: {
40965
41639
  usage: "repomind login",
40966
41640
  description: "Autenticar com sua conta RepoMind via browser.",
@@ -40978,7 +41652,7 @@ var COMMAND_HELP = {
40978
41652
  if (wantsHelp && command && COMMAND_HELP[command]) {
40979
41653
  const def = COMMAND_HELP[command];
40980
41654
  const { waitUntilExit } = render_default(
40981
- import_react40.default.createElement(CommandHelp, {
41655
+ import_react44.default.createElement(CommandHelp, {
40982
41656
  command,
40983
41657
  usage: def.usage,
40984
41658
  description: def.description,
@@ -41005,6 +41679,9 @@ switch (command) {
41005
41679
  case "split":
41006
41680
  run(splitCommand);
41007
41681
  break;
41682
+ case "pr":
41683
+ run(prCommand);
41684
+ break;
41008
41685
  default:
41009
41686
  run(helpCommand);
41010
41687
  break;