@wrenautomation/raven 0.2.1 → 0.3.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 +4 -3
- package/dist/app/cli.js +8 -1
- package/dist/plan.js +2 -1
- package/dist/plans/index.js +13 -10
- package/dist/render.d.ts +2 -0
- package/dist/render.js +2 -0
- package/dist/review.js +4 -1
- package/dist/triage.d.ts +4 -1
- package/dist/triage.js +9 -5
- package/dist/types.d.ts +26 -1
- package/dist/types.js +12 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,9 +10,9 @@ Three calls, one record each:
|
|
|
10
10
|
|
|
11
11
|
| Call | In | Out |
|
|
12
12
|
|---|---|---|
|
|
13
|
-
| `plan` | an ask (text, kind, what is known), 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
|
-
| `triage` | hits as a source shows them for free (title, channel, length, date, snippet, which sources returned it) | read or skip per hit
|
|
15
|
-
| `review` | what a round came to (counts, found lines, notes) | the edge: `stop`, `again` (a new round from plan) or `back` (rerun one step), with why |
|
|
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
|
+
| `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, the extractor's verdict and gap per read, notes) | the edge: `stop`, `again` (a new round from plan) or `back` (rerun one step), with why |
|
|
16
16
|
|
|
17
17
|
Ask kinds: `web`, `video`, `channel`, `person`, `site`. Each has a default plan file
|
|
18
18
|
(prompts, sources, budget). Copy one, tune it, keep it beside your ledger: that is where a run
|
|
@@ -29,6 +29,7 @@ killed and the call fails with why.
|
|
|
29
29
|
```sh
|
|
30
30
|
npm i @wrenautomation/raven
|
|
31
31
|
npx raven plan "how do staffing firms win repeat clients" --known "referrals convert"
|
|
32
|
+
npx raven plan "..." --steer "numbers only, skip vendor pages" # what you say to the model, first in every prompt
|
|
32
33
|
npx raven plan "..." --kind video --propose "cold email teardown" --by will # yours merge with the model's
|
|
33
34
|
npx raven triage --plan plan.json --hits hits.json
|
|
34
35
|
npx raven review --round round.json
|
package/dist/app/cli.js
CHANGED
|
@@ -40,6 +40,7 @@ withModel(program
|
|
|
40
40
|
.option("-k, --kind <kind>", `one of ${PLAN_KINDS.join(", ")}`, "web")
|
|
41
41
|
.option("--site <host>", "keep every query on one host (kind site)")
|
|
42
42
|
.option("--known <line>", "a fact already in hand; repeat", more, [])
|
|
43
|
+
.option("--steer <line>", "what you say to the model, rendered first; repeat", more, [])
|
|
43
44
|
.option("--propose <terms>", "a query of your own; repeat", more, [])
|
|
44
45
|
.option("--by <name>", "who proposed the --propose queries", who())
|
|
45
46
|
.option("--plan-file <path>", "a tuned plan file (JSON) instead of the default")
|
|
@@ -47,7 +48,13 @@ withModel(program
|
|
|
47
48
|
.option("--sources <names>", "narrow the plan file's sources, comma separated")
|
|
48
49
|
.option("--round <n>", "round number", "1")).action(async (text, o) => {
|
|
49
50
|
const kind = AskKind.parse(o.kind);
|
|
50
|
-
const ask = {
|
|
51
|
+
const ask = {
|
|
52
|
+
text,
|
|
53
|
+
kind,
|
|
54
|
+
known: o.known,
|
|
55
|
+
steer: o.steer,
|
|
56
|
+
...(o.site ? { site: o.site } : {}),
|
|
57
|
+
};
|
|
51
58
|
const proposals = o.propose.length
|
|
52
59
|
? [
|
|
53
60
|
{
|
package/dist/plan.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { fill } from "./model.js";
|
|
7
7
|
import { defaultPlanFile } from "./plans/index.js";
|
|
8
|
-
import { lines, renderYield } from "./render.js";
|
|
8
|
+
import { lines, renderSteer, renderYield } from "./render.js";
|
|
9
9
|
import { z, } from "./types.js";
|
|
10
10
|
const ProposalAnswer = z.object({
|
|
11
11
|
queries: z.array(z.object({ terms: z.string(), why: z.string(), site: z.string().optional() })),
|
|
@@ -16,6 +16,7 @@ export function proposePrompt(ask, planFile, yieldRows, now) {
|
|
|
16
16
|
year: String(now.getUTCFullYear()),
|
|
17
17
|
ask: ask.text,
|
|
18
18
|
site: ask.site ?? "",
|
|
19
|
+
steer: renderSteer(ask.steer),
|
|
19
20
|
known: lines(ask.known),
|
|
20
21
|
yield: renderYield(yieldRows),
|
|
21
22
|
});
|
package/dist/plans/index.js
CHANGED
|
@@ -6,39 +6,42 @@ 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:
|
|
9
|
-
{"hits": [{"url": "...", "read": true, "why": "..."}]}`;
|
|
9
|
+
{"hits": [{"url": "...", "read": true, "why": "..."}, {"url": "...", "read": false}]}`;
|
|
10
10
|
const SHAPE_EDGE = `Return ONLY a JSON object, no prose, exactly this shape:
|
|
11
11
|
{"next": "stop", "why": "..."}
|
|
12
12
|
where "next" is "stop", "again" (a new round from plan) or "back" (rerun one step of this round, named in "to": "plan", "fetch", "triage", "read" or "extract").`;
|
|
13
13
|
const CONTEXT = `Ask: {ask}
|
|
14
|
-
Known already (look past these):
|
|
14
|
+
{steer}Known already (look past these):
|
|
15
15
|
{known}
|
|
16
16
|
What yielded before (hits, reads, proposed, kept):
|
|
17
17
|
{yield}`;
|
|
18
18
|
const TRIAGE_RULES = `- One entry per hit, with its url as given. Mark "read": true for at most {n}.
|
|
19
19
|
- Read a hit when what it shows for free (title, snippet, channel, length, date) says it holds what the ask needs and is not known already.
|
|
20
20
|
- A hit returned by more than one source is a good sign, not a duplicate.
|
|
21
|
-
- "why"
|
|
21
|
+
- "why" on a read only: one short line a person reads to agree or not. A skip has no "why".`;
|
|
22
22
|
const REVIEW = `You decide what happens after one round of research.
|
|
23
23
|
|
|
24
24
|
${SHAPE_EDGE}
|
|
25
25
|
|
|
26
26
|
Rules:
|
|
27
27
|
- "stop" when the found lines answer the ask, or when another round would likely add nothing.
|
|
28
|
-
- "again" when the ask is still open and new queries could find more.
|
|
28
|
+
- "again" when the ask is still open and new queries could find more. The gaps say what is missing; say what to look for next in "why".
|
|
29
|
+
- "again" too when the reads were mostly "thin" or "off": the queries found the wrong pages, so plan different ones.
|
|
29
30
|
- "back" when one step of this round failed for a reason a rerun fixes (a source was down, reads timed out). Name the step in "to".
|
|
30
31
|
- "why" is one short line a person reads to agree or not.
|
|
31
32
|
|
|
32
33
|
Ask: {ask}
|
|
33
|
-
Round {round} of at most {rounds}. Hits {hits}, reads {reads}, findings proposed {proposed}, kept {kept}.
|
|
34
|
+
{steer}Round {round} of at most {rounds}. Hits {hits}, reads {reads}, findings proposed {proposed}, kept {kept}.
|
|
34
35
|
Found:
|
|
35
36
|
{found}
|
|
37
|
+
Read (quality: rich, thin, off or empty; then the gap, what the ask still lacks):
|
|
38
|
+
{verdicts}
|
|
36
39
|
Notes:
|
|
37
40
|
{notes}`;
|
|
38
41
|
const web = {
|
|
39
42
|
id: "raven/web",
|
|
40
43
|
kind: "web",
|
|
41
|
-
version:
|
|
44
|
+
version: 3,
|
|
42
45
|
propose: `You plan web searches for one research ask.
|
|
43
46
|
|
|
44
47
|
${SHAPE_QUERIES}
|
|
@@ -69,7 +72,7 @@ Hits:
|
|
|
69
72
|
const video = {
|
|
70
73
|
id: "raven/video",
|
|
71
74
|
kind: "video",
|
|
72
|
-
version:
|
|
75
|
+
version: 3,
|
|
73
76
|
propose: `You plan video searches for one research ask: talks, walkthroughs, interviews and reviews on YouTube and podcast feeds.
|
|
74
77
|
|
|
75
78
|
${SHAPE_QUERIES}
|
|
@@ -100,7 +103,7 @@ Hits:
|
|
|
100
103
|
const channel = {
|
|
101
104
|
id: "raven/channel",
|
|
102
105
|
kind: "channel",
|
|
103
|
-
version:
|
|
106
|
+
version: 3,
|
|
104
107
|
propose: `You plan searches that find the people and channels worth following for one research ask: creators, newsletters, podcasts, forums.
|
|
105
108
|
|
|
106
109
|
${SHAPE_QUERIES}
|
|
@@ -129,7 +132,7 @@ Hits:
|
|
|
129
132
|
const person = {
|
|
130
133
|
id: "raven/person",
|
|
131
134
|
kind: "person",
|
|
132
|
-
version:
|
|
135
|
+
version: 3,
|
|
133
136
|
propose: `You plan searches about one person or company for one research ask: what they do, what they said, what others say about them.
|
|
134
137
|
|
|
135
138
|
${SHAPE_QUERIES}
|
|
@@ -160,7 +163,7 @@ Hits:
|
|
|
160
163
|
const site = {
|
|
161
164
|
id: "raven/site",
|
|
162
165
|
kind: "site",
|
|
163
|
-
version:
|
|
166
|
+
version: 3,
|
|
164
167
|
propose: `You plan searches inside one website for one research ask. Every query runs on {site} only.
|
|
165
168
|
|
|
166
169
|
${SHAPE_QUERIES}
|
package/dist/render.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/** Text the prompts take: what is known, what yielded, what a hit shows for free. */
|
|
2
2
|
import type { HitView, YieldRow } from "./types.js";
|
|
3
3
|
export declare const lines: (xs: readonly string[], none?: string) => string;
|
|
4
|
+
/** "The person says:" and their lines, or nothing: a prompt pays for the heading only when there is one. */
|
|
5
|
+
export declare const renderSteer: (steer: readonly string[] | undefined) => string;
|
|
4
6
|
/** One line per row, the keys it has first: `source=exa channel=... hits=12 reads=4 proposed=9 kept=3`. */
|
|
5
7
|
export declare function renderYield(rows: readonly YieldRow[]): string;
|
|
6
8
|
/** Numbered, one hit per line, only the fields it has. */
|
package/dist/render.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const lines = (xs, none = "(nothing)") => xs.length ? xs.map((x) => `- ${x}`).join("\n") : none;
|
|
2
|
+
/** "The person says:" and their lines, or nothing: a prompt pays for the heading only when there is one. */
|
|
3
|
+
export const renderSteer = (steer) => steer?.length ? `The person says:\n${lines(steer)}\n` : "";
|
|
2
4
|
/** One line per row, the keys it has first: `source=exa channel=... hits=12 reads=4 proposed=9 kept=3`. */
|
|
3
5
|
export function renderYield(rows) {
|
|
4
6
|
if (!rows.length)
|
package/dist/review.js
CHANGED
|
@@ -5,16 +5,18 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { fill } from "./model.js";
|
|
7
7
|
import { defaultPlanFile } from "./plans/index.js";
|
|
8
|
-
import { lines } from "./render.js";
|
|
8
|
+
import { lines, renderSteer } from "./render.js";
|
|
9
9
|
import { Step, z } from "./types.js";
|
|
10
10
|
const EdgeAnswer = z.object({
|
|
11
11
|
next: z.enum(["stop", "again", "back"]),
|
|
12
12
|
to: Step.optional(),
|
|
13
13
|
why: z.string(),
|
|
14
14
|
});
|
|
15
|
+
const verdictLine = (v) => `${v.url}: ${v.quality}${v.gap ? `. ${v.gap}` : ""}`;
|
|
15
16
|
export function reviewPrompt(round, planFile) {
|
|
16
17
|
return fill(planFile.review, {
|
|
17
18
|
ask: round.ask.text,
|
|
19
|
+
steer: renderSteer(round.ask.steer),
|
|
18
20
|
round: String(round.round),
|
|
19
21
|
rounds: String(round.budget.rounds),
|
|
20
22
|
hits: String(round.hits),
|
|
@@ -23,6 +25,7 @@ export function reviewPrompt(round, planFile) {
|
|
|
23
25
|
kept: String(round.kept),
|
|
24
26
|
found: lines(round.found),
|
|
25
27
|
notes: lines(round.notes, "(none)"),
|
|
28
|
+
verdicts: lines(round.verdicts.map(verdictLine), "(none)"),
|
|
26
29
|
});
|
|
27
30
|
}
|
|
28
31
|
export async function review(round, model, options = {}) {
|
package/dist/triage.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The filter before the read: for each hit, read or skip, from what the hit shows for free.
|
|
3
3
|
* Hits dedupe by url and keep every source that returned them. The model picks; the read budget
|
|
4
|
-
* caps it; a hit the model did not name is a skip, written down as one.
|
|
4
|
+
* caps it; a hit the model did not name is a skip, written down as one. The model writes a why
|
|
5
|
+
* on a read only: a skip's why is fixed text, so the answer pays for the reads alone.
|
|
5
6
|
*/
|
|
6
7
|
import { type Model } from "./model.js";
|
|
7
8
|
import { HitView, type HitViewIn, type Plan, type PlanFile, type Triage, type YieldRow } from "./types.js";
|
|
9
|
+
/** What a skip says: the model named it and passed. */
|
|
10
|
+
export declare const SKIPPED = "skipped by the model";
|
|
8
11
|
/** One hit per url, sources merged, order of first sight. */
|
|
9
12
|
export declare function dedupeHits(hits: readonly HitViewIn[]): HitView[];
|
|
10
13
|
export declare function triagePrompt(hits: readonly HitView[], plan: Plan, planFile: PlanFile, yieldRows: readonly YieldRow[]): string;
|
package/dist/triage.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The filter before the read: for each hit, read or skip, from what the hit shows for free.
|
|
3
3
|
* Hits dedupe by url and keep every source that returned them. The model picks; the read budget
|
|
4
|
-
* caps it; a hit the model did not name is a skip, written down as one.
|
|
4
|
+
* caps it; a hit the model did not name is a skip, written down as one. The model writes a why
|
|
5
|
+
* on a read only: a skip's why is fixed text, so the answer pays for the reads alone.
|
|
5
6
|
*/
|
|
6
7
|
import { fill } from "./model.js";
|
|
7
8
|
import { defaultPlanFile } from "./plans/index.js";
|
|
8
|
-
import { lines, renderHits, renderYield } from "./render.js";
|
|
9
|
+
import { lines, renderHits, renderSteer, renderYield } from "./render.js";
|
|
9
10
|
import { HitView, z, } from "./types.js";
|
|
10
11
|
const TriageAnswer = z.object({
|
|
11
|
-
hits: z.array(z.object({ url: z.string(), read: z.boolean(), why: z.string() })),
|
|
12
|
+
hits: z.array(z.object({ url: z.string(), read: z.boolean(), why: z.string().nullable().optional() })),
|
|
12
13
|
});
|
|
14
|
+
/** What a skip says: the model named it and passed. */
|
|
15
|
+
export const SKIPPED = "skipped by the model";
|
|
13
16
|
/** One hit per url, sources merged, order of first sight. */
|
|
14
17
|
export function dedupeHits(hits) {
|
|
15
18
|
const byUrl = new Map();
|
|
@@ -35,6 +38,7 @@ export function triagePrompt(hits, plan, planFile, yieldRows) {
|
|
|
35
38
|
n: String(plan.budget.reads),
|
|
36
39
|
ask: plan.ask.text,
|
|
37
40
|
site: plan.ask.site ?? "",
|
|
41
|
+
steer: renderSteer(plan.ask.steer),
|
|
38
42
|
known: lines(plan.ask.known),
|
|
39
43
|
yield: renderYield(yieldRows),
|
|
40
44
|
hits: renderHits(hits),
|
|
@@ -55,11 +59,11 @@ export async function triage(hits, plan, model, options = {}) {
|
|
|
55
59
|
if (!a)
|
|
56
60
|
return { ...base, read: false, why: "not named by the model" };
|
|
57
61
|
if (!a.read)
|
|
58
|
-
return { ...base, read: false, why: a.why };
|
|
62
|
+
return { ...base, read: false, why: a.why?.trim() || SKIPPED };
|
|
59
63
|
if (reads >= plan.budget.reads)
|
|
60
64
|
return { ...base, read: false, why: `over the read budget (${plan.budget.reads})` };
|
|
61
65
|
reads++;
|
|
62
|
-
return { ...base, read: true, why: a.why };
|
|
66
|
+
return { ...base, read: true, why: a.why?.trim() || "read" };
|
|
63
67
|
});
|
|
64
68
|
}
|
|
65
69
|
//# sourceMappingURL=triage.js.map
|
package/dist/types.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ export declare const Ask: z.ZodObject<{
|
|
|
30
30
|
site: "site";
|
|
31
31
|
}>;
|
|
32
32
|
known: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
33
|
+
steer: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
33
34
|
site: z.ZodOptional<z.ZodString>;
|
|
34
35
|
}, z.core.$strip>;
|
|
35
36
|
export type Ask = z.infer<typeof Ask>;
|
|
@@ -146,6 +147,7 @@ export declare const Plan: z.ZodObject<{
|
|
|
146
147
|
site: "site";
|
|
147
148
|
}>;
|
|
148
149
|
known: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
150
|
+
steer: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
149
151
|
site: z.ZodOptional<z.ZodString>;
|
|
150
152
|
}, z.core.$strip>;
|
|
151
153
|
round: z.ZodNumber;
|
|
@@ -208,7 +210,19 @@ export declare const Triage: z.ZodObject<{
|
|
|
208
210
|
by: z.ZodString;
|
|
209
211
|
}, z.core.$strip>;
|
|
210
212
|
export type Triage = z.infer<typeof Triage>;
|
|
211
|
-
/**
|
|
213
|
+
/** The extractor's word on one read document: how much of the ask it served, what is still missing. */
|
|
214
|
+
export declare const Verdict: z.ZodObject<{
|
|
215
|
+
url: z.ZodString;
|
|
216
|
+
quality: z.ZodEnum<{
|
|
217
|
+
rich: "rich";
|
|
218
|
+
thin: "thin";
|
|
219
|
+
off: "off";
|
|
220
|
+
empty: "empty";
|
|
221
|
+
}>;
|
|
222
|
+
gap: z.ZodOptional<z.ZodString>;
|
|
223
|
+
}, z.core.$strip>;
|
|
224
|
+
export type Verdict = z.infer<typeof Verdict>;
|
|
225
|
+
/** What one round came to, as counts, verdicts and notes. The runner fills it; raven reads it. */
|
|
212
226
|
export declare const Round: z.ZodObject<{
|
|
213
227
|
ask: z.ZodObject<{
|
|
214
228
|
text: z.ZodString;
|
|
@@ -220,6 +234,7 @@ export declare const Round: z.ZodObject<{
|
|
|
220
234
|
site: "site";
|
|
221
235
|
}>;
|
|
222
236
|
known: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
237
|
+
steer: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
223
238
|
site: z.ZodOptional<z.ZodString>;
|
|
224
239
|
}, z.core.$strip>;
|
|
225
240
|
round: z.ZodNumber;
|
|
@@ -234,6 +249,16 @@ export declare const Round: z.ZodObject<{
|
|
|
234
249
|
kept: z.ZodNumber;
|
|
235
250
|
found: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
236
251
|
notes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
252
|
+
verdicts: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
253
|
+
url: z.ZodString;
|
|
254
|
+
quality: z.ZodEnum<{
|
|
255
|
+
rich: "rich";
|
|
256
|
+
thin: "thin";
|
|
257
|
+
off: "off";
|
|
258
|
+
empty: "empty";
|
|
259
|
+
}>;
|
|
260
|
+
gap: z.ZodOptional<z.ZodString>;
|
|
261
|
+
}, z.core.$strip>>>;
|
|
237
262
|
}, z.core.$strip>;
|
|
238
263
|
export type Round = z.infer<typeof Round>;
|
|
239
264
|
export declare const Step: z.ZodEnum<{
|
package/dist/types.js
CHANGED
|
@@ -14,6 +14,8 @@ export const Ask = z.object({
|
|
|
14
14
|
kind: AskKind,
|
|
15
15
|
/** Facts already in hand, one line each: the planner looks past them. */
|
|
16
16
|
known: z.array(z.string()).default([]),
|
|
17
|
+
/** What the person said along the way, one line each: every prompt renders it first. */
|
|
18
|
+
steer: z.array(z.string()).default([]),
|
|
17
19
|
/** Only for kind `site`, or when a query must stay on one host. */
|
|
18
20
|
site: z.string().optional(),
|
|
19
21
|
});
|
|
@@ -103,11 +105,18 @@ export const HitView = z.object({
|
|
|
103
105
|
export const Triage = z.object({
|
|
104
106
|
url: z.string(),
|
|
105
107
|
read: z.boolean(),
|
|
108
|
+
/** The model's line on a read; a skip's is fixed text, so the model writes none. */
|
|
106
109
|
why: z.string(),
|
|
107
110
|
from: From,
|
|
108
111
|
by: z.string(),
|
|
109
112
|
});
|
|
110
|
-
/**
|
|
113
|
+
/** The extractor's word on one read document: how much of the ask it served, what is still missing. */
|
|
114
|
+
export const Verdict = z.object({
|
|
115
|
+
url: z.string(),
|
|
116
|
+
quality: z.enum(["rich", "thin", "off", "empty"]),
|
|
117
|
+
gap: z.string().optional(),
|
|
118
|
+
});
|
|
119
|
+
/** What one round came to, as counts, verdicts and notes. The runner fills it; raven reads it. */
|
|
111
120
|
export const Round = z.object({
|
|
112
121
|
ask: Ask,
|
|
113
122
|
round: z.number().int().positive(),
|
|
@@ -120,6 +129,8 @@ export const Round = z.object({
|
|
|
120
129
|
found: z.array(z.string()).default([]),
|
|
121
130
|
/** What went wrong or ran out, one line each. */
|
|
122
131
|
notes: z.array(z.string()).default([]),
|
|
132
|
+
/** The extractor's verdict on each document read this round: the planner sees what the reads were worth. */
|
|
133
|
+
verdicts: z.array(Verdict).default([]),
|
|
123
134
|
});
|
|
124
135
|
export const Step = z.enum(["plan", "fetch", "triage", "read", "extract"]);
|
|
125
136
|
/** The edge out of a round. `again` is a new round from `plan`; `back` reruns one step of this round. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrenautomation/raven",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.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-Shield-1.0.0",
|
|
6
6
|
"repository": {
|