pi-chalin 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 +264 -0
- package/agents/conflict-resolver.md +28 -0
- package/agents/context-builder.md +31 -0
- package/agents/delegate.md +28 -0
- package/agents/oracle.md +28 -0
- package/agents/planner.md +28 -0
- package/agents/researcher.md +29 -0
- package/agents/reviewer.md +30 -0
- package/agents/scout.md +32 -0
- package/agents/worker.md +29 -0
- package/package.json +91 -0
- package/src/agent-overrides.ts +12 -0
- package/src/agents.ts +274 -0
- package/src/artifacts.ts +326 -0
- package/src/autoroute.ts +274 -0
- package/src/budget.ts +333 -0
- package/src/child-sessions.ts +108 -0
- package/src/child-tools.ts +796 -0
- package/src/commands.ts +140 -0
- package/src/config.ts +189 -0
- package/src/discovery.ts +190 -0
- package/src/index.ts +40 -0
- package/src/interview.ts +202 -0
- package/src/kernel.ts +254 -0
- package/src/memory.ts +945 -0
- package/src/model-resolution.ts +106 -0
- package/src/orchestration.ts +99 -0
- package/src/paths.ts +50 -0
- package/src/route-format.ts +149 -0
- package/src/route-guards.ts +92 -0
- package/src/route-widget.ts +219 -0
- package/src/runner-prompt.ts +346 -0
- package/src/runner-state.ts +105 -0
- package/src/runner.ts +1185 -0
- package/src/runtime-state.ts +175 -0
- package/src/schemas.ts +316 -0
- package/src/snapshot.ts +282 -0
- package/src/sql-js-fts5.d.ts +4 -0
- package/src/tools.ts +558 -0
- package/src/ui-agents.ts +338 -0
- package/src/ui-status.ts +87 -0
- package/src/ui.ts +875 -0
- package/src/webfetch.ts +294 -0
- package/src/worktrees.ts +113 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import type { RouteDecision, RunState } from "./schemas.ts";
|
|
2
|
+
|
|
3
|
+
let lastRun: RunState | undefined;
|
|
4
|
+
const liveStepSessions = new Map<string, LiveStepSessionRef>();
|
|
5
|
+
let routeInvocations: ChalinRouteInvocation[] = [];
|
|
6
|
+
let directCompletion: DirectCompletionState = freshDirectCompletionState();
|
|
7
|
+
|
|
8
|
+
export type ChalinRouteOutcome = "dry-run" | "ask" | "block" | "failed" | "paused" | "complete";
|
|
9
|
+
|
|
10
|
+
interface ChalinRouteInvocation {
|
|
11
|
+
id: number;
|
|
12
|
+
dryRun: boolean;
|
|
13
|
+
route?: Pick<RouteDecision, "kind" | "agents" | "risk">;
|
|
14
|
+
outcome?: ChalinRouteOutcome;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface DirectCompletionState {
|
|
18
|
+
prompt: string;
|
|
19
|
+
mutationObserved: boolean;
|
|
20
|
+
testMutationObserved: boolean;
|
|
21
|
+
verificationObserved: boolean;
|
|
22
|
+
verificationCommand?: string;
|
|
23
|
+
progressNudgeSent: boolean;
|
|
24
|
+
readyToVerifyNudgeSent: boolean;
|
|
25
|
+
failedVerificationNudgeSent: boolean;
|
|
26
|
+
missingTestNudgeSent: boolean;
|
|
27
|
+
nudgeSent: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface LiveStepSessionRef {
|
|
31
|
+
runId: string;
|
|
32
|
+
stepId: string;
|
|
33
|
+
agent: string;
|
|
34
|
+
cwd: string;
|
|
35
|
+
startedAt: string;
|
|
36
|
+
getMessages(): readonly unknown[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function setLatestRun(run: RunState | undefined): void {
|
|
40
|
+
lastRun = run;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function getLatestRun(): RunState | undefined {
|
|
44
|
+
return lastRun;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function getActiveRun(): RunState | undefined {
|
|
48
|
+
return lastRun?.status === "running" ? lastRun : undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function setLiveStepSession(ref: LiveStepSessionRef): void {
|
|
52
|
+
liveStepSessions.set(liveStepKey(ref.runId, ref.stepId), ref);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function getLiveStepSession(runId: string, stepId: string): LiveStepSessionRef | undefined {
|
|
56
|
+
return liveStepSessions.get(liveStepKey(runId, stepId));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function clearLiveStepSession(runId: string, stepId: string, ref?: LiveStepSessionRef): void {
|
|
60
|
+
const key = liveStepKey(runId, stepId);
|
|
61
|
+
if (ref && liveStepSessions.get(key) !== ref) return;
|
|
62
|
+
liveStepSessions.delete(key);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function beginChalinTurn(options: { prompt?: string } = {}): void {
|
|
66
|
+
routeInvocations = [];
|
|
67
|
+
directCompletion = freshDirectCompletionState();
|
|
68
|
+
directCompletion.prompt = options.prompt ?? "";
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function recordDirectToolCompletion(options: { toolName: string; isError?: boolean; command?: string; argsText?: string }): { shouldProgressNudge: boolean; shouldReadyToVerifyNudge: boolean; shouldFailureNudge: boolean; shouldMissingTestNudge: boolean; shouldCompletionNudge: boolean; verificationCommand?: string } {
|
|
72
|
+
let shouldProgressNudge = false;
|
|
73
|
+
if (options.toolName === "edit" || options.toolName === "write") {
|
|
74
|
+
if (options.isError) return { shouldProgressNudge: false, shouldReadyToVerifyNudge: false, shouldFailureNudge: false, shouldMissingTestNudge: false, shouldCompletionNudge: false };
|
|
75
|
+
directCompletion.mutationObserved = true;
|
|
76
|
+
if (directCompletion.verificationObserved || directCompletion.verificationCommand || directCompletion.failedVerificationNudgeSent || directCompletion.nudgeSent) {
|
|
77
|
+
directCompletion.verificationObserved = false;
|
|
78
|
+
directCompletion.verificationCommand = undefined;
|
|
79
|
+
directCompletion.readyToVerifyNudgeSent = false;
|
|
80
|
+
directCompletion.failedVerificationNudgeSent = false;
|
|
81
|
+
directCompletion.missingTestNudgeSent = false;
|
|
82
|
+
directCompletion.nudgeSent = false;
|
|
83
|
+
}
|
|
84
|
+
if (isTestMutation(options.argsText)) directCompletion.testMutationObserved = true;
|
|
85
|
+
shouldProgressNudge = !directCompletion.progressNudgeSent;
|
|
86
|
+
if (shouldProgressNudge) directCompletion.progressNudgeSent = true;
|
|
87
|
+
}
|
|
88
|
+
let shouldFailureNudge = false;
|
|
89
|
+
if (options.toolName === "bash" && directCompletion.mutationObserved && isVerificationCommand(options.command)) {
|
|
90
|
+
directCompletion.verificationCommand = options.command?.trim();
|
|
91
|
+
if (options.isError) {
|
|
92
|
+
shouldFailureNudge = !directCompletion.failedVerificationNudgeSent;
|
|
93
|
+
if (shouldFailureNudge) directCompletion.failedVerificationNudgeSent = true;
|
|
94
|
+
} else {
|
|
95
|
+
directCompletion.verificationObserved = true;
|
|
96
|
+
}
|
|
97
|
+
} else if (options.isError) {
|
|
98
|
+
return { shouldProgressNudge, shouldReadyToVerifyNudge: false, shouldFailureNudge: false, shouldMissingTestNudge: false, shouldCompletionNudge: false, verificationCommand: directCompletion.verificationCommand };
|
|
99
|
+
}
|
|
100
|
+
const shouldReadyToVerifyNudge = directCompletion.mutationObserved
|
|
101
|
+
&& !directCompletion.verificationObserved
|
|
102
|
+
&& !directCompletion.readyToVerifyNudgeSent
|
|
103
|
+
&& (!taskRequiresTests(directCompletion.prompt) || directCompletion.testMutationObserved);
|
|
104
|
+
if (shouldReadyToVerifyNudge) directCompletion.readyToVerifyNudgeSent = true;
|
|
105
|
+
const shouldMissingTestNudge = directCompletion.mutationObserved
|
|
106
|
+
&& directCompletion.verificationObserved
|
|
107
|
+
&& taskRequiresTests(directCompletion.prompt)
|
|
108
|
+
&& !directCompletion.testMutationObserved
|
|
109
|
+
&& !directCompletion.missingTestNudgeSent;
|
|
110
|
+
if (shouldMissingTestNudge) directCompletion.missingTestNudgeSent = true;
|
|
111
|
+
const shouldCompletionNudge = directCompletion.mutationObserved
|
|
112
|
+
&& directCompletion.verificationObserved
|
|
113
|
+
&& !shouldMissingTestNudge
|
|
114
|
+
&& !(taskRequiresTests(directCompletion.prompt) && !directCompletion.testMutationObserved)
|
|
115
|
+
&& !directCompletion.nudgeSent;
|
|
116
|
+
if (shouldCompletionNudge) directCompletion.nudgeSent = true;
|
|
117
|
+
return { shouldProgressNudge, shouldReadyToVerifyNudge, shouldFailureNudge, shouldMissingTestNudge, shouldCompletionNudge, verificationCommand: directCompletion.verificationCommand };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function beginChalinRouteInvocation(options: { dryRun: boolean; route: RouteDecision }): { allowed: boolean; reason?: string; invocationId?: number } {
|
|
121
|
+
const committed = routeInvocations.find((call) => call.outcome === "complete" || call.outcome === "paused");
|
|
122
|
+
if (!options.dryRun && committed) {
|
|
123
|
+
return {
|
|
124
|
+
allowed: false,
|
|
125
|
+
reason: "chalin_route already executed for this user prompt. Synthesize the existing result instead of launching another chalin workflow. A second call is allowed only after dryRun, ask, block, or failed outcomes.",
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const invocation: ChalinRouteInvocation = {
|
|
130
|
+
id: routeInvocations.length + 1,
|
|
131
|
+
dryRun: options.dryRun,
|
|
132
|
+
route: { kind: options.route.kind, agents: options.route.agents, risk: options.route.risk },
|
|
133
|
+
};
|
|
134
|
+
routeInvocations.push(invocation);
|
|
135
|
+
return { allowed: true, invocationId: invocation.id };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function finishChalinRouteInvocation(invocationId: number | undefined, outcome: ChalinRouteOutcome): void {
|
|
139
|
+
if (invocationId === undefined) return;
|
|
140
|
+
const invocation = routeInvocations.find((call) => call.id === invocationId);
|
|
141
|
+
if (invocation) invocation.outcome = outcome;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function getChalinRouteInvocations(): readonly ChalinRouteInvocation[] {
|
|
145
|
+
return routeInvocations;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function resetRuntimeState(): void {
|
|
149
|
+
lastRun = undefined;
|
|
150
|
+
liveStepSessions.clear();
|
|
151
|
+
routeInvocations = [];
|
|
152
|
+
directCompletion = freshDirectCompletionState();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function liveStepKey(runId: string, stepId: string): string {
|
|
156
|
+
return `${runId}:${stepId}`;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function freshDirectCompletionState(): DirectCompletionState {
|
|
160
|
+
return { prompt: "", mutationObserved: false, testMutationObserved: false, verificationObserved: false, verificationCommand: undefined, progressNudgeSent: false, readyToVerifyNudgeSent: false, failedVerificationNudgeSent: false, missingTestNudgeSent: false, nudgeSent: false };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function isVerificationCommand(command: string | undefined): boolean {
|
|
164
|
+
if (!command) return false;
|
|
165
|
+
return /\b(npm|pnpm|yarn|bun)\s+(test|run\s+(test|typecheck|lint|check)|exec\s+(vitest|jest|tsc|eslint))\b/i.test(command)
|
|
166
|
+
|| /\b(node\s+.*--test|python3?\s+-m\s+unittest(?:\s+discover)?|go\s+test|cargo\s+test|pytest|vitest|jest|tsc\s+--noEmit|eslint)\b/i.test(command);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function taskRequiresTests(prompt: string): boolean {
|
|
170
|
+
return /\b(test|tests|prueba|pruebas|spec|specs|coverage|cobertura)\b/i.test(prompt);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function isTestMutation(argsText: string | undefined): boolean {
|
|
174
|
+
return Boolean(argsText && /\b(test|tests|spec|__tests__)\/|\.test\.|\.spec\./i.test(argsText));
|
|
175
|
+
}
|
package/src/schemas.ts
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
export const AGENT_SCOPES = ["built-in", "project", "user"] as const;
|
|
2
|
+
export type AgentScope = (typeof AGENT_SCOPES)[number];
|
|
3
|
+
|
|
4
|
+
export const AGENT_CONCERNS = [
|
|
5
|
+
"recon",
|
|
6
|
+
"research",
|
|
7
|
+
"context-building",
|
|
8
|
+
"planning",
|
|
9
|
+
"implementation",
|
|
10
|
+
"review",
|
|
11
|
+
"conflict-resolution",
|
|
12
|
+
"decision-consistency",
|
|
13
|
+
"delegation",
|
|
14
|
+
"memory-curation",
|
|
15
|
+
] as const;
|
|
16
|
+
export type AgentConcern = (typeof AGENT_CONCERNS)[number];
|
|
17
|
+
|
|
18
|
+
export const AGENT_CAPABILITIES = [
|
|
19
|
+
"inspect-files",
|
|
20
|
+
"search-files",
|
|
21
|
+
"run-safe-bash",
|
|
22
|
+
"validate",
|
|
23
|
+
"edit-files",
|
|
24
|
+
"write-new-files",
|
|
25
|
+
"external-context",
|
|
26
|
+
"memory-read",
|
|
27
|
+
"memory-write",
|
|
28
|
+
"coordinate",
|
|
29
|
+
] as const;
|
|
30
|
+
export type AgentCapability = (typeof AGENT_CAPABILITIES)[number];
|
|
31
|
+
|
|
32
|
+
export const AGENT_THINKING_LEVELS = ["inherit", "off", "minimal", "low", "medium", "high", "xhigh"] as const;
|
|
33
|
+
export type AgentThinkingLevel = (typeof AGENT_THINKING_LEVELS)[number];
|
|
34
|
+
|
|
35
|
+
export type AgentMemoryWritePolicy = "never" | "candidate" | "approved";
|
|
36
|
+
|
|
37
|
+
export interface AgentMemoryPolicy {
|
|
38
|
+
read: boolean;
|
|
39
|
+
write: AgentMemoryWritePolicy;
|
|
40
|
+
categories: string[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface AgentDefinition {
|
|
44
|
+
name: string;
|
|
45
|
+
scope: AgentScope;
|
|
46
|
+
concern: AgentConcern;
|
|
47
|
+
capabilities: AgentCapability[];
|
|
48
|
+
description: string;
|
|
49
|
+
model: "inherit" | string;
|
|
50
|
+
thinking?: AgentThinkingLevel;
|
|
51
|
+
tools: string[];
|
|
52
|
+
memory: AgentMemoryPolicy;
|
|
53
|
+
systemPrompt: string;
|
|
54
|
+
sourcePath?: string;
|
|
55
|
+
diagnostics: string[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface AgentCatalogDiagnostics {
|
|
59
|
+
warnings: string[];
|
|
60
|
+
errors: string[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export type RouteKind =
|
|
64
|
+
| "bypass"
|
|
65
|
+
| "single-agent"
|
|
66
|
+
| "multi-agent-chain"
|
|
67
|
+
| "multi-agent-parallel"
|
|
68
|
+
| "multi-agent-dag"
|
|
69
|
+
| "memory-only"
|
|
70
|
+
| "ask-user";
|
|
71
|
+
|
|
72
|
+
export type RouteRisk = "low" | "medium" | "high" | "critical";
|
|
73
|
+
export type RouteAmbiguity = "low" | "medium" | "high";
|
|
74
|
+
|
|
75
|
+
export interface AgentStep {
|
|
76
|
+
id?: string;
|
|
77
|
+
agent: string;
|
|
78
|
+
task: string;
|
|
79
|
+
budget?: ToolBudgetProfile;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface AgentStage {
|
|
83
|
+
id: string;
|
|
84
|
+
tasks: AgentStep[];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type ToolBudgetProfile = "tight" | "normal" | "deep" | "extended";
|
|
88
|
+
|
|
89
|
+
export type RoutePlan =
|
|
90
|
+
| { kind: "single"; agent: string; task: string; budget?: ToolBudgetProfile }
|
|
91
|
+
| { kind: "chain"; steps: AgentStep[] }
|
|
92
|
+
| { kind: "parallel"; tasks: AgentStep[] }
|
|
93
|
+
| { kind: "dag"; stages: AgentStage[] };
|
|
94
|
+
|
|
95
|
+
export interface RouteDecision {
|
|
96
|
+
kind: RouteKind;
|
|
97
|
+
agents: string[];
|
|
98
|
+
risk: RouteRisk;
|
|
99
|
+
ambiguity: RouteAmbiguity;
|
|
100
|
+
needsMemory: boolean;
|
|
101
|
+
needsArtifacts: boolean;
|
|
102
|
+
reason: string;
|
|
103
|
+
plan?: RoutePlan;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export type ApprovalAction = "allow" | "ask" | "block";
|
|
107
|
+
|
|
108
|
+
export interface ApprovalDecision {
|
|
109
|
+
action: ApprovalAction;
|
|
110
|
+
reason: string;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export type RunStatus = "pending" | "running" | "complete" | "failed" | "paused" | "budget-capped" | "stale-repaired";
|
|
114
|
+
|
|
115
|
+
export interface MemoryCandidate {
|
|
116
|
+
id: string;
|
|
117
|
+
category: string;
|
|
118
|
+
content: string;
|
|
119
|
+
sourceAgent: string;
|
|
120
|
+
confidence: number;
|
|
121
|
+
evidence?: string;
|
|
122
|
+
scope: "project" | "user";
|
|
123
|
+
createdAt: string;
|
|
124
|
+
topicKey?: string;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export type MemoryRecordStatus = "active" | "pending" | "rejected" | "superseded" | "stale" | "quarantined";
|
|
128
|
+
|
|
129
|
+
export interface MemoryRecord extends MemoryCandidate {
|
|
130
|
+
status: MemoryRecordStatus;
|
|
131
|
+
reviewedAt?: string;
|
|
132
|
+
importance: number;
|
|
133
|
+
trigger: string;
|
|
134
|
+
lastSeenAt: string;
|
|
135
|
+
duplicateCount: number;
|
|
136
|
+
revisionCount: number;
|
|
137
|
+
updatedAt?: string;
|
|
138
|
+
lastUsedAt?: string;
|
|
139
|
+
useCount?: number;
|
|
140
|
+
utilityScore?: number;
|
|
141
|
+
tokenCostEstimate?: number;
|
|
142
|
+
supersedesId?: string;
|
|
143
|
+
supersededBy?: string;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export type MemoryAuditEventType =
|
|
147
|
+
| "create"
|
|
148
|
+
| "duplicate"
|
|
149
|
+
| "revise"
|
|
150
|
+
| "approve"
|
|
151
|
+
| "reject"
|
|
152
|
+
| "delete"
|
|
153
|
+
| "retrieve"
|
|
154
|
+
| "quarantine"
|
|
155
|
+
| "stale";
|
|
156
|
+
|
|
157
|
+
export interface MemoryAuditEvent {
|
|
158
|
+
id: string;
|
|
159
|
+
recordId: string;
|
|
160
|
+
type: MemoryAuditEventType;
|
|
161
|
+
actor: string;
|
|
162
|
+
at: string;
|
|
163
|
+
summary: string;
|
|
164
|
+
previousContent?: string;
|
|
165
|
+
nextContent?: string;
|
|
166
|
+
metadata?: Record<string, unknown>;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export interface AgentOutput {
|
|
170
|
+
agent: string;
|
|
171
|
+
text: string;
|
|
172
|
+
handoff?: string;
|
|
173
|
+
memoryCandidates: MemoryCandidate[];
|
|
174
|
+
raw: string;
|
|
175
|
+
warnings: string[];
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export interface TokenUsageCost {
|
|
179
|
+
input: number;
|
|
180
|
+
output: number;
|
|
181
|
+
cacheRead: number;
|
|
182
|
+
cacheWrite: number;
|
|
183
|
+
total: number;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export interface TokenUsageSummary {
|
|
187
|
+
input: number;
|
|
188
|
+
output: number;
|
|
189
|
+
cacheRead: number;
|
|
190
|
+
cacheWrite: number;
|
|
191
|
+
totalTokens: number;
|
|
192
|
+
cost: TokenUsageCost;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export interface RunStepMetrics {
|
|
196
|
+
durationMs: number;
|
|
197
|
+
usage: TokenUsageSummary;
|
|
198
|
+
toolCalls: number;
|
|
199
|
+
maxToolCalls?: number;
|
|
200
|
+
toolCallsByName: Record<string, number>;
|
|
201
|
+
policyViolations?: string[];
|
|
202
|
+
budgetStopCount?: number;
|
|
203
|
+
duplicateReadCount?: number;
|
|
204
|
+
crossStepDuplicateReadCount?: number;
|
|
205
|
+
crossStepDuplicateReads?: string[];
|
|
206
|
+
filesRead?: string[];
|
|
207
|
+
readBytes?: number;
|
|
208
|
+
outputChars?: number;
|
|
209
|
+
outputTruncatedCount?: number;
|
|
210
|
+
filesTouched?: string[];
|
|
211
|
+
retriesByTool?: Record<string, number>;
|
|
212
|
+
utility?: {
|
|
213
|
+
findingsPerTool: number;
|
|
214
|
+
filesReadPerFinding: number;
|
|
215
|
+
duplicateReads: number;
|
|
216
|
+
toolCallsBeforeFirstSignal: number;
|
|
217
|
+
verificationDone: boolean;
|
|
218
|
+
memoryCandidatesQuality: number;
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export type ModelResolutionSource = "session-override" | "agent" | "tier" | "inherit";
|
|
223
|
+
export type ModelResolutionStatus = "selected" | "invalid" | "unavailable" | "unauthenticated" | "fallback";
|
|
224
|
+
|
|
225
|
+
export interface ModelResolutionAttempt {
|
|
226
|
+
source: ModelResolutionSource;
|
|
227
|
+
ref?: string;
|
|
228
|
+
status: ModelResolutionStatus;
|
|
229
|
+
model?: string;
|
|
230
|
+
reason?: string;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export interface ModelResolutionLog {
|
|
234
|
+
selected: string;
|
|
235
|
+
tier: "fast" | "balanced" | "strong";
|
|
236
|
+
attempts: ModelResolutionAttempt[];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export interface RunStepState {
|
|
240
|
+
id: string;
|
|
241
|
+
agent: string;
|
|
242
|
+
task: string;
|
|
243
|
+
status: RunStatus;
|
|
244
|
+
budget?: ToolBudgetProfile;
|
|
245
|
+
maxToolCalls?: number;
|
|
246
|
+
startedAt?: string;
|
|
247
|
+
endedAt?: string;
|
|
248
|
+
model?: string;
|
|
249
|
+
thinkingLevel?: AgentThinkingLevel;
|
|
250
|
+
output?: AgentOutput;
|
|
251
|
+
error?: string;
|
|
252
|
+
currentTool?: string;
|
|
253
|
+
modelResolution?: ModelResolutionLog;
|
|
254
|
+
metrics?: RunStepMetrics;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export interface RunState {
|
|
258
|
+
id: string;
|
|
259
|
+
route: RouteDecision;
|
|
260
|
+
status: RunStatus;
|
|
261
|
+
startedAt: string;
|
|
262
|
+
endedAt?: string;
|
|
263
|
+
steps: RunStepState[];
|
|
264
|
+
logsPath?: string;
|
|
265
|
+
warnings: string[];
|
|
266
|
+
budgetPreflight?: {
|
|
267
|
+
taskKind: string;
|
|
268
|
+
expectedStages: number;
|
|
269
|
+
expectedTools: number;
|
|
270
|
+
risk: RouteRisk;
|
|
271
|
+
budgetProfile: ToolBudgetProfile;
|
|
272
|
+
resumeStrategy: string;
|
|
273
|
+
requiresArtifacts: boolean;
|
|
274
|
+
recommendation: string;
|
|
275
|
+
};
|
|
276
|
+
metrics?: {
|
|
277
|
+
durationMs: number;
|
|
278
|
+
usage: TokenUsageSummary;
|
|
279
|
+
toolCalls: number;
|
|
280
|
+
toolCallsByName: Record<string, number>;
|
|
281
|
+
policyViolations?: string[];
|
|
282
|
+
budgetStopCount?: number;
|
|
283
|
+
duplicateReadCount?: number;
|
|
284
|
+
crossStepDuplicateReadCount?: number;
|
|
285
|
+
crossStepDuplicateReads?: string[];
|
|
286
|
+
filesRead?: string[];
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export interface ChalinRuntimeState {
|
|
291
|
+
autoRoutingEnabled: boolean;
|
|
292
|
+
pendingApprovals: number;
|
|
293
|
+
activeRuns: number;
|
|
294
|
+
pendingMemoryCandidates: number;
|
|
295
|
+
lastRun?: RunState;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export function isAgentScope(value: string): value is AgentScope {
|
|
299
|
+
return (AGENT_SCOPES as readonly string[]).includes(value);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export function isAgentConcern(value: string): value is AgentConcern {
|
|
303
|
+
return (AGENT_CONCERNS as readonly string[]).includes(value);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export function isAgentCapability(value: string): value is AgentCapability {
|
|
307
|
+
return (AGENT_CAPABILITIES as readonly string[]).includes(value);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export function isAgentThinkingLevel(value: string): value is AgentThinkingLevel {
|
|
311
|
+
return (AGENT_THINKING_LEVELS as readonly string[]).includes(value);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export function riskRank(risk: RouteRisk): number {
|
|
315
|
+
return { low: 0, medium: 1, high: 2, critical: 3 }[risk];
|
|
316
|
+
}
|