oh-my-githubcopilot 1.4.1 → 1.8.0-alpha.f50f59a
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/.claude-plugin/plugin.json +36 -6
- package/.mcp.json +17 -0
- package/AGENTS.md +78 -9
- package/CHANGELOG.md +199 -1
- package/README.de.md +112 -26
- package/README.es.md +115 -29
- package/README.fr.md +114 -28
- package/README.it.md +114 -28
- package/README.ja.md +112 -26
- package/README.ko.md +112 -26
- package/README.md +96 -95
- package/README.pt.md +116 -30
- package/README.ru.md +116 -30
- package/README.tr.md +115 -29
- package/README.vi.md +116 -30
- package/README.zh.md +112 -26
- package/agents/analyst.agent.md +27 -0
- package/agents/architect.agent.md +24 -0
- package/agents/code-reviewer.agent.md +24 -0
- package/agents/critic.agent.md +24 -0
- package/agents/debugger.agent.md +24 -0
- package/agents/designer.agent.md +24 -0
- package/agents/document-specialist.agent.md +24 -0
- package/agents/executor.agent.md +27 -0
- package/agents/explorer.agent.md +23 -0
- package/agents/git-master.agent.md +24 -0
- package/agents/orchestrator.agent.md +26 -0
- package/agents/planner.agent.md +24 -0
- package/agents/qa-tester.agent.md +24 -0
- package/agents/researcher.agent.md +18 -0
- package/agents/reviewer.agent.md +23 -0
- package/agents/scientist.agent.md +20 -0
- package/agents/security-reviewer.agent.md +20 -0
- package/agents/simplifier.agent.md +20 -0
- package/agents/test-engineer.agent.md +20 -0
- package/agents/tester.agent.md +20 -0
- package/agents/tracer.agent.md +24 -0
- package/agents/verifier.agent.md +19 -0
- package/agents/writer.agent.md +24 -0
- package/bin/omp-statusline.mjs +179 -0
- package/bin/omp-statusline.mjs.map +7 -0
- package/bin/omp-statusline.sh +21 -0
- package/bin/omp.mjs +709 -16
- package/bin/omp.mjs.map +4 -4
- package/dist/hooks/hud-emitter.mjs +268 -82
- package/dist/hooks/hud-emitter.mjs.map +4 -4
- package/dist/hooks/keyword-detector.mjs +100 -23
- package/dist/hooks/keyword-detector.mjs.map +2 -2
- package/dist/hooks/model-router.mjs +1 -1
- package/dist/hooks/model-router.mjs.map +1 -1
- package/dist/hooks/stop-continuation.mjs +1 -1
- package/dist/hooks/stop-continuation.mjs.map +1 -1
- package/dist/hooks/token-tracker.mjs +2 -1
- package/dist/hooks/token-tracker.mjs.map +2 -2
- package/dist/mcp/server.mjs +85 -53
- package/dist/mcp/server.mjs.map +4 -4
- package/dist/skills/setup.mjs +39 -27
- package/dist/skills/setup.mjs.map +4 -4
- package/hooks/hooks.json +39 -45
- package/package.json +9 -4
- package/plugin.json +71 -0
- package/skills/ai-slop-cleaner/SKILL.md +137 -0
- package/skills/autopilot/SKILL.md +6 -0
- package/skills/configure-notifications/SKILL.md +6 -0
- package/skills/deep-interview/SKILL.md +6 -0
- package/skills/doctor/SKILL.md +188 -0
- package/skills/ecomode/SKILL.md +6 -0
- package/skills/graph-context/SKILL.md +119 -0
- package/skills/graph-provider/SKILL.md +6 -0
- package/skills/graphify/SKILL.md +6 -0
- package/skills/graphwiki/SKILL.md +6 -0
- package/skills/hud/SKILL.md +6 -0
- package/skills/improve-codebase-architecture/SKILL.md +214 -0
- package/skills/interactive-menu/SKILL.md +102 -0
- package/skills/interview/SKILL.md +203 -0
- package/skills/learner/SKILL.md +6 -0
- package/skills/mcp-setup/SKILL.md +6 -0
- package/skills/note/SKILL.md +6 -0
- package/skills/notifications/SKILL.md +190 -0
- package/skills/omp-doctor/SKILL.md +146 -0
- package/skills/omp-plan/SKILL.md +219 -2
- package/skills/omp-reference/SKILL.md +174 -0
- package/skills/omp-setup/SKILL.md +15 -1
- package/skills/pipeline/SKILL.md +6 -0
- package/skills/psm/SKILL.md +6 -0
- package/skills/ralph/SKILL.md +6 -0
- package/skills/ralplan/SKILL.md +148 -0
- package/skills/release/SKILL.md +6 -0
- package/skills/research/SKILL.md +149 -0
- package/skills/session/SKILL.md +220 -0
- package/skills/setup/SKILL.md +6 -0
- package/skills/skillify/SKILL.md +66 -0
- package/skills/spending/SKILL.md +6 -0
- package/skills/swarm/SKILL.md +6 -0
- package/skills/swe-bench/SKILL.md +6 -0
- package/skills/tdd/SKILL.md +246 -0
- package/skills/team/SKILL.md +6 -0
- package/skills/trace/SKILL.md +6 -0
- package/skills/ultrawork/SKILL.md +6 -0
- package/skills/wiki/SKILL.md +6 -0
- package/src/agents/analyst.md +0 -103
- package/src/agents/architect.md +0 -169
- package/src/agents/code-reviewer.md +0 -135
- package/src/agents/critic.md +0 -196
- package/src/agents/debugger.md +0 -132
- package/src/agents/designer.md +0 -103
- package/src/agents/document-specialist.md +0 -111
- package/src/agents/executor.md +0 -120
- package/src/agents/explorer.md +0 -98
- package/src/agents/git-master.md +0 -92
- package/src/agents/orchestrator.md +0 -125
- package/src/agents/planner.md +0 -106
- package/src/agents/qa-tester.md +0 -129
- package/src/agents/researcher.md +0 -102
- package/src/agents/reviewer.md +0 -100
- package/src/agents/scientist.md +0 -150
- package/src/agents/security-reviewer.md +0 -132
- package/src/agents/simplifier.md +0 -109
- package/src/agents/test-engineer.md +0 -124
- package/src/agents/tester.md +0 -102
- package/src/agents/tracer.md +0 -160
- package/src/agents/verifier.md +0 -100
- package/src/agents/writer.md +0 -96
package/bin/omp.mjs
CHANGED
|
@@ -1,23 +1,690 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __esm = (fn, res) => function __init() {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
};
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// src/hud/renderer.mts
|
|
13
|
+
function formatAge(startedAt) {
|
|
14
|
+
const elapsed = Date.now() - startedAt;
|
|
15
|
+
const mins = Math.floor(elapsed / 6e4);
|
|
16
|
+
if (mins < 60) return `${mins}m`;
|
|
17
|
+
const hours = Math.floor(mins / 60);
|
|
18
|
+
const remainingMins = mins % 60;
|
|
19
|
+
return `${hours}h${remainingMins}m`;
|
|
20
|
+
}
|
|
21
|
+
function formatTokens(tokens) {
|
|
22
|
+
if (tokens >= 1e6) return `${(tokens / 1e6).toFixed(1)}M`;
|
|
23
|
+
if (tokens >= 1e3) return `${(tokens / 1e3).toFixed(1)}k`;
|
|
24
|
+
return `${tokens}`;
|
|
25
|
+
}
|
|
26
|
+
function ctxColor(pct) {
|
|
27
|
+
if (pct < 60) return "\x1B[32m";
|
|
28
|
+
if (pct < 85) return "\x1B[33m";
|
|
29
|
+
return "\x1B[31m";
|
|
30
|
+
}
|
|
31
|
+
function reset() {
|
|
32
|
+
return "\x1B[0m";
|
|
33
|
+
}
|
|
34
|
+
function renderAnsi(state) {
|
|
35
|
+
const age = formatAge(state.startedAt);
|
|
36
|
+
const tokens = formatTokens(state.tokensUsed);
|
|
37
|
+
const ctx = state.contextPct;
|
|
38
|
+
const mode = state.activeMode || "-";
|
|
39
|
+
const model = state.activeModel || "sonnet";
|
|
40
|
+
const icon = STATUS_ICONS[state.status] || "\u25CF";
|
|
41
|
+
const ctxClr = ctxColor(ctx);
|
|
42
|
+
const ctxStr = `${ctxClr}ctx:${ctx}%${reset()}`;
|
|
43
|
+
const tokenStr = `tok:~${tokens}/${state.tokensTotal}`;
|
|
44
|
+
const modeStr = mode === "-" ? "-" : `\x1B[36m${mode}${reset()}`;
|
|
45
|
+
const reqWarning = state.warningActive ? " !!" : "";
|
|
46
|
+
const reqStr = `req:${state.premiumRequests ?? 0}/${state.premiumRequestsTotal ?? 1500}${reqWarning}`;
|
|
47
|
+
return `[OMP v${state.version}] ${modeStr} | ${model} | ${ctxStr} | ${tokenStr} | ${reqStr} | ${age} | tools:${state.toolsUsed?.size || 0}/${state.toolsTotal ?? 13} | skills:${state.skillsUsed?.size || 0}/${state.skillsTotal ?? 25} | agents:${state.cumulativeAgentsUsed}/${state.agentsTotal ?? 23} | ${icon} ${state.status}`;
|
|
48
|
+
}
|
|
49
|
+
function renderPlain(state) {
|
|
50
|
+
const age = formatAge(state.startedAt);
|
|
51
|
+
const tokens = formatTokens(state.tokensUsed);
|
|
52
|
+
const ctx = state.contextPct;
|
|
53
|
+
const mode = state.activeMode || "-";
|
|
54
|
+
const model = state.activeModel || "sonnet";
|
|
55
|
+
const reqWarningPlain = state.warningActive ? " !!" : "";
|
|
56
|
+
const reqStrPlain = `req:${state.premiumRequests ?? 0}/${state.premiumRequestsTotal ?? 1500}${reqWarningPlain}`;
|
|
57
|
+
return `[OMP v${state.version}] ${mode} | ${model} | ctx:${ctx}% | tok:~${tokens}/${state.tokensTotal} | ${reqStrPlain} | ${age} | tools:${state.toolsUsed?.size || 0}/${state.toolsTotal ?? 13} | skills:${state.skillsUsed?.size || 0}/${state.skillsTotal ?? 25} | agents:${state.cumulativeAgentsUsed}/${state.agentsTotal ?? 23} | ${state.status}`;
|
|
58
|
+
}
|
|
59
|
+
var STATUS_ICONS;
|
|
60
|
+
var init_renderer = __esm({
|
|
61
|
+
"src/hud/renderer.mts"() {
|
|
62
|
+
"use strict";
|
|
63
|
+
STATUS_ICONS = {
|
|
64
|
+
idle: "\u25CB",
|
|
65
|
+
running: "\u25CF",
|
|
66
|
+
waiting: "\u25F7",
|
|
67
|
+
complete: "\u2713",
|
|
68
|
+
error: "\u2717",
|
|
69
|
+
eco: "\u26A1"
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// src/hud/statusline.mts
|
|
75
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
|
|
76
|
+
import { homedir as homedir2 } from "os";
|
|
77
|
+
import { dirname as dirname2, join as join2 } from "path";
|
|
78
|
+
import { fileURLToPath } from "url";
|
|
79
|
+
function getStatuslinePaths(home = process.env["HOME"] || homedir2()) {
|
|
80
|
+
const ompDir = join2(home, ".omp");
|
|
81
|
+
const hudDir = join2(ompDir, "hud");
|
|
82
|
+
return {
|
|
83
|
+
legacyLinePath: join2(ompDir, "hud.line"),
|
|
84
|
+
hudDir,
|
|
85
|
+
statusJsonPath: join2(hudDir, "status.json"),
|
|
86
|
+
displayPath: join2(hudDir, "display.txt"),
|
|
87
|
+
tmuxSegmentPath: join2(hudDir, "tmux-segment.sh")
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function ensureParent(filePath) {
|
|
91
|
+
mkdirSync(dirname2(filePath), { recursive: true });
|
|
92
|
+
}
|
|
93
|
+
function writeAtomic(filePath, content, mode) {
|
|
94
|
+
ensureParent(filePath);
|
|
95
|
+
const tempPath = `${filePath}.tmp`;
|
|
96
|
+
writeFileSync(tempPath, content, mode === void 0 ? "utf-8" : { encoding: "utf-8", mode });
|
|
97
|
+
renameSync(tempPath, filePath);
|
|
98
|
+
}
|
|
99
|
+
function normalizeStringArray(value) {
|
|
100
|
+
if (!Array.isArray(value)) return [];
|
|
101
|
+
return value.filter((item) => typeof item === "string");
|
|
102
|
+
}
|
|
103
|
+
function serializeHudState(state) {
|
|
104
|
+
return {
|
|
105
|
+
...state,
|
|
106
|
+
toolsUsed: Array.from(state.toolsUsed),
|
|
107
|
+
skillsUsed: Array.from(state.skillsUsed)
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function deserializeHudState(raw) {
|
|
111
|
+
if (!raw || typeof raw !== "object") return null;
|
|
112
|
+
const value = raw;
|
|
113
|
+
const toolsUsed = new Set(normalizeStringArray(value.toolsUsed));
|
|
114
|
+
const skillsUsed = new Set(normalizeStringArray(value.skillsUsed));
|
|
115
|
+
const agentsActive = normalizeStringArray(value.agentsActive);
|
|
116
|
+
const status = typeof value.status === "string" ? value.status : "idle";
|
|
117
|
+
return {
|
|
118
|
+
sessionId: typeof value.sessionId === "string" ? value.sessionId : "default",
|
|
119
|
+
activeMode: typeof value.activeMode === "string" ? value.activeMode : null,
|
|
120
|
+
activeModel: typeof value.activeModel === "string" ? value.activeModel : "sonnet",
|
|
121
|
+
contextPct: typeof value.contextPct === "number" ? value.contextPct : 0,
|
|
122
|
+
tokensUsed: typeof value.tokensUsed === "number" ? value.tokensUsed : 0,
|
|
123
|
+
tokensTotal: typeof value.tokensTotal === "number" ? value.tokensTotal : DEFAULT_TOKEN_BUDGET,
|
|
124
|
+
agentsActive,
|
|
125
|
+
lastAgent: typeof value.lastAgent === "string" ? value.lastAgent : agentsActive.at(-1) ?? "-",
|
|
126
|
+
lastOutput: typeof value.lastOutput === "string" ? value.lastOutput : "",
|
|
127
|
+
taskProgress: typeof value.taskProgress === "number" ? value.taskProgress : 0,
|
|
128
|
+
startedAt: typeof value.startedAt === "number" ? value.startedAt : Date.now(),
|
|
129
|
+
updatedAt: typeof value.updatedAt === "number" ? value.updatedAt : Date.now(),
|
|
130
|
+
version: typeof value.version === "string" ? value.version : DEFAULT_VERSION,
|
|
131
|
+
status,
|
|
132
|
+
sessionDurationMs: typeof value.sessionDurationMs === "number" ? value.sessionDurationMs : 0,
|
|
133
|
+
cumulativeAgentsUsed: typeof value.cumulativeAgentsUsed === "number" ? value.cumulativeAgentsUsed : agentsActive.length,
|
|
134
|
+
toolsUsed,
|
|
135
|
+
skillsUsed,
|
|
136
|
+
toolsTotal: typeof value.toolsTotal === "number" ? value.toolsTotal : 13,
|
|
137
|
+
skillsTotal: typeof value.skillsTotal === "number" ? value.skillsTotal : 25,
|
|
138
|
+
agentsTotal: typeof value.agentsTotal === "number" ? value.agentsTotal : 23,
|
|
139
|
+
premiumRequests: typeof value.premiumRequests === "number" ? value.premiumRequests : 0,
|
|
140
|
+
premiumRequestsTotal: typeof value.premiumRequestsTotal === "number" ? value.premiumRequestsTotal : DEFAULT_PREMIUM_REQUESTS_TOTAL,
|
|
141
|
+
warningActive: typeof value.warningActive === "boolean" ? value.warningActive : false
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function buildHudState(snapshot, now = Date.now()) {
|
|
145
|
+
const startedAt = snapshot.started_at ?? now;
|
|
146
|
+
const updatedAt = snapshot.updated_at ?? now;
|
|
147
|
+
const toolsUsed = new Set(normalizeStringArray(snapshot.tools_used));
|
|
148
|
+
const skillsUsed = new Set(normalizeStringArray(snapshot.skills_used));
|
|
149
|
+
const agentsActive = normalizeStringArray(snapshot.agents_used);
|
|
150
|
+
return {
|
|
151
|
+
sessionId: snapshot.session_id ?? "default",
|
|
152
|
+
activeMode: snapshot.active_mode ?? null,
|
|
153
|
+
activeModel: snapshot.model ?? "sonnet",
|
|
154
|
+
contextPct: snapshot.context_pct ?? 0,
|
|
155
|
+
tokensUsed: snapshot.tokens_estimated ?? 0,
|
|
156
|
+
tokensTotal: snapshot.token_budget ?? DEFAULT_TOKEN_BUDGET,
|
|
157
|
+
agentsActive,
|
|
158
|
+
lastAgent: agentsActive.at(-1) ?? "-",
|
|
159
|
+
lastOutput: snapshot.last_output ?? "",
|
|
160
|
+
taskProgress: snapshot.task_progress ?? 0,
|
|
161
|
+
startedAt,
|
|
162
|
+
updatedAt,
|
|
163
|
+
version: snapshot.version ?? DEFAULT_VERSION,
|
|
164
|
+
status: snapshot.status ?? "idle",
|
|
165
|
+
sessionDurationMs: Math.max(0, updatedAt - startedAt),
|
|
166
|
+
cumulativeAgentsUsed: agentsActive.length,
|
|
167
|
+
toolsUsed,
|
|
168
|
+
skillsUsed,
|
|
169
|
+
toolsTotal: 13,
|
|
170
|
+
skillsTotal: 25,
|
|
171
|
+
agentsTotal: 23,
|
|
172
|
+
premiumRequests: snapshot.premium_requests ?? 0,
|
|
173
|
+
premiumRequestsTotal: snapshot.premium_requests_total ?? DEFAULT_PREMIUM_REQUESTS_TOTAL,
|
|
174
|
+
warningActive: snapshot.warning_active ?? false
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function writeHudArtifacts(snapshot, paths = getStatuslinePaths()) {
|
|
178
|
+
const state = buildHudState(snapshot);
|
|
179
|
+
const line = renderPlain(state);
|
|
180
|
+
const serializedState = `${JSON.stringify(serializeHudState(state), null, 2)}
|
|
181
|
+
`;
|
|
182
|
+
writeAtomic(paths.statusJsonPath, serializedState);
|
|
183
|
+
writeAtomic(paths.displayPath, `${line}
|
|
184
|
+
`);
|
|
185
|
+
writeAtomic(paths.tmuxSegmentPath, `${line}
|
|
186
|
+
`, 493);
|
|
187
|
+
writeAtomic(paths.legacyLinePath, `${line}
|
|
188
|
+
`);
|
|
189
|
+
return { line, state, paths };
|
|
190
|
+
}
|
|
191
|
+
function readStatusline(paths = getStatuslinePaths()) {
|
|
192
|
+
try {
|
|
193
|
+
const line = readFileSync(paths.displayPath, "utf-8").trim();
|
|
194
|
+
if (line) return line;
|
|
195
|
+
} catch {
|
|
196
|
+
}
|
|
197
|
+
try {
|
|
198
|
+
const parsed = JSON.parse(readFileSync(paths.statusJsonPath, "utf-8"));
|
|
199
|
+
const state = deserializeHudState(parsed);
|
|
200
|
+
if (state) return renderPlain(state);
|
|
201
|
+
} catch {
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
const line = readFileSync(paths.legacyLinePath, "utf-8").trim();
|
|
205
|
+
if (line) return line;
|
|
206
|
+
} catch {
|
|
207
|
+
}
|
|
208
|
+
return DEFAULT_STATUSLINE;
|
|
209
|
+
}
|
|
210
|
+
var DEFAULT_VERSION, DEFAULT_STATUSLINE, DEFAULT_TOKEN_BUDGET, DEFAULT_PREMIUM_REQUESTS_TOTAL;
|
|
211
|
+
var init_statusline = __esm({
|
|
212
|
+
"src/hud/statusline.mts"() {
|
|
213
|
+
"use strict";
|
|
214
|
+
init_renderer();
|
|
215
|
+
DEFAULT_VERSION = "0.0.0";
|
|
216
|
+
DEFAULT_STATUSLINE = "OMP | hud: no active session";
|
|
217
|
+
DEFAULT_TOKEN_BUDGET = 2e5;
|
|
218
|
+
DEFAULT_PREMIUM_REQUESTS_TOTAL = 1500;
|
|
219
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
220
|
+
console.log(readStatusline());
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// src/hud/watch.mts
|
|
226
|
+
var watch_exports = {};
|
|
227
|
+
__export(watch_exports, {
|
|
228
|
+
runHudWatch: () => runHudWatch
|
|
229
|
+
});
|
|
230
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
231
|
+
import { homedir as homedir3 } from "os";
|
|
232
|
+
import { join as join3 } from "path";
|
|
233
|
+
function readSnapshot() {
|
|
234
|
+
try {
|
|
235
|
+
const raw = readFileSync2(STATE_PATH, "utf-8");
|
|
236
|
+
const parsed = JSON.parse(raw);
|
|
237
|
+
return parsed;
|
|
238
|
+
} catch {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
function tick(paths = getStatuslinePaths()) {
|
|
243
|
+
const snapshot = readSnapshot();
|
|
244
|
+
if (!snapshot) return;
|
|
245
|
+
const now = Date.now();
|
|
246
|
+
const state = buildHudState(snapshot, now);
|
|
247
|
+
writeHudArtifacts(snapshot, paths);
|
|
248
|
+
process.stdout.write("\x1B[2J\x1B[H" + renderAnsi(state) + "\x1B[K\n\x1B[J");
|
|
249
|
+
}
|
|
250
|
+
function runHudWatch() {
|
|
251
|
+
const intervalMs = Math.max(
|
|
252
|
+
500,
|
|
253
|
+
parseInt(process.env["OMP_HUD_INTERVAL"] ?? "", 10) || DEFAULT_INTERVAL_MS
|
|
254
|
+
);
|
|
255
|
+
const paths = getStatuslinePaths();
|
|
256
|
+
process.stdout.write("\x1B[?25l");
|
|
257
|
+
try {
|
|
258
|
+
tick(paths);
|
|
259
|
+
} catch {
|
|
260
|
+
}
|
|
261
|
+
const timer = setInterval(() => {
|
|
262
|
+
try {
|
|
263
|
+
tick(paths);
|
|
264
|
+
} catch {
|
|
265
|
+
}
|
|
266
|
+
}, intervalMs);
|
|
267
|
+
const stop = () => {
|
|
268
|
+
clearInterval(timer);
|
|
269
|
+
process.stdout.write("\x1B[?25h\x1B[2J\x1B[H");
|
|
270
|
+
process.exit(0);
|
|
271
|
+
};
|
|
272
|
+
process.on("SIGINT", stop);
|
|
273
|
+
process.on("SIGTERM", stop);
|
|
274
|
+
}
|
|
275
|
+
var DEFAULT_INTERVAL_MS, STATE_PATH;
|
|
276
|
+
var init_watch = __esm({
|
|
277
|
+
"src/hud/watch.mts"() {
|
|
278
|
+
"use strict";
|
|
279
|
+
init_statusline();
|
|
280
|
+
init_renderer();
|
|
281
|
+
DEFAULT_INTERVAL_MS = 2e3;
|
|
282
|
+
STATE_PATH = join3(homedir3(), ".omp", "state", "session.json");
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// src/hooks/keyword-detector.mts
|
|
287
|
+
var keyword_detector_exports = {};
|
|
288
|
+
__export(keyword_detector_exports, {
|
|
289
|
+
processHook: () => processHook
|
|
290
|
+
});
|
|
291
|
+
function detectKeyword(prompt) {
|
|
292
|
+
const trimmed = prompt.trimStart();
|
|
293
|
+
for (const [keyword, skillId] of KEYWORD_ENTRIES) {
|
|
294
|
+
if (trimmed.startsWith(keyword)) {
|
|
295
|
+
return {
|
|
296
|
+
keyword,
|
|
297
|
+
skillId,
|
|
298
|
+
position: 0
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
const slashPattern = /^\/((?:omp:)?[a-zA-Z][a-zA-Z0-9-]*)\b/;
|
|
303
|
+
const slashMatch = trimmed.match(slashPattern);
|
|
304
|
+
if (slashMatch) {
|
|
305
|
+
const cmd = slashMatch[1].toLowerCase();
|
|
306
|
+
const skillId = KEYWORD_MAP[`/${cmd}`] ?? KEYWORD_MAP[`${cmd}:`];
|
|
307
|
+
if (skillId) {
|
|
308
|
+
return {
|
|
309
|
+
keyword: slashMatch[0],
|
|
310
|
+
skillId,
|
|
311
|
+
position: 0
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
const longNamespacePattern = /^\/?oh-my-githubcopilot:([a-zA-Z][a-zA-Z0-9-]*)\b/i;
|
|
316
|
+
const longNamespaceMatch = trimmed.match(longNamespacePattern);
|
|
317
|
+
if (longNamespaceMatch) {
|
|
318
|
+
const cmd = longNamespaceMatch[1].toLowerCase();
|
|
319
|
+
const skillId = KEYWORD_MAP[`/omp:${cmd}`] ?? KEYWORD_MAP[`/${cmd}`] ?? KEYWORD_MAP[`${cmd}:`];
|
|
320
|
+
if (skillId) {
|
|
321
|
+
return {
|
|
322
|
+
keyword: longNamespaceMatch[0],
|
|
323
|
+
skillId,
|
|
324
|
+
position: 0
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
function getCanonicalCommand(skillId) {
|
|
331
|
+
return CANONICAL_COMMAND_MAP[skillId] ?? `/omp:${skillId}`;
|
|
332
|
+
}
|
|
333
|
+
function processHook(input) {
|
|
334
|
+
const start = Date.now();
|
|
335
|
+
const log = [];
|
|
336
|
+
try {
|
|
337
|
+
if (input.hook_type !== "UserPromptSubmitted") {
|
|
338
|
+
return {
|
|
339
|
+
status: "skip",
|
|
340
|
+
latencyMs: Date.now() - start,
|
|
341
|
+
mutations: [],
|
|
342
|
+
log: ["Not a UserPromptSubmitted hook"]
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
const match = detectKeyword(input.prompt);
|
|
346
|
+
if (!match) {
|
|
347
|
+
return {
|
|
348
|
+
status: "ok",
|
|
349
|
+
latencyMs: Date.now() - start,
|
|
350
|
+
mutations: [],
|
|
351
|
+
log: []
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
const taskPart = input.prompt.slice(match.position + match.keyword.length).trim();
|
|
355
|
+
const rewritten = `${getCanonicalCommand(match.skillId)}${taskPart ? ` ${taskPart}` : ""}`;
|
|
356
|
+
log.push(`Keyword detected: "${match.keyword}" \u2192 skill: ${match.skillId}`);
|
|
357
|
+
log.push(`Rewritten: "${rewritten}"`);
|
|
358
|
+
return {
|
|
359
|
+
status: "ok",
|
|
360
|
+
latencyMs: Date.now() - start,
|
|
361
|
+
modifiedPrompt: rewritten,
|
|
362
|
+
mutations: [
|
|
363
|
+
{ type: "set_mode", mode: match.skillId },
|
|
364
|
+
{ type: "log", level: "info", message: `Skill activated: ${match.skillId}` }
|
|
365
|
+
],
|
|
366
|
+
log
|
|
367
|
+
};
|
|
368
|
+
} catch (err) {
|
|
369
|
+
return {
|
|
370
|
+
status: "error",
|
|
371
|
+
latencyMs: Date.now() - start,
|
|
372
|
+
mutations: [],
|
|
373
|
+
log: [`Error: ${err}`]
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
async function readStdin() {
|
|
378
|
+
const chunks = [];
|
|
379
|
+
for await (const chunk of process.stdin) {
|
|
380
|
+
chunks.push(chunk);
|
|
381
|
+
}
|
|
382
|
+
return chunks.join("");
|
|
383
|
+
}
|
|
384
|
+
var KEYWORD_MAP, KEYWORD_ENTRIES, CANONICAL_COMMAND_MAP;
|
|
385
|
+
var init_keyword_detector = __esm({
|
|
386
|
+
async "src/hooks/keyword-detector.mts"() {
|
|
387
|
+
"use strict";
|
|
388
|
+
KEYWORD_MAP = {
|
|
389
|
+
"autopilot:": "autopilot",
|
|
390
|
+
"/autopilot": "autopilot",
|
|
391
|
+
"/omp:autopilot": "autopilot",
|
|
392
|
+
"ralph:": "ralph",
|
|
393
|
+
"/ralph": "ralph",
|
|
394
|
+
"/omp:ralph": "ralph",
|
|
395
|
+
"ulw:": "ultrawork",
|
|
396
|
+
"ultrawork:": "ultrawork",
|
|
397
|
+
"/ulw": "ultrawork",
|
|
398
|
+
"/ultrawork": "ultrawork",
|
|
399
|
+
"/omp:ulw": "ultrawork",
|
|
400
|
+
"/omp:ultrawork": "ultrawork",
|
|
401
|
+
"team:": "team",
|
|
402
|
+
"/team": "team",
|
|
403
|
+
"/omp:team": "team",
|
|
404
|
+
"eco:": "ecomode",
|
|
405
|
+
"ecomode:": "ecomode",
|
|
406
|
+
"/eco": "ecomode",
|
|
407
|
+
"/ecomode": "ecomode",
|
|
408
|
+
"/omp:eco": "ecomode",
|
|
409
|
+
"/omp:ecomode": "ecomode",
|
|
410
|
+
"swarm:": "swarm",
|
|
411
|
+
"/swarm": "swarm",
|
|
412
|
+
"/omp:swarm": "swarm",
|
|
413
|
+
"pipeline:": "pipeline",
|
|
414
|
+
"/pipeline": "pipeline",
|
|
415
|
+
"/omp:pipeline": "pipeline",
|
|
416
|
+
"deep interview:": "deep-interview",
|
|
417
|
+
"/deep-interview": "deep-interview",
|
|
418
|
+
"/omp:deep-interview": "deep-interview",
|
|
419
|
+
"plan:": "omp-plan",
|
|
420
|
+
"/plan": "omp-plan",
|
|
421
|
+
"/omp-plan": "omp-plan",
|
|
422
|
+
"/omp:plan": "omp-plan",
|
|
423
|
+
"setup:": "omp-setup",
|
|
424
|
+
"/setup": "omp-setup",
|
|
425
|
+
"/omp-setup": "omp-setup",
|
|
426
|
+
"/omp:setup": "omp-setup",
|
|
427
|
+
"mcp:": "mcp-setup",
|
|
428
|
+
"mcp-setup:": "mcp-setup",
|
|
429
|
+
"/mcp": "mcp-setup",
|
|
430
|
+
"/mcp-setup": "mcp-setup",
|
|
431
|
+
"/omp:mcp-setup": "mcp-setup",
|
|
432
|
+
"/hud": "hud",
|
|
433
|
+
"hud:": "hud",
|
|
434
|
+
"/omp:hud": "hud",
|
|
435
|
+
"/wiki": "wiki",
|
|
436
|
+
"wiki:": "wiki",
|
|
437
|
+
"/omp:wiki": "wiki",
|
|
438
|
+
"/learner": "learner",
|
|
439
|
+
"learner:": "learner",
|
|
440
|
+
"/omp:learner": "learner",
|
|
441
|
+
"/note": "note",
|
|
442
|
+
"note:": "note",
|
|
443
|
+
"/omp:note": "note",
|
|
444
|
+
"/trace": "trace",
|
|
445
|
+
"trace:": "trace",
|
|
446
|
+
"/omp:trace": "trace",
|
|
447
|
+
"/release": "release",
|
|
448
|
+
"release:": "release",
|
|
449
|
+
"/omp:release": "release",
|
|
450
|
+
"/configure-notifications": "configure-notifications",
|
|
451
|
+
"configure-notifications:": "configure-notifications",
|
|
452
|
+
"/omp:configure-notifications": "configure-notifications",
|
|
453
|
+
"/psm": "psm",
|
|
454
|
+
"psm:": "psm",
|
|
455
|
+
"/omp:psm": "psm",
|
|
456
|
+
"/swe-bench": "swe-bench",
|
|
457
|
+
"swe-bench:": "swe-bench",
|
|
458
|
+
"/omp:swe-bench": "swe-bench",
|
|
459
|
+
"graphify:": "graphify",
|
|
460
|
+
"graph build": "graphify",
|
|
461
|
+
"build graph": "graphify",
|
|
462
|
+
"graphwiki:": "graphwiki",
|
|
463
|
+
"graph:": "graph-provider",
|
|
464
|
+
"spending:": "spending",
|
|
465
|
+
"/graphify": "graphify",
|
|
466
|
+
"/omp:graphify": "graphify",
|
|
467
|
+
"/graphwiki": "graphwiki",
|
|
468
|
+
"/omp:graphwiki": "graphwiki",
|
|
469
|
+
"/graph-provider": "graph-provider",
|
|
470
|
+
"/omp:graph-provider": "graph-provider",
|
|
471
|
+
"/spending": "spending",
|
|
472
|
+
"/omp:spending": "spending",
|
|
473
|
+
"--consensus": "omp-plan",
|
|
474
|
+
"/omp:omp-doctor": "omp-doctor",
|
|
475
|
+
"/omp:ralplan": "ralplan",
|
|
476
|
+
"/omp:research": "research",
|
|
477
|
+
"doctor:": "doctor",
|
|
478
|
+
"/doctor": "doctor",
|
|
479
|
+
"/omp:doctor": "doctor",
|
|
480
|
+
"interview:": "interview",
|
|
481
|
+
"/interview": "interview",
|
|
482
|
+
"/omp:interview": "interview",
|
|
483
|
+
"notifications:": "notifications",
|
|
484
|
+
"/notifications": "notifications",
|
|
485
|
+
"/omp:notifications": "notifications",
|
|
486
|
+
"session:": "session",
|
|
487
|
+
"/session": "session",
|
|
488
|
+
"/omp:session": "session"
|
|
489
|
+
};
|
|
490
|
+
KEYWORD_ENTRIES = Object.entries(KEYWORD_MAP).sort(([a], [b]) => b.length - a.length);
|
|
491
|
+
CANONICAL_COMMAND_MAP = {
|
|
492
|
+
"omp-plan": "/omp:plan",
|
|
493
|
+
"omp-setup": "/setup",
|
|
494
|
+
"mcp-setup": "/mcp"
|
|
495
|
+
};
|
|
496
|
+
if (process.argv[1]?.endsWith("keyword-detector.mjs") || process.argv[1]?.endsWith("keyword-detector.mts")) {
|
|
497
|
+
const input = JSON.parse(await readStdin());
|
|
498
|
+
const output = processHook(input);
|
|
499
|
+
console.log(JSON.stringify(output));
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
});
|
|
2
503
|
|
|
3
504
|
// src/index.mts
|
|
4
505
|
import { parseArgs } from "util";
|
|
5
506
|
import { createRequire } from "module";
|
|
507
|
+
|
|
508
|
+
// src/cli/update.mts
|
|
509
|
+
import { spawnSync } from "child_process";
|
|
510
|
+
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
511
|
+
import { homedir } from "os";
|
|
512
|
+
import { dirname, join } from "path";
|
|
513
|
+
import { createInterface } from "node:readline/promises";
|
|
514
|
+
var CHECK_INTERVAL_MS = 12 * 60 * 60 * 1e3;
|
|
515
|
+
var PROMPTABLE_SUBCOMMANDS = /* @__PURE__ */ new Set(["hud", "psm", "bench"]);
|
|
516
|
+
var DISABLED_AUTO_UPDATE_VALUES = /* @__PURE__ */ new Set(["0", "false", "no", "off"]);
|
|
517
|
+
var ENABLED_DISABLE_FLAG_VALUES = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
|
|
518
|
+
function parseSemver(version) {
|
|
519
|
+
const match = version.trim().match(/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/);
|
|
520
|
+
if (!match) return null;
|
|
521
|
+
return {
|
|
522
|
+
major: Number(match[1]),
|
|
523
|
+
minor: Number(match[2]),
|
|
524
|
+
patch: Number(match[3]),
|
|
525
|
+
prerelease: match[4] ?? null
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
function isNewerVersion(current, latest) {
|
|
529
|
+
const currentVersion = parseSemver(current);
|
|
530
|
+
const latestVersion = parseSemver(latest);
|
|
531
|
+
if (!currentVersion || !latestVersion) return false;
|
|
532
|
+
if (latestVersion.major !== currentVersion.major) return latestVersion.major > currentVersion.major;
|
|
533
|
+
if (latestVersion.minor !== currentVersion.minor) return latestVersion.minor > currentVersion.minor;
|
|
534
|
+
if (latestVersion.patch !== currentVersion.patch) return latestVersion.patch > currentVersion.patch;
|
|
535
|
+
if (currentVersion.prerelease && !latestVersion.prerelease) return true;
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
538
|
+
function shouldCheckForUpdates(nowMs, state, intervalMs = CHECK_INTERVAL_MS) {
|
|
539
|
+
if (!state?.last_checked_at) return true;
|
|
540
|
+
const lastCheckedAt = Date.parse(state.last_checked_at);
|
|
541
|
+
if (!Number.isFinite(lastCheckedAt)) return true;
|
|
542
|
+
return nowMs - lastCheckedAt >= intervalMs;
|
|
543
|
+
}
|
|
544
|
+
function isAutoUpdateDisabled(env = process.env) {
|
|
545
|
+
const autoUpdate = env["OMP_AUTO_UPDATE"]?.trim().toLowerCase();
|
|
546
|
+
if (autoUpdate && DISABLED_AUTO_UPDATE_VALUES.has(autoUpdate)) return true;
|
|
547
|
+
const disableCheck = env["OMP_DISABLE_UPDATE_CHECK"]?.trim().toLowerCase();
|
|
548
|
+
if (disableCheck && ENABLED_DISABLE_FLAG_VALUES.has(disableCheck)) return true;
|
|
549
|
+
return false;
|
|
550
|
+
}
|
|
551
|
+
function shouldSkipUpdatePrompt(subcommand2, flags2 = {}) {
|
|
552
|
+
if (flags2.help || flags2.version) return true;
|
|
553
|
+
return !PROMPTABLE_SUBCOMMANDS.has(subcommand2);
|
|
554
|
+
}
|
|
555
|
+
function updateStatePath(homeDir) {
|
|
556
|
+
return join(homeDir, ".omp", "state", "update-check.json");
|
|
557
|
+
}
|
|
558
|
+
async function readCachedUpdateState(statePath) {
|
|
559
|
+
try {
|
|
560
|
+
const raw = await readFile(statePath, "utf-8");
|
|
561
|
+
return JSON.parse(raw);
|
|
562
|
+
} catch {
|
|
563
|
+
return null;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
async function writeCachedUpdateState(statePath, state) {
|
|
567
|
+
await mkdir(dirname(statePath), { recursive: true });
|
|
568
|
+
await writeFile(statePath, JSON.stringify(state, null, 2), "utf-8");
|
|
569
|
+
}
|
|
570
|
+
async function fetchLatestVersionFromNpm(packageName, timeoutMs = 3500) {
|
|
571
|
+
const controller = new AbortController();
|
|
572
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
573
|
+
try {
|
|
574
|
+
const url = `https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`;
|
|
575
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
576
|
+
if (!response.ok) return null;
|
|
577
|
+
const payload = await response.json();
|
|
578
|
+
return typeof payload.version === "string" ? payload.version : null;
|
|
579
|
+
} catch {
|
|
580
|
+
return null;
|
|
581
|
+
} finally {
|
|
582
|
+
clearTimeout(timeout);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
function runNpmGlobalUpdate(packageName, cwd) {
|
|
586
|
+
const result = spawnSync("npm", ["install", "-g", `${packageName}@latest`], {
|
|
587
|
+
encoding: "utf-8",
|
|
588
|
+
stdio: ["ignore", "ignore", "pipe"],
|
|
589
|
+
timeout: 12e4,
|
|
590
|
+
windowsHide: true,
|
|
591
|
+
cwd
|
|
592
|
+
});
|
|
593
|
+
if (result.error) return { ok: false, stderr: result.error.message };
|
|
594
|
+
if (result.status !== 0) {
|
|
595
|
+
return { ok: false, stderr: (result.stderr || "").trim() || `npm exited ${result.status}` };
|
|
596
|
+
}
|
|
597
|
+
return { ok: true, stderr: "" };
|
|
598
|
+
}
|
|
599
|
+
async function askYesNo(question) {
|
|
600
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
601
|
+
const readline = createInterface({ input: process.stdin, output: process.stdout });
|
|
602
|
+
try {
|
|
603
|
+
const answer = (await readline.question(question)).trim().toLowerCase();
|
|
604
|
+
return answer === "" || answer === "y" || answer === "yes";
|
|
605
|
+
} finally {
|
|
606
|
+
readline.close();
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
var defaultDependencies = {
|
|
610
|
+
nowMs: () => Date.now(),
|
|
611
|
+
readUpdateState: readCachedUpdateState,
|
|
612
|
+
writeUpdateState: writeCachedUpdateState,
|
|
613
|
+
fetchLatestVersion: fetchLatestVersionFromNpm,
|
|
614
|
+
askYesNo,
|
|
615
|
+
runGlobalUpdate: runNpmGlobalUpdate
|
|
616
|
+
};
|
|
617
|
+
async function maybeCheckAndPromptUpdate(context, dependencies = {}) {
|
|
618
|
+
const updateDependencies = {
|
|
619
|
+
...defaultDependencies,
|
|
620
|
+
...dependencies
|
|
621
|
+
};
|
|
622
|
+
try {
|
|
623
|
+
if (isAutoUpdateDisabled()) return;
|
|
624
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) return;
|
|
625
|
+
if (shouldSkipUpdatePrompt(context.subcommand, context.flags)) return;
|
|
626
|
+
const statePath = updateStatePath(process.env["HOME"] || homedir());
|
|
627
|
+
const now = updateDependencies.nowMs();
|
|
628
|
+
const state = await updateDependencies.readUpdateState(statePath);
|
|
629
|
+
if (!shouldCheckForUpdates(now, state)) return;
|
|
630
|
+
const latestVersion = await updateDependencies.fetchLatestVersion(context.packageName);
|
|
631
|
+
await updateDependencies.writeUpdateState(statePath, {
|
|
632
|
+
last_checked_at: new Date(now).toISOString(),
|
|
633
|
+
last_seen_latest: latestVersion || state?.last_seen_latest
|
|
634
|
+
});
|
|
635
|
+
if (!latestVersion || !isNewerVersion(context.currentVersion, latestVersion)) return;
|
|
636
|
+
const approved = await updateDependencies.askYesNo(
|
|
637
|
+
`[omp] Update available: v${context.currentVersion} \u2192 v${latestVersion}. Update now? [Y/n] `
|
|
638
|
+
);
|
|
639
|
+
if (!approved) return;
|
|
640
|
+
console.log(`[omp] Running: npm install -g ${context.packageName}@latest`);
|
|
641
|
+
const result = updateDependencies.runGlobalUpdate(context.packageName, context.cwd);
|
|
642
|
+
if (result.ok) {
|
|
643
|
+
console.log(`[omp] Updated to v${latestVersion}. Restart this shell to load the new CLI.`);
|
|
644
|
+
} else {
|
|
645
|
+
console.log(`[omp] Update failed. Run manually: npm install -g ${context.packageName}@latest`);
|
|
646
|
+
}
|
|
647
|
+
} catch {
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// src/index.mts
|
|
6
652
|
var _require = createRequire(import.meta.url);
|
|
7
653
|
var { version: PKG_VERSION, name: PKG_NAME } = _require("../package.json");
|
|
8
|
-
var { positionals } = parseArgs({
|
|
654
|
+
var { positionals, values: flags } = parseArgs({
|
|
9
655
|
args: process.argv.slice(2),
|
|
10
656
|
options: {
|
|
11
657
|
help: { type: "boolean", default: false },
|
|
12
|
-
version: { type: "boolean", default: false }
|
|
658
|
+
version: { type: "boolean", default: false },
|
|
659
|
+
watch: { type: "boolean", default: false }
|
|
13
660
|
},
|
|
14
661
|
allowPositionals: true
|
|
15
662
|
});
|
|
16
663
|
var subcommand = positionals[0] || "hud";
|
|
664
|
+
var resolvedSubcommand = flags.version && !positionals[0] ? "version" : subcommand;
|
|
17
665
|
async function main() {
|
|
18
|
-
|
|
666
|
+
if (flags.help) {
|
|
667
|
+
printUsage();
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
await maybeCheckAndPromptUpdate({
|
|
671
|
+
cwd: process.cwd(),
|
|
672
|
+
packageName: PKG_NAME,
|
|
673
|
+
currentVersion: PKG_VERSION,
|
|
674
|
+
subcommand: resolvedSubcommand,
|
|
675
|
+
flags: {
|
|
676
|
+
help: flags.help,
|
|
677
|
+
version: flags.version
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
switch (resolvedSubcommand) {
|
|
19
681
|
case "hud":
|
|
20
|
-
|
|
682
|
+
if (flags.watch) {
|
|
683
|
+
const { runHudWatch: runHudWatch2 } = await Promise.resolve().then(() => (init_watch(), watch_exports));
|
|
684
|
+
runHudWatch2();
|
|
685
|
+
} else {
|
|
686
|
+
await printHud();
|
|
687
|
+
}
|
|
21
688
|
break;
|
|
22
689
|
case "version":
|
|
23
690
|
console.log(`${PKG_NAME} v${PKG_VERSION}`);
|
|
@@ -28,19 +695,26 @@ async function main() {
|
|
|
28
695
|
case "bench":
|
|
29
696
|
await runBench(positionals.slice(1));
|
|
30
697
|
break;
|
|
698
|
+
case "hook":
|
|
699
|
+
await runHook(positionals.slice(1));
|
|
700
|
+
break;
|
|
31
701
|
default:
|
|
32
|
-
console.error(`Unknown subcommand: ${
|
|
33
|
-
|
|
702
|
+
console.error(`Unknown subcommand: ${resolvedSubcommand}`);
|
|
703
|
+
printUsage(true);
|
|
34
704
|
process.exit(1);
|
|
35
705
|
}
|
|
36
706
|
}
|
|
707
|
+
function printUsage(stderr = false) {
|
|
708
|
+
const output = stderr ? console.error : console.log;
|
|
709
|
+
output("Usage: omp [hud|version|psm|bench|hook] [--watch]");
|
|
710
|
+
}
|
|
37
711
|
async function printHud() {
|
|
38
712
|
try {
|
|
39
|
-
const { readFileSync } = await import("fs");
|
|
40
|
-
const { join } = await import("path");
|
|
41
|
-
const { homedir } = await import("os");
|
|
42
|
-
const hudPath =
|
|
43
|
-
const line =
|
|
713
|
+
const { readFileSync: readFileSync3 } = await import("fs");
|
|
714
|
+
const { join: join4 } = await import("path");
|
|
715
|
+
const { homedir: homedir4 } = await import("os");
|
|
716
|
+
const hudPath = join4(homedir4(), ".omp", "hud.line");
|
|
717
|
+
const line = readFileSync3(hudPath, "utf-8").trim();
|
|
44
718
|
console.log(line);
|
|
45
719
|
} catch {
|
|
46
720
|
console.log(`OMP v${PKG_VERSION} | hud: no active session`);
|
|
@@ -48,14 +722,33 @@ async function printHud() {
|
|
|
48
722
|
}
|
|
49
723
|
async function runPsm(_args) {
|
|
50
724
|
console.log("PSM commands:");
|
|
51
|
-
console.log(" /
|
|
52
|
-
console.log(" /
|
|
53
|
-
console.log(" /
|
|
54
|
-
console.log(" /
|
|
725
|
+
console.log(" /omp:psm create <name> Create isolated worktree session");
|
|
726
|
+
console.log(" /omp:psm list List active sessions");
|
|
727
|
+
console.log(" /omp:psm switch <name> Switch to session");
|
|
728
|
+
console.log(" /omp:psm destroy <name> Destroy session");
|
|
729
|
+
}
|
|
730
|
+
async function runHook(args) {
|
|
731
|
+
const hookId = args[0];
|
|
732
|
+
if (hookId !== "keyword-detector") {
|
|
733
|
+
console.error("Usage: omp hook keyword-detector");
|
|
734
|
+
process.exit(1);
|
|
735
|
+
}
|
|
736
|
+
const { processHook: processHook2 } = await init_keyword_detector().then(() => keyword_detector_exports);
|
|
737
|
+
const inputText = await readStdin2();
|
|
738
|
+
const input = JSON.parse(inputText || "{}");
|
|
739
|
+
const output = processHook2(input);
|
|
740
|
+
console.log(JSON.stringify(output));
|
|
741
|
+
}
|
|
742
|
+
async function readStdin2() {
|
|
743
|
+
const chunks = [];
|
|
744
|
+
for await (const chunk of process.stdin) {
|
|
745
|
+
chunks.push(String(chunk));
|
|
746
|
+
}
|
|
747
|
+
return chunks.join("");
|
|
55
748
|
}
|
|
56
749
|
async function runBench(_args) {
|
|
57
750
|
console.log("SWE-bench requires Node.js subprocess with Python evaluation harness.");
|
|
58
|
-
console.log("Usage: /
|
|
751
|
+
console.log("Usage: /omp:swe-bench --suite lite --compare baseline");
|
|
59
752
|
}
|
|
60
753
|
main().catch((err) => {
|
|
61
754
|
console.error(err);
|