klyro 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/anthropic-adapter.d.ts +49 -5
- package/dist/agent/anthropic-adapter.js +86 -17
- package/dist/agent/capabilities.d.ts +23 -0
- package/dist/agent/capabilities.js +53 -6
- package/dist/agent/child-worker.d.ts +104 -0
- package/dist/agent/child-worker.js +250 -0
- package/dist/agent/orchestrator.d.ts +124 -6
- package/dist/agent/orchestrator.js +425 -58
- package/dist/agent/provider-adapter.d.ts +8 -0
- package/dist/agent/provider-adapter.js +12 -3
- package/dist/agent/retry.d.ts +1 -1
- package/dist/agent/retry.js +54 -12
- package/dist/agent/runtime.d.ts +84 -8
- package/dist/agent/runtime.js +352 -39
- package/dist/agent/stream-budget.d.ts +36 -0
- package/dist/agent/stream-budget.js +121 -0
- package/dist/agent/worktree-manager.d.ts +74 -0
- package/dist/agent/worktree-manager.js +189 -0
- package/dist/checkpoints/store.d.ts +9 -0
- package/dist/checkpoints/store.js +56 -5
- package/dist/cli/auth.js +16 -1
- package/dist/cli/commit.d.ts +31 -0
- package/dist/cli/commit.js +142 -0
- package/dist/cli/config.d.ts +54 -3
- package/dist/cli/config.js +146 -3
- package/dist/cli/doctor.d.ts +1 -0
- package/dist/cli/doctor.js +71 -6
- package/dist/cli/eval.d.ts +6 -1
- package/dist/cli/eval.js +9 -0
- package/dist/cli/hooks.d.ts +47 -0
- package/dist/cli/hooks.js +181 -0
- package/dist/cli/repl.js +196 -29
- package/dist/cli/run.d.ts +13 -11
- package/dist/cli/run.js +144 -20
- package/dist/cli/update.d.ts +5 -0
- package/dist/cli/update.js +62 -10
- package/dist/context/import-graph.d.ts +2 -0
- package/dist/context/import-graph.js +31 -3
- package/dist/context/klyro-md.js +4 -1
- package/dist/context/memory.d.ts +8 -0
- package/dist/context/memory.js +50 -2
- package/dist/context/project-map.d.ts +6 -0
- package/dist/context/project-map.js +50 -2
- package/dist/context/repo-map.d.ts +2 -0
- package/dist/context/repo-map.js +31 -1
- package/dist/events/catalog.d.ts +37 -0
- package/dist/events/catalog.js +9 -0
- package/dist/index.js +177 -8
- package/dist/mcp/client.d.ts +6 -4
- package/dist/mcp/client.js +83 -14
- package/dist/mcp/config.d.ts +10 -0
- package/dist/mcp/config.js +18 -1
- package/dist/mcp/registry.d.ts +23 -19
- package/dist/mcp/registry.js +127 -8
- package/dist/mcp/schema.d.ts +11 -4
- package/dist/mcp/schema.js +27 -16
- package/dist/mcp/trust.d.ts +20 -0
- package/dist/mcp/trust.js +74 -0
- package/dist/persistence/audit.d.ts +28 -0
- package/dist/persistence/audit.js +101 -1
- package/dist/persistence/store.d.ts +26 -2
- package/dist/persistence/store.js +140 -13
- package/dist/policy/approval.d.ts +14 -0
- package/dist/policy/approval.js +44 -2
- package/dist/policy/engine.d.ts +17 -0
- package/dist/policy/engine.js +162 -9
- package/dist/policy/path-guard.d.ts +24 -0
- package/dist/policy/path-guard.js +46 -0
- package/dist/policy/secret-redactor.js +4 -0
- package/dist/providers/model-info.d.ts +23 -0
- package/dist/providers/model-info.js +43 -2
- package/dist/repl.d.ts +6 -0
- package/dist/repl.js +12 -7
- package/dist/tools/agent/spawn-agent.js +5 -5
- package/dist/tools/agent/task-apply.d.ts +4 -0
- package/dist/tools/agent/task-apply.js +44 -0
- package/dist/tools/agent/task-stop.d.ts +6 -0
- package/dist/tools/agent/task-stop.js +39 -0
- package/dist/tools/agent/task-wait.d.ts +17 -0
- package/dist/tools/agent/task-wait.js +79 -0
- package/dist/tools/fs/apply-patch.js +77 -1
- package/dist/tools/fs/edit-file.js +69 -1
- package/dist/tools/fs/multi-edit.d.ts +4 -0
- package/dist/tools/fs/multi-edit.js +70 -1
- package/dist/tools/fs/write-file.js +83 -6
- package/dist/tools/plan/todo-write.js +1 -1
- package/dist/tools/registry.js +6 -0
- package/dist/tools/shell/background.js +6 -3
- package/dist/tools/shell/sandbox.d.ts +51 -0
- package/dist/tools/shell/sandbox.js +143 -0
- package/dist/tools/shell/shell-exec.d.ts +29 -0
- package/dist/tools/shell/shell-exec.js +170 -12
- package/dist/tools/shell/worker-entry.d.ts +12 -0
- package/dist/tools/shell/worker-entry.js +43 -0
- package/dist/tools/types.d.ts +6 -0
- package/dist/tools/verify/run-verify.js +3 -1
- package/dist/trace/writer.d.ts +20 -0
- package/dist/trace/writer.js +62 -4
- package/dist/tui/app.js +1 -1
- package/dist/tui/approval.js +20 -21
- package/dist/util.d.ts +1 -0
- package/dist/util.js +1 -0
- package/dist/verification/baseline.js +17 -3
- package/dist/verification/classify.js +27 -15
- package/dist/verification/engine.d.ts +8 -0
- package/dist/verification/engine.js +28 -1
- package/dist/verification/registry.d.ts +2 -0
- package/dist/verification/registry.js +44 -0
- package/dist/verification/scoped.js +64 -11
- package/package.json +1 -1
package/dist/agent/retry.js
CHANGED
|
@@ -15,10 +15,11 @@
|
|
|
15
15
|
*
|
|
16
16
|
* delay = min(maxMs, baseMs * 2^attempt) ± jitter
|
|
17
17
|
*
|
|
18
|
-
* The default policy matches the L6 plan:
|
|
18
|
+
* The default policy matches the L6 plan: 5 attempts, 500ms base, 8s cap.
|
|
19
19
|
*/
|
|
20
|
+
import { acquireStreamSlot, noteRateLimited } from './stream-budget.js';
|
|
20
21
|
export const DEFAULT_RETRY = {
|
|
21
|
-
maxAttempts:
|
|
22
|
+
maxAttempts: 5,
|
|
22
23
|
baseMs: 500,
|
|
23
24
|
maxMs: 8_000,
|
|
24
25
|
sleep: defaultSleep,
|
|
@@ -88,6 +89,28 @@ export function computeBackoff(attempt, baseMs, maxMs) {
|
|
|
88
89
|
const jitter = exp * 0.25 * (Math.random() * 2 - 1);
|
|
89
90
|
return Math.max(0, Math.floor(exp + jitter));
|
|
90
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* True when a retryable error event carries a 429 rate-limit signal.
|
|
94
|
+
* Checks the `status` field first, then `code`; accepts numeric values
|
|
95
|
+
* and `'429'` substrings (e.g. `'429'`, `'HTTP_429'`).
|
|
96
|
+
*/
|
|
97
|
+
function isRateLimitedError(ev) {
|
|
98
|
+
if (ev.kind !== 'error')
|
|
99
|
+
return false;
|
|
100
|
+
const rec = ev;
|
|
101
|
+
for (const key of ['status', 'code']) {
|
|
102
|
+
const value = rec[key];
|
|
103
|
+
if (typeof value === 'string' && value.includes('429'))
|
|
104
|
+
return true;
|
|
105
|
+
if (typeof value === 'number' && String(value).includes('429'))
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
function rateLimitDelayMs(ev) {
|
|
111
|
+
const raw = ev['retryAfterMs'];
|
|
112
|
+
return typeof raw === 'number' && Number.isFinite(raw) && raw >= 0 ? raw : undefined;
|
|
113
|
+
}
|
|
91
114
|
export function retryingAdapter(inner, opts = {}) {
|
|
92
115
|
const cfg = { ...DEFAULT_RETRY, ...opts };
|
|
93
116
|
const sleep = opts.sleep ?? defaultSleep;
|
|
@@ -129,20 +152,39 @@ export function retryingAdapter(inner, opts = {}) {
|
|
|
129
152
|
opts.onAttempt?.(attempt);
|
|
130
153
|
if (effectiveSignal?.aborted)
|
|
131
154
|
return;
|
|
155
|
+
// Rate-limit scheduler: hold one stream slot for the duration of
|
|
156
|
+
// this attempt's inner.stream consumption. Abort while queued ends
|
|
157
|
+
// the stream promptly with no inner call.
|
|
158
|
+
let release;
|
|
132
159
|
let sawRetryable = false;
|
|
133
160
|
let lastError = null;
|
|
134
|
-
|
|
135
|
-
|
|
161
|
+
try {
|
|
162
|
+
try {
|
|
163
|
+
release = await acquireStreamSlot(effectiveSignal);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
136
166
|
return;
|
|
137
|
-
if (ev.kind === 'error' && ev.retryable) {
|
|
138
|
-
// Buffer the retryable error; don't yield it yet. We'll either
|
|
139
|
-
// re-issue (and the caller will never see the error) or, on
|
|
140
|
-
// final attempt, yield it as the terminal error.
|
|
141
|
-
sawRetryable = true;
|
|
142
|
-
lastError = ev;
|
|
143
|
-
break; // stop consuming; the stream is dead on retryable errors.
|
|
144
167
|
}
|
|
145
|
-
|
|
168
|
+
for await (const ev of streamWithAbort(inner.stream(attemptReq), effectiveSignal)) {
|
|
169
|
+
if (effectiveSignal?.aborted)
|
|
170
|
+
return;
|
|
171
|
+
if (ev.kind === 'error' && ev.retryable) {
|
|
172
|
+
// Adaptive throttling: a 429 collapses the global stream cap
|
|
173
|
+
// to 1 for retryAfterMs (or 60s) — see stream-budget.ts.
|
|
174
|
+
if (isRateLimitedError(ev))
|
|
175
|
+
noteRateLimited(rateLimitDelayMs(ev));
|
|
176
|
+
// Buffer the retryable error; don't yield it yet. We'll either
|
|
177
|
+
// re-issue (and the caller will never see the error) or, on
|
|
178
|
+
// final attempt, yield it as the terminal error.
|
|
179
|
+
sawRetryable = true;
|
|
180
|
+
lastError = ev;
|
|
181
|
+
break; // stop consuming; the stream is dead on retryable errors.
|
|
182
|
+
}
|
|
183
|
+
yield ev;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
release?.();
|
|
146
188
|
}
|
|
147
189
|
if (!sawRetryable)
|
|
148
190
|
return; // success or non-retryable error — done.
|
package/dist/agent/runtime.d.ts
CHANGED
|
@@ -19,22 +19,58 @@ import type { Message } from './message.js';
|
|
|
19
19
|
import type { ToolRegistry } from '../tools/registry.js';
|
|
20
20
|
import type { PolicyEngine } from '../policy/engine.js';
|
|
21
21
|
import type { ApprovalPrompt } from '../policy/approval.js';
|
|
22
|
+
/**
|
|
23
|
+
* Verification mode. The canonical definition lives in verification/engine.ts
|
|
24
|
+
* (sibling-owned: `export type VerifyMode = 'strict'|'advisory'|'off'`). It is
|
|
25
|
+
* resolved conditionally here so this file typechecks regardless of sibling
|
|
26
|
+
* landing order — and converges to the sibling type automatically once the
|
|
27
|
+
* sibling export exists.
|
|
28
|
+
*/
|
|
29
|
+
export type VerifyMode = typeof import('../verification/engine.js') extends {
|
|
30
|
+
VerifyMode: infer V;
|
|
31
|
+
} ? V : 'strict' | 'advisory' | 'off';
|
|
22
32
|
export interface RuntimeDeps {
|
|
23
33
|
adapter: ProviderAdapter;
|
|
34
|
+
/**
|
|
35
|
+
* Ordered failover adapters (L15). When the active adapter ends a step
|
|
36
|
+
* with a terminal provider error, the runtime swaps to the next entry
|
|
37
|
+
* and re-issues the step (bounded by chain length, never loops).
|
|
38
|
+
* Optional — single-adapter callers behave exactly as before.
|
|
39
|
+
*/
|
|
40
|
+
failoverAdapters?: ProviderAdapter[];
|
|
24
41
|
registry: ToolRegistry;
|
|
25
42
|
policy: PolicyEngine;
|
|
26
43
|
approval: ApprovalPrompt;
|
|
27
44
|
/**
|
|
28
45
|
* Build a system prompt given cwd + the current Level-7 runtime telemetry.
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
46
|
+
*
|
|
47
|
+
* TELEMETRY SPLIT: the fn may return either a plain string (legacy —
|
|
48
|
+
* telemetry already concatenated, cache-unfriendly) or
|
|
49
|
+
* `{system, suffix}` where `suffix` is the volatile telemetry block.
|
|
50
|
+
* The runtime forwards both halves via CallRequest (`system` +
|
|
51
|
+
* `systemSuffix`) so adapters can keep the suffix out of the cacheable
|
|
52
|
+
* prefix (Anthropic array form) or concatenate it (OpenAI — unchanged).
|
|
53
|
+
* Both shapes are accepted so custom fns keep compiling.
|
|
32
54
|
*/
|
|
33
|
-
systemPrompt:
|
|
34
|
-
cwd: string;
|
|
35
|
-
telemetry?: string;
|
|
36
|
-
}) => string;
|
|
55
|
+
systemPrompt: SystemPromptFn;
|
|
37
56
|
}
|
|
57
|
+
/** Split system-prompt result: stable prefix + volatile telemetry suffix. */
|
|
58
|
+
export interface SystemPromptResult {
|
|
59
|
+
system: string;
|
|
60
|
+
suffix?: string;
|
|
61
|
+
}
|
|
62
|
+
export type SystemPromptFn = (ctx: {
|
|
63
|
+
cwd: string;
|
|
64
|
+
telemetry?: string;
|
|
65
|
+
}) => string | SystemPromptResult;
|
|
66
|
+
/** Normalize either systemPrompt shape into {system, suffix}. */
|
|
67
|
+
export declare function resolveSystemPrompt(fn: SystemPromptFn, ctx: {
|
|
68
|
+
cwd: string;
|
|
69
|
+
telemetry?: string;
|
|
70
|
+
}): {
|
|
71
|
+
system: string;
|
|
72
|
+
suffix?: string;
|
|
73
|
+
};
|
|
38
74
|
export type Phase = 'understanding' | 'exploring' | 'planning' | 'implementing' | 'verifying' | 'done' | 'blocked' | 'limit';
|
|
39
75
|
export interface RunOptions {
|
|
40
76
|
task: string;
|
|
@@ -77,6 +113,9 @@ export interface RunOptions {
|
|
|
77
113
|
maxRepairAttempts?: number;
|
|
78
114
|
timeoutMs?: number;
|
|
79
115
|
requireVerify?: boolean;
|
|
116
|
+
/** Verification mode (default 'strict'). 'off' skips the pipeline;
|
|
117
|
+
* 'advisory' runs verify once on completion without repair turns. */
|
|
118
|
+
mode?: VerifyMode;
|
|
80
119
|
};
|
|
81
120
|
/**
|
|
82
121
|
* Level 9 — persistence. When a SessionStore is provided, every message
|
|
@@ -99,6 +138,8 @@ export interface RunOptions {
|
|
|
99
138
|
depth: number;
|
|
100
139
|
maxDepth: number;
|
|
101
140
|
allowedTools?: ReadonlySet<string>;
|
|
141
|
+
/** Path allow-set inherited from the parent (sibling C contract). */
|
|
142
|
+
allowedPaths?: readonly string[];
|
|
102
143
|
model?: string;
|
|
103
144
|
};
|
|
104
145
|
/**
|
|
@@ -160,6 +201,8 @@ export type RuntimeEvent = {
|
|
|
160
201
|
input: number;
|
|
161
202
|
output: number;
|
|
162
203
|
estimated?: boolean;
|
|
204
|
+
cacheRead?: number;
|
|
205
|
+
cacheWrite?: number;
|
|
163
206
|
} | {
|
|
164
207
|
kind: 'final_text';
|
|
165
208
|
text: string;
|
|
@@ -190,6 +233,22 @@ export type RuntimeEvent = {
|
|
|
190
233
|
} | {
|
|
191
234
|
kind: 'checkpoint_saved';
|
|
192
235
|
sessionId: string;
|
|
236
|
+
} | {
|
|
237
|
+
kind: 'status';
|
|
238
|
+
message: string;
|
|
239
|
+
} | {
|
|
240
|
+
kind: 'budget_warning';
|
|
241
|
+
ratio: number;
|
|
242
|
+
threshold: number;
|
|
243
|
+
} | {
|
|
244
|
+
kind: 'provider_failover';
|
|
245
|
+
from: string;
|
|
246
|
+
to: string;
|
|
247
|
+
reason: string;
|
|
248
|
+
} | {
|
|
249
|
+
kind: 'model_override';
|
|
250
|
+
requested: string;
|
|
251
|
+
effective: string;
|
|
193
252
|
};
|
|
194
253
|
export interface RunResult {
|
|
195
254
|
status: 'complete' | 'max_steps' | 'aborted' | 'no_final' | 'verify_failed' | 'limit' | 'blocked' | 'stuck';
|
|
@@ -203,6 +262,8 @@ export interface RunResult {
|
|
|
203
262
|
input: number;
|
|
204
263
|
output: number;
|
|
205
264
|
estimated?: boolean;
|
|
265
|
+
cacheRead?: number;
|
|
266
|
+
cacheWrite?: number;
|
|
206
267
|
};
|
|
207
268
|
/** Number of policy-driven user prompts the user accepted. */
|
|
208
269
|
repairs?: number;
|
|
@@ -212,6 +273,10 @@ export interface RunResult {
|
|
|
212
273
|
command?: string;
|
|
213
274
|
attempts: number;
|
|
214
275
|
failureType?: string;
|
|
276
|
+
repairTokens?: {
|
|
277
|
+
input: number;
|
|
278
|
+
output: number;
|
|
279
|
+
};
|
|
215
280
|
};
|
|
216
281
|
/** 5.1 phase */
|
|
217
282
|
phase?: Phase;
|
|
@@ -222,10 +287,21 @@ export declare function toolDefinitions(registry: ToolRegistry): ToolDefinition[
|
|
|
222
287
|
export declare function estimateCost(model: string, usage: {
|
|
223
288
|
input: number;
|
|
224
289
|
output: number;
|
|
290
|
+
cacheRead?: number;
|
|
291
|
+
cacheWrite?: number;
|
|
225
292
|
}): number;
|
|
293
|
+
/**
|
|
294
|
+
* Parallel fan-out cap: approved concurrencySafe tool calls execute in
|
|
295
|
+
* sequential chunks of at most this size. Commit order stays identical
|
|
296
|
+
* (commits run sequentially after execution), so the transcript reads as
|
|
297
|
+
* if the calls ran in order.
|
|
298
|
+
*/
|
|
299
|
+
export declare const MAX_PARALLEL_TOOLS = 8;
|
|
300
|
+
/** Progressive budget-warning thresholds (fraction of maxCost), fired once each per run. */
|
|
301
|
+
export declare const BUDGET_WARNING_THRESHOLDS: readonly [0.4, 0.7, 0.9];
|
|
226
302
|
/** Run the autonomous loop. */
|
|
227
303
|
export declare function run(opts: RunOptions, deps: RuntimeDeps): Promise<RunResult>;
|
|
228
304
|
export declare function defaultSystemPrompt(ctx: {
|
|
229
305
|
cwd: string;
|
|
230
306
|
telemetry?: string;
|
|
231
|
-
}):
|
|
307
|
+
}): SystemPromptResult;
|