@sema-agent/server 1.187.0 → 1.189.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/capabilities/sandbox-file-send.d.ts +20 -0
- package/dist/capabilities/sandbox-file-send.d.ts.map +1 -0
- package/dist/capabilities/sandbox-file-send.js +106 -0
- package/dist/capabilities/sandbox-file-send.js.map +1 -0
- package/dist/capabilities/send-user-file-tool.d.ts +4 -5
- package/dist/capabilities/send-user-file-tool.d.ts.map +1 -1
- package/dist/capabilities/send-user-file-tool.js +6 -7
- package/dist/capabilities/send-user-file-tool.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -1
- package/dist/http/server.d.ts +1 -0
- package/dist/http/server.d.ts.map +1 -1
- package/dist/http/server.js +41 -16
- package/dist/http/server.js.map +1 -1
- package/dist/main.js +40 -14
- package/dist/main.js.map +1 -1
- package/dist/orchestration/workflow-completion-inbox.d.ts +12 -0
- package/dist/orchestration/workflow-completion-inbox.d.ts.map +1 -1
- package/dist/orchestration/workflow-completion-inbox.js +18 -0
- package/dist/orchestration/workflow-completion-inbox.js.map +1 -1
- package/dist/plugins/s3-presign.d.ts +12 -1
- package/dist/plugins/s3-presign.d.ts.map +1 -1
- package/dist/plugins/s3-presign.js +14 -5
- package/dist/plugins/s3-presign.js.map +1 -1
- package/dist/plugins/send-user-file.d.ts +8 -0
- package/dist/plugins/send-user-file.d.ts.map +1 -1
- package/dist/plugins/send-user-file.js +72 -1
- package/dist/plugins/send-user-file.js.map +1 -1
- package/dist/runs.d.ts.map +1 -1
- package/dist/runs.js +16 -9
- package/dist/runs.js.map +1 -1
- package/dist/sighup-idle.d.ts +12 -0
- package/dist/sighup-idle.d.ts.map +1 -0
- package/dist/sighup-idle.js +53 -0
- package/dist/sighup-idle.js.map +1 -0
- package/package.json +1 -1
package/dist/http/server.js
CHANGED
|
@@ -17,7 +17,7 @@ import { manifestToIndexEntry } from "../images/manifest.js";
|
|
|
17
17
|
import { runInBackground, evictIfConflict, stripCheckpointToken, resumeAtHttpStatus, TurnAnchorCapture, HEARTBEAT_MS, markChildrenStoppedByUserOnAbort } from "../runs.js";
|
|
18
18
|
import { looksLikeJwt } from "../auth-bridge.js";
|
|
19
19
|
import { redactSteerIn } from "../orchestration/workflow-agent-steer.js";
|
|
20
|
-
import { emitPendingWorkflowCompletions, taskNotificationInboxEntry, taskNotificationFoldKey } from "../orchestration/workflow-completion-inbox.js";
|
|
20
|
+
import { emitPendingWorkflowCompletions, taskNotificationInboxEntry, taskNotificationFoldKey, taskNotificationStreamKey, NotifiedKeys } from "../orchestration/workflow-completion-inbox.js";
|
|
21
21
|
import { fleetRunPublisher, fleetRunLabels } from "../fleet/fleet-bus.js";
|
|
22
22
|
import { RateLimiter } from "../observability/rate-limit.js";
|
|
23
23
|
import { withPrincipal } from "../observability/principal-context.js";
|
|
@@ -181,6 +181,14 @@ export function createHttpServer(deps) {
|
|
|
181
181
|
let uncountedBillableInflight = 0;
|
|
182
182
|
if (deps.drainState)
|
|
183
183
|
deps.drainState.inflight = () => new Set([...inflightRuns.keys(), ...steerableRuns.keys()]).size + uncountedBillableInflight + (deps.leaderEndpoint?.inflight?.() ?? 0);
|
|
184
|
+
let lastBillableActivityAt = Date.now();
|
|
185
|
+
const noteActivity = (url) => {
|
|
186
|
+
if (url === "/health" || url.startsWith("/metrics"))
|
|
187
|
+
return;
|
|
188
|
+
lastBillableActivityAt = Date.now();
|
|
189
|
+
};
|
|
190
|
+
if (deps.drainState)
|
|
191
|
+
deps.drainState.lastActivityAt = () => lastBillableActivityAt;
|
|
184
192
|
if (deps.hookWakeBus) {
|
|
185
193
|
deps.hookWakeBus.deliver = async (sessionId, text) => {
|
|
186
194
|
try {
|
|
@@ -249,6 +257,7 @@ export function createHttpServer(deps) {
|
|
|
249
257
|
const startedAt = Date.now();
|
|
250
258
|
const method = req.method ?? "GET";
|
|
251
259
|
const url = (req.url ?? "/").split("?")[0];
|
|
260
|
+
noteActivity(url);
|
|
252
261
|
let logged = false;
|
|
253
262
|
const record = (viaClose) => {
|
|
254
263
|
if (logged)
|
|
@@ -674,6 +683,7 @@ export function createHttpServer(deps) {
|
|
|
674
683
|
}, 15_000);
|
|
675
684
|
let ranLive = false;
|
|
676
685
|
let resp;
|
|
686
|
+
uncountedBillableInflight++;
|
|
677
687
|
try {
|
|
678
688
|
resp = await idemCache.run(idemKey, async () => {
|
|
679
689
|
ranLive = true;
|
|
@@ -725,7 +735,7 @@ export function createHttpServer(deps) {
|
|
|
725
735
|
let liveStreamRef;
|
|
726
736
|
const subagentHandleEvictions = [];
|
|
727
737
|
let syncLegLive = true;
|
|
728
|
-
const syncNotifiedKeys = new
|
|
738
|
+
const syncNotifiedKeys = new NotifiedKeys();
|
|
729
739
|
fleetPub?.onStart();
|
|
730
740
|
try {
|
|
731
741
|
const streamBody = async () => {
|
|
@@ -767,9 +777,9 @@ export function createHttpServer(deps) {
|
|
|
767
777
|
void deps.workflowCompletionInbox.enqueue(taskNotificationInboxEntry(prepared.spec.sessionId, askOwner, n, Date.now(), durableTaskId)).catch((err) => deps.logger?.warn?.("park_enqueue_failed", { route: "sync-stream", taskId: n.task_id, err: err instanceof Error ? err.message : String(err) }));
|
|
768
778
|
}
|
|
769
779
|
else if (deliverable) {
|
|
770
|
-
const key =
|
|
771
|
-
if (
|
|
772
|
-
syncNotifiedKeys.
|
|
780
|
+
const key = taskNotificationStreamKey(n);
|
|
781
|
+
if (syncNotifiedKeys.get(key) === undefined) {
|
|
782
|
+
syncNotifiedKeys.set(key, Promise.resolve(true));
|
|
773
783
|
res.write(`data: ${JSON.stringify({ type: "task_notification", ...taskNotificationEventData({ notification: n }) })}\n\n`);
|
|
774
784
|
}
|
|
775
785
|
}
|
|
@@ -814,9 +824,13 @@ export function createHttpServer(deps) {
|
|
|
814
824
|
}
|
|
815
825
|
else if (ev.type === "task_notification") {
|
|
816
826
|
const tnv = ev.notification;
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
827
|
+
const tnvKey = tnv?.task_id ? taskNotificationStreamKey({ task_type: tnv.task_type, task_id: tnv.task_id, status: String(tnv.status), seq: tnv.seq }) : undefined;
|
|
828
|
+
const tnvPrior = tnvKey !== undefined ? syncNotifiedKeys.get(tnvKey) : undefined;
|
|
829
|
+
if (tnvPrior === undefined || !(await tnvPrior)) {
|
|
830
|
+
if (tnvKey !== undefined)
|
|
831
|
+
syncNotifiedKeys.set(tnvKey, Promise.resolve(true));
|
|
832
|
+
res.write(`data: ${JSON.stringify({ type: "task_notification", ...taskNotificationEventData(ev) })}\n\n`);
|
|
833
|
+
}
|
|
820
834
|
}
|
|
821
835
|
else if (ev.type === "reasoning_delta" && typeof ev.delta === "string") {
|
|
822
836
|
res.write(`data: ${JSON.stringify({ ...ev, delta: redactSecrets(ev.delta) })}\n\n`);
|
|
@@ -845,6 +859,9 @@ export function createHttpServer(deps) {
|
|
|
845
859
|
await emitPendingWorkflowCompletions(deps.workflowCompletionInbox, prepared.spec.sessionId, askOwner, (frame) => {
|
|
846
860
|
if (closed || res.writableEnded || res.destroyed)
|
|
847
861
|
throw new Error("stream ended before the completion frame was written");
|
|
862
|
+
const f = frame;
|
|
863
|
+
if (f.type === "task_notification" && f.task_id)
|
|
864
|
+
syncNotifiedKeys.set(taskNotificationStreamKey({ task_type: f.task_type, task_id: f.task_id, status: String(f.status), seq: f.seq }), Promise.resolve(true));
|
|
848
865
|
res.write(`data: ${JSON.stringify(frame)}\n\n`);
|
|
849
866
|
}, { route: "sync-stream-open", connection: "live-sse", log: (m, x) => deps.logger?.info?.(m, x) });
|
|
850
867
|
const withElicit = deps.elicitation
|
|
@@ -896,6 +913,7 @@ export function createHttpServer(deps) {
|
|
|
896
913
|
throw e;
|
|
897
914
|
}
|
|
898
915
|
finally {
|
|
916
|
+
uncountedBillableInflight--;
|
|
899
917
|
clearInterval(hb);
|
|
900
918
|
}
|
|
901
919
|
if (!ranLive && resp && !res.writableEnded) {
|
|
@@ -3780,11 +3798,15 @@ export function createHttpServer(deps) {
|
|
|
3780
3798
|
}
|
|
3781
3799
|
try {
|
|
3782
3800
|
result = await withPrincipal(principal, async () => {
|
|
3801
|
+
const resumeNotifiedKeys = new NotifiedKeys();
|
|
3783
3802
|
if (deps.runStore && taskId) {
|
|
3784
3803
|
const rs0 = deps.runStore;
|
|
3785
3804
|
let drainSeq = (await rs0.maxSeq(taskId)) + 1;
|
|
3786
3805
|
await emitPendingWorkflowCompletions(deps.workflowCompletionInbox, sessionId, principal ?? null, (frame) => {
|
|
3787
3806
|
const { type, ...rest } = frame;
|
|
3807
|
+
const f = frame;
|
|
3808
|
+
if (f.type === "task_notification" && f.task_id)
|
|
3809
|
+
resumeNotifiedKeys.set(taskNotificationStreamKey({ task_type: f.task_type, task_id: f.task_id, status: String(f.status), seq: f.seq }), Promise.resolve(true));
|
|
3788
3810
|
return rs0.appendEvent(taskId, drainSeq++, type, rest);
|
|
3789
3811
|
}, { route: "resume-open", connection: "durable-append", log: (m, x) => deps.logger?.info?.(m, x) });
|
|
3790
3812
|
}
|
|
@@ -3817,7 +3839,6 @@ export function createHttpServer(deps) {
|
|
|
3817
3839
|
let reasoning = "";
|
|
3818
3840
|
const persistThinking = deps.config.traceThinking;
|
|
3819
3841
|
const append = (type, data) => (rs && taskId ? rs.appendEvent(taskId, ++seq, type, data) : Promise.resolve());
|
|
3820
|
-
const resumeNotifiedKeys = new Set();
|
|
3821
3842
|
const anchorOwner = principal ?? null;
|
|
3822
3843
|
const getLeafId = deps.sessionStorage?.getLeafId?.bind(deps.sessionStorage);
|
|
3823
3844
|
const captureTurnAnchor = deps.resumeAnchorStore && getLeafId
|
|
@@ -3866,10 +3887,9 @@ export function createHttpServer(deps) {
|
|
|
3866
3887
|
void deps.workflowCompletionInbox.enqueue(taskNotificationInboxEntry(sessionId, principal ?? null, n, Date.now(), taskId)).catch((err) => deps.logger?.warn?.("park_enqueue_failed", { route: "resume", taskId: n.task_id, err: err instanceof Error ? err.message : String(err) }));
|
|
3867
3888
|
}
|
|
3868
3889
|
else if (resumeLegLive) {
|
|
3869
|
-
const key =
|
|
3870
|
-
if (
|
|
3871
|
-
resumeNotifiedKeys.
|
|
3872
|
-
void append("task_notification", taskNotificationEventData({ notification: n })).catch(() => undefined);
|
|
3890
|
+
const key = taskNotificationStreamKey(n);
|
|
3891
|
+
if (resumeNotifiedKeys.get(key) === undefined) {
|
|
3892
|
+
resumeNotifiedKeys.set(key, append("task_notification", taskNotificationEventData({ notification: n })).then(() => true, () => false));
|
|
3873
3893
|
}
|
|
3874
3894
|
}
|
|
3875
3895
|
},
|
|
@@ -3930,9 +3950,14 @@ export function createHttpServer(deps) {
|
|
|
3930
3950
|
case "task_notification": {
|
|
3931
3951
|
await flush();
|
|
3932
3952
|
const tnr = ev.notification;
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3953
|
+
const tnrKey = tnr?.task_id ? taskNotificationStreamKey({ task_type: tnr.task_type, task_id: tnr.task_id, status: String(tnr.status), seq: tnr.seq }) : undefined;
|
|
3954
|
+
const tnrPrior = tnrKey !== undefined ? resumeNotifiedKeys.get(tnrKey) : undefined;
|
|
3955
|
+
if (tnrPrior === undefined || !(await tnrPrior)) {
|
|
3956
|
+
const write = append("task_notification", taskNotificationEventData(ev));
|
|
3957
|
+
if (tnrKey !== undefined)
|
|
3958
|
+
resumeNotifiedKeys.set(tnrKey, write.then(() => true, () => false));
|
|
3959
|
+
await write;
|
|
3960
|
+
}
|
|
3936
3961
|
break;
|
|
3937
3962
|
}
|
|
3938
3963
|
case "turn_end": {
|