@austinthesing/magic-shell 0.2.8 → 0.2.9
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/cli.js +56 -32
- package/dist/tui.js +56 -32
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -22914,13 +22914,13 @@ function getStatusBarContent() {
|
|
|
22914
22914
|
function getHelpBarContent() {
|
|
22915
22915
|
const theme = getTheme();
|
|
22916
22916
|
if (awaitingConfirmation) {
|
|
22917
|
-
return t`${fg(theme.colors.warning)(">>>
|
|
22917
|
+
return t`${fg(theme.colors.warning)(">>> Cmd+Enter or Enter to execute <<<")} ${fg(theme.colors.textMuted)("|")} ${fg(theme.colors.error)("Esc")}${fg(theme.colors.textMuted)(" Cancel")} ${fg(theme.colors.primary)("e")}${fg(theme.colors.textMuted)(" Edit")} ${fg(theme.colors.primary)("c")}${fg(theme.colors.textMuted)(" Copy")}`;
|
|
22918
22918
|
}
|
|
22919
22919
|
return t`${fg(theme.colors.primary)("Ctrl+X P")}${fg(theme.colors.textMuted)(" Commands")} ${fg(theme.colors.primary)("Ctrl+Y")}${fg(theme.colors.textMuted)(" Safety")} ${fg(theme.colors.primary)("Ctrl+Z")}${fg(theme.colors.textMuted)(" Exit")}`;
|
|
22920
22920
|
}
|
|
22921
22921
|
function getInputHintContent() {
|
|
22922
22922
|
const theme = getTheme();
|
|
22923
|
-
return t`${fg(theme.colors.textMuted)("Enter")}${fg(theme.colors.border)(" send")} ${fg(theme.colors.textMuted)("Shift+Enter")}${fg(theme.colors.border)(" newline")}
|
|
22923
|
+
return t`${fg(theme.colors.textMuted)("Enter")}${fg(theme.colors.border)(" send")} ${fg(theme.colors.textMuted)("Shift+Enter")}${fg(theme.colors.border)(" newline")}`;
|
|
22924
22924
|
}
|
|
22925
22925
|
function getWelcomeMessage() {
|
|
22926
22926
|
const providerName = config.provider === "opencode-zen" ? "OpenCode Zen" : "OpenRouter";
|
|
@@ -22965,13 +22965,15 @@ function addAssistantMessage(content, command, safety) {
|
|
|
22965
22965
|
renderMessage(msg);
|
|
22966
22966
|
return msg;
|
|
22967
22967
|
}
|
|
22968
|
-
function addResultMessage(content, exitCode) {
|
|
22968
|
+
function addResultMessage(content, exitCode, executionKind, parentMessageId) {
|
|
22969
22969
|
const msg = {
|
|
22970
22970
|
id: generateMessageId(),
|
|
22971
22971
|
type: "result",
|
|
22972
22972
|
content,
|
|
22973
22973
|
timestamp: Date.now(),
|
|
22974
|
-
exitCode
|
|
22974
|
+
exitCode,
|
|
22975
|
+
executionKind,
|
|
22976
|
+
parentMessageId
|
|
22975
22977
|
};
|
|
22976
22978
|
chatMessages.push(msg);
|
|
22977
22979
|
renderMessage(msg);
|
|
@@ -23016,7 +23018,7 @@ function createAssistantMessageRenderable(msg, theme) {
|
|
|
23016
23018
|
width: "100%",
|
|
23017
23019
|
border: true,
|
|
23018
23020
|
borderColor: isSelected ? theme.colors.primary : theme.colors.border,
|
|
23019
|
-
borderStyle: "
|
|
23021
|
+
borderStyle: "rounded",
|
|
23020
23022
|
paddingLeft: 1,
|
|
23021
23023
|
paddingRight: 1,
|
|
23022
23024
|
paddingTop: 0,
|
|
@@ -23025,34 +23027,32 @@ function createAssistantMessageRenderable(msg, theme) {
|
|
|
23025
23027
|
});
|
|
23026
23028
|
const commandText = new TextRenderable(renderer, {
|
|
23027
23029
|
id: `msg-${msg.id}-cmd`,
|
|
23028
|
-
content: t`${fg(theme.colors.textMuted)("Command:")} ${fg(theme.colors.
|
|
23030
|
+
content: t`${fg(theme.colors.textMuted)("Command:")} ${fg(theme.colors.secondary)(msg.command || "")}`
|
|
23029
23031
|
});
|
|
23030
23032
|
card.add(commandText);
|
|
23031
23033
|
if (msg.safety) {
|
|
23032
23034
|
const severityColor = getSeverityColor(msg.safety.severity);
|
|
23033
|
-
const
|
|
23035
|
+
const severityLabel = msg.safety.severity === "low" ? "Low risk" : `${msg.safety.severity[0].toUpperCase()}${msg.safety.severity.slice(1)} risk`;
|
|
23034
23036
|
const safetyText = new TextRenderable(renderer, {
|
|
23035
23037
|
id: `msg-${msg.id}-safety`,
|
|
23036
|
-
content: t`${fg(severityColor)(
|
|
23038
|
+
content: t`${fg(severityColor)(severityLabel)}`
|
|
23037
23039
|
});
|
|
23038
23040
|
card.add(safetyText);
|
|
23041
|
+
if (msg.safety.isDangerous && msg.safety.reason) {
|
|
23042
|
+
const reasonText = new TextRenderable(renderer, {
|
|
23043
|
+
id: `msg-${msg.id}-safety-reason`,
|
|
23044
|
+
content: t`${fg(theme.colors.textMuted)(msg.safety.reason)}`
|
|
23045
|
+
});
|
|
23046
|
+
card.add(reasonText);
|
|
23047
|
+
}
|
|
23039
23048
|
}
|
|
23040
23049
|
if (isSelected && !msg.executed) {
|
|
23041
23050
|
const actionsText = new TextRenderable(renderer, {
|
|
23042
23051
|
id: `msg-${msg.id}-actions`,
|
|
23043
|
-
content: t`${fg(theme.colors.warning)("
|
|
23052
|
+
content: t`${fg(theme.colors.warning)("Cmd+Enter or Enter to run")} ${fg(theme.colors.textMuted)("|")} ${fg(theme.colors.primary)("[c]")} ${fg(theme.colors.textMuted)("Copy")} ${fg(theme.colors.primary)("[e]")} ${fg(theme.colors.textMuted)("Edit")} ${fg(theme.colors.error)("[Esc]")} ${fg(theme.colors.textMuted)("Cancel")}`
|
|
23044
23053
|
});
|
|
23045
23054
|
card.add(actionsText);
|
|
23046
23055
|
}
|
|
23047
|
-
if (msg.executed) {
|
|
23048
|
-
const wasAutoRun = !msg.safety?.isDangerous;
|
|
23049
|
-
const execLabel = wasAutoRun ? "Auto-executed (safe)" : "Executed";
|
|
23050
|
-
const execText = new TextRenderable(renderer, {
|
|
23051
|
-
id: `msg-${msg.id}-exec`,
|
|
23052
|
-
content: t`${fg(theme.colors.success)("✓")} ${fg(theme.colors.success)(execLabel)}`
|
|
23053
|
-
});
|
|
23054
|
-
card.add(execText);
|
|
23055
|
-
}
|
|
23056
23056
|
return card;
|
|
23057
23057
|
}
|
|
23058
23058
|
function createResultMessageRenderable(msg, theme) {
|
|
@@ -23063,28 +23063,30 @@ function createResultMessageRenderable(msg, theme) {
|
|
|
23063
23063
|
`) : [];
|
|
23064
23064
|
const isLongOutput = outputLines.length > 5;
|
|
23065
23065
|
const PREVIEW_LINES = 3;
|
|
23066
|
+
const executionKind = msg.executionKind || "manual";
|
|
23066
23067
|
const card = new BoxRenderable(renderer, {
|
|
23067
23068
|
id: `msg-${msg.id}`,
|
|
23068
23069
|
flexDirection: "column",
|
|
23069
23070
|
width: "100%",
|
|
23070
23071
|
border: true,
|
|
23071
|
-
borderColor:
|
|
23072
|
-
borderStyle: "
|
|
23072
|
+
borderColor: theme.colors.border,
|
|
23073
|
+
borderStyle: "rounded",
|
|
23073
23074
|
paddingLeft: 1,
|
|
23074
23075
|
paddingRight: 1,
|
|
23076
|
+
paddingTop: 0,
|
|
23077
|
+
paddingBottom: 0,
|
|
23075
23078
|
backgroundColor: theme.colors.backgroundPanel,
|
|
23076
23079
|
onMouseDown: isLongOutput ? () => {
|
|
23077
23080
|
toggleResultExpand(msg.id);
|
|
23078
23081
|
} : undefined
|
|
23079
23082
|
});
|
|
23080
|
-
const statusIcon = isSuccess ? "✓" : "✗";
|
|
23081
23083
|
const statusColor = isSuccess ? theme.colors.success : theme.colors.error;
|
|
23082
|
-
const statusLabel = isSuccess ? "Executed
|
|
23084
|
+
const statusLabel = isSuccess ? executionKind === "auto" ? "Auto-executed (safe command)" : executionKind === "dry-run" ? "Dry run (not executed)" : "Executed (confirmed)" : `Command failed (exit code: ${msg.exitCode})`;
|
|
23083
23085
|
const expandIcon = isLongOutput ? isExpanded ? "▼" : "▶" : "";
|
|
23084
23086
|
const lineCount = isLongOutput ? ` (${outputLines.length} lines)` : "";
|
|
23085
23087
|
const statusText = new TextRenderable(renderer, {
|
|
23086
23088
|
id: `msg-${msg.id}-status`,
|
|
23087
|
-
content: t`${fg(statusColor)(
|
|
23089
|
+
content: t`${fg(statusColor)(">")} ${fg(statusColor)(statusLabel)}${fg(theme.colors.textMuted)(lineCount)} ${fg(theme.colors.primary)(expandIcon)}`
|
|
23088
23090
|
});
|
|
23089
23091
|
card.add(statusText);
|
|
23090
23092
|
if (hasOutput) {
|
|
@@ -23097,11 +23099,26 @@ function createResultMessageRenderable(msg, theme) {
|
|
|
23097
23099
|
`) + `
|
|
23098
23100
|
... ${outputLines.length - PREVIEW_LINES} more lines`;
|
|
23099
23101
|
}
|
|
23102
|
+
const outputBox = new BoxRenderable(renderer, {
|
|
23103
|
+
id: `msg-${msg.id}-output-box`,
|
|
23104
|
+
flexDirection: "column",
|
|
23105
|
+
width: "100%",
|
|
23106
|
+
border: true,
|
|
23107
|
+
borderColor: theme.colors.borderSubtle,
|
|
23108
|
+
borderStyle: "single",
|
|
23109
|
+
paddingLeft: 1,
|
|
23110
|
+
paddingRight: 1,
|
|
23111
|
+
paddingTop: 0,
|
|
23112
|
+
paddingBottom: 0,
|
|
23113
|
+
backgroundColor: theme.colors.backgroundElement,
|
|
23114
|
+
marginTop: 1
|
|
23115
|
+
});
|
|
23100
23116
|
const outputText = new TextRenderable(renderer, {
|
|
23101
23117
|
id: `msg-${msg.id}-output`,
|
|
23102
23118
|
content: t`${fg(theme.colors.textMuted)(displayContent)}`
|
|
23103
23119
|
});
|
|
23104
|
-
|
|
23120
|
+
outputBox.add(outputText);
|
|
23121
|
+
card.add(outputBox);
|
|
23105
23122
|
if (isLongOutput) {
|
|
23106
23123
|
const hintText = new TextRenderable(renderer, {
|
|
23107
23124
|
id: `msg-${msg.id}-hint`,
|
|
@@ -23275,6 +23292,8 @@ async function processDirectCommand(input, command) {
|
|
|
23275
23292
|
}
|
|
23276
23293
|
}
|
|
23277
23294
|
async function executeAndShowResult(input, command, assistantMsgId) {
|
|
23295
|
+
const executionKind = getExecutionKind(assistantMsgId, dryRunMode);
|
|
23296
|
+
updateAssistantMessage(assistantMsgId, { executed: true });
|
|
23278
23297
|
if (command.startsWith("cd ")) {
|
|
23279
23298
|
const path2 = command.slice(3).trim().replace(/^["']|["']$/g, "");
|
|
23280
23299
|
try {
|
|
@@ -23282,7 +23301,7 @@ async function executeAndShowResult(input, command, assistantMsgId) {
|
|
|
23282
23301
|
process.chdir(expandedPath);
|
|
23283
23302
|
currentCwd = getCwd();
|
|
23284
23303
|
statusBarText.content = getStatusBarContent();
|
|
23285
|
-
addResultMessage(`Changed directory to ${currentCwd}`, 0);
|
|
23304
|
+
addResultMessage(`Changed directory to ${currentCwd}`, 0, executionKind, assistantMsgId);
|
|
23286
23305
|
addToHistory({
|
|
23287
23306
|
input,
|
|
23288
23307
|
command,
|
|
@@ -23290,22 +23309,20 @@ async function executeAndShowResult(input, command, assistantMsgId) {
|
|
|
23290
23309
|
timestamp: Date.now()
|
|
23291
23310
|
});
|
|
23292
23311
|
history = loadHistory();
|
|
23293
|
-
updateAssistantMessage(assistantMsgId, { executed: true });
|
|
23294
23312
|
} catch (err) {
|
|
23295
|
-
addResultMessage(`cd: ${err instanceof Error ? err.message : String(err)}`, 1);
|
|
23313
|
+
addResultMessage(`cd: ${err instanceof Error ? err.message : String(err)}`, 1, executionKind, assistantMsgId);
|
|
23296
23314
|
}
|
|
23297
23315
|
clearCommandState();
|
|
23298
23316
|
return;
|
|
23299
23317
|
}
|
|
23300
23318
|
if (dryRunMode) {
|
|
23301
|
-
addResultMessage(`[DRY RUN] Would execute: ${command}`, 0);
|
|
23302
|
-
updateAssistantMessage(assistantMsgId, { executed: true });
|
|
23319
|
+
addResultMessage(`[DRY RUN] Would execute: ${command}`, 0, executionKind, assistantMsgId);
|
|
23303
23320
|
clearCommandState();
|
|
23304
23321
|
return;
|
|
23305
23322
|
}
|
|
23306
23323
|
try {
|
|
23307
23324
|
const { output, exitCode } = await executeCommandWithCode(command);
|
|
23308
|
-
addResultMessage(output || "Command completed successfully", exitCode);
|
|
23325
|
+
addResultMessage(output || "Command completed successfully", exitCode, executionKind, assistantMsgId);
|
|
23309
23326
|
addToHistory({
|
|
23310
23327
|
input,
|
|
23311
23328
|
command,
|
|
@@ -23313,13 +23330,20 @@ async function executeAndShowResult(input, command, assistantMsgId) {
|
|
|
23313
23330
|
timestamp: Date.now()
|
|
23314
23331
|
});
|
|
23315
23332
|
history = loadHistory();
|
|
23316
|
-
updateAssistantMessage(assistantMsgId, { executed: true });
|
|
23317
23333
|
} catch (error) {
|
|
23318
23334
|
const message = error instanceof Error ? error.message : String(error);
|
|
23319
|
-
addResultMessage(`Error: ${message}`, 1);
|
|
23335
|
+
addResultMessage(`Error: ${message}`, 1, executionKind, assistantMsgId);
|
|
23320
23336
|
}
|
|
23321
23337
|
clearCommandState();
|
|
23322
23338
|
}
|
|
23339
|
+
function getExecutionKind(assistantMsgId, isDryRun) {
|
|
23340
|
+
if (isDryRun)
|
|
23341
|
+
return "dry-run";
|
|
23342
|
+
const assistantMsg = chatMessages.find((msg) => msg.id === assistantMsgId);
|
|
23343
|
+
if (!assistantMsg || assistantMsg.type !== "assistant")
|
|
23344
|
+
return "manual";
|
|
23345
|
+
return assistantMsg.safety?.isDangerous ? "manual" : "auto";
|
|
23346
|
+
}
|
|
23323
23347
|
function executeCommandWithCode(command) {
|
|
23324
23348
|
return new Promise((resolve3, reject) => {
|
|
23325
23349
|
const child = spawn(command, {
|
package/dist/tui.js
CHANGED
|
@@ -22914,13 +22914,13 @@ function getStatusBarContent() {
|
|
|
22914
22914
|
function getHelpBarContent() {
|
|
22915
22915
|
const theme = getTheme();
|
|
22916
22916
|
if (awaitingConfirmation) {
|
|
22917
|
-
return t`${fg(theme.colors.warning)(">>>
|
|
22917
|
+
return t`${fg(theme.colors.warning)(">>> Cmd+Enter or Enter to execute <<<")} ${fg(theme.colors.textMuted)("|")} ${fg(theme.colors.error)("Esc")}${fg(theme.colors.textMuted)(" Cancel")} ${fg(theme.colors.primary)("e")}${fg(theme.colors.textMuted)(" Edit")} ${fg(theme.colors.primary)("c")}${fg(theme.colors.textMuted)(" Copy")}`;
|
|
22918
22918
|
}
|
|
22919
22919
|
return t`${fg(theme.colors.primary)("Ctrl+X P")}${fg(theme.colors.textMuted)(" Commands")} ${fg(theme.colors.primary)("Ctrl+Y")}${fg(theme.colors.textMuted)(" Safety")} ${fg(theme.colors.primary)("Ctrl+Z")}${fg(theme.colors.textMuted)(" Exit")}`;
|
|
22920
22920
|
}
|
|
22921
22921
|
function getInputHintContent() {
|
|
22922
22922
|
const theme = getTheme();
|
|
22923
|
-
return t`${fg(theme.colors.textMuted)("Enter")}${fg(theme.colors.border)(" send")} ${fg(theme.colors.textMuted)("Shift+Enter")}${fg(theme.colors.border)(" newline")}
|
|
22923
|
+
return t`${fg(theme.colors.textMuted)("Enter")}${fg(theme.colors.border)(" send")} ${fg(theme.colors.textMuted)("Shift+Enter")}${fg(theme.colors.border)(" newline")}`;
|
|
22924
22924
|
}
|
|
22925
22925
|
function getWelcomeMessage() {
|
|
22926
22926
|
const providerName = config.provider === "opencode-zen" ? "OpenCode Zen" : "OpenRouter";
|
|
@@ -22965,13 +22965,15 @@ function addAssistantMessage(content, command, safety) {
|
|
|
22965
22965
|
renderMessage(msg);
|
|
22966
22966
|
return msg;
|
|
22967
22967
|
}
|
|
22968
|
-
function addResultMessage(content, exitCode) {
|
|
22968
|
+
function addResultMessage(content, exitCode, executionKind, parentMessageId) {
|
|
22969
22969
|
const msg = {
|
|
22970
22970
|
id: generateMessageId(),
|
|
22971
22971
|
type: "result",
|
|
22972
22972
|
content,
|
|
22973
22973
|
timestamp: Date.now(),
|
|
22974
|
-
exitCode
|
|
22974
|
+
exitCode,
|
|
22975
|
+
executionKind,
|
|
22976
|
+
parentMessageId
|
|
22975
22977
|
};
|
|
22976
22978
|
chatMessages.push(msg);
|
|
22977
22979
|
renderMessage(msg);
|
|
@@ -23016,7 +23018,7 @@ function createAssistantMessageRenderable(msg, theme) {
|
|
|
23016
23018
|
width: "100%",
|
|
23017
23019
|
border: true,
|
|
23018
23020
|
borderColor: isSelected ? theme.colors.primary : theme.colors.border,
|
|
23019
|
-
borderStyle: "
|
|
23021
|
+
borderStyle: "rounded",
|
|
23020
23022
|
paddingLeft: 1,
|
|
23021
23023
|
paddingRight: 1,
|
|
23022
23024
|
paddingTop: 0,
|
|
@@ -23025,34 +23027,32 @@ function createAssistantMessageRenderable(msg, theme) {
|
|
|
23025
23027
|
});
|
|
23026
23028
|
const commandText = new TextRenderable(renderer, {
|
|
23027
23029
|
id: `msg-${msg.id}-cmd`,
|
|
23028
|
-
content: t`${fg(theme.colors.textMuted)("Command:")} ${fg(theme.colors.
|
|
23030
|
+
content: t`${fg(theme.colors.textMuted)("Command:")} ${fg(theme.colors.secondary)(msg.command || "")}`
|
|
23029
23031
|
});
|
|
23030
23032
|
card.add(commandText);
|
|
23031
23033
|
if (msg.safety) {
|
|
23032
23034
|
const severityColor = getSeverityColor(msg.safety.severity);
|
|
23033
|
-
const
|
|
23035
|
+
const severityLabel = msg.safety.severity === "low" ? "Low risk" : `${msg.safety.severity[0].toUpperCase()}${msg.safety.severity.slice(1)} risk`;
|
|
23034
23036
|
const safetyText = new TextRenderable(renderer, {
|
|
23035
23037
|
id: `msg-${msg.id}-safety`,
|
|
23036
|
-
content: t`${fg(severityColor)(
|
|
23038
|
+
content: t`${fg(severityColor)(severityLabel)}`
|
|
23037
23039
|
});
|
|
23038
23040
|
card.add(safetyText);
|
|
23041
|
+
if (msg.safety.isDangerous && msg.safety.reason) {
|
|
23042
|
+
const reasonText = new TextRenderable(renderer, {
|
|
23043
|
+
id: `msg-${msg.id}-safety-reason`,
|
|
23044
|
+
content: t`${fg(theme.colors.textMuted)(msg.safety.reason)}`
|
|
23045
|
+
});
|
|
23046
|
+
card.add(reasonText);
|
|
23047
|
+
}
|
|
23039
23048
|
}
|
|
23040
23049
|
if (isSelected && !msg.executed) {
|
|
23041
23050
|
const actionsText = new TextRenderable(renderer, {
|
|
23042
23051
|
id: `msg-${msg.id}-actions`,
|
|
23043
|
-
content: t`${fg(theme.colors.warning)("
|
|
23052
|
+
content: t`${fg(theme.colors.warning)("Cmd+Enter or Enter to run")} ${fg(theme.colors.textMuted)("|")} ${fg(theme.colors.primary)("[c]")} ${fg(theme.colors.textMuted)("Copy")} ${fg(theme.colors.primary)("[e]")} ${fg(theme.colors.textMuted)("Edit")} ${fg(theme.colors.error)("[Esc]")} ${fg(theme.colors.textMuted)("Cancel")}`
|
|
23044
23053
|
});
|
|
23045
23054
|
card.add(actionsText);
|
|
23046
23055
|
}
|
|
23047
|
-
if (msg.executed) {
|
|
23048
|
-
const wasAutoRun = !msg.safety?.isDangerous;
|
|
23049
|
-
const execLabel = wasAutoRun ? "Auto-executed (safe)" : "Executed";
|
|
23050
|
-
const execText = new TextRenderable(renderer, {
|
|
23051
|
-
id: `msg-${msg.id}-exec`,
|
|
23052
|
-
content: t`${fg(theme.colors.success)("✓")} ${fg(theme.colors.success)(execLabel)}`
|
|
23053
|
-
});
|
|
23054
|
-
card.add(execText);
|
|
23055
|
-
}
|
|
23056
23056
|
return card;
|
|
23057
23057
|
}
|
|
23058
23058
|
function createResultMessageRenderable(msg, theme) {
|
|
@@ -23063,28 +23063,30 @@ function createResultMessageRenderable(msg, theme) {
|
|
|
23063
23063
|
`) : [];
|
|
23064
23064
|
const isLongOutput = outputLines.length > 5;
|
|
23065
23065
|
const PREVIEW_LINES = 3;
|
|
23066
|
+
const executionKind = msg.executionKind || "manual";
|
|
23066
23067
|
const card = new BoxRenderable(renderer, {
|
|
23067
23068
|
id: `msg-${msg.id}`,
|
|
23068
23069
|
flexDirection: "column",
|
|
23069
23070
|
width: "100%",
|
|
23070
23071
|
border: true,
|
|
23071
|
-
borderColor:
|
|
23072
|
-
borderStyle: "
|
|
23072
|
+
borderColor: theme.colors.border,
|
|
23073
|
+
borderStyle: "rounded",
|
|
23073
23074
|
paddingLeft: 1,
|
|
23074
23075
|
paddingRight: 1,
|
|
23076
|
+
paddingTop: 0,
|
|
23077
|
+
paddingBottom: 0,
|
|
23075
23078
|
backgroundColor: theme.colors.backgroundPanel,
|
|
23076
23079
|
onMouseDown: isLongOutput ? () => {
|
|
23077
23080
|
toggleResultExpand(msg.id);
|
|
23078
23081
|
} : undefined
|
|
23079
23082
|
});
|
|
23080
|
-
const statusIcon = isSuccess ? "✓" : "✗";
|
|
23081
23083
|
const statusColor = isSuccess ? theme.colors.success : theme.colors.error;
|
|
23082
|
-
const statusLabel = isSuccess ? "Executed
|
|
23084
|
+
const statusLabel = isSuccess ? executionKind === "auto" ? "Auto-executed (safe command)" : executionKind === "dry-run" ? "Dry run (not executed)" : "Executed (confirmed)" : `Command failed (exit code: ${msg.exitCode})`;
|
|
23083
23085
|
const expandIcon = isLongOutput ? isExpanded ? "▼" : "▶" : "";
|
|
23084
23086
|
const lineCount = isLongOutput ? ` (${outputLines.length} lines)` : "";
|
|
23085
23087
|
const statusText = new TextRenderable(renderer, {
|
|
23086
23088
|
id: `msg-${msg.id}-status`,
|
|
23087
|
-
content: t`${fg(statusColor)(
|
|
23089
|
+
content: t`${fg(statusColor)(">")} ${fg(statusColor)(statusLabel)}${fg(theme.colors.textMuted)(lineCount)} ${fg(theme.colors.primary)(expandIcon)}`
|
|
23088
23090
|
});
|
|
23089
23091
|
card.add(statusText);
|
|
23090
23092
|
if (hasOutput) {
|
|
@@ -23097,11 +23099,26 @@ function createResultMessageRenderable(msg, theme) {
|
|
|
23097
23099
|
`) + `
|
|
23098
23100
|
... ${outputLines.length - PREVIEW_LINES} more lines`;
|
|
23099
23101
|
}
|
|
23102
|
+
const outputBox = new BoxRenderable(renderer, {
|
|
23103
|
+
id: `msg-${msg.id}-output-box`,
|
|
23104
|
+
flexDirection: "column",
|
|
23105
|
+
width: "100%",
|
|
23106
|
+
border: true,
|
|
23107
|
+
borderColor: theme.colors.borderSubtle,
|
|
23108
|
+
borderStyle: "single",
|
|
23109
|
+
paddingLeft: 1,
|
|
23110
|
+
paddingRight: 1,
|
|
23111
|
+
paddingTop: 0,
|
|
23112
|
+
paddingBottom: 0,
|
|
23113
|
+
backgroundColor: theme.colors.backgroundElement,
|
|
23114
|
+
marginTop: 1
|
|
23115
|
+
});
|
|
23100
23116
|
const outputText = new TextRenderable(renderer, {
|
|
23101
23117
|
id: `msg-${msg.id}-output`,
|
|
23102
23118
|
content: t`${fg(theme.colors.textMuted)(displayContent)}`
|
|
23103
23119
|
});
|
|
23104
|
-
|
|
23120
|
+
outputBox.add(outputText);
|
|
23121
|
+
card.add(outputBox);
|
|
23105
23122
|
if (isLongOutput) {
|
|
23106
23123
|
const hintText = new TextRenderable(renderer, {
|
|
23107
23124
|
id: `msg-${msg.id}-hint`,
|
|
@@ -23275,6 +23292,8 @@ async function processDirectCommand(input, command) {
|
|
|
23275
23292
|
}
|
|
23276
23293
|
}
|
|
23277
23294
|
async function executeAndShowResult(input, command, assistantMsgId) {
|
|
23295
|
+
const executionKind = getExecutionKind(assistantMsgId, dryRunMode);
|
|
23296
|
+
updateAssistantMessage(assistantMsgId, { executed: true });
|
|
23278
23297
|
if (command.startsWith("cd ")) {
|
|
23279
23298
|
const path2 = command.slice(3).trim().replace(/^["']|["']$/g, "");
|
|
23280
23299
|
try {
|
|
@@ -23282,7 +23301,7 @@ async function executeAndShowResult(input, command, assistantMsgId) {
|
|
|
23282
23301
|
process.chdir(expandedPath);
|
|
23283
23302
|
currentCwd = getCwd();
|
|
23284
23303
|
statusBarText.content = getStatusBarContent();
|
|
23285
|
-
addResultMessage(`Changed directory to ${currentCwd}`, 0);
|
|
23304
|
+
addResultMessage(`Changed directory to ${currentCwd}`, 0, executionKind, assistantMsgId);
|
|
23286
23305
|
addToHistory({
|
|
23287
23306
|
input,
|
|
23288
23307
|
command,
|
|
@@ -23290,22 +23309,20 @@ async function executeAndShowResult(input, command, assistantMsgId) {
|
|
|
23290
23309
|
timestamp: Date.now()
|
|
23291
23310
|
});
|
|
23292
23311
|
history = loadHistory();
|
|
23293
|
-
updateAssistantMessage(assistantMsgId, { executed: true });
|
|
23294
23312
|
} catch (err) {
|
|
23295
|
-
addResultMessage(`cd: ${err instanceof Error ? err.message : String(err)}`, 1);
|
|
23313
|
+
addResultMessage(`cd: ${err instanceof Error ? err.message : String(err)}`, 1, executionKind, assistantMsgId);
|
|
23296
23314
|
}
|
|
23297
23315
|
clearCommandState();
|
|
23298
23316
|
return;
|
|
23299
23317
|
}
|
|
23300
23318
|
if (dryRunMode) {
|
|
23301
|
-
addResultMessage(`[DRY RUN] Would execute: ${command}`, 0);
|
|
23302
|
-
updateAssistantMessage(assistantMsgId, { executed: true });
|
|
23319
|
+
addResultMessage(`[DRY RUN] Would execute: ${command}`, 0, executionKind, assistantMsgId);
|
|
23303
23320
|
clearCommandState();
|
|
23304
23321
|
return;
|
|
23305
23322
|
}
|
|
23306
23323
|
try {
|
|
23307
23324
|
const { output, exitCode } = await executeCommandWithCode(command);
|
|
23308
|
-
addResultMessage(output || "Command completed successfully", exitCode);
|
|
23325
|
+
addResultMessage(output || "Command completed successfully", exitCode, executionKind, assistantMsgId);
|
|
23309
23326
|
addToHistory({
|
|
23310
23327
|
input,
|
|
23311
23328
|
command,
|
|
@@ -23313,13 +23330,20 @@ async function executeAndShowResult(input, command, assistantMsgId) {
|
|
|
23313
23330
|
timestamp: Date.now()
|
|
23314
23331
|
});
|
|
23315
23332
|
history = loadHistory();
|
|
23316
|
-
updateAssistantMessage(assistantMsgId, { executed: true });
|
|
23317
23333
|
} catch (error) {
|
|
23318
23334
|
const message = error instanceof Error ? error.message : String(error);
|
|
23319
|
-
addResultMessage(`Error: ${message}`, 1);
|
|
23335
|
+
addResultMessage(`Error: ${message}`, 1, executionKind, assistantMsgId);
|
|
23320
23336
|
}
|
|
23321
23337
|
clearCommandState();
|
|
23322
23338
|
}
|
|
23339
|
+
function getExecutionKind(assistantMsgId, isDryRun) {
|
|
23340
|
+
if (isDryRun)
|
|
23341
|
+
return "dry-run";
|
|
23342
|
+
const assistantMsg = chatMessages.find((msg) => msg.id === assistantMsgId);
|
|
23343
|
+
if (!assistantMsg || assistantMsg.type !== "assistant")
|
|
23344
|
+
return "manual";
|
|
23345
|
+
return assistantMsg.safety?.isDangerous ? "manual" : "auto";
|
|
23346
|
+
}
|
|
23323
23347
|
function executeCommandWithCode(command) {
|
|
23324
23348
|
return new Promise((resolve3, reject) => {
|
|
23325
23349
|
const child = spawn(command, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@austinthesing/magic-shell",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"description": "Natural language to terminal commands with safety features. Supports OpenCode Zen (with free models) and OpenRouter.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|