@wrenautomation/birdwatch 0.29.0 → 0.30.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 +36 -53
- package/dist/app/cli.js +2 -2
- package/dist/app/cli.js.map +1 -1
- package/dist/app/engine-cli.d.ts +2 -8
- package/dist/app/engine-cli.js +18 -160
- package/dist/app/engine-cli.js.map +1 -1
- package/dist/app/index.d.ts +3 -3
- package/dist/app/index.js +3 -3
- package/dist/app/index.js.map +1 -1
- package/dist/document/extract.d.ts +1 -1
- package/dist/document/types.d.ts +2 -2
- package/dist/document/types.js +2 -2
- package/dist/engine/agent.d.ts +12 -10
- package/dist/engine/agent.js +21 -20
- package/dist/engine/agent.js.map +1 -1
- package/dist/engine/context.d.ts +9 -0
- package/dist/engine/{runner.js → context.js} +10 -78
- package/dist/engine/context.js.map +1 -0
- package/dist/engine/index.d.ts +2 -2
- package/dist/engine/index.js +2 -2
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/judge.d.ts +1 -1
- package/dist/engine/plan.d.ts +4 -4
- package/dist/engine/plan.js +4 -4
- package/dist/engine/plan.js.map +1 -1
- package/dist/{plan → engine}/plans/index.d.ts +4 -2
- package/dist/engine/plans/index.js +104 -0
- package/dist/engine/plans/index.js.map +1 -0
- package/dist/engine/ports.d.ts +9 -57
- package/dist/engine/ports.js +3 -3
- package/dist/engine/ports.js.map +1 -1
- package/dist/engine/recall.d.ts +1 -1
- package/dist/engine/state.d.ts +0 -3
- package/dist/engine/state.js +1 -25
- package/dist/engine/state.js.map +1 -1
- package/dist/engine/steps.d.ts +20 -20
- package/dist/engine/steps.js +42 -167
- package/dist/engine/steps.js.map +1 -1
- package/dist/engine/tree.d.ts +1 -1
- package/dist/engine/tree.js.map +1 -1
- package/dist/{plan → engine}/types.d.ts +14 -165
- package/dist/{plan → engine}/types.js +18 -73
- package/dist/engine/types.js.map +1 -0
- package/dist/index.d.ts +9 -9
- package/dist/index.js +9 -9
- package/dist/ledger/files.d.ts +1 -1
- package/dist/ledger/files.js +1 -1
- package/dist/ledger/files.js.map +1 -1
- package/dist/ledger/ledger.d.ts +2 -2
- package/dist/ledger/records.d.ts +139 -139
- package/dist/ledger/records.js +6 -6
- package/dist/ledger/records.js.map +1 -1
- package/dist/sources/arxiv.d.ts +1 -1
- package/dist/sources/google.d.ts +1 -1
- package/dist/sources/paste.d.ts +1 -1
- package/dist/sources/sites.d.ts +1 -1
- package/package.json +4 -8
- package/dist/engine/runner.d.ts +0 -30
- package/dist/engine/runner.js.map +0 -1
- package/dist/plan/index.d.ts +0 -7
- package/dist/plan/index.js +0 -8
- package/dist/plan/index.js.map +0 -1
- package/dist/plan/model.d.ts +0 -6
- package/dist/plan/model.js +0 -7
- package/dist/plan/model.js.map +0 -1
- package/dist/plan/plan.d.ts +0 -31
- package/dist/plan/plan.js +0 -87
- package/dist/plan/plan.js.map +0 -1
- package/dist/plan/plans/index.js +0 -236
- package/dist/plan/plans/index.js.map +0 -1
- package/dist/plan/render.d.ts +0 -41
- package/dist/plan/render.js +0 -75
- package/dist/plan/render.js.map +0 -1
- package/dist/plan/review.d.ts +0 -11
- package/dist/plan/review.js +0 -39
- package/dist/plan/review.js.map +0 -1
- package/dist/plan/triage.d.ts +0 -18
- package/dist/plan/triage.js +0 -65
- package/dist/plan/triage.js.map +0 -1
- package/dist/plan/types.js.map +0 -1
package/dist/engine/ports.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The ports
|
|
3
|
-
* `search` (hits for a query) or `open` (a hit read whole) or both; the registry holds
|
|
4
|
-
* name and the plan's allow-list picks per run. The model is the
|
|
2
|
+
* The ports each agent command is given, as one plain `deps` object. A source is one file that
|
|
3
|
+
* answers `search` (hits for a query) or `open` (a hit read whole) or both; the registry holds
|
|
4
|
+
* them by name and the plan's allow-list picks per run. The model is the bulk extract and check's, the extractor
|
|
5
5
|
* `./document`'s, the ledger `./ledger`'s. Nothing here reaches the network: the adapters in `src/sources` do.
|
|
6
6
|
*/
|
|
7
7
|
import type { Model } from "@wrenautomation/models";
|
|
@@ -10,7 +10,7 @@ import type { Document, Extractor } from "../document/index.js";
|
|
|
10
10
|
import type { Ids } from "../ledger/ids.js";
|
|
11
11
|
import type { Ledger } from "../ledger/ledger.js";
|
|
12
12
|
import type { CostKind, FollowAs, From, HitRecord, QueryRecord } from "../ledger/records.js";
|
|
13
|
-
import type {
|
|
13
|
+
import type { HitViewIn } from "./types.js";
|
|
14
14
|
export interface Source {
|
|
15
15
|
name: string;
|
|
16
16
|
kind: "search" | "open" | "both";
|
|
@@ -24,7 +24,7 @@ export interface Source {
|
|
|
24
24
|
* searcher that would answer from everywhere. Absent: it keeps to any site.
|
|
25
25
|
*/
|
|
26
26
|
keeps?(site: string): boolean;
|
|
27
|
-
/** Hits as the source shows them for free. Throw on failure: the
|
|
27
|
+
/** Hits as the source shows them for free. Throw on failure: the engine writes the spend. */
|
|
28
28
|
search?(query: QueryRecord): Promise<HitViewIn[]>;
|
|
29
29
|
/** Whether it lists that page's own posts (`posts`) or pages like it (`similar`). */
|
|
30
30
|
follows?(as: FollowAs, url: string): boolean;
|
|
@@ -43,7 +43,7 @@ export interface Source {
|
|
|
43
43
|
first?: true;
|
|
44
44
|
/**
|
|
45
45
|
* The hit read whole. Throw with the reason when it was fetched and nothing usable came back
|
|
46
|
-
* (a 403, a block, no reader for the media): the
|
|
46
|
+
* (a 403, a block, no reader for the media): the engine writes the spend `ok: false` with the
|
|
47
47
|
* reason and the next opener gets its turn.
|
|
48
48
|
*/
|
|
49
49
|
open?(hit: HitRecord): Promise<Document>;
|
|
@@ -55,66 +55,18 @@ export declare function pick(sources: Sources, names: readonly string[]): Source
|
|
|
55
55
|
export interface Deps {
|
|
56
56
|
sources: Sources;
|
|
57
57
|
ledger: Ledger;
|
|
58
|
-
/**
|
|
58
|
+
/** The bulk extract and check's model; null: none, and those two commands fail. */
|
|
59
59
|
model: Model | null;
|
|
60
|
-
/** The steps that decide what comes next (plan, triage, review) take it; absent: `model`. */
|
|
61
|
-
decider?: Model | null;
|
|
62
60
|
extractor: Extractor;
|
|
63
61
|
/** Cheap typed answers on every hit, page and finding: a hint and a router. Absent or null: none. */
|
|
64
62
|
judge?: Judge | null;
|
|
65
63
|
clock: () => Date;
|
|
66
64
|
ids: Ids;
|
|
67
|
-
/** `by` on the records the
|
|
68
|
-
|
|
65
|
+
/** `by` on the records the engine itself writes: this terminal's writer. */
|
|
66
|
+
writer: string;
|
|
69
67
|
/** The pause between tries of a call that failed with a Transient; `setTimeout` by default. A test passes a stub. */
|
|
70
68
|
sleep?: (ms: number) => Promise<void>;
|
|
71
69
|
}
|
|
72
|
-
export interface RunOptions {
|
|
73
|
-
/** Absent on a resume: the first snapshot has it. */
|
|
74
|
-
ask?: {
|
|
75
|
-
text: string;
|
|
76
|
-
kind: PlanFile["kind"];
|
|
77
|
-
known?: string[];
|
|
78
|
-
/** What the ask takes as given; a known line with no source joins them. */
|
|
79
|
-
premises?: string[];
|
|
80
|
-
/** The person's tests of a good source: the judge asks each on every hit and page. */
|
|
81
|
-
criteria?: Criterion[];
|
|
82
|
-
/** What the person says at the start; `steer` records add to it between rounds. */
|
|
83
|
-
steer?: string[];
|
|
84
|
-
site?: string;
|
|
85
|
-
};
|
|
86
|
-
/** The ledger's tuned plan file for the ask's kind; the stock one when absent. */
|
|
87
|
-
planFile?: PlanFile;
|
|
88
|
-
/** Queries from people or other models, merged with the model's in round 1. */
|
|
89
|
-
proposals?: readonly Proposal[];
|
|
90
|
-
/** Narrows the plan file's sources for this run. */
|
|
91
|
-
sources?: readonly string[];
|
|
92
|
-
/** Openers let in only to open and follow, never to search. Absent: the last snapshot's. */
|
|
93
|
-
opens?: readonly string[];
|
|
94
|
-
/** A new run's parent, and why this child: `--parent`. */
|
|
95
|
-
parent?: {
|
|
96
|
-
run: string;
|
|
97
|
-
why: string;
|
|
98
|
-
};
|
|
99
|
-
/** An earlier run to continue. */
|
|
100
|
-
resume?: string;
|
|
101
|
-
/** A run id for a new run; `deps.ids()` when absent. */
|
|
102
|
-
run?: string;
|
|
103
|
-
/** Called after each step, for a progress line. */
|
|
104
|
-
onStep?: (event: StepEvent) => void;
|
|
105
|
-
/** Steps to run before returning, whatever the pointer says: 64 by default. A loop that advances a run a little per pass passes a few. */
|
|
106
|
-
steps?: number;
|
|
107
|
-
/** Stop after each round's review when it says `again`: the person steers, then resumes. */
|
|
108
|
-
pause?: boolean;
|
|
109
|
-
}
|
|
110
|
-
export interface StepEvent {
|
|
111
|
-
run: string;
|
|
112
|
-
round: number;
|
|
113
|
-
step: string;
|
|
114
|
-
ok: boolean;
|
|
115
|
-
note?: string;
|
|
116
|
-
ms: number;
|
|
117
|
-
}
|
|
118
70
|
/**
|
|
119
71
|
* The searchers a query goes to: all of them, or for a site-scoped query those that keep to it.
|
|
120
72
|
* A follow goes to the sources that follow its URL that way.
|
package/dist/engine/ports.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The ports
|
|
3
|
-
* `search` (hits for a query) or `open` (a hit read whole) or both; the registry holds
|
|
4
|
-
* name and the plan's allow-list picks per run. The model is the
|
|
2
|
+
* The ports each agent command is given, as one plain `deps` object. A source is one file that
|
|
3
|
+
* answers `search` (hits for a query) or `open` (a hit read whole) or both; the registry holds
|
|
4
|
+
* them by name and the plan's allow-list picks per run. The model is the bulk extract and check's, the extractor
|
|
5
5
|
* `./document`'s, the ledger `./ledger`'s. Nothing here reaches the network: the adapters in `src/sources` do.
|
|
6
6
|
*/
|
|
7
7
|
export const registry = (...sources) => new Map(sources.map((s) => [s.name, s]));
|
package/dist/engine/ports.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ports.js","sourceRoot":"","sources":["../../src/engine/ports.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkDH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,GAAG,OAAiB,EAAW,EAAE,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAEpG,sGAAsG;AACtG,MAAM,UAAU,IAAI,CAAC,OAAgB,EAAE,KAAwB;IAC7D,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,IAAI,OAAO,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7E,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAW,CAAC,CAAC;AACpD,CAAC;
|
|
1
|
+
{"version":3,"file":"ports.js","sourceRoot":"","sources":["../../src/engine/ports.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkDH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,GAAG,OAAiB,EAAW,EAAE,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAEpG,sGAAsG;AACtG,MAAM,UAAU,IAAI,CAAC,OAAgB,EAAE,KAAwB;IAC7D,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,IAAI,OAAO,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7E,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAW,CAAC,CAAC;AACpD,CAAC;AAkBD;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,OAA0B,EAC1B,CAAuC,EAC7B,EAAE;IACZ,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;IACnB,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1E,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAClD,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAc,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3F,CAAC,CAAC;AAEF,oCAAoC;AACpC,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,CAAC"}
|
package/dist/engine/recall.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* still holds, puts it in `known` or reads the source again (WA-934, option A).
|
|
7
7
|
*/
|
|
8
8
|
import { type Ledger } from "../ledger/ledger.js";
|
|
9
|
-
import type { AskKind } from "
|
|
9
|
+
import type { AskKind } from "./plan.js";
|
|
10
10
|
export interface Recalled {
|
|
11
11
|
finding: string;
|
|
12
12
|
run: string;
|
package/dist/engine/state.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { type CallRecord, type CheckRecord, type ClassRecord, type DeadRecord, type DocumentRecord, type DraftRecord, type EdgeRecord, type FindingRecord, type FoundRecord, type GapRecord, type HitRecord, type JudgeRecord, type LedgerRecord, type PatternRecord, type PersonRecord, type QueryRecord, type SnapshotRecord, type SourceClass, type SpendRecord, type SteerRecord, type Step, type VerdictRecord } from "../ledger/records.js";
|
|
2
|
-
import { Plan } from "../plan/index.js";
|
|
3
2
|
export interface Pointer {
|
|
4
3
|
round: number;
|
|
5
4
|
step: Step;
|
|
@@ -52,8 +51,6 @@ export interface RunState {
|
|
|
52
51
|
}
|
|
53
52
|
/** Records must be in time order. */
|
|
54
53
|
export declare function fold(run: string, records: readonly LedgerRecord[]): RunState;
|
|
55
|
-
/** The plan of a round as the planner made it, rebuilt from its snapshot and queries. */
|
|
56
|
-
export declare function planOf(state: RunState, round: number): Plan;
|
|
57
54
|
/** A finding stays kept unless its latest call is a drop. */
|
|
58
55
|
export declare const kept: (state: RunState, f: FindingRecord) => boolean;
|
|
59
56
|
/** What the run has found so far: the kept findings' sentences with their URLs, oldest first. */
|
package/dist/engine/state.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A run's state is the fold of its records, never held between steps: every step reads the
|
|
3
|
-
* trace again. The fold gives the ask, the round, the plan
|
|
3
|
+
* trace again. The fold gives the ask, the round, the plan, what each step
|
|
4
4
|
* has handled, and the pointer: the next step to run, from the `done` and `edge` records.
|
|
5
5
|
*/
|
|
6
6
|
import { hostOf } from "../document/index.js";
|
|
7
7
|
import { latestCalls, ofType } from "../ledger/ledger.js";
|
|
8
8
|
import { STEPS, } from "../ledger/records.js";
|
|
9
|
-
import { Plan } from "../plan/index.js";
|
|
10
9
|
const after = (step) => STEPS[STEPS.indexOf(step) + 1] ?? null;
|
|
11
10
|
/** Records must be in time order. */
|
|
12
11
|
export function fold(run, records) {
|
|
@@ -71,29 +70,6 @@ export function fold(run, records) {
|
|
|
71
70
|
called: latestCalls(records),
|
|
72
71
|
};
|
|
73
72
|
}
|
|
74
|
-
const inRound = (round) => (r) => r.round === round;
|
|
75
|
-
/** The plan of a round as the planner made it, rebuilt from its snapshot and queries. */
|
|
76
|
-
export function planOf(state, round) {
|
|
77
|
-
const s = ofType(state.records, "snapshot").filter(inRound(round)).at(-1);
|
|
78
|
-
if (!s)
|
|
79
|
-
throw new Error(`round ${round} has no snapshot`);
|
|
80
|
-
const { ask, sources, budget, known, planFile, model, yieldRows, at } = s;
|
|
81
|
-
return Plan.parse({
|
|
82
|
-
ask,
|
|
83
|
-
round,
|
|
84
|
-
queries: state.queries.filter(inRound(round)).map((q) => ({
|
|
85
|
-
kind: q.kind,
|
|
86
|
-
terms: q.terms,
|
|
87
|
-
...(q.site ? { site: q.site } : {}),
|
|
88
|
-
why: q.why,
|
|
89
|
-
from: q.from === "tool" ? "ai" : q.from,
|
|
90
|
-
by: q.by,
|
|
91
|
-
})),
|
|
92
|
-
sources,
|
|
93
|
-
budget,
|
|
94
|
-
snapshot: { at, known, planFile, model, yieldRows },
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
73
|
/** A finding stays kept unless its latest call is a drop. */
|
|
98
74
|
export const kept = (state, f) => state.called.get(f.id) !== "drop";
|
|
99
75
|
/** What the run has found so far: the kept findings' sentences with their URLs, oldest first. */
|
package/dist/engine/state.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/engine/state.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAoBL,KAAK,GAIN,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/engine/state.ts"],"names":[],"mappings":"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"}
|
package/dist/engine/steps.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
3
|
-
*
|
|
4
|
-
* and appends records; it holds nothing between calls. Source calls fan out (per query across
|
|
2
|
+
* The fixed steps the agent commands run: search, read, extract, check. A step reads the fold,
|
|
3
|
+
* calls ports, and appends records; it holds nothing between calls. Source calls fan out (per query across
|
|
5
4
|
* the searchers; reads and extracts a few at a time) and their records land in order, so a
|
|
6
5
|
* trace reads the same whatever answered first. A step runs again after a transient failure
|
|
7
6
|
* from where its records say it got to: a search with an ok spend, a hit with a document, a
|
|
@@ -10,12 +9,12 @@
|
|
|
10
9
|
import { type Model } from "@wrenautomation/models";
|
|
11
10
|
import type { EntryType, Judged, JudgeFailure, Questions } from "@wrenautomation/models/judge";
|
|
12
11
|
import type { DocumentRecord, Envelope, FindingRecord, From, HitRecord, LedgerRecord, Step } from "../ledger/records.js";
|
|
13
|
-
import { type Deps, type
|
|
12
|
+
import { type Deps, type Source } from "./ports.js";
|
|
14
13
|
import { type RunState } from "./state.js";
|
|
15
14
|
import { type Parent } from "./tree.js";
|
|
15
|
+
import { HitView, type HitViewIn } from "./types.js";
|
|
16
16
|
export interface StepContext {
|
|
17
17
|
deps: Deps;
|
|
18
|
-
options: RunOptions;
|
|
19
18
|
/** The run's model, wrapped so every ask writes a spend; a Transient after the tries run out. */
|
|
20
19
|
model: Model | null;
|
|
21
20
|
/** The same model, its spends marked with the record they are about. */
|
|
@@ -56,8 +55,23 @@ export declare const PARALLEL = 4;
|
|
|
56
55
|
* keep or drop on its findings (often written after the review, between rounds).
|
|
57
56
|
*/
|
|
58
57
|
export declare const openAfter: (state: RunState, round: number) => string[];
|
|
58
|
+
/** A line with a URL or a ledger id on it: a fact someone can go and check. */
|
|
59
|
+
export declare const sourced: (line: string) => boolean;
|
|
59
60
|
/**
|
|
60
|
-
*
|
|
61
|
+
* The ask with each known line that names no source moved to its premises. A run seeded with
|
|
62
|
+
* "the buyer is X" plans inside X unless something tests X; a sourced line is looked past.
|
|
63
|
+
*/
|
|
64
|
+
export declare function withPremises<A extends {
|
|
65
|
+
known?: readonly string[];
|
|
66
|
+
premises?: readonly string[];
|
|
67
|
+
}>(ask: A): A & {
|
|
68
|
+
known: string[];
|
|
69
|
+
premises: string[];
|
|
70
|
+
};
|
|
71
|
+
/** One hit per url, sources merged, order of first sight. */
|
|
72
|
+
export declare function dedupeHits(hits: readonly HitViewIn[]): HitView[];
|
|
73
|
+
/**
|
|
74
|
+
* What a round's plan reads: the known lines (what
|
|
61
75
|
* the ask brought, what the run kept, then what its children found), the premises, and what is
|
|
62
76
|
* open (the last round's holes, children still going). A new child also reads what its parent
|
|
63
77
|
* and siblings found.
|
|
@@ -71,13 +85,8 @@ export declare function planAsk(deps: Pick<Deps, "ledger">, state: RunState, bas
|
|
|
71
85
|
premises: string[];
|
|
72
86
|
open: string[];
|
|
73
87
|
}>;
|
|
74
|
-
export declare const planStep: StepFn;
|
|
75
88
|
export declare const fetchStep: StepFn;
|
|
76
|
-
export declare const triageStep: StepFn;
|
|
77
|
-
export declare const readStep: StepFn;
|
|
78
|
-
/** Opens `hits`, each by the first opener that has it; the agent's `open` passes its own list. */
|
|
79
89
|
export declare function readHits(ctx: StepContext, state: RunState, wanted: readonly HitRecord[]): Promise<StepResult>;
|
|
80
|
-
export declare const extractStep: StepFn;
|
|
81
90
|
/** Extracts `docs` with the extractor on the run's model; the agent's `extract` passes its own list. */
|
|
82
91
|
export declare function extractDocuments(ctx: StepContext, state: RunState, docs: readonly DocumentRecord[]): Promise<StepResult>;
|
|
83
92
|
/**
|
|
@@ -86,13 +95,4 @@ export declare function extractDocuments(ctx: StepContext, state: RunState, docs
|
|
|
86
95
|
* drop call; one that holds gets a check record. The share that fails is the review's read on
|
|
87
96
|
* the extract. A check record is the checkpoint: a rerun checks only the rest of the sample.
|
|
88
97
|
*/
|
|
89
|
-
export declare const checkStep: StepFn;
|
|
90
|
-
/**
|
|
91
|
-
* Checks `findings` against their documents; the agent's `check` passes its own sample. The
|
|
92
|
-
* judge first reads every kept, unchecked finding with a quote; each one it doubts joins the
|
|
93
|
-
* sample. A judge's yes never takes a finding out of it. A fail's fix (a narrower sentence on
|
|
94
|
-
* the same quote) passes the gate and a second check before it lands as a new finding.
|
|
95
|
-
*/
|
|
96
98
|
export declare function checkSample(ctx: StepContext, state: RunState, sample: readonly FindingRecord[]): Promise<StepResult>;
|
|
97
|
-
export declare const reviewStep: StepFn;
|
|
98
|
-
export declare const STEP_TABLE: Record<Step, StepFn>;
|
package/dist/engine/steps.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
3
|
-
*
|
|
4
|
-
* and appends records; it holds nothing between calls. Source calls fan out (per query across
|
|
2
|
+
* The fixed steps the agent commands run: search, read, extract, check. A step reads the fold,
|
|
3
|
+
* calls ports, and appends records; it holds nothing between calls. Source calls fan out (per query across
|
|
5
4
|
* the searchers; reads and extracts a few at a time) and their records land in order, so a
|
|
6
5
|
* trace reads the same whatever answered first. A step runs again after a transient failure
|
|
7
6
|
* from where its records say it got to: a search with an ok spend, a hit with a document, a
|
|
@@ -9,12 +8,12 @@
|
|
|
9
8
|
*/
|
|
10
9
|
import { isTransient, Transient } from "@wrenautomation/models";
|
|
11
10
|
import { checkFinding, gateFindings } from "../document/index.js";
|
|
12
|
-
import { dedupeHits, defaultPlanFile, plan, review, triage, withPremises } from "../plan/index.js";
|
|
13
11
|
import { canonical } from "./canonical.js";
|
|
14
12
|
import { DOUBT, judgeDocuments, judgeFindings, judgeHits, passNote, yesOf } from "./judge.js";
|
|
15
13
|
import { FOLLOW_N, pick, searchersFor } from "./ports.js";
|
|
16
|
-
import { fold, found, kept
|
|
17
|
-
import {
|
|
14
|
+
import { fold, found, kept } from "./state.js";
|
|
15
|
+
import { fromChildren, fromSiblings, treeRoom } from "./tree.js";
|
|
16
|
+
import { HitView } from "./types.js";
|
|
18
17
|
const message = (err) => (err instanceof Error ? err.message : String(err));
|
|
19
18
|
/** Reads and extracts in flight at once. */
|
|
20
19
|
export const PARALLEL = 4;
|
|
@@ -87,8 +86,42 @@ async function batched(items, call, keep) {
|
|
|
87
86
|
}
|
|
88
87
|
return { transient };
|
|
89
88
|
}
|
|
89
|
+
/** A line with a URL or a ledger id on it: a fact someone can go and check. */
|
|
90
|
+
export const sourced = (line) => /https?:\/\/\S|\b[0-9A-HJKMNP-TV-Z]{26}\b/.test(line);
|
|
90
91
|
/**
|
|
91
|
-
*
|
|
92
|
+
* The ask with each known line that names no source moved to its premises. A run seeded with
|
|
93
|
+
* "the buyer is X" plans inside X unless something tests X; a sourced line is looked past.
|
|
94
|
+
*/
|
|
95
|
+
export function withPremises(ask) {
|
|
96
|
+
const known = ask.known ?? [];
|
|
97
|
+
return {
|
|
98
|
+
...ask,
|
|
99
|
+
known: known.filter(sourced),
|
|
100
|
+
premises: [...new Set([...(ask.premises ?? []), ...known.filter((l) => !sourced(l))])],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/** One hit per url, sources merged, order of first sight. */
|
|
104
|
+
export function dedupeHits(hits) {
|
|
105
|
+
const byUrl = new Map();
|
|
106
|
+
for (const h of hits.map((x) => HitView.parse(x))) {
|
|
107
|
+
const url = h.url.trim();
|
|
108
|
+
const have = byUrl.get(url);
|
|
109
|
+
if (!have) {
|
|
110
|
+
byUrl.set(url, { ...h, url, sources: [...new Set(h.sources)] });
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
for (const s of h.sources)
|
|
114
|
+
if (!have.sources.includes(s))
|
|
115
|
+
have.sources.push(s);
|
|
116
|
+
for (const k of ["title", "channel", "length", "date", "snippet"]) {
|
|
117
|
+
if (have[k] === undefined && h[k] !== undefined)
|
|
118
|
+
have[k] = h[k];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return [...byUrl.values()];
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* What a round's plan reads: the known lines (what
|
|
92
125
|
* the ask brought, what the run kept, then what its children found), the premises, and what is
|
|
93
126
|
* open (the last round's holes, children still going). A new child also reads what its parent
|
|
94
127
|
* and siblings found.
|
|
@@ -106,46 +139,6 @@ export async function planAsk(deps, state, base, round, parent) {
|
|
|
106
139
|
open: [...(round > 1 ? openAfter(state, round - 1) : []), ...children.open],
|
|
107
140
|
};
|
|
108
141
|
}
|
|
109
|
-
export const planStep = async (ctx, state) => {
|
|
110
|
-
const ask = state.snapshot?.ask ?? ctx.options.ask;
|
|
111
|
-
if (!ask)
|
|
112
|
-
return { ok: false, note: "no ask: a new run needs one" };
|
|
113
|
-
const planFile = ctx.options.planFile ?? defaultPlanFile(ask.kind);
|
|
114
|
-
const yieldRows = await ctx.deps.ledger.yield();
|
|
115
|
-
// A resume passes the same options: only a new run links; later rounds take the snapshot's.
|
|
116
|
-
const asked = state.snapshot ? undefined : ctx.options.parent;
|
|
117
|
-
const link = asked ? await linkTo(ctx.deps, asked, planFile) : null;
|
|
118
|
-
const parent = link?.parent ?? state.snapshot?.parent;
|
|
119
|
-
const { known, premises, open } = await planAsk(ctx.deps, state, ask, ctx.round, parent);
|
|
120
|
-
const steer = [...new Set([...(ask.steer ?? []), ...state.steers.map((s) => s.text)])];
|
|
121
|
-
const p = await plan({
|
|
122
|
-
ask: { ...ask, known, premises, steer, open, criteria: ask.criteria ?? [] },
|
|
123
|
-
planFile,
|
|
124
|
-
model: ctx.model,
|
|
125
|
-
proposals: ctx.round === 1 ? (ctx.options.proposals ?? []) : [],
|
|
126
|
-
yieldRows,
|
|
127
|
-
...(ctx.options.sources ? { sources: ctx.options.sources } : {}),
|
|
128
|
-
round: ctx.round,
|
|
129
|
-
now: ctx.deps.clock,
|
|
130
|
-
});
|
|
131
|
-
pick(ctx.deps.sources, p.sources);
|
|
132
|
-
const { at: _at, ...snapshot } = p.snapshot;
|
|
133
|
-
await ctx.write({
|
|
134
|
-
type: "snapshot",
|
|
135
|
-
ask: p.ask,
|
|
136
|
-
sources: p.sources,
|
|
137
|
-
opens: (ctx.options.opens ?? state.snapshot?.opens ?? []).filter((n) => !p.sources.includes(n)),
|
|
138
|
-
budget: await budgetUnder(ctx.deps, parent, p.budget),
|
|
139
|
-
...snapshot,
|
|
140
|
-
...(parent ? { parent } : { treeReads: treeReadsOf(planFile, p.budget) }),
|
|
141
|
-
}, tool(ctx.deps.runner));
|
|
142
|
-
for (const { from, by, ...q } of p.queries)
|
|
143
|
-
await ctx.write({ type: "query", ...q }, { from, by });
|
|
144
|
-
const warned = link?.warnings.length ? `; ${link.warnings.join("; ")}` : "";
|
|
145
|
-
return p.queries.length
|
|
146
|
-
? { ok: true, note: `${p.queries.length} queries over ${p.sources.join(", ")}${warned}` }
|
|
147
|
-
: { ok: false, note: "no queries: nothing proposed" };
|
|
148
|
-
};
|
|
149
142
|
export const fetchStep = async (ctx, state) => {
|
|
150
143
|
const queries = state.queries.filter((q) => q.round === ctx.round);
|
|
151
144
|
const searchers = sourcesOf(ctx, state);
|
|
@@ -227,7 +220,7 @@ export const fetchStep = async (ctx, state) => {
|
|
|
227
220
|
continue;
|
|
228
221
|
if (!searchersFor(q.follow ? followers : searchers, q).every((s) => okOn.has(`${q.id}\u0000${s.name}`)))
|
|
229
222
|
continue;
|
|
230
|
-
await ctx.write({ type: "gap", on: q.id, note: `query "${q.terms}": no new hits` }, tool(ctx.deps.
|
|
223
|
+
await ctx.write({ type: "gap", on: q.id, note: `query "${q.terms}": no new hits` }, tool(ctx.deps.writer));
|
|
231
224
|
empty++;
|
|
232
225
|
}
|
|
233
226
|
const judged = await judgeHits(ctx, fold(ctx.run, await ctx.deps.ledger.trace(ctx.run)));
|
|
@@ -236,49 +229,6 @@ export const fetchStep = async (ctx, state) => {
|
|
|
236
229
|
note: `${written} new hits${again ? `, ${again} found again,` : ""} from ${calls} searches${empty ? `, ${empty} queries with none` : ""}${passNote(judged)}`,
|
|
237
230
|
};
|
|
238
231
|
};
|
|
239
|
-
export const triageStep = async (ctx, state) => {
|
|
240
|
-
const hits = uncalledHits(state, ctx.round);
|
|
241
|
-
if (!hits.length)
|
|
242
|
-
return { ok: true, note: "no hits to triage" };
|
|
243
|
-
const p = planOf(state, ctx.round);
|
|
244
|
-
const byUrl = new Map(hits.map((h) => [h.url, h]));
|
|
245
|
-
if (!ctx.model) {
|
|
246
|
-
const budget = Math.max(0, p.budget.reads - toRead(state, ctx.round).length);
|
|
247
|
-
for (const [i, h] of hits.entries())
|
|
248
|
-
await ctx.write({
|
|
249
|
-
type: "call",
|
|
250
|
-
on: h.id,
|
|
251
|
-
verdict: i < budget ? "keep" : "drop",
|
|
252
|
-
why: i < budget ? "no model: read in order" : "no model: over the read budget",
|
|
253
|
-
}, tool(ctx.deps.runner));
|
|
254
|
-
return { ok: true, note: `no model: ${Math.min(budget, hits.length)} reads` };
|
|
255
|
-
}
|
|
256
|
-
const planFile = ctx.options.planFile ?? defaultPlanFile(p.ask.kind);
|
|
257
|
-
const views = hits.map(({ type: _t, id: _i, run: _r, round: _ro, step: _s, at: _a, from: _f, by: _b, key: _k, queries: _q, ...view }) => {
|
|
258
|
-
// Jev's yes on serves and each criterion: a hint the model sees, never the call
|
|
259
|
-
const odds = ["serves", ...(p.ask.criteria ?? []).map((c) => c.name)].flatMap((q) => {
|
|
260
|
-
const yes = yesOf(state, _i, q);
|
|
261
|
-
return yes === undefined ? [] : [[q, yes]];
|
|
262
|
-
});
|
|
263
|
-
return odds.length ? { ...view, odds: Object.fromEntries(odds) } : view;
|
|
264
|
-
});
|
|
265
|
-
const calls = await triage(views, p, ctx.model, {
|
|
266
|
-
planFile,
|
|
267
|
-
yieldRows: await ctx.deps.ledger.yield(),
|
|
268
|
-
});
|
|
269
|
-
let reads = 0;
|
|
270
|
-
for (const c of calls) {
|
|
271
|
-
const h = byUrl.get(c.url);
|
|
272
|
-
if (!h)
|
|
273
|
-
continue;
|
|
274
|
-
if (c.read)
|
|
275
|
-
reads++;
|
|
276
|
-
await ctx.write({ type: "call", on: h.id, verdict: c.read ? "keep" : "drop", why: c.why }, { from: c.from, by: c.by });
|
|
277
|
-
}
|
|
278
|
-
return { ok: true, note: `${reads} of ${hits.length} hits to read` };
|
|
279
|
-
};
|
|
280
|
-
export const readStep = (ctx, state) => readHits(ctx, state, toRead(state, ctx.round));
|
|
281
|
-
/** Opens `hits`, each by the first opener that has it; the agent's `open` passes its own list. */
|
|
282
232
|
export async function readHits(ctx, state, wanted) {
|
|
283
233
|
// The tree's cap is the one hard stop on reads.
|
|
284
234
|
const room = wanted.length ? await treeRoom(ctx.deps, ctx.run) : null;
|
|
@@ -333,7 +283,7 @@ export async function readHits(ctx, state, wanted) {
|
|
|
333
283
|
if (!g.missed || gapOn.has(h.id))
|
|
334
284
|
return;
|
|
335
285
|
const why = g.missed.length ? `: ${g.missed.join("; ")}` : "";
|
|
336
|
-
await ctx.write({ type: "gap", on: h.id, note: `no source could open ${h.url}${why}` }, tool(ctx.deps.
|
|
286
|
+
await ctx.write({ type: "gap", on: h.id, note: `no source could open ${h.url}${why}` }, tool(ctx.deps.writer));
|
|
337
287
|
missed++;
|
|
338
288
|
return;
|
|
339
289
|
}
|
|
@@ -356,8 +306,6 @@ export async function readHits(ctx, state, wanted) {
|
|
|
356
306
|
note: `${read} of ${hits.length} hits read${missed ? `, ${missed} no source could open` : ""}${capped}${hint}${passNote(judged)}`,
|
|
357
307
|
};
|
|
358
308
|
}
|
|
359
|
-
export const extractStep = (ctx, state) => extractDocuments(ctx, state, toExtract(state, ctx.round));
|
|
360
|
-
/** A transient stop that says what the step finished first: the next try does only the rest. */
|
|
361
309
|
const stopped = (t, finished) => new Transient(`${t.message} (${finished} before it stopped; run the step again for the rest)`, {
|
|
362
310
|
retryAfter: t.retryAfter,
|
|
363
311
|
...(t.status === undefined ? {} : { status: t.status }),
|
|
@@ -412,13 +360,6 @@ export async function extractDocuments(ctx, state, docs) {
|
|
|
412
360
|
* drop call; one that holds gets a check record. The share that fails is the review's read on
|
|
413
361
|
* the extract. A check record is the checkpoint: a rerun checks only the rest of the sample.
|
|
414
362
|
*/
|
|
415
|
-
export const checkStep = (ctx, state) => checkSample(ctx, state, toCheck(state, ctx.round, planOf(state, ctx.round).budget.checks));
|
|
416
|
-
/**
|
|
417
|
-
* Checks `findings` against their documents; the agent's `check` passes its own sample. The
|
|
418
|
-
* judge first reads every kept, unchecked finding with a quote; each one it doubts joins the
|
|
419
|
-
* sample. A judge's yes never takes a finding out of it. A fail's fix (a narrower sentence on
|
|
420
|
-
* the same quote) passes the gate and a second check before it lands as a new finding.
|
|
421
|
-
*/
|
|
422
363
|
export async function checkSample(ctx, state, sample) {
|
|
423
364
|
const checked = new Set(state.checks.map((c) => c.on));
|
|
424
365
|
const pool = state.findings.filter((f) => f.proof.quote && kept(state, f) && !checked.has(f.id));
|
|
@@ -491,70 +432,4 @@ export async function checkSample(ctx, state, sample) {
|
|
|
491
432
|
note: `${ok + failed} checked${why}, ${failed} not backed by their quote${fixed ? ` (${fixed} fixed: a narrower sentence on the same quote)` : ""}${judgeNote}`,
|
|
492
433
|
};
|
|
493
434
|
}
|
|
494
|
-
export const reviewStep = async (ctx, state) => {
|
|
495
|
-
const p = planOf(state, ctx.round);
|
|
496
|
-
const inRound = (r) => r.round === ctx.round;
|
|
497
|
-
const hits = state.hits.filter(inRound).length;
|
|
498
|
-
const reads = state.documents.filter(inRound).length;
|
|
499
|
-
const proposed = state.findings.filter(inRound).length;
|
|
500
|
-
const foundNow = found(state, ctx.round);
|
|
501
|
-
const dated = state.findings
|
|
502
|
-
.filter((f) => inRound(f) && kept(state, f))
|
|
503
|
-
.map((f) => (f.date ? `${f.text} [${f.date}]` : f.text));
|
|
504
|
-
const textOf = new Map(state.findings.map((f) => [f.id, f.text]));
|
|
505
|
-
const urlOf = new Map(state.documents.map((d) => [d.id, d.url]));
|
|
506
|
-
const round = {
|
|
507
|
-
ask: p.ask,
|
|
508
|
-
round: ctx.round,
|
|
509
|
-
budget: p.budget,
|
|
510
|
-
hits,
|
|
511
|
-
reads,
|
|
512
|
-
proposed,
|
|
513
|
-
kept: foundNow.length,
|
|
514
|
-
found: dated,
|
|
515
|
-
verdicts: state.verdicts.filter(inRound).map((v) => ({
|
|
516
|
-
url: urlOf.get(v.document) ?? v.document,
|
|
517
|
-
quality: v.quality,
|
|
518
|
-
...(v.gap ? { gap: v.gap } : {}),
|
|
519
|
-
})),
|
|
520
|
-
notes: [
|
|
521
|
-
...new Set(state.spends
|
|
522
|
-
.filter((s) => inRound(s) && !s.ok)
|
|
523
|
-
.map((s) => `${s.source} ${s.op} failed: ${s.error ?? "?"}`)),
|
|
524
|
-
...personCalls(state, ctx.round),
|
|
525
|
-
],
|
|
526
|
-
gaps: state.gaps.filter(inRound).map(gapLine),
|
|
527
|
-
checks: state.checks
|
|
528
|
-
.filter(inRound)
|
|
529
|
-
.map((c) => `${c.ok ? "ok" : "failed"}: ${textOf.get(c.on) ?? c.on} (${c.why})`),
|
|
530
|
-
earlier: Array.from({ length: ctx.round - 1 }, (_, i) => ({
|
|
531
|
-
hits: state.hits.filter((h) => h.round === i + 1).length,
|
|
532
|
-
kept: found(state, i + 1).length,
|
|
533
|
-
})),
|
|
534
|
-
};
|
|
535
|
-
const edge = ctx.model
|
|
536
|
-
? await review(round, ctx.model, {
|
|
537
|
-
planFile: ctx.options.planFile ?? defaultPlanFile(p.ask.kind),
|
|
538
|
-
})
|
|
539
|
-
: {
|
|
540
|
-
next: "stop",
|
|
541
|
-
why: "no model: one round",
|
|
542
|
-
from: "human",
|
|
543
|
-
by: ctx.deps.runner,
|
|
544
|
-
};
|
|
545
|
-
if (edge.next === "back" && !edge.to)
|
|
546
|
-
return { ok: false, note: "the edge says back but names no step" };
|
|
547
|
-
const { from, by, ...rest } = edge;
|
|
548
|
-
await ctx.write({ type: "edge", ...rest }, { from, by });
|
|
549
|
-
return { ok: true, note: `${edge.next}${edge.to ? ` to ${edge.to}` : ""}: ${edge.why}` };
|
|
550
|
-
};
|
|
551
|
-
export const STEP_TABLE = {
|
|
552
|
-
plan: planStep,
|
|
553
|
-
fetch: fetchStep,
|
|
554
|
-
triage: triageStep,
|
|
555
|
-
read: readStep,
|
|
556
|
-
extract: extractStep,
|
|
557
|
-
check: checkStep,
|
|
558
|
-
review: reviewStep,
|
|
559
|
-
};
|
|
560
435
|
//# sourceMappingURL=steps.js.map
|