@myagentroam/node 0.11.1 → 0.11.3
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 +1 -1
- package/dist/database.js +53 -31
- package/dist/migrations/v021.js +64 -0
- package/dist/native-session-history.js +31 -1
- package/dist/runner/claude/conversation-parser.js +42 -0
- package/dist/runner/claude/managed-run-controller.js +78 -60
- package/dist/runner/claude/tool-normalizer.js +10 -0
- package/dist/runner/codex/conversation-parser.js +18 -3
- package/dist/runner/codex/managed-run-controller.js +25 -10
- package/dist/runner/mar-agent/conversation-normalizer.js +23 -9
- package/dist/runner/mar-agent/history-projection.js +3 -3
- package/dist/runner/mar-agent/managed-run-controller.js +1 -0
- package/dist/runner/opencode/conversation-parser.js +16 -3
- package/dist/runner/opencode/managed-run-controller.js +9 -4
- package/dist/runner/opencode/tool-normalizer.js +10 -0
- package/dist/runtime-state.js +47 -4
- package/dist/service/conversation-history-service.js +2 -1
- package/dist/service/conversation-segment-service.js +3 -1
- package/dist/service/conversation-work-process.js +102 -0
- package/dist/service/node-workspace-coordinator.js +21 -3
- package/dist/service/run-event-service.js +9 -2
- package/dist/service/skill-directory-service.js +2 -2
- package/dist/service/skill-install-service.js +15 -7
- package/dist/service/skill-node-operation-service.js +5 -4
- package/dist/service/workbench-event-projection.js +2 -0
- package/dist/service/workbench-manifest-service.js +1 -1
- package/dist/service/workspace-change-service.js +29 -13
- package/dist/service/workspace-file-service.js +3 -1
- package/dist/service/workspace-git-exclude-service.js +59 -32
- package/dist/service/workspace-service.js +34 -9
- package/dist/service/workspace-watch-snapshot-service.js +35 -5
- package/dist/service/workspace-workbench-service.js +23 -11
- package/dist/util/node-operation-parsers.js +0 -10
- package/dist/util/runner-native-session-parsers.js +15 -6
- package/dist/workspace.js +27 -3
- package/package.json +4 -4
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import {
|
|
2
|
+
import { isAbsolute, win32 } from 'node:path';
|
|
3
|
+
import { listGitHistoryRefs, normalizeFilePreviewPath, openGitHistoryFileContent, readGitHistory, readGitHistoryFileDiff, readGitHistoryFileContentRange, readGitHistoryFiles, readCurrentChangeDiff, readRestrictedDiff, resolveGitRepository, resolveGitRepositoryTarget, resolveWorkspaceGitRoot, restoreCurrentChange } from '../workspace.js';
|
|
3
4
|
import { WorkspaceCodeNavigationService } from './workspace-code-navigation-service.js';
|
|
4
5
|
import { WorkspaceContentSearchService } from './workspace-content-search-service.js';
|
|
5
6
|
import { WorkspaceWatchController } from './workspace-watch-controller.js';
|
|
@@ -98,7 +99,7 @@ export class WorkspaceWorkbenchService {
|
|
|
98
99
|
}
|
|
99
100
|
async readPredictionFile(workspaceId, path, worktreePath) {
|
|
100
101
|
const workspace = this.options.requireWorkspace(workspaceId);
|
|
101
|
-
const repository = await this.fileRepository(workspace, worktreePath ? { worktreePath } : {});
|
|
102
|
+
const repository = await this.fileRepository(workspace, worktreePath ? { worktreePath, path } : {});
|
|
102
103
|
const { readWorkspaceTextFile } = await import('../workspace.js');
|
|
103
104
|
return readWorkspaceTextFile(repository, path, 0, 64 * 1024);
|
|
104
105
|
}
|
|
@@ -180,7 +181,7 @@ export class WorkspaceWorkbenchService {
|
|
|
180
181
|
(input.worktreePath !== undefined && typeof input.worktreePath !== 'string'))
|
|
181
182
|
throw new Error('GIT_DIFF_INVALID');
|
|
182
183
|
const workspace = this.gitWorkspace(input.workspaceId);
|
|
183
|
-
const repository = await resolveGitRepositoryTarget(workspace.path, input.repositoryPath ?? '', input.worktreePath);
|
|
184
|
+
const repository = await resolveGitRepositoryTarget(await resolveWorkspaceGitRoot(workspace.path, workspace.includeParentRepository ?? true), input.repositoryPath ?? '', input.worktreePath);
|
|
184
185
|
return { diff: await readCurrentChangeDiff(repository, input.path) };
|
|
185
186
|
}
|
|
186
187
|
async restoreChange(input) {
|
|
@@ -191,7 +192,7 @@ export class WorkspaceWorkbenchService {
|
|
|
191
192
|
(input.state !== 'STAGED' && input.state !== 'UNSTAGED' && input.state !== 'UNTRACKED'))
|
|
192
193
|
throw new Error('GIT_CHANGE_RESTORE_UNAVAILABLE');
|
|
193
194
|
const workspace = this.gitWorkspace(input.workspaceId);
|
|
194
|
-
const repository = await resolveGitRepositoryTarget(workspace.path, input.repositoryPath ?? '', input.worktreePath);
|
|
195
|
+
const repository = await resolveGitRepositoryTarget(await resolveWorkspaceGitRoot(workspace.path, workspace.includeParentRepository ?? true), input.repositoryPath ?? '', input.worktreePath);
|
|
195
196
|
await restoreCurrentChange(repository, input.path, input.state);
|
|
196
197
|
this.options.invalidate(workspace.id);
|
|
197
198
|
return { restored: true };
|
|
@@ -201,14 +202,22 @@ export class WorkspaceWorkbenchService {
|
|
|
201
202
|
(input.repositoryPath !== undefined && typeof input.repositoryPath !== 'string'))
|
|
202
203
|
throw new Error('GIT_REPOSITORY_INVALID');
|
|
203
204
|
const workspace = this.gitWorkspace(input.workspaceId);
|
|
204
|
-
return resolveGitRepository(workspace.path, input.repositoryPath ?? '');
|
|
205
|
+
return resolveGitRepository(await resolveWorkspaceGitRoot(workspace.path, workspace.includeParentRepository ?? true), input.repositoryPath ?? '');
|
|
205
206
|
}
|
|
206
207
|
async fileRepository(workspace, input) {
|
|
207
|
-
if (input.worktreePath === undefined)
|
|
208
|
+
if (input.worktreePath === undefined && input.repositoryPath === undefined)
|
|
208
209
|
return workspace.path;
|
|
209
|
-
if (typeof input.worktreePath !== 'string')
|
|
210
|
+
if ((input.worktreePath !== undefined && typeof input.worktreePath !== 'string') ||
|
|
211
|
+
(input.repositoryPath !== undefined && typeof input.repositoryPath !== 'string'))
|
|
210
212
|
throw new Error('GIT_REPOSITORY_INVALID');
|
|
211
|
-
|
|
213
|
+
if (typeof input.path !== 'string' ||
|
|
214
|
+
input.path.startsWith('mar-attachment:') ||
|
|
215
|
+
input.previewDirectory !== undefined)
|
|
216
|
+
throw new Error('FILE_PATH_ESCAPE');
|
|
217
|
+
const path = normalizeFilePreviewPath(input.path);
|
|
218
|
+
if (isAbsolute(path) || win32.isAbsolute(path))
|
|
219
|
+
throw new Error('FILE_PATH_ESCAPE');
|
|
220
|
+
return resolveGitRepositoryTarget(await resolveWorkspaceGitRoot(workspace.path, workspace.includeParentRepository ?? true), input.repositoryPath ?? '', input.worktreePath);
|
|
212
221
|
}
|
|
213
222
|
refs(input) {
|
|
214
223
|
if (input.refs === undefined)
|
|
@@ -280,6 +289,9 @@ export class WorkspaceWorkbenchService {
|
|
|
280
289
|
const input = {
|
|
281
290
|
workspaceId: workspace.id,
|
|
282
291
|
path: descriptor.resource.path,
|
|
292
|
+
...(descriptor.resource.repositoryPath === undefined
|
|
293
|
+
? {}
|
|
294
|
+
: { repositoryPath: descriptor.resource.repositoryPath }),
|
|
283
295
|
...(descriptor.resource.worktreePath === undefined
|
|
284
296
|
? {}
|
|
285
297
|
: { worktreePath: descriptor.resource.worktreePath })
|
|
@@ -372,12 +384,12 @@ export class WorkspaceWorkbenchService {
|
|
|
372
384
|
typeof input.toRef !== 'string')
|
|
373
385
|
throw new Error('GIT_DIFF_INVALID');
|
|
374
386
|
const workspace = this.gitWorkspace(input.workspaceId);
|
|
375
|
-
return {
|
|
387
|
+
return {
|
|
388
|
+
diff: await readRestrictedDiff(await resolveWorkspaceGitRoot(workspace.path, workspace.includeParentRepository ?? true), input.fromRef, input.toRef)
|
|
389
|
+
};
|
|
376
390
|
}
|
|
377
391
|
gitWorkspace(workspaceId) {
|
|
378
392
|
const workspace = this.options.requireWorkspace(workspaceId);
|
|
379
|
-
if (workspace.kind !== 'GIT_WORKSPACE')
|
|
380
|
-
throw new Error('WORKSPACE_NOT_GIT');
|
|
381
393
|
return workspace;
|
|
382
394
|
}
|
|
383
395
|
}
|
|
@@ -133,16 +133,6 @@ export function extractClaudeText(message) {
|
|
|
133
133
|
.flatMap((block) => block.type === 'text' && typeof block.text === 'string' ? [block.text] : [])
|
|
134
134
|
.join('');
|
|
135
135
|
}
|
|
136
|
-
export function extractClaudeThinkingSummaries(message) {
|
|
137
|
-
return claudeContentBlocks(message).flatMap((block) => {
|
|
138
|
-
// `showThinkingSummaries` asks the SDK/API for exactly these public
|
|
139
|
-
// summaries. Partial raw thinking events are intentionally not read.
|
|
140
|
-
if (block.type !== 'thinking' || typeof block.thinking !== 'string')
|
|
141
|
-
return [];
|
|
142
|
-
const text = compactRunnerText(block.thinking.trim(), 10_000);
|
|
143
|
-
return text.length === 0 ? [] : [text];
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
136
|
export function extractClaudeToolUses(message) {
|
|
147
137
|
return claudeContentBlocks(message).flatMap((block) => {
|
|
148
138
|
if (block.type !== 'tool_use' || typeof block.id !== 'string' || typeof block.name !== 'string')
|
|
@@ -263,7 +263,9 @@ function nativeTranscriptTurnIds(sessionId, turns) {
|
|
|
263
263
|
return turns.map((entries) => {
|
|
264
264
|
const user = entries.find(({ entry }) => entry.kind === 'message' && entry.role === 'USER')?.entry;
|
|
265
265
|
const first = user ?? entries[0]?.entry;
|
|
266
|
-
const base = first?.nativeId ??
|
|
266
|
+
const base = first?.nativeId ??
|
|
267
|
+
nativeTranscriptSourceIdentity(first) ??
|
|
268
|
+
nativeTranscriptItemFingerprint(first);
|
|
267
269
|
const occurrence = occurrences.get(base) ?? 0;
|
|
268
270
|
occurrences.set(base, occurrence + 1);
|
|
269
271
|
return `${sessionId}:native:${base}${occurrence === 0 ? '' : `:${occurrence}`}`;
|
|
@@ -276,14 +278,20 @@ function nativeTranscriptItemIdentities(entries) {
|
|
|
276
278
|
nativeIdCounts.set(entry.nativeId, (nativeIdCounts.get(entry.nativeId) ?? 0) + 1);
|
|
277
279
|
const occurrences = new Map();
|
|
278
280
|
return entries.map(({ entry }) => {
|
|
279
|
-
const base =
|
|
280
|
-
|
|
281
|
-
|
|
281
|
+
const base = nativeTranscriptSourceIdentity(entry) ??
|
|
282
|
+
(entry.nativeId !== undefined && nativeIdCounts.get(entry.nativeId) === 1
|
|
283
|
+
? entry.nativeId
|
|
284
|
+
: `${entry.nativeId === undefined ? '' : `${entry.nativeId}:`}${nativeTranscriptItemFingerprint(entry)}`);
|
|
282
285
|
const occurrence = occurrences.get(base) ?? 0;
|
|
283
286
|
occurrences.set(base, occurrence + 1);
|
|
284
287
|
return occurrence === 0 ? base : `${base}:${occurrence}`;
|
|
285
288
|
});
|
|
286
289
|
}
|
|
290
|
+
function nativeTranscriptSourceIdentity(entry) {
|
|
291
|
+
return entry?.sourceItemId === undefined
|
|
292
|
+
? undefined
|
|
293
|
+
: `source:${createHash('sha256').update(entry.sourceItemId).digest('base64url').slice(0, 24)}`;
|
|
294
|
+
}
|
|
287
295
|
function nativeTranscriptItemFingerprint(entry) {
|
|
288
296
|
return createHash('sha256')
|
|
289
297
|
.update(JSON.stringify(entry ?? null))
|
|
@@ -350,6 +358,7 @@ function nativeTranscriptConversationItem(session, entry, index, itemIdentity, t
|
|
|
350
358
|
const planText = entry.kind === 'message' && entry.role !== 'USER' ? claudePlanText(entryText) : undefined;
|
|
351
359
|
const item = {
|
|
352
360
|
id: `${turnId}:item:${itemIdentity}`,
|
|
361
|
+
...(entry.sourceItemId === undefined ? {} : { sourceItemId: entry.sourceItemId }),
|
|
353
362
|
sessionId: session.id,
|
|
354
363
|
turnId,
|
|
355
364
|
runId: null,
|
|
@@ -359,7 +368,7 @@ function nativeTranscriptConversationItem(session, entry, index, itemIdentity, t
|
|
|
359
368
|
kind: isUserInputRequest
|
|
360
369
|
? 'user_input_request'
|
|
361
370
|
: isReasoning
|
|
362
|
-
? '
|
|
371
|
+
? 'reasoning'
|
|
363
372
|
: isContextCompaction
|
|
364
373
|
? 'context_compaction'
|
|
365
374
|
: isToolCall
|
|
@@ -378,7 +387,7 @@ function nativeTranscriptConversationItem(session, entry, index, itemIdentity, t
|
|
|
378
387
|
questions: userInputQuestions
|
|
379
388
|
}
|
|
380
389
|
: isReasoning
|
|
381
|
-
? { sections: entry.sections }
|
|
390
|
+
? { representation: entry.representation ?? 'unspecified', sections: entry.sections }
|
|
382
391
|
: isContextCompaction
|
|
383
392
|
? { phase: entry.phase, summary: entry.summary }
|
|
384
393
|
: isToolCall
|
package/dist/workspace.js
CHANGED
|
@@ -1187,7 +1187,7 @@ export function isWithinAllowedRoot(target, roots, platform = hostPlatform()) {
|
|
|
1187
1187
|
});
|
|
1188
1188
|
}
|
|
1189
1189
|
/** Resolving both candidate and roots rejects Linux symlinks which point outside a root. */
|
|
1190
|
-
export async function inspectWorkspace(requestedPath, allowedRoots) {
|
|
1190
|
+
export async function inspectWorkspace(requestedPath, allowedRoots, includeParentRepository = true) {
|
|
1191
1191
|
const resolvedPath = await realpath(requestedPath);
|
|
1192
1192
|
const resolvedRoots = await Promise.all(allowedRoots.map((root) => realpath(root)));
|
|
1193
1193
|
const directory = await stat(resolvedPath);
|
|
@@ -1195,16 +1195,40 @@ export async function inspectWorkspace(requestedPath, allowedRoots) {
|
|
|
1195
1195
|
throw new Error('WORKSPACE_NOT_ALLOWED');
|
|
1196
1196
|
}
|
|
1197
1197
|
try {
|
|
1198
|
-
const
|
|
1198
|
+
const repositoryRoot = await resolveWorkspaceGitRoot(resolvedPath, includeParentRepository);
|
|
1199
|
+
const summary = { ...(await readGitSummary(repositoryRoot)), repositoryRoot };
|
|
1199
1200
|
return { path: resolvedPath, kind: 'GIT_WORKSPACE', gitSummary: summary };
|
|
1200
1201
|
}
|
|
1201
1202
|
catch (error) {
|
|
1202
|
-
if ((error instanceof GitCommandError && error.code === 128) ||
|
|
1203
|
+
if ((error instanceof GitCommandError && error.code === 128) ||
|
|
1204
|
+
isGitUnavailable(error) ||
|
|
1205
|
+
(error instanceof Error && error.message === 'WORKSPACE_NOT_GIT')) {
|
|
1203
1206
|
return { path: resolvedPath, kind: 'DIRECTORY' };
|
|
1204
1207
|
}
|
|
1205
1208
|
throw error;
|
|
1206
1209
|
}
|
|
1207
1210
|
}
|
|
1211
|
+
/** Resolves the working tree without changing the registered Workspace identity. */
|
|
1212
|
+
export async function resolveWorkspaceGitRoot(workspacePath, includeParentRepository = true) {
|
|
1213
|
+
const workspace = await resolveRegisteredWorkspaceRoot(workspacePath);
|
|
1214
|
+
if (!includeParentRepository) {
|
|
1215
|
+
const marker = await lstat(resolve(workspace, '.git')).catch((error) => {
|
|
1216
|
+
if (error.code === 'ENOENT')
|
|
1217
|
+
return undefined;
|
|
1218
|
+
throw error;
|
|
1219
|
+
});
|
|
1220
|
+
if (marker === undefined ||
|
|
1221
|
+
marker.isSymbolicLink() ||
|
|
1222
|
+
(!marker.isFile() && !marker.isDirectory()))
|
|
1223
|
+
throw new Error('WORKSPACE_NOT_GIT');
|
|
1224
|
+
}
|
|
1225
|
+
const result = await runReadOnlyGit(workspace, ['rev-parse', '--show-toplevel']);
|
|
1226
|
+
const root = await realpath(result.text.replace(/\n$/u, ''));
|
|
1227
|
+
if (!includeParentRepository &&
|
|
1228
|
+
normalizeWorkspacePath(root) !== normalizeWorkspacePath(workspace))
|
|
1229
|
+
throw new Error('WORKSPACE_NOT_GIT');
|
|
1230
|
+
return root;
|
|
1231
|
+
}
|
|
1208
1232
|
export async function readGitSummary(workspacePath) {
|
|
1209
1233
|
const commonDir = (await runReadOnlyGit(workspacePath, ['rev-parse', '--git-common-dir'])).text.trim();
|
|
1210
1234
|
const headResult = await runReadOnlyGitAllowFailure(workspacePath, [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/node",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.3",
|
|
4
4
|
"description": "MyAgentRoam Node runtime CLI.",
|
|
5
5
|
"license": "Apache-2.0 AND GPL-2.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
"playwright": "1.62.1",
|
|
38
38
|
"ws": "^8.21.3",
|
|
39
39
|
"zod": "4.4.3",
|
|
40
|
-
"@myagentroam/agent": "0.11.
|
|
40
|
+
"@myagentroam/agent": "0.11.3",
|
|
41
41
|
"@myagentroam/code-navigation": "0.11.0",
|
|
42
|
-
"@myagentroam/
|
|
43
|
-
"@myagentroam/
|
|
42
|
+
"@myagentroam/protocol": "0.11.3",
|
|
43
|
+
"@myagentroam/marctl": "0.11.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/ws": "^8.18.1"
|