@aragon-agent/core 0.2.23 → 0.2.24
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/CHANGELOG.md +8 -1
- package/dist/engine/accept-steering.d.ts +3 -0
- package/dist/engine/accept-steering.js +15 -0
- package/dist/engine/agent-loop.js +24 -32
- package/dist/engine/agent.d.ts +2 -2
- package/dist/engine/agent.js +3 -3
- package/dist/engine/steering.d.ts +8 -1
- package/dist/engine/steering.js +6 -2
- package/dist/index.d.ts +2 -1
- package/dist/types.d.ts +6 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,7 +7,14 @@ were written.
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
-
### Added
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Steering 精确接收回执。** `Agent.steer(text, id?)` 兼容原单参数调用,
|
|
13
|
+
历史接收后发出 `steering_accepted`,只确认当前批次的 ID;新增类型
|
|
14
|
+
`SteeringMessage` 和 `SteeringAcceptedEvent`,无新增运行时导出。
|
|
15
|
+
`drainSteeringItems()` 与原 `drainSteering()` 共用一个队列。
|
|
16
|
+
接收早于异步压缩,未执行工具先补齐 skipped 结果;无工具响应在结束前再次检查
|
|
17
|
+
steering,避免流式输出期间提交的消息滞留。回执仅代表历史接收,不代表回答完成。
|
|
11
18
|
|
|
12
19
|
- **Tail relief — the last rung of the compaction ladder.** `relieveTail` joins
|
|
13
20
|
the root barrel with `TailReliefOptions` and `TailReliefResult` (85 → 86
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Accept one batch atomically with respect to async work and receipt listeners. */
|
|
2
|
+
export function acceptSteering(ctx) {
|
|
3
|
+
if (ctx.signal.aborted)
|
|
4
|
+
return;
|
|
5
|
+
const items = ctx.messageQueueManager.drainSteeringItems();
|
|
6
|
+
const ids = [];
|
|
7
|
+
for (const item of items) {
|
|
8
|
+
ctx.messageManager.push({ role: 'user', content: item.text, timestamp: Date.now() });
|
|
9
|
+
if (item.id !== undefined)
|
|
10
|
+
ids.push(item.id);
|
|
11
|
+
}
|
|
12
|
+
// The entire batch must be in history before listeners can abort or enqueue more work.
|
|
13
|
+
if (ids.length > 0)
|
|
14
|
+
ctx.emit({ type: 'steering_accepted', ids });
|
|
15
|
+
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* block detection and execution.
|
|
7
7
|
*/
|
|
8
8
|
import { validateHistory } from './compaction.js';
|
|
9
|
+
import { acceptSteering } from './accept-steering.js';
|
|
9
10
|
import { estimatePromptTokens } from '../llm/output-limits.js';
|
|
10
11
|
// ---------------------------------------------------------------------------
|
|
11
12
|
// Compaction checkpoint (context-auto-compaction §3.3)
|
|
@@ -239,6 +240,21 @@ function getAssistantText(message) {
|
|
|
239
240
|
function getToolCalls(message) {
|
|
240
241
|
return message.content.filter((b) => b.type === 'tool_call');
|
|
241
242
|
}
|
|
243
|
+
/** Close the outstanding tool batch before steering creates the next user turn. */
|
|
244
|
+
function acceptToolSteering(ctx, remainingCalls) {
|
|
245
|
+
if (ctx.signal.aborted || !ctx.messageQueueManager.hasSteering())
|
|
246
|
+
return false;
|
|
247
|
+
for (const skipped of remainingCalls) {
|
|
248
|
+
ctx.messageManager.push({
|
|
249
|
+
role: 'tool_result',
|
|
250
|
+
toolCallId: skipped.toolCallId,
|
|
251
|
+
content: 'Tool execution skipped due to steering interrupt.',
|
|
252
|
+
isError: true,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
acceptSteering(ctx);
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
242
258
|
// ---------------------------------------------------------------------------
|
|
243
259
|
// runAgentLoop
|
|
244
260
|
// ---------------------------------------------------------------------------
|
|
@@ -263,14 +279,7 @@ export async function runAgentLoop(ctx) {
|
|
|
263
279
|
let overflowRecovered = false;
|
|
264
280
|
while (!ctx.signal.aborted) {
|
|
265
281
|
// ----- Steering checkpoint (before LLM call) -----
|
|
266
|
-
|
|
267
|
-
const steeringMessages = ctx.messageQueueManager.drainSteering();
|
|
268
|
-
for (const text of steeringMessages) {
|
|
269
|
-
const userMsg = { role: 'user', content: text, timestamp: Date.now() };
|
|
270
|
-
ctx.messageManager.push(userMsg);
|
|
271
|
-
}
|
|
272
|
-
// Continue to LLM call with injected steering messages.
|
|
273
|
-
}
|
|
282
|
+
acceptSteering(ctx);
|
|
274
283
|
turnIndex += 1;
|
|
275
284
|
// ----- Context pressure checkpoint (context-auto-compaction §3.3) -----
|
|
276
285
|
//
|
|
@@ -375,6 +384,8 @@ export async function runAgentLoop(ctx) {
|
|
|
375
384
|
lastUsage = usage;
|
|
376
385
|
overflowRecovered = false;
|
|
377
386
|
ctx.messageManager.push(assistantMessage);
|
|
387
|
+
if (ctx.signal.aborted)
|
|
388
|
+
break;
|
|
378
389
|
// ----- Process tool calls -----
|
|
379
390
|
const toolCalls = getToolCalls(assistantMessage);
|
|
380
391
|
const hasToolCalls = toolCalls.length > 0;
|
|
@@ -382,12 +393,7 @@ export async function runAgentLoop(ctx) {
|
|
|
382
393
|
if (hasToolCalls) {
|
|
383
394
|
// Steering checkpoint: if steering arrived during the LLM call,
|
|
384
395
|
// skip tool execution and inject steering messages instead.
|
|
385
|
-
if (ctx
|
|
386
|
-
const steeringMessages = ctx.messageQueueManager.drainSteering();
|
|
387
|
-
for (const text of steeringMessages) {
|
|
388
|
-
const userMsg = { role: 'user', content: text, timestamp: Date.now() };
|
|
389
|
-
ctx.messageManager.push(userMsg);
|
|
390
|
-
}
|
|
396
|
+
if (acceptToolSteering(ctx, toolCalls)) {
|
|
391
397
|
// Loop continues — LLM will see the steering messages.
|
|
392
398
|
continue;
|
|
393
399
|
}
|
|
@@ -396,23 +402,7 @@ export async function runAgentLoop(ctx) {
|
|
|
396
402
|
if (ctx.signal.aborted)
|
|
397
403
|
break;
|
|
398
404
|
// Check steering between individual tool executions.
|
|
399
|
-
if (ctx.
|
|
400
|
-
// Inject remaining tool results as errors so LLM knows they were skipped.
|
|
401
|
-
const remainingCalls = toolCalls.slice(toolCalls.indexOf(toolCall));
|
|
402
|
-
for (const skipped of remainingCalls) {
|
|
403
|
-
ctx.messageManager.push({
|
|
404
|
-
role: 'tool_result',
|
|
405
|
-
toolCallId: skipped.toolCallId,
|
|
406
|
-
content: 'Tool execution skipped due to steering interrupt.',
|
|
407
|
-
isError: true,
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
// Inject steering messages.
|
|
411
|
-
const steeringMessages = ctx.messageQueueManager.drainSteering();
|
|
412
|
-
for (const text of steeringMessages) {
|
|
413
|
-
const userMsg = { role: 'user', content: text, timestamp: Date.now() };
|
|
414
|
-
ctx.messageManager.push(userMsg);
|
|
415
|
-
}
|
|
405
|
+
if (acceptToolSteering(ctx, toolCalls.slice(toolCalls.indexOf(toolCall)))) {
|
|
416
406
|
steeringInterrupted = true;
|
|
417
407
|
break;
|
|
418
408
|
}
|
|
@@ -508,7 +498,9 @@ export async function runAgentLoop(ctx) {
|
|
|
508
498
|
}
|
|
509
499
|
// ----- Exit or follow-up checkpoint -----
|
|
510
500
|
if (!hasToolCalls && !hasCodeBlocks) {
|
|
511
|
-
//
|
|
501
|
+
// Give streaming and turn_end steering priority over follow-up and normal exit.
|
|
502
|
+
if (ctx.messageQueueManager.hasSteering())
|
|
503
|
+
continue;
|
|
512
504
|
if (ctx.messageQueueManager.hasFollowUp()) {
|
|
513
505
|
const followUpMessages = ctx.messageQueueManager.drainFollowUp();
|
|
514
506
|
for (const text of followUpMessages) {
|
package/dist/engine/agent.d.ts
CHANGED
|
@@ -128,8 +128,8 @@ export declare class Agent {
|
|
|
128
128
|
* @returns An unsubscribe function.
|
|
129
129
|
*/
|
|
130
130
|
subscribe(listener: AgentEventListener): () => void;
|
|
131
|
-
/**
|
|
132
|
-
steer(message: string): void;
|
|
131
|
+
/** Queue high-priority text; an optional ID is echoed only after history acceptance. */
|
|
132
|
+
steer(message: string, id?: string): void;
|
|
133
133
|
/** Queue a low-priority follow-up message (consumed after end_turn). */
|
|
134
134
|
followUp(message: string): void;
|
|
135
135
|
setModel(model: ModelRef): void;
|
package/dist/engine/agent.js
CHANGED
|
@@ -156,9 +156,9 @@ export class Agent {
|
|
|
156
156
|
// =========================================================================
|
|
157
157
|
// Message queues
|
|
158
158
|
// =========================================================================
|
|
159
|
-
/**
|
|
160
|
-
steer(message) {
|
|
161
|
-
this.messageQueueManager.pushSteering(message);
|
|
159
|
+
/** Queue high-priority text; an optional ID is echoed only after history acceptance. */
|
|
160
|
+
steer(message, id) {
|
|
161
|
+
this.messageQueueManager.pushSteering(message, id);
|
|
162
162
|
}
|
|
163
163
|
/** Queue a low-priority follow-up message (consumed after end_turn). */
|
|
164
164
|
followUp(message) {
|
|
@@ -7,13 +7,20 @@
|
|
|
7
7
|
* Follow-up messages have low priority: they are consumed only when the
|
|
8
8
|
* Agent loop would otherwise exit (end_turn with no pending work).
|
|
9
9
|
*/
|
|
10
|
+
/** Queued text with an optional host-supplied opaque receipt identifier. */
|
|
11
|
+
export interface SteeringMessage {
|
|
12
|
+
readonly text: string;
|
|
13
|
+
readonly id?: string;
|
|
14
|
+
}
|
|
10
15
|
export declare class MessageQueueManager {
|
|
11
16
|
private readonly steeringQueue;
|
|
12
17
|
private readonly followUpQueue;
|
|
13
18
|
/** Enqueue a high-priority steering message. */
|
|
14
|
-
pushSteering(message: string): void;
|
|
19
|
+
pushSteering(message: string, id?: string): void;
|
|
15
20
|
/** Drain and return all pending steering messages (empties the queue). */
|
|
16
21
|
drainSteering(): string[];
|
|
22
|
+
/** Drain all pending envelopes in FIFO order (empties the same queue). */
|
|
23
|
+
drainSteeringItems(): SteeringMessage[];
|
|
17
24
|
/** Whether there are pending steering messages. */
|
|
18
25
|
hasSteering(): boolean;
|
|
19
26
|
/** Enqueue a low-priority follow-up message. */
|
package/dist/engine/steering.js
CHANGED
|
@@ -14,11 +14,15 @@ export class MessageQueueManager {
|
|
|
14
14
|
// Steering
|
|
15
15
|
// -----------------------------------------------------------------------
|
|
16
16
|
/** Enqueue a high-priority steering message. */
|
|
17
|
-
pushSteering(message) {
|
|
18
|
-
this.steeringQueue.push(message);
|
|
17
|
+
pushSteering(message, id) {
|
|
18
|
+
this.steeringQueue.push({ text: message, ...(id !== undefined ? { id } : {}) });
|
|
19
19
|
}
|
|
20
20
|
/** Drain and return all pending steering messages (empties the queue). */
|
|
21
21
|
drainSteering() {
|
|
22
|
+
return this.drainSteeringItems().map((item) => item.text);
|
|
23
|
+
}
|
|
24
|
+
/** Drain all pending envelopes in FIFO order (empties the same queue). */
|
|
25
|
+
drainSteeringItems() {
|
|
22
26
|
return this.steeringQueue.splice(0);
|
|
23
27
|
}
|
|
24
28
|
/** Whether there are pending steering messages. */
|
package/dist/index.d.ts
CHANGED
|
@@ -41,13 +41,14 @@ export { createSkillFindTool } from './skills/skill-find-tool.js';
|
|
|
41
41
|
export { computeToolPolicy, evaluateToolCall } from './skills/tool-policy.js';
|
|
42
42
|
export { SKILL_CATALOG_MAX_BYTES, SKILL_BODY_MAX_BYTES, SKILL_RESULT_MAX_BYTES, ALWAYS_SKILLS_MAX_BYTES, SKILL_MD_MAX_BYTES, SKILL_DESC_LINE_MAX, SKILL_FILES_MAX, SKILL_FIND_MAX_BYTES, SKILL_NAME_PATTERN, } from './skills/constants.js';
|
|
43
43
|
export type { SkillScope, SkillActivation, SkillFrontmatter, SkillRecord, SkillFileRef, SkillHost, SkillManifest, SkillValidationIssue, SkillCatalogOptions, SkillBodyOptions, SkillFindOptions, SkillIntegrity, SkillUsageStat, SkillUsageMap, SkillInvocationOptions, SkillPlatform, SkillPolicyView, SkillToolPolicyMode, ToolPolicyDecision, ToolPolicyInput, ToolPolicySource, ToolPolicyVerdict, } from './skills/types.js';
|
|
44
|
-
export type { AgentEvent, AgentEventListener, AgentStartEvent, AgentEndEvent, TurnStartEvent, TurnEndEvent, MessageUpdateEvent, ToolExecutionStartEvent, ToolExecutionEndEvent, CodeExecutionStartEvent, CodeExecutionEndEvent, CompactionStartEvent, CompactionEndEvent, } from './types.js';
|
|
44
|
+
export type { AgentEvent, AgentEventListener, AgentStartEvent, AgentEndEvent, TurnStartEvent, SteeringAcceptedEvent, TurnEndEvent, MessageUpdateEvent, ToolExecutionStartEvent, ToolExecutionEndEvent, CodeExecutionStartEvent, CodeExecutionEndEvent, CompactionStartEvent, CompactionEndEvent, } from './types.js';
|
|
45
45
|
export { Agent } from './engine/agent.js';
|
|
46
46
|
export type { AgentConfig, AgentState } from './engine/agent.js';
|
|
47
47
|
export type { ModelRef } from './engine/agent-loop.js';
|
|
48
48
|
export type { CodeActSandbox, CodeActResult } from './engine/agent-loop.js';
|
|
49
49
|
export { MessageManager } from './engine/message-manager.js';
|
|
50
50
|
export { MessageQueueManager } from './engine/steering.js';
|
|
51
|
+
export type { SteeringMessage } from './engine/steering.js';
|
|
51
52
|
export { IdleWatchdog } from './engine/watchdog.js';
|
|
52
53
|
export { findSafeCutIndices, planCompaction, relieveTail, validateHistory, } from './engine/compaction.js';
|
|
53
54
|
export type { CompactionPlan, HistoryCheck, PlanCompactionOptions, TailReliefOptions, TailReliefResult, ValidateHistoryOptions, } from './engine/compaction.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -17,6 +17,11 @@ export interface AgentEndEvent {
|
|
|
17
17
|
export interface TurnStartEvent {
|
|
18
18
|
type: 'turn_start';
|
|
19
19
|
}
|
|
20
|
+
/** Text for these opaque IDs has entered history, not necessarily reached the model. */
|
|
21
|
+
export interface SteeringAcceptedEvent {
|
|
22
|
+
type: 'steering_accepted';
|
|
23
|
+
ids: readonly string[];
|
|
24
|
+
}
|
|
20
25
|
export interface TurnEndEvent {
|
|
21
26
|
type: 'turn_end';
|
|
22
27
|
message: AssistantMessage;
|
|
@@ -107,6 +112,6 @@ export interface CompactionEndEvent {
|
|
|
107
112
|
durationMs: number;
|
|
108
113
|
}
|
|
109
114
|
/** Union of all events emitted by the Agent engine. */
|
|
110
|
-
export type AgentEvent = AgentStartEvent | AgentEndEvent | TurnStartEvent | TurnEndEvent | MessageUpdateEvent | ToolExecutionStartEvent | ToolExecutionEndEvent | CodeExecutionStartEvent | CodeExecutionEndEvent | CompactionStartEvent | CompactionEndEvent;
|
|
115
|
+
export type AgentEvent = AgentStartEvent | AgentEndEvent | TurnStartEvent | SteeringAcceptedEvent | TurnEndEvent | MessageUpdateEvent | ToolExecutionStartEvent | ToolExecutionEndEvent | CodeExecutionStartEvent | CodeExecutionEndEvent | CompactionStartEvent | CompactionEndEvent;
|
|
111
116
|
/** Callback signature for Agent event listeners. */
|
|
112
117
|
export type AgentEventListener = (event: AgentEvent) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aragon-agent/core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.24",
|
|
4
4
|
"description": "AragonAgent core engine — LLM provider adapters, streaming, tool registry/execution, steering, idle watchdog, and an optional isolated-vm sandbox.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "AragonAgent contributors",
|