@pheem49/mint 1.6.3 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +3 -3
- package/Cargo.toml +1 -1
- package/README.md +82 -21
- package/assets/Mint_CLI.png +0 -0
- package/assets/Mint_Desktop.png +0 -0
- package/assets/Mint_Web.png +0 -0
- package/assets/Mint_WorkSpace.png +0 -0
- package/assets/Setting.png +0 -0
- package/assets/bridges.svg +4 -0
- package/assets/chat.svg +3 -0
- package/assets/code.svg +4 -0
- package/assets/features.svg +3 -0
- package/assets/imagegen.svg +5 -0
- package/assets/live2d.svg +6 -0
- package/assets/memory.svg +5 -0
- package/assets/screencapture.svg +4 -0
- package/assets/setup.svg +3 -0
- package/assets/tools.svg +4 -0
- package/bin/mint +0 -0
- package/crates/mint-cli/src/agent.rs +47 -15
- package/crates/mint-cli/src/main.rs +534 -7
- package/crates/mint-cli/src/onboard.rs +134 -1
- package/crates/mint-cli/src/setup.rs +173 -32
- package/crates/mint-core/src/api_server.rs +147 -3
- package/crates/mint-core/src/config.rs +22 -3
- package/crates/mint-core/src/image_gen.rs +895 -0
- package/crates/mint-core/src/lib.rs +4 -0
- package/crates/mint-core/src/memory.rs +27 -1
- package/crates/mint-core/src/orchestration.rs +1 -1
- package/crates/mint-core/src/plugins.rs +32 -0
- package/crates/mint-core/tests/memory_persistence.rs +28 -0
- package/package.json +1 -1
- package/src/bin/index.js +0 -0
- package/src/renderer/src/agentProgress.ts +39 -0
- package/src/renderer/src/components/ChatPanel.tsx +547 -47
- package/src/renderer/src/components/DashboardSidebar.tsx +12 -4
- package/src/renderer/src/components/ImageStudioPanel.tsx +638 -0
- package/src/renderer/src/components/MintDashboard.tsx +84 -31
- package/src/renderer/src/components/ModelPanel.tsx +2 -2
- package/src/renderer/src/components/PicturesLibrary.tsx +5 -1
- package/src/renderer/src/components/SettingsWindow.tsx +29 -20
- package/src/renderer/src/components/SpotlightWindow.tsx +8 -8
- package/src/renderer/src/components/WorkspacePanel.tsx +1 -1
- package/src/renderer/src/css/image-studio.css +722 -0
- package/src/renderer/src/css/settings.css +13 -3
- package/src/renderer/src/css/styles.css +245 -43
- package/src/renderer/src/index.css +152 -0
- package/src/renderer/src/tauri.ts +148 -0
- package/src/renderer/src-web/App.tsx +16 -1
- package/src/renderer/src-web/agentProgress.ts +39 -0
- package/src/renderer/src-web/components/ChatPanel.tsx +568 -46
- package/src/renderer/src-web/components/DashboardSidebar.tsx +10 -2
- package/src/renderer/src-web/components/ImageStudioPanel.tsx +638 -0
- package/src/renderer/src-web/components/MintDashboard.tsx +65 -19
- package/src/renderer/src-web/components/PicturesLibrary.tsx +5 -1
- package/src/renderer/src-web/components/SettingsWindow.tsx +29 -20
- package/src/renderer/src-web/css/image-studio.css +722 -0
- package/src/renderer/src-web/css/settings.css +14 -4
- package/src/renderer/src-web/css/styles.css +292 -44
- package/src/renderer/src-web/index.css +152 -0
- package/src/renderer/src-web/tauri.ts +149 -0
- package/src-tauri/src/lib.rs +65 -5
- package/src-tauri/tauri.conf.json +1 -1
|
@@ -5,6 +5,7 @@ pub mod chat;
|
|
|
5
5
|
pub mod code_tools;
|
|
6
6
|
pub mod config;
|
|
7
7
|
pub mod files;
|
|
8
|
+
pub mod image_gen;
|
|
8
9
|
pub mod knowledge;
|
|
9
10
|
pub mod mcp;
|
|
10
11
|
pub mod memory;
|
|
@@ -39,6 +40,9 @@ pub use config::{
|
|
|
39
40
|
set_config_value,
|
|
40
41
|
};
|
|
41
42
|
pub use files::{FileOperationError, PathKind, PathMatch, create_folder, find_paths};
|
|
43
|
+
pub use image_gen::{
|
|
44
|
+
GeneratedImage, ImageGenError, ImageGenRequest, ImageGenResponse, generate_images,
|
|
45
|
+
};
|
|
42
46
|
pub use knowledge::{
|
|
43
47
|
KnowledgeError, KnowledgeHit, KnowledgeSource, KnowledgeStore, extract_document_text,
|
|
44
48
|
};
|
|
@@ -36,6 +36,8 @@ pub struct InteractionMemory {
|
|
|
36
36
|
pub model: String,
|
|
37
37
|
pub fallback_provider: Option<String>,
|
|
38
38
|
pub created_at: String,
|
|
39
|
+
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
40
|
+
pub agent_activity: Option<serde_json::Value>,
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
|
|
@@ -172,7 +174,7 @@ impl MemoryStore {
|
|
|
172
174
|
ensure_builtin_chat_sessions(&connection)?;
|
|
173
175
|
ensure_chat_session_row(&connection, &chat_id)?;
|
|
174
176
|
let mut statement = connection.prepare(
|
|
175
|
-
"SELECT id, chat_id, user_text, ai_text, provider, model, fallback_provider, created_at
|
|
177
|
+
"SELECT id, chat_id, user_text, ai_text, provider, model, fallback_provider, created_at, agent_activity_json
|
|
176
178
|
FROM interaction_memories
|
|
177
179
|
WHERE chat_id = ?1
|
|
178
180
|
ORDER BY id DESC
|
|
@@ -202,6 +204,20 @@ impl MemoryStore {
|
|
|
202
204
|
rows.collect::<Result<Vec<_>, _>>().map_err(Into::into)
|
|
203
205
|
}
|
|
204
206
|
|
|
207
|
+
pub fn set_interaction_agent_activity_json(
|
|
208
|
+
&self,
|
|
209
|
+
interaction_id: i64,
|
|
210
|
+
activity_json: &str,
|
|
211
|
+
) -> Result<usize, MemoryError> {
|
|
212
|
+
let connection = self.connection()?;
|
|
213
|
+
Ok(connection.execute(
|
|
214
|
+
"UPDATE interaction_memories
|
|
215
|
+
SET agent_activity_json = ?2
|
|
216
|
+
WHERE id = ?1",
|
|
217
|
+
params![interaction_id, activity_json],
|
|
218
|
+
)?)
|
|
219
|
+
}
|
|
220
|
+
|
|
205
221
|
pub fn clear_interactions(&self) -> Result<usize, MemoryError> {
|
|
206
222
|
self.clear_interactions_for_chat(DEFAULT_CONVERSATION_ID)
|
|
207
223
|
}
|
|
@@ -551,6 +567,12 @@ fn initialize(
|
|
|
551
567
|
"fallback_provider",
|
|
552
568
|
"TEXT DEFAULT NULL",
|
|
553
569
|
)?;
|
|
570
|
+
ensure_column(
|
|
571
|
+
connection,
|
|
572
|
+
"interaction_memories",
|
|
573
|
+
"agent_activity_json",
|
|
574
|
+
"TEXT DEFAULT NULL",
|
|
575
|
+
)?;
|
|
554
576
|
ensure_column(
|
|
555
577
|
connection,
|
|
556
578
|
"chat_sessions",
|
|
@@ -612,6 +634,9 @@ fn learned_skill_row(row: &rusqlite::Row<'_>) -> Result<LearnedSkill, rusqlite::
|
|
|
612
634
|
}
|
|
613
635
|
|
|
614
636
|
fn interaction_row(row: &rusqlite::Row<'_>) -> Result<InteractionMemory, rusqlite::Error> {
|
|
637
|
+
let agent_activity = row
|
|
638
|
+
.get::<_, Option<String>>(8)?
|
|
639
|
+
.and_then(|raw| serde_json::from_str(&raw).ok());
|
|
615
640
|
Ok(InteractionMemory {
|
|
616
641
|
id: row.get(0)?,
|
|
617
642
|
chat_id: row.get(1)?,
|
|
@@ -621,6 +646,7 @@ fn interaction_row(row: &rusqlite::Row<'_>) -> Result<InteractionMemory, rusqlit
|
|
|
621
646
|
model: row.get(5)?,
|
|
622
647
|
fallback_provider: row.get(6)?,
|
|
623
648
|
created_at: row.get(7)?,
|
|
649
|
+
agent_activity,
|
|
624
650
|
})
|
|
625
651
|
}
|
|
626
652
|
|
|
@@ -385,7 +385,7 @@ pub fn build_system_prompt(config: &MintConfig) -> String {
|
|
|
385
385
|
"- write_file: {\"path\":\"new/relative/path\",\"fileContent\":\"full file content\"}",
|
|
386
386
|
);
|
|
387
387
|
}
|
|
388
|
-
input_formats.push("- finish: {\"summary\":\"concise final answer\",\"verification\":\"checks run or not run\"}");
|
|
388
|
+
input_formats.push("- finish: {\"summary\":\"concise final answer in Thai when the user writes Thai\",\"verification\":\"checks run or not run\"}");
|
|
389
389
|
|
|
390
390
|
let input_formats_str = input_formats.join("\n");
|
|
391
391
|
|
|
@@ -84,6 +84,10 @@ pub fn native_plugins() -> Vec<NativePlugin> {
|
|
|
84
84
|
name: "notion",
|
|
85
85
|
description: "Create notes, read databases, and append blocks through Notion API.",
|
|
86
86
|
},
|
|
87
|
+
NativePlugin {
|
|
88
|
+
name: "github",
|
|
89
|
+
description: "List issues, view issues, list pull requests, or check PR status via gh CLI.",
|
|
90
|
+
},
|
|
87
91
|
]
|
|
88
92
|
}
|
|
89
93
|
|
|
@@ -104,6 +108,7 @@ pub async fn execute_native_plugin(
|
|
|
104
108
|
"gmail" => gmail(config, instruction).await,
|
|
105
109
|
"google_calendar" => calendar(config, instruction).await,
|
|
106
110
|
"notion" => notion(config, instruction).await,
|
|
111
|
+
"github" => github(instruction),
|
|
107
112
|
_ => Err(PluginError::UnknownPlugin(name.into())),
|
|
108
113
|
}
|
|
109
114
|
}
|
|
@@ -229,6 +234,33 @@ fn spotify(instruction: &str) -> Result<String, PluginError> {
|
|
|
229
234
|
run("playerctl", &args)
|
|
230
235
|
}
|
|
231
236
|
|
|
237
|
+
fn github(instruction: &str) -> Result<String, PluginError> {
|
|
238
|
+
let parts = instruction.split_whitespace().collect::<Vec<_>>();
|
|
239
|
+
match parts.as_slice() {
|
|
240
|
+
["list_issues"] | ["issue", "list"] => run("gh", &["issue", "list", "--limit", "10"]),
|
|
241
|
+
["view_issue", id] | ["issue", "view", id] => {
|
|
242
|
+
if id.chars().all(|c| c.is_ascii_digit()) {
|
|
243
|
+
run("gh", &["issue", "view", id])
|
|
244
|
+
} else {
|
|
245
|
+
invalid("github", "view_issue/issue view requires a numeric issue ID")
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
["list_prs"] | ["pr", "list"] => run("gh", &["pr", "list", "--limit", "10"]),
|
|
249
|
+
["pr_status"] | ["pr", "status"] => run("gh", &["pr", "status"]),
|
|
250
|
+
["view_pr", id] | ["pr", "view", id] => {
|
|
251
|
+
if id.chars().all(|c| c.is_ascii_digit()) {
|
|
252
|
+
run("gh", &["pr", "view", id])
|
|
253
|
+
} else {
|
|
254
|
+
invalid("github", "view_pr/pr view requires a numeric PR ID")
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
_ => invalid(
|
|
258
|
+
"github",
|
|
259
|
+
"expected list_issues, view_issue <id>, list_prs, pr_status, or view_pr <id>",
|
|
260
|
+
),
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
232
264
|
fn system_metrics(instruction: &str) -> Result<String, PluginError> {
|
|
233
265
|
let uptime = fs::read_to_string("/proc/uptime")
|
|
234
266
|
.ok()
|
|
@@ -57,6 +57,34 @@ fn stores_recent_interactions_with_provider_metadata() {
|
|
|
57
57
|
assert_eq!(interactions[1].fallback_provider, None);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
#[test]
|
|
61
|
+
fn stores_and_reads_interaction_agent_activity() {
|
|
62
|
+
let store = store("agent-activity");
|
|
63
|
+
let interaction_id = store
|
|
64
|
+
.add_interaction_with_metadata("hello", "hi", "gemini", "gemini-test")
|
|
65
|
+
.unwrap();
|
|
66
|
+
store
|
|
67
|
+
.set_interaction_agent_activity_json(
|
|
68
|
+
interaction_id,
|
|
69
|
+
r#"[{"type":"Thought","data":{"thought":"step one"}}]"#,
|
|
70
|
+
)
|
|
71
|
+
.unwrap();
|
|
72
|
+
|
|
73
|
+
let interactions = store.recent_interactions(1).unwrap();
|
|
74
|
+
assert_eq!(interactions.len(), 1);
|
|
75
|
+
let activity = interactions[0]
|
|
76
|
+
.agent_activity
|
|
77
|
+
.as_ref()
|
|
78
|
+
.and_then(|value| value.as_array())
|
|
79
|
+
.cloned()
|
|
80
|
+
.unwrap_or_default();
|
|
81
|
+
assert_eq!(activity.len(), 1);
|
|
82
|
+
assert_eq!(
|
|
83
|
+
activity[0].get("type").and_then(|value| value.as_str()),
|
|
84
|
+
Some("Thought")
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
60
88
|
#[test]
|
|
61
89
|
fn preserves_chat_history_when_store_is_reopened() {
|
|
62
90
|
let path = test_path("reopen-history", "sqlite");
|
package/package.json
CHANGED
package/src/bin/index.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AgentProgress, InteractionMemory } from './tauri'
|
|
2
|
+
|
|
3
|
+
export function thoughtsFrom(progress: AgentProgress[]): string[] {
|
|
4
|
+
return progress
|
|
5
|
+
.filter((event) => event.type === 'Thought')
|
|
6
|
+
.map((event) => (event as Extract<AgentProgress, { type: 'Thought' }>).data.thought)
|
|
7
|
+
.filter(Boolean)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function trimAgentProgress(progress: AgentProgress[], maxNonThought = 20): AgentProgress[] {
|
|
11
|
+
if (progress.length === 0) return progress
|
|
12
|
+
const keptNonThought = new Set(
|
|
13
|
+
progress.filter((event) => event.type !== 'Thought').slice(-maxNonThought),
|
|
14
|
+
)
|
|
15
|
+
return progress.filter((event) => event.type === 'Thought' || keptNonThought.has(event))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function hasAgentToolActivity(progress: AgentProgress[]): boolean {
|
|
19
|
+
return progress.some((event) => event.type === 'ToolStart' || event.type === 'ToolEnd')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function mergeActivitySnapshots(
|
|
23
|
+
current: Record<string, AgentProgress[]>,
|
|
24
|
+
interactions: InteractionMemory[],
|
|
25
|
+
): Record<string, AgentProgress[]> {
|
|
26
|
+
const merged = { ...current }
|
|
27
|
+
for (const interaction of interactions) {
|
|
28
|
+
const key = String(interaction.id)
|
|
29
|
+
if (interaction.agentActivity?.length && !merged[key]) {
|
|
30
|
+
merged[key] = interaction.agentActivity
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return merged
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function parseAgentActivity(value: unknown): AgentProgress[] | undefined {
|
|
37
|
+
if (!Array.isArray(value)) return undefined
|
|
38
|
+
return value as AgentProgress[]
|
|
39
|
+
}
|