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
|
@@ -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
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
[
|
|
101
|
-
[
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
]
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
]
|
|
111
|
-
|
|
112
|
-
|
|
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
|
|
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({
|
|
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
|
|
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 {};
|