mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-05 05:50:22 +00:00
refactor(cli): remove bundled cli text providers
This commit is contained in:
@@ -5,11 +5,8 @@ import {
|
||||
resolveSendableOutboundReplyParts,
|
||||
} from "openclaw/plugin-sdk/reply-payload";
|
||||
import { resolveBootstrapWarningSignaturesSeen } from "../../agents/bootstrap-budget.js";
|
||||
import { runCliAgent } from "../../agents/cli-runner.js";
|
||||
import { getCliSessionBinding } from "../../agents/cli-session.js";
|
||||
import { LiveSessionModelSwitchError } from "../../agents/live-model-switch-error.js";
|
||||
import { runWithModelFallback, isFallbackSummaryError } from "../../agents/model-fallback.js";
|
||||
import { isCliProvider } from "../../agents/model-selection.js";
|
||||
import {
|
||||
BILLING_ERROR_USER_MESSAGE,
|
||||
isCompactionFailureError,
|
||||
@@ -697,126 +694,6 @@ export async function runAgentTurnWithFallback(params: {
|
||||
);
|
||||
}
|
||||
|
||||
if (isCliProvider(provider, params.followupRun.run.config)) {
|
||||
const startedAt = Date.now();
|
||||
notifyAgentRunStart();
|
||||
emitAgentEvent({
|
||||
runId,
|
||||
stream: "lifecycle",
|
||||
data: {
|
||||
phase: "start",
|
||||
startedAt,
|
||||
},
|
||||
});
|
||||
const cliSessionBinding = getCliSessionBinding(
|
||||
params.getActiveSessionEntry(),
|
||||
provider,
|
||||
);
|
||||
const authProfileId =
|
||||
provider === params.followupRun.run.provider
|
||||
? params.followupRun.run.authProfileId
|
||||
: undefined;
|
||||
return (async () => {
|
||||
let lifecycleTerminalEmitted = false;
|
||||
try {
|
||||
const result = await runCliAgent({
|
||||
sessionId: params.followupRun.run.sessionId,
|
||||
sessionKey: params.sessionKey,
|
||||
agentId: params.followupRun.run.agentId,
|
||||
sessionFile: params.followupRun.run.sessionFile,
|
||||
workspaceDir: params.followupRun.run.workspaceDir,
|
||||
config: params.followupRun.run.config,
|
||||
prompt: params.commandBody,
|
||||
provider,
|
||||
model,
|
||||
thinkLevel: params.followupRun.run.thinkLevel,
|
||||
timeoutMs: params.followupRun.run.timeoutMs,
|
||||
runId,
|
||||
extraSystemPrompt: params.followupRun.run.extraSystemPrompt,
|
||||
ownerNumbers: params.followupRun.run.ownerNumbers,
|
||||
cliSessionId: cliSessionBinding?.sessionId,
|
||||
cliSessionBinding,
|
||||
authProfileId,
|
||||
bootstrapPromptWarningSignaturesSeen,
|
||||
bootstrapPromptWarningSignature:
|
||||
bootstrapPromptWarningSignaturesSeen[
|
||||
bootstrapPromptWarningSignaturesSeen.length - 1
|
||||
],
|
||||
images: params.opts?.images,
|
||||
imageOrder: params.opts?.imageOrder,
|
||||
messageProvider: params.followupRun.run.messageProvider,
|
||||
agentAccountId: params.followupRun.run.agentAccountId,
|
||||
abortSignal: params.replyOperation?.abortSignal ?? params.opts?.abortSignal,
|
||||
replyOperation: params.replyOperation,
|
||||
});
|
||||
bootstrapPromptWarningSignaturesSeen = resolveBootstrapWarningSignaturesSeen(
|
||||
result.meta?.systemPromptReport,
|
||||
);
|
||||
|
||||
// CLI backends don't emit streaming assistant events, so we need to
|
||||
// emit one with the final text so server-chat can populate its buffer
|
||||
// and send the response to TUI/WebSocket clients.
|
||||
const cliText = result.payloads?.[0]?.text?.trim();
|
||||
if (cliText) {
|
||||
emitAgentEvent({
|
||||
runId,
|
||||
stream: "assistant",
|
||||
data: { text: cliText },
|
||||
});
|
||||
}
|
||||
|
||||
emitAgentEvent({
|
||||
runId,
|
||||
stream: "lifecycle",
|
||||
data: {
|
||||
phase: "end",
|
||||
startedAt,
|
||||
endedAt: Date.now(),
|
||||
},
|
||||
});
|
||||
lifecycleTerminalEmitted = true;
|
||||
|
||||
return result;
|
||||
} catch (err) {
|
||||
if (rollbackFallbackCandidateSelection) {
|
||||
try {
|
||||
await rollbackFallbackCandidateSelection();
|
||||
} catch (rollbackError) {
|
||||
logVerbose(
|
||||
`failed to roll back fallback candidate selection (non-fatal): ${String(rollbackError)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
emitAgentEvent({
|
||||
runId,
|
||||
stream: "lifecycle",
|
||||
data: {
|
||||
phase: "error",
|
||||
startedAt,
|
||||
endedAt: Date.now(),
|
||||
error: String(err),
|
||||
},
|
||||
});
|
||||
lifecycleTerminalEmitted = true;
|
||||
throw err;
|
||||
} finally {
|
||||
// Defensive backstop: never let a CLI run complete without a terminal
|
||||
// lifecycle event, otherwise downstream consumers can hang.
|
||||
if (!lifecycleTerminalEmitted) {
|
||||
emitAgentEvent({
|
||||
runId,
|
||||
stream: "lifecycle",
|
||||
data: {
|
||||
phase: "error",
|
||||
startedAt,
|
||||
endedAt: Date.now(),
|
||||
error: "CLI run completed without lifecycle terminal event",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
const { embeddedContext, senderContext, runBaseParams } = buildEmbeddedRunExecutionParams(
|
||||
{
|
||||
run: params.followupRun.run,
|
||||
|
||||
@@ -2,7 +2,6 @@ import fs from "node:fs";
|
||||
import { lookupContextTokens } from "../../agents/context.js";
|
||||
import { DEFAULT_CONTEXT_TOKENS } from "../../agents/defaults.js";
|
||||
import { resolveModelAuthMode } from "../../agents/model-auth.js";
|
||||
import { isCliProvider } from "../../agents/model-selection.js";
|
||||
import { queueEmbeddedPiMessage } from "../../agents/pi-embedded.js";
|
||||
import { hasNonzeroUsage } from "../../agents/usage.js";
|
||||
import {
|
||||
@@ -558,12 +557,6 @@ export async function runReplyAgent(params: {
|
||||
});
|
||||
}
|
||||
}
|
||||
const cliSessionId = isCliProvider(providerUsed, cfg)
|
||||
? runResult.meta?.agentMeta?.sessionId?.trim()
|
||||
: undefined;
|
||||
const cliSessionBinding = isCliProvider(providerUsed, cfg)
|
||||
? runResult.meta?.agentMeta?.cliSessionBinding
|
||||
: undefined;
|
||||
const contextTokensUsed =
|
||||
agentCfgContextTokens ??
|
||||
lookupContextTokens(modelUsed) ??
|
||||
@@ -581,9 +574,7 @@ export async function runReplyAgent(params: {
|
||||
providerUsed,
|
||||
contextTokensUsed,
|
||||
systemPromptReport: runResult.meta?.systemPromptReport,
|
||||
cliSessionId,
|
||||
cliSessionBinding,
|
||||
usageIsContextSnapshot: isCliProvider(providerUsed, cfg),
|
||||
usageIsContextSnapshot: false,
|
||||
});
|
||||
|
||||
// Drain any late tool/block deliveries before deciding there's "nothing to send".
|
||||
|
||||
@@ -42,12 +42,7 @@ import { resolveSubagentLabel } from "./subagents-utils.js";
|
||||
|
||||
// Some usage endpoints only work with CLI/session OAuth tokens, not API keys.
|
||||
// Skip those probes when the active auth mode cannot satisfy the endpoint.
|
||||
const USAGE_OAUTH_ONLY_PROVIDERS = new Set([
|
||||
"anthropic",
|
||||
"github-copilot",
|
||||
"google-gemini-cli",
|
||||
"openai-codex",
|
||||
]);
|
||||
const USAGE_OAUTH_ONLY_PROVIDERS = new Set(["anthropic", "github-copilot", "openai-codex"]);
|
||||
|
||||
function shouldLoadUsageSummary(params: {
|
||||
provider?: string;
|
||||
|
||||
@@ -8,7 +8,6 @@ import { resolveBootstrapWarningSignaturesSeen } from "../../agents/bootstrap-bu
|
||||
import { lookupContextTokens } from "../../agents/context.js";
|
||||
import { DEFAULT_CONTEXT_TOKENS } from "../../agents/defaults.js";
|
||||
import { runWithModelFallback } from "../../agents/model-fallback.js";
|
||||
import { isCliProvider } from "../../agents/model-selection.js";
|
||||
import { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
|
||||
import type { SessionEntry } from "../../config/sessions.js";
|
||||
import type { TypingMode } from "../../config/types.js";
|
||||
@@ -305,11 +304,7 @@ export function createFollowupRunner(params: {
|
||||
providerUsed: fallbackProvider,
|
||||
contextTokensUsed,
|
||||
systemPromptReport: runResult.meta?.systemPromptReport,
|
||||
cliSessionBinding: runResult.meta?.agentMeta?.cliSessionBinding,
|
||||
usageIsContextSnapshot: isCliProvider(
|
||||
fallbackProvider ?? queued.run.provider,
|
||||
queued.run.config,
|
||||
),
|
||||
usageIsContextSnapshot: false,
|
||||
logLabel: "followup",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { setCliSessionBinding, setCliSessionId } from "../../agents/cli-session.js";
|
||||
import {
|
||||
deriveSessionTotalTokens,
|
||||
hasNonzeroUsage,
|
||||
@@ -14,39 +13,6 @@ import {
|
||||
import { logVerbose } from "../../globals.js";
|
||||
import { estimateUsageCost, resolveModelCostConfig } from "../../utils/usage-format.js";
|
||||
|
||||
function applyCliSessionIdToSessionPatch(
|
||||
params: {
|
||||
providerUsed?: string;
|
||||
cliSessionId?: string;
|
||||
cliSessionBinding?: import("../../config/sessions.js").CliSessionBinding;
|
||||
},
|
||||
entry: SessionEntry,
|
||||
patch: Partial<SessionEntry>,
|
||||
): Partial<SessionEntry> {
|
||||
const cliProvider = params.providerUsed ?? entry.modelProvider;
|
||||
if (params.cliSessionBinding && cliProvider) {
|
||||
const nextEntry = { ...entry, ...patch };
|
||||
setCliSessionBinding(nextEntry, cliProvider, params.cliSessionBinding);
|
||||
return {
|
||||
...patch,
|
||||
cliSessionIds: nextEntry.cliSessionIds,
|
||||
cliSessionBindings: nextEntry.cliSessionBindings,
|
||||
claudeCliSessionId: nextEntry.claudeCliSessionId,
|
||||
};
|
||||
}
|
||||
if (params.cliSessionId && cliProvider) {
|
||||
const nextEntry = { ...entry, ...patch };
|
||||
setCliSessionId(nextEntry, cliProvider, params.cliSessionId);
|
||||
return {
|
||||
...patch,
|
||||
cliSessionIds: nextEntry.cliSessionIds,
|
||||
cliSessionBindings: nextEntry.cliSessionBindings,
|
||||
claudeCliSessionId: nextEntry.claudeCliSessionId,
|
||||
};
|
||||
}
|
||||
return patch;
|
||||
}
|
||||
|
||||
function resolveNonNegativeNumber(value: number | undefined): number | undefined {
|
||||
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined;
|
||||
}
|
||||
@@ -86,8 +52,6 @@ export async function persistSessionUsageUpdate(params: {
|
||||
promptTokens?: number;
|
||||
usageIsContextSnapshot?: boolean;
|
||||
systemPromptReport?: SessionSystemPromptReport;
|
||||
cliSessionId?: string;
|
||||
cliSessionBinding?: import("../../config/sessions.js").CliSessionBinding;
|
||||
logLabel?: string;
|
||||
}): Promise<void> {
|
||||
const { storePath, sessionKey } = params;
|
||||
@@ -158,7 +122,7 @@ export async function persistSessionUsageUpdate(params: {
|
||||
// context utilization is stale/unknown.
|
||||
patch.totalTokens = totalTokens;
|
||||
patch.totalTokensFresh = typeof totalTokens === "number";
|
||||
return applyCliSessionIdToSessionPatch(params, entry, patch);
|
||||
return patch;
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
@@ -180,7 +144,7 @@ export async function persistSessionUsageUpdate(params: {
|
||||
systemPromptReport: params.systemPromptReport ?? entry.systemPromptReport,
|
||||
updatedAt: Date.now(),
|
||||
};
|
||||
return applyCliSessionIdToSessionPatch(params, entry, patch);
|
||||
return patch;
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
|
||||
@@ -569,9 +569,6 @@ export async function initSessionState(params: {
|
||||
persistedAuthProfileOverrideSource ?? baseEntry?.authProfileOverrideSource,
|
||||
authProfileOverrideCompactionCount:
|
||||
persistedAuthProfileOverrideCompactionCount ?? baseEntry?.authProfileOverrideCompactionCount,
|
||||
cliSessionIds: baseEntry?.cliSessionIds,
|
||||
cliSessionBindings: baseEntry?.cliSessionBindings,
|
||||
claudeCliSessionId: baseEntry?.claudeCliSessionId,
|
||||
label: persistedLabel ?? baseEntry?.label,
|
||||
spawnedBy: persistedSpawnedBy ?? baseEntry?.spawnedBy,
|
||||
spawnedWorkspaceDir: persistedSpawnedWorkspaceDir ?? baseEntry?.spawnedWorkspaceDir,
|
||||
|
||||
Reference in New Issue
Block a user