@rien7/agent-center-host 0.1.0 → 0.1.1
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/README.md +9 -0
- package/dist/core-client.js +3 -0
- package/dist/host.js +1 -0
- package/dist/oar-driver.js +86 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -184,6 +184,13 @@ plus the runtime's file tools for memory (pi `read/edit/write`; Claude Code
|
|
|
184
184
|
run again are kept in `<workdir>/resumed-turns.json`).
|
|
185
185
|
- Core runs one turn per agent at a time, so a second message waits for the first (the
|
|
186
186
|
driver also handles oar's steer/queue landings for when that changes).
|
|
187
|
+
- **Inactive history.** When the session compacts (oar `compaction_ended`, completed),
|
|
188
|
+
the host calls `agent.history.mark_inactive` with `beforeTurnId` (the tool calls of every
|
|
189
|
+
earlier turn of the agent) and the calls the current turn made so far; the messages stay
|
|
190
|
+
(the summary keeps them). When oar drops an accepted input (`input_dropped`; oar 0.86
|
|
191
|
+
has no other rollback record), that turn fails and its user message, reply and tool calls
|
|
192
|
+
are marked inactive. The mark waits for the turn's queued events to reach Center.
|
|
193
|
+
`search.query` and `message.list` leave inactive records out unless `includeInactive`.
|
|
187
194
|
|
|
188
195
|
`Ctrl-C` flushes queued events, marks the host's agents offline and leaves any running
|
|
189
196
|
turn running. The next `run` resumes it.
|
|
@@ -293,6 +300,8 @@ bun test packages/agent-host # core in-process over real HTTP + the host loo
|
|
|
293
300
|
# oar-driver.test.ts: pi + the mock model, end to end
|
|
294
301
|
# subagents.test.ts: issued tokens, memory notes,
|
|
295
302
|
# sub-agents, presence, interrupted turns
|
|
303
|
+
# inactive.test.ts: compaction / dropped input →
|
|
304
|
+
# inactive history (fake oar session)
|
|
296
305
|
bun x tsc -p packages/agent-host # typecheck against Node types
|
|
297
306
|
```
|
|
298
307
|
|
package/dist/core-client.js
CHANGED
|
@@ -63,6 +63,9 @@ export class HttpCoreClient {
|
|
|
63
63
|
openTurn(input) {
|
|
64
64
|
return this.op("turn.open", input, `open-${input.id}`);
|
|
65
65
|
}
|
|
66
|
+
markInactive(input) {
|
|
67
|
+
return this.op("history.mark_inactive", input);
|
|
68
|
+
}
|
|
66
69
|
async claim(input) {
|
|
67
70
|
return (await this.op("turn.claim", input)).items;
|
|
68
71
|
}
|
package/dist/host.js
CHANGED
package/dist/oar-driver.js
CHANGED
|
@@ -90,6 +90,10 @@ function textSink(sink, holdMs = 100) {
|
|
|
90
90
|
flush();
|
|
91
91
|
sink.emit(event);
|
|
92
92
|
},
|
|
93
|
+
flushed() {
|
|
94
|
+
flush();
|
|
95
|
+
return sink.flushed?.() ?? Promise.resolve();
|
|
96
|
+
},
|
|
93
97
|
};
|
|
94
98
|
}
|
|
95
99
|
const clip = (text, max) => {
|
|
@@ -146,6 +150,12 @@ class AgentRun {
|
|
|
146
150
|
pending = [];
|
|
147
151
|
/** The owner of the oar turn that ended last (its report follows). */
|
|
148
152
|
lastEnded = null;
|
|
153
|
+
/** The owner the runtime's events went to last (a compaction while idle covers it). */
|
|
154
|
+
lastOwner = null;
|
|
155
|
+
/** Core turns this run delivered (input ids), newest last; bounded. */
|
|
156
|
+
turnIds = new Set();
|
|
157
|
+
/** history.mark_inactive calls in flight, in order. */
|
|
158
|
+
marking = Promise.resolve();
|
|
149
159
|
/** Its conversation with its parent. */
|
|
150
160
|
conversationId = null;
|
|
151
161
|
// A parent:
|
|
@@ -422,7 +432,11 @@ export class OarDriver {
|
|
|
422
432
|
finished: false,
|
|
423
433
|
chain: Promise.resolve(),
|
|
424
434
|
resolve: () => { },
|
|
435
|
+
calls: [],
|
|
425
436
|
};
|
|
437
|
+
run.turnIds.add(owner.turnId);
|
|
438
|
+
if (run.turnIds.size > 1000)
|
|
439
|
+
run.turnIds.delete(run.turnIds.values().next().value);
|
|
426
440
|
const ended = new Promise((resolve) => {
|
|
427
441
|
owner.resolve = resolve;
|
|
428
442
|
});
|
|
@@ -1130,11 +1144,82 @@ export class OarDriver {
|
|
|
1130
1144
|
};
|
|
1131
1145
|
}
|
|
1132
1146
|
call.announced = owner;
|
|
1147
|
+
if (!owner.calls.includes(id))
|
|
1148
|
+
owner.calls.push(id);
|
|
1133
1149
|
this.emit(owner, event);
|
|
1134
1150
|
}
|
|
1151
|
+
/**
|
|
1152
|
+
* Tell Center which history the runtime no longer has, once the events it names were
|
|
1153
|
+
* appended (behind `owner`'s chain and its sink's batches).
|
|
1154
|
+
*/
|
|
1155
|
+
markInactive(run, owner, input, why) {
|
|
1156
|
+
const client = this.client;
|
|
1157
|
+
if (!client?.markInactive)
|
|
1158
|
+
return;
|
|
1159
|
+
const ready = owner
|
|
1160
|
+
? owner.chain.then(() => owner.sink.flushed?.())
|
|
1161
|
+
: Promise.resolve();
|
|
1162
|
+
run.marking = run.marking
|
|
1163
|
+
.then(() => ready)
|
|
1164
|
+
.then(() => client.markInactive?.(input))
|
|
1165
|
+
.then((marked) => {
|
|
1166
|
+
if (marked && (marked.toolCalls || marked.messages))
|
|
1167
|
+
this.log(`${run.agent.name}: ${why}: ${marked.toolCalls} tool calls, ${marked.messages} messages marked inactive`);
|
|
1168
|
+
})
|
|
1169
|
+
.catch((error) => this.log(`${run.agent.name}: marking ${why} history inactive failed (${error.message})`));
|
|
1170
|
+
}
|
|
1171
|
+
/**
|
|
1172
|
+
* oar `compaction_ended` (completed): the runtime replaced its context with a summary.
|
|
1173
|
+
* Every earlier turn's tool calls and the calls of the turn it happened in are gone
|
|
1174
|
+
* from it.
|
|
1175
|
+
*/
|
|
1176
|
+
compacted(run, live) {
|
|
1177
|
+
const owner = live.owners[0] ?? run.lastOwner;
|
|
1178
|
+
if (!owner) {
|
|
1179
|
+
this.log(`${run.agent.name}: the session compacted before any turn here; nothing to mark`);
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1182
|
+
this.markInactive(run, owner, {
|
|
1183
|
+
agentId: run.agent.id,
|
|
1184
|
+
beforeTurnId: owner.turnId,
|
|
1185
|
+
toolCalls: owner.calls.map((callId) => ({
|
|
1186
|
+
turnId: owner.turnId,
|
|
1187
|
+
callId,
|
|
1188
|
+
})),
|
|
1189
|
+
}, "compaction");
|
|
1190
|
+
}
|
|
1191
|
+
/**
|
|
1192
|
+
* oar `input_dropped`: the runtime discarded an input it had accepted, so that turn's
|
|
1193
|
+
* exchange is not in the session's history (oar 0.86 has no rollback record). Its core
|
|
1194
|
+
* turn fails and its messages and tool calls become inactive.
|
|
1195
|
+
*/
|
|
1196
|
+
rolledBack(run, live, event) {
|
|
1197
|
+
const inputId = event.inputId;
|
|
1198
|
+
if (!run.turnIds.has(inputId))
|
|
1199
|
+
return;
|
|
1200
|
+
const waiting = live.owners.find((o) => o.turnId === inputId) ?? null;
|
|
1201
|
+
const owner = waiting ?? (run.lastOwner?.turnId === inputId ? run.lastOwner : null);
|
|
1202
|
+
if (waiting)
|
|
1203
|
+
this.finish(live.owners, waiting, {
|
|
1204
|
+
type: "failed",
|
|
1205
|
+
reason: `${run.runtimeId} 丢弃了这条消息${event.reason === "runtime_refused" && event.message
|
|
1206
|
+
? `:${event.message}`
|
|
1207
|
+
: ""}`,
|
|
1208
|
+
});
|
|
1209
|
+
this.markInactive(run, owner, { agentId: run.agent.id, turnIds: [inputId] }, "rollback");
|
|
1210
|
+
}
|
|
1135
1211
|
onEvent(run, live, event) {
|
|
1136
1212
|
if (event.agentPath.length)
|
|
1137
1213
|
return; // the runtime's own sub-agents (Task is off)
|
|
1214
|
+
if (event.kind === "compaction_ended") {
|
|
1215
|
+
if (event.outcome === "completed")
|
|
1216
|
+
this.compacted(run, live);
|
|
1217
|
+
return;
|
|
1218
|
+
}
|
|
1219
|
+
if (event.kind === "input_dropped") {
|
|
1220
|
+
this.rolledBack(run, live, event);
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
1138
1223
|
if (event.kind === "exited") {
|
|
1139
1224
|
for (const owner of [...live.owners])
|
|
1140
1225
|
this.finish(live.owners, owner, {
|
|
@@ -1158,6 +1243,7 @@ export class OarDriver {
|
|
|
1158
1243
|
const owner = live.owners[0];
|
|
1159
1244
|
if (!owner)
|
|
1160
1245
|
return;
|
|
1246
|
+
run.lastOwner = owner;
|
|
1161
1247
|
switch (event.kind) {
|
|
1162
1248
|
case "text_delta":
|
|
1163
1249
|
if (event.text)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rien7/agent-center-host",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Agent host for Agent Center: claims queued turns and answers them through a driver (an oar runtime: Claude Code, pi; or echo). Node 24+.",
|
|
6
6
|
"keywords": [
|