@shareai-lab/kode 1.1.16-dev.3 → 1.1.19-dev.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/components/Logo.js +6 -1
- package/dist/components/Logo.js.map +2 -2
- package/dist/components/messages/AssistantToolUseMessage.js.map +2 -2
- package/dist/screens/REPL.js +5 -5
- package/dist/screens/REPL.js.map +2 -2
- package/dist/services/openai.js +10 -6
- package/dist/services/openai.js.map +2 -2
- package/dist/tools/TaskTool/TaskTool.js +44 -1
- package/dist/tools/TaskTool/TaskTool.js.map +2 -2
- package/dist/utils/autoUpdater.js +5 -7
- package/dist/utils/autoUpdater.js.map +2 -2
- package/dist/utils/generators.js.map +1 -1
- package/package.json +58 -1
package/dist/components/Logo.js
CHANGED
|
@@ -5,7 +5,12 @@ import { PRODUCT_NAME } from "../constants/product.js";
|
|
|
5
5
|
import { getAnthropicApiKey, getGlobalConfig } from "../utils/config.js";
|
|
6
6
|
import { getCwd } from "../utils/state.js";
|
|
7
7
|
import { getModelManager } from "../utils/model.js";
|
|
8
|
+
import { MACRO } from "../constants/macros.js";
|
|
8
9
|
const MIN_LOGO_WIDTH = 50;
|
|
10
|
+
const DEFAULT_UPDATE_COMMANDS = [
|
|
11
|
+
"bun add -g @shareai-lab/kode@latest",
|
|
12
|
+
"npm install -g @shareai-lab/kode@latest"
|
|
13
|
+
];
|
|
9
14
|
function Logo({
|
|
10
15
|
mcpClients,
|
|
11
16
|
isDefaultModel = false,
|
|
@@ -33,7 +38,7 @@ function Logo({
|
|
|
33
38
|
marginRight: 2,
|
|
34
39
|
width
|
|
35
40
|
},
|
|
36
|
-
updateBannerVersion ? /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "New version available: ", updateBannerVersion
|
|
41
|
+
updateBannerVersion ? /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "New version available: ", updateBannerVersion, " (current: ", MACRO.VERSION, ")"), /* @__PURE__ */ React.createElement(Text, null, "Run the following command to update:"), /* @__PURE__ */ React.createElement(Text, null, " ", updateBannerCommands?.[1] ?? DEFAULT_UPDATE_COMMANDS[1]), process.platform !== "win32" && /* @__PURE__ */ React.createElement(Text, { dimColor: true }, 'Note: you may need to prefix with "sudo" on macOS/Linux.')) : null,
|
|
37
42
|
/* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { color: theme.kode }, "\u273B"), " Welcome to", " ", /* @__PURE__ */ React.createElement(Text, { bold: true }, PRODUCT_NAME), " ", /* @__PURE__ */ React.createElement(Text, null, "research preview!")),
|
|
38
43
|
/* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { paddingLeft: 2, flexDirection: "column", gap: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText, italic: true }, "/help for help"), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "cwd: ", getCwd())), hasOverrides && /* @__PURE__ */ React.createElement(
|
|
39
44
|
Box,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/components/Logo.tsx"],
|
|
4
|
-
"sourcesContent": ["import { Box, Text, Newline } from 'ink'\nimport * as React from 'react'\nimport { getTheme } from '../utils/theme'\nimport { PRODUCT_NAME } from '../constants/product'\nimport { getAnthropicApiKey, getGlobalConfig } from '../utils/config'\nimport { getCwd } from '../utils/state'\nimport { AsciiLogo } from './AsciiLogo'\nimport type { WrappedClient } from '../services/mcpClient'\nimport { getModelManager } from '../utils/model'\n\nexport const MIN_LOGO_WIDTH = 50\n\nexport function Logo({\n mcpClients,\n isDefaultModel = false,\n updateBannerVersion,\n updateBannerCommands,\n}: {\n mcpClients: WrappedClient[]\n isDefaultModel?: boolean\n updateBannerVersion?: string | null\n updateBannerCommands?: string[] | null\n}): React.ReactNode {\n const width = Math.max(MIN_LOGO_WIDTH, getCwd().length + 12)\n const theme = getTheme()\n const config = getGlobalConfig()\n\n const modelManager = getModelManager()\n const mainModelName = modelManager.getModelName('main')\n const currentModel = mainModelName || 'No model configured'\n const apiKey = getAnthropicApiKey()\n const hasOverrides = Boolean(\n process.env.ANTHROPIC_API_KEY ||\n process.env.DISABLE_PROMPT_CACHING ||\n process.env.API_TIMEOUT_MS ||\n process.env.MAX_THINKING_TOKENS,\n )\n\n return (\n <Box flexDirection=\"column\">\n <Box\n borderColor={theme.kode}\n borderStyle=\"round\"\n flexDirection=\"column\"\n gap={1}\n paddingLeft={1}\n marginRight={2}\n width={width}\n >\n {updateBannerVersion ? (\n <Box flexDirection=\"column\">\n <Text color=\"yellow\">New version available: {updateBannerVersion}</Text>\n <Text>Run the following command to update:</Text>\n <Text>\n {' '}\n {updateBannerCommands?.[
|
|
5
|
-
"mappings": "AAAA,SAAS,KAAK,YAAqB;AACnC,YAAY,WAAW;AACvB,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB,uBAAuB;AACpD,SAAS,cAAc;AAGvB,SAAS,uBAAuB;
|
|
4
|
+
"sourcesContent": ["import { Box, Text, Newline } from 'ink'\nimport * as React from 'react'\nimport { getTheme } from '../utils/theme'\nimport { PRODUCT_NAME } from '../constants/product'\nimport { getAnthropicApiKey, getGlobalConfig } from '../utils/config'\nimport { getCwd } from '../utils/state'\nimport { AsciiLogo } from './AsciiLogo'\nimport type { WrappedClient } from '../services/mcpClient'\nimport { getModelManager } from '../utils/model'\nimport { MACRO } from '../constants/macros'\n\nexport const MIN_LOGO_WIDTH = 50\n\nconst DEFAULT_UPDATE_COMMANDS = [\n 'bun add -g @shareai-lab/kode@latest',\n 'npm install -g @shareai-lab/kode@latest',\n] as const\n\nexport function Logo({\n mcpClients,\n isDefaultModel = false,\n updateBannerVersion,\n updateBannerCommands,\n}: {\n mcpClients: WrappedClient[]\n isDefaultModel?: boolean\n updateBannerVersion?: string | null\n updateBannerCommands?: string[] | null\n}): React.ReactNode {\n const width = Math.max(MIN_LOGO_WIDTH, getCwd().length + 12)\n const theme = getTheme()\n const config = getGlobalConfig()\n\n const modelManager = getModelManager()\n const mainModelName = modelManager.getModelName('main')\n const currentModel = mainModelName || 'No model configured'\n const apiKey = getAnthropicApiKey()\n const hasOverrides = Boolean(\n process.env.ANTHROPIC_API_KEY ||\n process.env.DISABLE_PROMPT_CACHING ||\n process.env.API_TIMEOUT_MS ||\n process.env.MAX_THINKING_TOKENS,\n )\n\n return (\n <Box flexDirection=\"column\">\n <Box\n borderColor={theme.kode}\n borderStyle=\"round\"\n flexDirection=\"column\"\n gap={1}\n paddingLeft={1}\n marginRight={2}\n width={width}\n >\n {updateBannerVersion ? (\n <Box flexDirection=\"column\">\n <Text color=\"yellow\">New version available: {updateBannerVersion} (current: {MACRO.VERSION})</Text>\n <Text>Run the following command to update:</Text>\n <Text>\n {' '}\n {updateBannerCommands?.[1] ?? DEFAULT_UPDATE_COMMANDS[1]}\n </Text>\n {process.platform !== 'win32' && (\n <Text dimColor>\n Note: you may need to prefix with \"sudo\" on macOS/Linux.\n </Text>\n )}\n </Box>\n ) : null}\n <Text>\n <Text color={theme.kode}>\u273B</Text> Welcome to{' '}\n <Text bold>{PRODUCT_NAME}</Text> <Text>research preview!</Text>\n </Text>\n {/* <AsciiLogo /> */}\n\n <>\n <Box paddingLeft={2} flexDirection=\"column\" gap={1}>\n <Text color={theme.secondaryText} italic>\n /help for help\n </Text>\n <Text color={theme.secondaryText}>cwd: {getCwd()}</Text>\n </Box>\n\n {hasOverrides && (\n <Box\n borderColor={theme.secondaryBorder}\n borderStyle=\"single\"\n borderBottom={false}\n borderLeft={false}\n borderRight={false}\n borderTop={true}\n flexDirection=\"column\"\n marginLeft={2}\n marginRight={1}\n paddingTop={1}\n >\n <Box marginBottom={1}>\n <Text color={theme.secondaryText}>Overrides (via env):</Text>\n </Box>\n {process.env.ANTHROPIC_API_KEY && apiKey ? (\n <Text color={theme.secondaryText}>\n \u2022 API Key:{' '}\n <Text bold>sk-ant-\u2026{apiKey!.slice(-width + 25)}</Text>\n </Text>\n ) : null}\n {process.env.DISABLE_PROMPT_CACHING ? (\n <Text color={theme.secondaryText}>\n \u2022 Prompt caching:{' '}\n <Text color={theme.error} bold>\n off\n </Text>\n </Text>\n ) : null}\n {process.env.API_TIMEOUT_MS ? (\n <Text color={theme.secondaryText}>\n \u2022 API timeout:{' '}\n <Text bold>{process.env.API_TIMEOUT_MS}ms</Text>\n </Text>\n ) : null}\n {process.env.MAX_THINKING_TOKENS ? (\n <Text color={theme.secondaryText}>\n \u2022 Max thinking tokens:{' '}\n <Text bold>{process.env.MAX_THINKING_TOKENS}</Text>\n </Text>\n ) : null}\n {process.env.ANTHROPIC_BASE_URL ? (\n <Text color={theme.secondaryText}>\n \u2022 API Base URL:{' '}\n <Text bold>{process.env.ANTHROPIC_BASE_URL}</Text>\n </Text>\n ) : null}\n </Box>\n )}\n </>\n {mcpClients.length ? (\n <Box\n borderColor={theme.secondaryBorder}\n borderStyle=\"single\"\n borderBottom={false}\n borderLeft={false}\n borderRight={false}\n borderTop={true}\n flexDirection=\"column\"\n marginLeft={2}\n marginRight={1}\n paddingTop={1}\n >\n <Box marginBottom={1}>\n <Text color={theme.secondaryText}>MCP Servers:</Text>\n </Box>\n {mcpClients.map((client, idx) => (\n <Box key={idx} width={width - 6}>\n <Text color={theme.secondaryText}>\u2022 {client.name}</Text>\n <Box flexGrow={1} />\n <Text\n bold\n color={\n client.type === 'connected' ? theme.success : theme.error\n }\n >\n {client.type === 'connected' ? 'connected' : 'failed'}\n </Text>\n </Box>\n ))}\n </Box>\n ) : null}\n </Box>\n </Box>\n )\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,KAAK,YAAqB;AACnC,YAAY,WAAW;AACvB,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB,uBAAuB;AACpD,SAAS,cAAc;AAGvB,SAAS,uBAAuB;AAChC,SAAS,aAAa;AAEf,MAAM,iBAAiB;AAE9B,MAAM,0BAA0B;AAAA,EAC9B;AAAA,EACA;AACF;AAEO,SAAS,KAAK;AAAA,EACnB;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA;AACF,GAKoB;AAClB,QAAM,QAAQ,KAAK,IAAI,gBAAgB,OAAO,EAAE,SAAS,EAAE;AAC3D,QAAM,QAAQ,SAAS;AACvB,QAAM,SAAS,gBAAgB;AAE/B,QAAM,eAAe,gBAAgB;AACrC,QAAM,gBAAgB,aAAa,aAAa,MAAM;AACtD,QAAM,eAAe,iBAAiB;AACtC,QAAM,SAAS,mBAAmB;AAClC,QAAM,eAAe;AAAA,IACnB,QAAQ,IAAI,qBACV,QAAQ,IAAI,0BACZ,QAAQ,IAAI,kBACZ,QAAQ,IAAI;AAAA,EAChB;AAEA,SACE,oCAAC,OAAI,eAAc,YACjB;AAAA,IAAC;AAAA;AAAA,MACC,aAAa,MAAM;AAAA,MACnB,aAAY;AAAA,MACZ,eAAc;AAAA,MACd,KAAK;AAAA,MACL,aAAa;AAAA,MACb,aAAa;AAAA,MACb;AAAA;AAAA,IAEC,sBACC,oCAAC,OAAI,eAAc,YACjB,oCAAC,QAAK,OAAM,YAAS,2BAAwB,qBAAoB,eAAY,MAAM,SAAQ,GAAC,GAC5F,oCAAC,YAAK,sCAAoC,GAC1C,oCAAC,YACE,MACA,uBAAuB,CAAC,KAAK,wBAAwB,CAAC,CACzD,GACC,QAAQ,aAAa,WACpB,oCAAC,QAAK,UAAQ,QAAC,0DAEf,CAEJ,IACE;AAAA,IACJ,oCAAC,YACC,oCAAC,QAAK,OAAO,MAAM,QAAM,QAAC,GAAO,eAAY,KAC7C,oCAAC,QAAK,MAAI,QAAE,YAAa,GAAO,KAAC,oCAAC,YAAK,mBAAiB,CAC1D;AAAA,IAGA,0DACE,oCAAC,OAAI,aAAa,GAAG,eAAc,UAAS,KAAK,KAC/C,oCAAC,QAAK,OAAO,MAAM,eAAe,QAAM,QAAC,gBAEzC,GACA,oCAAC,QAAK,OAAO,MAAM,iBAAe,SAAM,OAAO,CAAE,CACnD,GAEC,gBACC;AAAA,MAAC;AAAA;AAAA,QACC,aAAa,MAAM;AAAA,QACnB,aAAY;AAAA,QACZ,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,aAAa;AAAA,QACb,WAAW;AAAA,QACX,eAAc;AAAA,QACd,YAAY;AAAA,QACZ,aAAa;AAAA,QACb,YAAY;AAAA;AAAA,MAEZ,oCAAC,OAAI,cAAc,KACjB,oCAAC,QAAK,OAAO,MAAM,iBAAe,sBAAoB,CACxD;AAAA,MACC,QAAQ,IAAI,qBAAqB,SAChC,oCAAC,QAAK,OAAO,MAAM,iBAAe,mBACrB,KACX,oCAAC,QAAK,MAAI,QAAC,iBAAS,OAAQ,MAAM,CAAC,QAAQ,EAAE,CAAE,CACjD,IACE;AAAA,MACH,QAAQ,IAAI,yBACX,oCAAC,QAAK,OAAO,MAAM,iBAAe,0BACd,KAClB,oCAAC,QAAK,OAAO,MAAM,OAAO,MAAI,QAAC,KAE/B,CACF,IACE;AAAA,MACH,QAAQ,IAAI,iBACX,oCAAC,QAAK,OAAO,MAAM,iBAAe,uBACjB,KACf,oCAAC,QAAK,MAAI,QAAE,QAAQ,IAAI,gBAAe,IAAE,CAC3C,IACE;AAAA,MACH,QAAQ,IAAI,sBACX,oCAAC,QAAK,OAAO,MAAM,iBAAe,+BACT,KACvB,oCAAC,QAAK,MAAI,QAAE,QAAQ,IAAI,mBAAoB,CAC9C,IACE;AAAA,MACH,QAAQ,IAAI,qBACX,oCAAC,QAAK,OAAO,MAAM,iBAAe,wBAChB,KAChB,oCAAC,QAAK,MAAI,QAAE,QAAQ,IAAI,kBAAmB,CAC7C,IACE;AAAA,IACN,CAEJ;AAAA,IACC,WAAW,SACV;AAAA,MAAC;AAAA;AAAA,QACC,aAAa,MAAM;AAAA,QACnB,aAAY;AAAA,QACZ,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,aAAa;AAAA,QACb,WAAW;AAAA,QACX,eAAc;AAAA,QACd,YAAY;AAAA,QACZ,aAAa;AAAA,QACb,YAAY;AAAA;AAAA,MAEZ,oCAAC,OAAI,cAAc,KACjB,oCAAC,QAAK,OAAO,MAAM,iBAAe,cAAY,CAChD;AAAA,MACC,WAAW,IAAI,CAAC,QAAQ,QACvB,oCAAC,OAAI,KAAK,KAAK,OAAO,QAAQ,KAC5B,oCAAC,QAAK,OAAO,MAAM,iBAAe,WAAG,OAAO,IAAK,GACjD,oCAAC,OAAI,UAAU,GAAG,GAClB;AAAA,QAAC;AAAA;AAAA,UACC,MAAI;AAAA,UACJ,OACE,OAAO,SAAS,cAAc,MAAM,UAAU,MAAM;AAAA;AAAA,QAGrD,OAAO,SAAS,cAAc,cAAc;AAAA,MAC/C,CACF,CACD;AAAA,IACH,IACE;AAAA,EACN,CACF;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/messages/AssistantToolUseMessage.tsx"],
|
|
4
|
-
"sourcesContent": ["import { Box, Text } from 'ink'\nimport React from 'react'\nimport { logError } from '../../utils/log'\nimport { ToolUseBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'\nimport { Tool } from '../../Tool'\nimport { Cost } from '../Cost'\nimport { ToolUseLoader } from '../ToolUseLoader'\nimport { getTheme } from '../../utils/theme'\nimport { BLACK_CIRCLE } from '../../constants/figures'\nimport { ThinkTool } from '../../tools/ThinkTool/ThinkTool'\nimport { AssistantThinkingMessage } from './AssistantThinkingMessage'\nimport { TaskToolMessage } from './TaskToolMessage'\n\ntype Props = {\n param: ToolUseBlockParam\n costUSD: number\n durationMs: number\n addMargin: boolean\n tools: Tool[]\n debug: boolean\n verbose: boolean\n erroredToolUseIDs: Set<string>\n inProgressToolUseIDs: Set<string>\n unresolvedToolUseIDs: Set<string>\n shouldAnimate: boolean\n shouldShowDot: boolean\n}\n\nexport function AssistantToolUseMessage({\n param,\n costUSD,\n durationMs,\n addMargin,\n tools,\n debug,\n verbose,\n erroredToolUseIDs,\n inProgressToolUseIDs,\n unresolvedToolUseIDs,\n shouldAnimate,\n shouldShowDot,\n}: Props): React.ReactNode {\n const tool = tools.find(_ => _.name === param.name)\n if (!tool) {\n logError(`Tool ${param.name} not found`)\n return null\n }\n const isQueued =\n !inProgressToolUseIDs.has(param.id) && unresolvedToolUseIDs.has(param.id)\n // Keeping color undefined makes the OS use the default color regardless of appearance\n const color = isQueued ? getTheme().secondaryText : undefined\n\n //
|
|
5
|
-
"mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,OAAO,WAAW;AAClB,SAAS,gBAAgB;AAGzB,SAAS,YAAY;AACrB,SAAS,qBAAqB;AAC9B,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAC7B,SAAS,iBAAiB;AAC1B,SAAS,gCAAgC;AACzC,SAAS,uBAAuB;AAiBzB,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2B;AACzB,QAAM,OAAO,MAAM,KAAK,OAAK,EAAE,SAAS,MAAM,IAAI;AAClD,MAAI,CAAC,MAAM;AACT,aAAS,QAAQ,MAAM,IAAI,YAAY;AACvC,WAAO;AAAA,EACT;AACA,QAAM,WACJ,CAAC,qBAAqB,IAAI,MAAM,EAAE,KAAK,qBAAqB,IAAI,MAAM,EAAE;AAE1E,QAAM,QAAQ,WAAW,SAAS,EAAE,gBAAgB;AAGpD,MAAI,SAAS,WAAW;
|
|
4
|
+
"sourcesContent": ["import { Box, Text } from 'ink'\nimport React from 'react'\nimport { logError } from '../../utils/log'\nimport { ToolUseBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'\nimport { Tool } from '../../Tool'\nimport { Cost } from '../Cost'\nimport { ToolUseLoader } from '../ToolUseLoader'\nimport { getTheme } from '../../utils/theme'\nimport { BLACK_CIRCLE } from '../../constants/figures'\nimport { ThinkTool } from '../../tools/ThinkTool/ThinkTool'\nimport { AssistantThinkingMessage } from './AssistantThinkingMessage'\nimport { TaskToolMessage } from './TaskToolMessage'\n\ntype Props = {\n param: ToolUseBlockParam\n costUSD: number\n durationMs: number\n addMargin: boolean\n tools: Tool[]\n debug: boolean\n verbose: boolean\n erroredToolUseIDs: Set<string>\n inProgressToolUseIDs: Set<string>\n unresolvedToolUseIDs: Set<string>\n shouldAnimate: boolean\n shouldShowDot: boolean\n}\n\nexport function AssistantToolUseMessage({\n param,\n costUSD,\n durationMs,\n addMargin,\n tools,\n debug,\n verbose,\n erroredToolUseIDs,\n inProgressToolUseIDs,\n unresolvedToolUseIDs,\n shouldAnimate,\n shouldShowDot,\n}: Props): React.ReactNode {\n const tool = tools.find(_ => _.name === param.name)\n if (!tool) {\n logError(`Tool ${param.name} not found`)\n return null\n }\n const isQueued =\n !inProgressToolUseIDs.has(param.id) && unresolvedToolUseIDs.has(param.id)\n // Keeping color undefined makes the OS use the default color regardless of appearance\n const color = isQueued ? getTheme().secondaryText : undefined\n\n // Handle thinking tool with specialized rendering\n if (tool === ThinkTool) {\n const { thought } = ThinkTool.inputSchema.parse(param.input)\n return (\n <AssistantThinkingMessage\n param={{ thinking: thought, signature: '', type: 'thinking' }}\n addMargin={addMargin}\n />\n )\n }\n\n const userFacingToolName = tool.userFacingName ? tool.userFacingName() : tool.name\n return (\n <Box\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n marginTop={addMargin ? 1 : 0}\n width=\"100%\"\n >\n <Box>\n <Box\n flexWrap=\"nowrap\"\n minWidth={userFacingToolName.length + (shouldShowDot ? 2 : 0)}\n >\n {shouldShowDot &&\n (isQueued ? (\n <Box minWidth={2}>\n <Text color={color}>{BLACK_CIRCLE}</Text>\n </Box>\n ) : (\n <ToolUseLoader\n shouldAnimate={shouldAnimate}\n isUnresolved={unresolvedToolUseIDs.has(param.id)}\n isError={erroredToolUseIDs.has(param.id)}\n />\n ))}\n {tool.name === 'Task' && param.input ? (\n <TaskToolMessage\n agentType={String((param.input as any).subagent_type || 'general-purpose')}\n bold={Boolean(!isQueued)}\n children={String(userFacingToolName || '')}\n />\n ) : (\n <Text color={color} bold={!isQueued}>\n {userFacingToolName}\n </Text>\n )}\n </Box>\n <Box flexWrap=\"nowrap\">\n {Object.keys(param.input as { [key: string]: unknown }).length > 0 &&\n (() => {\n const toolMessage = tool.renderToolUseMessage(\n param.input as never,\n {\n verbose,\n },\n )\n\n // If the tool returns a React component, render it directly\n if (React.isValidElement(toolMessage)) {\n return (\n <Box flexDirection=\"row\">\n <Text color={color}>(</Text>\n {toolMessage}\n <Text color={color}>)</Text>\n </Box>\n )\n }\n\n // If it's a string, wrap it in Text\n return <Text color={color}>({toolMessage})</Text>\n })()}\n <Text color={color}>\u2026</Text>\n </Box>\n </Box>\n <Cost costUSD={costUSD} durationMs={durationMs} debug={debug} />\n </Box>\n )\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,OAAO,WAAW;AAClB,SAAS,gBAAgB;AAGzB,SAAS,YAAY;AACrB,SAAS,qBAAqB;AAC9B,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAC7B,SAAS,iBAAiB;AAC1B,SAAS,gCAAgC;AACzC,SAAS,uBAAuB;AAiBzB,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2B;AACzB,QAAM,OAAO,MAAM,KAAK,OAAK,EAAE,SAAS,MAAM,IAAI;AAClD,MAAI,CAAC,MAAM;AACT,aAAS,QAAQ,MAAM,IAAI,YAAY;AACvC,WAAO;AAAA,EACT;AACA,QAAM,WACJ,CAAC,qBAAqB,IAAI,MAAM,EAAE,KAAK,qBAAqB,IAAI,MAAM,EAAE;AAE1E,QAAM,QAAQ,WAAW,SAAS,EAAE,gBAAgB;AAGpD,MAAI,SAAS,WAAW;AACtB,UAAM,EAAE,QAAQ,IAAI,UAAU,YAAY,MAAM,MAAM,KAAK;AAC3D,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,EAAE,UAAU,SAAS,WAAW,IAAI,MAAM,WAAW;AAAA,QAC5D;AAAA;AAAA,IACF;AAAA,EAEJ;AAEA,QAAM,qBAAqB,KAAK,iBAAiB,KAAK,eAAe,IAAI,KAAK;AAC9E,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,WAAW,YAAY,IAAI;AAAA,MAC3B,OAAM;AAAA;AAAA,IAEN,oCAAC,WACC;AAAA,MAAC;AAAA;AAAA,QACC,UAAS;AAAA,QACT,UAAU,mBAAmB,UAAU,gBAAgB,IAAI;AAAA;AAAA,MAE1D,kBACE,WACC,oCAAC,OAAI,UAAU,KACb,oCAAC,QAAK,SAAe,YAAa,CACpC,IAEA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,cAAc,qBAAqB,IAAI,MAAM,EAAE;AAAA,UAC/C,SAAS,kBAAkB,IAAI,MAAM,EAAE;AAAA;AAAA,MACzC;AAAA,MAEH,KAAK,SAAS,UAAU,MAAM,QAC7B;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,OAAQ,MAAM,MAAc,iBAAiB,iBAAiB;AAAA,UACzE,MAAM,QAAQ,CAAC,QAAQ;AAAA,UACvB,UAAU,OAAO,sBAAsB,EAAE;AAAA;AAAA,MAC3C,IAEA,oCAAC,QAAK,OAAc,MAAM,CAAC,YACxB,kBACH;AAAA,IAEJ,GACA,oCAAC,OAAI,UAAS,YACX,OAAO,KAAK,MAAM,KAAmC,EAAE,SAAS,MAC9D,MAAM;AACL,YAAM,cAAc,KAAK;AAAA,QACvB,MAAM;AAAA,QACN;AAAA,UACE;AAAA,QACF;AAAA,MACF;AAGA,UAAI,MAAM,eAAe,WAAW,GAAG;AACrC,eACE,oCAAC,OAAI,eAAc,SACjB,oCAAC,QAAK,SAAc,GAAC,GACpB,aACD,oCAAC,QAAK,SAAc,GAAC,CACvB;AAAA,MAEJ;AAGA,aAAO,oCAAC,QAAK,SAAc,KAAE,aAAY,GAAC;AAAA,IAC5C,GAAG,GACL,oCAAC,QAAK,SAAc,QAAC,CACvB,CACF;AAAA,IACA,oCAAC,QAAK,SAAkB,YAAwB,OAAc;AAAA,EAChE;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/screens/REPL.js
CHANGED
|
@@ -71,7 +71,8 @@ function REPL({
|
|
|
71
71
|
initialUpdateVersion,
|
|
72
72
|
initialUpdateCommands
|
|
73
73
|
}) {
|
|
74
|
-
const
|
|
74
|
+
const [verboseConfig] = useState(() => verboseFromCLI ?? getGlobalConfig().verbose);
|
|
75
|
+
const verbose = verboseConfig;
|
|
75
76
|
const [forkNumber, setForkNumber] = useState(
|
|
76
77
|
getNextAvailableLogForkNumber(messageLogName, initialForkNumber, 0)
|
|
77
78
|
);
|
|
@@ -346,9 +347,8 @@ function REPL({
|
|
|
346
347
|
},
|
|
347
348
|
...reorderMessages(normalizedMessages).map((_) => {
|
|
348
349
|
const toolUseID = getToolUseID(_);
|
|
349
|
-
const message = _.type === "progress" ? _.content.message.content[0]?.type === "text" && //
|
|
350
|
-
//
|
|
351
|
-
// TODO: Find a cleaner way to do this.
|
|
350
|
+
const message = _.type === "progress" ? _.content.message.content[0]?.type === "text" && // TaskTool interrupts use Progress messages without extra ⎿
|
|
351
|
+
// since <Message /> component already adds the margin
|
|
352
352
|
_.content.message.content[0].text === INTERRUPT_MESSAGE ? /* @__PURE__ */ React.createElement(
|
|
353
353
|
Message,
|
|
354
354
|
{
|
|
@@ -447,7 +447,7 @@ function REPL({
|
|
|
447
447
|
Static,
|
|
448
448
|
{
|
|
449
449
|
items: messagesJSX.filter((_) => _.type === "static"),
|
|
450
|
-
children: (
|
|
450
|
+
children: (item) => item.jsx
|
|
451
451
|
}
|
|
452
452
|
)), messagesJSX.filter((_) => _.type === "transient").map((_) => _.jsx), /* @__PURE__ */ React.createElement(
|
|
453
453
|
Box,
|
package/dist/screens/REPL.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/screens/REPL.tsx"],
|
|
4
|
-
"sourcesContent": ["import { ToolUseBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'\nimport { Box, Newline, Static, Text } from 'ink'\nimport ProjectOnboarding, {\n markProjectOnboardingComplete,\n} from '../ProjectOnboarding.js'\nimport { CostThresholdDialog } from '../components/CostThresholdDialog'\nimport * as React from 'react'\nimport { useEffect, useMemo, useRef, useState, useCallback } from 'react'\nimport { Command } from '../commands'\nimport { Logo } from '../components/Logo'\nimport { Message } from '../components/Message'\nimport { MessageResponse } from '../components/MessageResponse'\nimport { MessageSelector } from '../components/MessageSelector'\nimport {\n PermissionRequest,\n type ToolUseConfirm,\n} from '../components/permissions/PermissionRequest.js'\nimport PromptInput from '../components/PromptInput'\nimport { Spinner } from '../components/Spinner'\nimport { getSystemPrompt } from '../constants/prompts'\nimport { getContext } from '../context'\nimport { getTotalCost, useCostSummary } from '../cost-tracker'\nimport { useLogStartupTime } from '../hooks/useLogStartupTime'\nimport { addToHistory } from '../history'\nimport { useApiKeyVerification } from '../hooks/useApiKeyVerification'\nimport { useCancelRequest } from '../hooks/useCancelRequest'\nimport useCanUseTool from '../hooks/useCanUseTool'\nimport { useLogMessages } from '../hooks/useLogMessages'\nimport { PermissionProvider } from '../context/PermissionContext'\nimport { ModeIndicator } from '../components/ModeIndicator'\nimport {\n setMessagesGetter,\n setMessagesSetter,\n setModelConfigChangeHandler,\n} from '../messages'\nimport {\n type AssistantMessage,\n type BinaryFeedbackResult,\n type Message as MessageType,\n type ProgressMessage,\n query,\n} from '../query.js'\nimport type { WrappedClient } from '../services/mcpClient'\nimport type { Tool } from '../Tool'\nimport { AutoUpdaterResult } from '../utils/autoUpdater'\nimport { getGlobalConfig, saveGlobalConfig } from '../utils/config'\nimport { MACRO } from '../constants/macros'\nimport { logEvent } from '../services/statsig'\nimport { getNextAvailableLogForkNumber } from '../utils/log'\nimport {\n getErroredToolUseMessages,\n getInProgressToolUseIDs,\n getLastAssistantMessageId,\n getToolUseID,\n getUnresolvedToolUseIDs,\n INTERRUPT_MESSAGE,\n isNotEmptyMessage,\n type NormalizedMessage,\n normalizeMessages,\n normalizeMessagesForAPI,\n processUserInput,\n reorderMessages,\n extractTag,\n createAssistantMessage,\n} from '../utils/messages.js'\nimport { getModelManager, ModelManager } from '../utils/model'\nimport { clearTerminal, updateTerminalTitle } from '../utils/terminal'\nimport { BinaryFeedback } from '../components/binary-feedback/BinaryFeedback'\nimport { getMaxThinkingTokens } from '../utils/thinking'\nimport { getOriginalCwd } from '../utils/state'\nimport { handleHashCommand } from '../commands/terminalSetup'\nimport { debug as debugLogger } from '../utils/debugLogger'\n\ntype Props = {\n commands: Command[]\n safeMode?: boolean\n debug?: boolean\n initialForkNumber?: number | undefined\n initialPrompt: string | undefined\n // A unique name for the message log file, used to identify the fork\n messageLogName: string\n shouldShowPromptInput: boolean\n tools: Tool[]\n verbose: boolean | undefined\n // Initial messages to populate the REPL with\n initialMessages?: MessageType[]\n // MCP clients\n mcpClients?: WrappedClient[]\n // Flag to indicate if current model is default\n isDefaultModel?: boolean\n // Update banner info passed from CLI before first render\n initialUpdateVersion?: string | null\n initialUpdateCommands?: string[] | null\n}\n\nexport type BinaryFeedbackContext = {\n m1: AssistantMessage\n m2: AssistantMessage\n resolve: (result: BinaryFeedbackResult) => void\n}\n\nexport function REPL({\n commands,\n safeMode,\n debug = false,\n initialForkNumber = 0,\n initialPrompt,\n messageLogName,\n shouldShowPromptInput,\n tools,\n verbose: verboseFromCLI,\n initialMessages,\n mcpClients = [],\n isDefaultModel = true,\n initialUpdateVersion,\n initialUpdateCommands,\n}: Props): React.ReactNode {\n // TODO: probably shouldn't re-read config from file synchronously on every keystroke\n const verbose = verboseFromCLI ?? getGlobalConfig().verbose\n\n // Used to force the logo to re-render and conversation log to use a new file\n const [forkNumber, setForkNumber] = useState(\n getNextAvailableLogForkNumber(messageLogName, initialForkNumber, 0),\n )\n\n const [\n forkConvoWithMessagesOnTheNextRender,\n setForkConvoWithMessagesOnTheNextRender,\n ] = useState<MessageType[] | null>(null)\n\n // \uD83D\uDD27 Simplified AbortController management - inspired by reference system\n const [abortController, setAbortController] = useState<AbortController | null>(null)\n const [isLoading, setIsLoading] = useState(false)\n const [autoUpdaterResult, setAutoUpdaterResult] =\n useState<AutoUpdaterResult | null>(null)\n const [toolJSX, setToolJSX] = useState<{\n jsx: React.ReactNode | null\n shouldHidePromptInput: boolean\n } | null>(null)\n const [toolUseConfirm, setToolUseConfirm] = useState<ToolUseConfirm | null>(\n null,\n )\n const [messages, setMessages] = useState<MessageType[]>(initialMessages ?? [])\n const [inputValue, setInputValue] = useState('')\n const [inputMode, setInputMode] = useState<'bash' | 'prompt' | 'koding'>(\n 'prompt',\n )\n const [submitCount, setSubmitCount] = useState(0)\n const [isMessageSelectorVisible, setIsMessageSelectorVisible] =\n useState(false)\n const [showCostDialog, setShowCostDialog] = useState(false)\n const [haveShownCostDialog, setHaveShownCostDialog] = useState(\n getGlobalConfig().hasAcknowledgedCostThreshold,\n )\n\n const [binaryFeedbackContext, setBinaryFeedbackContext] =\n useState<BinaryFeedbackContext | null>(null)\n // New version banner: passed in from CLI to guarantee top placement\n const updateAvailableVersion = initialUpdateVersion ?? null\n const updateCommands = initialUpdateCommands ?? null\n // No separate Static for banner; it renders inside Logo\n\n const getBinaryFeedbackResponse = useCallback(\n (\n m1: AssistantMessage,\n m2: AssistantMessage,\n ): Promise<BinaryFeedbackResult> => {\n return new Promise<BinaryFeedbackResult>(resolvePromise => {\n setBinaryFeedbackContext({\n m1,\n m2,\n resolve: resolvePromise,\n })\n })\n },\n [],\n )\n\n const readFileTimestamps = useRef<{\n [filename: string]: number\n }>({})\n\n const { status: apiKeyStatus, reverify } = useApiKeyVerification()\n function onCancel() {\n if (!isLoading) {\n return\n }\n setIsLoading(false)\n if (toolUseConfirm) {\n toolUseConfirm.onAbort()\n } else if (abortController && !abortController.signal.aborted) {\n abortController.abort()\n }\n }\n\n useCancelRequest(\n setToolJSX,\n setToolUseConfirm,\n setBinaryFeedbackContext,\n onCancel,\n isLoading,\n isMessageSelectorVisible,\n abortController?.signal,\n )\n\n useEffect(() => {\n if (forkConvoWithMessagesOnTheNextRender) {\n setForkNumber(_ => _ + 1)\n setForkConvoWithMessagesOnTheNextRender(null)\n setMessages(forkConvoWithMessagesOnTheNextRender)\n }\n }, [forkConvoWithMessagesOnTheNextRender])\n\n useEffect(() => {\n const totalCost = getTotalCost()\n if (totalCost >= 5 /* $5 */ && !showCostDialog && !haveShownCostDialog) {\n logEvent('tengu_cost_threshold_reached', {})\n setShowCostDialog(true)\n }\n }, [messages, showCostDialog, haveShownCostDialog])\n\n // Update banner is provided by CLI at startup; no async check here.\n\n const canUseTool = useCanUseTool(setToolUseConfirm)\n\n async function onInit() {\n reverify()\n\n if (!initialPrompt) {\n return\n }\n\n setIsLoading(true)\n\n const newAbortController = new AbortController()\n setAbortController(newAbortController)\n\n // \uD83D\uDD27 Force fresh config read to ensure model switching works\n const model = new ModelManager(getGlobalConfig()).getModelName('main')\n const newMessages = await processUserInput(\n initialPrompt,\n 'prompt',\n setToolJSX,\n {\n abortController: newAbortController,\n options: {\n commands,\n forkNumber,\n messageLogName,\n tools,\n verbose,\n maxThinkingTokens: 0,\n },\n messageId: getLastAssistantMessageId(messages),\n setForkConvoWithMessagesOnTheNextRender,\n readFileTimestamps: readFileTimestamps.current,\n },\n null,\n )\n\n if (newMessages.length) {\n for (const message of newMessages) {\n if (message.type === 'user') {\n addToHistory(initialPrompt)\n // TODO: setHistoryIndex\n }\n }\n setMessages(_ => [..._, ...newMessages])\n\n // The last message is an assistant message if the user input was a bash command,\n // or if the user input was an invalid slash command.\n const lastMessage = newMessages[newMessages.length - 1]!\n if (lastMessage.type === 'assistant') {\n setAbortController(null)\n setIsLoading(false)\n return\n }\n\n const [systemPrompt, context, model, maxThinkingTokens] =\n await Promise.all([\n getSystemPrompt(),\n getContext(),\n new ModelManager(getGlobalConfig()).getModelName('main'),\n getMaxThinkingTokens([...messages, ...newMessages]),\n ])\n\n for await (const message of query(\n [...messages, ...newMessages],\n systemPrompt,\n context,\n canUseTool,\n {\n options: {\n commands,\n forkNumber,\n messageLogName,\n tools,\n verbose,\n safeMode,\n maxThinkingTokens,\n },\n messageId: getLastAssistantMessageId([...messages, ...newMessages]),\n readFileTimestamps: readFileTimestamps.current,\n abortController: newAbortController,\n setToolJSX,\n },\n getBinaryFeedbackResponse,\n )) {\n setMessages(oldMessages => [...oldMessages, message])\n }\n } else {\n addToHistory(initialPrompt)\n // TODO: setHistoryIndex\n }\n\n setHaveShownCostDialog(\n getGlobalConfig().hasAcknowledgedCostThreshold || false,\n )\n\n // \uD83D\uDD27 Fix: Clean up state after onInit completion\n setIsLoading(false)\n setAbortController(null)\n }\n\n async function onQuery(newMessages: MessageType[], passedAbortController?: AbortController) {\n // Use passed AbortController or create new one\n const controllerToUse = passedAbortController || new AbortController()\n if (!passedAbortController) {\n setAbortController(controllerToUse)\n }\n\n // Check if this is a Koding request based on last message's options\n const isKodingRequest =\n newMessages.length > 0 &&\n newMessages[0].type === 'user' &&\n 'options' in newMessages[0] &&\n newMessages[0].options?.isKodingRequest === true\n\n setMessages(oldMessages => [...oldMessages, ...newMessages])\n\n // Mark onboarding as complete when any user message is sent to Claude\n markProjectOnboardingComplete()\n\n // The last message is an assistant message if the user input was a bash command,\n // or if the user input was an invalid slash command.\n const lastMessage = newMessages[newMessages.length - 1]!\n\n // Update terminal title based on user message\n if (\n lastMessage.type === 'user' &&\n typeof lastMessage.message.content === 'string'\n ) {\n // updateTerminalTitle(lastMessage.message.content)\n }\n if (lastMessage.type === 'assistant') {\n setAbortController(null)\n setIsLoading(false)\n return\n }\n\n const [systemPrompt, context, model, maxThinkingTokens] =\n await Promise.all([\n getSystemPrompt(),\n getContext(),\n new ModelManager(getGlobalConfig()).getModelName('main'),\n getMaxThinkingTokens([...messages, lastMessage]),\n ])\n\n let lastAssistantMessage: MessageType | null = null\n\n // query the API\n for await (const message of query(\n [...messages, lastMessage],\n systemPrompt,\n context,\n canUseTool,\n {\n options: {\n commands,\n forkNumber,\n messageLogName,\n tools,\n verbose,\n safeMode,\n maxThinkingTokens,\n // If this came from Koding mode, pass that along\n isKodingRequest: isKodingRequest || undefined,\n },\n messageId: getLastAssistantMessageId([...messages, lastMessage]),\n readFileTimestamps: readFileTimestamps.current,\n abortController: controllerToUse,\n setToolJSX,\n },\n getBinaryFeedbackResponse,\n )) {\n setMessages(oldMessages => [...oldMessages, message])\n\n // Keep track of the last assistant message for Koding mode\n if (message.type === 'assistant') {\n lastAssistantMessage = message\n }\n }\n\n // If this was a Koding request and we got an assistant message back,\n // save it to AGENTS.md (and CLAUDE.md if exists)\n if (\n isKodingRequest &&\n lastAssistantMessage &&\n lastAssistantMessage.type === 'assistant'\n ) {\n try {\n const content =\n typeof lastAssistantMessage.message.content === 'string'\n ? lastAssistantMessage.message.content\n : lastAssistantMessage.message.content\n .filter(block => block.type === 'text')\n .map(block => (block.type === 'text' ? block.text : ''))\n .join('\\n')\n\n // Add the content to AGENTS.md (and CLAUDE.md if exists)\n if (content && content.trim().length > 0) {\n handleHashCommand(content)\n }\n } catch (error) {\n console.error('Error saving response to project docs:', error)\n }\n }\n\n setIsLoading(false)\n }\n\n // Register cost summary tracker\n useCostSummary()\n\n // Register messages getter and setter\n useEffect(() => {\n const getMessages = () => messages\n setMessagesGetter(getMessages)\n setMessagesSetter(setMessages)\n }, [messages])\n\n // Register model config change handler for UI refresh\n useEffect(() => {\n setModelConfigChangeHandler(() => {\n setForkNumber(prev => prev + 1)\n })\n }, [])\n\n // Record transcripts locally, for debugging and conversation recovery\n useLogMessages(messages, messageLogName, forkNumber)\n\n // Log startup time\n useLogStartupTime()\n\n // Initial load\n useEffect(() => {\n onInit()\n // TODO: fix this\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const normalizedMessages = useMemo(\n () => normalizeMessages(messages).filter(isNotEmptyMessage),\n [messages],\n )\n\n const unresolvedToolUseIDs = useMemo(\n () => getUnresolvedToolUseIDs(normalizedMessages),\n [normalizedMessages],\n )\n\n const inProgressToolUseIDs = useMemo(\n () => getInProgressToolUseIDs(normalizedMessages),\n [normalizedMessages],\n )\n\n const erroredToolUseIDs = useMemo(\n () =>\n new Set(\n getErroredToolUseMessages(normalizedMessages).map(\n _ => (_.message.content[0]! as ToolUseBlockParam).id,\n ),\n ),\n [normalizedMessages],\n )\n\n const messagesJSX = useMemo(() => {\n return [\n {\n type: 'static',\n jsx: (\n <Box flexDirection=\"column\" key={`logo${forkNumber}`}>\n <Logo\n mcpClients={mcpClients}\n isDefaultModel={isDefaultModel}\n updateBannerVersion={updateAvailableVersion}\n updateBannerCommands={updateCommands}\n />\n <ProjectOnboarding workspaceDir={getOriginalCwd()} />\n </Box>\n ),\n },\n ...reorderMessages(normalizedMessages).map(_ => {\n const toolUseID = getToolUseID(_)\n const message =\n _.type === 'progress' ? (\n _.content.message.content[0]?.type === 'text' &&\n // Hack: TaskTool interrupts use Progress messages, so don't\n // need an extra \u23BF because <Message /> already adds one.\n // TODO: Find a cleaner way to do this.\n _.content.message.content[0].text === INTERRUPT_MESSAGE ? (\n <Message\n message={_.content}\n messages={_.normalizedMessages}\n addMargin={false}\n tools={_.tools}\n verbose={verbose ?? false}\n debug={debug}\n erroredToolUseIDs={new Set()}\n inProgressToolUseIDs={new Set()}\n unresolvedToolUseIDs={new Set()}\n shouldAnimate={false}\n shouldShowDot={false}\n />\n ) : (\n <MessageResponse children={\n <Message\n message={_.content}\n messages={_.normalizedMessages}\n addMargin={false}\n tools={_.tools}\n verbose={verbose ?? false}\n debug={debug}\n erroredToolUseIDs={new Set()}\n inProgressToolUseIDs={new Set()}\n unresolvedToolUseIDs={\n new Set([\n (_.content.message.content[0]! as ToolUseBlockParam).id,\n ])\n }\n shouldAnimate={false}\n shouldShowDot={false}\n />\n } />\n )\n ) : (\n <Message\n message={_}\n messages={normalizedMessages}\n addMargin={true}\n tools={tools}\n verbose={verbose}\n debug={debug}\n erroredToolUseIDs={erroredToolUseIDs}\n inProgressToolUseIDs={inProgressToolUseIDs}\n shouldAnimate={\n !toolJSX &&\n !toolUseConfirm &&\n !isMessageSelectorVisible &&\n (!toolUseID || inProgressToolUseIDs.has(toolUseID))\n }\n shouldShowDot={true}\n unresolvedToolUseIDs={unresolvedToolUseIDs}\n />\n )\n\n const type = shouldRenderStatically(\n _,\n normalizedMessages,\n unresolvedToolUseIDs,\n )\n ? 'static'\n : 'transient'\n\n if (debug) {\n return {\n type,\n jsx: (\n <Box\n borderStyle=\"single\"\n borderColor={type === 'static' ? 'green' : 'red'}\n key={_.uuid}\n width=\"100%\"\n >\n {message}\n </Box>\n ),\n }\n }\n\n return {\n type,\n jsx: (\n <Box key={_.uuid} width=\"100%\">\n {message}\n </Box>\n ),\n }\n }),\n ]\n }, [\n forkNumber,\n normalizedMessages,\n tools,\n verbose,\n debug,\n erroredToolUseIDs,\n inProgressToolUseIDs,\n toolJSX,\n toolUseConfirm,\n isMessageSelectorVisible,\n unresolvedToolUseIDs,\n mcpClients,\n isDefaultModel,\n ])\n\n // only show the dialog once not loading\n const showingCostDialog = !isLoading && showCostDialog\n\n return (\n <PermissionProvider \n isBypassPermissionsModeAvailable={!safeMode}\n children={\n <React.Fragment>\n {/* Update banner now renders inside Logo for stable placement */}\n <ModeIndicator />\n <React.Fragment key={`static-messages-${forkNumber}`}>\n <Static\n items={messagesJSX.filter(_ => _.type === 'static')}\n children={_ => ((_ as any).jsx)}\n />\n </React.Fragment>\n {messagesJSX.filter(_ => _.type === 'transient').map(_ => _.jsx)}\n <Box\n borderColor=\"red\"\n borderStyle={debug ? 'single' : undefined}\n flexDirection=\"column\"\n width=\"100%\"\n >\n {!toolJSX && !toolUseConfirm && !binaryFeedbackContext && isLoading && (\n <Spinner />\n )}\n {toolJSX ? toolJSX.jsx : null}\n {!toolJSX && binaryFeedbackContext && !isMessageSelectorVisible && (\n <BinaryFeedback\n m1={binaryFeedbackContext.m1}\n m2={binaryFeedbackContext.m2}\n resolve={result => {\n binaryFeedbackContext.resolve(result)\n setTimeout(() => setBinaryFeedbackContext(null), 0)\n }}\n verbose={verbose}\n normalizedMessages={normalizedMessages}\n tools={tools}\n debug={debug}\n erroredToolUseIDs={erroredToolUseIDs}\n inProgressToolUseIDs={inProgressToolUseIDs}\n unresolvedToolUseIDs={unresolvedToolUseIDs}\n />\n )}\n {!toolJSX &&\n toolUseConfirm &&\n !isMessageSelectorVisible &&\n !binaryFeedbackContext && (\n <PermissionRequest\n toolUseConfirm={toolUseConfirm}\n onDone={() => setToolUseConfirm(null)}\n verbose={verbose}\n />\n )}\n {!toolJSX &&\n !toolUseConfirm &&\n !isMessageSelectorVisible &&\n !binaryFeedbackContext &&\n showingCostDialog && (\n <CostThresholdDialog\n onDone={() => {\n setShowCostDialog(false)\n setHaveShownCostDialog(true)\n const projectConfig = getGlobalConfig()\n saveGlobalConfig({\n ...projectConfig,\n hasAcknowledgedCostThreshold: true,\n })\n logEvent('tengu_cost_threshold_acknowledged', {})\n }}\n />\n )}\n\n {!toolUseConfirm &&\n !toolJSX?.shouldHidePromptInput &&\n shouldShowPromptInput &&\n !isMessageSelectorVisible &&\n !binaryFeedbackContext &&\n !showingCostDialog && (\n <>\n <PromptInput\n commands={commands}\n forkNumber={forkNumber}\n messageLogName={messageLogName}\n tools={tools}\n isDisabled={apiKeyStatus === 'invalid'}\n isLoading={isLoading}\n onQuery={onQuery}\n debug={debug}\n verbose={verbose}\n messages={messages}\n setToolJSX={setToolJSX}\n onAutoUpdaterResult={setAutoUpdaterResult}\n autoUpdaterResult={autoUpdaterResult}\n input={inputValue}\n onInputChange={setInputValue}\n mode={inputMode}\n onModeChange={setInputMode}\n submitCount={submitCount}\n onSubmitCountChange={setSubmitCount}\n setIsLoading={setIsLoading}\n setAbortController={setAbortController}\n onShowMessageSelector={() =>\n setIsMessageSelectorVisible(prev => !prev)\n }\n setForkConvoWithMessagesOnTheNextRender={\n setForkConvoWithMessagesOnTheNextRender\n }\n readFileTimestamps={readFileTimestamps.current}\n abortController={abortController}\n onModelChange={() => setForkNumber(prev => prev + 1)}\n />\n </>\n )}\n </Box>\n {isMessageSelectorVisible && (\n <MessageSelector\n erroredToolUseIDs={erroredToolUseIDs}\n unresolvedToolUseIDs={unresolvedToolUseIDs}\n messages={normalizeMessagesForAPI(messages)}\n onSelect={async message => {\n setIsMessageSelectorVisible(false)\n\n // If the user selected the current prompt, do nothing\n if (!messages.includes(message)) {\n return\n }\n\n // Cancel tool use calls/requests\n onCancel()\n\n // Hack: make sure the \"Interrupted by user\" message is\n // rendered in response to the cancellation. Otherwise,\n // the screen will be cleared but there will remain a\n // vestigial \"Interrupted by user\" message at the top.\n setImmediate(async () => {\n // Clear messages, and re-render\n await clearTerminal()\n setMessages([])\n setForkConvoWithMessagesOnTheNextRender(\n messages.slice(0, messages.indexOf(message)),\n )\n\n // Populate/reset the prompt input\n if (typeof message.message.content === 'string') {\n setInputValue(message.message.content)\n }\n })\n }}\n onEscape={() => setIsMessageSelectorVisible(false)}\n tools={tools}\n />\n )}\n {/** Fix occasional rendering artifact */}\n <Newline />\n </React.Fragment>\n }\n />\n )\n}\n\nfunction shouldRenderStatically(\n message: NormalizedMessage,\n messages: NormalizedMessage[],\n unresolvedToolUseIDs: Set<string>,\n): boolean {\n switch (message.type) {\n case 'user':\n case 'assistant': {\n const toolUseID = getToolUseID(message)\n if (!toolUseID) {\n return true\n }\n if (unresolvedToolUseIDs.has(toolUseID)) {\n return false\n }\n\n const correspondingProgressMessage = messages.find(\n _ => _.type === 'progress' && _.toolUseID === toolUseID,\n ) as ProgressMessage | null\n if (!correspondingProgressMessage) {\n return true\n }\n\n return !intersects(\n unresolvedToolUseIDs,\n correspondingProgressMessage.siblingToolUseIDs,\n )\n }\n case 'progress':\n return !intersects(unresolvedToolUseIDs, message.siblingToolUseIDs)\n }\n}\n\nfunction intersects<A>(a: Set<A>, b: Set<A>): boolean {\n return a.size > 0 && b.size > 0 && [...a].some(_ => b.has(_))\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { ToolUseBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'\nimport { Box, Newline, Static, Text } from 'ink'\nimport ProjectOnboarding, {\n markProjectOnboardingComplete,\n} from '../ProjectOnboarding.js'\nimport { CostThresholdDialog } from '../components/CostThresholdDialog'\nimport * as React from 'react'\nimport { useEffect, useMemo, useRef, useState, useCallback } from 'react'\nimport { Command } from '../commands'\nimport { Logo } from '../components/Logo'\nimport { Message } from '../components/Message'\nimport { MessageResponse } from '../components/MessageResponse'\nimport { MessageSelector } from '../components/MessageSelector'\nimport {\n PermissionRequest,\n type ToolUseConfirm,\n} from '../components/permissions/PermissionRequest.js'\nimport PromptInput from '../components/PromptInput'\nimport { Spinner } from '../components/Spinner'\nimport { getSystemPrompt } from '../constants/prompts'\nimport { getContext } from '../context'\nimport { getTotalCost, useCostSummary } from '../cost-tracker'\nimport { useLogStartupTime } from '../hooks/useLogStartupTime'\nimport { addToHistory } from '../history'\nimport { useApiKeyVerification } from '../hooks/useApiKeyVerification'\nimport { useCancelRequest } from '../hooks/useCancelRequest'\nimport useCanUseTool from '../hooks/useCanUseTool'\nimport { useLogMessages } from '../hooks/useLogMessages'\nimport { PermissionProvider } from '../context/PermissionContext'\nimport { ModeIndicator } from '../components/ModeIndicator'\nimport {\n setMessagesGetter,\n setMessagesSetter,\n setModelConfigChangeHandler,\n} from '../messages'\nimport {\n type AssistantMessage,\n type BinaryFeedbackResult,\n type Message as MessageType,\n type ProgressMessage,\n query,\n} from '../query.js'\nimport type { WrappedClient } from '../services/mcpClient'\nimport type { Tool } from '../Tool'\nimport { AutoUpdaterResult } from '../utils/autoUpdater'\nimport { getGlobalConfig, saveGlobalConfig } from '../utils/config'\nimport { MACRO } from '../constants/macros'\nimport { logEvent } from '../services/statsig'\nimport { getNextAvailableLogForkNumber } from '../utils/log'\nimport {\n getErroredToolUseMessages,\n getInProgressToolUseIDs,\n getLastAssistantMessageId,\n getToolUseID,\n getUnresolvedToolUseIDs,\n INTERRUPT_MESSAGE,\n isNotEmptyMessage,\n type NormalizedMessage,\n normalizeMessages,\n normalizeMessagesForAPI,\n processUserInput,\n reorderMessages,\n extractTag,\n createAssistantMessage,\n} from '../utils/messages.js'\nimport { getModelManager, ModelManager } from '../utils/model'\nimport { clearTerminal, updateTerminalTitle } from '../utils/terminal'\nimport { BinaryFeedback } from '../components/binary-feedback/BinaryFeedback'\nimport { getMaxThinkingTokens } from '../utils/thinking'\nimport { getOriginalCwd } from '../utils/state'\nimport { handleHashCommand } from '../commands/terminalSetup'\nimport { debug as debugLogger } from '../utils/debugLogger'\n\ntype Props = {\n commands: Command[]\n safeMode?: boolean\n debug?: boolean\n initialForkNumber?: number | undefined\n initialPrompt: string | undefined\n // A unique name for the message log file, used to identify the fork\n messageLogName: string\n shouldShowPromptInput: boolean\n tools: Tool[]\n verbose: boolean | undefined\n // Initial messages to populate the REPL with\n initialMessages?: MessageType[]\n // MCP clients\n mcpClients?: WrappedClient[]\n // Flag to indicate if current model is default\n isDefaultModel?: boolean\n // Update banner info passed from CLI before first render\n initialUpdateVersion?: string | null\n initialUpdateCommands?: string[] | null\n}\n\nexport type BinaryFeedbackContext = {\n m1: AssistantMessage\n m2: AssistantMessage\n resolve: (result: BinaryFeedbackResult) => void\n}\n\nexport function REPL({\n commands,\n safeMode,\n debug = false,\n initialForkNumber = 0,\n initialPrompt,\n messageLogName,\n shouldShowPromptInput,\n tools,\n verbose: verboseFromCLI,\n initialMessages,\n mcpClients = [],\n isDefaultModel = true,\n initialUpdateVersion,\n initialUpdateCommands,\n}: Props): React.ReactNode {\n // Cache verbose config to avoid synchronous file reads on every render\n const [verboseConfig] = useState(() => verboseFromCLI ?? getGlobalConfig().verbose)\n const verbose = verboseConfig\n\n // Used to force the logo to re-render and conversation log to use a new file\n const [forkNumber, setForkNumber] = useState(\n getNextAvailableLogForkNumber(messageLogName, initialForkNumber, 0),\n )\n\n const [\n forkConvoWithMessagesOnTheNextRender,\n setForkConvoWithMessagesOnTheNextRender,\n ] = useState<MessageType[] | null>(null)\n\n // \uD83D\uDD27 Simplified AbortController management - inspired by reference system\n const [abortController, setAbortController] = useState<AbortController | null>(null)\n const [isLoading, setIsLoading] = useState(false)\n const [autoUpdaterResult, setAutoUpdaterResult] =\n useState<AutoUpdaterResult | null>(null)\n const [toolJSX, setToolJSX] = useState<{\n jsx: React.ReactNode | null\n shouldHidePromptInput: boolean\n } | null>(null)\n const [toolUseConfirm, setToolUseConfirm] = useState<ToolUseConfirm | null>(\n null,\n )\n const [messages, setMessages] = useState<MessageType[]>(initialMessages ?? [])\n const [inputValue, setInputValue] = useState('')\n const [inputMode, setInputMode] = useState<'bash' | 'prompt' | 'koding'>(\n 'prompt',\n )\n const [submitCount, setSubmitCount] = useState(0)\n const [isMessageSelectorVisible, setIsMessageSelectorVisible] =\n useState(false)\n const [showCostDialog, setShowCostDialog] = useState(false)\n const [haveShownCostDialog, setHaveShownCostDialog] = useState(\n getGlobalConfig().hasAcknowledgedCostThreshold,\n )\n\n const [binaryFeedbackContext, setBinaryFeedbackContext] =\n useState<BinaryFeedbackContext | null>(null)\n // New version banner: passed in from CLI to guarantee top placement\n const updateAvailableVersion = initialUpdateVersion ?? null\n const updateCommands = initialUpdateCommands ?? null\n // No separate Static for banner; it renders inside Logo\n\n const getBinaryFeedbackResponse = useCallback(\n (\n m1: AssistantMessage,\n m2: AssistantMessage,\n ): Promise<BinaryFeedbackResult> => {\n return new Promise<BinaryFeedbackResult>(resolvePromise => {\n setBinaryFeedbackContext({\n m1,\n m2,\n resolve: resolvePromise,\n })\n })\n },\n [],\n )\n\n const readFileTimestamps = useRef<{\n [filename: string]: number\n }>({})\n\n const { status: apiKeyStatus, reverify } = useApiKeyVerification()\n function onCancel() {\n if (!isLoading) {\n return\n }\n setIsLoading(false)\n if (toolUseConfirm) {\n toolUseConfirm.onAbort()\n } else if (abortController && !abortController.signal.aborted) {\n abortController.abort()\n }\n }\n\n useCancelRequest(\n setToolJSX,\n setToolUseConfirm,\n setBinaryFeedbackContext,\n onCancel,\n isLoading,\n isMessageSelectorVisible,\n abortController?.signal,\n )\n\n useEffect(() => {\n if (forkConvoWithMessagesOnTheNextRender) {\n setForkNumber(_ => _ + 1)\n setForkConvoWithMessagesOnTheNextRender(null)\n setMessages(forkConvoWithMessagesOnTheNextRender)\n }\n }, [forkConvoWithMessagesOnTheNextRender])\n\n useEffect(() => {\n const totalCost = getTotalCost()\n if (totalCost >= 5 /* $5 */ && !showCostDialog && !haveShownCostDialog) {\n logEvent('tengu_cost_threshold_reached', {})\n setShowCostDialog(true)\n }\n }, [messages, showCostDialog, haveShownCostDialog])\n\n // Update banner is provided by CLI at startup; no async check here.\n\n const canUseTool = useCanUseTool(setToolUseConfirm)\n\n async function onInit() {\n reverify()\n\n if (!initialPrompt) {\n return\n }\n\n setIsLoading(true)\n\n const newAbortController = new AbortController()\n setAbortController(newAbortController)\n\n // \uD83D\uDD27 Force fresh config read to ensure model switching works\n const model = new ModelManager(getGlobalConfig()).getModelName('main')\n const newMessages = await processUserInput(\n initialPrompt,\n 'prompt',\n setToolJSX,\n {\n abortController: newAbortController,\n options: {\n commands,\n forkNumber,\n messageLogName,\n tools,\n verbose,\n maxThinkingTokens: 0,\n },\n messageId: getLastAssistantMessageId(messages),\n setForkConvoWithMessagesOnTheNextRender,\n readFileTimestamps: readFileTimestamps.current,\n },\n null,\n )\n\n if (newMessages.length) {\n for (const message of newMessages) {\n if (message.type === 'user') {\n addToHistory(initialPrompt)\n // TODO: setHistoryIndex\n }\n }\n setMessages(_ => [..._, ...newMessages])\n\n // The last message is an assistant message if the user input was a bash command,\n // or if the user input was an invalid slash command.\n const lastMessage = newMessages[newMessages.length - 1]!\n if (lastMessage.type === 'assistant') {\n setAbortController(null)\n setIsLoading(false)\n return\n }\n\n const [systemPrompt, context, model, maxThinkingTokens] =\n await Promise.all([\n getSystemPrompt(),\n getContext(),\n new ModelManager(getGlobalConfig()).getModelName('main'),\n getMaxThinkingTokens([...messages, ...newMessages]),\n ])\n\n for await (const message of query(\n [...messages, ...newMessages],\n systemPrompt,\n context,\n canUseTool,\n {\n options: {\n commands,\n forkNumber,\n messageLogName,\n tools,\n verbose,\n safeMode,\n maxThinkingTokens,\n },\n messageId: getLastAssistantMessageId([...messages, ...newMessages]),\n readFileTimestamps: readFileTimestamps.current,\n abortController: newAbortController,\n setToolJSX,\n },\n getBinaryFeedbackResponse,\n )) {\n setMessages(oldMessages => [...oldMessages, message])\n }\n } else {\n addToHistory(initialPrompt)\n // TODO: setHistoryIndex\n }\n\n setHaveShownCostDialog(\n getGlobalConfig().hasAcknowledgedCostThreshold || false,\n )\n\n // \uD83D\uDD27 Fix: Clean up state after onInit completion\n setIsLoading(false)\n setAbortController(null)\n }\n\n async function onQuery(newMessages: MessageType[], passedAbortController?: AbortController) {\n // Use passed AbortController or create new one\n const controllerToUse = passedAbortController || new AbortController()\n if (!passedAbortController) {\n setAbortController(controllerToUse)\n }\n\n // Check if this is a Koding request based on last message's options\n const isKodingRequest =\n newMessages.length > 0 &&\n newMessages[0].type === 'user' &&\n 'options' in newMessages[0] &&\n newMessages[0].options?.isKodingRequest === true\n\n setMessages(oldMessages => [...oldMessages, ...newMessages])\n\n // Mark onboarding as complete when any user message is sent to Claude\n markProjectOnboardingComplete()\n\n // The last message is an assistant message if the user input was a bash command,\n // or if the user input was an invalid slash command.\n const lastMessage = newMessages[newMessages.length - 1]!\n\n // Update terminal title based on user message\n if (\n lastMessage.type === 'user' &&\n typeof lastMessage.message.content === 'string'\n ) {\n // updateTerminalTitle(lastMessage.message.content)\n }\n if (lastMessage.type === 'assistant') {\n setAbortController(null)\n setIsLoading(false)\n return\n }\n\n const [systemPrompt, context, model, maxThinkingTokens] =\n await Promise.all([\n getSystemPrompt(),\n getContext(),\n new ModelManager(getGlobalConfig()).getModelName('main'),\n getMaxThinkingTokens([...messages, lastMessage]),\n ])\n\n let lastAssistantMessage: MessageType | null = null\n\n // query the API\n for await (const message of query(\n [...messages, lastMessage],\n systemPrompt,\n context,\n canUseTool,\n {\n options: {\n commands,\n forkNumber,\n messageLogName,\n tools,\n verbose,\n safeMode,\n maxThinkingTokens,\n // If this came from Koding mode, pass that along\n isKodingRequest: isKodingRequest || undefined,\n },\n messageId: getLastAssistantMessageId([...messages, lastMessage]),\n readFileTimestamps: readFileTimestamps.current,\n abortController: controllerToUse,\n setToolJSX,\n },\n getBinaryFeedbackResponse,\n )) {\n setMessages(oldMessages => [...oldMessages, message])\n\n // Keep track of the last assistant message for Koding mode\n if (message.type === 'assistant') {\n lastAssistantMessage = message\n }\n }\n\n // If this was a Koding request and we got an assistant message back,\n // save it to AGENTS.md (and CLAUDE.md if exists)\n if (\n isKodingRequest &&\n lastAssistantMessage &&\n lastAssistantMessage.type === 'assistant'\n ) {\n try {\n const content =\n typeof lastAssistantMessage.message.content === 'string'\n ? lastAssistantMessage.message.content\n : lastAssistantMessage.message.content\n .filter(block => block.type === 'text')\n .map(block => (block.type === 'text' ? block.text : ''))\n .join('\\n')\n\n // Add the content to AGENTS.md (and CLAUDE.md if exists)\n if (content && content.trim().length > 0) {\n handleHashCommand(content)\n }\n } catch (error) {\n console.error('Error saving response to project docs:', error)\n }\n }\n\n setIsLoading(false)\n }\n\n // Register cost summary tracker\n useCostSummary()\n\n // Register messages getter and setter\n useEffect(() => {\n const getMessages = () => messages\n setMessagesGetter(getMessages)\n setMessagesSetter(setMessages)\n }, [messages])\n\n // Register model config change handler for UI refresh\n useEffect(() => {\n setModelConfigChangeHandler(() => {\n setForkNumber(prev => prev + 1)\n })\n }, [])\n\n // Record transcripts locally, for debugging and conversation recovery\n useLogMessages(messages, messageLogName, forkNumber)\n\n // Log startup time\n useLogStartupTime()\n\n // Initial load\n useEffect(() => {\n onInit()\n // TODO: fix this\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const normalizedMessages = useMemo(\n () => normalizeMessages(messages).filter(isNotEmptyMessage),\n [messages],\n )\n\n const unresolvedToolUseIDs = useMemo(\n () => getUnresolvedToolUseIDs(normalizedMessages),\n [normalizedMessages],\n )\n\n const inProgressToolUseIDs = useMemo(\n () => getInProgressToolUseIDs(normalizedMessages),\n [normalizedMessages],\n )\n\n const erroredToolUseIDs = useMemo(\n () =>\n new Set(\n getErroredToolUseMessages(normalizedMessages).map(\n _ => (_.message.content[0]! as ToolUseBlockParam).id,\n ),\n ),\n [normalizedMessages],\n )\n\n const messagesJSX = useMemo(() => {\n return [\n {\n type: 'static',\n jsx: (\n <Box flexDirection=\"column\" key={`logo${forkNumber}`}>\n <Logo\n mcpClients={mcpClients}\n isDefaultModel={isDefaultModel}\n updateBannerVersion={updateAvailableVersion}\n updateBannerCommands={updateCommands}\n />\n <ProjectOnboarding workspaceDir={getOriginalCwd()} />\n </Box>\n ),\n },\n ...reorderMessages(normalizedMessages).map(_ => {\n const toolUseID = getToolUseID(_)\n const message =\n _.type === 'progress' ? (\n _.content.message.content[0]?.type === 'text' &&\n // TaskTool interrupts use Progress messages without extra \u23BF \n // since <Message /> component already adds the margin\n _.content.message.content[0].text === INTERRUPT_MESSAGE ? (\n <Message\n message={_.content}\n messages={_.normalizedMessages}\n addMargin={false}\n tools={_.tools}\n verbose={verbose ?? false}\n debug={debug}\n erroredToolUseIDs={new Set()}\n inProgressToolUseIDs={new Set()}\n unresolvedToolUseIDs={new Set()}\n shouldAnimate={false}\n shouldShowDot={false}\n />\n ) : (\n <MessageResponse children={\n <Message\n message={_.content}\n messages={_.normalizedMessages}\n addMargin={false}\n tools={_.tools}\n verbose={verbose ?? false}\n debug={debug}\n erroredToolUseIDs={new Set()}\n inProgressToolUseIDs={new Set()}\n unresolvedToolUseIDs={\n new Set([\n (_.content.message.content[0]! as ToolUseBlockParam).id,\n ])\n }\n shouldAnimate={false}\n shouldShowDot={false}\n />\n } />\n )\n ) : (\n <Message\n message={_}\n messages={normalizedMessages}\n addMargin={true}\n tools={tools}\n verbose={verbose}\n debug={debug}\n erroredToolUseIDs={erroredToolUseIDs}\n inProgressToolUseIDs={inProgressToolUseIDs}\n shouldAnimate={\n !toolJSX &&\n !toolUseConfirm &&\n !isMessageSelectorVisible &&\n (!toolUseID || inProgressToolUseIDs.has(toolUseID))\n }\n shouldShowDot={true}\n unresolvedToolUseIDs={unresolvedToolUseIDs}\n />\n )\n\n const type = shouldRenderStatically(\n _,\n normalizedMessages,\n unresolvedToolUseIDs,\n )\n ? 'static'\n : 'transient'\n\n if (debug) {\n return {\n type,\n jsx: (\n <Box\n borderStyle=\"single\"\n borderColor={type === 'static' ? 'green' : 'red'}\n key={_.uuid}\n width=\"100%\"\n >\n {message}\n </Box>\n ),\n }\n }\n\n return {\n type,\n jsx: (\n <Box key={_.uuid} width=\"100%\">\n {message}\n </Box>\n ),\n }\n }),\n ]\n }, [\n forkNumber,\n normalizedMessages,\n tools,\n verbose,\n debug,\n erroredToolUseIDs,\n inProgressToolUseIDs,\n toolJSX,\n toolUseConfirm,\n isMessageSelectorVisible,\n unresolvedToolUseIDs,\n mcpClients,\n isDefaultModel,\n ])\n\n // only show the dialog once not loading\n const showingCostDialog = !isLoading && showCostDialog\n\n return (\n <PermissionProvider \n isBypassPermissionsModeAvailable={!safeMode}\n children={\n <React.Fragment>\n {/* Update banner now renders inside Logo for stable placement */}\n <ModeIndicator />\n <React.Fragment key={`static-messages-${forkNumber}`}>\n <Static\n items={messagesJSX.filter(_ => _.type === 'static')}\n children={(item: any) => item.jsx}\n />\n </React.Fragment>\n {messagesJSX.filter(_ => _.type === 'transient').map(_ => _.jsx)}\n <Box\n borderColor=\"red\"\n borderStyle={debug ? 'single' : undefined}\n flexDirection=\"column\"\n width=\"100%\"\n >\n {!toolJSX && !toolUseConfirm && !binaryFeedbackContext && isLoading && (\n <Spinner />\n )}\n {toolJSX ? toolJSX.jsx : null}\n {!toolJSX && binaryFeedbackContext && !isMessageSelectorVisible && (\n <BinaryFeedback\n m1={binaryFeedbackContext.m1}\n m2={binaryFeedbackContext.m2}\n resolve={result => {\n binaryFeedbackContext.resolve(result)\n setTimeout(() => setBinaryFeedbackContext(null), 0)\n }}\n verbose={verbose}\n normalizedMessages={normalizedMessages}\n tools={tools}\n debug={debug}\n erroredToolUseIDs={erroredToolUseIDs}\n inProgressToolUseIDs={inProgressToolUseIDs}\n unresolvedToolUseIDs={unresolvedToolUseIDs}\n />\n )}\n {!toolJSX &&\n toolUseConfirm &&\n !isMessageSelectorVisible &&\n !binaryFeedbackContext && (\n <PermissionRequest\n toolUseConfirm={toolUseConfirm}\n onDone={() => setToolUseConfirm(null)}\n verbose={verbose}\n />\n )}\n {!toolJSX &&\n !toolUseConfirm &&\n !isMessageSelectorVisible &&\n !binaryFeedbackContext &&\n showingCostDialog && (\n <CostThresholdDialog\n onDone={() => {\n setShowCostDialog(false)\n setHaveShownCostDialog(true)\n const projectConfig = getGlobalConfig()\n saveGlobalConfig({\n ...projectConfig,\n hasAcknowledgedCostThreshold: true,\n })\n logEvent('tengu_cost_threshold_acknowledged', {})\n }}\n />\n )}\n\n {!toolUseConfirm &&\n !toolJSX?.shouldHidePromptInput &&\n shouldShowPromptInput &&\n !isMessageSelectorVisible &&\n !binaryFeedbackContext &&\n !showingCostDialog && (\n <>\n <PromptInput\n commands={commands}\n forkNumber={forkNumber}\n messageLogName={messageLogName}\n tools={tools}\n isDisabled={apiKeyStatus === 'invalid'}\n isLoading={isLoading}\n onQuery={onQuery}\n debug={debug}\n verbose={verbose}\n messages={messages}\n setToolJSX={setToolJSX}\n onAutoUpdaterResult={setAutoUpdaterResult}\n autoUpdaterResult={autoUpdaterResult}\n input={inputValue}\n onInputChange={setInputValue}\n mode={inputMode}\n onModeChange={setInputMode}\n submitCount={submitCount}\n onSubmitCountChange={setSubmitCount}\n setIsLoading={setIsLoading}\n setAbortController={setAbortController}\n onShowMessageSelector={() =>\n setIsMessageSelectorVisible(prev => !prev)\n }\n setForkConvoWithMessagesOnTheNextRender={\n setForkConvoWithMessagesOnTheNextRender\n }\n readFileTimestamps={readFileTimestamps.current}\n abortController={abortController}\n onModelChange={() => setForkNumber(prev => prev + 1)}\n />\n </>\n )}\n </Box>\n {isMessageSelectorVisible && (\n <MessageSelector\n erroredToolUseIDs={erroredToolUseIDs}\n unresolvedToolUseIDs={unresolvedToolUseIDs}\n messages={normalizeMessagesForAPI(messages)}\n onSelect={async message => {\n setIsMessageSelectorVisible(false)\n\n // If the user selected the current prompt, do nothing\n if (!messages.includes(message)) {\n return\n }\n\n // Cancel tool use calls/requests\n onCancel()\n\n // Hack: make sure the \"Interrupted by user\" message is\n // rendered in response to the cancellation. Otherwise,\n // the screen will be cleared but there will remain a\n // vestigial \"Interrupted by user\" message at the top.\n setImmediate(async () => {\n // Clear messages, and re-render\n await clearTerminal()\n setMessages([])\n setForkConvoWithMessagesOnTheNextRender(\n messages.slice(0, messages.indexOf(message)),\n )\n\n // Populate/reset the prompt input\n if (typeof message.message.content === 'string') {\n setInputValue(message.message.content)\n }\n })\n }}\n onEscape={() => setIsMessageSelectorVisible(false)}\n tools={tools}\n />\n )}\n {/** Fix occasional rendering artifact */}\n <Newline />\n </React.Fragment>\n }\n />\n )\n}\n\nfunction shouldRenderStatically(\n message: NormalizedMessage,\n messages: NormalizedMessage[],\n unresolvedToolUseIDs: Set<string>,\n): boolean {\n switch (message.type) {\n case 'user':\n case 'assistant': {\n const toolUseID = getToolUseID(message)\n if (!toolUseID) {\n return true\n }\n if (unresolvedToolUseIDs.has(toolUseID)) {\n return false\n }\n\n const correspondingProgressMessage = messages.find(\n _ => _.type === 'progress' && _.toolUseID === toolUseID,\n ) as ProgressMessage | null\n if (!correspondingProgressMessage) {\n return true\n }\n\n return !intersects(\n unresolvedToolUseIDs,\n correspondingProgressMessage.siblingToolUseIDs,\n )\n }\n case 'progress':\n return !intersects(unresolvedToolUseIDs, message.siblingToolUseIDs)\n }\n}\n\nfunction intersects<A>(a: Set<A>, b: Set<A>): boolean {\n return a.size > 0 && b.size > 0 && [...a].some(_ => b.has(_))\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["model"]
|
|
7
7
|
}
|
package/dist/services/openai.js
CHANGED
|
@@ -3,18 +3,22 @@ import { ProxyAgent, fetch } from "undici";
|
|
|
3
3
|
import { setSessionState, getSessionState } from "../utils/sessionState.js";
|
|
4
4
|
import { logEvent } from "../services/statsig.js";
|
|
5
5
|
import { debug as debugLogger, getCurrentRequest, logAPIError } from "../utils/debugLogger.js";
|
|
6
|
+
const RETRY_CONFIG = {
|
|
7
|
+
BASE_DELAY_MS: 1e3,
|
|
8
|
+
MAX_DELAY_MS: 32e3,
|
|
9
|
+
MAX_SERVER_DELAY_MS: 6e4,
|
|
10
|
+
JITTER_FACTOR: 0.1
|
|
11
|
+
};
|
|
6
12
|
function getRetryDelay(attempt, retryAfter) {
|
|
7
13
|
if (retryAfter) {
|
|
8
14
|
const retryAfterMs = parseInt(retryAfter) * 1e3;
|
|
9
15
|
if (!isNaN(retryAfterMs) && retryAfterMs > 0) {
|
|
10
|
-
return Math.min(retryAfterMs,
|
|
16
|
+
return Math.min(retryAfterMs, RETRY_CONFIG.MAX_SERVER_DELAY_MS);
|
|
11
17
|
}
|
|
12
18
|
}
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
const jitter = Math.random() * 0.1 * delay;
|
|
17
|
-
return Math.min(delay + jitter, maxDelay);
|
|
19
|
+
const delay = RETRY_CONFIG.BASE_DELAY_MS * Math.pow(2, attempt - 1);
|
|
20
|
+
const jitter = Math.random() * RETRY_CONFIG.JITTER_FACTOR * delay;
|
|
21
|
+
return Math.min(delay + jitter, RETRY_CONFIG.MAX_DELAY_MS);
|
|
18
22
|
}
|
|
19
23
|
function abortableDelay(delayMs, signal) {
|
|
20
24
|
return new Promise((resolve, reject) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/services/openai.ts"],
|
|
4
|
-
"sourcesContent": ["import { OpenAI } from 'openai'\nimport { getGlobalConfig, GlobalConfig } from '../utils/config'\nimport { ProxyAgent, fetch, Response } from 'undici'\nimport { setSessionState, getSessionState } from '../utils/sessionState'\nimport { logEvent } from '../services/statsig'\nimport { debug as debugLogger, getCurrentRequest, logAPIError } from '../utils/debugLogger'\n\n// Helper function to calculate retry delay with exponential backoff\nfunction getRetryDelay(attempt: number, retryAfter?: string | null): number {\n // If server suggests a retry-after time, use it\n if (retryAfter) {\n const retryAfterMs = parseInt(retryAfter) * 1000\n if (!isNaN(retryAfterMs) && retryAfterMs > 0) {\n return Math.min(retryAfterMs, 60000) // Cap at 60 seconds\n }\n }\n\n // Exponential backoff: base delay of 1 second, doubling each attempt\n const baseDelay = 1000\n const maxDelay = 32000 // Cap at 32 seconds\n const delay = baseDelay * Math.pow(2, attempt - 1)\n\n // Add some jitter to avoid thundering herd\n const jitter = Math.random() * 0.1 * delay\n\n return Math.min(delay + jitter, maxDelay)\n}\n\n// Helper function to create an abortable delay\nfunction abortableDelay(delayMs: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n // Check if already aborted\n if (signal?.aborted) {\n reject(new Error('Request was aborted'))\n return\n }\n\n const timeoutId = setTimeout(() => {\n resolve()\n }, delayMs)\n\n // If signal is provided, listen for abort event\n if (signal) {\n const abortHandler = () => {\n clearTimeout(timeoutId)\n reject(new Error('Request was aborted'))\n }\n signal.addEventListener('abort', abortHandler, { once: true })\n }\n })\n}\n\nenum ModelErrorType {\n MaxLength = '1024',\n MaxCompletionTokens = 'max_completion_tokens',\n TemperatureRestriction = 'temperature_restriction',\n StreamOptions = 'stream_options',\n Citations = 'citations',\n RateLimit = 'rate_limit',\n}\n\nfunction getModelErrorKey(\n baseURL: string,\n model: string,\n type: ModelErrorType,\n): string {\n return `${baseURL}:${model}:${type}`\n}\n\nfunction hasModelError(\n baseURL: string,\n model: string,\n type: ModelErrorType,\n): boolean {\n return !!getSessionState('modelErrors')[\n getModelErrorKey(baseURL, model, type)\n ]\n}\n\nfunction setModelError(\n baseURL: string,\n model: string,\n type: ModelErrorType,\n error: string,\n) {\n setSessionState('modelErrors', {\n [getModelErrorKey(baseURL, model, type)]: error,\n })\n}\n\n// More flexible error detection system\ntype ErrorDetector = (errMsg: string) => boolean\ntype ErrorFixer = (\n opts: OpenAI.ChatCompletionCreateParams,\n) => Promise<void> | void\ninterface ErrorHandler {\n type: ModelErrorType\n detect: ErrorDetector\n fix: ErrorFixer\n}\n\n// GPT-5 specific error handlers with enhanced detection patterns\nconst GPT5_ERROR_HANDLERS: ErrorHandler[] = [\n {\n type: ModelErrorType.MaxCompletionTokens,\n detect: errMsg => {\n const lowerMsg = errMsg.toLowerCase()\n return (\n // Exact OpenAI GPT-5 error message\n (lowerMsg.includes(\"unsupported parameter: 'max_tokens'\") && lowerMsg.includes(\"'max_completion_tokens'\")) ||\n // Generic max_tokens error patterns\n (lowerMsg.includes(\"max_tokens\") && lowerMsg.includes(\"max_completion_tokens\")) ||\n (lowerMsg.includes(\"max_tokens\") && lowerMsg.includes(\"not supported\")) ||\n (lowerMsg.includes(\"max_tokens\") && lowerMsg.includes(\"use max_completion_tokens\")) ||\n // Additional patterns for various providers\n (lowerMsg.includes(\"invalid parameter\") && lowerMsg.includes(\"max_tokens\")) ||\n (lowerMsg.includes(\"parameter error\") && lowerMsg.includes(\"max_tokens\"))\n )\n },\n fix: async opts => {\n console.log(`\uD83D\uDD27 GPT-5 Fix: Converting max_tokens (${opts.max_tokens}) to max_completion_tokens`)\n if ('max_tokens' in opts) {\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n }\n },\n },\n {\n type: ModelErrorType.TemperatureRestriction,\n detect: errMsg => {\n const lowerMsg = errMsg.toLowerCase()\n return (\n lowerMsg.includes(\"temperature\") && \n (lowerMsg.includes(\"only supports\") || lowerMsg.includes(\"must be 1\") || lowerMsg.includes(\"invalid temperature\"))\n )\n },\n fix: async opts => {\n console.log(`\uD83D\uDD27 GPT-5 Fix: Adjusting temperature from ${opts.temperature} to 1`)\n opts.temperature = 1\n },\n },\n // Add more GPT-5 specific handlers as needed\n]\n\n// Standard error handlers\nconst ERROR_HANDLERS: ErrorHandler[] = [\n {\n type: ModelErrorType.MaxLength,\n detect: errMsg =>\n errMsg.includes('Expected a string with maximum length 1024'),\n fix: async opts => {\n const toolDescriptions = {}\n for (const tool of opts.tools || []) {\n if (tool.function.description.length <= 1024) continue\n let str = ''\n let remainder = ''\n for (let line of tool.function.description.split('\\n')) {\n if (str.length + line.length < 1024) {\n str += line + '\\n'\n } else {\n remainder += line + '\\n'\n }\n }\n logEvent('truncated_tool_description', {\n name: tool.function.name,\n original_length: String(tool.function.description.length),\n truncated_length: String(str.length),\n remainder_length: String(remainder.length),\n })\n tool.function.description = str\n toolDescriptions[tool.function.name] = remainder\n }\n if (Object.keys(toolDescriptions).length > 0) {\n let content = '<additional-tool-usage-instructions>\\n\\n'\n for (const [name, description] of Object.entries(toolDescriptions)) {\n content += `<${name}>\\n${description}\\n</${name}>\\n\\n`\n }\n content += '</additional-tool-usage-instructions>'\n\n for (let i = opts.messages.length - 1; i >= 0; i--) {\n if (opts.messages[i].role === 'system') {\n opts.messages.splice(i + 1, 0, {\n role: 'system',\n content,\n })\n break\n }\n }\n }\n },\n },\n {\n type: ModelErrorType.MaxCompletionTokens,\n detect: errMsg => errMsg.includes(\"Use 'max_completion_tokens'\"),\n fix: async opts => {\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n },\n },\n {\n type: ModelErrorType.StreamOptions,\n detect: errMsg => errMsg.includes('stream_options'),\n fix: async opts => {\n delete opts.stream_options\n },\n },\n {\n type: ModelErrorType.Citations,\n detect: errMsg =>\n errMsg.includes('Extra inputs are not permitted') &&\n errMsg.includes('citations'),\n fix: async opts => {\n if (!opts.messages) return\n\n for (const message of opts.messages) {\n if (!message) continue\n\n if (Array.isArray(message.content)) {\n for (const item of message.content) {\n // Convert to unknown first to safely access properties\n if (item && typeof item === 'object') {\n const itemObj = item as unknown as Record<string, unknown>\n if ('citations' in itemObj) {\n delete itemObj.citations\n }\n }\n }\n } else if (message.content && typeof message.content === 'object') {\n // Convert to unknown first to safely access properties\n const contentObj = message.content as unknown as Record<\n string,\n unknown\n >\n if ('citations' in contentObj) {\n delete contentObj.citations\n }\n }\n }\n },\n },\n]\n\n// Rate limit specific detection\nfunction isRateLimitError(errMsg: string): boolean {\n if (!errMsg) return false\n const lowerMsg = errMsg.toLowerCase()\n return (\n lowerMsg.includes('rate limit') ||\n lowerMsg.includes('too many requests') ||\n lowerMsg.includes('429')\n )\n}\n\n// Model-specific feature flags - can be extended with more properties as needed\ninterface ModelFeatures {\n usesMaxCompletionTokens: boolean\n supportsResponsesAPI?: boolean\n requiresTemperatureOne?: boolean\n supportsVerbosityControl?: boolean\n supportsCustomTools?: boolean\n supportsAllowedTools?: boolean\n}\n\n// Map of model identifiers to their specific features\nconst MODEL_FEATURES: Record<string, ModelFeatures> = {\n // OpenAI thinking models\n o1: { usesMaxCompletionTokens: true },\n 'o1-preview': { usesMaxCompletionTokens: true },\n 'o1-mini': { usesMaxCompletionTokens: true },\n 'o1-pro': { usesMaxCompletionTokens: true },\n 'o3-mini': { usesMaxCompletionTokens: true },\n // GPT-5 models\n 'gpt-5': { \n usesMaxCompletionTokens: true, \n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n },\n 'gpt-5-mini': { \n usesMaxCompletionTokens: true, \n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n },\n 'gpt-5-nano': { \n usesMaxCompletionTokens: true, \n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n },\n 'gpt-5-chat-latest': { \n usesMaxCompletionTokens: true, \n supportsResponsesAPI: false, // Uses Chat Completions only\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n },\n}\n\n// Helper to get model features based on model ID/name\nfunction getModelFeatures(modelName: string): ModelFeatures {\n if (!modelName || typeof modelName !== 'string') {\n return { usesMaxCompletionTokens: false }\n }\n\n // Check for exact matches first (highest priority)\n if (MODEL_FEATURES[modelName]) {\n return MODEL_FEATURES[modelName]\n }\n\n // Simple GPT-5 detection: any model name containing 'gpt-5'\n if (modelName.toLowerCase().includes('gpt-5')) {\n return {\n usesMaxCompletionTokens: true,\n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n }\n }\n\n // Check for partial matches (e.g., other reasoning models)\n for (const [key, features] of Object.entries(MODEL_FEATURES)) {\n if (modelName.includes(key)) {\n return features\n }\n }\n\n // Default features for unknown models\n return { usesMaxCompletionTokens: false }\n}\n\n// Apply model-specific parameter transformations based on model features\nfunction applyModelSpecificTransformations(\n opts: OpenAI.ChatCompletionCreateParams,\n): void {\n if (!opts.model || typeof opts.model !== 'string') {\n return\n }\n\n const features = getModelFeatures(opts.model)\n const isGPT5 = opts.model.toLowerCase().includes('gpt-5')\n\n // \uD83D\uDD25 Enhanced GPT-5 Detection and Transformation\n if (isGPT5 || features.usesMaxCompletionTokens) {\n // Force max_completion_tokens for all GPT-5 models\n if ('max_tokens' in opts && !('max_completion_tokens' in opts)) {\n console.log(`\uD83D\uDD27 Transforming max_tokens (${opts.max_tokens}) to max_completion_tokens for ${opts.model}`)\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n }\n \n // Force temperature = 1 for GPT-5 models\n if (features.requiresTemperatureOne && 'temperature' in opts) {\n if (opts.temperature !== 1 && opts.temperature !== undefined) {\n console.log(\n `\uD83D\uDD27 GPT-5 temperature constraint: Adjusting temperature from ${opts.temperature} to 1 for ${opts.model}`\n )\n opts.temperature = 1\n }\n }\n \n // Remove unsupported parameters for GPT-5\n if (isGPT5) {\n // Remove parameters that may not be supported by GPT-5\n delete opts.frequency_penalty\n delete opts.presence_penalty\n delete opts.logit_bias\n delete opts.user\n \n // Add reasoning_effort if not present and model supports it\n if (!opts.reasoning_effort && features.supportsVerbosityControl) {\n opts.reasoning_effort = 'medium' // Default reasoning effort for coding tasks\n }\n }\n }\n\n // Apply transformations for non-GPT-5 models\n else {\n // Standard max_tokens to max_completion_tokens conversion for other reasoning models\n if (\n features.usesMaxCompletionTokens &&\n 'max_tokens' in opts &&\n !('max_completion_tokens' in opts)\n ) {\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n }\n }\n\n // Add more transformations here as needed\n}\n\nasync function applyModelErrorFixes(\n opts: OpenAI.ChatCompletionCreateParams,\n baseURL: string,\n) {\n const isGPT5 = opts.model.startsWith('gpt-5')\n const handlers = isGPT5 ? [...GPT5_ERROR_HANDLERS, ...ERROR_HANDLERS] : ERROR_HANDLERS\n \n for (const handler of handlers) {\n if (hasModelError(baseURL, opts.model, handler.type)) {\n await handler.fix(opts)\n return\n }\n }\n}\n\n// Helper function to try different endpoints for OpenAI-compatible providers\nasync function tryWithEndpointFallback(\n baseURL: string,\n opts: OpenAI.ChatCompletionCreateParams,\n headers: Record<string, string>,\n provider: string,\n proxy: any,\n signal?: AbortSignal, // \uD83D\uDD27 Add AbortSignal support\n): Promise<{ response: Response; endpoint: string }> {\n const endpointsToTry = []\n\n if (provider === 'minimax') {\n endpointsToTry.push('/text/chatcompletion_v2', '/chat/completions')\n } else {\n endpointsToTry.push('/chat/completions')\n }\n\n let lastError = null\n\n for (const endpoint of endpointsToTry) {\n try {\n const response = await fetch(`${baseURL}${endpoint}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(opts.stream ? { ...opts, stream: true } : opts),\n dispatcher: proxy,\n signal: signal, // \uD83D\uDD27 Connect AbortSignal to fetch call\n })\n\n // If successful, return immediately\n if (response.ok) {\n return { response, endpoint }\n }\n\n // If it's a 404, try the next endpoint\n if (response.status === 404 && endpointsToTry.length > 1) {\n console.log(\n `Endpoint ${endpoint} returned 404, trying next endpoint...`,\n )\n continue\n }\n\n // For other error codes, return this response (don't try fallback)\n return { response, endpoint }\n } catch (error) {\n lastError = error\n // Network errors might be temporary, try next endpoint\n if (endpointsToTry.indexOf(endpoint) < endpointsToTry.length - 1) {\n console.log(`Network error on ${endpoint}, trying next endpoint...`)\n continue\n }\n }\n }\n\n // If we get here, all endpoints failed\n throw lastError || new Error('All endpoints failed')\n}\n\n// Export shared utilities for GPT-5 compatibility\nexport { getGPT5CompletionWithProfile, getModelFeatures, applyModelSpecificTransformations }\n\nexport async function getCompletionWithProfile(\n modelProfile: any,\n opts: OpenAI.ChatCompletionCreateParams,\n attempt: number = 0,\n maxAttempts: number = 10,\n signal?: AbortSignal, // \uD83D\uDD27 CRITICAL FIX: Add AbortSignal support\n): Promise<OpenAI.ChatCompletion | AsyncIterable<OpenAI.ChatCompletionChunk>> {\n if (attempt >= maxAttempts) {\n throw new Error('Max attempts reached')\n }\n\n const provider = modelProfile?.provider || 'anthropic'\n const baseURL = modelProfile?.baseURL\n const apiKey = modelProfile?.apiKey\n const proxy = getGlobalConfig().proxy\n ? new ProxyAgent(getGlobalConfig().proxy)\n : undefined\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n\n if (apiKey) {\n if (provider === 'azure') {\n headers['api-key'] = apiKey\n } else {\n headers['Authorization'] = `Bearer ${apiKey}`\n }\n }\n\n applyModelSpecificTransformations(opts)\n await applyModelErrorFixes(opts, baseURL || '')\n\n // \uD83D\uDD25 REAL-TIME API CALL DEBUG - \u4F7F\u7528\u5168\u5C40\u65E5\u5FD7\u7CFB\u7EDF\n debugLogger.api('OPENAI_API_CALL_START', {\n endpoint: baseURL || 'DEFAULT_OPENAI',\n model: opts.model,\n provider,\n apiKeyConfigured: !!apiKey,\n apiKeyPrefix: apiKey ? apiKey.substring(0, 8) : null,\n maxTokens: opts.max_tokens,\n temperature: opts.temperature,\n messageCount: opts.messages?.length || 0,\n streamMode: opts.stream,\n timestamp: new Date().toISOString(),\n modelProfileModelName: modelProfile?.modelName,\n modelProfileName: modelProfile?.name,\n })\n\n // Make sure all tool messages have string content\n opts.messages = opts.messages.map(msg => {\n if (msg.role === 'tool') {\n if (Array.isArray(msg.content)) {\n return {\n ...msg,\n content:\n msg.content\n .map(c => c.text || '')\n .filter(Boolean)\n .join('\\n\\n') || '(empty content)',\n }\n } else if (typeof msg.content !== 'string') {\n return {\n ...msg,\n content:\n typeof msg.content === 'undefined'\n ? '(empty content)'\n : JSON.stringify(msg.content),\n }\n }\n }\n return msg\n })\n\n // Define Azure-specific API endpoint with version\n const azureApiVersion = '2024-06-01'\n let endpoint = '/chat/completions'\n\n if (provider === 'azure') {\n endpoint = `/chat/completions?api-version=${azureApiVersion}`\n } else if (provider === 'minimax') {\n endpoint = '/text/chatcompletion_v2'\n }\n\n try {\n if (opts.stream) {\n const isOpenAICompatible = [\n 'minimax',\n 'kimi',\n 'deepseek',\n 'siliconflow',\n 'qwen',\n 'glm',\n 'baidu-qianfan',\n 'openai',\n 'mistral',\n 'xai',\n 'groq',\n 'custom-openai',\n ].includes(provider)\n\n let response: Response\n let usedEndpoint: string\n\n if (isOpenAICompatible && provider !== 'azure') {\n const result = await tryWithEndpointFallback(\n baseURL,\n opts,\n headers,\n provider,\n proxy,\n signal, // \uD83D\uDD27 Pass AbortSignal to endpoint fallback\n )\n response = result.response\n usedEndpoint = result.endpoint\n } else {\n response = await fetch(`${baseURL}${endpoint}`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ ...opts, stream: true }),\n dispatcher: proxy,\n signal: signal, // \uD83D\uDD27 CRITICAL FIX: Connect AbortSignal to fetch call\n })\n usedEndpoint = endpoint\n }\n\n if (!response.ok) {\n // \uD83D\uDD27 CRITICAL FIX: Check abort signal BEFORE showing retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n \n // \uD83D\uDD25 NEW: Parse error message to detect and handle specific API errors\n try {\n const errorData = await response.json()\n // Type guard for error data structure\n const hasError = (data: unknown): data is { error?: { message?: string }; message?: string } => {\n return typeof data === 'object' && data !== null\n }\n const errorMessage = hasError(errorData) \n ? (errorData.error?.message || errorData.message || `HTTP ${response.status}`)\n : `HTTP ${response.status}`\n \n // Check if this is a parameter error that we can fix\n const isGPT5 = opts.model.startsWith('gpt-5')\n const handlers = isGPT5 ? [...GPT5_ERROR_HANDLERS, ...ERROR_HANDLERS] : ERROR_HANDLERS\n \n for (const handler of handlers) {\n if (handler.detect(errorMessage)) {\n console.log(`\uD83D\uDD27 Detected ${handler.type} error for ${opts.model}: ${errorMessage}`)\n \n // Store this error for future requests\n setModelError(baseURL || '', opts.model, handler.type, errorMessage)\n \n // Apply the fix and retry immediately\n await handler.fix(opts)\n console.log(`\uD83D\uDD27 Applied fix for ${handler.type}, retrying...`)\n \n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal,\n )\n }\n }\n \n // If no specific handler found, log the error for debugging\n console.log(`\u26A0\uFE0F Unhandled API error (${response.status}): ${errorMessage}`)\n \n // Log API error using unified logger\n logAPIError({\n model: opts.model,\n endpoint: `${baseURL}${endpoint}`,\n status: response.status,\n error: errorMessage,\n request: opts,\n response: errorData,\n provider: provider\n })\n } catch (parseError) {\n // If we can't parse the error, fall back to generic retry\n console.log(`\u26A0\uFE0F Could not parse error response (${response.status})`)\n \n // Log parse error\n logAPIError({\n model: opts.model,\n endpoint: `${baseURL}${endpoint}`,\n status: response.status,\n error: `Could not parse error response: ${parseError.message}`,\n request: opts,\n response: { parseError: parseError.message },\n provider: provider\n })\n }\n \n const delayMs = getRetryDelay(attempt)\n console.log(\n ` \u23BF API error (${response.status}), retrying in ${Math.round(delayMs / 1000)}s... (attempt ${attempt + 1}/${maxAttempts})`,\n )\n try {\n await abortableDelay(delayMs, signal)\n } catch (error) {\n // If aborted during delay, throw the error to stop retrying\n if (error.message === 'Request was aborted') {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal, // \uD83D\uDD27 Pass AbortSignal to recursive call\n )\n }\n\n const stream = createStreamProcessor(response.body as any, signal)\n return stream\n }\n\n // Non-streaming request\n const isOpenAICompatible = [\n 'minimax',\n 'kimi',\n 'deepseek',\n 'siliconflow',\n 'qwen',\n 'glm',\n 'baidu-qianfan',\n 'openai',\n 'mistral',\n 'xai',\n 'groq',\n 'custom-openai',\n ].includes(provider)\n\n let response: Response\n let usedEndpoint: string\n\n if (isOpenAICompatible && provider !== 'azure') {\n const result = await tryWithEndpointFallback(\n baseURL,\n opts,\n headers,\n provider,\n proxy,\n signal, // \uD83D\uDD27 Pass AbortSignal to endpoint fallback\n )\n response = result.response\n usedEndpoint = result.endpoint\n } else {\n response = await fetch(`${baseURL}${endpoint}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(opts),\n dispatcher: proxy,\n signal: signal, // \uD83D\uDD27 CRITICAL FIX: Connect AbortSignal to non-streaming fetch call\n })\n usedEndpoint = endpoint\n }\n\n if (!response.ok) {\n // \uD83D\uDD27 CRITICAL FIX: Check abort signal BEFORE showing retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n \n // \uD83D\uDD25 NEW: Parse error message to detect and handle specific API errors\n try {\n const errorData = await response.json()\n // Type guard for error data structure\n const hasError = (data: unknown): data is { error?: { message?: string }; message?: string } => {\n return typeof data === 'object' && data !== null\n }\n const errorMessage = hasError(errorData) \n ? (errorData.error?.message || errorData.message || `HTTP ${response.status}`)\n : `HTTP ${response.status}`\n \n // Check if this is a parameter error that we can fix\n const isGPT5 = opts.model.startsWith('gpt-5')\n const handlers = isGPT5 ? [...GPT5_ERROR_HANDLERS, ...ERROR_HANDLERS] : ERROR_HANDLERS\n \n for (const handler of handlers) {\n if (handler.detect(errorMessage)) {\n console.log(`\uD83D\uDD27 Detected ${handler.type} error for ${opts.model}: ${errorMessage}`)\n \n // Store this error for future requests\n setModelError(baseURL || '', opts.model, handler.type, errorMessage)\n \n // Apply the fix and retry immediately\n await handler.fix(opts)\n console.log(`\uD83D\uDD27 Applied fix for ${handler.type}, retrying...`)\n \n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal,\n )\n }\n }\n \n // If no specific handler found, log the error for debugging\n console.log(`\u26A0\uFE0F Unhandled API error (${response.status}): ${errorMessage}`)\n } catch (parseError) {\n // If we can't parse the error, fall back to generic retry\n console.log(`\u26A0\uFE0F Could not parse error response (${response.status})`)\n }\n \n const delayMs = getRetryDelay(attempt)\n console.log(\n ` \u23BF API error (${response.status}), retrying in ${Math.round(delayMs / 1000)}s... (attempt ${attempt + 1}/${maxAttempts})`,\n )\n try {\n await abortableDelay(delayMs, signal)\n } catch (error) {\n // If aborted during delay, throw the error to stop retrying\n if (error.message === 'Request was aborted') {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal, // \uD83D\uDD27 Pass AbortSignal to recursive call\n )\n }\n\n const responseData = (await response.json()) as OpenAI.ChatCompletion\n return responseData\n } catch (error) {\n // \uD83D\uDD27 CRITICAL FIX: Check abort signal BEFORE showing retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n \n if (attempt < maxAttempts) {\n // \uD83D\uDD27 Double-check abort status to avoid showing misleading retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n \n const delayMs = getRetryDelay(attempt)\n console.log(\n ` \u23BF Network error, retrying in ${Math.round(delayMs / 1000)}s... (attempt ${attempt + 1}/${maxAttempts})`,\n )\n try {\n await abortableDelay(delayMs, signal)\n } catch (error) {\n // If aborted during delay, throw the error to stop retrying\n if (error.message === 'Request was aborted') {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal, // \uD83D\uDD27 Pass AbortSignal to recursive call\n )\n }\n throw error\n }\n}\n\nexport function createStreamProcessor(\n stream: any,\n signal?: AbortSignal,\n): AsyncGenerator<OpenAI.ChatCompletionChunk, void, unknown> {\n if (!stream) {\n throw new Error('Stream is null or undefined')\n }\n\n return (async function* () {\n const reader = stream.getReader()\n const decoder = new TextDecoder('utf-8')\n let buffer = ''\n\n try {\n while (true) {\n // Check for cancellation before attempting to read\n if (signal?.aborted) {\n break\n }\n\n let readResult\n try {\n readResult = await reader.read()\n } catch (e) {\n // If signal is aborted, this is user cancellation - exit silently\n if (signal?.aborted) {\n break\n }\n console.error('Error reading from stream:', e)\n break\n }\n\n const { done, value } = readResult\n if (done) {\n break\n }\n\n const chunk = decoder.decode(value, { stream: true })\n buffer += chunk\n\n let lineEnd = buffer.indexOf('\\n')\n while (lineEnd !== -1) {\n const line = buffer.substring(0, lineEnd).trim()\n buffer = buffer.substring(lineEnd + 1)\n\n if (line === 'data: [DONE]') {\n continue\n }\n\n if (line.startsWith('data: ')) {\n const data = line.slice(6).trim()\n if (!data) continue\n\n try {\n const parsed = JSON.parse(data) as OpenAI.ChatCompletionChunk\n yield parsed\n } catch (e) {\n console.error('Error parsing JSON:', data, e)\n }\n }\n\n lineEnd = buffer.indexOf('\\n')\n }\n }\n\n // Process any remaining data in the buffer\n if (buffer.trim()) {\n const lines = buffer.trim().split('\\n')\n for (const line of lines) {\n if (line.startsWith('data: ') && line !== 'data: [DONE]') {\n const data = line.slice(6).trim()\n if (!data) continue\n\n try {\n const parsed = JSON.parse(data) as OpenAI.ChatCompletionChunk\n yield parsed\n } catch (e) {\n console.error('Error parsing final JSON:', data, e)\n }\n }\n }\n }\n } catch (e) {\n console.error('Unexpected error in stream processing:', e)\n } finally {\n try {\n reader.releaseLock()\n } catch (e) {\n console.error('Error releasing reader lock:', e)\n }\n }\n })()\n}\n\nexport function streamCompletion(\n stream: any,\n signal?: AbortSignal,\n): AsyncGenerator<OpenAI.ChatCompletionChunk, void, unknown> {\n return createStreamProcessor(stream, signal)\n}\n\n/**\n * Call GPT-5 Responses API with proper parameter handling\n */\nexport async function callGPT5ResponsesAPI(\n modelProfile: any,\n opts: any, // Using 'any' for Responses API params which differ from ChatCompletionCreateParams\n signal?: AbortSignal,\n): Promise<any> {\n const baseURL = modelProfile?.baseURL || 'https://api.openai.com/v1'\n const apiKey = modelProfile?.apiKey\n const proxy = getGlobalConfig().proxy\n ? new ProxyAgent(getGlobalConfig().proxy)\n : undefined\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n }\n\n // \uD83D\uDD25 Enhanced Responses API Parameter Mapping for GPT-5\n const responsesParams: any = {\n model: opts.model,\n input: opts.messages, // Responses API uses 'input' instead of 'messages'\n }\n\n // \uD83D\uDD27 GPT-5 Token Configuration\n if (opts.max_completion_tokens) {\n responsesParams.max_completion_tokens = opts.max_completion_tokens\n } else if (opts.max_tokens) {\n // Fallback conversion if max_tokens is still present\n responsesParams.max_completion_tokens = opts.max_tokens\n }\n\n // \uD83D\uDD27 GPT-5 Temperature Handling (only 1 or undefined)\n if (opts.temperature === 1) {\n responsesParams.temperature = 1\n }\n // Note: Do not pass temperature if it's not 1, GPT-5 will use default\n\n // \uD83D\uDD27 GPT-5 Reasoning Configuration\n const reasoningEffort = opts.reasoning_effort || 'medium'\n responsesParams.reasoning = {\n effort: reasoningEffort,\n // \uD83D\uDE80 Enable reasoning summaries for transparency in coding tasks\n generate_summary: true,\n }\n\n // \uD83D\uDD27 GPT-5 Tools Support\n if (opts.tools && opts.tools.length > 0) {\n responsesParams.tools = opts.tools\n \n // \uD83D\uDE80 GPT-5 Tool Choice Configuration\n if (opts.tool_choice) {\n responsesParams.tool_choice = opts.tool_choice\n }\n }\n\n // \uD83D\uDD27 GPT-5 System Instructions (separate from messages)\n const systemMessages = opts.messages.filter(msg => msg.role === 'system')\n const nonSystemMessages = opts.messages.filter(msg => msg.role !== 'system')\n \n if (systemMessages.length > 0) {\n responsesParams.instructions = systemMessages.map(msg => msg.content).join('\\n\\n')\n responsesParams.input = nonSystemMessages\n }\n\n // Handle verbosity (if supported) - optimized for coding tasks\n const features = getModelFeatures(opts.model)\n if (features.supportsVerbosityControl) {\n // High verbosity for coding tasks to get detailed explanations and structured code\n // Based on GPT-5 best practices for agent-like coding environments\n responsesParams.text = {\n verbosity: 'high',\n }\n }\n\n // Apply GPT-5 coding optimizations\n if (opts.model.startsWith('gpt-5')) {\n // Set reasoning effort based on task complexity\n if (!responsesParams.reasoning) {\n responsesParams.reasoning = {\n effort: 'medium', // Balanced for most coding tasks\n }\n }\n\n // Add instructions parameter for coding-specific guidance\n if (!responsesParams.instructions) {\n responsesParams.instructions = `You are an expert programmer working in a terminal-based coding environment. Follow these guidelines:\n- Provide clear, concise code solutions\n- Use proper error handling and validation\n- Follow coding best practices and patterns\n- Explain complex logic when necessary\n- Focus on maintainable, readable code`\n }\n }\n\n try {\n const response = await fetch(`${baseURL}/responses`, {\n method: 'POST',\n headers,\n body: JSON.stringify(responsesParams),\n dispatcher: proxy,\n signal: signal,\n })\n\n if (!response.ok) {\n throw new Error(`GPT-5 Responses API error: ${response.status} ${response.statusText}`)\n }\n\n const responseData = await response.json()\n \n // Convert Responses API response back to Chat Completion format for compatibility\n return convertResponsesAPIToChatCompletion(responseData)\n } catch (error) {\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n}\n\n/**\n * Convert Responses API response to Chat Completion format for compatibility\n * \uD83D\uDD25 Enhanced for GPT-5 with reasoning summary support\n */\nfunction convertResponsesAPIToChatCompletion(responsesData: any): any {\n // Extract content from Responses API format\n let outputText = responsesData.output_text || ''\n const usage = responsesData.usage || {}\n \n // \uD83D\uDE80 GPT-5 Reasoning Summary Integration\n // If reasoning summary is available, prepend it to the output for transparency\n if (responsesData.output && Array.isArray(responsesData.output)) {\n const reasoningItems = responsesData.output.filter(item => item.type === 'reasoning' && item.summary)\n const messageItems = responsesData.output.filter(item => item.type === 'message')\n \n if (reasoningItems.length > 0 && messageItems.length > 0) {\n const reasoningSummary = reasoningItems\n .map(item => item.summary?.map(s => s.text).join('\\n'))\n .filter(Boolean)\n .join('\\n\\n')\n \n const mainContent = messageItems\n .map(item => item.content?.map(c => c.text).join('\\n'))\n .filter(Boolean)\n .join('\\n\\n')\n \n if (reasoningSummary) {\n outputText = `**\uD83E\uDDE0 Reasoning Process:**\\n${reasoningSummary}\\n\\n**\uD83D\uDCDD Response:**\\n${mainContent}`\n } else {\n outputText = mainContent\n }\n }\n }\n\n return {\n id: responsesData.id || `chatcmpl-${Date.now()}`,\n object: 'chat.completion',\n created: Math.floor(Date.now() / 1000),\n model: responsesData.model || '',\n choices: [\n {\n index: 0,\n message: {\n role: 'assistant',\n content: outputText,\n // \uD83D\uDE80 Include reasoning metadata if available\n ...(responsesData.reasoning && {\n reasoning: {\n effort: responsesData.reasoning.effort,\n summary: responsesData.reasoning.summary,\n },\n }),\n },\n finish_reason: responsesData.status === 'completed' ? 'stop' : 'length',\n },\n ],\n usage: {\n prompt_tokens: usage.input_tokens || 0,\n completion_tokens: usage.output_tokens || 0,\n total_tokens: (usage.input_tokens || 0) + (usage.output_tokens || 0),\n // \uD83D\uDD27 GPT-5 Enhanced Usage Details\n prompt_tokens_details: {\n cached_tokens: usage.input_tokens_details?.cached_tokens || 0,\n },\n completion_tokens_details: {\n reasoning_tokens: usage.output_tokens_details?.reasoning_tokens || 0,\n },\n },\n }\n}\n\n/**\n * Enhanced getCompletionWithProfile that supports GPT-5 Responses API\n * \uD83D\uDD25 Optimized for both official OpenAI and third-party GPT-5 providers\n */\nasync function getGPT5CompletionWithProfile(\n modelProfile: any,\n opts: OpenAI.ChatCompletionCreateParams,\n attempt: number = 0,\n maxAttempts: number = 10,\n signal?: AbortSignal,\n): Promise<OpenAI.ChatCompletion | AsyncIterable<OpenAI.ChatCompletionChunk>> {\n const features = getModelFeatures(opts.model)\n const isOfficialOpenAI = !modelProfile.baseURL || \n modelProfile.baseURL.includes('api.openai.com')\n\n // \uD83D\uDE80 Try Responses API for official OpenAI non-streaming requests\n if (features.supportsResponsesAPI && !opts.stream && isOfficialOpenAI) {\n try {\n debugLogger.api('ATTEMPTING_GPT5_RESPONSES_API', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n provider: modelProfile.provider,\n stream: opts.stream,\n requestId: getCurrentRequest()?.id,\n })\n \n const result = await callGPT5ResponsesAPI(modelProfile, opts, signal)\n \n debugLogger.api('GPT5_RESPONSES_API_SUCCESS', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n requestId: getCurrentRequest()?.id,\n })\n \n return result\n } catch (error) {\n debugLogger.api('GPT5_RESPONSES_API_FALLBACK', {\n model: opts.model,\n error: error.message,\n baseURL: modelProfile.baseURL || 'official',\n requestId: getCurrentRequest()?.id,\n })\n \n console.warn(\n `\uD83D\uDD04 GPT-5 Responses API failed, falling back to Chat Completions: ${error.message}`\n )\n // Fall through to Chat Completions API\n }\n } \n \n // \uD83C\uDF10 Handle third-party GPT-5 providers with enhanced compatibility\n else if (!isOfficialOpenAI) {\n debugLogger.api('GPT5_THIRD_PARTY_PROVIDER', {\n model: opts.model,\n baseURL: modelProfile.baseURL,\n provider: modelProfile.provider,\n supportsResponsesAPI: features.supportsResponsesAPI,\n requestId: getCurrentRequest()?.id,\n })\n \n // \uD83D\uDD27 Apply enhanced parameter optimization for third-party providers\n console.log(`\uD83C\uDF10 Using GPT-5 via third-party provider: ${modelProfile.provider} (${modelProfile.baseURL})`)\n \n // Some third-party providers may need additional parameter adjustments\n if (modelProfile.provider === 'azure') {\n // Azure OpenAI specific adjustments\n delete opts.reasoning_effort // Azure may not support this yet\n } else if (modelProfile.provider === 'custom-openai') {\n // Generic OpenAI-compatible provider optimizations\n console.log(`\uD83D\uDD27 Applying OpenAI-compatible optimizations for custom provider`)\n }\n }\n \n // \uD83D\uDCE1 Handle streaming requests (Responses API doesn't support streaming yet)\n else if (opts.stream) {\n debugLogger.api('GPT5_STREAMING_MODE', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n reason: 'responses_api_no_streaming',\n requestId: getCurrentRequest()?.id,\n })\n \n console.log(`\uD83D\uDD04 Using Chat Completions for streaming (Responses API streaming not available)`)\n }\n\n // \uD83D\uDD27 Enhanced Chat Completions fallback with GPT-5 optimizations\n debugLogger.api('USING_CHAT_COMPLETIONS_FOR_GPT5', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n provider: modelProfile.provider,\n reason: isOfficialOpenAI ? 'streaming_or_fallback' : 'third_party_provider',\n requestId: getCurrentRequest()?.id,\n })\n\n return await getCompletionWithProfile(\n modelProfile,\n opts,\n attempt,\n maxAttempts,\n signal,\n )\n}\n\n/**\n * Fetch available models from custom OpenAI-compatible API\n */\nexport async function fetchCustomModels(\n baseURL: string,\n apiKey: string,\n): Promise<any[]> {\n try {\n // Check if baseURL already contains version number (e.g., v1, v2, etc.)\n const hasVersionNumber = /\\/v\\d+/.test(baseURL)\n const cleanBaseURL = baseURL.replace(/\\/+$/, '')\n const modelsURL = hasVersionNumber\n ? `${cleanBaseURL}/models`\n : `${cleanBaseURL}/v1/models`\n\n const response = await fetch(modelsURL, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n },\n })\n\n if (!response.ok) {\n // Provide user-friendly error messages based on status code\n if (response.status === 401) {\n throw new Error(\n 'Invalid API key. Please check your API key and try again.',\n )\n } else if (response.status === 403) {\n throw new Error(\n 'API key does not have permission to access models. Please check your API key permissions.',\n )\n } else if (response.status === 404) {\n throw new Error(\n 'API endpoint not found. Please check if the base URL is correct and supports the /models endpoint.',\n )\n } else if (response.status === 429) {\n throw new Error(\n 'Too many requests. Please wait a moment and try again.',\n )\n } else if (response.status >= 500) {\n throw new Error(\n 'API service is temporarily unavailable. Please try again later.',\n )\n } else {\n throw new Error(\n `Unable to connect to API (${response.status}). Please check your base URL, API key, and internet connection.`,\n )\n }\n }\n\n const data = await response.json()\n\n // Type guards for different API response formats\n const hasDataArray = (obj: unknown): obj is { data: unknown[] } => {\n return typeof obj === 'object' && obj !== null && 'data' in obj && Array.isArray((obj as any).data)\n }\n \n const hasModelsArray = (obj: unknown): obj is { models: unknown[] } => {\n return typeof obj === 'object' && obj !== null && 'models' in obj && Array.isArray((obj as any).models)\n }\n\n // Validate response format and extract models array\n let models = []\n\n if (hasDataArray(data)) {\n // Standard OpenAI format: { data: [...] }\n models = data.data\n } else if (Array.isArray(data)) {\n // Direct array format\n models = data\n } else if (hasModelsArray(data)) {\n // Alternative format: { models: [...] }\n models = data.models\n } else {\n throw new Error(\n 'API returned unexpected response format. Expected an array of models or an object with a \"data\" or \"models\" array.',\n )\n }\n\n // Ensure we have an array and validate it contains model objects\n if (!Array.isArray(models)) {\n throw new Error('API response format error: models data is not an array.')\n }\n\n return models\n } catch (error) {\n // If it's already our custom error, pass it through\n if (\n error instanceof Error &&\n (error.message.includes('API key') ||\n error.message.includes('API endpoint') ||\n error.message.includes('API service') ||\n error.message.includes('response format'))\n ) {\n throw error\n }\n\n // For network errors or other issues\n console.error('Failed to fetch custom API models:', error)\n\n // Check if it's a network error\n if (error instanceof Error && error.message.includes('fetch')) {\n throw new Error(\n 'Unable to connect to the API. Please check the base URL and your internet connection.',\n )\n }\n\n throw new Error(\n 'Failed to fetch models from custom API. Please check your configuration and try again.',\n )\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { OpenAI } from 'openai'\nimport { getGlobalConfig, GlobalConfig } from '../utils/config'\nimport { ProxyAgent, fetch, Response } from 'undici'\nimport { setSessionState, getSessionState } from '../utils/sessionState'\nimport { logEvent } from '../services/statsig'\nimport { debug as debugLogger, getCurrentRequest, logAPIError } from '../utils/debugLogger'\n\n/**\n * Retry configuration constants for API calls\n */\nconst RETRY_CONFIG = {\n BASE_DELAY_MS: 1000,\n MAX_DELAY_MS: 32000,\n MAX_SERVER_DELAY_MS: 60000,\n JITTER_FACTOR: 0.1,\n} as const\n\n/**\n * Calculate retry delay with exponential backoff and jitter\n */\nfunction getRetryDelay(attempt: number, retryAfter?: string | null): number {\n // If server suggests a retry-after time, use it\n if (retryAfter) {\n const retryAfterMs = parseInt(retryAfter) * 1000\n if (!isNaN(retryAfterMs) && retryAfterMs > 0) {\n return Math.min(retryAfterMs, RETRY_CONFIG.MAX_SERVER_DELAY_MS)\n }\n }\n\n // Exponential backoff with jitter\n const delay = RETRY_CONFIG.BASE_DELAY_MS * Math.pow(2, attempt - 1)\n const jitter = Math.random() * RETRY_CONFIG.JITTER_FACTOR * delay\n\n return Math.min(delay + jitter, RETRY_CONFIG.MAX_DELAY_MS)\n}\n\n// Helper function to create an abortable delay\nfunction abortableDelay(delayMs: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n // Check if already aborted\n if (signal?.aborted) {\n reject(new Error('Request was aborted'))\n return\n }\n\n const timeoutId = setTimeout(() => {\n resolve()\n }, delayMs)\n\n // If signal is provided, listen for abort event\n if (signal) {\n const abortHandler = () => {\n clearTimeout(timeoutId)\n reject(new Error('Request was aborted'))\n }\n signal.addEventListener('abort', abortHandler, { once: true })\n }\n })\n}\n\nenum ModelErrorType {\n MaxLength = '1024',\n MaxCompletionTokens = 'max_completion_tokens',\n TemperatureRestriction = 'temperature_restriction',\n StreamOptions = 'stream_options',\n Citations = 'citations',\n RateLimit = 'rate_limit',\n}\n\nfunction getModelErrorKey(\n baseURL: string,\n model: string,\n type: ModelErrorType,\n): string {\n return `${baseURL}:${model}:${type}`\n}\n\nfunction hasModelError(\n baseURL: string,\n model: string,\n type: ModelErrorType,\n): boolean {\n return !!getSessionState('modelErrors')[\n getModelErrorKey(baseURL, model, type)\n ]\n}\n\nfunction setModelError(\n baseURL: string,\n model: string,\n type: ModelErrorType,\n error: string,\n) {\n setSessionState('modelErrors', {\n [getModelErrorKey(baseURL, model, type)]: error,\n })\n}\n\n// More flexible error detection system\ntype ErrorDetector = (errMsg: string) => boolean\ntype ErrorFixer = (\n opts: OpenAI.ChatCompletionCreateParams,\n) => Promise<void> | void\ninterface ErrorHandler {\n type: ModelErrorType\n detect: ErrorDetector\n fix: ErrorFixer\n}\n\n// GPT-5 specific error handlers with enhanced detection patterns\nconst GPT5_ERROR_HANDLERS: ErrorHandler[] = [\n {\n type: ModelErrorType.MaxCompletionTokens,\n detect: errMsg => {\n const lowerMsg = errMsg.toLowerCase()\n return (\n // Exact OpenAI GPT-5 error message\n (lowerMsg.includes(\"unsupported parameter: 'max_tokens'\") && lowerMsg.includes(\"'max_completion_tokens'\")) ||\n // Generic max_tokens error patterns\n (lowerMsg.includes(\"max_tokens\") && lowerMsg.includes(\"max_completion_tokens\")) ||\n (lowerMsg.includes(\"max_tokens\") && lowerMsg.includes(\"not supported\")) ||\n (lowerMsg.includes(\"max_tokens\") && lowerMsg.includes(\"use max_completion_tokens\")) ||\n // Additional patterns for various providers\n (lowerMsg.includes(\"invalid parameter\") && lowerMsg.includes(\"max_tokens\")) ||\n (lowerMsg.includes(\"parameter error\") && lowerMsg.includes(\"max_tokens\"))\n )\n },\n fix: async opts => {\n console.log(`\uD83D\uDD27 GPT-5 Fix: Converting max_tokens (${opts.max_tokens}) to max_completion_tokens`)\n if ('max_tokens' in opts) {\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n }\n },\n },\n {\n type: ModelErrorType.TemperatureRestriction,\n detect: errMsg => {\n const lowerMsg = errMsg.toLowerCase()\n return (\n lowerMsg.includes(\"temperature\") && \n (lowerMsg.includes(\"only supports\") || lowerMsg.includes(\"must be 1\") || lowerMsg.includes(\"invalid temperature\"))\n )\n },\n fix: async opts => {\n console.log(`\uD83D\uDD27 GPT-5 Fix: Adjusting temperature from ${opts.temperature} to 1`)\n opts.temperature = 1\n },\n },\n // Add more GPT-5 specific handlers as needed\n]\n\n// Standard error handlers\nconst ERROR_HANDLERS: ErrorHandler[] = [\n {\n type: ModelErrorType.MaxLength,\n detect: errMsg =>\n errMsg.includes('Expected a string with maximum length 1024'),\n fix: async opts => {\n const toolDescriptions = {}\n for (const tool of opts.tools || []) {\n if (tool.function.description.length <= 1024) continue\n let str = ''\n let remainder = ''\n for (let line of tool.function.description.split('\\n')) {\n if (str.length + line.length < 1024) {\n str += line + '\\n'\n } else {\n remainder += line + '\\n'\n }\n }\n logEvent('truncated_tool_description', {\n name: tool.function.name,\n original_length: String(tool.function.description.length),\n truncated_length: String(str.length),\n remainder_length: String(remainder.length),\n })\n tool.function.description = str\n toolDescriptions[tool.function.name] = remainder\n }\n if (Object.keys(toolDescriptions).length > 0) {\n let content = '<additional-tool-usage-instructions>\\n\\n'\n for (const [name, description] of Object.entries(toolDescriptions)) {\n content += `<${name}>\\n${description}\\n</${name}>\\n\\n`\n }\n content += '</additional-tool-usage-instructions>'\n\n for (let i = opts.messages.length - 1; i >= 0; i--) {\n if (opts.messages[i].role === 'system') {\n opts.messages.splice(i + 1, 0, {\n role: 'system',\n content,\n })\n break\n }\n }\n }\n },\n },\n {\n type: ModelErrorType.MaxCompletionTokens,\n detect: errMsg => errMsg.includes(\"Use 'max_completion_tokens'\"),\n fix: async opts => {\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n },\n },\n {\n type: ModelErrorType.StreamOptions,\n detect: errMsg => errMsg.includes('stream_options'),\n fix: async opts => {\n delete opts.stream_options\n },\n },\n {\n type: ModelErrorType.Citations,\n detect: errMsg =>\n errMsg.includes('Extra inputs are not permitted') &&\n errMsg.includes('citations'),\n fix: async opts => {\n if (!opts.messages) return\n\n for (const message of opts.messages) {\n if (!message) continue\n\n if (Array.isArray(message.content)) {\n for (const item of message.content) {\n // Convert to unknown first to safely access properties\n if (item && typeof item === 'object') {\n const itemObj = item as unknown as Record<string, unknown>\n if ('citations' in itemObj) {\n delete itemObj.citations\n }\n }\n }\n } else if (message.content && typeof message.content === 'object') {\n // Convert to unknown first to safely access properties\n const contentObj = message.content as unknown as Record<\n string,\n unknown\n >\n if ('citations' in contentObj) {\n delete contentObj.citations\n }\n }\n }\n },\n },\n]\n\n// Rate limit specific detection\nfunction isRateLimitError(errMsg: string): boolean {\n if (!errMsg) return false\n const lowerMsg = errMsg.toLowerCase()\n return (\n lowerMsg.includes('rate limit') ||\n lowerMsg.includes('too many requests') ||\n lowerMsg.includes('429')\n )\n}\n\n// Model-specific feature flags - can be extended with more properties as needed\ninterface ModelFeatures {\n usesMaxCompletionTokens: boolean\n supportsResponsesAPI?: boolean\n requiresTemperatureOne?: boolean\n supportsVerbosityControl?: boolean\n supportsCustomTools?: boolean\n supportsAllowedTools?: boolean\n}\n\n// Map of model identifiers to their specific features\nconst MODEL_FEATURES: Record<string, ModelFeatures> = {\n // OpenAI thinking models\n o1: { usesMaxCompletionTokens: true },\n 'o1-preview': { usesMaxCompletionTokens: true },\n 'o1-mini': { usesMaxCompletionTokens: true },\n 'o1-pro': { usesMaxCompletionTokens: true },\n 'o3-mini': { usesMaxCompletionTokens: true },\n // GPT-5 models\n 'gpt-5': { \n usesMaxCompletionTokens: true, \n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n },\n 'gpt-5-mini': { \n usesMaxCompletionTokens: true, \n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n },\n 'gpt-5-nano': { \n usesMaxCompletionTokens: true, \n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n },\n 'gpt-5-chat-latest': { \n usesMaxCompletionTokens: true, \n supportsResponsesAPI: false, // Uses Chat Completions only\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n },\n}\n\n// Helper to get model features based on model ID/name\nfunction getModelFeatures(modelName: string): ModelFeatures {\n if (!modelName || typeof modelName !== 'string') {\n return { usesMaxCompletionTokens: false }\n }\n\n // Check for exact matches first (highest priority)\n if (MODEL_FEATURES[modelName]) {\n return MODEL_FEATURES[modelName]\n }\n\n // Simple GPT-5 detection: any model name containing 'gpt-5'\n if (modelName.toLowerCase().includes('gpt-5')) {\n return {\n usesMaxCompletionTokens: true,\n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n }\n }\n\n // Check for partial matches (e.g., other reasoning models)\n for (const [key, features] of Object.entries(MODEL_FEATURES)) {\n if (modelName.includes(key)) {\n return features\n }\n }\n\n // Default features for unknown models\n return { usesMaxCompletionTokens: false }\n}\n\n// Apply model-specific parameter transformations based on model features\nfunction applyModelSpecificTransformations(\n opts: OpenAI.ChatCompletionCreateParams,\n): void {\n if (!opts.model || typeof opts.model !== 'string') {\n return\n }\n\n const features = getModelFeatures(opts.model)\n const isGPT5 = opts.model.toLowerCase().includes('gpt-5')\n\n // \uD83D\uDD25 Enhanced GPT-5 Detection and Transformation\n if (isGPT5 || features.usesMaxCompletionTokens) {\n // Force max_completion_tokens for all GPT-5 models\n if ('max_tokens' in opts && !('max_completion_tokens' in opts)) {\n console.log(`\uD83D\uDD27 Transforming max_tokens (${opts.max_tokens}) to max_completion_tokens for ${opts.model}`)\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n }\n \n // Force temperature = 1 for GPT-5 models\n if (features.requiresTemperatureOne && 'temperature' in opts) {\n if (opts.temperature !== 1 && opts.temperature !== undefined) {\n console.log(\n `\uD83D\uDD27 GPT-5 temperature constraint: Adjusting temperature from ${opts.temperature} to 1 for ${opts.model}`\n )\n opts.temperature = 1\n }\n }\n \n // Remove unsupported parameters for GPT-5\n if (isGPT5) {\n // Remove parameters that may not be supported by GPT-5\n delete opts.frequency_penalty\n delete opts.presence_penalty\n delete opts.logit_bias\n delete opts.user\n \n // Add reasoning_effort if not present and model supports it\n if (!opts.reasoning_effort && features.supportsVerbosityControl) {\n opts.reasoning_effort = 'medium' // Default reasoning effort for coding tasks\n }\n }\n }\n\n // Apply transformations for non-GPT-5 models\n else {\n // Standard max_tokens to max_completion_tokens conversion for other reasoning models\n if (\n features.usesMaxCompletionTokens &&\n 'max_tokens' in opts &&\n !('max_completion_tokens' in opts)\n ) {\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n }\n }\n\n // Add more transformations here as needed\n}\n\nasync function applyModelErrorFixes(\n opts: OpenAI.ChatCompletionCreateParams,\n baseURL: string,\n) {\n const isGPT5 = opts.model.startsWith('gpt-5')\n const handlers = isGPT5 ? [...GPT5_ERROR_HANDLERS, ...ERROR_HANDLERS] : ERROR_HANDLERS\n \n for (const handler of handlers) {\n if (hasModelError(baseURL, opts.model, handler.type)) {\n await handler.fix(opts)\n return\n }\n }\n}\n\n// Helper function to try different endpoints for OpenAI-compatible providers\nasync function tryWithEndpointFallback(\n baseURL: string,\n opts: OpenAI.ChatCompletionCreateParams,\n headers: Record<string, string>,\n provider: string,\n proxy: any,\n signal?: AbortSignal, // \uD83D\uDD27 Add AbortSignal support\n): Promise<{ response: Response; endpoint: string }> {\n const endpointsToTry = []\n\n if (provider === 'minimax') {\n endpointsToTry.push('/text/chatcompletion_v2', '/chat/completions')\n } else {\n endpointsToTry.push('/chat/completions')\n }\n\n let lastError = null\n\n for (const endpoint of endpointsToTry) {\n try {\n const response = await fetch(`${baseURL}${endpoint}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(opts.stream ? { ...opts, stream: true } : opts),\n dispatcher: proxy,\n signal: signal, // \uD83D\uDD27 Connect AbortSignal to fetch call\n })\n\n // If successful, return immediately\n if (response.ok) {\n return { response, endpoint }\n }\n\n // If it's a 404, try the next endpoint\n if (response.status === 404 && endpointsToTry.length > 1) {\n console.log(\n `Endpoint ${endpoint} returned 404, trying next endpoint...`,\n )\n continue\n }\n\n // For other error codes, return this response (don't try fallback)\n return { response, endpoint }\n } catch (error) {\n lastError = error\n // Network errors might be temporary, try next endpoint\n if (endpointsToTry.indexOf(endpoint) < endpointsToTry.length - 1) {\n console.log(`Network error on ${endpoint}, trying next endpoint...`)\n continue\n }\n }\n }\n\n // If we get here, all endpoints failed\n throw lastError || new Error('All endpoints failed')\n}\n\n// Export shared utilities for GPT-5 compatibility\nexport { getGPT5CompletionWithProfile, getModelFeatures, applyModelSpecificTransformations }\n\nexport async function getCompletionWithProfile(\n modelProfile: any,\n opts: OpenAI.ChatCompletionCreateParams,\n attempt: number = 0,\n maxAttempts: number = 10,\n signal?: AbortSignal, // \uD83D\uDD27 CRITICAL FIX: Add AbortSignal support\n): Promise<OpenAI.ChatCompletion | AsyncIterable<OpenAI.ChatCompletionChunk>> {\n if (attempt >= maxAttempts) {\n throw new Error('Max attempts reached')\n }\n\n const provider = modelProfile?.provider || 'anthropic'\n const baseURL = modelProfile?.baseURL\n const apiKey = modelProfile?.apiKey\n const proxy = getGlobalConfig().proxy\n ? new ProxyAgent(getGlobalConfig().proxy)\n : undefined\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n\n if (apiKey) {\n if (provider === 'azure') {\n headers['api-key'] = apiKey\n } else {\n headers['Authorization'] = `Bearer ${apiKey}`\n }\n }\n\n applyModelSpecificTransformations(opts)\n await applyModelErrorFixes(opts, baseURL || '')\n\n // \uD83D\uDD25 REAL-TIME API CALL DEBUG - \u4F7F\u7528\u5168\u5C40\u65E5\u5FD7\u7CFB\u7EDF\n debugLogger.api('OPENAI_API_CALL_START', {\n endpoint: baseURL || 'DEFAULT_OPENAI',\n model: opts.model,\n provider,\n apiKeyConfigured: !!apiKey,\n apiKeyPrefix: apiKey ? apiKey.substring(0, 8) : null,\n maxTokens: opts.max_tokens,\n temperature: opts.temperature,\n messageCount: opts.messages?.length || 0,\n streamMode: opts.stream,\n timestamp: new Date().toISOString(),\n modelProfileModelName: modelProfile?.modelName,\n modelProfileName: modelProfile?.name,\n })\n\n // Make sure all tool messages have string content\n opts.messages = opts.messages.map(msg => {\n if (msg.role === 'tool') {\n if (Array.isArray(msg.content)) {\n return {\n ...msg,\n content:\n msg.content\n .map(c => c.text || '')\n .filter(Boolean)\n .join('\\n\\n') || '(empty content)',\n }\n } else if (typeof msg.content !== 'string') {\n return {\n ...msg,\n content:\n typeof msg.content === 'undefined'\n ? '(empty content)'\n : JSON.stringify(msg.content),\n }\n }\n }\n return msg\n })\n\n // Define Azure-specific API endpoint with version\n const azureApiVersion = '2024-06-01'\n let endpoint = '/chat/completions'\n\n if (provider === 'azure') {\n endpoint = `/chat/completions?api-version=${azureApiVersion}`\n } else if (provider === 'minimax') {\n endpoint = '/text/chatcompletion_v2'\n }\n\n try {\n if (opts.stream) {\n const isOpenAICompatible = [\n 'minimax',\n 'kimi',\n 'deepseek',\n 'siliconflow',\n 'qwen',\n 'glm',\n 'baidu-qianfan',\n 'openai',\n 'mistral',\n 'xai',\n 'groq',\n 'custom-openai',\n ].includes(provider)\n\n let response: Response\n let usedEndpoint: string\n\n if (isOpenAICompatible && provider !== 'azure') {\n const result = await tryWithEndpointFallback(\n baseURL,\n opts,\n headers,\n provider,\n proxy,\n signal, // \uD83D\uDD27 Pass AbortSignal to endpoint fallback\n )\n response = result.response\n usedEndpoint = result.endpoint\n } else {\n response = await fetch(`${baseURL}${endpoint}`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ ...opts, stream: true }),\n dispatcher: proxy,\n signal: signal, // \uD83D\uDD27 CRITICAL FIX: Connect AbortSignal to fetch call\n })\n usedEndpoint = endpoint\n }\n\n if (!response.ok) {\n // \uD83D\uDD27 CRITICAL FIX: Check abort signal BEFORE showing retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n \n // \uD83D\uDD25 NEW: Parse error message to detect and handle specific API errors\n try {\n const errorData = await response.json()\n // Type guard for error data structure\n const hasError = (data: unknown): data is { error?: { message?: string }; message?: string } => {\n return typeof data === 'object' && data !== null\n }\n const errorMessage = hasError(errorData) \n ? (errorData.error?.message || errorData.message || `HTTP ${response.status}`)\n : `HTTP ${response.status}`\n \n // Check if this is a parameter error that we can fix\n const isGPT5 = opts.model.startsWith('gpt-5')\n const handlers = isGPT5 ? [...GPT5_ERROR_HANDLERS, ...ERROR_HANDLERS] : ERROR_HANDLERS\n \n for (const handler of handlers) {\n if (handler.detect(errorMessage)) {\n console.log(`\uD83D\uDD27 Detected ${handler.type} error for ${opts.model}: ${errorMessage}`)\n \n // Store this error for future requests\n setModelError(baseURL || '', opts.model, handler.type, errorMessage)\n \n // Apply the fix and retry immediately\n await handler.fix(opts)\n console.log(`\uD83D\uDD27 Applied fix for ${handler.type}, retrying...`)\n \n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal,\n )\n }\n }\n \n // If no specific handler found, log the error for debugging\n console.log(`\u26A0\uFE0F Unhandled API error (${response.status}): ${errorMessage}`)\n \n // Log API error using unified logger\n logAPIError({\n model: opts.model,\n endpoint: `${baseURL}${endpoint}`,\n status: response.status,\n error: errorMessage,\n request: opts,\n response: errorData,\n provider: provider\n })\n } catch (parseError) {\n // If we can't parse the error, fall back to generic retry\n console.log(`\u26A0\uFE0F Could not parse error response (${response.status})`)\n \n // Log parse error\n logAPIError({\n model: opts.model,\n endpoint: `${baseURL}${endpoint}`,\n status: response.status,\n error: `Could not parse error response: ${parseError.message}`,\n request: opts,\n response: { parseError: parseError.message },\n provider: provider\n })\n }\n \n const delayMs = getRetryDelay(attempt)\n console.log(\n ` \u23BF API error (${response.status}), retrying in ${Math.round(delayMs / 1000)}s... (attempt ${attempt + 1}/${maxAttempts})`,\n )\n try {\n await abortableDelay(delayMs, signal)\n } catch (error) {\n // If aborted during delay, throw the error to stop retrying\n if (error.message === 'Request was aborted') {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal, // \uD83D\uDD27 Pass AbortSignal to recursive call\n )\n }\n\n const stream = createStreamProcessor(response.body as any, signal)\n return stream\n }\n\n // Non-streaming request\n const isOpenAICompatible = [\n 'minimax',\n 'kimi',\n 'deepseek',\n 'siliconflow',\n 'qwen',\n 'glm',\n 'baidu-qianfan',\n 'openai',\n 'mistral',\n 'xai',\n 'groq',\n 'custom-openai',\n ].includes(provider)\n\n let response: Response\n let usedEndpoint: string\n\n if (isOpenAICompatible && provider !== 'azure') {\n const result = await tryWithEndpointFallback(\n baseURL,\n opts,\n headers,\n provider,\n proxy,\n signal, // \uD83D\uDD27 Pass AbortSignal to endpoint fallback\n )\n response = result.response\n usedEndpoint = result.endpoint\n } else {\n response = await fetch(`${baseURL}${endpoint}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(opts),\n dispatcher: proxy,\n signal: signal, // \uD83D\uDD27 CRITICAL FIX: Connect AbortSignal to non-streaming fetch call\n })\n usedEndpoint = endpoint\n }\n\n if (!response.ok) {\n // \uD83D\uDD27 CRITICAL FIX: Check abort signal BEFORE showing retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n \n // \uD83D\uDD25 NEW: Parse error message to detect and handle specific API errors\n try {\n const errorData = await response.json()\n // Type guard for error data structure\n const hasError = (data: unknown): data is { error?: { message?: string }; message?: string } => {\n return typeof data === 'object' && data !== null\n }\n const errorMessage = hasError(errorData) \n ? (errorData.error?.message || errorData.message || `HTTP ${response.status}`)\n : `HTTP ${response.status}`\n \n // Check if this is a parameter error that we can fix\n const isGPT5 = opts.model.startsWith('gpt-5')\n const handlers = isGPT5 ? [...GPT5_ERROR_HANDLERS, ...ERROR_HANDLERS] : ERROR_HANDLERS\n \n for (const handler of handlers) {\n if (handler.detect(errorMessage)) {\n console.log(`\uD83D\uDD27 Detected ${handler.type} error for ${opts.model}: ${errorMessage}`)\n \n // Store this error for future requests\n setModelError(baseURL || '', opts.model, handler.type, errorMessage)\n \n // Apply the fix and retry immediately\n await handler.fix(opts)\n console.log(`\uD83D\uDD27 Applied fix for ${handler.type}, retrying...`)\n \n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal,\n )\n }\n }\n \n // If no specific handler found, log the error for debugging\n console.log(`\u26A0\uFE0F Unhandled API error (${response.status}): ${errorMessage}`)\n } catch (parseError) {\n // If we can't parse the error, fall back to generic retry\n console.log(`\u26A0\uFE0F Could not parse error response (${response.status})`)\n }\n \n const delayMs = getRetryDelay(attempt)\n console.log(\n ` \u23BF API error (${response.status}), retrying in ${Math.round(delayMs / 1000)}s... (attempt ${attempt + 1}/${maxAttempts})`,\n )\n try {\n await abortableDelay(delayMs, signal)\n } catch (error) {\n // If aborted during delay, throw the error to stop retrying\n if (error.message === 'Request was aborted') {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal, // \uD83D\uDD27 Pass AbortSignal to recursive call\n )\n }\n\n const responseData = (await response.json()) as OpenAI.ChatCompletion\n return responseData\n } catch (error) {\n // \uD83D\uDD27 CRITICAL FIX: Check abort signal BEFORE showing retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n \n if (attempt < maxAttempts) {\n // \uD83D\uDD27 Double-check abort status to avoid showing misleading retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n \n const delayMs = getRetryDelay(attempt)\n console.log(\n ` \u23BF Network error, retrying in ${Math.round(delayMs / 1000)}s... (attempt ${attempt + 1}/${maxAttempts})`,\n )\n try {\n await abortableDelay(delayMs, signal)\n } catch (error) {\n // If aborted during delay, throw the error to stop retrying\n if (error.message === 'Request was aborted') {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal, // \uD83D\uDD27 Pass AbortSignal to recursive call\n )\n }\n throw error\n }\n}\n\nexport function createStreamProcessor(\n stream: any,\n signal?: AbortSignal,\n): AsyncGenerator<OpenAI.ChatCompletionChunk, void, unknown> {\n if (!stream) {\n throw new Error('Stream is null or undefined')\n }\n\n return (async function* () {\n const reader = stream.getReader()\n const decoder = new TextDecoder('utf-8')\n let buffer = ''\n\n try {\n while (true) {\n // Check for cancellation before attempting to read\n if (signal?.aborted) {\n break\n }\n\n let readResult\n try {\n readResult = await reader.read()\n } catch (e) {\n // If signal is aborted, this is user cancellation - exit silently\n if (signal?.aborted) {\n break\n }\n console.error('Error reading from stream:', e)\n break\n }\n\n const { done, value } = readResult\n if (done) {\n break\n }\n\n const chunk = decoder.decode(value, { stream: true })\n buffer += chunk\n\n let lineEnd = buffer.indexOf('\\n')\n while (lineEnd !== -1) {\n const line = buffer.substring(0, lineEnd).trim()\n buffer = buffer.substring(lineEnd + 1)\n\n if (line === 'data: [DONE]') {\n continue\n }\n\n if (line.startsWith('data: ')) {\n const data = line.slice(6).trim()\n if (!data) continue\n\n try {\n const parsed = JSON.parse(data) as OpenAI.ChatCompletionChunk\n yield parsed\n } catch (e) {\n console.error('Error parsing JSON:', data, e)\n }\n }\n\n lineEnd = buffer.indexOf('\\n')\n }\n }\n\n // Process any remaining data in the buffer\n if (buffer.trim()) {\n const lines = buffer.trim().split('\\n')\n for (const line of lines) {\n if (line.startsWith('data: ') && line !== 'data: [DONE]') {\n const data = line.slice(6).trim()\n if (!data) continue\n\n try {\n const parsed = JSON.parse(data) as OpenAI.ChatCompletionChunk\n yield parsed\n } catch (e) {\n console.error('Error parsing final JSON:', data, e)\n }\n }\n }\n }\n } catch (e) {\n console.error('Unexpected error in stream processing:', e)\n } finally {\n try {\n reader.releaseLock()\n } catch (e) {\n console.error('Error releasing reader lock:', e)\n }\n }\n })()\n}\n\nexport function streamCompletion(\n stream: any,\n signal?: AbortSignal,\n): AsyncGenerator<OpenAI.ChatCompletionChunk, void, unknown> {\n return createStreamProcessor(stream, signal)\n}\n\n/**\n * Call GPT-5 Responses API with proper parameter handling\n */\nexport async function callGPT5ResponsesAPI(\n modelProfile: any,\n opts: any, // Using 'any' for Responses API params which differ from ChatCompletionCreateParams\n signal?: AbortSignal,\n): Promise<any> {\n const baseURL = modelProfile?.baseURL || 'https://api.openai.com/v1'\n const apiKey = modelProfile?.apiKey\n const proxy = getGlobalConfig().proxy\n ? new ProxyAgent(getGlobalConfig().proxy)\n : undefined\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n }\n\n // \uD83D\uDD25 Enhanced Responses API Parameter Mapping for GPT-5\n const responsesParams: any = {\n model: opts.model,\n input: opts.messages, // Responses API uses 'input' instead of 'messages'\n }\n\n // \uD83D\uDD27 GPT-5 Token Configuration\n if (opts.max_completion_tokens) {\n responsesParams.max_completion_tokens = opts.max_completion_tokens\n } else if (opts.max_tokens) {\n // Fallback conversion if max_tokens is still present\n responsesParams.max_completion_tokens = opts.max_tokens\n }\n\n // \uD83D\uDD27 GPT-5 Temperature Handling (only 1 or undefined)\n if (opts.temperature === 1) {\n responsesParams.temperature = 1\n }\n // Note: Do not pass temperature if it's not 1, GPT-5 will use default\n\n // \uD83D\uDD27 GPT-5 Reasoning Configuration\n const reasoningEffort = opts.reasoning_effort || 'medium'\n responsesParams.reasoning = {\n effort: reasoningEffort,\n // \uD83D\uDE80 Enable reasoning summaries for transparency in coding tasks\n generate_summary: true,\n }\n\n // \uD83D\uDD27 GPT-5 Tools Support\n if (opts.tools && opts.tools.length > 0) {\n responsesParams.tools = opts.tools\n \n // \uD83D\uDE80 GPT-5 Tool Choice Configuration\n if (opts.tool_choice) {\n responsesParams.tool_choice = opts.tool_choice\n }\n }\n\n // \uD83D\uDD27 GPT-5 System Instructions (separate from messages)\n const systemMessages = opts.messages.filter(msg => msg.role === 'system')\n const nonSystemMessages = opts.messages.filter(msg => msg.role !== 'system')\n \n if (systemMessages.length > 0) {\n responsesParams.instructions = systemMessages.map(msg => msg.content).join('\\n\\n')\n responsesParams.input = nonSystemMessages\n }\n\n // Handle verbosity (if supported) - optimized for coding tasks\n const features = getModelFeatures(opts.model)\n if (features.supportsVerbosityControl) {\n // High verbosity for coding tasks to get detailed explanations and structured code\n // Based on GPT-5 best practices for agent-like coding environments\n responsesParams.text = {\n verbosity: 'high',\n }\n }\n\n // Apply GPT-5 coding optimizations\n if (opts.model.startsWith('gpt-5')) {\n // Set reasoning effort based on task complexity\n if (!responsesParams.reasoning) {\n responsesParams.reasoning = {\n effort: 'medium', // Balanced for most coding tasks\n }\n }\n\n // Add instructions parameter for coding-specific guidance\n if (!responsesParams.instructions) {\n responsesParams.instructions = `You are an expert programmer working in a terminal-based coding environment. Follow these guidelines:\n- Provide clear, concise code solutions\n- Use proper error handling and validation\n- Follow coding best practices and patterns\n- Explain complex logic when necessary\n- Focus on maintainable, readable code`\n }\n }\n\n try {\n const response = await fetch(`${baseURL}/responses`, {\n method: 'POST',\n headers,\n body: JSON.stringify(responsesParams),\n dispatcher: proxy,\n signal: signal,\n })\n\n if (!response.ok) {\n throw new Error(`GPT-5 Responses API error: ${response.status} ${response.statusText}`)\n }\n\n const responseData = await response.json()\n \n // Convert Responses API response back to Chat Completion format for compatibility\n return convertResponsesAPIToChatCompletion(responseData)\n } catch (error) {\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n}\n\n/**\n * Convert Responses API response to Chat Completion format for compatibility\n * \uD83D\uDD25 Enhanced for GPT-5 with reasoning summary support\n */\nfunction convertResponsesAPIToChatCompletion(responsesData: any): any {\n // Extract content from Responses API format\n let outputText = responsesData.output_text || ''\n const usage = responsesData.usage || {}\n \n // \uD83D\uDE80 GPT-5 Reasoning Summary Integration\n // If reasoning summary is available, prepend it to the output for transparency\n if (responsesData.output && Array.isArray(responsesData.output)) {\n const reasoningItems = responsesData.output.filter(item => item.type === 'reasoning' && item.summary)\n const messageItems = responsesData.output.filter(item => item.type === 'message')\n \n if (reasoningItems.length > 0 && messageItems.length > 0) {\n const reasoningSummary = reasoningItems\n .map(item => item.summary?.map(s => s.text).join('\\n'))\n .filter(Boolean)\n .join('\\n\\n')\n \n const mainContent = messageItems\n .map(item => item.content?.map(c => c.text).join('\\n'))\n .filter(Boolean)\n .join('\\n\\n')\n \n if (reasoningSummary) {\n outputText = `**\uD83E\uDDE0 Reasoning Process:**\\n${reasoningSummary}\\n\\n**\uD83D\uDCDD Response:**\\n${mainContent}`\n } else {\n outputText = mainContent\n }\n }\n }\n\n return {\n id: responsesData.id || `chatcmpl-${Date.now()}`,\n object: 'chat.completion',\n created: Math.floor(Date.now() / 1000),\n model: responsesData.model || '',\n choices: [\n {\n index: 0,\n message: {\n role: 'assistant',\n content: outputText,\n // \uD83D\uDE80 Include reasoning metadata if available\n ...(responsesData.reasoning && {\n reasoning: {\n effort: responsesData.reasoning.effort,\n summary: responsesData.reasoning.summary,\n },\n }),\n },\n finish_reason: responsesData.status === 'completed' ? 'stop' : 'length',\n },\n ],\n usage: {\n prompt_tokens: usage.input_tokens || 0,\n completion_tokens: usage.output_tokens || 0,\n total_tokens: (usage.input_tokens || 0) + (usage.output_tokens || 0),\n // \uD83D\uDD27 GPT-5 Enhanced Usage Details\n prompt_tokens_details: {\n cached_tokens: usage.input_tokens_details?.cached_tokens || 0,\n },\n completion_tokens_details: {\n reasoning_tokens: usage.output_tokens_details?.reasoning_tokens || 0,\n },\n },\n }\n}\n\n/**\n * Enhanced getCompletionWithProfile that supports GPT-5 Responses API\n * \uD83D\uDD25 Optimized for both official OpenAI and third-party GPT-5 providers\n */\nasync function getGPT5CompletionWithProfile(\n modelProfile: any,\n opts: OpenAI.ChatCompletionCreateParams,\n attempt: number = 0,\n maxAttempts: number = 10,\n signal?: AbortSignal,\n): Promise<OpenAI.ChatCompletion | AsyncIterable<OpenAI.ChatCompletionChunk>> {\n const features = getModelFeatures(opts.model)\n const isOfficialOpenAI = !modelProfile.baseURL || \n modelProfile.baseURL.includes('api.openai.com')\n\n // \uD83D\uDE80 Try Responses API for official OpenAI non-streaming requests\n if (features.supportsResponsesAPI && !opts.stream && isOfficialOpenAI) {\n try {\n debugLogger.api('ATTEMPTING_GPT5_RESPONSES_API', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n provider: modelProfile.provider,\n stream: opts.stream,\n requestId: getCurrentRequest()?.id,\n })\n \n const result = await callGPT5ResponsesAPI(modelProfile, opts, signal)\n \n debugLogger.api('GPT5_RESPONSES_API_SUCCESS', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n requestId: getCurrentRequest()?.id,\n })\n \n return result\n } catch (error) {\n debugLogger.api('GPT5_RESPONSES_API_FALLBACK', {\n model: opts.model,\n error: error.message,\n baseURL: modelProfile.baseURL || 'official',\n requestId: getCurrentRequest()?.id,\n })\n \n console.warn(\n `\uD83D\uDD04 GPT-5 Responses API failed, falling back to Chat Completions: ${error.message}`\n )\n // Fall through to Chat Completions API\n }\n } \n \n // \uD83C\uDF10 Handle third-party GPT-5 providers with enhanced compatibility\n else if (!isOfficialOpenAI) {\n debugLogger.api('GPT5_THIRD_PARTY_PROVIDER', {\n model: opts.model,\n baseURL: modelProfile.baseURL,\n provider: modelProfile.provider,\n supportsResponsesAPI: features.supportsResponsesAPI,\n requestId: getCurrentRequest()?.id,\n })\n \n // \uD83D\uDD27 Apply enhanced parameter optimization for third-party providers\n console.log(`\uD83C\uDF10 Using GPT-5 via third-party provider: ${modelProfile.provider} (${modelProfile.baseURL})`)\n \n // Some third-party providers may need additional parameter adjustments\n if (modelProfile.provider === 'azure') {\n // Azure OpenAI specific adjustments\n delete opts.reasoning_effort // Azure may not support this yet\n } else if (modelProfile.provider === 'custom-openai') {\n // Generic OpenAI-compatible provider optimizations\n console.log(`\uD83D\uDD27 Applying OpenAI-compatible optimizations for custom provider`)\n }\n }\n \n // \uD83D\uDCE1 Handle streaming requests (Responses API doesn't support streaming yet)\n else if (opts.stream) {\n debugLogger.api('GPT5_STREAMING_MODE', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n reason: 'responses_api_no_streaming',\n requestId: getCurrentRequest()?.id,\n })\n \n console.log(`\uD83D\uDD04 Using Chat Completions for streaming (Responses API streaming not available)`)\n }\n\n // \uD83D\uDD27 Enhanced Chat Completions fallback with GPT-5 optimizations\n debugLogger.api('USING_CHAT_COMPLETIONS_FOR_GPT5', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n provider: modelProfile.provider,\n reason: isOfficialOpenAI ? 'streaming_or_fallback' : 'third_party_provider',\n requestId: getCurrentRequest()?.id,\n })\n\n return await getCompletionWithProfile(\n modelProfile,\n opts,\n attempt,\n maxAttempts,\n signal,\n )\n}\n\n/**\n * Fetch available models from custom OpenAI-compatible API\n */\nexport async function fetchCustomModels(\n baseURL: string,\n apiKey: string,\n): Promise<any[]> {\n try {\n // Check if baseURL already contains version number (e.g., v1, v2, etc.)\n const hasVersionNumber = /\\/v\\d+/.test(baseURL)\n const cleanBaseURL = baseURL.replace(/\\/+$/, '')\n const modelsURL = hasVersionNumber\n ? `${cleanBaseURL}/models`\n : `${cleanBaseURL}/v1/models`\n\n const response = await fetch(modelsURL, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n },\n })\n\n if (!response.ok) {\n // Provide user-friendly error messages based on status code\n if (response.status === 401) {\n throw new Error(\n 'Invalid API key. Please check your API key and try again.',\n )\n } else if (response.status === 403) {\n throw new Error(\n 'API key does not have permission to access models. Please check your API key permissions.',\n )\n } else if (response.status === 404) {\n throw new Error(\n 'API endpoint not found. Please check if the base URL is correct and supports the /models endpoint.',\n )\n } else if (response.status === 429) {\n throw new Error(\n 'Too many requests. Please wait a moment and try again.',\n )\n } else if (response.status >= 500) {\n throw new Error(\n 'API service is temporarily unavailable. Please try again later.',\n )\n } else {\n throw new Error(\n `Unable to connect to API (${response.status}). Please check your base URL, API key, and internet connection.`,\n )\n }\n }\n\n const data = await response.json()\n\n // Type guards for different API response formats\n const hasDataArray = (obj: unknown): obj is { data: unknown[] } => {\n return typeof obj === 'object' && obj !== null && 'data' in obj && Array.isArray((obj as any).data)\n }\n \n const hasModelsArray = (obj: unknown): obj is { models: unknown[] } => {\n return typeof obj === 'object' && obj !== null && 'models' in obj && Array.isArray((obj as any).models)\n }\n\n // Validate response format and extract models array\n let models = []\n\n if (hasDataArray(data)) {\n // Standard OpenAI format: { data: [...] }\n models = data.data\n } else if (Array.isArray(data)) {\n // Direct array format\n models = data\n } else if (hasModelsArray(data)) {\n // Alternative format: { models: [...] }\n models = data.models\n } else {\n throw new Error(\n 'API returned unexpected response format. Expected an array of models or an object with a \"data\" or \"models\" array.',\n )\n }\n\n // Ensure we have an array and validate it contains model objects\n if (!Array.isArray(models)) {\n throw new Error('API response format error: models data is not an array.')\n }\n\n return models\n } catch (error) {\n // If it's already our custom error, pass it through\n if (\n error instanceof Error &&\n (error.message.includes('API key') ||\n error.message.includes('API endpoint') ||\n error.message.includes('API service') ||\n error.message.includes('response format'))\n ) {\n throw error\n }\n\n // For network errors or other issues\n console.error('Failed to fetch custom API models:', error)\n\n // Check if it's a network error\n if (error instanceof Error && error.message.includes('fetch')) {\n throw new Error(\n 'Unable to connect to the API. Please check the base URL and your internet connection.',\n )\n }\n\n throw new Error(\n 'Failed to fetch models from custom API. Please check your configuration and try again.',\n )\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["ModelErrorType", "isOpenAICompatible", "response", "usedEndpoint", "error"]
|
|
7
7
|
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
overwriteLog
|
|
15
15
|
} from "../../utils/log.js";
|
|
16
16
|
import {
|
|
17
|
+
createAssistantMessage,
|
|
17
18
|
createUserMessage,
|
|
18
19
|
getLastAssistantMessageId,
|
|
19
20
|
INTERRUPT_MESSAGE,
|
|
@@ -94,12 +95,36 @@ ${prompt}`;
|
|
|
94
95
|
tools = tools.filter((tool) => toolFilter.includes(tool.name));
|
|
95
96
|
}
|
|
96
97
|
}
|
|
98
|
+
const modelToUse = effectiveModel;
|
|
99
|
+
yield {
|
|
100
|
+
type: "progress",
|
|
101
|
+
content: createAssistantMessage(`Starting agent: ${agentType}`),
|
|
102
|
+
normalizedMessages: normalizeMessages(messages),
|
|
103
|
+
tools
|
|
104
|
+
};
|
|
105
|
+
yield {
|
|
106
|
+
type: "progress",
|
|
107
|
+
content: createAssistantMessage(`Using model: ${modelToUse}`),
|
|
108
|
+
normalizedMessages: normalizeMessages(messages),
|
|
109
|
+
tools
|
|
110
|
+
};
|
|
111
|
+
yield {
|
|
112
|
+
type: "progress",
|
|
113
|
+
content: createAssistantMessage(`Task: ${description}`),
|
|
114
|
+
normalizedMessages: normalizeMessages(messages),
|
|
115
|
+
tools
|
|
116
|
+
};
|
|
117
|
+
yield {
|
|
118
|
+
type: "progress",
|
|
119
|
+
content: createAssistantMessage(`Prompt: ${prompt.length > 150 ? prompt.substring(0, 150) + "..." : prompt}`),
|
|
120
|
+
normalizedMessages: normalizeMessages(messages),
|
|
121
|
+
tools
|
|
122
|
+
};
|
|
97
123
|
const [taskPrompt, context, maxThinkingTokens] = await Promise.all([
|
|
98
124
|
getAgentPrompt(),
|
|
99
125
|
getContext(),
|
|
100
126
|
getMaxThinkingTokens(messages)
|
|
101
127
|
]);
|
|
102
|
-
const modelToUse = effectiveModel;
|
|
103
128
|
taskPrompt.push(`
|
|
104
129
|
IMPORTANT: You are currently running as ${modelToUse}. You do not need to consult ${modelToUse} via AskExpertModel since you ARE ${modelToUse}. Complete tasks directly using your capabilities.`);
|
|
105
130
|
let toolUseCount = 0;
|
|
@@ -148,6 +173,12 @@ IMPORTANT: You are currently running as ${modelToUse}. You do not need to consul
|
|
|
148
173
|
for (const content of message.message.content) {
|
|
149
174
|
if (content.type === "text" && content.text && content.text !== INTERRUPT_MESSAGE) {
|
|
150
175
|
const preview = content.text.length > 200 ? content.text.substring(0, 200) + "..." : content.text;
|
|
176
|
+
yield {
|
|
177
|
+
type: "progress",
|
|
178
|
+
content: createAssistantMessage(`${preview}`),
|
|
179
|
+
normalizedMessages: normalizedMessages2,
|
|
180
|
+
tools
|
|
181
|
+
};
|
|
151
182
|
} else if (content.type === "tool_use") {
|
|
152
183
|
toolUseCount++;
|
|
153
184
|
const toolMessage = normalizedMessages2.find(
|
|
@@ -170,6 +201,12 @@ IMPORTANT: You are currently running as ${modelToUse}. You do not need to consul
|
|
|
170
201
|
})
|
|
171
202
|
}
|
|
172
203
|
};
|
|
204
|
+
yield {
|
|
205
|
+
type: "progress",
|
|
206
|
+
content: modifiedMessage,
|
|
207
|
+
normalizedMessages: normalizedMessages2,
|
|
208
|
+
tools
|
|
209
|
+
};
|
|
173
210
|
}
|
|
174
211
|
}
|
|
175
212
|
}
|
|
@@ -190,6 +227,12 @@ IMPORTANT: You are currently running as ${modelToUse}. You do not need to consul
|
|
|
190
227
|
) + " tokens",
|
|
191
228
|
formatDuration(Date.now() - startTime)
|
|
192
229
|
];
|
|
230
|
+
yield {
|
|
231
|
+
type: "progress",
|
|
232
|
+
content: createAssistantMessage(`Task completed (${result.join(" \xB7 ")})`),
|
|
233
|
+
normalizedMessages,
|
|
234
|
+
tools
|
|
235
|
+
};
|
|
193
236
|
}
|
|
194
237
|
const data = lastMessage.message.content.filter((_) => _.type === "text");
|
|
195
238
|
yield {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/tools/TaskTool/TaskTool.tsx"],
|
|
4
|
-
"sourcesContent": ["import { TextBlock } from '@anthropic-ai/sdk/resources/index.mjs'\nimport chalk from 'chalk'\nimport { last, memoize } from 'lodash-es'\nimport { EOL } from 'os'\nimport React, { useState, useEffect } from 'react'\nimport { Box, Text } from 'ink'\nimport { z } from 'zod'\nimport { Tool, ValidationResult } from '../../Tool'\nimport { FallbackToolUseRejectedMessage } from '../../components/FallbackToolUseRejectedMessage'\nimport { getAgentPrompt } from '../../constants/prompts'\nimport { getContext } from '../../context'\nimport { hasPermissionsToUseTool } from '../../permissions'\nimport { AssistantMessage, Message as MessageType, query } from '../../query'\nimport { formatDuration, formatNumber } from '../../utils/format'\nimport {\n getMessagesPath,\n getNextAvailableLogSidechainNumber,\n overwriteLog,\n} from '../../utils/log.js'\nimport { applyMarkdown } from '../../utils/markdown'\nimport {\n createAssistantMessage,\n createUserMessage,\n getLastAssistantMessageId,\n INTERRUPT_MESSAGE,\n normalizeMessages,\n} from '../../utils/messages.js'\nimport { getModelManager } from '../../utils/model'\nimport { getMaxThinkingTokens } from '../../utils/thinking'\nimport { getTheme } from '../../utils/theme'\nimport { generateAgentId } from '../../utils/agentStorage'\nimport { debug as debugLogger } from '../../utils/debugLogger'\nimport { getTaskTools, getPrompt } from './prompt'\nimport { TOOL_NAME } from './constants'\nimport { getActiveAgents, getAgentByType, getAvailableAgentTypes } from '../../utils/agentLoader'\n\nconst inputSchema = z.object({\n description: z\n .string()\n .describe('A short (3-5 word) description of the task'),\n prompt: z.string().describe('The task for the agent to perform'),\n model_name: z\n .string()\n .optional()\n .describe(\n 'Optional: Specific model name to use for this task. If not provided, uses the default task model pointer.',\n ),\n subagent_type: z\n .string()\n .optional()\n .describe(\n 'The type of specialized agent to use for this task',\n ),\n})\n\nexport const TaskTool = {\n async prompt({ safeMode }) {\n // Match original Claude Code - prompt returns full agent descriptions\n return await getPrompt(safeMode)\n },\n name: TOOL_NAME,\n async description() {\n // Match original Claude Code exactly - simple description\n return \"Launch a new task\"\n },\n inputSchema,\n \n async *call(\n { description, prompt, model_name, subagent_type },\n {\n abortController,\n options: { safeMode = false, forkNumber, messageLogName, verbose },\n readFileTimestamps,\n },\n ): AsyncGenerator<{ type: 'result'; data: TextBlock[]; resultForAssistant?: string }, void, unknown> {\n const startTime = Date.now()\n \n // Default to general-purpose if no subagent_type specified\n const agentType = subagent_type || 'general-purpose'\n \n // Apply subagent configuration\n let effectivePrompt = prompt\n let effectiveModel = model_name || 'task'\n let toolFilter = null\n let temperature = undefined\n \n // Load agent configuration dynamically\n if (agentType) {\n const agentConfig = await getAgentByType(agentType)\n \n if (!agentConfig) {\n // If agent type not found, return helpful message instead of throwing\n const availableTypes = await getAvailableAgentTypes()\n const helpMessage = `Agent type '${agentType}' not found.\\n\\nAvailable agents:\\n${availableTypes.map(t => ` \u2022 ${t}`).join('\\n')}\\n\\nUse /agents command to manage agent configurations.`\n \n yield {\n type: 'result',\n data: [{ type: 'text', text: helpMessage }] as TextBlock[],\n resultForAssistant: helpMessage,\n }\n return\n }\n \n // Apply system prompt if configured\n if (agentConfig.systemPrompt) {\n effectivePrompt = `${agentConfig.systemPrompt}\\n\\n${prompt}`\n }\n \n // Apply model if not overridden by model_name parameter\n if (!model_name && agentConfig.model_name) {\n // Support inherit: keep pointer-based default\n if (agentConfig.model_name !== 'inherit') {\n effectiveModel = agentConfig.model_name as string\n }\n }\n \n // Store tool filter for later application\n toolFilter = agentConfig.tools\n \n // Note: temperature is not currently in our agent configs\n // but could be added in the future\n }\n \n const messages: MessageType[] = [createUserMessage(effectivePrompt)]\n let tools = await getTaskTools(safeMode)\n \n // Apply tool filtering if specified by subagent config\n if (toolFilter) {\n // Back-compat: ['*'] means all tools\n const isAllArray = Array.isArray(toolFilter) && toolFilter.length === 1 && toolFilter[0] === '*'\n if (toolFilter === '*' || isAllArray) {\n // no-op, keep all tools\n } else if (Array.isArray(toolFilter)) {\n tools = tools.filter(tool => toolFilter.includes(tool.name))\n }\n }\n\n // Skip initial progress yield - only yield results for Tool interface\n\n const [taskPrompt, context, maxThinkingTokens] = await Promise.all([\n getAgentPrompt(),\n getContext(),\n getMaxThinkingTokens(messages),\n ])\n\n // Model already resolved in effectiveModel variable above\n const modelToUse = effectiveModel\n \n // Inject model context to prevent self-referential expert consultations\n taskPrompt.push(`\\nIMPORTANT: You are currently running as ${modelToUse}. You do not need to consult ${modelToUse} via AskExpertModel since you ARE ${modelToUse}. Complete tasks directly using your capabilities.`)\n\n let toolUseCount = 0\n\n const getSidechainNumber = memoize(() =>\n getNextAvailableLogSidechainNumber(messageLogName, forkNumber),\n )\n\n // Generate unique Task ID for this task execution\n const taskId = generateAgentId()\n\n // \uD83D\uDD27 ULTRA SIMPLIFIED: Exact original AgentTool pattern\n // Build query options, adding temperature if specified\n const queryOptions = {\n safeMode,\n forkNumber,\n messageLogName,\n tools,\n commands: [],\n verbose,\n maxThinkingTokens,\n model: modelToUse,\n }\n \n // Add temperature if specified by subagent config\n if (temperature !== undefined) {\n queryOptions['temperature'] = temperature\n }\n \n for await (const message of query(\n messages,\n taskPrompt,\n context,\n hasPermissionsToUseTool,\n {\n abortController,\n options: queryOptions,\n messageId: getLastAssistantMessageId(messages),\n agentId: taskId,\n readFileTimestamps,\n setToolJSX: () => {}, // No-op implementation for TaskTool\n },\n )) {\n messages.push(message)\n\n overwriteLog(\n getMessagesPath(messageLogName, forkNumber, getSidechainNumber()),\n messages.filter(_ => _.type !== 'progress'),\n )\n\n if (message.type !== 'assistant') {\n continue\n }\n\n const normalizedMessages = normalizeMessages(messages)\n \n // Process tool uses and text content for better visibility\n for (const content of message.message.content) {\n if (content.type === 'text' && content.text && content.text !== INTERRUPT_MESSAGE) {\n // Show agent's reasoning/responses\n const preview = content.text.length > 200 ? content.text.substring(0, 200) + '...' : content.text\n // Skip progress yield - only yield results for Tool interface\n } else if (content.type === 'tool_use') {\n toolUseCount++\n \n // Show which tool is being used with agent context\n const toolMessage = normalizedMessages.find(\n _ =>\n _.type === 'assistant' &&\n _.message.content[0]?.type === 'tool_use' &&\n _.message.content[0].id === content.id,\n ) as AssistantMessage\n \n if (toolMessage) {\n // Clone and modify the message to show agent context\n const modifiedMessage = {\n ...toolMessage,\n message: {\n ...toolMessage.message,\n content: toolMessage.message.content.map(c => {\n if (c.type === 'tool_use' && c.id === content.id) {\n // Add agent context to tool name display\n return {\n ...c,\n name: c.name // Keep original name, UI will handle display\n }\n }\n return c\n })\n }\n }\n \n // Skip progress yield - only yield results for Tool interface\n }\n }\n }\n }\n\n const normalizedMessages = normalizeMessages(messages)\n const lastMessage = last(messages)\n if (lastMessage?.type !== 'assistant') {\n throw new Error('Last message was not an assistant message')\n }\n\n // \uD83D\uDD27 CRITICAL FIX: Match original AgentTool interrupt handling pattern exactly\n if (\n lastMessage.message.content.some(\n _ => _.type === 'text' && _.text === INTERRUPT_MESSAGE,\n )\n ) {\n // Skip progress yield - only yield final result\n } else {\n const result = [\n toolUseCount === 1 ? '1 tool use' : `${toolUseCount} tool uses`,\n formatNumber(\n (lastMessage.message.usage.cache_creation_input_tokens ?? 0) +\n (lastMessage.message.usage.cache_read_input_tokens ?? 0) +\n lastMessage.message.usage.input_tokens +\n lastMessage.message.usage.output_tokens,\n ) + ' tokens',\n formatDuration(Date.now() - startTime),\n ]\n // Skip progress yield - only yield final result\n }\n\n // Output is an AssistantMessage, but since TaskTool is a tool, it needs\n // to serialize its response to UserMessage-compatible content.\n const data = lastMessage.message.content.filter(_ => _.type === 'text')\n yield {\n type: 'result',\n data,\n resultForAssistant: this.renderResultForAssistant(data),\n }\n },\n\n isReadOnly() {\n return true // for now...\n },\n isConcurrencySafe() {\n return true // Task tool supports concurrent execution in official implementation\n },\n async validateInput(input, context) {\n if (!input.description || typeof input.description !== 'string') {\n return {\n result: false,\n message: 'Description is required and must be a string',\n }\n }\n if (!input.prompt || typeof input.prompt !== 'string') {\n return {\n result: false,\n message: 'Prompt is required and must be a string',\n }\n }\n\n // Model validation - similar to Edit tool error handling\n if (input.model_name) {\n const modelManager = getModelManager()\n const availableModels = modelManager.getAllAvailableModelNames()\n\n if (!availableModels.includes(input.model_name)) {\n return {\n result: false,\n message: `Model '${input.model_name}' does not exist. Available models: ${availableModels.join(', ')}`,\n meta: {\n model_name: input.model_name,\n availableModels,\n },\n }\n }\n }\n\n // Validate subagent_type if provided\n if (input.subagent_type) {\n const availableTypes = await getAvailableAgentTypes()\n if (!availableTypes.includes(input.subagent_type)) {\n return {\n result: false,\n message: `Agent type '${input.subagent_type}' does not exist. Available types: ${availableTypes.join(', ')}`,\n meta: {\n subagent_type: input.subagent_type,\n availableTypes,\n },\n }\n }\n }\n\n return { result: true }\n },\n async isEnabled() {\n return true\n },\n userFacingName(input?: any) {\n // Return agent name with proper prefix\n const agentType = input?.subagent_type || 'general-purpose'\n return `agent-${agentType}`\n },\n needsPermissions() {\n return false\n },\n renderResultForAssistant(data: TextBlock[]) {\n return data.map(block => block.type === 'text' ? block.text : '').join('\\n')\n },\n renderToolUseMessage({ description, prompt, model_name, subagent_type }, { verbose }) {\n if (!description || !prompt) return null\n\n const modelManager = getModelManager()\n const defaultTaskModel = modelManager.getModelName('task')\n const actualModel = model_name || defaultTaskModel\n const agentType = subagent_type || 'general-purpose'\n const promptPreview =\n prompt.length > 80 ? prompt.substring(0, 80) + '...' : prompt\n\n const theme = getTheme()\n \n if (verbose) {\n return (\n <Box flexDirection=\"column\">\n <Text>\n [{agentType}] {actualModel}: {description}\n </Text>\n <Box\n paddingLeft={2}\n borderLeftStyle=\"single\"\n borderLeftColor={theme.secondaryBorder}\n >\n <Text color={theme.secondaryText}>{promptPreview}</Text>\n </Box>\n </Box>\n )\n }\n\n // Simple display: agent type, model and description\n return `[${agentType}] ${actualModel}: ${description}`\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage(content) {\n const theme = getTheme()\n\n if (Array.isArray(content)) {\n const textBlocks = content.filter(block => block.type === 'text')\n const totalLength = textBlocks.reduce(\n (sum, block) => sum + block.text.length,\n 0,\n )\n // \uD83D\uDD27 CRITICAL FIX: Use exact match for interrupt detection, not .includes()\n const isInterrupted = content.some(\n block =>\n block.type === 'text' && block.text === INTERRUPT_MESSAGE,\n )\n\n if (isInterrupted) {\n // \uD83D\uDD27 CRITICAL FIX: Match original system interrupt rendering exactly\n return (\n <Box flexDirection=\"row\">\n <Text> \u23BF </Text>\n <Text color={theme.error}>Interrupted by user</Text>\n </Box>\n )\n }\n\n return (\n <Box flexDirection=\"column\">\n <Box justifyContent=\"space-between\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text> \u23BF </Text>\n <Text>Task completed</Text>\n {textBlocks.length > 0 && (\n <Text color={theme.secondaryText}>\n {' '}\n ({totalLength} characters)\n </Text>\n )}\n </Box>\n </Box>\n </Box>\n )\n }\n\n return (\n <Box flexDirection=\"row\">\n <Text> \u23BF </Text>\n <Text color={theme.secondaryText}>Task completed</Text>\n </Box>\n )\n },\n} satisfies Tool<typeof inputSchema, TextBlock[]>\n"],
|
|
5
|
-
"mappings": "AAEA,SAAS,MAAM,eAAe;AAE9B,OAAO,WAAoC;AAC3C,SAAS,KAAK,YAAY;AAC1B,SAAS,SAAS;AAElB,SAAS,sCAAsC;AAC/C,SAAS,sBAAsB;AAC/B,SAAS,kBAAkB;AAC3B,SAAS,+BAA+B;AACxC,SAAmD,aAAa;AAChE,SAAS,gBAAgB,oBAAoB;AAC7C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP;AAAA,
|
|
4
|
+
"sourcesContent": ["import { TextBlock } from '@anthropic-ai/sdk/resources/index.mjs'\nimport chalk from 'chalk'\nimport { last, memoize } from 'lodash-es'\nimport { EOL } from 'os'\nimport React, { useState, useEffect } from 'react'\nimport { Box, Text } from 'ink'\nimport { z } from 'zod'\nimport { Tool, ValidationResult } from '../../Tool'\nimport { FallbackToolUseRejectedMessage } from '../../components/FallbackToolUseRejectedMessage'\nimport { getAgentPrompt } from '../../constants/prompts'\nimport { getContext } from '../../context'\nimport { hasPermissionsToUseTool } from '../../permissions'\nimport { AssistantMessage, Message as MessageType, query } from '../../query'\nimport { formatDuration, formatNumber } from '../../utils/format'\nimport {\n getMessagesPath,\n getNextAvailableLogSidechainNumber,\n overwriteLog,\n} from '../../utils/log.js'\nimport { applyMarkdown } from '../../utils/markdown'\nimport {\n createAssistantMessage,\n createUserMessage,\n getLastAssistantMessageId,\n INTERRUPT_MESSAGE,\n normalizeMessages,\n} from '../../utils/messages.js'\nimport { getModelManager } from '../../utils/model'\nimport { getMaxThinkingTokens } from '../../utils/thinking'\nimport { getTheme } from '../../utils/theme'\nimport { generateAgentId } from '../../utils/agentStorage'\nimport { debug as debugLogger } from '../../utils/debugLogger'\nimport { getTaskTools, getPrompt } from './prompt'\nimport { TOOL_NAME } from './constants'\nimport { getActiveAgents, getAgentByType, getAvailableAgentTypes } from '../../utils/agentLoader'\n\nconst inputSchema = z.object({\n description: z\n .string()\n .describe('A short (3-5 word) description of the task'),\n prompt: z.string().describe('The task for the agent to perform'),\n model_name: z\n .string()\n .optional()\n .describe(\n 'Optional: Specific model name to use for this task. If not provided, uses the default task model pointer.',\n ),\n subagent_type: z\n .string()\n .optional()\n .describe(\n 'The type of specialized agent to use for this task',\n ),\n})\n\nexport const TaskTool = {\n async prompt({ safeMode }) {\n // Match original Claude Code - prompt returns full agent descriptions\n return await getPrompt(safeMode)\n },\n name: TOOL_NAME,\n async description() {\n // Match original Claude Code exactly - simple description\n return \"Launch a new task\"\n },\n inputSchema,\n \n async *call(\n { description, prompt, model_name, subagent_type },\n {\n abortController,\n options: { safeMode = false, forkNumber, messageLogName, verbose },\n readFileTimestamps,\n },\n ): AsyncGenerator<\n | { type: 'result'; data: TextBlock[]; resultForAssistant?: string }\n | { type: 'progress'; content: any; normalizedMessages?: any[]; tools?: any[] },\n void,\n unknown\n > {\n const startTime = Date.now()\n \n // Default to general-purpose if no subagent_type specified\n const agentType = subagent_type || 'general-purpose'\n \n // Apply subagent configuration\n let effectivePrompt = prompt\n let effectiveModel = model_name || 'task'\n let toolFilter = null\n let temperature = undefined\n \n // Load agent configuration dynamically\n if (agentType) {\n const agentConfig = await getAgentByType(agentType)\n \n if (!agentConfig) {\n // If agent type not found, return helpful message instead of throwing\n const availableTypes = await getAvailableAgentTypes()\n const helpMessage = `Agent type '${agentType}' not found.\\n\\nAvailable agents:\\n${availableTypes.map(t => ` \u2022 ${t}`).join('\\n')}\\n\\nUse /agents command to manage agent configurations.`\n \n yield {\n type: 'result',\n data: [{ type: 'text', text: helpMessage }] as TextBlock[],\n resultForAssistant: helpMessage,\n }\n return\n }\n \n // Apply system prompt if configured\n if (agentConfig.systemPrompt) {\n effectivePrompt = `${agentConfig.systemPrompt}\\n\\n${prompt}`\n }\n \n // Apply model if not overridden by model_name parameter\n if (!model_name && agentConfig.model_name) {\n // Support inherit: keep pointer-based default\n if (agentConfig.model_name !== 'inherit') {\n effectiveModel = agentConfig.model_name as string\n }\n }\n \n // Store tool filter for later application\n toolFilter = agentConfig.tools\n \n // Note: temperature is not currently in our agent configs\n // but could be added in the future\n }\n \n const messages: MessageType[] = [createUserMessage(effectivePrompt)]\n let tools = await getTaskTools(safeMode)\n \n // Apply tool filtering if specified by subagent config\n if (toolFilter) {\n // Back-compat: ['*'] means all tools\n const isAllArray = Array.isArray(toolFilter) && toolFilter.length === 1 && toolFilter[0] === '*'\n if (toolFilter === '*' || isAllArray) {\n // no-op, keep all tools\n } else if (Array.isArray(toolFilter)) {\n tools = tools.filter(tool => toolFilter.includes(tool.name))\n }\n }\n\n // Model already resolved in effectiveModel variable above\n const modelToUse = effectiveModel\n\n // Display initial task information with separate progress lines\n yield {\n type: 'progress',\n content: createAssistantMessage(`Starting agent: ${agentType}`),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n \n yield {\n type: 'progress', \n content: createAssistantMessage(`Using model: ${modelToUse}`),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n \n yield {\n type: 'progress',\n content: createAssistantMessage(`Task: ${description}`),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n \n yield {\n type: 'progress',\n content: createAssistantMessage(`Prompt: ${prompt.length > 150 ? prompt.substring(0, 150) + '...' : prompt}`),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n\n const [taskPrompt, context, maxThinkingTokens] = await Promise.all([\n getAgentPrompt(),\n getContext(),\n getMaxThinkingTokens(messages),\n ])\n \n // Inject model context to prevent self-referential expert consultations\n taskPrompt.push(`\\nIMPORTANT: You are currently running as ${modelToUse}. You do not need to consult ${modelToUse} via AskExpertModel since you ARE ${modelToUse}. Complete tasks directly using your capabilities.`)\n\n let toolUseCount = 0\n\n const getSidechainNumber = memoize(() =>\n getNextAvailableLogSidechainNumber(messageLogName, forkNumber),\n )\n\n // Generate unique Task ID for this task execution\n const taskId = generateAgentId()\n\n // \uD83D\uDD27 ULTRA SIMPLIFIED: Exact original AgentTool pattern\n // Build query options, adding temperature if specified\n const queryOptions = {\n safeMode,\n forkNumber,\n messageLogName,\n tools,\n commands: [],\n verbose,\n maxThinkingTokens,\n model: modelToUse,\n }\n \n // Add temperature if specified by subagent config\n if (temperature !== undefined) {\n queryOptions['temperature'] = temperature\n }\n \n for await (const message of query(\n messages,\n taskPrompt,\n context,\n hasPermissionsToUseTool,\n {\n abortController,\n options: queryOptions,\n messageId: getLastAssistantMessageId(messages),\n agentId: taskId,\n readFileTimestamps,\n setToolJSX: () => {}, // No-op implementation for TaskTool\n },\n )) {\n messages.push(message)\n\n overwriteLog(\n getMessagesPath(messageLogName, forkNumber, getSidechainNumber()),\n messages.filter(_ => _.type !== 'progress'),\n )\n\n if (message.type !== 'assistant') {\n continue\n }\n\n const normalizedMessages = normalizeMessages(messages)\n \n // Process tool uses and text content for better visibility\n for (const content of message.message.content) {\n if (content.type === 'text' && content.text && content.text !== INTERRUPT_MESSAGE) {\n // Show agent's reasoning/responses\n const preview = content.text.length > 200 ? content.text.substring(0, 200) + '...' : content.text\n yield {\n type: 'progress',\n content: createAssistantMessage(`${preview}`),\n normalizedMessages,\n tools,\n }\n } else if (content.type === 'tool_use') {\n toolUseCount++\n \n // Show which tool is being used with agent context\n const toolMessage = normalizedMessages.find(\n _ =>\n _.type === 'assistant' &&\n _.message.content[0]?.type === 'tool_use' &&\n _.message.content[0].id === content.id,\n ) as AssistantMessage\n \n if (toolMessage) {\n // Clone and modify the message to show agent context\n const modifiedMessage = {\n ...toolMessage,\n message: {\n ...toolMessage.message,\n content: toolMessage.message.content.map(c => {\n if (c.type === 'tool_use' && c.id === content.id) {\n // Add agent context to tool name display\n return {\n ...c,\n name: c.name // Keep original name, UI will handle display\n }\n }\n return c\n })\n }\n }\n \n yield {\n type: 'progress',\n content: modifiedMessage,\n normalizedMessages,\n tools,\n }\n }\n }\n }\n }\n\n const normalizedMessages = normalizeMessages(messages)\n const lastMessage = last(messages)\n if (lastMessage?.type !== 'assistant') {\n throw new Error('Last message was not an assistant message')\n }\n\n // \uD83D\uDD27 CRITICAL FIX: Match original AgentTool interrupt handling pattern exactly\n if (\n lastMessage.message.content.some(\n _ => _.type === 'text' && _.text === INTERRUPT_MESSAGE,\n )\n ) {\n // Skip progress yield - only yield final result\n } else {\n const result = [\n toolUseCount === 1 ? '1 tool use' : `${toolUseCount} tool uses`,\n formatNumber(\n (lastMessage.message.usage.cache_creation_input_tokens ?? 0) +\n (lastMessage.message.usage.cache_read_input_tokens ?? 0) +\n lastMessage.message.usage.input_tokens +\n lastMessage.message.usage.output_tokens,\n ) + ' tokens',\n formatDuration(Date.now() - startTime),\n ]\n yield {\n type: 'progress',\n content: createAssistantMessage(`Task completed (${result.join(' \u00B7 ')})`),\n normalizedMessages,\n tools,\n }\n }\n\n // Output is an AssistantMessage, but since TaskTool is a tool, it needs\n // to serialize its response to UserMessage-compatible content.\n const data = lastMessage.message.content.filter(_ => _.type === 'text')\n yield {\n type: 'result',\n data,\n resultForAssistant: this.renderResultForAssistant(data),\n }\n },\n\n isReadOnly() {\n return true // for now...\n },\n isConcurrencySafe() {\n return true // Task tool supports concurrent execution in official implementation\n },\n async validateInput(input, context) {\n if (!input.description || typeof input.description !== 'string') {\n return {\n result: false,\n message: 'Description is required and must be a string',\n }\n }\n if (!input.prompt || typeof input.prompt !== 'string') {\n return {\n result: false,\n message: 'Prompt is required and must be a string',\n }\n }\n\n // Model validation - similar to Edit tool error handling\n if (input.model_name) {\n const modelManager = getModelManager()\n const availableModels = modelManager.getAllAvailableModelNames()\n\n if (!availableModels.includes(input.model_name)) {\n return {\n result: false,\n message: `Model '${input.model_name}' does not exist. Available models: ${availableModels.join(', ')}`,\n meta: {\n model_name: input.model_name,\n availableModels,\n },\n }\n }\n }\n\n // Validate subagent_type if provided\n if (input.subagent_type) {\n const availableTypes = await getAvailableAgentTypes()\n if (!availableTypes.includes(input.subagent_type)) {\n return {\n result: false,\n message: `Agent type '${input.subagent_type}' does not exist. Available types: ${availableTypes.join(', ')}`,\n meta: {\n subagent_type: input.subagent_type,\n availableTypes,\n },\n }\n }\n }\n\n return { result: true }\n },\n async isEnabled() {\n return true\n },\n userFacingName(input?: any) {\n // Return agent name with proper prefix\n const agentType = input?.subagent_type || 'general-purpose'\n return `agent-${agentType}`\n },\n needsPermissions() {\n return false\n },\n renderResultForAssistant(data: TextBlock[]) {\n return data.map(block => block.type === 'text' ? block.text : '').join('\\n')\n },\n renderToolUseMessage({ description, prompt, model_name, subagent_type }, { verbose }) {\n if (!description || !prompt) return null\n\n const modelManager = getModelManager()\n const defaultTaskModel = modelManager.getModelName('task')\n const actualModel = model_name || defaultTaskModel\n const agentType = subagent_type || 'general-purpose'\n const promptPreview =\n prompt.length > 80 ? prompt.substring(0, 80) + '...' : prompt\n\n const theme = getTheme()\n \n if (verbose) {\n return (\n <Box flexDirection=\"column\">\n <Text>\n [{agentType}] {actualModel}: {description}\n </Text>\n <Box\n paddingLeft={2}\n borderLeftStyle=\"single\"\n borderLeftColor={theme.secondaryBorder}\n >\n <Text color={theme.secondaryText}>{promptPreview}</Text>\n </Box>\n </Box>\n )\n }\n\n // Simple display: agent type, model and description\n return `[${agentType}] ${actualModel}: ${description}`\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage(content) {\n const theme = getTheme()\n\n if (Array.isArray(content)) {\n const textBlocks = content.filter(block => block.type === 'text')\n const totalLength = textBlocks.reduce(\n (sum, block) => sum + block.text.length,\n 0,\n )\n // \uD83D\uDD27 CRITICAL FIX: Use exact match for interrupt detection, not .includes()\n const isInterrupted = content.some(\n block =>\n block.type === 'text' && block.text === INTERRUPT_MESSAGE,\n )\n\n if (isInterrupted) {\n // \uD83D\uDD27 CRITICAL FIX: Match original system interrupt rendering exactly\n return (\n <Box flexDirection=\"row\">\n <Text> \u23BF </Text>\n <Text color={theme.error}>Interrupted by user</Text>\n </Box>\n )\n }\n\n return (\n <Box flexDirection=\"column\">\n <Box justifyContent=\"space-between\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text> \u23BF </Text>\n <Text>Task completed</Text>\n {textBlocks.length > 0 && (\n <Text color={theme.secondaryText}>\n {' '}\n ({totalLength} characters)\n </Text>\n )}\n </Box>\n </Box>\n </Box>\n )\n }\n\n return (\n <Box flexDirection=\"row\">\n <Text> \u23BF </Text>\n <Text color={theme.secondaryText}>Task completed</Text>\n </Box>\n )\n },\n} satisfies Tool<typeof inputSchema, TextBlock[]>\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["normalizedMessages"]
|
|
7
7
|
}
|
|
@@ -31,11 +31,6 @@ async function assertMinVersion() {
|
|
|
31
31
|
if (versionConfig.minVersion && lt(MACRO.VERSION, versionConfig.minVersion)) {
|
|
32
32
|
const suggestions = await getUpdateCommandSuggestions();
|
|
33
33
|
const cmdLines = suggestions.map((c) => ` ${c}`).join("\n");
|
|
34
|
-
console.error(`
|
|
35
|
-
\u60A8\u7684 ${PRODUCT_NAME} \u7248\u672C (${MACRO.VERSION}) \u8FC7\u4F4E\uFF0C\u9700\u8981\u5347\u7EA7\u5230 ${versionConfig.minVersion} \u6216\u66F4\u9AD8\u7248\u672C\u3002
|
|
36
|
-
\u8BF7\u624B\u52A8\u6267\u884C\u4EE5\u4E0B\u4EFB\u4E00\u547D\u4EE4\u8FDB\u884C\u5347\u7EA7\uFF1A
|
|
37
|
-
${cmdLines}
|
|
38
|
-
`);
|
|
39
34
|
process.exit(1);
|
|
40
35
|
}
|
|
41
36
|
} catch (error) {
|
|
@@ -337,8 +332,11 @@ async function checkAndNotifyUpdate() {
|
|
|
337
332
|
lastSuggestedVersion: latest
|
|
338
333
|
});
|
|
339
334
|
const suggestions = await getUpdateCommandSuggestions();
|
|
340
|
-
|
|
341
|
-
console.log(
|
|
335
|
+
console.log(`New version available: ${latest} (current: ${MACRO.VERSION})`);
|
|
336
|
+
console.log("Run the following command to update:");
|
|
337
|
+
for (const command of suggestions) {
|
|
338
|
+
console.log(` ${command}`);
|
|
339
|
+
}
|
|
342
340
|
} else {
|
|
343
341
|
saveGlobalConfig({ ...config, lastUpdateCheckAt: now });
|
|
344
342
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/autoUpdater.ts"],
|
|
4
|
-
"sourcesContent": ["import { homedir } from 'os'\nimport { join } from 'path'\nimport {\n existsSync,\n mkdirSync,\n appendFileSync,\n readFileSync,\n constants,\n writeFileSync,\n unlinkSync,\n statSync,\n} from 'fs'\nimport { platform } from 'process'\nimport { execFileNoThrow } from './execFileNoThrow'\nimport { spawn } from 'child_process'\nimport { logError } from './log'\nimport { accessSync } from 'fs'\nimport { CLAUDE_BASE_DIR } from './env'\nimport { logEvent, getDynamicConfig } from '../services/statsig'\nimport { lt, gt } from 'semver'\nimport { MACRO } from '../constants/macros'\nimport { PRODUCT_COMMAND, PRODUCT_NAME } from '../constants/product'\nimport { getGlobalConfig, saveGlobalConfig, isAutoUpdaterDisabled } from './config'\nimport { env } from './env'\nexport type InstallStatus =\n | 'success'\n | 'no_permissions'\n | 'install_failed'\n | 'in_progress'\n\nexport type AutoUpdaterResult = {\n version: string | null\n status: InstallStatus\n}\n\nexport type VersionConfig = {\n minVersion: string\n}\n\n/**\n * Checks if the current version meets the minimum required version from Statsig config\n * Terminates the process with an error message if the version is too old\n */\nexport async function assertMinVersion(): Promise<void> {\n try {\n const versionConfig = await getDynamicConfig<VersionConfig>(\n 'tengu_version_config',\n { minVersion: '0.0.0' },\n )\n\n if (\n versionConfig.minVersion &&\n lt(MACRO.VERSION, versionConfig.minVersion)\n ) {\n const suggestions = await getUpdateCommandSuggestions()\n const cmdLines = suggestions.map(c => ` ${c}`).join('\\n')\n console.error(`\n\u60A8\u7684 ${PRODUCT_NAME} \u7248\u672C (${MACRO.VERSION}) \u8FC7\u4F4E\uFF0C\u9700\u8981\u5347\u7EA7\u5230 ${versionConfig.minVersion} \u6216\u66F4\u9AD8\u7248\u672C\u3002\n\u8BF7\u624B\u52A8\u6267\u884C\u4EE5\u4E0B\u4EFB\u4E00\u547D\u4EE4\u8FDB\u884C\u5347\u7EA7\uFF1A\n${cmdLines}\n`)\n process.exit(1)\n }\n } catch (error) {\n logError(`Error checking minimum version: ${error}`)\n }\n}\n\n// Lock file for auto-updater to prevent concurrent updates\nexport const LOCK_FILE_PATH = join(CLAUDE_BASE_DIR, '.update.lock')\nconst LOCK_TIMEOUT_MS = 5 * 60 * 1000 // 5 minute timeout for locks\n\n/**\n * Attempts to acquire a lock for auto-updater\n * @returns {boolean} true if lock was acquired, false if another process holds the lock\n */\nfunction acquireLock(): boolean {\n try {\n // Ensure the base directory exists\n if (!existsSync(CLAUDE_BASE_DIR)) {\n mkdirSync(CLAUDE_BASE_DIR, { recursive: true })\n }\n\n // Check if lock file exists and is not stale\n if (existsSync(LOCK_FILE_PATH)) {\n const stats = statSync(LOCK_FILE_PATH)\n const age = Date.now() - stats.mtimeMs\n\n // If lock file is older than timeout, consider it stale\n if (age < LOCK_TIMEOUT_MS) {\n return false\n }\n\n // Lock is stale, we can take over\n try {\n unlinkSync(LOCK_FILE_PATH)\n } catch (err) {\n logError(`Failed to remove stale lock file: ${err}`)\n return false\n }\n }\n\n // Create lock file with current pid\n writeFileSync(LOCK_FILE_PATH, `${process.pid}`, 'utf8')\n return true\n } catch (err) {\n logError(`Failed to acquire lock: ${err}`)\n return false\n }\n}\n\n/**\n * Releases the update lock if it's held by this process\n */\nfunction releaseLock(): void {\n try {\n if (existsSync(LOCK_FILE_PATH)) {\n const lockData = readFileSync(LOCK_FILE_PATH, 'utf8')\n if (lockData === `${process.pid}`) {\n unlinkSync(LOCK_FILE_PATH)\n }\n }\n } catch (err) {\n logError(`Failed to release lock: ${err}`)\n }\n}\n\nexport async function checkNpmPermissions(): Promise<{\n hasPermissions: boolean\n npmPrefix: string | null\n}> {\n try {\n const prefixResult = await execFileNoThrow('npm', [\n '-g',\n 'config',\n 'get',\n 'prefix',\n ])\n if (prefixResult.code !== 0) {\n logError('Failed to check npm permissions')\n return { hasPermissions: false, npmPrefix: null }\n }\n\n const prefix = prefixResult.stdout.trim()\n\n let testWriteResult = false\n try {\n accessSync(prefix, constants.W_OK)\n testWriteResult = true\n } catch {\n testWriteResult = false\n }\n\n if (testWriteResult) {\n return { hasPermissions: true, npmPrefix: prefix }\n }\n\n logError('Insufficient permissions for global npm install.')\n return { hasPermissions: false, npmPrefix: prefix }\n } catch (error) {\n logError(`Failed to verify npm global install permissions: ${error}`)\n return { hasPermissions: false, npmPrefix: null }\n }\n}\n\nexport async function setupNewPrefix(prefix: string): Promise<void> {\n if (!acquireLock()) {\n // Log the lock contention to statsig\n logEvent('tengu_auto_updater_prefix_lock_contention', {\n pid: String(process.pid),\n currentVersion: MACRO.VERSION,\n prefix,\n })\n throw new Error('Another process is currently setting up npm prefix')\n }\n\n try {\n // Create directory if it doesn't exist\n if (!existsSync(prefix)) {\n mkdirSync(prefix, { recursive: true })\n }\n\n // Set npm prefix\n const setPrefix = await execFileNoThrow('npm', [\n '-g',\n 'config',\n 'set',\n 'prefix',\n prefix,\n ])\n\n if (setPrefix.code !== 0) {\n throw new Error(`Failed to set npm prefix: ${setPrefix.stderr}`)\n }\n\n // Update shell config files\n const pathUpdate = `\\n# npm global path\\nexport PATH=\"${prefix}/bin:$PATH\"\\n`\n\n if (platform === 'win32') {\n // On Windows, update user PATH environment variable\n const setxResult = await execFileNoThrow('setx', [\n 'PATH',\n `${process.env.PATH};${prefix}`,\n ])\n if (setxResult.code !== 0) {\n throw new Error(\n `Failed to update PATH on Windows: ${setxResult.stderr}`,\n )\n }\n } else {\n // Unix-like systems\n const shellConfigs = [\n // Bash\n join(homedir(), '.bashrc'),\n join(homedir(), '.bash_profile'),\n // Zsh\n join(homedir(), '.zshrc'),\n // Fish\n join(homedir(), '.config', 'fish', 'config.fish'),\n ]\n\n for (const config of shellConfigs) {\n if (existsSync(config)) {\n try {\n const content = readFileSync(config, 'utf8')\n if (!content.includes(prefix)) {\n if (config.includes('fish')) {\n // Fish shell has different syntax\n const fishPath = `\\n# npm global path\\nset -gx PATH ${prefix}/bin $PATH\\n`\n appendFileSync(config, fishPath)\n } else {\n appendFileSync(config, pathUpdate)\n }\n\n logEvent('npm_prefix_path_updated', {\n configPath: config,\n })\n }\n } catch (err) {\n // Log but don't throw - continue with other configs\n logEvent('npm_prefix_path_update_failed', {\n configPath: config,\n error:\n err instanceof Error\n ? err.message.slice(0, 200)\n : String(err).slice(0, 200),\n })\n logError(`Failed to update shell config ${config}: ${err}`)\n }\n }\n }\n }\n } finally {\n releaseLock()\n }\n}\n\nexport function getDefaultNpmPrefix(): string {\n return join(homedir(), '.npm-global')\n}\n\nexport function getPermissionsCommand(npmPrefix: string): string {\n const windowsCommand = `icacls \"${npmPrefix}\" /grant \"%USERNAME%:(OI)(CI)F\"`\n const prefixPath = npmPrefix || '$(npm -g config get prefix)'\n const unixCommand = `sudo chown -R $USER:$(id -gn) ${prefixPath} && sudo chmod -R u+w ${prefixPath}`\n\n return platform === 'win32' ? windowsCommand : unixCommand\n}\n\nexport async function getLatestVersion(): Promise<string | null> {\n // 1) Try npm CLI (fast when available)\n try {\n const abortController = new AbortController()\n setTimeout(() => abortController.abort(), 5000)\n const result = await execFileNoThrow(\n 'npm',\n ['view', MACRO.PACKAGE_URL, 'version'],\n abortController.signal,\n )\n if (result.code === 0) {\n const v = result.stdout.trim()\n if (v) return v\n }\n } catch {}\n\n // 2) Fallback: fetch npm registry (works in Bun/Node without npm)\n try {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), 5000)\n const res = await fetch(\n `https://registry.npmjs.org/${encodeURIComponent(MACRO.PACKAGE_URL)}`,\n {\n method: 'GET',\n headers: {\n Accept: 'application/vnd.npm.install-v1+json',\n 'User-Agent': `${PRODUCT_NAME}/${MACRO.VERSION}`,\n },\n signal: controller.signal,\n },\n )\n clearTimeout(timer)\n if (!res.ok) return null\n const json: any = await res.json().catch(() => null)\n const latest = json && json['dist-tags'] && json['dist-tags'].latest\n return typeof latest === 'string' ? latest : null\n } catch {\n return null\n }\n}\n\nexport async function installGlobalPackage(): Promise<InstallStatus> {\n // Detect preferred package manager and install accordingly\n if (!acquireLock()) {\n logError('Another process is currently installing an update')\n // Log the lock contention to statsig\n logEvent('tengu_auto_updater_lock_contention', {\n pid: String(process.pid),\n currentVersion: MACRO.VERSION,\n })\n return 'in_progress'\n }\n\n try {\n const manager = await detectPackageManager()\n if (manager === 'npm') {\n const { hasPermissions } = await checkNpmPermissions()\n if (!hasPermissions) {\n return 'no_permissions'\n }\n // Stream\u5B9E\u65F6\u8F93\u51FA\uFF0C\u51CF\u5C11\u7528\u6237\u7B49\u5F85\u611F\n const code = await runStreaming('npm', ['install', '-g', MACRO.PACKAGE_URL])\n if (code !== 0) {\n logError(`Failed to install new version via npm (exit ${code})`)\n return 'install_failed'\n }\n return 'success'\n }\n\n if (manager === 'bun') {\n const code = await runStreaming('bun', ['add', '-g', `${MACRO.PACKAGE_URL}@latest`])\n if (code !== 0) {\n logError(`Failed to install new version via bun (exit ${code})`)\n return 'install_failed'\n }\n return 'success'\n }\n\n // Fallback to npm if unknown\n const { hasPermissions } = await checkNpmPermissions()\n if (!hasPermissions) return 'no_permissions'\n const code = await runStreaming('npm', ['install', '-g', MACRO.PACKAGE_URL])\n if (code !== 0) return 'install_failed'\n return 'success'\n } finally {\n // Ensure we always release the lock\n releaseLock()\n }\n}\n\nexport type PackageManager = 'npm' | 'bun'\n\nexport async function detectPackageManager(): Promise<PackageManager> {\n // Respect explicit override if provided later via config/env (future-proof)\n try {\n // Heuristic 1: npm available and global root resolvable\n const npmRoot = await execFileNoThrow('npm', ['-g', 'root'])\n if (npmRoot.code === 0 && npmRoot.stdout.trim()) {\n return 'npm'\n }\n } catch {}\n\n try {\n // Heuristic 2: running on a system with bun and installed path hints bun\n const bunVer = await execFileNoThrow('bun', ['--version'])\n if (bunVer.code === 0) {\n // BUN_INSTALL defaults to ~/.bun; if our package lives under that tree, prefer bun\n // If npm not detected but bun is available, choose bun\n return 'bun'\n }\n } catch {}\n\n // Default to npm when uncertain\n return 'npm'\n}\n\nfunction runStreaming(cmd: string, args: string[]): Promise<number> {\n return new Promise(resolve => {\n // \u6253\u5370\u6B63\u5728\u4F7F\u7528\u7684\u5305\u7BA1\u7406\u5668\u4E0E\u547D\u4EE4\uFF0C\u589E\u5F3A\u900F\u660E\u5EA6\n try {\n // eslint-disable-next-line no-console\n console.log(`> ${cmd} ${args.join(' ')}`)\n } catch {}\n\n const child = spawn(cmd, args, {\n stdio: 'inherit',\n env: process.env,\n })\n child.on('close', code => resolve(code ?? 0))\n child.on('error', () => resolve(1))\n })\n}\n\n/**\n * Generate human-friendly update commands for the detected package manager.\n * Also includes an alternative manager command as fallback for users.\n */\nexport async function getUpdateCommandSuggestions(): Promise<string[]> {\n // Prefer Bun first, then npm (consistent, simple UX). Include @latest.\n return [\n `bun add -g ${MACRO.PACKAGE_URL}@latest`,\n `npm install -g ${MACRO.PACKAGE_URL}@latest`,\n ]\n}\n\n/**\n * Non-blocking update notifier (daily)\n * - Respects CI and disabled auto-updater\n * - Uses env.hasInternetAccess() to quickly skip offline cases\n * - Stores last check timestamp + last suggested version in global config\n */\nexport async function checkAndNotifyUpdate(): Promise<void> {\n try {\n if (process.env.NODE_ENV === 'test') return\n if (await isAutoUpdaterDisabled()) return\n if (await env.getIsDocker()) return\n if (!(await env.hasInternetAccess())) return\n\n const config: any = getGlobalConfig()\n const now = Date.now()\n const DAY_MS = 24 * 60 * 60 * 1000\n const lastCheck = Number(config.lastUpdateCheckAt || 0)\n if (lastCheck && now - lastCheck < DAY_MS) return\n\n const latest = await getLatestVersion()\n if (!latest) {\n // Still record the check to avoid spamming\n saveGlobalConfig({ ...config, lastUpdateCheckAt: now })\n return\n }\n\n if (gt(latest, MACRO.VERSION)) {\n // Update stored state and print a low-noise hint\n saveGlobalConfig({\n ...config,\n lastUpdateCheckAt: now,\n lastSuggestedVersion: latest,\n })\n const suggestions = await getUpdateCommandSuggestions()\n const first = suggestions[0]\n console.log(`New version available: ${latest}. Recommended: ${first}`)\n } else {\n saveGlobalConfig({ ...config, lastUpdateCheckAt: now })\n }\n } catch (error) {\n // Never block or throw; just log and move on\n logError(`update-notify: ${error}`)\n }\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,eAAe;AACxB,SAAS,YAAY;AACrB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,gBAAgB;AACzB,SAAS,uBAAuB;AAChC,SAAS,aAAa;AACtB,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAC3B,SAAS,uBAAuB;AAChC,SAAS,UAAU,wBAAwB;AAC3C,SAAS,IAAI,UAAU;AACvB,SAAS,aAAa;AACtB,SAA0B,oBAAoB;AAC9C,SAAS,iBAAiB,kBAAkB,6BAA6B;AACzE,SAAS,WAAW;AAoBpB,eAAsB,mBAAkC;AACtD,MAAI;AACF,UAAM,gBAAgB,MAAM;AAAA,MAC1B;AAAA,MACA,EAAE,YAAY,QAAQ;AAAA,IACxB;AAEA,QACE,cAAc,cACd,GAAG,MAAM,SAAS,cAAc,UAAU,GAC1C;AACA,YAAM,cAAc,MAAM,4BAA4B;AACtD,YAAM,WAAW,YAAY,IAAI,OAAK,OAAO,CAAC,EAAE,EAAE,KAAK,IAAI;AAC3D,cAAQ,
|
|
4
|
+
"sourcesContent": ["import { homedir } from 'os'\nimport { join } from 'path'\nimport {\n existsSync,\n mkdirSync,\n appendFileSync,\n readFileSync,\n constants,\n writeFileSync,\n unlinkSync,\n statSync,\n} from 'fs'\nimport { platform } from 'process'\nimport { execFileNoThrow } from './execFileNoThrow'\nimport { spawn } from 'child_process'\nimport { logError } from './log'\nimport { accessSync } from 'fs'\nimport { CLAUDE_BASE_DIR } from './env'\nimport { logEvent, getDynamicConfig } from '../services/statsig'\nimport { lt, gt } from 'semver'\nimport { MACRO } from '../constants/macros'\nimport { PRODUCT_COMMAND, PRODUCT_NAME } from '../constants/product'\nimport { getGlobalConfig, saveGlobalConfig, isAutoUpdaterDisabled } from './config'\nimport { env } from './env'\nexport type InstallStatus =\n | 'success'\n | 'no_permissions'\n | 'install_failed'\n | 'in_progress'\n\nexport type AutoUpdaterResult = {\n version: string | null\n status: InstallStatus\n}\n\nexport type VersionConfig = {\n minVersion: string\n}\n\n/**\n * Checks if the current version meets the minimum required version from Statsig config\n * Terminates the process with an error message if the version is too old\n */\nexport async function assertMinVersion(): Promise<void> {\n try {\n const versionConfig = await getDynamicConfig<VersionConfig>(\n 'tengu_version_config',\n { minVersion: '0.0.0' },\n )\n\n if (\n versionConfig.minVersion &&\n lt(MACRO.VERSION, versionConfig.minVersion)\n ) {\n const suggestions = await getUpdateCommandSuggestions()\n const cmdLines = suggestions.map(c => ` ${c}`).join('\\n')\n process.exit(1)\n }\n } catch (error) {\n logError(`Error checking minimum version: ${error}`)\n }\n}\n\n// Lock file for auto-updater to prevent concurrent updates\nexport const LOCK_FILE_PATH = join(CLAUDE_BASE_DIR, '.update.lock')\nconst LOCK_TIMEOUT_MS = 5 * 60 * 1000 // 5 minute timeout for locks\n\n/**\n * Attempts to acquire a lock for auto-updater\n * @returns {boolean} true if lock was acquired, false if another process holds the lock\n */\nfunction acquireLock(): boolean {\n try {\n // Ensure the base directory exists\n if (!existsSync(CLAUDE_BASE_DIR)) {\n mkdirSync(CLAUDE_BASE_DIR, { recursive: true })\n }\n\n // Check if lock file exists and is not stale\n if (existsSync(LOCK_FILE_PATH)) {\n const stats = statSync(LOCK_FILE_PATH)\n const age = Date.now() - stats.mtimeMs\n\n // If lock file is older than timeout, consider it stale\n if (age < LOCK_TIMEOUT_MS) {\n return false\n }\n\n // Lock is stale, we can take over\n try {\n unlinkSync(LOCK_FILE_PATH)\n } catch (err) {\n logError(`Failed to remove stale lock file: ${err}`)\n return false\n }\n }\n\n // Create lock file with current pid\n writeFileSync(LOCK_FILE_PATH, `${process.pid}`, 'utf8')\n return true\n } catch (err) {\n logError(`Failed to acquire lock: ${err}`)\n return false\n }\n}\n\n/**\n * Releases the update lock if it's held by this process\n */\nfunction releaseLock(): void {\n try {\n if (existsSync(LOCK_FILE_PATH)) {\n const lockData = readFileSync(LOCK_FILE_PATH, 'utf8')\n if (lockData === `${process.pid}`) {\n unlinkSync(LOCK_FILE_PATH)\n }\n }\n } catch (err) {\n logError(`Failed to release lock: ${err}`)\n }\n}\n\nexport async function checkNpmPermissions(): Promise<{\n hasPermissions: boolean\n npmPrefix: string | null\n}> {\n try {\n const prefixResult = await execFileNoThrow('npm', [\n '-g',\n 'config',\n 'get',\n 'prefix',\n ])\n if (prefixResult.code !== 0) {\n logError('Failed to check npm permissions')\n return { hasPermissions: false, npmPrefix: null }\n }\n\n const prefix = prefixResult.stdout.trim()\n\n let testWriteResult = false\n try {\n accessSync(prefix, constants.W_OK)\n testWriteResult = true\n } catch {\n testWriteResult = false\n }\n\n if (testWriteResult) {\n return { hasPermissions: true, npmPrefix: prefix }\n }\n\n logError('Insufficient permissions for global npm install.')\n return { hasPermissions: false, npmPrefix: prefix }\n } catch (error) {\n logError(`Failed to verify npm global install permissions: ${error}`)\n return { hasPermissions: false, npmPrefix: null }\n }\n}\n\nexport async function setupNewPrefix(prefix: string): Promise<void> {\n if (!acquireLock()) {\n // Log the lock contention to statsig\n logEvent('tengu_auto_updater_prefix_lock_contention', {\n pid: String(process.pid),\n currentVersion: MACRO.VERSION,\n prefix,\n })\n throw new Error('Another process is currently setting up npm prefix')\n }\n\n try {\n // Create directory if it doesn't exist\n if (!existsSync(prefix)) {\n mkdirSync(prefix, { recursive: true })\n }\n\n // Set npm prefix\n const setPrefix = await execFileNoThrow('npm', [\n '-g',\n 'config',\n 'set',\n 'prefix',\n prefix,\n ])\n\n if (setPrefix.code !== 0) {\n throw new Error(`Failed to set npm prefix: ${setPrefix.stderr}`)\n }\n\n // Update shell config files\n const pathUpdate = `\\n# npm global path\\nexport PATH=\"${prefix}/bin:$PATH\"\\n`\n\n if (platform === 'win32') {\n // On Windows, update user PATH environment variable\n const setxResult = await execFileNoThrow('setx', [\n 'PATH',\n `${process.env.PATH};${prefix}`,\n ])\n if (setxResult.code !== 0) {\n throw new Error(\n `Failed to update PATH on Windows: ${setxResult.stderr}`,\n )\n }\n } else {\n // Unix-like systems\n const shellConfigs = [\n // Bash\n join(homedir(), '.bashrc'),\n join(homedir(), '.bash_profile'),\n // Zsh\n join(homedir(), '.zshrc'),\n // Fish\n join(homedir(), '.config', 'fish', 'config.fish'),\n ]\n\n for (const config of shellConfigs) {\n if (existsSync(config)) {\n try {\n const content = readFileSync(config, 'utf8')\n if (!content.includes(prefix)) {\n if (config.includes('fish')) {\n // Fish shell has different syntax\n const fishPath = `\\n# npm global path\\nset -gx PATH ${prefix}/bin $PATH\\n`\n appendFileSync(config, fishPath)\n } else {\n appendFileSync(config, pathUpdate)\n }\n\n logEvent('npm_prefix_path_updated', {\n configPath: config,\n })\n }\n } catch (err) {\n // Log but don't throw - continue with other configs\n logEvent('npm_prefix_path_update_failed', {\n configPath: config,\n error:\n err instanceof Error\n ? err.message.slice(0, 200)\n : String(err).slice(0, 200),\n })\n logError(`Failed to update shell config ${config}: ${err}`)\n }\n }\n }\n }\n } finally {\n releaseLock()\n }\n}\n\nexport function getDefaultNpmPrefix(): string {\n return join(homedir(), '.npm-global')\n}\n\nexport function getPermissionsCommand(npmPrefix: string): string {\n const windowsCommand = `icacls \"${npmPrefix}\" /grant \"%USERNAME%:(OI)(CI)F\"`\n const prefixPath = npmPrefix || '$(npm -g config get prefix)'\n const unixCommand = `sudo chown -R $USER:$(id -gn) ${prefixPath} && sudo chmod -R u+w ${prefixPath}`\n\n return platform === 'win32' ? windowsCommand : unixCommand\n}\n\nexport async function getLatestVersion(): Promise<string | null> {\n // 1) Try npm CLI (fast when available)\n try {\n const abortController = new AbortController()\n setTimeout(() => abortController.abort(), 5000)\n const result = await execFileNoThrow(\n 'npm',\n ['view', MACRO.PACKAGE_URL, 'version'],\n abortController.signal,\n )\n if (result.code === 0) {\n const v = result.stdout.trim()\n if (v) return v\n }\n } catch {}\n\n // 2) Fallback: fetch npm registry (works in Bun/Node without npm)\n try {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), 5000)\n const res = await fetch(\n `https://registry.npmjs.org/${encodeURIComponent(MACRO.PACKAGE_URL)}`,\n {\n method: 'GET',\n headers: {\n Accept: 'application/vnd.npm.install-v1+json',\n 'User-Agent': `${PRODUCT_NAME}/${MACRO.VERSION}`,\n },\n signal: controller.signal,\n },\n )\n clearTimeout(timer)\n if (!res.ok) return null\n const json: any = await res.json().catch(() => null)\n const latest = json && json['dist-tags'] && json['dist-tags'].latest\n return typeof latest === 'string' ? latest : null\n } catch {\n return null\n }\n}\n\nexport async function installGlobalPackage(): Promise<InstallStatus> {\n // Detect preferred package manager and install accordingly\n if (!acquireLock()) {\n logError('Another process is currently installing an update')\n // Log the lock contention to statsig\n logEvent('tengu_auto_updater_lock_contention', {\n pid: String(process.pid),\n currentVersion: MACRO.VERSION,\n })\n return 'in_progress'\n }\n\n try {\n const manager = await detectPackageManager()\n if (manager === 'npm') {\n const { hasPermissions } = await checkNpmPermissions()\n if (!hasPermissions) {\n return 'no_permissions'\n }\n // Stream\u5B9E\u65F6\u8F93\u51FA\uFF0C\u51CF\u5C11\u7528\u6237\u7B49\u5F85\u611F\n const code = await runStreaming('npm', ['install', '-g', MACRO.PACKAGE_URL])\n if (code !== 0) {\n logError(`Failed to install new version via npm (exit ${code})`)\n return 'install_failed'\n }\n return 'success'\n }\n\n if (manager === 'bun') {\n const code = await runStreaming('bun', ['add', '-g', `${MACRO.PACKAGE_URL}@latest`])\n if (code !== 0) {\n logError(`Failed to install new version via bun (exit ${code})`)\n return 'install_failed'\n }\n return 'success'\n }\n\n // Fallback to npm if unknown\n const { hasPermissions } = await checkNpmPermissions()\n if (!hasPermissions) return 'no_permissions'\n const code = await runStreaming('npm', ['install', '-g', MACRO.PACKAGE_URL])\n if (code !== 0) return 'install_failed'\n return 'success'\n } finally {\n // Ensure we always release the lock\n releaseLock()\n }\n}\n\nexport type PackageManager = 'npm' | 'bun'\n\nexport async function detectPackageManager(): Promise<PackageManager> {\n // Respect explicit override if provided later via config/env (future-proof)\n try {\n // Heuristic 1: npm available and global root resolvable\n const npmRoot = await execFileNoThrow('npm', ['-g', 'root'])\n if (npmRoot.code === 0 && npmRoot.stdout.trim()) {\n return 'npm'\n }\n } catch {}\n\n try {\n // Heuristic 2: running on a system with bun and installed path hints bun\n const bunVer = await execFileNoThrow('bun', ['--version'])\n if (bunVer.code === 0) {\n // BUN_INSTALL defaults to ~/.bun; if our package lives under that tree, prefer bun\n // If npm not detected but bun is available, choose bun\n return 'bun'\n }\n } catch {}\n\n // Default to npm when uncertain\n return 'npm'\n}\n\nfunction runStreaming(cmd: string, args: string[]): Promise<number> {\n return new Promise(resolve => {\n // \u6253\u5370\u6B63\u5728\u4F7F\u7528\u7684\u5305\u7BA1\u7406\u5668\u4E0E\u547D\u4EE4\uFF0C\u589E\u5F3A\u900F\u660E\u5EA6\n try {\n // eslint-disable-next-line no-console\n console.log(`> ${cmd} ${args.join(' ')}`)\n } catch {}\n\n const child = spawn(cmd, args, {\n stdio: 'inherit',\n env: process.env,\n })\n child.on('close', code => resolve(code ?? 0))\n child.on('error', () => resolve(1))\n })\n}\n\n/**\n * Generate human-friendly update commands for the detected package manager.\n * Also includes an alternative manager command as fallback for users.\n */\nexport async function getUpdateCommandSuggestions(): Promise<string[]> {\n // Prefer Bun first, then npm (consistent, simple UX). Include @latest.\n return [\n `bun add -g ${MACRO.PACKAGE_URL}@latest`,\n `npm install -g ${MACRO.PACKAGE_URL}@latest`,\n ]\n}\n\n/**\n * Non-blocking update notifier (daily)\n * - Respects CI and disabled auto-updater\n * - Uses env.hasInternetAccess() to quickly skip offline cases\n * - Stores last check timestamp + last suggested version in global config\n */\nexport async function checkAndNotifyUpdate(): Promise<void> {\n try {\n if (process.env.NODE_ENV === 'test') return\n if (await isAutoUpdaterDisabled()) return\n if (await env.getIsDocker()) return\n if (!(await env.hasInternetAccess())) return\n\n const config: any = getGlobalConfig()\n const now = Date.now()\n const DAY_MS = 24 * 60 * 60 * 1000\n const lastCheck = Number(config.lastUpdateCheckAt || 0)\n if (lastCheck && now - lastCheck < DAY_MS) return\n\n const latest = await getLatestVersion()\n if (!latest) {\n // Still record the check to avoid spamming\n saveGlobalConfig({ ...config, lastUpdateCheckAt: now })\n return\n }\n\n if (gt(latest, MACRO.VERSION)) {\n // Update stored state and print a low-noise hint\n saveGlobalConfig({\n ...config,\n lastUpdateCheckAt: now,\n lastSuggestedVersion: latest,\n })\n const suggestions = await getUpdateCommandSuggestions()\n console.log(`New version available: ${latest} (current: ${MACRO.VERSION})`)\n console.log('Run the following command to update:')\n for (const command of suggestions) {\n console.log(` ${command}`)\n }\n } else {\n saveGlobalConfig({ ...config, lastUpdateCheckAt: now })\n }\n } catch (error) {\n // Never block or throw; just log and move on\n logError(`update-notify: ${error}`)\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["hasPermissions", "code"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/generators.ts"],
|
|
4
|
-
"sourcesContent": ["const NO_VALUE = Symbol('NO_VALUE')\n\nexport async function lastX<A>(as: AsyncGenerator<A>): Promise<A> {\n let lastValue: A | typeof NO_VALUE = NO_VALUE\n for await (const a of as) {\n lastValue = a\n }\n if (lastValue === NO_VALUE) {\n throw new Error('No items in generator')\n }\n return lastValue\n}\n\ntype QueuedGenerator<A> = {\n done: boolean | void\n value: A | void\n generator: AsyncGenerator<A, void>\n promise: Promise<QueuedGenerator<A>>\n}\n\n// Run all generators concurrently up to a concurrency cap, yielding values as they come in\nexport async function* all<A>(\n generators: AsyncGenerator<A, void>[],\n concurrencyCap = Infinity,\n): AsyncGenerator<A, void> {\n const next = (generator: AsyncGenerator<A, void>) => {\n const promise: Promise<QueuedGenerator<A>> = generator\n .next()\n .then(({ done, value }) => ({\n done,\n value,\n generator,\n promise,\n }))\n return promise\n }\n const waiting = [...generators]\n const promises = new Set<Promise<QueuedGenerator<A>>>()\n\n // Start initial batch up to concurrency cap\n while (promises.size < concurrencyCap && waiting.length > 0) {\n const gen = waiting.shift()!\n promises.add(next(gen))\n }\n\n while (promises.size > 0) {\n const { done, value, generator, promise } = await Promise.race(promises)\n promises.delete(promise)\n\n if (!done) {\n promises.add(next(generator))\n //
|
|
4
|
+
"sourcesContent": ["const NO_VALUE = Symbol('NO_VALUE')\n\nexport async function lastX<A>(as: AsyncGenerator<A>): Promise<A> {\n let lastValue: A | typeof NO_VALUE = NO_VALUE\n for await (const a of as) {\n lastValue = a\n }\n if (lastValue === NO_VALUE) {\n throw new Error('No items in generator')\n }\n return lastValue\n}\n\ntype QueuedGenerator<A> = {\n done: boolean | void\n value: A | void\n generator: AsyncGenerator<A, void>\n promise: Promise<QueuedGenerator<A>>\n}\n\n// Run all generators concurrently up to a concurrency cap, yielding values as they come in\nexport async function* all<A>(\n generators: AsyncGenerator<A, void>[],\n concurrencyCap = Infinity,\n): AsyncGenerator<A, void> {\n const next = (generator: AsyncGenerator<A, void>) => {\n const promise: Promise<QueuedGenerator<A>> = generator\n .next()\n .then(({ done, value }) => ({\n done,\n value,\n generator,\n promise,\n }))\n return promise\n }\n const waiting = [...generators]\n const promises = new Set<Promise<QueuedGenerator<A>>>()\n\n // Start initial batch up to concurrency cap\n while (promises.size < concurrencyCap && waiting.length > 0) {\n const gen = waiting.shift()!\n promises.add(next(gen))\n }\n\n while (promises.size > 0) {\n const { done, value, generator, promise } = await Promise.race(promises)\n promises.delete(promise)\n\n if (!done) {\n promises.add(next(generator))\n // Yield non-undefined values from the generator\n if (value !== undefined) {\n yield value as A\n }\n } else if (waiting.length > 0) {\n // Start a new generator when one finishes\n const nextGen = waiting.shift()!\n promises.add(next(nextGen))\n }\n }\n}\n"],
|
|
5
5
|
"mappings": "AAAA,MAAM,WAAW,OAAO,UAAU;AAElC,eAAsB,MAAS,IAAmC;AAChE,MAAI,YAAiC;AACrC,mBAAiB,KAAK,IAAI;AACxB,gBAAY;AAAA,EACd;AACA,MAAI,cAAc,UAAU;AAC1B,UAAM,IAAI,MAAM,uBAAuB;AAAA,EACzC;AACA,SAAO;AACT;AAUA,gBAAuB,IACrB,YACA,iBAAiB,UACQ;AACzB,QAAM,OAAO,CAAC,cAAuC;AACnD,UAAM,UAAuC,UAC1C,KAAK,EACL,KAAK,CAAC,EAAE,MAAM,MAAM,OAAO;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE;AACJ,WAAO;AAAA,EACT;AACA,QAAM,UAAU,CAAC,GAAG,UAAU;AAC9B,QAAM,WAAW,oBAAI,IAAiC;AAGtD,SAAO,SAAS,OAAO,kBAAkB,QAAQ,SAAS,GAAG;AAC3D,UAAM,MAAM,QAAQ,MAAM;AAC1B,aAAS,IAAI,KAAK,GAAG,CAAC;AAAA,EACxB;AAEA,SAAO,SAAS,OAAO,GAAG;AACxB,UAAM,EAAE,MAAM,OAAO,WAAW,QAAQ,IAAI,MAAM,QAAQ,KAAK,QAAQ;AACvE,aAAS,OAAO,OAAO;AAEvB,QAAI,CAAC,MAAM;AACT,eAAS,IAAI,KAAK,SAAS,CAAC;AAE5B,UAAI,UAAU,QAAW;AACvB,cAAM;AAAA,MACR;AAAA,IACF,WAAW,QAAQ,SAAS,GAAG;AAE7B,YAAM,UAAU,QAAQ,MAAM;AAC9B,eAAS,IAAI,KAAK,OAAO,CAAC;AAAA,IAC5B;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shareai-lab/kode",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.19-dev.1",
|
|
4
4
|
"bin": {
|
|
5
5
|
"kode": "cli.js",
|
|
6
6
|
"kwa": "cli.js",
|
|
@@ -43,5 +43,62 @@
|
|
|
43
43
|
"prepare": "",
|
|
44
44
|
"publish:dev": "node scripts/publish-dev.js",
|
|
45
45
|
"publish:release": "node scripts/publish-release.js"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@anthropic-ai/bedrock-sdk": "^0.12.6",
|
|
49
|
+
"@anthropic-ai/sdk": "^0.39.0",
|
|
50
|
+
"@anthropic-ai/vertex-sdk": "^0.7.0",
|
|
51
|
+
"@commander-js/extra-typings": "^13.1.0",
|
|
52
|
+
"@inkjs/ui": "^2.0.0",
|
|
53
|
+
"@modelcontextprotocol/sdk": "^1.15.1",
|
|
54
|
+
"@shareai-lab/kode": "^1.1.21-dev.1",
|
|
55
|
+
"@statsig/client-core": "^3.18.2",
|
|
56
|
+
"@statsig/js-client": "^3.18.2",
|
|
57
|
+
"@types/lodash-es": "^4.17.12",
|
|
58
|
+
"@types/react": "^19.1.8",
|
|
59
|
+
"ansi-escapes": "^7.0.0",
|
|
60
|
+
"chalk": "^5.4.1",
|
|
61
|
+
"cli-highlight": "^2.1.11",
|
|
62
|
+
"cli-table3": "^0.6.5",
|
|
63
|
+
"commander": "^13.1.0",
|
|
64
|
+
"debug": "^4.4.1",
|
|
65
|
+
"diff": "^7.0.0",
|
|
66
|
+
"dotenv": "^16.6.1",
|
|
67
|
+
"env-paths": "^3.0.0",
|
|
68
|
+
"figures": "^6.1.0",
|
|
69
|
+
"glob": "^11.0.3",
|
|
70
|
+
"gray-matter": "^4.0.3",
|
|
71
|
+
"highlight.js": "^11.11.1",
|
|
72
|
+
"ink": "^5.2.1",
|
|
73
|
+
"ink-link": "^4.1.0",
|
|
74
|
+
"ink-select-input": "^6.2.0",
|
|
75
|
+
"ink-text-input": "^6.0.0",
|
|
76
|
+
"lodash-es": "^4.17.21",
|
|
77
|
+
"lru-cache": "^11.1.0",
|
|
78
|
+
"marked": "^15.0.12",
|
|
79
|
+
"nanoid": "^5.1.5",
|
|
80
|
+
"node-fetch": "^3.3.2",
|
|
81
|
+
"node-html-parser": "^7.0.1",
|
|
82
|
+
"openai": "^4.104.0",
|
|
83
|
+
"turndown": "^7.2.0",
|
|
84
|
+
"react": "18.3.1",
|
|
85
|
+
"semver": "^7.7.2",
|
|
86
|
+
"shell-quote": "^1.8.3",
|
|
87
|
+
"spawn-rx": "^5.1.2",
|
|
88
|
+
"string-width": "^7.2.0",
|
|
89
|
+
"strip-ansi": "^7.1.0",
|
|
90
|
+
"tsx": "^4.20.3",
|
|
91
|
+
"undici": "^7.11.0",
|
|
92
|
+
"wrap-ansi": "^9.0.0",
|
|
93
|
+
"zod": "^3.25.76",
|
|
94
|
+
"zod-to-json-schema": "^3.24.6"
|
|
95
|
+
},
|
|
96
|
+
"devDependencies": {
|
|
97
|
+
"@types/bun": "latest",
|
|
98
|
+
"@types/jest": "^30.0.0",
|
|
99
|
+
"@types/node": "^24.1.0",
|
|
100
|
+
"bun-types": "latest",
|
|
101
|
+
"prettier": "^3.6.2",
|
|
102
|
+
"typescript": "^5.9.2"
|
|
46
103
|
}
|
|
47
104
|
}
|