chore: migrate to oxlint and oxfmt
Co-authored-by: Christoph Nakazawa <christoph.pojer@gmail.com>
This commit is contained in:
@@ -3,8 +3,6 @@ export function isAbortError(err: unknown): boolean {
|
||||
const name = "name" in err ? String(err.name) : "";
|
||||
if (name === "AbortError") return true;
|
||||
const message =
|
||||
"message" in err && typeof err.message === "string"
|
||||
? err.message.toLowerCase()
|
||||
: "";
|
||||
"message" in err && typeof err.message === "string" ? err.message.toLowerCase() : "";
|
||||
return message.includes("aborted");
|
||||
}
|
||||
|
||||
@@ -1,21 +1,14 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
|
||||
import {
|
||||
createAgentSession,
|
||||
SessionManager,
|
||||
SettingsManager,
|
||||
} from "@mariozechner/pi-coding-agent";
|
||||
import { createAgentSession, SessionManager, SettingsManager } from "@mariozechner/pi-coding-agent";
|
||||
|
||||
import { resolveHeartbeatPrompt } from "../../auto-reply/heartbeat.js";
|
||||
import type { ReasoningLevel, ThinkLevel } from "../../auto-reply/thinking.js";
|
||||
import { resolveChannelCapabilities } from "../../config/channel-capabilities.js";
|
||||
import type { ClawdbotConfig } from "../../config/config.js";
|
||||
import { getMachineDisplayName } from "../../infra/machine-name.js";
|
||||
import {
|
||||
type enqueueCommand,
|
||||
enqueueCommandInLane,
|
||||
} from "../../process/command-queue.js";
|
||||
import { type enqueueCommand, enqueueCommandInLane } from "../../process/command-queue.js";
|
||||
import { normalizeMessageChannel } from "../../utils/message-channel.js";
|
||||
import { isReasoningTagProvider } from "../../utils/provider-utils.js";
|
||||
import { resolveUserPath } from "../../utils.js";
|
||||
@@ -48,28 +41,16 @@ import {
|
||||
resolveSkillsPromptForRun,
|
||||
type SkillSnapshot,
|
||||
} from "../skills.js";
|
||||
import {
|
||||
filterBootstrapFilesForSession,
|
||||
loadWorkspaceBootstrapFiles,
|
||||
} from "../workspace.js";
|
||||
import { filterBootstrapFilesForSession, loadWorkspaceBootstrapFiles } from "../workspace.js";
|
||||
import { buildEmbeddedExtensionPaths } from "./extensions.js";
|
||||
import { logToolSchemasForGoogle, sanitizeSessionHistory } from "./google.js";
|
||||
import {
|
||||
getDmHistoryLimitFromSessionKey,
|
||||
limitHistoryTurns,
|
||||
} from "./history.js";
|
||||
import { getDmHistoryLimitFromSessionKey, limitHistoryTurns } from "./history.js";
|
||||
import { resolveGlobalLane, resolveSessionLane } from "./lanes.js";
|
||||
import { log } from "./logger.js";
|
||||
import { buildModelAliasLines, resolveModel } from "./model.js";
|
||||
import { buildEmbeddedSandboxInfo } from "./sandbox-info.js";
|
||||
import {
|
||||
prewarmSessionFile,
|
||||
trackSessionManagerAccess,
|
||||
} from "./session-manager-cache.js";
|
||||
import {
|
||||
buildEmbeddedSystemPrompt,
|
||||
createSystemPromptOverride,
|
||||
} from "./system-prompt.js";
|
||||
import { prewarmSessionFile, trackSessionManagerAccess } from "./session-manager-cache.js";
|
||||
import { buildEmbeddedSystemPrompt, createSystemPromptOverride } from "./system-prompt.js";
|
||||
import { splitSdkTools } from "./tool-split.js";
|
||||
import type { EmbeddedPiCompactResult } from "./types.js";
|
||||
import {
|
||||
@@ -102,20 +83,16 @@ export async function compactEmbeddedPiSession(params: {
|
||||
extraSystemPrompt?: string;
|
||||
ownerNumbers?: string[];
|
||||
}): Promise<EmbeddedPiCompactResult> {
|
||||
const sessionLane = resolveSessionLane(
|
||||
params.sessionKey?.trim() || params.sessionId,
|
||||
);
|
||||
const sessionLane = resolveSessionLane(params.sessionKey?.trim() || params.sessionId);
|
||||
const globalLane = resolveGlobalLane(params.lane);
|
||||
const enqueueGlobal =
|
||||
params.enqueue ??
|
||||
((task, opts) => enqueueCommandInLane(globalLane, task, opts));
|
||||
params.enqueue ?? ((task, opts) => enqueueCommandInLane(globalLane, task, opts));
|
||||
return enqueueCommandInLane(sessionLane, () =>
|
||||
enqueueGlobal(async () => {
|
||||
const resolvedWorkspace = resolveUserPath(params.workspaceDir);
|
||||
const prevCwd = process.cwd();
|
||||
|
||||
const provider =
|
||||
(params.provider ?? DEFAULT_PROVIDER).trim() || DEFAULT_PROVIDER;
|
||||
const provider = (params.provider ?? DEFAULT_PROVIDER).trim() || DEFAULT_PROVIDER;
|
||||
const modelId = (params.model ?? DEFAULT_MODEL).trim() || DEFAULT_MODEL;
|
||||
const agentDir = params.agentDir ?? resolveClawdbotAgentDir();
|
||||
await ensureClawdbotModelsJson(params.config, agentDir);
|
||||
@@ -139,9 +116,8 @@ export async function compactEmbeddedPiSession(params: {
|
||||
});
|
||||
|
||||
if (model.provider === "github-copilot") {
|
||||
const { resolveCopilotApiToken } = await import(
|
||||
"../../providers/github-copilot-token.js"
|
||||
);
|
||||
const { resolveCopilotApiToken } =
|
||||
await import("../../providers/github-copilot-token.js");
|
||||
const copilotToken = await resolveCopilotApiToken({
|
||||
githubToken: apiKeyInfo.apiKey,
|
||||
});
|
||||
@@ -205,14 +181,10 @@ export async function compactEmbeddedPiSession(params: {
|
||||
params.sessionKey ?? params.sessionId,
|
||||
);
|
||||
const sessionLabel = params.sessionKey ?? params.sessionId;
|
||||
const contextFiles: EmbeddedContextFile[] = buildBootstrapContextFiles(
|
||||
bootstrapFiles,
|
||||
{
|
||||
maxChars: resolveBootstrapMaxChars(params.config),
|
||||
warn: (message) =>
|
||||
log.warn(`${message} (sessionKey=${sessionLabel})`),
|
||||
},
|
||||
);
|
||||
const contextFiles: EmbeddedContextFile[] = buildBootstrapContextFiles(bootstrapFiles, {
|
||||
maxChars: resolveBootstrapMaxChars(params.config),
|
||||
warn: (message) => log.warn(`${message} (sessionKey=${sessionLabel})`),
|
||||
});
|
||||
const runAbortController = new AbortController();
|
||||
const tools = createClawdbotCodingTools({
|
||||
exec: {
|
||||
@@ -252,14 +224,9 @@ export async function compactEmbeddedPiSession(params: {
|
||||
channel: runtimeChannel,
|
||||
capabilities: runtimeCapabilities,
|
||||
};
|
||||
const sandboxInfo = buildEmbeddedSandboxInfo(
|
||||
sandbox,
|
||||
params.bashElevated,
|
||||
);
|
||||
const sandboxInfo = buildEmbeddedSandboxInfo(sandbox, params.bashElevated);
|
||||
const reasoningTagHint = isReasoningTagProvider(provider);
|
||||
const userTimezone = resolveUserTimezone(
|
||||
params.config?.agents?.defaults?.userTimezone,
|
||||
);
|
||||
const userTimezone = resolveUserTimezone(params.config?.agents?.defaults?.userTimezone);
|
||||
const userTime = formatUserTime(new Date(), userTimezone);
|
||||
const { defaultAgentId, sessionAgentId } = resolveSessionAgentIds({
|
||||
sessionKey: params.sessionKey,
|
||||
@@ -274,9 +241,7 @@ export async function compactEmbeddedPiSession(params: {
|
||||
ownerNumbers: params.ownerNumbers,
|
||||
reasoningTagHint,
|
||||
heartbeatPrompt: isDefaultAgent
|
||||
? resolveHeartbeatPrompt(
|
||||
params.config?.agents?.defaults?.heartbeat?.prompt,
|
||||
)
|
||||
? resolveHeartbeatPrompt(params.config?.agents?.defaults?.heartbeat?.prompt)
|
||||
: undefined,
|
||||
skillsPrompt,
|
||||
runtimeInfo,
|
||||
@@ -294,19 +259,12 @@ export async function compactEmbeddedPiSession(params: {
|
||||
});
|
||||
try {
|
||||
await prewarmSessionFile(params.sessionFile);
|
||||
const sessionManager = guardSessionManager(
|
||||
SessionManager.open(params.sessionFile),
|
||||
);
|
||||
const sessionManager = guardSessionManager(SessionManager.open(params.sessionFile));
|
||||
trackSessionManagerAccess(params.sessionFile);
|
||||
const settingsManager = SettingsManager.create(
|
||||
effectiveWorkspace,
|
||||
agentDir,
|
||||
);
|
||||
const settingsManager = SettingsManager.create(effectiveWorkspace, agentDir);
|
||||
ensurePiCompactionReserveTokens({
|
||||
settingsManager,
|
||||
minReserveTokens: resolveCompactionReserveTokensFloor(
|
||||
params.config,
|
||||
),
|
||||
minReserveTokens: resolveCompactionReserveTokensFloor(params.config),
|
||||
});
|
||||
const additionalExtensionPaths = buildEmbeddedExtensionPaths({
|
||||
cfg: params.config,
|
||||
@@ -321,9 +279,7 @@ export async function compactEmbeddedPiSession(params: {
|
||||
sandboxEnabled: !!sandbox?.enabled,
|
||||
});
|
||||
|
||||
let session: Awaited<
|
||||
ReturnType<typeof createAgentSession>
|
||||
>["session"];
|
||||
let session: Awaited<ReturnType<typeof createAgentSession>>["session"];
|
||||
({ session } = await createAgentSession({
|
||||
cwd: resolvedWorkspace,
|
||||
agentDir,
|
||||
|
||||
@@ -60,9 +60,7 @@ function buildContextPruningExtension(params: {
|
||||
}
|
||||
|
||||
function resolveCompactionMode(cfg?: ClawdbotConfig): "default" | "safeguard" {
|
||||
return cfg?.agents?.defaults?.compaction?.mode === "safeguard"
|
||||
? "safeguard"
|
||||
: "default";
|
||||
return cfg?.agents?.defaults?.compaction?.mode === "safeguard" ? "safeguard" : "default";
|
||||
}
|
||||
|
||||
export function buildEmbeddedExtensionPaths(params: {
|
||||
|
||||
@@ -84,9 +84,7 @@ function createStreamFnWithExtraParams(
|
||||
return undefined;
|
||||
}
|
||||
|
||||
log.debug(
|
||||
`creating streamFn wrapper with params: ${JSON.stringify(streamParams)}`,
|
||||
);
|
||||
log.debug(`creating streamFn wrapper with params: ${JSON.stringify(streamParams)}`);
|
||||
|
||||
const underlying = baseStreamFn ?? streamSimple;
|
||||
const wrappedStreamFn: StreamFn = (model, context, options) =>
|
||||
@@ -116,15 +114,10 @@ export function applyExtraParamsToAgent(
|
||||
modelId,
|
||||
thinkLevel,
|
||||
});
|
||||
const wrappedStreamFn = createStreamFnWithExtraParams(
|
||||
agent.streamFn,
|
||||
extraParams,
|
||||
);
|
||||
const wrappedStreamFn = createStreamFnWithExtraParams(agent.streamFn, extraParams);
|
||||
|
||||
if (wrappedStreamFn) {
|
||||
log.debug(
|
||||
`applying extraParams to agent streamFn for ${provider}/${modelId}`,
|
||||
);
|
||||
log.debug(`applying extraParams to agent streamFn for ${provider}/${modelId}`);
|
||||
agent.streamFn = wrappedStreamFn;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,10 +37,7 @@ const GOOGLE_SCHEMA_UNSUPPORTED_KEYWORDS = new Set([
|
||||
"maxProperties",
|
||||
]);
|
||||
|
||||
function findUnsupportedSchemaKeywords(
|
||||
schema: unknown,
|
||||
path: string,
|
||||
): string[] {
|
||||
function findUnsupportedSchemaKeywords(schema: unknown, path: string): string[] {
|
||||
if (!schema || typeof schema !== "object") return [];
|
||||
if (Array.isArray(schema)) {
|
||||
return schema.flatMap((item, index) =>
|
||||
@@ -54,22 +51,14 @@ function findUnsupportedSchemaKeywords(
|
||||
violations.push(`${path}.${key}`);
|
||||
}
|
||||
if (value && typeof value === "object") {
|
||||
violations.push(
|
||||
...findUnsupportedSchemaKeywords(value, `${path}.${key}`),
|
||||
);
|
||||
violations.push(...findUnsupportedSchemaKeywords(value, `${path}.${key}`));
|
||||
}
|
||||
}
|
||||
return violations;
|
||||
}
|
||||
|
||||
export function logToolSchemasForGoogle(params: {
|
||||
tools: AgentTool[];
|
||||
provider: string;
|
||||
}) {
|
||||
if (
|
||||
params.provider !== "google-antigravity" &&
|
||||
params.provider !== "google-gemini-cli"
|
||||
) {
|
||||
export function logToolSchemasForGoogle(params: { tools: AgentTool[]; provider: string }) {
|
||||
if (params.provider !== "google-antigravity" && params.provider !== "google-gemini-cli") {
|
||||
return;
|
||||
}
|
||||
const toolNames = params.tools.map((tool, index) => `${index}:${tool.name}`);
|
||||
@@ -79,10 +68,7 @@ export function logToolSchemasForGoogle(params: {
|
||||
tools: toolNames,
|
||||
});
|
||||
for (const [index, tool] of params.tools.entries()) {
|
||||
const violations = findUnsupportedSchemaKeywords(
|
||||
tool.parameters,
|
||||
`${tool.name}.parameters`,
|
||||
);
|
||||
const violations = findUnsupportedSchemaKeywords(tool.parameters, `${tool.name}.parameters`);
|
||||
if (violations.length > 0) {
|
||||
log.warn("google tool schema has unsupported keywords", {
|
||||
index,
|
||||
@@ -110,8 +96,7 @@ function hasGoogleTurnOrderingMarker(sessionManager: SessionManager): boolean {
|
||||
.some(
|
||||
(entry) =>
|
||||
(entry as CustomEntryLike)?.type === "custom" &&
|
||||
(entry as CustomEntryLike)?.customType ===
|
||||
GOOGLE_TURN_ORDERING_CUSTOM_TYPE,
|
||||
(entry as CustomEntryLike)?.customType === GOOGLE_TURN_ORDERING_CUSTOM_TYPE,
|
||||
);
|
||||
} catch {
|
||||
return false;
|
||||
@@ -138,9 +123,7 @@ export function applyGoogleTurnOrderingFix(params: {
|
||||
if (!isGoogleModelApi(params.modelApi)) {
|
||||
return { messages: params.messages, didPrepend: false };
|
||||
}
|
||||
const first = params.messages[0] as
|
||||
| { role?: unknown; content?: unknown }
|
||||
| undefined;
|
||||
const first = params.messages[0] as { role?: unknown; content?: unknown } | undefined;
|
||||
if (first?.role !== "assistant") {
|
||||
return { messages: params.messages, didPrepend: false };
|
||||
}
|
||||
@@ -148,9 +131,7 @@ export function applyGoogleTurnOrderingFix(params: {
|
||||
const didPrepend = sanitized !== params.messages;
|
||||
if (didPrepend && !hasGoogleTurnOrderingMarker(params.sessionManager)) {
|
||||
const warn = params.warn ?? ((message: string) => log.warn(message));
|
||||
warn(
|
||||
`google turn ordering fixup: prepended user bootstrap (sessionId=${params.sessionId})`,
|
||||
);
|
||||
warn(`google turn ordering fixup: prepended user bootstrap (sessionId=${params.sessionId})`);
|
||||
markGoogleTurnOrderingMarker(params.sessionManager);
|
||||
}
|
||||
return { messages: sanitized, didPrepend };
|
||||
@@ -162,14 +143,10 @@ export async function sanitizeSessionHistory(params: {
|
||||
sessionManager: SessionManager;
|
||||
sessionId: string;
|
||||
}): Promise<AgentMessage[]> {
|
||||
const sanitizedImages = await sanitizeSessionMessagesImages(
|
||||
params.messages,
|
||||
"session:history",
|
||||
{
|
||||
sanitizeToolCallIds: isGoogleModelApi(params.modelApi),
|
||||
enforceToolCallLast: params.modelApi === "anthropic-messages",
|
||||
},
|
||||
);
|
||||
const sanitizedImages = await sanitizeSessionMessagesImages(params.messages, "session:history", {
|
||||
sanitizeToolCallIds: isGoogleModelApi(params.modelApi),
|
||||
enforceToolCallLast: params.modelApi === "anthropic-messages",
|
||||
});
|
||||
const repairedTools = sanitizeToolUseResultPairing(sanitizedImages);
|
||||
|
||||
const downgraded = isGoogleModelApi(params.modelApi)
|
||||
|
||||
@@ -38,8 +38,7 @@ export function getDmHistoryLimitFromSessionKey(
|
||||
if (!sessionKey || !config) return undefined;
|
||||
|
||||
const parts = sessionKey.split(":").filter(Boolean);
|
||||
const providerParts =
|
||||
parts.length >= 3 && parts[0] === "agent" ? parts.slice(2) : parts;
|
||||
const providerParts = parts.length >= 3 && parts[0] === "agent" ? parts.slice(2) : parts;
|
||||
|
||||
const provider = providerParts[0]?.toLowerCase();
|
||||
if (!provider) return undefined;
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import type { Api, Model } from "@mariozechner/pi-ai";
|
||||
import {
|
||||
discoverAuthStorage,
|
||||
discoverModels,
|
||||
} from "@mariozechner/pi-coding-agent";
|
||||
import { discoverAuthStorage, discoverModels } from "@mariozechner/pi-coding-agent";
|
||||
|
||||
import type { ClawdbotConfig } from "../../config/config.js";
|
||||
import { resolveClawdbotAgentDir } from "../agent-paths.js";
|
||||
@@ -15,9 +12,7 @@ export function buildModelAliasLines(cfg?: ClawdbotConfig) {
|
||||
for (const [keyRaw, entryRaw] of Object.entries(models)) {
|
||||
const model = String(keyRaw ?? "").trim();
|
||||
if (!model) continue;
|
||||
const alias = String(
|
||||
(entryRaw as { alias?: string } | undefined)?.alias ?? "",
|
||||
).trim();
|
||||
const alias = String((entryRaw as { alias?: string } | undefined)?.alias ?? "").trim();
|
||||
if (!alias) continue;
|
||||
entries.push({ alias, model });
|
||||
}
|
||||
@@ -67,10 +62,8 @@ export function resolveModel(
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow:
|
||||
providerCfg?.models?.[0]?.contextWindow ?? DEFAULT_CONTEXT_TOKENS,
|
||||
maxTokens:
|
||||
providerCfg?.models?.[0]?.maxTokens ?? DEFAULT_CONTEXT_TOKENS,
|
||||
contextWindow: providerCfg?.models?.[0]?.contextWindow ?? DEFAULT_CONTEXT_TOKENS,
|
||||
maxTokens: providerCfg?.models?.[0]?.maxTokens ?? DEFAULT_CONTEXT_TOKENS,
|
||||
} as Model<Api>);
|
||||
return { model: fallbackModel, authStorage, modelRegistry };
|
||||
}
|
||||
|
||||
@@ -14,11 +14,7 @@ import {
|
||||
evaluateContextWindowGuard,
|
||||
resolveContextWindowInfo,
|
||||
} from "../context-window-guard.js";
|
||||
import {
|
||||
DEFAULT_CONTEXT_TOKENS,
|
||||
DEFAULT_MODEL,
|
||||
DEFAULT_PROVIDER,
|
||||
} from "../defaults.js";
|
||||
import { DEFAULT_CONTEXT_TOKENS, DEFAULT_MODEL, DEFAULT_PROVIDER } from "../defaults.js";
|
||||
import { FailoverError, resolveFailoverStatus } from "../failover-error.js";
|
||||
import {
|
||||
ensureAuthProfileStore,
|
||||
@@ -58,13 +54,10 @@ type ApiKeyInfo = {
|
||||
export async function runEmbeddedPiAgent(
|
||||
params: RunEmbeddedPiAgentParams,
|
||||
): Promise<EmbeddedPiRunResult> {
|
||||
const sessionLane = resolveSessionLane(
|
||||
params.sessionKey?.trim() || params.sessionId,
|
||||
);
|
||||
const sessionLane = resolveSessionLane(params.sessionKey?.trim() || params.sessionId);
|
||||
const globalLane = resolveGlobalLane(params.lane);
|
||||
const enqueueGlobal =
|
||||
params.enqueue ??
|
||||
((task, opts) => enqueueCommandInLane(globalLane, task, opts));
|
||||
params.enqueue ?? ((task, opts) => enqueueCommandInLane(globalLane, task, opts));
|
||||
|
||||
return enqueueCommandInLane(sessionLane, () =>
|
||||
enqueueGlobal(async () => {
|
||||
@@ -72,8 +65,7 @@ export async function runEmbeddedPiAgent(
|
||||
const resolvedWorkspace = resolveUserPath(params.workspaceDir);
|
||||
const prevCwd = process.cwd();
|
||||
|
||||
const provider =
|
||||
(params.provider ?? DEFAULT_PROVIDER).trim() || DEFAULT_PROVIDER;
|
||||
const provider = (params.provider ?? DEFAULT_PROVIDER).trim() || DEFAULT_PROVIDER;
|
||||
const modelId = (params.model ?? DEFAULT_MODEL).trim() || DEFAULT_MODEL;
|
||||
const agentDir = params.agentDir ?? resolveClawdbotAgentDir();
|
||||
await ensureClawdbotModelsJson(params.config, agentDir);
|
||||
@@ -124,12 +116,9 @@ export async function runEmbeddedPiAgent(
|
||||
preferredProfile: explicitProfileId,
|
||||
});
|
||||
if (explicitProfileId && !profileOrder.includes(explicitProfileId)) {
|
||||
throw new Error(
|
||||
`Auth profile "${explicitProfileId}" is not configured for ${provider}.`,
|
||||
);
|
||||
throw new Error(`Auth profile "${explicitProfileId}" is not configured for ${provider}.`);
|
||||
}
|
||||
const profileCandidates =
|
||||
profileOrder.length > 0 ? profileOrder : [undefined];
|
||||
const profileCandidates = profileOrder.length > 0 ? profileOrder : [undefined];
|
||||
let profileIndex = 0;
|
||||
|
||||
const initialThinkLevel = params.thinkLevel ?? "off";
|
||||
@@ -150,9 +139,8 @@ export async function runEmbeddedPiAgent(
|
||||
const applyApiKeyInfo = async (candidate?: string): Promise<void> => {
|
||||
apiKeyInfo = await resolveApiKeyForCandidate(candidate);
|
||||
if (model.provider === "github-copilot") {
|
||||
const { resolveCopilotApiToken } = await import(
|
||||
"../../providers/github-copilot-token.js"
|
||||
);
|
||||
const { resolveCopilotApiToken } =
|
||||
await import("../../providers/github-copilot-token.js");
|
||||
const copilotToken = await resolveCopilotApiToken({
|
||||
githubToken: apiKeyInfo.apiKey,
|
||||
});
|
||||
@@ -238,13 +226,7 @@ export async function runEmbeddedPiAgent(
|
||||
enforceFinalTag: params.enforceFinalTag,
|
||||
});
|
||||
|
||||
const {
|
||||
aborted,
|
||||
promptError,
|
||||
timedOut,
|
||||
sessionIdUsed,
|
||||
lastAssistant,
|
||||
} = attempt;
|
||||
const { aborted, promptError, timedOut, sessionIdUsed, lastAssistant } = attempt;
|
||||
|
||||
if (promptError && !aborted) {
|
||||
const errorText = describeUnknownError(promptError);
|
||||
@@ -273,11 +255,7 @@ export async function runEmbeddedPiAgent(
|
||||
};
|
||||
}
|
||||
const promptFailoverReason = classifyFailoverReason(errorText);
|
||||
if (
|
||||
promptFailoverReason &&
|
||||
promptFailoverReason !== "timeout" &&
|
||||
lastProfileId
|
||||
) {
|
||||
if (promptFailoverReason && promptFailoverReason !== "timeout" && lastProfileId) {
|
||||
await markAuthProfileFailure({
|
||||
store: authStore,
|
||||
profileId: lastProfileId,
|
||||
@@ -320,14 +298,11 @@ export async function runEmbeddedPiAgent(
|
||||
}
|
||||
|
||||
const fallbackConfigured =
|
||||
(params.config?.agents?.defaults?.model?.fallbacks?.length ?? 0) >
|
||||
0;
|
||||
(params.config?.agents?.defaults?.model?.fallbacks?.length ?? 0) > 0;
|
||||
const authFailure = isAuthAssistantError(lastAssistant);
|
||||
const rateLimitFailure = isRateLimitAssistantError(lastAssistant);
|
||||
const failoverFailure = isFailoverAssistantError(lastAssistant);
|
||||
const assistantFailoverReason = classifyFailoverReason(
|
||||
lastAssistant?.errorMessage ?? "",
|
||||
);
|
||||
const assistantFailoverReason = classifyFailoverReason(lastAssistant?.errorMessage ?? "");
|
||||
const cloudCodeAssistFormatError = attempt.cloudCodeAssistFormatError;
|
||||
|
||||
// Treat timeout as potential rate limit (Antigravity hangs on rate limit)
|
||||
@@ -406,8 +381,7 @@ export async function runEmbeddedPiAgent(
|
||||
sessionKey: params.sessionKey ?? params.sessionId,
|
||||
verboseLevel: params.verboseLevel,
|
||||
reasoningLevel: params.reasoningLevel,
|
||||
inlineToolResultsAllowed:
|
||||
!params.onPartialReply && !params.onToolResult,
|
||||
inlineToolResultsAllowed: !params.onPartialReply && !params.onToolResult,
|
||||
});
|
||||
|
||||
log.debug(
|
||||
|
||||
@@ -4,11 +4,7 @@ import os from "node:os";
|
||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import type { AssistantMessage } from "@mariozechner/pi-ai";
|
||||
import { streamSimple } from "@mariozechner/pi-ai";
|
||||
import {
|
||||
createAgentSession,
|
||||
SessionManager,
|
||||
SettingsManager,
|
||||
} from "@mariozechner/pi-coding-agent";
|
||||
import { createAgentSession, SessionManager, SettingsManager } from "@mariozechner/pi-coding-agent";
|
||||
|
||||
import { resolveHeartbeatPrompt } from "../../../auto-reply/heartbeat.js";
|
||||
import { resolveChannelCapabilities } from "../../../config/channel-capabilities.js";
|
||||
@@ -41,19 +37,13 @@ import {
|
||||
loadWorkspaceSkillEntries,
|
||||
resolveSkillsPromptForRun,
|
||||
} from "../../skills.js";
|
||||
import {
|
||||
filterBootstrapFilesForSession,
|
||||
loadWorkspaceBootstrapFiles,
|
||||
} from "../../workspace.js";
|
||||
import { filterBootstrapFilesForSession, loadWorkspaceBootstrapFiles } from "../../workspace.js";
|
||||
|
||||
import { isAbortError } from "../abort.js";
|
||||
import { buildEmbeddedExtensionPaths } from "../extensions.js";
|
||||
import { applyExtraParamsToAgent } from "../extra-params.js";
|
||||
import { logToolSchemasForGoogle, sanitizeSessionHistory } from "../google.js";
|
||||
import {
|
||||
getDmHistoryLimitFromSessionKey,
|
||||
limitHistoryTurns,
|
||||
} from "../history.js";
|
||||
import { getDmHistoryLimitFromSessionKey, limitHistoryTurns } from "../history.js";
|
||||
import { log } from "../logger.js";
|
||||
import { buildModelAliasLines } from "../model.js";
|
||||
import {
|
||||
@@ -62,15 +52,9 @@ import {
|
||||
setActiveEmbeddedRun,
|
||||
} from "../runs.js";
|
||||
import { buildEmbeddedSandboxInfo } from "../sandbox-info.js";
|
||||
import {
|
||||
prewarmSessionFile,
|
||||
trackSessionManagerAccess,
|
||||
} from "../session-manager-cache.js";
|
||||
import { prewarmSessionFile, trackSessionManagerAccess } from "../session-manager-cache.js";
|
||||
import { prepareSessionManagerForRun } from "../session-manager-init.js";
|
||||
import {
|
||||
buildEmbeddedSystemPrompt,
|
||||
createSystemPromptOverride,
|
||||
} from "../system-prompt.js";
|
||||
import { buildEmbeddedSystemPrompt, createSystemPromptOverride } from "../system-prompt.js";
|
||||
import { splitSdkTools } from "../tool-split.js";
|
||||
import {
|
||||
formatUserTime,
|
||||
@@ -79,10 +63,7 @@ import {
|
||||
resolveUserTimezone,
|
||||
} from "../utils.js";
|
||||
|
||||
import type {
|
||||
EmbeddedRunAttemptParams,
|
||||
EmbeddedRunAttemptResult,
|
||||
} from "./types.js";
|
||||
import type { EmbeddedRunAttemptParams, EmbeddedRunAttemptResult } from "./types.js";
|
||||
|
||||
export async function runEmbeddedAttempt(
|
||||
params: EmbeddedRunAttemptParams,
|
||||
@@ -113,8 +94,7 @@ export async function runEmbeddedAttempt(
|
||||
let restoreSkillEnv: (() => void) | undefined;
|
||||
process.chdir(effectiveWorkspace);
|
||||
try {
|
||||
const shouldLoadSkillEntries =
|
||||
!params.skillsSnapshot || !params.skillsSnapshot.resolvedSkills;
|
||||
const shouldLoadSkillEntries = !params.skillsSnapshot || !params.skillsSnapshot.resolvedSkills;
|
||||
const skillEntries = shouldLoadSkillEntries
|
||||
? loadWorkspaceSkillEntries(effectiveWorkspace)
|
||||
: [];
|
||||
@@ -171,9 +151,7 @@ export async function runEmbeddedAttempt(
|
||||
logToolSchemasForGoogle({ tools, provider: params.provider });
|
||||
|
||||
const machineName = await getMachineDisplayName();
|
||||
const runtimeChannel = normalizeMessageChannel(
|
||||
params.messageChannel ?? params.messageProvider,
|
||||
);
|
||||
const runtimeChannel = normalizeMessageChannel(params.messageChannel ?? params.messageProvider);
|
||||
const runtimeCapabilities = runtimeChannel
|
||||
? (resolveChannelCapabilities({
|
||||
cfg: params.config,
|
||||
@@ -193,9 +171,7 @@ export async function runEmbeddedAttempt(
|
||||
|
||||
const sandboxInfo = buildEmbeddedSandboxInfo(sandbox, params.bashElevated);
|
||||
const reasoningTagHint = isReasoningTagProvider(params.provider);
|
||||
const userTimezone = resolveUserTimezone(
|
||||
params.config?.agents?.defaults?.userTimezone,
|
||||
);
|
||||
const userTimezone = resolveUserTimezone(params.config?.agents?.defaults?.userTimezone);
|
||||
const userTime = formatUserTime(new Date(), userTimezone);
|
||||
const { defaultAgentId, sessionAgentId } = resolveSessionAgentIds({
|
||||
sessionKey: params.sessionKey,
|
||||
@@ -211,9 +187,7 @@ export async function runEmbeddedAttempt(
|
||||
ownerNumbers: params.ownerNumbers,
|
||||
reasoningTagHint,
|
||||
heartbeatPrompt: isDefaultAgent
|
||||
? resolveHeartbeatPrompt(
|
||||
params.config?.agents?.defaults?.heartbeat?.prompt,
|
||||
)
|
||||
? resolveHeartbeatPrompt(params.config?.agents?.defaults?.heartbeat?.prompt)
|
||||
: undefined,
|
||||
skillsPrompt,
|
||||
runtimeInfo,
|
||||
@@ -231,9 +205,7 @@ export async function runEmbeddedAttempt(
|
||||
});
|
||||
|
||||
let sessionManager: ReturnType<typeof guardSessionManager> | undefined;
|
||||
let session:
|
||||
| Awaited<ReturnType<typeof createAgentSession>>["session"]
|
||||
| undefined;
|
||||
let session: Awaited<ReturnType<typeof createAgentSession>>["session"] | undefined;
|
||||
try {
|
||||
const hadSessionFile = await fs
|
||||
.stat(params.sessionFile)
|
||||
@@ -241,9 +213,7 @@ export async function runEmbeddedAttempt(
|
||||
.catch(() => false);
|
||||
|
||||
await prewarmSessionFile(params.sessionFile);
|
||||
sessionManager = guardSessionManager(
|
||||
SessionManager.open(params.sessionFile),
|
||||
);
|
||||
sessionManager = guardSessionManager(SessionManager.open(params.sessionFile));
|
||||
trackSessionManagerAccess(params.sessionFile);
|
||||
|
||||
await prepareSessionManagerForRun({
|
||||
@@ -254,10 +224,7 @@ export async function runEmbeddedAttempt(
|
||||
cwd: effectiveWorkspace,
|
||||
});
|
||||
|
||||
const settingsManager = SettingsManager.create(
|
||||
effectiveWorkspace,
|
||||
agentDir,
|
||||
);
|
||||
const settingsManager = SettingsManager.create(effectiveWorkspace, agentDir);
|
||||
ensurePiCompactionReserveTokens({
|
||||
settingsManager,
|
||||
minReserveTokens: resolveCompactionReserveTokensFloor(params.config),
|
||||
@@ -412,9 +379,7 @@ export async function runEmbeddedAttempt(
|
||||
let promptError: unknown = null;
|
||||
try {
|
||||
const promptStartedAt = Date.now();
|
||||
log.debug(
|
||||
`embedded run prompt start: runId=${params.runId} sessionId=${params.sessionId}`,
|
||||
);
|
||||
log.debug(`embedded run prompt start: runId=${params.runId} sessionId=${params.sessionId}`);
|
||||
try {
|
||||
await activeSession.prompt(params.prompt, { images: params.images });
|
||||
} catch (err) {
|
||||
@@ -448,15 +413,12 @@ export async function runEmbeddedAttempt(
|
||||
const lastAssistant = messagesSnapshot
|
||||
.slice()
|
||||
.reverse()
|
||||
.find((m) => (m as AgentMessage)?.role === "assistant") as
|
||||
| AssistantMessage
|
||||
| undefined;
|
||||
.find((m) => (m as AgentMessage)?.role === "assistant") as AssistantMessage | undefined;
|
||||
|
||||
const toolMetasNormalized = toolMetas
|
||||
.filter(
|
||||
(entry): entry is { toolName: string; meta?: string } =>
|
||||
typeof entry.toolName === "string" &&
|
||||
entry.toolName.trim().length > 0,
|
||||
typeof entry.toolName === "string" && entry.toolName.trim().length > 0,
|
||||
)
|
||||
.map((entry) => ({ toolName: entry.toolName, meta: entry.meta }));
|
||||
|
||||
@@ -473,8 +435,7 @@ export async function runEmbeddedAttempt(
|
||||
messagingToolSentTexts: getMessagingToolSentTexts(),
|
||||
messagingToolSentTargets: getMessagingToolSentTargets(),
|
||||
cloudCodeAssistFormatError: Boolean(
|
||||
lastAssistant?.errorMessage &&
|
||||
isCloudCodeAssistFormatError(lastAssistant.errorMessage),
|
||||
lastAssistant?.errorMessage && isCloudCodeAssistFormatError(lastAssistant.errorMessage),
|
||||
),
|
||||
};
|
||||
} finally {
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import type { ImageContent } from "@mariozechner/pi-ai";
|
||||
import type {
|
||||
ReasoningLevel,
|
||||
ThinkLevel,
|
||||
VerboseLevel,
|
||||
} from "../../../auto-reply/thinking.js";
|
||||
import type { ReasoningLevel, ThinkLevel, VerboseLevel } from "../../../auto-reply/thinking.js";
|
||||
import type { ClawdbotConfig } from "../../../config/config.js";
|
||||
import type { enqueueCommand } from "../../../process/command-queue.js";
|
||||
import type { ExecElevatedDefaults } from "../../bash-tools.js";
|
||||
@@ -42,10 +38,7 @@ export type RunEmbeddedPiAgentParams = {
|
||||
runId: string;
|
||||
abortSignal?: AbortSignal;
|
||||
shouldEmitToolResult?: () => boolean;
|
||||
onPartialReply?: (payload: {
|
||||
text?: string;
|
||||
mediaUrls?: string[];
|
||||
}) => void | Promise<void>;
|
||||
onPartialReply?: (payload: { text?: string; mediaUrls?: string[] }) => void | Promise<void>;
|
||||
onAssistantMessageStart?: () => void | Promise<void>;
|
||||
onBlockReply?: (payload: {
|
||||
text?: string;
|
||||
@@ -55,18 +48,9 @@ export type RunEmbeddedPiAgentParams = {
|
||||
onBlockReplyFlush?: () => void | Promise<void>;
|
||||
blockReplyBreak?: "text_end" | "message_end";
|
||||
blockReplyChunking?: BlockReplyChunking;
|
||||
onReasoningStream?: (payload: {
|
||||
text?: string;
|
||||
mediaUrls?: string[];
|
||||
}) => void | Promise<void>;
|
||||
onToolResult?: (payload: {
|
||||
text?: string;
|
||||
mediaUrls?: string[];
|
||||
}) => void | Promise<void>;
|
||||
onAgentEvent?: (evt: {
|
||||
stream: string;
|
||||
data: Record<string, unknown>;
|
||||
}) => void;
|
||||
onReasoningStream?: (payload: { text?: string; mediaUrls?: string[] }) => void | Promise<void>;
|
||||
onToolResult?: (payload: { text?: string; mediaUrls?: string[] }) => void | Promise<void>;
|
||||
onAgentEvent?: (evt: { stream: string; data: Record<string, unknown> }) => void;
|
||||
lane?: string;
|
||||
enqueue?: typeof enqueueCommand;
|
||||
extraSystemPrompt?: string;
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import type { AssistantMessage } from "@mariozechner/pi-ai";
|
||||
import { parseReplyDirectives } from "../../../auto-reply/reply/reply-directives.js";
|
||||
import type {
|
||||
ReasoningLevel,
|
||||
VerboseLevel,
|
||||
} from "../../../auto-reply/thinking.js";
|
||||
import {
|
||||
isSilentReplyText,
|
||||
SILENT_REPLY_TOKEN,
|
||||
} from "../../../auto-reply/tokens.js";
|
||||
import type { ReasoningLevel, VerboseLevel } from "../../../auto-reply/thinking.js";
|
||||
import { isSilentReplyText, SILENT_REPLY_TOKEN } from "../../../auto-reply/tokens.js";
|
||||
import { formatToolAggregate } from "../../../auto-reply/tool-meta.js";
|
||||
import type { ClawdbotConfig } from "../../../config/config.js";
|
||||
import { formatAssistantErrorText } from "../../pi-embedded-helpers.js";
|
||||
@@ -57,9 +51,7 @@ export function buildEmbeddedRunPayloads(params: {
|
||||
if (errorText) replyItems.push({ text: errorText, isError: true });
|
||||
|
||||
const inlineToolResults =
|
||||
params.inlineToolResultsAllowed &&
|
||||
params.verboseLevel === "on" &&
|
||||
params.toolMetas.length > 0;
|
||||
params.inlineToolResultsAllowed && params.verboseLevel === "on" && params.toolMetas.length > 0;
|
||||
if (inlineToolResults) {
|
||||
for (const { toolName, meta } of params.toolMetas) {
|
||||
const agg = formatToolAggregate(toolName, meta ? [meta] : []);
|
||||
@@ -90,9 +82,7 @@ export function buildEmbeddedRunPayloads(params: {
|
||||
: "";
|
||||
if (reasoningText) replyItems.push({ text: reasoningText });
|
||||
|
||||
const fallbackAnswerText = params.lastAssistant
|
||||
? extractAssistantText(params.lastAssistant)
|
||||
: "";
|
||||
const fallbackAnswerText = params.lastAssistant ? extractAssistantText(params.lastAssistant) : "";
|
||||
const answerTexts = params.assistantTexts.length
|
||||
? params.assistantTexts
|
||||
: fallbackAnswerText
|
||||
@@ -108,11 +98,7 @@ export function buildEmbeddedRunPayloads(params: {
|
||||
replyToTag,
|
||||
replyToCurrent,
|
||||
} = parseReplyDirectives(text);
|
||||
if (
|
||||
!cleanedText &&
|
||||
(!mediaUrls || mediaUrls.length === 0) &&
|
||||
!audioAsVoice
|
||||
) {
|
||||
if (!cleanedText && (!mediaUrls || mediaUrls.length === 0) && !audioAsVoice) {
|
||||
continue;
|
||||
}
|
||||
replyItems.push({
|
||||
@@ -135,12 +121,10 @@ export function buildEmbeddedRunPayloads(params: {
|
||||
replyToId: item.replyToId,
|
||||
replyToTag: item.replyToTag,
|
||||
replyToCurrent: item.replyToCurrent,
|
||||
audioAsVoice:
|
||||
item.audioAsVoice || Boolean(hasAudioAsVoiceTag && item.media?.length),
|
||||
audioAsVoice: item.audioAsVoice || Boolean(hasAudioAsVoiceTag && item.media?.length),
|
||||
}))
|
||||
.filter((p) => {
|
||||
if (!p.text && !p.mediaUrl && (!p.mediaUrls || p.mediaUrls.length === 0))
|
||||
return false;
|
||||
if (!p.text && !p.mediaUrl && (!p.mediaUrls || p.mediaUrls.length === 0)) return false;
|
||||
if (p.text && isSilentReplyText(p.text, SILENT_REPLY_TOKEN)) return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -1,20 +1,8 @@
|
||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import type {
|
||||
Api,
|
||||
AssistantMessage,
|
||||
ImageContent,
|
||||
Model,
|
||||
} from "@mariozechner/pi-ai";
|
||||
import type {
|
||||
discoverAuthStorage,
|
||||
discoverModels,
|
||||
} from "@mariozechner/pi-coding-agent";
|
||||
import type { Api, AssistantMessage, ImageContent, Model } from "@mariozechner/pi-ai";
|
||||
import type { discoverAuthStorage, discoverModels } from "@mariozechner/pi-coding-agent";
|
||||
|
||||
import type {
|
||||
ReasoningLevel,
|
||||
ThinkLevel,
|
||||
VerboseLevel,
|
||||
} from "../../../auto-reply/thinking.js";
|
||||
import type { ReasoningLevel, ThinkLevel, VerboseLevel } from "../../../auto-reply/thinking.js";
|
||||
import type { ClawdbotConfig } from "../../../config/config.js";
|
||||
import type { ExecElevatedDefaults } from "../../bash-tools.js";
|
||||
import type { MessagingToolSend } from "../../pi-embedded-messaging.js";
|
||||
@@ -54,10 +42,7 @@ export type EmbeddedRunAttemptParams = {
|
||||
runId: string;
|
||||
abortSignal?: AbortSignal;
|
||||
shouldEmitToolResult?: () => boolean;
|
||||
onPartialReply?: (payload: {
|
||||
text?: string;
|
||||
mediaUrls?: string[];
|
||||
}) => void | Promise<void>;
|
||||
onPartialReply?: (payload: { text?: string; mediaUrls?: string[] }) => void | Promise<void>;
|
||||
onAssistantMessageStart?: () => void | Promise<void>;
|
||||
onBlockReply?: (payload: {
|
||||
text?: string;
|
||||
@@ -67,18 +52,9 @@ export type EmbeddedRunAttemptParams = {
|
||||
onBlockReplyFlush?: () => void | Promise<void>;
|
||||
blockReplyBreak?: "text_end" | "message_end";
|
||||
blockReplyChunking?: BlockReplyChunking;
|
||||
onReasoningStream?: (payload: {
|
||||
text?: string;
|
||||
mediaUrls?: string[];
|
||||
}) => void | Promise<void>;
|
||||
onToolResult?: (payload: {
|
||||
text?: string;
|
||||
mediaUrls?: string[];
|
||||
}) => void | Promise<void>;
|
||||
onAgentEvent?: (evt: {
|
||||
stream: string;
|
||||
data: Record<string, unknown>;
|
||||
}) => void;
|
||||
onReasoningStream?: (payload: { text?: string; mediaUrls?: string[] }) => void | Promise<void>;
|
||||
onToolResult?: (payload: { text?: string; mediaUrls?: string[] }) => void | Promise<void>;
|
||||
onAgentEvent?: (evt: { stream: string; data: Record<string, unknown> }) => void;
|
||||
extraSystemPrompt?: string;
|
||||
ownerNumbers?: string[];
|
||||
enforceFinalTag?: boolean;
|
||||
|
||||
@@ -12,10 +12,7 @@ type EmbeddedRunWaiter = {
|
||||
};
|
||||
const EMBEDDED_RUN_WAITERS = new Map<string, Set<EmbeddedRunWaiter>>();
|
||||
|
||||
export function queueEmbeddedPiMessage(
|
||||
sessionId: string,
|
||||
text: string,
|
||||
): boolean {
|
||||
export function queueEmbeddedPiMessage(sessionId: string, text: string): boolean {
|
||||
const handle = ACTIVE_EMBEDDED_RUNS.get(sessionId);
|
||||
if (!handle) return false;
|
||||
if (!handle.isStreaming()) return false;
|
||||
@@ -41,12 +38,8 @@ export function isEmbeddedPiRunStreaming(sessionId: string): boolean {
|
||||
return handle.isStreaming();
|
||||
}
|
||||
|
||||
export function waitForEmbeddedPiRunEnd(
|
||||
sessionId: string,
|
||||
timeoutMs = 15_000,
|
||||
): Promise<boolean> {
|
||||
if (!sessionId || !ACTIVE_EMBEDDED_RUNS.has(sessionId))
|
||||
return Promise.resolve(true);
|
||||
export function waitForEmbeddedPiRunEnd(sessionId: string, timeoutMs = 15_000): Promise<boolean> {
|
||||
if (!sessionId || !ACTIVE_EMBEDDED_RUNS.has(sessionId)) return Promise.resolve(true);
|
||||
return new Promise((resolve) => {
|
||||
const waiters = EMBEDDED_RUN_WAITERS.get(sessionId) ?? new Set();
|
||||
const waiter: EmbeddedRunWaiter = {
|
||||
@@ -81,17 +74,11 @@ function notifyEmbeddedRunEnded(sessionId: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export function setActiveEmbeddedRun(
|
||||
sessionId: string,
|
||||
handle: EmbeddedPiQueueHandle,
|
||||
) {
|
||||
export function setActiveEmbeddedRun(sessionId: string, handle: EmbeddedPiQueueHandle) {
|
||||
ACTIVE_EMBEDDED_RUNS.set(sessionId, handle);
|
||||
}
|
||||
|
||||
export function clearActiveEmbeddedRun(
|
||||
sessionId: string,
|
||||
handle: EmbeddedPiQueueHandle,
|
||||
) {
|
||||
export function clearActiveEmbeddedRun(sessionId: string, handle: EmbeddedPiQueueHandle) {
|
||||
if (ACTIVE_EMBEDDED_RUNS.get(sessionId) === handle) {
|
||||
ACTIVE_EMBEDDED_RUNS.delete(sessionId);
|
||||
notifyEmbeddedRunEnded(sessionId);
|
||||
|
||||
@@ -7,15 +7,12 @@ export function buildEmbeddedSandboxInfo(
|
||||
execElevated?: ExecElevatedDefaults,
|
||||
): EmbeddedSandboxInfo | undefined {
|
||||
if (!sandbox?.enabled) return undefined;
|
||||
const elevatedAllowed = Boolean(
|
||||
execElevated?.enabled && execElevated.allowed,
|
||||
);
|
||||
const elevatedAllowed = Boolean(execElevated?.enabled && execElevated.allowed);
|
||||
return {
|
||||
enabled: true,
|
||||
workspaceDir: sandbox.workspaceDir,
|
||||
workspaceAccess: sandbox.workspaceAccess,
|
||||
agentWorkspaceMount:
|
||||
sandbox.workspaceAccess === "ro" ? "/agent" : undefined,
|
||||
agentWorkspaceMount: sandbox.workspaceAccess === "ro" ? "/agent" : undefined,
|
||||
browserControlUrl: sandbox.browser?.controlUrl,
|
||||
browserNoVncUrl: sandbox.browser?.noVncUrl,
|
||||
hostBrowserAllowed: sandbox.browserAllowHostControl,
|
||||
|
||||
@@ -23,21 +23,15 @@ export async function prepareSessionManagerForRun(params: {
|
||||
const sm = params.sessionManager as {
|
||||
sessionId: string;
|
||||
flushed: boolean;
|
||||
fileEntries: Array<
|
||||
SessionHeaderEntry | SessionMessageEntry | { type: string }
|
||||
>;
|
||||
fileEntries: Array<SessionHeaderEntry | SessionMessageEntry | { type: string }>;
|
||||
byId?: Map<string, unknown>;
|
||||
labelsById?: Map<string, unknown>;
|
||||
leafId?: string | null;
|
||||
};
|
||||
|
||||
const header = sm.fileEntries.find(
|
||||
(e): e is SessionHeaderEntry => e.type === "session",
|
||||
);
|
||||
const header = sm.fileEntries.find((e): e is SessionHeaderEntry => e.type === "session");
|
||||
const hasAssistant = sm.fileEntries.some(
|
||||
(e) =>
|
||||
e.type === "message" &&
|
||||
(e as SessionMessageEntry).message?.role === "assistant",
|
||||
(e) => e.type === "message" && (e as SessionMessageEntry).message?.role === "assistant",
|
||||
);
|
||||
|
||||
if (!params.hadSessionFile && header) {
|
||||
|
||||
@@ -6,10 +6,7 @@ import { toToolDefinitions } from "../pi-tool-definition-adapter.js";
|
||||
// and extended toolset remain consistent across providers.
|
||||
type AnyAgentTool = AgentTool;
|
||||
|
||||
export function splitSdkTools(options: {
|
||||
tools: AnyAgentTool[];
|
||||
sandboxEnabled: boolean;
|
||||
}): {
|
||||
export function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }): {
|
||||
builtInTools: AnyAgentTool[];
|
||||
customTools: ReturnType<typeof toToolDefinitions>;
|
||||
} {
|
||||
|
||||
@@ -9,9 +9,7 @@ export function mapThinkingLevel(level?: ThinkLevel): ThinkingLevel {
|
||||
return level;
|
||||
}
|
||||
|
||||
export function resolveExecToolDefaults(
|
||||
config?: ClawdbotConfig,
|
||||
): ExecToolDefaults | undefined {
|
||||
export function resolveExecToolDefaults(config?: ClawdbotConfig): ExecToolDefaults | undefined {
|
||||
const tools = config?.tools;
|
||||
if (!tools) return undefined;
|
||||
if (!tools.exec) return tools.bash;
|
||||
@@ -23,9 +21,7 @@ export function resolveUserTimezone(configured?: string): string {
|
||||
const trimmed = configured?.trim();
|
||||
if (trimmed) {
|
||||
try {
|
||||
new Intl.DateTimeFormat("en-US", { timeZone: trimmed }).format(
|
||||
new Date(),
|
||||
);
|
||||
new Intl.DateTimeFormat("en-US", { timeZone: trimmed }).format(new Date());
|
||||
return trimmed;
|
||||
} catch {
|
||||
// ignore invalid timezone
|
||||
@@ -35,10 +31,7 @@ export function resolveUserTimezone(configured?: string): string {
|
||||
return host?.trim() || "UTC";
|
||||
}
|
||||
|
||||
export function formatUserTime(
|
||||
date: Date,
|
||||
timeZone: string,
|
||||
): string | undefined {
|
||||
export function formatUserTime(date: Date, timeZone: string): string | undefined {
|
||||
try {
|
||||
const parts = new Intl.DateTimeFormat("en-CA", {
|
||||
timeZone,
|
||||
@@ -54,14 +47,7 @@ export function formatUserTime(
|
||||
for (const part of parts) {
|
||||
if (part.type !== "literal") map[part.type] = part.value;
|
||||
}
|
||||
if (
|
||||
!map.weekday ||
|
||||
!map.year ||
|
||||
!map.month ||
|
||||
!map.day ||
|
||||
!map.hour ||
|
||||
!map.minute
|
||||
) {
|
||||
if (!map.weekday || !map.year || !map.month || !map.day || !map.hour || !map.minute) {
|
||||
return undefined;
|
||||
}
|
||||
return `${map.weekday} ${map.year}-${map.month}-${map.day} ${map.hour}:${map.minute}`;
|
||||
|
||||
Reference in New Issue
Block a user