@surething/cockpit 1.0.265 → 1.0.266

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 (57) hide show
  1. package/.next-prod/BUILD_ID +1 -1
  2. package/.next-prod/app-path-routes-manifest.json +3 -3
  3. package/.next-prod/build-manifest.json +2 -2
  4. package/.next-prod/cockpit-build.json +1 -1
  5. package/.next-prod/prerender-manifest.json +4 -4
  6. package/.next-prod/server/app/_global-error/page_client-reference-manifest.js +1 -1
  7. package/.next-prod/server/app/_global-error.html +1 -1
  8. package/.next-prod/server/app/_global-error.rsc +1 -1
  9. package/.next-prod/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/.next-prod/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  11. package/.next-prod/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  12. package/.next-prod/server/app/_not-found/page_client-reference-manifest.js +1 -1
  13. package/.next-prod/server/app/_not-found.html +2 -2
  14. package/.next-prod/server/app/_not-found.rsc +3 -3
  15. package/.next-prod/server/app/_not-found.segments/_full.segment.rsc +3 -3
  16. package/.next-prod/server/app/_not-found.segments/_index.segment.rsc +3 -3
  17. package/.next-prod/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  18. package/.next-prod/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  19. package/.next-prod/server/app/m/page.js +1 -1
  20. package/.next-prod/server/app/m/page_client-reference-manifest.js +1 -1
  21. package/.next-prod/server/app/page_client-reference-manifest.js +1 -1
  22. package/.next-prod/server/app/project/page_client-reference-manifest.js +1 -1
  23. package/.next-prod/server/app/review/[id]/page_client-reference-manifest.js +1 -1
  24. package/.next-prod/server/app-paths-manifest.json +3 -3
  25. package/.next-prod/server/chunks/5750.js +11 -11
  26. package/.next-prod/server/chunks/6548.js +1 -1
  27. package/.next-prod/server/middleware-build-manifest.js +1 -1
  28. package/.next-prod/server/pages/404.html +2 -2
  29. package/.next-prod/server/pages/500.html +1 -1
  30. package/.next-prod/server/server-reference-manifest.json +1 -1
  31. package/.next-prod/static/chunks/33940-9631b513c48757f4.js +35 -0
  32. package/.next-prod/static/chunks/46784-031e2d50dc5f9fba.js +716 -0
  33. package/.next-prod/static/chunks/{14333-ced10f36441c568c.js → 5504-583edbefcb22ed17.js} +7 -7
  34. package/.next-prod/static/chunks/{86160-b6431f3093820d49.js → 56819-56e9c6ff8d86d236.js} +1 -1
  35. package/.next-prod/static/chunks/72353-f1aaa693ddc49568.js +15 -0
  36. package/.next-prod/static/chunks/app/{layout-2e2ffdc76c7f77f6.js → layout-60f41d682cd860e9.js} +1 -1
  37. package/.next-prod/static/chunks/app/m/page-7eabf179a8b13f49.js +1 -0
  38. package/.next-prod/static/chunks/app/{page-8b3591aba80eac74.js → page-e83cd7365efbf878.js} +1 -1
  39. package/.next-prod/static/chunks/app/project/{page-8b3591aba80eac74.js → page-e83cd7365efbf878.js} +1 -1
  40. package/.next-prod/static/css/45835d91c2519c62.css +1 -0
  41. package/.next-prod/trace +14 -14
  42. package/.next-prod/trace-build +1 -1
  43. package/apps/file-viewer/app.jsx +83 -8
  44. package/apps/file-viewer/index.html +23 -1
  45. package/dist/scheduledTasks.mjs +38 -12
  46. package/dist/wsServer.mjs +12 -2
  47. package/package.json +1 -1
  48. package/public/html-lib/csv-viewer.css +416 -0
  49. package/public/html-lib/csv-viewer.js +100 -0
  50. package/public/html-lib/json-viewer.js +14 -14
  51. package/.next-prod/static/chunks/21372-8169ef641d8dec08.js +0 -15
  52. package/.next-prod/static/chunks/33940-eab092c09e660ac7.js +0 -35
  53. package/.next-prod/static/chunks/46784-55eed87a21c4c989.js +0 -716
  54. package/.next-prod/static/chunks/app/m/page-25cd9633a00ed40d.js +0 -1
  55. package/.next-prod/static/css/50c1581bbbec6990.css +0 -1
  56. /package/.next-prod/static/{kwmbFJqrsOBSPJpMWySD2 → YOIsQRqVhYPuRyXlhwhoY}/_buildManifest.js +0 -0
  57. /package/.next-prod/static/{kwmbFJqrsOBSPJpMWySD2 → YOIsQRqVhYPuRyXlhwhoY}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- [{"name":"run-webpack","duration":15159124,"timestamp":161806964,"id":14,"parentId":1,"tags":{},"startTime":1787048699681,"traceId":"3fc81d0f682b1c36"},{"name":"run-typescript","duration":4968078,"timestamp":176969667,"id":1483,"parentId":1,"tags":{},"startTime":1787048714844,"traceId":"3fc81d0f682b1c36"},{"name":"static-check","duration":1326382,"timestamp":181976902,"id":1486,"parentId":1,"tags":{},"startTime":1787048719851,"traceId":"3fc81d0f682b1c36"},{"name":"static-generation","duration":5629403,"timestamp":183444802,"id":1800,"parentId":1,"tags":{},"startTime":1787048721319,"traceId":"3fc81d0f682b1c36"},{"name":"collect-build-traces","duration":24011142,"timestamp":183303913,"id":1797,"parentId":1,"tags":{},"startTime":1787048721178,"traceId":"3fc81d0f682b1c36"},{"name":"telemetry-flush","duration":57,"timestamp":207318876,"id":1809,"parentId":1,"tags":{},"startTime":1787048745193,"traceId":"3fc81d0f682b1c36"},{"name":"next-build","duration":45692850,"timestamp":161626096,"id":1,"tags":{"buildMode":"default","version":"16.3.0","bundler":"webpack","has-custom-webpack-config":"true","use-build-worker":"false"},"startTime":1787048699500,"traceId":"3fc81d0f682b1c36"}]
1
+ [{"name":"run-webpack","duration":15189978,"timestamp":349628764,"id":14,"parentId":1,"tags":{},"startTime":1787558751324,"traceId":"722ba4d87bff2951"},{"name":"run-typescript","duration":4939039,"timestamp":364823027,"id":1483,"parentId":1,"tags":{},"startTime":1787558766519,"traceId":"722ba4d87bff2951"},{"name":"static-check","duration":1305858,"timestamp":369801199,"id":1486,"parentId":1,"tags":{},"startTime":1787558771497,"traceId":"722ba4d87bff2951"},{"name":"static-generation","duration":5396169,"timestamp":371263589,"id":1800,"parentId":1,"tags":{},"startTime":1787558772959,"traceId":"722ba4d87bff2951"},{"name":"collect-build-traces","duration":23597704,"timestamp":371107667,"id":1797,"parentId":1,"tags":{},"startTime":1787558772803,"traceId":"722ba4d87bff2951"},{"name":"telemetry-flush","duration":64,"timestamp":394709259,"id":1809,"parentId":1,"tags":{},"startTime":1787558796405,"traceId":"722ba4d87bff2951"},{"name":"next-build","duration":45258753,"timestamp":349450583,"id":1,"tags":{"buildMode":"default","version":"16.3.0","bundler":"webpack","has-custom-webpack-config":"true","use-build-worker":"false"},"startTime":1787558751146,"traceId":"722ba4d87bff2951"}]
@@ -1,5 +1,5 @@
1
1
  /**
2
- * file-viewer — preview a local file (markdown / json / image / pdf).
2
+ * file-viewer — preview a local file (markdown / json / csv / image / pdf).
3
3
  *
4
4
  * Built-in, but written against the PUBLIC contract only, so it doubles as the
5
5
  * reference app (see ~/.cockpit/skills/html/SKILL.md):
@@ -299,17 +299,91 @@ function JsonView({ file }) {
299
299
  );
300
300
  }
301
301
 
302
- function jsonToMarkdown(text) {
303
- let body = text;
304
- try { body = JSON.stringify(JSON.parse(text), null, 2); } catch { /* show raw */ }
305
- // The fence must be longer than any backtick run inside the content.
302
+ /** Wrap text in a markdown fence longer than any backtick run inside it. */
303
+ function toFence(body, lang) {
306
304
  let fence = '```';
307
305
  const runs = body.match(/`+/g);
308
306
  if (runs) {
309
307
  const longest = Math.max.apply(null, runs.map((s) => s.length));
310
308
  while (fence.length <= longest) fence += '`';
311
309
  }
312
- return fence + 'json\n' + body + '\n' + fence;
310
+ return fence + lang + '\n' + body + '\n' + fence;
311
+ }
312
+
313
+ function jsonToMarkdown(text) {
314
+ let body = text;
315
+ try { body = JSON.stringify(JSON.parse(text), null, 2); } catch { /* show raw */ }
316
+ return toFence(body, 'json');
317
+ }
318
+
319
+ /**
320
+ * CSV / TSV. Default is the table widget; a button swaps to the raw delimited
321
+ * source rendered as a markdown fence — same two-widget dance (and the same
322
+ * `loadedMode` reasoning) as JsonView.
323
+ *
324
+ * The button placement differs from JsonView on purpose: JsonView's floating
325
+ * .json-toggle would land on top of the table's sticky header, and it sits 48px
326
+ * in from the edge, so the button would visibly jump on every mode switch. Here
327
+ * table mode hands the button to the widget's filter toolbar and raw mode draws
328
+ * a bar with the same metrics, leaving it in one place.
329
+ */
330
+ function CsvView({ file }) {
331
+ const ref = useRef(null);
332
+ const t = useLang();
333
+ const lang = pickLang();
334
+ const [mode, setMode] = useState('table');
335
+ const [loadedMode, setLoadedMode] = useState(null);
336
+ const [libError, setLibError] = useState(null);
337
+ const { loading, data, error } = useAsync(() => readText(file), [file]);
338
+
339
+ useEffect(() => {
340
+ const lib = mode === 'table'
341
+ ? loadLib('/html-lib/csv-viewer.js', '/html-lib/csv-viewer.css')
342
+ : loadLib('/html-lib/markdown.js', '/html-lib/markdown.css');
343
+ let alive = true;
344
+ setLibError(null);
345
+ lib
346
+ .then(() => { if (alive) setLoadedMode(mode); })
347
+ .catch((e) => { if (alive) setLibError(e.message); });
348
+ return () => { alive = false; };
349
+ }, [mode]);
350
+
351
+ useWidget(
352
+ ref, loadedMode === mode && !loading && data != null,
353
+ (el) => {
354
+ if (mode === 'table') {
355
+ window.CockpitCsv.render(el, data, {
356
+ filePath: file,
357
+ actionLabel: t('raw'),
358
+ onAction: () => setMode('raw'),
359
+ });
360
+ } else {
361
+ window.CockpitMarkdown.render(el, toFence(data, ''), { toc: false });
362
+ }
363
+ },
364
+ (el) => {
365
+ if (mode === 'table') window.CockpitCsv.unmount(el);
366
+ else window.CockpitMarkdown.unmount(el);
367
+ },
368
+ [loadedMode, mode, loading, data, file, lang],
369
+ setLibError
370
+ );
371
+
372
+ if (loading) return <Status kind="loading">loading…</Status>;
373
+ if (error) return <Status kind="error">{'file-viewer: ' + file + '\n\n' + error}</Status>;
374
+ if (libError) return <Status kind="error">{'file-viewer: ' + libError}</Status>;
375
+ // Table mode: the toggle is handed to the widget (right end of its filter
376
+ // toolbar). Raw mode: the page draws a bar with the same metrics so the button
377
+ // stays in exactly the same spot across the switch.
378
+ if (mode === 'table') return <div className="csv-view" ref={ref} />;
379
+ return (
380
+ <div className="viewer-stack">
381
+ <div className="viewer-bar">
382
+ <button type="button" onClick={() => setMode('table')}>{t('table')}</button>
383
+ </div>
384
+ <div className="md-view" ref={ref} />
385
+ </div>
386
+ );
313
387
  }
314
388
 
315
389
  function ImageView({ file }) {
@@ -358,8 +432,8 @@ function PdfView({ file }) {
358
432
  // App-local dictionary. The app only PERCEIVES the language, it does not import
359
433
  // the host's i18n — same as any user app would.
360
434
  const DICT = {
361
- zh: { readable: '可读', raw: '原文' },
362
- en: { readable: 'Readable', raw: 'Raw' },
435
+ zh: { readable: '可读', raw: '原文', table: '表格' },
436
+ en: { readable: 'Readable', raw: 'Raw', table: 'Table' },
363
437
  };
364
438
 
365
439
  /**
@@ -404,6 +478,7 @@ function App() {
404
478
  if (ext === 'md') return <MarkdownView file={file} />;
405
479
  if (ext === 'json') return <JsonView file={file} />;
406
480
  if (ext === 'pdf') return <PdfView file={file} />;
481
+ if (ext === 'csv' || ext === 'tsv') return <CsvView file={file} />;
407
482
  if (IMAGE_EXTS.indexOf(ext) >= 0) return <ImageView file={file} />;
408
483
  return <Status kind="error">{'file-viewer: unsupported file type .' + ext + '\n' + file}</Status>;
409
484
  }
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
6
  <title>File Viewer</title>
7
7
  <meta name="cockpit-name" content="file-viewer">
8
- <meta name="description" content="Preview local files: markdown (with TOC), json, images, pdf">
8
+ <meta name="description" content="Preview local files: markdown (with TOC), json, csv, images, pdf">
9
9
  <meta name="cockpit-icon" content="📄">
10
10
  <!-- Opt into the SDK's theme handling: follows the Cockpit host, falls back to
11
11
  the OS outside it, and mounts the top-right light/dark toggle. -->
@@ -55,6 +55,28 @@
55
55
  .img-view.natural img { max-width: none; max-height: none; cursor: zoom-out; }
56
56
  /* ---- PDF view: CockpitPdf widget, full viewport ---- */
57
57
  .pdf-view { position: fixed; inset: 0; }
58
+ /* ---- CSV view: CockpitCsv widget owns its own scroll container ---- */
59
+ .csv-view { position: fixed; inset: 0; }
60
+ /* ---- Bar + content stack (CSV raw mode) ----
61
+ In table mode the toggle lives at the right end of the widget's own filter
62
+ toolbar. Raw mode has no widget toolbar, so the page draws a bar with the
63
+ SAME metrics (6px/8px padding, 12px button, bottom border) and the button
64
+ flush right — the button then does not MOVE between the two modes, which a
65
+ fixed floating one (.json-toggle, 48px in from the edge) could not do.
66
+ Flex column instead of a top offset: no magic number to keep in sync. */
67
+ .viewer-stack { position: fixed; inset: 0; display: flex; flex-direction: column; }
68
+ .viewer-bar {
69
+ flex: none; display: flex; align-items: center; justify-content: flex-end;
70
+ gap: 8px; padding: 6px 8px; border-bottom: 1px solid var(--border);
71
+ }
72
+ .viewer-bar button {
73
+ font-family: var(--font-sans); font-size: 12px; line-height: 16px;
74
+ padding: 4px 8px; border: 1px solid var(--border); border-radius: 4px;
75
+ background: transparent; color: var(--muted-foreground); cursor: pointer;
76
+ }
77
+ .viewer-bar button:hover { color: var(--foreground); background: var(--tint-hover); }
78
+ /* The widget inside a stack fills the leftover height instead of the viewport. */
79
+ .viewer-stack .md-view { position: relative; inset: auto; flex: 1; min-height: 0; }
58
80
  </style>
59
81
  </head>
60
82
  <body>
@@ -18508,7 +18508,7 @@ var en_default2 = {
18508
18508
  copiedAllQA: "All Q&A copied",
18509
18509
  sentQA: "Sent to AI",
18510
18510
  readFileFailed: "Failed to read file",
18511
- fileOutsideProject: "File is outside this project \u2014 only Markdown and images can be previewed",
18511
+ fileOutsideProject: "File is outside this project \u2014 only Markdown, CSV and images can be previewed",
18512
18512
  reviewCreated: "Review created, link copied",
18513
18513
  reviewUpdated: "Review updated, link copied",
18514
18514
  reviewCreateFailed: "Failed to create review",
@@ -18588,15 +18588,16 @@ var en_default2 = {
18588
18588
  },
18589
18589
  sessions: {
18590
18590
  recentSessions: "Recent Sessions",
18591
+ favorites: "Favorite Sessions",
18592
+ noFavorites: "No favorite sessions yet. Click the star in the tab bar to add.",
18593
+ addFavorite: "Add to favorites",
18594
+ removeFavorite: "Remove from favorites",
18591
18595
  runningCount: "{{count}} running",
18592
18596
  unreadCount: "{{count}} unread",
18593
18597
  noSessions: "No sessions yet",
18594
18598
  running: "Running",
18595
18599
  done: "Done",
18596
- pinnedSessions: "Pinned Sessions",
18597
- noPinnedSessions: "No pinned sessions. Click the pin icon in the tab bar to add.",
18598
18600
  editTitle: "Edit title",
18599
- remove: "Remove",
18600
18601
  projectSessions: "Project Sessions",
18601
18602
  browseAllSessions: "Browse all sessions",
18602
18603
  sessionList: "Session List",
@@ -18823,6 +18824,20 @@ var en_default2 = {
18823
18824
  enterKeywordToSearch: "Enter keyword to search file contents",
18824
18825
  searchMinChars: "Search requires at least 2 characters"
18825
18826
  },
18827
+ csv: {
18828
+ table: "Table",
18829
+ raw: "Raw",
18830
+ empty: "Empty table",
18831
+ summary: "{{rows}} rows \xB7 {{cols}} columns",
18832
+ summaryFiltered: "{{rows}} / {{total}} rows matched \xB7 {{cols}} columns",
18833
+ loadMore: "Load more ({{shown}} / {{total}} shown)",
18834
+ filterPlaceholder: "Filter rows\u2026",
18835
+ filterColumn: "Filter column",
18836
+ clearFilter: "Clear filter",
18837
+ allColumns: "All columns",
18838
+ noMatch: "No matching rows",
18839
+ sortHint: "Click to sort (asc / desc / off)"
18840
+ },
18826
18841
  codeViewer: {
18827
18842
  fileModifiedExternally: "File was modified externally. Saving will overwrite external changes.",
18828
18843
  useDiskVersion: "Use disk version",
@@ -19474,8 +19489,6 @@ var en_default2 = {
19474
19489
  notSelected: "(not selected)"
19475
19490
  },
19476
19491
  tabBar: {
19477
- unpin: "Unpin",
19478
- pin: "Pin to favorites",
19479
19492
  closeTab: "Close tab",
19480
19493
  closeAll: "Close all tabs",
19481
19494
  newTab: "New tab"
@@ -19749,7 +19762,7 @@ var zh_default = {
19749
19762
  copiedAllQA: "\u5DF2\u590D\u5236\u6240\u6709\u95EE\u7B54",
19750
19763
  sentQA: "\u5DF2\u53D1\u9001\u7ED9 AI",
19751
19764
  readFileFailed: "\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25",
19752
- fileOutsideProject: "\u6587\u4EF6\u5728\u5F53\u524D\u9879\u76EE\u4E4B\u5916\uFF0C\u4EC5\u652F\u6301\u9884\u89C8 Markdown \u548C\u56FE\u7247",
19765
+ fileOutsideProject: "\u6587\u4EF6\u5728\u5F53\u524D\u9879\u76EE\u4E4B\u5916\uFF0C\u4EC5\u652F\u6301\u9884\u89C8 Markdown\u3001CSV \u548C\u56FE\u7247",
19753
19766
  reviewCreated: "\u8BC4\u5BA1\u5DF2\u521B\u5EFA\uFF0C\u94FE\u63A5\u5DF2\u590D\u5236",
19754
19767
  reviewUpdated: "\u8BC4\u5BA1\u5DF2\u66F4\u65B0\uFF0C\u94FE\u63A5\u5DF2\u590D\u5236",
19755
19768
  reviewCreateFailed: "\u521B\u5EFA\u8BC4\u5BA1\u5931\u8D25",
@@ -19829,15 +19842,16 @@ var zh_default = {
19829
19842
  },
19830
19843
  sessions: {
19831
19844
  recentSessions: "\u6700\u8FD1\u4F1A\u8BDD",
19845
+ favorites: "\u6536\u85CF\u4F1A\u8BDD",
19846
+ noFavorites: "\u6682\u65E0\u6536\u85CF\u4F1A\u8BDD\uFF0C\u5728 Tab \u680F\u70B9\u51FB\u661F\u6807\u53EF\u6DFB\u52A0",
19847
+ addFavorite: "\u6536\u85CF\u6B64\u4F1A\u8BDD",
19848
+ removeFavorite: "\u53D6\u6D88\u6536\u85CF",
19832
19849
  runningCount: "{{count}} \u8FD0\u884C\u4E2D",
19833
19850
  unreadCount: "{{count}} \u672A\u8BFB",
19834
19851
  noSessions: "\u6682\u65E0\u4F1A\u8BDD\u8BB0\u5F55",
19835
19852
  running: "\u8FD0\u884C\u4E2D",
19836
19853
  done: "\u5B8C\u6210",
19837
- pinnedSessions: "\u5E38\u7528\u4F1A\u8BDD",
19838
- noPinnedSessions: "\u6682\u65E0\u5E38\u7528\u4F1A\u8BDD\uFF0C\u5728 Tab \u680F\u70B9\u51FB\u56FE\u9489\u53EF\u6DFB\u52A0",
19839
19854
  editTitle: "\u7F16\u8F91\u6807\u9898",
19840
- remove: "\u79FB\u9664",
19841
19855
  projectSessions: "\u9879\u76EE\u4F1A\u8BDD",
19842
19856
  browseAllSessions: "\u6D4F\u89C8\u6240\u6709\u4F1A\u8BDD",
19843
19857
  sessionList: "\u4F1A\u8BDD\u5217\u8868",
@@ -20064,6 +20078,20 @@ var zh_default = {
20064
20078
  enterKeywordToSearch: "\u8F93\u5165\u5173\u952E\u8BCD\u641C\u7D22\u6587\u4EF6\u5185\u5BB9",
20065
20079
  searchMinChars: "\u641C\u7D22\u5185\u5BB9\u81F3\u5C11\u9700\u8981 2 \u4E2A\u5B57\u7B26"
20066
20080
  },
20081
+ csv: {
20082
+ table: "\u8868\u683C",
20083
+ raw: "\u539F\u59CB\u5185\u5BB9",
20084
+ empty: "\u7A7A\u8868\u683C",
20085
+ summary: "{{rows}} \u884C \xB7 {{cols}} \u5217",
20086
+ summaryFiltered: "\u5339\u914D {{rows}} / {{total}} \u884C \xB7 {{cols}} \u5217",
20087
+ loadMore: "\u52A0\u8F7D\u66F4\u591A\uFF08\u5DF2\u663E\u793A {{shown}} / {{total}}\uFF09",
20088
+ filterPlaceholder: "\u7B5B\u9009\u5185\u5BB9\u2026",
20089
+ filterColumn: "\u7B5B\u9009\u5217",
20090
+ clearFilter: "\u6E05\u9664\u7B5B\u9009",
20091
+ allColumns: "\u5168\u90E8\u5217",
20092
+ noMatch: "\u6CA1\u6709\u5339\u914D\u7684\u884C",
20093
+ sortHint: "\u70B9\u51FB\u6392\u5E8F\uFF08\u5347\u5E8F / \u964D\u5E8F / \u53D6\u6D88\uFF09"
20094
+ },
20067
20095
  codeViewer: {
20068
20096
  fileModifiedExternally: "\u6587\u4EF6\u5DF2\u88AB\u5916\u90E8\u4FEE\u6539\uFF0C\u4FDD\u5B58\u5C06\u8986\u76D6\u5916\u90E8\u66F4\u6539",
20069
20097
  useDiskVersion: "\u4F7F\u7528\u78C1\u76D8\u7248\u672C",
@@ -20715,8 +20743,6 @@ var zh_default = {
20715
20743
  notSelected: "(\u672A\u9009\u62E9)"
20716
20744
  },
20717
20745
  tabBar: {
20718
- unpin: "\u53D6\u6D88\u56FA\u5B9A",
20719
- pin: "\u56FA\u5B9A\u5230\u5E38\u7528\u4F1A\u8BDD",
20720
20746
  closeTab: "\u5173\u95ED\u6807\u7B7E",
20721
20747
  closeAll: "\u5173\u95ED\u6240\u6709\u6807\u7B7E",
20722
20748
  newTab: "\u65B0\u5EFA\u6807\u7B7E"
package/dist/wsServer.mjs CHANGED
@@ -1123,12 +1123,22 @@ var dispatchMessage = (msg, projectCwd, registry, send) => Effect_exports.sync((
1123
1123
  return;
1124
1124
  }
1125
1125
  const childEnv = {
1126
+ // The server's own PATH — i.e. the one the user's interactive shell
1127
+ // exported when they launched cockpit. It must be set HERE, not only on
1128
+ // the pty branch: childEnv is rebuilt from scratch, and `zsh --login -c`
1129
+ // is NON-interactive, so it never sources ~/.zshrc. Without this, a pipe
1130
+ // command only sees the system PATH that /etc/zprofile's path_helper
1131
+ // builds, and every tool installed via an rc-file PATH edit (Android
1132
+ // platform-tools, ~/.local/bin, ~/.cargo/bin, nvm/pyenv shims) reports
1133
+ // `command not found` — while the exact same command works in a pty
1134
+ // bubble. Placed before ...env so a user-supplied PATH still wins.
1135
+ PATH: getDefaultPath(),
1126
1136
  HOME: process.env.HOME,
1127
1137
  USER: process.env.USER,
1128
1138
  SHELL: process.env.SHELL,
1129
1139
  TERM: "xterm-256color",
1130
1140
  // UTF-8 locale so the pty renders multi-byte text (CJK, emoji) correctly.
1131
- // ptyEnv is rebuilt from scratch (not inherited from process.env), and a
1141
+ // childEnv is rebuilt from scratch (not inherited from process.env), and a
1132
1142
  // macOS `--login` shell does NOT restore LANG (Terminal.app/iTerm inject it,
1133
1143
  // not the rc files) — so without this, vim/less open UTF-8 files in the
1134
1144
  // C/POSIX locale and mojibake every non-ASCII char. Pass the real locale
@@ -1152,7 +1162,7 @@ var dispatchMessage = (msg, projectCwd, registry, send) => Effect_exports.sync((
1152
1162
  };
1153
1163
  try {
1154
1164
  if (usePty) {
1155
- const ptyEnv = { PATH: getDefaultPath() };
1165
+ const ptyEnv = {};
1156
1166
  for (const [k, v] of Object.entries(childEnv)) {
1157
1167
  if (v !== void 0) ptyEnv[k] = v;
1158
1168
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@surething/cockpit",
3
- "version": "1.0.265",
3
+ "version": "1.0.266",
4
4
  "description": "The open-source Claude Code GUI — an IDE-like workbench for parallel AI coding. Drive Claude (default), Codex, DeepSeek, Kimi, or local Ollama in tabs. Terminal, browser & DB bubbles, code review. Self-host on a shared dev box — a seat for every teammate. Local-first, MIT.",
5
5
  "author": "Robert",
6
6
  "license": "MIT",