@leuduan/lagent 0.0.0-stage → 0.1.2
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 +16 -0
- package/README.md +144 -2
- package/dist/chunks/2O7ZGEIT.js +1 -0
- package/dist/chunks/2OSESBIL.js +1 -0
- package/dist/chunks/34KW6VNQ.js +1 -0
- package/dist/chunks/37YOGDGY.js +1 -0
- package/dist/chunks/3LQHQRIU.js +6 -0
- package/dist/chunks/3QCW4WDJ.js +1 -0
- package/dist/chunks/4XVRUSCQ.js +1 -0
- package/dist/chunks/6ECI2GGV.js +1 -0
- package/dist/chunks/74HKUGRR.js +1 -0
- package/dist/chunks/ADHERZLW.js +2 -0
- package/dist/chunks/AP6Q4EPT.js +36 -0
- package/dist/chunks/BM3S37EZ.js +1 -0
- package/dist/chunks/C5LYCXJG.js +1 -0
- package/dist/chunks/CDQG7RKA.js +1 -0
- package/dist/chunks/D7E6EWIE.js +3 -0
- package/dist/chunks/DDANMY45.js +3 -0
- package/dist/chunks/DRYAN665.js +1 -0
- package/dist/chunks/DXFXAYDN.js +17 -0
- package/dist/chunks/EGZI4XQX.js +24 -0
- package/dist/chunks/ENWFSU27.js +41 -0
- package/dist/chunks/G6RXC3AL.js +1 -0
- package/dist/chunks/G74AGRAJ.js +15 -0
- package/dist/chunks/GQGNVSKB.js +1 -0
- package/dist/chunks/IJ2WNMD5.js +7 -0
- package/dist/chunks/J5S4URAW.js +1 -0
- package/dist/chunks/JPZFKSWT.js +1 -0
- package/dist/chunks/KESCTXGO.js +5 -0
- package/dist/chunks/L3N4FIEN.js +1 -0
- package/dist/chunks/NAOUTU7A.js +4 -0
- package/dist/chunks/NDIM7MEW.js +1 -0
- package/dist/chunks/O4PPOM5Z.js +2 -0
- package/dist/chunks/OVZFGILJ.js +1 -0
- package/dist/chunks/P5ZHHOOM.js +6 -0
- package/dist/chunks/PUSUPTAT.js +1 -0
- package/dist/chunks/QMMLQJBS.js +1 -0
- package/dist/chunks/RK3VP2Q4.js +3 -0
- package/dist/chunks/SGGMBSBA.js +1 -0
- package/dist/chunks/SL2YLB2F.js +1 -0
- package/dist/chunks/TOOIB6J2.js +1 -0
- package/dist/chunks/TYTQRLTX.js +1 -0
- package/dist/chunks/UC3FVVJ2.js +5 -0
- package/dist/chunks/UCTEU62F.js +1 -0
- package/dist/chunks/UD3VJER6.js +1 -0
- package/dist/chunks/UKXMCHHT.js +1 -0
- package/dist/chunks/WUUKTSRT.js +7 -0
- package/dist/chunks/X65X4KP5.js +7 -0
- package/dist/chunks/YIR5MYGU.js +1 -0
- package/dist/chunks/YLNJXQ3Z.js +1 -0
- package/dist/context.d.ts +101 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +77 -0
- package/dist/journal/catalog.d.ts +112 -0
- package/dist/journal/forkChain.d.ts +16 -0
- package/dist/journal/index.d.ts +15 -0
- package/dist/journal/journal.d.ts +475 -0
- package/dist/journal/projection.d.ts +87 -0
- package/dist/journal/store.d.ts +181 -0
- package/dist/kit/claim.d.ts +13 -0
- package/dist/kit/drain.d.ts +10 -0
- package/dist/kit/extension.d.ts +180 -0
- package/dist/kit/grants.d.ts +9 -0
- package/dist/kit/modes.d.ts +65 -0
- package/dist/kit/retries.d.ts +25 -0
- package/dist/kit/scope.d.ts +32 -0
- package/dist/kit/service.d.ts +7 -0
- package/dist/kit/strategy.d.ts +10 -0
- package/dist/kit/timers.d.ts +43 -0
- package/dist/kit/tool.d.ts +72 -0
- package/dist/llm/client.d.ts +135 -0
- package/dist/llm/content.d.ts +52 -0
- package/dist/llm/door.d.ts +21 -0
- package/dist/llm/door.js +1 -0
- package/dist/llm/failure.d.ts +82 -0
- package/dist/llm/index.d.ts +16 -0
- package/dist/llm/primitives.d.ts +286 -0
- package/dist/llm/prompt.d.ts +21 -0
- package/dist/llm/provider.d.ts +63 -0
- package/dist/llm/readLedger.d.ts +24 -0
- package/dist/llm/request.d.ts +58 -0
- package/dist/loop/agent.d.ts +134 -0
- package/dist/loop/auxiliary.d.ts +54 -0
- package/dist/loop/chain.d.ts +46 -0
- package/dist/loop/chunks.d.ts +27 -0
- package/dist/loop/continuation.d.ts +166 -0
- package/dist/loop/decide.d.ts +64 -0
- package/dist/loop/errors.d.ts +162 -0
- package/dist/loop/forks.d.ts +61 -0
- package/dist/loop/holds.d.ts +104 -0
- package/dist/loop/hooks.d.ts +241 -0
- package/dist/loop/inbox.d.ts +188 -0
- package/dist/loop/index.d.ts +37 -0
- package/dist/loop/limits.d.ts +14 -0
- package/dist/loop/opening.d.ts +42 -0
- package/dist/loop/prepare.d.ts +30 -0
- package/dist/loop/projections.d.ts +307 -0
- package/dist/loop/replace.d.ts +33 -0
- package/dist/loop/requests.d.ts +129 -0
- package/dist/loop/route.d.ts +53 -0
- package/dist/loop/runtime.d.ts +85 -0
- package/dist/loop/state.d.ts +70 -0
- package/dist/loop/strategy.d.ts +71 -0
- package/dist/loop/summary.d.ts +3 -0
- package/dist/loop/surface.d.ts +153 -0
- package/dist/loop/threadState.d.ts +72 -0
- package/dist/loop/tool.d.ts +101 -0
- package/dist/loop/toolCalls.d.ts +42 -0
- package/dist/loop/wake.d.ts +32 -0
- package/dist/models/config/agent.d.ts +18 -0
- package/dist/models/config/prompt.d.ts +18 -0
- package/dist/models/door.d.ts +12 -0
- package/dist/models/door.js +1 -0
- package/dist/models/index.d.ts +7 -0
- package/dist/models/jsonSchema.d.ts +7 -0
- package/dist/models/wire/journal.d.ts +2772 -0
- package/dist/models/wire/primitives.d.ts +65 -0
- package/dist/plugin.d.ts +53 -0
- package/dist/plugin.js +1 -0
- package/dist/plugins/agentsMd.d.ts +76 -0
- package/dist/plugins/agentsMd.js +1 -0
- package/dist/plugins/ask/askQuestion.d.ts +9 -0
- package/dist/plugins/ask/index.d.ts +26 -0
- package/dist/plugins/ask/index.js +1 -0
- package/dist/plugins/ask/service.d.ts +125 -0
- package/dist/plugins/commands/background.d.ts +8 -0
- package/dist/plugins/commands/foreground.d.ts +4 -0
- package/dist/plugins/commands/index.d.ts +40 -0
- package/dist/plugins/commands/index.js +1 -0
- package/dist/plugins/commands/output.d.ts +115 -0
- package/dist/plugins/commands/record.d.ts +549 -0
- package/dist/plugins/commands/service.d.ts +314 -0
- package/dist/plugins/commands/shell.d.ts +25 -0
- package/dist/plugins/compaction/checkpoint.d.ts +91 -0
- package/dist/plugins/compaction/config.d.ts +133 -0
- package/dist/plugins/compaction/estimate.d.ts +29 -0
- package/dist/plugins/compaction/index.d.ts +2 -0
- package/dist/plugins/compaction/index.js +7 -0
- package/dist/plugins/compaction/log.d.ts +61 -0
- package/dist/plugins/compaction/planner.d.ts +207 -0
- package/dist/plugins/compaction/preset.d.ts +86 -0
- package/dist/plugins/compaction/prune.d.ts +9 -0
- package/dist/plugins/compaction/records.d.ts +227 -0
- package/dist/plugins/compaction/segments.d.ts +23 -0
- package/dist/plugins/compaction/shared.d.ts +14 -0
- package/dist/plugins/compaction/summarize.d.ts +13 -0
- package/dist/plugins/dateAndBranch.d.ts +47 -0
- package/dist/plugins/dateAndBranch.js +1 -0
- package/dist/plugins/delegations/answers.d.ts +39 -0
- package/dist/plugins/delegations/assignmentKey.d.ts +22 -0
- package/dist/plugins/delegations/cleanup.d.ts +161 -0
- package/dist/plugins/delegations/constraint.d.ts +76 -0
- package/dist/plugins/delegations/index.d.ts +39 -0
- package/dist/plugins/delegations/index.js +1 -0
- package/dist/plugins/delegations/notices.d.ts +261 -0
- package/dist/plugins/delegations/obligations.d.ts +210 -0
- package/dist/plugins/delegations/record.d.ts +632 -0
- package/dist/plugins/delegations/request.d.ts +381 -0
- package/dist/plugins/delegations/role.d.ts +30 -0
- package/dist/plugins/delegations/service.d.ts +562 -0
- package/dist/plugins/delegations/standing.d.ts +19 -0
- package/dist/plugins/delegations/stopCheck.d.ts +21 -0
- package/dist/plugins/delegations/testing.d.ts +16 -0
- package/dist/plugins/delegations/tools.d.ts +71 -0
- package/dist/plugins/delegations/waitBook.d.ts +116 -0
- package/dist/plugins/delegations/waits.d.ts +118 -0
- package/dist/plugins/diagnostics/digest.d.ts +14 -0
- package/dist/plugins/diagnostics/index.d.ts +68 -0
- package/dist/plugins/diagnostics/index.js +1 -0
- package/dist/plugins/historyRecall/history.d.ts +9 -0
- package/dist/plugins/historyRecall/index.d.ts +31 -0
- package/dist/plugins/historyRecall/index.js +1 -0
- package/dist/plugins/historyRecall/render.d.ts +34 -0
- package/dist/plugins/historyRecall/tools.d.ts +4 -0
- package/dist/plugins/mcp/catalog.d.ts +36 -0
- package/dist/plugins/mcp/config.d.ts +63 -0
- package/dist/plugins/mcp/connection.d.ts +53 -0
- package/dist/plugins/mcp/errors.d.ts +32 -0
- package/dist/plugins/mcp/index.d.ts +33 -0
- package/dist/plugins/mcp/index.js +5 -0
- package/dist/plugins/mcp/mount.d.ts +98 -0
- package/dist/plugins/mcp/names.d.ts +25 -0
- package/dist/plugins/mcp/render.d.ts +29 -0
- package/dist/plugins/mcp/slots.d.ts +15 -0
- package/dist/plugins/mcp/stdio.d.ts +49 -0
- package/dist/plugins/mcp/tool.d.ts +41 -0
- package/dist/plugins/providers/anthropic.d.ts +175 -0
- package/dist/plugins/providers/anthropicMessages.d.ts +65 -0
- package/dist/plugins/providers/codex.d.ts +60 -0
- package/dist/plugins/providers/codexAuth.d.ts +116 -0
- package/dist/plugins/providers/deepseek.d.ts +55 -0
- package/dist/plugins/providers/door.d.ts +61 -0
- package/dist/plugins/providers/door.js +1 -0
- package/dist/plugins/providers/failure.d.ts +23 -0
- package/dist/plugins/providers/gateway.d.ts +23 -0
- package/dist/plugins/providers/index.d.ts +6 -0
- package/dist/plugins/providers/openaiChat.d.ts +62 -0
- package/dist/plugins/providers/openaiResponses.d.ts +100 -0
- package/dist/plugins/providers/opencodeCopilot.d.ts +23 -0
- package/dist/plugins/providers/opencodeGo.d.ts +98 -0
- package/dist/plugins/providers/shared.d.ts +104 -0
- package/dist/plugins/providers/stream.d.ts +154 -0
- package/dist/plugins/routeContext.d.ts +22 -0
- package/dist/plugins/routeContext.js +1 -0
- package/dist/plugins/schedules/index.d.ts +21 -0
- package/dist/plugins/schedules/index.js +5 -0
- package/dist/plugins/schedules/record.d.ts +396 -0
- package/dist/plugins/schedules/service.d.ts +120 -0
- package/dist/plugins/schedules/time.d.ts +26 -0
- package/dist/plugins/schedules/tools.d.ts +6 -0
- package/dist/plugins/skills/discovery.d.ts +54 -0
- package/dist/plugins/skills/index.d.ts +31 -0
- package/dist/plugins/skills/index.js +1 -0
- package/dist/plugins/skills/tool.d.ts +11 -0
- package/dist/plugins/store/durableObject.d.ts +23 -0
- package/dist/plugins/store/durableObject.js +1 -0
- package/dist/plugins/store/durableObjectConnection.d.ts +27 -0
- package/dist/plugins/store/memory.d.ts +29 -0
- package/dist/plugins/store/sql.d.ts +59 -0
- package/dist/plugins/store/sqlite.d.ts +31 -0
- package/dist/plugins/store/sqlite.js +1 -0
- package/dist/plugins/subAgents/availableRoutes.d.ts +53 -0
- package/dist/plugins/subAgents/fork.d.ts +32 -0
- package/dist/plugins/subAgents/index.d.ts +67 -0
- package/dist/plugins/subAgents/index.js +1 -0
- package/dist/plugins/subAgents/tool.d.ts +38 -0
- package/dist/plugins/toolPolicy/index.d.ts +61 -0
- package/dist/plugins/toolPolicy/index.js +1 -0
- package/dist/plugins/tools/editFiles.d.ts +128 -0
- package/dist/plugins/tools/fsRead.d.ts +17 -0
- package/dist/plugins/tools/html.d.ts +23 -0
- package/dist/plugins/tools/index.d.ts +59 -0
- package/dist/plugins/tools/index.js +1 -0
- package/dist/plugins/tools/network.d.ts +23 -0
- package/dist/plugins/tools/ripgrep.d.ts +20 -0
- package/dist/plugins/tools/textEdit.d.ts +67 -0
- package/dist/plugins/tools/web.d.ts +32 -0
- package/dist/plugins/truncateToolOutput.d.ts +26 -0
- package/dist/plugins/truncateToolOutput.js +1 -0
- package/dist/plugins/usage/index.d.ts +24 -0
- package/dist/plugins/usage/index.js +1 -0
- package/dist/plugins/usage/tracker.d.ts +34 -0
- package/dist/plugins/verify/facts.d.ts +356 -0
- package/dist/plugins/verify/index.d.ts +75 -0
- package/dist/plugins/verify/index.js +1 -0
- package/dist/plugins/verify/service.d.ts +90 -0
- package/dist/plugins/workflows/assignment.d.ts +16 -0
- package/dist/plugins/workflows/bindings.d.ts +95 -0
- package/dist/plugins/workflows/cleanup.d.ts +38 -0
- package/dist/plugins/workflows/definition.d.ts +184 -0
- package/dist/plugins/workflows/fold.d.ts +373 -0
- package/dist/plugins/workflows/index.d.ts +28 -0
- package/dist/plugins/workflows/index.js +6 -0
- package/dist/plugins/workflows/observations.d.ts +81 -0
- package/dist/plugins/workflows/participants.d.ts +143 -0
- package/dist/plugins/workflows/policy.d.ts +112 -0
- package/dist/plugins/workflows/providers.d.ts +146 -0
- package/dist/plugins/workflows/record.d.ts +2863 -0
- package/dist/plugins/workflows/routing.d.ts +116 -0
- package/dist/plugins/workflows/schema.d.ts +26 -0
- package/dist/plugins/workflows/service.d.ts +477 -0
- package/dist/plugins/workflows/submit.d.ts +8 -0
- package/dist/plugins/workflows/view.d.ts +103 -0
- package/dist/plugins/workflows/work.d.ts +21 -0
- package/dist/plugins/workspaceContext.d.ts +38 -0
- package/dist/plugins/workspaceContext.js +1 -0
- package/dist/presets/agents.d.ts +7 -0
- package/dist/presets/base.d.ts +10 -0
- package/dist/presets/codex.d.ts +60 -0
- package/dist/presets/index.d.ts +4 -0
- package/dist/presets/prompts.d.ts +56 -0
- package/dist/sandbox/absent.d.ts +32 -0
- package/dist/sandbox/client.d.ts +39 -0
- package/dist/sandbox/files.d.ts +28 -0
- package/dist/sandbox/index.d.ts +49 -0
- package/dist/sandbox/index.js +4 -0
- package/dist/sandbox/mode.d.ts +57 -0
- package/dist/sandbox/policy.d.ts +86 -0
- package/dist/sandbox/protocol.d.ts +107 -0
- package/dist/sandbox/service.d.ts +143 -0
- package/dist/sandbox/worker.d.ts +12 -0
- package/dist/sandbox/worker.js +1 -0
- package/dist/services/admission.d.ts +174 -0
- package/dist/services/agents.d.ts +37 -0
- package/dist/services/birth.d.ts +220 -0
- package/dist/services/contributions.d.ts +73 -0
- package/dist/services/core.d.ts +34 -0
- package/dist/services/journal.d.ts +26 -0
- package/dist/services/launches.d.ts +104 -0
- package/dist/services/llm.d.ts +80 -0
- package/dist/services/owner.d.ts +367 -0
- package/dist/services/preset.d.ts +154 -0
- package/dist/services/presets.d.ts +139 -0
- package/dist/services/prompts.d.ts +67 -0
- package/dist/services/runEvents.d.ts +79 -0
- package/dist/services/thread.d.ts +267 -0
- package/dist/services/threadActivation.d.ts +100 -0
- package/dist/services/threadDirs.d.ts +38 -0
- package/dist/services/threadView.d.ts +92 -0
- package/dist/services/threads.d.ts +449 -0
- package/dist/services/tools.d.ts +41 -0
- package/dist/sys/environment.d.ts +47 -0
- package/dist/sys/git.d.ts +60 -0
- package/dist/sys/paths.d.ts +56 -0
- package/dist/sys/spawn.d.ts +176 -0
- package/dist/testing/clock.d.ts +17 -0
- package/dist/testing/fakeLlm.d.ts +74 -0
- package/dist/testing/fedLlm.d.ts +32 -0
- package/dist/testing/helpers.d.ts +344 -0
- package/dist/testing/index.d.ts +13 -0
- package/dist/testing/index.js +1 -0
- package/dist/testing/processes.d.ts +13 -0
- package/dist/testing/sandbox.d.ts +71 -0
- package/dist/testing/settlement.d.ts +6 -0
- package/dist/testing/tmpDirs.d.ts +17 -0
- package/dist/util/async.d.ts +8 -0
- package/dist/util/diff.d.ts +25 -0
- package/dist/util/dispatch.d.ts +8 -0
- package/dist/util/errors.d.ts +28 -0
- package/dist/util/foldState.d.ts +17 -0
- package/dist/util/freeze.d.ts +2 -0
- package/dist/util/ids.d.ts +2 -0
- package/dist/util/json.d.ts +37 -0
- package/dist/util/log.d.ts +6 -0
- package/dist/util/text.d.ts +21 -0
- package/dist/util/version.d.ts +2 -0
- package/package.json +175 -3
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
import type { JournalEventInput, JournalEventType, JournalEvent, Seq, ThreadSummary } from '../models/index.js';
|
|
2
|
+
import { type JsonValue } from '../util/json.js';
|
|
3
|
+
import type { ReadonlyState } from '../util/foldState.js';
|
|
4
|
+
import type { CoreFold, PluginProjection, Projection } from './projection.js';
|
|
5
|
+
import { type Origins } from './catalog.js';
|
|
6
|
+
import type { JournalStore } from './store.js';
|
|
7
|
+
export type AppendOptions = {
|
|
8
|
+
/** The thread the event belongs to; every row has one. */
|
|
9
|
+
threadId: string;
|
|
10
|
+
/** Earlier events this one answers — a `tool/result` cites the `tool/call` it completes. */
|
|
11
|
+
sourceSeqs?: readonly Seq[];
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* What a `transact` builder returns: the group's rows and a `value` for the writer. The value is
|
|
15
|
+
* observable only through the write's result, so only once the group is durable, an empty group
|
|
16
|
+
* included.
|
|
17
|
+
*/
|
|
18
|
+
export type Transaction<K extends JournalEventType, T> = {
|
|
19
|
+
readonly rows: readonly AppendEntry<K>[];
|
|
20
|
+
readonly value: T;
|
|
21
|
+
};
|
|
22
|
+
/** What a `transact` settles with: the events the group wrote and the builder's value. */
|
|
23
|
+
export type Committed<K extends JournalEventType, T> = {
|
|
24
|
+
readonly events: JournalEvent<K>[];
|
|
25
|
+
readonly value: T;
|
|
26
|
+
};
|
|
27
|
+
/** One row to append as part of an atomic group; see {@link Journal.appendAll}. */
|
|
28
|
+
export type AppendEntry<K extends JournalEventType = JournalEventType> = {
|
|
29
|
+
[T in K]: {
|
|
30
|
+
type: T;
|
|
31
|
+
data: JournalEventInput[T];
|
|
32
|
+
options: AppendOptions;
|
|
33
|
+
};
|
|
34
|
+
}[K];
|
|
35
|
+
/**
|
|
36
|
+
* The journal as a plugin holds it, `ctx.journal`: its reads, and writes of `ext` rows only. Core
|
|
37
|
+
* rows are the engine's, written by its own operations, which judge them; a core row a plugin wrote
|
|
38
|
+
* past this type is unsupported history. Listed, not derived, so a method the journal gains is not
|
|
39
|
+
* plugin API by default; loading and unloading threads is `ctx.threads.retain`'s.
|
|
40
|
+
*/
|
|
41
|
+
export interface PluginJournal extends Pick<Journal, 'head' | 'summary' | 'summaries' | 'summaryMap' | 'origins' | 'flush' | 'hold' | 'isLoaded' | 'loadedThreads' | 'eventAt' | 'readRow' | 'rows' | 'rowsAfter' | 'lineage' | 'inLineage' | 'subscribe'> {
|
|
42
|
+
/**
|
|
43
|
+
* Registers a plugin's fold and catches it up on every loaded thread; idempotent per projection.
|
|
44
|
+
* The returned function removes it, and only the registration that added it.
|
|
45
|
+
*/
|
|
46
|
+
register<S>(fold: PluginProjection<S>): () => void;
|
|
47
|
+
/**
|
|
48
|
+
* A fold's state on `threadId`, as a read-only view of plain data. A plugin's own projection is
|
|
49
|
+
* registered by its first read, so its state never goes stale; a {@link CoreFold} is core's, always
|
|
50
|
+
* registered already, and can be read but not made or registered here. A fold that failed throws
|
|
51
|
+
* {@link ProjectionFailedError}; a thread that is in the catalog but not loaded throws
|
|
52
|
+
* {@link ThreadNotLoadedError}.
|
|
53
|
+
*/
|
|
54
|
+
state<S>(fold: PluginProjection<S> | CoreFold<S>, threadId: string): ReadonlyState<S>;
|
|
55
|
+
/**
|
|
56
|
+
* A fold's state as it stood at `seq` on `threadId`'s lineage, folded fresh: nothing is
|
|
57
|
+
* registered, and the same read-only view as {@link state}.
|
|
58
|
+
*/
|
|
59
|
+
stateAt<S>(fold: Pick<Projection<S>, 'init' | 'apply'>, threadId: string, seq: Seq): ReadonlyState<S>;
|
|
60
|
+
append(type: 'ext', data: JournalEventInput['ext'], options: AppendOptions): Promise<JournalEvent<'ext'>>;
|
|
61
|
+
appendAll(entries: readonly AppendEntry<'ext'>[]): Promise<JournalEvent<'ext'>[]>;
|
|
62
|
+
transact<T>(threadId: string, build: () => Transaction<'ext', T>): Promise<Committed<'ext', T>>;
|
|
63
|
+
}
|
|
64
|
+
/** A thread's summary before the contributions the journal adds to it; see {@link Summarizer}. */
|
|
65
|
+
export type ThreadSummaryCore = Omit<ThreadSummary, 'contributions'>;
|
|
66
|
+
/**
|
|
67
|
+
* Computes a thread's summary from its folds, once a group is durable and folded. Registered once,
|
|
68
|
+
* by whoever knows the folds — the loop — since the journal knows only the shape.
|
|
69
|
+
*/
|
|
70
|
+
export type Summarizer = (journal: Journal, threadId: string) => ThreadSummaryCore;
|
|
71
|
+
/**
|
|
72
|
+
* What a plugin or host adds to a thread's summary: a pure function of the thread's folds, read
|
|
73
|
+
* through the journal, computed with the summary's core fields at each group. `undefined`
|
|
74
|
+
* contributes nothing for that thread. A plugin does not write one: `defineContribution` is the
|
|
75
|
+
* door, which owns the cache entry's shape.
|
|
76
|
+
*/
|
|
77
|
+
export type Contributor = (threadId: string, core: ThreadSummaryCore) => JsonValue | undefined;
|
|
78
|
+
export type ContributeOptions = {
|
|
79
|
+
/**
|
|
80
|
+
* Which summaries registration refreshes: those it says need their entry computed again. The ones
|
|
81
|
+
* without the key when omitted.
|
|
82
|
+
*/
|
|
83
|
+
refresh?: (summary: ThreadSummary) => boolean;
|
|
84
|
+
};
|
|
85
|
+
/** A registered contributor; see {@link Journal.contribute}. */
|
|
86
|
+
export type Contribution = {
|
|
87
|
+
/** Withdraws the contributor: summaries written from then on are computed without it. */
|
|
88
|
+
readonly withdraw: () => void;
|
|
89
|
+
/**
|
|
90
|
+
* The refresh registration queued: resolves with the threads whose repair failed, which keep a
|
|
91
|
+
* summary without the key; rejects if the refresh could not run at all, which the journal reports
|
|
92
|
+
* too, unless it was refusing writes.
|
|
93
|
+
*/
|
|
94
|
+
readonly refreshed: Promise<string[]>;
|
|
95
|
+
};
|
|
96
|
+
export type JournalOptions = {
|
|
97
|
+
summarize: Summarizer;
|
|
98
|
+
/**
|
|
99
|
+
* Where a throwing subscriber or contributor goes. Subscribers are isolated: appending is how
|
|
100
|
+
* the engine records what happened, so it cannot be at the mercy of who is watching.
|
|
101
|
+
*/
|
|
102
|
+
onListenerError?: (error: unknown) => void;
|
|
103
|
+
/**
|
|
104
|
+
* Core's folds: the only `fatal` projections the journal accepts, registered here, before it
|
|
105
|
+
* opens, and never removed. A plugin's fold isolates, so `register` and `state` refuse a `fatal`
|
|
106
|
+
* one that is not among these, by identity.
|
|
107
|
+
*/
|
|
108
|
+
coreFolds: readonly CoreFold<unknown>[];
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* The append-only journal, the folds over it, and the catalog of its threads.
|
|
112
|
+
*
|
|
113
|
+
* Everything the loop needs to resume is a projection of these events, never a snapshot beside
|
|
114
|
+
* them (`docs/architecture.md#state-and-lifetimes`).
|
|
115
|
+
*
|
|
116
|
+
* **Writes** go through one queue. `transact(threadId, build)` runs `build` once every earlier write
|
|
117
|
+
* has landed and been folded, synchronously, against durable state, and appends what it returns in
|
|
118
|
+
* the same slot: the rows go to the store as one attempt, and only once the store has them are they
|
|
119
|
+
* folded, summarized and published. Folds therefore hold only durable rows. `appendAll` and `append`
|
|
120
|
+
* are `transact` with a constant callback. A store failure is fatal: the journal revokes writes and
|
|
121
|
+
* tells `onRevoked` listeners, and the owner exits. The one exception is the summary written after
|
|
122
|
+
* a group: the catalog is a cache, so that failure is reported and the next write catches it up.
|
|
123
|
+
* A lost writer is fatal there too.
|
|
124
|
+
*
|
|
125
|
+
* **Reads** are synchronous over the **working set**: `load(threadId)` reads a thread's lineage
|
|
126
|
+
* from the store and folds it, and `unload()` drops it. A thread the catalog holds that is not
|
|
127
|
+
* loaded throws {@link ThreadNotLoadedError} on a synchronous read rather than reading the store
|
|
128
|
+
* behind the caller's back. Opening reads the head, the **catalog** of one summary per thread, and
|
|
129
|
+
* the store's thread index, which together answer listing, lineage and recovery questions without a
|
|
130
|
+
* row in memory. Rows are frozen as they enter memory, from an append or a load, and summaries as
|
|
131
|
+
* the catalog takes them, so a read hands out the journal's own and copies nothing.
|
|
132
|
+
*
|
|
133
|
+
* A thread may be a fork: its thread-scoped state is the fold over its **lineage**, the source's up
|
|
134
|
+
* to the row its spawn row names, then its own rows (`docs/forks.md`). Seqs are global, so one bound
|
|
135
|
+
* applies at every hop of a fork of a fork.
|
|
136
|
+
*
|
|
137
|
+
* The journal parses what it is given and writes it. A row whose meaning depends on the state it
|
|
138
|
+
* lands on is judged by whoever writes it, inside its `transact` callback, against durable state.
|
|
139
|
+
*/
|
|
140
|
+
export declare class Journal {
|
|
141
|
+
private readonly projections;
|
|
142
|
+
/** Core's folds, as the constructor took them: the only `fatal` projections that may be registered. */
|
|
143
|
+
private readonly coreFolds;
|
|
144
|
+
/** Fold state by thread, then projection key: unloading a thread drops its inner map. */
|
|
145
|
+
private readonly states;
|
|
146
|
+
private readonly failures;
|
|
147
|
+
/** Failures and contribution errors found during a write, reported once it is done. */
|
|
148
|
+
private readonly pendingReports;
|
|
149
|
+
/** Threads whose summary is current in memory but whose catalog write failed: the next write carries them. */
|
|
150
|
+
private readonly dirty;
|
|
151
|
+
private readonly listeners;
|
|
152
|
+
private readonly revokedListeners;
|
|
153
|
+
private readonly contributors;
|
|
154
|
+
/** The catalog: one summary per thread the store holds, in spawn order. */
|
|
155
|
+
private readonly catalog;
|
|
156
|
+
/** The working set: each loaded thread's own rows, in seq order. */
|
|
157
|
+
private readonly loaded;
|
|
158
|
+
/** Loads in flight, shared by everyone who asks for the same thread meanwhile. */
|
|
159
|
+
private readonly loading;
|
|
160
|
+
/** Row reads in flight, one per thread, shared by every load that needs that thread's rows. */
|
|
161
|
+
private readonly rowReads;
|
|
162
|
+
/** Bumped by every drop of a thread: a row read that started before one is read again. */
|
|
163
|
+
private readonly generations;
|
|
164
|
+
/** Every loaded row by seq, for lookups that name a row without its thread. */
|
|
165
|
+
private readonly bySeq;
|
|
166
|
+
/**
|
|
167
|
+
* Threads that must stay loaded, counted: a write in flight holds its thread and a new fork's
|
|
168
|
+
* source, and a host holds what a running thread reads (see {@link hold}).
|
|
169
|
+
*/
|
|
170
|
+
private readonly holds;
|
|
171
|
+
/** The threads whose registered folds hold their state. */
|
|
172
|
+
private readonly folded;
|
|
173
|
+
private readonly summarizer;
|
|
174
|
+
private readonly onListenerError;
|
|
175
|
+
private lease;
|
|
176
|
+
private ownsStore;
|
|
177
|
+
private seq;
|
|
178
|
+
private writable;
|
|
179
|
+
/** The failure that revoked writes, when one did; an orderly `revokeWrites()` leaves none. */
|
|
180
|
+
private revokedBy;
|
|
181
|
+
/** The tail of the write queue; every write and every catalog rebuild waits for it. */
|
|
182
|
+
private queue;
|
|
183
|
+
/** Whether a write is under way, during which reports wait. */
|
|
184
|
+
private writing;
|
|
185
|
+
/** Set by `close()`: writes already queued land, and new ones are refused. */
|
|
186
|
+
private closing;
|
|
187
|
+
readonly store: JournalStore;
|
|
188
|
+
constructor(store: JournalStore, options: JournalOptions);
|
|
189
|
+
/** Refuses every later append: the journal is closing. */
|
|
190
|
+
revokeWrites(): void;
|
|
191
|
+
/**
|
|
192
|
+
* Called once if the journal can no longer trust what it holds (see {@link JournalCommitError}):
|
|
193
|
+
* it has already refused every later write, and the owner must exit. Returns the function that
|
|
194
|
+
* stops listening.
|
|
195
|
+
*/
|
|
196
|
+
onRevoked(listener: (error: JournalCommitError) => void): () => void;
|
|
197
|
+
/**
|
|
198
|
+
* Takes the store's writer lease, opens the store if it is not open — and then owns it — and reads
|
|
199
|
+
* the head, the catalog and the thread index: nothing else. A summary the index shows trailing its
|
|
200
|
+
* thread's rows — written before a crash took the summary's own write — is refreshed from the
|
|
201
|
+
* rows, a missing one added and one with no thread dropped, before anything reads the catalog. No
|
|
202
|
+
* contributor is registered yet, so those summaries carry no contributions until one registers.
|
|
203
|
+
*/
|
|
204
|
+
open(): Promise<void>;
|
|
205
|
+
/**
|
|
206
|
+
* Refuses new writes, lets every write already queued land, then releases the lease and closes the
|
|
207
|
+
* store if the journal opened it.
|
|
208
|
+
*/
|
|
209
|
+
close(): Promise<void>;
|
|
210
|
+
get head(): Seq;
|
|
211
|
+
/** One thread's summary, or `undefined` for a thread the journal does not hold. */
|
|
212
|
+
summary(threadId: string): ThreadSummary | undefined;
|
|
213
|
+
/** Every thread's summary, in spawn order. */
|
|
214
|
+
summaries(): ThreadSummary[];
|
|
215
|
+
/** The summaries by thread id: what a walk over forks reads; origins have `origins`. */
|
|
216
|
+
summaryMap(): ReadonlyMap<string, ThreadSummary>;
|
|
217
|
+
/**
|
|
218
|
+
* The origin tree of the catalog's threads: callers, subtrees and required owners, loading nothing,
|
|
219
|
+
* and the one rule for a cited source row, which reads that row alone.
|
|
220
|
+
*/
|
|
221
|
+
readonly origins: Origins;
|
|
222
|
+
/**
|
|
223
|
+
* Adds to every thread's summary under `key`, computed with the summary at each group from then
|
|
224
|
+
* on. A contributor that throws contributes nothing to that summary and is reported; the group
|
|
225
|
+
* lands.
|
|
226
|
+
*
|
|
227
|
+
* Registering also refreshes the summaries `options.refresh` names — by default those written
|
|
228
|
+
* without the key, by a composition that did not register it or by a repair, which never carries
|
|
229
|
+
* a contribution it cannot compute: one queued task that reads the store's thread index as it
|
|
230
|
+
* starts, repairs those threads from their rows, the lineage they fold through included, and
|
|
231
|
+
* unloads what it loaded unless something holds it. Nothing else recomputes an earlier summary
|
|
232
|
+
* but `rebuildCatalog()`. A contributor that answers for every thread `refresh` names is
|
|
233
|
+
* refreshed once.
|
|
234
|
+
*/
|
|
235
|
+
contribute(key: string, contributor: Contributor, options?: ContributeOptions): Contribution;
|
|
236
|
+
/**
|
|
237
|
+
* Recomputes every thread's summary from its rows and replaces the catalog wholesale, in the
|
|
238
|
+
* store and in memory, in spawn order: what repairs a catalog from scratch. It waits its turn in
|
|
239
|
+
* the write queue and loads every thread meanwhile, unloading those it loaded after, so it is
|
|
240
|
+
* maintenance for a journal nothing else is using. A contribution whose contributor is not
|
|
241
|
+
* registered now is left out, also from the summary a thread keeps when its folds cannot take its
|
|
242
|
+
* rows. If the store fails, the previous catalog stays.
|
|
243
|
+
*/
|
|
244
|
+
rebuildCatalog(): Promise<void>;
|
|
245
|
+
/**
|
|
246
|
+
* Recomputes the summaries of `refresh` from their rows, with the contributors registered now,
|
|
247
|
+
* and writes them — wholesale when `replace`, which also drops summaries of threads the index does
|
|
248
|
+
* not hold. Everything it loads is unloaded after, unless something holds it; a failure leaves the
|
|
249
|
+
* previous catalog, in memory and in the store. Returns the threads whose rows their folds could
|
|
250
|
+
* not take: each keeps the summary it had, less the contributions no registered contributor
|
|
251
|
+
* computed, and is reported.
|
|
252
|
+
*/
|
|
253
|
+
private repair;
|
|
254
|
+
/** `summary` keeping only the contributions whose contributor is registered now. */
|
|
255
|
+
private withRegisteredContributions;
|
|
256
|
+
/** Refuses a write once the journal has been revoked or is closing. */
|
|
257
|
+
private requireWritable;
|
|
258
|
+
/** The threads whose rows and folds are in memory. */
|
|
259
|
+
loadedThreads(): string[];
|
|
260
|
+
/**
|
|
261
|
+
* Resolves once every write queued before the call has landed: what a reader awaits before it
|
|
262
|
+
* decides from the folds, so a `send()` it did not await is seen.
|
|
263
|
+
*/
|
|
264
|
+
flush(): Promise<void>;
|
|
265
|
+
/**
|
|
266
|
+
* Keeps threads loaded until the returned function is called: `unload` leaves a held thread, and
|
|
267
|
+
* any thread whose lineage runs through it, where it is. What a running thread reads — its lineage
|
|
268
|
+
* and its callers — is held for the run. Counted, so holds overlap.
|
|
269
|
+
*/
|
|
270
|
+
hold(threadIds: readonly string[]): () => void;
|
|
271
|
+
/**
|
|
272
|
+
* Loads a thread's lineage — its own rows and those of the threads it was forked from — and folds
|
|
273
|
+
* it, so the synchronous reads can answer for it. Idempotent; a load in flight is shared. A thread
|
|
274
|
+
* the catalog does not hold has nothing to load. A load that fails leaves nothing behind.
|
|
275
|
+
*/
|
|
276
|
+
load(threadId: string): Promise<void>;
|
|
277
|
+
/** Whether a thread's rows and folds are in memory, so the synchronous reads answer for it. */
|
|
278
|
+
isLoaded(threadId: string): boolean;
|
|
279
|
+
/**
|
|
280
|
+
* Drops a thread's rows and folds from memory; `load()` reads them again. The catalog entry
|
|
281
|
+
* stays. Every loaded thread whose lineage runs through it is dropped too, since its folds would
|
|
282
|
+
* otherwise be read over rows no longer in memory. A held thread stays (see {@link hold}), and so
|
|
283
|
+
* does one a held thread's lineage runs through; returns whether it went.
|
|
284
|
+
*/
|
|
285
|
+
unload(threadId: string): boolean;
|
|
286
|
+
private drop;
|
|
287
|
+
/**
|
|
288
|
+
* The row at `seq`, whichever thread it belongs to, from the working set. A row of a thread that is
|
|
289
|
+
* not loaded throws {@link RowNotLoadedError}; `readRow` reads it from the store.
|
|
290
|
+
*/
|
|
291
|
+
eventAt(seq: Seq): JournalEvent | undefined;
|
|
292
|
+
/** The row at `seq` from the working set, or else from the store. */
|
|
293
|
+
readRow(seq: Seq): Promise<JournalEvent | undefined>;
|
|
294
|
+
/** One thread's own rows, in order, up to and including `upTo`. Never the rows a fork inherits. */
|
|
295
|
+
rows(threadId: string, upTo?: Seq): readonly JournalEvent[];
|
|
296
|
+
/** One thread's own rows after `seq`, in order: found by binary search rather than a scan. */
|
|
297
|
+
rowsAfter(threadId: string, seq: Seq): readonly JournalEvent[];
|
|
298
|
+
/**
|
|
299
|
+
* The rows a thread's state folds, up to and including `upTo`: for a fork, its source's lineage
|
|
300
|
+
* up to the fork point, then its own rows. Every row keeps its original thread id and seq, and
|
|
301
|
+
* the whole is in seq order.
|
|
302
|
+
*/
|
|
303
|
+
lineage(threadId: string, upTo?: Seq): JournalEvent[];
|
|
304
|
+
/** Whether `event` is part of `threadId`'s lineage: its own row, or one it inherits. */
|
|
305
|
+
inLineage(threadId: string, event: JournalEvent): boolean;
|
|
306
|
+
/**
|
|
307
|
+
* A thread projection's state as it stood at `seq` on `threadId`'s lineage, folded fresh. For
|
|
308
|
+
* questions about the past, such as whether a row can be forked at; the live state is `state()`.
|
|
309
|
+
* The second signature is {@link PluginJournal.stateAt}'s, for the same reason as `state()`'s.
|
|
310
|
+
*/
|
|
311
|
+
stateAt<S>(fold: Pick<Projection<S>, 'init' | 'apply'>, threadId: string, seq: Seq): S;
|
|
312
|
+
stateAt<S>(fold: Pick<Projection<S>, 'init' | 'apply'>, threadId: string, seq: Seq): ReadonlyState<S>;
|
|
313
|
+
/**
|
|
314
|
+
* The threads whose rows make up `threadId`'s lineage up to `upTo`, from the thread itself out to
|
|
315
|
+
* its root. A fork is followed only once its spawn row is within the bound; each hop's bound is
|
|
316
|
+
* then below that spawn row, so the walk always ends.
|
|
317
|
+
*/
|
|
318
|
+
private hops;
|
|
319
|
+
/**
|
|
320
|
+
* A thread's spawn row's seq and fork: from the catalog, or from its loaded rows — while its first
|
|
321
|
+
* group is landing, or during a repair, which reads a thread's rows before it asks.
|
|
322
|
+
*/
|
|
323
|
+
private spawnOf;
|
|
324
|
+
/**
|
|
325
|
+
* The thread's own rows. A thread the catalog does not hold has none; one it holds must be loaded,
|
|
326
|
+
* so a read never reaches the store behind the caller's back.
|
|
327
|
+
*/
|
|
328
|
+
private own;
|
|
329
|
+
/**
|
|
330
|
+
* Reads a thread's rows from the store into the working set, unless they are there already. One
|
|
331
|
+
* read per thread is in flight at a time, shared by everyone who needs it; a read that a drop of
|
|
332
|
+
* the thread overtook is read again, so rows read before a write and an eviction are never
|
|
333
|
+
* installed after them.
|
|
334
|
+
*/
|
|
335
|
+
private loadRows;
|
|
336
|
+
private readRows;
|
|
337
|
+
/** The index of the first row in `rows` (sorted by seq) whose seq is above `seq`. */
|
|
338
|
+
private firstAfter;
|
|
339
|
+
/** Records one event through the same atomic path as a group. */
|
|
340
|
+
append<K extends JournalEventType>(type: K, data: JournalEventInput[K], options: AppendOptions): Promise<JournalEvent<K>>;
|
|
341
|
+
/** Records several events of one thread as one unit; see {@link transact}. */
|
|
342
|
+
appendAll<K extends JournalEventType>(entries: readonly AppendEntry<K>[]): Promise<JournalEvent<K>[]>;
|
|
343
|
+
/**
|
|
344
|
+
* Appends the rows `build` returns to `threadId` as one group, `build` running in the write queue —
|
|
345
|
+
* after every earlier write has landed and been folded, synchronously, against durable state —
|
|
346
|
+
* so a write that depends on what it reads is atomic. `build` loads nothing and awaits nothing:
|
|
347
|
+
* the thread is loaded before it runs. An empty group writes nothing. The `value` it returns
|
|
348
|
+
* comes back with the events once the group is durable, an empty group included, so what the
|
|
349
|
+
* writer learned inside the write needs no variable outside it.
|
|
350
|
+
*
|
|
351
|
+
* A `build` that throws writes nothing, and its error is the write's: a writer that judges what it
|
|
352
|
+
* appends refuses there. A thread begins with its spawn row and has one: a group on a thread the catalog does not hold must start with its one spawn row,
|
|
353
|
+
* and a group on a thread it holds may not carry one.
|
|
354
|
+
*
|
|
355
|
+
* The group goes to the store as one attempt. Once the store has it, its rows are folded, the
|
|
356
|
+
* thread's summary is computed and put in the catalog, the rows are published — the whole group
|
|
357
|
+
* folded before any row is published — and the summary is written to the store. A store that fails
|
|
358
|
+
* the append, or a core fold that cannot take rows the store holds, is a {@link JournalCommitError}:
|
|
359
|
+
* the journal refuses every later write with it as the cause, and `onRevoked` listeners are told
|
|
360
|
+
* once. A failed summary write is reported instead, unless the writer was lost: see
|
|
361
|
+
* {@link CatalogWriteError}.
|
|
362
|
+
*/
|
|
363
|
+
transact<K extends JournalEventType, T>(threadId: string, build: () => Transaction<K, T>): Promise<Committed<K, T>>;
|
|
364
|
+
/** Runs `task` once every earlier write is done; a failed one does not stop the queue. */
|
|
365
|
+
private enqueue;
|
|
366
|
+
private write;
|
|
367
|
+
private writeHeld;
|
|
368
|
+
private commit;
|
|
369
|
+
private writer;
|
|
370
|
+
/** Revokes writes for good, tells every listener once, and returns the error to throw. */
|
|
371
|
+
private revoke;
|
|
372
|
+
/**
|
|
373
|
+
* The row as it is, already frozen. A listener that writes gets a promise back, and may return it:
|
|
374
|
+
* its failure is reported, never left unhandled, and never awaited inside the write that published.
|
|
375
|
+
*/
|
|
376
|
+
private publish;
|
|
377
|
+
/**
|
|
378
|
+
* The thread's summary from its folds as they stand: core's fields, then every contribution,
|
|
379
|
+
* each checked to be JSON so what the store writes is what the catalog holds; one that is not, or
|
|
380
|
+
* that throws, is left out and reported once the write is done.
|
|
381
|
+
*/
|
|
382
|
+
private summarize;
|
|
383
|
+
/** Subscribes to appended events; returns the unsubscribe function. */
|
|
384
|
+
subscribe(listener: (event: JournalEvent) => void): () => void;
|
|
385
|
+
/**
|
|
386
|
+
* Registers a fold and catches it up on every thread in the working set. Idempotent per
|
|
387
|
+
* projection. Every fold is thread-scoped: a question about the set of threads is answered from
|
|
388
|
+
* the catalog, and a plugin that wants its own answer there registers a contribution.
|
|
389
|
+
*
|
|
390
|
+
* Only the registration that added the fold removes it: the function a repeated registration
|
|
391
|
+
* returns does nothing, so reading a fold, which registers it, can never hand out a way to remove
|
|
392
|
+
* one that core keeps for the journal's life.
|
|
393
|
+
*/
|
|
394
|
+
register<S>(projection: Projection<S>): () => void;
|
|
395
|
+
/**
|
|
396
|
+
* This projection's state on `threadId`. A thread the journal does not hold has the fold's initial
|
|
397
|
+
* state; one it holds must be loaded (see {@link load}), else {@link ThreadNotLoadedError}.
|
|
398
|
+
*
|
|
399
|
+
* Reading registers the fold: a state computed once and never updated again would go stale behind
|
|
400
|
+
* later appends, which is the one failure mode a projection must not have.
|
|
401
|
+
*
|
|
402
|
+
* A core fold is already registered, and reading it resolves that registration by identity; a
|
|
403
|
+
* `fatal` projection that is not one is refused, as `register` refuses it.
|
|
404
|
+
*
|
|
405
|
+
* The engine reads the state as its reducers hold it. The second signature is what a plugin's
|
|
406
|
+
* {@link PluginJournal.state} reads, so a `Journal` stands wherever a `PluginJournal` is wanted.
|
|
407
|
+
*/
|
|
408
|
+
state<S>(projection: Projection<S>, threadId: string): S;
|
|
409
|
+
state<S>(projection: PluginProjection<S> | CoreFold<S>, threadId: string): ReadonlyState<S>;
|
|
410
|
+
/**
|
|
411
|
+
* Folds every registered projection over the thread's lineage, once its rows are loaded. A thread
|
|
412
|
+
* counts as folded only once every fold has taken it: a fatal fold that throws leaves nothing
|
|
413
|
+
* behind, so the next load tries again and fails the same way rather than reading an initial state
|
|
414
|
+
* as the thread's.
|
|
415
|
+
*/
|
|
416
|
+
private ensureFolded;
|
|
417
|
+
/** Forgets every fold's state and failure on one thread. */
|
|
418
|
+
private dropStates;
|
|
419
|
+
/** One projection's state on one thread, folded fresh over its lineage. */
|
|
420
|
+
private foldLineage;
|
|
421
|
+
private fold;
|
|
422
|
+
private foldOne;
|
|
423
|
+
private failProjection;
|
|
424
|
+
/**
|
|
425
|
+
* Reports what folding and summarizing found, once no write is under way: an error observer may
|
|
426
|
+
* itself append to the journal, which queues behind the write.
|
|
427
|
+
*/
|
|
428
|
+
private flushReports;
|
|
429
|
+
private reportError;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* The journal can no longer trust what it holds: the store failed a write — which may or may not
|
|
433
|
+
* have landed — or a core fold could not take rows the store holds. The journal refuses every later
|
|
434
|
+
* append with this as the cause ({@link JournalRevokedError}); `Journal.onRevoked` listeners were
|
|
435
|
+
* told. The owner must exit; reopening reads the store as it is.
|
|
436
|
+
*/
|
|
437
|
+
export declare class JournalCommitError extends Error {
|
|
438
|
+
readonly threadId: string;
|
|
439
|
+
readonly cause: unknown;
|
|
440
|
+
constructor(threadId: string, cause: unknown);
|
|
441
|
+
}
|
|
442
|
+
/** An append after writes were revoked: by the journal closing, or by the failure it names. */
|
|
443
|
+
export declare class JournalRevokedError extends Error {
|
|
444
|
+
readonly cause: JournalCommitError | undefined;
|
|
445
|
+
constructor(cause: JournalCommitError | undefined);
|
|
446
|
+
}
|
|
447
|
+
/** A synchronous read of a thread the catalog holds but the working set does not: read it inside `thread.read` or a retention. */
|
|
448
|
+
export declare class ThreadNotLoadedError extends Error {
|
|
449
|
+
readonly threadId: string;
|
|
450
|
+
constructor(threadId: string);
|
|
451
|
+
}
|
|
452
|
+
/** A synchronous read of a row whose thread is not loaded: `readRow()` reads it from the store. */
|
|
453
|
+
export declare class RowNotLoadedError extends Error {
|
|
454
|
+
readonly seq: Seq;
|
|
455
|
+
constructor(seq: Seq);
|
|
456
|
+
}
|
|
457
|
+
/** A catalog write after a group that failed on a live journal: its summaries stay current in memory and dirty. */
|
|
458
|
+
export declare class CatalogWriteError extends Error {
|
|
459
|
+
readonly threadIds: readonly string[];
|
|
460
|
+
readonly cause: unknown;
|
|
461
|
+
constructor(threadIds: readonly string[], cause: unknown);
|
|
462
|
+
}
|
|
463
|
+
/** A thread whose summary could not be recomputed from its rows when the catalog was repaired; it kept the one it had. */
|
|
464
|
+
export declare class RepairError extends Error {
|
|
465
|
+
readonly threadId: string;
|
|
466
|
+
readonly cause: unknown;
|
|
467
|
+
constructor(threadId: string, cause: unknown);
|
|
468
|
+
}
|
|
469
|
+
/** A summary contributor threw; its key is missing from that thread's summary, and the group landed. */
|
|
470
|
+
export declare class ContributionError extends Error {
|
|
471
|
+
readonly key: string;
|
|
472
|
+
readonly threadId: string;
|
|
473
|
+
readonly cause: unknown;
|
|
474
|
+
constructor(key: string, threadId: string, cause: unknown);
|
|
475
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { type JournalEvent } from '../models/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* A fold over the journal, as the journal itself holds it.
|
|
4
|
+
*
|
|
5
|
+
* Projections are never persisted — they are recomputed from the journal, which is the only state —
|
|
6
|
+
* so unlike the journal's own events they need no schema and no version. Adding one is how a plugin
|
|
7
|
+
* gets durable state: register the fold, read it back with `Journal.state`. Every projection is
|
|
8
|
+
* thread-scoped: it keeps one state per thread and sees that thread's lineage, and every row belongs
|
|
9
|
+
* to a thread. A question about the set of threads is the catalog's, which a plugin adds to with a
|
|
10
|
+
* contribution.
|
|
11
|
+
*
|
|
12
|
+
* A forked thread's state is its source's at the fork point, carried on: the fold replays the
|
|
13
|
+
* source's lineage up to that row, then the fork's spawn row, then the fork's own rows. So the spawn
|
|
14
|
+
* row (`isForkSpawn`) is where a projection resets state that describes the source's execution
|
|
15
|
+
* rather than its conversation, and inherited state may name another thread's rows.
|
|
16
|
+
*
|
|
17
|
+
* `apply` may mutate `state` and return it, or return a fresh value. It runs once per appended
|
|
18
|
+
* event, so a fold that rebuilds its state each time makes a long journal quadratic; prefer
|
|
19
|
+
* mutation. What `state()` hands a plugin is a read-only view of that state, which is therefore
|
|
20
|
+
* plain data: primitives, arrays, records, `Map` and `Set`, no class instances or functions. A fold
|
|
21
|
+
* never reads another fold's state.
|
|
22
|
+
*
|
|
23
|
+
* Private to core: a plugin holds a {@link PluginProjection}, which is always isolated.
|
|
24
|
+
*/
|
|
25
|
+
export type Projection<S> = {
|
|
26
|
+
readonly key: string;
|
|
27
|
+
/**
|
|
28
|
+
* Whether a throwing fold fails the operation or only itself. A `fatal` fold is core's: a row it
|
|
29
|
+
* cannot take, once the store holds it, revokes the journal. An `isolate`d fold is
|
|
30
|
+
* marked failed on that thread, reported once, and skipped thereafter; reading that state throws
|
|
31
|
+
* rather than returning partial data. A plugin's fold is `isolate`: a plugin cannot refuse what
|
|
32
|
+
* the engine recorded.
|
|
33
|
+
*/
|
|
34
|
+
readonly failureMode: 'fatal' | 'isolate';
|
|
35
|
+
init(): S;
|
|
36
|
+
apply(state: S, event: JournalEvent): S;
|
|
37
|
+
};
|
|
38
|
+
declare const pluginFold: unique symbol;
|
|
39
|
+
declare const coreFold: unique symbol;
|
|
40
|
+
/**
|
|
41
|
+
* A fold a plugin registers: always isolated. Only {@link projection} makes one, so a plugin's fold
|
|
42
|
+
* can never be the kind that fails the journal.
|
|
43
|
+
*/
|
|
44
|
+
export type PluginProjection<S> = Readonly<Projection<S>> & {
|
|
45
|
+
readonly failureMode: 'isolate';
|
|
46
|
+
readonly [pluginFold]: true;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* A fold core registers when the journal is constructed, which a plugin can read but not register
|
|
50
|
+
* or make. The brand is only this type: a plugin that holds the handle reads it through
|
|
51
|
+
* `PluginJournal.state`, and the only way to produce one is {@link coreProjection}. Its members are
|
|
52
|
+
* read-only in the type only: it is not frozen, so a test can spy on its reducer, and TypeScript lets
|
|
53
|
+
* a read-only value be assigned to a mutable alias. That is acceptable because no door exports a
|
|
54
|
+
* core fold; only the package's own plugins hold one.
|
|
55
|
+
*/
|
|
56
|
+
export type CoreFold<S> = Readonly<Projection<S>> & {
|
|
57
|
+
readonly failureMode: 'fatal';
|
|
58
|
+
readonly [coreFold]: true;
|
|
59
|
+
};
|
|
60
|
+
/** What a fold declares besides its failure mode; {@link projection} and {@link coreProjection} share it. */
|
|
61
|
+
type FoldDefinition<S> = {
|
|
62
|
+
key: string;
|
|
63
|
+
init(): S;
|
|
64
|
+
apply(state: S, event: JournalEvent): S;
|
|
65
|
+
/**
|
|
66
|
+
* What a fork does with the state its source's lineage built. `'inherit'` carries it on, the
|
|
67
|
+
* default. `'reset'` starts again from `init()` at the fork's spawn row, for state that describes
|
|
68
|
+
* what the source did rather than its conversation; `apply` does not see that row.
|
|
69
|
+
*/
|
|
70
|
+
onFork?: 'inherit' | 'reset';
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Declares a plugin's projection, inferring its state type from `init`. It always isolates: a
|
|
74
|
+
* throwing fold marks only itself failed on that thread, and reading it throws
|
|
75
|
+
* {@link ProjectionFailedError}.
|
|
76
|
+
*/
|
|
77
|
+
export declare const projection: <S>(definition: FoldDefinition<S>) => PluginProjection<S>;
|
|
78
|
+
/** Declares a fold of core's: a row it cannot take revokes the journal. Not on any plugin door. */
|
|
79
|
+
export declare const coreProjection: <S>(definition: FoldDefinition<S>) => CoreFold<S>;
|
|
80
|
+
/** An isolated fold failed; its state is unavailable until it is unregistered and rebuilt. */
|
|
81
|
+
export declare class ProjectionFailedError extends Error {
|
|
82
|
+
readonly projectionKey: string;
|
|
83
|
+
readonly threadId: string;
|
|
84
|
+
readonly cause: unknown;
|
|
85
|
+
constructor(projectionKey: string, threadId: string, cause: unknown);
|
|
86
|
+
}
|
|
87
|
+
export {};
|