@corbat-tech/coco 2.5.2 → 2.5.3
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/cli/index.js +936 -69
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +108 -36
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11790,6 +11790,20 @@ var AnthropicProvider = class {
|
|
|
11790
11790
|
if (event.type === "content_block_start") {
|
|
11791
11791
|
const contentBlock = event.content_block;
|
|
11792
11792
|
if (contentBlock.type === "tool_use") {
|
|
11793
|
+
if (currentToolCall) {
|
|
11794
|
+
getLogger().warn(
|
|
11795
|
+
`[Anthropic] content_block_stop missing for tool '${currentToolCall.name}' \u2014 finalizing early to prevent data bleed.`
|
|
11796
|
+
);
|
|
11797
|
+
try {
|
|
11798
|
+
currentToolCall.input = currentToolInputJson ? JSON.parse(currentToolInputJson) : {};
|
|
11799
|
+
} catch {
|
|
11800
|
+
currentToolCall.input = {};
|
|
11801
|
+
}
|
|
11802
|
+
yield {
|
|
11803
|
+
type: "tool_use_end",
|
|
11804
|
+
toolCall: { ...currentToolCall }
|
|
11805
|
+
};
|
|
11806
|
+
}
|
|
11793
11807
|
currentToolCall = {
|
|
11794
11808
|
id: contentBlock.id,
|
|
11795
11809
|
name: contentBlock.name
|
|
@@ -12383,6 +12397,30 @@ var OpenAIProvider = class {
|
|
|
12383
12397
|
}
|
|
12384
12398
|
};
|
|
12385
12399
|
const timeoutInterval = setInterval(checkTimeout, 5e3);
|
|
12400
|
+
const providerName = this.name;
|
|
12401
|
+
const parseArguments = (builder) => {
|
|
12402
|
+
let input = {};
|
|
12403
|
+
try {
|
|
12404
|
+
input = builder.arguments ? JSON.parse(builder.arguments) : {};
|
|
12405
|
+
} catch (error) {
|
|
12406
|
+
console.warn(
|
|
12407
|
+
`[${providerName}] Failed to parse tool call arguments for ${builder.name}: ${builder.arguments?.slice(0, 300)}`
|
|
12408
|
+
);
|
|
12409
|
+
try {
|
|
12410
|
+
if (builder.arguments) {
|
|
12411
|
+
const repaired = jsonrepair(builder.arguments);
|
|
12412
|
+
input = JSON.parse(repaired);
|
|
12413
|
+
console.log(`[${providerName}] \u2713 Successfully repaired JSON for ${builder.name}`);
|
|
12414
|
+
}
|
|
12415
|
+
} catch {
|
|
12416
|
+
console.error(
|
|
12417
|
+
`[${providerName}] Cannot repair JSON for ${builder.name}, using empty object`
|
|
12418
|
+
);
|
|
12419
|
+
console.error(`[${providerName}] Original error:`, error);
|
|
12420
|
+
}
|
|
12421
|
+
}
|
|
12422
|
+
return input;
|
|
12423
|
+
};
|
|
12386
12424
|
try {
|
|
12387
12425
|
for await (const chunk of stream) {
|
|
12388
12426
|
const delta = chunk.choices[0]?.delta;
|
|
@@ -12394,7 +12432,7 @@ var OpenAIProvider = class {
|
|
|
12394
12432
|
}
|
|
12395
12433
|
if (delta?.tool_calls) {
|
|
12396
12434
|
for (const toolCallDelta of delta.tool_calls) {
|
|
12397
|
-
const index = toolCallDelta.index;
|
|
12435
|
+
const index = toolCallDelta.index ?? toolCallBuilders.size;
|
|
12398
12436
|
if (!toolCallBuilders.has(index)) {
|
|
12399
12437
|
toolCallBuilders.set(index, {
|
|
12400
12438
|
id: toolCallDelta.id ?? "",
|
|
@@ -12429,34 +12467,28 @@ var OpenAIProvider = class {
|
|
|
12429
12467
|
}
|
|
12430
12468
|
}
|
|
12431
12469
|
}
|
|
12432
|
-
|
|
12433
|
-
|
|
12434
|
-
|
|
12435
|
-
|
|
12436
|
-
|
|
12437
|
-
|
|
12438
|
-
|
|
12439
|
-
|
|
12440
|
-
|
|
12441
|
-
|
|
12442
|
-
|
|
12443
|
-
const repaired = jsonrepair(builder.arguments);
|
|
12444
|
-
input = JSON.parse(repaired);
|
|
12445
|
-
console.log(`[${this.name}] \u2713 Successfully repaired JSON for ${builder.name}`);
|
|
12446
|
-
}
|
|
12447
|
-
} catch {
|
|
12448
|
-
console.error(
|
|
12449
|
-
`[${this.name}] Cannot repair JSON for ${builder.name}, using empty object`
|
|
12450
|
-
);
|
|
12451
|
-
console.error(`[${this.name}] Original error:`, error);
|
|
12470
|
+
const finishReason = chunk.choices[0]?.finish_reason;
|
|
12471
|
+
if (finishReason && toolCallBuilders.size > 0) {
|
|
12472
|
+
for (const [, builder] of toolCallBuilders) {
|
|
12473
|
+
yield {
|
|
12474
|
+
type: "tool_use_end",
|
|
12475
|
+
toolCall: {
|
|
12476
|
+
id: builder.id,
|
|
12477
|
+
name: builder.name,
|
|
12478
|
+
input: parseArguments(builder)
|
|
12479
|
+
}
|
|
12480
|
+
};
|
|
12452
12481
|
}
|
|
12482
|
+
toolCallBuilders.clear();
|
|
12453
12483
|
}
|
|
12484
|
+
}
|
|
12485
|
+
for (const [, builder] of toolCallBuilders) {
|
|
12454
12486
|
yield {
|
|
12455
12487
|
type: "tool_use_end",
|
|
12456
12488
|
toolCall: {
|
|
12457
12489
|
id: builder.id,
|
|
12458
12490
|
name: builder.name,
|
|
12459
|
-
input
|
|
12491
|
+
input: parseArguments(builder)
|
|
12460
12492
|
}
|
|
12461
12493
|
};
|
|
12462
12494
|
}
|
|
@@ -12625,7 +12657,8 @@ var OpenAIProvider = class {
|
|
|
12625
12657
|
if (msg.role === "system") {
|
|
12626
12658
|
result.push({ role: "system", content: this.contentToString(msg.content) });
|
|
12627
12659
|
} else if (msg.role === "user") {
|
|
12628
|
-
if (Array.isArray(msg.content) && msg.content
|
|
12660
|
+
if (Array.isArray(msg.content) && msg.content.some((b) => b.type === "tool_result")) {
|
|
12661
|
+
const textParts = [];
|
|
12629
12662
|
for (const block of msg.content) {
|
|
12630
12663
|
if (block.type === "tool_result") {
|
|
12631
12664
|
const toolResult = block;
|
|
@@ -12634,8 +12667,16 @@ var OpenAIProvider = class {
|
|
|
12634
12667
|
tool_call_id: toolResult.tool_use_id,
|
|
12635
12668
|
content: toolResult.content
|
|
12636
12669
|
});
|
|
12670
|
+
} else if (block.type === "text") {
|
|
12671
|
+
textParts.push(block.text);
|
|
12637
12672
|
}
|
|
12638
12673
|
}
|
|
12674
|
+
if (textParts.length > 0) {
|
|
12675
|
+
console.warn(
|
|
12676
|
+
`[${this.name}] User message has mixed tool_result and text blocks \u2014 text emitted as a separate user message.`
|
|
12677
|
+
);
|
|
12678
|
+
result.push({ role: "user", content: textParts.join("") });
|
|
12679
|
+
}
|
|
12639
12680
|
} else if (Array.isArray(msg.content) && msg.content.some((b) => b.type === "image")) {
|
|
12640
12681
|
const parts = [];
|
|
12641
12682
|
for (const block of msg.content) {
|
|
@@ -12680,6 +12721,10 @@ var OpenAIProvider = class {
|
|
|
12680
12721
|
arguments: JSON.stringify(block.input)
|
|
12681
12722
|
}
|
|
12682
12723
|
});
|
|
12724
|
+
} else {
|
|
12725
|
+
console.warn(
|
|
12726
|
+
`[${this.name}] Unexpected block type '${block.type}' in assistant message \u2014 dropping. This may indicate a message history corruption.`
|
|
12727
|
+
);
|
|
12683
12728
|
}
|
|
12684
12729
|
}
|
|
12685
12730
|
if (textParts.length > 0) {
|
|
@@ -15156,7 +15201,7 @@ function escapeRegex(str) {
|
|
|
15156
15201
|
}
|
|
15157
15202
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
15158
15203
|
var MAX_OUTPUT_SIZE = 1024 * 1024;
|
|
15159
|
-
var
|
|
15204
|
+
var DANGEROUS_PATTERNS_FULL = [
|
|
15160
15205
|
/\brm\s+-rf\s+\/(?!\w)/,
|
|
15161
15206
|
// rm -rf / (root)
|
|
15162
15207
|
/\bsudo\s+rm\s+-rf/,
|
|
@@ -15169,14 +15214,6 @@ var DANGEROUS_PATTERNS = [
|
|
|
15169
15214
|
// Format filesystem
|
|
15170
15215
|
/\bformat\s+/,
|
|
15171
15216
|
// Windows format
|
|
15172
|
-
/`[^`]+`/,
|
|
15173
|
-
// Backtick command substitution
|
|
15174
|
-
/\$\([^)]+\)/,
|
|
15175
|
-
// $() command substitution
|
|
15176
|
-
/\beval\s+/,
|
|
15177
|
-
// eval command
|
|
15178
|
-
/\bsource\s+/,
|
|
15179
|
-
// source command (can execute arbitrary scripts)
|
|
15180
15217
|
/>\s*\/etc\//,
|
|
15181
15218
|
// Write to /etc
|
|
15182
15219
|
/>\s*\/root\//,
|
|
@@ -15190,6 +15227,25 @@ var DANGEROUS_PATTERNS = [
|
|
|
15190
15227
|
/\bwget\s+.*\|\s*(ba)?sh/
|
|
15191
15228
|
// wget | sh pattern
|
|
15192
15229
|
];
|
|
15230
|
+
var DANGEROUS_PATTERNS_SHELL_ONLY = [
|
|
15231
|
+
/`[^`]+`/,
|
|
15232
|
+
// Backtick command substitution
|
|
15233
|
+
/\$\([^)]+\)/,
|
|
15234
|
+
// $() command substitution
|
|
15235
|
+
/\beval\s+/,
|
|
15236
|
+
// eval command (shell eval, not JS eval())
|
|
15237
|
+
/\bsource\s+/
|
|
15238
|
+
// source command (can execute arbitrary scripts)
|
|
15239
|
+
];
|
|
15240
|
+
function getShellCommandPart(command) {
|
|
15241
|
+
const firstNewline = command.indexOf("\n");
|
|
15242
|
+
if (firstNewline === -1) return command;
|
|
15243
|
+
const firstLine = command.slice(0, firstNewline);
|
|
15244
|
+
if (/<<-?\s*['"]?\w/.test(firstLine)) {
|
|
15245
|
+
return firstLine;
|
|
15246
|
+
}
|
|
15247
|
+
return command;
|
|
15248
|
+
}
|
|
15193
15249
|
var SAFE_ENV_VARS = /* @__PURE__ */ new Set([
|
|
15194
15250
|
// System info (non-sensitive)
|
|
15195
15251
|
"PATH",
|
|
@@ -15256,13 +15312,21 @@ Examples:
|
|
|
15256
15312
|
env: z.record(z.string(), z.string()).optional().describe("Environment variables")
|
|
15257
15313
|
}),
|
|
15258
15314
|
async execute({ command, cwd, timeout, env: env2 }) {
|
|
15259
|
-
|
|
15315
|
+
const shellPart = getShellCommandPart(command);
|
|
15316
|
+
for (const pattern of DANGEROUS_PATTERNS_FULL) {
|
|
15260
15317
|
if (pattern.test(command)) {
|
|
15261
15318
|
throw new ToolError(`Potentially dangerous command blocked: ${command.slice(0, 100)}`, {
|
|
15262
15319
|
tool: "bash_exec"
|
|
15263
15320
|
});
|
|
15264
15321
|
}
|
|
15265
15322
|
}
|
|
15323
|
+
for (const pattern of DANGEROUS_PATTERNS_SHELL_ONLY) {
|
|
15324
|
+
if (pattern.test(shellPart)) {
|
|
15325
|
+
throw new ToolError(`Potentially dangerous command blocked: ${command.slice(0, 100)}`, {
|
|
15326
|
+
tool: "bash_exec"
|
|
15327
|
+
});
|
|
15328
|
+
}
|
|
15329
|
+
}
|
|
15266
15330
|
const startTime = performance.now();
|
|
15267
15331
|
const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS;
|
|
15268
15332
|
const { CommandHeartbeat: CommandHeartbeat2 } = await Promise.resolve().then(() => (init_heartbeat(), heartbeat_exports));
|
|
@@ -15344,13 +15408,21 @@ Examples:
|
|
|
15344
15408
|
env: z.record(z.string(), z.string()).optional().describe("Environment variables")
|
|
15345
15409
|
}),
|
|
15346
15410
|
async execute({ command, cwd, env: env2 }) {
|
|
15347
|
-
|
|
15411
|
+
const shellPart = getShellCommandPart(command);
|
|
15412
|
+
for (const pattern of DANGEROUS_PATTERNS_FULL) {
|
|
15348
15413
|
if (pattern.test(command)) {
|
|
15349
15414
|
throw new ToolError(`Potentially dangerous command blocked: ${command.slice(0, 100)}`, {
|
|
15350
15415
|
tool: "bash_background"
|
|
15351
15416
|
});
|
|
15352
15417
|
}
|
|
15353
15418
|
}
|
|
15419
|
+
for (const pattern of DANGEROUS_PATTERNS_SHELL_ONLY) {
|
|
15420
|
+
if (pattern.test(shellPart)) {
|
|
15421
|
+
throw new ToolError(`Potentially dangerous command blocked: ${command.slice(0, 100)}`, {
|
|
15422
|
+
tool: "bash_background"
|
|
15423
|
+
});
|
|
15424
|
+
}
|
|
15425
|
+
}
|
|
15354
15426
|
try {
|
|
15355
15427
|
const filteredEnv = {};
|
|
15356
15428
|
for (const [key, value] of Object.entries(process.env)) {
|
|
@@ -20932,7 +21004,7 @@ Examples:
|
|
|
20932
21004
|
});
|
|
20933
21005
|
var imageTools = [readImageTool];
|
|
20934
21006
|
var path31 = await import('path');
|
|
20935
|
-
var
|
|
21007
|
+
var DANGEROUS_PATTERNS = [
|
|
20936
21008
|
/\bDROP\s+(?:TABLE|DATABASE|INDEX|VIEW)\b/i,
|
|
20937
21009
|
/\bTRUNCATE\b/i,
|
|
20938
21010
|
/\bALTER\s+TABLE\b/i,
|
|
@@ -20942,7 +21014,7 @@ var DANGEROUS_PATTERNS2 = [
|
|
|
20942
21014
|
/\bCREATE\s+(?:TABLE|DATABASE|INDEX)\b/i
|
|
20943
21015
|
];
|
|
20944
21016
|
function isDangerousSql(sql2) {
|
|
20945
|
-
return
|
|
21017
|
+
return DANGEROUS_PATTERNS.some((pattern) => pattern.test(sql2));
|
|
20946
21018
|
}
|
|
20947
21019
|
var sqlQueryTool = defineTool({
|
|
20948
21020
|
name: "sql_query",
|