@polterware/polter 0.3.1 → 0.4.1
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/api.js +15 -2
- package/dist/chunk-VYHW3UNY.js +108 -0
- package/dist/{chunk-7MIUDIAI.js → chunk-ZHVOYB5M.js} +284 -60
- package/dist/index.js +956 -515
- package/dist/mcp.js +250 -14
- package/package.json +1 -1
- package/dist/chunk-AGVTFYXU.js +0 -0
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
allCommands,
|
|
4
4
|
applyActions,
|
|
5
5
|
commandExists,
|
|
6
|
+
createIpcServer,
|
|
6
7
|
detectPkgManager,
|
|
7
8
|
executePipeline,
|
|
8
9
|
features,
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
findNearestPackageRoot,
|
|
11
12
|
findPipelineByName,
|
|
12
13
|
findPolterYaml,
|
|
14
|
+
generateProcessId,
|
|
13
15
|
getAllPipelines,
|
|
14
16
|
getCommandById,
|
|
15
17
|
getCommandValue,
|
|
@@ -20,6 +22,8 @@ import {
|
|
|
20
22
|
getOrCreateProjectConfig,
|
|
21
23
|
getProcessOutput,
|
|
22
24
|
getProjectConfigPath,
|
|
25
|
+
getSocketPath,
|
|
26
|
+
getToolDisplayName,
|
|
23
27
|
getToolInfo,
|
|
24
28
|
getToolLinkInfo,
|
|
25
29
|
installMcpServer,
|
|
@@ -36,16 +40,18 @@ import {
|
|
|
36
40
|
runInteractiveCommand,
|
|
37
41
|
runSupabaseCommand,
|
|
38
42
|
savePipeline,
|
|
43
|
+
startProcess,
|
|
39
44
|
stopProcess,
|
|
45
|
+
translateCommand,
|
|
40
46
|
writeProjectConfig
|
|
41
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-ZHVOYB5M.js";
|
|
42
48
|
|
|
43
49
|
// src/index.tsx
|
|
44
|
-
import
|
|
50
|
+
import React28 from "react";
|
|
45
51
|
import { render } from "ink";
|
|
46
52
|
|
|
47
53
|
// src/app.tsx
|
|
48
|
-
import { Box as
|
|
54
|
+
import { Box as Box29, Text as Text33, useApp } from "ink";
|
|
49
55
|
|
|
50
56
|
// src/hooks/useNavigation.ts
|
|
51
57
|
import { useState, useCallback } from "react";
|
|
@@ -110,7 +116,7 @@ function useTerminalHeight() {
|
|
|
110
116
|
}
|
|
111
117
|
|
|
112
118
|
// src/components/GhostBanner.tsx
|
|
113
|
-
import React from "react";
|
|
119
|
+
import React, { useState as useState3, useEffect as useEffect2 } from "react";
|
|
114
120
|
import { Box, Text as Text2 } from "ink";
|
|
115
121
|
|
|
116
122
|
// src/theme.ts
|
|
@@ -197,6 +203,12 @@ var toolColors = {
|
|
|
197
203
|
git: "#F05032",
|
|
198
204
|
pkg: "#CB3837"
|
|
199
205
|
};
|
|
206
|
+
var pkgManagerColors = {
|
|
207
|
+
npm: "#CB3837",
|
|
208
|
+
pnpm: "#F69220",
|
|
209
|
+
yarn: "#2C8EBB",
|
|
210
|
+
bun: "#FBF0DF"
|
|
211
|
+
};
|
|
200
212
|
var toolLabels = {
|
|
201
213
|
supabase: "supabase",
|
|
202
214
|
gh: "github",
|
|
@@ -204,8 +216,21 @@ var toolLabels = {
|
|
|
204
216
|
git: "git",
|
|
205
217
|
pkg: "pkg"
|
|
206
218
|
};
|
|
219
|
+
function resolveToolColor(tool) {
|
|
220
|
+
if (tool === "pkg") {
|
|
221
|
+
const name = getToolDisplayName(tool);
|
|
222
|
+
return pkgManagerColors[name] ?? toolColors.pkg;
|
|
223
|
+
}
|
|
224
|
+
return toolColors[tool];
|
|
225
|
+
}
|
|
226
|
+
function resolveToolLabel(tool) {
|
|
227
|
+
if (tool === "pkg") {
|
|
228
|
+
return getToolDisplayName(tool);
|
|
229
|
+
}
|
|
230
|
+
return toolLabels[tool];
|
|
231
|
+
}
|
|
207
232
|
function ToolBadge({ tool }) {
|
|
208
|
-
return /* @__PURE__ */ jsx(Text, { color:
|
|
233
|
+
return /* @__PURE__ */ jsx(Text, { color: resolveToolColor(tool), dimColor: true, children: resolveToolLabel(tool) });
|
|
209
234
|
}
|
|
210
235
|
|
|
211
236
|
// src/components/GhostBanner.tsx
|
|
@@ -219,6 +244,23 @@ var McpBadge = React.memo(function McpBadge2() {
|
|
|
219
244
|
registered ? "ok" : "x"
|
|
220
245
|
] }) });
|
|
221
246
|
});
|
|
247
|
+
function ProcessBadge() {
|
|
248
|
+
const [count, setCount] = useState3(() => {
|
|
249
|
+
return listProcesses().filter((p) => p.status === "running").length;
|
|
250
|
+
});
|
|
251
|
+
useEffect2(() => {
|
|
252
|
+
const id = setInterval(() => {
|
|
253
|
+
const c = listProcesses().filter((p) => p.status === "running").length;
|
|
254
|
+
setCount(c);
|
|
255
|
+
}, 2e3);
|
|
256
|
+
return () => clearInterval(id);
|
|
257
|
+
}, []);
|
|
258
|
+
const color = count > 0 ? "#3ECF8E" : inkColors.accent;
|
|
259
|
+
return /* @__PURE__ */ jsx2(Box, { borderStyle: "round", borderColor: color, borderDimColor: count === 0, children: /* @__PURE__ */ jsxs(Text2, { color, dimColor: count === 0, children: [
|
|
260
|
+
"runs:",
|
|
261
|
+
count
|
|
262
|
+
] }) });
|
|
263
|
+
}
|
|
222
264
|
var ToolStatusBadges = React.memo(function ToolStatusBadges2() {
|
|
223
265
|
const tools = ["supabase", "gh", "vercel"].map((id) => getToolLinkInfo(id));
|
|
224
266
|
return /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
|
|
@@ -237,13 +279,16 @@ function GhostBanner({ width = 80, compact = false }) {
|
|
|
237
279
|
if (compact) {
|
|
238
280
|
if (width < 60) {
|
|
239
281
|
return /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, flexDirection: "column", alignItems: "flex-start", children: [
|
|
240
|
-
/* @__PURE__ */ jsxs(Box, {
|
|
241
|
-
/* @__PURE__ */
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
282
|
+
/* @__PURE__ */ jsxs(Box, { gap: 1, children: [
|
|
283
|
+
/* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, gap: 2, children: [
|
|
284
|
+
/* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, bold: true, children: "POLTER" }),
|
|
285
|
+
/* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
|
|
286
|
+
"v",
|
|
287
|
+
VERSION
|
|
288
|
+
] }),
|
|
289
|
+
/* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "alpha" })
|
|
245
290
|
] }),
|
|
246
|
-
/* @__PURE__ */ jsx2(
|
|
291
|
+
/* @__PURE__ */ jsx2(ProcessBadge, {})
|
|
247
292
|
] }),
|
|
248
293
|
/* @__PURE__ */ jsx2(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, children: /* @__PURE__ */ jsx2(ToolStatusBadges, {}) })
|
|
249
294
|
] });
|
|
@@ -251,13 +296,16 @@ function GhostBanner({ width = 80, compact = false }) {
|
|
|
251
296
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", borderStyle: "round", borderColor: inkColors.accent, gap: 1, alignItems: "flex-start", children: [
|
|
252
297
|
/* @__PURE__ */ jsx2(Box, { flexDirection: "column", children: ghost.art.map((line, i) => /* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, children: line }, i)) }),
|
|
253
298
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", alignItems: "flex-start", children: [
|
|
254
|
-
/* @__PURE__ */ jsxs(Box, {
|
|
255
|
-
/* @__PURE__ */
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
299
|
+
/* @__PURE__ */ jsxs(Box, { gap: 1, children: [
|
|
300
|
+
/* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, gap: 2, children: [
|
|
301
|
+
/* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, bold: true, children: "POLTER" }),
|
|
302
|
+
/* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
|
|
303
|
+
"v",
|
|
304
|
+
VERSION
|
|
305
|
+
] }),
|
|
306
|
+
/* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "alpha" })
|
|
259
307
|
] }),
|
|
260
|
-
/* @__PURE__ */ jsx2(
|
|
308
|
+
/* @__PURE__ */ jsx2(ProcessBadge, {})
|
|
261
309
|
] }),
|
|
262
310
|
/* @__PURE__ */ jsx2(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, children: /* @__PURE__ */ jsx2(ToolStatusBadges, {}) })
|
|
263
311
|
] })
|
|
@@ -265,13 +313,16 @@ function GhostBanner({ width = 80, compact = false }) {
|
|
|
265
313
|
}
|
|
266
314
|
if (width < 50) {
|
|
267
315
|
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, borderStyle: "round", borderColor: inkColors.accent, flexDirection: "column", alignItems: "flex-start", children: [
|
|
268
|
-
/* @__PURE__ */ jsxs(Box, {
|
|
269
|
-
/* @__PURE__ */
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
316
|
+
/* @__PURE__ */ jsxs(Box, { gap: 1, children: [
|
|
317
|
+
/* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, gap: 2, children: [
|
|
318
|
+
/* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, bold: true, children: "POLTER" }),
|
|
319
|
+
/* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
|
|
320
|
+
"v",
|
|
321
|
+
VERSION
|
|
322
|
+
] }),
|
|
323
|
+
/* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "alpha" })
|
|
273
324
|
] }),
|
|
274
|
-
/* @__PURE__ */ jsx2(
|
|
325
|
+
/* @__PURE__ */ jsx2(ProcessBadge, {})
|
|
275
326
|
] }),
|
|
276
327
|
/* @__PURE__ */ jsx2(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, children: /* @__PURE__ */ jsx2(ToolStatusBadges, {}) })
|
|
277
328
|
] });
|
|
@@ -286,13 +337,16 @@ function GhostBanner({ width = 80, compact = false }) {
|
|
|
286
337
|
borderColor: inkColors.accent,
|
|
287
338
|
marginBottom: 1,
|
|
288
339
|
children: [
|
|
289
|
-
/* @__PURE__ */ jsxs(Box, {
|
|
290
|
-
/* @__PURE__ */
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
340
|
+
/* @__PURE__ */ jsxs(Box, { gap: 1, children: [
|
|
341
|
+
/* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, gap: 2, children: [
|
|
342
|
+
/* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, bold: true, children: "POLTER" }),
|
|
343
|
+
/* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
|
|
344
|
+
"v",
|
|
345
|
+
VERSION
|
|
346
|
+
] }),
|
|
347
|
+
/* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "alpha" })
|
|
294
348
|
] }),
|
|
295
|
-
/* @__PURE__ */ jsx2(
|
|
349
|
+
/* @__PURE__ */ jsx2(ProcessBadge, {})
|
|
296
350
|
] }),
|
|
297
351
|
/* @__PURE__ */ jsx2(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, children: /* @__PURE__ */ jsx2(ToolStatusBadges, {}) }),
|
|
298
352
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Project & infrastructure orchestrator" })
|
|
@@ -303,13 +357,16 @@ function GhostBanner({ width = 80, compact = false }) {
|
|
|
303
357
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "flex-start", borderStyle: "round", borderColor: inkColors.accent, gap: 1, marginBottom: 1, children: [
|
|
304
358
|
/* @__PURE__ */ jsx2(Box, { flexDirection: "column", children: ghost.art.map((line, i) => /* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, children: line }, i)) }),
|
|
305
359
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", alignItems: "flex-start", children: [
|
|
306
|
-
/* @__PURE__ */ jsxs(Box, {
|
|
307
|
-
/* @__PURE__ */
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
360
|
+
/* @__PURE__ */ jsxs(Box, { gap: 1, children: [
|
|
361
|
+
/* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, gap: 2, children: [
|
|
362
|
+
/* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, bold: true, children: "POLTER" }),
|
|
363
|
+
/* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
|
|
364
|
+
"v",
|
|
365
|
+
VERSION
|
|
366
|
+
] }),
|
|
367
|
+
/* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "alpha" })
|
|
311
368
|
] }),
|
|
312
|
-
/* @__PURE__ */ jsx2(
|
|
369
|
+
/* @__PURE__ */ jsx2(ProcessBadge, {})
|
|
313
370
|
] }),
|
|
314
371
|
/* @__PURE__ */ jsx2(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, children: /* @__PURE__ */ jsx2(ToolStatusBadges, {}) }),
|
|
315
372
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " Project & infrastructure orchestrator" })
|
|
@@ -318,7 +375,7 @@ function GhostBanner({ width = 80, compact = false }) {
|
|
|
318
375
|
}
|
|
319
376
|
|
|
320
377
|
// src/screens/Home.tsx
|
|
321
|
-
import { useEffect as
|
|
378
|
+
import { useEffect as useEffect4, useMemo as useMemo2, useState as useState5 } from "react";
|
|
322
379
|
import { Box as Box5, Text as Text6, useInput as useInput2 } from "ink";
|
|
323
380
|
|
|
324
381
|
// src/components/TabBar.tsx
|
|
@@ -347,7 +404,7 @@ function TabBar({ tabs, activeIndex, width = 80 }) {
|
|
|
347
404
|
}
|
|
348
405
|
|
|
349
406
|
// src/components/SelectList.tsx
|
|
350
|
-
import { useEffect as
|
|
407
|
+
import { useEffect as useEffect3, useMemo, useState as useState4 } from "react";
|
|
351
408
|
import { Box as Box3, Text as Text4, useInput } from "ink";
|
|
352
409
|
|
|
353
410
|
// src/components/selectListSections.ts
|
|
@@ -454,8 +511,8 @@ function SelectList({
|
|
|
454
511
|
}, []),
|
|
455
512
|
[items]
|
|
456
513
|
);
|
|
457
|
-
const [selectedSelectableIndex, setSelectedSelectableIndex] =
|
|
458
|
-
|
|
514
|
+
const [selectedSelectableIndex, setSelectedSelectableIndex] = useState4(0);
|
|
515
|
+
useEffect3(() => {
|
|
459
516
|
if (selectableIndexes.length === 0) {
|
|
460
517
|
setSelectedSelectableIndex(0);
|
|
461
518
|
return;
|
|
@@ -707,13 +764,13 @@ function buildPinnedOnlyItems(pinnedCommands, pinnedRuns) {
|
|
|
707
764
|
if (pinnedCommands.length > 0) {
|
|
708
765
|
for (const command of pinnedCommands) {
|
|
709
766
|
const cmdDef = findCommandByValue(command);
|
|
710
|
-
const
|
|
767
|
+
const toolDisplay = cmdDef ? getToolDisplayName(cmdDef.tool) : "supabase";
|
|
711
768
|
const labelHint = cmdDef?.hint;
|
|
712
769
|
items.push({
|
|
713
770
|
id: `command:${command}`,
|
|
714
771
|
value: command,
|
|
715
|
-
label: cmdDef ? `${
|
|
716
|
-
hint: [
|
|
772
|
+
label: cmdDef ? `${toolDisplay} ${command}` : command,
|
|
773
|
+
hint: [toolDisplay, labelHint].filter(Boolean).join(" \xB7 "),
|
|
717
774
|
icon: "\u{1F4CC}",
|
|
718
775
|
kind: "command",
|
|
719
776
|
rightActionable: true,
|
|
@@ -725,12 +782,12 @@ function buildPinnedOnlyItems(pinnedCommands, pinnedRuns) {
|
|
|
725
782
|
for (const runCommand2 of pinnedRuns) {
|
|
726
783
|
const baseCommand = runCommand2.split(" ").filter(Boolean)[0] ?? "";
|
|
727
784
|
const cmdDef = findCommandByValue(baseCommand);
|
|
728
|
-
const
|
|
785
|
+
const toolDisplay = cmdDef ? getToolDisplayName(cmdDef.tool) : "supabase";
|
|
729
786
|
items.push({
|
|
730
787
|
id: `run:${runCommand2}`,
|
|
731
788
|
value: runCommand2,
|
|
732
|
-
label: cmdDef ? `${
|
|
733
|
-
hint:
|
|
789
|
+
label: cmdDef ? `${toolDisplay} ${runCommand2}` : runCommand2,
|
|
790
|
+
hint: toolDisplay,
|
|
734
791
|
icon: "\u25B6",
|
|
735
792
|
kind: "run",
|
|
736
793
|
rightActionable: true,
|
|
@@ -767,8 +824,8 @@ function buildHomeItems({
|
|
|
767
824
|
selectable: false
|
|
768
825
|
});
|
|
769
826
|
}
|
|
770
|
-
const toolOrder = { supabase: 0, vercel: 1, gh: 2, git: 3 };
|
|
771
|
-
const toolIcons = { supabase: "\u{1F7E2}", vercel: "\u26AA", gh: "\u{1F535}", git: "\u{1F7E0}" };
|
|
827
|
+
const toolOrder = { supabase: 0, vercel: 1, gh: 2, git: 3, pkg: 4 };
|
|
828
|
+
const toolIcons = { supabase: "\u{1F7E2}", vercel: "\u26AA", gh: "\u{1F535}", git: "\u{1F7E0}", pkg: "\u{1F4E6}" };
|
|
772
829
|
const grouped = /* @__PURE__ */ new Map();
|
|
773
830
|
for (const cmd of activeFeature.commands) {
|
|
774
831
|
const existing = grouped.get(cmd.tool) ?? [];
|
|
@@ -784,7 +841,7 @@ function buildHomeItems({
|
|
|
784
841
|
items.push({
|
|
785
842
|
id: `tool-header-${tool}`,
|
|
786
843
|
value: `__tool_header_${tool}__`,
|
|
787
|
-
label: `${icon} ${tool}`,
|
|
844
|
+
label: `${icon} ${getToolDisplayName(tool)}`,
|
|
788
845
|
kind: "header",
|
|
789
846
|
selectable: false
|
|
790
847
|
});
|
|
@@ -883,16 +940,16 @@ function Home({
|
|
|
883
940
|
height = 24
|
|
884
941
|
}) {
|
|
885
942
|
const allFeatures = useMemo2(() => getFeatures(), []);
|
|
886
|
-
const [activeTabIndex, setActiveTabIndex] =
|
|
887
|
-
const [pinnedCommands, setPinnedCommands2] =
|
|
943
|
+
const [activeTabIndex, setActiveTabIndex] = useState5(0);
|
|
944
|
+
const [pinnedCommands, setPinnedCommands2] = useState5(
|
|
888
945
|
() => getPinnedCommands()
|
|
889
946
|
);
|
|
890
|
-
const [pinnedRuns, setPinnedRuns2] =
|
|
947
|
+
const [pinnedRuns, setPinnedRuns2] = useState5(
|
|
891
948
|
() => getPinnedRuns()
|
|
892
949
|
);
|
|
893
|
-
const [pinFeedback, setPinFeedback] =
|
|
950
|
+
const [pinFeedback, setPinFeedback] = useState5();
|
|
894
951
|
const activeFeature = allFeatures[activeTabIndex];
|
|
895
|
-
|
|
952
|
+
useEffect4(() => {
|
|
896
953
|
if (!pinFeedback) return;
|
|
897
954
|
const timeout = setTimeout(() => setPinFeedback(void 0), 1400);
|
|
898
955
|
return () => clearTimeout(timeout);
|
|
@@ -1031,11 +1088,11 @@ function Home({
|
|
|
1031
1088
|
}
|
|
1032
1089
|
|
|
1033
1090
|
// src/screens/CommandArgs.tsx
|
|
1034
|
-
import { useEffect as
|
|
1091
|
+
import { useEffect as useEffect5, useMemo as useMemo3, useState as useState7 } from "react";
|
|
1035
1092
|
import { Box as Box7, Text as Text8, useInput as useInput4 } from "ink";
|
|
1036
1093
|
|
|
1037
1094
|
// src/components/TextPrompt.tsx
|
|
1038
|
-
import { useState as
|
|
1095
|
+
import { useState as useState6 } from "react";
|
|
1039
1096
|
import { Box as Box6, Text as Text7, useInput as useInput3 } from "ink";
|
|
1040
1097
|
import TextInputComponent from "ink-text-input";
|
|
1041
1098
|
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
@@ -1050,8 +1107,8 @@ function TextPrompt({
|
|
|
1050
1107
|
boxed = false,
|
|
1051
1108
|
focused = true
|
|
1052
1109
|
}) {
|
|
1053
|
-
const [value, setValue] =
|
|
1054
|
-
const [error, setError] =
|
|
1110
|
+
const [value, setValue] = useState6("");
|
|
1111
|
+
const [error, setError] = useState6();
|
|
1055
1112
|
useInput3((_input, key) => {
|
|
1056
1113
|
if (key.escape && onCancel) {
|
|
1057
1114
|
onCancel();
|
|
@@ -1190,15 +1247,15 @@ function CommandArgs({
|
|
|
1190
1247
|
() => cmdDef?.suggestedArgs ?? [],
|
|
1191
1248
|
[cmdDef]
|
|
1192
1249
|
);
|
|
1193
|
-
const [pinnedRuns, setPinnedRuns2] =
|
|
1194
|
-
const [pinFeedback, setPinFeedback] =
|
|
1195
|
-
const [phase, setPhase] =
|
|
1250
|
+
const [pinnedRuns, setPinnedRuns2] = useState7(() => getPinnedRuns());
|
|
1251
|
+
const [pinFeedback, setPinFeedback] = useState7();
|
|
1252
|
+
const [phase, setPhase] = useState7(
|
|
1196
1253
|
suggestions.length > 0 ? "select" : "custom"
|
|
1197
1254
|
);
|
|
1198
|
-
|
|
1255
|
+
useEffect5(() => {
|
|
1199
1256
|
setPhase(suggestions.length > 0 ? "select" : "custom");
|
|
1200
1257
|
}, [command, suggestions.length]);
|
|
1201
|
-
|
|
1258
|
+
useEffect5(() => {
|
|
1202
1259
|
if (!pinFeedback) return;
|
|
1203
1260
|
const timeout = setTimeout(() => setPinFeedback(void 0), 1400);
|
|
1204
1261
|
return () => clearTimeout(timeout);
|
|
@@ -1340,7 +1397,7 @@ function CommandArgs({
|
|
|
1340
1397
|
}
|
|
1341
1398
|
|
|
1342
1399
|
// src/screens/CustomCommand.tsx
|
|
1343
|
-
import { useState as
|
|
1400
|
+
import { useState as useState8 } from "react";
|
|
1344
1401
|
import { Box as Box8, Text as Text9 } from "ink";
|
|
1345
1402
|
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1346
1403
|
function CustomCommand({
|
|
@@ -1351,8 +1408,8 @@ function CustomCommand({
|
|
|
1351
1408
|
panelMode = false,
|
|
1352
1409
|
isInputActive = true
|
|
1353
1410
|
}) {
|
|
1354
|
-
const [phase, setPhase] =
|
|
1355
|
-
const [selectedTool, setSelectedTool] =
|
|
1411
|
+
const [phase, setPhase] = useState8("tool-select");
|
|
1412
|
+
const [selectedTool, setSelectedTool] = useState8("supabase");
|
|
1356
1413
|
if (phase === "tool-select") {
|
|
1357
1414
|
const toolItems = [
|
|
1358
1415
|
{ value: "__section__", label: "\u{1F6E0} Select Tool", kind: "header", selectable: false },
|
|
@@ -1360,6 +1417,8 @@ function CustomCommand({
|
|
|
1360
1417
|
{ value: "gh", label: "GitHub CLI", hint: "gh ...", kind: "action" },
|
|
1361
1418
|
{ value: "vercel", label: "Vercel CLI", hint: "vercel ...", kind: "action" },
|
|
1362
1419
|
{ value: "git", label: "Git", hint: "git ...", kind: "action" },
|
|
1420
|
+
{ value: "__free_header__", label: "", kind: "header", selectable: false },
|
|
1421
|
+
{ value: "free", label: "\u2328 Free command", hint: "any command", kind: "action" },
|
|
1363
1422
|
...!panelMode ? [{ value: "__back__", label: "\u2190 Back" }] : []
|
|
1364
1423
|
];
|
|
1365
1424
|
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
|
|
@@ -1374,6 +1433,10 @@ function CustomCommand({
|
|
|
1374
1433
|
onBack();
|
|
1375
1434
|
return;
|
|
1376
1435
|
}
|
|
1436
|
+
if (value === "free") {
|
|
1437
|
+
setPhase("free-input");
|
|
1438
|
+
return;
|
|
1439
|
+
}
|
|
1377
1440
|
setSelectedTool(value);
|
|
1378
1441
|
setPhase("input");
|
|
1379
1442
|
},
|
|
@@ -1389,6 +1452,34 @@ function CustomCommand({
|
|
|
1389
1452
|
!panelMode && /* @__PURE__ */ jsx9(StatusBar, { hint: "\u2191\u2193 navigate \xB7 Enter select \xB7 Esc back", width })
|
|
1390
1453
|
] });
|
|
1391
1454
|
}
|
|
1455
|
+
if (phase === "free-input") {
|
|
1456
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
|
|
1457
|
+
!panelMode && /* @__PURE__ */ jsx9(Box8, { marginBottom: 1, children: /* @__PURE__ */ jsx9(Text9, { bold: true, color: inkColors.accent, children: "\u2328 Free Command" }) }),
|
|
1458
|
+
/* @__PURE__ */ jsx9(
|
|
1459
|
+
TextPrompt,
|
|
1460
|
+
{
|
|
1461
|
+
label: "Enter full command:",
|
|
1462
|
+
placeholder: "e.g. docker ps, curl -s http://..., make build",
|
|
1463
|
+
validate: (val) => {
|
|
1464
|
+
if (!val || !val.trim()) return "Please enter a command";
|
|
1465
|
+
return void 0;
|
|
1466
|
+
},
|
|
1467
|
+
onSubmit: (value) => {
|
|
1468
|
+
const parts = value.split(" ").filter(Boolean);
|
|
1469
|
+
const cmd = parts[0];
|
|
1470
|
+
const args = parts.slice(1);
|
|
1471
|
+
onNavigate("command-execution", { args, rawCommand: cmd });
|
|
1472
|
+
},
|
|
1473
|
+
onCancel: () => setPhase("tool-select"),
|
|
1474
|
+
arrowNavigation: panelMode,
|
|
1475
|
+
isInputActive,
|
|
1476
|
+
boxed: panelMode,
|
|
1477
|
+
focused: isInputActive
|
|
1478
|
+
}
|
|
1479
|
+
),
|
|
1480
|
+
!panelMode && /* @__PURE__ */ jsx9(StatusBar, { hint: "Type full command \xB7 Enter to execute \xB7 Esc to go back", width })
|
|
1481
|
+
] });
|
|
1482
|
+
}
|
|
1392
1483
|
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
|
|
1393
1484
|
!panelMode && /* @__PURE__ */ jsxs8(Box8, { marginBottom: 1, gap: 1, children: [
|
|
1394
1485
|
/* @__PURE__ */ jsx9(Text9, { bold: true, color: inkColors.accent, children: "\u270F\uFE0F Custom Command" }),
|
|
@@ -1409,7 +1500,7 @@ function CustomCommand({
|
|
|
1409
1500
|
},
|
|
1410
1501
|
onSubmit: (value) => {
|
|
1411
1502
|
const args = value.split(" ").filter(Boolean);
|
|
1412
|
-
onNavigate("
|
|
1503
|
+
onNavigate("command-execution", { args, tool: selectedTool });
|
|
1413
1504
|
},
|
|
1414
1505
|
onCancel: () => setPhase("tool-select"),
|
|
1415
1506
|
arrowNavigation: panelMode,
|
|
@@ -1426,7 +1517,7 @@ function CustomCommand({
|
|
|
1426
1517
|
import { Box as Box10, Text as Text11 } from "ink";
|
|
1427
1518
|
|
|
1428
1519
|
// src/components/FlagToggle.tsx
|
|
1429
|
-
import { useState as
|
|
1520
|
+
import { useState as useState9 } from "react";
|
|
1430
1521
|
import { Box as Box9, Text as Text10, useInput as useInput5 } from "ink";
|
|
1431
1522
|
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1432
1523
|
function FlagToggle({
|
|
@@ -1436,8 +1527,8 @@ function FlagToggle({
|
|
|
1436
1527
|
isInputActive = true,
|
|
1437
1528
|
arrowNavigation = false
|
|
1438
1529
|
}) {
|
|
1439
|
-
const [cursor, setCursor] =
|
|
1440
|
-
const [selected, setSelected] =
|
|
1530
|
+
const [cursor, setCursor] = useState9(0);
|
|
1531
|
+
const [selected, setSelected] = useState9(/* @__PURE__ */ new Set());
|
|
1441
1532
|
useInput5((input2, key) => {
|
|
1442
1533
|
if (key.upArrow || input2 === "k") {
|
|
1443
1534
|
setCursor((prev) => prev > 0 ? prev - 1 : flags.length - 1);
|
|
@@ -1569,27 +1660,12 @@ function FlagSelection({
|
|
|
1569
1660
|
}
|
|
1570
1661
|
|
|
1571
1662
|
// src/screens/CommandExecution.tsx
|
|
1572
|
-
import { useState as
|
|
1573
|
-
import { Box as Box13, Text as
|
|
1574
|
-
|
|
1575
|
-
// src/components/Spinner.tsx
|
|
1576
|
-
import { Text as Text12 } from "ink";
|
|
1577
|
-
import InkSpinner from "ink-spinner";
|
|
1578
|
-
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1579
|
-
function Spinner({
|
|
1580
|
-
label = "Running...",
|
|
1581
|
-
color = inkColors.accent
|
|
1582
|
-
}) {
|
|
1583
|
-
return /* @__PURE__ */ jsxs11(Text12, { children: [
|
|
1584
|
-
/* @__PURE__ */ jsx12(Text12, { color, children: /* @__PURE__ */ jsx12(InkSpinner, { type: "dots" }) }),
|
|
1585
|
-
" ",
|
|
1586
|
-
/* @__PURE__ */ jsx12(Text12, { children: label })
|
|
1587
|
-
] });
|
|
1588
|
-
}
|
|
1663
|
+
import { useState as useState12, useEffect as useEffect9 } from "react";
|
|
1664
|
+
import { Box as Box13, Text as Text15, useInput as useInput8 } from "ink";
|
|
1589
1665
|
|
|
1590
1666
|
// src/components/ConfirmPrompt.tsx
|
|
1591
|
-
import { Box as Box11, Text as
|
|
1592
|
-
import { jsx as
|
|
1667
|
+
import { Box as Box11, Text as Text12, useInput as useInput6 } from "ink";
|
|
1668
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1593
1669
|
function ConfirmPrompt({
|
|
1594
1670
|
message,
|
|
1595
1671
|
defaultValue = true,
|
|
@@ -1615,16 +1691,16 @@ function ConfirmPrompt({
|
|
|
1615
1691
|
onConfirm(defaultValue);
|
|
1616
1692
|
}
|
|
1617
1693
|
}, { isActive: isInputActive });
|
|
1618
|
-
return /* @__PURE__ */
|
|
1619
|
-
/* @__PURE__ */
|
|
1620
|
-
/* @__PURE__ */
|
|
1621
|
-
/* @__PURE__ */
|
|
1694
|
+
return /* @__PURE__ */ jsxs11(Box11, { gap: 1, children: [
|
|
1695
|
+
/* @__PURE__ */ jsx12(Text12, { color: inkColors.accent, bold: true, children: "?" }),
|
|
1696
|
+
/* @__PURE__ */ jsx12(Text12, { children: message }),
|
|
1697
|
+
/* @__PURE__ */ jsx12(Text12, { dimColor: true, children: defaultValue ? "(Y/n)" : "(y/N)" })
|
|
1622
1698
|
] });
|
|
1623
1699
|
}
|
|
1624
1700
|
|
|
1625
1701
|
// src/components/Divider.tsx
|
|
1626
|
-
import { Text as
|
|
1627
|
-
import { jsx as
|
|
1702
|
+
import { Text as Text13 } from "ink";
|
|
1703
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1628
1704
|
function Divider({
|
|
1629
1705
|
label,
|
|
1630
1706
|
width
|
|
@@ -1635,7 +1711,7 @@ function Divider({
|
|
|
1635
1711
|
const sideLen = Math.max(2, Math.floor((effectiveWidth - labelLen) / 2));
|
|
1636
1712
|
const left = "\u2500".repeat(sideLen);
|
|
1637
1713
|
const right = "\u2500".repeat(sideLen);
|
|
1638
|
-
return /* @__PURE__ */
|
|
1714
|
+
return /* @__PURE__ */ jsxs12(Text13, { dimColor: true, children: [
|
|
1639
1715
|
left,
|
|
1640
1716
|
" ",
|
|
1641
1717
|
label,
|
|
@@ -1643,31 +1719,44 @@ function Divider({
|
|
|
1643
1719
|
right
|
|
1644
1720
|
] });
|
|
1645
1721
|
}
|
|
1646
|
-
return /* @__PURE__ */
|
|
1722
|
+
return /* @__PURE__ */ jsx13(Text13, { dimColor: true, children: "\u2500".repeat(effectiveWidth) });
|
|
1647
1723
|
}
|
|
1648
1724
|
|
|
1649
|
-
// src/components/CommandOutput.tsx
|
|
1650
|
-
import { Text as Text16 } from "ink";
|
|
1651
|
-
|
|
1652
1725
|
// src/components/ScrollableBox.tsx
|
|
1653
|
-
import { useState as
|
|
1654
|
-
import { Box as Box12, Text as
|
|
1655
|
-
import { jsx as
|
|
1726
|
+
import { useState as useState10, useEffect as useEffect6, useRef } from "react";
|
|
1727
|
+
import { Box as Box12, Text as Text14, useInput as useInput7 } from "ink";
|
|
1728
|
+
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1656
1729
|
function ScrollableBox({
|
|
1657
1730
|
height,
|
|
1658
1731
|
isActive = true,
|
|
1732
|
+
autoScrollToBottom = false,
|
|
1659
1733
|
children
|
|
1660
1734
|
}) {
|
|
1661
1735
|
const totalItems = children.length;
|
|
1662
|
-
const [scrollOffset, setScrollOffset] =
|
|
1736
|
+
const [scrollOffset, setScrollOffset] = useState10(0);
|
|
1663
1737
|
const visibleCount = Math.max(1, height - 2);
|
|
1738
|
+
const maxOffset = Math.max(0, totalItems - visibleCount);
|
|
1739
|
+
const pinnedToBottom = useRef(autoScrollToBottom);
|
|
1740
|
+
useEffect6(() => {
|
|
1741
|
+
if (autoScrollToBottom && pinnedToBottom.current) {
|
|
1742
|
+
setScrollOffset(maxOffset);
|
|
1743
|
+
}
|
|
1744
|
+
}, [autoScrollToBottom, maxOffset]);
|
|
1664
1745
|
useInput7(
|
|
1665
1746
|
(input2, key) => {
|
|
1666
1747
|
if (key.upArrow || input2 === "k") {
|
|
1667
|
-
setScrollOffset((prev) =>
|
|
1748
|
+
setScrollOffset((prev) => {
|
|
1749
|
+
const next = Math.max(0, prev - 1);
|
|
1750
|
+
pinnedToBottom.current = next >= maxOffset;
|
|
1751
|
+
return next;
|
|
1752
|
+
});
|
|
1668
1753
|
}
|
|
1669
1754
|
if (key.downArrow || input2 === "j") {
|
|
1670
|
-
setScrollOffset((prev) =>
|
|
1755
|
+
setScrollOffset((prev) => {
|
|
1756
|
+
const next = Math.min(maxOffset, prev + 1);
|
|
1757
|
+
pinnedToBottom.current = next >= maxOffset;
|
|
1758
|
+
return next;
|
|
1759
|
+
});
|
|
1671
1760
|
}
|
|
1672
1761
|
},
|
|
1673
1762
|
{ isActive }
|
|
@@ -1675,52 +1764,22 @@ function ScrollableBox({
|
|
|
1675
1764
|
const showScrollUp = scrollOffset > 0;
|
|
1676
1765
|
const showScrollDown = scrollOffset + visibleCount < totalItems;
|
|
1677
1766
|
const visible = children.slice(scrollOffset, scrollOffset + visibleCount);
|
|
1678
|
-
return /* @__PURE__ */
|
|
1679
|
-
showScrollUp && /* @__PURE__ */
|
|
1767
|
+
return /* @__PURE__ */ jsxs13(Box12, { flexDirection: "column", height, children: [
|
|
1768
|
+
showScrollUp && /* @__PURE__ */ jsx14(Text14, { dimColor: true, children: " \u2191 more" }),
|
|
1680
1769
|
visible,
|
|
1681
|
-
showScrollDown && /* @__PURE__ */
|
|
1682
|
-
] });
|
|
1683
|
-
}
|
|
1684
|
-
|
|
1685
|
-
// src/lib/ansi.ts
|
|
1686
|
-
var ANSI_RE = (
|
|
1687
|
-
// biome-ignore lint/suspicious/noControlCharactersInRegex: intentional ANSI stripping
|
|
1688
|
-
/[\u001B\u009B][[\]()#;?]*(?:(?:(?:[a-zA-Z\d]*(?:;[-a-zA-Z\d/#&.:=?%@~_]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-nq-uy=><~]))/g
|
|
1689
|
-
);
|
|
1690
|
-
function stripAnsi(text) {
|
|
1691
|
-
return text.replace(ANSI_RE, "");
|
|
1692
|
-
}
|
|
1693
|
-
|
|
1694
|
-
// src/components/CommandOutput.tsx
|
|
1695
|
-
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
1696
|
-
function cleanLines(raw) {
|
|
1697
|
-
const stripped = stripAnsi(raw);
|
|
1698
|
-
return stripped.replace(/\r/g, "").split("\n").filter((line) => line.length > 0);
|
|
1699
|
-
}
|
|
1700
|
-
function CommandOutput({
|
|
1701
|
-
stdout,
|
|
1702
|
-
stderr,
|
|
1703
|
-
height,
|
|
1704
|
-
isActive = false
|
|
1705
|
-
}) {
|
|
1706
|
-
const outLines = stdout ? cleanLines(stdout) : [];
|
|
1707
|
-
const errLines = stderr ? cleanLines(stderr) : [];
|
|
1708
|
-
if (outLines.length === 0 && errLines.length === 0) {
|
|
1709
|
-
return null;
|
|
1710
|
-
}
|
|
1711
|
-
return /* @__PURE__ */ jsx16(ScrollableBox, { height: Math.max(3, height), isActive, children: [
|
|
1712
|
-
...outLines.map((line, i) => /* @__PURE__ */ jsx16(Text16, { children: line }, `o-${i}`)),
|
|
1713
|
-
...errLines.map((line, i) => /* @__PURE__ */ jsx16(Text16, { color: "red", children: line }, `e-${i}`))
|
|
1770
|
+
showScrollDown && /* @__PURE__ */ jsx14(Text14, { dimColor: true, children: " \u2193 more" })
|
|
1714
1771
|
] });
|
|
1715
1772
|
}
|
|
1716
1773
|
|
|
1717
1774
|
// src/hooks/useCommand.ts
|
|
1718
|
-
import { useState as
|
|
1775
|
+
import { useState as useState11, useCallback as useCallback2, useRef as useRef2, useEffect as useEffect7 } from "react";
|
|
1719
1776
|
function useCommand(execution = "supabase", cwd = process.cwd(), options) {
|
|
1720
|
-
const [status, setStatus] =
|
|
1721
|
-
const [result, setResult] =
|
|
1722
|
-
const
|
|
1723
|
-
|
|
1777
|
+
const [status, setStatus] = useState11("idle");
|
|
1778
|
+
const [result, setResult] = useState11(null);
|
|
1779
|
+
const [partialStdout, setPartialStdout] = useState11("");
|
|
1780
|
+
const [partialStderr, setPartialStderr] = useState11("");
|
|
1781
|
+
const abortRef = useRef2(null);
|
|
1782
|
+
useEffect7(() => {
|
|
1724
1783
|
return () => {
|
|
1725
1784
|
abortRef.current?.();
|
|
1726
1785
|
abortRef.current = null;
|
|
@@ -1729,9 +1788,11 @@ function useCommand(execution = "supabase", cwd = process.cwd(), options) {
|
|
|
1729
1788
|
const run = useCallback2(async (args) => {
|
|
1730
1789
|
setStatus("running");
|
|
1731
1790
|
setResult(null);
|
|
1791
|
+
setPartialStdout("");
|
|
1792
|
+
setPartialStderr("");
|
|
1732
1793
|
let resolvedExecution;
|
|
1733
1794
|
if (typeof execution === "string") {
|
|
1734
|
-
const toolIds2 = ["supabase", "gh", "vercel"];
|
|
1795
|
+
const toolIds2 = ["supabase", "gh", "vercel", "git", "pkg"];
|
|
1735
1796
|
if (toolIds2.includes(execution)) {
|
|
1736
1797
|
const resolved = resolveToolCommand(execution, cwd);
|
|
1737
1798
|
resolvedExecution = { command: resolved.command, env: resolved.env };
|
|
@@ -1741,7 +1802,11 @@ function useCommand(execution = "supabase", cwd = process.cwd(), options) {
|
|
|
1741
1802
|
} else {
|
|
1742
1803
|
resolvedExecution = execution;
|
|
1743
1804
|
}
|
|
1744
|
-
const
|
|
1805
|
+
const onData = (stdout, stderr) => {
|
|
1806
|
+
setPartialStdout(stdout);
|
|
1807
|
+
setPartialStderr(stderr);
|
|
1808
|
+
};
|
|
1809
|
+
const runOpts = { quiet: options?.quiet, onData };
|
|
1745
1810
|
const handle = runCommand(resolvedExecution, args, cwd, runOpts);
|
|
1746
1811
|
abortRef.current = handle.abort;
|
|
1747
1812
|
const res = await handle.promise;
|
|
@@ -1761,21 +1826,23 @@ function useCommand(execution = "supabase", cwd = process.cwd(), options) {
|
|
|
1761
1826
|
const reset = useCallback2(() => {
|
|
1762
1827
|
setStatus("idle");
|
|
1763
1828
|
setResult(null);
|
|
1829
|
+
setPartialStdout("");
|
|
1830
|
+
setPartialStderr("");
|
|
1764
1831
|
}, []);
|
|
1765
|
-
return { status, result, run, reset, abort };
|
|
1832
|
+
return { status, result, run, reset, abort, partialStdout, partialStderr };
|
|
1766
1833
|
}
|
|
1767
1834
|
|
|
1768
1835
|
// src/hooks/useInteractiveRun.ts
|
|
1769
1836
|
import { useCallback as useCallback3 } from "react";
|
|
1770
1837
|
|
|
1771
1838
|
// src/hooks/useFullscreen.ts
|
|
1772
|
-
import { useEffect as
|
|
1839
|
+
import { useEffect as useEffect8 } from "react";
|
|
1773
1840
|
var ENTER_ALT_SCREEN = "\x1B[?1049h";
|
|
1774
1841
|
var LEAVE_ALT_SCREEN = "\x1B[?1049l";
|
|
1775
1842
|
var HIDE_CURSOR = "\x1B[?25l";
|
|
1776
1843
|
var SHOW_CURSOR = "\x1B[?25h";
|
|
1777
1844
|
function useFullscreen() {
|
|
1778
|
-
|
|
1845
|
+
useEffect8(() => {
|
|
1779
1846
|
process.stdout.write(ENTER_ALT_SCREEN + HIDE_CURSOR);
|
|
1780
1847
|
return () => {
|
|
1781
1848
|
process.stdout.write(SHOW_CURSOR + LEAVE_ALT_SCREEN);
|
|
@@ -1830,6 +1897,15 @@ async function copyToClipboard(text) {
|
|
|
1830
1897
|
});
|
|
1831
1898
|
}
|
|
1832
1899
|
|
|
1900
|
+
// src/lib/ansi.ts
|
|
1901
|
+
var ANSI_RE = (
|
|
1902
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: intentional ANSI stripping
|
|
1903
|
+
/[\u001B\u009B][[\]()#;?]*(?:(?:(?:[a-zA-Z\d]*(?:;[-a-zA-Z\d/#&.:=?%@~_]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-nq-uy=><~]))/g
|
|
1904
|
+
);
|
|
1905
|
+
function stripAnsi(text) {
|
|
1906
|
+
return text.replace(ANSI_RE, "");
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1833
1909
|
// src/lib/errorSuggestions.ts
|
|
1834
1910
|
var KNOWN_TOOLS = ["supabase", "gh", "vercel", "git"];
|
|
1835
1911
|
var BACKTICK_CMD = /(?:try\s+)?(?:run(?:ning)?|use|execute)\s+`([^`]+)`/gi;
|
|
@@ -1876,10 +1952,11 @@ ${stderr}`);
|
|
|
1876
1952
|
}
|
|
1877
1953
|
|
|
1878
1954
|
// src/screens/CommandExecution.tsx
|
|
1879
|
-
import { jsx as
|
|
1955
|
+
import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1880
1956
|
function CommandExecution({
|
|
1881
1957
|
args: initialArgs,
|
|
1882
1958
|
tool = "supabase",
|
|
1959
|
+
rawCommand,
|
|
1883
1960
|
interactive = false,
|
|
1884
1961
|
onBack,
|
|
1885
1962
|
onHome,
|
|
@@ -1890,38 +1967,56 @@ function CommandExecution({
|
|
|
1890
1967
|
panelMode = false,
|
|
1891
1968
|
isInputActive = true
|
|
1892
1969
|
}) {
|
|
1893
|
-
const [phase, setPhase] =
|
|
1894
|
-
const [currentArgs, setCurrentArgs] =
|
|
1895
|
-
const [pinMessage, setPinMessage] =
|
|
1896
|
-
const
|
|
1970
|
+
const [phase, setPhase] = useState12("confirm");
|
|
1971
|
+
const [currentArgs, setCurrentArgs] = useState12(initialArgs);
|
|
1972
|
+
const [pinMessage, setPinMessage] = useState12();
|
|
1973
|
+
const execution = rawCommand ?? tool;
|
|
1974
|
+
const { status, result, run, reset, abort, partialStdout, partialStderr } = useCommand(execution, process.cwd(), {
|
|
1897
1975
|
quiet: panelMode
|
|
1898
1976
|
});
|
|
1899
1977
|
const { runInteractive } = useInteractiveRun();
|
|
1900
|
-
const [outputFocused, setOutputFocused] =
|
|
1901
|
-
const [copyMessage, setCopyMessage] =
|
|
1902
|
-
const
|
|
1978
|
+
const [outputFocused, setOutputFocused] = useState12(false);
|
|
1979
|
+
const [copyMessage, setCopyMessage] = useState12();
|
|
1980
|
+
const [feedback, setFeedback] = useState12();
|
|
1981
|
+
const [aborting, setAborting] = useState12(false);
|
|
1982
|
+
const cmdDisplay = rawCommand ? `${rawCommand} ${currentArgs.join(" ")}`.trim() : `${getToolDisplayName(tool)} ${currentArgs.join(" ")}`;
|
|
1903
1983
|
const runCommand2 = currentArgs.join(" ");
|
|
1904
1984
|
useInput8(
|
|
1905
|
-
(
|
|
1985
|
+
(input2, key) => {
|
|
1906
1986
|
if (key.escape) {
|
|
1907
1987
|
abort();
|
|
1908
1988
|
onBack();
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1991
|
+
if (input2 === "x" && !aborting) {
|
|
1992
|
+
abort();
|
|
1993
|
+
setAborting(true);
|
|
1994
|
+
setFeedback("Aborting...");
|
|
1995
|
+
return;
|
|
1996
|
+
}
|
|
1997
|
+
if (input2 === "c") {
|
|
1998
|
+
const output2 = [partialStdout, partialStderr].filter(Boolean).join("\n");
|
|
1999
|
+
copyToClipboard(output2).then(() => setFeedback("Copied to clipboard"));
|
|
2000
|
+
return;
|
|
1909
2001
|
}
|
|
1910
2002
|
},
|
|
1911
2003
|
{ isActive: isInputActive && phase === "running" }
|
|
1912
2004
|
);
|
|
1913
2005
|
useInput8(
|
|
1914
|
-
(input2,
|
|
1915
|
-
if (input2 === "
|
|
1916
|
-
setOutputFocused(
|
|
1917
|
-
}
|
|
1918
|
-
if (key.escape && outputFocused) {
|
|
1919
|
-
setOutputFocused(false);
|
|
2006
|
+
(input2, _key) => {
|
|
2007
|
+
if (input2 === "/") {
|
|
2008
|
+
setOutputFocused((prev) => !prev);
|
|
1920
2009
|
}
|
|
1921
2010
|
},
|
|
1922
|
-
{ isActive: isInputActive && phase === "error-menu" }
|
|
2011
|
+
{ isActive: isInputActive && (phase === "error-menu" || phase === "success") }
|
|
1923
2012
|
);
|
|
1924
|
-
|
|
2013
|
+
useEffect9(() => {
|
|
2014
|
+
if (phase === "background-started") {
|
|
2015
|
+
const t = setTimeout(() => onBack(), 1500);
|
|
2016
|
+
return () => clearTimeout(t);
|
|
2017
|
+
}
|
|
2018
|
+
}, [phase, onBack]);
|
|
2019
|
+
useEffect9(() => {
|
|
1925
2020
|
if (phase === "running" && status === "idle") {
|
|
1926
2021
|
if (panelMode && interactive) {
|
|
1927
2022
|
const interactiveResult = runInteractive(tool, currentArgs);
|
|
@@ -1935,7 +2030,7 @@ function CommandExecution({
|
|
|
1935
2030
|
}
|
|
1936
2031
|
}
|
|
1937
2032
|
}, [phase, status, run, currentArgs, panelMode, interactive, tool, runInteractive]);
|
|
1938
|
-
|
|
2033
|
+
useEffect9(() => {
|
|
1939
2034
|
if (phase === "running" && status === "success") {
|
|
1940
2035
|
if (isPinnedRun(runCommand2)) {
|
|
1941
2036
|
setPhase("success");
|
|
@@ -1947,6 +2042,12 @@ function CommandExecution({
|
|
|
1947
2042
|
setPhase("error-menu");
|
|
1948
2043
|
}
|
|
1949
2044
|
}, [phase, runCommand2, status]);
|
|
2045
|
+
useEffect9(() => {
|
|
2046
|
+
if (feedback) {
|
|
2047
|
+
const timer = setTimeout(() => setFeedback(void 0), 2e3);
|
|
2048
|
+
return () => clearTimeout(timer);
|
|
2049
|
+
}
|
|
2050
|
+
}, [feedback]);
|
|
1950
2051
|
if (phase === "confirm") {
|
|
1951
2052
|
const pinned = isPinnedRun(runCommand2);
|
|
1952
2053
|
const confirmItems = [
|
|
@@ -1956,19 +2057,24 @@ function CommandExecution({
|
|
|
1956
2057
|
label: pinned ? "\u{1F4CC} Unpin command" : "\u{1F4CC} Pin command",
|
|
1957
2058
|
hint: "Save to quick access"
|
|
1958
2059
|
},
|
|
2060
|
+
{
|
|
2061
|
+
value: "background",
|
|
2062
|
+
label: "\u23E9 Run in background",
|
|
2063
|
+
hint: "Start as background process"
|
|
2064
|
+
},
|
|
1959
2065
|
{ value: "cancel", label: "\u2190 Cancel" }
|
|
1960
2066
|
];
|
|
1961
|
-
const confirmContent = /* @__PURE__ */
|
|
1962
|
-
/* @__PURE__ */
|
|
1963
|
-
/* @__PURE__ */
|
|
2067
|
+
const confirmContent = /* @__PURE__ */ jsxs14(Box13, { flexDirection: "column", children: [
|
|
2068
|
+
/* @__PURE__ */ jsxs14(Box13, { marginBottom: 1, gap: 1, children: [
|
|
2069
|
+
/* @__PURE__ */ jsxs14(Text15, { color: inkColors.accent, bold: true, children: [
|
|
1964
2070
|
"\u25B6",
|
|
1965
2071
|
" ",
|
|
1966
2072
|
cmdDisplay
|
|
1967
2073
|
] }),
|
|
1968
|
-
/* @__PURE__ */
|
|
2074
|
+
/* @__PURE__ */ jsx15(ToolBadge, { tool })
|
|
1969
2075
|
] }),
|
|
1970
|
-
pinMessage && /* @__PURE__ */
|
|
1971
|
-
/* @__PURE__ */
|
|
2076
|
+
pinMessage && /* @__PURE__ */ jsx15(Box13, { marginBottom: 1, children: /* @__PURE__ */ jsx15(Text15, { color: inkColors.accent, children: pinMessage }) }),
|
|
2077
|
+
/* @__PURE__ */ jsx15(
|
|
1972
2078
|
SelectList,
|
|
1973
2079
|
{
|
|
1974
2080
|
items: confirmItems,
|
|
@@ -1984,6 +2090,19 @@ function CommandExecution({
|
|
|
1984
2090
|
isPinnedRun(runCommand2) ? "\u2713 Command pinned" : "\u2713 Command unpinned"
|
|
1985
2091
|
);
|
|
1986
2092
|
break;
|
|
2093
|
+
case "background": {
|
|
2094
|
+
const cwd = process.cwd();
|
|
2095
|
+
if (rawCommand) {
|
|
2096
|
+
const id = generateProcessId(rawCommand, currentArgs);
|
|
2097
|
+
startProcess(id, rawCommand, currentArgs, cwd);
|
|
2098
|
+
} else {
|
|
2099
|
+
const resolved = resolveToolCommand(tool, cwd);
|
|
2100
|
+
const id = generateProcessId(resolved.command, currentArgs);
|
|
2101
|
+
startProcess(id, resolved.command, currentArgs, cwd, resolved.env);
|
|
2102
|
+
}
|
|
2103
|
+
setPhase("background-started");
|
|
2104
|
+
break;
|
|
2105
|
+
}
|
|
1987
2106
|
case "cancel":
|
|
1988
2107
|
onBack();
|
|
1989
2108
|
break;
|
|
@@ -1998,7 +2117,7 @@ function CommandExecution({
|
|
|
1998
2117
|
}
|
|
1999
2118
|
)
|
|
2000
2119
|
] });
|
|
2001
|
-
return /* @__PURE__ */
|
|
2120
|
+
return /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: panelMode ? /* @__PURE__ */ jsx15(
|
|
2002
2121
|
Box13,
|
|
2003
2122
|
{
|
|
2004
2123
|
flexDirection: "column",
|
|
@@ -2010,32 +2129,72 @@ function CommandExecution({
|
|
|
2010
2129
|
}
|
|
2011
2130
|
) : confirmContent });
|
|
2012
2131
|
}
|
|
2132
|
+
if (phase === "background-started") {
|
|
2133
|
+
return /* @__PURE__ */ jsxs14(Box13, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
|
|
2134
|
+
/* @__PURE__ */ jsxs14(Box13, { marginY: 1, gap: 1, children: [
|
|
2135
|
+
/* @__PURE__ */ jsx15(Text15, { color: "#3ECF8E", bold: true, children: "\u2713" }),
|
|
2136
|
+
/* @__PURE__ */ jsx15(Text15, { color: "#3ECF8E", bold: true, children: "Started in background" })
|
|
2137
|
+
] }),
|
|
2138
|
+
/* @__PURE__ */ jsxs14(Box13, { children: [
|
|
2139
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Command: " }),
|
|
2140
|
+
/* @__PURE__ */ jsx15(Text15, { children: cmdDisplay })
|
|
2141
|
+
] })
|
|
2142
|
+
] });
|
|
2143
|
+
}
|
|
2013
2144
|
if (phase === "running") {
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
/* @__PURE__ */
|
|
2145
|
+
const outputText = [partialStdout, partialStderr].filter(Boolean).join("\n");
|
|
2146
|
+
const outputLines = outputText ? stripAnsi(outputText).split("\n") : [];
|
|
2147
|
+
const logBoxHeight = Math.max(3, height - 7);
|
|
2148
|
+
const cardWidth = Math.max(30, (panelMode ? width - 4 : width) - 2);
|
|
2149
|
+
return /* @__PURE__ */ jsxs14(Box13, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
|
|
2150
|
+
/* @__PURE__ */ jsxs14(Box13, { marginBottom: 1, gap: 1, children: [
|
|
2151
|
+
/* @__PURE__ */ jsxs14(Text15, { color: inkColors.accent, bold: true, children: [
|
|
2152
|
+
"\u25B6",
|
|
2153
|
+
" ",
|
|
2154
|
+
cmdDisplay
|
|
2155
|
+
] }),
|
|
2156
|
+
/* @__PURE__ */ jsx15(ToolBadge, { tool }),
|
|
2157
|
+
/* @__PURE__ */ jsxs14(Text15, { color: aborting ? "yellow" : "green", children: [
|
|
2158
|
+
"\u25CF ",
|
|
2159
|
+
aborting ? "aborting" : "running"
|
|
2160
|
+
] })
|
|
2021
2161
|
] }),
|
|
2022
|
-
/* @__PURE__ */
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2162
|
+
/* @__PURE__ */ jsx15(
|
|
2163
|
+
Box13,
|
|
2164
|
+
{
|
|
2165
|
+
flexDirection: "column",
|
|
2166
|
+
borderStyle: "round",
|
|
2167
|
+
borderColor: inkColors.accent,
|
|
2168
|
+
paddingX: 1,
|
|
2169
|
+
width: cardWidth,
|
|
2170
|
+
children: /* @__PURE__ */ jsx15(
|
|
2171
|
+
ScrollableBox,
|
|
2172
|
+
{
|
|
2173
|
+
height: logBoxHeight,
|
|
2174
|
+
isActive: isInputActive,
|
|
2175
|
+
autoScrollToBottom: true,
|
|
2176
|
+
children: outputLines.length === 0 ? [/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Waiting for output..." }, "empty")] : outputLines.map((line, i) => /* @__PURE__ */ jsx15(Text15, { wrap: "truncate", children: line }, i))
|
|
2177
|
+
}
|
|
2178
|
+
)
|
|
2179
|
+
}
|
|
2180
|
+
),
|
|
2181
|
+
feedback && /* @__PURE__ */ jsx15(Box13, { children: /* @__PURE__ */ jsx15(Text15, { color: inkColors.accent, children: feedback }) }),
|
|
2182
|
+
/* @__PURE__ */ jsxs14(Box13, { marginTop: 1, gap: 2, children: [
|
|
2183
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "\u2191\u2193:scroll" }),
|
|
2184
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "x:abort" }),
|
|
2185
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "c:copy" }),
|
|
2186
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Esc:back" })
|
|
2028
2187
|
] })
|
|
2029
2188
|
] });
|
|
2030
2189
|
}
|
|
2031
2190
|
if (phase === "success-pin-offer") {
|
|
2032
|
-
return /* @__PURE__ */
|
|
2033
|
-
/* @__PURE__ */
|
|
2034
|
-
/* @__PURE__ */
|
|
2035
|
-
/* @__PURE__ */
|
|
2036
|
-
/* @__PURE__ */
|
|
2191
|
+
return /* @__PURE__ */ jsxs14(Box13, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
|
|
2192
|
+
/* @__PURE__ */ jsx15(Divider, { width: panelMode ? width - 4 : width }),
|
|
2193
|
+
/* @__PURE__ */ jsxs14(Box13, { marginY: 1, gap: 1, children: [
|
|
2194
|
+
/* @__PURE__ */ jsx15(Text15, { color: inkColors.accent, bold: true, children: "\u2713" }),
|
|
2195
|
+
/* @__PURE__ */ jsx15(Text15, { color: inkColors.accent, bold: true, children: "Command completed successfully!" })
|
|
2037
2196
|
] }),
|
|
2038
|
-
/* @__PURE__ */
|
|
2197
|
+
/* @__PURE__ */ jsx15(
|
|
2039
2198
|
ConfirmPrompt,
|
|
2040
2199
|
{
|
|
2041
2200
|
message: "Pin this exact command?",
|
|
@@ -2058,24 +2217,49 @@ function CommandExecution({
|
|
|
2058
2217
|
const successItems = [
|
|
2059
2218
|
{ value: "__back__", label: "\u2190 Back to menu" }
|
|
2060
2219
|
];
|
|
2061
|
-
const
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2220
|
+
const successOutput = [result?.stdout, result?.stderr].filter(Boolean).join("\n");
|
|
2221
|
+
const successLines = successOutput ? stripAnsi(successOutput).split("\n") : [];
|
|
2222
|
+
const successLogHeight = Math.max(3, height - 9 - (pinMessage ? 1 : 0));
|
|
2223
|
+
const successCardWidth = Math.max(30, (panelMode ? width - 4 : width) - 2);
|
|
2224
|
+
return /* @__PURE__ */ jsxs14(Box13, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
|
|
2225
|
+
/* @__PURE__ */ jsxs14(Box13, { marginBottom: 1, gap: 1, children: [
|
|
2226
|
+
/* @__PURE__ */ jsxs14(Text15, { color: inkColors.accent, bold: true, children: [
|
|
2227
|
+
"\u2713",
|
|
2228
|
+
" ",
|
|
2229
|
+
cmdDisplay
|
|
2230
|
+
] }),
|
|
2231
|
+
/* @__PURE__ */ jsx15(ToolBadge, { tool }),
|
|
2232
|
+
/* @__PURE__ */ jsx15(Text15, { color: "green", children: "\u25CF completed" })
|
|
2067
2233
|
] }),
|
|
2068
|
-
pinMessage && /* @__PURE__ */
|
|
2069
|
-
/* @__PURE__ */
|
|
2070
|
-
|
|
2234
|
+
pinMessage && /* @__PURE__ */ jsx15(Box13, { marginBottom: 1, children: /* @__PURE__ */ jsx15(Text15, { color: inkColors.accent, children: pinMessage }) }),
|
|
2235
|
+
/* @__PURE__ */ jsx15(
|
|
2236
|
+
Box13,
|
|
2071
2237
|
{
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2238
|
+
flexDirection: "column",
|
|
2239
|
+
borderStyle: "round",
|
|
2240
|
+
borderColor: outputFocused ? inkColors.accent : panel.borderDim,
|
|
2241
|
+
paddingX: 1,
|
|
2242
|
+
width: successCardWidth,
|
|
2243
|
+
children: /* @__PURE__ */ jsx15(
|
|
2244
|
+
ScrollableBox,
|
|
2245
|
+
{
|
|
2246
|
+
height: successLogHeight,
|
|
2247
|
+
isActive: isInputActive && outputFocused,
|
|
2248
|
+
autoScrollToBottom: true,
|
|
2249
|
+
children: successLines.length === 0 ? [/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "No output" }, "empty")] : successLines.map((line, i) => /* @__PURE__ */ jsx15(Text15, { wrap: "truncate", children: line }, i))
|
|
2250
|
+
}
|
|
2251
|
+
)
|
|
2076
2252
|
}
|
|
2077
2253
|
),
|
|
2078
|
-
/* @__PURE__ */
|
|
2254
|
+
/* @__PURE__ */ jsxs14(Box13, { marginTop: 1, gap: 2, children: [
|
|
2255
|
+
/* @__PURE__ */ jsxs14(Text15, { dimColor: true, children: [
|
|
2256
|
+
"/:",
|
|
2257
|
+
outputFocused ? "menu" : "scroll"
|
|
2258
|
+
] }),
|
|
2259
|
+
outputFocused && /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "\u2191\u2193:scroll" }),
|
|
2260
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Esc:back" })
|
|
2261
|
+
] }),
|
|
2262
|
+
/* @__PURE__ */ jsx15(
|
|
2079
2263
|
SelectList,
|
|
2080
2264
|
{
|
|
2081
2265
|
items: successItems,
|
|
@@ -2083,10 +2267,10 @@ function CommandExecution({
|
|
|
2083
2267
|
onCancel: onHome ?? onBack,
|
|
2084
2268
|
width: panelMode ? Math.max(20, width - 4) : width,
|
|
2085
2269
|
maxVisible: panelMode ? Math.max(6, height - 6) : void 0,
|
|
2086
|
-
isInputActive,
|
|
2270
|
+
isInputActive: isInputActive && !outputFocused,
|
|
2087
2271
|
arrowNavigation: panelMode,
|
|
2088
2272
|
boxedSections: panelMode,
|
|
2089
|
-
panelFocused: isInputActive
|
|
2273
|
+
panelFocused: isInputActive && !outputFocused
|
|
2090
2274
|
}
|
|
2091
2275
|
)
|
|
2092
2276
|
] });
|
|
@@ -2149,65 +2333,67 @@ function CommandExecution({
|
|
|
2149
2333
|
value: "menu",
|
|
2150
2334
|
label: "\u2190 Back to menu"
|
|
2151
2335
|
});
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
/* @__PURE__ */
|
|
2160
|
-
|
|
2161
|
-
/* @__PURE__ */ jsx17(Text17, { color: "red", children: result.spawnError })
|
|
2162
|
-
] }),
|
|
2163
|
-
(result.spawnError.includes("ENOENT") || result.spawnError.includes("not found")) && /* @__PURE__ */ jsx17(Box13, { flexDirection: "column", marginLeft: 2, marginTop: 1, children: /* @__PURE__ */ jsxs15(Text17, { color: inkColors.accent, bold: true, children: [
|
|
2164
|
-
"\u{1F4A1}",
|
|
2336
|
+
const errorOutput = [result?.stdout, result?.stderr].filter(Boolean).join("\n");
|
|
2337
|
+
const errorLines = errorOutput ? stripAnsi(errorOutput).split("\n") : [];
|
|
2338
|
+
const errorLogHeight = Math.max(3, height - 8 - Math.min(errorItems.length, 6) - (copyMessage ? 1 : 0));
|
|
2339
|
+
const errorCardWidth = Math.max(30, (panelMode ? width - 4 : width) - 2);
|
|
2340
|
+
const errorStatusLabel = result?.spawnError ? "spawn error" : `exit ${result?.exitCode}`;
|
|
2341
|
+
return /* @__PURE__ */ jsxs14(Box13, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
|
|
2342
|
+
/* @__PURE__ */ jsxs14(Box13, { marginBottom: 1, gap: 1, children: [
|
|
2343
|
+
/* @__PURE__ */ jsxs14(Text15, { color: "red", bold: true, children: [
|
|
2344
|
+
"\u2717",
|
|
2165
2345
|
" ",
|
|
2346
|
+
cmdDisplay
|
|
2347
|
+
] }),
|
|
2348
|
+
/* @__PURE__ */ jsx15(ToolBadge, { tool }),
|
|
2349
|
+
/* @__PURE__ */ jsxs14(Text15, { color: "red", children: [
|
|
2350
|
+
"\u25CF ",
|
|
2351
|
+
errorStatusLabel
|
|
2352
|
+
] })
|
|
2353
|
+
] }),
|
|
2354
|
+
result?.spawnError && /* @__PURE__ */ jsxs14(Box13, { marginBottom: 1, children: [
|
|
2355
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Error: " }),
|
|
2356
|
+
/* @__PURE__ */ jsx15(Text15, { color: "red", children: result.spawnError }),
|
|
2357
|
+
(result.spawnError.includes("ENOENT") || result.spawnError.includes("not found")) && /* @__PURE__ */ jsxs14(Text15, { color: inkColors.accent, children: [
|
|
2358
|
+
" \u2014 ",
|
|
2166
2359
|
tool,
|
|
2167
2360
|
" CLI not found in this repository or PATH"
|
|
2168
|
-
] }) })
|
|
2169
|
-
] }) : /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", marginY: 1, children: [
|
|
2170
|
-
/* @__PURE__ */ jsxs15(Box13, { gap: 1, children: [
|
|
2171
|
-
/* @__PURE__ */ jsx17(Text17, { color: "red", bold: true, children: "\u2717" }),
|
|
2172
|
-
/* @__PURE__ */ jsx17(Text17, { color: "red", children: "Command failed " }),
|
|
2173
|
-
/* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "(exit code " }),
|
|
2174
|
-
/* @__PURE__ */ jsx17(Text17, { color: "red", bold: true, children: String(result?.exitCode) }),
|
|
2175
|
-
/* @__PURE__ */ jsx17(Text17, { dimColor: true, children: ")" })
|
|
2176
|
-
] }),
|
|
2177
|
-
/* @__PURE__ */ jsxs15(Box13, { marginLeft: 2, marginTop: 1, children: [
|
|
2178
|
-
/* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "Command: " }),
|
|
2179
|
-
/* @__PURE__ */ jsx17(Text17, { children: cmdDisplay })
|
|
2180
|
-
] }),
|
|
2181
|
-
!hasDebug && /* @__PURE__ */ jsxs15(Box13, { marginLeft: 2, marginTop: 1, gap: 1, children: [
|
|
2182
|
-
/* @__PURE__ */ jsxs15(Text17, { dimColor: true, children: [
|
|
2183
|
-
"\u{1F4A1}",
|
|
2184
|
-
" Tip: retry with"
|
|
2185
|
-
] }),
|
|
2186
|
-
/* @__PURE__ */ jsx17(Text17, { color: inkColors.accent, children: "--debug" }),
|
|
2187
|
-
/* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "to see detailed logs" })
|
|
2188
2361
|
] })
|
|
2189
2362
|
] }),
|
|
2190
|
-
/* @__PURE__ */
|
|
2191
|
-
|
|
2363
|
+
!result?.spawnError && !hasDebug && /* @__PURE__ */ jsxs14(Box13, { marginBottom: 1, gap: 1, children: [
|
|
2364
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "\u{1F4A1} Tip: retry with" }),
|
|
2365
|
+
/* @__PURE__ */ jsx15(Text15, { color: inkColors.accent, children: "--debug" }),
|
|
2366
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "to see detailed logs" })
|
|
2367
|
+
] }),
|
|
2368
|
+
/* @__PURE__ */ jsx15(
|
|
2369
|
+
Box13,
|
|
2192
2370
|
{
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2371
|
+
flexDirection: "column",
|
|
2372
|
+
borderStyle: "round",
|
|
2373
|
+
borderColor: outputFocused ? "red" : panel.borderDim,
|
|
2374
|
+
paddingX: 1,
|
|
2375
|
+
width: errorCardWidth,
|
|
2376
|
+
children: /* @__PURE__ */ jsx15(
|
|
2377
|
+
ScrollableBox,
|
|
2378
|
+
{
|
|
2379
|
+
height: errorLogHeight,
|
|
2380
|
+
isActive: isInputActive && outputFocused,
|
|
2381
|
+
autoScrollToBottom: true,
|
|
2382
|
+
children: errorLines.length === 0 ? [/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "No output" }, "empty")] : errorLines.map((line, i) => /* @__PURE__ */ jsx15(Text15, { wrap: "truncate", children: line }, i))
|
|
2383
|
+
}
|
|
2384
|
+
)
|
|
2197
2385
|
}
|
|
2198
2386
|
),
|
|
2199
|
-
copyMessage && /* @__PURE__ */
|
|
2200
|
-
|
|
2201
|
-
/* @__PURE__ */
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
/* @__PURE__ */
|
|
2206
|
-
/* @__PURE__ */
|
|
2207
|
-
/* @__PURE__ */ jsx17(Text17, { color: inkColors.accent, children: "o" }),
|
|
2208
|
-
/* @__PURE__ */ jsx17(Text17, { dimColor: true, children: " to scroll output)" })
|
|
2387
|
+
copyMessage && /* @__PURE__ */ jsx15(Box13, { children: /* @__PURE__ */ jsx15(Text15, { color: inkColors.accent, children: copyMessage }) }),
|
|
2388
|
+
/* @__PURE__ */ jsxs14(Box13, { marginTop: 1, gap: 2, children: [
|
|
2389
|
+
/* @__PURE__ */ jsxs14(Text15, { dimColor: true, children: [
|
|
2390
|
+
"/:",
|
|
2391
|
+
outputFocused ? "menu" : "scroll"
|
|
2392
|
+
] }),
|
|
2393
|
+
outputFocused && /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "\u2191\u2193:scroll" }),
|
|
2394
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Esc:back" })
|
|
2209
2395
|
] }),
|
|
2210
|
-
/* @__PURE__ */
|
|
2396
|
+
/* @__PURE__ */ jsx15(
|
|
2211
2397
|
SelectList,
|
|
2212
2398
|
{
|
|
2213
2399
|
items: errorItems,
|
|
@@ -2231,6 +2417,8 @@ function CommandExecution({
|
|
|
2231
2417
|
case "retry":
|
|
2232
2418
|
setPinMessage(void 0);
|
|
2233
2419
|
setCopyMessage(void 0);
|
|
2420
|
+
setAborting(false);
|
|
2421
|
+
setFeedback(void 0);
|
|
2234
2422
|
reset();
|
|
2235
2423
|
setPhase("running");
|
|
2236
2424
|
break;
|
|
@@ -2239,6 +2427,8 @@ function CommandExecution({
|
|
|
2239
2427
|
setCurrentArgs(newArgs);
|
|
2240
2428
|
setPinMessage(void 0);
|
|
2241
2429
|
setCopyMessage(void 0);
|
|
2430
|
+
setAborting(false);
|
|
2431
|
+
setFeedback(void 0);
|
|
2242
2432
|
reset();
|
|
2243
2433
|
setPhase("running");
|
|
2244
2434
|
break;
|
|
@@ -2277,13 +2467,54 @@ function CommandExecution({
|
|
|
2277
2467
|
panelFocused: isInputActive && !outputFocused
|
|
2278
2468
|
}
|
|
2279
2469
|
),
|
|
2280
|
-
!panelMode && /* @__PURE__ */
|
|
2470
|
+
!panelMode && /* @__PURE__ */ jsx15(StatusBar, { width })
|
|
2281
2471
|
] });
|
|
2282
2472
|
}
|
|
2283
2473
|
|
|
2284
2474
|
// src/screens/SelfUpdate.tsx
|
|
2285
|
-
import { useEffect as
|
|
2475
|
+
import { useEffect as useEffect10, useState as useState13 } from "react";
|
|
2286
2476
|
import { Box as Box14, Text as Text18 } from "ink";
|
|
2477
|
+
|
|
2478
|
+
// src/components/Spinner.tsx
|
|
2479
|
+
import { Text as Text16 } from "ink";
|
|
2480
|
+
import InkSpinner from "ink-spinner";
|
|
2481
|
+
import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2482
|
+
function Spinner({
|
|
2483
|
+
label = "Running...",
|
|
2484
|
+
color = inkColors.accent
|
|
2485
|
+
}) {
|
|
2486
|
+
return /* @__PURE__ */ jsxs15(Text16, { children: [
|
|
2487
|
+
/* @__PURE__ */ jsx16(Text16, { color, children: /* @__PURE__ */ jsx16(InkSpinner, { type: "dots" }) }),
|
|
2488
|
+
" ",
|
|
2489
|
+
/* @__PURE__ */ jsx16(Text16, { children: label })
|
|
2490
|
+
] });
|
|
2491
|
+
}
|
|
2492
|
+
|
|
2493
|
+
// src/components/CommandOutput.tsx
|
|
2494
|
+
import { Text as Text17 } from "ink";
|
|
2495
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
2496
|
+
function cleanLines(raw) {
|
|
2497
|
+
const stripped = stripAnsi(raw);
|
|
2498
|
+
return stripped.replace(/\r/g, "").split("\n").filter((line) => line.length > 0);
|
|
2499
|
+
}
|
|
2500
|
+
function CommandOutput({
|
|
2501
|
+
stdout,
|
|
2502
|
+
stderr,
|
|
2503
|
+
height,
|
|
2504
|
+
isActive = false
|
|
2505
|
+
}) {
|
|
2506
|
+
const outLines = stdout ? cleanLines(stdout) : [];
|
|
2507
|
+
const errLines = stderr ? cleanLines(stderr) : [];
|
|
2508
|
+
if (outLines.length === 0 && errLines.length === 0) {
|
|
2509
|
+
return null;
|
|
2510
|
+
}
|
|
2511
|
+
return /* @__PURE__ */ jsx17(ScrollableBox, { height: Math.max(3, height), isActive, children: [
|
|
2512
|
+
...outLines.map((line, i) => /* @__PURE__ */ jsx17(Text17, { children: line }, `o-${i}`)),
|
|
2513
|
+
...errLines.map((line, i) => /* @__PURE__ */ jsx17(Text17, { color: "red", children: line }, `e-${i}`))
|
|
2514
|
+
] });
|
|
2515
|
+
}
|
|
2516
|
+
|
|
2517
|
+
// src/screens/SelfUpdate.tsx
|
|
2287
2518
|
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2288
2519
|
var packageName = "@polterware/polter";
|
|
2289
2520
|
var globalUpdateArgs = ["install", "-g", `${packageName}@latest`];
|
|
@@ -2300,10 +2531,10 @@ function SelfUpdate({
|
|
|
2300
2531
|
isInputActive = true
|
|
2301
2532
|
}) {
|
|
2302
2533
|
const repositoryRoot = findNearestPackageRoot();
|
|
2303
|
-
const [target, setTarget] =
|
|
2534
|
+
const [target, setTarget] = useState13(
|
|
2304
2535
|
repositoryRoot ? "repository" : "global"
|
|
2305
2536
|
);
|
|
2306
|
-
const [phase, setPhase] =
|
|
2537
|
+
const [phase, setPhase] = useState13(
|
|
2307
2538
|
repositoryRoot ? "target" : "confirm"
|
|
2308
2539
|
);
|
|
2309
2540
|
const updateArgs = getUpdateArgs(target);
|
|
@@ -2312,12 +2543,12 @@ function SelfUpdate({
|
|
|
2312
2543
|
const { status, result, run, reset } = useCommand("npm", updateCwd, {
|
|
2313
2544
|
quiet: panelMode
|
|
2314
2545
|
});
|
|
2315
|
-
|
|
2546
|
+
useEffect10(() => {
|
|
2316
2547
|
if (phase === "running" && status === "idle") {
|
|
2317
2548
|
run(updateArgs);
|
|
2318
2549
|
}
|
|
2319
2550
|
}, [phase, run, status, updateArgs]);
|
|
2320
|
-
|
|
2551
|
+
useEffect10(() => {
|
|
2321
2552
|
if (phase === "running" && status === "success") {
|
|
2322
2553
|
setPhase("success");
|
|
2323
2554
|
}
|
|
@@ -2558,15 +2789,15 @@ function SelfUpdate({
|
|
|
2558
2789
|
}
|
|
2559
2790
|
|
|
2560
2791
|
// src/screens/ToolStatus.tsx
|
|
2561
|
-
import { useEffect as
|
|
2792
|
+
import { useEffect as useEffect11, useState as useState14 } from "react";
|
|
2562
2793
|
import { Box as Box15, Text as Text19 } from "ink";
|
|
2563
2794
|
import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2564
2795
|
var toolIds = ["supabase", "gh", "vercel", "git", "pkg"];
|
|
2565
2796
|
var linkableTools = /* @__PURE__ */ new Set(["supabase", "gh", "vercel", "pkg"]);
|
|
2566
2797
|
function ToolStatus({ onBack, onNavigate, width = 80, height = 24, panelMode = false, isInputActive = true }) {
|
|
2567
|
-
const [tools, setTools] =
|
|
2568
|
-
const [mcpInfo, setMcpInfo] =
|
|
2569
|
-
|
|
2798
|
+
const [tools, setTools] = useState14(null);
|
|
2799
|
+
const [mcpInfo, setMcpInfo] = useState14(null);
|
|
2800
|
+
useEffect11(() => {
|
|
2570
2801
|
const t = setTimeout(() => {
|
|
2571
2802
|
setTools(toolIds.map((id) => getToolLinkInfo(id)));
|
|
2572
2803
|
setMcpInfo(getMcpStatusInfo());
|
|
@@ -2652,11 +2883,11 @@ function ToolStatus({ onBack, onNavigate, width = 80, height = 24, panelMode = f
|
|
|
2652
2883
|
}
|
|
2653
2884
|
|
|
2654
2885
|
// src/screens/ProjectConfig.tsx
|
|
2655
|
-
import { useMemo as useMemo4, useState as
|
|
2886
|
+
import { useMemo as useMemo4, useState as useState16 } from "react";
|
|
2656
2887
|
import { Box as Box16, Text as Text20 } from "ink";
|
|
2657
2888
|
|
|
2658
2889
|
// src/hooks/useEditor.ts
|
|
2659
|
-
import { useState as
|
|
2890
|
+
import { useState as useState15, useCallback as useCallback4 } from "react";
|
|
2660
2891
|
import { useStdin } from "ink";
|
|
2661
2892
|
|
|
2662
2893
|
// src/lib/editor.ts
|
|
@@ -2707,7 +2938,7 @@ function openInEditor(filePath) {
|
|
|
2707
2938
|
// src/hooks/useEditor.ts
|
|
2708
2939
|
function useEditor() {
|
|
2709
2940
|
const { setRawMode } = useStdin();
|
|
2710
|
-
const [isEditing, setIsEditing] =
|
|
2941
|
+
const [isEditing, setIsEditing] = useState15(false);
|
|
2711
2942
|
const openEditor = useCallback4(async (filePath) => {
|
|
2712
2943
|
const editor = resolveEditor();
|
|
2713
2944
|
const terminal = isTerminalEditor(editor.command);
|
|
@@ -2737,11 +2968,11 @@ function ProjectConfig({
|
|
|
2737
2968
|
isInputActive = true
|
|
2738
2969
|
}) {
|
|
2739
2970
|
const configPath = useMemo4(() => getProjectConfigPath(), []);
|
|
2740
|
-
const [config2, setConfig] =
|
|
2741
|
-
const [phase, setPhase] =
|
|
2742
|
-
const [feedback, setFeedback] =
|
|
2743
|
-
const [envKey, setEnvKey] =
|
|
2744
|
-
const [selectedEnvKey, setSelectedEnvKey] =
|
|
2971
|
+
const [config2, setConfig] = useState16(() => getOrCreateProjectConfig());
|
|
2972
|
+
const [phase, setPhase] = useState16("overview");
|
|
2973
|
+
const [feedback, setFeedback] = useState16();
|
|
2974
|
+
const [envKey, setEnvKey] = useState16("");
|
|
2975
|
+
const [selectedEnvKey, setSelectedEnvKey] = useState16("");
|
|
2745
2976
|
const { openEditor, isEditing } = useEditor();
|
|
2746
2977
|
const detectedPkg = useMemo4(() => detectPkgManager(), []);
|
|
2747
2978
|
if (!configPath) {
|
|
@@ -3223,7 +3454,7 @@ function PipelineList({
|
|
|
3223
3454
|
}
|
|
3224
3455
|
|
|
3225
3456
|
// src/screens/PipelineBuilder.tsx
|
|
3226
|
-
import { useState as
|
|
3457
|
+
import { useState as useState17 } from "react";
|
|
3227
3458
|
import { Box as Box18, Text as Text22 } from "ink";
|
|
3228
3459
|
import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
3229
3460
|
var stepCounter = 0;
|
|
@@ -3238,9 +3469,9 @@ function PipelineBuilder({
|
|
|
3238
3469
|
panelMode = false,
|
|
3239
3470
|
isInputActive = true
|
|
3240
3471
|
}) {
|
|
3241
|
-
const [phase, setPhase] =
|
|
3242
|
-
const [name, setName] =
|
|
3243
|
-
const [steps, setSteps] =
|
|
3472
|
+
const [phase, setPhase] = useState17("name");
|
|
3473
|
+
const [name, setName] = useState17("");
|
|
3474
|
+
const [steps, setSteps] = useState17([]);
|
|
3244
3475
|
if (phase === "name") {
|
|
3245
3476
|
return /* @__PURE__ */ jsxs20(Box18, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
|
|
3246
3477
|
/* @__PURE__ */ jsx22(Box18, { marginBottom: 1, children: /* @__PURE__ */ jsx22(Text22, { bold: true, color: inkColors.accent, children: "\u{1F517} New Pipeline" }) }),
|
|
@@ -3426,7 +3657,7 @@ function PipelineBuilder({
|
|
|
3426
3657
|
}
|
|
3427
3658
|
|
|
3428
3659
|
// src/screens/PipelineExecution.tsx
|
|
3429
|
-
import { useState as
|
|
3660
|
+
import { useState as useState18, useEffect as useEffect12, useMemo as useMemo6 } from "react";
|
|
3430
3661
|
import { Box as Box21, Text as Text25 } from "ink";
|
|
3431
3662
|
|
|
3432
3663
|
// src/components/StepIndicator.tsx
|
|
@@ -3519,10 +3750,10 @@ function PipelineExecution({
|
|
|
3519
3750
|
() => getAllPipelines().find((p) => p.id === pipelineId),
|
|
3520
3751
|
[pipelineId]
|
|
3521
3752
|
);
|
|
3522
|
-
const [phase, setPhase] =
|
|
3523
|
-
const [progress, setProgress] =
|
|
3524
|
-
const [results, setResults] =
|
|
3525
|
-
|
|
3753
|
+
const [phase, setPhase] = useState18("running");
|
|
3754
|
+
const [progress, setProgress] = useState18(null);
|
|
3755
|
+
const [results, setResults] = useState18([]);
|
|
3756
|
+
useEffect12(() => {
|
|
3526
3757
|
if (!pipeline) return;
|
|
3527
3758
|
executePipeline(pipeline, (p) => {
|
|
3528
3759
|
setProgress({ ...p });
|
|
@@ -3636,7 +3867,7 @@ function PipelineExecution({
|
|
|
3636
3867
|
}
|
|
3637
3868
|
|
|
3638
3869
|
// src/screens/McpManage.tsx
|
|
3639
|
-
import { useState as
|
|
3870
|
+
import { useState as useState19, useCallback as useCallback5 } from "react";
|
|
3640
3871
|
import { Box as Box22, Text as Text26 } from "ink";
|
|
3641
3872
|
import { jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
3642
3873
|
function McpManage({
|
|
@@ -3646,10 +3877,10 @@ function McpManage({
|
|
|
3646
3877
|
panelMode = false,
|
|
3647
3878
|
isInputActive = true
|
|
3648
3879
|
}) {
|
|
3649
|
-
const [status, setStatus] =
|
|
3650
|
-
const [phase, setPhase] =
|
|
3651
|
-
const [action, setAction] =
|
|
3652
|
-
const [result, setResult] =
|
|
3880
|
+
const [status, setStatus] = useState19(() => getMcpStatusInfo());
|
|
3881
|
+
const [phase, setPhase] = useState19("overview");
|
|
3882
|
+
const [action, setAction] = useState19(null);
|
|
3883
|
+
const [result, setResult] = useState19(null);
|
|
3653
3884
|
const refreshStatus = useCallback5(() => {
|
|
3654
3885
|
setStatus(getMcpStatusInfo());
|
|
3655
3886
|
}, []);
|
|
@@ -3791,7 +4022,7 @@ function McpManage({
|
|
|
3791
4022
|
}
|
|
3792
4023
|
|
|
3793
4024
|
// src/screens/ProcessList.tsx
|
|
3794
|
-
import { useState as
|
|
4025
|
+
import { useState as useState20, useEffect as useEffect13, useCallback as useCallback6 } from "react";
|
|
3795
4026
|
import { Box as Box23, Text as Text27, useInput as useInput9 } from "ink";
|
|
3796
4027
|
import { homedir } from "os";
|
|
3797
4028
|
import { jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
@@ -3831,22 +4062,22 @@ function ProcessList({
|
|
|
3831
4062
|
panelMode = false,
|
|
3832
4063
|
isInputActive = true
|
|
3833
4064
|
}) {
|
|
3834
|
-
const [processes, setProcesses] =
|
|
3835
|
-
const [selectedIndex, setSelectedIndex] =
|
|
3836
|
-
const [feedback, setFeedback] =
|
|
3837
|
-
|
|
4065
|
+
const [processes, setProcesses] = useState20(() => listProcesses());
|
|
4066
|
+
const [selectedIndex, setSelectedIndex] = useState20(0);
|
|
4067
|
+
const [feedback, setFeedback] = useState20();
|
|
4068
|
+
useEffect13(() => {
|
|
3838
4069
|
const interval = setInterval(() => {
|
|
3839
4070
|
setProcesses(listProcesses());
|
|
3840
4071
|
}, 2e3);
|
|
3841
4072
|
return () => clearInterval(interval);
|
|
3842
4073
|
}, []);
|
|
3843
|
-
|
|
4074
|
+
useEffect13(() => {
|
|
3844
4075
|
if (feedback) {
|
|
3845
4076
|
const timer = setTimeout(() => setFeedback(void 0), 2e3);
|
|
3846
4077
|
return () => clearTimeout(timer);
|
|
3847
4078
|
}
|
|
3848
4079
|
}, [feedback]);
|
|
3849
|
-
|
|
4080
|
+
useEffect13(() => {
|
|
3850
4081
|
if (selectedIndex >= processes.length && processes.length > 0) {
|
|
3851
4082
|
setSelectedIndex(processes.length - 1);
|
|
3852
4083
|
}
|
|
@@ -3996,7 +4227,7 @@ function ProcessList({
|
|
|
3996
4227
|
}
|
|
3997
4228
|
|
|
3998
4229
|
// src/screens/ProcessLogs.tsx
|
|
3999
|
-
import { useState as
|
|
4230
|
+
import { useState as useState21, useEffect as useEffect14, useCallback as useCallback7 } from "react";
|
|
4000
4231
|
import { Box as Box24, Text as Text28, useInput as useInput10 } from "ink";
|
|
4001
4232
|
import { spawn as spawn3 } from "child_process";
|
|
4002
4233
|
import { jsx as jsx27, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
@@ -4015,16 +4246,16 @@ function ProcessLogs({
|
|
|
4015
4246
|
panelMode = false,
|
|
4016
4247
|
isInputActive = true
|
|
4017
4248
|
}) {
|
|
4018
|
-
const [stream, setStream] =
|
|
4019
|
-
const [lines, setLines] =
|
|
4020
|
-
const [proc, setProc] =
|
|
4021
|
-
const [feedback, setFeedback] =
|
|
4249
|
+
const [stream, setStream] = useState21("both");
|
|
4250
|
+
const [lines, setLines] = useState21([]);
|
|
4251
|
+
const [proc, setProc] = useState21();
|
|
4252
|
+
const [feedback, setFeedback] = useState21();
|
|
4022
4253
|
const logBoxHeight = Math.max(3, height - 6);
|
|
4023
|
-
|
|
4254
|
+
useEffect14(() => {
|
|
4024
4255
|
const refresh = () => {
|
|
4025
4256
|
try {
|
|
4026
|
-
const output2 = getProcessOutput(processId,
|
|
4027
|
-
const combined = stream === "stderr" ? output2.stderr : stream === "stdout" ? output2.stdout : [...output2.stdout, ...output2.stderr].slice(-
|
|
4257
|
+
const output2 = getProcessOutput(processId, 1e3, stream);
|
|
4258
|
+
const combined = stream === "stderr" ? output2.stderr : stream === "stdout" ? output2.stdout : [...output2.stdout, ...output2.stderr].slice(-1e3);
|
|
4028
4259
|
setLines(combined);
|
|
4029
4260
|
} catch {
|
|
4030
4261
|
setLines([`Process "${processId}" not found`]);
|
|
@@ -4035,8 +4266,8 @@ function ProcessLogs({
|
|
|
4035
4266
|
refresh();
|
|
4036
4267
|
const interval = setInterval(refresh, 1e3);
|
|
4037
4268
|
return () => clearInterval(interval);
|
|
4038
|
-
}, [processId,
|
|
4039
|
-
|
|
4269
|
+
}, [processId, stream]);
|
|
4270
|
+
useEffect14(() => {
|
|
4040
4271
|
if (feedback) {
|
|
4041
4272
|
const timer = setTimeout(() => setFeedback(void 0), 2e3);
|
|
4042
4273
|
return () => clearTimeout(timer);
|
|
@@ -4104,10 +4335,16 @@ function ProcessLogs({
|
|
|
4104
4335
|
borderStyle: "round",
|
|
4105
4336
|
borderColor: inkColors.accent,
|
|
4106
4337
|
paddingX: 1,
|
|
4107
|
-
height: logBoxHeight + 2,
|
|
4108
4338
|
width: cardWidth,
|
|
4109
|
-
|
|
4110
|
-
|
|
4339
|
+
children: /* @__PURE__ */ jsx27(
|
|
4340
|
+
ScrollableBox,
|
|
4341
|
+
{
|
|
4342
|
+
height: logBoxHeight,
|
|
4343
|
+
isActive: isInputActive,
|
|
4344
|
+
autoScrollToBottom: true,
|
|
4345
|
+
children: lines.length === 0 ? [/* @__PURE__ */ jsx27(Text28, { dimColor: true, children: "No output yet..." }, "empty")] : lines.map((line, i) => /* @__PURE__ */ jsx27(Text28, { wrap: "truncate", children: line }, i))
|
|
4346
|
+
}
|
|
4347
|
+
)
|
|
4111
4348
|
}
|
|
4112
4349
|
),
|
|
4113
4350
|
feedback && /* @__PURE__ */ jsx27(Box24, { children: /* @__PURE__ */ jsx27(Text28, { color: inkColors.accent, children: feedback }) }),
|
|
@@ -4117,6 +4354,7 @@ function ProcessLogs({
|
|
|
4117
4354
|
/* @__PURE__ */ jsx27(Text28, { bold: true, color: inkColors.accent, children: stream }),
|
|
4118
4355
|
"]"
|
|
4119
4356
|
] }),
|
|
4357
|
+
/* @__PURE__ */ jsx27(Text28, { dimColor: true, children: "\u2191\u2193:scroll" }),
|
|
4120
4358
|
/* @__PURE__ */ jsx27(Text28, { dimColor: true, children: "s:toggle" }),
|
|
4121
4359
|
/* @__PURE__ */ jsx27(Text28, { dimColor: true, children: "x:stop" }),
|
|
4122
4360
|
/* @__PURE__ */ jsx27(Text28, { dimColor: true, children: "c:copy" }),
|
|
@@ -4126,7 +4364,7 @@ function ProcessLogs({
|
|
|
4126
4364
|
}
|
|
4127
4365
|
|
|
4128
4366
|
// src/screens/DeclarativePlan.tsx
|
|
4129
|
-
import { useEffect as
|
|
4367
|
+
import { useEffect as useEffect15, useState as useState22 } from "react";
|
|
4130
4368
|
import { Box as Box25, Text as Text29 } from "ink";
|
|
4131
4369
|
import { jsx as jsx28, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
4132
4370
|
function DeclarativePlan({
|
|
@@ -4137,10 +4375,10 @@ function DeclarativePlan({
|
|
|
4137
4375
|
panelMode = false,
|
|
4138
4376
|
isInputActive = true
|
|
4139
4377
|
}) {
|
|
4140
|
-
const [phase, setPhase] =
|
|
4141
|
-
const [actions, setActions] =
|
|
4142
|
-
const [applyProgress, setApplyProgress] =
|
|
4143
|
-
const [applyResults, setApplyResults] =
|
|
4378
|
+
const [phase, setPhase] = useState22("loading");
|
|
4379
|
+
const [actions, setActions] = useState22([]);
|
|
4380
|
+
const [applyProgress, setApplyProgress] = useState22("");
|
|
4381
|
+
const [applyResults, setApplyResults] = useState22([]);
|
|
4144
4382
|
const { openEditor } = useEditor();
|
|
4145
4383
|
const loadPlan = () => {
|
|
4146
4384
|
setPhase("loading");
|
|
@@ -4160,7 +4398,7 @@ function DeclarativePlan({
|
|
|
4160
4398
|
setPhase("plan-view");
|
|
4161
4399
|
}, 0);
|
|
4162
4400
|
};
|
|
4163
|
-
|
|
4401
|
+
useEffect15(() => {
|
|
4164
4402
|
loadPlan();
|
|
4165
4403
|
}, []);
|
|
4166
4404
|
if (phase === "loading") {
|
|
@@ -4354,7 +4592,7 @@ function DeclarativePlan({
|
|
|
4354
4592
|
}
|
|
4355
4593
|
|
|
4356
4594
|
// src/screens/DeclarativeStatus.tsx
|
|
4357
|
-
import { useEffect as
|
|
4595
|
+
import { useEffect as useEffect16, useState as useState23 } from "react";
|
|
4358
4596
|
import { Box as Box26, Text as Text30 } from "ink";
|
|
4359
4597
|
import { jsx as jsx29, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
4360
4598
|
function DeclarativeStatus({
|
|
@@ -4364,10 +4602,10 @@ function DeclarativeStatus({
|
|
|
4364
4602
|
panelMode = false,
|
|
4365
4603
|
isInputActive = true
|
|
4366
4604
|
}) {
|
|
4367
|
-
const [phase, setPhase] =
|
|
4368
|
-
const [status, setStatus] =
|
|
4369
|
-
const [config2, setConfig] =
|
|
4370
|
-
const [pkgInfo, setPkgInfo] =
|
|
4605
|
+
const [phase, setPhase] = useState23("loading");
|
|
4606
|
+
const [status, setStatus] = useState23({});
|
|
4607
|
+
const [config2, setConfig] = useState23(null);
|
|
4608
|
+
const [pkgInfo, setPkgInfo] = useState23(null);
|
|
4371
4609
|
const load = () => {
|
|
4372
4610
|
setPhase("loading");
|
|
4373
4611
|
setTimeout(() => {
|
|
@@ -4380,7 +4618,7 @@ function DeclarativeStatus({
|
|
|
4380
4618
|
setPhase("display");
|
|
4381
4619
|
}, 0);
|
|
4382
4620
|
};
|
|
4383
|
-
|
|
4621
|
+
useEffect16(() => {
|
|
4384
4622
|
load();
|
|
4385
4623
|
}, []);
|
|
4386
4624
|
if (phase === "loading") {
|
|
@@ -4486,7 +4724,7 @@ function DeclarativeStatus({
|
|
|
4486
4724
|
}
|
|
4487
4725
|
|
|
4488
4726
|
// src/screens/InitScaffold.tsx
|
|
4489
|
-
import { useEffect as
|
|
4727
|
+
import { useEffect as useEffect17, useState as useState24 } from "react";
|
|
4490
4728
|
import { Box as Box27, Text as Text31 } from "ink";
|
|
4491
4729
|
import { writeFileSync } from "fs";
|
|
4492
4730
|
import { join } from "path";
|
|
@@ -4630,9 +4868,9 @@ function InitScaffold({
|
|
|
4630
4868
|
panelMode = false,
|
|
4631
4869
|
isInputActive = true
|
|
4632
4870
|
}) {
|
|
4633
|
-
const [phase, setPhase] =
|
|
4634
|
-
const [yamlString, setYamlString] =
|
|
4635
|
-
const [overwrite, setOverwrite] =
|
|
4871
|
+
const [phase, setPhase] = useState24("detecting");
|
|
4872
|
+
const [yamlString, setYamlString] = useState24("");
|
|
4873
|
+
const [overwrite, setOverwrite] = useState24(false);
|
|
4636
4874
|
const { openEditor } = useEditor();
|
|
4637
4875
|
const cwd = process.cwd();
|
|
4638
4876
|
const yamlPath = join(cwd, "polter.yaml");
|
|
@@ -4678,7 +4916,7 @@ function InitScaffold({
|
|
|
4678
4916
|
setPhase("preview");
|
|
4679
4917
|
}, 0);
|
|
4680
4918
|
};
|
|
4681
|
-
|
|
4919
|
+
useEffect17(() => {
|
|
4682
4920
|
detect();
|
|
4683
4921
|
}, []);
|
|
4684
4922
|
if (phase === "detecting") {
|
|
@@ -4790,8 +5028,164 @@ function InitScaffold({
|
|
|
4790
5028
|
] });
|
|
4791
5029
|
}
|
|
4792
5030
|
|
|
4793
|
-
// src/
|
|
5031
|
+
// src/screens/ScriptPicker.tsx
|
|
5032
|
+
import { useState as useState25, useEffect as useEffect18, useMemo as useMemo8 } from "react";
|
|
5033
|
+
import { Box as Box28, Text as Text32, useInput as useInput11 } from "ink";
|
|
5034
|
+
import { readFileSync, existsSync } from "fs";
|
|
5035
|
+
import { join as join2 } from "path";
|
|
4794
5036
|
import { jsx as jsx31, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
5037
|
+
function readScripts(cwd) {
|
|
5038
|
+
const pkgPath = join2(cwd, "package.json");
|
|
5039
|
+
if (!existsSync(pkgPath)) return [];
|
|
5040
|
+
try {
|
|
5041
|
+
const raw = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
5042
|
+
const scripts = raw.scripts ?? {};
|
|
5043
|
+
return Object.entries(scripts).map(([name, command]) => ({ name, command }));
|
|
5044
|
+
} catch {
|
|
5045
|
+
return [];
|
|
5046
|
+
}
|
|
5047
|
+
}
|
|
5048
|
+
function ScriptPicker({
|
|
5049
|
+
onNavigate,
|
|
5050
|
+
onBack,
|
|
5051
|
+
width = 80,
|
|
5052
|
+
height = 24,
|
|
5053
|
+
panelMode = false,
|
|
5054
|
+
isInputActive = true
|
|
5055
|
+
}) {
|
|
5056
|
+
const cwd = process.cwd();
|
|
5057
|
+
const scripts = useMemo8(() => readScripts(cwd), [cwd]);
|
|
5058
|
+
const mgr = useMemo8(() => detectPkgManager(cwd), [cwd]);
|
|
5059
|
+
const [selectedIndex, setSelectedIndex] = useState25(0);
|
|
5060
|
+
const [feedback, setFeedback] = useState25();
|
|
5061
|
+
useEffect18(() => {
|
|
5062
|
+
if (feedback) {
|
|
5063
|
+
const timer = setTimeout(() => setFeedback(void 0), 3e3);
|
|
5064
|
+
return () => clearTimeout(timer);
|
|
5065
|
+
}
|
|
5066
|
+
}, [feedback]);
|
|
5067
|
+
useEffect18(() => {
|
|
5068
|
+
if (selectedIndex >= scripts.length && scripts.length > 0) {
|
|
5069
|
+
setSelectedIndex(scripts.length - 1);
|
|
5070
|
+
}
|
|
5071
|
+
}, [scripts.length, selectedIndex]);
|
|
5072
|
+
useInput11((input2, key) => {
|
|
5073
|
+
if (!isInputActive) return;
|
|
5074
|
+
if (key.escape || key.leftArrow && !key.ctrl) {
|
|
5075
|
+
onBack();
|
|
5076
|
+
return;
|
|
5077
|
+
}
|
|
5078
|
+
if (scripts.length === 0) return;
|
|
5079
|
+
if (key.upArrow || input2 === "k") {
|
|
5080
|
+
setSelectedIndex((i) => Math.max(0, i - 1));
|
|
5081
|
+
return;
|
|
5082
|
+
}
|
|
5083
|
+
if (key.downArrow || input2 === "j") {
|
|
5084
|
+
setSelectedIndex((i) => Math.min(scripts.length - 1, i + 1));
|
|
5085
|
+
return;
|
|
5086
|
+
}
|
|
5087
|
+
if (key.return || key.rightArrow) {
|
|
5088
|
+
const script = scripts[selectedIndex];
|
|
5089
|
+
if (script) {
|
|
5090
|
+
const resolved = resolveToolCommand("pkg", cwd);
|
|
5091
|
+
try {
|
|
5092
|
+
const translated = translateCommand(["run", script.name], mgr.id);
|
|
5093
|
+
onNavigate("command-execution", {
|
|
5094
|
+
tool: "pkg",
|
|
5095
|
+
args: translated.args
|
|
5096
|
+
});
|
|
5097
|
+
} catch {
|
|
5098
|
+
setFeedback(`"run" is not supported by ${mgr.id}`);
|
|
5099
|
+
}
|
|
5100
|
+
}
|
|
5101
|
+
return;
|
|
5102
|
+
}
|
|
5103
|
+
if (input2 === "b") {
|
|
5104
|
+
const script = scripts[selectedIndex];
|
|
5105
|
+
if (script) {
|
|
5106
|
+
try {
|
|
5107
|
+
const translated = translateCommand(["run", script.name], mgr.id);
|
|
5108
|
+
const id = generateProcessId(mgr.command, translated.args);
|
|
5109
|
+
startProcess(id, mgr.command, translated.args, cwd);
|
|
5110
|
+
setFeedback(`Started ${mgr.id} run ${script.name} as background process`);
|
|
5111
|
+
} catch (err) {
|
|
5112
|
+
setFeedback(err instanceof Error ? err.message : "Failed to start process");
|
|
5113
|
+
}
|
|
5114
|
+
}
|
|
5115
|
+
return;
|
|
5116
|
+
}
|
|
5117
|
+
});
|
|
5118
|
+
const contentWidth = Math.max(30, (panelMode ? width - 4 : width) - 2);
|
|
5119
|
+
if (scripts.length === 0) {
|
|
5120
|
+
return /* @__PURE__ */ jsxs30(Box28, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
|
|
5121
|
+
!panelMode && /* @__PURE__ */ jsx31(Box28, { marginBottom: 1, children: /* @__PURE__ */ jsxs30(Text32, { bold: true, color: inkColors.accent, children: [
|
|
5122
|
+
"\u{1F4DC}",
|
|
5123
|
+
" ",
|
|
5124
|
+
mgr.id,
|
|
5125
|
+
" scripts"
|
|
5126
|
+
] }) }),
|
|
5127
|
+
/* @__PURE__ */ jsx31(
|
|
5128
|
+
Box28,
|
|
5129
|
+
{
|
|
5130
|
+
flexDirection: "column",
|
|
5131
|
+
borderStyle: "round",
|
|
5132
|
+
borderColor: panel.borderDim,
|
|
5133
|
+
borderDimColor: true,
|
|
5134
|
+
paddingX: 1,
|
|
5135
|
+
width: contentWidth,
|
|
5136
|
+
children: /* @__PURE__ */ jsx31(Text32, { dimColor: true, children: "No scripts found in package.json" })
|
|
5137
|
+
}
|
|
5138
|
+
),
|
|
5139
|
+
/* @__PURE__ */ jsx31(Box28, { marginTop: 1, gap: 2, children: /* @__PURE__ */ jsx31(Text32, { dimColor: true, children: "Esc:back" }) })
|
|
5140
|
+
] });
|
|
5141
|
+
}
|
|
5142
|
+
const headerHeight = panelMode ? 0 : 2;
|
|
5143
|
+
const footerHeight = 2;
|
|
5144
|
+
const feedbackHeight = feedback ? 2 : 0;
|
|
5145
|
+
const availableHeight = height - headerHeight - footerHeight - feedbackHeight;
|
|
5146
|
+
const itemHeight = 1;
|
|
5147
|
+
const visibleCount = Math.max(1, Math.floor(availableHeight / itemHeight));
|
|
5148
|
+
const windowStart = Math.max(0, Math.min(selectedIndex - Math.floor(visibleCount / 2), scripts.length - visibleCount));
|
|
5149
|
+
const visibleScripts = scripts.slice(windowStart, windowStart + visibleCount);
|
|
5150
|
+
return /* @__PURE__ */ jsxs30(Box28, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
|
|
5151
|
+
!panelMode && /* @__PURE__ */ jsx31(Box28, { marginBottom: 1, children: /* @__PURE__ */ jsxs30(Text32, { bold: true, color: inkColors.accent, children: [
|
|
5152
|
+
"\u{1F4DC}",
|
|
5153
|
+
" ",
|
|
5154
|
+
mgr.id,
|
|
5155
|
+
" scripts"
|
|
5156
|
+
] }) }),
|
|
5157
|
+
feedback && /* @__PURE__ */ jsx31(Box28, { marginBottom: 1, children: /* @__PURE__ */ jsx31(Text32, { color: inkColors.accent, children: feedback }) }),
|
|
5158
|
+
/* @__PURE__ */ jsx31(Box28, { flexDirection: "column", width: contentWidth, children: visibleScripts.map((script) => {
|
|
5159
|
+
const idx = scripts.indexOf(script);
|
|
5160
|
+
const isFocused = idx === selectedIndex;
|
|
5161
|
+
return /* @__PURE__ */ jsxs30(Box28, { gap: 1, children: [
|
|
5162
|
+
/* @__PURE__ */ jsxs30(Text32, { color: isFocused ? inkColors.accent : void 0, bold: isFocused, children: [
|
|
5163
|
+
isFocused ? "\u25B6" : " ",
|
|
5164
|
+
" ",
|
|
5165
|
+
script.name
|
|
5166
|
+
] }),
|
|
5167
|
+
/* @__PURE__ */ jsx31(Text32, { dimColor: true, children: script.command })
|
|
5168
|
+
] }, script.name);
|
|
5169
|
+
}) }),
|
|
5170
|
+
scripts.length > visibleCount && /* @__PURE__ */ jsx31(Box28, { children: /* @__PURE__ */ jsxs30(Text32, { dimColor: true, children: [
|
|
5171
|
+
windowStart > 0 ? "\u25B2 " : " ",
|
|
5172
|
+
windowStart + visibleCount < scripts.length ? "\u25BC " : " ",
|
|
5173
|
+
scripts.length,
|
|
5174
|
+
" scripts"
|
|
5175
|
+
] }) }),
|
|
5176
|
+
/* @__PURE__ */ jsxs30(Box28, { marginTop: 1, gap: 2, children: [
|
|
5177
|
+
/* @__PURE__ */ jsxs30(Text32, { dimColor: true, children: [
|
|
5178
|
+
"\u21B5",
|
|
5179
|
+
":run"
|
|
5180
|
+
] }),
|
|
5181
|
+
/* @__PURE__ */ jsx31(Text32, { dimColor: true, children: "b:background" }),
|
|
5182
|
+
/* @__PURE__ */ jsx31(Text32, { dimColor: true, children: "Esc:back" })
|
|
5183
|
+
] })
|
|
5184
|
+
] });
|
|
5185
|
+
}
|
|
5186
|
+
|
|
5187
|
+
// src/app.tsx
|
|
5188
|
+
import { jsx as jsx32, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
4795
5189
|
function AppClassic() {
|
|
4796
5190
|
const { screen, params, navigate, goBack, goHome } = useNavigation();
|
|
4797
5191
|
const { exit } = useApp();
|
|
@@ -4806,9 +5200,9 @@ function AppClassic() {
|
|
|
4806
5200
|
const renderScreen = () => {
|
|
4807
5201
|
switch (screen) {
|
|
4808
5202
|
case "home":
|
|
4809
|
-
return /* @__PURE__ */
|
|
5203
|
+
return /* @__PURE__ */ jsx32(Home, { onNavigate: navigate, onExit: handleExit, width, height });
|
|
4810
5204
|
case "command-args":
|
|
4811
|
-
return /* @__PURE__ */
|
|
5205
|
+
return /* @__PURE__ */ jsx32(
|
|
4812
5206
|
CommandArgs,
|
|
4813
5207
|
{
|
|
4814
5208
|
command: params.command ?? "",
|
|
@@ -4819,9 +5213,9 @@ function AppClassic() {
|
|
|
4819
5213
|
}
|
|
4820
5214
|
);
|
|
4821
5215
|
case "custom-command":
|
|
4822
|
-
return /* @__PURE__ */
|
|
5216
|
+
return /* @__PURE__ */ jsx32(CustomCommand, { onNavigate: navigate, onBack: goBack, width });
|
|
4823
5217
|
case "flag-selection":
|
|
4824
|
-
return /* @__PURE__ */
|
|
5218
|
+
return /* @__PURE__ */ jsx32(
|
|
4825
5219
|
FlagSelection,
|
|
4826
5220
|
{
|
|
4827
5221
|
args: params.args ?? [],
|
|
@@ -4833,11 +5227,12 @@ function AppClassic() {
|
|
|
4833
5227
|
);
|
|
4834
5228
|
case "confirm-execute":
|
|
4835
5229
|
case "command-execution":
|
|
4836
|
-
return /* @__PURE__ */
|
|
5230
|
+
return /* @__PURE__ */ jsx32(
|
|
4837
5231
|
CommandExecution,
|
|
4838
5232
|
{
|
|
4839
5233
|
args: params.args ?? [],
|
|
4840
5234
|
tool: params.tool,
|
|
5235
|
+
rawCommand: params.rawCommand,
|
|
4841
5236
|
onBack: goBack,
|
|
4842
5237
|
onExit: handleExit,
|
|
4843
5238
|
onRunSuggestion: (sugTool, sugArgs) => {
|
|
@@ -4848,23 +5243,23 @@ function AppClassic() {
|
|
|
4848
5243
|
}
|
|
4849
5244
|
);
|
|
4850
5245
|
case "self-update":
|
|
4851
|
-
return /* @__PURE__ */
|
|
5246
|
+
return /* @__PURE__ */ jsx32(SelfUpdate, { onBack: goBack, onExit: handleExit, width });
|
|
4852
5247
|
case "tool-status":
|
|
4853
|
-
return /* @__PURE__ */
|
|
5248
|
+
return /* @__PURE__ */ jsx32(ToolStatus, { onBack: goBack, onNavigate: navigate, width });
|
|
4854
5249
|
case "mcp-manage":
|
|
4855
|
-
return /* @__PURE__ */
|
|
5250
|
+
return /* @__PURE__ */ jsx32(McpManage, { onBack: goBack, width });
|
|
4856
5251
|
case "process-list":
|
|
4857
|
-
return /* @__PURE__ */
|
|
5252
|
+
return /* @__PURE__ */ jsx32(ProcessList, { onNavigate: navigate, onBack: goBack, width, height });
|
|
4858
5253
|
case "process-logs":
|
|
4859
|
-
return /* @__PURE__ */
|
|
5254
|
+
return /* @__PURE__ */ jsx32(ProcessLogs, { processId: params.processId ?? "", onBack: goBack, width, height });
|
|
4860
5255
|
case "project-config":
|
|
4861
|
-
return /* @__PURE__ */
|
|
5256
|
+
return /* @__PURE__ */ jsx32(ProjectConfig, { onBack: goBack, width });
|
|
4862
5257
|
case "pipeline-list":
|
|
4863
|
-
return /* @__PURE__ */
|
|
5258
|
+
return /* @__PURE__ */ jsx32(PipelineList, { onNavigate: navigate, onBack: goBack, width });
|
|
4864
5259
|
case "pipeline-builder":
|
|
4865
|
-
return /* @__PURE__ */
|
|
5260
|
+
return /* @__PURE__ */ jsx32(PipelineBuilder, { onBack: goBack, width, height });
|
|
4866
5261
|
case "pipeline-execution":
|
|
4867
|
-
return /* @__PURE__ */
|
|
5262
|
+
return /* @__PURE__ */ jsx32(
|
|
4868
5263
|
PipelineExecution,
|
|
4869
5264
|
{
|
|
4870
5265
|
pipelineId: params.pipelineId ?? "",
|
|
@@ -4874,32 +5269,34 @@ function AppClassic() {
|
|
|
4874
5269
|
}
|
|
4875
5270
|
);
|
|
4876
5271
|
case "declarative-plan":
|
|
4877
|
-
return /* @__PURE__ */
|
|
5272
|
+
return /* @__PURE__ */ jsx32(DeclarativePlan, { onBack: goBack, onNavigate: navigate, width, height });
|
|
4878
5273
|
case "declarative-status":
|
|
4879
|
-
return /* @__PURE__ */
|
|
5274
|
+
return /* @__PURE__ */ jsx32(DeclarativeStatus, { onBack: goBack, width, height });
|
|
4880
5275
|
case "init-scaffold":
|
|
4881
|
-
return /* @__PURE__ */
|
|
5276
|
+
return /* @__PURE__ */ jsx32(InitScaffold, { onBack: goBack, onNavigate: navigate, width, height });
|
|
5277
|
+
case "script-picker":
|
|
5278
|
+
return /* @__PURE__ */ jsx32(ScriptPicker, { onNavigate: navigate, onBack: goBack, width, height });
|
|
4882
5279
|
default:
|
|
4883
|
-
return /* @__PURE__ */
|
|
5280
|
+
return /* @__PURE__ */ jsx32(Box29, { children: /* @__PURE__ */ jsxs31(Text33, { color: "red", children: [
|
|
4884
5281
|
"Unknown screen: ",
|
|
4885
5282
|
screen
|
|
4886
5283
|
] }) });
|
|
4887
5284
|
}
|
|
4888
5285
|
};
|
|
4889
|
-
return /* @__PURE__ */
|
|
4890
|
-
/* @__PURE__ */
|
|
5286
|
+
return /* @__PURE__ */ jsxs31(Box29, { flexDirection: "column", children: [
|
|
5287
|
+
/* @__PURE__ */ jsx32(GhostBanner, { width }),
|
|
4891
5288
|
renderScreen()
|
|
4892
5289
|
] });
|
|
4893
5290
|
}
|
|
4894
5291
|
|
|
4895
5292
|
// src/appPanel.tsx
|
|
4896
|
-
import
|
|
4897
|
-
import { Box as
|
|
5293
|
+
import React27 from "react";
|
|
5294
|
+
import { Box as Box38, Text as Text40, useApp as useApp2, useInput as useInput13 } from "ink";
|
|
4898
5295
|
|
|
4899
5296
|
// src/hooks/usePanelNavigation.ts
|
|
4900
|
-
import { useState as
|
|
5297
|
+
import { useState as useState26, useCallback as useCallback8 } from "react";
|
|
4901
5298
|
function usePanelNavigation() {
|
|
4902
|
-
const [state, setState] =
|
|
5299
|
+
const [state, setState] = useState26({
|
|
4903
5300
|
view: "pipelines",
|
|
4904
5301
|
featureId: "database",
|
|
4905
5302
|
innerScreen: "home",
|
|
@@ -4937,6 +5334,7 @@ function usePanelNavigation() {
|
|
|
4937
5334
|
config: "config",
|
|
4938
5335
|
"self-update": "self-update",
|
|
4939
5336
|
processes: "processes",
|
|
5337
|
+
scripts: "scripts",
|
|
4940
5338
|
declarative: "declarative"
|
|
4941
5339
|
};
|
|
4942
5340
|
const view = viewMap[itemId];
|
|
@@ -5004,9 +5402,9 @@ function usePanelNavigation() {
|
|
|
5004
5402
|
}
|
|
5005
5403
|
|
|
5006
5404
|
// src/hooks/usePanelFocus.ts
|
|
5007
|
-
import { useState as
|
|
5405
|
+
import { useState as useState27, useCallback as useCallback9 } from "react";
|
|
5008
5406
|
function usePanelFocus() {
|
|
5009
|
-
const [focused, setFocused] =
|
|
5407
|
+
const [focused, setFocused] = useState27("sidebar");
|
|
5010
5408
|
const toggleFocus = useCallback9(() => {
|
|
5011
5409
|
setFocused((prev) => prev === "sidebar" ? "main" : "sidebar");
|
|
5012
5410
|
}, []);
|
|
@@ -5023,15 +5421,16 @@ function usePanelFocus() {
|
|
|
5023
5421
|
}
|
|
5024
5422
|
|
|
5025
5423
|
// src/hooks/useSidebarItems.ts
|
|
5026
|
-
import { useMemo as
|
|
5424
|
+
import { useMemo as useMemo9 } from "react";
|
|
5027
5425
|
function useSidebarItems() {
|
|
5028
|
-
return
|
|
5426
|
+
return useMemo9(() => {
|
|
5029
5427
|
const items = [];
|
|
5030
5428
|
items.push({ id: "__sep_workflows__", label: "---", icon: "", type: "separator", sectionTitle: "Workflows" });
|
|
5031
5429
|
items.push({ id: "pipelines", label: "Pipelines", icon: "\u{1F517}", type: "action", section: "workflows" });
|
|
5032
5430
|
items.push({ id: "pinned", label: "Pinned", icon: "\u{1F4CC}", type: "action", section: "workflows" });
|
|
5033
5431
|
items.push({ id: "custom-command", label: "Custom Cmd", icon: "\u270F\uFE0F", type: "action", section: "workflows" });
|
|
5034
5432
|
items.push({ id: "processes", label: "Processes", icon: "\u{1F4BB}", type: "action", section: "workflows" });
|
|
5433
|
+
items.push({ id: "scripts", label: "Scripts", icon: "\u{1F4DC}", type: "action", section: "workflows" });
|
|
5035
5434
|
items.push({ id: "__sep_features__", label: "---", icon: "", type: "separator", sectionTitle: "Features" });
|
|
5036
5435
|
for (const feature of features) {
|
|
5037
5436
|
items.push({
|
|
@@ -5052,9 +5451,9 @@ function useSidebarItems() {
|
|
|
5052
5451
|
}
|
|
5053
5452
|
|
|
5054
5453
|
// src/hooks/useModal.ts
|
|
5055
|
-
import { useState as
|
|
5454
|
+
import { useState as useState28, useCallback as useCallback10 } from "react";
|
|
5056
5455
|
function useModal() {
|
|
5057
|
-
const [state, setState] =
|
|
5456
|
+
const [state, setState] = useState28(null);
|
|
5058
5457
|
const openModal = useCallback10((content, title) => {
|
|
5059
5458
|
setState({ content, title });
|
|
5060
5459
|
}, []);
|
|
@@ -5071,8 +5470,8 @@ function useModal() {
|
|
|
5071
5470
|
}
|
|
5072
5471
|
|
|
5073
5472
|
// src/components/PanelLayout.tsx
|
|
5074
|
-
import { Box as
|
|
5075
|
-
import { jsx as
|
|
5473
|
+
import { Box as Box30 } from "ink";
|
|
5474
|
+
import { jsx as jsx33, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
5076
5475
|
function PanelLayout({
|
|
5077
5476
|
header,
|
|
5078
5477
|
footer,
|
|
@@ -5087,19 +5486,19 @@ function PanelLayout({
|
|
|
5087
5486
|
const contentHeight = Math.max(5, height - bannerHeight - footerHeight);
|
|
5088
5487
|
const sidebarWidth = singlePanel ? 0 : panel.sidebarWidth(width);
|
|
5089
5488
|
const mainWidth = singlePanel ? width : width - sidebarWidth;
|
|
5090
|
-
return /* @__PURE__ */
|
|
5489
|
+
return /* @__PURE__ */ jsxs32(Box30, { flexDirection: "column", width, height, children: [
|
|
5091
5490
|
header,
|
|
5092
|
-
/* @__PURE__ */
|
|
5093
|
-
!singlePanel && /* @__PURE__ */
|
|
5094
|
-
/* @__PURE__ */
|
|
5491
|
+
/* @__PURE__ */ jsxs32(Box30, { flexDirection: "row", height: contentHeight, children: [
|
|
5492
|
+
!singlePanel && /* @__PURE__ */ jsx33(Box30, { width: sidebarWidth, height: contentHeight, children: sidebar }),
|
|
5493
|
+
/* @__PURE__ */ jsx33(Box30, { width: mainWidth, height: contentHeight, children: main2 })
|
|
5095
5494
|
] }),
|
|
5096
|
-
/* @__PURE__ */
|
|
5495
|
+
/* @__PURE__ */ jsx33(Box30, { height: footerHeight, children: footer })
|
|
5097
5496
|
] });
|
|
5098
5497
|
}
|
|
5099
5498
|
|
|
5100
5499
|
// src/components/Panel.tsx
|
|
5101
|
-
import { Box as
|
|
5102
|
-
import { jsx as
|
|
5500
|
+
import { Box as Box31, Text as Text34 } from "ink";
|
|
5501
|
+
import { jsx as jsx34, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
5103
5502
|
function Panel({
|
|
5104
5503
|
id,
|
|
5105
5504
|
title,
|
|
@@ -5109,8 +5508,8 @@ function Panel({
|
|
|
5109
5508
|
children
|
|
5110
5509
|
}) {
|
|
5111
5510
|
const borderColor = focused ? panel.borderFocused : panel.borderDim;
|
|
5112
|
-
return /* @__PURE__ */
|
|
5113
|
-
|
|
5511
|
+
return /* @__PURE__ */ jsxs33(
|
|
5512
|
+
Box31,
|
|
5114
5513
|
{
|
|
5115
5514
|
flexDirection: "column",
|
|
5116
5515
|
width,
|
|
@@ -5119,21 +5518,21 @@ function Panel({
|
|
|
5119
5518
|
borderColor,
|
|
5120
5519
|
overflow: "hidden",
|
|
5121
5520
|
children: [
|
|
5122
|
-
title && /* @__PURE__ */
|
|
5521
|
+
title && /* @__PURE__ */ jsx34(Box31, { marginBottom: 0, children: /* @__PURE__ */ jsxs33(Text34, { color: focused ? inkColors.accent : void 0, bold: focused, dimColor: !focused, children: [
|
|
5123
5522
|
" ",
|
|
5124
5523
|
title,
|
|
5125
5524
|
" "
|
|
5126
5525
|
] }) }),
|
|
5127
|
-
/* @__PURE__ */
|
|
5526
|
+
/* @__PURE__ */ jsx34(Box31, { flexDirection: "column", flexGrow: 1, overflow: "hidden", children })
|
|
5128
5527
|
]
|
|
5129
5528
|
}
|
|
5130
5529
|
);
|
|
5131
5530
|
}
|
|
5132
5531
|
|
|
5133
5532
|
// src/components/Sidebar.tsx
|
|
5134
|
-
import { useEffect as
|
|
5135
|
-
import { Box as
|
|
5136
|
-
import { jsx as
|
|
5533
|
+
import { useEffect as useEffect19, useMemo as useMemo10, useState as useState29 } from "react";
|
|
5534
|
+
import { Box as Box32, Text as Text35, useInput as useInput12 } from "ink";
|
|
5535
|
+
import { jsx as jsx35, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
5137
5536
|
function groupSections(items) {
|
|
5138
5537
|
const groups = [];
|
|
5139
5538
|
let current = null;
|
|
@@ -5155,18 +5554,18 @@ function Sidebar({
|
|
|
5155
5554
|
onSelect,
|
|
5156
5555
|
onHighlight
|
|
5157
5556
|
}) {
|
|
5158
|
-
const selectableItems =
|
|
5557
|
+
const selectableItems = useMemo10(
|
|
5159
5558
|
() => items.filter((item) => item.type !== "separator"),
|
|
5160
5559
|
[items]
|
|
5161
5560
|
);
|
|
5162
5561
|
const selectedIdx = selectableItems.findIndex((item) => item.id === selectedId);
|
|
5163
|
-
const [cursorIdx, setCursorIdx] =
|
|
5164
|
-
const sections =
|
|
5165
|
-
|
|
5562
|
+
const [cursorIdx, setCursorIdx] = useState29(Math.max(0, selectedIdx));
|
|
5563
|
+
const sections = useMemo10(() => groupSections(items), [items]);
|
|
5564
|
+
useEffect19(() => {
|
|
5166
5565
|
const idx = selectableItems.findIndex((item) => item.id === selectedId);
|
|
5167
5566
|
if (idx >= 0) setCursorIdx(idx);
|
|
5168
5567
|
}, [selectedId, selectableItems]);
|
|
5169
|
-
|
|
5568
|
+
useInput12(
|
|
5170
5569
|
(input2, key) => {
|
|
5171
5570
|
if (key.upArrow || input2 === "k") {
|
|
5172
5571
|
setCursorIdx((prev) => {
|
|
@@ -5194,28 +5593,28 @@ function Sidebar({
|
|
|
5194
5593
|
{ isActive: isFocused }
|
|
5195
5594
|
);
|
|
5196
5595
|
let flatIdx = 0;
|
|
5197
|
-
return /* @__PURE__ */
|
|
5596
|
+
return /* @__PURE__ */ jsx35(Box32, { flexDirection: "column", gap: 0, children: sections.map((section) => {
|
|
5198
5597
|
const sectionStartIdx = flatIdx;
|
|
5199
5598
|
const sectionEndIdx = sectionStartIdx + section.items.length - 1;
|
|
5200
5599
|
const hasCursorInSection = isFocused && cursorIdx >= sectionStartIdx && cursorIdx <= sectionEndIdx;
|
|
5201
5600
|
const hasActiveInSection = section.items.some((item) => item.id === selectedId);
|
|
5202
5601
|
const borderColor = hasCursorInSection || hasActiveInSection ? inkColors.accent : "#555555";
|
|
5203
|
-
const rendered = /* @__PURE__ */
|
|
5204
|
-
|
|
5602
|
+
const rendered = /* @__PURE__ */ jsxs34(
|
|
5603
|
+
Box32,
|
|
5205
5604
|
{
|
|
5206
5605
|
flexDirection: "column",
|
|
5207
5606
|
borderStyle: "round",
|
|
5208
5607
|
borderColor,
|
|
5209
5608
|
paddingX: 1,
|
|
5210
5609
|
children: [
|
|
5211
|
-
/* @__PURE__ */
|
|
5610
|
+
/* @__PURE__ */ jsx35(Text35, { dimColor: true, bold: true, children: section.title }),
|
|
5212
5611
|
section.items.map((item) => {
|
|
5213
5612
|
const thisIdx = flatIdx;
|
|
5214
5613
|
flatIdx++;
|
|
5215
5614
|
const isCursor = isFocused && thisIdx === cursorIdx;
|
|
5216
5615
|
const isActive = item.id === selectedId;
|
|
5217
|
-
return /* @__PURE__ */
|
|
5218
|
-
|
|
5616
|
+
return /* @__PURE__ */ jsx35(Box32, { gap: 0, children: /* @__PURE__ */ jsxs34(
|
|
5617
|
+
Text35,
|
|
5219
5618
|
{
|
|
5220
5619
|
color: isCursor ? inkColors.accent : isActive ? inkColors.accent : void 0,
|
|
5221
5620
|
bold: isCursor || isActive,
|
|
@@ -5238,12 +5637,12 @@ function Sidebar({
|
|
|
5238
5637
|
}
|
|
5239
5638
|
|
|
5240
5639
|
// src/components/PanelFooter.tsx
|
|
5241
|
-
import { Box as
|
|
5242
|
-
import { jsx as
|
|
5640
|
+
import { Box as Box33, Text as Text36 } from "ink";
|
|
5641
|
+
import { jsx as jsx36, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
5243
5642
|
function PanelFooter({ hints, width }) {
|
|
5244
|
-
return /* @__PURE__ */
|
|
5245
|
-
/* @__PURE__ */
|
|
5246
|
-
/* @__PURE__ */
|
|
5643
|
+
return /* @__PURE__ */ jsx36(Box33, { width, children: /* @__PURE__ */ jsx36(Box33, { gap: 1, children: hints.map((hint) => /* @__PURE__ */ jsxs35(Box33, { gap: 0, children: [
|
|
5644
|
+
/* @__PURE__ */ jsx36(Text36, { color: inkColors.accent, bold: true, children: hint.key }),
|
|
5645
|
+
/* @__PURE__ */ jsxs35(Text36, { dimColor: true, children: [
|
|
5247
5646
|
":",
|
|
5248
5647
|
hint.action
|
|
5249
5648
|
] })
|
|
@@ -5251,8 +5650,8 @@ function PanelFooter({ hints, width }) {
|
|
|
5251
5650
|
}
|
|
5252
5651
|
|
|
5253
5652
|
// src/components/Modal.tsx
|
|
5254
|
-
import { Box as
|
|
5255
|
-
import { jsx as
|
|
5653
|
+
import { Box as Box34, Text as Text37 } from "ink";
|
|
5654
|
+
import { jsx as jsx37, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
5256
5655
|
function Modal({
|
|
5257
5656
|
title,
|
|
5258
5657
|
width,
|
|
@@ -5263,10 +5662,10 @@ function Modal({
|
|
|
5263
5662
|
const modalHeight = Math.min(height - 4, 20);
|
|
5264
5663
|
const padX = Math.max(0, Math.floor((width - modalWidth) / 2));
|
|
5265
5664
|
const padY = Math.max(0, Math.floor((height - modalHeight) / 2));
|
|
5266
|
-
return /* @__PURE__ */
|
|
5267
|
-
padY > 0 && /* @__PURE__ */
|
|
5268
|
-
/* @__PURE__ */
|
|
5269
|
-
|
|
5665
|
+
return /* @__PURE__ */ jsxs36(Box34, { flexDirection: "column", width, height, children: [
|
|
5666
|
+
padY > 0 && /* @__PURE__ */ jsx37(Box34, { height: padY }),
|
|
5667
|
+
/* @__PURE__ */ jsx37(Box34, { marginLeft: padX, children: /* @__PURE__ */ jsxs36(
|
|
5668
|
+
Box34,
|
|
5270
5669
|
{
|
|
5271
5670
|
flexDirection: "column",
|
|
5272
5671
|
width: modalWidth,
|
|
@@ -5275,8 +5674,8 @@ function Modal({
|
|
|
5275
5674
|
borderColor: inkColors.accent,
|
|
5276
5675
|
paddingX: 1,
|
|
5277
5676
|
children: [
|
|
5278
|
-
/* @__PURE__ */
|
|
5279
|
-
/* @__PURE__ */
|
|
5677
|
+
/* @__PURE__ */ jsx37(Box34, { marginBottom: 1, children: /* @__PURE__ */ jsx37(Text37, { color: inkColors.accent, bold: true, children: title }) }),
|
|
5678
|
+
/* @__PURE__ */ jsx37(Box34, { flexDirection: "column", flexGrow: 1, overflow: "hidden", children })
|
|
5280
5679
|
]
|
|
5281
5680
|
}
|
|
5282
5681
|
) })
|
|
@@ -5284,9 +5683,9 @@ function Modal({
|
|
|
5284
5683
|
}
|
|
5285
5684
|
|
|
5286
5685
|
// src/components/FeatureCommands.tsx
|
|
5287
|
-
import { useEffect as
|
|
5288
|
-
import { Box as
|
|
5289
|
-
import { jsx as
|
|
5686
|
+
import { useEffect as useEffect20, useMemo as useMemo11, useState as useState30 } from "react";
|
|
5687
|
+
import { Box as Box35, Text as Text38 } from "ink";
|
|
5688
|
+
import { jsx as jsx38, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
5290
5689
|
function FeatureCommands({
|
|
5291
5690
|
feature,
|
|
5292
5691
|
onNavigate,
|
|
@@ -5297,15 +5696,15 @@ function FeatureCommands({
|
|
|
5297
5696
|
height = 24,
|
|
5298
5697
|
isInputActive = true
|
|
5299
5698
|
}) {
|
|
5300
|
-
const [pinnedCommands, setPinnedCommands2] =
|
|
5301
|
-
const [pinnedRuns, setPinnedRuns2] =
|
|
5302
|
-
const [pinFeedback, setPinFeedback] =
|
|
5303
|
-
|
|
5699
|
+
const [pinnedCommands, setPinnedCommands2] = useState30(() => getPinnedCommands());
|
|
5700
|
+
const [pinnedRuns, setPinnedRuns2] = useState30(() => getPinnedRuns());
|
|
5701
|
+
const [pinFeedback, setPinFeedback] = useState30();
|
|
5702
|
+
useEffect20(() => {
|
|
5304
5703
|
if (!pinFeedback) return;
|
|
5305
5704
|
const timeout = setTimeout(() => setPinFeedback(void 0), 1400);
|
|
5306
5705
|
return () => clearTimeout(timeout);
|
|
5307
5706
|
}, [pinFeedback]);
|
|
5308
|
-
const items =
|
|
5707
|
+
const items = useMemo11(
|
|
5309
5708
|
() => buildHomeItems({
|
|
5310
5709
|
activeFeature: feature,
|
|
5311
5710
|
pinnedCommands,
|
|
@@ -5315,8 +5714,8 @@ function FeatureCommands({
|
|
|
5315
5714
|
}),
|
|
5316
5715
|
[feature, pinnedCommands, pinnedRuns]
|
|
5317
5716
|
);
|
|
5318
|
-
const pinnedCommandSet =
|
|
5319
|
-
const pinnedRunSet =
|
|
5717
|
+
const pinnedCommandSet = useMemo11(() => new Set(pinnedCommands), [pinnedCommands]);
|
|
5718
|
+
const pinnedRunSet = useMemo11(() => new Set(pinnedRuns), [pinnedRuns]);
|
|
5320
5719
|
const refreshPins = () => {
|
|
5321
5720
|
setPinnedCommands2(getPinnedCommands());
|
|
5322
5721
|
setPinnedRuns2(getPinnedRuns());
|
|
@@ -5368,12 +5767,12 @@ function FeatureCommands({
|
|
|
5368
5767
|
);
|
|
5369
5768
|
}
|
|
5370
5769
|
};
|
|
5371
|
-
return /* @__PURE__ */
|
|
5372
|
-
pinFeedback && /* @__PURE__ */
|
|
5770
|
+
return /* @__PURE__ */ jsxs37(Box35, { flexDirection: "column", paddingX: 1, children: [
|
|
5771
|
+
pinFeedback && /* @__PURE__ */ jsx38(Box35, { marginBottom: 1, children: /* @__PURE__ */ jsxs37(Text38, { color: inkColors.accent, children: [
|
|
5373
5772
|
"\u2713 ",
|
|
5374
5773
|
pinFeedback
|
|
5375
5774
|
] }) }),
|
|
5376
|
-
/* @__PURE__ */
|
|
5775
|
+
/* @__PURE__ */ jsx38(
|
|
5377
5776
|
SelectList,
|
|
5378
5777
|
{
|
|
5379
5778
|
items,
|
|
@@ -5392,9 +5791,9 @@ function FeatureCommands({
|
|
|
5392
5791
|
}
|
|
5393
5792
|
|
|
5394
5793
|
// src/components/PinnedCommands.tsx
|
|
5395
|
-
import { useEffect as
|
|
5396
|
-
import { Box as
|
|
5397
|
-
import { jsx as
|
|
5794
|
+
import { useEffect as useEffect21, useMemo as useMemo12, useState as useState31 } from "react";
|
|
5795
|
+
import { Box as Box36, Text as Text39 } from "ink";
|
|
5796
|
+
import { jsx as jsx39, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
5398
5797
|
function PinnedCommands({
|
|
5399
5798
|
onNavigate,
|
|
5400
5799
|
onBack,
|
|
@@ -5403,20 +5802,20 @@ function PinnedCommands({
|
|
|
5403
5802
|
height = 24,
|
|
5404
5803
|
isInputActive = true
|
|
5405
5804
|
}) {
|
|
5406
|
-
const [pinnedCommands, setPinnedCommands2] =
|
|
5407
|
-
const [pinnedRuns, setPinnedRuns2] =
|
|
5408
|
-
const [pinFeedback, setPinFeedback] =
|
|
5409
|
-
|
|
5805
|
+
const [pinnedCommands, setPinnedCommands2] = useState31(() => getPinnedCommands());
|
|
5806
|
+
const [pinnedRuns, setPinnedRuns2] = useState31(() => getPinnedRuns());
|
|
5807
|
+
const [pinFeedback, setPinFeedback] = useState31();
|
|
5808
|
+
useEffect21(() => {
|
|
5410
5809
|
if (!pinFeedback) return;
|
|
5411
5810
|
const timeout = setTimeout(() => setPinFeedback(void 0), 1400);
|
|
5412
5811
|
return () => clearTimeout(timeout);
|
|
5413
5812
|
}, [pinFeedback]);
|
|
5414
|
-
const items =
|
|
5813
|
+
const items = useMemo12(
|
|
5415
5814
|
() => buildPinnedOnlyItems(pinnedCommands, pinnedRuns),
|
|
5416
5815
|
[pinnedCommands, pinnedRuns]
|
|
5417
5816
|
);
|
|
5418
|
-
const pinnedCommandSet =
|
|
5419
|
-
const pinnedRunSet =
|
|
5817
|
+
const pinnedCommandSet = useMemo12(() => new Set(pinnedCommands), [pinnedCommands]);
|
|
5818
|
+
const pinnedRunSet = useMemo12(() => new Set(pinnedRuns), [pinnedRuns]);
|
|
5420
5819
|
const refreshPins = () => {
|
|
5421
5820
|
setPinnedCommands2(getPinnedCommands());
|
|
5422
5821
|
setPinnedRuns2(getPinnedRuns());
|
|
@@ -5468,14 +5867,14 @@ function PinnedCommands({
|
|
|
5468
5867
|
}
|
|
5469
5868
|
};
|
|
5470
5869
|
if (items.length === 0) {
|
|
5471
|
-
return /* @__PURE__ */
|
|
5870
|
+
return /* @__PURE__ */ jsx39(Box36, { flexDirection: "column", paddingX: 1, children: /* @__PURE__ */ jsx39(Text39, { color: "gray", children: "No pinned items. Press p on any command to pin it." }) });
|
|
5472
5871
|
}
|
|
5473
|
-
return /* @__PURE__ */
|
|
5474
|
-
pinFeedback && /* @__PURE__ */
|
|
5872
|
+
return /* @__PURE__ */ jsxs38(Box36, { flexDirection: "column", paddingX: 1, children: [
|
|
5873
|
+
pinFeedback && /* @__PURE__ */ jsx39(Box36, { marginBottom: 1, children: /* @__PURE__ */ jsxs38(Text39, { color: inkColors.accent, children: [
|
|
5475
5874
|
"\u2713 ",
|
|
5476
5875
|
pinFeedback
|
|
5477
5876
|
] }) }),
|
|
5478
|
-
/* @__PURE__ */
|
|
5877
|
+
/* @__PURE__ */ jsx39(
|
|
5479
5878
|
SelectList,
|
|
5480
5879
|
{
|
|
5481
5880
|
items,
|
|
@@ -5494,9 +5893,9 @@ function PinnedCommands({
|
|
|
5494
5893
|
}
|
|
5495
5894
|
|
|
5496
5895
|
// src/screens/DeclarativeHome.tsx
|
|
5497
|
-
import { useMemo as
|
|
5498
|
-
import { Box as
|
|
5499
|
-
import { jsx as
|
|
5896
|
+
import { useMemo as useMemo13 } from "react";
|
|
5897
|
+
import { Box as Box37 } from "ink";
|
|
5898
|
+
import { jsx as jsx40 } from "react/jsx-runtime";
|
|
5500
5899
|
var ITEMS = [
|
|
5501
5900
|
{ value: "declarative-plan", label: "Plan / Apply", hint: "Diff and apply polter.yaml", kind: "action" },
|
|
5502
5901
|
{ value: "declarative-status", label: "Infrastructure Status", hint: "Live state from CLI tools", kind: "action" },
|
|
@@ -5509,11 +5908,11 @@ function DeclarativeHome({
|
|
|
5509
5908
|
height = 24,
|
|
5510
5909
|
isInputActive = true
|
|
5511
5910
|
}) {
|
|
5512
|
-
const handleSelect =
|
|
5911
|
+
const handleSelect = useMemo13(
|
|
5513
5912
|
() => (value) => onNavigate(value),
|
|
5514
5913
|
[onNavigate]
|
|
5515
5914
|
);
|
|
5516
|
-
return /* @__PURE__ */
|
|
5915
|
+
return /* @__PURE__ */ jsx40(Box37, { flexDirection: "column", paddingX: 1, children: /* @__PURE__ */ jsx40(
|
|
5517
5916
|
SelectList,
|
|
5518
5917
|
{
|
|
5519
5918
|
items: ITEMS,
|
|
@@ -5529,7 +5928,7 @@ function DeclarativeHome({
|
|
|
5529
5928
|
}
|
|
5530
5929
|
|
|
5531
5930
|
// src/appPanel.tsx
|
|
5532
|
-
import { jsx as
|
|
5931
|
+
import { jsx as jsx41, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
5533
5932
|
var screenLabels = {
|
|
5534
5933
|
"command-args": "Args",
|
|
5535
5934
|
"flag-selection": "Flags",
|
|
@@ -5547,7 +5946,8 @@ var screenLabels = {
|
|
|
5547
5946
|
"process-logs": "Logs",
|
|
5548
5947
|
"declarative-plan": "Plan/Apply",
|
|
5549
5948
|
"declarative-status": "Status",
|
|
5550
|
-
"init-scaffold": "Init"
|
|
5949
|
+
"init-scaffold": "Init",
|
|
5950
|
+
"script-picker": "Scripts"
|
|
5551
5951
|
};
|
|
5552
5952
|
function buildBreadcrumb(nav) {
|
|
5553
5953
|
let base;
|
|
@@ -5578,6 +5978,9 @@ function buildBreadcrumb(nav) {
|
|
|
5578
5978
|
case "processes":
|
|
5579
5979
|
base = "\u{1F4BB} Processes";
|
|
5580
5980
|
break;
|
|
5981
|
+
case "scripts":
|
|
5982
|
+
base = "\u{1F4DC} Scripts";
|
|
5983
|
+
break;
|
|
5581
5984
|
case "declarative":
|
|
5582
5985
|
base = "\u{1F3D7}\uFE0F Infrastructure";
|
|
5583
5986
|
break;
|
|
@@ -5613,7 +6016,7 @@ function AppPanel() {
|
|
|
5613
6016
|
const focus = usePanelFocus();
|
|
5614
6017
|
const sidebarItems = useSidebarItems();
|
|
5615
6018
|
const modal = useModal();
|
|
5616
|
-
const refreshPins =
|
|
6019
|
+
const refreshPins = React27.useCallback(() => {
|
|
5617
6020
|
}, []);
|
|
5618
6021
|
const singlePanel = width < 60 || height < 15;
|
|
5619
6022
|
const handleExit = () => {
|
|
@@ -5622,7 +6025,7 @@ function AppPanel() {
|
|
|
5622
6025
|
);
|
|
5623
6026
|
exit();
|
|
5624
6027
|
};
|
|
5625
|
-
|
|
6028
|
+
useInput13((input2, key) => {
|
|
5626
6029
|
if (modal.isOpen) {
|
|
5627
6030
|
if (key.escape || input2 === "q") {
|
|
5628
6031
|
modal.closeModal();
|
|
@@ -5647,37 +6050,37 @@ function AppPanel() {
|
|
|
5647
6050
|
}
|
|
5648
6051
|
if (input2 === "?") {
|
|
5649
6052
|
modal.openModal(
|
|
5650
|
-
/* @__PURE__ */
|
|
5651
|
-
/* @__PURE__ */
|
|
5652
|
-
/* @__PURE__ */
|
|
6053
|
+
/* @__PURE__ */ jsxs39(Box38, { flexDirection: "column", children: [
|
|
6054
|
+
/* @__PURE__ */ jsxs39(Text40, { children: [
|
|
6055
|
+
/* @__PURE__ */ jsx41(Text40, { bold: true, children: "\u2190/\u2192" }),
|
|
5653
6056
|
" Move between sidebar and main panel"
|
|
5654
6057
|
] }),
|
|
5655
|
-
/* @__PURE__ */
|
|
5656
|
-
/* @__PURE__ */
|
|
6058
|
+
/* @__PURE__ */ jsxs39(Text40, { children: [
|
|
6059
|
+
/* @__PURE__ */ jsx41(Text40, { bold: true, children: "Tab" }),
|
|
5657
6060
|
" Toggle sidebar / main panel"
|
|
5658
6061
|
] }),
|
|
5659
|
-
/* @__PURE__ */
|
|
5660
|
-
/* @__PURE__ */
|
|
6062
|
+
/* @__PURE__ */ jsxs39(Text40, { children: [
|
|
6063
|
+
/* @__PURE__ */ jsx41(Text40, { bold: true, children: "j/k" }),
|
|
5661
6064
|
" Navigate up/down"
|
|
5662
6065
|
] }),
|
|
5663
|
-
/* @__PURE__ */
|
|
5664
|
-
/* @__PURE__ */
|
|
6066
|
+
/* @__PURE__ */ jsxs39(Text40, { children: [
|
|
6067
|
+
/* @__PURE__ */ jsx41(Text40, { bold: true, children: "Enter" }),
|
|
5665
6068
|
" Select item"
|
|
5666
6069
|
] }),
|
|
5667
|
-
/* @__PURE__ */
|
|
5668
|
-
/* @__PURE__ */
|
|
6070
|
+
/* @__PURE__ */ jsxs39(Text40, { children: [
|
|
6071
|
+
/* @__PURE__ */ jsx41(Text40, { bold: true, children: "Esc" }),
|
|
5669
6072
|
" Go back (or return to sidebar)"
|
|
5670
6073
|
] }),
|
|
5671
|
-
/* @__PURE__ */
|
|
5672
|
-
/* @__PURE__ */
|
|
6074
|
+
/* @__PURE__ */ jsxs39(Text40, { children: [
|
|
6075
|
+
/* @__PURE__ */ jsx41(Text40, { bold: true, children: "q" }),
|
|
5673
6076
|
" Quit Polter"
|
|
5674
6077
|
] }),
|
|
5675
|
-
/* @__PURE__ */
|
|
5676
|
-
/* @__PURE__ */
|
|
6078
|
+
/* @__PURE__ */ jsxs39(Text40, { children: [
|
|
6079
|
+
/* @__PURE__ */ jsx41(Text40, { bold: true, children: "?" }),
|
|
5677
6080
|
" Show this help"
|
|
5678
6081
|
] }),
|
|
5679
|
-
/* @__PURE__ */
|
|
5680
|
-
/* @__PURE__ */
|
|
6082
|
+
/* @__PURE__ */ jsxs39(Text40, { children: [
|
|
6083
|
+
/* @__PURE__ */ jsx41(Text40, { bold: true, children: "p" }),
|
|
5681
6084
|
" Pin/unpin command"
|
|
5682
6085
|
] })
|
|
5683
6086
|
] }),
|
|
@@ -5703,6 +6106,8 @@ function AppPanel() {
|
|
|
5703
6106
|
return "self-update";
|
|
5704
6107
|
case "processes":
|
|
5705
6108
|
return "processes";
|
|
6109
|
+
case "scripts":
|
|
6110
|
+
return "scripts";
|
|
5706
6111
|
case "declarative":
|
|
5707
6112
|
return "declarative";
|
|
5708
6113
|
default:
|
|
@@ -5731,7 +6136,7 @@ function AppPanel() {
|
|
|
5731
6136
|
}
|
|
5732
6137
|
switch (nav.view) {
|
|
5733
6138
|
case "pinned":
|
|
5734
|
-
return /* @__PURE__ */
|
|
6139
|
+
return /* @__PURE__ */ jsx41(
|
|
5735
6140
|
PinnedCommands,
|
|
5736
6141
|
{
|
|
5737
6142
|
onNavigate: nav.navigateInner,
|
|
@@ -5745,12 +6150,12 @@ function AppPanel() {
|
|
|
5745
6150
|
case "feature": {
|
|
5746
6151
|
const feature = getFeatureById(nav.featureId);
|
|
5747
6152
|
if (!feature) {
|
|
5748
|
-
return /* @__PURE__ */
|
|
6153
|
+
return /* @__PURE__ */ jsxs39(Text40, { color: "red", children: [
|
|
5749
6154
|
"Feature not found: ",
|
|
5750
6155
|
nav.featureId
|
|
5751
6156
|
] });
|
|
5752
6157
|
}
|
|
5753
|
-
return /* @__PURE__ */
|
|
6158
|
+
return /* @__PURE__ */ jsx41(
|
|
5754
6159
|
FeatureCommands,
|
|
5755
6160
|
{
|
|
5756
6161
|
feature,
|
|
@@ -5765,7 +6170,7 @@ function AppPanel() {
|
|
|
5765
6170
|
);
|
|
5766
6171
|
}
|
|
5767
6172
|
case "custom-command":
|
|
5768
|
-
return /* @__PURE__ */
|
|
6173
|
+
return /* @__PURE__ */ jsx41(
|
|
5769
6174
|
CustomCommand,
|
|
5770
6175
|
{
|
|
5771
6176
|
onNavigate: nav.navigateInner,
|
|
@@ -5777,7 +6182,7 @@ function AppPanel() {
|
|
|
5777
6182
|
}
|
|
5778
6183
|
);
|
|
5779
6184
|
case "pipelines":
|
|
5780
|
-
return /* @__PURE__ */
|
|
6185
|
+
return /* @__PURE__ */ jsx41(
|
|
5781
6186
|
PipelineList,
|
|
5782
6187
|
{
|
|
5783
6188
|
onNavigate: nav.navigateInner,
|
|
@@ -5789,7 +6194,7 @@ function AppPanel() {
|
|
|
5789
6194
|
}
|
|
5790
6195
|
);
|
|
5791
6196
|
case "tool-status":
|
|
5792
|
-
return /* @__PURE__ */
|
|
6197
|
+
return /* @__PURE__ */ jsx41(
|
|
5793
6198
|
ToolStatus,
|
|
5794
6199
|
{
|
|
5795
6200
|
onBack: focus.focusSidebar,
|
|
@@ -5801,7 +6206,7 @@ function AppPanel() {
|
|
|
5801
6206
|
}
|
|
5802
6207
|
);
|
|
5803
6208
|
case "processes":
|
|
5804
|
-
return /* @__PURE__ */
|
|
6209
|
+
return /* @__PURE__ */ jsx41(
|
|
5805
6210
|
ProcessList,
|
|
5806
6211
|
{
|
|
5807
6212
|
onNavigate: nav.navigateInner,
|
|
@@ -5812,8 +6217,20 @@ function AppPanel() {
|
|
|
5812
6217
|
isInputActive: focus.isMainFocused
|
|
5813
6218
|
}
|
|
5814
6219
|
);
|
|
6220
|
+
case "scripts":
|
|
6221
|
+
return /* @__PURE__ */ jsx41(
|
|
6222
|
+
ScriptPicker,
|
|
6223
|
+
{
|
|
6224
|
+
onNavigate: nav.navigateInner,
|
|
6225
|
+
onBack: focus.focusSidebar,
|
|
6226
|
+
width: mainContentWidth - 2,
|
|
6227
|
+
height: mainContentHeight,
|
|
6228
|
+
panelMode: true,
|
|
6229
|
+
isInputActive: focus.isMainFocused
|
|
6230
|
+
}
|
|
6231
|
+
);
|
|
5815
6232
|
case "declarative":
|
|
5816
|
-
return /* @__PURE__ */
|
|
6233
|
+
return /* @__PURE__ */ jsx41(
|
|
5817
6234
|
DeclarativeHome,
|
|
5818
6235
|
{
|
|
5819
6236
|
onNavigate: nav.navigateInner,
|
|
@@ -5824,7 +6241,7 @@ function AppPanel() {
|
|
|
5824
6241
|
}
|
|
5825
6242
|
);
|
|
5826
6243
|
case "config":
|
|
5827
|
-
return /* @__PURE__ */
|
|
6244
|
+
return /* @__PURE__ */ jsx41(
|
|
5828
6245
|
ProjectConfig,
|
|
5829
6246
|
{
|
|
5830
6247
|
onBack: focus.focusSidebar,
|
|
@@ -5835,7 +6252,7 @@ function AppPanel() {
|
|
|
5835
6252
|
}
|
|
5836
6253
|
);
|
|
5837
6254
|
case "self-update":
|
|
5838
|
-
return /* @__PURE__ */
|
|
6255
|
+
return /* @__PURE__ */ jsx41(
|
|
5839
6256
|
SelfUpdate,
|
|
5840
6257
|
{
|
|
5841
6258
|
onBack: focus.focusSidebar,
|
|
@@ -5847,7 +6264,7 @@ function AppPanel() {
|
|
|
5847
6264
|
}
|
|
5848
6265
|
);
|
|
5849
6266
|
default:
|
|
5850
|
-
return /* @__PURE__ */
|
|
6267
|
+
return /* @__PURE__ */ jsx41(Text40, { children: "Select an item from the sidebar" });
|
|
5851
6268
|
}
|
|
5852
6269
|
};
|
|
5853
6270
|
const renderInnerScreen = () => {
|
|
@@ -5855,7 +6272,7 @@ function AppPanel() {
|
|
|
5855
6272
|
const w = mainContentWidth - 2;
|
|
5856
6273
|
switch (nav.innerScreen) {
|
|
5857
6274
|
case "command-args":
|
|
5858
|
-
return /* @__PURE__ */
|
|
6275
|
+
return /* @__PURE__ */ jsx41(
|
|
5859
6276
|
CommandArgs,
|
|
5860
6277
|
{
|
|
5861
6278
|
command: nav.innerParams.command ?? "",
|
|
@@ -5868,7 +6285,7 @@ function AppPanel() {
|
|
|
5868
6285
|
}
|
|
5869
6286
|
);
|
|
5870
6287
|
case "custom-command":
|
|
5871
|
-
return /* @__PURE__ */
|
|
6288
|
+
return /* @__PURE__ */ jsx41(
|
|
5872
6289
|
CustomCommand,
|
|
5873
6290
|
{
|
|
5874
6291
|
onNavigate: nav.navigateInner,
|
|
@@ -5880,7 +6297,7 @@ function AppPanel() {
|
|
|
5880
6297
|
}
|
|
5881
6298
|
);
|
|
5882
6299
|
case "flag-selection":
|
|
5883
|
-
return /* @__PURE__ */
|
|
6300
|
+
return /* @__PURE__ */ jsx41(
|
|
5884
6301
|
FlagSelection,
|
|
5885
6302
|
{
|
|
5886
6303
|
args: nav.innerParams.args ?? [],
|
|
@@ -5896,11 +6313,12 @@ function AppPanel() {
|
|
|
5896
6313
|
);
|
|
5897
6314
|
case "confirm-execute":
|
|
5898
6315
|
case "command-execution":
|
|
5899
|
-
return /* @__PURE__ */
|
|
6316
|
+
return /* @__PURE__ */ jsx41(
|
|
5900
6317
|
CommandExecution,
|
|
5901
6318
|
{
|
|
5902
6319
|
args: nav.innerParams.args ?? [],
|
|
5903
6320
|
tool: nav.innerParams.tool,
|
|
6321
|
+
rawCommand: nav.innerParams.rawCommand,
|
|
5904
6322
|
interactive: nav.innerParams.interactive,
|
|
5905
6323
|
onBack: nav.goBackInner,
|
|
5906
6324
|
onHome: nav.goHomeInner,
|
|
@@ -5916,7 +6334,7 @@ function AppPanel() {
|
|
|
5916
6334
|
`${nav.view}-${nav.innerParams.tool}-${(nav.innerParams.args ?? []).join("-")}`
|
|
5917
6335
|
);
|
|
5918
6336
|
case "pipeline-list":
|
|
5919
|
-
return /* @__PURE__ */
|
|
6337
|
+
return /* @__PURE__ */ jsx41(
|
|
5920
6338
|
PipelineList,
|
|
5921
6339
|
{
|
|
5922
6340
|
onNavigate: nav.navigateInner,
|
|
@@ -5928,7 +6346,7 @@ function AppPanel() {
|
|
|
5928
6346
|
}
|
|
5929
6347
|
);
|
|
5930
6348
|
case "pipeline-builder":
|
|
5931
|
-
return /* @__PURE__ */
|
|
6349
|
+
return /* @__PURE__ */ jsx41(
|
|
5932
6350
|
PipelineBuilder,
|
|
5933
6351
|
{
|
|
5934
6352
|
onBack: nav.goBackInner,
|
|
@@ -5939,7 +6357,7 @@ function AppPanel() {
|
|
|
5939
6357
|
}
|
|
5940
6358
|
);
|
|
5941
6359
|
case "pipeline-execution":
|
|
5942
|
-
return /* @__PURE__ */
|
|
6360
|
+
return /* @__PURE__ */ jsx41(
|
|
5943
6361
|
PipelineExecution,
|
|
5944
6362
|
{
|
|
5945
6363
|
pipelineId: nav.innerParams.pipelineId ?? "",
|
|
@@ -5951,7 +6369,7 @@ function AppPanel() {
|
|
|
5951
6369
|
}
|
|
5952
6370
|
);
|
|
5953
6371
|
case "self-update":
|
|
5954
|
-
return /* @__PURE__ */
|
|
6372
|
+
return /* @__PURE__ */ jsx41(
|
|
5955
6373
|
SelfUpdate,
|
|
5956
6374
|
{
|
|
5957
6375
|
onBack: nav.goBackInner,
|
|
@@ -5963,7 +6381,7 @@ function AppPanel() {
|
|
|
5963
6381
|
}
|
|
5964
6382
|
);
|
|
5965
6383
|
case "tool-status":
|
|
5966
|
-
return /* @__PURE__ */
|
|
6384
|
+
return /* @__PURE__ */ jsx41(
|
|
5967
6385
|
ToolStatus,
|
|
5968
6386
|
{
|
|
5969
6387
|
onBack: nav.goBackInner,
|
|
@@ -5975,7 +6393,7 @@ function AppPanel() {
|
|
|
5975
6393
|
}
|
|
5976
6394
|
);
|
|
5977
6395
|
case "mcp-manage":
|
|
5978
|
-
return /* @__PURE__ */
|
|
6396
|
+
return /* @__PURE__ */ jsx41(
|
|
5979
6397
|
McpManage,
|
|
5980
6398
|
{
|
|
5981
6399
|
onBack: nav.goBackInner,
|
|
@@ -5986,7 +6404,7 @@ function AppPanel() {
|
|
|
5986
6404
|
}
|
|
5987
6405
|
);
|
|
5988
6406
|
case "process-list":
|
|
5989
|
-
return /* @__PURE__ */
|
|
6407
|
+
return /* @__PURE__ */ jsx41(
|
|
5990
6408
|
ProcessList,
|
|
5991
6409
|
{
|
|
5992
6410
|
onNavigate: nav.navigateInner,
|
|
@@ -5998,7 +6416,7 @@ function AppPanel() {
|
|
|
5998
6416
|
}
|
|
5999
6417
|
);
|
|
6000
6418
|
case "process-logs":
|
|
6001
|
-
return /* @__PURE__ */
|
|
6419
|
+
return /* @__PURE__ */ jsx41(
|
|
6002
6420
|
ProcessLogs,
|
|
6003
6421
|
{
|
|
6004
6422
|
processId: nav.innerParams.processId ?? "",
|
|
@@ -6010,7 +6428,7 @@ function AppPanel() {
|
|
|
6010
6428
|
}
|
|
6011
6429
|
);
|
|
6012
6430
|
case "project-config":
|
|
6013
|
-
return /* @__PURE__ */
|
|
6431
|
+
return /* @__PURE__ */ jsx41(
|
|
6014
6432
|
ProjectConfig,
|
|
6015
6433
|
{
|
|
6016
6434
|
onBack: nav.goBackInner,
|
|
@@ -6021,7 +6439,7 @@ function AppPanel() {
|
|
|
6021
6439
|
}
|
|
6022
6440
|
);
|
|
6023
6441
|
case "declarative-plan":
|
|
6024
|
-
return /* @__PURE__ */
|
|
6442
|
+
return /* @__PURE__ */ jsx41(
|
|
6025
6443
|
DeclarativePlan,
|
|
6026
6444
|
{
|
|
6027
6445
|
onBack: nav.goBackInner,
|
|
@@ -6033,7 +6451,7 @@ function AppPanel() {
|
|
|
6033
6451
|
}
|
|
6034
6452
|
);
|
|
6035
6453
|
case "declarative-status":
|
|
6036
|
-
return /* @__PURE__ */
|
|
6454
|
+
return /* @__PURE__ */ jsx41(
|
|
6037
6455
|
DeclarativeStatus,
|
|
6038
6456
|
{
|
|
6039
6457
|
onBack: nav.goBackInner,
|
|
@@ -6044,7 +6462,7 @@ function AppPanel() {
|
|
|
6044
6462
|
}
|
|
6045
6463
|
);
|
|
6046
6464
|
case "init-scaffold":
|
|
6047
|
-
return /* @__PURE__ */
|
|
6465
|
+
return /* @__PURE__ */ jsx41(
|
|
6048
6466
|
InitScaffold,
|
|
6049
6467
|
{
|
|
6050
6468
|
onBack: nav.goBackInner,
|
|
@@ -6055,18 +6473,30 @@ function AppPanel() {
|
|
|
6055
6473
|
isInputActive: isActive
|
|
6056
6474
|
}
|
|
6057
6475
|
);
|
|
6476
|
+
case "script-picker":
|
|
6477
|
+
return /* @__PURE__ */ jsx41(
|
|
6478
|
+
ScriptPicker,
|
|
6479
|
+
{
|
|
6480
|
+
onNavigate: nav.navigateInner,
|
|
6481
|
+
onBack: nav.goBackInner,
|
|
6482
|
+
width: w,
|
|
6483
|
+
height: mainContentHeight,
|
|
6484
|
+
panelMode: true,
|
|
6485
|
+
isInputActive: isActive
|
|
6486
|
+
}
|
|
6487
|
+
);
|
|
6058
6488
|
default:
|
|
6059
|
-
return /* @__PURE__ */
|
|
6489
|
+
return /* @__PURE__ */ jsxs39(Text40, { color: "red", children: [
|
|
6060
6490
|
"Unknown screen: ",
|
|
6061
6491
|
nav.innerScreen
|
|
6062
6492
|
] });
|
|
6063
6493
|
}
|
|
6064
6494
|
};
|
|
6065
6495
|
if (modal.isOpen) {
|
|
6066
|
-
return /* @__PURE__ */
|
|
6496
|
+
return /* @__PURE__ */ jsx41(Box38, { flexDirection: "column", width, height, children: /* @__PURE__ */ jsx41(Modal, { title: modal.modalTitle, width, height, children: modal.modalContent }) });
|
|
6067
6497
|
}
|
|
6068
|
-
const header = /* @__PURE__ */
|
|
6069
|
-
const sidebar = /* @__PURE__ */
|
|
6498
|
+
const header = /* @__PURE__ */ jsx41(GhostBanner, { width, compact: true });
|
|
6499
|
+
const sidebar = /* @__PURE__ */ jsx41(
|
|
6070
6500
|
Panel,
|
|
6071
6501
|
{
|
|
6072
6502
|
id: "sidebar",
|
|
@@ -6074,7 +6504,7 @@ function AppPanel() {
|
|
|
6074
6504
|
width: Math.max(20, Math.min(35, Math.floor(width * 0.3))),
|
|
6075
6505
|
height: Math.max(5, height - bannerHeight - 1),
|
|
6076
6506
|
focused: focus.isSidebarFocused,
|
|
6077
|
-
children: /* @__PURE__ */
|
|
6507
|
+
children: /* @__PURE__ */ jsx41(
|
|
6078
6508
|
Sidebar,
|
|
6079
6509
|
{
|
|
6080
6510
|
items: sidebarItems,
|
|
@@ -6087,7 +6517,7 @@ function AppPanel() {
|
|
|
6087
6517
|
)
|
|
6088
6518
|
}
|
|
6089
6519
|
);
|
|
6090
|
-
const main2 = /* @__PURE__ */
|
|
6520
|
+
const main2 = /* @__PURE__ */ jsx41(
|
|
6091
6521
|
Panel,
|
|
6092
6522
|
{
|
|
6093
6523
|
id: "main",
|
|
@@ -6098,8 +6528,8 @@ function AppPanel() {
|
|
|
6098
6528
|
children: renderMainContent()
|
|
6099
6529
|
}
|
|
6100
6530
|
);
|
|
6101
|
-
const footer = /* @__PURE__ */
|
|
6102
|
-
return /* @__PURE__ */
|
|
6531
|
+
const footer = /* @__PURE__ */ jsx41(PanelFooter, { hints: footerHints, width });
|
|
6532
|
+
return /* @__PURE__ */ jsx41(
|
|
6103
6533
|
PanelLayout,
|
|
6104
6534
|
{
|
|
6105
6535
|
header,
|
|
@@ -6263,19 +6693,19 @@ function printCliHelp() {
|
|
|
6263
6693
|
import pc3 from "picocolors";
|
|
6264
6694
|
|
|
6265
6695
|
// src/apps/ops.ts
|
|
6266
|
-
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync as writeFileSync2 } from "fs";
|
|
6696
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, rmSync, writeFileSync as writeFileSync2 } from "fs";
|
|
6267
6697
|
import { mkdtemp, readdir, stat } from "fs/promises";
|
|
6268
|
-
import { dirname, join as
|
|
6698
|
+
import { dirname, join as join4, resolve } from "path";
|
|
6269
6699
|
import { tmpdir } from "os";
|
|
6270
6700
|
import pc2 from "picocolors";
|
|
6271
6701
|
|
|
6272
6702
|
// src/apps/bootstrapPaths.ts
|
|
6273
6703
|
import { homedir as homedir2 } from "os";
|
|
6274
|
-
import { join as
|
|
6704
|
+
import { join as join3 } from "path";
|
|
6275
6705
|
function getOpsBootstrapPayloadPath() {
|
|
6276
6706
|
const home = homedir2();
|
|
6277
6707
|
if (process.platform === "darwin") {
|
|
6278
|
-
return
|
|
6708
|
+
return join3(
|
|
6279
6709
|
home,
|
|
6280
6710
|
"Library",
|
|
6281
6711
|
"Application Support",
|
|
@@ -6285,10 +6715,10 @@ function getOpsBootstrapPayloadPath() {
|
|
|
6285
6715
|
);
|
|
6286
6716
|
}
|
|
6287
6717
|
if (process.platform === "win32") {
|
|
6288
|
-
const appData = process.env.APPDATA ??
|
|
6289
|
-
return
|
|
6718
|
+
const appData = process.env.APPDATA ?? join3(home, "AppData", "Roaming");
|
|
6719
|
+
return join3(appData, "ops", "bootstrap", "supabase.json");
|
|
6290
6720
|
}
|
|
6291
|
-
return
|
|
6721
|
+
return join3(home, ".config", "ops", "bootstrap", "supabase.json");
|
|
6292
6722
|
}
|
|
6293
6723
|
|
|
6294
6724
|
// src/apps/opsRelease.ts
|
|
@@ -6560,9 +6990,9 @@ async function promptSelect(label, options, defaultValue) {
|
|
|
6560
6990
|
}
|
|
6561
6991
|
|
|
6562
6992
|
// src/apps/ops.ts
|
|
6563
|
-
var LINK_REF_FILE =
|
|
6993
|
+
var LINK_REF_FILE = join4("supabase", ".temp", "project-ref");
|
|
6564
6994
|
function isOpsProjectRoot(candidate) {
|
|
6565
|
-
return
|
|
6995
|
+
return existsSync2(join4(candidate, "src-tauri", "tauri.conf.json")) && existsSync2(join4(candidate, "supabase", "migrations")) && existsSync2(join4(candidate, "package.json"));
|
|
6566
6996
|
}
|
|
6567
6997
|
function findNearestOpsRoot(startDir) {
|
|
6568
6998
|
let currentDir = resolve(startDir);
|
|
@@ -6570,7 +7000,7 @@ function findNearestOpsRoot(startDir) {
|
|
|
6570
7000
|
if (isOpsProjectRoot(currentDir)) {
|
|
6571
7001
|
return currentDir;
|
|
6572
7002
|
}
|
|
6573
|
-
const siblingCandidate =
|
|
7003
|
+
const siblingCandidate = join4(currentDir, "ops");
|
|
6574
7004
|
if (isOpsProjectRoot(siblingCandidate)) {
|
|
6575
7005
|
return siblingCandidate;
|
|
6576
7006
|
}
|
|
@@ -6582,10 +7012,10 @@ function findNearestOpsRoot(startDir) {
|
|
|
6582
7012
|
}
|
|
6583
7013
|
}
|
|
6584
7014
|
function readEnvFile(envPath) {
|
|
6585
|
-
if (!
|
|
7015
|
+
if (!existsSync2(envPath)) {
|
|
6586
7016
|
return {};
|
|
6587
7017
|
}
|
|
6588
|
-
const content =
|
|
7018
|
+
const content = readFileSync2(envPath, "utf-8");
|
|
6589
7019
|
const entries = {};
|
|
6590
7020
|
for (const line of content.split("\n")) {
|
|
6591
7021
|
const trimmed = line.trim();
|
|
@@ -6616,11 +7046,11 @@ function assertProjectRoot(projectRoot) {
|
|
|
6616
7046
|
return projectRoot;
|
|
6617
7047
|
}
|
|
6618
7048
|
function getLinkedProjectRef(projectRoot) {
|
|
6619
|
-
const refPath =
|
|
6620
|
-
if (!
|
|
7049
|
+
const refPath = join4(projectRoot, LINK_REF_FILE);
|
|
7050
|
+
if (!existsSync2(refPath)) {
|
|
6621
7051
|
return null;
|
|
6622
7052
|
}
|
|
6623
|
-
const value =
|
|
7053
|
+
const value = readFileSync2(refPath, "utf-8").trim();
|
|
6624
7054
|
return value || null;
|
|
6625
7055
|
}
|
|
6626
7056
|
function getDbPasswordArgs() {
|
|
@@ -6674,7 +7104,7 @@ async function ensureSupabaseLink(projectRoot, forceRelink = false) {
|
|
|
6674
7104
|
);
|
|
6675
7105
|
}
|
|
6676
7106
|
async function collectSupabaseConfig(projectRoot) {
|
|
6677
|
-
const envPath = projectRoot ?
|
|
7107
|
+
const envPath = projectRoot ? join4(projectRoot, ".env.local") : void 0;
|
|
6678
7108
|
const currentEnv = envPath ? readEnvFile(envPath) : {};
|
|
6679
7109
|
const currentRef = projectRoot ? getLinkedProjectRef(projectRoot) : null;
|
|
6680
7110
|
const url = await promptText("Supabase URL", {
|
|
@@ -6696,7 +7126,7 @@ async function collectSupabaseConfig(projectRoot) {
|
|
|
6696
7126
|
};
|
|
6697
7127
|
}
|
|
6698
7128
|
function writeOpsEnv(projectRoot, config2) {
|
|
6699
|
-
const envPath =
|
|
7129
|
+
const envPath = join4(projectRoot, ".env.local");
|
|
6700
7130
|
const currentEnv = readEnvFile(envPath);
|
|
6701
7131
|
const nextEnv = {
|
|
6702
7132
|
...currentEnv,
|
|
@@ -6896,7 +7326,7 @@ async function extractArchive(archivePath, outputDir) {
|
|
|
6896
7326
|
async function findFirstAppBundle(dir) {
|
|
6897
7327
|
const entries = await readdir(dir);
|
|
6898
7328
|
for (const entry of entries) {
|
|
6899
|
-
const fullPath =
|
|
7329
|
+
const fullPath = join4(dir, entry);
|
|
6900
7330
|
const entryStat = await stat(fullPath);
|
|
6901
7331
|
if (entryStat.isDirectory() && entry.endsWith(".app")) {
|
|
6902
7332
|
return fullPath;
|
|
@@ -6912,9 +7342,9 @@ async function findFirstAppBundle(dir) {
|
|
|
6912
7342
|
}
|
|
6913
7343
|
async function deployMacosApp(context, options) {
|
|
6914
7344
|
const artifact = await resolveOpsMacosArtifact(context.options);
|
|
6915
|
-
const tempRoot = await mkdtemp(
|
|
6916
|
-
const archivePath =
|
|
6917
|
-
const extractDir =
|
|
7345
|
+
const tempRoot = await mkdtemp(join4(tmpdir(), "polter-ops-"));
|
|
7346
|
+
const archivePath = join4(tempRoot, artifact.fileName);
|
|
7347
|
+
const extractDir = join4(tempRoot, "extract");
|
|
6918
7348
|
mkdirSync(extractDir, { recursive: true });
|
|
6919
7349
|
if (artifact.source === "github-release") {
|
|
6920
7350
|
const releaseLabel = artifact.tagName ?? "latest";
|
|
@@ -6943,13 +7373,13 @@ async function deployMacosApp(context, options) {
|
|
|
6943
7373
|
}
|
|
6944
7374
|
const installDir = context.options.installDir ?? "/Applications";
|
|
6945
7375
|
mkdirSync(installDir, { recursive: true });
|
|
6946
|
-
const destination =
|
|
6947
|
-
if (options.requireExistingInstallation && !
|
|
7376
|
+
const destination = join4(installDir, "ops.app");
|
|
7377
|
+
if (options.requireExistingInstallation && !existsSync2(destination)) {
|
|
6948
7378
|
throw new Error(
|
|
6949
7379
|
`No existing Ops installation was found at ${destination}. Run \`polter app install ops\` first.`
|
|
6950
7380
|
);
|
|
6951
7381
|
}
|
|
6952
|
-
if (
|
|
7382
|
+
if (existsSync2(destination)) {
|
|
6953
7383
|
const confirmed = context.options.yes || await promptConfirm(`Replace existing installation at ${destination}?`, false);
|
|
6954
7384
|
if (!confirmed) {
|
|
6955
7385
|
process.stdout.write(`${pc2.yellow("Cancelled.")}
|
|
@@ -7213,11 +7643,22 @@ Apply completed with ${errors.length} error(s).
|
|
|
7213
7643
|
process.exit(result.exitCode ?? 0);
|
|
7214
7644
|
}
|
|
7215
7645
|
const AppComponent2 = parsed.classic ? AppClassic : AppPanel;
|
|
7216
|
-
|
|
7217
|
-
|
|
7646
|
+
const socketPath2 = getSocketPath();
|
|
7647
|
+
const ipc2 = socketPath2 ? createIpcServer(socketPath2) : null;
|
|
7648
|
+
if (ipc2) await ipc2.start();
|
|
7649
|
+
const inst = render(React28.createElement(AppComponent2));
|
|
7650
|
+
await inst.waitUntilExit();
|
|
7651
|
+
if (ipc2) await ipc2.stop();
|
|
7652
|
+
process.exit(0);
|
|
7218
7653
|
}
|
|
7219
7654
|
const AppComponent = parsed.classic ? AppClassic : AppPanel;
|
|
7220
|
-
|
|
7655
|
+
const socketPath = getSocketPath();
|
|
7656
|
+
const ipc = socketPath ? createIpcServer(socketPath) : null;
|
|
7657
|
+
if (ipc) await ipc.start();
|
|
7658
|
+
const instance = render(React28.createElement(AppComponent));
|
|
7659
|
+
await instance.waitUntilExit();
|
|
7660
|
+
if (ipc) await ipc.stop();
|
|
7661
|
+
process.exit(0);
|
|
7221
7662
|
}
|
|
7222
7663
|
main().catch((error) => {
|
|
7223
7664
|
const message = error instanceof Error ? error.message : String(error);
|