open-multi-agent-kit 0.78.0 → 0.78.2
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 +56 -15
- package/MATURITY.md +6 -2
- package/README.md +125 -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-spec-agent-goal-commands.js +45 -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/cli/release-promotion-gate.d.ts +14 -0
- package/dist/cli/release-promotion-gate.js +71 -0
- package/dist/cli/v2/release-commands.d.ts +29 -0
- package/dist/cli/v2/release-commands.js +95 -0
- package/dist/commands/chat/core.js +5 -0
- package/dist/commands/chat/native-root-loop.js +74 -1
- package/dist/commands/chat/slash/commands/session.js +19 -1
- package/dist/commands/dag-from-spec.d.ts +1 -0
- package/dist/commands/dag-from-spec.js +61 -1
- package/dist/commands/goal-interview.d.ts +18 -0
- package/dist/commands/goal-interview.js +396 -0
- 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/interview.d.ts +106 -0
- package/dist/contracts/interview.js +9 -0
- package/dist/contracts/provider-health.d.ts +42 -0
- package/dist/contracts/provider-health.js +9 -0
- package/dist/evidence/index.d.ts +4 -0
- package/dist/evidence/index.js +2 -0
- package/dist/evidence/proof-trust-cli.d.ts +8 -0
- package/dist/evidence/proof-trust-cli.js +27 -0
- package/dist/evidence/proof-trust.d.ts +14 -0
- package/dist/evidence/proof-trust.js +381 -0
- package/dist/evidence/regression-proof-matrix.d.ts +42 -0
- package/dist/evidence/regression-proof-matrix.js +72 -0
- package/dist/goal/intent-frame.d.ts +30 -0
- package/dist/goal/intent-frame.js +39 -9
- package/dist/goal/interview-assimilation.d.ts +13 -0
- package/dist/goal/interview-assimilation.js +383 -0
- package/dist/goal/interview-question-bank.d.ts +11 -0
- package/dist/goal/interview-question-bank.js +225 -0
- package/dist/goal/interview-scoring.d.ts +31 -0
- package/dist/goal/interview-scoring.js +187 -0
- package/dist/goal/interview-session.d.ts +25 -0
- package/dist/goal/interview-session.js +116 -0
- package/dist/input/input-envelope.d.ts +22 -0
- package/dist/input/input-envelope.js +1 -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/advanced-control-loop.d.ts +60 -0
- package/dist/runtime/advanced-control-loop.js +136 -0
- package/dist/runtime/agent-runtime.d.ts +10 -0
- package/dist/runtime/blast-radius.d.ts +10 -0
- package/dist/runtime/blast-radius.js +14 -0
- package/dist/runtime/context-broker.d.ts +13 -4
- package/dist/runtime/context-broker.js +14 -1
- package/dist/runtime/contracts/evidence.d.ts +87 -0
- package/dist/runtime/contracts/evidence.js +7 -0
- package/dist/runtime/contracts/router-v2.d.ts +44 -0
- package/dist/runtime/contracts/router-v2.js +4 -0
- package/dist/runtime/contracts/weakness-remediation.d.ts +67 -0
- package/dist/runtime/contracts/weakness-remediation.js +36 -0
- package/dist/runtime/headroom-policy.d.ts +37 -0
- package/dist/runtime/headroom-policy.js +122 -0
- package/dist/runtime/kimi-api-runtime.js +59 -1
- package/dist/runtime/ouroboros-policy.d.ts +57 -0
- package/dist/runtime/ouroboros-policy.js +134 -0
- package/dist/runtime/proof-bundle-trust.d.ts +74 -0
- package/dist/runtime/proof-bundle-trust.js +100 -0
- package/dist/runtime/provider-maturity-gate.d.ts +41 -0
- package/dist/runtime/provider-maturity-gate.js +101 -0
- package/dist/runtime/public-surface.d.ts +93 -0
- package/dist/runtime/public-surface.js +146 -0
- package/dist/runtime/router-v2-scoring.d.ts +11 -0
- package/dist/runtime/router-v2-scoring.js +151 -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/runtime/weakness-remediation-index.d.ts +27 -0
- package/dist/runtime/weakness-remediation-index.js +37 -0
- package/dist/safety/tool-authority-gate.d.ts +62 -0
- package/dist/safety/tool-authority-gate.js +108 -0
- package/dist/schema/proof-bundle.schema.d.ts +26 -26
- package/dist/schema/provider.schema.d.ts +4 -4
- package/dist/util/clipboard-image.d.ts +49 -0
- package/dist/util/clipboard-image.js +263 -0
- 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/2026-06-09/critical-issues.md +20 -0
- package/docs/2026-06-09/improvements.md +14 -0
- package/docs/2026-06-09/init-checklist.md +25 -0
- package/docs/2026-06-09/plan.md +20 -0
- package/docs/getting-started.md +31 -3
- package/docs/github-organic-promotion.md +127 -0
- package/docs/integrations/ouroboros.md +96 -0
- package/docs/native-root-runtime-algorithms.md +301 -0
- package/docs/provider-maturity.md +1 -1
- package/docs/versioning.md +3 -3
- package/package.json +4 -3
- package/readmeasset/ASSET_INDEX.md +1 -0
- package/templates/skills/agents/omk-agent-reach-websearch/SKILL.md +55 -0
- package/templates/skills/kimi/omk-agent-reach-websearch/SKILL.md +55 -0
- package/dist/native/linux-x64/omk-safety +0 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform clipboard image reader.
|
|
3
|
+
*
|
|
4
|
+
* Wraps the platform-specific clipboard reading from screenshot-store patterns
|
|
5
|
+
* into a reusable utility for the chat REPL, goal commands, and any input
|
|
6
|
+
* surface that needs Ctrl+V / paste image support.
|
|
7
|
+
*
|
|
8
|
+
* Platforms:
|
|
9
|
+
* - macOS: `pngpaste -` (brew) or `osascript` with TIFF→PNG conversion
|
|
10
|
+
* - Linux: `xclip -selection clipboard -target image/png`
|
|
11
|
+
* - Windows: PowerShell System.Windows.Forms.Clipboard
|
|
12
|
+
*
|
|
13
|
+
* Output: PNG Buffer + saved file path under .omk/screenshots/
|
|
14
|
+
*/
|
|
15
|
+
import { execFileSync } from "node:child_process";
|
|
16
|
+
import { mkdirSync, writeFileSync, readFileSync, existsSync, unlinkSync } from "node:fs";
|
|
17
|
+
import { createHash } from "node:crypto";
|
|
18
|
+
import { join, relative } from "node:path";
|
|
19
|
+
export const SCREENSHOT_DIR = ".omk/screenshots";
|
|
20
|
+
export const MAX_IMAGE_BYTES = 20 * 1024 * 1024;
|
|
21
|
+
const CLIPBOARD_TIMEOUT_MS = 5000;
|
|
22
|
+
const CLIPBOARD_MAX_BUFFER = MAX_IMAGE_BYTES * 2;
|
|
23
|
+
const IMAGE_MAGIC = [
|
|
24
|
+
["png", [0x89, 0x50, 0x4e, 0x47]],
|
|
25
|
+
["jpg", [0xff, 0xd8, 0xff]],
|
|
26
|
+
["webp", [0x52, 0x49, 0x46, 0x46]],
|
|
27
|
+
["gif", [0x47, 0x49, 0x46, 0x38]],
|
|
28
|
+
];
|
|
29
|
+
export function detectImageExt(buf) {
|
|
30
|
+
for (const [ext, magic] of IMAGE_MAGIC) {
|
|
31
|
+
if (buf.length >= magic.length && magic.every((b, i) => buf[i] === b)) {
|
|
32
|
+
return ext;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
function mimeTypeForExt(ext) {
|
|
38
|
+
switch (ext) {
|
|
39
|
+
case "png": return "image/png";
|
|
40
|
+
case "jpg": return "image/jpeg";
|
|
41
|
+
case "webp": return "image/webp";
|
|
42
|
+
case "gif": return "image/gif";
|
|
43
|
+
default: return "application/octet-stream";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function toDataUri(base64, ext) {
|
|
47
|
+
return `data:${mimeTypeForExt(ext)};base64,${base64}`;
|
|
48
|
+
}
|
|
49
|
+
function generatePath(projectRoot, ext) {
|
|
50
|
+
const dateDir = new Date().toISOString().slice(0, 10);
|
|
51
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "").slice(0, 15);
|
|
52
|
+
const hash = createHash("sha256").update(`${Date.now()}-${Math.random()}`).digest("hex").slice(0, 8);
|
|
53
|
+
const fileName = `screenshot-${timestamp}-${hash}.${ext}`;
|
|
54
|
+
const dir = join(projectRoot, SCREENSHOT_DIR, dateDir);
|
|
55
|
+
mkdirSync(dir, { recursive: true });
|
|
56
|
+
const fullPath = join(dir, fileName);
|
|
57
|
+
const relativePath = relative(projectRoot, fullPath).replace(/\\/g, "/");
|
|
58
|
+
return { fullPath, relativePath };
|
|
59
|
+
}
|
|
60
|
+
// ── Platform readers ────────────────────────────────────────────────────────
|
|
61
|
+
function readMacClipboard() {
|
|
62
|
+
// Try pngpaste first (faster, more reliable)
|
|
63
|
+
try {
|
|
64
|
+
const out = execFileSync("pngpaste", ["-"], {
|
|
65
|
+
timeout: CLIPBOARD_TIMEOUT_MS,
|
|
66
|
+
maxBuffer: CLIPBOARD_MAX_BUFFER,
|
|
67
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
68
|
+
});
|
|
69
|
+
if (out.length > 0)
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// pngpaste not installed or clipboard empty
|
|
74
|
+
}
|
|
75
|
+
// Fallback: osascript (handles TIFF → PNG conversion)
|
|
76
|
+
try {
|
|
77
|
+
const script = `
|
|
78
|
+
set theFile to (POSIX path of (path to temporary items) & "omk-clip-" & (random number from 100000 to 999999) & ".png")
|
|
79
|
+
set img to the clipboard as «class PNGf»
|
|
80
|
+
set fRef to open for access POSIX file theFile with write permission
|
|
81
|
+
write img to fRef
|
|
82
|
+
close access fRef
|
|
83
|
+
return theFile
|
|
84
|
+
`;
|
|
85
|
+
const filePath = execFileSync("osascript", ["-e", script], {
|
|
86
|
+
timeout: CLIPBOARD_TIMEOUT_MS,
|
|
87
|
+
encoding: "utf-8",
|
|
88
|
+
}).trim();
|
|
89
|
+
if (filePath) {
|
|
90
|
+
const buf = readFileSync(filePath);
|
|
91
|
+
try {
|
|
92
|
+
unlinkSync(filePath);
|
|
93
|
+
}
|
|
94
|
+
catch { /* ignore */ }
|
|
95
|
+
if (buf.length > 0)
|
|
96
|
+
return buf;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// osascript failed
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
function readLinuxClipboard() {
|
|
105
|
+
try {
|
|
106
|
+
const out = execFileSync("xclip", ["-selection", "clipboard", "-target", "image/png", "-o"], {
|
|
107
|
+
timeout: CLIPBOARD_TIMEOUT_MS,
|
|
108
|
+
maxBuffer: CLIPBOARD_MAX_BUFFER,
|
|
109
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
110
|
+
});
|
|
111
|
+
if (out.length > 0)
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// xclip not available
|
|
116
|
+
}
|
|
117
|
+
// Fallback: wl-paste (Wayland)
|
|
118
|
+
try {
|
|
119
|
+
const out = execFileSync("wl-paste", ["--type", "image/png"], {
|
|
120
|
+
timeout: CLIPBOARD_TIMEOUT_MS,
|
|
121
|
+
maxBuffer: CLIPBOARD_MAX_BUFFER,
|
|
122
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
123
|
+
});
|
|
124
|
+
if (out.length > 0)
|
|
125
|
+
return out;
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// wl-paste not available
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
function readWindowsClipboard() {
|
|
133
|
+
const script = `
|
|
134
|
+
$ErrorActionPreference = 'SilentlyContinue'
|
|
135
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
136
|
+
Add-Type -AssemblyName System.Drawing
|
|
137
|
+
|
|
138
|
+
function Emit-Bytes([byte[]]$Bytes) {
|
|
139
|
+
if ($null -eq $Bytes -or $Bytes.Length -eq 0) { exit 1 }
|
|
140
|
+
[Console]::OpenStandardOutput().Write($Bytes, 0, $Bytes.Length)
|
|
141
|
+
exit 0
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
# Try PNG format first
|
|
145
|
+
$data = [System.Windows.Forms.Clipboard]::GetDataObject()
|
|
146
|
+
if ($null -ne $data) {
|
|
147
|
+
foreach ($format in @('PNG', 'image/png')) {
|
|
148
|
+
if ($data.GetDataPresent($format)) {
|
|
149
|
+
$raw = $data.GetData($format)
|
|
150
|
+
if ($raw -is [System.IO.MemoryStream]) { Emit-Bytes $raw.ToArray() }
|
|
151
|
+
if ($raw -is [byte[]]) { Emit-Bytes $raw }
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
# File drop (screenshot tool saves to file then copies path)
|
|
155
|
+
if ($data.GetDataPresent([System.Windows.Forms.DataFormats]::FileDrop)) {
|
|
156
|
+
$files = [string[]]$data.GetData([System.Windows.Forms.DataFormats]::FileDrop)
|
|
157
|
+
foreach ($file in $files) {
|
|
158
|
+
if ($file -match '[.](png|jpg|jpeg|webp|gif)$' -and [System.IO.File]::Exists($file)) {
|
|
159
|
+
Emit-Bytes ([System.IO.File]::ReadAllBytes($file))
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
# Fallback: GetImage
|
|
166
|
+
if ([System.Windows.Forms.Clipboard]::ContainsImage()) {
|
|
167
|
+
$img = [System.Windows.Forms.Clipboard]::GetImage()
|
|
168
|
+
if ($null -ne $img) {
|
|
169
|
+
$ms = New-Object System.IO.MemoryStream
|
|
170
|
+
try {
|
|
171
|
+
$img.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
|
|
172
|
+
Emit-Bytes $ms.ToArray()
|
|
173
|
+
} finally {
|
|
174
|
+
$ms.Dispose()
|
|
175
|
+
$img.Dispose()
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
exit 1
|
|
180
|
+
`;
|
|
181
|
+
try {
|
|
182
|
+
const out = execFileSync("powershell.exe", ["-NoProfile", "-Command", "-"], {
|
|
183
|
+
input: script,
|
|
184
|
+
timeout: CLIPBOARD_TIMEOUT_MS,
|
|
185
|
+
maxBuffer: CLIPBOARD_MAX_BUFFER,
|
|
186
|
+
windowsHide: true,
|
|
187
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
188
|
+
});
|
|
189
|
+
if (out.length > 0)
|
|
190
|
+
return out;
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// PowerShell failed
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Read an image from the system clipboard. Returns null if clipboard is empty
|
|
199
|
+
* or contains no image. Platform-specific: macOS (pngpaste/osascript), Linux
|
|
200
|
+
* (xclip/wl-paste), Windows (PowerShell).
|
|
201
|
+
*/
|
|
202
|
+
export function readClipboardImage(platform = process.platform) {
|
|
203
|
+
switch (platform) {
|
|
204
|
+
case "darwin": return readMacClipboard();
|
|
205
|
+
case "linux": return readLinuxClipboard();
|
|
206
|
+
case "win32": return readWindowsClipboard();
|
|
207
|
+
default: return null;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// ── High-level API ──────────────────────────────────────────────────────────
|
|
211
|
+
/**
|
|
212
|
+
* Read clipboard image, validate, save to .omk/screenshots/, and return
|
|
213
|
+
* both the file path and base64 data URI for wire protocol use.
|
|
214
|
+
*/
|
|
215
|
+
export function pasteClipboardImage(projectRoot) {
|
|
216
|
+
const buf = readClipboardImage();
|
|
217
|
+
if (!buf || buf.length === 0) {
|
|
218
|
+
return { ok: false, error: "No image found in clipboard" };
|
|
219
|
+
}
|
|
220
|
+
if (buf.length > MAX_IMAGE_BYTES) {
|
|
221
|
+
return { ok: false, error: `Clipboard image exceeds ${MAX_IMAGE_BYTES / (1024 * 1024)} MB` };
|
|
222
|
+
}
|
|
223
|
+
const ext = detectImageExt(buf);
|
|
224
|
+
if (!ext) {
|
|
225
|
+
return { ok: false, error: "Clipboard content is not a recognized image format (PNG/JPG/WebP/GIF)" };
|
|
226
|
+
}
|
|
227
|
+
const { fullPath, relativePath } = generatePath(projectRoot, ext);
|
|
228
|
+
writeFileSync(fullPath, buf);
|
|
229
|
+
const base64 = buf.toString("base64");
|
|
230
|
+
return {
|
|
231
|
+
ok: true,
|
|
232
|
+
path: fullPath,
|
|
233
|
+
relativePath: `./${relativePath}`,
|
|
234
|
+
dataUri: toDataUri(base64, ext),
|
|
235
|
+
base64,
|
|
236
|
+
ext,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Read an image file from disk, validate, and return base64 data URI.
|
|
241
|
+
* Used for --image <file> flag support.
|
|
242
|
+
*/
|
|
243
|
+
export function readImageFile(filePath) {
|
|
244
|
+
if (!existsSync(filePath)) {
|
|
245
|
+
return { ok: false, error: `File not found: ${filePath}` };
|
|
246
|
+
}
|
|
247
|
+
const buf = readFileSync(filePath);
|
|
248
|
+
if (buf.length > MAX_IMAGE_BYTES) {
|
|
249
|
+
return { ok: false, error: `File exceeds ${MAX_IMAGE_BYTES / (1024 * 1024)} MB` };
|
|
250
|
+
}
|
|
251
|
+
const ext = detectImageExt(buf);
|
|
252
|
+
if (!ext) {
|
|
253
|
+
return { ok: false, error: "File is not a recognized image format (PNG/JPG/WebP/GIF)" };
|
|
254
|
+
}
|
|
255
|
+
const base64 = buf.toString("base64");
|
|
256
|
+
return {
|
|
257
|
+
ok: true,
|
|
258
|
+
path: filePath,
|
|
259
|
+
dataUri: toDataUri(base64, ext),
|
|
260
|
+
base64,
|
|
261
|
+
ext,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
@@ -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.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# 2026-06-09 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-09 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-09 Required Init Checklist
|
|
2
|
+
|
|
3
|
+
**Run ID:** chat-2026-06-09T00-01-07-440Z-28177
|
|
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-09 OMK Chat Plan
|
|
2
|
+
|
|
3
|
+
**Run ID:** chat-2026-06-09T00-01-07-440Z-28177
|
|
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.
|