ur-agent 1.36.1 → 1.37.0

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.
@@ -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.36.1",
5
+ "version": "1.37.0",
6
6
  "publisher": "ur-agent",
7
7
  "engines": {
8
8
  "vscode": "^1.92.0"
@@ -12,14 +12,46 @@
12
12
  ],
13
13
  "activationEvents": [
14
14
  "onView:urInlineDiffs",
15
+ "onView:urActions",
15
16
  "onCommand:urInlineDiffs.refresh",
16
17
  "onCommand:urInlineDiffs.open",
17
18
  "onCommand:urInlineDiffs.comment",
18
19
  "onCommand:urInlineDiffs.apply",
19
20
  "onCommand:urInlineDiffs.reject",
20
- "onCommand:urInlineDiffs.status"
21
+ "onCommand:urInlineDiffs.status",
22
+ "onCommand:urInlineDiffs.chat.new",
23
+ "onCommand:urInlineDiffs.chat.open",
24
+ "onCommand:urInlineDiffs.chat.cancel",
25
+ "onCommand:urInlineDiffs.chat.addFile",
26
+ "onCommand:urInlineDiffs.chat.addSelection",
27
+ "onCommand:urInlineDiffs.chat.explainSelection",
28
+ "onCommand:urInlineDiffs.chat.fixSelection",
29
+ "onCommand:urInlineDiffs.chat.generateTests",
30
+ "onCommand:urInlineDiffs.agentStatus",
31
+ "onCommand:urInlineDiffs.agentOptions",
32
+ "onCommand:urInlineDiffs.reviewCurrentDiff",
33
+ "onCommand:urInlineDiffs.runVerifier",
34
+ "onCommand:urInlineDiffs.searchActions",
35
+ "onCommand:urInlineDiffs.openSettings",
36
+ "onCommand:urInlineDiffs.openDocs",
37
+ "onCommand:urInlineDiffs.openArtifacts",
38
+ "onCommand:urInlineDiffs.runSpec",
39
+ "onCommand:urInlineDiffs.runWorkflow",
40
+ "onCommand:urActions.refresh",
41
+ "onCommand:urActions.openBackgroundLog"
21
42
  ],
22
- "main": "./extension.js",
43
+ "main": "./out/extension.js",
44
+ "scripts": {
45
+ "build": "node esbuild.js",
46
+ "typecheck": "tsc --noEmit -p tsconfig.json"
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "^22.0.0",
50
+ "@types/vscode": "^1.92.0",
51
+ "bun-types": "^1.2.0",
52
+ "esbuild": "^0.28.1",
53
+ "typescript": "^5.7.0"
54
+ },
23
55
  "contributes": {
24
56
  "viewsContainers": {
25
57
  "activitybar": [
@@ -35,6 +67,10 @@
35
67
  {
36
68
  "id": "urInlineDiffs",
37
69
  "name": "Inline Diffs"
70
+ },
71
+ {
72
+ "id": "urActions",
73
+ "name": "Actions"
38
74
  }
39
75
  ]
40
76
  },
@@ -68,6 +104,95 @@
68
104
  "command": "urInlineDiffs.status",
69
105
  "title": "UR: Show Status (provider, model, plugins)",
70
106
  "icon": "$(pulse)"
107
+ },
108
+ {
109
+ "command": "urInlineDiffs.chat.new",
110
+ "title": "UR: New Chat",
111
+ "icon": "$(comment-add)"
112
+ },
113
+ {
114
+ "command": "urInlineDiffs.chat.open",
115
+ "title": "UR: Open Chat",
116
+ "icon": "$(comment)"
117
+ },
118
+ {
119
+ "command": "urInlineDiffs.chat.cancel",
120
+ "title": "UR: Cancel Current Chat Request",
121
+ "icon": "$(stop-circle)"
122
+ },
123
+ {
124
+ "command": "urInlineDiffs.chat.addFile",
125
+ "title": "UR: Add Current File to Chat"
126
+ },
127
+ {
128
+ "command": "urInlineDiffs.chat.addSelection",
129
+ "title": "UR: Add Selection to Chat"
130
+ },
131
+ {
132
+ "command": "urInlineDiffs.chat.explainSelection",
133
+ "title": "UR: Explain Selection"
134
+ },
135
+ {
136
+ "command": "urInlineDiffs.chat.fixSelection",
137
+ "title": "UR: Fix Selection"
138
+ },
139
+ {
140
+ "command": "urInlineDiffs.chat.generateTests",
141
+ "title": "UR: Generate Tests for Selection"
142
+ },
143
+ {
144
+ "command": "urInlineDiffs.agentStatus",
145
+ "title": "UR: Agent Status",
146
+ "icon": "$(info)"
147
+ },
148
+ {
149
+ "command": "urInlineDiffs.agentOptions",
150
+ "title": "UR: Agent Options",
151
+ "icon": "$(settings-gear)"
152
+ },
153
+ {
154
+ "command": "urInlineDiffs.reviewCurrentDiff",
155
+ "title": "UR: Review Current Diff",
156
+ "icon": "$(git-compare)"
157
+ },
158
+ {
159
+ "command": "urInlineDiffs.runVerifier",
160
+ "title": "UR: Run Verifier",
161
+ "icon": "$(shield)"
162
+ },
163
+ {
164
+ "command": "urInlineDiffs.searchActions",
165
+ "title": "UR: Search Actions",
166
+ "icon": "$(search)"
167
+ },
168
+ {
169
+ "command": "urInlineDiffs.openSettings",
170
+ "title": "UR: Open Settings"
171
+ },
172
+ {
173
+ "command": "urInlineDiffs.openDocs",
174
+ "title": "UR: Open Docs"
175
+ },
176
+ {
177
+ "command": "urInlineDiffs.openArtifacts",
178
+ "title": "UR: Open Artifacts"
179
+ },
180
+ {
181
+ "command": "urInlineDiffs.runSpec",
182
+ "title": "UR: Run Spec"
183
+ },
184
+ {
185
+ "command": "urInlineDiffs.runWorkflow",
186
+ "title": "UR: Run Workflow"
187
+ },
188
+ {
189
+ "command": "urActions.refresh",
190
+ "title": "UR: Refresh IDE Actions",
191
+ "icon": "$(refresh)"
192
+ },
193
+ {
194
+ "command": "urActions.openBackgroundLog",
195
+ "title": "UR: Open Background Task Log"
71
196
  }
72
197
  ],
73
198
  "viewsWelcome": [
@@ -78,6 +203,16 @@
78
203
  ],
79
204
  "menus": {
80
205
  "view/title": [
206
+ {
207
+ "command": "urInlineDiffs.chat.new",
208
+ "when": "view == urInlineDiffs",
209
+ "group": "navigation"
210
+ },
211
+ {
212
+ "command": "urInlineDiffs.chat.open",
213
+ "when": "view == urInlineDiffs",
214
+ "group": "navigation"
215
+ },
81
216
  {
82
217
  "command": "urInlineDiffs.refresh",
83
218
  "when": "view == urInlineDiffs",
@@ -87,29 +222,61 @@
87
222
  "command": "urInlineDiffs.status",
88
223
  "when": "view == urInlineDiffs",
89
224
  "group": "navigation"
225
+ },
226
+ {
227
+ "command": "urActions.refresh",
228
+ "when": "view == urActions",
229
+ "group": "navigation"
230
+ },
231
+ {
232
+ "command": "urInlineDiffs.agentStatus",
233
+ "when": "view == urActions",
234
+ "group": "navigation"
90
235
  }
91
236
  ],
92
237
  "view/item/context": [
93
238
  {
94
239
  "command": "urInlineDiffs.open",
95
- "when": "view == urInlineDiffs && viewItem == diff",
240
+ "when": "(view == urInlineDiffs || view == urActions) && viewItem == diff",
96
241
  "group": "inline"
97
242
  },
98
243
  {
99
244
  "command": "urInlineDiffs.apply",
100
- "when": "view == urInlineDiffs && viewItem == diff",
245
+ "when": "(view == urInlineDiffs || view == urActions) && viewItem == diff",
101
246
  "group": "1_actions"
102
247
  },
103
248
  {
104
249
  "command": "urInlineDiffs.reject",
105
- "when": "view == urInlineDiffs && viewItem == diff",
250
+ "when": "(view == urInlineDiffs || view == urActions) && viewItem == diff",
106
251
  "group": "1_actions"
107
252
  },
108
253
  {
109
254
  "command": "urInlineDiffs.comment",
110
- "when": "view == urInlineDiffs && viewItem == diff",
255
+ "when": "(view == urInlineDiffs || view == urActions) && viewItem == diff",
111
256
  "group": "2_review"
112
257
  }
258
+ ],
259
+ "editor/context": [
260
+ {
261
+ "command": "urInlineDiffs.chat.explainSelection",
262
+ "when": "editorHasSelection",
263
+ "group": "ur@1"
264
+ },
265
+ {
266
+ "command": "urInlineDiffs.chat.fixSelection",
267
+ "when": "editorHasSelection",
268
+ "group": "ur@2"
269
+ },
270
+ {
271
+ "command": "urInlineDiffs.chat.generateTests",
272
+ "when": "editorHasSelection",
273
+ "group": "ur@3"
274
+ },
275
+ {
276
+ "command": "urInlineDiffs.chat.addSelection",
277
+ "when": "editorHasSelection",
278
+ "group": "ur@4"
279
+ }
113
280
  ]
114
281
  }
115
282
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ur-agent",
3
- "version": "1.36.1",
4
- "description": "UR-AGENT autonomous engineering workflow engine (plan, execute, test, verify, document, benchmark, reproduce)",
3
+ "version": "1.37.0",
4
+ "description": "UR-AGENT \u2014 autonomous engineering workflow engine (plan, execute, test, verify, document, benchmark, reproduce)",
5
5
  "type": "module",
6
6
  "packageManager": "bun@1.3.14",
7
7
  "engines": {
@@ -1,383 +0,0 @@
1
- const fs = require('node:fs')
2
- const path = require('node:path')
3
- const { execFile } = require('node:child_process')
4
- const { promisify } = require('node:util')
5
- const vscode = require('vscode')
6
-
7
- const execFileAsync = promisify(execFile)
8
-
9
- function workspaceRoot() {
10
- return vscode.workspace.workspaceFolders?.[0]?.uri.fsPath
11
- }
12
-
13
- function diffsRoot(root) {
14
- return path.join(root, '.ur', 'ide', 'diffs')
15
- }
16
-
17
- function manifestPath(root) {
18
- return path.join(diffsRoot(root), 'manifest.json')
19
- }
20
-
21
- function readJson(file, fallback) {
22
- try {
23
- return JSON.parse(fs.readFileSync(file, 'utf8'))
24
- } catch {
25
- return fallback
26
- }
27
- }
28
-
29
- function writeJson(file, value) {
30
- fs.mkdirSync(path.dirname(file), { recursive: true })
31
- fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`)
32
- }
33
-
34
- function loadManifest(root) {
35
- const manifest = readJson(manifestPath(root), { version: 1, diffs: [] })
36
- return Array.isArray(manifest.diffs) ? manifest : { version: 1, diffs: [] }
37
- }
38
-
39
- function patchPath(root, bundle) {
40
- return path.join(diffsRoot(root), bundle.patchFile)
41
- }
42
-
43
- function metadataPath(root, bundle) {
44
- return path.join(diffsRoot(root), bundle.metadataFile)
45
- }
46
-
47
- function escapeHtml(text) {
48
- return String(text)
49
- .replace(/&/g, '&')
50
- .replace(/</g, '&lt;')
51
- .replace(/>/g, '&gt;')
52
- .replace(/"/g, '&quot;')
53
- }
54
-
55
- function formatCount(count, singular, plural = `${singular}s`) {
56
- return `${count} ${count === 1 ? singular : plural}`
57
- }
58
-
59
- function formatRelativeTime(value) {
60
- if (!value) return 'unknown time'
61
- const date = new Date(value)
62
- if (Number.isNaN(date.getTime())) return String(value)
63
- const deltaMs = Date.now() - date.getTime()
64
- const minute = 60 * 1000
65
- const hour = 60 * minute
66
- const day = 24 * hour
67
- if (deltaMs < minute) return 'just now'
68
- if (deltaMs < hour) return `${Math.max(1, Math.floor(deltaMs / minute))}m ago`
69
- if (deltaMs < day) return `${Math.floor(deltaMs / hour)}h ago`
70
- if (deltaMs < 7 * day) return `${Math.floor(deltaMs / day)}d ago`
71
- return date.toLocaleDateString()
72
- }
73
-
74
- function statusIcon(status) {
75
- switch (status) {
76
- case 'applied':
77
- return new vscode.ThemeIcon('check', new vscode.ThemeColor('testing.iconPassed'))
78
- case 'rejected':
79
- return new vscode.ThemeIcon('circle-slash', new vscode.ThemeColor('testing.iconFailed'))
80
- case 'commented':
81
- return new vscode.ThemeIcon('comment-discussion', new vscode.ThemeColor('charts.yellow'))
82
- default:
83
- return new vscode.ThemeIcon('diff', new vscode.ThemeColor('charts.blue'))
84
- }
85
- }
86
-
87
- class DiffItem extends vscode.TreeItem {
88
- constructor(bundle) {
89
- const title = bundle.title || bundle.id
90
- super(title, vscode.TreeItemCollapsibleState.None)
91
- this.bundle = bundle
92
- this.contextValue = 'diff'
93
- const fileCount = bundle.files?.length ?? 0
94
- const changedAt = bundle.updatedAt ?? bundle.createdAt
95
- this.description = `${bundle.status ?? 'captured'} · ${formatCount(fileCount, 'file')} · ${formatRelativeTime(changedAt)}`
96
- this.iconPath = statusIcon(bundle.status)
97
- this.tooltip = new vscode.MarkdownString(
98
- [
99
- `**${escapeHtml(title)}**`,
100
- '',
101
- `- ID: \`${escapeHtml(bundle.id)}\``,
102
- `- Status: ${escapeHtml(bundle.status ?? 'captured')}`,
103
- `- Files: ${fileCount}`,
104
- `- Patch: \`${escapeHtml(bundle.patchFile)}\``,
105
- ].join('\n'),
106
- )
107
- this.command = {
108
- command: 'urInlineDiffs.open',
109
- title: 'Open Inline Diff',
110
- arguments: [this],
111
- }
112
- }
113
- }
114
-
115
- class ActionItem extends vscode.TreeItem {
116
- constructor(label, description, icon, command, tooltip) {
117
- super(label, vscode.TreeItemCollapsibleState.None)
118
- this.contextValue = 'urAction'
119
- this.description = description
120
- this.iconPath = new vscode.ThemeIcon(icon)
121
- this.tooltip = tooltip ?? `${label}${description ? ` — ${description}` : ''}`
122
- this.command = command
123
- }
124
- }
125
-
126
- class InfoItem extends vscode.TreeItem {
127
- constructor(label, description, icon = 'info') {
128
- super(label, vscode.TreeItemCollapsibleState.None)
129
- this.contextValue = 'urInfo'
130
- this.description = description
131
- this.iconPath = new vscode.ThemeIcon(icon)
132
- this.tooltip = `${label}${description ? ` — ${description}` : ''}`
133
- }
134
- }
135
-
136
- class DiffProvider {
137
- constructor() {
138
- this._onDidChangeTreeData = new vscode.EventEmitter()
139
- this.onDidChangeTreeData = this._onDidChangeTreeData.event
140
- }
141
-
142
- refresh() {
143
- this._onDidChangeTreeData.fire()
144
- }
145
-
146
- getTreeItem(item) {
147
- return item
148
- }
149
-
150
- getChildren() {
151
- const root = workspaceRoot()
152
- if (!root) {
153
- return [
154
- new InfoItem('Open a workspace folder', 'UR inline diffs are scoped to the active project', 'folder-opened'),
155
- ]
156
- }
157
-
158
- const manifest = loadManifest(root)
159
- const diffs = manifest
160
- .diffs
161
- .slice()
162
- .sort((a, b) => String(b.createdAt).localeCompare(String(a.createdAt)))
163
-
164
- if (diffs.length === 0) {
165
- return [
166
- new InfoItem(
167
- 'Ready for inline review',
168
- fs.existsSync(manifestPath(root)) ? 'No pending diff bundles' : 'No diff bundles captured yet',
169
- 'pass',
170
- ),
171
- new ActionItem(
172
- 'Show UR status',
173
- 'Provider, model, plugins',
174
- 'pulse',
175
- { command: 'urInlineDiffs.status', title: 'Show UR Status' },
176
- ),
177
- new ActionItem(
178
- 'Refresh',
179
- path.relative(root, manifestPath(root)),
180
- 'refresh',
181
- { command: 'urInlineDiffs.refresh', title: 'Refresh Inline Diffs' },
182
- ),
183
- ]
184
- }
185
-
186
- return diffs.map(bundle => new DiffItem(bundle))
187
- }
188
- }
189
-
190
- function renderDiffHtml(root, bundle) {
191
- const patch = fs.existsSync(patchPath(root, bundle))
192
- ? fs.readFileSync(patchPath(root, bundle), 'utf8')
193
- : ''
194
- const comments = bundle.comments ?? []
195
- return `<!doctype html>
196
- <html lang="en">
197
- <head>
198
- <meta charset="utf-8">
199
- <meta name="viewport" content="width=device-width, initial-scale=1">
200
- <style>
201
- :root { color-scheme: light dark; }
202
- body { font: 13px/1.5 var(--vscode-font-family); color: var(--vscode-foreground); padding: 20px; margin: 0; }
203
- header { border-bottom: 1px solid var(--vscode-panel-border); padding-bottom: 14px; margin-bottom: 16px; }
204
- h1 { font-size: 20px; font-weight: 600; margin: 0 0 6px; }
205
- h2 { font-size: 14px; margin: 20px 0 10px; }
206
- .meta, .where { color: var(--vscode-descriptionForeground); }
207
- .chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
208
- .chip { border: 1px solid var(--vscode-panel-border); border-radius: 4px; padding: 3px 8px; background: var(--vscode-sideBar-background); }
209
- pre { background: var(--vscode-editor-background); border: 1px solid var(--vscode-panel-border); border-radius: 6px; padding: 14px; overflow: auto; font-family: var(--vscode-editor-font-family); }
210
- .comments { margin-top: 18px; }
211
- .comment { border: 1px solid var(--vscode-panel-border); border-radius: 6px; padding: 10px 12px; margin-bottom: 10px; background: var(--vscode-sideBar-background); }
212
- </style>
213
- </head>
214
- <body>
215
- <header>
216
- <h1>${escapeHtml(bundle.title)}</h1>
217
- <div class="meta">${escapeHtml(bundle.id)} · ${escapeHtml(formatRelativeTime(bundle.updatedAt ?? bundle.createdAt))}</div>
218
- <div class="chips">
219
- <span class="chip">${escapeHtml(bundle.status ?? 'captured')}</span>
220
- <span class="chip">${escapeHtml(formatCount(bundle.files?.length ?? 0, 'file'))}</span>
221
- <span class="chip">${escapeHtml(formatCount(comments.length, 'comment'))}</span>
222
- </div>
223
- </header>
224
- <pre>${escapeHtml(patch)}</pre>
225
- <section class="comments">
226
- <h2>Comments</h2>
227
- ${comments.length === 0 ? '<p class="meta">No comments yet.</p>' : comments.map(comment => {
228
- const where = comment.file ? `${comment.file}${comment.line ? `:${comment.line}` : ''}` : 'General'
229
- return `<div class="comment"><div class="where">${escapeHtml(where)} · ${escapeHtml(comment.at ?? '')}</div><div>${escapeHtml(comment.text)}</div></div>`
230
- }).join('')}
231
- </section>
232
- </body>
233
- </html>`
234
- }
235
-
236
- async function openDiff(item) {
237
- const root = workspaceRoot()
238
- const bundle = item?.bundle
239
- if (!root || !bundle) {
240
- vscode.window.showWarningMessage('No UR inline diff selected.')
241
- return
242
- }
243
- const panel = vscode.window.createWebviewPanel(
244
- 'urInlineDiff',
245
- `UR ${bundle.id}`,
246
- vscode.ViewColumn.Active,
247
- { enableScripts: false },
248
- )
249
- const latest = readJson(metadataPath(root, bundle), bundle)
250
- panel.webview.html = renderDiffHtml(root, latest)
251
- }
252
-
253
- async function commentDiff(item, provider) {
254
- const root = workspaceRoot()
255
- const bundle = item?.bundle
256
- if (!root || !bundle) {
257
- vscode.window.showWarningMessage('No UR inline diff selected.')
258
- return
259
- }
260
- const text = await vscode.window.showInputBox({
261
- title: `Comment on ${bundle.id}`,
262
- prompt: 'Comment text',
263
- ignoreFocusOut: true,
264
- })
265
- if (!text?.trim()) return
266
-
267
- const manifest = loadManifest(root)
268
- const manifestBundle = manifest.diffs.find(diff => diff.id === bundle.id)
269
- if (!manifestBundle) {
270
- vscode.window.showErrorMessage(`UR inline diff not found: ${bundle.id}`)
271
- return
272
- }
273
- const at = new Date().toISOString()
274
- const comment = { at, text: text.trim() }
275
- manifestBundle.status = 'commented'
276
- manifestBundle.updatedAt = at
277
- manifestBundle.comments = [...(manifestBundle.comments ?? []), comment]
278
- writeJson(manifestPath(root), manifest)
279
- writeJson(metadataPath(root, manifestBundle), manifestBundle)
280
- provider.refresh()
281
- vscode.window.showInformationMessage(`Added UR comment to ${bundle.id}.`)
282
- }
283
-
284
- function setBundleStatus(root, bundleId, status) {
285
- const manifest = loadManifest(root)
286
- const bundle = manifest.diffs.find(diff => diff.id === bundleId)
287
- if (!bundle) return null
288
- bundle.status = status
289
- bundle.updatedAt = new Date().toISOString()
290
- writeJson(manifestPath(root), manifest)
291
- writeJson(metadataPath(root, bundle), bundle)
292
- return bundle
293
- }
294
-
295
- // Apply the captured patch to the working tree. Never silent: the user is asked
296
- // to confirm, and the result is reported. Uses `git apply` from the repo root.
297
- async function applyDiff(item, provider) {
298
- const root = workspaceRoot()
299
- const bundle = item?.bundle
300
- if (!root || !bundle) {
301
- vscode.window.showWarningMessage('No UR inline diff selected.')
302
- return
303
- }
304
- const patch = patchPath(root, bundle)
305
- if (!fs.existsSync(patch)) {
306
- vscode.window.showErrorMessage(`UR patch file missing for ${bundle.id}.`)
307
- return
308
- }
309
- const choice = await vscode.window.showWarningMessage(
310
- `Apply UR patch ${bundle.id} to your working tree? This modifies ${bundle.files?.length ?? 0} file(s).`,
311
- { modal: true },
312
- 'Apply',
313
- )
314
- if (choice !== 'Apply') return
315
- try {
316
- await execFileAsync('git', ['apply', '--whitespace=nowarn', patch], { cwd: root })
317
- setBundleStatus(root, bundle.id, 'applied')
318
- provider.refresh()
319
- vscode.window.showInformationMessage(`Applied UR patch ${bundle.id}.`)
320
- } catch (error) {
321
- const message = error?.stderr || error?.message || String(error)
322
- vscode.window.showErrorMessage(`Failed to apply UR patch ${bundle.id}: ${message}`)
323
- }
324
- }
325
-
326
- async function rejectDiff(item, provider) {
327
- const root = workspaceRoot()
328
- const bundle = item?.bundle
329
- if (!root || !bundle) {
330
- vscode.window.showWarningMessage('No UR inline diff selected.')
331
- return
332
- }
333
- const updated = setBundleStatus(root, bundle.id, 'rejected')
334
- if (!updated) {
335
- vscode.window.showErrorMessage(`UR inline diff not found: ${bundle.id}`)
336
- return
337
- }
338
- provider.refresh()
339
- vscode.window.showInformationMessage(`Rejected UR patch ${bundle.id} (no files changed).`)
340
- }
341
-
342
- async function showStatus(channel) {
343
- const root = workspaceRoot()
344
- if (!root) {
345
- vscode.window.showWarningMessage('Open a workspace folder to query UR status.')
346
- return
347
- }
348
- channel.clear()
349
- channel.show(true)
350
- channel.appendLine('Running: ur ide status')
351
- try {
352
- const { stdout } = await execFileAsync('ur', ['ide', 'status'], { cwd: root })
353
- channel.appendLine(stdout.trim())
354
- } catch (error) {
355
- channel.appendLine(
356
- `Could not run \`ur ide status\`: ${error?.message || String(error)}\n` +
357
- 'Ensure the UR CLI is installed and on PATH.',
358
- )
359
- }
360
- }
361
-
362
- function activate(context) {
363
- const provider = new DiffProvider()
364
- const channel = vscode.window.createOutputChannel('UR')
365
- const tree = vscode.window.createTreeView('urInlineDiffs', {
366
- treeDataProvider: provider,
367
- showCollapseAll: false,
368
- })
369
- context.subscriptions.push(
370
- channel,
371
- tree,
372
- vscode.commands.registerCommand('urInlineDiffs.refresh', () => provider.refresh()),
373
- vscode.commands.registerCommand('urInlineDiffs.open', item => openDiff(item)),
374
- vscode.commands.registerCommand('urInlineDiffs.comment', item => commentDiff(item, provider)),
375
- vscode.commands.registerCommand('urInlineDiffs.apply', item => applyDiff(item, provider)),
376
- vscode.commands.registerCommand('urInlineDiffs.reject', item => rejectDiff(item, provider)),
377
- vscode.commands.registerCommand('urInlineDiffs.status', () => showStatus(channel)),
378
- )
379
- }
380
-
381
- function deactivate() {}
382
-
383
- module.exports = { activate, deactivate }