@agentskit/ink 0.4.0 → 0.4.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/README.md +54 -0
- package/dist/index.cjs +20 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +20 -2
- package/dist/index.js.map +1 -1
- package/package.json +18 -7
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# @agentskit/ink
|
|
2
|
+
|
|
3
|
+
Build terminal AI chat interfaces with the exact same API as `@agentskit/react`.
|
|
4
|
+
|
|
5
|
+
## Why
|
|
6
|
+
|
|
7
|
+
- **No context switching** — if you know `@agentskit/react`, you already know this; same hooks, same component names, different renderer
|
|
8
|
+
- **Real terminal UX** — keyboard navigation, ANSI colors, and proper TTY streaming so your CLI feels native, not like a web app in a box
|
|
9
|
+
- **Any local or cloud model** — pair with Ollama for fully offline CLI tools, or any other provider via `@agentskit/adapters`
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @agentskit/ink @agentskit/adapters
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick example
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import React from 'react'
|
|
21
|
+
import { render } from 'ink'
|
|
22
|
+
import { ChatContainer, InputBar, Message, useChat } from '@agentskit/ink'
|
|
23
|
+
import { ollama } from '@agentskit/adapters'
|
|
24
|
+
|
|
25
|
+
function App() {
|
|
26
|
+
const chat = useChat({ adapter: ollama({ model: 'llama3.1' }) })
|
|
27
|
+
return (
|
|
28
|
+
<ChatContainer>
|
|
29
|
+
{chat.messages.map(msg => <Message key={msg.id} message={msg} />)}
|
|
30
|
+
<InputBar chat={chat} />
|
|
31
|
+
</ChatContainer>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
render(<App />)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Next steps
|
|
39
|
+
|
|
40
|
+
- Use **tools** and **memory** from [`@agentskit/tools`](https://www.npmjs.com/package/@agentskit/tools) and [`@agentskit/memory`](https://www.npmjs.com/package/@agentskit/memory) in `useChat` the same way as in React
|
|
41
|
+
- For a **browser** UI, swap to [`@agentskit/react`](https://www.npmjs.com/package/@agentskit/react); for a quick **terminal chat** without your own Ink app, run [`@agentskit/cli`](https://www.npmjs.com/package/@agentskit/cli) `agentskit chat`
|
|
42
|
+
|
|
43
|
+
## Ecosystem
|
|
44
|
+
|
|
45
|
+
| Package | Role |
|
|
46
|
+
|---------|------|
|
|
47
|
+
| [@agentskit/react](https://www.npmjs.com/package/@agentskit/react) | Browser — same hooks, different renderer |
|
|
48
|
+
| [@agentskit/cli](https://www.npmjs.com/package/@agentskit/cli) | Interactive chat + `agentskit init` |
|
|
49
|
+
| [@agentskit/adapters](https://www.npmjs.com/package/@agentskit/adapters) | Providers (e.g. `ollama` for local models) |
|
|
50
|
+
| [@agentskit/core](https://www.npmjs.com/package/@agentskit/core) | Shared chat types and controller |
|
|
51
|
+
|
|
52
|
+
## Docs
|
|
53
|
+
|
|
54
|
+
[Full documentation](https://emersonbraun.github.io/agentskit/)
|
package/dist/index.cjs
CHANGED
|
@@ -25,7 +25,9 @@ function useChat(config) {
|
|
|
25
25
|
stop: controllerRef.current.stop,
|
|
26
26
|
retry: controllerRef.current.retry,
|
|
27
27
|
setInput: controllerRef.current.setInput,
|
|
28
|
-
clear: controllerRef.current.clear
|
|
28
|
+
clear: controllerRef.current.clear,
|
|
29
|
+
approve: controllerRef.current.approve,
|
|
30
|
+
deny: controllerRef.current.deny
|
|
29
31
|
};
|
|
30
32
|
}
|
|
31
33
|
function ChatContainer({ children }) {
|
|
@@ -96,6 +98,22 @@ function ThinkingIndicator({ visible, label = "Thinking..." }) {
|
|
|
96
98
|
if (!visible) return null;
|
|
97
99
|
return /* @__PURE__ */ jsxRuntime.jsx(ink.Text, { color: "yellow", children: label });
|
|
98
100
|
}
|
|
101
|
+
function ToolConfirmation({ toolCall, onApprove, onDeny }) {
|
|
102
|
+
ink.useInput((input) => {
|
|
103
|
+
if (toolCall.status !== "requires_confirmation") return;
|
|
104
|
+
if (input.toLowerCase() === "y") onApprove(toolCall.id);
|
|
105
|
+
if (input.toLowerCase() === "n") onDeny(toolCall.id);
|
|
106
|
+
});
|
|
107
|
+
if (toolCall.status !== "requires_confirmation") return null;
|
|
108
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ink.Box, { flexDirection: "column", borderStyle: "round", paddingX: 1, borderColor: "yellow", children: [
|
|
109
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ink.Text, { color: "yellow", bold: true, children: [
|
|
110
|
+
"Confirm: ",
|
|
111
|
+
toolCall.name
|
|
112
|
+
] }),
|
|
113
|
+
/* @__PURE__ */ jsxRuntime.jsx(ink.Text, { dimColor: true, children: JSON.stringify(toolCall.args) }),
|
|
114
|
+
/* @__PURE__ */ jsxRuntime.jsx(ink.Text, { color: "yellow", children: "Allow? (y/n)" })
|
|
115
|
+
] });
|
|
116
|
+
}
|
|
99
117
|
|
|
100
118
|
Object.defineProperty(exports, "createChatController", {
|
|
101
119
|
enumerable: true,
|
|
@@ -126,6 +144,7 @@ exports.InputBar = InputBar;
|
|
|
126
144
|
exports.Message = Message;
|
|
127
145
|
exports.ThinkingIndicator = ThinkingIndicator;
|
|
128
146
|
exports.ToolCallView = ToolCallView;
|
|
147
|
+
exports.ToolConfirmation = ToolConfirmation;
|
|
129
148
|
exports.useChat = useChat;
|
|
130
149
|
//# sourceMappingURL=index.cjs.map
|
|
131
150
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/useChat.ts","../src/components/ChatContainer.tsx","../src/components/Message.tsx","../src/components/InputBar.tsx","../src/components/ToolCallView.tsx","../src/components/ThinkingIndicator.tsx"],"names":["useRef","createChatController","useEffect","useSyncExternalStore","Box","jsxs","jsx","Text","useInput","Fragment"],"mappings":"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","file":"index.cjs","sourcesContent":["// NOTE: This hook is identical in @agentskit/react and @agentskit/ink.\n// Changes here must be mirrored in packages/react/src/useChat.ts.\nimport { useEffect, useRef, useSyncExternalStore } from 'react'\nimport { createChatController } from '@agentskit/core'\nimport type { ChatConfig, ChatController, ChatReturn } from '@agentskit/core'\n\nexport function useChat(config: ChatConfig): ChatReturn {\n const controllerRef = useRef<ChatController | null>(null)\n\n if (!controllerRef.current) {\n controllerRef.current = createChatController(config)\n }\n\n useEffect(() => {\n controllerRef.current?.updateConfig(config)\n }, [config])\n\n const state = useSyncExternalStore(\n controllerRef.current.subscribe,\n controllerRef.current.getState,\n controllerRef.current.getState\n )\n\n return {\n ...state,\n send: controllerRef.current.send,\n stop: controllerRef.current.stop,\n retry: controllerRef.current.retry,\n setInput: controllerRef.current.setInput,\n clear: controllerRef.current.clear,\n }\n}\n","import React, { type ReactNode } from 'react'\nimport { Box } from 'ink'\n\nexport interface ChatContainerProps {\n children: ReactNode\n}\n\nexport function ChatContainer({ children }: ChatContainerProps) {\n return (\n <Box flexDirection=\"column\" gap={1}>\n {children}\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { Message as MessageType } from '@agentskit/core'\n\nexport interface MessageProps {\n message: MessageType\n}\n\nfunction roleColor(role: MessageType['role']) {\n switch (role) {\n case 'assistant':\n return 'cyan'\n case 'user':\n return 'green'\n case 'system':\n return 'yellow'\n case 'tool':\n return 'magenta'\n default:\n return 'white'\n }\n}\n\nexport function Message({ message }: MessageProps) {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={roleColor(message.role)}>\n {message.role.toUpperCase()}\n </Text>\n <Text>{message.content || (message.status === 'streaming' ? '...' : '')}</Text>\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text, useInput } from 'ink'\nimport type { ChatReturn } from '@agentskit/core'\n\nexport interface InputBarProps {\n chat: ChatReturn\n placeholder?: string\n disabled?: boolean\n}\n\nexport function InputBar({ chat, placeholder = 'Type a message...', disabled = false }: InputBarProps) {\n useInput((input, key) => {\n if (disabled || chat.status === 'streaming') return\n\n if (key.return) {\n if (chat.input.trim()) {\n void chat.send(chat.input)\n }\n return\n }\n\n if (key.backspace || key.delete) {\n chat.setInput(chat.input.slice(0, -1))\n return\n }\n\n if (input && !key.ctrl && !key.meta) {\n chat.setInput(`${chat.input}${input}`)\n }\n })\n\n return (\n <Box flexDirection=\"column\">\n <Text dimColor>{placeholder}</Text>\n <Text color={disabled ? 'gray' : 'white'}>\n > {chat.input}\n </Text>\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { ToolCall } from '@agentskit/core'\n\nexport interface ToolCallViewProps {\n toolCall: ToolCall\n expanded?: boolean\n}\n\nexport function ToolCallView({ toolCall, expanded = false }: ToolCallViewProps) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" paddingX={1}>\n <Text color=\"magenta\">\n Tool: {toolCall.name} [{toolCall.status}]\n </Text>\n {expanded ? (\n <>\n <Text dimColor>{JSON.stringify(toolCall.args)}</Text>\n {toolCall.result ? <Text>{toolCall.result}</Text> : null}\n {toolCall.error ? <Text color=\"red\">{toolCall.error}</Text> : null}\n </>\n ) : null}\n </Box>\n )\n}\n","import React from 'react'\nimport { Text } from 'ink'\n\nexport interface ThinkingIndicatorProps {\n visible: boolean\n label?: string\n}\n\nexport function ThinkingIndicator({ visible, label = 'Thinking...' }: ThinkingIndicatorProps) {\n if (!visible) return null\n return <Text color=\"yellow\">{label}</Text>\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/useChat.ts","../src/components/ChatContainer.tsx","../src/components/Message.tsx","../src/components/InputBar.tsx","../src/components/ToolCallView.tsx","../src/components/ThinkingIndicator.tsx","../src/components/ToolConfirmation.tsx"],"names":["useRef","createChatController","useEffect","useSyncExternalStore","Box","jsxs","jsx","Text","useInput","Fragment"],"mappings":"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","file":"index.cjs","sourcesContent":["// NOTE: This hook is intentionally duplicated from @agentskit/react (packages/react/src/useChat.ts).\n// The two packages are React siblings and cannot cross-depend, so the hook is kept in sync\n// manually. A sync-guard test at packages/ink/tests/useChat-sync.test.ts will fail if they drift.\n// When changing this file, mirror the same change in packages/react/src/useChat.ts.\nimport { useEffect, useRef, useSyncExternalStore } from 'react'\nimport { createChatController } from '@agentskit/core'\nimport type { ChatConfig, ChatController, ChatReturn } from '@agentskit/core'\n\nexport function useChat(config: ChatConfig): ChatReturn {\n const controllerRef = useRef<ChatController | null>(null)\n\n if (!controllerRef.current) {\n controllerRef.current = createChatController(config)\n }\n\n useEffect(() => {\n controllerRef.current?.updateConfig(config)\n }, [config])\n\n const state = useSyncExternalStore(\n controllerRef.current.subscribe,\n controllerRef.current.getState,\n controllerRef.current.getState\n )\n\n return {\n ...state,\n send: controllerRef.current.send,\n stop: controllerRef.current.stop,\n retry: controllerRef.current.retry,\n setInput: controllerRef.current.setInput,\n clear: controllerRef.current.clear,\n approve: controllerRef.current.approve,\n deny: controllerRef.current.deny,\n }\n}\n","import React, { type ReactNode } from 'react'\nimport { Box } from 'ink'\n\nexport interface ChatContainerProps {\n children: ReactNode\n}\n\nexport function ChatContainer({ children }: ChatContainerProps) {\n return (\n <Box flexDirection=\"column\" gap={1}>\n {children}\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { Message as MessageType } from '@agentskit/core'\n\nexport interface MessageProps {\n message: MessageType\n}\n\nfunction roleColor(role: MessageType['role']) {\n switch (role) {\n case 'assistant':\n return 'cyan'\n case 'user':\n return 'green'\n case 'system':\n return 'yellow'\n case 'tool':\n return 'magenta'\n default:\n return 'white'\n }\n}\n\nexport function Message({ message }: MessageProps) {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={roleColor(message.role)}>\n {message.role.toUpperCase()}\n </Text>\n <Text>{message.content || (message.status === 'streaming' ? '...' : '')}</Text>\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text, useInput } from 'ink'\nimport type { ChatReturn } from '@agentskit/core'\n\nexport interface InputBarProps {\n chat: ChatReturn\n placeholder?: string\n disabled?: boolean\n}\n\nexport function InputBar({ chat, placeholder = 'Type a message...', disabled = false }: InputBarProps) {\n useInput((input, key) => {\n if (disabled || chat.status === 'streaming') return\n\n if (key.return) {\n if (chat.input.trim()) {\n void chat.send(chat.input)\n }\n return\n }\n\n if (key.backspace || key.delete) {\n chat.setInput(chat.input.slice(0, -1))\n return\n }\n\n if (input && !key.ctrl && !key.meta) {\n chat.setInput(`${chat.input}${input}`)\n }\n })\n\n return (\n <Box flexDirection=\"column\">\n <Text dimColor>{placeholder}</Text>\n <Text color={disabled ? 'gray' : 'white'}>\n > {chat.input}\n </Text>\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { ToolCall } from '@agentskit/core'\n\nexport interface ToolCallViewProps {\n toolCall: ToolCall\n expanded?: boolean\n}\n\nexport function ToolCallView({ toolCall, expanded = false }: ToolCallViewProps) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" paddingX={1}>\n <Text color=\"magenta\">\n Tool: {toolCall.name} [{toolCall.status}]\n </Text>\n {expanded ? (\n <>\n <Text dimColor>{JSON.stringify(toolCall.args)}</Text>\n {toolCall.result ? <Text>{toolCall.result}</Text> : null}\n {toolCall.error ? <Text color=\"red\">{toolCall.error}</Text> : null}\n </>\n ) : null}\n </Box>\n )\n}\n","import React from 'react'\nimport { Text } from 'ink'\n\nexport interface ThinkingIndicatorProps {\n visible: boolean\n label?: string\n}\n\nexport function ThinkingIndicator({ visible, label = 'Thinking...' }: ThinkingIndicatorProps) {\n if (!visible) return null\n return <Text color=\"yellow\">{label}</Text>\n}\n","import React from 'react'\nimport { Box, Text, useInput } from 'ink'\nimport type { ToolCall } from '@agentskit/core'\n\nexport interface ToolConfirmationProps {\n toolCall: ToolCall\n onApprove: (toolCallId: string) => void\n onDeny: (toolCallId: string, reason?: string) => void\n}\n\nexport function ToolConfirmation({ toolCall, onApprove, onDeny }: ToolConfirmationProps) {\n useInput((input) => {\n if (toolCall.status !== 'requires_confirmation') return\n if (input.toLowerCase() === 'y') onApprove(toolCall.id)\n if (input.toLowerCase() === 'n') onDeny(toolCall.id)\n })\n\n if (toolCall.status !== 'requires_confirmation') return null\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" paddingX={1} borderColor=\"yellow\">\n <Text color=\"yellow\" bold>\n Confirm: {toolCall.name}\n </Text>\n <Text dimColor>{JSON.stringify(toolCall.args)}</Text>\n <Text color=\"yellow\">Allow? (y/n)</Text>\n </Box>\n )\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -34,4 +34,11 @@ interface ThinkingIndicatorProps {
|
|
|
34
34
|
}
|
|
35
35
|
declare function ThinkingIndicator({ visible, label }: ThinkingIndicatorProps): react_jsx_runtime.JSX.Element | null;
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
interface ToolConfirmationProps {
|
|
38
|
+
toolCall: ToolCall;
|
|
39
|
+
onApprove: (toolCallId: string) => void;
|
|
40
|
+
onDeny: (toolCallId: string, reason?: string) => void;
|
|
41
|
+
}
|
|
42
|
+
declare function ToolConfirmation({ toolCall, onApprove, onDeny }: ToolConfirmationProps): react_jsx_runtime.JSX.Element | null;
|
|
43
|
+
|
|
44
|
+
export { ChatContainer, type ChatContainerProps, InputBar, type InputBarProps, Message, type MessageProps, ThinkingIndicator, type ThinkingIndicatorProps, ToolCallView, type ToolCallViewProps, ToolConfirmation, type ToolConfirmationProps, useChat };
|
package/dist/index.d.ts
CHANGED
|
@@ -34,4 +34,11 @@ interface ThinkingIndicatorProps {
|
|
|
34
34
|
}
|
|
35
35
|
declare function ThinkingIndicator({ visible, label }: ThinkingIndicatorProps): react_jsx_runtime.JSX.Element | null;
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
interface ToolConfirmationProps {
|
|
38
|
+
toolCall: ToolCall;
|
|
39
|
+
onApprove: (toolCallId: string) => void;
|
|
40
|
+
onDeny: (toolCallId: string, reason?: string) => void;
|
|
41
|
+
}
|
|
42
|
+
declare function ToolConfirmation({ toolCall, onApprove, onDeny }: ToolConfirmationProps): react_jsx_runtime.JSX.Element | null;
|
|
43
|
+
|
|
44
|
+
export { ChatContainer, type ChatContainerProps, InputBar, type InputBarProps, Message, type MessageProps, ThinkingIndicator, type ThinkingIndicatorProps, ToolCallView, type ToolCallViewProps, ToolConfirmation, type ToolConfirmationProps, useChat };
|
package/dist/index.js
CHANGED
|
@@ -24,7 +24,9 @@ function useChat(config) {
|
|
|
24
24
|
stop: controllerRef.current.stop,
|
|
25
25
|
retry: controllerRef.current.retry,
|
|
26
26
|
setInput: controllerRef.current.setInput,
|
|
27
|
-
clear: controllerRef.current.clear
|
|
27
|
+
clear: controllerRef.current.clear,
|
|
28
|
+
approve: controllerRef.current.approve,
|
|
29
|
+
deny: controllerRef.current.deny
|
|
28
30
|
};
|
|
29
31
|
}
|
|
30
32
|
function ChatContainer({ children }) {
|
|
@@ -95,7 +97,23 @@ function ThinkingIndicator({ visible, label = "Thinking..." }) {
|
|
|
95
97
|
if (!visible) return null;
|
|
96
98
|
return /* @__PURE__ */ jsx(Text, { color: "yellow", children: label });
|
|
97
99
|
}
|
|
100
|
+
function ToolConfirmation({ toolCall, onApprove, onDeny }) {
|
|
101
|
+
useInput((input) => {
|
|
102
|
+
if (toolCall.status !== "requires_confirmation") return;
|
|
103
|
+
if (input.toLowerCase() === "y") onApprove(toolCall.id);
|
|
104
|
+
if (input.toLowerCase() === "n") onDeny(toolCall.id);
|
|
105
|
+
});
|
|
106
|
+
if (toolCall.status !== "requires_confirmation") return null;
|
|
107
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", paddingX: 1, borderColor: "yellow", children: [
|
|
108
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", bold: true, children: [
|
|
109
|
+
"Confirm: ",
|
|
110
|
+
toolCall.name
|
|
111
|
+
] }),
|
|
112
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: JSON.stringify(toolCall.args) }),
|
|
113
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", children: "Allow? (y/n)" })
|
|
114
|
+
] });
|
|
115
|
+
}
|
|
98
116
|
|
|
99
|
-
export { ChatContainer, InputBar, Message, ThinkingIndicator, ToolCallView, useChat };
|
|
117
|
+
export { ChatContainer, InputBar, Message, ThinkingIndicator, ToolCallView, ToolConfirmation, useChat };
|
|
100
118
|
//# sourceMappingURL=index.js.map
|
|
101
119
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/useChat.ts","../src/components/ChatContainer.tsx","../src/components/Message.tsx","../src/components/InputBar.tsx","../src/components/ToolCallView.tsx","../src/components/ThinkingIndicator.tsx"],"names":["Box","jsx","jsxs","Text"],"mappings":"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","file":"index.js","sourcesContent":["// NOTE: This hook is identical in @agentskit/react and @agentskit/ink.\n// Changes here must be mirrored in packages/react/src/useChat.ts.\nimport { useEffect, useRef, useSyncExternalStore } from 'react'\nimport { createChatController } from '@agentskit/core'\nimport type { ChatConfig, ChatController, ChatReturn } from '@agentskit/core'\n\nexport function useChat(config: ChatConfig): ChatReturn {\n const controllerRef = useRef<ChatController | null>(null)\n\n if (!controllerRef.current) {\n controllerRef.current = createChatController(config)\n }\n\n useEffect(() => {\n controllerRef.current?.updateConfig(config)\n }, [config])\n\n const state = useSyncExternalStore(\n controllerRef.current.subscribe,\n controllerRef.current.getState,\n controllerRef.current.getState\n )\n\n return {\n ...state,\n send: controllerRef.current.send,\n stop: controllerRef.current.stop,\n retry: controllerRef.current.retry,\n setInput: controllerRef.current.setInput,\n clear: controllerRef.current.clear,\n }\n}\n","import React, { type ReactNode } from 'react'\nimport { Box } from 'ink'\n\nexport interface ChatContainerProps {\n children: ReactNode\n}\n\nexport function ChatContainer({ children }: ChatContainerProps) {\n return (\n <Box flexDirection=\"column\" gap={1}>\n {children}\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { Message as MessageType } from '@agentskit/core'\n\nexport interface MessageProps {\n message: MessageType\n}\n\nfunction roleColor(role: MessageType['role']) {\n switch (role) {\n case 'assistant':\n return 'cyan'\n case 'user':\n return 'green'\n case 'system':\n return 'yellow'\n case 'tool':\n return 'magenta'\n default:\n return 'white'\n }\n}\n\nexport function Message({ message }: MessageProps) {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={roleColor(message.role)}>\n {message.role.toUpperCase()}\n </Text>\n <Text>{message.content || (message.status === 'streaming' ? '...' : '')}</Text>\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text, useInput } from 'ink'\nimport type { ChatReturn } from '@agentskit/core'\n\nexport interface InputBarProps {\n chat: ChatReturn\n placeholder?: string\n disabled?: boolean\n}\n\nexport function InputBar({ chat, placeholder = 'Type a message...', disabled = false }: InputBarProps) {\n useInput((input, key) => {\n if (disabled || chat.status === 'streaming') return\n\n if (key.return) {\n if (chat.input.trim()) {\n void chat.send(chat.input)\n }\n return\n }\n\n if (key.backspace || key.delete) {\n chat.setInput(chat.input.slice(0, -1))\n return\n }\n\n if (input && !key.ctrl && !key.meta) {\n chat.setInput(`${chat.input}${input}`)\n }\n })\n\n return (\n <Box flexDirection=\"column\">\n <Text dimColor>{placeholder}</Text>\n <Text color={disabled ? 'gray' : 'white'}>\n > {chat.input}\n </Text>\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { ToolCall } from '@agentskit/core'\n\nexport interface ToolCallViewProps {\n toolCall: ToolCall\n expanded?: boolean\n}\n\nexport function ToolCallView({ toolCall, expanded = false }: ToolCallViewProps) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" paddingX={1}>\n <Text color=\"magenta\">\n Tool: {toolCall.name} [{toolCall.status}]\n </Text>\n {expanded ? (\n <>\n <Text dimColor>{JSON.stringify(toolCall.args)}</Text>\n {toolCall.result ? <Text>{toolCall.result}</Text> : null}\n {toolCall.error ? <Text color=\"red\">{toolCall.error}</Text> : null}\n </>\n ) : null}\n </Box>\n )\n}\n","import React from 'react'\nimport { Text } from 'ink'\n\nexport interface ThinkingIndicatorProps {\n visible: boolean\n label?: string\n}\n\nexport function ThinkingIndicator({ visible, label = 'Thinking...' }: ThinkingIndicatorProps) {\n if (!visible) return null\n return <Text color=\"yellow\">{label}</Text>\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/useChat.ts","../src/components/ChatContainer.tsx","../src/components/Message.tsx","../src/components/InputBar.tsx","../src/components/ToolCallView.tsx","../src/components/ThinkingIndicator.tsx","../src/components/ToolConfirmation.tsx"],"names":["Box","jsx","jsxs","Text","useInput"],"mappings":"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","file":"index.js","sourcesContent":["// NOTE: This hook is intentionally duplicated from @agentskit/react (packages/react/src/useChat.ts).\n// The two packages are React siblings and cannot cross-depend, so the hook is kept in sync\n// manually. A sync-guard test at packages/ink/tests/useChat-sync.test.ts will fail if they drift.\n// When changing this file, mirror the same change in packages/react/src/useChat.ts.\nimport { useEffect, useRef, useSyncExternalStore } from 'react'\nimport { createChatController } from '@agentskit/core'\nimport type { ChatConfig, ChatController, ChatReturn } from '@agentskit/core'\n\nexport function useChat(config: ChatConfig): ChatReturn {\n const controllerRef = useRef<ChatController | null>(null)\n\n if (!controllerRef.current) {\n controllerRef.current = createChatController(config)\n }\n\n useEffect(() => {\n controllerRef.current?.updateConfig(config)\n }, [config])\n\n const state = useSyncExternalStore(\n controllerRef.current.subscribe,\n controllerRef.current.getState,\n controllerRef.current.getState\n )\n\n return {\n ...state,\n send: controllerRef.current.send,\n stop: controllerRef.current.stop,\n retry: controllerRef.current.retry,\n setInput: controllerRef.current.setInput,\n clear: controllerRef.current.clear,\n approve: controllerRef.current.approve,\n deny: controllerRef.current.deny,\n }\n}\n","import React, { type ReactNode } from 'react'\nimport { Box } from 'ink'\n\nexport interface ChatContainerProps {\n children: ReactNode\n}\n\nexport function ChatContainer({ children }: ChatContainerProps) {\n return (\n <Box flexDirection=\"column\" gap={1}>\n {children}\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { Message as MessageType } from '@agentskit/core'\n\nexport interface MessageProps {\n message: MessageType\n}\n\nfunction roleColor(role: MessageType['role']) {\n switch (role) {\n case 'assistant':\n return 'cyan'\n case 'user':\n return 'green'\n case 'system':\n return 'yellow'\n case 'tool':\n return 'magenta'\n default:\n return 'white'\n }\n}\n\nexport function Message({ message }: MessageProps) {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={roleColor(message.role)}>\n {message.role.toUpperCase()}\n </Text>\n <Text>{message.content || (message.status === 'streaming' ? '...' : '')}</Text>\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text, useInput } from 'ink'\nimport type { ChatReturn } from '@agentskit/core'\n\nexport interface InputBarProps {\n chat: ChatReturn\n placeholder?: string\n disabled?: boolean\n}\n\nexport function InputBar({ chat, placeholder = 'Type a message...', disabled = false }: InputBarProps) {\n useInput((input, key) => {\n if (disabled || chat.status === 'streaming') return\n\n if (key.return) {\n if (chat.input.trim()) {\n void chat.send(chat.input)\n }\n return\n }\n\n if (key.backspace || key.delete) {\n chat.setInput(chat.input.slice(0, -1))\n return\n }\n\n if (input && !key.ctrl && !key.meta) {\n chat.setInput(`${chat.input}${input}`)\n }\n })\n\n return (\n <Box flexDirection=\"column\">\n <Text dimColor>{placeholder}</Text>\n <Text color={disabled ? 'gray' : 'white'}>\n > {chat.input}\n </Text>\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { ToolCall } from '@agentskit/core'\n\nexport interface ToolCallViewProps {\n toolCall: ToolCall\n expanded?: boolean\n}\n\nexport function ToolCallView({ toolCall, expanded = false }: ToolCallViewProps) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" paddingX={1}>\n <Text color=\"magenta\">\n Tool: {toolCall.name} [{toolCall.status}]\n </Text>\n {expanded ? (\n <>\n <Text dimColor>{JSON.stringify(toolCall.args)}</Text>\n {toolCall.result ? <Text>{toolCall.result}</Text> : null}\n {toolCall.error ? <Text color=\"red\">{toolCall.error}</Text> : null}\n </>\n ) : null}\n </Box>\n )\n}\n","import React from 'react'\nimport { Text } from 'ink'\n\nexport interface ThinkingIndicatorProps {\n visible: boolean\n label?: string\n}\n\nexport function ThinkingIndicator({ visible, label = 'Thinking...' }: ThinkingIndicatorProps) {\n if (!visible) return null\n return <Text color=\"yellow\">{label}</Text>\n}\n","import React from 'react'\nimport { Box, Text, useInput } from 'ink'\nimport type { ToolCall } from '@agentskit/core'\n\nexport interface ToolConfirmationProps {\n toolCall: ToolCall\n onApprove: (toolCallId: string) => void\n onDeny: (toolCallId: string, reason?: string) => void\n}\n\nexport function ToolConfirmation({ toolCall, onApprove, onDeny }: ToolConfirmationProps) {\n useInput((input) => {\n if (toolCall.status !== 'requires_confirmation') return\n if (input.toLowerCase() === 'y') onApprove(toolCall.id)\n if (input.toLowerCase() === 'n') onDeny(toolCall.id)\n })\n\n if (toolCall.status !== 'requires_confirmation') return null\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" paddingX={1} borderColor=\"yellow\">\n <Text color=\"yellow\" bold>\n Confirm: {toolCall.name}\n </Text>\n <Text dimColor>{JSON.stringify(toolCall.args)}</Text>\n <Text color=\"yellow\">Allow? (y/n)</Text>\n </Box>\n )\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentskit/ink",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Ink terminal components and hooks for AgentsKit.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agentskit",
|
|
7
|
+
"ai",
|
|
8
|
+
"agents",
|
|
9
|
+
"llm",
|
|
10
|
+
"chat",
|
|
11
|
+
"typescript",
|
|
12
|
+
"ink",
|
|
13
|
+
"terminal",
|
|
14
|
+
"cli"
|
|
15
|
+
],
|
|
5
16
|
"type": "module",
|
|
6
17
|
"main": "./dist/index.cjs",
|
|
7
18
|
"module": "./dist/index.js",
|
|
@@ -17,19 +28,19 @@
|
|
|
17
28
|
"dist"
|
|
18
29
|
],
|
|
19
30
|
"dependencies": {
|
|
20
|
-
"ink": "^
|
|
21
|
-
"@agentskit/core": "0.4.
|
|
31
|
+
"ink": "^6.8.0",
|
|
32
|
+
"@agentskit/core": "0.4.2"
|
|
22
33
|
},
|
|
23
34
|
"peerDependencies": {
|
|
24
35
|
"react": ">=18.0.0"
|
|
25
36
|
},
|
|
26
37
|
"devDependencies": {
|
|
27
|
-
"@types/node": "^
|
|
28
|
-
"@types/react": "^
|
|
38
|
+
"@types/node": "^25.5.2",
|
|
39
|
+
"@types/react": "^19.2.14",
|
|
29
40
|
"ink-testing-library": "^4.0.0",
|
|
30
|
-
"react": "^
|
|
41
|
+
"react": "^19.2.4",
|
|
31
42
|
"tsup": "^8.5.0",
|
|
32
|
-
"typescript": "^
|
|
43
|
+
"typescript": "^6.0.2",
|
|
33
44
|
"vitest": "^4.1.2"
|
|
34
45
|
},
|
|
35
46
|
"publishConfig": {
|