ur-agent 1.44.10 → 1.45.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/CHANGELOG.md +108 -0
- package/README.md +16 -9
- package/dist/cli.js +30223 -22644
- package/docs/AGENT_FEATURES.md +8 -4
- package/docs/CONFIGURATION.md +7 -2
- package/docs/IDE.md +14 -12
- package/docs/TROUBLESHOOTING.md +7 -0
- package/docs/USAGE.md +6 -2
- package/docs/VALIDATION.md +1 -1
- package/docs/providers.md +11 -1
- package/documentation/index.html +1 -1
- package/extensions/jetbrains-ur/README.md +22 -0
- package/extensions/jetbrains-ur/build.gradle.kts +34 -0
- package/extensions/jetbrains-ur/settings.gradle.kts +1 -0
- package/extensions/jetbrains-ur/src/main/kotlin/dev/urnexus/SendSelectionAction.kt +28 -0
- package/extensions/jetbrains-ur/src/main/kotlin/dev/urnexus/UrAcpClient.kt +97 -0
- package/extensions/jetbrains-ur/src/main/kotlin/dev/urnexus/UrToolWindowFactory.kt +27 -0
- package/extensions/jetbrains-ur/src/main/resources/META-INF/plugin.xml +17 -0
- package/extensions/vscode-ur-inline-diffs/out/extension.js +66 -21
- package/extensions/vscode-ur-inline-diffs/package.json +1 -1
- package/package.json +2 -1
|
@@ -62,7 +62,8 @@ var fs = __toESM(require("node:fs"));
|
|
|
62
62
|
var path = __toESM(require("node:path"));
|
|
63
63
|
var vscode2 = __toESM(require("vscode"));
|
|
64
64
|
function workspaceRoot() {
|
|
65
|
-
|
|
65
|
+
const activeUri = vscode2.window.activeTextEditor?.document.uri;
|
|
66
|
+
return (activeUri ? vscode2.workspace.getWorkspaceFolder(activeUri) : void 0)?.uri.fsPath ?? vscode2.workspace.workspaceFolders?.[0]?.uri.fsPath;
|
|
66
67
|
}
|
|
67
68
|
function diffsRoot(root) {
|
|
68
69
|
return path.join(root, ".ur", "ide", "diffs");
|
|
@@ -71,10 +72,34 @@ function manifestPath(root) {
|
|
|
71
72
|
return path.join(diffsRoot(root), "manifest.json");
|
|
72
73
|
}
|
|
73
74
|
function patchPath(root, bundle) {
|
|
74
|
-
return
|
|
75
|
+
return artifactPath(root, bundle, "patch");
|
|
75
76
|
}
|
|
76
77
|
function metadataPath(root, bundle) {
|
|
77
|
-
return
|
|
78
|
+
return artifactPath(root, bundle, "metadata");
|
|
79
|
+
}
|
|
80
|
+
var DIFF_ID_PATTERN = /^diff-[1-9][0-9]*$/u;
|
|
81
|
+
function artifactPath(root, bundle, kind) {
|
|
82
|
+
if (!DIFF_ID_PATTERN.test(bundle.id)) throw new Error(`Invalid UR diff id: ${bundle.id}`);
|
|
83
|
+
const relative2 = kind === "patch" ? bundle.patchFile : bundle.metadataFile;
|
|
84
|
+
const expected = kind === "patch" ? `patches/${bundle.id}.patch` : `metadata/${bundle.id}.json`;
|
|
85
|
+
if (relative2.replaceAll("\\", "/") !== expected) {
|
|
86
|
+
throw new Error(`Invalid UR diff ${kind} path for ${bundle.id}`);
|
|
87
|
+
}
|
|
88
|
+
const rootPath = path.resolve(diffsRoot(root));
|
|
89
|
+
const target = path.resolve(rootPath, relative2);
|
|
90
|
+
if (!target.startsWith(`${rootPath}${path.sep}`)) throw new Error(`UR diff ${kind} path escapes the diff store`);
|
|
91
|
+
return target;
|
|
92
|
+
}
|
|
93
|
+
function isValidBundle(value) {
|
|
94
|
+
if (!value || typeof value !== "object") return false;
|
|
95
|
+
const bundle = value;
|
|
96
|
+
try {
|
|
97
|
+
patchPath(".", bundle);
|
|
98
|
+
metadataPath(".", bundle);
|
|
99
|
+
return true;
|
|
100
|
+
} catch {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
78
103
|
}
|
|
79
104
|
function readJson(file, fallback) {
|
|
80
105
|
try {
|
|
@@ -90,10 +115,11 @@ function writeJson(file, value) {
|
|
|
90
115
|
}
|
|
91
116
|
function loadManifest(root) {
|
|
92
117
|
const manifest = readJson(manifestPath(root), { version: 1, diffs: [] });
|
|
93
|
-
return Array.isArray(manifest.diffs) ? manifest : { version: 1, diffs: [] };
|
|
118
|
+
return Array.isArray(manifest.diffs) ? { version: 1, diffs: manifest.diffs.filter(isValidBundle) } : { version: 1, diffs: [] };
|
|
94
119
|
}
|
|
95
120
|
function loadBundleMetadata(root, bundle) {
|
|
96
|
-
|
|
121
|
+
const metadata = readJson(metadataPath(root, bundle), bundle);
|
|
122
|
+
return isValidBundle(metadata) && metadata.id === bundle.id ? metadata : bundle;
|
|
97
123
|
}
|
|
98
124
|
function readPatch(root, bundle) {
|
|
99
125
|
const file = patchPath(root, bundle);
|
|
@@ -720,9 +746,9 @@ function languageIdToFence(languageId) {
|
|
|
720
746
|
}
|
|
721
747
|
function captureEditorSnapshot() {
|
|
722
748
|
const vscode18 = require("vscode");
|
|
723
|
-
const workspaceRoot2 = vscode18.workspace.workspaceFolders?.[0]?.uri.fsPath;
|
|
724
749
|
const editor = vscode18.window.activeTextEditor;
|
|
725
|
-
if (!editor) return { workspaceRoot:
|
|
750
|
+
if (!editor) return { workspaceRoot: vscode18.workspace.workspaceFolders?.[0]?.uri.fsPath };
|
|
751
|
+
const workspaceRoot2 = vscode18.workspace.getWorkspaceFolder(editor.document.uri)?.uri.fsPath;
|
|
726
752
|
const absolutePath = editor.document.uri.fsPath;
|
|
727
753
|
const relativePath = workspaceRoot2 ? path2.relative(workspaceRoot2, absolutePath) : absolutePath;
|
|
728
754
|
const activeFile = { path: relativePath, languageId: editor.document.languageId };
|
|
@@ -1294,12 +1320,16 @@ var ChatController = class {
|
|
|
1294
1320
|
attachments = [];
|
|
1295
1321
|
status = "idle";
|
|
1296
1322
|
turnHandle;
|
|
1323
|
+
activeTurnId = 0;
|
|
1297
1324
|
pendingPermissions = /* @__PURE__ */ new Map();
|
|
1298
1325
|
// --- commands ---
|
|
1299
1326
|
async newChat() {
|
|
1300
1327
|
const root = this.requireWorkspaceRoot();
|
|
1301
1328
|
if (!root) return;
|
|
1302
1329
|
this.turnHandle?.cancel();
|
|
1330
|
+
this.activeTurnId++;
|
|
1331
|
+
this.turnHandle = void 0;
|
|
1332
|
+
this.denyAllPending("A new chat was started.");
|
|
1303
1333
|
this.record = createSession(root);
|
|
1304
1334
|
this.attachments = [];
|
|
1305
1335
|
this.status = "idle";
|
|
@@ -1418,6 +1448,10 @@ var ChatController = class {
|
|
|
1418
1448
|
vscode6.window.showWarningMessage(reason);
|
|
1419
1449
|
return;
|
|
1420
1450
|
}
|
|
1451
|
+
if (this.record && snapshot.workspaceRoot !== this.record.session.workspaceRoot) {
|
|
1452
|
+
vscode6.window.showWarningMessage("The active file belongs to a different workspace folder. Start a new chat for that folder.");
|
|
1453
|
+
return;
|
|
1454
|
+
}
|
|
1421
1455
|
const attachment = kind === "file" ? { kind: "file", file: snapshot.activeFile } : { kind: "selection", selection: snapshot.selection };
|
|
1422
1456
|
this.attachments.push(attachment);
|
|
1423
1457
|
this.ensurePanel();
|
|
@@ -1437,7 +1471,7 @@ var ChatController = class {
|
|
|
1437
1471
|
/** The single pathway every turn goes through — manual sends and editor
|
|
1438
1472
|
* actions alike. */
|
|
1439
1473
|
async dispatchTurn(promptText) {
|
|
1440
|
-
const root = this.requireWorkspaceRoot();
|
|
1474
|
+
const root = this.record?.session.workspaceRoot ?? this.requireWorkspaceRoot();
|
|
1441
1475
|
if (!root) return;
|
|
1442
1476
|
if (this.status === "running") {
|
|
1443
1477
|
vscode6.window.showWarningMessage("UR is already running a request. Cancel it first or wait for it to finish.");
|
|
@@ -1460,17 +1494,24 @@ var ChatController = class {
|
|
|
1460
1494
|
this._onDidChangeState.fire();
|
|
1461
1495
|
this.panel?.post({ type: "statusChanged", status: this.status });
|
|
1462
1496
|
const resumeSessionId = this.record.session.cliSessionId;
|
|
1463
|
-
|
|
1497
|
+
const turnId = ++this.activeTurnId;
|
|
1498
|
+
let exitedSynchronously = false;
|
|
1499
|
+
const handle = runUrTurn(
|
|
1464
1500
|
{ cwd: root, prompt: promptText, resumeSessionId },
|
|
1465
1501
|
{
|
|
1466
|
-
onMessage: (message) => this.handleStreamMessage(root, sessionId, message),
|
|
1467
|
-
onControlRequest: (request) => this.handlePermissionRequest(request),
|
|
1468
|
-
onExit: (result) =>
|
|
1502
|
+
onMessage: (message) => this.handleStreamMessage(root, sessionId, turnId, message),
|
|
1503
|
+
onControlRequest: (request) => this.handlePermissionRequest(turnId, request),
|
|
1504
|
+
onExit: (result) => {
|
|
1505
|
+
exitedSynchronously = true;
|
|
1506
|
+
this.handleTurnExit(root, sessionId, turnId, result);
|
|
1507
|
+
}
|
|
1469
1508
|
},
|
|
1470
1509
|
{ executable: resolveUrCommand({ cwd: root, config: readUrCommandConfig() }) }
|
|
1471
1510
|
);
|
|
1511
|
+
this.turnHandle = exitedSynchronously ? void 0 : handle;
|
|
1472
1512
|
}
|
|
1473
|
-
handleStreamMessage(root, sessionId, message) {
|
|
1513
|
+
handleStreamMessage(root, sessionId, turnId, message) {
|
|
1514
|
+
if (turnId !== this.activeTurnId) return;
|
|
1474
1515
|
if (message.type === "system" && message.subtype === "init" && typeof message.session_id === "string") {
|
|
1475
1516
|
if (this.record && this.record.session.id === sessionId && !this.record.session.cliSessionId) {
|
|
1476
1517
|
setCliSessionId(root, sessionId, message.session_id);
|
|
@@ -1508,24 +1549,28 @@ var ChatController = class {
|
|
|
1508
1549
|
if (!this.record) return;
|
|
1509
1550
|
this.appendChatMessage(root, this.record.session.id, "status", [{ type: "text", text }]);
|
|
1510
1551
|
}
|
|
1511
|
-
handlePermissionRequest(request) {
|
|
1512
|
-
|
|
1552
|
+
handlePermissionRequest(turnId, request) {
|
|
1553
|
+
if (turnId !== this.activeTurnId) {
|
|
1554
|
+
return Promise.resolve({ behavior: "deny", message: "This chat turn is no longer active." });
|
|
1555
|
+
}
|
|
1556
|
+
return new Promise((resolve3) => {
|
|
1513
1557
|
const toolName = request.request.tool_name ?? "tool";
|
|
1514
1558
|
const input = request.request.input ?? {};
|
|
1515
|
-
this.pendingPermissions.set(request.request_id, { resolve:
|
|
1559
|
+
this.pendingPermissions.set(request.request_id, { resolve: resolve3, toolName, input, turnId });
|
|
1516
1560
|
this.panel?.post({ type: "permissionRequest", requestId: request.request_id, toolName, input });
|
|
1517
1561
|
});
|
|
1518
1562
|
}
|
|
1519
|
-
handleTurnExit(root, result) {
|
|
1563
|
+
handleTurnExit(root, sessionId, turnId, result) {
|
|
1564
|
+
if (turnId !== this.activeTurnId) return;
|
|
1520
1565
|
this.turnHandle = void 0;
|
|
1521
1566
|
this.denyAllPending("The chat turn ended before this request was answered.");
|
|
1522
1567
|
if (result.canceled) {
|
|
1523
1568
|
this.status = "canceled";
|
|
1524
|
-
this.
|
|
1569
|
+
this.appendChatMessage(root, sessionId, "status", [{ type: "text", text: "Canceled." }]);
|
|
1525
1570
|
} else if (!result.ok) {
|
|
1526
1571
|
this.status = "error";
|
|
1527
1572
|
const message = result.error ?? "UR failed to complete this turn.";
|
|
1528
|
-
this.
|
|
1573
|
+
this.appendChatMessage(root, sessionId, "status", [{ type: "text", text: `Error: ${message}` }]);
|
|
1529
1574
|
this.panel?.post({ type: "errorBanner", message });
|
|
1530
1575
|
} else {
|
|
1531
1576
|
this.status = "idle";
|
|
@@ -1535,13 +1580,13 @@ var ChatController = class {
|
|
|
1535
1580
|
}
|
|
1536
1581
|
resolvePermission(requestId, decision) {
|
|
1537
1582
|
const pending = this.pendingPermissions.get(requestId);
|
|
1538
|
-
if (!pending) return;
|
|
1583
|
+
if (!pending || pending.turnId !== this.activeTurnId) return;
|
|
1539
1584
|
this.pendingPermissions.delete(requestId);
|
|
1540
1585
|
pending.resolve(
|
|
1541
1586
|
decision === "allow" ? { behavior: "allow", updatedInput: pending.input } : { behavior: "deny", message: "User denied this tool call from the UR Chat panel." }
|
|
1542
1587
|
);
|
|
1543
1588
|
this.panel?.post({ type: "permissionResolved", requestId });
|
|
1544
|
-
const root = workspaceRoot
|
|
1589
|
+
const root = this.record?.session.workspaceRoot;
|
|
1545
1590
|
if (root) this.appendStatusText(root, `${decision === "allow" ? "Allowed" : "Denied"} ${pending.toolName}.`);
|
|
1546
1591
|
}
|
|
1547
1592
|
denyAllPending(reason) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "ur-inline-diffs",
|
|
3
3
|
"displayName": "UR Inline Diffs",
|
|
4
4
|
"description": "Review, apply, and reject UR inline diff bundles from .ur/ide/diffs inside VS Code.",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.45.3",
|
|
6
6
|
"publisher": "ur-nexus",
|
|
7
7
|
"engines": {
|
|
8
8
|
"vscode": "^1.92.0"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ur-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.45.3",
|
|
4
4
|
"description": "UR-Nexus — autonomous engineering workflow engine (plan, execute, test, verify, document, benchmark, reproduce)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "bun@1.3.14",
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
73
|
"diff2html": "^3.4.56",
|
|
74
|
+
"playwright-core": "^1.55.0",
|
|
74
75
|
"sharp": "^0.35.1"
|
|
75
76
|
},
|
|
76
77
|
"devDependencies": {
|