@myagentroam/node 0.9.154 → 0.9.155
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/connector.js
CHANGED
|
@@ -717,8 +717,9 @@ export class NodeConnector {
|
|
|
717
717
|
});
|
|
718
718
|
this.runWorkbenchService = new RunWorkbenchService({
|
|
719
719
|
runtime: this.runtime,
|
|
720
|
-
readImage: async (runId,
|
|
721
|
-
|
|
720
|
+
readImage: async (runId, selector) => typeof selector === 'number'
|
|
721
|
+
? this.runAttachmentService.read(runId, selector)
|
|
722
|
+
: this.runAttachmentService.readNative(runId, selector),
|
|
722
723
|
respondUserInput: (runId, requestId, answers) => this.runnerInteractionService.respondUserInput(runId, requestId, answers),
|
|
723
724
|
pauseQueue: (sessionId) => this.workspaceQueueWorkbenchService.pauseSessionQueue(sessionId),
|
|
724
725
|
runInterrupted: (sessionId) => {
|
|
@@ -1556,8 +1557,7 @@ export class NodeConnector {
|
|
|
1556
1557
|
emitWatchEvent: (payload) => this.send('watch.event', payload),
|
|
1557
1558
|
nextWorkbenchEvent: (payload) => this.workbenchEventService.next('hosted-conversation', payload),
|
|
1558
1559
|
emitWorkbenchEvent: (event) => this.workbenchEventService.publish(event),
|
|
1559
|
-
readImage:
|
|
1560
|
-
(await this.runAttachmentService.readNative(runId, imageIndex)),
|
|
1560
|
+
readImage: (runId, imageRef) => this.runAttachmentService.readNative(runId, imageRef),
|
|
1561
1561
|
processExecutorFactory: (input) => new BubblewrapSandboxExecutor({
|
|
1562
1562
|
profile: hostedConversationSandboxProfile(input)
|
|
1563
1563
|
}),
|
|
@@ -879,7 +879,7 @@ export class HostedConversationNodeService {
|
|
|
879
879
|
this.options.store.requireConversation(payload.userId, input.conversationId);
|
|
880
880
|
if (input.runId !== hostedConversationImageRunId(input.conversationId))
|
|
881
881
|
throw new Error('HOSTED_CONVERSATION_NOT_AUTHORIZED');
|
|
882
|
-
const image = await this.options.readImage(input.runId, input.
|
|
882
|
+
const image = await this.options.readImage(input.runId, input.imageRef);
|
|
883
883
|
if (image === undefined)
|
|
884
884
|
throw new Error('RUN_IMAGE_NOT_FOUND');
|
|
885
885
|
return { image };
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
1
2
|
import { tmpdir } from 'node:os';
|
|
2
3
|
import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
3
4
|
import { lstat, mkdir, mkdtemp, readFile, realpath, rm, writeFile } from 'node:fs/promises';
|
|
5
|
+
import { imageRefSchema } from '@myagentroam/protocol';
|
|
4
6
|
import { AttachmentDomainState } from './attachment-domain-state.js';
|
|
5
7
|
const MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024;
|
|
6
8
|
const IMAGE_CACHE_TTL_MS = 60 * 60_000;
|
|
7
|
-
const
|
|
9
|
+
const NATIVE_IMAGE_SOURCE_TTL_MS = 60 * 60_000;
|
|
8
10
|
export class RunAttachmentService {
|
|
9
11
|
nativeImageRoots;
|
|
10
12
|
state = new AttachmentDomainState();
|
|
@@ -140,7 +142,7 @@ export class RunAttachmentService {
|
|
|
140
142
|
}
|
|
141
143
|
registerNativeImages(runId, nativeRoots, images, options = {}) {
|
|
142
144
|
const roots = nativeRoots.map((root) => resolve(root));
|
|
143
|
-
const sources = this.state.nativeHistoryImages.get(runId) ??
|
|
145
|
+
const sources = this.state.nativeHistoryImages.get(runId) ?? new Map();
|
|
144
146
|
const attachments = [];
|
|
145
147
|
for (const image of images) {
|
|
146
148
|
const cached = options.reuseCachedRunImages === false || image.localPath === undefined
|
|
@@ -157,7 +159,11 @@ export class RunAttachmentService {
|
|
|
157
159
|
attachments.push({ name: image.name, mime: image.mime });
|
|
158
160
|
continue;
|
|
159
161
|
}
|
|
160
|
-
|
|
162
|
+
const imageRef = nativeImageReference('reader', image.sourceId);
|
|
163
|
+
if (imageRef === undefined) {
|
|
164
|
+
attachments.push({ name: image.name, mime: image.mime });
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
161
167
|
const source = {
|
|
162
168
|
kind: 'reader',
|
|
163
169
|
name: image.name,
|
|
@@ -166,18 +172,13 @@ export class RunAttachmentService {
|
|
|
166
172
|
sourceId: image.sourceId,
|
|
167
173
|
read: image.read
|
|
168
174
|
};
|
|
169
|
-
|
|
170
|
-
imageIndex = sources.length;
|
|
171
|
-
sources.push(source);
|
|
172
|
-
}
|
|
173
|
-
else
|
|
174
|
-
sources[imageIndex] = source;
|
|
175
|
+
sources.set(imageRef, source);
|
|
175
176
|
attachments.push({
|
|
176
177
|
name: image.name,
|
|
177
178
|
mime: image.mime,
|
|
178
179
|
...(image.byteSize === undefined ? {} : { byteSize: image.byteSize }),
|
|
179
180
|
runId,
|
|
180
|
-
|
|
181
|
+
imageRef
|
|
181
182
|
});
|
|
182
183
|
continue;
|
|
183
184
|
}
|
|
@@ -198,14 +199,24 @@ export class RunAttachmentService {
|
|
|
198
199
|
attachments.push({ name: image.name, mime: image.mime });
|
|
199
200
|
continue;
|
|
200
201
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
202
|
+
// Derive identity from the original source, never its registration position.
|
|
203
|
+
// The path digest hides physical paths; it is not a content/version hash.
|
|
204
|
+
const imageRef = nativeImageReference('file', image.sourceId === undefined
|
|
205
|
+
? createHash('sha256').update(path).digest('hex')
|
|
206
|
+
: image.sourceId);
|
|
207
|
+
if (imageRef === undefined) {
|
|
208
|
+
attachments.push({ name: image.name, mime: image.mime });
|
|
209
|
+
continue;
|
|
205
210
|
}
|
|
206
|
-
|
|
211
|
+
const previous = sources.get(imageRef);
|
|
212
|
+
if (previous !== undefined && (previous.kind !== 'file' || previous.path !== path)) {
|
|
213
|
+
attachments.push({ name: image.name, mime: image.mime });
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
sources.set(imageRef, { kind: 'file', name: image.name, mime: image.mime, path, root });
|
|
217
|
+
attachments.push({ name: image.name, mime: image.mime, runId, imageRef });
|
|
207
218
|
}
|
|
208
|
-
if (sources.
|
|
219
|
+
if (sources.size > 0) {
|
|
209
220
|
this.state.nativeHistoryImages.set(runId, sources);
|
|
210
221
|
const previousTimer = this.state.nativeHistoryImageTimers.get(runId);
|
|
211
222
|
if (previousTimer !== undefined)
|
|
@@ -213,7 +224,7 @@ export class RunAttachmentService {
|
|
|
213
224
|
const timer = setTimeout(() => {
|
|
214
225
|
this.state.nativeHistoryImageTimers.delete(runId);
|
|
215
226
|
this.state.nativeHistoryImages.delete(runId);
|
|
216
|
-
},
|
|
227
|
+
}, NATIVE_IMAGE_SOURCE_TTL_MS);
|
|
217
228
|
timer.unref();
|
|
218
229
|
this.state.nativeHistoryImageTimers.set(runId, timer);
|
|
219
230
|
}
|
|
@@ -242,8 +253,8 @@ export class RunAttachmentService {
|
|
|
242
253
|
}
|
|
243
254
|
return undefined;
|
|
244
255
|
}
|
|
245
|
-
async readNative(runId,
|
|
246
|
-
const source = this.state.nativeHistoryImages.get(runId)?.
|
|
256
|
+
async readNative(runId, imageRef) {
|
|
257
|
+
const source = this.state.nativeHistoryImages.get(runId)?.get(imageRef);
|
|
247
258
|
if (source === undefined)
|
|
248
259
|
return undefined;
|
|
249
260
|
try {
|
|
@@ -308,6 +319,15 @@ export class RunAttachmentService {
|
|
|
308
319
|
this.state.nativeHistoryImages.clear();
|
|
309
320
|
}
|
|
310
321
|
}
|
|
322
|
+
function nativeImageReference(kind, identity) {
|
|
323
|
+
try {
|
|
324
|
+
const reference = `${kind}:${encodeURIComponent(identity)}`;
|
|
325
|
+
return imageRefSchema.safeParse(reference).success ? reference : undefined;
|
|
326
|
+
}
|
|
327
|
+
catch {
|
|
328
|
+
return undefined;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
311
331
|
function canonicalBase64(value) {
|
|
312
332
|
if (value.length === 0)
|
|
313
333
|
return false;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { runImageReadInputSchema } from '@myagentroam/protocol';
|
|
2
|
+
import { nodeOperationData } from '../util/node-operation-data.js';
|
|
1
3
|
import { isTerminalRunStatus } from '../util/node-operation-parsers.js';
|
|
2
4
|
import { isPlainRecord } from '../runner/codex/conversation-parser.js';
|
|
3
5
|
import { isHostedConversationImageRunId } from '../runner/mar-agent/generated-images.js';
|
|
@@ -22,14 +24,17 @@ export class RunWorkbenchService {
|
|
|
22
24
|
return { run: this.requireRun(input.runId) };
|
|
23
25
|
}
|
|
24
26
|
async image(input) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const parsed = runImageReadInputSchema.safeParse(nodeOperationData(input));
|
|
28
|
+
if (!parsed.success)
|
|
29
|
+
throw new Error('RUN_IMAGE_INVALID');
|
|
30
|
+
const reference = parsed.data;
|
|
31
|
+
if (isHostedConversationImageRunId(reference.runId))
|
|
29
32
|
throw new Error('RUN_IMAGE_INVALID');
|
|
30
|
-
|
|
33
|
+
const native = reference.runId.startsWith('native-history:');
|
|
34
|
+
if (native !== 'imageRef' in reference)
|
|
31
35
|
throw new Error('RUN_IMAGE_INVALID');
|
|
32
|
-
const
|
|
36
|
+
const selector = 'imageRef' in reference ? reference.imageRef : reference.imageIndex;
|
|
37
|
+
const image = await this.options.readImage(reference.runId, selector);
|
|
33
38
|
if (image === undefined)
|
|
34
39
|
throw new Error('RUN_IMAGE_NOT_FOUND');
|
|
35
40
|
return { image };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/node",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.155",
|
|
4
4
|
"description": "MyAgentRoam Node runtime CLI.",
|
|
5
5
|
"license": "Apache-2.0 AND GPL-2.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"playwright": "1.62.1",
|
|
37
37
|
"ws": "^8.21.3",
|
|
38
38
|
"zod": "4.4.3",
|
|
39
|
-
"@myagentroam/agent": "0.9.
|
|
40
|
-
"@myagentroam/
|
|
39
|
+
"@myagentroam/agent": "0.9.155",
|
|
40
|
+
"@myagentroam/code-navigation": "0.9.129",
|
|
41
41
|
"@myagentroam/marctl": "0.9.120",
|
|
42
|
-
"@myagentroam/
|
|
42
|
+
"@myagentroam/protocol": "0.9.155"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/ws": "^8.18.1"
|