@wrenautomation/raven 0.0.0-stage → 0.1.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.
- package/LICENSE.md +91 -0
- package/README.md +52 -2
- package/dist/app/cli.d.ts +2 -0
- package/dist/app/cli.js +115 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/dist/model.d.ts +20 -0
- package/dist/model.js +68 -0
- package/dist/plan.d.ts +31 -0
- package/dist/plan.js +90 -0
- package/dist/plans/index.d.ts +8 -0
- package/dist/plans/index.js +196 -0
- package/dist/render.d.ts +7 -0
- package/dist/render.js +40 -0
- package/dist/review.d.ts +11 -0
- package/dist/review.js +44 -0
- package/dist/triage.d.ts +15 -0
- package/dist/triage.js +65 -0
- package/dist/types.d.ts +265 -0
- package/dist/types.js +134 -0
- package/package.json +50 -4
package/dist/types.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shapes raven owns. A query says what to look for and who asked for it; a plan is the
|
|
3
|
+
* queries of one round plus the sources and budget it runs under; a plan file is the tuned
|
|
4
|
+
* recipe per ask kind. Hits are weaver's; raven sees them through `HitView`, the fields a
|
|
5
|
+
* source shows for free, because weaver depends on raven and not the reverse.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
export const AskKind = z.enum(["web", "video", "channel", "person", "site"]);
|
|
9
|
+
/** Who wrote a record: a model, a plan file or a person. */
|
|
10
|
+
export const From = z.enum(["ai", "human"]);
|
|
11
|
+
/** What someone wants to know, and what is known already. */
|
|
12
|
+
export const Ask = z.object({
|
|
13
|
+
text: z.string().min(1),
|
|
14
|
+
kind: AskKind,
|
|
15
|
+
/** Facts already in hand, one line each: the planner looks past them. */
|
|
16
|
+
known: z.array(z.string()).default([]),
|
|
17
|
+
/** Only for kind `site`, or when a query must stay on one host. */
|
|
18
|
+
site: z.string().optional(),
|
|
19
|
+
});
|
|
20
|
+
/** One thing to look for. `terms` is what a person would type; a source adapter forms its own call from it. */
|
|
21
|
+
export const Query = z.object({
|
|
22
|
+
kind: AskKind,
|
|
23
|
+
terms: z.string().min(1),
|
|
24
|
+
site: z.string().optional(),
|
|
25
|
+
/** Why this query serves the ask: the line a reviewer reads first. */
|
|
26
|
+
why: z.string(),
|
|
27
|
+
from: From,
|
|
28
|
+
/** Model id, plan file id or a person's name. */
|
|
29
|
+
by: z.string(),
|
|
30
|
+
});
|
|
31
|
+
/** Queries from one proposer. The model is one; a plan file, a teammate or a second model are others. */
|
|
32
|
+
export const Proposal = z.object({
|
|
33
|
+
from: From,
|
|
34
|
+
by: z.string(),
|
|
35
|
+
queries: z.array(Query.omit({ from: true, by: true })),
|
|
36
|
+
});
|
|
37
|
+
export const Budget = z.object({
|
|
38
|
+
/** Queries per round after the merge. Human queries never count against it. */
|
|
39
|
+
queries: z.number().int().positive(),
|
|
40
|
+
/** Documents to read per round. */
|
|
41
|
+
reads: z.number().int().positive(),
|
|
42
|
+
/** Rounds before `review` must stop. */
|
|
43
|
+
rounds: z.number().int().positive(),
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* The recipe for one ask kind: the prompts, the sources it may use, the budget. Versioned and
|
|
47
|
+
* tuned like an SOP, stored beside the ledger. `{name}` marks in a prompt are filled from the
|
|
48
|
+
* ask: `{ask}`, `{known}`, `{yield}`, `{n}`, `{year}`, `{site}`.
|
|
49
|
+
*/
|
|
50
|
+
export const PlanFile = z.object({
|
|
51
|
+
id: z.string().min(1),
|
|
52
|
+
kind: AskKind,
|
|
53
|
+
version: z.number().int().positive(),
|
|
54
|
+
/** Asks the model for queries. Must say to answer with `{"queries":[{"terms","why","site?"}]}`. */
|
|
55
|
+
propose: z.string().min(1),
|
|
56
|
+
/** Asks the model to read or skip each hit. Must say to answer with `{"hits":[{"url","read","why"}]}`. */
|
|
57
|
+
triage: z.string().min(1),
|
|
58
|
+
/** Asks the model which edge to take after a round. Must say to answer with `{"next","to?","why"}`. */
|
|
59
|
+
review: z.string().min(1),
|
|
60
|
+
/** Source names a run may use, in order of preference. A run can narrow the list, never widen it. */
|
|
61
|
+
sources: z.array(z.string()),
|
|
62
|
+
budget: Budget,
|
|
63
|
+
});
|
|
64
|
+
/** What a source, channel or proposer yielded before. Raven reads it; wren or the files ledger writes it. */
|
|
65
|
+
export const YieldRow = z.object({
|
|
66
|
+
by: z.string().optional(),
|
|
67
|
+
source: z.string().optional(),
|
|
68
|
+
channel: z.string().optional(),
|
|
69
|
+
kind: AskKind.optional(),
|
|
70
|
+
hits: z.number().int().nonnegative(),
|
|
71
|
+
reads: z.number().int().nonnegative(),
|
|
72
|
+
proposed: z.number().int().nonnegative(),
|
|
73
|
+
kept: z.number().int().nonnegative(),
|
|
74
|
+
});
|
|
75
|
+
/** What raven was given for one round: the RL state, kept with the plan. */
|
|
76
|
+
export const Snapshot = z.object({
|
|
77
|
+
at: z.string(),
|
|
78
|
+
known: z.array(z.string()),
|
|
79
|
+
planFile: z.object({ id: z.string(), version: z.number().int() }),
|
|
80
|
+
model: z.string().nullable(),
|
|
81
|
+
yieldRows: z.number().int().nonnegative(),
|
|
82
|
+
});
|
|
83
|
+
export const Plan = z.object({
|
|
84
|
+
ask: Ask,
|
|
85
|
+
round: z.number().int().positive(),
|
|
86
|
+
queries: z.array(Query),
|
|
87
|
+
sources: z.array(z.string()),
|
|
88
|
+
budget: Budget,
|
|
89
|
+
snapshot: Snapshot,
|
|
90
|
+
});
|
|
91
|
+
/** A hit as a source shows it for free: no read has happened. `sources` is every source that returned it. */
|
|
92
|
+
export const HitView = z.object({
|
|
93
|
+
url: z.string().min(1),
|
|
94
|
+
title: z.string().optional(),
|
|
95
|
+
channel: z.string().optional(),
|
|
96
|
+
/** Seconds, for video and audio. */
|
|
97
|
+
length: z.number().nonnegative().optional(),
|
|
98
|
+
/** ISO date, when the source gives one. */
|
|
99
|
+
date: z.string().optional(),
|
|
100
|
+
snippet: z.string().optional(),
|
|
101
|
+
sources: z.array(z.string()).default([]),
|
|
102
|
+
});
|
|
103
|
+
export const Triage = z.object({
|
|
104
|
+
url: z.string(),
|
|
105
|
+
read: z.boolean(),
|
|
106
|
+
why: z.string(),
|
|
107
|
+
from: From,
|
|
108
|
+
by: z.string(),
|
|
109
|
+
});
|
|
110
|
+
/** What one round came to, as counts and notes. The runner fills it; raven reads it. */
|
|
111
|
+
export const Round = z.object({
|
|
112
|
+
ask: Ask,
|
|
113
|
+
round: z.number().int().positive(),
|
|
114
|
+
budget: Budget,
|
|
115
|
+
hits: z.number().int().nonnegative(),
|
|
116
|
+
reads: z.number().int().nonnegative(),
|
|
117
|
+
proposed: z.number().int().nonnegative(),
|
|
118
|
+
kept: z.number().int().nonnegative(),
|
|
119
|
+
/** What the kept findings say, one line each: the planner sees what is answered. */
|
|
120
|
+
found: z.array(z.string()).default([]),
|
|
121
|
+
/** What went wrong or ran out, one line each. */
|
|
122
|
+
notes: z.array(z.string()).default([]),
|
|
123
|
+
});
|
|
124
|
+
export const Step = z.enum(["plan", "fetch", "read", "extract"]);
|
|
125
|
+
/** The edge out of a round. `again` is a new round from `plan`; `back` reruns one step of this round. */
|
|
126
|
+
export const Edge = z.object({
|
|
127
|
+
next: z.enum(["stop", "again", "back"]),
|
|
128
|
+
to: Step.optional(),
|
|
129
|
+
why: z.string(),
|
|
130
|
+
from: From,
|
|
131
|
+
by: z.string(),
|
|
132
|
+
});
|
|
133
|
+
export { z };
|
|
134
|
+
//# sourceMappingURL=types.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrenautomation/raven",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.1",
|
|
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
|
+
"license": "PolyForm-Shield-1.0.0",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/wrenautomation/raven.git"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"!dist/**/*.test.*",
|
|
14
|
+
"!dist/**/*.map"
|
|
15
|
+
],
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"bin": {
|
|
26
|
+
"raven": "dist/app/cli.js"
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=24"
|
|
30
|
+
},
|
|
31
|
+
"packageManager": "pnpm@9.15.0",
|
|
32
|
+
"scripts": {
|
|
33
|
+
"prepare": "git config core.hooksPath .githooks || true",
|
|
34
|
+
"lint": "biome check --error-on-warnings .",
|
|
35
|
+
"lint:fix": "biome check --write .",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
37
|
+
"build": "rm -rf dist && tsc && chmod +x dist/app/cli.js",
|
|
38
|
+
"test": "vitest run",
|
|
39
|
+
"gates": "lockf -t 900 /tmp/wren_automation-checks.lock sh -c 'pnpm lint && pnpm typecheck && pnpm test'",
|
|
40
|
+
"prepublishOnly": "pnpm build"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"commander": "15.0.0",
|
|
44
|
+
"zod": "4.6.5"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@biomejs/biome": "2.5.14",
|
|
48
|
+
"@types/node": "22.20.3",
|
|
49
|
+
"typescript": "5.9.3",
|
|
50
|
+
"vitest": "5.0.1"
|
|
51
|
+
}
|
|
52
|
+
}
|