aiconductor-cli 1.3.3 → 1.3.4
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/package.json +1 -1
- package/src/api.js +13 -6
- package/src/api.test.js +61 -2
- package/src/commands/web_search.js +3 -3
package/package.json
CHANGED
package/src/api.js
CHANGED
|
@@ -330,12 +330,19 @@ async function webSearch(apiKey, params) {
|
|
|
330
330
|
if (params.imageShapes !== undefined) reqBody.image_shapes = params.imageShapes;
|
|
331
331
|
}
|
|
332
332
|
|
|
333
|
-
const resp = await httpPost(API_HOST, SEARCH_API_PATH, reqBody, {
|
|
334
|
-
Authorization: `Bearer ${apiKey}`,
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
333
|
+
const resp = await httpPost(API_HOST, SEARCH_API_PATH, reqBody, {
|
|
334
|
+
Authorization: `Bearer ${apiKey}`,
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
const result = stripBilling(resp);
|
|
338
|
+
if (result?.success === false || result?.data?.success === false) {
|
|
339
|
+
throw Object.assign(new Error(result?.data?.message || result?.message || "搜索接口返回失败"), {
|
|
340
|
+
type: "api_error",
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return result;
|
|
345
|
+
}
|
|
339
346
|
|
|
340
347
|
/**
|
|
341
348
|
* Markdown 转 HTML 并发布
|
package/src/api.test.js
CHANGED
|
@@ -4,8 +4,9 @@ const https = require("node:https");
|
|
|
4
4
|
const test = require("node:test");
|
|
5
5
|
|
|
6
6
|
const { webSearch } = require("./api");
|
|
7
|
+
const { formatSearchText } = require("./commands/web_search");
|
|
7
8
|
|
|
8
|
-
function captureRequest(callback) {
|
|
9
|
+
function captureRequest(callback, responseBody = { success: true, billing: {} }) {
|
|
9
10
|
const originalRequest = https.request;
|
|
10
11
|
let captured;
|
|
11
12
|
https.request = (options, responseCallback) => {
|
|
@@ -17,7 +18,7 @@ function captureRequest(callback) {
|
|
|
17
18
|
const response = new EventEmitter();
|
|
18
19
|
response.statusCode = 200;
|
|
19
20
|
responseCallback(response);
|
|
20
|
-
response.emit("data", Buffer.from(JSON.stringify(
|
|
21
|
+
response.emit("data", Buffer.from(JSON.stringify(responseBody)));
|
|
21
22
|
response.emit("end");
|
|
22
23
|
};
|
|
23
24
|
return request;
|
|
@@ -96,3 +97,61 @@ test("webSearch maps current image filters and rejects invalid count", async ()
|
|
|
96
97
|
{ type: "validation_error" }
|
|
97
98
|
);
|
|
98
99
|
});
|
|
100
|
+
|
|
101
|
+
test("formatSearchText renders top-level web search results", () => {
|
|
102
|
+
const text = formatSearchText({
|
|
103
|
+
data: {
|
|
104
|
+
Result: {
|
|
105
|
+
ResultCount: 1,
|
|
106
|
+
TimeCost: 42,
|
|
107
|
+
WebResults: [{
|
|
108
|
+
SortId: 1,
|
|
109
|
+
Title: "北京游玩攻略",
|
|
110
|
+
SiteName: "示例站点",
|
|
111
|
+
Url: "https://example.com/guide",
|
|
112
|
+
Snippet: "推荐路线",
|
|
113
|
+
PublishTime: "2026-07-28",
|
|
114
|
+
}],
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
assert.match(text, /结果数: 1/);
|
|
120
|
+
assert.match(text, /耗时: 42ms/);
|
|
121
|
+
assert.match(text, /\[1\] 北京游玩攻略/);
|
|
122
|
+
assert.match(text, /URL: https:\/\/example\.com\/guide/);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("formatSearchText renders top-level image search results", () => {
|
|
126
|
+
const text = formatSearchText({
|
|
127
|
+
data: {
|
|
128
|
+
Result: {
|
|
129
|
+
ResultCount: 1,
|
|
130
|
+
TimeCost: 18,
|
|
131
|
+
ImageResults: [{
|
|
132
|
+
SortId: 1,
|
|
133
|
+
Title: "长城风景",
|
|
134
|
+
SiteName: "示例图片站",
|
|
135
|
+
Image: { Url: "https://example.com/great-wall.jpg", Width: 1920, Height: 1080 },
|
|
136
|
+
Url: "https://example.com/great-wall",
|
|
137
|
+
}],
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
assert.match(text, /结果数: 1/);
|
|
143
|
+
assert.match(text, /耗时: 18ms/);
|
|
144
|
+
assert.match(text, /\[1\] 长城风景/);
|
|
145
|
+
assert.match(text, /尺寸: 1920x1080/);
|
|
146
|
+
assert.match(text, /图片: https:\/\/example\.com\/great-wall\.jpg/);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("webSearch raises nested API failures", async () => {
|
|
150
|
+
await assert.rejects(
|
|
151
|
+
captureRequest(
|
|
152
|
+
() => webSearch("test-key", { query: "长城", searchType: "image", count: 1 }),
|
|
153
|
+
{ success: true, data: { success: false, message: "image 搜索的 count 必须为 1~5" } }
|
|
154
|
+
),
|
|
155
|
+
{ type: "api_error", message: "image 搜索的 count 必须为 1~5" }
|
|
156
|
+
);
|
|
157
|
+
});
|
|
@@ -2,8 +2,8 @@ const { webSearch } = require("../api");
|
|
|
2
2
|
const { outputResult, outputError, resolveKeyOrExit, handleApiError } = require("../lib/cli-utils");
|
|
3
3
|
|
|
4
4
|
/** text 模式的自定义格式化 */
|
|
5
|
-
function formatSearchText(data) {
|
|
6
|
-
const inner = data.data || {};
|
|
5
|
+
function formatSearchText(data = {}) {
|
|
6
|
+
const inner = data.data?.Result || {};
|
|
7
7
|
let out = "✓ 搜索成功\n";
|
|
8
8
|
out += ` 结果数: ${inner.ResultCount}\n`;
|
|
9
9
|
out += ` 耗时: ${inner.TimeCost}ms\n\n`;
|
|
@@ -96,4 +96,4 @@ async function searchCommand(query, searchType, options = {}) {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
module.exports = { searchCommand };
|
|
99
|
+
module.exports = { searchCommand, formatSearchText };
|