@kal-elsam/kairo-runtime 0.16.0 → 0.17.0
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 +50 -0
- package/package.json +2 -1
- package/scripts/cockpit-smoke.mjs +1 -1
- package/scripts/ux-smoke-test.sh +3 -3
- package/src/cli.js +96 -11
- package/src/global/agent-capabilities/create-capability-adapter.js +2 -2
- package/src/global/architect/architect-cli.js +76 -0
- package/src/global/architect/architect-codex.js +146 -0
- package/src/global/architect/architect-manager.js +125 -0
- package/src/global/architect/architect-store.js +377 -0
- package/src/global/architect/architect-types.js +47 -0
- package/src/global/cli-help.js +10 -1
- package/src/global/cockpit/app.js +475 -0
- package/src/global/cockpit/card.js +111 -0
- package/src/global/cockpit/cli.js +33 -0
- package/src/global/cockpit/gauge.js +31 -0
- package/src/global/cockpit/project-overlay.js +683 -0
- package/src/global/cockpit/rows.js +148 -0
- package/src/global/cockpit/theme.js +118 -0
- package/src/global/cockpit/view.js +1263 -0
- package/src/global/conversation/bootstrap-analyzer-adapters.js +251 -0
- package/src/global/conversation/cli.js +53 -0
- package/src/global/conversation/codex-sandbox.js +230 -0
- package/src/global/conversation/cursor-sandbox.js +215 -0
- package/src/global/conversation/project-analysis.js +204 -0
- package/src/global/conversation/project-profile.js +178 -0
- package/src/global/conversation/project-router.js +149 -0
- package/src/global/conversation/project-strategy-store.js +64 -0
- package/src/global/conversation/project-strategy.js +514 -0
- package/src/global/conversation/sanitized-snapshot.js +169 -0
- package/src/global/conversation/secret-scanner.js +71 -0
- package/src/global/conversation/service.js +1063 -0
- package/src/global/conversation/session-store.js +75 -0
- package/src/global/conversation/transcript-store.js +79 -0
- package/src/global/conversation/ui.js +195 -0
- package/src/global/intelligence/capability-scoring.js +480 -0
- package/src/global/intelligence/execution-router.js +444 -0
- package/src/global/intelligence/kairo-telemetry-source.js +59 -0
- package/src/global/intelligence/kairobench-runner.js +85 -0
- package/src/global/intelligence/kairobench-source.js +34 -0
- package/src/global/intelligence/kairobench-tasks.js +47 -0
- package/src/global/intelligence/model-candidate-catalog.js +456 -0
- package/src/global/intelligence/model-capability-registry-sources.js +145 -0
- package/src/global/intelligence/model-capability-registry.js +125 -0
- package/src/global/intelligence/model-intelligence.js +1646 -0
- package/src/global/intelligence/official-benchmark-snapshots.js +162 -0
- package/src/global/intelligence/quick-ask.js +149 -0
- package/src/global/intelligence/role-profiles.js +251 -0
- package/src/global/intelligence/skill-catalog.js +67 -0
- package/src/global/intelligence/subscription-pressure-source.js +41 -0
- package/src/global/mcp/kairo-mcp.js +51 -18
- package/src/global/mcp/work-snapshot-rule.js +4 -2
- package/src/global/mcp/workspace-binding.js +88 -0
- package/src/global/mcp/workspace-mcp-entry.js +74 -0
- package/src/global/mcp-install.js +8 -1
- package/src/global/observability/artificial-analysis-models.js +118 -0
- package/src/global/observability/claude-models.js +31 -0
- package/src/global/observability/claude-usage.js +112 -0
- package/src/global/observability/codex-models.js +96 -0
- package/src/global/observability/codex-usage.js +160 -0
- package/src/global/observability/cursor-auth.js +88 -0
- package/src/global/observability/cursor-models.js +101 -0
- package/src/global/observability/huggingface-leaderboard.js +97 -0
- package/src/global/observability/opencode-models.js +101 -0
- package/src/global/observability/opencode-usage.js +162 -0
- package/src/global/paths.js +49 -2
- package/src/global/profile.js +23 -1
- package/src/global/runtime/execution-adapters/claude.js +63 -30
- package/src/global/runtime/execution-adapters/codex.js +9 -2
- package/src/global/runtime/execution-adapters/create-execution-adapter.js +6 -1
- package/src/global/runtime/execution-adapters/opencode.js +83 -18
- package/src/global/runtime/execution-worktree-manager.js +924 -0
- package/src/global/runtime/execution-worktree-orchestrator.js +194 -0
- package/src/global/runtime/execution-worktree-store.js +83 -0
- package/src/global/runtime/execution-worktree-types.js +45 -0
- package/src/global/runtime/run-events.js +38 -0
- package/src/global/runtime/run-manager.js +22 -6
- package/src/global/runtime/run-supervisor.js +41 -12
- package/src/global/runtime/usage-manager.js +96 -0
- package/src/global/runtime/usage-store.js +69 -0
- package/src/global/runtime/usage-types.js +62 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { mkdir, readdir, readFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { harnessHomePaths } from "../paths.js";
|
|
5
|
+
import { EXECUTION_ADAPTER_IDS } from "./execution-adapters/index.js";
|
|
6
|
+
import { writeAtomicJson } from "./write-atomic-json.js";
|
|
7
|
+
|
|
8
|
+
const writeLocks = new Map();
|
|
9
|
+
|
|
10
|
+
export function getUsageDir(homeDir) {
|
|
11
|
+
return harnessHomePaths(homeDir).usageDir;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The one real boundary a provider id gets validated at before it's ever
|
|
16
|
+
* used to build a path — the same defense-in-depth role
|
|
17
|
+
* assertWorktreeId/assertTaskId already play elsewhere. Provider ids are a
|
|
18
|
+
* real, closed list (the same one execution-adapters/index.js resolves
|
|
19
|
+
* against), never a free-form string, so an unknown one is always a bug
|
|
20
|
+
* to surface loudly rather than a path to silently sanitize.
|
|
21
|
+
*/
|
|
22
|
+
function usagePath(homeDir, provider) {
|
|
23
|
+
if (!EXECUTION_ADAPTER_IDS.includes(provider)) {
|
|
24
|
+
throw new Error(`Unknown provider "${provider}" for usage tracking. Use ${EXECUTION_ADAPTER_IDS.join(", ")}.`);
|
|
25
|
+
}
|
|
26
|
+
return join(getUsageDir(homeDir), `${provider}.json`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function readProviderUsage(homeDir, provider) {
|
|
30
|
+
const statePath = usagePath(homeDir, provider);
|
|
31
|
+
if (!existsSync(statePath)) return null;
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
return JSON.parse(await readFile(statePath, "utf8"));
|
|
35
|
+
} catch (error) {
|
|
36
|
+
throw new Error(`Invalid provider usage state at ${statePath}: ${error.message}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Read-modify-write is serialized per provider — same real race protection run-store.js's writeRunState already relies on. */
|
|
41
|
+
export async function writeProviderUsage(homeDir, provider, record) {
|
|
42
|
+
const key = provider;
|
|
43
|
+
const previous = writeLocks.get(key) ?? Promise.resolve();
|
|
44
|
+
const next = previous.then(async () => {
|
|
45
|
+
const usageDir = getUsageDir(homeDir);
|
|
46
|
+
await mkdir(usageDir, { recursive: true });
|
|
47
|
+
await writeAtomicJson(usagePath(homeDir, provider), record);
|
|
48
|
+
return record;
|
|
49
|
+
});
|
|
50
|
+
writeLocks.set(key, next.catch(() => {}));
|
|
51
|
+
return next;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function listProviderUsage(homeDir) {
|
|
55
|
+
const usageDir = getUsageDir(homeDir);
|
|
56
|
+
if (!existsSync(usageDir)) return [];
|
|
57
|
+
|
|
58
|
+
const entries = await readdir(usageDir, { withFileTypes: true });
|
|
59
|
+
const records = [];
|
|
60
|
+
for (const entry of entries) {
|
|
61
|
+
if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
|
|
62
|
+
const provider = entry.name.slice(0, -".json".length);
|
|
63
|
+
if (!EXECUTION_ADAPTER_IDS.includes(provider)) continue;
|
|
64
|
+
const record = await readProviderUsage(homeDir, provider);
|
|
65
|
+
if (record) records.push(record);
|
|
66
|
+
}
|
|
67
|
+
records.sort((left, right) => left.provider.localeCompare(right.provider));
|
|
68
|
+
return records;
|
|
69
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export const USAGE_SCHEMA = "kairo.provider-usage/v1";
|
|
2
|
+
|
|
3
|
+
// HEALTHY: well under budget. MODERATE/CONSERVE: real, rising signal — no
|
|
4
|
+
// enforcement yet. CRITICAL: the last tier before the gate. EXHAUSTED: the
|
|
5
|
+
// real, enforced stop — assertProviderNotExhausted (usage-manager.js)
|
|
6
|
+
// refuses to start a new run for a provider in this tier.
|
|
7
|
+
export const USAGE_TIERS = Object.freeze({
|
|
8
|
+
HEALTHY: "healthy",
|
|
9
|
+
MODERATE: "moderate",
|
|
10
|
+
CONSERVE: "conserve",
|
|
11
|
+
CRITICAL: "critical",
|
|
12
|
+
EXHAUSTED: "exhausted"
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// Fractions of the configured budget. Ratios strictly below MODERATE stay
|
|
16
|
+
// HEALTHY; at/above 1.0 (100% of budget) is always EXHAUSTED, regardless
|
|
17
|
+
// of where CRITICAL is set.
|
|
18
|
+
export const USAGE_TIER_THRESHOLDS = Object.freeze({
|
|
19
|
+
MODERATE: 0.5,
|
|
20
|
+
CONSERVE: 0.75,
|
|
21
|
+
CRITICAL: 0.9
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Classifies real, cumulative consumption against a real, configured
|
|
26
|
+
* budget — never against a single run's own usage. No budget configured
|
|
27
|
+
* (null) means no gate exists for this provider yet: always HEALTHY,
|
|
28
|
+
* exactly mirroring how a null profile.tokenBudget already means "no
|
|
29
|
+
* per-request gate" elsewhere in this codebase (see router.js).
|
|
30
|
+
*/
|
|
31
|
+
export function classifyUsageTier(consumedTokens, budgetTokens) {
|
|
32
|
+
if (budgetTokens == null || !Number.isFinite(budgetTokens) || budgetTokens <= 0) {
|
|
33
|
+
return USAGE_TIERS.HEALTHY;
|
|
34
|
+
}
|
|
35
|
+
const consumed = Number.isFinite(consumedTokens) ? Math.max(0, consumedTokens) : 0;
|
|
36
|
+
const ratio = consumed / budgetTokens;
|
|
37
|
+
|
|
38
|
+
if (ratio >= 1) return USAGE_TIERS.EXHAUSTED;
|
|
39
|
+
if (ratio >= USAGE_TIER_THRESHOLDS.CRITICAL) return USAGE_TIERS.CRITICAL;
|
|
40
|
+
if (ratio >= USAGE_TIER_THRESHOLDS.CONSERVE) return USAGE_TIERS.CONSERVE;
|
|
41
|
+
if (ratio >= USAGE_TIER_THRESHOLDS.MODERATE) return USAGE_TIERS.MODERATE;
|
|
42
|
+
return USAGE_TIERS.HEALTHY;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function isProviderExhausted(tier) {
|
|
46
|
+
return tier === USAGE_TIERS.EXHAUSTED;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function createProviderUsageRecord(provider) {
|
|
50
|
+
const now = new Date().toISOString();
|
|
51
|
+
return {
|
|
52
|
+
schema: USAGE_SCHEMA,
|
|
53
|
+
provider,
|
|
54
|
+
totalInputTokens: 0,
|
|
55
|
+
totalOutputTokens: 0,
|
|
56
|
+
totalTokens: 0,
|
|
57
|
+
totalCost: 0,
|
|
58
|
+
runCount: 0,
|
|
59
|
+
createdAt: now,
|
|
60
|
+
updatedAt: now
|
|
61
|
+
};
|
|
62
|
+
}
|