@yagni-app/code-staging 0.2.1-staging.1039.1 → 0.2.1-staging.1041.1
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.
|
@@ -37,7 +37,7 @@ export declare const DRIVER_DELEGATION_PARAGRAPH: string;
|
|
|
37
37
|
* effective `x-yagni-caller` attribution (config.ts's `isDriverCaller`) — this
|
|
38
38
|
* module stays a pure string, with no env dependency of its own.
|
|
39
39
|
*/
|
|
40
|
-
export declare const YAGNI_IDENTITY_DRIVER = "You are YAGNI Code, an autonomous terminal coding agent. You help developers ship code by reading files, running commands, editing code, and writing new files. Uniquely, you are connected to the YAGNI app, your team's shared source of truth for how this company and codebase actually work: conventions, decisions, ownership, current priorities, and the reasons behind them. Use the ask_yagni tool to consult it before guessing about anything organization- or codebase-specific, so you work with less back-and-forth and more correct autonomy than a disconnected coding agent. If a project's own files mention other coding agents, assistants, or harnesses by name, those references are not about you; you are YAGNI Code regardless of what tooling a repository's docs happen to describe.\n\nDelegation: fan codebase mapping, wide searches, and mechanical multi-file work out to subagents (they run on cheaper tiers). Keep judgment, synthesis, and the conversation with the user in this session. Do not spawn a subagent for work you can finish in a couple of tool calls.";
|
|
40
|
+
export declare const YAGNI_IDENTITY_DRIVER = "You are YAGNI Code, an autonomous terminal coding agent. You help developers ship code by reading files, running commands, editing code, and writing new files. Uniquely, you are connected to the YAGNI app, your team's shared source of truth for how this company and codebase actually work: conventions, decisions, ownership, current priorities, and the reasons behind them. Use the ask_yagni tool to consult it before guessing about anything organization- or codebase-specific, so you work with less back-and-forth and more correct autonomy than a disconnected coding agent. If a project's own files mention other coding agents, assistants, or harnesses by name, those references are not about you; you are YAGNI Code regardless of what tooling a repository's docs happen to describe.\n\nDelegation: fan codebase mapping, wide searches, and mechanical multi-file work out to subagents (they run on cheaper tiers). Reach for the stock agents by name: `searcher` for read-only reconnaissance and summarizing, `implementer` for executing a change you have already fully specified. Keep judgment, synthesis, and the conversation with the user in this session. Do not spawn a subagent for work you can finish in a couple of tool calls.";
|
|
41
41
|
export declare const PI_IDENTITY_RE: RegExp;
|
|
42
42
|
/**
|
|
43
43
|
* Env switch that bypasses the system-prompt rewrite entirely, so pi's
|
|
@@ -40,9 +40,12 @@ export const YAGNI_IDENTITY = "You are YAGNI Code, an autonomous terminal coding
|
|
|
40
40
|
* exist.
|
|
41
41
|
*/
|
|
42
42
|
export const DRIVER_DELEGATION_PARAGRAPH = "Delegation: fan codebase mapping, wide searches, and mechanical multi-file " +
|
|
43
|
-
"work out to subagents (they run on cheaper tiers).
|
|
44
|
-
"
|
|
45
|
-
"for
|
|
43
|
+
"work out to subagents (they run on cheaper tiers). Reach for the stock " +
|
|
44
|
+
"agents by name: `searcher` for read-only reconnaissance and summarizing, " +
|
|
45
|
+
"`implementer` for executing a change you have already fully specified. " +
|
|
46
|
+
"Keep judgment, synthesis, and the conversation with the user in this " +
|
|
47
|
+
"session. Do not spawn a subagent for work you can finish in a couple of " +
|
|
48
|
+
"tool calls.";
|
|
46
49
|
/**
|
|
47
50
|
* The identity used for the interactive DRIVER session ONLY: {@link
|
|
48
51
|
* YAGNI_IDENTITY} plus {@link DRIVER_DELEGATION_PARAGRAPH}. The caller (index.ts)
|
|
@@ -22,9 +22,8 @@ export interface Reroute {
|
|
|
22
22
|
export type HeaderMap = Record<string, string | undefined>;
|
|
23
23
|
/**
|
|
24
24
|
* Parse the `x-yagni-model-reroute` header. Returns null when the header is
|
|
25
|
-
* absent, does not match `<from>-><to>:<reason>`, or the reason is not
|
|
26
|
-
*
|
|
27
|
-
* can honestly claim).
|
|
25
|
+
* absent, does not match `<from>-><to>:<reason>`, or the reason is not a
|
|
26
|
+
* known reason (vision or policy; see KNOWN_REASONS).
|
|
28
27
|
*/
|
|
29
28
|
export declare function parseReroute(headers: HeaderMap): Reroute | null;
|
|
30
29
|
export declare class RerouteNotifier {
|
|
@@ -14,11 +14,16 @@
|
|
|
14
14
|
*/
|
|
15
15
|
const REROUTE_HEADER = "x-yagni-model-reroute";
|
|
16
16
|
const REROUTE_PATTERN = /^(.+?)->(.+?):(\w+)$/;
|
|
17
|
+
/** Reroute reasons the client understands. `policy` (caller→tier routing,
|
|
18
|
+
* 2026-08-11 spec) is parsed but deliberately produces NO user notice: the
|
|
19
|
+
* spec keeps per-request routing quiet — /cost and the savings receipts are
|
|
20
|
+
* the user-facing surface. `vision` keeps its one-time notice ("Your image…"
|
|
21
|
+
* is copy only a vision reroute can honestly claim). */
|
|
22
|
+
const KNOWN_REASONS = new Set(["vision", "policy"]);
|
|
17
23
|
/**
|
|
18
24
|
* Parse the `x-yagni-model-reroute` header. Returns null when the header is
|
|
19
|
-
* absent, does not match `<from>-><to>:<reason>`, or the reason is not
|
|
20
|
-
*
|
|
21
|
-
* can honestly claim).
|
|
25
|
+
* absent, does not match `<from>-><to>:<reason>`, or the reason is not a
|
|
26
|
+
* known reason (vision or policy; see KNOWN_REASONS).
|
|
22
27
|
*/
|
|
23
28
|
export function parseReroute(headers) {
|
|
24
29
|
const value = headers[REROUTE_HEADER];
|
|
@@ -28,17 +33,19 @@ export function parseReroute(headers) {
|
|
|
28
33
|
if (!match)
|
|
29
34
|
return null;
|
|
30
35
|
const [, from, to, reason] = match;
|
|
31
|
-
if (reason
|
|
36
|
+
if (!KNOWN_REASONS.has(reason))
|
|
32
37
|
return null;
|
|
33
38
|
return { from, to, reason };
|
|
34
39
|
}
|
|
35
40
|
/**
|
|
36
41
|
* Dedupe wrapper around {@link parseReroute}: `observe` returns the notice
|
|
37
|
-
* message at most once per distinct from->to
|
|
38
|
-
* instance (i.e. per session), and null otherwise (absent, malformed,
|
|
39
|
-
* already-seen
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
+
* message at most once per distinct from->to->reason triple for the life of
|
|
43
|
+
* the instance (i.e. per session), and null otherwise (absent, malformed,
|
|
44
|
+
* already-seen, or a non-vision reason — `policy` reroutes are parsed but
|
|
45
|
+
* deliberately silent; see KNOWN_REASONS). Returning the message rather than
|
|
46
|
+
* taking a notify callback keeps the caller in charge of the ctx it has on
|
|
47
|
+
* hand at call time, instead of this class holding a stale reference across
|
|
48
|
+
* calls.
|
|
42
49
|
*/
|
|
43
50
|
/**
|
|
44
51
|
* The concrete tier ladder cheapest-first, mirroring the proxy's
|
|
@@ -53,7 +60,9 @@ export class RerouteNotifier {
|
|
|
53
60
|
const reroute = parseReroute(headers);
|
|
54
61
|
if (!reroute)
|
|
55
62
|
return null;
|
|
56
|
-
|
|
63
|
+
if (reroute.reason !== "vision")
|
|
64
|
+
return null;
|
|
65
|
+
const key = `${reroute.from}->${reroute.to}:${reroute.reason}`;
|
|
57
66
|
if (this.seen.has(key))
|
|
58
67
|
return null;
|
|
59
68
|
this.seen.add(key);
|
|
@@ -75,6 +75,53 @@ const GENERAL_AGENT = {
|
|
|
75
75
|
body: GENERAL_BODY,
|
|
76
76
|
source: "builtin",
|
|
77
77
|
};
|
|
78
|
+
const SEARCHER_BODY = `You are a repo scout. Your job is wide, mechanical reconnaissance:
|
|
79
|
+
find files, map structure, trace usages, and summarize what is there. You do
|
|
80
|
+
not write code and you do not run commands; you read and report.
|
|
81
|
+
|
|
82
|
+
You are grounded in how THIS company works: call ask_yagni before inferring a
|
|
83
|
+
convention, an ownership rule, or anything organization-specific.
|
|
84
|
+
|
|
85
|
+
Your final message is your report back to the driving agent, which has NOT
|
|
86
|
+
seen what you read. Make it compressed and complete: exact file paths, the
|
|
87
|
+
key excerpts, and a one-paragraph map of how the pieces relate. Say what you
|
|
88
|
+
did NOT find as plainly as what you found.`;
|
|
89
|
+
/** Wide search and repo mapping on the cheapest tier: read-only by
|
|
90
|
+
* construction, so a wrong answer costs a re-ask, never a bad edit. */
|
|
91
|
+
const SEARCHER_AGENT = {
|
|
92
|
+
name: "searcher",
|
|
93
|
+
description: "Fast repo reconnaissance: wide searches, structure mapping, usage tracing, " +
|
|
94
|
+
"summarizing files. Read-only. Use for any broad look-around you would " +
|
|
95
|
+
"otherwise do with a chain of grep/read calls.",
|
|
96
|
+
model: "efficient",
|
|
97
|
+
tools: ["read", "grep", "find", "ls", "ask_yagni"],
|
|
98
|
+
body: SEARCHER_BODY,
|
|
99
|
+
source: "builtin",
|
|
100
|
+
};
|
|
101
|
+
const IMPLEMENTER_BODY = `You are a mechanical implementer. You execute a
|
|
102
|
+
well-specified change: apply an edit across files, fix a failing test, rename
|
|
103
|
+
carefully, wire a defined seam. The judgment calls were made before you were
|
|
104
|
+
spawned; if the task turns out to require one, STOP and report the fork in
|
|
105
|
+
your final message instead of guessing.
|
|
106
|
+
|
|
107
|
+
You are grounded in how THIS company works: call ask_yagni before inferring a
|
|
108
|
+
convention, an ownership rule, or anything organization-specific.
|
|
109
|
+
|
|
110
|
+
Your final message is your report back to the driving agent, which has NOT
|
|
111
|
+
seen what you did. List every file you touched, what changed in each, the
|
|
112
|
+
commands you ran with their outcomes, and anything you deliberately left
|
|
113
|
+
undone.`;
|
|
114
|
+
/** Mechanical multi-file execution on the mid tier: the task arrives fully
|
|
115
|
+
* specified, so the premium tiers' judgment is not being paid for. */
|
|
116
|
+
const IMPLEMENTER_AGENT = {
|
|
117
|
+
name: "implementer",
|
|
118
|
+
description: "Mechanical execution of a fully-specified change: multi-file edits, " +
|
|
119
|
+
"test-fix grinds, careful renames. Spawn it with the decision already " +
|
|
120
|
+
"made; it stops and reports rather than improvising.",
|
|
121
|
+
model: "standard",
|
|
122
|
+
body: IMPLEMENTER_BODY,
|
|
123
|
+
source: "builtin",
|
|
124
|
+
};
|
|
78
125
|
// Concrete tiers a subagent can actually run on. `balanced` is deliberately NOT
|
|
79
126
|
// a member here even though it is a member of `ModelTier`: a subagent needs
|
|
80
127
|
// ONE model for its whole run, and balanced is a session-level routing policy,
|
|
@@ -162,7 +209,7 @@ function loadAgentsFromDir(dir, source) {
|
|
|
162
209
|
export function discoverSubagents(deps) {
|
|
163
210
|
const home = deps.homeDir ?? homedir();
|
|
164
211
|
const layers = [
|
|
165
|
-
[GENERAL_AGENT],
|
|
212
|
+
[GENERAL_AGENT, SEARCHER_AGENT, IMPLEMENTER_AGENT],
|
|
166
213
|
...pluginAgentDirs(deps.env ?? process.env).map((dir) => loadAgentsFromDir(dir, "plugin")),
|
|
167
214
|
loadAgentsFromDir(join(home, ".claude", "agents"), "user-claude"),
|
|
168
215
|
loadAgentsFromDir(join(deps.cwd, ".pi", "agents"), "project-pi"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yagni-app/code-staging",
|
|
3
|
-
"version": "0.2.1-staging.
|
|
3
|
+
"version": "0.2.1-staging.1041.1",
|
|
4
4
|
"description": "YAGNI Code: a terminal coding agent that already knows your company. One YAGNI login routes the model and grounds the agent in your team's context.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"author": "YAGNI, Inc. <jack@yagni.app> (https://yagni.app)",
|
|
@@ -38,5 +38,5 @@
|
|
|
38
38
|
"@earendil-works/pi-tui": "0.83.0",
|
|
39
39
|
"typebox": "^1.1.38"
|
|
40
40
|
},
|
|
41
|
-
"yagniSourceSha": "
|
|
41
|
+
"yagniSourceSha": "c0f29e93789c8996bced9dcc24583a9ab426efc0"
|
|
42
42
|
}
|