@leuduan/lagent 0.0.0-stage → 44.0.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 +16 -0
- package/README.md +157 -2
- package/dist/chunks/2GCIWSOA.js +5 -0
- package/dist/chunks/2P47AHNK.js +7 -0
- package/dist/chunks/34KW6VNQ.js +1 -0
- package/dist/chunks/3UMZMPWW.js +1 -0
- package/dist/chunks/5IRF47YB.js +1 -0
- package/dist/chunks/6DRCKZ2C.js +1 -0
- package/dist/chunks/6FRNHMCV.js +1 -0
- package/dist/chunks/7LI64H5X.js +17 -0
- package/dist/chunks/7VAPNE3L.js +1 -0
- package/dist/chunks/ASSQZH3F.js +1 -0
- package/dist/chunks/B4FXK5ER.js +77 -0
- package/dist/chunks/BBCW2FZK.js +1 -0
- package/dist/chunks/BPRCULZH.js +1 -0
- package/dist/chunks/CANPZYTH.js +24 -0
- package/dist/chunks/CQEVREBT.js +1 -0
- package/dist/chunks/CUK7CGC7.js +1 -0
- package/dist/chunks/D4PQP5MA.js +3 -0
- package/dist/chunks/DDANMY45.js +3 -0
- package/dist/chunks/DDZ7YF26.js +1 -0
- package/dist/chunks/EMRB4KCN.js +6 -0
- package/dist/chunks/EPYQ5M3B.js +3 -0
- package/dist/chunks/FJLU4UH3.js +1 -0
- package/dist/chunks/G44LG6VL.js +1 -0
- package/dist/chunks/GGSVIIWJ.js +2 -0
- package/dist/chunks/HK6ZSONF.js +1 -0
- package/dist/chunks/IAAEP6VL.js +30 -0
- package/dist/chunks/JCTBX33H.js +36 -0
- package/dist/chunks/JFX2MXBA.js +4 -0
- package/dist/chunks/JFZZXVWD.js +15 -0
- package/dist/chunks/KUZCL2SH.js +1 -0
- package/dist/chunks/MHC6VPB4.js +7 -0
- package/dist/chunks/MMNNZCBO.js +5 -0
- package/dist/chunks/MNJ4SRF7.js +1 -0
- package/dist/chunks/N6IXG2VL.js +1 -0
- package/dist/chunks/OCBPT7KE.js +1 -0
- package/dist/chunks/OL5A6ITQ.js +1 -0
- package/dist/chunks/PUSUPTAT.js +1 -0
- package/dist/chunks/Q75FUN7D.js +2 -0
- package/dist/chunks/Q7S5LFGN.js +1 -0
- package/dist/chunks/RCIHV3KG.js +1 -0
- package/dist/chunks/S34ZA2R6.js +1 -0
- package/dist/chunks/SS3B5W34.js +12 -0
- package/dist/chunks/VYMT4TXD.js +1 -0
- package/dist/chunks/W57RW55W.js +1 -0
- package/dist/compositions/base.d.ts +11 -0
- package/dist/compositions/codex.d.ts +66 -0
- package/dist/compositions/codexPrompts.d.ts +56 -0
- package/dist/context.d.ts +109 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +1 -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/llm/client.d.ts +135 -0
- package/dist/llm/content.d.ts +52 -0
- package/dist/llm/failure.d.ts +82 -0
- package/dist/llm/index.d.ts +22 -0
- package/dist/llm/index.js +1 -0
- package/dist/llm/primitives.d.ts +286 -0
- package/dist/llm/prompt.d.ts +21 -0
- package/dist/llm/provider.d.ts +74 -0
- package/dist/llm/readLedger.d.ts +24 -0
- package/dist/llm/request.d.ts +58 -0
- package/dist/loop/agent.d.ts +18 -0
- package/dist/loop/authorization.d.ts +41 -0
- package/dist/loop/auxiliary.d.ts +58 -0
- package/dist/loop/chunks.d.ts +27 -0
- package/dist/loop/completion.d.ts +17 -0
- package/dist/loop/errors.d.ts +139 -0
- package/dist/loop/hooks.d.ts +274 -0
- package/dist/loop/index.d.ts +16 -0
- package/dist/loop/runner.d.ts +134 -0
- package/dist/loop/runtime.d.ts +76 -0
- package/dist/loop/strategy.d.ts +80 -0
- package/dist/loop/surfacePrepare.d.ts +30 -0
- package/dist/loop/tool.d.ts +106 -0
- package/dist/loop/toolCalls.d.ts +35 -0
- package/dist/plugin.d.ts +50 -0
- package/dist/plugin.js +1 -0
- package/dist/plugins/agentsMd.d.ts +80 -0
- package/dist/plugins/agentsMd.js +1 -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/ask/tools.d.ts +9 -0
- package/dist/plugins/commands/index.d.ts +43 -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 +558 -0
- package/dist/plugins/commands/service.d.ts +321 -0
- package/dist/plugins/commands/shell.d.ts +25 -0
- package/dist/plugins/commands/tools.d.ts +10 -0
- package/dist/plugins/compaction/checkpoint.d.ts +94 -0
- package/dist/plugins/compaction/config.d.ts +133 -0
- package/dist/plugins/compaction/estimate.d.ts +37 -0
- package/dist/plugins/compaction/index.d.ts +87 -0
- package/dist/plugins/compaction/index.js +7 -0
- package/dist/plugins/compaction/planner.d.ts +207 -0
- package/dist/plugins/compaction/prune.d.ts +9 -0
- package/dist/plugins/compaction/record.d.ts +227 -0
- package/dist/plugins/compaction/segments.d.ts +23 -0
- package/dist/plugins/compaction/state.d.ts +68 -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 +633 -0
- package/dist/plugins/delegations/request.d.ts +384 -0
- package/dist/plugins/delegations/role.d.ts +30 -0
- package/dist/plugins/delegations/service.d.ts +563 -0
- package/dist/plugins/delegations/standing.d.ts +19 -0
- package/dist/plugins/delegations/stopCheck.d.ts +21 -0
- package/dist/plugins/delegations/tools.d.ts +71 -0
- package/dist/plugins/delegations/waitContracts.d.ts +118 -0
- package/dist/plugins/delegations/waitResolver.d.ts +116 -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/fileTools/config.d.ts +10 -0
- package/dist/plugins/fileTools/editFiles.d.ts +117 -0
- package/dist/plugins/fileTools/fsRead.d.ts +17 -0
- package/dist/plugins/fileTools/gitDiscovery.d.ts +9 -0
- package/dist/plugins/fileTools/index.d.ts +18 -0
- package/dist/plugins/fileTools/index.js +1 -0
- package/dist/plugins/fileTools/ripgrep.d.ts +20 -0
- package/dist/plugins/fileTools/textEdit.d.ts +67 -0
- package/dist/plugins/fileTools/tools.d.ts +6 -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/tools.d.ts +41 -0
- package/dist/plugins/mcp/version.d.ts +2 -0
- package/dist/plugins/routeNotice.d.ts +22 -0
- package/dist/plugins/routeNotice.js +1 -0
- package/dist/plugins/sandbox/absent.d.ts +33 -0
- package/dist/plugins/sandbox/client.d.ts +39 -0
- package/dist/plugins/sandbox/files.d.ts +28 -0
- package/dist/plugins/sandbox/index.d.ts +52 -0
- package/dist/plugins/sandbox/index.js +4 -0
- package/dist/plugins/sandbox/mode.d.ts +57 -0
- package/dist/plugins/sandbox/policy.d.ts +163 -0
- package/dist/plugins/sandbox/protocol.d.ts +107 -0
- package/dist/plugins/sandbox/service.d.ts +153 -0
- package/dist/plugins/sandbox/worker.d.ts +12 -0
- package/dist/plugins/sandbox/worker.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 +83 -0
- package/dist/plugins/skills/index.d.ts +31 -0
- package/dist/plugins/skills/index.js +1 -0
- package/dist/plugins/skills/tools.d.ts +11 -0
- package/dist/plugins/subAgents/availableRoutes.d.ts +53 -0
- package/dist/plugins/subAgents/index.d.ts +67 -0
- package/dist/plugins/subAgents/index.js +1 -0
- package/dist/plugins/subAgents/tools.d.ts +67 -0
- package/dist/plugins/threadDirs.d.ts +36 -0
- package/dist/plugins/threadDirs.js +1 -0
- package/dist/plugins/toolPolicy/index.d.ts +61 -0
- package/dist/plugins/toolPolicy/index.js +1 -0
- package/dist/plugins/truncateToolOutput.d.ts +30 -0
- package/dist/plugins/truncateToolOutput.js +6 -0
- package/dist/plugins/usage/index.d.ts +26 -0
- package/dist/plugins/usage/index.js +1 -0
- package/dist/plugins/usage/tracker.d.ts +34 -0
- package/dist/plugins/verify/index.d.ts +27 -0
- package/dist/plugins/verify/index.js +6 -0
- package/dist/plugins/verify/judgement.d.ts +16 -0
- package/dist/plugins/verify/record.d.ts +382 -0
- package/dist/plugins/verify/service.d.ts +93 -0
- package/dist/plugins/verify/state.d.ts +58 -0
- package/dist/plugins/webTools/html.d.ts +23 -0
- package/dist/plugins/webTools/index.d.ts +34 -0
- package/dist/plugins/webTools/index.js +1 -0
- package/dist/plugins/webTools/network.d.ts +23 -0
- package/dist/plugins/webTools/web.d.ts +32 -0
- package/dist/plugins/workflows/assignment.d.ts +20 -0
- package/dist/plugins/workflows/cleanup.d.ts +38 -0
- package/dist/plugins/workflows/definition.d.ts +184 -0
- package/dist/plugins/workflows/entryPlan.d.ts +95 -0
- package/dist/plugins/workflows/hostBindings.d.ts +146 -0
- package/dist/plugins/workflows/index.d.ts +28 -0
- package/dist/plugins/workflows/index.js +11 -0
- package/dist/plugins/workflows/observations.d.ts +81 -0
- package/dist/plugins/workflows/participantModels.d.ts +28 -0
- package/dist/plugins/workflows/participants.d.ts +143 -0
- package/dist/plugins/workflows/policy.d.ts +112 -0
- package/dist/plugins/workflows/record.d.ts +2849 -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/state.d.ts +373 -0
- package/dist/plugins/workflows/stopCheck.d.ts +13 -0
- package/dist/plugins/workflows/tools.d.ts +13 -0
- package/dist/plugins/workflows/view.d.ts +103 -0
- package/dist/plugins/workflows/workStatus.d.ts +21 -0
- package/dist/plugins/workspaceNotice.d.ts +36 -0
- package/dist/plugins/workspaceNotice.js +1 -0
- package/dist/providers/anthropic.d.ts +178 -0
- package/dist/providers/anthropicMessages.d.ts +66 -0
- package/dist/providers/codex.d.ts +71 -0
- package/dist/providers/codexAuth.d.ts +116 -0
- package/dist/providers/deepseek.d.ts +59 -0
- package/dist/providers/failure.d.ts +23 -0
- package/dist/providers/gateway.d.ts +24 -0
- package/dist/providers/index.d.ts +18 -0
- package/dist/providers/index.js +6 -0
- package/dist/providers/openaiChat.d.ts +73 -0
- package/dist/providers/openaiResponses.d.ts +109 -0
- package/dist/providers/opencodeCopilot.d.ts +23 -0
- package/dist/providers/opencodeGo.d.ts +109 -0
- package/dist/providers/shared.d.ts +112 -0
- package/dist/providers/stream.d.ts +156 -0
- package/dist/records/index.d.ts +13 -0
- package/dist/records/index.js +1 -0
- package/dist/records/journal.d.ts +2968 -0
- package/dist/records/toolResult.d.ts +65 -0
- package/dist/services/agents.d.ts +62 -0
- package/dist/services/catalogContributions.d.ts +73 -0
- package/dist/services/confinement/files.d.ts +118 -0
- package/dist/services/confinement/service.d.ts +219 -0
- package/dist/services/core.d.ts +28 -0
- package/dist/services/extensionEvents.d.ts +181 -0
- package/dist/services/journal.d.ts +26 -0
- package/dist/services/llm.d.ts +82 -0
- package/dist/services/modes.d.ts +65 -0
- package/dist/services/plugins.d.ts +34 -0
- package/dist/services/presets/definition.d.ts +154 -0
- package/dist/services/presets/installations.d.ts +139 -0
- package/dist/services/prompts.d.ts +85 -0
- package/dist/services/threads/activation.d.ts +100 -0
- package/dist/services/threads/admission.d.ts +174 -0
- package/dist/services/threads/birth.d.ts +219 -0
- package/dist/services/threads/index.d.ts +14 -0
- package/dist/services/threads/runEvents.d.ts +79 -0
- package/dist/services/threads/runOwner.d.ts +368 -0
- package/dist/services/threads/service.d.ts +450 -0
- package/dist/services/threads/thread.d.ts +268 -0
- package/dist/services/threads/view.d.ts +93 -0
- package/dist/services/tools.d.ts +118 -0
- package/dist/state/birth.d.ts +62 -0
- package/dist/state/chain.d.ts +46 -0
- package/dist/state/confirmations.d.ts +64 -0
- package/dist/state/continuation.d.ts +167 -0
- package/dist/state/decide.d.ts +72 -0
- package/dist/state/dispatches.d.ts +54 -0
- package/dist/state/errors.d.ts +26 -0
- package/dist/state/forks.d.ts +61 -0
- package/dist/state/holds.d.ts +104 -0
- package/dist/state/inbox.d.ts +188 -0
- package/dist/state/index.d.ts +31 -0
- package/dist/state/inputs.d.ts +58 -0
- package/dist/state/installations.d.ts +28 -0
- package/dist/state/limits.d.ts +14 -0
- package/dist/state/prompt.d.ts +13 -0
- package/dist/state/recovery.d.ts +7 -0
- package/dist/state/replace.d.ts +33 -0
- package/dist/state/requests.d.ts +129 -0
- package/dist/state/route.d.ts +61 -0
- package/dist/state/summary.d.ts +16 -0
- package/dist/state/surface.d.ts +153 -0
- package/dist/state/surfaceRead.d.ts +20 -0
- package/dist/state/thread.d.ts +73 -0
- package/dist/state/turns.d.ts +87 -0
- package/dist/state/waits.d.ts +38 -0
- package/dist/state/wake.d.ts +32 -0
- package/dist/stores/durableObject.d.ts +23 -0
- package/dist/stores/durableObject.js +1 -0
- package/dist/stores/durableObjectConnection.d.ts +27 -0
- package/dist/stores/memory.d.ts +29 -0
- package/dist/stores/sql.d.ts +59 -0
- package/dist/stores/sqlite.d.ts +31 -0
- package/dist/stores/sqlite.js +1 -0
- package/dist/sys/environment.d.ts +42 -0
- package/dist/sys/git.d.ts +47 -0
- package/dist/sys/paths.d.ts +9 -0
- package/dist/sys/spawn.d.ts +186 -0
- package/dist/testing/clock.d.ts +17 -0
- package/dist/testing/fakeLlm.d.ts +76 -0
- package/dist/testing/fedLlm.d.ts +34 -0
- package/dist/testing/helpers.d.ts +362 -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/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/jsonSchema.d.ts +7 -0
- package/dist/util/log.d.ts +6 -0
- package/dist/util/retries.d.ts +25 -0
- package/dist/util/text.d.ts +21 -0
- package/dist/util/timers.d.ts +43 -0
- package/package.json +183 -3
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import type { Journal } from '../journal/index.js';
|
|
2
|
+
import type { Reducer } from './thread.js';
|
|
3
|
+
import type { ConversationMessage } from '../llm/primitives.js';
|
|
4
|
+
import type { JournalEvent, ReplacementKind, Seq, SurfaceEventType } from '../records/journal.js';
|
|
5
|
+
import type { ReadonlyState } from '../util/foldState.js';
|
|
6
|
+
/** A journal row, named by the thread that owns it. Inherited rows belong to a fork's source lineage. */
|
|
7
|
+
export type RowRef = {
|
|
8
|
+
readonly threadId: string;
|
|
9
|
+
readonly seq: Seq;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* One message on the surface, with the row behind it.
|
|
13
|
+
*
|
|
14
|
+
* An original message is behind its own `input/message`, `assistant/message` or `tool/result` row;
|
|
15
|
+
* a stand-in is behind the `surface/replaced` row that put it there, whose `source_seqs` name what
|
|
16
|
+
* it replaced (see {@link replacedOriginals}). A `ConversationMessage` alone does not say which, nor
|
|
17
|
+
* whether a host sent it, and the replacement rules need both.
|
|
18
|
+
*/
|
|
19
|
+
export type SurfaceEntry = {
|
|
20
|
+
readonly row: RowRef;
|
|
21
|
+
readonly type: SurfaceEventType;
|
|
22
|
+
/**
|
|
23
|
+
* An `input/message` in role `developer` with no `source`: the host speaking. No replacement
|
|
24
|
+
* may touch one, since no plugin could bring it back in its place.
|
|
25
|
+
*/
|
|
26
|
+
readonly directDeveloperInput: boolean;
|
|
27
|
+
readonly message: ConversationMessage;
|
|
28
|
+
} | {
|
|
29
|
+
readonly row: RowRef;
|
|
30
|
+
readonly type: 'surface/replaced';
|
|
31
|
+
readonly kind: ReplacementKind;
|
|
32
|
+
readonly directDeveloperInput: false;
|
|
33
|
+
readonly message: ConversationMessage;
|
|
34
|
+
};
|
|
35
|
+
/** A surface entry as a plugin reads it from the fold: read-only all the way down, its message included. */
|
|
36
|
+
export type SurfaceEntryView = ReadonlyState<SurfaceEntry>;
|
|
37
|
+
export type SurfaceState = {
|
|
38
|
+
/** What the model sees, in order. */
|
|
39
|
+
readonly entries: SurfaceEntry[];
|
|
40
|
+
/**
|
|
41
|
+
* `surface/replaced` rows this fold skipped, with why. `replaceSurface` writes none that would be
|
|
42
|
+
* skipped, so an entry here is a row written past it: a bug or a hand-edited store. The fold
|
|
43
|
+
* records it rather than throwing, since a throwing core fold would leave every thread unopenable;
|
|
44
|
+
* such a thread is read and forked before the row, and never executed on (`CorruptHistoryError`).
|
|
45
|
+
*/
|
|
46
|
+
readonly refused: {
|
|
47
|
+
readonly row: RowRef;
|
|
48
|
+
readonly refusal: ReplacementRefusal;
|
|
49
|
+
}[];
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* What the model sees, in journal order, with the row behind each message.
|
|
53
|
+
*
|
|
54
|
+
* The system prompt is not here: it is recorded once per thread on `thread/prompt` and sent beside
|
|
55
|
+
* the conversation. Content that has to come back byte-identical belongs here, as a thread's
|
|
56
|
+
* opening messages.
|
|
57
|
+
*
|
|
58
|
+
* A reply the stream cut off is not here either. It is journaled for the record, but as far as the
|
|
59
|
+
* conversation is concerned the model has not replied: the thread still owes an answer, recovery
|
|
60
|
+
* sees work left, and a delegating caller sees nothing to take. One rule, read by all three.
|
|
61
|
+
*
|
|
62
|
+
* A `surface/replaced` row is folded by splicing: a `span` puts its stand-in where the run it
|
|
63
|
+
* replaces was, a `rewrite` puts its stand-in in place of the one message it names. Every row it
|
|
64
|
+
* meets is judged by {@link judgeReplacement}, live or replayed, and `replaceSurface` judges a group
|
|
65
|
+
* the same way inside its write, so the engine writes no row that the fold would skip.
|
|
66
|
+
*
|
|
67
|
+
* A fork inherits all of it: the conversation is exactly what a fork continues. Inherited entries
|
|
68
|
+
* are named by their original rows, which belong to the source's lineage.
|
|
69
|
+
*/
|
|
70
|
+
export declare const surface: Reducer<SurfaceState>;
|
|
71
|
+
/**
|
|
72
|
+
* Judges a group of replacements against `entries`, each against the surface the previous one
|
|
73
|
+
* left, without changing `entries`: the first refused, with its position, or `null` when the whole
|
|
74
|
+
* group may land.
|
|
75
|
+
*/
|
|
76
|
+
export declare function judgeGroup(entries: readonly SurfaceEntry[], group: readonly JournalEvent<'surface/replaced'>[]): {
|
|
77
|
+
readonly index: number;
|
|
78
|
+
readonly refusal: ReplacementRefusal;
|
|
79
|
+
} | null;
|
|
80
|
+
/**
|
|
81
|
+
* Whether a row put a message of its own on the surface: an `input/message`, a reply that was not
|
|
82
|
+
* cut off, or a tool result. The one predicate for it: the surface fold, {@link historyMessage} and
|
|
83
|
+
* history's numbering all gate on it. A `surface/replaced` row's stand-in is derived and never counts.
|
|
84
|
+
*/
|
|
85
|
+
export declare const isHistoryRow: (event: JournalEvent) => boolean;
|
|
86
|
+
/**
|
|
87
|
+
* The message a row puts on a conversation, or `null` for a row that puts none there
|
|
88
|
+
* ({@link isHistoryRow}). The one row-to-message logic: the surface fold builds its entries from it
|
|
89
|
+
* and recall renders history from it, so the model reads what the model saw.
|
|
90
|
+
*/
|
|
91
|
+
export declare function historyMessage(event: JournalEvent): ConversationMessage | null;
|
|
92
|
+
/** A replacement as the rules judge it: the row's data and the rows it cites. A journal row is one. */
|
|
93
|
+
export type ReplacementCandidate = Pick<JournalEvent<'surface/replaced'>, 'data' | 'source_seqs'>;
|
|
94
|
+
/** Which rule a refused replacement breaks; see {@link judgeReplacement}. */
|
|
95
|
+
export type ReplacementRule = 'empty' | 'not-current' | 'developer-input' | 'newest-message' | 'unbalanced' | 'rewrite-target';
|
|
96
|
+
export type ReplacementRefusal = {
|
|
97
|
+
readonly accepted: false;
|
|
98
|
+
readonly rule: ReplacementRule;
|
|
99
|
+
readonly message: string;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* A judgment of one replacement against a surface. An accepted one says where it lands: the cited
|
|
103
|
+
* messages are `entries[start]` up to, not including, `entries[start + count]`.
|
|
104
|
+
*/
|
|
105
|
+
export type ReplacementVerdict = {
|
|
106
|
+
readonly accepted: true;
|
|
107
|
+
readonly start: number;
|
|
108
|
+
readonly count: number;
|
|
109
|
+
} | ReplacementRefusal;
|
|
110
|
+
/**
|
|
111
|
+
* Whether a replacement may land on a surface, as it stands. The one predicate for replacements:
|
|
112
|
+
* the surface fold runs it on every row it folds, `replaceSurface` on every group it writes, and a
|
|
113
|
+
* strategy may run it on a plan before it asks for anything.
|
|
114
|
+
*
|
|
115
|
+
* - **Not empty**: a `span` names at least one row; a `rewrite` names exactly one.
|
|
116
|
+
* - **Contiguous and current**: the cited rows are, in order, a contiguous run of the rows behind the
|
|
117
|
+
* surface. A message already replaced is not current; its stand-in's row is.
|
|
118
|
+
* - **No direct developer input** is inside a span or rewritten: the host's instruction stays where
|
|
119
|
+
* it was, in order with what surrounds it, with no plugin needed to restore it.
|
|
120
|
+
* - **A `span` keeps the newest message**, so what the thread owes is unchanged. It is also
|
|
121
|
+
* **balanced**: no tool call on one side of either edge with its result on the other, and no tool
|
|
122
|
+
* result straight after the stand-in (see {@link isBalancedCut}).
|
|
123
|
+
* - **A `rewrite` targets** a tool result, a `user`-role input, or a rewrite's stand-in: never an
|
|
124
|
+
* assistant message, whose recorded provider state the Responses adapters replay in place of its
|
|
125
|
+
* content; never a `developer` message, which speaks as the harness; never a span's stand-in, whose
|
|
126
|
+
* text the strategy that wrote it owns. It may name the newest message. Its stand-in takes the role
|
|
127
|
+
* and tool call id of what it rewrites, so balance and what is owed hold by identity.
|
|
128
|
+
*
|
|
129
|
+
* The roles a `span` stand-in may take are the row schema's to enforce, and are. Changing what this
|
|
130
|
+
* accepts changes what recorded rows mean on replay, so it bumps the journal format version.
|
|
131
|
+
*/
|
|
132
|
+
export declare function judgeReplacement(entries: readonly SurfaceEntry[], candidate: ReplacementCandidate): ReplacementVerdict;
|
|
133
|
+
/**
|
|
134
|
+
* Whether the surface can be cut just before `entries[at]` (`at` from 0 to `entries.length`)
|
|
135
|
+
* without separating a tool call from its result: no tool result after the cut answers a call before
|
|
136
|
+
* it, and no call before it is still owed one. What a span's edges must be, and what a request built
|
|
137
|
+
* from a prefix of the surface must end on.
|
|
138
|
+
*
|
|
139
|
+
* Results are paired with the latest assistant message that called tools before them, as a
|
|
140
|
+
* provider pairs them and as `unansweredToolCalls` reads them, never by call id across the surface:
|
|
141
|
+
* providers reuse call ids from one turn to the next.
|
|
142
|
+
*/
|
|
143
|
+
export declare function isBalancedCut(entries: readonly SurfaceEntryView[], at: number): boolean;
|
|
144
|
+
/**
|
|
145
|
+
* The original rows behind a row on the surface, in surface order: the row itself when it is an
|
|
146
|
+
* original, or for a `surface/replaced` row, the originals behind every row it cites, followed down
|
|
147
|
+
* through chains of spans and rewrites. Where any message came from, for whatever asks: recall's
|
|
148
|
+
* numbering, a checkpoint's range, the copied input.
|
|
149
|
+
*
|
|
150
|
+
* Every row a replacement the engine wrote cites was on the surface when it was written, so the walk
|
|
151
|
+
* meets only replacements that took effect; one the surface refused is not asked about here.
|
|
152
|
+
*/
|
|
153
|
+
export declare function replacedOriginals(journal: Pick<Journal, 'eventAt'>, row: RowRef): RowRef[];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Journal, PluginJournal } from '../journal/index.js';
|
|
2
|
+
import type { ConversationMessage } from '../llm/primitives.js';
|
|
3
|
+
import type { ReadonlyState } from '../util/foldState.js';
|
|
4
|
+
import { type ReplacementRefusal, type RowRef } from './surface.js';
|
|
5
|
+
/**
|
|
6
|
+
* The first replacement `threadId`'s surface refused, or `null`: a thread that has one carries
|
|
7
|
+
* history no execution may continue from, which every entry that executes checks.
|
|
8
|
+
*/
|
|
9
|
+
export declare function refusedReplacement(journal: Pick<Journal, 'state'>, threadId: string): {
|
|
10
|
+
readonly row: RowRef;
|
|
11
|
+
readonly refusal: ReplacementRefusal;
|
|
12
|
+
} | null;
|
|
13
|
+
/**
|
|
14
|
+
* The last thing the model said on a thread, if anything: the message of the last
|
|
15
|
+
* `assistant/message` row on its lineage that the stream did not cut off. Found through the rows
|
|
16
|
+
* behind the surface, not by role, so an assistant-role stand-in is never reported as the model's
|
|
17
|
+
* last word; a reply a replacement took off the surface is still found, through the rows its
|
|
18
|
+
* stand-in replaced.
|
|
19
|
+
*/
|
|
20
|
+
export declare function lastAssistantMessage(journal: Pick<PluginJournal, 'eventAt' | 'state'>, threadId: string): ReadonlyState<ConversationMessage> | null;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { CoreFold } from '../journal/index.js';
|
|
2
|
+
import type { JournalEvent } from '../records/journal.js';
|
|
3
|
+
/**
|
|
4
|
+
* One concern of a thread's state: where it starts, and what a row does to it. `apply` may mutate
|
|
5
|
+
* `state` and return it, or return a fresh value; it never reads another concern.
|
|
6
|
+
*/
|
|
7
|
+
export type Reducer<S> = {
|
|
8
|
+
init(): S;
|
|
9
|
+
apply(state: S, event: JournalEvent): S;
|
|
10
|
+
};
|
|
11
|
+
/** Every concern of core's state, by the field it fills in {@link ThreadState}. */
|
|
12
|
+
declare const REDUCERS: {
|
|
13
|
+
readonly surface: Reducer<import("./surface.js").SurfaceState>;
|
|
14
|
+
readonly turnBoundary: Reducer<{
|
|
15
|
+
lastTurn: number;
|
|
16
|
+
step: number;
|
|
17
|
+
lastReason: import("../records/journal.js").TurnEndReason | null;
|
|
18
|
+
turnOpen: boolean;
|
|
19
|
+
concludedTurn: number | null;
|
|
20
|
+
}>;
|
|
21
|
+
readonly answerCheck: Reducer<import("./turns.js").AnswerCheck>;
|
|
22
|
+
readonly dispatchedCalls: Reducer<Map<string, number>>;
|
|
23
|
+
readonly dispatchAttempts: Reducer<Map<string, import("./dispatches.js").DispatchAttempt>>;
|
|
24
|
+
readonly waits: Reducer<Map<number, import("./waits.js").WaitEntry>>;
|
|
25
|
+
readonly confirmations: Reducer<Map<string, import("./confirmations.js").ConfirmationState>>;
|
|
26
|
+
readonly executions: Reducer<Map<number, import("./confirmations.js").RuntimeExecution>>;
|
|
27
|
+
readonly threadRecord: Reducer<import("./birth.js").ThreadRecord | null>;
|
|
28
|
+
readonly threadRoute: Reducer<{
|
|
29
|
+
provider: string;
|
|
30
|
+
model: string;
|
|
31
|
+
thinking_effort: "low" | "high" | "none" | "medium" | "max" | null;
|
|
32
|
+
} | null>;
|
|
33
|
+
readonly threadPrompt: Reducer<{
|
|
34
|
+
kind: "base" | "instruction" | "context";
|
|
35
|
+
tag: string | null;
|
|
36
|
+
text: string;
|
|
37
|
+
}[] | null>;
|
|
38
|
+
readonly threadTools: Reducer<readonly {
|
|
39
|
+
input_schema: import("../llm/primitives.js").JsonObject;
|
|
40
|
+
name: string;
|
|
41
|
+
description: string;
|
|
42
|
+
}[] | null>;
|
|
43
|
+
readonly forkTask: Reducer<{
|
|
44
|
+
spawnSeq: import("../records/journal.js").Seq | null;
|
|
45
|
+
unclaimed: boolean;
|
|
46
|
+
}>;
|
|
47
|
+
readonly inbox: Reducer<import("./inputs.js").InboxState>;
|
|
48
|
+
readonly inputs: Reducer<Map<string, import("./inputs.js").InputRows>>;
|
|
49
|
+
readonly installations: Reducer<import("./installations.js").InstallationsState>;
|
|
50
|
+
readonly lastAnswer: Reducer<number | null>;
|
|
51
|
+
readonly requests: Reducer<import("./requests.js").RequestsState>;
|
|
52
|
+
readonly chain: Reducer<import("./chain.js").ChainState>;
|
|
53
|
+
};
|
|
54
|
+
type Concern = keyof typeof REDUCERS;
|
|
55
|
+
type StateOf<K extends Concern> = ReturnType<(typeof REDUCERS)[K]['init']>;
|
|
56
|
+
/** A thread's state as core folds it: one field per concern. */
|
|
57
|
+
export type ThreadState = {
|
|
58
|
+
[K in Concern]: StateOf<K>;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Core's one fold: a thread's {@link ThreadState}, every concern reduced from the same rows. Fatal,
|
|
62
|
+
* as all of core's state is, and registered by the journal plugin before the journal opens. Read it
|
|
63
|
+
* with `journal.state(threadState, threadId).inbox`, and so on; a plugin reads it the same way but
|
|
64
|
+
* cannot register or make a fold of this kind.
|
|
65
|
+
*/
|
|
66
|
+
export declare const threadState: CoreFold<ThreadState>;
|
|
67
|
+
/**
|
|
68
|
+
* One field of {@link ThreadState} as a reducer of its own, with the same fork rule, for a replay
|
|
69
|
+
* that folds only what it reads: `journal.stateAt` to a row, or a walk along a lineage. A reducer,
|
|
70
|
+
* not a projection, so it can never be registered as a second fold.
|
|
71
|
+
*/
|
|
72
|
+
export declare function subState<K extends Concern>(key: K): Reducer<StateOf<K>>;
|
|
73
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { Seq, TurnEndReason } from '../records/journal.js';
|
|
2
|
+
import { type ResponseFinish } from '../llm/primitives.js';
|
|
3
|
+
import type { Journal } from '../journal/index.js';
|
|
4
|
+
import type { Reducer } from './thread.js';
|
|
5
|
+
/**
|
|
6
|
+
* Where a thread is in its turns: the highest one opened, how many steps it has taken, how it ended,
|
|
7
|
+
* and whether a tool asked it to stop.
|
|
8
|
+
*
|
|
9
|
+
* `step` counts `step/start` since the last `turn/start`, so it is only meaningful while that turn
|
|
10
|
+
* is in flight — a finished turn's count says nothing about the next one. It is folded rather than
|
|
11
|
+
* counted in memory so the loop's decision stays a function of the journal across a restart.
|
|
12
|
+
* `turnOpen` holds while a turn is in flight — including one whose process died, which the thread
|
|
13
|
+
* closes as `interrupted` before it opens another.
|
|
14
|
+
*
|
|
15
|
+
* A fork continues the turn numbering and inherits `concludedTurn`, so a fork taken after a
|
|
16
|
+
* concluding result is not owed a reply either. Everything else here describes the source's
|
|
17
|
+
* execution and resets: a fork has no turn in flight and no outcome of its own, even when it was cut
|
|
18
|
+
* inside one of its source's turns.
|
|
19
|
+
*/
|
|
20
|
+
export declare const turnBoundary: Reducer<{
|
|
21
|
+
lastTurn: number;
|
|
22
|
+
step: number;
|
|
23
|
+
/** How this thread's own last turn ended; `null` before its first ends, or while one is open. */
|
|
24
|
+
lastReason: TurnEndReason | null;
|
|
25
|
+
turnOpen: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* The turn in which a tool result asked for the turn to end, until input arrives. Holds across
|
|
28
|
+
* the turn boundary: the concluding result is not a reply the model owes, so nothing happens until
|
|
29
|
+
* someone sends something new — but only the turn it landed in is cut short by it.
|
|
30
|
+
*/
|
|
31
|
+
concludedTurn: number | null;
|
|
32
|
+
}>;
|
|
33
|
+
/** Whether a thread's latest answer has been judged by its stop checks. */
|
|
34
|
+
export type AnswerCheck = {
|
|
35
|
+
status: 'none';
|
|
36
|
+
} | ({
|
|
37
|
+
status: 'pending' | 'accepted' | 'rejected';
|
|
38
|
+
seq: Seq;
|
|
39
|
+
text: string;
|
|
40
|
+
} & ({
|
|
41
|
+
kind: 'reply';
|
|
42
|
+
finish: ResponseFinish;
|
|
43
|
+
} | {
|
|
44
|
+
kind: 'concluded';
|
|
45
|
+
}));
|
|
46
|
+
/**
|
|
47
|
+
* The conversation's latest answer — a reply with no tool calls, or a result that concluded the
|
|
48
|
+
* turn — and whether a stop check has judged it.
|
|
49
|
+
*
|
|
50
|
+
* An answer is `pending` from the moment it is recorded until its turn ends `completed` (accepted)
|
|
51
|
+
* or `rejected`. Every other ending leaves it pending, so a check a crash, an abort or a failing
|
|
52
|
+
* listener cut short is still owed; new input supersedes the answer altogether. Folded from rows
|
|
53
|
+
* the loop writes anyway, so there is no marker for a crash to fall in front of.
|
|
54
|
+
*
|
|
55
|
+
* A fork resets it (see `threadState`'s fork table); a fork is never cut where a check is still owed,
|
|
56
|
+
* so nothing is lost.
|
|
57
|
+
*/
|
|
58
|
+
export declare const answerCheck: Reducer<AnswerCheck>;
|
|
59
|
+
/**
|
|
60
|
+
* How the run that began after a row ended, and what it answered, read from the thread's events
|
|
61
|
+
* after that row. A run's outcome, not a delegation task's: an `aborted` turn ends a run, while a
|
|
62
|
+
* task stays open across it (the delegations plugin's own fold).
|
|
63
|
+
*/
|
|
64
|
+
export type RunOutcome = {
|
|
65
|
+
/** The last turn ending seen for this run, if any. */
|
|
66
|
+
reason: TurnEndReason | null;
|
|
67
|
+
/**
|
|
68
|
+
* The accepted answer: the reply, or the output of the tool result that concluded the turn. Empty
|
|
69
|
+
* until the run has answered — a provisional or rejected answer is not one.
|
|
70
|
+
*/
|
|
71
|
+
output: string;
|
|
72
|
+
/** Whether the conversation has reached an answer: a complete reply, or a result that concluded the turn. */
|
|
73
|
+
answered: boolean;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* How the run that began after `fromSeq` ended, and what it answered.
|
|
77
|
+
*
|
|
78
|
+
* The `answerCheck` reducer folded over the rows after `fromSeq`: the same rule the loop and its stop
|
|
79
|
+
* checks read, so an answer is a complete reply with nothing left to call, or a tool result that
|
|
80
|
+
* concluded the turn, and it becomes the run's answer only at the `turn/end(completed)` that
|
|
81
|
+
* accepted it. A process that died before that ending leaves it unaccepted, and the scan goes on to
|
|
82
|
+
* the turn that checks it. Scanning stops at the first turn ending that settles the run, answered or
|
|
83
|
+
* failed outright, so a later turn of the same thread is never mistaken for this run's.
|
|
84
|
+
*/
|
|
85
|
+
export declare function outcomeSince(journal: Journal, threadId: string, fromSeq: Seq): RunOutcome;
|
|
86
|
+
/** A turn ending after which the run will not produce an answer without new input. */
|
|
87
|
+
export declare const isRunFailure: (reason: TurnEndReason | null) => boolean;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Seq } from '../records/journal.js';
|
|
2
|
+
import type { ReadonlyJsonValue } from '../util/json.js';
|
|
3
|
+
import type { Reducer } from './thread.js';
|
|
4
|
+
/** A call's `wait/declared` row, as the waits fold keeps it. */
|
|
5
|
+
export type WaitDeclaration = {
|
|
6
|
+
/** The `wait/declared` row. */
|
|
7
|
+
readonly seq: Seq;
|
|
8
|
+
readonly turn: number;
|
|
9
|
+
readonly step: number;
|
|
10
|
+
readonly call_id: string;
|
|
11
|
+
readonly call_seq: Seq;
|
|
12
|
+
readonly owner: string;
|
|
13
|
+
readonly dependency: {
|
|
14
|
+
readonly [key: string]: ReadonlyJsonValue;
|
|
15
|
+
};
|
|
16
|
+
readonly deadline_at: number | null;
|
|
17
|
+
readonly reason: string;
|
|
18
|
+
};
|
|
19
|
+
/** One declared wait: its declaration, the value it resolved with, and whether its call was answered. */
|
|
20
|
+
export type WaitEntry = {
|
|
21
|
+
readonly declaration: WaitDeclaration;
|
|
22
|
+
value: {
|
|
23
|
+
readonly [key: string]: ReadonlyJsonValue;
|
|
24
|
+
} | null;
|
|
25
|
+
/** The call's `tool/result` landed: by its dispatch from the value, or by a cancel. */
|
|
26
|
+
answered: boolean;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Every wait the thread declared, by `call_seq`, kept after its call is answered, so answer-once can
|
|
30
|
+
* report a value recorded before. A fork starts with none: it is never cut with a call unanswered.
|
|
31
|
+
*/
|
|
32
|
+
export declare const waits: Reducer<Map<Seq, WaitEntry>>;
|
|
33
|
+
/** Declared, with no value and no answer: what holds the thread, and what its owner still resolves. */
|
|
34
|
+
export declare const isUnresolved: (entry: WaitEntry | undefined) => boolean;
|
|
35
|
+
/** Declared and unanswered, resolved or not: the waiting call's authority, which a cancel answers. */
|
|
36
|
+
export declare const isSuspended: (entry: WaitEntry | undefined) => boolean;
|
|
37
|
+
/** The thread's suspended waits, in declaration order. */
|
|
38
|
+
export declare const suspendedWaits: (state: ReadonlyMap<Seq, WaitEntry>) => WaitEntry[];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AppendEntry } from '../journal/index.js';
|
|
2
|
+
import type { RunChain } from '../records/journal.js';
|
|
3
|
+
import type { PendingRun } from './requests.js';
|
|
4
|
+
import { type RouteAuthority, type RouteStatement } from './route.js';
|
|
5
|
+
/**
|
|
6
|
+
* How a write asks its thread to run: the cause it records beside what it brings. A person's wake
|
|
7
|
+
* names no authority: it releases the failure, cancellation and startup holds, and its turns are a
|
|
8
|
+
* person's. A plugin's names its own: `releases` whether it releases those holds, a person's or a
|
|
9
|
+
* host's authority, and `chain` how a turn it opens counts. Either may state the route it runs on
|
|
10
|
+
* (`RouteStatement`).
|
|
11
|
+
*/
|
|
12
|
+
export type Wake = {
|
|
13
|
+
readonly route?: RouteStatement;
|
|
14
|
+
} & ({
|
|
15
|
+
readonly releases?: undefined;
|
|
16
|
+
readonly chain?: undefined;
|
|
17
|
+
} | {
|
|
18
|
+
readonly releases: boolean;
|
|
19
|
+
readonly chain: RunChain;
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* The rows that record `wake` on a thread whose pending request is `pending`, built inside the
|
|
23
|
+
* write that brings it, which read `pending` there: a `run/requested` when none is pending, then
|
|
24
|
+
* the cause, naming the input it brought, if any, and the route it changed the thread to, if it did;
|
|
25
|
+
* and the run the cause joins or opens. A route statement is checked by `routes`, the thread owner,
|
|
26
|
+
* which is the one guard on every route-changing write; a refusal throws, refusing the whole write.
|
|
27
|
+
* A write with no `routes` (a thread's opening group, a plugin's resolution) takes no statement.
|
|
28
|
+
*/
|
|
29
|
+
export declare function causeRows(threadId: string, pending: PendingRun | null, wake: Wake, inputId: string | null, routes?: RouteAuthority): {
|
|
30
|
+
readonly runId: string;
|
|
31
|
+
readonly rows: AppendEntry[];
|
|
32
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SqlJournalStore, type SqlConnection, type SqlExclusivity } from './sql.js';
|
|
2
|
+
import { type DurableObjectStorage } from './durableObjectConnection.js';
|
|
3
|
+
export type { DurableObjectStorage } from './durableObjectConnection.js';
|
|
4
|
+
/** What `DurableObjectJournalStore` needs from the host, with no default. */
|
|
5
|
+
export type DurableObjectJournalStoreOptions = {
|
|
6
|
+
/** Names the journal in errors, such as `IncompatibleJournalError`; a Durable Object has nothing to derive it from, so `do:${ctx.id}` is the natural choice. */
|
|
7
|
+
readonly identity: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Journal in a Durable Object's own SQLite storage: the schema, contract checks and format stamp of
|
|
11
|
+
* every SQL store, with each write confirmed durable by `storage.sync()` before it resolves, so an
|
|
12
|
+
* append that resolved survives a crash. One writer per storage: a second store over the same
|
|
13
|
+
* `ctx.storage` is refused, whichever instance makes it. A failed append revokes the journal; the
|
|
14
|
+
* host resets the object, and the next instance rebuilds from committed storage. Construct one over
|
|
15
|
+
* `ctx.storage` and pass it to `core` as `store`.
|
|
16
|
+
*/
|
|
17
|
+
export declare class DurableObjectJournalStore extends SqlJournalStore {
|
|
18
|
+
private readonly storage;
|
|
19
|
+
private readonly identity;
|
|
20
|
+
constructor(storage: DurableObjectStorage, options: DurableObjectJournalStoreOptions);
|
|
21
|
+
protected connect(): SqlConnection;
|
|
22
|
+
protected exclusive(): Promise<SqlExclusivity>;
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as c}from"../chunks/JCTBX33H.js";import{l as i}from"../chunks/BBCW2FZK.js";import"../chunks/MMNNZCBO.js";import"../chunks/G44LG6VL.js";import"../chunks/D4PQP5MA.js";function o(e){return{exec:t=>{e.sql.exec(t).toArray()},run:(t,...r)=>{e.sql.exec(t,...r).toArray()},all:(t,...r)=>e.sql.exec(t,...r).toArray(),transaction:async t=>{let r=e.transactionSync(t);return await e.sync(),r},close:()=>{}}}var n=new WeakMap;function s(e,t){if(n.has(e))throw new i(t);let r={};return n.set(e,r),{identity:t,release:()=>{n.get(e)===r&&n.delete(e)}}}var l=class extends c{storage;identity;constructor(t,r){super(r.identity),this.storage=t,this.identity=r.identity}connect(){return o(this.storage)}async exclusive(){return s(this.storage,this.identity)}};export{l as DurableObjectJournalStore};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SqlConnection, SqlExclusivity, SqlValue } from './sql.js';
|
|
2
|
+
/**
|
|
3
|
+
* The part of a Durable Object's `ctx.storage` the store uses, typed structurally so this package
|
|
4
|
+
* takes no dependency on the Workers types. The real object satisfies it as it is.
|
|
5
|
+
*/
|
|
6
|
+
export type DurableObjectStorage = {
|
|
7
|
+
sql: {
|
|
8
|
+
exec(query: string, ...bindings: SqlValue[]): {
|
|
9
|
+
toArray(): unknown[];
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
transactionSync<T>(body: () => T): T;
|
|
13
|
+
sync(): Promise<void>;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Runs the store's SQL on the object's own SQLite. A transaction's local commit is synchronous, and
|
|
17
|
+
* its result resolves only after `sync()` confirms the write is durable. A `sync()` rejection is the
|
|
18
|
+
* transaction's failure and rolls nothing back: the local commit completed and may have persisted.
|
|
19
|
+
*/
|
|
20
|
+
export declare function durableObjectConnection(storage: DurableObjectStorage): SqlConnection;
|
|
21
|
+
/**
|
|
22
|
+
* The one writer of a storage. Wrappers over the same storage share the entry, so a second
|
|
23
|
+
* acquisition is refused whichever wrapper makes it; the platform runs one instance of an object,
|
|
24
|
+
* but that instance can still hold two stores over one `ctx.storage`. Release clears only the
|
|
25
|
+
* entry this acquisition made, so a stale release never clears a replacement's.
|
|
26
|
+
*/
|
|
27
|
+
export declare function durableObjectExclusivity(storage: object, identity: string): SqlExclusivity;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { JournalEvent, Seq, ThreadSummary } from '../records/journal.js';
|
|
2
|
+
import { JournalStore, type AppendOutcome, type Attempt, type ThreadIndexEntry, type WriterLease } from '../journal/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* In-memory backing, keeping serialized rows so it exercises the same round trip as SQLite. Its
|
|
5
|
+
* writer lease is exclusive within the process, which is as far as its rows reach.
|
|
6
|
+
*/
|
|
7
|
+
export declare class MemoryJournalStore extends JournalStore {
|
|
8
|
+
private readonly rows;
|
|
9
|
+
/** Each row's thread and seq, so a read need not parse every row. */
|
|
10
|
+
private readonly index;
|
|
11
|
+
private readonly threadIndex;
|
|
12
|
+
private readonly catalog;
|
|
13
|
+
private readonly attempts;
|
|
14
|
+
/** The acquisition the writer record names; `undefined` while nobody holds the lease. */
|
|
15
|
+
private writer;
|
|
16
|
+
get size(): number;
|
|
17
|
+
acquireWriter(): Promise<WriterLease>;
|
|
18
|
+
protected doOpen(): Promise<void>;
|
|
19
|
+
protected doClose(): Promise<void>;
|
|
20
|
+
protected doHead(): Promise<Seq>;
|
|
21
|
+
protected doAppend(attempt: Attempt, digest: string): Promise<AppendOutcome>;
|
|
22
|
+
protected doRead(threadId: string): Promise<JournalEvent[]>;
|
|
23
|
+
protected doRowAt(seq: Seq): Promise<JournalEvent | undefined>;
|
|
24
|
+
protected doThreads(): Promise<ThreadIndexEntry[]>;
|
|
25
|
+
protected doSummaries(): Promise<ThreadSummary[]>;
|
|
26
|
+
protected doPutSummaries(summaries: readonly ThreadSummary[], writer: string): Promise<void>;
|
|
27
|
+
protected doReplaceCatalog(summaries: readonly ThreadSummary[], writer: string): Promise<void>;
|
|
28
|
+
private headSeq;
|
|
29
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { JournalEvent, Seq, ThreadSummary } from '../records/journal.js';
|
|
2
|
+
import { JournalStore, type AppendOutcome, type Attempt, type ThreadIndexEntry, type WriterLease } from '../journal/index.js';
|
|
3
|
+
export type SqlValue = string | number | null;
|
|
4
|
+
/** A synchronous SQLite connection: what the two stores differ in, except exclusivity. */
|
|
5
|
+
export type SqlConnection = {
|
|
6
|
+
/** Statements without parameters or results; may hold several (the schema). */
|
|
7
|
+
exec(sql: string): void;
|
|
8
|
+
run(sql: string, ...params: SqlValue[]): void;
|
|
9
|
+
all<Row>(sql: string, ...params: SqlValue[]): Row[];
|
|
10
|
+
/** Runs `body` as one write transaction, rolled back when it throws; resolves once the commit is durable. */
|
|
11
|
+
transaction<T>(body: () => T): Promise<T>;
|
|
12
|
+
/** Releases this adapter's resources; never the host's storage. */
|
|
13
|
+
close(): void;
|
|
14
|
+
};
|
|
15
|
+
/** The exclusivity a store's platform grants, taken before anything is read: an OS lock, an in-process registry. */
|
|
16
|
+
export type SqlExclusivity = {
|
|
17
|
+
readonly identity: string;
|
|
18
|
+
release(): void;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* The journal store over a synchronous SQLite connection: the schema and its version stamp, the
|
|
22
|
+
* writer record, every append, summary and catalog check, and row parsing. A subclass supplies the
|
|
23
|
+
* connection and the exclusivity its platform grants; nothing else differs between stores.
|
|
24
|
+
*/
|
|
25
|
+
export declare abstract class SqlJournalStore extends JournalStore {
|
|
26
|
+
private db;
|
|
27
|
+
/** The acquisition this store holds, recorded in `writer` once the database is open. */
|
|
28
|
+
private acquisition;
|
|
29
|
+
private readonly location;
|
|
30
|
+
/** `location` names the journal in errors, such as `IncompatibleJournalError`. */
|
|
31
|
+
protected constructor(location: string);
|
|
32
|
+
/** Opens the connection `doOpen` uses; the store closes it in `doClose`. */
|
|
33
|
+
protected abstract connect(): SqlConnection;
|
|
34
|
+
/** Takes the platform's exclusivity for `acquireWriter`, or rejects with `JournalBusyError`. */
|
|
35
|
+
protected abstract exclusive(): Promise<SqlExclusivity>;
|
|
36
|
+
acquireWriter(): Promise<WriterLease>;
|
|
37
|
+
/**
|
|
38
|
+
* Inside a transaction: refuses unless `writer` is the acquisition this store holds and the writer
|
|
39
|
+
* record names it. The held acquisition alone fences a released lease whose record could not be
|
|
40
|
+
* cleared; the record alone fences another process that took the journal over.
|
|
41
|
+
*/
|
|
42
|
+
private requireWriter;
|
|
43
|
+
/** Names this store's acquisition in the writer record, which every append checks. */
|
|
44
|
+
private recordWriter;
|
|
45
|
+
protected doOpen(): Promise<void>;
|
|
46
|
+
protected doClose(): Promise<void>;
|
|
47
|
+
private requireDb;
|
|
48
|
+
protected doHead(): Promise<Seq>;
|
|
49
|
+
private headOf;
|
|
50
|
+
protected doAppend(attempt: Attempt, digest: string): Promise<AppendOutcome>;
|
|
51
|
+
protected doRead(threadId: string): Promise<JournalEvent[]>;
|
|
52
|
+
protected doRowAt(seq: Seq): Promise<JournalEvent | undefined>;
|
|
53
|
+
protected doThreads(): Promise<ThreadIndexEntry[]>;
|
|
54
|
+
protected doSummaries(): Promise<ThreadSummary[]>;
|
|
55
|
+
protected doPutSummaries(summaries: readonly ThreadSummary[], writer: string): Promise<void>;
|
|
56
|
+
protected doReplaceCatalog(summaries: readonly ThreadSummary[], writer: string): Promise<void>;
|
|
57
|
+
private writeSummaries;
|
|
58
|
+
private rows;
|
|
59
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { SqlJournalStore, type SqlConnection, type SqlExclusivity } from './sql.js';
|
|
2
|
+
/** What `SqliteJournalStore` needs from the host, with no default for either. */
|
|
3
|
+
export type SqliteJournalStoreOptions = {
|
|
4
|
+
/**
|
|
5
|
+
* The directory the writer-lock files live in, an absolute path. Every process that opens this
|
|
6
|
+
* journal must be given the same one, or two writers are not refused; one beside the journal is
|
|
7
|
+
* the natural choice.
|
|
8
|
+
*/
|
|
9
|
+
readonly lockDirectory: string;
|
|
10
|
+
/**
|
|
11
|
+
* How long, in total, an append or a catalog write waits for another connection's write lock, a
|
|
12
|
+
* shell or a backup say, before it fails with `StoreBusyError`. `0` does not wait.
|
|
13
|
+
*/
|
|
14
|
+
readonly busyTimeoutMs: number;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* SQLite-backed journal at `<directory>/journal.db`: the rows in `events`, the thread index in
|
|
18
|
+
* `threads` and the attempt record in `attempts`, written in one transaction per group; the catalog
|
|
19
|
+
* in `summaries`, written after; the writer record in `writer`; the format stamp in `meta`. The
|
|
20
|
+
* writer lease is an operating system lock, so a process that dies releases it; the record holds the
|
|
21
|
+
* acquisition id every append checks. Construct one and pass it to `core` as `store`.
|
|
22
|
+
*/
|
|
23
|
+
export declare class SqliteJournalStore extends SqlJournalStore {
|
|
24
|
+
private readonly lockDirectory;
|
|
25
|
+
private readonly busyTimeoutMs;
|
|
26
|
+
readonly directory: string;
|
|
27
|
+
constructor(directory: string, options: SqliteJournalStoreOptions);
|
|
28
|
+
get databasePath(): string;
|
|
29
|
+
protected connect(): SqlConnection;
|
|
30
|
+
protected exclusive(): Promise<SqlExclusivity>;
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as m}from"../chunks/JCTBX33H.js";import{l as u,m as h}from"../chunks/BBCW2FZK.js";import"../chunks/MMNNZCBO.js";import"../chunks/G44LG6VL.js";import"../chunks/D4PQP5MA.js";import{closeSync as d,mkdirSync as c,openSync as w,realpathSync as f,statSync as p}from"node:fs";import{isAbsolute as M,join as n}from"node:path";import{DatabaseSync as y}from"node:sqlite";var b=class extends m{lockDirectory;busyTimeoutMs;directory;constructor(t,e){super(n(t,"journal.db")),this.directory=t;let{lockDirectory:r,busyTimeoutMs:s}=e;if(!M(r))throw new TypeError(`lockDirectory must be an absolute path: ${r}`);if(!Number.isFinite(s)||s<0)throw new TypeError(`busyTimeoutMs must be a finite number of milliseconds, zero or more: ${s}`);this.lockDirectory=r,this.busyTimeoutMs=s}get databasePath(){return n(this.directory,"journal.db")}connect(){return c(this.directory,{recursive:!0}),new a(this.databasePath,this.busyTimeoutMs)}async exclusive(){c(this.directory,{recursive:!0}),d(w(this.databasePath,"a",384));let t=f(this.databasePath),{dev:e,ino:r}=p(t,{bigint:!0});c(this.lockDirectory,{recursive:!0,mode:448});let s=new y(n(this.lockDirectory,`${e}-${r}.db`));try{s.exec("PRAGMA busy_timeout=0; BEGIN EXCLUSIVE")}catch(i){throw s.close(),l(i)?new u(t):i}return{identity:`sqlite:${e}:${r}`,release:()=>s.close()}}},a=class{db;path;busyTimeoutMs;statements=new Map;writes=Promise.resolve();constructor(t,e){this.path=t,this.busyTimeoutMs=e,this.db=new y(t);try{this.db.exec("PRAGMA journal_mode=WAL")}catch(r){throw this.db.close(),r}}exec(t){this.db.exec(t)}run(t,...e){this.statement(t).run(...e)}all(t,...e){return this.statement(t).all(...e)}transaction(t){let e=()=>this.write(t),r=this.writes.then(e,e);return this.writes=r.catch(()=>{}),r}close(){this.statements.clear(),this.db.close()}statement(t){let e=this.statements.get(t);return e===void 0&&(e=this.db.prepare(t),this.statements.set(t,e)),e}async write(t){await this.beginWrite();try{let e=t();return this.db.exec("COMMIT"),e}catch(e){throw this.rollback(),e}}async beginWrite(){let t=Date.now();for(let e=5;;e=Math.min(e*2,100))try{this.db.exec("BEGIN IMMEDIATE");return}catch(r){if(!l(r))throw r;let s=Date.now()-t;if(s>=this.busyTimeoutMs)throw new h(this.path,s);await new Promise(i=>setTimeout(i,Math.min(e,this.busyTimeoutMs-s)))}}rollback(){if(this.db.isTransaction)try{this.db.exec("ROLLBACK")}catch(t){console.error(t)}}},l=o=>{let t=o?.errcode;return typeof t=="number"&&(t&255)===5};export{b as SqliteJournalStore};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* What a process lagent spawns may see, and which programs lagent itself runs: both chosen by the
|
|
4
|
+
* host, never read from lagent's own process. A plugin that spawns takes them as required
|
|
5
|
+
* configuration; the helpers here only build them from what the host hands in.
|
|
6
|
+
*/
|
|
7
|
+
/** A spawned process's whole environment, as configuration: every variable it gets, nothing else. */
|
|
8
|
+
export declare const SpawnEnvironmentSchema: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
9
|
+
/**
|
|
10
|
+
* The overrides for a process with no terminal: colour and pagers off, and an editor that fails at
|
|
11
|
+
* once rather than sitting until the deadline. `CI` is deliberately not set, since test runners
|
|
12
|
+
* change more than interactivity under it.
|
|
13
|
+
*/
|
|
14
|
+
export declare const NON_INTERACTIVE_ENVIRONMENT: Readonly<Record<string, string>>;
|
|
15
|
+
/** How a host derives a spawn environment from its own. */
|
|
16
|
+
export type SpawnEnvironmentPolicy = {
|
|
17
|
+
/**
|
|
18
|
+
* Variables whose names match one of these patterns are dropped. A pattern matches a whole name,
|
|
19
|
+
* case-insensitively; `*` stands for any run of characters.
|
|
20
|
+
*/
|
|
21
|
+
readonly drop: readonly string[];
|
|
22
|
+
/** Set over what remains. */
|
|
23
|
+
readonly set: Readonly<Record<string, string>>;
|
|
24
|
+
};
|
|
25
|
+
/** `source` filtered and overridden by `policy`: the whole environment a spawned process gets. */
|
|
26
|
+
export declare function buildSpawnEnvironment(source: Readonly<Record<string, string | undefined>>, policy: SpawnEnvironmentPolicy): Record<string, string>;
|
|
27
|
+
/**
|
|
28
|
+
* The programs lagent runs itself, by absolute path: never looked up through a spawned process's
|
|
29
|
+
* `PATH`, which a workspace can reach. `rg` is `null` when there is none; the search tools, which
|
|
30
|
+
* run it, are then not provided.
|
|
31
|
+
*/
|
|
32
|
+
export declare const TrustedProgramsSchema: z.ZodObject<{
|
|
33
|
+
git: z.ZodString;
|
|
34
|
+
rg: z.ZodNullable<z.ZodString>;
|
|
35
|
+
}, z.core.$strict>;
|
|
36
|
+
export type TrustedPrograms = z.output<typeof TrustedProgramsSchema>;
|
|
37
|
+
/**
|
|
38
|
+
* Each trusted program as the first executable file of its name in `searchPath`'s directories, in
|
|
39
|
+
* order. Relative directories are skipped: what they name depends on the working directory. Throws
|
|
40
|
+
* when `git` is not found; `rg` is `null` when it is not.
|
|
41
|
+
*/
|
|
42
|
+
export declare function resolveTrustedPrograms(searchPath: string): TrustedPrograms;
|