@nanocollective/nanocoder
Version:
A local-first CLI coding agent that brings the power of agentic coding tools like Claude Code and Gemini CLI to local models or controlled APIs like OpenRouter
66 lines • 3.27 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { Box, Text } from 'ink';
import React from 'react';
import ToolMessage from '../components/tool-message.js';
import { ThemeContext } from '../hooks/useTheme.js';
import { jsonSchema, tool } from '../types/core.js';
import { signalQuestion } from '../utils/question-queue.js';
const executeAskQuestion = async (args) => {
const { question, options, allowFreeform = true } = args;
if (!options || options.length < 2 || options.length > 4) {
return 'Error: ⚒ options must contain 2-4 items.';
}
const answer = await signalQuestion({
question,
options,
allowFreeform,
});
return answer;
};
const askQuestionCoreTool = tool({
description: 'Ask the user a question with selectable options. Use when you need clarification, a decision between approaches, or user preference. The user sees the question with clickable options and can optionally type a custom answer. Returns the selected answer as a string. IMPORTANT: Never re-ask a question the user has already answered. Accept their response and proceed.',
inputSchema: jsonSchema({
type: 'object',
properties: {
question: {
type: 'string',
description: 'The question to ask the user.',
},
options: {
type: 'array',
items: { type: 'string' },
description: '2-4 selectable answer options for the user to choose from.',
},
allowFreeform: {
type: 'boolean',
description: 'If true (default), adds a "Type custom answer..." option so the user can provide their own response.',
},
},
required: ['question', 'options'],
}),
needsApproval: false,
execute: async (args, _options) => {
return await executeAskQuestion(args);
},
});
const AskQuestionFormatter = React.memo(({ args, result }) => {
const themeContext = React.useContext(ThemeContext);
if (!themeContext) {
throw new Error('ThemeContext not found');
}
const { colors } = themeContext;
const messageContent = (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: colors.tool, children: "\u2692 ask_user" }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { color: colors.secondary, children: "Question:" }), _jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: colors.text, children: args.question }) })] }), result && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: colors.secondary, children: "Answer:" }), _jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: colors.text, children: result }) })] }))] }));
return _jsx(ToolMessage, { message: messageContent, hideBox: true });
});
const askQuestionFormatter = (args, result) => {
if (result && result.startsWith('Error:')) {
return _jsx(_Fragment, {});
}
return _jsx(AskQuestionFormatter, { args: args, result: result });
};
export const askQuestionTool = {
name: 'ask_user',
tool: askQuestionCoreTool,
formatter: askQuestionFormatter,
};
//# sourceMappingURL=ask-question.js.map