@gajae-code/coding-agent 0.16.0 → 0.16.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/CHANGELOG.md +52 -1
- package/dist/types/async/job-manager.d.ts +32 -1
- package/dist/types/browser-backend.d.ts +12 -0
- package/dist/types/cli/update-cli.d.ts +1 -0
- package/dist/types/commands/sdk.d.ts +2 -0
- package/dist/types/config/billing-path.d.ts +25 -0
- package/dist/types/config/config-schema-version.d.ts +13 -1
- package/dist/types/config/model-registry.d.ts +16 -0
- package/dist/types/config/settings-schema.d.ts +17 -7
- package/dist/types/extensibility/extensions/types.d.ts +8 -3
- package/dist/types/gjc-runtime/launch-worktree.d.ts +25 -1
- package/dist/types/gjc-runtime/session-state-lock.d.ts +22 -0
- package/dist/types/main.d.ts +1 -0
- package/dist/types/modes/acp/acp-agent.d.ts +21 -21
- package/dist/types/modes/components/model-selector.d.ts +4 -0
- package/dist/types/modes/components/session-selector.d.ts +1 -1
- package/dist/types/modes/components/sessions-dashboard.d.ts +2 -1
- package/dist/types/modes/interactive-mode.d.ts +16 -2
- package/dist/types/modes/theme/theme.d.ts +2 -1
- package/dist/types/modes/types.d.ts +2 -0
- package/dist/types/sdk/broker/broker.d.ts +2 -1
- package/dist/types/sdk/broker/ensure.d.ts +3 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +6 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +14 -0
- package/dist/types/sdk/broker/startup-budget.d.ts +52 -0
- package/dist/types/sdk/broker/state-version.d.ts +17 -0
- package/dist/types/sdk/bus/discord-daemon.d.ts +1 -1
- package/dist/types/sdk/bus/index.d.ts +3 -1
- package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +1 -1
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +1 -1
- package/dist/types/sdk/bus/slack-conversation.d.ts +1 -1
- package/dist/types/sdk/bus/slack-daemon.d.ts +1 -1
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +1 -1
- package/dist/types/sdk/cli/rows.d.ts +15 -2
- package/dist/types/sdk/cli/session-cli.d.ts +2 -1
- package/dist/types/sdk/host/events.d.ts +2 -0
- package/dist/types/sdk/host/host.d.ts +2 -0
- package/dist/types/sdk/host/query/cursor.d.ts +4 -2
- package/dist/types/sdk/host/query/handlers.d.ts +1 -0
- package/dist/types/sdk/host/query/revision-store.d.ts +1 -0
- package/dist/types/sdk/host/session-runtime.d.ts +18 -17
- package/dist/types/sdk/lifecycle-session.d.ts +1 -1
- package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -5
- package/dist/types/sdk/receipt-state.d.ts +2 -0
- package/dist/types/sdk/router/session-router.d.ts +4 -0
- package/dist/types/sdk/turn-result.d.ts +6 -0
- package/dist/types/session/agent-session.d.ts +47 -7
- package/dist/types/session/fold-coordinator.d.ts +29 -2
- package/dist/types/session/session-manager.d.ts +14 -2
- package/dist/types/tools/ask.d.ts +1 -0
- package/dist/types/tools/bash.d.ts +12 -0
- package/dist/types/tools/browser/launch.d.ts +10 -0
- package/dist/types/tools/browser/registry.d.ts +8 -0
- package/dist/types/tools/index.d.ts +4 -10
- package/dist/types/tools/job.d.ts +3 -1
- package/dist/types/utils/external-editor.d.ts +12 -0
- package/examples/extensions/README.md +1 -1
- package/examples/extensions/pirate.ts +7 -4
- package/package.json +7 -7
- package/scripts/generate-sdk-operation-inventory.ts +7 -1
- package/src/async/job-manager.ts +107 -9
- package/src/browser-backend.ts +29 -0
- package/src/cli/plugin-cli.ts +29 -0
- package/src/cli/update-cli.ts +63 -12
- package/src/commands/sdk.ts +22 -7
- package/src/config/billing-path.ts +42 -0
- package/src/config/config-schema-version.ts +18 -1
- package/src/config/model-preset-registry.ts +177 -18
- package/src/config/model-registry.ts +268 -42
- package/src/config/settings-schema.ts +19 -7
- package/src/config/settings.ts +46 -15
- package/src/coordinator-mcp/projection-scan.ts +6 -6
- package/src/coordinator-mcp/server.ts +21 -1
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +1 -1
- package/src/extensibility/extensions/runner.ts +27 -0
- package/src/extensibility/extensions/types.ts +8 -3
- package/src/extensibility/gjc-plugins/installer.ts +51 -11
- package/src/extensibility/runtime-skill-discovery.ts +110 -3
- package/src/extensibility/skills.ts +22 -12
- package/src/gjc-runtime/launch-worktree.ts +285 -4
- package/src/gjc-runtime/session-state-lock.ts +156 -32
- package/src/gjc-runtime/session-state-sidecar.ts +10 -17
- package/src/gjc-runtime/tmux-owner-isolation.ts +16 -1
- package/src/internal-urls/docs-index.generated.ts +11 -11
- package/src/main.ts +4 -1
- package/src/modes/acp/acp-agent.ts +34 -19
- package/src/modes/components/model-selector.ts +76 -8
- package/src/modes/components/session-selector.ts +23 -15
- package/src/modes/components/sessions-dashboard.ts +8 -5
- package/src/modes/controllers/command-controller.ts +1 -1
- package/src/modes/controllers/event-controller.ts +30 -4
- package/src/modes/controllers/extension-ui-controller.ts +13 -13
- package/src/modes/controllers/input-controller.ts +2 -2
- package/src/modes/controllers/selector-controller.ts +10 -3
- package/src/modes/interactive-mode.ts +36 -12
- package/src/modes/prompt-action-autocomplete.ts +30 -4
- package/src/modes/runtime-init.ts +12 -9
- package/src/modes/theme/theme.ts +5 -0
- package/src/modes/types.ts +2 -0
- package/src/modes/utils/ui-helpers.ts +22 -3
- package/src/prompts/agent-fragments/browser-aside.md +22 -0
- package/src/prompts/tools/ask.md +1 -1
- package/src/prompts/tools/bash.md +1 -0
- package/src/prompts/tools/job.md +1 -1
- package/src/sdk/acp/adapter.ts +6 -1
- package/src/sdk/broker/broker.ts +10 -1
- package/src/sdk/broker/ensure.ts +76 -3
- package/src/sdk/broker/lifecycle-ledger.ts +6 -0
- package/src/sdk/broker/lifecycle.ts +254 -34
- package/src/sdk/broker/spawn-substrate.ts +45 -2
- package/src/sdk/broker/startup-budget.ts +144 -2
- package/src/sdk/broker/state-version.ts +17 -0
- package/src/sdk/bus/chat-daemon-control.ts +2 -2
- package/src/sdk/bus/chat-daemon-runtime.ts +118 -24
- package/src/sdk/bus/discord-daemon.ts +50 -10
- package/src/sdk/bus/index.ts +33 -3
- package/src/sdk/bus/kind-aware-reconciliation.ts +296 -48
- package/src/sdk/bus/lifecycle-commands.ts +4 -0
- package/src/sdk/bus/notification-service.ts +22 -5
- package/src/sdk/bus/prompt-reconciliation.ts +7 -2
- package/src/sdk/bus/reconciliation-store.ts +55 -31
- package/src/sdk/bus/slack-conversation.ts +1 -1
- package/src/sdk/bus/slack-daemon.ts +72 -38
- package/src/sdk/bus/telegram-daemon-contract.ts +1 -1
- package/src/sdk/cli/rows.ts +75 -7
- package/src/sdk/cli/session-cli.ts +68 -35
- package/src/sdk/host/control/dispatch.ts +2 -2
- package/src/sdk/host/events.ts +26 -2
- package/src/sdk/host/host.ts +6 -1
- package/src/sdk/host/query/cursor.ts +52 -7
- package/src/sdk/host/query/handlers.ts +33 -12
- package/src/sdk/host/query/revision-store.ts +12 -0
- package/src/sdk/host/session-runtime.test.ts +497 -31
- package/src/sdk/host/session-runtime.ts +387 -54
- package/src/sdk/host/surface-policy.ts +3 -3
- package/src/sdk/lifecycle-session.ts +7 -2
- package/src/sdk/prompt-deadline-manager.ts +2 -1
- package/src/sdk/protocol/operation-inventory.generated.json +54 -3
- package/src/sdk/protocol/operation-registry.ts +1 -1
- package/src/sdk/receipt-state.ts +10 -0
- package/src/sdk/router/session-router.ts +210 -94
- package/src/sdk/session.ts +59 -41
- package/src/sdk/turn-result.ts +22 -0
- package/src/session/agent-session.ts +1033 -260
- package/src/session/fold-coordinator.ts +40 -3
- package/src/session/session-manager.ts +517 -77
- package/src/slash-commands/builtin-registry.ts +41 -0
- package/src/task/executor.ts +9 -4
- package/src/tools/ask-contract.test.ts +64 -0
- package/src/tools/ask-contract.ts +36 -1
- package/src/tools/ask.ts +10 -8
- package/src/tools/bash-interactive.ts +11 -2
- package/src/tools/bash.ts +158 -33
- package/src/tools/browser/launch.ts +37 -0
- package/src/tools/browser/registry.ts +99 -9
- package/src/tools/cron.ts +6 -4
- package/src/tools/descriptors.test.ts +15 -0
- package/src/tools/descriptors.ts +5 -1
- package/src/tools/index.ts +4 -6
- package/src/tools/job.ts +4 -1
- package/src/tools/monitor.ts +12 -9
- package/src/tools/resolve.ts +30 -10
- package/src/tools/tool-catalog.generated.ts +2 -2
- package/src/utils/external-editor.ts +86 -1
package/src/sdk/session.ts
CHANGED
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
isBackgroundJobSupportEnabled,
|
|
52
52
|
jobElapsedMs,
|
|
53
53
|
} from "../async";
|
|
54
|
+
import { resolveBrowserBackend } from "../browser-backend";
|
|
54
55
|
import { loadCapability, reset as resetCapabilities } from "../capability";
|
|
55
56
|
import { type Rule, ruleCapability, setActiveRules } from "../capability/rule";
|
|
56
57
|
import type { SourceMeta } from "../capability/types";
|
|
@@ -150,7 +151,7 @@ import { markAutoroutingInactive } from "../sdk/host/internal-autorouting-state"
|
|
|
150
151
|
import { createSdkSessionRuntimeExtension, registerSdkOnlyNotificationCommand } from "../sdk/host/session-runtime";
|
|
151
152
|
import { createSdkWebSocketTransport } from "../sdk/host/websocket-transport";
|
|
152
153
|
import type { SecretObfuscator } from "../secrets";
|
|
153
|
-
import { AgentSession, type ForkContextSeed } from "../session/agent-session";
|
|
154
|
+
import { AgentSession, type ForkContextSeed, isSessionDisposalIncompleteError } from "../session/agent-session";
|
|
154
155
|
import { AuthBrokerClient, AuthStorage, RemoteAuthCredentialStore } from "../session/auth-storage";
|
|
155
156
|
import { type CustomMessage, convertToLlm } from "../session/messages";
|
|
156
157
|
import { createReadonlySessionManager, SessionManager } from "../session/session-manager";
|
|
@@ -1104,12 +1105,16 @@ function buildMCPPromptCommands(manager: MCPManager): LoadedCustomCommand[] {
|
|
|
1104
1105
|
*/
|
|
1105
1106
|
|
|
1106
1107
|
function withEmbeddedDefaultGjcSkills(skills: Skill[]): Skill[] {
|
|
1107
|
-
const byName = new Map
|
|
1108
|
+
const byName = new Map<string, Skill>();
|
|
1109
|
+
for (const skill of skills) {
|
|
1110
|
+
const key = skill.name.toLowerCase();
|
|
1111
|
+
if (!byName.has(key)) byName.set(key, skill);
|
|
1112
|
+
}
|
|
1108
1113
|
// The four public GJC workflow skills are a product invariant: even if a
|
|
1109
1114
|
// caller-supplied or filesystem skill shares a name, the bundled definition
|
|
1110
1115
|
// wins so workflow routing can never be silently hijacked.
|
|
1111
1116
|
for (const defaultSkill of getEmbeddedDefaultGjcSkills()) {
|
|
1112
|
-
byName.set(defaultSkill.name, defaultSkill);
|
|
1117
|
+
byName.set(defaultSkill.name.toLowerCase(), defaultSkill);
|
|
1113
1118
|
}
|
|
1114
1119
|
return [...byName.values()];
|
|
1115
1120
|
}
|
|
@@ -2438,7 +2443,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2438
2443
|
"Cannot rescope a session with caller-owned MCP authority; recreate the session at the target cwd.",
|
|
2439
2444
|
);
|
|
2440
2445
|
}
|
|
2441
|
-
return sessionManager.
|
|
2446
|
+
return sessionManager.runExclusiveCwdMoveTransition(async () => {
|
|
2442
2447
|
if (moveConsumed) {
|
|
2443
2448
|
throw new Error(
|
|
2444
2449
|
"This session has already been rescoped; only one agent-invoked move is allowed per session.",
|
|
@@ -2713,7 +2718,8 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2713
2718
|
registerForegroundFoldParticipant: adapter =>
|
|
2714
2719
|
session?.registerForegroundFoldParticipant(adapter) ?? (() => {}),
|
|
2715
2720
|
hasForegroundBashBackgroundRequestHandler: () => session?.hasForegroundBashBackgroundRequestHandler() ?? false,
|
|
2716
|
-
requestForegroundBashBackground: () =>
|
|
2721
|
+
requestForegroundBashBackground: (reason, adapter) =>
|
|
2722
|
+
Promise.resolve(session?.requestForegroundBashBackground(reason, adapter) ?? false),
|
|
2717
2723
|
|
|
2718
2724
|
getCredentialSessionId: () => session?.credentialSessionId ?? credentialSessionId,
|
|
2719
2725
|
getMcpManager: () => mcpManager ?? options.inheritedMcpManager,
|
|
@@ -2770,16 +2776,6 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2770
2776
|
return m ? buildNamedToolChoice(name, m) : undefined;
|
|
2771
2777
|
},
|
|
2772
2778
|
buildToolChoiceResult: name => buildNamedToolChoiceResult(name, session.model),
|
|
2773
|
-
steer: msg =>
|
|
2774
|
-
session.agent.steer({
|
|
2775
|
-
role: "custom",
|
|
2776
|
-
customType: msg.customType,
|
|
2777
|
-
content: msg.content,
|
|
2778
|
-
display: false,
|
|
2779
|
-
details: msg.details,
|
|
2780
|
-
attribution: "agent",
|
|
2781
|
-
timestamp: Date.now(),
|
|
2782
|
-
}),
|
|
2783
2779
|
sendCustomMessage: (msg, opts) => session.sendCustomMessage(msg, opts),
|
|
2784
2780
|
purgeQueuedCustomMessages: predicate => session.purgeQueuedCustomMessages(predicate),
|
|
2785
2781
|
peekQueueInvoker: () => session.peekQueueInvoker(),
|
|
@@ -3562,7 +3558,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
3562
3558
|
!model &&
|
|
3563
3559
|
!options.modelPattern &&
|
|
3564
3560
|
!startupCredentialModelRejected &&
|
|
3565
|
-
configuredDefaultPatterns.length === 0
|
|
3561
|
+
(configuredDefaultPatterns.length === 0 || preferredCredentialProvider !== undefined)
|
|
3566
3562
|
) {
|
|
3567
3563
|
// Re-resolve the allowed set: extension factories above may have
|
|
3568
3564
|
// registered providers/models that weren't visible at startup.
|
|
@@ -3896,7 +3892,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
3896
3892
|
? await memoryBackend.buildDeveloperInstructions(agentDir, settings, session)
|
|
3897
3893
|
: undefined;
|
|
3898
3894
|
|
|
3899
|
-
const
|
|
3895
|
+
const browserBackend = resolveBrowserBackend(settings);
|
|
3896
|
+
const appendPrompt =
|
|
3897
|
+
[memoryInstructions, browserBackend.developerInstructions].filter(Boolean).join("\n\n") || undefined;
|
|
3900
3898
|
let pluginSystemAppendices = "";
|
|
3901
3899
|
try {
|
|
3902
3900
|
pluginSystemAppendices = await renderAlwaysOnSystemAppendices({ cwd: getLiveCwd() });
|
|
@@ -4277,7 +4275,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
4277
4275
|
transformContext,
|
|
4278
4276
|
steeringMode: settings.get("steeringMode") ?? "one-at-a-time",
|
|
4279
4277
|
followUpMode: settings.get("followUpMode") ?? "one-at-a-time",
|
|
4280
|
-
|
|
4278
|
+
toolInterruptPolicy: settings.get("toolInterruptPolicy") ?? "abort_tools",
|
|
4281
4279
|
thinkingBudgets: settings.getGroup("thinkingBudgets"),
|
|
4282
4280
|
temperature: settings.get("temperature") >= 0 ? settings.get("temperature") : undefined,
|
|
4283
4281
|
topP: settings.get("topP") >= 0 ? settings.get("topP") : undefined,
|
|
@@ -4575,38 +4573,49 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
4575
4573
|
|
|
4576
4574
|
// Attach the live session to the pre-registered ref so peers can route IRC
|
|
4577
4575
|
// messages here. Refresh sessionFile in case it was unavailable at pre-register
|
|
4578
|
-
// time. The
|
|
4576
|
+
// time. The registered terminal cleanup below unregisters on teardown.
|
|
4579
4577
|
agentRegistry.attachSession(resolvedAgentId, session, sessionManager.getSessionFile() ?? null);
|
|
4580
4578
|
{
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4579
|
+
let cleanupPromise: Promise<void> | undefined;
|
|
4580
|
+
const finishCleanup = async (): Promise<void> => {
|
|
4581
|
+
if (cleanupPromise) return cleanupPromise;
|
|
4582
|
+
const cleanup = (async () => {
|
|
4583
|
+
const failures: unknown[] = [];
|
|
4586
4584
|
try {
|
|
4587
4585
|
agentRegistry.unregister(resolvedAgentId);
|
|
4588
4586
|
releaseCredentialDisabledSubscription();
|
|
4589
4587
|
releaseLocalProtocolOverride();
|
|
4588
|
+
} catch (error) {
|
|
4589
|
+
failures.push(error);
|
|
4590
4590
|
} finally {
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
);
|
|
4603
|
-
|
|
4591
|
+
try {
|
|
4592
|
+
if (!options.parentTaskPrefix) {
|
|
4593
|
+
retireOwnedRegistrationsForEndpoint(
|
|
4594
|
+
AsyncJobManager.endpointIdOf(asyncJobManager) ?? asyncJobEndpointId,
|
|
4595
|
+
);
|
|
4596
|
+
AsyncJobManager.unregisterManager(asyncJobManager);
|
|
4597
|
+
}
|
|
4598
|
+
} catch (error) {
|
|
4599
|
+
failures.push(error);
|
|
4600
|
+
}
|
|
4601
|
+
try {
|
|
4602
|
+
await closeOwnedAuthStorage();
|
|
4603
|
+
} catch (error) {
|
|
4604
|
+
failures.push(error);
|
|
4605
|
+
}
|
|
4606
|
+
try {
|
|
4607
|
+
await closeOwnedSettings();
|
|
4608
|
+
} catch (error) {
|
|
4609
|
+
failures.push(error);
|
|
4604
4610
|
}
|
|
4605
|
-
await closeOwnedAuthStorage();
|
|
4606
|
-
await closeOwnedSettings();
|
|
4607
4611
|
}
|
|
4608
|
-
|
|
4612
|
+
if (failures.length > 0) throw new AggregateError(failures, "SDK disposal cleanup failed.");
|
|
4613
|
+
})();
|
|
4614
|
+
cleanupPromise = cleanup;
|
|
4615
|
+
void cleanup.catch(() => {});
|
|
4616
|
+
return cleanup;
|
|
4609
4617
|
};
|
|
4618
|
+
session.registerToolSessionCleanup(finishCleanup);
|
|
4610
4619
|
}
|
|
4611
4620
|
|
|
4612
4621
|
if (model?.api === "openai-codex-responses") {
|
|
@@ -4834,7 +4843,16 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
4834
4843
|
let cleanupDiagnostic: unknown;
|
|
4835
4844
|
try {
|
|
4836
4845
|
if (hasSession) {
|
|
4837
|
-
|
|
4846
|
+
try {
|
|
4847
|
+
await session.dispose();
|
|
4848
|
+
} catch (disposeError) {
|
|
4849
|
+
if (!isSessionDisposalIncompleteError(disposeError)) {
|
|
4850
|
+
throw disposeError;
|
|
4851
|
+
}
|
|
4852
|
+
// The first call is intentionally bounded for startup callers. Join the
|
|
4853
|
+
// retained teardown before releasing the resources it still owns.
|
|
4854
|
+
await session.awaitDisposeCompletion();
|
|
4855
|
+
}
|
|
4838
4856
|
} else {
|
|
4839
4857
|
if (hasRegistered) agentRegistry.unregister(resolvedAgentId);
|
|
4840
4858
|
// Admission happens before session construction. Any later startup
|
package/src/sdk/turn-result.ts
CHANGED
|
@@ -17,6 +17,7 @@ export interface TurnResultError {
|
|
|
17
17
|
code: string;
|
|
18
18
|
message: string;
|
|
19
19
|
}
|
|
20
|
+
export type TurnResultReceiptState = "absent" | "present" | "missing" | "unknown";
|
|
20
21
|
export interface TurnResultPage {
|
|
21
22
|
status: TurnResultStatus;
|
|
22
23
|
kind?: "prompt" | "skill";
|
|
@@ -26,6 +27,8 @@ export interface TurnResultPage {
|
|
|
26
27
|
acceptedAt?: number;
|
|
27
28
|
startedAt?: number;
|
|
28
29
|
terminalAt?: number;
|
|
30
|
+
receiptState?: TurnResultReceiptState;
|
|
31
|
+
outcome?: unknown;
|
|
29
32
|
content?: TurnResultContent;
|
|
30
33
|
error?: TurnResultError;
|
|
31
34
|
}
|
|
@@ -51,3 +54,22 @@ export function sanitizeTurnResultContent(text: unknown): TurnResultContent | un
|
|
|
51
54
|
truncated,
|
|
52
55
|
};
|
|
53
56
|
}
|
|
57
|
+
|
|
58
|
+
export function reportableTurnResultContent(content: TurnResultContent | undefined): boolean {
|
|
59
|
+
return content !== undefined && content.text.trim().length > 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** First reportable invocation-owned content wins; blank evidence remains replaceable. */
|
|
63
|
+
export function reduceTurnResultContent(
|
|
64
|
+
existing: TurnResultContent | undefined,
|
|
65
|
+
incoming: TurnResultContent | undefined,
|
|
66
|
+
): TurnResultContent | undefined {
|
|
67
|
+
if (reportableTurnResultContent(existing)) return existing;
|
|
68
|
+
if (incoming === undefined) return existing;
|
|
69
|
+
const sanitized = sanitizeTurnResultContent(incoming.text);
|
|
70
|
+
if (sanitized === undefined) return existing;
|
|
71
|
+
return {
|
|
72
|
+
...sanitized,
|
|
73
|
+
truncated: sanitized.truncated || incoming.truncated || existing?.truncated === true,
|
|
74
|
+
};
|
|
75
|
+
}
|