oh-my-githubcopilot 1.4.1 → 1.8.0-alpha.021bf87

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.
Files changed (123) hide show
  1. package/.claude-plugin/plugin.json +36 -6
  2. package/.mcp.json +17 -0
  3. package/AGENTS.md +78 -9
  4. package/CHANGELOG.md +216 -1
  5. package/README.de.md +112 -26
  6. package/README.es.md +115 -29
  7. package/README.fr.md +114 -28
  8. package/README.it.md +114 -28
  9. package/README.ja.md +112 -26
  10. package/README.ko.md +112 -26
  11. package/README.md +96 -95
  12. package/README.pt.md +116 -30
  13. package/README.ru.md +116 -30
  14. package/README.tr.md +115 -29
  15. package/README.vi.md +116 -30
  16. package/README.zh.md +112 -26
  17. package/agents/analyst.agent.md +27 -0
  18. package/agents/architect.agent.md +24 -0
  19. package/agents/code-reviewer.agent.md +24 -0
  20. package/agents/critic.agent.md +24 -0
  21. package/agents/debugger.agent.md +24 -0
  22. package/agents/designer.agent.md +24 -0
  23. package/agents/document-specialist.agent.md +24 -0
  24. package/agents/executor.agent.md +27 -0
  25. package/agents/explorer.agent.md +23 -0
  26. package/agents/git-master.agent.md +24 -0
  27. package/agents/orchestrator.agent.md +26 -0
  28. package/agents/planner.agent.md +24 -0
  29. package/agents/qa-tester.agent.md +24 -0
  30. package/agents/researcher.agent.md +18 -0
  31. package/agents/reviewer.agent.md +23 -0
  32. package/agents/scientist.agent.md +20 -0
  33. package/agents/security-reviewer.agent.md +20 -0
  34. package/agents/simplifier.agent.md +20 -0
  35. package/agents/test-engineer.agent.md +20 -0
  36. package/agents/tester.agent.md +20 -0
  37. package/agents/tracer.agent.md +24 -0
  38. package/agents/verifier.agent.md +19 -0
  39. package/agents/writer.agent.md +24 -0
  40. package/bin/omp-statusline.mjs +179 -0
  41. package/bin/omp-statusline.mjs.map +7 -0
  42. package/bin/omp-statusline.sh +21 -0
  43. package/bin/omp.mjs +709 -16
  44. package/bin/omp.mjs.map +4 -4
  45. package/dist/hooks/hud-emitter.mjs +268 -82
  46. package/dist/hooks/hud-emitter.mjs.map +4 -4
  47. package/dist/hooks/keyword-detector.mjs +100 -23
  48. package/dist/hooks/keyword-detector.mjs.map +2 -2
  49. package/dist/hooks/model-router.mjs +1 -1
  50. package/dist/hooks/model-router.mjs.map +1 -1
  51. package/dist/hooks/stop-continuation.mjs +1 -1
  52. package/dist/hooks/stop-continuation.mjs.map +1 -1
  53. package/dist/hooks/token-tracker.mjs +2 -1
  54. package/dist/hooks/token-tracker.mjs.map +2 -2
  55. package/dist/mcp/server.mjs +85 -53
  56. package/dist/mcp/server.mjs.map +4 -4
  57. package/dist/skills/setup.mjs +39 -27
  58. package/dist/skills/setup.mjs.map +4 -4
  59. package/hooks/hooks.json +39 -45
  60. package/package.json +9 -4
  61. package/plugin.json +71 -0
  62. package/skills/ai-slop-cleaner/SKILL.md +137 -0
  63. package/skills/autopilot/SKILL.md +6 -0
  64. package/skills/configure-notifications/SKILL.md +6 -0
  65. package/skills/deep-interview/SKILL.md +6 -0
  66. package/skills/doctor/SKILL.md +188 -0
  67. package/skills/ecomode/SKILL.md +6 -0
  68. package/skills/graph-context/SKILL.md +119 -0
  69. package/skills/graph-provider/SKILL.md +6 -0
  70. package/skills/graphify/SKILL.md +6 -0
  71. package/skills/graphwiki/SKILL.md +6 -0
  72. package/skills/hud/SKILL.md +6 -0
  73. package/skills/improve-codebase-architecture/SKILL.md +214 -0
  74. package/skills/interactive-menu/SKILL.md +102 -0
  75. package/skills/interview/SKILL.md +203 -0
  76. package/skills/learner/SKILL.md +6 -0
  77. package/skills/mcp-setup/SKILL.md +6 -0
  78. package/skills/note/SKILL.md +6 -0
  79. package/skills/notifications/SKILL.md +190 -0
  80. package/skills/omp-doctor/SKILL.md +146 -0
  81. package/skills/omp-plan/SKILL.md +219 -2
  82. package/skills/omp-reference/SKILL.md +174 -0
  83. package/skills/omp-setup/SKILL.md +15 -1
  84. package/skills/pipeline/SKILL.md +6 -0
  85. package/skills/psm/SKILL.md +6 -0
  86. package/skills/ralph/SKILL.md +6 -0
  87. package/skills/ralplan/SKILL.md +148 -0
  88. package/skills/release/SKILL.md +6 -0
  89. package/skills/research/SKILL.md +149 -0
  90. package/skills/session/SKILL.md +220 -0
  91. package/skills/setup/SKILL.md +6 -0
  92. package/skills/skillify/SKILL.md +66 -0
  93. package/skills/spending/SKILL.md +6 -0
  94. package/skills/swarm/SKILL.md +6 -0
  95. package/skills/swe-bench/SKILL.md +6 -0
  96. package/skills/tdd/SKILL.md +246 -0
  97. package/skills/team/SKILL.md +6 -0
  98. package/skills/trace/SKILL.md +6 -0
  99. package/skills/ultrawork/SKILL.md +6 -0
  100. package/skills/wiki/SKILL.md +6 -0
  101. package/src/agents/analyst.md +0 -103
  102. package/src/agents/architect.md +0 -169
  103. package/src/agents/code-reviewer.md +0 -135
  104. package/src/agents/critic.md +0 -196
  105. package/src/agents/debugger.md +0 -132
  106. package/src/agents/designer.md +0 -103
  107. package/src/agents/document-specialist.md +0 -111
  108. package/src/agents/executor.md +0 -120
  109. package/src/agents/explorer.md +0 -98
  110. package/src/agents/git-master.md +0 -92
  111. package/src/agents/orchestrator.md +0 -125
  112. package/src/agents/planner.md +0 -106
  113. package/src/agents/qa-tester.md +0 -129
  114. package/src/agents/researcher.md +0 -102
  115. package/src/agents/reviewer.md +0 -100
  116. package/src/agents/scientist.md +0 -150
  117. package/src/agents/security-reviewer.md +0 -132
  118. package/src/agents/simplifier.md +0 -109
  119. package/src/agents/test-engineer.md +0 -124
  120. package/src/agents/tester.md +0 -102
  121. package/src/agents/tracer.md +0 -160
  122. package/src/agents/verifier.md +0 -100
  123. package/src/agents/writer.md +0 -96
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: researcher
3
+ description: >
4
+ External knowledge researcher for SDK docs, library references, and technology comparisons.
5
+ Use when: looking up external docs, comparing libraries, researching APIs.
6
+ model: claude-sonnet-4-6
7
+ tools: [readFile, search, fetch]
8
+ agents: []
9
+ user-invocable: true
10
+ ---
11
+
12
+ # Researcher
13
+
14
+ ## Role
15
+ Find and synthesize external knowledge: SDK docs, library references, API docs, dependency information, technology comparisons.
16
+
17
+ ## Constraints
18
+ - READ-ONLY. Does not implement — finds and summarizes.
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: reviewer
3
+ description: >
4
+ Code quality reviewer and style enforcer.
5
+ Use when: code review, style enforcement, catching bugs before merge.
6
+ model: claude-opus-4-6
7
+ tools: [readFile, search, codebase, usages, problems]
8
+ agents: [explore]
9
+ user-invocable: true
10
+ ---
11
+
12
+ # Reviewer
13
+
14
+ ## Role
15
+ Thorough code reviews: enforce style, catch bugs, identify quality issues, and gate merges.
16
+
17
+ ## Responsibilities
18
+ - Style enforcement and pattern consistency
19
+ - Bug identification with LSP precision
20
+ - Merge gate verdicts
21
+
22
+ ## NOT Responsible For
23
+ - Implementing fixes (→ executor)
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: scientist
3
+ description: >
4
+ Data analysis and research execution specialist.
5
+ Use when: "analyze this data", "find patterns", "statistical analysis", experimental design.
6
+ model: claude-sonnet-4-6
7
+ tools: [readFile, editFiles, runInTerminal]
8
+ agents: [explore]
9
+ user-invocable: true
10
+ ---
11
+
12
+ # Scientist
13
+
14
+ ## Role
15
+ Data analysis and research execution through experimental design and hypothesis testing.
16
+
17
+ ## Responsibilities
18
+ - Experimental design and hypothesis testing
19
+ - Data analysis and pattern identification
20
+ - Statistical reasoning and evidence synthesis
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: security-reviewer
3
+ description: >
4
+ Security vulnerability detection specialist (OWASP Top 10, secrets, unsafe patterns).
5
+ Use when: "security review", "find vulnerabilities", "check for secrets", auth/crypto changes.
6
+ model: claude-sonnet-4-6
7
+ tools: [readFile, search, codebase]
8
+ agents: [explore]
9
+ user-invocable: true
10
+ ---
11
+
12
+ # Security Reviewer
13
+
14
+ ## Role
15
+ Detect security vulnerabilities: OWASP Top 10, exposed secrets, unsafe code patterns, dependency audits.
16
+
17
+ ## Responsibilities
18
+ - OWASP Top 10 vulnerability scanning
19
+ - Secret and credential exposure detection
20
+ - Unsafe pattern identification and remediation guidance
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: simplifier
3
+ description: >
4
+ Code simplification and refactoring specialist.
5
+ Use when: simplifying code, improving clarity, removing dead code, reducing complexity.
6
+ model: claude-opus-4-6
7
+ tools: [readFile, editFiles, search]
8
+ agents: [explore]
9
+ user-invocable: true
10
+ ---
11
+
12
+ # Simplifier
13
+
14
+ ## Role
15
+ Simplify and refine code for clarity, consistency, and maintainability while preserving exact functionality.
16
+
17
+ ## Responsibilities
18
+ - Dead code removal and duplication elimination
19
+ - Complexity reduction without behavior change
20
+ - Naming, structure, and pattern consistency
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: test-engineer
3
+ description: >
4
+ Test strategy, integration/e2e coverage, and TDD workflows.
5
+ Use when: "add tests", "improve test coverage", "design testing strategy", TDD implementation.
6
+ model: claude-sonnet-4-6
7
+ tools: [readFile, editFiles, runInTerminal, findTestFiles, testFailures]
8
+ agents: [explore, architect]
9
+ user-invocable: true
10
+ ---
11
+
12
+ # Test Engineer
13
+
14
+ ## Role
15
+ Test strategy, integration/e2e coverage analysis, flaky test hardening, and TDD workflows.
16
+
17
+ ## Responsibilities
18
+ - Test strategy design and coverage gap analysis
19
+ - Integration and e2e test implementation
20
+ - Flaky test diagnosis and hardening
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: tester
3
+ description: >
4
+ Test author and coverage analyzer.
5
+ Use when: writing unit tests, executing test suites, analyzing coverage, CI integration.
6
+ model: claude-sonnet-4-6
7
+ tools: [readFile, editFiles, runInTerminal, findTestFiles, testFailures]
8
+ agents: [explore]
9
+ user-invocable: true
10
+ ---
11
+
12
+ # Tester
13
+
14
+ ## Role
15
+ Author tests, execute test suites, analyze coverage, and integrate tests into CI pipelines.
16
+
17
+ ## Responsibilities
18
+ - Unit and integration test authoring
19
+ - Coverage analysis and gap identification
20
+ - CI pipeline integration
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: tracer
3
+ description: >
4
+ Evidence-driven causal tracing with competing hypotheses and uncertainty tracking.
5
+ Use when: explaining unexpected behavior, tracing causation chains, competing hypothesis analysis.
6
+ model: claude-sonnet-4-6
7
+ tools: [readFile, runInTerminal, search]
8
+ agents: [explore, architect]
9
+ user-invocable: true
10
+ ---
11
+
12
+ # Tracer
13
+
14
+ ## Role
15
+ Explain observed outcomes through disciplined, evidence-driven causal tracing.
16
+
17
+ ## Responsibilities
18
+ - Competing hypothesis generation and ranking
19
+ - Evidence collection for and against each hypothesis
20
+ - Next-probe recommendations to collapse uncertainty fastest
21
+
22
+ ## Constraints
23
+ - Never defaults to implementation
24
+ - Never bluffs certainty where evidence is incomplete
@@ -0,0 +1,19 @@
1
+ ---
2
+ name: verifier
3
+ description: >
4
+ Verification and evidence collection specialist.
5
+ Use when: confirming task completion, running tests, collecting diagnostics, validating command outputs.
6
+ model: claude-sonnet-4-6
7
+ tools: [readFile, runInTerminal, search, findTestFiles, testFailures]
8
+ agents: [explore]
9
+ user-invocable: true
10
+ ---
11
+
12
+ # Verifier
13
+
14
+ ## Role
15
+ Run tests, collect diagnostics, validate command outputs, and produce evidence that a task is truly complete.
16
+
17
+ ## Constraints
18
+ - NEVER implements — only confirms or denies
19
+ - Last line of defense before marking any task done
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: writer
3
+ description: >
4
+ Technical documentation author.
5
+ Use when: writing README, API docs, changelogs, code comments, guides.
6
+ model: claude-sonnet-4-6
7
+ tools: [readFile, editFiles, search]
8
+ agents: [explore]
9
+ user-invocable: true
10
+ ---
11
+
12
+ # Writer
13
+
14
+ ## Role
15
+ Produce clear, accurate technical documentation: README files, API docs, guides, code comments, and changelogs.
16
+
17
+ ## Responsibilities
18
+ - README and getting started guides
19
+ - API documentation and code comments
20
+ - Changelog and release notes
21
+
22
+ ## Constraints
23
+ - Matches existing documentation style
24
+ - Never documents code that does not exist
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/hud/statusline.mts
4
+ import { mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
5
+ import { homedir } from "os";
6
+ import { dirname, join } from "path";
7
+ import { fileURLToPath } from "url";
8
+
9
+ // src/hud/renderer.mts
10
+ function formatAge(startedAt) {
11
+ const elapsed = Date.now() - startedAt;
12
+ const mins = Math.floor(elapsed / 6e4);
13
+ if (mins < 60) return `${mins}m`;
14
+ const hours = Math.floor(mins / 60);
15
+ const remainingMins = mins % 60;
16
+ return `${hours}h${remainingMins}m`;
17
+ }
18
+ function formatTokens(tokens) {
19
+ if (tokens >= 1e6) return `${(tokens / 1e6).toFixed(1)}M`;
20
+ if (tokens >= 1e3) return `${(tokens / 1e3).toFixed(1)}k`;
21
+ return `${tokens}`;
22
+ }
23
+ function renderPlain(state) {
24
+ const age = formatAge(state.startedAt);
25
+ const tokens = formatTokens(state.tokensUsed);
26
+ const ctx = state.contextPct;
27
+ const mode = state.activeMode || "-";
28
+ const model = state.activeModel || "sonnet";
29
+ const reqWarningPlain = state.warningActive ? " !!" : "";
30
+ const reqStrPlain = `req:${state.premiumRequests ?? 0}/${state.premiumRequestsTotal ?? 1500}${reqWarningPlain}`;
31
+ 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}`;
32
+ }
33
+
34
+ // src/hud/statusline.mts
35
+ var DEFAULT_VERSION = "0.0.0";
36
+ var DEFAULT_STATUSLINE = "OMP | hud: no active session";
37
+ var DEFAULT_TOKEN_BUDGET = 2e5;
38
+ var DEFAULT_PREMIUM_REQUESTS_TOTAL = 1500;
39
+ function getStatuslinePaths(home = process.env["HOME"] || homedir()) {
40
+ const ompDir = join(home, ".omp");
41
+ const hudDir = join(ompDir, "hud");
42
+ return {
43
+ legacyLinePath: join(ompDir, "hud.line"),
44
+ hudDir,
45
+ statusJsonPath: join(hudDir, "status.json"),
46
+ displayPath: join(hudDir, "display.txt"),
47
+ tmuxSegmentPath: join(hudDir, "tmux-segment.sh")
48
+ };
49
+ }
50
+ function ensureParent(filePath) {
51
+ mkdirSync(dirname(filePath), { recursive: true });
52
+ }
53
+ function writeAtomic(filePath, content, mode) {
54
+ ensureParent(filePath);
55
+ const tempPath = `${filePath}.tmp`;
56
+ writeFileSync(tempPath, content, mode === void 0 ? "utf-8" : { encoding: "utf-8", mode });
57
+ renameSync(tempPath, filePath);
58
+ }
59
+ function normalizeStringArray(value) {
60
+ if (!Array.isArray(value)) return [];
61
+ return value.filter((item) => typeof item === "string");
62
+ }
63
+ function serializeHudState(state) {
64
+ return {
65
+ ...state,
66
+ toolsUsed: Array.from(state.toolsUsed),
67
+ skillsUsed: Array.from(state.skillsUsed)
68
+ };
69
+ }
70
+ function deserializeHudState(raw) {
71
+ if (!raw || typeof raw !== "object") return null;
72
+ const value = raw;
73
+ const toolsUsed = new Set(normalizeStringArray(value.toolsUsed));
74
+ const skillsUsed = new Set(normalizeStringArray(value.skillsUsed));
75
+ const agentsActive = normalizeStringArray(value.agentsActive);
76
+ const status = typeof value.status === "string" ? value.status : "idle";
77
+ return {
78
+ sessionId: typeof value.sessionId === "string" ? value.sessionId : "default",
79
+ activeMode: typeof value.activeMode === "string" ? value.activeMode : null,
80
+ activeModel: typeof value.activeModel === "string" ? value.activeModel : "sonnet",
81
+ contextPct: typeof value.contextPct === "number" ? value.contextPct : 0,
82
+ tokensUsed: typeof value.tokensUsed === "number" ? value.tokensUsed : 0,
83
+ tokensTotal: typeof value.tokensTotal === "number" ? value.tokensTotal : DEFAULT_TOKEN_BUDGET,
84
+ agentsActive,
85
+ lastAgent: typeof value.lastAgent === "string" ? value.lastAgent : agentsActive.at(-1) ?? "-",
86
+ lastOutput: typeof value.lastOutput === "string" ? value.lastOutput : "",
87
+ taskProgress: typeof value.taskProgress === "number" ? value.taskProgress : 0,
88
+ startedAt: typeof value.startedAt === "number" ? value.startedAt : Date.now(),
89
+ updatedAt: typeof value.updatedAt === "number" ? value.updatedAt : Date.now(),
90
+ version: typeof value.version === "string" ? value.version : DEFAULT_VERSION,
91
+ status,
92
+ sessionDurationMs: typeof value.sessionDurationMs === "number" ? value.sessionDurationMs : 0,
93
+ cumulativeAgentsUsed: typeof value.cumulativeAgentsUsed === "number" ? value.cumulativeAgentsUsed : agentsActive.length,
94
+ toolsUsed,
95
+ skillsUsed,
96
+ toolsTotal: typeof value.toolsTotal === "number" ? value.toolsTotal : 13,
97
+ skillsTotal: typeof value.skillsTotal === "number" ? value.skillsTotal : 25,
98
+ agentsTotal: typeof value.agentsTotal === "number" ? value.agentsTotal : 23,
99
+ premiumRequests: typeof value.premiumRequests === "number" ? value.premiumRequests : 0,
100
+ premiumRequestsTotal: typeof value.premiumRequestsTotal === "number" ? value.premiumRequestsTotal : DEFAULT_PREMIUM_REQUESTS_TOTAL,
101
+ warningActive: typeof value.warningActive === "boolean" ? value.warningActive : false
102
+ };
103
+ }
104
+ function buildHudState(snapshot, now = Date.now()) {
105
+ const startedAt = snapshot.started_at ?? now;
106
+ const updatedAt = snapshot.updated_at ?? now;
107
+ const toolsUsed = new Set(normalizeStringArray(snapshot.tools_used));
108
+ const skillsUsed = new Set(normalizeStringArray(snapshot.skills_used));
109
+ const agentsActive = normalizeStringArray(snapshot.agents_used);
110
+ return {
111
+ sessionId: snapshot.session_id ?? "default",
112
+ activeMode: snapshot.active_mode ?? null,
113
+ activeModel: snapshot.model ?? "sonnet",
114
+ contextPct: snapshot.context_pct ?? 0,
115
+ tokensUsed: snapshot.tokens_estimated ?? 0,
116
+ tokensTotal: snapshot.token_budget ?? DEFAULT_TOKEN_BUDGET,
117
+ agentsActive,
118
+ lastAgent: agentsActive.at(-1) ?? "-",
119
+ lastOutput: snapshot.last_output ?? "",
120
+ taskProgress: snapshot.task_progress ?? 0,
121
+ startedAt,
122
+ updatedAt,
123
+ version: snapshot.version ?? DEFAULT_VERSION,
124
+ status: snapshot.status ?? "idle",
125
+ sessionDurationMs: Math.max(0, updatedAt - startedAt),
126
+ cumulativeAgentsUsed: agentsActive.length,
127
+ toolsUsed,
128
+ skillsUsed,
129
+ toolsTotal: 13,
130
+ skillsTotal: 25,
131
+ agentsTotal: 23,
132
+ premiumRequests: snapshot.premium_requests ?? 0,
133
+ premiumRequestsTotal: snapshot.premium_requests_total ?? DEFAULT_PREMIUM_REQUESTS_TOTAL,
134
+ warningActive: snapshot.warning_active ?? false
135
+ };
136
+ }
137
+ function writeHudArtifacts(snapshot, paths = getStatuslinePaths()) {
138
+ const state = buildHudState(snapshot);
139
+ const line = renderPlain(state);
140
+ const serializedState = `${JSON.stringify(serializeHudState(state), null, 2)}
141
+ `;
142
+ writeAtomic(paths.statusJsonPath, serializedState);
143
+ writeAtomic(paths.displayPath, `${line}
144
+ `);
145
+ writeAtomic(paths.tmuxSegmentPath, `${line}
146
+ `, 493);
147
+ writeAtomic(paths.legacyLinePath, `${line}
148
+ `);
149
+ return { line, state, paths };
150
+ }
151
+ function readStatusline(paths = getStatuslinePaths()) {
152
+ try {
153
+ const line = readFileSync(paths.displayPath, "utf-8").trim();
154
+ if (line) return line;
155
+ } catch {
156
+ }
157
+ try {
158
+ const parsed = JSON.parse(readFileSync(paths.statusJsonPath, "utf-8"));
159
+ const state = deserializeHudState(parsed);
160
+ if (state) return renderPlain(state);
161
+ } catch {
162
+ }
163
+ try {
164
+ const line = readFileSync(paths.legacyLinePath, "utf-8").trim();
165
+ if (line) return line;
166
+ } catch {
167
+ }
168
+ return DEFAULT_STATUSLINE;
169
+ }
170
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
171
+ console.log(readStatusline());
172
+ }
173
+ export {
174
+ buildHudState,
175
+ getStatuslinePaths,
176
+ readStatusline,
177
+ writeHudArtifacts
178
+ };
179
+ //# sourceMappingURL=omp-statusline.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/hud/statusline.mts", "../src/hud/renderer.mts"],
4
+ "sourcesContent": ["/**\n * HUD statusline helpers and standalone entrypoint.\n *\n * Keeps HUD artifact generation in one place so hooks and shell wrappers\n * can share the same rendering and fallback behavior.\n */\n\nimport { mkdirSync, readFileSync, renameSync, writeFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { renderPlain, type HudState, type HudStatus } from \"./renderer.mts\";\n\nconst DEFAULT_VERSION = \"0.0.0\";\nconst DEFAULT_STATUSLINE = \"OMP | hud: no active session\";\nconst DEFAULT_TOKEN_BUDGET = 200_000;\nconst DEFAULT_PREMIUM_REQUESTS_TOTAL = 1500;\n\nexport interface StatuslinePaths {\n legacyLinePath: string;\n hudDir: string;\n statusJsonPath: string;\n displayPath: string;\n tmuxSegmentPath: string;\n}\n\nexport interface HudSnapshot {\n version?: string;\n session_id?: string;\n started_at?: number;\n updated_at?: number;\n model?: string;\n tokens_estimated?: number;\n token_budget?: number;\n context_pct?: number;\n tools_used?: string[];\n skills_used?: string[];\n agents_used?: string[];\n active_mode?: string | null;\n last_output?: string;\n task_progress?: number;\n status?: HudStatus;\n premium_requests?: number;\n premium_requests_total?: number;\n warning_active?: boolean;\n}\n\ninterface SerializedHudState extends Omit<HudState, \"toolsUsed\" | \"skillsUsed\"> {\n toolsUsed: string[];\n skillsUsed: string[];\n}\n\nexport function getStatuslinePaths(home = process.env[\"HOME\"] || homedir()): StatuslinePaths {\n const ompDir = join(home, \".omp\");\n const hudDir = join(ompDir, \"hud\");\n return {\n legacyLinePath: join(ompDir, \"hud.line\"),\n hudDir,\n statusJsonPath: join(hudDir, \"status.json\"),\n displayPath: join(hudDir, \"display.txt\"),\n tmuxSegmentPath: join(hudDir, \"tmux-segment.sh\"),\n };\n}\n\nfunction ensureParent(filePath: string): void {\n mkdirSync(dirname(filePath), { recursive: true });\n}\n\nfunction writeAtomic(filePath: string, content: string, mode?: number): void {\n ensureParent(filePath);\n const tempPath = `${filePath}.tmp`;\n writeFileSync(tempPath, content, mode === undefined ? \"utf-8\" : { encoding: \"utf-8\", mode });\n renameSync(tempPath, filePath);\n}\n\nfunction normalizeStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter((item): item is string => typeof item === \"string\");\n}\n\nfunction serializeHudState(state: HudState): SerializedHudState {\n return {\n ...state,\n toolsUsed: Array.from(state.toolsUsed),\n skillsUsed: Array.from(state.skillsUsed),\n };\n}\n\nfunction deserializeHudState(raw: unknown): HudState | null {\n if (!raw || typeof raw !== \"object\") return null;\n const value = raw as Record<string, unknown>;\n const toolsUsed = new Set(normalizeStringArray(value.toolsUsed));\n const skillsUsed = new Set(normalizeStringArray(value.skillsUsed));\n const agentsActive = normalizeStringArray(value.agentsActive);\n const status = typeof value.status === \"string\" ? (value.status as HudStatus) : \"idle\";\n\n return {\n sessionId: typeof value.sessionId === \"string\" ? value.sessionId : \"default\",\n activeMode: typeof value.activeMode === \"string\" ? value.activeMode : null,\n activeModel: typeof value.activeModel === \"string\" ? value.activeModel : \"sonnet\",\n contextPct: typeof value.contextPct === \"number\" ? value.contextPct : 0,\n tokensUsed: typeof value.tokensUsed === \"number\" ? value.tokensUsed : 0,\n tokensTotal: typeof value.tokensTotal === \"number\" ? value.tokensTotal : DEFAULT_TOKEN_BUDGET,\n agentsActive,\n lastAgent: typeof value.lastAgent === \"string\" ? value.lastAgent : agentsActive.at(-1) ?? \"-\",\n lastOutput: typeof value.lastOutput === \"string\" ? value.lastOutput : \"\",\n taskProgress: typeof value.taskProgress === \"number\" ? value.taskProgress : 0,\n startedAt: typeof value.startedAt === \"number\" ? value.startedAt : Date.now(),\n updatedAt: typeof value.updatedAt === \"number\" ? value.updatedAt : Date.now(),\n version: typeof value.version === \"string\" ? value.version : DEFAULT_VERSION,\n status,\n sessionDurationMs: typeof value.sessionDurationMs === \"number\" ? value.sessionDurationMs : 0,\n cumulativeAgentsUsed: typeof value.cumulativeAgentsUsed === \"number\" ? value.cumulativeAgentsUsed : agentsActive.length,\n toolsUsed,\n skillsUsed,\n toolsTotal: typeof value.toolsTotal === \"number\" ? value.toolsTotal : 13,\n skillsTotal: typeof value.skillsTotal === \"number\" ? value.skillsTotal : 25,\n agentsTotal: typeof value.agentsTotal === \"number\" ? value.agentsTotal : 23,\n premiumRequests: typeof value.premiumRequests === \"number\" ? value.premiumRequests : 0,\n premiumRequestsTotal: typeof value.premiumRequestsTotal === \"number\" ? value.premiumRequestsTotal : DEFAULT_PREMIUM_REQUESTS_TOTAL,\n warningActive: typeof value.warningActive === \"boolean\" ? value.warningActive : false,\n };\n}\n\nexport function buildHudState(snapshot: HudSnapshot, now = Date.now()): HudState {\n const startedAt = snapshot.started_at ?? now;\n const updatedAt = snapshot.updated_at ?? now;\n const toolsUsed = new Set(normalizeStringArray(snapshot.tools_used));\n const skillsUsed = new Set(normalizeStringArray(snapshot.skills_used));\n const agentsActive = normalizeStringArray(snapshot.agents_used);\n\n return {\n sessionId: snapshot.session_id ?? \"default\",\n activeMode: snapshot.active_mode ?? null,\n activeModel: snapshot.model ?? \"sonnet\",\n contextPct: snapshot.context_pct ?? 0,\n tokensUsed: snapshot.tokens_estimated ?? 0,\n tokensTotal: snapshot.token_budget ?? DEFAULT_TOKEN_BUDGET,\n agentsActive,\n lastAgent: agentsActive.at(-1) ?? \"-\",\n lastOutput: snapshot.last_output ?? \"\",\n taskProgress: snapshot.task_progress ?? 0,\n startedAt,\n updatedAt,\n version: snapshot.version ?? DEFAULT_VERSION,\n status: snapshot.status ?? \"idle\",\n sessionDurationMs: Math.max(0, updatedAt - startedAt),\n cumulativeAgentsUsed: agentsActive.length,\n toolsUsed,\n skillsUsed,\n toolsTotal: 13,\n skillsTotal: 25,\n agentsTotal: 23,\n premiumRequests: snapshot.premium_requests ?? 0,\n premiumRequestsTotal: snapshot.premium_requests_total ?? DEFAULT_PREMIUM_REQUESTS_TOTAL,\n warningActive: snapshot.warning_active ?? false,\n };\n}\n\nexport function writeHudArtifacts(snapshot: HudSnapshot, paths = getStatuslinePaths()): { line: string; state: HudState; paths: StatuslinePaths } {\n const state = buildHudState(snapshot);\n const line = renderPlain(state);\n const serializedState = `${JSON.stringify(serializeHudState(state), null, 2)}\\n`;\n\n writeAtomic(paths.statusJsonPath, serializedState);\n writeAtomic(paths.displayPath, `${line}\\n`);\n writeAtomic(paths.tmuxSegmentPath, `${line}\\n`, 0o755);\n writeAtomic(paths.legacyLinePath, `${line}\\n`);\n\n return { line, state, paths };\n}\n\nexport function readStatusline(paths = getStatuslinePaths()): string {\n try {\n const line = readFileSync(paths.displayPath, \"utf-8\").trim();\n if (line) return line;\n } catch {\n // Fall through to other sources.\n }\n\n try {\n const parsed = JSON.parse(readFileSync(paths.statusJsonPath, \"utf-8\"));\n const state = deserializeHudState(parsed);\n if (state) return renderPlain(state);\n } catch {\n // Fall through to legacy file.\n }\n\n try {\n const line = readFileSync(paths.legacyLinePath, \"utf-8\").trim();\n if (line) return line;\n } catch {\n // No HUD artifacts yet.\n }\n\n return DEFAULT_STATUSLINE;\n}\n\nif (process.argv[1] === fileURLToPath(import.meta.url)) {\n console.log(readStatusline());\n}\n", "/**\n * HUD Renderer\n * Formats HudState into ANSI or plain text status lines.\n */\n\n\nexport interface HudState {\n sessionId: string;\n activeMode: string | null;\n activeModel: string;\n contextPct: number;\n tokensUsed: number;\n tokensTotal: number;\n agentsActive: string[];\n lastAgent: string;\n lastOutput: string;\n taskProgress: number;\n startedAt: number;\n updatedAt: number;\n version: string;\n status: HudStatus;\n sessionDurationMs: number;\n cumulativeAgentsUsed: number;\n toolsUsed: Set<string>;\n skillsUsed: Set<string>;\n toolsTotal: number;\n skillsTotal: number;\n agentsTotal: number;\n premiumRequests: number;\n premiumRequestsTotal: number;\n warningActive: boolean;\n}\n\nexport type HudStatus = \"idle\" | \"running\" | \"waiting\" | \"complete\" | \"error\" | \"eco\";\n\nconst STATUS_ICONS: Record<HudStatus, string> = {\n idle: \"\u25CB\",\n running: \"\u25CF\",\n waiting: \"\u25F7\",\n complete: \"\u2713\",\n error: \"\u2717\",\n eco: \"\u26A1\",\n};\n\nfunction formatAge(startedAt: number): string {\n const elapsed = Date.now() - startedAt;\n const mins = Math.floor(elapsed / 60000);\n if (mins < 60) return `${mins}m`;\n const hours = Math.floor(mins / 60);\n const remainingMins = mins % 60;\n return `${hours}h${remainingMins}m`;\n}\n\nfunction formatTokens(tokens: number): string {\n if (tokens >= 1_000_000) return `${(tokens / 1_000_000).toFixed(1)}M`;\n if (tokens >= 1_000) return `${(tokens / 1_000).toFixed(1)}k`;\n return `${tokens}`;\n}\n\nfunction ctxColor(pct: number): string {\n if (pct < 60) return \"\\x1b[32m\"; // green\n if (pct < 85) return \"\\x1b[33m\"; // yellow\n return \"\\x1b[31m\"; // red\n}\n\nfunction reset(): string {\n return \"\\x1b[0m\";\n}\n\n/**\n * Render HUD line with ANSI color codes.\n * Format: [OMP v1.0.0] mode | model | ctx:N% | tok:~Nk/Nk | Nm | tools:N/N | skills:N/N | agents:N/N | N% status\n */\nexport function renderAnsi(state: HudState): string {\n const age = formatAge(state.startedAt);\n const tokens = formatTokens(state.tokensUsed);\n const ctx = state.contextPct;\n const mode = state.activeMode || \"-\";\n const model = state.activeModel || \"sonnet\";\n const icon = STATUS_ICONS[state.status] || \"\u25CF\";\n\n const ctxClr = ctxColor(ctx);\n const ctxStr = `${ctxClr}ctx:${ctx}%${reset()}`;\n const tokenStr = `tok:~${tokens}/${state.tokensTotal}`;\n const modeStr = mode === \"-\" ? \"-\" : `\\x1b[36m${mode}${reset()}`; // cyan for active modes\n\n const reqWarning = state.warningActive ? \" !!\" : \"\";\n const reqStr = `req:${state.premiumRequests ?? 0}/${state.premiumRequestsTotal ?? 1500}${reqWarning}`;\n\n 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}`;\n}\n\n/**\n * Render HUD line as plain text (no ANSI codes).\n * Format: [OMP v1.0.0] mode | model | ctx:N% | tok:~Nk/Nk | Nm | tools:N/N | skills:N/N | agents:N/N | N% status\n */\nexport function renderPlain(state: HudState): string {\n const age = formatAge(state.startedAt);\n const tokens = formatTokens(state.tokensUsed);\n const ctx = state.contextPct;\n const mode = state.activeMode || \"-\";\n const model = state.activeModel || \"sonnet\";\n\n const reqWarningPlain = state.warningActive ? \" !!\" : \"\";\n const reqStrPlain = `req:${state.premiumRequests ?? 0}/${state.premiumRequestsTotal ?? 1500}${reqWarningPlain}`;\n\n 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}`;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
5
+ ENTRY="$SCRIPT_DIR/omp-statusline.mjs"
6
+ DISPLAY_PATH="${OMP_HUD_DISPLAY_PATH:-$HOME/.omp/hud/display.txt}"
7
+ LEGACY_PATH="${OMP_HUD_LEGACY_PATH:-$HOME/.omp/hud.line}"
8
+
9
+ if [[ -f "$ENTRY" ]]; then
10
+ exec node "$ENTRY" "$@"
11
+ fi
12
+
13
+ if [[ -r "$DISPLAY_PATH" ]]; then
14
+ exec cat "$DISPLAY_PATH"
15
+ fi
16
+
17
+ if [[ -r "$LEGACY_PATH" ]]; then
18
+ exec cat "$LEGACY_PATH"
19
+ fi
20
+
21
+ printf 'OMP | hud: no active session\n'