@getpaseo/server 0.1.96 → 0.1.97-beta.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/server/{utils/executable.d.ts → executable-resolution/executable-resolution.d.ts} +2 -2
- package/dist/server/{utils/executable.js → executable-resolution/executable-resolution.js} +16 -14
- package/dist/server/executable-resolution/windows.d.ts +18 -0
- package/dist/server/executable-resolution/windows.js +62 -0
- package/dist/server/server/agent/agent-loading.js +4 -1
- package/dist/server/server/agent/agent-manager.d.ts +10 -2
- package/dist/server/server/agent/agent-manager.js +34 -46
- package/dist/server/server/agent/agent-projections.js +3 -0
- package/dist/server/server/agent/agent-prompt.js +19 -1
- package/dist/server/server/agent/agent-response-loop.js +2 -4
- package/dist/server/server/agent/agent-storage.d.ts +18 -19
- package/dist/server/server/agent/agent-storage.js +6 -23
- package/dist/server/server/agent/create-agent/create.d.ts +2 -12
- package/dist/server/server/agent/create-agent/create.js +28 -30
- package/dist/server/server/agent/create-agent-lifecycle-dispatch.d.ts +4 -2
- package/dist/server/server/agent/create-agent-lifecycle-dispatch.js +31 -22
- package/dist/server/server/agent/import-sessions.d.ts +1 -10
- package/dist/server/server/agent/import-sessions.js +1 -53
- package/dist/server/server/agent/lifecycle-command.js +5 -4
- package/dist/server/server/agent/mcp-server.d.ts +8 -5
- package/dist/server/server/agent/mcp-server.js +41 -14
- package/dist/server/server/agent/mcp-shared.d.ts +6 -3
- package/dist/server/server/agent/mcp-shared.js +3 -0
- package/dist/server/server/agent/provider-launch-config.js +1 -1
- package/dist/server/server/agent/providers/acp-agent.d.ts +5 -0
- package/dist/server/server/agent/providers/acp-agent.js +31 -26
- package/dist/server/server/agent/providers/claude/agent.js +45 -6
- package/dist/server/server/agent/providers/codex-app-server-agent.js +1 -1
- package/dist/server/server/agent/providers/copilot-acp-agent.js +1 -0
- package/dist/server/server/agent/providers/cursor-acp-agent.d.ts +0 -7
- package/dist/server/server/agent/providers/cursor-acp-agent.js +0 -78
- package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +2 -0
- package/dist/server/server/agent/providers/mock-load-test-agent.js +73 -1
- package/dist/server/server/agent/providers/opencode/server-manager.js +1 -1
- package/dist/server/server/agent/structured-generation-providers.js +45 -1
- package/dist/server/server/agent-attention-policy.d.ts +12 -3
- package/dist/server/server/agent-attention-policy.js +15 -3
- package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts +7 -6
- package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +21 -16
- package/dist/server/server/bootstrap.d.ts +3 -0
- package/dist/server/server/bootstrap.js +91 -12
- package/dist/server/server/config.js +1 -0
- package/dist/server/server/daemon-config-store.js +1 -0
- package/dist/server/server/exports.d.ts +1 -1
- package/dist/server/server/exports.js +1 -1
- package/dist/server/server/loop-service.d.ts +24 -24
- package/dist/server/server/migrations/backfill-workspace-id.migration.d.ts +9 -0
- package/dist/server/server/migrations/backfill-workspace-id.migration.js +60 -0
- package/dist/server/server/paseo-worktree-service.d.ts +9 -0
- package/dist/server/server/paseo-worktree-service.js +71 -12
- package/dist/server/server/path-utils.d.ts +1 -0
- package/dist/server/server/path-utils.js +6 -1
- package/dist/server/server/persisted-config.d.ts +7 -0
- package/dist/server/server/persisted-config.js +1 -0
- package/dist/server/server/persistence-hooks.d.ts +1 -0
- package/dist/server/server/persistence-hooks.js +13 -5
- package/dist/server/server/resolve-workspace-id-for-path.d.ts +3 -0
- package/dist/server/server/resolve-workspace-id-for-path.js +41 -0
- package/dist/server/server/script-proxy.d.ts +1 -1
- package/dist/server/server/script-proxy.js +1 -1
- package/dist/server/server/service-proxy.js +1 -1
- package/dist/server/server/session.d.ts +31 -6
- package/dist/server/server/session.js +640 -196
- package/dist/server/server/websocket-server.d.ts +5 -0
- package/dist/server/server/websocket-server.js +137 -3
- package/dist/server/server/workspace-archive-service.d.ts +60 -3
- package/dist/server/server/workspace-archive-service.js +217 -4
- package/dist/server/server/workspace-directory.d.ts +20 -2
- package/dist/server/server/workspace-directory.js +148 -70
- package/dist/server/server/workspace-git-service.js +21 -21
- package/dist/server/server/workspace-reconciliation-service.d.ts +1 -1
- package/dist/server/server/workspace-reconciliation-service.js +21 -22
- package/dist/server/server/workspace-registry-bootstrap.js +23 -10
- package/dist/server/server/workspace-registry-model.d.ts +3 -3
- package/dist/server/server/workspace-registry-model.js +9 -10
- package/dist/server/server/workspace-registry.d.ts +17 -4
- package/dist/server/server/workspace-registry.js +27 -0
- package/dist/server/server/worktree/commands.d.ts +7 -5
- package/dist/server/server/worktree/commands.js +38 -18
- package/dist/server/server/worktree-bootstrap.d.ts +1 -0
- package/dist/server/server/worktree-bootstrap.js +4 -1
- package/dist/server/server/worktree-branch-name-generator.d.ts +5 -1
- package/dist/server/server/worktree-branch-name-generator.js +8 -2
- package/dist/server/server/worktree-session.d.ts +4 -5
- package/dist/server/server/worktree-session.js +9 -3
- package/dist/server/services/github-service.js +1 -1
- package/dist/server/terminal/activity/terminal-activity-tracker.d.ts +20 -0
- package/dist/server/terminal/activity/terminal-activity-tracker.js +59 -0
- package/dist/server/terminal/agent-hooks/agent-hook-installer.d.ts +62 -0
- package/dist/server/terminal/agent-hooks/agent-hook-installer.js +117 -0
- package/dist/server/terminal/agent-hooks/claude/claude-settings.d.ts +7 -0
- package/dist/server/terminal/agent-hooks/claude/claude-settings.js +88 -0
- package/dist/server/terminal/agent-hooks/claude/claude.d.ts +4 -0
- package/dist/server/terminal/agent-hooks/claude/claude.js +47 -0
- package/dist/server/terminal/agent-hooks/codex/codex-settings.d.ts +7 -0
- package/dist/server/terminal/agent-hooks/codex/codex-settings.js +99 -0
- package/dist/server/terminal/agent-hooks/codex/codex.d.ts +4 -0
- package/dist/server/terminal/agent-hooks/codex/codex.js +30 -0
- package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.d.ts +4 -0
- package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.js +46 -0
- package/dist/server/terminal/agent-hooks/opencode/opencode.d.ts +3 -0
- package/dist/server/terminal/agent-hooks/opencode/opencode.js +23 -0
- package/dist/server/terminal/agent-hooks/provider-registry.d.ts +24 -0
- package/dist/server/terminal/agent-hooks/provider-registry.js +36 -0
- package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.d.ts +10 -0
- package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.js +26 -0
- package/dist/server/terminal/terminal-manager-factory.d.ts +4 -1
- package/dist/server/terminal/terminal-manager-factory.js +2 -2
- package/dist/server/terminal/terminal-manager.d.ts +33 -2
- package/dist/server/terminal/terminal-manager.js +144 -18
- package/dist/server/terminal/terminal-output-coalescer.d.ts +4 -0
- package/dist/server/terminal/terminal-output-coalescer.js +18 -0
- package/dist/server/terminal/terminal-restore.d.ts +1 -0
- package/dist/server/terminal/terminal-restore.js +6 -0
- package/dist/server/terminal/terminal-session-controller.d.ts +4 -2
- package/dist/server/terminal/terminal-session-controller.js +65 -24
- package/dist/server/terminal/terminal-worker-process.js +146 -63
- package/dist/server/terminal/terminal-worker-protocol.d.ts +19 -14
- package/dist/server/terminal/terminal.d.ts +42 -0
- package/dist/server/terminal/terminal.js +235 -16
- package/dist/server/terminal/worker-terminal-manager.d.ts +1 -0
- package/dist/server/terminal/worker-terminal-manager.js +220 -36
- package/dist/server/utils/build-metadata-prompt.d.ts +1 -1
- package/dist/server/utils/github-remote.js +1 -1
- package/dist/server/utils/tree-kill.d.ts +2 -2
- package/dist/src/{utils/executable.js → executable-resolution/executable-resolution.js} +16 -14
- package/dist/src/executable-resolution/windows.js +62 -0
- package/dist/src/server/agent/provider-launch-config.js +1 -1
- package/dist/src/server/persisted-config.js +1 -0
- package/package.json +10 -5
- package/dist/server/server/agent/agent-metadata-generator.d.ts +0 -36
- package/dist/server/server/agent/agent-metadata-generator.js +0 -112
- package/dist/server/server/paseo-worktree-archive-service.d.ts +0 -41
- package/dist/server/server/paseo-worktree-archive-service.js +0 -144
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ChildProcessWithoutNullStreams } from "node:child_process";
|
|
2
|
+
import type { ProcessTerminator } from "../../../utils/tree-kill.js";
|
|
2
3
|
import type { ReadableStream as NodeReadableStream, WritableStream as NodeWritableStream } from "node:stream/web";
|
|
3
4
|
import { ClientSideConnection, type Client as ACPClient, type CreateTerminalRequest, type InitializeResponse, type KillTerminalRequest, type LoadSessionResponse, type NewSessionResponse, type ReadTextFileRequest, type RequestPermissionRequest, type RequestPermissionResponse, type ResumeSessionResponse, type SessionConfigOption, type SessionMode, type SessionModelState, type SessionNotification, type TerminalOutputRequest, type TerminalOutputResponse, type ToolCallContent, type ToolCallLocation, type ToolCallStatus, type ToolKind, type Usage, type WaitForTerminalExitRequest, type WriteTextFileRequest, type Stream as ACPStream } from "@agentclientprotocol/sdk";
|
|
4
5
|
import type { Logger } from "pino";
|
|
@@ -31,6 +32,7 @@ interface ACPAgentClientOptions {
|
|
|
31
32
|
capabilities?: AgentCapabilityFlags;
|
|
32
33
|
waitForInitialCommands?: boolean;
|
|
33
34
|
initialCommandsWaitTimeoutMs?: number;
|
|
35
|
+
terminateProcess?: ProcessTerminator;
|
|
34
36
|
}
|
|
35
37
|
interface ACPAgentSessionOptions {
|
|
36
38
|
provider: string;
|
|
@@ -52,6 +54,7 @@ interface ACPAgentSessionOptions {
|
|
|
52
54
|
launchEnv?: Record<string, string>;
|
|
53
55
|
waitForInitialCommands?: boolean;
|
|
54
56
|
initialCommandsWaitTimeoutMs?: number;
|
|
57
|
+
terminateProcess?: ProcessTerminator;
|
|
55
58
|
}
|
|
56
59
|
export interface SpawnedACPProcess {
|
|
57
60
|
child: ChildProcessWithoutNullStreams;
|
|
@@ -148,6 +151,7 @@ export declare class ACPAgentClient implements AgentClient {
|
|
|
148
151
|
private readonly thinkingOptionWriter?;
|
|
149
152
|
private readonly waitForInitialCommands;
|
|
150
153
|
private readonly initialCommandsWaitTimeoutMs;
|
|
154
|
+
protected readonly terminateProcess: ProcessTerminator;
|
|
151
155
|
constructor(options: ACPAgentClientOptions);
|
|
152
156
|
createSession(config: AgentSessionConfig, launchContext?: AgentLaunchContext): Promise<AgentSession>;
|
|
153
157
|
resumeSession(handle: AgentPersistenceHandle, overrides?: Partial<AgentSessionConfig>, launchContext?: AgentLaunchContext): Promise<AgentSession>;
|
|
@@ -218,6 +222,7 @@ export declare class ACPAgentSession implements AgentSession, ACPClient {
|
|
|
218
222
|
private historyPending;
|
|
219
223
|
private replayingHistory;
|
|
220
224
|
private bootstrapThreadEventPending;
|
|
225
|
+
private readonly terminateProcess;
|
|
221
226
|
constructor(config: AgentSessionConfig, options: ACPAgentSessionOptions);
|
|
222
227
|
get id(): string | null;
|
|
223
228
|
initializeNewSession(): Promise<void>;
|
|
@@ -2,6 +2,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { Readable, Writable } from "node:stream";
|
|
5
|
+
import { terminateWithTreeKill } from "../../../utils/tree-kill.js";
|
|
5
6
|
import { ClientSideConnection, PROTOCOL_VERSION, } from "@agentclientprotocol/sdk";
|
|
6
7
|
import { getAgentStreamEventTurnId, } from "../agent-sdk-types.js";
|
|
7
8
|
import { importSessionFromPersistence } from "../provider-session-import.js";
|
|
@@ -72,6 +73,10 @@ function resolveTerminalCommand(command, args) {
|
|
|
72
73
|
export const DEFAULT_ACP_CAPABILITIES = {
|
|
73
74
|
supportsStreaming: true,
|
|
74
75
|
supportsSessionPersistence: true,
|
|
76
|
+
// ACP agents can list prior sessions via `session/list`. The runtime probe in
|
|
77
|
+
// listImportableSessions returns nothing for agents that don't advertise the
|
|
78
|
+
// capability, so enabling this here only makes the daemon query them.
|
|
79
|
+
supportsSessionListing: true,
|
|
75
80
|
supportsDynamicModes: true,
|
|
76
81
|
supportsMcpServers: true,
|
|
77
82
|
supportsReasoningStream: true,
|
|
@@ -255,6 +260,7 @@ export function deriveModelDefinitionsFromACP(provider, models, configOptions) {
|
|
|
255
260
|
export class ACPAgentClient {
|
|
256
261
|
constructor(options) {
|
|
257
262
|
this.provider = options.provider;
|
|
263
|
+
this.terminateProcess = options.terminateProcess ?? terminateWithTreeKill;
|
|
258
264
|
this.capabilities = options.capabilities ?? DEFAULT_ACP_CAPABILITIES;
|
|
259
265
|
this.logger = options.logger.child({
|
|
260
266
|
module: "agent",
|
|
@@ -379,7 +385,13 @@ export class ACPAgentClient {
|
|
|
379
385
|
const sessions = [];
|
|
380
386
|
let cursor;
|
|
381
387
|
for (;;) {
|
|
382
|
-
const page = await this.runACPRequest(() => probe.connection.listSessions(
|
|
388
|
+
const page = await this.runACPRequest(() => probe.connection.listSessions({
|
|
389
|
+
...(cursor ? { cursor } : {}),
|
|
390
|
+
// Filter by working directory at the source. Without this the agent
|
|
391
|
+
// returns globally-recent sessions, which the `limit` below can
|
|
392
|
+
// truncate before the current directory's sessions are reached.
|
|
393
|
+
...(options?.cwd ? { cwd: options.cwd } : {}),
|
|
394
|
+
}));
|
|
383
395
|
for (const session of page.sessions) {
|
|
384
396
|
sessions.push({
|
|
385
397
|
providerHandleId: session.sessionId,
|
|
@@ -463,7 +475,7 @@ export class ACPAgentClient {
|
|
|
463
475
|
]));
|
|
464
476
|
}
|
|
465
477
|
catch (error) {
|
|
466
|
-
await terminateChildProcess(child, 2000);
|
|
478
|
+
await terminateChildProcess(child, 2000, this.terminateProcess);
|
|
467
479
|
throw error;
|
|
468
480
|
}
|
|
469
481
|
finally {
|
|
@@ -500,7 +512,7 @@ export class ACPAgentClient {
|
|
|
500
512
|
}
|
|
501
513
|
}
|
|
502
514
|
finally {
|
|
503
|
-
await terminateChildProcess(probe.child, 2000);
|
|
515
|
+
await terminateChildProcess(probe.child, 2000, this.terminateProcess);
|
|
504
516
|
}
|
|
505
517
|
}
|
|
506
518
|
async runACPRequest(request) {
|
|
@@ -572,6 +584,7 @@ export class ACPAgentSession {
|
|
|
572
584
|
this.replayingHistory = false;
|
|
573
585
|
this.bootstrapThreadEventPending = false;
|
|
574
586
|
this.provider = options.provider;
|
|
587
|
+
this.terminateProcess = options.terminateProcess ?? terminateWithTreeKill;
|
|
575
588
|
this.capabilities = options.capabilities;
|
|
576
589
|
this.logger = options.logger.child({ module: "agent", provider: options.provider });
|
|
577
590
|
this.runtimeSettings = options.runtimeSettings;
|
|
@@ -1106,13 +1119,14 @@ export class ACPAgentSession {
|
|
|
1106
1119
|
this.logger.debug({ err: error }, "ACP closeSession failed during shutdown");
|
|
1107
1120
|
}
|
|
1108
1121
|
}
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1122
|
+
const terminalTerminations = Array.from(this.terminalEntries.values(), (terminal) => this.terminateProcess(terminal.child, {
|
|
1123
|
+
gracefulTimeoutMs: 2000,
|
|
1124
|
+
forceTimeoutMs: 2000,
|
|
1125
|
+
}));
|
|
1126
|
+
await Promise.all(terminalTerminations);
|
|
1112
1127
|
this.terminalEntries.clear();
|
|
1113
1128
|
if (this.child) {
|
|
1114
|
-
this.child
|
|
1115
|
-
await waitForChildExit(this.child, 2000);
|
|
1129
|
+
await this.terminateProcess(this.child, { gracefulTimeoutMs: 2000, forceTimeoutMs: 2000 });
|
|
1116
1130
|
}
|
|
1117
1131
|
this.subscribers.clear();
|
|
1118
1132
|
this.connection = null;
|
|
@@ -1260,14 +1274,14 @@ export class ACPAgentSession {
|
|
|
1260
1274
|
async releaseTerminal(params) {
|
|
1261
1275
|
const entry = this.getTerminalEntry(params.terminalId);
|
|
1262
1276
|
if (!entry.exit) {
|
|
1263
|
-
entry.child
|
|
1277
|
+
await this.terminateProcess(entry.child, { gracefulTimeoutMs: 2000, forceTimeoutMs: 2000 });
|
|
1264
1278
|
}
|
|
1265
1279
|
this.terminalEntries.delete(params.terminalId);
|
|
1266
1280
|
}
|
|
1267
1281
|
async killTerminal(params) {
|
|
1268
1282
|
const entry = this.getTerminalEntry(params.terminalId);
|
|
1269
1283
|
if (!entry.exit) {
|
|
1270
|
-
entry.child
|
|
1284
|
+
await this.terminateProcess(entry.child, { gracefulTimeoutMs: 2000, forceTimeoutMs: 2000 });
|
|
1271
1285
|
}
|
|
1272
1286
|
return {};
|
|
1273
1287
|
}
|
|
@@ -2099,23 +2113,14 @@ function coerceSessionConfigMetadata(metadata) {
|
|
|
2099
2113
|
}
|
|
2100
2114
|
return metadata;
|
|
2101
2115
|
}
|
|
2102
|
-
async function
|
|
2103
|
-
|
|
2104
|
-
|
|
2116
|
+
async function terminateChildProcess(child, timeoutMs, terminate) {
|
|
2117
|
+
try {
|
|
2118
|
+
await terminate(child, { gracefulTimeoutMs: timeoutMs, forceTimeoutMs: timeoutMs });
|
|
2105
2119
|
}
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
if (child.exitCode === null && child.signalCode === null) {
|
|
2111
|
-
child.kill("SIGKILL");
|
|
2120
|
+
finally {
|
|
2121
|
+
child.stdin.destroy();
|
|
2122
|
+
child.stdout.destroy();
|
|
2123
|
+
child.stderr.destroy();
|
|
2112
2124
|
}
|
|
2113
2125
|
}
|
|
2114
|
-
async function terminateChildProcess(child, timeoutMs) {
|
|
2115
|
-
child.kill("SIGTERM");
|
|
2116
|
-
child.stdin.destroy();
|
|
2117
|
-
child.stdout.destroy();
|
|
2118
|
-
child.stderr.destroy();
|
|
2119
|
-
await waitForChildExit(child, timeoutMs);
|
|
2120
|
-
}
|
|
2121
2126
|
//# sourceMappingURL=acp-agent.js.map
|
|
@@ -381,6 +381,9 @@ function isClaudeNoResponsePlaceholderText(value) {
|
|
|
381
381
|
return normalizeClaudeTranscriptText(value) === NO_RESPONSE_REQUESTED_PLACEHOLDER;
|
|
382
382
|
}
|
|
383
383
|
const LOCAL_COMMAND_STDOUT_PATTERN = /^\s*<local-command-stdout>[\s\S]*<\/local-command-stdout>\s*$/;
|
|
384
|
+
const CLAUDE_COMMAND_MESSAGE_PATTERN = /<command-message>([\s\S]*?)<\/command-message>/;
|
|
385
|
+
const CLAUDE_COMMAND_ARGS_PATTERN = /<command-args>([\s\S]*?)<\/command-args>/;
|
|
386
|
+
const CLAUDE_COMMAND_NAME_PATTERN = /<command-name>([\s\S]*?)<\/command-name>/;
|
|
384
387
|
function isClaudeLocalCommandStdout(value) {
|
|
385
388
|
const normalized = normalizeClaudeTranscriptText(value);
|
|
386
389
|
return normalized !== null && LOCAL_COMMAND_STDOUT_PATTERN.test(normalized);
|
|
@@ -426,7 +429,7 @@ export function extractUserMessageText(content) {
|
|
|
426
429
|
if (!normalized || isClaudeTranscriptNoiseText(normalized)) {
|
|
427
430
|
return null;
|
|
428
431
|
}
|
|
429
|
-
return normalized;
|
|
432
|
+
return normalizeClaudeUserPromptText(normalized);
|
|
430
433
|
}
|
|
431
434
|
if (!Array.isArray(content)) {
|
|
432
435
|
return null;
|
|
@@ -440,7 +443,10 @@ export function extractUserMessageText(content) {
|
|
|
440
443
|
if (text && text.trim()) {
|
|
441
444
|
const trimmed = text.trim();
|
|
442
445
|
if (!isClaudeTranscriptNoiseText(trimmed)) {
|
|
443
|
-
|
|
446
|
+
const normalized = normalizeClaudeUserPromptText(trimmed);
|
|
447
|
+
if (normalized) {
|
|
448
|
+
parts.push(normalized);
|
|
449
|
+
}
|
|
444
450
|
}
|
|
445
451
|
continue;
|
|
446
452
|
}
|
|
@@ -448,7 +454,10 @@ export function extractUserMessageText(content) {
|
|
|
448
454
|
if (input && input.trim()) {
|
|
449
455
|
const trimmed = input.trim();
|
|
450
456
|
if (!isClaudeTranscriptNoiseText(trimmed)) {
|
|
451
|
-
|
|
457
|
+
const normalized = normalizeClaudeUserPromptText(trimmed);
|
|
458
|
+
if (normalized) {
|
|
459
|
+
parts.push(normalized);
|
|
460
|
+
}
|
|
452
461
|
}
|
|
453
462
|
}
|
|
454
463
|
}
|
|
@@ -4074,6 +4083,32 @@ function normalizeImportablePromptPreview(text) {
|
|
|
4074
4083
|
return null;
|
|
4075
4084
|
return normalized.length > 160 ? normalized.slice(0, 160) : normalized;
|
|
4076
4085
|
}
|
|
4086
|
+
function normalizeClaudeUserPromptText(text) {
|
|
4087
|
+
const normalized = text.trim();
|
|
4088
|
+
if (!CLAUDE_COMMAND_MESSAGE_PATTERN.test(normalized)) {
|
|
4089
|
+
return normalized || null;
|
|
4090
|
+
}
|
|
4091
|
+
const command = readClaudeCommandPromptName(normalized);
|
|
4092
|
+
if (!command) {
|
|
4093
|
+
return null;
|
|
4094
|
+
}
|
|
4095
|
+
const commandArgs = normalized.match(CLAUDE_COMMAND_ARGS_PATTERN)?.[1]?.trim();
|
|
4096
|
+
if (commandArgs) {
|
|
4097
|
+
return `${command} ${commandArgs}`;
|
|
4098
|
+
}
|
|
4099
|
+
return command;
|
|
4100
|
+
}
|
|
4101
|
+
function readClaudeCommandPromptName(text) {
|
|
4102
|
+
const commandName = text.match(CLAUDE_COMMAND_NAME_PATTERN)?.[1]?.trim();
|
|
4103
|
+
if (commandName) {
|
|
4104
|
+
return commandName.startsWith("/") ? commandName : `/${commandName}`;
|
|
4105
|
+
}
|
|
4106
|
+
const commandMessage = text.match(CLAUDE_COMMAND_MESSAGE_PATTERN)?.[1]?.trim();
|
|
4107
|
+
if (!commandMessage) {
|
|
4108
|
+
return null;
|
|
4109
|
+
}
|
|
4110
|
+
return commandMessage.startsWith("/") ? commandMessage : `/${commandMessage}`;
|
|
4111
|
+
}
|
|
4077
4112
|
function extractClaudeUserText(messageRaw) {
|
|
4078
4113
|
const message = toObjectRecord(messageRaw);
|
|
4079
4114
|
if (!message) {
|
|
@@ -4081,11 +4116,15 @@ function extractClaudeUserText(messageRaw) {
|
|
|
4081
4116
|
}
|
|
4082
4117
|
if (typeof message.content === "string") {
|
|
4083
4118
|
const normalized = message.content.trim();
|
|
4084
|
-
|
|
4119
|
+
if (!normalized || isClaudeTranscriptNoiseText(normalized))
|
|
4120
|
+
return null;
|
|
4121
|
+
return normalizeClaudeUserPromptText(normalized);
|
|
4085
4122
|
}
|
|
4086
4123
|
if (typeof message.text === "string") {
|
|
4087
4124
|
const normalized = message.text.trim();
|
|
4088
|
-
|
|
4125
|
+
if (!normalized || isClaudeTranscriptNoiseText(normalized))
|
|
4126
|
+
return null;
|
|
4127
|
+
return normalizeClaudeUserPromptText(normalized);
|
|
4089
4128
|
}
|
|
4090
4129
|
if (isUnknownArray(message.content)) {
|
|
4091
4130
|
for (const block of message.content) {
|
|
@@ -4093,7 +4132,7 @@ function extractClaudeUserText(messageRaw) {
|
|
|
4093
4132
|
if (blockRecord && typeof blockRecord.text === "string") {
|
|
4094
4133
|
const normalized = blockRecord.text.trim();
|
|
4095
4134
|
if (normalized && !isClaudeTranscriptNoiseText(normalized)) {
|
|
4096
|
-
return normalized;
|
|
4135
|
+
return normalizeClaudeUserPromptText(normalized);
|
|
4097
4136
|
}
|
|
4098
4137
|
}
|
|
4099
4138
|
}
|
|
@@ -12,7 +12,7 @@ import { composeSystemPromptParts } from "../system-prompt.js";
|
|
|
12
12
|
import { curateAgentActivity } from "../activity-curator.js";
|
|
13
13
|
import { mapCodexToolCallEnvelope, mapCodexToolCallFromThreadItem, } from "./codex/tool-call-mapper.js";
|
|
14
14
|
import { checkProviderLaunchAvailable, createProviderEnv, createProviderEnvSpec, resolveProviderLaunch, } from "../provider-launch-config.js";
|
|
15
|
-
import { findExecutable, probeExecutable } from "../../../
|
|
15
|
+
import { findExecutable, probeExecutable, } from "../../../executable-resolution/executable-resolution.js";
|
|
16
16
|
import { createPathEquivalenceMatcher } from "../../../utils/path.js";
|
|
17
17
|
import { spawnProcess } from "../../../utils/spawn.js";
|
|
18
18
|
import { extractCodexTerminalSessionId, nonEmptyString } from "./tool-call-mapper-utils.js";
|
|
@@ -5,6 +5,7 @@ import { formatDiagnosticStatus, formatProviderDiagnostic, formatProviderDiagnos
|
|
|
5
5
|
const COPILOT_CAPABILITIES = {
|
|
6
6
|
supportsStreaming: true,
|
|
7
7
|
supportsSessionPersistence: true,
|
|
8
|
+
supportsSessionListing: true,
|
|
8
9
|
supportsDynamicModes: true,
|
|
9
10
|
supportsMcpServers: true,
|
|
10
11
|
supportsReasoningStream: true,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { Logger } from "pino";
|
|
2
|
-
import type { AgentModelDefinition, ListModelsOptions } from "../agent-sdk-types.js";
|
|
3
2
|
import { GenericACPAgentClient } from "./generic-acp-agent.js";
|
|
4
3
|
interface CursorACPAgentClientOptions {
|
|
5
4
|
logger: Logger;
|
|
@@ -10,13 +9,7 @@ interface CursorACPAgentClientOptions {
|
|
|
10
9
|
providerParams?: unknown;
|
|
11
10
|
}
|
|
12
11
|
export declare class CursorACPAgentClient extends GenericACPAgentClient {
|
|
13
|
-
private readonly cursorCommand;
|
|
14
|
-
private readonly env?;
|
|
15
12
|
constructor(options: CursorACPAgentClientOptions);
|
|
16
|
-
listModels(options: ListModelsOptions): Promise<AgentModelDefinition[]>;
|
|
17
|
-
private canUseCursorModelsFallback;
|
|
18
|
-
private listCursorModelsFallback;
|
|
19
13
|
}
|
|
20
|
-
export declare function parseCursorAgentModelsOutput(output: string): AgentModelDefinition[];
|
|
21
14
|
export {};
|
|
22
15
|
//# sourceMappingURL=cursor-acp-agent.d.ts.map
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import { basename } from "node:path";
|
|
2
|
-
import * as spawnUtils from "../../../utils/spawn.js";
|
|
3
1
|
import { GenericACPAgentClient } from "./generic-acp-agent.js";
|
|
4
|
-
const CURSOR_MODELS_TIMEOUT_MS = 10000;
|
|
5
2
|
const CURSOR_INITIAL_COMMANDS_WAIT_TIMEOUT_MS = 10000;
|
|
6
|
-
const CURSOR_MODEL_MARKER_PATTERN = /\s+\((?:default|current)\)$/;
|
|
7
3
|
export class CursorACPAgentClient extends GenericACPAgentClient {
|
|
8
4
|
constructor(options) {
|
|
9
5
|
super({
|
|
@@ -17,80 +13,6 @@ export class CursorACPAgentClient extends GenericACPAgentClient {
|
|
|
17
13
|
waitForInitialCommands: true,
|
|
18
14
|
initialCommandsWaitTimeoutMs: CURSOR_INITIAL_COMMANDS_WAIT_TIMEOUT_MS,
|
|
19
15
|
});
|
|
20
|
-
this.cursorCommand = options.command;
|
|
21
|
-
this.env = options.env;
|
|
22
16
|
}
|
|
23
|
-
async listModels(options) {
|
|
24
|
-
const acpModels = await super.listModels(options);
|
|
25
|
-
if (acpModels.length > 0) {
|
|
26
|
-
return acpModels;
|
|
27
|
-
}
|
|
28
|
-
if (this.canUseCursorModelsFallback()) {
|
|
29
|
-
return this.listCursorModelsFallback(acpModels);
|
|
30
|
-
}
|
|
31
|
-
return acpModels;
|
|
32
|
-
}
|
|
33
|
-
canUseCursorModelsFallback() {
|
|
34
|
-
return basename(this.cursorCommand[0]) === "cursor-agent";
|
|
35
|
-
}
|
|
36
|
-
async listCursorModelsFallback(acpModels) {
|
|
37
|
-
try {
|
|
38
|
-
const { stdout } = await spawnUtils.execCommand(this.cursorCommand[0], ["models"], {
|
|
39
|
-
envOverlay: this.env,
|
|
40
|
-
timeout: CURSOR_MODELS_TIMEOUT_MS,
|
|
41
|
-
maxBuffer: 1024 * 1024,
|
|
42
|
-
});
|
|
43
|
-
const fallbackModels = parseCursorAgentModelsOutput(stdout);
|
|
44
|
-
if (fallbackModels.length === 0) {
|
|
45
|
-
this.logger.warn({ provider: "cursor" }, "Cursor ACP model fallback returned no parseable models");
|
|
46
|
-
return acpModels;
|
|
47
|
-
}
|
|
48
|
-
return fallbackModels;
|
|
49
|
-
}
|
|
50
|
-
catch (error) {
|
|
51
|
-
this.logger.warn({ err: error, provider: "cursor" }, "Failed to list Cursor models via cursor-agent models fallback");
|
|
52
|
-
return acpModels;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
export function parseCursorAgentModelsOutput(output) {
|
|
57
|
-
const parsed = output
|
|
58
|
-
.split(/\r?\n/)
|
|
59
|
-
.map((line) => line.trim())
|
|
60
|
-
.filter((line) => line && line !== "Available models" && !line.startsWith("Tip:"))
|
|
61
|
-
.map((line) => {
|
|
62
|
-
const separatorIndex = line.indexOf(" - ");
|
|
63
|
-
if (separatorIndex <= 0) {
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
const id = line.slice(0, separatorIndex).trim();
|
|
67
|
-
const rawLabel = line.slice(separatorIndex + 3).trim();
|
|
68
|
-
if (!id || !rawLabel) {
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
let marker = null;
|
|
72
|
-
if (rawLabel.endsWith(" (default)")) {
|
|
73
|
-
marker = "default";
|
|
74
|
-
}
|
|
75
|
-
else if (rawLabel.endsWith(" (current)")) {
|
|
76
|
-
marker = "current";
|
|
77
|
-
}
|
|
78
|
-
return {
|
|
79
|
-
provider: "acp",
|
|
80
|
-
id,
|
|
81
|
-
label: rawLabel.replace(CURSOR_MODEL_MARKER_PATTERN, ""),
|
|
82
|
-
marker,
|
|
83
|
-
};
|
|
84
|
-
})
|
|
85
|
-
.filter((model) => model !== null);
|
|
86
|
-
const defaultModelId = parsed.find((model) => model.marker === "default")?.id ??
|
|
87
|
-
parsed.find((model) => model.marker === "current")?.id ??
|
|
88
|
-
parsed[0]?.id;
|
|
89
|
-
return parsed.map((model) => ({
|
|
90
|
-
provider: model.provider,
|
|
91
|
-
id: model.id,
|
|
92
|
-
label: model.label,
|
|
93
|
-
isDefault: model.id === defaultModelId,
|
|
94
|
-
}));
|
|
95
17
|
}
|
|
96
18
|
//# sourceMappingURL=cursor-acp-agent.js.map
|
|
@@ -67,6 +67,8 @@ export declare class MockLoadTestAgentSession implements AgentSession {
|
|
|
67
67
|
private scheduleStressTurn;
|
|
68
68
|
private schedulePlanApprovalTurn;
|
|
69
69
|
private scheduleQuestionPromptTurn;
|
|
70
|
+
private scheduleStructuredJsonTurn;
|
|
71
|
+
private emitStructuredJsonTurn;
|
|
70
72
|
private emitPlanApprovalTurn;
|
|
71
73
|
private emitQuestionPromptTurn;
|
|
72
74
|
private emitStressTurn;
|
|
@@ -165,6 +165,35 @@ function parseAgentStreamStressPrompt(prompt) {
|
|
|
165
165
|
coalesced: Boolean(match[2]),
|
|
166
166
|
};
|
|
167
167
|
}
|
|
168
|
+
function parseStructuredBranchNamePrompt(prompt) {
|
|
169
|
+
const text = promptToText(prompt);
|
|
170
|
+
const hasBranchNamePrompt = text.includes("Generate a git branch name for a coding agent") &&
|
|
171
|
+
(text.includes("Return JSON only with fields 'title' and 'branch'.") ||
|
|
172
|
+
text.includes('"title"') ||
|
|
173
|
+
text.includes('"branch"'));
|
|
174
|
+
if (!hasBranchNamePrompt &&
|
|
175
|
+
!(text.includes("You must respond with JSON only that matches this JSON Schema") &&
|
|
176
|
+
text.includes('"title"') &&
|
|
177
|
+
text.includes('"branch"'))) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
const seed = text.split("User context:\n").at(-1)?.trim() ?? "";
|
|
181
|
+
const firstLine = seed
|
|
182
|
+
.split("\n")
|
|
183
|
+
.find((line) => line.trim().length > 0)
|
|
184
|
+
?.trim() ?? "Mock task";
|
|
185
|
+
const title = firstLine
|
|
186
|
+
.replace(/^["'`]+|["'`]+$/g, "")
|
|
187
|
+
.replace(/\s+/g, " ")
|
|
188
|
+
.slice(0, 80)
|
|
189
|
+
.trim();
|
|
190
|
+
const branch = title
|
|
191
|
+
.toLowerCase()
|
|
192
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
193
|
+
.replace(/^-+|-+$/g, "")
|
|
194
|
+
.slice(0, 100) || "mock-task";
|
|
195
|
+
return { title: title || "Mock task", branch };
|
|
196
|
+
}
|
|
168
197
|
function buildRepeatedPayload(bytes, prefix) {
|
|
169
198
|
const line = `${prefix} ${"x".repeat(96)}\n`;
|
|
170
199
|
let output = "";
|
|
@@ -446,7 +475,11 @@ export class MockLoadTestAgentSession {
|
|
|
446
475
|
const largePayload = parseLargeAgentStreamPayloadPrompt(prompt);
|
|
447
476
|
const stress = parseAgentStreamStressPrompt(prompt);
|
|
448
477
|
const questionPrompt = parseMockQuestionPrompt(prompt);
|
|
449
|
-
|
|
478
|
+
const structuredBranchName = parseStructuredBranchNamePrompt(prompt);
|
|
479
|
+
if (structuredBranchName) {
|
|
480
|
+
this.scheduleStructuredJsonTurn(turn, structuredBranchName);
|
|
481
|
+
}
|
|
482
|
+
else if (shouldEmitPlanApprovalPrompt(prompt)) {
|
|
450
483
|
this.schedulePlanApprovalTurn(turn);
|
|
451
484
|
}
|
|
452
485
|
else if (questionPrompt) {
|
|
@@ -600,6 +633,45 @@ export class MockLoadTestAgentSession {
|
|
|
600
633
|
}, 0);
|
|
601
634
|
turn.timer.unref?.();
|
|
602
635
|
}
|
|
636
|
+
scheduleStructuredJsonTurn(turn, result) {
|
|
637
|
+
turn.timer = setTimeout(() => {
|
|
638
|
+
this.emitStructuredJsonTurn(turn, result);
|
|
639
|
+
}, 0);
|
|
640
|
+
turn.timer.unref?.();
|
|
641
|
+
}
|
|
642
|
+
emitStructuredJsonTurn(turn, result) {
|
|
643
|
+
if (this.activeTurn !== turn) {
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
this.clearTurnTimer(turn);
|
|
647
|
+
this.emit({
|
|
648
|
+
type: "turn_started",
|
|
649
|
+
provider: this.provider,
|
|
650
|
+
turnId: turn.turnId,
|
|
651
|
+
});
|
|
652
|
+
const finalText = JSON.stringify(result);
|
|
653
|
+
this.emitTimeline(turn.turnId, {
|
|
654
|
+
type: "assistant_message",
|
|
655
|
+
text: finalText,
|
|
656
|
+
});
|
|
657
|
+
this.activeTurn = null;
|
|
658
|
+
this.emit({
|
|
659
|
+
type: "turn_completed",
|
|
660
|
+
provider: this.provider,
|
|
661
|
+
turnId: turn.turnId,
|
|
662
|
+
});
|
|
663
|
+
turn.resolve({
|
|
664
|
+
sessionId: this.id,
|
|
665
|
+
finalText,
|
|
666
|
+
timeline: [
|
|
667
|
+
{
|
|
668
|
+
type: "assistant_message",
|
|
669
|
+
text: finalText,
|
|
670
|
+
},
|
|
671
|
+
],
|
|
672
|
+
canceled: false,
|
|
673
|
+
});
|
|
674
|
+
}
|
|
603
675
|
emitPlanApprovalTurn(turn) {
|
|
604
676
|
if (this.activeTurn !== turn) {
|
|
605
677
|
return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import net from "node:net";
|
|
2
|
-
import { findExecutable } from "../../../../
|
|
2
|
+
import { findExecutable } from "../../../../executable-resolution/executable-resolution.js";
|
|
3
3
|
import { spawnProcess } from "../../../../utils/spawn.js";
|
|
4
4
|
import { terminateWithTreeKill } from "../../../../utils/tree-kill.js";
|
|
5
5
|
import { createProviderEnvSpec, resolveProviderCommandPrefix, } from "../../provider-launch-config.js";
|
|
@@ -5,6 +5,21 @@ export const DEFAULT_STRUCTURED_GENERATION_PROVIDERS = [
|
|
|
5
5
|
{ modelSubstring: "nemotron-3-super" },
|
|
6
6
|
];
|
|
7
7
|
export async function resolveStructuredGenerationProviders(options) {
|
|
8
|
+
const configuredProviders = readConfiguredProviders(options.daemonConfig);
|
|
9
|
+
if (configuredProviders.length > 0) {
|
|
10
|
+
const explicitProviders = resolveExplicitConfiguredProviders(configuredProviders);
|
|
11
|
+
if (explicitProviders.length === configuredProviders.length) {
|
|
12
|
+
return dedupeProviders(explicitProviders);
|
|
13
|
+
}
|
|
14
|
+
const providerEntries = await options.providerSnapshotManager.listProviders({
|
|
15
|
+
cwd: options.cwd,
|
|
16
|
+
wait: false,
|
|
17
|
+
});
|
|
18
|
+
const providers = resolveConfiguredProviders(configuredProviders, providerEntries);
|
|
19
|
+
if (providers.length > 0) {
|
|
20
|
+
return dedupeProviders(providers);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
8
23
|
const providerEntries = await options.providerSnapshotManager.listProviders({
|
|
9
24
|
cwd: options.cwd,
|
|
10
25
|
wait: true,
|
|
@@ -13,7 +28,7 @@ export async function resolveStructuredGenerationProviders(options) {
|
|
|
13
28
|
const modelEntries = enabledEntries.filter((entry) => (entry.models?.length ?? 0) > 0);
|
|
14
29
|
const entriesByProvider = new Map(enabledEntries.map((entry) => [entry.provider, entry]));
|
|
15
30
|
const providers = [];
|
|
16
|
-
for (const configured of
|
|
31
|
+
for (const configured of configuredProviders) {
|
|
17
32
|
const resolvedConfigured = resolveConfiguredCandidate(configured, modelEntries, entriesByProvider);
|
|
18
33
|
if (!resolvedConfigured) {
|
|
19
34
|
continue;
|
|
@@ -32,6 +47,35 @@ export async function resolveStructuredGenerationProviders(options) {
|
|
|
32
47
|
}
|
|
33
48
|
return dedupeProviders(providers);
|
|
34
49
|
}
|
|
50
|
+
function resolveConfiguredProviders(configuredProviders, providerEntries) {
|
|
51
|
+
const enabledEntries = providerEntries.filter((entry) => entry.enabled);
|
|
52
|
+
const modelEntries = enabledEntries.filter((entry) => (entry.models?.length ?? 0) > 0);
|
|
53
|
+
const entriesByProvider = new Map(enabledEntries.map((entry) => [entry.provider, entry]));
|
|
54
|
+
const providers = [];
|
|
55
|
+
for (const configured of configuredProviders) {
|
|
56
|
+
const resolved = resolveConfiguredCandidate(configured, modelEntries, entriesByProvider);
|
|
57
|
+
if (resolved) {
|
|
58
|
+
providers.push(resolved);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return providers;
|
|
62
|
+
}
|
|
63
|
+
function resolveExplicitConfiguredProviders(configuredProviders) {
|
|
64
|
+
const providers = [];
|
|
65
|
+
for (const configured of configuredProviders) {
|
|
66
|
+
const provider = configured.provider.trim();
|
|
67
|
+
const model = configured.model?.trim();
|
|
68
|
+
if (!provider || !model) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
providers.push({
|
|
72
|
+
provider,
|
|
73
|
+
model,
|
|
74
|
+
...(configured.thinkingOptionId ? { thinkingOptionId: configured.thinkingOptionId } : {}),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return providers;
|
|
78
|
+
}
|
|
35
79
|
function resolveCurrentSelection(selection, readyEntries, entriesByProvider) {
|
|
36
80
|
if (!selection) {
|
|
37
81
|
return null;
|
|
@@ -4,17 +4,26 @@ export interface ClientPresenceState {
|
|
|
4
4
|
appVisible: boolean;
|
|
5
5
|
lastActivityAtMs: number | null;
|
|
6
6
|
focusedAgentId: string | null;
|
|
7
|
+
focusedTerminalId: string | null;
|
|
7
8
|
}
|
|
9
|
+
export type AttentionFocusTarget = {
|
|
10
|
+
kind: "agent";
|
|
11
|
+
id: string;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "terminal";
|
|
14
|
+
id: string;
|
|
15
|
+
};
|
|
8
16
|
export interface NotificationPlan {
|
|
9
17
|
inAppRecipientIndex: number | null;
|
|
10
18
|
shouldPush: boolean;
|
|
11
19
|
}
|
|
12
20
|
interface ComputeNotificationPlanInput {
|
|
13
21
|
allStates: ClientPresenceState[];
|
|
14
|
-
|
|
15
|
-
|
|
22
|
+
focusTarget: AttentionFocusTarget | null;
|
|
23
|
+
pushEligible: boolean;
|
|
16
24
|
nowMs: number;
|
|
17
25
|
}
|
|
18
|
-
export declare function computeNotificationPlan({ allStates,
|
|
26
|
+
export declare function computeNotificationPlan({ allStates, focusTarget, pushEligible, nowMs, }: ComputeNotificationPlanInput): NotificationPlan;
|
|
27
|
+
export declare function isPushEligibleAttentionReason(reason: AgentAttentionReason): boolean;
|
|
19
28
|
export {};
|
|
20
29
|
//# sourceMappingURL=agent-attention-policy.d.ts.map
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
export const PRESENCE_THRESHOLD_MS = 180000;
|
|
2
|
-
|
|
2
|
+
function isFocusedOnTarget(state, target) {
|
|
3
|
+
if (target === null) {
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
if (target.kind === "agent") {
|
|
7
|
+
return state.focusedAgentId === target.id;
|
|
8
|
+
}
|
|
9
|
+
return state.focusedTerminalId === target.id;
|
|
10
|
+
}
|
|
11
|
+
export function computeNotificationPlan({ allStates, focusTarget, pushEligible, nowMs, }) {
|
|
3
12
|
let mostRecentPresentIndex = null;
|
|
4
13
|
let mostRecentPresentAtMs = Number.NEGATIVE_INFINITY;
|
|
5
14
|
for (const [clientIndex, state] of allStates.entries()) {
|
|
@@ -8,7 +17,7 @@ export function computeNotificationPlan({ allStates, agentId, reason, nowMs, })
|
|
|
8
17
|
if (!isPresent) {
|
|
9
18
|
continue;
|
|
10
19
|
}
|
|
11
|
-
if (state.appVisible && state
|
|
20
|
+
if (state.appVisible && isFocusedOnTarget(state, focusTarget)) {
|
|
12
21
|
return { inAppRecipientIndex: null, shouldPush: false };
|
|
13
22
|
}
|
|
14
23
|
if (clampedActivityAtMs > mostRecentPresentAtMs) {
|
|
@@ -19,6 +28,9 @@ export function computeNotificationPlan({ allStates, agentId, reason, nowMs, })
|
|
|
19
28
|
if (mostRecentPresentIndex !== null) {
|
|
20
29
|
return { inAppRecipientIndex: mostRecentPresentIndex, shouldPush: false };
|
|
21
30
|
}
|
|
22
|
-
return { inAppRecipientIndex: null, shouldPush:
|
|
31
|
+
return { inAppRecipientIndex: null, shouldPush: pushEligible };
|
|
32
|
+
}
|
|
33
|
+
export function isPushEligibleAttentionReason(reason) {
|
|
34
|
+
return reason !== "error";
|
|
23
35
|
}
|
|
24
36
|
//# sourceMappingURL=agent-attention-policy.js.map
|