@orion-agents/orion-code 0.3.24 → 0.3.26

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 (29) hide show
  1. package/CHANGELOG.md +60 -4
  2. package/README.md +8 -5
  3. package/README.zh-CN.md +6 -4
  4. package/dist/runtime/legacy-thread-materializer.d.ts +13 -0
  5. package/dist/runtime/legacy-thread-materializer.js +72 -0
  6. package/dist/runtime/model-coordinator.d.ts +1 -0
  7. package/dist/runtime/model-coordinator.js +9 -2
  8. package/dist/runtime/session-composer-control.js +5 -1
  9. package/dist/services/session-storage.js +21 -0
  10. package/dist/services/workspace-registry.d.ts +9 -0
  11. package/dist/services/workspace-registry.js +13 -2
  12. package/dist/web/git-diff-document.d.ts +19 -0
  13. package/dist/web/git-diff-document.js +46 -2
  14. package/dist/web/git-history-service.js +3 -0
  15. package/dist/web/git-read-model-service.d.ts +9 -0
  16. package/dist/web/git-read-model-service.js +111 -5
  17. package/dist/web/git-version-service.d.ts +8 -0
  18. package/dist/web/git-version-service.js +50 -26
  19. package/dist/web/protocol.d.ts +5 -0
  20. package/dist/web/workbench-controller.js +1 -0
  21. package/dist/web-client/assets/{FilesPanel-BjEDjE7l.js → FilesPanel-CdoCa8u0.js} +1 -1
  22. package/dist/web-client/assets/{GitPanel-DvgAZDRA.js → GitPanel-CRr_iIDz.js} +1 -1
  23. package/dist/web-client/assets/{ReviewPanel-BMPaYKDY.js → ReviewPanel-C1Cu2IRV.js} +1 -1
  24. package/dist/web-client/assets/{TerminalPanel-Da1ZEhGF.js → TerminalPanel-BniCjatZ.js} +1 -1
  25. package/dist/web-client/assets/{index-DZOlUgt6.js → index-kQqA3li6.js} +11 -11
  26. package/dist/web-client/assets/{useAutoNotice-Ylj5bfSH.js → useAutoNotice-DPXFWIwK.js} +1 -1
  27. package/dist/web-client/index.html +1 -1
  28. package/npm-shrinkwrap.json +2 -2
  29. package/package.json +1 -1
@@ -6,6 +6,7 @@ exports.assertRelativeGitPath = assertRelativeGitPath;
6
6
  const child_process_1 = require("child_process");
7
7
  const crypto_1 = require("crypto");
8
8
  const fs_1 = require("fs");
9
+ const promises_1 = require("fs/promises");
9
10
  const path_1 = require("path");
10
11
  const redaction_1 = require("../services/redaction");
11
12
  const errors_1 = require("./errors");
@@ -235,7 +236,13 @@ class GitReadModelServiceV1 {
235
236
  */
236
237
  async diffDocument(input) {
237
238
  const page = await this.diff(input);
238
- return (0, git_diff_document_1.parseGitDiffDocument)({
239
+ // v0.3.26 #275 — the incoming cursor may carry the hunk state this page
240
+ // continues; diff() already validated the cursor, so decoding it here only
241
+ // reads the resume state.
242
+ const resumeHunk = input.cursor
243
+ ? this.decodeCursor(input.cursor, 'diff', page.repositoryRevision, page.fileId, diffScope(input.ignoreWhitespace === true, input.wordDiff === true)).resumeHunk
244
+ : undefined;
245
+ const document = (0, git_diff_document_1.parseGitDiffDocument)({
239
246
  fileToken: page.fileId,
240
247
  path: page.path,
241
248
  source: page.source,
@@ -243,7 +250,18 @@ class GitReadModelServiceV1 {
243
250
  lines: page.lines,
244
251
  hasMore: page.nextCursor !== null,
245
252
  nextCursor: page.nextCursor,
253
+ ...(resumeHunk ? { resume: resumeHunk } : {}),
246
254
  });
255
+ // A page that ends inside a hunk re-mints the cursor with the hunk state so
256
+ // the next page resumes it instead of demoting the rows to meta.
257
+ if (page.nextCursor && document.pendingHunk) {
258
+ const decoded = this.decodeCursor(page.nextCursor, 'diff', page.repositoryRevision, page.fileId, diffScope(input.ignoreWhitespace === true, input.wordDiff === true));
259
+ return Object.freeze({
260
+ ...document,
261
+ nextCursor: this.encodeCursor({ ...decoded, resumeHunk: document.pendingHunk }),
262
+ });
263
+ }
264
+ return document;
247
265
  }
248
266
  historyReader() {
249
267
  this.historyReaderInstance ?? (this.historyReaderInstance = (0, git_history_service_1.createGitHistoryReader)({
@@ -299,7 +317,8 @@ class GitReadModelServiceV1 {
299
317
  .update(`compare-diff:${input.baseOid}:${input.headOid}:${path}:${snapshot.revision}`)
300
318
  .digest('hex')
301
319
  .slice(0, 24);
302
- const offset = input.cursor ? decodeCommitDiffCursor(input.cursor, margin) : 0;
320
+ const cursorState = input.cursor ? decodeCommitDiffCursor(input.cursor, margin) : null;
321
+ const offset = cursorState?.offset ?? 0;
303
322
  const page = await streamDiffPage({
304
323
  cwd: root,
305
324
  commands: Object.freeze([
@@ -338,9 +357,19 @@ class GitReadModelServiceV1 {
338
357
  nextCursor: page.hasMore
339
358
  ? encodeCommitDiffCursor({ margin, offset: offset + page.returnedLines })
340
359
  : null,
360
+ ...(cursorState?.resumeHunk ? { resume: cursorState.resumeHunk } : {}),
341
361
  });
362
+ // v0.3.26 #275 — re-mint the continuation cursor with the split hunk state.
363
+ const nextCursor = page.hasMore && document.pendingHunk
364
+ ? encodeCommitDiffCursor({
365
+ margin,
366
+ offset: offset + page.returnedLines,
367
+ resumeHunk: document.pendingHunk,
368
+ })
369
+ : document.nextCursor;
342
370
  return Object.freeze({
343
371
  ...document,
372
+ nextCursor,
344
373
  baseOid: input.baseOid,
345
374
  baseLabel: `比较 ${input.baseOid.slice(0, 10)} → ${input.headOid.slice(0, 10)}`,
346
375
  });
@@ -349,9 +378,43 @@ class GitReadModelServiceV1 {
349
378
  this.versionReaderInstance ?? (this.versionReaderInstance = (0, git_version_service_1.createGitVersionReader)({
350
379
  runGit: async (args) => this.runGit(args, await this.requireRepositoryRoot()),
351
380
  runGitBytes: async (args) => this.runGitBytes(args, await this.requireRepositoryRoot()),
381
+ readWorktreeFile: async (relativePath) => this.readContainedWorktreeFile(relativePath),
352
382
  }));
353
383
  return this.versionReaderInstance;
354
384
  }
385
+ /**
386
+ * v0.3.25 #269 — reads one working-tree file for the conflict view, refusing
387
+ * to leave the repository: the requested relative path (already guarded as
388
+ * relative and non-sensitive by the version reader) is resolved against the
389
+ * repository root and both the file's real path and its parent's real path
390
+ * must stay inside the root's real path. Returns null instead of throwing so
391
+ * a missing or unreadable file reads as an absent worktree version.
392
+ */
393
+ async readContainedWorktreeFile(relativePath) {
394
+ let root;
395
+ try {
396
+ root = (0, fs_1.realpathSync)(await this.requireRepositoryRoot());
397
+ }
398
+ catch {
399
+ return null;
400
+ }
401
+ try {
402
+ const absolute = (0, path_1.resolve)(root, relativePath);
403
+ const fileReal = (0, fs_1.realpathSync)(absolute);
404
+ const parentReal = (0, fs_1.realpathSync)((0, path_1.resolve)(fileReal, '..'));
405
+ if (fileReal !== root && !fileReal.startsWith(root + path_1.sep))
406
+ return null;
407
+ if (parentReal !== root && !parentReal.startsWith(root + path_1.sep))
408
+ return null;
409
+ const stat = (0, fs_1.statSync)(fileReal);
410
+ if (!stat.isFile())
411
+ return null;
412
+ return await (0, promises_1.readFile)(fileReal);
413
+ }
414
+ catch {
415
+ return null;
416
+ }
417
+ }
355
418
  /**
356
419
  * v0.3.17 S5 — base / ours / theirs / worktree for a conflicted file.
357
420
  *
@@ -415,7 +478,8 @@ class GitReadModelServiceV1 {
415
478
  .update(`commit-diff:${detail.id}:${detail.baseOid}:${parentIndex}:${snapshot.revision}`)
416
479
  .digest('hex')
417
480
  .slice(0, 24);
418
- const offset = input.cursor ? decodeCommitDiffCursor(input.cursor, margin) : 0;
481
+ const cursorState = input.cursor ? decodeCommitDiffCursor(input.cursor, margin) : null;
482
+ const offset = cursorState?.offset ?? 0;
419
483
  const page = await streamDiffPage({
420
484
  cwd: root,
421
485
  commands: Object.freeze([
@@ -454,8 +518,22 @@ class GitReadModelServiceV1 {
454
518
  nextCursor: page.hasMore
455
519
  ? encodeCommitDiffCursor({ margin, offset: offset + page.returnedLines })
456
520
  : null,
521
+ ...(cursorState?.resumeHunk ? { resume: cursorState.resumeHunk } : {}),
522
+ });
523
+ // v0.3.26 #275 — re-mint the continuation cursor with the split hunk state.
524
+ const nextCursor = page.hasMore && document.pendingHunk
525
+ ? encodeCommitDiffCursor({
526
+ margin,
527
+ offset: offset + page.returnedLines,
528
+ resumeHunk: document.pendingHunk,
529
+ })
530
+ : document.nextCursor;
531
+ return Object.freeze({
532
+ ...document,
533
+ nextCursor,
534
+ baseLabel: detail.baseLabel,
535
+ baseOid: detail.baseOid,
457
536
  });
458
- return Object.freeze({ ...document, baseLabel: detail.baseLabel, baseOid: detail.baseOid });
459
537
  }
460
538
  async capture() {
461
539
  let root;
@@ -1176,6 +1254,9 @@ class GitReadModelServiceV1 {
1176
1254
  parsed.offset < 0) {
1177
1255
  return invalidCursor();
1178
1256
  }
1257
+ if (parsed.resumeHunk !== undefined && !isDiffHunkResume(parsed.resumeHunk)) {
1258
+ return invalidCursor();
1259
+ }
1179
1260
  if (parsed.revision !== revision) {
1180
1261
  throw new errors_1.WebWorkbenchError(409, 'Git cursor revision is stale.', 'git_revision_conflict');
1181
1262
  }
@@ -1189,6 +1270,22 @@ class GitReadModelServiceV1 {
1189
1270
  }
1190
1271
  }
1191
1272
  exports.GitReadModelServiceV1 = GitReadModelServiceV1;
1273
+ /** v0.3.26 #275 — the hunk header shape, mirrored for cursor validation. */
1274
+ const HUNK_HEADER_PATTERN = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$/u;
1275
+ /** v0.3.26 #275 — validates a cursor-carried hunk resume state. */
1276
+ function isDiffHunkResume(value) {
1277
+ if (!value || typeof value !== 'object')
1278
+ return false;
1279
+ const candidate = value;
1280
+ return (typeof candidate.header === 'string' &&
1281
+ HUNK_HEADER_PATTERN.test(candidate.header) &&
1282
+ Number.isSafeInteger(candidate.index) &&
1283
+ candidate.index >= 0 &&
1284
+ Number.isSafeInteger(candidate.oldCursor) &&
1285
+ candidate.oldCursor >= 1 &&
1286
+ Number.isSafeInteger(candidate.newCursor) &&
1287
+ candidate.newCursor >= 1);
1288
+ }
1192
1289
  function parsePorcelainV1(output) {
1193
1290
  const fields = output.split('\0');
1194
1291
  const records = [];
@@ -1657,7 +1754,16 @@ function decodeCommitDiffCursor(cursor, margin) {
1657
1754
  candidate.offset < 0) {
1658
1755
  throw new errors_1.WebWorkbenchError(409, 'Diff changed; reload before paginating.', 'git_cursor_invalid');
1659
1756
  }
1660
- return candidate.offset;
1757
+ if (candidate.resumeHunk !== undefined && !isDiffHunkResume(candidate.resumeHunk)) {
1758
+ throw new errors_1.WebWorkbenchError(400, 'Diff cursor is not valid.', 'git_cursor_invalid');
1759
+ }
1760
+ return {
1761
+ margin,
1762
+ offset: candidate.offset,
1763
+ ...(candidate.resumeHunk !== undefined
1764
+ ? { resumeHunk: candidate.resumeHunk }
1765
+ : {}),
1766
+ };
1661
1767
  }
1662
1768
  /**
1663
1769
  * Kills a detached child and everything it spawned.
@@ -66,6 +66,14 @@ export interface GitVersionReaderOptions {
66
66
  readonly runGit: (args: readonly string[]) => Promise<string>;
67
67
  /** Runs git and returns raw bytes, for content that may not be valid UTF-8. */
68
68
  readonly runGitBytes: (args: readonly string[]) => Promise<Buffer>;
69
+ /**
70
+ * v0.3.25 #269 — reads one working-tree file relative to the repository root,
71
+ * returning null when it does not exist or cannot be read safely. The
72
+ * `worktree` conflict version must come from the filesystem: `hash-object`
73
+ * without `-w` computes an OID that is not in the object database, so any
74
+ * edited working file made `cat-file` fail the whole conflict response.
75
+ */
76
+ readonly readWorktreeFile?: (relativePath: string) => Promise<Buffer | null>;
69
77
  }
70
78
  export declare function createGitVersionReader(options: GitVersionReaderOptions): GitVersionReader;
71
79
  //# sourceMappingURL=git-version-service.d.ts.map
@@ -85,28 +85,25 @@ function parseLfsPointer(head) {
85
85
  });
86
86
  }
87
87
  function createGitVersionReader(options) {
88
- const { runGit, runGitBytes } = options;
88
+ const { runGit, runGitBytes, readWorktreeFile } = options;
89
+ /** Absent version — the label legitimately has no content for this shape. */
90
+ const absentVersion = (label) => Object.freeze({
91
+ label,
92
+ oid: null,
93
+ exists: false,
94
+ binary: false,
95
+ byteSize: 0,
96
+ truncated: false,
97
+ content: null,
98
+ lfs: null,
99
+ });
89
100
  /**
90
- * Reads one blob by OID, bounded, with binary and LFS detection.
91
- *
92
- * The size is read first so an enormous historical file is reported by its size instead of
93
- * being pulled into memory just to be truncated.
101
+ * v0.3.25 #269 — decodes already-fetched bytes into a version, shared by the
102
+ * object-database reader and the working-tree reader so both apply the same
103
+ * size bound, binary probe and LFS-pointer detection.
94
104
  */
95
- const readVersion = async (label, oid) => {
96
- if (oid === null) {
97
- return Object.freeze({
98
- label,
99
- oid: null,
100
- exists: false,
101
- binary: false,
102
- byteSize: 0,
103
- truncated: false,
104
- content: null,
105
- lfs: null,
106
- });
107
- }
108
- const sizeRaw = (await runGit(['cat-file', '-s', oid])).trim();
109
- const byteSize = Number(sizeRaw) || 0;
105
+ const versionFromBytes = (label, oid, bytes) => {
106
+ const byteSize = bytes.length;
110
107
  if (byteSize > MAX_VERSION_BYTES) {
111
108
  return Object.freeze({
112
109
  label,
@@ -119,7 +116,6 @@ function createGitVersionReader(options) {
119
116
  lfs: null,
120
117
  });
121
118
  }
122
- const bytes = await runGitBytes(['cat-file', 'blob', oid]);
123
119
  const probe = bytes.subarray(0, LFS_PROBE_BYTES).toString('utf8');
124
120
  const lfs = parseLfsPointer(probe);
125
121
  if (lfs) {
@@ -149,6 +145,31 @@ function createGitVersionReader(options) {
149
145
  dataUrl,
150
146
  });
151
147
  };
148
+ /**
149
+ * Reads one blob by OID, bounded, with binary and LFS detection.
150
+ *
151
+ * The size is read first so an enormous historical file is reported by its size instead of
152
+ * being pulled into memory just to be truncated.
153
+ */
154
+ const readVersion = async (label, oid) => {
155
+ if (oid === null)
156
+ return absentVersion(label);
157
+ const sizeRaw = (await runGit(['cat-file', '-s', oid])).trim();
158
+ const byteSize = Number(sizeRaw) || 0;
159
+ if (byteSize > MAX_VERSION_BYTES) {
160
+ return Object.freeze({
161
+ label,
162
+ oid,
163
+ exists: true,
164
+ binary: false,
165
+ byteSize,
166
+ truncated: true,
167
+ content: null,
168
+ lfs: null,
169
+ });
170
+ }
171
+ return versionFromBytes(label, oid, await runGitBytes(['cat-file', 'blob', oid]));
172
+ };
152
173
  return {
153
174
  async conflict(pathInput) {
154
175
  const path = assertRelativePath(pathInput);
@@ -168,15 +189,18 @@ function createGitVersionReader(options) {
168
189
  continue;
169
190
  stageOids.set(Number(stage), oid);
170
191
  }
171
- const worktreeOid = (await runGit(['hash-object', '--path=' + path, '--', path]).catch(() => ''))
172
- .toString()
173
- .trim();
174
- const worktreeExists = /^[0-9a-f]{7,64}$/iu.test(worktreeOid);
192
+ // v0.3.25 #269 — the working file is read from the filesystem. The previous
193
+ // `hash-object` (without -w) → `cat-file` chain only worked while the edited
194
+ // content happened to match an object git already stored; any real edit made
195
+ // `cat-file` fail the entire conflict response.
196
+ const worktreeBytes = await readWorktreeFile?.(path);
175
197
  const [base, ours, theirs, worktree] = await Promise.all([
176
198
  readVersion('base', stageOids.get(1) ?? null),
177
199
  readVersion('ours', stageOids.get(2) ?? null),
178
200
  readVersion('theirs', stageOids.get(3) ?? null),
179
- worktreeExists ? readVersion('worktree', worktreeOid) : readVersion('worktree', null),
201
+ worktreeBytes
202
+ ? Promise.resolve(versionFromBytes('worktree', null, worktreeBytes))
203
+ : Promise.resolve(absentVersion('worktree')),
180
204
  ]);
181
205
  const hasBase = stageOids.has(1);
182
206
  const hasOurs = stageOids.has(2);
@@ -361,6 +361,11 @@ export interface WebWorkspaceSummaryV1 {
361
361
  readonly available: boolean;
362
362
  readonly sessionCount: number;
363
363
  readonly lastActivatedAt: string;
364
+ /**
365
+ * v0.3.25 #272 — when the workspace was first registered. The navigation's
366
+ * stable default order is derived from this; optional for older Hosts.
367
+ */
368
+ readonly registeredAt?: string;
364
369
  readonly pinnedOrder?: number;
365
370
  }
366
371
  export interface WebWorkspaceProjectSummaryV1 {
@@ -238,6 +238,7 @@ class WebWorkbenchController {
238
238
  available,
239
239
  sessionCount: counts.get(entry.canonicalPath) ?? 0,
240
240
  lastActivatedAt: entry.lastActivatedAt,
241
+ registeredAt: entry.registeredAt,
241
242
  ...(entry.pinnedOrder !== undefined ? { pinnedOrder: entry.pinnedOrder } : {}),
242
243
  });
243
244
  }));
@@ -1 +1 @@
1
- import{r as a,j as e,I as D,s as be,C as ye,W as ge}from"./index-DZOlUgt6.js";import{u as Ce,R as Ne}from"./useAutoNotice-Ylj5bfSH.js";function Le({workspaceId:s,refreshEpoch:o,actions:l,navigatorWidthPx:r,onNavigatorWidthCommit:d,revealRequest:c}){const[f,m]=a.useState({}),[x,j]=a.useState(new Set(["workspace-root"])),[i,N]=a.useState(null),[F,B]=a.useState(""),[M,G]=a.useState(null),[Y,P]=a.useState(!1),[H,K]=a.useState(""),{notice:J,showNotice:$,clearNotice:V}=Ce(),[T,ue]=a.useState(""),[Z,_]=a.useState({}),[I,A]=a.useState(""),[O,R]=a.useState("view"),[L,w]=a.useState(""),[k,q]=a.useState(!1),[de,S]=a.useState(!1),[fe,me]=a.useState(""),[he,W]=a.useState(!1),h=a.useRef(0),C=a.useRef(0),ee=a.useRef(null),E=async(t,n=!1,y=h.current)=>{if(y!==h.current)return;const p=f[t],g=n?p?.nextCursor:void 0;if(!(n&&!g)){m(u=>({...u,[t]:{items:p?.items??[],nextCursor:p?.nextCursor??null,revision:p?.revision??"",loading:!0}}));try{const u=await l.listFiles(t,g??void 0);if(y!==h.current)return;m(v=>({...v,[t]:{items:n?ke(v[t]?.items??[],u.items):u.items,nextCursor:u.nextCursor,revision:u.revision,loading:!1}}))}catch(u){if(y!==h.current)return;if(n&&U(u)){$("目录已变化,已重新载入第一页。"),E(t,!1,y);return}m(v=>({...v,[t]:{items:v[t]?.items??[],nextCursor:v[t]?.nextCursor??null,revision:v[t]?.revision??"",loading:!1,error:z(u)}}))}}},Q=async(t=h.current)=>{try{const n=await l.gitStatus();if(t!==h.current)return;_(Se(n)),A(n.nextCursor?"Git 装饰仅显示首批 200 个变更;在 Git 面板继续分页查看。":"")}catch(n){if(t!==h.current)return;_({}),A(`Git 状态装饰不可用:${z(n)}`)}},te=a.useRef(s);a.useEffect(()=>{const t=h.current+1;h.current=t,C.current+=1;const n=te.current===s?ee.current:null;te.current=s,m({}),j(new Set(["workspace-root"])),N(n),B(""),G(null),P(!1),K(""),V(),_({}),A(""),s&&(E("workspace-root",!1,t),Q(t),n&&b(n,!1,!1,t))},[o,s]);const se=a.useRef(null),b=async(t,n=!1,y=!1,p=h.current,g=C.current+1)=>{if(p===h.current&&!(!t.readable||t.sensitive||X(t))){C.current=g,N(t),K(""),n||(B(""),G(null),P(!1),R("view"),w(""),S(!1)),y||V();try{const u=await l.readFileContent(t.id,n?M??void 0:void 0);if(p!==h.current||g!==C.current)return;P(u.binary),B(v=>n?`${v}${u.content??""}`:u.content??""),G(u.nextCursor),me(u.revision),y&&$("文件已变化,已从第一页重新载入。")}catch(u){if(p!==h.current||g!==C.current)return;if(n&&U(u)){await b(t,!1,!0,p,g);return}K(z(u))}}},re=De({selected:i,binary:Y,hasMorePages:M!==null}),xe=()=>{w(F),S(!1),R("edit")},ie=()=>{if(L!==F){W(!0);return}ne()},ne=()=>{R("view"),w(""),S(!1),W(!1)},je=async()=>{if(!(!i||k)){q(!0),S(!1);try{await l.writeFileContent(i.id,L,fe),R("view"),w(""),await b(i,!1,!0,h.current,C.current+1),$("已保存文件。","success"),Q()}catch(t){U(t)?S(!0):$(z(t),"error")}finally{q(!1)}}},ae=t=>{const n=new Set(x);n.has(t)?n.delete(t):(n.add(t),f[t]||E(t)),j(n)};a.useEffect(()=>{c&&se.current!==c.id&&(se.current=c.id,b({id:c.fileId,name:c.displayPath.split("/").pop()??c.displayPath,displayPath:c.displayPath,kind:"file",modifiedAt:new Date().toISOString(),sensitive:!1,readable:!0}))},[c?.id]),a.useEffect(()=>{ee.current=i},[i]);const pe=a.useMemo(()=>Object.values(f).flatMap(t=>t.items),[f]),oe=T.trim()?pe.filter(t=>t.name.toLocaleLowerCase().includes(T.toLocaleLowerCase())):null,ve=!!f["workspace-root"]?.loading;return e.jsxs("div",{className:"work-resource-panel files-panel",children:[e.jsxs("div",{className:"resource-toolbar",children:[e.jsxs("label",{className:"resource-search",children:[e.jsx("span",{className:"sr-only",children:"搜索已加载文件"}),e.jsx(D,{name:"search",size:16}),e.jsx("input",{type:"search",value:T,onChange:t=>ue(t.target.value),placeholder:"搜索已加载文件",title:"搜索仅覆盖已加载的目录和文件"})]}),e.jsx("button",{type:"button",className:"icon-button","aria-label":"刷新文件树","aria-busy":ve,onClick:()=>{E("workspace-root"),Q()},children:e.jsx(D,{name:"refresh",size:16})})]}),e.jsxs(Ne,{panelId:"files",navigatorWidthPx:r,onNavigatorWidthCommit:d,contentLabel:"文件预览",navigatorLabel:"工作区文件",handleLabel:"调整文件目录宽度",contentClassName:"file-preview",navigatorClassName:"file-tree",children:[e.jsxs(e.Fragment,{children:[I?e.jsx("p",{className:"resource-hint",role:"status",children:I}):null,oe?e.jsx(e.Fragment,{children:e.jsx("ul",{role:"list",className:"file-node-list search-results",children:oe.map(t=>e.jsx(ce,{node:t,depth:0,expanded:!1,selected:i?.id===t.id,gitLabels:Z[t.displayPath]??[],onToggle:ae,onSelect:n=>{b(n)}},t.id))})}):e.jsx(le,{parentId:"workspace-root",depth:0,directories:f,expanded:x,selectedId:i?.id,gitDecorations:Z,onToggle:ae,onSelect:t=>{b(t)},onLoadMore:t=>{E(t,!0)}})]}),e.jsxs(e.Fragment,{children:[J?e.jsx("p",{className:"resource-notice",role:"status",children:J.text}):null,i?e.jsxs(e.Fragment,{children:[e.jsxs("header",{children:[e.jsx("strong",{children:i.name}),e.jsx("span",{children:Fe(i.sizeBytes??0)})]}),H?e.jsx("p",{className:"resource-error",role:"alert",children:H}):Y?e.jsxs("div",{className:"resource-empty",children:[e.jsx(D,{name:"code",size:16}),e.jsx("strong",{title:"出于安全和性能考虑,只显示元数据。",children:"二进制文件"})]}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"file-preview-actions",children:O==="view"?e.jsx("button",{type:"button",className:"text-button",disabled:!re,title:re?void 0:"仅支持编辑 512 KB 内的 UTF-8 文本文件",onClick:xe,children:"编辑"}):e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",className:"primary-button",disabled:k||L===F,"aria-busy":k,onClick:()=>{je()},children:k?"保存中…":"保存"}),e.jsx("button",{type:"button",className:"text-button",disabled:k,onClick:ie,children:"取消"})]})}),de?e.jsxs("p",{className:"resource-error",role:"alert",children:["文件已在别处变更,保存被拒绝。",e.jsx("button",{type:"button",className:"text-button",onClick:()=>{b(i,!1,!0)},children:"重新加载"})]}):null,O==="edit"?e.jsx("textarea",{className:"file-editor",value:L,spellCheck:!1,"aria-label":`编辑文件 ${i.name}`,onChange:t=>w(t.target.value),onKeyDown:t=>{t.key==="Escape"&&(t.preventDefault(),ie())}}):e.jsx("pre",{tabIndex:0,className:"file-code-view","aria-label":`文件内容 ${i.name}`,children:be(F)})]}),M&&O==="view"?e.jsx("button",{type:"button",className:"secondary-button",onClick:()=>{b(i,!0)},children:"加载更多内容"}):null]}):e.jsxs("div",{className:"resource-empty",children:[e.jsx(D,{name:"workspace",size:16}),e.jsx("strong",{children:"选择文件预览"}),e.jsx("p",{title:"敏感文件、工作区外链接和二进制正文不会返回浏览器。",children:"受限内容不会返回浏览器。"})]})]})]}),e.jsx(ye,{open:he,onClose:()=>W(!1),title:"放弃未保存的修改?",body:"当前草稿尚未保存,放弃后将回到文件的最新内容。",confirmLabel:"放弃修改",danger:!0,onConfirm:ne})]})}function le({parentId:s,depth:o,directories:l,expanded:r,selectedId:d,gitDecorations:c,onToggle:f,onSelect:m,onLoadMore:x}){const j=l[s];return j?j.error?e.jsx("p",{className:"resource-error",role:"alert",children:j.error}):e.jsxs("ul",{role:"list",className:"file-node-list",children:[j.items.map(i=>{const N=r.has(i.id);return e.jsxs("li",{children:[e.jsx(ce,{node:i,depth:o,expanded:N,selected:d===i.id,gitLabels:c[i.displayPath]??[],onToggle:f,onSelect:m}),X(i)&&N?e.jsx(le,{parentId:i.id,depth:o+1,directories:l,expanded:r,selectedId:d,gitDecorations:c,onToggle:f,onSelect:m,onLoadMore:x}):null]},i.id)}),j.loading?e.jsx("li",{className:"resource-loading",children:"正在读取…"}):null,j.nextCursor?e.jsx("li",{children:e.jsx("button",{type:"button",className:"text-button",onClick:()=>x(s),children:"加载更多"})}):null]}):e.jsx("p",{className:"resource-loading",children:"正在读取…"})}function ce({node:s,depth:o,expanded:l,selected:r,gitLabels:d,onToggle:c,onSelect:f}){const m=s.sensitive||!s.readable,x=X(s);return e.jsxs("button",{type:"button",className:`file-node ${r?"selected":""} ${m?"blocked":""}`,style:{paddingInlineStart:`${8+o*15}px`},"aria-expanded":x?l:void 0,"aria-label":`${we(s)} ${s.name}${m?",不可读取":""}${d.length?`,Git ${d.join("、")}`:""}`,onClick:()=>x?c(s.id):f(s),disabled:m,children:[e.jsx(D,{name:x?"workspace":"code",size:16}),e.jsx("span",{children:s.name}),s.kind==="symlink"?e.jsx("small",{children:"链接"}):null,s.sensitive?e.jsx("small",{children:"敏感"}):null,d.length?e.jsx("small",{className:"file-git-status",title:`Git ${d.join("、")}`,children:d.join(" · ")}):null]})}function we(s){return s.kind==="directory"?"目录":s.kind==="symlink"?s.targetKind==="directory"?"符号链接目录":"符号链接":"文件"}function X(s){return s.kind==="directory"||s.kind==="symlink"&&s.targetKind==="directory"}function ke(s,o){const l=new Map(s.map(r=>[r.id,r]));for(const r of o)l.set(r.id,r);return[...l.values()]}function Se(s){if(!s.hasWorktree)return{};const o=new Map,l=(r,d)=>{const c=r.replace(/\\/gu,"/").replace(/^\.\//u,"");if(!c)return;const f=o.get(c)??new Set;f.add(d),o.set(c,f);const m=c.split("/");for(let x=1;x<m.length;x+=1){const j=m.slice(0,x).join("/"),i=o.get(j)??new Set;i.add("含变更"),o.set(j,i)}};return s.conflicted.forEach(r=>l(r.path,"冲突")),s.staged.forEach(r=>l(r.path,"已暂存")),s.unstaged.forEach(r=>l(r.path,"未暂存")),s.untracked.forEach(r=>l(r.path,"未跟踪")),Object.fromEntries([...o].map(([r,d])=>[r,Object.freeze([...d])]))}const Ee=512*1024;function De(s){const{selected:o,binary:l,hasMorePages:r}=s;return!o||l||o.sensitive||!o.readable||r?!1:(o.sizeBytes??0)<=Ee}function Fe(s){return s<1024?`${s} B`:s<1048576?`${(s/1024).toFixed(1)} KB`:`${(s/1048576).toFixed(1)} MB`}function U(s){return s instanceof ge&&s.code==="file_revision_conflict"}function z(s){return s instanceof Error?s.message:"文件请求失败。"}export{Ee as FILE_EDIT_MAX_BYTES,Le as FilesPanel,De as canEditFileContent};
1
+ import{r as a,j as e,I as D,s as be,C as ye,W as ge}from"./index-kQqA3li6.js";import{u as Ce,R as Ne}from"./useAutoNotice-DPXFWIwK.js";function Le({workspaceId:s,refreshEpoch:o,actions:l,navigatorWidthPx:r,onNavigatorWidthCommit:d,revealRequest:c}){const[f,m]=a.useState({}),[x,j]=a.useState(new Set(["workspace-root"])),[i,N]=a.useState(null),[F,B]=a.useState(""),[M,G]=a.useState(null),[Y,P]=a.useState(!1),[H,K]=a.useState(""),{notice:J,showNotice:$,clearNotice:V}=Ce(),[T,ue]=a.useState(""),[Z,_]=a.useState({}),[I,A]=a.useState(""),[O,R]=a.useState("view"),[L,w]=a.useState(""),[k,q]=a.useState(!1),[de,S]=a.useState(!1),[fe,me]=a.useState(""),[he,W]=a.useState(!1),h=a.useRef(0),C=a.useRef(0),ee=a.useRef(null),E=async(t,n=!1,y=h.current)=>{if(y!==h.current)return;const p=f[t],g=n?p?.nextCursor:void 0;if(!(n&&!g)){m(u=>({...u,[t]:{items:p?.items??[],nextCursor:p?.nextCursor??null,revision:p?.revision??"",loading:!0}}));try{const u=await l.listFiles(t,g??void 0);if(y!==h.current)return;m(v=>({...v,[t]:{items:n?ke(v[t]?.items??[],u.items):u.items,nextCursor:u.nextCursor,revision:u.revision,loading:!1}}))}catch(u){if(y!==h.current)return;if(n&&U(u)){$("目录已变化,已重新载入第一页。"),E(t,!1,y);return}m(v=>({...v,[t]:{items:v[t]?.items??[],nextCursor:v[t]?.nextCursor??null,revision:v[t]?.revision??"",loading:!1,error:z(u)}}))}}},Q=async(t=h.current)=>{try{const n=await l.gitStatus();if(t!==h.current)return;_(Se(n)),A(n.nextCursor?"Git 装饰仅显示首批 200 个变更;在 Git 面板继续分页查看。":"")}catch(n){if(t!==h.current)return;_({}),A(`Git 状态装饰不可用:${z(n)}`)}},te=a.useRef(s);a.useEffect(()=>{const t=h.current+1;h.current=t,C.current+=1;const n=te.current===s?ee.current:null;te.current=s,m({}),j(new Set(["workspace-root"])),N(n),B(""),G(null),P(!1),K(""),V(),_({}),A(""),s&&(E("workspace-root",!1,t),Q(t),n&&b(n,!1,!1,t))},[o,s]);const se=a.useRef(null),b=async(t,n=!1,y=!1,p=h.current,g=C.current+1)=>{if(p===h.current&&!(!t.readable||t.sensitive||X(t))){C.current=g,N(t),K(""),n||(B(""),G(null),P(!1),R("view"),w(""),S(!1)),y||V();try{const u=await l.readFileContent(t.id,n?M??void 0:void 0);if(p!==h.current||g!==C.current)return;P(u.binary),B(v=>n?`${v}${u.content??""}`:u.content??""),G(u.nextCursor),me(u.revision),y&&$("文件已变化,已从第一页重新载入。")}catch(u){if(p!==h.current||g!==C.current)return;if(n&&U(u)){await b(t,!1,!0,p,g);return}K(z(u))}}},re=De({selected:i,binary:Y,hasMorePages:M!==null}),xe=()=>{w(F),S(!1),R("edit")},ie=()=>{if(L!==F){W(!0);return}ne()},ne=()=>{R("view"),w(""),S(!1),W(!1)},je=async()=>{if(!(!i||k)){q(!0),S(!1);try{await l.writeFileContent(i.id,L,fe),R("view"),w(""),await b(i,!1,!0,h.current,C.current+1),$("已保存文件。","success"),Q()}catch(t){U(t)?S(!0):$(z(t),"error")}finally{q(!1)}}},ae=t=>{const n=new Set(x);n.has(t)?n.delete(t):(n.add(t),f[t]||E(t)),j(n)};a.useEffect(()=>{c&&se.current!==c.id&&(se.current=c.id,b({id:c.fileId,name:c.displayPath.split("/").pop()??c.displayPath,displayPath:c.displayPath,kind:"file",modifiedAt:new Date().toISOString(),sensitive:!1,readable:!0}))},[c?.id]),a.useEffect(()=>{ee.current=i},[i]);const pe=a.useMemo(()=>Object.values(f).flatMap(t=>t.items),[f]),oe=T.trim()?pe.filter(t=>t.name.toLocaleLowerCase().includes(T.toLocaleLowerCase())):null,ve=!!f["workspace-root"]?.loading;return e.jsxs("div",{className:"work-resource-panel files-panel",children:[e.jsxs("div",{className:"resource-toolbar",children:[e.jsxs("label",{className:"resource-search",children:[e.jsx("span",{className:"sr-only",children:"搜索已加载文件"}),e.jsx(D,{name:"search",size:16}),e.jsx("input",{type:"search",value:T,onChange:t=>ue(t.target.value),placeholder:"搜索已加载文件",title:"搜索仅覆盖已加载的目录和文件"})]}),e.jsx("button",{type:"button",className:"icon-button","aria-label":"刷新文件树","aria-busy":ve,onClick:()=>{E("workspace-root"),Q()},children:e.jsx(D,{name:"refresh",size:16})})]}),e.jsxs(Ne,{panelId:"files",navigatorWidthPx:r,onNavigatorWidthCommit:d,contentLabel:"文件预览",navigatorLabel:"工作区文件",handleLabel:"调整文件目录宽度",contentClassName:"file-preview",navigatorClassName:"file-tree",children:[e.jsxs(e.Fragment,{children:[I?e.jsx("p",{className:"resource-hint",role:"status",children:I}):null,oe?e.jsx(e.Fragment,{children:e.jsx("ul",{role:"list",className:"file-node-list search-results",children:oe.map(t=>e.jsx(ce,{node:t,depth:0,expanded:!1,selected:i?.id===t.id,gitLabels:Z[t.displayPath]??[],onToggle:ae,onSelect:n=>{b(n)}},t.id))})}):e.jsx(le,{parentId:"workspace-root",depth:0,directories:f,expanded:x,selectedId:i?.id,gitDecorations:Z,onToggle:ae,onSelect:t=>{b(t)},onLoadMore:t=>{E(t,!0)}})]}),e.jsxs(e.Fragment,{children:[J?e.jsx("p",{className:"resource-notice",role:"status",children:J.text}):null,i?e.jsxs(e.Fragment,{children:[e.jsxs("header",{children:[e.jsx("strong",{children:i.name}),e.jsx("span",{children:Fe(i.sizeBytes??0)})]}),H?e.jsx("p",{className:"resource-error",role:"alert",children:H}):Y?e.jsxs("div",{className:"resource-empty",children:[e.jsx(D,{name:"code",size:16}),e.jsx("strong",{title:"出于安全和性能考虑,只显示元数据。",children:"二进制文件"})]}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"file-preview-actions",children:O==="view"?e.jsx("button",{type:"button",className:"text-button",disabled:!re,title:re?void 0:"仅支持编辑 512 KB 内的 UTF-8 文本文件",onClick:xe,children:"编辑"}):e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",className:"primary-button",disabled:k||L===F,"aria-busy":k,onClick:()=>{je()},children:k?"保存中…":"保存"}),e.jsx("button",{type:"button",className:"text-button",disabled:k,onClick:ie,children:"取消"})]})}),de?e.jsxs("p",{className:"resource-error",role:"alert",children:["文件已在别处变更,保存被拒绝。",e.jsx("button",{type:"button",className:"text-button",onClick:()=>{b(i,!1,!0)},children:"重新加载"})]}):null,O==="edit"?e.jsx("textarea",{className:"file-editor",value:L,spellCheck:!1,"aria-label":`编辑文件 ${i.name}`,onChange:t=>w(t.target.value),onKeyDown:t=>{t.key==="Escape"&&(t.preventDefault(),ie())}}):e.jsx("pre",{tabIndex:0,className:"file-code-view","aria-label":`文件内容 ${i.name}`,children:be(F)})]}),M&&O==="view"?e.jsx("button",{type:"button",className:"secondary-button",onClick:()=>{b(i,!0)},children:"加载更多内容"}):null]}):e.jsxs("div",{className:"resource-empty",children:[e.jsx(D,{name:"workspace",size:16}),e.jsx("strong",{children:"选择文件预览"}),e.jsx("p",{title:"敏感文件、工作区外链接和二进制正文不会返回浏览器。",children:"受限内容不会返回浏览器。"})]})]})]}),e.jsx(ye,{open:he,onClose:()=>W(!1),title:"放弃未保存的修改?",body:"当前草稿尚未保存,放弃后将回到文件的最新内容。",confirmLabel:"放弃修改",danger:!0,onConfirm:ne})]})}function le({parentId:s,depth:o,directories:l,expanded:r,selectedId:d,gitDecorations:c,onToggle:f,onSelect:m,onLoadMore:x}){const j=l[s];return j?j.error?e.jsx("p",{className:"resource-error",role:"alert",children:j.error}):e.jsxs("ul",{role:"list",className:"file-node-list",children:[j.items.map(i=>{const N=r.has(i.id);return e.jsxs("li",{children:[e.jsx(ce,{node:i,depth:o,expanded:N,selected:d===i.id,gitLabels:c[i.displayPath]??[],onToggle:f,onSelect:m}),X(i)&&N?e.jsx(le,{parentId:i.id,depth:o+1,directories:l,expanded:r,selectedId:d,gitDecorations:c,onToggle:f,onSelect:m,onLoadMore:x}):null]},i.id)}),j.loading?e.jsx("li",{className:"resource-loading",children:"正在读取…"}):null,j.nextCursor?e.jsx("li",{children:e.jsx("button",{type:"button",className:"text-button",onClick:()=>x(s),children:"加载更多"})}):null]}):e.jsx("p",{className:"resource-loading",children:"正在读取…"})}function ce({node:s,depth:o,expanded:l,selected:r,gitLabels:d,onToggle:c,onSelect:f}){const m=s.sensitive||!s.readable,x=X(s);return e.jsxs("button",{type:"button",className:`file-node ${r?"selected":""} ${m?"blocked":""}`,style:{paddingInlineStart:`${8+o*15}px`},"aria-expanded":x?l:void 0,"aria-label":`${we(s)} ${s.name}${m?",不可读取":""}${d.length?`,Git ${d.join("、")}`:""}`,onClick:()=>x?c(s.id):f(s),disabled:m,children:[e.jsx(D,{name:x?"workspace":"code",size:16}),e.jsx("span",{children:s.name}),s.kind==="symlink"?e.jsx("small",{children:"链接"}):null,s.sensitive?e.jsx("small",{children:"敏感"}):null,d.length?e.jsx("small",{className:"file-git-status",title:`Git ${d.join("、")}`,children:d.join(" · ")}):null]})}function we(s){return s.kind==="directory"?"目录":s.kind==="symlink"?s.targetKind==="directory"?"符号链接目录":"符号链接":"文件"}function X(s){return s.kind==="directory"||s.kind==="symlink"&&s.targetKind==="directory"}function ke(s,o){const l=new Map(s.map(r=>[r.id,r]));for(const r of o)l.set(r.id,r);return[...l.values()]}function Se(s){if(!s.hasWorktree)return{};const o=new Map,l=(r,d)=>{const c=r.replace(/\\/gu,"/").replace(/^\.\//u,"");if(!c)return;const f=o.get(c)??new Set;f.add(d),o.set(c,f);const m=c.split("/");for(let x=1;x<m.length;x+=1){const j=m.slice(0,x).join("/"),i=o.get(j)??new Set;i.add("含变更"),o.set(j,i)}};return s.conflicted.forEach(r=>l(r.path,"冲突")),s.staged.forEach(r=>l(r.path,"已暂存")),s.unstaged.forEach(r=>l(r.path,"未暂存")),s.untracked.forEach(r=>l(r.path,"未跟踪")),Object.fromEntries([...o].map(([r,d])=>[r,Object.freeze([...d])]))}const Ee=512*1024;function De(s){const{selected:o,binary:l,hasMorePages:r}=s;return!o||l||o.sensitive||!o.readable||r?!1:(o.sizeBytes??0)<=Ee}function Fe(s){return s<1024?`${s} B`:s<1048576?`${(s/1024).toFixed(1)} KB`:`${(s/1048576).toFixed(1)} MB`}function U(s){return s instanceof ge&&s.code==="file_revision_conflict"}function z(s){return s instanceof Error?s.message:"文件请求失败。"}export{Ee as FILE_EDIT_MAX_BYTES,Le as FilesPanel,De as canEditFileContent};
@@ -1,4 +1,4 @@
1
- var $e=Object.defineProperty;var Pe=(t,s,n)=>s in t?$e(t,s,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[s]=n;var ie=(t,s,n)=>Pe(t,typeof s!="symbol"?s+"":s,n);import{r as l,a as He,j as e,I as T}from"./index-DZOlUgt6.js";import{u as Oe,R as Me}from"./useAutoNotice-Ylj5bfSH.js";const Ne="orion.web.git-display.v1",_e=Object.freeze(["changes","history","compare"]),me=Object.freeze({message:"",author:"",path:"",sha:"",since:"",until:""}),xe=Object.freeze({view:"changes",group:null,query:"",selectedFileId:null,selectedSource:null,selectedFileIds:Object.freeze([]),selectedLineIds:Object.freeze([]),collapsedHunks:Object.freeze([]),anchorLineId:null,navigatorScrollTop:0,commitDraft:Object.freeze({summary:"",body:""}),historyQuery:me,selectedCommitId:null,selectedCommitParentIndex:0,selectedCommitPath:null,fileHistoryPath:null,notice:""}),pe=Object.freeze({mode:"unified",wrap:!1,showWhitespace:!1,ignoreWhitespace:!1,wordDiff:!1});function Ae(t){return t||"__no-workspace__"}function ze(){const t=new Map;return{read(s){return t.get(s)??xe},update(s,n){const i=Object.freeze({...t.get(s)??xe,...n});return t.set(s,i),i},clear(s){t.delete(s)}}}const Be=ze();function Ge(){try{const t=globalThis.localStorage?.getItem(Ne);if(!t)return pe;const s=JSON.parse(t);return Te(s)}catch{return pe}}function We(t){try{globalThis.localStorage?.setItem(Ne,JSON.stringify(t))}catch{}}function Te(t){if(typeof t!="object"||t===null)return pe;const s=t;return Object.freeze({mode:s.mode==="side-by-side"?"side-by-side":"unified",wrap:s.wrap===!0,showWhitespace:s.showWhitespace===!0,ignoreWhitespace:s.ignoreWhitespace===!0,wordDiff:s.wordDiff===!0})}function qe(t){if(t.entries.length===0)return{fileId:null,path:null,notice:""};const s=t.entries.find(o=>o.fileId===t.previousFileId);if(s)return{fileId:s.fileId,path:s.path,notice:""};const i=t.entries.find(o=>o.path===t.previousPath)??t.entries[0];return{fileId:i.fileId,path:i.path,notice:t.previousFileId===null?"":`原选中的改动已不在此列表,已跳到 ${i.path}。`}}const Qe=959,Ve=620,Ke=640;function Ue(t,s){if(!Number.isFinite(t)||t<=0)return{tier:"wide",narrow:!1,effectiveMode:s,dataWidth:"wide"};const n=t<=Ve?"narrow":t<=Qe?"compact":"wide";return{tier:n,narrow:n==="narrow",effectiveMode:t<=Ke?"unified":s,dataWidth:n}}const Ye=350,je=30;function Xe(t){const{enabled:s,session:n,setSession:i,actions:o,refreshEpoch:h}=t,g=n.historyQuery??me,[x,a]=l.useState(null),[p,j]=l.useState(null),[b,d]=l.useState(null),[S,u]=l.useState(null),[_,L]=l.useState(null),[v,N]=l.useState(null),[Q,P]=l.useState(!1),[B,E]=l.useState(!1),[q,H]=l.useState(!1),[k,R]=l.useState(""),$=l.useRef(0),r=l.useRef(0),I=l.useMemo(()=>({...g.message.trim()?{message:g.message.trim()}:{},...g.author.trim()?{author:g.author.trim()}:{},...g.path.trim()?{path:g.path.trim()}:{},...g.sha.trim()?{sha:g.sha.trim()}:{},...g.since.trim()?{since:g.since.trim()}:{},...g.until.trim()?{until:g.until.trim()}:{}}),[g]);l.useEffect(()=>{if(!s)return;const w=$.current+1;$.current=w,P(!0),R("");const A=setTimeout(()=>{(async()=>{try{const[z,W]=await Promise.all([o.gitRefs(),o.gitHistory({...I,pageSize:je})]);if(w!==$.current)return;a(z),j(W)}catch(z){if(w!==$.current)return;R(le(z))}finally{w===$.current&&P(!1)}})()},I.message||I.author||I.path||I.sha?Ye:0);return()=>clearTimeout(A)},[o,s,h,I]),l.useEffect(()=>{const w=n.selectedCommitId;if(!s||!w){d(null),u(null),L(null);return}const A=r.current+1;r.current=A;const z=n.selectedCommitParentIndex;H(!0),R(""),(async()=>{try{const[W,X]=await Promise.all([o.gitCommitDetail(w,z),o.gitCommitFiles(w,z)]);if(A!==r.current)return;d(W),u(X);const J=X.files.find(U=>!U.sensitive&&!U.binary),ee=n.selectedCommitPath&&X.files.some(U=>U.path===n.selectedCommitPath)?n.selectedCommitPath:J?.path??null;ee!==n.selectedCommitPath&&i({selectedCommitPath:ee}),ee||L(null)}catch(W){if(A!==r.current)return;R(le(W))}finally{A===r.current&&H(!1)}})()},[o,s,n.selectedCommitId,n.selectedCommitParentIndex]),l.useEffect(()=>{const w=n.selectedCommitId,A=n.selectedCommitPath;if(!s||!w||!A){L(null);return}const z=r.current;(async()=>{try{const W=await o.gitCommitDiff({oid:w,path:A,parentIndex:n.selectedCommitParentIndex});if(z!==r.current)return;L(W)}catch(W){if(z!==r.current)return;R(le(W)),L(null)}})()},[o,s,n.selectedCommitId,n.selectedCommitPath,n.selectedCommitParentIndex]),l.useEffect(()=>{const w=n.fileHistoryPath;if(!s||!w){N(null);return}const A=r.current;(async()=>{try{const z=await o.gitFileHistory({path:w});if(A!==r.current)return;N(z)}catch(z){if(A!==r.current)return;R(le(z))}})()},[o,s,n.fileHistoryPath]);const f=l.useCallback(w=>{i({historyQuery:{...g,...w}})},[g,i]),V=l.useCallback(()=>{i({historyQuery:me})},[i]),c=l.useCallback(w=>{i({selectedCommitId:w.id,selectedCommitParentIndex:0,selectedCommitPath:null})},[i]),M=l.useCallback(()=>{i({selectedCommitId:null,selectedCommitPath:null,selectedCommitParentIndex:0})},[i]),G=l.useCallback(w=>{i({selectedCommitParentIndex:w,selectedCommitPath:null})},[i]),K=l.useCallback(w=>i({selectedCommitPath:w}),[i]),Y=l.useCallback(()=>{const w=p?.nextCursor;if(!w||B)return;const A=$.current;E(!0),(async()=>{try{const z=await o.gitHistory({...I,cursor:w,pageSize:je});if(A!==$.current)return;j(W=>W?{...z,items:[...W.items,...z.items]}:z)}catch(z){if(A!==$.current)return;R(le(z))}finally{A===$.current&&E(!1)}})()},[o,B,p,I]),se=l.useCallback(w=>i({fileHistoryPath:w}),[i]),D=l.useCallback(()=>i({fileHistoryPath:null}),[i]);return{query:g,refs:x,page:p,detail:b,files:S,diff:_,fileHistory:v,loading:Q,loadingMore:B,loadingDetail:q,error:k,isEmptyRepository:p!==null&&p.tipOid===null,setQuery:f,resetQuery:V,selectCommit:c,closeDetail:M,setParentIndex:G,selectFile:K,loadMore:Y,openFileHistory:se,closeFileHistory:D}}function le(t){return t?.code==="git_cursor_invalid"?"历史已变化,已重新载入列表。":t instanceof Error?t.message:"Git 历史读取失败。"}function Je(t){if(!(t instanceof HTMLElement))return!1;const s=t.tagName.toLowerCase();return s==="input"||s==="textarea"||s==="select"||t.isContentEditable?!0:t.closest('[role="dialog"]')!==null}function Ze(t){const{enabled:s,session:n,setSession:i,fileIds:o,anchorLineIds:h,onOpenSelection:g,onEscapeFallback:x}=t;l.useEffect(()=>{if(!s)return;const a=p=>{if(Je(p.target))return;if(p.key==="F7"&&h.length>0){p.preventDefault();const b=n.anchorLineId?h.indexOf(n.anchorLineId):-1,d=p.shiftKey?-1:1,S=b<0?d>0?0:h.length-1:Math.min(h.length-1,Math.max(0,b+d));i({anchorLineId:h[S]});return}if(p.key==="Escape"){if(n.query){p.preventDefault(),i({query:"",selectedFileId:null});return}if(n.selectedLineIds.length>0){p.preventDefault(),i({selectedLineIds:[]});return}x();return}if(o.length===0)return;const j=n.selectedFileId?o.indexOf(n.selectedFileId):-1;if(p.key==="ArrowDown"||p.key==="ArrowUp"){p.preventDefault();const b=p.key==="ArrowDown"?1:-1,d=j<0?b>0?0:o.length-1:Math.min(o.length-1,Math.max(0,j+b));i({selectedFileId:o[d],selectedSource:null,anchorLineId:null});return}if(p.key==="Enter"&&j>=0){p.preventDefault(),g();return}if(p.key===" "){if(j<0)return;p.preventDefault();const b=o[j];i({selectedFileIds:n.selectedFileIds.includes(b)?n.selectedFileIds.filter(d=>d!==b):[...n.selectedFileIds,b]})}};return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[s,n.query,n.selectedFileId,n.selectedLineIds,n.anchorLineId,n.selectedFileIds,i,o,h,g,x])}class et{constructor(s){ie(this,"fetcher");ie(this,"freshnessMs");ie(this,"slots",new Map);this.fetcher=s.fetcher,this.freshnessMs=s.freshnessMs??3e4}getSnapshot(s){const n=this.slotFor(s);n.invalidated&&(n.inFlight=null,n.invalidated=!1);const i=n.snapshot;if(i&&Date.now()-i.fetchedAt<=this.freshnessMs)return Promise.resolve(i);if(n.inFlight)return n.inFlight;n.generation+=1;const o=n.generation,h=this.fetcher(s).then(g=>{const x=this.slots.get(s);if(!x||x.generation!==o||x.invalidated)throw new tt(s);return x.snapshot=Object.freeze({...g,fetchedAt:Date.now()}),x.inFlight=null,x.snapshot}).catch(g=>{const x=this.slots.get(s);throw x&&x.inFlight===h&&(x.inFlight=null),g});return n.inFlight=h,h}invalidate(s){const n=this.slots.get(s);if(!n)return!1;const i=!!(n.snapshot||n.inFlight);return n.invalidated=!0,n.snapshot=null,i}isStale(s,n){const i=this.slots.get(s)?.snapshot;return i?n==null?!1:i.repositoryRevision!==n:!0}cachedSnapshot(s){const n=this.slots.get(s);return!n||n.invalidated||!n.snapshot?null:n.snapshot}clear(){this.slots.clear()}slotFor(s){const n=this.slots.get(s);if(n)return n;const i={workspaceId:s,snapshot:null,inFlight:null,generation:0,invalidated:!1};return this.slots.set(s,i),i}}class tt extends Error{constructor(n){super(`Repository snapshot for ${n} is stale; refetching.`);ie(this,"code","workspace_snapshot_stale")}}const st=20*1024*1024,nt=5*1024*1024;function it(t){let s=0;for(const n of t.hunks){s+=n.header.length;for(const i of n.lines)s+=i.raw.length+48}return s+t.path.length+256}function lt(t){const s=st,n=nt,i=new Map;let o=0,h=0,g=0;const x=(a,p)=>`${a}\0${p}`;return{read(a,p){const j=x(a,p),b=i.get(j);return b?(i.delete(j),i.set(j,b),h+=1,b.document):(g+=1,null)},write(a,p,j){const b=it(j);if(b>n)return;const d=x(a,p),S=i.get(d);for(S&&(i.delete(d),o-=S.bytes),i.set(d,{document:j,bytes:b}),o+=b;o>s&&i.size>0;){const u=i.keys().next();if(u.done)break;const _=i.get(u.value);i.delete(u.value),o-=_?.bytes??0}},clear(){i.clear(),o=0},stats(){return{entries:i.size,bytes:o,hits:h,misses:g}}}}const at=lt(),rt=2e3;function ct(t){const{workspaceId:s,refreshEpoch:n,actions:i}=t,o=t.store??Be,h=t.cache??at,g=Ae(s),[x,a]=l.useState(()=>o.read(g)),[p,j]=l.useState(()=>Ge()),[b,d]=l.useState(null),[S,u]=l.useState(null),[_,L]=l.useState(null),[v,N]=l.useState(!1),[Q,P]=l.useState(!1),[B,E]=l.useState(""),[q,H]=l.useState(!1),k=l.useRef(0),R=l.useRef(0),$=l.useRef(x);$.current=x;const r=l.useRef(b),I=l.useRef(p);I.current=p,r.current=b;const f=l.useCallback(m=>{a(o.update(g,m))},[g,o]),V=l.useCallback(m=>{j(y=>{const F=Object.freeze({...y,...m});return We(F),F})},[]),c=l.useCallback(async(m,y)=>{if(m===k.current){y.quiet?P(!0):N(!0),E("");try{const F=$.current,[C,O]=await Promise.all([i.gitStatus(void 0,{...F.group?{group:F.group}:{},...F.query?{query:F.query}:{}}),i.gitLog()]);if(m!==k.current)return;if(d(C),u(O),!C.hasWorktree){L(null),H(!1);return}const ne=ue(C);if(!y.keepSelection){L(null),f({selectedFileId:null,selectedSource:null,anchorLineId:null}),H(!1);return}const ae=F.selectedFileId,Re=ne.find(de=>de.fileId===ae)?.path??(_?_.path:null),oe=qe({entries:ne,previousFileId:ae,previousPath:Re});if(oe.fileId&&oe.fileId!==ae){f({selectedFileId:null,selectedSource:null,notice:oe.notice}),L(null),H(!1);return}if(ae){const de=_!==null&&C.repositoryRevision===_.repositoryRevision;H(!de)}else H(!1)}catch(F){if(m!==k.current)return;E(Z(F))}finally{m===k.current&&(N(!1),P(!1))}}},[i,_,f]),M=l.useCallback(()=>{const m=k.current+1;k.current=m,R.current+=1,c(m,{keepSelection:!0,quiet:b!==null})},[c,b]);l.useEffect(()=>{const m=k.current+1;k.current=m,R.current+=1,d(null),u(null),L(null),E(""),H(!1),N(!!s),a(o.read(g)),s?c(m,{keepSelection:!1}):N(!1)},[g,s,o]),l.useEffect(()=>{if(!s||n===0)return;const m=k.current+1;k.current=m,R.current+=1,c(m,{keepSelection:!0,quiet:!0})},[n]),l.useEffect(()=>{if(!s||typeof document>"u")return;let m;const y=()=>{m!==void 0&&clearInterval(m),m=void 0},F=()=>{y(),m=setInterval(()=>{const O=k.current+1;k.current=O,c(O,{keepSelection:!0,quiet:!0})},rt)},C=()=>{if(document.visibilityState==="visible"){const O=k.current+1;k.current=O,c(O,{keepSelection:!0,quiet:!0}),F()}else y()};return document.visibilityState==="visible"&&F(),document.addEventListener("visibilitychange",C),()=>{y(),document.removeEventListener("visibilitychange",C)}},[s,x.group,x.query]);const G=l.useCallback(m=>{const y=R.current+1;R.current=y,f({selectedLineIds:[],selectedFileId:m.fileId,selectedSource:m.source,anchorLineId:null,notice:""}),E("");const F=r.current?.repositoryRevision,C=F?h.read(F,m.fileId):null;if(C){L(C),H(!1),N(!1);return}L(null),N(!0),(async()=>{try{const O=await i.gitDiffDocument(m.fileId,void 0,I.current.ignoreWhitespace,I.current.wordDiff);if(y!==R.current)return;h.write(O.repositoryRevision,m.fileId,O),L(O),H(O.repositoryRevision!==r.current?.repositoryRevision)}catch(O){if(y!==R.current)return;if(ut(O)){E("仓库已变化,已重新载入 Git 状态。"),f({selectedFileId:null,selectedSource:null});return}E(Z(O))}finally{y===R.current&&N(!1)}})()},[i,h,f]),K=l.useCallback(()=>{const m=b?.nextCursor;if(!m)return;const y=k.current,F=b?.repositoryRevision;(async()=>{try{const C=await i.gitStatus(m,{...x.group?{group:x.group}:{},...x.query?{query:x.query}:{}});if(y!==k.current)return;if(F!==void 0&&C.repositoryRevision!==F){E("仓库已变化,已重新载入 Git 状态。");return}d(O=>O&&{...C,conflicted:re(O.conflicted,C.conflicted),staged:re(O.staged,C.staged),unstaged:re(O.unstaged,C.unstaged),untracked:re(O.untracked,C.untracked),counts:{...C.counts,loaded:O.counts.loaded+C.counts.loaded}})}catch(C){if(y!==k.current)return;E(Z(C))}})()},[i,x.group,x.query,b]),Y=l.useCallback(()=>{const m=S?.nextCursor;if(!m)return;const y=k.current;(async()=>{try{const F=await i.gitLog(m);if(y!==k.current)return;u(C=>C&&{...F,items:dt(C.items,F.items)})}catch(F){if(y!==k.current)return;E(Z(F))}})()},[i,S]),se=l.useCallback(()=>{const m=_?.nextCursor,y=x.selectedFileId;if(!m||!y)return;const F=k.current,C=R.current;(async()=>{try{const O=await i.gitDiffDocument(y,m,I.current.ignoreWhitespace,I.current.wordDiff);if(F!==k.current||C!==R.current)return;L(ne=>ne?{...O,hunks:[...ne.hunks,...O.hunks]}:O)}catch(O){if(F!==k.current||C!==R.current)return;E(Z(O))}})()},[i,_,x.selectedFileId]);l.useEffect(()=>{!b||!x.selectedFileId||ue(b).some(y=>y.fileId===x.selectedFileId)||(L(null),f({selectedFileId:null,selectedSource:null,anchorLineId:null}))},[b,x.selectedFileId,f]);const D=l.useMemo(()=>!b||!x.selectedFileId?null:ue(b).find(m=>m.fileId===x.selectedFileId)??null,[b,x.selectedFileId]),[w,A]=l.useState(!1),[z,W]=l.useState(null),X=l.useRef(null);X.current===null&&(X.current=new et({fetcher:async m=>{const y=await i.gitStatus(void 0,{});return Object.freeze({repositoryRevision:y.repositoryRevision,branch:y.branch,counts:Object.freeze({totalChangedFiles:y.counts.total,staged:y.counts.staged,unstaged:y.counts.unstaged,untracked:y.counts.untracked,conflicted:y.counts.conflicted}),fetchedAt:Date.now()})}}));const J=X.current,ee=l.useCallback(async()=>{const m=r.current;if(m?.hasWorktree)try{if((await J.getSnapshot(s)).repositoryRevision===m.repositoryRevision)return;J.invalidate(s),await c(k.current,{keepSelection:!0,quiet:!0})}catch{}},[c,J,s]);l.useEffect(()=>{if(!s)return;let m=!1;const y=()=>{m||document.hidden||(m=!0,ee().finally(()=>{m=!1}))},F=()=>{document.hidden||y()};return window.addEventListener("focus",y),document.addEventListener("visibilitychange",F),()=>{window.removeEventListener("focus",y),document.removeEventListener("visibilitychange",F)}},[ee,s]);const U=l.useCallback(async()=>{h.clear(),J.invalidate(s);const m=k.current+1;k.current=m,R.current+=1,await c(m,{keepSelection:!0,quiet:!0})},[h,c,J,s]),te=l.useCallback(async(m,y)=>{if(!w){A(!0),E("");try{await m(),await U(),f({notice:y})}catch(F){E(Z(F))}finally{A(!1)}}},[w,U,f]),Ce=l.useCallback(async m=>{const y=r.current?.repositoryRevision;y&&(await te(()=>i.gitStage(m,y),m.length>1?`已暂存 ${m.length} 个文件。`:"已暂存。"),f({selectedFileIds:[]}))},[i,te,f]),we=l.useCallback(async m=>{const y=r.current?.repositoryRevision;y&&(await te(()=>i.gitUnstage(m,y),m.length>1?`已取消暂存 ${m.length} 个文件。`:"已取消暂存。"),f({selectedFileIds:[]}))},[i,te,f]),Fe=l.useCallback(async m=>{const y=r.current?.repositoryRevision;y&&await te(()=>i.gitApplyPatch({...m,expectedRepositoryRevision:y}),"已应用所选改动到索引。")},[i,te]),Le=l.useCallback(async m=>{const y=r.current?.repositoryRevision;if(!y)throw new Error("Git repository is unavailable.");A(!0),E("");const F=He();try{const C=await i.gitCommit({summary:m.summary,...m.body?{body:m.body}:{},expectedRepositoryRevision:y,requestId:F});return await U(),f({commitDraft:{summary:"",body:""},notice:C.warning?`已提交 ${C.commitSha.slice(0,8)},但:${C.warning}`:`已提交 ${C.commitSha.slice(0,8)}。`}),C.commitSha}catch(C){throw E(Z(C)),C}finally{A(!1)}},[i,U,f]),De=l.useCallback(m=>{const y=$.current.selectedFileIds;f({selectedFileIds:y.includes(m)?y.filter(F=>F!==m):[...y,m]})},[f]),Ee=l.useCallback(()=>f({selectedFileIds:[]}),[f]);return l.useEffect(()=>{if(!b?.hasWorktree){W(null);return}let m=!1;return(async()=>{try{const y=await i.gitCommitPreview();m||W(y)}catch{m||W(null)}})(),()=>{m=!0}},[i,b?.hasWorktree,b?.repositoryRevision]),{session:x,display:p,status:b,log:S,diff:_,loading:v,refreshing:Q,error:B,stale:q,setSession:f,setDisplay:V,openFile:G,reload:M,loadMoreStatus:K,loadMoreLog:Y,loadMoreDiff:se,selectedEntry:D,busy:w,commitPreview:z,toggleSelection:De,clearSelection:Ee,stagePaths:Ce,unstagePaths:we,applyPatch:Fe,commit:Le}}function ue(t){return[...t.conflicted,...t.unstaged,...t.staged,...t.untracked]}function ot(t,s){return s==="conflict"?t.conflicted:s==="unstaged"?t.unstaged:s==="staged"?t.staged:t.untracked}function re(t,s){const n=new Map(t.map(i=>[i.fileId,i]));for(const i of s)n.set(i.fileId,i);return[...n.values()]}function dt(t,s){const n=new Map(t.map(i=>[i.id,i]));for(const i of s)n.set(i.id,i);return[...n.values()]}function Z(t){return t instanceof Error?t.message:"Git 请求失败。"}function ut(t){return typeof t=="object"&&t!==null&&t.code==="git_revision_conflict"}function ht(t){const s=[];let n=0;const i=t.lines;for(;n<i.length;){const o=i[n];if(o.kind==="deletion"){const h=[];for(;n<i.length&&i[n].kind==="deletion";)h.push(i[n]),n+=1;const g=[];for(;n<i.length&&i[n].kind==="addition";)g.push(i[n]),n+=1;const x=Math.max(h.length,g.length);for(let a=0;a<x;a+=1){const p=h[a]??null,j=g[a]??null;s.push(Object.freeze({key:`${t.hunkId}:${p?.lineId??`-${a}`}:${j?.lineId??`-${a}`}`,left:p,right:j,changed:!0}))}continue}if(o.kind==="addition"){s.push(Object.freeze({key:`${t.hunkId}:${o.lineId}`,left:null,right:o,changed:!0})),n+=1;continue}s.push(Object.freeze({key:`${t.hunkId}:${o.lineId}`,left:o,right:o,changed:!1})),n+=1}return s}function ft(t,s,n){const i=new Set(s),o=[];for(const h of t){if(o.push(Object.freeze({kind:"hunk-header",hunk:h})),i.has(h.hunkId)){o.push(Object.freeze({kind:"folded",hunk:h}));continue}if(n==="side-by-side"){for(const g of ht(h))o.push(Object.freeze({kind:"side-by-side",hunk:h,row:g}));continue}for(const g of h.lines)o.push(Object.freeze({kind:"unified-line",hunk:h,line:g}))}return o}function ve(t){const s=[];for(const n of t){let i=!1;for(const o of n.lines){const h=o.kind==="addition"||o.kind==="deletion";h&&!i&&s.push(Object.freeze({lineId:o.lineId,hunkId:n.hunkId,oldLineNumber:o.oldLineNumber,newLineNumber:o.newLineNumber})),i=h}}return s}function mt(t,s,n=500){const i=s.trim().toLowerCase();if(!i)return[];const o=[];for(const h of t)for(const g of h.lines){if(o.length>=n)return o;g.text.toLowerCase().includes(i)&&o.push(Object.freeze({lineId:g.lineId,hunkId:h.hunkId,side:g.oldLineNumber!==null&&g.newLineNumber!==null?"both":g.oldLineNumber!==null?"old":"new"}))}return o}function pt(t){let s=0,n=0;for(const i of t)for(const o of i.lines)o.kind==="addition"?s+=1:o.kind==="deletion"&&(n+=1);return Object.freeze({additions:s,deletions:n,hunks:t.length})}function ce(t,s){return s?t.replace(/\t/gu,"→ ").replace(/ +$/gu,n=>"·".repeat(n.length)):t}function ge(t){return t==="addition"?"+":t==="deletion"?"-":t==="meta"?"\\":" "}function gt(t,s){const n={schemaVersion:2,type:"review_context",repositoryRevision:t.repositoryRevision,path:t.path,source:t.source,hunk:s.header,hunkId:s.hunkId,complete:s.complete},i=s.lines.map(o=>o.raw).join(`
1
+ var $e=Object.defineProperty;var Pe=(t,s,n)=>s in t?$e(t,s,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[s]=n;var ie=(t,s,n)=>Pe(t,typeof s!="symbol"?s+"":s,n);import{r as l,a as He,j as e,I as T}from"./index-kQqA3li6.js";import{u as Oe,R as Me}from"./useAutoNotice-DPXFWIwK.js";const Ne="orion.web.git-display.v1",_e=Object.freeze(["changes","history","compare"]),me=Object.freeze({message:"",author:"",path:"",sha:"",since:"",until:""}),xe=Object.freeze({view:"changes",group:null,query:"",selectedFileId:null,selectedSource:null,selectedFileIds:Object.freeze([]),selectedLineIds:Object.freeze([]),collapsedHunks:Object.freeze([]),anchorLineId:null,navigatorScrollTop:0,commitDraft:Object.freeze({summary:"",body:""}),historyQuery:me,selectedCommitId:null,selectedCommitParentIndex:0,selectedCommitPath:null,fileHistoryPath:null,notice:""}),pe=Object.freeze({mode:"unified",wrap:!1,showWhitespace:!1,ignoreWhitespace:!1,wordDiff:!1});function Ae(t){return t||"__no-workspace__"}function ze(){const t=new Map;return{read(s){return t.get(s)??xe},update(s,n){const i=Object.freeze({...t.get(s)??xe,...n});return t.set(s,i),i},clear(s){t.delete(s)}}}const Be=ze();function Ge(){try{const t=globalThis.localStorage?.getItem(Ne);if(!t)return pe;const s=JSON.parse(t);return Te(s)}catch{return pe}}function We(t){try{globalThis.localStorage?.setItem(Ne,JSON.stringify(t))}catch{}}function Te(t){if(typeof t!="object"||t===null)return pe;const s=t;return Object.freeze({mode:s.mode==="side-by-side"?"side-by-side":"unified",wrap:s.wrap===!0,showWhitespace:s.showWhitespace===!0,ignoreWhitespace:s.ignoreWhitespace===!0,wordDiff:s.wordDiff===!0})}function qe(t){if(t.entries.length===0)return{fileId:null,path:null,notice:""};const s=t.entries.find(o=>o.fileId===t.previousFileId);if(s)return{fileId:s.fileId,path:s.path,notice:""};const i=t.entries.find(o=>o.path===t.previousPath)??t.entries[0];return{fileId:i.fileId,path:i.path,notice:t.previousFileId===null?"":`原选中的改动已不在此列表,已跳到 ${i.path}。`}}const Qe=959,Ve=620,Ke=640;function Ue(t,s){if(!Number.isFinite(t)||t<=0)return{tier:"wide",narrow:!1,effectiveMode:s,dataWidth:"wide"};const n=t<=Ve?"narrow":t<=Qe?"compact":"wide";return{tier:n,narrow:n==="narrow",effectiveMode:t<=Ke?"unified":s,dataWidth:n}}const Ye=350,je=30;function Xe(t){const{enabled:s,session:n,setSession:i,actions:o,refreshEpoch:h}=t,g=n.historyQuery??me,[x,a]=l.useState(null),[p,j]=l.useState(null),[b,d]=l.useState(null),[S,u]=l.useState(null),[_,L]=l.useState(null),[v,N]=l.useState(null),[Q,P]=l.useState(!1),[B,E]=l.useState(!1),[q,H]=l.useState(!1),[k,R]=l.useState(""),$=l.useRef(0),r=l.useRef(0),I=l.useMemo(()=>({...g.message.trim()?{message:g.message.trim()}:{},...g.author.trim()?{author:g.author.trim()}:{},...g.path.trim()?{path:g.path.trim()}:{},...g.sha.trim()?{sha:g.sha.trim()}:{},...g.since.trim()?{since:g.since.trim()}:{},...g.until.trim()?{until:g.until.trim()}:{}}),[g]);l.useEffect(()=>{if(!s)return;const w=$.current+1;$.current=w,P(!0),R("");const A=setTimeout(()=>{(async()=>{try{const[z,W]=await Promise.all([o.gitRefs(),o.gitHistory({...I,pageSize:je})]);if(w!==$.current)return;a(z),j(W)}catch(z){if(w!==$.current)return;R(le(z))}finally{w===$.current&&P(!1)}})()},I.message||I.author||I.path||I.sha?Ye:0);return()=>clearTimeout(A)},[o,s,h,I]),l.useEffect(()=>{const w=n.selectedCommitId;if(!s||!w){d(null),u(null),L(null);return}const A=r.current+1;r.current=A;const z=n.selectedCommitParentIndex;H(!0),R(""),(async()=>{try{const[W,X]=await Promise.all([o.gitCommitDetail(w,z),o.gitCommitFiles(w,z)]);if(A!==r.current)return;d(W),u(X);const J=X.files.find(U=>!U.sensitive&&!U.binary),ee=n.selectedCommitPath&&X.files.some(U=>U.path===n.selectedCommitPath)?n.selectedCommitPath:J?.path??null;ee!==n.selectedCommitPath&&i({selectedCommitPath:ee}),ee||L(null)}catch(W){if(A!==r.current)return;R(le(W))}finally{A===r.current&&H(!1)}})()},[o,s,n.selectedCommitId,n.selectedCommitParentIndex]),l.useEffect(()=>{const w=n.selectedCommitId,A=n.selectedCommitPath;if(!s||!w||!A){L(null);return}const z=r.current;(async()=>{try{const W=await o.gitCommitDiff({oid:w,path:A,parentIndex:n.selectedCommitParentIndex});if(z!==r.current)return;L(W)}catch(W){if(z!==r.current)return;R(le(W)),L(null)}})()},[o,s,n.selectedCommitId,n.selectedCommitPath,n.selectedCommitParentIndex]),l.useEffect(()=>{const w=n.fileHistoryPath;if(!s||!w){N(null);return}const A=r.current;(async()=>{try{const z=await o.gitFileHistory({path:w});if(A!==r.current)return;N(z)}catch(z){if(A!==r.current)return;R(le(z))}})()},[o,s,n.fileHistoryPath]);const f=l.useCallback(w=>{i({historyQuery:{...g,...w}})},[g,i]),V=l.useCallback(()=>{i({historyQuery:me})},[i]),c=l.useCallback(w=>{i({selectedCommitId:w.id,selectedCommitParentIndex:0,selectedCommitPath:null})},[i]),M=l.useCallback(()=>{i({selectedCommitId:null,selectedCommitPath:null,selectedCommitParentIndex:0})},[i]),G=l.useCallback(w=>{i({selectedCommitParentIndex:w,selectedCommitPath:null})},[i]),K=l.useCallback(w=>i({selectedCommitPath:w}),[i]),Y=l.useCallback(()=>{const w=p?.nextCursor;if(!w||B)return;const A=$.current;E(!0),(async()=>{try{const z=await o.gitHistory({...I,cursor:w,pageSize:je});if(A!==$.current)return;j(W=>W?{...z,items:[...W.items,...z.items]}:z)}catch(z){if(A!==$.current)return;R(le(z))}finally{A===$.current&&E(!1)}})()},[o,B,p,I]),se=l.useCallback(w=>i({fileHistoryPath:w}),[i]),D=l.useCallback(()=>i({fileHistoryPath:null}),[i]);return{query:g,refs:x,page:p,detail:b,files:S,diff:_,fileHistory:v,loading:Q,loadingMore:B,loadingDetail:q,error:k,isEmptyRepository:p!==null&&p.tipOid===null,setQuery:f,resetQuery:V,selectCommit:c,closeDetail:M,setParentIndex:G,selectFile:K,loadMore:Y,openFileHistory:se,closeFileHistory:D}}function le(t){return t?.code==="git_cursor_invalid"?"历史已变化,已重新载入列表。":t instanceof Error?t.message:"Git 历史读取失败。"}function Je(t){if(!(t instanceof HTMLElement))return!1;const s=t.tagName.toLowerCase();return s==="input"||s==="textarea"||s==="select"||t.isContentEditable?!0:t.closest('[role="dialog"]')!==null}function Ze(t){const{enabled:s,session:n,setSession:i,fileIds:o,anchorLineIds:h,onOpenSelection:g,onEscapeFallback:x}=t;l.useEffect(()=>{if(!s)return;const a=p=>{if(Je(p.target))return;if(p.key==="F7"&&h.length>0){p.preventDefault();const b=n.anchorLineId?h.indexOf(n.anchorLineId):-1,d=p.shiftKey?-1:1,S=b<0?d>0?0:h.length-1:Math.min(h.length-1,Math.max(0,b+d));i({anchorLineId:h[S]});return}if(p.key==="Escape"){if(n.query){p.preventDefault(),i({query:"",selectedFileId:null});return}if(n.selectedLineIds.length>0){p.preventDefault(),i({selectedLineIds:[]});return}x();return}if(o.length===0)return;const j=n.selectedFileId?o.indexOf(n.selectedFileId):-1;if(p.key==="ArrowDown"||p.key==="ArrowUp"){p.preventDefault();const b=p.key==="ArrowDown"?1:-1,d=j<0?b>0?0:o.length-1:Math.min(o.length-1,Math.max(0,j+b));i({selectedFileId:o[d],selectedSource:null,anchorLineId:null});return}if(p.key==="Enter"&&j>=0){p.preventDefault(),g();return}if(p.key===" "){if(j<0)return;p.preventDefault();const b=o[j];i({selectedFileIds:n.selectedFileIds.includes(b)?n.selectedFileIds.filter(d=>d!==b):[...n.selectedFileIds,b]})}};return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[s,n.query,n.selectedFileId,n.selectedLineIds,n.anchorLineId,n.selectedFileIds,i,o,h,g,x])}class et{constructor(s){ie(this,"fetcher");ie(this,"freshnessMs");ie(this,"slots",new Map);this.fetcher=s.fetcher,this.freshnessMs=s.freshnessMs??3e4}getSnapshot(s){const n=this.slotFor(s);n.invalidated&&(n.inFlight=null,n.invalidated=!1);const i=n.snapshot;if(i&&Date.now()-i.fetchedAt<=this.freshnessMs)return Promise.resolve(i);if(n.inFlight)return n.inFlight;n.generation+=1;const o=n.generation,h=this.fetcher(s).then(g=>{const x=this.slots.get(s);if(!x||x.generation!==o||x.invalidated)throw new tt(s);return x.snapshot=Object.freeze({...g,fetchedAt:Date.now()}),x.inFlight=null,x.snapshot}).catch(g=>{const x=this.slots.get(s);throw x&&x.inFlight===h&&(x.inFlight=null),g});return n.inFlight=h,h}invalidate(s){const n=this.slots.get(s);if(!n)return!1;const i=!!(n.snapshot||n.inFlight);return n.invalidated=!0,n.snapshot=null,i}isStale(s,n){const i=this.slots.get(s)?.snapshot;return i?n==null?!1:i.repositoryRevision!==n:!0}cachedSnapshot(s){const n=this.slots.get(s);return!n||n.invalidated||!n.snapshot?null:n.snapshot}clear(){this.slots.clear()}slotFor(s){const n=this.slots.get(s);if(n)return n;const i={workspaceId:s,snapshot:null,inFlight:null,generation:0,invalidated:!1};return this.slots.set(s,i),i}}class tt extends Error{constructor(n){super(`Repository snapshot for ${n} is stale; refetching.`);ie(this,"code","workspace_snapshot_stale")}}const st=20*1024*1024,nt=5*1024*1024;function it(t){let s=0;for(const n of t.hunks){s+=n.header.length;for(const i of n.lines)s+=i.raw.length+48}return s+t.path.length+256}function lt(t){const s=st,n=nt,i=new Map;let o=0,h=0,g=0;const x=(a,p)=>`${a}\0${p}`;return{read(a,p){const j=x(a,p),b=i.get(j);return b?(i.delete(j),i.set(j,b),h+=1,b.document):(g+=1,null)},write(a,p,j){const b=it(j);if(b>n)return;const d=x(a,p),S=i.get(d);for(S&&(i.delete(d),o-=S.bytes),i.set(d,{document:j,bytes:b}),o+=b;o>s&&i.size>0;){const u=i.keys().next();if(u.done)break;const _=i.get(u.value);i.delete(u.value),o-=_?.bytes??0}},clear(){i.clear(),o=0},stats(){return{entries:i.size,bytes:o,hits:h,misses:g}}}}const at=lt(),rt=2e3;function ct(t){const{workspaceId:s,refreshEpoch:n,actions:i}=t,o=t.store??Be,h=t.cache??at,g=Ae(s),[x,a]=l.useState(()=>o.read(g)),[p,j]=l.useState(()=>Ge()),[b,d]=l.useState(null),[S,u]=l.useState(null),[_,L]=l.useState(null),[v,N]=l.useState(!1),[Q,P]=l.useState(!1),[B,E]=l.useState(""),[q,H]=l.useState(!1),k=l.useRef(0),R=l.useRef(0),$=l.useRef(x);$.current=x;const r=l.useRef(b),I=l.useRef(p);I.current=p,r.current=b;const f=l.useCallback(m=>{a(o.update(g,m))},[g,o]),V=l.useCallback(m=>{j(y=>{const F=Object.freeze({...y,...m});return We(F),F})},[]),c=l.useCallback(async(m,y)=>{if(m===k.current){y.quiet?P(!0):N(!0),E("");try{const F=$.current,[C,O]=await Promise.all([i.gitStatus(void 0,{...F.group?{group:F.group}:{},...F.query?{query:F.query}:{}}),i.gitLog()]);if(m!==k.current)return;if(d(C),u(O),!C.hasWorktree){L(null),H(!1);return}const ne=ue(C);if(!y.keepSelection){L(null),f({selectedFileId:null,selectedSource:null,anchorLineId:null}),H(!1);return}const ae=F.selectedFileId,Re=ne.find(de=>de.fileId===ae)?.path??(_?_.path:null),oe=qe({entries:ne,previousFileId:ae,previousPath:Re});if(oe.fileId&&oe.fileId!==ae){f({selectedFileId:null,selectedSource:null,notice:oe.notice}),L(null),H(!1);return}if(ae){const de=_!==null&&C.repositoryRevision===_.repositoryRevision;H(!de)}else H(!1)}catch(F){if(m!==k.current)return;E(Z(F))}finally{m===k.current&&(N(!1),P(!1))}}},[i,_,f]),M=l.useCallback(()=>{const m=k.current+1;k.current=m,R.current+=1,c(m,{keepSelection:!0,quiet:b!==null})},[c,b]);l.useEffect(()=>{const m=k.current+1;k.current=m,R.current+=1,d(null),u(null),L(null),E(""),H(!1),N(!!s),a(o.read(g)),s?c(m,{keepSelection:!1}):N(!1)},[g,s,o]),l.useEffect(()=>{if(!s||n===0)return;const m=k.current+1;k.current=m,R.current+=1,c(m,{keepSelection:!0,quiet:!0})},[n]),l.useEffect(()=>{if(!s||typeof document>"u")return;let m;const y=()=>{m!==void 0&&clearInterval(m),m=void 0},F=()=>{y(),m=setInterval(()=>{const O=k.current+1;k.current=O,c(O,{keepSelection:!0,quiet:!0})},rt)},C=()=>{if(document.visibilityState==="visible"){const O=k.current+1;k.current=O,c(O,{keepSelection:!0,quiet:!0}),F()}else y()};return document.visibilityState==="visible"&&F(),document.addEventListener("visibilitychange",C),()=>{y(),document.removeEventListener("visibilitychange",C)}},[s,x.group,x.query]);const G=l.useCallback(m=>{const y=R.current+1;R.current=y,f({selectedLineIds:[],selectedFileId:m.fileId,selectedSource:m.source,anchorLineId:null,notice:""}),E("");const F=r.current?.repositoryRevision,C=F?h.read(F,m.fileId):null;if(C){L(C),H(!1),N(!1);return}L(null),N(!0),(async()=>{try{const O=await i.gitDiffDocument(m.fileId,void 0,I.current.ignoreWhitespace,I.current.wordDiff);if(y!==R.current)return;h.write(O.repositoryRevision,m.fileId,O),L(O),H(O.repositoryRevision!==r.current?.repositoryRevision)}catch(O){if(y!==R.current)return;if(ut(O)){E("仓库已变化,已重新载入 Git 状态。"),f({selectedFileId:null,selectedSource:null});return}E(Z(O))}finally{y===R.current&&N(!1)}})()},[i,h,f]),K=l.useCallback(()=>{const m=b?.nextCursor;if(!m)return;const y=k.current,F=b?.repositoryRevision;(async()=>{try{const C=await i.gitStatus(m,{...x.group?{group:x.group}:{},...x.query?{query:x.query}:{}});if(y!==k.current)return;if(F!==void 0&&C.repositoryRevision!==F){E("仓库已变化,已重新载入 Git 状态。");return}d(O=>O&&{...C,conflicted:re(O.conflicted,C.conflicted),staged:re(O.staged,C.staged),unstaged:re(O.unstaged,C.unstaged),untracked:re(O.untracked,C.untracked),counts:{...C.counts,loaded:O.counts.loaded+C.counts.loaded}})}catch(C){if(y!==k.current)return;E(Z(C))}})()},[i,x.group,x.query,b]),Y=l.useCallback(()=>{const m=S?.nextCursor;if(!m)return;const y=k.current;(async()=>{try{const F=await i.gitLog(m);if(y!==k.current)return;u(C=>C&&{...F,items:dt(C.items,F.items)})}catch(F){if(y!==k.current)return;E(Z(F))}})()},[i,S]),se=l.useCallback(()=>{const m=_?.nextCursor,y=x.selectedFileId;if(!m||!y)return;const F=k.current,C=R.current;(async()=>{try{const O=await i.gitDiffDocument(y,m,I.current.ignoreWhitespace,I.current.wordDiff);if(F!==k.current||C!==R.current)return;L(ne=>ne?{...O,hunks:[...ne.hunks,...O.hunks]}:O)}catch(O){if(F!==k.current||C!==R.current)return;E(Z(O))}})()},[i,_,x.selectedFileId]);l.useEffect(()=>{!b||!x.selectedFileId||ue(b).some(y=>y.fileId===x.selectedFileId)||(L(null),f({selectedFileId:null,selectedSource:null,anchorLineId:null}))},[b,x.selectedFileId,f]);const D=l.useMemo(()=>!b||!x.selectedFileId?null:ue(b).find(m=>m.fileId===x.selectedFileId)??null,[b,x.selectedFileId]),[w,A]=l.useState(!1),[z,W]=l.useState(null),X=l.useRef(null);X.current===null&&(X.current=new et({fetcher:async m=>{const y=await i.gitStatus(void 0,{});return Object.freeze({repositoryRevision:y.repositoryRevision,branch:y.branch,counts:Object.freeze({totalChangedFiles:y.counts.total,staged:y.counts.staged,unstaged:y.counts.unstaged,untracked:y.counts.untracked,conflicted:y.counts.conflicted}),fetchedAt:Date.now()})}}));const J=X.current,ee=l.useCallback(async()=>{const m=r.current;if(m?.hasWorktree)try{if((await J.getSnapshot(s)).repositoryRevision===m.repositoryRevision)return;J.invalidate(s),await c(k.current,{keepSelection:!0,quiet:!0})}catch{}},[c,J,s]);l.useEffect(()=>{if(!s)return;let m=!1;const y=()=>{m||document.hidden||(m=!0,ee().finally(()=>{m=!1}))},F=()=>{document.hidden||y()};return window.addEventListener("focus",y),document.addEventListener("visibilitychange",F),()=>{window.removeEventListener("focus",y),document.removeEventListener("visibilitychange",F)}},[ee,s]);const U=l.useCallback(async()=>{h.clear(),J.invalidate(s);const m=k.current+1;k.current=m,R.current+=1,await c(m,{keepSelection:!0,quiet:!0})},[h,c,J,s]),te=l.useCallback(async(m,y)=>{if(!w){A(!0),E("");try{await m(),await U(),f({notice:y})}catch(F){E(Z(F))}finally{A(!1)}}},[w,U,f]),Ce=l.useCallback(async m=>{const y=r.current?.repositoryRevision;y&&(await te(()=>i.gitStage(m,y),m.length>1?`已暂存 ${m.length} 个文件。`:"已暂存。"),f({selectedFileIds:[]}))},[i,te,f]),we=l.useCallback(async m=>{const y=r.current?.repositoryRevision;y&&(await te(()=>i.gitUnstage(m,y),m.length>1?`已取消暂存 ${m.length} 个文件。`:"已取消暂存。"),f({selectedFileIds:[]}))},[i,te,f]),Fe=l.useCallback(async m=>{const y=r.current?.repositoryRevision;y&&await te(()=>i.gitApplyPatch({...m,expectedRepositoryRevision:y}),"已应用所选改动到索引。")},[i,te]),Le=l.useCallback(async m=>{const y=r.current?.repositoryRevision;if(!y)throw new Error("Git repository is unavailable.");A(!0),E("");const F=He();try{const C=await i.gitCommit({summary:m.summary,...m.body?{body:m.body}:{},expectedRepositoryRevision:y,requestId:F});return await U(),f({commitDraft:{summary:"",body:""},notice:C.warning?`已提交 ${C.commitSha.slice(0,8)},但:${C.warning}`:`已提交 ${C.commitSha.slice(0,8)}。`}),C.commitSha}catch(C){throw E(Z(C)),C}finally{A(!1)}},[i,U,f]),De=l.useCallback(m=>{const y=$.current.selectedFileIds;f({selectedFileIds:y.includes(m)?y.filter(F=>F!==m):[...y,m]})},[f]),Ee=l.useCallback(()=>f({selectedFileIds:[]}),[f]);return l.useEffect(()=>{if(!b?.hasWorktree){W(null);return}let m=!1;return(async()=>{try{const y=await i.gitCommitPreview();m||W(y)}catch{m||W(null)}})(),()=>{m=!0}},[i,b?.hasWorktree,b?.repositoryRevision]),{session:x,display:p,status:b,log:S,diff:_,loading:v,refreshing:Q,error:B,stale:q,setSession:f,setDisplay:V,openFile:G,reload:M,loadMoreStatus:K,loadMoreLog:Y,loadMoreDiff:se,selectedEntry:D,busy:w,commitPreview:z,toggleSelection:De,clearSelection:Ee,stagePaths:Ce,unstagePaths:we,applyPatch:Fe,commit:Le}}function ue(t){return[...t.conflicted,...t.unstaged,...t.staged,...t.untracked]}function ot(t,s){return s==="conflict"?t.conflicted:s==="unstaged"?t.unstaged:s==="staged"?t.staged:t.untracked}function re(t,s){const n=new Map(t.map(i=>[i.fileId,i]));for(const i of s)n.set(i.fileId,i);return[...n.values()]}function dt(t,s){const n=new Map(t.map(i=>[i.id,i]));for(const i of s)n.set(i.id,i);return[...n.values()]}function Z(t){return t instanceof Error?t.message:"Git 请求失败。"}function ut(t){return typeof t=="object"&&t!==null&&t.code==="git_revision_conflict"}function ht(t){const s=[];let n=0;const i=t.lines;for(;n<i.length;){const o=i[n];if(o.kind==="deletion"){const h=[];for(;n<i.length&&i[n].kind==="deletion";)h.push(i[n]),n+=1;const g=[];for(;n<i.length&&i[n].kind==="addition";)g.push(i[n]),n+=1;const x=Math.max(h.length,g.length);for(let a=0;a<x;a+=1){const p=h[a]??null,j=g[a]??null;s.push(Object.freeze({key:`${t.hunkId}:${p?.lineId??`-${a}`}:${j?.lineId??`-${a}`}`,left:p,right:j,changed:!0}))}continue}if(o.kind==="addition"){s.push(Object.freeze({key:`${t.hunkId}:${o.lineId}`,left:null,right:o,changed:!0})),n+=1;continue}s.push(Object.freeze({key:`${t.hunkId}:${o.lineId}`,left:o,right:o,changed:!1})),n+=1}return s}function ft(t,s,n){const i=new Set(s),o=[];for(const h of t){if(o.push(Object.freeze({kind:"hunk-header",hunk:h})),i.has(h.hunkId)){o.push(Object.freeze({kind:"folded",hunk:h}));continue}if(n==="side-by-side"){for(const g of ht(h))o.push(Object.freeze({kind:"side-by-side",hunk:h,row:g}));continue}for(const g of h.lines)o.push(Object.freeze({kind:"unified-line",hunk:h,line:g}))}return o}function ve(t){const s=[];for(const n of t){let i=!1;for(const o of n.lines){const h=o.kind==="addition"||o.kind==="deletion";h&&!i&&s.push(Object.freeze({lineId:o.lineId,hunkId:n.hunkId,oldLineNumber:o.oldLineNumber,newLineNumber:o.newLineNumber})),i=h}}return s}function mt(t,s,n=500){const i=s.trim().toLowerCase();if(!i)return[];const o=[];for(const h of t)for(const g of h.lines){if(o.length>=n)return o;g.text.toLowerCase().includes(i)&&o.push(Object.freeze({lineId:g.lineId,hunkId:h.hunkId,side:g.oldLineNumber!==null&&g.newLineNumber!==null?"both":g.oldLineNumber!==null?"old":"new"}))}return o}function pt(t){let s=0,n=0;for(const i of t)for(const o of i.lines)o.kind==="addition"?s+=1:o.kind==="deletion"&&(n+=1);return Object.freeze({additions:s,deletions:n,hunks:t.length})}function ce(t,s){return s?t.replace(/\t/gu,"→ ").replace(/ +$/gu,n=>"·".repeat(n.length)):t}function ge(t){return t==="addition"?"+":t==="deletion"?"-":t==="meta"?"\\":" "}function gt(t,s){const n={schemaVersion:2,type:"review_context",repositoryRevision:t.repositoryRevision,path:t.path,source:t.source,hunk:s.header,hunkId:s.hunkId,complete:s.complete},i=s.lines.map(o=>o.raw).join(`
2
2
  `).slice(0,12e3);return[`请审阅 ${t.path} 的这个 diff hunk,并指出正确性、安全性和测试风险:`,"","```review_context",JSON.stringify(n,null,2),"```","","```diff",i,"```"].join(`
3
3
  `)}function be({document:t,mode:s,wrap:n,showWhitespace:i,collapsedHunks:o,anchorLineId:h,loading:g=!1,stale:x=!1,onChangeMode:a,onToggleWrap:p,onToggleWhitespace:j,onToggleHunk:b,hunkAction:d=null,selectedLineIds:S=[],onToggleLine:u,ignoreWhitespace:_=!1,onToggleIgnoreWhitespace:L,wordDiff:v=!1,onToggleWordDiff:N,onSetAllFolded:Q,onAnchorChange:P,onNotice:B,onLoadMore:E,onSendToComposer:q}){const H=l.useRef(null),[k,R]=l.useState(!1),[$,r]=l.useState(""),[I,f]=l.useState(0),V=l.useMemo(()=>ft(t.hunks,o,s),[t.hunks,o,s]),c=l.useMemo(()=>ve(t.hunks),[t.hunks]),M=l.useMemo(()=>pt(t.hunks),[t.hunks]),G=l.useMemo(()=>k?mt(t.hunks,$):[],[t.hunks,k,$]);l.useEffect(()=>{!h||!H.current||H.current.querySelector(`[data-line-id="${CSS.escape(h)}"]`)?.scrollIntoView({block:"center"})},[h]),l.useEffect(()=>{f(0)},[$]);const K=l.useMemo(()=>h?c.findIndex(D=>D.lineId===h):-1,[c,h]),Y=D=>{if(c.length===0){B("这个文件没有改动。");return}const w=K<0?D>0?-1:0:K,A=Math.min(c.length-1,Math.max(0,w+D));P(c[A].lineId)},se=D=>{if(D.key==="F7"){D.preventDefault(),Y(D.shiftKey?-1:1);return}if(D.key==="Escape"){k&&(D.stopPropagation(),R(!1),r(""));return}if(D.key==="Enter"&&k&&G.length>0){D.preventDefault();const w=D.shiftKey?(I-1+G.length)%G.length:(I+1)%G.length;f(w),P(G[w].lineId)}};return t.kind==="binary"||t.kind==="symlink"||t.kind==="submodule"?e.jsxs("div",{className:"diff-viewer",children:[e.jsx(he,{doc:t,stats:M,stale:x}),e.jsxs("div",{className:"resource-empty compact",children:[e.jsx(T,{name:"code"}),e.jsx("strong",{children:Nt(t.kind)}),e.jsx("p",{children:"只展示变更事实,不返回可预览内容。"}),e.jsx("ul",{className:"diff-meta-list",children:t.meta.slice(0,8).map(D=>e.jsx("li",{children:e.jsx("code",{children:D})},D))})]})]}):t.kind==="metadata"?e.jsxs("div",{className:"diff-viewer",children:[e.jsx(he,{doc:t,stats:M,stale:x}),e.jsxs("div",{className:"resource-empty compact",children:[e.jsx(T,{name:"code"}),e.jsx("strong",{children:"仅有元数据变化"}),e.jsx("p",{children:"没有文本 Hunk,但文件确实变了。"}),e.jsx("ul",{className:"diff-meta-list",children:t.meta.slice(0,8).map(D=>e.jsx("li",{children:e.jsx("code",{children:D})},D))})]})]}):e.jsxs("div",{className:"diff-viewer",children:[e.jsx(he,{doc:t,stats:M,stale:x}),e.jsxs("div",{className:"diff-toolbar",role:"toolbar","aria-label":"Diff 显示选项",children:[e.jsxs("div",{className:"diff-mode-group",role:"group","aria-label":"Diff 布局",children:[e.jsx("button",{type:"button",className:"text-button","aria-pressed":s==="unified",onClick:()=>a("unified"),children:"统一"}),e.jsx("button",{type:"button",className:"text-button","aria-pressed":s==="side-by-side",onClick:()=>a("side-by-side"),children:"并排"})]}),e.jsx("button",{type:"button",className:"text-button","aria-pressed":n,onClick:p,children:"换行"}),e.jsx("button",{type:"button",className:"text-button","aria-pressed":i,onClick:j,children:"空白字符"}),N?e.jsx("button",{type:"button",className:`text-button ${v?"diff-toggle-on":""}`,"aria-pressed":v,title:"词级差异(重新读取 Diff)",onClick:N,children:"词级"}):null,L?e.jsx("button",{type:"button",className:`text-button ${_?"diff-toggle-on":""}`,"aria-pressed":_,title:"忽略空白差异(重新读取 Diff)",onClick:L,children:"忽略空白"}):null,e.jsx("button",{type:"button",className:"text-button",onClick:()=>Q(o.length===0),children:o.length===0?"折叠全部":"展开全部"}),e.jsx("button",{type:"button",className:"text-button",onClick:()=>Y(-1),disabled:c.length===0,"aria-label":"上一个改动",children:"↑改动"}),e.jsx("button",{type:"button",className:"text-button",onClick:()=>Y(1),disabled:c.length===0,"aria-label":"下一个改动",children:"↓改动"}),e.jsx("span",{className:"diff-anchor-count","aria-live":"polite",children:c.length===0?"无改动":`改动 ${Math.max(1,K+1)}/${c.length}`}),e.jsx("button",{type:"button",className:"text-button","aria-pressed":k,onClick:()=>R(D=>!D),children:"查找"})]}),k?e.jsxs("div",{className:"diff-find",children:[e.jsx("input",{type:"search",value:$,autoFocus:!0,"aria-label":"在已加载的 Diff 中查找",placeholder:"在已加载内容中查找",onChange:D=>r(D.target.value)}),e.jsxs("span",{"aria-live":"polite",children:[$.trim()?G.length===0?"无命中":`${I+1}/${G.length}`:"输入以查找",t.completeness!=="complete"?" · 仅已加载内容":""]})]}):null,t.completeness==="paged"?e.jsx("p",{className:"resource-notice",role:"status",children:"当前为分页预览,未加载的 Hunk 不能执行任何写入。"}):null,e.jsx("div",{className:`diff-body diff-body-${s} ${n?"diff-wrap":""}`,ref:H,tabIndex:0,role:"region","aria-label":`Diff ${t.path}`,onKeyDown:se,children:V.length===0?e.jsxs("div",{className:"resource-empty compact",children:[e.jsx(T,{name:"check"}),e.jsx("strong",{children:"没有文本改动"})]}):V.map(D=>e.jsx(bt,{row:D,mode:s,showWhitespace:i,folded:o.includes(kt(D).hunkId),activeAnchor:h,onToggleHunk:b,hunkAction:d,selectedLineIds:S,onToggleLine:u,wordDiff:v},yt(D)))}),e.jsxs("footer",{className:"diff-footer",children:[q?e.jsx("button",{type:"button",className:"secondary-button",disabled:t.hunks.length===0,onClick:()=>q(gt({path:t.path,source:t.source,repositoryRevision:t.repositoryRevision},t.hunks[Math.max(0,c.findIndex(D=>D.lineId===h))]??t.hunks[0])),children:"发送当前 Hunk 到对话"}):null,t.nextCursor&&E?e.jsx("button",{type:"button",className:"text-button",onClick:E,disabled:g,children:g?"加载中…":"加载更多 Diff"}):null,e.jsxs("span",{className:"diff-footer-hint",children:[t.capabilities.stageFile?"可暂存此文件":t.capabilities.unstageFile?"可取消暂存此文件":"只读",t.capabilities.reason?` · ${t.capabilities.reason}`:""]})]})]})}function he({doc:t,stats:s,stale:n}){return e.jsxs("header",{children:[e.jsx("strong",{title:t.path,children:t.path}),e.jsx("span",{className:"diff-source",children:vt(t.source)}),e.jsxs("span",{className:"diff-stat-add",children:["+",s.additions]}),e.jsxs("span",{className:"diff-stat-del",children:["-",s.deletions]}),e.jsxs("span",{children:[s.hunks," 个 Hunk"]}),n?e.jsx("span",{className:"diff-stale",role:"status",children:"已变化"}):null]})}function bt({row:t,mode:s,showWhitespace:n,folded:i,activeAnchor:o,onToggleHunk:h,hunkAction:g=null,selectedLineIds:x=[],onToggleLine:a,wordDiff:p=!1}){if(t.kind==="hunk-header")return e.jsxs("div",{className:"diff-hunk-header",children:[e.jsx("button",{type:"button",className:"diff-fold","aria-expanded":!i,"aria-label":i?"展开 Hunk":"折叠 Hunk",onClick:()=>h(t.hunk.hunkId),children:i?"▸":"▾"}),e.jsx("code",{children:t.hunk.header}),t.hunk.complete?null:e.jsx("em",{className:"diff-incomplete",children:"未完整加载"}),g&&t.hunk.complete?e.jsx("button",{type:"button",className:"text-button diff-hunk-action","aria-label":g.label,onClick:()=>g.run(t.hunk.hunkId),children:g.label}):null]});if(t.kind==="folded")return e.jsxs("button",{type:"button",className:"diff-folded-row",onClick:()=>h(t.hunk.hunkId),children:["已折叠 ",t.hunk.lines.length," 行 · 点击展开"]});if(t.kind==="side-by-side")return e.jsx(jt,{row:t.row,showWhitespace:n});const j=t.line;return e.jsxs("div",{className:`diff-line diff-line-${j.kind} ${o===j.lineId?"diff-line-anchor":""}`,"data-line-id":j.lineId,"data-side":j.oldLineNumber!==null&&j.newLineNumber!==null?"both":j.oldLineNumber!==null?"old":"new",children:[e.jsx("span",{className:"diff-gutter",children:j.oldLineNumber??""}),e.jsx("span",{className:"diff-gutter",children:j.newLineNumber??""}),a&&(j.kind==="addition"||j.kind==="deletion")?e.jsx("input",{type:"checkbox",className:"diff-line-select","aria-label":`选择第 ${j.newLineNumber??j.oldLineNumber??""} 行`,checked:x.includes(j.lineId),onChange:()=>a(j.lineId)}):null,e.jsx("span",{className:"diff-marker","aria-hidden":"true",children:ge(j.kind)}),e.jsx("span",{className:"diff-code",children:p?xt(ce(j.text,n)):ce(j.text,n)||" "}),null]})}function xt(t){if(!t)return" ";const s=[],n=/\[-([\s\S]*?)-\]|\{\+([\s\S]*?)\+\}/gu;let i=0,o,h=0;for(;(o=n.exec(t))!==null;)o.index>i&&s.push(t.slice(i,o.index)),o[1]!==void 0?s.push(e.jsx("em",{className:"diff-word-del",children:o[1]},h++)):s.push(e.jsx("em",{className:"diff-word-add",children:o[2]},h++)),i=o.index+o[0].length;return i<t.length&&s.push(t.slice(i)),s.length>0?s:" "}function jt({row:t,showWhitespace:s}){return e.jsxs("div",{className:`diff-sbs-row ${t.changed?"diff-sbs-changed":""}`,children:[e.jsxs("div",{className:`diff-sbs-side ${t.left?.kind==="deletion"?"diff-line-deletion":""}`,"data-line-id":t.left?.lineId??void 0,children:[e.jsx("span",{className:"diff-gutter",children:t.left?.oldLineNumber??""}),e.jsx("span",{className:"diff-marker","aria-hidden":"true",children:t.left?ge(t.left.kind):" "}),e.jsx("span",{className:"diff-code",children:t.left?ce(t.left.text,s)||" ":""})]}),e.jsxs("div",{className:`diff-sbs-side ${t.right?.kind==="addition"?"diff-line-addition":""}`,"data-line-id":t.right?.lineId??void 0,children:[e.jsx("span",{className:"diff-gutter",children:t.right?.newLineNumber??""}),e.jsx("span",{className:"diff-marker","aria-hidden":"true",children:t.right?ge(t.right.kind):" "}),e.jsx("span",{className:"diff-code",children:t.right?ce(t.right.text,s)||" ":""})]})]})}function yt(t){return t.kind==="hunk-header"?`h:${t.hunk.hunkId}`:t.kind==="folded"?`f:${t.hunk.hunkId}`:t.kind==="side-by-side"?t.row.key:t.line.lineId}function kt(t){return t.hunk}function Nt(t){return t==="binary"?"二进制差异":t==="symlink"?"符号链接变化":t==="submodule"?"Submodule 指针变化":"元数据变化"}function vt(t){return t==="staged"?"HEAD → 索引":t==="unstaged"?"索引 → 工作区":t==="untracked"?"空 → 未跟踪文件":"冲突版本"}const ye=Object.freeze({snapshot:"两端快照 A → B","merge-base":"共同祖先 → B"});function It({refs:t,actions:s,display:n,collapsedHunks:i,anchorLineId:o,onDisplayChange:h,onToggleHunk:g,onSetAllFolded:x,onAnchorChange:a,onNotice:p,onSendToComposer:j}){const b=l.useMemo(()=>St(t),[t]),d=b.find(f=>f.isBranch)?.value??b[0]?.value??"",S=t?.refs.find(f=>f.isHead)?.shortName??d,[u,_]=l.useState(d),[L,v]=l.useState(S),[N,Q]=l.useState("snapshot"),[P,B]=l.useState(null),[E,q]=l.useState(null),[H,k]=l.useState(!1),[R,$]=l.useState(""),r=()=>{!u||!L||H||(k(!0),$(""),(async()=>{try{const f=await s.gitCompare({baseRef:u,headRef:L,mode:N});B(f),q(null)}catch(f){$(ke(f))}finally{k(!1)}})())},I=f=>{!P||f.sensitive||H||(k(!0),$(""),(async()=>{try{const V=await s.gitCompareFileDiff({baseOid:P.baseOid,headOid:P.headOid,path:f.path});q(V)}catch(V){$(ke(V))}finally{k(!1)}})())};return b.length===0?e.jsxs("div",{className:"resource-empty",children:[e.jsx(T,{name:"branch",size:16}),e.jsx("strong",{children:"没有可比较的 ref"}),e.jsx("p",{children:"这个仓库还没有分支或标签。"})]}):e.jsxs("div",{className:"git-compare","aria-label":"分支与版本比较",children:[e.jsxs("div",{className:"git-compare-form",children:[e.jsxs("label",{children:[e.jsx("span",{children:"基准 A"}),e.jsx("select",{value:u,"aria-label":"选择基准 A",onChange:f=>_(f.target.value),children:b.map(f=>e.jsx("option",{value:f.value,children:f.label},f.value))})]}),e.jsxs("label",{children:[e.jsx("span",{children:"目标 B"}),e.jsx("select",{value:L,"aria-label":"选择目标 B",onChange:f=>v(f.target.value),children:b.map(f=>e.jsx("option",{value:f.value,children:f.label},f.value))})]}),e.jsxs("label",{children:[e.jsx("span",{children:"模式"}),e.jsx("select",{value:N,"aria-label":"选择比较模式",onChange:f=>Q(f.target.value),children:Object.keys(ye).map(f=>e.jsx("option",{value:f,children:ye[f]},f))})]}),e.jsx("button",{type:"button",className:"primary-button",disabled:H||u===L,"aria-busy":H,onClick:r,children:H?"比较中…":"比较"})]}),e.jsx("p",{className:"git-compare-hint",children:"修改选择不会立即发起查询;点「比较」或按 Enter 才执行。交换 A/B 后会取消旧的请求。"}),R?e.jsx("p",{className:"resource-error",role:"alert",children:R}):null,P?e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"git-compare-range",children:[P.baseLabel," ",e.jsx("code",{children:P.baseOid.slice(0,10)})," → ",P.headLabel," ",e.jsx("code",{children:P.headOid.slice(0,10)}),P.truncated?" · 文件列表已截断":""]}),e.jsxs("p",{className:"git-compare-range",children:[P.files.length," 个文件 ·",e.jsxs("em",{className:"diff-stat-add",children:[" +",P.additions]}),e.jsxs("em",{className:"diff-stat-del",children:[" -",P.deletions]}),e.jsx("button",{type:"button",className:"text-button",onClick:r,disabled:H,children:"重新比较"})]}),e.jsx("ul",{className:"git-compare-files",children:P.files.map(f=>e.jsx("li",{children:e.jsxs("button",{type:"button",className:E?.path===f.path?"selected":"","aria-current":E?.path===f.path?"true":void 0,disabled:f.sensitive,onClick:()=>I(f),children:[e.jsx("span",{className:"git-commit-file-stats",children:f.binary?"bin":`+${f.additions} -${f.deletions}`}),e.jsx("span",{title:f.path,children:f.renamedFrom?`${f.renamedFrom} → ${f.path}`:f.path}),f.sensitive?e.jsx("em",{className:"git-sensitive-badge",children:"受保护"}):null]})},`${f.renamedFrom??""}:${f.path}`))}),E?e.jsx(be,{document:E,mode:n.mode,wrap:n.wrap,showWhitespace:n.showWhitespace,collapsedHunks:i,anchorLineId:o,loading:H,onChangeMode:f=>h({mode:f}),onToggleWrap:()=>h({wrap:!n.wrap}),onToggleWhitespace:()=>h({showWhitespace:!n.showWhitespace}),onToggleHunk:g,onSetAllFolded:x,onAnchorChange:a,onNotice:p,onSendToComposer:j}):e.jsx("p",{className:"git-compare-hint",children:"点一个文件查看该比较下的 Diff。"})]}):null]})}function St(t){return t?t.refs.map(s=>Object.freeze({value:s.shortName,label:s.kind==="branch"?s.shortName:`${s.shortName}(${s.kind==="tag"?"tag":s.kind==="remote"?"远程":"其他"})`,isBranch:s.kind==="branch"})):[]}function ke(t){const s=t?.code;return s==="git_merge_base_multiple"?"这两个 ref 有多个共同祖先,没有唯一分叉点;请改用「两端快照」模式。":s==="git_merge_base_missing"?"两个 ref 没有共同祖先,无法用「共同祖先」模式;请改用「两端快照」模式。":s==="git_shallow_history"?"仓库缺少完成该比较所需的对象(浅克隆?)。":s==="git_ref_not_found"?"所选 ref 无法解析为提交。":t instanceof Error?t.message:"比较失败。"}const Ct=Object.freeze({"both-modified":"双方都修改","both-added":"双方都新增","added-by-us":"我们新增 · 对方删除","added-by-them":"对方新增 · 我们删除","deleted-by-us":"我们删除 · 对方修改","deleted-by-them":"对方删除 · 我们修改","both-deleted":"双方都删除",other:"其他冲突形态"}),wt=Object.freeze({base:"base(共同祖先)",ours:"ours(当前分支)",theirs:"theirs(合入分支)",worktree:"工作区文件",revision:"该版本"});function Ft({path:t,actions:s}){const[n,i]=l.useState(null),[o,h]=l.useState(""),[g,x]=l.useState(!0);if(l.useEffect(()=>{let p=!1;return x(!0),h(""),(async()=>{try{const j=await s.gitConflictVersions(t);p||i(j)}catch(j){p||(i(null),h(j instanceof Error?j.message:"冲突详情读取失败。"))}finally{p||x(!1)}})(),()=>{p=!0}},[s,t]),g)return e.jsx("p",{className:"resource-loading",children:"正在读取冲突版本…"});if(o)return e.jsx("p",{className:"resource-error",role:"alert",children:o});if(!n)return null;const a=[n.base,n.ours,n.theirs,n.worktree];return e.jsxs("section",{className:"git-conflict","aria-label":"冲突版本",children:[e.jsxs("header",{className:"git-conflict-header",children:[e.jsx(T,{name:"warning",size:14}),e.jsx("strong",{children:n.path}),e.jsx("em",{className:"git-merge-badge",children:Ct[n.shape]})]}),e.jsx("p",{className:"git-compare-hint",children:"直接读 index 的 stage 1/2/3,不用普通暂存 Diff 代替完整冲突视图。缺失的版本是这种冲突形态的正常结果。"}),e.jsx("div",{className:"git-conflict-grid",children:a.map(p=>e.jsxs("article",{className:"git-conflict-version",children:[e.jsxs("header",{children:[e.jsx("span",{children:wt[p.label]}),p.exists?e.jsx("code",{children:p.oid?.slice(0,10)}):e.jsx("em",{className:"git-conflict-absent",children:"此形态下不存在"})]}),p.exists?p.lfs?e.jsxs("p",{className:"git-conflict-note",children:["LFS 指针 · oid ",p.lfs.oid.slice(0,16),"…",p.lfs.size!==null?` · ${p.lfs.size} 字节(不下载对象)`:""]}):p.binary?e.jsxs("p",{className:"git-conflict-note",children:["二进制内容(",p.byteSize," 字节),不在此处渲染。"]}):p.truncated?e.jsxs("p",{className:"git-conflict-note",children:["超过上限(",p.byteSize," 字节),未读取内容。"]}):e.jsx("pre",{className:"git-conflict-content",children:p.content??""}):e.jsx("p",{className:"git-conflict-note",children:"没有这个版本。"})]},p.label))})]})}function Lt({history:t,actions:s,display:n,collapsedHunks:i,anchorLineId:o,onDisplayChange:h,onToggleHunk:g,onSetAllFolded:x,onAnchorChange:a,onNotice:p,onSendToComposer:j}){const{page:b,detail:d,files:S,diff:u,fileHistory:_,error:L}=t,[v,N]=l.useState(null),[Q,P]=l.useState(!1),[B,E]=l.useState(null),[q,H]=l.useState(!1),[k,R]=l.useState(null),$=l.useMemo(()=>(b?.items??[]).filter(r=>r.isMerge).length,[b]);return t.isEmptyRepository?e.jsxs("div",{className:"resource-empty",children:[e.jsx(T,{name:"branch",size:16}),e.jsx("strong",{children:"尚无提交"}),e.jsx("p",{children:"这个仓库还没有提交。新文件仍可暂存并完成首次提交。"})]}):e.jsxs("div",{className:"git-history","aria-label":"Git 历史",children:[e.jsxs("div",{className:"git-history-search",children:[e.jsx("input",{type:"search","aria-label":"搜索提交消息",placeholder:"搜索提交消息…",value:t.query.message,onChange:r=>t.setQuery({message:r.target.value})}),e.jsx("input",{type:"search","aria-label":"按作者筛选",placeholder:"作者",value:t.query.author,onChange:r=>t.setQuery({author:r.target.value})}),e.jsx("input",{type:"search","aria-label":"按文件路径筛选",placeholder:"文件路径",value:t.query.path,onChange:r=>t.setQuery({path:r.target.value})}),e.jsx("input",{type:"search","aria-label":"按提交哈希查找",placeholder:"提交哈希",value:t.query.sha,onChange:r=>t.setQuery({sha:r.target.value})}),e.jsxs("div",{className:"git-history-dates",children:[e.jsx("input",{type:"search","aria-label":"起始日期",placeholder:"自 (2026-01-01)",value:t.query.since,onChange:r=>t.setQuery({since:r.target.value})}),e.jsx("input",{type:"search","aria-label":"结束日期",placeholder:"至",value:t.query.until,onChange:r=>t.setQuery({until:r.target.value})})]}),e.jsxs("div",{className:"git-history-search-actions",children:[e.jsxs("span",{role:"status",children:[b?`已载 ${b.items.length}${b.truncated?"+":""} 个提交${$>0?` · 含 ${$} 个合并`:""}`:"读取中…",t.refs?.detached?" · detached HEAD":""]}),e.jsx("button",{type:"button",className:`text-button ${B?"diff-toggle-on":""}`,"aria-pressed":B!==null,onClick:()=>{if(B){E(null);return}H(!0),s.gitGraph().then(E).finally(()=>H(!1))},children:"拓扑"}),e.jsx("button",{type:"button",className:"text-button",onClick:t.resetQuery,children:"清除筛选"})]})]}),L?e.jsx("p",{className:"resource-error",role:"alert",children:L}):null,_?e.jsxs("section",{className:"git-file-history","aria-label":"文件历史",children:[e.jsxs("header",{children:[e.jsxs("strong",{children:["文件历史 · ",_.path]}),e.jsx("button",{type:"button",className:"text-button",onClick:t.closeFileHistory,children:"返回提交列表"})]}),e.jsx("p",{className:"git-file-history-note",children:"跟随重命名;复制与复杂合并场景的追踪可能不完整。"}),e.jsx("ul",{children:_.items.map(r=>e.jsx("li",{children:e.jsxs("button",{type:"button",onClick:()=>{t.closeFileHistory(),t.selectCommit(r)},children:[e.jsx("code",{children:r.shortId}),e.jsx("span",{children:r.subject}),e.jsx("time",{dateTime:r.authoredAt,children:fe(r.authoredAt)})]})},r.id))}),_.truncated?e.jsx("p",{className:"git-file-history-note",children:"结果已截断,仅显示最近的提交。"}):null]}):null,d?e.jsxs("section",{className:"git-commit-detail","aria-label":"提交详情",children:[e.jsxs("header",{children:[e.jsxs("div",{children:[e.jsx("code",{children:d.shortId}),d.isMerge?e.jsxs("span",{className:"git-merge-badge",children:["合并提交 · ",d.parents.length," 个父提交"]}):d.parents.length===0?e.jsx("span",{className:"git-root-badge",children:"根提交"}):null]}),e.jsx("button",{type:"button",className:"text-button",onClick:t.closeDetail,children:"关闭详情"})]}),e.jsx("p",{className:"git-commit-subject",children:d.subject}),d.message.trim()!==d.subject.trim()?e.jsx("pre",{className:"git-commit-message",children:d.message.trim()}):null,e.jsxs("p",{className:"git-commit-meta",children:[d.authorName," <",d.authorEmail,"> · ",fe(d.authoredAt),d.committerName&&d.committerName!==d.authorName?` · 提交者 ${d.committerName}`:""]}),e.jsxs("p",{className:"git-commit-base",children:["比较基准:",d.baseLabel," ",e.jsx("code",{children:d.baseOid.slice(0,10)})]}),d.isMerge?e.jsx("div",{className:"git-parent-picker",role:"group","aria-label":"选择父提交",children:d.parents.map((r,I)=>e.jsxs("button",{type:"button","aria-pressed":d.parentIndex===I,className:d.parentIndex===I?"selected":"",onClick:()=>t.setParentIndex(I),children:["父 ",I+1," ",e.jsx("code",{children:r.slice(0,8)})]},r))}):null,S?e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"git-commit-stats-line",children:[S.files.length," 个文件 ·",e.jsxs("em",{className:"diff-stat-add",children:[" +",S.additions]}),e.jsxs("em",{className:"diff-stat-del",children:[" -",S.deletions]}),S.truncated?" · 已截断":""]}),e.jsx("ul",{className:"git-commit-file-list",children:S.files.map(r=>e.jsxs("li",{children:[e.jsxs("button",{type:"button",className:d&&t.diff?.path===r.path?"selected":"","aria-current":t.diff?.path===r.path?"true":void 0,onClick:()=>t.selectFile(r.path),children:[e.jsx("span",{className:"git-commit-file-stats",children:r.binary?"bin":`+${r.additions} -${r.deletions}`}),e.jsx("span",{title:r.path,children:r.renamedFrom?`${r.renamedFrom} → ${r.path}`:r.path}),r.sensitive?e.jsx("em",{className:"git-sensitive-badge",children:"受保护"}):null]}),e.jsx("button",{type:"button",className:"text-button","aria-label":`查看 ${r.path} 的文件历史`,onClick:()=>t.openFileHistory(r.path),children:"历史"}),e.jsx("button",{type:"button",className:"text-button","aria-label":`查看 ${r.path} 在该提交的版本`,onClick:()=>{d&&s.gitBlob({path:r.path,rev:d.id}).then(I=>R({path:I.path,rev:I.rev,lines:I.content,binary:I.binary,truncated:I.truncated,byteSize:I.byteSize,dataUrl:I.dataUrl})).catch(()=>R(null))},children:"该版本"}),e.jsx("button",{type:"button",className:"text-button","aria-label":`查看 ${r.path} 的 Blame`,onClick:()=>{d&&(P(!0),s.gitBlame({path:r.path,rev:d.id}).then(I=>N({...I,rev:d.id})).catch(()=>N(null)).finally(()=>P(!1)))},children:"Blame"})]},r.path))})]}):e.jsx("p",{className:"resource-loading",children:"正在读取该提交的改动…"})]}):null,u?e.jsx(be,{document:u,mode:n.mode,wrap:n.wrap,showWhitespace:n.showWhitespace,collapsedHunks:i,anchorLineId:o,loading:t.loadingDetail,onChangeMode:r=>h({mode:r}),onToggleWrap:()=>h({wrap:!n.wrap}),onToggleWhitespace:()=>h({showWhitespace:!n.showWhitespace}),onToggleHunk:g,onSetAllFolded:x,onAnchorChange:a,onNotice:p,onSendToComposer:j}):null,q?e.jsx("p",{className:"git-file-history-note",children:"正在读取拓扑…"}):null,B?e.jsxs("section",{className:"git-graph","aria-label":"提交拓扑",children:[e.jsxs("header",{children:[e.jsxs("strong",{children:["拓扑(",B.rows.length,B.truncated?"+":""," 行)"]}),e.jsx("button",{type:"button",className:"text-button",onClick:()=>E(null),children:"关闭"})]}),e.jsx("p",{className:"git-file-history-note",children:"图形列由 git 直接绘制,不由前端重算。"}),e.jsx("div",{className:"git-graph-body",children:B.rows.map((r,I)=>e.jsxs("button",{type:"button",className:r.id&&d?.id===r.id?"selected":"",disabled:!r.id,onClick:()=>{r.id&&(E(null),t.selectCommit({id:r.id}))},children:[e.jsx("code",{children:r.graph}),e.jsx("span",{children:r.id?r.subject:""})]},`${r.id??"graph"}:${I}`))})]}):null,k?e.jsxs("section",{className:"git-blob","aria-label":"该版本内容",children:[e.jsxs("header",{children:[e.jsxs("strong",{children:[k.path," @ ",k.rev.slice(0,10)]}),e.jsx("button",{type:"button",className:"text-button",onClick:()=>R(null),children:"关闭"})]}),k.truncated?e.jsxs("p",{className:"git-file-history-note",children:["文件超过上限(",k.byteSize," 字节),未读取内容。"]}):k.dataUrl?e.jsx("img",{src:k.dataUrl,alt:`${k.path} 在该提交的图像版本`,className:"git-blob-image"}):k.binary?e.jsxs("p",{className:"git-file-history-note",children:["二进制内容(",k.byteSize," 字节),不在此处渲染。"]}):e.jsx("pre",{className:"git-blob-content",children:k.lines.join(`
4
4
  `)})]}):null,v?e.jsxs("section",{className:"git-blame","aria-label":"Blame",children:[e.jsxs("header",{children:[e.jsxs("strong",{children:["Blame · ",v.path]}),e.jsx("button",{type:"button",className:"text-button",onClick:()=>N(null),children:"关闭"})]}),Q?e.jsx("p",{className:"git-file-history-note",children:"读取中…"}):null,e.jsx("div",{className:"git-blame-table",children:v.lines.map(r=>e.jsxs("div",{className:"git-blame-row",children:[e.jsx("code",{children:r.commitShort}),e.jsx("span",{className:"git-blame-author",title:r.summary,children:r.author}),e.jsx("time",{children:r.authoredAt.slice(0,10)}),e.jsx("span",{className:"git-blame-summary",title:r.summary,children:r.summary})]},r.lineNumber))}),v.truncated?e.jsx("p",{className:"git-file-history-note",children:"结果已截断。"}):null]}):null,e.jsx("ul",{className:"git-history-list",children:(b?.items??[]).map(r=>e.jsx("li",{children:e.jsxs("button",{type:"button",className:d?.id===r.id?"selected":"","aria-current":d?.id===r.id?"true":void 0,onClick:()=>t.selectCommit(r),children:[e.jsx("code",{children:r.shortId}),e.jsx("span",{title:r.subject,children:r.subject}),r.isMerge?e.jsx("em",{className:"git-merge-badge-inline",children:"合并"}):null,r.decoration.length>0?e.jsx("em",{className:"git-ref-badge",title:r.decoration.join(", "),children:r.decoration[0]}):null,e.jsx("time",{dateTime:r.authoredAt,children:fe(r.authoredAt)})]})},r.id))}),b&&b.items.length===0&&!t.loading?e.jsxs("div",{className:"resource-empty compact",children:[e.jsx(T,{name:"search",size:16}),e.jsx("strong",{children:"没有匹配的提交"}),e.jsx("p",{children:"筛选在 Host 上对整个可达历史执行,不只是当前页。"})]}):null,b?.nextCursor?e.jsx("button",{type:"button",className:"text-button resource-load-more",onClick:t.loadMore,disabled:t.loadingMore,children:t.loadingMore?"加载中…":"加载更多提交"}):null]})}function fe(t){const s=new Date(t);return Number.isNaN(s.getTime())?t:s.toLocaleDateString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit"})}const Dt={changes:"变更",history:"历史",compare:"比较"},Ie={conflict:"冲突",unstaged:"未暂存",staged:"已暂存",untracked:"未跟踪"},Se=["conflict","unstaged","staged","untracked"];function Et(t,s){return s==="conflict"?t.conflicted:t[s]}function _t({workspaceId:t,refreshEpoch:s,actions:n,onSendToComposer:i,onRevealInFiles:o,navigatorWidthPx:h,onNavigatorWidthCommit:g,store:x}){const a=ct({workspaceId:t,refreshEpoch:s,actions:n,store:x}),{notice:p,showNotice:j,clearNotice:b}=Oe(),{status:d,diff:S,session:u}=a,_=()=>{if(!u.selectedFileId||u.selectedLineIds.length===0)return;const c=u.selectedFileId,M=u.selectedLineIds;a.applyPatch({fileId:c,lineIds:M}),a.setSession({selectedLineIds:[]})},L=l.useRef(null),v=l.useCallback(c=>{if(L.current?.disconnect(),L.current=null,!c)return;const M=new ResizeObserver(G=>{for(const K of G)Q(K.contentRect.width)});M.observe(c),L.current=M,Q(c.getBoundingClientRect().width)},[]),[N,Q]=l.useState(0);l.useEffect(()=>()=>L.current?.disconnect(),[]);const P=Ue(N,a.display.mode),B=P.narrow,E=P.effectiveMode,[q,H]=l.useState(!1),k=l.useMemo(()=>{const c=a.selectedEntry;if(!o||!c||u.view!=="changes")return null;const M=c.fileId;return()=>{n.gitFilesTarget(M).then(G=>o({path:G.path,filesToken:G.filesToken})).catch(()=>j("该文件无法在 Files 中打开。"))}},[n,a.selectedEntry,o,u.view,j]),R=l.useMemo(()=>{if(u.view!=="changes"||!u.selectedFileId||!S)return null;const c=u.selectedFileId;return S.source!=="staged"&&S.source!=="unstaged"&&S.source!=="untracked"?null:{label:S.source==="staged"?"取消暂存此 Hunk":"暂存此 Hunk",run:G=>{a.applyPatch({fileId:c,hunkIds:[G]})}}},[S,a,u.selectedFileId,u.view]),$=Xe({enabled:(u.view==="history"||u.view==="compare")&&!!t,session:u,setSession:a.setSession,actions:n,refreshEpoch:s}),r=l.useMemo(()=>d?Se.map(c=>({source:c,label:Ie[c],count:Et(d.counts,c),items:ot(d,c)})):[],[d]),I=l.useMemo(()=>u.group?r.filter(c=>c.source===u.group):r,[r,u.group]),f=l.useMemo(()=>I.flatMap(c=>c.items.map(M=>M.fileId)),[I]),V=l.useMemo(()=>S?ve(S.hunks).map(c=>c.lineId):[],[S]);return Ze({enabled:u.view==="changes",session:u,setSession:a.setSession,fileIds:f,anchorLineIds:V,onOpenSelection:()=>{const c=a.selectedEntry;c&&a.openFile(c)},onEscapeFallback:()=>{}}),a.error&&!d?e.jsxs("div",{className:"resource-empty",role:"alert",children:[e.jsx(T,{name:"warning"}),e.jsx("strong",{children:"Git 状态读取失败"}),e.jsx("p",{children:a.error}),e.jsx("button",{type:"button",className:"secondary-button",onClick:a.reload,children:"重试"})]}):a.loading&&!d?e.jsx("p",{className:"resource-loading",children:"正在读取 Git 状态…"}):d&&d.repositoryKind==="bare"?e.jsxs("div",{className:"resource-empty",children:[e.jsx(T,{name:"branch",size:16}),e.jsx("strong",{children:"当前项目是裸仓库"}),e.jsx("p",{children:"裸仓库没有工作区,工作栏没有可显示的变更或 Diff。文件和 Agent 不受影响。"})]}):d&&!d.isRepository?e.jsxs("div",{className:"resource-empty",children:[e.jsx(T,{name:"branch",size:16}),e.jsx("strong",{children:"当前项目不是 Git 仓库"}),e.jsx("p",{children:"文件和 Agent 不受影响。"})]}):e.jsxs("div",{ref:v,"data-width":P.dataWidth,"data-narrow-view":B&&q&&u.selectedFileId?"detail":"list",className:"work-resource-panel git-panel",children:[e.jsxs("div",{className:"git-summary",children:[e.jsxs("div",{children:[e.jsx(T,{name:"branch",size:16}),e.jsx("strong",{children:d?.detached?`detached ${d.head??""}`:d?.branch||"HEAD"})]}),e.jsxs("span",{children:[d?.upstream||"无 upstream",d&&(d.ahead||d.behind)?` · ↑${d.ahead} ↓${d.behind}`:""]}),e.jsx("button",{type:"button",className:"icon-button","aria-label":"刷新 Git 状态","aria-busy":a.refreshing,onClick:()=>{b(),a.reload()},disabled:a.refreshing,children:e.jsx(T,{name:"refresh",size:16})})]}),e.jsxs("div",{className:"git-views",role:"tablist","aria-label":"Git 视图",children:[_e.map(c=>e.jsxs("button",{type:"button",role:"tab","aria-selected":u.view===c,className:u.view===c?"selected":"",onClick:()=>a.setSession({view:c}),children:[Dt[c],c==="changes"&&d&&d.counts.total>0?e.jsx("span",{className:"git-view-count",children:d.counts.total}):null]},c)),a.refreshing?e.jsx("span",{className:"git-refreshing",children:"更新中…"}):null]}),p?e.jsx("p",{className:"resource-notice",role:"status",children:p.text}):null,u.notice?e.jsx("p",{className:"resource-notice",role:"status",children:u.notice}):null,a.error?e.jsx("p",{className:"resource-error",role:"alert",children:a.error}):null,e.jsxs(Me,{panelId:"git",navigatorWidthPx:h,onNavigatorWidthCommit:g,contentLabel:"Git 内容",navigatorLabel:"Git 导航",handleLabel:"调整 Git 导航宽度",contentClassName:"git-content",navigatorClassName:"git-changes",children:[e.jsxs(e.Fragment,{children:[B&&u.selectedFileId?e.jsx("button",{type:"button",className:"git-back-to-list",onClick:()=>H(!1),children:"← 返回文件列表"}):null,u.view==="changes"?e.jsx($t,{groups:I,activeGroup:u.group,query:u.query,total:d?.counts.total??0,clean:d?.clean??!1,busy:a.busy,selectedFileIds:u.selectedFileIds,onQueryChange:c=>a.setSession({query:c,selectedFileId:null}),onGroupChange:c=>a.setSession({group:c,selectedFileId:null}),selectedFileId:u.selectedFileId,onSelect:c=>{a.setSession({selectedLineIds:[]}),H(!0),a.openFile(c)},onToggleSelection:a.toggleSelection,onClearSelection:a.clearSelection,onStage:c=>{a.stagePaths(c)},onUnstage:c=>{a.unstagePaths(c)}}):null,u.view==="history"?e.jsx("div",{className:"git-history-nav",children:e.jsx("p",{className:"git-history-nav-note",children:"提交列表与详情显示在右侧。"})}):null,u.view==="compare"?e.jsx(It,{refs:$.refs,actions:n,display:a.display,collapsedHunks:u.collapsedHunks,anchorLineId:u.anchorLineId,onDisplayChange:c=>a.setDisplay(c),onToggleHunk:c=>a.setSession({collapsedHunks:u.collapsedHunks.includes(c)?u.collapsedHunks.filter(M=>M!==c):[...u.collapsedHunks,c]}),onSetAllFolded:c=>a.setSession({collapsedHunks:c?u.collapsedHunks:[]}),onAnchorChange:c=>a.setSession({anchorLineId:c}),onNotice:j,onSendToComposer:i}):null]}),e.jsxs(e.Fragment,{children:[u.view==="changes"?a.selectedEntry?.source==="conflict"?e.jsx(Ft,{path:a.selectedEntry.path,actions:n}):S?e.jsxs("div",{children:[k?e.jsx("div",{className:"git-reveal-row",children:e.jsx("button",{type:"button",className:"text-button",onClick:k,children:"在 Files 打开"})}):null,u.selectedLineIds.length>0?e.jsxs("div",{className:"git-line-actions",role:"group","aria-label":"选中的行",children:[e.jsxs("span",{children:["已选 ",u.selectedLineIds.length," 行"]}),e.jsx("button",{type:"button",className:"secondary-button",disabled:a.busy,onClick:_,children:"暂存选中行"}),e.jsx("button",{type:"button",className:"text-button",onClick:()=>a.setSession({selectedLineIds:[]}),children:"清除"})]}):null,e.jsx(be,{hunkAction:R,ignoreWhitespace:a.display.ignoreWhitespace,onToggleIgnoreWhitespace:()=>a.setDisplay({ignoreWhitespace:!a.display.ignoreWhitespace}),wordDiff:a.display.wordDiff,onToggleWordDiff:()=>a.setDisplay({wordDiff:!a.display.wordDiff}),selectedLineIds:u.selectedLineIds,onToggleLine:c=>a.setSession({selectedLineIds:u.selectedLineIds.includes(c)?u.selectedLineIds.filter(M=>M!==c):[...u.selectedLineIds,c]}),document:S,mode:E,wrap:a.display.wrap,showWhitespace:a.display.showWhitespace,collapsedHunks:u.collapsedHunks,anchorLineId:u.anchorLineId,loading:a.loading,stale:a.stale,onChangeMode:c=>a.setDisplay({mode:c}),onToggleWrap:()=>a.setDisplay({wrap:!a.display.wrap}),onToggleWhitespace:()=>a.setDisplay({showWhitespace:!a.display.showWhitespace}),onToggleHunk:c=>a.setSession({collapsedHunks:u.collapsedHunks.includes(c)?u.collapsedHunks.filter(M=>M!==c):[...u.collapsedHunks,c]}),onSetAllFolded:c=>a.setSession({collapsedHunks:c?S.hunks.map(M=>M.hunkId):[]}),onAnchorChange:c=>a.setSession({anchorLineId:c}),onNotice:j,onLoadMore:S.nextCursor?a.loadMoreDiff:void 0,onSendToComposer:i})]}):e.jsxs("div",{className:"resource-empty",children:[e.jsx(T,{name:"code",size:16}),e.jsx("strong",{children:"选择变更查看 Diff"}),e.jsx("p",{children:"同一文件的「未暂存」和「已暂存」是两个不同的比较目标。"})]}):null,u.view==="changes"?e.jsx(Rt,{preview:a.commitPreview,draft:u.commitDraft,busy:a.busy,onDraftChange:c=>a.setSession({commitDraft:c}),onCommit:c=>a.commit(c)}):null,u.view==="history"?e.jsx(Lt,{history:$,actions:n,display:a.display,collapsedHunks:u.collapsedHunks,anchorLineId:u.anchorLineId,onDisplayChange:c=>a.setDisplay(c),onToggleHunk:c=>a.setSession({collapsedHunks:u.collapsedHunks.includes(c)?u.collapsedHunks.filter(M=>M!==c):[...u.collapsedHunks,c]}),onSetAllFolded:c=>a.setSession({collapsedHunks:c?u.collapsedHunks:[]}),onAnchorChange:c=>a.setSession({anchorLineId:c}),onNotice:j,onSendToComposer:i}):null,u.view==="compare"?e.jsx(Pt,{title:"比较结果",stage:"S5"}):null]})]})]})}function Rt({preview:t,draft:s,busy:n,onDraftChange:i,onCommit:o}){const[h,g]=l.useState(!1),[x,a]=l.useState(""),p=t?.blockedReason??"正在读取暂存区…",j=!!t?.canCommit&&s.summary.trim().length>0&&!n,b=()=>{a(""),o({summary:s.summary,...s.body.trim()?{body:s.body}:{}}).catch(d=>a(d instanceof Error?d.message:"提交失败。"))};return e.jsxs("section",{className:"git-commit","aria-label":"提交",children:[e.jsxs("button",{type:"button",className:"git-commit-toggle","aria-expanded":h,onClick:()=>g(d=>!d),children:[h?"▾":"▸"," 提交 ",t?`${t.filesChanged} 个文件`:"",t&&(t.additions>0||t.deletions>0)?e.jsxs("span",{className:"git-commit-stats",children:[e.jsxs("em",{className:"diff-stat-add",children:["+",t.additions]})," ",e.jsxs("em",{className:"diff-stat-del",children:["-",t.deletions]})]}):null]}),h?e.jsxs("div",{className:"git-commit-body",children:[t?e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"git-commit-meta",children:[t.detached?"detached HEAD":t.branch||"HEAD"," ·"," ",t.identity.name??"未配置 user.name"," <",t.identity.email??"未配置 user.email",">",t.identity.signingEnabled?" · 已启用签名":" · 未启用签名",` · hooks ${t.identity.hooksPresent?"存在":"不存在"}`]}),e.jsxs("ul",{className:"git-commit-files",children:[t.entries.slice(0,40).map(d=>e.jsxs("li",{children:[e.jsx("code",{children:d.status}),e.jsx("span",{children:d.path})]},`${d.source}:${d.path}`)),t.entries.length>40?e.jsxs("li",{className:"git-commit-more",children:["…还有 ",t.entries.length-40," 个文件"]}):null]})]}):null,e.jsxs("label",{children:[e.jsx("span",{children:"摘要"}),e.jsx("input",{type:"text",value:s.summary,maxLength:2e3,disabled:n,placeholder:"本次提交做了什么",onChange:d=>i({...s,summary:d.target.value})})]}),e.jsxs("label",{children:[e.jsx("span",{children:"正文(可选)"}),e.jsx("textarea",{value:s.body,rows:3,disabled:n,placeholder:"为什么这样做",onChange:d=>i({...s,body:d.target.value})})]}),x?e.jsx("p",{className:"resource-error",role:"alert",children:x}):null,e.jsxs("div",{className:"git-commit-actions",children:[e.jsx("button",{type:"button",className:"primary-button",disabled:!j,"aria-busy":n,onClick:b,children:n?"提交中…":"提交到本地索引"}),t?.canCommit?null:e.jsx("span",{className:"git-commit-blocked",children:p})]}),e.jsx("p",{className:"git-commit-note",children:"只提交本地 index:不自动暂存、不 amend、不 push。"})]}):null]})}function $t({groups:t,activeGroup:s,query:n,total:i,clean:o,busy:h,selectedFileIds:g,onQueryChange:x,onGroupChange:a,selectedFileId:p,onSelect:j,onToggleSelection:b,onClearSelection:d,onStage:S,onUnstage:u}){const _=new Set(g),L=g.length>0;return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"git-filter",children:[e.jsx("input",{type:"search",value:n,"aria-label":"搜索文件路径",placeholder:"搜索文件…",onChange:v=>x(v.target.value)}),e.jsxs("div",{className:"git-filter-groups",role:"group","aria-label":"按分组筛选",children:[e.jsx("button",{type:"button","aria-pressed":s===null,onClick:()=>a(null),children:"全部"}),Se.map(v=>e.jsx("button",{type:"button","aria-pressed":s===v,onClick:()=>a(s===v?null:v),children:Ie[v]},v))]}),e.jsx("p",{className:"git-filter-summary",role:"status",children:i===0?n?"没有匹配的改动":"没有改动":`匹配 ${i} 个改动`}),L?e.jsxs("div",{className:"git-bulk",role:"group","aria-label":"对选中文件操作",children:[e.jsxs("span",{children:["已选 ",g.length," 个文件"]}),e.jsx("button",{type:"button",className:"secondary-button",disabled:h,onClick:()=>S(g),children:"暂存选中"}),e.jsx("button",{type:"button",className:"secondary-button",disabled:h,onClick:()=>u(g),children:"取消暂存选中"}),e.jsx("button",{type:"button",className:"text-button",onClick:d,children:"清除"})]}):null]}),o?e.jsxs("div",{className:"resource-empty compact",children:[e.jsx(T,{name:"check"}),e.jsx("strong",{children:"工作区干净"})]}):t.map(v=>v.count?e.jsxs("div",{className:"git-group",children:[e.jsxs("h3",{children:[v.label," ",e.jsx("span",{children:v.count}),v.items.length<v.count?e.jsxs("small",{className:"git-group-loaded",children:["已载 ",v.items.length]}):null,v.source==="unstaged"||v.source==="untracked"?e.jsx("button",{type:"button",className:"text-button git-group-action",disabled:h,onClick:()=>S(v.items.map(N=>N.fileId)),children:"暂存该组已载"}):null,v.source==="staged"?e.jsx("button",{type:"button",className:"text-button git-group-action",disabled:h,onClick:()=>u(v.items.map(N=>N.fileId)),children:"取消暂存该组已载"}):null]}),v.items.map(N=>e.jsxs("div",{className:`git-row ${p===N.fileId?"selected":""}`,children:[e.jsx("input",{type:"checkbox","aria-label":`选择 ${N.path}`,checked:_.has(N.fileId),onChange:()=>b(N.fileId)}),e.jsxs("button",{type:"button",className:p===N.fileId?"selected":"","aria-current":p===N.fileId?"true":void 0,onClick:()=>j(N),children:[e.jsx("span",{className:`git-status-code ${v.source}`,children:N.indexStatus.trim()||N.worktreeStatus.trim()||"?"}),e.jsx("span",{title:N.path,children:N.renamedFrom?`${N.renamedFrom} → ${N.path}`:N.path})]}),v.source==="unstaged"||v.source==="untracked"?e.jsx("button",{type:"button",className:"text-button",disabled:h,"aria-label":`暂存 ${N.path}`,onClick:()=>S([N.fileId]),children:"暂存"}):null,v.source==="staged"?e.jsx("button",{type:"button",className:"text-button",disabled:h,"aria-label":`取消暂存 ${N.path}`,onClick:()=>u([N.fileId]),children:"取消"}):null,v.source==="conflict"?e.jsx("span",{className:"git-conflict-hint",children:"需在 Files 处理"}):null]},N.fileId))]},v.source):null)]})}function Pt({title:t,stage:s}){return e.jsxs("div",{className:"resource-empty",children:[e.jsx(T,{name:"info",size:16}),e.jsx("strong",{children:t}),e.jsxs("p",{children:["计划阶段 ",s," 交付,当前版本尚未实现。"]})]})}export{_t as GitPanel};