jeopi-cli 16.3.0 → 16.4.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 +16 -0
- package/dist/cli.js +2731 -2707
- package/dist/types/config/settings-schema.d.ts +20 -0
- package/dist/types/memories/index.d.ts +9 -0
- package/dist/types/memory-backend/types.d.ts +11 -0
- package/dist/types/slash-commands/helpers/skill-verify.d.ts +5 -0
- package/dist/types/task/model-tier-classifier.d.ts +8 -0
- package/dist/types/tools/builtin-names.d.ts +1 -1
- package/dist/types/tools/index.d.ts +1 -0
- package/dist/types/tools/learn.d.ts +4 -0
- package/dist/types/tools/path-write-lock.d.ts +10 -0
- package/dist/types/tools/vision-verify.d.ts +34 -0
- package/package.json +12 -12
- package/src/autolearn/controller.ts +21 -5
- package/src/config/settings-schema.ts +24 -0
- package/src/edit/index.ts +2 -1
- package/src/internal-urls/docs-index.generated.txt +2 -2
- package/src/memories/index.ts +10 -2
- package/src/memory-backend/local-backend.ts +34 -0
- package/src/memory-backend/types.ts +11 -0
- package/src/prompts/agents/designer.md +1 -0
- package/src/prompts/tools/learn.md +2 -0
- package/src/prompts/tools/vision-verify-system.md +16 -0
- package/src/prompts/tools/vision-verify.md +20 -0
- package/src/slash-commands/builtin-registry.ts +9 -0
- package/src/slash-commands/helpers/skill-verify.ts +171 -0
- package/src/task/index.ts +26 -1
- package/src/task/model-tier-classifier.ts +43 -0
- package/src/tools/builtin-names.ts +1 -0
- package/src/tools/index.ts +4 -0
- package/src/tools/learn.ts +16 -1
- package/src/tools/path-write-lock.ts +44 -0
- package/src/tools/vision-verify.ts +347 -0
- package/src/tools/write.ts +12 -9
|
@@ -3690,6 +3690,16 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
3690
3690
|
readonly description: "Enable the inspect_image tool, delegating image understanding to a vision-capable model";
|
|
3691
3691
|
};
|
|
3692
3692
|
};
|
|
3693
|
+
readonly "vision_verify.enabled": {
|
|
3694
|
+
readonly type: "boolean";
|
|
3695
|
+
readonly default: false;
|
|
3696
|
+
readonly ui: {
|
|
3697
|
+
readonly tab: "tools";
|
|
3698
|
+
readonly group: "Available Tools";
|
|
3699
|
+
readonly label: "Vision Verify";
|
|
3700
|
+
readonly description: "Enable the vision_verify tool, checking a screenshot/artifact against a stated goal with a vision-capable model";
|
|
3701
|
+
};
|
|
3702
|
+
};
|
|
3693
3703
|
readonly "checkpoint.enabled": {
|
|
3694
3704
|
readonly type: "boolean";
|
|
3695
3705
|
readonly default: false;
|
|
@@ -4257,6 +4267,16 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
4257
4267
|
readonly description: "Allow subagents spawned via the task tool to use the lsp tool. Off by default to keep subagents cheap; enable when LSP-aware delegation is worth the extra tokens.";
|
|
4258
4268
|
};
|
|
4259
4269
|
};
|
|
4270
|
+
readonly "task.autoModelTier": {
|
|
4271
|
+
readonly type: "boolean";
|
|
4272
|
+
readonly default: true;
|
|
4273
|
+
readonly ui: {
|
|
4274
|
+
readonly tab: "tasks";
|
|
4275
|
+
readonly group: "Subagents";
|
|
4276
|
+
readonly label: "Auto Model Tier for Simple Tasks";
|
|
4277
|
+
readonly description: "Classify a task() spawn's assignment text and route trivially-simple work to the cheap 'smol' model tier instead of the default 'task' tier, when the caller has not explicitly overridden the model. Off-by-default agent-type model pins (named specialist agents like reviewer/critic/architect) are never affected — this only applies to the generic default 'task' agent.";
|
|
4278
|
+
};
|
|
4279
|
+
};
|
|
4260
4280
|
readonly "task.maxRecursionDepth": {
|
|
4261
4281
|
readonly type: "number";
|
|
4262
4282
|
readonly default: 2;
|
|
@@ -45,6 +45,15 @@ export declare function clearMemoryData(agentDir: string, cwd: string): Promise<
|
|
|
45
45
|
*/
|
|
46
46
|
export declare function enqueueMemoryConsolidation(agentDir: string, cwd: string, sourceUpdatedAt?: number): void;
|
|
47
47
|
export declare function getMemoryRoot(agentDir: string, cwd: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* Filename of the captured-lessons file under a project's memory root.
|
|
50
|
+
*
|
|
51
|
+
* Written by the `learn` tool via {@link saveLearnedLesson} and read back by
|
|
52
|
+
* {@link buildMemoryToolDeveloperInstructions}. Deliberately distinct from the
|
|
53
|
+
* consolidation artifacts (`MEMORY.md`, `memory_summary.md`, `skills/`) so a
|
|
54
|
+
* consolidation pass never clobbers manually captured lessons.
|
|
55
|
+
*/
|
|
56
|
+
export declare const LEARNED_LESSONS_FILE = "learned.md";
|
|
48
57
|
/**
|
|
49
58
|
* Append one lesson to the project's `learned.md` (newest-first, deduped,
|
|
50
59
|
* capped, secret-redacted, injection-neutralized). The file backs the `learn`
|
|
@@ -53,6 +53,17 @@ export interface MemoryBackendSaveInput {
|
|
|
53
53
|
context?: string;
|
|
54
54
|
source?: string;
|
|
55
55
|
importance?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Marks this lesson as independently re-checked against the repo (a
|
|
58
|
+
* command run, a file read, a test executed) rather than merely asserted
|
|
59
|
+
* from inference. Mirrors the "verify" stage of the fail → investigate →
|
|
60
|
+
* verify → distill → consult self-improvement progression: a lesson that
|
|
61
|
+
* skips verification is still worth capturing, but downstream consumers
|
|
62
|
+
* (e.g. `stats()`) should be able to tell the two apart.
|
|
63
|
+
*/
|
|
64
|
+
verified?: boolean;
|
|
65
|
+
/** The short check that was run to establish `verified` (a command, a file path, a test name). Ignored when `verified` is not `true`. */
|
|
66
|
+
evidence?: string;
|
|
56
67
|
}
|
|
57
68
|
export interface MemoryBackendSaveResult {
|
|
58
69
|
backend: MemoryBackendId;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ParsedSlashCommand, SlashCommandResult, SlashCommandRuntime } from "../types";
|
|
2
|
+
/** Extract the bulleted list under a `## Eval Cases` heading, if present. */
|
|
3
|
+
export declare function extractEvalCases(skillBody: string): string[];
|
|
4
|
+
/** `/verify-skill <name>` handler — resolves a skill, runs its `## Eval Cases`, reports pass/fail. */
|
|
5
|
+
export declare function handleSkillCommand(command: ParsedSlashCommand, runtime: SlashCommandRuntime): Promise<SlashCommandResult>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ClassifyDifficultyDeps } from "../auto-thinking/classifier";
|
|
2
|
+
/**
|
|
3
|
+
* Classify `assignment` and return `"smol"` when the work is trivially
|
|
4
|
+
* simple ({@link Effort.Minimal} or {@link Effort.Low}), or `undefined` when
|
|
5
|
+
* the caller should leave normal model resolution in place (not-simple
|
|
6
|
+
* enough, no classifier available, or the classification failed/timed out).
|
|
7
|
+
*/
|
|
8
|
+
export declare function classifyDefaultTaskModelTier(assignment: string, deps: ClassifyDifficultyDeps): Promise<"smol" | undefined>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const BUILTIN_TOOL_NAMES: readonly ["read", "bash", "edit", "ast_grep", "ast_edit", "ask", "debug", "eval", "ssh", "github", "glob", "grep", "lsp", "inspect_image", "browser", "checkpoint", "rewind", "task", "job", "irc", "subagent", "todo", "web_search", "search_tool_bm25", "write", "memory_edit", "retain", "recall", "reflect", "learn", "manage_skill"];
|
|
1
|
+
export declare const BUILTIN_TOOL_NAMES: readonly ["read", "bash", "edit", "ast_grep", "ast_edit", "ask", "debug", "eval", "ssh", "github", "glob", "grep", "lsp", "inspect_image", "vision_verify", "browser", "checkpoint", "rewind", "task", "job", "irc", "subagent", "todo", "web_search", "search_tool_bm25", "write", "memory_edit", "retain", "recall", "reflect", "learn", "manage_skill"];
|
|
2
2
|
export type BuiltinToolName = (typeof BUILTIN_TOOL_NAMES)[number];
|
|
3
3
|
/** Return the canonical tool name for current and legacy built-in tool IDs. */
|
|
4
4
|
export declare function normalizeToolName(name: string): string;
|
|
@@ -3,6 +3,8 @@ import type { ToolSession } from ".";
|
|
|
3
3
|
declare const learnSchema: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
4
4
|
memory: string;
|
|
5
5
|
context?: string | undefined;
|
|
6
|
+
verified?: boolean | undefined;
|
|
7
|
+
evidence?: string | undefined;
|
|
6
8
|
skill?: {
|
|
7
9
|
action: "create" | "update";
|
|
8
10
|
name: string;
|
|
@@ -27,6 +29,8 @@ export declare class LearnTool implements AgentTool<typeof learnSchema> {
|
|
|
27
29
|
readonly parameters: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
28
30
|
memory: string;
|
|
29
31
|
context?: string | undefined;
|
|
32
|
+
verified?: boolean | undefined;
|
|
33
|
+
evidence?: string | undefined;
|
|
30
34
|
skill?: {
|
|
31
35
|
action: "create" | "update";
|
|
32
36
|
name: string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { WritethroughCallback } from "../lsp";
|
|
2
|
+
/**
|
|
3
|
+
* Wrap a {@link WritethroughCallback} so concurrent writes to the same `dst`
|
|
4
|
+
* are serialized instead of racing. `dst` is used as-is for the chain key:
|
|
5
|
+
* every caller (edit's hashline/patch/replace paths, and the write tool)
|
|
6
|
+
* resolves `dst` to an absolute path via `resolvePlanPath`/`resolveToCwd`
|
|
7
|
+
* before invoking the writethrough, so the same logical file always arrives
|
|
8
|
+
* under the same string.
|
|
9
|
+
*/
|
|
10
|
+
export declare function withPathWriteLock(callback: WritethroughCallback): WritethroughCallback;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "jeopi-agent-core";
|
|
2
|
+
import { completeSimple, type ToolExample } from "jeopi-ai";
|
|
3
|
+
import type { ToolSession } from "./index";
|
|
4
|
+
declare const visionVerifySchema: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
5
|
+
goal: string;
|
|
6
|
+
screenshot: string;
|
|
7
|
+
baseline?: string | undefined;
|
|
8
|
+
}, {}>;
|
|
9
|
+
export type VisionVerifyParams = typeof visionVerifySchema.infer;
|
|
10
|
+
export interface VisionVerifyToolDetails {
|
|
11
|
+
model: string;
|
|
12
|
+
matches: boolean;
|
|
13
|
+
gaps: string[];
|
|
14
|
+
}
|
|
15
|
+
export declare class VisionVerifyTool implements AgentTool<typeof visionVerifySchema, VisionVerifyToolDetails> {
|
|
16
|
+
private readonly session;
|
|
17
|
+
private readonly completeImageRequest;
|
|
18
|
+
readonly name = "vision_verify";
|
|
19
|
+
readonly approval: "read";
|
|
20
|
+
readonly label = "VisionVerify";
|
|
21
|
+
readonly loadMode = "discoverable";
|
|
22
|
+
readonly summary = "Check a screenshot/artifact against a stated goal with a vision model";
|
|
23
|
+
readonly description: string;
|
|
24
|
+
readonly parameters: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
25
|
+
goal: string;
|
|
26
|
+
screenshot: string;
|
|
27
|
+
baseline?: string | undefined;
|
|
28
|
+
}, {}>;
|
|
29
|
+
readonly strict = false;
|
|
30
|
+
readonly examples: readonly ToolExample<typeof visionVerifySchema.infer>[];
|
|
31
|
+
constructor(session: ToolSession, completeImageRequest?: typeof completeSimple);
|
|
32
|
+
execute(_toolCallId: string, params: VisionVerifyParams, signal?: AbortSignal, _onUpdate?: AgentToolUpdateCallback<VisionVerifyToolDetails>, _context?: AgentToolContext): Promise<AgentToolResult<VisionVerifyToolDetails>>;
|
|
33
|
+
}
|
|
34
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "jeopi-cli",
|
|
4
|
-
"version": "16.
|
|
4
|
+
"version": "16.4.0",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://github.com/akillness/jeopi",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -57,17 +57,17 @@
|
|
|
57
57
|
"@agentclientprotocol/sdk": "0.25.0",
|
|
58
58
|
"@babel/parser": "^7.29.7",
|
|
59
59
|
"@mozilla/readability": "^0.6.0",
|
|
60
|
-
"jeopi-hashline": "16.
|
|
61
|
-
"jeopi-stats": "16.
|
|
62
|
-
"jeopi-agent-core": "16.
|
|
63
|
-
"jeopi-ai": "16.
|
|
64
|
-
"jeopi-catalog": "16.
|
|
65
|
-
"jeopi-mnemopi": "16.
|
|
66
|
-
"jeopi-natives": "16.
|
|
67
|
-
"jeopi-tui": "16.
|
|
68
|
-
"jeopi-utils": "16.
|
|
69
|
-
"jeopi-wire": "16.
|
|
70
|
-
"jeopi-snapcompact": "16.
|
|
60
|
+
"jeopi-hashline": "16.4.0",
|
|
61
|
+
"jeopi-stats": "16.4.0",
|
|
62
|
+
"jeopi-agent-core": "16.4.0",
|
|
63
|
+
"jeopi-ai": "16.4.0",
|
|
64
|
+
"jeopi-catalog": "16.4.0",
|
|
65
|
+
"jeopi-mnemopi": "16.4.0",
|
|
66
|
+
"jeopi-natives": "16.4.0",
|
|
67
|
+
"jeopi-tui": "16.4.0",
|
|
68
|
+
"jeopi-utils": "16.4.0",
|
|
69
|
+
"jeopi-wire": "16.4.0",
|
|
70
|
+
"jeopi-snapcompact": "16.4.0",
|
|
71
71
|
"@opentelemetry/api": "^1.9.1",
|
|
72
72
|
"@opentelemetry/context-async-hooks": "^2.7.1",
|
|
73
73
|
"@opentelemetry/exporter-trace-otlp-proto": "^0.218.0",
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-learn session controller (experimental).
|
|
3
3
|
*
|
|
4
|
-
* Subscribes to the session event stream and, after a
|
|
5
|
-
* optionally auto-runs a synthetic capture turn.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Subscribes to the session event stream and, after a turn becomes eligible
|
|
5
|
+
* for the capture nudge, optionally auto-runs a synthetic capture turn. A
|
|
6
|
+
* turn is eligible via either of two independent paths: it cleared the
|
|
7
|
+
* `autolearn.minToolCalls` volume threshold, OR it saw at least one failed
|
|
8
|
+
* tool call regardless of volume — a single failure is treated as a likely
|
|
9
|
+
* reusable lesson even in an otherwise-short turn. Passive mode is
|
|
10
|
+
* intentionally prompt-cache neutral: the standing system guidance remains
|
|
11
|
+
* available, but no hidden mid-session reminder is inserted into the
|
|
12
|
+
* conversation.
|
|
8
13
|
*
|
|
9
14
|
* Installed once per top-level session (taskDepth 0). The subscription lives
|
|
10
15
|
* for the session's lifetime — `newSession` resets the session in place
|
|
@@ -54,6 +59,8 @@ export class AutoLearnController {
|
|
|
54
59
|
* would let a goal-continuation turn slip through and get nudged.
|
|
55
60
|
*/
|
|
56
61
|
#turnStartedInGoalMode = false;
|
|
62
|
+
/** Whether any `tool_execution_end` in the in-flight turn carried `isError === true`. */
|
|
63
|
+
#sawFailure = false;
|
|
57
64
|
/** Swallow the agent_end produced by an auto-run capture turn so it cannot re-trigger. */
|
|
58
65
|
#suppressNext = false;
|
|
59
66
|
|
|
@@ -73,6 +80,7 @@ export class AutoLearnController {
|
|
|
73
80
|
}
|
|
74
81
|
if (event.type === "tool_execution_end") {
|
|
75
82
|
this.#toolCalls++;
|
|
83
|
+
if (event.isError === true) this.#sawFailure = true;
|
|
76
84
|
return;
|
|
77
85
|
}
|
|
78
86
|
if (event.type === "agent_end") {
|
|
@@ -90,6 +98,10 @@ export class AutoLearnController {
|
|
|
90
98
|
// observed no agent_start can never inherit a stale value.
|
|
91
99
|
const startedInGoalMode = this.#turnStartedInGoalMode;
|
|
92
100
|
this.#turnStartedInGoalMode = false;
|
|
101
|
+
// Snapshot and reset alongside the counter above: a failure describes
|
|
102
|
+
// only the just-finished turn.
|
|
103
|
+
const sawFailure = this.#sawFailure;
|
|
104
|
+
this.#sawFailure = false;
|
|
93
105
|
|
|
94
106
|
if (this.#suppressNext) {
|
|
95
107
|
this.#suppressNext = false;
|
|
@@ -99,7 +111,11 @@ export class AutoLearnController {
|
|
|
99
111
|
// the current flag rather than trusting install-time state.
|
|
100
112
|
if (!this.#settings.get("autolearn.enabled")) return;
|
|
101
113
|
const minToolCalls = this.#settings.get("autolearn.minToolCalls") ?? DEFAULT_MIN_TOOL_CALLS;
|
|
102
|
-
|
|
114
|
+
// Eligible when EITHER the turn cleared the volume threshold OR it saw at
|
|
115
|
+
// least one failed tool call — a single failure is a reusable lesson
|
|
116
|
+
// regardless of how few tools ran, while the volume gate remains the
|
|
117
|
+
// fallback for long clean turns.
|
|
118
|
+
if (toolCalls < minToolCalls && !sawFailure) return;
|
|
103
119
|
// Never interrupt plan-mode review.
|
|
104
120
|
if (this.#session.getPlanModeState()?.enabled) return;
|
|
105
121
|
// Never divert a goal loop. Skip when the turn STARTED in goal mode — a
|
|
@@ -3560,6 +3560,18 @@ export const SETTINGS_SCHEMA = {
|
|
|
3560
3560
|
},
|
|
3561
3561
|
},
|
|
3562
3562
|
|
|
3563
|
+
"vision_verify.enabled": {
|
|
3564
|
+
type: "boolean",
|
|
3565
|
+
default: false,
|
|
3566
|
+
ui: {
|
|
3567
|
+
tab: "tools",
|
|
3568
|
+
group: "Available Tools",
|
|
3569
|
+
label: "Vision Verify",
|
|
3570
|
+
description:
|
|
3571
|
+
"Enable the vision_verify tool, checking a screenshot/artifact against a stated goal with a vision-capable model",
|
|
3572
|
+
},
|
|
3573
|
+
},
|
|
3574
|
+
|
|
3563
3575
|
"checkpoint.enabled": {
|
|
3564
3576
|
type: "boolean",
|
|
3565
3577
|
default: false,
|
|
@@ -4124,6 +4136,18 @@ export const SETTINGS_SCHEMA = {
|
|
|
4124
4136
|
},
|
|
4125
4137
|
},
|
|
4126
4138
|
|
|
4139
|
+
"task.autoModelTier": {
|
|
4140
|
+
type: "boolean",
|
|
4141
|
+
default: true,
|
|
4142
|
+
ui: {
|
|
4143
|
+
tab: "tasks",
|
|
4144
|
+
group: "Subagents",
|
|
4145
|
+
label: "Auto Model Tier for Simple Tasks",
|
|
4146
|
+
description:
|
|
4147
|
+
"Classify a task() spawn's assignment text and route trivially-simple work to the cheap 'smol' model tier instead of the default 'task' tier, when the caller has not explicitly overridden the model. Off-by-default agent-type model pins (named specialist agents like reviewer/critic/architect) are never affected — this only applies to the generic default 'task' agent.",
|
|
4148
|
+
},
|
|
4149
|
+
},
|
|
4150
|
+
|
|
4127
4151
|
"task.maxRecursionDepth": {
|
|
4128
4152
|
type: "number",
|
|
4129
4153
|
default: 2,
|
package/src/edit/index.ts
CHANGED
|
@@ -19,6 +19,7 @@ import replaceDescription from "../prompts/tools/replace.md" with { type: "text"
|
|
|
19
19
|
import type { DeferredDiagnosticsEntry, ToolSession } from "../tools";
|
|
20
20
|
import { truncateForPrompt } from "../tools/approval";
|
|
21
21
|
import { isInternalUrlPath } from "../tools/path-utils";
|
|
22
|
+
import { withPathWriteLock } from "../tools/path-write-lock";
|
|
22
23
|
import { type EditMode, normalizeEditMode, resolveEditMode } from "../utils/edit-mode";
|
|
23
24
|
import { executeHashlineSingle, hashlineEditParamsSchema } from "./hashline";
|
|
24
25
|
import { type ApplyPatchParams, applyPatchSchema, expandApplyPatchToEntries } from "./modes/apply-patch";
|
|
@@ -405,7 +406,7 @@ export class EditTool implements AgentTool<TInput> {
|
|
|
405
406
|
(session.enableLsp ?? true) &&
|
|
406
407
|
session.settings.get("lsp.diagnosticsOnEdit") &&
|
|
407
408
|
session.settings.get("lsp.diagnosticsDeduplicate");
|
|
408
|
-
this.#writethrough = createEditWritethrough(session);
|
|
409
|
+
this.#writethrough = withPathWriteLock(createEditWritethrough(session));
|
|
409
410
|
}
|
|
410
411
|
|
|
411
412
|
get mode(): EditMode {
|