@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,362 @@
|
|
|
1
|
+
import { Context, type Plugin } from '@leuduan/cordis';
|
|
2
|
+
import { Journal, type CoreFold, type JournalStore, type PluginJournal, type Summarizer } from '../journal/index.js';
|
|
3
|
+
import type { ConfirmationState, RouteStatement, RowRef, SendOutcome, TurnLimits } from '../state/index.js';
|
|
4
|
+
import type { InvocationContext, ResolvedWait, Tool } from '../loop/index.js';
|
|
5
|
+
import type { ConversationMessage, ThinkingEffort } from '../llm/primitives.js';
|
|
6
|
+
import type { FailureClassification } from '../llm/failure.js';
|
|
7
|
+
import type { LLMClient, ModelCapacity } from '../llm/client.js';
|
|
8
|
+
import type { ModelRequest } from '../llm/request.js';
|
|
9
|
+
import type { ModelRoute } from '../llm/provider.js';
|
|
10
|
+
import type { PromptBlock } from '../llm/prompt.js';
|
|
11
|
+
import type { DeepReadonly, ReadonlyJsonValue } from '../util/json.js';
|
|
12
|
+
import type { AgentDefinitionInput } from '../loop/index.js';
|
|
13
|
+
import type { ExtensionRecord, JournalEvent, Seq, ThreadOrigin, ThreadSummary, TurnEndReason } from '../records/journal.js';
|
|
14
|
+
import { type TrustedPrograms } from '../sys/environment.js';
|
|
15
|
+
import type { ConfinementService, Launched, LaunchOptions, LaunchRequest } from '../services/confinement/service.js';
|
|
16
|
+
import { MemoryJournalStore } from '../stores/memory.js';
|
|
17
|
+
import { type PromptContribution } from '../services/prompts.js';
|
|
18
|
+
import { type RetryPolicy } from '../services/llm.js';
|
|
19
|
+
import type { Thread } from '../services/threads/index.js';
|
|
20
|
+
import type { BirthInput, CreateThreadOptions, Opening } from '../services/threads/index.js';
|
|
21
|
+
import type { InitialInstallationInput } from '../services/presets/installations.js';
|
|
22
|
+
import type { OwnerHandle, StartOptions } from '../services/threads/index.js';
|
|
23
|
+
import type { DelegationsConfig } from '../plugins/delegations/service.js';
|
|
24
|
+
import type { ThreadView } from '../services/threads/index.js';
|
|
25
|
+
import { ownedTmpDir, tmpWorkspace } from './tmpDirs.js';
|
|
26
|
+
/**
|
|
27
|
+
* A provider plugin that hands out one fixed client, for tests and embedding. Like the real ones,
|
|
28
|
+
* it takes an optional default thinking effort; it declares what `capacity` answers, by default no
|
|
29
|
+
* window, no provider-executed tools and no images in tool results, and classifies every failure
|
|
30
|
+
* the engine's typed evidence leaves to it as `classify` says, by default `other`.
|
|
31
|
+
*/
|
|
32
|
+
export declare const fakeProvider: (client: LLMClient, name?: string) => Plugin.Object<{
|
|
33
|
+
thinkingEffort?: ThinkingEffort;
|
|
34
|
+
capacity?: (model: string) => ModelCapacity;
|
|
35
|
+
classify?: (error: unknown) => FailureClassification;
|
|
36
|
+
retry?: RetryPolicy;
|
|
37
|
+
} | undefined>;
|
|
38
|
+
/** The route of the fake provider a test root registers: what a test thread is born on. */
|
|
39
|
+
export declare const TEST_ROUTE: ModelRoute;
|
|
40
|
+
/** The retry policy a test provider gets unless it asks for one: a call is never sent twice. */
|
|
41
|
+
export declare const NO_RETRY: RetryPolicy;
|
|
42
|
+
export type TestRootOptions = {
|
|
43
|
+
llm: LLMClient;
|
|
44
|
+
/** Start from an existing journal, as reopening does. */
|
|
45
|
+
store?: JournalStore;
|
|
46
|
+
cwd?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Where `threadDirs` keeps thread directories: a temporary directory, removed with the
|
|
49
|
+
* root, when omitted; `null` mounts no thread directories, as on a host with no file system.
|
|
50
|
+
*/
|
|
51
|
+
dataDir?: string | null;
|
|
52
|
+
limits?: Partial<TurnLimits>;
|
|
53
|
+
/** Agents to register, each granted its `tools`; one `main_agent` that can read files when omitted. */
|
|
54
|
+
agents?: readonly TestAgent[];
|
|
55
|
+
/** Tools to register; just the test reader when omitted. */
|
|
56
|
+
tools?: readonly TestToolEntry[];
|
|
57
|
+
/** What the fake provider declares it can carry; no window when omitted. */
|
|
58
|
+
capacity?: (model: string) => ModelCapacity;
|
|
59
|
+
/** How the fake provider classifies a failure the engine's typed evidence leaves to it; `other` when omitted. */
|
|
60
|
+
classify?: (error: unknown) => FailureClassification;
|
|
61
|
+
/** How the fake provider's calls are retried; never when omitted. */
|
|
62
|
+
retry?: RetryPolicy;
|
|
63
|
+
/**
|
|
64
|
+
* `defer` leaves `ctx.threads.start` to the test, which calls it once after composing what it
|
|
65
|
+
* mounts beside: a reopened journal's recovered runs would otherwise start before it. Started at
|
|
66
|
+
* once, with every pending run resumed, when omitted.
|
|
67
|
+
*/
|
|
68
|
+
start?: 'defer';
|
|
69
|
+
/**
|
|
70
|
+
* What the threads service does with a thread nothing holds any more. `keep` when omitted, so a
|
|
71
|
+
* test reads a thread's rows after its run; a host's test passes what the host configures.
|
|
72
|
+
*/
|
|
73
|
+
retention?: 'retire' | 'keep';
|
|
74
|
+
/** How many reactive turns in a row a thread may run; {@link TEST_CHAIN_LIMIT} when omitted. */
|
|
75
|
+
chainLimit?: number;
|
|
76
|
+
/**
|
|
77
|
+
* `manual` leaves disposing the root to the caller, for one that a whole file's tests share, such
|
|
78
|
+
* as a root holding a process-wide service. Disposed when the test that made it finishes when omitted.
|
|
79
|
+
*/
|
|
80
|
+
disposal?: 'manual';
|
|
81
|
+
};
|
|
82
|
+
/** The chain limit a test root gets unless it asks for one: room for any test's notices. */
|
|
83
|
+
export declare const TEST_CHAIN_LIMIT = 10;
|
|
84
|
+
/** How a test root starts: every pending run resumed, with room for every thread a test runs. */
|
|
85
|
+
export declare const TEST_START: StartOptions;
|
|
86
|
+
/** `Omit` over each member of a union, which a plain `Omit` would collapse into one object type. */
|
|
87
|
+
type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
|
|
88
|
+
type BirthFields = Partial<BirthInput<InitialInstallationInput>>;
|
|
89
|
+
/**
|
|
90
|
+
* A fresh thread's `birth` on {@link TEST_ROUTE} from `defaults`, with `fields` beside its route, in
|
|
91
|
+
* the shape `create` takes. `from: 'caller'` says the birth reads the origin's live caller instead,
|
|
92
|
+
* which the options then name an `origin` for.
|
|
93
|
+
*/
|
|
94
|
+
export declare function testBirth(fields?: BirthFields): {
|
|
95
|
+
from: 'defaults';
|
|
96
|
+
} & BirthInput<InitialInstallationInput>;
|
|
97
|
+
export declare function testBirth(fields: BirthFields & {
|
|
98
|
+
from: 'caller';
|
|
99
|
+
}): {
|
|
100
|
+
from: 'caller';
|
|
101
|
+
} & BirthInput<InitialInstallationInput>;
|
|
102
|
+
/**
|
|
103
|
+
* What {@link TestRoot.newThread} takes: `create`'s options, with a fresh id and `main_agent`.
|
|
104
|
+
* `reuse` and `birth`, given together as `create` takes them, default as a whole to `identity`
|
|
105
|
+
* reuse of {@link testBirth}`()`.
|
|
106
|
+
*/
|
|
107
|
+
export type TestThreadOptions = Omit<Opening, 'id'> & {
|
|
108
|
+
/** A fresh id is generated when omitted. */
|
|
109
|
+
id?: string;
|
|
110
|
+
/** `main_agent` when omitted. */
|
|
111
|
+
agent?: string;
|
|
112
|
+
} & ({
|
|
113
|
+
reuse?: undefined;
|
|
114
|
+
birth?: undefined;
|
|
115
|
+
origin?: undefined;
|
|
116
|
+
} | DistributiveOmit<CreateThreadOptions, keyof Opening>);
|
|
117
|
+
export type TestRoot = Context & {
|
|
118
|
+
/** Every journal event appended since the root was made. */
|
|
119
|
+
appended: JournalEvent[];
|
|
120
|
+
/** `threads.create` with a fresh id and test defaults: `main_agent`, born on {@link TEST_ROUTE} (see {@link TestThreadOptions}). */
|
|
121
|
+
newThread(options?: TestThreadOptions): Promise<Thread>;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* A root with the core, a fake provider, and the given agents and tools mounted. It lives as long
|
|
125
|
+
* as the test that made it, in its body or a `beforeEach`: disposed once that test finishes, unless
|
|
126
|
+
* the test disposed it before.
|
|
127
|
+
*/
|
|
128
|
+
export declare function createTestRoot(options: TestRootOptions): Promise<TestRoot>;
|
|
129
|
+
/**
|
|
130
|
+
* The spawn environment tests run programs with: this process's, filtered as the hosts filter
|
|
131
|
+
* theirs. Tests are the host here, so they may read `process.env`.
|
|
132
|
+
*/
|
|
133
|
+
export declare const testEnvironment: () => Record<string, string>;
|
|
134
|
+
/** The trusted programs tests run, found on this process's `PATH`. */
|
|
135
|
+
export declare const testPrograms: () => TrustedPrograms;
|
|
136
|
+
/** Minimal file reader so loop tests can exercise the tool path without the file tools. */
|
|
137
|
+
export declare const testReadFileTool: Tool;
|
|
138
|
+
export type TestToolEntry = {
|
|
139
|
+
name: string;
|
|
140
|
+
tool: Tool;
|
|
141
|
+
};
|
|
142
|
+
/** The default tool set for loop tests: just the reader. */
|
|
143
|
+
export declare const testTools: () => TestToolEntry[];
|
|
144
|
+
/** An agent definition and the tools a fixture grants it, written together for brevity. */
|
|
145
|
+
export type TestAgent = AgentDefinitionInput & {
|
|
146
|
+
readonly tools?: readonly string[];
|
|
147
|
+
};
|
|
148
|
+
/** Registers each agent and grants it its `tools`, in order, for the life of the plugin. */
|
|
149
|
+
export declare const testAgentsPlugin: (agents: readonly TestAgent[]) => Plugin.Object<undefined>;
|
|
150
|
+
/** One agent that can read files, the shape most loop tests need. */
|
|
151
|
+
export declare const testAgent: (overrides?: Partial<TestAgent>) => TestAgent;
|
|
152
|
+
export declare const testAgents: (...agents: Partial<TestAgent>[]) => TestAgent[];
|
|
153
|
+
/** What a test's {@link drive} asks: a route statement for the cause it writes, and a signal that cancels it. */
|
|
154
|
+
export type DriveOptions = {
|
|
155
|
+
readonly route?: RouteStatement;
|
|
156
|
+
readonly signal?: AbortSignal;
|
|
157
|
+
/** Resolve at a `wait` hold too, rather than follow the run until its waits resolve. */
|
|
158
|
+
readonly untilWait?: boolean;
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* How a driven run ended, as a test reads it: `turns` when it opened a turn, `none` when it opened
|
|
162
|
+
* none, `cancelled` when it was cancelled or shutdown held it; how the last turn it closed ended;
|
|
163
|
+
* and the confirmations it left waiting, `null` when cancelled before the run was read. A run held
|
|
164
|
+
* on an approval ends `turns`, its last turn `blocked`.
|
|
165
|
+
*/
|
|
166
|
+
export type DriveResult = {
|
|
167
|
+
readonly thread_id: string;
|
|
168
|
+
readonly ended: 'none' | 'turns' | 'cancelled';
|
|
169
|
+
readonly reason: DeepReadonly<TurnEndReason> | null;
|
|
170
|
+
readonly pending_confirmations: DeepReadonly<ConfirmationState[]> | null;
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* The testing door into execution: asks `thread` to run as a person does (`resume`, a cause that
|
|
174
|
+
* releases its holds), drives it once, and resolves when its run is held or settled; a run held on a
|
|
175
|
+
* call's `wait` goes on once the wait resolves, so it is followed through it unless `untilWait`
|
|
176
|
+
* says to stop there. Applications
|
|
177
|
+
* never drive a thread; they send to it. `route` is the cause's route statement; a `signal` that aborts cancels the thread as a person's stop does (`Thread.cancel`, which
|
|
178
|
+
* also clears its queued input), one already aborted before anything runs.
|
|
179
|
+
*/
|
|
180
|
+
export declare function drive(thread: Thread, options?: DriveOptions): Promise<DriveResult>;
|
|
181
|
+
/** The delegations plugin's configuration for a test: 8 open tasks per origin tree and the system clock unless given. */
|
|
182
|
+
export declare const testDelegations: (overrides?: Partial<DelegationsConfig>) => DelegationsConfig;
|
|
183
|
+
/** The owner `testWaitOwner` registers by default. */
|
|
184
|
+
export declare const TEST_WAIT_OWNER = "test:waits";
|
|
185
|
+
/**
|
|
186
|
+
* Registers a constraint owner a test's tools may wait on (`waitFor({ owner: TEST_WAIT_OWNER, … })`)
|
|
187
|
+
* and returns its handle, whose `resolveWait` the test resolves them with. It constrains no thread.
|
|
188
|
+
*/
|
|
189
|
+
export declare function testWaitOwner(root: Context, owner?: string): OwnerHandle;
|
|
190
|
+
/**
|
|
191
|
+
* Holds `threadIds` from running, as a constraint holding them does, until `release()`: a test that
|
|
192
|
+
* answers or sends and must look before the owner runs the thread takes this first.
|
|
193
|
+
*/
|
|
194
|
+
export declare function holdRuns(root: Context, ...threadIds: string[]): {
|
|
195
|
+
release(): void;
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Resolves once nothing on the root runs or waits to run: every pending run held or settled, as a
|
|
199
|
+
* started root leaves things once the work its causes asked for is done.
|
|
200
|
+
*/
|
|
201
|
+
export declare function untilQuiet(root: Context): Promise<void>;
|
|
202
|
+
/** Starts a thread on `agent` (the first registered agent by default) and drives one turn on `text`. */
|
|
203
|
+
export declare function runTestTurn(root: Context, text?: string, options?: {
|
|
204
|
+
agent?: string;
|
|
205
|
+
threadId?: string;
|
|
206
|
+
}): Promise<{
|
|
207
|
+
thread: Thread;
|
|
208
|
+
result: DriveResult;
|
|
209
|
+
}>;
|
|
210
|
+
/**
|
|
211
|
+
* What a turn opened on the fake provider records, for a test that writes `turn/start` itself: the
|
|
212
|
+
* turn serves run `runId`, whose execution was admitted at `attemptCutoff`.
|
|
213
|
+
*/
|
|
214
|
+
export declare const turnStartData: (turn: number, runId?: string, attemptCutoff?: number) => {
|
|
215
|
+
turn: number;
|
|
216
|
+
route: {
|
|
217
|
+
provider: string;
|
|
218
|
+
model: string;
|
|
219
|
+
thinking_effort: "low" | "high" | "none" | "medium" | "max" | null;
|
|
220
|
+
};
|
|
221
|
+
run_id: string;
|
|
222
|
+
attempt_cutoff: number;
|
|
223
|
+
};
|
|
224
|
+
/** An invocation context for calling a tool directly, without a loop around it. */
|
|
225
|
+
export declare function testInvocationContext(root: Context, options?: {
|
|
226
|
+
threadId?: string;
|
|
227
|
+
agentName?: string;
|
|
228
|
+
callId?: string;
|
|
229
|
+
callSeq?: number;
|
|
230
|
+
cwd?: string;
|
|
231
|
+
/** The turn's route; the fake provider's when omitted. */
|
|
232
|
+
route?: ModelRoute;
|
|
233
|
+
/** The resolved wait of a dispatch again; none when omitted. */
|
|
234
|
+
wait?: ResolvedWait | null;
|
|
235
|
+
}): InvocationContext;
|
|
236
|
+
export { ownedTmpDir, tmpWorkspace };
|
|
237
|
+
/**
|
|
238
|
+
* Replaces `rows`, a run of a thread's surface, with one stand-in, between turns, as a manual
|
|
239
|
+
* compaction records it: through `replaceSurface`, which refuses it with a
|
|
240
|
+
* `ReplacementRefusedError` where the surface would not take it.
|
|
241
|
+
*/
|
|
242
|
+
export declare function replaceSpan(journal: PluginJournal, threadId: string, rows: readonly RowRef[], text: string, options?: {
|
|
243
|
+
role?: 'user' | 'assistant';
|
|
244
|
+
source?: ExtensionRecord;
|
|
245
|
+
}): Promise<JournalEvent<'surface/replaced'>>;
|
|
246
|
+
/** The text of a message that may not exist — the shape an assertion usually wants. */
|
|
247
|
+
export declare const textOf: (message: DeepReadonly<ConversationMessage> | undefined) => string;
|
|
248
|
+
/** A model request with everything defaulted, for a test that cares about one field. */
|
|
249
|
+
export declare const modelRequest: (overrides?: Partial<ModelRequest>) => ModelRequest;
|
|
250
|
+
/** The system prompt a request carried, as one string. */
|
|
251
|
+
export declare const promptTextOf: (request: {
|
|
252
|
+
systemPrompt: readonly PromptBlock[];
|
|
253
|
+
}) => string;
|
|
254
|
+
/** Content of the last `role: tool` message the model received in a request. */
|
|
255
|
+
export declare const lastToolMessage: (messages: readonly DeepReadonly<ConversationMessage>[]) => string | null;
|
|
256
|
+
/**
|
|
257
|
+
* A thread's view, read now, for a test that has just run or written to it in this process, which
|
|
258
|
+
* loaded it: the synchronous counterpart of `thread.read` that tests use for brevity. Throws
|
|
259
|
+
* `ThreadNotLoadedError` for a thread nothing loaded.
|
|
260
|
+
*/
|
|
261
|
+
export declare const viewOf: (thread: Thread) => ThreadView;
|
|
262
|
+
/** The row a `send` queued its input at, or found it queued at; a refused send fails the test. */
|
|
263
|
+
export declare function sentAt(outcome: SendOutcome): Seq;
|
|
264
|
+
/** A thread's tool results as its conversation holds them, in order. */
|
|
265
|
+
export declare const toolResultsOf: (thread: Thread) => string[];
|
|
266
|
+
/** Every tool result the model saw, across every thread and request. */
|
|
267
|
+
export declare const toolMessages: (requests: readonly ModelRequest[]) => string[];
|
|
268
|
+
/**
|
|
269
|
+
* A summary from a thread's rows alone, consulting no fold: for tests of `journal/` itself, whose
|
|
270
|
+
* folds are their own and must not meet the loop's. The identity comes from the spawn row when
|
|
271
|
+
* there is one; nothing is ever pending.
|
|
272
|
+
*/
|
|
273
|
+
export declare const bareSummary: Summarizer;
|
|
274
|
+
export interface TestJournalOptions {
|
|
275
|
+
/** How summaries are computed: the loop's `summarizeThread` unless given, `bareSummary` for `journal/` tests. */
|
|
276
|
+
summarize?: Summarizer;
|
|
277
|
+
onListenerError?: (error: unknown) => void;
|
|
278
|
+
/**
|
|
279
|
+
* Core folds the journal registers at construction. When omitted: `threadState`, which the loop's
|
|
280
|
+
* summary reads, unless `summarize` is given, as a test of `journal/` alone does, and then none.
|
|
281
|
+
*/
|
|
282
|
+
coreFolds?: readonly CoreFold<unknown>[];
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* A journal over `store` for tests that drive the journal without a root. Not opened.
|
|
286
|
+
*/
|
|
287
|
+
export declare function testJournal(store?: JournalStore, options?: TestJournalOptions): Journal;
|
|
288
|
+
/**
|
|
289
|
+
* Every row the journal holds, across its threads, in seq order: what a test asserts over a whole
|
|
290
|
+
* journal. Loads every thread first.
|
|
291
|
+
*/
|
|
292
|
+
export declare function journalRows(journal: PluginJournal): Promise<JournalEvent[]>;
|
|
293
|
+
/** Every row a store holds, across its threads, in seq order; opens and closes a closed store around the read. */
|
|
294
|
+
export declare function storeRows(store: JournalStore): Promise<JournalEvent[]>;
|
|
295
|
+
/**
|
|
296
|
+
* Writes `rows` into an open `store`, one attempt per row, under a writer lease it takes and gives back:
|
|
297
|
+
* rows written past the journal, as a test that bypasses its gate needs. No journal may hold the store.
|
|
298
|
+
*/
|
|
299
|
+
export declare function writeRows(store: JournalStore, rows: readonly JournalEvent[], summaries: readonly ThreadSummary[]): Promise<void>;
|
|
300
|
+
/** The value of the contribution under `key` in `summary`'s catalog entry, past its cache envelope; `undefined` without an entry. */
|
|
301
|
+
export declare const contributedValue: (summary: ThreadSummary, key: string) => unknown;
|
|
302
|
+
/** Replaces a store's catalog past the journal, under a writer lease it takes and gives back: damage a test inflicts. */
|
|
303
|
+
export declare function writeCatalog(store: JournalStore, summaries: readonly ThreadSummary[]): Promise<void>;
|
|
304
|
+
/**
|
|
305
|
+
* A memory store holding exactly what `source` holds — its rows and its catalog, as they are — the
|
|
306
|
+
* way a process that crashed leaves them for the next one to open. Returned open, its lease free.
|
|
307
|
+
*/
|
|
308
|
+
export declare function copyStore(source: JournalStore): Promise<MemoryJournalStore>;
|
|
309
|
+
/**
|
|
310
|
+
* A memory store holding exactly `events` — seqs and timestamps as they are, gaps included — with
|
|
311
|
+
* a catalog rebuilt from them: a journal cut off, or thinned, where a test says. Returned open, its
|
|
312
|
+
* lease free.
|
|
313
|
+
*/
|
|
314
|
+
export declare function replayStore(events: readonly JournalEvent[]): Promise<MemoryJournalStore>;
|
|
315
|
+
/**
|
|
316
|
+
* Makes core's fold throw on every row `fails` accepts, as a thread core cannot read behaves: a
|
|
317
|
+
* thread whose rows it cannot fold does not load. Scoped to the test that calls it, undone when it
|
|
318
|
+
* finishes or when the returned function is called, whichever comes first.
|
|
319
|
+
*/
|
|
320
|
+
export declare function breakCoreFold(fails: (event: JournalEvent) => boolean): () => void;
|
|
321
|
+
/**
|
|
322
|
+
* `rows` with the origin rule broken above `threadId`, damage a test inflicts: its caller's rows
|
|
323
|
+
* dropped (`missing`), or its caller's spawn row naming `threadId` as its own caller (`cycle`).
|
|
324
|
+
*/
|
|
325
|
+
export declare function breakCallerChain(rows: readonly JournalEvent[], threadId: string, damage: 'missing' | 'cycle'): JournalEvent[];
|
|
326
|
+
/**
|
|
327
|
+
* The origin of a thread a test creates under `callerId`, citing a real `tool/call` row recorded on
|
|
328
|
+
* the caller now: what `origins.validate` requires of a call cause. The call is not on any turn, so
|
|
329
|
+
* only a caller that no test drives afterwards should be given one.
|
|
330
|
+
*/
|
|
331
|
+
export declare function callOrigin(root: Context, callerId: string): Promise<{
|
|
332
|
+
caller_thread_id: string;
|
|
333
|
+
source_seq: Seq;
|
|
334
|
+
cause: {
|
|
335
|
+
kind: 'call';
|
|
336
|
+
};
|
|
337
|
+
}>;
|
|
338
|
+
/**
|
|
339
|
+
* The invocation context of a call `threadId` made, named by `label`: a real `tool/call` row recorded
|
|
340
|
+
* on the thread the first time the label is asked for, so the origin a delegation records cites a row
|
|
341
|
+
* of its caller (`origins.validate`), and the same label is the same call afterwards, as a
|
|
342
|
+
* re-dispatch of it is. `options` are {@link testInvocationContext}'s, without the call's identity.
|
|
343
|
+
*/
|
|
344
|
+
export declare function callAt(root: Context, threadId: string, label: string | number, options?: Omit<NonNullable<Parameters<typeof testInvocationContext>[1]>, 'threadId' | 'callSeq' | 'callId'>): Promise<InvocationContext>;
|
|
345
|
+
/**
|
|
346
|
+
* The origin of a thread an owner's assignment creates under `callerId`: the row that granted it is
|
|
347
|
+
* the caller's spawn row, a real row of the caller, and `key` is the owner's.
|
|
348
|
+
*/
|
|
349
|
+
export declare function assignmentOrigin(root: Context, callerId: string, owner: string, key: ReadonlyJsonValue): ThreadOrigin;
|
|
350
|
+
/** Mounts one agent as a plugin, for tests that need a registration with a fiber of its own. */
|
|
351
|
+
export declare const testAgentPlugin: (agent: AgentDefinitionInput) => Plugin.Object<undefined>;
|
|
352
|
+
/** Mounts one prompt contribution as a plugin, for tests that need it with a fiber of its own. */
|
|
353
|
+
export declare const testPromptPlugin: (contribution: PromptContribution) => Plugin.Object<undefined>;
|
|
354
|
+
/** One shell launch for `request.threadId` as its own operation: a snapshot, then the launch under it. */
|
|
355
|
+
export declare function launchOnce(service: ConfinementService, { threadId, ...request }: LaunchRequest & {
|
|
356
|
+
threadId: string;
|
|
357
|
+
program: {
|
|
358
|
+
shell: string;
|
|
359
|
+
};
|
|
360
|
+
}, options: LaunchOptions): Promise<Launched>;
|
|
361
|
+
/** Makes every launch through `confinement` report that its stop could not be confirmed, as a launcher that cannot confirm the group ended. */
|
|
362
|
+
export declare function failStops(confinement: ConfinementService): void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test doubles and helpers, available at `@leuduan/lagent/testing` so they stay out of the engine's
|
|
3
|
+
* public surface. They are not part of the semver contract the root entry point offers.
|
|
4
|
+
*
|
|
5
|
+
* The door lists exactly the names hosts outside this package use. lagent's own tests import the
|
|
6
|
+
* helper modules by relative path, so a helper only they need stays in its module and off this list.
|
|
7
|
+
*/
|
|
8
|
+
export { FakeLLMClient, assistant, withToolCalls } from './fakeLlm.js';
|
|
9
|
+
export type { FakeChatHandler } from './fakeLlm.js';
|
|
10
|
+
export { FedLLM } from './fedLlm.js';
|
|
11
|
+
export { TEST_START, callOrigin, copyStore, createTestRoot, drive, fakeProvider, journalRows, lastToolMessage, replaceSpan, replayStore, storeRows, testAgents, testAgentsPlugin, testBirth, testDelegations, testEnvironment, testPrograms, testPromptPlugin, textOf, tmpWorkspace, viewOf, } from './helpers.js';
|
|
12
|
+
export type { TestRoot, TestRootOptions } from './helpers.js';
|
|
13
|
+
export { manualClock } from './clock.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as B}from"../chunks/W57RW55W.js";import{a as E,b as I,c as N,f as J,h as m}from"../chunks/B4FXK5ER.js";import"../chunks/SS3B5W34.js";import"../chunks/IAAEP6VL.js";import"../chunks/OCBPT7KE.js";import"../chunks/2P47AHNK.js";import"../chunks/MHC6VPB4.js";import"../chunks/EMRB4KCN.js";import"../chunks/RCIHV3KG.js";import"../chunks/2GCIWSOA.js";import{a as z}from"../chunks/GGSVIIWJ.js";import{c as L,d as M}from"../chunks/CANPZYTH.js";import"../chunks/VYMT4TXD.js";import"../chunks/MNJ4SRF7.js";import"../chunks/JFZZXVWD.js";import{c as F,e as W}from"../chunks/N6IXG2VL.js";import"../chunks/6DRCKZ2C.js";import"../chunks/7LI64H5X.js";import"../chunks/3UMZMPWW.js";import{a as A}from"../chunks/Q75FUN7D.js";import"../chunks/PUSUPTAT.js";import"../chunks/34KW6VNQ.js";import"../chunks/KUZCL2SH.js";import"../chunks/CQEVREBT.js";import{b as $}from"../chunks/HK6ZSONF.js";import"../chunks/7VAPNE3L.js";import{b as C}from"../chunks/EPYQ5M3B.js";import{a as b,c as R}from"../chunks/5IRF47YB.js";import"../chunks/OL5A6ITQ.js";import{b as D,e as j}from"../chunks/JFX2MXBA.js";import"../chunks/S34ZA2R6.js";import"../chunks/6FRNHMCV.js";import{b as P}from"../chunks/CUK7CGC7.js";import{H as S,s as q}from"../chunks/BPRCULZH.js";import"../chunks/FJLU4UH3.js";import{f as O}from"../chunks/DDANMY45.js";import{w as v}from"../chunks/BBCW2FZK.js";import"../chunks/MMNNZCBO.js";import"../chunks/G44LG6VL.js";import{o as T,q as p,r as w}from"../chunks/D4PQP5MA.js";var u=class{claimed=!1;ledger=new A;failure;chunks;settled;options;constructor(e,n,r={}){this.chunks=e,this.settled=n,this.options=r}[Symbol.asyncIterator](){if(this.claimed)throw new Error("A response is read once: it has been claimed already");this.claimed=!0;let e=this.read();return{next:()=>this.ledger.operation(()=>e.next()),return:n=>this.ledger.operation(()=>e.return(n),!0),throw:n=>this.ledger.operation(()=>e.throw(n),!0)}}async*read(){try{for await(let n of this.chunks)yield T.parse(n);let e=this.options.readFailure===!0?this.settlement():void 0;if(e instanceof Error)throw e}catch(e){throw this.failure={error:e},e}finally{this.ledger.finish()}}settlement(){return typeof this.settled=="function"?this.settled():this.settled}async completed(){if(this.claimed){if(!this.ledger.ended)throw new Error("A response is settled before its read or after it, not while the read is under way")}else for await(let n of this);if(this.failure!==void 0)throw this.failure.error;let e=this.settlement();if(e instanceof Error)throw e;return"finish"in e?e:{message:e,finish:this.options.finish??"completed",provider_metadata:{}}}},g=class t{providerName="fake";requests=[];handler;constructor(e){this.handler=e}static scripted(...e){let n=0;return new t(()=>{let r=e[n];if(r===void 0)throw new Error(`Unexpected LLM call #${n+1}`);return n+=1,r})}async chat(e){if(this.requests.push(e),e.signal?.aborted)throw e.signal.reason instanceof Error?e.signal.reason:new Error("aborted");let n=await this.handler(e.messages,e);return"failure"in n?new u(n.chunks,n.failure):"chunks"in n?new u(n.chunks,n.message):new u([],n)}},ie=(t,e={})=>p({role:"assistant",content:t,...e}),le=(t,e=null)=>p({role:"assistant",content:e,tool_calls:t.map(n=>n.arguments===void 0?{...n,arguments:{}}:n)});var y=class{request;queue=[];ended=null;text="";wake=null;constructor(e){this.request=e,e.signal?.addEventListener("abort",()=>{this.ended??={cutOff:!0},this.wake?.()},{once:!0})}push(e){this.queue.push(e),this.wake?.()}finish(e,n={}){this.ended??={message:p({role:"assistant",content:e,...n})},this.wake?.()}fail(e){this.ended??={error:e},this.wake?.()}stream=new u(this.feed(),()=>this.ended!==null&&"cutOff"in this.ended?{message:p({role:"assistant",content:this.text||null}),finish:"other",provider_metadata:{}}:this.ended!==null&&"message"in this.ended?this.ended.message:new Error("The stream did not finish"));async*feed(){for(;;){let e=this.queue.shift();if(e!==void 0){this.text+=e.text_delta??"",yield e;continue}if(this.ended!==null){if("error"in this.ended)throw this.ended.error;return}await new Promise(n=>this.wake=n),this.wake=null}}},x=class{providerName="fake";calls=[];waiting=[];taken=0;async chat(e){let n=new y(e);return this.calls.push(n),this.waiting.shift()?.(n),n.stream}next(){let e=this.taken++,n=this.calls[e];return n!==void 0?Promise.resolve(n):new Promise(r=>this.waiting.push(r))}};import{randomUUID as _}from"node:crypto";import{resolve as me}from"node:path";import{Context as he,scopeOf as we}from"@leuduan/cordis";import{onTestFinished as ge,vi as tt}from"vitest";import{z as Q}from"zod";import{mkdtempSync as de,rmSync as ce}from"node:fs";import{tmpdir as ue}from"node:os";import{join as pe}from"node:path";import{onTestFinished as fe}from"vitest";var U=new Set;function H(t){let e=de(pe(ue(),t));return U.add(e),e}function V(t){U.delete(t),ce(t,{recursive:!0,force:!0})}function Y(t="lagent-test-"){let e=H(t);return fe(()=>V(e)),{root:e}}function G(t,e="lagent-test-"){let n=H(e);return t.effect(()=>()=>V(n)),n}var Z=(t,e="fake")=>({name:`test:provider:${e}`,inject:["llm"],apply:(n,r)=>I(n,{name:e,defaultModel:"test-model",...r?.thinkingEffort===void 0?{}:{defaultThinkingEffort:r.thinkingEffort},capacity:r?.capacity??(()=>({contextWindow:null,providerTools:!1,toolResultImages:!1})),createClient:()=>t,classify:r?.classify??(()=>({kind:"other"}))},{retry:r?.retry??xe})}),ye=Object.freeze({provider:"fake",model:"test-model",thinking_effort:null}),xe={maxAttempts:1,baseDelayMs:0,maxDelayMs:0},_e=10,K={resume:"all",startLimit:64};function ee(t={}){return{from:"defaults",route:ye,...t}}async function ke(t){let e=new he;t.disposal!=="manual"&&ge(()=>e.fiber.dispose()),await e.plugin(N,{store:t.store??new m,cwd:t.cwd??process.cwd(),retention:t.retention??"keep",chainLimit:t.chainLimit??_e,...t.limits===void 0?{}:{limits:t.limits}});let n=t.dataDir===void 0?G(e,"lagent-data-"):t.dataDir;return n!==null&&await e.plugin(B,{dataDir:n}),await e.plugin(Z(t.llm),{...t.capacity===void 0?{}:{capacity:t.capacity},...t.classify===void 0?{}:{classify:t.classify},...t.retry===void 0?{}:{retry:t.retry}}),await e.plugin(te(t.agents??ne())),await e.plugin({name:"test:tools",inject:["tools"],apply(r){for(let{name:s,tool:o}of t.tools??Se())r.effect(()=>r.tools.register(we(r),s,o))}}),e.appended=[],e.journal.subscribe(r=>e.appended.push(r)),e.newThread=({id:r=_(),agent:s="main_agent",...o}={})=>e.threads.create(s,{id:r,...o.birth===void 0?{reuse:"identity",birth:ee()}:{},...o}),t.start!=="defer"&&await e.threads.start(K),e}var Te=()=>{let t=F(process.env,J);for(let e of z)delete t[e];return t},ve=()=>W(process.env.PATH??""),qe=Q.strictObject({path:Q.string()}),Ee=D({name:"read_file",description:"Read a file from the workspace.",parameters:qe,onInterrupted:"rerun",executionMode:"parallel",async execute(t,e){let n=await e.operation.files.open(me(e.environment.cwd,t.path));try{return{output:(await n.readAll()).toString("utf8")}}finally{await n.close()}}}),Se=()=>[{name:"read_file",tool:Ee}],te=t=>({name:"test:agents",inject:["agents","tools"],apply(e){for(let{tools:n=[],...r}of t){P(e,r);for(let s of n)j(e,s,[r.name])}}}),X=(t={})=>({name:"main_agent",tools:["read_file"],...t}),ne=(...t)=>t.length>0?t.map(e=>X(e)):[X()];async function be(t,e={}){let{route:n,signal:r,untilWait:s=!1}=e,o=()=>t.cancel(r===void 0?"Turn cancelled":O(r.reason),{intent:"user"});if(r?.aborted)return await o(),{thread_id:t.id,ended:"cancelled",reason:null,pending_confirmations:null};let a,i=()=>{a=o(),a.catch(()=>{})};r?.addEventListener("abort",i,{once:!0});let d=t.service,h=t.summary.through_seq;try{let f=await t.resume(n===void 0?{}:{route:n});if(a!==void 0)return await a,{thread_id:t.id,ended:"cancelled",reason:null,pending_confirmations:null};let c=await L(d,t.id,f,l=>M(l)&&(s||l.state!=="held"||l.hold.reason!=="wait"));await a;let k=await t.read(l=>l.replay().filter(oe=>oe.seq>h)),se=r?.aborted===!0||c.state==="held"&&c.hold.reason==="shutdown"||c.state==="settled"&&(c.outcome==="cancelled"||c.outcome==="superseded");return{thread_id:t.id,ended:se?"cancelled":k.some(l=>l.type==="turn/start")?"turns":"none",reason:k.some(l=>l.type==="turn/end")?t.lastOutcome():null,pending_confirmations:await t.read(l=>l.pendingConfirmations())}}finally{r?.removeEventListener("abort",i)}}var Oe=(t={})=>({maxOpenTasks:8,clock:$,...t});async function Pe(t,e,n,r,s={}){let o=t,[a]=await S(o,e,{trigger:"request",turn:null,step:null},[{kind:"span",stand_in:{role:s.role??"user",content:r},source:s.source??{plugin:"test:strategy",kind:"checkpoint",version:1,data:null},source_seqs:n.map(i=>i.seq)}]);return o.eventAt(a.seq)}var Re=t=>t===void 0?"":w(t);var Ae=t=>{let e=[...t].reverse().find(n=>n.role==="tool");return e===void 0?null:w(e)},Ie=t=>t.service.view(t.id);function Ce(t=new m,e={}){return new v(t,{summarize:e.summarize??((n,r)=>b(n,r,E())),...e.onListenerError===void 0?{}:{onListenerError:e.onListenerError},coreFolds:e.coreFolds??(e.summarize===void 0?[q]:[])})}async function Le(t){let e=t;return await Promise.all(t.summaries().map(n=>e.load(n.thread_id))),t.summaries().flatMap(n=>t.rows(n.thread_id)).sort((n,r)=>n.seq-r.seq)}async function re(t){let e=t.isOpen;e||await t.open();try{let n=await t.threads();return(await Promise.all(n.map(({threadId:s})=>t.read(s)))).flat().sort((s,o)=>s.seq-o.seq)}finally{e||await t.close()}}async function ae(t,e,n){let r=await t.acquireWriter();try{for(let s of e)await t.append({id:_(),baseHead:await t.head(),writer:r.acquisitionId,rows:[s]});await t.putSummaries(n,r.acquisitionId)}finally{await r.release()}}async function Me(t){let e=new m;await e.open();let n=t.isOpen;n||await t.open();try{await ae(e,await re(t),await t.summaries())}finally{n||await t.close()}return e}async function De(t){let e=new m;await e.open(),await ae(e,t,[]);let n=Ce(e);return await n.open(),await n.close(),e}async function je(t,e){let n=await R(t).append("tool/call",{turn:1,step:1,call_id:`call-${_()}`,name:"test_call"},{threadId:e});return{caller_thread_id:e,source_seq:n.seq,cause:{kind:"call"}}}var Ne=t=>({name:`test:prompt:${t.tag}`,inject:["prompts"],apply:e=>C(e,t)});function Fe(t=Date.parse("2026-01-05T09:00:00Z")){let e=t,n=0,r=0,s=new Map,o=(a,i)=>{for(;;){let d;for(let c of s)c[1].due<=a&&(d===void 0||c[1].due<d[1].due)&&(d=c);if(d===void 0)break;let[h,f]=d;i&&(e+=f.due-n),n=f.due,s.delete(h),f.fire()}i&&(e+=a-n),n=a};return{now:()=>e,setTimer(a,i){let d=r++;return s.set(d,{due:n+Math.max(0,a),fire:i}),()=>{s.delete(d)}},advance:a=>o(n+a,!0),jump(a){e+=a},elapse:a=>o(n+a,!1),pending:()=>[...s.values()].map(a=>a.due-n).sort((a,i)=>a-i)}}export{g as FakeLLMClient,x as FedLLM,K as TEST_START,ie as assistant,je as callOrigin,Me as copyStore,ke as createTestRoot,be as drive,Z as fakeProvider,Le as journalRows,Ae as lastToolMessage,Fe as manualClock,Pe as replaceSpan,De as replayStore,re as storeRows,ne as testAgents,te as testAgentsPlugin,ee as testBirth,Oe as testDelegations,Te as testEnvironment,ve as testPrograms,Ne as testPromptPlugin,Re as textOf,Y as tmpWorkspace,Ie as viewOf,le as withToolCalls};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ChildProcess } from 'node:child_process';
|
|
2
|
+
/** The URL of a source module, such as `sys/spawn.ts`, for a {@link lagentProcess} script to import. */
|
|
3
|
+
export declare const sourceModule: (path: string) => string;
|
|
4
|
+
/**
|
|
5
|
+
* Another lagent process, running `script` as an ES module against the TypeScript sources, for
|
|
6
|
+
* tests of what happens when a process ends — which a test cannot do to its own. Only for tests
|
|
7
|
+
* run from the sources. The caller kills it.
|
|
8
|
+
*/
|
|
9
|
+
export declare function lagentProcess(script: string): {
|
|
10
|
+
child: ChildProcess;
|
|
11
|
+
line: () => Promise<string>;
|
|
12
|
+
exited: () => Promise<number | null>;
|
|
13
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { StreamingLLMResponse } from '../llm/client.js';
|
|
2
|
+
/**
|
|
3
|
+
* Asks `stream` to settle at every turn of the microtask queue while `closing` is pending, and fails
|
|
4
|
+
* when one settles with `closing` still pending at the moment it was asked: the read is not over.
|
|
5
|
+
*/
|
|
6
|
+
export declare function settlementNeverEarly(stream: StreamingLLMResponse, closing: Promise<unknown>): Promise<void>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Context } from '@leuduan/cordis';
|
|
2
|
+
/**
|
|
3
|
+
* A temporary directory that lives as long as the test that made it, in its body or a
|
|
4
|
+
* `beforeEach`: removed once that test finishes, after any root made after it is disposed.
|
|
5
|
+
*/
|
|
6
|
+
export declare function tmpWorkspace(prefix?: string): {
|
|
7
|
+
root: string;
|
|
8
|
+
};
|
|
9
|
+
/** A temporary directory removed when `ctx` is disposed. */
|
|
10
|
+
export declare function ownedTmpDir(ctx: Context, prefix?: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Removes every temporary directory made by `tmpWorkspace` or `ownedTmpDir` that nothing cleaned
|
|
13
|
+
* up, such as the data directory of a root a test never disposed. The vitest setup file calls it
|
|
14
|
+
* after each test file, so no directory outlives the file that made it. Kept apart from the
|
|
15
|
+
* helpers so that setup file imports nothing else.
|
|
16
|
+
*/
|
|
17
|
+
export declare function removeLeftoverTmpDirs(): void;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `task`, or the signal's reason once it aborts: stops waiting, not the work, which keeps running.
|
|
3
|
+
* A signal aborted already rejects at once, even when `task` has settled: the abort is raced first.
|
|
4
|
+
* `task` is always observed, so its later failure is never an unhandled rejection.
|
|
5
|
+
*/
|
|
6
|
+
export declare function abortable<T>(task: Promise<T>, signal: AbortSignal): Promise<T>;
|
|
7
|
+
/** The longest delay a Node timer honours; a longer one fires at once. The bound of every timer setting. */
|
|
8
|
+
export declare const MAX_TIMER_MS: number;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A line diff between two texts, as unified diff text.
|
|
3
|
+
*
|
|
4
|
+
* Myers' algorithm over the lines left once the common head and tail are set aside, which is all
|
|
5
|
+
* that differs when an edit changed a few places. Its search is bounded: past
|
|
6
|
+
* {@link MAX_EDIT_DISTANCE} differing lines, or work proportional to it, the middle is given as
|
|
7
|
+
* removed and added whole, which is still a correct diff, only not the shortest.
|
|
8
|
+
*/
|
|
9
|
+
export type UnifiedDiff = {
|
|
10
|
+
/** The diff, with `---`/`+++` headers; empty when the texts have the same lines. */
|
|
11
|
+
readonly text: string;
|
|
12
|
+
readonly added: number;
|
|
13
|
+
readonly removed: number;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* The unified diff from `before` to `after`, with `context` lines around each change. Lines split
|
|
17
|
+
* on `\n`, a carriage return right before it dropped, and a last line without a newline is marked
|
|
18
|
+
* as git marks it.
|
|
19
|
+
*/
|
|
20
|
+
export declare function unifiedDiff(before: string, after: string, labels: {
|
|
21
|
+
readonly from: string;
|
|
22
|
+
readonly to: string;
|
|
23
|
+
}, context?: number): UnifiedDiff;
|
|
24
|
+
/** How many lines a text has: a last line without a newline counts. */
|
|
25
|
+
export declare function lineCount(text: string): number;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calls every listener with `event`, synchronously and in order, and never awaits one. A throw, or
|
|
3
|
+
* the rejection of anything a listener returns with a `then`, is reported, and the other listeners
|
|
4
|
+
* still run. A returned thenable is adopted, so its `then` is called once. The one rule for "a
|
|
5
|
+
* listener failed"; the caller owns the event, freezing it when the listeners must not change what
|
|
6
|
+
* the others see.
|
|
7
|
+
*/
|
|
8
|
+
export declare function dispatch<T>(listeners: Iterable<(event: T) => unknown>, event: T, report: (error: unknown) => void): void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const formatError: (error: unknown) => string;
|
|
3
|
+
/**
|
|
4
|
+
* `formatError` followed by the `cause` chain. A transport failure's own message says nothing (the
|
|
5
|
+
* OpenAI SDK's is just `Connection error.`); what actually broke is in its causes.
|
|
6
|
+
*/
|
|
7
|
+
export declare function formatErrorWithCauses(error: unknown): string;
|
|
8
|
+
/** The Node system-error code of `error`, such as `ENOENT`, when it has one. */
|
|
9
|
+
export declare const errnoCode: (error: unknown) => string | undefined;
|
|
10
|
+
/** Whether `error` is a Node system error with one of `codes`. */
|
|
11
|
+
export declare const hasErrnoCode: (error: unknown, ...codes: string[]) => boolean;
|
|
12
|
+
/** A zod failure as one line per bad field, in the form the calling model is told about. */
|
|
13
|
+
export declare function formatValidationError(error: z.ZodError): string;
|
|
14
|
+
/** What a failure says in the journal: a validation error as its fields, anything else with its causes. */
|
|
15
|
+
export declare const failureText: (error: unknown) => string;
|
|
16
|
+
/**
|
|
17
|
+
* Whether `error` is how work stops on `signal`: its reason, or one wrapping it as Node's abortable
|
|
18
|
+
* APIs do (`cause`), possibly again (`Promise.any` over them), a few levels down. A failure that only
|
|
19
|
+
* coincided with the abort is not.
|
|
20
|
+
*/
|
|
21
|
+
export declare function stoppedOn(signal: AbortSignal, error: unknown, depth?: number): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Whether `error` is the cancellation of work on `signal`, not a failure that coincided with it: its
|
|
24
|
+
* reason (see {@link stoppedOn}), or the `AbortError` a platform transport (`fetch`, a stream) throws
|
|
25
|
+
* when the signal it was handed fired. Either needs the signal to have fired. An adapter whose SDK
|
|
26
|
+
* throws an abort error of its own turns it into the signal's reason.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isCancellation(signal: AbortSignal, error: unknown): boolean;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { JsonValue, ReadonlyJsonValue } from './json.js';
|
|
2
|
+
/**
|
|
3
|
+
* A fold's state as a reader sees it: read-only all the way down. Arrays become `readonly`, `Map`
|
|
4
|
+
* and `Set` their read-only forms, and records map property by property. Fold state is plain data
|
|
5
|
+
* (primitives, arrays, records, `Map` and `Set`), so a function-typed member becomes `never`: the
|
|
6
|
+
* state cannot hand a reader a way to change it. A field typed exactly `JsonValue` becomes
|
|
7
|
+
* {@link ReadonlyJsonValue}, as in `DeepReadonly`, since mapping the recursive alias does not
|
|
8
|
+
* terminate. This is cooperative authoring, not a sandbox: reducers keep the mutable state and
|
|
9
|
+
* nothing is copied or frozen on read, so a cast, or a narrowing TypeScript widens, can still reach
|
|
10
|
+
* the mutable value. `Array.isArray` is the known one: it narrows a read-only array to `any[]`, so
|
|
11
|
+
* `push` on a JSON array payload compiles. The type does not exclude every cast-free mutation.
|
|
12
|
+
*/
|
|
13
|
+
export type ReadonlyState<S> = [S] extends [JsonValue] ? [JsonValue] extends [S] ? ReadonlyJsonValue : ReadonlyStateOf<S> : [S] extends [ReadonlyJsonValue] ? [ReadonlyJsonValue] extends [S] ? S : ReadonlyStateOf<S> : ReadonlyStateOf<S>;
|
|
14
|
+
type ReadonlyStateOf<S> = S extends (...args: never[]) => unknown ? never : S extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<ReadonlyState<K>, ReadonlyState<V>> : S extends ReadonlySet<infer T> ? ReadonlySet<ReadonlyState<T>> : S extends object ? {
|
|
15
|
+
readonly [K in keyof S]: ReadonlyState<S[K]>;
|
|
16
|
+
} : S;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Recursively drops `null` object values, so a field left unset and one set to null compare equal.
|
|
4
|
+
*
|
|
5
|
+
* This is for comparing, not for storing: the session journal writes events as they stand, because
|
|
6
|
+
* a row that read back differently from the event in memory made a live session and a resumed one
|
|
7
|
+
* disagree about their own history.
|
|
8
|
+
*/
|
|
9
|
+
export declare function stripNone<T>(value: T): T;
|
|
10
|
+
/**
|
|
11
|
+
* JSON with object keys sorted at every level, so equal values produce equal strings. Like
|
|
12
|
+
* `JSON.stringify`, it leaves out properties whose value is `undefined`, so a value compares equal
|
|
13
|
+
* to itself read back from storage.
|
|
14
|
+
*/
|
|
15
|
+
export declare function stableStringify(value: unknown): string;
|
|
16
|
+
export declare const JsonValueSchema: z.ZodJSONSchema;
|
|
17
|
+
export type JsonValue = z.infer<typeof JsonValueSchema>;
|
|
18
|
+
/** A {@link JsonValue} no reader may change: what a frozen fact holds. */
|
|
19
|
+
export type ReadonlyJsonValue = string | number | boolean | null | readonly ReadonlyJsonValue[] | {
|
|
20
|
+
readonly [key: string]: ReadonlyJsonValue;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* `T` with every property and array readonly, all the way down: the type of a frozen fact. A field
|
|
24
|
+
* typed exactly `JsonValue` or `ReadonlyJsonValue` becomes {@link ReadonlyJsonValue}, since mapping
|
|
25
|
+
* the recursive alias itself does not terminate; so a type that is already deeply readonly maps to
|
|
26
|
+
* itself.
|
|
27
|
+
*/
|
|
28
|
+
export type DeepReadonly<T> = [T] extends [ReadonlyJsonValue] ? [ReadonlyJsonValue] extends [T] ? ReadonlyJsonValue : [JsonValue] extends [T] ? ReadonlyJsonValue : DeepReadonlyObject<T> : DeepReadonlyObject<T>;
|
|
29
|
+
type DeepReadonlyObject<T> = T extends object ? {
|
|
30
|
+
readonly [K in keyof T]: DeepReadonly<T[K]>;
|
|
31
|
+
} : T;
|
|
32
|
+
/**
|
|
33
|
+
* A mutable copy of a read-only JSON value: for a payload read from a fold that a row or a public
|
|
34
|
+
* result is made of, which must not share what the fold holds.
|
|
35
|
+
*/
|
|
36
|
+
export declare function copyJson(value: ReadonlyJsonValue): JsonValue;
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* JSON Schema for a validation schema, as advertised to the model. Uses the input shape, so
|
|
4
|
+
* defaulted fields stay optional, and every advertised schema is derived from the one that
|
|
5
|
+
* actually validates — the two can never drift.
|
|
6
|
+
*/
|
|
7
|
+
export declare function toJsonSchema(schema: z.ZodType): Record<string, unknown>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Minimal logger: warnings and errors go to stderr, debug output only with LAGENT_DEBUG set. */
|
|
2
|
+
export declare const log: {
|
|
3
|
+
debug(message: string, ...args: unknown[]): void;
|
|
4
|
+
warn(message: string, ...args: unknown[]): void;
|
|
5
|
+
error(message: string, ...args: unknown[]): void;
|
|
6
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type Clock } from './timers.js';
|
|
2
|
+
/**
|
|
3
|
+
* Consecutive failures and the retry timer of work whose write failed, by key: what ask, schedules
|
|
4
|
+
* and delegations each kept beside their deadlines. Owns the counts and one timer queue of retries;
|
|
5
|
+
* the feature keeps its liveness checks, its deadlines, its reporting and what a retry does. There
|
|
6
|
+
* is no attempt identity: a retry is the feature's own check, which decides again from current state.
|
|
7
|
+
*/
|
|
8
|
+
export type RetryTracker = {
|
|
9
|
+
/**
|
|
10
|
+
* Records one more failure of `key` and arms `retry` after the backoff its count earns, replacing a
|
|
11
|
+
* retry already pending for it. The retry firing keeps the count: only `succeeded` or `clear`
|
|
12
|
+
* resets it. Inert once disposed.
|
|
13
|
+
*/
|
|
14
|
+
failed(key: string, retry: () => void): void;
|
|
15
|
+
/** `key`'s work went through: its count and pending retry are forgotten. */
|
|
16
|
+
succeeded(key: string): void;
|
|
17
|
+
/** `key`'s work is no longer wanted: its count and pending retry are forgotten. */
|
|
18
|
+
clear(key: string): void;
|
|
19
|
+
/** Whether `key` has failed since it last succeeded or was cleared, its retry pending or in flight. */
|
|
20
|
+
pending(key: string): boolean;
|
|
21
|
+
/** Cancels every retry and forgets every count; later calls do nothing. Whoever creates a tracker disposes it. */
|
|
22
|
+
dispose(): void;
|
|
23
|
+
};
|
|
24
|
+
/** A {@link RetryTracker} whose retries are timed on `clock`; a retry that throws is handed to `report`. */
|
|
25
|
+
export declare function retryTracker(clock: Clock, report: (error: unknown) => void): RetryTracker;
|