Skip to content

Commit 1d19c74

Browse files
authored
Merge pull request #22 from CeerDecy/feature/data-nodes
feat: support nested ctx sub-parameter resolution in variable parsing
2 parents 347318f + c362775 commit 1d19c74

33 files changed

Lines changed: 2250 additions & 74 deletions

File tree

Cargo.lock

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

auto-engine-core/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ tauri = { version = "2.9.4", features = [] }
1414
regex = "1.11.2"
1515
futures = "0.3"
1616
once_cell = "1.21.3"
17+
base64 = "0.22.1"
1718
evalexpr = "12.0.2"
1819
tokio = { version = "1.47.1", features = ["full"] }
1920
tokio-util = "0.7.16"
@@ -36,6 +37,9 @@ toml = "0.9.10"
3637
async-openai = { version = "0.32.2", features = ["responses", "completions", "chat-completion"] }
3738
secrecy = "0.10"
3839
bytes = "1.11.0"
40+
uuid = { version = "1.11.0", features = ["v4"] }
41+
chrono = { version = "0.4.42", features = ["serde"] }
42+
chrono-tz = "0.10.1"
3943

4044
[features]
4145
default = ["types", "context", "event", "pipeline", "runner", "utils"]

auto-engine-core/src/context.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::utils;
22
use serde::{Deserialize, Serialize};
33
use std::collections::HashMap;
4+
use std::fs;
45
use std::path::{Path, PathBuf};
56
use std::sync::Arc;
67
use tauri::Manager;
@@ -99,19 +100,29 @@ impl Context {
99100
}
100101

101102
pub fn path_image(&self, image: &str) -> Result<PathBuf, String> {
102-
let image_path = self.workflow_path.join("images").join(image);
103+
let image_path = self.workflow_path.join("files").join(image);
103104
if !image_path.exists() {
104105
return Err(format!("Image {} does not exist", image));
105106
}
106107
Ok(image_path)
107108
}
109+
pub fn path_files(&self) -> Result<PathBuf, String> {
110+
let dir = self.workflow_path.join("files");
111+
if !dir.exists() {
112+
fs::create_dir_all(&dir).map_err(|e| format!("Failed to create files dir: {}", e))?;
113+
}
114+
Ok(dir)
115+
}
108116

109117
pub fn path_resource(&self) -> PathBuf {
110-
if let Some(handle) = self.app_handle.clone() {
111-
if cfg!(debug_assertions) {
112-
return PathBuf::from("");
118+
#[cfg(feature = "tauri")]
119+
{
120+
if let Some(handle) = self.app_handle.clone() {
121+
if cfg!(debug_assertions) {
122+
return PathBuf::from("");
123+
}
124+
return handle.path().resource_dir().unwrap().to_path_buf();
113125
}
114-
return handle.path().resource_dir().unwrap().to_path_buf();
115126
}
116127
PathBuf::from("")
117128
}

auto-engine-core/src/node.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
pub mod data_aggregator;
2+
pub mod base64_decode;
3+
pub mod base64_encode;
4+
pub mod file_write;
25
pub mod http;
36
pub mod image_match;
47
pub mod keyboard;
@@ -7,7 +10,10 @@ pub mod mouse_move;
710
pub mod ocr;
811
pub mod screen_capture;
912
pub mod start;
13+
pub mod text_case;
14+
pub mod text_replace;
1015
pub mod time_wait;
16+
pub mod time_now;
1117
#[cfg(feature = "wasm")]
1218
pub mod wasm;
1319
pub mod ai;

auto-engine-core/src/node/ai/gpt/node.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ impl NodeDefine for GptNode {
153153
},
154154
SchemaField {
155155
name: "system".to_string(),
156-
field_type: FieldType::String,
156+
field_type: FieldType::Text,
157157
item_type: None,
158158
description: Some(I18nValue {
159159
zh: "系统提示词,可为空".to_string(),
@@ -169,7 +169,7 @@ impl NodeDefine for GptNode {
169169
},
170170
SchemaField {
171171
name: "prompt".to_string(),
172-
field_type: FieldType::String,
172+
field_type: FieldType::Text,
173173
item_type: None,
174174
description: Some(I18nValue {
175175
zh: "用户提示词".to_string(),

auto-engine-core/src/node/ai/gpt/runner.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,17 +110,26 @@ impl NodeRunner for GptRunner {
110110
let mut messages: Vec<ChatCompletionRequestMessage> = vec![];
111111

112112
// context prompt
113+
// {
114+
// let context_prompt = self.build_context_prompt(ctx).await;
115+
// messages.push(
116+
// ChatCompletionRequestSystemMessageArgs::default()
117+
// .content(context_prompt)
118+
// .build()
119+
// .map_err(|e| format!("failed to build system message: {}", e))?
120+
// .into(),
121+
// );
122+
// }
123+
113124
{
114-
let context_prompt = self.build_context_prompt(ctx).await;
115-
messages.push(
116-
ChatCompletionRequestSystemMessageArgs::default()
117-
.content(context_prompt)
118-
.build()
119-
.map_err(|e| format!("failed to build system message: {}", e))?
120-
.into(),
121-
);
125+
messages.push(
126+
ChatCompletionRequestSystemMessageArgs::default()
127+
.content(String::from("The generated content needs to be placed in the data section: {\"data\": object}"))
128+
.build()
129+
.map_err(|e| format!("failed to build system message: {}", e))?
130+
.into(),
131+
);
122132
}
123-
124133
// user set system prompt
125134
if let Some(system_prompt) = param
126135
.system
@@ -153,7 +162,6 @@ impl NodeRunner for GptRunner {
153162
}
154163

155164
let request = CreateChatCompletionRequestArgs::default()
156-
.max_tokens(512u32)
157165
.model(param.model)
158166
.response_format(ResponseFormat::JsonSchema {
159167
json_schema: response_schema,
@@ -188,6 +196,7 @@ impl NodeRunner for GptRunner {
188196
.inspect_err(|e| log::error!("chat message: {}, error: {}", content, e))
189197
.map_err(|e| format!("failed to parse chat message: {}", e))?;
190198

199+
log::info!("OpenAI chat message: {}", content);
191200
res.insert("data".to_string(), serde_json::json!(data.get("data")));
192201
}
193202

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod node;
2+
pub mod runner;
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
use crate::types::field::{FieldType, SchemaField};
2+
use crate::types::node::{I18nValue, NodeDefine};
3+
use std::collections::HashMap;
4+
5+
pub const NODE_TYPE: &str = "Base64Decode";
6+
7+
#[derive(Default)]
8+
pub struct Base64DecodeNode;
9+
10+
impl Base64DecodeNode {
11+
pub fn new() -> Self {
12+
Self {}
13+
}
14+
}
15+
16+
impl NodeDefine for Base64DecodeNode {
17+
fn action_type(&self) -> String {
18+
NODE_TYPE.to_string()
19+
}
20+
21+
fn name(&self) -> I18nValue {
22+
I18nValue {
23+
zh: "Base64 解码".to_string(),
24+
en: "Base64 Decode".to_string(),
25+
}
26+
}
27+
28+
fn icon(&self) -> String {
29+
String::from(
30+
"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHJlY3QgeD0iMyIgeT0iMyIgd2lkdGg9IjE4IiBoZWlnaHQ9IjE4IiByeD0iMiIvPjxwYXRoIGQ9Ik04IDEwaDgiLz48cGF0aCBkPSJNMTIgMTR2NCIvPjxwYXRoIGQ9Ik05LjUgMTUuNSAxMiAxOGwyLjUtMi41Ii8+PC9zdmc+",
31+
)
32+
}
33+
34+
fn category(&self) -> Option<I18nValue> {
35+
Some(I18nValue {
36+
zh: "文本处理".to_string(),
37+
en: "Text Processing".to_string(),
38+
})
39+
}
40+
41+
fn description(&self) -> Option<I18nValue> {
42+
Some(I18nValue {
43+
zh: "将 Base64 字符串解码为文本,包含 UTF-8 检查与长度信息。".to_string(),
44+
en: "Decode a Base64 string into text with UTF-8 validation and length info."
45+
.to_string(),
46+
})
47+
}
48+
49+
fn output_schema(&self, _input: HashMap<String, serde_json::Value>) -> Vec<SchemaField> {
50+
vec![
51+
SchemaField {
52+
name: "decoded".to_string(),
53+
field_type: FieldType::String,
54+
item_type: None,
55+
description: Some(I18nValue {
56+
zh: "解码得到的文本(非 UTF-8 会采用替换字符)".to_string(),
57+
en: "Decoded text (non UTF-8 bytes are lossily converted).".to_string(),
58+
}),
59+
enums: vec![],
60+
default: None,
61+
condition: None,
62+
},
63+
SchemaField {
64+
name: "is_utf8".to_string(),
65+
field_type: FieldType::Boolean,
66+
item_type: None,
67+
description: Some(I18nValue {
68+
zh: "解码结果是否是有效 UTF-8".to_string(),
69+
en: "Whether the decoded bytes are valid UTF-8.".to_string(),
70+
}),
71+
enums: vec![],
72+
default: None,
73+
condition: None,
74+
},
75+
SchemaField {
76+
name: "byte_length".to_string(),
77+
field_type: FieldType::Number,
78+
item_type: None,
79+
description: Some(I18nValue {
80+
zh: "解码结果的字节长度".to_string(),
81+
en: "Byte length of the decoded result.".to_string(),
82+
}),
83+
enums: vec![],
84+
default: None,
85+
condition: None,
86+
},
87+
]
88+
}
89+
90+
fn input_schema(&self) -> Vec<SchemaField> {
91+
vec![
92+
SchemaField {
93+
name: "data".to_string(),
94+
field_type: FieldType::String,
95+
item_type: None,
96+
description: Some(I18nValue {
97+
zh: "需要解码的 Base64 字符串".to_string(),
98+
en: "Base64 string to decode.".to_string(),
99+
}),
100+
enums: vec![],
101+
default: None,
102+
condition: None,
103+
},
104+
SchemaField {
105+
name: "url_safe".to_string(),
106+
field_type: FieldType::Boolean,
107+
item_type: None,
108+
description: Some(I18nValue {
109+
zh: "是否使用 URL Safe 字母表".to_string(),
110+
en: "Use the URL-safe alphabet.".to_string(),
111+
}),
112+
enums: vec![],
113+
default: None,
114+
condition: None,
115+
},
116+
SchemaField {
117+
name: "no_padding".to_string(),
118+
field_type: FieldType::Boolean,
119+
item_type: None,
120+
description: Some(I18nValue {
121+
zh: "输入是否移除了末尾填充符号 \"=\"".to_string(),
122+
en: "Input omits trailing padding characters (=).".to_string(),
123+
}),
124+
enums: vec![],
125+
default: None,
126+
condition: None,
127+
},
128+
]
129+
}
130+
}

0 commit comments

Comments
 (0)