@epoch-agent/server 0.11.0 → 0.13.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/README.md +55 -4
- package/dist/index.d.ts +265 -21
- package/dist/index.js +90 -10
- package/dist/web/assets/index-CC3FkqSr.js +378 -0
- package/dist/web/assets/index-NPzOQj0s.css +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +3 -3
- package/dist/web/assets/index-VIMaRUrq.js +0 -377
- package/dist/web/assets/index-aGMNpUZA.css +0 -1
package/dist/index.js
CHANGED
|
@@ -197,6 +197,7 @@ var SessionRegistry = class {
|
|
|
197
197
|
controller: null,
|
|
198
198
|
turnStartedAt: null,
|
|
199
199
|
lastFinish: null,
|
|
200
|
+
persisted: null,
|
|
200
201
|
queue: [],
|
|
201
202
|
lastActiveTick: ++this.tick
|
|
202
203
|
});
|
|
@@ -465,6 +466,9 @@ var SessionHub = class {
|
|
|
465
466
|
isCooled(sessionId) {
|
|
466
467
|
return this.registry.isCooled(sessionId);
|
|
467
468
|
}
|
|
469
|
+
persistedThrough(sessionId) {
|
|
470
|
+
return this.registry.get(sessionId)?.persisted ?? null;
|
|
471
|
+
}
|
|
468
472
|
stateOf(sessionId) {
|
|
469
473
|
return this.registry.get(sessionId)?.state ?? "idle";
|
|
470
474
|
}
|
|
@@ -542,21 +546,22 @@ var SessionHub = class {
|
|
|
542
546
|
}
|
|
543
547
|
const queued = { message, ...decorate ? { decorate } : {} };
|
|
544
548
|
if (entry.state !== "idle") {
|
|
549
|
+
const steered = decorate === void 0 && entry.queue.every((q) => q.decorate === void 0);
|
|
545
550
|
if (!this.registry.enqueue(entry, queued)) {
|
|
546
551
|
return { ok: false, reason: "queue-full", state: entry.state };
|
|
547
552
|
}
|
|
548
|
-
return { ok: true, queued: true };
|
|
553
|
+
return { ok: true, queued: true, steered };
|
|
549
554
|
}
|
|
550
555
|
this.beginTurn(entry, queued);
|
|
551
556
|
return { ok: true, queued: false };
|
|
552
557
|
}
|
|
553
558
|
abort(sessionId) {
|
|
554
559
|
const entry = this.registry.get(sessionId);
|
|
555
|
-
if (!entry) return false;
|
|
556
|
-
entry.queue.length
|
|
557
|
-
if (!entry.controller) return false;
|
|
560
|
+
if (!entry) return { running: false, returned: [] };
|
|
561
|
+
const returned = entry.queue.splice(0, entry.queue.length).map((q) => q.message);
|
|
562
|
+
if (!entry.controller) return { running: false, returned };
|
|
558
563
|
entry.controller.abort();
|
|
559
|
-
return true;
|
|
564
|
+
return { running: true, returned };
|
|
560
565
|
}
|
|
561
566
|
listPending(sessionId) {
|
|
562
567
|
return this.registry.get(sessionId)?.relay.listPending() ?? [];
|
|
@@ -637,12 +642,19 @@ var SessionHub = class {
|
|
|
637
642
|
const sessionId = entry.session.sessionId;
|
|
638
643
|
const signal = entry.controller?.signal;
|
|
639
644
|
try {
|
|
640
|
-
const run = entry.session.run(queued.message,
|
|
645
|
+
const run = entry.session.run(queued.message, {
|
|
646
|
+
...signal ? { signal } : {},
|
|
647
|
+
steer: this.steerFrom(entry)
|
|
648
|
+
});
|
|
641
649
|
const raw = queued.decorate ? queued.decorate(run) : run;
|
|
642
650
|
for await (const event of serializeStream(raw, entry.relay, entry.questions)) {
|
|
643
651
|
const blocking = event.type === "approval-request" || event.type === "question";
|
|
644
652
|
if (blocking) this.requestOwner.set(event.requestId, sessionId);
|
|
645
653
|
const frame = this.publish(sessionId, stripArtifactData(event));
|
|
654
|
+
const through = entry.session.persistedThrough?.() ?? null;
|
|
655
|
+
if (through !== null && through !== entry.persisted?.id) {
|
|
656
|
+
entry.persisted = { id: through, seq: frame.seq };
|
|
657
|
+
}
|
|
646
658
|
if (event.type === "finish") {
|
|
647
659
|
entry.lastFinish = toWireFinish(event, frame.ts, entry.turnStartedAt);
|
|
648
660
|
}
|
|
@@ -657,10 +669,22 @@ var SessionHub = class {
|
|
|
657
669
|
}
|
|
658
670
|
this.registry.touch(sessionId);
|
|
659
671
|
entry.turnStartedAt = null;
|
|
672
|
+
entry.persisted = null;
|
|
660
673
|
this.setState(entry, "idle");
|
|
661
674
|
this.drainQueue(entry);
|
|
662
675
|
}
|
|
663
676
|
}
|
|
677
|
+
steerFrom(entry) {
|
|
678
|
+
const runLength = () => {
|
|
679
|
+
let n = 0;
|
|
680
|
+
while (n < entry.queue.length && entry.queue[n].decorate === void 0) n += 1;
|
|
681
|
+
return n;
|
|
682
|
+
};
|
|
683
|
+
return {
|
|
684
|
+
pending: () => runLength() > 0,
|
|
685
|
+
take: () => entry.queue.splice(0, runLength()).map((q) => q.message)
|
|
686
|
+
};
|
|
687
|
+
}
|
|
664
688
|
drainQueue(entry) {
|
|
665
689
|
if (this.closed || !this.registry.has(entry.session.sessionId)) return;
|
|
666
690
|
if (this.present === 0) {
|
|
@@ -1503,9 +1527,13 @@ function toWireSettingRow(row) {
|
|
|
1503
1527
|
overridable: row.overridable,
|
|
1504
1528
|
writes: row.writes.map(toWireSettingWrite),
|
|
1505
1529
|
...row.valueKind === void 0 ? {} : { valueKind: row.valueKind },
|
|
1506
|
-
...row.choices === void 0 ? {} : { choices: [...row.choices] }
|
|
1530
|
+
...row.choices === void 0 ? {} : { choices: [...row.choices] },
|
|
1531
|
+
...row.pending === void 0 ? {} : { pending: toWireSettingPending(row.pending) }
|
|
1507
1532
|
};
|
|
1508
1533
|
}
|
|
1534
|
+
function toWireSettingPending(pending) {
|
|
1535
|
+
return { ...toWireSettingWrite(pending), value: pending.value };
|
|
1536
|
+
}
|
|
1509
1537
|
function toWireSettingStep(step) {
|
|
1510
1538
|
return { layer: step.layer, ...step.value === void 0 ? {} : { value: step.value } };
|
|
1511
1539
|
}
|
|
@@ -1720,8 +1748,10 @@ async function patchSession(ctx, req, res, sessionId, lang) {
|
|
|
1720
1748
|
);
|
|
1721
1749
|
}
|
|
1722
1750
|
let row = wantsTitle ? catalog.rename(sessionId, title) : catalog.get(sessionId);
|
|
1751
|
+
const archivedBefore = row?.archived;
|
|
1723
1752
|
if (row && wantsArchive) row = catalog.setArchived(sessionId, rawArchived);
|
|
1724
1753
|
if (!row) return sendUnknownSession(res, sessionId, lang);
|
|
1754
|
+
if (wantsArchive && archivedBefore !== row.archived) ctx.hub.notifySessionsChanged(sessionId);
|
|
1725
1755
|
const hub = ctx.hub.listSessions().find((s) => s.id === sessionId);
|
|
1726
1756
|
sendJson(res, 200, {
|
|
1727
1757
|
session: toWireSummary(sessionId, hub, row, {
|
|
@@ -1734,11 +1764,17 @@ function listMessages(ctx, res, sessionId, lang) {
|
|
|
1734
1764
|
if (!ctx.hub.has(sessionId) && !ctx.runtime.sessions?.get(sessionId)) {
|
|
1735
1765
|
return sendUnknownSession(res, sessionId, lang);
|
|
1736
1766
|
}
|
|
1737
|
-
const
|
|
1767
|
+
const all = ctx.runtime.sessionStore?.loadMessages(sessionId) ?? [];
|
|
1738
1768
|
const usage = ctx.runtime.sessionUsage(sessionId);
|
|
1769
|
+
const flight = ctx.hub.persistedThrough(sessionId);
|
|
1770
|
+
const openFrom = ctx.runtime.sessionStore?.openTurnFrom(sessionId) ?? null;
|
|
1771
|
+
const messages = flight ? all.filter((m) => m.id <= flight.id) : all;
|
|
1772
|
+
const interrupted = flight === null && openFrom !== null ? openFrom : void 0;
|
|
1739
1773
|
sendJson(res, 200, {
|
|
1740
1774
|
messages,
|
|
1741
|
-
...usage ? { usage } : {}
|
|
1775
|
+
...usage ? { usage } : {},
|
|
1776
|
+
...flight ? { inFlightThroughSeq: flight.seq } : {},
|
|
1777
|
+
...interrupted !== void 0 ? { interruptedTurnFrom: interrupted } : {}
|
|
1742
1778
|
});
|
|
1743
1779
|
}
|
|
1744
1780
|
async function postMessage(ctx, req, res, sessionId, lang) {
|
|
@@ -1772,6 +1808,7 @@ async function postMessage(ctx, req, res, sessionId, lang) {
|
|
|
1772
1808
|
return sendJson(res, 202, {
|
|
1773
1809
|
accepted: true,
|
|
1774
1810
|
queued: started.queued,
|
|
1811
|
+
...started.steered === void 0 ? {} : { steered: started.steered },
|
|
1775
1812
|
...expansion.notice ? { command: expansion.notice } : {},
|
|
1776
1813
|
...attached.references.length > 0 ? { references: attached.references } : {},
|
|
1777
1814
|
...attached.files.length > 0 ? { files: attached.files } : {}
|
|
@@ -1793,7 +1830,11 @@ function pickTurnRole(live, raw) {
|
|
|
1793
1830
|
}
|
|
1794
1831
|
function abortSession(ctx, res, sessionId, lang) {
|
|
1795
1832
|
if (!ctx.hub.has(sessionId)) return sendUnknownSession(res, sessionId, lang);
|
|
1796
|
-
|
|
1833
|
+
const stopped = ctx.hub.abort(sessionId);
|
|
1834
|
+
sendJson(res, 200, {
|
|
1835
|
+
aborted: stopped.running,
|
|
1836
|
+
...stopped.returned.length > 0 ? { returned: stopped.returned } : {}
|
|
1837
|
+
});
|
|
1797
1838
|
}
|
|
1798
1839
|
function listApprovals(ctx, res, sessionId, lang) {
|
|
1799
1840
|
if (!ctx.hub.has(sessionId)) return sendUnknownSession(res, sessionId, lang);
|
|
@@ -2108,6 +2149,9 @@ async function rewind(ctx, req, res, sessionId, lang) {
|
|
|
2108
2149
|
const input = readRewindInput(body.value, lang);
|
|
2109
2150
|
if (!input.ok) return sendError(res, 400, input.code, input.message);
|
|
2110
2151
|
const { turnIndex, scope, overwrite } = input.value;
|
|
2152
|
+
if (scope !== "files" && ctx.hub.stateOf(sessionId) !== "idle") {
|
|
2153
|
+
return sendError(res, 409, "turn-running", t("web.rewind_turn_running", void 0, lang));
|
|
2154
|
+
}
|
|
2111
2155
|
const result = await control.rewind(turnIndex, {
|
|
2112
2156
|
scope,
|
|
2113
2157
|
...overwrite === void 0 ? {} : { overwrite }
|
|
@@ -3192,6 +3236,39 @@ function addFailure2(reason, detail, lang) {
|
|
|
3192
3236
|
function stringList2(value) {
|
|
3193
3237
|
return value.filter((v) => typeof v === "string");
|
|
3194
3238
|
}
|
|
3239
|
+
async function removeRole(ctx, req, res, lang) {
|
|
3240
|
+
if (ctx.lanExposed) {
|
|
3241
|
+
return sendError(
|
|
3242
|
+
res,
|
|
3243
|
+
403,
|
|
3244
|
+
"role-remove-lan-exposed",
|
|
3245
|
+
t("web.role_remove_lan_exposed", void 0, lang)
|
|
3246
|
+
);
|
|
3247
|
+
}
|
|
3248
|
+
const body = await readJsonBody(req);
|
|
3249
|
+
if (!body.ok) return sendError(res, body.status, "bad-body", body.message);
|
|
3250
|
+
const payload = asRecord(body.value);
|
|
3251
|
+
const name = typeof payload["name"] === "string" ? payload["name"].trim() : "";
|
|
3252
|
+
const outcome = ctx.runtime.roleWrite.remove(name, lang);
|
|
3253
|
+
if (!outcome.ok) {
|
|
3254
|
+
return sendJson(res, 200, {
|
|
3255
|
+
ok: false,
|
|
3256
|
+
name: "",
|
|
3257
|
+
path: null,
|
|
3258
|
+
takenOverBy: null,
|
|
3259
|
+
detail: outcome.detail,
|
|
3260
|
+
reason: outcome.reason
|
|
3261
|
+
});
|
|
3262
|
+
}
|
|
3263
|
+
sendJson(res, 200, {
|
|
3264
|
+
ok: true,
|
|
3265
|
+
name: outcome.name,
|
|
3266
|
+
path: outcome.path,
|
|
3267
|
+
takenOverBy: outcome.takenOverBy,
|
|
3268
|
+
detail: null,
|
|
3269
|
+
reason: null
|
|
3270
|
+
});
|
|
3271
|
+
}
|
|
3195
3272
|
function stringList3(value) {
|
|
3196
3273
|
if (!Array.isArray(value)) return null;
|
|
3197
3274
|
const out = [];
|
|
@@ -4837,6 +4914,9 @@ async function handleApi(opts, req, res, method, segments, lang) {
|
|
|
4837
4914
|
if (resource === "roles" && first === void 0 && method === "POST") {
|
|
4838
4915
|
return addRole(ctx, req, res, lang);
|
|
4839
4916
|
}
|
|
4917
|
+
if (resource === "roles" && first === "remove" && method === "POST") {
|
|
4918
|
+
return removeRole(ctx, req, res, lang);
|
|
4919
|
+
}
|
|
4840
4920
|
if (resource === "skills" && first === "import" && second === "preview" && method === "POST") {
|
|
4841
4921
|
return previewSkillImport(ctx, req, res, lang);
|
|
4842
4922
|
}
|