commit
This commit is contained in:
52
.air.toml
Normal file
52
.air.toml
Normal file
@@ -0,0 +1,52 @@
|
||||
root = "."
|
||||
testdata_dir = "testdata"
|
||||
tmp_dir = "tmp"
|
||||
|
||||
[build]
|
||||
args_bin = []
|
||||
bin = "./tmp/main"
|
||||
cmd = "go build -o ./tmp/main ."
|
||||
delay = 1000
|
||||
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
|
||||
exclude_file = []
|
||||
exclude_regex = ["_test.go"]
|
||||
exclude_unchanged = false
|
||||
follow_symlink = false
|
||||
full_bin = ""
|
||||
include_dir = []
|
||||
include_ext = ["go", "tpl", "tmpl", "html"]
|
||||
include_file = []
|
||||
kill_delay = "0s"
|
||||
log = "build-errors.log"
|
||||
poll = false
|
||||
poll_interval = 0
|
||||
post_cmd = []
|
||||
pre_cmd = []
|
||||
rerun = false
|
||||
rerun_delay = 500
|
||||
send_interrupt = false
|
||||
stop_on_error = false
|
||||
|
||||
[color]
|
||||
app = ""
|
||||
build = "yellow"
|
||||
main = "magenta"
|
||||
runner = "green"
|
||||
watcher = "cyan"
|
||||
|
||||
[log]
|
||||
main_only = false
|
||||
silent = false
|
||||
time = false
|
||||
|
||||
[misc]
|
||||
clean_on_exit = false
|
||||
|
||||
[proxy]
|
||||
app_port = 0
|
||||
enabled = false
|
||||
proxy_port = 0
|
||||
|
||||
[screen]
|
||||
clear_on_rebuild = false
|
||||
keep_scroll = true
|
||||
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"go.toolsEnvVars": {
|
||||
"GOOS": "",
|
||||
"GOARCH": ""
|
||||
},
|
||||
}
|
||||
146
cmd/message-migrator/README.md
Normal file
146
cmd/message-migrator/README.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Message Migrator 数据迁移工具
|
||||
|
||||
这个工具用于将指定项目的消息数据从源数据库迁移到目标数据库。
|
||||
|
||||
## 功能特性
|
||||
|
||||
- ✅ 按项目ID迁移数据
|
||||
- ✅ 支持可选的UID替换
|
||||
- ✅ 自动处理表之间的ID关联映射
|
||||
- ✅ 使用事务保证数据一致性
|
||||
- ✅ 按正确的依赖顺序迁移:`m_stream_messages` → `m_stream_contents` → `m_context_messages` → `m_task_messages`
|
||||
|
||||
## 涉及的表
|
||||
|
||||
1. `m_stream_messages` - 流式消息记录表(主表)
|
||||
2. `m_stream_contents` - 流式消息内容详情及分段表
|
||||
3. `m_context_messages` - Agent上下文消息记录表
|
||||
4. `m_task_messages` - 任务聚合消息记录表
|
||||
|
||||
## 安装依赖
|
||||
|
||||
```bash
|
||||
go get github.com/go-sql-driver/mysql
|
||||
```
|
||||
|
||||
## 配置
|
||||
|
||||
在使用前,请修改 `main.go` 中的数据库连接配置:
|
||||
|
||||
```go
|
||||
const (
|
||||
// 源数据库 DSN 格式: user:password@tcp(host:port)/database?parseTime=true
|
||||
SOURCE_DSN = "user:password@tcp(localhost:3306)/goalfymax_prod?parseTime=true"
|
||||
// 目标数据库 DSN
|
||||
TARGET_DSN = "user:password@tcp(localhost:3306)/goalfymax_archive?parseTime=true"
|
||||
)
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 基本用法(保持原始UID)
|
||||
|
||||
```bash
|
||||
go run main.go -project <project_id>
|
||||
```
|
||||
|
||||
示例:
|
||||
```bash
|
||||
go run main.go -project 123
|
||||
```
|
||||
|
||||
### 替换UID
|
||||
|
||||
```bash
|
||||
go run main.go -project <project_id> -uid <new_uid>
|
||||
```
|
||||
|
||||
示例:
|
||||
```bash
|
||||
go run main.go -project 123 -uid 456
|
||||
```
|
||||
|
||||
### 自定义数据库连接
|
||||
|
||||
```bash
|
||||
go run main.go -project 123 \
|
||||
-source "root:pass@tcp(source-host:3306)/goalfymax_prod?parseTime=true" \
|
||||
-target "root:pass@tcp(target-host:3306)/goalfymax_archive?parseTime=true"
|
||||
```
|
||||
|
||||
### 编译后使用
|
||||
|
||||
```bash
|
||||
# 编译
|
||||
go build -o message-migrator
|
||||
|
||||
# 运行
|
||||
./message-migrator -project 123
|
||||
./message-migrator -project 123 -uid 456
|
||||
```
|
||||
|
||||
## 参数说明
|
||||
|
||||
| 参数 | 必需 | 说明 | 示例 |
|
||||
| ---------- | ---- | ------------------------------------------- | --------------------------------------- |
|
||||
| `-project` | 是 | 要迁移的项目ID | `-project 123` |
|
||||
| `-uid` | 否 | 新的用户ID(不指定则使用原始UID) | `-uid 456` |
|
||||
| `-source` | 否 | 源数据库DSN(不指定则使用代码中的默认值) | `-source "user:pass@tcp(host:3306)/db"` |
|
||||
| `-target` | 否 | 目标数据库DSN(不指定则使用代码中的默认值) | `-target "user:pass@tcp(host:3306)/db"` |
|
||||
|
||||
## 迁移流程
|
||||
|
||||
1. **连接数据库**:连接到源数据库和目标数据库
|
||||
2. **开启事务**:在两个数据库上分别开启事务
|
||||
3. **迁移主表**:迁移 `m_stream_messages`,记录旧ID到新ID的映射
|
||||
4. **迁移关联表**:
|
||||
- 迁移 `m_stream_contents`,使用映射更新 `main_message_id`
|
||||
- 迁移 `m_context_messages`,使用映射更新 `main_message_id`
|
||||
- 迁移 `m_task_messages`,使用映射更新 `main_message_id`
|
||||
5. **提交事务**:所有数据迁移成功后提交事务
|
||||
|
||||
## 注意事项
|
||||
|
||||
⚠️ **重要提示**:
|
||||
|
||||
1. **备份数据**:在执行迁移前,请务必备份源数据库和目标数据库
|
||||
2. **目标表存在**:工具不会创建表,请确保目标数据库中已存在所有需要的表结构
|
||||
3. **事务一致性**:迁移过程使用事务,如果中途失败会自动回滚
|
||||
4. **ID映射**:工具会自动处理 `main_message_id` 的映射关系,确保关联正确
|
||||
5. **UID替换**:如果指定了 `-uid` 参数,所有表中的 `uid` 字段都会被替换为新值
|
||||
6. **重复执行**:请注意,重复执行相同的迁移命令可能会导致数据重复
|
||||
|
||||
## 日志输出
|
||||
|
||||
工具会输出详细的迁移日志:
|
||||
|
||||
```
|
||||
2025/11/07 10:00:00 Starting migration for project_id=123
|
||||
2025/11/07 10:00:00 Will replace UID with: 456
|
||||
2025/11/07 10:00:01 Step 1: Migrating m_stream_messages...
|
||||
2025/11/07 10:00:02 Migrated 150 stream messages
|
||||
2025/11/07 10:00:02 Step 2: Migrating m_stream_contents...
|
||||
2025/11/07 10:00:03 Migrated 300 stream contents
|
||||
2025/11/07 10:00:03 Step 3: Migrating m_context_messages...
|
||||
2025/11/07 10:00:04 Migrated 200 context messages
|
||||
2025/11/07 10:00:04 Step 4: Migrating m_task_messages...
|
||||
2025/11/07 10:00:05 Migrated 180 task messages
|
||||
2025/11/07 10:00:05 Migration completed successfully!
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
|
||||
如果迁移过程中遇到错误:
|
||||
|
||||
- 事务会自动回滚,不会产生部分数据
|
||||
- 错误信息会显示在日志中
|
||||
- 检查数据库连接、权限和表结构是否正确
|
||||
|
||||
## 性能建议
|
||||
|
||||
对于大量数据的迁移:
|
||||
|
||||
1. 在非高峰期执行
|
||||
2. 确保数据库有足够的临时空间
|
||||
3. 可以考虑先迁移到测试环境验证
|
||||
4. 监控数据库性能指标
|
||||
569
cmd/message-migrator/main.go
Normal file
569
cmd/message-migrator/main.go
Normal file
@@ -0,0 +1,569 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
// 配置常量 - 请根据实际情况修改
|
||||
const (
|
||||
// 源数据库 DSN 格式: user:password@tcp(host:port)/database?parseTime=true
|
||||
SOURCE_DSN = "goalfymax_prod:X6cQDaOLOifFBOMq@tcp(goalfyagent-aurora-mysql-staging.cb2sq6y2mg93.us-west-2.rds.amazonaws.com:3306)/goalfymax_prod?charset=utf8mb4&parseTime=True&loc=UTC"
|
||||
// 目标数据库 DSN
|
||||
TARGET_DSN = "root:123456@tcp(localhost:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
)
|
||||
|
||||
type MigrationConfig struct {
|
||||
ProjectID uint64
|
||||
NewUID *uint64 // 如果为 nil,则使用原始 UID
|
||||
SourceDB *sql.DB
|
||||
TargetDB *sql.DB
|
||||
}
|
||||
|
||||
// StreamMessage 对应 m_stream_messages 表
|
||||
type StreamMessage struct {
|
||||
ID uint64
|
||||
UID uint64
|
||||
ProjectID uint64
|
||||
SenderID sql.NullString
|
||||
SenderAgentType sql.NullString
|
||||
Type string
|
||||
MessageTimestamp string
|
||||
AgentGenMessageID sql.NullString
|
||||
Content string
|
||||
FormattedContent string
|
||||
TaskID sql.NullString
|
||||
TaskStatus sql.NullString
|
||||
TurnID sql.NullInt32
|
||||
AgentMessageID sql.NullString
|
||||
Source string
|
||||
Metadata sql.NullString
|
||||
ReceivedAt string
|
||||
CreatedAt string
|
||||
Show int
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 命令行参数
|
||||
projectID := flag.Uint64("project", 0, "Project ID to migrate (required)")
|
||||
newUID := flag.Uint64("uid", 0, "New UID for migrated data (optional, use 0 to keep original)")
|
||||
sourceDSN := flag.String("source", SOURCE_DSN, "Source database DSN")
|
||||
targetDSN := flag.String("target", TARGET_DSN, "Target database DSN")
|
||||
flag.Parse()
|
||||
|
||||
if *projectID == 0 {
|
||||
fmt.Println("Usage: go run main.go -project <project_id> [-uid <new_uid>] [-source <dsn>] [-target <dsn>]")
|
||||
fmt.Println("\nExample:")
|
||||
fmt.Println(" go run main.go -project 123")
|
||||
fmt.Println(" go run main.go -project 123 -uid 456")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 连接数据库
|
||||
sourceDB, err := sql.Open("mysql", *sourceDSN)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to connect to source database: %v", err)
|
||||
}
|
||||
defer sourceDB.Close()
|
||||
|
||||
targetDB, err := sql.Open("mysql", *targetDSN)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to connect to target database: %v", err)
|
||||
}
|
||||
defer targetDB.Close()
|
||||
|
||||
// 测试连接
|
||||
if err := sourceDB.Ping(); err != nil {
|
||||
log.Fatalf("Failed to ping source database: %v", err)
|
||||
}
|
||||
if err := targetDB.Ping(); err != nil {
|
||||
log.Fatalf("Failed to ping target database: %v", err)
|
||||
}
|
||||
|
||||
config := &MigrationConfig{
|
||||
ProjectID: *projectID,
|
||||
SourceDB: sourceDB,
|
||||
TargetDB: targetDB,
|
||||
}
|
||||
|
||||
if *newUID != 0 {
|
||||
config.NewUID = newUID
|
||||
}
|
||||
|
||||
log.Printf("Starting migration for project_id=%d", *projectID)
|
||||
if config.NewUID != nil {
|
||||
log.Printf("Will replace UID with: %d", *config.NewUID)
|
||||
}
|
||||
|
||||
// 执行迁移
|
||||
if err := migrateProject(config); err != nil {
|
||||
log.Fatalf("Migration failed: %v", err)
|
||||
}
|
||||
|
||||
log.Println("Migration completed successfully!")
|
||||
}
|
||||
|
||||
func migrateProject(config *MigrationConfig) error {
|
||||
// 开启事务
|
||||
txSource, err := config.SourceDB.Begin()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to begin source transaction: %w", err)
|
||||
}
|
||||
defer txSource.Rollback()
|
||||
|
||||
txTarget, err := config.TargetDB.Begin()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to begin target transaction: %w", err)
|
||||
}
|
||||
defer txTarget.Rollback()
|
||||
|
||||
// 步骤0: 清除目标库中已存在的该项目数据
|
||||
log.Println("Step 0: Cleaning existing data in target database...")
|
||||
if err := cleanExistingData(txTarget, config); err != nil {
|
||||
return fmt.Errorf("failed to clean existing data: %w", err)
|
||||
}
|
||||
log.Println(" Existing data cleaned")
|
||||
|
||||
// 步骤1: 迁移 m_stream_messages (主表)
|
||||
log.Println("Step 1: Migrating m_stream_messages...")
|
||||
oldToNewStreamMsgID, err := migrateStreamMessages(txSource, txTarget, config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to migrate stream messages: %w", err)
|
||||
}
|
||||
log.Printf(" Migrated %d stream messages", len(oldToNewStreamMsgID))
|
||||
|
||||
// 步骤2: 迁移 m_stream_contents (依赖 main_message_id)
|
||||
log.Println("Step 2: Migrating m_stream_contents...")
|
||||
count, err := migrateStreamContents(txSource, txTarget, config, oldToNewStreamMsgID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to migrate stream contents: %w", err)
|
||||
}
|
||||
log.Printf(" Migrated %d stream contents", count)
|
||||
|
||||
// 步骤3: 迁移 m_context_messages (依赖 main_message_id)
|
||||
log.Println("Step 3: Migrating m_context_messages...")
|
||||
count, err = migrateContextMessages(txSource, txTarget, config, oldToNewStreamMsgID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to migrate context messages: %w", err)
|
||||
}
|
||||
log.Printf(" Migrated %d context messages", count)
|
||||
|
||||
// 步骤4: 迁移 m_task_messages (依赖 main_message_id)
|
||||
log.Println("Step 4: Migrating m_task_messages...")
|
||||
count, err = migrateTaskMessages(txSource, txTarget, config, oldToNewStreamMsgID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to migrate task messages: %w", err)
|
||||
}
|
||||
log.Printf(" Migrated %d task messages", count)
|
||||
|
||||
// 提交事务
|
||||
if err := txTarget.Commit(); err != nil {
|
||||
return fmt.Errorf("failed to commit target transaction: %w", err)
|
||||
}
|
||||
if err := txSource.Commit(); err != nil {
|
||||
return fmt.Errorf("failed to commit source transaction: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// cleanExistingData 清除目标库中已存在的该项目数据
|
||||
// 按照依赖关系逆序删除:先删除依赖表,最后删除主表
|
||||
func cleanExistingData(txTarget *sql.Tx, config *MigrationConfig) error {
|
||||
// 首先获取该项目在目标库中的所有 stream_message IDs
|
||||
var streamMessageIDs []uint64
|
||||
query := `SELECT id FROM m_stream_messages WHERE project_id = ?`
|
||||
rows, err := txTarget.Query(query, config.ProjectID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to query existing stream messages: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var id uint64
|
||||
if err := rows.Scan(&id); err != nil {
|
||||
return err
|
||||
}
|
||||
streamMessageIDs = append(streamMessageIDs, id)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(streamMessageIDs) == 0 {
|
||||
log.Println(" No existing data found for this project in target database")
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Printf(" Found %d existing stream messages to clean", len(streamMessageIDs))
|
||||
|
||||
// 步骤1: 删除 m_task_messages (依赖 main_message_id)
|
||||
result, err := txTarget.Exec(`DELETE FROM m_task_messages WHERE project_id = ?`, config.ProjectID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete task messages: %w", err)
|
||||
}
|
||||
if affected, _ := result.RowsAffected(); affected > 0 {
|
||||
log.Printf(" Deleted %d task messages", affected)
|
||||
}
|
||||
|
||||
// 步骤2: 删除 m_context_messages (依赖 main_message_id)
|
||||
result, err = txTarget.Exec(`DELETE FROM m_context_messages WHERE project_id = ?`, config.ProjectID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete context messages: %w", err)
|
||||
}
|
||||
if affected, _ := result.RowsAffected(); affected > 0 {
|
||||
log.Printf(" Deleted %d context messages", affected)
|
||||
}
|
||||
|
||||
// 步骤3: 删除 m_stream_contents (依赖 main_message_id)
|
||||
// 需要通过 main_message_id IN (...) 来删除
|
||||
if len(streamMessageIDs) > 0 {
|
||||
// 构建 IN 子句
|
||||
query := `DELETE FROM m_stream_contents WHERE main_message_id IN (`
|
||||
args := make([]interface{}, len(streamMessageIDs))
|
||||
for i, id := range streamMessageIDs {
|
||||
if i > 0 {
|
||||
query += ","
|
||||
}
|
||||
query += "?"
|
||||
args[i] = id
|
||||
}
|
||||
query += ")"
|
||||
|
||||
result, err = txTarget.Exec(query, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete stream contents: %w", err)
|
||||
}
|
||||
if affected, _ := result.RowsAffected(); affected > 0 {
|
||||
log.Printf(" Deleted %d stream contents", affected)
|
||||
}
|
||||
}
|
||||
|
||||
// 步骤4: 删除 m_stream_messages (主表)
|
||||
result, err = txTarget.Exec(`DELETE FROM m_stream_messages WHERE project_id = ?`, config.ProjectID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete stream messages: %w", err)
|
||||
}
|
||||
if affected, _ := result.RowsAffected(); affected > 0 {
|
||||
log.Printf(" Deleted %d stream messages", affected)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// formatTimestamp 将时间字符串转换为 MySQL datetime 格式
|
||||
// 输入可能是 "2025-11-07T02:37:23Z" 或已经是 "2025-11-07 02:37:23" 格式
|
||||
func formatTimestamp(ts string) string {
|
||||
// 尝试解析 ISO 8601 格式
|
||||
if t, err := time.Parse(time.RFC3339, ts); err == nil {
|
||||
return t.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
// 尝试解析带纳秒的 ISO 8601 格式
|
||||
if t, err := time.Parse(time.RFC3339Nano, ts); err == nil {
|
||||
return t.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
// 如果已经是正确格式或解析失败,返回原值
|
||||
return ts
|
||||
}
|
||||
|
||||
// migrateStreamMessages 迁移主消息表,返回旧ID到新ID的映射
|
||||
func migrateStreamMessages(txSource, txTarget *sql.Tx, config *MigrationConfig) (map[uint64]uint64, error) {
|
||||
query := `SELECT id, uid, project_id, sender_id, sender_agent_type, type,
|
||||
message_timestamp, agent_gen_message_id, content, formatted_content,
|
||||
task_id, task_status, turn_id, agent_message_id, source, metadata,
|
||||
received_at, created_at, ` + "`show`" + `
|
||||
FROM m_stream_messages WHERE project_id = ?`
|
||||
|
||||
rows, err := txSource.Query(query, config.ProjectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
oldToNewID := make(map[uint64]uint64)
|
||||
insertQuery := `INSERT INTO m_stream_messages
|
||||
(uid, project_id, sender_id, sender_agent_type, type, message_timestamp,
|
||||
agent_gen_message_id, content, formatted_content, task_id, task_status,
|
||||
turn_id, agent_message_id, source, metadata, received_at, created_at, ` + "`show`" + `)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
|
||||
for rows.Next() {
|
||||
var msg StreamMessage
|
||||
err := rows.Scan(&msg.ID, &msg.UID, &msg.ProjectID, &msg.SenderID, &msg.SenderAgentType,
|
||||
&msg.Type, &msg.MessageTimestamp, &msg.AgentGenMessageID, &msg.Content,
|
||||
&msg.FormattedContent, &msg.TaskID, &msg.TaskStatus, &msg.TurnID,
|
||||
&msg.AgentMessageID, &msg.Source, &msg.Metadata, &msg.ReceivedAt,
|
||||
&msg.CreatedAt, &msg.Show)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 如果指定了新UID,替换
|
||||
uid := msg.UID
|
||||
if config.NewUID != nil {
|
||||
uid = *config.NewUID
|
||||
}
|
||||
|
||||
// 转换时间戳格式
|
||||
messageTimestamp := formatTimestamp(msg.MessageTimestamp)
|
||||
receivedAt := formatTimestamp(msg.ReceivedAt)
|
||||
createdAt := formatTimestamp(msg.CreatedAt)
|
||||
|
||||
result, err := txTarget.Exec(insertQuery,
|
||||
uid, msg.ProjectID, msg.SenderID, msg.SenderAgentType, msg.Type,
|
||||
messageTimestamp, msg.AgentGenMessageID, msg.Content,
|
||||
msg.FormattedContent, msg.TaskID, msg.TaskStatus, msg.TurnID,
|
||||
msg.AgentMessageID, msg.Source, msg.Metadata, receivedAt,
|
||||
createdAt, msg.Show)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newID, err := result.LastInsertId()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oldToNewID[msg.ID] = uint64(newID)
|
||||
}
|
||||
|
||||
return oldToNewID, rows.Err()
|
||||
}
|
||||
|
||||
// migrateStreamContents 迁移流式内容表
|
||||
func migrateStreamContents(txSource, txTarget *sql.Tx, config *MigrationConfig, idMap map[uint64]uint64) (int, error) {
|
||||
query := `SELECT id, main_message_id, agent_gen_message_id, type, content,
|
||||
formatted_content, metadata, message_timestamp, ` + "`show`" + `, received_at, created_at
|
||||
FROM m_stream_contents
|
||||
WHERE main_message_id IN (
|
||||
SELECT id FROM m_stream_messages WHERE project_id = ?
|
||||
)`
|
||||
|
||||
rows, err := txSource.Query(query, config.ProjectID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
insertQuery := `INSERT INTO m_stream_contents
|
||||
(main_message_id, agent_gen_message_id, type, content, formatted_content,
|
||||
metadata, message_timestamp, ` + "`show`" + `, received_at, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
|
||||
count := 0
|
||||
for rows.Next() {
|
||||
var (
|
||||
id uint64
|
||||
mainMessageID uint64
|
||||
agentGenMessageID sql.NullString
|
||||
msgType string
|
||||
content string
|
||||
formattedContent string
|
||||
metadata sql.NullString
|
||||
messageTimestamp string
|
||||
show int
|
||||
receivedAt string
|
||||
createdAt string
|
||||
)
|
||||
|
||||
err := rows.Scan(&id, &mainMessageID, &agentGenMessageID, &msgType, &content,
|
||||
&formattedContent, &metadata, &messageTimestamp, &show, &receivedAt, &createdAt)
|
||||
if err != nil {
|
||||
return count, err
|
||||
}
|
||||
|
||||
// 映射新的 main_message_id
|
||||
newMainMessageID, ok := idMap[mainMessageID]
|
||||
if !ok {
|
||||
log.Printf("Warning: main_message_id %d not found in mapping, skipping content id %d", mainMessageID, id)
|
||||
continue
|
||||
}
|
||||
|
||||
// 转换时间戳格式
|
||||
messageTimestamp = formatTimestamp(messageTimestamp)
|
||||
receivedAt = formatTimestamp(receivedAt)
|
||||
createdAt = formatTimestamp(createdAt)
|
||||
|
||||
_, err = txTarget.Exec(insertQuery, newMainMessageID, agentGenMessageID, msgType,
|
||||
content, formattedContent, metadata, messageTimestamp, show, receivedAt, createdAt)
|
||||
if err != nil {
|
||||
return count, err
|
||||
}
|
||||
count++
|
||||
}
|
||||
|
||||
return count, rows.Err()
|
||||
}
|
||||
|
||||
// migrateContextMessages 迁移上下文消息表
|
||||
func migrateContextMessages(txSource, txTarget *sql.Tx, config *MigrationConfig, idMap map[uint64]uint64) (int, error) {
|
||||
query := `SELECT id, main_message_id, ownership, uid, project_id, turn_id,
|
||||
agent_message_id, sender_id, sender_agent_type, type, source, content,
|
||||
formatted_content, metadata, message_timestamp, agent_gen_message_id,
|
||||
` + "`show`" + `, received_at, created_at
|
||||
FROM m_context_messages WHERE project_id = ?`
|
||||
|
||||
rows, err := txSource.Query(query, config.ProjectID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
insertQuery := `INSERT INTO m_context_messages
|
||||
(main_message_id, ownership, uid, project_id, turn_id, agent_message_id,
|
||||
sender_id, sender_agent_type, type, source, content, formatted_content,
|
||||
metadata, message_timestamp, agent_gen_message_id, ` + "`show`" + `, received_at, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
|
||||
count := 0
|
||||
for rows.Next() {
|
||||
var (
|
||||
id uint64
|
||||
mainMessageID uint64
|
||||
ownership string
|
||||
uid uint64
|
||||
projectID uint64
|
||||
turnID sql.NullInt32
|
||||
agentMessageID sql.NullString
|
||||
senderID sql.NullString
|
||||
senderAgentType sql.NullString
|
||||
msgType string
|
||||
source string
|
||||
content sql.NullString
|
||||
formattedContent sql.NullString
|
||||
metadata sql.NullString
|
||||
messageTimestamp string
|
||||
agentGenMessageID sql.NullString
|
||||
show int
|
||||
receivedAt string
|
||||
createdAt string
|
||||
)
|
||||
|
||||
err := rows.Scan(&id, &mainMessageID, &ownership, &uid, &projectID, &turnID,
|
||||
&agentMessageID, &senderID, &senderAgentType, &msgType, &source, &content,
|
||||
&formattedContent, &metadata, &messageTimestamp, &agentGenMessageID,
|
||||
&show, &receivedAt, &createdAt)
|
||||
if err != nil {
|
||||
return count, err
|
||||
}
|
||||
|
||||
// 映射新的 main_message_id
|
||||
newMainMessageID, ok := idMap[mainMessageID]
|
||||
if !ok {
|
||||
log.Printf("Warning: main_message_id %d not found in mapping, skipping context message id %d", mainMessageID, id)
|
||||
continue
|
||||
}
|
||||
|
||||
// 如果指定了新UID,替换
|
||||
targetUID := uid
|
||||
if config.NewUID != nil {
|
||||
targetUID = *config.NewUID
|
||||
}
|
||||
|
||||
// 转换时间戳格式
|
||||
messageTimestamp = formatTimestamp(messageTimestamp)
|
||||
receivedAt = formatTimestamp(receivedAt)
|
||||
createdAt = formatTimestamp(createdAt)
|
||||
|
||||
_, err = txTarget.Exec(insertQuery, newMainMessageID, ownership, targetUID, projectID,
|
||||
turnID, agentMessageID, senderID, senderAgentType, msgType, source, content,
|
||||
formattedContent, metadata, messageTimestamp, agentGenMessageID, show,
|
||||
receivedAt, createdAt)
|
||||
if err != nil {
|
||||
return count, err
|
||||
}
|
||||
count++
|
||||
}
|
||||
|
||||
return count, rows.Err()
|
||||
}
|
||||
|
||||
// migrateTaskMessages 迁移任务消息表
|
||||
func migrateTaskMessages(txSource, txTarget *sql.Tx, config *MigrationConfig, idMap map[uint64]uint64) (int, error) {
|
||||
query := `SELECT id, main_message_id, uid, project_id, sender_id, sender_agent_type,
|
||||
type, message_timestamp, agent_gen_message_id, content, formatted_content,
|
||||
task_status, turn_id, agent_message_id, source, metadata, ` + "`show`" + `,
|
||||
received_at, created_at
|
||||
FROM m_task_messages WHERE project_id = ?`
|
||||
|
||||
rows, err := txSource.Query(query, config.ProjectID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
insertQuery := `INSERT INTO m_task_messages
|
||||
(main_message_id, uid, project_id, sender_id, sender_agent_type, type,
|
||||
message_timestamp, agent_gen_message_id, content, formatted_content,
|
||||
task_status, turn_id, agent_message_id, source, metadata, ` + "`show`" + `,
|
||||
received_at, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
|
||||
count := 0
|
||||
for rows.Next() {
|
||||
var (
|
||||
id uint64
|
||||
mainMessageID uint64
|
||||
uid uint64
|
||||
projectID uint64
|
||||
senderID sql.NullString
|
||||
senderAgentType sql.NullString
|
||||
msgType string
|
||||
messageTimestamp string
|
||||
agentGenMessageID sql.NullString
|
||||
content string
|
||||
formattedContent string
|
||||
taskStatus sql.NullString
|
||||
turnID sql.NullInt32
|
||||
agentMessageID sql.NullString
|
||||
source sql.NullString
|
||||
metadata sql.NullString
|
||||
show int
|
||||
receivedAt string
|
||||
createdAt string
|
||||
)
|
||||
|
||||
err := rows.Scan(&id, &mainMessageID, &uid, &projectID, &senderID, &senderAgentType,
|
||||
&msgType, &messageTimestamp, &agentGenMessageID, &content, &formattedContent,
|
||||
&taskStatus, &turnID, &agentMessageID, &source, &metadata, &show,
|
||||
&receivedAt, &createdAt)
|
||||
if err != nil {
|
||||
return count, err
|
||||
}
|
||||
|
||||
// 映射新的 main_message_id
|
||||
newMainMessageID, ok := idMap[mainMessageID]
|
||||
if !ok {
|
||||
log.Printf("Warning: main_message_id %d not found in mapping, skipping task message id %d", mainMessageID, id)
|
||||
continue
|
||||
}
|
||||
|
||||
// 如果指定了新UID,替换
|
||||
targetUID := uid
|
||||
if config.NewUID != nil {
|
||||
targetUID = *config.NewUID
|
||||
}
|
||||
|
||||
// 转换时间戳格式
|
||||
messageTimestamp = formatTimestamp(messageTimestamp)
|
||||
receivedAt = formatTimestamp(receivedAt)
|
||||
createdAt = formatTimestamp(createdAt)
|
||||
|
||||
_, err = txTarget.Exec(insertQuery, newMainMessageID, targetUID, projectID, senderID,
|
||||
senderAgentType, msgType, messageTimestamp, agentGenMessageID, content,
|
||||
formattedContent, taskStatus, turnID, agentMessageID, source, metadata,
|
||||
show, receivedAt, createdAt)
|
||||
if err != nil {
|
||||
return count, err
|
||||
}
|
||||
count++
|
||||
}
|
||||
|
||||
return count, rows.Err()
|
||||
}
|
||||
BIN
cmd/message-migrator/message-migrator
Executable file
BIN
cmd/message-migrator/message-migrator
Executable file
Binary file not shown.
124
cmd/redis-pub-sub/main.go
Normal file
124
cmd/redis-pub-sub/main.go
Normal file
@@ -0,0 +1,124 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
// 定义 Redis 配置和频道名称
|
||||
const redisAddr = "localhost:6379" // 替换成您的 Redis 地址
|
||||
const channelName = "stream:10"
|
||||
|
||||
// 全局 Redis 客户端
|
||||
var rdb *redis.Client
|
||||
|
||||
// 定义命令行参数
|
||||
var mode = flag.String("mode", "", "运行模式:必须是 'pub' (发布者) 或 'sub' (订阅者)")
|
||||
|
||||
// 初始化 Redis 客户端并检查连接
|
||||
func initRedis() {
|
||||
rdb = redis.NewClient(&redis.Options{
|
||||
Addr: redisAddr,
|
||||
Password: "", // 您的密码(如果没有则为空)
|
||||
DB: 7, // 默认 DB
|
||||
})
|
||||
|
||||
ctx := context.Background()
|
||||
_, err := rdb.Ping(ctx).Result()
|
||||
if err != nil {
|
||||
log.Fatalf("无法连接到 Redis (%s): %v", redisAddr, err)
|
||||
}
|
||||
fmt.Println("成功连接到 Redis。")
|
||||
}
|
||||
|
||||
// 订阅者逻辑
|
||||
func runSubscriber() {
|
||||
fmt.Println("--- 启动订阅者 (Subscriber) 模式 ---")
|
||||
|
||||
// 订阅频道
|
||||
// Subscribes to the given channels.
|
||||
pubsub := rdb.Subscribe(context.Background(), channelName)
|
||||
defer pubsub.Close() // 确保在函数退出时关闭连接
|
||||
|
||||
// 接收并处理消息
|
||||
fmt.Printf("已订阅频道: %s。等待消息...\n", channelName)
|
||||
|
||||
// 使用 Channel() 方法获取一个 Go Channel 来接收消息
|
||||
ch := pubsub.Channel()
|
||||
|
||||
// 循环接收消息
|
||||
for msg := range ch {
|
||||
fmt.Printf("\n--- 收到消息 ---\n")
|
||||
fmt.Printf("频道 (Channel): %s\n", msg.Channel)
|
||||
fmt.Printf("消息 (Payload): %s\n", msg.Payload)
|
||||
fmt.Printf("----------------\n")
|
||||
|
||||
// 添加退出逻辑
|
||||
if msg.Payload == "exit" {
|
||||
fmt.Println("\n收到 'exit' 消息,退出订阅循环。")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("订阅者程序退出。")
|
||||
}
|
||||
|
||||
// 发布者逻辑
|
||||
func runPublisher() {
|
||||
fmt.Println("--- 启动发布者 (Publisher) 模式 ---")
|
||||
|
||||
messages := []string{
|
||||
"Hello Redis Pub/Sub!",
|
||||
"This is message two from publisher.",
|
||||
"A third message is here.",
|
||||
"exit", // 发送退出信号给订阅者
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// 循环发布消息
|
||||
for i, msg := range messages {
|
||||
// Publish publishes message to channel.
|
||||
// Result() 返回值是接收到消息的订阅者数量 (int64)
|
||||
result, err := rdb.Publish(ctx, channelName, msg).Result()
|
||||
if err != nil {
|
||||
log.Fatalf("发布消息失败: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("发布消息 %d: '%s' 到频道 '%s',有 %d 个订阅者接收。\n",
|
||||
i+1, msg, channelName, result)
|
||||
|
||||
// 每次发送后等待一小段时间
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
|
||||
fmt.Println("发布者程序完成。")
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 解析命令行参数
|
||||
flag.Parse()
|
||||
|
||||
// 检查模式参数
|
||||
if *mode != "pub" && *mode != "sub" {
|
||||
fmt.Println("错误:请指定有效的运行模式。")
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 初始化 Redis
|
||||
initRedis()
|
||||
|
||||
// 根据模式执行相应逻辑
|
||||
if *mode == "sub" {
|
||||
runSubscriber()
|
||||
} else if *mode == "pub" {
|
||||
runPublisher()
|
||||
}
|
||||
}
|
||||
49
cmd/xb/main.go
Normal file
49
cmd/xb/main.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TzStrToOffset(ianaZone string) (string, error) {
|
||||
loc, err := time.LoadLocation(ianaZone)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("无法加载时区 %s: %v", ianaZone, err)
|
||||
}
|
||||
|
||||
t := time.Date(2025, time.October, 28, 0, 0, 0, 0, loc)
|
||||
|
||||
_, offsetSeconds := t.Zone()
|
||||
|
||||
offset := time.Duration(offsetSeconds) * time.Second
|
||||
|
||||
// 格式化偏移量。time.Time.Format() 无法直接将 Location 格式化成 UTC+HH:MM,
|
||||
// 因此我们需要手动计算并格式化。
|
||||
sign := "+"
|
||||
if offsetSeconds < 0 {
|
||||
sign = "-"
|
||||
offset = -offset // 确保偏移量为正值进行计算
|
||||
}
|
||||
|
||||
hours := int(offset.Hours())
|
||||
minutes := int(offset.Minutes()) % 60
|
||||
|
||||
// 最终的格式化字符串
|
||||
utcOffsetString := fmt.Sprintf("%s%02d%02d", sign, hours, minutes)
|
||||
|
||||
return utcOffsetString, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
ianaZone := "Asia/Shanghai"
|
||||
ianaZone = "UTC"
|
||||
|
||||
utcOffsetString, err := TzStrToOffset(ianaZone)
|
||||
if err != nil {
|
||||
log.Fatalf("错误: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("IANA 时区: %s\n", ianaZone)
|
||||
fmt.Printf("UTC 偏移量: %s\n", utcOffsetString)
|
||||
}
|
||||
795
copy.go.bak
Normal file
795
copy.go.bak
Normal file
@@ -0,0 +1,795 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
func main() {
|
||||
dsn := "root:123456@tcp(localhost:3306)/copy_play?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
|
||||
// 使用 sql.Open() 打开数据库连接
|
||||
db, err := sql.Open("mysql", dsn)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open database: %v", err)
|
||||
}
|
||||
defer db.Close() // 养成好习惯,确保连接在函数结束时关闭
|
||||
|
||||
// 验证数据库连接是否有效
|
||||
if err := db.Ping(); err != nil {
|
||||
log.Fatalf("failed to connect to database: %v", err)
|
||||
}
|
||||
fmt.Println("Successfully connected to the database!")
|
||||
|
||||
err = copy(db, context.Background(), 10900, "_")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to copy data")
|
||||
}
|
||||
}
|
||||
|
||||
type Project struct {
|
||||
ID uint
|
||||
UserID uint
|
||||
Name string
|
||||
Env string
|
||||
Status string
|
||||
State []byte
|
||||
}
|
||||
|
||||
// `id` int NOT NULL AUTO_INCREMENT,
|
||||
//
|
||||
// `experience_title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '经验体主题',
|
||||
// `version` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '当前版本号',
|
||||
// `session_id` bigint NOT NULL COMMENT '所属会话的唯一ID',
|
||||
// `created_at` datetime NOT NULL COMMENT '创建时间',
|
||||
// `updated_at` datetime NOT NULL COMMENT '更新时间',
|
||||
// `deleted_at` datetime DEFAULT NULL COMMENT '删除时间(未删为null)',
|
||||
// `publish_version` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '构建版本',
|
||||
// `status` int DEFAULT NULL COMMENT '经验体状态 0:下线 1:已上线 2:构建中',
|
||||
// `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '经验体描述',
|
||||
type Experience struct {
|
||||
ID uint
|
||||
ExperienceTitle string
|
||||
Version *string
|
||||
PublishVersion *string
|
||||
ExpStatus sql.NullInt64
|
||||
Description *string
|
||||
}
|
||||
|
||||
// `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '消息ID,主键',
|
||||
// `user_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户ID',
|
||||
// `project_id` int NOT NULL COMMENT '项目ID',
|
||||
// `chat_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '聊天会话ID',
|
||||
// `content` text COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '消息内容',
|
||||
// `tree_type` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'message' COMMENT '树类型:message、taskpoint',
|
||||
// `source` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '消息来源',
|
||||
// `type` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '消息类型',
|
||||
// `task_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '任务id',
|
||||
// `parent_task_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '父任务ID',
|
||||
// `task_status` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '任务点状态,tree_type为message时为空,taskpoint情况下为runing或finished,状态变更不会更新该字段只会添加消息',
|
||||
// `event_type` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'mq消息event_type字段的记录',
|
||||
// `metadata` json DEFAULT NULL COMMENT '消息元数据',
|
||||
// `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
// `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
type Message struct {
|
||||
ID uint
|
||||
MsgUserID string
|
||||
ChatID string
|
||||
Content string
|
||||
TreeType string
|
||||
Source string
|
||||
MsgType string
|
||||
TaskID *string
|
||||
ParentTaskID *string
|
||||
TaskStatus *string
|
||||
EventType *string
|
||||
Metadata *string
|
||||
}
|
||||
|
||||
// `id` int NOT NULL AUTO_INCREMENT,
|
||||
// `system_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '系统名称',
|
||||
// `system_desc` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '系统描述',
|
||||
// `created_at` datetime NOT NULL COMMENT '创建时间',
|
||||
// `updated_at` datetime NOT NULL COMMENT '更新时间',
|
||||
// `system_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '系统域名',
|
||||
// `experience_id` int DEFAULT NULL COMMENT '经验体id',
|
||||
// `unique_system_id` varchar(255) DEFAULT NULL COMMENT '所属的全局唯一系统id',
|
||||
// `system_pages_desc` longtext COMMENT '系统下所有页面描述',
|
||||
// `system_summary` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '系统简介',
|
||||
// `matched_labels` json DEFAULT NULL COMMENT '系统关联的标签',
|
||||
// `memo_process_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否处理备忘录,0=未处理,1=已处理',
|
||||
type System struct {
|
||||
ID uint
|
||||
SystemName string
|
||||
SystemDesc *string
|
||||
SystemURL string
|
||||
ExperienceID *uint
|
||||
UniqueSystemID *string
|
||||
SystemPagesDesc *string
|
||||
SystemSummary *string
|
||||
MatchedLabels []byte
|
||||
MemoProcessStatus int
|
||||
}
|
||||
|
||||
// `id` int NOT NULL AUTO_INCREMENT,
|
||||
// `relation_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
// `user_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
// `taskpoint_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
// `experience_id` int NOT NULL COMMENT '所属经验体的唯一ID',
|
||||
// `status` tinyint DEFAULT NULL COMMENT '0:关闭,1:开启',
|
||||
// `version` int DEFAULT NULL,
|
||||
// `created_at` datetime NOT NULL COMMENT '创建时间',
|
||||
// `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
// `last_heartbeat_time` datetime DEFAULT NULL COMMENT '最后一次心跳',
|
||||
// `clean_status` int NOT NULL DEFAULT '0' COMMENT '0为清洗完毕,1为需要判断清洗,2为判断中,3为需要清洗',
|
||||
// `dig_status` int NOT NULL DEFAULT '0' COMMENT '0=准备挖掘,1=挖掘中',
|
||||
//
|
||||
// 根据经验体ID来查询所有的关联插件
|
||||
// TODO 应该使用新的taskpoint_id
|
||||
type RelationPlugin struct {
|
||||
UserID string
|
||||
TaskpointID string
|
||||
RelationID string
|
||||
Status sql.NullInt64
|
||||
Version sql.NullInt64
|
||||
LastHeartbeatTime *time.Time
|
||||
CleanStatus int
|
||||
DigStatus int
|
||||
}
|
||||
|
||||
// `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
//
|
||||
// `video_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '视频ID(与l_video_events表一致)',
|
||||
// `relation_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '关联经验体ID(支持UUID)',
|
||||
// `video_path` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '视频文件路径',
|
||||
// `start_time` bigint DEFAULT NULL COMMENT '视频开始毫秒时间戳',
|
||||
// `end_time` bigint DEFAULT NULL COMMENT '视频结束毫秒时间戳',
|
||||
// `upload_time` datetime DEFAULT NULL COMMENT '上传时间',
|
||||
// `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间',
|
||||
// `action_sequence` json DEFAULT NULL COMMENT '动作序列',
|
||||
// `system_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '系统名称',
|
||||
type Video struct {
|
||||
VideoID string
|
||||
RelationID string
|
||||
VideoPath string
|
||||
StartTime int64
|
||||
EndTime int64
|
||||
UploadTime time.Time
|
||||
// 这是user action表的id集合
|
||||
ActionSeq []byte
|
||||
SystemName string
|
||||
}
|
||||
|
||||
// `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||
//
|
||||
// `parse_result` json NOT NULL COMMENT '解析结果(JSON格式)',
|
||||
// `relation_id` varchar(64) NOT NULL COMMENT '采集订单ID(字符串)',
|
||||
// `session_id` bigint NOT NULL COMMENT '会话ID',
|
||||
// `clean_plan_id` int DEFAULT NULL COMMENT '关联的清洗计划ID',
|
||||
// `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
// `status` tinyint NOT NULL DEFAULT '0' COMMENT '解析任务状态:0=待处理,1=处理中,2=已完成,3=处理失败',
|
||||
type MonitoringLogParseResult struct {
|
||||
ParseResult []byte
|
||||
RelationID string
|
||||
SessionID uint
|
||||
CleanPlanID *uint
|
||||
Status int
|
||||
}
|
||||
|
||||
// `id` int NOT NULL AUTO_INCREMENT,
|
||||
//
|
||||
// `extracted_subjective_knowledge_desc` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '主观知识描述',
|
||||
// `session_id` bigint NOT NULL COMMENT '会话ID',
|
||||
// `dialog_ids` json DEFAULT NULL COMMENT '关联的对话ID列表',
|
||||
// `experience_id` int NOT NULL COMMENT '所属经验体的唯一ID',
|
||||
// `version` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '所属经验体的版本号',
|
||||
// `created_at` datetime NOT NULL COMMENT '创建时间',
|
||||
// `updated_at` datetime NOT NULL COMMENT '更新时间',
|
||||
// `status` int DEFAULT NULL COMMENT '0:通过挖掘产生但未实践 1:通过实践 2:实践未通过',
|
||||
// `taskpoint_id` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '任务点id',
|
||||
// `relation_id` varchar(200) DEFAULT NULL,
|
||||
// `system_ids` json DEFAULT NULL COMMENT '系统ID列表',
|
||||
// `page_ids` json DEFAULT NULL COMMENT '页面ID列表',
|
||||
// `category_tags` varchar(255) DEFAULT NULL COMMENT '分类标签',
|
||||
// `is_global_associated` int DEFAULT NULL COMMENT '是否全局关联 (0:否, 1:是)',
|
||||
type SubjectKnowledge struct {
|
||||
ExtractedSubjectiveKnowledgeDesc *string
|
||||
SessionID uint
|
||||
DialogIDs []byte
|
||||
ExperienceID uint
|
||||
Version *string
|
||||
Status *int
|
||||
TaskpointID *string
|
||||
RelationID *string
|
||||
SystemIDs []byte
|
||||
PageIDs []byte
|
||||
CategoryTags *string
|
||||
IsGlobalAssociated *int
|
||||
}
|
||||
|
||||
// `id` int NOT NULL AUTO_INCREMENT COMMENT '采集的操作信息唯一ID',
|
||||
//
|
||||
// `relation_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '插件&系统通讯关系唯一ID',
|
||||
// `created_at` datetime(3) NOT NULL COMMENT '创建时间(操作上报的时间)',
|
||||
// `updated_at` datetime(3) NOT NULL COMMENT '更新时间',
|
||||
// `system_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '操作所在的系统名称',
|
||||
// `page_url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '操作所在页面的 URL',
|
||||
// `element_text` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '被操作元素的文本',
|
||||
// `event_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户执行的操作类型(如 click、input)',
|
||||
// `page_html_path` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '页面 HTML 存储路径(OSS 路径)',
|
||||
// `screenshot_path` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '页面截图存储路径(OSS 路径)',
|
||||
// `element_tag` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '操作的元素标签(如 input、button等)',
|
||||
// `status` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '0' COMMENT '是否参与客观知识生成(0=否,1=是)',
|
||||
// `extra_data` json DEFAULT NULL COMMENT '用户行为数据集合',
|
||||
// `user_id` int DEFAULT NULL,
|
||||
// `experience_id` int DEFAULT NULL COMMENT '经验体id',
|
||||
// `page_id` int DEFAULT NULL COMMENT '所属页面',
|
||||
// `system_id` int DEFAULT NULL COMMENT '所属系统',
|
||||
// `log_dig_status` int NOT NULL DEFAULT '0' COMMENT '0=待挖掘,1=挖掘中,2=已挖掘',
|
||||
// `clean_page_desc` int NOT NULL DEFAULT '0' COMMENT '0=未清洗,1=已清洗',
|
||||
// `clean_system_desc` int NOT NULL DEFAULT '0' COMMENT '0=未清洗,1=已清洗',
|
||||
// `clean_html_diff` int NOT NULL DEFAULT '0' COMMENT '0=未清洗,1=已清洗',
|
||||
// `clean_elements_json` int NOT NULL DEFAULT '0' COMMENT '0=未清洗,1=已清洗',
|
||||
// `clean_page_inputs` int NOT NULL DEFAULT '0' COMMENT '0=未清洗,1=已清洗',
|
||||
// `clean_page_stats` int NOT NULL DEFAULT '0' COMMENT '0=未清洗,1=已清洗',
|
||||
// `processing_delay` int DEFAULT NULL,
|
||||
type UserAction struct {
|
||||
ID uint
|
||||
RelationID string
|
||||
SystemName string
|
||||
PageUrl string
|
||||
ElementText *string
|
||||
EventType string
|
||||
PageHtmlPath *string
|
||||
ScreenshotPath *string
|
||||
ElementTag *string
|
||||
Status string
|
||||
ExtraData []byte
|
||||
UserID uint
|
||||
ExperienceID uint
|
||||
PageID uint
|
||||
SystemID uint
|
||||
LogDigStatus int
|
||||
CleanPageDesc int
|
||||
CleanSystemDesc int
|
||||
CleanHtmlDiff int
|
||||
CleanElementsJson int
|
||||
CleanPageInputs int
|
||||
CleanPageStats int
|
||||
ProcessingDelay *int
|
||||
}
|
||||
|
||||
// `id` int NOT NULL AUTO_INCREMENT,
|
||||
//
|
||||
// `page_url` json NOT NULL DEFAULT (json_array()) COMMENT '页面URL(JSON 数组)',
|
||||
// `page_desc` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '页面说明',
|
||||
// `elements_json` json DEFAULT NULL COMMENT '页面元素结构',
|
||||
// `statistics` json DEFAULT NULL COMMENT '页面统计结果&条件关系',
|
||||
// `system_id` int NOT NULL COMMENT '所属系统的唯一ID',
|
||||
// `system_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '所属系统名称',
|
||||
// `created_at` datetime NOT NULL COMMENT '创建时间',
|
||||
// `updated_at` datetime NOT NULL COMMENT '更新时间',
|
||||
// `input_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
|
||||
// `page_summary` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '页面简介',
|
||||
// `clickable` json NOT NULL DEFAULT (json_array()) COMMENT '可点击元素列表,元素格式:<tag>_<text>,JSON 数组存储',
|
||||
// `experience_id` int DEFAULT NULL COMMENT '经验体id',
|
||||
// `page_type` json DEFAULT NULL COMMENT '页面类型与分析结果',
|
||||
// `unique_page_id` varchar(255) DEFAULT NULL COMMENT '所属的全局唯一页面id',
|
||||
// `unique_system_id` varchar(255) DEFAULT NULL COMMENT '所属的全局唯一系统id',
|
||||
// `memo_process_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否处理备忘录,0=未处理,1=已处理',
|
||||
type Page struct {
|
||||
ID uint
|
||||
PageUrl []byte
|
||||
PageDesc string
|
||||
ElementsJson []byte
|
||||
Statistics []byte
|
||||
SystemID uint
|
||||
SystemName string
|
||||
InputJson *string
|
||||
PageSummary *string
|
||||
Clickable []byte
|
||||
PageType []byte
|
||||
UniquePageID *string
|
||||
UniqueSystemID *string
|
||||
MemoProcessStatus int
|
||||
}
|
||||
|
||||
func copy(db *sql.DB, ctx context.Context, projectID uint, _taskPointID string) error {
|
||||
tx, err := db.Begin()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to begin transaction: %v", err)
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
var project Project
|
||||
query := "select id, user_id,name,env,status,state from l_projects lp where lp.id = ?"
|
||||
row := tx.QueryRowContext(ctx, query, projectID)
|
||||
if err := row.Scan(&project.ID, &project.UserID, &project.Name, &project.Env, &project.Status, &project.State); err != nil {
|
||||
log.Fatalf("failed to scan row: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
oldProjectID := project.ID
|
||||
|
||||
// 向project表插入这条查询出来的数据,然后记录返回的ID
|
||||
xsql := "INSERT INTO l_projects (user_id, name, env, status, state, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)"
|
||||
result, err := tx.ExecContext(ctx, xsql, project.UserID, project.Name, project.Env, project.Status, project.State, time.Now(), time.Now())
|
||||
if err != nil {
|
||||
log.Fatalf("failed to insert data: %v", err)
|
||||
return err
|
||||
}
|
||||
newProjectID, err := result.LastInsertId()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get last insert id: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
println("新项目ID:", newProjectID)
|
||||
|
||||
var experience Experience
|
||||
query = "select id, experience_title, version, publish_version, status, description from l_experiences le where le.session_id = ?"
|
||||
row = tx.QueryRowContext(ctx, query, oldProjectID)
|
||||
|
||||
if err := row.Scan(&experience.ID, &experience.ExperienceTitle, &experience.Version, &experience.PublishVersion, &experience.ExpStatus, &experience.Description); err != nil {
|
||||
log.Fatalf("failed to scan row: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
oldExperienceID := experience.ID
|
||||
|
||||
// 插入一条新的经验体
|
||||
xsql = "INSERT INTO l_experiences (experience_title, version, session_id, created_at, updated_at, publish_version, status, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
result, err = tx.ExecContext(ctx, xsql, experience.ExperienceTitle, experience.Version, newProjectID, time.Now(), time.Now(), experience.PublishVersion, experience.ExpStatus, experience.Description)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to insert data into l_experiences: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 获取新的ID
|
||||
newExperienceID, err := result.LastInsertId()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get last insert id for l_experiences: %v", err)
|
||||
}
|
||||
|
||||
println("新经验ID:", newExperienceID)
|
||||
|
||||
// 查询一个项目ID下面的所有消息
|
||||
// TODO 这里chat——id需要使用更新后的,而不是查询得到的
|
||||
// TODO task_id parent_task_id 也需要更新
|
||||
query = "select id, user_id, chat_id, content, tree_type, source, type, task_id, parent_task_id, task_status, event_type, metadata from l_message lm where lm.project_id = ?"
|
||||
rows, err := tx.QueryContext(ctx, query, oldProjectID)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to query l_message: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
messages := make([]Message, 0)
|
||||
for rows.Next() {
|
||||
var message Message
|
||||
if err := rows.Scan(&message.ID, &message.MsgUserID, &message.ChatID, &message.Content, &message.TreeType, &message.Source, &message.MsgType, &message.TaskID, &message.ParentTaskID, &message.TaskStatus, &message.EventType, &message.Metadata); err != nil {
|
||||
log.Fatalf("failed to scan row from l_message: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
messages = append(messages, message)
|
||||
}
|
||||
rows.Close()
|
||||
|
||||
msgIDRel := make(map[uint]uint)
|
||||
|
||||
// 单独处理消息插入,需要记录新旧ID的关系
|
||||
for _, msg := range messages {
|
||||
xsql = "INSERT INTO l_message (user_id, project_id, chat_id, content, tree_type, source, type, task_id, parent_task_id, task_status, event_type, metadata, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
result, err = tx.ExecContext(ctx, xsql, msg.MsgUserID, newProjectID, msg.ChatID, msg.Content, msg.TreeType, msg.Source, msg.MsgType, msg.TaskID, msg.ParentTaskID, msg.TaskStatus, msg.EventType, msg.Metadata, time.Now(), time.Now())
|
||||
if err != nil {
|
||||
log.Fatalf("failed to insert data into l_message: %v", err)
|
||||
return err
|
||||
}
|
||||
newMsgID, err := result.LastInsertId()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get last insert id for l_message: %v", err)
|
||||
return err
|
||||
}
|
||||
msgIDRel[msg.ID] = uint(newMsgID)
|
||||
}
|
||||
|
||||
for oldID, newID := range msgIDRel {
|
||||
println("旧消息ID:", oldID, "新消息ID:", newID)
|
||||
}
|
||||
|
||||
// 查询经验体ID下的系统
|
||||
query = "select id, system_name, system_desc, system_url, unique_system_id, system_pages_desc, system_summary, matched_labels, memo_process_status from l_systems ls where ls.experience_id = ?"
|
||||
rows, err = tx.QueryContext(ctx, query, oldExperienceID)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to query l_systems: %v", err)
|
||||
return err
|
||||
}
|
||||
systems := make([]System, 0)
|
||||
for rows.Next() {
|
||||
var system System
|
||||
if err := rows.Scan(&system.ID, &system.SystemName, &system.SystemDesc, &system.SystemURL, &system.UniqueSystemID, &system.SystemPagesDesc, &system.SystemSummary, &system.MatchedLabels, &system.MemoProcessStatus); err != nil {
|
||||
log.Fatalf("failed to scan row from l_systems: %v", err)
|
||||
return err
|
||||
}
|
||||
systems = append(systems, system)
|
||||
}
|
||||
rows.Close()
|
||||
|
||||
sysRel := make(map[uint]uint)
|
||||
for _, sys := range systems {
|
||||
xsql = "INSERT INTO l_systems (system_name, system_desc, system_url, experience_id, unique_system_id, system_pages_desc, system_summary, matched_labels, memo_process_status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
result, err = tx.ExecContext(ctx, xsql, sys.SystemName, sys.SystemDesc, sys.SystemURL, newExperienceID, sys.UniqueSystemID, sys.SystemPagesDesc, sys.SystemSummary, sys.MatchedLabels, sys.MemoProcessStatus, time.Now(), time.Now())
|
||||
if err != nil {
|
||||
log.Fatalf("failed to insert data into l_systems: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
newSysID, err := result.LastInsertId()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get last insert id for l_systems: %v", err)
|
||||
return err
|
||||
}
|
||||
sysRel[sys.ID] = uint(newSysID)
|
||||
}
|
||||
|
||||
for oldID, newID := range sysRel {
|
||||
println("旧系统ID:", oldID, "新系统ID:", newID)
|
||||
}
|
||||
|
||||
query = "select relation_id, user_id, taskpoint_id, status, version, last_heartbeat_time, clean_status, dig_status from l_plugin_relation where experience_id = ?"
|
||||
rows, err = tx.QueryContext(ctx, query, oldExperienceID)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to query l_plugin_relation: %v", err)
|
||||
return err
|
||||
}
|
||||
relations := make([]RelationPlugin, 0)
|
||||
for rows.Next() {
|
||||
var relation RelationPlugin
|
||||
if err := rows.Scan(&relation.RelationID, &relation.UserID, &relation.TaskpointID, &relation.Status, &relation.Version, &relation.LastHeartbeatTime, &relation.CleanStatus, &relation.DigStatus); err != nil {
|
||||
log.Fatalf("failed to scan row from l_plugin_relation: %v", err)
|
||||
return err
|
||||
}
|
||||
relations = append(relations, relation)
|
||||
}
|
||||
rows.Close()
|
||||
|
||||
newRelIDs := make([]string, 0)
|
||||
relRelIDs := make(map[string]string)
|
||||
for _, rel := range relations {
|
||||
oldRelID := rel.RelationID
|
||||
newRelID := rel.RelationID + "-" + strconv.FormatUint(uint64(newProjectID), 10)
|
||||
xsql := "INSERT INTO l_plugin_relation (relation_id, user_id, taskpoint_id, status, version, last_heartbeat_time, experience_id, clean_status, dig_status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
_, err = tx.ExecContext(ctx, xsql, newRelID, rel.UserID, rel.TaskpointID, rel.Status, rel.Version, rel.LastHeartbeatTime, newExperienceID, rel.CleanStatus, rel.DigStatus, time.Now(), time.Now())
|
||||
if err != nil {
|
||||
log.Fatalf("failed to insert data into l_plugin_relation: %v", err)
|
||||
return err
|
||||
}
|
||||
println("旧关联ID:", oldRelID, "新关联ID:", newRelID)
|
||||
newRelIDs = append(newRelIDs, newRelID)
|
||||
relRelIDs[oldRelID] = newRelID
|
||||
// 通过关联ID来获取video的内容
|
||||
query = "select video_id, video_path, start_time, end_time, upload_time, action_sequence, system_name from l_videos where relation_id = ?"
|
||||
rows, err = tx.QueryContext(ctx, query, oldRelID)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to query l_video: %v", err)
|
||||
return err
|
||||
}
|
||||
videos := make([]Video, 0)
|
||||
for rows.Next() {
|
||||
var video Video
|
||||
if err := rows.Scan(&video.VideoID, &video.VideoPath, &video.StartTime, &video.EndTime, &video.UploadTime, &video.ActionSeq, &video.SystemName); err != nil {
|
||||
log.Fatalf("failed to scan row from l_video: %v", err)
|
||||
return err
|
||||
}
|
||||
videos = append(videos, video)
|
||||
}
|
||||
rows.Close()
|
||||
|
||||
// video可以支持批量插入
|
||||
valueStrings := make([]string, 0, len(videos))
|
||||
valueArgs := make([]any, 0, len(videos)*9) // 每个项目有9个字段
|
||||
|
||||
for _, video := range videos {
|
||||
oldVideoID := video.VideoID
|
||||
newVideoID := oldVideoID + "-" + strconv.FormatUint(uint64(newProjectID), 10)
|
||||
valueStrings = append(valueStrings, "(?, ?, ?, ?, ?, ?, ?, ?, ?)")
|
||||
valueArgs = append(valueArgs, newVideoID, newRelID, video.VideoPath, video.StartTime, video.EndTime, video.UploadTime, video.ActionSeq, video.SystemName, time.Now())
|
||||
}
|
||||
|
||||
xsql = fmt.Sprintf("INSERT INTO l_videos (video_id, relation_id, video_path, start_time, end_time, upload_time, action_sequence, system_name, created_at) VALUES %s", strings.Join(valueStrings, ","))
|
||||
result, err = tx.ExecContext(ctx, xsql, valueArgs...)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to insert data into l_videos: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
x, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get rows affected for l_video: %v", err)
|
||||
return err
|
||||
}
|
||||
println("插入视频:", x)
|
||||
|
||||
// 根据旧的relation_ID获取monitor_parse_result的内容
|
||||
query = "select parse_result, session_id, clean_plan_id, status from l_monitoring_log_parse_result where relation_id = ?"
|
||||
rows, err = tx.QueryContext(ctx, query, oldRelID)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to query l_monitoring_log_parse_result: %v", err)
|
||||
return err
|
||||
}
|
||||
parses := make([]MonitoringLogParseResult, 0)
|
||||
for rows.Next() {
|
||||
var parse MonitoringLogParseResult
|
||||
if err := rows.Scan(&parse.ParseResult, &parse.SessionID, &parse.CleanPlanID, &parse.Status); err != nil {
|
||||
log.Fatalf("failed to scan row from l_monitoring_log_parse_result: %v", err)
|
||||
return err
|
||||
}
|
||||
parses = append(parses, parse)
|
||||
}
|
||||
rows.Close()
|
||||
// 使用新的relation_id和新的project_id插入新记录
|
||||
valueStrings = make([]string, 0, len(parses))
|
||||
valueArgs = make([]any, 0, len(parses)*6) // 每个项目有6个字段
|
||||
|
||||
for _, parse := range parses {
|
||||
valueStrings = append(valueStrings, "(?, ?, ?, ?, ?, ?)")
|
||||
valueArgs = append(valueArgs, parse.ParseResult, newRelID, newProjectID, parse.CleanPlanID, parse.Status, time.Now())
|
||||
}
|
||||
|
||||
xsql = fmt.Sprintf("INSERT INTO l_monitoring_log_parse_result (parse_result, relation_id, session_id, clean_plan_id, status, created_at) VALUES %s", strings.Join(valueStrings, ","))
|
||||
result, err = tx.ExecContext(ctx, xsql, valueArgs...)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to insert data into l_monitoring_log_parse_result: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
x, err = result.RowsAffected()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get rows affected for l_monitoring_log_parse_result: %v", err)
|
||||
return err
|
||||
}
|
||||
println("插入日志解析结果:", x)
|
||||
}
|
||||
|
||||
// 根据旧的经验体ID读取pages内容
|
||||
query = "select id, page_url, page_desc, elements_json, statistics, system_id, system_name, input_json, page_summary, clickable, page_type, unique_page_id, unique_system_id, memo_process_status from l_pages where experience_id = ?"
|
||||
rows, err = tx.QueryContext(ctx, query, oldExperienceID)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to query l_pages: %v", err)
|
||||
return err
|
||||
}
|
||||
pages := make([]Page, 0)
|
||||
for rows.Next() {
|
||||
var page Page
|
||||
if err := rows.Scan(&page.ID, &page.PageUrl, &page.PageDesc, &page.ElementsJson, &page.Statistics, &page.SystemID, &page.SystemName, &page.InputJson, &page.PageSummary, &page.Clickable, &page.PageType, &page.UniquePageID, &page.UniqueSystemID, &page.MemoProcessStatus); err != nil {
|
||||
log.Fatalf("failed to scan row from l_pages: %v", err)
|
||||
return err
|
||||
}
|
||||
pages = append(pages, page)
|
||||
}
|
||||
rows.Close()
|
||||
|
||||
pageIDRel := make(map[uint]uint)
|
||||
actionIDRel := make(map[uint]uint)
|
||||
for _, page := range pages {
|
||||
oldPageID := page.ID
|
||||
// 每个page单独插入
|
||||
newSysID, ok := sysRel[page.SystemID]
|
||||
if !ok {
|
||||
log.Fatalf("failed to find new system ID for old system ID: %d", page.SystemID)
|
||||
return fmt.Errorf("failed to find new system ID for old system ID: %d", page.SystemID)
|
||||
}
|
||||
|
||||
xsql = "INSERT INTO l_pages (page_url, page_desc, elements_json, statistics, system_id, system_name, input_json, page_summary, clickable, page_type, experience_id, unique_page_id, unique_system_id, memo_process_status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
result, err = tx.ExecContext(ctx, xsql, page.PageUrl, page.PageDesc, page.ElementsJson, page.Statistics, newSysID, page.SystemName, page.InputJson, page.PageSummary, page.Clickable, page.PageType, newExperienceID, page.UniquePageID, page.UniqueSystemID, page.MemoProcessStatus, time.Now(), time.Now())
|
||||
if err != nil {
|
||||
log.Fatalf("failed to insert data into l_pages: %v", err)
|
||||
return err
|
||||
}
|
||||
newPageID, err := result.LastInsertId()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get rows affected for l_pages: %v", err)
|
||||
return err
|
||||
}
|
||||
println("插入页面:", newPageID)
|
||||
pageIDRel[oldPageID] = uint(newPageID)
|
||||
|
||||
// 使用旧的PageID获取user_action表中的数据
|
||||
query = "select id, relation_id, system_name, page_url, element_text, event_type, page_html_path, screenshot_path, element_tag, status, extra_data, user_id, experience_id, page_id, system_id, log_dig_status, clean_page_desc, clean_system_desc, clean_html_diff, clean_elements_json, clean_page_inputs, clean_page_stats, processing_delay from l_user_actions where page_id = ?"
|
||||
rows, err = tx.QueryContext(ctx, query, oldPageID)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to query l_user_actions: %v", err)
|
||||
return err
|
||||
}
|
||||
actions := make([]UserAction, 0)
|
||||
for rows.Next() {
|
||||
var action UserAction
|
||||
if err := rows.Scan(&action.ID, &action.RelationID, &action.SystemName, &action.PageUrl, &action.ElementText, &action.EventType, &action.PageHtmlPath, &action.ScreenshotPath, &action.ElementTag, &action.Status, &action.ExtraData, &action.UserID, &action.ExperienceID, &action.PageID, &action.SystemID, &action.LogDigStatus, &action.CleanPageDesc, &action.CleanSystemDesc, &action.CleanHtmlDiff, &action.CleanElementsJson, &action.CleanPageInputs, &action.CleanPageStats, &action.ProcessingDelay); err != nil {
|
||||
log.Fatalf("failed to scan row from l_user_actions: %v", err)
|
||||
return err
|
||||
}
|
||||
actions = append(actions, action)
|
||||
}
|
||||
rows.Close()
|
||||
|
||||
// 需要收集每个新插入的user_action的id,所以要一个一个插入
|
||||
for _, action := range actions {
|
||||
oldRelID := action.RelationID
|
||||
newRelID := oldRelID + "-" + strconv.FormatUint(uint64(newProjectID), 10)
|
||||
xsql = "INSERT INTO l_user_actions (relation_id, system_name, page_url, element_text, event_type, page_html_path, screenshot_path, element_tag, status, extra_data, user_id, experience_id, page_id, system_id, log_dig_status, clean_page_desc, clean_system_desc, clean_html_diff, clean_elements_json, clean_page_inputs, clean_page_stats, processing_delay, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
result, err = tx.ExecContext(ctx, xsql, newRelID, action.SystemName, action.PageUrl, action.ElementText, action.EventType, action.PageHtmlPath, action.ScreenshotPath, action.ElementTag, action.Status, action.ExtraData, action.UserID, newExperienceID, newPageID, sysRel[action.SystemID], action.LogDigStatus, action.CleanPageDesc, action.CleanSystemDesc, action.CleanHtmlDiff, action.CleanElementsJson, action.CleanPageInputs, action.CleanPageStats, action.ProcessingDelay, time.Now(), time.Now())
|
||||
if err != nil {
|
||||
log.Fatalf("failed to insert data into l_user_actions: %v", err)
|
||||
return err
|
||||
}
|
||||
x, err := result.LastInsertId()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get last insert id for l_user_actions: %v", err)
|
||||
return err
|
||||
}
|
||||
actionIDRel[action.ID] = uint(x)
|
||||
}
|
||||
}
|
||||
for old, new := range actionIDRel {
|
||||
fmt.Printf("旧ActionID: %d, 新ActionID: %d\n", old, new)
|
||||
}
|
||||
|
||||
updateVideoIDSequence := make(map[uint][]byte)
|
||||
for _, newRelID := range newRelIDs {
|
||||
videoQuery := "SELECT id, action_sequence FROM l_videos WHERE relation_id = ?"
|
||||
videoRows, err := tx.QueryContext(ctx, videoQuery, newRelID)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to query l_videos: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
for videoRows.Next() {
|
||||
var videoID uint
|
||||
var actionSequence string
|
||||
if err := videoRows.Scan(&videoID, &actionSequence); err != nil {
|
||||
log.Fatalf("failed to scan row from l_videos: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 2. 然后将action_sequence解析为json数组
|
||||
var actionIDs []uint
|
||||
if err := json.Unmarshal([]byte(actionSequence), &actionIDs); err != nil {
|
||||
log.Fatalf("failed to unmarshal action_sequence: %v", err)
|
||||
return err
|
||||
}
|
||||
fmt.Printf("old actions IDs: %+v\n", actionIDs)
|
||||
|
||||
// 3. 然后根据新旧ID关系来创建好新的json数组
|
||||
var newActionIDs []uint
|
||||
for _, oldID := range actionIDs {
|
||||
if newID, ok := actionIDRel[oldID]; ok {
|
||||
newActionIDs = append(newActionIDs, newID)
|
||||
}
|
||||
}
|
||||
fmt.Printf("new actions IDs: %+v\n", newActionIDs)
|
||||
|
||||
// 4. 根据ID来更新video表
|
||||
newActionSequence, err := json.Marshal(newActionIDs)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to marshal new action_sequence: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
updateVideoIDSequence[videoID] = newActionSequence
|
||||
}
|
||||
videoRows.Close()
|
||||
}
|
||||
updateVideoQuery := "UPDATE l_videos SET action_sequence = ? WHERE id = ?"
|
||||
for videoID, newActionSequence := range updateVideoIDSequence {
|
||||
if _, err := tx.ExecContext(ctx, updateVideoQuery, newActionSequence, videoID); err != nil {
|
||||
log.Fatalf("failed to update l_video: %v", err)
|
||||
return err
|
||||
}
|
||||
println("更新视频ID:", videoID, "的用户动作序列")
|
||||
}
|
||||
|
||||
// 根据旧的经验体ID获取主观知识表
|
||||
query = "select extracted_subjective_knowledge_desc, session_id, dialog_ids, experience_id, version, status, taskpoint_id, relation_id, system_ids, page_ids, category_tags, is_global_associated from l_extracted_subjective_knowledges where experience_id = ?"
|
||||
rows, err = tx.QueryContext(ctx, query, oldExperienceID)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to query l_extracted_subjective_knowledges: %v", err)
|
||||
return err
|
||||
}
|
||||
subjectKnowledges := make([]SubjectKnowledge, 0)
|
||||
for rows.Next() {
|
||||
var sk SubjectKnowledge
|
||||
if err := rows.Scan(&sk.ExtractedSubjectiveKnowledgeDesc, &sk.SessionID, &sk.DialogIDs, &sk.ExperienceID, &sk.Version, &sk.Status, &sk.TaskpointID, &sk.RelationID, &sk.SystemIDs, &sk.PageIDs, &sk.CategoryTags, &sk.IsGlobalAssociated); err != nil {
|
||||
log.Fatalf("failed to scan row from l_extracted_subjective_knowledges: %v", err)
|
||||
return err
|
||||
}
|
||||
subjectKnowledges = append(subjectKnowledges, sk)
|
||||
}
|
||||
rows.Close()
|
||||
|
||||
for _, sk := range subjectKnowledges {
|
||||
// 解析DialogIDs
|
||||
var dialogIDs []uint
|
||||
if err := json.Unmarshal(sk.DialogIDs, &dialogIDs); err != nil {
|
||||
log.Fatalf("failed to unmarshal dialog_ids: %v", err)
|
||||
return err
|
||||
}
|
||||
var newDialogIDs []uint
|
||||
for _, oldID := range dialogIDs {
|
||||
if newID, ok := msgIDRel[oldID]; ok {
|
||||
newDialogIDs = append(newDialogIDs, newID)
|
||||
}
|
||||
}
|
||||
newDialogIDsJson, err := json.Marshal(newDialogIDs)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to marshal new dialog_ids: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 解析systemIDs
|
||||
var systemIDs []uint
|
||||
if err := json.Unmarshal(sk.SystemIDs, &systemIDs); err != nil {
|
||||
log.Fatalf("failed to unmarshal system_ids: %v", err)
|
||||
return err
|
||||
}
|
||||
var newSystemIDs []uint
|
||||
for _, oldID := range systemIDs {
|
||||
if newID, ok := sysRel[oldID]; ok {
|
||||
newSystemIDs = append(newSystemIDs, newID)
|
||||
}
|
||||
}
|
||||
newSystemIDsJson, err := json.Marshal(newSystemIDs)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to marshal new system_ids: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 解析pageIDs
|
||||
var pageIDs []uint
|
||||
if err := json.Unmarshal(sk.PageIDs, &pageIDs); err != nil {
|
||||
log.Fatalf("failed to unmarshal page_ids: %v", err)
|
||||
return err
|
||||
}
|
||||
var newPageIDs []uint
|
||||
for _, oldID := range pageIDs {
|
||||
if newID, ok := pageIDRel[oldID]; ok {
|
||||
newPageIDs = append(newPageIDs, newID)
|
||||
}
|
||||
}
|
||||
newPageIDsJson, err := json.Marshal(newPageIDs)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to marshal new page_ids: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
newRelID := relRelIDs[*sk.RelationID]
|
||||
xsql = "INSERT INTO l_extracted_subjective_knowledges (extracted_subjective_knowledge_desc, session_id, dialog_ids, experience_id, version, status, taskpoint_id, relation_id, system_ids, page_ids, category_tags, is_global_associated, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
result, err = tx.ExecContext(ctx, xsql, sk.ExtractedSubjectiveKnowledgeDesc, newProjectID, newDialogIDsJson, newExperienceID, sk.Version, sk.Status, sk.TaskpointID, newRelID, newSystemIDsJson, newPageIDsJson, sk.CategoryTags, sk.IsGlobalAssociated, time.Now(), time.Now())
|
||||
if err != nil {
|
||||
log.Fatalf("failed to insert data into l_extracted_subjective_knowledges: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
x, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get rows affected for l_extracted_subjective_knowledges: %v", err)
|
||||
return err
|
||||
}
|
||||
println("插入主观知识:", x)
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to commit transaction: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
32
docker-compose-kraft.yml
Normal file
32
docker-compose-kraft.yml
Normal file
@@ -0,0 +1,32 @@
|
||||
services:
|
||||
kafka:
|
||||
image: apache/kafka:4.0.0
|
||||
container_name: kafka-apache-kraft-410
|
||||
hostname: kafka-kraft
|
||||
ports:
|
||||
- "9092:9092" # 映射 Broker 端口
|
||||
environment:
|
||||
KAFKA_LOG4J_OPTS: "-Dlog4j.configurationFile=file:/opt/kafka/config/custom-log4j2.yaml"
|
||||
KAFKA_NODE_ID: 1
|
||||
KAFKA_PROCESS_ROLES: "broker,controller"
|
||||
|
||||
# 2. 监听器配置
|
||||
KAFKA_LISTENERS: "PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093"
|
||||
KAFKA_ADVERTISED_LISTENERS: "PLAINTEXT://localhost:9092"
|
||||
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT"
|
||||
KAFKA_CONTROLLER_LISTENER_NAMES: "CONTROLLER"
|
||||
|
||||
# 3. Controller 连接信息(单节点)
|
||||
KAFKA_CONTROLLER_QUORUM_VOTERS: "1@kafka-kraft:9093"
|
||||
|
||||
KAFKA_LOG_DIRS: "/var/lib/kafka/data"
|
||||
|
||||
# 为内部 topic __consumer_offsets 设置副本因子为 1
|
||||
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
|
||||
# (可选,推荐) 事务状态 topic 的副本因子也设置为 1
|
||||
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
|
||||
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
|
||||
volumes:
|
||||
- ./kafka-data:/var/lib/kafka/data # 数据持久化
|
||||
- ./log4j2.yaml:/opt/kafka/config/custom-log4j2.yaml:ro # 日志级别配置
|
||||
restart: always
|
||||
27
docker-compose.yml
Normal file
27
docker-compose.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
services:
|
||||
kafka:
|
||||
image: apache/kafka:4.0.0
|
||||
container_name: kafka-apache-kraft-410
|
||||
ports:
|
||||
- "9092:9092" # 映射 Broker 端口
|
||||
environment:
|
||||
# 1. 启用 KRaft 模式
|
||||
KAFKA_NODE_ID: 1
|
||||
KAFKA_CLUSTER_ID: 4V-T-K3dRSy_6s2d17K97Q
|
||||
KAFKA_PROCESS_ROLES: "broker,controller"
|
||||
|
||||
# 2. 监听器配置
|
||||
KAFKA_LISTENERS: "PLAINTEXT://:9092,CONTROLLER://:9093"
|
||||
KAFKA_ADVERTISED_LISTENERS: "PLAINTEXT://localhost:9092"
|
||||
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT"
|
||||
KAFKA_CONTROLLER_LISTENER_NAMES: "CONTROLLER"
|
||||
|
||||
# 3. Controller 连接信息(单节点)
|
||||
KAFKA_CONTROLLER_QUORUM_VOTERS: "1@localhost:9093"
|
||||
|
||||
KAFKA_LOG_DIRS: "/var/lib/kafka/data"
|
||||
|
||||
volumes:
|
||||
- ./kafka-data:/var/lib/kafka/data # 数据持久化
|
||||
- ./log4j2.properties:/opt/kafka/config/log4j2.properties:ro # 日志级别配置
|
||||
restart: always
|
||||
35
go.mod
35
go.mod
@@ -1,5 +1,34 @@
|
||||
module git.goalfyagent.ai/lixuan/playground
|
||||
module playground
|
||||
|
||||
go 1.25.3
|
||||
go 1.24.0
|
||||
|
||||
require github.com/buger/jsonparser v1.1.1
|
||||
require (
|
||||
github.com/IBM/sarama v1.46.2
|
||||
github.com/redis/go-redis/v9 v9.14.0
|
||||
github.com/xdg/scram v1.0.5
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/eapache/go-resiliency v1.7.0 // indirect
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect
|
||||
github.com/eapache/queue v1.1.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.9.3 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
|
||||
github.com/jcmturner/gofork v1.7.6 // indirect
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.22 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect
|
||||
github.com/xdg/stringprep v1.0.3 // indirect
|
||||
golang.org/x/crypto v0.43.0 // indirect
|
||||
golang.org/x/net v0.46.0 // indirect
|
||||
golang.org/x/text v0.30.0 // indirect
|
||||
)
|
||||
|
||||
112
go.sum
112
go.sum
@@ -1,2 +1,110 @@
|
||||
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/IBM/sarama v1.46.2 h1:65JJmZpxKUWe/7HEHmc56upTfAvgoxuyu4Ek+TcevDE=
|
||||
github.com/IBM/sarama v1.46.2/go.mod h1:PDOGmVeKmW744c/0d4CZ0MfrzmcIYtpmS5+KIWs1zHQ=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/eapache/go-resiliency v1.7.0 h1:n3NRTnBn5N0Cbi/IeOHuQn9s2UwVUH7Ga0ZWcP+9JTA=
|
||||
github.com/eapache/go-resiliency v1.7.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 h1:Oy0F4ALJ04o5Qqpdz8XLIpNA3WM/iSIXqxtqo7UGVws=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0=
|
||||
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
|
||||
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
|
||||
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
|
||||
github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg=
|
||||
github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=
|
||||
github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=
|
||||
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8=
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU=
|
||||
github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 h1:bsUq1dX0N8AOIL7EB/X911+m4EHsnWEHeJ0c+3TTBrg=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/redis/go-redis/v9 v9.14.0 h1:u4tNCjXOyzfgeLN+vAZaW1xUooqWDqVEsZN0U01jfAE=
|
||||
github.com/redis/go-redis/v9 v9.14.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/xdg/scram v1.0.5 h1:TuS0RFmt5Is5qm9Tm2SoD89OPqe4IRiFtyFY4iwWXsw=
|
||||
github.com/xdg/scram v1.0.5/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||
github.com/xdg/stringprep v1.0.3 h1:cmL5Enob4W83ti/ZHuZLuKD/xqJfus4fVPwE+/BDm+4=
|
||||
github.com/xdg/stringprep v1.0.3/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
61
kafka-op.txt
Normal file
61
kafka-op.txt
Normal file
@@ -0,0 +1,61 @@
|
||||
docker compose -f ./docker-compose-kraft.yml down
|
||||
rm -rf ./kafka-data/*
|
||||
docker compose -f ./docker-compose-kraft.yml up -d
|
||||
|
||||
|
||||
docker compose -f ./docker-compose-kraft.yml up -d --force-recreate
|
||||
docker logs -f kafka-apache-kraft-410
|
||||
|
||||
docker exec -it kafka-apache-kraft-410 /bin/bash
|
||||
|
||||
cd /opt/kafka/bin/
|
||||
/opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --topic test-topic --partitions 1 --replication-factor 1
|
||||
cat /opt/kafka/config/server.properties
|
||||
cat /opt/kafka/config/log4j2.yaml
|
||||
|
||||
|
||||
./kafka-topics.sh --bootstrap-server localhost:9092 --list
|
||||
./kafka-consumer-groups.sh --bootstrap-server localhost:9092 --list
|
||||
./kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group test-consumer-group
|
||||
|
||||
./kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test-topic --from-beginning --max-messages 1
|
||||
|
||||
./kafka-consumer-groups.sh \
|
||||
--bootstrap-server localhost:9092 \
|
||||
--group temp-offset-checker-$(date +%s) \
|
||||
--describe \
|
||||
--all-topics
|
||||
|
||||
./kafka-consumer-groups.sh \
|
||||
--bootstrap-server localhost:9092 \
|
||||
--group temp-offset-checker \
|
||||
--describe \
|
||||
--all-topics
|
||||
|
||||
./kafka-console-consumer.sh \
|
||||
--bootstrap-server localhost:9092 \
|
||||
--topic test-topic \
|
||||
--from-beginning \
|
||||
--max-messages 1 \
|
||||
--group test-manual-group-001
|
||||
|
||||
# --time -2 表示获取 Latest Offset (最大 Offset)
|
||||
./kafka-run-class.sh kafka.tools.GetOffsetShell \
|
||||
--broker-list localhost:9092 \
|
||||
--topic test-topic \
|
||||
--time -2
|
||||
|
||||
./kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group go-sarama-consumer-group-v1
|
||||
|
||||
# 消费量
|
||||
./kafka-log-dirs.sh \
|
||||
--bootstrap-server localhost:9092 --describe --topic-list test-topic
|
||||
|
||||
./kafka-console-consumer.sh \
|
||||
--bootstrap-server localhost:9092 \
|
||||
--topic test-topic
|
||||
--consumer-property auto.offset.reset=latest
|
||||
|
||||
./kafka-console-producer.sh \
|
||||
--bootstrap-server localhost:9092 \
|
||||
--topic test-topic
|
||||
52
log4j2.yaml
Normal file
52
log4j2.yaml
Normal file
@@ -0,0 +1,52 @@
|
||||
Configuration:
|
||||
# -------------------------
|
||||
# Appenders (日志输出目标)
|
||||
# -------------------------
|
||||
Appenders:
|
||||
Console:
|
||||
# 输出到容器的标准输出(控制台)
|
||||
name: STDOUT
|
||||
target: SYSTEM_OUT
|
||||
PatternLayout:
|
||||
# Kafka 标准的日志格式
|
||||
pattern: "[%d] %p %X{kafka.server.tag} %m%n"
|
||||
|
||||
# -------------------------
|
||||
# Loggers (日志记录器配置)
|
||||
# -------------------------
|
||||
Loggers:
|
||||
# 根 Logger 配置: 确保所有日志都输出到 STDOUT
|
||||
Root:
|
||||
level: info # <-- 全局设置为 INFO 级别
|
||||
AppenderRef:
|
||||
ref: STDOUT
|
||||
|
||||
# 针对性配置:为了排查 Group Coordinator 和协议问题,确保关键组件级别正确
|
||||
Logger:
|
||||
# Kafka 服务器的核心组件
|
||||
- name: kafka.server
|
||||
level: error
|
||||
additivity: false
|
||||
AppenderRef:
|
||||
ref: STDOUT
|
||||
|
||||
# 消费者组协调器 (Group Coordinator)
|
||||
- name: kafka.coordinator.group
|
||||
level: error
|
||||
additivity: false
|
||||
AppenderRef:
|
||||
ref: STDOUT
|
||||
|
||||
# 请求通道:调试客户端连接、心跳和协议版本协商
|
||||
- name: kafka.server.RequestChannel
|
||||
level: error
|
||||
additivity: false
|
||||
AppenderRef:
|
||||
ref: STDOUT
|
||||
|
||||
# 抑制 ZooKeeper 和其他冗余组件的 DEBUG 日志 (如果 Kafka 4.0 仍在加载其库)
|
||||
- name: org.apache.zookeeper
|
||||
level: warn # 保持 WARN 级别,避免日志爆炸
|
||||
additivity: false
|
||||
AppenderRef:
|
||||
ref: STDOUT
|
||||
56
long1.txt
Normal file
56
long1.txt
Normal file
@@ -0,0 +1,56 @@
|
||||
{"type":"start_chunk","msg_id":"M-b290465eb963","project_id":"16049","sender_agent_type":"SA","sender_id":"C-58b742e14ea2c82b","timestamp":"2025-11-10T03:29:23.791"}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"{\""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"type"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"ask"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"\","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"text"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"您"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"希望"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"我问"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"一个"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"关于"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"什么"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"主题"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"的问题"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"比如"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"生活"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"科技"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"学习"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"娱乐"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"还是"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"其他"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"领域"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"?\","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"attachments"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" [],"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"s"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"uggested"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"_user"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"_action"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"none"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"\","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"browser"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"_s"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"andbox"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"_id"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \"\""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"}"}}}
|
||||
{"type":"finish_chunk","msg_id":"M-b290465eb963","project_id":"16049","sender_agent_type":"SA","sender_id":"C-58b742e14ea2c82b","ai_message":{"model":"kimi-k2-0905-preview","content":"","msg_id":"M-b290465eb963","tool_calls":[{"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"{\"type\": \"ask\", \"text\": \"您希望我问一个关于什么主题的问题?比如生活、科技、学习、娱乐,还是其他领域?\", \"attachments\": [], \"suggested_user_action\": \"none\", \"browser_sandbox_id\": \"\"}"}}],"usage":{"request_model":"kimi/kimi-k2-0905-preview","prompt_tokens":214,"cache_read_tokens":8448,"completion_tokens":63,"total_tokens":8725}},"timestamp":"2025-11-10T03:29:23.791"}
|
||||
1063
long2.bak.json
Normal file
1063
long2.bak.json
Normal file
File diff suppressed because it is too large
Load Diff
100
long2.json
Normal file
100
long2.json
Normal file
@@ -0,0 +1,100 @@
|
||||
[
|
||||
{
|
||||
"type": "start_chunk",
|
||||
"msg_id": "S-001",
|
||||
"project_id": "1",
|
||||
"sender_agent_type": "AI",
|
||||
"sender_id": "gemini-2.5-flash",
|
||||
"task_id": "task-1-S001",
|
||||
"content": null,
|
||||
"ai_message": {
|
||||
"model": "gemini-2.5-flash",
|
||||
"content": "",
|
||||
"reasoning_content": "",
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": "tool-S001-1",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_weather",
|
||||
"arguments": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"usage": {}
|
||||
},
|
||||
"tool_call": null,
|
||||
"timestamp": "2025-10-13T14:00:00.200000",
|
||||
"metadata": {
|
||||
"session_type": "tool_use"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "content_chunk",
|
||||
"msg_id": "S-001",
|
||||
"project_id": "1",
|
||||
"sender_agent_type": "AI",
|
||||
"sender_id": "gemini-2.5-flash",
|
||||
"task_id": "task-1-S001",
|
||||
"content": "{\"text\":\"正在为用户\"}",
|
||||
"ai_message": {},
|
||||
"tool_call": null,
|
||||
"timestamp": "2025-10-13T14:00:00.600000",
|
||||
"metadata": {
|
||||
"session_type": "tool_use"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "content_chunk",
|
||||
"msg_id": "S-001",
|
||||
"project_id": "1",
|
||||
"sender_agent_type": "AI",
|
||||
"sender_id": "gemini-2.5-flash",
|
||||
"task_id": "task-2-S002",
|
||||
"content": "{\"text\":\"项目2的流式内容\"}",
|
||||
"ai_message": {},
|
||||
"tool_call": null,
|
||||
"timestamp": "2025-10-13T14:00:00.700000",
|
||||
"metadata": {
|
||||
"session_type": "text_only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "content_chunk",
|
||||
"msg_id": "S-001",
|
||||
"project_id": "1",
|
||||
"sender_agent_type": "AI",
|
||||
"sender_id": "gemini-2.5-flash",
|
||||
"task_id": "task-1-S003",
|
||||
"content": "{\"text\":\"这是第一个部分\"}",
|
||||
"ai_message": {},
|
||||
"tool_call": null,
|
||||
"timestamp": "2025-10-13T14:00:00.800000",
|
||||
"metadata": {
|
||||
"session_type": "reasoning_first"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "finish_chunk",
|
||||
"msg_id": "S-001",
|
||||
"project_id": "1",
|
||||
"sender_agent_type": "AI",
|
||||
"sender_id": "gemini-2.5-flash",
|
||||
"task_id": "task-1-S001",
|
||||
"content": null,
|
||||
"ai_message": {
|
||||
"model": "gemini-2.5-flash",
|
||||
"usage": {
|
||||
"model": "gemini-2.5-flash",
|
||||
"prompt_tokens": 120,
|
||||
"completion_tokens": 55,
|
||||
"total_tokens": 175
|
||||
}
|
||||
},
|
||||
"tool_call": null,
|
||||
"timestamp": "2025-10-13T14:00:01.800000",
|
||||
"metadata": {
|
||||
"session_type": "tool_use"
|
||||
}
|
||||
}
|
||||
]
|
||||
77
long2.sim.json.bak
Normal file
77
long2.sim.json.bak
Normal file
@@ -0,0 +1,77 @@
|
||||
[
|
||||
{
|
||||
"type": "start_chunk",
|
||||
"msg_id": "S-001",
|
||||
"project_id": "1",
|
||||
"sender_agent_type": "AI",
|
||||
"sender_id": "gemini-2.5-flash",
|
||||
"task_id": "task-1-S001",
|
||||
"content": null,
|
||||
"ai_message": {
|
||||
"model": "gemini-2.5-flash",
|
||||
"content": "",
|
||||
"reasoning_content": "",
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": "tool-S001-1",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_weather",
|
||||
"arguments": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"usage": {}
|
||||
},
|
||||
"tool_call": null,
|
||||
"timestamp": "2025-10-13T14:00:00.200000",
|
||||
"metadata": {
|
||||
"session_type": "tool_use"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "content_chunk",
|
||||
"msg_id": "S-001",
|
||||
"project_id": "1",
|
||||
"sender_agent_type": "AI",
|
||||
"sender_id": "gemini-2.5-flash",
|
||||
"task_id": "task-1-S001",
|
||||
"content": "{\"text\":\"正在为用户\"}",
|
||||
"ai_message": {},
|
||||
"tool_call": null,
|
||||
"timestamp": "2025-10-13T14:00:00.600000",
|
||||
"metadata": {
|
||||
"session_type": "tool_use"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "content_chunk",
|
||||
"msg_id": "S-001",
|
||||
"project_id": "1",
|
||||
"sender_agent_type": "AI",
|
||||
"sender_id": "gemini-2.5-flash",
|
||||
"task_id": "task-2-S002",
|
||||
"content": "{\"text\":\"项目2的流式内容\"}",
|
||||
"ai_message": {},
|
||||
"tool_call": null,
|
||||
"timestamp": "2025-10-13T14:00:00.700000",
|
||||
"metadata": {
|
||||
"session_type": "text_only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "content_chunk",
|
||||
"msg_id": "S-001",
|
||||
"project_id": "1",
|
||||
"sender_agent_type": "AI",
|
||||
"sender_id": "gemini-2.5-flash",
|
||||
"task_id": "task-1-S003",
|
||||
"content": "{\"text\":\"这是第一个部分\"}",
|
||||
"ai_message": {},
|
||||
"tool_call": null,
|
||||
"timestamp": "2025-10-13T14:00:00.800000",
|
||||
"metadata": {
|
||||
"session_type": "reasoning_first"
|
||||
}
|
||||
}
|
||||
]
|
||||
526
main.go
Normal file
526
main.go
Normal file
@@ -0,0 +1,526 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"crypto/sha512"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/IBM/sarama"
|
||||
"github.com/xdg/scram"
|
||||
)
|
||||
|
||||
// SCRAMClientGeneratorFunc 必须指向一个返回 sarama.SCRAMClient 接口的函数
|
||||
// 这里的 func() sarama.SCRAMClient { ... } 就是所需的实现。
|
||||
func createScramClient() sarama.SCRAMClient {
|
||||
// 传入用于 SCRAM 认证的 Hash 算法,这里是 SHA-512
|
||||
return &XDGSCRAMClient{HashGeneratorFcn: sha512.New}
|
||||
}
|
||||
|
||||
// XDGSCRAMClient 是对 github.com/xdg/scram/client 库的包装
|
||||
// 使得它符合 Sarama 的 sarama.SCRAMClient 接口
|
||||
type XDGSCRAMClient struct {
|
||||
*scram.Client
|
||||
*scram.ClientConversation
|
||||
scram.HashGeneratorFcn
|
||||
}
|
||||
|
||||
// Begin 用于启动 SCRAM 认证流程
|
||||
func (x *XDGSCRAMClient) Begin(userName, password, salt string) (err error) {
|
||||
x.Client, err = x.HashGeneratorFcn.NewClient(userName, password, salt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
x.ClientConversation = x.Client.NewConversation()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Step 用于处理 SCRAM 认证中的每一步挑战和响应
|
||||
func (x *XDGSCRAMClient) Step(challenge string) (response string, err error) {
|
||||
response, err = x.ClientConversation.Step(challenge)
|
||||
return
|
||||
}
|
||||
|
||||
// Done 检查 SCRAM 认证是否完成
|
||||
func (x *XDGSCRAMClient) Done() bool {
|
||||
return x.ClientConversation.Done()
|
||||
}
|
||||
|
||||
// --- 配置常量 ---
|
||||
const (
|
||||
// 假设 Kafka 运行在宿主机的 9092 端口
|
||||
// BrokerList = "localhost:9092"
|
||||
// Topic = "test-topic"
|
||||
BrokerList = "k8s-kafka-kafkaclu-ea0121c7a5-0f29d8348027ca52.elb.us-west-2.amazonaws.com:9094"
|
||||
// prd
|
||||
// BrokerList = "k8s-middlewa-kafkakaf-8362de7238-60b500b1ed68bc69.elb.us-west-2.amazonaws.com:9094"
|
||||
Topic = "message-users"
|
||||
GroupID = "go-sarama-consumer-group-v1" // 消费组 ID
|
||||
)
|
||||
|
||||
// --- Web 服务相关常量 ---
|
||||
const (
|
||||
WebServerAddress = ":8080" // Web 服务监听的地址和端口
|
||||
)
|
||||
|
||||
// 初始化 Sarama 配置
|
||||
func newConfig() *sarama.Config {
|
||||
config := sarama.NewConfig()
|
||||
// 假设您使用的 Kafka 版本为 4.0.0 或更高 (Sarama 库会兼容)
|
||||
config.Version = sarama.V4_0_0_0 // 请根据您的 Kafka 版本进行调整
|
||||
// 生产者配置
|
||||
config.Producer.RequiredAcks = sarama.WaitForAll // 等待所有副本确认
|
||||
config.Producer.Retry.Max = 5
|
||||
config.Producer.Return.Successes = true // 必须开启,以便同步生产者可以等待确认
|
||||
// 消费者配置:使用 Consumer Group 模式
|
||||
if Topic == "message-users" {
|
||||
// 2. 启用 SASL
|
||||
config.Net.SASL.Enable = true
|
||||
config.Net.SASL.SCRAMClientGeneratorFunc = func() sarama.SCRAMClient {
|
||||
return createScramClient()
|
||||
}
|
||||
|
||||
config.Net.SASL.Mechanism = sarama.SASLTypeSCRAMSHA512
|
||||
|
||||
// 4. 设置用户名和密码
|
||||
config.Net.SASL.User = "kafka-user"
|
||||
config.Net.SASL.Password = "Nrp0vwxgFJXfydV8zISPxjp8RSETjOEq"
|
||||
// prd
|
||||
// config.Net.SASL.Password = "oP0rACG2ka5EBVWfuAyR1fslH4yAlLZX"
|
||||
}
|
||||
|
||||
config.Consumer.Return.Errors = true
|
||||
config.Consumer.Group.Session.Timeout = 20 * time.Second
|
||||
config.Metadata.Timeout = 15 * time.Second
|
||||
return config
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// 生产者逻辑
|
||||
// --------------------------------------------------------------------------------------
|
||||
func startProducer(config *sarama.Config) {
|
||||
// 使用同步生产者 (SyncProducer)
|
||||
producer, err := sarama.NewSyncProducer([]string{BrokerList}, config)
|
||||
if err != nil {
|
||||
log.Printf("Error creating sync producer: %v", err) // 改为 Printf 以避免程序退出
|
||||
return
|
||||
}
|
||||
defer producer.Close()
|
||||
log.Println("Producer started. Sending messages from long1.txt...")
|
||||
|
||||
f, err := os.Open("./long1.txt")
|
||||
if err != nil {
|
||||
log.Printf("failed to read file: %v", err) // 改为 Printf
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
bs, _ := io.ReadAll(f)
|
||||
str := string(bs)
|
||||
lines := strings.Split(str, "\n")
|
||||
|
||||
messageID := 0
|
||||
// 循环发送消息
|
||||
for _, line := range lines {
|
||||
// 忽略空行
|
||||
if strings.TrimSpace(line) == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// 1. 构造 ProducerRecord
|
||||
msg := &sarama.ProducerMessage{
|
||||
Topic: Topic,
|
||||
Key: sarama.StringEncoder(fmt.Sprintf("Key-%d", messageID)),
|
||||
Value: sarama.StringEncoder(line),
|
||||
}
|
||||
|
||||
// 2. 发送消息
|
||||
partition, offset, err := producer.SendMessage(msg)
|
||||
if err != nil {
|
||||
log.Printf("Failed to send message: %v", err)
|
||||
} else {
|
||||
log.Printf("Producer sent: Topic=%s | Partition=%d | Offset=%d | Value='%s'", Topic, partition, offset, line)
|
||||
messageID++
|
||||
}
|
||||
|
||||
// 3. 暂停 (根据需求调整)
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
log.Println("Producer finished sending all messages.")
|
||||
}
|
||||
|
||||
// fetchPartitionMessages connects to a specific partition starting from the given offset,
|
||||
// writes up to limit messages into outputPath (one per line), then returns.
|
||||
// If filterKey is not empty, only messages with matching key are written.
|
||||
// If withTimestamp is true, prepends formatted timestamp to each message.
|
||||
func fetchPartitionMessages(config *sarama.Config, partition int32, offset int64, limit int, outputPath string, filterKey string, withTimestamp bool) error {
|
||||
if limit <= 0 {
|
||||
return fmt.Errorf("limit must be > 0")
|
||||
}
|
||||
|
||||
client, err := sarama.NewClient([]string{BrokerList}, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
consumer, err := sarama.NewConsumerFromClient(client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer consumer.Close()
|
||||
|
||||
pc, err := consumer.ConsumePartition(Topic, partition, offset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer pc.Close()
|
||||
|
||||
outFile, err := os.Create(outputPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer outFile.Close()
|
||||
|
||||
writer := bufio.NewWriter(outFile)
|
||||
defer writer.Flush()
|
||||
|
||||
received := 0
|
||||
scanned := 0
|
||||
filterEnabled := filterKey != ""
|
||||
|
||||
// 设置超时和最大扫描数
|
||||
timeout := time.After(15 * time.Second)
|
||||
maxScan := limit * 1000 // 如果过滤模式下扫描了这么多消息还没找到足够的匹配,就放弃
|
||||
if !filterEnabled {
|
||||
maxScan = limit // 非过滤模式下,扫描数就是 limit
|
||||
}
|
||||
|
||||
for received < limit && scanned < maxScan {
|
||||
select {
|
||||
case <-timeout:
|
||||
log.Printf("Fetch timeout after 30s. Retrieved %d messages (scanned %d)", received, scanned)
|
||||
return nil // 超时不算错误,返回已获取的消息
|
||||
case err, ok := <-pc.Errors():
|
||||
if !ok {
|
||||
return fmt.Errorf("partition consumer error channel closed")
|
||||
}
|
||||
if err != nil {
|
||||
return err.Err
|
||||
}
|
||||
case msg, ok := <-pc.Messages():
|
||||
if !ok {
|
||||
log.Printf("Partition consumer closed. Retrieved %d messages (scanned %d)", received, scanned)
|
||||
return nil // channel 关闭说明没有更多消息了
|
||||
}
|
||||
if msg == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
scanned++
|
||||
|
||||
// 如果启用了 key 过滤,检查 key 是否匹配
|
||||
if filterEnabled {
|
||||
msgKey := string(msg.Key)
|
||||
if msgKey != filterKey {
|
||||
continue // 跳过不匹配的消息
|
||||
}
|
||||
log.Printf("Found matching message %d/%d (scanned %d total)", received+1, limit, scanned)
|
||||
}
|
||||
|
||||
// 构造要写入的内容
|
||||
var line string
|
||||
if withTimestamp {
|
||||
// 格式化时间戳为易读格式: 2006-01-02 15:04:05.000
|
||||
timestampStr := msg.Timestamp.Format("2006-01-02 15:04:05.000")
|
||||
line = fmt.Sprintf("%s %s\n", timestampStr, string(msg.Value))
|
||||
} else {
|
||||
line = string(msg.Value) + "\n"
|
||||
}
|
||||
|
||||
if _, err := writer.WriteString(line); err != nil {
|
||||
return err
|
||||
}
|
||||
received++
|
||||
}
|
||||
}
|
||||
|
||||
if scanned >= maxScan && received < limit {
|
||||
log.Printf("Reached max scan limit (%d messages scanned). Retrieved %d matching messages", scanned, received)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// 消费者逻辑 (保持不变)
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsumerHandler 结构体实现了 sarama.ConsumerGroupHandler 接口
|
||||
type ConsumerHandler struct{}
|
||||
|
||||
// Setup 是在新会话开始时运行的,在 ConsumeClaim 之前
|
||||
func (consumer *ConsumerHandler) Setup(sarama.ConsumerGroupSession) error {
|
||||
log.Println("Consumer Group session setup complete.")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Cleanup 是在会话结束时运行的,在所有 ConsumeClaim 协程退出后
|
||||
func (consumer *ConsumerHandler) Cleanup(sarama.ConsumerGroupSession) error {
|
||||
log.Println("Consumer Group session cleanup complete.")
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConsumeClaim 必须启动一个消费循环,处理分配给当前 consumer 的分区消息
|
||||
func (consumer *ConsumerHandler) ConsumeClaim(session sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error {
|
||||
for message := range claim.Messages() {
|
||||
log.Printf("Consumer Received: Topic=%s | Partition=%d | Offset=%d | Value='%s' (Timestamp: %v)",
|
||||
message.Topic, message.Partition, message.Offset, string(message.Value), message.Timestamp)
|
||||
session.MarkMessage(message, "")
|
||||
}
|
||||
log.Printf("Consumer for Partition %d stopped or rebalancing...", claim.Partition())
|
||||
return nil
|
||||
}
|
||||
|
||||
func startConsumer(config *sarama.Config) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
group, err := sarama.NewConsumerGroup([]string{BrokerList}, GroupID, config)
|
||||
if err != nil {
|
||||
log.Fatalf("Error creating consumer group client: %v", err)
|
||||
}
|
||||
defer group.Close()
|
||||
|
||||
log.Printf("Consumer Group '%s' started. Listening on topic '%s'...", GroupID, Topic)
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
handler := ConsumerHandler{}
|
||||
for {
|
||||
if err := group.Consume(ctx, []string{Topic}, &handler); err != nil {
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
log.Printf("Error from consumer group: %v", err)
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
signals := make(chan os.Signal, 1)
|
||||
signal.Notify(signals, os.Interrupt)
|
||||
if _, ok := <-signals; ok {
|
||||
log.Println("Interrupt signal received. Shutting down consumer...")
|
||||
cancel()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
log.Println("Consumer shutdown complete.")
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Web 服务逻辑
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
// handleRoot 处理根路径请求,显示操作页面
|
||||
func handleRoot(w http.ResponseWriter, r *http.Request) {
|
||||
// 定义一个简单的 HTML 页面模板
|
||||
const htmlTemplate = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Kafka Web Producer</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background-color: #f4f4f4; }
|
||||
.container { text-align: center; }
|
||||
#startButton {
|
||||
padding: 15px 30px;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
#startButton:hover { background-color: #45a049; }
|
||||
#status { margin-top: 20px; font-size: 16px; color: #333; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Kafka 消息生产者</h1>
|
||||
<button id="startButton">开始发送消息</button>
|
||||
<p id="status"></p>
|
||||
</div>
|
||||
<script>
|
||||
document.getElementById('startButton').addEventListener('click', function() {
|
||||
const statusElem = document.getElementById('status');
|
||||
statusElem.textContent = '正在请求服务器开始发送消息...';
|
||||
|
||||
fetch('/start-producer', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log('Success:', data);
|
||||
statusElem.textContent = data.message;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error:', error);
|
||||
statusElem.textContent = '请求失败: ' + error;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
// 解析并执行模板
|
||||
tmpl, err := template.New("index").Parse(htmlTemplate)
|
||||
if err != nil {
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
tmpl.Execute(w, nil)
|
||||
}
|
||||
|
||||
// handleStartProducer 处理开始生产消息的请求
|
||||
func handleStartProducer(config *sarama.Config) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
log.Println("Received request to start producer...")
|
||||
|
||||
// 使用 goroutine 在后台运行生产者,避免阻塞 HTTP 响应
|
||||
go startProducer(config)
|
||||
|
||||
// 立即返回响应给前端
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintln(w, `{"message": "生产者已在后台启动,请查看服务器日志确认消息发送状态。"}`)
|
||||
}
|
||||
}
|
||||
|
||||
// startWebServer 启动 Web 服务
|
||||
func startWebServer(config *sarama.Config) {
|
||||
// 注册 HTTP 路由处理器
|
||||
http.HandleFunc("/", handleRoot)
|
||||
http.HandleFunc("/start-producer", handleStartProducer(config))
|
||||
|
||||
log.Printf("Web server starting on %s...", WebServerAddress)
|
||||
log.Println("Visit http://localhost:8080 in your browser.")
|
||||
|
||||
// 启动 HTTP 服务器
|
||||
if err := http.ListenAndServe(WebServerAddress, nil); err != nil {
|
||||
log.Fatalf("Failed to start web server: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// 主函数与命令行处理
|
||||
// --------------------------------------------------------------------------------------
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Println("Usage: go run main.go <web|consumer|fetch>")
|
||||
fmt.Println(" web: Starts the web server to trigger the producer.")
|
||||
fmt.Println(" consumer: Starts the Kafka consumer.")
|
||||
fmt.Println(" fetch <partition> <offset|oldest|latest> <count> <output-file> [key] [--with-timestamp]: Fetches messages to a file.")
|
||||
fmt.Println(" If [key] is provided, only messages with that key will be fetched.")
|
||||
fmt.Println(" If --with-timestamp is provided, timestamp will be prepended to each message.")
|
||||
return
|
||||
}
|
||||
|
||||
// 初始化配置
|
||||
config := newConfig()
|
||||
|
||||
role := strings.ToLower(os.Args[1])
|
||||
switch role {
|
||||
case "web":
|
||||
startWebServer(config) // 启动 Web 服务
|
||||
case "consumer":
|
||||
startConsumer(config) // 启动消费者
|
||||
case "fetch":
|
||||
if len(os.Args) < 6 {
|
||||
fmt.Println("Usage: go run main.go fetch <partition> <offset|oldest|latest> <count> <output-file> [key] [--with-timestamp]")
|
||||
return
|
||||
}
|
||||
|
||||
partitionVal, err := strconv.Atoi(os.Args[2])
|
||||
if err != nil {
|
||||
log.Fatalf("invalid partition: %v", err)
|
||||
}
|
||||
|
||||
offsetArg := strings.ToLower(os.Args[3])
|
||||
var offset int64
|
||||
switch offsetArg {
|
||||
case "oldest":
|
||||
offset = sarama.OffsetOldest
|
||||
case "latest":
|
||||
offset = sarama.OffsetNewest
|
||||
default:
|
||||
offset, err = strconv.ParseInt(offsetArg, 10, 64)
|
||||
if err != nil {
|
||||
log.Fatalf("invalid offset: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
limit, err := strconv.Atoi(os.Args[4])
|
||||
if err != nil {
|
||||
log.Fatalf("invalid count: %v", err)
|
||||
}
|
||||
|
||||
outputPath := os.Args[5]
|
||||
|
||||
// 可选的 key 参数和 timestamp 标志
|
||||
var filterKey string
|
||||
withTimestamp := false
|
||||
|
||||
// 检查剩余的参数
|
||||
for i := 6; i < len(os.Args); i++ {
|
||||
arg := os.Args[i]
|
||||
if arg == "--with-timestamp" || arg == "-t" {
|
||||
withTimestamp = true
|
||||
} else if filterKey == "" {
|
||||
// 第一个非标志参数作为 filterKey
|
||||
filterKey = arg
|
||||
}
|
||||
}
|
||||
|
||||
if filterKey != "" {
|
||||
log.Printf("Filtering by key: %s", filterKey)
|
||||
}
|
||||
if withTimestamp {
|
||||
log.Printf("Will include timestamps in output")
|
||||
}
|
||||
|
||||
if err := fetchPartitionMessages(config, int32(partitionVal), offset, limit, outputPath, filterKey, withTimestamp); err != nil {
|
||||
log.Fatalf("fetch failed: %v", err)
|
||||
}
|
||||
|
||||
offsetDesc := offsetArg
|
||||
if offsetArg != "oldest" && offsetArg != "latest" {
|
||||
offsetDesc = fmt.Sprintf("%d", offset)
|
||||
}
|
||||
if filterKey != "" {
|
||||
log.Printf("Fetched %d messages with key '%s' from partition %d starting at %s into %s", limit, filterKey, partitionVal, offsetDesc, outputPath)
|
||||
} else {
|
||||
log.Printf("Fetched %d messages from partition %d starting at %s into %s", limit, partitionVal, offsetDesc, outputPath)
|
||||
}
|
||||
default:
|
||||
fmt.Println("Invalid argument. Usage: go run main.go <web|consumer|fetch>")
|
||||
}
|
||||
}
|
||||
70
mcp.go.bak
Normal file
70
mcp.go.bak
Normal file
@@ -0,0 +1,70 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/mark3labs/mcp-go/mcp"
|
||||
"github.com/mark3labs/mcp-go/server"
|
||||
)
|
||||
|
||||
func main() {
|
||||
mode := os.Args[1]
|
||||
switch mode {
|
||||
case "server":
|
||||
startServer()
|
||||
case "client":
|
||||
startClient()
|
||||
}
|
||||
}
|
||||
|
||||
func startServer() {
|
||||
// Create a new MCP server
|
||||
s := server.NewMCPServer(
|
||||
"Demo 🚀",
|
||||
"1.0.0",
|
||||
server.WithToolCapabilities(false),
|
||||
)
|
||||
|
||||
// Add tool
|
||||
tool := mcp.NewTool("hello_world",
|
||||
mcp.WithDescription("Say hello to someone"),
|
||||
mcp.WithString("name",
|
||||
mcp.Required(),
|
||||
mcp.Description("Name of the person to greet"),
|
||||
),
|
||||
)
|
||||
|
||||
// Add tool handler
|
||||
s.AddTool(tool, helloHandler)
|
||||
|
||||
// Start the stdio server
|
||||
testServer := server.NewTestServer(s,
|
||||
server.WithDynamicBasePath(func(r *http.Request, sessionID string) string {
|
||||
tenant := r.Header.Get("X-Tenant-ID")
|
||||
return "/api/" + tenant
|
||||
}),
|
||||
server.WithBaseURL("http://localhost:9090"),
|
||||
server.WithUseFullURLForMessageEndpoint(true))
|
||||
|
||||
mux := http.NewServeMux()
|
||||
// mux.Handle("/api/{tenant}/sse", testServer.)
|
||||
if err := http.ListenAndServe(":9090", mux); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func helloHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
name, err := request.RequireString("name")
|
||||
if err != nil {
|
||||
return mcp.NewToolResultError(err.Error()), nil
|
||||
}
|
||||
|
||||
return mcp.NewToolResultText(fmt.Sprintf("Hello, %s!", name)), nil
|
||||
}
|
||||
|
||||
func startClient() {
|
||||
// Client implementation goes here
|
||||
}
|
||||
191
oss.go.bak
Normal file
191
oss.go.bak
Normal file
@@ -0,0 +1,191 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"log"
|
||||
mrand "math/rand"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
|
||||
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
|
||||
)
|
||||
|
||||
const (
|
||||
ACCESS_KEY_ID = "LTAI5tMRYxK6YpEoNZ4U1AdS"
|
||||
ACCESS_KEY_SECRET = "6qTiPMHmubJ3Y6CRNx8gpg9c2MCtrb"
|
||||
BUCKET_NAME string = "goalfyagent-data-test"
|
||||
ENDPOINT = "http://oss-us-west-1.aliyuncs.com"
|
||||
REGION = "us-west-1"
|
||||
)
|
||||
|
||||
const (
|
||||
totalFiles = 1000
|
||||
minFileSizeKB = 15
|
||||
maxFileSizeKB = 20
|
||||
// 协程数
|
||||
numWorkers = 100
|
||||
objectPrefix = "user/100/goalfymax/UserGlobalData"
|
||||
)
|
||||
|
||||
// 任务结构体,包含文件名和文件内容
|
||||
type uploadTask struct {
|
||||
filename string
|
||||
data []byte
|
||||
}
|
||||
|
||||
// 模拟生成指定大小的随机文件数据
|
||||
func generateRandomData(minKB, maxKB int) []byte {
|
||||
sizeKB := minKB + mrand.Intn(maxKB-minKB+1)
|
||||
sizeBytes := sizeKB * 1024
|
||||
data := make([]byte, sizeBytes)
|
||||
_, err := rand.Read(data)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate random data: %v", err)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// 文件生成器,将任务发送到通道
|
||||
func fileGenerator(tasks chan<- uploadTask, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
for i := range totalFiles {
|
||||
// 创建层级目录
|
||||
dirLevel1 := strconv.Itoa(i / 100) // 每100个文件一个一级目录
|
||||
dirLevel2 := strconv.Itoa((i % 100) / 10) // 每10个文件一个二级目录
|
||||
filename := fmt.Sprintf("%s%s/%s/file_%d.txt", objectPrefix, dirLevel1, dirLevel2, i)
|
||||
|
||||
task := uploadTask{
|
||||
filename: filename,
|
||||
data: generateRandomData(minFileSizeKB, maxFileSizeKB),
|
||||
}
|
||||
tasks <- task
|
||||
}
|
||||
close(tasks)
|
||||
}
|
||||
|
||||
// 文件上传器,从通道接收任务并上传
|
||||
func fileUploader(client *oss.Client, tasks <-chan uploadTask, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
for task := range tasks {
|
||||
reader := bytes.NewReader(task.data)
|
||||
pr, err := client.PutObject(context.Background(), &oss.PutObjectRequest{
|
||||
Bucket: oss.Ptr(BUCKET_NAME),
|
||||
Key: oss.Ptr(task.filename),
|
||||
Body: reader,
|
||||
})
|
||||
if err != nil && pr.StatusCode != 200 {
|
||||
log.Printf("Failed to upload %s: %v\n", task.filename, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 创建OSS客户端
|
||||
conf := oss.LoadDefaultConfig().WithCredentialsProvider(credentials.NewStaticCredentialsProvider(
|
||||
ACCESS_KEY_ID,
|
||||
ACCESS_KEY_SECRET,
|
||||
"",
|
||||
)).WithRegion(REGION).WithEndpoint(ENDPOINT)
|
||||
client := oss.NewClient(conf)
|
||||
|
||||
// // 创建一个带缓冲的通道
|
||||
// tasks := make(chan uploadTask, totalFiles)
|
||||
// var wg sync.WaitGroup
|
||||
|
||||
// // 启动文件生成协程
|
||||
// wg.Add(1)
|
||||
// go fileGenerator(tasks, &wg)
|
||||
|
||||
// // 启动多个文件上传协程(协程池)
|
||||
// for range numWorkers {
|
||||
// wg.Add(1)
|
||||
// go fileUploader(client, tasks, &wg)
|
||||
// }
|
||||
|
||||
// // 等待所有协程完成
|
||||
// wg.Wait()
|
||||
// log.Println("All files have been uploaded.")
|
||||
|
||||
// --- 第一次:全量遍历 ---
|
||||
fmt.Println("--- 开始第一次全量遍历 ---")
|
||||
fullListResult, err := ListObjectsInDirectory(client, BUCKET_NAME, objectPrefix, "")
|
||||
if err != nil {
|
||||
log.Fatalf("全量遍历失败: %v", err)
|
||||
}
|
||||
fmt.Printf("\n全量遍历完成,共获取 %d 个文件。\n", len(fullListResult.Objects))
|
||||
fmt.Printf("下一次增量遍历的Marker是: %s\n", fullListResult.NextMarker)
|
||||
|
||||
// 模拟将 marker 保存起来,用于下次增量遍历
|
||||
nextMarker := fullListResult.NextMarker
|
||||
|
||||
// --- 第二次:增量遍历 ---
|
||||
// 假设在两次遍历之间,OSS中没有新增文件,那么增量遍历应该返回0个文件
|
||||
fmt.Println("\n--- 开始第二次增量遍历 ---")
|
||||
incrementalResult, err := ListObjectsInDirectory(client, BUCKET_NAME, objectPrefix, nextMarker)
|
||||
if err != nil {
|
||||
log.Fatalf("增量遍历失败: %v", err)
|
||||
}
|
||||
fmt.Printf("\n增量遍历完成,共获取 %d 个文件。\n", len(incrementalResult.Objects))
|
||||
if len(incrementalResult.Objects) > 0 {
|
||||
fmt.Printf("新的Marker是: %s\n", incrementalResult.NextMarker)
|
||||
} else {
|
||||
fmt.Println("没有新增文件。")
|
||||
}
|
||||
}
|
||||
|
||||
// ListObjectsResult 包含遍历到的文件列表和下一次增量遍历的起始点
|
||||
type ListObjectsResult struct {
|
||||
Objects []oss.ObjectProperties
|
||||
NextMarker string
|
||||
}
|
||||
|
||||
// ListObjectsInDirectory 遍历OSS指定目录下的文件
|
||||
// bucketName: 存储空间名称
|
||||
// directoryPrefix: 要遍历的目录,例如 "my-folder/"
|
||||
// startAfterMarker: 上一次遍历结束的位置,用于增量遍历。首次全量遍历时传入空字符串""
|
||||
func ListObjectsInDirectory(client *oss.Client, bucketName, directoryPrefix, startAfterMarker string) (*ListObjectsResult, error) {
|
||||
// 2. 创建ListObjectsV2请求
|
||||
request := &oss.ListObjectsV2Request{
|
||||
Bucket: oss.Ptr(bucketName),
|
||||
Prefix: oss.Ptr(directoryPrefix),
|
||||
}
|
||||
|
||||
// 如果传入了marker,则设置为增量遍历
|
||||
if startAfterMarker != "" {
|
||||
request.StartAfter = oss.Ptr(startAfterMarker)
|
||||
}
|
||||
|
||||
// 3. 创建并使用分页器进行遍历
|
||||
paginator := client.NewListObjectsV2Paginator(request,
|
||||
func(po *oss.PaginatorOptions) { po.Limit = 200 })
|
||||
|
||||
var allObjects []oss.ObjectProperties
|
||||
var lastObjectKey string
|
||||
|
||||
fmt.Println("开始遍历文件:")
|
||||
for paginator.HasNext() {
|
||||
page, err := paginator.NextPage(context.TODO())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取下一页数据失败: %w", err)
|
||||
}
|
||||
|
||||
for _, obj := range page.Contents {
|
||||
fmt.Printf(" - %s\n", *obj.Key)
|
||||
allObjects = append(allObjects, obj)
|
||||
lastObjectKey = *obj.Key
|
||||
}
|
||||
}
|
||||
|
||||
result := &ListObjectsResult{
|
||||
Objects: allObjects,
|
||||
NextMarker: lastObjectKey,
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
569
output.txt
Normal file
569
output.txt
Normal file
@@ -0,0 +1,569 @@
|
||||
{"type":"start_chunk","msg_id":"M-b290465eb963","project_id":"16049","sender_agent_type":"SA","sender_id":"C-58b742e14ea2c82b","timestamp":"2025-11-10T03:29:23.791"}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"{\""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"type"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"ask"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"\","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"text"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"您"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"希望"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"我问"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"一个"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"关于"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"什么"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"主题"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"的问题"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"比如"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"生活"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"科技"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"学习"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"娱乐"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"还是"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"其他"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"领域"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"?\","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"attachments"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" [],"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"s"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"uggested"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"_user"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"_action"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"none"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"\","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"browser"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"_s"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"andbox"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"_id"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":" \"\""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb963","project_id":"16049","tool_call":{"index":0,"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"}"}}}
|
||||
{"type":"finish_chunk","msg_id":"M-b290465eb963","project_id":"16049","sender_agent_type":"SA","sender_id":"C-58b742e14ea2c82b","ai_message":{"model":"kimi-k2-0905-preview","content":"","msg_id":"M-b290465eb963","tool_calls":[{"id":"message_user:0","type":"function","function":{"name":"message_user","arguments":"{\"type\": \"ask\", \"text\": \"您希望我问一个关于什么主题的问题?比如生活、科技、学习、娱乐,还是其他领域?\", \"attachments\": [], \"suggested_user_action\": \"none\", \"browser_sandbox_id\": \"\"}"}}],"usage":{"request_model":"kimi/kimi-k2-0905-preview","prompt_tokens":214,"cache_read_tokens":8448,"completion_tokens":63,"total_tokens":8725}},"timestamp":"2025-11-10T03:29:23.791"}
|
||||
{"type":"start_chunk","msg_id":"M-b290465eb984","turn_id":1,"project_id":"16049","sender_agent_type":"SA","sender_id":"C-58b742e14ea2c82b","timestamp":"2025-11-10T03:29:58.581"}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"{\""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"type"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"ask"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"\","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"text"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"在这个"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"信息"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"爆炸"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"的时代"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"我们每天"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"都被"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"无数"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"的声音"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"和"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"观点"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"包围"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"社交媒体"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"新闻"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"推送"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"短视频"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"平台"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"不断"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"向我们"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"输送"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"着"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"各种"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"内容"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"有些"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"真实"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"有些"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"虚假"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"有些"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"甚至"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"带有"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"强烈的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"情绪"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"操控"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"。"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"在这样的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"环境下"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"你认为"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"一个人"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"应该如何"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"保持"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"独立思考"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"的能力"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"你是否"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"会"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"主动"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"去寻找"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"与自己"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"观点"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"不同的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"信息"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"来源"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"当"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"面对"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"一个"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"你"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"原本"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"深信不疑"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"的观点"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"被"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"质疑"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"时"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"你会"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"如何"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"反应"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"你会"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"选择"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"深入"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"探究"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"还是"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"本能"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"地"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"捍卫"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"自己的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"立场"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"这种"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"能力"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"对你"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"的人生"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"决策"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"价值观"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"形成"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"以及"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"与他人"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"沟通"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"的方式"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"产生了"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"哪些"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"具体"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"影响"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"你是否"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"曾经"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"因为"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"坚持"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"独立思考"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"而"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"与他人"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"产生"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"冲突"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"又是如何"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"处理的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"?\","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"attachments"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":" [],"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"s"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"uggested"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"_user"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"_action"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"none"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"\","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"browser"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"_s"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"andbox"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"_id"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":" \"\""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-b290465eb984","project_id":"16049","tool_call":{"index":0,"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"}"}}}
|
||||
{"type":"finish_chunk","msg_id":"M-b290465eb984","turn_id":1,"project_id":"16049","sender_agent_type":"SA","sender_id":"C-58b742e14ea2c82b","ai_message":{"model":"kimi-k2-0905-preview","content":"","msg_id":"M-b290465eb984","turn_id":1,"tool_calls":[{"id":"message_user:1","type":"function","function":{"name":"message_user","arguments":"{\"type\": \"ask\", \"text\": \"在这个信息爆炸的时代,我们每天都被无数的声音和观点包围,社交媒体、新闻推送、短视频平台不断向我们输送着各种内容,有些真实,有些虚假,有些甚至带有强烈的情绪操控。在这样的环境下,你认为一个人应该如何保持独立思考的能力?你是否会主动去寻找与自己观点不同的信息来源?当面对一个你原本深信不疑的观点被质疑时,你会如何反应?你会选择深入探究,还是本能地捍卫自己的立场?这种能力对你的人生决策、价值观形成以及与他人沟通的方式产生了哪些具体影响?你是否曾经因为坚持独立思考而与他人产生冲突,又是如何处理的?\", \"attachments\": [], \"suggested_user_action\": \"none\", \"browser_sandbox_id\": \"\"}"}}],"usage":{"request_model":"kimi/kimi-k2-0905-preview","prompt_tokens":346,"cache_read_tokens":8448,"completion_tokens":158,"total_tokens":8952}},"timestamp":"2025-11-10T03:29:58.581"}
|
||||
{"type":"start_chunk","msg_id":"M-67edbca7ebb1","turn_id":2,"project_id":"16049","sender_agent_type":"SA","sender_id":"C-58b742e14ea2c82b","timestamp":"2025-11-10T03:31:11.846"}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"{\""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"type"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"ask"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"\","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"text"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"如果你"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"有机会"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"重新"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"设计"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"你"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"所在"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"城市"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"的一个"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"公共空间"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"比如"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"一个"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"老"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"旧的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"社区"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"公园"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"一条"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"被"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"忽视的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"街道"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"角落"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"或者"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"一个"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"利用率"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"极"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"低的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"广场"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"你会"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"如何"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"着手"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"你会"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"优先考虑"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"哪些"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"人群"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"的需求"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"老人"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"儿童"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"上班族"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"流浪"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"者"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"残障"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"人士"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"还是"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"其他"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"群体"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"你会"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"如何"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"平衡"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"美观"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"与"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"实用"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"传统"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"与现代"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"安静"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"与"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"活跃"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"之间的关系"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"你会"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"引入"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"哪些"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"自然"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"元素"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"或"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"科技"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"设施"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"你希望"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"这个"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"空间"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"如何"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"影响"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"人们的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"情绪"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"行为"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"甚至"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"人际关系"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"如果"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"预算"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"有限"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"你会"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"如何"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"取舍"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"如果"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"居民"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"意见"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"分歧"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"你会"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"如何"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"协调"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"这个"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"空间"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"对你"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"个人"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"又"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"意味着什么"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"你希望"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"它"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"留下"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"怎样的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"城市"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"记忆"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"?\","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"attachments"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":" [],"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"s"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"uggested"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"_user"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"_action"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"none"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"\","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"browser"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"_s"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"andbox"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"_id"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":" \"\""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ebb1","project_id":"16049","tool_call":{"index":0,"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"}"}}}
|
||||
{"type":"finish_chunk","msg_id":"M-67edbca7ebb1","turn_id":2,"project_id":"16049","sender_agent_type":"SA","sender_id":"C-58b742e14ea2c82b","ai_message":{"model":"kimi-k2-0905-preview","content":"","msg_id":"M-67edbca7ebb1","turn_id":2,"tool_calls":[{"id":"message_user:2","type":"function","function":{"name":"message_user","arguments":"{\"type\": \"ask\", \"text\": \"如果你有机会重新设计你所在城市的一个公共空间,比如一个老旧的社区公园、一条被忽视的街道角落,或者一个利用率极低的广场,你会如何着手?你会优先考虑哪些人群的需求?老人、儿童、上班族、流浪者、残障人士,还是其他群体?你会如何平衡美观与实用、传统与现代、安静与活跃之间的关系?你会引入哪些自然元素或科技设施?你希望这个空间如何影响人们的情绪、行为甚至人际关系?如果预算有限,你会如何取舍?如果居民意见分歧,你会如何协调?这个空间对你个人又意味着什么?你希望它留下怎样的城市记忆?\", \"attachments\": [], \"suggested_user_action\": \"none\", \"browser_sandbox_id\": \"\"}"}}],"usage":{"request_model":"kimi/kimi-k2-0905-preview","prompt_tokens":305,"cache_read_tokens":8704,"completion_tokens":164,"total_tokens":9173}},"timestamp":"2025-11-10T03:31:11.846"}
|
||||
{"type":"start_chunk","msg_id":"M-67edbca7ec2b","turn_id":3,"project_id":"16049","sender_agent_type":"SA","sender_id":"C-58b742e14ea2c82b","timestamp":"2025-11-10T03:32:02.212"}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"{\""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"type"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"ask"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"\","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"text"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"想象"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"你"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"正在"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"经历"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"一段"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"人生的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"低谷"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"期"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"可能是"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"事业上的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"挫败"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"亲密"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"关系的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"破裂"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"或是"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"长期"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"以来的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"自我"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"怀疑"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"在这段"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"时期"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"里"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"你"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"发现自己"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"对"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"曾经"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"热爱"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"的事物"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"失去了"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"兴趣"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"每天"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"醒来"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"都"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"伴随着"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"一种"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"难以"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"名"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"状的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"空虚"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"感"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"你"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"试图"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"通过"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"忙碌"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"娱乐"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"社交"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"来"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"填补"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"却发现"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"这些"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"只是"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"暂时的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"麻醉"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"在这种"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"状态下"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"你会"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"如何"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"与自己"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"对话"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"你会"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"选择"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"向"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"谁"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"倾诉"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"还是"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"独自"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"承受"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"你是否"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"相信"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"痛苦"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"本身"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"具有"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"某种"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"意义"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"还是"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"认为"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"它"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"纯粹"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"是"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"需要"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"被"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"摆脱"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"折磨"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"你有没有"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"想过"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"这种"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"低谷"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"可能"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"正在"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"悄悄"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"塑造"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"一个"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"你"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"尚未"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"认识"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"的新"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"自己"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"如果"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"给你"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"一次机会"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"把"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"这段"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"经历"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"转化为"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"某种"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"创作"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"——"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"一封信"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"一幅"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"画"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"一首歌"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"一段"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"舞蹈"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"甚至"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"一个"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"虚构"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"的故事"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"——"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"你会"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"如何"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"表达"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"那种"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"深"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"层的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"、"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"无法"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"用语言"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"完全"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"捕捉"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"的感受"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"?"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"你希望"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"谁"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"看到"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"它"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"或者"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"你"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"其实"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"只想"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"说"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"给"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"曾经的"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"自己"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"听"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"?\","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"attachments"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":" [],"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"s"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"uggested"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"_user"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"_action"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"none"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"\","}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":" \""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"browser"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"_s"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"andbox"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"_id"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"\":"}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":" \"\""}}}
|
||||
{"type":"tool_call_chunk","msg_id":"M-67edbca7ec2b","project_id":"16049","tool_call":{"index":0,"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"}"}}}
|
||||
{"type":"finish_chunk","msg_id":"M-67edbca7ec2b","turn_id":3,"project_id":"16049","sender_agent_type":"SA","sender_id":"C-58b742e14ea2c82b","ai_message":{"model":"kimi-k2-0905-preview","content":"","msg_id":"M-67edbca7ec2b","turn_id":3,"tool_calls":[{"id":"message_user:3","type":"function","function":{"name":"message_user","arguments":"{\"type\": \"ask\", \"text\": \"想象你正在经历一段人生的低谷期,可能是事业上的挫败、亲密关系的破裂,或是长期以来的自我怀疑,在这段时期里,你发现自己对曾经热爱的事物失去了兴趣,每天醒来都伴随着一种难以名状的空虚感,你试图通过忙碌、娱乐、社交来填补,却发现这些只是暂时的麻醉,在这种状态下,你会如何与自己对话?你会选择向谁倾诉,还是独自承受?你是否相信痛苦本身具有某种意义,还是认为它纯粹是需要被摆脱的折磨?你有没有想过,这种低谷可能正在悄悄塑造一个你尚未认识的新自己?如果给你一次机会,把这段经历转化为某种创作——一封信、一幅画、一首歌、一段舞蹈,甚至一个虚构的故事——你会如何表达那种深层的、无法用语言完全捕捉的感受?你希望谁看到它,或者你其实只想说给曾经的自己听?\", \"attachments\": [], \"suggested_user_action\": \"none\", \"browser_sandbox_id\": \"\"}"}}],"usage":{"request_model":"kimi/kimi-k2-0905-preview","prompt_tokens":270,"cache_read_tokens":8960,"completion_tokens":212,"total_tokens":9442}},"timestamp":"2025-11-10T03:32:02.212"}
|
||||
BIN
playground
Executable file
BIN
playground
Executable file
Binary file not shown.
2
r/data-transfer/.gitignore
vendored
Normal file
2
r/data-transfer/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.github
|
||||
target
|
||||
279
r/data-transfer/Cargo.lock
generated
Normal file
279
r/data-transfer/Cargo.lock
generated
Normal file
@@ -0,0 +1,279 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "data-transfer"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.53.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
|
||||
9
r/data-transfer/Cargo.toml
Normal file
9
r/data-transfer/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "data-transfer"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.51", features = ["derive"] }
|
||||
anyhow = "1.0.100"
|
||||
thiserror = "2.0.17"
|
||||
101
r/data-transfer/PROJECT_MILESTONES.md
Normal file
101
r/data-transfer/PROJECT_MILESTONES.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# Project Milestones
|
||||
|
||||
## Dependencies and Crate Management
|
||||
|
||||
This section documents all external crates used in the project. We strictly avoid using multiple crates that provide the same core functionality to maintain a clean and maintainable dependency tree.
|
||||
|
||||
### Core Dependencies
|
||||
|
||||
| Crate | Version | Purpose | Rationale |
|
||||
| ----------- | ------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `clap` | 4.5.51 | Command-line argument parsing | Industry-standard CLI framework with derive API support. Chosen for its ergonomic API, comprehensive feature set, and excellent documentation. |
|
||||
| `anyhow` | 1.0.100 | Error handling and propagation | Provides simplified error handling for application-level code. Ideal for quickly propagating errors with context up the call stack. |
|
||||
| `thiserror` | 2.0.17 | Custom error type definitions | Complementary to anyhow, used for defining library-level error types with derive macros. Provides clear error messages and seamless integration with Result types. |
|
||||
|
||||
### Dependency Selection Principles
|
||||
|
||||
1. **Single Responsibility**: Each dependency serves a distinct, non-overlapping purpose
|
||||
2. **Maturity**: All selected crates are stable, well-maintained, and widely adopted in the Rust ecosystem
|
||||
3. **Minimal Overhead**: Dependencies are lightweight and do not introduce unnecessary transitive dependencies
|
||||
4. **Compatibility**: All dependencies work seamlessly together without version conflicts
|
||||
|
||||
### Future Considerations
|
||||
|
||||
As new requirements emerge, the following types of crates may be considered:
|
||||
|
||||
- **Serialization**: `serde`, `serde_json` for data format handling
|
||||
- **HTTP Client**: `reqwest` if network operations are needed
|
||||
- **Async Runtime**: `tokio` if asynchronous operations become necessary
|
||||
- **Logging**: `tracing` or `log` if advanced logging capabilities are required
|
||||
- **Configuration**: `config` or `figment` if complex configuration management is needed
|
||||
|
||||
## Version Contents
|
||||
|
||||
### Version 0.1.0 (Current)
|
||||
|
||||
**Release Date**: November 5, 2025
|
||||
|
||||
**Status**: Initial Development
|
||||
|
||||
#### Features
|
||||
|
||||
- ✅ **Project Foundation**
|
||||
- Established modular project structure with clear separation of concerns
|
||||
- Implemented core modules: `cli`, `config`, `error`, `commands`
|
||||
- Set up Rust edition 2024 for latest language features
|
||||
- Configured dependencies using latest stable versions (clap 4.5.51, anyhow 1.0.100, thiserror 2.0.17)
|
||||
|
||||
- ✅ **CLI Framework**
|
||||
- Integrated `clap` for command-line argument parsing using derive API
|
||||
- Implemented verbose flag for detailed logging
|
||||
- Created extensible subcommand structure
|
||||
- Added help and version information display
|
||||
|
||||
- ✅ **Error Handling System**
|
||||
- Defined custom error types using `thiserror`
|
||||
- Implemented `DataTransferError` enum covering common error scenarios
|
||||
- Established `Result<T>` type alias for consistent error handling
|
||||
- Integrated `anyhow` for application-level error propagation
|
||||
|
||||
- ✅ **Configuration Management**
|
||||
- Created `Config` struct for application settings
|
||||
- Implemented configuration loading from CLI arguments
|
||||
- Added default configuration support
|
||||
|
||||
- ✅ **Example Command**
|
||||
- Implemented sample command as a template for future commands
|
||||
- Demonstrated proper error handling patterns
|
||||
- Included unit tests for command functionality
|
||||
|
||||
- ✅ **Testing Infrastructure**
|
||||
- Added unit tests for configuration module
|
||||
- Added unit tests for example command
|
||||
- Established testing patterns for future development
|
||||
|
||||
#### Architecture Highlights
|
||||
|
||||
1. **High Cohesion, Low Coupling**: Each module has a single, well-defined responsibility
|
||||
2. **Explicit Error Handling**: No use of `unwrap()` or `expect()` in production code
|
||||
3. **Ownership Safety**: Careful management of borrowing and lifetimes throughout
|
||||
4. **Documentation**: Comprehensive inline documentation for all public APIs
|
||||
5. **Test Coverage**: Unit tests for critical functionality
|
||||
|
||||
#### Known Limitations
|
||||
|
||||
- Currently contains only a placeholder example command
|
||||
- No persistent configuration file support yet
|
||||
- Limited logging infrastructure (only verbose flag)
|
||||
|
||||
#### Next Steps
|
||||
|
||||
The framework is now ready for feature implementation. Future versions will add:
|
||||
|
||||
1. Actual task automation commands based on user requirements
|
||||
2. Enhanced configuration management (possibly file-based)
|
||||
3. Improved logging with structured output
|
||||
4. Integration tests for end-to-end command validation
|
||||
5. Performance optimizations as needed
|
||||
|
||||
---
|
||||
|
||||
**Note**: This document will be updated as new features are implemented and new dependencies are added. All architectural decisions and dependency additions must be documented here to maintain project clarity and technical governance.
|
||||
163
r/data-transfer/README.md
Normal file
163
r/data-transfer/README.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# Data Transfer
|
||||
|
||||
一个用于自动化处理工作中繁琐任务的命令行工具。
|
||||
|
||||
## 项目简介
|
||||
|
||||
Data Transfer 是一个基于 Rust 开发的命令行程序,旨在帮助快速处理工作中所需执行的重复性、繁琐任务。通过模块化设计和良好的错误处理机制,该工具提供了可靠且易于扩展的任务自动化解决方案。
|
||||
|
||||
## 特性
|
||||
|
||||
- 🚀 **高性能**: 基于 Rust 构建,执行速度快,内存安全
|
||||
- 🔧 **模块化设计**: 清晰的代码结构,易于维护和扩展
|
||||
- ⚡ **命令行友好**: 使用 clap 提供完善的命令行参数解析
|
||||
- 🛡️ **健壮的错误处理**: 使用 anyhow 和 thiserror 进行显式错误管理
|
||||
- 📝 **详细的日志**: 支持 verbose 模式查看详细运行信息
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
data-transfer/
|
||||
├── Cargo.toml # 项目配置和依赖管理
|
||||
├── README.md # 项目文档
|
||||
├── PROJECT_MILESTONES.md # 版本里程碑和依赖管理
|
||||
└── src/
|
||||
├── main.rs # 程序入口
|
||||
├── cli.rs # 命令行参数定义
|
||||
├── config.rs # 配置管理
|
||||
├── error.rs # 错误类型定义
|
||||
└── commands/ # 命令实现模块
|
||||
├── mod.rs # 命令模块导出
|
||||
└── example.rs # 示例命令实现
|
||||
```
|
||||
|
||||
## 技术架构
|
||||
|
||||
### 核心模块
|
||||
|
||||
- **cli**: 使用 clap 的派生 API 定义命令行接口
|
||||
- **config**: 管理应用程序配置和参数
|
||||
- **error**: 自定义错误类型,提供清晰的错误上下文
|
||||
- **commands**: 所有子命令的实现逻辑
|
||||
|
||||
### 设计原则
|
||||
|
||||
项目严格遵循以下 Rust 最佳实践:
|
||||
|
||||
1. **高内聚、低耦合**: 功能模块独立,接口清晰
|
||||
2. **显式错误处理**: 使用 `Result<T, E>` 处理可恢复错误
|
||||
3. **所有权管理**: 合理使用借用和生命周期
|
||||
4. **并发安全**: 使用标准库同步原语保证线程安全
|
||||
5. **测试驱动**: 为核心逻辑提供单元测试
|
||||
|
||||
## 安装
|
||||
|
||||
### 前置要求
|
||||
|
||||
- Rust 1.70 或更高版本
|
||||
- Cargo
|
||||
|
||||
### 从源码构建
|
||||
|
||||
```bash
|
||||
# 克隆仓库
|
||||
git clone <repository-url>
|
||||
cd data-transfer
|
||||
|
||||
# 构建项目
|
||||
cargo build --release
|
||||
|
||||
# 可执行文件位于 target/release/data-transfer
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 基本命令
|
||||
|
||||
```bash
|
||||
# 查看帮助信息
|
||||
./data-transfer --help
|
||||
|
||||
# 启用详细日志模式
|
||||
./data-transfer --verbose
|
||||
|
||||
# 运行示例命令
|
||||
./data-transfer example --input "test data"
|
||||
```
|
||||
|
||||
### 命令参数
|
||||
|
||||
- `-v, --verbose`: 启用详细日志输出
|
||||
- `-h, --help`: 显示帮助信息
|
||||
- `-V, --version`: 显示版本信息
|
||||
|
||||
## 开发指南
|
||||
|
||||
### 添加新命令
|
||||
|
||||
1. 在 `src/commands/` 目录下创建新模块文件
|
||||
2. 在 `src/cli.rs` 中的 `Commands` 枚举添加新命令变体
|
||||
3. 在 `src/commands/mod.rs` 中导出新命令
|
||||
4. 在 `src/main.rs` 中处理新命令的执行逻辑
|
||||
5. 为新命令编写单元测试
|
||||
|
||||
### 运行测试
|
||||
|
||||
```bash
|
||||
# 运行所有测试
|
||||
cargo test
|
||||
|
||||
# 运行特定测试
|
||||
cargo test test_name
|
||||
|
||||
# 显示测试输出
|
||||
cargo test -- --nocapture
|
||||
```
|
||||
|
||||
### 代码规范
|
||||
|
||||
- 使用 `snake_case` 命名函数、变量和模块
|
||||
- 使用 `UpperCamelCase` 命名类型(struct、enum、trait)
|
||||
- 所有公共 API 必须包含文档注释(`///`)
|
||||
- 禁止在生产代码中使用 `unwrap()` 或 `expect()`
|
||||
- 优先使用不可变引用 `&`,仅在必要时使用 `&mut`
|
||||
|
||||
### 错误处理规范
|
||||
|
||||
- 可恢复错误使用 `Result<T, E>` 类型
|
||||
- 使用 `?` 操作符传播错误
|
||||
- 自定义错误类型继承 `thiserror::Error`
|
||||
- 错误消息必须包含足够的上下文信息
|
||||
|
||||
## 依赖说明
|
||||
|
||||
核心依赖库:
|
||||
|
||||
- **clap**: 命令行参数解析库,提供强大的 CLI 构建能力
|
||||
- **anyhow**: 简化错误处理和传播
|
||||
- **thiserror**: 自定义错误类型的派生宏
|
||||
|
||||
详细依赖信息请参考 `PROJECT_MILESTONES.md`。
|
||||
|
||||
## 许可证
|
||||
|
||||
[待补充]
|
||||
|
||||
## 贡献指南
|
||||
|
||||
欢迎贡献代码和提交问题报告!请确保:
|
||||
|
||||
1. 代码符合项目规范
|
||||
2. 添加必要的测试
|
||||
3. 更新相关文档
|
||||
4. 提交前运行 `cargo fmt` 和 `cargo clippy`
|
||||
|
||||
## 路线图
|
||||
|
||||
当前版本为 0.1.0,处于初始开发阶段。后续功能将根据实际需求逐步添加。
|
||||
|
||||
详细的版本规划和功能列表请查看 `PROJECT_MILESTONES.md`。
|
||||
|
||||
## 联系方式
|
||||
|
||||
[待补充]
|
||||
31
r/data-transfer/src/cli.rs
Normal file
31
r/data-transfer/src/cli.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
/// CLI argument parsing module
|
||||
/// Defines command-line interface structure using clap's derive API
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(
|
||||
name = "data-transfer",
|
||||
version,
|
||||
about = "A CLI tool for automating tedious work tasks",
|
||||
long_about = None
|
||||
)]
|
||||
pub struct Cli {
|
||||
/// Enable verbose logging
|
||||
#[arg(short, long)]
|
||||
pub verbose: bool,
|
||||
|
||||
/// Subcommands
|
||||
#[command(subcommand)]
|
||||
pub command: Option<Commands>,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
pub enum Commands {
|
||||
/// Example command placeholder
|
||||
/// This will be replaced with actual commands as requirements are added
|
||||
Example {
|
||||
/// Example parameter
|
||||
#[arg(short, long)]
|
||||
input: Option<String>,
|
||||
},
|
||||
}
|
||||
33
r/data-transfer/src/commands/example.rs
Normal file
33
r/data-transfer/src/commands/example.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
/// Example command implementation
|
||||
/// This serves as a template for future command implementations
|
||||
use crate::error::{DataTransferError, Result};
|
||||
|
||||
/// Run the example command
|
||||
pub fn run(input: Option<String>) -> Result<()> {
|
||||
match input {
|
||||
Some(value) => {
|
||||
println!("Processing input: {}", value);
|
||||
Ok(())
|
||||
}
|
||||
None => Err(DataTransferError::CommandError(
|
||||
"No input provided".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_run_with_input() {
|
||||
let result = run(Some("test".to_string()));
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_run_without_input() {
|
||||
let result = run(None);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
||||
10
r/data-transfer/src/commands/mod.rs
Normal file
10
r/data-transfer/src/commands/mod.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
/// Commands module
|
||||
/// Contains implementations for all CLI subcommands
|
||||
use crate::error::Result;
|
||||
|
||||
pub mod example;
|
||||
|
||||
/// Execute the example command
|
||||
pub fn execute_example(input: Option<String>) -> Result<()> {
|
||||
example::run(input)
|
||||
}
|
||||
48
r/data-transfer/src/config.rs
Normal file
48
r/data-transfer/src/config.rs
Normal file
@@ -0,0 +1,48 @@
|
||||
/// Configuration module
|
||||
/// Handles application configuration loading and management
|
||||
use crate::error::Result;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Config {
|
||||
pub verbose: bool,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Create a new configuration with default values
|
||||
pub fn new() -> Self {
|
||||
Self { verbose: false }
|
||||
}
|
||||
|
||||
/// Create configuration from CLI arguments
|
||||
pub fn from_cli(verbose: bool) -> Self {
|
||||
Self { verbose }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// Load configuration
|
||||
pub fn load(verbose: bool) -> Result<Config> {
|
||||
Ok(Config::from_cli(verbose))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_default_config() {
|
||||
let config = Config::default();
|
||||
assert!(!config.verbose);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_cli() {
|
||||
let config = Config::from_cli(true);
|
||||
assert!(config.verbose);
|
||||
}
|
||||
}
|
||||
20
r/data-transfer/src/error.rs
Normal file
20
r/data-transfer/src/error.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
/// Custom error types for the application
|
||||
/// Uses thiserror for ergonomic error definitions
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum DataTransferError {
|
||||
#[error("Configuration error: {0}")]
|
||||
ConfigError(String),
|
||||
|
||||
#[error("Command execution failed: {0}")]
|
||||
CommandError(String),
|
||||
|
||||
#[error("I/O error: {0}")]
|
||||
IoError(#[from] std::io::Error),
|
||||
|
||||
#[error("Unknown error occurred")]
|
||||
Unknown,
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, DataTransferError>;
|
||||
31
r/data-transfer/src/main.rs
Normal file
31
r/data-transfer/src/main.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
mod cli;
|
||||
mod commands;
|
||||
mod config;
|
||||
mod error;
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use cli::{Cli, Commands};
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
// Load configuration based on CLI arguments
|
||||
let config = config::load(cli.verbose)?;
|
||||
|
||||
if config.verbose {
|
||||
println!("Running in verbose mode");
|
||||
}
|
||||
|
||||
// Execute command based on subcommand
|
||||
match &cli.command {
|
||||
Some(Commands::Example { input }) => {
|
||||
commands::execute_example(input.clone())?;
|
||||
}
|
||||
None => {
|
||||
println!("No command specified. Use --help for usage information.");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
137
rmq.go.bak
Normal file
137
rmq.go.bak
Normal file
@@ -0,0 +1,137 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
amqp "github.com/rabbitmq/amqp091-go"
|
||||
)
|
||||
|
||||
// 连接字符串
|
||||
const amqpURL = "amqp://guest:guest@localhost:5672/"
|
||||
|
||||
// 队列名称
|
||||
const queueName = "hello"
|
||||
|
||||
// 错误处理函数
|
||||
func failOnError(err error, msg string) {
|
||||
if err != nil {
|
||||
log.Panicf("%s: %s", msg, err)
|
||||
}
|
||||
}
|
||||
|
||||
//---
|
||||
|
||||
// 生产者函数
|
||||
func producer() {
|
||||
// 1. 连接 RabbitMQ 服务器
|
||||
conn, err := amqp.Dial(amqpURL)
|
||||
failOnError(err, "Failed to connect to RabbitMQ")
|
||||
defer conn.Close()
|
||||
|
||||
// 2. 创建通道
|
||||
ch, err := conn.Channel()
|
||||
failOnError(err, "Failed to open a channel")
|
||||
defer ch.Close()
|
||||
|
||||
// 3. 声明队列(如果队列不存在则创建)
|
||||
q, err := ch.QueueDeclare(
|
||||
queueName, // name
|
||||
false, // durable 持久化
|
||||
false, // delete when unused 当没有消费者时删除队列
|
||||
false, // exclusive 独占
|
||||
false, // no-wait
|
||||
nil, // arguments
|
||||
)
|
||||
failOnError(err, "Failed to declare a queue")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// 4. 发布消息
|
||||
body := "Hello RabbitMQ!"
|
||||
err = ch.PublishWithContext(ctx,
|
||||
"", // exchange
|
||||
q.Name, // routing key
|
||||
false, // mandatory
|
||||
false, // immediate
|
||||
amqp.Publishing{
|
||||
ContentType: "text/plain",
|
||||
Body: []byte(body),
|
||||
})
|
||||
failOnError(err, "Failed to publish a message")
|
||||
log.Printf(" [x] Sent %s\n", body)
|
||||
}
|
||||
|
||||
//---
|
||||
|
||||
// 消费者函数
|
||||
func consumer() {
|
||||
// 1. 连接 RabbitMQ 服务器
|
||||
conn, err := amqp.Dial(amqpURL)
|
||||
failOnError(err, "Failed to connect to RabbitMQ")
|
||||
defer conn.Close()
|
||||
|
||||
// 2. 创建通道
|
||||
ch, err := conn.Channel()
|
||||
failOnError(err, "Failed to open a channel")
|
||||
defer ch.Close()
|
||||
|
||||
// 3. 声明队列(消费者也需要确保队列存在)
|
||||
q, err := ch.QueueDeclare(
|
||||
queueName, // name
|
||||
false, // durable
|
||||
false, // delete when unused
|
||||
false, // exclusive
|
||||
false, // no-wait
|
||||
nil, // arguments
|
||||
)
|
||||
failOnError(err, "Failed to declare a queue")
|
||||
|
||||
// 4. 注册消费者
|
||||
msgs, err := ch.Consume(
|
||||
q.Name, // queue
|
||||
"", // consumer
|
||||
true, // auto-ack 自动确认
|
||||
false, // exclusive
|
||||
false, // no-local
|
||||
false, // no-wait
|
||||
nil, // args
|
||||
)
|
||||
failOnError(err, "Failed to register a consumer")
|
||||
|
||||
var forever chan struct{}
|
||||
|
||||
// 5. 持续消费消息
|
||||
go func() {
|
||||
for d := range msgs {
|
||||
log.Printf(" [x] Received a message: %s", d.Body)
|
||||
}
|
||||
}()
|
||||
|
||||
log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
|
||||
<-forever
|
||||
}
|
||||
|
||||
//---
|
||||
|
||||
// 主函数,根据命令行参数启动生产者或消费者
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
log.Fatalf("Usage: go run main.go [producer|consumer]")
|
||||
}
|
||||
|
||||
mode := os.Args[1]
|
||||
switch mode {
|
||||
case "producer":
|
||||
log.Println("Starting producer...")
|
||||
producer()
|
||||
case "consumer":
|
||||
log.Println("Starting consumer...")
|
||||
consumer()
|
||||
default:
|
||||
log.Fatalf("Invalid mode: %s. Use 'producer' or 'consumer'.", mode)
|
||||
}
|
||||
}
|
||||
236
task.go.bak
Normal file
236
task.go.bak
Normal file
@@ -0,0 +1,236 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
taskManager, _ := NewTaskManager()
|
||||
go taskManager.Run()
|
||||
|
||||
count := 1
|
||||
for {
|
||||
r := rand.Intn(10)
|
||||
if r < 6 {
|
||||
taskManager.CreateTask(TaskMetadata{
|
||||
ID: strconv.Itoa(count),
|
||||
CreatedAt: time.Now(),
|
||||
UID: count,
|
||||
ProjectID: count,
|
||||
Status: true,
|
||||
})
|
||||
count += 1
|
||||
} else if r < 8 {
|
||||
st := rand.Intn(count) + 1
|
||||
println("prepared to stop task", st)
|
||||
taskManager.StopTask(strconv.Itoa(st))
|
||||
} else if r == 9 {
|
||||
allTasks := taskManager.GetTaskDetails()
|
||||
bs, _ := json.MarshalIndent(allTasks, "", " ")
|
||||
println(string(bs))
|
||||
} else {
|
||||
taskManager.Stop()
|
||||
break
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
time.Sleep(10 * time.Minute)
|
||||
}
|
||||
|
||||
type TaskMetadata struct {
|
||||
ID string `json:"task_id"`
|
||||
CreatedAt time.Time `json:"task_create_time"`
|
||||
UID int `json:"uid"`
|
||||
ProjectID int `json:"project_id"`
|
||||
Status bool `json:"is_run"`
|
||||
StopCause string `json:"stop_cause"`
|
||||
}
|
||||
|
||||
type CommandType int
|
||||
|
||||
const (
|
||||
CmdCreate CommandType = iota // 创建新任务
|
||||
CmdStop // 停止任务
|
||||
CmdQuery // 查询任务状态
|
||||
)
|
||||
|
||||
type TaskCommand struct {
|
||||
Type CommandType
|
||||
Data any
|
||||
}
|
||||
|
||||
// TaskManager 是后台任务的核心管理器
|
||||
type TaskManager struct {
|
||||
ctx context.Context
|
||||
// commands 是一个只接收命令的管道(channel),用于接收外部的创建、停止和查询命令。
|
||||
commands chan TaskCommand
|
||||
|
||||
// tasks 存储所有正在运行的任务。
|
||||
tasks map[string]struct {
|
||||
context.Context
|
||||
context.CancelCauseFunc
|
||||
}
|
||||
rw sync.RWMutex
|
||||
|
||||
// tasksMetadata 存储所有任务的元数据,用于提供任务详情查询。
|
||||
tasksMetadata map[string]TaskMetadata
|
||||
rw1 sync.RWMutex
|
||||
|
||||
doneCh chan struct{}
|
||||
close sync.Once
|
||||
}
|
||||
|
||||
// NewTaskManager 创建并返回一个后台任务管理器实例及其命令管道。
|
||||
// 外部通过 commands 通道向管理器发送命令。
|
||||
func NewTaskManager() (*TaskManager, chan<- TaskCommand) {
|
||||
// 实例化 TaskManager,初始化 map 和 channel
|
||||
tm := &TaskManager{
|
||||
ctx: context.Background(),
|
||||
commands: make(chan TaskCommand, 100), // 带有缓冲区的命令管道,避免阻塞
|
||||
tasks: make(map[string]struct {
|
||||
context.Context
|
||||
context.CancelCauseFunc
|
||||
}),
|
||||
tasksMetadata: make(map[string]TaskMetadata),
|
||||
doneCh: make(chan struct{}, 1),
|
||||
}
|
||||
|
||||
// 返回管理器实例以及一个只写的命令管道
|
||||
return tm, tm.commands
|
||||
}
|
||||
|
||||
func (tm *TaskManager) Run() {
|
||||
// 这个方法将在一个独立的 goroutine 中运行
|
||||
// 负责从 tm.commands 通道读取命令并处理
|
||||
for {
|
||||
select {
|
||||
case <-tm.doneCh:
|
||||
return
|
||||
case cmd, ok := <-tm.commands:
|
||||
if !ok {
|
||||
println("channel was closed")
|
||||
return
|
||||
}
|
||||
// 根据命令类型调用私有方法处理
|
||||
switch cmd.Type {
|
||||
case CmdCreate:
|
||||
if createTask, ok := cmd.Data.(TaskMetadata); ok {
|
||||
go func(data any) {
|
||||
tm.rw.Lock()
|
||||
ctx, cancel := context.WithCancelCause(tm.ctx)
|
||||
tm.tasks[createTask.ID] = struct {
|
||||
context.Context
|
||||
context.CancelCauseFunc
|
||||
}{ctx, cancel}
|
||||
tm.rw.Unlock()
|
||||
|
||||
tm.rw1.Lock()
|
||||
tm.tasksMetadata[createTask.ID] = createTask
|
||||
tm.rw1.Unlock()
|
||||
|
||||
ticker := time.NewTicker(1 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
fmt.Printf("Task is running current user_id is %d\n", createTask.UID)
|
||||
case <-ctx.Done():
|
||||
fmt.Printf("Task is stopped.\n")
|
||||
return
|
||||
}
|
||||
}
|
||||
}(cmd.Data)
|
||||
}
|
||||
case CmdStop:
|
||||
if taskID, ok := cmd.Data.(string); ok {
|
||||
tm.rw.Lock()
|
||||
if task, ok := tm.tasks[taskID]; ok {
|
||||
task.CancelCauseFunc(errors.New("force to cancel the task"))
|
||||
tm.rw1.Lock()
|
||||
meta := tm.tasksMetadata[taskID]
|
||||
meta.Status = false
|
||||
meta.StopCause = context.Cause(task.Context).Error()
|
||||
tm.tasksMetadata[taskID] = meta
|
||||
tm.rw1.Unlock()
|
||||
delete(tm.tasks, taskID)
|
||||
}
|
||||
tm.rw.Unlock()
|
||||
}
|
||||
case CmdQuery:
|
||||
tm.GetTaskDetails()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CreateTask 封装了创建任务的命令,并发送给管理器
|
||||
func (tm *TaskManager) CreateTask(metadata TaskMetadata) {
|
||||
tm.commands <- TaskCommand{
|
||||
Type: CmdCreate,
|
||||
Data: metadata,
|
||||
}
|
||||
}
|
||||
|
||||
// StopTask 封装了停止任务的命令,通过任务ID来指定
|
||||
func (tm *TaskManager) StopTask(taskID string) {
|
||||
tm.commands <- TaskCommand{
|
||||
Type: CmdStop,
|
||||
Data: taskID,
|
||||
}
|
||||
}
|
||||
|
||||
// GetTaskDetails 返回当前所有正在运行任务的元数据列表
|
||||
func (tm *TaskManager) GetTaskDetails() []TaskMetadata {
|
||||
tm.rw1.RLock()
|
||||
defer tm.rw1.RUnlock()
|
||||
|
||||
var details []TaskMetadata
|
||||
for _, metadata := range tm.tasksMetadata {
|
||||
details = append(details, metadata)
|
||||
}
|
||||
return details
|
||||
}
|
||||
|
||||
// Stop 关闭任务管理器
|
||||
// 先拒绝新任务,然后关闭所有当前任务,关闭一个任务就删除一条元数据
|
||||
// 调用此方法默认关闭发送管道
|
||||
func (tm *TaskManager) Stop() {
|
||||
tm.close.Do(func() {
|
||||
// 1. 发送信号给 Run 方法,使其退出
|
||||
tm.doneCh <- struct{}{}
|
||||
|
||||
// 2. 遍历并关闭所有正在运行的任务
|
||||
tm.rw.RLock()
|
||||
for id, task := range tm.tasks {
|
||||
fmt.Printf("Shutting down task %s...\n", id)
|
||||
task.CancelCauseFunc(errors.New("task manager is shutting down"))
|
||||
tm.rw1.Lock()
|
||||
meta := tm.tasksMetadata[id]
|
||||
meta.Status = false
|
||||
meta.StopCause = context.Cause(task.Context).Error()
|
||||
tm.tasksMetadata[id] = meta
|
||||
tm.rw1.Unlock()
|
||||
}
|
||||
tm.rw.RUnlock()
|
||||
|
||||
// 4. 清空任务
|
||||
tm.rw.Lock()
|
||||
for k := range tm.tasks {
|
||||
delete(tm.tasks, k)
|
||||
}
|
||||
tm.rw.Unlock()
|
||||
fmt.Println("All tasks have been stopped and data has been cleared.")
|
||||
|
||||
// 5. 最后关闭 doneCh 和 commands 管道,以释放资源
|
||||
close(tm.doneCh)
|
||||
close(tm.commands)
|
||||
})
|
||||
}
|
||||
1
tmp/build-errors.log
Normal file
1
tmp/build-errors.log
Normal file
@@ -0,0 +1 @@
|
||||
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1
|
||||
587
trie.go.bak
Normal file
587
trie.go.bak
Normal file
@@ -0,0 +1,587 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dghubble/trie"
|
||||
)
|
||||
|
||||
// PathNode 表示路径节点,用于BFS遍历
|
||||
type PathNode struct {
|
||||
Path string // 完整路径
|
||||
Level int // 层级深度
|
||||
ParentID *int64 // 父节点ID,根节点为nil
|
||||
IsFile bool // 是否是文件
|
||||
}
|
||||
|
||||
// MFiles 表示 m_files 表的记录
|
||||
type MFiles struct {
|
||||
ID int64 `json:"id"`
|
||||
FileName string `json:"file_name"`
|
||||
FileType string `json:"file_type"`
|
||||
FileSize int64 `json:"file_size"`
|
||||
FileKey string `json:"file_key"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
}
|
||||
|
||||
// MDocuments 表示 m_documents 表的记录
|
||||
type MDocuments struct {
|
||||
ID int64 `json:"id"`
|
||||
ParentID int64 `json:"parent_id"`
|
||||
FileID *int64 `json:"file_id"`
|
||||
Type string `json:"type"` // 'file' or 'dir'
|
||||
Path string `json:"path"`
|
||||
ProjectID int64 `json:"project_id"`
|
||||
UID int64 `json:"uid"`
|
||||
IsDelete int8 `json:"is_delete"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
DeletedAt *string `json:"deleted_at"`
|
||||
Alias string `json:"alias"`
|
||||
}
|
||||
|
||||
// DatabaseSimulator 数据库模拟器
|
||||
type DatabaseSimulator struct {
|
||||
filesTable map[string]*MFiles // file_key -> record
|
||||
documentsTable map[string]*MDocuments // path -> record
|
||||
nextFileID int64
|
||||
nextDocID int64
|
||||
projectID int64 // 固定项目ID
|
||||
uid int64 // 固定用户ID
|
||||
}
|
||||
|
||||
// NewDatabaseSimulator 创建数据库模拟器
|
||||
func NewDatabaseSimulator(projectID, uid int64) *DatabaseSimulator {
|
||||
return &DatabaseSimulator{
|
||||
filesTable: make(map[string]*MFiles),
|
||||
documentsTable: make(map[string]*MDocuments),
|
||||
nextFileID: 1,
|
||||
nextDocID: 1,
|
||||
projectID: projectID,
|
||||
uid: uid,
|
||||
}
|
||||
}
|
||||
|
||||
// isFilePath 判断路径是否为文件(基于是否有扩展名)
|
||||
func isFilePath(path string) bool {
|
||||
// 获取路径的最后一部分
|
||||
parts := strings.Split(path, "/")
|
||||
if len(parts) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
fileName := parts[len(parts)-1]
|
||||
// 如果包含点且不是以点开头,则认为是文件
|
||||
return strings.Contains(fileName, ".") && !strings.HasPrefix(fileName, ".")
|
||||
}
|
||||
|
||||
// getFileName 从路径获取文件名
|
||||
func getFileName(path string) string {
|
||||
parts := strings.Split(path, "/")
|
||||
if len(parts) == 0 {
|
||||
return ""
|
||||
}
|
||||
return parts[len(parts)-1]
|
||||
}
|
||||
|
||||
// getFileExtension 获取文件扩展名
|
||||
func getFileExtension(fileName string) string {
|
||||
parts := strings.Split(fileName, ".")
|
||||
if len(parts) <= 1 {
|
||||
return ""
|
||||
}
|
||||
return parts[len(parts)-1]
|
||||
}
|
||||
|
||||
// ProcessFileOperation 处理文件操作(插入或更新 m_files 表)
|
||||
func (db *DatabaseSimulator) ProcessFileOperation(fileKey string) (*MFiles, string) {
|
||||
fileName := getFileName(fileKey)
|
||||
fileExt := getFileExtension(fileName)
|
||||
currentTime := time.Now().Format("2006-01-02 15:04:05.000")
|
||||
|
||||
if existingFile, exists := db.filesTable[fileKey]; exists {
|
||||
// 文件已存在,更新记录
|
||||
updateSQL := fmt.Sprintf(`UPDATE m_files SET
|
||||
file_name = '%s',
|
||||
file_type = '%s',
|
||||
updated_at = '%s'
|
||||
WHERE file_key = '%s';`,
|
||||
fileName, fileExt, currentTime, fileKey)
|
||||
|
||||
existingFile.FileName = fileName
|
||||
existingFile.FileType = fileExt
|
||||
|
||||
return existingFile, updateSQL
|
||||
} else {
|
||||
// 插入新文件记录
|
||||
newFile := &MFiles{
|
||||
ID: db.nextFileID,
|
||||
FileName: fileName,
|
||||
FileType: fileExt,
|
||||
FileSize: 1024, // 模拟文件大小
|
||||
FileKey: fileKey,
|
||||
CreatedAt: currentTime,
|
||||
}
|
||||
|
||||
insertSQL := fmt.Sprintf(`INSERT INTO m_files (id, file_name, file_type, file_size, file_key, created_at)
|
||||
VALUES (%d, '%s', '%s', %d, '%s', '%s');`,
|
||||
newFile.ID, newFile.FileName, newFile.FileType, newFile.FileSize, newFile.FileKey, newFile.CreatedAt)
|
||||
|
||||
db.filesTable[fileKey] = newFile
|
||||
db.nextFileID++
|
||||
|
||||
return newFile, insertSQL
|
||||
}
|
||||
}
|
||||
|
||||
// ProcessDocumentOperation 处理文档操作(插入或跳过 m_documents 表)
|
||||
func (db *DatabaseSimulator) ProcessDocumentOperation(path string, parentID *int64, isFile bool, fileID *int64) (*MDocuments, string) {
|
||||
currentTime := time.Now().Format("2006-01-02 15:04:05.000")
|
||||
|
||||
// 检查是否已存在且未删除
|
||||
if existingDoc, exists := db.documentsTable[path]; exists && existingDoc.IsDelete == 0 {
|
||||
// 文档已存在且未删除,不处理
|
||||
return existingDoc, ""
|
||||
}
|
||||
|
||||
// 确定父级ID(如果没有父级则为0)
|
||||
actualParentID := int64(0)
|
||||
if parentID != nil {
|
||||
actualParentID = *parentID
|
||||
}
|
||||
|
||||
// 确定文档类型
|
||||
docType := "dir"
|
||||
if isFile {
|
||||
docType = "file"
|
||||
}
|
||||
|
||||
// 插入新文档记录
|
||||
newDoc := &MDocuments{
|
||||
ID: db.nextDocID,
|
||||
ParentID: actualParentID,
|
||||
FileID: fileID,
|
||||
Type: docType,
|
||||
Path: path,
|
||||
ProjectID: db.projectID,
|
||||
UID: db.uid,
|
||||
IsDelete: 0,
|
||||
CreatedAt: currentTime,
|
||||
UpdatedAt: currentTime,
|
||||
DeletedAt: nil,
|
||||
Alias: getFileName(path),
|
||||
}
|
||||
|
||||
fileIDStr := "NULL"
|
||||
if fileID != nil {
|
||||
fileIDStr = fmt.Sprintf("%d", *fileID)
|
||||
}
|
||||
|
||||
insertSQL := fmt.Sprintf(`INSERT INTO m_documents (id, parent_id, file_id, type, path, project_id, uid, is_delete, created_at, updated_at, alias)
|
||||
VALUES (%d, %d, %s, '%s', '%s', %d, %d, %d, '%s', '%s', '%s');`,
|
||||
newDoc.ID, newDoc.ParentID, fileIDStr, newDoc.Type, newDoc.Path,
|
||||
newDoc.ProjectID, newDoc.UID, newDoc.IsDelete, newDoc.CreatedAt, newDoc.UpdatedAt, newDoc.Alias)
|
||||
|
||||
db.documentsTable[path] = newDoc
|
||||
db.nextDocID++
|
||||
|
||||
return newDoc, insertSQL
|
||||
}
|
||||
|
||||
// PathTrieBuilder 路径字典树构建器
|
||||
type PathTrieBuilder struct {
|
||||
trie *trie.PathTrie
|
||||
}
|
||||
|
||||
// NewPathTrieBuilder 创建新的路径字典树构建器
|
||||
func NewPathTrieBuilder() *PathTrieBuilder {
|
||||
return &PathTrieBuilder{
|
||||
trie: trie.NewPathTrie(),
|
||||
}
|
||||
}
|
||||
|
||||
// BuildTrie 构建字典树
|
||||
func (ptb *PathTrieBuilder) BuildTrie(paths []string) {
|
||||
for _, path := range paths {
|
||||
// 将路径按分隔符分割
|
||||
parts := strings.Split(path, "/")
|
||||
|
||||
// 逐步构建路径并插入到trie中
|
||||
currentPath := ""
|
||||
for i, part := range parts {
|
||||
if i == 0 {
|
||||
currentPath = part
|
||||
} else {
|
||||
currentPath = currentPath + "/" + part
|
||||
}
|
||||
|
||||
// 将当前路径插入到trie中,值为路径的层级
|
||||
ptb.trie.Put(currentPath, len(strings.Split(currentPath, "/")))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BFSTraverse 使用BFS遍历字典树,构建带有父子关系的路径节点
|
||||
func (ptb *PathTrieBuilder) BFSTraverse() []PathNode {
|
||||
var result []PathNode
|
||||
var queue []PathNode
|
||||
|
||||
// 获取所有根路径(第一层)
|
||||
ptb.trie.Walk(func(key string, value interface{}) error {
|
||||
level := value.(int)
|
||||
if level == 1 { // 第一层的路径
|
||||
queue = append(queue, PathNode{
|
||||
Path: key,
|
||||
Level: level,
|
||||
ParentID: nil,
|
||||
IsFile: isFilePath(key),
|
||||
})
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// BFS遍历
|
||||
for len(queue) > 0 {
|
||||
// 取出队列头部节点
|
||||
current := queue[0]
|
||||
queue = queue[1:]
|
||||
|
||||
// 添加到结果中
|
||||
result = append(result, current)
|
||||
|
||||
// 查找当前节点的子节点
|
||||
ptb.trie.Walk(func(key string, value interface{}) error {
|
||||
level := value.(int)
|
||||
// 如果是当前路径的直接子路径
|
||||
if strings.HasPrefix(key, current.Path+"/") && level == current.Level+1 {
|
||||
// 确保是直接子路径,而不是孙子路径
|
||||
remainingPath := strings.TrimPrefix(key, current.Path+"/")
|
||||
if !strings.Contains(remainingPath, "/") {
|
||||
childNode := PathNode{
|
||||
Path: key,
|
||||
Level: level,
|
||||
ParentID: nil,
|
||||
IsFile: isFilePath(key),
|
||||
}
|
||||
queue = append(queue, childNode)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// ProcessPathsWithDatabase 处理路径并生成数据库操作
|
||||
func ProcessPathsWithDatabase(paths []PathNode) {
|
||||
fmt.Println("=== 模拟数据库操作 ===")
|
||||
fmt.Println("按BFS顺序处理路径并生成SQL语句:")
|
||||
fmt.Println()
|
||||
|
||||
// 创建数据库模拟器
|
||||
db := NewDatabaseSimulator(1, 1001) // projectID=1, uid=1001
|
||||
pathToDocIDMap := make(map[string]int64) // 路径到document ID的映射
|
||||
|
||||
// 预先插入一些已存在的记录
|
||||
fmt.Println("=== 预置数据库记录 ===")
|
||||
existingDocs := []*MDocuments{
|
||||
{ID: 100, ParentID: 0, FileID: nil, Type: "dir", Path: "home", ProjectID: 1, UID: 1001, IsDelete: 0, Alias: "home"},
|
||||
{ID: 101, ParentID: 100, FileID: nil, Type: "dir", Path: "home/user", ProjectID: 1, UID: 1001, IsDelete: 0, Alias: "user"},
|
||||
}
|
||||
|
||||
for _, doc := range existingDocs {
|
||||
db.documentsTable[doc.Path] = doc
|
||||
pathToDocIDMap[doc.Path] = doc.ID
|
||||
if doc.ID >= db.nextDocID {
|
||||
db.nextDocID = doc.ID + 1
|
||||
}
|
||||
fmt.Printf("已存在文档: ID=%d, Path=%s, Type=%s, ParentID=%d\n",
|
||||
doc.ID, doc.Path, doc.Type, doc.ParentID)
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
// 统计计数器
|
||||
var (
|
||||
filesInserted = 0
|
||||
filesUpdated = 0
|
||||
dirsInserted = 0
|
||||
dirsSkipped = 0
|
||||
sqlStatements []string
|
||||
)
|
||||
|
||||
// 处理BFS遍历的路径
|
||||
for i, node := range paths {
|
||||
// 获取父节点ID
|
||||
parentID := getParentDocumentID(node.Path, pathToDocIDMap)
|
||||
|
||||
fmt.Printf("[%03d] 处理路径: %s (Level %d, Type: %s)\n",
|
||||
i+1, node.Path, node.Level, func() string {
|
||||
if node.IsFile {
|
||||
return "文件"
|
||||
}
|
||||
return "目录"
|
||||
}())
|
||||
|
||||
if node.IsFile {
|
||||
// 处理文件
|
||||
fmt.Printf(" → 1. 处理文件表 (m_files):\n")
|
||||
|
||||
// 先处理 m_files 表
|
||||
fileRecord, fileSQL := db.ProcessFileOperation(node.Path)
|
||||
if strings.Contains(fileSQL, "INSERT") {
|
||||
fmt.Printf(" INSERT文件: %s\n", fileSQL)
|
||||
filesInserted++
|
||||
} else if strings.Contains(fileSQL, "UPDATE") {
|
||||
fmt.Printf(" UPDATE文件: %s\n", fileSQL)
|
||||
filesUpdated++
|
||||
}
|
||||
sqlStatements = append(sqlStatements, fileSQL)
|
||||
|
||||
// 再处理 m_documents 表
|
||||
fmt.Printf(" → 2. 处理文档表 (m_documents):\n")
|
||||
docRecord, docSQL := db.ProcessDocumentOperation(node.Path, parentID, true, &fileRecord.ID)
|
||||
if docSQL != "" {
|
||||
fmt.Printf(" INSERT文档: %s\n", docSQL)
|
||||
pathToDocIDMap[node.Path] = docRecord.ID
|
||||
dirsInserted++
|
||||
sqlStatements = append(sqlStatements, docSQL)
|
||||
} else {
|
||||
fmt.Printf(" SKIP文档: 路径已存在且未删除\n")
|
||||
dirsSkipped++
|
||||
}
|
||||
} else {
|
||||
// 处理目录
|
||||
fmt.Printf(" → 处理文档表 (m_documents) - 目录:\n")
|
||||
docRecord, docSQL := db.ProcessDocumentOperation(node.Path, parentID, false, nil)
|
||||
if docSQL != "" {
|
||||
fmt.Printf(" INSERT目录: %s\n", docSQL)
|
||||
pathToDocIDMap[node.Path] = docRecord.ID
|
||||
dirsInserted++
|
||||
sqlStatements = append(sqlStatements, docSQL)
|
||||
} else {
|
||||
fmt.Printf(" SKIP目录: 路径已存在且未删除\n")
|
||||
// 即使跳过,也要记录ID供子节点使用
|
||||
if existingDoc, exists := db.documentsTable[node.Path]; exists {
|
||||
pathToDocIDMap[node.Path] = existingDoc.ID
|
||||
}
|
||||
dirsSkipped++
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 输出统计信息
|
||||
fmt.Println("=== 操作统计 ===")
|
||||
fmt.Printf("总共处理路径: %d 个\n", len(paths))
|
||||
fmt.Printf("文件插入: %d 条\n", filesInserted)
|
||||
fmt.Printf("文件更新: %d 条\n", filesUpdated)
|
||||
fmt.Printf("目录插入: %d 条\n", dirsInserted)
|
||||
fmt.Printf("目录跳过: %d 条\n", dirsSkipped)
|
||||
fmt.Printf("生成SQL语句: %d 条\n", len(sqlStatements))
|
||||
|
||||
fmt.Println("\n=== 完整SQL执行顺序 ===")
|
||||
for i, sql := range sqlStatements {
|
||||
fmt.Printf("[%03d] %s\n", i+1, sql)
|
||||
}
|
||||
}
|
||||
|
||||
// getParentDocumentID 根据路径获取父文档ID
|
||||
func getParentDocumentID(path string, pathToDocIDMap map[string]int64) *int64 {
|
||||
parts := strings.Split(path, "/")
|
||||
if len(parts) <= 1 {
|
||||
return nil // 根节点没有父节点
|
||||
}
|
||||
|
||||
// 构建父路径
|
||||
parentParts := parts[:len(parts)-1]
|
||||
parentPath := strings.Join(parentParts, "/")
|
||||
|
||||
if parentID, exists := pathToDocIDMap[parentPath]; exists {
|
||||
return &parentID
|
||||
}
|
||||
|
||||
return nil
|
||||
} // GenerateSamplePaths 生成示例路径数据,包含文件和目录
|
||||
func GenerateSamplePaths() []string {
|
||||
return []string{
|
||||
// 文档目录相关
|
||||
"home/user/documents",
|
||||
"home/user/documents/readme.txt",
|
||||
"home/user/documents/project.pdf",
|
||||
"home/user/downloads",
|
||||
"home/user/downloads/setup.exe",
|
||||
"home/user/pictures/vacation",
|
||||
"home/user/pictures/vacation/beach.jpg",
|
||||
"home/user/pictures/vacation/sunset.png",
|
||||
"home/user/pictures/family",
|
||||
"home/user/pictures/family/photo1.jpg",
|
||||
|
||||
// 管理员目录
|
||||
"home/admin/config",
|
||||
"home/admin/config/app.yaml",
|
||||
"home/admin/logs/error",
|
||||
"home/admin/logs/error/app.log",
|
||||
"home/admin/logs/access",
|
||||
"home/admin/logs/access/access.log",
|
||||
|
||||
// 系统日志
|
||||
"var/log/system",
|
||||
"var/log/system/boot.log",
|
||||
"var/log/application/debug",
|
||||
"var/log/application/debug/debug.log",
|
||||
"var/log/application/info",
|
||||
"var/log/application/info/info.log",
|
||||
|
||||
// 缓存目录
|
||||
"var/cache/temp",
|
||||
"var/cache/temp/temp_file.tmp",
|
||||
"var/cache/sessions",
|
||||
"var/cache/sessions/session_123.dat",
|
||||
|
||||
// 用户程序目录
|
||||
"usr/local/bin",
|
||||
"usr/local/bin/app",
|
||||
"usr/local/lib/python",
|
||||
"usr/local/lib/python/module.py",
|
||||
"usr/local/lib/nodejs",
|
||||
"usr/local/lib/nodejs/package.json",
|
||||
|
||||
// 共享资源
|
||||
"usr/share/docs",
|
||||
"usr/share/docs/manual.pdf",
|
||||
"usr/share/icons/themes",
|
||||
"usr/share/icons/themes/icon.png",
|
||||
|
||||
// 配置文件
|
||||
"etc/nginx/sites",
|
||||
"etc/nginx/sites/default.conf",
|
||||
"etc/nginx/conf.d",
|
||||
"etc/nginx/conf.d/ssl.conf",
|
||||
"etc/ssl/certs",
|
||||
"etc/ssl/certs/server.crt",
|
||||
"etc/ssh/keys",
|
||||
"etc/ssh/keys/id_rsa.pub",
|
||||
|
||||
// 软件目录
|
||||
"opt/software/database",
|
||||
"opt/software/database/config.ini",
|
||||
"opt/software/webserver",
|
||||
"opt/software/webserver/httpd.conf",
|
||||
|
||||
// 临时上传
|
||||
"tmp/uploads/images",
|
||||
"tmp/uploads/images/upload.jpg",
|
||||
"tmp/uploads/documents",
|
||||
"tmp/uploads/documents/doc.docx",
|
||||
"tmp/cache/thumbnails",
|
||||
"tmp/cache/thumbnails/thumb.jpg",
|
||||
|
||||
// 数据备份
|
||||
"data/backups/daily",
|
||||
"data/backups/daily/backup_20240829.sql",
|
||||
"data/backups/weekly",
|
||||
"data/backups/weekly/backup_week34.tar.gz",
|
||||
"data/exports/csv",
|
||||
"data/exports/csv/users.csv",
|
||||
"data/exports/json",
|
||||
"data/exports/json/data.json",
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// // 密钥长度:32字节(256位)
|
||||
// key := make([]byte, 32)
|
||||
// // Nonce长度:12字节(96位)
|
||||
// nonce := make([]byte, 12)
|
||||
|
||||
// // 使用crypto/rand包安全地生成随机字节
|
||||
// _, err := rand.Read(key)
|
||||
// if err != nil {
|
||||
// log.Fatalf("Error generating key: %v", err)
|
||||
// }
|
||||
|
||||
// _, err = rand.Read(nonce)
|
||||
// if err != nil {
|
||||
// log.Fatalf("Error generating nonce: %v", err)
|
||||
// }
|
||||
|
||||
// // 打印生成的字节数组的字面值
|
||||
// fmt.Printf("生成的ChaCha20密钥:\n%#v\n", key)
|
||||
// fmt.Printf("生成的ChaCha20 Nonce:\n%#v\n", nonce)
|
||||
// db, err := gorm.Open(mysql.Open(""), &gorm.Config{
|
||||
// Logger: logger.Default.LogMode(logger.Info),
|
||||
// })
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// // 配置连接池
|
||||
// sqlDB, err := db.DB()
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// // 设置连接池参数
|
||||
// if conf.MaxIdleConns > 0 {
|
||||
// sqlDB.SetMaxIdleConns(conf.MaxIdleConns)
|
||||
// }
|
||||
// if conf.MaxOpenConns > 0 {
|
||||
// sqlDB.SetMaxOpenConns(conf.MaxOpenConns)
|
||||
// }
|
||||
// if conf.ConnMaxLifetime > 0 {
|
||||
// sqlDB.SetConnMaxLifetime(time.Duration(conf.ConnMaxLifetime) * time.Second)
|
||||
// }
|
||||
|
||||
fmt.Println("=== 路径字典树构建和数据库操作演示 ===")
|
||||
fmt.Println()
|
||||
|
||||
// 生成示例路径
|
||||
paths := GenerateSamplePaths()
|
||||
fmt.Printf("生成了 %d 个示例路径(包含文件和目录):\n", len(paths))
|
||||
for i, path := range paths {
|
||||
pathType := "目录"
|
||||
if isFilePath(path) {
|
||||
pathType = "文件"
|
||||
}
|
||||
fmt.Printf(" [%02d] %s (%s)\n", i+1, path, pathType)
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
// 创建路径字典树构建器
|
||||
builder := NewPathTrieBuilder()
|
||||
|
||||
// 构建字典树
|
||||
fmt.Println("正在构建字典树...")
|
||||
builder.BuildTrie(paths)
|
||||
fmt.Println("字典树构建完成!")
|
||||
fmt.Println()
|
||||
|
||||
builder.trie.Walk(func(key string, value interface{}) error {
|
||||
println("key is ", key)
|
||||
return nil
|
||||
})
|
||||
|
||||
// BFS遍历字典树
|
||||
// fmt.Println("开始BFS遍历字典树...")
|
||||
// bfsResult := builder.BFSTraverse()
|
||||
// fmt.Printf("BFS遍历完成,共获得 %d 个节点\n", len(bfsResult))
|
||||
// fmt.Println()
|
||||
|
||||
// 处理路径并生成数据库操作
|
||||
// ProcessPathsWithDatabase(bfsResult)
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("=== 程序执行完成 ===")
|
||||
|
||||
p := "a/b/c"
|
||||
dir, base := path.Split(p)
|
||||
println("dir:", dir, "base:", base)
|
||||
p = "a/b/c/"
|
||||
dir, base = path.Split(p)
|
||||
println("dir:", dir, "base:", base)
|
||||
println("tst", strings.Join([]string{"good"}, "/"))
|
||||
}
|
||||
95
xxx.ctl
Normal file
95
xxx.ctl
Normal file
@@ -0,0 +1,95 @@
|
||||
-- *****************************************************************************
|
||||
-- ** automatically created redirect restore script
|
||||
-- *****************************************************************************
|
||||
UPDATE COMMAND OPTIONS USING S ON Z ON NBUDB_NODE0000.out V ON;
|
||||
SET CLIENT ATTACH_MEMBER 0;
|
||||
SET CLIENT CONNECT_MEMBER 0;
|
||||
-- *****************************************************************************
|
||||
-- ** automatically created redirect restore script
|
||||
-- *****************************************************************************
|
||||
RESTORE DATABASE NBUDB
|
||||
-- USER <username>
|
||||
-- USING '<password>'
|
||||
LOAD '/usr/openv/netbackup/bin/nbdb2.so64'
|
||||
OPEN 4 SESSIONS
|
||||
OPTIONS 'DB2_CLIENT=cvdb2:DB2_POLICY=bk-db2:DB2_FULL=1'
|
||||
TAKEN AT 20240815135857
|
||||
-- ON '/home/db2inst1'
|
||||
DBPATH ON '/fcdm/8627c95c-32ac-e16b-c31f-59632309da1b/NBUDB'
|
||||
INTO NBUDB
|
||||
LOGTARGET 'DEFAULT'
|
||||
-- NEWLOGPATH DEFAULT
|
||||
-- WITH <num-buff> BUFFERS
|
||||
-- BUFFER <buffer-size>
|
||||
REPLACE HISTORY FILE
|
||||
-- REPLACE EXISTING
|
||||
REDIRECT
|
||||
-- PARALLELISM <n>
|
||||
-- WITHOUT ROLLING FORWARD
|
||||
-- WITHOUT PROMPTING
|
||||
;
|
||||
-- *****************************************************************************
|
||||
-- ** storage group definition
|
||||
-- ** Default storage group ID = 0
|
||||
-- ** Number of storage groups = 1
|
||||
-- *****************************************************************************
|
||||
-- *****************************************************************************
|
||||
-- ** Storage group name = IBMSTOGROUP
|
||||
-- ** Storage group ID = 0
|
||||
-- ** Data tag = None
|
||||
-- *****************************************************************************
|
||||
-- SET STOGROUP PATHS FOR IBMSTOGROUP
|
||||
-- ON '/home/db2inst1'
|
||||
-- ;
|
||||
-- *****************************************************************************
|
||||
-- ** table space definition
|
||||
-- *****************************************************************************
|
||||
-- *****************************************************************************
|
||||
-- ** Tablespace name = SYSCATSPACE
|
||||
-- ** Tablespace ID = 0
|
||||
-- ** Tablespace Type = Database managed space
|
||||
-- ** Tablespace Content Type = All permanent data. Regular table space.
|
||||
-- ** Tablespace Page size (bytes) = 4096
|
||||
-- ** Tablespace Extent size (pages) = 4
|
||||
-- ** Using automatic storage = Yes
|
||||
-- ** Storage group ID = 0
|
||||
-- ** Source storage group ID = -1
|
||||
-- ** Data tag = None
|
||||
-- ** Auto-resize enabled = Yes
|
||||
-- ** Total number of pages = 32768
|
||||
-- ** Number of usable pages = 32764
|
||||
-- ** High water mark (pages) = 28816
|
||||
-- *****************************************************************************
|
||||
-- *****************************************************************************
|
||||
-- ** Tablespace name = TEMPSPACE1
|
||||
-- ** Tablespace ID = 1
|
||||
-- ** Tablespace Type = System managed space
|
||||
-- ** Tablespace Content Type = System Temporary data
|
||||
-- ** Tablespace Page size (bytes) = 4096
|
||||
-- ** Tablespace Extent size (pages) = 32
|
||||
-- ** Using automatic storage = Yes
|
||||
-- ** Total number of pages = 1
|
||||
-- *****************************************************************************
|
||||
-- *****************************************************************************
|
||||
-- ** Tablespace name = USERSPACE1
|
||||
-- ** Tablespace ID = 2
|
||||
-- ** Tablespace Type = Database managed space
|
||||
-- ** Tablespace Content Type = All permanent data. Large table space.
|
||||
-- ** Tablespace Page size (bytes) = 4096
|
||||
-- ** Tablespace Extent size (pages) = 32
|
||||
-- ** Using automatic storage = Yes
|
||||
-- ** Storage group ID = 0
|
||||
-- ** Source storage group ID = -1
|
||||
-- ** Data tag = -1
|
||||
-- ** Auto-resize enabled = Yes
|
||||
-- ** Total number of pages = 8192
|
||||
-- ** Number of usable pages = 8160
|
||||
-- ** High water mark (pages) = 96
|
||||
-- *****************************************************************************
|
||||
-- *****************************************************************************
|
||||
-- ** start redirected restore
|
||||
-- *****************************************************************************
|
||||
RESTORE DATABASE NBUDB CONTINUE;
|
||||
-- *****************************************************************************
|
||||
-- ** end of file
|
||||
-- *****************************************************************************
|
||||
Reference in New Issue
Block a user