@adecore/agents 0.45.0 → 0.46.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/dist/chat/chat-core.js +1 -0
- package/dist/chat/claude-protocol.js +8 -4
- package/dist/chat/projector.d.ts +1 -0
- package/dist/chat/projector.js +16 -4
- package/dist/chat/thread.d.ts +2 -1
- package/dist/chat/thread.js +5 -1
- package/package.json +3 -3
- package/src/chat/chat-core.ts +1 -0
- package/src/chat/claude-protocol.ts +9 -4
- package/src/chat/projector.ts +17 -4
- package/src/chat/thread.ts +8 -1
package/dist/chat/chat-core.js
CHANGED
|
@@ -408,6 +408,7 @@ export class ChatCore {
|
|
|
408
408
|
items: session.previewItems(page.items),
|
|
409
409
|
pending: session.previewItems(session.thread.pending()),
|
|
410
410
|
subagents: session.thread.subagentsBefore(page.history.start),
|
|
411
|
+
workflows: session.thread.workflowsBefore(page.history.start),
|
|
411
412
|
outline: session.thread.outlineBefore(page.history.start),
|
|
412
413
|
seq: log.seq
|
|
413
414
|
};
|
|
@@ -764,7 +764,7 @@ export class ClaudeProtocol {
|
|
|
764
764
|
const errors = Array.isArray(frame.errors) ? frame.errors.filter((error) => typeof error === 'string') : [];
|
|
765
765
|
const lastUuid = this.lastUuid;
|
|
766
766
|
this.lastUuid = null;
|
|
767
|
-
const limit = failed ? this.limit() : null;
|
|
767
|
+
const limit = failed ? this.limit([str(frame.result), ...errors].join('\n')) : null;
|
|
768
768
|
const replaceProcess = failed && this.apiError === 'authentication_failed';
|
|
769
769
|
if (limit?.kind !== 'usage') {
|
|
770
770
|
this.refusedResets.clear();
|
|
@@ -819,10 +819,10 @@ export class ClaudeProtocol {
|
|
|
819
819
|
}
|
|
820
820
|
/*
|
|
821
821
|
* What stopped a failed turn, in the words of Claude Code 2.1.281: a window of the plan that refused
|
|
822
|
-
* the request is a usage limit
|
|
823
|
-
* not explain) or
|
|
822
|
+
* the request or an explicit spent-plan message is a usage limit. A bare `rate_limit` (a 429
|
|
823
|
+
* the plan did not explain) or `overloaded` is a model too busy to answer.
|
|
824
824
|
*/
|
|
825
|
-
limit() {
|
|
825
|
+
limit(message) {
|
|
826
826
|
if (this.refusedWindows.size > 0) {
|
|
827
827
|
let resetsAt = 0;
|
|
828
828
|
for (const reset of this.refusedWindows.values()) {
|
|
@@ -833,6 +833,10 @@ export class ClaudeProtocol {
|
|
|
833
833
|
}
|
|
834
834
|
return { kind: 'usage', resetsAt };
|
|
835
835
|
}
|
|
836
|
+
// The first refusal can name the spent plan before a rate_limit_event supplies its window.
|
|
837
|
+
if (this.apiError === 'rate_limit' && /you(?:'|’)ve hit your (?:5[- ]hour|weekly|session|usage) limit\b/i.test(message)) {
|
|
838
|
+
return { kind: 'usage' };
|
|
839
|
+
}
|
|
836
840
|
if (this.apiError === 'rate_limit' || this.apiError === 'overloaded') {
|
|
837
841
|
return { kind: 'overload' };
|
|
838
842
|
}
|
package/dist/chat/projector.d.ts
CHANGED
package/dist/chat/projector.js
CHANGED
|
@@ -199,9 +199,17 @@ export class ThreadProjector {
|
|
|
199
199
|
const tool = this.thread.get(this.itemId(generation, event.ref));
|
|
200
200
|
if (tool?.kind === 'tool') {
|
|
201
201
|
const name = event.workflow.name ?? tool.workflow?.name ?? null;
|
|
202
|
+
// A late frame after the call settled must not wipe the end it noted.
|
|
203
|
+
const finishedAt = event.workflow.finishedAt ?? tool.workflow?.finishedAt;
|
|
202
204
|
events.push(this.thread.upsert({
|
|
203
205
|
...tool,
|
|
204
|
-
workflow: {
|
|
206
|
+
workflow: {
|
|
207
|
+
...event.workflow,
|
|
208
|
+
name,
|
|
209
|
+
taskId: event.workflow.taskId ?? tool.workflow?.taskId,
|
|
210
|
+
lastProgressAt: this.now(),
|
|
211
|
+
...(finishedAt === undefined ? {} : { finishedAt })
|
|
212
|
+
}
|
|
205
213
|
}));
|
|
206
214
|
}
|
|
207
215
|
break;
|
|
@@ -415,7 +423,7 @@ export class ThreadProjector {
|
|
|
415
423
|
events.push(this.thread.upsert({ ...item, state: 'cancelled' }));
|
|
416
424
|
}
|
|
417
425
|
else if (item.kind === 'tool' && item.state === 'running' && (processGone || !this.backgroundCalls.has(item.id))) {
|
|
418
|
-
events.push(this.thread.upsert({ ...item, state: 'error' }));
|
|
426
|
+
events.push(this.thread.upsert(this.ended({ ...item, state: 'error' })));
|
|
419
427
|
}
|
|
420
428
|
else if (item.kind === 'subagent' && item.status === 'running' && (processGone || !this.outlivesTurn(item))) {
|
|
421
429
|
events.push(this.thread.upsert({ ...item, status: 'failed', finishedAt: this.now() }));
|
|
@@ -553,7 +561,7 @@ export class ThreadProjector {
|
|
|
553
561
|
if (event.changes) {
|
|
554
562
|
settled.changes = event.changes;
|
|
555
563
|
}
|
|
556
|
-
events.push(this.thread.upsert(settled));
|
|
564
|
+
events.push(this.thread.upsert(this.ended(settled)));
|
|
557
565
|
}
|
|
558
566
|
patchProgress(generation, event, events) {
|
|
559
567
|
const tool = this.thread.get(this.itemId(generation, event.ref));
|
|
@@ -803,7 +811,11 @@ export class ThreadProjector {
|
|
|
803
811
|
const output = summary === '' ? call.output : [call.output, summary].filter((part) => part !== null && part !== '').join('\n\n');
|
|
804
812
|
const settled = { ...call, output, state: event.ok ? 'done' : 'error' };
|
|
805
813
|
delete settled.progress;
|
|
806
|
-
events.push(this.thread.upsert(settled));
|
|
814
|
+
events.push(this.thread.upsert(this.ended(settled)));
|
|
815
|
+
}
|
|
816
|
+
/* A settling Workflow call notes when, since a tool item has no end of its own to tell a finished workflow's age by. */
|
|
817
|
+
ended(tool) {
|
|
818
|
+
return tool.workflow === undefined ? tool : { ...tool, workflow: { ...tool.workflow, finishedAt: this.now() } };
|
|
807
819
|
}
|
|
808
820
|
/* A shell or a monitor, told apart by the call that started it when the CLI's frame does not say. */
|
|
809
821
|
startBackground(generation, event, events) {
|
package/dist/chat/thread.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AgentStatus, type ChatApprovalItem, type ChatEvent, type ChatHistoryResult, type ChatInfo, type ChatItem, type ChatQuestionItem, type ChatSubagentItem } from '@adecore/agent-contracts';
|
|
1
|
+
import { type AgentStatus, type ChatApprovalItem, type ChatEvent, type ChatHistoryResult, type ChatInfo, type ChatItem, type ChatQuestionItem, type ChatSubagentItem, type ChatToolItem } from '@adecore/agent-contracts';
|
|
2
2
|
export declare class ChatThread {
|
|
3
3
|
info: ChatInfo;
|
|
4
4
|
private readonly items;
|
|
@@ -30,6 +30,7 @@ export declare class ChatThread {
|
|
|
30
30
|
private syncRequests;
|
|
31
31
|
history(limit?: number, cursor?: string): ChatHistoryResult;
|
|
32
32
|
subagentsBefore(start: number): ChatSubagentItem[];
|
|
33
|
+
workflowsBefore(start: number): ChatToolItem[];
|
|
33
34
|
outlineBefore(start: number, marked?: ReadonlySet<string>): ChatItem[];
|
|
34
35
|
snapshot(): {
|
|
35
36
|
info: ChatInfo;
|
package/dist/chat/thread.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { activeSubagents, outlineItems } from '@adecore/agent-contracts';
|
|
2
|
+
import { activeSubagents, activeWorkflows, outlineItems } from '@adecore/agent-contracts';
|
|
3
3
|
import { appendToolOutput } from '@adecore/agent-contracts/text';
|
|
4
4
|
import { ChatError } from './errors.js';
|
|
5
5
|
import { requestSummaries } from './request-summary.js';
|
|
@@ -185,6 +185,10 @@ export class ChatThread {
|
|
|
185
185
|
subagentsBefore(start) {
|
|
186
186
|
return activeSubagents(this.list()).filter((item) => this.indices.get(item.id) < start);
|
|
187
187
|
}
|
|
188
|
+
/* The active Workflow calls a page that begins at `start` leaves out. */
|
|
189
|
+
workflowsBefore(start) {
|
|
190
|
+
return activeWorkflows(this.list()).filter((item) => this.indices.get(item.id) < start);
|
|
191
|
+
}
|
|
188
192
|
/* The outline of what a page that begins at `start` leaves out, with the replies in `marked` that a bookmark is on. */
|
|
189
193
|
outlineBefore(start, marked) {
|
|
190
194
|
return outlineItems(this.order.slice(0, start).map((id) => this.items.get(id)), marked);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adecore/agents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.46.0",
|
|
4
4
|
"description": "Node-compatible agent chat hosts, providers, accounts, usage and durable task coordination.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -93,8 +93,8 @@
|
|
|
93
93
|
"test": "bun --conditions=source test"
|
|
94
94
|
},
|
|
95
95
|
"dependencies": {
|
|
96
|
-
"@adecore/agent-contracts": "0.
|
|
97
|
-
"@adecore/intelligent-ui": "0.
|
|
96
|
+
"@adecore/agent-contracts": "0.46.0",
|
|
97
|
+
"@adecore/intelligent-ui": "0.46.0",
|
|
98
98
|
"zod": "^4.6.7"
|
|
99
99
|
},
|
|
100
100
|
"devDependencies": {
|
package/src/chat/chat-core.ts
CHANGED
|
@@ -663,6 +663,7 @@ export class ChatCore {
|
|
|
663
663
|
items: session.previewItems(page.items),
|
|
664
664
|
pending: session.previewItems(session.thread.pending()),
|
|
665
665
|
subagents: session.thread.subagentsBefore(page.history.start),
|
|
666
|
+
workflows: session.thread.workflowsBefore(page.history.start),
|
|
666
667
|
outline: session.thread.outlineBefore(page.history.start),
|
|
667
668
|
seq: log.seq
|
|
668
669
|
};
|
|
@@ -949,7 +949,7 @@ export class ClaudeProtocol {
|
|
|
949
949
|
const errors = Array.isArray(frame.errors) ? frame.errors.filter((error): error is string => typeof error === 'string') : [];
|
|
950
950
|
const lastUuid = this.lastUuid;
|
|
951
951
|
this.lastUuid = null;
|
|
952
|
-
const limit = failed ? this.limit() : null;
|
|
952
|
+
const limit = failed ? this.limit([str(frame.result), ...errors].join('\n')) : null;
|
|
953
953
|
const replaceProcess = failed && this.apiError === 'authentication_failed';
|
|
954
954
|
|
|
955
955
|
if (limit?.kind !== 'usage') {
|
|
@@ -1014,10 +1014,10 @@ export class ClaudeProtocol {
|
|
|
1014
1014
|
|
|
1015
1015
|
/*
|
|
1016
1016
|
* What stopped a failed turn, in the words of Claude Code 2.1.281: a window of the plan that refused
|
|
1017
|
-
* the request is a usage limit
|
|
1018
|
-
* not explain) or
|
|
1017
|
+
* the request or an explicit spent-plan message is a usage limit. A bare `rate_limit` (a 429
|
|
1018
|
+
* the plan did not explain) or `overloaded` is a model too busy to answer.
|
|
1019
1019
|
*/
|
|
1020
|
-
private limit(): ChatTurnLimit | null {
|
|
1020
|
+
private limit(message: string): ChatTurnLimit | null {
|
|
1021
1021
|
if (this.refusedWindows.size > 0) {
|
|
1022
1022
|
let resetsAt = 0;
|
|
1023
1023
|
|
|
@@ -1032,6 +1032,11 @@ export class ClaudeProtocol {
|
|
|
1032
1032
|
return { kind: 'usage', resetsAt };
|
|
1033
1033
|
}
|
|
1034
1034
|
|
|
1035
|
+
// The first refusal can name the spent plan before a rate_limit_event supplies its window.
|
|
1036
|
+
if (this.apiError === 'rate_limit' && /you(?:'|’)ve hit your (?:5[- ]hour|weekly|session|usage) limit\b/i.test(message)) {
|
|
1037
|
+
return { kind: 'usage' };
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1035
1040
|
if (this.apiError === 'rate_limit' || this.apiError === 'overloaded') {
|
|
1036
1041
|
return { kind: 'overload' };
|
|
1037
1042
|
}
|
package/src/chat/projector.ts
CHANGED
|
@@ -261,11 +261,19 @@ export class ThreadProjector {
|
|
|
261
261
|
|
|
262
262
|
if (tool?.kind === 'tool') {
|
|
263
263
|
const name = event.workflow.name ?? tool.workflow?.name ?? null;
|
|
264
|
+
// A late frame after the call settled must not wipe the end it noted.
|
|
265
|
+
const finishedAt = event.workflow.finishedAt ?? tool.workflow?.finishedAt;
|
|
264
266
|
|
|
265
267
|
events.push(
|
|
266
268
|
this.thread.upsert({
|
|
267
269
|
...tool,
|
|
268
|
-
workflow: {
|
|
270
|
+
workflow: {
|
|
271
|
+
...event.workflow,
|
|
272
|
+
name,
|
|
273
|
+
taskId: event.workflow.taskId ?? tool.workflow?.taskId,
|
|
274
|
+
lastProgressAt: this.now(),
|
|
275
|
+
...(finishedAt === undefined ? {} : { finishedAt })
|
|
276
|
+
}
|
|
269
277
|
})
|
|
270
278
|
);
|
|
271
279
|
}
|
|
@@ -532,7 +540,7 @@ export class ThreadProjector {
|
|
|
532
540
|
} else if (item.kind === 'question' && item.state === 'pending' && dropRequests) {
|
|
533
541
|
events.push(this.thread.upsert({ ...item, state: 'cancelled' }));
|
|
534
542
|
} else if (item.kind === 'tool' && item.state === 'running' && (processGone || !this.backgroundCalls.has(item.id))) {
|
|
535
|
-
events.push(this.thread.upsert({ ...item, state: 'error' }));
|
|
543
|
+
events.push(this.thread.upsert(this.ended({ ...item, state: 'error' })));
|
|
536
544
|
} else if (item.kind === 'subagent' && item.status === 'running' && (processGone || !this.outlivesTurn(item))) {
|
|
537
545
|
events.push(this.thread.upsert({ ...item, status: 'failed', finishedAt: this.now() }));
|
|
538
546
|
}
|
|
@@ -711,7 +719,7 @@ export class ThreadProjector {
|
|
|
711
719
|
settled.changes = event.changes;
|
|
712
720
|
}
|
|
713
721
|
|
|
714
|
-
events.push(this.thread.upsert(settled));
|
|
722
|
+
events.push(this.thread.upsert(this.ended(settled)));
|
|
715
723
|
}
|
|
716
724
|
|
|
717
725
|
private patchProgress(generation: number, event: Extract<BackendEvent, { type: 'tool.progress' }>, events: ChatEvent[]): void {
|
|
@@ -1030,7 +1038,12 @@ export class ThreadProjector {
|
|
|
1030
1038
|
const output = summary === '' ? call.output : [call.output, summary].filter((part) => part !== null && part !== '').join('\n\n');
|
|
1031
1039
|
const settled: ChatToolItem = { ...call, output, state: event.ok ? 'done' : 'error' };
|
|
1032
1040
|
delete settled.progress;
|
|
1033
|
-
events.push(this.thread.upsert(settled));
|
|
1041
|
+
events.push(this.thread.upsert(this.ended(settled)));
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
/* A settling Workflow call notes when, since a tool item has no end of its own to tell a finished workflow's age by. */
|
|
1045
|
+
private ended(tool: ChatToolItem): ChatToolItem {
|
|
1046
|
+
return tool.workflow === undefined ? tool : { ...tool, workflow: { ...tool.workflow, finishedAt: this.now() } };
|
|
1034
1047
|
}
|
|
1035
1048
|
|
|
1036
1049
|
/* A shell or a monitor, told apart by the call that started it when the CLI's frame does not say. */
|
package/src/chat/thread.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import {
|
|
3
3
|
activeSubagents,
|
|
4
|
+
activeWorkflows,
|
|
4
5
|
outlineItems,
|
|
5
6
|
type AgentStatus,
|
|
6
7
|
type ChatApprovalItem,
|
|
@@ -9,7 +10,8 @@ import {
|
|
|
9
10
|
type ChatInfo,
|
|
10
11
|
type ChatItem,
|
|
11
12
|
type ChatQuestionItem,
|
|
12
|
-
type ChatSubagentItem
|
|
13
|
+
type ChatSubagentItem,
|
|
14
|
+
type ChatToolItem
|
|
13
15
|
} from '@adecore/agent-contracts';
|
|
14
16
|
import { appendToolOutput } from '@adecore/agent-contracts/text';
|
|
15
17
|
import { ChatError } from './errors.ts';
|
|
@@ -247,6 +249,11 @@ export class ChatThread {
|
|
|
247
249
|
return activeSubagents(this.list()).filter((item) => this.indices.get(item.id)! < start);
|
|
248
250
|
}
|
|
249
251
|
|
|
252
|
+
/* The active Workflow calls a page that begins at `start` leaves out. */
|
|
253
|
+
workflowsBefore(start: number): ChatToolItem[] {
|
|
254
|
+
return activeWorkflows(this.list()).filter((item) => this.indices.get(item.id)! < start);
|
|
255
|
+
}
|
|
256
|
+
|
|
250
257
|
/* The outline of what a page that begins at `start` leaves out, with the replies in `marked` that a bookmark is on. */
|
|
251
258
|
outlineBefore(start: number, marked?: ReadonlySet<string>): ChatItem[] {
|
|
252
259
|
return outlineItems(
|