@myagentroam/node 0.9.2 → 0.9.4
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/codex-app-server.d.ts +24 -0
- package/dist/codex-app-server.js +100 -5
- package/dist/connector.js +18 -15
- package/dist/control-outbound-scheduler.d.ts +4 -1
- package/dist/control-outbound-scheduler.js +39 -6
- package/dist/database.d.ts +2 -19
- package/dist/database.js +1 -62
- package/dist/event-buffer.d.ts +2 -5
- package/dist/event-buffer.js +3 -12
- package/dist/native-session-history.js +33 -12
- package/dist/runner/claude/managed-run-controller.d.ts +0 -1
- package/dist/runner/claude/managed-run-controller.js +17 -12
- package/dist/runner/codex/conversation-parser.d.ts +1 -1
- package/dist/runner/codex/conversation-parser.js +3 -0
- package/dist/runner/codex/managed-run-controller.d.ts +11 -2
- package/dist/runner/codex/managed-run-controller.js +79 -24
- package/dist/runner/codex-runner.d.ts +3 -0
- package/dist/runner/codex-runner.js +42 -3
- package/dist/runner/opencode/conversation-parser.js +1 -1
- package/dist/runner/opencode/managed-run-controller.d.ts +7 -2
- package/dist/runner/opencode/managed-run-controller.js +72 -14
- package/dist/runner/opencode-runner.d.ts +3 -0
- package/dist/runner/opencode-runner.js +25 -0
- package/dist/runner-profiles.js +10 -6
- package/dist/runtime-state.d.ts +7 -12
- package/dist/runtime-state.js +43 -53
- package/dist/service/attachment-domain-state.d.ts +2 -0
- package/dist/service/attachment-domain-state.js +2 -0
- package/dist/service/conversation-history-service.d.ts +8 -0
- package/dist/service/conversation-history-service.js +181 -9
- package/dist/service/conversation-segment-service.js +17 -10
- package/dist/service/external-session-resume-service.js +9 -0
- package/dist/service/fake-managed-run-service.d.ts +0 -1
- package/dist/service/fake-managed-run-service.js +0 -2
- package/dist/service/native-session-projection-service.js +5 -0
- package/dist/service/native-session-watch-service.d.ts +8 -2
- package/dist/service/native-session-watch-service.js +28 -10
- package/dist/service/node-connection-lifecycle-service.d.ts +0 -2
- package/dist/service/node-connection-lifecycle-service.js +0 -1
- package/dist/service/node-control-channel.js +1 -1
- package/dist/service/node-control-message-service.d.ts +0 -1
- package/dist/service/node-control-message-service.js +9 -6
- package/dist/service/node-request-service.js +2 -1
- package/dist/service/node-workspace-coordinator.d.ts +1 -4
- package/dist/service/node-workspace-coordinator.js +2 -12
- package/dist/service/run-attachment-service.js +30 -6
- package/dist/service/run-event-service.d.ts +1 -0
- package/dist/service/run-event-service.js +80 -0
- package/dist/service/run-workbench-service.d.ts +1 -1
- package/dist/service/run-workbench-service.js +1 -5
- package/dist/service/runner-interaction-service.d.ts +1 -2
- package/dist/service/runner-interaction-service.js +1 -4
- package/dist/service/session-context-service.d.ts +1 -0
- package/dist/service/session-context-service.js +14 -0
- package/dist/service/session-domain-state.d.ts +1 -0
- package/dist/service/session-domain-state.js +1 -0
- package/dist/service/session-lifecycle-service.js +4 -12
- package/dist/service/session-message-service.d.ts +1 -0
- package/dist/service/session-message-service.js +109 -85
- package/dist/service/skill-directory-service.d.ts +3 -1
- package/dist/service/skill-directory-service.js +28 -4
- package/dist/service/skill-node-operation-service.d.ts +1 -1
- package/dist/service/skill-node-operation-service.js +4 -2
- package/dist/service/workbench-event-service.d.ts +1 -13
- package/dist/service/workbench-event-service.js +2 -36
- package/dist/service/workbench-manifest-service.d.ts +0 -1
- package/dist/service/workbench-manifest-service.js +0 -1
- package/dist/service/workspace-change-service.js +1 -1
- package/dist/service/workspace-domain-state.d.ts +1 -0
- package/dist/service/workspace-queue-workbench-service.d.ts +13 -2
- package/dist/service/workspace-queue-workbench-service.js +8 -2
- package/dist/service/workspace-upload-service.d.ts +2 -0
- package/dist/service/workspace-upload-service.js +28 -6
- package/dist/service/workspace-workbench-service.d.ts +0 -3
- package/dist/service/workspace-workbench-service.js +0 -17
- package/dist/util/runner-error.d.ts +6 -0
- package/dist/util/runner-error.js +52 -0
- package/dist/util/runner-native-session-parsers.d.ts +2 -1
- package/dist/util/runner-native-session-parsers.js +63 -15
- package/dist/workspace.js +33 -8
- package/package.json +2 -2
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const MAX_RUNNER_ERROR_MESSAGE = 1000;
|
|
2
|
+
export function runnerErrorProjection(error, fallbackCode) {
|
|
3
|
+
const httpStatus = findHttpStatus(error);
|
|
4
|
+
const message = findMessage(error) ?? fallbackCode;
|
|
5
|
+
return {
|
|
6
|
+
code: httpStatus === null ? fallbackCode : `HTTP_${httpStatus}`,
|
|
7
|
+
message: message.slice(0, MAX_RUNNER_ERROR_MESSAGE),
|
|
8
|
+
httpStatus
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
function findHttpStatus(value, depth = 0) {
|
|
12
|
+
if (depth > 3 || value === null || typeof value !== 'object')
|
|
13
|
+
return null;
|
|
14
|
+
const record = value;
|
|
15
|
+
for (const key of ['status', 'statusCode', 'status_code', 'httpStatus', 'http_status']) {
|
|
16
|
+
const candidate = record[key];
|
|
17
|
+
if (((typeof candidate === 'number' && Number.isInteger(candidate)) ||
|
|
18
|
+
(typeof candidate === 'string' && /^\d{3}$/u.test(candidate))) &&
|
|
19
|
+
Number(candidate) >= 100 &&
|
|
20
|
+
Number(candidate) <= 599)
|
|
21
|
+
return Number(candidate);
|
|
22
|
+
}
|
|
23
|
+
const match = findMessage(value)?.match(/(?:^|\b(?:http(?:\s+status)?|status(?:\s+code)?|error)\s*[:=_-]?\s*)([1-5]\d{2})\b/iu);
|
|
24
|
+
if (match !== null && match !== undefined)
|
|
25
|
+
return Number(match[1]);
|
|
26
|
+
for (const key of ['error', 'cause', 'response', 'data']) {
|
|
27
|
+
const nested = findHttpStatus(record[key], depth + 1);
|
|
28
|
+
if (nested !== null)
|
|
29
|
+
return nested;
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
function findMessage(value, depth = 0) {
|
|
34
|
+
if (typeof value === 'string')
|
|
35
|
+
return value.trim() || undefined;
|
|
36
|
+
if (value instanceof Error && value.message.trim())
|
|
37
|
+
return value.message.trim();
|
|
38
|
+
if (depth > 3 || value === null || typeof value !== 'object')
|
|
39
|
+
return undefined;
|
|
40
|
+
const record = value;
|
|
41
|
+
for (const key of ['message', 'error_description', 'detail', 'result']) {
|
|
42
|
+
const candidate = record[key];
|
|
43
|
+
if (typeof candidate === 'string' && candidate.trim())
|
|
44
|
+
return candidate.trim();
|
|
45
|
+
}
|
|
46
|
+
for (const key of ['error', 'cause', 'response', 'data']) {
|
|
47
|
+
const nested = findMessage(record[key], depth + 1);
|
|
48
|
+
if (nested !== undefined)
|
|
49
|
+
return nested;
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
@@ -15,6 +15,7 @@ export interface ConversationHistoryPage {
|
|
|
15
15
|
readonly source: ConversationHistorySource;
|
|
16
16
|
readonly readAt: number;
|
|
17
17
|
readonly latestVisibleAt: number;
|
|
18
|
+
readonly deferredOlderHistory?: boolean;
|
|
18
19
|
}
|
|
19
20
|
export declare function extractId(result: unknown, key: 'thread' | 'turn'): string;
|
|
20
21
|
export declare function settleWithin<T>(promise: Promise<T>, milliseconds: number): Promise<T | undefined>;
|
|
@@ -50,7 +51,7 @@ export declare function nativeConversationPage(session: NodeAgentSession, histor
|
|
|
50
51
|
*/
|
|
51
52
|
export declare function nativeUserClientMessageId(entry: Extract<NativeSessionHistory['items'][number], {
|
|
52
53
|
readonly kind: 'message';
|
|
53
|
-
}>, createdAt: number, runtimeTurns: readonly NodeConversationTurn[]): string | null;
|
|
54
|
+
}>, createdAt: number | null, runtimeTurns: readonly NodeConversationTurn[]): string | null;
|
|
54
55
|
/**
|
|
55
56
|
* Normalize the documented App Server `thread/read(includeTurns: true)`
|
|
56
57
|
* result. Only items with a user-visible Workbench representation are kept;
|
|
@@ -146,23 +146,53 @@ export function deduplicateDirectSessions(sessions) {
|
|
|
146
146
|
export function nativeConversationPage(session, history, input, runtimeTurns = [], registerImages = () => []) {
|
|
147
147
|
const limit = Math.min(Math.max(input.limit ?? 30, 1), 500);
|
|
148
148
|
const nativeTurns = nativeTranscriptTurns(history.items);
|
|
149
|
+
const representedClientMessageIds = new Set(nativeTurns.flatMap((entries) => entries.flatMap(({ entry, index }) => {
|
|
150
|
+
if (entry.kind !== 'message' || entry.role !== 'USER')
|
|
151
|
+
return [];
|
|
152
|
+
const clientMessageId = nativeUserClientMessageId(entry, entry.createdAt ?? index, runtimeTurns);
|
|
153
|
+
return clientMessageId === null ? [] : [clientMessageId];
|
|
154
|
+
})));
|
|
155
|
+
const missingRuntimeErrorTurns = input.cursor === undefined
|
|
156
|
+
? runtimeTurns.filter((turn) => {
|
|
157
|
+
const clientMessageId = runtimeTurnClientMessageId(turn);
|
|
158
|
+
return (turn.items.some((item) => item.kind === 'error') &&
|
|
159
|
+
(clientMessageId === undefined || !representedClientMessageIds.has(clientMessageId)));
|
|
160
|
+
})
|
|
161
|
+
: [];
|
|
149
162
|
const end = nativePageEnd(input.cursor, session.id, nativeTurns.length);
|
|
150
163
|
const start = Math.max(0, end - limit);
|
|
151
|
-
const
|
|
164
|
+
const nativePageTurns = nativeTurns
|
|
152
165
|
.slice(start, end)
|
|
153
166
|
.map((entries, relativeIndex) => {
|
|
154
167
|
const firstIndex = entries[0]?.index ?? 0;
|
|
155
|
-
const
|
|
156
|
-
const
|
|
157
|
-
|
|
168
|
+
const nativeUser = entries.find(({ entry }) => entry.kind === 'message' && entry.role === 'USER')?.entry;
|
|
169
|
+
const matchedClientMessageId = nativeUser?.kind === 'message'
|
|
170
|
+
? nativeUserClientMessageId(nativeUser, nativeUser.createdAt, runtimeTurns)
|
|
171
|
+
: null;
|
|
172
|
+
const runtimeTurn = typeof matchedClientMessageId === 'string'
|
|
173
|
+
? runtimeTurns.find((turn) => runtimeTurnClientMessageId(turn) === matchedClientMessageId)
|
|
174
|
+
: undefined;
|
|
175
|
+
const turnId = runtimeTurn?.id ?? `${session.id}:native:${firstIndex}`;
|
|
176
|
+
const nativeItems = entries.map(({ entry, index }) => ({
|
|
177
|
+
...nativeTranscriptConversationItem(session, entry, index, turnId, runtimeTurns, registerImages),
|
|
178
|
+
runId: runtimeTurn?.runId ?? null
|
|
179
|
+
}));
|
|
180
|
+
const runtimeErrors = (runtimeTurn?.items ?? [])
|
|
181
|
+
.filter((item) => item.kind === 'error')
|
|
182
|
+
.map((item) => ({ ...item, turnId, runId: runtimeTurn?.runId ?? null }));
|
|
183
|
+
const items = [
|
|
184
|
+
...nativeItems,
|
|
185
|
+
...runtimeErrors.filter((error) => !nativeItems.some((item) => item.id === error.id))
|
|
186
|
+
];
|
|
187
|
+
const startedAt = items[0]?.startedAt ?? null;
|
|
158
188
|
const completedAt = items.at(-1)?.completedAt ?? startedAt;
|
|
159
189
|
const after = lastNativeItemId(entries);
|
|
160
190
|
return {
|
|
161
191
|
id: turnId,
|
|
162
192
|
sessionId: session.id,
|
|
163
|
-
runId: null,
|
|
193
|
+
runId: runtimeTurn?.runId ?? null,
|
|
164
194
|
userItemId: items.find((item) => item.kind === 'user_message')?.id ?? null,
|
|
165
|
-
status: 'SUCCEEDED',
|
|
195
|
+
status: runtimeErrors.length > 0 ? 'FAILED' : 'SUCCEEDED',
|
|
166
196
|
model: null,
|
|
167
197
|
effort: null,
|
|
168
198
|
access: null,
|
|
@@ -179,13 +209,24 @@ export function nativeConversationPage(session, history, input, runtimeTurns = [
|
|
|
179
209
|
completedAt
|
|
180
210
|
};
|
|
181
211
|
});
|
|
212
|
+
const combined = [...nativePageTurns, ...missingRuntimeErrorTurns];
|
|
213
|
+
const dropped = combined.slice(0, Math.max(0, combined.length - limit));
|
|
214
|
+
const turns = combined.slice(-limit);
|
|
215
|
+
const nativePageIds = new Set(nativePageTurns.map((turn) => turn.id));
|
|
216
|
+
const nextEnd = start + dropped.filter((turn) => nativePageIds.has(turn.id)).length;
|
|
182
217
|
return {
|
|
183
218
|
turns,
|
|
184
|
-
nextCursor:
|
|
185
|
-
? Buffer.from(JSON.stringify({ sessionId: session.id, end:
|
|
219
|
+
nextCursor: nextEnd > 0
|
|
220
|
+
? Buffer.from(JSON.stringify({ sessionId: session.id, end: nextEnd })).toString('base64url')
|
|
186
221
|
: null
|
|
187
222
|
};
|
|
188
223
|
}
|
|
224
|
+
function runtimeTurnClientMessageId(turn) {
|
|
225
|
+
const user = turn.items.find((item) => item.kind === 'user_message');
|
|
226
|
+
return isPlainRecord(user?.payload) && typeof user.payload.clientMessageId === 'string'
|
|
227
|
+
? user.payload.clientMessageId
|
|
228
|
+
: undefined;
|
|
229
|
+
}
|
|
189
230
|
function lastNativeItemId(entries) {
|
|
190
231
|
return entries.findLast(({ entry }) => entry.nativeId !== undefined)?.entry.nativeId;
|
|
191
232
|
}
|
|
@@ -204,7 +245,7 @@ function nativeTranscriptTurns(items) {
|
|
|
204
245
|
return turns;
|
|
205
246
|
}
|
|
206
247
|
function nativeTranscriptConversationItem(session, entry, index, turnId, runtimeTurns, registerImages) {
|
|
207
|
-
const time = entry.createdAt
|
|
248
|
+
const time = entry.createdAt;
|
|
208
249
|
const isToolCall = entry.kind === 'tool_call';
|
|
209
250
|
const isUnknown = entry.kind === 'unknown';
|
|
210
251
|
const isReasoning = entry.kind === 'reasoning_summary';
|
|
@@ -299,6 +340,7 @@ function nativeTranscriptConversationItem(session, entry, index, turnId, runtime
|
|
|
299
340
|
* runtime user messages by content and creation time so native history replaces the optimistic Turn.
|
|
300
341
|
*/
|
|
301
342
|
export function nativeUserClientMessageId(entry, createdAt, runtimeTurns) {
|
|
343
|
+
const candidates = [];
|
|
302
344
|
for (const turn of runtimeTurns) {
|
|
303
345
|
const user = turn.items.find((item) => item.kind === 'user_message');
|
|
304
346
|
if (user === undefined || !isPlainRecord(user.payload))
|
|
@@ -309,13 +351,19 @@ export function nativeUserClientMessageId(entry, createdAt, runtimeTurns) {
|
|
|
309
351
|
if (clientMessageId === null || payload.text !== stripClaudePlanTag(entry.text))
|
|
310
352
|
continue;
|
|
311
353
|
const runtimeCreatedAt = user.startedAt ?? turn.startedAt;
|
|
312
|
-
|
|
313
|
-
runtimeCreatedAt !== undefined &&
|
|
314
|
-
Math.abs(createdAt - runtimeCreatedAt) > 60_000)
|
|
315
|
-
continue;
|
|
316
|
-
return clientMessageId;
|
|
354
|
+
candidates.push({ clientMessageId, createdAt: runtimeCreatedAt ?? null });
|
|
317
355
|
}
|
|
318
|
-
|
|
356
|
+
if (createdAt === null)
|
|
357
|
+
return candidates.length === 1 ? candidates[0].clientMessageId : null;
|
|
358
|
+
const timed = candidates
|
|
359
|
+
.filter((candidate) => candidate.createdAt !== null)
|
|
360
|
+
.map((candidate) => ({
|
|
361
|
+
...candidate,
|
|
362
|
+
distance: Math.abs(createdAt - candidate.createdAt)
|
|
363
|
+
}))
|
|
364
|
+
.filter((candidate) => candidate.distance <= 60_000)
|
|
365
|
+
.sort((left, right) => left.distance - right.distance);
|
|
366
|
+
return timed[0]?.clientMessageId ?? null;
|
|
319
367
|
}
|
|
320
368
|
/**
|
|
321
369
|
* Normalize the documented App Server `thread/read(includeTurns: true)`
|
package/dist/workspace.js
CHANGED
|
@@ -1232,14 +1232,7 @@ export async function readCurrentChanges(workspacePath) {
|
|
|
1232
1232
|
export async function readCurrentChangeDiff(workspacePath, requestedPath) {
|
|
1233
1233
|
const path = safeGitWorkspacePath(requestedPath);
|
|
1234
1234
|
await assertCurrentChangePathAccessible(workspacePath, path);
|
|
1235
|
-
const result = await
|
|
1236
|
-
'diff',
|
|
1237
|
-
'--no-ext-diff',
|
|
1238
|
-
'--no-textconv',
|
|
1239
|
-
'HEAD',
|
|
1240
|
-
'--',
|
|
1241
|
-
`:(literal)${path}`
|
|
1242
|
-
]);
|
|
1235
|
+
const result = await readCurrentChangeGitDiff(workspacePath, path);
|
|
1243
1236
|
const after = await readWorkingTreeText(workspacePath, path);
|
|
1244
1237
|
const binary = result.output.includes(0) || result.text.includes('Binary files ') || after?.binary === true;
|
|
1245
1238
|
if (binary) {
|
|
@@ -1263,6 +1256,38 @@ export async function readCurrentChangeDiff(workspacePath, requestedPath) {
|
|
|
1263
1256
|
...(after === undefined ? {} : { afterTruncated: after.truncated })
|
|
1264
1257
|
};
|
|
1265
1258
|
}
|
|
1259
|
+
async function readCurrentChangeGitDiff(workspacePath, path) {
|
|
1260
|
+
const untracked = await runGit(workspacePath, [
|
|
1261
|
+
'ls-files',
|
|
1262
|
+
'--others',
|
|
1263
|
+
'--exclude-standard',
|
|
1264
|
+
'-z',
|
|
1265
|
+
'--',
|
|
1266
|
+
`:(literal)${path}`
|
|
1267
|
+
]);
|
|
1268
|
+
if (untracked.text.split('\0').includes(path)) {
|
|
1269
|
+
const result = await runGitAllowFailure(workspacePath, [
|
|
1270
|
+
'diff',
|
|
1271
|
+
'--no-index',
|
|
1272
|
+
'--no-ext-diff',
|
|
1273
|
+
'--no-textconv',
|
|
1274
|
+
'--',
|
|
1275
|
+
'/dev/null',
|
|
1276
|
+
path
|
|
1277
|
+
]);
|
|
1278
|
+
if (result.code !== 0 && result.code !== 1)
|
|
1279
|
+
throw new GitCommandError(result.code, result.stderr);
|
|
1280
|
+
return result;
|
|
1281
|
+
}
|
|
1282
|
+
return runGit(workspacePath, [
|
|
1283
|
+
'diff',
|
|
1284
|
+
'--no-ext-diff',
|
|
1285
|
+
'--no-textconv',
|
|
1286
|
+
'HEAD',
|
|
1287
|
+
'--',
|
|
1288
|
+
`:(literal)${path}`
|
|
1289
|
+
]);
|
|
1290
|
+
}
|
|
1266
1291
|
/** Current Changes must not expose an external link. */
|
|
1267
1292
|
export async function isWorkspaceChangeVisible(workspacePath, requestedPath) {
|
|
1268
1293
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/node",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"description": "MyAgentRoam Node runtime CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"node-pty": "1.1.0",
|
|
25
25
|
"ws": "^8.21.3",
|
|
26
26
|
"zod": "4.4.3",
|
|
27
|
-
"@myagentroam/protocol": "^0.9.
|
|
27
|
+
"@myagentroam/protocol": "^0.9.4"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/ws": "^8.18.1"
|