@leuduan/lagent 0.0.0-stage → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +16 -0
- package/README.md +144 -2
- package/dist/chunks/2O7ZGEIT.js +1 -0
- package/dist/chunks/2OSESBIL.js +1 -0
- package/dist/chunks/34KW6VNQ.js +1 -0
- package/dist/chunks/37YOGDGY.js +1 -0
- package/dist/chunks/3LQHQRIU.js +6 -0
- package/dist/chunks/3QCW4WDJ.js +1 -0
- package/dist/chunks/4XVRUSCQ.js +1 -0
- package/dist/chunks/6ECI2GGV.js +1 -0
- package/dist/chunks/74HKUGRR.js +1 -0
- package/dist/chunks/ADHERZLW.js +2 -0
- package/dist/chunks/AP6Q4EPT.js +36 -0
- package/dist/chunks/BM3S37EZ.js +1 -0
- package/dist/chunks/C5LYCXJG.js +1 -0
- package/dist/chunks/CDQG7RKA.js +1 -0
- package/dist/chunks/D7E6EWIE.js +3 -0
- package/dist/chunks/DDANMY45.js +3 -0
- package/dist/chunks/DRYAN665.js +1 -0
- package/dist/chunks/DXFXAYDN.js +17 -0
- package/dist/chunks/EGZI4XQX.js +24 -0
- package/dist/chunks/ENWFSU27.js +41 -0
- package/dist/chunks/G6RXC3AL.js +1 -0
- package/dist/chunks/G74AGRAJ.js +15 -0
- package/dist/chunks/GQGNVSKB.js +1 -0
- package/dist/chunks/IJ2WNMD5.js +7 -0
- package/dist/chunks/J5S4URAW.js +1 -0
- package/dist/chunks/JPZFKSWT.js +1 -0
- package/dist/chunks/KESCTXGO.js +5 -0
- package/dist/chunks/L3N4FIEN.js +1 -0
- package/dist/chunks/NAOUTU7A.js +4 -0
- package/dist/chunks/NDIM7MEW.js +1 -0
- package/dist/chunks/O4PPOM5Z.js +2 -0
- package/dist/chunks/OVZFGILJ.js +1 -0
- package/dist/chunks/P5ZHHOOM.js +6 -0
- package/dist/chunks/PUSUPTAT.js +1 -0
- package/dist/chunks/QMMLQJBS.js +1 -0
- package/dist/chunks/RK3VP2Q4.js +3 -0
- package/dist/chunks/SGGMBSBA.js +1 -0
- package/dist/chunks/SL2YLB2F.js +1 -0
- package/dist/chunks/TOOIB6J2.js +1 -0
- package/dist/chunks/TYTQRLTX.js +1 -0
- package/dist/chunks/UC3FVVJ2.js +5 -0
- package/dist/chunks/UCTEU62F.js +1 -0
- package/dist/chunks/UD3VJER6.js +1 -0
- package/dist/chunks/UKXMCHHT.js +1 -0
- package/dist/chunks/WUUKTSRT.js +7 -0
- package/dist/chunks/X65X4KP5.js +7 -0
- package/dist/chunks/YIR5MYGU.js +1 -0
- package/dist/chunks/YLNJXQ3Z.js +1 -0
- package/dist/context.d.ts +101 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +77 -0
- package/dist/journal/catalog.d.ts +112 -0
- package/dist/journal/forkChain.d.ts +16 -0
- package/dist/journal/index.d.ts +15 -0
- package/dist/journal/journal.d.ts +475 -0
- package/dist/journal/projection.d.ts +87 -0
- package/dist/journal/store.d.ts +181 -0
- package/dist/kit/claim.d.ts +13 -0
- package/dist/kit/drain.d.ts +10 -0
- package/dist/kit/extension.d.ts +180 -0
- package/dist/kit/grants.d.ts +9 -0
- package/dist/kit/modes.d.ts +65 -0
- package/dist/kit/retries.d.ts +25 -0
- package/dist/kit/scope.d.ts +32 -0
- package/dist/kit/service.d.ts +7 -0
- package/dist/kit/strategy.d.ts +10 -0
- package/dist/kit/timers.d.ts +43 -0
- package/dist/kit/tool.d.ts +72 -0
- package/dist/llm/client.d.ts +135 -0
- package/dist/llm/content.d.ts +52 -0
- package/dist/llm/door.d.ts +21 -0
- package/dist/llm/door.js +1 -0
- package/dist/llm/failure.d.ts +82 -0
- package/dist/llm/index.d.ts +16 -0
- package/dist/llm/primitives.d.ts +286 -0
- package/dist/llm/prompt.d.ts +21 -0
- package/dist/llm/provider.d.ts +63 -0
- package/dist/llm/readLedger.d.ts +24 -0
- package/dist/llm/request.d.ts +58 -0
- package/dist/loop/agent.d.ts +134 -0
- package/dist/loop/auxiliary.d.ts +54 -0
- package/dist/loop/chain.d.ts +46 -0
- package/dist/loop/chunks.d.ts +27 -0
- package/dist/loop/continuation.d.ts +166 -0
- package/dist/loop/decide.d.ts +64 -0
- package/dist/loop/errors.d.ts +162 -0
- package/dist/loop/forks.d.ts +61 -0
- package/dist/loop/holds.d.ts +104 -0
- package/dist/loop/hooks.d.ts +241 -0
- package/dist/loop/inbox.d.ts +188 -0
- package/dist/loop/index.d.ts +37 -0
- package/dist/loop/limits.d.ts +14 -0
- package/dist/loop/opening.d.ts +42 -0
- package/dist/loop/prepare.d.ts +30 -0
- package/dist/loop/projections.d.ts +307 -0
- package/dist/loop/replace.d.ts +33 -0
- package/dist/loop/requests.d.ts +129 -0
- package/dist/loop/route.d.ts +53 -0
- package/dist/loop/runtime.d.ts +85 -0
- package/dist/loop/state.d.ts +70 -0
- package/dist/loop/strategy.d.ts +71 -0
- package/dist/loop/summary.d.ts +3 -0
- package/dist/loop/surface.d.ts +153 -0
- package/dist/loop/threadState.d.ts +72 -0
- package/dist/loop/tool.d.ts +101 -0
- package/dist/loop/toolCalls.d.ts +42 -0
- package/dist/loop/wake.d.ts +32 -0
- package/dist/models/config/agent.d.ts +18 -0
- package/dist/models/config/prompt.d.ts +18 -0
- package/dist/models/door.d.ts +12 -0
- package/dist/models/door.js +1 -0
- package/dist/models/index.d.ts +7 -0
- package/dist/models/jsonSchema.d.ts +7 -0
- package/dist/models/wire/journal.d.ts +2772 -0
- package/dist/models/wire/primitives.d.ts +65 -0
- package/dist/plugin.d.ts +53 -0
- package/dist/plugin.js +1 -0
- package/dist/plugins/agentsMd.d.ts +76 -0
- package/dist/plugins/agentsMd.js +1 -0
- package/dist/plugins/ask/askQuestion.d.ts +9 -0
- package/dist/plugins/ask/index.d.ts +26 -0
- package/dist/plugins/ask/index.js +1 -0
- package/dist/plugins/ask/service.d.ts +125 -0
- package/dist/plugins/commands/background.d.ts +8 -0
- package/dist/plugins/commands/foreground.d.ts +4 -0
- package/dist/plugins/commands/index.d.ts +40 -0
- package/dist/plugins/commands/index.js +1 -0
- package/dist/plugins/commands/output.d.ts +115 -0
- package/dist/plugins/commands/record.d.ts +549 -0
- package/dist/plugins/commands/service.d.ts +314 -0
- package/dist/plugins/commands/shell.d.ts +25 -0
- package/dist/plugins/compaction/checkpoint.d.ts +91 -0
- package/dist/plugins/compaction/config.d.ts +133 -0
- package/dist/plugins/compaction/estimate.d.ts +29 -0
- package/dist/plugins/compaction/index.d.ts +2 -0
- package/dist/plugins/compaction/index.js +7 -0
- package/dist/plugins/compaction/log.d.ts +61 -0
- package/dist/plugins/compaction/planner.d.ts +207 -0
- package/dist/plugins/compaction/preset.d.ts +86 -0
- package/dist/plugins/compaction/prune.d.ts +9 -0
- package/dist/plugins/compaction/records.d.ts +227 -0
- package/dist/plugins/compaction/segments.d.ts +23 -0
- package/dist/plugins/compaction/shared.d.ts +14 -0
- package/dist/plugins/compaction/summarize.d.ts +13 -0
- package/dist/plugins/dateAndBranch.d.ts +47 -0
- package/dist/plugins/dateAndBranch.js +1 -0
- package/dist/plugins/delegations/answers.d.ts +39 -0
- package/dist/plugins/delegations/assignmentKey.d.ts +22 -0
- package/dist/plugins/delegations/cleanup.d.ts +161 -0
- package/dist/plugins/delegations/constraint.d.ts +76 -0
- package/dist/plugins/delegations/index.d.ts +39 -0
- package/dist/plugins/delegations/index.js +1 -0
- package/dist/plugins/delegations/notices.d.ts +261 -0
- package/dist/plugins/delegations/obligations.d.ts +210 -0
- package/dist/plugins/delegations/record.d.ts +632 -0
- package/dist/plugins/delegations/request.d.ts +381 -0
- package/dist/plugins/delegations/role.d.ts +30 -0
- package/dist/plugins/delegations/service.d.ts +562 -0
- package/dist/plugins/delegations/standing.d.ts +19 -0
- package/dist/plugins/delegations/stopCheck.d.ts +21 -0
- package/dist/plugins/delegations/testing.d.ts +16 -0
- package/dist/plugins/delegations/tools.d.ts +71 -0
- package/dist/plugins/delegations/waitBook.d.ts +116 -0
- package/dist/plugins/delegations/waits.d.ts +118 -0
- package/dist/plugins/diagnostics/digest.d.ts +14 -0
- package/dist/plugins/diagnostics/index.d.ts +68 -0
- package/dist/plugins/diagnostics/index.js +1 -0
- package/dist/plugins/historyRecall/history.d.ts +9 -0
- package/dist/plugins/historyRecall/index.d.ts +31 -0
- package/dist/plugins/historyRecall/index.js +1 -0
- package/dist/plugins/historyRecall/render.d.ts +34 -0
- package/dist/plugins/historyRecall/tools.d.ts +4 -0
- package/dist/plugins/mcp/catalog.d.ts +36 -0
- package/dist/plugins/mcp/config.d.ts +63 -0
- package/dist/plugins/mcp/connection.d.ts +53 -0
- package/dist/plugins/mcp/errors.d.ts +32 -0
- package/dist/plugins/mcp/index.d.ts +33 -0
- package/dist/plugins/mcp/index.js +5 -0
- package/dist/plugins/mcp/mount.d.ts +98 -0
- package/dist/plugins/mcp/names.d.ts +25 -0
- package/dist/plugins/mcp/render.d.ts +29 -0
- package/dist/plugins/mcp/slots.d.ts +15 -0
- package/dist/plugins/mcp/stdio.d.ts +49 -0
- package/dist/plugins/mcp/tool.d.ts +41 -0
- package/dist/plugins/providers/anthropic.d.ts +175 -0
- package/dist/plugins/providers/anthropicMessages.d.ts +65 -0
- package/dist/plugins/providers/codex.d.ts +60 -0
- package/dist/plugins/providers/codexAuth.d.ts +116 -0
- package/dist/plugins/providers/deepseek.d.ts +55 -0
- package/dist/plugins/providers/door.d.ts +61 -0
- package/dist/plugins/providers/door.js +1 -0
- package/dist/plugins/providers/failure.d.ts +23 -0
- package/dist/plugins/providers/gateway.d.ts +23 -0
- package/dist/plugins/providers/index.d.ts +6 -0
- package/dist/plugins/providers/openaiChat.d.ts +62 -0
- package/dist/plugins/providers/openaiResponses.d.ts +100 -0
- package/dist/plugins/providers/opencodeCopilot.d.ts +23 -0
- package/dist/plugins/providers/opencodeGo.d.ts +98 -0
- package/dist/plugins/providers/shared.d.ts +104 -0
- package/dist/plugins/providers/stream.d.ts +154 -0
- package/dist/plugins/routeContext.d.ts +22 -0
- package/dist/plugins/routeContext.js +1 -0
- package/dist/plugins/schedules/index.d.ts +21 -0
- package/dist/plugins/schedules/index.js +5 -0
- package/dist/plugins/schedules/record.d.ts +396 -0
- package/dist/plugins/schedules/service.d.ts +120 -0
- package/dist/plugins/schedules/time.d.ts +26 -0
- package/dist/plugins/schedules/tools.d.ts +6 -0
- package/dist/plugins/skills/discovery.d.ts +54 -0
- package/dist/plugins/skills/index.d.ts +31 -0
- package/dist/plugins/skills/index.js +1 -0
- package/dist/plugins/skills/tool.d.ts +11 -0
- package/dist/plugins/store/durableObject.d.ts +23 -0
- package/dist/plugins/store/durableObject.js +1 -0
- package/dist/plugins/store/durableObjectConnection.d.ts +27 -0
- package/dist/plugins/store/memory.d.ts +29 -0
- package/dist/plugins/store/sql.d.ts +59 -0
- package/dist/plugins/store/sqlite.d.ts +31 -0
- package/dist/plugins/store/sqlite.js +1 -0
- package/dist/plugins/subAgents/availableRoutes.d.ts +53 -0
- package/dist/plugins/subAgents/fork.d.ts +32 -0
- package/dist/plugins/subAgents/index.d.ts +67 -0
- package/dist/plugins/subAgents/index.js +1 -0
- package/dist/plugins/subAgents/tool.d.ts +38 -0
- package/dist/plugins/toolPolicy/index.d.ts +61 -0
- package/dist/plugins/toolPolicy/index.js +1 -0
- package/dist/plugins/tools/editFiles.d.ts +128 -0
- package/dist/plugins/tools/fsRead.d.ts +17 -0
- package/dist/plugins/tools/html.d.ts +23 -0
- package/dist/plugins/tools/index.d.ts +59 -0
- package/dist/plugins/tools/index.js +1 -0
- package/dist/plugins/tools/network.d.ts +23 -0
- package/dist/plugins/tools/ripgrep.d.ts +20 -0
- package/dist/plugins/tools/textEdit.d.ts +67 -0
- package/dist/plugins/tools/web.d.ts +32 -0
- package/dist/plugins/truncateToolOutput.d.ts +26 -0
- package/dist/plugins/truncateToolOutput.js +1 -0
- package/dist/plugins/usage/index.d.ts +24 -0
- package/dist/plugins/usage/index.js +1 -0
- package/dist/plugins/usage/tracker.d.ts +34 -0
- package/dist/plugins/verify/facts.d.ts +356 -0
- package/dist/plugins/verify/index.d.ts +75 -0
- package/dist/plugins/verify/index.js +1 -0
- package/dist/plugins/verify/service.d.ts +90 -0
- package/dist/plugins/workflows/assignment.d.ts +16 -0
- package/dist/plugins/workflows/bindings.d.ts +95 -0
- package/dist/plugins/workflows/cleanup.d.ts +38 -0
- package/dist/plugins/workflows/definition.d.ts +184 -0
- package/dist/plugins/workflows/fold.d.ts +373 -0
- package/dist/plugins/workflows/index.d.ts +28 -0
- package/dist/plugins/workflows/index.js +6 -0
- package/dist/plugins/workflows/observations.d.ts +81 -0
- package/dist/plugins/workflows/participants.d.ts +143 -0
- package/dist/plugins/workflows/policy.d.ts +112 -0
- package/dist/plugins/workflows/providers.d.ts +146 -0
- package/dist/plugins/workflows/record.d.ts +2863 -0
- package/dist/plugins/workflows/routing.d.ts +116 -0
- package/dist/plugins/workflows/schema.d.ts +26 -0
- package/dist/plugins/workflows/service.d.ts +477 -0
- package/dist/plugins/workflows/submit.d.ts +8 -0
- package/dist/plugins/workflows/view.d.ts +103 -0
- package/dist/plugins/workflows/work.d.ts +21 -0
- package/dist/plugins/workspaceContext.d.ts +38 -0
- package/dist/plugins/workspaceContext.js +1 -0
- package/dist/presets/agents.d.ts +7 -0
- package/dist/presets/base.d.ts +10 -0
- package/dist/presets/codex.d.ts +60 -0
- package/dist/presets/index.d.ts +4 -0
- package/dist/presets/prompts.d.ts +56 -0
- package/dist/sandbox/absent.d.ts +32 -0
- package/dist/sandbox/client.d.ts +39 -0
- package/dist/sandbox/files.d.ts +28 -0
- package/dist/sandbox/index.d.ts +49 -0
- package/dist/sandbox/index.js +4 -0
- package/dist/sandbox/mode.d.ts +57 -0
- package/dist/sandbox/policy.d.ts +86 -0
- package/dist/sandbox/protocol.d.ts +107 -0
- package/dist/sandbox/service.d.ts +143 -0
- package/dist/sandbox/worker.d.ts +12 -0
- package/dist/sandbox/worker.js +1 -0
- package/dist/services/admission.d.ts +174 -0
- package/dist/services/agents.d.ts +37 -0
- package/dist/services/birth.d.ts +220 -0
- package/dist/services/contributions.d.ts +73 -0
- package/dist/services/core.d.ts +34 -0
- package/dist/services/journal.d.ts +26 -0
- package/dist/services/launches.d.ts +104 -0
- package/dist/services/llm.d.ts +80 -0
- package/dist/services/owner.d.ts +367 -0
- package/dist/services/preset.d.ts +154 -0
- package/dist/services/presets.d.ts +139 -0
- package/dist/services/prompts.d.ts +67 -0
- package/dist/services/runEvents.d.ts +79 -0
- package/dist/services/thread.d.ts +267 -0
- package/dist/services/threadActivation.d.ts +100 -0
- package/dist/services/threadDirs.d.ts +38 -0
- package/dist/services/threadView.d.ts +92 -0
- package/dist/services/threads.d.ts +449 -0
- package/dist/services/tools.d.ts +41 -0
- package/dist/sys/environment.d.ts +47 -0
- package/dist/sys/git.d.ts +60 -0
- package/dist/sys/paths.d.ts +56 -0
- package/dist/sys/spawn.d.ts +176 -0
- package/dist/testing/clock.d.ts +17 -0
- package/dist/testing/fakeLlm.d.ts +74 -0
- package/dist/testing/fedLlm.d.ts +32 -0
- package/dist/testing/helpers.d.ts +344 -0
- package/dist/testing/index.d.ts +13 -0
- package/dist/testing/index.js +1 -0
- package/dist/testing/processes.d.ts +13 -0
- package/dist/testing/sandbox.d.ts +71 -0
- package/dist/testing/settlement.d.ts +6 -0
- package/dist/testing/tmpDirs.d.ts +17 -0
- package/dist/util/async.d.ts +8 -0
- package/dist/util/diff.d.ts +25 -0
- package/dist/util/dispatch.d.ts +8 -0
- package/dist/util/errors.d.ts +28 -0
- package/dist/util/foldState.d.ts +17 -0
- package/dist/util/freeze.d.ts +2 -0
- package/dist/util/ids.d.ts +2 -0
- package/dist/util/json.d.ts +37 -0
- package/dist/util/log.d.ts +6 -0
- package/dist/util/text.d.ts +21 -0
- package/dist/util/version.d.ts +2 -0
- package/package.json +175 -3
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Context, Service, type ScopeKey } from '@leuduan/cordis';
|
|
2
|
+
import type { PromptBlock } from '../llm/index.js';
|
|
3
|
+
import type { ToolEntry } from '../loop/index.js';
|
|
4
|
+
import type { AgentDefinition, ThreadSummary } from '../models/index.js';
|
|
5
|
+
import { type AgentSelector } from '../kit/scope.js';
|
|
6
|
+
export type PromptSlot = 'base' | 'instruction' | 'context';
|
|
7
|
+
/**
|
|
8
|
+
* What a contribution is rendered against: the agent, where the thread works, and the tools it
|
|
9
|
+
* reaches.
|
|
10
|
+
*
|
|
11
|
+
* Deliberately not the thread's id or metadata. A recorded prompt is the head of every request a
|
|
12
|
+
* provider caches, so it must not depend on which thread it is: threads of one agent in one
|
|
13
|
+
* workspace then render the same prompt. Anything thread-specific belongs in the conversation, as
|
|
14
|
+
* a step contribution (see `workspaceContext`).
|
|
15
|
+
*/
|
|
16
|
+
export type PromptRenderInput = {
|
|
17
|
+
readonly agent: AgentDefinition;
|
|
18
|
+
readonly thread: {
|
|
19
|
+
readonly environment: ThreadSummary['environment'];
|
|
20
|
+
};
|
|
21
|
+
/** What the agent may call from the rendering scope, as the registries stand at render time. */
|
|
22
|
+
readonly tools: readonly ToolEntry[];
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* One section a plugin adds to an agent's prompt.
|
|
26
|
+
*
|
|
27
|
+
* `render` is synchronous and pure in its inputs: anything needing IO reads it when the plugin
|
|
28
|
+
* mounts, and returns the cached value here. Returning `null` contributes nothing — or, for a tag
|
|
29
|
+
* that already exists, removes it.
|
|
30
|
+
*/
|
|
31
|
+
export type PromptContribution = {
|
|
32
|
+
readonly tag: string;
|
|
33
|
+
readonly slot: PromptSlot;
|
|
34
|
+
/** Which agents get it; see `AgentSelector`. */
|
|
35
|
+
readonly agents: AgentSelector;
|
|
36
|
+
/** Render order within the slot; ties break on `tag`. Default 0. */
|
|
37
|
+
readonly order?: number;
|
|
38
|
+
render(input: PromptRenderInput): string | null;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Prompt contributions, live like the other registries and layered by Cordis scope like tools:
|
|
42
|
+
* an untagged contribution is global, a contribution registered through a thread's context belongs
|
|
43
|
+
* to that thread's layer. The prompt itself is rendered once, when a thread first runs and every
|
|
44
|
+
* activation plugin is ready, and recorded on it; this service only says what that render
|
|
45
|
+
* would be right now.
|
|
46
|
+
*/
|
|
47
|
+
export declare class PromptsService extends Service {
|
|
48
|
+
static inject: string[];
|
|
49
|
+
private readonly layers;
|
|
50
|
+
constructor(ctx: Context);
|
|
51
|
+
/** Adds a contribution to one layer; returns the function that removes it. */
|
|
52
|
+
contribute(scope: ScopeKey | undefined, contribution: PromptContribution): () => void;
|
|
53
|
+
/**
|
|
54
|
+
* The prompt `agentName` would send on a thread rendered now from `scope`: the agent's base
|
|
55
|
+
* prompt, then the global layer's contributions, then each closer layer outward-in, each in
|
|
56
|
+
* declared order, never mount order. A contribution whose tag is already present replaces that
|
|
57
|
+
* section in place — so the closest layer wins a tag — and `null` removes it.
|
|
58
|
+
*
|
|
59
|
+
* The base prompt is seeded at the layer that defines the agent, so only that layer and closer
|
|
60
|
+
* ones can replace or remove it with a `base` contribution: for a global agent every layer can,
|
|
61
|
+
* while a scoped agent's own base prompt outranks every layer farther out. Instruction and context
|
|
62
|
+
* contributions apply from every layer. Throws for an agent unknown from `scope`.
|
|
63
|
+
*/
|
|
64
|
+
render(scope: ScopeKey | undefined, agentName: string, thread: PromptRenderInput['thread']): PromptBlock[];
|
|
65
|
+
}
|
|
66
|
+
/** Registers a contribution in the calling plugin's layer for the lifetime of its fiber. */
|
|
67
|
+
export declare const contributePrompt: (ctx: Context, contribution: PromptContribution) => (() => void | Promise<void>);
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { RunOutcomeKind, RunSettledReason } from '../models/index.js';
|
|
2
|
+
import type { DurableRunState, Hold, HoldBasis } from '../loop/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Where one run request stands, as its waiters see it: waiting to be admitted (`requested`), with
|
|
5
|
+
* an execution serving it (`running`, finalization included), held with the request still pending,
|
|
6
|
+
* or settled. A held run carries its structured `hold` and the `basis` it was read on, an immutable
|
|
7
|
+
* observation at publication, not a snapshot of the thread. `{ reason: 'shutdown' }` is what a
|
|
8
|
+
* waiter is told when the application closes under it.
|
|
9
|
+
*/
|
|
10
|
+
export type RunState = {
|
|
11
|
+
readonly state: 'requested';
|
|
12
|
+
} | {
|
|
13
|
+
readonly state: 'running';
|
|
14
|
+
} | {
|
|
15
|
+
readonly state: 'held';
|
|
16
|
+
readonly hold: Hold;
|
|
17
|
+
readonly basis: HoldBasis;
|
|
18
|
+
} | {
|
|
19
|
+
readonly state: 'settled';
|
|
20
|
+
readonly outcome: RunOutcomeKind;
|
|
21
|
+
readonly reason: RunSettledReason;
|
|
22
|
+
readonly errorText: string | null;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* One change of a run's state, published as it happens: `requested` once its cause is durable,
|
|
26
|
+
* `running` at admission, and `held` or `settled` only after the execution's finalization and its
|
|
27
|
+
* release of the thread, so nothing that reads it can still find the execution running.
|
|
28
|
+
*/
|
|
29
|
+
export type RunEvent = {
|
|
30
|
+
readonly threadId: string;
|
|
31
|
+
readonly runId: string;
|
|
32
|
+
} & RunState;
|
|
33
|
+
/**
|
|
34
|
+
* The read rule, the same as the events': a run an execution serves is `running` until that
|
|
35
|
+
* execution releases the thread, even when its settlement row is already durable; a settled run
|
|
36
|
+
* with no live execution is its settlement; a pending one is what the owner's current decision for
|
|
37
|
+
* it says, `held` with its hold or `requested`, since holds have no rows to read. `null` for a
|
|
38
|
+
* run the reader does not know: one the thread never had, or, on a thread out of memory, one older
|
|
39
|
+
* than its pending run and its latest settlement, which its catalog entry does not keep.
|
|
40
|
+
*/
|
|
41
|
+
export declare function readRunState(facts: {
|
|
42
|
+
readonly durable: DurableRunState;
|
|
43
|
+
/** Whether an execution serving this run holds the thread now. */
|
|
44
|
+
readonly executing: boolean;
|
|
45
|
+
/** The hold the owner currently reads on the thread's pending request, `null` when it has none to say. */
|
|
46
|
+
readonly held: {
|
|
47
|
+
readonly hold: Hold;
|
|
48
|
+
readonly basis: HoldBasis;
|
|
49
|
+
} | null;
|
|
50
|
+
}): RunState | null;
|
|
51
|
+
/** Where a waiter reads runs from: the event stream, and the read that follows the same rule. */
|
|
52
|
+
export type RunSource = {
|
|
53
|
+
onRunEvent(listener: (event: RunEvent) => void): () => void;
|
|
54
|
+
runState(threadId: string, runId: string): RunState | null;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* A run a waiter named is unknown to the catalog: the thread never had it, or the thread is out of
|
|
58
|
+
* memory and the run is older than its pending run and its latest settlement. A read or a hold
|
|
59
|
+
* loads the thread, which knows its every run.
|
|
60
|
+
*/
|
|
61
|
+
export declare class UnknownRunError extends Error {
|
|
62
|
+
readonly threadId: string;
|
|
63
|
+
readonly runId: string;
|
|
64
|
+
constructor(threadId: string, runId: string);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Waits until run `runId` on `threadId` reaches a state `until` accepts, and resolves with it, where
|
|
68
|
+
* `source` is `ctx.threads`. The wait is for that run: not for the input that asked for it to be
|
|
69
|
+
* answered, nor for the thread to go quiet, since a cause that lands while an execution finishes is
|
|
70
|
+
* carried to a successor request. `queued.runId` of a `send` names the run to wait for. It
|
|
71
|
+
* subscribes first and reads the state after, so a change that happened before the call is read,
|
|
72
|
+
* not missed; on each event of the run it reads again rather than trust the event, which may be
|
|
73
|
+
* stale by the time it is delivered. Rejects with the signal's reason when aborted (the run goes on),
|
|
74
|
+
* with {@link UnknownRunError} for a run unknown to the catalog, and with whatever the read or
|
|
75
|
+
* `until` threw; unsubscribes however it ends.
|
|
76
|
+
*/
|
|
77
|
+
export declare function waitForRun(source: RunSource, threadId: string, runId: string, until: (state: RunState) => boolean, signal?: AbortSignal): Promise<RunState>;
|
|
78
|
+
/** What a caller waiting for a run's work to stop waits for: the run held or settled, as `waitForRun`'s `until`. */
|
|
79
|
+
export declare const heldOrSettled: (state: RunState) => boolean;
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import type { Context } from '@leuduan/cordis';
|
|
2
|
+
import type { AppendEntry, Journal } from '../journal/index.js';
|
|
3
|
+
import type { PromptBlock } from '../llm/index.js';
|
|
4
|
+
import type { CompactOptions, RouteStatement, RowRef, SendOptions, SendOutcome, StreamedChunk, SurfacePrepareOutcome, WithdrawOptions, WithdrawOutcome } from '../loop/index.js';
|
|
5
|
+
import type { CancelIntent, JournalEvent, ThreadInput, ThreadOrigin, ThreadSummary, TurnEndReason } from '../models/index.js';
|
|
6
|
+
import type { DeepReadonly } from '../util/json.js';
|
|
7
|
+
import type { AdmissionView } from './admission.js';
|
|
8
|
+
import type { ForkOptions } from './birth.js';
|
|
9
|
+
import type { ConfigurationChange, ConfigurationResult, ThreadsService } from './threads.js';
|
|
10
|
+
import type { ThreadView } from './threadView.js';
|
|
11
|
+
/** One answer to a parked confirmation. */
|
|
12
|
+
export type ConfirmationAnswer = {
|
|
13
|
+
request_id: string;
|
|
14
|
+
approved: boolean;
|
|
15
|
+
rejection_message?: string | null;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* How `cancel()` cancels: a person's stop (`user`), which holds the thread until a releasing cause,
|
|
19
|
+
* or a feature's `cleanup`, which holds nothing; `rows`, extension rows built inside the cancel's
|
|
20
|
+
* write for the same group, or a refusal of it by throwing; and `until`, the milestone the call
|
|
21
|
+
* settles at: `released` (the default) once the write has landed and what the cancel captured has
|
|
22
|
+
* released the thread, `recorded` once the write alone has landed.
|
|
23
|
+
*/
|
|
24
|
+
export type CancelOptions = {
|
|
25
|
+
readonly intent: CancelIntent;
|
|
26
|
+
readonly rows?: (threadId: string) => readonly AppendEntry<'ext'>[];
|
|
27
|
+
readonly until?: 'recorded' | 'released';
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* One conversation in the journal. Threads are independent: their own transcript, their own
|
|
31
|
+
* exclusive admission while the owner runs them, their own confirmations. Two may run at once. A
|
|
32
|
+
* thread runs for a recorded request: `send` or `answer` with `wake`, or `resume`.
|
|
33
|
+
*
|
|
34
|
+
* Durable accessors read the journal; execution status and ctx belong to the current activation.
|
|
35
|
+
* The handle never owns plugin lifetime and survives replacement of that activation.
|
|
36
|
+
*/
|
|
37
|
+
export declare class Thread {
|
|
38
|
+
private readonly inbox;
|
|
39
|
+
private readonly service;
|
|
40
|
+
private readonly admission;
|
|
41
|
+
readonly id: string;
|
|
42
|
+
private readonly journal;
|
|
43
|
+
constructor(service: ThreadsService,
|
|
44
|
+
/** The admission owner's reads and cancel, given by the service that owns it. */
|
|
45
|
+
admission: AdmissionView, id: string,
|
|
46
|
+
/** The journal with core's writes, which only the thread owner hands out. */
|
|
47
|
+
journal: Journal);
|
|
48
|
+
/**
|
|
49
|
+
* Reads what this thread's folds say through `reader`, which is synchronous: the thread is loaded
|
|
50
|
+
* and held for the call (a `keep` retention), so nothing drops it meanwhile: how a caller that
|
|
51
|
+
* holds nothing reads a thread's conversation, where one that holds it already reads
|
|
52
|
+
* `ctx.threads.view`. The catalog reads (`summary`, `status`, `lastOutcome`) need neither.
|
|
53
|
+
*/
|
|
54
|
+
read<T>(reader: (view: ThreadView) => T): Promise<T>;
|
|
55
|
+
/** Lazily activates this thread. Its plugins are fixed once ready: mount them from activate listeners or presets. */
|
|
56
|
+
get ctx(): Context;
|
|
57
|
+
/**
|
|
58
|
+
* The current activation's signal, the one its `lagent/thread/activate` listeners receive: it
|
|
59
|
+
* aborts when the activation is released or stopped, not when one turn is cancelled. Activates
|
|
60
|
+
* the thread, as `ctx` does, and like `ctx` throws `ThreadBusyError` while the activation is being
|
|
61
|
+
* released, since a getter cannot wait; a read after the release starts a new activation; and once
|
|
62
|
+
* `ctx.threads` has shut down it throws.
|
|
63
|
+
*/
|
|
64
|
+
get signal(): AbortSignal;
|
|
65
|
+
/**
|
|
66
|
+
* Activates this thread if it is not live, after any release in progress, and resolves once its
|
|
67
|
+
* plugins are ready: the barrier a run waits at, so a plugin that cannot mount, such as a recorded
|
|
68
|
+
* preset installation that no longer restores, rejects here with its error and nothing runs. A
|
|
69
|
+
* host that changes a thread's installations and wants the failure now awaits this.
|
|
70
|
+
*/
|
|
71
|
+
whenReady(): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Changes this thread's preset installations as one operation: validates the whole change,
|
|
74
|
+
* releases the live activation, records every installation applied or removed in one write, and
|
|
75
|
+
* restores a thread that was live from the record, rebuilding its recorded prompt when asked
|
|
76
|
+
* (which restores a thread at rest too); a thread at rest otherwise stays at rest, and its next run
|
|
77
|
+
* or `whenReady()` restores it. Removals go first, then
|
|
78
|
+
* applications, which are restored in that order. A given `installationId` makes a retry a no-op,
|
|
79
|
+
* and a removed id is never accepted again; removing an id not installed is no change, and a
|
|
80
|
+
* defining installation is never removed. Refused busy while an operation holds the thread, and
|
|
81
|
+
* refused with `ThreadActivatingError` while its activation is still getting ready, with
|
|
82
|
+
* `ThreadUnsettledError` for an unfinished confirmation (open, or approved and not yet run), and
|
|
83
|
+
* once lagent is closing. The record is the boundary: a cancel before it records nothing, a cancel
|
|
84
|
+
* after it ends only the restoration, and a setup that fails after it rejects with
|
|
85
|
+
* `RestoreFailedError`, the change standing, so a change that removes a broken installation
|
|
86
|
+
* always goes through.
|
|
87
|
+
*/
|
|
88
|
+
configure(change: ConfigurationChange): Promise<ConfigurationResult>;
|
|
89
|
+
/**
|
|
90
|
+
* Takes this thread out of the working set: releases an idle activation and drops the rows and
|
|
91
|
+
* folds, under one admission; the catalog entry stays. Refused busy while an operation holds it.
|
|
92
|
+
*/
|
|
93
|
+
close(): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* This thread's catalog entry: its identity and lineage, how its last turn ended, whether it has
|
|
96
|
+
* work, what it waits on, and what plugins and hosts contributed — everything a listing shows,
|
|
97
|
+
* read without a row of the thread in memory, exact as of the thread's last group.
|
|
98
|
+
*/
|
|
99
|
+
get summary(): ThreadSummary;
|
|
100
|
+
get agentName(): string;
|
|
101
|
+
/** App-owned annotations the engine never reads. */
|
|
102
|
+
get metadata(): ThreadSummary['metadata'];
|
|
103
|
+
/** Where this thread came from: its caller, the caller's row and the cause; `null` for a root thread. */
|
|
104
|
+
get origin(): ThreadOrigin | null;
|
|
105
|
+
/**
|
|
106
|
+
* How many delegation hops separate this thread from its origin root: one for each thread
|
|
107
|
+
* of its caller chain that has a caller, a caller the catalog does not hold included.
|
|
108
|
+
*/
|
|
109
|
+
get depth(): number;
|
|
110
|
+
/**
|
|
111
|
+
* The thread at the top of this one's origin tree, the caller chain's thread with no caller:
|
|
112
|
+
* itself for a thread created without an `origin`. `null` when the chain does not reach one, at a
|
|
113
|
+
* caller the catalog does not hold or a cycle, which only a journal that broke its rules has; a
|
|
114
|
+
* reader that decides by the root then decides nothing, rather than take a thread part-way up for
|
|
115
|
+
* it. From the catalog, loading nothing; fork lineage is {@link lineageRoot}'s.
|
|
116
|
+
*/
|
|
117
|
+
get originRoot(): string | null;
|
|
118
|
+
get environment(): ThreadSummary['environment'];
|
|
119
|
+
/** The thread and row this one was forked at, or `null` unless it is a fork. */
|
|
120
|
+
get forkedFrom(): RowRef | null;
|
|
121
|
+
/**
|
|
122
|
+
* The thread at the start of this one's fork lineage: itself unless it is a fork. Forks of one
|
|
123
|
+
* root share its history, and so the provider cache that holds it.
|
|
124
|
+
*/
|
|
125
|
+
get lineageRoot(): string;
|
|
126
|
+
/** How this thread's own last turn ended, from the catalog; `null` before its first ends, or while one is open. */
|
|
127
|
+
lastOutcome(): DeepReadonly<TurnEndReason> | null;
|
|
128
|
+
/** Forks this thread at a row, or at the turn holding one; see `ctx.threads.fork`. */
|
|
129
|
+
fork(options: ForkOptions): Promise<Thread>;
|
|
130
|
+
/**
|
|
131
|
+
* Re-renders the prompt from the registries as they stand — the thread's own plugins included,
|
|
132
|
+
* which is why it activates the thread and waits for them — and records it; later turns send the
|
|
133
|
+
* new one. The deliberate exception to a prompt being frozen at first run.
|
|
134
|
+
*/
|
|
135
|
+
rebuildPrompt(): Promise<PromptBlock[]>;
|
|
136
|
+
/**
|
|
137
|
+
* This thread's events as they are appended: `ctx.journal.subscribe` filtered to the thread, so a
|
|
138
|
+
* promise the listener returns is reported if it rejects, as any subscriber's is. Returns the
|
|
139
|
+
* unsubscribe function.
|
|
140
|
+
*/
|
|
141
|
+
on(listener: (event: JournalEvent) => void): () => void;
|
|
142
|
+
/** The model's output as it streams on this thread. Returns the unsubscribe function. */
|
|
143
|
+
onChunk(listener: (chunk: StreamedChunk) => void): () => void;
|
|
144
|
+
/**
|
|
145
|
+
* Queues durable input without driving, and resolves once it is durable with what the write did:
|
|
146
|
+
* `queued`, with the row that recorded it; `known`, when this thread was already handed `id`, which
|
|
147
|
+
* queues nothing and names the original row; or `refused`, with the reason `rows` vetoed it for.
|
|
148
|
+
*
|
|
149
|
+
* `rows` runs inside the write once the input's target is decided, and adds a plugin's rows to the
|
|
150
|
+
* same group or vetoes the input by returning `{ refuse }` (see `WriteRows`); a callback that
|
|
151
|
+
* throws fails the send with that error instead. A known id never calls it.
|
|
152
|
+
* `source` attributes the input to a plugin, as on a step contribution, and needs the `id` the
|
|
153
|
+
* plugin derived: the claimed `input/message` keeps both, and input waiting for a turn is claimed
|
|
154
|
+
* as one unsourced input or every consecutive sourced input at the head of the queue.
|
|
155
|
+
*
|
|
156
|
+
* Text is the common case and stays a string; `{ role: 'developer', content }` queues a message
|
|
157
|
+
* that speaks as the harness rather than as the person, and content parts carry what text cannot.
|
|
158
|
+
*
|
|
159
|
+
* Where input waits is the sender's `target` when it names one, and admission's choice otherwise.
|
|
160
|
+
* Admission joins a running turn at its next step; the caller that started the turn owns its
|
|
161
|
+
* result. On an idle thread it waits for a turn of its own, behind input sent before it, and is
|
|
162
|
+
* claimed only by that turn's first step: a turn that opens by answering calls an earlier turn
|
|
163
|
+
* left leaves it for the next turn, which the same run opens once that work completed.
|
|
164
|
+
* `target: 'next-turn'` asks for a turn of its own even while a run holds the thread, as a new
|
|
165
|
+
* assignment does; `target: 'next-step'` joins the next model step of whichever turn takes it,
|
|
166
|
+
* including a turn that resumes parked calls, as a report on work already set going does.
|
|
167
|
+
* Sending never interrupts: an in-flight model call or tool is never cut off. Interruption is
|
|
168
|
+
* `cancel()`, then `send()` with a wake, deliberately two visible steps.
|
|
169
|
+
*
|
|
170
|
+
* A wake may state the route it runs on (`RouteStatement`), checked inside the write: an `expect`
|
|
171
|
+
* that no longer matches the thread's route is refused with `RouteConflictError`, one whose route
|
|
172
|
+
* cannot run with `RouteUnavailableError`; a `select` changes the route, which reauthorizes all the
|
|
173
|
+
* thread's unfinished work on it, only while no request is pending or the route cannot run, and no
|
|
174
|
+
* run serving the pending request holds the thread. A refusal writes nothing.
|
|
175
|
+
*/
|
|
176
|
+
send(input: ThreadInput, options?: SendOptions): Promise<SendOutcome>;
|
|
177
|
+
/**
|
|
178
|
+
* Takes back one queued input that no step has claimed yet, by the id it was sent with, and
|
|
179
|
+
* resolves with what the write did: `withdrawn`, `not-queued` (claimed, discarded or unknown), or
|
|
180
|
+
* `refused` by a `rows` veto, which adds a plugin's rows to the same write either way and is told whether
|
|
181
|
+
* the input was withdrawn. The id stays known, so `send` with it queues nothing again.
|
|
182
|
+
*/
|
|
183
|
+
withdraw(inputId: string, options?: WithdrawOptions): Promise<WithdrawOutcome>;
|
|
184
|
+
/**
|
|
185
|
+
* Records answers to confirmations parked on this thread, all of them or none. Does not drive: the
|
|
186
|
+
* run the answer's cause asks for re-dispatches them, through authorization again. A request that
|
|
187
|
+
* already has a decision — answered before, or approved and then revoked — is refused with
|
|
188
|
+
* `ConfirmationAnsweredError`, carrying the decision on record; a batch naming one request twice
|
|
189
|
+
* is refused outright.
|
|
190
|
+
*/
|
|
191
|
+
answer(decisions: readonly ConfirmationAnswer[], options?: {
|
|
192
|
+
readonly wake?: boolean;
|
|
193
|
+
}): Promise<void>;
|
|
194
|
+
/**
|
|
195
|
+
* Asks the thread to run again, as a person or a host does: a cause that releases the failure,
|
|
196
|
+
* cancellation and startup holds, recorded in one write and resolving once durable. A `route`
|
|
197
|
+
* statement is checked as `send` checks a wake's. Resolves with the run the cause joined or opened.
|
|
198
|
+
*/
|
|
199
|
+
resume(options?: {
|
|
200
|
+
readonly route?: RouteStatement;
|
|
201
|
+
}): Promise<string>;
|
|
202
|
+
/**
|
|
203
|
+
* A cancel's answer to each call the thread suspended, read inside its write: an error result in
|
|
204
|
+
* the declaration's turn and step, citing the call and the declaration.
|
|
205
|
+
*/
|
|
206
|
+
private closeWaitRows;
|
|
207
|
+
/** The thread's pending run request, read inside a write. */
|
|
208
|
+
private pendingRun;
|
|
209
|
+
/**
|
|
210
|
+
* Takes back approvals of calls without a result. Each becomes a rejection, so the call does not run
|
|
211
|
+
* again: its next dispatch ends it with an error. A call that already started, and then waits or
|
|
212
|
+
* was cut off, keeps what it did, and a child thread it started keeps running. Refused while a run
|
|
213
|
+
* holds the thread, since that run may be executing one. A batch with any id that does not qualify
|
|
214
|
+
* records nothing. Writes only to the journal, so it also works on a thread that cannot activate,
|
|
215
|
+
* which is how a host gets such a thread out of an approval it cannot run.
|
|
216
|
+
*/
|
|
217
|
+
revokeApprovals(requestIds: readonly string[], rejectionMessage?: string | null): Promise<void>;
|
|
218
|
+
/**
|
|
219
|
+
* Asks the thread's strategy to prepare its surface now, between turns, with the `request`
|
|
220
|
+
* trigger and `options`, which the engine passes on and never reads. This is how a host offers a `/compact` command.
|
|
221
|
+
*
|
|
222
|
+
* Holds the thread's admission, as a run does, but accepts no input: `send()` meanwhile queues for the
|
|
223
|
+
* next turn unless its sender names `next-step`, a run waits for it, and `activity` names the compaction. Requires a
|
|
224
|
+
* settled thread — no tool call without a result, no open confirmation, no answer its stop checks
|
|
225
|
+
* still owe — and rejects with `ThreadUnsettledError` otherwise; an interrupted open turn is closed
|
|
226
|
+
* first, as a run closes it. The route is resolved as a turn's would be. Opens no turn, runs no
|
|
227
|
+
* step hook and claims no queued input. Aborts on `signal`, on `cancel()` and on shutdown, and then
|
|
228
|
+
* resolves `cancelled` rather than rejects, with whatever the dispatch committed; cancelled before
|
|
229
|
+
* it began, it resolves `cancelled` with nothing dispatched. A strategy that failed on its own while
|
|
230
|
+
* the signal aborted resolves `failed`.
|
|
231
|
+
*
|
|
232
|
+
* Resolves with the one outcome record: the replacement rows committed and how the dispatch ended;
|
|
233
|
+
* `skipped` with a reason when no strategy answered.
|
|
234
|
+
*/
|
|
235
|
+
compact(options?: CompactOptions): Promise<SurfacePrepareOutcome>;
|
|
236
|
+
/**
|
|
237
|
+
* Cancels the thread, whatever its state: captures the operation admitted now, if any, and aborts
|
|
238
|
+
* only it, then records one write: the `thread/cancel` row, the clear of everything queued, an
|
|
239
|
+
* error result answering each call the thread suspended on a wait, resolved or not, the rows
|
|
240
|
+
* `options.rows` adds, and the settlement, by the cancel's intent, of a pending run no execution is
|
|
241
|
+
* still to settle. So a cancelled thread never holds a waiting call, and a feature watching the
|
|
242
|
+
* call learns of the cancel from its result. The run the captured execution serves settles in that execution's
|
|
243
|
+
* finalization, unless the finalization built its settlement before this write and left it pending. A `user` cancel (a person's stop) holds the thread until a releasing cause; a
|
|
244
|
+
* `cleanup` one holds nothing. From the call until its write has landed and what it captured has
|
|
245
|
+
* released the thread, the cancel holds the thread, so a run meanwhile is refused busy; a cancel
|
|
246
|
+
* made meanwhile joins it. With `until: 'released'`, the default, resolves then, or rejects with its
|
|
247
|
+
* own write's failure, which records nothing — so a `send` after `cancel()` never races the
|
|
248
|
+
* cancelled operation. With `until: 'recorded'` it settles with that write alone, resolving once
|
|
249
|
+
* it has landed and rejecting with its failure, without waiting for what was captured to wind down:
|
|
250
|
+
* a run's drain and finalization are the engine's, and a failure of theirs goes to `reportError`,
|
|
251
|
+
* so a caller that needs the thread free awaits `released`. Each joined call gets its own write's
|
|
252
|
+
* outcome.
|
|
253
|
+
*/
|
|
254
|
+
cancel(reason: string, options: CancelOptions): Promise<void>;
|
|
255
|
+
}
|
|
256
|
+
/** The answers as journal rows on the thread that asked, appended as one group. */
|
|
257
|
+
export declare const confirmationRows: (threadId: string, decisions: readonly ConfirmationAnswer[]) => {
|
|
258
|
+
type: "confirm/resolved";
|
|
259
|
+
data: {
|
|
260
|
+
request_id: string;
|
|
261
|
+
approved: boolean;
|
|
262
|
+
rejection_message: string | null;
|
|
263
|
+
};
|
|
264
|
+
options: {
|
|
265
|
+
threadId: string;
|
|
266
|
+
};
|
|
267
|
+
}[];
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { type Context, type Scope, type Scoped, type ScopeKey } from '@leuduan/cordis';
|
|
2
|
+
import { type CompactOptions, type Lease, type LoopServices, type SurfacePrepareOutcome } from '../loop/index.js';
|
|
3
|
+
import type { ServedRun } from '../loop/index.js';
|
|
4
|
+
import type { Thread } from './thread.js';
|
|
5
|
+
import type { AdmissionView } from './admission.js';
|
|
6
|
+
import type { ThreadsService } from './threads.js';
|
|
7
|
+
/**
|
|
8
|
+
* One process-local activation: the thread's Cordis scope, the plugins mounted in it, their
|
|
9
|
+
* readiness, and the loop that runs in it. It owns resources, never admission: which operation
|
|
10
|
+
* holds the thread, and its cancellation, are the admission owner's, which the threads service
|
|
11
|
+
* keeps and which hands each run or compaction its signal and lease.
|
|
12
|
+
*/
|
|
13
|
+
export declare class ThreadActivation {
|
|
14
|
+
readonly scope: Scope;
|
|
15
|
+
readonly target: Scoped;
|
|
16
|
+
private readonly runtime;
|
|
17
|
+
private readonly loop;
|
|
18
|
+
private readiness;
|
|
19
|
+
private readonly controller;
|
|
20
|
+
private failed;
|
|
21
|
+
private prepared;
|
|
22
|
+
/** The plugin tree as it was when the activation became ready, which is what it runs with. */
|
|
23
|
+
private readyTree;
|
|
24
|
+
private staleBecause;
|
|
25
|
+
private draining;
|
|
26
|
+
private closingDone;
|
|
27
|
+
private readonly service;
|
|
28
|
+
private readonly admission;
|
|
29
|
+
readonly thread: Thread;
|
|
30
|
+
private readonly released;
|
|
31
|
+
constructor(service: ThreadsService,
|
|
32
|
+
/** The admission owner's reads, given by the service that owns it. */
|
|
33
|
+
admission: AdmissionView, owner: Context, thread: Thread, loopServices: (scope: ScopeKey) => LoopServices, released: () => void);
|
|
34
|
+
/**
|
|
35
|
+
* From readiness on, the plugin tree is what the activation runs with. A guard on each of its
|
|
36
|
+
* plugins marks the activation stale before that plugin's disposers run, whatever unloads it: a
|
|
37
|
+
* dependency gone, a root mount disposed, a reload. Its own release marks it too, harmlessly.
|
|
38
|
+
*/
|
|
39
|
+
private watchTree;
|
|
40
|
+
private markStale;
|
|
41
|
+
/**
|
|
42
|
+
* Whether the plugins changed since readiness: one unloaded or reloaded, or one added through
|
|
43
|
+
* `thread.ctx`, which is reported once. A stale activation dispatches nothing new, and the owner
|
|
44
|
+
* replaces it once the operation holding the thread settles.
|
|
45
|
+
*/
|
|
46
|
+
isStale(): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Whether a setup in this activation is still running: its listeners and installations have not
|
|
49
|
+
* settled, or a plugin of its tree is in transition, one mounted later through `thread.ctx` or one
|
|
50
|
+
* reloading included. A change that waits for this activation to go, made from one of those
|
|
51
|
+
* setups, would wait on itself, so it is refused meanwhile. Not a readiness check: readiness is
|
|
52
|
+
* settled once.
|
|
53
|
+
*/
|
|
54
|
+
get activating(): boolean;
|
|
55
|
+
private observe;
|
|
56
|
+
/** Aborts on release and on stop; what the activate listeners receive. */
|
|
57
|
+
get signal(): AbortSignal;
|
|
58
|
+
/** Whether readiness failed: the owner releases such an activation once its operation settles. */
|
|
59
|
+
get hasFailed(): boolean;
|
|
60
|
+
/** Set once `release()` has begun: resolves when the scope is disposed. The owner waits for it before activating again. */
|
|
61
|
+
get closed(): Promise<void> | undefined;
|
|
62
|
+
private settle;
|
|
63
|
+
/** One execution of the run `served`, under the admitted operation's signal and lease. */
|
|
64
|
+
run(options: {
|
|
65
|
+
signal: AbortSignal;
|
|
66
|
+
lease: Lease;
|
|
67
|
+
served: ServedRun;
|
|
68
|
+
}): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* One request to prepare the surface, under the admitted operation's signal and lease; see
|
|
71
|
+
* `Thread.compact`. Resolves with the outcome, `cancelled` when the signal aborts first.
|
|
72
|
+
*/
|
|
73
|
+
compact(options: CompactOptions & {
|
|
74
|
+
signal: AbortSignal;
|
|
75
|
+
lease: Lease;
|
|
76
|
+
}): Promise<SurfacePrepareOutcome>;
|
|
77
|
+
/**
|
|
78
|
+
* Waits for readiness, settled once when the activation began, then checks the agent and records
|
|
79
|
+
* the prompt if the thread has none. Only then is the scope complete: the thread's plugins may
|
|
80
|
+
* define its agent, and an unknown one fails here, before a prompt is recorded or a turn opens,
|
|
81
|
+
* so input waits for a retry. A stale activation never gets here: the owner replaces it first.
|
|
82
|
+
*/
|
|
83
|
+
private ready;
|
|
84
|
+
/**
|
|
85
|
+
* Resolves once the activation is ready: its listeners and installations settled, every plugin of
|
|
86
|
+
* its tree active. The same barrier a run uses: a settled but PENDING plugin is not ready, so a
|
|
87
|
+
* caller never reads a half-configured scope.
|
|
88
|
+
*/
|
|
89
|
+
whenReady(): Promise<void>;
|
|
90
|
+
/** The owner releases scopes only after every thread has drained, including failed setup. */
|
|
91
|
+
stop(reason: Error): void;
|
|
92
|
+
/** Resolves once setup has ended, however, and every plugin mounted since is settled. */
|
|
93
|
+
whenIdle(): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Disposes the scope once setup has ended. The owner calls this with no executing operation on
|
|
96
|
+
* the thread, or from the operation that is settling; the scope's own unload guard is what waits
|
|
97
|
+
* for a loop when something else disposes the scope.
|
|
98
|
+
*/
|
|
99
|
+
release(): Promise<void>;
|
|
100
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Service, type Context } from '@leuduan/cordis';
|
|
2
|
+
export type ThreadDirsConfig = {
|
|
3
|
+
/**
|
|
4
|
+
* Absolute application data directory; thread directories live under `<dataDir>/threads`. `null`
|
|
5
|
+
* turns thread directories off, for a host without a filesystem of its own. Required either way.
|
|
6
|
+
*/
|
|
7
|
+
dataDir: string | null;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Where each thread keeps files of its own: `<dataDir>/threads/<thread-id>/`, a scratch space its
|
|
11
|
+
* file tools may read and write as part of the application's shared data directory. Harness-written
|
|
12
|
+
* files go in named subdirectories such as `tool-outputs/`.
|
|
13
|
+
*
|
|
14
|
+
* The path is derived from the data directory and thread id, but absolute paths are also recorded
|
|
15
|
+
* in prompts and tool results. Keep the data directory at the same location when reopening a
|
|
16
|
+
* durable journal. Plugins can use the id supplied by their activation hook to find the directory.
|
|
17
|
+
*
|
|
18
|
+
* File tools may read and write the entire data directory, including other threads' scratch files.
|
|
19
|
+
*
|
|
20
|
+
* With `dataDir: null` there are no directories: `dataDir` and `root` are `null`, activation creates
|
|
21
|
+
* nothing, and `dirFor` and `ensure` throw. The service stays mounted either way, because the threads
|
|
22
|
+
* service injects it. A plugin that needs directories calls {@link ThreadDirsService.require} where it
|
|
23
|
+
* mounts, so a composition without them fails there.
|
|
24
|
+
*/
|
|
25
|
+
export declare class ThreadDirsService extends Service<ThreadDirsConfig> {
|
|
26
|
+
readonly dataDir: string | null;
|
|
27
|
+
readonly root: string | null;
|
|
28
|
+
constructor(ctx: Context, config: ThreadDirsConfig);
|
|
29
|
+
/**
|
|
30
|
+
* The data directory, for the plugin `user` that cannot work without thread directories. Call it
|
|
31
|
+
* first where the plugin mounts, so a root mounted with `dataDir: null` refuses there.
|
|
32
|
+
*/
|
|
33
|
+
require(user: string): string;
|
|
34
|
+
/** The directory of `threadId`, without touching the filesystem. */
|
|
35
|
+
dirFor(threadId: string): string;
|
|
36
|
+
/** The directory of `threadId`, created if missing. */
|
|
37
|
+
ensure(threadId: string): string;
|
|
38
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { ConversationMessage, PromptBlock, ToolSpec } from '../llm/index.js';
|
|
2
|
+
import type { ConfirmationState, ForkPoint, InputFate, InstallationRecord, RowRef, RunOutcome, Target, WaitEntry } from '../loop/index.js';
|
|
3
|
+
import type { JournalEvent, QueuedInput, Seq } from '../models/index.js';
|
|
4
|
+
import type { DeepReadonly } from '../util/json.js';
|
|
5
|
+
import type { Journal } from '../journal/index.js';
|
|
6
|
+
import type { ReadonlyState } from '../util/foldState.js';
|
|
7
|
+
/**
|
|
8
|
+
* What one thread's folds say, read synchronously (`ctx.threads.view`, `thread.read`): valid while
|
|
9
|
+
* something holds the thread in memory — a journal write or a contributor running for it, a run, a
|
|
10
|
+
* retention. Reading a thread nothing holds may find it unloaded and throws `ThreadNotLoadedError`.
|
|
11
|
+
*/
|
|
12
|
+
export declare class ThreadView {
|
|
13
|
+
private readonly inbox;
|
|
14
|
+
private readonly journal;
|
|
15
|
+
readonly threadId: string;
|
|
16
|
+
private readonly targetOf;
|
|
17
|
+
constructor(journal: Journal, threadId: string, targetOf: (threadId: string) => Target);
|
|
18
|
+
/**
|
|
19
|
+
* The thread's route, why it cannot run here (`blocked`), and whether a route change is accepted
|
|
20
|
+
* now (`selectable`): what a route statement is checked against (`Thread.send`). Never throws.
|
|
21
|
+
*/
|
|
22
|
+
target(): Target;
|
|
23
|
+
/**
|
|
24
|
+
* The conversation as the model sees it, a fork's inherited history included. After a
|
|
25
|
+
* replacement that is the replaced view, stand-ins included; `replayLineage()` is the record.
|
|
26
|
+
*/
|
|
27
|
+
transcript(): readonly ConversationMessage[];
|
|
28
|
+
/**
|
|
29
|
+
* The row behind each {@link transcript} message, index for index — what a fork anchors on. A
|
|
30
|
+
* stand-in's is the `surface/replaced` row that put it there.
|
|
31
|
+
*/
|
|
32
|
+
messageSeqs(): readonly RowRef[];
|
|
33
|
+
/**
|
|
34
|
+
* The `llm/request` that produced the reply at `row`, on the thread that owns it; `null` for a
|
|
35
|
+
* row that is not a reply. Forking there regenerates the reply.
|
|
36
|
+
*/
|
|
37
|
+
requestBehind(row: RowRef): RowRef | null;
|
|
38
|
+
/**
|
|
39
|
+
* The original rows a {@link messageSeqs} row stands for, in transcript order: the row itself
|
|
40
|
+
* when it is an original, and for a `surface/replaced` row, the originals behind every row it
|
|
41
|
+
* cites, followed through replacements of replacements — what a stand-in summarizes, on whichever
|
|
42
|
+
* thread holds `row`.
|
|
43
|
+
*/
|
|
44
|
+
originalsBehind(row: RowRef): RowRef[];
|
|
45
|
+
/**
|
|
46
|
+
* Every turn ending along the thread's lineage, and every replacement recorded between turns,
|
|
47
|
+
* oldest first: where "fork from here" cuts.
|
|
48
|
+
*/
|
|
49
|
+
forkPoints(): ForkPoint[];
|
|
50
|
+
/** The last thing the model said on the thread, if anything; see {@link lastAssistantMessage}. */
|
|
51
|
+
finalMessage(): ReadonlyState<ConversationMessage> | null;
|
|
52
|
+
/**
|
|
53
|
+
* How the run that began after `fromSeq` ended, and what it answered: a run's outcome, which an
|
|
54
|
+
* `aborted` turn ends. A delegation task is not a run and keeps its own settlement rule.
|
|
55
|
+
*/
|
|
56
|
+
outcomeSince(fromSeq: Seq): RunOutcome;
|
|
57
|
+
/** The system prompt the thread sends; empty until its first turn records it. */
|
|
58
|
+
prompt(): readonly PromptBlock[];
|
|
59
|
+
/**
|
|
60
|
+
* The tool specifications `request` sent, as recorded then: thread-local tools and middleware's
|
|
61
|
+
* changes included, whatever is registered now. The request may be the thread's own or one it
|
|
62
|
+
* inherits; it is read on the thread that made it.
|
|
63
|
+
*/
|
|
64
|
+
requestTools(request: JournalEvent<'llm/request'> | JournalEvent<'auxiliary/request'>): readonly ToolSpec[];
|
|
65
|
+
/** Requests waiting on the user, as owned frozen snapshots that survive later answers. */
|
|
66
|
+
pendingConfirmations(): DeepReadonly<ConfirmationState[]>;
|
|
67
|
+
/**
|
|
68
|
+
* The waits the thread declared, in declaration order, answered ones included, as owned frozen
|
|
69
|
+
* snapshots that survive later resolutions; with `owner`, only the waits declared under it. The
|
|
70
|
+
* registration named by an owner resolves its waits; a read never does.
|
|
71
|
+
*/
|
|
72
|
+
waits(options?: {
|
|
73
|
+
readonly owner?: string;
|
|
74
|
+
}): readonly Readonly<WaitEntry>[];
|
|
75
|
+
/** The thread's own rows so far: what `thread.on` would have delivered. */
|
|
76
|
+
replay(): readonly JournalEvent[];
|
|
77
|
+
/**
|
|
78
|
+
* A fork's inherited rows, then its own, each with its original thread id and seq — what a
|
|
79
|
+
* frontend replays to show a fork's whole history. The same as `replay()` for a thread that is
|
|
80
|
+
* not a fork.
|
|
81
|
+
*/
|
|
82
|
+
replayLineage(): readonly JournalEvent[];
|
|
83
|
+
/** Input waiting for a step to claim it, in the order it was sent. */
|
|
84
|
+
queued(): readonly QueuedInput[];
|
|
85
|
+
/**
|
|
86
|
+
* What became of the input `inputId`: never handed to this thread, queued, claimed by a step, or
|
|
87
|
+
* discarded unclaimed; see {@link InputFate}.
|
|
88
|
+
*/
|
|
89
|
+
input(inputId: string): InputFate;
|
|
90
|
+
/** The thread's preset installations in recorded order, as readonly snapshots. */
|
|
91
|
+
installations(): readonly InstallationRecord[];
|
|
92
|
+
}
|