open-multi-agent-kit 0.78.0 → 0.78.1
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/CHANGELOG.md +44 -15
- package/MATURITY.md +2 -2
- package/README.md +56 -26
- package/ROADMAP.md +36 -28
- package/dist/cli/register-basic-commands.js +3 -2
- package/dist/cli/register-mcp-dag-cron-screenshot-commands.js +2 -0
- package/dist/cli/register-tool-commands.js +11 -0
- package/dist/cli/register-workflow-commands.js +1 -0
- package/dist/cli/registry/tooling.js +3 -2
- package/dist/commands/chat/core.js +5 -0
- package/dist/commands/chat/native-root-loop.js +60 -0
- package/dist/commands/dag-from-spec.d.ts +1 -0
- package/dist/commands/dag-from-spec.js +61 -1
- package/dist/commands/graph.d.ts +62 -0
- package/dist/commands/graph.js +182 -0
- package/dist/commands/merge.d.ts +1 -0
- package/dist/commands/merge.js +88 -0
- package/dist/commands/parallel/core.js +3 -3
- package/dist/commands/provider.js +5 -3
- package/dist/commands/star.js +6 -1
- package/dist/commands/summary.d.ts +4 -1
- package/dist/commands/summary.js +103 -1
- package/dist/commands/team.d.ts +1 -0
- package/dist/commands/team.js +38 -0
- package/dist/contracts/provider-health.d.ts +42 -0
- package/dist/contracts/provider-health.js +9 -0
- package/dist/goal/intent-frame.d.ts +24 -0
- package/dist/goal/intent-frame.js +18 -0
- package/dist/memory/local-graph-memory-store.d.ts +15 -0
- package/dist/memory/local-graph-memory-store.js +176 -0
- package/dist/memory/memory-store.d.ts +18 -0
- package/dist/memory/memory-store.js +18 -0
- package/dist/orchestration/adaptorch-topology.d.ts +59 -0
- package/dist/orchestration/adaptorch-topology.js +194 -0
- package/dist/orchestration/capability-routing.d.ts +23 -0
- package/dist/orchestration/capability-routing.js +56 -0
- package/dist/orchestration/dag-compiler-types.d.ts +3 -0
- package/dist/orchestration/dag-compiler.js +14 -1
- package/dist/orchestration/parallel-orchestrator.d.ts +6 -0
- package/dist/orchestration/parallel-orchestrator.js +31 -0
- package/dist/providers/provider-health.d.ts +39 -0
- package/dist/providers/provider-health.js +161 -0
- package/dist/runtime/context-broker.d.ts +13 -4
- package/dist/runtime/context-broker.js +14 -1
- package/dist/runtime/headroom-policy.d.ts +37 -0
- package/dist/runtime/headroom-policy.js +122 -0
- package/dist/runtime/ouroboros-policy.d.ts +57 -0
- package/dist/runtime/ouroboros-policy.js +134 -0
- package/dist/runtime/runtime-backed-task-runner.js +9 -1
- package/dist/runtime/tool-dispatch-contracts.d.ts +57 -1
- package/dist/runtime/tool-dispatch-contracts.js +79 -3
- package/dist/safety/tool-authority-gate.d.ts +62 -0
- package/dist/safety/tool-authority-gate.js +108 -0
- package/dist/schema/provider.schema.d.ts +4 -4
- package/dist/util/first-run-star.d.ts +9 -0
- package/dist/util/first-run-star.js +42 -1
- package/dist/util/terminal-input.d.ts +20 -0
- package/dist/util/terminal-input.js +32 -0
- package/dist/util/update-check.d.ts +6 -1
- package/dist/util/update-check.js +35 -1
- package/docs/2026-06-08/critical-issues.md +20 -0
- package/docs/2026-06-08/improvements.md +14 -0
- package/docs/2026-06-08/init-checklist.md +25 -0
- package/docs/2026-06-08/plan.md +20 -0
- package/docs/getting-started.md +31 -3
- package/docs/integrations/ouroboros.md +96 -0
- package/docs/provider-maturity.md +1 -1
- package/docs/versioning.md +3 -3
- package/package.json +1 -1
- package/dist/native/linux-x64/omk-safety +0 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure tool-authority decision primitive.
|
|
3
|
+
*
|
|
4
|
+
* Decides allow / ask / block for a tool operation given the provider's
|
|
5
|
+
* write/shell authority, the active approval policy, the sandbox mode, and
|
|
6
|
+
* whether a TTY is attached. The function is intentionally pure: no IO, no
|
|
7
|
+
* environment reads, no secrets, no side effects.
|
|
8
|
+
*
|
|
9
|
+
* STATUS (0.78.2 stabilization): this primitive is NOT wired into any live
|
|
10
|
+
* tool-dispatch path. It exists so 0.78.3 can wire it into
|
|
11
|
+
* `dispatchToolCallsByContract` (src/runtime/tool-dispatch-contracts.ts) and
|
|
12
|
+
* the kimi runner tool loop without re-deriving the policy. Zero behavior
|
|
13
|
+
* change to current execution.
|
|
14
|
+
*
|
|
15
|
+
* Design rules (authority outranks policy; fail-closed):
|
|
16
|
+
* 1. read ops are always allowed.
|
|
17
|
+
* 2. a read-only sandbox is a hard floor: any non-read op is blocked.
|
|
18
|
+
* 3. authority must be satisfied for the op before policy is consulted:
|
|
19
|
+
* write -> writeAuthority === "full"
|
|
20
|
+
* shell -> shellAuthority === "full"
|
|
21
|
+
* merge -> writeAuthority === "full" AND shellAuthority === "full"
|
|
22
|
+
* 4. once authority is satisfied, the approval policy decides:
|
|
23
|
+
* block -> block
|
|
24
|
+
* yolo -> allow
|
|
25
|
+
* auto -> allow
|
|
26
|
+
* interactive -> ask when a TTY is present, otherwise block
|
|
27
|
+
* (ask in a non-TTY context = deny-by-default).
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Map a raw tool name to its coarse {@link ToolOp} class.
|
|
31
|
+
*
|
|
32
|
+
* Matching is case-insensitive. Unrecognized tools fail closed to the most
|
|
33
|
+
* restrictive sensible op (`shell` = arbitrary effect execution) rather than
|
|
34
|
+
* `read`, so an unknown tool is never silently treated as harmless.
|
|
35
|
+
*/
|
|
36
|
+
export function mapToolNameToOp(toolName) {
|
|
37
|
+
const name = toolName.trim().toLowerCase();
|
|
38
|
+
// Highest-risk git operations publish or rewrite history -> merge.
|
|
39
|
+
const mergeSignals = ["push", "merge", "cherry-pick", "cherrypick", "rebase", "tag"];
|
|
40
|
+
const looksLikeGit = name.startsWith("git") || /\bgit\b/.test(name);
|
|
41
|
+
if (looksLikeGit && mergeSignals.some((signal) => name.includes(signal))) {
|
|
42
|
+
return "merge";
|
|
43
|
+
}
|
|
44
|
+
// Bare verbs used directly as tool names (e.g. "merge", "rebase").
|
|
45
|
+
if (mergeSignals.some((signal) => name === signal)) {
|
|
46
|
+
return "merge";
|
|
47
|
+
}
|
|
48
|
+
// Shell / command execution.
|
|
49
|
+
if (name === "shell" || name === "bash" || name.includes("shell") || name.includes("bash")) {
|
|
50
|
+
return "shell";
|
|
51
|
+
}
|
|
52
|
+
// Write / mutation tools.
|
|
53
|
+
const writeSignals = ["write", "str_replace", "strreplace", "applydiff", "apply_diff", "edit"];
|
|
54
|
+
if (writeSignals.some((signal) => name.includes(signal))) {
|
|
55
|
+
return "write";
|
|
56
|
+
}
|
|
57
|
+
// Read-only tools (exact names to avoid accidental substring matches).
|
|
58
|
+
const readSignals = ["read", "grep", "glob", "ls", "cat"];
|
|
59
|
+
if (readSignals.includes(name)) {
|
|
60
|
+
return "read";
|
|
61
|
+
}
|
|
62
|
+
// Unknown / unrecognized -> most restrictive sensible op (fail-closed).
|
|
63
|
+
return "shell";
|
|
64
|
+
}
|
|
65
|
+
/** Returns true when provider authority is sufficient for the requested op. */
|
|
66
|
+
function isAuthoritySatisfied(ctx) {
|
|
67
|
+
switch (ctx.op) {
|
|
68
|
+
case "read":
|
|
69
|
+
return true;
|
|
70
|
+
case "write":
|
|
71
|
+
return ctx.writeAuthority === "full";
|
|
72
|
+
case "shell":
|
|
73
|
+
return ctx.shellAuthority === "full";
|
|
74
|
+
case "merge":
|
|
75
|
+
return ctx.writeAuthority === "full" && ctx.shellAuthority === "full";
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Decide allow / ask / block for a tool operation. Pure and fail-closed.
|
|
80
|
+
*
|
|
81
|
+
* @see ToolAuthorityContext for the decision inputs and ordering rules.
|
|
82
|
+
*/
|
|
83
|
+
export function decideToolAuthority(ctx) {
|
|
84
|
+
// Rule 1: reads are always allowed.
|
|
85
|
+
if (ctx.op === "read") {
|
|
86
|
+
return "allow";
|
|
87
|
+
}
|
|
88
|
+
// Rule 2: a read-only sandbox is a hard floor for any non-read op.
|
|
89
|
+
if (ctx.sandboxMode === "read-only") {
|
|
90
|
+
return "block";
|
|
91
|
+
}
|
|
92
|
+
// Rule 3: authority outranks policy. Insufficient authority => block.
|
|
93
|
+
if (!isAuthoritySatisfied(ctx)) {
|
|
94
|
+
return "block";
|
|
95
|
+
}
|
|
96
|
+
// Rule 4: authority satisfied -> apply approval policy.
|
|
97
|
+
if (ctx.approvalPolicy === "block") {
|
|
98
|
+
return "block";
|
|
99
|
+
}
|
|
100
|
+
if (ctx.approvalPolicy === "yolo") {
|
|
101
|
+
return "allow";
|
|
102
|
+
}
|
|
103
|
+
if (ctx.approvalPolicy === "auto") {
|
|
104
|
+
return "allow";
|
|
105
|
+
}
|
|
106
|
+
// interactive: ask only when a TTY is attached; non-TTY ask = deny-by-default.
|
|
107
|
+
return ctx.tty ? "ask" : "block";
|
|
108
|
+
}
|
|
@@ -47,16 +47,16 @@ export declare const ProviderCapabilitySchema: z.ZodObject<{
|
|
|
47
47
|
cli: boolean;
|
|
48
48
|
api: boolean;
|
|
49
49
|
mcp: boolean;
|
|
50
|
-
streaming: boolean;
|
|
51
50
|
tools: boolean;
|
|
51
|
+
streaming: boolean;
|
|
52
52
|
screenshots: boolean;
|
|
53
53
|
worktreeSafe: boolean;
|
|
54
54
|
}, {
|
|
55
55
|
cli: boolean;
|
|
56
56
|
api: boolean;
|
|
57
57
|
mcp: boolean;
|
|
58
|
-
streaming: boolean;
|
|
59
58
|
tools: boolean;
|
|
59
|
+
streaming: boolean;
|
|
60
60
|
screenshots: boolean;
|
|
61
61
|
worktreeSafe: boolean;
|
|
62
62
|
}>;
|
|
@@ -102,8 +102,8 @@ export declare const ProviderCapabilitySchema: z.ZodObject<{
|
|
|
102
102
|
cli: boolean;
|
|
103
103
|
api: boolean;
|
|
104
104
|
mcp: boolean;
|
|
105
|
-
streaming: boolean;
|
|
106
105
|
tools: boolean;
|
|
106
|
+
streaming: boolean;
|
|
107
107
|
screenshots: boolean;
|
|
108
108
|
worktreeSafe: boolean;
|
|
109
109
|
};
|
|
@@ -130,8 +130,8 @@ export declare const ProviderCapabilitySchema: z.ZodObject<{
|
|
|
130
130
|
cli: boolean;
|
|
131
131
|
api: boolean;
|
|
132
132
|
mcp: boolean;
|
|
133
|
-
streaming: boolean;
|
|
134
133
|
tools: boolean;
|
|
134
|
+
streaming: boolean;
|
|
135
135
|
screenshots: boolean;
|
|
136
136
|
worktreeSafe: boolean;
|
|
137
137
|
};
|
|
@@ -23,6 +23,7 @@ export interface StarPromptOptions {
|
|
|
23
23
|
commandName?: string;
|
|
24
24
|
prompt?: (repoUrl: string) => Promise<boolean>;
|
|
25
25
|
starRepo?: (repoUrl: string) => Promise<void> | void;
|
|
26
|
+
openBrowser?: typeof openRepoInBrowser;
|
|
26
27
|
now?: () => Date;
|
|
27
28
|
}
|
|
28
29
|
export declare function getStarPromptStatePath(homeDir?: string): string;
|
|
@@ -47,3 +48,11 @@ export declare function getStarPromptSummary(homeDir?: string): Promise<StarProm
|
|
|
47
48
|
export declare function parseGitHubRepoSlug(repoUrl: string): string | null;
|
|
48
49
|
export declare function checkGhAuth(): Promise<void>;
|
|
49
50
|
export declare function starGitHubRepo(repoUrl: string): Promise<void>;
|
|
51
|
+
export interface OpenRepoInBrowserOptions {
|
|
52
|
+
spawnFn?: typeof import("child_process").spawn;
|
|
53
|
+
platform?: NodeJS.Platform;
|
|
54
|
+
display?: string;
|
|
55
|
+
isTTY?: boolean;
|
|
56
|
+
env?: NodeJS.ProcessEnv;
|
|
57
|
+
}
|
|
58
|
+
export declare function openRepoInBrowser(repoUrl: string, opts?: OpenRepoInBrowserOptions): Promise<boolean>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { execFile } from "child_process";
|
|
1
|
+
import { execFile, spawn } from "child_process";
|
|
2
2
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
3
3
|
import { homedir } from "os";
|
|
4
4
|
import { dirname, join } from "path";
|
|
@@ -72,6 +72,7 @@ export async function maybeAskForGitHubStar(options) {
|
|
|
72
72
|
console.error(style.gray(`GitHub star failed: ${starError}`));
|
|
73
73
|
if (slug)
|
|
74
74
|
console.error(style.gray(`Visit ${style.cream(`https://github.com/${slug}`)} to star manually.`));
|
|
75
|
+
await (options.openBrowser ?? openRepoInBrowser)(repoUrl);
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
await writeStarPromptState({
|
|
@@ -124,6 +125,7 @@ export async function maybeAskForGitHubStarAfterCommand(options) {
|
|
|
124
125
|
console.error(style.gray(`GitHub star failed: ${starError}`));
|
|
125
126
|
if (slug)
|
|
126
127
|
console.error(style.gray(`Visit ${style.cream(`https://github.com/${slug}`)} to star manually.`));
|
|
128
|
+
await (options.openBrowser ?? openRepoInBrowser)(repoUrl);
|
|
127
129
|
}
|
|
128
130
|
}
|
|
129
131
|
await writeStarPromptState({
|
|
@@ -221,3 +223,42 @@ export async function starGitHubRepo(repoUrl) {
|
|
|
221
223
|
timeout: 10_000,
|
|
222
224
|
});
|
|
223
225
|
}
|
|
226
|
+
export async function openRepoInBrowser(repoUrl, opts) {
|
|
227
|
+
try {
|
|
228
|
+
const isTTY = opts?.isTTY ?? process.stdout.isTTY;
|
|
229
|
+
const env = opts?.env ?? process.env;
|
|
230
|
+
const platform = opts?.platform ?? process.platform;
|
|
231
|
+
if (!isTTY)
|
|
232
|
+
return false;
|
|
233
|
+
if (env.CI || env.GITHUB_ACTIONS)
|
|
234
|
+
return false;
|
|
235
|
+
const display = opts?.display ?? env.DISPLAY;
|
|
236
|
+
let cmd;
|
|
237
|
+
let args;
|
|
238
|
+
if (platform === "darwin") {
|
|
239
|
+
cmd = "open";
|
|
240
|
+
args = [repoUrl];
|
|
241
|
+
}
|
|
242
|
+
else if (platform === "win32") {
|
|
243
|
+
cmd = "cmd";
|
|
244
|
+
args = ["/c", "start", "", repoUrl];
|
|
245
|
+
}
|
|
246
|
+
else if (platform === "linux" && display) {
|
|
247
|
+
cmd = "xdg-open";
|
|
248
|
+
args = [repoUrl];
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
const spawnFn = opts?.spawnFn ?? spawn;
|
|
254
|
+
const child = spawnFn(cmd, args, {
|
|
255
|
+
stdio: "ignore",
|
|
256
|
+
detached: true,
|
|
257
|
+
});
|
|
258
|
+
child.unref();
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
@@ -22,4 +22,24 @@ export interface TerminalInputState {
|
|
|
22
22
|
}
|
|
23
23
|
export declare function captureTerminalInputState(input?: TerminalInputLike): TerminalInputState;
|
|
24
24
|
export declare function enableRawTerminalInput(input?: TerminalInputLike): TerminalInputState;
|
|
25
|
+
/**
|
|
26
|
+
* Defensive re-validation of interactive stdin before a fresh readline takes
|
|
27
|
+
* ownership of the TTY.
|
|
28
|
+
*
|
|
29
|
+
* The first-run GitHub-star prompt (maybeAskForGitHubStarAtChatStart) and the
|
|
30
|
+
* update prompt (maybePromptForOmkUpdate) use @inquirer/prompts, which take
|
|
31
|
+
* over raw mode and run their own readline on process.stdin. On completion they
|
|
32
|
+
* can leave the shared interactive stdin explicitly paused
|
|
33
|
+
* (readableFlowing === false). A freshly created readline then observes an
|
|
34
|
+
* immediate EOF/'close' and the native chat loop exits with "Session ended".
|
|
35
|
+
*
|
|
36
|
+
* This helper only resumes a real TTY that was explicitly paused. Non-TTY
|
|
37
|
+
* stdin (pipes/EOF, CI, non-interactive callers) is intentionally left
|
|
38
|
+
* untouched so existing exit/EOF behavior is preserved. A fresh, never-started
|
|
39
|
+
* stream (readableFlowing === null) is also left alone so readline can manage
|
|
40
|
+
* its own initial resume without racing for the first byte.
|
|
41
|
+
*
|
|
42
|
+
* Returns true only when it actually resumed a paused interactive stream.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resumeInteractiveInput(input?: TerminalInputLike): boolean;
|
|
25
45
|
export declare function restoreTerminalInputState(input: TerminalInputLike | undefined, state: TerminalInputState): void;
|
|
@@ -21,6 +21,38 @@ export function enableRawTerminalInput(input = process.stdin) {
|
|
|
21
21
|
input.resume();
|
|
22
22
|
return state;
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Defensive re-validation of interactive stdin before a fresh readline takes
|
|
26
|
+
* ownership of the TTY.
|
|
27
|
+
*
|
|
28
|
+
* The first-run GitHub-star prompt (maybeAskForGitHubStarAtChatStart) and the
|
|
29
|
+
* update prompt (maybePromptForOmkUpdate) use @inquirer/prompts, which take
|
|
30
|
+
* over raw mode and run their own readline on process.stdin. On completion they
|
|
31
|
+
* can leave the shared interactive stdin explicitly paused
|
|
32
|
+
* (readableFlowing === false). A freshly created readline then observes an
|
|
33
|
+
* immediate EOF/'close' and the native chat loop exits with "Session ended".
|
|
34
|
+
*
|
|
35
|
+
* This helper only resumes a real TTY that was explicitly paused. Non-TTY
|
|
36
|
+
* stdin (pipes/EOF, CI, non-interactive callers) is intentionally left
|
|
37
|
+
* untouched so existing exit/EOF behavior is preserved. A fresh, never-started
|
|
38
|
+
* stream (readableFlowing === null) is also left alone so readline can manage
|
|
39
|
+
* its own initial resume without racing for the first byte.
|
|
40
|
+
*
|
|
41
|
+
* Returns true only when it actually resumed a paused interactive stream.
|
|
42
|
+
*/
|
|
43
|
+
export function resumeInteractiveInput(input = process.stdin) {
|
|
44
|
+
if (!input.isTTY)
|
|
45
|
+
return false;
|
|
46
|
+
if (input.readableFlowing !== false)
|
|
47
|
+
return false;
|
|
48
|
+
try {
|
|
49
|
+
input.resume();
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
24
56
|
export function restoreTerminalInputState(input = process.stdin, state) {
|
|
25
57
|
const externalDataOwnerAttached = input.listenerCount("data") > state.dataListenerCount;
|
|
26
58
|
if (!externalDataOwnerAttached && state.wasTTY && typeof input.setRawMode === "function") {
|
|
@@ -21,9 +21,14 @@ export interface KimiUpdateStatus {
|
|
|
21
21
|
fallbackInstallCmd: string;
|
|
22
22
|
installScript: string;
|
|
23
23
|
}
|
|
24
|
-
export declare const OMK_NPM_PACKAGE_NAME = "
|
|
24
|
+
export declare const OMK_NPM_PACKAGE_NAME = "open-multi-agent-kit";
|
|
25
25
|
type UpdatePromptEnv = Record<string, string | undefined>;
|
|
26
26
|
export type OmkUpdatePromptChoice = "update-now" | "skip-version" | "remind-later";
|
|
27
|
+
/**
|
|
28
|
+
* Returns true when `env.OMK_AUTO_UPDATE` is one of 1/true/yes/on/always
|
|
29
|
+
* (case-insensitive), indicating the user wants non-interactive auto-updates.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveAutoUpdateMode(env: UpdatePromptEnv): boolean;
|
|
27
32
|
export type OmkUpdatePromptDecisionReason = "disabled" | "ci" | "non-tty" | "not-outdated" | "missing-latest" | "skipped-version" | "remind-active" | "prompt";
|
|
28
33
|
export type OmkUpdatePromptAction = Exclude<OmkUpdatePromptDecisionReason, "prompt"> | "suppressed" | "prompted-skip" | "prompted-remind" | "updated" | "update-failed" | "cancelled" | "timeout";
|
|
29
34
|
export interface OmkUpdatePromptState {
|
|
@@ -6,9 +6,17 @@ import { homedir } from "os";
|
|
|
6
6
|
const CACHE_TTL_MS = 6 * 60 * 60 * 1000;
|
|
7
7
|
const DEFAULT_UPDATE_REMIND_HOURS = 24;
|
|
8
8
|
const UPDATE_PROMPT_TIMEOUT_MS = 30_000;
|
|
9
|
-
export const OMK_NPM_PACKAGE_NAME = "
|
|
9
|
+
export const OMK_NPM_PACKAGE_NAME = "open-multi-agent-kit";
|
|
10
10
|
const OMK_UPDATE_INSTALL_CMD = `npm i -g ${OMK_NPM_PACKAGE_NAME}`;
|
|
11
11
|
const FALLBACK_INSTALL_SCRIPT = "Set KIMI_API_KEY and optionally KIMI_MODEL for direct Moonshot API access.";
|
|
12
|
+
/**
|
|
13
|
+
* Returns true when `env.OMK_AUTO_UPDATE` is one of 1/true/yes/on/always
|
|
14
|
+
* (case-insensitive), indicating the user wants non-interactive auto-updates.
|
|
15
|
+
*/
|
|
16
|
+
export function resolveAutoUpdateMode(env) {
|
|
17
|
+
const raw = env.OMK_AUTO_UPDATE?.trim().toLowerCase();
|
|
18
|
+
return raw === "1" || raw === "true" || raw === "yes" || raw === "on" || raw === "always";
|
|
19
|
+
}
|
|
12
20
|
function getCachePath() {
|
|
13
21
|
return join(homedir(), ".omk", "update-cache.json");
|
|
14
22
|
}
|
|
@@ -120,6 +128,32 @@ export async function maybePromptForOmkUpdate(options = {}) {
|
|
|
120
128
|
const isTTY = options.isTTY ?? Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
|
121
129
|
const isCI = options.isCI ?? (isTruthyCiValue(env.CI) || isTruthyCiValue(env.GITHUB_ACTIONS));
|
|
122
130
|
const log = options.onLog ?? ((message) => console.log(message));
|
|
131
|
+
const autoUpdate = resolveAutoUpdateMode(env);
|
|
132
|
+
if (autoUpdate && !isCI && getUpdatePromptMode(env) !== "off") {
|
|
133
|
+
let updateStatus;
|
|
134
|
+
try {
|
|
135
|
+
updateStatus = options.status ?? await (options.checkUpdatesFn ?? checkUpdates)();
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
139
|
+
return { action: "suppressed", shouldExit: false, message };
|
|
140
|
+
}
|
|
141
|
+
const latestVersion = updateStatus.omk.latest;
|
|
142
|
+
if (updateStatus.omk.outdated && latestVersion) {
|
|
143
|
+
log(`Auto-updating OMK to ${normalizeVersionForPrompt(latestVersion)} ...`);
|
|
144
|
+
const runUpdate = options.runUpdate ?? (() => runShell("npm", ["i", "-g", OMK_NPM_PACKAGE_NAME], { timeout: 120_000 }));
|
|
145
|
+
const updateResult = await runUpdate();
|
|
146
|
+
if (updateResult.failed) {
|
|
147
|
+
const detail = updateResult.stderr.trim() || updateResult.stdout.trim() || `exit ${updateResult.exitCode}`;
|
|
148
|
+
log(`Auto-update failed: ${detail}`);
|
|
149
|
+
log(`Manual update command: ${OMK_UPDATE_INSTALL_CMD}`);
|
|
150
|
+
return { action: "update-failed", shouldExit: true, exitCode: 1, version: latestVersion, message: detail };
|
|
151
|
+
}
|
|
152
|
+
log("OMK auto-update completed successfully. Restart omk chat to use the new version.");
|
|
153
|
+
return { action: "updated", shouldExit: true, exitCode: 0, version: latestVersion };
|
|
154
|
+
}
|
|
155
|
+
return { action: "not-outdated", shouldExit: false };
|
|
156
|
+
}
|
|
123
157
|
const preflight = resolveOmkUpdatePromptState({
|
|
124
158
|
status: null,
|
|
125
159
|
env,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# 2026-06-08 Critical Issues
|
|
2
|
+
|
|
3
|
+
## Critical Init Status
|
|
4
|
+
- No critical init artifacts were missing when this daily file was generated.
|
|
5
|
+
### Missing critical artifacts
|
|
6
|
+
- None detected.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## Critical Artifacts Present
|
|
10
|
+
- ✅ `AGENTS.md` — top-level operating contract
|
|
11
|
+
- ✅ `.kimi/AGENTS.md` — Kimi-specific operating rules
|
|
12
|
+
- ✅ `.omk/config.toml` — OMK project runtime settings
|
|
13
|
+
- ✅ `.omk/agents/root.yaml` — root coordinator agent
|
|
14
|
+
- ✅ `.kimi/mcp.json` — Kimi project MCP registry
|
|
15
|
+
- ✅ `.omk/hooks/pre-shell-guard.sh` — destructive shell guard
|
|
16
|
+
- ✅ `.omk/hooks/protect-secrets.sh` — secret write guard
|
|
17
|
+
- ✅ `.omk/memory/graph-state.json` — local ontology graph database
|
|
18
|
+
|
|
19
|
+
## Escalation Rule
|
|
20
|
+
- Treat missing shell/secret guards, root agent config, MCP registry, or ontology graph as critical until restored.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# 2026-06-08 Improvements
|
|
2
|
+
|
|
3
|
+
## Current Improvement Backlog
|
|
4
|
+
### Optional init/support artifacts to add or refresh
|
|
5
|
+
- None detected.
|
|
6
|
+
|
|
7
|
+
### Critical init artifacts currently blocking reliable chat startup
|
|
8
|
+
- None detected.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## Suggested Focus
|
|
12
|
+
- Keep `omk chat` startup idempotent and non-destructive.
|
|
13
|
+
- Prefer local graph memory for default ontology state.
|
|
14
|
+
- Keep generated daily docs small, dated, and safe to edit by hand.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# 2026-06-08 Required Init Checklist
|
|
2
|
+
|
|
3
|
+
**Run ID:** chat-2026-06-07T16-16-01-461Z-1315
|
|
4
|
+
**Ontology graph:** `.omk/memory/graph-state.json`
|
|
5
|
+
|
|
6
|
+
## Required Artifacts
|
|
7
|
+
- ✅ `AGENTS.md` — critical; top-level operating contract
|
|
8
|
+
- ✅ `.kimi/AGENTS.md` — critical; Kimi-specific operating rules
|
|
9
|
+
- ✅ `DESIGN.md` — support; design/brand source of truth
|
|
10
|
+
- ✅ `.omk/config.toml` — critical; OMK project runtime settings
|
|
11
|
+
- ✅ `.omk/agents/root.yaml` — critical; root coordinator agent
|
|
12
|
+
- ✅ `.kimi/mcp.json` — critical; Kimi project MCP registry
|
|
13
|
+
- ✅ `.omk/mcp.json` — support; legacy OMK MCP fallback
|
|
14
|
+
- ✅ `.omk/lsp.json` — support; bundled TypeScript/Python LSP config
|
|
15
|
+
- ✅ `.omk/hooks/pre-shell-guard.sh` — critical; destructive shell guard
|
|
16
|
+
- ✅ `.omk/hooks/protect-secrets.sh` — critical; secret write guard
|
|
17
|
+
- ✅ `.omk/memory/graph-state.json` — critical; local ontology graph database
|
|
18
|
+
- ✅ `.kimi/skills` — support; Kimi skill directory
|
|
19
|
+
- ✅ `.agents/skills` — support; portable skill directory
|
|
20
|
+
|
|
21
|
+
## Recovery Command
|
|
22
|
+
```bash
|
|
23
|
+
omk init
|
|
24
|
+
omk doctor
|
|
25
|
+
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# 2026-06-08 OMK Chat Plan
|
|
2
|
+
|
|
3
|
+
**Run ID:** chat-2026-06-07T16-16-01-461Z-1315
|
|
4
|
+
**Generated by:** omk chat bootstrap
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
- Start every chat with a dated workspace for planning, issue triage, and verification evidence.
|
|
8
|
+
- Keep ontology-backed memory available before the root coordinator starts.
|
|
9
|
+
- Make required init state visible without overwriting user-authored docs.
|
|
10
|
+
|
|
11
|
+
## Today Plan
|
|
12
|
+
1. Review `init-checklist.md` and resolve missing critical init artifacts first.
|
|
13
|
+
2. Use `improvements.md` as the active improvement backlog.
|
|
14
|
+
3. Use `critical-issues.md` for blocking defects, safety risks, and verification gaps.
|
|
15
|
+
4. Record command evidence before claiming work is complete.
|
|
16
|
+
|
|
17
|
+
## Stop Condition
|
|
18
|
+
- Critical init artifacts are present.
|
|
19
|
+
- Ontology graph exists at `.omk/memory/graph-state.json`.
|
|
20
|
+
- Any new code/docs changes have explicit verification evidence.
|
package/docs/getting-started.md
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# Getting Started
|
|
2
2
|
|
|
3
|
-
Source release target:
|
|
3
|
+
Source release target: `open-multi-agent-kit@0.78.1` (`pre-1.0`).
|
|
4
4
|
|
|
5
5
|
## Prerequisites
|
|
6
6
|
|
|
7
7
|
- Node.js 20+
|
|
8
8
|
- Git
|
|
9
|
-
- At least one
|
|
9
|
+
- At least one configured provider or local runtime adapter. Kimi is the most mature authority path; other lanes depend on local CLI/API availability and the provider-maturity contract.
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
npm install -g
|
|
14
|
+
npm install -g open-multi-agent-kit
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Initialize a project
|
|
@@ -35,3 +35,31 @@ omk chat
|
|
|
35
35
|
omk plan "refactor auth module"
|
|
36
36
|
omk run feature-dev "add user dashboard"
|
|
37
37
|
```
|
|
38
|
+
|
|
39
|
+
## Updates
|
|
40
|
+
|
|
41
|
+
On startup OMK checks npm for a newer release and, when one exists, shows an
|
|
42
|
+
interactive prompt (Update now / Skip this version / Remind me later). Choosing
|
|
43
|
+
"Update now" runs `npm i -g open-multi-agent-kit`.
|
|
44
|
+
|
|
45
|
+
- **Automatic (non-interactive) updates:** set `OMK_AUTO_UPDATE=1` (also accepts
|
|
46
|
+
`true|yes|on|always`). When OMK is outdated it self-updates on startup without
|
|
47
|
+
prompting. CI is always skipped, and `OMK_UPDATE_PROMPT=off` disables update
|
|
48
|
+
checks entirely.
|
|
49
|
+
- Manual check: `omk update check` (add `--refresh` to bypass the cache).
|
|
50
|
+
|
|
51
|
+
## Adaptive runtime algorithms
|
|
52
|
+
|
|
53
|
+
OMK embeds three adaptive control behaviors (all additive, safe defaults, non-fatal fallback):
|
|
54
|
+
|
|
55
|
+
- **Topology-routed first run** — on the first DAG composition OMK derives structural features (width, critical depth, coupling, parallel ratio) and selects an execution topology (parallel / pipeline / map-reduce / hierarchical / hybrid / dag) with layered waves. Toggle with `OMK_ADAPTORCH_ROUTING=off`.
|
|
56
|
+
- **Context guard before 90%** — before the context window crosses a threshold (default `0.90`) OMK compacts via [headroom](https://github.com/chopratejas/headroom) when available, otherwise its built-in budget optimizer. Tune with `OMK_HEADROOM_THRESHOLD` (0.50–0.99), `OMK_CONTEXT_WINDOW`, or disable with `OMK_HEADROOM=off`.
|
|
57
|
+
- **Spec-first via Ouroboros** — goal/spec/orchestration intents prefer the embedded Ouroboros flow by default; when Ouroboros is not installed OMK degrades to the native path with no error. Modes: `OMK_OUROBOROS=always` (default) `| auto | off`. See [Ouroboros integration](integrations/ouroboros.md).
|
|
58
|
+
|
|
59
|
+
## Support the project (GitHub star)
|
|
60
|
+
|
|
61
|
+
First-time users get a one-time prompt to star the repository. If the GitHub CLI
|
|
62
|
+
(`gh`) is authenticated the star is applied directly; otherwise OMK prints the
|
|
63
|
+
repo URL and, on a desktop session, opens it in your browser so you can star in
|
|
64
|
+
one click. You can star anytime with `omk star`, check status with
|
|
65
|
+
`omk star --status`, and disable the prompt with `OMK_STAR_PROMPT=off`.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Ouroboros integration (embedded in OMK)
|
|
2
|
+
|
|
3
|
+
[Ouroboros](https://github.com/Q00/ouroboros) is a spec-first "Agent OS"
|
|
4
|
+
(PyPI `ouroboros-ai`). OMK embeds it through the documented runtime-adapter
|
|
5
|
+
surface that Ouroboros already supports for the `pi`-family CLI that OMK builds
|
|
6
|
+
on:
|
|
7
|
+
|
|
8
|
+
- an **MCP server** (`ouroboros mcp serve`, ~29 `ouroboros_*` tools) registered in OMK's MCP config,
|
|
9
|
+
- the official **`ooo` bridge extension** installed into OMK's agent extensions dir, so `ooo ...` works inside interactive OMK sessions, and
|
|
10
|
+
- the 20 Ouroboros **skills** (SKILL.md) installed namespaced as `ouroboros-*`.
|
|
11
|
+
|
|
12
|
+
Ouroboros owns its own workflow engine; the OMK runtime CLI is selected as its
|
|
13
|
+
`runtime_backend` (a `--mode json` subprocess). This follows the runtime guide
|
|
14
|
+
in the Ouroboros repository.
|
|
15
|
+
|
|
16
|
+
## Prerequisites
|
|
17
|
+
|
|
18
|
+
- Python `>=3.12`, `uv` (or `pipx`), and the OMK runtime CLI on `PATH`.
|
|
19
|
+
- OMK global agent dir at `~/.omk/agent` (extensions, skills, `mcp.json`).
|
|
20
|
+
|
|
21
|
+
## Install (reproducible)
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# 0. Back up the global MCP config (mode 600, contains secrets) before merging.
|
|
25
|
+
ts=$(date +%Y%m%d-%H%M%S)
|
|
26
|
+
cp -a ~/.omk/agent/mcp.json ~/.omk/agent/mcp.json.bak-$ts
|
|
27
|
+
|
|
28
|
+
# 1. Install the package with MCP support.
|
|
29
|
+
uv tool install 'ouroboros-ai[mcp,claude]' # or: pipx install 'ouroboros-ai[mcp,claude]'
|
|
30
|
+
|
|
31
|
+
# 2. Non-interactive runtime setup: writes ~/.ouroboros/config.yaml
|
|
32
|
+
# (runtime_backend) and generates the ooo bridge extension.
|
|
33
|
+
ouroboros setup --runtime pi --non-interactive
|
|
34
|
+
|
|
35
|
+
# 3. Mirror the generated ooo bridge into OMK's extension dir.
|
|
36
|
+
# (locate the file Ouroboros generated, regardless of upstream dir)
|
|
37
|
+
BRIDGE_SRC=$(find "$HOME" -maxdepth 4 -name ouroboros-ooo-bridge.ts -not -path '*/.omk/*' 2>/dev/null | head -1)
|
|
38
|
+
cp "$BRIDGE_SRC" ~/.omk/agent/extensions/ouroboros-ooo-bridge.ts
|
|
39
|
+
|
|
40
|
+
# 4. Register the MCP server in OMK (additive jq merge; keep mode 600).
|
|
41
|
+
OURO_BIN="$(command -v ouroboros)"
|
|
42
|
+
jq --arg bin "$OURO_BIN" '.mcpServers.ouroboros = {command:$bin, args:["mcp","serve"], env:{}}' \
|
|
43
|
+
~/.omk/agent/mcp.json > /tmp/omk-mcp.new \
|
|
44
|
+
&& python3 -m json.tool < /tmp/omk-mcp.new >/dev/null \
|
|
45
|
+
&& install -m600 /tmp/omk-mcp.new ~/.omk/agent/mcp.json && rm -f /tmp/omk-mcp.new
|
|
46
|
+
|
|
47
|
+
# 5. Install the 20 Ouroboros skills (namespaced).
|
|
48
|
+
git clone --depth 1 https://github.com/Q00/ouroboros.git /tmp/ouroboros-src
|
|
49
|
+
for d in /tmp/ouroboros-src/skills/*/; do b=$(basename "$d");
|
|
50
|
+
mkdir -p ~/.omk/agent/skills/ouroboros-$b;
|
|
51
|
+
cp "$d/SKILL.md" ~/.omk/agent/skills/ouroboros-$b/SKILL.md; done
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
> The MCP entry uses the absolute `ouroboros` binary path because OMK sanitizes
|
|
55
|
+
> the child environment; a bare `ouroboros`/`uvx` command may not resolve under
|
|
56
|
+
> the sanitized `PATH`.
|
|
57
|
+
|
|
58
|
+
## Verify
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
ouroboros --version
|
|
62
|
+
ouroboros mcp serve --help # MCP entrypoint
|
|
63
|
+
ouroboros dispatch --help # ooo bridge dispatch entrypoint
|
|
64
|
+
test -f ~/.omk/agent/extensions/ouroboros-ooo-bridge.ts && echo "omk bridge OK"
|
|
65
|
+
grep -q ouroboros ~/.omk/agent/mcp.json && echo "mcp registered"
|
|
66
|
+
ls -d ~/.omk/agent/skills/ouroboros-* | wc -l # expect 20
|
|
67
|
+
grep runtime_backend ~/.ouroboros/config.yaml # expect: pi
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
A successful MCP handshake reports `serverInfo: ouroboros-mcp` and ~29
|
|
71
|
+
`ouroboros_*` tools. In an interactive OMK session, after restart or `/reload`:
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
ooo status
|
|
75
|
+
ooo auto build a small CLI
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Scope and safety notes
|
|
79
|
+
|
|
80
|
+
- The `ouroboros` MCP server is registered in the **global** `~/.omk/agent/mcp.json`,
|
|
81
|
+
so it is available under all-scope MCP sessions. Default project-scope sessions
|
|
82
|
+
(`omk-project` only) are unaffected, so OMK startup is not slowed by Ouroboros.
|
|
83
|
+
- `ouroboros setup` mutates `~/.ouroboros/config.yaml` and the upstream runtime's
|
|
84
|
+
global extensions dir; it does not touch the OMK repo.
|
|
85
|
+
- First MCP cold start resolves the uv tool venv and can be slow; `omk mcp doctor
|
|
86
|
+
ouroboros` may need a longer timeout on first run.
|
|
87
|
+
|
|
88
|
+
## Rollback
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
ts=<backup timestamp>
|
|
92
|
+
rm -f ~/.omk/agent/extensions/ouroboros-ooo-bridge.ts
|
|
93
|
+
[ -f ~/.omk/agent/mcp.json.bak-$ts ] && install -m600 ~/.omk/agent/mcp.json.bak-$ts ~/.omk/agent/mcp.json
|
|
94
|
+
rm -rf ~/.omk/agent/skills/ouroboros-*
|
|
95
|
+
uv tool uninstall ouroboros-ai # or: pipx uninstall ouroboros-ai
|
|
96
|
+
```
|
package/docs/versioning.md
CHANGED
|
@@ -4,11 +4,11 @@ OMK uses two version fields in release artifacts:
|
|
|
4
4
|
|
|
5
5
|
| Field | Current value | Source | Meaning |
|
|
6
6
|
| --- | --- | --- | --- |
|
|
7
|
-
| Package version | `0.78.
|
|
7
|
+
| Package version | `0.78.1` | `package.json`, `package-lock.json` | npm/package source version. |
|
|
8
8
|
| Runtime version | `v1.2` | `src/version.ts`, JSON schemas | Contract/runtime family used by OMK envelopes. |
|
|
9
9
|
| Release channel | `pre-1.0` | `src/version.ts` | Pre-1.0 package channel. |
|
|
10
10
|
|
|
11
|
-
`0.78.
|
|
11
|
+
`0.78.1` is the package source version for the `v1.2` runtime contract family.
|
|
12
12
|
Use `v1.2` only for runtime contracts; do not substitute it for the package version.
|
|
13
13
|
|
|
14
14
|
## Contract versions
|
|
@@ -44,6 +44,6 @@ The `version --json` command emits one `omk.contract.v1` envelope whose data pay
|
|
|
44
44
|
|
|
45
45
|
## Documentation rules
|
|
46
46
|
|
|
47
|
-
- Use `0.78.
|
|
47
|
+
- Use `0.78.1` when referring to the current package source version.
|
|
48
48
|
- Use `v1.2` only for the runtime contract family.
|
|
49
49
|
- Keep historical changelog entries unchanged unless the text is not clearly historical.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "open-multi-agent-kit",
|
|
3
|
-
"version": "0.78.
|
|
3
|
+
"version": "0.78.1",
|
|
4
4
|
"description": "Provider-neutral multi-agent control plane for coding workflows: route agents, verify evidence, orchestrate MCP-aware DAGs, and control the loop from the omk CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
Binary file
|