thatgfsj-code 0.7.0 → 0.7.2
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/app/index.d.ts.map +1 -1
- package/dist/app/index.js +5 -0
- package/dist/app/index.js.map +1 -1
- package/dist/cmd/index.d.ts +0 -5
- package/dist/cmd/index.d.ts.map +1 -1
- package/dist/cmd/index.js +36 -56
- package/dist/cmd/index.js.map +1 -1
- package/dist/session/index.d.ts +5 -21
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/index.js +26 -22
- package/dist/session/index.js.map +1 -1
- package/dist/tools/nwt.d.ts +5 -0
- package/dist/tools/nwt.d.ts.map +1 -1
- package/dist/tools/nwt.js +68 -0
- package/dist/tools/nwt.js.map +1 -1
- package/dist/tui/app.js +1 -1
- package/dist/tui/app.js.map +1 -1
- package/dist/tui/components/ChatList.d.ts +1 -1
- package/dist/tui/components/ChatList.d.ts.map +1 -1
- package/dist/tui/components/ChatList.js +5 -3
- package/dist/tui/components/ChatList.js.map +1 -1
- package/dist/tui/components/ChatMessage.d.ts +1 -1
- package/dist/tui/components/ChatMessage.d.ts.map +1 -1
- package/dist/tui/components/ChatMessage.js +4 -2
- package/dist/tui/components/ChatMessage.js.map +1 -1
- package/dist/tui/components/Header.d.ts +1 -1
- package/dist/tui/components/Header.d.ts.map +1 -1
- package/dist/tui/components/Header.js +5 -3
- package/dist/tui/components/Header.js.map +1 -1
- package/dist/tui/components/StatusBar.d.ts +1 -1
- package/dist/tui/components/StatusBar.d.ts.map +1 -1
- package/dist/tui/components/StatusBar.js +4 -2
- package/dist/tui/components/StatusBar.js.map +1 -1
- package/dist/tui/components/Thinking.d.ts +2 -1
- package/dist/tui/components/Thinking.d.ts.map +1 -1
- package/dist/tui/components/Thinking.js +5 -1
- package/dist/tui/components/Thinking.js.map +1 -1
- package/dist/tui/components/UserInput.d.ts +1 -1
- package/dist/tui/components/UserInput.d.ts.map +1 -1
- package/dist/tui/components/UserInput.js +5 -22
- package/dist/tui/components/UserInput.js.map +1 -1
- package/package.json +1 -1
- package/src/app/index.ts +6 -0
- package/src/cmd/index.tsx +38 -51
- package/src/session/index.ts +28 -22
- package/src/tools/nwt.ts +68 -0
- package/src/tui/app.tsx +1 -1
- package/src/tui/components/ChatList.tsx +4 -4
- package/src/tui/components/ChatMessage.tsx +2 -2
- package/src/tui/components/Header.tsx +3 -3
- package/src/tui/components/StatusBar.tsx +2 -2
- package/src/tui/components/Thinking.tsx +7 -1
- package/src/tui/components/UserInput.tsx +8 -24
- package/dist/app/agent.d.ts +0 -31
- package/dist/app/agent.d.ts.map +0 -1
- package/dist/app/agent.js +0 -106
- package/dist/app/agent.js.map +0 -1
- package/dist/tui/input.d.ts +0 -13
- package/dist/tui/input.d.ts.map +0 -1
- package/dist/tui/input.js +0 -47
- package/dist/tui/input.js.map +0 -1
- package/dist/tui/output.d.ts +0 -44
- package/dist/tui/output.d.ts.map +0 -1
- package/dist/tui/output.js +0 -202
- package/dist/tui/output.js.map +0 -1
- package/dist/tui/repl.d.ts +0 -15
- package/dist/tui/repl.d.ts.map +0 -1
- package/dist/tui/repl.js +0 -162
- package/dist/tui/repl.js.map +0 -1
- package/install.bat +0 -63
- package/install.ps1 +0 -217
- package/install.sh +0 -113
- package/src/tui/input.ts +0 -53
- package/src/tui/output.ts +0 -235
- package/src/tui/repl.ts +0 -181
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/** @jsxImportSource react */
|
|
3
|
+
import { memo } from 'react';
|
|
2
4
|
import { Box } from 'ink';
|
|
3
5
|
import { ChatMessage } from './ChatMessage.js';
|
|
4
|
-
export function ChatList({ messages, streaming, streamingToolCalls, width }) {
|
|
5
|
-
return (_jsxs(Box, { flexDirection: "column",
|
|
6
|
+
export const ChatList = memo(function ChatList({ messages, streaming, streamingToolCalls, width }) {
|
|
7
|
+
return (_jsxs(Box, { flexDirection: "column", children: [messages.map((msg, i) => (_jsx(ChatMessage, { message: msg, width: width }, i))), (streaming || streamingToolCalls) && (_jsx(ChatMessage, { message: {
|
|
6
8
|
role: 'assistant',
|
|
7
9
|
content: streaming || '',
|
|
8
10
|
toolCalls: streamingToolCalls,
|
|
9
11
|
}, width: width }))] }));
|
|
10
|
-
}
|
|
12
|
+
});
|
|
11
13
|
//# sourceMappingURL=ChatList.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatList.js","sourceRoot":"","sources":["../../../src/tui/components/ChatList.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"ChatList.js","sourceRoot":"","sources":["../../../src/tui/components/ChatList.tsx"],"names":[],"mappings":";AAAA,6BAA6B;AAC7B,OAAc,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAoB,MAAM,kBAAkB,CAAC;AAUjE,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,QAAQ,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,KAAK,EAAS;IACtG,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACxB,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CACxB,KAAC,WAAW,IAAS,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,IAA7B,CAAC,CAAgC,CACpD,CAAC,EACD,CAAC,SAAS,IAAI,kBAAkB,CAAC,IAAI,CACpC,KAAC,WAAW,IACV,OAAO,EAAE;oBACP,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE,SAAS,IAAI,EAAE;oBACxB,SAAS,EAAE,kBAAkB;iBAC9B,EACD,KAAK,EAAE,KAAK,GACZ,CACH,IACG,CACP,CAAC;AACJ,CAAC,CAAC,CAAC"}
|
|
@@ -10,6 +10,6 @@ interface Props {
|
|
|
10
10
|
message: MessageData;
|
|
11
11
|
width?: number;
|
|
12
12
|
}
|
|
13
|
-
export declare
|
|
13
|
+
export declare const ChatMessage: React.NamedExoticComponent<Props>;
|
|
14
14
|
export type { MessageData };
|
|
15
15
|
//# sourceMappingURL=ChatMessage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatMessage.d.ts","sourceRoot":"","sources":["../../../src/tui/components/ChatMessage.tsx"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAY,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAE5D,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;CAC5B;AAED,UAAU,KAAK;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA+BD,
|
|
1
|
+
{"version":3,"file":"ChatMessage.d.ts","sourceRoot":"","sources":["../../../src/tui/components/ChatMessage.tsx"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAY,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAE5D,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;CAC5B;AAED,UAAU,KAAK;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA+BD,eAAO,MAAM,WAAW,mCAKtB,CAAC;AAEH,YAAY,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/** @jsxImportSource react */
|
|
3
|
+
import React from 'react';
|
|
2
4
|
import { Box, Text } from 'ink';
|
|
3
5
|
import { Markdown } from './Markdown.js';
|
|
4
6
|
import { ToolCall } from './ToolCall.js';
|
|
@@ -8,10 +10,10 @@ function UserMessage({ content, width }) {
|
|
|
8
10
|
function AssistantMessage({ content, toolCalls, width }) {
|
|
9
11
|
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [toolCalls && toolCalls.map((tc, i) => (_jsx(ToolCall, { tool: tc, width: width }, i))), content && (_jsx(Box, { borderStyle: "round", borderLeft: true, borderColor: "#22D3EE", paddingLeft: 1, children: _jsxs(Box, { flexDirection: "column", width: width ? width - 4 : undefined, children: [_jsx(Text, { bold: true, color: "#22D3EE", children: "AI" }), _jsx(Markdown, { content: content })] }) }))] }));
|
|
10
12
|
}
|
|
11
|
-
export function ChatMessage({ message, width }) {
|
|
13
|
+
export const ChatMessage = React.memo(function ChatMessage({ message, width }) {
|
|
12
14
|
if (message.role === 'user') {
|
|
13
15
|
return _jsx(UserMessage, { content: message.content, width: width });
|
|
14
16
|
}
|
|
15
17
|
return _jsx(AssistantMessage, { content: message.content, toolCalls: message.toolCalls, width: width });
|
|
16
|
-
}
|
|
18
|
+
});
|
|
17
19
|
//# sourceMappingURL=ChatMessage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatMessage.js","sourceRoot":"","sources":["../../../src/tui/components/ChatMessage.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"ChatMessage.js","sourceRoot":"","sources":["../../../src/tui/components/ChatMessage.tsx"],"names":[],"mappings":";AAAA,6BAA6B;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAqB,MAAM,eAAe,CAAC;AAa5D,SAAS,WAAW,CAAC,EAAE,OAAO,EAAE,KAAK,EAAuC;IAC1E,OAAO,CACL,KAAC,GAAG,IAAC,WAAW,EAAC,OAAO,EAAC,UAAU,QAAC,WAAW,EAAC,SAAS,EAAC,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,YACvF,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,aAC9D,KAAC,IAAI,IAAC,IAAI,QAAC,KAAK,EAAC,SAAS,oBAAW,EACrC,KAAC,IAAI,cAAE,OAAO,GAAQ,IAClB,GACF,CACP,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAmE;IACtH,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,YAAY,EAAE,CAAC,aACxC,SAAS,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CACrC,KAAC,QAAQ,IAAS,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,IAAzB,CAAC,CAA4B,CAC7C,CAAC,EACD,OAAO,IAAI,CACV,KAAC,GAAG,IAAC,WAAW,EAAC,OAAO,EAAC,UAAU,QAAC,WAAW,EAAC,SAAS,EAAC,WAAW,EAAE,CAAC,YACtE,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,aAC9D,KAAC,IAAI,IAAC,IAAI,QAAC,KAAK,EAAC,SAAS,mBAAU,EACpC,KAAC,QAAQ,IAAC,OAAO,EAAE,OAAO,GAAI,IAC1B,GACF,CACP,IACG,CACP,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,WAAW,CAAC,EAAE,OAAO,EAAE,KAAK,EAAS;IAClF,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5B,OAAO,KAAC,WAAW,IAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,GAAI,CAAC;IACjE,CAAC;IACD,OAAO,KAAC,gBAAgB,IAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,GAAI,CAAC;AACpG,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../../src/tui/components/Header.tsx"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,KAAK;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,
|
|
1
|
+
{"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../../src/tui/components/Header.tsx"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,KAAK;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,MAAM,mCAkBjB,CAAC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/** @jsxImportSource react */
|
|
3
|
+
import React from 'react';
|
|
2
4
|
import { Box, Text } from 'ink';
|
|
3
|
-
export function Header({ provider, model }) {
|
|
4
|
-
return (_jsxs(Box, { flexDirection: "column", marginBottom: 0, children: [_jsxs(Box, { justifyContent: "space-between", width: "100%", children: [_jsxs(Box, { children: [_jsx(Text, { color: "#06B6D4", bold: true, children: " \u26A1 " }), _jsx(Text, { color: "#22D3EE", bold: true, children: "THATGFSJ CODE" }), _jsx(Text, { dimColor: true, children: " v0.7.
|
|
5
|
-
}
|
|
5
|
+
export const Header = React.memo(function Header({ provider, model }) {
|
|
6
|
+
return (_jsxs(Box, { flexDirection: "column", marginBottom: 0, children: [_jsxs(Box, { justifyContent: "space-between", width: "100%", children: [_jsxs(Box, { children: [_jsx(Text, { color: "#06B6D4", bold: true, children: " \u26A1 " }), _jsx(Text, { color: "#22D3EE", bold: true, children: "THATGFSJ CODE" }), _jsx(Text, { dimColor: true, children: " v0.7.2" })] }), _jsxs(Box, { children: [_jsxs(Text, { color: "#06B6D4", bold: true, children: [" ", provider, " "] }), _jsx(Text, { dimColor: true, children: "/" }), _jsxs(Text, { color: "#22D3EE", children: [" ", model, " "] })] })] }), _jsx(Text, { color: "#374151", children: '─'.repeat(80) })] }));
|
|
7
|
+
});
|
|
6
8
|
//# sourceMappingURL=Header.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Header.js","sourceRoot":"","sources":["../../../src/tui/components/Header.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"Header.js","sourceRoot":"","sources":["../../../src/tui/components/Header.tsx"],"names":[],"mappings":";AAAA,6BAA6B;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAOhC,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAS;IACzE,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,YAAY,EAAE,CAAC,aACzC,MAAC,GAAG,IAAC,cAAc,EAAC,eAAe,EAAC,KAAK,EAAC,MAAM,aAC9C,MAAC,GAAG,eACF,KAAC,IAAI,IAAC,KAAK,EAAC,SAAS,EAAC,IAAI,+BAAW,EACrC,KAAC,IAAI,IAAC,KAAK,EAAC,SAAS,EAAC,IAAI,oCAAqB,EAC/C,KAAC,IAAI,IAAC,QAAQ,8BAAe,IACzB,EACN,MAAC,GAAG,eACF,MAAC,IAAI,IAAC,KAAK,EAAC,SAAS,EAAC,IAAI,wBAAG,QAAQ,SAAS,EAC9C,KAAC,IAAI,IAAC,QAAQ,wBAAS,EACvB,MAAC,IAAI,IAAC,KAAK,EAAC,SAAS,kBAAG,KAAK,SAAS,IAClC,IACF,EACN,KAAC,IAAI,IAAC,KAAK,EAAC,SAAS,YAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAQ,IACzC,CACP,CAAC;AACJ,CAAC,CAAC,CAAC"}
|
|
@@ -4,6 +4,6 @@ interface Props {
|
|
|
4
4
|
messageCount: number;
|
|
5
5
|
skills: string[];
|
|
6
6
|
}
|
|
7
|
-
export declare
|
|
7
|
+
export declare const StatusBar: React.NamedExoticComponent<Props>;
|
|
8
8
|
export {};
|
|
9
9
|
//# sourceMappingURL=StatusBar.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusBar.d.ts","sourceRoot":"","sources":["../../../src/tui/components/StatusBar.tsx"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,KAAK;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,
|
|
1
|
+
{"version":3,"file":"StatusBar.d.ts","sourceRoot":"","sources":["../../../src/tui/components/StatusBar.tsx"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,KAAK;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,eAAO,MAAM,SAAS,mCAoBpB,CAAC"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/** @jsxImportSource react */
|
|
3
|
+
import React from 'react';
|
|
2
4
|
import { Box, Text } from 'ink';
|
|
3
|
-
export function StatusBar({ messageCount, skills }) {
|
|
5
|
+
export const StatusBar = React.memo(function StatusBar({ messageCount, skills }) {
|
|
4
6
|
const activeSkills = skills.slice(0, 3).join(', ');
|
|
5
7
|
const moreSkills = skills.length > 3 ? ` +${skills.length - 3}` : '';
|
|
6
8
|
return (_jsxs(Box, { flexDirection: "column", marginTop: 0, children: [_jsx(Text, { color: "#374151", children: '─'.repeat(80) }), _jsxs(Box, { justifyContent: "space-between", width: "100%", children: [_jsxs(Box, { children: [_jsx(Text, { backgroundColor: "#06B6D4", color: "#0F172A", bold: true, children: " \u26A1 THATGFSJ CODE " }), _jsxs(Text, { dimColor: true, children: [" \u2502 ", messageCount, " messages"] })] }), _jsx(Box, { children: skills.length > 0 && (_jsxs(Text, { dimColor: true, children: [" skills: ", activeSkills, moreSkills, " "] })) })] })] }));
|
|
7
|
-
}
|
|
9
|
+
});
|
|
8
10
|
//# sourceMappingURL=StatusBar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusBar.js","sourceRoot":"","sources":["../../../src/tui/components/StatusBar.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"StatusBar.js","sourceRoot":"","sources":["../../../src/tui/components/StatusBar.tsx"],"names":[],"mappings":";AAAA,6BAA6B;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAOhC,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,EAAE,YAAY,EAAE,MAAM,EAAS;IACpF,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAErE,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,SAAS,EAAE,CAAC,aACtC,KAAC,IAAI,IAAC,KAAK,EAAC,SAAS,YAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAQ,EAC7C,MAAC,GAAG,IAAC,cAAc,EAAC,eAAe,EAAC,KAAK,EAAC,MAAM,aAC9C,MAAC,GAAG,eACF,KAAC,IAAI,IAAC,eAAe,EAAC,SAAS,EAAC,KAAK,EAAC,SAAS,EAAC,IAAI,6CAAyB,EAC7E,MAAC,IAAI,IAAC,QAAQ,+BAAK,YAAY,iBAAiB,IAC5C,EACN,KAAC,GAAG,cACD,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CACpB,MAAC,IAAI,IAAC,QAAQ,gCAAW,YAAY,EAAE,UAAU,SAAS,CAC3D,GACG,IACF,IACF,CACP,CAAC;AACJ,CAAC,CAAC,CAAC"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/** @jsxImportSource react */
|
|
2
2
|
import React from 'react';
|
|
3
3
|
interface Props {
|
|
4
|
+
active?: boolean;
|
|
4
5
|
message?: string;
|
|
5
6
|
}
|
|
6
|
-
export declare function Thinking({ message }: Props): React.JSX.Element;
|
|
7
|
+
export declare function Thinking({ active, message }: Props): React.JSX.Element;
|
|
7
8
|
export {};
|
|
8
9
|
//# sourceMappingURL=Thinking.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Thinking.d.ts","sourceRoot":"","sources":["../../../src/tui/components/Thinking.tsx"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,UAAU,KAAK;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,QAAQ,CAAC,EAAE,OAAoB,EAAE,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"Thinking.d.ts","sourceRoot":"","sources":["../../../src/tui/components/Thinking.tsx"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,UAAU,KAAK;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,QAAQ,CAAC,EAAE,MAAa,EAAE,OAAoB,EAAE,EAAE,KAAK,qBActE"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
3
|
import Spinner from 'ink-spinner';
|
|
4
|
-
export function Thinking({ message = 'Thinking' }) {
|
|
4
|
+
export function Thinking({ active = true, message = 'Thinking' }) {
|
|
5
|
+
if (!active) {
|
|
6
|
+
// Keep layout stable - render empty space
|
|
7
|
+
return _jsx(Box, { paddingY: 0, children: _jsx(Text, { children: " " }) });
|
|
8
|
+
}
|
|
5
9
|
return (_jsxs(Box, { paddingLeft: 1, children: [_jsx(Text, { color: "#06B6D4", children: _jsx(Spinner, { type: "dots" }) }), _jsxs(Text, { color: "#06B6D4", children: [" ", message] })] }));
|
|
6
10
|
}
|
|
7
11
|
//# sourceMappingURL=Thinking.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Thinking.js","sourceRoot":"","sources":["../../../src/tui/components/Thinking.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,OAAO,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"Thinking.js","sourceRoot":"","sources":["../../../src/tui/components/Thinking.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,OAAO,MAAM,aAAa,CAAC;AAOlC,MAAM,UAAU,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,GAAG,UAAU,EAAS;IACrE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,0CAA0C;QAC1C,OAAO,KAAC,GAAG,IAAC,QAAQ,EAAE,CAAC,YAAE,KAAC,IAAI,oBAAS,GAAM,CAAC;IAChD,CAAC;IAED,OAAO,CACL,MAAC,GAAG,IAAC,WAAW,EAAE,CAAC,aACjB,KAAC,IAAI,IAAC,KAAK,EAAC,SAAS,YACnB,KAAC,OAAO,IAAC,IAAI,EAAC,MAAM,GAAG,GAClB,EACP,MAAC,IAAI,IAAC,KAAK,EAAC,SAAS,kBAAG,OAAO,IAAQ,IACnC,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -4,6 +4,6 @@ interface Props {
|
|
|
4
4
|
onSubmit: (input: string) => void;
|
|
5
5
|
disabled?: boolean;
|
|
6
6
|
}
|
|
7
|
-
export declare
|
|
7
|
+
export declare const UserInput: React.NamedExoticComponent<Props>;
|
|
8
8
|
export {};
|
|
9
9
|
//# sourceMappingURL=UserInput.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserInput.d.ts","sourceRoot":"","sources":["../../../src/tui/components/UserInput.tsx"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,OAAO,
|
|
1
|
+
{"version":3,"file":"UserInput.d.ts","sourceRoot":"","sources":["../../../src/tui/components/UserInput.tsx"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,OAAO,KAAyB,MAAM,OAAO,CAAC;AAG9C,UAAU,KAAK;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,SAAS,mCAyDpB,CAAC"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
/** @jsxImportSource react */
|
|
3
|
-
import { useState } from 'react';
|
|
3
|
+
import { useState, memo } from 'react';
|
|
4
4
|
import { Box, Text, useInput, useApp } from 'ink';
|
|
5
|
-
export function UserInput({ onSubmit, disabled }) {
|
|
5
|
+
export const UserInput = memo(function UserInput({ onSubmit, disabled }) {
|
|
6
6
|
const [value, setValue] = useState('');
|
|
7
|
-
const [cursorPos, setCursorPos] = useState(0);
|
|
8
7
|
const [history, setHistory] = useState([]);
|
|
9
8
|
const [historyIdx, setHistoryIdx] = useState(-1);
|
|
10
9
|
const { exit } = useApp();
|
|
@@ -22,7 +21,6 @@ export function UserInput({ onSubmit, disabled }) {
|
|
|
22
21
|
setHistoryIdx(-1);
|
|
23
22
|
onSubmit(trimmed);
|
|
24
23
|
setValue('');
|
|
25
|
-
setCursorPos(0);
|
|
26
24
|
}
|
|
27
25
|
return;
|
|
28
26
|
}
|
|
@@ -30,7 +28,6 @@ export function UserInput({ onSubmit, disabled }) {
|
|
|
30
28
|
const newIdx = historyIdx === -1 ? history.length - 1 : Math.max(0, historyIdx - 1);
|
|
31
29
|
setHistoryIdx(newIdx);
|
|
32
30
|
setValue(history[newIdx]);
|
|
33
|
-
setCursorPos(history[newIdx].length);
|
|
34
31
|
return;
|
|
35
32
|
}
|
|
36
33
|
if (key.downArrow && historyIdx >= 0) {
|
|
@@ -38,28 +35,15 @@ export function UserInput({ onSubmit, disabled }) {
|
|
|
38
35
|
if (newIdx >= history.length) {
|
|
39
36
|
setHistoryIdx(-1);
|
|
40
37
|
setValue('');
|
|
41
|
-
setCursorPos(0);
|
|
42
38
|
}
|
|
43
39
|
else {
|
|
44
40
|
setHistoryIdx(newIdx);
|
|
45
41
|
setValue(history[newIdx]);
|
|
46
|
-
setCursorPos(history[newIdx].length);
|
|
47
42
|
}
|
|
48
43
|
return;
|
|
49
44
|
}
|
|
50
45
|
if (key.backspace || key.delete) {
|
|
51
|
-
|
|
52
|
-
setValue(v => v.slice(0, cursorPos - 1) + v.slice(cursorPos));
|
|
53
|
-
setCursorPos(p => p - 1);
|
|
54
|
-
}
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
if (key.leftArrow) {
|
|
58
|
-
setCursorPos(p => Math.max(0, p - 1));
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
if (key.rightArrow) {
|
|
62
|
-
setCursorPos(p => Math.min(value.length, p + 1));
|
|
46
|
+
setValue(v => v.slice(0, -1));
|
|
63
47
|
return;
|
|
64
48
|
}
|
|
65
49
|
if (key.ctrl && input === 'c') {
|
|
@@ -67,10 +51,9 @@ export function UserInput({ onSubmit, disabled }) {
|
|
|
67
51
|
return;
|
|
68
52
|
}
|
|
69
53
|
if (input && !key.ctrl && !key.meta) {
|
|
70
|
-
setValue(v => v
|
|
71
|
-
setCursorPos(p => p + input.length);
|
|
54
|
+
setValue(v => v + input);
|
|
72
55
|
}
|
|
73
56
|
});
|
|
74
57
|
return (_jsxs(Box, { paddingY: 0, children: [_jsx(Text, { color: "#06B6D4", bold: true, children: disabled ? ' ' : '❯ ' }), _jsx(Text, { children: value }), !disabled && _jsx(Text, { color: "#06B6D4", children: "\u2588" })] }));
|
|
75
|
-
}
|
|
58
|
+
});
|
|
76
59
|
//# sourceMappingURL=UserInput.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserInput.js","sourceRoot":"","sources":["../../../src/tui/components/UserInput.tsx"],"names":[],"mappings":";AAAA,6BAA6B;AAC7B,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"UserInput.js","sourceRoot":"","sources":["../../../src/tui/components/UserInput.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/app/index.ts
CHANGED
|
@@ -52,6 +52,12 @@ export class App {
|
|
|
52
52
|
// Register tools with LLM service
|
|
53
53
|
llm.registerTools(tools.list());
|
|
54
54
|
|
|
55
|
+
// Auto-init NWT timeline
|
|
56
|
+
const nwtTool = tools.get('nwt');
|
|
57
|
+
if (nwtTool) {
|
|
58
|
+
await nwtTool.execute({ action: 'init' });
|
|
59
|
+
}
|
|
60
|
+
|
|
55
61
|
// Build system prompt with active skills
|
|
56
62
|
const prompts = new SystemPromptBuilder({
|
|
57
63
|
cwd: process.cwd(),
|
package/src/cmd/index.tsx
CHANGED
|
@@ -2,14 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Thatgfsj Code - CLI Entry Point
|
|
5
|
-
*
|
|
6
|
-
* Two modes:
|
|
7
|
-
* gfcode → Interactive TUI (Ink)
|
|
8
|
-
* gfcode "prompt" → Single prompt mode
|
|
9
|
-
* gfcode init → Setup wizard
|
|
10
5
|
*/
|
|
11
6
|
|
|
12
|
-
// Force UTF-8 on Windows
|
|
13
7
|
if (process.platform === 'win32') {
|
|
14
8
|
try {
|
|
15
9
|
require('child_process').execSync('chcp 65001', { stdio: 'ignore', windowsHide: true });
|
|
@@ -20,9 +14,6 @@ import { program } from 'commander';
|
|
|
20
14
|
import chalk from 'chalk';
|
|
21
15
|
import { App } from '../app/index.js';
|
|
22
16
|
import { WelcomeScreen } from '../tui/welcome.js';
|
|
23
|
-
import { REPLOutput } from '../tui/output.js';
|
|
24
|
-
|
|
25
|
-
// ==================== Error Handling ====================
|
|
26
17
|
|
|
27
18
|
process.on('uncaughtException', (error) => {
|
|
28
19
|
console.error(chalk.red('\n Error:'), error.message);
|
|
@@ -34,61 +25,50 @@ process.on('unhandledRejection', (reason) => {
|
|
|
34
25
|
process.exit(1);
|
|
35
26
|
});
|
|
36
27
|
|
|
37
|
-
// ==================== CLI Commands ====================
|
|
38
|
-
|
|
39
28
|
program
|
|
40
29
|
.name('gfcode')
|
|
41
30
|
.description('Thatgfsj Code - AI Coding Assistant')
|
|
42
|
-
.version('0.7.
|
|
31
|
+
.version('0.7.2')
|
|
43
32
|
.argument('[prompt]', 'Task to execute (omit to start interactive mode)')
|
|
44
33
|
.option('-m, --model <model>', 'Specify model')
|
|
45
34
|
.option('-i, --interactive', 'Force interactive mode')
|
|
46
35
|
.action(async (prompt: string | undefined, options: { model?: string; interactive?: boolean }) => {
|
|
47
36
|
try {
|
|
48
37
|
const app = await App.create();
|
|
49
|
-
|
|
50
|
-
// Show welcome if no API key
|
|
51
38
|
WelcomeScreen.show(app.config.hasApiKey());
|
|
52
39
|
|
|
53
|
-
// Override model if specified
|
|
54
40
|
if (options.model) {
|
|
55
41
|
await app.config.save({ model: options.model });
|
|
56
42
|
}
|
|
57
43
|
|
|
58
44
|
if (!prompt || options.interactive) {
|
|
59
|
-
// Interactive mode -
|
|
45
|
+
// Interactive mode - Ink TUI
|
|
60
46
|
const { render } = await import('ink');
|
|
61
47
|
const { TuiApp } = await import('../tui/app.js');
|
|
62
|
-
|
|
63
48
|
const { unmount } = render(<TuiApp app={app} />);
|
|
64
|
-
|
|
65
|
-
// Wait for the app to exit
|
|
66
49
|
await new Promise<void>((resolve) => {
|
|
67
|
-
|
|
68
|
-
// Ink will call process.exit or we detect it
|
|
69
|
-
}, 1000);
|
|
70
|
-
process.on('exit', () => {
|
|
71
|
-
clearInterval(check);
|
|
72
|
-
unmount();
|
|
73
|
-
resolve();
|
|
74
|
-
});
|
|
50
|
+
process.on('exit', () => { unmount(); resolve(); });
|
|
75
51
|
});
|
|
76
52
|
} else {
|
|
77
|
-
// Single prompt mode
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
53
|
+
// Single prompt mode
|
|
54
|
+
console.log(chalk.cyan.bold('\n ⚡ THATGFSJ CODE\n'));
|
|
55
|
+
console.log(chalk.gray(' You'));
|
|
56
|
+
console.log(chalk.gray(' ' + '─'.repeat(40)));
|
|
57
|
+
console.log(' ' + prompt);
|
|
58
|
+
console.log();
|
|
82
59
|
|
|
83
60
|
app.session.addMessage('user', prompt);
|
|
84
61
|
let fullResponse = '';
|
|
85
|
-
let hasStarted = false;
|
|
86
62
|
|
|
87
63
|
try {
|
|
64
|
+
process.stdout.write(chalk.gray(' Thinking...\r'));
|
|
88
65
|
const stream = app.streamResponse();
|
|
66
|
+
|
|
89
67
|
for await (const chunk of stream) {
|
|
90
|
-
|
|
68
|
+
// Clear thinking line
|
|
69
|
+
process.stdout.write('\r' + ' '.repeat(40) + '\r');
|
|
91
70
|
|
|
71
|
+
// Parse tool messages
|
|
92
72
|
if (chunk.includes('@@TOOL@@')) {
|
|
93
73
|
const parts = chunk.split('\n');
|
|
94
74
|
for (const part of parts) {
|
|
@@ -96,34 +76,31 @@ program
|
|
|
96
76
|
try {
|
|
97
77
|
const data = JSON.parse(part.slice(8));
|
|
98
78
|
if (data.action === 'call') {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
out.startExecuting(data.name);
|
|
79
|
+
console.log();
|
|
80
|
+
console.log(chalk.cyan(` ⚙ ${data.name}: ${formatArgs(data.args)}`));
|
|
102
81
|
} else if (data.action === 'result') {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
82
|
+
const output = data.output || data.error || '';
|
|
83
|
+
const lines = output.split('\n').slice(0, 10);
|
|
84
|
+
for (const line of lines) {
|
|
85
|
+
console.log(chalk.gray(' │ ') + line);
|
|
86
|
+
}
|
|
106
87
|
}
|
|
107
88
|
} catch {}
|
|
108
89
|
} else if (part) {
|
|
109
|
-
|
|
110
|
-
out.writeChunk(part + '\n');
|
|
90
|
+
process.stdout.write(chalk.cyan(' │ ') + part);
|
|
111
91
|
}
|
|
112
92
|
}
|
|
113
93
|
} else {
|
|
114
|
-
|
|
115
|
-
out.writeChunk(chunk);
|
|
94
|
+
process.stdout.write(chunk);
|
|
116
95
|
}
|
|
117
96
|
fullResponse += chunk;
|
|
118
97
|
}
|
|
119
|
-
|
|
98
|
+
|
|
99
|
+
console.log();
|
|
100
|
+
app.session.addMessage('assistant', fullResponse);
|
|
120
101
|
} catch (error: any) {
|
|
121
|
-
|
|
122
|
-
out.stopThinkingFail(error.message);
|
|
123
|
-
out.error(error.message);
|
|
102
|
+
console.error(chalk.red(`\n Error: ${error.message}`));
|
|
124
103
|
}
|
|
125
|
-
|
|
126
|
-
app.session.addMessage('assistant', fullResponse);
|
|
127
104
|
}
|
|
128
105
|
} catch (error: any) {
|
|
129
106
|
console.error(chalk.red(`\n ${error.message}`));
|
|
@@ -131,7 +108,6 @@ program
|
|
|
131
108
|
}
|
|
132
109
|
});
|
|
133
110
|
|
|
134
|
-
// Init command
|
|
135
111
|
program
|
|
136
112
|
.command('init')
|
|
137
113
|
.description('Configure API key and model')
|
|
@@ -140,3 +116,14 @@ program
|
|
|
140
116
|
});
|
|
141
117
|
|
|
142
118
|
program.parse(process.argv);
|
|
119
|
+
|
|
120
|
+
function formatArgs(args: string): string {
|
|
121
|
+
try {
|
|
122
|
+
const obj = JSON.parse(args);
|
|
123
|
+
return Object.entries(obj)
|
|
124
|
+
.map(([k, v]) => `${k}=${typeof v === 'string' && v.length > 40 ? v.slice(0, 40) + '...' : JSON.stringify(v)}`)
|
|
125
|
+
.join(' ');
|
|
126
|
+
} catch {
|
|
127
|
+
return args.length > 60 ? args.slice(0, 60) + '...' : args;
|
|
128
|
+
}
|
|
129
|
+
}
|
package/src/session/index.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Session Manager - Manages conversation history
|
|
3
|
-
* Migrated from old src/core/session.ts
|
|
2
|
+
* Session Manager - Manages conversation history with auto-compaction
|
|
4
3
|
*/
|
|
5
4
|
|
|
6
5
|
import type { ChatMessage } from '../types.js';
|
|
@@ -11,62 +10,69 @@ export class SessionManager {
|
|
|
11
10
|
private sessionId: string;
|
|
12
11
|
private createdAt: Date;
|
|
13
12
|
private compactor: ContextCompactor;
|
|
13
|
+
private maxMessages: number;
|
|
14
14
|
|
|
15
15
|
constructor(maxMessages = 50) {
|
|
16
|
+
this.maxMessages = maxMessages;
|
|
16
17
|
this.sessionId = `session_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
17
18
|
this.createdAt = new Date();
|
|
18
19
|
this.compactor = new ContextCompactor({ maxMessages });
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
/**
|
|
22
|
-
* Add a message to the session
|
|
23
|
-
*/
|
|
24
22
|
addMessage(role: ChatMessage['role'], content: string, extras?: Partial<ChatMessage>): void {
|
|
25
23
|
this.messages.push({ role, content, ...extras });
|
|
24
|
+
this.autoCompact();
|
|
26
25
|
}
|
|
27
26
|
|
|
28
|
-
/**
|
|
29
|
-
* Get all messages (copy)
|
|
30
|
-
*/
|
|
31
27
|
getMessages(): ChatMessage[] {
|
|
32
28
|
return [...this.messages];
|
|
33
29
|
}
|
|
34
30
|
|
|
35
|
-
/**
|
|
36
|
-
* Get message count
|
|
37
|
-
*/
|
|
38
31
|
getMessageCount(): number {
|
|
39
32
|
return this.messages.length;
|
|
40
33
|
}
|
|
41
34
|
|
|
42
|
-
/**
|
|
43
|
-
* Clear session history
|
|
44
|
-
*/
|
|
45
35
|
clear(): void {
|
|
46
36
|
this.messages = [];
|
|
47
37
|
}
|
|
48
38
|
|
|
49
39
|
/**
|
|
50
|
-
*
|
|
40
|
+
* Auto-compact when messages exceed max.
|
|
41
|
+
* Keeps system messages + recent half. One summary replaces the rest.
|
|
51
42
|
*/
|
|
43
|
+
private autoCompact(): void {
|
|
44
|
+
if (this.messages.length <= this.maxMessages) return;
|
|
45
|
+
|
|
46
|
+
const systemMsgs = this.messages.filter(m => m.role === 'system');
|
|
47
|
+
const others = this.messages.filter(m => m.role !== 'system');
|
|
48
|
+
const keepCount = Math.floor(this.maxMessages * 0.5);
|
|
49
|
+
const recent = others.slice(-keepCount);
|
|
50
|
+
const removed = others.length - keepCount;
|
|
51
|
+
|
|
52
|
+
if (removed <= 0) return;
|
|
53
|
+
|
|
54
|
+
// Remove old summaries before adding new one
|
|
55
|
+
const cleanSystem = systemMsgs.filter(m => !m.content.startsWith('[Earlier conversation'));
|
|
56
|
+
const summary: ChatMessage = {
|
|
57
|
+
role: 'system',
|
|
58
|
+
content: `[Earlier conversation: ${removed} messages compacted to save context]`,
|
|
59
|
+
};
|
|
60
|
+
this.messages = [...cleanSystem, summary, ...recent];
|
|
61
|
+
}
|
|
62
|
+
|
|
52
63
|
truncate(maxMessages?: number): void {
|
|
53
64
|
if (maxMessages) {
|
|
65
|
+
this.maxMessages = maxMessages;
|
|
54
66
|
this.compactor = new ContextCompactor({ maxMessages });
|
|
55
67
|
}
|
|
56
|
-
const { compacted } = this.compactor.
|
|
68
|
+
const { compacted } = this.compactor.compact(this.messages);
|
|
57
69
|
this.messages = compacted;
|
|
58
70
|
}
|
|
59
71
|
|
|
60
|
-
/**
|
|
61
|
-
* Get session ID
|
|
62
|
-
*/
|
|
63
72
|
getId(): string {
|
|
64
73
|
return this.sessionId;
|
|
65
74
|
}
|
|
66
75
|
|
|
67
|
-
/**
|
|
68
|
-
* Get session info
|
|
69
|
-
*/
|
|
70
76
|
getInfo(): { id: string; messageCount: number; createdAt: Date } {
|
|
71
77
|
return {
|
|
72
78
|
id: this.sessionId,
|