@ironmussa/funny 0.1.4 → 0.1.5

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 (87) hide show
  1. package/README.md +14 -19
  2. package/bin/funny.js +37 -66
  3. package/package.json +1 -1
  4. package/packages/client/dist/assets/{AcceptInvitePage-D2QlnwXy.js → AcceptInvitePage-Bz8azFPS.js} +1 -1
  5. package/packages/client/dist/assets/{ActivityPane-kz91jVAM.js → ActivityPane-DY9GzNxE.js} +1 -1
  6. package/packages/client/dist/assets/{AddProjectView-DWAvSEfh.js → AddProjectView-CS9PMuwG.js} +1 -1
  7. package/packages/client/dist/assets/{AllThreadsView-CEwWCoDj.js → AllThreadsView-wK8q3SsH.js} +1 -1
  8. package/packages/client/dist/assets/{AnalyticsView-DAWyZa5z.js → AnalyticsView-CZlraPUL.js} +1 -1
  9. package/packages/client/dist/assets/{App-BzBTjMsb.js → App-9j57f85r.js} +3 -3
  10. package/packages/client/dist/assets/{AutomationInboxView-zNA4E_CB.js → AutomationInboxView-CDlKbclJ.js} +1 -1
  11. package/packages/client/dist/assets/{BrowserPanel-CLETmPIM.js → BrowserPanel-B7imTgqS.js} +1 -1
  12. package/packages/client/dist/assets/{BrowserPreview-D6-GY7Lk.js → BrowserPreview-DOUyF-0l.js} +1 -1
  13. package/packages/client/dist/assets/{CircuitBreakerDialog-DCiRlBvD.js → CircuitBreakerDialog-C20MeUCC.js} +1 -1
  14. package/packages/client/dist/assets/{CommandPalette-MY2bMCP4.js → CommandPalette-B55GwOW8.js} +1 -1
  15. package/packages/client/dist/assets/{CommentsPane-tyNsUWqs.js → CommentsPane-js2FWA8j.js} +1 -1
  16. package/packages/client/dist/assets/{CsvTable-DB3mtG8a.js → CsvTable-CBgoinyU.js} +1 -1
  17. package/packages/client/dist/assets/{FileSearchDialog-4lhZizzD.js → FileSearchDialog-HCT2Hz0_.js} +1 -1
  18. package/packages/client/dist/assets/{FileTree-DESC68xP.js → FileTree-DUODDbNL.js} +1 -1
  19. package/packages/client/dist/assets/{FolderPicker-B5JTJeAY.js → FolderPicker-DEwPUyou.js} +1 -1
  20. package/packages/client/dist/assets/{GeneralSettingsView-SHsx-3nX.js → GeneralSettingsView-DkKqhc1H.js} +2 -2
  21. package/packages/client/dist/assets/{GitProgressModal-C_W78wcH.js → GitProgressModal-wumxtrFG.js} +1 -1
  22. package/packages/client/dist/assets/{LiveColumnsView-XMHr9OEz.js → LiveColumnsView-C9sNbvg3.js} +1 -1
  23. package/packages/client/dist/assets/{LoginPage-CQ9fP0F4.js → LoginPage-5VQrfpbg.js} +1 -1
  24. package/packages/client/dist/assets/{MediaPreview-2jhQWqiK.js → MediaPreview-DzlqoZwu.js} +1 -1
  25. package/packages/client/dist/assets/{MediaPreviewDialog-ZMIFbNgy.js → MediaPreviewDialog-C9ZILO-C.js} +1 -1
  26. package/packages/client/dist/assets/{MermaidBlock-Ub8VkOL4.js → MermaidBlock-xuBty90Y.js} +1 -1
  27. package/packages/client/dist/assets/{MobilePage-C9PpVVfq.js → MobilePage-B3b4tpPe.js} +2 -2
  28. package/packages/client/dist/assets/{MonacoEditorDialog-Co2xdBGu.js → MonacoEditorDialog-DfJmfHiL.js} +1 -1
  29. package/packages/client/dist/assets/{OrchestratorView-CJ529EFF.js → OrchestratorView--Df-JFQd.js} +1 -1
  30. package/packages/client/dist/assets/{PreferencesPanel-Cz4IuCEn.js → PreferencesPanel-CAhnrHw0.js} +1 -1
  31. package/packages/client/dist/assets/{PreviewBrowser-Csflu6Sr.js → PreviewBrowser-DKz2hR71.js} +1 -1
  32. package/packages/client/dist/assets/{ProjectFilesPane-C0-WA5jW.js → ProjectFilesPane-BbOGQ3kp.js} +1 -1
  33. package/packages/client/dist/assets/{ProjectHeader-Bf1gaA1F.js → ProjectHeader-DZ9UUaqW.js} +1 -1
  34. package/packages/client/dist/assets/{ProjectHooksSettings-DdChzrcv.js → ProjectHooksSettings-BGHkJMxp.js} +1 -1
  35. package/packages/client/dist/assets/{ReviewPane-DSytotSX.js → ReviewPane-83OOq41s.js} +1 -1
  36. package/packages/client/dist/assets/{SearchablePicker-ePO3BIOx.js → SearchablePicker-Cz6G4abl.js} +1 -1
  37. package/packages/client/dist/assets/{SettingsDetailView-DH9yGrff.js → SettingsDetailView-DwWVM6qW.js} +1 -1
  38. package/packages/client/dist/assets/{SettingsPageContent-C8EUEhHQ.js → SettingsPageContent-Cre7rDf1.js} +3 -3
  39. package/packages/client/dist/assets/{SetupWizard-DXcV9Vsz.js → SetupWizard-im6s3weh.js} +1 -1
  40. package/packages/client/dist/assets/{Sidebar-CnSzyO_S.js → Sidebar-C7PRUuZe.js} +1 -1
  41. package/packages/client/dist/assets/{StashTab-BZn6-Wn3.js → StashTab-CzC8WNxJ.js} +1 -1
  42. package/packages/client/dist/assets/{TestRunnerPane-Cz8KHMSp.js → TestRunnerPane-DjzPYNLs.js} +1 -1
  43. package/packages/client/dist/assets/{TextSearchDialog-BWChISXp.js → TextSearchDialog-DcYyEuMd.js} +1 -1
  44. package/packages/client/dist/assets/{ThreadPowerline-CX-bm7_6.js → ThreadPowerline-CTbQgGLL.js} +1 -1
  45. package/packages/client/dist/assets/{ThreadStatusPin-CjNRn4Rx.js → ThreadStatusPin-CYsH0F8e.js} +1 -1
  46. package/packages/client/dist/assets/{ThreadView-DbwUcWMo.js → ThreadView-DUaDYGnz.js} +1 -1
  47. package/packages/client/dist/assets/{app-store-BwZB2xp_.js → app-store-CVcOgstJ.js} +1 -1
  48. package/packages/client/dist/assets/{automation-store-DBy-NuND.js → automation-store-DteeWFhQ.js} +1 -1
  49. package/packages/client/dist/assets/{browser-panel-store-Bih_qYi6.js → browser-panel-store-3T75tTA2.js} +2 -2
  50. package/packages/client/dist/assets/{button-DeEOU1Fb.js → button-Bi9_EZFh.js} +1 -1
  51. package/packages/client/dist/assets/{combine-ISTWP4AL.js → combine-JFcc9GB_.js} +1 -1
  52. package/packages/client/dist/assets/{comment-store-Be3Fd_A7.js → comment-store-DgECCb00.js} +1 -1
  53. package/packages/client/dist/assets/{diff-parse-738OLLMl.js → diff-parse-CRTMJKOI.js} +1 -1
  54. package/packages/client/dist/assets/{element-CuNJpCWR.js → element-DgNlo25W.js} +1 -1
  55. package/packages/client/dist/assets/{go-to-thread-XoxeW5m_.js → go-to-thread-DJT-R5-a.js} +1 -1
  56. package/packages/client/dist/assets/{index-BsxcqNXe.js → index-Bmp1UFM1.js} +2 -2
  57. package/packages/client/dist/assets/{input-DV30TVat.js → input-BGZP-HTx.js} +1 -1
  58. package/packages/client/dist/assets/{items-_g3-I08l.js → items-C-m69VjA.js} +1 -1
  59. package/packages/client/dist/assets/{job-store-C5Ten7SL.js → job-store-BBERDOJO.js} +1 -1
  60. package/packages/client/dist/assets/{kbd-C7L0hICt.js → kbd-BrgsdFIb.js} +1 -1
  61. package/packages/client/dist/assets/{loading-state-BQjalkhM.js → loading-state-DGzdeccZ.js} +1 -1
  62. package/packages/client/dist/assets/{markdown-components-D4Y3yxJk.js → markdown-components-DbIYr3N1.js} +1 -1
  63. package/packages/client/dist/assets/{native-git-store-B9ZRXl6g.js → native-git-store-CYZj3IWH.js} +1 -1
  64. package/packages/client/dist/assets/{orchestrator-store-Vf7hIdtx.js → orchestrator-store-B-nOHeLj.js} +1 -1
  65. package/packages/client/dist/assets/{pipeline-approval-store-BzDMPaHv.js → pipeline-approval-store-DOhazL3I.js} +1 -1
  66. package/packages/client/dist/assets/{pr-detail-store-ZCVq5jO-.js → pr-detail-store-BJ3P2gik.js} +1 -1
  67. package/packages/client/dist/assets/{providers-CBJW4tBi.js → providers-BD43Asis.js} +1 -1
  68. package/packages/client/dist/assets/{sidebar-BzOM_jNz.js → sidebar-CL7TSCIO.js} +1 -1
  69. package/packages/client/dist/assets/{tabs-C98UD1RJ.js → tabs-DWlrx7U8.js} +1 -1
  70. package/packages/client/dist/assets/{test-store-BbGZeyOw.js → test-store-C40x04Fz.js} +1 -1
  71. package/packages/client/dist/assets/{tooltip-icon-button-z_YicoMI.js → tooltip-icon-button-DUnFi3-p.js} +1 -1
  72. package/packages/client/dist/assets/use-active-thread-id-De6IjhUY.js +1 -0
  73. package/packages/client/dist/assets/{use-branch-switch-mtbqs9Jw.js → use-branch-switch-4nDECRMh.js} +1 -1
  74. package/packages/client/dist/assets/{use-image-lightbox-D_bv65q5.js → use-image-lightbox-13VQ9o9i.js} +1 -1
  75. package/packages/client/dist/assets/{use-stable-navigate-CTxO5fW7.js → use-stable-navigate-uXVRGpin.js} +1 -1
  76. package/packages/client/dist/assets/{use-terminal-scope-DdXii8xw.js → use-terminal-scope-DHhH7AvQ.js} +1 -1
  77. package/packages/client/dist/assets/{use-thread-creation-Dyd2HCG5.js → use-thread-creation-CgT3SuOi.js} +1 -1
  78. package/packages/client/dist/assets/{use-thread-search-BIXj6zRV.js → use-thread-search-CbgQmS3O.js} +1 -1
  79. package/packages/client/dist/assets/{use-todo-panel-D9pAUf5W.js → use-todo-panel-CsXYDjtr.js} +1 -1
  80. package/packages/client/dist/assets/{use-unified-prompt-model-groups-CjX0kT2J.js → use-unified-prompt-model-groups-CUMps-gq.js} +1 -1
  81. package/packages/client/dist/assets/{use-ws-CeBgbigk.js → use-ws-DVvliZBW.js} +3 -3
  82. package/packages/client/dist/assets/{visualizer-loader-BVlcAMHr.js → visualizer-loader-Dv9AyyLp.js} +1 -1
  83. package/packages/client/dist/assets/{watcher-store-C6B9wUDN.js → watcher-store-srZSE5jI.js} +1 -1
  84. package/packages/client/dist/index.html +1 -1
  85. package/packages/runtime/dist/index.js +2 -2
  86. package/packages/runtime/dist/index.js.map +1 -1
  87. package/packages/client/dist/assets/use-active-thread-id-DE1fU7g0.js +0 -1
package/README.md CHANGED
@@ -105,19 +105,13 @@ The admin can create additional user accounts from the central server's API.
105
105
 
106
106
  #### Step 2: Each team member connects
107
107
 
108
- Each team member runs funny locally with the `--team` and `--token` flags:
108
+ Each team member runs funny locally with the `--team` flag:
109
109
 
110
110
  ```bash
111
- funny --team http://<central-server-ip>:3002 --token <invite-token>
111
+ funny --team http://<central-server-ip>:3002
112
112
  ```
113
113
 
114
- The invite token is generated from the central server's **Settings > Runners** page. Copy the install command and run it it works on Windows, macOS, and Linux.
115
-
116
- On first run, the `--team` and `--token` values are **automatically saved** to `~/.funny/.env`, so subsequent runs only need:
117
-
118
- ```bash
119
- funny
120
- ```
114
+ The runner prints a short device-link code. In the central server UI, open **Settings > Runners**, click **Link a runner**, enter the code, and approve it. A plain `funny` or `bunx @ironmussa/funny@latest` always starts local by default; every team run should pass `--team <url>` explicitly.
121
115
 
122
116
  This starts the full funny app locally (UI, git, agents) **and** connects to the central server to:
123
117
 
@@ -159,6 +153,7 @@ Team member A Team member B
159
153
  | `--auth-mode <mode>` | Authentication mode: `local` or `multi` | `local` |
160
154
  | `--team <url>` | Connect to a central team server | - |
161
155
  | `--token <token>` | Runner invite token for team registration | - |
156
+ | `--local` | Start standalone; cannot combine with `--team` | `false` |
162
157
  | `--help` | Show help message | - |
163
158
 
164
159
  **funny-server** (team coordination server)
@@ -171,19 +166,19 @@ Team member A Team member B
171
166
 
172
167
  ### Persistent Configuration
173
168
 
174
- When you pass `--team` or `--token` via the CLI, the values are automatically saved to `~/.funny/.env`. On subsequent runs, funny loads this file so you don't need to repeat the flags.
169
+ Saved values in `~/.funny/.env` do not activate team mode. A plain `funny` or `bunx @ironmussa/funny@latest` always starts in local mode by default. To connect to a central server, pass `--team <url>` explicitly.
175
170
 
176
171
  ```bash
177
- # First time — pass the full connection info
178
- funny --team http://192.168.1.10:3002 --token utkn_xxx
179
-
180
- # Every subsequent run — just this
172
+ # Local standalone
181
173
  funny
174
+
175
+ # Team runner
176
+ funny --team http://192.168.1.10:3002
182
177
  ```
183
178
 
184
- **Precedence order:** CLI flags > shell environment variables > saved `~/.funny/.env`
179
+ **Precedence order:** CLI flags > shell environment variables > saved non-team values in `~/.funny/.env`. Team mode requires `--team <url>`.
185
180
 
186
- To change the server, simply pass `--team` again with a new URL — the saved config is updated automatically. The `.env` file is created with restricted permissions (`0600`) since it contains tokens.
181
+ To change the server, pass `--team` with the new URL.
187
182
 
188
183
  ### Environment Variables
189
184
 
@@ -192,8 +187,8 @@ To change the server, simply pass `--team` again with a new URL — the saved co
192
187
  | `PORT` | Server port | `3001` / `3002` | both |
193
188
  | `HOST` | Server hostname | `127.0.0.1` | both |
194
189
  | `AUTH_MODE` | Authentication mode (`local`/`multi`) | `local` | funny |
195
- | `TEAM_SERVER_URL` | Central server URL (same as `--team`) | - | funny |
196
- | `RUNNER_INVITE_TOKEN` | Runner invite token (same as `--token`) | - | funny |
190
+ | `RUNNER_INVITE_TOKEN` | Runner invite token for `--team` classic flow | - | funny |
191
+ | `RUNNER_AUTH_SECRET` | Shared secret for `--team` classic flow | - | funny |
197
192
  | `CORS_ORIGIN` | Custom CORS origins (comma-separated) | Auto-configured | both |
198
193
  | `FUNNY_CENTRAL_DATA_DIR` | Central server data directory | `~/.funny-central` | funny-server |
199
194
  | `LOG_LEVEL` | Log level (debug/info/warn/error) | `info` | funny-server |
@@ -489,7 +484,7 @@ run `bun run dev` as usual, or prefix any command with `PORTLESS=0`.
489
484
 
490
485
  ```
491
486
  ~/.funny/
492
- ├── .env # Saved CLI config (--team, --token) auto-generated
487
+ ├── .env # Optional local env file; team connection keys are ignored by the CLI
493
488
  ├── data.db # SQLite database (projects, threads, messages)
494
489
  ├── auth-token # Bearer token for local auth
495
490
  ├── auth-secret # Session secret (multi-user mode)
package/bin/funny.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bun
2
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
2
+ import { existsSync, readFileSync } from 'fs';
3
3
  import { homedir } from 'os';
4
4
  import { resolve, join } from 'path';
5
5
  import { parseArgs } from 'util';
@@ -8,6 +8,7 @@ import { parseArgs } from 'util';
8
8
 
9
9
  const FUNNY_DIR = join(homedir(), '.funny');
10
10
  const ENV_FILE = join(FUNNY_DIR, '.env');
11
+ const TEAM_ENV_KEYS = new Set(['TEAM_SERVER_URL', 'RUNNER_INVITE_TOKEN', 'RUNNER_AUTH_SECRET']);
11
12
 
12
13
  /**
13
14
  * Parse a simple .env file into key-value pairs.
@@ -37,6 +38,8 @@ function parseEnvFile(content) {
37
38
  /**
38
39
  * Load saved env vars from ~/.funny/.env.
39
40
  * Only sets values that are NOT already in process.env (env vars take precedence).
41
+ * Team connection keys are intentionally ignored: connecting to a central server
42
+ * must be requested explicitly with --team.
40
43
  */
41
44
  function loadSavedEnv() {
42
45
  if (!existsSync(ENV_FILE)) return;
@@ -44,6 +47,7 @@ function loadSavedEnv() {
44
47
  const content = readFileSync(ENV_FILE, 'utf-8');
45
48
  const vars = parseEnvFile(content);
46
49
  for (const [key, value] of Object.entries(vars)) {
50
+ if (TEAM_ENV_KEYS.has(key)) continue;
47
51
  if (!process.env[key]) {
48
52
  process.env[key] = value;
49
53
  }
@@ -53,51 +57,17 @@ function loadSavedEnv() {
53
57
  }
54
58
  }
55
59
 
56
- /**
57
- * Save env vars to ~/.funny/.env, merging with existing values.
58
- * Creates ~/.funny directory if it doesn't exist.
59
- */
60
- function saveEnv(updates) {
61
- // Read existing values
62
- let existing = {};
63
- if (existsSync(ENV_FILE)) {
64
- try {
65
- existing = parseEnvFile(readFileSync(ENV_FILE, 'utf-8'));
66
- } catch {}
67
- }
68
-
69
- // Merge updates
70
- const merged = { ...existing, ...updates };
71
-
72
- // Write header + key=value pairs
73
- const lines = ['# Saved by funny CLI — do not edit while running'];
74
- for (const [key, value] of Object.entries(merged)) {
75
- lines.push(`${key}=${value}`);
76
- }
77
-
78
- // Ensure directory exists
79
- mkdirSync(FUNNY_DIR, { recursive: true });
80
-
81
- // Write with restricted permissions (0o600) — contains tokens
82
- writeFileSync(ENV_FILE, lines.join('\n') + '\n', { mode: 0o600 });
83
- }
84
-
85
- // ── Load saved config before parsing CLI args ─────────────
86
- loadSavedEnv();
87
-
88
60
  // ── `funny ext` — manage visualizer extensions (runs without the server) ──
89
61
  // Dispatched BEFORE the strict parseArgs below, because `ext` subcommands carry
90
62
  // their own flags (--ref, --subdir) that the top-level parser doesn't know.
91
- {
92
- const rawArgs = process.argv.slice(2);
93
- if (rawArgs[0] === 'ext') {
94
- process.exit(await runExtCommand(rawArgs.slice(1)));
95
- }
63
+ const rawArgs = process.argv.slice(2);
64
+ if (rawArgs[0] === 'ext') {
65
+ process.exit(await runExtCommand(rawArgs.slice(1)));
96
66
  }
97
67
 
98
68
  // ── Parse CLI arguments ───────────────────────────────────
99
69
 
100
- const { values, positionals } = parseArgs({
70
+ const { values } = parseArgs({
101
71
  options: {
102
72
  port: {
103
73
  type: 'string',
@@ -121,6 +91,10 @@ const { values, positionals } = parseArgs({
121
91
  type: 'string',
122
92
  description: 'Shared RUNNER_AUTH_SECRET (must match the central server) for team mode',
123
93
  },
94
+ local: {
95
+ type: 'boolean',
96
+ default: false,
97
+ },
124
98
  help: {
125
99
  type: 'boolean',
126
100
  },
@@ -128,6 +102,22 @@ const { values, positionals } = parseArgs({
128
102
  allowPositionals: true,
129
103
  });
130
104
 
105
+ if (values.local && values.team) {
106
+ console.error('[funny] ERROR: --local cannot be combined with --team.');
107
+ process.exit(1);
108
+ }
109
+
110
+ // Saved and inherited team credentials are intentionally ignored unless --team
111
+ // is present. A plain `funny` or `bunx @ironmussa/funny` should always start
112
+ // local, even if the shell or ~/.funny/.env contains stale team variables.
113
+ loadSavedEnv();
114
+
115
+ if (!values.team || values.local) {
116
+ delete process.env.TEAM_SERVER_URL;
117
+ delete process.env.RUNNER_INVITE_TOKEN;
118
+ delete process.env.RUNNER_AUTH_SECRET;
119
+ }
120
+
131
121
  if (values.help) {
132
122
  console.log(`
133
123
  funny - Parallel Claude Code agent orchestration
@@ -141,6 +131,7 @@ Options:
141
131
  --team <url> Connect to a central team server (e.g. http://192.168.1.10:3002)
142
132
  --token <token> Runner invite token for team server registration
143
133
  --secret <secret> Shared RUNNER_AUTH_SECRET — must match the central server (team mode)
134
+ --local Start standalone; cannot be combined with --team
144
135
  --help Show this help message
145
136
 
146
137
  Team Mode:
@@ -151,10 +142,7 @@ Team Mode:
151
142
 
152
143
  funny prints a short code; open the server, go to Settings ▸ Runners ▸
153
144
  "Link a runner", enter the code, and approve. The runner then receives its
154
- credentials automatically — no secret or token to copy. Credentials are saved
155
- to ~/.funny so later runs only need:
156
-
157
- funny
145
+ credentials automatically — no secret or token to copy.
158
146
 
159
147
  Classic flow (advanced): you may instead supply the shared secret + an invite
160
148
  token yourself. RUNNER_AUTH_SECRET must match the central server's value:
@@ -176,15 +164,15 @@ Authentication:
176
164
  Environment Variables:
177
165
  PORT Server port
178
166
  HOST Server host
179
- TEAM_SERVER_URL Central team server URL (same as --team)
180
- RUNNER_INVITE_TOKEN Runner invite token (same as --token)
181
- RUNNER_AUTH_SECRET Shared secret matching the central server (same as --secret)
167
+ RUNNER_INVITE_TOKEN Runner invite token for --team classic flow
168
+ RUNNER_AUTH_SECRET Shared secret for --team classic flow
182
169
  CORS_ORIGIN Custom CORS origins (comma-separated)
183
170
  DB_MODE Database mode: sqlite (default) or postgres
184
171
  DATABASE_URL PostgreSQL connection URL (when DB_MODE=postgres)
185
172
 
186
173
  Config:
187
174
  Saved config: ~/.funny/.env
175
+ Note: saved and inherited team connection keys are ignored; pass --team to connect.
188
176
  Database: ~/.funny/data.db
189
177
 
190
178
  For more information, visit: https://github.com/anthropics/funny
@@ -197,7 +185,7 @@ For more information, visit: https://github.com/anthropics/funny
197
185
  process.env.PORT = values.port;
198
186
  process.env.HOST = values.host;
199
187
 
200
- // CLI --team and --token override env vars and saved config
188
+ // CLI --team and --token override env vars for this process only.
201
189
  if (values.team) {
202
190
  process.env.TEAM_SERVER_URL = values.team;
203
191
  }
@@ -208,28 +196,11 @@ if (values.secret) {
208
196
  process.env.RUNNER_AUTH_SECRET = values.secret;
209
197
  }
210
198
 
211
- // ── Save team config when provided via CLI ────────────────
212
-
213
- const toSave = {};
214
- if (values.team) toSave.TEAM_SERVER_URL = values.team;
215
- if (values.token) toSave.RUNNER_INVITE_TOKEN = values.token;
216
- if (values.secret) toSave.RUNNER_AUTH_SECRET = values.secret;
217
-
218
- if (Object.keys(toSave).length > 0) {
219
- try {
220
- saveEnv(toSave);
221
- console.log(`[funny] Config saved to ${ENV_FILE}`);
222
- } catch (err) {
223
- console.warn(`[funny] Warning: could not save config to ${ENV_FILE}:`, err.message);
224
- }
225
- }
226
-
227
199
  // ── Team mode log ─────────────────────────────────────────
228
200
 
229
201
  if (process.env.TEAM_SERVER_URL) {
230
- const source = values.team ? 'CLI' : existsSync(ENV_FILE) ? 'saved config' : 'env';
231
202
  console.log(
232
- `[funny] Team mode enabled — connecting to ${process.env.TEAM_SERVER_URL} (from ${source})`,
203
+ `[funny] Team mode enabled — connecting to ${process.env.TEAM_SERVER_URL} (from CLI)`,
233
204
  );
234
205
  }
235
206
 
@@ -255,7 +226,7 @@ if (!process.env.RUNNER_AUTH_SECRET) {
255
226
  '\n[funny] ERROR: RUNNER_AUTH_SECRET is required when using --token in team mode.\n\n' +
256
227
  'This runner connects to a central server and must use the SAME\n' +
257
228
  'RUNNER_AUTH_SECRET as that server. Ask your admin for it, then pass\n' +
258
- 'it via flag or env (it is saved to ~/.funny/.env for next time):\n\n' +
229
+ 'it via flag or env:\n\n' +
259
230
  ` funny --team ${process.env.TEAM_SERVER_URL} --secret <secret-from-admin> --token <invite-token>\n\n` +
260
231
  'Or drop --token and use device-link enrollment (no secret needed):\n\n' +
261
232
  ` funny --team ${process.env.TEAM_SERVER_URL}\n`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ironmussa/funny",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "private": false,
5
5
  "packageManager": "bun@1.3.10",
6
6
  "description": "Codex App clone powered by Claude Code — parallel agent orchestration with git worktrees",
@@ -1 +1 @@
1
- import{a as e}from"./rolldown-runtime-Cyuzqnbw.js";import{Lt as t,ar as n,lr as r,m as i,zr as a}from"./icons-sqwAEN28.js";import{o}from"./markdown-DBtwZWLP.js";import{M as s,P as c,k as l}from"./index-BsxcqNXe.js";import{t as u}from"./button-DeEOU1Fb.js";import{t as d}from"./input-DV30TVat.js";import{t as f}from"./loading-state-BQjalkhM.js";var p=e(a(),1),m=e(o(),1);function h({token:e}){let a=l(e=>e.isAuthenticated),[o,h]=(0,p.useState)(`verifying`),[g,_]=(0,p.useState)(``),[v,y]=(0,p.useState)(``),[b,x]=(0,p.useState)(``),[S,C]=(0,p.useState)(``),[w,T]=(0,p.useState)(``),[E,D]=(0,p.useState)(``),[O,k]=(0,p.useState)(!1),[A,j]=(0,p.useState)(``),[M,N]=(0,p.useState)(!1);(0,p.useEffect)(()=>{c.verifyInviteLink(e).then(e=>{e.isOk()?(y(e.value.organizationName),x(e.value.role),a?P():h(`register`)):(h(`error`),_(e.error.message||`Invalid or expired invite link`))})},[e]);let P=(0,p.useCallback)(async()=>{h(`accepting`);let t=await c.acceptInviteLink(e);t.isOk()?h(t.value.alreadyMember?`already`:`success`):(h(`error`),_(t.error.message||`Failed to join organization`))},[e]),F=async t=>{t.preventDefault(),j(``),k(!0);try{let t=await c.registerViaInvite({token:e,username:S,password:w,displayName:E||void 0});if(t.isOk()){let{user:e}=t.value;l.setState({isAuthenticated:!0,user:{id:e.id,username:e.username,displayName:e.displayName,role:`user`}}),h(`success`)}else j(t.error.message||`Registration failed`),k(!1)}catch(e){j(e.message||`Registration failed`),k(!1)}},I=async e=>{e.preventDefault(),j(``),k(!0);try{let e=await s.signIn.username({username:S,password:w});if(e.error){j(e.error.message||`Login failed`),k(!1);return}let t=e.data?.user;t&&l.setState({isAuthenticated:!0,user:{id:t.id,username:t.username||t.name||`user`,displayName:t.name||t.username||`User`,role:t.role||`user`}}),await P()}catch(e){j(e.message||`Login failed`),k(!1)}},L=()=>{window.location.href=`/`};return(0,m.jsx)(`div`,{className:`bg-background flex min-h-screen items-center justify-center`,children:(0,m.jsxs)(`div`,{className:`border-border bg-card w-full max-w-sm space-y-6 rounded-lg border p-8 text-center shadow-lg`,children:[o===`verifying`&&(0,m.jsx)(f,{fill:!1,testId:`accept-invite-verifying`,label:`Verifying invite link…`}),o===`register`&&(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(i,{className:`text-primary mx-auto size-8`}),(0,m.jsxs)(`div`,{children:[(0,m.jsxs)(`h2`,{className:`text-foreground text-lg font-semibold`,children:[`Join `,v]}),(0,m.jsxs)(`p`,{className:`text-muted-foreground mt-1 text-sm`,children:[`You've been invited as `,(0,m.jsx)(`span`,{className:`font-medium`,children:b}),`.`,` `,M?`Sign in to accept.`:`Create an account to get started.`]})]}),(0,m.jsxs)(`form`,{onSubmit:M?I:F,className:`space-y-4 text-left`,children:[(0,m.jsxs)(`div`,{className:`space-y-2`,children:[(0,m.jsx)(`label`,{htmlFor:`invite-username`,className:`text-foreground text-sm font-medium`,children:`Username`}),(0,m.jsx)(d,{id:`invite-username`,type:`text`,value:S,onChange:e=>C(e.target.value),placeholder:`Choose a username`,autoFocus:!0,required:!0,"data-testid":`invite-username`})]}),!M&&(0,m.jsxs)(`div`,{className:`space-y-2`,children:[(0,m.jsxs)(`label`,{htmlFor:`invite-display-name`,className:`text-foreground text-sm font-medium`,children:[`Display Name`,(0,m.jsx)(`span`,{className:`text-muted-foreground ml-1 font-normal`,children:`(optional)`})]}),(0,m.jsx)(d,{id:`invite-display-name`,type:`text`,value:E,onChange:e=>D(e.target.value),placeholder:`Your display name`,"data-testid":`invite-display-name`})]}),(0,m.jsxs)(`div`,{className:`space-y-2`,children:[(0,m.jsx)(`label`,{htmlFor:`invite-password`,className:`text-foreground text-sm font-medium`,children:`Password`}),(0,m.jsx)(d,{id:`invite-password`,type:`password`,value:w,onChange:e=>T(e.target.value),placeholder:M?`Your password`:`Choose a password`,required:!0,"data-testid":`invite-password`})]}),A&&(0,m.jsx)(`p`,{className:`text-destructive text-sm`,children:A}),(0,m.jsxs)(u,{type:`submit`,className:`w-full`,disabled:O||!S||!w,"data-testid":`invite-submit`,children:[O?(0,m.jsx)(t,{className:`icon-base mr-2 animate-spin`}):null,M?`Sign In & Join`:`Create Account & Join`]})]}),(0,m.jsx)(`p`,{className:`text-muted-foreground text-sm`,children:M?(0,m.jsxs)(m.Fragment,{children:[`Don't have an account?`,` `,(0,m.jsx)(`button`,{type:`button`,className:`text-primary hover:underline`,onClick:()=>{N(!1),j(``)},"data-testid":`invite-switch-register`,children:`Register`})]}):(0,m.jsxs)(m.Fragment,{children:[`Already have an account?`,` `,(0,m.jsx)(`button`,{type:`button`,className:`text-primary hover:underline`,onClick:()=>{N(!0),j(``)},"data-testid":`invite-switch-login`,children:`Sign in`})]})})]}),o===`accepting`&&(0,m.jsx)(f,{fill:!1,testId:`accept-invite-accepting`,label:`Joining ${v}...`}),o===`success`&&(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(r,{className:`mx-auto size-8 text-green-500`}),(0,m.jsx)(`h2`,{className:`text-foreground text-lg font-semibold`,children:`You're in!`}),(0,m.jsxs)(`p`,{className:`text-muted-foreground text-sm`,children:[`You've successfully joined `,(0,m.jsx)(`span`,{className:`font-medium`,children:v}),`.`]}),(0,m.jsx)(u,{onClick:L,className:`w-full`,"data-testid":`invite-continue`,children:`Continue to App`})]}),o===`already`&&(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(r,{className:`mx-auto size-8 text-blue-500`}),(0,m.jsx)(`h2`,{className:`text-foreground text-lg font-semibold`,children:`Already a member`}),(0,m.jsxs)(`p`,{className:`text-muted-foreground text-sm`,children:[`You're already a member of `,(0,m.jsx)(`span`,{className:`font-medium`,children:v}),`.`]}),(0,m.jsx)(u,{onClick:L,className:`w-full`,"data-testid":`invite-continue`,children:`Continue to App`})]}),o===`error`&&(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(n,{className:`text-destructive mx-auto size-8`}),(0,m.jsx)(`h2`,{className:`text-foreground text-lg font-semibold`,children:`Invitation failed`}),(0,m.jsx)(`p`,{className:`text-muted-foreground text-sm`,children:g}),(0,m.jsx)(u,{variant:`outline`,onClick:L,className:`w-full`,"data-testid":`invite-continue`,children:`Go to App`})]})]})})}export{h as AcceptInvitePage};
1
+ import{a as e}from"./rolldown-runtime-Cyuzqnbw.js";import{Lt as t,ar as n,lr as r,m as i,zr as a}from"./icons-sqwAEN28.js";import{o}from"./markdown-DBtwZWLP.js";import{M as s,P as c,k as l}from"./index-Bmp1UFM1.js";import{t as u}from"./button-Bi9_EZFh.js";import{t as d}from"./input-BGZP-HTx.js";import{t as f}from"./loading-state-DGzdeccZ.js";var p=e(a(),1),m=e(o(),1);function h({token:e}){let a=l(e=>e.isAuthenticated),[o,h]=(0,p.useState)(`verifying`),[g,_]=(0,p.useState)(``),[v,y]=(0,p.useState)(``),[b,x]=(0,p.useState)(``),[S,C]=(0,p.useState)(``),[w,T]=(0,p.useState)(``),[E,D]=(0,p.useState)(``),[O,k]=(0,p.useState)(!1),[A,j]=(0,p.useState)(``),[M,N]=(0,p.useState)(!1);(0,p.useEffect)(()=>{c.verifyInviteLink(e).then(e=>{e.isOk()?(y(e.value.organizationName),x(e.value.role),a?P():h(`register`)):(h(`error`),_(e.error.message||`Invalid or expired invite link`))})},[e]);let P=(0,p.useCallback)(async()=>{h(`accepting`);let t=await c.acceptInviteLink(e);t.isOk()?h(t.value.alreadyMember?`already`:`success`):(h(`error`),_(t.error.message||`Failed to join organization`))},[e]),F=async t=>{t.preventDefault(),j(``),k(!0);try{let t=await c.registerViaInvite({token:e,username:S,password:w,displayName:E||void 0});if(t.isOk()){let{user:e}=t.value;l.setState({isAuthenticated:!0,user:{id:e.id,username:e.username,displayName:e.displayName,role:`user`}}),h(`success`)}else j(t.error.message||`Registration failed`),k(!1)}catch(e){j(e.message||`Registration failed`),k(!1)}},I=async e=>{e.preventDefault(),j(``),k(!0);try{let e=await s.signIn.username({username:S,password:w});if(e.error){j(e.error.message||`Login failed`),k(!1);return}let t=e.data?.user;t&&l.setState({isAuthenticated:!0,user:{id:t.id,username:t.username||t.name||`user`,displayName:t.name||t.username||`User`,role:t.role||`user`}}),await P()}catch(e){j(e.message||`Login failed`),k(!1)}},L=()=>{window.location.href=`/`};return(0,m.jsx)(`div`,{className:`bg-background flex min-h-screen items-center justify-center`,children:(0,m.jsxs)(`div`,{className:`border-border bg-card w-full max-w-sm space-y-6 rounded-lg border p-8 text-center shadow-lg`,children:[o===`verifying`&&(0,m.jsx)(f,{fill:!1,testId:`accept-invite-verifying`,label:`Verifying invite link…`}),o===`register`&&(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(i,{className:`text-primary mx-auto size-8`}),(0,m.jsxs)(`div`,{children:[(0,m.jsxs)(`h2`,{className:`text-foreground text-lg font-semibold`,children:[`Join `,v]}),(0,m.jsxs)(`p`,{className:`text-muted-foreground mt-1 text-sm`,children:[`You've been invited as `,(0,m.jsx)(`span`,{className:`font-medium`,children:b}),`.`,` `,M?`Sign in to accept.`:`Create an account to get started.`]})]}),(0,m.jsxs)(`form`,{onSubmit:M?I:F,className:`space-y-4 text-left`,children:[(0,m.jsxs)(`div`,{className:`space-y-2`,children:[(0,m.jsx)(`label`,{htmlFor:`invite-username`,className:`text-foreground text-sm font-medium`,children:`Username`}),(0,m.jsx)(d,{id:`invite-username`,type:`text`,value:S,onChange:e=>C(e.target.value),placeholder:`Choose a username`,autoFocus:!0,required:!0,"data-testid":`invite-username`})]}),!M&&(0,m.jsxs)(`div`,{className:`space-y-2`,children:[(0,m.jsxs)(`label`,{htmlFor:`invite-display-name`,className:`text-foreground text-sm font-medium`,children:[`Display Name`,(0,m.jsx)(`span`,{className:`text-muted-foreground ml-1 font-normal`,children:`(optional)`})]}),(0,m.jsx)(d,{id:`invite-display-name`,type:`text`,value:E,onChange:e=>D(e.target.value),placeholder:`Your display name`,"data-testid":`invite-display-name`})]}),(0,m.jsxs)(`div`,{className:`space-y-2`,children:[(0,m.jsx)(`label`,{htmlFor:`invite-password`,className:`text-foreground text-sm font-medium`,children:`Password`}),(0,m.jsx)(d,{id:`invite-password`,type:`password`,value:w,onChange:e=>T(e.target.value),placeholder:M?`Your password`:`Choose a password`,required:!0,"data-testid":`invite-password`})]}),A&&(0,m.jsx)(`p`,{className:`text-destructive text-sm`,children:A}),(0,m.jsxs)(u,{type:`submit`,className:`w-full`,disabled:O||!S||!w,"data-testid":`invite-submit`,children:[O?(0,m.jsx)(t,{className:`icon-base mr-2 animate-spin`}):null,M?`Sign In & Join`:`Create Account & Join`]})]}),(0,m.jsx)(`p`,{className:`text-muted-foreground text-sm`,children:M?(0,m.jsxs)(m.Fragment,{children:[`Don't have an account?`,` `,(0,m.jsx)(`button`,{type:`button`,className:`text-primary hover:underline`,onClick:()=>{N(!1),j(``)},"data-testid":`invite-switch-register`,children:`Register`})]}):(0,m.jsxs)(m.Fragment,{children:[`Already have an account?`,` `,(0,m.jsx)(`button`,{type:`button`,className:`text-primary hover:underline`,onClick:()=>{N(!0),j(``)},"data-testid":`invite-switch-login`,children:`Sign in`})]})})]}),o===`accepting`&&(0,m.jsx)(f,{fill:!1,testId:`accept-invite-accepting`,label:`Joining ${v}...`}),o===`success`&&(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(r,{className:`mx-auto size-8 text-green-500`}),(0,m.jsx)(`h2`,{className:`text-foreground text-lg font-semibold`,children:`You're in!`}),(0,m.jsxs)(`p`,{className:`text-muted-foreground text-sm`,children:[`You've successfully joined `,(0,m.jsx)(`span`,{className:`font-medium`,children:v}),`.`]}),(0,m.jsx)(u,{onClick:L,className:`w-full`,"data-testid":`invite-continue`,children:`Continue to App`})]}),o===`already`&&(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(r,{className:`mx-auto size-8 text-blue-500`}),(0,m.jsx)(`h2`,{className:`text-foreground text-lg font-semibold`,children:`Already a member`}),(0,m.jsxs)(`p`,{className:`text-muted-foreground text-sm`,children:[`You're already a member of `,(0,m.jsx)(`span`,{className:`font-medium`,children:v}),`.`]}),(0,m.jsx)(u,{onClick:L,className:`w-full`,"data-testid":`invite-continue`,children:`Continue to App`})]}),o===`error`&&(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(n,{className:`text-destructive mx-auto size-8`}),(0,m.jsx)(`h2`,{className:`text-foreground text-lg font-semibold`,children:`Invitation failed`}),(0,m.jsx)(`p`,{className:`text-muted-foreground text-sm`,children:g}),(0,m.jsx)(u,{variant:`outline`,onClick:L,className:`w-full`,"data-testid":`invite-continue`,children:`Go to App`})]})]})})}export{h as AcceptInvitePage};
@@ -1 +1 @@
1
- import{a as e}from"./rolldown-runtime-Cyuzqnbw.js";import{Dr as t,Gn as n,Lt as r,Mn as i,Rr as a,ir as o,kn as s,lr as c,sr as l,ut as u,wn as d,zr as f}from"./icons-sqwAEN28.js";import{o as p}from"./markdown-DBtwZWLP.js";import{t as m}from"./useTranslation-DAPPK3Hy.js";import{G as h,P as g,W as _,lt as v,q as y}from"./index-BsxcqNXe.js";import{t as b}from"./button-DeEOU1Fb.js";import{$r as x,Ct as S,Dr as C,Dt as w,Gr as T,Jr as ee,Ot as E,Tt as D,Ur as O,in as te,qr as k,wt as A,yr as ne}from"./items-_g3-I08l.js";import{t as j}from"./FileTree-DESC68xP.js";import{a as M,i as N,n as P,t as F}from"./diff-parse-738OLLMl.js";import{n as I}from"./review-pane-store-B31R8Yhv.js";import{n as re}from"./use-todo-panel-D9pAUf5W.js";var L=e(f(),1),R=new Set;function z(e){let t=S(),n=w()===`running`,[r,i]=(0,L.useState)(R),a=(0,L.useRef)(R),o=(0,L.useRef)(void 0),s=(0,L.useRef)(null);return(0,L.useEffect)(()=>{if(t!==o.current&&(o.current=t,i(R),a.current=R,s.current?.abort(),s.current=null),!t||!e)return;let r=!1,c=async()=>{s.current?.abort();let e=new AbortController;s.current=e;let n;try{n=await g.getTouchedFiles(t,e.signal)}catch{return}if(!(r||e.signal.aborted)&&n.isOk()){let e=n.value.files;if(e.length===0){a.current.size!==0&&(a.current=R,i(R));return}let t=new Set(e),r=a.current;(t.size!==r.size||![...t].every(e=>r.has(e)))&&(a.current=t,i(t))}};if(c(),n){let e=setInterval(c,5e3);return()=>{r=!0,s.current?.abort(),clearInterval(e)}}return()=>{r=!0,s.current?.abort()}},[t,n,e]),r}function B(e=!0){let t=S(),n=I(e=>e.dirtySignal),r=z(e),[i,a]=(0,L.useState)([]),[o,s]=(0,L.useState)(!1),[c,l]=(0,L.useState)(0),u=(0,L.useRef)(t);return(0,L.useEffect)(()=>{t!==u.current&&(u.current=t,a([]),s(!!t))},[t]),(0,L.useEffect)(()=>{if(!t){a([]);return}if(r.size===0){a([]),s(!1);return}let e=!1,n=setTimeout(async()=>{s(!0);let n;try{n=await g.getDiffSummary(t)}catch{e||s(!1);return}!e&&n.isOk()&&a(n.value.files.filter(e=>{for(let t of r)if(t.endsWith(`/${e.path}`)||t===e.path)return!0;return!1})),e||s(!1)},300);return()=>{e=!0,clearTimeout(n)}},[t,n,c,r]),{files:i,loading:o,refresh:(0,L.useCallback)(()=>l(e=>e+1),[])}}var V=e(p(),1),H={added:s,modified:i,deleted:d,renamed:i};function U(){let e=(0,L.useRef)([]),t=A();return(0,L.useMemo)(()=>{if(!t)return e.current.length===0||(e.current=[]),e.current;let n=[];for(let e of t)for(let t of e.toolCalls??[])n.push(t);let r=[];for(let e of n)if((e.name===`Task`||e.name===`Agent`)&&!e.output){let t=M(e.input),i=t.description??t.prompt??`Sub-agent`,a=n.filter(t=>t.parentToolCallId===e.id).length;r.push({id:e.id,description:i,childToolCallCount:a})}let i=e.current;return i.length===r.length&&r.every((e,t)=>e.id===i[t].id&&e.childToolCallCount===i[t].childToolCallCount)?i:(e.current=r,r)},[t])}function W({title:e,testId:t,count:n,children:r}){return(0,V.jsxs)(`div`,{"data-testid":t,children:[(0,V.jsxs)(`div`,{className:`border-border/50 flex items-center gap-2 border-b px-2 py-1.5`,children:[(0,V.jsx)(`span`,{className:`text-muted-foreground flex-1 text-xs font-semibold tracking-wider uppercase`,children:e}),n!==void 0&&n>0&&(0,V.jsx)(`span`,{className:`bg-muted text-muted-foreground rounded-full px-1.5 py-0.5 font-mono text-[10px]`,children:n})]}),r]})}function G({todos:e,progress:t}){let n=t.total>0?Math.round(t.completed/t.total*100):0,r=t.completed===t.total;return(0,V.jsxs)(`div`,{className:`mt-1.5 space-y-1.5`,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,V.jsx)(`div`,{className:`bg-muted h-1 flex-1 overflow-hidden rounded-full`,children:(0,V.jsx)(`div`,{className:v(`h-full rounded-full transition-all duration-500`,r?`bg-status-success/80`:`bg-status-info/80`),style:{width:`${n}%`}})}),(0,V.jsxs)(`span`,{className:v(`font-mono text-[10px]`,r?`text-status-success/80`:`text-muted-foreground`),children:[t.completed,`/`,t.total]})]}),(0,V.jsx)(`div`,{className:`space-y-1`,children:e.map((e,t)=>(0,V.jsxs)(`div`,{"data-testid":`activity-todo-${t}`,className:`flex items-start gap-2`,children:[e.status===`completed`?(0,V.jsx)(c,{className:`icon-sm text-status-success/80 mt-0.5 shrink-0`}):e.status===`in_progress`?(0,V.jsx)(l,{className:`icon-sm text-status-info mt-0.5 shrink-0 animate-pulse`}):(0,V.jsx)(o,{className:`icon-sm text-muted-foreground/50 mt-0.5 shrink-0`}),(0,V.jsx)(`span`,{className:v(`text-xs leading-relaxed`,e.status===`completed`&&`text-muted-foreground line-through`,e.status===`in_progress`&&`font-medium text-foreground`,e.status===`pending`&&`text-muted-foreground`),children:e.status===`in_progress`&&e.activeForm||e.content})]},e.content))})]})}function K({testId:e,icon:t,label:n,isRunning:i,childToolCallCount:a,todoSnapshot:o}){let{t:s}=m();return(0,V.jsxs)(`div`,{"data-testid":e,className:`px-2.5 py-2`,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2`,children:[i&&(0,V.jsx)(r,{className:`icon-xs text-muted-foreground shrink-0 animate-spin`}),(0,V.jsx)(t,{className:`icon-sm text-muted-foreground shrink-0`}),(0,V.jsx)(`span`,{className:`text-muted-foreground min-w-0 flex-1 truncate text-xs font-medium`,children:n}),a!==void 0&&a>0&&(0,V.jsxs)(`span`,{className:`bg-muted text-muted-foreground shrink-0 rounded px-1.5 py-0.5 font-mono text-[10px]`,children:[a,` `,s(`activity.toolCalls`,`tool calls`)]})]}),o&&(0,V.jsx)(G,{todos:o.todos,progress:o.progress})]})}function q({message:e}){return(0,V.jsx)(`div`,{className:`text-muted-foreground/50 px-4 py-3 text-center text-xs italic`,children:e})}function J(){let{t:e}=m(),r=U(),o=re(),s=w()===`running`,c=s||o.mainAgent!==null,l=+!!c+r.length,{files:d,loading:f,refresh:p}=B(),[v,A]=(0,L.useState)(null),[M,I]=(0,L.useState)(null),[R,z]=(0,L.useState)(new Map),[G,J]=(0,L.useState)(null),Y=S(),X=(0,L.useRef)(Y);(0,L.useEffect)(()=>{Y!==X.current&&(X.current=Y,A(null),I(null),z(new Map),J(null))},[Y]);let Z=E(),Q=D(),$=C(e=>e.projects),ie=(0,L.useMemo)(()=>Z||(Q?$.find(e=>e.id===Q)?.path??``:``),[Z,Q,$]),ae=(0,L.useCallback)(async e=>{if(!Y||R.has(e))return;let t=d.find(t=>t.path===e);if(!t)return;J(e);let n=await g.getFileDiff(Y,e,t.staged);n.isOk()&&z(t=>new Map(t).set(e,n.value.diff)),J(t=>t===e?null:t)},[Y,R,d]);(0,L.useEffect)(()=>{M&&!R.has(M)&&ae(M)},[M]);let oe=(0,L.useCallback)(async e=>{if(!Y)return null;let t=d.find(t=>t.path===e);if(!t)return null;let n=await g.getFileDiff(Y,e,t.staged,void 0,`full`);return n.isOk()?{oldValue:P(n.value.diff),newValue:F(n.value.diff),rawDiff:n.value.diff}:null},[Y,d]),se=(0,L.useCallback)(async t=>{if(!Y)return;let n=await g.revertFiles(Y,[t]);n.isErr()?O.error(e(`review.revertFailed`,{message:n.error.message})):(O.success(e(`review.revertSuccess`,{path:t,defaultValue:`{{path}} reverted`})),z(e=>{let n=new Map(e);return n.delete(t),n}),p())},[Y,e,p]),ce=(0,L.useCallback)(e=>{A(e),I(e)},[]);return Y?(0,V.jsxs)(`div`,{"data-testid":`activity-pane`,className:`flex h-full flex-col`,children:[(0,V.jsxs)(`div`,{className:`border-sidebar-border flex shrink-0 items-center justify-between border-b px-4 py-3`,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,V.jsx)(a,{className:`icon-base text-muted-foreground`}),(0,V.jsx)(`h3`,{className:`text-sidebar-foreground text-xs font-semibold tracking-wider uppercase`,children:e(`activity.title`,`Activity`)})]}),(0,V.jsxs)(_,{children:[(0,V.jsx)(y,{asChild:!0,children:(0,V.jsx)(b,{variant:`ghost`,size:`icon-xs`,onClick:()=>ne.getState().setReviewPaneOpen(!1),className:`text-muted-foreground`,"data-testid":`activity-close`,children:(0,V.jsx)(u,{className:`icon-sm`})})}),(0,V.jsx)(h,{side:`bottom`,children:e(`common.close`,`Close`)})]})]}),(0,V.jsx)(te,{className:`min-h-0 flex-1`,children:(0,V.jsxs)(`div`,{className:`space-y-3 p-3`,children:[(0,V.jsx)(W,{title:e(`activity.agents`,`Agents`),testId:`activity-agents`,count:l,children:l>0?(0,V.jsxs)(`div`,{className:`space-y-1.5 px-2 py-1.5`,children:[c&&(0,V.jsx)(K,{testId:`activity-agent-main`,icon:n,label:e(`activity.mainAgent`,`Main agent`),isRunning:!!s,todoSnapshot:o.mainAgent}),r.map(e=>(0,V.jsx)(K,{testId:`activity-agent-${e.id}`,icon:t,label:e.description,isRunning:!0,childToolCallCount:e.childToolCallCount,todoSnapshot:o.bySubAgent.get(e.id)??null},e.id))]}):(0,V.jsx)(q,{message:e(`activity.noAgents`,`No running agents`)})}),(0,V.jsx)(W,{title:e(`activity.files`,`Modified Files`),testId:`activity-files`,count:d.length,children:d.length>0?(0,V.jsx)(j,{files:d,selectedFile:v,onFileClick:ce,onRevertFile:se,basePath:ie,diffStatsSize:`xs`,fontSize:`text-xs`,testIdPrefix:`activity-file`}):(0,V.jsx)(q,{message:f?e(`activity.loadingFiles`,`Loading...`):e(`activity.noFiles`,`No modified files`)})})]})}),(0,V.jsx)(T,{open:!!M,onOpenChange:e=>{e||I(null)},children:(0,V.jsx)(k,{className:`flex h-[85vh] w-[90vw] max-w-[90vw] flex-col gap-0 overflow-hidden p-0`,"data-testid":`activity-expanded-diff-overlay`,children:(()=>{let t=M?d.find(e=>e.path===M):void 0,n=M?R.get(M):void 0,r=t&&H[t.status]||i;return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(x,{className:`sr-only`,children:t?.path??e(`review.diffViewer`,`Diff viewer`)}),(0,V.jsx)(ee,{className:`sr-only`,children:e(`review.diffViewerDescription`,`View and stage changes for the selected file`)}),M&&(0,V.jsx)(`div`,{className:`flex min-h-0 min-w-0 flex-1`,children:(0,V.jsx)(`div`,{className:`flex min-w-0 flex-1 flex-col`,children:(0,V.jsx)(N,{filePath:t?.path||M,oldValue:n?P(n):``,newValue:n?F(n):``,icon:r,loading:G===M,rawDiff:n,files:d,onFileSelect:e=>{A(e),I(e)},diffCache:R,onClose:()=>I(null),onRequestFullDiff:oe})})})]})})()})})]}):(0,V.jsx)(`div`,{"data-testid":`activity-pane`,className:`text-muted-foreground flex h-full items-center justify-center text-sm`,children:e(`activity.noThread`,`Select a thread to see activity`)})}export{J as ActivityPane};
1
+ import{a as e}from"./rolldown-runtime-Cyuzqnbw.js";import{Dr as t,Gn as n,Lt as r,Mn as i,Rr as a,ir as o,kn as s,lr as c,sr as l,ut as u,wn as d,zr as f}from"./icons-sqwAEN28.js";import{o as p}from"./markdown-DBtwZWLP.js";import{t as m}from"./useTranslation-DAPPK3Hy.js";import{G as h,P as g,W as _,lt as v,q as y}from"./index-Bmp1UFM1.js";import{t as b}from"./button-Bi9_EZFh.js";import{$r as x,Ct as S,Dr as C,Dt as w,Gr as T,Jr as ee,Ot as E,Tt as D,Ur as O,in as te,qr as k,wt as A,yr as ne}from"./items-C-m69VjA.js";import{t as j}from"./FileTree-DUODDbNL.js";import{a as M,i as N,n as P,t as F}from"./diff-parse-CRTMJKOI.js";import{n as I}from"./review-pane-store-B31R8Yhv.js";import{n as re}from"./use-todo-panel-CsXYDjtr.js";var L=e(f(),1),R=new Set;function z(e){let t=S(),n=w()===`running`,[r,i]=(0,L.useState)(R),a=(0,L.useRef)(R),o=(0,L.useRef)(void 0),s=(0,L.useRef)(null);return(0,L.useEffect)(()=>{if(t!==o.current&&(o.current=t,i(R),a.current=R,s.current?.abort(),s.current=null),!t||!e)return;let r=!1,c=async()=>{s.current?.abort();let e=new AbortController;s.current=e;let n;try{n=await g.getTouchedFiles(t,e.signal)}catch{return}if(!(r||e.signal.aborted)&&n.isOk()){let e=n.value.files;if(e.length===0){a.current.size!==0&&(a.current=R,i(R));return}let t=new Set(e),r=a.current;(t.size!==r.size||![...t].every(e=>r.has(e)))&&(a.current=t,i(t))}};if(c(),n){let e=setInterval(c,5e3);return()=>{r=!0,s.current?.abort(),clearInterval(e)}}return()=>{r=!0,s.current?.abort()}},[t,n,e]),r}function B(e=!0){let t=S(),n=I(e=>e.dirtySignal),r=z(e),[i,a]=(0,L.useState)([]),[o,s]=(0,L.useState)(!1),[c,l]=(0,L.useState)(0),u=(0,L.useRef)(t);return(0,L.useEffect)(()=>{t!==u.current&&(u.current=t,a([]),s(!!t))},[t]),(0,L.useEffect)(()=>{if(!t){a([]);return}if(r.size===0){a([]),s(!1);return}let e=!1,n=setTimeout(async()=>{s(!0);let n;try{n=await g.getDiffSummary(t)}catch{e||s(!1);return}!e&&n.isOk()&&a(n.value.files.filter(e=>{for(let t of r)if(t.endsWith(`/${e.path}`)||t===e.path)return!0;return!1})),e||s(!1)},300);return()=>{e=!0,clearTimeout(n)}},[t,n,c,r]),{files:i,loading:o,refresh:(0,L.useCallback)(()=>l(e=>e+1),[])}}var V=e(p(),1),H={added:s,modified:i,deleted:d,renamed:i};function U(){let e=(0,L.useRef)([]),t=A();return(0,L.useMemo)(()=>{if(!t)return e.current.length===0||(e.current=[]),e.current;let n=[];for(let e of t)for(let t of e.toolCalls??[])n.push(t);let r=[];for(let e of n)if((e.name===`Task`||e.name===`Agent`)&&!e.output){let t=M(e.input),i=t.description??t.prompt??`Sub-agent`,a=n.filter(t=>t.parentToolCallId===e.id).length;r.push({id:e.id,description:i,childToolCallCount:a})}let i=e.current;return i.length===r.length&&r.every((e,t)=>e.id===i[t].id&&e.childToolCallCount===i[t].childToolCallCount)?i:(e.current=r,r)},[t])}function W({title:e,testId:t,count:n,children:r}){return(0,V.jsxs)(`div`,{"data-testid":t,children:[(0,V.jsxs)(`div`,{className:`border-border/50 flex items-center gap-2 border-b px-2 py-1.5`,children:[(0,V.jsx)(`span`,{className:`text-muted-foreground flex-1 text-xs font-semibold tracking-wider uppercase`,children:e}),n!==void 0&&n>0&&(0,V.jsx)(`span`,{className:`bg-muted text-muted-foreground rounded-full px-1.5 py-0.5 font-mono text-[10px]`,children:n})]}),r]})}function G({todos:e,progress:t}){let n=t.total>0?Math.round(t.completed/t.total*100):0,r=t.completed===t.total;return(0,V.jsxs)(`div`,{className:`mt-1.5 space-y-1.5`,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,V.jsx)(`div`,{className:`bg-muted h-1 flex-1 overflow-hidden rounded-full`,children:(0,V.jsx)(`div`,{className:v(`h-full rounded-full transition-all duration-500`,r?`bg-status-success/80`:`bg-status-info/80`),style:{width:`${n}%`}})}),(0,V.jsxs)(`span`,{className:v(`font-mono text-[10px]`,r?`text-status-success/80`:`text-muted-foreground`),children:[t.completed,`/`,t.total]})]}),(0,V.jsx)(`div`,{className:`space-y-1`,children:e.map((e,t)=>(0,V.jsxs)(`div`,{"data-testid":`activity-todo-${t}`,className:`flex items-start gap-2`,children:[e.status===`completed`?(0,V.jsx)(c,{className:`icon-sm text-status-success/80 mt-0.5 shrink-0`}):e.status===`in_progress`?(0,V.jsx)(l,{className:`icon-sm text-status-info mt-0.5 shrink-0 animate-pulse`}):(0,V.jsx)(o,{className:`icon-sm text-muted-foreground/50 mt-0.5 shrink-0`}),(0,V.jsx)(`span`,{className:v(`text-xs leading-relaxed`,e.status===`completed`&&`text-muted-foreground line-through`,e.status===`in_progress`&&`font-medium text-foreground`,e.status===`pending`&&`text-muted-foreground`),children:e.status===`in_progress`&&e.activeForm||e.content})]},e.content))})]})}function K({testId:e,icon:t,label:n,isRunning:i,childToolCallCount:a,todoSnapshot:o}){let{t:s}=m();return(0,V.jsxs)(`div`,{"data-testid":e,className:`px-2.5 py-2`,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2`,children:[i&&(0,V.jsx)(r,{className:`icon-xs text-muted-foreground shrink-0 animate-spin`}),(0,V.jsx)(t,{className:`icon-sm text-muted-foreground shrink-0`}),(0,V.jsx)(`span`,{className:`text-muted-foreground min-w-0 flex-1 truncate text-xs font-medium`,children:n}),a!==void 0&&a>0&&(0,V.jsxs)(`span`,{className:`bg-muted text-muted-foreground shrink-0 rounded px-1.5 py-0.5 font-mono text-[10px]`,children:[a,` `,s(`activity.toolCalls`,`tool calls`)]})]}),o&&(0,V.jsx)(G,{todos:o.todos,progress:o.progress})]})}function q({message:e}){return(0,V.jsx)(`div`,{className:`text-muted-foreground/50 px-4 py-3 text-center text-xs italic`,children:e})}function J(){let{t:e}=m(),r=U(),o=re(),s=w()===`running`,c=s||o.mainAgent!==null,l=+!!c+r.length,{files:d,loading:f,refresh:p}=B(),[v,A]=(0,L.useState)(null),[M,I]=(0,L.useState)(null),[R,z]=(0,L.useState)(new Map),[G,J]=(0,L.useState)(null),Y=S(),X=(0,L.useRef)(Y);(0,L.useEffect)(()=>{Y!==X.current&&(X.current=Y,A(null),I(null),z(new Map),J(null))},[Y]);let Z=E(),Q=D(),$=C(e=>e.projects),ie=(0,L.useMemo)(()=>Z||(Q?$.find(e=>e.id===Q)?.path??``:``),[Z,Q,$]),ae=(0,L.useCallback)(async e=>{if(!Y||R.has(e))return;let t=d.find(t=>t.path===e);if(!t)return;J(e);let n=await g.getFileDiff(Y,e,t.staged);n.isOk()&&z(t=>new Map(t).set(e,n.value.diff)),J(t=>t===e?null:t)},[Y,R,d]);(0,L.useEffect)(()=>{M&&!R.has(M)&&ae(M)},[M]);let oe=(0,L.useCallback)(async e=>{if(!Y)return null;let t=d.find(t=>t.path===e);if(!t)return null;let n=await g.getFileDiff(Y,e,t.staged,void 0,`full`);return n.isOk()?{oldValue:P(n.value.diff),newValue:F(n.value.diff),rawDiff:n.value.diff}:null},[Y,d]),se=(0,L.useCallback)(async t=>{if(!Y)return;let n=await g.revertFiles(Y,[t]);n.isErr()?O.error(e(`review.revertFailed`,{message:n.error.message})):(O.success(e(`review.revertSuccess`,{path:t,defaultValue:`{{path}} reverted`})),z(e=>{let n=new Map(e);return n.delete(t),n}),p())},[Y,e,p]),ce=(0,L.useCallback)(e=>{A(e),I(e)},[]);return Y?(0,V.jsxs)(`div`,{"data-testid":`activity-pane`,className:`flex h-full flex-col`,children:[(0,V.jsxs)(`div`,{className:`border-sidebar-border flex shrink-0 items-center justify-between border-b px-4 py-3`,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,V.jsx)(a,{className:`icon-base text-muted-foreground`}),(0,V.jsx)(`h3`,{className:`text-sidebar-foreground text-xs font-semibold tracking-wider uppercase`,children:e(`activity.title`,`Activity`)})]}),(0,V.jsxs)(_,{children:[(0,V.jsx)(y,{asChild:!0,children:(0,V.jsx)(b,{variant:`ghost`,size:`icon-xs`,onClick:()=>ne.getState().setReviewPaneOpen(!1),className:`text-muted-foreground`,"data-testid":`activity-close`,children:(0,V.jsx)(u,{className:`icon-sm`})})}),(0,V.jsx)(h,{side:`bottom`,children:e(`common.close`,`Close`)})]})]}),(0,V.jsx)(te,{className:`min-h-0 flex-1`,children:(0,V.jsxs)(`div`,{className:`space-y-3 p-3`,children:[(0,V.jsx)(W,{title:e(`activity.agents`,`Agents`),testId:`activity-agents`,count:l,children:l>0?(0,V.jsxs)(`div`,{className:`space-y-1.5 px-2 py-1.5`,children:[c&&(0,V.jsx)(K,{testId:`activity-agent-main`,icon:n,label:e(`activity.mainAgent`,`Main agent`),isRunning:!!s,todoSnapshot:o.mainAgent}),r.map(e=>(0,V.jsx)(K,{testId:`activity-agent-${e.id}`,icon:t,label:e.description,isRunning:!0,childToolCallCount:e.childToolCallCount,todoSnapshot:o.bySubAgent.get(e.id)??null},e.id))]}):(0,V.jsx)(q,{message:e(`activity.noAgents`,`No running agents`)})}),(0,V.jsx)(W,{title:e(`activity.files`,`Modified Files`),testId:`activity-files`,count:d.length,children:d.length>0?(0,V.jsx)(j,{files:d,selectedFile:v,onFileClick:ce,onRevertFile:se,basePath:ie,diffStatsSize:`xs`,fontSize:`text-xs`,testIdPrefix:`activity-file`}):(0,V.jsx)(q,{message:f?e(`activity.loadingFiles`,`Loading...`):e(`activity.noFiles`,`No modified files`)})})]})}),(0,V.jsx)(T,{open:!!M,onOpenChange:e=>{e||I(null)},children:(0,V.jsx)(k,{className:`flex h-[85vh] w-[90vw] max-w-[90vw] flex-col gap-0 overflow-hidden p-0`,"data-testid":`activity-expanded-diff-overlay`,children:(()=>{let t=M?d.find(e=>e.path===M):void 0,n=M?R.get(M):void 0,r=t&&H[t.status]||i;return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(x,{className:`sr-only`,children:t?.path??e(`review.diffViewer`,`Diff viewer`)}),(0,V.jsx)(ee,{className:`sr-only`,children:e(`review.diffViewerDescription`,`View and stage changes for the selected file`)}),M&&(0,V.jsx)(`div`,{className:`flex min-h-0 min-w-0 flex-1`,children:(0,V.jsx)(`div`,{className:`flex min-w-0 flex-1 flex-col`,children:(0,V.jsx)(N,{filePath:t?.path||M,oldValue:n?P(n):``,newValue:n?F(n):``,icon:r,loading:G===M,rawDiff:n,files:d,onFileSelect:e=>{A(e),I(e)},diffCache:R,onClose:()=>I(null),onRequestFullDiff:oe})})})]})})()})})]}):(0,V.jsx)(`div`,{"data-testid":`activity-pane`,className:`text-muted-foreground flex h-full items-center justify-center text-sm`,children:e(`activity.noThread`,`Select a thread to see activity`)})}export{J as ActivityPane};
@@ -1 +1 @@
1
- import{a as e,t}from"./rolldown-runtime-Cyuzqnbw.js";import{Ft as n,It as r,Kn as i,L as a,Lt as o,Mr as s,Q as c,on as l,yn as u,yr as d,zn as f,zr as p}from"./icons-sqwAEN28.js";import{o as m}from"./markdown-DBtwZWLP.js";import{i as h}from"./_core-lD_pNs53.js";import{a as g,i as _,n as v,o as y,r as b,t as x}from"./useTranslation-DAPPK3Hy.js";import{i as S,n as C,r as ee}from"./initReactI18next-Dr0vnWXF.js";import{G as w,P as T,W as te,_t as E,j as D,lt as O,q as k}from"./index-BsxcqNXe.js";import{t as A}from"./button-DeEOU1Fb.js";import{$r as ne,Gr as re,Jr as j,K as ie,Nn as M,Rt as N,Ur as P,Wn as F,Xr as ae,Yr as I,gt as oe,in as se,mn as ce,qr as L,yr as le}from"./items-_g3-I08l.js";import{t as R}from"./input-DV30TVat.js";import{t as ue}from"./loading-state-BQjalkhM.js";import{t as de}from"./app-store-BwZB2xp_.js";import{t as fe}from"./FolderPicker-B5JTJeAY.js";var pe=e(t(((e,t)=>{t.exports={area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0}}))()),z=/\s([^'"/\s><]+?)[\s/>]|([^\s=]+)=\s?(".*?"|'.*?')/g;function B(e){var t={type:`tag`,name:``,voidElement:!1,attrs:{},children:[]},n=e.match(/<\/?([^\s]+?)[/\s>]/);if(n&&(t.name=n[1],(pe.default[n[1]]||e.charAt(e.length-2)===`/`)&&(t.voidElement=!0),t.name.startsWith(`!--`))){var r=e.indexOf(`-->`);return{type:`comment`,comment:r===-1?``:e.slice(4,r)}}for(var i=new RegExp(z),a=null;(a=i.exec(e))!==null;)if(a[0].trim())if(a[1]){var o=a[1].trim(),s=[o,``];o.indexOf(`=`)>-1&&(s=o.split(`=`)),t.attrs[s[0]]=s[1],i.lastIndex--}else a[2]&&(t.attrs[a[2]]=a[3].trim().substring(1,a[3].length-1));return t}var V=/<[a-zA-Z0-9\-\!\/](?:"[^"]*"|'[^']*'|[^'">])*>/g,me=/^\s*$/,he=Object.create(null);function ge(e,t){switch(t.type){case`text`:return e+t.content;case`tag`:return e+=`<`+t.name+(t.attrs?function(e){var t=[];for(var n in e)t.push(n+`="`+e[n]+`"`);return t.length?` `+t.join(` `):``}(t.attrs):``)+(t.voidElement?`/>`:`>`),t.voidElement?e:e+t.children.reduce(ge,``)+`</`+t.name+`>`;case`comment`:return e+`<!--`+t.comment+`-->`}}var _e={parse:function(e,t){t||={},t.components||=he;var n,r=[],i=[],a=-1,o=!1;if(e.indexOf(`<`)!==0){var s=e.indexOf(`<`);r.push({type:`text`,content:s===-1?e:e.substring(0,s)})}return e.replace(V,function(s,c){if(o){if(s!==`</`+n.name+`>`)return;o=!1}var l,u=s.charAt(1)!==`/`,d=s.startsWith(`<!--`),f=c+s.length,p=e.charAt(f);if(d){var m=B(s);return a<0?(r.push(m),r):((l=i[a]).children.push(m),r)}if(u&&(a++,(n=B(s)).type===`tag`&&t.components[n.name]&&(n.type=`component`,o=!0),n.voidElement||o||!p||p===`<`||n.children.push({type:`text`,content:e.slice(f,e.indexOf(`<`,f))}),a===0&&r.push(n),(l=i[a-1])&&l.children.push(n),i[a]=n),(!u||n.voidElement)&&(a>-1&&(n.voidElement||n.name===s.slice(2,-1))&&(a--,n=a===-1?r:i[a]),!o&&p!==`<`&&p)){l=a===-1?r:i[a].children;var h=e.indexOf(`<`,f),g=e.slice(f,h===-1?void 0:h);me.test(g)&&(g=` `),(h>-1&&a+l.length>=0||g!==` `)&&l.push({type:`text`,content:g})}}),r},stringify:function(e){return e.reduce(function(e,t){return e+ge(``,t)},``)}},H=e(p()),U=(e,t)=>{if(!e)return!1;let n=e.props?.children??e.children;return t?n.length>0:!!n},W=e=>{if(!e)return[];let t=e.props?.children??e.children;return e.props?.i18nIsDynamicList?K(t):t},G=e=>Array.isArray(e)&&e.every(H.isValidElement),K=e=>Array.isArray(e)?e:[e],ve=(e,t)=>{let n={...t};return n.props={...t.props,...e.props},n},q=e=>{let t={};if(!e)return t;let n=e=>{K(e).forEach(e=>{_(e)||(U(e)?n(W(e)):b(e)&&!(0,H.isValidElement)(e)&&Object.assign(t,e))})};return n(e),t},J=(e,t,n,r)=>{if(!e)return``;let i=``,a=K(e),o=t?.transSupportBasicHtmlNodes?t.transKeepBasicHtmlNodesFor??[]:[];return a.forEach((e,a)=>{if(_(e)){i+=`${e}`;return}if((0,H.isValidElement)(e)){let{props:s,type:c}=e,l=Object.keys(s).length,u=o.indexOf(c)>-1,d=s.children;if(!d&&u&&!l){i+=`<${c}/>`;return}if(!d&&(!u||l)||s.i18nIsDynamicList){i+=`<${a}></${a}>`;return}if(u&&l<=1){let e=_(d)?d:J(d,t,n,r);i+=`<${c}>${e}</${c}>`;return}let f=J(d,t,n,r);i+=`<${a}>${f}</${a}>`;return}if(e===null){g(n,`TRANS_NULL_VALUE`,`Passed in a null value as child`,{i18nKey:r});return}if(b(e)){let{format:t,...a}=e,o=Object.keys(a);if(o.length===1){let e=t?`${o[0]}, ${t}`:o[0];i+=`{{${e}}}`;return}g(n,`TRANS_INVALID_OBJ`,`Invalid child - Object should only have keys {{ value, format }} (format is optional).`,{i18nKey:r,child:e});return}g(n,`TRANS_INVALID_VAR`,`Passed in a variable like {number} - pass variables for interpolation as full objects like {{number}}.`,{i18nKey:r,child:e})}),i},ye=(e,t=[],n={})=>{if(!e)return e;let r=Object.keys(n),i=[...t,...r],a=``,o=0;for(;o<e.length;)if(e[o]===`<`){let t=!1,n=e.slice(o).match(/^<\/(\d+|[a-zA-Z][a-zA-Z0-9_-]*)>/);if(n){let e=n[1];(/^\d+$/.test(e)||i.includes(e))&&(t=!0,a+=n[0],o+=n[0].length)}if(!t){let n=e.slice(o).match(/^<(\d+|[a-zA-Z][a-zA-Z0-9_-]*)(\s+[\w-]+(?:=(?:"[^"]*"|'[^']*'|[^\s>]+))?)*\s*(\/)?>/);if(n){let e=n[1];(/^\d+$/.test(e)||i.includes(e))&&(t=!0,a+=n[0],o+=n[0].length)}}t||(a+=`&lt;`,o+=1)}else a+=e[o],o+=1;return a},be=(e,t,n,r,i,a,o)=>{if(n===``)return[];let s=i.transKeepBasicHtmlNodesFor||[],c=n&&new RegExp(s.map(e=>`<${e}`).join(`|`)).test(n);if(!e&&!t&&!c&&!o)return[n];let l=t??{},u=e=>{K(e).forEach(e=>{_(e)||(U(e)?u(W(e)):b(e)&&!(0,H.isValidElement)(e)&&Object.assign(l,e))})};u(e);let d=ye(n,s,l),f=_e.parse(`<0>${d}</0>`),p={...l,...a},m=(e,t,n)=>{let r=W(e),i=g(r,t.children,n);return G(r)&&i.length===0||e.props?.i18nIsDynamicList?r:i},h=(e,t,n,r,i)=>{e.dummy?(e.children=t,n.push((0,H.cloneElement)(e,{key:r},i?void 0:t))):n.push(...H.Children.map([e],e=>{if(e.type===H.Fragment||e.props?.i18nIsDynamicList!==void 0){let n={key:r};return e&&e.props&&Object.keys(e.props).forEach(t=>{t===`children`||t===`i18nIsDynamicList`||(n[t]=e.props[t])}),(0,H.createElement)(e.type,n,i?null:t)}let n={key:r};return e&&e.props&&Object.keys(e.props).forEach(t=>{t===`ref`||t===`children`||(n[t]=e.props[t])}),(0,H.cloneElement)(e,n,i?null:t)}))},g=(e,n,a)=>{let l=K(e),u=K(n),d={};return u.reduce((e,n,u)=>{let f=n.children?.[0]?.content&&r.services.interpolator.interpolate(n.children[0].content,p,r.language);if(n.type===`tag`){let v=l[parseInt(n.name,10)];!v&&t&&(v=t[n.name]),a.length===1&&!v&&(v=a[0][n.name]),v||={};let y={...n.attrs};o&&Object.keys(y).forEach(e=>{let t=y[e];_(t)&&(y[e]=S(t))});let x=Object.keys(y).length===0?v:ve({props:y},v),C=(0,H.isValidElement)(x),ee=C&&U(n,!0)&&!n.voidElement,w=c&&b(x)&&x.dummy&&!C,T=b(t)&&Object.hasOwnProperty.call(t,n.name);if(_(x)){let t=r.services.interpolator.interpolate(x,p,r.language);e.push(t)}else if(U(x)||ee)h(x,m(x,n,a),e,u);else if(w)h(x,g(l,n.children,a),e,u);else if(Number.isNaN(parseFloat(n.name)))if(T)h(x,m(x,n,a),e,u,n.voidElement);else if(i.transSupportBasicHtmlNodes&&s.indexOf(n.name)>-1)if(n.voidElement)e.push((0,H.createElement)(n.name,{key:`${n.name}-${u}`}));else{let t=d[n.name]||0;d[n.name]=t+1;let r,i=0;for(let e=0;e<l.length;e+=1){let a=l[e];if((0,H.isValidElement)(a)&&a.type===n.name){if(i===t){r=a;break}i+=1}}let o=g(r?K(W(r)):l,n.children,a);e.push((0,H.createElement)(n.name,{key:`${n.name}-${u}`},o))}else if(n.voidElement)e.push(`<${n.name} />`);else{let t=g(l,n.children,a);e.push(`<${n.name}>${t}</${n.name}>`)}else if(b(x)&&!C){let t=n.children[0]?f:null;t&&e.push(t)}else h(x,f,e,u,n.children.length!==1||!f)}else if(n.type===`text`){let t=i.transWrapTextNodes,a=typeof i.unescape==`function`?i.unescape:ee().unescape,s=o?a(r.services.interpolator.interpolate(n.content,p,r.language)):r.services.interpolator.interpolate(n.content,p,r.language);t?e.push((0,H.createElement)(t,{key:`${n.name}-${u}`},s)):e.push(s)}return e},[])};return W(g([{dummy:!0,children:e||[]}],f,K(e||[]))[0])},Y=(e,t,n)=>{let r=e.key||t,i=(0,H.cloneElement)(e,{key:r});if(!i.props||!i.props.children||n.indexOf(`${t}/>`)<0&&n.indexOf(`${t} />`)<0)return i;function a(){return(0,H.createElement)(H.Fragment,null,i)}return(0,H.createElement)(a,{key:r})},xe=(e,t)=>e.map((e,n)=>Y(e,n,t)),X=(e,t)=>{let n={};return Object.keys(e).forEach(r=>{Object.assign(n,{[r]:Y(e[r],r,t)})}),n},Se=(e,t,n,r)=>e?Array.isArray(e)?xe(e,t):b(e)?X(e,t):(y(n,`TRANS_INVALID_COMPONENTS`,`<Trans /> "components" prop expects an object or array`,{i18nKey:r}),null):null,Z=e=>!b(e)||Array.isArray(e)?!1:Object.keys(e).reduce((e,t)=>e&&Number.isNaN(Number.parseFloat(t)),!0);function Ce({children:e,count:t,parent:n,i18nKey:r,context:i,tOptions:a={},values:o,defaults:s,components:c,ns:l,i18n:u,t:d,shouldUnescape:f,...p}){let m=u||C();if(!m)return y(m,`NO_I18NEXT_INSTANCE`,`Trans: You need to pass in an i18next instance using i18nextReactModule`,{i18nKey:r}),e;let g=d||m.t.bind(m)||(e=>e),v={...ee(),...m.options?.react},b=l||g.ns||m.options?.defaultNS;b=_(b)?[b]:b||[`translation`];let{transDefaultProps:x}=v,S=x?.tOptions?{...x.tOptions,...a}:a,w=f??x?.shouldUnescape,T=x?.values?{...x.values,...o}:o,te=x?.components?{...x.components,...c}:c,E=J(e,v,m,r),D=s||S?.defaultValue||E||v.transEmptyNodeValue||(typeof r==`function`?h(r):r),{hashTransKey:O}=v,k=r||(O?O(E||D):E||D);o=m.options?.interpolation?.defaultVariables?T&&Object.keys(T).length>0?{...T,...m.options.interpolation.defaultVariables}:{...m.options.interpolation.defaultVariables}:T;let A=q(e);A&&typeof A.count==`number`&&t===void 0&&(t=A.count);let ne=o||t!==void 0&&!m.options?.interpolation?.alwaysFormat||!e?S.interpolation:{interpolation:{...S.interpolation,prefix:`#$?`,suffix:`?$#`}},re={...S,context:i||S.context,count:t,...o,...ne,defaultValue:D,ns:b},j=k?g(k,re):D;j===k&&D&&(j=D);let ie=Se(te,j,m,r),M=ie||e,N=null;Z(ie)&&(N=ie,M=e);let P=be(M,N,j,m,v,re,w),F=n??v.defaultTransParent;return F?(0,H.createElement)(F,p,P):P}function we({children:e,count:t,parent:n,i18nKey:r,context:i,tOptions:a={},values:o,defaults:s,components:c,ns:l,i18n:u,t:d,shouldUnescape:f,...p}){let{i18n:m,defaultNS:h}=(0,H.useContext)(v)||{},g=u||m||C(),_=d||g?.t.bind(g);return Ce({children:e,count:t,parent:n,i18nKey:r,context:i,tOptions:a,values:o,defaults:s,components:c,ns:l||_?.ns||h||g?.options?.defaultNS,i18n:g,t:d,shouldUnescape:f,...p})}var Q=e(m(),1),Te=D(`clone-repo-view`);function Ee({onCloningChange:e}={}){let{t}=x(),c=E(),p=de(e=>e.loadProjects),m=de(e=>e.setAddProjectOpen),h=le(e=>e.generalSettingsOpen),[g,_]=(0,H.useState)(`checking`);(0,H.useEffect)(()=>{e?.(g===`cloning`)},[g,e]);let[v,y]=(0,H.useState)(null),[b,S]=(0,H.useState)(null),[C,ee]=(0,H.useState)(``),[w,te]=(0,H.useState)(``),[D,k]=(0,H.useState)(``),[ne,re]=(0,H.useState)(5),[j,ae]=ie(),I=(0,H.useRef)(null),[L,pe]=(0,H.useState)([]),[z,B]=(0,H.useState)(``),[V,me]=(0,H.useState)(``),[he,ge]=(0,H.useState)(!1),[_e,U]=(0,H.useState)(!1),[W,G]=(0,H.useState)(-1),K=(0,H.useRef)(null),ve=(0,H.useRef)(null),q=(0,H.useRef)(void 0),J=(0,H.useRef)(!1),ye=(0,H.useRef)(0),be=(0,H.useRef)(1),[Y,xe]=(0,H.useState)(null),[X,Se]=(0,H.useState)(``),[Z,Ce]=(0,H.useState)(``),[Ee,De]=(0,H.useState)(!1),[Oe,ke]=(0,H.useState)(!1),[Ae,je]=(0,H.useState)(``),[Me,Ne]=(0,H.useState)(void 0),[Pe,Fe]=(0,H.useState)(!1),Ie=(0,H.useRef)(``);(0,H.useEffect)(()=>{let e=e=>{let t=e.detail;if(t.phase){let e=t.phase.replace(/:.*$/,``).trim();e!==Ie.current&&(Fe(!0),Ie.current=e,requestAnimationFrame(()=>Fe(!1))),je(t.phase)}t.percent!==void 0&&Ne(t.percent)};return window.addEventListener(`clone:progress`,e),()=>window.removeEventListener(`clone:progress`,e)},[]);let $=(0,H.useCallback)(async()=>{let e=await T.githubStatus();e.isOk()?e.value.connected?(S(e.value.source??`profile`),await Le(),_(`repos`)):(S(null),_(`connect`)):_(`error`)},[]);(0,H.useEffect)(()=>{$()},[$]),(0,H.useEffect)(()=>{!h&&(g===`connect`||g===`error`)&&$()},[h,g,$]);let Le=async()=>{let e=await T.githubUser();e.isOk()&&y(e.value)},Re=(0,H.useCallback)(async(e,t,n)=>{let r=++ye.current;J.current=!0,U(!0),Te.debug(`github repo search`,{page:e,query:t,append:n});let i=await T.githubRepos({page:e,per_page:30,sort:`updated`,search:t||void 0});r===ye.current&&(i.isOk()&&(pe(e=>n?[...e,...i.value.repos]:i.value.repos),ge(i.value.hasMore)),J.current=!1,U(!1))},[]);(0,H.useEffect)(()=>(q.current&&clearTimeout(q.current),q.current=setTimeout(()=>{me(z)},200),()=>{q.current&&clearTimeout(q.current)}),[z]);let ze=z!==V||_e;(0,H.useEffect)(()=>{G(-1)},[V]);let Be=e=>{if(e.key===`ArrowDown`)e.preventDefault(),G(e=>Math.min(e+1,L.length-1));else if(e.key===`ArrowUp`)e.preventDefault(),G(e=>Math.max(e-1,0));else if(e.key===`Enter`&&W>=0&&W<L.length){e.preventDefault();let t=L[W];xe(t),Ce(t.name),_(`clone-config`)}};(0,H.useEffect)(()=>{W<0||!K.current||K.current.querySelectorAll(`[data-repo-item]`)[W]?.scrollIntoView({block:`nearest`})},[W]),(0,H.useEffect)(()=>{g===`repos`&&(be.current=1,Re(1,V,!1))},[g,V,Re]),(0,H.useEffect)(()=>{if(g!==`repos`)return;let e=K.current,t=ve.current;if(!e||!t)return;let n=new IntersectionObserver(e=>{if(!e[0]?.isIntersecting||J.current||!he)return;let t=be.current+1;be.current=t,Re(t,V,!0)},{root:e,rootMargin:`0px 0px 200px 0px`,threshold:0});return n.observe(t),()=>n.disconnect()},[g,he,V,Re]),(0,H.useEffect)(()=>()=>{I.current&&clearInterval(I.current)},[]);let Ve=async()=>{let e=await T.githubStartDevice();if(e.isErr()){F(e.error,`cloneRepo`);return}let t=e.value;ee(t.device_code),te(t.user_code),k(t.verification_uri),re(t.interval),_(`device-flow`),He(t.device_code,t.interval)},He=(e,n)=>{I.current&&clearInterval(I.current),I.current=setInterval(async()=>{let n=await T.githubPoll(e);if(n.isErr())return;let r=n.value;r.status===`success`?(I.current&&clearInterval(I.current),await Le(),_(`repos`),P.success(t(`github.connected`,{login:``}))):r.status===`expired`||r.status===`denied`?(I.current&&clearInterval(I.current),P.error(r.status===`expired`?t(`github.deviceFlow.expired`):t(`github.deviceFlow.denied`)),_(`connect`)):r.interval&&(I.current&&clearInterval(I.current),He(e,r.interval))},(n+1)*1e3)},Ue=e=>{xe(e),Ce(e.name),_(`clone-config`)},We=async()=>{if(!Y||!X||!Z)return;ke(!0),je(``),Ne(void 0),_(`cloning`);let e=await T.cloneRepo(Y.clone_url,X,Z);if(e.isErr()){F(e.error,`cloneRepo`),ke(!1),_(`clone-config`);return}P.success(t(`github.clone.success`)),await p(),m(!1),c(N(`/projects/${e.value.id}`))},Ge=async()=>{await T.githubDisconnect(),y(null),pe([]),_(`connect`),P.success(t(`github.disconnected`))},Ke=e=>{let n=Date.now()-new Date(e).getTime(),r=Math.floor(n/6e4);if(r<60)return t(`time.minutes`,{count:r});let i=Math.floor(r/60);if(i<24)return t(`time.hours`,{count:i});let a=Math.floor(i/24);return a<30?t(`time.days`,{count:a}):t(`time.months`,{count:Math.floor(a/30)})};if(g===`checking`)return(0,Q.jsx)(ue,{fill:!1,className:`py-12`,testId:`clone-repo-checking`});if(g===`error`)return(0,Q.jsxs)(`div`,{className:`flex flex-col items-center gap-4 py-8`,children:[(0,Q.jsx)(`div`,{className:`bg-destructive/10 flex size-12 items-center justify-center rounded-full`,children:(0,Q.jsx)(oe,{className:`icon-xl text-destructive`})}),(0,Q.jsxs)(`div`,{className:`space-y-1 text-center`,children:[(0,Q.jsx)(`h3`,{className:`font-medium`,children:t(`github.connectionError`,{defaultValue:`Connection Error`})}),(0,Q.jsx)(`p`,{className:`text-muted-foreground max-w-xs text-sm`,children:t(`github.connectionErrorDesc`,{defaultValue:`Could not check GitHub connection status. The server may be unavailable.`})})]}),(0,Q.jsx)(A,{onClick:()=>{_(`checking`),$()},"data-testid":`clone-repo-retry`,children:t(`common.retry`,{defaultValue:`Retry`})})]});if(g===`connect`)return(0,Q.jsxs)(`div`,{className:`flex flex-col items-center gap-4 py-8`,children:[(0,Q.jsx)(`div`,{className:`bg-muted flex size-12 items-center justify-center rounded-full`,children:(0,Q.jsx)(oe,{className:`icon-xl`})}),(0,Q.jsxs)(`div`,{className:`space-y-1 text-center`,children:[(0,Q.jsx)(`h3`,{className:`font-medium`,children:t(`github.connectGithub`)}),(0,Q.jsx)(`p`,{className:`text-muted-foreground max-w-xs text-sm`,children:t(`github.connectDesc`)})]}),(0,Q.jsxs)(`div`,{className:`flex w-full max-w-xs flex-col gap-2`,children:[(0,Q.jsxs)(A,{className:`w-full`,onClick:Ve,children:[(0,Q.jsx)(oe,{className:`icon-base mr-2`}),t(`github.connectGithub`)]}),(0,Q.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,Q.jsx)(`div`,{className:`bg-border h-px flex-1`}),(0,Q.jsx)(`span`,{className:`text-muted-foreground text-xs`,children:t(`common.or`)}),(0,Q.jsx)(`div`,{className:`bg-border h-px flex-1`})]}),(0,Q.jsxs)(A,{variant:`outline`,className:`w-full`,onClick:()=>c(N(`/preferences/github`)),children:[(0,Q.jsx)(a,{className:`icon-base mr-2`}),t(`github.useToken`)]}),(0,Q.jsx)(`p`,{className:`text-muted-foreground text-center text-xs`,children:(0,Q.jsx)(we,{i18nKey:`github.useTokenHint`,components:{link:(0,Q.jsx)(`a`,{href:`https://github.com/settings/tokens/new`,target:`_blank`,rel:`noopener noreferrer`,className:`hover:text-foreground underline`})}})})]})]});if(g===`device-flow`)return(0,Q.jsxs)(`div`,{className:`flex flex-col items-center gap-5 py-8`,children:[(0,Q.jsxs)(`div`,{className:`space-y-1 text-center`,children:[(0,Q.jsx)(`h3`,{className:`font-medium`,children:t(`github.deviceFlow.title`)}),(0,Q.jsx)(`p`,{className:`text-muted-foreground text-sm`,children:t(`github.deviceFlow.desc`)})]}),(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`code`,{className:`bg-muted rounded-md px-4 py-2 font-mono text-2xl font-bold tracking-widest`,children:w}),(0,Q.jsx)(A,{variant:`outline`,size:`sm`,onClick:()=>ae(w),children:j?(0,Q.jsx)(d,{className:`icon-base`}):(0,Q.jsx)(i,{className:`icon-base`})})]}),(0,Q.jsx)(`div`,{className:`flex gap-2`,children:(0,Q.jsxs)(A,{variant:`outline`,onClick:()=>window.open(D,`_blank`),children:[(0,Q.jsx)(f,{className:`icon-base mr-2`}),t(`github.deviceFlow.openGithub`)]})}),(0,Q.jsx)(ue,{fill:!1,layout:`inline`,className:`text-sm`,testId:`clone-repo-waiting-auth`,label:t(`github.deviceFlow.waitingAuth`)}),(0,Q.jsx)(A,{variant:`ghost`,size:`sm`,className:`text-muted-foreground`,onClick:()=>{I.current&&clearInterval(I.current),_(`connect`)},children:t(`common.cancel`)})]});if(g===`repos`)return(0,Q.jsxs)(`div`,{className:`flex h-full flex-col`,children:[v&&(0,Q.jsxs)(`div`,{className:`mb-3 flex items-center gap-2`,children:[(0,Q.jsx)(`img`,{src:v.avatar_url,alt:v.login,className:`size-6 rounded-full`}),(0,Q.jsx)(`span`,{className:`text-sm font-medium`,children:v.login}),b===`cli`?(0,Q.jsx)(`span`,{className:`text-muted-foreground ml-auto text-xs`,children:t(`github.viaGhCli`,{defaultValue:`via gh CLI`})}):(0,Q.jsxs)(A,{variant:`ghost`,size:`sm`,className:`text-muted-foreground ml-auto h-7 text-xs`,onClick:Ge,"data-testid":`clone-repo-disconnect`,children:[(0,Q.jsx)(n,{className:`icon-xs mr-1`}),t(`github.disconnect`)]})]}),(0,Q.jsx)(`div`,{className:`mb-3`,children:(0,Q.jsx)(ce,{query:z,onQueryChange:B,placeholder:t(`github.repos.searchPlaceholder`),totalMatches:L.length,resultLabel:z?`${L.length}`:``,loading:ze,onClose:z?()=>B(``):void 0,onInputKeyDown:Be,autoFocus:!1,testIdPrefix:`clone-repo-search`,className:`border-input bg-background rounded-md border px-2`})}),(0,Q.jsxs)(se,{viewportRef:K,className:`-mx-1 max-h-[40vh] min-h-0 flex-1`,children:[L.map((e,t)=>(0,Q.jsxs)(`button`,{"data-repo-item":!0,"data-testid":`clone-repo-item-${e.id}`,onClick:()=>Ue(e),onMouseEnter:()=>G(t),className:O(`flex w-full flex-col gap-0.5 rounded-md px-3 py-2 text-left transition-colors hover:bg-accent`,W===t&&`bg-accent`),children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(M,{text:e.full_name,query:V,className:`truncate text-sm font-medium`}),e.private?(0,Q.jsx)(r,{className:`icon-xs text-status-pending shrink-0`}):(0,Q.jsx)(l,{className:`icon-xs text-muted-foreground shrink-0`})]}),e.description&&(0,Q.jsx)(M,{text:e.description,query:V,className:`text-muted-foreground truncate text-xs`}),(0,Q.jsxs)(`div`,{className:`text-muted-foreground flex items-center gap-3 text-xs`,children:[e.language&&(0,Q.jsx)(M,{text:e.language,query:V}),(0,Q.jsx)(`span`,{children:Ke(e.updated_at)})]})]},e.id)),_e&&(0,Q.jsx)(ue,{fill:!1,className:`py-4`,testId:`clone-repo-loading-repos`}),!_e&&L.length===0&&(0,Q.jsx)(`p`,{className:`text-muted-foreground py-8 text-center text-sm`,children:t(`github.repos.noRepos`)}),(0,Q.jsx)(`div`,{ref:ve,"aria-hidden":!0,className:`h-1 w-full`})]})]});if(g===`clone-config`&&Y)return(0,Q.jsxs)(`div`,{className:`space-y-4`,children:[(0,Q.jsxs)(A,{variant:`ghost`,size:`sm`,className:`text-muted-foreground -ml-2`,onClick:()=>_(`repos`),children:[(0,Q.jsx)(s,{className:`icon-sm mr-1`}),t(`github.repos.title`)]}),(0,Q.jsxs)(`div`,{className:`border-border space-y-1 rounded-md border p-3`,children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`span`,{className:`text-sm font-medium`,children:Y.full_name}),Y.private&&(0,Q.jsx)(r,{className:`icon-xs text-status-pending`})]}),Y.description&&(0,Q.jsx)(`p`,{className:`text-muted-foreground text-xs`,children:Y.description})]}),(0,Q.jsxs)(`div`,{children:[(0,Q.jsx)(`label`,{className:`mb-1.5 block text-sm font-medium`,children:t(`github.clone.projectName`)}),(0,Q.jsx)(R,{value:Z,onChange:e=>Ce(e.target.value)})]}),(0,Q.jsxs)(`div`,{children:[(0,Q.jsx)(`label`,{className:`mb-1.5 block text-sm font-medium`,children:t(`github.clone.destination`)}),(0,Q.jsxs)(`div`,{className:`flex gap-2`,children:[(0,Q.jsx)(R,{className:`flex-1`,placeholder:t(`github.clone.destinationDesc`),value:X,onChange:e=>Se(e.target.value)}),(0,Q.jsx)(A,{variant:`outline`,size:`sm`,onClick:()=>De(!0),children:(0,Q.jsx)(u,{className:`icon-base`})})]})]}),(0,Q.jsxs)(`div`,{className:`flex gap-2 pt-2`,children:[(0,Q.jsx)(A,{variant:`outline`,className:`flex-1`,onClick:()=>_(`repos`),children:t(`common.cancel`)}),(0,Q.jsx)(A,{className:`flex-1`,onClick:We,disabled:!X||!Z,children:t(`github.clone.cloneAndCreate`)})]}),Ee&&(0,Q.jsx)(fe,{onSelect:e=>{Se(e),De(!1)},onClose:()=>De(!1)})]});if(g===`cloning`){let e=Ae?Ae.replace(/:.*$/,``).trim().replace(/\b\w/g,e=>e.toUpperCase()):``;return(0,Q.jsxs)(`div`,{className:`flex flex-col items-center gap-4 py-12`,children:[(0,Q.jsx)(o,{className:`text-primary size-8 animate-spin`}),(0,Q.jsx)(`p`,{className:`text-sm font-medium`,children:t(`github.clone.cloning`,{repo:Y?.full_name})}),(0,Q.jsxs)(`div`,{className:`w-full max-w-xs`,children:[e&&(0,Q.jsx)(`p`,{className:`text-muted-foreground mb-1 text-xs font-medium`,children:e}),Me!==void 0&&(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(`div`,{className:`bg-muted h-1.5 w-full overflow-hidden rounded-full`,children:(0,Q.jsx)(`div`,{className:O(`h-full rounded-full bg-primary`,Pe?``:`transition-all duration-300`),style:{width:`${Me}%`}})}),(0,Q.jsxs)(`p`,{className:`text-muted-foreground mt-1 text-right text-xs`,children:[Me,`%`]})]})]})]})}return null}function De(){let{t:e}=x(),t=E(),n=de(e=>e.loadProjects),[r,i]=(0,H.useState)(`local`),[a,s]=(0,H.useState)(``),[l,d]=(0,H.useState)(``),[f,p]=(0,H.useState)(!1),[m,h]=(0,H.useState)(!1),[g,_]=(0,H.useState)(!1),[v,y]=(0,H.useState)(!1);return(0,Q.jsxs)(se,{className:`flex flex-1 justify-center pt-[10vh]`,children:[(0,Q.jsxs)(`div`,{className:`mx-auto w-full max-w-md space-y-6 px-4 pb-8`,children:[!v&&(0,Q.jsxs)(`div`,{className:`space-y-2 text-center`,children:[(0,Q.jsx)(`div`,{className:`bg-primary/10 mx-auto flex size-12 items-center justify-center rounded-full`,children:(0,Q.jsx)(c,{className:`icon-xl text-primary`})}),(0,Q.jsx)(`h2`,{className:`text-xl font-semibold`,children:e(`sidebar.addProject`)})]}),(0,Q.jsxs)(`div`,{className:O(`flex gap-1 rounded-lg bg-muted p-1`,v&&`hidden`),children:[(0,Q.jsxs)(`button`,{className:`flex flex-1 items-center justify-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors ${r===`local`?`bg-background text-foreground shadow-xs`:`text-muted-foreground hover:text-foreground`}`,"data-testid":`add-project-tab-local`,onClick:()=>i(`local`),children:[(0,Q.jsx)(u,{className:`icon-sm`}),e(`github.localFolder`)]}),(0,Q.jsxs)(`button`,{className:`flex flex-1 items-center justify-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors ${r===`github`?`bg-background text-foreground shadow-xs`:`text-muted-foreground hover:text-foreground`}`,"data-testid":`add-project-tab-clone`,onClick:()=>i(`github`),children:[(0,Q.jsx)(oe,{className:`icon-sm`}),e(`github.cloneFromGithub`)]})]}),r===`local`?(0,Q.jsxs)(`div`,{className:`space-y-4`,children:[(0,Q.jsx)(`p`,{className:`text-muted-foreground text-center text-sm`,children:e(`sidebar.addProjectDescription`,{defaultValue:`Enter the project name and select the folder path.`})}),(0,Q.jsxs)(`div`,{children:[(0,Q.jsx)(`label`,{className:`mb-1.5 block text-sm font-medium`,children:e(`sidebar.projectName`)}),(0,Q.jsx)(R,{"data-testid":`add-project-name`,placeholder:e(`sidebar.projectName`),value:a,onChange:e=>s(e.target.value),autoFocus:!0})]}),(0,Q.jsxs)(`div`,{children:[(0,Q.jsx)(`label`,{className:`mb-1.5 block text-sm font-medium`,children:e(`sidebar.absolutePath`)}),(0,Q.jsxs)(`div`,{className:`flex gap-2`,children:[(0,Q.jsx)(R,{"data-testid":`add-project-path`,className:`flex-1`,placeholder:e(`sidebar.absolutePath`),value:l,onChange:e=>d(e.target.value)}),(0,Q.jsxs)(te,{children:[(0,Q.jsx)(k,{asChild:!0,children:(0,Q.jsx)(A,{"data-testid":`add-project-browse`,variant:`outline`,size:`sm`,onClick:()=>p(!0),"aria-label":e(`sidebar.browseFolder`),children:(0,Q.jsx)(u,{className:`icon-base`})})}),(0,Q.jsx)(w,{children:e(`sidebar.browseFolder`)})]})]})]}),(0,Q.jsxs)(`div`,{className:`flex gap-2 pt-2`,children:[(0,Q.jsx)(A,{"data-testid":`add-project-cancel`,variant:`outline`,className:`flex-1`,onClick:()=>t(N(`/`)),children:e(`common.cancel`,{defaultValue:`Cancel`})}),(0,Q.jsx)(A,{"data-testid":`add-project-submit`,className:`flex-1`,onClick:async()=>{if(!a||!l||m)return;h(!0);let r=await T.createProject(a,l);if(r.isErr()){if(r.error.message?.includes(`Not a git repository`)||r.error.message?.includes(`nested inside another git repository`)){h(!1),_(!0);return}F(r.error,`createProject`),h(!1);return}await n(),P.success(e(`project.created`,{name:a,defaultValue:`Project "${a}" created`})),t(N(`/projects/${r.value.id}`)),h(!1)},disabled:m||!a||!l,children:m?(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(o,{className:`icon-base mr-2 animate-spin`}),e(`common.loading`)]}):e(`sidebar.add`)})]})]}):(0,Q.jsx)(Ee,{onCloningChange:y})]}),f&&(0,Q.jsx)(fe,{onSelect:async e=>{if(d(e),p(!1),!a){let t=await T.repoName(e);t.isOk()&&t.value.name?s(t.value.name):s(e.split(/[\\/]/).filter(Boolean).pop()||``)}},onClose:()=>p(!1)}),(0,Q.jsx)(re,{open:g,onOpenChange:_,children:(0,Q.jsxs)(L,{children:[(0,Q.jsxs)(ae,{children:[(0,Q.jsx)(ne,{children:e(`confirm.gitInitTitle`,{defaultValue:`Initialize Git Repository`})}),(0,Q.jsx)(j,{children:e(`confirm.notGitRepo`,{path:l})})]}),(0,Q.jsxs)(I,{children:[(0,Q.jsx)(A,{"data-testid":`git-init-cancel`,variant:`outline`,onClick:()=>_(!1),children:e(`common.cancel`,{defaultValue:`Cancel`})}),(0,Q.jsx)(A,{"data-testid":`git-init-confirm`,onClick:async()=>{_(!1),h(!0);let r=await T.gitInit(l);if(r.isErr()){F(r.error,`createProject`),h(!1);return}let i=await T.createProject(a,l);if(i.isErr()){F(i.error,`createProject`),h(!1);return}await n(),P.success(e(`project.created`,{name:a,defaultValue:`Project "${a}" created`})),t(N(`/projects/${i.value.id}`)),h(!1)},children:e(`confirm.gitInitAction`,{defaultValue:`Initialize`})})]})]})})]})}export{De as AddProjectView};
1
+ import{a as e,t}from"./rolldown-runtime-Cyuzqnbw.js";import{Ft as n,It as r,Kn as i,L as a,Lt as o,Mr as s,Q as c,on as l,yn as u,yr as d,zn as f,zr as p}from"./icons-sqwAEN28.js";import{o as m}from"./markdown-DBtwZWLP.js";import{i as h}from"./_core-lD_pNs53.js";import{a as g,i as _,n as v,o as y,r as b,t as x}from"./useTranslation-DAPPK3Hy.js";import{i as S,n as C,r as ee}from"./initReactI18next-Dr0vnWXF.js";import{G as w,P as T,W as te,_t as E,j as D,lt as O,q as k}from"./index-Bmp1UFM1.js";import{t as A}from"./button-Bi9_EZFh.js";import{$r as ne,Gr as re,Jr as j,K as ie,Nn as M,Rt as N,Ur as P,Wn as F,Xr as ae,Yr as I,gt as oe,in as se,mn as ce,qr as L,yr as le}from"./items-C-m69VjA.js";import{t as R}from"./input-BGZP-HTx.js";import{t as ue}from"./loading-state-DGzdeccZ.js";import{t as de}from"./app-store-CVcOgstJ.js";import{t as fe}from"./FolderPicker-DEwPUyou.js";var pe=e(t(((e,t)=>{t.exports={area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0}}))()),z=/\s([^'"/\s><]+?)[\s/>]|([^\s=]+)=\s?(".*?"|'.*?')/g;function B(e){var t={type:`tag`,name:``,voidElement:!1,attrs:{},children:[]},n=e.match(/<\/?([^\s]+?)[/\s>]/);if(n&&(t.name=n[1],(pe.default[n[1]]||e.charAt(e.length-2)===`/`)&&(t.voidElement=!0),t.name.startsWith(`!--`))){var r=e.indexOf(`-->`);return{type:`comment`,comment:r===-1?``:e.slice(4,r)}}for(var i=new RegExp(z),a=null;(a=i.exec(e))!==null;)if(a[0].trim())if(a[1]){var o=a[1].trim(),s=[o,``];o.indexOf(`=`)>-1&&(s=o.split(`=`)),t.attrs[s[0]]=s[1],i.lastIndex--}else a[2]&&(t.attrs[a[2]]=a[3].trim().substring(1,a[3].length-1));return t}var V=/<[a-zA-Z0-9\-\!\/](?:"[^"]*"|'[^']*'|[^'">])*>/g,me=/^\s*$/,he=Object.create(null);function ge(e,t){switch(t.type){case`text`:return e+t.content;case`tag`:return e+=`<`+t.name+(t.attrs?function(e){var t=[];for(var n in e)t.push(n+`="`+e[n]+`"`);return t.length?` `+t.join(` `):``}(t.attrs):``)+(t.voidElement?`/>`:`>`),t.voidElement?e:e+t.children.reduce(ge,``)+`</`+t.name+`>`;case`comment`:return e+`<!--`+t.comment+`-->`}}var _e={parse:function(e,t){t||={},t.components||=he;var n,r=[],i=[],a=-1,o=!1;if(e.indexOf(`<`)!==0){var s=e.indexOf(`<`);r.push({type:`text`,content:s===-1?e:e.substring(0,s)})}return e.replace(V,function(s,c){if(o){if(s!==`</`+n.name+`>`)return;o=!1}var l,u=s.charAt(1)!==`/`,d=s.startsWith(`<!--`),f=c+s.length,p=e.charAt(f);if(d){var m=B(s);return a<0?(r.push(m),r):((l=i[a]).children.push(m),r)}if(u&&(a++,(n=B(s)).type===`tag`&&t.components[n.name]&&(n.type=`component`,o=!0),n.voidElement||o||!p||p===`<`||n.children.push({type:`text`,content:e.slice(f,e.indexOf(`<`,f))}),a===0&&r.push(n),(l=i[a-1])&&l.children.push(n),i[a]=n),(!u||n.voidElement)&&(a>-1&&(n.voidElement||n.name===s.slice(2,-1))&&(a--,n=a===-1?r:i[a]),!o&&p!==`<`&&p)){l=a===-1?r:i[a].children;var h=e.indexOf(`<`,f),g=e.slice(f,h===-1?void 0:h);me.test(g)&&(g=` `),(h>-1&&a+l.length>=0||g!==` `)&&l.push({type:`text`,content:g})}}),r},stringify:function(e){return e.reduce(function(e,t){return e+ge(``,t)},``)}},H=e(p()),U=(e,t)=>{if(!e)return!1;let n=e.props?.children??e.children;return t?n.length>0:!!n},W=e=>{if(!e)return[];let t=e.props?.children??e.children;return e.props?.i18nIsDynamicList?K(t):t},G=e=>Array.isArray(e)&&e.every(H.isValidElement),K=e=>Array.isArray(e)?e:[e],ve=(e,t)=>{let n={...t};return n.props={...t.props,...e.props},n},q=e=>{let t={};if(!e)return t;let n=e=>{K(e).forEach(e=>{_(e)||(U(e)?n(W(e)):b(e)&&!(0,H.isValidElement)(e)&&Object.assign(t,e))})};return n(e),t},J=(e,t,n,r)=>{if(!e)return``;let i=``,a=K(e),o=t?.transSupportBasicHtmlNodes?t.transKeepBasicHtmlNodesFor??[]:[];return a.forEach((e,a)=>{if(_(e)){i+=`${e}`;return}if((0,H.isValidElement)(e)){let{props:s,type:c}=e,l=Object.keys(s).length,u=o.indexOf(c)>-1,d=s.children;if(!d&&u&&!l){i+=`<${c}/>`;return}if(!d&&(!u||l)||s.i18nIsDynamicList){i+=`<${a}></${a}>`;return}if(u&&l<=1){let e=_(d)?d:J(d,t,n,r);i+=`<${c}>${e}</${c}>`;return}let f=J(d,t,n,r);i+=`<${a}>${f}</${a}>`;return}if(e===null){g(n,`TRANS_NULL_VALUE`,`Passed in a null value as child`,{i18nKey:r});return}if(b(e)){let{format:t,...a}=e,o=Object.keys(a);if(o.length===1){let e=t?`${o[0]}, ${t}`:o[0];i+=`{{${e}}}`;return}g(n,`TRANS_INVALID_OBJ`,`Invalid child - Object should only have keys {{ value, format }} (format is optional).`,{i18nKey:r,child:e});return}g(n,`TRANS_INVALID_VAR`,`Passed in a variable like {number} - pass variables for interpolation as full objects like {{number}}.`,{i18nKey:r,child:e})}),i},ye=(e,t=[],n={})=>{if(!e)return e;let r=Object.keys(n),i=[...t,...r],a=``,o=0;for(;o<e.length;)if(e[o]===`<`){let t=!1,n=e.slice(o).match(/^<\/(\d+|[a-zA-Z][a-zA-Z0-9_-]*)>/);if(n){let e=n[1];(/^\d+$/.test(e)||i.includes(e))&&(t=!0,a+=n[0],o+=n[0].length)}if(!t){let n=e.slice(o).match(/^<(\d+|[a-zA-Z][a-zA-Z0-9_-]*)(\s+[\w-]+(?:=(?:"[^"]*"|'[^']*'|[^\s>]+))?)*\s*(\/)?>/);if(n){let e=n[1];(/^\d+$/.test(e)||i.includes(e))&&(t=!0,a+=n[0],o+=n[0].length)}}t||(a+=`&lt;`,o+=1)}else a+=e[o],o+=1;return a},be=(e,t,n,r,i,a,o)=>{if(n===``)return[];let s=i.transKeepBasicHtmlNodesFor||[],c=n&&new RegExp(s.map(e=>`<${e}`).join(`|`)).test(n);if(!e&&!t&&!c&&!o)return[n];let l=t??{},u=e=>{K(e).forEach(e=>{_(e)||(U(e)?u(W(e)):b(e)&&!(0,H.isValidElement)(e)&&Object.assign(l,e))})};u(e);let d=ye(n,s,l),f=_e.parse(`<0>${d}</0>`),p={...l,...a},m=(e,t,n)=>{let r=W(e),i=g(r,t.children,n);return G(r)&&i.length===0||e.props?.i18nIsDynamicList?r:i},h=(e,t,n,r,i)=>{e.dummy?(e.children=t,n.push((0,H.cloneElement)(e,{key:r},i?void 0:t))):n.push(...H.Children.map([e],e=>{if(e.type===H.Fragment||e.props?.i18nIsDynamicList!==void 0){let n={key:r};return e&&e.props&&Object.keys(e.props).forEach(t=>{t===`children`||t===`i18nIsDynamicList`||(n[t]=e.props[t])}),(0,H.createElement)(e.type,n,i?null:t)}let n={key:r};return e&&e.props&&Object.keys(e.props).forEach(t=>{t===`ref`||t===`children`||(n[t]=e.props[t])}),(0,H.cloneElement)(e,n,i?null:t)}))},g=(e,n,a)=>{let l=K(e),u=K(n),d={};return u.reduce((e,n,u)=>{let f=n.children?.[0]?.content&&r.services.interpolator.interpolate(n.children[0].content,p,r.language);if(n.type===`tag`){let v=l[parseInt(n.name,10)];!v&&t&&(v=t[n.name]),a.length===1&&!v&&(v=a[0][n.name]),v||={};let y={...n.attrs};o&&Object.keys(y).forEach(e=>{let t=y[e];_(t)&&(y[e]=S(t))});let x=Object.keys(y).length===0?v:ve({props:y},v),C=(0,H.isValidElement)(x),ee=C&&U(n,!0)&&!n.voidElement,w=c&&b(x)&&x.dummy&&!C,T=b(t)&&Object.hasOwnProperty.call(t,n.name);if(_(x)){let t=r.services.interpolator.interpolate(x,p,r.language);e.push(t)}else if(U(x)||ee)h(x,m(x,n,a),e,u);else if(w)h(x,g(l,n.children,a),e,u);else if(Number.isNaN(parseFloat(n.name)))if(T)h(x,m(x,n,a),e,u,n.voidElement);else if(i.transSupportBasicHtmlNodes&&s.indexOf(n.name)>-1)if(n.voidElement)e.push((0,H.createElement)(n.name,{key:`${n.name}-${u}`}));else{let t=d[n.name]||0;d[n.name]=t+1;let r,i=0;for(let e=0;e<l.length;e+=1){let a=l[e];if((0,H.isValidElement)(a)&&a.type===n.name){if(i===t){r=a;break}i+=1}}let o=g(r?K(W(r)):l,n.children,a);e.push((0,H.createElement)(n.name,{key:`${n.name}-${u}`},o))}else if(n.voidElement)e.push(`<${n.name} />`);else{let t=g(l,n.children,a);e.push(`<${n.name}>${t}</${n.name}>`)}else if(b(x)&&!C){let t=n.children[0]?f:null;t&&e.push(t)}else h(x,f,e,u,n.children.length!==1||!f)}else if(n.type===`text`){let t=i.transWrapTextNodes,a=typeof i.unescape==`function`?i.unescape:ee().unescape,s=o?a(r.services.interpolator.interpolate(n.content,p,r.language)):r.services.interpolator.interpolate(n.content,p,r.language);t?e.push((0,H.createElement)(t,{key:`${n.name}-${u}`},s)):e.push(s)}return e},[])};return W(g([{dummy:!0,children:e||[]}],f,K(e||[]))[0])},Y=(e,t,n)=>{let r=e.key||t,i=(0,H.cloneElement)(e,{key:r});if(!i.props||!i.props.children||n.indexOf(`${t}/>`)<0&&n.indexOf(`${t} />`)<0)return i;function a(){return(0,H.createElement)(H.Fragment,null,i)}return(0,H.createElement)(a,{key:r})},xe=(e,t)=>e.map((e,n)=>Y(e,n,t)),X=(e,t)=>{let n={};return Object.keys(e).forEach(r=>{Object.assign(n,{[r]:Y(e[r],r,t)})}),n},Se=(e,t,n,r)=>e?Array.isArray(e)?xe(e,t):b(e)?X(e,t):(y(n,`TRANS_INVALID_COMPONENTS`,`<Trans /> "components" prop expects an object or array`,{i18nKey:r}),null):null,Z=e=>!b(e)||Array.isArray(e)?!1:Object.keys(e).reduce((e,t)=>e&&Number.isNaN(Number.parseFloat(t)),!0);function Ce({children:e,count:t,parent:n,i18nKey:r,context:i,tOptions:a={},values:o,defaults:s,components:c,ns:l,i18n:u,t:d,shouldUnescape:f,...p}){let m=u||C();if(!m)return y(m,`NO_I18NEXT_INSTANCE`,`Trans: You need to pass in an i18next instance using i18nextReactModule`,{i18nKey:r}),e;let g=d||m.t.bind(m)||(e=>e),v={...ee(),...m.options?.react},b=l||g.ns||m.options?.defaultNS;b=_(b)?[b]:b||[`translation`];let{transDefaultProps:x}=v,S=x?.tOptions?{...x.tOptions,...a}:a,w=f??x?.shouldUnescape,T=x?.values?{...x.values,...o}:o,te=x?.components?{...x.components,...c}:c,E=J(e,v,m,r),D=s||S?.defaultValue||E||v.transEmptyNodeValue||(typeof r==`function`?h(r):r),{hashTransKey:O}=v,k=r||(O?O(E||D):E||D);o=m.options?.interpolation?.defaultVariables?T&&Object.keys(T).length>0?{...T,...m.options.interpolation.defaultVariables}:{...m.options.interpolation.defaultVariables}:T;let A=q(e);A&&typeof A.count==`number`&&t===void 0&&(t=A.count);let ne=o||t!==void 0&&!m.options?.interpolation?.alwaysFormat||!e?S.interpolation:{interpolation:{...S.interpolation,prefix:`#$?`,suffix:`?$#`}},re={...S,context:i||S.context,count:t,...o,...ne,defaultValue:D,ns:b},j=k?g(k,re):D;j===k&&D&&(j=D);let ie=Se(te,j,m,r),M=ie||e,N=null;Z(ie)&&(N=ie,M=e);let P=be(M,N,j,m,v,re,w),F=n??v.defaultTransParent;return F?(0,H.createElement)(F,p,P):P}function we({children:e,count:t,parent:n,i18nKey:r,context:i,tOptions:a={},values:o,defaults:s,components:c,ns:l,i18n:u,t:d,shouldUnescape:f,...p}){let{i18n:m,defaultNS:h}=(0,H.useContext)(v)||{},g=u||m||C(),_=d||g?.t.bind(g);return Ce({children:e,count:t,parent:n,i18nKey:r,context:i,tOptions:a,values:o,defaults:s,components:c,ns:l||_?.ns||h||g?.options?.defaultNS,i18n:g,t:d,shouldUnescape:f,...p})}var Q=e(m(),1),Te=D(`clone-repo-view`);function Ee({onCloningChange:e}={}){let{t}=x(),c=E(),p=de(e=>e.loadProjects),m=de(e=>e.setAddProjectOpen),h=le(e=>e.generalSettingsOpen),[g,_]=(0,H.useState)(`checking`);(0,H.useEffect)(()=>{e?.(g===`cloning`)},[g,e]);let[v,y]=(0,H.useState)(null),[b,S]=(0,H.useState)(null),[C,ee]=(0,H.useState)(``),[w,te]=(0,H.useState)(``),[D,k]=(0,H.useState)(``),[ne,re]=(0,H.useState)(5),[j,ae]=ie(),I=(0,H.useRef)(null),[L,pe]=(0,H.useState)([]),[z,B]=(0,H.useState)(``),[V,me]=(0,H.useState)(``),[he,ge]=(0,H.useState)(!1),[_e,U]=(0,H.useState)(!1),[W,G]=(0,H.useState)(-1),K=(0,H.useRef)(null),ve=(0,H.useRef)(null),q=(0,H.useRef)(void 0),J=(0,H.useRef)(!1),ye=(0,H.useRef)(0),be=(0,H.useRef)(1),[Y,xe]=(0,H.useState)(null),[X,Se]=(0,H.useState)(``),[Z,Ce]=(0,H.useState)(``),[Ee,De]=(0,H.useState)(!1),[Oe,ke]=(0,H.useState)(!1),[Ae,je]=(0,H.useState)(``),[Me,Ne]=(0,H.useState)(void 0),[Pe,Fe]=(0,H.useState)(!1),Ie=(0,H.useRef)(``);(0,H.useEffect)(()=>{let e=e=>{let t=e.detail;if(t.phase){let e=t.phase.replace(/:.*$/,``).trim();e!==Ie.current&&(Fe(!0),Ie.current=e,requestAnimationFrame(()=>Fe(!1))),je(t.phase)}t.percent!==void 0&&Ne(t.percent)};return window.addEventListener(`clone:progress`,e),()=>window.removeEventListener(`clone:progress`,e)},[]);let $=(0,H.useCallback)(async()=>{let e=await T.githubStatus();e.isOk()?e.value.connected?(S(e.value.source??`profile`),await Le(),_(`repos`)):(S(null),_(`connect`)):_(`error`)},[]);(0,H.useEffect)(()=>{$()},[$]),(0,H.useEffect)(()=>{!h&&(g===`connect`||g===`error`)&&$()},[h,g,$]);let Le=async()=>{let e=await T.githubUser();e.isOk()&&y(e.value)},Re=(0,H.useCallback)(async(e,t,n)=>{let r=++ye.current;J.current=!0,U(!0),Te.debug(`github repo search`,{page:e,query:t,append:n});let i=await T.githubRepos({page:e,per_page:30,sort:`updated`,search:t||void 0});r===ye.current&&(i.isOk()&&(pe(e=>n?[...e,...i.value.repos]:i.value.repos),ge(i.value.hasMore)),J.current=!1,U(!1))},[]);(0,H.useEffect)(()=>(q.current&&clearTimeout(q.current),q.current=setTimeout(()=>{me(z)},200),()=>{q.current&&clearTimeout(q.current)}),[z]);let ze=z!==V||_e;(0,H.useEffect)(()=>{G(-1)},[V]);let Be=e=>{if(e.key===`ArrowDown`)e.preventDefault(),G(e=>Math.min(e+1,L.length-1));else if(e.key===`ArrowUp`)e.preventDefault(),G(e=>Math.max(e-1,0));else if(e.key===`Enter`&&W>=0&&W<L.length){e.preventDefault();let t=L[W];xe(t),Ce(t.name),_(`clone-config`)}};(0,H.useEffect)(()=>{W<0||!K.current||K.current.querySelectorAll(`[data-repo-item]`)[W]?.scrollIntoView({block:`nearest`})},[W]),(0,H.useEffect)(()=>{g===`repos`&&(be.current=1,Re(1,V,!1))},[g,V,Re]),(0,H.useEffect)(()=>{if(g!==`repos`)return;let e=K.current,t=ve.current;if(!e||!t)return;let n=new IntersectionObserver(e=>{if(!e[0]?.isIntersecting||J.current||!he)return;let t=be.current+1;be.current=t,Re(t,V,!0)},{root:e,rootMargin:`0px 0px 200px 0px`,threshold:0});return n.observe(t),()=>n.disconnect()},[g,he,V,Re]),(0,H.useEffect)(()=>()=>{I.current&&clearInterval(I.current)},[]);let Ve=async()=>{let e=await T.githubStartDevice();if(e.isErr()){F(e.error,`cloneRepo`);return}let t=e.value;ee(t.device_code),te(t.user_code),k(t.verification_uri),re(t.interval),_(`device-flow`),He(t.device_code,t.interval)},He=(e,n)=>{I.current&&clearInterval(I.current),I.current=setInterval(async()=>{let n=await T.githubPoll(e);if(n.isErr())return;let r=n.value;r.status===`success`?(I.current&&clearInterval(I.current),await Le(),_(`repos`),P.success(t(`github.connected`,{login:``}))):r.status===`expired`||r.status===`denied`?(I.current&&clearInterval(I.current),P.error(r.status===`expired`?t(`github.deviceFlow.expired`):t(`github.deviceFlow.denied`)),_(`connect`)):r.interval&&(I.current&&clearInterval(I.current),He(e,r.interval))},(n+1)*1e3)},Ue=e=>{xe(e),Ce(e.name),_(`clone-config`)},We=async()=>{if(!Y||!X||!Z)return;ke(!0),je(``),Ne(void 0),_(`cloning`);let e=await T.cloneRepo(Y.clone_url,X,Z);if(e.isErr()){F(e.error,`cloneRepo`),ke(!1),_(`clone-config`);return}P.success(t(`github.clone.success`)),await p(),m(!1),c(N(`/projects/${e.value.id}`))},Ge=async()=>{await T.githubDisconnect(),y(null),pe([]),_(`connect`),P.success(t(`github.disconnected`))},Ke=e=>{let n=Date.now()-new Date(e).getTime(),r=Math.floor(n/6e4);if(r<60)return t(`time.minutes`,{count:r});let i=Math.floor(r/60);if(i<24)return t(`time.hours`,{count:i});let a=Math.floor(i/24);return a<30?t(`time.days`,{count:a}):t(`time.months`,{count:Math.floor(a/30)})};if(g===`checking`)return(0,Q.jsx)(ue,{fill:!1,className:`py-12`,testId:`clone-repo-checking`});if(g===`error`)return(0,Q.jsxs)(`div`,{className:`flex flex-col items-center gap-4 py-8`,children:[(0,Q.jsx)(`div`,{className:`bg-destructive/10 flex size-12 items-center justify-center rounded-full`,children:(0,Q.jsx)(oe,{className:`icon-xl text-destructive`})}),(0,Q.jsxs)(`div`,{className:`space-y-1 text-center`,children:[(0,Q.jsx)(`h3`,{className:`font-medium`,children:t(`github.connectionError`,{defaultValue:`Connection Error`})}),(0,Q.jsx)(`p`,{className:`text-muted-foreground max-w-xs text-sm`,children:t(`github.connectionErrorDesc`,{defaultValue:`Could not check GitHub connection status. The server may be unavailable.`})})]}),(0,Q.jsx)(A,{onClick:()=>{_(`checking`),$()},"data-testid":`clone-repo-retry`,children:t(`common.retry`,{defaultValue:`Retry`})})]});if(g===`connect`)return(0,Q.jsxs)(`div`,{className:`flex flex-col items-center gap-4 py-8`,children:[(0,Q.jsx)(`div`,{className:`bg-muted flex size-12 items-center justify-center rounded-full`,children:(0,Q.jsx)(oe,{className:`icon-xl`})}),(0,Q.jsxs)(`div`,{className:`space-y-1 text-center`,children:[(0,Q.jsx)(`h3`,{className:`font-medium`,children:t(`github.connectGithub`)}),(0,Q.jsx)(`p`,{className:`text-muted-foreground max-w-xs text-sm`,children:t(`github.connectDesc`)})]}),(0,Q.jsxs)(`div`,{className:`flex w-full max-w-xs flex-col gap-2`,children:[(0,Q.jsxs)(A,{className:`w-full`,onClick:Ve,children:[(0,Q.jsx)(oe,{className:`icon-base mr-2`}),t(`github.connectGithub`)]}),(0,Q.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,Q.jsx)(`div`,{className:`bg-border h-px flex-1`}),(0,Q.jsx)(`span`,{className:`text-muted-foreground text-xs`,children:t(`common.or`)}),(0,Q.jsx)(`div`,{className:`bg-border h-px flex-1`})]}),(0,Q.jsxs)(A,{variant:`outline`,className:`w-full`,onClick:()=>c(N(`/preferences/github`)),children:[(0,Q.jsx)(a,{className:`icon-base mr-2`}),t(`github.useToken`)]}),(0,Q.jsx)(`p`,{className:`text-muted-foreground text-center text-xs`,children:(0,Q.jsx)(we,{i18nKey:`github.useTokenHint`,components:{link:(0,Q.jsx)(`a`,{href:`https://github.com/settings/tokens/new`,target:`_blank`,rel:`noopener noreferrer`,className:`hover:text-foreground underline`})}})})]})]});if(g===`device-flow`)return(0,Q.jsxs)(`div`,{className:`flex flex-col items-center gap-5 py-8`,children:[(0,Q.jsxs)(`div`,{className:`space-y-1 text-center`,children:[(0,Q.jsx)(`h3`,{className:`font-medium`,children:t(`github.deviceFlow.title`)}),(0,Q.jsx)(`p`,{className:`text-muted-foreground text-sm`,children:t(`github.deviceFlow.desc`)})]}),(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`code`,{className:`bg-muted rounded-md px-4 py-2 font-mono text-2xl font-bold tracking-widest`,children:w}),(0,Q.jsx)(A,{variant:`outline`,size:`sm`,onClick:()=>ae(w),children:j?(0,Q.jsx)(d,{className:`icon-base`}):(0,Q.jsx)(i,{className:`icon-base`})})]}),(0,Q.jsx)(`div`,{className:`flex gap-2`,children:(0,Q.jsxs)(A,{variant:`outline`,onClick:()=>window.open(D,`_blank`),children:[(0,Q.jsx)(f,{className:`icon-base mr-2`}),t(`github.deviceFlow.openGithub`)]})}),(0,Q.jsx)(ue,{fill:!1,layout:`inline`,className:`text-sm`,testId:`clone-repo-waiting-auth`,label:t(`github.deviceFlow.waitingAuth`)}),(0,Q.jsx)(A,{variant:`ghost`,size:`sm`,className:`text-muted-foreground`,onClick:()=>{I.current&&clearInterval(I.current),_(`connect`)},children:t(`common.cancel`)})]});if(g===`repos`)return(0,Q.jsxs)(`div`,{className:`flex h-full flex-col`,children:[v&&(0,Q.jsxs)(`div`,{className:`mb-3 flex items-center gap-2`,children:[(0,Q.jsx)(`img`,{src:v.avatar_url,alt:v.login,className:`size-6 rounded-full`}),(0,Q.jsx)(`span`,{className:`text-sm font-medium`,children:v.login}),b===`cli`?(0,Q.jsx)(`span`,{className:`text-muted-foreground ml-auto text-xs`,children:t(`github.viaGhCli`,{defaultValue:`via gh CLI`})}):(0,Q.jsxs)(A,{variant:`ghost`,size:`sm`,className:`text-muted-foreground ml-auto h-7 text-xs`,onClick:Ge,"data-testid":`clone-repo-disconnect`,children:[(0,Q.jsx)(n,{className:`icon-xs mr-1`}),t(`github.disconnect`)]})]}),(0,Q.jsx)(`div`,{className:`mb-3`,children:(0,Q.jsx)(ce,{query:z,onQueryChange:B,placeholder:t(`github.repos.searchPlaceholder`),totalMatches:L.length,resultLabel:z?`${L.length}`:``,loading:ze,onClose:z?()=>B(``):void 0,onInputKeyDown:Be,autoFocus:!1,testIdPrefix:`clone-repo-search`,className:`border-input bg-background rounded-md border px-2`})}),(0,Q.jsxs)(se,{viewportRef:K,className:`-mx-1 max-h-[40vh] min-h-0 flex-1`,children:[L.map((e,t)=>(0,Q.jsxs)(`button`,{"data-repo-item":!0,"data-testid":`clone-repo-item-${e.id}`,onClick:()=>Ue(e),onMouseEnter:()=>G(t),className:O(`flex w-full flex-col gap-0.5 rounded-md px-3 py-2 text-left transition-colors hover:bg-accent`,W===t&&`bg-accent`),children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(M,{text:e.full_name,query:V,className:`truncate text-sm font-medium`}),e.private?(0,Q.jsx)(r,{className:`icon-xs text-status-pending shrink-0`}):(0,Q.jsx)(l,{className:`icon-xs text-muted-foreground shrink-0`})]}),e.description&&(0,Q.jsx)(M,{text:e.description,query:V,className:`text-muted-foreground truncate text-xs`}),(0,Q.jsxs)(`div`,{className:`text-muted-foreground flex items-center gap-3 text-xs`,children:[e.language&&(0,Q.jsx)(M,{text:e.language,query:V}),(0,Q.jsx)(`span`,{children:Ke(e.updated_at)})]})]},e.id)),_e&&(0,Q.jsx)(ue,{fill:!1,className:`py-4`,testId:`clone-repo-loading-repos`}),!_e&&L.length===0&&(0,Q.jsx)(`p`,{className:`text-muted-foreground py-8 text-center text-sm`,children:t(`github.repos.noRepos`)}),(0,Q.jsx)(`div`,{ref:ve,"aria-hidden":!0,className:`h-1 w-full`})]})]});if(g===`clone-config`&&Y)return(0,Q.jsxs)(`div`,{className:`space-y-4`,children:[(0,Q.jsxs)(A,{variant:`ghost`,size:`sm`,className:`text-muted-foreground -ml-2`,onClick:()=>_(`repos`),children:[(0,Q.jsx)(s,{className:`icon-sm mr-1`}),t(`github.repos.title`)]}),(0,Q.jsxs)(`div`,{className:`border-border space-y-1 rounded-md border p-3`,children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`span`,{className:`text-sm font-medium`,children:Y.full_name}),Y.private&&(0,Q.jsx)(r,{className:`icon-xs text-status-pending`})]}),Y.description&&(0,Q.jsx)(`p`,{className:`text-muted-foreground text-xs`,children:Y.description})]}),(0,Q.jsxs)(`div`,{children:[(0,Q.jsx)(`label`,{className:`mb-1.5 block text-sm font-medium`,children:t(`github.clone.projectName`)}),(0,Q.jsx)(R,{value:Z,onChange:e=>Ce(e.target.value)})]}),(0,Q.jsxs)(`div`,{children:[(0,Q.jsx)(`label`,{className:`mb-1.5 block text-sm font-medium`,children:t(`github.clone.destination`)}),(0,Q.jsxs)(`div`,{className:`flex gap-2`,children:[(0,Q.jsx)(R,{className:`flex-1`,placeholder:t(`github.clone.destinationDesc`),value:X,onChange:e=>Se(e.target.value)}),(0,Q.jsx)(A,{variant:`outline`,size:`sm`,onClick:()=>De(!0),children:(0,Q.jsx)(u,{className:`icon-base`})})]})]}),(0,Q.jsxs)(`div`,{className:`flex gap-2 pt-2`,children:[(0,Q.jsx)(A,{variant:`outline`,className:`flex-1`,onClick:()=>_(`repos`),children:t(`common.cancel`)}),(0,Q.jsx)(A,{className:`flex-1`,onClick:We,disabled:!X||!Z,children:t(`github.clone.cloneAndCreate`)})]}),Ee&&(0,Q.jsx)(fe,{onSelect:e=>{Se(e),De(!1)},onClose:()=>De(!1)})]});if(g===`cloning`){let e=Ae?Ae.replace(/:.*$/,``).trim().replace(/\b\w/g,e=>e.toUpperCase()):``;return(0,Q.jsxs)(`div`,{className:`flex flex-col items-center gap-4 py-12`,children:[(0,Q.jsx)(o,{className:`text-primary size-8 animate-spin`}),(0,Q.jsx)(`p`,{className:`text-sm font-medium`,children:t(`github.clone.cloning`,{repo:Y?.full_name})}),(0,Q.jsxs)(`div`,{className:`w-full max-w-xs`,children:[e&&(0,Q.jsx)(`p`,{className:`text-muted-foreground mb-1 text-xs font-medium`,children:e}),Me!==void 0&&(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(`div`,{className:`bg-muted h-1.5 w-full overflow-hidden rounded-full`,children:(0,Q.jsx)(`div`,{className:O(`h-full rounded-full bg-primary`,Pe?``:`transition-all duration-300`),style:{width:`${Me}%`}})}),(0,Q.jsxs)(`p`,{className:`text-muted-foreground mt-1 text-right text-xs`,children:[Me,`%`]})]})]})]})}return null}function De(){let{t:e}=x(),t=E(),n=de(e=>e.loadProjects),[r,i]=(0,H.useState)(`local`),[a,s]=(0,H.useState)(``),[l,d]=(0,H.useState)(``),[f,p]=(0,H.useState)(!1),[m,h]=(0,H.useState)(!1),[g,_]=(0,H.useState)(!1),[v,y]=(0,H.useState)(!1);return(0,Q.jsxs)(se,{className:`flex flex-1 justify-center pt-[10vh]`,children:[(0,Q.jsxs)(`div`,{className:`mx-auto w-full max-w-md space-y-6 px-4 pb-8`,children:[!v&&(0,Q.jsxs)(`div`,{className:`space-y-2 text-center`,children:[(0,Q.jsx)(`div`,{className:`bg-primary/10 mx-auto flex size-12 items-center justify-center rounded-full`,children:(0,Q.jsx)(c,{className:`icon-xl text-primary`})}),(0,Q.jsx)(`h2`,{className:`text-xl font-semibold`,children:e(`sidebar.addProject`)})]}),(0,Q.jsxs)(`div`,{className:O(`flex gap-1 rounded-lg bg-muted p-1`,v&&`hidden`),children:[(0,Q.jsxs)(`button`,{className:`flex flex-1 items-center justify-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors ${r===`local`?`bg-background text-foreground shadow-xs`:`text-muted-foreground hover:text-foreground`}`,"data-testid":`add-project-tab-local`,onClick:()=>i(`local`),children:[(0,Q.jsx)(u,{className:`icon-sm`}),e(`github.localFolder`)]}),(0,Q.jsxs)(`button`,{className:`flex flex-1 items-center justify-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors ${r===`github`?`bg-background text-foreground shadow-xs`:`text-muted-foreground hover:text-foreground`}`,"data-testid":`add-project-tab-clone`,onClick:()=>i(`github`),children:[(0,Q.jsx)(oe,{className:`icon-sm`}),e(`github.cloneFromGithub`)]})]}),r===`local`?(0,Q.jsxs)(`div`,{className:`space-y-4`,children:[(0,Q.jsx)(`p`,{className:`text-muted-foreground text-center text-sm`,children:e(`sidebar.addProjectDescription`,{defaultValue:`Enter the project name and select the folder path.`})}),(0,Q.jsxs)(`div`,{children:[(0,Q.jsx)(`label`,{className:`mb-1.5 block text-sm font-medium`,children:e(`sidebar.projectName`)}),(0,Q.jsx)(R,{"data-testid":`add-project-name`,placeholder:e(`sidebar.projectName`),value:a,onChange:e=>s(e.target.value),autoFocus:!0})]}),(0,Q.jsxs)(`div`,{children:[(0,Q.jsx)(`label`,{className:`mb-1.5 block text-sm font-medium`,children:e(`sidebar.absolutePath`)}),(0,Q.jsxs)(`div`,{className:`flex gap-2`,children:[(0,Q.jsx)(R,{"data-testid":`add-project-path`,className:`flex-1`,placeholder:e(`sidebar.absolutePath`),value:l,onChange:e=>d(e.target.value)}),(0,Q.jsxs)(te,{children:[(0,Q.jsx)(k,{asChild:!0,children:(0,Q.jsx)(A,{"data-testid":`add-project-browse`,variant:`outline`,size:`sm`,onClick:()=>p(!0),"aria-label":e(`sidebar.browseFolder`),children:(0,Q.jsx)(u,{className:`icon-base`})})}),(0,Q.jsx)(w,{children:e(`sidebar.browseFolder`)})]})]})]}),(0,Q.jsxs)(`div`,{className:`flex gap-2 pt-2`,children:[(0,Q.jsx)(A,{"data-testid":`add-project-cancel`,variant:`outline`,className:`flex-1`,onClick:()=>t(N(`/`)),children:e(`common.cancel`,{defaultValue:`Cancel`})}),(0,Q.jsx)(A,{"data-testid":`add-project-submit`,className:`flex-1`,onClick:async()=>{if(!a||!l||m)return;h(!0);let r=await T.createProject(a,l);if(r.isErr()){if(r.error.message?.includes(`Not a git repository`)||r.error.message?.includes(`nested inside another git repository`)){h(!1),_(!0);return}F(r.error,`createProject`),h(!1);return}await n(),P.success(e(`project.created`,{name:a,defaultValue:`Project "${a}" created`})),t(N(`/projects/${r.value.id}`)),h(!1)},disabled:m||!a||!l,children:m?(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(o,{className:`icon-base mr-2 animate-spin`}),e(`common.loading`)]}):e(`sidebar.add`)})]})]}):(0,Q.jsx)(Ee,{onCloningChange:y})]}),f&&(0,Q.jsx)(fe,{onSelect:async e=>{if(d(e),p(!1),!a){let t=await T.repoName(e);t.isOk()&&t.value.name?s(t.value.name):s(e.split(/[\\/]/).filter(Boolean).pop()||``)}},onClose:()=>p(!1)}),(0,Q.jsx)(re,{open:g,onOpenChange:_,children:(0,Q.jsxs)(L,{children:[(0,Q.jsxs)(ae,{children:[(0,Q.jsx)(ne,{children:e(`confirm.gitInitTitle`,{defaultValue:`Initialize Git Repository`})}),(0,Q.jsx)(j,{children:e(`confirm.notGitRepo`,{path:l})})]}),(0,Q.jsxs)(I,{children:[(0,Q.jsx)(A,{"data-testid":`git-init-cancel`,variant:`outline`,onClick:()=>_(!1),children:e(`common.cancel`,{defaultValue:`Cancel`})}),(0,Q.jsx)(A,{"data-testid":`git-init-confirm`,onClick:async()=>{_(!1),h(!0);let r=await T.gitInit(l);if(r.isErr()){F(r.error,`createProject`),h(!1);return}let i=await T.createProject(a,l);if(i.isErr()){F(i.error,`createProject`),h(!1);return}await n(),P.success(e(`project.created`,{name:a,defaultValue:`Project "${a}" created`})),t(N(`/projects/${i.value.id}`)),h(!1)},children:e(`confirm.gitInitAction`,{defaultValue:`Initialize`})})]})]})})]})}export{De as AddProjectView};