@wrenautomation/birdwatch 0.0.0-stage → 0.29.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/LICENSE.md +61 -0
- package/README.md +337 -2
- package/dist/app/cli.d.ts +4 -0
- package/dist/app/cli.js +149 -0
- package/dist/app/cli.js.map +1 -0
- package/dist/app/engine-cli.d.ts +50 -0
- package/dist/app/engine-cli.js +738 -0
- package/dist/app/engine-cli.js.map +1 -0
- package/dist/app/index.d.ts +6 -0
- package/dist/app/index.js +7 -0
- package/dist/app/index.js.map +1 -0
- package/dist/app/serve.d.ts +14 -0
- package/dist/app/serve.js +102 -0
- package/dist/app/serve.js.map +1 -0
- package/dist/document/body.d.ts +6 -0
- package/dist/document/body.js +18 -0
- package/dist/document/body.js.map +1 -0
- package/dist/document/check.d.ts +35 -0
- package/dist/document/check.js +68 -0
- package/dist/document/check.js.map +1 -0
- package/dist/document/extract.d.ts +81 -0
- package/dist/document/extract.js +226 -0
- package/dist/document/extract.js.map +1 -0
- package/dist/document/index.d.ts +11 -0
- package/dist/document/index.js +12 -0
- package/dist/document/index.js.map +1 -0
- package/dist/document/model.d.ts +10 -0
- package/dist/document/model.js +2 -0
- package/dist/document/model.js.map +1 -0
- package/dist/document/readers.d.ts +24 -0
- package/dist/document/readers.js +87 -0
- package/dist/document/readers.js.map +1 -0
- package/dist/document/types.d.ts +99 -0
- package/dist/document/types.js +93 -0
- package/dist/document/types.js.map +1 -0
- package/dist/engine/agent.d.ts +473 -0
- package/dist/engine/agent.js +989 -0
- package/dist/engine/agent.js.map +1 -0
- package/dist/engine/canonical.d.ts +4 -0
- package/dist/engine/canonical.js +55 -0
- package/dist/engine/canonical.js.map +1 -0
- package/dist/engine/cost.d.ts +13 -0
- package/dist/engine/cost.js +31 -0
- package/dist/engine/cost.js.map +1 -0
- package/dist/engine/index.d.ts +16 -0
- package/dist/engine/index.js +17 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/judge.d.ts +158 -0
- package/dist/engine/judge.js +323 -0
- package/dist/engine/judge.js.map +1 -0
- package/dist/engine/people.d.ts +34 -0
- package/dist/engine/people.js +125 -0
- package/dist/engine/people.js.map +1 -0
- package/dist/engine/plan.d.ts +6 -0
- package/dist/engine/plan.js +7 -0
- package/dist/engine/plan.js.map +1 -0
- package/dist/engine/ports.d.ts +124 -0
- package/dist/engine/ports.js +28 -0
- package/dist/engine/ports.js.map +1 -0
- package/dist/engine/recall.d.ts +42 -0
- package/dist/engine/recall.js +71 -0
- package/dist/engine/recall.js.map +1 -0
- package/dist/engine/runner.d.ts +30 -0
- package/dist/engine/runner.js +209 -0
- package/dist/engine/runner.js.map +1 -0
- package/dist/engine/state.d.ts +99 -0
- package/dist/engine/state.js +186 -0
- package/dist/engine/state.js.map +1 -0
- package/dist/engine/steps.d.ts +98 -0
- package/dist/engine/steps.js +560 -0
- package/dist/engine/steps.js.map +1 -0
- package/dist/engine/tree.d.ts +76 -0
- package/dist/engine/tree.js +148 -0
- package/dist/engine/tree.js.map +1 -0
- package/dist/engine/view.d.ts +138 -0
- package/dist/engine/view.js +188 -0
- package/dist/engine/view.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/ledger/files.d.ts +39 -0
- package/dist/ledger/files.js +113 -0
- package/dist/ledger/files.js.map +1 -0
- package/dist/ledger/ids.d.ts +4 -0
- package/dist/ledger/ids.js +9 -0
- package/dist/ledger/ids.js.map +1 -0
- package/dist/ledger/index.d.ts +11 -0
- package/dist/ledger/index.js +12 -0
- package/dist/ledger/index.js.map +1 -0
- package/dist/ledger/ledger.d.ts +46 -0
- package/dist/ledger/ledger.js +105 -0
- package/dist/ledger/ledger.js.map +1 -0
- package/dist/ledger/memory.d.ts +19 -0
- package/dist/ledger/memory.js +19 -0
- package/dist/ledger/memory.js.map +1 -0
- package/dist/ledger/records.d.ts +1424 -0
- package/dist/ledger/records.js +292 -0
- package/dist/ledger/records.js.map +1 -0
- package/dist/plan/index.d.ts +7 -0
- package/dist/plan/index.js +8 -0
- package/dist/plan/index.js.map +1 -0
- package/dist/plan/model.d.ts +6 -0
- package/dist/plan/model.js +7 -0
- package/dist/plan/model.js.map +1 -0
- package/dist/plan/plan.d.ts +31 -0
- package/dist/plan/plan.js +87 -0
- package/dist/plan/plan.js.map +1 -0
- package/dist/plan/plans/index.d.ts +17 -0
- package/dist/plan/plans/index.js +236 -0
- package/dist/plan/plans/index.js.map +1 -0
- package/dist/plan/render.d.ts +41 -0
- package/dist/plan/render.js +75 -0
- package/dist/plan/render.js.map +1 -0
- package/dist/plan/review.d.ts +11 -0
- package/dist/plan/review.js +39 -0
- package/dist/plan/review.js.map +1 -0
- package/dist/plan/triage.d.ts +18 -0
- package/dist/plan/triage.js +65 -0
- package/dist/plan/triage.js.map +1 -0
- package/dist/plan/types.d.ts +401 -0
- package/dist/plan/types.js +223 -0
- package/dist/plan/types.js.map +1 -0
- package/dist/sources/arxiv.d.ts +105 -0
- package/dist/sources/arxiv.js +321 -0
- package/dist/sources/arxiv.js.map +1 -0
- package/dist/sources/exa.d.ts +19 -0
- package/dist/sources/exa.js +59 -0
- package/dist/sources/exa.js.map +1 -0
- package/dist/sources/fetcher.d.ts +35 -0
- package/dist/sources/fetcher.js +67 -0
- package/dist/sources/fetcher.js.map +1 -0
- package/dist/sources/google.d.ts +16 -0
- package/dist/sources/google.js +64 -0
- package/dist/sources/google.js.map +1 -0
- package/dist/sources/index.d.ts +17 -0
- package/dist/sources/index.js +18 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/sources/junk.d.ts +10 -0
- package/dist/sources/junk.js +16 -0
- package/dist/sources/junk.js.map +1 -0
- package/dist/sources/ladder.d.ts +47 -0
- package/dist/sources/ladder.js +158 -0
- package/dist/sources/ladder.js.map +1 -0
- package/dist/sources/ledger.d.ts +7 -0
- package/dist/sources/ledger.js +35 -0
- package/dist/sources/ledger.js.map +1 -0
- package/dist/sources/paste.d.ts +8 -0
- package/dist/sources/paste.js +22 -0
- package/dist/sources/paste.js.map +1 -0
- package/dist/sources/searxng.d.ts +11 -0
- package/dist/sources/searxng.js +38 -0
- package/dist/sources/searxng.js.map +1 -0
- package/dist/sources/sites.d.ts +53 -0
- package/dist/sources/sites.js +285 -0
- package/dist/sources/sites.js.map +1 -0
- package/dist/sources/ytdlp.d.ts +43 -0
- package/dist/sources/ytdlp.js +117 -0
- package/dist/sources/ytdlp.js.map +1 -0
- package/package.json +65 -3
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ports the runner is given, as one plain `deps` object. A source is one file that answers
|
|
3
|
+
* `search` (hits for a query) or `open` (a hit read whole) or both; the registry holds them by
|
|
4
|
+
* name and the plan's allow-list picks per run. The model is the planner's, the extractor
|
|
5
|
+
* `./document`'s, the ledger `./ledger`'s. Nothing here reaches the network: the adapters in `src/sources` do.
|
|
6
|
+
*/
|
|
7
|
+
import type { Model } from "@wrenautomation/models";
|
|
8
|
+
import type { Judge } from "@wrenautomation/models/judge";
|
|
9
|
+
import type { Document, Extractor } from "../document/index.js";
|
|
10
|
+
import type { Ids } from "../ledger/ids.js";
|
|
11
|
+
import type { Ledger } from "../ledger/ledger.js";
|
|
12
|
+
import type { CostKind, FollowAs, From, HitRecord, QueryRecord } from "../ledger/records.js";
|
|
13
|
+
import type { Criterion, HitViewIn, PlanFile, Proposal } from "../plan/index.js";
|
|
14
|
+
export interface Source {
|
|
15
|
+
name: string;
|
|
16
|
+
kind: "search" | "open" | "both";
|
|
17
|
+
cost: CostKind;
|
|
18
|
+
/** Who the records it writes are from. A person pasting URLs is `human`; the default is `tool`. */
|
|
19
|
+
from?: From;
|
|
20
|
+
/** Who its records are by: the person behind a paste. The default is the source's name. */
|
|
21
|
+
by?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Whether its search keeps to that site (a query's `site`). A site-scoped query skips a
|
|
24
|
+
* searcher that would answer from everywhere. Absent: it keeps to any site.
|
|
25
|
+
*/
|
|
26
|
+
keeps?(site: string): boolean;
|
|
27
|
+
/** Hits as the source shows them for free. Throw on failure: the runner writes the spend. */
|
|
28
|
+
search?(query: QueryRecord): Promise<HitViewIn[]>;
|
|
29
|
+
/** Whether it lists that page's own posts (`posts`) or pages like it (`similar`). */
|
|
30
|
+
follows?(as: FollowAs, url: string): boolean;
|
|
31
|
+
/** The follow's hits, newest or closest first, `n` at most. Throw on failure, like search. */
|
|
32
|
+
follow?(as: FollowAs, url: string, n: number): Promise<HitViewIn[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Whether this source opens that URL at all (a YouTube page, an http(s) page). The read step
|
|
35
|
+
* asks before a call, so a source that was never going to open it writes no spend. Absent: it
|
|
36
|
+
* opens everything.
|
|
37
|
+
*/
|
|
38
|
+
opens?(url: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Opens only its own site's URLs, better than any general opener (a thread as data, not a
|
|
41
|
+
* fetched wall): it gets its turn before the rest, whatever the allow-list's order.
|
|
42
|
+
*/
|
|
43
|
+
first?: true;
|
|
44
|
+
/**
|
|
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 runner writes the spend `ok: false` with the
|
|
47
|
+
* reason and the next opener gets its turn.
|
|
48
|
+
*/
|
|
49
|
+
open?(hit: HitRecord): Promise<Document>;
|
|
50
|
+
}
|
|
51
|
+
export type Sources = Map<string, Source>;
|
|
52
|
+
export declare const registry: (...sources: Source[]) => Sources;
|
|
53
|
+
/** The allow-list's sources, in its order. A name no source answers to fails the run at its start. */
|
|
54
|
+
export declare function pick(sources: Sources, names: readonly string[]): Source[];
|
|
55
|
+
export interface Deps {
|
|
56
|
+
sources: Sources;
|
|
57
|
+
ledger: Ledger;
|
|
58
|
+
/** null: no model. The plan is the proposals given; every hit is read; nothing is extracted. */
|
|
59
|
+
model: Model | null;
|
|
60
|
+
/** The steps that decide what comes next (plan, triage, review) take it; absent: `model`. */
|
|
61
|
+
decider?: Model | null;
|
|
62
|
+
extractor: Extractor;
|
|
63
|
+
/** Cheap typed answers on every hit, page and finding: a hint and a router. Absent or null: none. */
|
|
64
|
+
judge?: Judge | null;
|
|
65
|
+
clock: () => Date;
|
|
66
|
+
ids: Ids;
|
|
67
|
+
/** `by` on the records the runner itself writes. */
|
|
68
|
+
runner: string;
|
|
69
|
+
/** The pause between tries of a call that failed with a Transient; `setTimeout` by default. A test passes a stub. */
|
|
70
|
+
sleep?: (ms: number) => Promise<void>;
|
|
71
|
+
}
|
|
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
|
+
/**
|
|
119
|
+
* The searchers a query goes to: all of them, or for a site-scoped query those that keep to it.
|
|
120
|
+
* A follow goes to the sources that follow its URL that way.
|
|
121
|
+
*/
|
|
122
|
+
export declare const searchersFor: (sources: readonly Source[], q: Pick<QueryRecord, "site" | "follow">) => Source[];
|
|
123
|
+
/** How many hits a follow lists. */
|
|
124
|
+
export declare const FOLLOW_N = 30;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ports the runner is given, as one plain `deps` object. A source is one file that answers
|
|
3
|
+
* `search` (hits for a query) or `open` (a hit read whole) or both; the registry holds them by
|
|
4
|
+
* name and the plan's allow-list picks per run. The model is the planner's, the extractor
|
|
5
|
+
* `./document`'s, the ledger `./ledger`'s. Nothing here reaches the network: the adapters in `src/sources` do.
|
|
6
|
+
*/
|
|
7
|
+
export const registry = (...sources) => new Map(sources.map((s) => [s.name, s]));
|
|
8
|
+
/** The allow-list's sources, in its order. A name no source answers to fails the run at its start. */
|
|
9
|
+
export function pick(sources, names) {
|
|
10
|
+
const missing = names.filter((n) => !sources.has(n));
|
|
11
|
+
if (missing.length)
|
|
12
|
+
throw new Error(`no source named ${missing.join(", ")}`);
|
|
13
|
+
return names.map((n) => sources.get(n));
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The searchers a query goes to: all of them, or for a site-scoped query those that keep to it.
|
|
17
|
+
* A follow goes to the sources that follow its URL that way.
|
|
18
|
+
*/
|
|
19
|
+
export const searchersFor = (sources, q) => {
|
|
20
|
+
const f = q.follow;
|
|
21
|
+
if (f)
|
|
22
|
+
return sources.filter((s) => s.follow && s.follows?.(f.as, f.url));
|
|
23
|
+
const searchers = sources.filter((s) => s.search);
|
|
24
|
+
return q.site ? searchers.filter((s) => s.keeps?.(q.site) ?? true) : searchers;
|
|
25
|
+
};
|
|
26
|
+
/** How many hits a follow lists. */
|
|
27
|
+
export const FOLLOW_N = 30;
|
|
28
|
+
//# sourceMappingURL=ports.js.map
|
|
@@ -0,0 +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;AAiED;;;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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What earlier runs proved, found again: the findings of every run in the ledger, ranked by
|
|
3
|
+
* MiniSearch (BM25 over the finding's text and quote, prefix and a little fuzz). Each carries its
|
|
4
|
+
* quote, its source's date and its run, so a later run sees how old a fact is and where it came
|
|
5
|
+
* from. A finding a call or a failed check dropped is left out. Read only: the agent decides what
|
|
6
|
+
* still holds, puts it in `known` or reads the source again (WA-934, option A).
|
|
7
|
+
*/
|
|
8
|
+
import { type Ledger } from "../ledger/ledger.js";
|
|
9
|
+
import type { AskKind } from "../plan/index.js";
|
|
10
|
+
export interface Recalled {
|
|
11
|
+
finding: string;
|
|
12
|
+
run: string;
|
|
13
|
+
/** The ask of the run that found it. */
|
|
14
|
+
ask: string;
|
|
15
|
+
text: string;
|
|
16
|
+
quote: string;
|
|
17
|
+
url: string;
|
|
18
|
+
/** The source's own date, when its document had one. */
|
|
19
|
+
date: string | null;
|
|
20
|
+
/** When the run found it. */
|
|
21
|
+
found: string;
|
|
22
|
+
/** Who wrote it: the agent's id for a finding it read and added, a model's id for `extract`. */
|
|
23
|
+
by: string;
|
|
24
|
+
/** `kept`: a call kept it; `open`: no call on it yet. Ranking ignores it. */
|
|
25
|
+
state: "kept" | "open";
|
|
26
|
+
/** Other runs that found the same quote on the same page, newest first. */
|
|
27
|
+
alsoIn: string[];
|
|
28
|
+
score: number;
|
|
29
|
+
}
|
|
30
|
+
export interface RecallOptions {
|
|
31
|
+
/** At most this many; 20 by default. */
|
|
32
|
+
n?: number;
|
|
33
|
+
/** Leave this run out: the one asking. */
|
|
34
|
+
not?: string;
|
|
35
|
+
/** Only runs of this ask kind. */
|
|
36
|
+
kind?: AskKind;
|
|
37
|
+
/** Only these runs: a child's siblings and parent. */
|
|
38
|
+
runs?: readonly string[];
|
|
39
|
+
}
|
|
40
|
+
/** Several ledgers read as one (a folder per day): their records merged in time order. */
|
|
41
|
+
export declare const joined: (ledgers: readonly Pick<Ledger, "scan">[]) => Pick<Ledger, "scan">;
|
|
42
|
+
export declare function recall(ledger: Pick<Ledger, "scan">, terms: string, o?: RecallOptions): Promise<Recalled[]>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What earlier runs proved, found again: the findings of every run in the ledger, ranked by
|
|
3
|
+
* MiniSearch (BM25 over the finding's text and quote, prefix and a little fuzz). Each carries its
|
|
4
|
+
* quote, its source's date and its run, so a later run sees how old a fact is and where it came
|
|
5
|
+
* from. A finding a call or a failed check dropped is left out. Read only: the agent decides what
|
|
6
|
+
* still holds, puts it in `known` or reads the source again (WA-934, option A).
|
|
7
|
+
*/
|
|
8
|
+
import MiniSearch from "minisearch";
|
|
9
|
+
import { latestCalls, ofType } from "../ledger/ledger.js";
|
|
10
|
+
import { byTime } from "../ledger/records.js";
|
|
11
|
+
/** Several ledgers read as one (a folder per day): their records merged in time order. */
|
|
12
|
+
export const joined = (ledgers) => ({
|
|
13
|
+
scan: async (f) => (await Promise.all(ledgers.map((l) => l.scan(f)))).flat().sort(byTime),
|
|
14
|
+
});
|
|
15
|
+
const fold = (s) => s.replace(/\s+/g, " ").trim().toLowerCase();
|
|
16
|
+
export async function recall(ledger, terms, o = {}) {
|
|
17
|
+
if (!terms.trim())
|
|
18
|
+
throw new Error("recall needs terms");
|
|
19
|
+
const records = await ledger.scan({ type: ["snapshot", "finding", "call"] });
|
|
20
|
+
const asks = new Map();
|
|
21
|
+
for (const s of ofType(records, "snapshot"))
|
|
22
|
+
if (!asks.has(s.run))
|
|
23
|
+
asks.set(s.run, { text: s.ask.text, kind: s.ask.kind });
|
|
24
|
+
const calls = latestCalls(records);
|
|
25
|
+
// Newest first, so the first of a quote seen twice is the latest proof of it.
|
|
26
|
+
const findings = ofType(records, "finding")
|
|
27
|
+
.filter((f) => f.run !== o.not && calls.get(f.id) !== "drop")
|
|
28
|
+
.filter((f) => !o.kind || asks.get(f.run)?.kind === o.kind)
|
|
29
|
+
.filter((f) => !o.runs || o.runs.includes(f.run))
|
|
30
|
+
.reverse();
|
|
31
|
+
const byKey = new Map();
|
|
32
|
+
for (const f of findings) {
|
|
33
|
+
const quote = f.proof.quote ?? "";
|
|
34
|
+
const key = `${f.proof.url}\u0000${fold(quote)}`;
|
|
35
|
+
const seen = byKey.get(key);
|
|
36
|
+
if (seen) {
|
|
37
|
+
if (f.run !== seen.run && !seen.alsoIn.includes(f.run))
|
|
38
|
+
seen.alsoIn.push(f.run);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
byKey.set(key, {
|
|
42
|
+
finding: f.id,
|
|
43
|
+
run: f.run,
|
|
44
|
+
ask: asks.get(f.run)?.text ?? "",
|
|
45
|
+
text: f.text,
|
|
46
|
+
quote,
|
|
47
|
+
url: f.proof.url,
|
|
48
|
+
date: f.date ?? null,
|
|
49
|
+
found: f.at,
|
|
50
|
+
by: f.by,
|
|
51
|
+
state: calls.get(f.id) === "keep" ? "kept" : "open",
|
|
52
|
+
alsoIn: [],
|
|
53
|
+
score: 0,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
const index = new MiniSearch({
|
|
57
|
+
idField: "finding",
|
|
58
|
+
fields: ["text", "quote"],
|
|
59
|
+
searchOptions: { boost: { text: 2 }, prefix: true, fuzzy: 0.2 },
|
|
60
|
+
});
|
|
61
|
+
index.addAll([...byKey.values()]);
|
|
62
|
+
const of = new Map([...byKey.values()].map((r) => [r.finding, r]));
|
|
63
|
+
return index
|
|
64
|
+
.search(terms)
|
|
65
|
+
.slice(0, o.n ?? 20)
|
|
66
|
+
.flatMap((hit) => {
|
|
67
|
+
const r = of.get(hit.id);
|
|
68
|
+
return r ? [{ ...r, score: Math.round(hit.score * 100) / 100 }] : [];
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=recall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recall.js","sourceRoot":"","sources":["../../src/engine/recall.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type Envelope, type From, type Step } from "../ledger/records.js";
|
|
2
|
+
import type { Deps, RunOptions } from "./ports.js";
|
|
3
|
+
import { type RunState } from "./state.js";
|
|
4
|
+
import { type StepContext } from "./steps.js";
|
|
5
|
+
export interface RunResult {
|
|
6
|
+
run: string;
|
|
7
|
+
rounds: number;
|
|
8
|
+
/** Why the run stopped: the last edge's why, or the step that gave up. */
|
|
9
|
+
note: string | null;
|
|
10
|
+
/** The run stopped on an edge, not on a step that gave up. */
|
|
11
|
+
finished: boolean;
|
|
12
|
+
/** The run stopped after a review that said `again`, on `pause`: `resume` goes on. */
|
|
13
|
+
paused: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* The review said `again` into a round past the budget: the runner parked, and this says so.
|
|
16
|
+
* The budget is a guard rail: `resume` goes one more round; the agent's `plan --run` opens it.
|
|
17
|
+
*/
|
|
18
|
+
parked: string | null;
|
|
19
|
+
state: RunState;
|
|
20
|
+
}
|
|
21
|
+
/** Tries per call over a Transient. */
|
|
22
|
+
export declare const TRIES = 3;
|
|
23
|
+
/** The default step bound: three full rounds and some backs. */
|
|
24
|
+
export declare const DEFAULT_STEPS = 64;
|
|
25
|
+
/** The pause before the next try: to `retryAfter` (a minute at most), else a second per try so far. */
|
|
26
|
+
export declare function waitMs(attempt: number, retryAfter: string | undefined, now: () => Date): number;
|
|
27
|
+
export declare function run(deps: Deps, options?: RunOptions): Promise<RunResult>;
|
|
28
|
+
/** The step context: `write` fills the envelope, `invoke` and `modelOn` write every spend. The agent commands build one per call. */
|
|
29
|
+
export declare function context(deps: Deps, options: RunOptions, run: string, round: number, step: Step): StepContext;
|
|
30
|
+
export type { Envelope, From };
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The interpreter: fold the trace, take the pointer's step from the table, write `done`, fold
|
|
3
|
+
* again. `--resume` is the same loop on an old run: the fold says where it stopped. Every model
|
|
4
|
+
* ask and source call writes a `spend` with what it cost and whether it worked. A call that
|
|
5
|
+
* fails with a `Transient` is tried again with a pause, three tries in all, every attempt on
|
|
6
|
+
* record; a step that still cannot go on throws it past the runner with no `done`, so a resume
|
|
7
|
+
* runs the step again once the cause has passed. A model answer the output cap cut (models'
|
|
8
|
+
* `Cut`) is a spend that worked, with its tokens: the extractor goes on from it. `pause` stops
|
|
9
|
+
* the loop after a review that says `again`, so the person can steer before the next round.
|
|
10
|
+
*/
|
|
11
|
+
import { isCut, isTransient, modelOf, promptText, } from "@wrenautomation/models";
|
|
12
|
+
import { judgeFailure } from "@wrenautomation/models/judge";
|
|
13
|
+
import { LedgerRecord } from "../ledger/records.js";
|
|
14
|
+
import { fold } from "./state.js";
|
|
15
|
+
import { STEP_TABLE } from "./steps.js";
|
|
16
|
+
/** Tries per call over a Transient. */
|
|
17
|
+
export const TRIES = 3;
|
|
18
|
+
/** The longest pause before another try, whatever `retry-after` said. */
|
|
19
|
+
const MAX_WAIT_MS = 60_000;
|
|
20
|
+
/** The default step bound: three full rounds and some backs. */
|
|
21
|
+
export const DEFAULT_STEPS = 64;
|
|
22
|
+
/** The pause before the next try: to `retryAfter` (a minute at most), else a second per try so far. */
|
|
23
|
+
export function waitMs(attempt, retryAfter, now) {
|
|
24
|
+
if (retryAfter) {
|
|
25
|
+
const until = Date.parse(retryAfter) - now().getTime();
|
|
26
|
+
if (!Number.isNaN(until))
|
|
27
|
+
return Math.max(0, Math.min(until, MAX_WAIT_MS));
|
|
28
|
+
}
|
|
29
|
+
return 1000 * attempt;
|
|
30
|
+
}
|
|
31
|
+
const message = (err) => (err instanceof Error ? err.message : String(err));
|
|
32
|
+
const defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
33
|
+
export async function run(deps, options = {}) {
|
|
34
|
+
const id = options.resume ?? options.run ?? deps.ids();
|
|
35
|
+
if (!options.resume && !options.ask)
|
|
36
|
+
throw new Error("a new run needs an ask");
|
|
37
|
+
const steps = options.steps ?? DEFAULT_STEPS;
|
|
38
|
+
let state = fold(id, await deps.ledger.trace(id));
|
|
39
|
+
if (options.resume && !state.records.length)
|
|
40
|
+
throw new Error(`run ${id}: no records`);
|
|
41
|
+
let paused = false;
|
|
42
|
+
let parked = null;
|
|
43
|
+
for (let n = 0; n < steps && state.next; n++) {
|
|
44
|
+
const { round, step } = state.next;
|
|
45
|
+
const ctx = context(deps, options, id, round, step);
|
|
46
|
+
const t0 = performance.now();
|
|
47
|
+
let result;
|
|
48
|
+
try {
|
|
49
|
+
result = await STEP_TABLE[step](ctx, state);
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
if (isTransient(err))
|
|
53
|
+
throw err;
|
|
54
|
+
result = { ok: false, note: message(err) };
|
|
55
|
+
}
|
|
56
|
+
await ctx.write({ type: "done", step, ok: result.ok, ...(result.note ? { note: result.note } : {}) }, { from: "tool", by: deps.runner });
|
|
57
|
+
const ms = Math.round(performance.now() - t0);
|
|
58
|
+
options.onStep?.({
|
|
59
|
+
run: id,
|
|
60
|
+
round,
|
|
61
|
+
step,
|
|
62
|
+
ok: result.ok,
|
|
63
|
+
...(result.note ? { note: result.note } : {}),
|
|
64
|
+
ms,
|
|
65
|
+
});
|
|
66
|
+
state = fold(id, await deps.ledger.trace(id));
|
|
67
|
+
if (!result.ok)
|
|
68
|
+
break;
|
|
69
|
+
if (step !== "review" || state.next?.step !== "plan")
|
|
70
|
+
continue;
|
|
71
|
+
const budget = state.snapshot?.budget;
|
|
72
|
+
if (budget && state.next.round > budget.rounds) {
|
|
73
|
+
parked = `round ${state.next.round} is past the budget of ${budget.rounds}: parked. The edge says: ${state.note}`;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
if (options.pause) {
|
|
77
|
+
paused = true;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
run: id,
|
|
83
|
+
rounds: state.round,
|
|
84
|
+
note: state.note,
|
|
85
|
+
finished: !state.next && state.edges.at(-1)?.next === "stop",
|
|
86
|
+
paused,
|
|
87
|
+
parked,
|
|
88
|
+
state,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const tokens = (u) => ({
|
|
92
|
+
...(u?.usd !== undefined ? { usd: u.usd } : {}),
|
|
93
|
+
...(u && (u.input !== undefined || u.output !== undefined)
|
|
94
|
+
? {
|
|
95
|
+
tokens: {
|
|
96
|
+
...(u.input !== undefined ? { input: u.input } : {}),
|
|
97
|
+
...(u.output !== undefined ? { output: u.output } : {}),
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
: {}),
|
|
101
|
+
});
|
|
102
|
+
/** The steps that decide what comes next: the decider's. The bulk (extract, check) is the model's. */
|
|
103
|
+
const DECIDES = new Set(["plan", "triage", "review"]);
|
|
104
|
+
/** The step context: `write` fills the envelope, `invoke` and `modelOn` write every spend. The agent commands build one per call. */
|
|
105
|
+
export function context(deps, options, run, round, step) {
|
|
106
|
+
const sleep = deps.sleep ?? defaultSleep;
|
|
107
|
+
const write = async (record, who) => {
|
|
108
|
+
const id = deps.ids();
|
|
109
|
+
const full = LedgerRecord.parse({
|
|
110
|
+
...record,
|
|
111
|
+
id,
|
|
112
|
+
run,
|
|
113
|
+
round,
|
|
114
|
+
step,
|
|
115
|
+
at: deps.clock().toISOString(),
|
|
116
|
+
from: who.from,
|
|
117
|
+
by: who.by,
|
|
118
|
+
});
|
|
119
|
+
await deps.ledger.append(full);
|
|
120
|
+
return id;
|
|
121
|
+
};
|
|
122
|
+
const spend = (source, op, about, on, t0, outcome) => write({
|
|
123
|
+
type: "spend",
|
|
124
|
+
source: source.name,
|
|
125
|
+
op,
|
|
126
|
+
about: about.slice(0, 200),
|
|
127
|
+
...(on ? { on } : {}),
|
|
128
|
+
cost: source.cost,
|
|
129
|
+
ms: Math.round(performance.now() - t0),
|
|
130
|
+
...outcome,
|
|
131
|
+
}, { from: "tool", by: deps.runner });
|
|
132
|
+
/** One attempt, its spend written either way. */
|
|
133
|
+
const once = async (source, op, about, on, call, usageOf) => {
|
|
134
|
+
const t0 = performance.now();
|
|
135
|
+
try {
|
|
136
|
+
const out = await call();
|
|
137
|
+
await spend(source, op, about, on, t0, { ok: true, ...tokens(usageOf?.(out)) });
|
|
138
|
+
return out;
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
if (isCut(err))
|
|
142
|
+
await spend(source, op, about, on, t0, { ok: true, ...tokens(err.usage) });
|
|
143
|
+
else
|
|
144
|
+
await spend(source, op, about, on, t0, {
|
|
145
|
+
ok: false,
|
|
146
|
+
error: message(err),
|
|
147
|
+
...(isTransient(err) && err.retryAfter ? { retryAfter: err.retryAfter } : {}),
|
|
148
|
+
});
|
|
149
|
+
throw err;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
/** The call again after a Transient, with a pause, TRIES in all. */
|
|
153
|
+
const tried = async (call) => {
|
|
154
|
+
for (let attempt = 1;; attempt++) {
|
|
155
|
+
try {
|
|
156
|
+
return await call();
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
if (!isTransient(err) || attempt >= TRIES)
|
|
160
|
+
throw err;
|
|
161
|
+
await sleep(waitMs(attempt, err.retryAfter, deps.clock));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
const invoke = async (source, op, about, on, call) => {
|
|
166
|
+
try {
|
|
167
|
+
return await tried(() => once(source, op, about, on, call));
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
if (isTransient(err))
|
|
171
|
+
throw err;
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
// Every call writes a spend, a repair's too: the wrap is on `complete`, and `ask` is built over it.
|
|
176
|
+
const modelOn = (on) => {
|
|
177
|
+
const m = deps.model && ((DECIDES.has(step) && deps.decider) || deps.model);
|
|
178
|
+
if (!m)
|
|
179
|
+
return null;
|
|
180
|
+
return modelOf({
|
|
181
|
+
id: m.id,
|
|
182
|
+
provider: m.provider,
|
|
183
|
+
takes: m.takes,
|
|
184
|
+
complete: (req) => {
|
|
185
|
+
const text = promptText(req.prompt) ?? "";
|
|
186
|
+
const about = text.split("\n").find((l) => l.trim()) ?? "";
|
|
187
|
+
return tried(() => once({ name: m.id, cost: "metered" }, "ask", about, on, () => m.complete(req), (r) => r.usage));
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
const judge = async (on, about, state, questions) => {
|
|
192
|
+
const j = deps.judge;
|
|
193
|
+
if (!j)
|
|
194
|
+
return { failure: "off" };
|
|
195
|
+
const t0 = performance.now();
|
|
196
|
+
const spender = { name: j.id, cost: "metered" };
|
|
197
|
+
try {
|
|
198
|
+
const r = await j.judge(state, questions);
|
|
199
|
+
await spend(spender, "ask", about, on, t0, { ok: true, ...tokens(r.usage) });
|
|
200
|
+
return r;
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
await spend(spender, "ask", about, on, t0, { ok: false, error: message(err) });
|
|
204
|
+
return { failure: judgeFailure(err) };
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
return { deps, options, model: modelOn(), modelOn, run, round, step, write, invoke, judge };
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/engine/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
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
|
+
export interface Pointer {
|
|
4
|
+
round: number;
|
|
5
|
+
step: Step;
|
|
6
|
+
}
|
|
7
|
+
export interface RunState {
|
|
8
|
+
run: string;
|
|
9
|
+
records: LedgerRecord[];
|
|
10
|
+
/** The latest snapshot: the ask and the allow-list. Absent before round 1's plan. */
|
|
11
|
+
snapshot: SnapshotRecord | null;
|
|
12
|
+
/** The round the pointer is in. */
|
|
13
|
+
round: number;
|
|
14
|
+
/** Where to go next; null when the run stopped. */
|
|
15
|
+
next: Pointer | null;
|
|
16
|
+
/** Why the run stopped or the last step gave up. */
|
|
17
|
+
note: string | null;
|
|
18
|
+
queries: QueryRecord[];
|
|
19
|
+
hits: HitRecord[];
|
|
20
|
+
documents: DocumentRecord[];
|
|
21
|
+
findings: FindingRecord[];
|
|
22
|
+
/** The extractor's word on each document it handled. */
|
|
23
|
+
verdicts: VerdictRecord[];
|
|
24
|
+
calls: CallRecord[];
|
|
25
|
+
spends: SpendRecord[];
|
|
26
|
+
edges: EdgeRecord[];
|
|
27
|
+
/** What the person said along the way, oldest first. */
|
|
28
|
+
steers: SteerRecord[];
|
|
29
|
+
/** What a step or a person said a round lacks. */
|
|
30
|
+
gaps: GapRecord[];
|
|
31
|
+
/** The sample check's word on each finding it checked. */
|
|
32
|
+
checks: CheckRecord[];
|
|
33
|
+
/** What the agent says several findings say together. */
|
|
34
|
+
patterns: PatternRecord[];
|
|
35
|
+
drafts: DraftRecord[];
|
|
36
|
+
classes: ClassRecord[];
|
|
37
|
+
/** Facets the agent gave up on, for the rest of the run. */
|
|
38
|
+
dead: DeadRecord[];
|
|
39
|
+
/** People the agent named across platforms, in time order. */
|
|
40
|
+
people: PersonRecord[];
|
|
41
|
+
/** The latest class on each document and finding. */
|
|
42
|
+
classOf: Map<string, SourceClass>;
|
|
43
|
+
/** The judge's latest answers on each hit, document and finding. */
|
|
44
|
+
judged: Map<string, JudgeRecord["answers"]>;
|
|
45
|
+
judges: JudgeRecord[];
|
|
46
|
+
/** A known hit found again by another query. */
|
|
47
|
+
founds: FoundRecord[];
|
|
48
|
+
/** The hit record for each canonical URL: a hit seen again, in any round, is a `found`, not a new record. */
|
|
49
|
+
hitByKey: Map<string, string>;
|
|
50
|
+
/** The latest call on each hit and finding. */
|
|
51
|
+
called: Map<string, "keep" | "drop">;
|
|
52
|
+
}
|
|
53
|
+
/** Records must be in time order. */
|
|
54
|
+
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
|
+
/** A finding stays kept unless its latest call is a drop. */
|
|
58
|
+
export declare const kept: (state: RunState, f: FindingRecord) => boolean;
|
|
59
|
+
/** What the run has found so far: the kept findings' sentences with their URLs, oldest first. */
|
|
60
|
+
export declare const found: (state: RunState, round?: number) => string[];
|
|
61
|
+
/**
|
|
62
|
+
* The round a person's gap or back edge is about. Between rounds (a pause, a stop) the pointer
|
|
63
|
+
* is one ahead of the last review, so it is the round that review closed; mid-round, the current one.
|
|
64
|
+
*/
|
|
65
|
+
export declare const personRound: (state: RunState) => number;
|
|
66
|
+
/** The queries that found a hit: the one that wrote it, then every one it came back for. */
|
|
67
|
+
export declare const queriesOf: (state: RunState) => Map<string, Set<string>>;
|
|
68
|
+
/** The hits of a round, the ones no call has named yet. */
|
|
69
|
+
export declare const uncalledHits: (state: RunState, round: number) => HitRecord[];
|
|
70
|
+
/**
|
|
71
|
+
* The hits to read: kept by triage in this round, no document yet. A failed open is tried again
|
|
72
|
+
* on a rerun (`birdwatch back <run> read`).
|
|
73
|
+
*/
|
|
74
|
+
export declare const toRead: (state: RunState, round: number) => HitRecord[];
|
|
75
|
+
/**
|
|
76
|
+
* The kept findings to check, at most `n`, spread across documents: each document's first
|
|
77
|
+
* unchecked finding, then each one's second, and so on. A finding with no quote, or one checked
|
|
78
|
+
* already, is not in it. Findings come in record order, so the sample is the same on a rerun.
|
|
79
|
+
*/
|
|
80
|
+
export declare function spreadSample(state: RunState, n: number, only?: (f: FindingRecord) => boolean): FindingRecord[];
|
|
81
|
+
/** Share of kept findings a check reads at least: the budget's `checks` is the floor under it. */
|
|
82
|
+
export declare const CHECK_SHARE = 0.1;
|
|
83
|
+
/** The sample's size: the budget's `checks`, or a tenth of the kept findings in reach, whichever is more; 0 checks is none. */
|
|
84
|
+
export declare const checkCount: (inReach: number, budget: number) => number;
|
|
85
|
+
/** A round's sample for the check step, less what the round checked already. */
|
|
86
|
+
export declare const toCheck: (state: RunState, round: number, budget: number) => FindingRecord[];
|
|
87
|
+
/** The documents of a round without a verdict: the extract step has not finished them. */
|
|
88
|
+
export declare const toExtract: (state: RunState, round: number) => DocumentRecord[];
|
|
89
|
+
/** A finding's class: its own, else its document's; undefined when neither has one. */
|
|
90
|
+
export declare const classOfFinding: (state: RunState, f: FindingRecord) => SourceClass | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Sources per class over findings still kept: distinct sites, but each forum thread (a
|
|
93
|
+
* document) counts on its own, so 31 threads on one forum are 31 voices, not one site.
|
|
94
|
+
*/
|
|
95
|
+
export declare function classesOf(state: RunState, ids: readonly string[]): Partial<Record<SourceClass | "unclassed", number>>;
|
|
96
|
+
/** The sources a set of findings rests on: the sum over `classesOf`. */
|
|
97
|
+
export declare const sourcesOf: (classes: ReturnType<typeof classesOf>) => number;
|
|
98
|
+
/** Vendor echo: every classed source is a vendor, and vendors cite each other. */
|
|
99
|
+
export declare const echoOf: (classes: ReturnType<typeof classesOf>) => boolean;
|