clairo 1.0.8 → 1.0.9
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/dist/cli.js +120 -7
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -573,6 +573,26 @@ function extractTicketKey(text) {
|
|
|
573
573
|
}
|
|
574
574
|
|
|
575
575
|
// src/lib/jira/config.ts
|
|
576
|
+
function getExistingJiraConfigs(excludeRepoPath) {
|
|
577
|
+
const config = loadConfig();
|
|
578
|
+
const repos = config.repositories ?? {};
|
|
579
|
+
const configs = [];
|
|
580
|
+
const seen = /* @__PURE__ */ new Set();
|
|
581
|
+
for (const [repoPath, repoConfig] of Object.entries(repos)) {
|
|
582
|
+
if (repoPath === excludeRepoPath) continue;
|
|
583
|
+
if (!repoConfig.jiraSiteUrl || !repoConfig.jiraEmail || !repoConfig.jiraApiToken) continue;
|
|
584
|
+
const key = `${repoConfig.jiraSiteUrl}|${repoConfig.jiraEmail}`;
|
|
585
|
+
if (seen.has(key)) continue;
|
|
586
|
+
seen.add(key);
|
|
587
|
+
configs.push({
|
|
588
|
+
repoPath,
|
|
589
|
+
siteUrl: repoConfig.jiraSiteUrl,
|
|
590
|
+
email: repoConfig.jiraEmail,
|
|
591
|
+
apiToken: repoConfig.jiraApiToken
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
return configs;
|
|
595
|
+
}
|
|
576
596
|
function isJiraConfigured(repoPath) {
|
|
577
597
|
const config = getRepoConfig(repoPath);
|
|
578
598
|
return !!(config.jiraSiteUrl && config.jiraEmail && config.jiraApiToken);
|
|
@@ -594,6 +614,13 @@ function getJiraCredentials(repoPath) {
|
|
|
594
614
|
function setJiraCredentials(repoPath, email, apiToken) {
|
|
595
615
|
updateRepoConfig(repoPath, { jiraEmail: email, jiraApiToken: apiToken });
|
|
596
616
|
}
|
|
617
|
+
function clearJiraConfig(repoPath) {
|
|
618
|
+
updateRepoConfig(repoPath, {
|
|
619
|
+
jiraSiteUrl: void 0,
|
|
620
|
+
jiraEmail: void 0,
|
|
621
|
+
jiraApiToken: void 0
|
|
622
|
+
});
|
|
623
|
+
}
|
|
597
624
|
function getLinkedTickets(repoPath, branch) {
|
|
598
625
|
var _a;
|
|
599
626
|
const config = getRepoConfig(repoPath);
|
|
@@ -2035,6 +2062,7 @@ function ChangeStatusModal({ repoPath, ticketKey, currentStatus, onComplete, onC
|
|
|
2035
2062
|
// src/components/jira/ConfigureJiraSiteModal.tsx
|
|
2036
2063
|
import { useState as useState15 } from "react";
|
|
2037
2064
|
import { Box as Box9, Text as Text9, useInput as useInput8 } from "ink";
|
|
2065
|
+
import { ScrollView as ScrollView4 } from "ink-scroll-view";
|
|
2038
2066
|
|
|
2039
2067
|
// src/lib/editor.ts
|
|
2040
2068
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
@@ -2066,27 +2094,57 @@ function openInEditor(content, filename) {
|
|
|
2066
2094
|
|
|
2067
2095
|
// src/components/jira/ConfigureJiraSiteModal.tsx
|
|
2068
2096
|
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2097
|
+
var MAX_VISIBLE_ITEMS = 4;
|
|
2069
2098
|
function ConfigureJiraSiteModal({
|
|
2070
2099
|
initialSiteUrl,
|
|
2071
2100
|
initialEmail,
|
|
2101
|
+
existingConfigs = [],
|
|
2072
2102
|
onSubmit,
|
|
2073
2103
|
onCancel,
|
|
2074
2104
|
loading,
|
|
2075
2105
|
error
|
|
2076
2106
|
}) {
|
|
2107
|
+
const hasExisting = existingConfigs.length > 0;
|
|
2108
|
+
const [mode, setMode] = useState15(hasExisting ? "choose" : "manual");
|
|
2109
|
+
const [selectedExisting, setSelectedExisting] = useState15(0);
|
|
2110
|
+
const scrollRef = useScrollToIndex(selectedExisting);
|
|
2077
2111
|
const [siteUrl, setSiteUrl] = useState15(initialSiteUrl ?? "");
|
|
2078
2112
|
const [email, setEmail] = useState15(initialEmail ?? "");
|
|
2079
2113
|
const [apiToken, setApiToken] = useState15("");
|
|
2080
2114
|
const [selectedItem, setSelectedItem] = useState15("siteUrl");
|
|
2081
2115
|
const items = ["siteUrl", "email", "apiToken", "submit"];
|
|
2082
2116
|
const canSubmit = siteUrl.trim() && email.trim() && apiToken.trim();
|
|
2117
|
+
const chooseItems = existingConfigs.length + 1;
|
|
2083
2118
|
useInput8(
|
|
2084
2119
|
(input, key) => {
|
|
2085
2120
|
if (loading) return;
|
|
2086
2121
|
if (key.escape) {
|
|
2122
|
+
if (mode === "manual" && hasExisting) {
|
|
2123
|
+
setMode("choose");
|
|
2124
|
+
return;
|
|
2125
|
+
}
|
|
2087
2126
|
onCancel();
|
|
2088
2127
|
return;
|
|
2089
2128
|
}
|
|
2129
|
+
if (mode === "choose") {
|
|
2130
|
+
if (key.upArrow || input === "k") {
|
|
2131
|
+
setSelectedExisting((prev) => Math.max(0, prev - 1));
|
|
2132
|
+
return;
|
|
2133
|
+
}
|
|
2134
|
+
if (key.downArrow || input === "j") {
|
|
2135
|
+
setSelectedExisting((prev) => Math.min(chooseItems - 1, prev + 1));
|
|
2136
|
+
return;
|
|
2137
|
+
}
|
|
2138
|
+
if (key.return) {
|
|
2139
|
+
if (selectedExisting < existingConfigs.length) {
|
|
2140
|
+
const config = existingConfigs[selectedExisting];
|
|
2141
|
+
onSubmit(config.siteUrl, config.email, config.apiToken);
|
|
2142
|
+
} else {
|
|
2143
|
+
setMode("manual");
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
return;
|
|
2147
|
+
}
|
|
2090
2148
|
if (key.upArrow || input === "k") {
|
|
2091
2149
|
setSelectedItem((prev) => {
|
|
2092
2150
|
const idx = items.indexOf(prev);
|
|
@@ -2137,9 +2195,49 @@ function ConfigureJiraSiteModal({
|
|
|
2137
2195
|
value !== void 0 && /* @__PURE__ */ jsx9(Box9, { marginLeft: 4, children: /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: displayValue || "(empty - press Enter to edit)" }) })
|
|
2138
2196
|
] });
|
|
2139
2197
|
};
|
|
2198
|
+
if (mode === "choose") {
|
|
2199
|
+
const totalItems = existingConfigs.length + 1;
|
|
2200
|
+
const listHeight = Math.min(totalItems * 2, MAX_VISIBLE_ITEMS * 2);
|
|
2201
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, paddingY: 1, children: [
|
|
2202
|
+
/* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: "Configure Jira Site" }),
|
|
2203
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Select an existing configuration or enter new credentials" }),
|
|
2204
|
+
/* @__PURE__ */ jsx9(Box9, { marginTop: 1 }),
|
|
2205
|
+
error && /* @__PURE__ */ jsx9(Box9, { marginBottom: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "red", children: error }) }),
|
|
2206
|
+
/* @__PURE__ */ jsx9(Box9, { height: listHeight, overflow: "hidden", children: /* @__PURE__ */ jsxs9(ScrollView4, { ref: scrollRef, children: [
|
|
2207
|
+
existingConfigs.map((config, idx) => {
|
|
2208
|
+
const isSelected = selectedExisting === idx;
|
|
2209
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
2210
|
+
/* @__PURE__ */ jsxs9(Text9, { color: isSelected ? "yellow" : void 0, bold: isSelected, children: [
|
|
2211
|
+
isSelected ? "> " : " ",
|
|
2212
|
+
config.siteUrl
|
|
2213
|
+
] }),
|
|
2214
|
+
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
2215
|
+
" ",
|
|
2216
|
+
config.email
|
|
2217
|
+
] })
|
|
2218
|
+
] }, config.siteUrl + config.email);
|
|
2219
|
+
}),
|
|
2220
|
+
/* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsxs9(
|
|
2221
|
+
Text9,
|
|
2222
|
+
{
|
|
2223
|
+
color: selectedExisting === existingConfigs.length ? "yellow" : void 0,
|
|
2224
|
+
bold: selectedExisting === existingConfigs.length,
|
|
2225
|
+
children: [
|
|
2226
|
+
selectedExisting === existingConfigs.length ? "> " : " ",
|
|
2227
|
+
"Enter new credentials..."
|
|
2228
|
+
]
|
|
2229
|
+
}
|
|
2230
|
+
) })
|
|
2231
|
+
] }) }),
|
|
2232
|
+
loading && /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "Validating credentials..." }) })
|
|
2233
|
+
] });
|
|
2234
|
+
}
|
|
2140
2235
|
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, paddingY: 1, children: [
|
|
2141
2236
|
/* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: "Configure Jira Site" }),
|
|
2142
|
-
/* @__PURE__ */
|
|
2237
|
+
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
2238
|
+
"Up/Down to select, Enter to edit, Esc to ",
|
|
2239
|
+
hasExisting ? "go back" : "cancel"
|
|
2240
|
+
] }),
|
|
2143
2241
|
/* @__PURE__ */ jsx9(Box9, { marginTop: 1 }),
|
|
2144
2242
|
error && /* @__PURE__ */ jsx9(Box9, { marginBottom: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "red", children: error }) }),
|
|
2145
2243
|
renderItem("siteUrl", "Site URL (e.g., https://company.atlassian.net)", siteUrl),
|
|
@@ -2251,6 +2349,11 @@ function JiraView({ isFocused, onModalChange, onJiraStateChange, onLogUpdated })
|
|
|
2251
2349
|
modal.close();
|
|
2252
2350
|
jira.refreshTickets(repo.repoPath, repo.currentBranch);
|
|
2253
2351
|
};
|
|
2352
|
+
const handleRemoveConfig = () => {
|
|
2353
|
+
if (!repo.repoPath || !repo.currentBranch) return;
|
|
2354
|
+
clearJiraConfig(repo.repoPath);
|
|
2355
|
+
jira.initializeJiraState(repo.repoPath, repo.currentBranch, repo.currentRepoSlug);
|
|
2356
|
+
};
|
|
2254
2357
|
useInput9(
|
|
2255
2358
|
(input, key) => {
|
|
2256
2359
|
if (input === "c" && jira.jiraState === "not_configured") {
|
|
@@ -2261,6 +2364,10 @@ function JiraView({ isFocused, onModalChange, onJiraStateChange, onLogUpdated })
|
|
|
2261
2364
|
modal.open("link");
|
|
2262
2365
|
return;
|
|
2263
2366
|
}
|
|
2367
|
+
if (input === "r" && jira.jiraState !== "not_configured") {
|
|
2368
|
+
handleRemoveConfig();
|
|
2369
|
+
return;
|
|
2370
|
+
}
|
|
2264
2371
|
if (jira.jiraState === "has_tickets") {
|
|
2265
2372
|
if (key.upArrow || input === "k") nav.prev();
|
|
2266
2373
|
if (key.downArrow || input === "j") nav.next();
|
|
@@ -2278,11 +2385,13 @@ function JiraView({ isFocused, onModalChange, onJiraStateChange, onLogUpdated })
|
|
|
2278
2385
|
if (modal.type === "configure") {
|
|
2279
2386
|
const siteUrl = repo.repoPath ? getJiraSiteUrl(repo.repoPath) : void 0;
|
|
2280
2387
|
const creds = repo.repoPath ? getJiraCredentials(repo.repoPath) : { email: null, apiToken: null };
|
|
2388
|
+
const existingConfigs = getExistingJiraConfigs(repo.repoPath ?? void 0);
|
|
2281
2389
|
return /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx11(
|
|
2282
2390
|
ConfigureJiraSiteModal,
|
|
2283
2391
|
{
|
|
2284
2392
|
initialSiteUrl: siteUrl ?? void 0,
|
|
2285
2393
|
initialEmail: creds.email ?? void 0,
|
|
2394
|
+
existingConfigs,
|
|
2286
2395
|
onSubmit: handleConfigureSubmit,
|
|
2287
2396
|
onCancel: () => {
|
|
2288
2397
|
modal.close();
|
|
@@ -2346,7 +2455,7 @@ import { Box as Box14, useInput as useInput12 } from "ink";
|
|
|
2346
2455
|
import { useRef as useRef7, useState as useState16 } from "react";
|
|
2347
2456
|
import { TitledBox as TitledBox5 } from "@mishieck/ink-titled-box";
|
|
2348
2457
|
import { Box as Box12, Text as Text12, useInput as useInput10 } from "ink";
|
|
2349
|
-
import { ScrollView as
|
|
2458
|
+
import { ScrollView as ScrollView5 } from "ink-scroll-view";
|
|
2350
2459
|
import TextInput2 from "ink-text-input";
|
|
2351
2460
|
|
|
2352
2461
|
// src/lib/claude/api.ts
|
|
@@ -2524,7 +2633,7 @@ ${value.trim()}
|
|
|
2524
2633
|
onRefresh();
|
|
2525
2634
|
};
|
|
2526
2635
|
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", flexGrow: 1, children: [
|
|
2527
|
-
/* @__PURE__ */ jsx12(TitledBox5, { borderStyle: "round", titles: [displayTitle], borderColor, flexGrow: 1, children: /* @__PURE__ */ jsx12(Box12, { flexDirection: "column", flexGrow: 1, children: /* @__PURE__ */ jsx12(
|
|
2636
|
+
/* @__PURE__ */ jsx12(TitledBox5, { borderStyle: "round", titles: [displayTitle], borderColor, flexGrow: 1, children: /* @__PURE__ */ jsx12(Box12, { flexDirection: "column", flexGrow: 1, children: /* @__PURE__ */ jsx12(ScrollView5, { ref: scrollRef, children: /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", paddingX: 1, children: [
|
|
2528
2637
|
!date && /* @__PURE__ */ jsx12(Text12, { dimColor: true, children: "Select a log file to view" }),
|
|
2529
2638
|
date && content === null && /* @__PURE__ */ jsx12(Text12, { dimColor: true, children: "Log file not found" }),
|
|
2530
2639
|
date && content !== null && content.trim() === "" && /* @__PURE__ */ jsx12(Text12, { dimColor: true, children: "Empty log file" }),
|
|
@@ -2560,7 +2669,7 @@ ${value.trim()}
|
|
|
2560
2669
|
// src/components/logs/LogsHistoryBox.tsx
|
|
2561
2670
|
import { TitledBox as TitledBox6 } from "@mishieck/ink-titled-box";
|
|
2562
2671
|
import { Box as Box13, Text as Text13, useInput as useInput11 } from "ink";
|
|
2563
|
-
import { ScrollView as
|
|
2672
|
+
import { ScrollView as ScrollView6 } from "ink-scroll-view";
|
|
2564
2673
|
import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2565
2674
|
function LogsHistoryBox({
|
|
2566
2675
|
logFiles,
|
|
@@ -2593,7 +2702,7 @@ function LogsHistoryBox({
|
|
|
2593
2702
|
);
|
|
2594
2703
|
return /* @__PURE__ */ jsx13(TitledBox6, { borderStyle: "round", titles: [title], borderColor, height: 5, children: /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingX: 1, flexGrow: 1, overflow: "hidden", children: [
|
|
2595
2704
|
logFiles.length === 0 && /* @__PURE__ */ jsx13(Text13, { dimColor: true, children: "No logs yet" }),
|
|
2596
|
-
logFiles.length > 0 && /* @__PURE__ */ jsx13(
|
|
2705
|
+
logFiles.length > 0 && /* @__PURE__ */ jsx13(ScrollView6, { ref: scrollRef, children: logFiles.map((file, idx) => {
|
|
2597
2706
|
const isHighlighted = idx === highlightedIndex;
|
|
2598
2707
|
const isSelected = file.date === selectedDate;
|
|
2599
2708
|
const cursor = isHighlighted ? ">" : " ";
|
|
@@ -2695,13 +2804,17 @@ var GITHUB_KEYBINDINGS = {
|
|
|
2695
2804
|
// src/constants/jira.ts
|
|
2696
2805
|
var JIRA_KEYBINDINGS = {
|
|
2697
2806
|
not_configured: [{ key: "c", label: "Configure Jira" }],
|
|
2698
|
-
no_tickets: [
|
|
2807
|
+
no_tickets: [
|
|
2808
|
+
{ key: "l", label: "Link Ticket" },
|
|
2809
|
+
{ key: "r", label: "Remove Config", color: "red" }
|
|
2810
|
+
],
|
|
2699
2811
|
has_tickets: [
|
|
2700
2812
|
{ key: "l", label: "Link" },
|
|
2701
2813
|
{ key: "s", label: "Status" },
|
|
2702
2814
|
{ key: "d", label: "Unlink", color: "red" },
|
|
2703
2815
|
{ key: "o", label: "Open", color: "green" },
|
|
2704
|
-
{ key: "y", label: "Copy Link" }
|
|
2816
|
+
{ key: "y", label: "Copy Link" },
|
|
2817
|
+
{ key: "r", label: "Remove Config", color: "red" }
|
|
2705
2818
|
]
|
|
2706
2819
|
};
|
|
2707
2820
|
|