@librechat/agents 3.9.4 → 3.9.6
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/cjs/graphs/Graph.cjs +1 -1
- package/dist/cjs/llm/invoke.cjs +1 -1
- package/dist/cjs/stream.cjs +3 -2
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/ArtifactTruncation.cjs +45 -0
- package/dist/cjs/tools/ArtifactTruncation.cjs.map +1 -0
- package/dist/cjs/tools/BashExecutor.cjs +6 -1
- package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
- package/dist/cjs/tools/CodeExecutor.cjs +6 -1
- package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs +5 -1
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +5 -4
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/toolErrorContent.cjs +17 -0
- package/dist/cjs/tools/toolErrorContent.cjs.map +1 -0
- package/dist/esm/graphs/Graph.mjs +1 -1
- package/dist/esm/llm/invoke.mjs +1 -1
- package/dist/esm/stream.mjs +3 -2
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/ArtifactTruncation.mjs +44 -0
- package/dist/esm/tools/ArtifactTruncation.mjs.map +1 -0
- package/dist/esm/tools/BashExecutor.mjs +6 -1
- package/dist/esm/tools/BashExecutor.mjs.map +1 -1
- package/dist/esm/tools/CodeExecutor.mjs +6 -1
- package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
- package/dist/esm/tools/ProgrammaticToolCalling.mjs +5 -1
- package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +5 -4
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/toolErrorContent.mjs +17 -0
- package/dist/esm/tools/toolErrorContent.mjs.map +1 -0
- package/dist/types/tools/ArtifactTruncation.d.ts +3 -0
- package/dist/types/tools/toolErrorContent.d.ts +2 -0
- package/dist/types/types/tools.d.ts +12 -0
- package/package.json +1 -1
- package/src/stream.ts +5 -3
- package/src/tools/ArtifactTruncation.ts +85 -0
- package/src/tools/BashExecutor.ts +22 -5
- package/src/tools/CodeExecutor.ts +18 -1
- package/src/tools/ProgrammaticToolCalling.ts +17 -3
- package/src/tools/ToolNode.ts +14 -9
- package/src/tools/toolErrorContent.ts +48 -0
- package/src/types/tools.ts +19 -0
|
@@ -464,6 +464,14 @@ export type ArtifactDeliveryFailure = {
|
|
|
464
464
|
delivered: number;
|
|
465
465
|
failed: number;
|
|
466
466
|
};
|
|
467
|
+
export type ArtifactTruncationReason = 'max_files' | 'depth' | 'size' | 'path' | 'unreadable';
|
|
468
|
+
export type ArtifactTruncation = {
|
|
469
|
+
code: 'artifact_truncated';
|
|
470
|
+
reasons: Partial<Record<ArtifactTruncationReason, number>>;
|
|
471
|
+
/** Up to 20 relative paths omitted from the response. */
|
|
472
|
+
skipped: string[];
|
|
473
|
+
skipped_count: number;
|
|
474
|
+
};
|
|
467
475
|
export type ExecuteResult = {
|
|
468
476
|
/**
|
|
469
477
|
* Execution session id — the (transient) sandbox run that produced
|
|
@@ -477,6 +485,7 @@ export type ExecuteResult = {
|
|
|
477
485
|
/** Persisted input paths explicitly removed during this execution. */
|
|
478
486
|
deleted_files?: string[];
|
|
479
487
|
artifact_delivery?: ArtifactDeliveryFailure;
|
|
488
|
+
artifact_truncation?: ArtifactTruncation;
|
|
480
489
|
/**
|
|
481
490
|
* Durable runtime session id echoed by a stateful Code API backend
|
|
482
491
|
* (hash of tenant+user+hint). Additive; absent on stateless servers.
|
|
@@ -1245,6 +1254,7 @@ export type ProgrammaticExecutionResponse = {
|
|
|
1245
1254
|
/** Persisted input paths explicitly removed during this execution. */
|
|
1246
1255
|
deleted_files?: string[];
|
|
1247
1256
|
artifact_delivery?: ArtifactDeliveryFailure;
|
|
1257
|
+
artifact_truncation?: ArtifactTruncation;
|
|
1248
1258
|
/** Durable runtime session echo from a stateful backend (additive). */
|
|
1249
1259
|
runtime_session_id?: string;
|
|
1250
1260
|
runtime_status?: 'new' | 'reused';
|
|
@@ -1261,6 +1271,7 @@ export type ProgrammaticExecutionArtifact = {
|
|
|
1261
1271
|
/** Persisted input paths explicitly removed during this execution. */
|
|
1262
1272
|
deleted_files?: string[];
|
|
1263
1273
|
artifact_delivery?: ArtifactDeliveryFailure;
|
|
1274
|
+
artifact_truncation?: ArtifactTruncation;
|
|
1264
1275
|
/** Durable runtime session echo from a stateful backend (additive). */
|
|
1265
1276
|
runtime_session_id?: string;
|
|
1266
1277
|
runtime_status?: 'new' | 'reused';
|
|
@@ -1328,6 +1339,7 @@ export type CodeExecutionArtifact = {
|
|
|
1328
1339
|
/** Persisted input paths explicitly removed during this execution. */
|
|
1329
1340
|
deleted_files?: string[];
|
|
1330
1341
|
artifact_delivery?: ArtifactDeliveryFailure;
|
|
1342
|
+
artifact_truncation?: ArtifactTruncation;
|
|
1331
1343
|
/** Durable runtime session echo from a stateful backend (additive). */
|
|
1332
1344
|
runtime_session_id?: string;
|
|
1333
1345
|
runtime_status?: 'new' | 'reused';
|
package/package.json
CHANGED
package/src/stream.ts
CHANGED
|
@@ -56,6 +56,7 @@ import {
|
|
|
56
56
|
truncateToolResultContent,
|
|
57
57
|
} from '@/utils/truncation';
|
|
58
58
|
import { resolveToolOutcome, outcomeFieldsFromResult } from '@/tools/intentArg';
|
|
59
|
+
import { formatToolErrorContent } from '@/tools/toolErrorContent';
|
|
59
60
|
import { snapshotValidatedModelChunk } from '@/graphs/acceptedModelResponse';
|
|
60
61
|
import { TOOL_OUTPUT_REF_PATTERN } from '@/tools/toolOutputReferences';
|
|
61
62
|
import { PreparedSubagentError } from '@/tools/preparedSubagents';
|
|
@@ -940,9 +941,10 @@ async function dispatchEagerToolCompletions(args: {
|
|
|
940
941
|
}
|
|
941
942
|
let output: string;
|
|
942
943
|
if (result.status === 'error') {
|
|
943
|
-
output =
|
|
944
|
-
|
|
945
|
-
maxToolResultChars
|
|
944
|
+
output = formatToolErrorContent(
|
|
945
|
+
result.errorMessage,
|
|
946
|
+
maxToolResultChars,
|
|
947
|
+
graph.config?.signal
|
|
946
948
|
);
|
|
947
949
|
} else if (typeof result.content === 'string') {
|
|
948
950
|
output = truncateToolResultContent(result.content, maxToolResultChars);
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { ArtifactTruncation, ArtifactTruncationReason } from '@/types';
|
|
2
|
+
|
|
3
|
+
const MAX_REPORTED_TRUNCATED_PATHS = 20;
|
|
4
|
+
const ARTIFACT_TRUNCATION_REASONS = new Set<string>([
|
|
5
|
+
'max_files',
|
|
6
|
+
'depth',
|
|
7
|
+
'size',
|
|
8
|
+
'path',
|
|
9
|
+
'unreadable',
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
function isNonNegativeInteger(value: unknown): value is number {
|
|
13
|
+
return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function normalizeArtifactTruncation(
|
|
17
|
+
value: unknown
|
|
18
|
+
): ArtifactTruncation | undefined {
|
|
19
|
+
if (value == null || typeof value !== 'object' || Array.isArray(value)) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const candidate = value as Partial<ArtifactTruncation>;
|
|
24
|
+
if (
|
|
25
|
+
candidate.code !== 'artifact_truncated' ||
|
|
26
|
+
!isNonNegativeInteger(candidate.skipped_count) ||
|
|
27
|
+
candidate.skipped_count === 0 ||
|
|
28
|
+
candidate.reasons == null ||
|
|
29
|
+
typeof candidate.reasons !== 'object' ||
|
|
30
|
+
Array.isArray(candidate.reasons) ||
|
|
31
|
+
!Array.isArray(candidate.skipped) ||
|
|
32
|
+
candidate.skipped.length > MAX_REPORTED_TRUNCATED_PATHS ||
|
|
33
|
+
candidate.skipped.length > candidate.skipped_count ||
|
|
34
|
+
candidate.skipped.some((path) => typeof path !== 'string')
|
|
35
|
+
) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const reasons: ArtifactTruncation['reasons'] = {};
|
|
40
|
+
let reasonTotal = 0;
|
|
41
|
+
for (const [reason, count] of Object.entries(candidate.reasons)) {
|
|
42
|
+
if (
|
|
43
|
+
!ARTIFACT_TRUNCATION_REASONS.has(reason) ||
|
|
44
|
+
!isNonNegativeInteger(count)
|
|
45
|
+
) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
reasonTotal += count;
|
|
49
|
+
if (reasonTotal > candidate.skipped_count) {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
reasons[reason as ArtifactTruncationReason] = count;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (reasonTotal !== candidate.skipped_count) {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
code: candidate.code,
|
|
61
|
+
reasons,
|
|
62
|
+
skipped: [...candidate.skipped],
|
|
63
|
+
skipped_count: candidate.skipped_count,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function appendArtifactTruncationWarning(
|
|
68
|
+
output: string,
|
|
69
|
+
truncation: ArtifactTruncation | undefined
|
|
70
|
+
): string {
|
|
71
|
+
if (truncation == null) {
|
|
72
|
+
return output;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const reasons = Object.entries(truncation.reasons)
|
|
76
|
+
.map(([reason, count]) => `${reason}: ${count}`)
|
|
77
|
+
.join(', ');
|
|
78
|
+
const shown = truncation.skipped.length;
|
|
79
|
+
const paths =
|
|
80
|
+
shown > 0
|
|
81
|
+
? ` Not delivered: ${truncation.skipped.join(', ')}${shown < truncation.skipped_count ? ` (${shown} of ${truncation.skipped_count} shown)` : ''}.`
|
|
82
|
+
: '';
|
|
83
|
+
const warning = `Note: ${truncation.skipped_count} file(s) were omitted from delivery${reasons ? ` (${reasons})` : ''}.${paths} Write fewer files per execution or combine them into an archive. The code itself ran; do not rerun automatically because it may have had side effects.`;
|
|
84
|
+
return `${output.trimEnd()}\n${warning}\n`;
|
|
85
|
+
}
|
|
@@ -23,14 +23,18 @@ import {
|
|
|
23
23
|
appendArtifactDeliveryWarning,
|
|
24
24
|
normalizeArtifactDeliveryFailure,
|
|
25
25
|
} from '@/tools/ArtifactDelivery';
|
|
26
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
appendArtifactTruncationWarning,
|
|
28
|
+
normalizeArtifactTruncation,
|
|
29
|
+
} from '@/tools/ArtifactTruncation';
|
|
27
30
|
import { appendExecutionArtifactFileSummary } from '@/tools/CodeSessionFileSummary';
|
|
28
31
|
import { resolveAttachedWorkspaceInstanceId } from '@/tools/workspaceIdentity';
|
|
32
|
+
import { prepareBashProgrammaticCode } from './BashProgrammaticToolCalling';
|
|
33
|
+
import { logCodeApiDiagnostic } from '@/tools/diagnostics';
|
|
34
|
+
import { makeRequest } from './ProgrammaticToolCalling';
|
|
29
35
|
import { resolveFetchProxyAgent } from '@/utils/proxy';
|
|
30
36
|
import { INTENT_PROPERTY } from '@/tools/intentArg';
|
|
31
37
|
import { Constants } from '@/common';
|
|
32
|
-
import { prepareBashProgrammaticCode } from './BashProgrammaticToolCalling';
|
|
33
|
-
import { makeRequest } from './ProgrammaticToolCalling';
|
|
34
38
|
|
|
35
39
|
config();
|
|
36
40
|
|
|
@@ -407,6 +411,13 @@ function createBashExecutionTool(
|
|
|
407
411
|
outputWithReminder,
|
|
408
412
|
artifactDelivery
|
|
409
413
|
);
|
|
414
|
+
const artifactTruncation = normalizeArtifactTruncation(
|
|
415
|
+
result.artifact_truncation
|
|
416
|
+
);
|
|
417
|
+
const outputWithWarnings = appendArtifactTruncationWarning(
|
|
418
|
+
outputWithDeliveryWarning,
|
|
419
|
+
artifactTruncation
|
|
420
|
+
);
|
|
410
421
|
const hasFiles = result.files != null && result.files.length > 0;
|
|
411
422
|
const deletionEcho =
|
|
412
423
|
result.deleted_files != null
|
|
@@ -422,11 +433,11 @@ function createBashExecutionTool(
|
|
|
422
433
|
return [
|
|
423
434
|
hasWorkspace
|
|
424
435
|
? appendExecutionArtifactFileSummary(
|
|
425
|
-
|
|
436
|
+
outputWithWarnings,
|
|
426
437
|
result.files
|
|
427
438
|
)
|
|
428
439
|
: appendCodeSessionFileSummary(
|
|
429
|
-
|
|
440
|
+
outputWithWarnings,
|
|
430
441
|
result.files
|
|
431
442
|
),
|
|
432
443
|
(hasFiles
|
|
@@ -436,6 +447,9 @@ function createBashExecutionTool(
|
|
|
436
447
|
...(artifactDelivery != null
|
|
437
448
|
? { artifact_delivery: artifactDelivery }
|
|
438
449
|
: {}),
|
|
450
|
+
...(artifactTruncation != null
|
|
451
|
+
? { artifact_truncation: artifactTruncation }
|
|
452
|
+
: {}),
|
|
439
453
|
...deletionEcho,
|
|
440
454
|
...runtimeEcho,
|
|
441
455
|
}
|
|
@@ -444,6 +458,9 @@ function createBashExecutionTool(
|
|
|
444
458
|
...(artifactDelivery != null
|
|
445
459
|
? { artifact_delivery: artifactDelivery }
|
|
446
460
|
: {}),
|
|
461
|
+
...(artifactTruncation != null
|
|
462
|
+
? { artifact_truncation: artifactTruncation }
|
|
463
|
+
: {}),
|
|
447
464
|
...deletionEcho,
|
|
448
465
|
...runtimeEcho,
|
|
449
466
|
}) satisfies t.CodeExecutionArtifact,
|
|
@@ -9,6 +9,10 @@ import {
|
|
|
9
9
|
appendArtifactDeliveryWarning,
|
|
10
10
|
normalizeArtifactDeliveryFailure,
|
|
11
11
|
} from '@/tools/ArtifactDelivery';
|
|
12
|
+
import {
|
|
13
|
+
appendArtifactTruncationWarning,
|
|
14
|
+
normalizeArtifactTruncation,
|
|
15
|
+
} from '@/tools/ArtifactTruncation';
|
|
12
16
|
import {
|
|
13
17
|
describeCodeApiError,
|
|
14
18
|
logCodeApiDiagnostic,
|
|
@@ -671,6 +675,13 @@ function createCodeExecutionTool(
|
|
|
671
675
|
outputWithReminder,
|
|
672
676
|
artifactDelivery
|
|
673
677
|
);
|
|
678
|
+
const artifactTruncation = normalizeArtifactTruncation(
|
|
679
|
+
result.artifact_truncation
|
|
680
|
+
);
|
|
681
|
+
const outputWithWarnings = appendArtifactTruncationWarning(
|
|
682
|
+
outputWithDeliveryWarning,
|
|
683
|
+
artifactTruncation
|
|
684
|
+
);
|
|
674
685
|
const hasFiles = result.files != null && result.files.length > 0;
|
|
675
686
|
const deletionEcho =
|
|
676
687
|
result.deleted_files != null
|
|
@@ -687,7 +698,7 @@ function createCodeExecutionTool(
|
|
|
687
698
|
}
|
|
688
699
|
: {};
|
|
689
700
|
return [
|
|
690
|
-
appendCodeSessionFileSummary(
|
|
701
|
+
appendCodeSessionFileSummary(outputWithWarnings, result.files),
|
|
691
702
|
(hasFiles
|
|
692
703
|
? {
|
|
693
704
|
session_id: result.session_id,
|
|
@@ -695,6 +706,9 @@ function createCodeExecutionTool(
|
|
|
695
706
|
...(artifactDelivery != null
|
|
696
707
|
? { artifact_delivery: artifactDelivery }
|
|
697
708
|
: {}),
|
|
709
|
+
...(artifactTruncation != null
|
|
710
|
+
? { artifact_truncation: artifactTruncation }
|
|
711
|
+
: {}),
|
|
698
712
|
...deletionEcho,
|
|
699
713
|
...runtimeEcho,
|
|
700
714
|
}
|
|
@@ -703,6 +717,9 @@ function createCodeExecutionTool(
|
|
|
703
717
|
...(artifactDelivery != null
|
|
704
718
|
? { artifact_delivery: artifactDelivery }
|
|
705
719
|
: {}),
|
|
720
|
+
...(artifactTruncation != null
|
|
721
|
+
? { artifact_truncation: artifactTruncation }
|
|
722
|
+
: {}),
|
|
706
723
|
...deletionEcho,
|
|
707
724
|
...runtimeEcho,
|
|
708
725
|
}) satisfies t.CodeExecutionArtifact,
|
|
@@ -22,7 +22,6 @@ import {
|
|
|
22
22
|
resolveCodeApiAuthHeaders,
|
|
23
23
|
selectRuntimeSessionHint,
|
|
24
24
|
} from './CodeExecutor';
|
|
25
|
-
import { appendExecutionArtifactFileSummary } from './CodeSessionFileSummary';
|
|
26
25
|
import {
|
|
27
26
|
assertUnambiguousIdentifiers,
|
|
28
27
|
projectProgrammaticToolMap,
|
|
@@ -39,10 +38,15 @@ import {
|
|
|
39
38
|
appendArtifactDeliveryWarning,
|
|
40
39
|
normalizeArtifactDeliveryFailure,
|
|
41
40
|
} from '@/tools/ArtifactDelivery';
|
|
41
|
+
import {
|
|
42
|
+
appendArtifactTruncationWarning,
|
|
43
|
+
normalizeArtifactTruncation,
|
|
44
|
+
} from '@/tools/ArtifactTruncation';
|
|
42
45
|
import {
|
|
43
46
|
describeCodeApiError,
|
|
44
47
|
logCodeApiDiagnostic,
|
|
45
48
|
} from '@/tools/diagnostics';
|
|
49
|
+
import { appendExecutionArtifactFileSummary } from './CodeSessionFileSummary';
|
|
46
50
|
import { resolveFetchProxyAgent } from '@/utils/proxy';
|
|
47
51
|
import { INTENT_PROPERTY } from '@/tools/intentArg';
|
|
48
52
|
import { Constants } from '@/common';
|
|
@@ -946,11 +950,18 @@ export function formatCompletedResponse(
|
|
|
946
950
|
outputWithReminder,
|
|
947
951
|
artifactDelivery
|
|
948
952
|
);
|
|
953
|
+
const artifactTruncation = normalizeArtifactTruncation(
|
|
954
|
+
response.artifact_truncation
|
|
955
|
+
);
|
|
956
|
+
const outputWithWarnings = appendArtifactTruncationWarning(
|
|
957
|
+
outputWithDeliveryWarning,
|
|
958
|
+
artifactTruncation
|
|
959
|
+
);
|
|
949
960
|
|
|
950
961
|
return [
|
|
951
962
|
filePersistence === 'execution'
|
|
952
|
-
? appendExecutionArtifactFileSummary(
|
|
953
|
-
: appendCodeSessionFileSummary(
|
|
963
|
+
? appendExecutionArtifactFileSummary(outputWithWarnings, response.files)
|
|
964
|
+
: appendCodeSessionFileSummary(outputWithWarnings, response.files),
|
|
954
965
|
{
|
|
955
966
|
session_id: response.session_id,
|
|
956
967
|
files: response.files,
|
|
@@ -960,6 +971,9 @@ export function formatCompletedResponse(
|
|
|
960
971
|
...(artifactDelivery != null
|
|
961
972
|
? { artifact_delivery: artifactDelivery }
|
|
962
973
|
: {}),
|
|
974
|
+
...(artifactTruncation != null
|
|
975
|
+
? { artifact_truncation: artifactTruncation }
|
|
976
|
+
: {}),
|
|
963
977
|
...(response.runtime_session_id != null
|
|
964
978
|
? {
|
|
965
979
|
runtime_session_id: response.runtime_session_id,
|
package/src/tools/ToolNode.ts
CHANGED
|
@@ -129,6 +129,7 @@ import {
|
|
|
129
129
|
resolveLocalExecutionTools,
|
|
130
130
|
} from '@/tools/local';
|
|
131
131
|
import { stripCodeSessionFileSummary } from '@/tools/CodeSessionFileSummary';
|
|
132
|
+
import { formatToolErrorContent } from '@/tools/toolErrorContent';
|
|
132
133
|
import { Constants, GraphEvents, CODE_EXECUTION_TOOLS } from '@/common';
|
|
133
134
|
import { PreparedSubagentError } from '@/tools/preparedSubagents';
|
|
134
135
|
import { attachRunStepResumeState } from '@/tools/runStepResume';
|
|
@@ -2201,9 +2202,11 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
2201
2202
|
});
|
|
2202
2203
|
}
|
|
2203
2204
|
}
|
|
2204
|
-
const errorContent =
|
|
2205
|
-
|
|
2206
|
-
this.maxToolResultChars
|
|
2205
|
+
const errorContent = formatToolErrorContent(
|
|
2206
|
+
e.message,
|
|
2207
|
+
this.maxToolResultChars,
|
|
2208
|
+
config.signal,
|
|
2209
|
+
e
|
|
2207
2210
|
);
|
|
2208
2211
|
const refMeta =
|
|
2209
2212
|
unresolvedRefs.length > 0
|
|
@@ -4461,9 +4464,10 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
4461
4464
|
let finalToolOutput: unknown = result.content;
|
|
4462
4465
|
|
|
4463
4466
|
if (result.status === 'error') {
|
|
4464
|
-
contentString =
|
|
4465
|
-
|
|
4466
|
-
this.maxToolResultChars
|
|
4467
|
+
contentString = formatToolErrorContent(
|
|
4468
|
+
result.errorMessage,
|
|
4469
|
+
this.maxToolResultChars,
|
|
4470
|
+
config.signal
|
|
4467
4471
|
);
|
|
4468
4472
|
/**
|
|
4469
4473
|
* Error results bypass registration but stamp the
|
|
@@ -4977,9 +4981,10 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
4977
4981
|
): Promise<boolean> {
|
|
4978
4982
|
const output =
|
|
4979
4983
|
result.status === 'error'
|
|
4980
|
-
?
|
|
4981
|
-
|
|
4982
|
-
this.maxToolResultChars
|
|
4984
|
+
? formatToolErrorContent(
|
|
4985
|
+
result.errorMessage,
|
|
4986
|
+
this.maxToolResultChars,
|
|
4987
|
+
config.signal
|
|
4983
4988
|
)
|
|
4984
4989
|
: serializeToolOutputWithinLimits(
|
|
4985
4990
|
result.content,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { PreparedSubagentError } from '@/tools/preparedSubagents';
|
|
2
|
+
import { truncateToolResultContent } from '@/utils/truncation';
|
|
3
|
+
import { StreamLimitExceededError } from '@/llm/streamLimits';
|
|
4
|
+
|
|
5
|
+
export const STOPPED_RUN_TOOL_ERROR =
|
|
6
|
+
'STOP. The user doesn\'t want to proceed with this tool use. ' +
|
|
7
|
+
'The run was stopped; the tool may not have completed, and its effects should not be assumed. ' +
|
|
8
|
+
'STOP what you are doing and wait for the user to tell you how to proceed.';
|
|
9
|
+
|
|
10
|
+
/** A host result only carries error text, so require the run signal as well. */
|
|
11
|
+
function isStoppedRunToolError(
|
|
12
|
+
message: string | undefined,
|
|
13
|
+
signal?: AbortSignal,
|
|
14
|
+
error?: Error
|
|
15
|
+
): boolean {
|
|
16
|
+
if (
|
|
17
|
+
signal?.aborted !== true ||
|
|
18
|
+
signal.reason instanceof StreamLimitExceededError ||
|
|
19
|
+
signal.reason instanceof PreparedSubagentError
|
|
20
|
+
) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
if (
|
|
24
|
+
(error != null && error === signal.reason) ||
|
|
25
|
+
(error instanceof Error &&
|
|
26
|
+
(error.name === 'AbortError' ||
|
|
27
|
+
('code' in error &&
|
|
28
|
+
(error.code === 'ABORT_ERR' || error.code === 'ERR_CANCELED'))))
|
|
29
|
+
) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
return (
|
|
33
|
+
message != null &&
|
|
34
|
+
/AbortError|(?:operation|request|stream) was aborted/i.test(message)
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function formatToolErrorContent(
|
|
39
|
+
message: string | undefined,
|
|
40
|
+
maxChars: number,
|
|
41
|
+
signal?: AbortSignal,
|
|
42
|
+
error?: Error
|
|
43
|
+
): string {
|
|
44
|
+
const content = isStoppedRunToolError(message, signal, error)
|
|
45
|
+
? STOPPED_RUN_TOOL_ERROR
|
|
46
|
+
: `Error: ${message ?? 'Unknown error'}\n Please fix your mistakes.`;
|
|
47
|
+
return truncateToolResultContent(content, maxChars);
|
|
48
|
+
}
|
package/src/types/tools.ts
CHANGED
|
@@ -497,6 +497,21 @@ export type ArtifactDeliveryFailure = {
|
|
|
497
497
|
failed: number;
|
|
498
498
|
};
|
|
499
499
|
|
|
500
|
+
export type ArtifactTruncationReason =
|
|
501
|
+
| 'max_files'
|
|
502
|
+
| 'depth'
|
|
503
|
+
| 'size'
|
|
504
|
+
| 'path'
|
|
505
|
+
| 'unreadable';
|
|
506
|
+
|
|
507
|
+
export type ArtifactTruncation = {
|
|
508
|
+
code: 'artifact_truncated';
|
|
509
|
+
reasons: Partial<Record<ArtifactTruncationReason, number>>;
|
|
510
|
+
/** Up to 20 relative paths omitted from the response. */
|
|
511
|
+
skipped: string[];
|
|
512
|
+
skipped_count: number;
|
|
513
|
+
};
|
|
514
|
+
|
|
500
515
|
export type ExecuteResult = {
|
|
501
516
|
/**
|
|
502
517
|
* Execution session id — the (transient) sandbox run that produced
|
|
@@ -510,6 +525,7 @@ export type ExecuteResult = {
|
|
|
510
525
|
/** Persisted input paths explicitly removed during this execution. */
|
|
511
526
|
deleted_files?: string[];
|
|
512
527
|
artifact_delivery?: ArtifactDeliveryFailure;
|
|
528
|
+
artifact_truncation?: ArtifactTruncation;
|
|
513
529
|
/**
|
|
514
530
|
* Durable runtime session id echoed by a stateful Code API backend
|
|
515
531
|
* (hash of tenant+user+hint). Additive; absent on stateless servers.
|
|
@@ -1356,6 +1372,7 @@ export type ProgrammaticExecutionResponse = {
|
|
|
1356
1372
|
/** Persisted input paths explicitly removed during this execution. */
|
|
1357
1373
|
deleted_files?: string[];
|
|
1358
1374
|
artifact_delivery?: ArtifactDeliveryFailure;
|
|
1375
|
+
artifact_truncation?: ArtifactTruncation;
|
|
1359
1376
|
|
|
1360
1377
|
/** Durable runtime session echo from a stateful backend (additive). */
|
|
1361
1378
|
runtime_session_id?: string;
|
|
@@ -1375,6 +1392,7 @@ export type ProgrammaticExecutionArtifact = {
|
|
|
1375
1392
|
/** Persisted input paths explicitly removed during this execution. */
|
|
1376
1393
|
deleted_files?: string[];
|
|
1377
1394
|
artifact_delivery?: ArtifactDeliveryFailure;
|
|
1395
|
+
artifact_truncation?: ArtifactTruncation;
|
|
1378
1396
|
/** Durable runtime session echo from a stateful backend (additive). */
|
|
1379
1397
|
runtime_session_id?: string;
|
|
1380
1398
|
runtime_status?: 'new' | 'reused';
|
|
@@ -1457,6 +1475,7 @@ export type CodeExecutionArtifact = {
|
|
|
1457
1475
|
/** Persisted input paths explicitly removed during this execution. */
|
|
1458
1476
|
deleted_files?: string[];
|
|
1459
1477
|
artifact_delivery?: ArtifactDeliveryFailure;
|
|
1478
|
+
artifact_truncation?: ArtifactTruncation;
|
|
1460
1479
|
/** Durable runtime session echo from a stateful backend (additive). */
|
|
1461
1480
|
runtime_session_id?: string;
|
|
1462
1481
|
runtime_status?: 'new' | 'reused';
|