@within-7/minto 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/commands/build.js +74 -0
  2. package/dist/commands/build.js.map +7 -0
  3. package/dist/commands/mcp.js +40 -0
  4. package/dist/commands/mcp.js.map +7 -0
  5. package/dist/commands/mcp_refresh.js +40 -0
  6. package/dist/commands/mcp_refresh.js.map +7 -0
  7. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js +140 -0
  8. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js.map +7 -0
  9. package/dist/components/AskUserQuestionDialog/QuestionView.js +45 -0
  10. package/dist/components/AskUserQuestionDialog/QuestionView.js.map +7 -0
  11. package/dist/components/AskUserQuestionDialog/index.js +7 -0
  12. package/dist/components/AskUserQuestionDialog/index.js.map +7 -0
  13. package/dist/components/TodoPanel.js +2 -3
  14. package/dist/components/TodoPanel.js.map +2 -2
  15. package/dist/entrypoints/cli-wrapper.js +61 -0
  16. package/dist/entrypoints/cli-wrapper.js.map +7 -0
  17. package/dist/entrypoints/cli.js +0 -0
  18. package/dist/hooks/useAskUser.js +24 -0
  19. package/dist/hooks/useAskUser.js.map +7 -0
  20. package/dist/query.js.map +2 -2
  21. package/dist/screens/REPL.js +18 -5
  22. package/dist/screens/REPL.js.map +2 -2
  23. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js +113 -0
  24. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js.map +7 -0
  25. package/dist/tools/AskUserQuestionTool/index.js +5 -0
  26. package/dist/tools/AskUserQuestionTool/index.js.map +7 -0
  27. package/dist/tools/AskUserQuestionTool/prompt.js +167 -0
  28. package/dist/tools/AskUserQuestionTool/prompt.js.map +7 -0
  29. package/dist/tools.js +2 -0
  30. package/dist/tools.js.map +2 -2
  31. package/dist/types/askUserQuestion.js +1 -0
  32. package/dist/types/askUserQuestion.js.map +7 -0
  33. package/dist/version.js +7 -0
  34. package/dist/version.js.map +7 -0
  35. package/package.json +17 -15
  36. package/.npmrc +0 -3
@@ -0,0 +1,74 @@
1
+ import { Box, Text } from "ink";
2
+ import React, { useState, useEffect } from "react";
3
+ import { getTheme } from "../utils/theme.js";
4
+ import { execFileNoThrow } from "../utils/execFileNoThrow.js";
5
+ import Spinner from "ink-spinner";
6
+ const BuildCommand = ({ onDone }) => {
7
+ const theme = getTheme();
8
+ const [status, setStatus] = useState("building");
9
+ const [output, setOutput] = useState([]);
10
+ const [error, setError] = useState("");
11
+ useEffect(() => {
12
+ const runBuildProcess = async () => {
13
+ try {
14
+ setStatus("building");
15
+ setOutput((prev) => [...prev, "\u{1F680} Building Minto..."]);
16
+ const buildResult = await execFileNoThrow("bun", ["run", "build"]);
17
+ if (buildResult.code !== 0) {
18
+ setError(`Build failed: ${buildResult.stderr || buildResult.stdout}`);
19
+ setStatus("error");
20
+ return;
21
+ }
22
+ setOutput((prev) => [...prev, "\u2705 Build completed"]);
23
+ setStatus("linking-bun");
24
+ setOutput((prev) => [...prev, "\u{1F517} Linking with bun..."]);
25
+ const bunLinkResult = await execFileNoThrow("bun", ["link"]);
26
+ if (bunLinkResult.code !== 0) {
27
+ setError(`Bun link failed: ${bunLinkResult.stderr || bunLinkResult.stdout}`);
28
+ setStatus("error");
29
+ return;
30
+ }
31
+ setOutput((prev) => [...prev, "\u2705 Bun link completed"]);
32
+ setStatus("linking-npm");
33
+ setOutput((prev) => [...prev, "\u{1F517} Linking with npm..."]);
34
+ const npmLinkResult = await execFileNoThrow("npm", ["link"]);
35
+ if (npmLinkResult.code !== 0) {
36
+ setError(`npm link failed: ${npmLinkResult.stderr || npmLinkResult.stdout}`);
37
+ setStatus("error");
38
+ return;
39
+ }
40
+ setOutput((prev) => [...prev, "\u2705 npm link completed"]);
41
+ setStatus("success");
42
+ } catch (err) {
43
+ setError(err instanceof Error ? err.message : String(err));
44
+ setStatus("error");
45
+ }
46
+ };
47
+ runBuildProcess();
48
+ }, []);
49
+ useEffect(() => {
50
+ if (status === "success" || status === "error") {
51
+ const timer = setTimeout(() => {
52
+ onDone();
53
+ }, 2e3);
54
+ return () => clearTimeout(timer);
55
+ }
56
+ }, [status, onDone]);
57
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingY: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: theme.primary }, "Build & Link Process")), output.map((line, i) => /* @__PURE__ */ React.createElement(Box, { key: i }, /* @__PURE__ */ React.createElement(Text, null, line))), status !== "success" && status !== "error" && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.info }, /* @__PURE__ */ React.createElement(Spinner, { type: "dots" }), " ", status === "building" && "Building...", status === "linking-bun" && "Linking with bun...", status === "linking-npm" && "Linking with npm...")), status === "success" && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: theme.success }, "\u2728 All steps completed successfully!")), status === "error" && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: theme.error }, "\u274C Error occurred:"), /* @__PURE__ */ React.createElement(Text, { color: theme.error }, error)), (status === "success" || status === "error") && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "Closing in 2 seconds...")));
58
+ };
59
+ const build = {
60
+ name: "build",
61
+ description: "Build the project and link it for local testing (runs: bun run build && bun link && npm link)",
62
+ aliases: ["b"],
63
+ isEnabled: true,
64
+ isHidden: false,
65
+ type: "local-jsx",
66
+ userFacingName: () => "build",
67
+ async call(onDone) {
68
+ return /* @__PURE__ */ React.createElement(BuildCommand, { onDone });
69
+ }
70
+ };
71
+ export {
72
+ build
73
+ };
74
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/build.tsx"],
4
+ "sourcesContent": ["import { Box, Text } from 'ink'\nimport React, { useState, useEffect } from 'react'\nimport { getTheme } from '@utils/theme'\nimport { execFileNoThrow } from '@utils/execFileNoThrow'\nimport Spinner from 'ink-spinner'\nimport type { Command } from '@commands'\n\nconst BuildCommand: React.FC<{ onDone: () => void }> = ({ onDone }) => {\n const theme = getTheme()\n const [status, setStatus] = useState<'building' | 'linking-bun' | 'linking-npm' | 'success' | 'error'>('building')\n const [output, setOutput] = useState<string[]>([])\n const [error, setError] = useState<string>('')\n\n useEffect(() => {\n const runBuildProcess = async () => {\n try {\n // Step 1: Build\n setStatus('building')\n setOutput(prev => [...prev, '\uD83D\uDE80 Building Minto...'])\n\n const buildResult = await execFileNoThrow('bun', ['run', 'build'])\n\n if (buildResult.code !== 0) {\n setError(`Build failed: ${buildResult.stderr || buildResult.stdout}`)\n setStatus('error')\n return\n }\n\n setOutput(prev => [...prev, '\u2705 Build completed'])\n\n // Step 2: Bun link\n setStatus('linking-bun')\n setOutput(prev => [...prev, '\uD83D\uDD17 Linking with bun...'])\n\n const bunLinkResult = await execFileNoThrow('bun', ['link'])\n\n if (bunLinkResult.code !== 0) {\n setError(`Bun link failed: ${bunLinkResult.stderr || bunLinkResult.stdout}`)\n setStatus('error')\n return\n }\n\n setOutput(prev => [...prev, '\u2705 Bun link completed'])\n\n // Step 3: npm link\n setStatus('linking-npm')\n setOutput(prev => [...prev, '\uD83D\uDD17 Linking with npm...'])\n\n const npmLinkResult = await execFileNoThrow('npm', ['link'])\n\n if (npmLinkResult.code !== 0) {\n setError(`npm link failed: ${npmLinkResult.stderr || npmLinkResult.stdout}`)\n setStatus('error')\n return\n }\n\n setOutput(prev => [...prev, '\u2705 npm link completed'])\n setStatus('success')\n\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err))\n setStatus('error')\n }\n }\n\n runBuildProcess()\n }, [])\n\n useEffect(() => {\n if (status === 'success' || status === 'error') {\n // Auto-close after showing result\n const timer = setTimeout(() => {\n onDone()\n }, 2000)\n\n return () => clearTimeout(timer)\n }\n }, [status, onDone])\n\n return (\n <Box flexDirection=\"column\" paddingY={1}>\n <Box marginBottom={1}>\n <Text bold color={theme.primary}>\n Build & Link Process\n </Text>\n </Box>\n\n {output.map((line, i) => (\n <Box key={i}>\n <Text>{line}</Text>\n </Box>\n ))}\n\n {status !== 'success' && status !== 'error' && (\n <Box marginTop={1}>\n <Text color={theme.info}>\n <Spinner type=\"dots\" />\n {' '}\n {status === 'building' && 'Building...'}\n {status === 'linking-bun' && 'Linking with bun...'}\n {status === 'linking-npm' && 'Linking with npm...'}\n </Text>\n </Box>\n )}\n\n {status === 'success' && (\n <Box marginTop={1}>\n <Text bold color={theme.success}>\n \u2728 All steps completed successfully!\n </Text>\n </Box>\n )}\n\n {status === 'error' && (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text bold color={theme.error}>\n \u274C Error occurred:\n </Text>\n <Text color={theme.error}>{error}</Text>\n </Box>\n )}\n\n {(status === 'success' || status === 'error') && (\n <Box marginTop={1}>\n <Text dimColor>\n Closing in 2 seconds...\n </Text>\n </Box>\n )}\n </Box>\n )\n}\n\nexport const build = {\n name: 'build',\n description: 'Build the project and link it for local testing (runs: bun run build && bun link && npm link)',\n aliases: ['b'],\n isEnabled: true,\n isHidden: false,\n type: 'local-jsx',\n userFacingName: () => 'build',\n async call(onDone: (result?: string) => void) {\n return <BuildCommand onDone={onDone} />\n },\n} satisfies Command\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,40 @@
1
+ import { listMCPServers, getClients } from "../services/mcpClient.js";
2
+ import { PRODUCT_COMMAND } from "../constants/product.js";
3
+ import chalk from "chalk";
4
+ import { getTheme } from "../utils/theme.js";
5
+ const mcp = {
6
+ type: "local",
7
+ name: "mcp",
8
+ description: "Show MCP server connection status",
9
+ isEnabled: true,
10
+ isHidden: false,
11
+ async call() {
12
+ const servers = listMCPServers();
13
+ const clients = await getClients();
14
+ const theme = getTheme();
15
+ if (Object.keys(servers).length === 0) {
16
+ return `\u23BF No MCP servers configured. Run \`${PRODUCT_COMMAND} mcp\` to learn about how to configure MCP servers.
17
+ \u23BF To refresh connections after configuration changes, use \`/${PRODUCT_COMMAND} mcp-refresh\``;
18
+ }
19
+ const serverStatusLines = clients.sort((a, b) => a.name.localeCompare(b.name)).map((client) => {
20
+ const isConnected = client.type === "connected";
21
+ const status = isConnected ? "connected" : "disconnected";
22
+ const coloredStatus = isConnected ? chalk.hex(theme.success)(status) : chalk.hex(theme.error)(status);
23
+ return `\u23BF \u2022 ${client.name}: ${coloredStatus}`;
24
+ });
25
+ return [
26
+ "\u23BF MCP Server Status",
27
+ ...serverStatusLines,
28
+ "",
29
+ `\u23BF Tip: Use \`/mcp-refresh\` to reconnect to servers after configuration changes`
30
+ ].join("\n");
31
+ },
32
+ userFacingName() {
33
+ return "mcp";
34
+ }
35
+ };
36
+ var mcp_default = mcp;
37
+ export {
38
+ mcp_default as default
39
+ };
40
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/mcp.ts"],
4
+ "sourcesContent": ["import type { Command } from '@commands'\nimport { listMCPServers, getClients } from '@services/mcpClient'\nimport { PRODUCT_COMMAND } from '@constants/product'\nimport chalk from 'chalk'\nimport { getTheme } from '@utils/theme'\n\nconst mcp = {\n type: 'local',\n name: 'mcp',\n description: 'Show MCP server connection status',\n isEnabled: true,\n isHidden: false,\n async call() {\n const servers = listMCPServers()\n const clients = await getClients()\n const theme = getTheme()\n\n if (Object.keys(servers).length === 0) {\n return `\u23BF No MCP servers configured. Run \\`${PRODUCT_COMMAND} mcp\\` to learn about how to configure MCP servers.\\n\u23BF To refresh connections after configuration changes, use \\`/${PRODUCT_COMMAND} mcp-refresh\\``\n }\n\n // Sort servers by name and format status with colors\n const serverStatusLines = clients\n .sort((a, b) => a.name.localeCompare(b.name))\n .map(client => {\n const isConnected = client.type === 'connected'\n const status = isConnected ? 'connected' : 'disconnected'\n const coloredStatus = isConnected\n ? chalk.hex(theme.success)(status)\n : chalk.hex(theme.error)(status)\n return `\u23BF \u2022 ${client.name}: ${coloredStatus}`\n })\n\n return [\n '\u23BF MCP Server Status',\n ...serverStatusLines,\n '',\n `\u23BF Tip: Use \\`/mcp-refresh\\` to reconnect to servers after configuration changes`,\n ].join('\\n')\n },\n userFacingName() {\n return 'mcp'\n },\n} satisfies Command\n\nexport default mcp\n"],
5
+ "mappings": "AACA,SAAS,gBAAgB,kBAAkB;AAC3C,SAAS,uBAAuB;AAChC,OAAO,WAAW;AAClB,SAAS,gBAAgB;AAEzB,MAAM,MAAM;AAAA,EACV,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,WAAW;AAAA,EACX,UAAU;AAAA,EACV,MAAM,OAAO;AACX,UAAM,UAAU,eAAe;AAC/B,UAAM,UAAU,MAAM,WAAW;AACjC,UAAM,QAAQ,SAAS;AAEvB,QAAI,OAAO,KAAK,OAAO,EAAE,WAAW,GAAG;AACrC,aAAO,4CAAuC,eAAe;AAAA,qEAAsH,eAAe;AAAA,IACpM;AAGA,UAAM,oBAAoB,QACvB,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC,EAC3C,IAAI,YAAU;AACb,YAAM,cAAc,OAAO,SAAS;AACpC,YAAM,SAAS,cAAc,cAAc;AAC3C,YAAM,gBAAgB,cAClB,MAAM,IAAI,MAAM,OAAO,EAAE,MAAM,IAC/B,MAAM,IAAI,MAAM,KAAK,EAAE,MAAM;AACjC,aAAO,kBAAQ,OAAO,IAAI,KAAK,aAAa;AAAA,IAC9C,CAAC;AAEH,WAAO;AAAA,MACL;AAAA,MACA,GAAG;AAAA,MACH;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AAAA,EACA,iBAAiB;AACf,WAAO;AAAA,EACT;AACF;AAEA,IAAO,cAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,40 @@
1
+ import { refreshMCPConnections, getClients } from "../services/mcpClient.js";
2
+ import { PRODUCT_COMMAND } from "../constants/product.js";
3
+ import chalk from "chalk";
4
+ import { getTheme } from "../utils/theme.js";
5
+ const mcpRefresh = {
6
+ type: "local",
7
+ name: "mcp-refresh",
8
+ description: "Refresh MCP server connections (reconnect to all configured servers)",
9
+ isEnabled: true,
10
+ isHidden: false,
11
+ async call() {
12
+ const theme = getTheme();
13
+ refreshMCPConnections();
14
+ await new Promise((resolve) => setTimeout(resolve, 100));
15
+ const clients = await getClients();
16
+ if (clients.length === 0) {
17
+ return `\u23BF No MCP servers configured. Run \`${PRODUCT_COMMAND} mcp\` to learn about how to configure MCP servers.`;
18
+ }
19
+ const serverStatusLines = clients.sort((a, b) => a.name.localeCompare(b.name)).map((client) => {
20
+ const isConnected = client.type === "connected";
21
+ const status = isConnected ? "connected" : "failed";
22
+ const coloredStatus = isConnected ? chalk.hex(theme.success)(status) : chalk.hex(theme.error)(status);
23
+ return `\u23BF \u2022 ${client.name}: ${coloredStatus}`;
24
+ });
25
+ return [
26
+ "\u23BF MCP connections refreshed",
27
+ ...serverStatusLines,
28
+ "",
29
+ "\u23BF Note: You may need to restart the conversation for new tools to be available."
30
+ ].join("\n");
31
+ },
32
+ userFacingName() {
33
+ return "mcp-refresh";
34
+ }
35
+ };
36
+ var mcp_refresh_default = mcpRefresh;
37
+ export {
38
+ mcp_refresh_default as default
39
+ };
40
+ //# sourceMappingURL=mcp_refresh.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/mcp_refresh.ts"],
4
+ "sourcesContent": ["import type { Command } from '@commands'\nimport { refreshMCPConnections, getClients } from '@services/mcpClient'\nimport { PRODUCT_COMMAND } from '@constants/product'\nimport chalk from 'chalk'\nimport { getTheme } from '@utils/theme'\n\nconst mcpRefresh = {\n type: 'local',\n name: 'mcp-refresh',\n description: 'Refresh MCP server connections (reconnect to all configured servers)',\n isEnabled: true,\n isHidden: false,\n async call() {\n const theme = getTheme()\n\n // Clear cache and force reconnection\n refreshMCPConnections()\n\n // Wait a moment for cleanup\n await new Promise(resolve => setTimeout(resolve, 100))\n\n // Get fresh connections\n const clients = await getClients()\n\n if (clients.length === 0) {\n return `\u23BF No MCP servers configured. Run \\`${PRODUCT_COMMAND} mcp\\` to learn about how to configure MCP servers.`\n }\n\n // Sort servers by name and format status with colors\n const serverStatusLines = clients\n .sort((a, b) => a.name.localeCompare(b.name))\n .map(client => {\n const isConnected = client.type === 'connected'\n const status = isConnected ? 'connected' : 'failed'\n const coloredStatus = isConnected\n ? chalk.hex(theme.success)(status)\n : chalk.hex(theme.error)(status)\n return `\u23BF \u2022 ${client.name}: ${coloredStatus}`\n })\n\n return [\n '\u23BF MCP connections refreshed',\n ...serverStatusLines,\n '',\n '\u23BF Note: You may need to restart the conversation for new tools to be available.',\n ].join('\\n')\n },\n userFacingName() {\n return 'mcp-refresh'\n },\n} satisfies Command\n\nexport default mcpRefresh\n"],
5
+ "mappings": "AACA,SAAS,uBAAuB,kBAAkB;AAClD,SAAS,uBAAuB;AAChC,OAAO,WAAW;AAClB,SAAS,gBAAgB;AAEzB,MAAM,aAAa;AAAA,EACjB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,WAAW;AAAA,EACX,UAAU;AAAA,EACV,MAAM,OAAO;AACX,UAAM,QAAQ,SAAS;AAGvB,0BAAsB;AAGtB,UAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,GAAG,CAAC;AAGrD,UAAM,UAAU,MAAM,WAAW;AAEjC,QAAI,QAAQ,WAAW,GAAG;AACxB,aAAO,4CAAuC,eAAe;AAAA,IAC/D;AAGA,UAAM,oBAAoB,QACvB,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC,EAC3C,IAAI,YAAU;AACb,YAAM,cAAc,OAAO,SAAS;AACpC,YAAM,SAAS,cAAc,cAAc;AAC3C,YAAM,gBAAgB,cAClB,MAAM,IAAI,MAAM,OAAO,EAAE,MAAM,IAC/B,MAAM,IAAI,MAAM,KAAK,EAAE,MAAM;AACjC,aAAO,kBAAQ,OAAO,IAAI,KAAK,aAAa;AAAA,IAC9C,CAAC;AAEH,WAAO;AAAA,MACL;AAAA,MACA,GAAG;AAAA,MACH;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AAAA,EACA,iBAAiB;AACf,WAAO;AAAA,EACT;AACF;AAEA,IAAO,sBAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,140 @@
1
+ import { Box, Text, useInput } from "ink";
2
+ import * as React from "react";
3
+ import { useState, useCallback } from "react";
4
+ import { QuestionView } from "./QuestionView.js";
5
+ import { useNotifyAfterTimeout } from "../../hooks/useNotifyAfterTimeout.js";
6
+ import { PRODUCT_NAME } from "../../constants/product.js";
7
+ import TextInput from "ink-text-input";
8
+ function AskUserQuestionDialog({
9
+ context,
10
+ onDone
11
+ }) {
12
+ const { questions, resolve, reject } = context;
13
+ const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
14
+ const [selectedOptions, setSelectedOptions] = useState(
15
+ questions.map(() => 0)
16
+ );
17
+ const [isCustomInputMode, setIsCustomInputMode] = useState(false);
18
+ const [customInput, setCustomInput] = useState("");
19
+ useNotifyAfterTimeout(`${PRODUCT_NAME} needs your input to continue`);
20
+ const currentQuestion = questions[currentQuestionIndex];
21
+ useInput(
22
+ (input, key) => {
23
+ if (key.escape || key.ctrl && input === "c") {
24
+ onDone();
25
+ reject();
26
+ return;
27
+ }
28
+ if (isCustomInputMode) {
29
+ return;
30
+ }
31
+ if (key.leftArrow && currentQuestionIndex > 0) {
32
+ setCurrentQuestionIndex((prev) => prev - 1);
33
+ return;
34
+ }
35
+ if (key.rightArrow && currentQuestionIndex < questions.length - 1) {
36
+ setCurrentQuestionIndex((prev) => prev + 1);
37
+ return;
38
+ }
39
+ if (key.return) {
40
+ handleConfirm();
41
+ return;
42
+ }
43
+ if (input === "o" && currentQuestion.options) {
44
+ setIsCustomInputMode(true);
45
+ setCustomInput("");
46
+ return;
47
+ }
48
+ },
49
+ { isActive: true }
50
+ );
51
+ const handleOptionChange = useCallback(
52
+ (optionIndex) => {
53
+ const newSelectedOptions = [...selectedOptions];
54
+ newSelectedOptions[currentQuestionIndex] = optionIndex;
55
+ setSelectedOptions(newSelectedOptions);
56
+ if (optionIndex === -1) {
57
+ setIsCustomInputMode(true);
58
+ setCustomInput("");
59
+ }
60
+ },
61
+ [selectedOptions, currentQuestionIndex]
62
+ );
63
+ const handleConfirm = useCallback(() => {
64
+ if (isCustomInputMode) {
65
+ if (!customInput.trim()) {
66
+ return;
67
+ }
68
+ setIsCustomInputMode(false);
69
+ if (currentQuestionIndex === questions.length - 1) {
70
+ submitAnswers(customInput);
71
+ } else {
72
+ setCurrentQuestionIndex((prev) => prev + 1);
73
+ }
74
+ return;
75
+ }
76
+ if (currentQuestionIndex === questions.length - 1) {
77
+ submitAnswers();
78
+ } else {
79
+ setCurrentQuestionIndex((prev) => prev + 1);
80
+ }
81
+ }, [isCustomInputMode, customInput, currentQuestionIndex, questions.length]);
82
+ const submitAnswers = useCallback(
83
+ (customInputOverride) => {
84
+ const answers = questions.map((question, index) => {
85
+ const selectedOptionIndex = selectedOptions[index];
86
+ if (index === currentQuestionIndex && (customInputOverride || isCustomInputMode)) {
87
+ return {
88
+ questionIndex: index,
89
+ customInput: customInputOverride || customInput
90
+ };
91
+ }
92
+ if (selectedOptionIndex === -1) {
93
+ return {
94
+ questionIndex: index,
95
+ customInput
96
+ };
97
+ }
98
+ return {
99
+ questionIndex: index,
100
+ selectedOptions: [selectedOptionIndex]
101
+ };
102
+ });
103
+ onDone();
104
+ resolve(answers);
105
+ },
106
+ [
107
+ questions,
108
+ selectedOptions,
109
+ currentQuestionIndex,
110
+ isCustomInputMode,
111
+ customInput,
112
+ onDone,
113
+ resolve
114
+ ]
115
+ );
116
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingY: 1 }, isCustomInputMode ? /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingX: 2 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, "Enter your custom response:")), /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, "> "), /* @__PURE__ */ React.createElement(
117
+ TextInput,
118
+ {
119
+ value: customInput,
120
+ onChange: setCustomInput,
121
+ onSubmit: handleConfirm
122
+ }
123
+ )), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "[Enter to confirm] [Esc to cancel]"))) : (
124
+ /* Normal question view */
125
+ /* @__PURE__ */ React.createElement(
126
+ QuestionView,
127
+ {
128
+ question: currentQuestion,
129
+ questionIndex: currentQuestionIndex,
130
+ totalQuestions: questions.length,
131
+ selectedOptionIndex: selectedOptions[currentQuestionIndex],
132
+ onOptionChange: handleOptionChange
133
+ }
134
+ )
135
+ ));
136
+ }
137
+ export {
138
+ AskUserQuestionDialog
139
+ };
140
+ //# sourceMappingURL=AskUserQuestionDialog.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/components/AskUserQuestionDialog/AskUserQuestionDialog.tsx"],
4
+ "sourcesContent": ["import { Box, Text, useInput } from 'ink'\nimport * as React from 'react'\nimport { useState, useCallback } from 'react'\nimport { type AskUserQuestionContext, type UserAnswer } from '@minto-types/askUserQuestion'\nimport { QuestionView } from './QuestionView'\nimport { useNotifyAfterTimeout } from '@hooks/useNotifyAfterTimeout'\nimport { PRODUCT_NAME } from '@constants/product'\nimport TextInput from 'ink-text-input'\n\ninterface AskUserQuestionDialogProps {\n context: AskUserQuestionContext\n onDone: () => void\n}\n\nexport function AskUserQuestionDialog({\n context,\n onDone,\n}: AskUserQuestionDialogProps): React.ReactElement {\n const { questions, resolve, reject } = context\n\n // Current question index (for multi-question scenarios)\n const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0)\n\n // Selected option indices for each question\n const [selectedOptions, setSelectedOptions] = useState<number[]>(\n questions.map(() => 0),\n )\n\n // Custom input mode for \"Other\" option\n const [isCustomInputMode, setIsCustomInputMode] = useState(false)\n const [customInput, setCustomInput] = useState('')\n\n // Notification after timeout\n useNotifyAfterTimeout(`${PRODUCT_NAME} needs your input to continue`)\n\n const currentQuestion = questions[currentQuestionIndex]!\n\n // Handle keyboard input\n useInput(\n (input, key) => {\n // Cancel with Escape or Ctrl+C\n if (key.escape || (key.ctrl && input === 'c')) {\n onDone()\n reject()\n return\n }\n\n // Don't handle other keys in custom input mode\n if (isCustomInputMode) {\n return\n }\n\n // Navigate between questions with left/right arrows\n if (key.leftArrow && currentQuestionIndex > 0) {\n setCurrentQuestionIndex(prev => prev - 1)\n return\n }\n\n if (key.rightArrow && currentQuestionIndex < questions.length - 1) {\n setCurrentQuestionIndex(prev => prev + 1)\n return\n }\n\n // Confirm with Enter\n if (key.return) {\n handleConfirm()\n return\n }\n\n // Press 'o' to enter custom input mode\n if (input === 'o' && currentQuestion.options) {\n setIsCustomInputMode(true)\n setCustomInput('')\n return\n }\n },\n { isActive: true },\n )\n\n // Handle option change\n const handleOptionChange = useCallback(\n (optionIndex: number) => {\n const newSelectedOptions = [...selectedOptions]\n newSelectedOptions[currentQuestionIndex] = optionIndex\n setSelectedOptions(newSelectedOptions)\n\n // If \"Other\" is selected (-1), enter custom input mode\n if (optionIndex === -1) {\n setIsCustomInputMode(true)\n setCustomInput('')\n }\n },\n [selectedOptions, currentQuestionIndex],\n )\n\n // Handle confirmation\n const handleConfirm = useCallback(() => {\n // If in custom input mode, save the custom input\n if (isCustomInputMode) {\n if (!customInput.trim()) {\n // Don't allow empty custom input\n return\n }\n\n // Save custom input and exit custom input mode\n setIsCustomInputMode(false)\n\n // If this is the last question, submit all answers\n if (currentQuestionIndex === questions.length - 1) {\n submitAnswers(customInput)\n } else {\n // Move to next question\n setCurrentQuestionIndex(prev => prev + 1)\n }\n return\n }\n\n // If this is the last question, submit all answers\n if (currentQuestionIndex === questions.length - 1) {\n submitAnswers()\n } else {\n // Move to next question\n setCurrentQuestionIndex(prev => prev + 1)\n }\n }, [isCustomInputMode, customInput, currentQuestionIndex, questions.length])\n\n // Submit all answers\n const submitAnswers = useCallback(\n (customInputOverride?: string) => {\n const answers: UserAnswer[] = questions.map((question, index) => {\n const selectedOptionIndex = selectedOptions[index]!\n\n // If it's the current question and we have custom input\n if (\n index === currentQuestionIndex &&\n (customInputOverride || isCustomInputMode)\n ) {\n return {\n questionIndex: index,\n customInput: customInputOverride || customInput,\n }\n }\n\n // If \"Other\" was selected (-1), use custom input\n if (selectedOptionIndex === -1) {\n return {\n questionIndex: index,\n customInput: customInput,\n }\n }\n\n // Regular option selection\n return {\n questionIndex: index,\n selectedOptions: [selectedOptionIndex],\n }\n })\n\n onDone()\n resolve(answers)\n },\n [\n questions,\n selectedOptions,\n currentQuestionIndex,\n isCustomInputMode,\n customInput,\n onDone,\n resolve,\n ],\n )\n\n return (\n <Box flexDirection=\"column\" paddingY={1}>\n {/* Custom input mode */}\n {isCustomInputMode ? (\n <Box flexDirection=\"column\" paddingX={2}>\n <Box marginBottom={1}>\n <Text bold>Enter your custom response:</Text>\n </Box>\n <Box marginBottom={1}>\n <Text color=\"cyan\">&gt; </Text>\n <TextInput\n value={customInput}\n onChange={setCustomInput}\n onSubmit={handleConfirm}\n />\n </Box>\n <Box>\n <Text dimColor>[Enter to confirm] [Esc to cancel]</Text>\n </Box>\n </Box>\n ) : (\n /* Normal question view */\n <QuestionView\n question={currentQuestion}\n questionIndex={currentQuestionIndex}\n totalQuestions={questions.length}\n selectedOptionIndex={selectedOptions[currentQuestionIndex]!}\n onOptionChange={handleOptionChange}\n />\n )}\n </Box>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,45 @@
1
+ import { Box, Text } from "ink";
2
+ import * as React from "react";
3
+ import { Select } from "../CustomSelect/select.js";
4
+ import { getTheme } from "../../utils/theme.js";
5
+ function QuestionView({
6
+ question,
7
+ questionIndex,
8
+ totalQuestions,
9
+ selectedOptionIndex,
10
+ onOptionChange
11
+ }) {
12
+ const theme = getTheme();
13
+ const options = React.useMemo(() => {
14
+ if (!question.options || question.options.length === 0) {
15
+ return [];
16
+ }
17
+ const selectOptions = question.options.map((opt, index) => ({
18
+ label: opt.label,
19
+ value: String(index)
20
+ }));
21
+ selectOptions.push({
22
+ label: "Other (custom input)",
23
+ value: "other"
24
+ });
25
+ return selectOptions;
26
+ }, [question.options]);
27
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.primary, bold: true }, "\u{1F914} AI needs your input"), totalQuestions > 1 && /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, " ", "(Question ", questionIndex + 1, " of ", totalQuestions, ")")), question.header && /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.minto }, "[", question.header, "]")), /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, question.question)), question.options && question.options.length > 0 && /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(
28
+ Select,
29
+ {
30
+ options,
31
+ defaultValue: String(selectedOptionIndex),
32
+ onChange: (value) => {
33
+ if (value === "other") {
34
+ onOptionChange(-1);
35
+ } else {
36
+ onOptionChange(Number(value));
37
+ }
38
+ }
39
+ }
40
+ )), question.options && question.options.length > 0 && selectedOptionIndex >= 0 && selectedOptionIndex < question.options.length && /* @__PURE__ */ React.createElement(Box, { marginLeft: 2, marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText, dimColor: true }, question.options[selectedOptionIndex]?.description || "")), /* @__PURE__ */ React.createElement(Box, { marginTop: 1, borderStyle: "single", borderColor: theme.secondaryBorder, paddingX: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "[\u2191/\u2193 Navigate] [Enter Confirm]", totalQuestions > 1 && " [\u2190/\u2192 Switch Questions]", " [Esc Cancel]")));
41
+ }
42
+ export {
43
+ QuestionView
44
+ };
45
+ //# sourceMappingURL=QuestionView.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/components/AskUserQuestionDialog/QuestionView.tsx"],
4
+ "sourcesContent": ["import { Box, Text } from 'ink'\nimport * as React from 'react'\nimport { Select } from '@components/CustomSelect/select'\nimport { type UserQuestion, type QuestionOption } from '@minto-types/askUserQuestion'\nimport { Option } from '@inkjs/ui'\nimport { getTheme } from '@utils/theme'\n\ninterface QuestionViewProps {\n question: UserQuestion\n questionIndex: number\n totalQuestions: number\n selectedOptionIndex: number\n onOptionChange: (optionIndex: number) => void\n}\n\nexport function QuestionView({\n question,\n questionIndex,\n totalQuestions,\n selectedOptionIndex,\n onOptionChange,\n}: QuestionViewProps): React.ReactElement {\n const theme = getTheme()\n\n // Build options for the Select component\n const options: Option[] = React.useMemo(() => {\n if (!question.options || question.options.length === 0) {\n return []\n }\n\n const selectOptions = question.options.map((opt, index) => ({\n label: opt.label,\n value: String(index),\n }))\n\n // Always add \"Other (custom input)\" option\n selectOptions.push({\n label: 'Other (custom input)',\n value: 'other',\n })\n\n return selectOptions\n }, [question.options])\n\n return (\n <Box flexDirection=\"column\" paddingX={2} paddingY={1}>\n {/* Header with question counter */}\n <Box marginBottom={1}>\n <Text color={theme.primary} bold>\n \uD83E\uDD14 AI needs your input\n </Text>\n {totalQuestions > 1 && (\n <Text color={theme.secondaryText}>\n {' '}\n (Question {questionIndex + 1} of {totalQuestions})\n </Text>\n )}\n </Box>\n\n {/* Question header tag */}\n {question.header && (\n <Box marginBottom={1}>\n <Text color={theme.minto}>[{question.header}]</Text>\n </Box>\n )}\n\n {/* Question text */}\n <Box marginBottom={1}>\n <Text bold>{question.question}</Text>\n </Box>\n\n {/* Options list */}\n {question.options && question.options.length > 0 && (\n <Box marginBottom={1}>\n <Select\n options={options}\n defaultValue={String(selectedOptionIndex)}\n onChange={value => {\n if (value === 'other') {\n onOptionChange(-1) // -1 indicates \"Other\"\n } else {\n onOptionChange(Number(value))\n }\n }}\n />\n </Box>\n )}\n\n {/* Show option descriptions */}\n {question.options &&\n question.options.length > 0 &&\n selectedOptionIndex >= 0 &&\n selectedOptionIndex < question.options.length && (\n <Box marginLeft={2} marginBottom={1}>\n <Text color={theme.secondaryText} dimColor>\n {question.options[selectedOptionIndex]?.description || ''}\n </Text>\n </Box>\n )}\n\n {/* Help text */}\n <Box marginTop={1} borderStyle=\"single\" borderColor={theme.secondaryBorder} paddingX={1}>\n <Text color={theme.secondaryText}>\n [\u2191/\u2193 Navigate] [Enter Confirm]\n {totalQuestions > 1 && ' [\u2190/\u2192 Switch Questions]'} [Esc Cancel]\n </Text>\n </Box>\n </Box>\n )\n}\n"],
5
+ "mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,YAAY,WAAW;AACvB,SAAS,cAAc;AAGvB,SAAS,gBAAgB;AAUlB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0C;AACxC,QAAM,QAAQ,SAAS;AAGvB,QAAM,UAAoB,MAAM,QAAQ,MAAM;AAC5C,QAAI,CAAC,SAAS,WAAW,SAAS,QAAQ,WAAW,GAAG;AACtD,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,gBAAgB,SAAS,QAAQ,IAAI,CAAC,KAAK,WAAW;AAAA,MAC1D,OAAO,IAAI;AAAA,MACX,OAAO,OAAO,KAAK;AAAA,IACrB,EAAE;AAGF,kBAAc,KAAK;AAAA,MACjB,OAAO;AAAA,MACP,OAAO;AAAA,IACT,CAAC;AAED,WAAO;AAAA,EACT,GAAG,CAAC,SAAS,OAAO,CAAC;AAErB,SACE,oCAAC,OAAI,eAAc,UAAS,UAAU,GAAG,UAAU,KAEjD,oCAAC,OAAI,cAAc,KACjB,oCAAC,QAAK,OAAO,MAAM,SAAS,MAAI,QAAC,+BAEjC,GACC,iBAAiB,KAChB,oCAAC,QAAK,OAAO,MAAM,iBAChB,KAAI,cACM,gBAAgB,GAAE,QAAK,gBAAe,GACnD,CAEJ,GAGC,SAAS,UACR,oCAAC,OAAI,cAAc,KACjB,oCAAC,QAAK,OAAO,MAAM,SAAO,KAAE,SAAS,QAAO,GAAC,CAC/C,GAIF,oCAAC,OAAI,cAAc,KACjB,oCAAC,QAAK,MAAI,QAAE,SAAS,QAAS,CAChC,GAGC,SAAS,WAAW,SAAS,QAAQ,SAAS,KAC7C,oCAAC,OAAI,cAAc,KACjB;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,cAAc,OAAO,mBAAmB;AAAA,MACxC,UAAU,WAAS;AACjB,YAAI,UAAU,SAAS;AACrB,yBAAe,EAAE;AAAA,QACnB,OAAO;AACL,yBAAe,OAAO,KAAK,CAAC;AAAA,QAC9B;AAAA,MACF;AAAA;AAAA,EACF,CACF,GAID,SAAS,WACR,SAAS,QAAQ,SAAS,KAC1B,uBAAuB,KACvB,sBAAsB,SAAS,QAAQ,UACrC,oCAAC,OAAI,YAAY,GAAG,cAAc,KAChC,oCAAC,QAAK,OAAO,MAAM,eAAe,UAAQ,QACvC,SAAS,QAAQ,mBAAmB,GAAG,eAAe,EACzD,CACF,GAIJ,oCAAC,OAAI,WAAW,GAAG,aAAY,UAAS,aAAa,MAAM,iBAAiB,UAAU,KACpF,oCAAC,QAAK,OAAO,MAAM,iBAAe,4CAE/B,iBAAiB,KAAK,qCAA0B,eACnD,CACF,CACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,7 @@
1
+ import { AskUserQuestionDialog } from "./AskUserQuestionDialog.js";
2
+ import { QuestionView } from "./QuestionView.js";
3
+ export {
4
+ AskUserQuestionDialog,
5
+ QuestionView
6
+ };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/components/AskUserQuestionDialog/index.ts"],
4
+ "sourcesContent": ["export { AskUserQuestionDialog } from './AskUserQuestionDialog'\nexport { QuestionView } from './QuestionView'\n"],
5
+ "mappings": "AAAA,SAAS,6BAA6B;AACtC,SAAS,oBAAoB;",
6
+ "names": []
7
+ }
@@ -28,15 +28,14 @@ function TodoPanel({
28
28
  }
29
29
  const visibleTodos = todos;
30
30
  const currentTask = currentTaskActiveForm || todos.find((t) => t.status === "in_progress")?.activeForm || "Executing tasks";
31
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Box, { width: 2, flexShrink: 0 }, /* @__PURE__ */ React.createElement(Text, null, SYMBOLS.THINKING_FRAMES[frameIndex])), /* @__PURE__ */ React.createElement(Text, null, currentTask), /* @__PURE__ */ React.createElement(Text, null, "\u2026 "), /* @__PURE__ */ React.createElement(Text, { color: theme.dim }, "(esc to interrupt \xB7 ctrl+t to hide todos \xB7 ", elapsedTime, "s \xB7 \u2193", " ", formatNumber(tokenCount), " tokens)")), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, visibleTodos.map((todo, idx) => /* @__PURE__ */ React.createElement(
31
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Box, { width: 2, flexShrink: 0 }, /* @__PURE__ */ React.createElement(Text, null, SYMBOLS.THINKING_FRAMES[frameIndex])), /* @__PURE__ */ React.createElement(Text, null, currentTask), /* @__PURE__ */ React.createElement(Text, null, "\u2026 "), /* @__PURE__ */ React.createElement(Text, { color: theme.dim }, "(esc to interrupt \xB7 ctrl+t to hide todos \xB7 ", elapsedTime, "s \xB7 \u2193", " ", formatNumber(tokenCount), " tokens)")), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, visibleTodos.map((todo, idx) => /* @__PURE__ */ React.createElement(React.Fragment, { key: `todo-${idx}-${todo.content.slice(0, 20)}` }, /* @__PURE__ */ React.createElement(
32
32
  TodoItemClaudeStyle,
33
33
  {
34
- key: `todo-${idx}-${todo.content.slice(0, 20)}`,
35
34
  todo,
36
35
  theme,
37
36
  isFirst: idx === 0
38
37
  }
39
- ))));
38
+ )))));
40
39
  }
41
40
  function TodoItemClaudeStyle({
42
41
  todo,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/TodoPanel.tsx"],
4
- "sourcesContent": ["import React, { useState, useEffect } from 'react'\nimport { Box, Text } from 'ink'\nimport { TodoItem } from './TodoItem'\nimport { getTheme } from '@utils/theme'\nimport { SYMBOLS, getTodoStatusSymbol } from '@constants/symbols'\nimport { formatNumber } from '@utils/format'\nimport type { TodoItem as TodoItemType } from '@utils/todoStorage'\n\ninterface TodoPanelProps {\n /** TODO \u5217\u8868 */\n todos: TodoItemType[]\n /** \u662F\u5426\u663E\u793A\u9762\u677F\uFF08\u7531 Ctrl+T \u63A7\u5236\uFF09 */\n isVisible: boolean\n /** \u5F53\u524D\u4E3B\u4EFB\u52A1\u7684 activeForm\uFF08\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u63CF\u8FF0\uFF09 */\n currentTaskActiveForm?: string\n /** \u8FD0\u884C\u65F6\u95F4\uFF08\u79D2\uFF09 */\n elapsedTime?: number\n /** Token \u8BA1\u6570 */\n tokenCount?: number\n /** \u662F\u5426\u6B63\u5728\u52A0\u8F7D\uFF08\u63A7\u5236\u52A8\u753B\uFF09 */\n isLoading?: boolean\n}\n\n/**\n * TODO \u9762\u677F\u7EC4\u4EF6 - Claude Code CLI \u98CE\u683C\n *\n * \u89C6\u89C9\u683C\u5F0F\uFF1A\n * ```\n * \u273D \u4F18\u5316\u5E76\u884C\u4EFB\u52A1\u8FDB\u5EA6\u5C55\u793A\u2026 (esc to interrupt \u00B7 ctrl+t to hide todos \u00B7 252s \u00B7 \u2193 5.8k tokens)\n * \u23BF \u2612 \u5DF2\u5B8C\u6210\u4EFB\u52A1 (\u7070\u8272 + \u5220\u9664\u7EBF)\n * \u2610 \u5F85\u5B8C\u6210\u4EFB\u52A1\n * ```\n */\nexport function TodoPanel({\n todos,\n isVisible,\n currentTaskActiveForm,\n elapsedTime = 0,\n tokenCount = 0,\n isLoading = true,\n}: TodoPanelProps) {\n const theme = getTheme()\n\n // Claude Code \u98CE\u683C\uFF1A\u52A8\u6001\u52A8\u753B\u7B26\u53F7 (6\u5E27\u5FAA\u73AF)\n const [frameIndex, setFrameIndex] = useState(0)\n useEffect(() => {\n // \u53EA\u5728 isLoading \u4E3A true \u65F6\u8FD0\u884C\u52A8\u753B\n if (!isLoading) {\n return\n }\n\n const timer = setInterval(() => {\n setFrameIndex(i => (i + 1) % SYMBOLS.THINKING_FRAMES.length)\n }, 150)\n return () => clearInterval(timer)\n }, [isLoading])\n\n // Claude Code \u98CE\u683C\uFF1A\u6240\u6709\u4EFB\u52A1\u5B8C\u6210\u540E\u9690\u85CF\u9762\u677F\n const hasIncompleteTasks = todos.some(t => t.status !== 'completed')\n\n // \u5982\u679C\u4E0D\u53EF\u89C1\u3001\u6CA1\u6709 TODO\u3001\u6216\u6240\u6709\u4EFB\u52A1\u90FD\u5DF2\u5B8C\u6210\uFF0C\u4E0D\u6E32\u67D3\n if (!isVisible || todos.length === 0 || !hasIncompleteTasks) {\n return null\n }\n\n // Claude Code \u98CE\u683C\uFF1A\u663E\u793A\u6240\u6709 TODO\uFF08\u5305\u62EC\u5DF2\u5B8C\u6210\u7684\uFF09\n const visibleTodos = todos\n\n // \u83B7\u53D6\u5F53\u524D\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u63CF\u8FF0\n const currentTask =\n currentTaskActiveForm ||\n todos.find(t => t.status === 'in_progress')?.activeForm ||\n 'Executing tasks'\n\n return (\n <Box flexDirection=\"column\" marginY={1}>\n {/* \u7B2C\u4E00\u884C\uFF1A\u52A8\u753B + \u5F53\u524D\u4EFB\u52A1 + \u7EDF\u8BA1\u4FE1\u606F */}\n <Box flexDirection=\"row\">\n {/* \u52A8\u753B\u7B26\u53F7 - \u4F7F\u7528\u56FA\u5B9A\u5BBD\u5EA6\u907F\u514D\u6296\u52A8 */}\n <Box width={2} flexShrink={0}>\n <Text>{SYMBOLS.THINKING_FRAMES[frameIndex]}</Text>\n </Box>\n\n {/* \u5F53\u524D\u4EFB\u52A1\u63CF\u8FF0 */}\n <Text>{currentTask}</Text>\n\n {/* \u7701\u7565\u7B26\u53F7 */}\n <Text>\u2026 </Text>\n\n {/* \u7EDF\u8BA1\u4FE1\u606F\u548C\u63D0\u793A */}\n <Text color={theme.dim}>\n (esc to interrupt \u00B7 ctrl+t to hide todos \u00B7 {elapsedTime}s \u00B7 \u2193{' '}\n {formatNumber(tokenCount)} tokens)\n </Text>\n </Box>\n\n {/* TODO \u5217\u8868 */}\n <Box flexDirection=\"column\">\n {visibleTodos.map((todo, idx) => (\n <TodoItemClaudeStyle\n key={`todo-${idx}-${todo.content.slice(0, 20)}`}\n todo={todo}\n theme={theme}\n isFirst={idx === 0}\n />\n ))}\n </Box>\n </Box>\n )\n}\n\n/**\n * Claude Code \u98CE\u683C\u7684 TODO \u9879\n *\n * \u683C\u5F0F\uFF1A\n * ```\n * \u23BF \u2612 \u5DF2\u5B8C\u6210\u4EFB\u52A1 (\u7070\u8272 + \u5220\u9664\u7EBF)\n * \u2610 \u5F85\u5B8C\u6210\u4EFB\u52A1\n * ```\n */\ninterface TodoItemClaudeStyleProps {\n todo: TodoItemType\n theme: ReturnType<typeof getTheme>\n isFirst: boolean\n}\n\nfunction TodoItemClaudeStyle({\n todo,\n theme,\n isFirst,\n}: TodoItemClaudeStyleProps) {\n const isCompleted = todo.status === 'completed'\n\n // \u7B26\u53F7\uFF1A\u2610 \u672A\u5B8C\u6210 / \u2612 \u5DF2\u5B8C\u6210\n const symbol = getTodoStatusSymbol(todo.status)\n\n // \u989C\u8272\uFF1A\u5DF2\u5B8C\u6210\u7528\u7070\u8272\uFF0C\u5176\u4ED6\u6B63\u5E38\n const color = isCompleted ? theme.dim : undefined\n\n // \u7F29\u8FDB\uFF1A\u7B2C\u4E00\u4E2A\u7528 \" \u23BF \"\uFF0C\u5176\u4ED6\u7528 \" \" (5\u4E2A\u7A7A\u683C\u5BF9\u9F50)\n const indent = isFirst ? ' \u23BF ' : ' '\n\n return (\n <Box flexDirection=\"row\">\n {/* \u7F29\u8FDB */}\n <Text color={theme.dim}>{indent}</Text>\n\n {/* \u72B6\u6001\u7B26\u53F7 */}\n <Text color={color}>{symbol} </Text>\n\n {/* \u4EFB\u52A1\u63CF\u8FF0 */}\n <Text color={color} strikethrough={isCompleted}>\n {todo.content}\n </Text>\n </Box>\n )\n}\n"],
5
- "mappings": "AAAA,OAAO,SAAS,UAAU,iBAAiB;AAC3C,SAAS,KAAK,YAAY;AAE1B,SAAS,gBAAgB;AACzB,SAAS,SAAS,2BAA2B;AAC7C,SAAS,oBAAoB;AA4BtB,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,aAAa;AAAA,EACb,YAAY;AACd,GAAmB;AACjB,QAAM,QAAQ,SAAS;AAGvB,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,CAAC;AAC9C,YAAU,MAAM;AAEd,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AAEA,UAAM,QAAQ,YAAY,MAAM;AAC9B,oBAAc,QAAM,IAAI,KAAK,QAAQ,gBAAgB,MAAM;AAAA,IAC7D,GAAG,GAAG;AACN,WAAO,MAAM,cAAc,KAAK;AAAA,EAClC,GAAG,CAAC,SAAS,CAAC;AAGd,QAAM,qBAAqB,MAAM,KAAK,OAAK,EAAE,WAAW,WAAW;AAGnE,MAAI,CAAC,aAAa,MAAM,WAAW,KAAK,CAAC,oBAAoB;AAC3D,WAAO;AAAA,EACT;AAGA,QAAM,eAAe;AAGrB,QAAM,cACJ,yBACA,MAAM,KAAK,OAAK,EAAE,WAAW,aAAa,GAAG,cAC7C;AAEF,SACE,oCAAC,OAAI,eAAc,UAAS,SAAS,KAEnC,oCAAC,OAAI,eAAc,SAEjB,oCAAC,OAAI,OAAO,GAAG,YAAY,KACzB,oCAAC,YAAM,QAAQ,gBAAgB,UAAU,CAAE,CAC7C,GAGA,oCAAC,YAAM,WAAY,GAGnB,oCAAC,YAAK,SAAE,GAGR,oCAAC,QAAK,OAAO,MAAM,OAAK,qDACsB,aAAY,iBAAM,KAC7D,aAAa,UAAU,GAAE,UAC5B,CACF,GAGA,oCAAC,OAAI,eAAc,YAChB,aAAa,IAAI,CAAC,MAAM,QACvB;AAAA,IAAC;AAAA;AAAA,MACC,KAAK,QAAQ,GAAG,IAAI,KAAK,QAAQ,MAAM,GAAG,EAAE,CAAC;AAAA,MAC7C;AAAA,MACA;AAAA,MACA,SAAS,QAAQ;AAAA;AAAA,EACnB,CACD,CACH,CACF;AAEJ;AAiBA,SAAS,oBAAoB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,GAA6B;AAC3B,QAAM,cAAc,KAAK,WAAW;AAGpC,QAAM,SAAS,oBAAoB,KAAK,MAAM;AAG9C,QAAM,QAAQ,cAAc,MAAM,MAAM;AAGxC,QAAM,SAAS,UAAU,eAAU;AAEnC,SACE,oCAAC,OAAI,eAAc,SAEjB,oCAAC,QAAK,OAAO,MAAM,OAAM,MAAO,GAGhC,oCAAC,QAAK,SAAe,QAAO,GAAC,GAG7B,oCAAC,QAAK,OAAc,eAAe,eAChC,KAAK,OACR,CACF;AAEJ;",
4
+ "sourcesContent": ["import React, { useState, useEffect } from 'react'\nimport { Box, Text } from 'ink'\nimport { TodoItem } from './TodoItem'\nimport { getTheme } from '@utils/theme'\nimport { SYMBOLS, getTodoStatusSymbol } from '@constants/symbols'\nimport { formatNumber } from '@utils/format'\nimport type { TodoItem as TodoItemType } from '@utils/todoStorage'\n\ninterface TodoPanelProps {\n /** TODO \u5217\u8868 */\n todos: TodoItemType[]\n /** \u662F\u5426\u663E\u793A\u9762\u677F\uFF08\u7531 Ctrl+T \u63A7\u5236\uFF09 */\n isVisible: boolean\n /** \u5F53\u524D\u4E3B\u4EFB\u52A1\u7684 activeForm\uFF08\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u63CF\u8FF0\uFF09 */\n currentTaskActiveForm?: string\n /** \u8FD0\u884C\u65F6\u95F4\uFF08\u79D2\uFF09 */\n elapsedTime?: number\n /** Token \u8BA1\u6570 */\n tokenCount?: number\n /** \u662F\u5426\u6B63\u5728\u52A0\u8F7D\uFF08\u63A7\u5236\u52A8\u753B\uFF09 */\n isLoading?: boolean\n}\n\n/**\n * TODO \u9762\u677F\u7EC4\u4EF6 - Claude Code CLI \u98CE\u683C\n *\n * \u89C6\u89C9\u683C\u5F0F\uFF1A\n * ```\n * \u273D \u4F18\u5316\u5E76\u884C\u4EFB\u52A1\u8FDB\u5EA6\u5C55\u793A\u2026 (esc to interrupt \u00B7 ctrl+t to hide todos \u00B7 252s \u00B7 \u2193 5.8k tokens)\n * \u23BF \u2612 \u5DF2\u5B8C\u6210\u4EFB\u52A1 (\u7070\u8272 + \u5220\u9664\u7EBF)\n * \u2610 \u5F85\u5B8C\u6210\u4EFB\u52A1\n * ```\n */\nexport function TodoPanel({\n todos,\n isVisible,\n currentTaskActiveForm,\n elapsedTime = 0,\n tokenCount = 0,\n isLoading = true,\n}: TodoPanelProps) {\n const theme = getTheme()\n\n // Claude Code \u98CE\u683C\uFF1A\u52A8\u6001\u52A8\u753B\u7B26\u53F7 (6\u5E27\u5FAA\u73AF)\n const [frameIndex, setFrameIndex] = useState(0)\n useEffect(() => {\n // \u53EA\u5728 isLoading \u4E3A true \u65F6\u8FD0\u884C\u52A8\u753B\n if (!isLoading) {\n return\n }\n\n const timer = setInterval(() => {\n setFrameIndex(i => (i + 1) % SYMBOLS.THINKING_FRAMES.length)\n }, 150)\n return () => clearInterval(timer)\n }, [isLoading])\n\n // Claude Code \u98CE\u683C\uFF1A\u6240\u6709\u4EFB\u52A1\u5B8C\u6210\u540E\u9690\u85CF\u9762\u677F\n const hasIncompleteTasks = todos.some(t => t.status !== 'completed')\n\n // \u5982\u679C\u4E0D\u53EF\u89C1\u3001\u6CA1\u6709 TODO\u3001\u6216\u6240\u6709\u4EFB\u52A1\u90FD\u5DF2\u5B8C\u6210\uFF0C\u4E0D\u6E32\u67D3\n if (!isVisible || todos.length === 0 || !hasIncompleteTasks) {\n return null\n }\n\n // Claude Code \u98CE\u683C\uFF1A\u663E\u793A\u6240\u6709 TODO\uFF08\u5305\u62EC\u5DF2\u5B8C\u6210\u7684\uFF09\n const visibleTodos = todos\n\n // \u83B7\u53D6\u5F53\u524D\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u63CF\u8FF0\n const currentTask =\n currentTaskActiveForm ||\n todos.find(t => t.status === 'in_progress')?.activeForm ||\n 'Executing tasks'\n\n return (\n <Box flexDirection=\"column\" marginY={1}>\n {/* \u7B2C\u4E00\u884C\uFF1A\u52A8\u753B + \u5F53\u524D\u4EFB\u52A1 + \u7EDF\u8BA1\u4FE1\u606F */}\n <Box flexDirection=\"row\">\n {/* \u52A8\u753B\u7B26\u53F7 - \u4F7F\u7528\u56FA\u5B9A\u5BBD\u5EA6\u907F\u514D\u6296\u52A8 */}\n <Box width={2} flexShrink={0}>\n <Text>{SYMBOLS.THINKING_FRAMES[frameIndex]}</Text>\n </Box>\n\n {/* \u5F53\u524D\u4EFB\u52A1\u63CF\u8FF0 */}\n <Text>{currentTask}</Text>\n\n {/* \u7701\u7565\u7B26\u53F7 */}\n <Text>\u2026 </Text>\n\n {/* \u7EDF\u8BA1\u4FE1\u606F\u548C\u63D0\u793A */}\n <Text color={theme.dim}>\n (esc to interrupt \u00B7 ctrl+t to hide todos \u00B7 {elapsedTime}s \u00B7 \u2193{' '}\n {formatNumber(tokenCount)} tokens)\n </Text>\n </Box>\n\n {/* TODO \u5217\u8868 */}\n <Box flexDirection=\"column\">\n {visibleTodos.map((todo, idx) => (\n <React.Fragment key={`todo-${idx}-${todo.content.slice(0, 20)}`}>\n <TodoItemClaudeStyle\n todo={todo}\n theme={theme}\n isFirst={idx === 0}\n />\n </React.Fragment>\n ))}\n </Box>\n </Box>\n )\n}\n\n/**\n * Claude Code \u98CE\u683C\u7684 TODO \u9879\n *\n * \u683C\u5F0F\uFF1A\n * ```\n * \u23BF \u2612 \u5DF2\u5B8C\u6210\u4EFB\u52A1 (\u7070\u8272 + \u5220\u9664\u7EBF)\n * \u2610 \u5F85\u5B8C\u6210\u4EFB\u52A1\n * ```\n */\ninterface TodoItemClaudeStyleProps {\n todo: TodoItemType\n theme: ReturnType<typeof getTheme>\n isFirst: boolean\n}\n\nfunction TodoItemClaudeStyle({\n todo,\n theme,\n isFirst,\n}: TodoItemClaudeStyleProps) {\n const isCompleted = todo.status === 'completed'\n\n // \u7B26\u53F7\uFF1A\u2610 \u672A\u5B8C\u6210 / \u2612 \u5DF2\u5B8C\u6210\n const symbol = getTodoStatusSymbol(todo.status)\n\n // \u989C\u8272\uFF1A\u5DF2\u5B8C\u6210\u7528\u7070\u8272\uFF0C\u5176\u4ED6\u6B63\u5E38\n const color = isCompleted ? theme.dim : undefined\n\n // \u7F29\u8FDB\uFF1A\u7B2C\u4E00\u4E2A\u7528 \" \u23BF \"\uFF0C\u5176\u4ED6\u7528 \" \" (5\u4E2A\u7A7A\u683C\u5BF9\u9F50)\n const indent = isFirst ? ' \u23BF ' : ' '\n\n return (\n <Box flexDirection=\"row\">\n {/* \u7F29\u8FDB */}\n <Text color={theme.dim}>{indent}</Text>\n\n {/* \u72B6\u6001\u7B26\u53F7 */}\n <Text color={color}>{symbol} </Text>\n\n {/* \u4EFB\u52A1\u63CF\u8FF0 */}\n <Text color={color} strikethrough={isCompleted}>\n {todo.content}\n </Text>\n </Box>\n )\n}\n"],
5
+ "mappings": "AAAA,OAAO,SAAS,UAAU,iBAAiB;AAC3C,SAAS,KAAK,YAAY;AAE1B,SAAS,gBAAgB;AACzB,SAAS,SAAS,2BAA2B;AAC7C,SAAS,oBAAoB;AA4BtB,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,aAAa;AAAA,EACb,YAAY;AACd,GAAmB;AACjB,QAAM,QAAQ,SAAS;AAGvB,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,CAAC;AAC9C,YAAU,MAAM;AAEd,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AAEA,UAAM,QAAQ,YAAY,MAAM;AAC9B,oBAAc,QAAM,IAAI,KAAK,QAAQ,gBAAgB,MAAM;AAAA,IAC7D,GAAG,GAAG;AACN,WAAO,MAAM,cAAc,KAAK;AAAA,EAClC,GAAG,CAAC,SAAS,CAAC;AAGd,QAAM,qBAAqB,MAAM,KAAK,OAAK,EAAE,WAAW,WAAW;AAGnE,MAAI,CAAC,aAAa,MAAM,WAAW,KAAK,CAAC,oBAAoB;AAC3D,WAAO;AAAA,EACT;AAGA,QAAM,eAAe;AAGrB,QAAM,cACJ,yBACA,MAAM,KAAK,OAAK,EAAE,WAAW,aAAa,GAAG,cAC7C;AAEF,SACE,oCAAC,OAAI,eAAc,UAAS,SAAS,KAEnC,oCAAC,OAAI,eAAc,SAEjB,oCAAC,OAAI,OAAO,GAAG,YAAY,KACzB,oCAAC,YAAM,QAAQ,gBAAgB,UAAU,CAAE,CAC7C,GAGA,oCAAC,YAAM,WAAY,GAGnB,oCAAC,YAAK,SAAE,GAGR,oCAAC,QAAK,OAAO,MAAM,OAAK,qDACsB,aAAY,iBAAM,KAC7D,aAAa,UAAU,GAAE,UAC5B,CACF,GAGA,oCAAC,OAAI,eAAc,YAChB,aAAa,IAAI,CAAC,MAAM,QACvB,oCAAC,MAAM,UAAN,EAAe,KAAK,QAAQ,GAAG,IAAI,KAAK,QAAQ,MAAM,GAAG,EAAE,CAAC,MAC3D;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,SAAS,QAAQ;AAAA;AAAA,EACnB,CACF,CACD,CACH,CACF;AAEJ;AAiBA,SAAS,oBAAoB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,GAA6B;AAC3B,QAAM,cAAc,KAAK,WAAW;AAGpC,QAAM,SAAS,oBAAoB,KAAK,MAAM;AAG9C,QAAM,QAAQ,cAAc,MAAM,MAAM;AAGxC,QAAM,SAAS,UAAU,eAAU;AAEnC,SACE,oCAAC,OAAI,eAAc,SAEjB,oCAAC,QAAK,OAAO,MAAM,OAAM,MAAO,GAGhC,oCAAC,QAAK,SAAe,QAAO,GAAC,GAG7B,oCAAC,QAAK,OAAc,eAAe,eAChC,KAAK,OACR,CACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env -S node --no-warnings=ExperimentalWarning --enable-source-maps
2
+ import { fileURLToPath } from "node:url";
3
+ import { dirname, join } from "node:path";
4
+ import { existsSync } from "node:fs";
5
+ try {
6
+ if (!process.env.YOGA_WASM_PATH) {
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+ const devCandidate = join(__dirname, "../../yoga.wasm");
10
+ const distCandidate = join(__dirname, "./yoga.wasm");
11
+ const resolved = existsSync(distCandidate) ? distCandidate : existsSync(devCandidate) ? devCandidate : void 0;
12
+ if (resolved) {
13
+ process.env.YOGA_WASM_PATH = resolved;
14
+ }
15
+ }
16
+ } catch {
17
+ }
18
+ import * as dontcare from "@anthropic-ai/sdk/shims/node";
19
+ Object.keys(dontcare);
20
+ import { createRequire } from "module";
21
+ const require2 = createRequire(import.meta.url);
22
+ function hasFlag(...flags) {
23
+ return process.argv.some((arg) => flags.includes(arg));
24
+ }
25
+ if (hasFlag("--version", "-v")) {
26
+ try {
27
+ const pkg = require2("../../package.json");
28
+ console.log(pkg.version || "");
29
+ } catch {
30
+ console.log("");
31
+ }
32
+ process.exit(0);
33
+ }
34
+ if (hasFlag("--help-lite")) {
35
+ console.log(`Usage: minto [options] [command] [prompt]
36
+
37
+ Common options:
38
+ -h, --help Show full help
39
+ -v, --version Show version
40
+ -p, --print Print response and exit (non-interactive)
41
+ -c, --cwd <cwd> Set working directory`);
42
+ process.exit(0);
43
+ }
44
+ ;
45
+ (async () => {
46
+ try {
47
+ const { initSentry } = await import("../services/sentry.js");
48
+ initSentry();
49
+ const cliModule = await import("./cli.js");
50
+ if (typeof cliModule.main === "function") {
51
+ await cliModule.main();
52
+ } else {
53
+ console.error("\u274C main() function not found in CLI module");
54
+ process.exit(1);
55
+ }
56
+ } catch (err) {
57
+ console.error("\u274C Failed to start Minto:", err);
58
+ process.exit(1);
59
+ }
60
+ })();
61
+ //# sourceMappingURL=cli-wrapper.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/entrypoints/cli-wrapper.tsx"],
4
+ "sourcesContent": ["#!/usr/bin/env -S node --no-warnings=ExperimentalWarning --enable-source-maps\n\n/**\n * CLI Entry Point Wrapper\n *\n * This wrapper uses dynamic imports to avoid top-level await issues when bundled with esbuild.\n * All imports are lazy-loaded inside an async IIFE to ensure the module initializes synchronously.\n */\n\nimport { fileURLToPath } from 'node:url'\nimport { dirname, join } from 'node:path'\nimport { existsSync } from 'node:fs'\n\n// Ensure YOGA_WASM_PATH is set for Ink across run modes (wrapper/dev)\ntry {\n if (!process.env.YOGA_WASM_PATH) {\n const __filename = fileURLToPath(import.meta.url)\n const __dirname = dirname(__filename)\n const devCandidate = join(__dirname, '../../yoga.wasm')\n const distCandidate = join(__dirname, './yoga.wasm')\n const resolved = existsSync(distCandidate)\n ? distCandidate\n : existsSync(devCandidate)\n ? devCandidate\n : undefined\n if (resolved) {\n process.env.YOGA_WASM_PATH = resolved\n }\n }\n} catch {}\n\n// XXX: Bun Win32 bug workaround - import for side effects\nimport * as dontcare from '@anthropic-ai/sdk/shims/node'\nObject.keys(dontcare)\n\nimport { createRequire } from 'module'\nconst require = createRequire(import.meta.url)\n\nfunction hasFlag(...flags: string[]): boolean {\n return process.argv.some(arg => flags.includes(arg))\n}\n\n// Minimal pre-parse: handle version/help-lite early without loading heavy UI modules\nif (hasFlag('--version', '-v')) {\n try {\n const pkg = require('../../package.json')\n console.log(pkg.version || '')\n } catch {\n console.log('')\n }\n process.exit(0)\n}\n\nif (hasFlag('--help-lite')) {\n console.log(`Usage: minto [options] [command] [prompt]\\n\\n` +\n `Common options:\\n` +\n ` -h, --help Show full help\\n` +\n ` -v, --version Show version\\n` +\n ` -p, --print Print response and exit (non-interactive)\\n` +\n ` -c, --cwd <cwd> Set working directory`)\n process.exit(0)\n}\n\n// Main async wrapper to avoid top-level await\n;(async () => {\n try {\n // Initialize Sentry as early as possible (dynamic import)\n const { initSentry } = await import('@services/sentry')\n initSentry()\n\n // Dynamically import and execute the main CLI module\n const cliModule = await import('./cli.js')\n\n // The cli module will have already executed main() in development mode,\n // but in bundled mode we need to call it explicitly if it exports it\n if (typeof cliModule.main === 'function') {\n await cliModule.main()\n } else {\n console.error('\u274C main() function not found in CLI module')\n process.exit(1)\n }\n } catch (err) {\n console.error('\u274C Failed to start Minto:', err)\n process.exit(1)\n }\n})()\n"],
5
+ "mappings": ";AASA,SAAS,qBAAqB;AAC9B,SAAS,SAAS,YAAY;AAC9B,SAAS,kBAAkB;AAG3B,IAAI;AACF,MAAI,CAAC,QAAQ,IAAI,gBAAgB;AAC/B,UAAM,aAAa,cAAc,YAAY,GAAG;AAChD,UAAM,YAAY,QAAQ,UAAU;AACpC,UAAM,eAAe,KAAK,WAAW,iBAAiB;AACtD,UAAM,gBAAgB,KAAK,WAAW,aAAa;AACnD,UAAM,WAAW,WAAW,aAAa,IACrC,gBACA,WAAW,YAAY,IACrB,eACA;AACN,QAAI,UAAU;AACZ,cAAQ,IAAI,iBAAiB;AAAA,IAC/B;AAAA,EACF;AACF,QAAQ;AAAC;AAGT,YAAY,cAAc;AAC1B,OAAO,KAAK,QAAQ;AAEpB,SAAS,qBAAqB;AAC9B,MAAMA,WAAU,cAAc,YAAY,GAAG;AAE7C,SAAS,WAAW,OAA0B;AAC5C,SAAO,QAAQ,KAAK,KAAK,SAAO,MAAM,SAAS,GAAG,CAAC;AACrD;AAGA,IAAI,QAAQ,aAAa,IAAI,GAAG;AAC9B,MAAI;AACF,UAAM,MAAMA,SAAQ,oBAAoB;AACxC,YAAQ,IAAI,IAAI,WAAW,EAAE;AAAA,EAC/B,QAAQ;AACN,YAAQ,IAAI,EAAE;AAAA,EAChB;AACA,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAI,QAAQ,aAAa,GAAG;AAC1B,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6CAKoC;AAChD,UAAQ,KAAK,CAAC;AAChB;AAGA;AAAA,CAAE,YAAY;AACZ,MAAI;AAEF,UAAM,EAAE,WAAW,IAAI,MAAM,OAAO,kBAAkB;AACtD,eAAW;AAGX,UAAM,YAAY,MAAM,OAAO,UAAU;AAIzC,QAAI,OAAO,UAAU,SAAS,YAAY;AACxC,YAAM,UAAU,KAAK;AAAA,IACvB,OAAO;AACL,cAAQ,MAAM,gDAA2C;AACzD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,SAAS,KAAK;AACZ,YAAQ,MAAM,iCAA4B,GAAG;AAC7C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,GAAG;",
6
+ "names": ["require"]
7
+ }
File without changes
@@ -0,0 +1,24 @@
1
+ import { useCallback } from "react";
2
+ function useAskUser(setAskUserQuestionContext) {
3
+ return useCallback(
4
+ (questions) => {
5
+ return new Promise((resolve, reject) => {
6
+ setAskUserQuestionContext({
7
+ questions,
8
+ resolve: (answers) => {
9
+ resolve(answers);
10
+ },
11
+ reject: () => {
12
+ reject(new Error("User cancelled the question dialog"));
13
+ }
14
+ });
15
+ });
16
+ },
17
+ [setAskUserQuestionContext]
18
+ );
19
+ }
20
+ var useAskUser_default = useAskUser;
21
+ export {
22
+ useAskUser_default as default
23
+ };
24
+ //# sourceMappingURL=useAskUser.js.map