@poolzin/pool-bot 2026.2.0 → 2026.2.1
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/agents/bash-tools.exec.js +76 -25
- package/dist/agents/cli-runner/helpers.js +9 -11
- package/dist/agents/identity.js +47 -7
- package/dist/agents/memory-search.js +25 -8
- package/dist/agents/model-selection.js +21 -0
- package/dist/agents/pi-embedded-block-chunker.js +117 -42
- package/dist/agents/pi-embedded-helpers/errors.js +183 -78
- package/dist/agents/pi-embedded-helpers.js +1 -1
- package/dist/agents/pi-embedded-runner/compact.js +1 -0
- package/dist/agents/pi-embedded-runner/model.js +61 -2
- package/dist/agents/pi-embedded-runner/run/attempt.js +21 -11
- package/dist/agents/pi-embedded-runner/run.js +199 -46
- package/dist/agents/pi-embedded-runner/system-prompt.js +10 -2
- package/dist/agents/pi-embedded-subscribe.js +118 -29
- package/dist/agents/pi-tools.js +10 -5
- package/dist/agents/poolbot-tools.js +15 -10
- package/dist/agents/sandbox-paths.js +31 -0
- package/dist/agents/session-tool-result-guard.js +94 -15
- package/dist/agents/shell-utils.js +51 -0
- package/dist/agents/skills/bundled-context.js +23 -0
- package/dist/agents/skills/bundled-dir.js +41 -7
- package/dist/agents/skills-install.js +60 -23
- package/dist/agents/subagent-announce.js +79 -34
- package/dist/agents/tool-policy.conformance.js +14 -0
- package/dist/agents/tool-policy.js +24 -0
- package/dist/agents/tools/cron-tool.js +166 -19
- package/dist/agents/tools/discord-actions-presence.js +78 -0
- package/dist/agents/tools/message-tool.js +56 -2
- package/dist/agents/tools/sessions-history-tool.js +69 -1
- package/dist/agents/tools/web-search.js +211 -42
- package/dist/agents/usage.js +23 -1
- package/dist/agents/workspace-run.js +67 -0
- package/dist/agents/workspace-templates.js +44 -0
- package/dist/auto-reply/command-auth.js +121 -6
- package/dist/auto-reply/envelope.js +50 -72
- package/dist/auto-reply/reply/commands-compact.js +1 -0
- package/dist/auto-reply/reply/commands-context-report.js +1 -0
- package/dist/auto-reply/reply/commands-context.js +1 -0
- package/dist/auto-reply/reply/commands-models.js +107 -60
- package/dist/auto-reply/reply/commands-ptt.js +171 -0
- package/dist/auto-reply/reply/get-reply-run.js +2 -1
- package/dist/auto-reply/reply/inbound-context.js +5 -1
- package/dist/auto-reply/reply/model-selection.js +3 -3
- package/dist/auto-reply/thinking.js +88 -43
- package/dist/browser/bridge-server.js +13 -0
- package/dist/browser/cdp.helpers.js +38 -24
- package/dist/browser/client-fetch.js +50 -7
- package/dist/browser/config.js +1 -10
- package/dist/browser/extension-relay.js +101 -40
- package/dist/browser/pw-ai.js +1 -1
- package/dist/browser/pw-session.js +143 -8
- package/dist/browser/pw-tools-core.interactions.js +125 -27
- package/dist/browser/pw-tools-core.responses.js +1 -1
- package/dist/browser/pw-tools-core.state.js +1 -1
- package/dist/browser/routes/agent.act.js +86 -41
- package/dist/browser/routes/dispatcher.js +4 -4
- package/dist/browser/screenshot.js +1 -1
- package/dist/browser/server.js +13 -0
- package/dist/build-info.json +3 -3
- package/dist/channels/reply-prefix.js +8 -1
- package/dist/cli/cron-cli/register.cron-add.js +61 -40
- package/dist/cli/cron-cli/register.cron-edit.js +60 -34
- package/dist/cli/cron-cli/shared.js +56 -41
- package/dist/cli/dns-cli.js +26 -14
- package/dist/cli/gateway-cli/register.js +37 -19
- package/dist/cli/memory-cli.js +5 -5
- package/dist/cli/parse-bytes.js +37 -0
- package/dist/cli/update-cli.js +173 -52
- package/dist/commands/agent.js +1 -0
- package/dist/commands/doctor-config-flow.js +61 -5
- package/dist/commands/doctor-state-migrations.js +1 -1
- package/dist/commands/health.js +1 -1
- package/dist/commands/model-allowlist.js +29 -0
- package/dist/commands/model-picker.js +2 -1
- package/dist/commands/models/list.status-command.js +43 -23
- package/dist/commands/models/shared.js +15 -0
- package/dist/commands/onboard-custom.js +384 -0
- package/dist/commands/onboard-non-interactive/local/auth-choice-inference.js +35 -0
- package/dist/commands/onboard-non-interactive/local/auth-choice.js +6 -3
- package/dist/commands/onboard-skills.js +63 -38
- package/dist/commands/openai-model-default.js +41 -0
- package/dist/config/defaults.js +3 -2
- package/dist/config/paths.js +136 -35
- package/dist/config/plugin-auto-enable.js +21 -5
- package/dist/config/redact-snapshot.js +153 -0
- package/dist/config/schema.field-metadata.js +590 -0
- package/dist/config/schema.js +2 -2
- package/dist/config/sessions/store.js +291 -23
- package/dist/config/zod-schema.agent-defaults.js +3 -0
- package/dist/config/zod-schema.agent-runtime.js +13 -2
- package/dist/config/zod-schema.providers-core.js +142 -0
- package/dist/config/zod-schema.session.js +3 -0
- package/dist/cron/delivery.js +57 -0
- package/dist/cron/isolated-agent/delivery-target.js +18 -3
- package/dist/cron/isolated-agent/helpers.js +22 -5
- package/dist/cron/isolated-agent/run.js +171 -63
- package/dist/cron/isolated-agent/session.js +2 -0
- package/dist/cron/normalize.js +356 -28
- package/dist/cron/parse.js +10 -5
- package/dist/cron/run-log.js +35 -10
- package/dist/cron/schedule.js +41 -6
- package/dist/cron/service/jobs.js +208 -35
- package/dist/cron/service/ops.js +72 -16
- package/dist/cron/service/state.js +2 -0
- package/dist/cron/service/store.js +386 -14
- package/dist/cron/service/timer.js +390 -147
- package/dist/cron/session-reaper.js +86 -0
- package/dist/cron/store.js +23 -8
- package/dist/cron/validate-timestamp.js +43 -0
- package/dist/discord/monitor/agent-components.js +438 -0
- package/dist/discord/monitor/allow-list.js +28 -5
- package/dist/discord/monitor/gateway-registry.js +29 -0
- package/dist/discord/monitor/native-command.js +44 -23
- package/dist/discord/monitor/sender-identity.js +45 -0
- package/dist/discord/pluralkit.js +27 -0
- package/dist/discord/send.outbound.js +92 -5
- package/dist/discord/send.shared.js +60 -23
- package/dist/discord/targets.js +84 -1
- package/dist/entry.js +15 -9
- package/dist/extensionAPI.js +8 -0
- package/dist/gateway/control-ui.js +8 -1
- package/dist/gateway/hooks-mapping.js +3 -0
- package/dist/gateway/hooks.js +65 -0
- package/dist/gateway/net.js +96 -31
- package/dist/gateway/node-command-policy.js +50 -15
- package/dist/gateway/origin-check.js +56 -0
- package/dist/gateway/protocol/client-info.js +9 -0
- package/dist/gateway/protocol/index.js +9 -2
- package/dist/gateway/protocol/schema/agents-models-skills.js +71 -1
- package/dist/gateway/protocol/schema/cron.js +22 -10
- package/dist/gateway/protocol/schema/protocol-schemas.js +16 -2
- package/dist/gateway/protocol/schema/sessions.js +12 -0
- package/dist/gateway/server/hooks.js +1 -1
- package/dist/gateway/server-broadcast.js +26 -9
- package/dist/gateway/server-chat.js +112 -23
- package/dist/gateway/server-discovery-runtime.js +10 -2
- package/dist/gateway/server-http.js +109 -11
- package/dist/gateway/server-methods/agent-timestamp.js +60 -0
- package/dist/gateway/server-methods/agents.js +321 -2
- package/dist/gateway/server-methods/usage.js +559 -16
- package/dist/gateway/server-runtime-state.js +22 -8
- package/dist/gateway/server-startup-memory.js +16 -0
- package/dist/gateway/server.impl.js +5 -1
- package/dist/gateway/session-utils.fs.js +23 -25
- package/dist/gateway/session-utils.js +20 -10
- package/dist/gateway/sessions-patch.js +7 -22
- package/dist/gateway/test-helpers.server.js +35 -2
- package/dist/imessage/constants.js +2 -0
- package/dist/imessage/monitor/deliver.js +4 -1
- package/dist/imessage/monitor/monitor-provider.js +51 -1
- package/dist/infra/bonjour-discovery.js +131 -70
- package/dist/infra/control-ui-assets.js +134 -12
- package/dist/infra/errors.js +12 -0
- package/dist/infra/exec-approvals.js +266 -57
- package/dist/infra/format-time/format-datetime.js +79 -0
- package/dist/infra/format-time/format-duration.js +81 -0
- package/dist/infra/format-time/format-relative.js +80 -0
- package/dist/infra/heartbeat-runner.js +140 -49
- package/dist/infra/home-dir.js +54 -0
- package/dist/infra/net/fetch-guard.js +122 -0
- package/dist/infra/net/ssrf.js +65 -29
- package/dist/infra/outbound/abort.js +14 -0
- package/dist/infra/outbound/message-action-runner.js +77 -13
- package/dist/infra/outbound/outbound-session.js +143 -37
- package/dist/infra/poolbot-root.js +43 -1
- package/dist/infra/session-cost-usage.js +631 -41
- package/dist/infra/state-migrations.js +317 -47
- package/dist/infra/update-global.js +35 -0
- package/dist/infra/update-runner.js +149 -43
- package/dist/infra/warning-filter.js +65 -0
- package/dist/infra/widearea-dns.js +30 -9
- package/dist/logging/redact-identifier.js +12 -0
- package/dist/media/fetch.js +81 -58
- package/dist/media-understanding/apply.js +403 -3
- package/dist/media-understanding/attachments.js +38 -27
- package/dist/media-understanding/defaults.js +16 -0
- package/dist/media-understanding/providers/deepgram/audio.js +22 -14
- package/dist/media-understanding/providers/google/audio.js +24 -17
- package/dist/media-understanding/providers/google/video.js +24 -17
- package/dist/media-understanding/providers/image.js +2 -2
- package/dist/media-understanding/providers/index.js +4 -1
- package/dist/media-understanding/providers/openai/audio.js +22 -14
- package/dist/media-understanding/providers/shared.js +16 -11
- package/dist/media-understanding/providers/zai/index.js +6 -0
- package/dist/media-understanding/runner.js +158 -90
- package/dist/memory/batch-voyage.js +277 -0
- package/dist/memory/embeddings-voyage.js +75 -0
- package/dist/memory/embeddings.js +28 -16
- package/dist/memory/internal.js +101 -18
- package/dist/memory/manager.js +154 -48
- package/dist/memory/search-manager.js +173 -0
- package/dist/memory/session-files.js +9 -3
- package/dist/node-host/runner.js +34 -24
- package/dist/node-host/with-timeout.js +27 -0
- package/dist/plugins/commands.js +5 -1
- package/dist/plugins/config-state.js +86 -7
- package/dist/plugins/source-display.js +51 -0
- package/dist/process/exec.js +20 -2
- package/dist/routing/resolve-route.js +12 -0
- package/dist/routing/session-key.js +15 -0
- package/dist/runtime.js +2 -0
- package/dist/security/audit-extra.async.js +601 -0
- package/dist/security/audit-extra.js +2 -830
- package/dist/security/audit-extra.sync.js +505 -0
- package/dist/security/channel-metadata.js +34 -0
- package/dist/security/external-content.js +88 -6
- package/dist/security/skill-scanner.js +330 -0
- package/dist/sessions/session-key-utils.js +7 -0
- package/dist/signal/monitor/event-handler.js +80 -1
- package/dist/slack/monitor/media.js +85 -15
- package/dist/tailscale/detect.js +1 -2
- package/dist/telegram/bot/helpers.js +109 -28
- package/dist/telegram/bot-handlers.js +144 -3
- package/dist/telegram/bot-message-context.js +37 -10
- package/dist/telegram/bot-message-dispatch.js +48 -15
- package/dist/telegram/bot-native-commands.js +86 -29
- package/dist/telegram/bot.js +30 -29
- package/dist/telegram/model-buttons.js +163 -0
- package/dist/telegram/monitor.js +110 -85
- package/dist/telegram/send.js +129 -47
- package/dist/terminal/restore.js +45 -0
- package/dist/test-helpers/state-dir-env.js +16 -0
- package/dist/tts/tts.js +12 -6
- package/dist/tui/tui-session-actions.js +166 -54
- package/dist/utils/fetch-timeout.js +20 -0
- package/dist/utils/normalize-secret-input.js +19 -0
- package/dist/utils/transcript-tools.js +58 -0
- package/dist/utils.js +45 -14
- package/dist/version.js +42 -5
- package/package.json +1 -1
|
@@ -24,6 +24,7 @@ import { isCloudCodeAssistFormatError, resolveBootstrapMaxChars, validateAnthrop
|
|
|
24
24
|
import { subscribeEmbeddedPiSession } from "../../pi-embedded-subscribe.js";
|
|
25
25
|
import { ensurePiCompactionReserveTokens, resolveCompactionReserveTokensFloor, } from "../../pi-settings.js";
|
|
26
26
|
import { createPoolbotCodingTools } from "../../pi-tools.js";
|
|
27
|
+
import { repairSessionFileIfNeeded } from "../../session-file-repair.js";
|
|
27
28
|
import { resolveSandboxContext } from "../../sandbox.js";
|
|
28
29
|
import { guardSessionManager } from "../../session-tool-result-guard-wrapper.js";
|
|
29
30
|
import { resolveTranscriptPolicy } from "../../transcript-policy.js";
|
|
@@ -44,10 +45,11 @@ import { clearActiveEmbeddedRun, setActiveEmbeddedRun, } from "../runs.js";
|
|
|
44
45
|
import { buildEmbeddedSandboxInfo } from "../sandbox-info.js";
|
|
45
46
|
import { prewarmSessionFile, trackSessionManagerAccess } from "../session-manager-cache.js";
|
|
46
47
|
import { prepareSessionManagerForRun } from "../session-manager-init.js";
|
|
47
|
-
import { buildEmbeddedSystemPrompt, createSystemPromptOverride } from "../system-prompt.js";
|
|
48
|
+
import { applySystemPromptOverrideToSession, buildEmbeddedSystemPrompt, createSystemPromptOverride, } from "../system-prompt.js";
|
|
48
49
|
import { splitSdkTools } from "../tool-split.js";
|
|
49
50
|
import { toClientToolDefinitions } from "../../pi-tool-definition-adapter.js";
|
|
50
51
|
import { buildSystemPromptParams } from "../../system-prompt-params.js";
|
|
52
|
+
import { detectRuntimeShell } from "../../shell-utils.js";
|
|
51
53
|
import { describeUnknownError, mapThinkingLevel } from "../utils.js";
|
|
52
54
|
import { resolveSandboxRuntimeStatus } from "../../sandbox/runtime-status.js";
|
|
53
55
|
import { buildTtsSystemPromptHint } from "../../../tts/tts.js";
|
|
@@ -164,6 +166,7 @@ export async function runEmbeddedAttempt(params) {
|
|
|
164
166
|
senderName: params.senderName,
|
|
165
167
|
senderUsername: params.senderUsername,
|
|
166
168
|
senderE164: params.senderE164,
|
|
169
|
+
senderIsOwner: params.senderIsOwner,
|
|
167
170
|
sessionKey: params.sessionKey ?? params.sessionId,
|
|
168
171
|
agentDir,
|
|
169
172
|
workspaceDir: effectiveWorkspace,
|
|
@@ -177,6 +180,8 @@ export async function runEmbeddedAttempt(params) {
|
|
|
177
180
|
replyToMode: params.replyToMode,
|
|
178
181
|
hasRepliedRef: params.hasRepliedRef,
|
|
179
182
|
modelHasVision,
|
|
183
|
+
requireExplicitMessageTarget: params.requireExplicitMessageTarget ?? isSubagentSessionKey(params.sessionKey),
|
|
184
|
+
disableMessageTool: params.disableMessageTool,
|
|
180
185
|
});
|
|
181
186
|
const tools = sanitizeToolsForGoogle({ tools: toolsRaw, provider: params.provider });
|
|
182
187
|
logToolSchemasForGoogle({ tools, provider: params.provider });
|
|
@@ -263,6 +268,7 @@ export async function runEmbeddedAttempt(params) {
|
|
|
263
268
|
channel: runtimeChannel,
|
|
264
269
|
capabilities: runtimeCapabilities,
|
|
265
270
|
channelActions,
|
|
271
|
+
shell: detectRuntimeShell(),
|
|
266
272
|
},
|
|
267
273
|
});
|
|
268
274
|
const isDefaultAgent = sessionAgentId === defaultAgentId;
|
|
@@ -299,6 +305,7 @@ export async function runEmbeddedAttempt(params) {
|
|
|
299
305
|
userTime,
|
|
300
306
|
userTimeFormat,
|
|
301
307
|
contextFiles,
|
|
308
|
+
memoryCitationsMode: params.config?.memory?.citations,
|
|
302
309
|
});
|
|
303
310
|
const systemPromptReport = buildSystemPromptReport({
|
|
304
311
|
source: "run",
|
|
@@ -322,13 +329,18 @@ export async function runEmbeddedAttempt(params) {
|
|
|
322
329
|
skillsPrompt,
|
|
323
330
|
tools,
|
|
324
331
|
});
|
|
325
|
-
const
|
|
332
|
+
const systemPromptOverride = createSystemPromptOverride(appendPrompt);
|
|
333
|
+
const systemPromptText = systemPromptOverride();
|
|
326
334
|
const sessionLock = await acquireSessionWriteLock({
|
|
327
335
|
sessionFile: params.sessionFile,
|
|
328
336
|
});
|
|
329
337
|
let sessionManager;
|
|
330
338
|
let session;
|
|
331
339
|
try {
|
|
340
|
+
await repairSessionFileIfNeeded({
|
|
341
|
+
sessionFile: params.sessionFile,
|
|
342
|
+
warn: (message) => log.warn(message),
|
|
343
|
+
});
|
|
332
344
|
const hadSessionFile = await fs
|
|
333
345
|
.stat(params.sessionFile)
|
|
334
346
|
.then(() => true)
|
|
@@ -357,7 +369,7 @@ export async function runEmbeddedAttempt(params) {
|
|
|
357
369
|
settingsManager,
|
|
358
370
|
minReserveTokens: resolveCompactionReserveTokensFloor(params.config),
|
|
359
371
|
});
|
|
360
|
-
|
|
372
|
+
buildEmbeddedExtensionPaths({
|
|
361
373
|
cfg: params.config,
|
|
362
374
|
sessionManager,
|
|
363
375
|
provider: params.provider,
|
|
@@ -373,7 +385,7 @@ export async function runEmbeddedAttempt(params) {
|
|
|
373
385
|
const clientToolDefs = params.clientTools
|
|
374
386
|
? toClientToolDefinitions(params.clientTools, (toolName, toolParams) => {
|
|
375
387
|
clientToolCallDetected = { name: toolName, params: toolParams };
|
|
376
|
-
})
|
|
388
|
+
}, { agentId: sessionAgentId, sessionKey: params.sessionKey })
|
|
377
389
|
: [];
|
|
378
390
|
const allCustomTools = [...customTools, ...clientToolDefs];
|
|
379
391
|
({ session } = await createAgentSession({
|
|
@@ -383,15 +395,12 @@ export async function runEmbeddedAttempt(params) {
|
|
|
383
395
|
modelRegistry: params.modelRegistry,
|
|
384
396
|
model: params.model,
|
|
385
397
|
thinkingLevel: mapThinkingLevel(params.thinkLevel),
|
|
386
|
-
systemPrompt,
|
|
387
398
|
tools: builtInTools,
|
|
388
399
|
customTools: allCustomTools,
|
|
389
400
|
sessionManager,
|
|
390
401
|
settingsManager,
|
|
391
|
-
skills: [],
|
|
392
|
-
contextFiles: [],
|
|
393
|
-
additionalExtensionPaths,
|
|
394
402
|
}));
|
|
403
|
+
applySystemPromptOverrideToSession(session, systemPromptText);
|
|
395
404
|
if (!session) {
|
|
396
405
|
throw new Error("Embedded agent session missing");
|
|
397
406
|
}
|
|
@@ -423,7 +432,7 @@ export async function runEmbeddedAttempt(params) {
|
|
|
423
432
|
if (cacheTrace) {
|
|
424
433
|
cacheTrace.recordStage("session:loaded", {
|
|
425
434
|
messages: activeSession.messages,
|
|
426
|
-
system:
|
|
435
|
+
system: systemPromptText,
|
|
427
436
|
note: "after session create",
|
|
428
437
|
});
|
|
429
438
|
activeSession.agent.streamFn = cacheTrace.wrapStreamFn(activeSession.agent.streamFn);
|
|
@@ -570,6 +579,7 @@ export async function runEmbeddedAttempt(params) {
|
|
|
570
579
|
}
|
|
571
580
|
// Get hook runner once for both before_agent_start and agent_end hooks
|
|
572
581
|
const hookRunner = getGlobalHookRunner();
|
|
582
|
+
const hookAgentId = sessionAgentId;
|
|
573
583
|
let promptError = null;
|
|
574
584
|
try {
|
|
575
585
|
const promptStartedAt = Date.now();
|
|
@@ -581,7 +591,7 @@ export async function runEmbeddedAttempt(params) {
|
|
|
581
591
|
prompt: params.prompt,
|
|
582
592
|
messages: activeSession.messages,
|
|
583
593
|
}, {
|
|
584
|
-
agentId:
|
|
594
|
+
agentId: hookAgentId,
|
|
585
595
|
sessionKey: params.sessionKey,
|
|
586
596
|
workspaceDir: params.workspaceDir,
|
|
587
597
|
messageProvider: params.messageProvider ?? undefined,
|
|
@@ -694,7 +704,7 @@ export async function runEmbeddedAttempt(params) {
|
|
|
694
704
|
error: promptError ? describeUnknownError(promptError) : undefined,
|
|
695
705
|
durationMs: Date.now() - promptStartedAt,
|
|
696
706
|
}, {
|
|
697
|
-
agentId:
|
|
707
|
+
agentId: hookAgentId,
|
|
698
708
|
sessionKey: params.sessionKey,
|
|
699
709
|
workspaceDir: params.workspaceDir,
|
|
700
710
|
messageProvider: params.messageProvider ?? undefined,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import { enqueueCommandInLane } from "../../process/command-queue.js";
|
|
3
|
-
import { resolveUserPath } from "../../utils.js";
|
|
4
3
|
import { isMarkdownCapableMessageChannel } from "../../utils/message-channel.js";
|
|
5
4
|
import { resolvePoolbotAgentDir } from "../agent-paths.js";
|
|
6
5
|
import { isProfileInCooldown, markAuthProfileFailure, markAuthProfileGood, markAuthProfileUsed, } from "../auth-profiles.js";
|
|
@@ -10,14 +9,16 @@ import { FailoverError, resolveFailoverStatus } from "../failover-error.js";
|
|
|
10
9
|
import { ensureAuthProfileStore, getApiKeyForModel, resolveAuthProfileOrder, } from "../model-auth.js";
|
|
11
10
|
import { normalizeProviderId } from "../model-selection.js";
|
|
12
11
|
import { ensurePoolbotModelsJson } from "../models-config.js";
|
|
13
|
-
import { classifyFailoverReason, formatAssistantErrorText, isAuthAssistantError, isCompactionFailureError, isContextOverflowError, isFailoverAssistantError, isFailoverErrorMessage, parseImageDimensionError, isRateLimitAssistantError, isTimeoutErrorMessage, pickFallbackThinkingLevel, } from "../pi-embedded-helpers.js";
|
|
12
|
+
import { BILLING_ERROR_USER_MESSAGE, classifyFailoverReason, formatAssistantErrorText, isAuthAssistantError, isBillingAssistantError, isCompactionFailureError, isContextOverflowError, isFailoverAssistantError, isFailoverErrorMessage, parseImageSizeError, parseImageDimensionError, isRateLimitAssistantError, isTimeoutErrorMessage, pickFallbackThinkingLevel, } from "../pi-embedded-helpers.js";
|
|
14
13
|
import { normalizeUsage } from "../usage.js";
|
|
14
|
+
import { redactRunIdentifier, resolveRunWorkspaceDir } from "../workspace-run.js";
|
|
15
15
|
import { compactEmbeddedPiSessionDirect } from "./compact.js";
|
|
16
16
|
import { resolveGlobalLane, resolveSessionLane } from "./lanes.js";
|
|
17
17
|
import { log } from "./logger.js";
|
|
18
18
|
import { resolveModel } from "./model.js";
|
|
19
19
|
import { runEmbeddedAttempt } from "./run/attempt.js";
|
|
20
20
|
import { buildEmbeddedRunPayloads } from "./run/payloads.js";
|
|
21
|
+
import { truncateOversizedToolResultsInSession, sessionLikelyHasOversizedToolResults, } from "./tool-result-truncation.js";
|
|
21
22
|
import { describeUnknownError } from "./utils.js";
|
|
22
23
|
// Avoid Anthropic's refusal test token poisoning session transcripts.
|
|
23
24
|
const ANTHROPIC_MAGIC_STRING_TRIGGER_REFUSAL = "ANTHROPIC_MAGIC_STRING_TRIGGER_REFUSAL";
|
|
@@ -27,6 +28,45 @@ function scrubAnthropicRefusalMagic(prompt) {
|
|
|
27
28
|
return prompt;
|
|
28
29
|
return prompt.replaceAll(ANTHROPIC_MAGIC_STRING_TRIGGER_REFUSAL, ANTHROPIC_MAGIC_STRING_REPLACEMENT);
|
|
29
30
|
}
|
|
31
|
+
const createUsageAccumulator = () => ({
|
|
32
|
+
input: 0,
|
|
33
|
+
output: 0,
|
|
34
|
+
cacheRead: 0,
|
|
35
|
+
cacheWrite: 0,
|
|
36
|
+
total: 0,
|
|
37
|
+
});
|
|
38
|
+
const hasUsageValues = (usage) => !!usage &&
|
|
39
|
+
[usage.input, usage.output, usage.cacheRead, usage.cacheWrite, usage.total].some((value) => typeof value === "number" && Number.isFinite(value) && value > 0);
|
|
40
|
+
const mergeUsageIntoAccumulator = (target, usage) => {
|
|
41
|
+
if (!hasUsageValues(usage)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
target.input += usage.input ?? 0;
|
|
45
|
+
target.output += usage.output ?? 0;
|
|
46
|
+
target.cacheRead += usage.cacheRead ?? 0;
|
|
47
|
+
target.cacheWrite += usage.cacheWrite ?? 0;
|
|
48
|
+
target.total +=
|
|
49
|
+
usage.total ??
|
|
50
|
+
(usage.input ?? 0) + (usage.output ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
|
|
51
|
+
};
|
|
52
|
+
const toNormalizedUsage = (usage) => {
|
|
53
|
+
const hasUsage = usage.input > 0 ||
|
|
54
|
+
usage.output > 0 ||
|
|
55
|
+
usage.cacheRead > 0 ||
|
|
56
|
+
usage.cacheWrite > 0 ||
|
|
57
|
+
usage.total > 0;
|
|
58
|
+
if (!hasUsage) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
const derivedTotal = usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
|
|
62
|
+
return {
|
|
63
|
+
input: usage.input || undefined,
|
|
64
|
+
output: usage.output || undefined,
|
|
65
|
+
cacheRead: usage.cacheRead || undefined,
|
|
66
|
+
cacheWrite: usage.cacheWrite || undefined,
|
|
67
|
+
total: usage.total || derivedTotal || undefined,
|
|
68
|
+
};
|
|
69
|
+
};
|
|
30
70
|
export async function runEmbeddedPiAgent(params) {
|
|
31
71
|
const sessionLane = resolveSessionLane(params.sessionKey?.trim() || params.sessionId);
|
|
32
72
|
const globalLane = resolveGlobalLane(params.lane);
|
|
@@ -42,7 +82,18 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
42
82
|
const isProbeSession = params.sessionId?.startsWith("probe-") ?? false;
|
|
43
83
|
return enqueueSession(() => enqueueGlobal(async () => {
|
|
44
84
|
const started = Date.now();
|
|
45
|
-
const
|
|
85
|
+
const workspaceResolution = resolveRunWorkspaceDir({
|
|
86
|
+
workspaceDir: params.workspaceDir,
|
|
87
|
+
sessionKey: params.sessionKey,
|
|
88
|
+
config: params.config,
|
|
89
|
+
});
|
|
90
|
+
const resolvedWorkspace = workspaceResolution.workspaceDir;
|
|
91
|
+
const redactedSessionId = redactRunIdentifier(params.sessionId);
|
|
92
|
+
const redactedSessionKey = redactRunIdentifier(params.sessionKey);
|
|
93
|
+
const redactedWorkspace = redactRunIdentifier(resolvedWorkspace);
|
|
94
|
+
if (workspaceResolution.usedFallback) {
|
|
95
|
+
log.warn(`[workspace-fallback] caller=runEmbeddedPiAgent reason=${workspaceResolution.fallbackReason} run=${params.runId} session=${redactedSessionId} sessionKey=${redactedSessionKey} agent=${workspaceResolution.agentId} workspace=${redactedWorkspace}`);
|
|
96
|
+
}
|
|
46
97
|
const prevCwd = process.cwd();
|
|
47
98
|
const provider = (params.provider ?? DEFAULT_PROVIDER).trim() || DEFAULT_PROVIDER;
|
|
48
99
|
const modelId = (params.model ?? DEFAULT_MODEL).trim() || DEFAULT_MODEL;
|
|
@@ -213,7 +264,11 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
213
264
|
throwAuthProfileFailover({ allInCooldown: false, error: err });
|
|
214
265
|
}
|
|
215
266
|
}
|
|
216
|
-
|
|
267
|
+
const MAX_OVERFLOW_COMPACTION_ATTEMPTS = 3;
|
|
268
|
+
let overflowCompactionAttempts = 0;
|
|
269
|
+
let toolResultTruncationAttempted = false;
|
|
270
|
+
const usageAccumulator = createUsageAccumulator();
|
|
271
|
+
let autoCompactionCount = 0;
|
|
217
272
|
try {
|
|
218
273
|
while (true) {
|
|
219
274
|
attemptedThinking.add(thinkLevel);
|
|
@@ -231,12 +286,13 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
231
286
|
groupChannel: params.groupChannel,
|
|
232
287
|
groupSpace: params.groupSpace,
|
|
233
288
|
spawnedBy: params.spawnedBy,
|
|
289
|
+
senderIsOwner: params.senderIsOwner,
|
|
234
290
|
currentChannelId: params.currentChannelId,
|
|
235
291
|
currentThreadTs: params.currentThreadTs,
|
|
236
292
|
replyToMode: params.replyToMode,
|
|
237
293
|
hasRepliedRef: params.hasRepliedRef,
|
|
238
294
|
sessionFile: params.sessionFile,
|
|
239
|
-
workspaceDir:
|
|
295
|
+
workspaceDir: resolvedWorkspace,
|
|
240
296
|
agentDir,
|
|
241
297
|
config: params.config,
|
|
242
298
|
skillsSnapshot: params.skillsSnapshot,
|
|
@@ -274,46 +330,135 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
274
330
|
enforceFinalTag: params.enforceFinalTag,
|
|
275
331
|
});
|
|
276
332
|
const { aborted, promptError, timedOut, sessionIdUsed, lastAssistant } = attempt;
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
333
|
+
mergeUsageIntoAccumulator(usageAccumulator, attempt.attemptUsage ?? normalizeUsage(lastAssistant?.usage));
|
|
334
|
+
autoCompactionCount += Math.max(0, attempt.compactionCount ?? 0);
|
|
335
|
+
const formattedAssistantErrorText = lastAssistant
|
|
336
|
+
? formatAssistantErrorText(lastAssistant, {
|
|
337
|
+
cfg: params.config,
|
|
338
|
+
sessionKey: params.sessionKey ?? params.sessionId,
|
|
339
|
+
})
|
|
340
|
+
: undefined;
|
|
341
|
+
const assistantErrorText = lastAssistant?.stopReason === "error"
|
|
342
|
+
? lastAssistant.errorMessage?.trim() || formattedAssistantErrorText
|
|
343
|
+
: undefined;
|
|
344
|
+
const contextOverflowError = !aborted
|
|
345
|
+
? (() => {
|
|
346
|
+
if (promptError) {
|
|
347
|
+
const errorText = describeUnknownError(promptError);
|
|
348
|
+
if (isContextOverflowError(errorText)) {
|
|
349
|
+
return { text: errorText, source: "promptError" };
|
|
350
|
+
}
|
|
351
|
+
// Prompt submission failed with a non-overflow error. Do not
|
|
352
|
+
// inspect prior assistant errors from history for this attempt.
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
if (assistantErrorText && isContextOverflowError(assistantErrorText)) {
|
|
356
|
+
return { text: assistantErrorText, source: "assistantError" };
|
|
357
|
+
}
|
|
358
|
+
return null;
|
|
359
|
+
})()
|
|
360
|
+
: null;
|
|
361
|
+
if (contextOverflowError) {
|
|
362
|
+
const errorText = contextOverflowError.text;
|
|
363
|
+
const msgCount = attempt.messagesSnapshot?.length ?? 0;
|
|
364
|
+
log.warn(`[context-overflow-diag] sessionKey=${params.sessionKey ?? params.sessionId} ` +
|
|
365
|
+
`provider=${provider}/${modelId} source=${contextOverflowError.source} ` +
|
|
366
|
+
`messages=${msgCount} sessionFile=${params.sessionFile} ` +
|
|
367
|
+
`compactionAttempts=${overflowCompactionAttempts} error=${errorText.slice(0, 200)}`);
|
|
368
|
+
const isCompactionFailure = isCompactionFailureError(errorText);
|
|
369
|
+
// Attempt auto-compaction on context overflow (not compaction_failure)
|
|
370
|
+
if (!isCompactionFailure &&
|
|
371
|
+
overflowCompactionAttempts < MAX_OVERFLOW_COMPACTION_ATTEMPTS) {
|
|
372
|
+
overflowCompactionAttempts++;
|
|
373
|
+
log.warn(`context overflow detected (attempt ${overflowCompactionAttempts}/${MAX_OVERFLOW_COMPACTION_ATTEMPTS}); attempting auto-compaction for ${provider}/${modelId}`);
|
|
374
|
+
const compactResult = await compactEmbeddedPiSessionDirect({
|
|
375
|
+
sessionId: params.sessionId,
|
|
376
|
+
sessionKey: params.sessionKey,
|
|
377
|
+
messageChannel: params.messageChannel,
|
|
378
|
+
messageProvider: params.messageProvider,
|
|
379
|
+
agentAccountId: params.agentAccountId,
|
|
380
|
+
authProfileId: lastProfileId,
|
|
381
|
+
sessionFile: params.sessionFile,
|
|
382
|
+
workspaceDir: resolvedWorkspace,
|
|
383
|
+
agentDir,
|
|
384
|
+
config: params.config,
|
|
385
|
+
skillsSnapshot: params.skillsSnapshot,
|
|
386
|
+
senderIsOwner: params.senderIsOwner,
|
|
387
|
+
provider,
|
|
388
|
+
model: modelId,
|
|
389
|
+
thinkLevel,
|
|
390
|
+
reasoningLevel: params.reasoningLevel,
|
|
391
|
+
bashElevated: params.bashElevated,
|
|
392
|
+
extraSystemPrompt: params.extraSystemPrompt,
|
|
393
|
+
ownerNumbers: params.ownerNumbers,
|
|
394
|
+
});
|
|
395
|
+
if (compactResult.compacted) {
|
|
396
|
+
autoCompactionCount += 1;
|
|
397
|
+
log.info(`auto-compaction succeeded for ${provider}/${modelId}; retrying prompt`);
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
log.warn(`auto-compaction failed for ${provider}/${modelId}: ${compactResult.reason ?? "nothing to compact"}`);
|
|
401
|
+
}
|
|
402
|
+
// Fallback: try truncating oversized tool results in the session.
|
|
403
|
+
// This handles the case where a single tool result exceeds the
|
|
404
|
+
// context window and compaction cannot reduce it further.
|
|
405
|
+
if (!toolResultTruncationAttempted) {
|
|
406
|
+
const contextWindowTokens = ctxInfo.tokens;
|
|
407
|
+
const hasOversized = attempt.messagesSnapshot
|
|
408
|
+
? sessionLikelyHasOversizedToolResults({
|
|
409
|
+
messages: attempt.messagesSnapshot,
|
|
410
|
+
contextWindowTokens,
|
|
411
|
+
})
|
|
412
|
+
: false;
|
|
413
|
+
if (hasOversized) {
|
|
414
|
+
toolResultTruncationAttempted = true;
|
|
415
|
+
log.warn(`[context-overflow-recovery] Attempting tool result truncation for ${provider}/${modelId} ` +
|
|
416
|
+
`(contextWindow=${contextWindowTokens} tokens)`);
|
|
417
|
+
const truncResult = await truncateOversizedToolResultsInSession({
|
|
418
|
+
sessionFile: params.sessionFile,
|
|
419
|
+
contextWindowTokens,
|
|
286
420
|
sessionId: params.sessionId,
|
|
287
421
|
sessionKey: params.sessionKey,
|
|
288
|
-
messageChannel: params.messageChannel,
|
|
289
|
-
messageProvider: params.messageProvider,
|
|
290
|
-
agentAccountId: params.agentAccountId,
|
|
291
|
-
authProfileId: lastProfileId,
|
|
292
|
-
sessionFile: params.sessionFile,
|
|
293
|
-
workspaceDir: params.workspaceDir,
|
|
294
|
-
agentDir,
|
|
295
|
-
config: params.config,
|
|
296
|
-
skillsSnapshot: params.skillsSnapshot,
|
|
297
|
-
provider,
|
|
298
|
-
model: modelId,
|
|
299
|
-
thinkLevel,
|
|
300
|
-
reasoningLevel: params.reasoningLevel,
|
|
301
|
-
bashElevated: params.bashElevated,
|
|
302
|
-
extraSystemPrompt: params.extraSystemPrompt,
|
|
303
|
-
ownerNumbers: params.ownerNumbers,
|
|
304
422
|
});
|
|
305
|
-
if (
|
|
306
|
-
log.info(`
|
|
423
|
+
if (truncResult.truncated) {
|
|
424
|
+
log.info(`[context-overflow-recovery] Truncated ${truncResult.truncatedCount} tool result(s); retrying prompt`);
|
|
425
|
+
// Session is now smaller; allow compaction retries again.
|
|
426
|
+
overflowCompactionAttempts = 0;
|
|
307
427
|
continue;
|
|
308
428
|
}
|
|
309
|
-
log.warn(`
|
|
429
|
+
log.warn(`[context-overflow-recovery] Tool result truncation did not help: ${truncResult.reason ?? "unknown"}`);
|
|
310
430
|
}
|
|
311
|
-
|
|
431
|
+
}
|
|
432
|
+
const kind = isCompactionFailure ? "compaction_failure" : "context_overflow";
|
|
433
|
+
return {
|
|
434
|
+
payloads: [
|
|
435
|
+
{
|
|
436
|
+
text: "Context overflow: prompt too large for the model. " +
|
|
437
|
+
"Try /reset (or /new) to start a fresh session, or use a larger-context model.",
|
|
438
|
+
isError: true,
|
|
439
|
+
},
|
|
440
|
+
],
|
|
441
|
+
meta: {
|
|
442
|
+
durationMs: Date.now() - started,
|
|
443
|
+
agentMeta: {
|
|
444
|
+
sessionId: sessionIdUsed,
|
|
445
|
+
provider,
|
|
446
|
+
model: model.id,
|
|
447
|
+
},
|
|
448
|
+
systemPromptReport: attempt.systemPromptReport,
|
|
449
|
+
error: { kind, message: errorText },
|
|
450
|
+
},
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
if (promptError && !aborted) {
|
|
454
|
+
const errorText = describeUnknownError(promptError);
|
|
455
|
+
// Handle role ordering errors with a user-friendly message
|
|
456
|
+
if (/incorrect role information|roles must alternate/i.test(errorText)) {
|
|
312
457
|
return {
|
|
313
458
|
payloads: [
|
|
314
459
|
{
|
|
315
|
-
text: "
|
|
316
|
-
"
|
|
460
|
+
text: "Message ordering conflict - please try again. " +
|
|
461
|
+
"If this persists, use /new to start a fresh session.",
|
|
317
462
|
isError: true,
|
|
318
463
|
},
|
|
319
464
|
],
|
|
@@ -325,17 +470,21 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
325
470
|
model: model.id,
|
|
326
471
|
},
|
|
327
472
|
systemPromptReport: attempt.systemPromptReport,
|
|
328
|
-
error: { kind, message: errorText },
|
|
473
|
+
error: { kind: "role_ordering", message: errorText },
|
|
329
474
|
},
|
|
330
475
|
};
|
|
331
476
|
}
|
|
332
|
-
// Handle
|
|
333
|
-
|
|
477
|
+
// Handle image size errors with a user-friendly message (no retry needed)
|
|
478
|
+
const imageSizeError = parseImageSizeError(errorText);
|
|
479
|
+
if (imageSizeError) {
|
|
480
|
+
const maxMb = imageSizeError.maxMb;
|
|
481
|
+
const maxMbLabel = typeof maxMb === "number" && Number.isFinite(maxMb) ? `${maxMb}` : null;
|
|
482
|
+
const maxBytesHint = maxMbLabel ? ` (max ${maxMbLabel}MB)` : "";
|
|
334
483
|
return {
|
|
335
484
|
payloads: [
|
|
336
485
|
{
|
|
337
|
-
text:
|
|
338
|
-
"
|
|
486
|
+
text: `Image too large for the model${maxBytesHint}. ` +
|
|
487
|
+
"Please compress or resize the image and try again.",
|
|
339
488
|
isError: true,
|
|
340
489
|
},
|
|
341
490
|
],
|
|
@@ -347,7 +496,7 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
347
496
|
model: model.id,
|
|
348
497
|
},
|
|
349
498
|
systemPromptReport: attempt.systemPromptReport,
|
|
350
|
-
error: { kind: "
|
|
499
|
+
error: { kind: "image_size", message: errorText },
|
|
351
500
|
},
|
|
352
501
|
};
|
|
353
502
|
}
|
|
@@ -399,6 +548,7 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
399
548
|
}
|
|
400
549
|
const authFailure = isAuthAssistantError(lastAssistant);
|
|
401
550
|
const rateLimitFailure = isRateLimitAssistantError(lastAssistant);
|
|
551
|
+
const billingFailure = isBillingAssistantError(lastAssistant);
|
|
402
552
|
const failoverFailure = isFailoverAssistantError(lastAssistant);
|
|
403
553
|
const assistantFailoverReason = classifyFailoverReason(lastAssistant?.errorMessage ?? "");
|
|
404
554
|
const cloudCodeAssistFormatError = attempt.cloudCodeAssistFormatError;
|
|
@@ -456,9 +606,11 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
456
606
|
? "LLM request timed out."
|
|
457
607
|
: rateLimitFailure
|
|
458
608
|
? "LLM request rate limited."
|
|
459
|
-
:
|
|
460
|
-
?
|
|
461
|
-
:
|
|
609
|
+
: billingFailure
|
|
610
|
+
? BILLING_ERROR_USER_MESSAGE
|
|
611
|
+
: authFailure
|
|
612
|
+
? "LLM request unauthorized."
|
|
613
|
+
: "LLM request failed.");
|
|
462
614
|
const status = resolveFailoverStatus(assistantFailoverReason ?? "unknown") ??
|
|
463
615
|
(isTimeoutErrorMessage(message) ? 408 : undefined);
|
|
464
616
|
throw new FailoverError(message, {
|
|
@@ -470,12 +622,13 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
470
622
|
});
|
|
471
623
|
}
|
|
472
624
|
}
|
|
473
|
-
const usage =
|
|
625
|
+
const usage = toNormalizedUsage(usageAccumulator);
|
|
474
626
|
const agentMeta = {
|
|
475
627
|
sessionId: sessionIdUsed,
|
|
476
628
|
provider: lastAssistant?.provider ?? provider,
|
|
477
629
|
model: lastAssistant?.model ?? model.id,
|
|
478
630
|
usage,
|
|
631
|
+
compactionCount: autoCompactionCount > 0 ? autoCompactionCount : undefined,
|
|
479
632
|
};
|
|
480
633
|
const payloads = buildEmbeddedRunPayloads({
|
|
481
634
|
assistantTexts: attempt.assistantTexts,
|
|
@@ -25,9 +25,17 @@ export function buildEmbeddedSystemPrompt(params) {
|
|
|
25
25
|
userTime: params.userTime,
|
|
26
26
|
userTimeFormat: params.userTimeFormat,
|
|
27
27
|
contextFiles: params.contextFiles,
|
|
28
|
+
memoryCitationsMode: params.memoryCitationsMode,
|
|
28
29
|
});
|
|
29
30
|
}
|
|
30
31
|
export function createSystemPromptOverride(systemPrompt) {
|
|
31
|
-
const
|
|
32
|
-
return () =>
|
|
32
|
+
const override = systemPrompt.trim();
|
|
33
|
+
return (_defaultPrompt) => override;
|
|
34
|
+
}
|
|
35
|
+
export function applySystemPromptOverrideToSession(session, override) {
|
|
36
|
+
const prompt = typeof override === "function" ? override() : override.trim();
|
|
37
|
+
session.agent.setSystemPrompt(prompt);
|
|
38
|
+
const mutableSession = session;
|
|
39
|
+
mutableSession._baseSystemPrompt = prompt;
|
|
40
|
+
mutableSession._rebuildSystemPrompt = () => prompt;
|
|
33
41
|
}
|