@abacus-ai/cli 2.0.0-canary.1 → 2.0.0-canary.3
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/index.mjs +450 -422
- package/package.json +4 -1
- package/.oxlintrc.json +0 -8
- package/resources/abacus.ico +0 -0
- package/resources/entitlements.plist +0 -9
- package/src/__e2e__/README.md +0 -196
- package/src/__e2e__/agent-interactions.e2e.test.tsx +0 -61
- package/src/__e2e__/cli-commands.e2e.test.tsx +0 -77
- package/src/__e2e__/conversation-throttle.e2e.test.ts +0 -453
- package/src/__e2e__/conversation.e2e.test.tsx +0 -56
- package/src/__e2e__/diff-preview.e2e.test.tsx +0 -3399
- package/src/__e2e__/file-creation.e2e.test.tsx +0 -149
- package/src/__e2e__/helpers/test-helpers.ts +0 -449
- package/src/__e2e__/keyboard-navigation.e2e.test.tsx +0 -34
- package/src/__e2e__/llm-models.e2e.test.ts +0 -402
- package/src/__e2e__/mcp/mcp-callback-flow.e2e.test.tsx +0 -71
- package/src/__e2e__/mcp/mcp-full-app-ui.e2e.test.tsx +0 -167
- package/src/__e2e__/mcp/mcp-ui-rendering.e2e.test.tsx +0 -185
- package/src/__e2e__/repl.e2e.test.tsx +0 -78
- package/src/__e2e__/shell-compatibility.e2e.test.tsx +0 -76
- package/src/__e2e__/theme-mcp.e2e.test.tsx +0 -98
- package/src/__e2e__/tool-permissions.e2e.test.tsx +0 -66
- package/src/args.ts +0 -22
- package/src/components/__tests__/react-compiler.test.tsx +0 -78
- package/src/components/__tests__/status-indicator.test.tsx +0 -403
- package/src/components/composer/__tests__/bash-runner.test.tsx +0 -263
- package/src/components/composer/agent-mode-indicator.tsx +0 -63
- package/src/components/composer/bash-runner.tsx +0 -54
- package/src/components/composer/commands/default-commands.tsx +0 -615
- package/src/components/composer/commands/handler.tsx +0 -59
- package/src/components/composer/commands/picker.tsx +0 -273
- package/src/components/composer/commands/registry.ts +0 -233
- package/src/components/composer/commands/types.ts +0 -33
- package/src/components/composer/context.tsx +0 -88
- package/src/components/composer/file-mention-picker.tsx +0 -83
- package/src/components/composer/help.tsx +0 -44
- package/src/components/composer/index.tsx +0 -1007
- package/src/components/composer/mentions.ts +0 -57
- package/src/components/composer/message-queue.tsx +0 -70
- package/src/components/composer/mode-panel.tsx +0 -35
- package/src/components/composer/modes/__tests__/bash-handler.test.tsx +0 -755
- package/src/components/composer/modes/__tests__/bash-renderer.test.tsx +0 -1108
- package/src/components/composer/modes/bash-handler.tsx +0 -132
- package/src/components/composer/modes/bash-renderer.tsx +0 -175
- package/src/components/composer/modes/default-handlers.tsx +0 -33
- package/src/components/composer/modes/index.ts +0 -41
- package/src/components/composer/modes/types.ts +0 -21
- package/src/components/composer/persistent-shell.ts +0 -283
- package/src/components/composer/process.ts +0 -65
- package/src/components/composer/types.ts +0 -9
- package/src/components/composer/use-mention-search.ts +0 -68
- package/src/components/error-boundry.tsx +0 -60
- package/src/components/exit-message.tsx +0 -29
- package/src/components/expanded-view.tsx +0 -74
- package/src/components/file-completion.tsx +0 -127
- package/src/components/header.tsx +0 -47
- package/src/components/logo.tsx +0 -37
- package/src/components/segments.tsx +0 -356
- package/src/components/status-indicator.tsx +0 -306
- package/src/components/tool-group-summary.tsx +0 -263
- package/src/components/tool-permissions/ask-user-question-permission-ui.tsx +0 -319
- package/src/components/tool-permissions/diff-preview.tsx +0 -359
- package/src/components/tool-permissions/index.ts +0 -5
- package/src/components/tool-permissions/permission-options.tsx +0 -401
- package/src/components/tool-permissions/permission-preview-header.tsx +0 -57
- package/src/components/tool-permissions/tool-permission-ui.tsx +0 -420
- package/src/components/tools/agent/ask-user-question.tsx +0 -107
- package/src/components/tools/agent/enter-plan-mode.tsx +0 -55
- package/src/components/tools/agent/exit-plan-mode.tsx +0 -83
- package/src/components/tools/agent/handoff-to-main.tsx +0 -27
- package/src/components/tools/agent/subagent.tsx +0 -37
- package/src/components/tools/agent/todo-write.tsx +0 -104
- package/src/components/tools/browser/close-tab.tsx +0 -58
- package/src/components/tools/browser/computer.tsx +0 -70
- package/src/components/tools/browser/get-interactive-elements.tsx +0 -54
- package/src/components/tools/browser/get-tab-content.tsx +0 -51
- package/src/components/tools/browser/navigate-to.tsx +0 -59
- package/src/components/tools/browser/new-tab.tsx +0 -60
- package/src/components/tools/browser/perform-action.tsx +0 -63
- package/src/components/tools/browser/refresh-tab.tsx +0 -43
- package/src/components/tools/browser/switch-tab.tsx +0 -58
- package/src/components/tools/filesystem/delete-file.tsx +0 -104
- package/src/components/tools/filesystem/edit.tsx +0 -220
- package/src/components/tools/filesystem/list-dir.tsx +0 -78
- package/src/components/tools/filesystem/read-file.tsx +0 -180
- package/src/components/tools/filesystem/upload-image.tsx +0 -76
- package/src/components/tools/ide/ide-diagnostics.tsx +0 -62
- package/src/components/tools/index.ts +0 -91
- package/src/components/tools/mcp/mcp-tool.tsx +0 -158
- package/src/components/tools/search/fetch-url.tsx +0 -73
- package/src/components/tools/search/file-search.tsx +0 -78
- package/src/components/tools/search/grep.tsx +0 -90
- package/src/components/tools/search/semantic-search.tsx +0 -66
- package/src/components/tools/search/web-search.tsx +0 -71
- package/src/components/tools/shared/index.tsx +0 -48
- package/src/components/tools/shared/zod-coercion.ts +0 -35
- package/src/components/tools/terminal/bash-tool-output.tsx +0 -188
- package/src/components/tools/terminal/get-terminal-output.tsx +0 -91
- package/src/components/tools/terminal/run-in-terminal.tsx +0 -131
- package/src/components/tools/types.ts +0 -16
- package/src/components/tools.tsx +0 -68
- package/src/components/ui/__tests__/divider.test.tsx +0 -61
- package/src/components/ui/__tests__/gradient.test.tsx +0 -125
- package/src/components/ui/__tests__/input.test.tsx +0 -166
- package/src/components/ui/__tests__/select.test.tsx +0 -273
- package/src/components/ui/__tests__/shimmer.test.tsx +0 -99
- package/src/components/ui/blinking-indicator.tsx +0 -27
- package/src/components/ui/divider.tsx +0 -162
- package/src/components/ui/gradient.tsx +0 -56
- package/src/components/ui/input.tsx +0 -228
- package/src/components/ui/select.tsx +0 -151
- package/src/components/ui/shimmer.tsx +0 -76
- package/src/context/agent-mode.tsx +0 -95
- package/src/context/extension-file.tsx +0 -136
- package/src/context/network-activity.tsx +0 -45
- package/src/context/notification.tsx +0 -62
- package/src/context/shell-size.tsx +0 -49
- package/src/context/shell-title.tsx +0 -38
- package/src/entrypoints/print-mode.ts +0 -312
- package/src/entrypoints/repl.tsx +0 -389
- package/src/hooks/use-agent.ts +0 -15
- package/src/hooks/use-api-client.ts +0 -1
- package/src/hooks/use-available-height.ts +0 -8
- package/src/hooks/use-cleanup.ts +0 -29
- package/src/hooks/use-interrupt-manager.ts +0 -242
- package/src/hooks/use-models.ts +0 -22
- package/src/index.ts +0 -217
- package/src/lib/__tests__/ansi.test.ts +0 -255
- package/src/lib/__tests__/cli.test.ts +0 -122
- package/src/lib/__tests__/commands.test.ts +0 -325
- package/src/lib/__tests__/constants.test.ts +0 -15
- package/src/lib/__tests__/focusables.test.ts +0 -25
- package/src/lib/__tests__/fs.test.ts +0 -231
- package/src/lib/__tests__/markdown.test.tsx +0 -348
- package/src/lib/__tests__/mcpCommandHandler.test.ts +0 -173
- package/src/lib/__tests__/mcpManagement.test.ts +0 -38
- package/src/lib/__tests__/path-paste.test.ts +0 -144
- package/src/lib/__tests__/path.test.ts +0 -300
- package/src/lib/__tests__/queries.test.ts +0 -39
- package/src/lib/__tests__/standaloneMcpService.test.ts +0 -71
- package/src/lib/__tests__/text-buffer.test.ts +0 -328
- package/src/lib/__tests__/text-utils.test.ts +0 -32
- package/src/lib/__tests__/timing.test.ts +0 -78
- package/src/lib/__tests__/utils.test.ts +0 -238
- package/src/lib/__tests__/vim-buffer-actions.test.ts +0 -154
- package/src/lib/ansi.ts +0 -150
- package/src/lib/cli-push-server.ts +0 -112
- package/src/lib/cli.ts +0 -44
- package/src/lib/clipboard.ts +0 -226
- package/src/lib/command-utils.ts +0 -93
- package/src/lib/commands.ts +0 -270
- package/src/lib/constants.ts +0 -3
- package/src/lib/extension-connection.ts +0 -181
- package/src/lib/focusables.ts +0 -7
- package/src/lib/fs.ts +0 -533
- package/src/lib/markdown/code-block.tsx +0 -63
- package/src/lib/markdown/index.ts +0 -4
- package/src/lib/markdown/link.tsx +0 -19
- package/src/lib/markdown/markdown.tsx +0 -372
- package/src/lib/markdown/types.ts +0 -15
- package/src/lib/mcpCommandHandler.ts +0 -121
- package/src/lib/mcpManagement.ts +0 -44
- package/src/lib/path-paste.ts +0 -185
- package/src/lib/path.ts +0 -179
- package/src/lib/queries.ts +0 -15
- package/src/lib/standaloneMcpService.ts +0 -688
- package/src/lib/status-utils.ts +0 -237
- package/src/lib/test-utils.tsx +0 -72
- package/src/lib/text-buffer.ts +0 -2415
- package/src/lib/text-utils.ts +0 -272
- package/src/lib/timing.ts +0 -63
- package/src/lib/types.ts +0 -295
- package/src/lib/utils.ts +0 -182
- package/src/lib/vim-buffer-actions.ts +0 -732
- package/src/providers/agent.tsx +0 -1063
- package/src/providers/api-client.tsx +0 -43
- package/src/services/logger.ts +0 -85
- package/src/terminal/detection.ts +0 -187
- package/src/terminal/exit.ts +0 -279
- package/src/terminal/notification.ts +0 -83
- package/src/terminal/progress.ts +0 -201
- package/src/terminal/setup.ts +0 -797
- package/src/terminal/types.ts +0 -51
- package/src/theme/context.tsx +0 -57
- package/src/theme/index.ts +0 -4
- package/src/theme/themed.tsx +0 -35
- package/src/theme/themes.json +0 -546
- package/src/theme/types.ts +0 -110
- package/src/tools/types.ts +0 -59
- package/src/tools/utils/__tests__/zod-coercion.test.ts +0 -33
- package/src/tools/utils/tool-ui-components.tsx +0 -649
- package/src/tools/utils/zod-coercion.ts +0 -35
- package/tsconfig.json +0 -16
- package/tsconfig.node.json +0 -29
- package/tsconfig.test.json +0 -27
- package/tsdown.config.ts +0 -17
- package/vitest.config.ts +0 -76
package/src/hooks/use-agent.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { use } from "react";
|
|
2
|
-
|
|
3
|
-
import { AgentContext, AgentProvider } from "../providers/agent.js";
|
|
4
|
-
|
|
5
|
-
export function useAgent() {
|
|
6
|
-
const agent = use(AgentContext);
|
|
7
|
-
|
|
8
|
-
if (!agent) {
|
|
9
|
-
throw new Error(
|
|
10
|
-
`Agent context not found. Did you forget to wrap your component in <${AgentProvider.name}>?`,
|
|
11
|
-
);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return agent;
|
|
15
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { useApiClient } from "../providers/api-client.js";
|
package/src/hooks/use-cleanup.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { useEffect, useRef } from "react";
|
|
2
|
-
|
|
3
|
-
export function useCleanup(callback: () => void) {
|
|
4
|
-
const cleaningUpRef = useRef(false);
|
|
5
|
-
const callbackRef = useRef(callback);
|
|
6
|
-
|
|
7
|
-
useEffect(() => {
|
|
8
|
-
callbackRef.current = callback;
|
|
9
|
-
}, [callback]);
|
|
10
|
-
|
|
11
|
-
useEffect(() => {
|
|
12
|
-
const cleanup = () => {
|
|
13
|
-
if (cleaningUpRef.current) {
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
cleaningUpRef.current = true;
|
|
17
|
-
callbackRef.current();
|
|
18
|
-
};
|
|
19
|
-
process.on("exit", cleanup);
|
|
20
|
-
process.on("SIGINT", cleanup);
|
|
21
|
-
process.on("SIGTERM", cleanup);
|
|
22
|
-
return () => {
|
|
23
|
-
cleanup();
|
|
24
|
-
process.off("exit", cleanup);
|
|
25
|
-
process.off("SIGINT", cleanup);
|
|
26
|
-
process.off("SIGTERM", cleanup);
|
|
27
|
-
};
|
|
28
|
-
}, []);
|
|
29
|
-
}
|
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
import { useInput, type Key } from "@codellm/jar";
|
|
2
|
-
import { useCallback, useEffect, useEffectEvent, useRef, useState } from "react";
|
|
3
|
-
|
|
4
|
-
import { AgentStatus } from "../providers/agent.js";
|
|
5
|
-
|
|
6
|
-
export interface InterruptHints {
|
|
7
|
-
/** "ESC again to clear" shown bottom-right of composer */
|
|
8
|
-
escClear: boolean;
|
|
9
|
-
/** "Press Ctrl+C/D again to exit" shown bottom-left */
|
|
10
|
-
exitKey: "c" | "d" | null;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
type InterruptContext =
|
|
14
|
-
| "tool-executing"
|
|
15
|
-
| "streaming"
|
|
16
|
-
| "permission-ui"
|
|
17
|
-
| "idle-with-text"
|
|
18
|
-
| "idle-empty";
|
|
19
|
-
|
|
20
|
-
interface UseInterruptManagerProps {
|
|
21
|
-
agentStatus: AgentStatus;
|
|
22
|
-
hasPendingPermission: boolean;
|
|
23
|
-
composerHasText: () => boolean;
|
|
24
|
-
hasQueuedMessages: () => boolean;
|
|
25
|
-
// Actions
|
|
26
|
-
stopAgent: () => void;
|
|
27
|
-
rejectPermission: () => void;
|
|
28
|
-
saveAndClearComposer: () => void;
|
|
29
|
-
clearComposer: () => void;
|
|
30
|
-
dequeueOne: () => void; // pop one queued message (for ESC)
|
|
31
|
-
clearQueue: () => void; // clear all queued messages (for Ctrl+C/D)
|
|
32
|
-
exitApp: () => void;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const HINT_TIMEOUT = 2_000;
|
|
36
|
-
|
|
37
|
-
function deriveContext(
|
|
38
|
-
agentStatus: AgentStatus,
|
|
39
|
-
hasPendingPermission: boolean,
|
|
40
|
-
composerHasText: () => boolean,
|
|
41
|
-
): InterruptContext {
|
|
42
|
-
if (agentStatus === AgentStatus.ExecutingTool) return "tool-executing";
|
|
43
|
-
if (agentStatus === AgentStatus.Submitted || agentStatus === AgentStatus.Streaming)
|
|
44
|
-
return "streaming";
|
|
45
|
-
if (agentStatus === AgentStatus.WaitingForToolPermission && hasPendingPermission)
|
|
46
|
-
return "permission-ui";
|
|
47
|
-
if (composerHasText()) return "idle-with-text";
|
|
48
|
-
return "idle-empty";
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function useInterruptManager(props: UseInterruptManagerProps): InterruptHints {
|
|
52
|
-
const {
|
|
53
|
-
agentStatus,
|
|
54
|
-
hasPendingPermission,
|
|
55
|
-
composerHasText,
|
|
56
|
-
hasQueuedMessages,
|
|
57
|
-
stopAgent,
|
|
58
|
-
rejectPermission,
|
|
59
|
-
saveAndClearComposer,
|
|
60
|
-
clearComposer,
|
|
61
|
-
dequeueOne,
|
|
62
|
-
clearQueue,
|
|
63
|
-
exitApp,
|
|
64
|
-
} = props;
|
|
65
|
-
|
|
66
|
-
const [escClear, setEscClear] = useState(false);
|
|
67
|
-
const [exitKey, setExitKey] = useState<"c" | "d" | null>(null);
|
|
68
|
-
|
|
69
|
-
const escTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
70
|
-
const exitTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
71
|
-
|
|
72
|
-
const clearEscHint = useCallback(() => {
|
|
73
|
-
setEscClear(false);
|
|
74
|
-
if (escTimerRef.current) {
|
|
75
|
-
clearTimeout(escTimerRef.current);
|
|
76
|
-
escTimerRef.current = null;
|
|
77
|
-
}
|
|
78
|
-
}, []);
|
|
79
|
-
|
|
80
|
-
const clearExitHint = useCallback(() => {
|
|
81
|
-
setExitKey(null);
|
|
82
|
-
if (exitTimerRef.current) {
|
|
83
|
-
clearTimeout(exitTimerRef.current);
|
|
84
|
-
exitTimerRef.current = null;
|
|
85
|
-
}
|
|
86
|
-
}, []);
|
|
87
|
-
|
|
88
|
-
const clearAllHints = useCallback(() => {
|
|
89
|
-
clearEscHint();
|
|
90
|
-
clearExitHint();
|
|
91
|
-
}, [clearEscHint, clearExitHint]);
|
|
92
|
-
|
|
93
|
-
// Clear hints when context changes away from idle
|
|
94
|
-
const context = deriveContext(agentStatus, hasPendingPermission, composerHasText);
|
|
95
|
-
const prevContextRef = useRef(context);
|
|
96
|
-
|
|
97
|
-
useEffect(() => {
|
|
98
|
-
const prev = prevContextRef.current;
|
|
99
|
-
prevContextRef.current = context;
|
|
100
|
-
|
|
101
|
-
if (prev !== context) {
|
|
102
|
-
clearAllHints();
|
|
103
|
-
}
|
|
104
|
-
}, [context, clearAllHints]);
|
|
105
|
-
|
|
106
|
-
const handleInput = useEffectEvent((input: string, key: Key) => {
|
|
107
|
-
// Ctrl+Z → suspend (Unix only)
|
|
108
|
-
if (key.ctrl && input === "z") {
|
|
109
|
-
if (process.platform !== "win32") {
|
|
110
|
-
process.kill(process.pid, "SIGTSTP");
|
|
111
|
-
}
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const isEsc = key.escape;
|
|
116
|
-
const isCtrlC = key.ctrl && input === "c";
|
|
117
|
-
const isCtrlD = key.ctrl && input === "d";
|
|
118
|
-
|
|
119
|
-
if (!isEsc && !isCtrlC && !isCtrlD) return;
|
|
120
|
-
|
|
121
|
-
const ctx = deriveContext(agentStatus, hasPendingPermission, composerHasText);
|
|
122
|
-
|
|
123
|
-
// ── Active contexts: immediate action, no hints ──
|
|
124
|
-
if (ctx === "tool-executing" || ctx === "streaming") {
|
|
125
|
-
clearAllHints();
|
|
126
|
-
stopAgent();
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (ctx === "permission-ui") {
|
|
131
|
-
clearAllHints();
|
|
132
|
-
rejectPermission();
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// ── Idle with text ──
|
|
137
|
-
if (ctx === "idle-with-text") {
|
|
138
|
-
if (isEsc) {
|
|
139
|
-
if (escClear) {
|
|
140
|
-
// Second ESC → clear composer
|
|
141
|
-
clearComposer();
|
|
142
|
-
clearAllHints();
|
|
143
|
-
} else {
|
|
144
|
-
// First ESC → show hint
|
|
145
|
-
clearExitHint();
|
|
146
|
-
setEscClear(true);
|
|
147
|
-
escTimerRef.current = setTimeout(() => {
|
|
148
|
-
setEscClear(false);
|
|
149
|
-
escTimerRef.current = null;
|
|
150
|
-
}, HINT_TIMEOUT);
|
|
151
|
-
}
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Ctrl+C or Ctrl+D
|
|
156
|
-
const pressedKey = isCtrlC ? "c" : "d";
|
|
157
|
-
if (exitKey === pressedKey) {
|
|
158
|
-
// Same key pressed again → exit
|
|
159
|
-
clearAllHints();
|
|
160
|
-
exitApp();
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if (exitKey !== null) {
|
|
165
|
-
// Different key → reset to new key
|
|
166
|
-
clearExitHint();
|
|
167
|
-
setExitKey(pressedKey);
|
|
168
|
-
exitTimerRef.current = setTimeout(() => {
|
|
169
|
-
setExitKey(null);
|
|
170
|
-
exitTimerRef.current = null;
|
|
171
|
-
}, HINT_TIMEOUT);
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// First press → save text to history, clear composer, show exit hint
|
|
176
|
-
clearEscHint();
|
|
177
|
-
saveAndClearComposer();
|
|
178
|
-
if (hasQueuedMessages()) {
|
|
179
|
-
clearQueue();
|
|
180
|
-
}
|
|
181
|
-
setExitKey(pressedKey);
|
|
182
|
-
exitTimerRef.current = setTimeout(() => {
|
|
183
|
-
setExitKey(null);
|
|
184
|
-
exitTimerRef.current = null;
|
|
185
|
-
}, HINT_TIMEOUT);
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// ── Idle empty ──
|
|
190
|
-
if (ctx === "idle-empty") {
|
|
191
|
-
if (isEsc) {
|
|
192
|
-
// Dequeue one message at a time
|
|
193
|
-
if (hasQueuedMessages()) {
|
|
194
|
-
dequeueOne();
|
|
195
|
-
}
|
|
196
|
-
// Otherwise no-op
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Ctrl+C or Ctrl+D
|
|
201
|
-
const pressedKey = isCtrlC ? "c" : "d";
|
|
202
|
-
if (exitKey === pressedKey) {
|
|
203
|
-
clearAllHints();
|
|
204
|
-
exitApp();
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (exitKey !== null) {
|
|
209
|
-
// Different key → reset
|
|
210
|
-
clearExitHint();
|
|
211
|
-
setExitKey(pressedKey);
|
|
212
|
-
exitTimerRef.current = setTimeout(() => {
|
|
213
|
-
setExitKey(null);
|
|
214
|
-
exitTimerRef.current = null;
|
|
215
|
-
}, HINT_TIMEOUT);
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Clear all queued messages on first Ctrl+C/D
|
|
220
|
-
if (hasQueuedMessages()) {
|
|
221
|
-
clearQueue();
|
|
222
|
-
}
|
|
223
|
-
setExitKey(pressedKey);
|
|
224
|
-
exitTimerRef.current = setTimeout(() => {
|
|
225
|
-
setExitKey(null);
|
|
226
|
-
exitTimerRef.current = null;
|
|
227
|
-
}, HINT_TIMEOUT);
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
useInput(handleInput, { isActive: true });
|
|
232
|
-
|
|
233
|
-
// Cleanup timers on unmount
|
|
234
|
-
useEffect(() => {
|
|
235
|
-
return () => {
|
|
236
|
-
if (escTimerRef.current) clearTimeout(escTimerRef.current);
|
|
237
|
-
if (exitTimerRef.current) clearTimeout(exitTimerRef.current);
|
|
238
|
-
};
|
|
239
|
-
}, []);
|
|
240
|
-
|
|
241
|
-
return { escClear, exitKey };
|
|
242
|
-
}
|
package/src/hooks/use-models.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { AbacusClient, ILLMOption } from "@codellm/api";
|
|
2
|
-
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
3
|
-
|
|
4
|
-
import { QueryKey } from "../lib/queries.js";
|
|
5
|
-
|
|
6
|
-
export function useModels(apiClient: AbacusClient) {
|
|
7
|
-
return useSuspenseQuery<ILLMOption[]>({
|
|
8
|
-
queryKey: [QueryKey.Models],
|
|
9
|
-
queryFn: async () => {
|
|
10
|
-
try {
|
|
11
|
-
const response = await apiClient.listLLMModels();
|
|
12
|
-
return response?.result ?? [];
|
|
13
|
-
} catch {
|
|
14
|
-
return [];
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
staleTime: 5 * 60 * 1000,
|
|
18
|
-
retry: 1,
|
|
19
|
-
refetchOnMount: "always",
|
|
20
|
-
refetchOnWindowFocus: false,
|
|
21
|
-
});
|
|
22
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { AbacusClient } from "@codellm/api";
|
|
4
|
-
export type { AbacusClient };
|
|
5
|
-
import { AuthManager } from "@codellm/auth";
|
|
6
|
-
import { product } from "@codellm/product";
|
|
7
|
-
import chalk from "chalk";
|
|
8
|
-
import { parseArgs } from "node:util";
|
|
9
|
-
|
|
10
|
-
import packageJson from "@/package.json" with { type: "json" };
|
|
11
|
-
|
|
12
|
-
import type { AgentArgs } from "./args.js";
|
|
13
|
-
|
|
14
|
-
import { runPrintMode } from "./entrypoints/print-mode.js";
|
|
15
|
-
import { runRepl } from "./entrypoints/repl.js";
|
|
16
|
-
import { logger } from "./services/logger.js";
|
|
17
|
-
import { gracefulExit } from "./terminal/exit.js";
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Centralized error handling function
|
|
21
|
-
*/
|
|
22
|
-
function handleError(message: string, exitCode = 1): never {
|
|
23
|
-
console.error(chalk.red(message));
|
|
24
|
-
gracefulExit(exitCode);
|
|
25
|
-
throw new Error(message);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Validates URL format and returns a new URL instance
|
|
30
|
-
*/
|
|
31
|
-
function validateUrl(urlString: string): URL {
|
|
32
|
-
try {
|
|
33
|
-
return new URL(urlString);
|
|
34
|
-
} catch {
|
|
35
|
-
handleError(`Invalid ${product.envPrefix}BASE_URL: ${urlString}`);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Validates agent arguments for print mode requirements
|
|
41
|
-
*/
|
|
42
|
-
function validatePrintModeArgs(agentArgs?: AgentArgs): void {
|
|
43
|
-
const hasFormatFlags = agentArgs?.["output-format"] || agentArgs?.["input-format"];
|
|
44
|
-
if (hasFormatFlags && !agentArgs?.print) {
|
|
45
|
-
handleError("--output-format and --input-format flags can only be used with --print mode");
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Reads input from stdin asynchronously
|
|
51
|
-
*/
|
|
52
|
-
async function readStdinInput(): Promise<string> {
|
|
53
|
-
const stdin = process.stdin;
|
|
54
|
-
|
|
55
|
-
if (stdin.isTTY) {
|
|
56
|
-
handleError(
|
|
57
|
-
"No prompt provided and no piped input detected. Either provide a prompt or pipe input.",
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
let inputData = "";
|
|
62
|
-
for await (const chunk of stdin) {
|
|
63
|
-
inputData += chunk;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const trimmed = inputData.trim();
|
|
67
|
-
if (!trimmed) {
|
|
68
|
-
handleError("No input provided");
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return trimmed;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Resolves the input prompt from args or stdin
|
|
76
|
-
*/
|
|
77
|
-
async function resolveInputPrompt(agentArgs?: AgentArgs): Promise<string> {
|
|
78
|
-
if (agentArgs?.prompt) {
|
|
79
|
-
return agentArgs.prompt;
|
|
80
|
-
}
|
|
81
|
-
return readStdinInput();
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Configures API client with custom base URL if provided
|
|
86
|
-
*/
|
|
87
|
-
async function configureApiClient(apiClient: AbacusClient): Promise<void> {
|
|
88
|
-
const baseUrl = process.env[`${product.envPrefix}BASE_URL`];
|
|
89
|
-
if (!baseUrl) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
validateUrl(baseUrl);
|
|
94
|
-
apiClient.setUrl(baseUrl);
|
|
95
|
-
apiClient.resetEndpoints();
|
|
96
|
-
await apiClient.getApiEndpoint();
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Resolve --resume <id> or --continue into a conversation ID.
|
|
101
|
-
* --resume uses the provided ID directly.
|
|
102
|
-
* --continue fetches the most recently updated conversation from the API.
|
|
103
|
-
*/
|
|
104
|
-
async function resolveConversationId(
|
|
105
|
-
agentArgs: AgentArgs | undefined,
|
|
106
|
-
apiClient: AbacusClient,
|
|
107
|
-
): Promise<string | undefined> {
|
|
108
|
-
if (agentArgs?.resume) {
|
|
109
|
-
return agentArgs.resume;
|
|
110
|
-
}
|
|
111
|
-
if (agentArgs?.continue) {
|
|
112
|
-
try {
|
|
113
|
-
const result = await apiClient.getConversationsList(product.agentType);
|
|
114
|
-
const conversations = result?.result ?? [];
|
|
115
|
-
const latest = conversations.sort((a, b) => {
|
|
116
|
-
const aTime = a.lastEventCreatedAt ? new Date(a.lastEventCreatedAt).getTime() : 0;
|
|
117
|
-
const bTime = b.lastEventCreatedAt ? new Date(b.lastEventCreatedAt).getTime() : 0;
|
|
118
|
-
return bTime - aTime;
|
|
119
|
-
})[0];
|
|
120
|
-
return latest?.deploymentConversationId;
|
|
121
|
-
} catch {
|
|
122
|
-
// fall through — start fresh
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return undefined;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
async function main(agentArgs?: AgentArgs): Promise<void> {
|
|
129
|
-
if (agentArgs?.version) {
|
|
130
|
-
console.log(`Abacus.AI CLI version ${packageJson.version}`);
|
|
131
|
-
gracefulExit(0);
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
validatePrintModeArgs(agentArgs);
|
|
136
|
-
|
|
137
|
-
if (agentArgs?.print) {
|
|
138
|
-
const inputPrompt = await resolveInputPrompt(agentArgs);
|
|
139
|
-
// For print mode the API client is created inside runPrintMode, so resolve
|
|
140
|
-
// conversation ID there — pass raw args through.
|
|
141
|
-
await runPrintMode({ agentArgs: { ...agentArgs, prompt: inputPrompt } });
|
|
142
|
-
} else {
|
|
143
|
-
const authManager = await AuthManager.create();
|
|
144
|
-
|
|
145
|
-
// Auth is fully managed by AuthManager.create() — no env access needed here.
|
|
146
|
-
|
|
147
|
-
const cliLogger = {
|
|
148
|
-
error: (message: string | Error, ...args: unknown[]) => logger.error(message, ...args),
|
|
149
|
-
debug: (...message: unknown[]) => logger.debug(...message),
|
|
150
|
-
warn: (message: string, ...args: unknown[]) => logger.warn(message, ...args),
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
const apiClient = new AbacusClient(authManager, cliLogger);
|
|
154
|
-
|
|
155
|
-
await configureApiClient(apiClient);
|
|
156
|
-
|
|
157
|
-
// Resolve --resume / --continue into a single conversationId before dispatch.
|
|
158
|
-
// Downstream consumers (AgentProvider) read agentArgs.conversationId — they
|
|
159
|
-
// don't know or care how it was resolved.
|
|
160
|
-
const conversationId = await resolveConversationId(agentArgs, apiClient);
|
|
161
|
-
const resolvedArgs: AgentArgs = { ...agentArgs, ...(conversationId && { conversationId }) };
|
|
162
|
-
|
|
163
|
-
await runRepl({
|
|
164
|
-
apiClient,
|
|
165
|
-
authManager,
|
|
166
|
-
agentArgs: resolvedArgs,
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const HELP_TEXT = `
|
|
172
|
-
Usage: abacus [options] [prompt]
|
|
173
|
-
|
|
174
|
-
Options:
|
|
175
|
-
--help Show this help message
|
|
176
|
-
--version Show version number
|
|
177
|
-
--model <model> Model to use (-m)
|
|
178
|
-
--print Print mode, non-interactive (-p)
|
|
179
|
-
--resume <id> Resume a specific conversation by ID
|
|
180
|
-
--continue Continue the most recent conversation (-c)
|
|
181
|
-
--output-format <format> Output format: text (default), stream-json
|
|
182
|
-
--auto-accept-edits Automatically accept edits
|
|
183
|
-
--dangerously-skip-permissions Skip permission checks
|
|
184
|
-
--plan-mode Enable plan mode
|
|
185
|
-
`.trim();
|
|
186
|
-
|
|
187
|
-
const { values, positionals } = parseArgs({
|
|
188
|
-
options: {
|
|
189
|
-
help: { type: "boolean", short: "h" },
|
|
190
|
-
version: { type: "boolean", short: "v" },
|
|
191
|
-
model: { type: "string", short: "m" },
|
|
192
|
-
print: { type: "boolean", short: "p" },
|
|
193
|
-
resume: { type: "string" },
|
|
194
|
-
continue: { type: "boolean", short: "c" },
|
|
195
|
-
"output-format": { type: "string" },
|
|
196
|
-
"input-format": { type: "string" },
|
|
197
|
-
"allow-editing": { type: "string" },
|
|
198
|
-
"auto-accept-edits": { type: "boolean" },
|
|
199
|
-
"dangerously-skip-permissions": { type: "boolean" },
|
|
200
|
-
"plan-mode": { type: "boolean" },
|
|
201
|
-
},
|
|
202
|
-
allowPositionals: true,
|
|
203
|
-
strict: true,
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
if (values.help) {
|
|
207
|
-
console.log(HELP_TEXT);
|
|
208
|
-
process.exit(0);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
main({
|
|
212
|
-
...values,
|
|
213
|
-
prompt: positionals.length > 0 ? positionals.join(" ") : null,
|
|
214
|
-
}).catch((err) => {
|
|
215
|
-
console.error(err);
|
|
216
|
-
process.exit(1);
|
|
217
|
-
});
|