@wrenautomation/raven 0.9.0 → 0.11.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 +10 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/plans/index.d.ts +9 -2
- package/dist/plans/index.js +32 -8
- package/dist/review.d.ts +3 -4
- package/dist/review.js +1 -12
- package/dist/types.d.ts +59 -2
- package/dist/types.js +30 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -12,11 +12,18 @@ Three calls, one record each:
|
|
|
12
12
|
|---|---|---|
|
|
13
13
|
| `plan` | an ask (text, kind, what is known, what the person says: `steer`, rendered first in every prompt), proposals from people or other models, yield rows from earlier runs | a `Plan`: typed queries, each with `why`, `from` (ai or human) and `by` (model id, plan file or person), the sources it may use, the budget, and a snapshot of what raven was given |
|
|
14
14
|
| `triage` | hits as a source shows them for free (title, channel, length, date, snippet, which sources returned it) | read or skip per hit; the model writes a why on a read only (a skip's is fixed text); the read budget caps it |
|
|
15
|
-
| `review` | what a round came to (counts, found lines with their dates, the extractor's verdict and gap per read, the steps' gaps, the sample check, notes) | the edge: `stop`, `again` (a new round from plan) or `back` (rerun one step), with why.
|
|
15
|
+
| `review` | what a round came to (counts, found lines with their dates, the extractor's verdict and gap per read, the steps' gaps, the sample check, notes) | the edge: `stop`, `again` (a new round from plan) or `back` (rerun one step), with why. The budget is shown, never enforced here: the runner parks past it |
|
|
16
16
|
|
|
17
17
|
Ask kinds: `web`, `video`, `channel`, `person`, `site`. Each has a default plan file
|
|
18
|
-
(prompts, sources, budget,
|
|
19
|
-
|
|
18
|
+
(prompts, sources, budget, `age`: one sentence on how much a source's age counts, and `tree`: the
|
|
19
|
+
facets a round's query tree covers and `thin`, the new hits under which a try falls through to the
|
|
20
|
+
next). Copy one,
|
|
21
|
+
tune it, keep it beside your ledger (`weaver learn`): that is where a run learns. Raven never
|
|
22
|
+
loops; the runner takes the edge.
|
|
23
|
+
|
|
24
|
+
Raven is the runner's planner. An agent that drives weaver's commands (`skills/birdwatch`) does
|
|
25
|
+
raven's three decisions itself and uses raven for its types (`Ask`, `Plan`, `PlanFile`, the
|
|
26
|
+
records), the merge of proposals, and the renderers.
|
|
20
27
|
|
|
21
28
|
## CLI
|
|
22
29
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { fill } from "./model.js";
|
|
2
2
|
export { mergeProposals, type PlanInput, plan, propose, proposePrompt } from "./plan.js";
|
|
3
|
-
export { defaultPlanFile, PLAN_KINDS } from "./plans/index.js";
|
|
3
|
+
export { ageOf, defaultPlanFile, PLAN_KINDS, TREE, treeOf } from "./plans/index.js";
|
|
4
4
|
export { renderHits, renderYield } from "./render.js";
|
|
5
5
|
export { review, reviewPrompt } from "./review.js";
|
|
6
6
|
export { dedupeHits, triage, triagePrompt } from "./triage.js";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { fill } from "./model.js";
|
|
2
2
|
export { mergeProposals, plan, propose, proposePrompt } from "./plan.js";
|
|
3
|
-
export { defaultPlanFile, PLAN_KINDS } from "./plans/index.js";
|
|
3
|
+
export { ageOf, defaultPlanFile, PLAN_KINDS, TREE, treeOf } from "./plans/index.js";
|
|
4
4
|
export { renderHits, renderYield } from "./render.js";
|
|
5
5
|
export { review, reviewPrompt } from "./review.js";
|
|
6
6
|
export { dedupeHits, triage, triagePrompt } from "./triage.js";
|
package/dist/plans/index.d.ts
CHANGED
|
@@ -2,9 +2,16 @@
|
|
|
2
2
|
* The default plan file per ask kind. A copy of one, tuned and stored beside a ledger, is how
|
|
3
3
|
* a run learns: the recipe changes, raven does not. `raven plans <kind>` prints one to start from.
|
|
4
4
|
*/
|
|
5
|
-
import { type AskKind, type PlanFile } from "../types.js";
|
|
5
|
+
import { type AskKind, type PlanFile, type TreeGuide } from "../types.js";
|
|
6
|
+
/**
|
|
7
|
+
* The five sides a researcher covers before the reads start. One tree per round; the agent
|
|
8
|
+
* fills each facet with tries, in order of what it expects to work.
|
|
9
|
+
*/
|
|
10
|
+
export declare const TREE: TreeGuide;
|
|
6
11
|
/** The default plan file for a kind, validated, as a fresh copy. */
|
|
7
12
|
export declare function defaultPlanFile(kind: AskKind): PlanFile;
|
|
8
|
-
/** The plan file's word on age; a stored file from before version 4 takes its kind's default. */
|
|
13
|
+
/** The plan file's word on age; a stored file from before version 4 takes its kind's default. Version 5: the review no longer says "at most". Version 6: `tree`, the query tree's guide. */
|
|
9
14
|
export declare const ageOf: (planFile: PlanFile) => string | undefined;
|
|
15
|
+
/** The plan file's guide for a query tree; a stored file from before version 6 takes its kind's default. */
|
|
16
|
+
export declare const treeOf: (planFile: PlanFile) => TreeGuide;
|
|
10
17
|
export declare const PLAN_KINDS: AskKind[];
|
package/dist/plans/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The default plan file per ask kind. A copy of one, tuned and stored beside a ledger, is how
|
|
3
3
|
* a run learns: the recipe changes, raven does not. `raven plans <kind>` prints one to start from.
|
|
4
4
|
*/
|
|
5
|
-
import { PlanFile as PlanFileShape } from "../types.js";
|
|
5
|
+
import { PlanFile as PlanFileShape, } from "../types.js";
|
|
6
6
|
const SHAPE_QUERIES = `Return ONLY a JSON object, no prose, exactly this shape:
|
|
7
7
|
{"queries": [{"terms": "...", "why": "..."}]}`;
|
|
8
8
|
const SHAPE_HITS = `Return ONLY a JSON object, no prose, exactly this shape:
|
|
@@ -33,7 +33,7 @@ Rules:
|
|
|
33
33
|
- "why" is one short line a person reads to agree or not. On "again" it is what the next plan reads first.
|
|
34
34
|
|
|
35
35
|
Ask: {ask}
|
|
36
|
-
{steer}Round {round}
|
|
36
|
+
{steer}Round {round}; the budget is {rounds} rounds, a guard rail (past it the runner parks and a person decides), not a stop rule. Hits {hits}, reads {reads}, findings proposed {proposed}, kept {kept}.
|
|
37
37
|
Found (the source's date in brackets when it gives one):
|
|
38
38
|
{found}
|
|
39
39
|
Read (quality: rich, thin, off or empty; then the gap, what the ask still lacks):
|
|
@@ -44,10 +44,27 @@ Checked (a sample of the kept findings, each against its document):
|
|
|
44
44
|
{checks}
|
|
45
45
|
Notes:
|
|
46
46
|
{notes}`;
|
|
47
|
+
/**
|
|
48
|
+
* The five sides a researcher covers before the reads start. One tree per round; the agent
|
|
49
|
+
* fills each facet with tries, in order of what it expects to work.
|
|
50
|
+
*/
|
|
51
|
+
export const TREE = {
|
|
52
|
+
facets: [
|
|
53
|
+
{ name: "number", why: "a figure: a rate, a price, a count, a date" },
|
|
54
|
+
{ name: "how", why: "how it is done: a method, a step list, a tool" },
|
|
55
|
+
{ name: "who", why: "who does it or buys it, in their own words" },
|
|
56
|
+
{ name: "counter", why: "the case against: what fails, who says no" },
|
|
57
|
+
{
|
|
58
|
+
name: "primary",
|
|
59
|
+
why: "the source itself: a study, a filing, a transcript, the maker's own page",
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
thin: 3,
|
|
63
|
+
};
|
|
47
64
|
const web = {
|
|
48
65
|
id: "raven/web",
|
|
49
66
|
kind: "web",
|
|
50
|
-
version:
|
|
67
|
+
version: 6,
|
|
51
68
|
propose: `You plan web searches for one research ask.
|
|
52
69
|
|
|
53
70
|
${SHAPE_QUERIES}
|
|
@@ -74,12 +91,13 @@ Hits:
|
|
|
74
91
|
review: REVIEW,
|
|
75
92
|
sources: ["searxng", "exa", "google"],
|
|
76
93
|
budget: { queries: 3, reads: 6, rounds: 3, checks: 3 },
|
|
94
|
+
tree: TREE,
|
|
77
95
|
age: "Prices, tools and numbers that move: prefer the last two years. A principle or a method can be old.",
|
|
78
96
|
};
|
|
79
97
|
const video = {
|
|
80
98
|
id: "raven/video",
|
|
81
99
|
kind: "video",
|
|
82
|
-
version:
|
|
100
|
+
version: 6,
|
|
83
101
|
propose: `You plan video searches for one research ask: talks, walkthroughs, interviews and reviews on YouTube and podcast feeds.
|
|
84
102
|
|
|
85
103
|
${SHAPE_QUERIES}
|
|
@@ -106,12 +124,13 @@ Hits:
|
|
|
106
124
|
review: REVIEW,
|
|
107
125
|
sources: ["youtube", "podcasts"],
|
|
108
126
|
budget: { queries: 3, reads: 4, rounds: 2, checks: 3 },
|
|
127
|
+
tree: TREE,
|
|
109
128
|
age: "Tools and platforms: prefer the last two years. A talk on a principle can be old.",
|
|
110
129
|
};
|
|
111
130
|
const channel = {
|
|
112
131
|
id: "raven/channel",
|
|
113
132
|
kind: "channel",
|
|
114
|
-
version:
|
|
133
|
+
version: 6,
|
|
115
134
|
propose: `You plan searches that find the people and channels worth following for one research ask: creators, newsletters, podcasts, forums.
|
|
116
135
|
|
|
117
136
|
${SHAPE_QUERIES}
|
|
@@ -136,12 +155,13 @@ Hits:
|
|
|
136
155
|
review: REVIEW,
|
|
137
156
|
sources: ["searxng", "youtube", "exa"],
|
|
138
157
|
budget: { queries: 3, reads: 6, rounds: 2, checks: 3 },
|
|
158
|
+
tree: TREE,
|
|
139
159
|
age: "A channel that has not posted in the last year counts for little.",
|
|
140
160
|
};
|
|
141
161
|
const person = {
|
|
142
162
|
id: "raven/person",
|
|
143
163
|
kind: "person",
|
|
144
|
-
version:
|
|
164
|
+
version: 6,
|
|
145
165
|
propose: `You plan searches about one person or company for one research ask: what they do, what they said, what others say about them.
|
|
146
166
|
|
|
147
167
|
${SHAPE_QUERIES}
|
|
@@ -168,12 +188,13 @@ Hits:
|
|
|
168
188
|
review: REVIEW,
|
|
169
189
|
sources: ["searxng", "exa", "linkedin", "google"],
|
|
170
190
|
budget: { queries: 4, reads: 6, rounds: 2, checks: 3 },
|
|
191
|
+
tree: TREE,
|
|
171
192
|
age: "What they do now: prefer the latest pages. Their history can be old.",
|
|
172
193
|
};
|
|
173
194
|
const site = {
|
|
174
195
|
id: "raven/site",
|
|
175
196
|
kind: "site",
|
|
176
|
-
version:
|
|
197
|
+
version: 6,
|
|
177
198
|
propose: `You plan searches inside one website for one research ask. Every query runs on {site} only.
|
|
178
199
|
|
|
179
200
|
${SHAPE_QUERIES}
|
|
@@ -199,6 +220,7 @@ Hits:
|
|
|
199
220
|
review: REVIEW,
|
|
200
221
|
sources: ["sitemap", "searxng", "fetch"],
|
|
201
222
|
budget: { queries: 4, reads: 8, rounds: 2, checks: 3 },
|
|
223
|
+
tree: TREE,
|
|
202
224
|
age: "When two pages of the site disagree, the later one counts.",
|
|
203
225
|
};
|
|
204
226
|
const DEFAULTS = { web, video, channel, person, site };
|
|
@@ -206,7 +228,9 @@ const DEFAULTS = { web, video, channel, person, site };
|
|
|
206
228
|
export function defaultPlanFile(kind) {
|
|
207
229
|
return PlanFileShape.parse(structuredClone(DEFAULTS[kind]));
|
|
208
230
|
}
|
|
209
|
-
/** The plan file's word on age; a stored file from before version 4 takes its kind's default. */
|
|
231
|
+
/** The plan file's word on age; a stored file from before version 4 takes its kind's default. Version 5: the review no longer says "at most". Version 6: `tree`, the query tree's guide. */
|
|
210
232
|
export const ageOf = (planFile) => planFile.age ?? DEFAULTS[planFile.kind].age;
|
|
233
|
+
/** The plan file's guide for a query tree; a stored file from before version 6 takes its kind's default. */
|
|
234
|
+
export const treeOf = (planFile) => planFile.tree ?? DEFAULTS[planFile.kind].tree;
|
|
211
235
|
export const PLAN_KINDS = Object.keys(DEFAULTS);
|
|
212
236
|
//# sourceMappingURL=index.js.map
|
package/dist/review.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* After a round: stop, go again from plan, or back to one step. The
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* stop whatever it answers. The runner takes the edge; raven never loops.
|
|
2
|
+
* After a round: stop, go again from plan, or back to one step. The model decides and says why;
|
|
3
|
+
* the round budget is a guard rail it sees (`{round}` of `{rounds}`), never a stop rule. The
|
|
4
|
+
* runner takes the edge and parks past the budget; raven never loops.
|
|
6
5
|
*/
|
|
7
6
|
import type { Model } from "@wrenautomation/models";
|
|
8
7
|
import { type Edge, type PlanFile, type Round } from "./types.js";
|
package/dist/review.js
CHANGED
|
@@ -26,20 +26,9 @@ export function reviewPrompt(round, planFile) {
|
|
|
26
26
|
verdicts: lines(round.verdicts.map(verdictLine), "(none)"),
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
|
-
/** Told to the model on the last round: its answer cannot be again or back. */
|
|
30
|
-
const LAST = "This is the last round: the run stops whatever you answer. Answer stop, and in why say what the ask still lacks, or that it is answered.";
|
|
31
29
|
export async function review(round, model, options = {}) {
|
|
32
30
|
const planFile = options.planFile ?? defaultPlanFile(round.ask.kind);
|
|
33
|
-
const
|
|
34
|
-
const shown = last ? { ...round, notes: [...round.notes, LAST] } : round;
|
|
35
|
-
const { value: out } = await model.ask(reviewPrompt(shown, planFile), EdgeAnswer);
|
|
36
|
-
if (last)
|
|
37
|
-
return {
|
|
38
|
-
next: "stop",
|
|
39
|
-
why: `round budget spent (${round.round} of ${round.budget.rounds}): ${out.why}`,
|
|
40
|
-
from: "ai",
|
|
41
|
-
by: model.id,
|
|
42
|
-
};
|
|
31
|
+
const { value: out } = await model.ask(reviewPrompt(round, planFile), EdgeAnswer);
|
|
43
32
|
const edge = { next: out.next, why: out.why, from: "ai", by: model.id };
|
|
44
33
|
if (out.next === "back")
|
|
45
34
|
edge.to = out.to ?? "fetch";
|
package/dist/types.d.ts
CHANGED
|
@@ -47,6 +47,8 @@ export declare const Query: z.ZodObject<{
|
|
|
47
47
|
terms: z.ZodString;
|
|
48
48
|
site: z.ZodOptional<z.ZodString>;
|
|
49
49
|
why: z.ZodString;
|
|
50
|
+
facet: z.ZodOptional<z.ZodString>;
|
|
51
|
+
tier: z.ZodOptional<z.ZodNumber>;
|
|
50
52
|
from: z.ZodEnum<{
|
|
51
53
|
ai: "ai";
|
|
52
54
|
human: "human";
|
|
@@ -72,9 +74,55 @@ export declare const Proposal: z.ZodObject<{
|
|
|
72
74
|
}>;
|
|
73
75
|
terms: z.ZodString;
|
|
74
76
|
why: z.ZodString;
|
|
77
|
+
facet: z.ZodOptional<z.ZodString>;
|
|
78
|
+
tier: z.ZodOptional<z.ZodNumber>;
|
|
75
79
|
}, z.core.$strip>>;
|
|
76
80
|
}, z.core.$strip>;
|
|
77
81
|
export type Proposal = z.infer<typeof Proposal>;
|
|
82
|
+
/** One query as a leaf of the tree: what a person would type, and why. */
|
|
83
|
+
export declare const Leaf: z.ZodObject<{
|
|
84
|
+
terms: z.ZodString;
|
|
85
|
+
why: z.ZodString;
|
|
86
|
+
site: z.ZodOptional<z.ZodString>;
|
|
87
|
+
}, z.core.$strip>;
|
|
88
|
+
export type Leaf = z.infer<typeof Leaf>;
|
|
89
|
+
/**
|
|
90
|
+
* One side of the ask a researcher covers: a number, a how, a who, a counter-view, a primary
|
|
91
|
+
* source. `tries` are its alternatives in order: the first runs; the next runs only when the
|
|
92
|
+
* one before it yielded thin (fewer new hits than the guide's `thin`), or when the agent asks.
|
|
93
|
+
*/
|
|
94
|
+
export declare const Facet: z.ZodObject<{
|
|
95
|
+
name: z.ZodString;
|
|
96
|
+
why: z.ZodString;
|
|
97
|
+
tries: z.ZodArray<z.ZodArray<z.ZodObject<{
|
|
98
|
+
terms: z.ZodString;
|
|
99
|
+
why: z.ZodString;
|
|
100
|
+
site: z.ZodOptional<z.ZodString>;
|
|
101
|
+
}, z.core.$strip>>>;
|
|
102
|
+
}, z.core.$strip>;
|
|
103
|
+
export type Facet = z.infer<typeof Facet>;
|
|
104
|
+
/** The fan-out for one round: the facets, each with its tries. The agent writes it; weaver runs it. */
|
|
105
|
+
export declare const QueryTree: z.ZodObject<{
|
|
106
|
+
facets: z.ZodArray<z.ZodObject<{
|
|
107
|
+
name: z.ZodString;
|
|
108
|
+
why: z.ZodString;
|
|
109
|
+
tries: z.ZodArray<z.ZodArray<z.ZodObject<{
|
|
110
|
+
terms: z.ZodString;
|
|
111
|
+
why: z.ZodString;
|
|
112
|
+
site: z.ZodOptional<z.ZodString>;
|
|
113
|
+
}, z.core.$strip>>>;
|
|
114
|
+
}, z.core.$strip>>;
|
|
115
|
+
}, z.core.$strip>;
|
|
116
|
+
export type QueryTree = z.infer<typeof QueryTree>;
|
|
117
|
+
/** The plan file's guide for a tree: the facets a tree of this kind covers, and what thin means. A guide, not a cap: a tree may add facets; one it leaves out is a warning. */
|
|
118
|
+
export declare const TreeGuide: z.ZodObject<{
|
|
119
|
+
facets: z.ZodArray<z.ZodObject<{
|
|
120
|
+
name: z.ZodString;
|
|
121
|
+
why: z.ZodString;
|
|
122
|
+
}, z.core.$strip>>;
|
|
123
|
+
thin: z.ZodNumber;
|
|
124
|
+
}, z.core.$strip>;
|
|
125
|
+
export type TreeGuide = z.infer<typeof TreeGuide>;
|
|
78
126
|
export declare const Budget: z.ZodObject<{
|
|
79
127
|
queries: z.ZodNumber;
|
|
80
128
|
reads: z.ZodNumber;
|
|
@@ -109,6 +157,13 @@ export declare const PlanFile: z.ZodObject<{
|
|
|
109
157
|
checks: z.ZodDefault<z.ZodNumber>;
|
|
110
158
|
}, z.core.$strip>;
|
|
111
159
|
age: z.ZodOptional<z.ZodString>;
|
|
160
|
+
tree: z.ZodOptional<z.ZodObject<{
|
|
161
|
+
facets: z.ZodArray<z.ZodObject<{
|
|
162
|
+
name: z.ZodString;
|
|
163
|
+
why: z.ZodString;
|
|
164
|
+
}, z.core.$strip>>;
|
|
165
|
+
thin: z.ZodNumber;
|
|
166
|
+
}, z.core.$strip>>;
|
|
112
167
|
}, z.core.$strip>;
|
|
113
168
|
export type PlanFile = z.infer<typeof PlanFile>;
|
|
114
169
|
/** What a source, channel or proposer yielded before. Raven reads it; wren or the files ledger writes it. */
|
|
@@ -168,6 +223,8 @@ export declare const Plan: z.ZodObject<{
|
|
|
168
223
|
terms: z.ZodString;
|
|
169
224
|
site: z.ZodOptional<z.ZodString>;
|
|
170
225
|
why: z.ZodString;
|
|
226
|
+
facet: z.ZodOptional<z.ZodString>;
|
|
227
|
+
tier: z.ZodOptional<z.ZodNumber>;
|
|
171
228
|
from: z.ZodEnum<{
|
|
172
229
|
ai: "ai";
|
|
173
230
|
human: "human";
|
|
@@ -221,8 +278,8 @@ export type Triage = z.infer<typeof Triage>;
|
|
|
221
278
|
export declare const Verdict: z.ZodObject<{
|
|
222
279
|
url: z.ZodString;
|
|
223
280
|
quality: z.ZodEnum<{
|
|
224
|
-
rich: "rich";
|
|
225
281
|
thin: "thin";
|
|
282
|
+
rich: "rich";
|
|
226
283
|
off: "off";
|
|
227
284
|
empty: "empty";
|
|
228
285
|
}>;
|
|
@@ -261,8 +318,8 @@ export declare const Round: z.ZodObject<{
|
|
|
261
318
|
verdicts: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
262
319
|
url: z.ZodString;
|
|
263
320
|
quality: z.ZodEnum<{
|
|
264
|
-
rich: "rich";
|
|
265
321
|
thin: "thin";
|
|
322
|
+
rich: "rich";
|
|
266
323
|
off: "off";
|
|
267
324
|
empty: "empty";
|
|
268
325
|
}>;
|
package/dist/types.js
CHANGED
|
@@ -28,6 +28,9 @@ export const Query = z.object({
|
|
|
28
28
|
site: z.string().optional(),
|
|
29
29
|
/** Why this query serves the ask: the line a reviewer reads first. */
|
|
30
30
|
why: z.string(),
|
|
31
|
+
/** The tree's facet it serves, and which try (1 = the first). Absent on a flat query. */
|
|
32
|
+
facet: z.string().optional(),
|
|
33
|
+
tier: z.number().int().positive().optional(),
|
|
31
34
|
from: From,
|
|
32
35
|
/** Model id, plan file id or a person's name. */
|
|
33
36
|
by: z.string(),
|
|
@@ -38,6 +41,31 @@ export const Proposal = z.object({
|
|
|
38
41
|
by: z.string(),
|
|
39
42
|
queries: z.array(Query.omit({ from: true, by: true })),
|
|
40
43
|
});
|
|
44
|
+
/** One query as a leaf of the tree: what a person would type, and why. */
|
|
45
|
+
export const Leaf = z.object({
|
|
46
|
+
terms: z.string().min(1),
|
|
47
|
+
why: z.string(),
|
|
48
|
+
site: z.string().optional(),
|
|
49
|
+
});
|
|
50
|
+
/**
|
|
51
|
+
* One side of the ask a researcher covers: a number, a how, a who, a counter-view, a primary
|
|
52
|
+
* source. `tries` are its alternatives in order: the first runs; the next runs only when the
|
|
53
|
+
* one before it yielded thin (fewer new hits than the guide's `thin`), or when the agent asks.
|
|
54
|
+
*/
|
|
55
|
+
export const Facet = z.object({
|
|
56
|
+
name: z.string().min(1),
|
|
57
|
+
/** What this facet would prove. */
|
|
58
|
+
why: z.string(),
|
|
59
|
+
tries: z.array(z.array(Leaf).min(1)).min(1),
|
|
60
|
+
});
|
|
61
|
+
/** The fan-out for one round: the facets, each with its tries. The agent writes it; weaver runs it. */
|
|
62
|
+
export const QueryTree = z.object({ facets: z.array(Facet).min(1) });
|
|
63
|
+
/** The plan file's guide for a tree: the facets a tree of this kind covers, and what thin means. A guide, not a cap: a tree may add facets; one it leaves out is a warning. */
|
|
64
|
+
export const TreeGuide = z.object({
|
|
65
|
+
facets: z.array(z.object({ name: z.string().min(1), why: z.string() })),
|
|
66
|
+
/** New hits under which a try counts as thin, so the next try runs. */
|
|
67
|
+
thin: z.number().int().nonnegative(),
|
|
68
|
+
});
|
|
41
69
|
export const Budget = z.object({
|
|
42
70
|
/** Queries per round after the merge. Human queries never count against it. */
|
|
43
71
|
queries: z.number().int().positive(),
|
|
@@ -69,6 +97,8 @@ export const PlanFile = z.object({
|
|
|
69
97
|
budget: Budget,
|
|
70
98
|
/** How much a source's age counts for this kind, one sentence: filled as `{age}`. Never a cutoff. */
|
|
71
99
|
age: z.string().optional(),
|
|
100
|
+
/** The facets a query tree of this kind covers. Absent on a file from before version 6: the kind's default. */
|
|
101
|
+
tree: TreeGuide.optional(),
|
|
72
102
|
});
|
|
73
103
|
/** What a source, channel or proposer yielded before. Raven reads it; wren or the files ledger writes it. */
|
|
74
104
|
export const YieldRow = z.object({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrenautomation/raven",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Ask in, plan out. The planner of Wren's research engine: typed queries with who proposed them and why, proposals merged into one plan under a plan file per ask kind, read-or-skip on hits, and the edge to take after a round. Pure functions and prompts; the model is injected.",
|
|
5
5
|
"license": "PolyForm-Strict-1.0.0",
|
|
6
6
|
"repository": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"commander": "15.0.0",
|
|
34
34
|
"zod": "4.6.5",
|
|
35
|
-
"@wrenautomation/models": "0.
|
|
35
|
+
"@wrenautomation/models": "0.11.0"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"typecheck": "tsc --noEmit",
|