demian-cli 1.0.8 → 1.1.0
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 +13 -2
- package/dist/cli.mjs +68 -24
- package/dist/index.mjs +29 -3
- package/dist/tui.mjs +393 -175
- package/dist/vscode-worker.mjs +72 -27
- package/docs/ko/README.md +6 -2
- package/package.json +1 -1
package/dist/tui.mjs
CHANGED
|
@@ -23573,11 +23573,18 @@ function providerModelProfiles(providerName, providerConfig) {
|
|
|
23573
23573
|
return out;
|
|
23574
23574
|
}
|
|
23575
23575
|
function providerModelOptions(providerName, providerConfig) {
|
|
23576
|
-
return providerModelProfiles(providerName, providerConfig).filter((profile) => !profile.hidden).map((profile) => profile
|
|
23576
|
+
return providerModelProfiles(providerName, providerConfig).filter((profile) => !profile.hidden).map((profile) => displayModelForProfile(profile));
|
|
23577
23577
|
}
|
|
23578
23578
|
function defaultModelForProvider(providerName, providerConfig) {
|
|
23579
23579
|
return providerModelProfiles(providerName, providerConfig)[0]?.model ?? "";
|
|
23580
23580
|
}
|
|
23581
|
+
function displayModelForProfile(profile) {
|
|
23582
|
+
return profile.displayName?.trim() || profile.name?.trim() || profile.model;
|
|
23583
|
+
}
|
|
23584
|
+
function defaultDisplayModelForProvider(providerName, providerConfig) {
|
|
23585
|
+
const profile = providerModelProfiles(providerName, providerConfig)[0];
|
|
23586
|
+
return profile ? displayModelForProfile(profile) : defaultModelForProvider(providerName, providerConfig);
|
|
23587
|
+
}
|
|
23581
23588
|
function resolveConfiguredApiKey(providerConfig) {
|
|
23582
23589
|
if (providerConfig.apiKey) return { value: providerConfig.apiKey };
|
|
23583
23590
|
for (const envName of [providerConfig.apiKeyEnv, ...providerConfig.apiKeyEnvAliases ?? []]) {
|
|
@@ -23614,7 +23621,7 @@ function mergeModelProfile(providerConfig, profile) {
|
|
|
23614
23621
|
...providerConfig,
|
|
23615
23622
|
...definedOnly({
|
|
23616
23623
|
baseURL: profile.baseURL,
|
|
23617
|
-
apiKey: profile.apiKey,
|
|
23624
|
+
apiKey: nonEmptyString(profile.apiKey),
|
|
23618
23625
|
apiKeyEnv: profile.apiKeyEnv,
|
|
23619
23626
|
apiKeyEnvAliases: profile.apiKeyEnvAliases,
|
|
23620
23627
|
auth: profile.auth,
|
|
@@ -23629,6 +23636,9 @@ function mergeModelProfile(providerConfig, profile) {
|
|
|
23629
23636
|
function definedOnly(input2) {
|
|
23630
23637
|
return Object.fromEntries(Object.entries(input2).filter(([, value]) => value !== void 0));
|
|
23631
23638
|
}
|
|
23639
|
+
function nonEmptyString(value) {
|
|
23640
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
23641
|
+
}
|
|
23632
23642
|
function fallbackModelForProvider(providerName, providerConfig) {
|
|
23633
23643
|
if (typeof providerConfig.model === "string" && providerConfig.model.trim()) return providerConfig.model.trim();
|
|
23634
23644
|
if (providerName === "openai") return "gpt-5.5";
|
|
@@ -23932,6 +23942,7 @@ var init_config = __esm({
|
|
|
23932
23942
|
defaultProvider: "brave",
|
|
23933
23943
|
providers: {
|
|
23934
23944
|
brave: {
|
|
23945
|
+
apiKey: "",
|
|
23935
23946
|
apiKeyEnv: "BRAVE_SEARCH_API_KEY",
|
|
23936
23947
|
endpoint: "https://api.search.brave.com/res/v1/web/search",
|
|
23937
23948
|
count: 10,
|
|
@@ -23940,12 +23951,14 @@ var init_config = __esm({
|
|
|
23940
23951
|
safeSearch: "moderate"
|
|
23941
23952
|
},
|
|
23942
23953
|
tavily: {
|
|
23954
|
+
apiKey: "",
|
|
23943
23955
|
apiKeyEnv: "TAVILY_API_KEY",
|
|
23944
23956
|
endpoint: "https://api.tavily.com/search",
|
|
23945
23957
|
maxResults: 5,
|
|
23946
23958
|
searchDepth: "basic"
|
|
23947
23959
|
},
|
|
23948
23960
|
exa: {
|
|
23961
|
+
apiKey: "",
|
|
23949
23962
|
apiKeyEnv: "EXA_API_KEY",
|
|
23950
23963
|
endpoint: "https://api.exa.ai/search",
|
|
23951
23964
|
numResults: 5,
|
|
@@ -24000,6 +24013,7 @@ var init_config = __esm({
|
|
|
24000
24013
|
openai: {
|
|
24001
24014
|
type: "openai-compatible",
|
|
24002
24015
|
baseURL: "https://api.openai.com/v1",
|
|
24016
|
+
apiKey: "",
|
|
24003
24017
|
apiKeyEnv: "OPENAI_API_KEY",
|
|
24004
24018
|
catalog: {
|
|
24005
24019
|
type: "openai-models",
|
|
@@ -24009,6 +24023,7 @@ var init_config = __esm({
|
|
|
24009
24023
|
anthropic: {
|
|
24010
24024
|
type: "anthropic",
|
|
24011
24025
|
baseURL: "https://api.anthropic.com/v1",
|
|
24026
|
+
apiKey: "",
|
|
24012
24027
|
apiKeyEnv: "ANTHROPIC_API_KEY",
|
|
24013
24028
|
catalog: {
|
|
24014
24029
|
type: "anthropic-models",
|
|
@@ -24018,6 +24033,7 @@ var init_config = __esm({
|
|
|
24018
24033
|
gemini: {
|
|
24019
24034
|
type: "openai-compatible",
|
|
24020
24035
|
baseURL: "https://generativelanguage.googleapis.com/v1beta/openai/",
|
|
24036
|
+
apiKey: "",
|
|
24021
24037
|
apiKeyEnv: "GEMINI_API_KEY",
|
|
24022
24038
|
apiKeyEnvAliases: ["GOOGLE_API_KEY"],
|
|
24023
24039
|
catalog: {
|
|
@@ -24028,6 +24044,7 @@ var init_config = __esm({
|
|
|
24028
24044
|
groq: {
|
|
24029
24045
|
type: "openai-compatible",
|
|
24030
24046
|
baseURL: "https://api.groq.com/openai/v1",
|
|
24047
|
+
apiKey: "",
|
|
24031
24048
|
apiKeyEnv: "GROQ_API_KEY",
|
|
24032
24049
|
catalog: {
|
|
24033
24050
|
type: "groq-models",
|
|
@@ -24043,6 +24060,7 @@ var init_config = __esm({
|
|
|
24043
24060
|
displayName: "Azure example",
|
|
24044
24061
|
model: "azure-deployment-name",
|
|
24045
24062
|
baseURL: "https://example.openai.azure.com/openai/v1",
|
|
24063
|
+
apiKey: "",
|
|
24046
24064
|
apiKeyEnv: "AZURE_OPENAI_API_KEY"
|
|
24047
24065
|
}
|
|
24048
24066
|
]
|
|
@@ -24051,6 +24069,7 @@ var init_config = __esm({
|
|
|
24051
24069
|
type: "openai-compatible",
|
|
24052
24070
|
baseURL: "http://localhost:1234/v1",
|
|
24053
24071
|
apiKey: "lm-studio",
|
|
24072
|
+
modelProfiles: [],
|
|
24054
24073
|
catalog: {
|
|
24055
24074
|
type: "openai-compatible-models",
|
|
24056
24075
|
endpoint: "http://localhost:1234/v1/models"
|
|
@@ -24060,6 +24079,7 @@ var init_config = __esm({
|
|
|
24060
24079
|
type: "openai-compatible",
|
|
24061
24080
|
baseURL: "http://localhost:11434/v1",
|
|
24062
24081
|
apiKey: "ollama",
|
|
24082
|
+
modelProfiles: [],
|
|
24063
24083
|
quirks: { omitTemperature: true },
|
|
24064
24084
|
catalog: {
|
|
24065
24085
|
type: "openai-compatible-models",
|
|
@@ -24069,7 +24089,9 @@ var init_config = __esm({
|
|
|
24069
24089
|
"ollama-cloud": {
|
|
24070
24090
|
type: "ollama",
|
|
24071
24091
|
baseURL: "https://ollama.com/api",
|
|
24092
|
+
apiKey: "",
|
|
24072
24093
|
apiKeyEnv: "OLLAMA_API_KEY",
|
|
24094
|
+
modelProfiles: [],
|
|
24073
24095
|
catalog: {
|
|
24074
24096
|
type: "ollama-tags",
|
|
24075
24097
|
endpoint: "https://ollama.com/api/tags"
|
|
@@ -24079,6 +24101,7 @@ var init_config = __esm({
|
|
|
24079
24101
|
type: "openai-compatible",
|
|
24080
24102
|
baseURL: "http://localhost:8080/v1",
|
|
24081
24103
|
apiKey: "llama.cpp",
|
|
24104
|
+
modelProfiles: [],
|
|
24082
24105
|
catalog: {
|
|
24083
24106
|
type: "openai-compatible-models",
|
|
24084
24107
|
endpoint: "http://localhost:8080/v1/models"
|
|
@@ -24088,6 +24111,7 @@ var init_config = __esm({
|
|
|
24088
24111
|
type: "openai-compatible",
|
|
24089
24112
|
baseURL: "http://localhost:8000/v1",
|
|
24090
24113
|
apiKey: "vllm",
|
|
24114
|
+
modelProfiles: [],
|
|
24091
24115
|
catalog: {
|
|
24092
24116
|
type: "openai-compatible-models",
|
|
24093
24117
|
endpoint: "http://localhost:8000/v1/models"
|
|
@@ -25703,7 +25727,7 @@ var init_store = __esm({
|
|
|
25703
25727
|
}
|
|
25704
25728
|
markTaskFailed(message) {
|
|
25705
25729
|
const lines = [message];
|
|
25706
|
-
if (this.#lastRetryPrompt()) lines.push("Press
|
|
25730
|
+
if (this.#lastRetryPrompt()) lines.push("Press Esc then r or type /retry to run the last task again.");
|
|
25707
25731
|
this.#append({ kind: "warning", title: "Task Failed", lines });
|
|
25708
25732
|
this.#state.status.reason = "error";
|
|
25709
25733
|
this.#state.inputMode = this.#exitRequested ? "done" : "prompt";
|
|
@@ -26963,9 +26987,10 @@ __export(app_exports, {
|
|
|
26963
26987
|
});
|
|
26964
26988
|
import React, { useEffect, useState } from "react";
|
|
26965
26989
|
import { Box, Text, useApp, useInput } from "ink";
|
|
26966
|
-
function TuiApp({ store }) {
|
|
26990
|
+
function TuiApp({ store, version = "dev" }) {
|
|
26967
26991
|
const [state, setState] = useState(() => store.snapshot());
|
|
26968
26992
|
const [now2, setNow] = useState(() => Date.now());
|
|
26993
|
+
const [shortcutMode, setShortcutMode] = useState(false);
|
|
26969
26994
|
const app = useApp();
|
|
26970
26995
|
useEffect(() => {
|
|
26971
26996
|
const update = () => setState(store.snapshot());
|
|
@@ -26978,27 +27003,64 @@ function TuiApp({ store }) {
|
|
|
26978
27003
|
const timer = setInterval(() => setNow(Date.now()), 450);
|
|
26979
27004
|
return () => clearInterval(timer);
|
|
26980
27005
|
}, [state.workPlan?.planId, state.inputMode]);
|
|
27006
|
+
useEffect(() => {
|
|
27007
|
+
setShortcutMode(false);
|
|
27008
|
+
}, [state.inputMode, state.permission !== void 0]);
|
|
26981
27009
|
useInput((input2, key) => {
|
|
26982
27010
|
const textInput = textInputForKeypress(input2, key);
|
|
26983
|
-
if (
|
|
26984
|
-
|
|
26985
|
-
|
|
26986
|
-
|
|
26987
|
-
|
|
26988
|
-
|
|
26989
|
-
|
|
26990
|
-
|
|
26991
|
-
|
|
26992
|
-
|
|
26993
|
-
|
|
26994
|
-
|
|
26995
|
-
|
|
26996
|
-
|
|
26997
|
-
|
|
26998
|
-
|
|
26999
|
-
|
|
27000
|
-
|
|
27001
|
-
|
|
27011
|
+
if (shortcutMode) {
|
|
27012
|
+
setShortcutMode(false);
|
|
27013
|
+
if (key.escape) return;
|
|
27014
|
+
const shortcut = input2.toLowerCase();
|
|
27015
|
+
if (shortcut === "q") {
|
|
27016
|
+
store.requestExit();
|
|
27017
|
+
app.exit();
|
|
27018
|
+
return;
|
|
27019
|
+
}
|
|
27020
|
+
if (shortcut === "s" && state.inputMode === "running") {
|
|
27021
|
+
store.stopActiveTask();
|
|
27022
|
+
return;
|
|
27023
|
+
}
|
|
27024
|
+
if (shortcut === "p" && state.inputMode === "prompt") {
|
|
27025
|
+
store.openProviderSelector();
|
|
27026
|
+
return;
|
|
27027
|
+
}
|
|
27028
|
+
if (shortcut === "a" && state.inputMode === "prompt") {
|
|
27029
|
+
store.openAgentSelector();
|
|
27030
|
+
return;
|
|
27031
|
+
}
|
|
27032
|
+
if (shortcut === "m" && state.inputMode === "prompt") {
|
|
27033
|
+
store.openModelEditor();
|
|
27034
|
+
return;
|
|
27035
|
+
}
|
|
27036
|
+
if (shortcut === "o" && state.inputMode === "prompt") {
|
|
27037
|
+
store.openPermissionPresetSelector();
|
|
27038
|
+
return;
|
|
27039
|
+
}
|
|
27040
|
+
if (shortcut === "u" && state.inputMode === "prompt") {
|
|
27041
|
+
store.clearPromptInput();
|
|
27042
|
+
return;
|
|
27043
|
+
}
|
|
27044
|
+
if (shortcut === "d" && state.turnDiff) {
|
|
27045
|
+
store.toggleDiffExpanded();
|
|
27046
|
+
return;
|
|
27047
|
+
}
|
|
27048
|
+
if (shortcut === "t" && state.blocks.some((block) => block.kind === "tool")) {
|
|
27049
|
+
store.toggleLatestToolExpanded();
|
|
27050
|
+
return;
|
|
27051
|
+
}
|
|
27052
|
+
if (shortcut === "w" && (state.workPlan || state.inputMode === "running")) {
|
|
27053
|
+
store.toggleWorkPlanExpanded();
|
|
27054
|
+
return;
|
|
27055
|
+
}
|
|
27056
|
+
if (shortcut === "e" && state.pendingClaudeCodePlan) {
|
|
27057
|
+
store.usePendingClaudeCodePlan();
|
|
27058
|
+
return;
|
|
27059
|
+
}
|
|
27060
|
+
if (shortcut === "r" && state.canRetryLastPrompt) {
|
|
27061
|
+
store.retryLastPrompt();
|
|
27062
|
+
return;
|
|
27063
|
+
}
|
|
27002
27064
|
return;
|
|
27003
27065
|
}
|
|
27004
27066
|
if (state.permission) {
|
|
@@ -27070,10 +27132,6 @@ function TuiApp({ store }) {
|
|
|
27070
27132
|
store.closeSettings();
|
|
27071
27133
|
return;
|
|
27072
27134
|
}
|
|
27073
|
-
if (key.ctrl && input2 === "u") {
|
|
27074
|
-
store.clearModelInput();
|
|
27075
|
-
return;
|
|
27076
|
-
}
|
|
27077
27135
|
if (key.return) {
|
|
27078
27136
|
if (textInput) store.appendModelInput(textInput);
|
|
27079
27137
|
store.submitModelInput();
|
|
@@ -27087,10 +27145,6 @@ function TuiApp({ store }) {
|
|
|
27087
27145
|
return;
|
|
27088
27146
|
}
|
|
27089
27147
|
if (state.inputMode === "prompt" || state.inputMode === "running") {
|
|
27090
|
-
if (key.tab && state.turnDiff) {
|
|
27091
|
-
store.toggleDiffExpanded();
|
|
27092
|
-
return;
|
|
27093
|
-
}
|
|
27094
27148
|
if (state.inputMode === "prompt" && key.upArrow) {
|
|
27095
27149
|
store.navigatePromptHistory(-1);
|
|
27096
27150
|
return;
|
|
@@ -27099,24 +27153,8 @@ function TuiApp({ store }) {
|
|
|
27099
27153
|
store.navigatePromptHistory(1);
|
|
27100
27154
|
return;
|
|
27101
27155
|
}
|
|
27102
|
-
if (
|
|
27103
|
-
|
|
27104
|
-
return;
|
|
27105
|
-
}
|
|
27106
|
-
if (!key.return && state.inputMode === "prompt" && !state.promptInput && input2 === "a") {
|
|
27107
|
-
store.openAgentSelector();
|
|
27108
|
-
return;
|
|
27109
|
-
}
|
|
27110
|
-
if (!key.return && state.inputMode === "prompt" && !state.promptInput && input2 === "m") {
|
|
27111
|
-
store.openModelEditor();
|
|
27112
|
-
return;
|
|
27113
|
-
}
|
|
27114
|
-
if (!key.return && state.inputMode === "prompt" && !state.promptInput && input2 === "o") {
|
|
27115
|
-
store.openPermissionPresetSelector();
|
|
27116
|
-
return;
|
|
27117
|
-
}
|
|
27118
|
-
if (key.ctrl && input2 === "u") {
|
|
27119
|
-
store.clearPromptInput();
|
|
27156
|
+
if (key.escape) {
|
|
27157
|
+
setShortcutMode(true);
|
|
27120
27158
|
return;
|
|
27121
27159
|
}
|
|
27122
27160
|
if (key.return) {
|
|
@@ -27132,17 +27170,29 @@ function TuiApp({ store }) {
|
|
|
27132
27170
|
return;
|
|
27133
27171
|
}
|
|
27134
27172
|
});
|
|
27173
|
+
const shellProps = { flexDirection: "column", paddingX: 1, minHeight: terminalHeight() };
|
|
27174
|
+
if (shouldShowEmptyState(state)) {
|
|
27175
|
+
return React.createElement(
|
|
27176
|
+
Box,
|
|
27177
|
+
shellProps,
|
|
27178
|
+
React.createElement(EmptyState, { state, version, shortcutMode })
|
|
27179
|
+
);
|
|
27180
|
+
}
|
|
27135
27181
|
return React.createElement(
|
|
27136
27182
|
Box,
|
|
27137
|
-
|
|
27138
|
-
React.createElement(StatusBar, { state, now: now2 }),
|
|
27139
|
-
React.createElement(
|
|
27140
|
-
|
|
27141
|
-
|
|
27142
|
-
|
|
27143
|
-
|
|
27144
|
-
|
|
27145
|
-
|
|
27183
|
+
shellProps,
|
|
27184
|
+
React.createElement(StatusBar, { state, now: now2, version }),
|
|
27185
|
+
React.createElement(
|
|
27186
|
+
Box,
|
|
27187
|
+
{ flexDirection: "column", flexGrow: 1, paddingX: 1 },
|
|
27188
|
+
React.createElement(shouldShowLoading(state) ? LoadingView : TranscriptView, { state }),
|
|
27189
|
+
React.createElement(DiffAccordion, { state }),
|
|
27190
|
+
React.createElement(WorkPlanPanel, { state, now: now2 }),
|
|
27191
|
+
React.createElement(ActivityBar, { state }),
|
|
27192
|
+
React.createElement(GoalIsland, { state }),
|
|
27193
|
+
React.createElement(Box, { flexGrow: 1 }),
|
|
27194
|
+
React.createElement(InteractionPanel, { state, shortcutMode })
|
|
27195
|
+
)
|
|
27146
27196
|
);
|
|
27147
27197
|
}
|
|
27148
27198
|
function textInputForKeypress(input2, key) {
|
|
@@ -27155,15 +27205,107 @@ function textInputForKeypress(input2, key) {
|
|
|
27155
27205
|
function shouldShowLoading(state) {
|
|
27156
27206
|
return state.inputMode === "starting" || state.inputMode === "running" && state.blocks.length === 0 && !state.streamingText;
|
|
27157
27207
|
}
|
|
27208
|
+
function shouldShowEmptyState(state) {
|
|
27209
|
+
return state.inputMode === "prompt" && !state.permission && state.blocks.length === 0 && !state.streamingText && !state.turnDiff && !state.workPlan && !state.goal;
|
|
27210
|
+
}
|
|
27211
|
+
function EmptyState({ state, version, shortcutMode }) {
|
|
27212
|
+
const prompt = state.promptInput || 'Ask anything... "\uC774 \uD504\uB85C\uC81D\uD2B8\uC758 \uAD6C\uC870\uB97C \uC54C\uB824\uC918"';
|
|
27213
|
+
const hint = shortcutMode ? shortcutHelp(state) : "enter send \xB7 esc commands \xB7 / commands";
|
|
27214
|
+
const topGap = Math.max(2, Math.min(8, Math.floor(terminalHeight() * 0.18)));
|
|
27215
|
+
return React.createElement(
|
|
27216
|
+
Box,
|
|
27217
|
+
{ flexDirection: "column", flexGrow: 1 },
|
|
27218
|
+
React.createElement(Box, { height: topGap }),
|
|
27219
|
+
React.createElement(DemianWordmark),
|
|
27220
|
+
React.createElement(Box, { height: 2 }),
|
|
27221
|
+
React.createElement(
|
|
27222
|
+
Box,
|
|
27223
|
+
{ alignSelf: "center", width: promptPanelWidth(), flexDirection: "column", borderStyle: "double", borderColor: shortcutMode ? "cyan" : "blue", paddingX: 2, paddingY: 1 },
|
|
27224
|
+
React.createElement(Text, { color: state.promptInput ? "white" : "gray" }, prompt)
|
|
27225
|
+
),
|
|
27226
|
+
React.createElement(SessionMetaBox, { state, version }),
|
|
27227
|
+
React.createElement(
|
|
27228
|
+
Box,
|
|
27229
|
+
{ alignSelf: "center", width: promptPanelWidth(), justifyContent: "flex-end", marginTop: 1 },
|
|
27230
|
+
React.createElement(Text, { color: shortcutMode ? "cyan" : "gray" }, hint)
|
|
27231
|
+
),
|
|
27232
|
+
state.promptError ? React.createElement(Box, { alignSelf: "center", width: promptPanelWidth(), marginTop: 1 }, React.createElement(Text, { color: "yellow" }, state.promptError)) : null,
|
|
27233
|
+
React.createElement(Box, { flexGrow: 1 })
|
|
27234
|
+
);
|
|
27235
|
+
}
|
|
27236
|
+
function SessionMetaBox({ state, version, marginTop = 1 }) {
|
|
27237
|
+
const width = promptPanelWidth();
|
|
27238
|
+
const compact = width < 68;
|
|
27239
|
+
const agent = shorten(state.selectedAgent ?? state.status.agent ?? "general", compact ? 14 : 18);
|
|
27240
|
+
const model = shorten(state.selection?.model ?? state.status.model ?? "model", compact ? Math.max(18, width - 14) : 30);
|
|
27241
|
+
const workspace = shorten(state.status.cwd ?? process.cwd(), compact ? Math.max(18, width - 18) : 46);
|
|
27242
|
+
const rows = compact ? [
|
|
27243
|
+
React.createElement(
|
|
27244
|
+
Box,
|
|
27245
|
+
{ key: "mode" },
|
|
27246
|
+
React.createElement(MetaItem, { label: "agent", value: agent, color: "green" }),
|
|
27247
|
+
React.createElement(MetaDivider),
|
|
27248
|
+
React.createElement(MetaItem, { label: "perm", value: state.permissionPreset, color: "yellow" })
|
|
27249
|
+
),
|
|
27250
|
+
React.createElement(Box, { key: "model" }, React.createElement(MetaItem, { label: "model", value: model, color: "cyan" })),
|
|
27251
|
+
React.createElement(Box, { key: "workspace" }, React.createElement(MetaItem, { label: "workspace", value: workspace, color: "white" })),
|
|
27252
|
+
version ? React.createElement(Box, { key: "version" }, React.createElement(MetaItem, { label: "version", value: `v${version}`, color: "gray" })) : null
|
|
27253
|
+
].filter(Boolean) : [
|
|
27254
|
+
React.createElement(
|
|
27255
|
+
Box,
|
|
27256
|
+
{ key: "mode" },
|
|
27257
|
+
React.createElement(MetaItem, { label: "agent", value: agent, color: "green" }),
|
|
27258
|
+
React.createElement(MetaDivider),
|
|
27259
|
+
React.createElement(MetaItem, { label: "model", value: model, color: "cyan" }),
|
|
27260
|
+
React.createElement(MetaDivider),
|
|
27261
|
+
React.createElement(MetaItem, { label: "perm", value: state.permissionPreset, color: "yellow" })
|
|
27262
|
+
),
|
|
27263
|
+
React.createElement(
|
|
27264
|
+
Box,
|
|
27265
|
+
{ key: "workspace" },
|
|
27266
|
+
React.createElement(MetaItem, { label: "workspace", value: workspace, color: "white" }),
|
|
27267
|
+
version ? React.createElement(MetaDivider) : null,
|
|
27268
|
+
version ? React.createElement(MetaItem, { label: "version", value: `v${version}`, color: "gray" }) : null
|
|
27269
|
+
)
|
|
27270
|
+
];
|
|
27271
|
+
return React.createElement(
|
|
27272
|
+
Box,
|
|
27273
|
+
{ alignSelf: "center", width, flexDirection: "column", borderStyle: "single", borderColor: "gray", paddingX: 2, marginTop },
|
|
27274
|
+
...rows
|
|
27275
|
+
);
|
|
27276
|
+
}
|
|
27277
|
+
function MetaItem({ label, value, color }) {
|
|
27278
|
+
return React.createElement(
|
|
27279
|
+
Text,
|
|
27280
|
+
null,
|
|
27281
|
+
React.createElement(Text, { color: "gray" }, `${label} `),
|
|
27282
|
+
React.createElement(Text, { color }, value)
|
|
27283
|
+
);
|
|
27284
|
+
}
|
|
27285
|
+
function MetaDivider() {
|
|
27286
|
+
return React.createElement(Text, { color: "gray" }, " \xB7 ");
|
|
27287
|
+
}
|
|
27288
|
+
function DemianWordmark() {
|
|
27289
|
+
if (terminalWidth() < 58) {
|
|
27290
|
+
return React.createElement(Box, { alignSelf: "center" }, React.createElement(Text, { color: "gray", bold: true }, "DEMIAN"));
|
|
27291
|
+
}
|
|
27292
|
+
return React.createElement(
|
|
27293
|
+
Box,
|
|
27294
|
+
{ alignSelf: "center", flexDirection: "column" },
|
|
27295
|
+
...DEMIAN_WORDMARK_LINES.map(
|
|
27296
|
+
(line, index) => React.createElement(Text, { key: index, color: index < 2 ? "gray" : "white", bold: true }, line)
|
|
27297
|
+
)
|
|
27298
|
+
);
|
|
27299
|
+
}
|
|
27158
27300
|
function LoadingView({ state }) {
|
|
27159
|
-
const title = state.inputMode === "starting" ? "
|
|
27301
|
+
const title = state.inputMode === "starting" ? "Demian runtime" : "Preparing session";
|
|
27160
27302
|
const message = state.activity || (state.inputMode === "starting" ? "Loading configuration" : "Starting session");
|
|
27161
27303
|
return React.createElement(
|
|
27162
27304
|
Box,
|
|
27163
|
-
{ flexDirection: "column", marginTop: 1, borderStyle: "
|
|
27305
|
+
{ flexDirection: "column", marginTop: 1, borderStyle: "double", borderColor: "cyan", paddingX: 1, paddingY: 1 },
|
|
27164
27306
|
React.createElement(Text, { color: "cyan", bold: true }, title),
|
|
27165
27307
|
React.createElement(Text, { color: "white" }, message),
|
|
27166
|
-
React.createElement(Text, { color: "gray" }, "
|
|
27308
|
+
React.createElement(Text, { color: "gray" }, "Loading providers, tools, workspace state, and permissions.")
|
|
27167
27309
|
);
|
|
27168
27310
|
}
|
|
27169
27311
|
function contextEfficiencySummary(state) {
|
|
@@ -27183,61 +27325,53 @@ function contextEfficiencySummary(state) {
|
|
|
27183
27325
|
].filter(Boolean);
|
|
27184
27326
|
return parts.join(" | ");
|
|
27185
27327
|
}
|
|
27186
|
-
function StatusBar({ state, now: now2 }) {
|
|
27328
|
+
function StatusBar({ state, now: now2, version }) {
|
|
27187
27329
|
const status = state.status;
|
|
27188
|
-
const
|
|
27189
|
-
|
|
27190
|
-
|
|
27191
|
-
|
|
27192
|
-
status.agent ? `agent ${status.agent}` : void 0,
|
|
27193
|
-
status.cwd ? `cwd ${shorten(status.cwd, 48)}` : void 0,
|
|
27194
|
-
status.externalSessionId ? `cc session ${shorten(status.externalSessionId, 18)}` : void 0,
|
|
27195
|
-
status.reason ? `reason ${status.reason}` : void 0
|
|
27196
|
-
].filter(Boolean);
|
|
27330
|
+
const mode = tuiMode(state);
|
|
27331
|
+
const provider = state.selection?.providerName ?? status.provider;
|
|
27332
|
+
const model = state.selection?.model ?? status.model ?? "-";
|
|
27333
|
+
const meta = [provider, shorten(model, 32), state.permissionPreset, `v${version}`].filter(Boolean).join(" \xB7 ");
|
|
27197
27334
|
return React.createElement(
|
|
27198
27335
|
Box,
|
|
27199
|
-
{
|
|
27200
|
-
React.createElement(
|
|
27201
|
-
|
|
27202
|
-
|
|
27336
|
+
{ paddingX: 1, marginBottom: 1, justifyContent: "space-between" },
|
|
27337
|
+
React.createElement(
|
|
27338
|
+
Text,
|
|
27339
|
+
null,
|
|
27340
|
+
React.createElement(DemianTuiMark, { active: state.inputMode === "starting" || state.inputMode === "running", now: now2 }),
|
|
27341
|
+
React.createElement(Text, { color: "cyan", bold: true }, " Demian")
|
|
27342
|
+
),
|
|
27343
|
+
React.createElement(
|
|
27344
|
+
Text,
|
|
27345
|
+
null,
|
|
27346
|
+
React.createElement(Text, { color: mode.color }, mode.label),
|
|
27347
|
+
React.createElement(Text, { color: "gray" }, ` \xB7 ${meta}`)
|
|
27348
|
+
)
|
|
27203
27349
|
);
|
|
27204
27350
|
}
|
|
27205
27351
|
function DemianTuiMark({ active, now: now2 }) {
|
|
27206
27352
|
const frame = active ? Math.floor(now2 / 450) % 4 : 0;
|
|
27207
|
-
const
|
|
27208
|
-
const face = frame === 2 ? "o" : "*";
|
|
27353
|
+
const mark = active ? ["D>", "D*", "D+", "D*"][frame] : "D>";
|
|
27209
27354
|
return React.createElement(
|
|
27210
27355
|
Text,
|
|
27211
27356
|
{ color: "yellow", bold: true },
|
|
27212
|
-
`[${
|
|
27357
|
+
`[${mark}]`
|
|
27213
27358
|
);
|
|
27214
27359
|
}
|
|
27215
|
-
function
|
|
27216
|
-
|
|
27217
|
-
|
|
27218
|
-
if (
|
|
27219
|
-
|
|
27220
|
-
}
|
|
27221
|
-
|
|
27222
|
-
|
|
27223
|
-
return providerName ? state.providerOptions.find((option) => option.name === providerName) : void 0;
|
|
27224
|
-
}
|
|
27225
|
-
function SettingsBar({ state }) {
|
|
27226
|
-
const selection = state.selection;
|
|
27227
|
-
if (!selection) return null;
|
|
27228
|
-
const help = state.inputMode === "provider" ? "up/down select | enter apply | esc cancel" : state.inputMode === "agent" ? "up/down select | enter apply | esc cancel" : state.inputMode === "permissionPreset" ? "up/down select | enter apply | esc cancel" : state.inputMode === "model" ? "type model | enter apply | esc cancel" : "p provider | a agent | m model | o permissions | up/down history | /cowork task | /compact compact | enter send | ctrl+c exit";
|
|
27229
|
-
return React.createElement(
|
|
27230
|
-
Box,
|
|
27231
|
-
{ borderStyle: "single", paddingX: 1 },
|
|
27232
|
-
React.createElement(Text, null, `agent ${state.selectedAgent ?? state.status.agent ?? "?"} | provider ${selection.providerName} (${selection.providerSource}) | model ${selection.model} (${selection.modelSource}) | permission ${state.permissionPreset} | ${help}`)
|
|
27233
|
-
);
|
|
27360
|
+
function tuiMode(state) {
|
|
27361
|
+
if (state.done) return { label: "done", color: "green" };
|
|
27362
|
+
if (state.permission) return { label: "approval", color: "yellow" };
|
|
27363
|
+
if (state.inputMode === "starting") return { label: "booting", color: "cyan" };
|
|
27364
|
+
if (state.inputMode === "running") return { label: "running", color: "cyan" };
|
|
27365
|
+
if (state.inputMode === "provider" || state.inputMode === "agent" || state.inputMode === "model" || state.inputMode === "permissionPreset") return { label: "settings", color: "magenta" };
|
|
27366
|
+
if (state.inputMode === "prompt") return { label: "ready", color: "green" };
|
|
27367
|
+
return { label: state.inputMode, color: "gray" };
|
|
27234
27368
|
}
|
|
27235
27369
|
function TranscriptView({ state }) {
|
|
27236
27370
|
const blocks = state.blocks.slice(-12);
|
|
27237
27371
|
const streaming = !state.streamingFinalized && state.streamingText ? { kind: "assistant", title: "Assistant streaming", lines: streamingLines(state.streamingText) } : void 0;
|
|
27238
27372
|
return React.createElement(
|
|
27239
27373
|
Box,
|
|
27240
|
-
{ flexDirection: "column", marginTop: 1 },
|
|
27374
|
+
{ flexDirection: "column", marginTop: 1, paddingX: 1 },
|
|
27241
27375
|
...blocks.map((block) => React.createElement(BlockView, { key: block.id, block })),
|
|
27242
27376
|
streaming ? React.createElement(BlockView, { key: "streaming", block: streaming }) : null
|
|
27243
27377
|
);
|
|
@@ -27429,21 +27563,26 @@ function toneColor(tone) {
|
|
|
27429
27563
|
return void 0;
|
|
27430
27564
|
}
|
|
27431
27565
|
function ActivityBar({ state }) {
|
|
27566
|
+
if (!shouldShowActivity(state)) return null;
|
|
27432
27567
|
const warning = state.warnings.at(-1);
|
|
27433
27568
|
const context = contextEfficiencySummary(state);
|
|
27569
|
+
const color = state.done ? "green" : state.inputMode === "running" ? "cyan" : "blue";
|
|
27434
27570
|
return React.createElement(
|
|
27435
27571
|
Box,
|
|
27436
|
-
{ borderStyle: "round", borderColor:
|
|
27572
|
+
{ borderStyle: "round", borderColor: color, paddingX: 1, flexDirection: "column" },
|
|
27437
27573
|
React.createElement(
|
|
27438
27574
|
Box,
|
|
27439
27575
|
null,
|
|
27440
|
-
React.createElement(Text, { color
|
|
27576
|
+
React.createElement(Text, { color, bold: true }, "Activity "),
|
|
27441
27577
|
React.createElement(Text, { color: state.done ? "green" : "white" }, state.activity),
|
|
27442
27578
|
context ? React.createElement(Text, { color: "gray" }, ` | ${context}`) : null
|
|
27443
27579
|
),
|
|
27444
27580
|
warning ? React.createElement(Text, { color: "yellow" }, ` \xB7 ${warning}`) : null
|
|
27445
27581
|
);
|
|
27446
27582
|
}
|
|
27583
|
+
function shouldShowActivity(state) {
|
|
27584
|
+
return state.inputMode === "running" || state.done || state.warnings.length > 0 || Boolean(state.contextEfficiency);
|
|
27585
|
+
}
|
|
27447
27586
|
function GoalIsland({ state }) {
|
|
27448
27587
|
const goal = state.goal;
|
|
27449
27588
|
if (!goal) return null;
|
|
@@ -27499,7 +27638,7 @@ function DiffAccordion({ state }) {
|
|
|
27499
27638
|
null,
|
|
27500
27639
|
React.createElement(Text, { color: "cyan", bold: true }, `${indicator} Diff `),
|
|
27501
27640
|
React.createElement(Text, { color: "white" }, summary),
|
|
27502
|
-
React.createElement(Text, { color: "gray" }, " |
|
|
27641
|
+
React.createElement(Text, { color: "gray" }, " | esc then d toggle")
|
|
27503
27642
|
),
|
|
27504
27643
|
state.diffExpanded ? React.createElement(
|
|
27505
27644
|
Box,
|
|
@@ -27539,7 +27678,7 @@ function WorkPlanPanel({ state, now: now2 }) {
|
|
|
27539
27678
|
null,
|
|
27540
27679
|
React.createElement(Text, { color: "cyan", bold: true }, `${expanded ? "[-]" : "[+]"} Plan `),
|
|
27541
27680
|
React.createElement(Text, { color: "white" }, "Thinking"),
|
|
27542
|
-
React.createElement(Text, { color: "gray" }, " |
|
|
27681
|
+
React.createElement(Text, { color: "gray" }, " | esc then w toggle")
|
|
27543
27682
|
),
|
|
27544
27683
|
expanded ? React.createElement(Text, { color: "gray" }, "Demian is inspecting context and preparing a step-by-step plan.") : null
|
|
27545
27684
|
);
|
|
@@ -27563,7 +27702,7 @@ function WorkPlanPanel({ state, now: now2 }) {
|
|
|
27563
27702
|
elapsed ? React.createElement(Text, { color: "gray" }, ` (${elapsed})`) : null,
|
|
27564
27703
|
React.createElement(Text, { color: "gray" }, ` | ${planProgressGraph(progress.resolved, progress.total)} ${progress.resolved}/${progress.total}`),
|
|
27565
27704
|
blocked ? React.createElement(Text, { color: "red" }, ` | ${blocked} blocked`) : null,
|
|
27566
|
-
React.createElement(Text, { color: "gray" }, " |
|
|
27705
|
+
React.createElement(Text, { color: "gray" }, " | esc then w toggle")
|
|
27567
27706
|
),
|
|
27568
27707
|
expanded ? React.createElement(
|
|
27569
27708
|
Box,
|
|
@@ -27684,15 +27823,15 @@ function formatElapsed2(ms2) {
|
|
|
27684
27823
|
if (minutes > 0) return `${minutes}m ${String(seconds).padStart(2, "0")}s`;
|
|
27685
27824
|
return `${seconds}s`;
|
|
27686
27825
|
}
|
|
27687
|
-
function
|
|
27826
|
+
function InteractionPanel({ state, shortcutMode }) {
|
|
27688
27827
|
if (state.inputMode === "starting") return React.createElement(LoadingBar);
|
|
27689
27828
|
if (state.permission) return React.createElement(PermissionBar, { state });
|
|
27690
27829
|
if (state.inputMode === "provider") return React.createElement(ProviderSelector, { state });
|
|
27691
27830
|
if (state.inputMode === "agent") return React.createElement(AgentSelector, { state });
|
|
27692
27831
|
if (state.inputMode === "permissionPreset") return React.createElement(PermissionPresetSelector, { state });
|
|
27693
27832
|
if (state.inputMode === "model") return React.createElement(ModelEditor, { state });
|
|
27694
|
-
if (state.inputMode === "running") return React.createElement(CommandBar, { state });
|
|
27695
|
-
if (state.inputMode === "prompt") return React.createElement(PromptBar, { state });
|
|
27833
|
+
if (state.inputMode === "running") return React.createElement(CommandBar, { state, shortcutMode });
|
|
27834
|
+
if (state.inputMode === "prompt") return React.createElement(PromptBar, { state, shortcutMode });
|
|
27696
27835
|
return React.createElement(PermissionBar, { state });
|
|
27697
27836
|
}
|
|
27698
27837
|
function LoadingBar() {
|
|
@@ -27700,58 +27839,72 @@ function LoadingBar() {
|
|
|
27700
27839
|
Box,
|
|
27701
27840
|
{ flexDirection: "column", borderStyle: "double", paddingX: 1 },
|
|
27702
27841
|
React.createElement(Text, { color: "cyan", bold: true }, "loading"),
|
|
27703
|
-
React.createElement(Text, { color: "gray" }, "demian is preparing the session |
|
|
27842
|
+
React.createElement(Text, { color: "gray" }, "demian is preparing the session | type /exit after loading to quit")
|
|
27704
27843
|
);
|
|
27705
27844
|
}
|
|
27706
|
-
function
|
|
27845
|
+
function shortcutHelp(state) {
|
|
27846
|
+
const parts = ["esc cancel"];
|
|
27847
|
+
if (state.inputMode === "prompt") parts.push("p provider", "a agent", "m model", "o permissions", "u clear");
|
|
27848
|
+
if (state.inputMode === "running") parts.push("s stop");
|
|
27849
|
+
if (state.turnDiff) parts.push("d diff");
|
|
27850
|
+
if (state.blocks.some((block) => block.kind === "tool")) parts.push("t tools");
|
|
27851
|
+
if (state.workPlan || state.inputMode === "running") parts.push("w plan");
|
|
27852
|
+
if (state.pendingClaudeCodePlan) parts.push("e use CC plan");
|
|
27853
|
+
if (state.canRetryLastPrompt) parts.push("r retry");
|
|
27854
|
+
parts.push("q quit");
|
|
27855
|
+
return `shortcut: ${parts.join(" | ")}`;
|
|
27856
|
+
}
|
|
27857
|
+
function PromptBar({ state, shortcutMode }) {
|
|
27707
27858
|
const value = state.promptInput || "Type first message and press Enter";
|
|
27708
|
-
const
|
|
27709
|
-
const toolHelp = state.blocks.some((block) => block.kind === "tool") ? " | ctrl+t tools" : "";
|
|
27710
|
-
const planHelp = state.workPlan || state.inputMode === "running" ? " | ctrl+p plan" : "";
|
|
27711
|
-
const claudeCodePlanHelp = state.pendingClaudeCodePlan ? " | ctrl+e use CC plan" : "";
|
|
27712
|
-
const retryHelp = state.canRetryLastPrompt ? " | ctrl+r retry" : "";
|
|
27859
|
+
const hint = shortcutMode ? shortcutHelp(state) : "enter send | esc shortcuts | up/down history | /cowork | /compact | /retry | /exit";
|
|
27713
27860
|
return React.createElement(
|
|
27714
27861
|
Box,
|
|
27715
|
-
{
|
|
27862
|
+
{ alignSelf: "center", width: promptPanelWidth(), flexDirection: "column", marginTop: 1 },
|
|
27863
|
+
React.createElement(SessionMetaBox, { state, marginTop: 0 }),
|
|
27716
27864
|
React.createElement(
|
|
27717
27865
|
Box,
|
|
27718
|
-
|
|
27719
|
-
React.createElement(
|
|
27720
|
-
|
|
27721
|
-
|
|
27722
|
-
|
|
27723
|
-
|
|
27866
|
+
{ flexDirection: "column", borderStyle: "double", borderColor: shortcutMode ? "cyan" : "blue", paddingX: 2, paddingY: 1, marginTop: 1 },
|
|
27867
|
+
React.createElement(
|
|
27868
|
+
Box,
|
|
27869
|
+
null,
|
|
27870
|
+
React.createElement(Text, { color: "cyan", bold: true }, "> "),
|
|
27871
|
+
React.createElement(Text, { color: state.promptInput ? "white" : "gray" }, value)
|
|
27872
|
+
),
|
|
27873
|
+
state.promptError ? React.createElement(Text, { color: "yellow" }, state.promptError) : React.createElement(Text, { color: shortcutMode ? "cyan" : "gray" }, hint)
|
|
27874
|
+
)
|
|
27724
27875
|
);
|
|
27725
27876
|
}
|
|
27726
|
-
function CommandBar({ state }) {
|
|
27877
|
+
function CommandBar({ state, shortcutMode }) {
|
|
27727
27878
|
const value = state.promptInput || "Type /stop to stop or /exit to quit";
|
|
27728
|
-
const
|
|
27729
|
-
const toolHelp = state.blocks.some((block) => block.kind === "tool") ? " | ctrl+t tools" : "";
|
|
27730
|
-
const planHelp = state.workPlan || state.inputMode === "running" ? " | ctrl+p plan" : "";
|
|
27879
|
+
const hint = shortcutMode ? shortcutHelp(state) : "running | /stop stop | /exit quit | esc shortcuts";
|
|
27731
27880
|
return React.createElement(
|
|
27732
27881
|
Box,
|
|
27733
|
-
{
|
|
27882
|
+
{ alignSelf: "center", width: promptPanelWidth(), flexDirection: "column", marginTop: 1 },
|
|
27883
|
+
React.createElement(SessionMetaBox, { state, marginTop: 0 }),
|
|
27734
27884
|
React.createElement(
|
|
27735
27885
|
Box,
|
|
27736
|
-
|
|
27737
|
-
React.createElement(
|
|
27738
|
-
|
|
27739
|
-
|
|
27740
|
-
|
|
27741
|
-
|
|
27886
|
+
{ flexDirection: "column", borderStyle: "double", borderColor: shortcutMode ? "cyan" : "yellow", paddingX: 2, paddingY: 1, marginTop: 1 },
|
|
27887
|
+
React.createElement(
|
|
27888
|
+
Box,
|
|
27889
|
+
null,
|
|
27890
|
+
React.createElement(Text, { color: "yellow", bold: true }, ": "),
|
|
27891
|
+
React.createElement(Text, { color: state.promptInput ? "white" : "gray" }, value)
|
|
27892
|
+
),
|
|
27893
|
+
state.promptError ? React.createElement(Text, { color: "yellow" }, state.promptError) : React.createElement(Text, { color: shortcutMode ? "cyan" : "gray" }, hint)
|
|
27894
|
+
)
|
|
27742
27895
|
);
|
|
27743
27896
|
}
|
|
27744
27897
|
function ProviderSelector({ state }) {
|
|
27745
27898
|
const items = state.providerOptions;
|
|
27746
27899
|
return React.createElement(
|
|
27747
|
-
|
|
27748
|
-
{
|
|
27749
|
-
React.createElement(Text, { color: "
|
|
27900
|
+
DialogFrame,
|
|
27901
|
+
{ title: "Providers", accent: "magenta" },
|
|
27902
|
+
React.createElement(Text, { color: "gray" }, `${"Provider".padEnd(22)} ${"Model".padEnd(30)} Status`),
|
|
27750
27903
|
...items.map(
|
|
27751
27904
|
(item, index) => React.createElement(
|
|
27752
27905
|
Text,
|
|
27753
27906
|
{ key: item.name, color: index === state.providerCursor ? "cyan" : item.available === false ? "gray" : "white", bold: index === state.providerCursor },
|
|
27754
|
-
`${index === state.providerCursor ? ">" : " "} ${item.label ?? item.name}
|
|
27907
|
+
`${index === state.providerCursor ? ">" : " "} ${shorten(item.label ?? item.name, 20).padEnd(20)} ${shorten((item.modelLabel ?? item.model) || "-", 30).padEnd(30)} ${providerStatusLabel(item)}`
|
|
27755
27908
|
)
|
|
27756
27909
|
),
|
|
27757
27910
|
React.createElement(Text, { color: "gray" }, "up/down select | enter apply | esc cancel")
|
|
@@ -27760,9 +27913,8 @@ function ProviderSelector({ state }) {
|
|
|
27760
27913
|
function AgentSelector({ state }) {
|
|
27761
27914
|
const items = state.agentOptions;
|
|
27762
27915
|
return React.createElement(
|
|
27763
|
-
|
|
27764
|
-
{
|
|
27765
|
-
React.createElement(Text, { color: "cyan", bold: true }, "Select agent"),
|
|
27916
|
+
DialogFrame,
|
|
27917
|
+
{ title: "Agents", accent: "magenta" },
|
|
27766
27918
|
...items.map(
|
|
27767
27919
|
(item, index) => React.createElement(
|
|
27768
27920
|
Text,
|
|
@@ -27775,9 +27927,8 @@ function AgentSelector({ state }) {
|
|
|
27775
27927
|
}
|
|
27776
27928
|
function PermissionPresetSelector({ state }) {
|
|
27777
27929
|
return React.createElement(
|
|
27778
|
-
|
|
27779
|
-
{
|
|
27780
|
-
React.createElement(Text, { color: "cyan", bold: true }, "Default permission"),
|
|
27930
|
+
DialogFrame,
|
|
27931
|
+
{ title: "Default Permission", accent: "magenta" },
|
|
27781
27932
|
...PERMISSION_PRESETS.map(
|
|
27782
27933
|
(item, index) => React.createElement(
|
|
27783
27934
|
Text,
|
|
@@ -27798,16 +27949,15 @@ function ModelEditor({ state }) {
|
|
|
27798
27949
|
const current = state.selection?.model ?? "";
|
|
27799
27950
|
const value = state.modelInput || `Keep ${current}`;
|
|
27800
27951
|
return React.createElement(
|
|
27801
|
-
|
|
27802
|
-
{
|
|
27803
|
-
React.createElement(Text, { color: "cyan", bold: true }, "Model"),
|
|
27952
|
+
DialogFrame,
|
|
27953
|
+
{ title: "Model", accent: "magenta" },
|
|
27804
27954
|
React.createElement(
|
|
27805
27955
|
Box,
|
|
27806
27956
|
null,
|
|
27807
27957
|
React.createElement(Text, { color: "cyan", bold: true }, "> "),
|
|
27808
27958
|
React.createElement(Text, { color: state.modelInput ? "white" : "gray" }, value)
|
|
27809
27959
|
),
|
|
27810
|
-
state.settingsError ? React.createElement(Text, { color: "yellow" }, state.settingsError) : React.createElement(Text, { color: "gray" }, "enter apply |
|
|
27960
|
+
state.settingsError ? React.createElement(Text, { color: "yellow" }, state.settingsError) : React.createElement(Text, { color: "gray" }, "enter apply | backspace edit | esc cancel")
|
|
27811
27961
|
);
|
|
27812
27962
|
}
|
|
27813
27963
|
function PermissionBar({ state }) {
|
|
@@ -27817,18 +27967,48 @@ function PermissionBar({ state }) {
|
|
|
27817
27967
|
}
|
|
27818
27968
|
const detailLines = describeToolInput(pending.request.tool, pending.request.input);
|
|
27819
27969
|
return React.createElement(
|
|
27820
|
-
|
|
27821
|
-
{
|
|
27822
|
-
React.createElement(Text, { color: "yellow", bold: true }, "Permission required"),
|
|
27970
|
+
DialogFrame,
|
|
27971
|
+
{ title: "Permission Required", accent: "yellow" },
|
|
27823
27972
|
React.createElement(Text, null, `Allow ${toolLabel(pending.request.tool, pending.request.input)}?`),
|
|
27824
27973
|
...detailLines.map((line, index) => React.createElement(Text, { key: index, color: "white" }, line)),
|
|
27825
27974
|
...permissionShortcutLines().map((line, index) => React.createElement(Text, { key: `shortcut-${index}`, color: "cyan", bold: true }, line))
|
|
27826
27975
|
);
|
|
27827
27976
|
}
|
|
27977
|
+
function DialogFrame({ title, accent, children }) {
|
|
27978
|
+
return React.createElement(
|
|
27979
|
+
Box,
|
|
27980
|
+
{ alignSelf: "center", width: dialogPanelWidth(), flexDirection: "column", borderStyle: "round", borderColor: accent, paddingX: 2, paddingY: 1, marginTop: 1 },
|
|
27981
|
+
React.createElement(Text, { color: accent, bold: true }, title),
|
|
27982
|
+
React.createElement(Box, { height: 1 }),
|
|
27983
|
+
children
|
|
27984
|
+
);
|
|
27985
|
+
}
|
|
27986
|
+
function providerStatusLabel(item) {
|
|
27987
|
+
if (item.available !== false) return "ready";
|
|
27988
|
+
if (item.catalog?.status === "missing-auth") return "auth";
|
|
27989
|
+
if (item.catalog?.status === "unavailable") return "offline";
|
|
27990
|
+
return "n/a";
|
|
27991
|
+
}
|
|
27828
27992
|
function shorten(value, max) {
|
|
27829
27993
|
if (value.length <= max) return value;
|
|
27830
27994
|
return `\u2026${value.slice(value.length - max + 1)}`;
|
|
27831
27995
|
}
|
|
27996
|
+
function terminalHeight() {
|
|
27997
|
+
const rows = process.stdout.rows;
|
|
27998
|
+
return typeof rows === "number" && Number.isFinite(rows) && rows > 0 ? Math.max(18, rows - 1) : 24;
|
|
27999
|
+
}
|
|
28000
|
+
function terminalWidth() {
|
|
28001
|
+
const columns = process.stdout.columns;
|
|
28002
|
+
return typeof columns === "number" && Number.isFinite(columns) && columns > 0 ? Math.max(48, columns) : 100;
|
|
28003
|
+
}
|
|
28004
|
+
function promptPanelWidth() {
|
|
28005
|
+
const columns = terminalWidth();
|
|
28006
|
+
return Math.max(40, Math.min(96, columns - 8, Math.floor(columns * 0.86)));
|
|
28007
|
+
}
|
|
28008
|
+
function dialogPanelWidth() {
|
|
28009
|
+
const columns = terminalWidth();
|
|
28010
|
+
return Math.max(48, Math.min(92, columns - 10, Math.floor(columns * 0.78)));
|
|
28011
|
+
}
|
|
27832
28012
|
function formatTokens(value) {
|
|
27833
28013
|
const tokens = typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.round(value)) : 0;
|
|
27834
28014
|
if (tokens >= 1e6) return `${trimDecimal2(tokens / 1e6)}m`;
|
|
@@ -27842,12 +28022,20 @@ function clamp01(value) {
|
|
|
27842
28022
|
if (!Number.isFinite(value)) return 0;
|
|
27843
28023
|
return Math.max(0, Math.min(1, value));
|
|
27844
28024
|
}
|
|
28025
|
+
var DEMIAN_WORDMARK_LINES;
|
|
27845
28026
|
var init_app = __esm({
|
|
27846
28027
|
"src/ui/tui/app.ts"() {
|
|
27847
28028
|
"use strict";
|
|
27848
28029
|
init_store();
|
|
27849
28030
|
init_presets();
|
|
27850
28031
|
init_tool_summary();
|
|
28032
|
+
DEMIAN_WORDMARK_LINES = [
|
|
28033
|
+
" _ _ ",
|
|
28034
|
+
" __| | ___ _ __ ___ (_) __ _ _ __ ",
|
|
28035
|
+
" / _` |/ _ \\ '_ ` _ \\| |/ _` | '_ \\ ",
|
|
28036
|
+
"| (_| | __/ | | | | | | (_| | | | |",
|
|
28037
|
+
" \\__,_|\\___|_| |_| |_|_|\\__,_|_| |_|"
|
|
28038
|
+
];
|
|
27851
28039
|
}
|
|
27852
28040
|
});
|
|
27853
28041
|
|
|
@@ -30877,7 +31065,7 @@ async function runExaSearch(config, options) {
|
|
|
30877
31065
|
return searchResult("exa", options.query, results, json.value);
|
|
30878
31066
|
}
|
|
30879
31067
|
function resolveApiKey(provider, config) {
|
|
30880
|
-
const value = config.apiKey
|
|
31068
|
+
const value = config.apiKey || (config.apiKeyEnv ? process.env[config.apiKeyEnv] : void 0);
|
|
30881
31069
|
if (value) return { ok: true, value };
|
|
30882
31070
|
return toolFail(`Missing API key for web_search provider "${provider}". Set webSearch.providers.${provider}.apiKey or set ${config.apiKeyEnv ?? "the configured apiKeyEnv"}.`);
|
|
30883
31071
|
}
|
|
@@ -33864,7 +34052,7 @@ function providerOptions(config, catalogs = {}) {
|
|
|
33864
34052
|
isDefault: model.isDefault
|
|
33865
34053
|
})) : providerModelProfiles(name, provider);
|
|
33866
34054
|
const modelProfiles = profiles.map((profile) => {
|
|
33867
|
-
const displayName = profile
|
|
34055
|
+
const displayName = displayModelForProfile(profile);
|
|
33868
34056
|
return {
|
|
33869
34057
|
...profile,
|
|
33870
34058
|
label: available ? displayName : unavailableLabel(displayName),
|
|
@@ -33872,7 +34060,7 @@ function providerOptions(config, catalogs = {}) {
|
|
|
33872
34060
|
};
|
|
33873
34061
|
});
|
|
33874
34062
|
const models = modelProfiles.length ? [...new Set(modelProfiles.map((item) => item.model).filter((item) => typeof item === "string" && item.trim()))] : providerModelOptions(name, provider);
|
|
33875
|
-
const defaultModel =
|
|
34063
|
+
const defaultModel = defaultDisplayModelForProvider(name, provider);
|
|
33876
34064
|
return {
|
|
33877
34065
|
name,
|
|
33878
34066
|
label: available ? name : unavailableLabel(name),
|
|
@@ -33935,13 +34123,18 @@ function createInteractiveModelSelection(config, flags = {}, saved) {
|
|
|
33935
34123
|
}
|
|
33936
34124
|
const usesSavedProvider = !flags.provider && savedProviderExists && providerName === savedProviderName;
|
|
33937
34125
|
const savedModel = usesSavedProvider && saved?.model ? saved.model : void 0;
|
|
33938
|
-
const
|
|
34126
|
+
const profiles = providerModelProfiles(providerName, providerConfig);
|
|
34127
|
+
const savedProfile = savedModel ? profiles.find((profile) => profile.model === savedModel || profile.displayName === savedModel || profile.name === savedModel) : void 0;
|
|
34128
|
+
const defaultModel = displayModelForProfile(profiles[0] ?? { name: "", displayName: "", model: "" }) || defaultDisplayModelForProvider(providerName, providerConfig);
|
|
34129
|
+
const flagProfile = flags.model ? profiles.find((profile) => profile.model === flags.model || profile.displayName === flags.model || profile.name === flags.model) : void 0;
|
|
34130
|
+
const selectedProfile = flags.model ? flagProfile : savedModel ? savedProfile : profiles[0];
|
|
34131
|
+
const model = flags.model ?? (savedProfile ? displayModelForProfile(savedProfile) : savedModel) ?? defaultModel;
|
|
33939
34132
|
return {
|
|
33940
34133
|
providerName,
|
|
33941
34134
|
providerSource: flags.provider ? "flag" : usesSavedProvider ? "saved" : "config",
|
|
33942
34135
|
model,
|
|
33943
34136
|
modelSource: flags.model ? "flag" : savedModel ? "saved" : "config",
|
|
33944
|
-
modelProfileName:
|
|
34137
|
+
modelProfileName: selectedProfile?.name
|
|
33945
34138
|
};
|
|
33946
34139
|
}
|
|
33947
34140
|
function providerCatalogAvailable(catalog) {
|
|
@@ -34244,6 +34437,7 @@ var init_controller = __esm({
|
|
|
34244
34437
|
|
|
34245
34438
|
// src/tui.ts
|
|
34246
34439
|
init_parser();
|
|
34440
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
34247
34441
|
|
|
34248
34442
|
// src/doctor/policies.ts
|
|
34249
34443
|
import { existsSync } from "node:fs";
|
|
@@ -34492,18 +34686,21 @@ function defaultUserConfig(defaultProvider = detectDefaultProvider()) {
|
|
|
34492
34686
|
openai: {
|
|
34493
34687
|
type: "openai-compatible",
|
|
34494
34688
|
baseURL: "https://api.openai.com/v1",
|
|
34689
|
+
apiKey: "",
|
|
34495
34690
|
apiKeyEnv: "OPENAI_API_KEY",
|
|
34496
34691
|
catalog: { type: "openai-models", endpoint: "https://api.openai.com/v1/models" }
|
|
34497
34692
|
},
|
|
34498
34693
|
anthropic: {
|
|
34499
34694
|
type: "anthropic",
|
|
34500
34695
|
baseURL: "https://api.anthropic.com/v1",
|
|
34696
|
+
apiKey: "",
|
|
34501
34697
|
apiKeyEnv: "ANTHROPIC_API_KEY",
|
|
34502
34698
|
catalog: { type: "anthropic-models", endpoint: "https://api.anthropic.com/v1/models" }
|
|
34503
34699
|
},
|
|
34504
34700
|
gemini: {
|
|
34505
34701
|
type: "openai-compatible",
|
|
34506
34702
|
baseURL: "https://generativelanguage.googleapis.com/v1beta/openai/",
|
|
34703
|
+
apiKey: "",
|
|
34507
34704
|
apiKeyEnv: "GEMINI_API_KEY",
|
|
34508
34705
|
apiKeyEnvAliases: ["GOOGLE_API_KEY"],
|
|
34509
34706
|
catalog: { type: "gemini-openai-models", endpoint: "https://generativelanguage.googleapis.com/v1beta/openai/models" }
|
|
@@ -34511,6 +34708,7 @@ function defaultUserConfig(defaultProvider = detectDefaultProvider()) {
|
|
|
34511
34708
|
groq: {
|
|
34512
34709
|
type: "openai-compatible",
|
|
34513
34710
|
baseURL: "https://api.groq.com/openai/v1",
|
|
34711
|
+
apiKey: "",
|
|
34514
34712
|
apiKeyEnv: "GROQ_API_KEY",
|
|
34515
34713
|
catalog: { type: "groq-models", endpoint: "https://api.groq.com/openai/v1/models" }
|
|
34516
34714
|
},
|
|
@@ -34523,6 +34721,7 @@ function defaultUserConfig(defaultProvider = detectDefaultProvider()) {
|
|
|
34523
34721
|
displayName: "Azure example",
|
|
34524
34722
|
model: "azure-deployment-name",
|
|
34525
34723
|
baseURL: "https://example.openai.azure.com/openai/v1",
|
|
34724
|
+
apiKey: "",
|
|
34526
34725
|
apiKeyEnv: "AZURE_OPENAI_API_KEY"
|
|
34527
34726
|
}
|
|
34528
34727
|
]
|
|
@@ -34531,31 +34730,37 @@ function defaultUserConfig(defaultProvider = detectDefaultProvider()) {
|
|
|
34531
34730
|
type: "openai-compatible",
|
|
34532
34731
|
baseURL: "http://localhost:1234/v1",
|
|
34533
34732
|
apiKey: "lm-studio",
|
|
34733
|
+
modelProfiles: [],
|
|
34534
34734
|
catalog: { type: "openai-compatible-models", endpoint: "http://localhost:1234/v1/models" }
|
|
34535
34735
|
},
|
|
34536
34736
|
"ollama-local": {
|
|
34537
34737
|
type: "openai-compatible",
|
|
34538
34738
|
baseURL: "http://localhost:11434/v1",
|
|
34539
34739
|
apiKey: "ollama",
|
|
34740
|
+
modelProfiles: [],
|
|
34540
34741
|
quirks: { omitTemperature: true },
|
|
34541
34742
|
catalog: { type: "openai-compatible-models", endpoint: "http://localhost:11434/v1/models" }
|
|
34542
34743
|
},
|
|
34543
34744
|
"ollama-cloud": {
|
|
34544
34745
|
type: "ollama",
|
|
34545
34746
|
baseURL: "https://ollama.com/api",
|
|
34747
|
+
apiKey: "",
|
|
34546
34748
|
apiKeyEnv: "OLLAMA_API_KEY",
|
|
34749
|
+
modelProfiles: [],
|
|
34547
34750
|
catalog: { type: "ollama-tags", endpoint: "https://ollama.com/api/tags" }
|
|
34548
34751
|
},
|
|
34549
34752
|
llamacpp: {
|
|
34550
34753
|
type: "openai-compatible",
|
|
34551
34754
|
baseURL: "http://localhost:8080/v1",
|
|
34552
34755
|
apiKey: "llama.cpp",
|
|
34756
|
+
modelProfiles: [],
|
|
34553
34757
|
catalog: { type: "openai-compatible-models", endpoint: "http://localhost:8080/v1/models" }
|
|
34554
34758
|
},
|
|
34555
34759
|
vllm: {
|
|
34556
34760
|
type: "openai-compatible",
|
|
34557
34761
|
baseURL: "http://localhost:8000/v1",
|
|
34558
34762
|
apiKey: "vllm",
|
|
34763
|
+
modelProfiles: [],
|
|
34559
34764
|
catalog: { type: "openai-compatible-models", endpoint: "http://localhost:8000/v1/models" }
|
|
34560
34765
|
},
|
|
34561
34766
|
codex: {
|
|
@@ -34627,7 +34832,7 @@ async function addModelProfile(options) {
|
|
|
34627
34832
|
displayName,
|
|
34628
34833
|
model: options.model,
|
|
34629
34834
|
...options.baseURL ? { baseURL: options.baseURL } : {},
|
|
34630
|
-
...options.apiKey ? { apiKey: options.apiKey } : {},
|
|
34835
|
+
...options.apiKey !== void 0 || options.apiKeyEnv ? { apiKey: options.apiKey ?? "" } : {},
|
|
34631
34836
|
...options.apiKeyEnv ? { apiKeyEnv: options.apiKeyEnv } : {}
|
|
34632
34837
|
};
|
|
34633
34838
|
if (existingByName >= 0) profiles[existingByName] = next;
|
|
@@ -34649,18 +34854,15 @@ async function readConfigObject(filePath) {
|
|
|
34649
34854
|
}
|
|
34650
34855
|
function providerPreset(options) {
|
|
34651
34856
|
const preset = options.preset ?? options.name;
|
|
34652
|
-
const auth =
|
|
34653
|
-
...options.apiKey ? { apiKey: options.apiKey } : {},
|
|
34654
|
-
...options.apiKeyEnv ? { apiKeyEnv: options.apiKeyEnv } : {}
|
|
34655
|
-
};
|
|
34857
|
+
const auth = apiKeyAuthFields(options);
|
|
34656
34858
|
const openAIAuth = options.authHeader ? { auth: { type: "api-key", header: options.authHeader } } : {};
|
|
34657
|
-
if (preset === "openai") return { type: "openai-compatible", baseURL: options.baseURL ?? "https://api.openai.com/v1",
|
|
34658
|
-
if (preset === "anthropic") return { type: "anthropic", baseURL: options.baseURL ?? "https://api.anthropic.com/v1",
|
|
34859
|
+
if (preset === "openai") return { type: "openai-compatible", baseURL: options.baseURL ?? "https://api.openai.com/v1", ...apiKeyAuthFields(options, "OPENAI_API_KEY"), ...openAIAuth, catalog: { type: "openai-models", endpoint: `${(options.baseURL ?? "https://api.openai.com/v1").replace(/\/+$/, "")}/models` } };
|
|
34860
|
+
if (preset === "anthropic") return { type: "anthropic", baseURL: options.baseURL ?? "https://api.anthropic.com/v1", ...apiKeyAuthFields(options, "ANTHROPIC_API_KEY"), catalog: { type: "anthropic-models", endpoint: `${(options.baseURL ?? "https://api.anthropic.com/v1").replace(/\/+$/, "")}/models` } };
|
|
34659
34861
|
if (preset === "gemini") {
|
|
34660
34862
|
const geminiBase = options.baseURL ?? "https://generativelanguage.googleapis.com/v1beta/openai/";
|
|
34661
|
-
return { type: "openai-compatible", baseURL: geminiBase,
|
|
34863
|
+
return { type: "openai-compatible", baseURL: geminiBase, ...apiKeyAuthFields(options, "GEMINI_API_KEY"), apiKeyEnvAliases: ["GOOGLE_API_KEY"], ...openAIAuth, catalog: { type: "gemini-openai-models", endpoint: `${geminiBase.replace(/\/+$/, "")}/models` } };
|
|
34662
34864
|
}
|
|
34663
|
-
if (preset === "groq") return { type: "openai-compatible", baseURL: options.baseURL ?? "https://api.groq.com/openai/v1",
|
|
34865
|
+
if (preset === "groq") return { type: "openai-compatible", baseURL: options.baseURL ?? "https://api.groq.com/openai/v1", ...apiKeyAuthFields(options, "GROQ_API_KEY"), ...openAIAuth, catalog: { type: "groq-models", endpoint: `${(options.baseURL ?? "https://api.groq.com/openai/v1").replace(/\/+$/, "")}/models` } };
|
|
34664
34866
|
if (preset === "azure") {
|
|
34665
34867
|
return {
|
|
34666
34868
|
type: "openai-compatible",
|
|
@@ -34672,16 +34874,17 @@ function providerPreset(options) {
|
|
|
34672
34874
|
displayName: "Azure example",
|
|
34673
34875
|
model: "azure-deployment-name",
|
|
34674
34876
|
baseURL: options.baseURL ?? "https://example.openai.azure.com/openai/v1",
|
|
34877
|
+
...options.apiKey ? {} : { apiKey: "" },
|
|
34675
34878
|
apiKeyEnv: options.apiKeyEnv ?? "AZURE_OPENAI_API_KEY"
|
|
34676
34879
|
}
|
|
34677
34880
|
]
|
|
34678
34881
|
};
|
|
34679
34882
|
}
|
|
34680
|
-
if (preset === "lmstudio") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:1234/v1", apiKey: options.apiKey ?? "lm-studio", catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:1234/v1").replace(/\/+$/, "")}/models` } };
|
|
34681
|
-
if (preset === "ollama-local" || preset === "ollama") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:11434/v1", apiKey: options.apiKey ?? "ollama", quirks: { omitTemperature: true }, catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:11434/v1").replace(/\/+$/, "")}/models` } };
|
|
34682
|
-
if (preset === "ollama-cloud") return { type: "ollama", baseURL: options.baseURL ?? "https://ollama.com/api", ...
|
|
34683
|
-
if (preset === "llamacpp") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:8080/v1", apiKey: options.apiKey ?? "llama.cpp", catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:8080/v1").replace(/\/+$/, "")}/models` } };
|
|
34684
|
-
if (preset === "vllm") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:8000/v1", apiKey: options.apiKey ?? "vllm", catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:8000/v1").replace(/\/+$/, "")}/models` } };
|
|
34883
|
+
if (preset === "lmstudio") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:1234/v1", apiKey: options.apiKey ?? "lm-studio", modelProfiles: [], catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:1234/v1").replace(/\/+$/, "")}/models` } };
|
|
34884
|
+
if (preset === "ollama-local" || preset === "ollama") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:11434/v1", apiKey: options.apiKey ?? "ollama", modelProfiles: [], quirks: { omitTemperature: true }, catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:11434/v1").replace(/\/+$/, "")}/models` } };
|
|
34885
|
+
if (preset === "ollama-cloud") return { type: "ollama", baseURL: options.baseURL ?? "https://ollama.com/api", ...apiKeyAuthFields(options, "OLLAMA_API_KEY"), modelProfiles: [], catalog: { type: "ollama-tags", endpoint: `${(options.baseURL ?? "https://ollama.com/api").replace(/\/+$/, "")}/tags` } };
|
|
34886
|
+
if (preset === "llamacpp") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:8080/v1", apiKey: options.apiKey ?? "llama.cpp", modelProfiles: [], catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:8080/v1").replace(/\/+$/, "")}/models` } };
|
|
34887
|
+
if (preset === "vllm") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:8000/v1", apiKey: options.apiKey ?? "vllm", modelProfiles: [], catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:8000/v1").replace(/\/+$/, "")}/models` } };
|
|
34685
34888
|
if (preset === "codex") return { type: "codex", baseURL: options.baseURL ?? "https://chatgpt.com/backend-api/codex", authStore: "auto", allowApiKeyFallback: false, promptCacheKey: "root-session", catalog: { type: "codex-oauth-models" } };
|
|
34686
34889
|
if (preset === "claudecode") return { type: "claudecode", runtime: "agent-sdk", cliPath: "~/.local/bin/claude", cwdMode: "session", historyPolicy: "passthrough-resume", onInvalidResume: "fresh", attachmentFallback: "block", allowSubagents: false, sanitizeApiKeyEnv: true, authPreflight: true, useBareMode: false, usageLedgerScope: "process", sessionLock: true, abortPolicy: "record-only", catalog: { type: "claudecode-supported-models" } };
|
|
34687
34890
|
if ((options.type ?? preset) === "openai-compatible") {
|
|
@@ -34690,14 +34893,20 @@ function providerPreset(options) {
|
|
|
34690
34893
|
return {
|
|
34691
34894
|
type: "openai-compatible",
|
|
34692
34895
|
baseURL,
|
|
34693
|
-
...
|
|
34694
|
-
...options.apiKeyEnv ? { apiKeyEnv: options.apiKeyEnv } : {},
|
|
34896
|
+
...auth,
|
|
34695
34897
|
...openAIAuth,
|
|
34696
34898
|
catalog: { type: "openai-compatible-models", endpoint: `${baseURL.replace(/\/+$/, "")}/models` }
|
|
34697
34899
|
};
|
|
34698
34900
|
}
|
|
34699
34901
|
throw new Error(`Unknown provider preset: ${preset}`);
|
|
34700
34902
|
}
|
|
34903
|
+
function apiKeyAuthFields(options, defaultApiKeyEnv) {
|
|
34904
|
+
const apiKeyEnv = options.apiKeyEnv ?? defaultApiKeyEnv;
|
|
34905
|
+
return {
|
|
34906
|
+
...options.apiKey !== void 0 || apiKeyEnv ? { apiKey: options.apiKey ?? "" } : {},
|
|
34907
|
+
...apiKeyEnv ? { apiKeyEnv } : {}
|
|
34908
|
+
};
|
|
34909
|
+
}
|
|
34701
34910
|
async function writeJsonAtomic(filePath, content) {
|
|
34702
34911
|
await mkdir(path3.dirname(filePath), { recursive: true, mode: 448 });
|
|
34703
34912
|
const temp = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
@@ -35178,7 +35387,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
35178
35387
|
]);
|
|
35179
35388
|
const React2 = ReactModule.default;
|
|
35180
35389
|
const store = new TuiStore2();
|
|
35181
|
-
const instance = render(React2.createElement(TuiApp2, { store }));
|
|
35390
|
+
const instance = render(React2.createElement(TuiApp2, { store, version: packageVersion() }));
|
|
35182
35391
|
try {
|
|
35183
35392
|
const code = await runTuiSession2(flags, store);
|
|
35184
35393
|
setTimeout(() => instance.unmount(), 100);
|
|
@@ -35197,6 +35406,14 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
35197
35406
|
throw error;
|
|
35198
35407
|
}
|
|
35199
35408
|
}
|
|
35409
|
+
function packageVersion() {
|
|
35410
|
+
try {
|
|
35411
|
+
const metadata = JSON.parse(readFileSync2(new URL("../package.json", import.meta.url), "utf8"));
|
|
35412
|
+
return typeof metadata.version === "string" && metadata.version.trim() ? metadata.version : "dev";
|
|
35413
|
+
} catch {
|
|
35414
|
+
return "dev";
|
|
35415
|
+
}
|
|
35416
|
+
}
|
|
35200
35417
|
function parseArgs(argv) {
|
|
35201
35418
|
const out = { prompt: "", transcript: true, images: [] };
|
|
35202
35419
|
const rest = [];
|
|
@@ -35317,15 +35534,16 @@ Usage:
|
|
|
35317
35534
|
Default:
|
|
35318
35535
|
demian and demian-cli launch the Ink terminal UI.
|
|
35319
35536
|
The TUI shows provider/model defaults before asking for the first message.
|
|
35320
|
-
Press p to select provider, m to edit model, then Enter to send.
|
|
35321
|
-
Press a to select the main agent before sending a message.
|
|
35322
|
-
Press o to select the default permission preset: deny, ask, auto, or full.
|
|
35537
|
+
Press Esc then p to select provider, Esc then m to edit model, then Enter to send.
|
|
35538
|
+
Press Esc then a to select the main agent before sending a message.
|
|
35539
|
+
Press Esc then o to select the default permission preset: deny, ask, auto, or full.
|
|
35323
35540
|
Press up/down in the message composer to recall previous prompts.
|
|
35324
|
-
Provider/model selections are remembered in
|
|
35541
|
+
Provider/model selections are remembered in ~/.demian/preferences.json.
|
|
35325
35542
|
After each answer, the TUI returns to standby for the next message.
|
|
35326
35543
|
Use /cowork <task> to explicitly ask Demian to coordinate cowork sub agents in multi-agent mode.
|
|
35327
35544
|
Use /compact to compact current history, /stop to stop active work, and /exit or /quit to close the TUI.
|
|
35328
|
-
|
|
35545
|
+
Press Esc then q to quit, Esc then s to stop a running task, and Esc then u to clear the composer.
|
|
35546
|
+
Tool approvals show the requested command/path in a permission dialog.
|
|
35329
35547
|
Press y to allow once, a to always allow the grant scope, or n/Enter to deny.
|
|
35330
35548
|
Prompt arguments are still accepted as a compatibility shortcut.
|
|
35331
35549
|
|