@imdeadpool/guardex 7.0.39 → 7.0.43
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/README.md +85 -16
- package/package.json +2 -1
- package/skills/gitguardex/SKILL.md +13 -0
- package/skills/guardex-merge-skills-to-dev/SKILL.md +59 -0
- package/src/agents/cleanup-sessions.js +126 -0
- package/src/agents/detect.js +160 -0
- package/src/agents/finish.js +172 -0
- package/src/agents/inspect.js +189 -0
- package/src/agents/launch.js +240 -0
- package/src/agents/registry.js +133 -0
- package/src/agents/selection-panel.js +571 -0
- package/src/agents/sessions.js +151 -0
- package/src/agents/start.js +591 -0
- package/src/agents/status.js +143 -0
- package/src/agents/terminal.js +152 -0
- package/src/budget/index.js +343 -0
- package/src/ci-init/index.js +265 -0
- package/src/cli/args.js +305 -1
- package/src/cli/main.js +262 -132
- package/src/cockpit/action-runner.js +3 -0
- package/src/cockpit/actions.js +80 -0
- package/src/cockpit/control.js +1121 -0
- package/src/cockpit/index.js +426 -0
- package/src/cockpit/keybindings.js +224 -0
- package/src/cockpit/kitty-layout.js +549 -0
- package/src/cockpit/kitty-tree.js +144 -0
- package/src/cockpit/layout.js +224 -0
- package/src/cockpit/logs-reader.js +182 -0
- package/src/cockpit/menu.js +204 -0
- package/src/cockpit/pane-actions.js +597 -0
- package/src/cockpit/pane-menu.js +387 -0
- package/src/cockpit/projects-finder.js +178 -0
- package/src/cockpit/render.js +215 -0
- package/src/cockpit/settings-render.js +128 -0
- package/src/cockpit/settings.js +124 -0
- package/src/cockpit/shortcuts.js +24 -0
- package/src/cockpit/sidebar.js +311 -0
- package/src/cockpit/state.js +72 -0
- package/src/cockpit/theme.js +128 -0
- package/src/cockpit/welcome.js +266 -0
- package/src/context.js +78 -35
- package/src/doctor/index.js +4 -3
- package/src/finish/index.js +39 -2
- package/src/git/index.js +65 -0
- package/src/kitty/command.js +101 -0
- package/src/kitty/runtime.js +250 -0
- package/src/output/index.js +1 -1
- package/src/pr-review.js +241 -0
- package/src/scaffold/index.js +19 -0
- package/src/submodule/index.js +288 -0
- package/src/terminal/index.js +120 -0
- package/src/terminal/kitty.js +622 -0
- package/src/terminal/tmux.js +126 -0
- package/src/tmux/command.js +27 -0
- package/src/tmux/session.js +89 -0
- package/templates/AGENTS.multiagent-safety.md +421 -37
- package/templates/codex/skills/gitguardex/SKILL.md +2 -0
- package/templates/githooks/pre-commit +22 -1
- package/templates/github/workflows/README.md +87 -0
- package/templates/github/workflows/ci-full.yml +55 -0
- package/templates/github/workflows/ci.yml +56 -0
- package/templates/github/workflows/cr.yml +20 -1
- package/templates/scripts/agent-branch-finish.sh +545 -27
- package/templates/scripts/agent-branch-start.sh +193 -21
- package/templates/scripts/agent-preflight.sh +89 -0
- package/templates/scripts/agent-worktree-prune.sh +96 -5
- package/templates/scripts/codex-agent.sh +41 -6
- package/templates/scripts/openspec/init-plan-workspace.sh +43 -0
- package/templates/scripts/review-bot-watch.sh +31 -2
- package/templates/scripts/agent-session-state.js +0 -171
- package/templates/scripts/install-vscode-active-agents-extension.js +0 -135
- package/templates/vscode/guardex-active-agents/README.md +0 -34
- package/templates/vscode/guardex-active-agents/extension.js +0 -3782
- package/templates/vscode/guardex-active-agents/fileicons/gitguardex-fileicons.json +0 -54
- package/templates/vscode/guardex-active-agents/fileicons/icons/agent.svg +0 -5
- package/templates/vscode/guardex-active-agents/fileicons/icons/branch.svg +0 -7
- package/templates/vscode/guardex-active-agents/fileicons/icons/config.svg +0 -4
- package/templates/vscode/guardex-active-agents/fileicons/icons/hook.svg +0 -4
- package/templates/vscode/guardex-active-agents/fileicons/icons/openspec.svg +0 -5
- package/templates/vscode/guardex-active-agents/fileicons/icons/plan.svg +0 -4
- package/templates/vscode/guardex-active-agents/fileicons/icons/spec.svg +0 -5
- package/templates/vscode/guardex-active-agents/icon.png +0 -0
- package/templates/vscode/guardex-active-agents/media/active-agents-hivemind.svg +0 -14
- package/templates/vscode/guardex-active-agents/package.json +0 -169
- package/templates/vscode/guardex-active-agents/session-schema.js +0 -1348
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const tmuxCommand = require('../tmux/command');
|
|
4
|
+
const tmuxSession = require('../tmux/session');
|
|
5
|
+
|
|
6
|
+
function text(value, fallback = '') {
|
|
7
|
+
if (typeof value === 'string') return value.trim() || fallback;
|
|
8
|
+
if (value === null || value === undefined) return fallback;
|
|
9
|
+
return String(value).trim() || fallback;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function requireText(value, name) {
|
|
13
|
+
const normalized = text(value);
|
|
14
|
+
if (!normalized) {
|
|
15
|
+
throw new TypeError(`${name} must be a non-empty string`);
|
|
16
|
+
}
|
|
17
|
+
return normalized;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function targetId(target) {
|
|
21
|
+
if (target && typeof target === 'object') {
|
|
22
|
+
return requireText(target.paneId || target.tmuxPaneId || target.tmuxTarget || target.id || target.target, 'tmux target');
|
|
23
|
+
}
|
|
24
|
+
return requireText(target, 'tmux target');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function assertStatus(result, message) {
|
|
28
|
+
if (result && result.error) throw result.error;
|
|
29
|
+
if (!result || result.status === 0) return result;
|
|
30
|
+
const detail = String(result.stderr || result.stdout || '').trim();
|
|
31
|
+
throw new Error(`${message}${detail ? `: ${detail}` : '.'}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function defaultTmuxApi() {
|
|
35
|
+
return {
|
|
36
|
+
ensureTmuxAvailable: tmuxSession.ensureTmuxAvailable,
|
|
37
|
+
sessionExists: tmuxSession.sessionExists,
|
|
38
|
+
createSession: tmuxSession.createSession,
|
|
39
|
+
attachSession: tmuxSession.attachSession,
|
|
40
|
+
newWindowOrPane: tmuxSession.newWindowOrPane,
|
|
41
|
+
sendKeys: tmuxSession.sendKeys,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function createBackend(options = {}) {
|
|
46
|
+
const tmux = options.tmux || defaultTmuxApi();
|
|
47
|
+
const runTmux = typeof options.runTmux === 'function' ? options.runTmux : tmuxCommand.runTmux;
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
name: 'tmux',
|
|
51
|
+
isAvailable() {
|
|
52
|
+
try {
|
|
53
|
+
if (typeof tmux.isAvailable === 'function') return Boolean(tmux.isAvailable());
|
|
54
|
+
tmux.ensureTmuxAvailable();
|
|
55
|
+
return true;
|
|
56
|
+
} catch (_error) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
openCockpitLayout(config = {}) {
|
|
61
|
+
const sessionName = requireText(config.sessionName, 'tmux sessionName');
|
|
62
|
+
const repoRoot = requireText(config.repoRoot, 'tmux repoRoot');
|
|
63
|
+
const command = requireText(config.command, 'tmux cockpit command');
|
|
64
|
+
|
|
65
|
+
tmux.ensureTmuxAvailable();
|
|
66
|
+
|
|
67
|
+
if (tmux.sessionExists(sessionName)) {
|
|
68
|
+
assertStatus(tmux.attachSession(sessionName), `tmux could not attach session '${sessionName}'`);
|
|
69
|
+
return { action: 'attached', sessionName, repoRoot };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
assertStatus(
|
|
73
|
+
tmux.createSession(sessionName, repoRoot),
|
|
74
|
+
`tmux could not create session '${sessionName}'`,
|
|
75
|
+
);
|
|
76
|
+
assertStatus(
|
|
77
|
+
tmux.sendKeys(sessionName, command),
|
|
78
|
+
'tmux could not start cockpit control pane',
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
if (config.attach) {
|
|
82
|
+
assertStatus(tmux.attachSession(sessionName), `tmux could not attach session '${sessionName}'`);
|
|
83
|
+
return { action: 'created-attached', sessionName, repoRoot };
|
|
84
|
+
}
|
|
85
|
+
return { action: 'created', sessionName, repoRoot };
|
|
86
|
+
},
|
|
87
|
+
launchAgentPane(config = {}) {
|
|
88
|
+
const session = config.session && typeof config.session === 'object' ? config.session : {};
|
|
89
|
+
const cwd = requireText(config.worktree || session.worktreePath || session.path, 'tmux agent worktree');
|
|
90
|
+
const result = tmux.newWindowOrPane({
|
|
91
|
+
pane: true,
|
|
92
|
+
split: 'horizontal',
|
|
93
|
+
target: config.target || session.tmuxTarget || session.tmuxSession || session.sessionName,
|
|
94
|
+
cwd,
|
|
95
|
+
name: config.title || session.title,
|
|
96
|
+
});
|
|
97
|
+
return assertStatus(result, 'tmux could not launch agent pane');
|
|
98
|
+
},
|
|
99
|
+
launchTerminalPane(config = {}) {
|
|
100
|
+
const result = tmux.newWindowOrPane({
|
|
101
|
+
pane: true,
|
|
102
|
+
split: 'horizontal',
|
|
103
|
+
target: config.target,
|
|
104
|
+
cwd: requireText(config.cwd, 'tmux terminal cwd'),
|
|
105
|
+
name: config.title,
|
|
106
|
+
});
|
|
107
|
+
return assertStatus(result, 'tmux could not launch terminal pane');
|
|
108
|
+
},
|
|
109
|
+
focusPane(target) {
|
|
110
|
+
return assertStatus(runTmux(['select-pane', '-t', targetId(target)]), 'tmux could not focus pane');
|
|
111
|
+
},
|
|
112
|
+
closePane(target) {
|
|
113
|
+
return assertStatus(runTmux(['kill-pane', '-t', targetId(target)]), 'tmux could not close pane');
|
|
114
|
+
},
|
|
115
|
+
sendText(target, value, options = {}) {
|
|
116
|
+
const args = ['send-keys', '-t', targetId(target), String(value === undefined || value === null ? '' : value)];
|
|
117
|
+
if (options.submit) args.push('C-m');
|
|
118
|
+
return assertStatus(runTmux(args), 'tmux could not send text');
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
module.exports = {
|
|
124
|
+
createBackend,
|
|
125
|
+
targetId,
|
|
126
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const runtime = require('../core/runtime');
|
|
2
|
+
|
|
3
|
+
function assertArgs(args) {
|
|
4
|
+
if (!Array.isArray(args)) {
|
|
5
|
+
throw new TypeError('tmux args must be an array');
|
|
6
|
+
}
|
|
7
|
+
for (const arg of args) {
|
|
8
|
+
if (typeof arg !== 'string') {
|
|
9
|
+
throw new TypeError('tmux args must contain only strings');
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function runTmux(args, options = {}) {
|
|
15
|
+
assertArgs(args);
|
|
16
|
+
return runtime.run(process.env.GUARDEX_TMUX_BIN || 'tmux', args, options);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function isTmuxAvailable() {
|
|
20
|
+
const result = runTmux(['-V'], { stdio: 'pipe' });
|
|
21
|
+
return result.status === 0 && !result.error;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = {
|
|
25
|
+
isTmuxAvailable,
|
|
26
|
+
runTmux,
|
|
27
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const tmux = require('./command');
|
|
2
|
+
|
|
3
|
+
function requireName(name) {
|
|
4
|
+
if (typeof name !== 'string' || name.trim() === '') {
|
|
5
|
+
throw new TypeError('tmux session name must be a non-empty string');
|
|
6
|
+
}
|
|
7
|
+
return name;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function addCwd(args, cwd) {
|
|
11
|
+
if (cwd !== undefined) {
|
|
12
|
+
if (typeof cwd !== 'string' || cwd.trim() === '') {
|
|
13
|
+
throw new TypeError('tmux cwd must be a non-empty string');
|
|
14
|
+
}
|
|
15
|
+
args.push('-c', cwd);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function ensureTmuxAvailable() {
|
|
20
|
+
if (tmux.isTmuxAvailable()) return;
|
|
21
|
+
throw new Error('tmux is required for gx cockpit. Install tmux and retry.');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function sessionExists(name) {
|
|
25
|
+
const result = tmux.runTmux(['has-session', '-t', requireName(name)], {
|
|
26
|
+
stdio: 'pipe',
|
|
27
|
+
});
|
|
28
|
+
return result.status === 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function createSession(name, cwd) {
|
|
32
|
+
const args = ['new-session', '-d', '-s', requireName(name)];
|
|
33
|
+
addCwd(args, cwd);
|
|
34
|
+
return tmux.runTmux(args);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function attachSession(name) {
|
|
38
|
+
return tmux.runTmux(['attach-session', '-t', requireName(name)], {
|
|
39
|
+
stdio: 'inherit',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function newWindowOrPane(options = {}) {
|
|
44
|
+
const {
|
|
45
|
+
target,
|
|
46
|
+
cwd,
|
|
47
|
+
name,
|
|
48
|
+
pane = false,
|
|
49
|
+
split = 'vertical',
|
|
50
|
+
} = options;
|
|
51
|
+
const args = pane ? ['split-window'] : ['new-window'];
|
|
52
|
+
|
|
53
|
+
if (pane) {
|
|
54
|
+
if (split === 'horizontal') {
|
|
55
|
+
args.push('-h');
|
|
56
|
+
} else if (split === 'vertical') {
|
|
57
|
+
args.push('-v');
|
|
58
|
+
} else {
|
|
59
|
+
throw new TypeError('tmux split must be horizontal or vertical');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (target !== undefined) {
|
|
63
|
+
args.push('-t', requireName(target));
|
|
64
|
+
}
|
|
65
|
+
if (!pane && name !== undefined) {
|
|
66
|
+
args.push('-n', requireName(name));
|
|
67
|
+
}
|
|
68
|
+
addCwd(args, cwd);
|
|
69
|
+
return tmux.runTmux(args);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function sendKeys(paneId, command) {
|
|
73
|
+
if (typeof paneId !== 'string' || paneId.trim() === '') {
|
|
74
|
+
throw new TypeError('tmux pane id must be a non-empty string');
|
|
75
|
+
}
|
|
76
|
+
if (typeof command !== 'string') {
|
|
77
|
+
throw new TypeError('tmux command must be a string');
|
|
78
|
+
}
|
|
79
|
+
return tmux.runTmux(['send-keys', '-t', paneId, command, 'C-m']);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
module.exports = {
|
|
83
|
+
ensureTmuxAvailable,
|
|
84
|
+
sessionExists,
|
|
85
|
+
createSession,
|
|
86
|
+
attachSession,
|
|
87
|
+
newWindowOrPane,
|
|
88
|
+
sendKeys,
|
|
89
|
+
};
|