@pentoshi/clai 3.11.9 → 3.11.11
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/agent/compaction-summary.d.ts +2 -2
- package/dist/agent/compaction-summary.js +6 -2
- package/dist/agent/compaction-summary.js.map +1 -1
- package/dist/agent/context-manager.d.ts +3 -4
- package/dist/agent/context-manager.js +8 -11
- package/dist/agent/context-manager.js.map +1 -1
- package/dist/agent/events.d.ts +6 -0
- package/dist/agent/finalize-gate.d.ts +1 -0
- package/dist/agent/finalize-gate.js +2 -1
- package/dist/agent/finalize-gate.js.map +1 -1
- package/dist/agent/loop-guard.d.ts +13 -0
- package/dist/agent/loop-guard.js +54 -8
- package/dist/agent/loop-guard.js.map +1 -1
- package/dist/agent/reliability-policy.d.ts +5 -3
- package/dist/agent/reliability-policy.js +5 -1
- package/dist/agent/reliability-policy.js.map +1 -1
- package/dist/agent/request-budget.d.ts +7 -3
- package/dist/agent/request-budget.js +24 -7
- package/dist/agent/request-budget.js.map +1 -1
- package/dist/agent/runner.d.ts +2 -0
- package/dist/agent/runner.js +39 -19
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/tool-history.js +1 -1
- package/dist/agent/tool-history.js.map +1 -1
- package/dist/agent/turn-outcome.js +3 -0
- package/dist/agent/turn-outcome.js.map +1 -1
- package/dist/app/adapters/agent-event-adapter.js +6 -0
- package/dist/app/adapters/agent-event-adapter.js.map +1 -1
- package/dist/app/adapters/current-agent-adapter.js +1 -0
- package/dist/app/adapters/current-agent-adapter.js.map +1 -1
- package/dist/app/controllers/session-compact-helper.js +7 -11
- package/dist/app/controllers/session-compact-helper.js.map +1 -1
- package/dist/app/controllers/session-context-limits.d.ts +14 -0
- package/dist/app/controllers/session-context-limits.js +48 -0
- package/dist/app/controllers/session-context-limits.js.map +1 -0
- package/dist/app/controllers/session-context-usage.d.ts +3 -0
- package/dist/app/controllers/session-context-usage.js +27 -9
- package/dist/app/controllers/session-context-usage.js.map +1 -1
- package/dist/app/controllers/session-controller.d.ts +6 -3
- package/dist/app/controllers/session-controller.js +34 -7
- package/dist/app/controllers/session-controller.js.map +1 -1
- package/dist/app/controllers/session-turn-request.d.ts +1 -0
- package/dist/app/controllers/session-turn-request.js +3 -0
- package/dist/app/controllers/session-turn-request.js.map +1 -1
- package/dist/app/events/app-event.d.ts +4 -0
- package/dist/app/events/app-event.js.map +1 -1
- package/dist/app/ports/agent-port.d.ts +2 -0
- package/dist/llm/adapters/openai-tools.d.ts +1 -0
- package/dist/llm/adapters/openai-tools.js +10 -0
- package/dist/llm/adapters/openai-tools.js.map +1 -1
- package/dist/llm/key-rotation.d.ts +1 -1
- package/dist/llm/key-rotation.js +4 -0
- package/dist/llm/key-rotation.js.map +1 -1
- package/dist/llm/router.d.ts +2 -0
- package/dist/llm/router.js +35 -3
- package/dist/llm/router.js.map +1 -1
- package/dist/llm/token-usage.d.ts +3 -2
- package/dist/llm/token-usage.js +6 -3
- package/dist/llm/token-usage.js.map +1 -1
- package/dist/prompts/index.d.ts +4 -1
- package/dist/prompts/index.js +12 -3
- package/dist/prompts/index.js.map +1 -1
- package/dist/store/config.d.ts +5 -0
- package/dist/store/config.js +38 -4
- package/dist/store/config.js.map +1 -1
- package/dist/store/keys.js +2 -2
- package/dist/store/keys.js.map +1 -1
- package/dist/tools/file-diff.js +59 -27
- package/dist/tools/file-diff.js.map +1 -1
- package/dist/tui-v2/bootstrap/composition-root.js +9 -0
- package/dist/tui-v2/bootstrap/composition-root.js.map +1 -1
- package/dist/tui-v2/components/status/context-limit-chip.d.ts +17 -0
- package/dist/tui-v2/components/status/context-limit-chip.js +72 -0
- package/dist/tui-v2/components/status/context-limit-chip.js.map +1 -0
- package/dist/tui-v2/components/status/status-line.d.ts +3 -4
- package/dist/tui-v2/components/status/status-line.js +6 -17
- package/dist/tui-v2/components/status/status-line.js.map +1 -1
- package/dist/tui-v2/components/transcript/transcript-view.js +8 -7
- package/dist/tui-v2/components/transcript/transcript-view.js.map +1 -1
- package/dist/tui-v2/components/transcript/use-transcript-selection.js +57 -22
- package/dist/tui-v2/components/transcript/use-transcript-selection.js.map +1 -1
- package/dist/tui-v2/composer/composer-editor.js +5 -1
- package/dist/tui-v2/composer/composer-editor.js.map +1 -1
- package/dist/tui-v2/controllers/selection-controller.js +7 -1
- package/dist/tui-v2/controllers/selection-controller.js.map +1 -1
- package/dist/tui-v2/state/semantic-document.js +13 -1
- package/dist/tui-v2/state/semantic-document.js.map +1 -1
- package/dist/tui-v2/state/transcript-reducer.js +12 -4
- package/dist/tui-v2/state/transcript-reducer.js.map +1 -1
- package/dist/version.generated.d.ts +2 -2
- package/dist/version.generated.js +2 -2
- package/dist/version.generated.js.map +1 -1
- package/package.json +1 -1
|
@@ -4,7 +4,9 @@ import { modelContextWindow } from "../llm/token-usage.js";
|
|
|
4
4
|
// request tokens (system blocks, history, tool protocol, schemas and media
|
|
5
5
|
// together) rather than in transcript size. Behaviour, status line and
|
|
6
6
|
// reliability policy all read this module so they cannot disagree.
|
|
7
|
-
export const DEFAULT_AUTO_COMPACT_REQUEST_TOKENS =
|
|
7
|
+
export const DEFAULT_AUTO_COMPACT_REQUEST_TOKENS = 180_000;
|
|
8
|
+
/** A session-specific model window reserves 30% for output and wire overhead. */
|
|
9
|
+
export const CUSTOM_CONTEXT_COMPACTION_RATIO = 0.7;
|
|
8
10
|
// Never trigger below this: compaction itself needs room to be useful.
|
|
9
11
|
export const MIN_AUTO_COMPACT_REQUEST_TOKENS = 20_000;
|
|
10
12
|
// Output allowance reserved inside the model window before the trigger.
|
|
@@ -35,25 +37,40 @@ export function modelSafeRequestTokens(provider, model) {
|
|
|
35
37
|
return Math.max(MIN_AUTO_COMPACT_REQUEST_TOKENS, window - RESERVED_OUTPUT_TOKENS - SAFETY_MARGIN_TOKENS);
|
|
36
38
|
}
|
|
37
39
|
export function resolveRequestBudget(input) {
|
|
40
|
+
const customLimit = input?.contextLimitTokens;
|
|
41
|
+
if (typeof customLimit === "number" &&
|
|
42
|
+
Number.isFinite(customLimit) &&
|
|
43
|
+
customLimit >= MIN_AUTO_COMPACT_REQUEST_TOKENS) {
|
|
44
|
+
const modelSafe = Math.floor(customLimit);
|
|
45
|
+
const effectiveTrigger = Math.floor(modelSafe * CUSTOM_CONTEXT_COMPACTION_RATIO);
|
|
46
|
+
return {
|
|
47
|
+
configured: effectiveTrigger,
|
|
48
|
+
modelSafe,
|
|
49
|
+
effectiveTrigger,
|
|
50
|
+
source: "session",
|
|
51
|
+
clampedByModel: false,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
38
54
|
const resolved = configuredRequestTokens();
|
|
39
55
|
const raw = input?.overrideTokens ?? resolved.tokens;
|
|
40
56
|
const configured = Math.max(MIN_AUTO_COMPACT_REQUEST_TOKENS, raw);
|
|
41
57
|
const modelSafe = modelSafeRequestTokens(input?.provider, input?.model);
|
|
42
|
-
const effectiveTrigger = Math.min(configured, modelSafe);
|
|
43
58
|
return {
|
|
44
59
|
configured,
|
|
45
60
|
modelSafe,
|
|
46
|
-
effectiveTrigger,
|
|
61
|
+
effectiveTrigger: configured,
|
|
47
62
|
source: input?.overrideTokens === undefined ? resolved.source : "explicit",
|
|
48
|
-
|
|
63
|
+
// The explicit 180k default is provider/model-neutral. A user can opt into
|
|
64
|
+
// a different window through the session control, which always uses 70%.
|
|
65
|
+
clampedByModel: false,
|
|
49
66
|
};
|
|
50
67
|
}
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
export function requestBudgetDenominator(provider, model) {
|
|
68
|
+
// Request budget used by callers that need the active compaction trigger.
|
|
69
|
+
export function requestBudgetDenominator(provider, model, contextLimitTokens) {
|
|
54
70
|
return resolveRequestBudget({
|
|
55
71
|
...(provider ? { provider } : {}),
|
|
56
72
|
...(model ? { model } : {}),
|
|
73
|
+
...(contextLimitTokens ? { contextLimitTokens } : {}),
|
|
57
74
|
}).effectiveTrigger;
|
|
58
75
|
}
|
|
59
76
|
//# sourceMappingURL=request-budget.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-budget.js","sourceRoot":"","sources":["../../src/agent/request-budget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAG3D,yEAAyE;AACzE,2EAA2E;AAC3E,uEAAuE;AACvE,mEAAmE;AACnE,MAAM,CAAC,MAAM,mCAAmC,GAAG,OAAO,CAAC;AAE3D,uEAAuE;AACvE,MAAM,CAAC,MAAM,+BAA+B,GAAG,MAAM,CAAC;AAEtD,wEAAwE;AACxE,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAE7C,4DAA4D;AAC5D,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,CAAC;AAiB1C,0EAA0E;AAC1E,+EAA+E;AAC/E,yEAAyE;AACzE,MAAM,UAAU,uBAAuB;IAIrC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,IACE,oBAAoB,CAAC,0BAA0B,CAAC;QAChD,OAAO,MAAM,CAAC,wBAAwB,KAAK,QAAQ,EACnD,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,wBAAwB,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IACzE,CAAC;IACD,IACE,oBAAoB,CAAC,wBAAwB,CAAC;QAC9C,OAAO,MAAM,CAAC,sBAAsB,KAAK,QAAQ,EACjD,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,sBAAsB,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACrE,CAAC;IACD,OAAO;QACL,MAAM,EAAE,mCAAmC;QAC3C,MAAM,EAAE,SAAS;KAClB,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,sBAAsB,CACpC,QAAgC,EAChC,KAAyB;IAEzB,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACnD,OAAO,IAAI,CAAC,GAAG,CACb,+BAA+B,EAC/B,MAAM,GAAG,sBAAsB,GAAG,oBAAoB,CACvD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,
|
|
1
|
+
{"version":3,"file":"request-budget.js","sourceRoot":"","sources":["../../src/agent/request-budget.ts"],"names":[],"mappings":"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"}
|
package/dist/agent/runner.d.ts
CHANGED
|
@@ -56,6 +56,8 @@ export interface AgentRunOptions {
|
|
|
56
56
|
displayPrompt?: string | null | undefined;
|
|
57
57
|
/** How the previous turn ended, so recovery is decided from state. */
|
|
58
58
|
previousTurn?: PreviousTurnSignal | undefined;
|
|
59
|
+
/** User-declared model window for this provider/model/session. */
|
|
60
|
+
contextLimitTokens?: number | undefined;
|
|
59
61
|
}
|
|
60
62
|
export declare function runAgentTurn(prompt: string, options?: AgentRunOptions): Promise<import("./turn-outcome.js").TurnOutcome>;
|
|
61
63
|
/** Compatibility boundary for callers that consume visible assistant text. */
|
package/dist/agent/runner.js
CHANGED
|
@@ -60,7 +60,6 @@ import { maybeAppendPlanModeReminder, PLAN_REMINDER_TOAST, } from "./plan-mode-r
|
|
|
60
60
|
import { LoopGuard } from "./loop-guard.js";
|
|
61
61
|
import { appendInterruptedReasoning, interruptedReasoningBrief, isMeaningfulResumptionYield, } from "./interrupted-reasoning.js";
|
|
62
62
|
import { CompactionAttemptLedger, compactionAttemptKey, } from "./compaction-attempt.js";
|
|
63
|
-
import { resolveRequestBudget } from "./request-budget.js";
|
|
64
63
|
import { loadPlan, mutatePlan, markTask, appendPlanTask, readyPlanTasks, foregroundRemaining, responderOpenTasks, isPlanTerminal, isPlanSuccessful, } from "../store/plan.js";
|
|
65
64
|
import { stat } from "node:fs/promises";
|
|
66
65
|
import { isOutsideWorkingDirectory, resolveFsToolPath, } from "../tools/fs.js";
|
|
@@ -558,10 +557,11 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
558
557
|
imageView: visionAvailable,
|
|
559
558
|
// E6: slim native constitution when API tool schemas are attached.
|
|
560
559
|
...(native ? { slimNative: reliability.slimNativePrompt } : {}),
|
|
561
|
-
...(pentestPromptTurn ? { pentest: true } : {}),
|
|
562
560
|
});
|
|
563
561
|
};
|
|
564
|
-
const systemSections = [
|
|
562
|
+
const systemSections = [
|
|
563
|
+
renderRequestEnvironmentContext({ plan: activePlan }),
|
|
564
|
+
];
|
|
565
565
|
if (projectContext) {
|
|
566
566
|
systemSections.push(`Project context from .clai/context.md:\n${projectContext}`);
|
|
567
567
|
}
|
|
@@ -2829,10 +2829,10 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
2829
2829
|
{ role: "user", content: summaryPrompt },
|
|
2830
2830
|
],
|
|
2831
2831
|
temperature: 0.1,
|
|
2832
|
-
maxTokens:
|
|
2832
|
+
maxTokens: 8_192,
|
|
2833
2833
|
signal: options.signal,
|
|
2834
2834
|
};
|
|
2835
|
-
const response = await streamWithProvider(request, (token) => deltaParser?.push(token), { onStatus: () => undefined });
|
|
2835
|
+
const response = await streamWithProvider(request, (token) => deltaParser?.push(token), { onStatus: () => undefined, maxRetries: 1 });
|
|
2836
2836
|
deltaParser?.finish();
|
|
2837
2837
|
const parsed = stripThinking(response.text);
|
|
2838
2838
|
if (parsed.visible.trim() || !parsed.hasThinking)
|
|
@@ -2849,7 +2849,7 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
2849
2849
|
temperature: 0,
|
|
2850
2850
|
maxTokens: 8_192,
|
|
2851
2851
|
thinking: { enabled: false, effort: "none" },
|
|
2852
|
-
});
|
|
2852
|
+
}, { maxRetries: 1 });
|
|
2853
2853
|
const retryVisible = stripThinking(retry.text).visible.trim();
|
|
2854
2854
|
if (retryVisible && compactionId) {
|
|
2855
2855
|
writeCompactionDelta(compactionId, retryVisible);
|
|
@@ -2918,8 +2918,13 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
2918
2918
|
}
|
|
2919
2919
|
async function maybeAutoCompact(reason, force = false) {
|
|
2920
2920
|
const beforeTokens = estimateNextRequestTokens(messages);
|
|
2921
|
-
const
|
|
2922
|
-
|
|
2921
|
+
const compactTrigger = autoCompactTriggerTokens(getReliabilityPolicy(), {
|
|
2922
|
+
provider,
|
|
2923
|
+
model,
|
|
2924
|
+
...(options.contextLimitTokens
|
|
2925
|
+
? { contextLimitTokens: options.contextLimitTokens }
|
|
2926
|
+
: {}),
|
|
2927
|
+
});
|
|
2923
2928
|
if (!force && beforeTokens < compactTrigger)
|
|
2924
2929
|
return;
|
|
2925
2930
|
// Structural eligibility only: there must be closed history to summarize.
|
|
@@ -3003,12 +3008,10 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
3003
3008
|
: insertedText(insertedSummary, insertedSummary.startsWith(PLAN_IMPLEMENT_MEMORY_PREFIX)
|
|
3004
3009
|
? PLAN_IMPLEMENT_MEMORY_PREFIX
|
|
3005
3010
|
: COMPACTION_MEMORY_PREFIX);
|
|
3006
|
-
//
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
: "";
|
|
3011
|
-
writeNotice("info", `context auto-compacted to fit the window (~${beforeTokens.toLocaleString()} → ~${compactedTokens.toLocaleString()} tokens${planNote})`, chalk.dim(` ℹ context auto-compacted (~${beforeTokens.toLocaleString()} → ~${compactedTokens.toLocaleString()} tokens${planNote})\n`));
|
|
3011
|
+
// Report the final assembled request, including live plan and session
|
|
3012
|
+
// state reinjection, so the card and the next provider request agree.
|
|
3013
|
+
writeCompactionCompleted(compactionId, summaryText, beforeTokens, afterTokens);
|
|
3014
|
+
writeNotice("info", `context auto-compacted to fit the window (~${beforeTokens.toLocaleString()} → ~${afterTokens.toLocaleString()} tokens)`, chalk.dim(` ℹ context auto-compacted (~${beforeTokens.toLocaleString()} → ~${afterTokens.toLocaleString()} tokens)\n`));
|
|
3012
3015
|
}
|
|
3013
3016
|
catch (error) {
|
|
3014
3017
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -3121,7 +3124,7 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
3121
3124
|
? `${seconds}s`
|
|
3122
3125
|
: `${Math.floor(seconds / 60)}m${String(seconds % 60).padStart(2, "0")}s`;
|
|
3123
3126
|
if (generatedTokens > 0 && !inThinking) {
|
|
3124
|
-
return `generating response · ${
|
|
3127
|
+
return `generating response · ${elapsed}`;
|
|
3125
3128
|
}
|
|
3126
3129
|
if (sawReasoning)
|
|
3127
3130
|
return `thinking · ${elapsed}`;
|
|
@@ -3166,6 +3169,11 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
3166
3169
|
const turnTools = selectToolDefs(nativeToolsActive, useCompactSystemPrompt);
|
|
3167
3170
|
toolsAttached = Boolean(turnTools?.length);
|
|
3168
3171
|
const contextBreakdown = buildContextBreakdown(messages, toolsAttached ? turnTools : undefined);
|
|
3172
|
+
emit({
|
|
3173
|
+
type: "context-estimate",
|
|
3174
|
+
estimatedTokens: contextBreakdown.estimatedTotalTokens,
|
|
3175
|
+
model,
|
|
3176
|
+
});
|
|
3169
3177
|
// E4: advisory only — never blocks free-tier users.
|
|
3170
3178
|
if (!freeTierLargeContextWarned) {
|
|
3171
3179
|
const notices = freeTierGuardNotices({
|
|
@@ -3721,7 +3729,10 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
3721
3729
|
const salvageHistoryCalls = ensureUniqueToolCallIds(nativeToolCalls, toolCallIdsInHistory(messages));
|
|
3722
3730
|
const salvagedCallIndex = nativeToolCalls.indexOf(writeTc);
|
|
3723
3731
|
const salvagedCallId = salvageHistoryCalls[salvagedCallIndex]?.id ?? writeTc.id;
|
|
3724
|
-
appendAssistantWithTools(messages, assistantText.visible, salvageHistoryCalls, completion.reasoningBlock
|
|
3732
|
+
appendAssistantWithTools(messages, assistantText.visible, salvageHistoryCalls, completion.reasoningBlock ??
|
|
3733
|
+
(assistantText.hasThinking && assistantText.thinkContent
|
|
3734
|
+
? { text: assistantText.thinkContent }
|
|
3735
|
+
: undefined));
|
|
3725
3736
|
for (const tc of salvageHistoryCalls) {
|
|
3726
3737
|
appendToolResult(messages, tc.id, tc.id === salvagedCallId
|
|
3727
3738
|
? `Tool ${tc.name} result (exit=0, ok=true):\nSalvaged partial write: ${lineCount} lines to ${salvaged.path}`
|
|
@@ -4071,6 +4082,7 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
4071
4082
|
sawServerTail,
|
|
4072
4083
|
sawLocalHttpProbe,
|
|
4073
4084
|
sawFailedLocalHttpProbe,
|
|
4085
|
+
serverCriterionRequired: outcomeState.outcome.criteria.some((criterion) => criterion.domain === "server" && criterion.required),
|
|
4074
4086
|
sawActivePentestTest,
|
|
4075
4087
|
sawSuccessfulMutation,
|
|
4076
4088
|
featureAppAsk,
|
|
@@ -4254,7 +4266,9 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
4254
4266
|
if (sequenceDecision.suppress) {
|
|
4255
4267
|
const reason = sequenceDecision.terminal
|
|
4256
4268
|
? "The model repeated the same action sequence after it was already suppressed. No commands were run again."
|
|
4257
|
-
:
|
|
4269
|
+
: sequenceDecision.oscillation
|
|
4270
|
+
? "This exact action sequence already completed earlier this turn (the agent is oscillating back to finished work). No commands were run again; every one of these results is already in context — synthesize them and either advance to a genuinely new action or finish."
|
|
4271
|
+
: "The same action sequence already ran in the previous model round. No commands were run again; reuse the existing results and choose a materially different next action or finish.";
|
|
4258
4272
|
writeNotice("warn", reason, chalk.yellow(` ⚠ ${reason}\n`));
|
|
4259
4273
|
const suppressedResults = bound.map((b) => {
|
|
4260
4274
|
const duplicate = runIds.has(b.id);
|
|
@@ -4284,7 +4298,10 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
4284
4298
|
emitToolResult(eventId, result, resultReason);
|
|
4285
4299
|
}
|
|
4286
4300
|
if (historyNativeCalls.length) {
|
|
4287
|
-
appendAssistantWithTools(messages, beforeTool ?? "", historyNativeCalls, completion.reasoningBlock
|
|
4301
|
+
appendAssistantWithTools(messages, beforeTool ?? "", historyNativeCalls, completion.reasoningBlock ??
|
|
4302
|
+
(assistantText.hasThinking && assistantText.thinkContent
|
|
4303
|
+
? { text: assistantText.thinkContent }
|
|
4304
|
+
: undefined));
|
|
4288
4305
|
for (const { b, resultReason, result } of suppressedResults) {
|
|
4289
4306
|
appendToolResult(messages, b.id, `Tool ${b.call.name} result (exit=${result.exitCode}, ok=false):\n${resultReason}`, b.call.name, false);
|
|
4290
4307
|
}
|
|
@@ -4325,7 +4342,10 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
4325
4342
|
}
|
|
4326
4343
|
}
|
|
4327
4344
|
if (historyNativeCalls.length) {
|
|
4328
|
-
appendAssistantWithTools(messages, beforeTool ?? "", historyNativeCalls, completion.reasoningBlock
|
|
4345
|
+
appendAssistantWithTools(messages, beforeTool ?? "", historyNativeCalls, completion.reasoningBlock ??
|
|
4346
|
+
(assistantText.hasThinking && assistantText.thinkContent
|
|
4347
|
+
? { text: assistantText.thinkContent }
|
|
4348
|
+
: undefined));
|
|
4329
4349
|
}
|
|
4330
4350
|
else {
|
|
4331
4351
|
const standardizedContent = (beforeTool ? beforeTool.trim() + "\n\n" : "") +
|