@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,104 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import type { FailureClassification } from '../../llm/index.js';
|
|
4
|
+
/** Extra top-level request fields merged into every call (vendor extensions), minus the refused ones. */
|
|
5
|
+
export declare const ExtraBodySchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
6
|
+
/**
|
|
7
|
+
* A provider's declared context windows, by model id. A model with no entry has no window: `null`,
|
|
8
|
+
* never a guess.
|
|
9
|
+
*/
|
|
10
|
+
export declare const contextWindowOf: (windows: Readonly<Record<string, number>>, model: string) => number | null;
|
|
11
|
+
/** The structured fields of a provider error, wherever it arrived: a rejected request or the stream. */
|
|
12
|
+
export type ProviderErrorFields = {
|
|
13
|
+
readonly code?: unknown;
|
|
14
|
+
readonly type?: unknown;
|
|
15
|
+
readonly message?: unknown;
|
|
16
|
+
};
|
|
17
|
+
/** The OpenAI-shaped code for a request over the model's context window. */
|
|
18
|
+
export declare const CONTEXT_LENGTH_EXCEEDED = "context_length_exceeded";
|
|
19
|
+
/**
|
|
20
|
+
* A credential problem the transport found while authorizing a request. The SDK wraps whatever a
|
|
21
|
+
* custom `fetch` throws in its connection error, so {@link classifyProviderError} hands it back as
|
|
22
|
+
* itself: a login that cannot be used reads as that login's problem, not as a failed connection.
|
|
23
|
+
*/
|
|
24
|
+
export declare class TransportCredentialError extends Error {
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* `error` as the failure it is, else unchanged. An SDK `APIError` has fields to read: a rejected
|
|
28
|
+
* request, or an error event the SDK raised while reading the stream. When `isOverflow` recognizes
|
|
29
|
+
* them it is the overflow, with the message the provider's own, without the SDK's status prefix.
|
|
30
|
+
* The SDK's own abort error, once the request's `signal` fired, is that signal's reason: the
|
|
31
|
+
* caller's cancellation, as the engine recognises it, whatever the SDK names its class. A connection
|
|
32
|
+
* error that carries a {@link TransportCredentialError} is that error.
|
|
33
|
+
*/
|
|
34
|
+
export declare function classifyProviderError(provider: string, error: unknown, isOverflow: (fields: ProviderErrorFields) => boolean, signal: AbortSignal | undefined): unknown;
|
|
35
|
+
/**
|
|
36
|
+
* A failure a provider reported inside its stream (a `response.failed` or `error` event), with the
|
|
37
|
+
* structured fields it gave. There is no HTTP status: the request had already succeeded.
|
|
38
|
+
*/
|
|
39
|
+
export declare class ProviderStreamError extends Error {
|
|
40
|
+
readonly code: unknown;
|
|
41
|
+
readonly type: unknown;
|
|
42
|
+
constructor(fields: ProviderErrorFields, fallback: string);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The failure kind of an error from an OpenAI-shaped client, by structured evidence only: the HTTP
|
|
46
|
+
* status and error code of a rejected request, the code of a stream's error event, the SDK's
|
|
47
|
+
* transport errors, and socket error codes. A spent quota or usage limit is `quota` whether its name
|
|
48
|
+
* comes in the code or the type, on any status or on a failure with none; otherwise a status is read
|
|
49
|
+
* as every protocol reads it (`statusKind`). `retryAfterMs` is read from the
|
|
50
|
+
* `retry-after-ms` or `retry-after` header, never from prose. Anything unrecognised is `other`.
|
|
51
|
+
*/
|
|
52
|
+
export declare function classifyOpenAIFailure(error: unknown, now?: number): FailureClassification;
|
|
53
|
+
/**
|
|
54
|
+
* The request option every model request carries, an injected SDK client's included: the SDK retries
|
|
55
|
+
* nothing. Retrying is the engine's (`ctx.llm`), once, before any output, by the failure's kind.
|
|
56
|
+
*/
|
|
57
|
+
export declare const NO_SDK_RETRIES: {
|
|
58
|
+
readonly maxRetries: 0;
|
|
59
|
+
};
|
|
60
|
+
/** The OpenAI API's public endpoint: the protocol default of the providers that speak to OpenAI. */
|
|
61
|
+
export declare const OPENAI_API_BASE_URL = "https://api.openai.com/v1";
|
|
62
|
+
/**
|
|
63
|
+
* What every OpenAI-shaped provider is configured with. Each one extends it with its own
|
|
64
|
+
* `defaultModel`, its endpoint's default, and whatever its API alone has. The credential is the
|
|
65
|
+
* host's to resolve: lagent reads no environment variable for it.
|
|
66
|
+
*/
|
|
67
|
+
export declare const OpenAICommonConfigSchema: z.ZodObject<{
|
|
68
|
+
apiKey: z.ZodOptional<z.ZodString>;
|
|
69
|
+
streamIdleTimeoutMs: z.ZodNullable<z.ZodNumber>;
|
|
70
|
+
baseURL: z.ZodOptional<z.ZodString>;
|
|
71
|
+
defaultHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
72
|
+
extraBody: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
73
|
+
thinkingEffort: z.ZodOptional<z.ZodEnum<{
|
|
74
|
+
low: "low";
|
|
75
|
+
high: "high";
|
|
76
|
+
none: "none";
|
|
77
|
+
medium: "medium";
|
|
78
|
+
max: "max";
|
|
79
|
+
}>>;
|
|
80
|
+
}, z.core.$strip>;
|
|
81
|
+
/**
|
|
82
|
+
* The SDK client for an OpenAI-shaped endpoint, the one constructor every provider here uses. The
|
|
83
|
+
* SDK fills an option left out from the process environment (`OPENAI_API_KEY`, `OPENAI_BASE_URL`,
|
|
84
|
+
* `OPENAI_ORG_ID`, `OPENAI_PROJECT_ID`, `OPENAI_ADMIN_KEY`, `OPENAI_WEBHOOK_SECRET`, `OPENAI_LOG`),
|
|
85
|
+
* so each is given here: the credential and endpoint the caller's, the log level the SDK's default,
|
|
86
|
+
* the rest, which lagent never uses, none. Its `OPENAI_CUSTOM_HEADERS` merge is undone, so a request
|
|
87
|
+
* carries the SDK's own headers, its authorization and the caller's `defaultHeaders`, and nothing
|
|
88
|
+
* from the environment.
|
|
89
|
+
*/
|
|
90
|
+
export declare function openAIClient(options: {
|
|
91
|
+
readonly apiKey: string;
|
|
92
|
+
readonly baseURL: string;
|
|
93
|
+
readonly defaultHeaders?: Record<string, string>;
|
|
94
|
+
readonly fetch?: typeof globalThis.fetch;
|
|
95
|
+
}): OpenAI;
|
|
96
|
+
/**
|
|
97
|
+
* The client a provider's adapter sends with: the one injected, else one built from its
|
|
98
|
+
* configuration, which then has to carry the credential.
|
|
99
|
+
*/
|
|
100
|
+
export declare function adapterClient(provider: string, config: {
|
|
101
|
+
readonly apiKey?: string | undefined;
|
|
102
|
+
readonly baseURL: string;
|
|
103
|
+
readonly defaultHeaders?: Record<string, string> | undefined;
|
|
104
|
+
}, injected: OpenAI | undefined): OpenAI;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { StreamIdleError } from '../../llm/index.js';
|
|
3
|
+
import type { ConversationMessage, JsonObject, LLMStreamChunk, ModelRequest, ModelResponse, StreamingLLMResponse, ToolCall } from '../../llm/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* How long one attempt may go without a single event from the provider, waiting for the first
|
|
6
|
+
* included, before it fails as `timeout`; `null` disables the deadline. Required: it is transport
|
|
7
|
+
* configuration, and a reasoning model that streams no reasoning needs a long one, or none.
|
|
8
|
+
*/
|
|
9
|
+
export declare const StreamIdleTimeoutSchema: z.ZodNullable<z.ZodNumber>;
|
|
10
|
+
/**
|
|
11
|
+
* A tool call with its arguments as a provider hands them over: already an object, or JSON still in
|
|
12
|
+
* a string. Absent or empty arguments are an empty object. Anything that is not a JSON object is kept
|
|
13
|
+
* as the model sent it, malformed, so its call alone is answered with an error and its siblings run.
|
|
14
|
+
*/
|
|
15
|
+
export declare function toolCall(callId: string, name: string, value: unknown): ToolCall;
|
|
16
|
+
/**
|
|
17
|
+
* Runs `work` with the idle deadline of the attempt whose transport is opening held: work the
|
|
18
|
+
* transport does on the attempt's behalf with a bound of its own, such as reading or recovering
|
|
19
|
+
* credentials, is not provider silence. Outside an attempt it runs `work` as it is.
|
|
20
|
+
*/
|
|
21
|
+
export declare function holdDeadline<T>(work: () => Promise<T>): Promise<T>;
|
|
22
|
+
/**
|
|
23
|
+
* One attempt's lifetime, made before its transport opens: the controller its SDK call is handed
|
|
24
|
+
* (aborted with the request's signal, or when the deadline passes), the idle timer, and their
|
|
25
|
+
* cleanup. The timer starts when the request is sent and resets on every raw provider event the
|
|
26
|
+
* stream sees (`events`), including events the adapter drops, since reasoning can be visibly silent;
|
|
27
|
+
* it is held while the transport works on the attempt's behalf (`holdDeadline`). Expiry is recorded
|
|
28
|
+
* before the controller aborts, so a read that ends afterwards, by an SDK abort error or quietly, is
|
|
29
|
+
* told from the caller's own cancel; nothing the transport delivers after expiry is read. The
|
|
30
|
+
* caller's cancel clears the deadline: a cancelled attempt never times out.
|
|
31
|
+
*/
|
|
32
|
+
export declare class AttemptLifetime {
|
|
33
|
+
private readonly controller;
|
|
34
|
+
/** What `close()` aborts with, kept so the read it ends can tell it from a failure of the transport. */
|
|
35
|
+
private readonly closure;
|
|
36
|
+
private timer;
|
|
37
|
+
private expiredAt;
|
|
38
|
+
private holds;
|
|
39
|
+
private readonly forward;
|
|
40
|
+
private readonly provider;
|
|
41
|
+
private readonly requestSignal;
|
|
42
|
+
private readonly idleMs;
|
|
43
|
+
constructor(provider: string, requestSignal: AbortSignal | undefined, idleMs: number | null);
|
|
44
|
+
/** Runs `open` as this attempt's: what it calls can hold the deadline (`holdDeadline`). */
|
|
45
|
+
opening<T>(open: () => Promise<T>): Promise<T>;
|
|
46
|
+
/** Stops the deadline until as many `release`s as `hold`s have been made. */
|
|
47
|
+
hold(): void;
|
|
48
|
+
release(): void;
|
|
49
|
+
/** What the attempt's SDK call is given: aborted by the caller's cancel or the deadline. */
|
|
50
|
+
get signal(): AbortSignal;
|
|
51
|
+
/** Whether the deadline passed before the attempt ended. */
|
|
52
|
+
get expired(): boolean;
|
|
53
|
+
/** The failure an expired attempt reports. */
|
|
54
|
+
idleError(): StreamIdleError;
|
|
55
|
+
/**
|
|
56
|
+
* `source`, resetting the deadline on every event it yields, and ending without another once the
|
|
57
|
+
* deadline passed: an event that arrives after expiry, terminal evidence included, is not read.
|
|
58
|
+
*/
|
|
59
|
+
events<T>(source: AsyncIterable<T>): AsyncGenerator<T>;
|
|
60
|
+
/**
|
|
61
|
+
* Ends the attempt for a reader that closed its stream: aborts the controller the SDK was handed,
|
|
62
|
+
* which closes the transport, then disposes. Without the abort an unread response would hold its
|
|
63
|
+
* connection open, and nothing would close it once the caller's signal is no longer followed.
|
|
64
|
+
*/
|
|
65
|
+
close(): void;
|
|
66
|
+
/**
|
|
67
|
+
* Whether `error` is the abort `close()` raised: a transport read through `fetch` fails with its
|
|
68
|
+
* abort's reason, so a reader that leaves would otherwise end its own read as a failure.
|
|
69
|
+
*/
|
|
70
|
+
closedBy(error: unknown): boolean;
|
|
71
|
+
/** Clears the timer and stops following the request's signal; safe to call more than once. */
|
|
72
|
+
dispose(): void;
|
|
73
|
+
private clearTimer;
|
|
74
|
+
private arm;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* What an owner of a protocol client adds to every call it sends: headers for one call, over the
|
|
78
|
+
* client's own. It receives the call and the request the client mapped from it, so a header can
|
|
79
|
+
* derive from either; nothing rebuilds the request for it.
|
|
80
|
+
*/
|
|
81
|
+
export type CallHeaders = (call: ModelRequest, request: Readonly<Record<string, unknown>>) => Record<string, string>;
|
|
82
|
+
/**
|
|
83
|
+
* Opens one attempt, the one place an adapter creates, ends and classifies it: the lifetime is made
|
|
84
|
+
* before `open` runs, so its deadline bounds the wait for the first event too, and `open` gets the
|
|
85
|
+
* signal its transport must carry. When `open` fails the lifetime is disposed, and the failure is
|
|
86
|
+
* the deadline's `StreamIdleError` if the deadline passed (the caller's own cancel clears the
|
|
87
|
+
* deadline, so a cancel never reads as a timeout), else `classify(error)`, which names a
|
|
88
|
+
* cancellation and a provider's overflow as the engine recognises them. On success the lifetime stays
|
|
89
|
+
* live for the stream that reads `opened`.
|
|
90
|
+
*/
|
|
91
|
+
export declare function openAttempt<T>(provider: string, requestSignal: AbortSignal | undefined, idleMs: number | null, open: (signal: AbortSignal) => Promise<T>, classify: (error: unknown) => unknown): Promise<{
|
|
92
|
+
readonly lifetime: AttemptLifetime;
|
|
93
|
+
readonly opened: T;
|
|
94
|
+
}>;
|
|
95
|
+
/**
|
|
96
|
+
* The one enforcement of the reader rules `StreamingLLMResponse` states: a response is iterated at
|
|
97
|
+
* most once, `completed()` drains a response nobody has read and otherwise reports the outcome of
|
|
98
|
+
* the read that ended, and never settles while one is under way.
|
|
99
|
+
*
|
|
100
|
+
* A transport is consumed as it is read and a reader that stops early has already closed it, so only
|
|
101
|
+
* a stream nobody has touched can be drained; asking a consumed one for the rest returns what the
|
|
102
|
+
* read left rather than resuming, which would lose the whole message — including the text the reader
|
|
103
|
+
* had already seen. Everything a cut-off stream did say is accumulated by `read`.
|
|
104
|
+
*
|
|
105
|
+
* It owns one rule for every adapter: a response counts only once the provider said it was
|
|
106
|
+
* complete. A transport that ran to its end without saying so is a `transport` failure, and one that
|
|
107
|
+
* said so with no text and no tool call is an `empty` one (see {@link ResponseSettlementError}). A
|
|
108
|
+
* stream its reader stopped early, or whose request was aborted, is neither: the caller cut it off,
|
|
109
|
+
* and gets what arrived as a cut-off reply.
|
|
110
|
+
*/
|
|
111
|
+
export declare abstract class ReadOnceStream implements StreamingLLMResponse {
|
|
112
|
+
/** Whether the read is claimed: by the iterator, or by `completed()` draining. */
|
|
113
|
+
private claimed;
|
|
114
|
+
/** When the read has ended, whether it ran through, was stopped early or failed. */
|
|
115
|
+
private readonly ledger;
|
|
116
|
+
/** Whether the request was aborted when the read ended: fixed then, so a later abort changes nothing. */
|
|
117
|
+
private abortedAtEnd;
|
|
118
|
+
/** Whether the transport ran to its end, rather than its reader stopping or the read failing. */
|
|
119
|
+
private drained;
|
|
120
|
+
/** Whether its reader closed it early, before or while reading. */
|
|
121
|
+
private closedByReader;
|
|
122
|
+
/** The failure the read ended on, which `completed()` throws again rather than settling a partial. */
|
|
123
|
+
private readFailure;
|
|
124
|
+
protected readonly providerName: string;
|
|
125
|
+
protected readonly signal: AbortSignal | undefined;
|
|
126
|
+
private readonly lifetime;
|
|
127
|
+
protected constructor(providerName: string, signal: AbortSignal | undefined, lifetime: AttemptLifetime);
|
|
128
|
+
/**
|
|
129
|
+
* Claims the read, so a second iterator throws here and not at its first `next()`, and reads the
|
|
130
|
+
* transport through. When the attempt's deadline passed, the read's ending (an SDK abort error, or
|
|
131
|
+
* a quiet end) is that deadline's `StreamIdleError`, unless the provider's terminal evidence had
|
|
132
|
+
* already arrived: then the response stands, as complete as the provider said it was (Chat's usage,
|
|
133
|
+
* sent after the finish, may be missing). The lifetime ends with the read, however it ends, the
|
|
134
|
+
* reader abandoning it included.
|
|
135
|
+
*/
|
|
136
|
+
[Symbol.asyncIterator](): AsyncIterator<LLMStreamChunk>;
|
|
137
|
+
private readThrough;
|
|
138
|
+
/** Whether `error` is the caller's own cancellation; a failure that only coincided with one is not. */
|
|
139
|
+
private cancelled;
|
|
140
|
+
/** `error`, with what arrived before it kept beside it. */
|
|
141
|
+
private interrupted;
|
|
142
|
+
/** Reads the transport through, accumulating whatever `settle` and `partial` will need. */
|
|
143
|
+
protected abstract read(): AsyncGenerator<LLMStreamChunk>;
|
|
144
|
+
/** The response, once the provider's terminal evidence arrived; `undefined` before that. */
|
|
145
|
+
protected abstract settle(): ModelResponse | undefined;
|
|
146
|
+
/** What arrived so far: text and reasoning only, never a tool call nobody finished asking for. */
|
|
147
|
+
protected abstract partial(): {
|
|
148
|
+
message: ConversationMessage;
|
|
149
|
+
providerMetadata: JsonObject;
|
|
150
|
+
};
|
|
151
|
+
/** Remembers the failure the read ended on, and returns it to be thrown. */
|
|
152
|
+
private failed;
|
|
153
|
+
completed(): Promise<ModelResponse>;
|
|
154
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Plugin } from '@leuduan/cordis';
|
|
2
|
+
import { type ModelRoute } from '../llm/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Tells an agent the route it runs on: provider, model and thinking effort.
|
|
5
|
+
*
|
|
6
|
+
* Told as a conversation message at the next model step already due whenever the turn's route
|
|
7
|
+
* differs from the latest notice the model can still see: on its first step, after a person
|
|
8
|
+
* switches its model, when a turn falls back to another provider or returns from one, and after a
|
|
9
|
+
* replacement took the notice that said it off the surface. The route is the one the turn pinned,
|
|
10
|
+
* which request middleware cannot change, so it names what lagent sends. A step whose route did not
|
|
11
|
+
* resolve is told nothing; its model call fails anyway. A fork inherits what its source was told and
|
|
12
|
+
* runs on its source's route, so it is told nothing unless the route moved.
|
|
13
|
+
*
|
|
14
|
+
* Not a prompt section: the recorded prompt must not change while the thread lives, and the route
|
|
15
|
+
* does. Mounted on the root it tells every thread; mounted through `thread.ctx` it tells that thread
|
|
16
|
+
* only.
|
|
17
|
+
*/
|
|
18
|
+
export declare const routeContext: Plugin.Object<undefined>;
|
|
19
|
+
/** What a thread is told: its route, and the one it replaces when the model can still see another. */
|
|
20
|
+
export declare function renderRouteNotice(route: ModelRoute, told: ModelRoute | null): string;
|
|
21
|
+
/** A route as a model reads it; an effort of `null` is the provider's default. */
|
|
22
|
+
export declare function renderRoute(route: ModelRoute): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a,b,c}from"../chunks/TOOIB6J2.js";import"../chunks/DRYAN665.js";import"../chunks/2OSESBIL.js";import"../chunks/YLNJXQ3Z.js";import"../chunks/DDANMY45.js";import"../chunks/37YOGDGY.js";import"../chunks/KESCTXGO.js";import"../chunks/TYTQRLTX.js";import"../chunks/D7E6EWIE.js";export{c as renderRoute,b as renderRouteNotice,a as routeContext};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Plugin } from '@leuduan/cordis';
|
|
2
|
+
import { type SchedulesConfig } from './service.js';
|
|
3
|
+
/**
|
|
4
|
+
* Scheduled wakes of root threads: `schedule_wake`, `list_wakes` and `cancel_wake`, registered for
|
|
5
|
+
* a grant, and `ctx.schedules` for the host (`list`, `create`, `cancel`, and `cancelRows` for a
|
|
6
|
+
* thread `cancel` that should stop them too). A wake fires once, after `in_seconds` or `at` a time,
|
|
7
|
+
* and is created only in a person's turn or by the host; it delivers its prompt as sourced user
|
|
8
|
+
* input waiting for a turn of its own, under a `fresh` cause.
|
|
9
|
+
*
|
|
10
|
+
* Its configuration is required: the `clock`, the `timeZone` a local `at` is read in, and the
|
|
11
|
+
* bounds `maxDelayMs` and `maxPendingPerThread`.
|
|
12
|
+
*
|
|
13
|
+
* Root-only. Mounted before `ctx.threads.start`, the wakes that fell due while the process was down
|
|
14
|
+
* fire inside its barrier, judged by its startup policy; mounted after, they are new causes.
|
|
15
|
+
*/
|
|
16
|
+
export declare const schedules: Plugin.Object<SchedulesConfig>;
|
|
17
|
+
export { readScheduledWake } from './record.js';
|
|
18
|
+
export type { ScheduledWake, ScheduleStatus } from './record.js';
|
|
19
|
+
export { ScheduleRefusedError } from './service.js';
|
|
20
|
+
export type { ScheduleInfo, ScheduleRequest, SchedulesConfig, SchedulesService } from './service.js';
|
|
21
|
+
export { SCHEDULE_TOOLS } from './tools.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{a as I}from"../../chunks/C5LYCXJG.js";import{a as H,d as B}from"../../chunks/J5S4URAW.js";import{a as Q}from"../../chunks/SL2YLB2F.js";import{b as Z}from"../../chunks/RK3VP2Q4.js";import"../../chunks/74HKUGRR.js";import{a as G}from"../../chunks/QMMLQJBS.js";import{a as L}from"../../chunks/YIR5MYGU.js";import{a as y,b as z}from"../../chunks/NAOUTU7A.js";import"../../chunks/UKXMCHHT.js";import{b as T}from"../../chunks/DRYAN665.js";import{d as R}from"../../chunks/2OSESBIL.js";import{G as P}from"../../chunks/YLNJXQ3Z.js";import"../../chunks/DDANMY45.js";import"../../chunks/37YOGDGY.js";import"../../chunks/KESCTXGO.js";import"../../chunks/TYTQRLTX.js";import"../../chunks/D7E6EWIE.js";import{Service as he}from"@leuduan/cordis";import{z as A}from"zod";import{z as c}from"zod";var v=c.number().int().nonnegative(),ae=c.discriminatedUnion("op",[c.strictObject({op:c.literal("created"),id:c.string().min(1),due_at:v,prompt:c.string().min(1),reason:c.string().min(1),time_zone:c.string().min(1),created_at:v,call_seq:c.number().int().positive().nullable()}),c.strictObject({op:c.literal("fired"),id:c.string().min(1),input_id:c.string().min(1)}),c.strictObject({op:c.literal("cancelled"),id:c.string().min(1),reason:c.string()})]),g=T({plugin:"lagent:schedules",kind:"schedule",version:1,schema:ae}),w=n=>n.cancelled?"cancelled":n.delivered===null?"pending":"fired",h=g.projection({key:"schedules",onFork:"reset",init:()=>new Map,apply(n,e){if(e.op==="created")return n.has(e.id)||n.set(e.id,{created:e,delivered:null,cancelled:!1}),n;let t=n.get(e.id);return t===void 0||n.set(e.id,e.op==="fired"?{...t,delivered:e.input_id}:{...t,cancelled:!0}),n}}),j=Q({key:"lagent:schedules",version:1,schema:c.strictObject({next_wake_at:v.nullable()}),applies:()=>!0,compute(n,e){let t=null;for(let r of n.state(h,e).values())w(r)==="pending"&&(t=t===null?r.created.due_at:Math.min(t,r.created.due_at));return{next_wake_at:t}}});function O(n,e){let t=j.read(n,e);return t.status==="available"?t.value.next_wake_at:null}var ce=c.strictObject({schedule_id:c.string().min(1),due_at:v,summary:c.string()}),$=T({plugin:"lagent:schedules",kind:"wake",version:1,schema:ce}),ue=n=>$.readSource(n);function J(n){try{return new Intl.DateTimeFormat("en-US",{timeZone:n}),!0}catch{return!1}}var Y=new Map;function le(n){let e=Y.get(n);return e===void 0&&(e=new Intl.DateTimeFormat("en-US",{timeZone:n,hourCycle:"h23",year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",second:"numeric"}),Y.set(n,e)),e}function M(n,e){let t={};for(let r of le(e).formatToParts(n))r.type!=="literal"&&(t[r.type]=Number(r.value));return{year:t.year,month:t.month,day:t.day,hour:t.hour,minute:t.minute,second:t.second}}function U(n,e){let t=M(n,e);return Date.UTC(t.year,t.month-1,t.day,t.hour,t.minute,t.second)-Math.floor(n/1e3)*1e3}var K=(n,e)=>n.year===e.year&&n.month===e.month&&n.day===e.day&&n.hour===e.hour&&n.minute===e.minute;function de(n,e){let t=Date.UTC(n.year,n.month-1,n.day,n.hour,n.minute),r=U(t-54e6,e),s=U(t+54e6,e),u=[...new Set([t-r,t-s])].sort((a,l)=>a-l);for(let a of u)if(K(M(a,e),n))return a;let o=Math.min(t-r,t-s),i=Math.max(t-r,t-s);for(;i-o>1e3;){let a=Math.floor((o+i)/2e3)*1e3;U(a,e)===s?i=a:o=a}return i}function V(n,e){let t=/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::(\d{2}))?(?:(Z)|([+-])(\d{2}):?(\d{2}))?$/.exec(n.trim());if(t===null)return null;let[r,s,u,o,i,a]=t.slice(1,7).map(_=>Number(_??0)),l=new Date(Date.UTC(r,s-1,u));if(l.getUTCFullYear()!==r||l.getUTCMonth()!==s-1||l.getUTCDate()!==u||o>23||i>59||a>59)return null;let[,,,,,,,d,p,S,ie]=t;if(d!==void 0||p!==void 0){let _=Number(S??0),q=Number(ie??0);if(_>14||q>59)return null;let oe=(p==="-"?-1:1)*(_*60+q)*6e4;return Date.UTC(r,s-1,u,o,i,a)-oe}let C={year:r,month:s,day:u,hour:o,minute:i},b=de(C,e);return K(M(b,e),C)?b+a*1e3:b}var X=A.number().int().positive(),me=A.strictObject({clock:H,timeZone:A.string().refine(J,"timeZone must be an IANA time zone"),maxDelayMs:X,maxPendingPerThread:X}),m=class extends Error{constructor(e){super(e),this.name="ScheduleRefusedError"}},D="Scheduled wakes are for conversations a person talks to; an agent working for another agent cannot schedule one.",fe="A scheduled wake can be created only in a turn a person started, not from a wake or a notice. Tell the person what to schedule, or ask them.",pe=n=>`sch-${n}`,ee=n=>`wake_${n}`,W=n=>n.replaceAll("&","&").replaceAll('"',""").replaceAll("<","<"),k=n=>new Date(n).toISOString().replace(".000Z","Z"),te=(n,e)=>`A scheduled wake may be due at most ${Math.round(n/6e4)} minutes from now, by ${k(e+n)}.`;function E(n,e,t){let{created:r}=e,s=e.delivered!==null&&!e.cancelled&&t.input(e.delivered).state==="queued";return{id:r.id,threadId:n,dueAt:r.due_at,timeZone:r.time_zone,prompt:r.prompt,reason:r.reason,status:w(e),unread:s,createdAt:r.created_at}}var x=class extends he{static inject=["threads","journal"];config;queue;inFlight=new Set;refreshed=Promise.resolve([]);armed=!1;retries;closed=!1;constructor(e,t){super(e,"schedules"),this.config=me.parse(t),this.queue=B(this.config.clock,r=>e.reportError(r)),this.retries=I(this.config.clock,r=>e.reportError(r)),e.effect(()=>e.journal.register(h)),e.effect(()=>e.journal.subscribe(r=>{this.armed&&g.read(r)!==void 0&&this.arm(r.thread_id)})),this.refreshed=j.register(e).refreshed,e.effect(()=>{let r=e.threads.registerOwner({owner:"lagent:schedules",repair:()=>this.catchUp()});return()=>r.dispose()}),L(e,()=>this.shutdown())}list({threadId:e}){let t=this.ctx.threads.view(e);return[...this.ctx.journal.state(h,e).values()].map(r=>E(e,r,t))}async create(e,t,r={}){let s=this.thread(e),u=r.callSeq===void 0?P("sch"):pe(r.callSeq),o=await s.read(l=>{let d=this.ctx.journal.state(h,e).get(u);if(d!==void 0)return E(e,d,l);if(s.origin!=null)throw new m(D);if(r.requirePersonTurn===!0&&!this.ctx.threads.chain(e).personTurn)throw new m(fe)});if(o!==void 0)return o;let i=this.createdRow(u,t,r.callSeq??null),{value:a}=await this.ctx.journal.transact(e,()=>{let l=this.ctx.journal.state(h,e);if(l.has(u))return{rows:[],value:null};let d=[...l.values()].filter(S=>w(S)==="pending").length;if(d>=this.config.maxPendingPerThread)return{rows:[],value:`This conversation already has ${d} scheduled wakes waiting, the most it may; cancel one with cancel_wake first.`};let p=this.config.clock.now();return i.due_at<=p?{rows:[],value:`${k(i.due_at)} has already passed; it is now ${k(p)}.`}:i.due_at>p+this.config.maxDelayMs?{rows:[],value:te(this.config.maxDelayMs,p)}:{rows:[g.entry({...i,created_at:p},{threadId:e})],value:null}});if(a!==null)throw new m(a);return s.read(l=>E(e,this.ctx.journal.state(h,e).get(u),l))}cancel(e,t,r="cancelled"){return this.track(async()=>{let s=this.thread(e);if(!await s.read(()=>this.ctx.journal.state(h,e).has(t)))throw new m(`No scheduled wake ${t} in this conversation.`);let o=await s.withdraw(ee(t),{rows:()=>this.ctx.journal.state(h,e).get(t).cancelled?[]:[g.entry({op:"cancelled",id:t,reason:r},{threadId:e})]});if(o.status==="refused")throw new Error(o.refusal.message);return{withdrawn:o.status==="withdrawn"}})}cancelRows(e,t="the conversation was stopped"){return[...this.ctx.journal.state(h,e).values()].filter(r=>w(r)==="pending").map(r=>g.entry({op:"cancelled",id:r.created.id,reason:t},{threadId:e}))}thread(e){let t=this.ctx.threads.get(e);if(t===void 0)throw new m(`No thread ${e}`);return t}createdRow(e,t,r){let{clock:s,timeZone:u,maxDelayMs:o}=this.config,i=s.now(),a=p=>{throw new m(p)};t.prompt.trim()===""&&a("A scheduled wake needs a prompt."),t.reason.trim()===""&&a("A scheduled wake needs a reason.");let{when:l}=t,d;return"in_seconds"in l?((!Number.isInteger(l.in_seconds)||l.in_seconds<1)&&a("in_seconds must be a whole number of at least 1."),d=i+l.in_seconds*1e3):(d=V(l.at,u)??a(`"${l.at}" is not a date and time such as 2026-10-11T14:30 or 2026-10-11T14:30+02:00.`),d<=i&&a(`${l.at} has already passed; it is now ${k(i)}.`)),d>i+o&&a(te(o,i)),{op:"created",id:e,due_at:d,prompt:t.prompt,reason:t.reason,time_zone:u,created_at:i,call_seq:r}}track(e){let t=e(),r=t.then(()=>{},()=>{});return this.inFlight.add(r),r.then(()=>this.inFlight.delete(r)),t}async catchUp(){try{await this.refreshed;let e=this.config.clock.now();await Promise.all(this.ctx.journal.summaries().filter(t=>{let r=O(this.ctx.journal,t.thread_id);return r!==null&&r<=e}).map(t=>this.check(t.thread_id)))}finally{this.armed=!0;for(let e of this.ctx.journal.summaries())this.arm(e.thread_id)}}arm(e){if(this.closed||this.retries.pending(e))return;let t=O(this.ctx.journal,e);t===null?this.queue.delete(e):this.queue.set(e,t,()=>{this.check(e)})}check(e){return this.track(()=>this.deliverDue(e))}async deliverDue(e){if(!this.closed)try{let t=this.ctx.threads.get(e);if(t===void 0)return;let r=this.config.clock.now(),s=await t.read(()=>[...this.ctx.journal.state(h,e).values()].filter(i=>w(i)==="pending"&&i.created.due_at<=r).map(i=>i.created.id)),o=(await Promise.allSettled(s.map(i=>this.fire(e,i)))).find(i=>i.status==="rejected");if(o!==void 0)throw o.reason;this.retries.succeeded(e),this.arm(e)}catch(t){if(this.ctx.reportError(t),this.closed)return;this.queue.delete(e),this.retries.failed(e,()=>{this.check(e)})}}async fire(e,t){if(this.closed)return;let r=this.thread(e),s=await r.read(()=>this.ctx.journal.state(h,e).get(t));if(s===void 0||w(s)!=="pending")return;let{created:u}=s,o=ee(t);await r.send({role:"user",content:we(u)},{id:o,source:$.record({schedule_id:t,due_at:u.due_at,summary:`${t} ${u.reason}`.slice(0,120)}),wake:{releases:!1,chain:"fresh"},target:"next-turn",rows:()=>{let i=this.ctx.journal.state(h,e).get(t);return i===void 0||w(i)!=="pending"?{refuse:{message:`Scheduled wake ${t} is no longer pending`}}:[g.entry({op:"fired",id:t,input_id:o},{threadId:e})]}})}async shutdown(){this.closed=!0,this.queue.dispose(),this.retries.dispose(),await Promise.allSettled([...this.inFlight])}};function we(n){return`<scheduled_wake ${[`schedule="${W(n.id)}"`,`due="${k(n.due_at)}"`,`time_zone="${W(n.time_zone)}"`,`reason="${W(n.reason)}"`].join(" ")}>
|
|
2
|
+
${n.prompt}
|
|
3
|
+
</scheduled_wake>`}import{z as f}from"zod";function N(n,e){let t=G(n.ctx,"schedules",e);if(n.ctx.threads.get(n.threadId)?.origin!=null)throw new m(D);return t}var ne=n=>`${n.id} ${n.unread?"delivered, not read yet":n.status} due ${k(n.dueAt)} (${n.timeZone}): ${n.reason}`,ge=f.strictObject({when:f.union([f.strictObject({in_seconds:f.number().int().min(1).describe("Seconds from now.")}),f.strictObject({at:f.string().describe("A date and time, such as 2026-10-11T14:30 (in the conversation\u2019s time zone) or 2026-10-11T14:30+02:00.")})]).describe("When: after in_seconds, or at a time."),prompt:f.string().min(1).describe("What you will be told when it fires: write it for yourself, then."),reason:f.string().min(1).describe("One line for the person, saying why.")}),F=y({name:"schedule_wake",description:"Schedule one wake of this conversation, after a delay or at a time. When it fires, you get its prompt as a new turn, even if nobody is here.",parameters:ge,onInterrupted:"rerun",executionMode:"exclusive",async execute(n,e){let t=await N(e,"schedule_wake").create(e.threadId,n,{callSeq:e.callSeq,requirePersonTurn:!0});return{output:`Scheduled ${ne(t)}`,metadata:{id:t.id,due_at:t.dueAt}}}}),re=y({name:"list_wakes",description:"List the scheduled wakes of this conversation still waiting to fire, and those that fired but whose message you have not read yet.",parameters:f.strictObject({}),onInterrupted:"rerun",executionMode:"parallel",execute:async(n,e)=>{let t=N(e,"list_wakes").list({threadId:e.threadId}),r=t.filter(s=>s.status==="pending"||s.unread);return{output:r.map(ne).join(`
|
|
4
|
+
`)||"No scheduled wakes waiting.",metadata:{pending:r.filter(s=>!s.unread).length,unread:r.filter(s=>s.unread).length,total:t.length}}}}),se=y({name:"cancel_wake",description:"Cancel a scheduled wake of this conversation, or its delivery still waiting to be read.",parameters:f.strictObject({id:f.string().min(1).describe("The id schedule_wake returned, such as sch-42.")}),onInterrupted:"rerun",executionMode:"exclusive",async execute({id:n},e){let{withdrawn:t}=await N(e,"cancel_wake").cancel(e.threadId,n,"cancel_wake");return{output:`Cancelled ${n}.${t?" Its waiting delivery was withdrawn.":""}`,metadata:{id:n,withdrawn:t}}}}),ke=["schedule_wake","list_wakes","cancel_wake"];var _e=["Use schedule_wake only when the person asks for something later, never to wait for what a notice will report, such as a sub-agent or a command started with notify.","A scheduled wake fires once, and can be created only in a turn the person started: never from a wake or a notice, so do not promise follow-ups you cannot schedule then.","When a wake fires you get its prompt as user input in a <scheduled_wake> frame naming its due time; compare it with the current date, since a wake waiting behind a stop is delivered late."].join(`
|
|
5
|
+
`),Ge={name:"lagent:schedules",inject:["tools","prompts","threads","journal"],async apply(n,e){R(n,"schedules"),await n.plugin(x,e);let t=[F,re,se];for(let r of t)z(n,r);Z(n,{tag:"schedules",slot:"instruction",agents:"all",render:({tools:r})=>r.some(s=>s.tool===F)?_e:null})}};export{ke as SCHEDULE_TOOLS,m as ScheduleRefusedError,ue as readScheduledWake,Ge as schedules};
|