@neuralnomads/codenomad-dev 0.18.0-dev-20260721-d74a8a39 → 0.18.0-dev-20260727-269cff64

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/dist/config/schema.js +2 -1
  2. package/dist/config/schema.test.js +13 -0
  3. package/dist/filesystem/__tests__/search-cache.test.js +19 -7
  4. package/dist/filesystem/__tests__/search.test.js +53 -0
  5. package/dist/filesystem/search-cache.js +5 -9
  6. package/dist/filesystem/search.js +22 -9
  7. package/dist/server/routes/auth-pages/login.html +3 -3
  8. package/dist/server/routes/auth.js +1 -1
  9. package/dist/server/routes/auth.test.js +21 -0
  10. package/dist/workspaces/process-identity.js +28 -10
  11. package/dist/workspaces/process-identity.test.js +29 -0
  12. package/dist/workspaces/runtime.js +1 -1
  13. package/dist/workspaces/runtime.test.js +8 -0
  14. package/package.json +1 -1
  15. package/public/assets/{FilesTab-DRWiHv0M.js → FilesTab-pl_3_Ppx.js} +2 -2
  16. package/public/assets/{GitChangesTab-Bby-dRmu.js → GitChangesTab-COJ_xDva.js} +2 -2
  17. package/public/assets/{SplitFilePanel-C1aKE1hq.js → SplitFilePanel-B5nrgBs3.js} +1 -1
  18. package/public/assets/StatusTab-rXgEwwYW.js +1 -0
  19. package/public/assets/{align-justify-Ce1uZY4E.js → align-justify-CKDczyVy.js} +1 -1
  20. package/public/assets/{bundle-full-CWkY9-v4.js → bundle-full-CuWt9dTK.js} +1 -1
  21. package/public/assets/{diff-viewer-ChdWzmb2.js → diff-viewer-drQ_Yje8.js} +1 -1
  22. package/public/assets/index-Bt9PdFAD.css +1 -0
  23. package/public/assets/index-BymyGk2C.js +1 -0
  24. package/public/assets/index-CEIEYgCg.js +1 -0
  25. package/public/assets/{index-DOprq6Gt.js → index-CozaqOFM.js} +1 -1
  26. package/public/assets/index-Cqo6ftJT.js +1 -0
  27. package/public/assets/index-Cs1fQOLl.js +1 -0
  28. package/public/assets/{index-DM1cpVNo.js → index-Cs2gBaWC.js} +1 -1
  29. package/public/assets/index-CwhvpTeE.js +1 -0
  30. package/public/assets/index-D0xuNxlo.js +2 -0
  31. package/public/assets/index-D1HW4nyh.js +1 -0
  32. package/public/assets/index-DBw0YE-2.js +1 -0
  33. package/public/assets/index-OYNGtp3z.js +1 -0
  34. package/public/assets/{loading-B8b-5OAQ.js → loading-Cz4dKVP8.js} +1 -1
  35. package/public/assets/main-BEYytlgD.js +68 -0
  36. package/public/assets/{markdown-DfOGkX-q.js → markdown-DUHZyBXo.js} +3 -3
  37. package/public/assets/{monaco-viewer-DM35aobI.js → monaco-viewer-CiFg18Ak.js} +11 -11
  38. package/public/assets/tool-call-C7FlzFBf.js +59 -0
  39. package/public/assets/unified-picker-CpU6qugd.js +1 -0
  40. package/public/assets/{wrap-text-D7C2RpdK.js → wrap-text-CS5K8Uhi.js} +1 -1
  41. package/public/index.html +4 -4
  42. package/public/loading.html +4 -4
  43. package/public/sw.js +1 -1
  44. package/public/assets/StatusTab-DGAe2jhy.js +0 -1
  45. package/public/assets/index-60Fu5kUB.js +0 -1
  46. package/public/assets/index-BhJHlWzk.js +0 -1
  47. package/public/assets/index-Cce2Hk2L.js +0 -1
  48. package/public/assets/index-CpB67B7z.js +0 -1
  49. package/public/assets/index-D3fvGcC7.js +0 -1
  50. package/public/assets/index-D8WMdSS9.js +0 -2
  51. package/public/assets/index-D_qqDz2d.js +0 -1
  52. package/public/assets/index-E0A5Kg-d.js +0 -1
  53. package/public/assets/index-L7fX3W8k.css +0 -1
  54. package/public/assets/index-j4B2FQw9.js +0 -1
  55. package/public/assets/main-B9uXiXu7.js +0 -68
  56. package/public/assets/tool-call-BpefPuGQ.js +0 -59
  57. package/public/assets/unified-picker-CXhvV1sd.js +0 -1
@@ -19,8 +19,9 @@ const PreferencesSchema = z
19
19
  modelThinkingSelections: z.record(z.string(), z.string()).default({}),
20
20
  diffViewMode: z.enum(["split", "unified"]).default("split"),
21
21
  toolOutputExpansion: z.enum(["expanded", "collapsed"]).default("expanded"),
22
- diagnosticsExpansion: z.enum(["expanded", "collapsed"]).default("expanded"),
22
+ diagnosticsExpansion: z.enum(["hidden", "expanded", "collapsed"]).default("expanded"),
23
23
  showUsageMetrics: z.boolean().default(true),
24
+ usageMetricsExpansion: z.enum(["expanded", "collapsed"]).default("collapsed"),
24
25
  autoCleanupBlankSessions: z.boolean().default(true),
25
26
  listeningMode: z.enum(["local", "all"]).default("local"),
26
27
  logLevel: z.enum(["DEBUG", "INFO", "WARN", "ERROR"]).default("DEBUG"),
@@ -0,0 +1,13 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { PreferencesSchema } from "./schema";
4
+ describe("chat visibility preferences", () => {
5
+ it("accepts hidden diagnostics and collapsed usage metrics", () => {
6
+ const preferences = PreferencesSchema.parse({
7
+ diagnosticsExpansion: "hidden",
8
+ usageMetricsExpansion: "collapsed",
9
+ });
10
+ assert.equal(preferences.diagnosticsExpansion, "hidden");
11
+ assert.equal(preferences.usageMetricsExpansion, "collapsed");
12
+ });
13
+ });
@@ -8,25 +8,37 @@ describe("workspace search cache", () => {
8
8
  it("expires cached candidates after the TTL", () => {
9
9
  const workspacePath = "/tmp/workspace";
10
10
  const startTime = 1_000;
11
- refreshWorkspaceCandidates(workspacePath, () => [createEntry("file-a")], startTime);
12
- const beforeExpiry = getWorkspaceCandidates(workspacePath, startTime + WORKSPACE_CANDIDATE_CACHE_TTL_MS - 1);
11
+ refreshWorkspaceCandidates(workspacePath, "query-a", () => [createEntry("file-a")], startTime);
12
+ const beforeExpiry = getWorkspaceCandidates(workspacePath, "query-a", startTime + WORKSPACE_CANDIDATE_CACHE_TTL_MS - 1);
13
13
  assert.ok(beforeExpiry);
14
14
  assert.equal(beforeExpiry.length, 1);
15
15
  assert.equal(beforeExpiry[0].name, "file-a");
16
- const afterExpiry = getWorkspaceCandidates(workspacePath, startTime + WORKSPACE_CANDIDATE_CACHE_TTL_MS + 1);
16
+ const afterExpiry = getWorkspaceCandidates(workspacePath, "query-a", startTime + WORKSPACE_CANDIDATE_CACHE_TTL_MS + 1);
17
17
  assert.equal(afterExpiry, undefined);
18
18
  });
19
19
  it("replaces cached entries when manually refreshed", () => {
20
20
  const workspacePath = "/tmp/workspace";
21
- refreshWorkspaceCandidates(workspacePath, () => [createEntry("file-a")], 5_000);
22
- const initial = getWorkspaceCandidates(workspacePath, 5_001);
21
+ refreshWorkspaceCandidates(workspacePath, "query-a", () => [createEntry("file-a")], 5_000);
22
+ const initial = getWorkspaceCandidates(workspacePath, "query-a", 5_001);
23
23
  assert.ok(initial);
24
24
  assert.equal(initial[0].name, "file-a");
25
- refreshWorkspaceCandidates(workspacePath, () => [createEntry("file-b")], 6_000);
26
- const refreshed = getWorkspaceCandidates(workspacePath, 6_001);
25
+ refreshWorkspaceCandidates(workspacePath, "query-a", () => [createEntry("file-b")], 6_000);
26
+ const refreshed = getWorkspaceCandidates(workspacePath, "query-a", 6_001);
27
27
  assert.ok(refreshed);
28
28
  assert.equal(refreshed[0].name, "file-b");
29
29
  });
30
+ it("does not reuse candidates across query scopes", () => {
31
+ const workspacePath = "/tmp/workspace";
32
+ refreshWorkspaceCandidates(workspacePath, "query-a", () => [createEntry("file-a")], 5_000);
33
+ assert.equal(getWorkspaceCandidates(workspacePath, "query-a", 5_001)?.[0].name, "file-a");
34
+ assert.equal(getWorkspaceCandidates(workspacePath, "query-b", 5_001), undefined);
35
+ refreshWorkspaceCandidates(workspacePath, "query-b", () => [createEntry("file-b")], 5_000);
36
+ assert.equal(getWorkspaceCandidates(workspacePath, "query-a", 5_001), undefined);
37
+ assert.equal(getWorkspaceCandidates(workspacePath, "query-b", 5_001)?.[0].name, "file-b");
38
+ clearWorkspaceSearchCache(workspacePath);
39
+ assert.equal(getWorkspaceCandidates(workspacePath, "query-a", 5_001), undefined);
40
+ assert.equal(getWorkspaceCandidates(workspacePath, "query-b", 5_001), undefined);
41
+ });
30
42
  });
31
43
  function createEntry(name) {
32
44
  return {
@@ -0,0 +1,53 @@
1
+ import assert from "node:assert/strict";
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { after, test } from "node:test";
6
+ import { searchWorkspaceFiles } from "../search";
7
+ import { getWorkspaceCandidates } from "../search-cache";
8
+ const workspace = fs.mkdtempSync(path.join(os.tmpdir(), "codenomad-search-"));
9
+ after(() => fs.rmSync(workspace, { recursive: true, force: true }));
10
+ test("finds a matching file after more than 8000 non-matching entries", () => {
11
+ fs.mkdirSync(path.join(workspace, "a"));
12
+ fs.mkdirSync(path.join(workspace, "b"));
13
+ const [targetDirName, fillerDirName] = fs.readdirSync(workspace);
14
+ const fillerDir = path.join(workspace, fillerDirName);
15
+ const targetDir = path.join(workspace, targetDirName);
16
+ for (let index = 0; index < 8_001; index += 1) {
17
+ fs.writeFileSync(path.join(fillerDir, `filler-${index}.txt`), "");
18
+ }
19
+ fs.writeFileSync(path.join(targetDir, "unique-search-target.txt"), "");
20
+ const results = searchWorkspaceFiles(workspace, "unique-search-target", {
21
+ type: "file",
22
+ refresh: true,
23
+ });
24
+ assert.equal(results.some((entry) => entry.name === "unique-search-target.txt"), true);
25
+ searchWorkspaceFiles(workspace, "filler", { type: "file", refresh: true });
26
+ assert.equal(getWorkspaceCandidates(workspace, "file\0filler")?.length, 8_000);
27
+ });
28
+ test("does not revisit directory links", () => {
29
+ const cyclicWorkspace = fs.mkdtempSync(path.join(os.tmpdir(), "codenomad-search-cycle-"));
30
+ try {
31
+ fs.symlinkSync(cyclicWorkspace, path.join(cyclicWorkspace, "cycle"), process.platform === "win32" ? "junction" : "dir");
32
+ assert.deepEqual(searchWorkspaceFiles(cyclicWorkspace, "not-present", { refresh: true }), []);
33
+ }
34
+ finally {
35
+ fs.rmSync(cyclicWorkspace, { recursive: true, force: true });
36
+ }
37
+ });
38
+ test("indexes both real and linked directory paths", () => {
39
+ const linkedWorkspace = fs.mkdtempSync(path.join(os.tmpdir(), "codenomad-search-link-"));
40
+ try {
41
+ const realDirectory = path.join(linkedWorkspace, "b");
42
+ fs.mkdirSync(realDirectory);
43
+ fs.writeFileSync(path.join(realDirectory, "needle.txt"), "");
44
+ fs.symlinkSync(realDirectory, path.join(linkedWorkspace, "a"), process.platform === "win32" ? "junction" : "dir");
45
+ const linkedResults = searchWorkspaceFiles(linkedWorkspace, "a/needle", { type: "file", refresh: true });
46
+ const realResults = searchWorkspaceFiles(linkedWorkspace, "b/needle", { type: "file", refresh: true });
47
+ assert.equal(linkedResults.some((entry) => entry.path === "a/needle.txt"), true);
48
+ assert.equal(realResults.some((entry) => entry.path === "b/needle.txt"), true);
49
+ }
50
+ finally {
51
+ fs.rmSync(linkedWorkspace, { recursive: true, force: true });
52
+ }
53
+ });
@@ -1,10 +1,10 @@
1
1
  import path from "path";
2
2
  export const WORKSPACE_CANDIDATE_CACHE_TTL_MS = 30_000;
3
3
  const workspaceCandidateCache = new Map();
4
- export function getWorkspaceCandidates(rootDir, now = Date.now()) {
4
+ export function getWorkspaceCandidates(rootDir, scope, now = Date.now()) {
5
5
  const key = normalizeKey(rootDir);
6
6
  const cached = workspaceCandidateCache.get(key);
7
- if (!cached) {
7
+ if (!cached || cached.scope !== scope) {
8
8
  return undefined;
9
9
  }
10
10
  if (cached.expiresAt <= now) {
@@ -13,15 +13,12 @@ export function getWorkspaceCandidates(rootDir, now = Date.now()) {
13
13
  }
14
14
  return cloneEntries(cached.candidates);
15
15
  }
16
- export function refreshWorkspaceCandidates(rootDir, builder, now = Date.now()) {
16
+ export function refreshWorkspaceCandidates(rootDir, scope, builder, now = Date.now()) {
17
17
  const key = normalizeKey(rootDir);
18
18
  const freshCandidates = builder();
19
- if (!freshCandidates || freshCandidates.length === 0) {
20
- workspaceCandidateCache.delete(key);
21
- return [];
22
- }
23
19
  const storedCandidates = cloneEntries(freshCandidates);
24
20
  workspaceCandidateCache.set(key, {
21
+ scope,
25
22
  expiresAt: now + WORKSPACE_CANDIDATE_CACHE_TTL_MS,
26
23
  candidates: storedCandidates,
27
24
  });
@@ -32,8 +29,7 @@ export function clearWorkspaceSearchCache(rootDir) {
32
29
  workspaceCandidateCache.clear();
33
30
  return;
34
31
  }
35
- const key = normalizeKey(rootDir);
36
- workspaceCandidateCache.delete(key);
32
+ workspaceCandidateCache.delete(normalizeKey(rootDir));
37
33
  }
38
34
  function cloneEntries(entries) {
39
35
  return entries.map((entry) => ({ ...entry }));
@@ -15,13 +15,14 @@ export function searchWorkspaceFiles(rootDir, query, options = {}) {
15
15
  const limit = normalizeLimit(options.limit);
16
16
  const typeFilter = options.type ?? "all";
17
17
  const refreshRequested = options.refresh === true;
18
+ const cacheScope = `${typeFilter}\0${trimmedQuery.toLowerCase()}`;
18
19
  let entries;
19
20
  try {
20
21
  if (!refreshRequested) {
21
- entries = getWorkspaceCandidates(normalizedRoot);
22
+ entries = getWorkspaceCandidates(normalizedRoot, cacheScope);
22
23
  }
23
24
  if (!entries) {
24
- entries = refreshWorkspaceCandidates(normalizedRoot, () => collectCandidates(normalizedRoot));
25
+ entries = refreshWorkspaceCandidates(normalizedRoot, cacheScope, () => collectCandidates(normalizedRoot, trimmedQuery, typeFilter));
25
26
  }
26
27
  }
27
28
  catch (error) {
@@ -29,7 +30,6 @@ export function searchWorkspaceFiles(rootDir, query, options = {}) {
29
30
  throw error;
30
31
  }
31
32
  if (!entries || entries.length === 0) {
32
- clearWorkspaceSearchCache(normalizedRoot);
33
33
  return [];
34
34
  }
35
35
  const candidates = buildCandidateEntries(entries, typeFilter);
@@ -45,14 +45,23 @@ export function searchWorkspaceFiles(rootDir, query, options = {}) {
45
45
  }
46
46
  return matches.map((match) => match.obj.entry);
47
47
  }
48
- function collectCandidates(rootDir) {
49
- const queue = [""];
48
+ function collectCandidates(rootDir, query, filter) {
49
+ const queue = [
50
+ { relativeDir: "", ancestors: new Set() },
51
+ ];
50
52
  const entries = [];
51
53
  while (queue.length > 0 && entries.length < MAX_CANDIDATES) {
52
- const relativeDir = queue.pop() || "";
54
+ const queuedDirectory = queue.pop();
55
+ const { relativeDir, ancestors } = queuedDirectory;
53
56
  const absoluteDir = relativeDir ? path.join(rootDir, relativeDir) : rootDir;
54
57
  let dirents;
58
+ let branchAncestors;
55
59
  try {
60
+ const realDir = normalizeDirectoryIdentity(fs.realpathSync.native(absoluteDir));
61
+ if (ancestors.has(realDir)) {
62
+ continue;
63
+ }
64
+ branchAncestors = new Set([...ancestors, realDir]);
56
65
  dirents = fs.readdirSync(absoluteDir, { withFileTypes: true });
57
66
  }
58
67
  catch {
@@ -75,9 +84,7 @@ function collectCandidates(rootDir) {
75
84
  }
76
85
  const isDirectory = stats.isDirectory();
77
86
  if (isDirectory && !IGNORED_DIRECTORIES.has(lowerName)) {
78
- if (entries.length < MAX_CANDIDATES) {
79
- queue.push(relativePath);
80
- }
87
+ queue.push({ relativeDir: relativePath, ancestors: branchAncestors });
81
88
  }
82
89
  const entryType = isDirectory ? "directory" : "file";
83
90
  const normalizedPath = normalizeRelativeEntryPath(relativePath);
@@ -89,6 +96,9 @@ function collectCandidates(rootDir) {
89
96
  size: entryType === "file" ? stats.size : undefined,
90
97
  modifiedAt: stats.mtime.toISOString(),
91
98
  };
99
+ if (!shouldInclude(entry.type, filter) || !fuzzysort.single(query, buildSearchKey(entry))) {
100
+ continue;
101
+ }
92
102
  entries.push(entry);
93
103
  if (entries.length >= MAX_CANDIDATES) {
94
104
  break;
@@ -133,3 +143,6 @@ function normalizeRelativeEntryPath(relativePath) {
133
143
  function buildSearchKey(entry) {
134
144
  return entry.path.toLowerCase();
135
145
  }
146
+ function normalizeDirectoryIdentity(directoryPath) {
147
+ return process.platform === "win32" ? directoryPath.toLowerCase() : directoryPath;
148
+ }
@@ -72,10 +72,10 @@
72
72
  <p>This CodeNomad server is protected. Enter your credentials to continue.</p>
73
73
 
74
74
  <label for="username">Username</label>
75
- <input id="username" autocomplete="username" placeholder="{{DEFAULT_USERNAME}}" value="" />
75
+ <input id="username" autocomplete="username" autocapitalize="none" autocorrect="off" spellcheck="false" placeholder="{{DEFAULT_USERNAME}}" value="{{DEFAULT_USERNAME}}" />
76
76
 
77
77
  <label for="password">Password</label>
78
- <input id="password" type="password" autocomplete="current-password" value="" />
78
+ <input id="password" type="password" autocomplete="current-password" autocapitalize="none" autocorrect="off" spellcheck="false" value="" />
79
79
 
80
80
  <button id="submit" type="button">Continue</button>
81
81
  <div id="error" class="error" style="display: none"></div>
@@ -95,7 +95,7 @@
95
95
 
96
96
  async function submit() {
97
97
  hideError()
98
- const username = $("username").value.trim()
98
+ const username = $("username").value
99
99
  const password = $("password").value
100
100
  if (!username || !password) {
101
101
  showError("Username and password are required.")
@@ -26,7 +26,7 @@ function getLoginHtml(defaultUsername) {
26
26
  cachedLoginTemplate = readTemplate(LOGIN_TEMPLATE_URL, null);
27
27
  }
28
28
  const escapedUsername = escapeHtml(defaultUsername);
29
- return cachedLoginTemplate.replace(/\{\{DEFAULT_USERNAME\}\}/g, escapedUsername);
29
+ return cachedLoginTemplate.replace(/\{\{DEFAULT_USERNAME\}\}/g, () => escapedUsername);
30
30
  }
31
31
  function getTokenHtml() {
32
32
  if (!cachedTokenTemplate) {
@@ -0,0 +1,21 @@
1
+ import assert from "node:assert/strict";
2
+ import { it } from "node:test";
3
+ import Fastify from "fastify";
4
+ import { registerAuthRoutes } from "./auth";
5
+ it("renders the escaped default username literally as the login field value", async () => {
6
+ const app = Fastify({ logger: false });
7
+ const username = " code$&\"nomad ";
8
+ const authManager = {
9
+ getSessionFromRequest: () => null,
10
+ getStatus: () => ({ username }),
11
+ };
12
+ registerAuthRoutes(app, { authManager });
13
+ const response = await app.inject({ method: "GET", url: "/login" });
14
+ assert.equal(response.statusCode, 200);
15
+ assert.ok(response.body.includes('value=" code$&amp;&quot;nomad "'));
16
+ assert.match(response.body, /const username = \$\("username"\)\.value\s*\n/);
17
+ assert.equal(response.body.match(/autocapitalize="none"/g)?.length, 2);
18
+ assert.equal(response.body.match(/autocorrect="off"/g)?.length, 2);
19
+ assert.equal(response.body.match(/spellcheck="false"/g)?.length, 2);
20
+ await app.close();
21
+ });
@@ -1,16 +1,31 @@
1
1
  export const LAUNCH_CLEANUP_TOKEN_ENV = "CODENOMAD_LAUNCH_CLEANUP_TOKEN";
2
+ const SHELL_DOLLAR = "$";
2
3
  const LINUX_IDENTITY_FUNCTIONS = String.raw `
3
- boot=$(cat /proc/sys/kernel/random/boot_id 2>/dev/null) || exit 20
4
+ IFS= read -r boot 2>/dev/null < /proc/sys/kernel/random/boot_id || exit 20
4
5
  read_stat() {
5
- line=$(cat "/proc/$1/stat" 2>/dev/null) || return 1
6
- stat_pid=$(printf '%s\n' "$line" | cut -d' ' -f1); rest=$(printf '%s\n' "$line" | sed 's/^.*) //'); set -- $rest
7
- stat_ppid=$2; stat_group=$3; stat_start=$20
6
+ line=
7
+ while IFS= read -r chunk || test -n "$chunk"; do line=$line$chunk; done 2>/dev/null < "/proc/$1/stat"
8
+ test -n "$line" || return 1
9
+ stat_pid=$1; rest=${SHELL_DOLLAR}{line##*) }; set -- $rest
10
+ test "$#" -ge 20 || return 1
11
+ stat_ppid=$2; stat_group=$3; shift 19; stat_start=$1
12
+ }
13
+ emit_linux() {
14
+ test -n "$1" && printf '%s|' "$1"
15
+ printf '%s|%s|%s|%s|%s|%s\n' "$stat_pid" "$stat_ppid" "$stat_group" "$stat_start" "$boot" "$stat_start"
8
16
  }
9
- emit_linux() { printf '%s|%s|%s|%s|%s|%s|%s\n' "$1" "$stat_pid" "$stat_ppid" "$stat_group" "$stat_start" "$boot" "$stat_start"; }
10
17
  `;
11
18
  const LINUX_SNAPSHOT_SCRIPT = String.raw `${LINUX_IDENTITY_FUNCTIONS}
12
19
  for stat in /proc/[0-9]*/stat; do
13
- pid=$(basename "$(dirname "$stat")"); read_stat "$pid" && emit_linux "" | cut -c2-
20
+ directory=${SHELL_DOLLAR}{stat%/stat}; pid=${SHELL_DOLLAR}{directory##*/}; read_stat "$pid" && emit_linux ""
21
+ done
22
+ exit 0
23
+ `;
24
+ const LINUX_LAUNCH_GROUP_SNAPSHOT_SCRIPT = String.raw `${LINUX_IDENTITY_FUNCTIONS}
25
+ leader_pid=$1; read_stat "$leader_pid" || exit 22; expected_group=$stat_group; emit_linux ""
26
+ for stat in /proc/[0-9]*/stat; do
27
+ directory=${SHELL_DOLLAR}{stat%/stat}; pid=${SHELL_DOLLAR}{directory##*/}; test "$pid" = "$leader_pid" && continue
28
+ read_stat "$pid" && test "$stat_group" = "$expected_group" && emit_linux ""
14
29
  done
15
30
  exit 0
16
31
  `;
@@ -20,7 +35,7 @@ shift 5; matched=0; cutoff=; signal_sent=0
20
35
  if read_stat "$leader_pid" && test "$boot" = "$leader_boot" && test "$stat_start" = "$leader_start" && test "$stat_group" = "$expected_group"; then
21
36
  matched=1
22
37
  for stat in /proc/[0-9]*/stat; do
23
- candidate=$(basename "$(dirname "$stat")"); read_stat "$candidate" && test "$stat_group" = "$expected_group" && emit_linux CODENOMAD_TARGET
38
+ directory=${SHELL_DOLLAR}{stat%/stat}; candidate=${SHELL_DOLLAR}{directory##*/}; read_stat "$candidate" && test "$stat_group" = "$expected_group" && emit_linux CODENOMAD_TARGET
24
39
  done
25
40
  if kill "-$requested_signal" -- "-$expected_group" 2>/dev/null; then
26
41
  signal_sent=1
@@ -69,7 +84,7 @@ pass=0
69
84
  while test "$pass" -lt "$passes"; do
70
85
  pass=$((pass + 1))
71
86
  for environ in /proc/[0-9]*/environ; do
72
- pid=$(basename "$(dirname "$environ")")
87
+ directory=${SHELL_DOLLAR}{environ%/environ}; pid=${SHELL_DOLLAR}{directory##*/}
73
88
  if matches_token "$pid" && read_stat "$pid"; then
74
89
  test -n "$requested_signal" && prefix=CODENOMAD_TARGET || prefix=CODENOMAD_PROCESS
75
90
  emit_linux "$prefix"
@@ -372,8 +387,11 @@ export function descendantsOf(processes, rootPid) {
372
387
  return descendants;
373
388
  }
374
389
  export function probePosixProcesses(spawnCommand, timeoutMs, platform = process.platform, filter) {
375
- if (platform === "linux")
376
- return querySnapshot(() => runLinuxScript(spawnCommand, LINUX_SNAPSHOT_SCRIPT, [], timeoutMs, "codenomad-posix-identity"), (output) => parseDelimitedSnapshot(output, true));
390
+ if (platform === "linux") {
391
+ const pids = filter?.pids?.filter((pid) => Number.isInteger(pid) && pid > 0).map(String) ?? [];
392
+ const launchGroupProbe = pids.length === 1 && filter?.groupId === Number(pids[0]);
393
+ return querySnapshot(() => runLinuxScript(spawnCommand, launchGroupProbe ? LINUX_LAUNCH_GROUP_SNAPSHOT_SCRIPT : LINUX_SNAPSHOT_SCRIPT, launchGroupProbe ? pids : [], timeoutMs, "codenomad-posix-identity"), (output) => parseDelimitedSnapshot(output, true), { allowEmpty: Boolean(filter) });
394
+ }
377
395
  // POSIX has no portable pidfd/start ticks; collect one coherent table instead of probing every PID.
378
396
  return querySnapshot(() => spawnCommand("ps", ["-axo", "pid=,ppid=,pgid=,lstart=,comm="], {
379
397
  encoding: "utf8", timeout: timeoutMs, env: { ...process.env, LC_ALL: "C", LANG: "C" },
@@ -1,4 +1,7 @@
1
1
  import assert from "node:assert/strict";
2
+ import { spawn as spawnChild, spawnSync } from "node:child_process";
3
+ import { once } from "node:events";
4
+ import { readFileSync } from "node:fs";
2
5
  import { describe, it } from "node:test";
3
6
  import { probePosixProcesses, probeWindowsProcesses, probeWslProcesses, sameProcess, signalOwnedPosixProcessGroup, signalPosixProcesses, signalWindowsProcesses, startedNoLaterThan, } from "./process-identity";
4
7
  const output = (stdout = "", status = 0, stderr = "") => ({ pid: 1, output: [null, stdout, stderr], stdout, stderr, status, signal: null });
@@ -16,6 +19,32 @@ describe("process identity probes", () => {
16
19
  assert.deepEqual([call.command, call.args.includes("codenomad-posix-identity"), call.script.trimEnd().endsWith("exit 0")], ["sh", true, true]);
17
20
  assert.deepEqual(probe.ok && probe.processes.get(42), identity());
18
21
  });
22
+ it("queries the requested Linux launch group without per-process subprocesses", () => {
23
+ const call = {};
24
+ const probe = probePosixProcesses(spawn("42|1|42|123456|boot-a|123456\n", call), 25, "linux", { pids: [42], groupId: 42 });
25
+ assert.deepEqual(call.args.slice(-1), ["42"]);
26
+ assert.match(call.script, /expected_group=\$stat_group/);
27
+ assert.doesNotMatch(call.script, /\b(?:cat|cut|sed|basename|dirname)\b/);
28
+ assert.deepEqual(probe.ok && probe.processes.get(42), identity());
29
+ });
30
+ it("captures real Linux start ticks and launch-group members within the deadline", { skip: process.platform !== "linux" }, async () => {
31
+ const child = spawnChild("sh", ["-c", "sleep 5"], { stdio: "ignore" });
32
+ await once(child, "spawn");
33
+ try {
34
+ const stat = readFileSync(`/proc/${process.pid}/stat`, "utf8");
35
+ const expectedStart = stat.slice(stat.lastIndexOf(") ") + 2).split(" ")[19];
36
+ const probe = probePosixProcesses(spawnSync, 1_000, "linux", { pids: [process.pid], groupId: process.pid });
37
+ assert.equal(probe.ok && probe.processes.get(process.pid)?.startTime, expectedStart);
38
+ assert.equal(probe.ok && probe.processes.has(child.pid), true);
39
+ }
40
+ finally {
41
+ if (child.exitCode === null && child.signalCode === null) {
42
+ const exited = once(child, "exit");
43
+ child.kill();
44
+ await exited;
45
+ }
46
+ }
47
+ });
19
48
  it("uses one delimiter-safe process-table query on portable POSIX", () => {
20
49
  const call = {};
21
50
  const command = "/opt/opencode 'pipe|value'\t\"quoted\" café";
@@ -146,7 +146,7 @@ export class WorkspaceRuntime {
146
146
  const launchSnapshot = child.pid
147
147
  ? this.platform === "win32"
148
148
  ? probeWindowsProcesses(this.spawnCommand, this.stopCommandTimeoutMs)
149
- : probePosixProcesses(this.spawnCommand, this.stopCommandTimeoutMs, this.platform, this.platform === "linux" ? undefined : { pids: [child.pid], groupId: child.pid })
149
+ : probePosixProcesses(this.spawnCommand, this.stopCommandTimeoutMs, this.platform, { pids: [child.pid], groupId: child.pid })
150
150
  : { ok: false, error: "spawned child did not expose a PID" };
151
151
  const launchLeader = launchSnapshot.ok && child.pid ? launchSnapshot.processes.get(child.pid) : undefined;
152
152
  if (!launchLeader) {
@@ -80,6 +80,14 @@ async function harness(options = {}) {
80
80
  return { runtime, child, timers, calls, launch, abort };
81
81
  }
82
82
  describe("workspace runtime lifecycle contracts", () => {
83
+ it("captures the Linux launch group with one bounded shell command", async () => {
84
+ let launchCall;
85
+ await harness({ spawnSync: ((command, args) => {
86
+ launchCall ??= { command, args: [...args] };
87
+ return result(posix([[4242, 1, 4242, "100"]]));
88
+ }) });
89
+ assert.deepEqual(launchCall?.args.slice(-1), ["4242"]);
90
+ });
83
91
  it("cancels before spawn and while waiting for a port without losing retryable cleanup", async () => {
84
92
  let spawned = false;
85
93
  const runtime = new WorkspaceRuntime(new EventBus(), pino({ level: "silent" }), {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neuralnomads/codenomad-dev",
3
- "version": "0.18.0-dev-20260721-d74a8a39",
3
+ "version": "0.18.0-dev-20260727-269cff64",
4
4
  "description": "CodeNomad Server",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -1,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/monaco-viewer-DM35aobI.js","assets/git-diff-vendor-CYS3ApzA.js","assets/fast-diff-vendor-DgdwVvTQ.js","assets/highlight-vendor-8FKMu9os.js","assets/git-diff-vendor-HAZkIolJ.css"])))=>i.map(i=>d[i]);
2
- import{a8 as J,m,t as h,i as s,d as u,a as C,u as U,_ as X,f as Y}from"./monaco-viewer-DM35aobI.js";import{d as K,b as P,c as $,n as o,S as g,a as w,z as Z,A as p,F as ee}from"./git-diff-vendor-CYS3ApzA.js";import{S as te}from"./SplitFilePanel-C1aKE1hq.js";import{R as O,O as le,M as ne,Q as re,C as ae,e as ie,T as se}from"./main-B9uXiXu7.js";import{W as oe}from"./wrap-text-D7C2RpdK.js";import"./fast-diff-vendor-DgdwVvTQ.js";import"./highlight-vendor-8FKMu9os.js";import"./index-D8WMdSS9.js";var ce=h('<div class="px-2 py-2 border-b border-base"><div class=selector-input-group><div class="flex items-center gap-2 px-3 text-muted"></div><input type=text class=selector-input>'),de=h("<div class=file-list-header><span class=file-list-title></span><span class=file-list-count>"),V=h('<div class="p-3 text-xs text-secondary">'),he=h("<div class=file-list-item><div class=file-list-item-content><div class=file-list-item-path><span class=file-path-text>.."),ue=h('<div class="p-3 text-xs text-error">'),ve=h('<div><div class=file-list-item-content><div class=file-list-item-path><span class=file-path-text></span></div><div class="flex items-center gap-2 shrink-0"><div class=file-list-item-stats><span class="text-[10px] text-secondary"></span></div><button type=button class=git-change-row-action>'),x=h("<div class=file-viewer-empty><span class=file-viewer-empty-text>"),fe=h('<div class="file-viewer-panel flex-1"><div>'),ge=h('<div class="h-full outline-none"tabindex=0>'),we=h("<span>"),be=h("<div class=files-tab-stats><span class=files-tab-stat><span class=files-tab-selected-path><span class=file-path-text>"),Se=h("<button type=button style=margin-inline-start:auto>"),me=h("<button type=button>"),Q=h("<button type=button class=files-header-icon-button>"),$e=h("<span class=text-error>");const ye=p(()=>X(()=>import("./monaco-viewer-DM35aobI.js").then(e=>e.at),__vite__mapDeps([0,1,2,3,4])).then(e=>({default:e.MonacoFileViewer})));function _e(e){return e?/\.(md|markdown|mdown|mkdn)$/i.test(e):!1}const De=e=>{const[E,L]=K(""),{isDark:q}=J(),[N,M]=K(!1);let b;P(()=>{e.browserPath(),L("")});const H=$(()=>[...e.browserEntries()||[]].sort((i,d)=>{const l=i.type==="directory"?0:1,t=d.type==="directory"?0:1;return l!==t?l-t:String(i.name||"").localeCompare(String(d.name||""))})),W=$(()=>E().trim().toLowerCase()),k=$(()=>{const n=W(),i=H();return n?i.filter(d=>String(d.name||"").toLowerCase().includes(n)):i}),y=()=>e.browserLoading()&&e.browserEntries()===null,j=()=>W()?e.t("instanceShell.filesShell.search.empty"):e.t("instanceShell.filesShell.listEmpty"),_=$(()=>_e(e.browserSelectedPath())),S=$(()=>_()&&N());P(()=>{_()||M(!1)});const T=()=>{const n=e.browserSelectedContent();n!=null&&e.onSave(n)},B=async(n,i)=>{i==null||i.stopPropagation();const d=await ie(n);se({message:d?e.t("instanceShell.filesShell.toast.copyPathSuccess"):e.t("instanceShell.filesShell.toast.copyPathError"),variant:d?"success":"error"})};P(()=>{S()&&requestAnimationFrame(()=>b==null?void 0:b.focus())});const D=()=>[(()=>{var n=ce(),i=n.firstChild,d=i.firstChild,l=d.nextSibling;return s(d,o(re,{class:"w-4 h-4"})),l.$$input=t=>L(t.currentTarget.value),w(t=>{var a=e.t("instanceShell.filesShell.search.placeholder"),r=e.t("instanceShell.filesShell.search.ariaLabel");return a!==t.e&&u(l,"placeholder",t.e=a),r!==t.t&&u(l,"aria-label",t.t=r),t},{e:void 0,t:void 0}),w(()=>l.value=E()),n})(),(()=>{var n=de(),i=n.firstChild,d=i.nextSibling;return s(i,()=>e.t("instanceShell.filesShell.fileListTitle")),s(d,()=>k().length),n})(),o(g,{get when(){return e.parentPath()},children:n=>(()=>{var i=he(),d=i.firstChild,l=d.firstChild;return i.$$click=()=>e.onLoadEntries(n()),w(()=>u(l,"title",n())),i})()}),o(g,{get when(){return y()},get children(){var n=V();return s(n,()=>e.t("instanceInfo.loading")),n}}),o(g,{get when(){return m(()=>!e.browserError()&&!y())()&&k().length>0},get fallback(){return m(()=>!y())()?m(()=>!!e.browserError())()?(()=>{var n=ue();return s(n,()=>e.browserError()),n})():(()=>{var n=V();return s(n,j),n})():void 0},get children(){return o(ee,{get each(){return k()},children:n=>(()=>{var i=ve(),d=i.firstChild,l=d.firstChild,t=l.firstChild,a=l.nextSibling,r=a.firstChild,c=r.firstChild,f=r.nextSibling;return i.$$click=()=>{if(n.type==="directory"){e.onLoadEntries(n.path);return}e.onRequestOpenFile(n.path)},s(t,()=>n.name),s(c,()=>n.type),f.$$click=v=>void B(n.path,v),s(f,o(ae,{class:"w-3 h-3"})),w(v=>{var F=`file-list-item ${e.browserSelectedPath()===n.path?"file-list-item-active":""}`,z=n.path,R=n.path,I=e.t("instanceShell.filesShell.actions.copyPath"),A=e.t("instanceShell.filesShell.actions.copyPath");return F!==v.e&&C(i,v.e=F),z!==v.t&&u(i,"title",v.t=z),R!==v.a&&u(l,"title",v.a=R),I!==v.o&&u(f,"title",v.o=I),A!==v.i&&u(f,"aria-label",v.i=A),v},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0}),i})()})}})],G=n=>{!(n.ctrlKey||n.metaKey)||n.key.toLowerCase()!=="s"||e.browserSelectedSaving()||!e.browserSelectedDirty()||(n.preventDefault(),T())};return m(()=>{const n=()=>e.browserSelectedPath()||e.browserPath(),i=()=>y()?e.t("instanceInfo.loading"):e.t("instanceShell.filesShell.viewerEmpty"),d=()=>(()=>{var l=fe(),t=l.firstChild;return s(t,o(g,{get when(){return e.browserSelectedLoading()},get fallback(){return o(g,{get when(){return e.browserSelectedError()},get fallback(){return o(g,{get when(){return m(()=>!!(e.browserSelectedPath()&&e.browserSelectedContent()!==null))()?{path:e.browserSelectedPath(),content:e.browserSelectedContent()}:null},get fallback(){return(()=>{var a=x(),r=a.firstChild;return s(r,i),a})()},children:a=>o(g,{get when(){return S()},get fallback(){return o(Z,{get fallback(){return(()=>{var r=x(),c=r.firstChild;return s(c,()=>e.t("instanceInfo.loading")),r})()},get children(){return o(ye,{get scopeKey(){return e.scopeKey()},get path(){return a().path},get content(){return a().content},get wordWrap(){return e.wordWrapMode()},get onSave(){return e.onSave},get onContentChange(){return e.onContentChange}})}})},get children(){var r=ge();r.$$mousedown=()=>b==null?void 0:b.focus(),r.$$keydown=G;var c=b;return typeof c=="function"?U(c,r):b=r,s(r,o(ne,{get part(){return{type:"text",text:a().content}},get isDark(){return q()},escapeRawHtml:!0})),r}})})},children:a=>(()=>{var r=x(),c=r.firstChild;return s(c,a),r})()})},get children(){var a=x(),r=a.firstChild;return s(r,()=>e.t("instanceInfo.loading")),a}})),w(()=>C(t,S()?"file-viewer-content":"file-viewer-content file-viewer-content--monaco")),l})();return o(te,{get header(){return[(()=>{var l=be(),t=l.firstChild,a=t.firstChild,r=a.firstChild;return s(r,n),s(l,o(g,{get when(){return e.browserLoading()},get children(){var c=we();return s(c,()=>e.t("instanceInfo.loading")),c}}),null),s(l,o(g,{get when(){return e.browserError()},children:c=>(()=>{var f=$e();return s(f,c),f})()}),null),w(()=>u(a,"title",n())),l})(),(()=>{var l=Se();return l.$$click=()=>_()&&M(t=>!t),s(l,(()=>{var t=m(()=>!!S());return()=>t()?e.t("instanceShell.filesShell.showSource"):e.t("instanceShell.filesShell.previewMarkdown")})()),w(t=>{var a=`file-viewer-toolbar-button${S()?" active":""}`,r=!_();return a!==t.e&&C(l,t.e=a),r!==t.t&&(l.disabled=t.t=r),t},{e:void 0,t:void 0}),l})(),(()=>{var l=me();return l.$$click=()=>e.onWordWrapModeChange(e.wordWrapMode()==="on"?"off":"on"),s(l,o(oe,{class:"h-4 w-4"})),w(t=>{var a=`file-viewer-toolbar-icon-button${e.wordWrapMode()==="on"?" active":""}`,r=e.wordWrapMode()==="on"?e.t("instanceShell.filesShell.disableWordWrap"):e.t("instanceShell.filesShell.enableWordWrap"),c=e.wordWrapMode()==="on"?e.t("instanceShell.filesShell.disableWordWrap"):e.t("instanceShell.filesShell.enableWordWrap"),f=S();return a!==t.e&&C(l,t.e=a),r!==t.t&&u(l,"title",t.t=r),c!==t.a&&u(l,"aria-label",t.a=c),f!==t.o&&(l.disabled=t.o=f),t},{e:void 0,t:void 0,a:void 0,o:void 0}),l})(),(()=>{var l=Q();return l.$$click=T,s(l,o(g,{get when(){return e.browserSelectedSaving()},get fallback(){return o(le,{class:"h-4 w-4"})},get children(){return o(O,{class:"h-4 w-4 animate-spin"})}})),w(t=>{var a=e.t("instanceShell.rightPanel.actions.save")||"Save (Ctrl+S)",r=e.t("instanceShell.rightPanel.actions.save")||"Save",c=e.browserSelectedSaving()||!e.browserSelectedDirty();return a!==t.e&&u(l,"title",t.e=a),r!==t.t&&u(l,"aria-label",t.t=r),c!==t.a&&(l.disabled=t.a=c),t},{e:void 0,t:void 0,a:void 0}),l})(),(()=>{var l=Q();return l.$$click=()=>e.onRefresh(),s(l,o(O,{get class(){return`h-4 w-4${e.browserLoading()?" animate-spin":""}`}})),w(t=>{var a=e.t("instanceShell.rightPanel.actions.refresh"),r=e.t("instanceShell.rightPanel.actions.refresh"),c=e.browserLoading();return a!==t.e&&u(l,"title",t.e=a),r!==t.t&&u(l,"aria-label",t.t=r),c!==t.a&&(l.disabled=t.a=c),t},{e:void 0,t:void 0,a:void 0}),l})()]},list:{panel:()=>o(D,{}),overlay:()=>o(D,{})},get viewer(){return d()},get listOpen(){return e.listOpen()},get onToggleList(){return e.onToggleList},get splitWidth(){return e.splitWidth()},get onResizeMouseDown(){return e.onResizeMouseDown},get onResizeTouchStart(){return e.onResizeTouchStart},get isPhoneLayout(){return e.isPhoneLayout()},get overlayAriaLabel(){return e.t("instanceShell.rightPanel.tabs.files")}})})};Y(["input","click","keydown","mousedown"]);export{De as default};
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/monaco-viewer-CiFg18Ak.js","assets/git-diff-vendor-CYS3ApzA.js","assets/fast-diff-vendor-DgdwVvTQ.js","assets/highlight-vendor-8FKMu9os.js","assets/git-diff-vendor-HAZkIolJ.css"])))=>i.map(i=>d[i]);
2
+ import{a8 as G,m,t as h,i as s,d as u,a as C,u as J,_ as X,f as Y}from"./monaco-viewer-CiFg18Ak.js";import{d as K,b as P,c as $,n as o,S as g,a as w,z as Z,A as p,F as ee}from"./git-diff-vendor-CYS3ApzA.js";import{S as te}from"./SplitFilePanel-B5nrgBs3.js";import{R as V,Q as le,M as ne,T as re,C as ae,e as ie,U as se}from"./main-BEYytlgD.js";import{W as oe}from"./wrap-text-CS5K8Uhi.js";import"./fast-diff-vendor-DgdwVvTQ.js";import"./highlight-vendor-8FKMu9os.js";import"./index-D0xuNxlo.js";var ce=h('<div class="px-2 py-2 border-b border-base"><div class=selector-input-group><div class="flex items-center gap-2 px-3 text-muted"></div><input type=text class=selector-input>'),de=h("<div class=file-list-header><span class=file-list-title></span><span class=file-list-count>"),O=h('<div class="p-3 text-xs text-secondary">'),he=h("<div class=file-list-item><div class=file-list-item-content><div class=file-list-item-path><span class=file-path-text>.."),ue=h('<div class="p-3 text-xs text-error">'),ve=h('<div><div class=file-list-item-content><div class=file-list-item-path><span class=file-path-text></span></div><div class="flex items-center gap-2 shrink-0"><div class=file-list-item-stats><span class="text-[10px] text-secondary"></span></div><button type=button class=git-change-row-action>'),x=h("<div class=file-viewer-empty><span class=file-viewer-empty-text>"),fe=h('<div class="file-viewer-panel flex-1"><div>'),ge=h('<div class="h-full outline-none"tabindex=0>'),we=h("<span>"),be=h("<div class=files-tab-stats><span class=files-tab-stat><span class=files-tab-selected-path><span class=file-path-text>"),Se=h("<button type=button style=margin-inline-start:auto>"),me=h("<button type=button>"),Q=h("<button type=button class=files-header-icon-button>"),$e=h("<span class=text-error>");const ye=p(()=>X(()=>import("./monaco-viewer-CiFg18Ak.js").then(e=>e.at),__vite__mapDeps([0,1,2,3,4])).then(e=>({default:e.MonacoFileViewer})));function _e(e){return e?/\.(md|markdown|mdown|mkdn)$/i.test(e):!1}const De=e=>{const[E,L]=K(""),{isDark:q}=G(),[N,M]=K(!1);let b;P(()=>{e.browserPath(),L("")});const H=$(()=>[...e.browserEntries()||[]].sort((i,d)=>{const l=i.type==="directory"?0:1,t=d.type==="directory"?0:1;return l!==t?l-t:String(i.name||"").localeCompare(String(d.name||""))})),W=$(()=>E().trim().toLowerCase()),k=$(()=>{const n=W(),i=H();return n?i.filter(d=>String(d.name||"").toLowerCase().includes(n)):i}),y=()=>e.browserLoading()&&e.browserEntries()===null,U=()=>W()?e.t("instanceShell.filesShell.search.empty"):e.t("instanceShell.filesShell.listEmpty"),_=$(()=>_e(e.browserSelectedPath())),S=$(()=>_()&&N());P(()=>{_()||M(!1)});const T=()=>{const n=e.browserSelectedContent();n!=null&&e.onSave(n)},j=async(n,i)=>{i==null||i.stopPropagation();const d=await ie(n);se({message:d?e.t("instanceShell.filesShell.toast.copyPathSuccess"):e.t("instanceShell.filesShell.toast.copyPathError"),variant:d?"success":"error"})};P(()=>{S()&&requestAnimationFrame(()=>b==null?void 0:b.focus())});const D=()=>[(()=>{var n=ce(),i=n.firstChild,d=i.firstChild,l=d.nextSibling;return s(d,o(re,{class:"w-4 h-4"})),l.$$input=t=>L(t.currentTarget.value),w(t=>{var a=e.t("instanceShell.filesShell.search.placeholder"),r=e.t("instanceShell.filesShell.search.ariaLabel");return a!==t.e&&u(l,"placeholder",t.e=a),r!==t.t&&u(l,"aria-label",t.t=r),t},{e:void 0,t:void 0}),w(()=>l.value=E()),n})(),(()=>{var n=de(),i=n.firstChild,d=i.nextSibling;return s(i,()=>e.t("instanceShell.filesShell.fileListTitle")),s(d,()=>k().length),n})(),o(g,{get when(){return e.parentPath()},children:n=>(()=>{var i=he(),d=i.firstChild,l=d.firstChild;return i.$$click=()=>e.onLoadEntries(n()),w(()=>u(l,"title",n())),i})()}),o(g,{get when(){return y()},get children(){var n=O();return s(n,()=>e.t("instanceInfo.loading")),n}}),o(g,{get when(){return m(()=>!e.browserError()&&!y())()&&k().length>0},get fallback(){return m(()=>!y())()?m(()=>!!e.browserError())()?(()=>{var n=ue();return s(n,()=>e.browserError()),n})():(()=>{var n=O();return s(n,U),n})():void 0},get children(){return o(ee,{get each(){return k()},children:n=>(()=>{var i=ve(),d=i.firstChild,l=d.firstChild,t=l.firstChild,a=l.nextSibling,r=a.firstChild,c=r.firstChild,f=r.nextSibling;return i.$$click=()=>{if(n.type==="directory"){e.onLoadEntries(n.path);return}e.onRequestOpenFile(n.path)},s(t,()=>n.name),s(c,()=>n.type),f.$$click=v=>void j(n.path,v),s(f,o(ae,{class:"w-3 h-3"})),w(v=>{var F=`file-list-item ${e.browserSelectedPath()===n.path?"file-list-item-active":""}`,z=n.path,R=n.path,I=e.t("instanceShell.filesShell.actions.copyPath"),A=e.t("instanceShell.filesShell.actions.copyPath");return F!==v.e&&C(i,v.e=F),z!==v.t&&u(i,"title",v.t=z),R!==v.a&&u(l,"title",v.a=R),I!==v.o&&u(f,"title",v.o=I),A!==v.i&&u(f,"aria-label",v.i=A),v},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0}),i})()})}})],B=n=>{!(n.ctrlKey||n.metaKey)||n.key.toLowerCase()!=="s"||e.browserSelectedSaving()||!e.browserSelectedDirty()||(n.preventDefault(),T())};return m(()=>{const n=()=>e.browserSelectedPath()||e.browserPath(),i=()=>y()?e.t("instanceInfo.loading"):e.t("instanceShell.filesShell.viewerEmpty"),d=()=>(()=>{var l=fe(),t=l.firstChild;return s(t,o(g,{get when(){return e.browserSelectedLoading()},get fallback(){return o(g,{get when(){return e.browserSelectedError()},get fallback(){return o(g,{get when(){return m(()=>!!(e.browserSelectedPath()&&e.browserSelectedContent()!==null))()?{path:e.browserSelectedPath(),content:e.browserSelectedContent()}:null},get fallback(){return(()=>{var a=x(),r=a.firstChild;return s(r,i),a})()},children:a=>o(g,{get when(){return S()},get fallback(){return o(Z,{get fallback(){return(()=>{var r=x(),c=r.firstChild;return s(c,()=>e.t("instanceInfo.loading")),r})()},get children(){return o(ye,{get scopeKey(){return e.scopeKey()},get path(){return a().path},get content(){return a().content},get wordWrap(){return e.wordWrapMode()},get onSave(){return e.onSave},get onContentChange(){return e.onContentChange}})}})},get children(){var r=ge();r.$$mousedown=()=>b==null?void 0:b.focus(),r.$$keydown=B;var c=b;return typeof c=="function"?J(c,r):b=r,s(r,o(ne,{get part(){return{type:"text",text:a().content}},get isDark(){return q()},escapeRawHtml:!0})),r}})})},children:a=>(()=>{var r=x(),c=r.firstChild;return s(c,a),r})()})},get children(){var a=x(),r=a.firstChild;return s(r,()=>e.t("instanceInfo.loading")),a}})),w(()=>C(t,S()?"file-viewer-content":"file-viewer-content file-viewer-content--monaco")),l})();return o(te,{get header(){return[(()=>{var l=be(),t=l.firstChild,a=t.firstChild,r=a.firstChild;return s(r,n),s(l,o(g,{get when(){return e.browserLoading()},get children(){var c=we();return s(c,()=>e.t("instanceInfo.loading")),c}}),null),s(l,o(g,{get when(){return e.browserError()},children:c=>(()=>{var f=$e();return s(f,c),f})()}),null),w(()=>u(a,"title",n())),l})(),(()=>{var l=Se();return l.$$click=()=>_()&&M(t=>!t),s(l,(()=>{var t=m(()=>!!S());return()=>t()?e.t("instanceShell.filesShell.showSource"):e.t("instanceShell.filesShell.previewMarkdown")})()),w(t=>{var a=`file-viewer-toolbar-button${S()?" active":""}`,r=!_();return a!==t.e&&C(l,t.e=a),r!==t.t&&(l.disabled=t.t=r),t},{e:void 0,t:void 0}),l})(),(()=>{var l=me();return l.$$click=()=>e.onWordWrapModeChange(e.wordWrapMode()==="on"?"off":"on"),s(l,o(oe,{class:"h-4 w-4"})),w(t=>{var a=`file-viewer-toolbar-icon-button${e.wordWrapMode()==="on"?" active":""}`,r=e.wordWrapMode()==="on"?e.t("instanceShell.filesShell.disableWordWrap"):e.t("instanceShell.filesShell.enableWordWrap"),c=e.wordWrapMode()==="on"?e.t("instanceShell.filesShell.disableWordWrap"):e.t("instanceShell.filesShell.enableWordWrap"),f=S();return a!==t.e&&C(l,t.e=a),r!==t.t&&u(l,"title",t.t=r),c!==t.a&&u(l,"aria-label",t.a=c),f!==t.o&&(l.disabled=t.o=f),t},{e:void 0,t:void 0,a:void 0,o:void 0}),l})(),(()=>{var l=Q();return l.$$click=T,s(l,o(g,{get when(){return e.browserSelectedSaving()},get fallback(){return o(le,{class:"h-4 w-4"})},get children(){return o(V,{class:"h-4 w-4 animate-spin"})}})),w(t=>{var a=e.t("instanceShell.rightPanel.actions.save")||"Save (Ctrl+S)",r=e.t("instanceShell.rightPanel.actions.save")||"Save",c=e.browserSelectedSaving()||!e.browserSelectedDirty();return a!==t.e&&u(l,"title",t.e=a),r!==t.t&&u(l,"aria-label",t.t=r),c!==t.a&&(l.disabled=t.a=c),t},{e:void 0,t:void 0,a:void 0}),l})(),(()=>{var l=Q();return l.$$click=()=>e.onRefresh(),s(l,o(V,{get class(){return`h-4 w-4${e.browserLoading()?" animate-spin":""}`}})),w(t=>{var a=e.t("instanceShell.rightPanel.actions.refresh"),r=e.t("instanceShell.rightPanel.actions.refresh"),c=e.browserLoading();return a!==t.e&&u(l,"title",t.e=a),r!==t.t&&u(l,"aria-label",t.t=r),c!==t.a&&(l.disabled=t.a=c),t},{e:void 0,t:void 0,a:void 0}),l})()]},list:{panel:()=>o(D,{}),overlay:()=>o(D,{})},get viewer(){return d()},get listOpen(){return e.listOpen()},get onToggleList(){return e.onToggleList},get splitWidth(){return e.splitWidth()},get onResizeMouseDown(){return e.onResizeMouseDown},get onResizeTouchStart(){return e.onResizeTouchStart},get isPhoneLayout(){return e.isPhoneLayout()},get overlayAriaLabel(){return e.t("instanceShell.rightPanel.tabs.files")}})})};Y(["input","click","keydown","mousedown"]);export{De as default};
@@ -1,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/monaco-viewer-DM35aobI.js","assets/git-diff-vendor-CYS3ApzA.js","assets/fast-diff-vendor-DgdwVvTQ.js","assets/highlight-vendor-8FKMu9os.js","assets/git-diff-vendor-HAZkIolJ.css"])))=>i.map(i=>d[i]);
2
- import{t as u,i as n,m as D,d as g,a as q,f as ae,h as ee,_ as re}from"./monaco-viewer-DM35aobI.js";import{n as i,m as ce,a as P,c as b,S as k,F as te,z as oe,A as de}from"./git-diff-vendor-CYS3ApzA.js";import{u as he}from"./index-D8WMdSS9.js";import{I as ge,S as ue,G as fe,H as ve,R as me,J as ne,K as ie,N as be}from"./main-B9uXiXu7.js";import{A as $e}from"./align-justify-Ce1uZY4E.js";import{W as Ce}from"./wrap-text-D7C2RpdK.js";import{S as we}from"./SplitFilePanel-C1aKE1hq.js";import"./fast-diff-vendor-DgdwVvTQ.js";import"./highlight-vendor-8FKMu9os.js";const _e=[["path",{d:"M12 22v-6",key:"6o8u61"}],["path",{d:"M12 8V2",key:"1wkif3"}],["path",{d:"M4 12H2",key:"rhcxmi"}],["path",{d:"M10 12H8",key:"s88cx1"}],["path",{d:"M16 12h-2",key:"10asgb"}],["path",{d:"M22 12h-2",key:"14jgyd"}],["path",{d:"m15 19-3 3-3-3",key:"11eu04"}],["path",{d:"m15 5-3-3-3 3",key:"itvq4r"}]],Se=e=>i(ge,ce(e,{name:"UnfoldVertical",iconNode:_e}));var ye=u("<div class=file-viewer-toolbar><button type=button class=file-viewer-toolbar-icon-button></button><button type=button class=file-viewer-toolbar-icon-button></button><button type=button>");const xe=e=>{const{t:S}=he(),L=()=>e.viewMode==="split"?"unified":"split",V=()=>e.contextMode==="collapsed"?"expanded":"collapsed",O=()=>e.wordWrapMode==="on"?"off":"on",w=()=>L()==="split"?S("instanceShell.diff.switchToSplit"):S("instanceShell.diff.switchToUnified"),K=()=>V()==="collapsed"?S("instanceShell.diff.hideUnchanged"):S("instanceShell.diff.showFull"),B=()=>O()==="on"?S("instanceShell.diff.enableWordWrap"):S("instanceShell.diff.disableWordWrap");return(()=>{var U=ye(),T=U.firstChild,E=T.nextSibling,I=E.nextSibling;return T.$$click=()=>e.onViewModeChange(L()),n(T,(()=>{var c=D(()=>L()==="split");return()=>c()?i(ue,{class:"h-4 w-4","aria-hidden":"true"}):i($e,{class:"h-4 w-4","aria-hidden":"true"})})()),E.$$click=()=>e.onContextModeChange(V()),n(E,(()=>{var c=D(()=>V()==="collapsed");return()=>c()?i(fe,{class:"h-4 w-4","aria-hidden":"true"}):i(Se,{class:"h-4 w-4","aria-hidden":"true"})})()),I.$$click=()=>e.onWordWrapModeChange(O()),n(I,i(Ce,{class:"h-4 w-4","aria-hidden":"true"})),P(c=>{var N=w(),o=w(),d=K(),y=K(),x=`file-viewer-toolbar-icon-button${e.wordWrapMode==="on"?" active":""}`,W=B(),G=B();return N!==c.e&&g(T,"aria-label",c.e=N),o!==c.t&&g(T,"title",c.t=o),d!==c.a&&g(E,"aria-label",c.a=d),y!==c.o&&g(E,"title",c.o=y),x!==c.i&&q(I,c.i=x),W!==c.n&&g(I,"aria-label",c.n=W),G!==c.s&&g(I,"title",c.s=G),c},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0,s:void 0}),U})()};ae(["click"]);var H=u("<div class=file-viewer-empty><span class=file-viewer-empty-text>"),Me=u('<div class="file-viewer-panel flex-1"><div class="file-viewer-content file-viewer-content--monaco">'),ke=u('<div class="p-3 text-xs text-secondary">'),Ie=u('<span class="git-change-row-action-bar git-change-row-action-bar-vertical">'),We=u('<div><div class=file-list-item-content><div class=file-list-item-path><span class=file-path-text></span></div><div class=git-change-list-item-right><div class=file-list-item-stats><span class=file-list-item-additions>+</span><span class=file-list-item-deletions>-</span></div></div></div><div class=git-change-list-item-actions-zone><div class=git-change-list-item-actions><button type=button class=git-change-row-action><span aria-hidden=true><span class="git-change-row-action-bar git-change-row-action-bar-horizontal">'),Le=u("<div class=git-change-section-items>"),Ve=u("<div class=git-change-section><button type=button class=git-change-section-header><span class=git-change-section-header-main><span class=git-change-section-chevron></span><span class=git-change-section-title></span></span><span class=git-change-section-count>"),Te=u('<div class=git-change-section-items><div class=git-change-commit-box><div class=git-change-commit-input-wrap><textarea class=git-change-commit-input rows=1></textarea><button type=button class="git-change-commit-button git-change-commit-button-overlay">'),Ee=u("<div class=git-change-sections><div class=git-change-section><button type=button class=git-change-section-header><span class=git-change-section-header-main><span class=git-change-section-chevron></span><span class=git-change-section-title-row><span class=git-change-section-title></span></span></span><span class=git-change-section-count>"),Ae=u('<span class="status-indicator session-status-list worktree-indicator git-change-section-badge"><span class=worktree-indicator-label>'),Pe=u("<span class=files-tab-selected-path><span class=file-path-text>"),Re=u('<div class=files-tab-stats style="flex:0 0 auto"><span class="files-tab-stat files-tab-stat-additions"><span class=files-tab-stat-value>+</span></span><span class="files-tab-stat files-tab-stat-deletions"><span class=files-tab-stat-value>-'),ze=u("<button type=button class=files-header-icon-button style=margin-left:auto>"),De=u("<span class=text-error>");const Be=de(()=>re(()=>import("./monaco-viewer-DM35aobI.js").then(e=>e.au),__vite__mapDeps([0,1,2,3,4])).then(e=>({default:e.MonacoDiffViewer}))),je=e=>{const S=b(()=>e.activeSessionId()),L=b(()=>!!(S()&&S()!=="info")),V=b(()=>L()?e.entries():null),O=b(()=>{const o=V();return Array.isArray(o)?[...o].sort((d,y)=>String(d.path||"").localeCompare(String(y.path||""))):[]}),w=b(()=>ve(O())),K=b(()=>w().reduce((o,d)=>(o.additions+=typeof d.additions=="number"?d.additions:0,o.deletions+=typeof d.deletions=="number"?d.deletions:0,o),{additions:0,deletions:0})),B=b(()=>w().filter(o=>o.section==="staged")),U=b(()=>w().filter(o=>o.section==="unstaged")),T=b(()=>B().length>0&&e.commitMessage().trim().length>0&&!e.commitSubmitting()),E=b(()=>{const o=w(),d=e.selectedItemId(),y=e.mostChangedItemId(),x=o.find(W=>W.id===d)||(y?o.find(W=>W.id===y):void 0);return(x==null?void 0:x.entry)??null}),I=b(()=>L()?V()===null?e.t("instanceShell.gitChanges.loading"):w().length===0?e.t("instanceShell.gitChanges.empty"):e.t("instanceShell.filesShell.viewerEmpty"):e.t("instanceShell.gitChanges.noSessionSelected")),c=b(()=>e.selectedError()===e.t("instanceShell.gitChanges.binaryViewer"));return D(()=>{const o=K(),d=E(),y=w(),x=B(),W=U(),G=()=>(()=>{var t=Me(),r=t.firstChild;return n(r,i(k,{get when(){return e.selectedLoading()},get fallback(){return i(k,{get when(){return e.selectedError()},get fallback(){return i(k,{get when(){return D(()=>!!(d&&e.selectedBefore()!==null&&e.selectedAfter()!==null))()?{path:d.path,before:e.selectedBefore(),after:e.selectedAfter()}:null},get fallback(){return(()=>{var a=H(),s=a.firstChild;return n(s,I),a})()},children:a=>i(oe,{get fallback(){return(()=>{var s=H(),l=s.firstChild;return n(l,()=>e.t("instanceInfo.loading")),s})()},get children(){return i(Be,{get scopeKey(){return e.scopeKey()},get path(){return String(a().path||"")},get before(){return String(a().before||"")},get after(){return String(a().after||"")},get viewMode(){return e.diffViewMode()},get contextMode(){return e.diffContextMode()},get wordWrap(){return e.diffWordWrapMode()},get insertContextLabel(){return e.t("instanceShell.gitChanges.actions.insertContext")},get onRequestInsertContext(){return c()?void 0:s=>{const l=e.selectedItemId();if(!l)return;const f=w().find(v=>v.id===l);f&&e.onInsertContext(f,s)}}})}})})},children:a=>(()=>{var s=H(),l=s.firstChild;return n(l,a),s})()})},get children(){var a=H(),s=a.firstChild;return n(s,()=>e.t("instanceInfo.loading")),a}})),t})(),le=()=>(()=>{var t=ke();return n(t,I),t})(),J=t=>{const r=b(()=>e.selectedBulkItemIds().has(t.id)),a=t.section==="staged"?e.t("instanceShell.gitChanges.actions.unstage"):e.t("instanceShell.gitChanges.actions.stage"),s=()=>{t.section==="staged"?e.onUnstageFile(t):e.onStageFile(t)};return(()=>{var l=We(),f=l.firstChild,v=f.firstChild,R=v.firstChild,$=v.nextSibling,_=$.firstChild,C=_.firstChild;C.firstChild;var M=C.nextSibling;M.firstChild;var F=f.nextSibling,m=F.firstChild,A=m.firstChild,z=A.firstChild;return z.firstChild,l.$$click=h=>e.onRowClick(t,h),l.$$mousedown=h=>{(h.shiftKey||h.ctrlKey||h.metaKey)&&h.preventDefault()},n(R,()=>t.path),n(C,()=>t.additions,null),n(M,()=>t.deletions,null),A.$$click=h=>{h.stopPropagation(),s()},g(A,"title",a),g(A,"aria-label",a),n(z,i(k,{get when(){return t.section!=="staged"},get children(){return Ie()}}),null),P(h=>{var Q=`file-list-item git-change-list-item ${e.selectedItemId()===t.id?"file-list-item-active":""} ${r()?"git-change-list-item-bulk-selected":""}`,X=t.path,Y=t.path,Z=t.path,p=`git-change-row-action-glyph ${t.section==="staged"?"git-change-row-action-glyph-minus":"git-change-row-action-glyph-plus"}`;return Q!==h.e&&q(l,h.e=Q),X!==h.t&&g(l,"title",h.t=X),Y!==h.a&&g(f,"title",h.a=Y),Z!==h.o&&g(v,"title",h.o=Z),p!==h.i&&q(z,h.i=p),h},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0}),l})()},se=(t,r,a,s)=>(()=>{var l=Ve(),f=l.firstChild,v=f.firstChild,R=v.firstChild,$=R.nextSibling,_=v.nextSibling;return ee(f,"click",s,!0),n(R,a?i(ne,{class:"h-3.5 w-3.5"}):i(ie,{class:"h-3.5 w-3.5"})),n($,t),n(_,()=>r.length),n(l,i(k,{when:a,get children(){var C=Le();return n(C,i(te,{each:r,children:M=>J(M)})),C}}),null),l})(),j=()=>i(k,{get when(){return y.length>0},get fallback(){return le()},get children(){var t=Ee(),r=t.firstChild,a=r.firstChild,s=a.firstChild,l=s.firstChild,f=l.nextSibling,v=f.firstChild,R=s.nextSibling;return ee(a,"click",e.onToggleStagedOpen,!0),n(l,(()=>{var $=D(()=>!!e.stagedOpen());return()=>$()?i(ne,{class:"h-3.5 w-3.5"}):i(ie,{class:"h-3.5 w-3.5"})})()),n(v,()=>e.t("instanceShell.gitChanges.sections.staged")),n(f,i(k,{get when(){return e.branchLabel()},children:$=>(()=>{var _=Ae(),C=_.firstChild;return n(_,i(be,{class:"w-3.5 h-3.5","aria-hidden":"true"}),C),n(C,$),P(()=>g(_,"title",`Branch: ${$()}`)),_})()}),null),n(R,()=>x.length),n(r,i(k,{get when(){return e.stagedOpen()},get children(){var $=Te(),_=$.firstChild,C=_.firstChild,M=C.firstChild,F=M.nextSibling;return M.$$input=m=>e.onCommitMessageInput(m.currentTarget.value),F.$$click=()=>e.onSubmitCommit(),n(F,(()=>{var m=D(()=>!!e.commitSubmitting());return()=>m()?e.t("instanceShell.gitChanges.commit.submitting"):e.t("instanceShell.gitChanges.commit.submit")})()),n($,i(te,{each:x,children:m=>J(m)}),null),P(m=>{var A=e.t("instanceShell.gitChanges.commit.placeholder"),z=!T();return A!==m.e&&g(M,"placeholder",m.e=A),z!==m.t&&(F.disabled=m.t=z),m},{e:void 0,t:void 0}),P(()=>M.value=e.commitMessage()),$}}),null),n(t,()=>se(e.t("instanceShell.gitChanges.sections.unstaged"),W,e.unstagedOpen(),e.onToggleUnstagedOpen),null),t}});return i(we,{get header(){return[(()=>{var t=Pe(),r=t.firstChild;return n(r,()=>(d==null?void 0:d.path)||e.t("instanceShell.rightPanel.tabs.gitChanges")),P(()=>g(t,"title",(d==null?void 0:d.path)||e.t("instanceShell.rightPanel.tabs.gitChanges"))),t})(),(()=>{var t=Re(),r=t.firstChild,a=r.firstChild;a.firstChild;var s=r.nextSibling,l=s.firstChild;return l.firstChild,n(a,()=>o.additions,null),n(l,()=>o.deletions,null),n(t,i(k,{get when(){return e.statusError()},children:f=>(()=>{var v=De();return n(v,f),v})()}),null),t})(),(()=>{var t=ze();return t.$$click=()=>e.onRefresh(),n(t,i(me,{get class(){return`h-4 w-4${e.statusLoading()?" animate-spin":""}`}})),P(r=>{var a=e.t("instanceShell.rightPanel.actions.refresh"),s=e.t("instanceShell.rightPanel.actions.refresh"),l=!L()||e.statusLoading()||V()===null;return a!==r.e&&g(t,"title",r.e=a),s!==r.t&&g(t,"aria-label",r.t=s),l!==r.a&&(t.disabled=r.a=l),r},{e:void 0,t:void 0,a:void 0}),t})(),i(xe,{get viewMode(){return e.diffViewMode()},get contextMode(){return e.diffContextMode()},get wordWrapMode(){return e.diffWordWrapMode()},get onViewModeChange(){return e.onViewModeChange},get onContextModeChange(){return e.onContextModeChange},get onWordWrapModeChange(){return e.onWordWrapModeChange}})]},list:{panel:j,overlay:j},get viewer(){return G()},get listOpen(){return e.listOpen()},get onToggleList(){return e.onToggleList},get splitWidth(){return e.splitWidth()},get onResizeMouseDown(){return e.onResizeMouseDown},get onResizeTouchStart(){return e.onResizeTouchStart},get isPhoneLayout(){return e.isPhoneLayout()},get overlayAriaLabel(){return e.t("instanceShell.rightPanel.tabs.gitChanges")}})})};ae(["mousedown","click","input"]);export{je as default};
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/monaco-viewer-CiFg18Ak.js","assets/git-diff-vendor-CYS3ApzA.js","assets/fast-diff-vendor-DgdwVvTQ.js","assets/highlight-vendor-8FKMu9os.js","assets/git-diff-vendor-HAZkIolJ.css"])))=>i.map(i=>d[i]);
2
+ import{t as u,i as n,m as D,d as g,a as q,f as ae,h as ee,_ as re}from"./monaco-viewer-CiFg18Ak.js";import{n as i,m as ce,a as P,c as b,S as k,F as te,z as oe,A as de}from"./git-diff-vendor-CYS3ApzA.js";import{u as he}from"./index-D0xuNxlo.js";import{I as ge,S as ue,H as fe,J as ve,R as me,K as ne,N as ie,O as be}from"./main-BEYytlgD.js";import{A as $e}from"./align-justify-CKDczyVy.js";import{W as Ce}from"./wrap-text-CS5K8Uhi.js";import{S as we}from"./SplitFilePanel-B5nrgBs3.js";import"./fast-diff-vendor-DgdwVvTQ.js";import"./highlight-vendor-8FKMu9os.js";const _e=[["path",{d:"M12 22v-6",key:"6o8u61"}],["path",{d:"M12 8V2",key:"1wkif3"}],["path",{d:"M4 12H2",key:"rhcxmi"}],["path",{d:"M10 12H8",key:"s88cx1"}],["path",{d:"M16 12h-2",key:"10asgb"}],["path",{d:"M22 12h-2",key:"14jgyd"}],["path",{d:"m15 19-3 3-3-3",key:"11eu04"}],["path",{d:"m15 5-3-3-3 3",key:"itvq4r"}]],Se=e=>i(ge,ce(e,{name:"UnfoldVertical",iconNode:_e}));var ye=u("<div class=file-viewer-toolbar><button type=button class=file-viewer-toolbar-icon-button></button><button type=button class=file-viewer-toolbar-icon-button></button><button type=button>");const xe=e=>{const{t:S}=he(),L=()=>e.viewMode==="split"?"unified":"split",V=()=>e.contextMode==="collapsed"?"expanded":"collapsed",F=()=>e.wordWrapMode==="on"?"off":"on",w=()=>L()==="split"?S("instanceShell.diff.switchToSplit"):S("instanceShell.diff.switchToUnified"),K=()=>V()==="collapsed"?S("instanceShell.diff.hideUnchanged"):S("instanceShell.diff.showFull"),O=()=>F()==="on"?S("instanceShell.diff.enableWordWrap"):S("instanceShell.diff.disableWordWrap");return(()=>{var U=ye(),T=U.firstChild,E=T.nextSibling,I=E.nextSibling;return T.$$click=()=>e.onViewModeChange(L()),n(T,(()=>{var c=D(()=>L()==="split");return()=>c()?i(ue,{class:"h-4 w-4","aria-hidden":"true"}):i($e,{class:"h-4 w-4","aria-hidden":"true"})})()),E.$$click=()=>e.onContextModeChange(V()),n(E,(()=>{var c=D(()=>V()==="collapsed");return()=>c()?i(fe,{class:"h-4 w-4","aria-hidden":"true"}):i(Se,{class:"h-4 w-4","aria-hidden":"true"})})()),I.$$click=()=>e.onWordWrapModeChange(F()),n(I,i(Ce,{class:"h-4 w-4","aria-hidden":"true"})),P(c=>{var N=w(),o=w(),d=K(),y=K(),x=`file-viewer-toolbar-icon-button${e.wordWrapMode==="on"?" active":""}`,W=O(),G=O();return N!==c.e&&g(T,"aria-label",c.e=N),o!==c.t&&g(T,"title",c.t=o),d!==c.a&&g(E,"aria-label",c.a=d),y!==c.o&&g(E,"title",c.o=y),x!==c.i&&q(I,c.i=x),W!==c.n&&g(I,"aria-label",c.n=W),G!==c.s&&g(I,"title",c.s=G),c},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0,s:void 0}),U})()};ae(["click"]);var H=u("<div class=file-viewer-empty><span class=file-viewer-empty-text>"),Me=u('<div class="file-viewer-panel flex-1"><div class="file-viewer-content file-viewer-content--monaco">'),ke=u('<div class="p-3 text-xs text-secondary">'),Ie=u('<span class="git-change-row-action-bar git-change-row-action-bar-vertical">'),We=u('<div><div class=file-list-item-content><div class=file-list-item-path><span class=file-path-text></span></div><div class=git-change-list-item-right><div class=file-list-item-stats><span class=file-list-item-additions>+</span><span class=file-list-item-deletions>-</span></div></div></div><div class=git-change-list-item-actions-zone><div class=git-change-list-item-actions><button type=button class=git-change-row-action><span aria-hidden=true><span class="git-change-row-action-bar git-change-row-action-bar-horizontal">'),Le=u("<div class=git-change-section-items>"),Ve=u("<div class=git-change-section><button type=button class=git-change-section-header><span class=git-change-section-header-main><span class=git-change-section-chevron></span><span class=git-change-section-title></span></span><span class=git-change-section-count>"),Te=u('<div class=git-change-section-items><div class=git-change-commit-box><div class=git-change-commit-input-wrap><textarea class=git-change-commit-input rows=1></textarea><button type=button class="git-change-commit-button git-change-commit-button-overlay">'),Ee=u("<div class=git-change-sections><div class=git-change-section><button type=button class=git-change-section-header><span class=git-change-section-header-main><span class=git-change-section-chevron></span><span class=git-change-section-title-row><span class=git-change-section-title></span></span></span><span class=git-change-section-count>"),Ae=u('<span class="status-indicator session-status-list worktree-indicator git-change-section-badge"><span class=worktree-indicator-label>'),Pe=u("<span class=files-tab-selected-path><span class=file-path-text>"),Re=u('<div class=files-tab-stats style="flex:0 0 auto"><span class="files-tab-stat files-tab-stat-additions"><span class=files-tab-stat-value>+</span></span><span class="files-tab-stat files-tab-stat-deletions"><span class=files-tab-stat-value>-'),ze=u("<button type=button class=files-header-icon-button style=margin-left:auto>"),De=u("<span class=text-error>");const Oe=de(()=>re(()=>import("./monaco-viewer-CiFg18Ak.js").then(e=>e.au),__vite__mapDeps([0,1,2,3,4])).then(e=>({default:e.MonacoDiffViewer}))),je=e=>{const S=b(()=>e.activeSessionId()),L=b(()=>!!(S()&&S()!=="info")),V=b(()=>L()?e.entries():null),F=b(()=>{const o=V();return Array.isArray(o)?[...o].sort((d,y)=>String(d.path||"").localeCompare(String(y.path||""))):[]}),w=b(()=>ve(F())),K=b(()=>w().reduce((o,d)=>(o.additions+=typeof d.additions=="number"?d.additions:0,o.deletions+=typeof d.deletions=="number"?d.deletions:0,o),{additions:0,deletions:0})),O=b(()=>w().filter(o=>o.section==="staged")),U=b(()=>w().filter(o=>o.section==="unstaged")),T=b(()=>O().length>0&&e.commitMessage().trim().length>0&&!e.commitSubmitting()),E=b(()=>{const o=w(),d=e.selectedItemId(),y=e.mostChangedItemId(),x=o.find(W=>W.id===d)||(y?o.find(W=>W.id===y):void 0);return(x==null?void 0:x.entry)??null}),I=b(()=>L()?V()===null?e.t("instanceShell.gitChanges.loading"):w().length===0?e.t("instanceShell.gitChanges.empty"):e.t("instanceShell.filesShell.viewerEmpty"):e.t("instanceShell.gitChanges.noSessionSelected")),c=b(()=>e.selectedError()===e.t("instanceShell.gitChanges.binaryViewer"));return D(()=>{const o=K(),d=E(),y=w(),x=O(),W=U(),G=()=>(()=>{var t=Me(),r=t.firstChild;return n(r,i(k,{get when(){return e.selectedLoading()},get fallback(){return i(k,{get when(){return e.selectedError()},get fallback(){return i(k,{get when(){return D(()=>!!(d&&e.selectedBefore()!==null&&e.selectedAfter()!==null))()?{path:d.path,before:e.selectedBefore(),after:e.selectedAfter()}:null},get fallback(){return(()=>{var a=H(),s=a.firstChild;return n(s,I),a})()},children:a=>i(oe,{get fallback(){return(()=>{var s=H(),l=s.firstChild;return n(l,()=>e.t("instanceInfo.loading")),s})()},get children(){return i(Oe,{get scopeKey(){return e.scopeKey()},get path(){return String(a().path||"")},get before(){return String(a().before||"")},get after(){return String(a().after||"")},get viewMode(){return e.diffViewMode()},get contextMode(){return e.diffContextMode()},get wordWrap(){return e.diffWordWrapMode()},get insertContextLabel(){return e.t("instanceShell.gitChanges.actions.insertContext")},get onRequestInsertContext(){return c()?void 0:s=>{const l=e.selectedItemId();if(!l)return;const f=w().find(v=>v.id===l);f&&e.onInsertContext(f,s)}}})}})})},children:a=>(()=>{var s=H(),l=s.firstChild;return n(l,a),s})()})},get children(){var a=H(),s=a.firstChild;return n(s,()=>e.t("instanceInfo.loading")),a}})),t})(),le=()=>(()=>{var t=ke();return n(t,I),t})(),J=t=>{const r=b(()=>e.selectedBulkItemIds().has(t.id)),a=t.section==="staged"?e.t("instanceShell.gitChanges.actions.unstage"):e.t("instanceShell.gitChanges.actions.stage"),s=()=>{t.section==="staged"?e.onUnstageFile(t):e.onStageFile(t)};return(()=>{var l=We(),f=l.firstChild,v=f.firstChild,R=v.firstChild,$=v.nextSibling,_=$.firstChild,C=_.firstChild;C.firstChild;var M=C.nextSibling;M.firstChild;var B=f.nextSibling,m=B.firstChild,A=m.firstChild,z=A.firstChild;return z.firstChild,l.$$click=h=>e.onRowClick(t,h),l.$$mousedown=h=>{(h.shiftKey||h.ctrlKey||h.metaKey)&&h.preventDefault()},n(R,()=>t.path),n(C,()=>t.additions,null),n(M,()=>t.deletions,null),A.$$click=h=>{h.stopPropagation(),s()},g(A,"title",a),g(A,"aria-label",a),n(z,i(k,{get when(){return t.section!=="staged"},get children(){return Ie()}}),null),P(h=>{var Q=`file-list-item git-change-list-item ${e.selectedItemId()===t.id?"file-list-item-active":""} ${r()?"git-change-list-item-bulk-selected":""}`,X=t.path,Y=t.path,Z=t.path,p=`git-change-row-action-glyph ${t.section==="staged"?"git-change-row-action-glyph-minus":"git-change-row-action-glyph-plus"}`;return Q!==h.e&&q(l,h.e=Q),X!==h.t&&g(l,"title",h.t=X),Y!==h.a&&g(f,"title",h.a=Y),Z!==h.o&&g(v,"title",h.o=Z),p!==h.i&&q(z,h.i=p),h},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0}),l})()},se=(t,r,a,s)=>(()=>{var l=Ve(),f=l.firstChild,v=f.firstChild,R=v.firstChild,$=R.nextSibling,_=v.nextSibling;return ee(f,"click",s,!0),n(R,a?i(ne,{class:"h-3.5 w-3.5"}):i(ie,{class:"h-3.5 w-3.5"})),n($,t),n(_,()=>r.length),n(l,i(k,{when:a,get children(){var C=Le();return n(C,i(te,{each:r,children:M=>J(M)})),C}}),null),l})(),j=()=>i(k,{get when(){return y.length>0},get fallback(){return le()},get children(){var t=Ee(),r=t.firstChild,a=r.firstChild,s=a.firstChild,l=s.firstChild,f=l.nextSibling,v=f.firstChild,R=s.nextSibling;return ee(a,"click",e.onToggleStagedOpen,!0),n(l,(()=>{var $=D(()=>!!e.stagedOpen());return()=>$()?i(ne,{class:"h-3.5 w-3.5"}):i(ie,{class:"h-3.5 w-3.5"})})()),n(v,()=>e.t("instanceShell.gitChanges.sections.staged")),n(f,i(k,{get when(){return e.branchLabel()},children:$=>(()=>{var _=Ae(),C=_.firstChild;return n(_,i(be,{class:"w-3.5 h-3.5","aria-hidden":"true"}),C),n(C,$),P(()=>g(_,"title",`Branch: ${$()}`)),_})()}),null),n(R,()=>x.length),n(r,i(k,{get when(){return e.stagedOpen()},get children(){var $=Te(),_=$.firstChild,C=_.firstChild,M=C.firstChild,B=M.nextSibling;return M.$$input=m=>e.onCommitMessageInput(m.currentTarget.value),B.$$click=()=>e.onSubmitCommit(),n(B,(()=>{var m=D(()=>!!e.commitSubmitting());return()=>m()?e.t("instanceShell.gitChanges.commit.submitting"):e.t("instanceShell.gitChanges.commit.submit")})()),n($,i(te,{each:x,children:m=>J(m)}),null),P(m=>{var A=e.t("instanceShell.gitChanges.commit.placeholder"),z=!T();return A!==m.e&&g(M,"placeholder",m.e=A),z!==m.t&&(B.disabled=m.t=z),m},{e:void 0,t:void 0}),P(()=>M.value=e.commitMessage()),$}}),null),n(t,()=>se(e.t("instanceShell.gitChanges.sections.unstaged"),W,e.unstagedOpen(),e.onToggleUnstagedOpen),null),t}});return i(we,{get header(){return[(()=>{var t=Pe(),r=t.firstChild;return n(r,()=>(d==null?void 0:d.path)||e.t("instanceShell.rightPanel.tabs.gitChanges")),P(()=>g(t,"title",(d==null?void 0:d.path)||e.t("instanceShell.rightPanel.tabs.gitChanges"))),t})(),(()=>{var t=Re(),r=t.firstChild,a=r.firstChild;a.firstChild;var s=r.nextSibling,l=s.firstChild;return l.firstChild,n(a,()=>o.additions,null),n(l,()=>o.deletions,null),n(t,i(k,{get when(){return e.statusError()},children:f=>(()=>{var v=De();return n(v,f),v})()}),null),t})(),(()=>{var t=ze();return t.$$click=()=>e.onRefresh(),n(t,i(me,{get class(){return`h-4 w-4${e.statusLoading()?" animate-spin":""}`}})),P(r=>{var a=e.t("instanceShell.rightPanel.actions.refresh"),s=e.t("instanceShell.rightPanel.actions.refresh"),l=!L()||e.statusLoading()||V()===null;return a!==r.e&&g(t,"title",r.e=a),s!==r.t&&g(t,"aria-label",r.t=s),l!==r.a&&(t.disabled=r.a=l),r},{e:void 0,t:void 0,a:void 0}),t})(),i(xe,{get viewMode(){return e.diffViewMode()},get contextMode(){return e.diffContextMode()},get wordWrapMode(){return e.diffWordWrapMode()},get onViewModeChange(){return e.onViewModeChange},get onContextModeChange(){return e.onContextModeChange},get onWordWrapModeChange(){return e.onWordWrapModeChange}})]},list:{panel:j,overlay:j},get viewer(){return G()},get listOpen(){return e.listOpen()},get onToggleList(){return e.onToggleList},get splitWidth(){return e.splitWidth()},get onResizeMouseDown(){return e.onResizeMouseDown},get onResizeTouchStart(){return e.onResizeTouchStart},get isPhoneLayout(){return e.isPhoneLayout()},get overlayAriaLabel(){return e.t("instanceShell.rightPanel.tabs.gitChanges")}})})};ae(["mousedown","click","input"]);export{je as default};
@@ -1 +1 @@
1
- import{t as d,i as l,d as m,h as s,m as b,g as _,f as w}from"./monaco-viewer-DM35aobI.js";import{a as g,n as r,S as n}from"./git-diff-vendor-CYS3ApzA.js";import{u as S}from"./index-D8WMdSS9.js";var y=d("<div class=file-list-overlay role=dialog><div class=file-list-scroll>");const L=e=>(()=>{var t=y(),a=t.firstChild;return l(a,()=>e.children),g(()=>m(t,"aria-label",e.ariaLabel)),t})();var C=d('<div class=files-split><div class=file-list-panel><div class=file-list-scroll></div></div><div class=file-split-handle role=separator aria-orientation=vertical aria-label="Resize file list">'),x=d("<div class=files-tab-container><div class=files-tab-header><div class=files-tab-header-row><button type=button class=files-toggle-button></button></div></div><div class=files-tab-body>");const z=e=>{const{t}=S();return(()=>{var a=x(),c=a.firstChild,o=c.firstChild,u=o.firstChild,h=c.nextSibling;return s(u,"click",e.onToggleList,!0),l(u,(()=>{var i=b(()=>!!e.listOpen);return()=>i()?t("instanceShell.filesShell.hideFiles"):t("instanceShell.filesShell.showFiles")})()),l(o,()=>e.header,null),l(h,r(n,{get when(){return b(()=>!e.isPhoneLayout)()&&e.listOpen},get fallback(){return e.viewer},get children(){var i=C(),v=i.firstChild,$=v.firstChild,f=v.nextSibling;return l($,()=>e.list.panel()),s(f,"touchstart",e.onResizeTouchStart,!0),s(f,"mousedown",e.onResizeMouseDown,!0),l(i,()=>e.viewer,null),g(O=>_(i,"--files-pane-width",`${e.splitWidth}px`)),i}}),null),l(h,r(n,{get when(){return e.isPhoneLayout},get children(){return r(n,{get when(){return e.listOpen},get children(){return r(L,{get ariaLabel(){return e.overlayAriaLabel},get children(){return e.list.overlay()}})}})}}),null),a})()};w(["click","mousedown","touchstart"]);export{z as S};
1
+ import{t as d,i as l,d as m,h as s,m as b,g as _,f as w}from"./monaco-viewer-CiFg18Ak.js";import{a as g,n as r,S as n}from"./git-diff-vendor-CYS3ApzA.js";import{u as S}from"./index-D0xuNxlo.js";var y=d("<div class=file-list-overlay role=dialog><div class=file-list-scroll>");const L=e=>(()=>{var t=y(),a=t.firstChild;return l(a,()=>e.children),g(()=>m(t,"aria-label",e.ariaLabel)),t})();var C=d('<div class=files-split><div class=file-list-panel><div class=file-list-scroll></div></div><div class=file-split-handle role=separator aria-orientation=vertical aria-label="Resize file list">'),x=d("<div class=files-tab-container><div class=files-tab-header><div class=files-tab-header-row><button type=button class=files-toggle-button></button></div></div><div class=files-tab-body>");const z=e=>{const{t}=S();return(()=>{var a=x(),c=a.firstChild,o=c.firstChild,u=o.firstChild,h=c.nextSibling;return s(u,"click",e.onToggleList,!0),l(u,(()=>{var i=b(()=>!!e.listOpen);return()=>i()?t("instanceShell.filesShell.hideFiles"):t("instanceShell.filesShell.showFiles")})()),l(o,()=>e.header,null),l(h,r(n,{get when(){return b(()=>!e.isPhoneLayout)()&&e.listOpen},get fallback(){return e.viewer},get children(){var i=C(),v=i.firstChild,$=v.firstChild,f=v.nextSibling;return l($,()=>e.list.panel()),s(f,"touchstart",e.onResizeTouchStart,!0),s(f,"mousedown",e.onResizeMouseDown,!0),l(i,()=>e.viewer,null),g(O=>_(i,"--files-pane-width",`${e.splitWidth}px`)),i}}),null),l(h,r(n,{get when(){return e.isPhoneLayout},get children(){return r(n,{get when(){return e.listOpen},get children(){return r(L,{get ariaLabel(){return e.overlayAriaLabel},get children(){return e.list.overlay()}})}})}}),null),a})()};w(["click","mousedown","touchstart"]);export{z as S};