@gird/ccli 2.15.0 → 2.18.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/README.md +22 -6
- package/dist/agent/ai.js +10 -345
- package/dist/agent/ai.js.map +1 -1
- package/dist/agent/providers/anthropic.js +258 -0
- package/dist/agent/providers/anthropic.js.map +1 -0
- package/dist/agent/providers/gemini.js +14 -0
- package/dist/agent/providers/gemini.js.map +1 -0
- package/dist/agent/providers/openai.js +110 -0
- package/dist/agent/providers/openai.js.map +1 -0
- package/dist/agent/tool-projection.js +57 -0
- package/dist/agent/tool-projection.js.map +1 -0
- package/dist/cli/args/index.js +4 -0
- package/dist/cli/args/index.js.map +1 -1
- package/dist/cli/clipboard-image.js +51 -0
- package/dist/cli/clipboard-image.js.map +1 -0
- package/dist/cli/image-compress.js +62 -0
- package/dist/cli/image-compress.js.map +1 -0
- package/dist/cli/image-reference.js +190 -0
- package/dist/cli/image-reference.js.map +1 -0
- package/dist/cli/repl/index.js +110 -60
- package/dist/cli/repl/index.js.map +1 -1
- package/dist/cli/run/event-renderer.js +57 -0
- package/dist/cli/run/event-renderer.js.map +1 -0
- package/dist/cli/run/hooks.js +58 -19
- package/dist/cli/run/hooks.js.map +1 -1
- package/dist/cli/run/index.js +218 -9
- package/dist/cli/run/index.js.map +1 -1
- package/dist/cli/run/task.js +58 -1
- package/dist/cli/run/task.js.map +1 -1
- package/dist/cli/run/todo-panel.js +13 -0
- package/dist/cli/run/todo-panel.js.map +1 -1
- package/dist/cli/session/checkpoint.js +252 -0
- package/dist/cli/session/checkpoint.js.map +1 -0
- package/dist/cli/session/index.js +1 -1
- package/dist/cli/session/index.js.map +1 -1
- package/dist/cli/slash/index.js +26 -2
- package/dist/cli/slash/index.js.map +1 -1
- package/dist/cli/slash/session/load.js +3 -0
- package/dist/cli/slash/session/load.js.map +1 -1
- package/dist/cli/slash/session/replay.js +118 -0
- package/dist/cli/slash/session/replay.js.map +1 -0
- package/dist/cli/slash/session/save.js +1 -0
- package/dist/cli/slash/session/save.js.map +1 -1
- package/dist/cli/slash/system/agent.js +38 -104
- package/dist/cli/slash/system/agent.js.map +1 -1
- package/dist/cli/slash/system/compact.js +26 -5
- package/dist/cli/slash/system/compact.js.map +1 -1
- package/dist/cli/slash/system/goal.js +34 -34
- package/dist/cli/slash/system/goal.js.map +1 -1
- package/dist/cli/slash/system/help.js +3 -0
- package/dist/cli/slash/system/help.js.map +1 -1
- package/dist/cli/slash/system/plan.js +140 -0
- package/dist/cli/slash/system/plan.js.map +1 -0
- package/dist/cli/slash/system/revert.js +133 -0
- package/dist/cli/slash/system/revert.js.map +1 -0
- package/dist/config/config.js +57 -4
- package/dist/config/config.js.map +1 -1
- package/dist/config/plugins.js +378 -0
- package/dist/config/plugins.js.map +1 -0
- package/dist/config/skills.js +68 -6
- package/dist/config/skills.js.map +1 -1
- package/dist/harness/index.js +334 -0
- package/dist/harness/index.js.map +1 -0
- package/dist/harness/records.js +98 -0
- package/dist/harness/records.js.map +1 -0
- package/dist/index.js +87 -42
- package/dist/index.js.map +1 -1
- package/dist/tools/bash-background.js +2 -2
- package/dist/tools/bash-background.js.map +1 -1
- package/dist/tools/bash.js +3 -2
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/edit-file.js +8 -2
- package/dist/tools/edit-file.js.map +1 -1
- package/dist/tools/glob.js +4 -3
- package/dist/tools/glob.js.map +1 -1
- package/dist/tools/grep.js +4 -3
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/index.js +20 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/list-dir.js +3 -2
- package/dist/tools/list-dir.js.map +1 -1
- package/dist/tools/read-file.js +3 -2
- package/dist/tools/read-file.js.map +1 -1
- package/dist/tools/shared.js.map +1 -1
- package/dist/tools/todo.js +17 -5
- package/dist/tools/todo.js.map +1 -1
- package/dist/tools/web-fetch.js +95 -0
- package/dist/tools/web-fetch.js.map +1 -0
- package/dist/tools/write-file.js +8 -2
- package/dist/tools/write-file.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
2
|
+
import { toolDefs } from '../../tools/index.js';
|
|
3
|
+
import { projectToolPairedMessages } from '../tool-projection.js';
|
|
4
|
+
export class AnthropicClient {
|
|
5
|
+
client;
|
|
6
|
+
model;
|
|
7
|
+
/** 保存 Anthropic SDK 实例;baseURL 仅在用户配置代理或兼容网关时生效。 */
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.client = new Anthropic({
|
|
10
|
+
apiKey: config.apiKey,
|
|
11
|
+
baseURL: config.baseURL,
|
|
12
|
+
});
|
|
13
|
+
this.model = config.model;
|
|
14
|
+
}
|
|
15
|
+
/** 返回当前 Claude 模型名,保持与 OpenAIClient 的统一接口。 */
|
|
16
|
+
getModel() {
|
|
17
|
+
return this.model;
|
|
18
|
+
}
|
|
19
|
+
/** 只更新后续请求使用的模型名,不影响已存在的历史消息。 */
|
|
20
|
+
setModel(model) {
|
|
21
|
+
this.model = model;
|
|
22
|
+
}
|
|
23
|
+
/** Claude 3 及以后全系支持图像;老的 claude-2 / instant 不支持。 */
|
|
24
|
+
supportsVision() {
|
|
25
|
+
return !/claude-2|claude-instant/i.test(this.model);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Anthropic SDK 没有稳定的模型列表接口,返回常用模型。
|
|
29
|
+
* 用户仍可用 /model <完整名> 切换到列表外的模型。
|
|
30
|
+
*/
|
|
31
|
+
async listModels() {
|
|
32
|
+
return [
|
|
33
|
+
'claude-opus-4-5-20251101',
|
|
34
|
+
'claude-sonnet-4-5-20251101',
|
|
35
|
+
'claude-sonnet-4-5-20241022',
|
|
36
|
+
'claude-3-5-sonnet-20241022',
|
|
37
|
+
'claude-3-opus-20240229',
|
|
38
|
+
'claude-3-sonnet-20240229',
|
|
39
|
+
'claude-3-haiku-20240307',
|
|
40
|
+
].sort();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 发送 Anthropic Messages 流式请求。
|
|
44
|
+
*
|
|
45
|
+
* 这里会先把 OpenAI 风格历史转换成 Anthropic 的 system/messages/tool_use 结构,
|
|
46
|
+
* 再把流式事件重新聚合成 CCLI 内部统一的 AssistantTurn。
|
|
47
|
+
*/
|
|
48
|
+
async chat(messages, onDelta, options, onReasoning, onToolArgumentDelta) {
|
|
49
|
+
const { system, messages: anthropicMessages } = toAnthropicMessages(messages);
|
|
50
|
+
const tools = toAnthropicTools(options?.allowedTools);
|
|
51
|
+
const stream = await this.client.messages.create({
|
|
52
|
+
model: this.model,
|
|
53
|
+
max_tokens: 4096,
|
|
54
|
+
system,
|
|
55
|
+
messages: anthropicMessages,
|
|
56
|
+
stream: true,
|
|
57
|
+
...(options?.disableTools
|
|
58
|
+
? {}
|
|
59
|
+
: {
|
|
60
|
+
tools,
|
|
61
|
+
...(options?.requireTools
|
|
62
|
+
? { tool_choice: { type: 'any' } }
|
|
63
|
+
: {}),
|
|
64
|
+
}),
|
|
65
|
+
});
|
|
66
|
+
let content = '';
|
|
67
|
+
const acc = {};
|
|
68
|
+
let usage;
|
|
69
|
+
// Anthropic 流式协议:input_tokens 只出现在 message_start 事件,
|
|
70
|
+
// message_delta 只带 output_tokens——两处都要读才能拼出完整 usage。
|
|
71
|
+
let inputTokens = 0;
|
|
72
|
+
for await (const event of stream) {
|
|
73
|
+
if (event.type === 'message_start') {
|
|
74
|
+
const u = event.message?.usage;
|
|
75
|
+
if (u)
|
|
76
|
+
inputTokens = u.input_tokens ?? 0;
|
|
77
|
+
}
|
|
78
|
+
else if (event.type === 'content_block_delta') {
|
|
79
|
+
if (event.delta.type === 'text_delta') {
|
|
80
|
+
content += event.delta.text;
|
|
81
|
+
onDelta(event.delta.text);
|
|
82
|
+
}
|
|
83
|
+
else if (event.delta.type === 'thinking_delta') {
|
|
84
|
+
onReasoning?.(event.delta.thinking);
|
|
85
|
+
}
|
|
86
|
+
else if (event.delta.type === 'input_json_delta') {
|
|
87
|
+
const tc = acc[event.index];
|
|
88
|
+
if (tc) {
|
|
89
|
+
tc.arguments += event.delta.partial_json;
|
|
90
|
+
if (tc.name) {
|
|
91
|
+
onToolArgumentDelta?.(event.index, tc.name, tc.arguments);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else if (event.type === 'content_block_start') {
|
|
97
|
+
if (event.content_block.type === 'tool_use') {
|
|
98
|
+
acc[event.index] = {
|
|
99
|
+
id: event.content_block.id,
|
|
100
|
+
name: event.content_block.name,
|
|
101
|
+
arguments: '',
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else if (event.type === 'message_delta') {
|
|
106
|
+
const u = event.usage;
|
|
107
|
+
if (u) {
|
|
108
|
+
const promptTokens = inputTokens || (u.input_tokens ?? 0);
|
|
109
|
+
const completionTokens = u.output_tokens ?? 0;
|
|
110
|
+
usage = {
|
|
111
|
+
promptTokens,
|
|
112
|
+
completionTokens,
|
|
113
|
+
totalTokens: promptTokens + completionTokens,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const toolCalls = Object.keys(acc)
|
|
119
|
+
.map(Number)
|
|
120
|
+
.sort((a, b) => a - b)
|
|
121
|
+
.map((i) => acc[i]);
|
|
122
|
+
return { content, toolCalls, usage };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* 把 OpenAI 风格的消息列表转成 Anthropic 的 system + messages。
|
|
127
|
+
*
|
|
128
|
+
* Anthropic 不接受 `role:"system"` 混在 messages 里,也要求 tool_result 作为 user
|
|
129
|
+
* 内容块出现,所以这里集中做一次协议投影,避免业务层到处写 provider 分支。
|
|
130
|
+
*/
|
|
131
|
+
export function toAnthropicMessages(messages) {
|
|
132
|
+
const projectedMessages = projectToolPairedMessages(messages);
|
|
133
|
+
const systemParts = [];
|
|
134
|
+
const anthropicMessages = [];
|
|
135
|
+
const pendingToolUseIds = [];
|
|
136
|
+
for (const m of projectedMessages) {
|
|
137
|
+
if (m.role === 'system') {
|
|
138
|
+
if (typeof m.content === 'string') {
|
|
139
|
+
systemParts.push(m.content);
|
|
140
|
+
}
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (m.role === 'tool') {
|
|
144
|
+
// Anthropic 的 tool_result 必须放在 user 消息里
|
|
145
|
+
const toolCallId = m.tool_call_id ?? '';
|
|
146
|
+
if (!pendingToolUseIds.includes(toolCallId)) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const resultText = typeof m.content === 'string' ? m.content : JSON.stringify(m.content);
|
|
150
|
+
anthropicMessages.push({
|
|
151
|
+
role: 'user',
|
|
152
|
+
content: [
|
|
153
|
+
{
|
|
154
|
+
type: 'tool_result',
|
|
155
|
+
tool_use_id: toolCallId,
|
|
156
|
+
content: resultText,
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
});
|
|
160
|
+
pendingToolUseIds.splice(pendingToolUseIds.indexOf(toolCallId), 1);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (m.role === 'assistant') {
|
|
164
|
+
const content = [];
|
|
165
|
+
if (typeof m.content === 'string' && m.content) {
|
|
166
|
+
content.push({ type: 'text', text: m.content });
|
|
167
|
+
}
|
|
168
|
+
const toolCalls = m.tool_calls;
|
|
169
|
+
if (Array.isArray(toolCalls)) {
|
|
170
|
+
for (const tc of toolCalls) {
|
|
171
|
+
if (!tc?.id || !tc?.function?.name) {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
content.push({
|
|
175
|
+
type: 'tool_use',
|
|
176
|
+
id: tc.id,
|
|
177
|
+
name: tc.function?.name ?? '',
|
|
178
|
+
input: safeParse(tc.function?.arguments ?? '{}'),
|
|
179
|
+
});
|
|
180
|
+
pendingToolUseIds.push(tc.id);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
anthropicMessages.push({ role: 'assistant', content });
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (m.role === 'user') {
|
|
187
|
+
if (typeof m.content === 'string') {
|
|
188
|
+
anthropicMessages.push({ role: 'user', content: m.content });
|
|
189
|
+
}
|
|
190
|
+
else if (Array.isArray(m.content)) {
|
|
191
|
+
// 多模态:把 OpenAI 风格的 text / image_url 片段翻译成 Anthropic block
|
|
192
|
+
const blocks = [];
|
|
193
|
+
for (const part of m.content) {
|
|
194
|
+
if (part?.type === 'text') {
|
|
195
|
+
blocks.push({ type: 'text', text: part.text });
|
|
196
|
+
}
|
|
197
|
+
else if (part?.type === 'image_url') {
|
|
198
|
+
const img = dataUrlToImageBlock(part.image_url?.url);
|
|
199
|
+
if (img)
|
|
200
|
+
blocks.push(img);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
anthropicMessages.push({
|
|
204
|
+
role: 'user',
|
|
205
|
+
content: blocks.length > 0 ? blocks : '',
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
anthropicMessages.push({
|
|
210
|
+
role: 'user',
|
|
211
|
+
content: JSON.stringify(m.content),
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return { system: systemParts.join('\n\n'), messages: anthropicMessages };
|
|
217
|
+
}
|
|
218
|
+
/** 把内部工具定义转成 Anthropic 的 tool 格式。
|
|
219
|
+
* 传 allowedNames 时只转换这些工具(与 OpenAI 路径一致)。 */
|
|
220
|
+
export function toAnthropicTools(allowedNames) {
|
|
221
|
+
return toolDefs(allowedNames).map((t) => ({
|
|
222
|
+
name: t.function.name,
|
|
223
|
+
description: t.function.description,
|
|
224
|
+
input_schema: {
|
|
225
|
+
type: 'object',
|
|
226
|
+
...t.function.parameters,
|
|
227
|
+
},
|
|
228
|
+
}));
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* 把 `data:<mime>;base64,<data>` 解析成 Anthropic 的 base64 image block。
|
|
232
|
+
* 非 data URL 或格式不符时返回 null(跳过该图,不阻断整段请求)。
|
|
233
|
+
*/
|
|
234
|
+
function dataUrlToImageBlock(url) {
|
|
235
|
+
if (typeof url !== 'string')
|
|
236
|
+
return null;
|
|
237
|
+
const m = /^data:([^;]+);base64,(.+)$/s.exec(url);
|
|
238
|
+
if (!m)
|
|
239
|
+
return null;
|
|
240
|
+
return {
|
|
241
|
+
type: 'image',
|
|
242
|
+
source: {
|
|
243
|
+
type: 'base64',
|
|
244
|
+
media_type: m[1],
|
|
245
|
+
data: m[2],
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/** 解析模型给出的工具参数;失败时回落为空对象,避免坏 JSON 破坏整段 Anthropic 请求。 */
|
|
250
|
+
function safeParse(json) {
|
|
251
|
+
try {
|
|
252
|
+
return JSON.parse(json);
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
return {};
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=anthropic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/agent/providers/anthropic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { OpenAIClient } from './openai.js';
|
|
2
|
+
/** Gemini 的 OpenAI 兼容端点(config.baseURL 未配置时的默认指向)。 */
|
|
3
|
+
export const DEFAULT_GEMINI_BASE_URL = 'https://generativelanguage.googleapis.com/v1beta/openai/';
|
|
4
|
+
/**
|
|
5
|
+
* Gemini 后端:走 Google 的 OpenAI 兼容协议,请求/流式聚合逻辑与
|
|
6
|
+
* OpenAIClient 完全一致,因此直接继承,只改默认 baseURL。
|
|
7
|
+
* (此前是 70 行逐字复制的 chat 循环,两处分叉风险已被继承结构消除。)
|
|
8
|
+
*/
|
|
9
|
+
export class GeminiClient extends OpenAIClient {
|
|
10
|
+
constructor(config) {
|
|
11
|
+
super({ ...config, baseURL: config.baseURL || DEFAULT_GEMINI_BASE_URL });
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=gemini.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../../src/agent/providers/gemini.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,sDAAsD;AACtD,MAAM,CAAC,MAAM,uBAAuB,GAChC,0DAA0D,CAAC;AAE/D;;;;GAIG;AACH,MAAM,OAAO,YAAa,SAAQ,YAAY;IAC1C,YAAY,MAAc;QACtB,KAAK,CAAC,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,uBAAuB,EAAE,CAAC,CAAC;IAC7E,CAAC;CACJ"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
import { toolDefs } from '../../tools/index.js';
|
|
3
|
+
import { projectToolPairedMessages } from '../tool-projection.js';
|
|
4
|
+
export class OpenAIClient {
|
|
5
|
+
client;
|
|
6
|
+
model;
|
|
7
|
+
/** 保存 OpenAI 兼容 SDK 实例;baseURL 可指向 Qwen / DeepSeek / GLM 等兼容服务。 */
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.client = new OpenAI({
|
|
10
|
+
apiKey: config.apiKey,
|
|
11
|
+
baseURL: config.baseURL,
|
|
12
|
+
});
|
|
13
|
+
this.model = config.model;
|
|
14
|
+
}
|
|
15
|
+
/** 当前模型名只存在本地,真正请求时才写入 body.model。 */
|
|
16
|
+
getModel() {
|
|
17
|
+
return this.model;
|
|
18
|
+
}
|
|
19
|
+
/** 切换模型时不清空模型列表缓存,因为同一后端的模型列表不随选择变化。 */
|
|
20
|
+
setModel(model) {
|
|
21
|
+
this.model = model;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 按模型名启发式判断是否支持图像输入。OpenAI 兼容后端型号繁杂,没有统一的
|
|
25
|
+
* capability 接口,只能靠常见命名规律匹配(qwen-vl / *-vision / gpt-4o /
|
|
26
|
+
* gemini / *-4v / omni 等)。宁可漏判降级为文字,也不误判导致后端报错。
|
|
27
|
+
*/
|
|
28
|
+
supportsVision() {
|
|
29
|
+
return /vl|vision|4o|omni|4v|gemini|internvl|llava|pixtral|claude/i.test(this.model);
|
|
30
|
+
}
|
|
31
|
+
/** 拉取后端可用模型列表(结果缓存,避免重复请求)。 */
|
|
32
|
+
modelCache;
|
|
33
|
+
async listModels() {
|
|
34
|
+
if (!this.modelCache) {
|
|
35
|
+
const list = await this.client.models.list();
|
|
36
|
+
this.modelCache = list.data.map((m) => m.id).sort();
|
|
37
|
+
}
|
|
38
|
+
return this.modelCache;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 发送整段对话历史,流式接收助手回复。
|
|
42
|
+
* @param messages 完整历史(含本轮 user 消息、以及可能的工具结果)
|
|
43
|
+
* @param onDelta 每收到一小段文本就回调(用于实时打印)
|
|
44
|
+
* @returns 助手本回合的文本 + 它想调用的工具
|
|
45
|
+
*/
|
|
46
|
+
async chat(messages, onDelta, options, onReasoning, onToolArgumentDelta) {
|
|
47
|
+
const body = {
|
|
48
|
+
model: this.model,
|
|
49
|
+
messages: projectToolPairedMessages(messages),
|
|
50
|
+
stream: true,
|
|
51
|
+
stream_options: { include_usage: true },
|
|
52
|
+
};
|
|
53
|
+
if (!options?.disableTools) {
|
|
54
|
+
body.tools = toolDefs(options?.allowedTools);
|
|
55
|
+
if (options?.requireTools) {
|
|
56
|
+
body.tool_choice = 'required';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const stream = (await this.client.chat.completions.create(body));
|
|
60
|
+
let content = '';
|
|
61
|
+
// 工具调用在流里是分片到达的,按 index 累加拼回完整的 id/name/arguments
|
|
62
|
+
const acc = {};
|
|
63
|
+
let usage;
|
|
64
|
+
for await (const chunk of stream) {
|
|
65
|
+
const delta = chunk.choices[0]?.delta;
|
|
66
|
+
if (!delta) {
|
|
67
|
+
// OpenAI 流式 usage 通常在 choices 为空的最终 chunk 里
|
|
68
|
+
const u = chunk.usage;
|
|
69
|
+
if (u) {
|
|
70
|
+
usage = {
|
|
71
|
+
promptTokens: u.prompt_tokens ?? 0,
|
|
72
|
+
completionTokens: u.completion_tokens ?? 0,
|
|
73
|
+
totalTokens: u.total_tokens ?? 0,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const reasoning = delta.reasoning_content;
|
|
79
|
+
if (reasoning)
|
|
80
|
+
onReasoning?.(reasoning);
|
|
81
|
+
if (delta.content) {
|
|
82
|
+
content += delta.content;
|
|
83
|
+
onDelta(delta.content);
|
|
84
|
+
}
|
|
85
|
+
for (const tc of delta.tool_calls ?? []) {
|
|
86
|
+
const cur = (acc[tc.index] ??= {
|
|
87
|
+
id: '',
|
|
88
|
+
name: '',
|
|
89
|
+
arguments: '',
|
|
90
|
+
});
|
|
91
|
+
if (tc.id)
|
|
92
|
+
cur.id = tc.id;
|
|
93
|
+
if (tc.function?.name)
|
|
94
|
+
cur.name = tc.function.name;
|
|
95
|
+
if (tc.function?.arguments) {
|
|
96
|
+
cur.arguments += tc.function.arguments;
|
|
97
|
+
if (cur.name) {
|
|
98
|
+
onToolArgumentDelta?.(tc.index, cur.name, cur.arguments);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const toolCalls = Object.keys(acc)
|
|
104
|
+
.map(Number)
|
|
105
|
+
.sort((a, b) => a - b)
|
|
106
|
+
.map((i) => acc[i]);
|
|
107
|
+
return { content, toolCalls, usage };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/agent/providers/openai.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 严格投影工具消息:只保留「assistant.tool_calls 后紧跟对应 tool 结果」
|
|
3
|
+
* 的完整配对,丢弃孤儿 tool 结果与未完成的 tool_calls,避免 provider
|
|
4
|
+
* 因 tool_use / tool_result 不配对拒绝整段上下文。
|
|
5
|
+
*/
|
|
6
|
+
export function projectToolPairedMessages(messages) {
|
|
7
|
+
const projected = [];
|
|
8
|
+
const pendingToolCallIds = [];
|
|
9
|
+
for (let i = 0; i < messages.length; i++) {
|
|
10
|
+
const m = messages[i];
|
|
11
|
+
if (m.role === 'tool') {
|
|
12
|
+
const toolCallId = m.tool_call_id;
|
|
13
|
+
const pendingIndex = pendingToolCallIds.indexOf(toolCallId);
|
|
14
|
+
if (pendingIndex < 0)
|
|
15
|
+
continue;
|
|
16
|
+
projected.push(m);
|
|
17
|
+
pendingToolCallIds.splice(pendingIndex, 1);
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (m.role === 'assistant') {
|
|
21
|
+
const toolCalls = m.tool_calls;
|
|
22
|
+
if (Array.isArray(toolCalls) && toolCalls.length > 0) {
|
|
23
|
+
const validToolCallIds = toolCalls
|
|
24
|
+
.map((tc) => tc?.id)
|
|
25
|
+
.filter((id) => typeof id === 'string' && id.length > 0);
|
|
26
|
+
const resultIds = collectFollowingToolResultIds(messages, i);
|
|
27
|
+
if (validToolCallIds.length !== toolCalls.length ||
|
|
28
|
+
!validToolCallIds.every((id) => resultIds.has(id))) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
projected.push(m);
|
|
32
|
+
pendingToolCallIds.push(...validToolCallIds);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
projected.push(m);
|
|
37
|
+
}
|
|
38
|
+
return projected;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 从某条 assistant.tool_calls 后面连续的 tool 消息里收集结果 id。
|
|
42
|
+
*
|
|
43
|
+
* 一旦遇到非 tool 消息就停止,因为 provider 语义要求 tool_result 紧跟对应 tool_use。
|
|
44
|
+
*/
|
|
45
|
+
function collectFollowingToolResultIds(messages, assistantIndex) {
|
|
46
|
+
const ids = new Set();
|
|
47
|
+
for (let i = assistantIndex + 1; i < messages.length; i++) {
|
|
48
|
+
const m = messages[i];
|
|
49
|
+
if (m.role !== 'tool')
|
|
50
|
+
break;
|
|
51
|
+
const id = m.tool_call_id;
|
|
52
|
+
if (id)
|
|
53
|
+
ids.add(id);
|
|
54
|
+
}
|
|
55
|
+
return ids;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=tool-projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-projection.js","sourceRoot":"","sources":["../../src/agent/tool-projection.ts"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,QAAuB;IAC7D,MAAM,SAAS,GAAkB,EAAE,CAAC;IACpC,MAAM,kBAAkB,GAAa,EAAE,CAAC;IAExC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAEtB,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,MAAM,UAAU,GAAI,CAAS,CAAC,YAAY,CAAC;YAC3C,MAAM,YAAY,GAAG,kBAAkB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAC5D,IAAI,YAAY,GAAG,CAAC;gBAAE,SAAS;YAC/B,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,kBAAkB,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;YAC3C,SAAS;QACb,CAAC;QAED,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACzB,MAAM,SAAS,GAAI,CAAS,CAAC,UAAU,CAAC;YACxC,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACnD,MAAM,gBAAgB,GAAG,SAAS;qBAC7B,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;qBACnB,MAAM,CAAC,CAAC,EAAE,EAAgB,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBAC3E,MAAM,SAAS,GAAG,6BAA6B,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;gBAC7D,IACI,gBAAgB,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM;oBAC5C,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EACpD,CAAC;oBACC,SAAS;gBACb,CAAC;gBACD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAClB,kBAAkB,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,CAAC;gBAC7C,SAAS;YACb,CAAC;QACL,CAAC;QAED,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC;AAED;;;;GAIG;AACH,SAAS,6BAA6B,CAClC,QAAuB,EACvB,cAAsB;IAEtB,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,cAAc,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxD,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;YAAE,MAAM;QAC7B,MAAM,EAAE,GAAI,CAAS,CAAC,YAAY,CAAC;QACnC,IAAI,EAAE;YAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC"}
|
package/dist/cli/args/index.js
CHANGED
|
@@ -10,6 +10,7 @@ export function parseArgs(argv) {
|
|
|
10
10
|
help: false,
|
|
11
11
|
yes: false,
|
|
12
12
|
noHooks: false,
|
|
13
|
+
project: false,
|
|
13
14
|
unknown: [],
|
|
14
15
|
positionals: [],
|
|
15
16
|
};
|
|
@@ -31,6 +32,9 @@ export function parseArgs(argv) {
|
|
|
31
32
|
case '--no-hooks':
|
|
32
33
|
result.noHooks = true;
|
|
33
34
|
break;
|
|
35
|
+
case '--project':
|
|
36
|
+
result.project = true;
|
|
37
|
+
break;
|
|
34
38
|
case '-r':
|
|
35
39
|
case '--role': {
|
|
36
40
|
const next = argv[i + 1];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/args/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/args/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAqBH,MAAM,UAAU,SAAS,CAAC,IAAc;IACpC,MAAM,MAAM,GAAe;QACvB,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,KAAK;QACX,GAAG,EAAE,KAAK;QACV,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,EAAE;QACX,WAAW,EAAE,EAAE;KAClB,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,QAAQ,GAAG,EAAE,CAAC;YACV,KAAK,IAAI,CAAC;YACV,KAAK,WAAW;gBACZ,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;gBACtB,MAAM;YACV,KAAK,IAAI,CAAC;YACV,KAAK,QAAQ;gBACT,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;gBACnB,MAAM;YACV,KAAK,IAAI,CAAC;YACV,KAAK,OAAO;gBACR,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC;gBAClB,MAAM;YACV,KAAK,YAAY;gBACb,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;gBACtB,MAAM;YACV,KAAK,WAAW;gBACZ,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;gBACtB,MAAM;YACV,KAAK,IAAI,CAAC;YACV,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACZ,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACzB,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBAChC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;oBACnB,CAAC,EAAE,CAAC;gBACR,CAAC;qBAAM,CAAC;oBACJ,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC7B,CAAC;gBACD,MAAM;YACV,CAAC;YACD;gBACI,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACtB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC7B,CAAC;qBAAM,CAAC;oBACJ,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACjC,CAAC;QACT,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 从系统剪贴板取图片(Ctrl-V 粘贴图片用)。
|
|
3
|
+
*
|
|
4
|
+
* 参考 Kimi Code:终端里 Cmd-V 会被终端 App 截走(程序收不到),所以走
|
|
5
|
+
* **Ctrl-V**——它能真正传到程序里。这里负责把剪贴板里的图像位图落成一个临时
|
|
6
|
+
* PNG 文件,交给已有的图片引用管线(`@路径`)发送。
|
|
7
|
+
*
|
|
8
|
+
* 目前仅实现 macOS(osascript,系统自带、无需装东西)。其它平台返回不支持,
|
|
9
|
+
* 后续可补 Linux(wl-paste / xclip)与 Windows(PowerShell)。
|
|
10
|
+
*/
|
|
11
|
+
import { execFileSync } from 'node:child_process';
|
|
12
|
+
import { randomUUID } from 'node:crypto';
|
|
13
|
+
import { existsSync, statSync } from 'node:fs';
|
|
14
|
+
import { tmpdir } from 'node:os';
|
|
15
|
+
import { join } from 'node:path';
|
|
16
|
+
/** osascript:把剪贴板内容按 PNG 写到 outPath;剪贴板无图会非零退出。 */
|
|
17
|
+
function readViaOsascript(outPath) {
|
|
18
|
+
execFileSync('osascript', [
|
|
19
|
+
'-e',
|
|
20
|
+
'set png to (the clipboard as «class PNGf»)',
|
|
21
|
+
'-e',
|
|
22
|
+
`set f to open for access POSIX file "${outPath}" with write permission`,
|
|
23
|
+
'-e',
|
|
24
|
+
'set eof f to 0',
|
|
25
|
+
'-e',
|
|
26
|
+
'write png to f',
|
|
27
|
+
'-e',
|
|
28
|
+
'close access f',
|
|
29
|
+
], { stdio: ['ignore', 'ignore', 'ignore'], timeout: 5000 });
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 取剪贴板图片,成功时返回落地的临时 PNG 路径。
|
|
33
|
+
* 剪贴板没有图片、平台不支持或提取失败都返回 `{ ok:false, reason }`。
|
|
34
|
+
*/
|
|
35
|
+
export function readClipboardImage() {
|
|
36
|
+
if (process.platform !== 'darwin') {
|
|
37
|
+
return { ok: false, reason: '当前平台暂不支持剪贴板取图(仅 macOS)' };
|
|
38
|
+
}
|
|
39
|
+
const outPath = join(tmpdir(), `ccli-paste-${randomUUID()}.png`);
|
|
40
|
+
try {
|
|
41
|
+
readViaOsascript(outPath);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return { ok: false, reason: '剪贴板里没有图片' };
|
|
45
|
+
}
|
|
46
|
+
if (!existsSync(outPath) || statSync(outPath).size === 0) {
|
|
47
|
+
return { ok: false, reason: '剪贴板里没有图片' };
|
|
48
|
+
}
|
|
49
|
+
return { ok: true, path: outPath };
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=clipboard-image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clipboard-image.js","sourceRoot":"","sources":["../../src/cli/clipboard-image.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAMjC,mDAAmD;AACnD,SAAS,gBAAgB,CAAC,OAAe;IACrC,YAAY,CACR,WAAW,EACX;QACI,IAAI;QACJ,4CAA4C;QAC5C,IAAI;QACJ,wCAAwC,OAAO,yBAAyB;QACxE,IAAI;QACJ,gBAAgB;QAChB,IAAI;QACJ,gBAAgB;QAChB,IAAI;QACJ,gBAAgB;KACnB,EACD,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAC3D,CAAC;AACN,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAC9B,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAC;IAC3D,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,cAAc,UAAU,EAAE,MAAM,CAAC,CAAC;IACjE,IAAI,CAAC;QACD,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC7C,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACvD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC7C,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 发送前给过大的图片降分辨率,省 token / 请求体。
|
|
3
|
+
*
|
|
4
|
+
* 背景(实测 qwen-vl-plus):图片 token 按分辨率算,且服务端对超大图有封顶
|
|
5
|
+
* (~1M 像素 ≈ 1280 token)。把最长边压到 1024,一张全屏截图能从 ~1259 token
|
|
6
|
+
* 降到 ~684(省 ~46%),文字基本仍可读;对按面积计费的 Claude/GPT-4o 省得更多。
|
|
7
|
+
*
|
|
8
|
+
* 实现走 macOS 自带的 `sips`(零依赖,剪贴板取图本就靠 macOS)。非 macOS 或任何
|
|
9
|
+
* 失败都**原样透传**——压缩只是优化,绝不能挡住发送。只在最长边超过上限时才降,
|
|
10
|
+
* 小图一律不动(`sips -Z` 会放大小图,必须先判断)。
|
|
11
|
+
*/
|
|
12
|
+
import { execFileSync } from 'node:child_process';
|
|
13
|
+
import { randomUUID } from 'node:crypto';
|
|
14
|
+
import { existsSync, statSync } from 'node:fs';
|
|
15
|
+
import { tmpdir } from 'node:os';
|
|
16
|
+
import { join } from 'node:path';
|
|
17
|
+
/** 默认最长边上限(px);超过才降,小图不动。 */
|
|
18
|
+
export const MAX_IMAGE_EDGE = 1024;
|
|
19
|
+
/** 用 sips 读像素宽高;失败返回 null。 */
|
|
20
|
+
function sipsDimensions(path) {
|
|
21
|
+
try {
|
|
22
|
+
const out = execFileSync('sips', ['-g', 'pixelWidth', '-g', 'pixelHeight', path], { encoding: 'utf8', timeout: 5000 });
|
|
23
|
+
const w = /pixelWidth:\s*(\d+)/.exec(out);
|
|
24
|
+
const h = /pixelHeight:\s*(\d+)/.exec(out);
|
|
25
|
+
if (!w || !h)
|
|
26
|
+
return null;
|
|
27
|
+
return { width: Number(w[1]), height: Number(h[1]) };
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 若图片最长边超过 maxEdge,用 sips 等比降到 maxEdge 并输出临时 PNG;
|
|
35
|
+
* 否则(含非 macOS、读尺寸失败、压缩失败)原样透传。
|
|
36
|
+
*/
|
|
37
|
+
export function compressImageForModel(path, maxEdge = MAX_IMAGE_EDGE) {
|
|
38
|
+
if (process.platform !== 'darwin')
|
|
39
|
+
return { path, changed: false };
|
|
40
|
+
const from = sipsDimensions(path);
|
|
41
|
+
if (!from)
|
|
42
|
+
return { path, changed: false };
|
|
43
|
+
if (Math.max(from.width, from.height) <= maxEdge) {
|
|
44
|
+
return { path, changed: false };
|
|
45
|
+
}
|
|
46
|
+
const out = join(tmpdir(), `ccli-shrink-${randomUUID()}.png`);
|
|
47
|
+
try {
|
|
48
|
+
execFileSync('sips', ['-Z', String(maxEdge), path, '--out', out], {
|
|
49
|
+
stdio: ['ignore', 'ignore', 'ignore'],
|
|
50
|
+
timeout: 10000,
|
|
51
|
+
});
|
|
52
|
+
if (!existsSync(out) || statSync(out).size === 0) {
|
|
53
|
+
return { path, changed: false };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return { path, changed: false };
|
|
58
|
+
}
|
|
59
|
+
const to = sipsDimensions(out) ?? undefined;
|
|
60
|
+
return { path: out, changed: true, from, to };
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=image-compress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-compress.js","sourceRoot":"","sources":["../../src/cli/image-compress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,6BAA6B;AAC7B,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AAWnC,8BAA8B;AAC9B,SAAS,cAAc,CACnB,IAAY;IAEZ,IAAI,CAAC;QACD,MAAM,GAAG,GAAG,YAAY,CACpB,MAAM,EACN,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,EAC/C,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CACtC,CAAC;QACF,MAAM,CAAC,GAAG,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1C,MAAM,CAAC,GAAG,sBAAsB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1B,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACjC,IAAY,EACZ,UAAkB,cAAc;IAEhC,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACnE,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC3C,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QAC/C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACpC,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,UAAU,EAAE,MAAM,CAAC,CAAC;IAC9D,IAAI,CAAC;QACD,YAAY,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE;YAC9D,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;YACrC,OAAO,EAAE,KAAK;SACjB,CAAC,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC/C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACpC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACpC,CAAC;IACD,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;IAC5C,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AAClD,CAAC"}
|