@ap3x/agent-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +29 -0
- package/dist/agent-errors.d.ts +54 -0
- package/dist/agent-errors.d.ts.map +1 -0
- package/dist/agent-loop.d.ts +30 -0
- package/dist/agent-loop.d.ts.map +1 -0
- package/dist/agent.d.ts +160 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/backend.d.ts +67 -0
- package/dist/backend.d.ts.map +1 -0
- package/dist/compaction.d.ts +147 -0
- package/dist/compaction.d.ts.map +1 -0
- package/dist/concurrency.d.ts +32 -0
- package/dist/concurrency.d.ts.map +1 -0
- package/dist/conversation.d.ts +215 -0
- package/dist/conversation.d.ts.map +1 -0
- package/dist/env.d.ts +125 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/errors.d.ts +37 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/harness.d.ts +110 -0
- package/dist/harness.d.ts.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4153 -0
- package/dist/loader.d.ts +142 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/logger.d.ts +36 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/output-formatter.d.ts +27 -0
- package/dist/output-formatter.d.ts.map +1 -0
- package/dist/prompt-templates.d.ts +78 -0
- package/dist/prompt-templates.d.ts.map +1 -0
- package/dist/result.d.ts +26 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/serialization.d.ts +75 -0
- package/dist/serialization.d.ts.map +1 -0
- package/dist/session-repo.d.ts +90 -0
- package/dist/session-repo.d.ts.map +1 -0
- package/dist/session.d.ts +251 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/shell-blocklist.d.ts +18 -0
- package/dist/shell-blocklist.d.ts.map +1 -0
- package/dist/skills.d.ts +95 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/system-prompt.d.ts +90 -0
- package/dist/system-prompt.d.ts.map +1 -0
- package/dist/tools.d.ts +61 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/types.d.ts +320 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/uuid.d.ts +23 -0
- package/dist/uuid.d.ts.map +1 -0
- package/package.json +33 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AP3X
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# @ap3x/agent-core
|
|
2
|
+
|
|
3
|
+
The native agent runtime: a tool-calling loop, a conversation memory substrate, durable sessions, and context compaction — plus the `AgentBackend` seam orchestration builds on.
|
|
4
|
+
|
|
5
|
+
Part of [AP3X](https://github.com/AP3X-Dev/AP3X) — a TypeScript multi-agent framework.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @ap3x/agent-core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## What's inside
|
|
14
|
+
|
|
15
|
+
- **`runAgentLoop`** — the tool-calling agent loop with typed events.
|
|
16
|
+
- **`Conversation`** — the append-only transcript every orchestrator reads and writes, with JSON/YAML persistence, token-budget management, and durable memory files.
|
|
17
|
+
- **Compaction** — automatic context compaction with summary threading across runs.
|
|
18
|
+
- **`defineTool`** — explicit TypeBox parameter schemas; no runtime reflection.
|
|
19
|
+
- **Sessions** — durable session storage with resume and fork.
|
|
20
|
+
- **`AgentBackend`** — the interface orchestration depends on, so runtimes stay swappable.
|
|
21
|
+
- **Typed errors** — a single `AgentError` hierarchy with stable machine-readable codes.
|
|
22
|
+
|
|
23
|
+
## Documentation
|
|
24
|
+
|
|
25
|
+
See the [AP3X repository](https://github.com/AP3X-Dev/AP3X) for architecture notes, the full package map, and examples.
|
|
26
|
+
|
|
27
|
+
## License
|
|
28
|
+
|
|
29
|
+
MIT
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `AgentError` hierarchy.
|
|
3
|
+
*
|
|
4
|
+
* The orchestration layer (`@ap3x/swarms`) and the swarms-facing `Agent`
|
|
5
|
+
* wrapper raise these for failures that originate inside a single agent's
|
|
6
|
+
* lifecycle (initialization, LLM calls, tool execution, memory, MCP). They
|
|
7
|
+
* form one taxonomy under AP3X names and follow
|
|
8
|
+
* the same `Ap3xError` contract as the rest of the package: every error
|
|
9
|
+
* carries a stable, machine-readable `code` (and an optional `cause`).
|
|
10
|
+
*/
|
|
11
|
+
/** Stable codes for the agent error hierarchy. */
|
|
12
|
+
export type AgentErrorCode = "agent" | "agent_initialization" | "agent_run" | "agent_llm" | "agent_tool" | "agent_memory" | "agent_mcp_connection" | "agent_mcp_tool";
|
|
13
|
+
/**
|
|
14
|
+
* Base class for every agent error.
|
|
15
|
+
*
|
|
16
|
+
* This is a sibling taxonomy to {@link import("./errors").Ap3xError}: it keeps
|
|
17
|
+
* the same `code`/`cause` shape but is rooted here so the orchestration layer
|
|
18
|
+
* can `instanceof AgentError` across the whole family.
|
|
19
|
+
*/
|
|
20
|
+
export declare class AgentError extends Error {
|
|
21
|
+
/** Machine-readable, stable error code. */
|
|
22
|
+
readonly code: AgentErrorCode;
|
|
23
|
+
readonly cause?: unknown;
|
|
24
|
+
constructor(message: string, code?: AgentErrorCode, cause?: unknown);
|
|
25
|
+
}
|
|
26
|
+
/** Raised when an agent fails to construct/validate its configuration. */
|
|
27
|
+
export declare class AgentInitializationError extends AgentError {
|
|
28
|
+
constructor(message: string, cause?: unknown);
|
|
29
|
+
}
|
|
30
|
+
/** Raised when an agent's run loop fails. */
|
|
31
|
+
export declare class AgentRunError extends AgentError {
|
|
32
|
+
constructor(message: string, cause?: unknown);
|
|
33
|
+
}
|
|
34
|
+
/** Raised when the underlying LLM call fails. */
|
|
35
|
+
export declare class AgentLLMError extends AgentError {
|
|
36
|
+
constructor(message: string, cause?: unknown);
|
|
37
|
+
}
|
|
38
|
+
/** Raised when a tool invocation fails. */
|
|
39
|
+
export declare class AgentToolError extends AgentError {
|
|
40
|
+
constructor(message: string, cause?: unknown);
|
|
41
|
+
}
|
|
42
|
+
/** Raised when the agent's memory/conversation substrate fails. */
|
|
43
|
+
export declare class AgentMemoryError extends AgentError {
|
|
44
|
+
constructor(message: string, cause?: unknown);
|
|
45
|
+
}
|
|
46
|
+
/** Raised when connecting to an MCP server fails. */
|
|
47
|
+
export declare class AgentMCPConnectionError extends AgentError {
|
|
48
|
+
constructor(message: string, cause?: unknown);
|
|
49
|
+
}
|
|
50
|
+
/** Raised when executing a tool served over MCP fails. */
|
|
51
|
+
export declare class AgentMCPToolError extends AgentError {
|
|
52
|
+
constructor(message: string, cause?: unknown);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=agent-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-errors.d.ts","sourceRoot":"","sources":["../src/agent-errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,kDAAkD;AAClD,MAAM,MAAM,cAAc,GACtB,OAAO,GACP,sBAAsB,GACtB,WAAW,GACX,WAAW,GACX,YAAY,GACZ,cAAc,GACd,sBAAsB,GACtB,gBAAgB,CAAC;AAErB;;;;;;GAMG;AACH,qBAAa,UAAW,SAAQ,KAAK;IACnC,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,SAAkB,KAAK,CAAC,EAAE,OAAO,CAAC;gBAEtB,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,cAAwB,EAAE,KAAK,CAAC,EAAE,OAAO;CAM7E;AAED,0EAA0E;AAC1E,qBAAa,wBAAyB,SAAQ,UAAU;gBAC1C,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAG7C;AAED,6CAA6C;AAC7C,qBAAa,aAAc,SAAQ,UAAU;gBAC/B,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAG7C;AAED,iDAAiD;AACjD,qBAAa,aAAc,SAAQ,UAAU;gBAC/B,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAG7C;AAED,2CAA2C;AAC3C,qBAAa,cAAe,SAAQ,UAAU;gBAChC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAG7C;AAED,mEAAmE;AACnE,qBAAa,gBAAiB,SAAQ,UAAU;gBAClC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAG7C;AAED,qDAAqD;AACrD,qBAAa,uBAAwB,SAAQ,UAAU;gBACzC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAG7C;AAED,0DAA0D;AAC1D,qBAAa,iBAAkB,SAAQ,UAAU;gBACnC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAG7C"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { AgentContext, AgentEvent, AgentEventSink, AgentLoopConfig, AgentMessage } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Default assistant-turn cap. Deliberately high (not `10`) so legitimate long
|
|
4
|
+
* tool runs are never silently truncated — while still bounding a runaway model
|
|
5
|
+
* against a true infinite loop. Callers can set a low `maxLoops` to cap
|
|
6
|
+
* explicitly, or `Infinity` to disable the guard entirely.
|
|
7
|
+
*/
|
|
8
|
+
export declare const DEFAULT_MAX_LOOPS = 1000;
|
|
9
|
+
/**
|
|
10
|
+
* Run the turn cycle starting from a set of new prompt messages. Emits the full
|
|
11
|
+
* lifecycle and returns every NEW message produced (prompts + assistant turns +
|
|
12
|
+
* tool results). The loop stops when an assistant turn requests no tools, when
|
|
13
|
+
* a tool batch terminates, on an error/aborted stop reason, or at `maxLoops`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function runAgentLoop(prompts: AgentMessage[], context: AgentContext, config: AgentLoopConfig, emit: AgentEventSink, signal?: AbortSignal): Promise<AgentMessage[]>;
|
|
16
|
+
/**
|
|
17
|
+
* Continue the loop from an existing context without injecting a new prompt.
|
|
18
|
+
* The last message must not be an assistant message (after a turn that produced
|
|
19
|
+
* tool results, the tail is a `toolResult`, which is a valid continuation).
|
|
20
|
+
*/
|
|
21
|
+
export declare function runAgentLoopContinue(context: AgentContext, config: AgentLoopConfig, emit: AgentEventSink, signal?: AbortSignal): Promise<AgentMessage[]>;
|
|
22
|
+
/** A streamed view of a loop run: iterate {@link AgentEvent}s, await the result. */
|
|
23
|
+
export interface AgentEventStream extends AsyncIterable<AgentEvent> {
|
|
24
|
+
result(): Promise<AgentMessage[]>;
|
|
25
|
+
}
|
|
26
|
+
/** Streaming wrapper over {@link runAgentLoop}. */
|
|
27
|
+
export declare function agentLoop(prompts: AgentMessage[], context: AgentContext, config: AgentLoopConfig, signal?: AbortSignal): AgentEventStream;
|
|
28
|
+
/** Streaming wrapper over {@link runAgentLoopContinue}, validated eagerly. */
|
|
29
|
+
export declare function agentLoopContinue(context: AgentContext, config: AgentLoopConfig, signal?: AbortSignal): AgentEventStream;
|
|
30
|
+
//# sourceMappingURL=agent-loop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-loop.d.ts","sourceRoot":"","sources":["../src/agent-loop.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,cAAc,EACd,eAAe,EACf,YAAY,EAEb,MAAM,SAAS,CAAC;AAEjB;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AA6ItC;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,YAAY,EAAE,EACvB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,cAAc,EACpB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,YAAY,EAAE,CAAC,CA+RzB;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,cAAc,EACpB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,YAAY,EAAE,CAAC,CAOzB;AAED,oFAAoF;AACpF,MAAM,WAAW,gBAAiB,SAAQ,aAAa,CAAC,UAAU,CAAC;IACjE,MAAM,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;CACnC;AAwCD,mDAAmD;AACnD,wBAAgB,SAAS,CACvB,OAAO,EAAE,YAAY,EAAE,EACvB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,MAAM,CAAC,EAAE,WAAW,GACnB,gBAAgB,CAElB;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,MAAM,CAAC,EAAE,WAAW,GACnB,gBAAgB,CAOlB"}
|
package/dist/agent.d.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import type { AssistantMessage, Model, SimpleStreamOptions, Usage } from "@ap3x/ai";
|
|
2
|
+
import type { AgentEvent, AgentHooks, AgentMessage, AnyAgentTool, StreamFn, ThinkingLevel } from "./types";
|
|
3
|
+
/** A live subscriber to {@link Agent} events; receives the run's abort signal. */
|
|
4
|
+
export type AgentListener = (event: AgentEvent, signal: AbortSignal) => void | Promise<void>;
|
|
5
|
+
/** Construction options for a stateful {@link Agent}. */
|
|
6
|
+
export interface AgentOptions {
|
|
7
|
+
model: Model<string>;
|
|
8
|
+
systemPrompt?: string;
|
|
9
|
+
tools?: AnyAgentTool[];
|
|
10
|
+
reasoning?: Exclude<ThinkingLevel, "off">;
|
|
11
|
+
/**
|
|
12
|
+
* Initial transcript to seed the agent with. Seeds are CONTEXT-ONLY: the
|
|
13
|
+
* model sees them, but session-backed hosts ({@link AgentHarness#prompt},
|
|
14
|
+
* the CLI) persist only turn-PRODUCED messages, so a session resumed later
|
|
15
|
+
* reconstructs WITHOUT the seed. This is deliberate — resume paths seed
|
|
16
|
+
* `messages` from the session's own `buildContext()`, and persisting seeds
|
|
17
|
+
* would re-append the entire history to the session on every resume.
|
|
18
|
+
* Callers who want a seed to be durable must append it to the session
|
|
19
|
+
* themselves before prompting. (B21)
|
|
20
|
+
*/
|
|
21
|
+
messages?: AgentMessage[];
|
|
22
|
+
maxLoops?: number;
|
|
23
|
+
toolExecution?: "sequential" | "parallel";
|
|
24
|
+
streamOptions?: SimpleStreamOptions;
|
|
25
|
+
hooks?: AgentHooks;
|
|
26
|
+
streamFn?: StreamFn;
|
|
27
|
+
sessionId?: string;
|
|
28
|
+
/** Auto-compact context when it nears the window. Default: enabled. */
|
|
29
|
+
autoCompact?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Summary of a prior compaction (e.g. from the session this agent was seeded
|
|
32
|
+
* from). Threads into the loop so the next compaction merges into it instead
|
|
33
|
+
* of summarizing blind. Kept current across runs from `compaction` events.
|
|
34
|
+
*/
|
|
35
|
+
previousSummary?: string;
|
|
36
|
+
}
|
|
37
|
+
/** Public, read-only snapshot of an agent's current state. */
|
|
38
|
+
export interface AgentState {
|
|
39
|
+
systemPrompt?: string;
|
|
40
|
+
model: Model<string>;
|
|
41
|
+
/** A copy of the current transcript. */
|
|
42
|
+
messages: AgentMessage[];
|
|
43
|
+
/** A copy of the registered tools. */
|
|
44
|
+
tools: AnyAgentTool[];
|
|
45
|
+
isRunning: boolean;
|
|
46
|
+
errorMessage?: string;
|
|
47
|
+
}
|
|
48
|
+
/** Concatenate the text blocks of an assistant message into a single string. */
|
|
49
|
+
export declare function finalTextOf(message: AssistantMessage | undefined): string;
|
|
50
|
+
/** The last assistant message in a transcript, if any. */
|
|
51
|
+
export declare function lastAssistant(messages: AgentMessage[]): AssistantMessage | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* A stateful agent that owns a transcript and a single active run at a time.
|
|
54
|
+
* `prompt()` appends a user message and drives the loop to completion;
|
|
55
|
+
* `continue()` resumes from the current transcript without a new prompt.
|
|
56
|
+
*/
|
|
57
|
+
export declare class Agent {
|
|
58
|
+
model: Model<string>;
|
|
59
|
+
systemPrompt?: string;
|
|
60
|
+
reasoning?: Exclude<ThinkingLevel, "off">;
|
|
61
|
+
maxLoops?: number;
|
|
62
|
+
toolExecution: "sequential" | "parallel";
|
|
63
|
+
streamOptions?: SimpleStreamOptions;
|
|
64
|
+
hooks: AgentHooks;
|
|
65
|
+
streamFn?: StreamFn;
|
|
66
|
+
sessionId?: string;
|
|
67
|
+
autoCompact?: boolean;
|
|
68
|
+
previousSummary?: string;
|
|
69
|
+
private toolList;
|
|
70
|
+
private transcript;
|
|
71
|
+
private running;
|
|
72
|
+
private controller?;
|
|
73
|
+
private lastError?;
|
|
74
|
+
private readonly listeners;
|
|
75
|
+
/**
|
|
76
|
+
* One shared FIFO of pending host-queued messages, each tagged with its
|
|
77
|
+
* {@link QueueMode}. `steer`-mode entries drain at each turn boundary
|
|
78
|
+
* (mid-run injection); everything left — `followUp`, `nextTurn`, and any
|
|
79
|
+
* late `steer` — drains when the run would otherwise stop (the rescue).
|
|
80
|
+
* JS is single-threaded, so enqueue is a plain push and drain is a plain
|
|
81
|
+
* splice at a loop boundary: no locking, no lost update.
|
|
82
|
+
*/
|
|
83
|
+
private pending;
|
|
84
|
+
/** A never-aborted signal handed to listeners for out-of-run queue events. */
|
|
85
|
+
private readonly idleSignal;
|
|
86
|
+
constructor(options: AgentOptions);
|
|
87
|
+
/** A defensive snapshot of the agent's state. */
|
|
88
|
+
get state(): AgentState;
|
|
89
|
+
/** Whether a run is in progress. */
|
|
90
|
+
get isRunning(): boolean;
|
|
91
|
+
/** The abort signal of the active run, if any. */
|
|
92
|
+
get signal(): AbortSignal | undefined;
|
|
93
|
+
/** The full transcript (a copy). */
|
|
94
|
+
get messages(): AgentMessage[];
|
|
95
|
+
/** The registered tools (a copy). Setting replaces the list with a copy. */
|
|
96
|
+
get tools(): AnyAgentTool[];
|
|
97
|
+
set tools(tools: AnyAgentTool[]);
|
|
98
|
+
/** Register an event listener. Returns an unsubscribe function. */
|
|
99
|
+
subscribe(listener: AgentListener): () => void;
|
|
100
|
+
/**
|
|
101
|
+
* Queue a steering message. During a live run it is injected at the next turn
|
|
102
|
+
* boundary (before the next assistant turn streams); a steer queued during the
|
|
103
|
+
* final turn is rescued into the follow-up drain so it still extends the run.
|
|
104
|
+
* While idle it rides into the next run's first turn. Safe to call any time.
|
|
105
|
+
*/
|
|
106
|
+
steer(message: AgentMessage): void;
|
|
107
|
+
/** Queue a follow-up message that extends the run once it would otherwise stop. */
|
|
108
|
+
followUp(message: AgentMessage): void;
|
|
109
|
+
/**
|
|
110
|
+
* Queue a next-turn message. At the Agent level this shares the follow-up
|
|
111
|
+
* drain (delivered when the run would stop); the mode tag is preserved on
|
|
112
|
+
* `queue_update` so a host/harness can apply richer next-prompt semantics.
|
|
113
|
+
*/
|
|
114
|
+
nextTurn(message: AgentMessage): void;
|
|
115
|
+
/**
|
|
116
|
+
* Move every pending host-queued message (steer/followUp/nextTurn, in queue
|
|
117
|
+
* order, mode tags intact) from `source` into this agent's queue. Used when a
|
|
118
|
+
* host replaces its agent mid-conversation (e.g. a compaction reseed) so
|
|
119
|
+
* messages queued while idle survive the rebuild instead of being dropped.
|
|
120
|
+
*/
|
|
121
|
+
adoptPendingFrom(source: Agent): void;
|
|
122
|
+
/** Abort the active run, if any. */
|
|
123
|
+
abort(): void;
|
|
124
|
+
/** Clear the transcript and any error state. Rejects while running. */
|
|
125
|
+
reset(): void;
|
|
126
|
+
/**
|
|
127
|
+
* Append a user prompt and run the loop to completion. Returns the final
|
|
128
|
+
* assistant message. Throws {@link AgentHarnessError} `busy` if already running.
|
|
129
|
+
*/
|
|
130
|
+
prompt(input: string | AgentMessage | AgentMessage[]): Promise<AssistantMessage>;
|
|
131
|
+
/** Continue the loop from the current transcript with no new prompt. */
|
|
132
|
+
continue(): Promise<AssistantMessage>;
|
|
133
|
+
private normalizePrompts;
|
|
134
|
+
private currentContext;
|
|
135
|
+
private currentConfig;
|
|
136
|
+
/**
|
|
137
|
+
* Wire the shared pending queue into the loop's two drain hooks, COMPOSED
|
|
138
|
+
* with any user-supplied hooks (never clobbered): the queue is drained first,
|
|
139
|
+
* then the user's hook is consulted and appended. `getSteeringMessages`
|
|
140
|
+
* drains `steer`-mode entries (mid-run inject); `getFollowUpMessages` drains
|
|
141
|
+
* everything left — `followUp`, `nextTurn`, and any late `steer` (the rescue).
|
|
142
|
+
* When the queue is empty and the user set no hook, each returns `[]`, which
|
|
143
|
+
* the loop treats identically to an absent hook (byte-identical no-queue path).
|
|
144
|
+
*/
|
|
145
|
+
private composedHooks;
|
|
146
|
+
/** Enqueue a pending message and notify observers via `queue_update`. */
|
|
147
|
+
private enqueue;
|
|
148
|
+
/** Remove and return (in FIFO order) the messages whose mode matches. */
|
|
149
|
+
private drainQueue;
|
|
150
|
+
/**
|
|
151
|
+
* Emit a `queue_update` snapshot to every listener. Best-effort and
|
|
152
|
+
* out-of-band: a failing observer is isolated so it can neither break an
|
|
153
|
+
* enqueue nor the active run. Uses the active run's signal when running, else
|
|
154
|
+
* a never-aborted idle signal.
|
|
155
|
+
*/
|
|
156
|
+
private emitQueueUpdate;
|
|
157
|
+
private runWithLifecycle;
|
|
158
|
+
}
|
|
159
|
+
export type { Usage };
|
|
160
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Model } from "@ap3x/ai";
|
|
2
|
+
import { type AgentOptions } from "./agent";
|
|
3
|
+
import { type AgentEventStream } from "./agent-loop";
|
|
4
|
+
import type { AgentEvent, AgentMessage, StopReason, Usage } from "./types";
|
|
5
|
+
/** Per-run options accepted by an {@link AgentBackend}. */
|
|
6
|
+
export interface AgentRunOptions {
|
|
7
|
+
signal?: AbortSignal;
|
|
8
|
+
}
|
|
9
|
+
/** The uniform result every backend returns from a `run()`. */
|
|
10
|
+
export interface AgentRunResult {
|
|
11
|
+
/** All NEW messages produced by the run (prompts + assistant turns + tool results). */
|
|
12
|
+
messages: AgentMessage[];
|
|
13
|
+
/** Concatenated text of the final assistant message. */
|
|
14
|
+
finalText: string;
|
|
15
|
+
/** Usage of the final assistant message. */
|
|
16
|
+
usage: Usage;
|
|
17
|
+
/** Why the run stopped. */
|
|
18
|
+
stopReason: StopReason;
|
|
19
|
+
/** Present when the run failed. */
|
|
20
|
+
errorMessage?: string;
|
|
21
|
+
}
|
|
22
|
+
/** Optional capabilities a backend can advertise via {@link AgentBackend.supports}. */
|
|
23
|
+
export type BackendCapability = "stream" | "subscribe" | "abort" | "clone" | "tools";
|
|
24
|
+
/**
|
|
25
|
+
* The load-bearing seam between AP3X orchestration and any agent runtime. The
|
|
26
|
+
* only required method is `run`; the rest are optional so simple backends can
|
|
27
|
+
* be tiny while richer ones expose streaming, eventing and cloning.
|
|
28
|
+
*/
|
|
29
|
+
export interface AgentBackend {
|
|
30
|
+
run(task: string | AgentMessage[], opts?: AgentRunOptions): Promise<AgentRunResult>;
|
|
31
|
+
runStream?(task: string | AgentMessage[], opts?: AgentRunOptions): AgentEventStream;
|
|
32
|
+
subscribe?(listener: (event: AgentEvent) => void | Promise<void>): () => void;
|
|
33
|
+
abort?(): void;
|
|
34
|
+
clone?(): AgentBackend;
|
|
35
|
+
supports?(capability: BackendCapability): boolean;
|
|
36
|
+
getCurrentModel?(): Model<string>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The AP3X-native default backend. By default each `run()` is *ephemeral*: it
|
|
40
|
+
* spins up a fresh {@link Agent} over a snapshot of the configured transcript so
|
|
41
|
+
* concurrent runs don't share state. Pass `{ ephemeral: false }` to keep a
|
|
42
|
+
* single stateful agent across runs.
|
|
43
|
+
*/
|
|
44
|
+
export declare class Ap3xRuntimeBackend implements AgentBackend {
|
|
45
|
+
private readonly options;
|
|
46
|
+
private readonly ephemeral;
|
|
47
|
+
private stateful?;
|
|
48
|
+
private active?;
|
|
49
|
+
private readonly listeners;
|
|
50
|
+
constructor(options: AgentOptions & {
|
|
51
|
+
ephemeral?: boolean;
|
|
52
|
+
});
|
|
53
|
+
private newAgent;
|
|
54
|
+
private agentFor;
|
|
55
|
+
run(task: string | AgentMessage[], opts?: AgentRunOptions): Promise<AgentRunResult>;
|
|
56
|
+
runStream(task: string | AgentMessage[], opts?: AgentRunOptions): AgentEventStream;
|
|
57
|
+
subscribe(listener: (event: AgentEvent) => void | Promise<void>): () => void;
|
|
58
|
+
abort(): void;
|
|
59
|
+
clone(): AgentBackend;
|
|
60
|
+
supports(capability: BackendCapability): boolean;
|
|
61
|
+
getCurrentModel(): Model<string>;
|
|
62
|
+
}
|
|
63
|
+
/** Convenience factory mirroring the {@link Ap3xRuntimeBackend} constructor. */
|
|
64
|
+
export declare function createRuntimeBackend(options: AgentOptions & {
|
|
65
|
+
ephemeral?: boolean;
|
|
66
|
+
}): AgentBackend;
|
|
67
|
+
//# sourceMappingURL=backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAS,KAAK,YAAY,EAA8B,MAAM,SAAS,CAAC;AAC/E,OAAO,EAAE,KAAK,gBAAgB,EAAa,MAAM,cAAc,CAAC;AAEhE,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAE3E,2DAA2D;AAC3D,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,uFAAuF;IACvF,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,KAAK,EAAE,KAAK,CAAC;IACb,2BAA2B;IAC3B,UAAU,EAAE,UAAU,CAAC;IACvB,mCAAmC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,uFAAuF;AACvF,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAErF;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACpF,SAAS,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,gBAAgB,CAAC;IACpF,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC;IAC9E,KAAK,CAAC,IAAI,IAAI,CAAC;IACf,KAAK,CAAC,IAAI,YAAY,CAAC;IACvB,QAAQ,CAAC,CAAC,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAClD,eAAe,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;CACnC;AA6BD;;;;;GAKG;AACH,qBAAa,kBAAmB,YAAW,YAAY;IACrD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAU;IACpC,OAAO,CAAC,QAAQ,CAAC,CAAQ;IACzB,OAAO,CAAC,MAAM,CAAC,CAAQ;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0D;gBAExE,OAAO,EAAE,YAAY,GAAG;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE;IAM3D,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,QAAQ;IAMV,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAkCzF,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,gBAAgB;IA8BlF,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI;IAO5E,KAAK,IAAI,IAAI;IAIb,KAAK,IAAI,YAAY;IAIrB,QAAQ,CAAC,UAAU,EAAE,iBAAiB,GAAG,OAAO;IAchD,eAAe,IAAI,KAAK,CAAC,MAAM,CAAC;CAGjC;AAED,gFAAgF;AAChF,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,YAAY,GAAG;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAC9C,YAAY,CAEd"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { AssistantMessage, Context, Model, SimpleStreamOptions } from "@ap3x/ai";
|
|
2
|
+
import { CompactionError } from "./errors";
|
|
3
|
+
import { type Result } from "./result";
|
|
4
|
+
import type { AgentMessage, ThinkingLevel } from "./types";
|
|
5
|
+
/** Tunables that govern when and how aggressively context is compacted. */
|
|
6
|
+
export interface CompactionSettings {
|
|
7
|
+
enabled: boolean;
|
|
8
|
+
/** Tokens kept in reserve below the context window before compacting. */
|
|
9
|
+
reserveTokens: number;
|
|
10
|
+
/** Tokens of recent history to preserve uncompacted. */
|
|
11
|
+
keepRecentTokens: number;
|
|
12
|
+
}
|
|
13
|
+
export declare const DEFAULT_COMPACTION_SETTINGS: CompactionSettings;
|
|
14
|
+
/** Fractions of the context window that cap the fixed token levers on small models. */
|
|
15
|
+
export declare const RESERVE_FRACTION = 0.15;
|
|
16
|
+
export declare const KEEP_RECENT_FRACTION = 0.25;
|
|
17
|
+
/**
|
|
18
|
+
* Clamp the fixed token levers to a fraction of the model's context window, so
|
|
19
|
+
* compaction stays possible on a small model. `reserveTokens`/`keepRecentTokens`
|
|
20
|
+
* are sized for large windows; left unscaled they push `compactionTier`'s
|
|
21
|
+
* post-swap floor above the line, so both tiers return "none" and compaction is
|
|
22
|
+
* silently inert on any window below ~49,491. Never raises a lever above its
|
|
23
|
+
* configured value, so any window >= 109,227 resolves byte-identically to the
|
|
24
|
+
* settings it was given. Pure: no wall-clock, no RNG. Guards a non-positive
|
|
25
|
+
* window by returning the settings unchanged.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveCompactionSettings(settings: CompactionSettings, contextWindow: number): CompactionSettings;
|
|
28
|
+
/**
|
|
29
|
+
* Resolve an `autoCompact` option to compaction settings: `false` disables
|
|
30
|
+
* compaction, `true`/`undefined` use the defaults.
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveAutoCompact(autoCompact?: boolean): CompactionSettings;
|
|
33
|
+
/** System prompt used when asking the model to summarize prior context. */
|
|
34
|
+
export declare const SUMMARIZATION_SYSTEM_PROMPT: string;
|
|
35
|
+
/**
|
|
36
|
+
* Inflation applied to an estimate that has NO provider usage anchor. Plain
|
|
37
|
+
* chars/4 under-counts tool-call/JSON overhead and multibyte text, so a
|
|
38
|
+
* seeded/replayed transcript (the resume path) can read low and let the HARD
|
|
39
|
+
* line fire late — a provider rejection. With no ground truth we err high
|
|
40
|
+
* (~3.2 chars/token): the worst case of over-estimating is one early,
|
|
41
|
+
* overlapped SOFT summary call. Anchored estimates are exact provider counts
|
|
42
|
+
* and are never inflated.
|
|
43
|
+
*/
|
|
44
|
+
export declare const NO_ANCHOR_INFLATION = 1.25;
|
|
45
|
+
/** Estimate the token cost of a single message (chars/4, images flat-rated). */
|
|
46
|
+
export declare function estimateMessageTokens(message: AgentMessage): number;
|
|
47
|
+
/**
|
|
48
|
+
* Estimate the token usage of a context. Prefers the provider-reported
|
|
49
|
+
* `usage.totalTokens` of the last successful assistant message, then adds a
|
|
50
|
+
* chars/4 estimate for every message after that point.
|
|
51
|
+
*
|
|
52
|
+
* `anchorFromIndex` restricts which assistants may anchor: only those at index
|
|
53
|
+
* >= the floor are eligible. After a compaction swap, every retained assistant's
|
|
54
|
+
* `totalTokens` still describes the OLD (uncompacted) context, so the loop
|
|
55
|
+
* passes the post-swap length as the floor; until a fresh post-swap assistant
|
|
56
|
+
* lands, the estimate falls back to the anchor-free chars/4 sum, inflated by
|
|
57
|
+
* {@link NO_ANCHOR_INFLATION}. Default 0 is byte-identical to the historical
|
|
58
|
+
* behavior for anchored contexts.
|
|
59
|
+
*/
|
|
60
|
+
export declare function estimateContextTokens(messages: AgentMessage[], anchorFromIndex?: number): number;
|
|
61
|
+
/** Whether the context is large enough to warrant compaction. */
|
|
62
|
+
export declare function shouldCompact(contextTokens: number, contextWindow: number, settings?: CompactionSettings): boolean;
|
|
63
|
+
/** Fraction of the window at which a background (speculative) compaction starts. */
|
|
64
|
+
export declare const SOFT_FRACTION = 0.6;
|
|
65
|
+
/** Fraction of the window at which a blocking (emergency) compaction is required. */
|
|
66
|
+
export declare const HARD_FRACTION = 0.85;
|
|
67
|
+
/** The compaction urgency for a usage estimate: none, background, or emergency. */
|
|
68
|
+
export type CompactionTier = "none" | "soft" | "hard";
|
|
69
|
+
/**
|
|
70
|
+
* Decide the compaction tier for a usage estimate. Pure: no wall-clock, no RNG.
|
|
71
|
+
* HARD reuses `shouldCompact` as its reserve-line term — its first live call
|
|
72
|
+
* site — while `usage > HARD_FRACTION*window` adds large-window scaling. Each
|
|
73
|
+
* tier is gated on whether compaction can actually drop usage below the line:
|
|
74
|
+
* the post-swap floor is the kept recent tail plus the largest possible summary
|
|
75
|
+
* (`summaryMaxTokens` caps generation at 0.8*reserveTokens). If a swap cannot get
|
|
76
|
+
* under the line it would just re-trigger every turn, so we return "none" instead
|
|
77
|
+
* — killing perpetual per-turn summarization on small windows.
|
|
78
|
+
*/
|
|
79
|
+
export declare function compactionTier(usage: number, contextWindow: number, settings: CompactionSettings): CompactionTier;
|
|
80
|
+
export interface CutPointResult {
|
|
81
|
+
/** Index into `messages` where the kept (recent) tail begins. */
|
|
82
|
+
cutIndex: number;
|
|
83
|
+
/** Estimated tokens of the kept tail. */
|
|
84
|
+
keptTokens: number;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Walk backward from the end accumulating tokens until `keepRecentTokens` is
|
|
88
|
+
* reached, then snap the cut to a turn boundary (a user or assistant message)
|
|
89
|
+
* so a tool result is never separated from the assistant turn that produced it.
|
|
90
|
+
*/
|
|
91
|
+
export declare function findCutPoint(messages: AgentMessage[], keepRecentTokens: number): CutPointResult;
|
|
92
|
+
export interface CompactionResult {
|
|
93
|
+
summary: string;
|
|
94
|
+
/** The messages kept after the cut, ready to follow the summary. */
|
|
95
|
+
keptMessages: AgentMessage[];
|
|
96
|
+
tokensBefore: number;
|
|
97
|
+
/** Files read (and not later modified) across the compacted history. */
|
|
98
|
+
readFiles: string[];
|
|
99
|
+
/** Files written or edited across the compacted history. */
|
|
100
|
+
modifiedFiles: string[];
|
|
101
|
+
}
|
|
102
|
+
/** Prepared slices for a compaction run, independent of any LLM call. */
|
|
103
|
+
export interface CompactionPreparation {
|
|
104
|
+
/** History summarized into the main summary (before any split turn). */
|
|
105
|
+
historyMessages: AgentMessage[];
|
|
106
|
+
/** Prefix of a turn split by the cut, summarized separately (empty if none). */
|
|
107
|
+
turnPrefixMessages: AgentMessage[];
|
|
108
|
+
/** Messages kept uncompacted after the cut. */
|
|
109
|
+
keptMessages: AgentMessage[];
|
|
110
|
+
/** Whether the cut lands inside a turn (kept tail starts mid-turn). */
|
|
111
|
+
isSplitTurn: boolean;
|
|
112
|
+
/** Estimated context tokens before compaction. */
|
|
113
|
+
tokensBefore: number;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Compute the cut point and the history / split-turn-prefix / kept slices for a
|
|
117
|
+
* message list. Pure: makes no LLM call. When the cut lands on an assistant
|
|
118
|
+
* message whose originating user turn is in the summarized history, the turn is
|
|
119
|
+
* "split" and its prefix is summarized separately from the older history.
|
|
120
|
+
*/
|
|
121
|
+
export declare function prepareCompaction(messages: AgentMessage[], settings?: CompactionSettings): CompactionPreparation;
|
|
122
|
+
/** Injectable summary-generation call; defaults to `@ap3x/ai` `completeSimple`. */
|
|
123
|
+
type CompleteFn = (model: Model<string>, context: Context, options?: SimpleStreamOptions) => Promise<AssistantMessage>;
|
|
124
|
+
/**
|
|
125
|
+
* Summarize the older portion of a context and return the summary plus the
|
|
126
|
+
* recent tail. Uses the provider's `completeSimple` (overridable for tests via
|
|
127
|
+
* `options.complete`) with the summarization prompt. Deepens the base
|
|
128
|
+
* single-shot behavior with:
|
|
129
|
+
* - iterative merge into a `previousSummary` (UPDATE_SUMMARIZATION),
|
|
130
|
+
* - separate summarization of a split turn's prefix,
|
|
131
|
+
* - a maxTokens cap (and reasoning support) on the generation call,
|
|
132
|
+
* - read/modified file-operation tracking carried on the result + summary.
|
|
133
|
+
* Returns a {@link CompactionError} on failure rather than throwing.
|
|
134
|
+
*/
|
|
135
|
+
export declare function compact(messages: AgentMessage[], model: Model<string>, options?: {
|
|
136
|
+
settings?: CompactionSettings;
|
|
137
|
+
customInstructions?: string;
|
|
138
|
+
signal?: AbortSignal;
|
|
139
|
+
/** Previous compaction summary to merge into rather than regenerate. */
|
|
140
|
+
previousSummary?: string;
|
|
141
|
+
/** Reasoning level forwarded to the generation call when the model supports it. */
|
|
142
|
+
thinkingLevel?: ThinkingLevel;
|
|
143
|
+
/** Override for the summary-generation call (test seam). */
|
|
144
|
+
complete?: CompleteFn;
|
|
145
|
+
}): Promise<Result<CompactionResult, CompactionError>>;
|
|
146
|
+
export {};
|
|
147
|
+
//# sourceMappingURL=compaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../src/compaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded-concurrency primitives — the single source of truth for fan-out limits.
|
|
3
|
+
*
|
|
4
|
+
* Node's single-threaded async model means parallelism over already-async work
|
|
5
|
+
* (LLM calls, tool execution) is just `Promise` concurrency. Unbounded
|
|
6
|
+
* `Promise.all` over a large collection of agent/tool work fires every task at
|
|
7
|
+
* once; this module provides a hand-rolled `pLimit`-style semaphore so at most N
|
|
8
|
+
* run concurrently, with no new dependency.
|
|
9
|
+
*
|
|
10
|
+
* Two ordering contracts are exposed:
|
|
11
|
+
* - {@link createLimiter} preserves COMPLETION semantics — `run(fn)` resolves
|
|
12
|
+
* when `fn` resolves, and callers compose ordering themselves.
|
|
13
|
+
* - {@link mapLimit} preserves INPUT order — results map back to input position
|
|
14
|
+
* regardless of completion order.
|
|
15
|
+
*/
|
|
16
|
+
/** Available logical parallelism, guarded for older Node (we target >=20). */
|
|
17
|
+
export declare function availableParallelism(): number;
|
|
18
|
+
/**
|
|
19
|
+
* A hand-rolled `pLimit`-style semaphore. `run(fn)` schedules `fn` so at most
|
|
20
|
+
* `concurrency` are in flight at once; it resolves with `fn`'s result.
|
|
21
|
+
*/
|
|
22
|
+
export declare function createLimiter(concurrency: number): <T>(fn: () => Promise<T>) => Promise<T>;
|
|
23
|
+
/**
|
|
24
|
+
* Map `fn` over `items` with at most `concurrency` calls in flight, returning
|
|
25
|
+
* results in INPUT order (results map back to input position regardless of
|
|
26
|
+
* completion order). `fn` is invoked with each item and its index.
|
|
27
|
+
*
|
|
28
|
+
* Mirrors `Promise.all(items.map(fn))` semantics: it rejects with the first
|
|
29
|
+
* rejection. Callers that need per-item error capture should catch inside `fn`.
|
|
30
|
+
*/
|
|
31
|
+
export declare function mapLimit<TItem, TResult>(items: readonly TItem[], concurrency: number, fn: (item: TItem, index: number) => Promise<TResult>): Promise<TResult[]>;
|
|
32
|
+
//# sourceMappingURL=concurrency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"concurrency.d.ts","sourceRoot":"","sources":["../src/concurrency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,8EAA8E;AAC9E,wBAAgB,oBAAoB,IAAI,MAAM,CAG7C;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,IAc3B,CAAC,EAAE,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAAC,CAczD;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EACrC,KAAK,EAAE,SAAS,KAAK,EAAE,EACvB,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GACnD,OAAO,CAAC,OAAO,EAAE,CAAC,CAGpB"}
|