@within-7/minto 0.3.6 → 0.3.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/{cli.js → cli.cjs} +25 -23
- package/dist/commands/language.js +137 -0
- package/dist/commands/language.js.map +7 -0
- package/dist/commands/new.js +56 -0
- package/dist/commands/new.js.map +7 -0
- package/dist/commands/resume.js +251 -16
- package/dist/commands/resume.js.map +2 -2
- package/dist/commands/sessions.js +224 -0
- package/dist/commands/sessions.js.map +7 -0
- package/dist/commands/setup.js +3 -2
- package/dist/commands/setup.js.map +2 -2
- package/dist/commands/stats.js +235 -0
- package/dist/commands/stats.js.map +7 -0
- package/dist/commands/status.js +11 -5
- package/dist/commands/status.js.map +2 -2
- package/dist/commands/undo.js +26 -16
- package/dist/commands/undo.js.map +2 -2
- package/dist/commands.js +6 -0
- package/dist/commands.js.map +2 -2
- package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js +3 -2
- package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js.map +2 -2
- package/dist/components/Config.js +9 -8
- package/dist/components/Config.js.map +2 -2
- package/dist/components/HeaderBar.js +2 -1
- package/dist/components/HeaderBar.js.map +2 -2
- package/dist/components/Help.js +2 -1
- package/dist/components/Help.js.map +2 -2
- package/dist/components/HotkeyHelpPanel.js +46 -44
- package/dist/components/HotkeyHelpPanel.js.map +2 -2
- package/dist/components/Logo.js +5 -2
- package/dist/components/Logo.js.map +2 -2
- package/dist/components/MCPServerApprovalDialog.js +6 -5
- package/dist/components/MCPServerApprovalDialog.js.map +2 -2
- package/dist/components/MCPServerMultiselectDialog.js +5 -4
- package/dist/components/MCPServerMultiselectDialog.js.map +2 -2
- package/dist/components/MessageSelector.js +4 -3
- package/dist/components/MessageSelector.js.map +2 -2
- package/dist/components/ModelConfig.js +13 -12
- package/dist/components/ModelConfig.js.map +2 -2
- package/dist/components/ModelListManager.js +4 -3
- package/dist/components/ModelListManager.js.map +2 -2
- package/dist/components/PromptInput.js +72 -39
- package/dist/components/PromptInput.js.map +2 -2
- package/dist/components/SensitiveFileWarning.js +12 -8
- package/dist/components/SensitiveFileWarning.js.map +2 -2
- package/dist/components/TabbedListView/ScrollableList.js +91 -0
- package/dist/components/TabbedListView/ScrollableList.js.map +7 -0
- package/dist/components/TabbedListView/SearchInput.js +23 -0
- package/dist/components/TabbedListView/SearchInput.js.map +7 -0
- package/dist/components/TabbedListView/TabBar.js +20 -0
- package/dist/components/TabbedListView/TabBar.js.map +7 -0
- package/dist/components/TabbedListView/TabbedListView.js +171 -0
- package/dist/components/TabbedListView/TabbedListView.js.map +7 -0
- package/dist/components/TabbedListView/index.js +11 -0
- package/dist/components/TabbedListView/index.js.map +7 -0
- package/dist/components/TabbedListView/types.js +1 -0
- package/dist/components/TabbedListView/types.js.map +7 -0
- package/dist/components/TodoChangeBlock.js +6 -5
- package/dist/components/TodoChangeBlock.js.map +3 -3
- package/dist/components/TodoPanel.js +6 -3
- package/dist/components/TodoPanel.js.map +3 -3
- package/dist/components/TrustDialog.js +6 -5
- package/dist/components/TrustDialog.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js +2 -1
- package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js.map +2 -2
- package/dist/constants/macros.js +1 -1
- package/dist/constants/macros.js.map +1 -1
- package/dist/constants/product.js +2 -2
- package/dist/constants/product.js.map +1 -1
- package/dist/constants/prompts.js +17 -0
- package/dist/constants/prompts.js.map +2 -2
- package/dist/constants/toolInputExamples.js +5 -1
- package/dist/constants/toolInputExamples.js.map +2 -2
- package/dist/core/tokenStatsManager.js +5 -0
- package/dist/core/tokenStatsManager.js.map +2 -2
- package/dist/entrypoints/bootstrap.js +54 -0
- package/dist/entrypoints/bootstrap.js.map +7 -0
- package/dist/entrypoints/cli.js +132 -23
- package/dist/entrypoints/cli.js.map +3 -3
- package/dist/history.js +75 -15
- package/dist/history.js.map +2 -2
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/index.js.map +2 -2
- package/dist/i18n/locales/en.js +283 -1
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/zh-CN.js +283 -1
- package/dist/i18n/locales/zh-CN.js.map +2 -2
- package/dist/i18n/types.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +2 -2
- package/dist/messages.js +11 -0
- package/dist/messages.js.map +2 -2
- package/dist/permissions.js.map +2 -2
- package/dist/query.js +9 -0
- package/dist/query.js.map +2 -2
- package/dist/screens/REPL.js +45 -7
- package/dist/screens/REPL.js.map +2 -2
- package/dist/services/customCommands.js +14 -8
- package/dist/services/customCommands.js.map +2 -2
- package/dist/tools/TaskTool/TaskTool.js +176 -1
- package/dist/tools/TaskTool/TaskTool.js.map +2 -2
- package/dist/tools/TodoWriteTool/prompt.js +21 -0
- package/dist/tools/TodoWriteTool/prompt.js.map +2 -2
- package/dist/tools/URLFetcherTool/prompt.js +14 -9
- package/dist/tools/URLFetcherTool/prompt.js.map +2 -2
- package/dist/tools/WebSearchTool/prompt.js +12 -6
- package/dist/tools/WebSearchTool/prompt.js.map +2 -2
- package/dist/types/PermissionMode.js +30 -1
- package/dist/types/PermissionMode.js.map +2 -2
- package/dist/types/plugin.js.map +2 -2
- package/dist/utils/agentHookExecutor.js +106 -0
- package/dist/utils/agentHookExecutor.js.map +7 -0
- package/dist/utils/agentLoader.js +212 -26
- package/dist/utils/agentLoader.js.map +2 -2
- package/dist/utils/agentMemory.js +134 -0
- package/dist/utils/agentMemory.js.map +7 -0
- package/dist/utils/config.js +51 -1
- package/dist/utils/config.js.map +2 -2
- package/dist/utils/configPaths.js +199 -0
- package/dist/utils/configPaths.js.map +7 -0
- package/dist/utils/historyManager.js +234 -0
- package/dist/utils/historyManager.js.map +7 -0
- package/dist/utils/messages.js +13 -8
- package/dist/utils/messages.js.map +2 -2
- package/dist/utils/migration/index.js +37 -0
- package/dist/utils/migration/index.js.map +7 -0
- package/dist/utils/migration/migrateHistory.js +273 -0
- package/dist/utils/migration/migrateHistory.js.map +7 -0
- package/dist/utils/migration/migrateTodos.js +323 -0
- package/dist/utils/migration/migrateTodos.js.map +7 -0
- package/dist/utils/pasteCache.js +309 -0
- package/dist/utils/pasteCache.js.map +7 -0
- package/dist/utils/pluginLoader.js +6 -3
- package/dist/utils/pluginLoader.js.map +2 -2
- package/dist/utils/sessionIndex.js +192 -0
- package/dist/utils/sessionIndex.js.map +7 -0
- package/dist/utils/sessionTracker.js +170 -0
- package/dist/utils/sessionTracker.js.map +7 -0
- package/dist/utils/skillLoader.js +91 -5
- package/dist/utils/skillLoader.js.map +2 -2
- package/dist/utils/stats.js +417 -0
- package/dist/utils/stats.js.map +7 -0
- package/dist/utils/stringSubstitution.js +107 -0
- package/dist/utils/stringSubstitution.js.map +7 -0
- package/dist/utils/teamConfig.js +3 -1
- package/dist/utils/teamConfig.js.map +2 -2
- package/dist/utils/todoStorage.js +51 -19
- package/dist/utils/todoStorage.js.map +2 -2
- package/dist/utils/tooling/safeRender.js.map +2 -2
- package/dist/version.js +2 -2
- package/dist/version.js.map +1 -1
- package/package.json +71 -28
- package/scripts/{postinstall.js → postinstall.cjs} +1 -1
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import React, { useState, useMemo } from "react";
|
|
2
|
+
import { Box, Text, useInput } from "ink";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { t } from "../i18n/index.js";
|
|
5
|
+
import { SEMANTIC_COLORS, BRAND_GRADIENT } from "../constants/colors.js";
|
|
6
|
+
import { getCwd } from "../utils/state.js";
|
|
7
|
+
import {
|
|
8
|
+
getRecentSessions,
|
|
9
|
+
getSessionsByProject,
|
|
10
|
+
searchSessions,
|
|
11
|
+
getSessionsIndex
|
|
12
|
+
} from "../utils/sessionIndex.js";
|
|
13
|
+
import { PressEnterToContinue } from "../components/PressEnterToContinue.js";
|
|
14
|
+
import {
|
|
15
|
+
TabbedListView
|
|
16
|
+
} from "../components/TabbedListView/index.js";
|
|
17
|
+
function parseArgs(args) {
|
|
18
|
+
const result = {
|
|
19
|
+
all: false,
|
|
20
|
+
limit: 20,
|
|
21
|
+
project: false,
|
|
22
|
+
search: null,
|
|
23
|
+
help: false
|
|
24
|
+
};
|
|
25
|
+
if (!args) return result;
|
|
26
|
+
const parts = args.trim().split(/\s+/);
|
|
27
|
+
let i = 0;
|
|
28
|
+
while (i < parts.length) {
|
|
29
|
+
const part = parts[i];
|
|
30
|
+
if (part === "--all" || part === "-a") {
|
|
31
|
+
result.all = true;
|
|
32
|
+
} else if (part === "--project" || part === "-p") {
|
|
33
|
+
result.project = true;
|
|
34
|
+
} else if (part === "--help" || part === "-h") {
|
|
35
|
+
result.help = true;
|
|
36
|
+
} else if (part === "--limit" || part === "-l") {
|
|
37
|
+
i++;
|
|
38
|
+
if (i < parts.length) {
|
|
39
|
+
const num = parseInt(parts[i], 10);
|
|
40
|
+
if (!isNaN(num) && num > 0) {
|
|
41
|
+
result.limit = num;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
} else if (part === "--search" || part === "-s") {
|
|
45
|
+
i++;
|
|
46
|
+
if (i < parts.length) {
|
|
47
|
+
const searchParts = [];
|
|
48
|
+
while (i < parts.length && !parts[i].startsWith("-")) {
|
|
49
|
+
searchParts.push(parts[i]);
|
|
50
|
+
i++;
|
|
51
|
+
}
|
|
52
|
+
i--;
|
|
53
|
+
result.search = searchParts.join(" ").replace(/^["']|["']$/g, "");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
i++;
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
function formatDate(isoString) {
|
|
61
|
+
const date = new Date(isoString);
|
|
62
|
+
const now = /* @__PURE__ */ new Date();
|
|
63
|
+
const hours = date.getHours().toString().padStart(2, "0");
|
|
64
|
+
const minutes = date.getMinutes().toString().padStart(2, "0");
|
|
65
|
+
const timeStr = `${hours}:${minutes}`;
|
|
66
|
+
const isToday = date.getDate() === now.getDate() && date.getMonth() === now.getMonth() && date.getFullYear() === now.getFullYear();
|
|
67
|
+
if (isToday) {
|
|
68
|
+
return `${t("commands.sessions.today")} ${timeStr}`;
|
|
69
|
+
}
|
|
70
|
+
const yesterday = new Date(now);
|
|
71
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
72
|
+
const isYesterday = date.getDate() === yesterday.getDate() && date.getMonth() === yesterday.getMonth() && date.getFullYear() === yesterday.getFullYear();
|
|
73
|
+
if (isYesterday) {
|
|
74
|
+
return `${t("commands.sessions.yesterday")} ${timeStr}`;
|
|
75
|
+
}
|
|
76
|
+
const month = (date.getMonth() + 1).toString().padStart(2, "0");
|
|
77
|
+
const day = date.getDate().toString().padStart(2, "0");
|
|
78
|
+
return `${month}-${day} ${timeStr}`;
|
|
79
|
+
}
|
|
80
|
+
function truncate(str, maxLength) {
|
|
81
|
+
if (str.length <= maxLength) return str;
|
|
82
|
+
return str.slice(0, maxLength - 3) + "...";
|
|
83
|
+
}
|
|
84
|
+
function getProjectName(projectPath) {
|
|
85
|
+
return path.basename(projectPath) || projectPath;
|
|
86
|
+
}
|
|
87
|
+
const HelpDisplay = ({ onClose }) => {
|
|
88
|
+
useInput((_, key) => {
|
|
89
|
+
if (key.return || key.escape) onClose();
|
|
90
|
+
});
|
|
91
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: BRAND_GRADIENT.START }, "/sessions - ", t("commands.sessions.description")), /* @__PURE__ */ React.createElement(Box, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { bold: true }, "Usage:"), /* @__PURE__ */ React.createElement(Box, { paddingLeft: 2, flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "/sessions"), " ", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, "Show recent 20 sessions")), /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "/sessions --all"), " ", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, "Show all sessions")), /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "/sessions --limit 20"), " ", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, "Show recent 20 sessions")), /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "/sessions --project"), " ", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, "Show only current project")), /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, '/sessions --search "keyword"'), " ", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, "Search sessions")))), /* @__PURE__ */ React.createElement(Box, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { bold: true }, "Options:"), /* @__PURE__ */ React.createElement(Box, { paddingLeft: 2, flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "-a, --all"), " ", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, "Show all sessions")), /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "-l, --limit N"), " ", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, "Limit to N sessions (default: 20)")), /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "-p, --project"), " ", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, "Filter to current project only")), /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "-s, --search"), " ", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, "Search by prompt or summary")), /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "-h, --help"), " ", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, "Show this help")))), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(PressEnterToContinue, null)));
|
|
92
|
+
};
|
|
93
|
+
function sessionToListItem(session) {
|
|
94
|
+
const dateStr = formatDate(session.modified);
|
|
95
|
+
const projectName = truncate(getProjectName(session.projectPath), 15);
|
|
96
|
+
const msgCount = session.messageCount;
|
|
97
|
+
const toolCount = session.toolCallCount;
|
|
98
|
+
return {
|
|
99
|
+
id: session.sessionId,
|
|
100
|
+
label: truncate(session.firstPrompt, 45),
|
|
101
|
+
description: `${projectName}`,
|
|
102
|
+
metadata: `${dateStr} \xB7 ${msgCount} msgs \xB7 ${toolCount} tools`,
|
|
103
|
+
category: projectName,
|
|
104
|
+
data: session
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const SessionsDisplay = ({
|
|
108
|
+
recentSessions,
|
|
109
|
+
projectSessions,
|
|
110
|
+
allSessions,
|
|
111
|
+
total,
|
|
112
|
+
onClose
|
|
113
|
+
}) => {
|
|
114
|
+
const [activeTab, setActiveTab] = useState("recent");
|
|
115
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
116
|
+
const tabs = useMemo(
|
|
117
|
+
() => [
|
|
118
|
+
{
|
|
119
|
+
id: "recent",
|
|
120
|
+
label: t("commands.sessions.title"),
|
|
121
|
+
badge: recentSessions.length
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
id: "project",
|
|
125
|
+
label: t("commands.sessions.headerProject"),
|
|
126
|
+
badge: projectSessions.length
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: "all",
|
|
130
|
+
label: t("common.all"),
|
|
131
|
+
badge: allSessions.length
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
[recentSessions.length, projectSessions.length, allSessions.length]
|
|
135
|
+
);
|
|
136
|
+
const items = useMemo(() => {
|
|
137
|
+
let sessions;
|
|
138
|
+
switch (activeTab) {
|
|
139
|
+
case "project":
|
|
140
|
+
sessions = projectSessions;
|
|
141
|
+
break;
|
|
142
|
+
case "all":
|
|
143
|
+
sessions = allSessions;
|
|
144
|
+
break;
|
|
145
|
+
case "recent":
|
|
146
|
+
default:
|
|
147
|
+
sessions = recentSessions;
|
|
148
|
+
}
|
|
149
|
+
return sessions.map(sessionToListItem);
|
|
150
|
+
}, [activeTab, recentSessions, projectSessions, allSessions]);
|
|
151
|
+
const handleSelect = () => {
|
|
152
|
+
onClose();
|
|
153
|
+
};
|
|
154
|
+
return /* @__PURE__ */ React.createElement(
|
|
155
|
+
TabbedListView,
|
|
156
|
+
{
|
|
157
|
+
title: t("commands.sessions.title"),
|
|
158
|
+
tabs,
|
|
159
|
+
activeTab,
|
|
160
|
+
onTabChange: setActiveTab,
|
|
161
|
+
items,
|
|
162
|
+
searchEnabled: true,
|
|
163
|
+
searchPlaceholder: t("ui.tabbedList.search"),
|
|
164
|
+
searchQuery,
|
|
165
|
+
onSearchChange: setSearchQuery,
|
|
166
|
+
onSelect: handleSelect,
|
|
167
|
+
onClose,
|
|
168
|
+
emptyText: t("commands.sessions.noSessions"),
|
|
169
|
+
footerHint: t("commands.sessions.navigationHint"),
|
|
170
|
+
groupByCategory: activeTab === "all"
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
};
|
|
174
|
+
const command = {
|
|
175
|
+
name: "sessions",
|
|
176
|
+
description: t("commands.sessions.description"),
|
|
177
|
+
isEnabled: true,
|
|
178
|
+
isHidden: false,
|
|
179
|
+
type: "local-jsx",
|
|
180
|
+
showBelowPrompt: true,
|
|
181
|
+
userFacingName() {
|
|
182
|
+
return this.name;
|
|
183
|
+
},
|
|
184
|
+
async call(onDone, _context, args) {
|
|
185
|
+
const options = parseArgs(args || "");
|
|
186
|
+
if (options.help) {
|
|
187
|
+
return /* @__PURE__ */ React.createElement(HelpDisplay, { onClose: onDone });
|
|
188
|
+
}
|
|
189
|
+
const cwd = getCwd();
|
|
190
|
+
const index = getSessionsIndex();
|
|
191
|
+
const total = index.entries.length;
|
|
192
|
+
const recentSessions = getRecentSessions(options.limit);
|
|
193
|
+
const projectSessions = getSessionsByProject(cwd);
|
|
194
|
+
const allSessions = options.all ? getRecentSessions(total) : getRecentSessions(100);
|
|
195
|
+
if (options.search) {
|
|
196
|
+
const searchResults = searchSessions(options.search);
|
|
197
|
+
return /* @__PURE__ */ React.createElement(
|
|
198
|
+
SessionsDisplay,
|
|
199
|
+
{
|
|
200
|
+
recentSessions: searchResults.slice(0, options.limit),
|
|
201
|
+
projectSessions: searchResults.filter((s) => s.projectPath === cwd),
|
|
202
|
+
allSessions: searchResults,
|
|
203
|
+
total: searchResults.length,
|
|
204
|
+
onClose: onDone
|
|
205
|
+
}
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
return /* @__PURE__ */ React.createElement(
|
|
209
|
+
SessionsDisplay,
|
|
210
|
+
{
|
|
211
|
+
recentSessions,
|
|
212
|
+
projectSessions,
|
|
213
|
+
allSessions,
|
|
214
|
+
total,
|
|
215
|
+
onClose: onDone
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
var sessions_default = command;
|
|
221
|
+
export {
|
|
222
|
+
sessions_default as default
|
|
223
|
+
};
|
|
224
|
+
//# sourceMappingURL=sessions.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/commands/sessions.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * Sessions Command\n *\n * Displays and manages session history with TabbedListView.\n *\n * Usage:\n * /sessions # Show recent sessions\n * /sessions --all # Show all sessions\n * /sessions --help # Show help\n */\n\nimport React, { useState, useMemo } from 'react'\nimport { Box, Text, useInput } from 'ink'\nimport path from 'path'\nimport type { Command } from '@commands'\nimport { t } from '@i18n'\nimport { SEMANTIC_COLORS, BRAND_GRADIENT } from '@constants/colors'\nimport { getCwd } from '@utils/state'\nimport {\n getRecentSessions,\n getSessionsByProject,\n searchSessions,\n getSessionsIndex,\n type SessionEntry,\n} from '@utils/sessionIndex'\nimport { PressEnterToContinue } from '@components/PressEnterToContinue'\nimport {\n TabbedListView,\n type ListItem,\n type TabDefinition,\n} from '@components/TabbedListView'\n\n/**\n * Parse command arguments\n */\nfunction parseArgs(args: string): {\n all: boolean\n limit: number\n project: boolean\n search: string | null\n help: boolean\n} {\n const result = {\n all: false,\n limit: 20,\n project: false,\n search: null as string | null,\n help: false,\n }\n\n if (!args) return result\n\n const parts = args.trim().split(/\\s+/)\n let i = 0\n\n while (i < parts.length) {\n const part = parts[i]\n\n if (part === '--all' || part === '-a') {\n result.all = true\n } else if (part === '--project' || part === '-p') {\n result.project = true\n } else if (part === '--help' || part === '-h') {\n result.help = true\n } else if (part === '--limit' || part === '-l') {\n i++\n if (i < parts.length) {\n const num = parseInt(parts[i], 10)\n if (!isNaN(num) && num > 0) {\n result.limit = num\n }\n }\n } else if (part === '--search' || part === '-s') {\n i++\n if (i < parts.length) {\n // Collect remaining parts as search query\n const searchParts: string[] = []\n while (i < parts.length && !parts[i].startsWith('-')) {\n searchParts.push(parts[i])\n i++\n }\n i-- // Step back since the loop will increment\n result.search = searchParts.join(' ').replace(/^[\"']|[\"']$/g, '')\n }\n }\n\n i++\n }\n\n return result\n}\n\n/**\n * Format date for display\n * - Today: \"Today HH:mm\"\n * - Yesterday: \"Yesterday HH:mm\"\n * - Other: \"MM-DD HH:mm\"\n */\nfunction formatDate(isoString: string): string {\n const date = new Date(isoString)\n const now = new Date()\n\n const hours = date.getHours().toString().padStart(2, '0')\n const minutes = date.getMinutes().toString().padStart(2, '0')\n const timeStr = `${hours}:${minutes}`\n\n // Check if it's today\n const isToday =\n date.getDate() === now.getDate() &&\n date.getMonth() === now.getMonth() &&\n date.getFullYear() === now.getFullYear()\n\n if (isToday) {\n return `${t('commands.sessions.today')} ${timeStr}`\n }\n\n // Check if it's yesterday\n const yesterday = new Date(now)\n yesterday.setDate(yesterday.getDate() - 1)\n const isYesterday =\n date.getDate() === yesterday.getDate() &&\n date.getMonth() === yesterday.getMonth() &&\n date.getFullYear() === yesterday.getFullYear()\n\n if (isYesterday) {\n return `${t('commands.sessions.yesterday')} ${timeStr}`\n }\n\n // Default format: MM-DD HH:mm\n const month = (date.getMonth() + 1).toString().padStart(2, '0')\n const day = date.getDate().toString().padStart(2, '0')\n return `${month}-${day} ${timeStr}`\n}\n\n/**\n * Truncate string with ellipsis\n */\nfunction truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str\n return str.slice(0, maxLength - 3) + '...'\n}\n\n/**\n * Get project name from path\n */\nfunction getProjectName(projectPath: string): string {\n return path.basename(projectPath) || projectPath\n}\n\n/**\n * Help display component\n */\nconst HelpDisplay = ({ onClose }: { onClose: () => void }) => {\n useInput((_, key) => {\n if (key.return || key.escape) onClose()\n })\n\n return (\n <Box flexDirection=\"column\" marginY={1}>\n <Text bold color={BRAND_GRADIENT.START}>\n /sessions - {t('commands.sessions.description')}\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n <Text bold>Usage:</Text>\n <Box paddingLeft={2} flexDirection=\"column\">\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>/sessions</Text>\n {' '}\n <Text color={SEMANTIC_COLORS.secondary}>\n Show recent 20 sessions\n </Text>\n </Text>\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>/sessions --all</Text>\n {' '}\n <Text color={SEMANTIC_COLORS.secondary}>Show all sessions</Text>\n </Text>\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>/sessions --limit 20</Text>\n {' '}\n <Text color={SEMANTIC_COLORS.secondary}>\n Show recent 20 sessions\n </Text>\n </Text>\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>/sessions --project</Text>\n {' '}\n <Text color={SEMANTIC_COLORS.secondary}>\n Show only current project\n </Text>\n </Text>\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>\n /sessions --search \"keyword\"\n </Text>\n {' '}\n <Text color={SEMANTIC_COLORS.secondary}>Search sessions</Text>\n </Text>\n </Box>\n </Box>\n <Box marginTop={1} flexDirection=\"column\">\n <Text bold>Options:</Text>\n <Box paddingLeft={2} flexDirection=\"column\">\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>-a, --all</Text>\n {' '}\n <Text color={SEMANTIC_COLORS.secondary}>Show all sessions</Text>\n </Text>\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>-l, --limit N</Text>\n {' '}\n <Text color={SEMANTIC_COLORS.secondary}>\n Limit to N sessions (default: 20)\n </Text>\n </Text>\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>-p, --project</Text>\n {' '}\n <Text color={SEMANTIC_COLORS.secondary}>\n Filter to current project only\n </Text>\n </Text>\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>-s, --search</Text>\n {' '}\n <Text color={SEMANTIC_COLORS.secondary}>\n Search by prompt or summary\n </Text>\n </Text>\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>-h, --help</Text>\n {' '}\n <Text color={SEMANTIC_COLORS.secondary}>Show this help</Text>\n </Text>\n </Box>\n </Box>\n <Box marginTop={1}>\n <PressEnterToContinue />\n </Box>\n </Box>\n )\n}\n\n/**\n * Convert SessionEntry to ListItem for TabbedListView\n */\nfunction sessionToListItem(session: SessionEntry): ListItem {\n const dateStr = formatDate(session.modified)\n const projectName = truncate(getProjectName(session.projectPath), 15)\n const msgCount = session.messageCount\n const toolCount = session.toolCallCount\n\n return {\n id: session.sessionId,\n label: truncate(session.firstPrompt, 45),\n description: `${projectName}`,\n metadata: `${dateStr} \u00B7 ${msgCount} msgs \u00B7 ${toolCount} tools`,\n category: projectName,\n data: session,\n }\n}\n\n/**\n * Sessions display component with TabbedListView\n */\nconst SessionsDisplay = ({\n recentSessions,\n projectSessions,\n allSessions,\n total,\n onClose,\n}: {\n recentSessions: SessionEntry[]\n projectSessions: SessionEntry[]\n allSessions: SessionEntry[]\n total: number\n onClose: () => void\n}) => {\n const [activeTab, setActiveTab] = useState('recent')\n const [searchQuery, setSearchQuery] = useState('')\n\n // Tab definitions\n const tabs: TabDefinition[] = useMemo(\n () => [\n {\n id: 'recent',\n label: t('commands.sessions.title'),\n badge: recentSessions.length,\n },\n {\n id: 'project',\n label: t('commands.sessions.headerProject'),\n badge: projectSessions.length,\n },\n {\n id: 'all',\n label: t('common.all'),\n badge: allSessions.length,\n },\n ],\n [recentSessions.length, projectSessions.length, allSessions.length],\n )\n\n // Get items based on active tab\n const items: ListItem[] = useMemo(() => {\n let sessions: SessionEntry[]\n\n switch (activeTab) {\n case 'project':\n sessions = projectSessions\n break\n case 'all':\n sessions = allSessions\n break\n case 'recent':\n default:\n sessions = recentSessions\n }\n\n return sessions.map(sessionToListItem)\n }, [activeTab, recentSessions, projectSessions, allSessions])\n\n // Handle item selection (view-only mode, just close)\n const handleSelect = () => {\n onClose()\n }\n\n return (\n <TabbedListView\n title={t('commands.sessions.title')}\n tabs={tabs}\n activeTab={activeTab}\n onTabChange={setActiveTab}\n items={items}\n searchEnabled={true}\n searchPlaceholder={t('ui.tabbedList.search')}\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n onSelect={handleSelect}\n onClose={onClose}\n emptyText={t('commands.sessions.noSessions')}\n footerHint={t('commands.sessions.navigationHint')}\n groupByCategory={activeTab === 'all'}\n />\n )\n}\n\nconst command: Command = {\n name: 'sessions',\n description: t('commands.sessions.description'),\n isEnabled: true,\n isHidden: false,\n type: 'local-jsx',\n showBelowPrompt: true,\n\n userFacingName() {\n return this.name\n },\n\n async call(onDone, _context, args) {\n const options = parseArgs(args || '')\n\n // Show help if requested\n if (options.help) {\n return <HelpDisplay onClose={onDone} />\n }\n\n // Get sessions based on options\n const cwd = getCwd()\n const index = getSessionsIndex()\n const total = index.entries.length\n\n // Get different session views\n const recentSessions = getRecentSessions(options.limit)\n const projectSessions = getSessionsByProject(cwd)\n const allSessions = options.all\n ? getRecentSessions(total)\n : getRecentSessions(100)\n\n // If search is specified, override with search results\n if (options.search) {\n const searchResults = searchSessions(options.search)\n return (\n <SessionsDisplay\n recentSessions={searchResults.slice(0, options.limit)}\n projectSessions={searchResults.filter(s => s.projectPath === cwd)}\n allSessions={searchResults}\n total={searchResults.length}\n onClose={onDone}\n />\n )\n }\n\n return (\n <SessionsDisplay\n recentSessions={recentSessions}\n projectSessions={projectSessions}\n allSessions={allSessions}\n total={total}\n onClose={onDone}\n />\n )\n },\n}\n\nexport default command\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/commands/setup.js
CHANGED
|
@@ -135,8 +135,9 @@ const command = {
|
|
|
135
135
|
userFacingName() {
|
|
136
136
|
return "setup";
|
|
137
137
|
},
|
|
138
|
-
async call(onDone, _context) {
|
|
139
|
-
const
|
|
138
|
+
async call(onDone, _context, commandArgs) {
|
|
139
|
+
const argsString = commandArgs || process.argv.slice(2).join(" ");
|
|
140
|
+
const args = argsString.split(/\s+/).filter(Boolean);
|
|
140
141
|
const fromIndex = args.findIndex((arg) => arg === "--from");
|
|
141
142
|
const strategyIndex = args.findIndex((arg) => arg === "--strategy");
|
|
142
143
|
const noPluginsFlag = args.includes("--no-plugins");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/commands/setup.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * Setup Command\n *\n * Initialize Minto with a team configuration from a remote URL or local file\n */\n\nimport React from 'react'\nimport { Text, Box } from 'ink'\nimport { SimpleSpinner } from '@components/Spinner'\nimport type { Command } from '@commands'\nimport { SEMANTIC_COLORS } from '@constants/colors'\nimport {\n fetchTeamConfig,\n loadTeamConfigFromFile,\n applyTeamConfig,\n addMarketplaces,\n installPlugins,\n installRemoteAgents,\n installInlineAgents,\n installTeamHooks,\n type MergeStrategy,\n} from '@utils/teamConfig'\n\ntype SetupProps = {\n source: string // URL or file path\n strategy?: MergeStrategy\n installPlugins?: boolean\n onDone: (result?: string) => void\n}\n\ntype SetupState =\n | { stage: 'loading' }\n | { stage: 'applying' }\n | { stage: 'adding-marketplaces'; total: number }\n | { stage: 'installing-plugins'; total: number }\n | { stage: 'installing-agents'; total: number }\n | { stage: 'installing-hooks' }\n | {\n stage: 'success'\n modelsAdded: number\n mcpServersAdded: number\n settingsUpdated: string[]\n marketplacesAdded?: number\n pluginsInstalled?: number\n agentsInstalled?: number\n hooksInstalled?: boolean\n instructions?: string\n }\n | { stage: 'error'; message: string }\n\nexport function SetupComponent({\n source,\n strategy = 'merge',\n installPlugins: shouldInstallPlugins = true,\n onDone,\n}: SetupProps) {\n const [state, setState] = React.useState<SetupState>({ stage: 'loading' })\n\n React.useEffect(() => {\n async function init() {\n try {\n // Step 1: Load configuration\n setState({ stage: 'loading' })\n\n const teamConfig =\n source.startsWith('http://') || source.startsWith('https://')\n ? await fetchTeamConfig(source)\n : loadTeamConfigFromFile(source)\n\n // Step 2: Apply configuration\n setState({ stage: 'applying' })\n\n const result = applyTeamConfig(teamConfig, strategy)\n\n // Step 3: Add marketplaces (if configured)\n let marketplacesAdded = 0\n if (shouldInstallPlugins && teamConfig.plugins?.marketplaces) {\n const marketplaceCount = teamConfig.plugins.marketplaces.length\n setState({ stage: 'adding-marketplaces', total: marketplaceCount })\n\n const marketplaceResult = await addMarketplaces(\n teamConfig.plugins.marketplaces,\n )\n\n marketplacesAdded = marketplaceResult.added\n }\n\n // Step 4: Install plugins (if configured)\n let pluginsInstalled = 0\n if (shouldInstallPlugins && teamConfig.plugins?.install) {\n const pluginCount = teamConfig.plugins.install.length\n setState({ stage: 'installing-plugins', total: pluginCount })\n\n const pluginResult = await installPlugins(teamConfig.plugins.install)\n\n pluginsInstalled = pluginResult.installed\n }\n\n // Step 5: Install agents (if configured)\n let agentsInstalled = 0\n if (shouldInstallPlugins && teamConfig.agents) {\n const remoteCount = teamConfig.agents.remoteAgents?.length || 0\n const inlineCount = teamConfig.agents.inlineAgents?.length || 0\n const totalAgents = remoteCount + inlineCount\n\n if (totalAgents > 0) {\n setState({ stage: 'installing-agents', total: totalAgents })\n\n if (teamConfig.agents.remoteAgents) {\n const remoteResult = await installRemoteAgents(\n teamConfig.agents.remoteAgents,\n )\n agentsInstalled += remoteResult.installed\n }\n\n if (teamConfig.agents.inlineAgents) {\n const inlineResult = await installInlineAgents(\n teamConfig.agents.inlineAgents,\n )\n agentsInstalled += inlineResult.installed\n }\n }\n }\n\n // Step 6: Install hooks (if configured)\n let hooksInstalled = false\n if (shouldInstallPlugins && teamConfig.hooks) {\n setState({ stage: 'installing-hooks' })\n const hookResult = await installTeamHooks(teamConfig.hooks)\n hooksInstalled = hookResult.installed\n }\n\n // Success\n setState({\n stage: 'success',\n modelsAdded: result.modelsAdded,\n mcpServersAdded: result.mcpServersAdded,\n settingsUpdated: result.settingsUpdated,\n marketplacesAdded:\n marketplacesAdded > 0 ? marketplacesAdded : undefined,\n pluginsInstalled: pluginsInstalled > 0 ? pluginsInstalled : undefined,\n agentsInstalled: agentsInstalled > 0 ? agentsInstalled : undefined,\n hooksInstalled: hooksInstalled || undefined,\n instructions: teamConfig.postInstallInstructions,\n })\n\n // Notify parent component\n setTimeout(() => onDone('Configuration applied successfully'), 2000)\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n setState({\n stage: 'error',\n message: errorMessage,\n })\n\n // Notify parent component of error\n setTimeout(() => onDone(), 2000)\n }\n }\n\n init()\n }, [source, strategy, shouldInstallPlugins, onDone])\n\n if (state.stage === 'loading') {\n return (\n <Box>\n <Text color=\"cyan\">\n <SimpleSpinner /> Loading configuration from {source}...\n </Text>\n </Box>\n )\n }\n\n if (state.stage === 'applying') {\n return (\n <Box>\n <Text color=\"cyan\">\n <SimpleSpinner /> Applying configuration...\n </Text>\n </Box>\n )\n }\n\n if (state.stage === 'adding-marketplaces') {\n return (\n <Box>\n <Text color=\"cyan\">\n <SimpleSpinner /> Adding {state.total} marketplace\n {state.total !== 1 ? 's' : ''}...\n </Text>\n </Box>\n )\n }\n\n if (state.stage === 'installing-plugins') {\n return (\n <Box>\n <Text color=\"cyan\">\n <SimpleSpinner /> Installing {state.total} plugin\n {state.total !== 1 ? 's' : ''}...\n </Text>\n </Box>\n )\n }\n\n if (state.stage === 'installing-agents') {\n return (\n <Box>\n <Text color=\"cyan\">\n <SimpleSpinner /> Installing {state.total} agent\n {state.total !== 1 ? 's' : ''}...\n </Text>\n </Box>\n )\n }\n\n if (state.stage === 'installing-hooks') {\n return (\n <Box>\n <Text color=\"cyan\">\n <SimpleSpinner /> Installing hooks...\n </Text>\n </Box>\n )\n }\n\n if (state.stage === 'error') {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"red\">\u2717 Initialization failed</Text>\n <Text color=\"red\">{state.message}</Text>\n </Box>\n )\n }\n\n // Success state\n return (\n <Box flexDirection=\"column\" paddingY={1}>\n <Text color=\"green\" bold>\n \u2713 Configuration applied successfully!\n </Text>\n\n <Box flexDirection=\"column\" paddingTop={1}>\n {state.modelsAdded > 0 && (\n <Text>\n \u2022 Added <Text color=\"cyan\">{state.modelsAdded}</Text> model profile\n {state.modelsAdded !== 1 ? 's' : ''}\n </Text>\n )}\n\n {state.mcpServersAdded > 0 && (\n <Text>\n \u2022 Added <Text color=\"cyan\">{state.mcpServersAdded}</Text> MCP server\n {state.mcpServersAdded !== 1 ? 's' : ''}\n </Text>\n )}\n\n {state.settingsUpdated.length > 0 && (\n <Text>\n \u2022 Updated <Text color=\"cyan\">{state.settingsUpdated.length}</Text>{' '}\n setting\n {state.settingsUpdated.length !== 1 ? 's' : ''}:{' '}\n {state.settingsUpdated.join(', ')}\n </Text>\n )}\n\n {state.marketplacesAdded !== undefined &&\n state.marketplacesAdded > 0 && (\n <Text>\n \u2022 Added <Text color=\"cyan\">{state.marketplacesAdded}</Text>{' '}\n marketplace\n {state.marketplacesAdded !== 1 ? 's' : ''}\n </Text>\n )}\n\n {state.pluginsInstalled !== undefined && state.pluginsInstalled > 0 && (\n <Text>\n \u2022 Installed <Text color=\"cyan\">{state.pluginsInstalled}</Text>{' '}\n plugin\n {state.pluginsInstalled !== 1 ? 's' : ''}\n </Text>\n )}\n\n {state.agentsInstalled !== undefined && state.agentsInstalled > 0 && (\n <Text>\n \u2022 Installed <Text color=\"cyan\">{state.agentsInstalled}</Text> agent\n {state.agentsInstalled !== 1 ? 's' : ''}\n </Text>\n )}\n\n {state.hooksInstalled && (\n <Text>\n \u2022 Installed <Text color=\"cyan\">hooks</Text> configuration\n </Text>\n )}\n </Box>\n\n {state.instructions && (\n <Box\n flexDirection=\"column\"\n paddingTop={1}\n borderStyle=\"round\"\n borderColor=\"yellow\"\n paddingX={1}\n >\n <Text color=\"yellow\" bold>\n \uD83D\uDCCB Next Steps:\n </Text>\n <Text>{state.instructions}</Text>\n </Box>\n )}\n\n <Box paddingTop={1}>\n <Text color={SEMANTIC_COLORS.dim}>\n Run <Text color=\"cyan\">minto</Text> to start using your configured\n setup.\n </Text>\n </Box>\n </Box>\n )\n}\n\n// Command definition\nconst command = {\n type: 'local-jsx',\n name: 'setup',\n description: 'Initialize Minto with team configuration from a URL or file',\n isEnabled: true,\n isHidden: false,\n userFacingName() {\n return 'setup'\n },\n async call(onDone, _context) {\n // Parse arguments\n const args = process.argv.slice(2)\n const fromIndex = args.findIndex(arg => arg === '--from')\n const strategyIndex = args.findIndex(arg => arg === '--strategy')\n const noPluginsFlag = args.includes('--no-plugins')\n\n if (fromIndex === -1 || !args[fromIndex + 1]) {\n onDone()\n return (\n <Box flexDirection=\"column\">\n <Text color=\"red\">Error: --from parameter is required</Text>\n <Text>\n Usage: minto setup --from <url|path> [--strategy\n <merge|replace|skip-existing>] [--no-plugins]\n </Text>\n </Box>\n )\n }\n\n const source = args[fromIndex + 1]\n const strategy: MergeStrategy =\n strategyIndex !== -1 && args[strategyIndex + 1]\n ? (args[strategyIndex + 1] as MergeStrategy)\n : 'merge'\n const shouldInstallPlugins = !noPluginsFlag\n\n return (\n <SetupComponent\n source={source}\n strategy={strategy}\n installPlugins={shouldInstallPlugins}\n onDone={onDone}\n />\n )\n },\n} satisfies Command\n\nexport default command\n"],
|
|
5
|
-
"mappings": "AAMA,OAAO,WAAW;AAClB,SAAS,MAAM,WAAW;AAC1B,SAAS,qBAAqB;AAE9B,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AA6BA,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA,WAAW;AAAA,EACX,gBAAgB,uBAAuB;AAAA,EACvC;AACF,GAAe;AACb,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAqB,EAAE,OAAO,UAAU,CAAC;AAEzE,QAAM,UAAU,MAAM;AACpB,mBAAe,OAAO;AACpB,UAAI;AAEF,iBAAS,EAAE,OAAO,UAAU,CAAC;AAE7B,cAAM,aACJ,OAAO,WAAW,SAAS,KAAK,OAAO,WAAW,UAAU,IACxD,MAAM,gBAAgB,MAAM,IAC5B,uBAAuB,MAAM;AAGnC,iBAAS,EAAE,OAAO,WAAW,CAAC;AAE9B,cAAM,SAAS,gBAAgB,YAAY,QAAQ;AAGnD,YAAI,oBAAoB;AACxB,YAAI,wBAAwB,WAAW,SAAS,cAAc;AAC5D,gBAAM,mBAAmB,WAAW,QAAQ,aAAa;AACzD,mBAAS,EAAE,OAAO,uBAAuB,OAAO,iBAAiB,CAAC;AAElE,gBAAM,oBAAoB,MAAM;AAAA,YAC9B,WAAW,QAAQ;AAAA,UACrB;AAEA,8BAAoB,kBAAkB;AAAA,QACxC;AAGA,YAAI,mBAAmB;AACvB,YAAI,wBAAwB,WAAW,SAAS,SAAS;AACvD,gBAAM,cAAc,WAAW,QAAQ,QAAQ;AAC/C,mBAAS,EAAE,OAAO,sBAAsB,OAAO,YAAY,CAAC;AAE5D,gBAAM,eAAe,MAAM,eAAe,WAAW,QAAQ,OAAO;AAEpE,6BAAmB,aAAa;AAAA,QAClC;AAGA,YAAI,kBAAkB;AACtB,YAAI,wBAAwB,WAAW,QAAQ;AAC7C,gBAAM,cAAc,WAAW,OAAO,cAAc,UAAU;AAC9D,gBAAM,cAAc,WAAW,OAAO,cAAc,UAAU;AAC9D,gBAAM,cAAc,cAAc;AAElC,cAAI,cAAc,GAAG;AACnB,qBAAS,EAAE,OAAO,qBAAqB,OAAO,YAAY,CAAC;AAE3D,gBAAI,WAAW,OAAO,cAAc;AAClC,oBAAM,eAAe,MAAM;AAAA,gBACzB,WAAW,OAAO;AAAA,cACpB;AACA,iCAAmB,aAAa;AAAA,YAClC;AAEA,gBAAI,WAAW,OAAO,cAAc;AAClC,oBAAM,eAAe,MAAM;AAAA,gBACzB,WAAW,OAAO;AAAA,cACpB;AACA,iCAAmB,aAAa;AAAA,YAClC;AAAA,UACF;AAAA,QACF;AAGA,YAAI,iBAAiB;AACrB,YAAI,wBAAwB,WAAW,OAAO;AAC5C,mBAAS,EAAE,OAAO,mBAAmB,CAAC;AACtC,gBAAM,aAAa,MAAM,iBAAiB,WAAW,KAAK;AAC1D,2BAAiB,WAAW;AAAA,QAC9B;AAGA,iBAAS;AAAA,UACP,OAAO;AAAA,UACP,aAAa,OAAO;AAAA,UACpB,iBAAiB,OAAO;AAAA,UACxB,iBAAiB,OAAO;AAAA,UACxB,mBACE,oBAAoB,IAAI,oBAAoB;AAAA,UAC9C,kBAAkB,mBAAmB,IAAI,mBAAmB;AAAA,UAC5D,iBAAiB,kBAAkB,IAAI,kBAAkB;AAAA,UACzD,gBAAgB,kBAAkB;AAAA,UAClC,cAAc,WAAW;AAAA,QAC3B,CAAC;AAGD,mBAAW,MAAM,OAAO,oCAAoC,GAAG,GAAI;AAAA,MACrE,SAAS,OAAO;AACd,cAAM,eACJ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACvD,iBAAS;AAAA,UACP,OAAO;AAAA,UACP,SAAS;AAAA,QACX,CAAC;AAGD,mBAAW,MAAM,OAAO,GAAG,GAAI;AAAA,MACjC;AAAA,IACF;AAEA,SAAK;AAAA,EACP,GAAG,CAAC,QAAQ,UAAU,sBAAsB,MAAM,CAAC;AAEnD,MAAI,MAAM,UAAU,WAAW;AAC7B,WACE,oCAAC,WACC,oCAAC,QAAK,OAAM,UACV,oCAAC,mBAAc,GAAE,gCAA6B,QAAO,KACvD,CACF;AAAA,EAEJ;AAEA,MAAI,MAAM,UAAU,YAAY;AAC9B,WACE,oCAAC,WACC,oCAAC,QAAK,OAAM,UACV,oCAAC,mBAAc,GAAE,4BACnB,CACF;AAAA,EAEJ;AAEA,MAAI,MAAM,UAAU,uBAAuB;AACzC,WACE,oCAAC,WACC,oCAAC,QAAK,OAAM,UACV,oCAAC,mBAAc,GAAE,YAAS,MAAM,OAAM,gBACrC,MAAM,UAAU,IAAI,MAAM,IAAG,KAChC,CACF;AAAA,EAEJ;AAEA,MAAI,MAAM,UAAU,sBAAsB;AACxC,WACE,oCAAC,WACC,oCAAC,QAAK,OAAM,UACV,oCAAC,mBAAc,GAAE,gBAAa,MAAM,OAAM,WACzC,MAAM,UAAU,IAAI,MAAM,IAAG,KAChC,CACF;AAAA,EAEJ;AAEA,MAAI,MAAM,UAAU,qBAAqB;AACvC,WACE,oCAAC,WACC,oCAAC,QAAK,OAAM,UACV,oCAAC,mBAAc,GAAE,gBAAa,MAAM,OAAM,UACzC,MAAM,UAAU,IAAI,MAAM,IAAG,KAChC,CACF;AAAA,EAEJ;AAEA,MAAI,MAAM,UAAU,oBAAoB;AACtC,WACE,oCAAC,WACC,oCAAC,QAAK,OAAM,UACV,oCAAC,mBAAc,GAAE,sBACnB,CACF;AAAA,EAEJ;AAEA,MAAI,MAAM,UAAU,SAAS;AAC3B,WACE,oCAAC,OAAI,eAAc,YACjB,oCAAC,QAAK,OAAM,SAAM,8BAAuB,GACzC,oCAAC,QAAK,OAAM,SAAO,MAAM,OAAQ,CACnC;AAAA,EAEJ;AAGA,SACE,oCAAC,OAAI,eAAc,UAAS,UAAU,KACpC,oCAAC,QAAK,OAAM,SAAQ,MAAI,QAAC,4CAEzB,GAEA,oCAAC,OAAI,eAAc,UAAS,YAAY,KACrC,MAAM,cAAc,KACnB,oCAAC,YAAK,iBACI,oCAAC,QAAK,OAAM,UAAQ,MAAM,WAAY,GAAO,kBACpD,MAAM,gBAAgB,IAAI,MAAM,EACnC,GAGD,MAAM,kBAAkB,KACvB,oCAAC,YAAK,iBACI,oCAAC,QAAK,OAAM,UAAQ,MAAM,eAAgB,GAAO,eACxD,MAAM,oBAAoB,IAAI,MAAM,EACvC,GAGD,MAAM,gBAAgB,SAAS,KAC9B,oCAAC,YAAK,mBACM,oCAAC,QAAK,OAAM,UAAQ,MAAM,gBAAgB,MAAO,GAAQ,KAAI,WAEtE,MAAM,gBAAgB,WAAW,IAAI,MAAM,IAAG,KAAE,KAChD,MAAM,gBAAgB,KAAK,IAAI,CAClC,GAGD,MAAM,sBAAsB,UAC3B,MAAM,oBAAoB,KACxB,oCAAC,YAAK,iBACI,oCAAC,QAAK,OAAM,UAAQ,MAAM,iBAAkB,GAAQ,KAAI,eAE/D,MAAM,sBAAsB,IAAI,MAAM,EACzC,GAGH,MAAM,qBAAqB,UAAa,MAAM,mBAAmB,KAChE,oCAAC,YAAK,qBACQ,oCAAC,QAAK,OAAM,UAAQ,MAAM,gBAAiB,GAAQ,KAAI,UAElE,MAAM,qBAAqB,IAAI,MAAM,EACxC,GAGD,MAAM,oBAAoB,UAAa,MAAM,kBAAkB,KAC9D,oCAAC,YAAK,qBACQ,oCAAC,QAAK,OAAM,UAAQ,MAAM,eAAgB,GAAO,UAC5D,MAAM,oBAAoB,IAAI,MAAM,EACvC,GAGD,MAAM,kBACL,oCAAC,YAAK,qBACQ,oCAAC,QAAK,OAAM,UAAO,OAAK,GAAO,gBAC7C,CAEJ,GAEC,MAAM,gBACL;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,YAAY;AAAA,MACZ,aAAY;AAAA,MACZ,aAAY;AAAA,MACZ,UAAU;AAAA;AAAA,IAEV,oCAAC,QAAK,OAAM,UAAS,MAAI,QAAC,uBAE1B;AAAA,IACA,oCAAC,YAAM,MAAM,YAAa;AAAA,EAC5B,GAGF,oCAAC,OAAI,YAAY,KACf,oCAAC,QAAK,OAAO,gBAAgB,OAAK,QAC5B,oCAAC,QAAK,OAAM,UAAO,OAAK,GAAO,wCAErC,CACF,CACF;AAEJ;AAGA,MAAM,UAAU;AAAA,EACd,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,WAAW;AAAA,EACX,UAAU;AAAA,EACV,iBAAiB;AACf,WAAO;AAAA,EACT;AAAA,EACA,MAAM,KAAK,QAAQ,UAAU;
|
|
4
|
+
"sourcesContent": ["/**\n * Setup Command\n *\n * Initialize Minto with a team configuration from a remote URL or local file\n */\n\nimport React from 'react'\nimport { Text, Box } from 'ink'\nimport { SimpleSpinner } from '@components/Spinner'\nimport type { Command } from '@commands'\nimport { SEMANTIC_COLORS } from '@constants/colors'\nimport {\n fetchTeamConfig,\n loadTeamConfigFromFile,\n applyTeamConfig,\n addMarketplaces,\n installPlugins,\n installRemoteAgents,\n installInlineAgents,\n installTeamHooks,\n type MergeStrategy,\n} from '@utils/teamConfig'\n\ntype SetupProps = {\n source: string // URL or file path\n strategy?: MergeStrategy\n installPlugins?: boolean\n onDone: (result?: string) => void\n}\n\ntype SetupState =\n | { stage: 'loading' }\n | { stage: 'applying' }\n | { stage: 'adding-marketplaces'; total: number }\n | { stage: 'installing-plugins'; total: number }\n | { stage: 'installing-agents'; total: number }\n | { stage: 'installing-hooks' }\n | {\n stage: 'success'\n modelsAdded: number\n mcpServersAdded: number\n settingsUpdated: string[]\n marketplacesAdded?: number\n pluginsInstalled?: number\n agentsInstalled?: number\n hooksInstalled?: boolean\n instructions?: string\n }\n | { stage: 'error'; message: string }\n\nexport function SetupComponent({\n source,\n strategy = 'merge',\n installPlugins: shouldInstallPlugins = true,\n onDone,\n}: SetupProps) {\n const [state, setState] = React.useState<SetupState>({ stage: 'loading' })\n\n React.useEffect(() => {\n async function init() {\n try {\n // Step 1: Load configuration\n setState({ stage: 'loading' })\n\n const teamConfig =\n source.startsWith('http://') || source.startsWith('https://')\n ? await fetchTeamConfig(source)\n : loadTeamConfigFromFile(source)\n\n // Step 2: Apply configuration\n setState({ stage: 'applying' })\n\n const result = applyTeamConfig(teamConfig, strategy)\n\n // Step 3: Add marketplaces (if configured)\n let marketplacesAdded = 0\n if (shouldInstallPlugins && teamConfig.plugins?.marketplaces) {\n const marketplaceCount = teamConfig.plugins.marketplaces.length\n setState({ stage: 'adding-marketplaces', total: marketplaceCount })\n\n const marketplaceResult = await addMarketplaces(\n teamConfig.plugins.marketplaces,\n )\n\n marketplacesAdded = marketplaceResult.added\n }\n\n // Step 4: Install plugins (if configured)\n let pluginsInstalled = 0\n if (shouldInstallPlugins && teamConfig.plugins?.install) {\n const pluginCount = teamConfig.plugins.install.length\n setState({ stage: 'installing-plugins', total: pluginCount })\n\n const pluginResult = await installPlugins(teamConfig.plugins.install)\n\n pluginsInstalled = pluginResult.installed\n }\n\n // Step 5: Install agents (if configured)\n let agentsInstalled = 0\n if (shouldInstallPlugins && teamConfig.agents) {\n const remoteCount = teamConfig.agents.remoteAgents?.length || 0\n const inlineCount = teamConfig.agents.inlineAgents?.length || 0\n const totalAgents = remoteCount + inlineCount\n\n if (totalAgents > 0) {\n setState({ stage: 'installing-agents', total: totalAgents })\n\n if (teamConfig.agents.remoteAgents) {\n const remoteResult = await installRemoteAgents(\n teamConfig.agents.remoteAgents,\n )\n agentsInstalled += remoteResult.installed\n }\n\n if (teamConfig.agents.inlineAgents) {\n const inlineResult = await installInlineAgents(\n teamConfig.agents.inlineAgents,\n )\n agentsInstalled += inlineResult.installed\n }\n }\n }\n\n // Step 6: Install hooks (if configured)\n let hooksInstalled = false\n if (shouldInstallPlugins && teamConfig.hooks) {\n setState({ stage: 'installing-hooks' })\n const hookResult = await installTeamHooks(teamConfig.hooks)\n hooksInstalled = hookResult.installed\n }\n\n // Success\n setState({\n stage: 'success',\n modelsAdded: result.modelsAdded,\n mcpServersAdded: result.mcpServersAdded,\n settingsUpdated: result.settingsUpdated,\n marketplacesAdded:\n marketplacesAdded > 0 ? marketplacesAdded : undefined,\n pluginsInstalled: pluginsInstalled > 0 ? pluginsInstalled : undefined,\n agentsInstalled: agentsInstalled > 0 ? agentsInstalled : undefined,\n hooksInstalled: hooksInstalled || undefined,\n instructions: teamConfig.postInstallInstructions,\n })\n\n // Notify parent component\n setTimeout(() => onDone('Configuration applied successfully'), 2000)\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n setState({\n stage: 'error',\n message: errorMessage,\n })\n\n // Notify parent component of error\n setTimeout(() => onDone(), 2000)\n }\n }\n\n init()\n }, [source, strategy, shouldInstallPlugins, onDone])\n\n if (state.stage === 'loading') {\n return (\n <Box>\n <Text color=\"cyan\">\n <SimpleSpinner /> Loading configuration from {source}...\n </Text>\n </Box>\n )\n }\n\n if (state.stage === 'applying') {\n return (\n <Box>\n <Text color=\"cyan\">\n <SimpleSpinner /> Applying configuration...\n </Text>\n </Box>\n )\n }\n\n if (state.stage === 'adding-marketplaces') {\n return (\n <Box>\n <Text color=\"cyan\">\n <SimpleSpinner /> Adding {state.total} marketplace\n {state.total !== 1 ? 's' : ''}...\n </Text>\n </Box>\n )\n }\n\n if (state.stage === 'installing-plugins') {\n return (\n <Box>\n <Text color=\"cyan\">\n <SimpleSpinner /> Installing {state.total} plugin\n {state.total !== 1 ? 's' : ''}...\n </Text>\n </Box>\n )\n }\n\n if (state.stage === 'installing-agents') {\n return (\n <Box>\n <Text color=\"cyan\">\n <SimpleSpinner /> Installing {state.total} agent\n {state.total !== 1 ? 's' : ''}...\n </Text>\n </Box>\n )\n }\n\n if (state.stage === 'installing-hooks') {\n return (\n <Box>\n <Text color=\"cyan\">\n <SimpleSpinner /> Installing hooks...\n </Text>\n </Box>\n )\n }\n\n if (state.stage === 'error') {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"red\">\u2717 Initialization failed</Text>\n <Text color=\"red\">{state.message}</Text>\n </Box>\n )\n }\n\n // Success state\n return (\n <Box flexDirection=\"column\" paddingY={1}>\n <Text color=\"green\" bold>\n \u2713 Configuration applied successfully!\n </Text>\n\n <Box flexDirection=\"column\" paddingTop={1}>\n {state.modelsAdded > 0 && (\n <Text>\n \u2022 Added <Text color=\"cyan\">{state.modelsAdded}</Text> model profile\n {state.modelsAdded !== 1 ? 's' : ''}\n </Text>\n )}\n\n {state.mcpServersAdded > 0 && (\n <Text>\n \u2022 Added <Text color=\"cyan\">{state.mcpServersAdded}</Text> MCP server\n {state.mcpServersAdded !== 1 ? 's' : ''}\n </Text>\n )}\n\n {state.settingsUpdated.length > 0 && (\n <Text>\n \u2022 Updated <Text color=\"cyan\">{state.settingsUpdated.length}</Text>{' '}\n setting\n {state.settingsUpdated.length !== 1 ? 's' : ''}:{' '}\n {state.settingsUpdated.join(', ')}\n </Text>\n )}\n\n {state.marketplacesAdded !== undefined &&\n state.marketplacesAdded > 0 && (\n <Text>\n \u2022 Added <Text color=\"cyan\">{state.marketplacesAdded}</Text>{' '}\n marketplace\n {state.marketplacesAdded !== 1 ? 's' : ''}\n </Text>\n )}\n\n {state.pluginsInstalled !== undefined && state.pluginsInstalled > 0 && (\n <Text>\n \u2022 Installed <Text color=\"cyan\">{state.pluginsInstalled}</Text>{' '}\n plugin\n {state.pluginsInstalled !== 1 ? 's' : ''}\n </Text>\n )}\n\n {state.agentsInstalled !== undefined && state.agentsInstalled > 0 && (\n <Text>\n \u2022 Installed <Text color=\"cyan\">{state.agentsInstalled}</Text> agent\n {state.agentsInstalled !== 1 ? 's' : ''}\n </Text>\n )}\n\n {state.hooksInstalled && (\n <Text>\n \u2022 Installed <Text color=\"cyan\">hooks</Text> configuration\n </Text>\n )}\n </Box>\n\n {state.instructions && (\n <Box\n flexDirection=\"column\"\n paddingTop={1}\n borderStyle=\"round\"\n borderColor=\"yellow\"\n paddingX={1}\n >\n <Text color=\"yellow\" bold>\n \uD83D\uDCCB Next Steps:\n </Text>\n <Text>{state.instructions}</Text>\n </Box>\n )}\n\n <Box paddingTop={1}>\n <Text color={SEMANTIC_COLORS.dim}>\n Run <Text color=\"cyan\">minto</Text> to start using your configured\n setup.\n </Text>\n </Box>\n </Box>\n )\n}\n\n// Command definition\nconst command = {\n type: 'local-jsx',\n name: 'setup',\n description: 'Initialize Minto with team configuration from a URL or file',\n isEnabled: true,\n isHidden: false,\n userFacingName() {\n return 'setup'\n },\n async call(onDone, _context, commandArgs) {\n // Parse arguments from either slash command args or process.argv (CLI mode)\n // Slash command: /setup --from <url> passes args as commandArgs\n // CLI mode: minto setup --from <url> uses process.argv\n const argsString = commandArgs || process.argv.slice(2).join(' ')\n const args = argsString.split(/\\s+/).filter(Boolean)\n const fromIndex = args.findIndex(arg => arg === '--from')\n const strategyIndex = args.findIndex(arg => arg === '--strategy')\n const noPluginsFlag = args.includes('--no-plugins')\n\n if (fromIndex === -1 || !args[fromIndex + 1]) {\n onDone()\n return (\n <Box flexDirection=\"column\">\n <Text color=\"red\">Error: --from parameter is required</Text>\n <Text>\n Usage: minto setup --from <url|path> [--strategy\n <merge|replace|skip-existing>] [--no-plugins]\n </Text>\n </Box>\n )\n }\n\n const source = args[fromIndex + 1]\n const strategy: MergeStrategy =\n strategyIndex !== -1 && args[strategyIndex + 1]\n ? (args[strategyIndex + 1] as MergeStrategy)\n : 'merge'\n const shouldInstallPlugins = !noPluginsFlag\n\n return (\n <SetupComponent\n source={source}\n strategy={strategy}\n installPlugins={shouldInstallPlugins}\n onDone={onDone}\n />\n )\n },\n} satisfies Command\n\nexport default command\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Box, Text, useInput } from "ink";
|
|
3
|
+
import { t } from "../i18n/index.js";
|
|
4
|
+
import { BRAND_GRADIENT, SEMANTIC_COLORS } from "../constants/colors.js";
|
|
5
|
+
import {
|
|
6
|
+
getStats,
|
|
7
|
+
getTodayStats,
|
|
8
|
+
getStatsForDays,
|
|
9
|
+
getModelUsageStats,
|
|
10
|
+
getToolUsageStats
|
|
11
|
+
} from "../utils/stats.js";
|
|
12
|
+
import { PressEnterToContinue } from "../components/PressEnterToContinue.js";
|
|
13
|
+
function renderProgressBar(value, max, width = 40) {
|
|
14
|
+
if (max === 0) return "\u2591".repeat(width);
|
|
15
|
+
const filled = Math.min(Math.round(value / max * width), width);
|
|
16
|
+
const empty = width - filled;
|
|
17
|
+
return "\u2588".repeat(filled) + "\u2591".repeat(empty);
|
|
18
|
+
}
|
|
19
|
+
function formatNumber(n) {
|
|
20
|
+
return n.toLocaleString();
|
|
21
|
+
}
|
|
22
|
+
function formatCompactNumber(n) {
|
|
23
|
+
if (n >= 1e6) {
|
|
24
|
+
return `${(n / 1e6).toFixed(1)}M`;
|
|
25
|
+
}
|
|
26
|
+
if (n >= 1e3) {
|
|
27
|
+
return `${(n / 1e3).toFixed(1)}K`;
|
|
28
|
+
}
|
|
29
|
+
return n.toString();
|
|
30
|
+
}
|
|
31
|
+
function formatCost(cost) {
|
|
32
|
+
if (cost < 0.01) {
|
|
33
|
+
return `$${cost.toFixed(4)}`;
|
|
34
|
+
}
|
|
35
|
+
return `$${cost.toFixed(2)}`;
|
|
36
|
+
}
|
|
37
|
+
function getTodayString() {
|
|
38
|
+
return (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
39
|
+
}
|
|
40
|
+
function safePercentage(value, total) {
|
|
41
|
+
if (total === 0) return 0;
|
|
42
|
+
return Math.round(value / total * 100);
|
|
43
|
+
}
|
|
44
|
+
function sumDailyStats(days) {
|
|
45
|
+
return days.reduce(
|
|
46
|
+
(acc, day) => ({
|
|
47
|
+
date: "",
|
|
48
|
+
messageCount: acc.messageCount + day.messageCount,
|
|
49
|
+
sessionCount: acc.sessionCount + day.sessionCount,
|
|
50
|
+
toolCallCount: acc.toolCallCount + day.toolCallCount,
|
|
51
|
+
tokensUsed: acc.tokensUsed + day.tokensUsed,
|
|
52
|
+
costEstimate: acc.costEstimate + day.costEstimate
|
|
53
|
+
}),
|
|
54
|
+
{
|
|
55
|
+
date: "",
|
|
56
|
+
messageCount: 0,
|
|
57
|
+
sessionCount: 0,
|
|
58
|
+
toolCallCount: 0,
|
|
59
|
+
tokensUsed: 0,
|
|
60
|
+
costEstimate: 0
|
|
61
|
+
}
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
function StatRow({
|
|
65
|
+
label,
|
|
66
|
+
value,
|
|
67
|
+
max,
|
|
68
|
+
barWidth = 20,
|
|
69
|
+
comparison,
|
|
70
|
+
suffix
|
|
71
|
+
}) {
|
|
72
|
+
const bar = renderProgressBar(value, max, barWidth);
|
|
73
|
+
const formattedValue = formatNumber(value);
|
|
74
|
+
const paddedLabel = label.padEnd(12);
|
|
75
|
+
const paddedValue = formattedValue.padStart(8);
|
|
76
|
+
return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, paddedLabel), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, paddedValue), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, " "), /* @__PURE__ */ React.createElement(Text, { color: BRAND_GRADIENT.START }, bar), comparison !== void 0 && comparison !== 0 && /* @__PURE__ */ React.createElement(
|
|
77
|
+
Text,
|
|
78
|
+
{
|
|
79
|
+
color: comparison > 0 ? SEMANTIC_COLORS.success : SEMANTIC_COLORS.error
|
|
80
|
+
},
|
|
81
|
+
" ",
|
|
82
|
+
"(",
|
|
83
|
+
comparison > 0 ? "+" : "",
|
|
84
|
+
comparison,
|
|
85
|
+
" ",
|
|
86
|
+
t("commands.stats.vsYesterday"),
|
|
87
|
+
")"
|
|
88
|
+
), suffix && /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, " ", suffix));
|
|
89
|
+
}
|
|
90
|
+
function ModelRow({ model, totalCalls, barWidth = 40 }) {
|
|
91
|
+
const percentage = safePercentage(model.calls, totalCalls);
|
|
92
|
+
const bar = renderProgressBar(model.calls, totalCalls, barWidth);
|
|
93
|
+
const displayName = model.model.length > 14 ? model.model.slice(0, 11) + "..." : model.model;
|
|
94
|
+
return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, displayName.padEnd(14)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, String(percentage).padStart(3), "%"), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, " "), /* @__PURE__ */ React.createElement(Text, { color: BRAND_GRADIENT.MIDDLE }, bar), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, " ", "(", formatNumber(model.calls), " ", t("commands.stats.calls"), ")"));
|
|
95
|
+
}
|
|
96
|
+
function ToolRow({ tool, rank }) {
|
|
97
|
+
const successRate = safePercentage(tool.successCount, tool.calls);
|
|
98
|
+
const displayName = tool.toolName.length > 16 ? tool.toolName.slice(0, 13) + "..." : tool.toolName;
|
|
99
|
+
return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, String(rank).padStart(2), ". "), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, displayName.padEnd(16)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, formatNumber(tool.calls).padStart(6)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, " ", t("commands.stats.calls")), tool.errorCount > 0 && /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.error }, " (", successRate, "% success)"));
|
|
100
|
+
}
|
|
101
|
+
function StatsDisplay({
|
|
102
|
+
stats,
|
|
103
|
+
today,
|
|
104
|
+
yesterday,
|
|
105
|
+
weekStats,
|
|
106
|
+
showWeek,
|
|
107
|
+
showMonth,
|
|
108
|
+
showModels,
|
|
109
|
+
showTools,
|
|
110
|
+
onClose
|
|
111
|
+
}) {
|
|
112
|
+
useInput((_, key) => {
|
|
113
|
+
if (key.return || key.escape) onClose();
|
|
114
|
+
});
|
|
115
|
+
const modelStats = getModelUsageStats();
|
|
116
|
+
const toolStats = getToolUsageStats();
|
|
117
|
+
const totalModelCalls = modelStats.reduce((sum, m) => sum + m.calls, 0);
|
|
118
|
+
const msgDiff = today && yesterday ? today.messageCount - yesterday.messageCount : void 0;
|
|
119
|
+
const sessionDiff = today && yesterday ? today.sessionCount - yesterday.sessionCount : void 0;
|
|
120
|
+
const toolDiff = today && yesterday ? today.toolCallCount - yesterday.toolCallCount : void 0;
|
|
121
|
+
const tokenDiff = today && yesterday ? today.tokensUsed - yesterday.tokensUsed : void 0;
|
|
122
|
+
const maxMsg = Math.max(
|
|
123
|
+
today?.messageCount ?? 0,
|
|
124
|
+
yesterday?.messageCount ?? 0,
|
|
125
|
+
1
|
|
126
|
+
);
|
|
127
|
+
const maxSession = Math.max(
|
|
128
|
+
today?.sessionCount ?? 0,
|
|
129
|
+
yesterday?.sessionCount ?? 0,
|
|
130
|
+
1
|
|
131
|
+
);
|
|
132
|
+
const maxTool = Math.max(
|
|
133
|
+
today?.toolCallCount ?? 0,
|
|
134
|
+
yesterday?.toolCallCount ?? 0,
|
|
135
|
+
1
|
|
136
|
+
);
|
|
137
|
+
const maxToken = Math.max(
|
|
138
|
+
today?.tokensUsed ?? 0,
|
|
139
|
+
yesterday?.tokensUsed ?? 0,
|
|
140
|
+
1
|
|
141
|
+
);
|
|
142
|
+
const hasData = stats.lifetime.totalMessages > 0 || stats.lifetime.totalSessions > 0;
|
|
143
|
+
if (!hasData) {
|
|
144
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: BRAND_GRADIENT.START }, t("commands.stats.title"))), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, t("commands.stats.noData")), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(PressEnterToContinue, null)));
|
|
145
|
+
}
|
|
146
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: BRAND_GRADIENT.START }, t("commands.stats.title"))), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "\u2500".repeat(65)), !showWeek && !showMonth && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, t("commands.stats.today"), " (", getTodayString(), ")")), /* @__PURE__ */ React.createElement(Box, { paddingLeft: 2, flexDirection: "column" }, /* @__PURE__ */ React.createElement(
|
|
147
|
+
StatRow,
|
|
148
|
+
{
|
|
149
|
+
label: t("commands.stats.messages"),
|
|
150
|
+
value: today?.messageCount ?? 0,
|
|
151
|
+
max: maxMsg * 1.2,
|
|
152
|
+
comparison: msgDiff
|
|
153
|
+
}
|
|
154
|
+
), /* @__PURE__ */ React.createElement(
|
|
155
|
+
StatRow,
|
|
156
|
+
{
|
|
157
|
+
label: t("commands.stats.sessions"),
|
|
158
|
+
value: today?.sessionCount ?? 0,
|
|
159
|
+
max: maxSession * 1.2,
|
|
160
|
+
comparison: sessionDiff
|
|
161
|
+
}
|
|
162
|
+
), /* @__PURE__ */ React.createElement(
|
|
163
|
+
StatRow,
|
|
164
|
+
{
|
|
165
|
+
label: t("commands.stats.toolCalls"),
|
|
166
|
+
value: today?.toolCallCount ?? 0,
|
|
167
|
+
max: maxTool * 1.2,
|
|
168
|
+
comparison: toolDiff
|
|
169
|
+
}
|
|
170
|
+
), /* @__PURE__ */ React.createElement(
|
|
171
|
+
StatRow,
|
|
172
|
+
{
|
|
173
|
+
label: t("commands.stats.tokens"),
|
|
174
|
+
value: today?.tokensUsed ?? 0,
|
|
175
|
+
max: maxToken * 1.2,
|
|
176
|
+
comparison: tokenDiff
|
|
177
|
+
}
|
|
178
|
+
))), (showWeek || !showMonth) && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, t("commands.stats.thisWeek"))), /* @__PURE__ */ React.createElement(Box, { paddingLeft: 2, flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, t("commands.stats.totalMessages").padEnd(16)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, formatNumber(weekStats.messageCount))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, t("commands.stats.totalSessions").padEnd(16)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, formatNumber(weekStats.sessionCount))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, t("commands.stats.totalTools").padEnd(16)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, formatNumber(weekStats.toolCallCount))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, t("commands.stats.estCost").padEnd(16)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, formatCost(weekStats.costEstimate))))), showMonth && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, t("commands.stats.thisMonth"))), /* @__PURE__ */ React.createElement(Box, { paddingLeft: 2, flexDirection: "column" }, (() => {
|
|
179
|
+
const monthStats = sumDailyStats(getStatsForDays(30));
|
|
180
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, t("commands.stats.totalMessages").padEnd(16)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, formatNumber(monthStats.messageCount))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, t("commands.stats.totalSessions").padEnd(16)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, formatNumber(monthStats.sessionCount))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, t("commands.stats.totalTools").padEnd(16)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, formatNumber(monthStats.toolCallCount))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, t("commands.stats.estCost").padEnd(16)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, formatCost(monthStats.costEstimate))));
|
|
181
|
+
})())), (showModels || !showWeek && !showMonth && !showTools) && modelStats.length > 0 && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, t("commands.stats.modelUsage"))), /* @__PURE__ */ React.createElement(Box, { paddingLeft: 2, flexDirection: "column" }, modelStats.slice(0, 5).map((model) => /* @__PURE__ */ React.createElement(
|
|
182
|
+
ModelRow,
|
|
183
|
+
{
|
|
184
|
+
key: model.model,
|
|
185
|
+
model,
|
|
186
|
+
totalCalls: totalModelCalls
|
|
187
|
+
}
|
|
188
|
+
)))), (showTools || !showWeek && !showMonth && !showModels) && toolStats.length > 0 && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, t("commands.stats.topTools"))), /* @__PURE__ */ React.createElement(Box, { paddingLeft: 2, flexDirection: "column" }, toolStats.slice(0, 5).map((tool, index) => /* @__PURE__ */ React.createElement(ToolRow, { key: tool.toolName, tool, rank: index + 1 })))), !showWeek && !showMonth && !showModels && !showTools && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, t("commands.stats.lifetime"))), /* @__PURE__ */ React.createElement(Box, { paddingLeft: 2, flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, t("commands.stats.totalMessages").padEnd(16)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, formatNumber(stats.lifetime.totalMessages))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, t("commands.stats.totalSessions").padEnd(16)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, formatNumber(stats.lifetime.totalSessions))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, t("commands.stats.totalTools").padEnd(16)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, formatNumber(stats.lifetime.totalToolCalls))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, t("commands.stats.tokens").padEnd(16)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, formatCompactNumber(stats.lifetime.totalTokens))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, t("commands.stats.estCost").padEnd(16)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.primary }, formatCost(stats.lifetime.totalCost))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, t("commands.stats.firstUsed").padEnd(16)), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, stats.lifetime.firstUsed.split("T")[0])))), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "\u2500".repeat(65)), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(PressEnterToContinue, null)));
|
|
189
|
+
}
|
|
190
|
+
function parseArgs(args) {
|
|
191
|
+
const trimmed = args.trim().toLowerCase();
|
|
192
|
+
return {
|
|
193
|
+
week: trimmed.includes("--week") || trimmed.includes("-w"),
|
|
194
|
+
month: trimmed.includes("--month") || trimmed.includes("-m"),
|
|
195
|
+
models: trimmed.includes("--models"),
|
|
196
|
+
tools: trimmed.includes("--tools")
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
const command = {
|
|
200
|
+
name: "stats",
|
|
201
|
+
description: t("commands.stats.description"),
|
|
202
|
+
isEnabled: true,
|
|
203
|
+
isHidden: false,
|
|
204
|
+
type: "local-jsx",
|
|
205
|
+
userFacingName() {
|
|
206
|
+
return this.name;
|
|
207
|
+
},
|
|
208
|
+
async call(onDone, _context, args) {
|
|
209
|
+
const parsedArgs = parseArgs(args ?? "");
|
|
210
|
+
const stats = getStats();
|
|
211
|
+
const today = getTodayStats();
|
|
212
|
+
const recentDays = getStatsForDays(2);
|
|
213
|
+
const yesterday = recentDays.length >= 2 ? recentDays[1] ?? null : null;
|
|
214
|
+
const weekStats = sumDailyStats(getStatsForDays(7));
|
|
215
|
+
return /* @__PURE__ */ React.createElement(
|
|
216
|
+
StatsDisplay,
|
|
217
|
+
{
|
|
218
|
+
stats,
|
|
219
|
+
today,
|
|
220
|
+
yesterday,
|
|
221
|
+
weekStats,
|
|
222
|
+
showWeek: parsedArgs.week,
|
|
223
|
+
showMonth: parsedArgs.month,
|
|
224
|
+
showModels: parsedArgs.models,
|
|
225
|
+
showTools: parsedArgs.tools,
|
|
226
|
+
onClose: onDone
|
|
227
|
+
}
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
var stats_default = command;
|
|
232
|
+
export {
|
|
233
|
+
stats_default as default
|
|
234
|
+
};
|
|
235
|
+
//# sourceMappingURL=stats.js.map
|