open-multi-agent-kit 0.78.6 → 0.78.7
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/AGENTS.md +1 -1
- package/CHANGELOG.md +26 -0
- package/MATURITY.md +2 -2
- package/README.md +19 -4
- package/dist/brand/night-city.theme.json +80 -0
- package/dist/brand/palette.d.ts +73 -177
- package/dist/brand/palette.js +115 -39
- package/dist/brand/rust-forge.theme.json +216 -0
- package/dist/brand/theme-compiled.d.ts +61 -0
- package/dist/brand/theme-compiled.js +241 -0
- package/dist/brand/theme.js +50 -37
- package/dist/cli/release-promotion-gate.d.ts +8 -1
- package/dist/cli/release-promotion-gate.js +20 -9
- package/dist/cli/root.d.ts +1 -0
- package/dist/cli/root.js +2 -1
- package/dist/cli/theme/index.d.ts +11 -2
- package/dist/cli/theme/index.js +6 -1
- package/dist/cli/theme/oklab-quantize.d.ts +29 -0
- package/dist/cli/theme/oklab-quantize.js +105 -0
- package/dist/cli/theme/render-table.d.ts +59 -0
- package/dist/cli/theme/render-table.js +112 -0
- package/dist/cli/theme/status-frame.d.ts +10 -0
- package/dist/cli/theme/status-frame.js +22 -0
- package/dist/cli/theme/terminal-capability.d.ts +6 -1
- package/dist/cli/theme/terminal-capability.js +20 -4
- package/dist/cli/theme/theme-doc.d.ts +22 -0
- package/dist/cli/theme/theme-doc.js +97 -0
- package/dist/cli/theme/theme-registry.js +39 -18
- package/dist/cli/theme/tier-explain.d.ts +21 -0
- package/dist/cli/theme/tier-explain.js +60 -0
- package/dist/cli/ui/green-rain-renderer.js +3 -2
- package/dist/cli/ui/neon-grid-renderer.js +4 -3
- package/dist/cli/ui/rust-forge-renderer.js +17 -3
- package/dist/cli/ui/system24-renderer.d.ts +18 -1
- package/dist/cli/ui/system24-renderer.js +39 -16
- package/dist/cli/v2/chat-repl.js +3 -1
- package/dist/cli/v2/cli-v2-skeleton.d.ts +6 -0
- package/dist/cli/v2/cli-v2-skeleton.js +121 -9
- package/dist/cli/v2/interactive-prompt.d.ts +1 -0
- package/dist/cli/v2/interactive-prompt.js +6 -2
- package/dist/commands/chat/core.js +2 -2
- package/dist/commands/chat/runtime.js +2 -0
- package/dist/commands/chat/utils.js +12 -4
- package/dist/commands/cockpit/render.js +102 -64
- package/dist/commands/cockpit/utils.d.ts +2 -0
- package/dist/commands/design.js +18 -16
- package/dist/commands/doctor/checks.d.ts +0 -1
- package/dist/commands/doctor/checks.js +1 -36
- package/dist/commands/doctor/report.js +0 -11
- package/dist/commands/init/content.d.ts +1 -1
- package/dist/commands/init/content.js +3 -11
- package/dist/commands/init.js +2 -2
- package/dist/commands/mcp/config.d.ts +32 -0
- package/dist/commands/mcp/config.js +264 -0
- package/dist/commands/mcp/doctor-fix.d.ts +12 -0
- package/dist/commands/mcp/doctor-fix.js +261 -0
- package/dist/commands/mcp/doctor.d.ts +55 -0
- package/dist/commands/mcp/doctor.js +401 -0
- package/dist/commands/mcp/list.d.ts +1 -0
- package/dist/commands/mcp/list.js +56 -0
- package/dist/commands/mcp/shared.d.ts +47 -0
- package/dist/commands/mcp/shared.js +192 -0
- package/dist/commands/mcp/test.d.ts +5 -0
- package/dist/commands/mcp/test.js +457 -0
- package/dist/commands/mcp.d.ts +8 -104
- package/dist/commands/mcp.js +5 -1603
- package/dist/contracts/proof.d.ts +1 -1
- package/dist/goal/control-loop.d.ts +15 -0
- package/dist/goal/control-loop.js +39 -5
- package/dist/hud/render.d.ts +2 -0
- package/dist/hud/render.js +7 -1
- package/dist/mcp/secret-scanner.d.ts +6 -0
- package/dist/mcp/secret-scanner.js +44 -11
- package/dist/memory/graph-delta-log.d.ts +137 -0
- package/dist/memory/graph-delta-log.js +650 -0
- package/dist/memory/graph-viewer.js +13 -32
- package/dist/memory/local-graph-memory-store.d.ts +36 -3
- package/dist/memory/local-graph-memory-store.js +255 -10
- package/dist/orchestration/log-streamer.js +13 -8
- package/dist/orchestration/routing.d.ts +4 -0
- package/dist/orchestration/routing.js +28 -3
- package/dist/orchestration/state-persister.js +8 -1
- package/dist/providers/anthropic-messages-runner.d.ts +17 -0
- package/dist/providers/anthropic-messages-runner.js +197 -0
- package/dist/providers/model-registry.d.ts +1 -1
- package/dist/providers/model-registry.js +37 -3
- package/dist/providers/provider-runtime.js +27 -11
- package/dist/providers/thinking-levels.js +4 -1
- package/dist/providers/types.d.ts +3 -3
- package/dist/runtime/contracts/weakness-remediation.d.ts +9 -1
- package/dist/runtime/contracts/weakness-remediation.js +9 -1
- package/dist/runtime/router-v2-scoring.d.ts +8 -3
- package/dist/runtime/router-v2-scoring.js +27 -22
- package/dist/runtime/runtime-router.d.ts +5 -0
- package/dist/runtime/runtime-router.js +40 -8
- package/dist/runtime/sandbox-profile.d.ts +29 -0
- package/dist/runtime/sandbox-profile.js +101 -0
- package/dist/runtime/slash-commands.js +300 -2
- package/dist/runtime/tool-dispatch-contracts.d.ts +15 -0
- package/dist/runtime/tool-dispatch-contracts.js +12 -0
- package/dist/runtime/weights-config.d.ts +90 -0
- package/dist/runtime/weights-config.js +249 -0
- package/dist/schema/envelope.schema.d.ts +18 -18
- package/dist/schema/evidence.schema.d.ts +2 -2
- package/dist/schema/proof-bundle.schema.d.ts +6 -6
- package/dist/schema/proof-bundle.schema.js +0 -1
- package/dist/schema/provider.schema.d.ts +2 -2
- package/dist/schema/run-manifest.schema.d.ts +16 -16
- package/dist/theme/ansi.js +9 -2
- package/dist/theme/extended-palette.d.ts +85 -0
- package/dist/theme/extended-palette.js +108 -0
- package/dist/theme/layout.js +29 -8
- package/dist/theme/metrics.js +5 -5
- package/dist/theme/parallel.js +25 -15
- package/dist/ui/omk-sigil.js +5 -14
- package/dist/ui/omk-working-sweep.js +5 -15
- package/dist/util/chat-agent-mode.d.ts +11 -0
- package/dist/util/chat-agent-mode.js +41 -8
- package/dist/util/chat-cockpit.d.ts +9 -0
- package/dist/util/chat-cockpit.js +77 -20
- package/dist/util/fs/core.d.ts +5 -0
- package/dist/util/fs/core.js +35 -0
- package/dist/util/fs/internal.d.ts +14 -0
- package/dist/util/fs/internal.js +169 -0
- package/dist/util/fs/kimi-sync.d.ts +41 -0
- package/dist/util/fs/kimi-sync.js +495 -0
- package/dist/util/fs/logo.d.ts +2 -0
- package/dist/util/fs/logo.js +78 -0
- package/dist/util/fs/manifest.d.ts +6 -0
- package/dist/util/fs/manifest.js +40 -0
- package/dist/util/fs/mcp-diagnose.d.ts +15 -0
- package/dist/util/fs/mcp-diagnose.js +204 -0
- package/dist/util/fs/mcp-runtime-config.d.ts +23 -0
- package/dist/util/fs/mcp-runtime-config.js +412 -0
- package/dist/util/fs/paths.d.ts +13 -0
- package/dist/util/fs/paths.js +82 -0
- package/dist/util/fs/preflight.d.ts +27 -0
- package/dist/util/fs/preflight.js +271 -0
- package/dist/util/fs.d.ts +8 -128
- package/dist/util/fs.js +8 -1757
- package/dist/util/terminal-layout.js +5 -1
- package/dist/util/version.js +2 -1
- package/docs/2026-06-11/critical-issues.md +20 -0
- package/docs/2026-06-11/improvements.md +14 -0
- package/docs/2026-06-11/init-checklist.md +25 -0
- package/docs/2026-06-11/plan.md +20 -0
- package/docs/ARCHITECTURE_ANALYSIS_CODEGRAPH.md +223 -0
- package/docs/adr/0001-no-native-rust-lane.md +52 -0
- package/docs/codex-oauth-setup.md +14 -0
- package/docs/decisions/2026-06-10-git-history-bloat.md +61 -0
- package/docs/decisions/ADR-theme-dark-only-assets.md +43 -0
- package/docs/getting-started.md +1 -1
- package/docs/headroom-omk-final-summary.md +188 -0
- package/docs/headroom-omk-integration.md +394 -0
- package/docs/headroom-omk-setup-guide.md +422 -0
- package/docs/headroom-omk-usage-examples.md +371 -0
- package/docs/provider-maturity.md +1 -1
- package/docs/versioning.md +3 -3
- package/package.json +10 -10
- package/readmeasset/.npmignore +2 -0
- package/readmeasset/ASSET_INDEX.md +7 -5
- package/readmeasset/ASSET_PROVENANCE.md +21 -5
- package/readmeasset/omk-control-surfaces.svg +55 -0
- package/readmeasset/omk-core-loop.svg +1 -0
- package/readmeasset/omk-logo-mark.svg +1 -0
- package/readmeasset/omk-release-assertions.svg +51 -0
- package/dist/native/linux-x64/omk-safety +0 -0
- package/dist/util/native-safety.d.ts +0 -28
- package/dist/util/native-safety.js +0 -118
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
* Maps semantic tokens to ANSI colors. Reuses src/theme/colors.ts exports.
|
|
4
4
|
*/
|
|
5
5
|
import { style } from "../../theme/colors.js";
|
|
6
|
+
import { compileTheme } from "./render-table.js";
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
import { join, dirname } from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
6
10
|
// --- omk (full brand) ---
|
|
7
11
|
const omkPalette = {
|
|
8
12
|
name: "omk",
|
|
@@ -138,30 +142,47 @@ const neonCircuitPalette = {
|
|
|
138
142
|
}
|
|
139
143
|
},
|
|
140
144
|
};
|
|
141
|
-
// --- rust-forge (
|
|
145
|
+
// --- rust-forge (oxidized forge console) ---
|
|
146
|
+
// Compiled from themes/rust-forge.theme.json (omk.theme.v1).
|
|
147
|
+
const rustForgeDoc = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "themes", "rust-forge.theme.json"), "utf8"));
|
|
148
|
+
const rustForgeCompiled = compileTheme(rustForgeDoc, "truecolor");
|
|
142
149
|
const rustForgePalette = {
|
|
143
150
|
name: "rust-forge",
|
|
144
151
|
mode: "dark",
|
|
145
152
|
supportsColor: true,
|
|
146
153
|
render(semantic, text) {
|
|
154
|
+
const map = {
|
|
155
|
+
success: "evidence.pass",
|
|
156
|
+
warning: "telemetry.warn",
|
|
157
|
+
error: "telemetry.error",
|
|
158
|
+
info: "telemetry.info",
|
|
159
|
+
agent: "control.accent",
|
|
160
|
+
task: "control.fg",
|
|
161
|
+
tool: "evidence.pass",
|
|
162
|
+
header: "control.accent",
|
|
163
|
+
subheader: "dag.lane.done",
|
|
164
|
+
separator: "control.dim",
|
|
165
|
+
bullet: "control.accent",
|
|
166
|
+
labelKey: "control.dim",
|
|
167
|
+
labelValue: "control.fg",
|
|
168
|
+
};
|
|
147
169
|
switch (semantic) {
|
|
148
|
-
case "
|
|
149
|
-
case "
|
|
150
|
-
case "
|
|
151
|
-
case "
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
default: return text;
|
|
170
|
+
case "dim": return "\u001b[2m" + text + "\u001b[0m";
|
|
171
|
+
case "bold": return "\u001b[1m" + text + "\u001b[0m";
|
|
172
|
+
case "reset": return "\u001b[0m" + text;
|
|
173
|
+
case "bullet": {
|
|
174
|
+
const entry = rustForgeCompiled.tokens[map.bullet];
|
|
175
|
+
return entry ? entry.sgr + "▣ " + text + rustForgeCompiled.reset : text;
|
|
176
|
+
}
|
|
177
|
+
default: {
|
|
178
|
+
const role = map[semantic];
|
|
179
|
+
if (role) {
|
|
180
|
+
const entry = rustForgeCompiled.tokens[role];
|
|
181
|
+
if (entry)
|
|
182
|
+
return entry.sgr + text + rustForgeCompiled.reset;
|
|
183
|
+
}
|
|
184
|
+
return text;
|
|
185
|
+
}
|
|
165
186
|
}
|
|
166
187
|
},
|
|
167
188
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Theme — Color Tier Explanation
|
|
3
|
+
* Re-derives the degradation tier with the SAME precedence rules as
|
|
4
|
+
* terminal-capability.ts detectColorDepth(), but records WHY each decision
|
|
5
|
+
* was taken (env vars, --no-color flag, TERM) for `omk doctor` reporting.
|
|
6
|
+
*/
|
|
7
|
+
import type { ColorTier } from "./terminal-capability.js";
|
|
8
|
+
export interface ColorTierExplanation {
|
|
9
|
+
readonly tier: ColorTier;
|
|
10
|
+
/** Human-readable reasons, in detection-precedence order. */
|
|
11
|
+
readonly reasons: readonly string[];
|
|
12
|
+
/** True when NO_COLOR env or --no-color flag asked for color suppression. */
|
|
13
|
+
readonly noColorRequested: boolean;
|
|
14
|
+
/** True when a no-color request actually resulted in the no-color tier. */
|
|
15
|
+
readonly noColorHonored: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Explain the detected color tier. Pure given (argv, env, isTty); defaults
|
|
19
|
+
* mirror terminal-capability.ts getTerminalCapability() inputs.
|
|
20
|
+
*/
|
|
21
|
+
export declare function explainColorTier(argv?: readonly string[], env?: NodeJS.ProcessEnv, isTty?: boolean): ColorTierExplanation;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Theme — Color Tier Explanation
|
|
3
|
+
* Re-derives the degradation tier with the SAME precedence rules as
|
|
4
|
+
* terminal-capability.ts detectColorDepth(), but records WHY each decision
|
|
5
|
+
* was taken (env vars, --no-color flag, TERM) for `omk doctor` reporting.
|
|
6
|
+
*/
|
|
7
|
+
import { colorTierForDepth } from "./terminal-capability.js";
|
|
8
|
+
function decideDepth(argv, env, isTty) {
|
|
9
|
+
if (argv.includes("--no-color")) {
|
|
10
|
+
return { depth: 0, reason: "--no-color CLI flag" };
|
|
11
|
+
}
|
|
12
|
+
if (env.NO_COLOR !== undefined) {
|
|
13
|
+
return { depth: 0, reason: "NO_COLOR env var set" };
|
|
14
|
+
}
|
|
15
|
+
if (env.TERM === "dumb") {
|
|
16
|
+
return { depth: 0, reason: "TERM=dumb" };
|
|
17
|
+
}
|
|
18
|
+
const force = env.FORCE_COLOR;
|
|
19
|
+
if (force === "0" || force === "false")
|
|
20
|
+
return { depth: 0, reason: `FORCE_COLOR=${force}` };
|
|
21
|
+
if (force === "1")
|
|
22
|
+
return { depth: 1, reason: "FORCE_COLOR=1 (basic ANSI)" };
|
|
23
|
+
if (force === "2")
|
|
24
|
+
return { depth: 4, reason: "FORCE_COLOR=2 (16-color)" };
|
|
25
|
+
if (force === "3")
|
|
26
|
+
return { depth: 8, reason: "FORCE_COLOR=3 (256-color)" };
|
|
27
|
+
if (env.COLORTERM === "truecolor" || env.COLORTERM === "24bit") {
|
|
28
|
+
return { depth: 24, reason: `COLORTERM=${env.COLORTERM}` };
|
|
29
|
+
}
|
|
30
|
+
const term = env.TERM ?? "";
|
|
31
|
+
if (term.includes("256color") || term.includes("256")) {
|
|
32
|
+
return { depth: 8, reason: `TERM=${term} (256-color terminfo)` };
|
|
33
|
+
}
|
|
34
|
+
if (term.includes("color") || term.includes("xterm") || term.includes("screen") || term.includes("tmux")) {
|
|
35
|
+
return { depth: 4, reason: `TERM=${term} (basic color terminfo)` };
|
|
36
|
+
}
|
|
37
|
+
if (isTty) {
|
|
38
|
+
return { depth: 1, reason: "TTY without explicit color hints (basic ANSI assumed)" };
|
|
39
|
+
}
|
|
40
|
+
return { depth: 0, reason: "not a TTY and no color env hints" };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Explain the detected color tier. Pure given (argv, env, isTty); defaults
|
|
44
|
+
* mirror terminal-capability.ts getTerminalCapability() inputs.
|
|
45
|
+
*/
|
|
46
|
+
export function explainColorTier(argv = process.argv, env = process.env, isTty = process.stdout.isTTY ?? false) {
|
|
47
|
+
const decision = decideDepth(argv, env, isTty);
|
|
48
|
+
const tier = colorTierForDepth(decision.depth);
|
|
49
|
+
const noColorRequested = argv.includes("--no-color") || env.NO_COLOR !== undefined;
|
|
50
|
+
const reasons = [decision.reason];
|
|
51
|
+
if (noColorRequested && tier !== "no-color") {
|
|
52
|
+
reasons.push("WARNING: no-color was requested but a color tier was selected");
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
tier,
|
|
56
|
+
reasons,
|
|
57
|
+
noColorRequested,
|
|
58
|
+
noColorHonored: !noColorRequested || tier === "no-color",
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import gradientString from "gradient-string";
|
|
2
2
|
import { System24Renderer } from "./system24-renderer.js";
|
|
3
3
|
import { GREEN_RAIN_THEME, resolveTuiMotion, shouldUseAnsiColor } from "../../brand/theme.js";
|
|
4
|
+
import { BRAND_HEX } from "../../brand/palette.js";
|
|
4
5
|
import { renderMatrixRain } from "../../brand/matrix-rain.js";
|
|
5
6
|
import { renderOmkSparkleText } from "../../ui/omk-sigil.js";
|
|
6
7
|
const ESC = "\x1b[";
|
|
@@ -87,9 +88,9 @@ export class GreenRainRenderer {
|
|
|
87
88
|
line(this.err, renderOmkSparkleText(titleLine, {
|
|
88
89
|
frame: Math.floor(Date.now() / 80),
|
|
89
90
|
noColor: this.noColor,
|
|
90
|
-
colors: [
|
|
91
|
+
colors: [BRAND_HEX.mint, BRAND_HEX.sparkleWhite, BRAND_HEX.sparkleGold, BRAND_HEX.cyan, BRAND_HEX.purple],
|
|
91
92
|
}), this.noColor);
|
|
92
|
-
line(this.err, gradientLine(mottoLine, [
|
|
93
|
+
line(this.err, gradientLine(mottoLine, [BRAND_HEX.mint, BRAND_HEX.cyan], this.noColor), this.noColor);
|
|
93
94
|
line(this.err, `${dim}${routeLine}${RST}`, this.noColor);
|
|
94
95
|
line(this.err, `${dim}${rootLine}${RST}`, this.noColor);
|
|
95
96
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import gradientString from "gradient-string";
|
|
2
2
|
import { System24Renderer } from "./system24-renderer.js";
|
|
3
3
|
import { NEON_GRID_THEME, resolveTuiMotion, shouldUseAnsiColor } from "../../brand/theme.js";
|
|
4
|
+
import { BRAND_HEX } from "../../brand/palette.js";
|
|
4
5
|
import { renderOmkSparkleText } from "../../ui/omk-sigil.js";
|
|
5
6
|
const ESC = "\x1b[";
|
|
6
7
|
const RST = `${ESC}0m`;
|
|
@@ -89,11 +90,11 @@ export class NeonGridRenderer {
|
|
|
89
90
|
line(this.err, renderOmkSparkleText(titleLine, {
|
|
90
91
|
frame: Math.floor(Date.now() / 80),
|
|
91
92
|
noColor: this.noColor,
|
|
92
|
-
colors: [
|
|
93
|
+
colors: [BRAND_HEX.cyan, BRAND_HEX.sparkleWhite, BRAND_HEX.sparkleGold, BRAND_HEX.magenta, BRAND_HEX.mint],
|
|
93
94
|
}), this.noColor);
|
|
94
|
-
line(this.err, gradientLine(mottoLine, [
|
|
95
|
+
line(this.err, gradientLine(mottoLine, [BRAND_HEX.mint, BRAND_HEX.cyan, BRAND_HEX.purple], this.noColor), this.noColor);
|
|
95
96
|
line(this.err, `${dim}${routeLine}${RST}`, this.noColor);
|
|
96
|
-
line(this.err, gradientLine(statusLine, [
|
|
97
|
+
line(this.err, gradientLine(statusLine, [BRAND_HEX.mint, BRAND_HEX.cyan, BRAND_HEX.amber], this.noColor), this.noColor);
|
|
97
98
|
line(this.err, `${dim}${rootLine}${RST}`, this.noColor);
|
|
98
99
|
}
|
|
99
100
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { System24Renderer } from "./system24-renderer.js";
|
|
2
2
|
import { RUST_FORGE_THEME, resolveTuiMotion, shouldUseAnsiColor } from "../../brand/theme.js";
|
|
3
|
+
import { BRAND_HEX } from "../../brand/palette.js";
|
|
3
4
|
import { renderOmkSigil, renderOmkSparkleText } from "../../ui/omk-sigil.js";
|
|
4
5
|
const ESC = "\x1b[";
|
|
5
6
|
const RST = `${ESC}0m`;
|
|
@@ -19,6 +20,13 @@ function center(text, width) {
|
|
|
19
20
|
const pad = Math.max(0, Math.floor((width - visibleLength(text)) / 2));
|
|
20
21
|
return `${" ".repeat(pad)}${text}`;
|
|
21
22
|
}
|
|
23
|
+
function forgeGauge(label, value, width) {
|
|
24
|
+
const clamped = Math.max(0, Math.min(1, value));
|
|
25
|
+
const barWidth = Math.max(6, Math.min(16, width - label.length - 10));
|
|
26
|
+
const filled = Math.round(clamped * barWidth);
|
|
27
|
+
const bar = `${"█".repeat(filled)}${"░".repeat(Math.max(0, barWidth - filled))}`;
|
|
28
|
+
return truncate(`${label} [${bar}] ${Math.round(clamped * 100)}%`, width);
|
|
29
|
+
}
|
|
22
30
|
function forgeScanline(seed, width) {
|
|
23
31
|
const glyphs = ["═", "─", "■", "▣", "◉", "◆"];
|
|
24
32
|
let hash = 0;
|
|
@@ -68,7 +76,7 @@ export class RustForgeRenderer {
|
|
|
68
76
|
const shouldRenderScanline = this.motion !== "off" && this.started && this.err.isTTY !== false;
|
|
69
77
|
const sigilName = this.resolveSigilName();
|
|
70
78
|
const sigilRows = sigilName !== "none" ? this.sigilHeight(sigilName) : 0;
|
|
71
|
-
return (shouldRenderScanline ? 1 : 0) +
|
|
79
|
+
return (shouldRenderScanline ? 1 : 0) + 7 + sigilRows;
|
|
72
80
|
}
|
|
73
81
|
resolveSigilName() {
|
|
74
82
|
const env = process.env.OMK_SIGIL?.trim().toLowerCase();
|
|
@@ -96,8 +104,12 @@ export class RustForgeRenderer {
|
|
|
96
104
|
const root = event.root ? truncate(event.root, Math.max(12, width - 16)) : "root:unknown";
|
|
97
105
|
const shouldRenderScanline = this.motion !== "off" && this.started && this.err.isTTY !== false;
|
|
98
106
|
const routeLine = truncate(`${RUST_FORGE_THEME.symbols.signal} FORGE ${run} · provider:${event.provider} · model:${event.model ?? "auto"}`, width);
|
|
99
|
-
const statusLine = truncate(`■
|
|
107
|
+
const statusLine = truncate(`■ FORGE route armed · VERIFY evidence · SCOPE MCP/skills/hooks`, width);
|
|
100
108
|
const rootLine = truncate(`${RUST_FORGE_THEME.symbols.pending} PENDING root ${root}`, width);
|
|
109
|
+
const independentLine = truncate("OMK INDEPENDENT CONTROL · adapters are lanes, not authority", width);
|
|
110
|
+
const heatSeed = (event.runId ?? "rust-forge").split("").reduce((sum, char) => sum + char.charCodeAt(0), 0);
|
|
111
|
+
const heat = 0.72 + (heatSeed % 19) / 100;
|
|
112
|
+
const forgeStateLine = truncate(`${forgeGauge("HEAT", heat, Math.floor(width / 2))} · ANVIL locked · QUENCH ready`, width);
|
|
101
113
|
const sigilName = this.resolveSigilName();
|
|
102
114
|
const showSigil = sigilName !== "none";
|
|
103
115
|
const sigilWidth = Math.min(64, Math.max(30, width - 4));
|
|
@@ -108,9 +120,11 @@ export class RustForgeRenderer {
|
|
|
108
120
|
line(this.err, renderOmkSparkleText(center(RUST_FORGE_THEME.label.toUpperCase(), width), {
|
|
109
121
|
frame: sigilFrame,
|
|
110
122
|
noColor: this.noColor,
|
|
111
|
-
colors: [hot,
|
|
123
|
+
colors: [hot, BRAND_HEX.sparkleWhite, BRAND_HEX.sparkleGold, BRAND_HEX.rustEmber, BRAND_HEX.rustCrimson],
|
|
112
124
|
}), this.noColor);
|
|
113
125
|
line(this.err, `${success}${center(truncate(RUST_FORGE_THEME.motto, width), width)}${RST}`, this.noColor);
|
|
126
|
+
line(this.err, `${hot}${center(independentLine, width)}${RST}`, this.noColor);
|
|
127
|
+
line(this.err, `${success}${center(forgeStateLine, width)}${RST}`, this.noColor);
|
|
114
128
|
// Render sigil art with animated sweep
|
|
115
129
|
if (showSigil) {
|
|
116
130
|
const sigilLines = renderOmkSigil({
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Panels:
|
|
12
12
|
* ┌─ session ──────────────────────────────────────┐
|
|
13
|
-
* │ ◆ OMK · mimo · mimo-v2.5-pro run
|
|
13
|
+
* │ ◆ OMK · mimo · mimo-v2.5-pro run id ab12 │
|
|
14
14
|
* └────────────────────────────────────────────────┘
|
|
15
15
|
* ┌─ turn ─────────────────────────────────────────┐
|
|
16
16
|
* │ ▸ user input │
|
|
@@ -26,12 +26,29 @@
|
|
|
26
26
|
import type { CliUiEvent } from "./event.js";
|
|
27
27
|
import type { CliRenderer } from "./renderer.js";
|
|
28
28
|
import type { OmkBrandTheme } from "../../brand/theme.js";
|
|
29
|
+
interface System24Palette {
|
|
30
|
+
bg3: string;
|
|
31
|
+
text1: string;
|
|
32
|
+
text2: string;
|
|
33
|
+
text3: string;
|
|
34
|
+
text5: string;
|
|
35
|
+
accent: string;
|
|
36
|
+
green: string;
|
|
37
|
+
amber: string;
|
|
38
|
+
red: string;
|
|
39
|
+
cyan: string;
|
|
40
|
+
border: string;
|
|
41
|
+
borderHL: string;
|
|
42
|
+
}
|
|
29
43
|
interface WritableStreamLike {
|
|
30
44
|
write(chunk: string): unknown;
|
|
31
45
|
isTTY?: boolean;
|
|
32
46
|
columns?: number;
|
|
33
47
|
rows?: number;
|
|
34
48
|
}
|
|
49
|
+
export declare function visibleLenForTest(s: string): number;
|
|
50
|
+
export declare function renderPanelLineForTest(c: System24Palette, content: string, width: number): string;
|
|
51
|
+
export declare function renderInlineForTest(c: System24Palette, text: string): string;
|
|
35
52
|
export interface System24RendererStreams {
|
|
36
53
|
stdout?: WritableStreamLike;
|
|
37
54
|
stderr?: WritableStreamLike;
|
|
@@ -31,6 +31,15 @@ const BORDER_BL = "└";
|
|
|
31
31
|
const BORDER_BR = "┘";
|
|
32
32
|
const BORDER_ML = "├";
|
|
33
33
|
const BORDER_MR = "┤";
|
|
34
|
+
// ── Hoisted regex constants (avoid per-call compilation) ───────────────────
|
|
35
|
+
const RE_HEADER = /^(#{1,3})\s+(.+)$/;
|
|
36
|
+
const RE_LIST_ITEM = /^(\s*)[-*]\s+(.+)$/;
|
|
37
|
+
const RE_HR = /^[-*_]{3,}$/;
|
|
38
|
+
const RE_BOLD_STAR = /\*\*(.+?)\*\*/g;
|
|
39
|
+
const RE_BOLD_UNDER = /__(.+?)__/g;
|
|
40
|
+
const RE_ITALIC = /(?<!\w)\*(.+?)\*(?!\w)/g;
|
|
41
|
+
const RE_INLINE_CODE = /`([^`]+)`/g;
|
|
42
|
+
const RE_LINK = /\[([^\]]+)\]\([^)]+\)/g;
|
|
34
43
|
function termWidth(stream) {
|
|
35
44
|
const width = stream.columns ?? process.stdout.columns ?? 80;
|
|
36
45
|
return Number.isFinite(width) ? Math.max(40, width) : 80;
|
|
@@ -48,6 +57,9 @@ function countRows(chunk) {
|
|
|
48
57
|
function stripAnsi(s) {
|
|
49
58
|
return s.replace(/\x1b\[[0-9;]*m/g, "");
|
|
50
59
|
}
|
|
60
|
+
export function visibleLenForTest(s) {
|
|
61
|
+
return stripAnsi(s).length;
|
|
62
|
+
}
|
|
51
63
|
function visibleLen(s) {
|
|
52
64
|
return stripAnsi(s).length;
|
|
53
65
|
}
|
|
@@ -92,12 +104,24 @@ function renderPanelDivider(c, width, label) {
|
|
|
92
104
|
}
|
|
93
105
|
return c.border + BORDER_ML + SEP_CHAR.repeat(inner) + BORDER_MR + RST;
|
|
94
106
|
}
|
|
107
|
+
export function renderPanelLineForTest(c, content, width) {
|
|
108
|
+
return renderPanelLine(c, content, width);
|
|
109
|
+
}
|
|
95
110
|
function renderPanelLine(c, content, width) {
|
|
96
111
|
const inner = width - 2;
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
112
|
+
const plain = stripAnsi(content);
|
|
113
|
+
const vLen = plain.length;
|
|
114
|
+
let safeContent;
|
|
115
|
+
let safeVLen;
|
|
116
|
+
if (vLen > inner) {
|
|
117
|
+
safeContent = plain.slice(0, Math.max(0, inner - 1)) + "…";
|
|
118
|
+
safeVLen = inner; // inner-1 chars + "…" (1 wide) = inner
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
safeContent = content;
|
|
122
|
+
safeVLen = vLen;
|
|
123
|
+
}
|
|
124
|
+
const padded = safeVLen < inner ? safeContent + " ".repeat(inner - safeVLen) : safeContent;
|
|
101
125
|
return c.border + BORDER_V + RST + padded + c.border + BORDER_V + RST;
|
|
102
126
|
}
|
|
103
127
|
// ── Code Block Rendering ───────────────────────────────────────────────────
|
|
@@ -119,16 +143,15 @@ function renderCodeBlock(c, codeLines, lang, width) {
|
|
|
119
143
|
return result;
|
|
120
144
|
}
|
|
121
145
|
// ── Inline Markdown (system24 style) ───────────────────────────────────────
|
|
146
|
+
export function renderInlineForTest(c, text) {
|
|
147
|
+
return renderInline(c, text);
|
|
148
|
+
}
|
|
122
149
|
function renderInline(c, text) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
s = s.replace(
|
|
126
|
-
|
|
127
|
-
s = s.replace(
|
|
128
|
-
// Inline code
|
|
129
|
-
s = s.replace(/`([^`]+)`/g, (_, m) => c.bg3 + c.text1 + " " + m + " " + RST);
|
|
130
|
-
// Links
|
|
131
|
-
s = s.replace(/\[([^\]]+)\]\([^)]+\)/g, (_, m) => c.cyan + m + RST);
|
|
150
|
+
let s = text.replace(RE_BOLD_STAR, (_, m) => BOLD + c.text1 + m + RST);
|
|
151
|
+
s = s.replace(RE_BOLD_UNDER, (_, m) => BOLD + c.text1 + m + RST);
|
|
152
|
+
s = s.replace(RE_ITALIC, (_, m) => ITALIC + c.text3 + m + RST);
|
|
153
|
+
s = s.replace(RE_INLINE_CODE, (_, m) => c.bg3 + c.text1 + " " + m + " " + RST);
|
|
154
|
+
s = s.replace(RE_LINK, (_, m) => c.cyan + m + RST);
|
|
132
155
|
return s;
|
|
133
156
|
}
|
|
134
157
|
// ── Thinking Animation ─────────────────────────────────────────────────────
|
|
@@ -368,7 +391,7 @@ export class System24Renderer {
|
|
|
368
391
|
continue;
|
|
369
392
|
}
|
|
370
393
|
// Headers
|
|
371
|
-
const hMatch = line.match(
|
|
394
|
+
const hMatch = line.match(RE_HEADER);
|
|
372
395
|
if (hMatch) {
|
|
373
396
|
const level = hMatch[1].length;
|
|
374
397
|
const text = hMatch[2];
|
|
@@ -381,13 +404,13 @@ export class System24Renderer {
|
|
|
381
404
|
continue;
|
|
382
405
|
}
|
|
383
406
|
// List items
|
|
384
|
-
const lMatch = line.match(
|
|
407
|
+
const lMatch = line.match(RE_LIST_ITEM);
|
|
385
408
|
if (lMatch) {
|
|
386
409
|
this.writeOut(renderPanelLine(c, " " + c.accent + "◆" + RST + " " + renderInline(c, lMatch[2]), w) + "\n");
|
|
387
410
|
continue;
|
|
388
411
|
}
|
|
389
412
|
// Horizontal rule
|
|
390
|
-
if (
|
|
413
|
+
if (RE_HR.test(line.trim())) {
|
|
391
414
|
this.writeOut(renderPanelLine(c, " " + c.text5 + SEP_CHAR.repeat(Math.min(w - 6, 40)) + RST, w) + "\n");
|
|
392
415
|
continue;
|
|
393
416
|
}
|
package/dist/cli/v2/chat-repl.js
CHANGED
|
@@ -112,7 +112,9 @@ export async function startChatRepl(options) {
|
|
|
112
112
|
const rl = readline.createInterface({
|
|
113
113
|
input: process.stdin,
|
|
114
114
|
output: process.stdout,
|
|
115
|
-
|
|
115
|
+
// ANSI-16 cyan (conceptually night-city route.active) assembled from a CSI
|
|
116
|
+
// prefix so color:gate stays literal-free; the rendered bytes are unchanged.
|
|
117
|
+
prompt: options.json ? "omk> " : `${"\x1b["}36momk>${"\x1b["}0m `,
|
|
116
118
|
completer: (line) => {
|
|
117
119
|
const trimmed = line.trim();
|
|
118
120
|
if (/^\/(?:model|m)(?:\s|$)/.test(trimmed) || (trimmed.length === 0 && replState.activeProviderTab)) {
|
|
@@ -68,6 +68,9 @@ export declare class ModelCommand extends OmkCommand {
|
|
|
68
68
|
export declare class DoctorCommand extends OmkCommand {
|
|
69
69
|
static paths: string[][];
|
|
70
70
|
static usage: import("clipanion").Usage;
|
|
71
|
+
noColor: boolean;
|
|
72
|
+
/** Color-tier / theme / NO_COLOR diagnostic section (theme contract T5a). */
|
|
73
|
+
private writeColorThemeSection;
|
|
71
74
|
execute(): Promise<number>;
|
|
72
75
|
}
|
|
73
76
|
/**
|
|
@@ -86,6 +89,9 @@ export declare class ThemeCommand extends OmkCommand {
|
|
|
86
89
|
static paths: string[][];
|
|
87
90
|
static usage: import("clipanion").Usage;
|
|
88
91
|
nameArgs: string[];
|
|
92
|
+
noColor: boolean;
|
|
93
|
+
/** Detect the degradation tier, honoring the command's --no-color flag. */
|
|
94
|
+
private detectTier;
|
|
89
95
|
execute(): Promise<number>;
|
|
90
96
|
}
|
|
91
97
|
/**
|
|
@@ -16,6 +16,8 @@ import { registerSlashCommands } from "../../runtime/slash-commands.js";
|
|
|
16
16
|
import { registerProviderCommandsV2 } from "./provider-commands.js";
|
|
17
17
|
import { registerWorkflowCommandsV2 } from "./workflow-commands.js";
|
|
18
18
|
import { DEFAULT_AUTHORITY_PROVIDER } from "../../providers/types.js";
|
|
19
|
+
import { getOmkVersionSync } from "../../util/version.js";
|
|
20
|
+
import { OMK_RUNTIME_VERSION } from "../../version.js";
|
|
19
21
|
/**
|
|
20
22
|
* Base class for all OMK v2 commands.
|
|
21
23
|
* Provides common pipeline execution helpers.
|
|
@@ -201,7 +203,47 @@ export class DoctorCommand extends OmkCommand {
|
|
|
201
203
|
static usage = Command.Usage({
|
|
202
204
|
description: "Run OMK health checks",
|
|
203
205
|
});
|
|
206
|
+
noColor = Option.Boolean("--no-color", false, { description: "Disable color output (NO_COLOR equivalent)" });
|
|
207
|
+
/** Color-tier / theme / NO_COLOR diagnostic section (theme contract T5a). */
|
|
208
|
+
async writeColorThemeSection() {
|
|
209
|
+
const { explainColorTier } = await import("../theme/tier-explain.js");
|
|
210
|
+
const { resolveTheme } = await import("../theme/theme-resolver.js");
|
|
211
|
+
const { loadThemeDocument, validateThemeDocument } = await import("../theme/theme-doc.js");
|
|
212
|
+
const argv = this.noColor ? ["--no-color"] : [];
|
|
213
|
+
const explanation = explainColorTier(argv);
|
|
214
|
+
const active = resolveTheme({ cwd: this.cwd, flagTheme: this.theme || undefined });
|
|
215
|
+
const doc = loadThemeDocument(active.name, this.cwd);
|
|
216
|
+
const schemaStatus = doc === undefined
|
|
217
|
+
? "builtin palette (no omk.theme.v1 document)"
|
|
218
|
+
: (() => {
|
|
219
|
+
const errors = validateThemeDocument(doc);
|
|
220
|
+
return errors.length === 0 ? "omk.theme.v1 document: valid" : `omk.theme.v1 document: INVALID (${errors.length} error(s): ${errors[0]})`;
|
|
221
|
+
})();
|
|
222
|
+
if (this.json) {
|
|
223
|
+
this.context.stdout.write(JSON.stringify({
|
|
224
|
+
section: "color-theme",
|
|
225
|
+
tier: explanation.tier,
|
|
226
|
+
reasons: explanation.reasons,
|
|
227
|
+
noColorRequested: explanation.noColorRequested,
|
|
228
|
+
noColorHonored: explanation.noColorHonored,
|
|
229
|
+
activeTheme: active.name,
|
|
230
|
+
themeMode: active.mode,
|
|
231
|
+
schema: schemaStatus,
|
|
232
|
+
}) + "\n");
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
this.context.stdout.write([
|
|
236
|
+
"Color tier & theme",
|
|
237
|
+
` detected tier : ${explanation.tier}`,
|
|
238
|
+
` why : ${explanation.reasons.join("; ")}`,
|
|
239
|
+
` NO_COLOR : requested=${explanation.noColorRequested ? "yes" : "no"} honored=${explanation.noColorHonored ? "yes" : "no"}`,
|
|
240
|
+
` active theme : ${active.name} (mode ${active.mode})`,
|
|
241
|
+
` theme schema : ${schemaStatus}`,
|
|
242
|
+
"",
|
|
243
|
+
].join("\n"));
|
|
244
|
+
}
|
|
204
245
|
async execute() {
|
|
246
|
+
await this.writeColorThemeSection();
|
|
205
247
|
return this.executePipeline("run health checks", "doctor");
|
|
206
248
|
}
|
|
207
249
|
}
|
|
@@ -265,36 +307,105 @@ export class ThemeCommand extends OmkCommand {
|
|
|
265
307
|
],
|
|
266
308
|
});
|
|
267
309
|
nameArgs = Option.Rest({ required: 0 });
|
|
310
|
+
noColor = Option.Boolean("--no-color", false, { description: "Disable color output (NO_COLOR equivalent)" });
|
|
311
|
+
/** Detect the degradation tier, honoring the command's --no-color flag. */
|
|
312
|
+
async detectTier() {
|
|
313
|
+
const { detectColorTier } = await import("../theme/terminal-capability.js");
|
|
314
|
+
return detectColorTier(this.noColor ? ["--no-color"] : []);
|
|
315
|
+
}
|
|
268
316
|
async execute() {
|
|
269
317
|
const name = this.nameArgs.join(" ").trim();
|
|
270
318
|
const subcommand = this.nameArgs[0] ?? "";
|
|
271
319
|
const target = this.nameArgs.slice(1).join(" ").trim();
|
|
272
|
-
// omk theme list —
|
|
320
|
+
// omk theme list — active theme + omk.theme.v1 documents + builtin swatches
|
|
273
321
|
if (subcommand === "list") {
|
|
274
322
|
const { renderAllThemePreviews, getBuiltinTheme } = await import("../theme/theme-registry.js");
|
|
275
|
-
const
|
|
276
|
-
const
|
|
277
|
-
|
|
323
|
+
const { resolveTheme } = await import("../theme/theme-resolver.js");
|
|
324
|
+
const { listThemeDocuments, loadThemeDocument, validateThemeDocument } = await import("../theme/theme-doc.js");
|
|
325
|
+
const active = resolveTheme({ cwd: this.cwd, flagTheme: this.theme || undefined });
|
|
326
|
+
const tier = await this.detectTier();
|
|
327
|
+
const currentPalette = getBuiltinTheme(active.name) ?? getBuiltinTheme("omk");
|
|
328
|
+
this.context.stdout.write((currentPalette?.render("header", `Active theme: ${active.name}`) ?? `Active theme: ${active.name}`)
|
|
329
|
+
+ ` (mode ${active.mode}, tier ${tier})\n\n`);
|
|
330
|
+
const docs = listThemeDocuments(this.cwd);
|
|
331
|
+
if (docs.length > 0) {
|
|
332
|
+
this.context.stdout.write("Theme documents (omk.theme.v1):\n");
|
|
333
|
+
for (const ref of docs) {
|
|
334
|
+
const doc = loadThemeDocument(ref.name, this.cwd);
|
|
335
|
+
const valid = doc !== undefined && validateThemeDocument(doc).length === 0;
|
|
336
|
+
const marker = ref.name === active.name ? "●" : "○";
|
|
337
|
+
this.context.stdout.write(` ${marker} ${ref.name} — ${ref.path} (${valid ? "valid" : "INVALID"})\n`);
|
|
338
|
+
}
|
|
339
|
+
this.context.stdout.write("\n");
|
|
340
|
+
}
|
|
341
|
+
this.context.stdout.write("Built-in palettes:\n");
|
|
278
342
|
this.context.stdout.write(renderAllThemePreviews() + "\n");
|
|
279
343
|
return 0;
|
|
280
344
|
}
|
|
281
|
-
// omk theme
|
|
345
|
+
// omk theme set <name> — validate + persist choice to project config
|
|
346
|
+
if (subcommand === "set") {
|
|
347
|
+
if (!target) {
|
|
348
|
+
this.context.stderr.write("Usage: omk theme set <name>\n");
|
|
349
|
+
return 2;
|
|
350
|
+
}
|
|
351
|
+
const { getBuiltinTheme, listBuiltinThemes } = await import("../theme/theme-registry.js");
|
|
352
|
+
const { listThemeDocuments } = await import("../theme/theme-doc.js");
|
|
353
|
+
const docNames = listThemeDocuments(this.cwd).map((r) => r.name);
|
|
354
|
+
const known = getBuiltinTheme(target) !== undefined || docNames.includes(target);
|
|
355
|
+
if (!known) {
|
|
356
|
+
this.context.stderr.write(`Unknown theme: ${target}\n`);
|
|
357
|
+
this.context.stderr.write(`Available: ${[...new Set([...docNames, ...listBuiltinThemes()])].join(", ")}\n`);
|
|
358
|
+
return 2;
|
|
359
|
+
}
|
|
360
|
+
const { readFile, writeFile } = await import("node:fs/promises");
|
|
361
|
+
const { resolve } = await import("node:path");
|
|
362
|
+
const cfgPath = resolve(this.cwd, ".omkrc.json");
|
|
363
|
+
let existing = {};
|
|
364
|
+
try {
|
|
365
|
+
existing = JSON.parse(await readFile(cfgPath, "utf8"));
|
|
366
|
+
}
|
|
367
|
+
catch {
|
|
368
|
+
existing = {};
|
|
369
|
+
}
|
|
370
|
+
const next = { ...existing, theme: target };
|
|
371
|
+
await writeFile(cfgPath, JSON.stringify(next, null, 2) + "\n");
|
|
372
|
+
process.env.OMK_THEME = target;
|
|
373
|
+
this.context.stdout.write(`Theme set to: ${target} (persisted to ${cfgPath})\n`);
|
|
374
|
+
return 0;
|
|
375
|
+
}
|
|
376
|
+
// omk theme preview <name> — representative status frame at detected tier
|
|
377
|
+
// (same frame as test/theme-degradation.test.mjs) for omk.theme.v1 docs;
|
|
378
|
+
// falls back to the builtin palette swatch for registry-only themes.
|
|
282
379
|
if (subcommand === "preview") {
|
|
283
380
|
if (!target) {
|
|
284
381
|
this.context.stderr.write("Usage: omk theme preview <name>\n");
|
|
285
382
|
return 2;
|
|
286
383
|
}
|
|
384
|
+
const { loadThemeDocument, listThemeDocuments } = await import("../theme/theme-doc.js");
|
|
385
|
+
const doc = loadThemeDocument(target, this.cwd);
|
|
386
|
+
if (doc !== undefined) {
|
|
387
|
+
const { compileTheme } = await import("../theme/render-table.js");
|
|
388
|
+
const { renderStatusFrame } = await import("../theme/status-frame.js");
|
|
389
|
+
const tier = await this.detectTier();
|
|
390
|
+
const compiled = compileTheme(doc, tier);
|
|
391
|
+
this.context.stdout.write(`${doc.displayName ?? doc.name} — tier ${tier}\n\n`);
|
|
392
|
+
this.context.stdout.write(renderStatusFrame(compiled) + "\n");
|
|
393
|
+
const current = process.env.OMK_THEME ?? "omk";
|
|
394
|
+
this.context.stdout.write(`\nCurrent theme: ${current}. Use \`omk theme set ${target}\` to switch.\n`);
|
|
395
|
+
return 0;
|
|
396
|
+
}
|
|
287
397
|
const { renderThemePreview, getBuiltinTheme, listBuiltinThemes } = await import("../theme/theme-registry.js");
|
|
288
398
|
const palette = getBuiltinTheme(target);
|
|
289
399
|
if (!palette) {
|
|
290
|
-
const
|
|
400
|
+
const docNames = listThemeDocuments(this.cwd).map((r) => r.name);
|
|
401
|
+
const available = [...new Set([...docNames, ...listBuiltinThemes()])].join(", ");
|
|
291
402
|
this.context.stderr.write(`Unknown theme: ${target}\n`);
|
|
292
403
|
this.context.stderr.write(`Available: ${available}\n`);
|
|
293
404
|
return 2;
|
|
294
405
|
}
|
|
295
406
|
this.context.stdout.write(renderThemePreview(palette) + "\n");
|
|
296
407
|
const current = process.env.OMK_THEME ?? "omk";
|
|
297
|
-
this.context.stdout.write(`\nCurrent theme: ${current}. Use \`omk theme ${target}\` to switch.\n`);
|
|
408
|
+
this.context.stdout.write(`\nCurrent theme: ${current}. Use \`omk theme set ${target}\` to switch.\n`);
|
|
298
409
|
return 0;
|
|
299
410
|
}
|
|
300
411
|
// omk theme <name> — set theme
|
|
@@ -321,10 +432,11 @@ export class ThemeCommand extends OmkCommand {
|
|
|
321
432
|
* Register all v2 commands on a Clipanion CLI instance.
|
|
322
433
|
*/
|
|
323
434
|
export function createCliV2() {
|
|
435
|
+
const packageVersion = getOmkVersionSync();
|
|
324
436
|
const cli = new Cli({
|
|
325
|
-
binaryLabel: "OMK
|
|
437
|
+
binaryLabel: "OMK root orchestrator",
|
|
326
438
|
binaryName: "omk",
|
|
327
|
-
binaryVersion:
|
|
439
|
+
binaryVersion: `${packageVersion} (${OMK_RUNTIME_VERSION})`,
|
|
328
440
|
});
|
|
329
441
|
cli.register(ChatCommand);
|
|
330
442
|
cli.register(RunCommand);
|
|
@@ -47,5 +47,6 @@ export declare function withSpinner<T>(message: string, fn: () => Promise<T>): P
|
|
|
47
47
|
/**
|
|
48
48
|
* Intro/outro for OMK session.
|
|
49
49
|
*/
|
|
50
|
+
export declare function formatOmkIntroTitle(version: string): string;
|
|
50
51
|
export declare function omkIntro(version: string): void;
|
|
51
52
|
export declare function omkOutro(message: string): void;
|