@mrace07/kairo 0.1.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/README.md +141 -0
- package/dist/application/coding-agent.d.ts +85 -0
- package/dist/application/coding-agent.js +765 -0
- package/dist/application/context-manager.d.ts +22 -0
- package/dist/application/context-manager.js +174 -0
- package/dist/application/context-selector.d.ts +11 -0
- package/dist/application/context-selector.js +74 -0
- package/dist/application/evaluated-agent.d.ts +7 -0
- package/dist/application/evaluated-agent.js +16 -0
- package/dist/application/evaluation-comparison.d.ts +34 -0
- package/dist/application/evaluation-comparison.js +91 -0
- package/dist/application/evaluation-harness.d.ts +19 -0
- package/dist/application/evaluation-harness.js +217 -0
- package/dist/application/failure-analyzer.d.ts +5 -0
- package/dist/application/failure-analyzer.js +37 -0
- package/dist/application/interaction-routing.d.ts +9 -0
- package/dist/application/interaction-routing.js +20 -0
- package/dist/application/live-evaluation.d.ts +8 -0
- package/dist/application/live-evaluation.js +185 -0
- package/dist/application/model-routing.d.ts +12 -0
- package/dist/application/model-routing.js +40 -0
- package/dist/application/model-system-instruction.d.ts +4 -0
- package/dist/application/model-system-instruction.js +4 -0
- package/dist/application/self-evaluation.d.ts +26 -0
- package/dist/application/self-evaluation.js +394 -0
- package/dist/application/task-metrics.d.ts +31 -0
- package/dist/application/task-metrics.js +42 -0
- package/dist/application/verification-planner.d.ts +12 -0
- package/dist/application/verification-planner.js +97 -0
- package/dist/domain/models.d.ts +247 -0
- package/dist/domain/models.js +1 -0
- package/dist/domain/ports.d.ts +87 -0
- package/dist/domain/ports.js +1 -0
- package/dist/domain/provider-error.d.ts +18 -0
- package/dist/domain/provider-error.js +17 -0
- package/dist/infrastructure/configuration/config.d.ts +24 -0
- package/dist/infrastructure/configuration/config.js +79 -0
- package/dist/infrastructure/filesystem/platform-paths.d.ts +8 -0
- package/dist/infrastructure/filesystem/platform-paths.js +18 -0
- package/dist/infrastructure/persistence/sqlite-session-store.d.ts +82 -0
- package/dist/infrastructure/persistence/sqlite-session-store.js +447 -0
- package/dist/infrastructure/providers/gemini-provider.d.ts +14 -0
- package/dist/infrastructure/providers/gemini-provider.js +90 -0
- package/dist/infrastructure/providers/groq-provider.d.ts +16 -0
- package/dist/infrastructure/providers/groq-provider.js +101 -0
- package/dist/infrastructure/providers/jev-safety-advisor.d.ts +18 -0
- package/dist/infrastructure/providers/jev-safety-advisor.js +95 -0
- package/dist/infrastructure/providers/mistral-provider.d.ts +15 -0
- package/dist/infrastructure/providers/mistral-provider.js +137 -0
- package/dist/infrastructure/providers/openrouter-provider.d.ts +15 -0
- package/dist/infrastructure/providers/openrouter-provider.js +104 -0
- package/dist/infrastructure/providers/provider-recovery.d.ts +10 -0
- package/dist/infrastructure/providers/provider-recovery.js +108 -0
- package/dist/infrastructure/providers/provider-registry.d.ts +22 -0
- package/dist/infrastructure/providers/provider-registry.js +67 -0
- package/dist/infrastructure/repository/repository-awareness.d.ts +12 -0
- package/dist/infrastructure/repository/repository-awareness.js +25 -0
- package/dist/infrastructure/repository/repository-profiler.d.ts +35 -0
- package/dist/infrastructure/repository/repository-profiler.js +498 -0
- package/dist/infrastructure/security/macos-keychain-store.d.ts +17 -0
- package/dist/infrastructure/security/macos-keychain-store.js +73 -0
- package/dist/infrastructure/tools/workspace-tools.d.ts +30 -0
- package/dist/infrastructure/tools/workspace-tools.js +321 -0
- package/dist/interface/cli/evaluation-comparison-report.d.ts +6 -0
- package/dist/interface/cli/evaluation-comparison-report.js +46 -0
- package/dist/interface/cli/evaluation-report.d.ts +14 -0
- package/dist/interface/cli/evaluation-report.js +122 -0
- package/dist/interface/cli/index.d.ts +2 -0
- package/dist/interface/cli/index.js +238 -0
- package/dist/interface/cli/provider-setup.d.ts +16 -0
- package/dist/interface/cli/provider-setup.js +86 -0
- package/dist/interface/cli/repl.d.ts +7 -0
- package/dist/interface/cli/repl.js +19 -0
- package/dist/interface/cli/task-trace.d.ts +7 -0
- package/dist/interface/cli/task-trace.js +48 -0
- package/dist/interface/cli/tui.d.ts +147 -0
- package/dist/interface/cli/tui.js +910 -0
- package/package.json +61 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
export type Role = "user" | "model" | "tool";
|
|
2
|
+
export type ProviderId = "gemini" | "groq" | "mistral";
|
|
3
|
+
/** Credential-only services are deliberately separate from selectable coding providers. */
|
|
4
|
+
export type CredentialId = ProviderId | "jev";
|
|
5
|
+
export interface ModelSelection {
|
|
6
|
+
provider: ProviderId;
|
|
7
|
+
model: string;
|
|
8
|
+
}
|
|
9
|
+
/** Metadata-only events avoid copying source code, credentials, or command output into traces. */
|
|
10
|
+
export interface TaskEvent {
|
|
11
|
+
id?: number;
|
|
12
|
+
taskId: string;
|
|
13
|
+
kind: "status" | "model_started" | "provider_retry" | "provider_retry_wait" | "provider_exhausted" | "model_finished" | "tool_requested" | "tool_started" | "tool_finished" | "approval" | "autonomous" | "repair" | "verification" | "verification_selected" | "plan_submitted" | "jev_requested" | "jev_completed" | "jev_failed";
|
|
14
|
+
createdAt: number;
|
|
15
|
+
operationId?: string;
|
|
16
|
+
name?: string;
|
|
17
|
+
outcome?: string;
|
|
18
|
+
durationMs?: number;
|
|
19
|
+
exitCode?: number | null;
|
|
20
|
+
}
|
|
21
|
+
export interface Message {
|
|
22
|
+
role: Role;
|
|
23
|
+
content: string;
|
|
24
|
+
createdAt: number;
|
|
25
|
+
toolCallId?: string;
|
|
26
|
+
toolName?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface ToolCall {
|
|
29
|
+
id: string;
|
|
30
|
+
name: string;
|
|
31
|
+
args: Record<string, unknown>;
|
|
32
|
+
}
|
|
33
|
+
export interface ModelTurn {
|
|
34
|
+
text: string;
|
|
35
|
+
toolCalls: ToolCall[];
|
|
36
|
+
}
|
|
37
|
+
export interface ToolResult {
|
|
38
|
+
ok: boolean;
|
|
39
|
+
output: string;
|
|
40
|
+
exitCode?: number | null;
|
|
41
|
+
durationMs?: number;
|
|
42
|
+
}
|
|
43
|
+
export interface VerificationCandidate {
|
|
44
|
+
label: "test" | "typecheck" | "lint" | "build";
|
|
45
|
+
command: string;
|
|
46
|
+
/** Discovery metadata explains a recommendation without retaining source or output. */
|
|
47
|
+
scope?: "focused" | "broad";
|
|
48
|
+
reason?: string;
|
|
49
|
+
evidence?: RepositoryEvidence[];
|
|
50
|
+
}
|
|
51
|
+
/** Records why one safe verification command was selected for a task. */
|
|
52
|
+
export interface VerificationSelection {
|
|
53
|
+
command: string;
|
|
54
|
+
label: VerificationCandidate["label"] | "custom";
|
|
55
|
+
scope: "focused" | "broad";
|
|
56
|
+
reason: string;
|
|
57
|
+
source: "recommended" | "model" | "manual" | "repair";
|
|
58
|
+
}
|
|
59
|
+
export interface RepositoryFile {
|
|
60
|
+
path: string;
|
|
61
|
+
terms: string[];
|
|
62
|
+
symbols: string[];
|
|
63
|
+
imports: string[];
|
|
64
|
+
relatedFiles: string[];
|
|
65
|
+
}
|
|
66
|
+
export type RepositoryFileKind = "instruction" | "manifest" | "ci" | "build" | "documentation" | "source" | "test" | "config" | "other";
|
|
67
|
+
export interface RepositoryEntry {
|
|
68
|
+
path: string;
|
|
69
|
+
kind: RepositoryFileKind;
|
|
70
|
+
size: number;
|
|
71
|
+
mtimeMs: number;
|
|
72
|
+
contentHash?: string;
|
|
73
|
+
}
|
|
74
|
+
export interface RepositoryFingerprint {
|
|
75
|
+
value: string;
|
|
76
|
+
kind: "git" | "filesystem";
|
|
77
|
+
gitRoot?: string;
|
|
78
|
+
branch?: string;
|
|
79
|
+
head?: string;
|
|
80
|
+
}
|
|
81
|
+
export interface RepositoryEvidence {
|
|
82
|
+
path: string;
|
|
83
|
+
kind: "manifest" | "lockfile" | "config" | "ci" | "build";
|
|
84
|
+
}
|
|
85
|
+
export interface RepositorySnapshot {
|
|
86
|
+
schemaVersion: 1;
|
|
87
|
+
root: string;
|
|
88
|
+
fingerprint: RepositoryFingerprint;
|
|
89
|
+
entries: RepositoryEntry[];
|
|
90
|
+
ecosystems: string[];
|
|
91
|
+
changedPaths: string[];
|
|
92
|
+
instructionFiles: string[];
|
|
93
|
+
documentationFiles: string[];
|
|
94
|
+
manifestFiles: string[];
|
|
95
|
+
ciFiles: string[];
|
|
96
|
+
buildFiles: string[];
|
|
97
|
+
truncated: boolean;
|
|
98
|
+
packageName?: string;
|
|
99
|
+
packageManager: "npm" | "pnpm" | "yarn" | "bun" | "unknown";
|
|
100
|
+
scripts: Record<string, string>;
|
|
101
|
+
configFiles: string[];
|
|
102
|
+
sourceRoots: string[];
|
|
103
|
+
testRoots: string[];
|
|
104
|
+
ignoredPaths: string[];
|
|
105
|
+
indexedFiles: string[];
|
|
106
|
+
files: RepositoryFile[];
|
|
107
|
+
verificationCandidates: VerificationCandidate[];
|
|
108
|
+
createdAt: number;
|
|
109
|
+
}
|
|
110
|
+
export interface FailureEvidence {
|
|
111
|
+
summary: string;
|
|
112
|
+
fileLocations: Array<{
|
|
113
|
+
path: string;
|
|
114
|
+
line?: number;
|
|
115
|
+
column?: number;
|
|
116
|
+
}>;
|
|
117
|
+
excerpts: string[];
|
|
118
|
+
}
|
|
119
|
+
export interface RepairAttempt {
|
|
120
|
+
id: string;
|
|
121
|
+
taskId: string;
|
|
122
|
+
command: string;
|
|
123
|
+
evidence: FailureEvidence;
|
|
124
|
+
selectedFiles: string[];
|
|
125
|
+
createdAt: number;
|
|
126
|
+
}
|
|
127
|
+
export type TaskStatus = "planning" | "acting" | "verifying" | "planned" | "completed" | "verification_required" | "failed" | "interrupted" | "cancelled";
|
|
128
|
+
export type TaskMode = "implementation" | "planning";
|
|
129
|
+
/** A reviewable, execution-free proposal produced by Kairo's planning mode. */
|
|
130
|
+
export interface TaskPlan {
|
|
131
|
+
goal: string;
|
|
132
|
+
assumptions: string[];
|
|
133
|
+
files: Array<{
|
|
134
|
+
path: string;
|
|
135
|
+
reason: string;
|
|
136
|
+
}>;
|
|
137
|
+
steps: string[];
|
|
138
|
+
verification: {
|
|
139
|
+
command?: string;
|
|
140
|
+
reason: string;
|
|
141
|
+
};
|
|
142
|
+
risks: string[];
|
|
143
|
+
}
|
|
144
|
+
export interface Task {
|
|
145
|
+
id: string;
|
|
146
|
+
sessionId: string;
|
|
147
|
+
prompt: string;
|
|
148
|
+
mode: TaskMode;
|
|
149
|
+
status: TaskStatus;
|
|
150
|
+
plan?: TaskPlan;
|
|
151
|
+
changedFiles: string[];
|
|
152
|
+
/** User-approved write paths, scoped to this task and never applied to commands. */
|
|
153
|
+
approvedWritePaths: string[];
|
|
154
|
+
verificationCommand?: string;
|
|
155
|
+
verificationOutput?: string;
|
|
156
|
+
verificationPassed?: boolean;
|
|
157
|
+
verificationExitCode?: number | null;
|
|
158
|
+
verificationDiscovered?: boolean;
|
|
159
|
+
verificationSelection?: VerificationSelection;
|
|
160
|
+
summary?: string;
|
|
161
|
+
error?: string;
|
|
162
|
+
createdAt: number;
|
|
163
|
+
updatedAt: number;
|
|
164
|
+
}
|
|
165
|
+
export interface ContextCheckpoint {
|
|
166
|
+
id: string;
|
|
167
|
+
sessionId: string;
|
|
168
|
+
taskId?: string;
|
|
169
|
+
summary: string;
|
|
170
|
+
throughMessageId: number;
|
|
171
|
+
createdAt: number;
|
|
172
|
+
}
|
|
173
|
+
/** One benchmark result combines the task outcome, an independent verifier, and agent metrics. */
|
|
174
|
+
export interface EvaluationResult {
|
|
175
|
+
failureCategory?: EvaluationAttempt["failureCategory"];
|
|
176
|
+
id: string;
|
|
177
|
+
passed: boolean;
|
|
178
|
+
taskStatus: TaskStatus;
|
|
179
|
+
verified: boolean;
|
|
180
|
+
expectationPassed: boolean;
|
|
181
|
+
error?: string;
|
|
182
|
+
metrics: {
|
|
183
|
+
providerRetries?: number;
|
|
184
|
+
providerWaitMs?: number;
|
|
185
|
+
modelTurns: number;
|
|
186
|
+
toolExecutions: number;
|
|
187
|
+
toolFailures: number;
|
|
188
|
+
approvals: number;
|
|
189
|
+
repairs: number;
|
|
190
|
+
verificationPasses: number;
|
|
191
|
+
verificationFailures: number;
|
|
192
|
+
verificationSelections: number;
|
|
193
|
+
focusedVerifications: number;
|
|
194
|
+
broadVerifications: number;
|
|
195
|
+
repairConverged: boolean;
|
|
196
|
+
modelMs: number;
|
|
197
|
+
toolMs: number;
|
|
198
|
+
jevDecisions?: number;
|
|
199
|
+
jevFailures?: number;
|
|
200
|
+
jevMs?: number;
|
|
201
|
+
jevRoutes?: number;
|
|
202
|
+
jevSafetyChecks?: number;
|
|
203
|
+
jevRecoveryChecks?: number;
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
/** A DeepEval verdict is advisory model-quality evidence, alongside deterministic task checks. */
|
|
207
|
+
export interface DeepEvalVerdict {
|
|
208
|
+
passed: boolean;
|
|
209
|
+
score?: number;
|
|
210
|
+
reason?: string;
|
|
211
|
+
error?: string;
|
|
212
|
+
}
|
|
213
|
+
/** A live evaluation combines isolated workspace assertions with an LLM-judged agent trace. */
|
|
214
|
+
export interface LiveEvaluationResult extends EvaluationResult {
|
|
215
|
+
judge: DeepEvalVerdict;
|
|
216
|
+
}
|
|
217
|
+
/** One live run of a Kairo-on-Kairo benchmark task. */
|
|
218
|
+
export interface SelfEvaluationResult extends EvaluationResult {
|
|
219
|
+
trial: number;
|
|
220
|
+
}
|
|
221
|
+
/** Durable metadata for one real-model reliability-suite run. */
|
|
222
|
+
export interface EvaluationRun {
|
|
223
|
+
id: string;
|
|
224
|
+
suite: "self";
|
|
225
|
+
provider: ProviderId;
|
|
226
|
+
model: string;
|
|
227
|
+
sourceRevision: string;
|
|
228
|
+
trialCount: number;
|
|
229
|
+
attemptCount: number;
|
|
230
|
+
passedCount: number;
|
|
231
|
+
startedAt: number;
|
|
232
|
+
completedAt?: number;
|
|
233
|
+
}
|
|
234
|
+
/** Sanitized attempt data retained for reliability comparisons, never raw agent content. */
|
|
235
|
+
export interface EvaluationAttempt {
|
|
236
|
+
runId: string;
|
|
237
|
+
scenarioId: string;
|
|
238
|
+
trial: number;
|
|
239
|
+
passed: boolean;
|
|
240
|
+
taskStatus: TaskStatus;
|
|
241
|
+
verified: boolean;
|
|
242
|
+
expectationPassed: boolean;
|
|
243
|
+
failureCategory?: "agent" | "verification" | "grader" | "setup" | "unknown" | import("./provider-error.js").ProviderFailure;
|
|
244
|
+
metrics: EvaluationResult["metrics"];
|
|
245
|
+
durationMs: number;
|
|
246
|
+
createdAt: number;
|
|
247
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { ContextCheckpoint, Message, ModelTurn, Task, ToolCall, ToolResult, RepairAttempt, TaskEvent, EvaluationAttempt, EvaluationRun, CredentialId, TaskMode } from "./models.js";
|
|
2
|
+
export interface ModelProvider {
|
|
3
|
+
stream(messages: Message[], onText: (chunk: string) => void, onProgress?: (event: import("./provider-error.js").ProviderProgress) => void, systemInstruction?: string, toolsEnabled?: boolean): Promise<ModelTurn>;
|
|
4
|
+
}
|
|
5
|
+
export interface ToolDefinition {
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
parameters: Record<string, unknown>;
|
|
9
|
+
mutating: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface ToolExecutor {
|
|
12
|
+
readonly root: string;
|
|
13
|
+
description(call: ToolCall): string;
|
|
14
|
+
execute(call: ToolCall): Promise<ToolResult>;
|
|
15
|
+
}
|
|
16
|
+
export interface TaskStore {
|
|
17
|
+
/** Appends metadata for one observable task operation. */
|
|
18
|
+
recordTaskEvent(event: TaskEvent): void;
|
|
19
|
+
/** Returns events in durable insertion order, including earlier resumed runs. */
|
|
20
|
+
taskEvents(taskId: string): TaskEvent[];
|
|
21
|
+
messages(sessionId: string): Message[];
|
|
22
|
+
recentMessages(sessionId: string, limit: number): Message[];
|
|
23
|
+
addMessage(sessionId: string, message: Message): void;
|
|
24
|
+
recordTool(sessionId: string, id: string, name: string, args: Record<string, unknown>, approved: boolean | null, output: string): void;
|
|
25
|
+
startTask(sessionId: string, prompt: string, mode?: TaskMode): Task;
|
|
26
|
+
task(id: string): Task | undefined;
|
|
27
|
+
latestTask(sessionId: string): Task | undefined;
|
|
28
|
+
updateTask(id: string, patch: Partial<Pick<Task, "status" | "mode" | "plan" | "changedFiles" | "approvedWritePaths" | "verificationCommand" | "verificationOutput" | "verificationPassed" | "verificationExitCode" | "verificationDiscovered" | "verificationSelection" | "summary" | "error">>): Task;
|
|
29
|
+
saveCheckpoint(sessionId: string, taskId: string | undefined, summary: string, throughMessageId: number): ContextCheckpoint;
|
|
30
|
+
latestCheckpoint(sessionId: string): ContextCheckpoint | undefined;
|
|
31
|
+
messageCount(sessionId: string): number;
|
|
32
|
+
lastMessageId(sessionId: string): number;
|
|
33
|
+
saveRepositorySnapshot(sessionId: string, snapshot: import("./models.js").RepositorySnapshot): void;
|
|
34
|
+
repositorySnapshot(sessionId: string): import("./models.js").RepositorySnapshot | undefined;
|
|
35
|
+
recordRepairAttempt(attempt: RepairAttempt): void;
|
|
36
|
+
repairAttempts(taskId: string): RepairAttempt[];
|
|
37
|
+
}
|
|
38
|
+
export interface ApprovalPolicy {
|
|
39
|
+
approve(call: ToolCall, description: string): Promise<ApprovalDecision>;
|
|
40
|
+
}
|
|
41
|
+
/** `task_file` authorizes later writes only to the same normalized path in the current task. */
|
|
42
|
+
export type ApprovalDecision = boolean | "task_file";
|
|
43
|
+
export interface CredentialStore {
|
|
44
|
+
get(provider: CredentialId): Promise<string | undefined>;
|
|
45
|
+
save(provider: CredentialId, value: string): Promise<void>;
|
|
46
|
+
clear(provider: CredentialId): Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
export type JevRisk = "low" | "medium" | "high";
|
|
49
|
+
export type JevRoute = "build" | "plan";
|
|
50
|
+
export type JevRecovery = "repair" | "broaden" | "escalate";
|
|
51
|
+
export type JevModelTier = "fast" | "balanced" | "strong";
|
|
52
|
+
export type JevInteractionIntent = "conversation" | "answer" | "repository_task";
|
|
53
|
+
export interface JevDecision<T extends string> {
|
|
54
|
+
value: T;
|
|
55
|
+
confidence: number;
|
|
56
|
+
}
|
|
57
|
+
export interface JevAssessment {
|
|
58
|
+
risk: JevRisk;
|
|
59
|
+
confidence: number;
|
|
60
|
+
}
|
|
61
|
+
/** Classifies bounded operation metadata; Kairo applies all autonomy policy locally. */
|
|
62
|
+
export interface JevSafetyAdvisor {
|
|
63
|
+
assess(state: string): Promise<JevAssessment>;
|
|
64
|
+
/** Routes an input before Kairo creates a repository task or exposes tools. */
|
|
65
|
+
intent?(state: string): Promise<JevDecision<JevInteractionIntent>>;
|
|
66
|
+
route(state: string): Promise<JevDecision<JevRoute>>;
|
|
67
|
+
recover(state: string): Promise<JevDecision<JevRecovery>>;
|
|
68
|
+
modelTier(state: string): Promise<JevDecision<JevModelTier>>;
|
|
69
|
+
}
|
|
70
|
+
export interface JevFeatures {
|
|
71
|
+
routing: boolean;
|
|
72
|
+
safety: boolean;
|
|
73
|
+
recovery: boolean;
|
|
74
|
+
/** Allows only Jev-approved, discovered verification commands to run without a prompt. */
|
|
75
|
+
autonomy?: boolean;
|
|
76
|
+
}
|
|
77
|
+
/** Stores metadata-only reliability evidence separately from raw task history. */
|
|
78
|
+
export interface EvaluationStore {
|
|
79
|
+
setEvaluationBaseline(runId: string): EvaluationRun;
|
|
80
|
+
evaluationBaseline(): EvaluationRun | undefined;
|
|
81
|
+
createEvaluationRun(input: Omit<EvaluationRun, "id" | "attemptCount" | "passedCount">): EvaluationRun;
|
|
82
|
+
saveEvaluationAttempt(attempt: EvaluationAttempt): void;
|
|
83
|
+
completeEvaluationRun(id: string): EvaluationRun;
|
|
84
|
+
evaluationRuns(limit?: number): EvaluationRun[];
|
|
85
|
+
evaluationRun(id: string): EvaluationRun | undefined;
|
|
86
|
+
evaluationAttempts(runId: string): EvaluationAttempt[];
|
|
87
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type ProviderFailure = "quota" | "authentication" | "network" | "service" | "request";
|
|
2
|
+
export interface ProviderProgress {
|
|
3
|
+
kind: "retry" | "retry_wait" | "exhausted";
|
|
4
|
+
category: ProviderFailure;
|
|
5
|
+
retry: number;
|
|
6
|
+
delayMs: number;
|
|
7
|
+
}
|
|
8
|
+
/** Exposes only safe provider metadata; never retains the underlying error body. */
|
|
9
|
+
export declare class ProviderError extends Error {
|
|
10
|
+
readonly category: ProviderFailure;
|
|
11
|
+
readonly retryable: boolean;
|
|
12
|
+
readonly retryAfterMs?: number | undefined;
|
|
13
|
+
/** A deliberately generic next step; never copied from a provider response. */
|
|
14
|
+
readonly guidance?: string | undefined;
|
|
15
|
+
constructor(category: ProviderFailure, retryable: boolean, retryAfterMs?: number | undefined, provider?: string,
|
|
16
|
+
/** A deliberately generic next step; never copied from a provider response. */
|
|
17
|
+
guidance?: string | undefined);
|
|
18
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Exposes only safe provider metadata; never retains the underlying error body. */
|
|
2
|
+
export class ProviderError extends Error {
|
|
3
|
+
category;
|
|
4
|
+
retryable;
|
|
5
|
+
retryAfterMs;
|
|
6
|
+
guidance;
|
|
7
|
+
constructor(category, retryable, retryAfterMs, provider = "Model provider",
|
|
8
|
+
/** A deliberately generic next step; never copied from a provider response. */
|
|
9
|
+
guidance) {
|
|
10
|
+
super(`${provider} request failed (${category}).${guidance ? ` ${guidance}` : ""}`);
|
|
11
|
+
this.category = category;
|
|
12
|
+
this.retryable = retryable;
|
|
13
|
+
this.retryAfterMs = retryAfterMs;
|
|
14
|
+
this.guidance = guidance;
|
|
15
|
+
this.name = "ProviderError";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ModelSelection } from "../../domain/models.js";
|
|
2
|
+
export interface KairoConfig extends ModelSelection {
|
|
3
|
+
jevEnabled: boolean;
|
|
4
|
+
jevRoutingEnabled: boolean;
|
|
5
|
+
jevSafetyEnabled: boolean;
|
|
6
|
+
jevRecoveryEnabled: boolean;
|
|
7
|
+
jevAutonomyEnabled: boolean;
|
|
8
|
+
autoModelRoutingEnabled: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare const defaultConfig: KairoConfig;
|
|
11
|
+
/** Reads only an explicitly stored, valid config; legacy model-only files migrate to Gemini. */
|
|
12
|
+
export declare function loadStoredConfig(): Promise<KairoConfig | undefined>;
|
|
13
|
+
/** Loads the user configuration, falling back to safe defaults when it is absent. */
|
|
14
|
+
export declare function loadConfig(): Promise<KairoConfig>;
|
|
15
|
+
/** Persists an atomic provider/model selection without storing credentials. */
|
|
16
|
+
export declare function setModelSelection(selection: ModelSelection): Promise<void>;
|
|
17
|
+
/** Persists Jev's enabled flag while its secret remains only in Keychain. */
|
|
18
|
+
export declare function setJevEnabled(jevEnabled: boolean): Promise<void>;
|
|
19
|
+
/** Updates one Jev capability without exposing its credential in configuration. */
|
|
20
|
+
export declare function setJevFeature(feature: "routing" | "safety" | "recovery" | "autonomy", enabled: boolean): Promise<void>;
|
|
21
|
+
/** Persists whether Jev may choose an allowed coding model for each BUILD request. */
|
|
22
|
+
export declare function setAutoModelRoutingEnabled(enabled: boolean): Promise<void>;
|
|
23
|
+
/** Updates one supported configuration value while preserving all other settings. */
|
|
24
|
+
export declare function setConfig(key: string, value: string): Promise<void>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { configPath, ensureStateDir } from "../filesystem/platform-paths.js";
|
|
3
|
+
import { isProviderId } from "../providers/provider-registry.js";
|
|
4
|
+
export const defaultConfig = {
|
|
5
|
+
provider: "gemini",
|
|
6
|
+
model: "gemini-2.5-flash",
|
|
7
|
+
jevEnabled: false,
|
|
8
|
+
jevRoutingEnabled: true,
|
|
9
|
+
jevSafetyEnabled: true,
|
|
10
|
+
jevRecoveryEnabled: true,
|
|
11
|
+
jevAutonomyEnabled: false,
|
|
12
|
+
autoModelRoutingEnabled: false,
|
|
13
|
+
};
|
|
14
|
+
/** Reads only an explicitly stored, valid config; legacy model-only files migrate to Gemini. */
|
|
15
|
+
export async function loadStoredConfig() {
|
|
16
|
+
try {
|
|
17
|
+
const parsed = JSON.parse(await readFile(configPath(), "utf8"));
|
|
18
|
+
if (typeof parsed.model !== "string" || !parsed.model.trim())
|
|
19
|
+
return undefined;
|
|
20
|
+
return {
|
|
21
|
+
provider: isProviderId(parsed.provider) ? parsed.provider : "gemini",
|
|
22
|
+
model: parsed.model.trim(),
|
|
23
|
+
jevEnabled: parsed.jevEnabled === true,
|
|
24
|
+
jevRoutingEnabled: parsed.jevRoutingEnabled !== false,
|
|
25
|
+
jevSafetyEnabled: parsed.jevSafetyEnabled !== false,
|
|
26
|
+
jevRecoveryEnabled: parsed.jevRecoveryEnabled !== false,
|
|
27
|
+
jevAutonomyEnabled: parsed.jevAutonomyEnabled === true,
|
|
28
|
+
autoModelRoutingEnabled: parsed.autoModelRoutingEnabled === true,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
if (error.code === "ENOENT")
|
|
33
|
+
return undefined;
|
|
34
|
+
throw new Error(`Could not read Kairo config: ${error.message}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Loads the user configuration, falling back to safe defaults when it is absent. */
|
|
38
|
+
export async function loadConfig() {
|
|
39
|
+
return (await loadStoredConfig()) ?? { ...defaultConfig };
|
|
40
|
+
}
|
|
41
|
+
/** Persists an atomic provider/model selection without storing credentials. */
|
|
42
|
+
export async function setModelSelection(selection) {
|
|
43
|
+
if (!isProviderId(selection.provider) || !selection.model.trim())
|
|
44
|
+
throw new Error("A supported provider and non-empty model are required.");
|
|
45
|
+
await ensureStateDir();
|
|
46
|
+
const current = await loadConfig();
|
|
47
|
+
await saveConfig({ ...current, provider: selection.provider, model: selection.model.trim() });
|
|
48
|
+
}
|
|
49
|
+
/** Persists Jev's enabled flag while its secret remains only in Keychain. */
|
|
50
|
+
export async function setJevEnabled(jevEnabled) {
|
|
51
|
+
await saveConfig({ ...(await loadConfig()), jevEnabled });
|
|
52
|
+
}
|
|
53
|
+
/** Updates one Jev capability without exposing its credential in configuration. */
|
|
54
|
+
export async function setJevFeature(feature, enabled) {
|
|
55
|
+
const key = feature === "routing"
|
|
56
|
+
? "jevRoutingEnabled"
|
|
57
|
+
: feature === "safety"
|
|
58
|
+
? "jevSafetyEnabled"
|
|
59
|
+
: feature === "recovery"
|
|
60
|
+
? "jevRecoveryEnabled"
|
|
61
|
+
: "jevAutonomyEnabled";
|
|
62
|
+
await saveConfig({ ...(await loadConfig()), [key]: enabled });
|
|
63
|
+
}
|
|
64
|
+
/** Persists whether Jev may choose an allowed coding model for each BUILD request. */
|
|
65
|
+
export async function setAutoModelRoutingEnabled(enabled) {
|
|
66
|
+
await saveConfig({ ...(await loadConfig()), autoModelRoutingEnabled: enabled });
|
|
67
|
+
}
|
|
68
|
+
async function saveConfig(config) {
|
|
69
|
+
await ensureStateDir();
|
|
70
|
+
await writeFile(configPath(), `${JSON.stringify(config, null, 2)}\n`, { mode: 0o600 });
|
|
71
|
+
}
|
|
72
|
+
/** Updates one supported configuration value while preserving all other settings. */
|
|
73
|
+
export async function setConfig(key, value) {
|
|
74
|
+
if (key !== "model" || !value.trim())
|
|
75
|
+
throw new Error("Only a non-empty `model` setting is supported.");
|
|
76
|
+
const config = await loadConfig();
|
|
77
|
+
config.model = value.trim();
|
|
78
|
+
await setModelSelection(config);
|
|
79
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Returns Kairo's overridable platform state directory. */
|
|
2
|
+
export declare function stateDir(): string;
|
|
3
|
+
/** Creates the state directory before SQLite or configuration writes use it. */
|
|
4
|
+
export declare function ensureStateDir(): Promise<string>;
|
|
5
|
+
/** Returns the configuration-file path inside Kairo's platform state directory. */
|
|
6
|
+
export declare const configPath: () => string;
|
|
7
|
+
/** Returns the SQLite database path inside Kairo's platform state directory. */
|
|
8
|
+
export declare const databasePath: () => string;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { mkdir } from "node:fs/promises";
|
|
4
|
+
/** Returns Kairo's overridable platform state directory. */
|
|
5
|
+
export function stateDir() {
|
|
6
|
+
return (process.env.KAIRO_STATE_DIR ||
|
|
7
|
+
join(process.env.XDG_STATE_HOME || join(homedir(), ".local", "state"), "kairo"));
|
|
8
|
+
}
|
|
9
|
+
/** Creates the state directory before SQLite or configuration writes use it. */
|
|
10
|
+
export async function ensureStateDir() {
|
|
11
|
+
const dir = stateDir();
|
|
12
|
+
await mkdir(dir, { recursive: true, mode: 0o700 });
|
|
13
|
+
return dir;
|
|
14
|
+
}
|
|
15
|
+
/** Returns the configuration-file path inside Kairo's platform state directory. */
|
|
16
|
+
export const configPath = () => join(stateDir(), "config.json");
|
|
17
|
+
/** Returns the SQLite database path inside Kairo's platform state directory. */
|
|
18
|
+
export const databasePath = () => join(stateDir(), "sessions.sqlite");
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { ContextCheckpoint, Message, TaskEvent, RepairAttempt, RepositorySnapshot, Task, TaskMode, EvaluationAttempt, EvaluationRun } from "../../domain/models.js";
|
|
2
|
+
export interface Session {
|
|
3
|
+
id: string;
|
|
4
|
+
workspace: string;
|
|
5
|
+
createdAt: number;
|
|
6
|
+
updatedAt: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class SqliteSessionStore {
|
|
9
|
+
private readonly db;
|
|
10
|
+
/** Wraps an already-initialized database; callers use open() to guarantee setup. */
|
|
11
|
+
private constructor();
|
|
12
|
+
/** Opens the database, creates current schema objects, and recovers interrupted tasks. */
|
|
13
|
+
static open(path?: string): Promise<SqliteSessionStore>;
|
|
14
|
+
/** Closes the SQLite handle after the CLI session exits. */
|
|
15
|
+
close(): void;
|
|
16
|
+
/** Atomically replaces the local self baseline after validating the selected run. */
|
|
17
|
+
setEvaluationBaseline(runId: string): EvaluationRun;
|
|
18
|
+
/** Resolves the baseline pointer without duplicating evaluation metadata. */
|
|
19
|
+
evaluationBaseline(): EvaluationRun | undefined;
|
|
20
|
+
/** Starts a metadata-only real-model evaluation run. */
|
|
21
|
+
createEvaluationRun(input: Omit<EvaluationRun, "id" | "attemptCount" | "passedCount">): EvaluationRun;
|
|
22
|
+
/** Saves counters and a sanitized outcome without raw prompts, source, or tool output. */
|
|
23
|
+
saveEvaluationAttempt(attempt: EvaluationAttempt): void;
|
|
24
|
+
/** Computes aggregate counts from attempts so historical reports cannot drift. */
|
|
25
|
+
completeEvaluationRun(id: string): EvaluationRun;
|
|
26
|
+
/** Lists recent evaluation runs, newest first. */
|
|
27
|
+
evaluationRuns(limit?: number): EvaluationRun[];
|
|
28
|
+
/** Reads one saved evaluation run. */
|
|
29
|
+
evaluationRun(id: string): EvaluationRun | undefined;
|
|
30
|
+
/** Reads attempts in stable execution order. */
|
|
31
|
+
evaluationAttempts(runId: string): EvaluationAttempt[];
|
|
32
|
+
/** Stores bounded operation metadata separately from model context and raw tool history. */
|
|
33
|
+
recordTaskEvent(event: TaskEvent): void;
|
|
34
|
+
/** Uses insertion ids rather than timestamps to preserve ordering within the same millisecond. */
|
|
35
|
+
taskEvents(taskId: string): TaskEvent[];
|
|
36
|
+
/** Creates a durable session associated with one resolved workspace. */
|
|
37
|
+
create(workspace: string): Session;
|
|
38
|
+
/** Loads one session by id, if it still exists. */
|
|
39
|
+
get(id: string): Session | undefined;
|
|
40
|
+
/** Lists sessions from most recently active to oldest. */
|
|
41
|
+
list(): Session[];
|
|
42
|
+
/** Loads all messages required to reconstruct a full conversation. */
|
|
43
|
+
messages(sessionId: string): Message[];
|
|
44
|
+
/** Loads only the newest messages for bounded model context. */
|
|
45
|
+
recentMessages(sessionId: string, limit: number): Message[];
|
|
46
|
+
/** Appends one durable message and refreshes the owning session timestamp. */
|
|
47
|
+
addMessage(sessionId: string, message: Message): void;
|
|
48
|
+
/** Records the requested action, approval decision, and visible tool output. */
|
|
49
|
+
recordTool(sessionId: string, id: string, name: string, args: Record<string, unknown>, approved: boolean | null, output: string): void;
|
|
50
|
+
/** Creates a new task in the initial planning state. */
|
|
51
|
+
startTask(sessionId: string, prompt: string, mode?: TaskMode): Task;
|
|
52
|
+
/** Loads one task by id and maps database columns to domain names. */
|
|
53
|
+
task(id: string): Task | undefined;
|
|
54
|
+
/** Finds the newest task belonging to a session. */
|
|
55
|
+
latestTask(sessionId: string): Task | undefined;
|
|
56
|
+
/** Finds the most recently saved planning artifact in a session. */
|
|
57
|
+
latestPlan(sessionId: string): Task | undefined;
|
|
58
|
+
/** Merges a partial task update and writes the complete task state atomically. */
|
|
59
|
+
updateTask(id: string, patch: Partial<Pick<Task, "status" | "mode" | "plan" | "changedFiles" | "approvedWritePaths" | "verificationCommand" | "verificationOutput" | "verificationPassed" | "verificationExitCode" | "verificationDiscovered" | "verificationSelection" | "summary" | "error">>): Task;
|
|
60
|
+
/** Persists a summary that replaces older conversation detail in future context. */
|
|
61
|
+
saveCheckpoint(sessionId: string, taskId: string | undefined, summary: string, throughMessageId: number): ContextCheckpoint;
|
|
62
|
+
/** Retrieves the most recent compaction checkpoint for a session. */
|
|
63
|
+
latestCheckpoint(sessionId: string): ContextCheckpoint | undefined;
|
|
64
|
+
/** Counts messages to decide when automatic compaction is needed. */
|
|
65
|
+
messageCount(sessionId: string): number;
|
|
66
|
+
/** Returns the newest message id used to mark checkpoint coverage. */
|
|
67
|
+
lastMessageId(sessionId: string): number;
|
|
68
|
+
/** Upserts the session's bounded, derived repository snapshot. */
|
|
69
|
+
saveRepositorySnapshot(sessionId: string, snapshot: RepositorySnapshot): void;
|
|
70
|
+
/** Reads current snapshots and normalizes legacy profiles as stale snapshots. */
|
|
71
|
+
repositorySnapshot(sessionId: string): RepositorySnapshot | undefined;
|
|
72
|
+
/** Persists one verification failure that started an agent repair cycle. */
|
|
73
|
+
recordRepairAttempt(attempt: RepairAttempt): void;
|
|
74
|
+
/** Returns repair attempts in the order they happened for context and evaluation. */
|
|
75
|
+
repairAttempts(taskId: string): RepairAttempt[];
|
|
76
|
+
/** Marks tasks left active by a process exit so the user can explicitly resume them. */
|
|
77
|
+
private recoverInterruptedTasks;
|
|
78
|
+
/** Converts a raw SQLite row into the application's Task object. */
|
|
79
|
+
private toTask;
|
|
80
|
+
/** Converts one evaluation run row while keeping persistence column names private. */
|
|
81
|
+
private toEvaluationRun;
|
|
82
|
+
}
|