@imdeadpool/guardex 7.0.41 → 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 +68 -13
- 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 +76 -33
- package/src/doctor/index.js +3 -2
- 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 +27 -1
- 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 +544 -26
- package/templates/scripts/agent-branch-start.sh +89 -22
- 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,288 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
|
|
6
|
+
const { run } = require('../core/runtime');
|
|
7
|
+
const { TOOL_NAME, SHORT_TOOL_NAME } = require('../context');
|
|
8
|
+
const { resolveRepoRoot, currentBranchName } = require('../git');
|
|
9
|
+
|
|
10
|
+
function gitOut(cwd, args, { allowFailure = false } = {}) {
|
|
11
|
+
const result = run('git', ['-C', cwd, ...args]);
|
|
12
|
+
if (!allowFailure && result.status !== 0) {
|
|
13
|
+
throw new Error(`git ${args.join(' ')} failed: ${(result.stderr || '').trim()}`);
|
|
14
|
+
}
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function parseGitmodules(repoRoot) {
|
|
19
|
+
const file = path.join(repoRoot, '.gitmodules');
|
|
20
|
+
if (!fs.existsSync(file)) return [];
|
|
21
|
+
const text = fs.readFileSync(file, 'utf8');
|
|
22
|
+
const entries = [];
|
|
23
|
+
let current = null;
|
|
24
|
+
for (const rawLine of text.split(/\r?\n/)) {
|
|
25
|
+
const line = rawLine.trim();
|
|
26
|
+
if (!line || line.startsWith('#')) continue;
|
|
27
|
+
const header = line.match(/^\[submodule\s+"([^"]+)"\]$/);
|
|
28
|
+
if (header) {
|
|
29
|
+
if (current) entries.push(current);
|
|
30
|
+
current = { name: header[1], path: '', url: '', branch: '' };
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (!current) continue;
|
|
34
|
+
const kv = line.match(/^([a-zA-Z][a-zA-Z0-9._-]*)\s*=\s*(.*)$/);
|
|
35
|
+
if (!kv) continue;
|
|
36
|
+
const [, key, value] = kv;
|
|
37
|
+
if (key === 'path') current.path = value;
|
|
38
|
+
else if (key === 'url') current.url = value;
|
|
39
|
+
else if (key === 'branch') current.branch = value;
|
|
40
|
+
}
|
|
41
|
+
if (current) entries.push(current);
|
|
42
|
+
return entries.filter((entry) => entry.path);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function readSubmoduleHeadSha(repoRoot, submodulePath) {
|
|
46
|
+
const result = gitOut(repoRoot, ['-C', submodulePath, 'rev-parse', 'HEAD'], { allowFailure: true });
|
|
47
|
+
if (result.status !== 0) return '';
|
|
48
|
+
return (result.stdout || '').trim();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function submoduleIsInitialized(repoRoot, submodulePath) {
|
|
52
|
+
const fullPath = path.join(repoRoot, submodulePath);
|
|
53
|
+
if (!fs.existsSync(fullPath)) return false;
|
|
54
|
+
const dotGit = path.join(fullPath, '.git');
|
|
55
|
+
return fs.existsSync(dotGit);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function ensureSubmoduleInitialized(repoRoot, submodulePath, { dryRun }) {
|
|
59
|
+
if (submoduleIsInitialized(repoRoot, submodulePath)) return { initialized: false };
|
|
60
|
+
if (dryRun) return { initialized: false, wouldInit: true };
|
|
61
|
+
gitOut(repoRoot, ['submodule', 'update', '--init', submodulePath]);
|
|
62
|
+
return { initialized: true };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function submoduleWorkingTreeDirty(repoRoot, submodulePath) {
|
|
66
|
+
const result = gitOut(repoRoot, ['-C', submodulePath, 'status', '--porcelain'], { allowFailure: true });
|
|
67
|
+
if (result.status !== 0) return false;
|
|
68
|
+
return Boolean((result.stdout || '').trim());
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function fetchSubmodule(repoRoot, submodulePath) {
|
|
72
|
+
return gitOut(repoRoot, ['-C', submodulePath, 'fetch', '--quiet', 'origin'], { allowFailure: true });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function resolveRemoteSha(repoRoot, submodulePath, ref) {
|
|
76
|
+
const candidate = ref || 'main';
|
|
77
|
+
const remoteRef = candidate.startsWith('origin/') ? candidate : `origin/${candidate}`;
|
|
78
|
+
const result = gitOut(repoRoot, ['-C', submodulePath, 'rev-parse', remoteRef], { allowFailure: true });
|
|
79
|
+
if (result.status !== 0) return { ok: false, ref: remoteRef, reason: (result.stderr || '').trim().split('\n')[0] };
|
|
80
|
+
return { ok: true, ref: remoteRef, sha: (result.stdout || '').trim() };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function checkoutDetached(repoRoot, submodulePath, sha) {
|
|
84
|
+
return gitOut(repoRoot, ['-C', submodulePath, 'checkout', '--detach', sha]);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function stageSubmoduleInParent(repoRoot, submodulePath) {
|
|
88
|
+
return gitOut(repoRoot, ['add', '--', submodulePath]);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function repoIsClean(repoRoot) {
|
|
92
|
+
const result = gitOut(repoRoot, ['status', '--porcelain'], { allowFailure: true });
|
|
93
|
+
if (result.status !== 0) return true;
|
|
94
|
+
return !(result.stdout || '').trim();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function isProtectedBranch(repoRoot) {
|
|
98
|
+
const branch = currentBranchName(repoRoot) || '';
|
|
99
|
+
if (!branch) return false;
|
|
100
|
+
if (branch.startsWith('agent/')) return false;
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function commitPointerBumps(repoRoot, bumped) {
|
|
105
|
+
const paths = bumped.map((entry) => entry.path).join(', ');
|
|
106
|
+
const subject = `chore: bump submodule pointer${bumped.length === 1 ? '' : 's'} (${paths})`;
|
|
107
|
+
const bodyLines = bumped.map((entry) => `- ${entry.path}: ${entry.before.slice(0, 8)}..${entry.after.slice(0, 8)} (${entry.ref})`);
|
|
108
|
+
const fullMessage = `${subject}\n\n${bodyLines.join('\n')}\n`;
|
|
109
|
+
return gitOut(repoRoot, ['commit', '-m', fullMessage]);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function advance(options) {
|
|
113
|
+
const repoRoot = resolveRepoRoot(options.target);
|
|
114
|
+
const entries = parseGitmodules(repoRoot);
|
|
115
|
+
if (entries.length === 0) {
|
|
116
|
+
return {
|
|
117
|
+
repoRoot,
|
|
118
|
+
operations: [],
|
|
119
|
+
committed: false,
|
|
120
|
+
pushed: false,
|
|
121
|
+
message: 'no submodules declared in .gitmodules',
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const filter = options.path ? path.normalize(options.path).replace(/\/+$/, '') : '';
|
|
126
|
+
const targets = filter
|
|
127
|
+
? entries.filter((entry) => path.normalize(entry.path) === filter)
|
|
128
|
+
: entries;
|
|
129
|
+
if (filter && targets.length === 0) {
|
|
130
|
+
throw new Error(`submodule path not found in .gitmodules: ${options.path}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const overrideBranch = options.branch || '';
|
|
134
|
+
const dryRun = Boolean(options.dryRun);
|
|
135
|
+
const operations = [];
|
|
136
|
+
const bumped = [];
|
|
137
|
+
|
|
138
|
+
for (const entry of targets) {
|
|
139
|
+
const initResult = ensureSubmoduleInitialized(repoRoot, entry.path, { dryRun });
|
|
140
|
+
if (initResult.wouldInit) {
|
|
141
|
+
operations.push({
|
|
142
|
+
path: entry.path,
|
|
143
|
+
status: 'would-init',
|
|
144
|
+
ref: overrideBranch || entry.branch || 'main',
|
|
145
|
+
note: 'submodule not initialized; would run `git submodule update --init`',
|
|
146
|
+
});
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (submoduleWorkingTreeDirty(repoRoot, entry.path)) {
|
|
151
|
+
operations.push({
|
|
152
|
+
path: entry.path,
|
|
153
|
+
status: 'skipped-dirty',
|
|
154
|
+
ref: overrideBranch || entry.branch || 'main',
|
|
155
|
+
note: 'submodule has local uncommitted changes; refusing to overwrite',
|
|
156
|
+
});
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const before = readSubmoduleHeadSha(repoRoot, entry.path);
|
|
161
|
+
fetchSubmodule(repoRoot, entry.path);
|
|
162
|
+
const remote = resolveRemoteSha(repoRoot, entry.path, overrideBranch || entry.branch);
|
|
163
|
+
if (!remote.ok) {
|
|
164
|
+
operations.push({
|
|
165
|
+
path: entry.path,
|
|
166
|
+
status: 'failed',
|
|
167
|
+
ref: remote.ref,
|
|
168
|
+
note: `could not resolve ${remote.ref}: ${remote.reason || 'unknown error'}`,
|
|
169
|
+
});
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (before === remote.sha) {
|
|
174
|
+
operations.push({
|
|
175
|
+
path: entry.path,
|
|
176
|
+
status: 'unchanged',
|
|
177
|
+
ref: remote.ref,
|
|
178
|
+
before,
|
|
179
|
+
after: remote.sha,
|
|
180
|
+
note: 'already at remote tip',
|
|
181
|
+
});
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (dryRun) {
|
|
186
|
+
operations.push({
|
|
187
|
+
path: entry.path,
|
|
188
|
+
status: 'would-advance',
|
|
189
|
+
ref: remote.ref,
|
|
190
|
+
before,
|
|
191
|
+
after: remote.sha,
|
|
192
|
+
note: `${before.slice(0, 8)}..${remote.sha.slice(0, 8)}`,
|
|
193
|
+
});
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
checkoutDetached(repoRoot, entry.path, remote.sha);
|
|
198
|
+
stageSubmoduleInParent(repoRoot, entry.path);
|
|
199
|
+
operations.push({
|
|
200
|
+
path: entry.path,
|
|
201
|
+
status: 'advanced',
|
|
202
|
+
ref: remote.ref,
|
|
203
|
+
before,
|
|
204
|
+
after: remote.sha,
|
|
205
|
+
note: `${before.slice(0, 8)}..${remote.sha.slice(0, 8)}`,
|
|
206
|
+
});
|
|
207
|
+
bumped.push({ path: entry.path, before, after: remote.sha, ref: remote.ref });
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (dryRun || bumped.length === 0) {
|
|
211
|
+
return { repoRoot, operations, committed: false, pushed: false };
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (options.commit === false) {
|
|
215
|
+
return {
|
|
216
|
+
repoRoot,
|
|
217
|
+
operations,
|
|
218
|
+
committed: false,
|
|
219
|
+
pushed: false,
|
|
220
|
+
note: 'pointer bumps staged but not committed (--no-commit)',
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (!repoIsClean(repoRoot)) {
|
|
225
|
+
// We staged submodule entries; check that the working tree is otherwise clean.
|
|
226
|
+
const dirty = gitOut(repoRoot, ['status', '--porcelain'], { allowFailure: true }).stdout || '';
|
|
227
|
+
const lines = dirty.split('\n').filter(Boolean);
|
|
228
|
+
const onlyOurStages = lines.every((line) => {
|
|
229
|
+
const status = line.slice(0, 2);
|
|
230
|
+
const file = line.slice(3);
|
|
231
|
+
return /M /.test(status) && bumped.some((entry) => entry.path === file);
|
|
232
|
+
});
|
|
233
|
+
if (!onlyOurStages) {
|
|
234
|
+
return {
|
|
235
|
+
repoRoot,
|
|
236
|
+
operations,
|
|
237
|
+
committed: false,
|
|
238
|
+
pushed: false,
|
|
239
|
+
note: 'working tree has unrelated changes; pointer bumps staged but not committed',
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (isProtectedBranch(repoRoot)) {
|
|
245
|
+
return {
|
|
246
|
+
repoRoot,
|
|
247
|
+
operations,
|
|
248
|
+
committed: false,
|
|
249
|
+
pushed: false,
|
|
250
|
+
note:
|
|
251
|
+
`current branch '${currentBranchName(repoRoot)}' looks protected; pointer bumps staged but not committed. ` +
|
|
252
|
+
`Start a lane with '${SHORT_TOOL_NAME} branch start' or commit manually.`,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
commitPointerBumps(repoRoot, bumped);
|
|
257
|
+
let pushed = false;
|
|
258
|
+
if (options.push) {
|
|
259
|
+
gitOut(repoRoot, ['push']);
|
|
260
|
+
pushed = true;
|
|
261
|
+
}
|
|
262
|
+
return { repoRoot, operations, committed: true, pushed };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function printAdvanceResult(result) {
|
|
266
|
+
console.log(`[${TOOL_NAME}] submodule advance: ${result.repoRoot}`);
|
|
267
|
+
if (result.operations.length === 0) {
|
|
268
|
+
console.log(` ${result.message || 'nothing to do.'}`);
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
for (const op of result.operations) {
|
|
272
|
+
const before = op.before ? ` ${op.before.slice(0, 8)}` : '';
|
|
273
|
+
const after = op.after ? `..${op.after.slice(0, 8)}` : '';
|
|
274
|
+
const note = op.note ? ` (${op.note})` : '';
|
|
275
|
+
console.log(` - ${op.status.padEnd(14)} ${op.path}${before}${after} [${op.ref}]${note}`);
|
|
276
|
+
}
|
|
277
|
+
if (result.committed) {
|
|
278
|
+
console.log(`[${TOOL_NAME}] Pointer bump committed${result.pushed ? ' and pushed' : ''}.`);
|
|
279
|
+
} else if (result.note) {
|
|
280
|
+
console.log(`[${TOOL_NAME}] ${result.note}`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
module.exports = {
|
|
285
|
+
advance,
|
|
286
|
+
parseGitmodules,
|
|
287
|
+
printAdvanceResult,
|
|
288
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const kitty = require('./kitty');
|
|
4
|
+
const tmux = require('./tmux');
|
|
5
|
+
|
|
6
|
+
const BACKEND_NAMES = new Set(['auto', 'kitty', 'tmux']);
|
|
7
|
+
const DEFAULT_BACKEND = 'tmux';
|
|
8
|
+
|
|
9
|
+
function normalizeBackendName(value, fallback = DEFAULT_BACKEND) {
|
|
10
|
+
const normalized = String(value || fallback).trim().toLowerCase();
|
|
11
|
+
if (!BACKEND_NAMES.has(normalized)) {
|
|
12
|
+
throw new Error(`--backend requires auto, kitty, or tmux`);
|
|
13
|
+
}
|
|
14
|
+
return normalized;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function createBackends(options = {}) {
|
|
18
|
+
return {
|
|
19
|
+
kitty: options.kittyBackend || kitty.createBackend(options.kitty || {}),
|
|
20
|
+
tmux: options.tmuxBackend || tmux.createBackend(options.tmux || {}),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function firstText(...values) {
|
|
25
|
+
for (const value of values) {
|
|
26
|
+
if (typeof value === 'string' && value.trim().length > 0) return value.trim();
|
|
27
|
+
}
|
|
28
|
+
return '';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function metadataOf(target = {}) {
|
|
32
|
+
return target.metadata && typeof target.metadata === 'object' ? target.metadata : {};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function terminalOf(target = {}) {
|
|
36
|
+
return target.terminal && typeof target.terminal === 'object' ? target.terminal : {};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function tmuxOf(target = {}) {
|
|
40
|
+
return target.tmux && typeof target.tmux === 'object' ? target.tmux : {};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function kittyOf(target = {}) {
|
|
44
|
+
return target.kitty && typeof target.kitty === 'object' ? target.kitty : {};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function resolveTargetBackendName(target = {}, fallback = '') {
|
|
48
|
+
const metadata = metadataOf(target);
|
|
49
|
+
const terminal = terminalOf(target);
|
|
50
|
+
const explicit = firstText(
|
|
51
|
+
target.terminalBackend,
|
|
52
|
+
target.backend,
|
|
53
|
+
terminal.backend,
|
|
54
|
+
metadata.terminalBackend,
|
|
55
|
+
metadata['terminal.backend'],
|
|
56
|
+
);
|
|
57
|
+
if (explicit) return normalizeBackendName(explicit);
|
|
58
|
+
|
|
59
|
+
const tmux = tmuxOf(target);
|
|
60
|
+
if (firstText(target.paneId, target.tmuxPaneId, target.tmuxTarget, tmux.paneId, tmux.target, metadata.tmuxPaneId, metadata['tmux.paneId'])) {
|
|
61
|
+
return 'tmux';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const kittyTarget = kittyOf(target);
|
|
65
|
+
if (firstText(
|
|
66
|
+
target.kittyMatch,
|
|
67
|
+
target.match,
|
|
68
|
+
target.kittyWindowId,
|
|
69
|
+
target.windowId,
|
|
70
|
+
target.kittyTitle,
|
|
71
|
+
target.windowTitle,
|
|
72
|
+
terminal.match,
|
|
73
|
+
terminal.windowId,
|
|
74
|
+
terminal.title,
|
|
75
|
+
kittyTarget.match,
|
|
76
|
+
kittyTarget.windowId,
|
|
77
|
+
kittyTarget.title,
|
|
78
|
+
metadata.kittyMatch,
|
|
79
|
+
metadata['kitty.match'],
|
|
80
|
+
metadata.kittyWindowId,
|
|
81
|
+
metadata['kitty.windowId'],
|
|
82
|
+
metadata.kittyTitle,
|
|
83
|
+
metadata['kitty.title'],
|
|
84
|
+
)) {
|
|
85
|
+
return 'kitty';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return fallback ? normalizeBackendName(fallback) : '';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function selectTerminalBackend(value = DEFAULT_BACKEND, options = {}) {
|
|
92
|
+
const name = normalizeBackendName(value);
|
|
93
|
+
const backends = createBackends(options);
|
|
94
|
+
|
|
95
|
+
if (name === 'auto') {
|
|
96
|
+
if (backends.kitty && typeof backends.kitty.isAvailable === 'function' && backends.kitty.isAvailable()) {
|
|
97
|
+
return backends.kitty;
|
|
98
|
+
}
|
|
99
|
+
return backends.tmux;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return backends[name];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function selectTerminalBackendForTarget(target = {}, options = {}) {
|
|
106
|
+
const name = resolveTargetBackendName(target, options.defaultBackend);
|
|
107
|
+
if (!name) return null;
|
|
108
|
+
return selectTerminalBackend(name, options);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
module.exports = {
|
|
112
|
+
DEFAULT_BACKEND,
|
|
113
|
+
normalizeBackendName,
|
|
114
|
+
resolveTargetBackendName,
|
|
115
|
+
selectTerminalBackend,
|
|
116
|
+
selectTerminalBackendForTarget,
|
|
117
|
+
createBackends,
|
|
118
|
+
kitty,
|
|
119
|
+
tmux,
|
|
120
|
+
};
|