open-multi-agent-kit 0.78.8 → 0.79.3
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 +131 -2
- package/CHANGELOG.md +32 -0
- package/CLAUDE.md +105 -3
- package/DESIGN.md +141 -117
- package/MATURITY.md +7 -12
- package/README.md +66 -347
- package/ROADMAP.md +33 -47
- package/dist/adapters/kimi/runner.js +2 -2
- package/dist/brand/theme.js +2 -2
- package/dist/cli/register-basic-commands.js +3 -2
- package/dist/cli/register-mcp-dag-cron-screenshot-commands.js +1 -1
- package/dist/cli/root.d.ts +1 -0
- package/dist/cli/root.js +2 -0
- package/dist/cli/runtime/command-bus.js +14 -1
- package/dist/cli/theme/terminal-capability.js +1 -1
- package/dist/cli/theme/theme-registry.js +90 -2
- package/dist/cli/ui/event.d.ts +1 -0
- package/dist/cli/ui/neon-grid-renderer.d.ts +8 -0
- package/dist/cli/ui/neon-grid-renderer.js +84 -14
- package/dist/cli/ui/plain-renderer.js +3 -1
- package/dist/cli/ui/system24-renderer.js +3 -1
- package/dist/cli/v2/chat-repl.d.ts +2 -1
- package/dist/cli/v2/chat-repl.js +58 -2
- package/dist/cli/v2/cli-v2-skeleton.js +7 -4
- package/dist/cli/v2/interactive-prompt.js +4 -3
- package/dist/commands/auth.js +2 -0
- package/dist/commands/chat/native-root-loop.d.ts +1 -0
- package/dist/commands/chat/native-root-loop.js +162 -13
- package/dist/commands/chat/runtime.js +9 -0
- package/dist/commands/chat/slash/commands/routing.js +31 -1
- package/dist/commands/chat/utils.js +3 -1
- package/dist/commands/cockpit/render.js +2 -1
- package/dist/commands/doctor/checks.js +2 -2
- package/dist/commands/init/core.js +2 -2
- package/dist/commands/init.js +2 -2
- package/dist/commands/mcp/config.js +38 -16
- package/dist/commands/mcp/doctor.js +7 -8
- package/dist/commands/mcp/list.js +4 -3
- package/dist/commands/mcp/shared.d.ts +4 -1
- package/dist/commands/mcp/shared.js +21 -3
- package/dist/commands/mcp/test.js +13 -12
- package/dist/commands/model.js +4 -0
- package/dist/commands/provider.js +5 -1
- package/dist/commands/version.d.ts +1 -0
- package/dist/commands/version.js +18 -0
- package/dist/contracts/command.d.ts +25 -0
- package/dist/contracts/command.js +1 -0
- package/dist/contracts/evidence-bundle.d.ts +52 -0
- package/dist/contracts/evidence-bundle.js +1 -0
- package/dist/contracts/index.d.ts +2 -0
- package/dist/contracts/index.js +2 -0
- package/dist/contracts/web-bridge.d.ts +1 -1
- package/dist/contracts/web-bridge.js +1 -1
- package/dist/evidence/bundle-validator.d.ts +7 -0
- package/dist/evidence/bundle-validator.js +103 -0
- package/dist/evidence/index.d.ts +5 -0
- package/dist/evidence/index.js +2 -0
- package/dist/evidence/proof-trust.js +2 -10
- package/dist/evidence/trust-calibration.d.ts +25 -0
- package/dist/evidence/trust-calibration.js +151 -0
- package/dist/mcp/omk-project-server.js +1 -1
- package/dist/metrics/provenance-ratio.d.ts +16 -0
- package/dist/metrics/provenance-ratio.js +33 -0
- package/dist/orchestration/dag.d.ts +17 -0
- package/dist/orchestration/ensemble-decision.d.ts +2 -0
- package/dist/orchestration/ensemble-decision.js +4 -0
- package/dist/orchestration/hedge-persona-weights.d.ts +25 -0
- package/dist/orchestration/hedge-persona-weights.js +43 -0
- package/dist/orchestration/parallel-ui.d.ts +1 -0
- package/dist/orchestration/parallel-ui.js +12 -3
- package/dist/orchestration/route-calibration.d.ts +27 -0
- package/dist/orchestration/route-calibration.js +123 -0
- package/dist/orchestration/routing/mcp-config.js +5 -1
- package/dist/orchestration/routing/types.d.ts +21 -0
- package/dist/orchestration/routing.d.ts +10 -0
- package/dist/orchestration/routing.js +89 -3
- package/dist/providers/model-registry.d.ts +2 -1
- package/dist/providers/model-registry.js +76 -4
- package/dist/providers/provider-runtime.js +9 -1
- package/dist/providers/thinking-levels.js +2 -0
- package/dist/providers/types.d.ts +1 -1
- package/dist/runtime/glm-api-runtime.d.ts +4 -0
- package/dist/runtime/glm-api-runtime.js +15 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/kimi-api-runtime.d.ts +6 -1
- package/dist/runtime/kimi-api-runtime.js +10 -4
- package/dist/runtime/recovery-artifact-store.d.ts +39 -0
- package/dist/runtime/recovery-artifact-store.js +111 -0
- package/dist/runtime/runtime-backed-task-runner.js +10 -0
- package/dist/runtime/runtime-bootstrap.js +17 -1
- package/dist/runtime/slash-commands.js +38 -5
- package/dist/schema/command.schema.d.ts +121 -0
- package/dist/schema/command.schema.js +25 -0
- package/dist/schema/envelope.schema.d.ts +2 -2
- package/dist/schema/evidence-bundle.schema.d.ts +196 -0
- package/dist/schema/evidence-bundle.schema.js +38 -0
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.js +2 -0
- package/dist/schema/proof-bundle.schema.d.ts +2 -2
- package/dist/theme/external-theme-adapters.d.ts +27 -0
- package/dist/theme/external-theme-adapters.js +52 -0
- package/dist/theme/library-effects.d.ts +12 -0
- package/dist/theme/library-effects.js +47 -0
- package/dist/theme/parallel.js +3 -2
- package/dist/tui/terminal-frame-renderer.d.ts +9 -1
- package/dist/tui/terminal-frame-renderer.js +77 -7
- package/dist/util/chat-cockpit.d.ts +3 -1
- package/dist/util/chat-cockpit.js +44 -5
- package/dist/util/command-envelope.d.ts +19 -0
- package/dist/util/command-envelope.js +31 -0
- package/dist/util/events-logger.d.ts +1 -1
- package/dist/util/events-logger.js +23 -16
- package/dist/util/fs/mcp-diagnose.js +2 -1
- package/dist/util/fs/mcp-runtime-config.js +14 -2
- package/dist/util/i18n.js +2 -2
- package/dist/util/screenshot-store.d.ts +7 -0
- package/dist/util/screenshot-store.js +30 -0
- package/dist/util/terminal-kit-bridge.d.ts +24 -0
- package/dist/util/terminal-kit-bridge.js +60 -0
- package/dist/util/terminal-owner.d.ts +1 -0
- package/dist/util/terminal-owner.js +31 -0
- package/dist/version.d.ts +3 -1
- package/dist/version.js +4 -0
- package/docs/2026-05-18-project-direction.md +1 -1
- package/docs/2026-06-14/critical-issues.md +19 -0
- package/docs/2026-06-14/improvements.md +15 -0
- package/docs/2026-06-14/init-checklist.md +25 -0
- package/docs/2026-06-14/plan.md +20 -0
- package/docs/2026-06-15/critical-issues.md +19 -0
- package/docs/2026-06-15/improvements.md +15 -0
- package/docs/2026-06-15/init-checklist.md +25 -0
- package/docs/2026-06-15/plan.md +20 -0
- package/docs/claims.md +85 -0
- package/docs/comparisons/omk-vs-claude-code.md +31 -0
- package/docs/comparisons/omk-vs-codex.md +33 -0
- package/docs/comparisons/omk-vs-mcp-agent.md +33 -0
- package/docs/comparisons/omk-vs-opencode.md +32 -0
- package/docs/decision-layer-calibration.md +20 -0
- package/docs/geo-eval-prompts.md +53 -0
- package/docs/getting-started.md +3 -31
- package/docs/headroom-omk-setup-guide.md +2 -2
- package/docs/integrations/adaptorch.md +46 -0
- package/docs/native-root-runtime-algorithms.md +2 -303
- package/docs/native-root-runtime-hardening.md +1 -1
- package/docs/provider-maturity.md +1 -1
- package/docs/use-cases/evidence-gated-coding-agents.md +52 -0
- package/docs/use-cases/no-kimi-mode.md +38 -0
- package/docs/use-cases/provider-routing-for-ai-coding.md +36 -0
- package/docs/use-cases/replayable-agent-runs.md +40 -0
- package/docs/use-cases/scoped-mcp-for-coding-agents.md +34 -0
- package/docs/versioning.md +9 -3
- package/docs/what-is-omk.md +64 -0
- package/llms.txt +28 -18
- package/package.json +7 -2
- package/readmeasset/.npmignore +3 -0
- package/readmeasset/ASSET_INDEX.md +3 -0
- package/readmeasset/ASSET_PROVENANCE.md +6 -0
- package/readmeasset/omk-adaptorch-ouroboros-supermemory.svg +95 -0
- package/readmeasset/omk-init-control-loop.svg +118 -0
- package/readmeasset/omk-parallel-subagents.svg +97 -0
- package/templates/web-bridge/chrome-extension/background.js +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { runShell } from "../util/shell.js";
|
|
2
2
|
import { readOmkProvidersConfig, writeOmkProvidersConfig, } from "./deepseek/deepseek-config.js";
|
|
3
3
|
import { DEFAULT_AUTHORITY_PROVIDER } from "./types.js";
|
|
4
|
-
export const KNOWN_PROVIDER_IDS = ["mimo", "kimi", "deepseek", "qwen", "codex", "openrouter", "anthropic"];
|
|
4
|
+
export const KNOWN_PROVIDER_IDS = ["mimo", "kimi", "deepseek", "qwen", "codex", "openrouter", "anthropic", "glm"];
|
|
5
5
|
export const QWEN_DASHSCOPE_COMPAT_BASE_URL = "https://dashscope-intl.aliyuncs.com/compatible-mode/v1";
|
|
6
6
|
export const OPENROUTER_COMPAT_BASE_URL = "https://openrouter.ai/api/v1";
|
|
7
7
|
const DEFAULT_PROVIDER_CONFIGS = {
|
|
@@ -121,6 +121,29 @@ const DEFAULT_PROVIDER_CONFIGS = {
|
|
|
121
121
|
planKind: "qwen-coding-plan",
|
|
122
122
|
routing: "advisory",
|
|
123
123
|
},
|
|
124
|
+
glm: {
|
|
125
|
+
enabled: false,
|
|
126
|
+
kind: "openai-compatible",
|
|
127
|
+
baseUrl: "https://open.bigmodel.cn/api/paas/v1",
|
|
128
|
+
apiKeyEnv: "BIGMODEL_API_KEY",
|
|
129
|
+
defaultModel: "glm-5.2",
|
|
130
|
+
aliases: {
|
|
131
|
+
default: "glm-5.2",
|
|
132
|
+
glm: "glm-5.2",
|
|
133
|
+
"glm-5": "glm-5",
|
|
134
|
+
"glm-5.2": "glm-5.2",
|
|
135
|
+
"glm-5-air": "glm-5-air",
|
|
136
|
+
"glm-5-airx": "glm-5-airx",
|
|
137
|
+
},
|
|
138
|
+
capabilities: ["read", "research", "review", "qa", "advisory"],
|
|
139
|
+
contextWindow: 128_000,
|
|
140
|
+
reservedOutputTokens: 4096,
|
|
141
|
+
wireApi: "openai-chat-completions",
|
|
142
|
+
auth: { method: "api-key-env" },
|
|
143
|
+
profileType: "runtime",
|
|
144
|
+
planKind: "runtime",
|
|
145
|
+
routing: "advisory",
|
|
146
|
+
},
|
|
124
147
|
openrouter: {
|
|
125
148
|
enabled: false,
|
|
126
149
|
kind: "openai-compatible",
|
|
@@ -176,6 +199,8 @@ export function normalizeProviderId(value) {
|
|
|
176
199
|
return "openrouter";
|
|
177
200
|
if (lower === "anthropic-api" || lower === "anthropic-direct" || lower === "claude-api")
|
|
178
201
|
return "anthropic";
|
|
202
|
+
if (lower === "glm" || lower === "bigmodel" || lower === "zhipu")
|
|
203
|
+
return "glm";
|
|
179
204
|
return lower;
|
|
180
205
|
}
|
|
181
206
|
export function parseProviderModelArg(value) {
|
|
@@ -202,11 +227,22 @@ export function parseProviderModelArg(value) {
|
|
|
202
227
|
const slash = modelPart.indexOf("/");
|
|
203
228
|
if (slash > 0) {
|
|
204
229
|
const provider = normalizeProviderId(modelPart.slice(0, slash));
|
|
205
|
-
|
|
230
|
+
let modelSegment = modelPart.slice(slash + 1);
|
|
231
|
+
const inlineThinking = extractInlineThinkingLevel(modelSegment);
|
|
232
|
+
if (inlineThinking && !thinkingLevel) {
|
|
233
|
+
modelSegment = inlineThinking.modelPart;
|
|
234
|
+
thinkingLevel = inlineThinking.thinkingLevel;
|
|
235
|
+
}
|
|
236
|
+
const arg = { model: normalizeModelAlias(modelSegment) };
|
|
206
237
|
if (provider !== "auto")
|
|
207
238
|
arg.provider = provider;
|
|
208
239
|
return withThinking(arg);
|
|
209
240
|
}
|
|
241
|
+
const inlineThinking = extractInlineThinkingLevel(modelPart);
|
|
242
|
+
if (inlineThinking && !thinkingLevel) {
|
|
243
|
+
modelPart = inlineThinking.modelPart;
|
|
244
|
+
thinkingLevel = inlineThinking.thinkingLevel;
|
|
245
|
+
}
|
|
210
246
|
const model = normalizeModelAlias(modelPart);
|
|
211
247
|
if (model === "codex-cli")
|
|
212
248
|
return withThinking({ provider: "codex", model });
|
|
@@ -214,6 +250,8 @@ export function parseProviderModelArg(value) {
|
|
|
214
250
|
return withThinking({ provider: "deepseek", model });
|
|
215
251
|
if (model.startsWith("claude-") || model.startsWith("gpt-") || model.startsWith("anthropic/"))
|
|
216
252
|
return withThinking({ provider: "openrouter", model });
|
|
253
|
+
if (model.startsWith("glm-"))
|
|
254
|
+
return withThinking({ provider: "glm", model });
|
|
217
255
|
return withThinking({ model });
|
|
218
256
|
}
|
|
219
257
|
function isThinkingLevelSuffix(suffix) {
|
|
@@ -225,6 +263,19 @@ function isThinkingLevelSuffix(suffix) {
|
|
|
225
263
|
];
|
|
226
264
|
return thinkingAliases.includes(suffix);
|
|
227
265
|
}
|
|
266
|
+
function extractInlineThinkingLevel(value) {
|
|
267
|
+
const lower = value.trim().toLowerCase().replace(/[_\s]+/g, "-");
|
|
268
|
+
const match = lower.match(/^(glm-?5(?:\.\d+)?)-?([a-z_ -]+)$/);
|
|
269
|
+
if (!match)
|
|
270
|
+
return undefined;
|
|
271
|
+
const suffix = match[2]?.replace(/[-\s]+/g, "_") ?? "";
|
|
272
|
+
if (!isThinkingLevelSuffix(suffix))
|
|
273
|
+
return undefined;
|
|
274
|
+
const modelPart = match[1]?.replace(/^glm-?/, "glm-");
|
|
275
|
+
if (!modelPart)
|
|
276
|
+
return undefined;
|
|
277
|
+
return { modelPart, thinkingLevel: suffix.replace(/_/g, "-") };
|
|
278
|
+
}
|
|
228
279
|
export function normalizeModelAlias(value) {
|
|
229
280
|
const trimmed = value.trim();
|
|
230
281
|
const lower = trimmed.toLowerCase().replace(/[_\s]+/g, "-");
|
|
@@ -248,6 +299,17 @@ export function normalizeModelAlias(value) {
|
|
|
248
299
|
return "qwen3-max";
|
|
249
300
|
if (lower === "qwen-3.7-max" || lower === "qwen3.7-max" || lower === "qwen-3-7-max")
|
|
250
301
|
return "qwen3-max";
|
|
302
|
+
const inlineThinking = extractInlineThinkingLevel(trimmed);
|
|
303
|
+
if (inlineThinking)
|
|
304
|
+
return inlineThinking.modelPart;
|
|
305
|
+
if (lower === "glm-5" || lower === "glm5")
|
|
306
|
+
return "glm-5";
|
|
307
|
+
if (lower === "glm-5.2" || lower === "glm5.2")
|
|
308
|
+
return "glm-5.2";
|
|
309
|
+
if (lower === "glm-5-air")
|
|
310
|
+
return "glm-5-air";
|
|
311
|
+
if (lower === "glm-5-airx" || lower === "glm-5-air-x")
|
|
312
|
+
return "glm-5-airx";
|
|
251
313
|
return trimmed;
|
|
252
314
|
}
|
|
253
315
|
export async function readProviderRegistry(options = {}) {
|
|
@@ -373,7 +435,8 @@ export async function providerDoctorStatus(provider, options = {}) {
|
|
|
373
435
|
: "Codex CLI missing/disabled or authentication not verified; configured authority fallback is active",
|
|
374
436
|
};
|
|
375
437
|
}
|
|
376
|
-
const
|
|
438
|
+
const env = options.env ?? process.env;
|
|
439
|
+
const apiKeySet = entry.apiKeyEnv ? Boolean(resolveProviderApiKeyEnvValue(entry, env)?.trim()) : undefined;
|
|
377
440
|
const needsKey = entry.kind === "openai-compatible";
|
|
378
441
|
const available = entry.enabled && (!needsKey || apiKeySet === true);
|
|
379
442
|
return {
|
|
@@ -400,6 +463,14 @@ export async function providerDoctorStatus(provider, options = {}) {
|
|
|
400
463
|
: entry.disabledReason ?? "Provider disabled; configured authority fallback is active",
|
|
401
464
|
};
|
|
402
465
|
}
|
|
466
|
+
function resolveProviderApiKeyEnvValue(entry, env) {
|
|
467
|
+
const primary = entry.apiKeyEnv ? env[entry.apiKeyEnv] : undefined;
|
|
468
|
+
if (primary?.trim())
|
|
469
|
+
return primary;
|
|
470
|
+
if (entry.id === "glm")
|
|
471
|
+
return env.GLM_API_KEY ?? env.BIGMODEL_API_KEY;
|
|
472
|
+
return primary;
|
|
473
|
+
}
|
|
403
474
|
function mergeProviderConfig(id, stored) {
|
|
404
475
|
const known = isKnownProviderId(id) ? DEFAULT_PROVIDER_CONFIGS[id] : undefined;
|
|
405
476
|
const aliases = { ...(known?.aliases ?? {}), ...(stored?.aliases ?? {}) };
|
|
@@ -540,11 +611,12 @@ export async function resolveUserModelAlias(input, options = {}) {
|
|
|
540
611
|
const aliased = aliases[normalizeUserAlias(raw)];
|
|
541
612
|
const candidate = aliased ?? raw;
|
|
542
613
|
const parsed = parseProviderModelArg(candidate);
|
|
543
|
-
if (parsed.provider || parsed.model !== raw) {
|
|
614
|
+
if (parsed.provider || parsed.model !== raw || parsed.thinkingLevel) {
|
|
544
615
|
return {
|
|
545
616
|
input: raw,
|
|
546
617
|
provider: parsed.provider,
|
|
547
618
|
model: parsed.model ?? candidate,
|
|
619
|
+
thinkingLevel: parsed.thinkingLevel,
|
|
548
620
|
source: aliased ? "user-alias" : "literal",
|
|
549
621
|
};
|
|
550
622
|
}
|
|
@@ -69,7 +69,7 @@ export async function createProviderBackedTaskRunner(options) {
|
|
|
69
69
|
for (const entry of registry) {
|
|
70
70
|
if (!shouldUseOpenAICompatibleProvider(entry, providerPolicy))
|
|
71
71
|
continue;
|
|
72
|
-
const apiKey = entry
|
|
72
|
+
const apiKey = resolveOpenAICompatibleApiKey(entry, process.env);
|
|
73
73
|
if (apiKey && entry.baseUrl) {
|
|
74
74
|
if (entry.wireApi === "anthropic-messages") {
|
|
75
75
|
providerRunners[entry.id] = createAnthropicMessagesReadOnlyTaskRunner({
|
|
@@ -192,6 +192,14 @@ function shouldUseOpenAICompatibleProvider(entry, providerPolicy) {
|
|
|
192
192
|
return false;
|
|
193
193
|
return providerPolicy === "auto" || providerPolicy === entry.id;
|
|
194
194
|
}
|
|
195
|
+
function resolveOpenAICompatibleApiKey(entry, env) {
|
|
196
|
+
const primary = entry.apiKeyEnv ? env[entry.apiKeyEnv] : undefined;
|
|
197
|
+
if (primary?.trim())
|
|
198
|
+
return primary;
|
|
199
|
+
if (entry.id === "glm")
|
|
200
|
+
return env.GLM_API_KEY ?? env.BIGMODEL_API_KEY;
|
|
201
|
+
return primary;
|
|
202
|
+
}
|
|
195
203
|
function providerModelDefault(entry) {
|
|
196
204
|
return {
|
|
197
205
|
model: entry.defaultModel,
|
|
@@ -4,6 +4,7 @@ const PROVIDER_LEVELS = {
|
|
|
4
4
|
mimo: ["medium", "high", "xhigh", "max"],
|
|
5
5
|
deepseek: ["off", "high", "xhigh", "max"],
|
|
6
6
|
qwen: ["off", "medium", "high", "max"],
|
|
7
|
+
glm: ["off", "medium", "high", "max"],
|
|
7
8
|
anthropic: ["minimal", "low", "medium", "high", "xhigh", "max"],
|
|
8
9
|
openrouter: ["minimal", "low", "medium", "high", "xhigh", "max"],
|
|
9
10
|
duckcoding: ["minimal", "low", "medium", "high", "xhigh", "max"],
|
|
@@ -13,6 +14,7 @@ const MODEL_LEVELS = [
|
|
|
13
14
|
{ pattern: /kimi|mimo/i, levels: PROVIDER_LEVELS.kimi },
|
|
14
15
|
{ pattern: /deepseek/i, levels: PROVIDER_LEVELS.deepseek },
|
|
15
16
|
{ pattern: /qwen/i, levels: PROVIDER_LEVELS.qwen },
|
|
17
|
+
{ pattern: /glm/i, levels: PROVIDER_LEVELS.glm },
|
|
16
18
|
{ pattern: /duck[-_ ]?coding/i, levels: PROVIDER_LEVELS.duckcoding },
|
|
17
19
|
{ pattern: /fable|claude|sonnet|opus|haiku|anthropic|gpt|openrouter/i, levels: PROVIDER_LEVELS.anthropic },
|
|
18
20
|
{ pattern: /codex/i, levels: PROVIDER_LEVELS.codex },
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TaskResult, TaskRunner } from "../contracts/orchestration.js";
|
|
2
|
-
export type KnownProviderId = "mimo" | "kimi" | "deepseek" | "codex" | "qwen" | "openrouter" | "anthropic";
|
|
2
|
+
export type KnownProviderId = "mimo" | "kimi" | "deepseek" | "codex" | "qwen" | "openrouter" | "anthropic" | "glm";
|
|
3
3
|
export type ProviderId = KnownProviderId | (string & {});
|
|
4
4
|
export type ProviderPolicy = "auto" | ProviderId;
|
|
5
5
|
export declare const DEFAULT_AUTHORITY_PROVIDER: ProviderId;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { AgentRuntime } from "./agent-runtime.js";
|
|
2
|
+
import { type KimiApiRuntimeOptions } from "./kimi-api-runtime.js";
|
|
3
|
+
export type GlmApiRuntimeOptions = KimiApiRuntimeOptions;
|
|
4
|
+
export declare function createGlmApiRuntime(options?: GlmApiRuntimeOptions): AgentRuntime;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { KimiApiRuntime } from "./kimi-api-runtime.js";
|
|
2
|
+
export function createGlmApiRuntime(options = {}) {
|
|
3
|
+
const env = options.env ?? process.env;
|
|
4
|
+
return new KimiApiRuntime({
|
|
5
|
+
...options,
|
|
6
|
+
id: options.id ?? "glm-api",
|
|
7
|
+
providerId: "glm",
|
|
8
|
+
providerName: "Zhipu GLM",
|
|
9
|
+
apiKeyEnvName: env.GLM_API_KEY && !env.BIGMODEL_API_KEY ? "GLM_API_KEY" : "BIGMODEL_API_KEY",
|
|
10
|
+
priority: options.priority ?? 84,
|
|
11
|
+
apiKey: options.apiKey ?? env.BIGMODEL_API_KEY ?? env.GLM_API_KEY,
|
|
12
|
+
model: options.model ?? env.GLM_MODEL ?? "glm-5.2",
|
|
13
|
+
baseUrl: options.baseUrl ?? env.GLM_BASE_URL ?? env.BIGMODEL_BASE_URL ?? "https://open.bigmodel.cn/api/paas/v1",
|
|
14
|
+
});
|
|
15
|
+
}
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -5,4 +5,5 @@ export { type RuntimeRouterOptions, type RuntimeRouteDecision, type NodeIntent,
|
|
|
5
5
|
export { type ToolProxyOptions, type ToolResultCompression, createToolProxy, } from "./tool-proxy.js";
|
|
6
6
|
export { type KimiWireRuntimeOptions, createKimiWireRuntime, } from "./kimi-wire-runtime.js";
|
|
7
7
|
export { type KimiPrintRuntimeOptions, createKimiPrintRuntime, } from "./kimi-print-runtime.js";
|
|
8
|
+
export { type RecoveryArtifactRef, type RecoveryArtifactStore, type RecoveryArtifactStoreOptions, type RecoveryCaptureInput, type RecoveryFailureKind, createRecoveryArtifactStore, } from "./recovery-artifact-store.js";
|
|
8
9
|
export { type ContextBudgetReport, type DroppedContextItem, type ContextTokenBreakdown, type ContextBudgetOptimizationResult, type ContextItemEvidenceStats, createContextBudgetOptimizer, estimateTokens, breakdownCapsuleTokens, } from "./context-budget-optimizer.js";
|
package/dist/runtime/index.js
CHANGED
|
@@ -5,4 +5,5 @@ export { createRuntimeRouter, } from './runtime-router.js';
|
|
|
5
5
|
export { createToolProxy, } from "./tool-proxy.js";
|
|
6
6
|
export { createKimiWireRuntime, } from "./kimi-wire-runtime.js";
|
|
7
7
|
export { createKimiPrintRuntime, } from "./kimi-print-runtime.js";
|
|
8
|
+
export { createRecoveryArtifactStore, } from "./recovery-artifact-store.js";
|
|
8
9
|
export { createContextBudgetOptimizer, estimateTokens, breakdownCapsuleTokens, } from "./context-budget-optimizer.js";
|
|
@@ -8,6 +8,9 @@ import type { AgentRuntime, AgentRunResult, AgentResult, AgentTask, RuntimeCapab
|
|
|
8
8
|
import type { ContextCapsule } from "./context-capsule.js";
|
|
9
9
|
export interface KimiApiRuntimeOptions {
|
|
10
10
|
id?: string;
|
|
11
|
+
providerId?: string;
|
|
12
|
+
providerName?: string;
|
|
13
|
+
apiKeyEnvName?: string;
|
|
11
14
|
priority?: number;
|
|
12
15
|
apiKey?: string;
|
|
13
16
|
model?: string;
|
|
@@ -34,13 +37,15 @@ export declare function createKimiApiRuntime(options?: KimiApiRuntimeOptions): A
|
|
|
34
37
|
export declare const createKimiWireRuntime: typeof createKimiApiRuntime;
|
|
35
38
|
export declare class KimiApiRuntime implements AgentRuntime {
|
|
36
39
|
readonly id: string;
|
|
37
|
-
readonly providerId
|
|
40
|
+
readonly providerId: string;
|
|
38
41
|
readonly legacy = false;
|
|
39
42
|
readonly runtimeMode = "api";
|
|
40
43
|
readonly kind = "api";
|
|
41
44
|
readonly priority: number;
|
|
42
45
|
readonly capabilities: RuntimeCapabilities;
|
|
43
46
|
private readonly apiKey;
|
|
47
|
+
private readonly apiKeyEnvName;
|
|
48
|
+
private readonly providerName;
|
|
44
49
|
private readonly model;
|
|
45
50
|
private readonly baseUrl;
|
|
46
51
|
constructor(options?: KimiApiRuntimeOptions);
|
|
@@ -76,6 +76,7 @@ function mapToolCalls(apiToolCalls, context) {
|
|
|
76
76
|
export function createKimiApiRuntime(options = {}) {
|
|
77
77
|
const env = options.env ?? process.env;
|
|
78
78
|
return new KimiApiRuntime({
|
|
79
|
+
...options,
|
|
79
80
|
apiKey: options.apiKey ?? env.KIMI_API_KEY,
|
|
80
81
|
model: options.model ?? env.KIMI_MODEL,
|
|
81
82
|
baseUrl: options.baseUrl ?? env.KIMI_BASE_URL,
|
|
@@ -85,7 +86,7 @@ export function createKimiApiRuntime(options = {}) {
|
|
|
85
86
|
export const createKimiWireRuntime = createKimiApiRuntime;
|
|
86
87
|
export class KimiApiRuntime {
|
|
87
88
|
id;
|
|
88
|
-
providerId
|
|
89
|
+
providerId;
|
|
89
90
|
legacy = false;
|
|
90
91
|
runtimeMode = "api";
|
|
91
92
|
kind = "api";
|
|
@@ -104,11 +105,16 @@ export class KimiApiRuntime {
|
|
|
104
105
|
supportsToolCalling: true,
|
|
105
106
|
};
|
|
106
107
|
apiKey;
|
|
108
|
+
apiKeyEnvName;
|
|
109
|
+
providerName;
|
|
107
110
|
model;
|
|
108
111
|
baseUrl;
|
|
109
112
|
constructor(options = {}) {
|
|
110
113
|
this.id = options.id ?? "kimi-api";
|
|
114
|
+
this.providerId = options.providerId ?? "kimi";
|
|
111
115
|
this.priority = options.priority ?? 90;
|
|
116
|
+
this.apiKeyEnvName = options.apiKeyEnvName ?? "KIMI_API_KEY";
|
|
117
|
+
this.providerName = options.providerName ?? "Moonshot";
|
|
112
118
|
this.apiKey = options.apiKey ?? process.env.KIMI_API_KEY;
|
|
113
119
|
this.model = options.model ?? process.env.KIMI_MODEL ?? "kimi-k2-6";
|
|
114
120
|
this.baseUrl = (options.baseUrl ?? "https://api.moonshot.cn/v1").replace(/\/+$/, "");
|
|
@@ -132,7 +138,7 @@ export class KimiApiRuntime {
|
|
|
132
138
|
return {
|
|
133
139
|
runtimeId: this.id,
|
|
134
140
|
available,
|
|
135
|
-
reason: available ? undefined :
|
|
141
|
+
reason: available ? undefined : `${this.apiKeyEnvName} is not set`,
|
|
136
142
|
checkedAt: new Date().toISOString(),
|
|
137
143
|
};
|
|
138
144
|
}
|
|
@@ -171,7 +177,7 @@ export class KimiApiRuntime {
|
|
|
171
177
|
output: "",
|
|
172
178
|
exitCode: 1,
|
|
173
179
|
thinking: "",
|
|
174
|
-
metadata: { error:
|
|
180
|
+
metadata: { error: `${this.apiKeyEnvName} is not set` },
|
|
175
181
|
};
|
|
176
182
|
}
|
|
177
183
|
if (task.capabilities.write ||
|
|
@@ -246,7 +252,7 @@ export class KimiApiRuntime {
|
|
|
246
252
|
output: "",
|
|
247
253
|
exitCode: 1,
|
|
248
254
|
thinking: "",
|
|
249
|
-
metadata: { error:
|
|
255
|
+
metadata: { error: `${this.providerName} API error ${response.status}: ${errorText}` },
|
|
250
256
|
};
|
|
251
257
|
}
|
|
252
258
|
if (useStreaming) {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type RecoveryFailureKind = "rate_limit" | "quota" | "timeout" | "provider_crash" | "provider_error" | "abort" | "unknown";
|
|
2
|
+
export interface RecoveryCaptureInput {
|
|
3
|
+
readonly runId: string;
|
|
4
|
+
readonly provider: string;
|
|
5
|
+
readonly nodeId: string;
|
|
6
|
+
readonly attemptId?: string;
|
|
7
|
+
readonly failureKind: RecoveryFailureKind;
|
|
8
|
+
readonly exitCode?: number;
|
|
9
|
+
readonly cwd?: string;
|
|
10
|
+
readonly command?: readonly string[];
|
|
11
|
+
readonly stdout?: string;
|
|
12
|
+
readonly stderr?: string;
|
|
13
|
+
readonly sessionPaths?: readonly string[];
|
|
14
|
+
readonly metadata?: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
export interface RecoveryArtifactRef {
|
|
17
|
+
readonly schemaVersion: "omk.recovery-artifact.v1";
|
|
18
|
+
readonly runId: string;
|
|
19
|
+
readonly provider: string;
|
|
20
|
+
readonly nodeId: string;
|
|
21
|
+
readonly attemptId?: string;
|
|
22
|
+
readonly failureKind: RecoveryFailureKind;
|
|
23
|
+
readonly dir: string;
|
|
24
|
+
readonly manifestPath: string;
|
|
25
|
+
readonly sessionHandlePath?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface RecoveryArtifactStore {
|
|
28
|
+
captureFailure(input: RecoveryCaptureInput): Promise<RecoveryArtifactRef>;
|
|
29
|
+
cleanup(input: {
|
|
30
|
+
runId: string;
|
|
31
|
+
provider?: string;
|
|
32
|
+
nodeId?: string;
|
|
33
|
+
}): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
export interface RecoveryArtifactStoreOptions {
|
|
36
|
+
readonly root?: string;
|
|
37
|
+
readonly maxLogBytes?: number;
|
|
38
|
+
}
|
|
39
|
+
export declare function createRecoveryArtifactStore(options?: RecoveryArtifactStoreOptions): RecoveryArtifactStore;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { lstat, mkdir, readFile, readlink, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { basename, join } from "node:path";
|
|
4
|
+
import { redactSecrets } from "../orchestration/state-persister.js";
|
|
5
|
+
import { getRunPath, validateRunId } from "../util/run-store.js";
|
|
6
|
+
const DEFAULT_MAX_LOG_BYTES = 128 * 1024;
|
|
7
|
+
const MAX_SEGMENT_LENGTH = 80;
|
|
8
|
+
function safeSegment(value, fallback) {
|
|
9
|
+
const sanitized = value
|
|
10
|
+
.replace(/[^A-Za-z0-9._-]/g, "-")
|
|
11
|
+
.replace(/-+/g, "-")
|
|
12
|
+
.replace(/^-|-$/g, "")
|
|
13
|
+
.slice(0, MAX_SEGMENT_LENGTH);
|
|
14
|
+
return sanitized && sanitized !== "." && sanitized !== ".." ? sanitized : fallback;
|
|
15
|
+
}
|
|
16
|
+
function redactText(value, maxBytes) {
|
|
17
|
+
if (!value)
|
|
18
|
+
return "";
|
|
19
|
+
const bounded = Buffer.byteLength(value, "utf8") > maxBytes
|
|
20
|
+
? Buffer.from(value, "utf8").subarray(-maxBytes).toString("utf8")
|
|
21
|
+
: value;
|
|
22
|
+
const redacted = redactSecrets(bounded);
|
|
23
|
+
return typeof redacted === "string" ? redacted : JSON.stringify(redacted);
|
|
24
|
+
}
|
|
25
|
+
function sha256Text(value) {
|
|
26
|
+
return createHash("sha256").update(value).digest("hex");
|
|
27
|
+
}
|
|
28
|
+
async function inspectSessionPath(path) {
|
|
29
|
+
const base = { path, name: basename(path) };
|
|
30
|
+
try {
|
|
31
|
+
const stat = await lstat(path);
|
|
32
|
+
if (stat.isSymbolicLink()) {
|
|
33
|
+
return { ...base, kind: "symlink", target: await readlink(path).catch(() => "unreadable"), copied: false };
|
|
34
|
+
}
|
|
35
|
+
if (stat.isFile()) {
|
|
36
|
+
const bytes = await readFile(path);
|
|
37
|
+
return { ...base, kind: "file", size: bytes.length, sha256: createHash("sha256").update(bytes).digest("hex"), copied: false };
|
|
38
|
+
}
|
|
39
|
+
if (stat.isDirectory()) {
|
|
40
|
+
return { ...base, kind: "directory", copied: false };
|
|
41
|
+
}
|
|
42
|
+
return { ...base, kind: "other", copied: false };
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
return { ...base, kind: "missing", error: error instanceof Error ? error.message : String(error), copied: false };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export function createRecoveryArtifactStore(options = {}) {
|
|
49
|
+
const maxLogBytes = options.maxLogBytes ?? DEFAULT_MAX_LOG_BYTES;
|
|
50
|
+
function runDir(runId) {
|
|
51
|
+
return getRunPath(validateRunId(runId), undefined, options.root);
|
|
52
|
+
}
|
|
53
|
+
function recoveryDir(input) {
|
|
54
|
+
const base = join(runDir(input.runId), "recovery");
|
|
55
|
+
const provider = input.provider ? safeSegment(input.provider, "provider") : undefined;
|
|
56
|
+
const nodeId = input.nodeId ? safeSegment(input.nodeId, "node") : undefined;
|
|
57
|
+
return provider ? nodeId ? join(base, provider, nodeId) : join(base, provider) : base;
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
async captureFailure(input) {
|
|
61
|
+
const runId = validateRunId(input.runId);
|
|
62
|
+
const provider = safeSegment(input.provider, "provider");
|
|
63
|
+
const nodeId = safeSegment(input.nodeId, "node");
|
|
64
|
+
const dir = recoveryDir({ runId, provider, nodeId });
|
|
65
|
+
await mkdir(dir, { recursive: true });
|
|
66
|
+
const stdout = redactText(input.stdout, maxLogBytes);
|
|
67
|
+
const stderr = redactText(input.stderr, maxLogBytes);
|
|
68
|
+
const stdoutPath = join(dir, "stdout.log");
|
|
69
|
+
const stderrPath = join(dir, "stderr.redacted.log");
|
|
70
|
+
await writeFile(stdoutPath, stdout, "utf8");
|
|
71
|
+
await writeFile(stderrPath, stderr, "utf8");
|
|
72
|
+
const sessionHandlePath = join(dir, "session-handle.json");
|
|
73
|
+
const sessionHandles = await Promise.all((input.sessionPaths ?? []).map(inspectSessionPath));
|
|
74
|
+
await writeFile(sessionHandlePath, `${JSON.stringify({ schemaVersion: "omk.recovery-session.v1", sessionPaths: sessionHandles }, null, 2)}\n`, "utf8");
|
|
75
|
+
const manifestPath = join(dir, "manifest.json");
|
|
76
|
+
const manifest = {
|
|
77
|
+
schemaVersion: "omk.recovery-artifact.v1",
|
|
78
|
+
runId,
|
|
79
|
+
provider,
|
|
80
|
+
nodeId,
|
|
81
|
+
...(input.attemptId ? { attemptId: safeSegment(input.attemptId, "attempt") } : {}),
|
|
82
|
+
failureKind: input.failureKind,
|
|
83
|
+
...(input.exitCode !== undefined ? { exitCode: input.exitCode } : {}),
|
|
84
|
+
capturedAt: new Date().toISOString(),
|
|
85
|
+
...(input.cwd ? { cwd: input.cwd } : {}),
|
|
86
|
+
command: input.command ? input.command.map((part) => redactText(part, maxLogBytes)) : [],
|
|
87
|
+
logs: {
|
|
88
|
+
stdout: { path: "stdout.log", sha256: sha256Text(stdout), bytes: Buffer.byteLength(stdout, "utf8") },
|
|
89
|
+
stderr: { path: "stderr.redacted.log", sha256: sha256Text(stderr), bytes: Buffer.byteLength(stderr, "utf8"), redacted: true },
|
|
90
|
+
},
|
|
91
|
+
sessionHandle: { path: "session-handle.json", count: sessionHandles.length },
|
|
92
|
+
metadata: redactSecrets(input.metadata ?? {}),
|
|
93
|
+
};
|
|
94
|
+
await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
|
|
95
|
+
return {
|
|
96
|
+
schemaVersion: "omk.recovery-artifact.v1",
|
|
97
|
+
runId,
|
|
98
|
+
provider,
|
|
99
|
+
nodeId,
|
|
100
|
+
...(input.attemptId ? { attemptId: safeSegment(input.attemptId, "attempt") } : {}),
|
|
101
|
+
failureKind: input.failureKind,
|
|
102
|
+
dir,
|
|
103
|
+
manifestPath,
|
|
104
|
+
sessionHandlePath,
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
async cleanup(input) {
|
|
108
|
+
await rm(recoveryDir(input), { recursive: true, force: true });
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
@@ -24,6 +24,7 @@ import { LocalLlmRuntime } from "./local-llm-runtime.js";
|
|
|
24
24
|
import { checkCommand } from "../util/shell.js";
|
|
25
25
|
import { createMimoApiRuntime } from "./mimo-api-runtime.js";
|
|
26
26
|
import { createKimiApiRuntime } from "./kimi-api-runtime.js";
|
|
27
|
+
import { createGlmApiRuntime } from "./glm-api-runtime.js";
|
|
27
28
|
import { getUserHome } from "../util/fs.js";
|
|
28
29
|
async function createDefaultRuntimeRegistry(options) {
|
|
29
30
|
const registry = createRuntimeRegistry();
|
|
@@ -43,6 +44,15 @@ async function createDefaultRuntimeRegistry(options) {
|
|
|
43
44
|
if (kimiApiKey) {
|
|
44
45
|
registry.register(createKimiApiRuntime({ apiKey: kimiApiKey }));
|
|
45
46
|
}
|
|
47
|
+
// ── GLM API runtime (Zhipu AI — OpenAI-compatible advisory lane) ──
|
|
48
|
+
const glmKey = options.env?.BIGMODEL_API_KEY
|
|
49
|
+
?? options.env?.GLM_API_KEY
|
|
50
|
+
?? process.env.BIGMODEL_API_KEY
|
|
51
|
+
?? process.env.GLM_API_KEY
|
|
52
|
+
?? readConfiguredProviderApiKey("glm");
|
|
53
|
+
if (glmKey) {
|
|
54
|
+
registry.register(createGlmApiRuntime({ apiKey: glmKey, env: options.env }));
|
|
55
|
+
}
|
|
46
56
|
// ── codex-cli ──
|
|
47
57
|
const codexBin = options.env?.CODEX_BIN ?? process.env.CODEX_BIN ?? "codex";
|
|
48
58
|
if (await checkCommand(codexBin).catch(() => false)) {
|
|
@@ -35,6 +35,16 @@ function detectProvider(provider, env) {
|
|
|
35
35
|
authHint: "Set DEEPSEEK_API_KEY env var",
|
|
36
36
|
modelHint: env.DEEPSEEK_MODEL ?? "deepseek-chat",
|
|
37
37
|
};
|
|
38
|
+
case "glm":
|
|
39
|
+
case "bigmodel":
|
|
40
|
+
case "zhipu":
|
|
41
|
+
return {
|
|
42
|
+
envKey: env.GLM_API_KEY && !env.BIGMODEL_API_KEY ? "GLM_API_KEY" : "BIGMODEL_API_KEY",
|
|
43
|
+
sessionMode: "api-turn",
|
|
44
|
+
installHint: "export BIGMODEL_API_KEY=...",
|
|
45
|
+
authHint: "Set BIGMODEL_API_KEY env var",
|
|
46
|
+
modelHint: env.GLM_MODEL ?? "glm-5.2",
|
|
47
|
+
};
|
|
38
48
|
case "local":
|
|
39
49
|
case "llama":
|
|
40
50
|
case "local-llm":
|
|
@@ -82,11 +92,15 @@ async function resolveAutoProvider(env) {
|
|
|
82
92
|
return { provider: "kimi", runtimeId: "kimi-api" };
|
|
83
93
|
if (defaultModel.startsWith("deepseek") && env.DEEPSEEK_API_KEY)
|
|
84
94
|
return { provider: "deepseek", runtimeId: "deepseek-api" };
|
|
95
|
+
if (defaultModel.startsWith("glm") && (env.BIGMODEL_API_KEY || env.GLM_API_KEY || providerConfigHasApiKey(configContent, "glm")))
|
|
96
|
+
return { provider: "glm", runtimeId: "glm-api" };
|
|
85
97
|
}
|
|
86
98
|
if (providerConfigHasApiKey(configContent, "mimo"))
|
|
87
99
|
return { provider: "mimo", runtimeId: "mimo-api" };
|
|
88
100
|
if (providerConfigHasApiKey(configContent, "kimi"))
|
|
89
101
|
return { provider: "kimi", runtimeId: "kimi-api" };
|
|
102
|
+
if (providerConfigHasApiKey(configContent, "glm"))
|
|
103
|
+
return { provider: "glm", runtimeId: "glm-api" };
|
|
90
104
|
}
|
|
91
105
|
// 2. Check for API keys in env
|
|
92
106
|
if (env.MIMO_API_KEY)
|
|
@@ -95,6 +109,8 @@ async function resolveAutoProvider(env) {
|
|
|
95
109
|
return { provider: "kimi", runtimeId: "kimi-api" };
|
|
96
110
|
if (env.DEEPSEEK_API_KEY)
|
|
97
111
|
return { provider: "deepseek", runtimeId: "deepseek-api" };
|
|
112
|
+
if (env.BIGMODEL_API_KEY || env.GLM_API_KEY)
|
|
113
|
+
return { provider: "glm", runtimeId: "glm-api" };
|
|
98
114
|
if (env.LOCAL_LLM_BASE_URL)
|
|
99
115
|
return { provider: "local-llm", runtimeId: "local-llm" };
|
|
100
116
|
// 3. CLI binary detection (lowest priority)
|
|
@@ -145,7 +161,7 @@ export async function resolveRuntimeBootstrap(options) {
|
|
|
145
161
|
}
|
|
146
162
|
else if (info.envKey) {
|
|
147
163
|
runtimeOk = Boolean(env[info.envKey]);
|
|
148
|
-
if (!runtimeOk && (selectedProvider === "mimo" || selectedProvider === "kimi")) {
|
|
164
|
+
if (!runtimeOk && (selectedProvider === "mimo" || selectedProvider === "kimi" || selectedProvider === "glm")) {
|
|
149
165
|
const configContent = readHomeProviderConfig(env, ".omk");
|
|
150
166
|
runtimeOk = configContent ? providerConfigHasApiKey(configContent, selectedProvider) : false;
|
|
151
167
|
}
|
|
@@ -91,6 +91,24 @@ function renderSlashResultContent(result, fallback) {
|
|
|
91
91
|
lines.push(" Persistent default unchanged; use `omk model use` to persist.\n");
|
|
92
92
|
return lines.join("\n");
|
|
93
93
|
}
|
|
94
|
+
case "think.show": {
|
|
95
|
+
const provider = stringValue(payload, "provider", "auto");
|
|
96
|
+
const model = stringValue(payload, "model", "auto");
|
|
97
|
+
const current = stringValue(payload, "currentThinking", "");
|
|
98
|
+
const levels = stringListValue(payload, "supportedThinkingLevels");
|
|
99
|
+
const levelLine = levels
|
|
100
|
+
.map((level) => `${level === current ? "●" : "○"} ${level}`)
|
|
101
|
+
.join(" ");
|
|
102
|
+
return [
|
|
103
|
+
"\n OMK Thinking Control · choose level",
|
|
104
|
+
` Target: ${provider}/${model}`,
|
|
105
|
+
levelLine ? ` ${levelLine}` : undefined,
|
|
106
|
+
levels.length > 0 ? ` Choose directly: ${levels.map((level) => `/think ${level}`).join(" | ")}` : undefined,
|
|
107
|
+
" Cycle only when explicit: /think next",
|
|
108
|
+
` Active: ${current || "not selected"}`,
|
|
109
|
+
"",
|
|
110
|
+
].filter((line) => typeof line === "string").join("\n");
|
|
111
|
+
}
|
|
94
112
|
case "think.set": {
|
|
95
113
|
const thinking = stringValue(payload, "thinking");
|
|
96
114
|
const modelVariant = stringValue(payload, "modelVariant", "auto");
|
|
@@ -105,12 +123,12 @@ function renderSlashResultContent(result, fallback) {
|
|
|
105
123
|
case "status.show":
|
|
106
124
|
return `\n Status: ${stringValue(payload, "provider")}/${stringValue(payload, "model")} theme=${stringValue(payload, "theme")}`;
|
|
107
125
|
case "theme.show": {
|
|
108
|
-
const current = stringValue(payload, "current", stringValue(payload, "theme", "omk"));
|
|
126
|
+
const current = stringValue(payload, "current", stringValue(payload, "theme", "omk-control-grid-dark"));
|
|
109
127
|
const available = stringListValue(payload, "available");
|
|
110
128
|
return `\n Theme: ${current}${available.length > 0 ? `\n Available: ${available.join(", ")}` : ""}`;
|
|
111
129
|
}
|
|
112
130
|
case "theme.set":
|
|
113
|
-
return `\n Theme updated: ${stringValue(payload, "theme", "omk")}`;
|
|
131
|
+
return `\n Theme updated: ${stringValue(payload, "theme", "omk-control-grid-dark")}`;
|
|
114
132
|
case "help": {
|
|
115
133
|
const commands = stringListValue(payload, "commands");
|
|
116
134
|
return [`\n OMK Slash Commands`, ...commands.map((command) => ` - ${command}`), ""].join("\n");
|
|
@@ -301,7 +319,22 @@ class ThinkCommandHandler {
|
|
|
301
319
|
sideEffects: [{ type: "thinking_changed", thinking: variant, modelVariant }],
|
|
302
320
|
};
|
|
303
321
|
}
|
|
304
|
-
|
|
322
|
+
if (!requested) {
|
|
323
|
+
return {
|
|
324
|
+
kind: "status",
|
|
325
|
+
command: "think.show",
|
|
326
|
+
payload: {
|
|
327
|
+
provider: input.state.provider ?? "auto",
|
|
328
|
+
model: input.state.model ?? "auto",
|
|
329
|
+
currentThinking: input.state.thinking,
|
|
330
|
+
supportedThinkingLevels: levels,
|
|
331
|
+
usage: `/think ${levels.join(" | ")} | next | variant <name>`,
|
|
332
|
+
},
|
|
333
|
+
renderMode: "theme",
|
|
334
|
+
sideEffects: [],
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
const level = requested === "next" || requested === "tab"
|
|
305
338
|
? nextThinkingLevel(input.state.thinking, input.state.provider, input.state.model)
|
|
306
339
|
: normalizeThinkingLevel(requested);
|
|
307
340
|
if (!level || !levels.includes(level)) {
|
|
@@ -346,9 +379,9 @@ class ThemeCommandHandler {
|
|
|
346
379
|
kind: "status",
|
|
347
380
|
command: "theme.show",
|
|
348
381
|
payload: {
|
|
349
|
-
current: input.state.theme ?? "omk",
|
|
382
|
+
current: input.state.theme ?? "omk-control-grid-dark",
|
|
350
383
|
usage: "/theme <name>",
|
|
351
|
-
available: ["omk", "night-city", "omk-control", "green-rain", "rust-forge", "neon-circuit", "minimal", "mono", "dark", "light"],
|
|
384
|
+
available: ["omk-control-grid-dark", "night-city", "omk-control", "green-rain", "rust-forge", "neon-circuit", "omk", "minimal", "mono", "dark", "light"],
|
|
352
385
|
},
|
|
353
386
|
renderMode: "theme",
|
|
354
387
|
sideEffects: [],
|