intention-coding 0.6.9 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/db/lark-storage.d.ts.map +1 -1
- package/dist/index.cjs +991 -432
- package/dist/services/image-analysis/analyzer.d.ts +7 -36
- package/dist/services/image-analysis/analyzer.d.ts.map +1 -1
- package/dist/services/image-analysis/image-processor.d.ts +47 -0
- package/dist/services/image-analysis/image-processor.d.ts.map +1 -0
- package/dist/services/image-analysis/types.d.ts +1 -38
- package/dist/services/image-analysis/types.d.ts.map +1 -1
- package/dist/services/image-analysis/vision-client.d.ts +41 -0
- package/dist/services/image-analysis/vision-client.d.ts.map +1 -0
- package/dist/services/lark/index.d.ts +53 -1
- package/dist/services/lark/index.d.ts.map +1 -1
- package/dist/services/lark/tools/bitable-tools.d.ts +87 -1
- package/dist/services/lark/tools/bitable-tools.d.ts.map +1 -1
- package/dist/services/lark/tools/doc-tools.d.ts +3 -1
- package/dist/services/lark/tools/doc-tools.d.ts.map +1 -1
- package/dist/services/lark/tools/index.d.ts +40 -0
- package/dist/services/lark/tools/index.d.ts.map +1 -1
- package/dist/services/lark/types.d.ts +20 -0
- package/dist/services/lark/types.d.ts.map +1 -1
- package/dist/utils/openai.d.ts +34 -1
- package/dist/utils/openai.d.ts.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -1084,6 +1084,11 @@ var __webpack_modules__ = {
|
|
|
1084
1084
|
return module;
|
|
1085
1085
|
});
|
|
1086
1086
|
},
|
|
1087
|
+
https: function(module) {
|
|
1088
|
+
module.exports = import("https").then(function(module) {
|
|
1089
|
+
return module;
|
|
1090
|
+
});
|
|
1091
|
+
},
|
|
1087
1092
|
"path?5fdd": function(module) {
|
|
1088
1093
|
module.exports = import("path").then(function(module) {
|
|
1089
1094
|
return module;
|
|
@@ -1093,6 +1098,11 @@ var __webpack_modules__ = {
|
|
|
1093
1098
|
module.exports = import("pdf-parse/lib/pdf-parse.js").then(function(module) {
|
|
1094
1099
|
return module;
|
|
1095
1100
|
});
|
|
1101
|
+
},
|
|
1102
|
+
undici: function(module) {
|
|
1103
|
+
module.exports = import("undici").then(function(module) {
|
|
1104
|
+
return module;
|
|
1105
|
+
});
|
|
1096
1106
|
}
|
|
1097
1107
|
};
|
|
1098
1108
|
var __webpack_module_cache__ = {};
|
|
@@ -6116,7 +6126,8 @@ ${logic}` : ""}`;
|
|
|
6116
6126
|
kimiConfig = {
|
|
6117
6127
|
apiKey: "sk-fp8wJSigZBEP3x8y6MAZWGPuVIHJ5PDZtX9lMQQk8hjP2R0u",
|
|
6118
6128
|
baseUrl: "https://api.moonshot.cn/v1/chat/completions",
|
|
6119
|
-
model: "kimi-k2-0905-preview"
|
|
6129
|
+
model: "kimi-k2-0905-preview",
|
|
6130
|
+
visionModel: "moonshot-v1-128k-vision-preview"
|
|
6120
6131
|
};
|
|
6121
6132
|
glm4vConfig = {
|
|
6122
6133
|
apiKey: "fb26a7ff758c3974e43bfff49a684dd3.apcuRq6v6RvwuJDu",
|
|
@@ -6132,6 +6143,12 @@ ${logic}` : ""}`;
|
|
|
6132
6143
|
apiKey: "app-AvlLh0nfN4l9oz1MSW4sEAQ6",
|
|
6133
6144
|
baseUrl: "http://11.0.166.20:9199/v1"
|
|
6134
6145
|
};
|
|
6146
|
+
internalConfig = {
|
|
6147
|
+
apiKey: "sk-3W5NXAzeXX9mNP5yppQwPt6cnEoSK03u5NgiNW1Hsi41Tniu",
|
|
6148
|
+
baseUrl: "https://aiproxy.jla.petrotech.cnpc/v1/chat/completions",
|
|
6149
|
+
visionModel: "qwen2-7b-vl",
|
|
6150
|
+
ocrModel: "deepseek-ocr"
|
|
6151
|
+
};
|
|
6135
6152
|
constructor(){}
|
|
6136
6153
|
async generateText(params) {
|
|
6137
6154
|
const { prompt, temperature, system_prompt } = params;
|
|
@@ -6517,7 +6534,7 @@ ${logic}` : ""}`;
|
|
|
6517
6534
|
}
|
|
6518
6535
|
const image_base64 = `data:${mimeType};base64,${base64}`;
|
|
6519
6536
|
try {
|
|
6520
|
-
logger.k.info("[OpenAI] \u5C1D\u8BD5\u4F7F\u7528 Kimi \u8FDB\u884C\u56FE\u50CF\u8BC6\u522B");
|
|
6537
|
+
logger.k.info("[OpenAI] \u5C1D\u8BD5\u4F7F\u7528 Kimi Vision \u8FDB\u884C\u56FE\u50CF\u8BC6\u522B");
|
|
6521
6538
|
const controller = new AbortController();
|
|
6522
6539
|
const timeoutId = setTimeout(()=>controller.abort(), 30000);
|
|
6523
6540
|
const response = await fetch(this.kimiConfig.baseUrl, {
|
|
@@ -6527,17 +6544,12 @@ ${logic}` : ""}`;
|
|
|
6527
6544
|
Authorization: `Bearer ${this.kimiConfig.apiKey}`
|
|
6528
6545
|
},
|
|
6529
6546
|
body: JSON.stringify({
|
|
6530
|
-
model: this.kimiConfig.
|
|
6547
|
+
model: this.kimiConfig.visionModel,
|
|
6531
6548
|
messages: [
|
|
6532
6549
|
...system_prompt ? [
|
|
6533
6550
|
{
|
|
6534
6551
|
role: "system",
|
|
6535
|
-
content:
|
|
6536
|
-
{
|
|
6537
|
-
type: "text",
|
|
6538
|
-
text: system_prompt
|
|
6539
|
-
}
|
|
6540
|
-
]
|
|
6552
|
+
content: system_prompt
|
|
6541
6553
|
}
|
|
6542
6554
|
] : [],
|
|
6543
6555
|
{
|
|
@@ -6558,7 +6570,10 @@ ${logic}` : ""}`;
|
|
|
6558
6570
|
],
|
|
6559
6571
|
stream: false,
|
|
6560
6572
|
temperature,
|
|
6561
|
-
max_tokens
|
|
6573
|
+
max_tokens,
|
|
6574
|
+
stop: [
|
|
6575
|
+
"<<<END>>>"
|
|
6576
|
+
]
|
|
6562
6577
|
}),
|
|
6563
6578
|
signal: controller.signal
|
|
6564
6579
|
});
|
|
@@ -6569,103 +6584,103 @@ ${logic}` : ""}`;
|
|
|
6569
6584
|
}
|
|
6570
6585
|
const data = await response.json();
|
|
6571
6586
|
if (!data.choices || 0 === data.choices.length) throw new Error("No choices returned from Kimi Vision API");
|
|
6572
|
-
logger.k.info("[OpenAI] Kimi \u56FE\u50CF\u8BC6\u522B\u6210\u529F");
|
|
6587
|
+
logger.k.info("[OpenAI] Kimi Vision \u56FE\u50CF\u8BC6\u522B\u6210\u529F");
|
|
6573
6588
|
return data.choices[0].message.content;
|
|
6574
6589
|
} catch (kimiError) {
|
|
6575
|
-
logger.k.error("[OpenAI] Kimi \u8C03\u7528\u5931\u8D25\uFF0C\u56DE\u9000\u5230
|
|
6590
|
+
logger.k.error("[OpenAI] Kimi Vision \u8C03\u7528\u5931\u8D25\uFF0C\u56DE\u9000\u5230 GLM-4V", {
|
|
6576
6591
|
error: kimiError instanceof Error ? kimiError.message : String(kimiError)
|
|
6577
6592
|
});
|
|
6578
6593
|
try {
|
|
6579
|
-
logger.k.info("[OpenAI] \u5C1D\u8BD5\u4F7F\u7528
|
|
6580
|
-
const
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
});
|
|
6588
|
-
const workflowData = {
|
|
6589
|
-
imagePath: {
|
|
6590
|
-
type: "image",
|
|
6591
|
-
transfer_method: "local_file",
|
|
6592
|
-
upload_file_id: uploadResult.id
|
|
6594
|
+
logger.k.info("[OpenAI] \u5C1D\u8BD5\u4F7F\u7528 GLM-4V \u8FDB\u884C\u56FE\u50CF\u8BC6\u522B");
|
|
6595
|
+
const controller = new AbortController();
|
|
6596
|
+
const timeoutId = setTimeout(()=>controller.abort(), 30000);
|
|
6597
|
+
const response = await fetch(this.glm4vConfig.baseUrl, {
|
|
6598
|
+
method: "POST",
|
|
6599
|
+
headers: {
|
|
6600
|
+
"Content-Type": "application/json",
|
|
6601
|
+
Authorization: `Bearer ${this.glm4vConfig.apiKey}`
|
|
6593
6602
|
},
|
|
6594
|
-
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
|
|
6603
|
+
body: JSON.stringify({
|
|
6604
|
+
model: this.glm4vConfig.model,
|
|
6605
|
+
messages: [
|
|
6606
|
+
...system_prompt ? [
|
|
6607
|
+
{
|
|
6608
|
+
role: "system",
|
|
6609
|
+
content: system_prompt
|
|
6610
|
+
}
|
|
6611
|
+
] : [],
|
|
6612
|
+
{
|
|
6613
|
+
role: "user",
|
|
6614
|
+
content: [
|
|
6615
|
+
{
|
|
6616
|
+
type: "image_url",
|
|
6617
|
+
image_url: {
|
|
6618
|
+
url: image_base64
|
|
6619
|
+
}
|
|
6620
|
+
},
|
|
6621
|
+
{
|
|
6622
|
+
type: "text",
|
|
6623
|
+
text: prompt
|
|
6624
|
+
}
|
|
6625
|
+
]
|
|
6626
|
+
}
|
|
6627
|
+
],
|
|
6628
|
+
stream: false,
|
|
6629
|
+
temperature,
|
|
6630
|
+
max_tokens
|
|
6631
|
+
}),
|
|
6632
|
+
signal: controller.signal
|
|
6611
6633
|
});
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6634
|
+
clearTimeout(timeoutId);
|
|
6635
|
+
if (!response.ok) {
|
|
6636
|
+
const errorText = await response.text();
|
|
6637
|
+
throw new Error(`GLM-4V API error: ${response.status} ${response.statusText} - ${errorText}`);
|
|
6638
|
+
}
|
|
6639
|
+
const data = await response.json();
|
|
6640
|
+
if (!data.choices || 0 === data.choices.length) throw new Error("No choices returned from GLM-4V API");
|
|
6641
|
+
logger.k.info("[OpenAI] GLM-4V \u56FE\u50CF\u8BC6\u522B\u6210\u529F");
|
|
6642
|
+
return data.choices[0].message.content;
|
|
6643
|
+
} catch (glmError) {
|
|
6644
|
+
logger.k.error("[OpenAI] GLM-4V \u8C03\u7528\u5931\u8D25\uFF0C\u56DE\u9000\u5230 Dify", {
|
|
6645
|
+
error: glmError instanceof Error ? glmError.message : String(glmError)
|
|
6616
6646
|
});
|
|
6617
6647
|
try {
|
|
6618
|
-
logger.k.info("[OpenAI] \u5C1D\u8BD5\u4F7F\u7528
|
|
6619
|
-
const
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6648
|
+
logger.k.info("[OpenAI] \u5C1D\u8BD5\u4F7F\u7528 Dify \u5DE5\u4F5C\u6D41");
|
|
6649
|
+
const uploadResult = await uploadFile({
|
|
6650
|
+
appid: this.difyConfig.apiKey,
|
|
6651
|
+
filePath: image_path,
|
|
6652
|
+
user: "aico-mcp"
|
|
6653
|
+
});
|
|
6654
|
+
logger.k.info("[OpenAI] \u6587\u4EF6\u4E0A\u4F20\u6210\u529F", {
|
|
6655
|
+
upload_file_id: uploadResult.id
|
|
6656
|
+
});
|
|
6657
|
+
const workflowData = {
|
|
6658
|
+
imagePath: {
|
|
6659
|
+
type: "image",
|
|
6660
|
+
transfer_method: "local_file",
|
|
6661
|
+
upload_file_id: uploadResult.id
|
|
6626
6662
|
},
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
content: system_prompt
|
|
6634
|
-
}
|
|
6635
|
-
] : [],
|
|
6636
|
-
{
|
|
6637
|
-
role: "user",
|
|
6638
|
-
content: [
|
|
6639
|
-
{
|
|
6640
|
-
type: "image_url",
|
|
6641
|
-
image_url: {
|
|
6642
|
-
url: image_base64
|
|
6643
|
-
}
|
|
6644
|
-
},
|
|
6645
|
-
{
|
|
6646
|
-
type: "text",
|
|
6647
|
-
text: prompt
|
|
6648
|
-
}
|
|
6649
|
-
]
|
|
6650
|
-
}
|
|
6651
|
-
],
|
|
6652
|
-
stream: false,
|
|
6653
|
-
temperature,
|
|
6654
|
-
max_tokens
|
|
6655
|
-
}),
|
|
6656
|
-
signal: controller.signal
|
|
6663
|
+
context: prompt
|
|
6664
|
+
};
|
|
6665
|
+
const workflowResponse = await invokeFlow({
|
|
6666
|
+
appid: this.difyConfig.apiKey,
|
|
6667
|
+
data: workflowData,
|
|
6668
|
+
timeout: 120000
|
|
6657
6669
|
});
|
|
6658
|
-
|
|
6659
|
-
if (
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
if (
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6670
|
+
let summary = "";
|
|
6671
|
+
if ("string" == typeof workflowResponse && workflowResponse.length > 0) summary = workflowResponse;
|
|
6672
|
+
else if (workflowResponse?.outputs?.text) summary = workflowResponse.outputs.text;
|
|
6673
|
+
else if (workflowResponse?.data?.outputs?.text) summary = workflowResponse.data.outputs.text;
|
|
6674
|
+
else if (workflowResponse?.data?.text) summary = workflowResponse.data.text;
|
|
6675
|
+
else if (workflowResponse?.answer) summary = workflowResponse.answer;
|
|
6676
|
+
else if (workflowResponse?.status === "failed") throw new Error(`Dify\u{5DE5}\u{4F5C}\u{6D41}\u{6267}\u{884C}\u{5931}\u{8D25}: ${workflowResponse.error || "\u672A\u77E5\u9519\u8BEF"}`);
|
|
6677
|
+
if (!summary || 0 === summary.length) throw new Error("Dify\u5DE5\u4F5C\u6D41\u54CD\u5E94\u4E2D\u672A\u627E\u5230\u6709\u6548\u6587\u672C\u5185\u5BB9");
|
|
6678
|
+
logger.k.info("[OpenAI] Dify \u5206\u6790\u5B8C\u6210", {
|
|
6679
|
+
summary_length: summary.length
|
|
6680
|
+
});
|
|
6681
|
+
return summary;
|
|
6682
|
+
} catch (difyError) {
|
|
6683
|
+
throw new Error(`All vision services failed. Kimi: ${kimiError instanceof Error ? kimiError.message : String(kimiError)}, GLM-4V: ${glmError instanceof Error ? glmError.message : String(glmError)}, Dify: ${difyError instanceof Error ? difyError.message : String(difyError)}`);
|
|
6669
6684
|
}
|
|
6670
6685
|
}
|
|
6671
6686
|
}
|
|
@@ -6775,6 +6790,205 @@ ${logic}` : ""}`;
|
|
|
6775
6790
|
}
|
|
6776
6791
|
}
|
|
6777
6792
|
}
|
|
6793
|
+
async analyzeTextImage(imagePath, prompt, systemPrompt, temperature = 0.1, maxTokens = 8000, stop) {
|
|
6794
|
+
const fs = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "fs/promises?238c"));
|
|
6795
|
+
const pathModule = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "path?5fdd"));
|
|
6796
|
+
const imageBuffer = await fs.readFile(imagePath);
|
|
6797
|
+
const base64 = imageBuffer.toString("base64");
|
|
6798
|
+
const ext = pathModule.extname(imagePath).toLowerCase();
|
|
6799
|
+
const mimeType = ".png" === ext ? "image/png" : "image/jpeg";
|
|
6800
|
+
const image_base64 = `data:${mimeType};base64,${base64}`;
|
|
6801
|
+
logger.k.info("[OpenAI] \u4F7F\u7528\u5185\u7F51\u6A21\u578B\u5206\u6790\u7EAF\u6587\u5B57\u56FE\u7247");
|
|
6802
|
+
const [visionResult, ocrResult] = await Promise.all([
|
|
6803
|
+
this.callInternalVision(image_base64, prompt, systemPrompt, temperature, maxTokens, stop),
|
|
6804
|
+
this.callInternalOCR(image_base64)
|
|
6805
|
+
]);
|
|
6806
|
+
const coverage = this.calculateOcrCoverage(visionResult, ocrResult);
|
|
6807
|
+
logger.k.info("[OpenAI] \u7EAF\u6587\u5B57\u56FE\u7247\u5206\u6790\u5B8C\u6210", {
|
|
6808
|
+
visionLength: visionResult.length,
|
|
6809
|
+
ocrLength: ocrResult.length,
|
|
6810
|
+
coverage: `${(100 * coverage).toFixed(1)}%`
|
|
6811
|
+
});
|
|
6812
|
+
let finalResult = visionResult;
|
|
6813
|
+
if (coverage < 0.7 && ocrResult.length > 0.5 * visionResult.length) {
|
|
6814
|
+
logger.k.warn("[OpenAI] \u89C6\u89C9\u6A21\u578B\u8986\u76D6\u7387\u4F4E\uFF0C\u4F7F\u7528 OCR \u7ED3\u679C\u8865\u5145");
|
|
6815
|
+
finalResult = this.mergeVisionAndOcr(visionResult, ocrResult);
|
|
6816
|
+
}
|
|
6817
|
+
return {
|
|
6818
|
+
result: finalResult,
|
|
6819
|
+
ocrResult,
|
|
6820
|
+
coverage
|
|
6821
|
+
};
|
|
6822
|
+
}
|
|
6823
|
+
async analyzeComplexImage(imagePath, prompt, systemPrompt, temperature = 0.1, maxTokens = 8000) {
|
|
6824
|
+
logger.k.info("[OpenAI] \u4F7F\u7528 Kimi \u5206\u6790\u590D\u6742\u56FE\u7247");
|
|
6825
|
+
return this.analyzeImageWithPath({
|
|
6826
|
+
image_path: imagePath,
|
|
6827
|
+
prompt,
|
|
6828
|
+
system_prompt: systemPrompt,
|
|
6829
|
+
temperature,
|
|
6830
|
+
max_tokens: maxTokens
|
|
6831
|
+
});
|
|
6832
|
+
}
|
|
6833
|
+
async getInternalAgent() {
|
|
6834
|
+
const https = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "https"));
|
|
6835
|
+
return new https.Agent({
|
|
6836
|
+
rejectUnauthorized: false
|
|
6837
|
+
});
|
|
6838
|
+
}
|
|
6839
|
+
async callInternalVision(image_base64, prompt, systemPrompt, temperature = 0.1, maxTokens = 8000, stop) {
|
|
6840
|
+
const controller = new AbortController();
|
|
6841
|
+
const timeoutId = setTimeout(()=>controller.abort(), 60000);
|
|
6842
|
+
try {
|
|
6843
|
+
await this.getInternalAgent();
|
|
6844
|
+
const response = await fetch(this.internalConfig.baseUrl, {
|
|
6845
|
+
method: "POST",
|
|
6846
|
+
headers: {
|
|
6847
|
+
"Content-Type": "application/json",
|
|
6848
|
+
Authorization: `Bearer ${this.internalConfig.apiKey}`
|
|
6849
|
+
},
|
|
6850
|
+
body: JSON.stringify({
|
|
6851
|
+
model: this.internalConfig.visionModel,
|
|
6852
|
+
messages: [
|
|
6853
|
+
...systemPrompt ? [
|
|
6854
|
+
{
|
|
6855
|
+
role: "system",
|
|
6856
|
+
content: systemPrompt
|
|
6857
|
+
}
|
|
6858
|
+
] : [],
|
|
6859
|
+
{
|
|
6860
|
+
role: "user",
|
|
6861
|
+
content: [
|
|
6862
|
+
{
|
|
6863
|
+
type: "image_url",
|
|
6864
|
+
image_url: {
|
|
6865
|
+
url: image_base64
|
|
6866
|
+
}
|
|
6867
|
+
},
|
|
6868
|
+
{
|
|
6869
|
+
type: "text",
|
|
6870
|
+
text: prompt
|
|
6871
|
+
}
|
|
6872
|
+
]
|
|
6873
|
+
}
|
|
6874
|
+
],
|
|
6875
|
+
stream: false,
|
|
6876
|
+
temperature,
|
|
6877
|
+
max_tokens: maxTokens,
|
|
6878
|
+
...stop ? {
|
|
6879
|
+
stop
|
|
6880
|
+
} : {}
|
|
6881
|
+
}),
|
|
6882
|
+
signal: controller.signal,
|
|
6883
|
+
dispatcher: new (await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "undici"))).Agent({
|
|
6884
|
+
connect: {
|
|
6885
|
+
rejectUnauthorized: false
|
|
6886
|
+
}
|
|
6887
|
+
})
|
|
6888
|
+
});
|
|
6889
|
+
clearTimeout(timeoutId);
|
|
6890
|
+
if (!response.ok) {
|
|
6891
|
+
const errorText = await response.text();
|
|
6892
|
+
throw new Error(`Internal Vision API error: ${response.status} - ${errorText}`);
|
|
6893
|
+
}
|
|
6894
|
+
const data = await response.json();
|
|
6895
|
+
if (!data.choices || 0 === data.choices.length) throw new Error("No choices returned from Internal Vision API");
|
|
6896
|
+
logger.k.info("[OpenAI] \u5185\u7F51\u89C6\u89C9\u6A21\u578B\u8C03\u7528\u6210\u529F");
|
|
6897
|
+
return data.choices[0].message.content;
|
|
6898
|
+
} catch (error) {
|
|
6899
|
+
clearTimeout(timeoutId);
|
|
6900
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
6901
|
+
logger.k.error("[OpenAI] \u5185\u7F51\u89C6\u89C9\u6A21\u578B\u8C03\u7528\u5931\u8D25", {
|
|
6902
|
+
error: errorMsg,
|
|
6903
|
+
baseUrl: this.internalConfig.baseUrl,
|
|
6904
|
+
model: this.internalConfig.visionModel
|
|
6905
|
+
});
|
|
6906
|
+
throw error;
|
|
6907
|
+
}
|
|
6908
|
+
}
|
|
6909
|
+
async callInternalOCR(image_base64, stop) {
|
|
6910
|
+
const controller = new AbortController();
|
|
6911
|
+
const timeoutId = setTimeout(()=>controller.abort(), 30000);
|
|
6912
|
+
const ocrPrompt = `\u{8BF7}\u{63D0}\u{53D6}\u{56FE}\u{7247}\u{4E2D}\u{7684}\u{6240}\u{6709}\u{6587}\u{5B57}\u{5185}\u{5BB9}\u{FF0C}\u{539F}\u{6587}\u{7167}\u{6284}\u{FF0C}\u{4FDD}\u{6301}\u{683C}\u{5F0F}\u{3002}\u{53EA}\u{8F93}\u{51FA}\u{6587}\u{5B57}\u{FF0C}\u{4E0D}\u{8981}\u{6DFB}\u{52A0}\u{4EFB}\u{4F55}\u{89E3}\u{91CA}\u{3002}`;
|
|
6913
|
+
try {
|
|
6914
|
+
const response = await fetch(this.internalConfig.baseUrl, {
|
|
6915
|
+
method: "POST",
|
|
6916
|
+
headers: {
|
|
6917
|
+
"Content-Type": "application/json",
|
|
6918
|
+
Authorization: `Bearer ${this.internalConfig.apiKey}`
|
|
6919
|
+
},
|
|
6920
|
+
body: JSON.stringify({
|
|
6921
|
+
model: this.internalConfig.ocrModel,
|
|
6922
|
+
messages: [
|
|
6923
|
+
{
|
|
6924
|
+
role: "user",
|
|
6925
|
+
content: [
|
|
6926
|
+
{
|
|
6927
|
+
type: "image_url",
|
|
6928
|
+
image_url: {
|
|
6929
|
+
url: image_base64
|
|
6930
|
+
}
|
|
6931
|
+
},
|
|
6932
|
+
{
|
|
6933
|
+
type: "text",
|
|
6934
|
+
text: ocrPrompt
|
|
6935
|
+
}
|
|
6936
|
+
]
|
|
6937
|
+
}
|
|
6938
|
+
],
|
|
6939
|
+
stream: false,
|
|
6940
|
+
temperature: 0,
|
|
6941
|
+
max_tokens: 4000,
|
|
6942
|
+
...stop ? {
|
|
6943
|
+
stop
|
|
6944
|
+
} : {
|
|
6945
|
+
stop: [
|
|
6946
|
+
"<<<END>>>"
|
|
6947
|
+
]
|
|
6948
|
+
}
|
|
6949
|
+
}),
|
|
6950
|
+
signal: controller.signal,
|
|
6951
|
+
dispatcher: new (await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "undici"))).Agent({
|
|
6952
|
+
connect: {
|
|
6953
|
+
rejectUnauthorized: false
|
|
6954
|
+
}
|
|
6955
|
+
})
|
|
6956
|
+
});
|
|
6957
|
+
clearTimeout(timeoutId);
|
|
6958
|
+
if (!response.ok) {
|
|
6959
|
+
const errorText = await response.text();
|
|
6960
|
+
throw new Error(`Internal OCR API error: ${response.status} - ${errorText}`);
|
|
6961
|
+
}
|
|
6962
|
+
const data = await response.json();
|
|
6963
|
+
if (!data.choices || 0 === data.choices.length) throw new Error("No choices returned from Internal OCR API");
|
|
6964
|
+
logger.k.info("[OpenAI] \u5185\u7F51 OCR \u6A21\u578B\u8C03\u7528\u6210\u529F");
|
|
6965
|
+
return data.choices[0].message.content;
|
|
6966
|
+
} catch (error) {
|
|
6967
|
+
clearTimeout(timeoutId);
|
|
6968
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
6969
|
+
logger.k.warn("[OpenAI] \u5185\u7F51 OCR \u8C03\u7528\u5931\u8D25", {
|
|
6970
|
+
error: errorMsg,
|
|
6971
|
+
baseUrl: this.internalConfig.baseUrl,
|
|
6972
|
+
model: this.internalConfig.ocrModel
|
|
6973
|
+
});
|
|
6974
|
+
return "";
|
|
6975
|
+
}
|
|
6976
|
+
}
|
|
6977
|
+
calculateOcrCoverage(visionResult, ocrResult) {
|
|
6978
|
+
if (!ocrResult || 0 === ocrResult.length) return 1;
|
|
6979
|
+
const ocrLines = ocrResult.split('\n').map((line)=>line.trim()).filter((line)=>line.length > 5);
|
|
6980
|
+
if (0 === ocrLines.length) return 1;
|
|
6981
|
+
let matchedCount = 0;
|
|
6982
|
+
for (const line of ocrLines){
|
|
6983
|
+
const sample = line.length > 10 ? line.substring(Math.floor(line.length / 2) - 5, Math.floor(line.length / 2) + 5) : line;
|
|
6984
|
+
if (visionResult.includes(sample)) matchedCount++;
|
|
6985
|
+
}
|
|
6986
|
+
return matchedCount / ocrLines.length;
|
|
6987
|
+
}
|
|
6988
|
+
mergeVisionAndOcr(visionResult, ocrResult) {
|
|
6989
|
+
if (ocrResult.length > visionResult.length) return ocrResult;
|
|
6990
|
+
return visionResult;
|
|
6991
|
+
}
|
|
6778
6992
|
}
|
|
6779
6993
|
const openAIService = new OpenAIService();
|
|
6780
6994
|
const renderRequirementDocumentTool = {
|
|
@@ -7140,7 +7354,7 @@ ${chaptersContent}
|
|
|
7140
7354
|
context;
|
|
7141
7355
|
constructor(message, code, context){
|
|
7142
7356
|
super(message), this.code = code, this.context = context;
|
|
7143
|
-
this.name =
|
|
7357
|
+
this.name = "ImageAnalysisError";
|
|
7144
7358
|
}
|
|
7145
7359
|
}
|
|
7146
7360
|
var types_AnalysisErrorCodes = /*#__PURE__*/ function(AnalysisErrorCodes) {
|
|
@@ -7153,343 +7367,602 @@ ${chaptersContent}
|
|
|
7153
7367
|
return AnalysisErrorCodes;
|
|
7154
7368
|
}({});
|
|
7155
7369
|
const SUPPORTED_IMAGE_FORMATS = [
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7370
|
+
"jpg",
|
|
7371
|
+
"jpeg",
|
|
7372
|
+
"png",
|
|
7373
|
+
"gif",
|
|
7374
|
+
"bmp",
|
|
7375
|
+
"tiff",
|
|
7376
|
+
"tif",
|
|
7377
|
+
"webp"
|
|
7164
7378
|
];
|
|
7165
|
-
const
|
|
7166
|
-
|
|
7167
|
-
overlapRatio: 0.
|
|
7168
|
-
minResultLength: 200
|
|
7379
|
+
const DEFAULT_SEGMENT_CONFIG = {
|
|
7380
|
+
maxHeight: 1500,
|
|
7381
|
+
overlapRatio: 0.1
|
|
7169
7382
|
};
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
|
|
7192
|
-
imagePath: imagePath,
|
|
7193
|
-
processingTimeMs: processingTime
|
|
7194
|
-
});
|
|
7195
|
-
return result;
|
|
7196
|
-
} catch (error) {
|
|
7197
|
-
logger.k.error("\u56FE\u7247\u5185\u5BB9\u5206\u6790\u5931\u8D25", {
|
|
7198
|
-
error,
|
|
7199
|
-
params: {
|
|
7200
|
-
image_path: imagePath
|
|
7201
|
-
}
|
|
7202
|
-
});
|
|
7203
|
-
throw error;
|
|
7204
|
-
}
|
|
7205
|
-
}
|
|
7206
|
-
async performSmartAnalysis(imagePath, context, basicInfo) {
|
|
7207
|
-
try {
|
|
7208
|
-
logger.k.info("\u5F00\u59CB\u6574\u4F53\u56FE\u7247\u8BC6\u522B", {
|
|
7209
|
-
imagePath
|
|
7210
|
-
});
|
|
7211
|
-
const initialResult = await this.performAIAnalysisWithCompletenessCheck(imagePath, context);
|
|
7212
|
-
const completenessCheck = this.checkCompleteness(initialResult);
|
|
7213
|
-
if (completenessCheck.complete) {
|
|
7214
|
-
logger.k.info("\u56FE\u7247\u8BC6\u522B\u5B8C\u6574\uFF0C\u65E0\u9700\u5206\u5757");
|
|
7215
|
-
return {
|
|
7216
|
-
summary: completenessCheck.content,
|
|
7217
|
-
details: {},
|
|
7218
|
-
tags: []
|
|
7219
|
-
};
|
|
7220
|
-
}
|
|
7221
|
-
logger.k.info("\u56FE\u7247\u8BC6\u522B\u4E0D\u5B8C\u6574\uFF0C\u542F\u7528\u5206\u5757\u8BC6\u522B", {
|
|
7222
|
-
reason: completenessCheck.reason,
|
|
7223
|
-
width: basicInfo.dimensions.width,
|
|
7224
|
-
height: basicInfo.dimensions.height
|
|
7225
|
-
});
|
|
7226
|
-
const chunkedResult = await this.analyzeWithChunks(imagePath, context, basicInfo);
|
|
7227
|
-
return {
|
|
7228
|
-
summary: chunkedResult,
|
|
7229
|
-
details: {
|
|
7230
|
-
chunked: true,
|
|
7231
|
-
reason: completenessCheck.reason
|
|
7232
|
-
},
|
|
7233
|
-
tags: []
|
|
7234
|
-
};
|
|
7235
|
-
} catch (error) {
|
|
7236
|
-
logger.k.error("\u667A\u80FD\u5206\u6790\u5931\u8D25", {
|
|
7237
|
-
error,
|
|
7238
|
-
imagePath
|
|
7239
|
-
});
|
|
7240
|
-
throw new ImageAnalysisError("\u8BC6\u522B\u56FE\u7247\u5931\u8D25", types_AnalysisErrorCodes.ANALYSIS_FAILED, {
|
|
7241
|
-
originalError: error
|
|
7242
|
-
});
|
|
7243
|
-
}
|
|
7383
|
+
const LONG_IMAGE_THRESHOLD = {
|
|
7384
|
+
minHeight: 2000,
|
|
7385
|
+
minAspectRatio: 2
|
|
7386
|
+
};
|
|
7387
|
+
async function getImageInfo(imagePath) {
|
|
7388
|
+
try {
|
|
7389
|
+
const metadata = await external_sharp_default()(imagePath).metadata();
|
|
7390
|
+
const stats = await promises_.stat(imagePath);
|
|
7391
|
+
return {
|
|
7392
|
+
path: imagePath,
|
|
7393
|
+
format: metadata.format || "unknown",
|
|
7394
|
+
dimensions: {
|
|
7395
|
+
width: metadata.width || 0,
|
|
7396
|
+
height: metadata.height || 0
|
|
7397
|
+
},
|
|
7398
|
+
file_size: stats.size
|
|
7399
|
+
};
|
|
7400
|
+
} catch (error) {
|
|
7401
|
+
throw new ImageAnalysisError(`\u{65E0}\u{6CD5}\u{8BFB}\u{53D6}\u{56FE}\u{7247}\u{4FE1}\u{606F}: ${imagePath}`, types_AnalysisErrorCodes.IMAGE_CORRUPTED, {
|
|
7402
|
+
imagePath,
|
|
7403
|
+
originalError: error
|
|
7404
|
+
});
|
|
7244
7405
|
}
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
|
|
7248
|
-
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
5. \u{56FE}\u{7247}/\u{56FE}\u{6807}\u{FF1A}\u{7528} [\u{56FE}\u{7247}: \u{7B80}\u{8981}\u{63CF}\u{8FF0}] \u{6807}\u{6CE8}
|
|
7258
|
-
|
|
7259
|
-
\u{7981}\u{6B62}\u{FF1A}
|
|
7260
|
-
- \u{7981}\u{6B62}\u{4F7F}\u{7528}"\u{9875}\u{9762}\u{7ED3}\u{6784}"\u{3001}"\u{6838}\u{5FC3}\u{5185}\u{5BB9}"\u{3001}"\u{4E3B}\u{8981}\u{529F}\u{80FD}"\u{7B49}\u{603B}\u{7ED3}\u{6027}\u{8BCD}\u{6C47}\u{FF08}\u{9664}\u{975E}\u{56FE}\u{7247}\u{4E2D}\u{539F}\u{6587}\u{5C31}\u{6709}\u{FF09}
|
|
7261
|
-
- \u{7981}\u{6B62}\u{6DFB}\u{52A0}\u{4EFB}\u{4F55}\u{89E3}\u{91CA}\u{3001}\u{5206}\u{6790}\u{3001}\u{8BC4}\u{8BBA}
|
|
7262
|
-
- \u{7981}\u{6B62}\u{7701}\u{7565}\u{4EFB}\u{4F55}\u{5185}\u{5BB9}
|
|
7263
|
-
|
|
7264
|
-
${context ? `\u{8865}\u{5145}\u{8981}\u{6C42}\u{FF1A}${context}\n\n` : ''}\u{73B0}\u{5728}\u{5F00}\u{59CB}\u{9010}\u{5B57}\u{6284}\u{5F55}\u{FF1A}`;
|
|
7265
|
-
const aiResponse = await openAIService.analyzeImageWithPath({
|
|
7266
|
-
image_path: imagePath,
|
|
7267
|
-
prompt: userPrompt,
|
|
7268
|
-
system_prompt: systemPrompt,
|
|
7269
|
-
temperature: 0,
|
|
7270
|
-
max_tokens: 8000
|
|
7406
|
+
}
|
|
7407
|
+
function image_processor_isLongImage(info) {
|
|
7408
|
+
const { width, height } = info.dimensions;
|
|
7409
|
+
const aspectRatio = height / width;
|
|
7410
|
+
return height > LONG_IMAGE_THRESHOLD.minHeight && aspectRatio > LONG_IMAGE_THRESHOLD.minAspectRatio;
|
|
7411
|
+
}
|
|
7412
|
+
async function validateImage(imagePath) {
|
|
7413
|
+
try {
|
|
7414
|
+
await promises_.access(imagePath);
|
|
7415
|
+
} catch {
|
|
7416
|
+
throw new ImageAnalysisError(`\u{56FE}\u{7247}\u{6587}\u{4EF6}\u{4E0D}\u{5B58}\u{5728}: ${imagePath}`, types_AnalysisErrorCodes.FILE_NOT_FOUND, {
|
|
7417
|
+
imagePath
|
|
7271
7418
|
});
|
|
7272
|
-
return aiResponse.trim();
|
|
7273
7419
|
}
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7420
|
+
const ext = external_path_.extname(imagePath).slice(1).toLowerCase();
|
|
7421
|
+
if (!SUPPORTED_IMAGE_FORMATS.includes(ext)) throw new ImageAnalysisError(`\u{4E0D}\u{652F}\u{6301}\u{7684}\u{56FE}\u{7247}\u{683C}\u{5F0F}: ${ext}`, types_AnalysisErrorCodes.UNSUPPORTED_FORMAT, {
|
|
7422
|
+
format: ext,
|
|
7423
|
+
supportedFormats: SUPPORTED_IMAGE_FORMATS
|
|
7424
|
+
});
|
|
7425
|
+
}
|
|
7426
|
+
async function splitLongImage(imagePath, info, config = DEFAULT_SEGMENT_CONFIG) {
|
|
7427
|
+
const { width, height } = info.dimensions;
|
|
7428
|
+
const { maxHeight, overlapRatio } = config;
|
|
7429
|
+
const overlap = Math.floor(maxHeight * overlapRatio);
|
|
7430
|
+
const segments = [];
|
|
7431
|
+
let currentY = 0;
|
|
7432
|
+
let index = 0;
|
|
7433
|
+
while(currentY < height){
|
|
7434
|
+
const endY = Math.min(currentY + maxHeight, height);
|
|
7435
|
+
const segmentHeight = endY - currentY;
|
|
7436
|
+
const buffer = await external_sharp_default()(imagePath).extract({
|
|
7437
|
+
left: 0,
|
|
7438
|
+
top: currentY,
|
|
7439
|
+
width: width,
|
|
7440
|
+
height: segmentHeight
|
|
7441
|
+
}).jpeg({
|
|
7442
|
+
quality: 90
|
|
7443
|
+
}).toBuffer();
|
|
7444
|
+
segments.push({
|
|
7445
|
+
index,
|
|
7446
|
+
total: 0,
|
|
7447
|
+
startY: currentY,
|
|
7448
|
+
endY,
|
|
7449
|
+
buffer
|
|
7450
|
+
});
|
|
7451
|
+
currentY = endY - overlap;
|
|
7452
|
+
if (currentY >= height - overlap) break;
|
|
7453
|
+
index++;
|
|
7454
|
+
}
|
|
7455
|
+
const total = segments.length;
|
|
7456
|
+
segments.forEach((s)=>s.total = total);
|
|
7457
|
+
logger.k.info("\u957F\u56FE\u5206\u6BB5\u5B8C\u6210", {
|
|
7458
|
+
width,
|
|
7459
|
+
height,
|
|
7460
|
+
segments: total
|
|
7461
|
+
});
|
|
7462
|
+
return segments;
|
|
7463
|
+
}
|
|
7464
|
+
async function saveSegmentToTemp(segment) {
|
|
7465
|
+
const tempPath = external_path_.join("/tmp", `segment_${Date.now()}_${segment.index}.jpg`);
|
|
7466
|
+
await promises_.writeFile(tempPath, segment.buffer);
|
|
7467
|
+
return tempPath;
|
|
7468
|
+
}
|
|
7469
|
+
async function cleanupTempFile(filePath) {
|
|
7470
|
+
try {
|
|
7471
|
+
await promises_.unlink(filePath);
|
|
7472
|
+
} catch {}
|
|
7473
|
+
}
|
|
7474
|
+
function mergeSegmentResults(results) {
|
|
7475
|
+
if (0 === results.length) return "";
|
|
7476
|
+
if (1 === results.length) return results[0];
|
|
7477
|
+
let merged = results[0];
|
|
7478
|
+
for(let i = 1; i < results.length; i++){
|
|
7479
|
+
const current = results[i];
|
|
7480
|
+
const overlapLen = findTextOverlap(merged, current);
|
|
7481
|
+
if (overlapLen > 0) merged += "\n" + current.substring(overlapLen);
|
|
7482
|
+
else merged += "\n\n" + current;
|
|
7483
|
+
}
|
|
7484
|
+
return merged.trim();
|
|
7485
|
+
}
|
|
7486
|
+
function findTextOverlap(prev, curr) {
|
|
7487
|
+
const prevLines = prev.split("\n").slice(-10);
|
|
7488
|
+
const currLines = curr.split("\n").slice(0, 10);
|
|
7489
|
+
for(let i = Math.min(prevLines.length, currLines.length); i >= 2; i--){
|
|
7490
|
+
const prevTail = prevLines.slice(-i).map((l)=>l.trim()).join("\n");
|
|
7491
|
+
const currHead = currLines.slice(0, i).map((l)=>l.trim()).join("\n");
|
|
7492
|
+
if (prevTail === currHead) return currLines.slice(0, i).join("\n").length;
|
|
7493
|
+
}
|
|
7494
|
+
return 0;
|
|
7495
|
+
}
|
|
7496
|
+
const INTERNAL_CONFIG = {
|
|
7497
|
+
apiKey: "sk-3W5NXAzeXX9mNP5yppQwPt6cnEoSK03u5NgiNW1Hsi41Tniu",
|
|
7498
|
+
baseUrl: "https://aiproxy.jla.petrotech.cnpc/v1/chat/completions",
|
|
7499
|
+
visionModel: "qwen2-7b-vl",
|
|
7500
|
+
ocrModel: "deepseek-ocr"
|
|
7501
|
+
};
|
|
7502
|
+
const DIFY_CONFIG = {
|
|
7503
|
+
apiKey: "app-xPG7ROh2YaAzR3v9vKnhAWpz"
|
|
7504
|
+
};
|
|
7505
|
+
const KIMI_CONFIG = {
|
|
7506
|
+
apiKey: "sk-fp8wJSigZBEP3x8y6MAZWGPuVIHJ5PDZtX9lMQQk8hjP2R0u",
|
|
7507
|
+
baseUrl: "https://api.moonshot.cn/v1/chat/completions",
|
|
7508
|
+
model: "moonshot-v1-128k-vision-preview"
|
|
7509
|
+
};
|
|
7510
|
+
const GLM_CONFIG = {
|
|
7511
|
+
apiKey: "fb26a7ff758c3974e43bfff49a684dd3.apcuRq6v6RvwuJDu",
|
|
7512
|
+
baseUrl: "https://open.bigmodel.cn/api/paas/v4/chat/completions",
|
|
7513
|
+
model: "glm-4v-flash"
|
|
7514
|
+
};
|
|
7515
|
+
async function getHttpsAgent() {
|
|
7516
|
+
const { Agent } = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "undici"));
|
|
7517
|
+
return new Agent({
|
|
7518
|
+
connect: {
|
|
7519
|
+
rejectUnauthorized: false
|
|
7520
|
+
}
|
|
7521
|
+
});
|
|
7522
|
+
}
|
|
7523
|
+
async function imageToBase64(imagePath) {
|
|
7524
|
+
const buffer = await promises_.readFile(imagePath);
|
|
7525
|
+
const ext = external_path_.extname(imagePath).toLowerCase();
|
|
7526
|
+
const mimeType = ".png" === ext ? "image/png" : "image/jpeg";
|
|
7527
|
+
return `data:${mimeType};base64,${buffer.toString("base64")}`;
|
|
7528
|
+
}
|
|
7529
|
+
function bufferToBase64(buffer, format = "jpeg") {
|
|
7530
|
+
const mimeType = "png" === format ? "image/png" : "image/jpeg";
|
|
7531
|
+
return `data:${mimeType};base64,${buffer.toString("base64")}`;
|
|
7532
|
+
}
|
|
7533
|
+
const SYSTEM_PROMPT = `You must interpret and analyze images strictly according to the assigned task.
|
|
7534
|
+
When an image is provided, your role is to parse the image content only within the scope of the user's instructions.
|
|
7535
|
+
Do not ignore or deviate from the task.
|
|
7536
|
+
Always ensure that your response reflects a clear, accurate interpretation of the image aligned with the given objective.`;
|
|
7537
|
+
async function callInternalVision(imageBase64, prompt, maxTokens = 8000) {
|
|
7538
|
+
const controller = new AbortController();
|
|
7539
|
+
const timeoutId = setTimeout(()=>controller.abort(), 90000);
|
|
7540
|
+
try {
|
|
7541
|
+
const agent = await getHttpsAgent();
|
|
7542
|
+
const response = await fetch(INTERNAL_CONFIG.baseUrl, {
|
|
7543
|
+
method: "POST",
|
|
7544
|
+
headers: {
|
|
7545
|
+
"Content-Type": "application/json",
|
|
7546
|
+
Authorization: `Bearer ${INTERNAL_CONFIG.apiKey}`
|
|
7547
|
+
},
|
|
7548
|
+
body: JSON.stringify({
|
|
7549
|
+
model: INTERNAL_CONFIG.visionModel,
|
|
7550
|
+
messages: [
|
|
7551
|
+
{
|
|
7552
|
+
role: "system",
|
|
7553
|
+
content: SYSTEM_PROMPT
|
|
7554
|
+
},
|
|
7555
|
+
{
|
|
7556
|
+
role: "user",
|
|
7557
|
+
content: [
|
|
7558
|
+
{
|
|
7559
|
+
type: "image_url",
|
|
7560
|
+
image_url: {
|
|
7561
|
+
url: imageBase64
|
|
7562
|
+
}
|
|
7563
|
+
},
|
|
7564
|
+
{
|
|
7565
|
+
type: "text",
|
|
7566
|
+
text: prompt
|
|
7567
|
+
}
|
|
7568
|
+
]
|
|
7569
|
+
}
|
|
7570
|
+
],
|
|
7571
|
+
temperature: 0.2,
|
|
7572
|
+
max_tokens: maxTokens
|
|
7573
|
+
}),
|
|
7574
|
+
signal: controller.signal,
|
|
7575
|
+
dispatcher: agent
|
|
7576
|
+
});
|
|
7577
|
+
clearTimeout(timeoutId);
|
|
7578
|
+
if (!response.ok) {
|
|
7579
|
+
const errorText = await response.text();
|
|
7580
|
+
throw new Error(`\u{5185}\u{7F51}\u{89C6}\u{89C9}\u{6A21}\u{578B}\u{9519}\u{8BEF}: ${response.status} - ${errorText}`);
|
|
7581
|
+
}
|
|
7582
|
+
const data = await response.json();
|
|
7583
|
+
const content = data.choices?.[0]?.message?.content || "";
|
|
7584
|
+
if (!content) throw new Error("\u5185\u7F51\u89C6\u89C9\u6A21\u578B\u8FD4\u56DE\u7A7A\u7ED3\u679C");
|
|
7585
|
+
logger.k.info("\u5185\u7F51\u89C6\u89C9\u6A21\u578B\u8C03\u7528\u6210\u529F", {
|
|
7586
|
+
contentLength: content.length
|
|
7587
|
+
});
|
|
7588
|
+
return content;
|
|
7589
|
+
} catch (error) {
|
|
7590
|
+
clearTimeout(timeoutId);
|
|
7591
|
+
throw error;
|
|
7592
|
+
}
|
|
7593
|
+
}
|
|
7594
|
+
async function callInternalOCR(imageBase64, prompt, maxTokens = 4000) {
|
|
7595
|
+
const controller = new AbortController();
|
|
7596
|
+
const timeoutId = setTimeout(()=>controller.abort(), 60000);
|
|
7597
|
+
try {
|
|
7598
|
+
const agent = await getHttpsAgent();
|
|
7599
|
+
const response = await fetch(INTERNAL_CONFIG.baseUrl, {
|
|
7600
|
+
method: "POST",
|
|
7601
|
+
headers: {
|
|
7602
|
+
"Content-Type": "application/json",
|
|
7603
|
+
Authorization: `Bearer ${INTERNAL_CONFIG.apiKey}`
|
|
7604
|
+
},
|
|
7605
|
+
body: JSON.stringify({
|
|
7606
|
+
model: INTERNAL_CONFIG.ocrModel,
|
|
7607
|
+
messages: [
|
|
7608
|
+
{
|
|
7609
|
+
role: "system",
|
|
7610
|
+
content: SYSTEM_PROMPT
|
|
7611
|
+
},
|
|
7612
|
+
{
|
|
7613
|
+
role: "user",
|
|
7614
|
+
content: [
|
|
7615
|
+
{
|
|
7616
|
+
type: "image_url",
|
|
7617
|
+
image_url: {
|
|
7618
|
+
url: imageBase64
|
|
7619
|
+
}
|
|
7620
|
+
},
|
|
7621
|
+
{
|
|
7622
|
+
type: "text",
|
|
7623
|
+
text: prompt
|
|
7624
|
+
}
|
|
7625
|
+
]
|
|
7626
|
+
}
|
|
7627
|
+
],
|
|
7628
|
+
temperature: 0.2,
|
|
7629
|
+
max_tokens: maxTokens
|
|
7630
|
+
}),
|
|
7631
|
+
signal: controller.signal,
|
|
7632
|
+
dispatcher: agent
|
|
7633
|
+
});
|
|
7634
|
+
clearTimeout(timeoutId);
|
|
7635
|
+
if (!response.ok) throw new Error(`\u{5185}\u{7F51}OCR\u{9519}\u{8BEF}: ${response.status}`);
|
|
7636
|
+
const data = await response.json();
|
|
7637
|
+
const content = data.choices?.[0]?.message?.content || "";
|
|
7638
|
+
logger.k.info("\u5185\u7F51OCR\u8C03\u7528\u6210\u529F", {
|
|
7639
|
+
contentLength: content.length
|
|
7640
|
+
});
|
|
7641
|
+
return content;
|
|
7642
|
+
} catch (error) {
|
|
7643
|
+
clearTimeout(timeoutId);
|
|
7644
|
+
logger.k.warn("\u5185\u7F51OCR\u8C03\u7528\u5931\u8D25", {
|
|
7645
|
+
error
|
|
7646
|
+
});
|
|
7647
|
+
return "";
|
|
7648
|
+
}
|
|
7649
|
+
}
|
|
7650
|
+
async function callDifyWorkflow(imagePath, context) {
|
|
7651
|
+
try {
|
|
7652
|
+
const uploadResult = await uploadFile({
|
|
7653
|
+
appid: DIFY_CONFIG.apiKey,
|
|
7654
|
+
filePath: imagePath,
|
|
7655
|
+
user: "aico-mcp"
|
|
7656
|
+
});
|
|
7657
|
+
logger.k.info("Dify \u6587\u4EF6\u4E0A\u4F20\u6210\u529F", {
|
|
7658
|
+
fileId: uploadResult.id
|
|
7659
|
+
});
|
|
7660
|
+
const workflowData = {
|
|
7661
|
+
imagePath: {
|
|
7662
|
+
type: "image",
|
|
7663
|
+
transfer_method: "local_file",
|
|
7664
|
+
upload_file_id: uploadResult.id
|
|
7665
|
+
},
|
|
7666
|
+
context: context
|
|
7278
7667
|
};
|
|
7279
|
-
const
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7668
|
+
const response = await invokeFlow({
|
|
7669
|
+
appid: DIFY_CONFIG.apiKey,
|
|
7670
|
+
data: workflowData,
|
|
7671
|
+
timeout: 120000
|
|
7672
|
+
});
|
|
7673
|
+
let content = "";
|
|
7674
|
+
if ("string" == typeof response && response.length > 0) content = response;
|
|
7675
|
+
else if (response?.outputs?.text) content = response.outputs.text;
|
|
7676
|
+
else if (response?.data?.outputs?.text) content = response.data.outputs.text;
|
|
7677
|
+
if (!content) throw new Error("Dify \u54CD\u5E94\u4E2D\u672A\u627E\u5230\u6709\u6548\u5185\u5BB9");
|
|
7678
|
+
logger.k.info("Dify \u5DE5\u4F5C\u6D41\u8C03\u7528\u6210\u529F", {
|
|
7679
|
+
contentLength: content.length
|
|
7680
|
+
});
|
|
7681
|
+
return content;
|
|
7682
|
+
} catch (error) {
|
|
7683
|
+
throw error;
|
|
7684
|
+
}
|
|
7685
|
+
}
|
|
7686
|
+
async function callKimiVision(imageBase64, prompt, maxTokens = 8000) {
|
|
7687
|
+
const controller = new AbortController();
|
|
7688
|
+
const timeoutId = setTimeout(()=>controller.abort(), 90000);
|
|
7689
|
+
try {
|
|
7690
|
+
const response = await fetch(KIMI_CONFIG.baseUrl, {
|
|
7691
|
+
method: "POST",
|
|
7692
|
+
headers: {
|
|
7693
|
+
"Content-Type": "application/json",
|
|
7694
|
+
Authorization: `Bearer ${KIMI_CONFIG.apiKey}`
|
|
7695
|
+
},
|
|
7696
|
+
body: JSON.stringify({
|
|
7697
|
+
model: KIMI_CONFIG.model,
|
|
7698
|
+
messages: [
|
|
7699
|
+
{
|
|
7700
|
+
role: "system",
|
|
7701
|
+
content: SYSTEM_PROMPT
|
|
7702
|
+
},
|
|
7703
|
+
{
|
|
7704
|
+
role: "user",
|
|
7705
|
+
content: [
|
|
7706
|
+
{
|
|
7707
|
+
type: "image_url",
|
|
7708
|
+
image_url: {
|
|
7709
|
+
url: imageBase64
|
|
7710
|
+
}
|
|
7711
|
+
},
|
|
7712
|
+
{
|
|
7713
|
+
type: "text",
|
|
7714
|
+
text: prompt
|
|
7715
|
+
}
|
|
7716
|
+
]
|
|
7717
|
+
}
|
|
7718
|
+
],
|
|
7719
|
+
temperature: 0.2,
|
|
7720
|
+
max_tokens: maxTokens
|
|
7721
|
+
}),
|
|
7722
|
+
signal: controller.signal
|
|
7723
|
+
});
|
|
7724
|
+
clearTimeout(timeoutId);
|
|
7725
|
+
if (!response.ok) {
|
|
7726
|
+
const errorText = await response.text();
|
|
7727
|
+
throw new Error(`Kimi \u{9519}\u{8BEF}: ${response.status} - ${errorText}`);
|
|
7728
|
+
}
|
|
7729
|
+
const data = await response.json();
|
|
7730
|
+
const content = data.choices?.[0]?.message?.content || "";
|
|
7731
|
+
if (!content) throw new Error("Kimi \u8FD4\u56DE\u7A7A\u7ED3\u679C");
|
|
7732
|
+
logger.k.info("Kimi Vision \u8C03\u7528\u6210\u529F", {
|
|
7733
|
+
contentLength: content.length
|
|
7734
|
+
});
|
|
7735
|
+
return content;
|
|
7736
|
+
} catch (error) {
|
|
7737
|
+
clearTimeout(timeoutId);
|
|
7738
|
+
throw error;
|
|
7739
|
+
}
|
|
7740
|
+
}
|
|
7741
|
+
async function callGLMVision(imageBase64, prompt, maxTokens = 4000) {
|
|
7742
|
+
const controller = new AbortController();
|
|
7743
|
+
const timeoutId = setTimeout(()=>controller.abort(), 60000);
|
|
7744
|
+
try {
|
|
7745
|
+
const response = await fetch(GLM_CONFIG.baseUrl, {
|
|
7746
|
+
method: "POST",
|
|
7747
|
+
headers: {
|
|
7748
|
+
"Content-Type": "application/json",
|
|
7749
|
+
Authorization: `Bearer ${GLM_CONFIG.apiKey}`
|
|
7750
|
+
},
|
|
7751
|
+
body: JSON.stringify({
|
|
7752
|
+
model: GLM_CONFIG.model,
|
|
7753
|
+
messages: [
|
|
7754
|
+
{
|
|
7755
|
+
role: "system",
|
|
7756
|
+
content: SYSTEM_PROMPT
|
|
7757
|
+
},
|
|
7758
|
+
{
|
|
7759
|
+
role: "user",
|
|
7760
|
+
content: [
|
|
7761
|
+
{
|
|
7762
|
+
type: "image_url",
|
|
7763
|
+
image_url: {
|
|
7764
|
+
url: imageBase64
|
|
7765
|
+
}
|
|
7766
|
+
},
|
|
7767
|
+
{
|
|
7768
|
+
type: "text",
|
|
7769
|
+
text: prompt
|
|
7770
|
+
}
|
|
7771
|
+
]
|
|
7772
|
+
}
|
|
7773
|
+
],
|
|
7774
|
+
temperature: 0.2,
|
|
7775
|
+
max_tokens: maxTokens
|
|
7776
|
+
}),
|
|
7777
|
+
signal: controller.signal
|
|
7778
|
+
});
|
|
7779
|
+
clearTimeout(timeoutId);
|
|
7780
|
+
if (!response.ok) {
|
|
7781
|
+
const errorText = await response.text();
|
|
7782
|
+
throw new Error(`GLM-4V \u{9519}\u{8BEF}: ${response.status} - ${errorText}`);
|
|
7783
|
+
}
|
|
7784
|
+
const data = await response.json();
|
|
7785
|
+
const content = data.choices?.[0]?.message?.content || "";
|
|
7786
|
+
if (!content) throw new Error("GLM-4V \u8FD4\u56DE\u7A7A\u7ED3\u679C");
|
|
7787
|
+
logger.k.info("GLM-4V \u8C03\u7528\u6210\u529F", {
|
|
7788
|
+
contentLength: content.length
|
|
7789
|
+
});
|
|
7790
|
+
return content;
|
|
7791
|
+
} catch (error) {
|
|
7792
|
+
clearTimeout(timeoutId);
|
|
7793
|
+
throw error;
|
|
7794
|
+
}
|
|
7795
|
+
}
|
|
7796
|
+
async function analyzeWithVision(imagePath, imageBase64, prompt, context) {
|
|
7797
|
+
try {
|
|
7798
|
+
const [visionResult, ocrResult] = await Promise.all([
|
|
7799
|
+
callInternalVision(imageBase64, prompt).catch(()=>""),
|
|
7800
|
+
callInternalOCR(imageBase64, prompt).catch(()=>"")
|
|
7801
|
+
]);
|
|
7802
|
+
if (visionResult || ocrResult) {
|
|
7803
|
+
const chosen = chooseBestTranscription(visionResult, ocrResult);
|
|
7804
|
+
return {
|
|
7805
|
+
content: chosen.content,
|
|
7806
|
+
model: chosen.source
|
|
7807
|
+
};
|
|
7808
|
+
}
|
|
7809
|
+
throw new Error("\u5185\u7F51\u6A21\u578B\u5747\u8FD4\u56DE\u7A7A\u7ED3\u679C");
|
|
7810
|
+
} catch (internalError) {
|
|
7811
|
+
logger.k.warn("\u5185\u7F51\u6A21\u578B\u5931\u8D25", {
|
|
7812
|
+
error: internalError
|
|
7813
|
+
});
|
|
7814
|
+
}
|
|
7815
|
+
try {
|
|
7816
|
+
const content = await callKimiVision(imageBase64, prompt);
|
|
7817
|
+
return {
|
|
7818
|
+
content,
|
|
7819
|
+
model: "kimi"
|
|
7284
7820
|
};
|
|
7285
|
-
|
|
7286
|
-
|
|
7287
|
-
|
|
7288
|
-
|
|
7821
|
+
} catch (kimiError) {
|
|
7822
|
+
logger.k.warn("Kimi \u5931\u8D25", {
|
|
7823
|
+
error: kimiError
|
|
7824
|
+
});
|
|
7825
|
+
}
|
|
7826
|
+
try {
|
|
7827
|
+
const content = await callGLMVision(imageBase64, prompt);
|
|
7828
|
+
return {
|
|
7829
|
+
content,
|
|
7830
|
+
model: "glm"
|
|
7289
7831
|
};
|
|
7832
|
+
} catch (glmError) {
|
|
7833
|
+
logger.k.warn("GLM-4V \u5931\u8D25", {
|
|
7834
|
+
error: glmError
|
|
7835
|
+
});
|
|
7836
|
+
}
|
|
7837
|
+
const content = await callDifyWorkflow(imagePath, context || prompt);
|
|
7838
|
+
return {
|
|
7839
|
+
content,
|
|
7840
|
+
model: "dify"
|
|
7841
|
+
};
|
|
7842
|
+
}
|
|
7843
|
+
function chooseBestTranscription(vision, ocr) {
|
|
7844
|
+
const hasSummaryPattern = (s)=>{
|
|
7845
|
+
if (!s) return false;
|
|
7846
|
+
const lines = s.split(/\r?\n/).slice(0, 5).join("\n");
|
|
7847
|
+
const summaryHeaders = /(截图内容分析|核心信息|功能描述|接口说明|限制条件|主要内容|图片内容|内容概述)/;
|
|
7848
|
+
const chattyPrefix = /^(好的|如下|以下为|以下是|我将|这是一张|根据图片|请见)[,,::]?/m;
|
|
7849
|
+
return summaryHeaders.test(lines) || chattyPrefix.test(lines);
|
|
7850
|
+
};
|
|
7851
|
+
const visionIsSummary = hasSummaryPattern(vision);
|
|
7852
|
+
const ocrIsSummary = hasSummaryPattern(ocr);
|
|
7853
|
+
if (ocr && !ocrIsSummary) return {
|
|
7854
|
+
content: ocr,
|
|
7855
|
+
source: "internal-ocr"
|
|
7856
|
+
};
|
|
7857
|
+
if (vision && !visionIsSummary) return {
|
|
7858
|
+
content: vision,
|
|
7859
|
+
source: "internal-vision"
|
|
7860
|
+
};
|
|
7861
|
+
if ((ocr || "").length >= (vision || "").length) return {
|
|
7862
|
+
content: ocr || vision,
|
|
7863
|
+
source: ocr ? "internal-ocr" : "internal-vision"
|
|
7864
|
+
};
|
|
7865
|
+
return {
|
|
7866
|
+
content: vision,
|
|
7867
|
+
source: "internal-vision"
|
|
7868
|
+
};
|
|
7869
|
+
}
|
|
7870
|
+
class ImageAnalyzer {
|
|
7871
|
+
async analyzeImage(imagePath, context) {
|
|
7872
|
+
const startTime = Date.now();
|
|
7873
|
+
logger.k.info("\u5F00\u59CB\u56FE\u7247\u5206\u6790", {
|
|
7874
|
+
imagePath
|
|
7875
|
+
});
|
|
7876
|
+
await validateImage(imagePath);
|
|
7877
|
+
const imageInfo = await getImageInfo(imagePath);
|
|
7878
|
+
logger.k.info("\u56FE\u7247\u4FE1\u606F", {
|
|
7879
|
+
width: imageInfo.dimensions.width,
|
|
7880
|
+
height: imageInfo.dimensions.height,
|
|
7881
|
+
format: imageInfo.format
|
|
7882
|
+
});
|
|
7883
|
+
let content;
|
|
7884
|
+
content = image_processor_isLongImage(imageInfo) ? await this.analyzeLongImage(imagePath, imageInfo, context) : await this.analyzeSingleImage(imagePath, context);
|
|
7885
|
+
const processingTime = Date.now() - startTime;
|
|
7886
|
+
logger.k.info("\u56FE\u7247\u5206\u6790\u5B8C\u6210", {
|
|
7887
|
+
processingTime,
|
|
7888
|
+
contentLength: content.summary.length
|
|
7889
|
+
});
|
|
7290
7890
|
return {
|
|
7291
|
-
|
|
7292
|
-
content
|
|
7891
|
+
basic_info: imageInfo,
|
|
7892
|
+
content,
|
|
7893
|
+
processing_time_ms: processingTime
|
|
7293
7894
|
};
|
|
7294
7895
|
}
|
|
7295
|
-
async
|
|
7296
|
-
const
|
|
7297
|
-
const
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
x: c.x,
|
|
7303
|
-
y: c.y,
|
|
7304
|
-
width: c.width,
|
|
7305
|
-
height: c.height
|
|
7306
|
-
}))
|
|
7896
|
+
async analyzeSingleImage(imagePath, context) {
|
|
7897
|
+
const imageBase64 = await imageToBase64(imagePath);
|
|
7898
|
+
const prompt = this.buildPrompt(context);
|
|
7899
|
+
const result = await analyzeWithVision(imagePath, imageBase64, prompt, context);
|
|
7900
|
+
logger.k.info("\u56FE\u7247\u8BC6\u522B\u5B8C\u6210", {
|
|
7901
|
+
model: result.model,
|
|
7902
|
+
contentLength: result.content.length
|
|
7307
7903
|
});
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
}
|
|
7325
|
-
const mergedResult = await this.mergeChunkResults(chunkResults, context);
|
|
7326
|
-
return mergedResult;
|
|
7327
|
-
} finally{
|
|
7904
|
+
return {
|
|
7905
|
+
summary: result.content,
|
|
7906
|
+
details: {
|
|
7907
|
+
model: result.model
|
|
7908
|
+
},
|
|
7909
|
+
tags: []
|
|
7910
|
+
};
|
|
7911
|
+
}
|
|
7912
|
+
async analyzeLongImage(imagePath, imageInfo, context) {
|
|
7913
|
+
const segments = await splitLongImage(imagePath, imageInfo);
|
|
7914
|
+
const results = [];
|
|
7915
|
+
const models = [];
|
|
7916
|
+
for (const segment of segments){
|
|
7917
|
+
const segmentBase64 = bufferToBase64(segment.buffer);
|
|
7918
|
+
const prompt = this.buildPrompt(context, segment.index + 1, segment.total);
|
|
7919
|
+
const tempPath = await saveSegmentToTemp(segment);
|
|
7328
7920
|
try {
|
|
7329
|
-
await
|
|
7330
|
-
|
|
7331
|
-
|
|
7921
|
+
const result = await analyzeWithVision(tempPath, segmentBase64, prompt, context);
|
|
7922
|
+
results.push(result.content);
|
|
7923
|
+
models.push(result.model);
|
|
7924
|
+
logger.k.info(`\u{5206}\u{6BB5} ${segment.index + 1}/${segment.total} \u{5B8C}\u{6210}`, {
|
|
7925
|
+
model: result.model
|
|
7332
7926
|
});
|
|
7333
|
-
} catch (
|
|
7334
|
-
logger.k.
|
|
7335
|
-
|
|
7336
|
-
error: e
|
|
7927
|
+
} catch (error) {
|
|
7928
|
+
logger.k.error(`\u{5206}\u{6BB5} ${segment.index + 1} \u{8BC6}\u{522B}\u{5931}\u{8D25}`, {
|
|
7929
|
+
error
|
|
7337
7930
|
});
|
|
7931
|
+
results.push(`[\u{7B2C} ${segment.index + 1} \u{90E8}\u{5206}\u{8BC6}\u{522B}\u{5931}\u{8D25}]`);
|
|
7932
|
+
} finally{
|
|
7933
|
+
await cleanupTempFile(tempPath);
|
|
7338
7934
|
}
|
|
7339
7935
|
}
|
|
7936
|
+
const mergedContent = mergeSegmentResults(results);
|
|
7937
|
+
return {
|
|
7938
|
+
summary: mergedContent,
|
|
7939
|
+
details: {
|
|
7940
|
+
segments: segments.length,
|
|
7941
|
+
models: [
|
|
7942
|
+
...new Set(models)
|
|
7943
|
+
]
|
|
7944
|
+
},
|
|
7945
|
+
tags: []
|
|
7946
|
+
};
|
|
7340
7947
|
}
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
const area = width * height;
|
|
7344
|
-
let cols, rows;
|
|
7345
|
-
if (area <= 2000000) {
|
|
7346
|
-
cols = 1;
|
|
7347
|
-
rows = 1;
|
|
7348
|
-
} else if (area <= 4000000) {
|
|
7349
|
-
cols = 2;
|
|
7350
|
-
rows = 1;
|
|
7351
|
-
} else if (area <= 6000000) {
|
|
7352
|
-
cols = 2;
|
|
7353
|
-
rows = 2;
|
|
7354
|
-
} else {
|
|
7355
|
-
cols = 3;
|
|
7356
|
-
rows = 2;
|
|
7357
|
-
}
|
|
7358
|
-
if (1 === cols && 1 === rows) return [
|
|
7359
|
-
{
|
|
7360
|
-
index: 0,
|
|
7361
|
-
position: "\u5168\u56FE",
|
|
7362
|
-
x: 0,
|
|
7363
|
-
y: 0,
|
|
7364
|
-
width,
|
|
7365
|
-
height
|
|
7366
|
-
}
|
|
7367
|
-
];
|
|
7368
|
-
const overlapRatio = DEFAULT_CHUNK_CONFIG.overlapRatio;
|
|
7369
|
-
const chunkWidth = Math.ceil(width / cols);
|
|
7370
|
-
const chunkHeight = Math.ceil(height / rows);
|
|
7371
|
-
const overlapX = Math.ceil(chunkWidth * overlapRatio);
|
|
7372
|
-
const overlapY = Math.ceil(chunkHeight * overlapRatio);
|
|
7373
|
-
const positionNames = [
|
|
7374
|
-
[
|
|
7375
|
-
"\u5DE6\u4E0A",
|
|
7376
|
-
"\u4E2D\u4E0A",
|
|
7377
|
-
"\u53F3\u4E0A"
|
|
7378
|
-
],
|
|
7379
|
-
[
|
|
7380
|
-
"\u5DE6\u4E2D",
|
|
7381
|
-
"\u4E2D\u592E",
|
|
7382
|
-
"\u53F3\u4E2D"
|
|
7383
|
-
],
|
|
7384
|
-
[
|
|
7385
|
-
"\u5DE6\u4E0B",
|
|
7386
|
-
"\u4E2D\u4E0B",
|
|
7387
|
-
"\u53F3\u4E0B"
|
|
7388
|
-
]
|
|
7389
|
-
];
|
|
7390
|
-
let index = 0;
|
|
7391
|
-
for(let row = 0; row < rows; row++)for(let col = 0; col < cols; col++){
|
|
7392
|
-
const x = Math.max(0, col * chunkWidth - (col > 0 ? overlapX : 0));
|
|
7393
|
-
const y = Math.max(0, row * chunkHeight - (row > 0 ? overlapY : 0));
|
|
7394
|
-
const w = Math.min(chunkWidth + (col > 0 ? overlapX : 0) + (col < cols - 1 ? overlapX : 0), width - x);
|
|
7395
|
-
const h = Math.min(chunkHeight + (row > 0 ? overlapY : 0) + (row < rows - 1 ? overlapY : 0), height - y);
|
|
7396
|
-
chunks.push({
|
|
7397
|
-
index,
|
|
7398
|
-
position: positionNames[row]?.[col] || `\u{533A}\u{57DF}${index + 1}`,
|
|
7399
|
-
x,
|
|
7400
|
-
y,
|
|
7401
|
-
width: w,
|
|
7402
|
-
height: h
|
|
7403
|
-
});
|
|
7404
|
-
index++;
|
|
7405
|
-
}
|
|
7406
|
-
return chunks;
|
|
7407
|
-
}
|
|
7408
|
-
async extractChunk(imagePath, chunk, tempDir) {
|
|
7409
|
-
const chunkPath = external_path_.join(tempDir, `chunk_${chunk.index}.png`);
|
|
7410
|
-
await external_sharp_default()(imagePath).extract({
|
|
7411
|
-
left: chunk.x,
|
|
7412
|
-
top: chunk.y,
|
|
7413
|
-
width: chunk.width,
|
|
7414
|
-
height: chunk.height
|
|
7415
|
-
}).toFile(chunkPath);
|
|
7416
|
-
return chunkPath;
|
|
7417
|
-
}
|
|
7418
|
-
async analyzeChunk(chunkPath, position, context) {
|
|
7419
|
-
const systemPrompt = "You are an OCR transcription machine. Output ONLY the exact text from images. Never summarize or interpret.";
|
|
7420
|
-
const userPrompt = `\u{8FD9}\u{662F}\u{56FE}\u{7247}\u{7684}\u{3010}${position}\u{3011}\u{90E8}\u{5206}\u{3002}\u{8BF7}\u{9010}\u{5B57}\u{6284}\u{5F55}\u{6B64}\u{533A}\u{57DF}\u{5185}\u{7684}\u{6240}\u{6709}\u{6587}\u{5B57}\u{3002}
|
|
7948
|
+
buildPrompt(context, segmentIndex, totalSegments) {
|
|
7949
|
+
let prompt = `\u{4F60}\u{662F}\u{4E00}\u{4E2A}\u{4EC5}\u{505A}\u{9010}\u{5B57}\u{6284}\u{5F55}\u{7684} OCR \u{5DE5}\u{5177}\u{FF0C}\u{53EA}\u{80FD}\u{628A}\u{56FE}\u{7247}\u{91CC}\u{7684}\u{6587}\u{5B57}\u{539F}\u{6837}\u{6284}\u{5199}\u{51FA}\u{6765}\u{FF0C}\u{4E0D}\u{5141}\u{8BB8}\u{6DFB}\u{52A0}\u{4EFB}\u{4F55}\u{8BF4}\u{660E}\u{6216}\u{603B}\u{7ED3}\u{3002}
|
|
7421
7950
|
|
|
7422
7951
|
\u{89C4}\u{5219}\u{FF1A}
|
|
7423
|
-
1
|
|
7424
|
-
2
|
|
7425
|
-
3
|
|
7426
|
-
4
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
system_prompt: systemPrompt,
|
|
7433
|
-
temperature: 0,
|
|
7434
|
-
max_tokens: 4000
|
|
7435
|
-
});
|
|
7436
|
-
return aiResponse.trim();
|
|
7437
|
-
}
|
|
7438
|
-
async mergeChunkResults(chunkResults, context) {
|
|
7439
|
-
if (1 === chunkResults.length) return chunkResults[0].content;
|
|
7440
|
-
const chunkedResultsText = chunkResults.map((r)=>`### ${r.chunk.position}\u{533A}\u{57DF}
|
|
7441
|
-
${r.content}`).join('\n\n');
|
|
7442
|
-
const mergePrompt = `\u{4EE5}\u{4E0B}\u{662F}\u{540C}\u{4E00}\u{5F20}\u{56FE}\u{7247}\u{4E0D}\u{540C}\u{533A}\u{57DF}\u{7684}\u{8BC6}\u{522B}\u{7ED3}\u{679C}\u{FF0C}\u{8BF7}\u{6574}\u{5408}\u{4E3A}\u{5B8C}\u{6574}\u{7684}\u{56FE}\u{7247}\u{63CF}\u{8FF0}\u{FF1A}
|
|
7443
|
-
|
|
7444
|
-
1. \u{5408}\u{5E76}\u{6240}\u{6709}\u{533A}\u{57DF}\u{7684}\u{5185}\u{5BB9}
|
|
7445
|
-
2. \u{6D88}\u{9664}\u{91CD}\u{590D}\u{63CF}\u{8FF0}\u{FF08}\u{91CD}\u{53E0}\u{533A}\u{57DF}\u{53EF}\u{80FD}\u{6709}\u{76F8}\u{540C}\u{5185}\u{5BB9}\u{FF09}
|
|
7446
|
-
3. \u{4FDD}\u{6301}\u{5185}\u{5BB9}\u{7684}\u{7A7A}\u{95F4}\u{4F4D}\u{7F6E}\u{5173}\u{7CFB}
|
|
7447
|
-
4. \u{4E0D}\u{6DFB}\u{52A0}\u{3001}\u{4E0D}\u{4FEE}\u{6539}\u{539F}\u{59CB}\u{8BC6}\u{522B}\u{5230}\u{7684}\u{5185}\u{5BB9}
|
|
7448
|
-
|
|
7449
|
-
${context}
|
|
7952
|
+
1) \u{539F}\u{6587}\u{7167}\u{6284}\u{FF1A}\u{56FE}\u{7247}\u{91CC}\u{6709}\u{4EC0}\u{4E48}\u{5C31}\u{8F93}\u{51FA}\u{4EC0}\u{4E48}\u{FF0C}\u{4E00}\u{4E2A}\u{5B57}\u{90FD}\u{4E0D}\u{80FD}\u{5C11}\u{6216}\u{6539}
|
|
7953
|
+
2) \u{4FDD}\u{6301}\u{683C}\u{5F0F}\u{FF1A}\u{6362}\u{884C}\u{3001}\u{7A7A}\u{683C}\u{3001}\u{7F29}\u{8FDB}\u{3001}\u{5217}\u{8868}\u{7F16}\u{53F7}\u{5168}\u{90E8}\u{4FDD}\u{7559}
|
|
7954
|
+
3) \u{4EE3}\u{7801}\u{5757}\u{FF1A}\u{7528} \`\`\` \u{5305}\u{88F9}\u{FF0C}\u{7F29}\u{8FDB}\u{4E0E}\u{7A7A}\u{683C}\u{5FC5}\u{987B}\u{4FDD}\u{6301}
|
|
7955
|
+
4) \u{8868}\u{683C}\u{FF1A}\u{7528} markdown \u{8868}\u{683C}\u{8868}\u{793A}
|
|
7956
|
+
5) \u{7981}\u{6B62}\u{6DFB}\u{52A0}\u{5F00}\u{573A}\u{767D}\u{FF08}\u{5982}\u{201C}\u{4EE5}\u{4E0B}\u{662F}/\u{4E0B}\u{9762}\u{662F}/\u{6211}\u{5C06}/\u{8FD9}\u{662F}\u{2026}\u{201D}\u{FF09}
|
|
7957
|
+
6) \u{7981}\u{6B62}\u{51ED}\u{7A7A}\u{751F}\u{6210}\u{6807}\u{9898}\u{FF08}\u{5982}\u{201C}\u{6838}\u{5FC3}\u{4FE1}\u{606F}/\u{529F}\u{80FD}\u{63CF}\u{8FF0}/\u{63A5}\u{53E3}\u{8BF4}\u{660E}\u{201D}\u{7B49}\u{FF09}\u{3002}\u{5982}\u{679C}\u{8FD9}\u{4E9B}\u{8BCD}\u{51FA}\u{73B0}\u{5728}\u{56FE}\u{7247}\u{91CC}\u{FF0C}\u{6309}\u{539F}\u{6837}\u{8F93}\u{51FA}\u{5373}\u{53EF}
|
|
7958
|
+
7) \u{4E0D}\u{8981}\u{7FFB}\u{8BD1}\u{6216}\u{6539}\u{5199}
|
|
7959
|
+
`;
|
|
7960
|
+
if (segmentIndex && totalSegments) prompt = `\u{7B2C} ${segmentIndex}/${totalSegments} \u{90E8}\u{5206}
|
|
7450
7961
|
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
system_prompt: "\u4F60\u662F\u4E00\u4E2A\u5185\u5BB9\u6574\u5408\u4E13\u5BB6\uFF0C\u64C5\u957F\u5C06\u591A\u4E2A\u7247\u6BB5\u7684\u63CF\u8FF0\u6574\u5408\u4E3A\u5B8C\u6574\u3001\u8FDE\u8D2F\u7684\u6587\u672C\u3002\u4F7F\u7528\u4E2D\u6587\u56DE\u7B54\u3002",
|
|
7456
|
-
temperature: 0.3
|
|
7457
|
-
});
|
|
7458
|
-
return mergedResult.trim();
|
|
7459
|
-
}
|
|
7460
|
-
async getImageBasicInfo(imagePath) {
|
|
7461
|
-
try {
|
|
7462
|
-
const metadata = await external_sharp_default()(imagePath).metadata();
|
|
7463
|
-
const stats = await promises_.stat(imagePath);
|
|
7464
|
-
return {
|
|
7465
|
-
path: imagePath,
|
|
7466
|
-
format: metadata.format || "unknown",
|
|
7467
|
-
dimensions: {
|
|
7468
|
-
width: metadata.width || 0,
|
|
7469
|
-
height: metadata.height || 0
|
|
7470
|
-
},
|
|
7471
|
-
file_size: stats.size
|
|
7472
|
-
};
|
|
7473
|
-
} catch (error) {
|
|
7474
|
-
throw new ImageAnalysisError(`\u{65E0}\u{6CD5}\u{8BFB}\u{53D6}\u{56FE}\u{7247}\u{4FE1}\u{606F}: ${imagePath}`, types_AnalysisErrorCodes.IMAGE_CORRUPTED, {
|
|
7475
|
-
imagePath,
|
|
7476
|
-
originalError: error
|
|
7477
|
-
});
|
|
7478
|
-
}
|
|
7479
|
-
}
|
|
7480
|
-
async validateParams(imagePath) {
|
|
7481
|
-
try {
|
|
7482
|
-
await promises_.access(imagePath);
|
|
7483
|
-
} catch {
|
|
7484
|
-
throw new ImageAnalysisError(`\u{56FE}\u{7247}\u{6587}\u{4EF6}\u{4E0D}\u{5B58}\u{5728}: ${imagePath}`, types_AnalysisErrorCodes.FILE_NOT_FOUND, {
|
|
7485
|
-
imagePath: imagePath
|
|
7486
|
-
});
|
|
7487
|
-
}
|
|
7488
|
-
const ext = external_path_.extname(imagePath).slice(1).toLowerCase();
|
|
7489
|
-
if (!SUPPORTED_IMAGE_FORMATS.includes(ext)) throw new ImageAnalysisError(`\u{4E0D}\u{652F}\u{6301}\u{7684}\u{56FE}\u{7247}\u{683C}\u{5F0F}: ${ext}`, types_AnalysisErrorCodes.UNSUPPORTED_FORMAT, {
|
|
7490
|
-
format: ext,
|
|
7491
|
-
supportedFormats: SUPPORTED_IMAGE_FORMATS
|
|
7492
|
-
});
|
|
7962
|
+
${prompt}`;
|
|
7963
|
+
if (context) prompt += `
|
|
7964
|
+
\u{4E0A}\u{4E0B}\u{6587}\u{63D0}\u{793A}\u{FF08}\u{4EC5}\u{4F9B}\u{4F60}\u{7406}\u{89E3}\u{FF0C}\u{4E0D}\u{5F97}\u{5199}\u{5165}\u{8F93}\u{51FA}\u{FF09}\u{FF1A}${context}`;
|
|
7965
|
+
return prompt;
|
|
7493
7966
|
}
|
|
7494
7967
|
}
|
|
7495
7968
|
const ImageAnalysisParamsSchema = objectType({
|
|
@@ -12298,7 +12771,8 @@ ${failedProjects.map((p)=>`- ${p.projectName}: ${p.errorMessage}`).join("\n")}
|
|
|
12298
12771
|
usersFile;
|
|
12299
12772
|
constructor(){
|
|
12300
12773
|
try {
|
|
12301
|
-
const
|
|
12774
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || "/tmp";
|
|
12775
|
+
const storageDir = external_path_.join(homeDir, ".aico");
|
|
12302
12776
|
this.dataDir = external_path_.join(storageDir, "lark");
|
|
12303
12777
|
this.usersFile = external_path_.join(this.dataDir, "users.json");
|
|
12304
12778
|
this.ensureDataDir();
|
|
@@ -12526,12 +13000,16 @@ ${failedProjects.map((p)=>`- ${p.projectName}: ${p.errorMessage}`).join("\n")}
|
|
|
12526
13000
|
});
|
|
12527
13001
|
const createDocTool = {
|
|
12528
13002
|
name: "lark_doc_create",
|
|
12529
|
-
description:
|
|
13003
|
+
description: `\u{3010}\u{521B}\u{5EFA}\u{4E91}\u{6587}\u{6863}\u{9996}\u{9009}\u{3011}\u{521B}\u{5EFA}\u{6606}\u{4ED1}\u{667A}\u{8054}\u{4E91}\u{6587}\u{6863}\u{5E76}\u{5199}\u{5165}\u{5185}\u{5BB9}\u{3002}
|
|
13004
|
+
\u{4F7F}\u{7528}\u{573A}\u{666F}: \u{7528}\u{6237}\u{8BF4}"\u{5E2E}\u{6211}\u{5199}\u{4E00}\u{4E2A}XXX\u{6587}\u{6863}/\u{62A5}\u{544A}/\u{8BF4}\u{660E}/\u{65B9}\u{6848}"\u{65F6}\u{4F7F}\u{7528}\u{6B64}\u{5DE5}\u{5177}\u{3002}
|
|
13005
|
+
\u{793A}\u{4F8B}: "\u{5199}\u{4E00}\u{4E2A}\u{4F1A}\u{8BAE}\u{7EAA}\u{8981}" \u{2192} title="\u{4F1A}\u{8BAE}\u{7EAA}\u{8981}", blocks=[{type:"h1",content:"\u{4F1A}\u{8BAE}\u{4E3B}\u{9898}"},{type:"text",content:"\u{5185}\u{5BB9}..."}]
|
|
13006
|
+
\u{5757}\u{7C7B}\u{578B}: text=\u{6587}\u{672C}, h1-h6=\u{6807}\u{9898}, bullet=\u{65E0}\u{5E8F}\u{5217}\u{8868}, ordered=\u{6709}\u{5E8F}\u{5217}\u{8868}, code=\u{4EE3}\u{7801}, quote=\u{5F15}\u{7528}, todo=\u{5F85}\u{529E}, callout=\u{9AD8}\u{4EAE}, divider=\u{5206}\u{5272}\u{7EBF}
|
|
13007
|
+
\u{26A0}\u{FE0F} \u{5FC5}\u{987B}\u{63D0}\u{4F9B}email\u{53C2}\u{6570}\u{FF0C}\u{8BF7}\u{5148}\u{8BE2}\u{95EE}\u{7528}\u{6237}\u{90AE}\u{7BB1}\u{FF01}\u{6210}\u{529F}\u{540E}\u{4EC5}\u{8FD4}\u{56DE}\u{6587}\u{6863}\u{94FE}\u{63A5}\u{3002}`,
|
|
12530
13008
|
inputSchema: {
|
|
12531
|
-
title: stringType().describe("\u6587\u6863\u6807\u9898"),
|
|
12532
|
-
blocks: arrayType(blockSchema).optional().describe("\u6587\u6863\u5185\u5BB9\u5757\u6570\u7EC4
|
|
12533
|
-
folder: stringType().optional().describe("\u6587\u4EF6\u5939token"),
|
|
12534
|
-
email: stringType().describe("\u6240\u6709\u8005\u90AE\u7BB1
|
|
13009
|
+
title: stringType().describe("\u6587\u6863\u6807\u9898(\u5982: \u4F1A\u8BAE\u7EAA\u8981, \u9879\u76EE\u65B9\u6848)"),
|
|
13010
|
+
blocks: arrayType(blockSchema).optional().describe("\u6587\u6863\u5185\u5BB9\u5757\u6570\u7EC4\u3002\u793A\u4F8B: [{type:'h1',content:'\u6807\u9898'},{type:'text',content:'\u5185\u5BB9'}]"),
|
|
13011
|
+
folder: stringType().optional().describe("\u6587\u4EF6\u5939token(\u53EF\u9009)"),
|
|
13012
|
+
email: stringType().describe("\u6240\u6709\u8005\u90AE\u7BB1\u3010\u5FC5\u586B\u3011- \u8BF7\u5148\u8BE2\u95EE\u7528\u6237\u90AE\u7BB1\u5730\u5740")
|
|
12535
13013
|
},
|
|
12536
13014
|
handler: async (args)=>{
|
|
12537
13015
|
const client = getLarkClient();
|
|
@@ -12569,12 +13047,14 @@ ${failedProjects.map((p)=>`- ${p.projectName}: ${p.errorMessage}`).join("\n")}
|
|
|
12569
13047
|
};
|
|
12570
13048
|
const importMarkdownTool = {
|
|
12571
13049
|
name: "lark_doc_import_md",
|
|
12572
|
-
description:
|
|
13050
|
+
description: `\u{5C06}Markdown\u{5185}\u{5BB9}\u{5BFC}\u{5165}\u{4E3A}\u{6606}\u{4ED1}\u{667A}\u{8054}\u{4E91}\u{6587}\u{6863}\u{3002}
|
|
13051
|
+
\u{4F7F}\u{7528}\u{573A}\u{666F}: \u{7528}\u{6237}\u{63D0}\u{4F9B}\u{4E86}Markdown\u{683C}\u{5F0F}\u{5185}\u{5BB9},\u{8981}\u{6C42}\u{8F6C}\u{4E3A}\u{4E91}\u{6587}\u{6863}\u{3002}
|
|
13052
|
+
\u{26A0}\u{FE0F} \u{5FC5}\u{987B}\u{63D0}\u{4F9B}email\u{53C2}\u{6570}\u{FF01}`,
|
|
12573
13053
|
inputSchema: {
|
|
12574
13054
|
md: stringType().describe("Markdown\u5185\u5BB9"),
|
|
12575
13055
|
title: stringType().optional().describe("\u6587\u6863\u6807\u9898"),
|
|
12576
|
-
folder: stringType().optional().describe("\u6587\u4EF6\u5939token"),
|
|
12577
|
-
email: stringType().describe("\u6240\u6709\u8005\u90AE\u7BB1
|
|
13056
|
+
folder: stringType().optional().describe("\u6587\u4EF6\u5939token(\u53EF\u9009)"),
|
|
13057
|
+
email: stringType().describe("\u6240\u6709\u8005\u90AE\u7BB1\u3010\u5FC5\u586B\u3011")
|
|
12578
13058
|
},
|
|
12579
13059
|
handler: async (args)=>{
|
|
12580
13060
|
const client = getLarkClient();
|
|
@@ -12624,9 +13104,10 @@ ${failedProjects.map((p)=>`- ${p.projectName}: ${p.errorMessage}`).join("\n")}
|
|
|
12624
13104
|
};
|
|
12625
13105
|
const getDocContentTool = {
|
|
12626
13106
|
name: "lark_doc_content",
|
|
12627
|
-
description:
|
|
13107
|
+
description: `\u{83B7}\u{53D6}\u{4E91}\u{6587}\u{6863}\u{7684}\u{7EAF}\u{6587}\u{672C}\u{5185}\u{5BB9}\u{3002}
|
|
13108
|
+
\u{4F7F}\u{7528}\u{573A}\u{666F}: \u{9700}\u{8981}\u{8BFB}\u{53D6}\u{67D0}\u{4E2A}\u{6587}\u{6863}\u{5185}\u{5BB9}\u{65F6}\u{4F7F}\u{7528}\u{3002}`,
|
|
12628
13109
|
inputSchema: {
|
|
12629
|
-
id: stringType().describe("\u6587\u6863ID")
|
|
13110
|
+
id: stringType().describe("\u6587\u6863ID(\u4ECE\u94FE\u63A5\u4E2D\u63D0\u53D6,\u5982https://xxx/docx/ABC123\u5219ID\u4E3AABC123)")
|
|
12630
13111
|
},
|
|
12631
13112
|
handler: async (args)=>{
|
|
12632
13113
|
const client = getLarkClient();
|
|
@@ -12643,7 +13124,8 @@ ${failedProjects.map((p)=>`- ${p.projectName}: ${p.errorMessage}`).join("\n")}
|
|
|
12643
13124
|
};
|
|
12644
13125
|
const searchDocsTool = {
|
|
12645
13126
|
name: "lark_doc_search",
|
|
12646
|
-
description:
|
|
13127
|
+
description: `\u{641C}\u{7D22}\u{6606}\u{4ED1}\u{667A}\u{8054}\u{4E91}\u{6587}\u{6863}\u{3002}
|
|
13128
|
+
\u{4F7F}\u{7528}\u{573A}\u{666F}: \u{7528}\u{6237}\u{8981}\u{6C42}\u{67E5}\u{627E}/\u{641C}\u{7D22}\u{67D0}\u{4E2A}\u{6587}\u{6863}\u{65F6}\u{4F7F}\u{7528}\u{3002}`,
|
|
12647
13129
|
inputSchema: {
|
|
12648
13130
|
q: stringType().describe("\u641C\u7D22\u5173\u952E\u8BCD"),
|
|
12649
13131
|
types: arrayType(enumType([
|
|
@@ -12651,8 +13133,8 @@ ${failedProjects.map((p)=>`- ${p.projectName}: ${p.errorMessage}`).join("\n")}
|
|
|
12651
13133
|
"sheet",
|
|
12652
13134
|
"bitable",
|
|
12653
13135
|
"docx"
|
|
12654
|
-
])).optional().describe("\u6587\u6863\u7C7B\u578B"),
|
|
12655
|
-
limit: numberType().optional().describe("\u8FD4\u56DE\u6570\u91CF
|
|
13136
|
+
])).optional().describe("\u6587\u6863\u7C7B\u578B: doc=\u65E7\u7248\u6587\u6863, docx=\u65B0\u7248\u6587\u6863, sheet=\u8868\u683C, bitable=\u591A\u7EF4\u8868\u683C"),
|
|
13137
|
+
limit: numberType().optional().describe("\u8FD4\u56DE\u6570\u91CF(\u9ED8\u8BA420)")
|
|
12656
13138
|
},
|
|
12657
13139
|
handler: async (args)=>{
|
|
12658
13140
|
const client = getLarkClient();
|
|
@@ -12680,10 +13162,12 @@ ${failedProjects.map((p)=>`- ${p.projectName}: ${p.errorMessage}`).join("\n")}
|
|
|
12680
13162
|
};
|
|
12681
13163
|
const appendDocTool = {
|
|
12682
13164
|
name: "lark_doc_append",
|
|
12683
|
-
description:
|
|
13165
|
+
description: `\u{5411}\u{5DF2}\u{6709}\u{4E91}\u{6587}\u{6863}\u{8FFD}\u{52A0}\u{5185}\u{5BB9}\u{3002}
|
|
13166
|
+
\u{4F7F}\u{7528}\u{573A}\u{666F}: \u{7528}\u{6237}\u{63D0}\u{4F9B}\u{4E86}\u{6587}\u{6863}ID\u{6216}\u{94FE}\u{63A5},\u{8981}\u{6C42}\u{66F4}\u{65B0}/\u{8FFD}\u{52A0}\u{5185}\u{5BB9}\u{65F6}\u{4F7F}\u{7528}\u{3002}
|
|
13167
|
+
\u{6CE8}\u{610F}: \u{5982}\u{679C}\u{7528}\u{6237}\u{8981}\u{6C42}\u{521B}\u{5EFA}\u{65B0}\u{6587}\u{6863},\u{8BF7}\u{4F7F}\u{7528}lark_doc_create\u{3002}`,
|
|
12684
13168
|
inputSchema: {
|
|
12685
|
-
doc: stringType().describe("\u6587\u6863ID(\u4ECE\
|
|
12686
|
-
blocks: arrayType(blockSchema).describe("\u8981\u8FFD\u52A0\u7684\u5185\u5BB9\u5757\u6570\u7EC4")
|
|
13169
|
+
doc: stringType().describe("\u6587\u6863ID(\u4ECE\u94FE\u63A5\u4E2D\u63D0\u53D6,\u5982https://xxx/docx/ABC123\u5219ID\u4E3AABC123)"),
|
|
13170
|
+
blocks: arrayType(blockSchema).describe("\u8981\u8FFD\u52A0\u7684\u5185\u5BB9\u5757\u6570\u7EC4\u3002\u793A\u4F8B: [{type:'text',content:'\u65B0\u5185\u5BB9'}]")
|
|
12687
13171
|
},
|
|
12688
13172
|
handler: async (args)=>{
|
|
12689
13173
|
const client = getLarkClient();
|
|
@@ -12728,13 +13212,87 @@ ${failedProjects.map((p)=>`- ${p.projectName}: ${p.errorMessage}`).join("\n")}
|
|
|
12728
13212
|
if (email) return email;
|
|
12729
13213
|
return await larkDbOperations.getDefaultEmail();
|
|
12730
13214
|
}
|
|
13215
|
+
const bitable_tools_fieldSchema = objectType({
|
|
13216
|
+
name: stringType().describe("\u5B57\u6BB5\u540D\u79F0"),
|
|
13217
|
+
type: numberType().describe("\u5B57\u6BB5\u7C7B\u578B: 1=\u6587\u672C, 2=\u6570\u5B57, 3=\u5355\u9009, 4=\u591A\u9009, 5=\u65E5\u671F, 7=\u590D\u9009\u6846, 11=\u4EBA\u5458, 15=\u94FE\u63A5"),
|
|
13218
|
+
options: arrayType(stringType()).optional().describe("\u9009\u9879\u503C(\u4EC5\u5355\u9009/\u591A\u9009\u7C7B\u578B\u9700\u8981)")
|
|
13219
|
+
});
|
|
13220
|
+
const createCompleteBitableTool = {
|
|
13221
|
+
name: "lark_bitable_create_complete",
|
|
13222
|
+
description: `\u{3010}\u{521B}\u{5EFA}\u{591A}\u{7EF4}\u{8868}\u{683C}\u{9996}\u{9009}\u{3011}\u{4E00}\u{6B65}\u{5B8C}\u{6210}\u{521B}\u{5EFA}\u{591A}\u{7EF4}\u{8868}\u{683C}\u{3001}\u{6570}\u{636E}\u{8868}\u{3001}\u{5B57}\u{6BB5}\u{5B9A}\u{4E49}\u{3002}
|
|
13223
|
+
\u{4F7F}\u{7528}\u{573A}\u{666F}: \u{7528}\u{6237}\u{8BF4}"\u{5E2E}\u{6211}\u{521B}\u{5EFA}\u{4E00}\u{4E2A}\u{7EDF}\u{8BA1}XXX\u{7684}\u{591A}\u{7EF4}\u{8868}\u{683C}/\u{8868}\u{683C}"\u{65F6}\u{4F7F}\u{7528}\u{6B64}\u{5DE5}\u{5177}\u{3002}
|
|
13224
|
+
\u{793A}\u{4F8B}: "\u{521B}\u{5EFA}\u{4E00}\u{4E2A}\u{5458}\u{5DE5}\u{624B}\u{673A}\u{53F7}\u{7EDF}\u{8BA1}\u{8868}\u{683C}" \u{2192} name="\u{5458}\u{5DE5}\u{624B}\u{673A}\u{53F7}\u{7EDF}\u{8BA1}", tableName="\u{5458}\u{5DE5}\u{4FE1}\u{606F}", fields=[{name:"\u{59D3}\u{540D}",type:1},{name:"\u{90E8}\u{95E8}",type:1},{name:"\u{624B}\u{673A}\u{53F7}",type:1}]
|
|
13225
|
+
\u{5B57}\u{6BB5}\u{7C7B}\u{578B}: 1=\u{6587}\u{672C}, 2=\u{6570}\u{5B57}, 3=\u{5355}\u{9009}, 4=\u{591A}\u{9009}, 5=\u{65E5}\u{671F}, 7=\u{590D}\u{9009}\u{6846}, 11=\u{4EBA}\u{5458}, 15=\u{94FE}\u{63A5}
|
|
13226
|
+
\u{26A0}\u{FE0F} \u{5FC5}\u{987B}\u{63D0}\u{4F9B}email\u{53C2}\u{6570}\u{FF0C}\u{8BF7}\u{5148}\u{8BE2}\u{95EE}\u{7528}\u{6237}\u{90AE}\u{7BB1}\u{FF01}\u{6210}\u{529F}\u{540E}\u{4EC5}\u{8FD4}\u{56DE}\u{8868}\u{683C}\u{94FE}\u{63A5}\u{3002}`,
|
|
13227
|
+
inputSchema: {
|
|
13228
|
+
name: stringType().describe("\u591A\u7EF4\u8868\u683C\u540D\u79F0(\u5982: \u5458\u5DE5\u4FE1\u606F\u7EDF\u8BA1)"),
|
|
13229
|
+
tableName: stringType().describe("\u6570\u636E\u8868\u540D\u79F0(\u5982: \u5458\u5DE5\u5217\u8868)"),
|
|
13230
|
+
fields: arrayType(bitable_tools_fieldSchema).describe("\u5B57\u6BB5\u5B9A\u4E49\u6570\u7EC4\u3002\u793A\u4F8B: [{name:'\u59D3\u540D',type:1},{name:'\u5E74\u9F84',type:2}]"),
|
|
13231
|
+
records: arrayType(recordType(anyType())).optional().describe("\u521D\u59CB\u6570\u636E(\u53EF\u9009),\u5B57\u6BB5\u540D\u4E3Akey\u3002\u793A\u4F8B: [{\u59D3\u540D:'\u5F20\u4E09',\u5E74\u9F84:25}]"),
|
|
13232
|
+
folder: stringType().optional().describe("\u6587\u4EF6\u5939token(\u53EF\u9009)"),
|
|
13233
|
+
email: stringType().describe("\u6240\u6709\u8005\u90AE\u7BB1\u3010\u5FC5\u586B\u3011- \u8BF7\u5148\u8BE2\u95EE\u7528\u6237\u90AE\u7BB1\u5730\u5740")
|
|
13234
|
+
},
|
|
13235
|
+
handler: async (args)=>{
|
|
13236
|
+
const client = getLarkClient();
|
|
13237
|
+
try {
|
|
13238
|
+
const email = await bitable_tools_getEmail(args.email);
|
|
13239
|
+
if (!email) return bitable_tools_formatResponse(false, null, "\u8BF7\u63D0\u4F9B\u90AE\u7BB1(email)\u53C2\u6570,\u7528\u4E8E\u8BBE\u7F6E\u8868\u683C\u6240\u6709\u8005\u3002\u8BF7\u8BE2\u95EE\u7528\u6237\u7684\u90AE\u7BB1\u5730\u5740");
|
|
13240
|
+
const createRes = await client.post("/open-apis/bitable/v1/apps", {
|
|
13241
|
+
name: args.name,
|
|
13242
|
+
folder_token: args.folder
|
|
13243
|
+
});
|
|
13244
|
+
if (0 !== createRes.code) throw new Error(createRes.msg);
|
|
13245
|
+
const appToken = createRes.data?.app?.app_token;
|
|
13246
|
+
if (!appToken) throw new Error("\u521B\u5EFA\u8868\u683C\u5931\u8D25,\u672A\u83B7\u53D6\u5230token");
|
|
13247
|
+
const url = createRes.data?.app?.url || client.buildDocUrl(appToken, "bitable");
|
|
13248
|
+
const fields = args.fields.map((f)=>{
|
|
13249
|
+
const field = {
|
|
13250
|
+
field_name: f.name,
|
|
13251
|
+
type: f.type
|
|
13252
|
+
};
|
|
13253
|
+
if ((3 === f.type || 4 === f.type) && f.options?.length) field.property = {
|
|
13254
|
+
options: f.options.map((opt)=>({
|
|
13255
|
+
name: opt
|
|
13256
|
+
}))
|
|
13257
|
+
};
|
|
13258
|
+
return field;
|
|
13259
|
+
});
|
|
13260
|
+
const tableRes = await client.post(`/open-apis/bitable/v1/apps/${appToken}/tables`, {
|
|
13261
|
+
table: {
|
|
13262
|
+
name: args.tableName,
|
|
13263
|
+
fields
|
|
13264
|
+
}
|
|
13265
|
+
});
|
|
13266
|
+
if (0 !== tableRes.code) throw new Error(tableRes.msg);
|
|
13267
|
+
const tableId = tableRes.data?.table_id;
|
|
13268
|
+
if (args.records && args.records.length > 0 && tableId) {
|
|
13269
|
+
const records = args.records.map((r)=>({
|
|
13270
|
+
fields: r
|
|
13271
|
+
}));
|
|
13272
|
+
await client.post(`/open-apis/bitable/v1/apps/${appToken}/tables/${tableId}/records/batch_create`, {
|
|
13273
|
+
records
|
|
13274
|
+
});
|
|
13275
|
+
}
|
|
13276
|
+
const ok = await client.transferOwnerByEmail(appToken, "bitable", email);
|
|
13277
|
+
if (ok) await larkDbOperations.saveUser({
|
|
13278
|
+
email
|
|
13279
|
+
});
|
|
13280
|
+
return bitable_tools_formatResponse(true, {
|
|
13281
|
+
url
|
|
13282
|
+
});
|
|
13283
|
+
} catch (error) {
|
|
13284
|
+
return bitable_tools_formatResponse(false, null, error.message);
|
|
13285
|
+
}
|
|
13286
|
+
}
|
|
13287
|
+
};
|
|
12731
13288
|
const createBitableTool = {
|
|
12732
13289
|
name: "lark_bitable_create",
|
|
12733
|
-
description:
|
|
13290
|
+
description: `\u{521B}\u{5EFA}\u{7A7A}\u{767D}\u{591A}\u{7EF4}\u{8868}\u{683C}\u{3002}\u{5982}\u{9700}\u{540C}\u{65F6}\u{521B}\u{5EFA}\u{5B57}\u{6BB5},\u{63A8}\u{8350}\u{4F7F}\u{7528}lark_bitable_create_complete\u{3002}
|
|
13291
|
+
\u{26A0}\u{FE0F} \u{5FC5}\u{987B}\u{63D0}\u{4F9B}email\u{53C2}\u{6570}\u{FF01}`,
|
|
12734
13292
|
inputSchema: {
|
|
12735
13293
|
name: stringType().describe("\u8868\u683C\u540D\u79F0"),
|
|
12736
13294
|
folder: stringType().optional().describe("\u6587\u4EF6\u5939token"),
|
|
12737
|
-
email: stringType().describe("\u6240\u6709\u8005\u90AE\u7BB1
|
|
13295
|
+
email: stringType().describe("\u6240\u6709\u8005\u90AE\u7BB1\u3010\u5FC5\u586B\u3011")
|
|
12738
13296
|
},
|
|
12739
13297
|
handler: async (args)=>{
|
|
12740
13298
|
const client = getLarkClient();
|
|
@@ -13003,6 +13561,7 @@ ${failedProjects.map((p)=>`- ${p.projectName}: ${p.errorMessage}`).join("\n")}
|
|
|
13003
13561
|
}
|
|
13004
13562
|
};
|
|
13005
13563
|
const bitableTools = [
|
|
13564
|
+
createCompleteBitableTool,
|
|
13006
13565
|
createBitableTool,
|
|
13007
13566
|
createTableTool,
|
|
13008
13567
|
listTablesTool,
|