@myagentroam/node 0.9.3 → 0.9.5
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/claude-agent-sdk.d.ts +1 -0
- package/dist/claude-agent-sdk.js +9 -0
- package/dist/codex-app-server.d.ts +25 -0
- package/dist/codex-app-server.js +104 -7
- package/dist/connector.d.ts +1 -0
- package/dist/connector.js +21 -12
- package/dist/database.d.ts +2 -0
- package/dist/native-session-history.d.ts +3 -2
- package/dist/native-session-history.js +199 -30
- package/dist/opencode-server.d.ts +1 -0
- package/dist/opencode-server.js +1 -0
- package/dist/runner/abstract-runner.d.ts +11 -2
- package/dist/runner/abstract-runner.js +4 -0
- package/dist/runner/claude/managed-run-controller.js +3 -0
- package/dist/runner/claude-code-runner.d.ts +2 -1
- package/dist/runner/claude-code-runner.js +4 -0
- package/dist/runner/codex/managed-run-controller.d.ts +9 -0
- package/dist/runner/codex/managed-run-controller.js +63 -17
- package/dist/runner/codex-runner.d.ts +3 -1
- package/dist/runner/codex-runner.js +23 -2
- package/dist/runner/opencode/managed-run-controller.js +4 -0
- package/dist/runner/opencode-runner.d.ts +10 -3
- package/dist/runner/opencode-runner.js +87 -14
- package/dist/runner/runner-registry.js +16 -1
- package/dist/runtime-command-detector.js +1 -6
- package/dist/runtime-state.d.ts +2 -0
- package/dist/runtime-state.js +12 -7
- package/dist/service/conversation-history-service.d.ts +10 -1
- package/dist/service/conversation-history-service.js +272 -42
- package/dist/service/conversation-segment-service.js +7 -1
- package/dist/service/external-session-resume-service.d.ts +2 -0
- package/dist/service/external-session-resume-service.js +45 -34
- package/dist/service/native-session-projection-service.d.ts +1 -0
- package/dist/service/native-session-projection-service.js +4 -0
- package/dist/service/native-session-watch-service.d.ts +26 -2
- package/dist/service/native-session-watch-service.js +258 -42
- package/dist/service/node-request-service.js +2 -1
- package/dist/service/run-event-service.js +16 -5
- package/dist/service/run-workbench-service.d.ts +2 -4
- package/dist/service/run-workbench-service.js +2 -7
- package/dist/service/session-command-service.js +1 -1
- package/dist/service/session-identity-service.d.ts +1 -1
- package/dist/service/session-identity-service.js +1 -1
- package/dist/service/session-lifecycle-service.js +7 -12
- package/dist/service/session-message-service.d.ts +1 -1
- package/dist/service/session-message-service.js +104 -83
- package/dist/service/skill-directory-service.d.ts +1 -0
- package/dist/service/skill-directory-service.js +40 -6
- package/dist/service/workspace-change-service.js +1 -1
- package/dist/service/workspace-domain-state.d.ts +3 -0
- package/dist/service/workspace-domain-state.js +1 -0
- package/dist/service/workspace-file-service.d.ts +1 -0
- package/dist/service/workspace-file-service.js +14 -1
- package/dist/service/workspace-queue-workbench-service.d.ts +29 -2
- package/dist/service/workspace-queue-workbench-service.js +73 -8
- package/dist/service/workspace-watch-service.d.ts +7 -2
- package/dist/service/workspace-watch-service.js +32 -6
- package/dist/service/workspace-workbench-service.d.ts +14 -0
- package/dist/service/workspace-workbench-service.js +215 -16
- package/dist/util/personal-instructions.d.ts +2 -0
- package/dist/util/personal-instructions.js +31 -0
- package/dist/util/runner-native-session-parsers.d.ts +3 -1
- package/dist/util/runner-native-session-parsers.js +35 -17
- package/dist/workspace.d.ts +14 -8
- package/dist/workspace.js +98 -50
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { NodeCapabilities, RunnerDefaultConfiguration, RunnerProfile } from '@myagentroam/protocol';
|
|
2
2
|
import type { NodeAgentSession, NodeDatabase, NodeWorkspace } from '../database.js';
|
|
3
3
|
import { OpenCodeServerClient } from '../opencode-server.js';
|
|
4
|
-
import { AbstractRunner, type ExternalResumeContext, type ExternalResumeResult, type RunnerDiscoveryContext, type RunnerSessionPresentation, type RunnerSessionPresentationContext } from './abstract-runner.js';
|
|
4
|
+
import { AbstractRunner, type ExternalResumeContext, type ExternalResumeResult, type RunnerDiscoveryContext, type RunnerConversationHistoryPage, type RunnerConversationHistoryReaders, type RunnerSessionPresentation, type RunnerSessionPresentationContext } from './abstract-runner.js';
|
|
5
5
|
export interface OpenCodeManagedExecution {
|
|
6
6
|
readonly runId: string;
|
|
7
7
|
readonly sessionId: string;
|
|
@@ -20,6 +20,8 @@ export declare class OpenCodeRunner extends AbstractRunner<'opencode'> {
|
|
|
20
20
|
private readonly modelsByWorkspace;
|
|
21
21
|
private readonly contextLimitsByWorkspace;
|
|
22
22
|
private readonly profileTimersByWorkspace;
|
|
23
|
+
private readonly profileCache;
|
|
24
|
+
private readonly profileRefreshes;
|
|
23
25
|
readonly execution: Map<string, OpenCodeManagedExecution>;
|
|
24
26
|
readonly managedTurns: Map<string, string>;
|
|
25
27
|
private readonly environmentClients;
|
|
@@ -27,10 +29,14 @@ export declare class OpenCodeRunner extends AbstractRunner<'opencode'> {
|
|
|
27
29
|
constructor(client?: OpenCodeServerClient, clientFactory?: () => OpenCodeServerClient);
|
|
28
30
|
profile(capabilities: NodeCapabilities): RunnerProfile;
|
|
29
31
|
refreshProfile(capabilities: NodeCapabilities, workspace?: NodeWorkspace, environment?: Readonly<Record<string, string>>): Promise<RunnerProfile>;
|
|
32
|
+
private fetchProfile;
|
|
33
|
+
private profileCacheKey;
|
|
34
|
+
private environmentFingerprint;
|
|
30
35
|
available(capabilities: NodeCapabilities): boolean;
|
|
31
36
|
protected profileForValidation(): RunnerProfile;
|
|
32
|
-
supportsConfiguration(configuration: RunnerDefaultConfiguration, workspace?: NodeWorkspace): boolean;
|
|
33
|
-
defaultConfiguration(workspace?: NodeWorkspace): RunnerDefaultConfiguration;
|
|
37
|
+
supportsConfiguration(configuration: RunnerDefaultConfiguration, workspace?: NodeWorkspace, environment?: Readonly<Record<string, string>>): boolean;
|
|
38
|
+
defaultConfiguration(workspace?: NodeWorkspace, environment?: Readonly<Record<string, string>>): RunnerDefaultConfiguration;
|
|
39
|
+
private cachedModels;
|
|
34
40
|
mcpConfiguration(raw: unknown, secrets: Readonly<Record<string, string>>): unknown;
|
|
35
41
|
discoverSessions(context: RunnerDiscoveryContext, workspace?: NodeWorkspace): Promise<readonly NodeAgentSession[]>;
|
|
36
42
|
resumeExternal(external: NodeAgentSession, context: ExternalResumeContext): Promise<ExternalResumeResult>;
|
|
@@ -42,6 +48,7 @@ export declare class OpenCodeRunner extends AbstractRunner<'opencode'> {
|
|
|
42
48
|
readonly turns: readonly import("../database.js").NodeConversationTurn[];
|
|
43
49
|
readonly nextCursor: string | null;
|
|
44
50
|
} | undefined>;
|
|
51
|
+
readConversationHistory(readers: RunnerConversationHistoryReaders): Promise<RunnerConversationHistoryPage | undefined>;
|
|
45
52
|
managedRunForNativeTurn(nativeTurnId: string): string | undefined;
|
|
46
53
|
presentSession(session: NodeAgentSession, capabilities: NodeCapabilities, context: RunnerSessionPresentationContext): RunnerSessionPresentation;
|
|
47
54
|
renameNative(session: NodeAgentSession, input: {
|
|
@@ -5,6 +5,7 @@ import { AbstractRunner } from './abstract-runner.js';
|
|
|
5
5
|
import { isWithinWorkspace } from './codex/conversation-parser.js';
|
|
6
6
|
import { createHash } from 'node:crypto';
|
|
7
7
|
import { openCodeConversationPage } from './opencode/conversation-parser.js';
|
|
8
|
+
import { nodeLog } from '../operational.js';
|
|
8
9
|
const PROFILE_ENTRY_TTL_MS = 30 * 60_000;
|
|
9
10
|
export class OpenCodeRunner extends AbstractRunner {
|
|
10
11
|
client;
|
|
@@ -14,6 +15,8 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
14
15
|
modelsByWorkspace = new Map();
|
|
15
16
|
contextLimitsByWorkspace = new Map();
|
|
16
17
|
profileTimersByWorkspace = new Map();
|
|
18
|
+
profileCache = new Map();
|
|
19
|
+
profileRefreshes = new Map();
|
|
17
20
|
execution = new Map();
|
|
18
21
|
managedTurns = new Map();
|
|
19
22
|
environmentClients = new Map();
|
|
@@ -35,25 +38,79 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
35
38
|
if (capabilities.openCode?.available !== true || workspace === undefined) {
|
|
36
39
|
return this.profile(capabilities);
|
|
37
40
|
}
|
|
41
|
+
const cacheKey = this.profileCacheKey(workspace.path, environment);
|
|
42
|
+
const now = Date.now();
|
|
43
|
+
for (const [key, entry] of this.profileCache)
|
|
44
|
+
if (entry.expiresAt <= now)
|
|
45
|
+
this.profileCache.delete(key);
|
|
46
|
+
const cached = this.profileCache.get(cacheKey);
|
|
47
|
+
if (cached !== undefined) {
|
|
48
|
+
nodeLog('runner.opencode.profile.cache-hit', {
|
|
49
|
+
workspaceId: workspace.id,
|
|
50
|
+
models: cached.models.length,
|
|
51
|
+
remainingTtlMs: cached.expiresAt - now
|
|
52
|
+
});
|
|
53
|
+
this.modelsByWorkspace.set(workspace.path, cached.models);
|
|
54
|
+
this.contextLimitsByWorkspace.set(workspace.path, cached.contextLimits);
|
|
55
|
+
this.scheduleProfileExpiry(workspace.path);
|
|
56
|
+
return { ...this.profile(capabilities), models: cached.models };
|
|
57
|
+
}
|
|
58
|
+
const current = this.profileRefreshes.get(cacheKey);
|
|
59
|
+
if (current !== undefined) {
|
|
60
|
+
nodeLog('runner.opencode.profile.single-flight-joined', { workspaceId: workspace.id });
|
|
61
|
+
return current;
|
|
62
|
+
}
|
|
63
|
+
const refresh = this.fetchProfile(capabilities, workspace, environment, cacheKey).finally(() => {
|
|
64
|
+
if (this.profileRefreshes.get(cacheKey) === refresh)
|
|
65
|
+
this.profileRefreshes.delete(cacheKey);
|
|
66
|
+
});
|
|
67
|
+
this.profileRefreshes.set(cacheKey, refresh);
|
|
68
|
+
return refresh;
|
|
69
|
+
}
|
|
70
|
+
async fetchProfile(capabilities, workspace, environment, cacheKey) {
|
|
38
71
|
const client = this.managedClient(environment);
|
|
72
|
+
const startedAt = performance.now();
|
|
39
73
|
try {
|
|
40
74
|
const catalog = await client.providers(workspace.path);
|
|
41
75
|
const models = openCodeProfileModels(catalog);
|
|
76
|
+
const contextLimits = openCodeContextLimits(catalog);
|
|
42
77
|
this.modelsByWorkspace.set(workspace.path, models);
|
|
43
|
-
this.contextLimitsByWorkspace.set(workspace.path,
|
|
78
|
+
this.contextLimitsByWorkspace.set(workspace.path, contextLimits);
|
|
79
|
+
this.profileCache.set(cacheKey, {
|
|
80
|
+
expiresAt: Date.now() + PROFILE_ENTRY_TTL_MS,
|
|
81
|
+
workspacePath: workspace.path,
|
|
82
|
+
environmentFingerprint: this.environmentFingerprint(environment),
|
|
83
|
+
models,
|
|
84
|
+
contextLimits
|
|
85
|
+
});
|
|
44
86
|
this.scheduleProfileExpiry(workspace.path);
|
|
87
|
+
nodeLog('runner.opencode.profile.providers.completed', {
|
|
88
|
+
workspaceId: workspace.id,
|
|
89
|
+
models: models.length,
|
|
90
|
+
durationMs: Math.round(performance.now() - startedAt)
|
|
91
|
+
});
|
|
45
92
|
return { ...this.profile(capabilities), models };
|
|
46
93
|
}
|
|
47
94
|
catch {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
95
|
+
nodeLog('runner.opencode.profile.providers.failed', {
|
|
96
|
+
workspaceId: workspace.id,
|
|
97
|
+
durationMs: Math.round(performance.now() - startedAt)
|
|
98
|
+
});
|
|
51
99
|
}
|
|
52
100
|
finally {
|
|
53
101
|
this.releaseManagedClient(client);
|
|
54
102
|
}
|
|
55
103
|
return this.profile(capabilities);
|
|
56
104
|
}
|
|
105
|
+
profileCacheKey(workspacePath, environment) {
|
|
106
|
+
return createHash('sha256')
|
|
107
|
+
.update(JSON.stringify({ workspacePath, environment: this.environmentFingerprint(environment) }))
|
|
108
|
+
.digest('hex');
|
|
109
|
+
}
|
|
110
|
+
environmentFingerprint(environment) {
|
|
111
|
+
const entries = Object.entries(environment).sort(([left], [right]) => left.localeCompare(right));
|
|
112
|
+
return createHash('sha256').update(JSON.stringify(entries)).digest('hex');
|
|
113
|
+
}
|
|
57
114
|
available(capabilities) {
|
|
58
115
|
return capabilities.openCode?.available === true;
|
|
59
116
|
}
|
|
@@ -68,22 +125,18 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
68
125
|
openCode: { available: true }
|
|
69
126
|
});
|
|
70
127
|
}
|
|
71
|
-
supportsConfiguration(configuration, workspace) {
|
|
128
|
+
supportsConfiguration(configuration, workspace, environment = {}) {
|
|
72
129
|
if (configuration.runner !== this.name)
|
|
73
130
|
return false;
|
|
74
|
-
const models = workspace
|
|
75
|
-
? [...this.modelsByWorkspace.values()].flat()
|
|
76
|
-
: (this.modelsByWorkspace.get(workspace.path) ?? []);
|
|
131
|
+
const models = this.cachedModels(workspace, environment);
|
|
77
132
|
const model = models.find((candidate) => candidate.id === configuration.model);
|
|
78
133
|
return (model !== undefined &&
|
|
79
134
|
(model.supportedEfforts.length === 0 ||
|
|
80
135
|
model.supportedEfforts.includes(configuration.effort)) &&
|
|
81
136
|
this.profileForValidation().accessOptions.some((candidate) => candidate.id === configuration.access));
|
|
82
137
|
}
|
|
83
|
-
defaultConfiguration(workspace) {
|
|
84
|
-
const model = workspace
|
|
85
|
-
? this.modelsByWorkspace.values().next().value?.[0]
|
|
86
|
-
: this.modelsByWorkspace.get(workspace.path)?.[0];
|
|
138
|
+
defaultConfiguration(workspace, environment = {}) {
|
|
139
|
+
const model = this.cachedModels(workspace, environment)[0];
|
|
87
140
|
return {
|
|
88
141
|
runner: this.name,
|
|
89
142
|
model: model?.id ?? '',
|
|
@@ -91,6 +144,15 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
91
144
|
access: 'default'
|
|
92
145
|
};
|
|
93
146
|
}
|
|
147
|
+
cachedModels(workspace, environment) {
|
|
148
|
+
const fingerprint = this.environmentFingerprint(environment);
|
|
149
|
+
const now = Date.now();
|
|
150
|
+
return [...this.profileCache.values()]
|
|
151
|
+
.filter((entry) => entry.expiresAt > now &&
|
|
152
|
+
entry.environmentFingerprint === fingerprint &&
|
|
153
|
+
(workspace === undefined || entry.workspacePath === workspace.path))
|
|
154
|
+
.flatMap((entry) => entry.models);
|
|
155
|
+
}
|
|
94
156
|
mcpConfiguration(raw, secrets) {
|
|
95
157
|
const servers = super.mcpConfiguration(raw, secrets);
|
|
96
158
|
return Object.fromEntries(servers.map((server) => [
|
|
@@ -121,7 +183,9 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
121
183
|
}
|
|
122
184
|
for (const value of sessions) {
|
|
123
185
|
const session = openCodeSession(value);
|
|
124
|
-
if (session === undefined ||
|
|
186
|
+
if (session === undefined ||
|
|
187
|
+
session.parentId !== undefined ||
|
|
188
|
+
!isWithinWorkspace(session.directory, target.path))
|
|
125
189
|
continue;
|
|
126
190
|
result.push(context.createProjection({
|
|
127
191
|
workspace: target,
|
|
@@ -177,6 +241,10 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
177
241
|
return undefined;
|
|
178
242
|
}
|
|
179
243
|
}
|
|
244
|
+
async readConversationHistory(readers) {
|
|
245
|
+
const official = await readers.official();
|
|
246
|
+
return official === undefined ? undefined : { ...official, source: 'official' };
|
|
247
|
+
}
|
|
180
248
|
managedRunForNativeTurn(nativeTurnId) {
|
|
181
249
|
return this.managedTurns.get(nativeTurnId);
|
|
182
250
|
}
|
|
@@ -286,6 +354,8 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
286
354
|
for (const timer of this.profileTimersByWorkspace.values())
|
|
287
355
|
clearTimeout(timer);
|
|
288
356
|
this.profileTimersByWorkspace.clear();
|
|
357
|
+
this.profileCache.clear();
|
|
358
|
+
this.profileRefreshes.clear();
|
|
289
359
|
this.modelsByWorkspace.clear();
|
|
290
360
|
this.contextLimitsByWorkspace.clear();
|
|
291
361
|
const stopping = [
|
|
@@ -370,6 +440,9 @@ function openCodeSession(value) {
|
|
|
370
440
|
id: record.id,
|
|
371
441
|
directory: record.directory,
|
|
372
442
|
title: record.title,
|
|
373
|
-
updatedAt: typeof time?.updated === 'number' ? time.updated : 0
|
|
443
|
+
updatedAt: typeof time?.updated === 'number' ? time.updated : 0,
|
|
444
|
+
...(typeof record.parentID === 'string' && record.parentID.length > 0
|
|
445
|
+
? { parentId: record.parentID }
|
|
446
|
+
: {})
|
|
374
447
|
};
|
|
375
448
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { nodeLog } from '../operational.js';
|
|
1
2
|
export class RunnerRegistry {
|
|
2
3
|
runners = new Map();
|
|
3
4
|
constructor(runners = []) {
|
|
@@ -35,7 +36,21 @@ export class RunnerRegistry {
|
|
|
35
36
|
});
|
|
36
37
|
}
|
|
37
38
|
async refreshProfiles(capabilities, workspace, environment = {}) {
|
|
38
|
-
const profiles = await Promise.all(this.advertised().map((runner) =>
|
|
39
|
+
const profiles = await Promise.all(this.advertised().map(async (runner) => {
|
|
40
|
+
const startedAt = performance.now();
|
|
41
|
+
try {
|
|
42
|
+
return await runner.refreshProfile(capabilities, workspace, environment);
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
const durationMs = Math.round(performance.now() - startedAt);
|
|
46
|
+
if (durationMs >= 100)
|
|
47
|
+
nodeLog('runner.profile.refresh.completed', {
|
|
48
|
+
runner: runner.name,
|
|
49
|
+
workspaceId: workspace?.id,
|
|
50
|
+
durationMs
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}));
|
|
39
54
|
return profiles.flatMap((profile) => (profile === undefined ? [] : [profile]));
|
|
40
55
|
}
|
|
41
56
|
supportsConfiguration(configuration, workspace, environment) {
|
|
@@ -50,18 +50,13 @@ export function normalizeVersion(id, value) {
|
|
|
50
50
|
}
|
|
51
51
|
async function executeVersion(command, args) {
|
|
52
52
|
const executable = process.platform === 'win32' ? process.env['ComSpec'] || 'cmd.exe' : command;
|
|
53
|
-
const commandArgs = process.platform === 'win32'
|
|
54
|
-
? ['/d', '/s', '/c', [command, ...args].map(quoteWindowsArgument).join(' ')]
|
|
55
|
-
: [...args];
|
|
53
|
+
const commandArgs = process.platform === 'win32' ? ['/d', '/s', '/c', [command, ...args].join(' ')] : [...args];
|
|
56
54
|
return execFileAsync(executable, commandArgs, {
|
|
57
55
|
timeout: 5_000,
|
|
58
56
|
maxBuffer: 64 * 1024,
|
|
59
57
|
windowsHide: true
|
|
60
58
|
});
|
|
61
59
|
}
|
|
62
|
-
function quoteWindowsArgument(value) {
|
|
63
|
-
return `"${value.replaceAll('"', '""')}"`;
|
|
64
|
-
}
|
|
65
60
|
async function resolveCommandPath(command) {
|
|
66
61
|
try {
|
|
67
62
|
const resolver = process.platform === 'win32' ? 'where.exe' : 'which';
|
package/dist/runtime-state.d.ts
CHANGED
|
@@ -86,9 +86,11 @@ export declare class NodeRuntimeState {
|
|
|
86
86
|
*/
|
|
87
87
|
setRunnerTitleFromNative(id: string, title: string): NodeAgentSession;
|
|
88
88
|
createMessageRun(input: {
|
|
89
|
+
readonly runId?: string;
|
|
89
90
|
readonly sessionId: string;
|
|
90
91
|
readonly clientMessageId: string;
|
|
91
92
|
readonly content: string;
|
|
93
|
+
readonly initiatedByUserId?: number;
|
|
92
94
|
readonly attachments?: readonly NodeMessageAttachmentInput[];
|
|
93
95
|
}): {
|
|
94
96
|
readonly run: NodeAgentRun;
|
package/dist/runtime-state.js
CHANGED
|
@@ -255,7 +255,7 @@ export class NodeRuntimeState {
|
|
|
255
255
|
const session = this.requireSession(input.sessionId);
|
|
256
256
|
const now = this.now();
|
|
257
257
|
const run = {
|
|
258
|
-
id: randomUUID(),
|
|
258
|
+
id: input.runId ?? randomUUID(),
|
|
259
259
|
sessionId: session.id,
|
|
260
260
|
nodeId: this.nodeId(),
|
|
261
261
|
workspaceId: session.workspaceId,
|
|
@@ -264,6 +264,9 @@ export class NodeRuntimeState {
|
|
|
264
264
|
recoveryState: 'ACTIVE',
|
|
265
265
|
version: 0,
|
|
266
266
|
clientMessageId: input.clientMessageId,
|
|
267
|
+
...(input.initiatedByUserId === undefined
|
|
268
|
+
? {}
|
|
269
|
+
: { initiatedByUserId: input.initiatedByUserId }),
|
|
267
270
|
createdAt: now,
|
|
268
271
|
updatedAt: now
|
|
269
272
|
};
|
|
@@ -388,6 +391,7 @@ export class NodeRuntimeState {
|
|
|
388
391
|
? { ...item, payload: { ...item.payload, text: content } }
|
|
389
392
|
: item)
|
|
390
393
|
}));
|
|
394
|
+
this.bumpQueueVersion(run.sessionId);
|
|
391
395
|
return run;
|
|
392
396
|
}
|
|
393
397
|
deleteQueuedRun(runId) {
|
|
@@ -471,15 +475,16 @@ export class NodeRuntimeState {
|
|
|
471
475
|
}
|
|
472
476
|
listConversationTurns(input) {
|
|
473
477
|
this.requireSession(input.sessionId);
|
|
474
|
-
//
|
|
475
|
-
//
|
|
476
|
-
//
|
|
477
|
-
//
|
|
478
|
+
// A managed Turn keeps the user's acceptance time as its stable timeline
|
|
479
|
+
// position. Runner start/completion timestamps must not move it behind a
|
|
480
|
+
// message that was accepted later. Native Turns without a user timestamp
|
|
481
|
+
// fall back to their own lifecycle time.
|
|
478
482
|
const all = [...(this.turns.get(input.sessionId) ?? [])]
|
|
479
483
|
.map((turn, index) => ({ turn, index }))
|
|
480
484
|
.sort((a, b) => {
|
|
481
|
-
const timestamp = (value) => value.startedAt ??
|
|
482
|
-
value.
|
|
485
|
+
const timestamp = (value) => value.items.find((item) => item.id === value.userItemId)?.startedAt ??
|
|
486
|
+
value.startedAt ??
|
|
487
|
+
value.completedAt ??
|
|
483
488
|
0;
|
|
484
489
|
return timestamp(a.turn) - timestamp(b.turn) || a.index - b.index;
|
|
485
490
|
})
|
|
@@ -5,6 +5,10 @@ import type { RunnerRegistry } from '../runner/runner-registry.js';
|
|
|
5
5
|
import { type ConversationHistoryPage } from '../util/runner-native-session-parsers.js';
|
|
6
6
|
import type { RunAttachmentService } from './run-attachment-service.js';
|
|
7
7
|
export declare function hasManagedActiveRun(runtime: NodeRuntimeState, session: NodeAgentSession): boolean;
|
|
8
|
+
export declare function convergeConversationWatchPage(previous: ConversationHistoryPage | undefined, previousObserved: ConversationHistoryPage | undefined, next: ConversationHistoryPage, previousAuthority: unknown): {
|
|
9
|
+
readonly page: ConversationHistoryPage;
|
|
10
|
+
readonly authority: ConversationHistoryPage['source'];
|
|
11
|
+
};
|
|
8
12
|
interface ConversationHistoryServiceOptions {
|
|
9
13
|
readonly runtime: NodeRuntimeState;
|
|
10
14
|
readonly runners: RunnerRegistry;
|
|
@@ -16,18 +20,23 @@ interface ConversationHistoryServiceOptions {
|
|
|
16
20
|
}
|
|
17
21
|
export declare class ConversationHistoryService {
|
|
18
22
|
private readonly options;
|
|
23
|
+
private readonly activeHistoryReads;
|
|
19
24
|
constructor(options: ConversationHistoryServiceOptions);
|
|
20
25
|
read(session: NodeAgentSession, input: {
|
|
21
26
|
readonly cursor?: string;
|
|
22
27
|
readonly limit?: number;
|
|
23
28
|
}): Promise<ConversationHistoryPage>;
|
|
29
|
+
private readRunnerHistory;
|
|
30
|
+
private readManagedActive;
|
|
31
|
+
private prefetchActiveHistory;
|
|
32
|
+
private takeActiveHistoryRead;
|
|
24
33
|
refreshExternalActivity(session: NodeAgentSession): Promise<void>;
|
|
25
34
|
readNative(session: NodeAgentSession): Promise<import("../native-session-history.js").NativeSessionHistory | undefined>;
|
|
26
35
|
private attachNativeImages;
|
|
27
36
|
readOfficial(session: NodeAgentSession, input: {
|
|
28
37
|
readonly cursor?: string;
|
|
29
38
|
readonly limit?: number;
|
|
30
|
-
}): Promise<import("../runner/abstract-runner.js").
|
|
39
|
+
}): Promise<import("../runner/abstract-runner.js").RunnerConversationPage | undefined>;
|
|
31
40
|
private managedRunnerTurn;
|
|
32
41
|
private page;
|
|
33
42
|
}
|