open-multi-agent-kit 0.78.6 → 0.78.8

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 (170) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +38 -0
  3. package/MATURITY.md +2 -2
  4. package/README.md +19 -4
  5. package/dist/brand/night-city.theme.json +80 -0
  6. package/dist/brand/palette.d.ts +73 -177
  7. package/dist/brand/palette.js +115 -39
  8. package/dist/brand/rust-forge.theme.json +216 -0
  9. package/dist/brand/theme-compiled.d.ts +61 -0
  10. package/dist/brand/theme-compiled.js +241 -0
  11. package/dist/brand/theme.js +50 -37
  12. package/dist/cli/release-promotion-gate.d.ts +8 -1
  13. package/dist/cli/release-promotion-gate.js +20 -9
  14. package/dist/cli/root.d.ts +1 -0
  15. package/dist/cli/root.js +2 -1
  16. package/dist/cli/theme/index.d.ts +11 -2
  17. package/dist/cli/theme/index.js +6 -1
  18. package/dist/cli/theme/oklab-quantize.d.ts +29 -0
  19. package/dist/cli/theme/oklab-quantize.js +105 -0
  20. package/dist/cli/theme/render-table.d.ts +59 -0
  21. package/dist/cli/theme/render-table.js +112 -0
  22. package/dist/cli/theme/status-frame.d.ts +10 -0
  23. package/dist/cli/theme/status-frame.js +22 -0
  24. package/dist/cli/theme/terminal-capability.d.ts +6 -1
  25. package/dist/cli/theme/terminal-capability.js +20 -4
  26. package/dist/cli/theme/theme-doc.d.ts +22 -0
  27. package/dist/cli/theme/theme-doc.js +97 -0
  28. package/dist/cli/theme/theme-registry.js +39 -18
  29. package/dist/cli/theme/tier-explain.d.ts +21 -0
  30. package/dist/cli/theme/tier-explain.js +60 -0
  31. package/dist/cli/ui/green-rain-renderer.js +3 -2
  32. package/dist/cli/ui/neon-grid-renderer.js +4 -3
  33. package/dist/cli/ui/rust-forge-renderer.js +17 -3
  34. package/dist/cli/ui/system24-renderer.d.ts +18 -1
  35. package/dist/cli/ui/system24-renderer.js +39 -16
  36. package/dist/cli/v2/chat-repl.js +3 -1
  37. package/dist/cli/v2/cli-v2-skeleton.d.ts +6 -0
  38. package/dist/cli/v2/cli-v2-skeleton.js +121 -9
  39. package/dist/cli/v2/interactive-prompt.d.ts +1 -0
  40. package/dist/cli/v2/interactive-prompt.js +6 -2
  41. package/dist/commands/chat/core.js +2 -2
  42. package/dist/commands/chat/runtime.js +2 -0
  43. package/dist/commands/chat/utils.js +12 -4
  44. package/dist/commands/cockpit/render.js +102 -64
  45. package/dist/commands/cockpit/utils.d.ts +2 -0
  46. package/dist/commands/design.js +18 -16
  47. package/dist/commands/doctor/checks.d.ts +0 -1
  48. package/dist/commands/doctor/checks.js +1 -36
  49. package/dist/commands/doctor/report.js +0 -11
  50. package/dist/commands/doctor/utils.js +2 -2
  51. package/dist/commands/init/content.d.ts +1 -1
  52. package/dist/commands/init/content.js +3 -11
  53. package/dist/commands/init.js +2 -2
  54. package/dist/commands/mcp/config.d.ts +32 -0
  55. package/dist/commands/mcp/config.js +264 -0
  56. package/dist/commands/mcp/doctor-fix.d.ts +12 -0
  57. package/dist/commands/mcp/doctor-fix.js +261 -0
  58. package/dist/commands/mcp/doctor.d.ts +55 -0
  59. package/dist/commands/mcp/doctor.js +401 -0
  60. package/dist/commands/mcp/list.d.ts +1 -0
  61. package/dist/commands/mcp/list.js +56 -0
  62. package/dist/commands/mcp/shared.d.ts +47 -0
  63. package/dist/commands/mcp/shared.js +192 -0
  64. package/dist/commands/mcp/test.d.ts +5 -0
  65. package/dist/commands/mcp/test.js +457 -0
  66. package/dist/commands/mcp.d.ts +8 -104
  67. package/dist/commands/mcp.js +5 -1603
  68. package/dist/contracts/proof.d.ts +1 -1
  69. package/dist/goal/control-loop.d.ts +15 -0
  70. package/dist/goal/control-loop.js +39 -5
  71. package/dist/hud/render.d.ts +2 -0
  72. package/dist/hud/render.js +7 -1
  73. package/dist/mcp/secret-scanner.d.ts +6 -0
  74. package/dist/mcp/secret-scanner.js +44 -11
  75. package/dist/memory/graph-delta-log.d.ts +137 -0
  76. package/dist/memory/graph-delta-log.js +650 -0
  77. package/dist/memory/graph-viewer.js +13 -32
  78. package/dist/memory/local-graph-memory-store.d.ts +36 -3
  79. package/dist/memory/local-graph-memory-store.js +255 -10
  80. package/dist/orchestration/log-streamer.js +13 -8
  81. package/dist/orchestration/routing.d.ts +4 -0
  82. package/dist/orchestration/routing.js +28 -3
  83. package/dist/orchestration/state-persister.js +8 -1
  84. package/dist/providers/anthropic-messages-runner.d.ts +17 -0
  85. package/dist/providers/anthropic-messages-runner.js +197 -0
  86. package/dist/providers/model-registry.d.ts +1 -1
  87. package/dist/providers/model-registry.js +37 -3
  88. package/dist/providers/provider-runtime.js +27 -11
  89. package/dist/providers/thinking-levels.js +4 -1
  90. package/dist/providers/types.d.ts +3 -3
  91. package/dist/runtime/contracts/weakness-remediation.d.ts +9 -1
  92. package/dist/runtime/contracts/weakness-remediation.js +9 -1
  93. package/dist/runtime/router-v2-scoring.d.ts +8 -3
  94. package/dist/runtime/router-v2-scoring.js +27 -22
  95. package/dist/runtime/runtime-router.d.ts +5 -0
  96. package/dist/runtime/runtime-router.js +40 -8
  97. package/dist/runtime/sandbox-profile.d.ts +29 -0
  98. package/dist/runtime/sandbox-profile.js +101 -0
  99. package/dist/runtime/slash-commands.js +300 -2
  100. package/dist/runtime/tool-dispatch-contracts.d.ts +15 -0
  101. package/dist/runtime/tool-dispatch-contracts.js +12 -0
  102. package/dist/runtime/weights-config.d.ts +90 -0
  103. package/dist/runtime/weights-config.js +249 -0
  104. package/dist/schema/envelope.schema.d.ts +18 -18
  105. package/dist/schema/evidence.schema.d.ts +2 -2
  106. package/dist/schema/proof-bundle.schema.d.ts +6 -6
  107. package/dist/schema/proof-bundle.schema.js +0 -1
  108. package/dist/schema/provider.schema.d.ts +2 -2
  109. package/dist/schema/run-manifest.schema.d.ts +16 -16
  110. package/dist/theme/ansi.js +9 -2
  111. package/dist/theme/extended-palette.d.ts +85 -0
  112. package/dist/theme/extended-palette.js +108 -0
  113. package/dist/theme/layout.js +29 -8
  114. package/dist/theme/metrics.js +5 -5
  115. package/dist/theme/parallel.js +25 -15
  116. package/dist/ui/omk-sigil.js +5 -14
  117. package/dist/ui/omk-working-sweep.js +5 -15
  118. package/dist/util/chat-agent-mode.d.ts +11 -0
  119. package/dist/util/chat-agent-mode.js +41 -8
  120. package/dist/util/chat-cockpit.d.ts +9 -0
  121. package/dist/util/chat-cockpit.js +77 -20
  122. package/dist/util/fs/core.d.ts +5 -0
  123. package/dist/util/fs/core.js +35 -0
  124. package/dist/util/fs/internal.d.ts +14 -0
  125. package/dist/util/fs/internal.js +169 -0
  126. package/dist/util/fs/kimi-sync.d.ts +41 -0
  127. package/dist/util/fs/kimi-sync.js +495 -0
  128. package/dist/util/fs/logo.d.ts +2 -0
  129. package/dist/util/fs/logo.js +78 -0
  130. package/dist/util/fs/manifest.d.ts +6 -0
  131. package/dist/util/fs/manifest.js +40 -0
  132. package/dist/util/fs/mcp-diagnose.d.ts +15 -0
  133. package/dist/util/fs/mcp-diagnose.js +204 -0
  134. package/dist/util/fs/mcp-runtime-config.d.ts +23 -0
  135. package/dist/util/fs/mcp-runtime-config.js +412 -0
  136. package/dist/util/fs/paths.d.ts +13 -0
  137. package/dist/util/fs/paths.js +82 -0
  138. package/dist/util/fs/preflight.d.ts +27 -0
  139. package/dist/util/fs/preflight.js +271 -0
  140. package/dist/util/fs.d.ts +8 -128
  141. package/dist/util/fs.js +8 -1757
  142. package/dist/util/terminal-layout.js +5 -1
  143. package/dist/util/version.js +2 -1
  144. package/docs/2026-06-11/critical-issues.md +20 -0
  145. package/docs/2026-06-11/improvements.md +14 -0
  146. package/docs/2026-06-11/init-checklist.md +25 -0
  147. package/docs/2026-06-11/plan.md +20 -0
  148. package/docs/ARCHITECTURE_ANALYSIS_CODEGRAPH.md +223 -0
  149. package/docs/adr/0001-no-native-rust-lane.md +52 -0
  150. package/docs/codex-oauth-setup.md +14 -0
  151. package/docs/decisions/2026-06-10-git-history-bloat.md +61 -0
  152. package/docs/decisions/ADR-theme-dark-only-assets.md +43 -0
  153. package/docs/getting-started.md +1 -1
  154. package/docs/headroom-omk-final-summary.md +188 -0
  155. package/docs/headroom-omk-integration.md +394 -0
  156. package/docs/headroom-omk-setup-guide.md +422 -0
  157. package/docs/headroom-omk-usage-examples.md +371 -0
  158. package/docs/provider-maturity.md +1 -1
  159. package/docs/versioning.md +3 -3
  160. package/package.json +10 -10
  161. package/readmeasset/.npmignore +2 -0
  162. package/readmeasset/ASSET_INDEX.md +7 -5
  163. package/readmeasset/ASSET_PROVENANCE.md +21 -5
  164. package/readmeasset/omk-control-surfaces.svg +55 -0
  165. package/readmeasset/omk-core-loop.svg +1 -0
  166. package/readmeasset/omk-logo-mark.svg +1 -0
  167. package/readmeasset/omk-release-assertions.svg +51 -0
  168. package/dist/native/linux-x64/omk-safety +0 -0
  169. package/dist/util/native-safety.d.ts +0 -28
  170. package/dist/util/native-safety.js +0 -118
@@ -1,6 +1,8 @@
1
1
  import { resolve, join } from "path";
2
2
  import { mkdir, writeFile } from "fs/promises";
3
3
  import { runShell } from "./shell.js";
4
+ import { BRAND_HEX, setBrandPaletteTheme } from "../brand/palette.js";
5
+ import { getActiveBrandChromeLabel } from "../brand/theme-compiled.js";
4
6
  import { getProjectRoot, getRunPath, pathExists } from "./fs.js";
5
7
  import { writeSessionMeta } from "./session.js";
6
8
  import { writeTodos } from "./todo-sync.js";
@@ -83,8 +85,46 @@ function parseCockpitHeight(value) {
83
85
  return undefined;
84
86
  return Math.min(MAX_CHAT_COCKPIT_HEIGHT, Math.max(MIN_CHAT_COCKPIT_HEIGHT, parsed));
85
87
  }
88
+ function normalizeBrandChromeTheme(value) {
89
+ const normalized = value?.trim().toLowerCase();
90
+ if (!normalized)
91
+ return undefined;
92
+ if (normalized === "rust-forge" ||
93
+ normalized === "rust" ||
94
+ normalized === "cargo" ||
95
+ normalized === "oxide" ||
96
+ normalized === "forge" ||
97
+ normalized === "oxidized-forge" ||
98
+ normalized === "oxidized" ||
99
+ normalized === "rust-native") {
100
+ return "rust-forge";
101
+ }
102
+ if (normalized === "night-city" ||
103
+ normalized === "night-city-ops" ||
104
+ normalized === "neon-grid" ||
105
+ normalized === "neon" ||
106
+ normalized === "grid" ||
107
+ normalized === "control" ||
108
+ normalized === "omk-control" ||
109
+ normalized === "metrics" ||
110
+ normalized === "metrics-control" ||
111
+ normalized === "cyberpunk") {
112
+ return "night-city";
113
+ }
114
+ return undefined;
115
+ }
116
+ export function resolveCockpitChromeTheme(options) {
117
+ // OMK_THEME is the user-selected control chrome theme. Chat `--brand omk`
118
+ // is only the left-pane skin and must not overwrite an env/project theme.
119
+ return normalizeBrandChromeTheme(options.env?.OMK_THEME)
120
+ ?? normalizeBrandChromeTheme(options.brand);
121
+ }
86
122
  export function buildRightPaneCommand(options) {
87
123
  let cmd = `${options.nodeCmd} ${options.cliCmd} cockpit --run-id ${shellQuote(options.runId)} --watch --refresh ${options.refreshMs}`;
124
+ const theme = normalizeBrandChromeTheme(options.theme);
125
+ if (theme) {
126
+ cmd = `OMK_THEME=${shellQuote(theme)} ${cmd}`;
127
+ }
88
128
  if (options.redraw && options.redraw !== "diff") {
89
129
  cmd += ` --redraw ${shellQuote(options.redraw)}`;
90
130
  }
@@ -93,29 +133,37 @@ export function buildRightPaneCommand(options) {
93
133
  }
94
134
  return cmd;
95
135
  }
96
- const TMUX_NIGHT_CITY_STATUS_LEFT = "#[fg=#00FFC2,bold] OMK//CONTROL #[fg=#758FA8]Night City";
97
- const TMUX_NIGHT_CITY_STATUS_RIGHT = "#[fg=#00D6FF]#S #[fg=#758FA8]%H:%M";
98
- const TMUX_NIGHT_CITY_SESSION_OPTIONS = [
99
- ["status", "on"],
100
- ["status-style", "bg=#070B14,fg=#E8F8FF"],
101
- ["message-style", "bg=#9D4EDD,fg=#E8F8FF,bold"],
102
- ["window-status-style", "fg=#758FA8,bg=#070B14"],
103
- ["window-status-current-style", "fg=#070B14,bg=#00FFC2,bold"],
104
- ["status-left", TMUX_NIGHT_CITY_STATUS_LEFT],
105
- ["status-right", TMUX_NIGHT_CITY_STATUS_RIGHT],
106
- ];
107
- const TMUX_NIGHT_CITY_WINDOW_OPTIONS = [
108
- ["pane-border-style", "fg=#22324A"],
109
- ["pane-active-border-style", "fg=#FF47B2"],
110
- ];
111
- async function applyTmuxNightCityTheme(session, cwd) {
112
- for (const [option, value] of TMUX_NIGHT_CITY_SESSION_OPTIONS) {
136
+ // Active brand tmux chrome. Values are built at launch time so P/BRAND_HEX
137
+ // mutations from setBrandPaletteTheme() are reflected without changing imports.
138
+ export function buildTmuxBrandChromeOptions(brand) {
139
+ setBrandPaletteTheme(brand);
140
+ const statusLeft = `#[fg=${BRAND_HEX.mint},bold] OMK//CONTROL #[fg=${BRAND_HEX.gray}]${getActiveBrandChromeLabel()}`;
141
+ const statusRight = `#[fg=${BRAND_HEX.cyan}]#S #[fg=${BRAND_HEX.gray}]%H:%M`;
142
+ return {
143
+ sessionOptions: [
144
+ ["status", "on"],
145
+ ["status-style", `bg=${BRAND_HEX.dark},fg=${BRAND_HEX.cream}`],
146
+ ["message-style", `bg=${BRAND_HEX.purple},fg=${BRAND_HEX.cream},bold`],
147
+ ["window-status-style", `fg=${BRAND_HEX.gray},bg=${BRAND_HEX.dark}`],
148
+ ["window-status-current-style", `fg=${BRAND_HEX.dark},bg=${BRAND_HEX.mint},bold`],
149
+ ["status-left", statusLeft],
150
+ ["status-right", statusRight],
151
+ ],
152
+ windowOptions: [
153
+ ["pane-border-style", `fg=${BRAND_HEX.gridLine}`],
154
+ ["pane-active-border-style", `fg=${BRAND_HEX.magenta}`],
155
+ ],
156
+ };
157
+ }
158
+ async function applyTmuxBrandTheme(session, cwd, brand) {
159
+ const chrome = buildTmuxBrandChromeOptions(brand);
160
+ for (const [option, value] of chrome.sessionOptions) {
113
161
  const result = await runShell("tmux", ["set-option", "-t", session, option, value], { cwd, timeout: 5000 });
114
162
  if (result.failed) {
115
163
  console.warn(`Failed to set tmux ${option}: ${result.stderr || result.stdout}`);
116
164
  }
117
165
  }
118
- for (const [option, value] of TMUX_NIGHT_CITY_WINDOW_OPTIONS) {
166
+ for (const [option, value] of chrome.windowOptions) {
119
167
  const result = await runShell("tmux", ["set-window-option", "-t", `${session}:chat`, option, value], { cwd, timeout: 5000 });
120
168
  if (result.failed) {
121
169
  console.warn(`Failed to set tmux ${option}: ${result.stderr || result.stdout}`);
@@ -183,10 +231,19 @@ export async function launchChatCockpit(options = {}) {
183
231
  const hasRoomForHistoryPane = history === "watch" &&
184
232
  terminalWidth >= 80 &&
185
233
  terminalHeight >= MIN_CHAT_COCKPIT_HEIGHT + minHistoryPaneHeight;
234
+ const chromeTheme = resolveCockpitChromeTheme({ brand, env: process.env });
186
235
  const leftCmd = buildLeftPaneCommand({ nodeCmd, cliCmd, runId, brand, agentFile: options.agentFile, workers: options.workers, maxStepsPerTurn: options.maxStepsPerTurn, mcpScope: options.mcpScope, provider: options.provider, model: options.model, execution: options.execution, ui: options.ui });
187
236
  // When no explicit --cockpit-height is provided, pass undefined so the child
188
237
  // measures its actual tmux pane after splits/resizes and keeps the right rail pinned.
189
- const rightTopCmd = buildRightPaneCommand({ nodeCmd, cliCmd, runId, refreshMs, redraw, height: requestedCockpitHeight });
238
+ const rightTopCmd = buildRightPaneCommand({
239
+ nodeCmd,
240
+ cliCmd,
241
+ runId,
242
+ refreshMs,
243
+ redraw,
244
+ height: requestedCockpitHeight,
245
+ theme: chromeTheme,
246
+ });
190
247
  const rightBottomCmd = `${nodeCmd} ${cliCmd} runs --watch --limit 15 --refresh 5000`;
191
248
  // 3. Create detached tmux session with left-pane command already running
192
249
  const createResult = await runShell("tmux", ["new-session", "-d", "-s", session, "-n", "chat", "-e", "OMK_CHAT_COCKPIT_CHILD=1", leftCmd], { cwd, timeout: 10000 });
@@ -247,7 +304,7 @@ export async function launchChatCockpit(options = {}) {
247
304
  if (historyResult.failed) {
248
305
  console.warn(`Failed to set tmux history limit: ${historyResult.stderr || historyResult.stdout}`);
249
306
  }
250
- await applyTmuxNightCityTheme(session, cwd);
307
+ await applyTmuxBrandTheme(session, cwd, chromeTheme);
251
308
  // 8. Set a hook so the session is destroyed when the chat pane dies
252
309
  const hookResult = await runShell("tmux", ["set-hook", "-t", leftPaneId, "pane-died", `if-shell -F '#{==:#{hook_pane},${leftPaneId}}' 'kill-session -t ${session}'`], { cwd, timeout: 5000 });
253
310
  if (hookResult.failed) {
@@ -0,0 +1,5 @@
1
+ export declare function ensureDir(path: string): Promise<void>;
2
+ export declare function writeFileSafe(path: string, content: string): Promise<void>;
3
+ export declare function pathExists(path: string): Promise<boolean>;
4
+ export declare function isDirectory(path: string): Promise<boolean>;
5
+ export declare function readTextFile(path: string, defaultValue?: string): Promise<string>;
@@ -0,0 +1,35 @@
1
+ import { mkdir, writeFile, readFile, access, constants, readdir } from "fs/promises";
2
+ import { dirname } from "path";
3
+ export async function ensureDir(path) {
4
+ await mkdir(path, { recursive: true });
5
+ }
6
+ export async function writeFileSafe(path, content) {
7
+ await ensureDir(dirname(path));
8
+ await writeFile(path, content, "utf-8");
9
+ }
10
+ export async function pathExists(path) {
11
+ try {
12
+ await access(path, constants.F_OK);
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ export async function isDirectory(path) {
20
+ try {
21
+ await readdir(path);
22
+ return true;
23
+ }
24
+ catch {
25
+ return false;
26
+ }
27
+ }
28
+ export async function readTextFile(path, defaultValue = "") {
29
+ try {
30
+ return await readFile(path, "utf-8");
31
+ }
32
+ catch {
33
+ return defaultValue;
34
+ }
35
+ }
@@ -0,0 +1,14 @@
1
+ import type { RuntimeMcpPreflightFailureReason } from "./preflight.js";
2
+ export declare function isShellInlineMcpArg(server: Record<string, unknown>, index: number): boolean;
3
+ export declare const PACKAGE_MANAGER_COMMANDS: Set<string>;
4
+ export declare const PDF_MCP_SERVER_RE: RegExp;
5
+ export declare const QUIET_PACKAGE_MANAGER_ENV: Record<string, string>;
6
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;
7
+ export declare function basenameOfRuntimeCommand(command: string): string;
8
+ export declare function runtimeShellInlineScripts(server: Record<string, unknown>): string[];
9
+ export declare function runtimeCommandText(server: Record<string, unknown>): string;
10
+ export declare function hasHttpTransportMismatch(name: string, server: Record<string, unknown>): boolean;
11
+ export declare function isPackageManagerRuntimeServer(server: Record<string, unknown>): boolean;
12
+ export declare function sanitizeRuntimeMcpPreflightText(value: string): string;
13
+ export declare function formatPreflightFailureDetail(reason: RuntimeMcpPreflightFailureReason | undefined, detail: string | undefined): string;
14
+ export declare function registerRuntimeMcpCleanupPath(runtimeConfigPath: string): void;
@@ -0,0 +1,169 @@
1
+ import { rmSync } from "fs";
2
+ export function isShellInlineMcpArg(server, index) {
3
+ const command = typeof server.command === "string" ? server.command : "";
4
+ const commandName = command.replace(/\\/g, "/").split("/").pop()?.toLowerCase() ?? command.toLowerCase();
5
+ if (!["bash", "sh", "zsh", "fish", "pwsh", "powershell", "cmd", "cmd.exe"].includes(commandName)) {
6
+ return false;
7
+ }
8
+ const args = Array.isArray(server.args) ? server.args : [];
9
+ const previous = args[index - 1];
10
+ return previous === "-c" || previous === "-lc" || previous === "/c" || previous === "--command";
11
+ }
12
+ const NODE_PACKAGE_MANAGER_COMMANDS = new Set([
13
+ "npm",
14
+ "npx",
15
+ "pnpm",
16
+ "yarn",
17
+ "bun",
18
+ "bunx",
19
+ "npm.cmd",
20
+ "npx.cmd",
21
+ "pnpm.cmd",
22
+ "yarn.cmd",
23
+ "bun.cmd",
24
+ "bunx.cmd",
25
+ "npm.exe",
26
+ "npx.exe",
27
+ "pnpm.exe",
28
+ "yarn.exe",
29
+ "bun.exe",
30
+ "bunx.exe",
31
+ ]);
32
+ const PYTHON_PACKAGE_MANAGER_COMMANDS = new Set([
33
+ "uv",
34
+ "uvx",
35
+ "pip",
36
+ "pip3",
37
+ "pipx",
38
+ "poetry",
39
+ "rye",
40
+ "uv.exe",
41
+ "uvx.exe",
42
+ "pip.exe",
43
+ "pip3.exe",
44
+ "pipx.exe",
45
+ "poetry.exe",
46
+ "rye.exe",
47
+ ]);
48
+ export const PACKAGE_MANAGER_COMMANDS = new Set([
49
+ ...NODE_PACKAGE_MANAGER_COMMANDS,
50
+ ...PYTHON_PACKAGE_MANAGER_COMMANDS,
51
+ ]);
52
+ const PYTHON_RUNTIME_COMMANDS = new Set(["python", "python3", "py", "python.exe", "python3.exe", "py.exe"]);
53
+ const INLINE_PACKAGE_MANAGER_RE = /(?:^|[\s/])(npm|npx|pnpm|yarn|bun|bunx|uv|uvx|pip|pip3|pipx|poetry|rye)(?:\.(?:cmd|exe))?(?:\s|$)/i;
54
+ const INLINE_PYTHON_PACKAGE_MANAGER_RE = /(?:^|[\s/])(?:python(?:3)?|py)(?:\.exe)?\s+-m\s+(?:pip|pip3|uv)(?:\s|$)/i;
55
+ const STDIO_INCOMPATIBLE_HTTP_MCP_COMMANDS = new Set(["page-design-guide", "mcp-pdf-server"]);
56
+ export const PDF_MCP_SERVER_RE = /(?:^|\s)(?:@modelcontextprotocol\/server-pdf|mcp-pdf-server)(?:\s|$)/i;
57
+ const EXPLICIT_STDIO_TRANSPORT_RE = /(?:^|\s)(?:--stdio|--transport(?:=|\s+)stdio)(?:\s|$)/i;
58
+ const EXPLICIT_HTTP_TRANSPORT_RE = /(?:^|\s)--transport(?:=|\s+)(?:http|sse|streamable-http)(?:\s|$)/i;
59
+ export const QUIET_PACKAGE_MANAGER_ENV = {
60
+ npm_config_loglevel: "error",
61
+ NPM_CONFIG_LOGLEVEL: "error",
62
+ npm_config_progress: "false",
63
+ NPM_CONFIG_PROGRESS: "false",
64
+ npm_config_audit: "false",
65
+ NPM_CONFIG_AUDIT: "false",
66
+ npm_config_fund: "false",
67
+ NPM_CONFIG_FUND: "false",
68
+ npm_config_prefer_offline: "true",
69
+ NPM_CONFIG_PREFER_OFFLINE: "true",
70
+ npm_config_fetch_retries: "0",
71
+ NPM_CONFIG_FETCH_RETRIES: "0",
72
+ npm_config_fetch_retry_mintimeout: "1000",
73
+ NPM_CONFIG_FETCH_RETRY_MINTIMEOUT: "1000",
74
+ npm_config_fetch_retry_maxtimeout: "1000",
75
+ NPM_CONFIG_FETCH_RETRY_MAXTIMEOUT: "1000",
76
+ npm_config_maxsockets: "3",
77
+ NPM_CONFIG_MAXSOCKETS: "3",
78
+ npm_config_update_notifier: "false",
79
+ NPM_CONFIG_UPDATE_NOTIFIER: "false",
80
+ NO_UPDATE_NOTIFIER: "1",
81
+ NODE_NO_WARNINGS: "1",
82
+ UV_NO_PROGRESS: "1",
83
+ PIP_DISABLE_PIP_VERSION_CHECK: "1",
84
+ PIP_NO_INPUT: "1",
85
+ PIP_NO_PYTHON_VERSION_WARNING: "1",
86
+ PIP_PROGRESS_BAR: "off",
87
+ };
88
+ export function isRecord(value) {
89
+ return typeof value === "object" && value !== null && !Array.isArray(value);
90
+ }
91
+ export function basenameOfRuntimeCommand(command) {
92
+ return command.replace(/\\/g, "/").split("/").pop()?.toLowerCase() ?? command.toLowerCase();
93
+ }
94
+ export function runtimeShellInlineScripts(server) {
95
+ const args = Array.isArray(server.args) ? server.args : [];
96
+ return args.filter((arg, index) => typeof arg === "string" && isShellInlineMcpArg(server, index));
97
+ }
98
+ export function runtimeCommandText(server) {
99
+ const command = typeof server.command === "string" ? server.command : "";
100
+ const args = Array.isArray(server.args)
101
+ ? server.args.filter((arg) => typeof arg === "string")
102
+ : [];
103
+ return [command, ...args, ...runtimeShellInlineScripts(server)].join(" ");
104
+ }
105
+ function hasExplicitStdioTransport(server) {
106
+ return EXPLICIT_STDIO_TRANSPORT_RE.test(runtimeCommandText(server));
107
+ }
108
+ export function hasHttpTransportMismatch(name, server) {
109
+ if (hasExplicitStdioTransport(server))
110
+ return false;
111
+ const command = typeof server.command === "string" ? basenameOfRuntimeCommand(server.command) : "";
112
+ const targetText = runtimeCommandText(server);
113
+ if (PDF_MCP_SERVER_RE.test(targetText))
114
+ return true;
115
+ if (STDIO_INCOMPATIBLE_HTTP_MCP_COMMANDS.has(command) || STDIO_INCOMPATIBLE_HTTP_MCP_COMMANDS.has(name)) {
116
+ return true;
117
+ }
118
+ return EXPLICIT_HTTP_TRANSPORT_RE.test(targetText);
119
+ }
120
+ export function isPackageManagerRuntimeServer(server) {
121
+ const command = typeof server.command === "string" ? basenameOfRuntimeCommand(server.command) : "";
122
+ if (PACKAGE_MANAGER_COMMANDS.has(command))
123
+ return true;
124
+ if (PYTHON_RUNTIME_COMMANDS.has(command)) {
125
+ const args = Array.isArray(server.args)
126
+ ? server.args.filter((arg) => typeof arg === "string")
127
+ : [];
128
+ for (let index = 0; index < args.length - 1; index += 1) {
129
+ if (args[index] === "-m" && PYTHON_PACKAGE_MANAGER_COMMANDS.has(basenameOfRuntimeCommand(args[index + 1]))) {
130
+ return true;
131
+ }
132
+ }
133
+ }
134
+ return runtimeShellInlineScripts(server).some((script) => {
135
+ const normalized = script.replace(/\\/g, "/");
136
+ return INLINE_PACKAGE_MANAGER_RE.test(normalized) || INLINE_PYTHON_PACKAGE_MANAGER_RE.test(normalized);
137
+ });
138
+ }
139
+ export function sanitizeRuntimeMcpPreflightText(value) {
140
+ return value
141
+ .replace(/(Bearer\s+)[A-Za-z0-9._~+/=-]+/gi, "$1***")
142
+ .replace(/(--(?:api-)?(?:token|key|secret|password)(?:=|\s+))[^"'`\s;]+/gi, "$1***")
143
+ .replace(/([A-Za-z_][A-Za-z0-9_]*(?:SECRET|TOKEN|KEY|PASSWORD|CREDENTIAL|AUTH)[A-Za-z0-9_]*\s*=\s*)[^"'`\s;]+/gi, "$1***")
144
+ .replace(/([?&](?:token|api[-_]?key|key|secret|password|auth|credential|session|bearer|access[-_]?token|refresh[-_]?token|client[-_]?secret|x[-_]?auth[-_]?token|signature|sig)=)[^&#\s]+/gi, "$1***");
145
+ }
146
+ export function formatPreflightFailureDetail(reason, detail) {
147
+ if (reason === "timeout")
148
+ return "timeout";
149
+ return sanitizeRuntimeMcpPreflightText(detail ?? "failed");
150
+ }
151
+ const runtimeMcpCleanupPaths = new Set();
152
+ let runtimeMcpCleanupRegistered = false;
153
+ function cleanupRuntimeMcpFiles() {
154
+ for (const path of runtimeMcpCleanupPaths) {
155
+ try {
156
+ rmSync(path, { force: true });
157
+ }
158
+ catch {
159
+ // Best-effort cleanup for a local runtime cache that may contain MCP env.
160
+ }
161
+ }
162
+ }
163
+ export function registerRuntimeMcpCleanupPath(runtimeConfigPath) {
164
+ runtimeMcpCleanupPaths.add(runtimeConfigPath);
165
+ if (!runtimeMcpCleanupRegistered) {
166
+ runtimeMcpCleanupRegistered = true;
167
+ process.once("exit", cleanupRuntimeMcpFiles);
168
+ }
169
+ }
@@ -0,0 +1,41 @@
1
+ import { SyncManifestEntry } from "../sync-manifest.js";
2
+ type KimiGlobalSyncStepName = "hooks" | "mcp" | "skills" | "memory";
3
+ export interface KimiGlobalSyncOptions {
4
+ dryRun?: boolean;
5
+ diff?: boolean;
6
+ quiet?: boolean;
7
+ manifest?: SyncManifestEntry[];
8
+ timestamp?: string;
9
+ }
10
+ export interface KimiGlobalSyncStepReport {
11
+ name: KimiGlobalSyncStepName;
12
+ changed: boolean;
13
+ blocked: boolean;
14
+ skipped: boolean;
15
+ error?: string;
16
+ manifest: SyncManifestEntry[];
17
+ }
18
+ export interface KimiGlobalSyncReport {
19
+ changed: boolean;
20
+ blocked: boolean;
21
+ steps: KimiGlobalSyncStepReport[];
22
+ actions: string[];
23
+ skipped: string[];
24
+ errors: string[];
25
+ manifest: SyncManifestEntry[];
26
+ }
27
+ /**
28
+ * .omk/kimi.config.toml 의 hooks 를 ~/.kimi/config.toml 에 병합.
29
+ * 상대 경로를 절대 경로로 변환하여 어디서 실행돼도 작동하도록 함.
30
+ */
31
+ export declare function mergeKimiHooks(omkConfigPath: string, options?: KimiGlobalSyncOptions): Promise<boolean>;
32
+ export declare function extractHooksBlocks(content: string): string;
33
+ /** 프로젝트의 .omk/mcp.json + .kimi/mcp.json → ~/.kimi/mcp.json 병합 */
34
+ export declare function syncKimiMcpGlobal(options?: KimiGlobalSyncOptions): Promise<boolean>;
35
+ /** 프로젝트의 .kimi/skills/* → ~/.kimi/skills/ 심링크 */
36
+ export declare function syncKimiSkillsGlobal(options?: KimiGlobalSyncOptions): Promise<boolean>;
37
+ /** local graph memory policy를 ~/.kimi/omk.memory.toml 에 동기화 */
38
+ export declare function syncKimiMemoryGlobal(options?: KimiGlobalSyncOptions): Promise<boolean>;
39
+ /** Sync hooks + MCP + skills to ~/.kimi/ at once */
40
+ export declare function syncAllKimiGlobals(options?: KimiGlobalSyncOptions): Promise<KimiGlobalSyncReport>;
41
+ export {};