dsh-kenari-plugin 0.1.1
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/LICENSE +21 -0
- package/README.en.md +281 -0
- package/README.md +283 -0
- package/assets/kenari-favicon-128.png +0 -0
- package/assets/kenari-favicon-256.png +0 -0
- package/client/index.js +1998 -0
- package/cordis.patch.yml +137 -0
- package/lib/billing.d.ts +120 -0
- package/lib/billing.d.ts.map +1 -0
- package/lib/billing.js +209 -0
- package/lib/billing.js.map +1 -0
- package/lib/catalog-view.d.ts +78 -0
- package/lib/catalog-view.d.ts.map +1 -0
- package/lib/catalog-view.js +113 -0
- package/lib/catalog-view.js.map +1 -0
- package/lib/catalog.d.ts +239 -0
- package/lib/catalog.d.ts.map +1 -0
- package/lib/catalog.js +445 -0
- package/lib/catalog.js.map +1 -0
- package/lib/default-route.d.ts +35 -0
- package/lib/default-route.d.ts.map +1 -0
- package/lib/default-route.js +111 -0
- package/lib/default-route.js.map +1 -0
- package/lib/errors.d.ts +29 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +74 -0
- package/lib/errors.js.map +1 -0
- package/lib/favicon.d.ts +24 -0
- package/lib/favicon.d.ts.map +1 -0
- package/lib/favicon.js +68 -0
- package/lib/favicon.js.map +1 -0
- package/lib/http.d.ts +104 -0
- package/lib/http.d.ts.map +1 -0
- package/lib/http.js +247 -0
- package/lib/http.js.map +1 -0
- package/lib/index.d.ts +83 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +285 -0
- package/lib/index.js.map +1 -0
- package/lib/llm/adapter.d.ts +78 -0
- package/lib/llm/adapter.d.ts.map +1 -0
- package/lib/llm/adapter.js +429 -0
- package/lib/llm/adapter.js.map +1 -0
- package/lib/llm/candidates.d.ts +57 -0
- package/lib/llm/candidates.d.ts.map +1 -0
- package/lib/llm/candidates.js +86 -0
- package/lib/llm/candidates.js.map +1 -0
- package/lib/llm/recovery.d.ts +48 -0
- package/lib/llm/recovery.d.ts.map +1 -0
- package/lib/llm/recovery.js +118 -0
- package/lib/llm/recovery.js.map +1 -0
- package/lib/llm/retry.d.ts +35 -0
- package/lib/llm/retry.d.ts.map +1 -0
- package/lib/llm/retry.js +53 -0
- package/lib/llm/retry.js.map +1 -0
- package/lib/plans.d.ts +59 -0
- package/lib/plans.d.ts.map +1 -0
- package/lib/plans.js +118 -0
- package/lib/plans.js.map +1 -0
- package/lib/session-title.d.ts +63 -0
- package/lib/session-title.d.ts.map +1 -0
- package/lib/session-title.js +280 -0
- package/lib/session-title.js.map +1 -0
- package/lib/settings.d.ts +35 -0
- package/lib/settings.d.ts.map +1 -0
- package/lib/settings.js +78 -0
- package/lib/settings.js.map +1 -0
- package/lib/tools/account.d.ts +11 -0
- package/lib/tools/account.d.ts.map +1 -0
- package/lib/tools/account.js +132 -0
- package/lib/tools/account.js.map +1 -0
- package/lib/tools/billing.d.ts +10 -0
- package/lib/tools/billing.d.ts.map +1 -0
- package/lib/tools/billing.js +100 -0
- package/lib/tools/billing.js.map +1 -0
- package/lib/tools/count-tokens.d.ts +11 -0
- package/lib/tools/count-tokens.d.ts.map +1 -0
- package/lib/tools/count-tokens.js +84 -0
- package/lib/tools/count-tokens.js.map +1 -0
- package/lib/tools/data.d.ts +12 -0
- package/lib/tools/data.d.ts.map +1 -0
- package/lib/tools/data.js +205 -0
- package/lib/tools/data.js.map +1 -0
- package/lib/tools/docs.d.ts +13 -0
- package/lib/tools/docs.d.ts.map +1 -0
- package/lib/tools/docs.js +209 -0
- package/lib/tools/docs.js.map +1 -0
- package/lib/tools/documents.d.ts +10 -0
- package/lib/tools/documents.d.ts.map +1 -0
- package/lib/tools/documents.js +118 -0
- package/lib/tools/documents.js.map +1 -0
- package/lib/tools/media.d.ts +28 -0
- package/lib/tools/media.d.ts.map +1 -0
- package/lib/tools/media.js +599 -0
- package/lib/tools/media.js.map +1 -0
- package/lib/tools/shared.d.ts +89 -0
- package/lib/tools/shared.d.ts.map +1 -0
- package/lib/tools/shared.js +128 -0
- package/lib/tools/shared.js.map +1 -0
- package/lib/tools/x-search.d.ts +11 -0
- package/lib/tools/x-search.d.ts.map +1 -0
- package/lib/tools/x-search.js +129 -0
- package/lib/tools/x-search.js.map +1 -0
- package/lib/web/fallback.d.ts +39 -0
- package/lib/web/fallback.d.ts.map +1 -0
- package/lib/web/fallback.js +79 -0
- package/lib/web/fallback.js.map +1 -0
- package/lib/web/fetch.d.ts +19 -0
- package/lib/web/fetch.d.ts.map +1 -0
- package/lib/web/fetch.js +41 -0
- package/lib/web/fetch.js.map +1 -0
- package/lib/web/search.d.ts +21 -0
- package/lib/web/search.d.ts.map +1 -0
- package/lib/web/search.js +47 -0
- package/lib/web/search.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 文档与模型目录工具:kenari_search_docs(本地检索 /llms-full.txt,无需 key)
|
|
3
|
+
* 与 kenari_list_models(目录走 catalog.ts 的 TTL 缓存,公开端点)。
|
|
4
|
+
* @module dsh-kenari-plugin/tools/docs
|
|
5
|
+
*/
|
|
6
|
+
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
7
|
+
import { formatPricingLines, formatTokenPrice } from '../catalog.js';
|
|
8
|
+
/** /llms-full.txt 的内存缓存:文档量大(约 130KB),进程内只抓一次。 */
|
|
9
|
+
let llmsFullCache;
|
|
10
|
+
/** 文档全文抓取(公开端点,无需 key);失败上抛由 execute 层转错误文本。 */
|
|
11
|
+
async function fetchLlmsFull(ttlMs) {
|
|
12
|
+
if (ttlMs > 0 && llmsFullCache !== undefined && Date.now() - llmsFullCache.fetchedAt < ttlMs) {
|
|
13
|
+
return llmsFullCache.text;
|
|
14
|
+
}
|
|
15
|
+
const response = await fetch('https://kenari.id/llms-full.txt', {
|
|
16
|
+
headers: { Accept: 'text/plain' },
|
|
17
|
+
signal: AbortSignal.timeout(30_000),
|
|
18
|
+
});
|
|
19
|
+
if (!response.ok)
|
|
20
|
+
throw new Error(`llms-full.txt HTTP ${response.status}`);
|
|
21
|
+
const text = await response.text();
|
|
22
|
+
llmsFullCache = { text, fetchedAt: Date.now() };
|
|
23
|
+
return text;
|
|
24
|
+
}
|
|
25
|
+
/** 文档分节:按一级/二级标题切,保留标题行以便模型引用章节名。 */
|
|
26
|
+
function splitSections(text) {
|
|
27
|
+
const sections = [];
|
|
28
|
+
const lines = text.split('\n');
|
|
29
|
+
let title = '(前言)';
|
|
30
|
+
let body = [];
|
|
31
|
+
for (const line of lines) {
|
|
32
|
+
if (/^#{1,2} /.test(line)) {
|
|
33
|
+
if (body.length > 0)
|
|
34
|
+
sections.push({ title, body: body.join('\n') });
|
|
35
|
+
title = line.replace(/^#+ /, '');
|
|
36
|
+
body = [];
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
body.push(line);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (body.length > 0)
|
|
43
|
+
sections.push({ title, body: body.join('\n') });
|
|
44
|
+
return sections;
|
|
45
|
+
}
|
|
46
|
+
/** 命中打分:查询词按出现次数累加,标题命中权重 ×4。 */
|
|
47
|
+
function scoreSection(section, terms) {
|
|
48
|
+
let score = 0;
|
|
49
|
+
const titleLower = section.title.toLowerCase();
|
|
50
|
+
const bodyLower = section.body.toLowerCase();
|
|
51
|
+
for (const term of terms) {
|
|
52
|
+
const t = term.toLowerCase();
|
|
53
|
+
if (t.length === 0)
|
|
54
|
+
continue;
|
|
55
|
+
let inTitle = 0;
|
|
56
|
+
let idx = titleLower.indexOf(t);
|
|
57
|
+
while (idx !== -1) {
|
|
58
|
+
inTitle++;
|
|
59
|
+
idx = titleLower.indexOf(t, idx + t.length);
|
|
60
|
+
}
|
|
61
|
+
score += inTitle * 4;
|
|
62
|
+
let inBody = 0;
|
|
63
|
+
idx = bodyLower.indexOf(t);
|
|
64
|
+
while (idx !== -1) {
|
|
65
|
+
inBody++;
|
|
66
|
+
idx = bodyLower.indexOf(t, idx + t.length);
|
|
67
|
+
}
|
|
68
|
+
score += inBody;
|
|
69
|
+
}
|
|
70
|
+
return score;
|
|
71
|
+
}
|
|
72
|
+
/** 单节正文截断:够 context 而不淹没模型。 */
|
|
73
|
+
const SECTION_BODY_CHARS = 2500;
|
|
74
|
+
/** 模型条目 → 人读多行块(能力、上下文、价格、非 token 单价、告警)。 */
|
|
75
|
+
export function formatModelEntry(resolved) {
|
|
76
|
+
const model = resolved.model;
|
|
77
|
+
const bits = [];
|
|
78
|
+
bits.push(`ctx ${model.context_length ?? '未知'}`);
|
|
79
|
+
if (model.tool_call === true)
|
|
80
|
+
bits.push('工具调用');
|
|
81
|
+
if (model.reasoning === true) {
|
|
82
|
+
const options = model.reasoning_options ?? [];
|
|
83
|
+
bits.push(options.length > 0 ? `推理(${options.join('/')})` : '推理');
|
|
84
|
+
}
|
|
85
|
+
if (model.owned_by !== undefined)
|
|
86
|
+
bits.push(`by ${model.owned_by}`);
|
|
87
|
+
const inputModalities = model.modalities?.input ?? [];
|
|
88
|
+
if (inputModalities.length > 0)
|
|
89
|
+
bits.push(`输入 ${inputModalities.join('+')}`);
|
|
90
|
+
const lines = [`- ${model.id}${resolved.free ? '(免费)' : ''} — ${bits.join(',')}`, ` ${formatTokenPrice(model)}`];
|
|
91
|
+
const pricingLines = formatPricingLines(model);
|
|
92
|
+
if (pricingLines.length > 0)
|
|
93
|
+
lines.push(` ${pricingLines.join(';')}`);
|
|
94
|
+
const aliases = resolved.aliases.filter((alias) => alias !== model.id);
|
|
95
|
+
if (aliases.length > 0)
|
|
96
|
+
lines.push(` 别名:${aliases.join('、')}`);
|
|
97
|
+
for (const warning of resolved.warnings)
|
|
98
|
+
lines.push(` ⚠️ ${warning}`);
|
|
99
|
+
return lines.join('\n');
|
|
100
|
+
}
|
|
101
|
+
/** 免费模型首选(新账户 Rp 0 也能跑通全流程)。 */
|
|
102
|
+
const RECOMMENDED_FREE_MODEL = 'step-3-7-flash:free';
|
|
103
|
+
/** 注册文档检索与模型目录两个公开工具(不消耗余额)。 */
|
|
104
|
+
export function registerDocsTools(deps, register) {
|
|
105
|
+
register(defineTool({
|
|
106
|
+
name: 'kenari_search_docs',
|
|
107
|
+
description: 'Search the Kenari (kenari.id) documentation — quickstart, API reference, billing, routing, BYOK, error codes. Free, no API key needed.',
|
|
108
|
+
parameters: {
|
|
109
|
+
query: { type: 'string', required: true, description: 'What to look up, e.g. "streaming", "error codes", "shared keys".' },
|
|
110
|
+
},
|
|
111
|
+
output: {
|
|
112
|
+
schema: {
|
|
113
|
+
type: 'object',
|
|
114
|
+
additionalProperties: false,
|
|
115
|
+
properties: {
|
|
116
|
+
text: { type: 'string', required: true },
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
render: (_args, value) => [{ type: 'text', text: value.text }],
|
|
120
|
+
},
|
|
121
|
+
timeoutMs: 45_000,
|
|
122
|
+
isConcurrencySafe: () => true,
|
|
123
|
+
async execute(args) {
|
|
124
|
+
try {
|
|
125
|
+
const full = await fetchLlmsFull(deps.config.docsCacheTtlMs ?? 3_600_000);
|
|
126
|
+
const terms = args.query.split(/[\s,,、]+/).filter((term) => term.length > 0);
|
|
127
|
+
if (terms.length === 0) {
|
|
128
|
+
return { text: '查询为空:请给出检索词。' };
|
|
129
|
+
}
|
|
130
|
+
const scored = splitSections(full)
|
|
131
|
+
.map((section) => ({ section, score: scoreSection(section, terms) }))
|
|
132
|
+
.filter((entry) => entry.score > 0)
|
|
133
|
+
.sort((a, b) => b.score - a.score)
|
|
134
|
+
.slice(0, 4);
|
|
135
|
+
if (scored.length === 0) {
|
|
136
|
+
return { text: `文档中没有匹配 "${args.query}" 的章节。可尝试的检索词:streaming、error codes、billing、BYOK、routing、tools。` };
|
|
137
|
+
}
|
|
138
|
+
const parts = scored.map(({ section, score }) => {
|
|
139
|
+
const body = section.body.length > SECTION_BODY_CHARS ? `${section.body.slice(0, SECTION_BODY_CHARS)}\n…(已截断)` : section.body;
|
|
140
|
+
return `## ${section.title}\n${body}\n(相关度 ${score})`;
|
|
141
|
+
});
|
|
142
|
+
return { text: `Kenari 文档检索结果(${scored.length} 节,来源 https://kenari.id/llms-full.txt):\n\n${parts.join('\n\n')}` };
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
return { text: `kenari 文档检索失败:${String(err)}` };
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
}));
|
|
149
|
+
register(defineTool({
|
|
150
|
+
name: 'kenari_list_models',
|
|
151
|
+
description: 'List Kenari models with live per-token IDR prices, context window, capabilities, and non-token unit prices. Public catalog, free. Filter by id/provider substring, by specialized modality, or to free models only.',
|
|
152
|
+
parameters: {
|
|
153
|
+
search: { type: 'string', description: 'Optional substring to filter by model id or provider.' },
|
|
154
|
+
modality: {
|
|
155
|
+
type: 'string',
|
|
156
|
+
description: 'Omit this for chat/session models (the common case). Set it only to list a specialized capability catalog instead of chat models.',
|
|
157
|
+
enum: ['embedding', 'rerank', 'moderation'],
|
|
158
|
+
},
|
|
159
|
+
free_only: { type: 'boolean', description: 'Return only free models (id ends with :free or pricing.free).' },
|
|
160
|
+
},
|
|
161
|
+
output: {
|
|
162
|
+
schema: {
|
|
163
|
+
type: 'object',
|
|
164
|
+
additionalProperties: false,
|
|
165
|
+
properties: {
|
|
166
|
+
text: { type: 'string', required: true },
|
|
167
|
+
free_ids: { type: 'array', items: { type: 'string' } },
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
render: (_args, value) => [{ type: 'text', text: value.text }],
|
|
171
|
+
},
|
|
172
|
+
timeoutMs: 30_000,
|
|
173
|
+
isConcurrencySafe: () => true,
|
|
174
|
+
async execute(args) {
|
|
175
|
+
const all = await deps.catalog.list(args.modality);
|
|
176
|
+
const described = all.map((model) => deps.catalog.describe(model));
|
|
177
|
+
const search = args.search?.toLowerCase();
|
|
178
|
+
const filtered = described.filter((entry) => {
|
|
179
|
+
if (args.free_only === true && !entry.free)
|
|
180
|
+
return false;
|
|
181
|
+
if (search === undefined || search.length === 0)
|
|
182
|
+
return true;
|
|
183
|
+
return entry.id.toLowerCase().includes(search) || (entry.model.owned_by ?? '').toLowerCase().includes(search);
|
|
184
|
+
});
|
|
185
|
+
const freeIds = described.filter((entry) => entry.free).map((entry) => entry.id);
|
|
186
|
+
if (filtered.length === 0) {
|
|
187
|
+
return {
|
|
188
|
+
text: `目录中没有匹配的模型(search=${args.search ?? '(无)'}, modality=${args.modality ?? 'chat'}, free_only=${args.free_only === true ? '是' : '否'})。`,
|
|
189
|
+
free_ids: freeIds,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
const free = filtered.filter((entry) => entry.free);
|
|
193
|
+
const paid = filtered.filter((entry) => !entry.free);
|
|
194
|
+
const sections = [];
|
|
195
|
+
if (free.length > 0)
|
|
196
|
+
sections.push(`【免费模型 ${free.length} 个】\n${free.map(formatModelEntry).join('\n')}`);
|
|
197
|
+
if (paid.length > 0)
|
|
198
|
+
sections.push(`【付费模型 ${paid.length} 个】\n${paid.map(formatModelEntry).join('\n')}`);
|
|
199
|
+
const hint = freeIds.includes(RECOMMENDED_FREE_MODEL)
|
|
200
|
+
? `\n\n新账户(Rp 0)建议先用 ${RECOMMENDED_FREE_MODEL}:免费且在三条协议线上都可用。`
|
|
201
|
+
: '';
|
|
202
|
+
return {
|
|
203
|
+
text: `Kenari 模型目录(${filtered.length}/${all.length} 个,token 价格单位 IDR / 1M tokens):\n\n${sections.join('\n\n')}${hint}`,
|
|
204
|
+
free_ids: freeIds,
|
|
205
|
+
};
|
|
206
|
+
},
|
|
207
|
+
}));
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=docs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../../src/tools/docs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OCR 工具:POST /v1/ocr,按页计费;reuse_id 复用已解析文档不再计费。
|
|
3
|
+
* 会话内复用:同一次 execute 的返回值带 reuse_id,模型下次直接回传即免重复扣费。
|
|
4
|
+
* @module dsh-kenari-plugin/tools/documents
|
|
5
|
+
*/
|
|
6
|
+
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
7
|
+
import type { ToolsDeps } from './shared.js';
|
|
8
|
+
/** 注册 kenari_ocr。 */
|
|
9
|
+
export declare function registerOcrTool(deps: ToolsDeps, register: (tool: ReturnType<typeof defineTool>) => void): void;
|
|
10
|
+
//# sourceMappingURL=documents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/tools/documents.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAwB5C,qBAAqB;AACrB,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,KAAK,IAAI,GAAG,IAAI,CAgF9G"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OCR 工具:POST /v1/ocr,按页计费;reuse_id 复用已解析文档不再计费。
|
|
3
|
+
* 会话内复用:同一次 execute 的返回值带 reuse_id,模型下次直接回传即免重复扣费。
|
|
4
|
+
* @module dsh-kenari-plugin/tools/documents
|
|
5
|
+
*/
|
|
6
|
+
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
7
|
+
import { billSpend, spendGuard } from './shared.js';
|
|
8
|
+
import { kenariPost } from '../http.js';
|
|
9
|
+
/** data URL 解析:`data:<media-type>;base64,<payload>`,负载要求 canonical base64。 */
|
|
10
|
+
function parseDataUrl(dataUrl) {
|
|
11
|
+
const match = /^data:([!#$%&'*+.^_`|~a-zA-Z0-9/-]+);base64,([A-Za-z0-9+/]+={0,2})$/.exec(dataUrl);
|
|
12
|
+
if (match === null) {
|
|
13
|
+
throw new Error('file_data 必须是 data:<media-type>;base64,<内容> 形式的 data URL(Kenari 不抓取 http URL)');
|
|
14
|
+
}
|
|
15
|
+
return { mediaType: match[1], bytes: Uint8Array.from(Buffer.from(match[2], 'base64')) };
|
|
16
|
+
}
|
|
17
|
+
/** Kenari 接受的文档媒体类型(OpenAPI:pdf 与四种位图)。 */
|
|
18
|
+
const ACCEPTED_MEDIA_TYPES = new Set([
|
|
19
|
+
'application/pdf',
|
|
20
|
+
'image/png',
|
|
21
|
+
'image/jpeg',
|
|
22
|
+
'image/webp',
|
|
23
|
+
'image/gif',
|
|
24
|
+
'image/tiff',
|
|
25
|
+
]);
|
|
26
|
+
/** 注册 kenari_ocr。 */
|
|
27
|
+
export function registerOcrTool(deps, register) {
|
|
28
|
+
register(defineTool({
|
|
29
|
+
name: 'kenari_ocr',
|
|
30
|
+
description: 'Read a PDF or document image to text via Kenari OCR. Billed per page from your Kenari balance (~15 MB limit). Send file_data as a data URL, or pass reuse_id from a previous call to re-read the same document free of charge.',
|
|
31
|
+
parameters: {
|
|
32
|
+
file_data: { type: 'string', description: 'The document as a data URL: data:application/pdf;base64,... or an image data URL. Provide this OR reuse_id, never both.' },
|
|
33
|
+
reuse_id: { type: 'string', description: 'Echo of a previously issued reuse_id to serve the stored reading at no cost. Provide this OR file_data, never both.' },
|
|
34
|
+
},
|
|
35
|
+
output: {
|
|
36
|
+
schema: {
|
|
37
|
+
type: 'object',
|
|
38
|
+
additionalProperties: false,
|
|
39
|
+
properties: {
|
|
40
|
+
reuse_id: { type: 'string', required: true },
|
|
41
|
+
pages: { type: 'integer' },
|
|
42
|
+
cost_micro_idr: { type: 'integer' },
|
|
43
|
+
text: { type: 'string', required: true },
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
render: (_args, value) => [{ type: 'text', text: value.text }],
|
|
47
|
+
},
|
|
48
|
+
timeoutMs: 400_000,
|
|
49
|
+
isConcurrencySafe: () => true,
|
|
50
|
+
async execute(args, exec) {
|
|
51
|
+
spendGuard(deps, exec, 'kenari_ocr');
|
|
52
|
+
if (args.file_data !== undefined && args.reuse_id !== undefined) {
|
|
53
|
+
throw new Error('file_data 与 reuse_id 不可同时提供');
|
|
54
|
+
}
|
|
55
|
+
if (args.file_data === undefined && args.reuse_id === undefined) {
|
|
56
|
+
throw new Error('必须提供 file_data(data URL)或 reuse_id 之一');
|
|
57
|
+
}
|
|
58
|
+
const body = { engine: 'ocr' };
|
|
59
|
+
if (args.reuse_id !== undefined) {
|
|
60
|
+
body.reuse_id = args.reuse_id;
|
|
61
|
+
}
|
|
62
|
+
else if (args.file_data !== undefined) {
|
|
63
|
+
// OpenAPI 要求 file: { filename, file_data };filename 从数据源推断
|
|
64
|
+
const parsed = parseDataUrl(args.file_data);
|
|
65
|
+
if (!ACCEPTED_MEDIA_TYPES.has(parsed.mediaType)) {
|
|
66
|
+
throw new Error(`不支持的媒体类型 ${parsed.mediaType}:接受 application/pdf、image/png、image/jpeg、image/webp、image/gif、image/tiff`);
|
|
67
|
+
}
|
|
68
|
+
const ext = mediaExtension(parsed.mediaType);
|
|
69
|
+
body.file = { filename: `document${ext}`, file_data: args.file_data };
|
|
70
|
+
}
|
|
71
|
+
// OCR 按页计费:长超时(大文档),超时不重试以免重复扣费
|
|
72
|
+
const ocrOptions = {
|
|
73
|
+
timeoutMs: deps.http.config.generationTimeoutMs ?? 180_000,
|
|
74
|
+
retries: 1,
|
|
75
|
+
retryTimeouts: false,
|
|
76
|
+
};
|
|
77
|
+
const result = await kenariPost(deps.http, '/ocr', body, undefined, ocrOptions);
|
|
78
|
+
if (result.reuse_id === undefined) {
|
|
79
|
+
throw new Error('kenari: OCR 响应缺少 reuse_id,无法建立会话内复用');
|
|
80
|
+
}
|
|
81
|
+
const text = (result.content ?? [])
|
|
82
|
+
.map((block) => block.text ?? '')
|
|
83
|
+
.filter((part) => part.length > 0)
|
|
84
|
+
.join('\n\n');
|
|
85
|
+
const summary = [
|
|
86
|
+
`OCR 完成:${result.pages ?? '?'} 页,置信度${result.confidence === null || result.confidence === undefined ? '未知' : ` ${Math.round(result.confidence * 100)}%`}${result.low_confidence === true ? '(低置信度告警)' : ''}。`,
|
|
87
|
+
`复用凭证 reuse_id:${result.reuse_id} —— 下次读同一文档传这个 id,不再计费。`,
|
|
88
|
+
];
|
|
89
|
+
summary.push('', text);
|
|
90
|
+
const billed = await billSpend(deps, exec, {
|
|
91
|
+
tool: 'kenari_ocr',
|
|
92
|
+
costMicroIdr: result.cost_micro_idr,
|
|
93
|
+
note: result.cost_micro_idr === 0 ? '复用命中,本次免费' : '按页计费',
|
|
94
|
+
});
|
|
95
|
+
if (billed.length > 0)
|
|
96
|
+
summary.push(billed.trimStart());
|
|
97
|
+
return {
|
|
98
|
+
reuse_id: result.reuse_id,
|
|
99
|
+
...(result.pages !== undefined ? { pages: result.pages } : {}),
|
|
100
|
+
...(result.cost_micro_idr !== undefined ? { cost_micro_idr: result.cost_micro_idr } : {}),
|
|
101
|
+
text: summary.join('\n'),
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
/** 媒体类型 → 文件扩展名(仅用于 filename 字段)。 */
|
|
107
|
+
function mediaExtension(mediaType) {
|
|
108
|
+
switch (mediaType) {
|
|
109
|
+
case 'application/pdf': return '.pdf';
|
|
110
|
+
case 'image/png': return '.png';
|
|
111
|
+
case 'image/jpeg': return '.jpg';
|
|
112
|
+
case 'image/webp': return '.webp';
|
|
113
|
+
case 'image/gif': return '.gif';
|
|
114
|
+
case 'image/tiff': return '.tiff';
|
|
115
|
+
default: return '';
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=documents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documents.js","sourceRoot":"","sources":["../../src/tools/documents.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 媒体工具族:图像生成/编辑、语音合成/转写、音乐生成、视频生成/续写/状态/下载。
|
|
3
|
+
* 二进制产物(图像、音频、视频)经 ctx.attachments 落盘;attachment ref 是纯 JSON,
|
|
4
|
+
* 放进规范 value 由 render 重建 image/file block,模型与 UI 都能看到产物。
|
|
5
|
+
* @module dsh-kenari-plugin/tools/media
|
|
6
|
+
*/
|
|
7
|
+
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
8
|
+
import type { ContentBlock } from '@deepseek-ai/dsh-llm';
|
|
9
|
+
import type { ToolsDeps } from './shared.js';
|
|
10
|
+
/** 规范 value 里的产物描述:kind 决定 render 重建成 image 还是 file block。 */
|
|
11
|
+
export interface MediaAttachmentValue {
|
|
12
|
+
kind: 'image' | 'file';
|
|
13
|
+
/** ImageAttachmentRef 字段(image)。 */
|
|
14
|
+
attachmentId: string;
|
|
15
|
+
mediaType?: string;
|
|
16
|
+
width?: number;
|
|
17
|
+
height?: number;
|
|
18
|
+
/** FileAttachmentRef 字段(file)。 */
|
|
19
|
+
name?: string;
|
|
20
|
+
bytes: number;
|
|
21
|
+
}
|
|
22
|
+
/** 规范 value 的 attachments → ContentBlock(render 用;损坏的 ref 退化为文本)。 */
|
|
23
|
+
export declare function renderAttachments(value: {
|
|
24
|
+
attachments?: MediaAttachmentValue[];
|
|
25
|
+
}): ContentBlock[];
|
|
26
|
+
/** 注册媒体工具族。 */
|
|
27
|
+
export declare function registerMediaTools(deps: ToolsDeps, register: (tool: ReturnType<typeof defineTool>) => void): void;
|
|
28
|
+
//# sourceMappingURL=media.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../src/tools/media.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAExD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAI5C,8DAA8D;AAC9D,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAA;IACtB,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAuDD,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IAAE,WAAW,CAAC,EAAE,oBAAoB,EAAE,CAAA;CAAE,GAAG,YAAY,EAAE,CAuBjG;AAiED,eAAe;AACf,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,KAAK,IAAI,GAAG,IAAI,CAsajH"}
|