@adecore/agents 0.29.2 → 0.29.3
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-session.d.ts +2 -0
- package/dist/chat/chat-session.js +14 -10
- package/package.json +3 -3
- package/src/chat/chat-session.ts +17 -8
|
@@ -104,6 +104,7 @@ export declare class ChatSession {
|
|
|
104
104
|
private staleResults;
|
|
105
105
|
private spokenTurnId;
|
|
106
106
|
private titleTimer;
|
|
107
|
+
private readonly checkpointWork;
|
|
107
108
|
private naming;
|
|
108
109
|
private frozen;
|
|
109
110
|
private readonly subagentOwners;
|
|
@@ -232,6 +233,7 @@ export declare class ChatSession {
|
|
|
232
233
|
private settleAgentTurn;
|
|
233
234
|
private checkpoint;
|
|
234
235
|
private settleCheckpoint;
|
|
236
|
+
private trackCheckpoint;
|
|
235
237
|
private contextNote;
|
|
236
238
|
private submit;
|
|
237
239
|
private acceptPrompt;
|
|
@@ -71,6 +71,8 @@ export class ChatSession {
|
|
|
71
71
|
// The last turn the main agent spoke in; a turn opened only for a subagent's request gets no `result`.
|
|
72
72
|
spokenTurnId = null;
|
|
73
73
|
titleTimer = null;
|
|
74
|
+
/* Checkpoints still asking git, which `dispose` waits for: the host may remove the folder next. */
|
|
75
|
+
checkpointWork = new Set();
|
|
74
76
|
// A name is asked for once per chat this host holds; the turn count keeps it once across restarts.
|
|
75
77
|
naming = false;
|
|
76
78
|
// Set while the host goes down: a CLI dying with it must not end the turn a restart takes up again.
|
|
@@ -1126,7 +1128,7 @@ export class ChatSession {
|
|
|
1126
1128
|
this.frozen = true;
|
|
1127
1129
|
this.backend?.stop();
|
|
1128
1130
|
}
|
|
1129
|
-
/* Ends the CLI and everything it started; settles once it exited or was sent the SIGKILL. */
|
|
1131
|
+
/* Ends the CLI and everything it started; settles once it exited or was sent the SIGKILL and no checkpoint asks git any more. */
|
|
1130
1132
|
dispose() {
|
|
1131
1133
|
this.uiReplies.clear();
|
|
1132
1134
|
this.clearStartWarning();
|
|
@@ -1138,7 +1140,7 @@ export class ChatSession {
|
|
|
1138
1140
|
const ended = this.backend?.dispose() ?? Promise.resolve();
|
|
1139
1141
|
this.backend = null;
|
|
1140
1142
|
this.starting = null;
|
|
1141
|
-
return ended;
|
|
1143
|
+
return Promise.all([ended, ...this.checkpointWork]).then(() => undefined);
|
|
1142
1144
|
}
|
|
1143
1145
|
/* What a turn changed against its checkpoint: the stored answer, or one taken now while it runs. */
|
|
1144
1146
|
async turnDiff(turnId) {
|
|
@@ -1412,15 +1414,13 @@ export class ChatSession {
|
|
|
1412
1414
|
return Promise.resolve();
|
|
1413
1415
|
}
|
|
1414
1416
|
const cwd = this.thread.info.cwd;
|
|
1415
|
-
return Promise.all([checkpoints.take(cwd), checkpoints.head?.(cwd) ?? null])
|
|
1416
|
-
.then(([tree, head]) => {
|
|
1417
|
+
return this.trackCheckpoint(Promise.all([checkpoints.take(cwd), checkpoints.head?.(cwd) ?? null]).then(([tree, head]) => {
|
|
1417
1418
|
const turn = this.thread.get(turnId);
|
|
1418
1419
|
if (tree === null || turn?.kind !== 'turn' || turn.state !== 'running' || this.info.activeTurnId !== turnId) {
|
|
1419
1420
|
return;
|
|
1420
1421
|
}
|
|
1421
1422
|
this.emit([this.thread.upsert({ ...turn, checkpoint: tree, ...(head === null ? {} : { checkpointHead: head }) })]);
|
|
1422
|
-
})
|
|
1423
|
-
.catch(() => undefined);
|
|
1423
|
+
}));
|
|
1424
1424
|
}
|
|
1425
1425
|
/* The diff of a turn that just ended, so a reload shows it without asking git again, and the tree a fork after it starts from. */
|
|
1426
1426
|
settleCheckpoint(turnId) {
|
|
@@ -1430,8 +1430,7 @@ export class ChatSession {
|
|
|
1430
1430
|
}
|
|
1431
1431
|
const { checkpoints } = this.options;
|
|
1432
1432
|
const cwd = this.thread.info.cwd;
|
|
1433
|
-
void Promise.all([checkpoints.settle(cwd, turn.checkpoint), checkpoints.head?.(cwd) ?? null])
|
|
1434
|
-
.then(([answer, head]) => {
|
|
1433
|
+
void this.trackCheckpoint(Promise.all([checkpoints.settle(cwd, turn.checkpoint), checkpoints.head?.(cwd) ?? null]).then(([answer, head]) => {
|
|
1435
1434
|
const settled = this.thread.get(turnId);
|
|
1436
1435
|
if (answer === null || settled?.kind !== 'turn') {
|
|
1437
1436
|
return;
|
|
@@ -1445,8 +1444,13 @@ export class ChatSession {
|
|
|
1445
1444
|
})
|
|
1446
1445
|
]);
|
|
1447
1446
|
this.options.persist();
|
|
1448
|
-
})
|
|
1449
|
-
|
|
1447
|
+
}));
|
|
1448
|
+
}
|
|
1449
|
+
/* Keeps the work in `checkpointWork` until it settled; a failure leaves the turn without a checkpoint. */
|
|
1450
|
+
trackCheckpoint(work) {
|
|
1451
|
+
const tracked = work.catch(() => undefined).finally(() => this.checkpointWork.delete(tracked));
|
|
1452
|
+
this.checkpointWork.add(tracked);
|
|
1453
|
+
return tracked;
|
|
1450
1454
|
}
|
|
1451
1455
|
/*
|
|
1452
1456
|
* What the agent has to hear before this prompt: what the chat kept for it and what the host says.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adecore/agents",
|
|
3
|
-
"version": "0.29.
|
|
3
|
+
"version": "0.29.3",
|
|
4
4
|
"description": "Node-compatible agent chat hosts, providers, accounts, usage and durable task coordination.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -81,8 +81,8 @@
|
|
|
81
81
|
"test": "bun --conditions=source test"
|
|
82
82
|
},
|
|
83
83
|
"dependencies": {
|
|
84
|
-
"@adecore/agent-contracts": "0.29.
|
|
85
|
-
"@adecore/intelligent-ui": "0.29.
|
|
84
|
+
"@adecore/agent-contracts": "0.29.3",
|
|
85
|
+
"@adecore/intelligent-ui": "0.29.3",
|
|
86
86
|
"zod": "^4.6.5"
|
|
87
87
|
},
|
|
88
88
|
"devDependencies": {
|
package/src/chat/chat-session.ts
CHANGED
|
@@ -198,6 +198,8 @@ export class ChatSession {
|
|
|
198
198
|
// The last turn the main agent spoke in; a turn opened only for a subagent's request gets no `result`.
|
|
199
199
|
private spokenTurnId: string | null = null;
|
|
200
200
|
private titleTimer: ReturnType<typeof setTimeout> | null = null;
|
|
201
|
+
/* Checkpoints still asking git, which `dispose` waits for: the host may remove the folder next. */
|
|
202
|
+
private readonly checkpointWork = new Set<Promise<void>>();
|
|
201
203
|
// A name is asked for once per chat this host holds; the turn count keeps it once across restarts.
|
|
202
204
|
private naming = false;
|
|
203
205
|
// Set while the host goes down: a CLI dying with it must not end the turn a restart takes up again.
|
|
@@ -1341,7 +1343,7 @@ export class ChatSession {
|
|
|
1341
1343
|
this.backend?.stop();
|
|
1342
1344
|
}
|
|
1343
1345
|
|
|
1344
|
-
/* Ends the CLI and everything it started; settles once it exited or was sent the SIGKILL. */
|
|
1346
|
+
/* Ends the CLI and everything it started; settles once it exited or was sent the SIGKILL and no checkpoint asks git any more. */
|
|
1345
1347
|
dispose(): Promise<void> {
|
|
1346
1348
|
this.uiReplies.clear();
|
|
1347
1349
|
this.clearStartWarning();
|
|
@@ -1353,7 +1355,7 @@ export class ChatSession {
|
|
|
1353
1355
|
const ended = this.backend?.dispose() ?? Promise.resolve();
|
|
1354
1356
|
this.backend = null;
|
|
1355
1357
|
this.starting = null;
|
|
1356
|
-
return ended;
|
|
1358
|
+
return Promise.all([ended, ...this.checkpointWork]).then(() => undefined);
|
|
1357
1359
|
}
|
|
1358
1360
|
|
|
1359
1361
|
/* What a turn changed against its checkpoint: the stored answer, or one taken now while it runs. */
|
|
@@ -1645,15 +1647,15 @@ export class ChatSession {
|
|
|
1645
1647
|
return Promise.resolve();
|
|
1646
1648
|
}
|
|
1647
1649
|
const cwd = this.thread.info.cwd;
|
|
1648
|
-
return
|
|
1649
|
-
.then(([tree, head]) => {
|
|
1650
|
+
return this.trackCheckpoint(
|
|
1651
|
+
Promise.all([checkpoints.take(cwd), checkpoints.head?.(cwd) ?? null]).then(([tree, head]) => {
|
|
1650
1652
|
const turn = this.thread.get(turnId);
|
|
1651
1653
|
if (tree === null || turn?.kind !== 'turn' || turn.state !== 'running' || this.info.activeTurnId !== turnId) {
|
|
1652
1654
|
return;
|
|
1653
1655
|
}
|
|
1654
1656
|
this.emit([this.thread.upsert({ ...turn, checkpoint: tree, ...(head === null ? {} : { checkpointHead: head }) })]);
|
|
1655
1657
|
})
|
|
1656
|
-
|
|
1658
|
+
);
|
|
1657
1659
|
}
|
|
1658
1660
|
|
|
1659
1661
|
/* The diff of a turn that just ended, so a reload shows it without asking git again, and the tree a fork after it starts from. */
|
|
@@ -1664,8 +1666,8 @@ export class ChatSession {
|
|
|
1664
1666
|
}
|
|
1665
1667
|
const { checkpoints } = this.options;
|
|
1666
1668
|
const cwd = this.thread.info.cwd;
|
|
1667
|
-
void
|
|
1668
|
-
.then(([answer, head]) => {
|
|
1669
|
+
void this.trackCheckpoint(
|
|
1670
|
+
Promise.all([checkpoints.settle(cwd, turn.checkpoint), checkpoints.head?.(cwd) ?? null]).then(([answer, head]) => {
|
|
1669
1671
|
const settled = this.thread.get(turnId);
|
|
1670
1672
|
if (answer === null || settled?.kind !== 'turn') {
|
|
1671
1673
|
return;
|
|
@@ -1680,7 +1682,14 @@ export class ChatSession {
|
|
|
1680
1682
|
]);
|
|
1681
1683
|
this.options.persist();
|
|
1682
1684
|
})
|
|
1683
|
-
|
|
1685
|
+
);
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
/* Keeps the work in `checkpointWork` until it settled; a failure leaves the turn without a checkpoint. */
|
|
1689
|
+
private trackCheckpoint(work: Promise<void>): Promise<void> {
|
|
1690
|
+
const tracked = work.catch(() => undefined).finally(() => this.checkpointWork.delete(tracked));
|
|
1691
|
+
this.checkpointWork.add(tracked);
|
|
1692
|
+
return tracked;
|
|
1684
1693
|
}
|
|
1685
1694
|
|
|
1686
1695
|
/*
|