@imdeadpool/guardex 7.0.16 → 7.0.19
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/CONTRIBUTING.md +1 -1
- package/README.md +187 -53
- package/bin/multiagent-safety.js +863 -220
- package/package.json +2 -2
- package/templates/AGENTS.multiagent-safety.md +7 -4
- package/templates/codex/skills/gitguardex/SKILL.md +1 -1
- package/templates/codex/skills/guardex-merge-skills-to-dev/SKILL.md +3 -3
- package/templates/githooks/post-checkout +1 -1
- package/templates/githooks/post-merge +19 -6
- package/templates/githooks/pre-commit +29 -10
- package/templates/scripts/agent-branch-finish.sh +32 -19
- package/templates/scripts/agent-branch-merge.sh +24 -5
- package/templates/scripts/agent-branch-start.sh +23 -29
- package/templates/scripts/agent-file-locks.py +11 -11
- package/templates/scripts/agent-session-state.js +110 -0
- package/templates/scripts/codex-agent.sh +113 -54
- package/templates/scripts/install-vscode-active-agents-extension.js +92 -0
- package/templates/scripts/openspec/init-change-workspace.sh +77 -9
- package/templates/scripts/openspec/init-plan-workspace.sh +576 -74
- package/templates/scripts/review-bot-watch.sh +30 -7
- package/templates/vscode/guardex-active-agents/README.md +22 -0
- package/templates/vscode/guardex-active-agents/extension.js +357 -0
- package/templates/vscode/guardex-active-agents/package.json +57 -0
- package/templates/vscode/guardex-active-agents/session-schema.js +407 -0
|
@@ -9,10 +9,12 @@ BASE_BRANCH="${GUARDEX_REVIEW_BOT_BASE_BRANCH:-}"
|
|
|
9
9
|
ONLY_PR="${GUARDEX_REVIEW_BOT_ONLY_PR:-}"
|
|
10
10
|
RETRY_FAILED_RAW="${GUARDEX_REVIEW_BOT_RETRY_FAILED:-false}"
|
|
11
11
|
INCLUDE_DRAFT_RAW="${GUARDEX_REVIEW_BOT_INCLUDE_DRAFT:-false}"
|
|
12
|
+
NODE_BIN="${GUARDEX_NODE_BIN:-node}"
|
|
13
|
+
CLI_ENTRY="${GUARDEX_CLI_ENTRY:-}"
|
|
12
14
|
|
|
13
15
|
usage() {
|
|
14
16
|
cat <<'USAGE'
|
|
15
|
-
Usage:
|
|
17
|
+
Usage: gx review [options]
|
|
16
18
|
|
|
17
19
|
Continuously monitor GitHub pull requests targeting a base branch and dispatch
|
|
18
20
|
one Codex-agent task per newly opened/updated PR.
|
|
@@ -34,6 +36,23 @@ Environment overrides:
|
|
|
34
36
|
USAGE
|
|
35
37
|
}
|
|
36
38
|
|
|
39
|
+
run_guardex_cli() {
|
|
40
|
+
if [[ -n "$CLI_ENTRY" ]]; then
|
|
41
|
+
"$NODE_BIN" "$CLI_ENTRY" "$@"
|
|
42
|
+
return $?
|
|
43
|
+
fi
|
|
44
|
+
if command -v gx >/dev/null 2>&1; then
|
|
45
|
+
gx "$@"
|
|
46
|
+
return $?
|
|
47
|
+
fi
|
|
48
|
+
if command -v gitguardex >/dev/null 2>&1; then
|
|
49
|
+
gitguardex "$@"
|
|
50
|
+
return $?
|
|
51
|
+
fi
|
|
52
|
+
echo "[review-bot-watch] Guardex CLI entrypoint unavailable; rerun via gx." >&2
|
|
53
|
+
return 127
|
|
54
|
+
}
|
|
55
|
+
|
|
37
56
|
normalize_bool() {
|
|
38
57
|
local raw="${1:-}"
|
|
39
58
|
local fallback="${2:-0}"
|
|
@@ -134,16 +153,20 @@ if ! command -v codex >/dev/null 2>&1; then
|
|
|
134
153
|
exit 127
|
|
135
154
|
fi
|
|
136
155
|
|
|
137
|
-
if [[ ! -x "$repo_root/scripts/codex-agent.sh" ]]; then
|
|
138
|
-
echo "[review-bot-watch] Missing scripts/codex-agent.sh. Run: gx setup" >&2
|
|
139
|
-
exit 1
|
|
140
|
-
fi
|
|
141
|
-
|
|
142
156
|
if ! gh auth status >/dev/null 2>&1; then
|
|
143
157
|
echo "[review-bot-watch] gh is not authenticated. Run: gh auth login" >&2
|
|
144
158
|
exit 1
|
|
145
159
|
fi
|
|
146
160
|
|
|
161
|
+
run_codex_agent() {
|
|
162
|
+
local local_script="$repo_root/scripts/codex-agent.sh"
|
|
163
|
+
if [[ -x "$local_script" ]]; then
|
|
164
|
+
bash "$local_script" "$@"
|
|
165
|
+
return $?
|
|
166
|
+
fi
|
|
167
|
+
run_guardex_cli internal run-shell codexAgent --target "$repo_root" "$@"
|
|
168
|
+
}
|
|
169
|
+
|
|
147
170
|
sanitize_slug() {
|
|
148
171
|
local raw="$1"
|
|
149
172
|
local fallback="$2"
|
|
@@ -262,7 +285,7 @@ process_one_pr() {
|
|
|
262
285
|
|
|
263
286
|
echo "[review-bot-watch] Dispatching Codex agent for PR #${pr} (${head_branch})"
|
|
264
287
|
set +e
|
|
265
|
-
|
|
288
|
+
run_codex_agent \
|
|
266
289
|
--task "$task_name" \
|
|
267
290
|
--agent "$AGENT_NAME" \
|
|
268
291
|
--base "$BASE_BRANCH" \
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# GitGuardex Active Agents
|
|
2
|
+
|
|
3
|
+
Local VS Code companion for Guardex-managed repos.
|
|
4
|
+
|
|
5
|
+
What it does:
|
|
6
|
+
|
|
7
|
+
- Adds an `Active Agents` view to the Source Control container.
|
|
8
|
+
- Renders one repo node per live Guardex workspace with grouped `ACTIVE AGENTS` and `CHANGES` sections.
|
|
9
|
+
- Splits live sessions inside `ACTIVE AGENTS` into `WORKING NOW` and `THINKING` groups so active edit lanes stand out immediately.
|
|
10
|
+
- Shows one row per live Guardex sandbox session inside those activity groups.
|
|
11
|
+
- Shows repo-root git changes in a sibling `CHANGES` section when the guarded repo itself is dirty.
|
|
12
|
+
- Derives `thinking` versus `working` from the live sandbox worktree, surfaces working counts in the repo/header summary, and shows changed-file counts for active edits.
|
|
13
|
+
- Uses VS Code's native animated `loading~spin` icon for the running-state affordance.
|
|
14
|
+
- Reads repo-local presence files from `.omx/state/active-sessions/`.
|
|
15
|
+
|
|
16
|
+
Install from a Guardex-wired repo:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
node scripts/install-vscode-active-agents-extension.js
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Then reload the VS Code window.
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
const fs = require('node:fs');
|
|
2
|
+
const path = require('node:path');
|
|
3
|
+
const vscode = require('vscode');
|
|
4
|
+
const { formatElapsedFrom, readActiveSessions, readRepoChanges } = require('./session-schema.js');
|
|
5
|
+
|
|
6
|
+
class InfoItem extends vscode.TreeItem {
|
|
7
|
+
constructor(label, description = '') {
|
|
8
|
+
super(label, vscode.TreeItemCollapsibleState.None);
|
|
9
|
+
this.description = description;
|
|
10
|
+
this.iconPath = new vscode.ThemeIcon('info');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class RepoItem extends vscode.TreeItem {
|
|
15
|
+
constructor(repoRoot, sessions, changes) {
|
|
16
|
+
super(path.basename(repoRoot), vscode.TreeItemCollapsibleState.Expanded);
|
|
17
|
+
this.repoRoot = repoRoot;
|
|
18
|
+
this.sessions = sessions;
|
|
19
|
+
this.changes = changes;
|
|
20
|
+
const descriptionParts = [`${sessions.length} active`];
|
|
21
|
+
const workingCount = countWorkingSessions(sessions);
|
|
22
|
+
if (workingCount > 0) {
|
|
23
|
+
descriptionParts.push(`${workingCount} working`);
|
|
24
|
+
}
|
|
25
|
+
if (changes.length > 0) {
|
|
26
|
+
descriptionParts.push(`${changes.length} changed`);
|
|
27
|
+
}
|
|
28
|
+
this.description = descriptionParts.join(' · ');
|
|
29
|
+
this.tooltip = [
|
|
30
|
+
repoRoot,
|
|
31
|
+
this.description,
|
|
32
|
+
].join('\n');
|
|
33
|
+
this.iconPath = new vscode.ThemeIcon('repo');
|
|
34
|
+
this.contextValue = 'gitguardex.repo';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
class SectionItem extends vscode.TreeItem {
|
|
39
|
+
constructor(label, items, options = {}) {
|
|
40
|
+
super(label, vscode.TreeItemCollapsibleState.Expanded);
|
|
41
|
+
this.items = items;
|
|
42
|
+
this.description = options.description
|
|
43
|
+
|| (items.length > 0 ? String(items.length) : '');
|
|
44
|
+
this.contextValue = 'gitguardex.section';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
class SessionItem extends vscode.TreeItem {
|
|
49
|
+
constructor(session) {
|
|
50
|
+
super(session.label, vscode.TreeItemCollapsibleState.None);
|
|
51
|
+
this.session = session;
|
|
52
|
+
const descriptionParts = [session.activityLabel || 'thinking'];
|
|
53
|
+
if (session.activityCountLabel) {
|
|
54
|
+
descriptionParts.push(session.activityCountLabel);
|
|
55
|
+
}
|
|
56
|
+
descriptionParts.push(session.elapsedLabel || formatElapsedFrom(session.startedAt));
|
|
57
|
+
this.description = descriptionParts.join(' · ');
|
|
58
|
+
const tooltipLines = [
|
|
59
|
+
session.branch,
|
|
60
|
+
`${session.agentName} · ${session.taskName}`,
|
|
61
|
+
`Status ${this.description}`,
|
|
62
|
+
session.changeCount > 0
|
|
63
|
+
? `Changed ${session.activityCountLabel}: ${session.activitySummary}`
|
|
64
|
+
: session.activitySummary,
|
|
65
|
+
`Started ${session.startedAt}`,
|
|
66
|
+
session.worktreePath,
|
|
67
|
+
];
|
|
68
|
+
this.tooltip = tooltipLines.filter(Boolean).join('\n');
|
|
69
|
+
this.iconPath = session.activityKind === 'working'
|
|
70
|
+
? new vscode.ThemeIcon('edit')
|
|
71
|
+
: new vscode.ThemeIcon('loading~spin');
|
|
72
|
+
this.contextValue = 'gitguardex.session';
|
|
73
|
+
this.command = {
|
|
74
|
+
command: 'gitguardex.activeAgents.openWorktree',
|
|
75
|
+
title: 'Open Agent Worktree',
|
|
76
|
+
arguments: [session],
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
class FolderItem extends vscode.TreeItem {
|
|
82
|
+
constructor(label, relativePath, items) {
|
|
83
|
+
super(label, vscode.TreeItemCollapsibleState.Expanded);
|
|
84
|
+
this.relativePath = relativePath;
|
|
85
|
+
this.items = items;
|
|
86
|
+
this.tooltip = relativePath;
|
|
87
|
+
this.iconPath = new vscode.ThemeIcon('folder');
|
|
88
|
+
this.contextValue = 'gitguardex.folder';
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
class ChangeItem extends vscode.TreeItem {
|
|
93
|
+
constructor(change) {
|
|
94
|
+
super(path.basename(change.relativePath), vscode.TreeItemCollapsibleState.None);
|
|
95
|
+
this.change = change;
|
|
96
|
+
this.description = change.statusLabel;
|
|
97
|
+
this.tooltip = [
|
|
98
|
+
change.relativePath,
|
|
99
|
+
`Status ${change.statusText}`,
|
|
100
|
+
change.originalPath ? `Renamed from ${change.originalPath}` : '',
|
|
101
|
+
change.absolutePath,
|
|
102
|
+
].filter(Boolean).join('\n');
|
|
103
|
+
this.resourceUri = vscode.Uri.file(change.absolutePath);
|
|
104
|
+
this.contextValue = 'gitguardex.change';
|
|
105
|
+
this.command = {
|
|
106
|
+
command: 'gitguardex.activeAgents.openChange',
|
|
107
|
+
title: 'Open Changed File',
|
|
108
|
+
arguments: [change],
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function repoRootFromSessionFile(filePath) {
|
|
114
|
+
return path.resolve(path.dirname(filePath), '..', '..', '..');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function buildChangeTreeNodes(changes) {
|
|
118
|
+
const root = [];
|
|
119
|
+
|
|
120
|
+
function sortNodes(nodes) {
|
|
121
|
+
nodes.sort((left, right) => {
|
|
122
|
+
const leftIsFolder = left.kind === 'folder';
|
|
123
|
+
const rightIsFolder = right.kind === 'folder';
|
|
124
|
+
if (leftIsFolder !== rightIsFolder) {
|
|
125
|
+
return leftIsFolder ? -1 : 1;
|
|
126
|
+
}
|
|
127
|
+
return left.label.localeCompare(right.label);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
for (const node of nodes) {
|
|
131
|
+
if (node.kind === 'folder') {
|
|
132
|
+
sortNodes(node.children);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
for (const change of changes) {
|
|
138
|
+
const segments = change.relativePath.split(/[\\/]+/).filter(Boolean);
|
|
139
|
+
if (segments.length <= 1) {
|
|
140
|
+
root.push({ kind: 'change', label: change.relativePath, change });
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
let nodes = root;
|
|
145
|
+
let folderPath = '';
|
|
146
|
+
for (const segment of segments.slice(0, -1)) {
|
|
147
|
+
folderPath = folderPath ? path.posix.join(folderPath, segment) : segment;
|
|
148
|
+
let folderNode = nodes.find((node) => node.kind === 'folder' && node.relativePath === folderPath);
|
|
149
|
+
if (!folderNode) {
|
|
150
|
+
folderNode = {
|
|
151
|
+
kind: 'folder',
|
|
152
|
+
label: segment,
|
|
153
|
+
relativePath: folderPath,
|
|
154
|
+
children: [],
|
|
155
|
+
};
|
|
156
|
+
nodes.push(folderNode);
|
|
157
|
+
}
|
|
158
|
+
nodes = folderNode.children;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
nodes.push({ kind: 'change', label: change.relativePath, change });
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
sortNodes(root);
|
|
165
|
+
|
|
166
|
+
function materialize(nodes) {
|
|
167
|
+
return nodes.map((node) => {
|
|
168
|
+
if (node.kind === 'folder') {
|
|
169
|
+
return new FolderItem(node.label, node.relativePath, materialize(node.children));
|
|
170
|
+
}
|
|
171
|
+
return new ChangeItem(node.change);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return materialize(root);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function countWorkingSessions(sessions) {
|
|
179
|
+
return sessions.filter((session) => session.activityKind === 'working').length;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function buildActiveAgentGroupNodes(sessions) {
|
|
183
|
+
const workingSessions = sessions
|
|
184
|
+
.filter((session) => session.activityKind === 'working')
|
|
185
|
+
.map((session) => new SessionItem(session));
|
|
186
|
+
const thinkingSessions = sessions
|
|
187
|
+
.filter((session) => session.activityKind !== 'working')
|
|
188
|
+
.map((session) => new SessionItem(session));
|
|
189
|
+
const groups = [];
|
|
190
|
+
|
|
191
|
+
if (workingSessions.length > 0) {
|
|
192
|
+
groups.push(new SectionItem('WORKING NOW', workingSessions));
|
|
193
|
+
}
|
|
194
|
+
if (thinkingSessions.length > 0) {
|
|
195
|
+
groups.push(new SectionItem('THINKING', thinkingSessions));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return groups;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
class ActiveAgentsProvider {
|
|
202
|
+
constructor() {
|
|
203
|
+
this.onDidChangeTreeDataEmitter = new vscode.EventEmitter();
|
|
204
|
+
this.onDidChangeTreeData = this.onDidChangeTreeDataEmitter.event;
|
|
205
|
+
this.treeView = null;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
getTreeItem(element) {
|
|
209
|
+
return element;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
attachTreeView(treeView) {
|
|
213
|
+
this.treeView = treeView;
|
|
214
|
+
this.updateViewState(0, 0);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
updateViewState(sessionCount, workingCount) {
|
|
218
|
+
if (!this.treeView) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
this.treeView.badge = sessionCount > 0
|
|
223
|
+
? {
|
|
224
|
+
value: sessionCount,
|
|
225
|
+
tooltip: `${sessionCount} active agent${sessionCount === 1 ? '' : 's'}`
|
|
226
|
+
+ (workingCount > 0 ? ` · ${workingCount} working now` : ''),
|
|
227
|
+
}
|
|
228
|
+
: undefined;
|
|
229
|
+
this.treeView.message = sessionCount > 0
|
|
230
|
+
? undefined
|
|
231
|
+
: 'Start a sandbox session to populate this view.';
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
refresh() {
|
|
235
|
+
this.onDidChangeTreeDataEmitter.fire();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async getChildren(element) {
|
|
239
|
+
if (element instanceof RepoItem) {
|
|
240
|
+
const sectionItems = [
|
|
241
|
+
new SectionItem('ACTIVE AGENTS', buildActiveAgentGroupNodes(element.sessions), {
|
|
242
|
+
description: String(element.sessions.length),
|
|
243
|
+
}),
|
|
244
|
+
];
|
|
245
|
+
if (element.changes.length > 0) {
|
|
246
|
+
sectionItems.push(new SectionItem('CHANGES', buildChangeTreeNodes(element.changes)));
|
|
247
|
+
}
|
|
248
|
+
return sectionItems;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (element instanceof SectionItem || element instanceof FolderItem) {
|
|
252
|
+
return element.items;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const repoEntries = await this.loadRepoEntries();
|
|
256
|
+
const sessionCount = repoEntries.reduce((total, entry) => total + entry.sessions.length, 0);
|
|
257
|
+
const workingCount = repoEntries.reduce(
|
|
258
|
+
(total, entry) => total + countWorkingSessions(entry.sessions),
|
|
259
|
+
0,
|
|
260
|
+
);
|
|
261
|
+
this.updateViewState(sessionCount, workingCount);
|
|
262
|
+
|
|
263
|
+
if (repoEntries.length === 0) {
|
|
264
|
+
return [new InfoItem('No active Guardex agents', 'Open or start a sandbox session.')];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return repoEntries.map((entry) => new RepoItem(entry.repoRoot, entry.sessions, entry.changes));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async loadRepoEntries() {
|
|
271
|
+
const sessionFiles = await vscode.workspace.findFiles(
|
|
272
|
+
'**/.omx/state/active-sessions/*.json',
|
|
273
|
+
'**/{node_modules,.git,.omx/agent-worktrees,.omc/agent-worktrees}/**',
|
|
274
|
+
200,
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
const repoRoots = new Set();
|
|
278
|
+
for (const uri of sessionFiles) {
|
|
279
|
+
repoRoots.add(repoRootFromSessionFile(uri.fsPath));
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (repoRoots.size === 0) {
|
|
283
|
+
for (const workspaceFolder of vscode.workspace.workspaceFolders || []) {
|
|
284
|
+
repoRoots.add(workspaceFolder.uri.fsPath);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const repoEntries = [];
|
|
289
|
+
for (const repoRoot of repoRoots) {
|
|
290
|
+
const sessions = readActiveSessions(repoRoot);
|
|
291
|
+
if (sessions.length > 0) {
|
|
292
|
+
repoEntries.push({
|
|
293
|
+
repoRoot,
|
|
294
|
+
sessions,
|
|
295
|
+
changes: readRepoChanges(repoRoot),
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
repoEntries.sort((left, right) => left.repoRoot.localeCompare(right.repoRoot));
|
|
301
|
+
return repoEntries;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function activate(context) {
|
|
306
|
+
const provider = new ActiveAgentsProvider();
|
|
307
|
+
const treeView = vscode.window.createTreeView('gitguardex.activeAgents', {
|
|
308
|
+
treeDataProvider: provider,
|
|
309
|
+
showCollapseAll: true,
|
|
310
|
+
});
|
|
311
|
+
provider.attachTreeView(treeView);
|
|
312
|
+
const refresh = () => provider.refresh();
|
|
313
|
+
const watcher = vscode.workspace.createFileSystemWatcher('**/.omx/state/active-sessions/*.json');
|
|
314
|
+
const interval = setInterval(refresh, 5_000);
|
|
315
|
+
|
|
316
|
+
context.subscriptions.push(
|
|
317
|
+
treeView,
|
|
318
|
+
vscode.commands.registerCommand('gitguardex.activeAgents.refresh', refresh),
|
|
319
|
+
vscode.commands.registerCommand('gitguardex.activeAgents.openWorktree', async (session) => {
|
|
320
|
+
if (!session?.worktreePath) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
await vscode.commands.executeCommand(
|
|
325
|
+
'vscode.openFolder',
|
|
326
|
+
vscode.Uri.file(session.worktreePath),
|
|
327
|
+
{ forceNewWindow: true },
|
|
328
|
+
);
|
|
329
|
+
}),
|
|
330
|
+
vscode.commands.registerCommand('gitguardex.activeAgents.openChange', async (change) => {
|
|
331
|
+
if (!change?.absolutePath) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (!fs.existsSync(change.absolutePath)) {
|
|
336
|
+
vscode.window.showInformationMessage?.(`Changed path is no longer on disk: ${change.relativePath}`);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
await vscode.commands.executeCommand('vscode.open', vscode.Uri.file(change.absolutePath));
|
|
341
|
+
}),
|
|
342
|
+
vscode.workspace.onDidChangeWorkspaceFolders(refresh),
|
|
343
|
+
watcher,
|
|
344
|
+
{ dispose: () => clearInterval(interval) },
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
watcher.onDidCreate(refresh, undefined, context.subscriptions);
|
|
348
|
+
watcher.onDidChange(refresh, undefined, context.subscriptions);
|
|
349
|
+
watcher.onDidDelete(refresh, undefined, context.subscriptions);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function deactivate() {}
|
|
353
|
+
|
|
354
|
+
module.exports = {
|
|
355
|
+
activate,
|
|
356
|
+
deactivate,
|
|
357
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gitguardex-active-agents",
|
|
3
|
+
"displayName": "GitGuardex Active Agents",
|
|
4
|
+
"description": "Shows live Guardex sandbox sessions and repo changes inside VS Code Source Control.",
|
|
5
|
+
"publisher": "recodeee",
|
|
6
|
+
"version": "0.0.1",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"engines": {
|
|
9
|
+
"vscode": "^1.88.0"
|
|
10
|
+
},
|
|
11
|
+
"categories": [
|
|
12
|
+
"Source Control",
|
|
13
|
+
"Other"
|
|
14
|
+
],
|
|
15
|
+
"activationEvents": [
|
|
16
|
+
"workspaceContains:.omx/state/active-sessions",
|
|
17
|
+
"onView:gitguardex.activeAgents"
|
|
18
|
+
],
|
|
19
|
+
"main": "./extension.js",
|
|
20
|
+
"contributes": {
|
|
21
|
+
"commands": [
|
|
22
|
+
{
|
|
23
|
+
"command": "gitguardex.activeAgents.refresh",
|
|
24
|
+
"title": "Refresh Active Agents"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"command": "gitguardex.activeAgents.openWorktree",
|
|
28
|
+
"title": "Open Agent Worktree"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"views": {
|
|
32
|
+
"scm": [
|
|
33
|
+
{
|
|
34
|
+
"id": "gitguardex.activeAgents",
|
|
35
|
+
"name": "Active Agents",
|
|
36
|
+
"visibility": "visible"
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"menus": {
|
|
41
|
+
"view/title": [
|
|
42
|
+
{
|
|
43
|
+
"command": "gitguardex.activeAgents.refresh",
|
|
44
|
+
"when": "view == gitguardex.activeAgents",
|
|
45
|
+
"group": "navigation"
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"view/item/context": [
|
|
49
|
+
{
|
|
50
|
+
"command": "gitguardex.activeAgents.openWorktree",
|
|
51
|
+
"when": "view == gitguardex.activeAgents && viewItem == gitguardex.session",
|
|
52
|
+
"group": "inline"
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|