@deepseek-ai/dsh-api-session-controller 0.1.5-rc.2 → 0.1.6-alpha.2
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.i18n.yaml +2 -2
- package/README.md +20 -4
- package/README.zh.md +26 -10
- package/lib/client.js +432 -474
- package/lib/index.js +18 -49
- package/lib/typert.host.js +242 -200
- package/lib/typert.remote-client.js +195 -165
- package/lib/types/agent.d.ts +1 -1
- package/lib/types/agent.js +8 -1
- package/lib/types/client/contract/sessions.d.ts +55 -20
- package/lib/types/client/contract/snapshot.d.ts +0 -14
- package/lib/types/client/index.d.ts +11 -2
- package/lib/types/client/index.js +16 -5
- package/lib/types/client/scope.d.ts +13 -3
- package/lib/types/client/scope.js +15 -22
- package/lib/types/client/sessions/lineage.d.ts +1 -4
- package/lib/types/client/sessions/lineage.js +1 -3
- package/lib/types/client/sessions/manager.d.ts +28 -49
- package/lib/types/client/sessions/manager.js +75 -174
- package/lib/types/client/sessions/projection-store.d.ts +5 -11
- package/lib/types/client/sessions/projection-store.js +6 -14
- package/lib/types/client/sessions/service.d.ts +34 -119
- package/lib/types/client/sessions/service.js +259 -244
- package/lib/types/client/sessions/session.d.ts +7 -20
- package/lib/types/client/sessions/session.js +29 -33
- package/lib/types/client/time-zone.d.ts +1 -1
- package/lib/types/client/time-zone.js +1 -1
- package/lib/types/commands.d.ts +2 -2
- package/lib/types/commands.js +13 -8
- package/lib/types/control.d.ts +1 -1
- package/lib/types/control.js +1 -41
- package/lib/types/history.js +1 -0
- package/lib/types/index.d.ts +2 -2
- package/lib/types/index.js +2 -1
- package/lib/types/skill-catalog.js +1 -0
- package/lib/types/types.d.ts +5 -17
- package/package.json +72 -69
- package/lib/types/client/sessions/queue-mirror.d.ts +0 -26
- package/lib/types/client/sessions/queue-mirror.js +0 -61
package/lib/index.js
CHANGED
|
@@ -227,7 +227,8 @@ var ApiSessionAgentController = class {
|
|
|
227
227
|
this.resumes.set(sessionId, resume);
|
|
228
228
|
}
|
|
229
229
|
try {
|
|
230
|
-
|
|
230
|
+
const agent = await resume;
|
|
231
|
+
return this.liveAgent(sessionId) ?? { agent };
|
|
231
232
|
} catch (error) {
|
|
232
233
|
if (error instanceof ApiSessionNotFound) return { error: new RemoteError("session/not-found", error.message, { sessionId }) };
|
|
233
234
|
if (error instanceof ApiSessionSubagentOwnership) return { error: apiSessionSubagentOwnershipError(error.sessionId) };
|
|
@@ -235,6 +236,7 @@ var ApiSessionAgentController = class {
|
|
|
235
236
|
if (raced !== void 0) return raced;
|
|
236
237
|
const racedSession = this.ctx.sessions.get(sessionId);
|
|
237
238
|
if (racedSession !== void 0 && hasApiSessionSubagentOwner(this.ctx, racedSession, void 0)) return { error: apiSessionSubagentOwnershipError(sessionId) };
|
|
239
|
+
if (error instanceof Error && error.name === "SessionAlreadyOwnedError") return { error: new RemoteError("session/writer-held", error.message, { sessionId }) };
|
|
238
240
|
return { error: new RemoteError("gateway/internal", `resume failed for session "${sessionId}": ${String(error)}`, {}) };
|
|
239
241
|
}
|
|
240
242
|
}
|
|
@@ -681,8 +683,7 @@ var SessionCommandController = class {
|
|
|
681
683
|
const lastSeq = source.events.at(-1)?.seq ?? -1;
|
|
682
684
|
const boundary = (atSeq === void 0 ? void 0 : source.events.find((event) => event.type === "turn/end" && event.seq >= atSeq)) ?? (atSeq === void 0 || atSeq > lastSeq ? source.events.findLast((event) => event.type === "turn/end") : void 0);
|
|
683
685
|
if (boundary === void 0) throw new RemoteError("session/fork-unavailable", atSeq !== void 0 && atSeq <= lastSeq ? `session "${request.sessionId}" has not completed the turn containing event ${String(atSeq)}` : `session "${request.sessionId}" has no completed turn to fork from`, { sessionId: request.sessionId });
|
|
684
|
-
|
|
685
|
-
while (cut < source.events.length && source.events[cut]?.type !== "turn/start") cut = SessionLogOffset(cut + 1);
|
|
686
|
+
const cut = SessionLogOffset(boundary.seq + 1);
|
|
686
687
|
let workspace;
|
|
687
688
|
try {
|
|
688
689
|
workspace = await this.forkWorkspace(source.header);
|
|
@@ -815,17 +816,24 @@ var SessionCommandController = class {
|
|
|
815
816
|
}
|
|
816
817
|
}
|
|
817
818
|
/**
|
|
818
|
-
* Mutate one
|
|
819
|
+
* Mutate one pending Inbox occurrence, restoring an ordinary cold Agent when needed.
|
|
819
820
|
* @param request - Session, queue item, and requested mutation.
|
|
820
821
|
* @returns acknowledgement that the queue mutation was applied.
|
|
821
822
|
*/
|
|
822
|
-
updateQueue(request) {
|
|
823
|
+
async updateQueue(request) {
|
|
823
824
|
if (request.action.kind === "edit") {
|
|
824
825
|
if (request.action.content.some((block) => block.type !== "text")) throw new RemoteError("session/attachment-invalid", "queue edits accept text content only", { reason: "QUEUE_EDIT_NON_TEXT" });
|
|
825
826
|
if (!hasPromptContent(request.action.content)) throw new RemoteError("gateway/bad-request", "queue edit content must include non-whitespace text", {});
|
|
826
827
|
}
|
|
827
|
-
|
|
828
|
-
if (agent === void 0)
|
|
828
|
+
let agent = this.ctx.agents.get(request.sessionId);
|
|
829
|
+
if (agent === void 0) {
|
|
830
|
+
const found = await this.agents.resolveAgent(request.sessionId);
|
|
831
|
+
if ("error" in found) {
|
|
832
|
+
if (found.error.code !== "session/not-found") throw found.error;
|
|
833
|
+
throw new RemoteError("session/queue-item-not-found", "queued item is no longer pending", { itemId: request.itemId });
|
|
834
|
+
}
|
|
835
|
+
agent = found.agent;
|
|
836
|
+
}
|
|
829
837
|
if (hasApiSessionSubagentOwner(this.ctx, agent.session, agent)) {
|
|
830
838
|
const identity = this.ctx.sessionProjections.snapshot(agent.session, ["subagent"]).values.subagent;
|
|
831
839
|
if (identity?.mode !== "continuable" || !agent.session.isOwnSeq(identity.seq)) throw apiSessionSubagentOwnershipError(request.sessionId);
|
|
@@ -990,7 +998,7 @@ function routeServed(ctx, provider) {
|
|
|
990
998
|
}
|
|
991
999
|
//#endregion
|
|
992
1000
|
//#region lib/types/control.js
|
|
993
|
-
/** Live Session
|
|
1001
|
+
/** Live Session jobs and projection state with reconnect baselines. */
|
|
994
1002
|
/** Owns the Host-wide Session control stream. */
|
|
995
1003
|
var SessionControlController = class {
|
|
996
1004
|
ctx;
|
|
@@ -1006,13 +1014,6 @@ var SessionControlController = class {
|
|
|
1006
1014
|
value,
|
|
1007
1015
|
seq
|
|
1008
1016
|
});
|
|
1009
|
-
if (key !== "inbox") return;
|
|
1010
|
-
if (this.ctx.agents.get(session.id)?.session !== session) return;
|
|
1011
|
-
this.broadcast({
|
|
1012
|
-
type: "queue",
|
|
1013
|
-
sessionId: session.id,
|
|
1014
|
-
items: queueItemsFromInbox(value)
|
|
1015
|
-
});
|
|
1016
1017
|
});
|
|
1017
1018
|
ctx.inject(["jobs"], (jobsCtx) => {
|
|
1018
1019
|
jobsCtx.jobs.onJobsChanged((owner) => {
|
|
@@ -1054,15 +1055,12 @@ var SessionControlController = class {
|
|
|
1054
1055
|
}
|
|
1055
1056
|
baseline() {
|
|
1056
1057
|
const sessions = this.ctx.sessions.list();
|
|
1057
|
-
const queues = Object.create(null);
|
|
1058
1058
|
const jobs = Object.create(null);
|
|
1059
1059
|
for (const session of sessions) {
|
|
1060
1060
|
const agent = this.ctx.agents.get(session.id);
|
|
1061
|
-
queues[session.id] = agent?.session === session ? queueItems(agent) : [];
|
|
1062
1061
|
jobs[session.id] = this.jobsFor(agent);
|
|
1063
1062
|
}
|
|
1064
1063
|
return {
|
|
1065
|
-
queues,
|
|
1066
1064
|
jobs,
|
|
1067
1065
|
projections: this.projectionBaseline(sessions)
|
|
1068
1066
|
};
|
|
@@ -1142,36 +1140,6 @@ var ControlQueue = class {
|
|
|
1142
1140
|
}
|
|
1143
1141
|
}
|
|
1144
1142
|
};
|
|
1145
|
-
function queueItems(agent) {
|
|
1146
|
-
return queueItemsFromInbox({
|
|
1147
|
-
"next-turn": agent.inbox.nextTurn,
|
|
1148
|
-
"next-step": agent.inbox.nextStep
|
|
1149
|
-
});
|
|
1150
|
-
}
|
|
1151
|
-
function queueItemsFromInbox(inbox) {
|
|
1152
|
-
return [...inbox["next-turn"].map((message) => ({
|
|
1153
|
-
id: message.id,
|
|
1154
|
-
placement: "queued",
|
|
1155
|
-
...promptRpcId(message),
|
|
1156
|
-
message: {
|
|
1157
|
-
id: message.id,
|
|
1158
|
-
content: message.content
|
|
1159
|
-
}
|
|
1160
|
-
})), ...inbox["next-step"].map((message) => ({
|
|
1161
|
-
id: message.id,
|
|
1162
|
-
placement: message.source.kind === "user" ? "steering" : "context",
|
|
1163
|
-
...promptRpcId(message),
|
|
1164
|
-
message: {
|
|
1165
|
-
id: message.id,
|
|
1166
|
-
content: message.content
|
|
1167
|
-
}
|
|
1168
|
-
}))];
|
|
1169
|
-
}
|
|
1170
|
-
/** Prompt-RPC identity carried by a browser-submitted message's user source. */
|
|
1171
|
-
function promptRpcId(message) {
|
|
1172
|
-
const source = message.source;
|
|
1173
|
-
return source.kind === "user" && "rpcId" in source ? { rpcId: source.rpcId } : {};
|
|
1174
|
-
}
|
|
1175
1143
|
function jobView(job) {
|
|
1176
1144
|
return {
|
|
1177
1145
|
id: job.id,
|
|
@@ -2279,6 +2247,7 @@ let SessionSkillCatalog = (() => {
|
|
|
2279
2247
|
scope
|
|
2280
2248
|
})).filter(isUserInvocable).map((skill) => ({
|
|
2281
2249
|
name: skill.name,
|
|
2250
|
+
...skill.path === void 0 ? {} : { path: skill.path },
|
|
2282
2251
|
description: skill.description,
|
|
2283
2252
|
...skill.whenToUse === void 0 ? {} : { whenToUse: skill.whenToUse },
|
|
2284
2253
|
modelInvocable: skill.invocation.modelInvocable
|
|
@@ -2930,7 +2899,7 @@ let SessionController = (() => {
|
|
|
2930
2899
|
return this.commands.attachment(request);
|
|
2931
2900
|
}
|
|
2932
2901
|
/**
|
|
2933
|
-
* Mutate one still-pending queue occurrence
|
|
2902
|
+
* Mutate one still-pending queue occurrence, resuming a cold Agent first.
|
|
2934
2903
|
* @param request - Session, queue item, and requested mutation.
|
|
2935
2904
|
* @returns acknowledgement that the queue mutation was applied.
|
|
2936
2905
|
*/
|