@deepseek-ai/dsh-api-session-controller 0.1.7-alpha.2 → 0.1.7-rc.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 +39 -5
- package/README.md +4 -2
- package/README.zh.md +4 -2
- package/lib/client.js +27 -3
- package/lib/index.js +140 -73
- package/lib/typert.host.js +168 -96
- package/lib/typert.remote-client.d.ts +2 -0
- package/lib/typert.remote-client.js +31 -14
- package/lib/types/catalog.d.ts +13 -0
- package/lib/types/catalog.js +52 -3
- package/lib/types/client/sessions/assistant-stream.d.ts +5 -0
- package/lib/types/client/sessions/assistant-stream.js +16 -1
- package/lib/types/client/sessions/session.js +6 -2
- package/lib/types/commands.d.ts +3 -2
- package/lib/types/commands.js +11 -14
- package/lib/types/index.d.ts +7 -2
- package/lib/types/index.js +24 -4
- package/lib/types/types.d.ts +5 -1
- package/package.json +76 -69
|
@@ -371,6 +371,8 @@ let _deepseek_ai_dsh_api_session_controller_session_fork_result$schema$value
|
|
|
371
371
|
const _deepseek_ai_dsh_api_session_controller_session_fork_result$schema = () => (_deepseek_ai_dsh_api_session_controller_session_fork_result$schema$value ??= z.object({
|
|
372
372
|
'sessionId': z.intersection(z.string(), z.unknown()).readonly(),
|
|
373
373
|
}))
|
|
374
|
+
let _deepseek_ai_dsh_api_session_controller_session_initializeDefaultModel_result$schema$value
|
|
375
|
+
const _deepseek_ai_dsh_api_session_controller_session_initializeDefaultModel_result$schema = () => (_deepseek_ai_dsh_api_session_controller_session_initializeDefaultModel_result$schema$value ??= z.void())
|
|
374
376
|
let _deepseek_ai_dsh_api_session_controller_session_list_parameter_0$schema$value
|
|
375
377
|
const _deepseek_ai_dsh_api_session_controller_session_list_parameter_0$schema = () => (_deepseek_ai_dsh_api_session_controller_session_list_parameter_0$schema$value ??= z.object({
|
|
376
378
|
'cursor': z.string().readonly().optional(),
|
|
@@ -831,7 +833,7 @@ export const TYPERT_REMOTE = {
|
|
|
831
833
|
typeSymbol: '@deepseek-ai/dsh-api-session-controller/types#SessionAttachmentValue',
|
|
832
834
|
create: _deepseek_ai_dsh_api_session_controller_session_attachment_result$schema,
|
|
833
835
|
},
|
|
834
|
-
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":
|
|
836
|
+
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":437,"column":3},
|
|
835
837
|
},
|
|
836
838
|
{
|
|
837
839
|
id: '@deepseek-ai/dsh-api-session-controller#session/cancel',
|
|
@@ -856,7 +858,7 @@ export const TYPERT_REMOTE = {
|
|
|
856
858
|
typeSymbol: '@deepseek-ai/dsh-api-session-controller/types#SessionCancelValue',
|
|
857
859
|
create: _deepseek_ai_dsh_api_session_controller_session_cancel_result$schema,
|
|
858
860
|
},
|
|
859
|
-
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":
|
|
861
|
+
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":457,"column":3},
|
|
860
862
|
},
|
|
861
863
|
{
|
|
862
864
|
id: '@deepseek-ai/dsh-api-session-controller#session/canOpenWorkspacePath',
|
|
@@ -871,7 +873,7 @@ export const TYPERT_REMOTE = {
|
|
|
871
873
|
typeSymbol: '@deepseek-ai/dsh-api-session-controller#session/canOpenWorkspacePath:result',
|
|
872
874
|
create: _deepseek_ai_dsh_api_session_controller_session_canOpenWorkspacePath_result$schema,
|
|
873
875
|
},
|
|
874
|
-
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":
|
|
876
|
+
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":319,"column":3},
|
|
875
877
|
},
|
|
876
878
|
{
|
|
877
879
|
id: '@deepseek-ai/dsh-api-session-controller#session/control',
|
|
@@ -888,7 +890,7 @@ export const TYPERT_REMOTE = {
|
|
|
888
890
|
typeSymbol: '@deepseek-ai/dsh-api-session-controller/types#SessionControlFrame',
|
|
889
891
|
create: _deepseek_ai_dsh_api_session_controller_session_control_result$schema,
|
|
890
892
|
},
|
|
891
|
-
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":
|
|
893
|
+
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":520,"column":3},
|
|
892
894
|
},
|
|
893
895
|
{
|
|
894
896
|
id: '@deepseek-ai/dsh-api-session-controller#session/create',
|
|
@@ -940,7 +942,7 @@ export const TYPERT_REMOTE = {
|
|
|
940
942
|
typeSymbol: '@deepseek-ai/dsh-api-session-controller/types#SessionFollowFrame',
|
|
941
943
|
create: _deepseek_ai_dsh_api_session_controller_session_follow_result$schema,
|
|
942
944
|
},
|
|
943
|
-
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":
|
|
945
|
+
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":480,"column":3},
|
|
944
946
|
},
|
|
945
947
|
{
|
|
946
948
|
id: '@deepseek-ai/dsh-api-session-controller#session/fork',
|
|
@@ -965,7 +967,22 @@ export const TYPERT_REMOTE = {
|
|
|
965
967
|
typeSymbol: '@deepseek-ai/dsh-api-session-controller/types#SessionForkValue',
|
|
966
968
|
create: _deepseek_ai_dsh_api_session_controller_session_fork_result$schema,
|
|
967
969
|
},
|
|
968
|
-
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":
|
|
970
|
+
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":415,"column":3},
|
|
971
|
+
},
|
|
972
|
+
{
|
|
973
|
+
id: '@deepseek-ai/dsh-api-session-controller#session/initializeDefaultModel',
|
|
974
|
+
service: 'sessionController',
|
|
975
|
+
namespace: 'session',
|
|
976
|
+
method: 'initializeDefaultModel',
|
|
977
|
+
invocation: { kind: 'direct' },
|
|
978
|
+
parameters: [
|
|
979
|
+
],
|
|
980
|
+
result: {
|
|
981
|
+
mode: 'strict',
|
|
982
|
+
typeSymbol: '@deepseek-ai/dsh-api-session-controller#session/initializeDefaultModel:result',
|
|
983
|
+
create: _deepseek_ai_dsh_api_session_controller_session_initializeDefaultModel_result$schema,
|
|
984
|
+
},
|
|
985
|
+
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":292,"column":9},
|
|
969
986
|
},
|
|
970
987
|
{
|
|
971
988
|
id: '@deepseek-ai/dsh-api-session-controller#session/list',
|
|
@@ -1006,7 +1023,7 @@ export const TYPERT_REMOTE = {
|
|
|
1006
1023
|
typeSymbol: '@deepseek-ai/dsh-api-session-controller/types#ModelCatalog',
|
|
1007
1024
|
create: _deepseek_ai_dsh_api_session_controller_session_modelCatalog_result$schema,
|
|
1008
1025
|
},
|
|
1009
|
-
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":
|
|
1026
|
+
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":310,"column":3},
|
|
1010
1027
|
},
|
|
1011
1028
|
{
|
|
1012
1029
|
id: '@deepseek-ai/dsh-api-session-controller#session/openWorkspacePath',
|
|
@@ -1032,7 +1049,7 @@ export const TYPERT_REMOTE = {
|
|
|
1032
1049
|
typeSymbol: '@deepseek-ai/dsh-api-session-controller/types#SessionOpenWorkspacePathValue',
|
|
1033
1050
|
create: _deepseek_ai_dsh_api_session_controller_session_openWorkspacePath_result$schema,
|
|
1034
1051
|
},
|
|
1035
|
-
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":
|
|
1052
|
+
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":340,"column":9},
|
|
1036
1053
|
},
|
|
1037
1054
|
{
|
|
1038
1055
|
id: '@deepseek-ai/dsh-api-session-controller#session/page',
|
|
@@ -1058,7 +1075,7 @@ export const TYPERT_REMOTE = {
|
|
|
1058
1075
|
typeSymbol: '@deepseek-ai/dsh-api-session-controller/types#SessionPage',
|
|
1059
1076
|
create: _deepseek_ai_dsh_api_session_controller_session_page_result$schema,
|
|
1060
1077
|
},
|
|
1061
|
-
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":
|
|
1078
|
+
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":468,"column":3},
|
|
1062
1079
|
},
|
|
1063
1080
|
{
|
|
1064
1081
|
id: '@deepseek-ai/dsh-api-session-controller#session/projections',
|
|
@@ -1084,7 +1101,7 @@ export const TYPERT_REMOTE = {
|
|
|
1084
1101
|
typeSymbol: '@deepseek-ai/dsh-api-session-controller/types#SessionProjectionsValue',
|
|
1085
1102
|
create: _deepseek_ai_dsh_api_session_controller_session_projections_result$schema,
|
|
1086
1103
|
},
|
|
1087
|
-
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":
|
|
1104
|
+
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":491,"column":9},
|
|
1088
1105
|
},
|
|
1089
1106
|
{
|
|
1090
1107
|
id: '@deepseek-ai/dsh-api-session-controller#session/prompt',
|
|
@@ -1110,7 +1127,7 @@ export const TYPERT_REMOTE = {
|
|
|
1110
1127
|
typeSymbol: '@deepseek-ai/dsh-api-session-controller/types#SessionPromptValue',
|
|
1111
1128
|
create: _deepseek_ai_dsh_api_session_controller_session_prompt_result$schema,
|
|
1112
1129
|
},
|
|
1113
|
-
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":
|
|
1130
|
+
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":426,"column":3},
|
|
1114
1131
|
},
|
|
1115
1132
|
{
|
|
1116
1133
|
id: '@deepseek-ai/dsh-api-session-controller#session/rename',
|
|
@@ -1135,7 +1152,7 @@ export const TYPERT_REMOTE = {
|
|
|
1135
1152
|
typeSymbol: '@deepseek-ai/dsh-api-session-controller/types#SessionRenameValue',
|
|
1136
1153
|
create: _deepseek_ai_dsh_api_session_controller_session_rename_result$schema,
|
|
1137
1154
|
},
|
|
1138
|
-
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":
|
|
1155
|
+
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":403,"column":3},
|
|
1139
1156
|
},
|
|
1140
1157
|
{
|
|
1141
1158
|
id: '@deepseek-ai/dsh-api-session-controller#session/search',
|
|
@@ -1211,7 +1228,7 @@ export const TYPERT_REMOTE = {
|
|
|
1211
1228
|
typeSymbol: '@deepseek-ai/dsh-api-session-controller/types#SessionUpdateQueueValue',
|
|
1212
1229
|
create: _deepseek_ai_dsh_api_session_controller_session_updateQueue_result$schema,
|
|
1213
1230
|
},
|
|
1214
|
-
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":
|
|
1231
|
+
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":447,"column":3},
|
|
1215
1232
|
},
|
|
1216
1233
|
{
|
|
1217
1234
|
id: '@deepseek-ai/dsh-api-session-controller#session/workspacePathApplications',
|
|
@@ -1237,7 +1254,7 @@ export const TYPERT_REMOTE = {
|
|
|
1237
1254
|
typeSymbol: '@deepseek-ai/dsh-api-session-controller#session/workspacePathApplications:result',
|
|
1238
1255
|
create: _deepseek_ai_dsh_api_session_controller_session_workspacePathApplications_result$schema,
|
|
1239
1256
|
},
|
|
1240
|
-
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":
|
|
1257
|
+
sourceLocation: {"file":"packages/api/session-controller/src/index.ts","line":370,"column":9},
|
|
1241
1258
|
},
|
|
1242
1259
|
{
|
|
1243
1260
|
id: '@deepseek-ai/dsh-api-session-controller#skills/list',
|
package/lib/types/catalog.d.ts
CHANGED
|
@@ -8,4 +8,17 @@ import type { ModelCatalog, ModelSelection } from './types.ts';
|
|
|
8
8
|
* @returns successful non-empty provider groups and isolated provider failures.
|
|
9
9
|
*/
|
|
10
10
|
export declare function buildModelCatalog(ctx: Context, defaultSelection?: ModelSelection): Promise<ModelCatalog>;
|
|
11
|
+
/**
|
|
12
|
+
* Check a GUI selection against the current available provider catalog.
|
|
13
|
+
* @param ctx - Host LLM registry.
|
|
14
|
+
* @param selection - stored or explicitly requested selection.
|
|
15
|
+
* @returns whether the exact model is currently advertised as available.
|
|
16
|
+
*/
|
|
17
|
+
export declare function modelAvailable(ctx: Context, selection: ModelSelection): Promise<boolean>;
|
|
18
|
+
/**
|
|
19
|
+
* Check configured provider API-key references independently of model availability.
|
|
20
|
+
* @param ctx - Host registry, settings, and credential services.
|
|
21
|
+
* @returns whether any API-key provider has a configured credential.
|
|
22
|
+
*/
|
|
23
|
+
export declare function hasProviderApiKey(ctx: Context): Promise<boolean>;
|
|
11
24
|
//# sourceMappingURL=catalog.d.ts.map
|
package/lib/types/catalog.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/** Shared projection of the live LLM registry into the browser model catalog. */
|
|
2
|
+
import { RemoteError } from '@deepseek-ai/dsh-typert-protocol';
|
|
3
|
+
import { credentialRef } from '@deepseek-ai/dsh-credentials';
|
|
2
4
|
/**
|
|
3
5
|
* Build the browser model catalog without requiring a Session.
|
|
4
6
|
* @param ctx - Host context carrying the live LLM registry.
|
|
@@ -47,12 +49,59 @@ export async function buildModelCatalog(ctx, defaultSelection = ctx.agentDefault
|
|
|
47
49
|
};
|
|
48
50
|
}
|
|
49
51
|
}));
|
|
52
|
+
const groups = catalog.flatMap(item => item.kind === 'group' ? [item.group] : [])
|
|
53
|
+
.filter(group => group.models.length > 0);
|
|
50
54
|
return {
|
|
51
55
|
default: { ...defaultSelection },
|
|
52
|
-
routableProviders:
|
|
53
|
-
groups
|
|
54
|
-
.filter(group => group.models.length > 0),
|
|
56
|
+
routableProviders: groups.map(group => group.id),
|
|
57
|
+
groups,
|
|
55
58
|
failures: catalog.flatMap(item => item.kind === 'failure' ? [item.failure] : []),
|
|
56
59
|
};
|
|
57
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Check a GUI selection against the current available provider catalog.
|
|
63
|
+
* @param ctx - Host LLM registry.
|
|
64
|
+
* @param selection - stored or explicitly requested selection.
|
|
65
|
+
* @returns whether the exact model is currently advertised as available.
|
|
66
|
+
*/
|
|
67
|
+
export async function modelAvailable(ctx, selection) {
|
|
68
|
+
if (!ctx.llm.listProviders().some(provider => provider.id === selection.provider))
|
|
69
|
+
return false;
|
|
70
|
+
let models;
|
|
71
|
+
try {
|
|
72
|
+
models = await ctx.llm.listModels(selection.provider);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
throw new RemoteError('session/model-unavailable', error instanceof Error ? error.message : String(error), { provider: selection.provider, model: selection.model });
|
|
76
|
+
}
|
|
77
|
+
return models.some(model => model.id === selection.model);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Check configured provider API-key references independently of model availability.
|
|
81
|
+
* @param ctx - Host registry, settings, and credential services.
|
|
82
|
+
* @returns whether any API-key provider has a configured credential.
|
|
83
|
+
*/
|
|
84
|
+
export async function hasProviderApiKey(ctx) {
|
|
85
|
+
const settings = ctx.get('settings');
|
|
86
|
+
const credentials = ctx.get('credentials');
|
|
87
|
+
if (settings === undefined || credentials === undefined) {
|
|
88
|
+
throw new RemoteError('session/provider-credentials-unavailable', 'provider credentials are unavailable', {});
|
|
89
|
+
}
|
|
90
|
+
const namespaces = settings.describe({ redactSecrets: true });
|
|
91
|
+
for (const provider of ctx.llm.listConfigurableProviders()) {
|
|
92
|
+
if (provider.provider === 'deepseek-account')
|
|
93
|
+
continue;
|
|
94
|
+
let profile = namespaces.find(namespace => namespace.ns === provider.settingsNs)?.value;
|
|
95
|
+
for (const key of provider.settingsPath) {
|
|
96
|
+
profile = typeof profile === 'object' && profile !== null ? Reflect.get(profile, key) : undefined;
|
|
97
|
+
}
|
|
98
|
+
if (typeof profile !== 'object' || profile === null)
|
|
99
|
+
continue;
|
|
100
|
+
const ref = Reflect.get(profile, 'apiKeyEnv');
|
|
101
|
+
if (typeof ref === 'string' && ref.length > 0
|
|
102
|
+
&& (await credentials.describe(credentialRef(ref))).configured)
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
58
107
|
//# sourceMappingURL=catalog.js.map
|
|
@@ -6,6 +6,8 @@ import type { SessionAssistantSettlementEntry, SessionEventLikeEntry, SessionLiv
|
|
|
6
6
|
export type ClientAssistantStreamResult = {
|
|
7
7
|
readonly type: 'publish';
|
|
8
8
|
readonly entry: SessionLiveEventEntry;
|
|
9
|
+
/** Retire the successful attempt's transient rows after publishing its Step end. */
|
|
10
|
+
readonly retireAttemptId?: LlmAttemptId;
|
|
9
11
|
} | {
|
|
10
12
|
readonly type: 'settlement';
|
|
11
13
|
readonly attemptId: LlmAttemptId;
|
|
@@ -22,6 +24,7 @@ export type ClientAssistantStreamResult = {
|
|
|
22
24
|
/** Keeps transient Assistant presentation behind one settlement-aware interface. */
|
|
23
25
|
export declare class ClientAssistantStream {
|
|
24
26
|
private activeAttempt;
|
|
27
|
+
private retainedAttempt;
|
|
25
28
|
private readonly pending;
|
|
26
29
|
private publishedSeqs;
|
|
27
30
|
private durableCursor;
|
|
@@ -41,6 +44,8 @@ export declare class ClientAssistantStream {
|
|
|
41
44
|
acceptDurable(entry: SessionLiveEventEntry): ClientAssistantStreamResult;
|
|
42
45
|
/**
|
|
43
46
|
* Fold one dense transient frame and release its named durable settlement.
|
|
47
|
+
* Successful messages retain their transient rows until the owning Step ends;
|
|
48
|
+
* interrupted messages, failed attempts, and abandonment retire them immediately.
|
|
44
49
|
* @param frame - next Assistant stream frame received by the follow connection.
|
|
45
50
|
* @returns a transient, publication, or rebaseline decision, or `undefined` when no entry becomes visible.
|
|
46
51
|
*/
|
|
@@ -3,6 +3,7 @@ import { expandAssistantStream } from '@deepseek-ai/dsh-llm/assistant-stream';
|
|
|
3
3
|
/** Keeps transient Assistant presentation behind one settlement-aware interface. */
|
|
4
4
|
export class ClientAssistantStream {
|
|
5
5
|
activeAttempt;
|
|
6
|
+
retainedAttempt;
|
|
6
7
|
pending = new Map();
|
|
7
8
|
publishedSeqs = new Set();
|
|
8
9
|
durableCursor = -1;
|
|
@@ -17,6 +18,7 @@ export class ClientAssistantStream {
|
|
|
17
18
|
this.pending.clear();
|
|
18
19
|
this.transientInGap = 0;
|
|
19
20
|
this.activeAttempt = undefined;
|
|
21
|
+
this.retainedAttempt = undefined;
|
|
20
22
|
const opening = baseline?.activeAttempt;
|
|
21
23
|
if (opening !== undefined) {
|
|
22
24
|
this.activeAttempt = {
|
|
@@ -73,13 +75,16 @@ export class ClientAssistantStream {
|
|
|
73
75
|
}
|
|
74
76
|
/**
|
|
75
77
|
* Fold one dense transient frame and release its named durable settlement.
|
|
78
|
+
* Successful messages retain their transient rows until the owning Step ends;
|
|
79
|
+
* interrupted messages, failed attempts, and abandonment retire them immediately.
|
|
76
80
|
* @param frame - next Assistant stream frame received by the follow connection.
|
|
77
81
|
* @returns a transient, publication, or rebaseline decision, or `undefined` when no entry becomes visible.
|
|
78
82
|
*/
|
|
79
83
|
acceptFrame(frame) {
|
|
80
84
|
switch (frame.type) {
|
|
81
85
|
case 'start':
|
|
82
|
-
if (this.activeAttempt !== undefined || this.
|
|
86
|
+
if (this.activeAttempt !== undefined || this.retainedAttempt !== undefined
|
|
87
|
+
|| this.pending.size > 0)
|
|
83
88
|
return { type: 'rebaseline' };
|
|
84
89
|
this.pending.clear();
|
|
85
90
|
this.activeAttempt = {
|
|
@@ -140,6 +145,10 @@ export class ClientAssistantStream {
|
|
|
140
145
|
return { type: 'rebaseline' };
|
|
141
146
|
}
|
|
142
147
|
this.pending.delete(frame.outcome.seq);
|
|
148
|
+
if (entry.event.type === 'assistant/message' && entry.event.data.interrupted !== true) {
|
|
149
|
+
this.retainedAttempt = { attemptId: attempt.attemptId, turn: attempt.turn, step: attempt.step };
|
|
150
|
+
return this.publish(entry);
|
|
151
|
+
}
|
|
143
152
|
this.publishedSeqs.add(entry.event.seq);
|
|
144
153
|
return { type: 'settlement', attemptId: attempt.attemptId, entry };
|
|
145
154
|
}
|
|
@@ -157,6 +166,12 @@ export class ClientAssistantStream {
|
|
|
157
166
|
}
|
|
158
167
|
publish(entry) {
|
|
159
168
|
this.publishedSeqs.add(entry.event.seq);
|
|
169
|
+
const retained = this.retainedAttempt;
|
|
170
|
+
if (retained !== undefined && entry.event.type === 'step/end'
|
|
171
|
+
&& entry.event.data.turn === retained.turn && entry.event.data.step === retained.step) {
|
|
172
|
+
this.retainedAttempt = undefined;
|
|
173
|
+
return { type: 'publish', entry, retireAttemptId: retained.attemptId };
|
|
174
|
+
}
|
|
160
175
|
return { type: 'publish', entry };
|
|
161
176
|
}
|
|
162
177
|
}
|
|
@@ -634,8 +634,12 @@ export class Session {
|
|
|
634
634
|
this.notifier.markDirty();
|
|
635
635
|
return;
|
|
636
636
|
}
|
|
637
|
-
if (result?.type === 'publish'
|
|
638
|
-
this.
|
|
637
|
+
if (result?.type === 'publish') {
|
|
638
|
+
const changed = this.appendLive(result.entry);
|
|
639
|
+
if (result.retireAttemptId !== undefined)
|
|
640
|
+
this.eventSource.settleAssistant(result.retireAttemptId);
|
|
641
|
+
if (changed || result.retireAttemptId !== undefined)
|
|
642
|
+
this.notifier.markDirty();
|
|
639
643
|
}
|
|
640
644
|
else if (result?.type === 'transient') {
|
|
641
645
|
this.eventSource.append(result.entry);
|
package/lib/types/commands.d.ts
CHANGED
|
@@ -20,9 +20,9 @@ export declare class SessionCommandController {
|
|
|
20
20
|
*/
|
|
21
21
|
create(request: SessionCreateRequest): Promise<SessionCreateValue>;
|
|
22
22
|
/**
|
|
23
|
-
* Validate and install one Session-local model selection.
|
|
23
|
+
* Validate and install one Session-local model selection; save the default in the background.
|
|
24
24
|
* @param request - Session identity and requested model selection.
|
|
25
|
-
* @returns the normalized selection installed for the Session.
|
|
25
|
+
* @returns the normalized selection installed for the Session, without waiting for default persistence.
|
|
26
26
|
*/
|
|
27
27
|
selectModel(request: SessionSelectModelRequest): Promise<SessionSelectModelValue>;
|
|
28
28
|
/**
|
|
@@ -45,6 +45,7 @@ export declare class SessionCommandController {
|
|
|
45
45
|
* @returns acknowledgement that the Agent accepted the prompt.
|
|
46
46
|
*/
|
|
47
47
|
prompt(request: SessionPromptRequest): Promise<SessionPromptValue>;
|
|
48
|
+
private requireModel;
|
|
48
49
|
/**
|
|
49
50
|
* Read one durable image after proving the Session log references it.
|
|
50
51
|
* @param request - Session and attachment identities used for authorization.
|
package/lib/types/commands.js
CHANGED
|
@@ -51,6 +51,7 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
51
51
|
var e = new Error(message);
|
|
52
52
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
53
53
|
});
|
|
54
|
+
import { modelAvailable } from "./catalog.js";
|
|
54
55
|
import { randomUUID } from 'node:crypto';
|
|
55
56
|
import { brandString } from '@deepseek-ai/dsh-brand';
|
|
56
57
|
import { AttachmentError } from '@deepseek-ai/dsh-attachment';
|
|
@@ -137,14 +138,15 @@ export class SessionCommandController {
|
|
|
137
138
|
return { sessionId, ...(agentPreset === undefined ? {} : { agentPreset }) };
|
|
138
139
|
}
|
|
139
140
|
/**
|
|
140
|
-
* Validate and install one Session-local model selection.
|
|
141
|
+
* Validate and install one Session-local model selection; save the default in the background.
|
|
141
142
|
* @param request - Session identity and requested model selection.
|
|
142
|
-
* @returns the normalized selection installed for the Session.
|
|
143
|
+
* @returns the normalized selection installed for the Session, without waiting for default persistence.
|
|
143
144
|
*/
|
|
144
145
|
async selectModel(request) {
|
|
145
146
|
const agent = await this.resolveAgent(request.sessionId);
|
|
146
147
|
return this.agents.serializeImageAdmission(agent, async () => {
|
|
147
148
|
try {
|
|
149
|
+
await this.requireModel(request);
|
|
148
150
|
const resolved = await this.ctx.llm.resolveCallConfig({
|
|
149
151
|
provider: request.provider,
|
|
150
152
|
model: request.model,
|
|
@@ -160,12 +162,9 @@ export class SessionCommandController {
|
|
|
160
162
|
: { reasoningEffort: resolved.reasoningEffort }),
|
|
161
163
|
};
|
|
162
164
|
this.agents.selectForNextRequest(agent, selected);
|
|
163
|
-
|
|
164
|
-
await this.ctx.agentDefaultModel.saveSelection(selected);
|
|
165
|
-
}
|
|
166
|
-
catch (error) {
|
|
165
|
+
void this.ctx.agentDefaultModel.saveSelection(selected).catch((error) => {
|
|
167
166
|
this.ctx.logger.warn(`session-controller: model selection changed for the Session but the default was not saved: ${String(error)}`);
|
|
168
|
-
}
|
|
167
|
+
});
|
|
169
168
|
return { selected: { ...selected } };
|
|
170
169
|
}
|
|
171
170
|
catch (error) {
|
|
@@ -301,10 +300,6 @@ export class SessionCommandController {
|
|
|
301
300
|
const agent = await this.resolveAgent(request.sessionId);
|
|
302
301
|
if (hasPromptRequest(agent, request.requestId))
|
|
303
302
|
return { accepted: true };
|
|
304
|
-
const selection = this.agents.selectionFor(agent).current;
|
|
305
|
-
if (!routeServed(this.ctx, selection.provider)) {
|
|
306
|
-
throw new RemoteError('session/model-unavailable', `no adapter serves provider "${selection.provider}"; select a model for this session`, { provider: selection.provider, model: selection.model });
|
|
307
|
-
}
|
|
308
303
|
const source = {
|
|
309
304
|
kind: 'user',
|
|
310
305
|
rpcId: request.requestId,
|
|
@@ -355,6 +350,11 @@ export class SessionCommandController {
|
|
|
355
350
|
};
|
|
356
351
|
return hasImage ? this.agents.serializeImageAdmission(agent, admit) : admit();
|
|
357
352
|
}
|
|
353
|
+
async requireModel(selection) {
|
|
354
|
+
if (!await modelAvailable(this.ctx, selection)) {
|
|
355
|
+
throw new RemoteError('session/model-unavailable', 'Select an available model before sending a message.', { provider: selection.provider, model: selection.model });
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
358
|
/**
|
|
359
359
|
* Read one durable image after proving the Session log references it.
|
|
360
360
|
* @param request - Session and attachment identities used for authorization.
|
|
@@ -628,7 +628,4 @@ function referencedImage(events, attachmentId) {
|
|
|
628
628
|
}
|
|
629
629
|
return undefined;
|
|
630
630
|
}
|
|
631
|
-
function routeServed(ctx, provider) {
|
|
632
|
-
return ctx.llm.listProviders().some(entry => entry.id === provider);
|
|
633
|
-
}
|
|
634
631
|
//# sourceMappingURL=commands.js.map
|
package/lib/types/index.d.ts
CHANGED
|
@@ -92,11 +92,16 @@ export declare class SessionController extends TypertRemoteService {
|
|
|
92
92
|
*/
|
|
93
93
|
create(request: SessionCreateRequest): Promise<SessionCreateValue>;
|
|
94
94
|
/**
|
|
95
|
-
* Select one Session-local model after explicitly resuming the Session.
|
|
95
|
+
* Select one Session-local model after explicitly resuming the Session; save the default in the background.
|
|
96
96
|
* @param request - Session identity and requested model selection.
|
|
97
|
-
* @returns the normalized selection installed for the Session.
|
|
97
|
+
* @returns the normalized selection installed for the Session, without waiting for default persistence.
|
|
98
98
|
*/
|
|
99
99
|
selectModel(request: SessionSelectModelRequest): Promise<SessionSelectModelValue>;
|
|
100
|
+
/**
|
|
101
|
+
* Select the first available account model after login when no provider API key is configured.
|
|
102
|
+
* @returns after saving the first available model or retaining the existing default.
|
|
103
|
+
*/
|
|
104
|
+
initializeDefaultModel(): Promise<void>;
|
|
100
105
|
/**
|
|
101
106
|
* Describe every currently routable model for Host-generation selectors.
|
|
102
107
|
* @returns provider-grouped models, the deployment default, and isolated provider failures.
|
package/lib/types/index.js
CHANGED
|
@@ -88,7 +88,7 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
88
88
|
import { hostname } from 'node:os';
|
|
89
89
|
import { resolve } from 'node:path';
|
|
90
90
|
import z from '@deepseek-ai/schemastery';
|
|
91
|
-
import { errorChain } from '@deepseek-ai/dsh-llm';
|
|
91
|
+
import { errorChain, ReasoningEffortId } from '@deepseek-ai/dsh-llm';
|
|
92
92
|
import { canOpenNativePath, nativeFileManager, nativeFileApplications, openNativeFileApplication, openNativeAssociatedPath, revealNativePath } from '@deepseek-ai/dsh-native-command';
|
|
93
93
|
import { SessionQueryError } from '@deepseek-ai/dsh-session-query';
|
|
94
94
|
import { Remote, RemoteError, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
@@ -98,7 +98,7 @@ import { SessionControlController } from "./control.js";
|
|
|
98
98
|
import { SessionHistoryController } from "./history.js";
|
|
99
99
|
import { SessionFileReferences } from "./file-references.js";
|
|
100
100
|
import { ApiSessionList } from "./list.js";
|
|
101
|
-
import { buildModelCatalog } from "./catalog.js";
|
|
101
|
+
import { buildModelCatalog, hasProviderApiKey } from "./catalog.js";
|
|
102
102
|
import { installModelSelectionProjection } from "./model-selection-projection.js";
|
|
103
103
|
import { SessionSkillCatalog } from "./skill-catalog.js";
|
|
104
104
|
import { SessionMediaReferences } from "./media-references.js";
|
|
@@ -114,6 +114,7 @@ let SessionController = (() => {
|
|
|
114
114
|
let _search_decorators;
|
|
115
115
|
let _create_decorators;
|
|
116
116
|
let _selectModel_decorators;
|
|
117
|
+
let _initializeDefaultModel_decorators;
|
|
117
118
|
let _modelCatalog_decorators;
|
|
118
119
|
let _canOpenWorkspacePath_decorators;
|
|
119
120
|
let _openWorkspacePath_decorators;
|
|
@@ -135,6 +136,7 @@ let SessionController = (() => {
|
|
|
135
136
|
_search_decorators = [Remote('search')];
|
|
136
137
|
_create_decorators = [Remote('create')];
|
|
137
138
|
_selectModel_decorators = [Remote('selectModel')];
|
|
139
|
+
_initializeDefaultModel_decorators = [Remote];
|
|
138
140
|
_modelCatalog_decorators = [Remote('modelCatalog')];
|
|
139
141
|
_canOpenWorkspacePath_decorators = [Remote];
|
|
140
142
|
_openWorkspacePath_decorators = [Remote('openWorkspacePath')];
|
|
@@ -153,6 +155,7 @@ let SessionController = (() => {
|
|
|
153
155
|
__esDecorate(this, null, _search_decorators, { kind: "method", name: "search", static: false, private: false, access: { has: obj => "search" in obj, get: obj => obj.search }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
154
156
|
__esDecorate(this, null, _create_decorators, { kind: "method", name: "create", static: false, private: false, access: { has: obj => "create" in obj, get: obj => obj.create }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
155
157
|
__esDecorate(this, null, _selectModel_decorators, { kind: "method", name: "selectModel", static: false, private: false, access: { has: obj => "selectModel" in obj, get: obj => obj.selectModel }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
158
|
+
__esDecorate(this, null, _initializeDefaultModel_decorators, { kind: "method", name: "initializeDefaultModel", static: false, private: false, access: { has: obj => "initializeDefaultModel" in obj, get: obj => obj.initializeDefaultModel }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
156
159
|
__esDecorate(this, null, _modelCatalog_decorators, { kind: "method", name: "modelCatalog", static: false, private: false, access: { has: obj => "modelCatalog" in obj, get: obj => obj.modelCatalog }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
157
160
|
__esDecorate(this, null, _canOpenWorkspacePath_decorators, { kind: "method", name: "canOpenWorkspacePath", static: false, private: false, access: { has: obj => "canOpenWorkspacePath" in obj, get: obj => obj.canOpenWorkspacePath }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
158
161
|
__esDecorate(this, null, _openWorkspacePath_decorators, { kind: "method", name: "openWorkspacePath", static: false, private: false, access: { has: obj => "openWorkspacePath" in obj, get: obj => obj.openWorkspacePath }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
@@ -339,13 +342,30 @@ let SessionController = (() => {
|
|
|
339
342
|
return this.commands.create(request);
|
|
340
343
|
}
|
|
341
344
|
/**
|
|
342
|
-
* Select one Session-local model after explicitly resuming the Session.
|
|
345
|
+
* Select one Session-local model after explicitly resuming the Session; save the default in the background.
|
|
343
346
|
* @param request - Session identity and requested model selection.
|
|
344
|
-
* @returns the normalized selection installed for the Session.
|
|
347
|
+
* @returns the normalized selection installed for the Session, without waiting for default persistence.
|
|
345
348
|
*/
|
|
346
349
|
selectModel(request) {
|
|
347
350
|
return this.commands.selectModel(request);
|
|
348
351
|
}
|
|
352
|
+
/**
|
|
353
|
+
* Select the first available account model after login when no provider API key is configured.
|
|
354
|
+
* @returns after saving the first available model or retaining the existing default.
|
|
355
|
+
*/
|
|
356
|
+
async initializeDefaultModel() {
|
|
357
|
+
const provider = 'deepseek-account';
|
|
358
|
+
if (await hasProviderApiKey(this.ctx))
|
|
359
|
+
return;
|
|
360
|
+
const catalog = await buildModelCatalog(this.ctx);
|
|
361
|
+
const model = catalog.groups.find(group => group.id === provider)?.models[0];
|
|
362
|
+
if (model === undefined)
|
|
363
|
+
throw new RemoteError('session/provider-models-unavailable', `provider "${provider}" has no available models`, { provider });
|
|
364
|
+
const selection = { provider, model: model.id,
|
|
365
|
+
...model.reasoning?.defaultEffort === undefined ? {} : { reasoningEffort: ReasoningEffortId(model.reasoning.defaultEffort) },
|
|
366
|
+
};
|
|
367
|
+
await this.ctx.agentDefaultModel.saveSelection(selection);
|
|
368
|
+
}
|
|
349
369
|
/**
|
|
350
370
|
* Describe every currently routable model for Host-generation selectors.
|
|
351
371
|
* @returns provider-grouped models, the deployment default, and isolated provider failures.
|
package/lib/types/types.d.ts
CHANGED
|
@@ -140,7 +140,7 @@ export interface ModelCatalogFailure {
|
|
|
140
140
|
/** Host-generation model catalog and the default used by unconfigured Sessions. */
|
|
141
141
|
export interface ModelCatalog {
|
|
142
142
|
readonly default: ModelSelection;
|
|
143
|
-
/** Provider routes
|
|
143
|
+
/** Provider routes with at least one currently available catalog model. */
|
|
144
144
|
readonly routableProviders: readonly string[];
|
|
145
145
|
readonly groups: readonly ModelProviderGroup[];
|
|
146
146
|
readonly failures: readonly ModelCatalogFailure[];
|
|
@@ -179,6 +179,10 @@ export declare const SESSION_SEARCH_RESULT_LIMIT = 20;
|
|
|
179
179
|
export declare const SESSION_SEARCH_SNIPPET_MAX_CODE_POINTS = 240;
|
|
180
180
|
declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
181
181
|
interface RemoteErrorDetailsMap {
|
|
182
|
+
'session/provider-credentials-unavailable': Record<string, never>;
|
|
183
|
+
'session/provider-models-unavailable': {
|
|
184
|
+
readonly provider: string;
|
|
185
|
+
};
|
|
182
186
|
'session/model-unavailable': {
|
|
183
187
|
readonly provider: string;
|
|
184
188
|
readonly model: string;
|