commandmate 0.2.3 → 0.2.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.
- package/.next/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +25 -25
- package/.next/app-path-routes-manifest.json +1 -1
- package/.next/build-manifest.json +7 -7
- package/.next/cache/.tsbuildinfo +1 -1
- package/.next/cache/config.json +3 -3
- package/.next/cache/fetch-cache/e7a5282a8c6f6e86940328b91498c8c8abc4b300cf449cb16e8ecd707767c12b +1 -0
- package/.next/cache/webpack/client-production/0.pack +0 -0
- package/.next/cache/webpack/client-production/1.pack +0 -0
- package/.next/cache/webpack/client-production/2.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/0.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +1 -1
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update-check/route.js +1 -0
- package/.next/server/app/api/app/update-check/route.js.nft.json +1 -0
- package/.next/server/app/api/app/update-check.body +1 -0
- package/.next/server/app/api/app/update-check.meta +1 -0
- package/.next/server/app/api/repositories/restore/route.js +1 -1
- package/.next/server/app/api/repositories/scan/route.js +1 -1
- package/.next/server/app/api/repositories/sync/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/route.js +2 -2
- package/.next/server/app/api/worktrees/[id]/search/route.js +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/proxy/[...path]/route.js +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +3 -3
- package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +10 -9
- package/.next/server/chunks/2683.js +1 -1
- package/.next/server/chunks/5488.js +1 -1
- package/.next/server/chunks/5823.js +1 -1
- package/.next/server/chunks/7425.js +3 -3
- package/.next/server/chunks/7536.js +1 -1
- package/.next/server/chunks/9367.js +2 -2
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/{816-bb41b20a51ae924a.js → 816-af44cb865b0c980e.js} +1 -1
- package/.next/static/chunks/app/page-43b5de1a0a788b1f.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/{page-9d77c6f755d08086.js → page-66b59fb8c9ee90f4.js} +1 -1
- package/.next/static/chunks/{main-b6d727aa9248d4f2.js → main-f00f82f1cf18dd99.js} +1 -1
- package/.next/static/chunks/{webpack-e6531fcf859d9451.js → webpack-af8567a485ade35a.js} +1 -1
- package/.next/static/css/{4eca30cb81bc52b4.css → 6a92c8ad3c94d15a.css} +1 -1
- package/.next/trace +5 -5
- package/.next/types/app/api/app/update-check/route.ts +343 -0
- package/dist/cli/commands/docs.d.ts +22 -0
- package/dist/cli/commands/docs.d.ts.map +1 -0
- package/dist/cli/commands/docs.js +96 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +3 -0
- package/dist/cli/commands/issue.d.ts +23 -0
- package/dist/cli/commands/issue.d.ts.map +1 -0
- package/dist/cli/commands/issue.js +143 -0
- package/dist/cli/config/ai-integration-messages.d.ts +6 -0
- package/dist/cli/config/ai-integration-messages.d.ts.map +1 -0
- package/dist/cli/config/ai-integration-messages.js +27 -0
- package/dist/cli/config/cli-dependencies.d.ts.map +1 -1
- package/dist/cli/config/cli-dependencies.js +6 -0
- package/dist/cli/config/security-messages.d.ts +3 -1
- package/dist/cli/config/security-messages.d.ts.map +1 -1
- package/dist/cli/config/security-messages.js +4 -1
- package/dist/cli/index.js +15 -2
- package/dist/cli/types/index.d.ts +23 -0
- package/dist/cli/types/index.d.ts.map +1 -1
- package/dist/cli/utils/docs-reader.d.ts +42 -0
- package/dist/cli/utils/docs-reader.d.ts.map +1 -0
- package/dist/cli/utils/docs-reader.js +155 -0
- package/dist/cli/utils/input-validators.d.ts +32 -0
- package/dist/cli/utils/input-validators.d.ts.map +1 -1
- package/dist/cli/utils/input-validators.js +51 -1
- package/dist/cli/utils/preflight.d.ts.map +1 -1
- package/dist/cli/utils/preflight.js +1 -0
- package/dist/config/github-links.d.ts +16 -0
- package/dist/config/github-links.d.ts.map +1 -0
- package/dist/config/github-links.js +22 -0
- package/dist/server/src/lib/prompt-detector.js +207 -67
- package/package.json +1 -1
- package/.next/static/chunks/app/page-792c0577dc44e5e5.js +0 -1
- /package/.next/static/chunks/{4733-db0112b08802aaa7.js → 4733-50bdfc169adb4881.js} +0 -0
- /package/.next/static/{rppRTm2sRWa4sZE7ili8A → zoVKZmyy2snskN1roYhHr}/_buildManifest.js +0 -0
- /package/.next/static/{rppRTm2sRWa4sZE7ili8A → zoVKZmyy2snskN1roYhHr}/_ssgManifest.js +0 -0
|
@@ -184,6 +184,28 @@ const NORMAL_OPTION_PATTERN = /^\s*(\d+)\.\s*(.+)$/;
|
|
|
184
184
|
* Anchored at both ends -- ReDoS safe (S4-001).
|
|
185
185
|
*/
|
|
186
186
|
const SEPARATOR_LINE_PATTERN = /^[-─]+$/;
|
|
187
|
+
/**
|
|
188
|
+
* Maximum number of lines to scan upward from questionEndIndex
|
|
189
|
+
* when the questionEndIndex line itself is not a question-like line.
|
|
190
|
+
*
|
|
191
|
+
* Design rationale (IC-256-001):
|
|
192
|
+
* - model selection prompts have 1-2 lines between "Select model" and first option
|
|
193
|
+
* - multi-line question wrapping typically produces 2-3 continuation lines
|
|
194
|
+
* - value of 3 covers these cases while minimizing False Positive surface
|
|
195
|
+
*
|
|
196
|
+
* [SF-002] Change guidelines:
|
|
197
|
+
* - Increase this value ONLY if real-world prompts are discovered where
|
|
198
|
+
* the question line is more than 3 lines above questionEndIndex
|
|
199
|
+
* - Before increasing, verify that the new value does not cause
|
|
200
|
+
* T11h-T11m False Positive tests to fail
|
|
201
|
+
* - Consider that larger values increase the False Positive surface area
|
|
202
|
+
* - If increasing beyond 5, consider whether the detection approach
|
|
203
|
+
* itself needs to be redesigned (e.g., pattern-based instead of scan-based)
|
|
204
|
+
* - Document the specific prompt pattern that necessitated the change
|
|
205
|
+
*
|
|
206
|
+
* @see Issue #256: multiple_choice prompt detection improvement
|
|
207
|
+
*/
|
|
208
|
+
const QUESTION_SCAN_RANGE = 3;
|
|
187
209
|
/**
|
|
188
210
|
* Creates a "no prompt detected" result.
|
|
189
211
|
* Centralizes the repeated pattern of returning isPrompt: false with trimmed content.
|
|
@@ -244,17 +266,75 @@ function isQuestionLikeLine(line) {
|
|
|
244
266
|
// Empty lines are not questions
|
|
245
267
|
if (line.length === 0)
|
|
246
268
|
return false;
|
|
247
|
-
// Pattern 1: Lines
|
|
269
|
+
// Pattern 1: Lines containing question mark anywhere (English '?' or full-width U+FF1F).
|
|
270
|
+
// This covers both:
|
|
271
|
+
// - Lines ending with '?' (standard question format)
|
|
272
|
+
// - Lines with '?' mid-line (Issue #256: multi-line question wrapping where '?'
|
|
273
|
+
// appears mid-line due to terminal width causing the question text to wrap)
|
|
274
|
+
//
|
|
248
275
|
// Full-width question mark (U+FF1F) support is a defensive measure: Claude Code/CLI
|
|
249
276
|
// displays questions in English, but this covers future multi-language support
|
|
250
277
|
// and third-party tool integration.
|
|
251
|
-
|
|
278
|
+
//
|
|
279
|
+
// [SF-001] Scope constraints:
|
|
280
|
+
// - The mid-line '?' detection is effective without False Positive risk only within
|
|
281
|
+
// SEC-001b guard context (questionEndIndex vicinity and upward scan range).
|
|
282
|
+
// - isQuestionLikeLine() is currently module-private (no export).
|
|
283
|
+
// - If this function is exported for external use in the future, consider:
|
|
284
|
+
// (a) Providing a stricter variant (e.g., isStrictQuestionLikeLine()) without mid-line match
|
|
285
|
+
// (b) Separating mid-line match into a SEC-001b-specific helper function
|
|
286
|
+
// (c) Adding URL exclusion logic (/[?&]\w+=/.test(line) to exclude)
|
|
287
|
+
if (line.includes('?') || line.includes('\uff1f'))
|
|
288
|
+
return true;
|
|
289
|
+
// Pattern 2: Lines containing a selection/input keyword.
|
|
290
|
+
// Detects both colon-terminated (e.g., "Select an option:", "Choose a mode:") and
|
|
291
|
+
// non-colon forms (e.g., "Select model") used by CLI prompts (Issue #256).
|
|
292
|
+
//
|
|
293
|
+
// [SF-001] Scope constraints apply:
|
|
294
|
+
// - Effective without False Positive risk only within SEC-001b guard context.
|
|
295
|
+
// - T11h-T11m False Positive lines do not contain QUESTION_KEYWORD_PATTERN keywords.
|
|
296
|
+
// - If this function is exported, consider restricting this pattern to SEC-001b context.
|
|
297
|
+
if (QUESTION_KEYWORD_PATTERN.test(line))
|
|
252
298
|
return true;
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Search upward from a given line index to find a question-like line.
|
|
303
|
+
* Skips empty lines and separator lines (horizontal rules).
|
|
304
|
+
*
|
|
305
|
+
* This function is used by SEC-001b guard to find a question line above
|
|
306
|
+
* questionEndIndex when the questionEndIndex line itself is not a question-like line.
|
|
307
|
+
* This handles cases where the question text wraps across multiple lines or
|
|
308
|
+
* where description lines appear between the question and the numbered options.
|
|
309
|
+
*
|
|
310
|
+
* @param lines - Array of output lines
|
|
311
|
+
* @param startIndex - Starting line index (exclusive, searches startIndex-1 and above)
|
|
312
|
+
* @param scanRange - Maximum number of lines to scan upward (must be >= 0, clamped to MAX_SCAN_RANGE=10)
|
|
313
|
+
* @param lowerBound - Minimum line index (inclusive, scan will not go below this)
|
|
314
|
+
* @returns true if a question-like line is found within the scan range
|
|
315
|
+
*
|
|
316
|
+
* @see IC-256-002: SEC-001b upward scan implementation
|
|
317
|
+
* @see SF-003: Function extraction for readability
|
|
318
|
+
* @see SF-S4-001: scanRange input validation (defensive clamping)
|
|
319
|
+
*
|
|
320
|
+
* ReDoS safe: Uses SEPARATOR_LINE_PATTERN (existing ReDoS safe pattern) and
|
|
321
|
+
* isQuestionLikeLine() (literal character checks + simple alternation pattern).
|
|
322
|
+
* No new regex patterns introduced. (C-S4-001)
|
|
323
|
+
*/
|
|
324
|
+
function findQuestionLineInRange(lines, startIndex, scanRange, lowerBound) {
|
|
325
|
+
// [SF-S4-001] Defensive input validation: clamp scanRange to safe bounds.
|
|
326
|
+
// Currently only called with QUESTION_SCAN_RANGE=3, but guards against
|
|
327
|
+
// future misuse if the function is refactored or exported.
|
|
328
|
+
const safeScanRange = Math.min(Math.max(scanRange, 0), 10);
|
|
329
|
+
const scanLimit = Math.max(lowerBound, startIndex - safeScanRange);
|
|
330
|
+
for (let i = startIndex - 1; i >= scanLimit; i--) {
|
|
331
|
+
const candidateLine = lines[i]?.trim() ?? '';
|
|
332
|
+
// Skip empty lines and separator lines (horizontal rules)
|
|
333
|
+
if (!candidateLine || SEPARATOR_LINE_PATTERN.test(candidateLine))
|
|
334
|
+
continue;
|
|
335
|
+
if (isQuestionLikeLine(candidateLine)) {
|
|
257
336
|
return true;
|
|
337
|
+
}
|
|
258
338
|
}
|
|
259
339
|
return false;
|
|
260
340
|
}
|
|
@@ -308,19 +388,103 @@ function isConsecutiveFromOne(numbers) {
|
|
|
308
388
|
* @returns true if the line should be treated as a continuation of a previous option
|
|
309
389
|
*/
|
|
310
390
|
function isContinuationLine(rawLine, line) {
|
|
311
|
-
//
|
|
312
|
-
// Excludes lines ending with '?' or '?' (U+FF1F) because those are typically question lines
|
|
391
|
+
// Lines ending with '?' or full-width '?' (U+FF1F) are typically question lines
|
|
313
392
|
// (e.g., " Do you want to proceed?", " コピーしたい対象はどれですか?") from CLI tool output
|
|
314
|
-
// where both the question and options are 2-space indented.
|
|
315
|
-
//
|
|
316
|
-
//
|
|
393
|
+
// where both the question and options are 2-space indented. These must NOT be
|
|
394
|
+
// treated as continuation lines, otherwise questionEndIndex remains -1 and
|
|
395
|
+
// Layer 5 SEC-001 blocks detection.
|
|
317
396
|
const endsWithQuestion = line.endsWith('?') || line.endsWith('\uff1f');
|
|
318
|
-
|
|
319
|
-
//
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
397
|
+
// Check 1: Indented non-option line (label text wrapping with indentation).
|
|
398
|
+
// Must have 2+ leading spaces, not start with a number (option line), and not end with '?'.
|
|
399
|
+
if (!endsWithQuestion && /^\s{2,}[^\d]/.test(rawLine) && !/^\s*\d+\./.test(rawLine)) {
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
// Check 2: Short fragment (< 5 chars, e.g., filename tail).
|
|
403
|
+
// Excludes question-ending lines to prevent misclassifying short questions.
|
|
404
|
+
if (line.length < 5 && !endsWithQuestion) {
|
|
405
|
+
return true;
|
|
406
|
+
}
|
|
407
|
+
// Check 3: Path string continuation (Issue #181).
|
|
408
|
+
// Lines starting with / or ~, or alphanumeric-only fragments (2+ chars).
|
|
409
|
+
if (/^[\/~]/.test(line) || (line.length >= 2 && /^[a-zA-Z0-9_-]+$/.test(line))) {
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Extract question text from the lines around questionEndIndex.
|
|
416
|
+
* Collects non-empty, non-separator lines from up to 5 lines before questionEndIndex
|
|
417
|
+
* through questionEndIndex itself, joining them with spaces.
|
|
418
|
+
*
|
|
419
|
+
* @param lines - Array of output lines
|
|
420
|
+
* @param questionEndIndex - Index of the last line before options, or -1 if not found
|
|
421
|
+
* @returns Extracted question text, or generic fallback if questionEndIndex is -1
|
|
422
|
+
*/
|
|
423
|
+
function extractQuestionText(lines, questionEndIndex) {
|
|
424
|
+
if (questionEndIndex < 0) {
|
|
425
|
+
return 'Please select an option:';
|
|
426
|
+
}
|
|
427
|
+
const questionLines = [];
|
|
428
|
+
for (let i = Math.max(0, questionEndIndex - 5); i <= questionEndIndex; i++) {
|
|
429
|
+
const line = lines[i].trim();
|
|
430
|
+
if (line && !SEPARATOR_LINE_PATTERN.test(line)) {
|
|
431
|
+
questionLines.push(line);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return questionLines.join(' ');
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Extract instruction text for the prompt block.
|
|
438
|
+
* Captures the complete AskUserQuestion block including context before the question,
|
|
439
|
+
* option descriptions, and navigation hints.
|
|
440
|
+
*
|
|
441
|
+
* @param lines - Array of output lines
|
|
442
|
+
* @param questionEndIndex - Index of the last line before options, or -1 if not found
|
|
443
|
+
* @param effectiveEnd - End index of non-trailing-empty lines
|
|
444
|
+
* @returns Instruction text string, or undefined if no question line found
|
|
445
|
+
*/
|
|
446
|
+
function extractInstructionText(lines, questionEndIndex, effectiveEnd) {
|
|
447
|
+
if (questionEndIndex < 0) {
|
|
448
|
+
return undefined;
|
|
449
|
+
}
|
|
450
|
+
const contextStart = Math.max(0, questionEndIndex - 19);
|
|
451
|
+
const blockLines = lines.slice(contextStart, effectiveEnd)
|
|
452
|
+
.map(l => l.trimEnd());
|
|
453
|
+
const joined = blockLines.join('\n').trim();
|
|
454
|
+
return joined.length > 0 ? joined : undefined;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Build the final PromptDetectionResult for a multiple choice prompt.
|
|
458
|
+
* Maps collected options to the output format, checking each option for
|
|
459
|
+
* text input requirements using TEXT_INPUT_PATTERNS.
|
|
460
|
+
*
|
|
461
|
+
* @param question - Extracted question text
|
|
462
|
+
* @param collectedOptions - Options collected during Pass 2 scanning
|
|
463
|
+
* @param instructionText - Instruction text for the prompt block
|
|
464
|
+
* @param output - Original output text (used for rawContent truncation)
|
|
465
|
+
* @returns PromptDetectionResult with isPrompt: true and multiple_choice data
|
|
466
|
+
*/
|
|
467
|
+
function buildMultipleChoiceResult(question, collectedOptions, instructionText, output) {
|
|
468
|
+
return {
|
|
469
|
+
isPrompt: true,
|
|
470
|
+
promptData: {
|
|
471
|
+
type: 'multiple_choice',
|
|
472
|
+
question: question.trim(),
|
|
473
|
+
options: collectedOptions.map(opt => {
|
|
474
|
+
const requiresTextInput = TEXT_INPUT_PATTERNS.some(pattern => pattern.test(opt.label));
|
|
475
|
+
return {
|
|
476
|
+
number: opt.number,
|
|
477
|
+
label: opt.label,
|
|
478
|
+
isDefault: opt.isDefault,
|
|
479
|
+
requiresTextInput,
|
|
480
|
+
};
|
|
481
|
+
}),
|
|
482
|
+
status: 'pending',
|
|
483
|
+
instructionText,
|
|
484
|
+
},
|
|
485
|
+
cleanContent: question.trim(),
|
|
486
|
+
rawContent: truncateRawContent(output.trim()), // Issue #235: complete prompt output (truncated) [MF-001]
|
|
487
|
+
};
|
|
324
488
|
}
|
|
325
489
|
/**
|
|
326
490
|
* Detect multiple choice prompts (numbered list with ❯ indicator)
|
|
@@ -399,6 +563,20 @@ function detectMultipleChoicePrompt(output, options) {
|
|
|
399
563
|
}
|
|
400
564
|
// Non-option line handling
|
|
401
565
|
if (collectedOptions.length > 0 && line && !SEPARATOR_LINE_PATTERN.test(line)) {
|
|
566
|
+
// [MF-001 / Issue #256] Check if line is a question-like line BEFORE
|
|
567
|
+
// continuation check. This preserves isContinuationLine()'s SRP by not
|
|
568
|
+
// mixing question detection into it. Without this pre-check, indented
|
|
569
|
+
// question lines (e.g., " Select model") could be misclassified as
|
|
570
|
+
// continuation lines by isContinuationLine()'s hasLeadingSpaces check.
|
|
571
|
+
//
|
|
572
|
+
// [SF-S4-003] Both this pre-check and SEC-001b upward scan use the same
|
|
573
|
+
// isQuestionLikeLine() function intentionally (DRY). If a question line is
|
|
574
|
+
// caught here, SEC-001b upward scan is not needed (questionEndIndex line
|
|
575
|
+
// itself passes isQuestionLikeLine()).
|
|
576
|
+
if (isQuestionLikeLine(line)) {
|
|
577
|
+
questionEndIndex = i;
|
|
578
|
+
break;
|
|
579
|
+
}
|
|
402
580
|
// Check if this is a continuation line (indented line between options,
|
|
403
581
|
// or path/filename fragments from terminal width wrapping - Issue #181)
|
|
404
582
|
const rawLine = lines[i]; // Original line with indentation preserved
|
|
@@ -435,61 +613,23 @@ function detectMultipleChoicePrompt(output, options) {
|
|
|
435
613
|
// SEC-001b: Question line exists but is not actually a question/selection request.
|
|
436
614
|
// Validates that the question line contains a question mark or a selection keyword
|
|
437
615
|
// with colon, distinguishing "Select an option:" from "Recommendations:".
|
|
616
|
+
//
|
|
617
|
+
// [Issue #256] Enhanced with upward scan via findQuestionLineInRange() (SF-003).
|
|
618
|
+
// When questionEndIndex line itself is not a question-like line, scan upward
|
|
619
|
+
// within QUESTION_SCAN_RANGE to find a question line above it. This handles:
|
|
620
|
+
// - Multi-line question wrapping where ? is on a line above questionEndIndex
|
|
621
|
+
// - Model selection prompts where "Select model" is above description lines
|
|
438
622
|
const questionLine = lines[questionEndIndex]?.trim() ?? '';
|
|
439
623
|
if (!isQuestionLikeLine(questionLine)) {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
// Extract question text
|
|
444
|
-
let question = '';
|
|
445
|
-
if (questionEndIndex >= 0) {
|
|
446
|
-
// Get all non-empty lines from questionEndIndex up to (but not including) first option
|
|
447
|
-
const questionLines = [];
|
|
448
|
-
for (let i = Math.max(0, questionEndIndex - 5); i <= questionEndIndex; i++) {
|
|
449
|
-
const line = lines[i].trim();
|
|
450
|
-
if (line && !SEPARATOR_LINE_PATTERN.test(line)) {
|
|
451
|
-
questionLines.push(line);
|
|
624
|
+
// Upward scan: look for a question-like line above questionEndIndex
|
|
625
|
+
if (!findQuestionLineInRange(lines, questionEndIndex, QUESTION_SCAN_RANGE, scanStart)) {
|
|
626
|
+
return noPromptResult(output);
|
|
452
627
|
}
|
|
453
628
|
}
|
|
454
|
-
question = questionLines.join(' ');
|
|
455
|
-
}
|
|
456
|
-
else {
|
|
457
|
-
// No clear question found - use a generic one
|
|
458
|
-
question = 'Please select an option:';
|
|
459
|
-
}
|
|
460
|
-
// Extract instruction text: full prompt block (context before question through all options/descriptions)
|
|
461
|
-
// Captures the complete AskUserQuestion block including option descriptions and navigation hints.
|
|
462
|
-
let instructionText;
|
|
463
|
-
if (questionEndIndex >= 0) {
|
|
464
|
-
const contextStart = Math.max(0, questionEndIndex - 19);
|
|
465
|
-
const blockLines = lines.slice(contextStart, effectiveEnd)
|
|
466
|
-
.map(l => l.trimEnd());
|
|
467
|
-
const joined = blockLines.join('\n').trim();
|
|
468
|
-
if (joined.length > 0) {
|
|
469
|
-
instructionText = joined;
|
|
470
|
-
}
|
|
471
629
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
type: 'multiple_choice',
|
|
476
|
-
question: question.trim(),
|
|
477
|
-
options: collectedOptions.map(opt => {
|
|
478
|
-
// Check if this option requires text input using module-level patterns
|
|
479
|
-
const requiresTextInput = TEXT_INPUT_PATTERNS.some(pattern => pattern.test(opt.label));
|
|
480
|
-
return {
|
|
481
|
-
number: opt.number,
|
|
482
|
-
label: opt.label,
|
|
483
|
-
isDefault: opt.isDefault,
|
|
484
|
-
requiresTextInput,
|
|
485
|
-
};
|
|
486
|
-
}),
|
|
487
|
-
status: 'pending',
|
|
488
|
-
instructionText,
|
|
489
|
-
},
|
|
490
|
-
cleanContent: question.trim(),
|
|
491
|
-
rawContent: truncateRawContent(output.trim()), // Issue #235: complete prompt output (truncated) [MF-001]
|
|
492
|
-
};
|
|
630
|
+
const question = extractQuestionText(lines, questionEndIndex);
|
|
631
|
+
const instructionText = extractInstructionText(lines, questionEndIndex, effectiveEnd);
|
|
632
|
+
return buildMultipleChoiceResult(question, collectedOptions, instructionText, output);
|
|
493
633
|
}
|
|
494
634
|
/**
|
|
495
635
|
* Get tmux input string for an answer
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1931],{14564:function(e,t,a){Promise.resolve().then(a.bind(a,23327))},23327:function(e,t,a){"use strict";a.r(t),a.d(t,{default:function(){return z}});var s=a(57437),r=a(2265),l=a(21221),n=a(27648),i=a(10789),c=a(38706),o=a(69234),d=a(45306),x=a(69073),m=a(8854);let p={en:m._,ja:x.ja};var u=a(3227);function h(e){var t;let{worktree:a,onSessionKilled:l,onStatusChanged:x}=e,{id:h,name:g,description:y,updatedAt:b,isSessionRunning:f,isWaitingForResponse:j,favorite:v,status:N,link:w}=a,[k,C]=(0,r.useState)(!1),[S,z]=(0,r.useState)(v||!1),[P,A]=(0,r.useState)(!1),[E,L]=(0,r.useState)(N||null),[T,D]=(0,r.useState)(!1),R=(0,c.T)(),I=null!==(t=p[(0,o.bU)()])&&void 0!==t?t:m._,O=b?(0,d.Q)(new Date(b),{addSuffix:!0,locale:I}):null,M="main"===g||"master"===g,F=async e=>{if(e.preventDefault(),e.stopPropagation(),confirm(R("worktree.session.confirmKill",{name:g})))try{C(!0),await u.Iv.killSession(h),l&&l()}catch(t){let e=(0,u.zG)(t);alert("".concat(R("worktree.session.failedToKill"),": ").concat(e))}finally{C(!1)}},U=async e=>{e.preventDefault(),e.stopPropagation();try{A(!0);let e=!S;await u.Iv.toggleFavorite(h,e),z(e)}catch(t){let e=(0,u.zG)(t);alert("".concat(R("worktree.errors.failedToUpdateFavorite"),": ").concat(e))}finally{A(!1)}},_=async(e,t)=>{t.preventDefault(),t.stopPropagation();try{D(!0),await u.Iv.updateStatus(h,e),L(e),x&&x()}catch(t){let e=(0,u.zG)(t);alert("".concat(R("worktree.errors.failedToUpdateStatus"),": ").concat(e))}finally{D(!1)}};return(0,s.jsx)(n.default,{href:"/worktrees/".concat(h),className:"block",children:(0,s.jsxs)(i.Zb,{hover:!0,padding:"lg",className:"h-full",children:[(0,s.jsx)(i.Ol,{children:(0,s.jsxs)("div",{className:"flex items-start justify-between gap-2",children:[(0,s.jsxs)(i.ll,{className:"flex items-center gap-2 flex-wrap",children:[(0,s.jsx)("button",{onClick:U,disabled:P,className:"flex-shrink-0 transition-colors hover:scale-110",title:S?R("common.favorites.remove"):R("common.favorites.add"),children:(0,s.jsx)("svg",{className:"w-5 h-5 ".concat(S?"fill-yellow-400 text-yellow-400":"fill-none text-gray-400"),stroke:"currentColor",strokeWidth:"2",viewBox:"0 0 24 24",children:(0,s.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z"})})}),(0,s.jsx)("span",{className:"truncate",children:g}),M&&(0,s.jsx)(i.Ct,{variant:"info",children:"Main"}),f&&j&&(0,s.jsx)(i.Ct,{variant:"warning",dot:!0,children:R("worktree.status.waitingForResponse")}),f&&!j&&(0,s.jsx)(i.Ct,{variant:"success",dot:!0,children:R("worktree.status.responseCompleted")})]}),f&&(0,s.jsx)(i.zx,{variant:"danger",size:"sm",onClick:F,disabled:k,className:"flex-shrink-0",children:k?R("common.ending"):R("common.end")})]})}),(0,s.jsx)(i.aY,{children:(0,s.jsxs)("div",{className:"space-y-3",children:[y&&(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"text-xs text-gray-500 mb-1",children:"Description"}),(0,s.jsx)("p",{className:"text-sm text-gray-700 line-clamp-2 whitespace-pre-wrap",children:y})]}),w&&(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"text-xs text-gray-500 mb-1",children:"Link"}),(0,s.jsxs)("button",{onClick:e=>{e.preventDefault(),e.stopPropagation(),w&&window.open(w,"_blank","noopener,noreferrer")},className:"flex items-center gap-1 text-sm text-blue-600 hover:text-blue-800 hover:underline transition-colors",title:"Open link in new tab",children:[(0,s.jsx)("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,s.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"})}),(0,s.jsx)("span",{className:"truncate",children:w})]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"text-xs text-gray-500 mb-1",children:"Status"}),(0,s.jsxs)("div",{className:"flex gap-1 flex-wrap",children:[(0,s.jsx)("button",{onClick:e=>_(null,e),disabled:T,className:"px-2 py-1 text-xs font-medium rounded border transition-colors disabled:opacity-50 ".concat(null===E?"bg-gray-100 text-gray-700 border-gray-400":"bg-white text-gray-600 border-gray-200 hover:bg-gray-50"),children:"Not set"}),(0,s.jsx)("button",{onClick:e=>_("todo",e),disabled:T,className:"px-2 py-1 text-xs font-medium rounded border transition-colors disabled:opacity-50 ".concat("todo"===E?"bg-gray-100 text-gray-700 border-gray-400":"bg-white text-gray-600 border-gray-200 hover:bg-gray-50"),children:"ToDo"}),(0,s.jsx)("button",{onClick:e=>_("doing",e),disabled:T,className:"px-2 py-1 text-xs font-medium rounded border transition-colors disabled:opacity-50 ".concat("doing"===E?"bg-blue-100 text-blue-700 border-blue-400":"bg-white text-gray-600 border-gray-200 hover:bg-blue-50"),children:"Doing"}),(0,s.jsx)("button",{onClick:e=>_("done",e),disabled:T,className:"px-2 py-1 text-xs font-medium rounded border transition-colors disabled:opacity-50 ".concat("done"===E?"bg-green-100 text-green-700 border-green-400":"bg-white text-gray-600 border-gray-200 hover:bg-green-50"),children:"Done"})]})]}),O&&(0,s.jsxs)("div",{className:"flex items-center text-xs text-gray-500",children:[(0,s.jsx)("svg",{className:"w-4 h-4 mr-1",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,s.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"})}),(0,s.jsxs)("span",{children:["Updated ",O]})]})]})})]})})}function g(e){let{initialWorktrees:t=[]}=e,[a,l]=(0,r.useState)(t),[n,c]=(0,r.useState)([]),[o,d]=(0,r.useState)(!t.length),[x,m]=(0,r.useState)(null),[p,g]=(0,r.useState)(""),[y,b]=(0,r.useState)("updated"),[f,j]=(0,r.useState)("desc"),[v,N]=(0,r.useState)(null),[w,k]=(0,r.useState)(null),[C,S]=(0,r.useState)(null),[z,P]=(0,r.useState)([]),[A,E]=(0,r.useState)(!1),[L,T]=(0,r.useState)(null),D=(0,r.useCallback)(async()=>{try{let e=await u.J1.getExcluded();e.success&&P(e.repositories)}catch(e){}},[]),R=(0,r.useCallback)(async function(){let e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];try{e||d(!0),m(null);let t=await u.Iv.getAll();l(t.worktrees),c(t.repositories)}catch(e){m((0,u.zG)(e))}finally{e||d(!1)}},[]),I=e=>!!(e&&"session_status_changed"===e.type),{status:O}=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{worktreeIds:t=[],onMessage:a,onStatusChange:s,autoReconnect:l=!0,reconnectDelay:n=3e3}=e,[i,c]=(0,r.useState)("disconnected"),o=(0,r.useRef)(null),d=(0,r.useRef)(),x=(0,r.useRef)(new Set),m=(0,r.useCallback)(e=>{c(e),null==s||s(e)},[s]),p=(0,r.useCallback)(()=>{var e;if((null===(e=o.current)||void 0===e?void 0:e.readyState)===WebSocket.OPEN)return;m("connecting");let t="https:"===window.location.protocol?"wss:":"ws:",s=new WebSocket("".concat(t,"//").concat(window.location.host));s.onopen=()=>{m("connected"),x.current.forEach(e=>{s.send(JSON.stringify({type:"subscribe",worktreeId:e}))})},s.onmessage=e=>{try{let t=JSON.parse(e.data);null==a||a(t)}catch(e){console.error("Failed to parse WebSocket message:",e)}},s.onerror=()=>{m("error")},s.onclose=()=>{m("disconnected"),o.current=null,l&&(d.current=setTimeout(()=>{p()},n))},o.current=s},[m,a,l,n]),u=(0,r.useCallback)(()=>{d.current&&clearTimeout(d.current),o.current&&(o.current.close(1e3,"Client disconnect"),o.current=null),m("disconnected")},[m]),h=(0,r.useCallback)(e=>{var t;(null===(t=o.current)||void 0===t?void 0:t.readyState)===WebSocket.OPEN&&(o.current.send(JSON.stringify({type:"subscribe",worktreeId:e})),x.current.add(e))},[]),g=(0,r.useCallback)(e=>{var t;(null===(t=o.current)||void 0===t?void 0:t.readyState)===WebSocket.OPEN&&(o.current.send(JSON.stringify({type:"unsubscribe",worktreeId:e})),x.current.delete(e))},[]),y=(0,r.useCallback)(e=>{var t;(null===(t=o.current)||void 0===t?void 0:t.readyState)===WebSocket.OPEN&&o.current.send(JSON.stringify(e))},[]);return(0,r.useEffect)(()=>(p(),()=>{u()}),[]),(0,r.useEffect)(()=>{"connected"===i&&t.length>0&&t.forEach(e=>{h(e)})},[i,t]),{status:i,subscribe:h,unsubscribe:g,sendMessage:y,connect:p,disconnect:u}}({onMessage:(0,r.useCallback)(e=>{if(I(e.data)){let t=e.data;l(e=>e.map(e=>e.id===t.worktreeId?{...e,isSessionRunning:t.isRunning}:e))}"broadcast"===e.type&&R(!0)},[R])});(0,r.useEffect)(()=>{t.length||R(),D()},[t.length,R,D]),(0,r.useEffect)(()=>{let e=setInterval(()=>{R(!0)},5e3);return()=>clearInterval(e)},[R]);let M=(0,r.useMemo)(()=>{let e=[...a];if(v&&(e=e.filter(e=>e.repositoryPath===v)),null!==w&&(e="unset"===w?e.filter(e=>!e.status):e.filter(e=>e.status===w)),p){let t=p.toLowerCase();e=e.filter(e=>{var a,s;return e.name.toLowerCase().includes(t)||e.path.toLowerCase().includes(t)||e.repositoryName.toLowerCase().includes(t)||(null===(a=e.lastMessageSummary)||void 0===a?void 0:a.toLowerCase().includes(t))||(null===(s=e.description)||void 0===s?void 0:s.toLowerCase().includes(t))})}return e.sort((e,t)=>{let a=0;switch(y){case"name":a=e.name.localeCompare(t.name);break;case"updated":a=(e.updatedAt?new Date(e.updatedAt).getTime():0)-(t.updatedAt?new Date(t.updatedAt).getTime():0);break;case"favorite":a=(e.favorite?1:0)-(t.favorite?1:0)}return"asc"===f?a:-a}),e},[a,v,w,p,y,f]),F=(0,r.useMemo)(()=>{let e=new Map;for(let t of M){let a=t.repositoryPath||"unknown";e.has(a)||e.set(a,[]),e.get(a).push(t)}return e},[M]),U=e=>{y===e?j(e=>"asc"===e?"desc":"asc"):(b(e),j("asc"))},_=async e=>{T(e);try{let t=await u.J1.restore(e);t.warning&&m(t.warning),await R(),await D()}catch(e){m((0,u.zG)(e))}finally{T(null)}},W=async(e,t)=>{var a;let s=(null===(a=n.find(t=>t.path===e))||void 0===a?void 0:a.worktreeCount)||0;if("delete"===prompt('Delete repository "'.concat(t,'"?\n\nThis will delete:\n- ').concat(s,' worktree(s)\n- Related chat history\n- Related memos\n\n* Log files will be preserved\n\nThis repository will be added to the exclusion list.\nIt will NOT be re-registered when you run "Sync All".\nYou can restore it from the excluded repositories list.\n\nType "delete" to confirm:'))){S(e);try{await u.J1.delete(e),v===e&&N(null),await R(),await D()}catch(e){m((0,u.zG)(e))}finally{S(null)}}};return(0,s.jsxs)("div",{className:"space-y-6",children:[(0,s.jsxs)("div",{className:"flex flex-col sm:flex-row gap-4 items-start sm:items-center justify-between",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 flex-wrap",children:[(0,s.jsxs)(i.Ct,{variant:"gray",children:[a.length," branches"]}),n.length>0&&(0,s.jsxs)(i.Ct,{variant:"info",children:[n.length," ",1===n.length?"repository":"repositories"]}),"connected"===O&&(0,s.jsx)(i.Ct,{variant:"success",dot:!0,children:"Live"})]}),(0,s.jsx)("div",{className:"flex gap-2 w-full sm:w-auto",children:(0,s.jsx)(i.zx,{variant:"secondary",size:"sm",onClick:()=>R(),disabled:o,children:o?"Loading...":"Refresh"})})]}),(0,s.jsx)("div",{className:"flex flex-col sm:flex-row gap-3",children:(0,s.jsx)("input",{type:"text",placeholder:"Search worktrees...",value:p,onChange:e=>g(e.target.value),className:"input flex-1"})}),n.length>0&&(0,s.jsxs)("div",{className:"flex gap-2 flex-wrap items-center",children:[(0,s.jsxs)(i.zx,{variant:null===v?"primary":"ghost",size:"sm",onClick:()=>N(null),children:["All (",a.length,")"]}),n.map(e=>(0,s.jsxs)("div",{className:"relative group inline-flex items-center",children:[(0,s.jsxs)(i.zx,{variant:v===e.path?"primary":"ghost",size:"sm",onClick:()=>N(e.path),className:"pr-6",children:[e.name," (",e.worktreeCount,")"]}),(0,s.jsx)("button",{className:"absolute right-1 opacity-0 group-hover:opacity-100 text-gray-400 hover:text-red-500 transition-opacity px-1",onClick:t=>{t.stopPropagation(),W(e.path,e.name)},disabled:C===e.path,title:"Delete repository",children:C===e.path?"...":"x"})]},e.path))]}),(0,s.jsxs)("div",{className:"flex gap-2 flex-wrap items-center",children:[(0,s.jsx)(i.zx,{variant:null===w?"primary":"ghost",size:"sm",onClick:()=>k(null),children:"All"}),(0,s.jsx)(i.zx,{variant:"todo"===w?"primary":"ghost",size:"sm",onClick:()=>k("todo"),children:"\uD83D\uDCDD ToDo"}),(0,s.jsx)(i.zx,{variant:"doing"===w?"primary":"ghost",size:"sm",onClick:()=>k("doing"),children:"\uD83D\uDEA7 Doing"}),(0,s.jsx)(i.zx,{variant:"done"===w?"primary":"ghost",size:"sm",onClick:()=>k("done"),children:"✅ Done"}),(0,s.jsx)(i.zx,{variant:"unset"===w?"primary":"ghost",size:"sm",onClick:()=>k("unset"),children:"Not set"})]}),(0,s.jsxs)("div",{className:"flex gap-2 flex-wrap",children:[(0,s.jsx)("span",{className:"text-sm text-gray-600 self-center",children:"Sort by:"}),(0,s.jsxs)(i.zx,{variant:"favorite"===y?"primary":"ghost",size:"sm",onClick:()=>U("favorite"),children:["⭐ Favorite ","favorite"===y&&("asc"===f?"↑":"↓")]}),(0,s.jsxs)(i.zx,{variant:"name"===y?"primary":"ghost",size:"sm",onClick:()=>U("name"),children:["Name ","name"===y&&("asc"===f?"↑":"↓")]}),(0,s.jsxs)(i.zx,{variant:"updated"===y?"primary":"ghost",size:"sm",onClick:()=>U("updated"),children:["Updated ","updated"===y&&("asc"===f?"↑":"↓")]})]}),x&&(0,s.jsx)("div",{className:"p-4 bg-red-50 border border-red-200 rounded-lg",children:(0,s.jsx)("p",{className:"text-sm text-red-800",children:x})}),o&&!a.length&&(0,s.jsxs)("div",{className:"text-center py-12",children:[(0,s.jsx)("div",{className:"inline-block animate-spin rounded-full h-8 w-8 border-4 border-gray-300 border-t-blue-600"}),(0,s.jsx)("p",{className:"mt-4 text-gray-600",children:"Loading worktrees..."})]}),!o&&!x&&0===M.length&&(0,s.jsxs)("div",{className:"text-center py-12",children:[(0,s.jsx)("svg",{className:"mx-auto h-12 w-12 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,s.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"})}),(0,s.jsx)("p",{className:"mt-4 text-gray-600",children:p?"No worktrees found matching your search":"No worktrees found"})]}),!o&&M.length>0&&(0,s.jsx)("div",{className:"space-y-8",children:Array.from(F.entries()).map(e=>{let[t,a]=e,r=n.find(e=>e.path===t),l=(null==r?void 0:r.name)||"Unknown Repository";return(0,s.jsxs)("div",{className:"space-y-4",children:[(n.length>1||!v)&&(0,s.jsxs)("div",{className:"flex items-center gap-3 pb-2 border-b border-gray-200",children:[(0,s.jsx)("h3",{className:"text-xl font-semibold text-gray-900",children:l}),(0,s.jsx)(i.Ct,{variant:"gray",children:a.length})]}),(0,s.jsx)("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6",children:a.map(e=>(0,s.jsx)(h,{worktree:e,onSessionKilled:R,onStatusChanged:R},e.id))})]},t)})}),z.length>0&&(0,s.jsxs)("div",{className:"border border-gray-200 rounded-lg",children:[(0,s.jsxs)("button",{className:"w-full flex items-center justify-between p-4 text-left hover:bg-gray-50 transition-colors",onClick:()=>E(!A),children:[(0,s.jsxs)("span",{className:"text-sm font-medium text-gray-700",children:["Excluded Repositories (",z.length,")"]}),(0,s.jsx)("span",{className:"text-gray-400 text-sm",children:A?"Hide":"Show"})]}),A&&(0,s.jsx)("div",{className:"border-t border-gray-200 divide-y divide-gray-100",children:z.map(e=>(0,s.jsxs)("div",{className:"flex items-center justify-between p-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("span",{className:"text-sm font-medium text-gray-700",children:e.name}),(0,s.jsx)("span",{className:"text-xs text-gray-500 ml-2",children:e.path})]}),(0,s.jsx)(i.zx,{variant:"secondary",size:"sm",onClick:()=>_(e.path),disabled:L===e.path,children:L===e.path?"Restoring...":"Restore"})]},e.id))})]})]})}a(99376),a(34343),a(6940),a(43616);class y{static getInstance(){return y.instance||(y.instance=new y),y.instance}normalize(e){let t=e.match(/^ssh:\/\/git@([^:\/]+)(:\d+)?\/(.+?)(\.git)?$/);if(t)return"https://".concat(t[1],"/").concat(t[3]).toLowerCase().replace(/\/$/,"");let a=e.match(/^git@([^:]+):(.+?)(\.git)?$/);return a?"https://".concat(a[1],"/").concat(a[2]).toLowerCase().replace(/\/$/,""):e.replace(/\.git\/?$/,"").replace(/\/$/,"").toLowerCase()}isSameRepository(e,t){return this.normalize(e)===this.normalize(t)}extractRepoName(e){let t=e.match(/^ssh:\/\/git@[^\/]+\/(.+?)(\.git)?$/);if(t){let e=t[1].split("/");return e[e.length-1]}let a=e.match(/:(.+?)(\.git)?$/);if(a&&e.startsWith("git@")){let e=a[1].split("/");return e[e.length-1]}let s=e.match(/\/([^\/]+?)(\.git)?$/);return s?s[1]:""}getUrlType(e){return e.startsWith("https://")?"https":e.startsWith("git@")||e.startsWith("ssh://")?"ssh":null}validate(e){if(!e||"string"!=typeof e||""===e.trim())return{valid:!1,error:"EMPTY_URL"};let t=e.trim();return t.startsWith("https://")?/^https:\/\/[^\/]+\/[^\/]+\/[^\/]+(\.git)?$/.test(t)?{valid:!0}:{valid:!1,error:"INVALID_URL_FORMAT"}:t.startsWith("git@")?/^git@[^:]+:.+\/.+(\.git)?$/.test(t)?{valid:!0}:{valid:!1,error:"INVALID_URL_FORMAT"}:t.startsWith("ssh://")&&/^ssh:\/\/git@[^\/]+(:\d+)?\/[^\/]+\/.+(\.git)?$/.test(t)?{valid:!0}:{valid:!1,error:"INVALID_URL_FORMAT"}}constructor(){}}function b(e){let{onRepositoryAdded:t}=e,[a,l]=(0,r.useState)(!1),[n,c]=(0,r.useState)("local"),[o,d]=(0,r.useState)(""),[x,m]=(0,r.useState)(""),[p,h]=(0,r.useState)(!1),[g,b]=(0,r.useState)(!1),[f,j]=(0,r.useState)(!1),[v,N]=(0,r.useState)(null),[w,k]=(0,r.useState)(null),[C,S]=(0,r.useState)(null),z=y.getInstance(),P=(0,r.useCallback)(async e=>{try{let s=await u.J1.getCloneStatus(e);if("completed"===s.status)S("Repository cloned successfully"),j(!1),N(null),m(""),l(!1),t&&t();else if("failed"===s.status){var a;k((null===(a=s.error)||void 0===a?void 0:a.message)||"Clone failed"),j(!1),N(null)}else("running"===s.status||"pending"===s.status)&&setTimeout(()=>P(e),2e3)}catch(e){k((0,u.zG)(e)),j(!1),N(null)}},[t]);(0,r.useEffect)(()=>{v&&f&&P(v)},[v,f,P]);let A=async e=>{if(e.preventDefault(),!o.trim()){k("Repository path is required");return}k(null),S(null),h(!0);try{let e=await u.J1.scan(o);S(e.message),d(""),l(!1),t&&t()}catch(e){k((0,u.zG)(e))}finally{h(!1)}},E=async e=>{if(e.preventDefault(),!x.trim()){k("Clone URL is required");return}let t=z.validate(x.trim());if(!t.valid){"EMPTY_URL"===t.error?k("Clone URL is required"):k("Invalid URL format");return}k(null),S(null),j(!0);try{let e=await u.J1.clone(x.trim());N(e.jobId)}catch(e){k((0,u.zG)(e)),j(!1)}},L=async()=>{k(null),S(null),b(!0);try{let e=await u.J1.sync();S(e.message),t&&t()}catch(e){k((0,u.zG)(e))}finally{b(!1)}},T=()=>{l(!1),d(""),m(""),k(null),c("local")};return(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsxs)("div",{className:"flex gap-2 flex-wrap",children:[!a&&(0,s.jsx)(i.zx,{variant:"primary",size:"sm",onClick:()=>l(!0),children:"+ Add Repository"}),(0,s.jsx)(i.zx,{variant:"secondary",size:"sm",onClick:L,disabled:g,children:g?"Syncing...":"Sync All"})]}),a&&(0,s.jsx)(i.Zb,{padding:"lg",children:(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsx)("div",{children:(0,s.jsx)("h3",{className:"text-lg font-semibold mb-2",children:"Add New Repository"})}),(0,s.jsxs)("div",{className:"flex border-b border-gray-200",role:"tablist",children:[(0,s.jsx)("button",{role:"tab","aria-selected":"local"===n,onClick:()=>c("local"),className:"px-4 py-2 text-sm font-medium border-b-2 -mb-px transition-colors ".concat("local"===n?"border-blue-500 text-blue-600":"border-transparent text-gray-500 hover:text-gray-700"),children:"Local Path"}),(0,s.jsx)("button",{role:"tab","aria-selected":"url"===n,onClick:()=>c("url"),className:"px-4 py-2 text-sm font-medium border-b-2 -mb-px transition-colors ".concat("url"===n?"border-blue-500 text-blue-600":"border-transparent text-gray-500 hover:text-gray-700"),children:"Clone URL"})]}),"local"===n&&(0,s.jsxs)("form",{onSubmit:A,className:"space-y-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"text-sm text-gray-600 mb-4",children:"Enter the absolute path to a git repository containing worktrees."}),(0,s.jsx)("label",{htmlFor:"repositoryPath",className:"block text-sm font-medium text-gray-700 mb-2",children:"Repository Path"}),(0,s.jsx)("input",{id:"repositoryPath",type:"text",value:o,onChange:e=>d(e.target.value),placeholder:"/absolute/path/to/repository",className:"input w-full font-mono text-sm",disabled:p}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-1",children:"Example: /Users/username/projects/my-repo"})]}),(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)(i.zx,{type:"submit",variant:"primary",disabled:p||!o.trim(),children:p?"Scanning...":"Scan & Add"}),(0,s.jsx)(i.zx,{type:"button",variant:"ghost",onClick:T,disabled:p,children:"Cancel"})]})]}),"url"===n&&(0,s.jsxs)("form",{onSubmit:E,className:"space-y-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"text-sm text-gray-600 mb-4",children:"Enter a git clone URL to clone a remote repository."}),(0,s.jsx)("label",{htmlFor:"cloneUrl",className:"block text-sm font-medium text-gray-700 mb-2",children:"Clone URL"}),(0,s.jsx)("input",{id:"cloneUrl",type:"text",value:x,onChange:e=>m(e.target.value),placeholder:"https://github.com/user/repo.git",className:"input w-full font-mono text-sm",disabled:f}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-1",children:"Supports HTTPS and SSH URLs"})]}),(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)(i.zx,{type:"submit",variant:"primary",disabled:f||!x.trim(),children:f?"Cloning...":"Clone"}),(0,s.jsx)(i.zx,{type:"button",variant:"ghost",onClick:T,disabled:f,children:"Cancel"})]})]})]})}),C&&(0,s.jsx)("div",{className:"p-4 bg-green-50 border border-green-200 rounded-lg",children:(0,s.jsx)("p",{className:"text-sm text-green-800",children:C})}),w&&(0,s.jsx)("div",{className:"p-4 bg-red-50 border border-red-200 rounded-lg",children:(0,s.jsx)("p",{className:"text-sm text-red-800",children:w})})]})}function f(e){var t;let{appId:a,pollInterval:l=3e4,showResponseTime:n=!1,compact:i=!1}=e,[c,o]=(0,r.useState)(null),[d,x]=(0,r.useState)(!0),m=(0,r.useCallback)(async()=>{try{let e=await fetch("/api/external-apps/".concat(a,"/health"));if(e.ok){let t=await e.json();o(t)}else o({id:a,healthy:!1,lastChecked:Date.now(),error:"Failed to check health"})}catch(e){o({id:a,healthy:!1,lastChecked:Date.now(),error:"Network error"})}finally{x(!1)}},[a]);if((0,r.useEffect)(()=>{m();let e=setInterval(m,l);return()=>clearInterval(e)},[m,l]),d)return(0,s.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,s.jsx)("span",{className:"inline-block h-2.5 w-2.5 rounded-full bg-gray-300 animate-pulse"}),!i&&(0,s.jsx)("span",{className:"text-xs text-gray-400",children:"Checking..."})]});let p=null!==(t=null==c?void 0:c.healthy)&&void 0!==t&&t,u=p?"bg-green-500":"bg-gray-400",h=p?"Running":"Stopped";return i?(0,s.jsx)("span",{className:"inline-block h-2.5 w-2.5 rounded-full ".concat(u),title:h}):(0,s.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,s.jsx)("span",{className:"inline-block h-2.5 w-2.5 rounded-full ".concat(u)}),(0,s.jsx)("span",{className:"text-xs ".concat(p?"text-green-600":"text-gray-500"),children:h}),n&&(null==c?void 0:c.responseTime)!==void 0&&(0,s.jsxs)("span",{className:"text-xs text-gray-400",children:["(",c.responseTime,"ms)"]})]})}function j(e){var t;let{app:a,onEdit:l,onDelete:n}=e,[c,o]=(0,r.useState)(!1),[d,x]=(0,r.useState)(!1),m=async()=>{x(!0);try{await n(a.id)}finally{x(!1),o(!1)}},p="/proxy/".concat(a.pathPrefix,"/");return(0,s.jsxs)(i.Zb,{padding:"md",className:"relative",children:[(0,s.jsxs)("div",{className:"flex items-start justify-between mb-3",children:[(0,s.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,s.jsx)("h4",{className:"text-base font-semibold text-gray-900 truncate",children:a.displayName}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-0.5 font-mono truncate",children:a.name})]}),(0,s.jsx)(i.Ct,{variant:{sveltekit:"warning",streamlit:"error",nextjs:"info",other:"gray"}[a.appType]||"gray",children:{sveltekit:"SvelteKit",streamlit:"Streamlit",nextjs:"Next.js",other:"Other"}[t=a.appType]||t})]}),(0,s.jsxs)("div",{className:"space-y-2 mb-4",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between",children:[(0,s.jsx)("span",{className:"text-sm text-gray-600",children:"Status"}),(0,s.jsx)(f,{appId:a.id,pollInterval:3e4})]}),(0,s.jsxs)("div",{className:"flex items-center justify-between",children:[(0,s.jsx)("span",{className:"text-sm text-gray-600",children:"Port"}),(0,s.jsxs)("span",{className:"text-sm font-mono text-gray-900",children:[":",a.targetPort]})]}),(0,s.jsxs)("div",{className:"flex items-center justify-between",children:[(0,s.jsx)("span",{className:"text-sm text-gray-600",children:"Path"}),(0,s.jsxs)("span",{className:"text-sm font-mono text-gray-900 truncate max-w-[150px]",children:["/proxy/",a.pathPrefix,"/"]})]}),a.websocketEnabled&&(0,s.jsxs)("div",{className:"flex items-center justify-between",children:[(0,s.jsx)("span",{className:"text-sm text-gray-600",children:"WebSocket"}),(0,s.jsx)(i.Ct,{variant:"info",children:"Enabled"})]}),!a.enabled&&(0,s.jsx)("div",{className:"mt-2 py-1 px-2 bg-yellow-50 border border-yellow-200 rounded text-xs text-yellow-700",children:"This app is disabled"})]}),c?(0,s.jsxs)("div",{className:"space-y-2",children:[(0,s.jsxs)("p",{className:"text-sm text-gray-600",children:['Delete "',a.displayName,'"?']}),(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)(i.zx,{variant:"danger",size:"sm",onClick:m,disabled:d,loading:d,children:"Delete"}),(0,s.jsx)(i.zx,{variant:"ghost",size:"sm",onClick:()=>o(!1),disabled:d,children:"Cancel"})]})]}):(0,s.jsxs)("div",{className:"flex gap-2 flex-wrap",children:[(0,s.jsx)(i.zx,{variant:"primary",size:"sm",onClick:()=>window.open(p,"_blank"),disabled:!a.enabled,children:"Open"}),(0,s.jsx)(i.zx,{variant:"secondary",size:"sm",onClick:()=>l(a),children:"Settings"}),(0,s.jsx)(i.zx,{variant:"ghost",size:"sm",onClick:()=>o(!0),className:"text-red-600 hover:bg-red-50",children:"Delete"})]})]})}let v={MIN:1024,MAX:65535},N=/^[a-zA-Z0-9-]+$/,w={sveltekit:"SvelteKit",streamlit:"Streamlit",nextjs:"Next.js",other:"Other"},k=["sveltekit","streamlit","nextjs","other"].map(e=>({value:e,label:w[e]}));function C(e){let{isOpen:t,onClose:a,editApp:l,onSave:n}=e,c=!!l,[o,d]=(0,r.useState)(""),[x,m]=(0,r.useState)(""),[p,u]=(0,r.useState)(""),[h,g]=(0,r.useState)(""),[y,b]=(0,r.useState)(""),[f,j]=(0,r.useState)(!1),[w,C]=(0,r.useState)(""),[S,z]=(0,r.useState)(!0),[P,A]=(0,r.useState)({}),[E,L]=(0,r.useState)(!1),[T,D]=(0,r.useState)(null);(0,r.useEffect)(()=>{t&&(l?(d(l.displayName),m(l.name),u(l.pathPrefix),g(l.targetPort),b(l.appType),j(l.websocketEnabled),C(l.description||""),z(l.enabled)):(d(""),m(""),u(""),g(""),b(""),j(!1),C(""),z(!0)),A({}),D(null))},[t,l]);let R=async e=>{e.preventDefault(),D(null);let t=function(e,t){var a,s,r,l;let n={};return((null===(a=e.displayName)||void 0===a?void 0:a.trim())||(n.displayName="Display name is required"),t||((null===(s=e.name)||void 0===s?void 0:s.trim())?N.test(e.name)||(n.name="Only alphanumeric characters and hyphens are allowed"):n.name="Identifier name is required",(null===(r=e.pathPrefix)||void 0===r?void 0:r.trim())?N.test(e.pathPrefix)||(n.pathPrefix="Only alphanumeric characters and hyphens are allowed"):n.pathPrefix="Path prefix is required"),e.targetPort)?"number"!=typeof e.targetPort||Number.isInteger(l=e.targetPort)&&l>=v.MIN&&l<=v.MAX||(n.targetPort="Port must be between ".concat(v.MIN," and ").concat(v.MAX)):n.targetPort="Port number is required",t||e.appType||(n.appType="App type is required"),n}({displayName:o,name:x,pathPrefix:p,targetPort:h,appType:y},c);if(Object.keys(t).length>0){A(t);return}A({}),L(!0);try{if(c&&l){let e=await fetch("/api/external-apps/".concat(l.id),{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({displayName:o,description:w||void 0,targetPort:h||void 0,websocketEnabled:f,enabled:S})});if(!e.ok){let t=await e.json();throw Error(t.error||"Failed to update app")}}else{let e=await fetch("/api/external-apps",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({displayName:o,name:x,pathPrefix:p,targetPort:h,appType:y,websocketEnabled:f,description:w||void 0})});if(!e.ok){let t=await e.json();throw Error(t.error||"Failed to create app")}}n(),a()}catch(e){D(e instanceof Error?e.message:"An error occurred")}finally{L(!1)}};return(0,s.jsx)(i.u_,{isOpen:t,onClose:a,title:c?"Edit External App":"Add External App",size:"md",children:(0,s.jsxs)("form",{onSubmit:R,className:"space-y-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsxs)("label",{htmlFor:"displayName",className:"block text-sm font-medium text-gray-700 mb-1",children:["Display Name ",(0,s.jsx)("span",{className:"text-red-500",children:"*"})]}),(0,s.jsx)("input",{id:"displayName",type:"text",value:o,onChange:e=>d(e.target.value),className:"input w-full ".concat(P.displayName?"border-red-500":""),placeholder:"My App",disabled:E}),P.displayName&&(0,s.jsx)("p",{className:"mt-1 text-xs text-red-500",children:P.displayName})]}),!c&&(0,s.jsxs)("div",{children:[(0,s.jsxs)("label",{htmlFor:"name",className:"block text-sm font-medium text-gray-700 mb-1",children:["Identifier Name ",(0,s.jsx)("span",{className:"text-red-500",children:"*"})]}),(0,s.jsx)("input",{id:"name",type:"text",value:x,onChange:e=>m(e.target.value),className:"input w-full font-mono ".concat(P.name?"border-red-500":""),placeholder:"my-app",disabled:E}),(0,s.jsx)("p",{className:"mt-1 text-xs text-gray-500",children:"Alphanumeric and hyphens only. Cannot be changed later."}),P.name&&(0,s.jsx)("p",{className:"mt-1 text-xs text-red-500",children:P.name})]}),!c&&(0,s.jsxs)("div",{children:[(0,s.jsxs)("label",{htmlFor:"pathPrefix",className:"block text-sm font-medium text-gray-700 mb-1",children:["Path Prefix ",(0,s.jsx)("span",{className:"text-red-500",children:"*"})]}),(0,s.jsxs)("div",{className:"flex items-center",children:[(0,s.jsx)("span",{className:"text-sm text-gray-500 mr-1",children:"/proxy/"}),(0,s.jsx)("input",{id:"pathPrefix",type:"text",value:p,onChange:e=>u(e.target.value),className:"input flex-1 font-mono ".concat(P.pathPrefix?"border-red-500":""),placeholder:"app-name",disabled:E}),(0,s.jsx)("span",{className:"text-sm text-gray-500 ml-1",children:"/"})]}),(0,s.jsx)("p",{className:"mt-1 text-xs text-gray-500",children:"URL path for accessing this app. Cannot be changed later."}),P.pathPrefix&&(0,s.jsx)("p",{className:"mt-1 text-xs text-red-500",children:P.pathPrefix})]}),(0,s.jsxs)("div",{children:[(0,s.jsxs)("label",{htmlFor:"targetPort",className:"block text-sm font-medium text-gray-700 mb-1",children:["Port Number ",(0,s.jsx)("span",{className:"text-red-500",children:"*"})]}),(0,s.jsx)("input",{id:"targetPort",type:"number",value:h,onChange:e=>g(e.target.value?parseInt(e.target.value,10):""),className:"input w-full font-mono ".concat(P.targetPort?"border-red-500":""),placeholder:"5173",min:v.MIN,max:v.MAX,disabled:E}),(0,s.jsxs)("p",{className:"mt-1 text-xs text-gray-500",children:["Target port (",v.MIN,"-",v.MAX,")"]}),P.targetPort&&(0,s.jsx)("p",{className:"mt-1 text-xs text-red-500",children:P.targetPort})]}),!c&&(0,s.jsxs)("div",{children:[(0,s.jsxs)("label",{htmlFor:"appType",className:"block text-sm font-medium text-gray-700 mb-1",children:["App Type ",(0,s.jsx)("span",{className:"text-red-500",children:"*"})]}),(0,s.jsxs)("select",{id:"appType",value:y,onChange:e=>b(e.target.value),className:"input w-full ".concat(P.appType?"border-red-500":""),disabled:E,children:[(0,s.jsx)("option",{value:"",children:"Select app type..."}),k.map(e=>(0,s.jsx)("option",{value:e.value,children:e.label},e.value))]}),P.appType&&(0,s.jsx)("p",{className:"mt-1 text-xs text-red-500",children:P.appType})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{htmlFor:"description",className:"block text-sm font-medium text-gray-700 mb-1",children:"Description"}),(0,s.jsx)("textarea",{id:"description",value:w,onChange:e=>C(e.target.value),className:"input w-full",placeholder:"Optional description...",rows:2,disabled:E})]}),(0,s.jsxs)("div",{className:"flex items-center",children:[(0,s.jsx)("input",{id:"websocketEnabled",type:"checkbox",checked:f,onChange:e=>j(e.target.checked),className:"h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500",disabled:E}),(0,s.jsx)("label",{htmlFor:"websocketEnabled",className:"ml-2 text-sm text-gray-700",children:"Enable WebSocket support"})]}),c&&(0,s.jsxs)("div",{className:"flex items-center",children:[(0,s.jsx)("input",{id:"enabled",type:"checkbox",checked:S,onChange:e=>z(e.target.checked),className:"h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500",disabled:E}),(0,s.jsx)("label",{htmlFor:"enabled",className:"ml-2 text-sm text-gray-700",children:"App is enabled"})]}),T&&(0,s.jsx)("div",{className:"p-3 bg-red-50 border border-red-200 rounded text-sm text-red-700",children:T}),(0,s.jsxs)("div",{className:"flex justify-end gap-2 pt-4 border-t border-gray-200",children:[(0,s.jsx)(i.zx,{type:"button",variant:"ghost",onClick:a,disabled:E,children:"Cancel"}),(0,s.jsx)(i.zx,{type:"submit",variant:"primary",loading:E,children:c?"Save Changes":"Add App"})]})]})})}function S(){let[e,t]=(0,r.useState)([]),[a,l]=(0,r.useState)(!0),[n,c]=(0,r.useState)(null),[o,d]=(0,r.useState)(!1),[x,m]=(0,r.useState)(null),p=(0,r.useCallback)(async()=>{try{c(null);let e=await fetch("/api/external-apps");if(!e.ok)throw Error("Failed to fetch external apps");let a=await e.json();t(a.apps||[])}catch(e){c(e instanceof Error?e.message:"An error occurred")}finally{l(!1)}},[]);(0,r.useEffect)(()=>{p();let e=setInterval(p,6e4);return()=>clearInterval(e)},[p]);let u=(0,r.useCallback)(e=>{m(e),d(!0)},[]),h=(0,r.useCallback)(()=>{m(null),d(!0)},[]),g=(0,r.useCallback)(async e=>{try{let t=await fetch("/api/external-apps/".concat(e),{method:"DELETE"});if(!t.ok){let e=await t.json();throw Error(e.error||"Failed to delete app")}p()}catch(e){console.error("Failed to delete app:",e)}},[p]),y=(0,r.useCallback)(()=>{p()},[p]),b=(0,r.useCallback)(()=>{d(!1),m(null)},[]);return(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between",children:[(0,s.jsx)("h2",{className:"text-xl font-semibold text-gray-900",children:"External Apps"}),(0,s.jsx)(i.zx,{variant:"primary",size:"sm",onClick:h,children:"+ Add App"})]}),a?(0,s.jsx)(i.Zb,{padding:"lg",children:(0,s.jsxs)("div",{className:"flex items-center justify-center py-8",children:[(0,s.jsx)("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"}),(0,s.jsx)("span",{className:"ml-3 text-gray-600",children:"Loading apps..."})]})}):n?(0,s.jsx)(i.Zb,{padding:"lg",children:(0,s.jsxs)("div",{className:"text-center py-8",children:[(0,s.jsx)("p",{className:"text-red-600 mb-4",children:"Failed to load external apps"}),(0,s.jsx)(i.zx,{variant:"secondary",size:"sm",onClick:p,children:"Retry"})]})}):0===e.length?(0,s.jsx)(i.Zb,{padding:"lg",children:(0,s.jsxs)("div",{className:"text-center py-8",children:[(0,s.jsx)("p",{className:"text-gray-500 mb-4",children:"No external apps registered yet."}),(0,s.jsx)("p",{className:"text-sm text-gray-400 mb-4",children:"Add an external app to proxy requests to other frontend applications."}),(0,s.jsx)(i.zx,{variant:"primary",size:"sm",onClick:h,children:"Add Your First App"})]})}):(0,s.jsx)("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4",children:e.map(e=>(0,s.jsx)(j,{app:e,onEdit:u,onDelete:g},e.id))}),(0,s.jsx)(C,{isOpen:o,onClose:b,editApp:x,onSave:y})]})}function z(){let[e,t]=(0,r.useState)(0),a=(0,r.useCallback)(()=>{t(e=>e+1)},[]);return(0,s.jsx)(l.Vw,{children:(0,s.jsxs)("div",{className:"container-custom py-8 overflow-auto h-full",children:[(0,s.jsxs)("div",{className:"mb-8",children:[(0,s.jsx)("h1",{className:"mb-2",children:"CommandMate"}),(0,s.jsx)("p",{className:"text-lg text-gray-600",children:"Git worktree management with Claude CLI and tmux sessions"})]}),(0,s.jsx)("div",{className:"mb-8",children:(0,s.jsx)(b,{onRepositoryAdded:a})}),(0,s.jsx)(g,{},e),(0,s.jsx)("div",{className:"mt-8",children:(0,s.jsx)(S,{})})]})})}}},function(e){e.O(0,[9234,216,8216,2330,816,4733,2971,2117,1744],function(){return e(e.s=14564)}),_N_E=e.O()}]);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|