dsh-more 0.0.2 → 0.0.3
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 +11 -0
- package/README.zh-CN.md +11 -0
- package/dist/client.js +1103 -141
- package/dist/index.js +232 -12
- package/dist/types/generated/host-settings-schema.d.ts +4 -0
- package/dist/types/generated/patch-catalog.d.ts +16 -0
- package/dist/types/patches/conversation-quick-navigation/client/index.d.ts +22 -0
- package/dist/types/patches/conversation-quick-navigation/client/navigation.d.ts +26 -0
- package/dist/types/patches/conversation-quick-navigation/host/index.d.ts +2 -0
- package/dist/types/patches/conversation-quick-navigation/shared.d.ts +1 -0
- package/dist/types/patches/model-reasoning-efforts/client/index.d.ts +39 -0
- package/dist/types/patches/model-reasoning-efforts/host/index.d.ts +2 -0
- package/dist/types/patches/model-reasoning-efforts/host/validate.d.ts +13 -0
- package/dist/types/patches/model-reasoning-efforts/shared.d.ts +51 -0
- package/dist/types/platform/dsh/client/api.d.ts +2 -0
- package/dist/types/platform/dsh/client/message-targets.d.ts +13 -1
- package/dist/types/platform/dsh/host/wire.d.ts +6 -0
- package/dsh.plugin.json +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -78,6 +78,14 @@ function verifyConfirmationToken(secret, token, expected, now = Date.now()) {
|
|
|
78
78
|
|
|
79
79
|
// src/platform/dsh/host/wire.ts
|
|
80
80
|
var MAX_BODY_BYTES = 64 * 1024;
|
|
81
|
+
var RawPatchResponse = class {
|
|
82
|
+
constructor(body, contentType) {
|
|
83
|
+
this.body = body;
|
|
84
|
+
this.contentType = contentType;
|
|
85
|
+
}
|
|
86
|
+
body;
|
|
87
|
+
contentType;
|
|
88
|
+
};
|
|
81
89
|
function requireJsonContentType(req) {
|
|
82
90
|
const value = req.headers["content-type"];
|
|
83
91
|
const contentType = (Array.isArray(value) ? value[0] : value)?.split(";", 1)[0]?.trim().toLowerCase();
|
|
@@ -121,6 +129,15 @@ function write(res, status, body) {
|
|
|
121
129
|
res.end(JSON.stringify(body));
|
|
122
130
|
}
|
|
123
131
|
function writeOk(res, value) {
|
|
132
|
+
if (value instanceof RawPatchResponse) {
|
|
133
|
+
res.writeHead(200, {
|
|
134
|
+
"content-type": value.contentType,
|
|
135
|
+
"cache-control": "no-store",
|
|
136
|
+
"x-content-type-options": "nosniff"
|
|
137
|
+
});
|
|
138
|
+
res.end(value.body);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
124
141
|
write(res, 200, { ok: true, value });
|
|
125
142
|
}
|
|
126
143
|
function writeError(res, error) {
|
|
@@ -802,7 +819,16 @@ function isoTime(value) {
|
|
|
802
819
|
return Number.isFinite(date.getTime()) ? date.toISOString() : "\u672A\u77E5\u65F6\u95F4";
|
|
803
820
|
}
|
|
804
821
|
function codeFence(value, language = "") {
|
|
805
|
-
|
|
822
|
+
let longest = 0;
|
|
823
|
+
let current = 0;
|
|
824
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
825
|
+
if (value.charCodeAt(index) === 96) {
|
|
826
|
+
current += 1;
|
|
827
|
+
if (current > longest) longest = current;
|
|
828
|
+
} else {
|
|
829
|
+
current = 0;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
806
832
|
const fence = "`".repeat(Math.max(3, longest + 1));
|
|
807
833
|
return `${fence}${language}
|
|
808
834
|
${value}
|
|
@@ -855,7 +881,12 @@ ${jsonBlock(block)}`;
|
|
|
855
881
|
}
|
|
856
882
|
function contentMarkdown(content) {
|
|
857
883
|
if (content.length === 0) return "\uFF08\u7A7A\u6D88\u606F\uFF09";
|
|
858
|
-
|
|
884
|
+
const parts = [];
|
|
885
|
+
for (const block of content) {
|
|
886
|
+
const part = contentBlockMarkdown(block);
|
|
887
|
+
if (part !== "") parts.push(part);
|
|
888
|
+
}
|
|
889
|
+
return parts.join("\n\n") || "\uFF08\u7A7A\u6D88\u606F\uFF09";
|
|
859
890
|
}
|
|
860
891
|
function messageSection(label, time, body) {
|
|
861
892
|
return `## ${singleLine(label)}
|
|
@@ -870,9 +901,6 @@ function sourceLabel(event) {
|
|
|
870
901
|
if (source.kind === "plugin") return `\u4E0A\u4E0B\u6587 \xB7 ${singleLine(source.plugin) || "\u63D2\u4EF6"}`;
|
|
871
902
|
return "\u4E0A\u4E0B\u6587";
|
|
872
903
|
}
|
|
873
|
-
function toolCallIds(content) {
|
|
874
|
-
return content.filter((block) => block.type === "tool-call").map((block) => String(block.id));
|
|
875
|
-
}
|
|
876
904
|
function conversationMarkdown(events, options) {
|
|
877
905
|
const sections = [];
|
|
878
906
|
const renderedCalls = /* @__PURE__ */ new Set();
|
|
@@ -883,7 +911,9 @@ function conversationMarkdown(events, options) {
|
|
|
883
911
|
continue;
|
|
884
912
|
}
|
|
885
913
|
if (event.type === "assistant/message") {
|
|
886
|
-
for (const
|
|
914
|
+
for (const block of event.data.message.content) {
|
|
915
|
+
if (block.type === "tool-call") renderedCalls.add(String(block.id));
|
|
916
|
+
}
|
|
887
917
|
sections.push(messageSection("\u52A9\u624B", event.time, contentMarkdown(event.data.message.content)));
|
|
888
918
|
continue;
|
|
889
919
|
}
|
|
@@ -943,7 +973,8 @@ function render(ctx, payload) {
|
|
|
943
973
|
if ([...title].length > MAX_TITLE_LENGTH) throw new DshMoreError("bad-request", "\u4F1A\u8BDD\u6807\u9898\u8FC7\u957F\u3002");
|
|
944
974
|
const session = requireLiveSession(ctx, sessionId);
|
|
945
975
|
requireIdleAgent(ctx, sessionId, session);
|
|
946
|
-
|
|
976
|
+
const transcript = conversationMarkdown(session.events, { title, sessionId });
|
|
977
|
+
return new RawPatchResponse(transcript.markdown, "text/markdown; charset=utf-8");
|
|
947
978
|
}
|
|
948
979
|
var hostPatch4 = {
|
|
949
980
|
id: CONVERSATION_MARKDOWN_EXPORT_PATCH_ID,
|
|
@@ -952,15 +983,202 @@ var hostPatch4 = {
|
|
|
952
983
|
})
|
|
953
984
|
};
|
|
954
985
|
|
|
986
|
+
// src/patches/model-reasoning-efforts/host/index.ts
|
|
987
|
+
import { settingsNamespace } from "@deepseek-ai/dsh-settings";
|
|
988
|
+
|
|
989
|
+
// src/patches/model-reasoning-efforts/shared.ts
|
|
990
|
+
var MODEL_REASONING_EFFORTS_PATCH_ID = "model-reasoning-efforts";
|
|
991
|
+
var LLM_PI_AI_SETTINGS_NAMESPACE = "llm-pi-ai";
|
|
992
|
+
var THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
993
|
+
var DEFAULT_REASONING_EFFORTS = {
|
|
994
|
+
low: "low",
|
|
995
|
+
medium: "medium",
|
|
996
|
+
high: "high"
|
|
997
|
+
};
|
|
998
|
+
|
|
999
|
+
// src/patches/model-reasoning-efforts/host/validate.ts
|
|
1000
|
+
var LEVEL_SET = new Set(THINKING_LEVELS);
|
|
1001
|
+
function validateReasoningEfforts(raw) {
|
|
1002
|
+
if (raw === null || raw === void 0) return null;
|
|
1003
|
+
if (raw === false) return false;
|
|
1004
|
+
if (typeof raw !== "object" || Array.isArray(raw)) {
|
|
1005
|
+
throw new DshMoreError("bad-request", "reasoningEfforts \u5FC5\u987B\u662F false\u3001\u601D\u8003\u7EA7\u522B\u5B57\u5178\u6216 null\u3002");
|
|
1006
|
+
}
|
|
1007
|
+
const dict = raw;
|
|
1008
|
+
const keys = Object.keys(dict);
|
|
1009
|
+
if (keys.length === 0) throw new DshMoreError("bad-request", "\u81F3\u5C11\u9700\u8981\u58F0\u660E\u4E00\u4E2A\u601D\u8003\u7EA7\u522B\u3002");
|
|
1010
|
+
const result = {};
|
|
1011
|
+
let offersThinking = false;
|
|
1012
|
+
for (const key of keys) {
|
|
1013
|
+
if (!LEVEL_SET.has(key)) throw new DshMoreError("bad-request", `\u672A\u77E5\u7684\u601D\u8003\u7EA7\u522B\uFF1A${key}`);
|
|
1014
|
+
const value = dict[key];
|
|
1015
|
+
if (value === null) {
|
|
1016
|
+
if (key !== "off") throw new DshMoreError("bad-request", `\u601D\u8003\u7EA7\u522B ${key} \u5FC5\u987B\u586B\u5199\u7EBF\u4E0A\u503C\uFF0C\u53EA\u6709 off \u53EF\u4EE5\u4E3A\u7A7A\u3002`);
|
|
1017
|
+
result[key] = null;
|
|
1018
|
+
continue;
|
|
1019
|
+
}
|
|
1020
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
1021
|
+
throw new DshMoreError("bad-request", `\u601D\u8003\u7EA7\u522B ${key} \u7684\u7EBF\u4E0A\u503C\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\u3002`);
|
|
1022
|
+
}
|
|
1023
|
+
result[key] = value;
|
|
1024
|
+
if (key !== "off") offersThinking = true;
|
|
1025
|
+
}
|
|
1026
|
+
if (!offersThinking) throw new DshMoreError("bad-request", "\u9700\u8981\u81F3\u5C11\u58F0\u660E\u4E00\u4E2A\u975E off \u7684\u601D\u8003\u7EA7\u522B\u3002");
|
|
1027
|
+
return result;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
// src/patches/model-reasoning-efforts/host/index.ts
|
|
1031
|
+
var LLM_PI_AI_NS = settingsNamespace(LLM_PI_AI_SETTINGS_NAMESPACE);
|
|
1032
|
+
function piAiSection(ctx) {
|
|
1033
|
+
const value = ctx.settings.get(LLM_PI_AI_NS);
|
|
1034
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
1035
|
+
const providers = value.providers;
|
|
1036
|
+
if (typeof providers !== "object" || providers === null || Array.isArray(providers)) return void 0;
|
|
1037
|
+
return { providers };
|
|
1038
|
+
}
|
|
1039
|
+
function normalizeEfforts(value) {
|
|
1040
|
+
if (value === false) return false;
|
|
1041
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
|
|
1042
|
+
return value;
|
|
1043
|
+
}
|
|
1044
|
+
function read(ctx) {
|
|
1045
|
+
const section = piAiSection(ctx);
|
|
1046
|
+
const rows = [];
|
|
1047
|
+
if (section !== void 0) {
|
|
1048
|
+
for (const [provider, profile] of Object.entries(section.providers)) {
|
|
1049
|
+
if (typeof profile !== "object" || profile === null || Array.isArray(profile)) continue;
|
|
1050
|
+
const models = profile.models;
|
|
1051
|
+
if (!Array.isArray(models)) continue;
|
|
1052
|
+
const displayName = profile.displayName;
|
|
1053
|
+
const providerName = typeof displayName === "string" && displayName.trim() !== "" ? displayName : provider;
|
|
1054
|
+
for (const model of models) {
|
|
1055
|
+
if (typeof model !== "object" || model === null || Array.isArray(model)) continue;
|
|
1056
|
+
const modelId = model.id;
|
|
1057
|
+
if (typeof modelId !== "string" || modelId === "") continue;
|
|
1058
|
+
rows.push({
|
|
1059
|
+
provider,
|
|
1060
|
+
providerName,
|
|
1061
|
+
modelId,
|
|
1062
|
+
reasoningEfforts: normalizeEfforts(model.reasoningEfforts)
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
return {
|
|
1068
|
+
rows,
|
|
1069
|
+
writable: ctx.settings.writable,
|
|
1070
|
+
documentPath: ctx.settings.documentPath
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
1073
|
+
async function save(ctx, payload) {
|
|
1074
|
+
const provider = requireString(payload, "provider");
|
|
1075
|
+
const modelId = requireString(payload, "modelId");
|
|
1076
|
+
const reasoningEfforts = validateReasoningEfforts(payload.reasoningEfforts);
|
|
1077
|
+
const section = piAiSection(ctx);
|
|
1078
|
+
if (section === void 0) throw new DshMoreError("bad-request", "llm-pi-ai \u914D\u7F6E\u5C1A\u672A\u6CE8\u518C\uFF0C\u65E0\u6CD5\u4FDD\u5B58\u601D\u8003\u5F3A\u5EA6\u3002");
|
|
1079
|
+
const profile = section.providers[provider];
|
|
1080
|
+
if (typeof profile !== "object" || profile === null || Array.isArray(profile)) {
|
|
1081
|
+
throw new DshMoreError("bad-request", `\u672A\u627E\u5230\u63D0\u4F9B\u65B9 ${provider} \u7684\u914D\u7F6E\u3002`);
|
|
1082
|
+
}
|
|
1083
|
+
const models = profile.models;
|
|
1084
|
+
if (!Array.isArray(models)) throw new DshMoreError("bad-request", `\u63D0\u4F9B\u65B9 ${provider} \u672A\u914D\u7F6E\u4EFB\u4F55\u6A21\u578B\u3002`);
|
|
1085
|
+
const index = models.findIndex((model) => {
|
|
1086
|
+
if (typeof model !== "object" || model === null) return false;
|
|
1087
|
+
return model.id === modelId;
|
|
1088
|
+
});
|
|
1089
|
+
if (index === -1) throw new DshMoreError("bad-request", `\u63D0\u4F9B\u65B9 ${provider} \u4E0B\u672A\u627E\u5230\u6A21\u578B ${modelId}\u3002`);
|
|
1090
|
+
const descriptor = ctx.settings.describe().find((entry) => entry.ns === LLM_PI_AI_NS);
|
|
1091
|
+
if (descriptor === void 0) throw new DshMoreError("bad-request", "llm-pi-ai \u914D\u7F6E\u5C1A\u672A\u6CE8\u518C\uFF0C\u65E0\u6CD5\u4FDD\u5B58\u601D\u8003\u5F3A\u5EA6\u3002");
|
|
1092
|
+
const user = descriptor.user;
|
|
1093
|
+
const userProviders = typeof user === "object" && user !== null && !Array.isArray(user) ? user.providers : void 0;
|
|
1094
|
+
const providers = typeof userProviders === "object" && userProviders !== null && !Array.isArray(userProviders) ? { ...userProviders } : {};
|
|
1095
|
+
const userProfile = providers[provider];
|
|
1096
|
+
const userModels = typeof userProfile === "object" && userProfile !== null && !Array.isArray(userProfile) ? userProfile.models : void 0;
|
|
1097
|
+
const storedModels = Array.isArray(userModels) ? [...userModels] : [];
|
|
1098
|
+
const storedIndex = storedModels.findIndex((model) => {
|
|
1099
|
+
if (typeof model !== "object" || model === null) return false;
|
|
1100
|
+
return model.id === modelId;
|
|
1101
|
+
});
|
|
1102
|
+
if (storedIndex === -1 && reasoningEfforts === null) {
|
|
1103
|
+
return { provider, modelId, reasoningEfforts };
|
|
1104
|
+
}
|
|
1105
|
+
const stored = storedIndex === -1 ? { id: modelId } : storedModels[storedIndex];
|
|
1106
|
+
let nextModel;
|
|
1107
|
+
if (reasoningEfforts === null) {
|
|
1108
|
+
const { reasoningEfforts: _dropped, ...rest } = stored;
|
|
1109
|
+
nextModel = rest;
|
|
1110
|
+
} else {
|
|
1111
|
+
nextModel = { ...stored, reasoningEfforts };
|
|
1112
|
+
}
|
|
1113
|
+
const nextModels = storedIndex === -1 ? [...storedModels, nextModel] : storedModels.map((model, modelIndex) => modelIndex === storedIndex ? nextModel : model);
|
|
1114
|
+
const nextProfile = {
|
|
1115
|
+
...typeof userProfile === "object" && userProfile !== null && !Array.isArray(userProfile) ? userProfile : {},
|
|
1116
|
+
models: nextModels
|
|
1117
|
+
};
|
|
1118
|
+
const ops = [{ op: "set", path: ["providers"], value: { ...providers, [provider]: nextProfile } }];
|
|
1119
|
+
await ctx.settings.mutate(LLM_PI_AI_NS, ops, descriptor.revision);
|
|
1120
|
+
return { provider, modelId, reasoningEfforts };
|
|
1121
|
+
}
|
|
1122
|
+
async function fillDefaults(ctx) {
|
|
1123
|
+
const descriptor = ctx.settings.describe().find((entry) => entry.ns === LLM_PI_AI_NS);
|
|
1124
|
+
if (descriptor === void 0) return { filled: 0 };
|
|
1125
|
+
const user = descriptor.user;
|
|
1126
|
+
const userProviders = typeof user === "object" && user !== null && !Array.isArray(user) ? user.providers : void 0;
|
|
1127
|
+
const providers = typeof userProviders === "object" && userProviders !== null && !Array.isArray(userProviders) ? { ...userProviders } : {};
|
|
1128
|
+
let filled = 0;
|
|
1129
|
+
const nextProviders = { ...providers };
|
|
1130
|
+
for (const [route, profile] of Object.entries(providers)) {
|
|
1131
|
+
if (typeof profile !== "object" || profile === null || Array.isArray(profile)) continue;
|
|
1132
|
+
const models = profile.models;
|
|
1133
|
+
if (!Array.isArray(models)) continue;
|
|
1134
|
+
let changed = false;
|
|
1135
|
+
const nextModels = models.map((model) => {
|
|
1136
|
+
if (typeof model !== "object" || model === null) return model;
|
|
1137
|
+
const entry = model;
|
|
1138
|
+
if ("reasoningEfforts" in entry) return model;
|
|
1139
|
+
changed = true;
|
|
1140
|
+
filled += 1;
|
|
1141
|
+
return { ...entry, reasoningEfforts: { ...DEFAULT_REASONING_EFFORTS } };
|
|
1142
|
+
});
|
|
1143
|
+
if (!changed) continue;
|
|
1144
|
+
nextProviders[route] = { ...profile, models: nextModels };
|
|
1145
|
+
}
|
|
1146
|
+
if (filled === 0) return { filled: 0 };
|
|
1147
|
+
const ops = [{ op: "set", path: ["providers"], value: nextProviders }];
|
|
1148
|
+
await ctx.settings.mutate(LLM_PI_AI_NS, ops, descriptor.revision);
|
|
1149
|
+
return { filled };
|
|
1150
|
+
}
|
|
1151
|
+
var hostPatch5 = {
|
|
1152
|
+
id: MODEL_REASONING_EFFORTS_PATCH_ID,
|
|
1153
|
+
routes: ({ ctx }) => ({
|
|
1154
|
+
read: () => read(ctx),
|
|
1155
|
+
save: (payload) => save(ctx, payload),
|
|
1156
|
+
fillDefaults: () => fillDefaults(ctx)
|
|
1157
|
+
})
|
|
1158
|
+
};
|
|
1159
|
+
|
|
1160
|
+
// src/patches/conversation-quick-navigation/shared.ts
|
|
1161
|
+
var CONVERSATION_QUICK_NAVIGATION_PATCH_ID = "conversation-quick-navigation";
|
|
1162
|
+
|
|
1163
|
+
// src/patches/conversation-quick-navigation/host/index.ts
|
|
1164
|
+
var hostPatch6 = {
|
|
1165
|
+
id: CONVERSATION_QUICK_NAVIGATION_PATCH_ID,
|
|
1166
|
+
routes: () => ({
|
|
1167
|
+
status: () => ({ available: true })
|
|
1168
|
+
})
|
|
1169
|
+
};
|
|
1170
|
+
|
|
955
1171
|
// src/generated/host-registry.ts
|
|
956
|
-
var HOST_PATCHES = [hostPatch, hostPatch2, hostPatch3, hostPatch4];
|
|
1172
|
+
var HOST_PATCHES = [hostPatch, hostPatch2, hostPatch3, hostPatch4, hostPatch5, hostPatch6];
|
|
957
1173
|
|
|
958
1174
|
// src/generated/patch-catalog.ts
|
|
959
1175
|
var DEFAULT_PATCH_SETTINGS = {
|
|
960
1176
|
"message-edit": true,
|
|
961
1177
|
"message-delete": true,
|
|
962
1178
|
"session-delete": true,
|
|
963
|
-
"conversation-markdown-export": true
|
|
1179
|
+
"conversation-markdown-export": true,
|
|
1180
|
+
"model-reasoning-efforts": true,
|
|
1181
|
+
"conversation-quick-navigation": true
|
|
964
1182
|
};
|
|
965
1183
|
|
|
966
1184
|
// src/kernel/host/activation.ts
|
|
@@ -997,7 +1215,7 @@ var HostPatchActivation = class {
|
|
|
997
1215
|
};
|
|
998
1216
|
|
|
999
1217
|
// src/kernel/host/settings.ts
|
|
1000
|
-
import { installSettingsSection, settingsNamespace } from "@deepseek-ai/dsh-settings";
|
|
1218
|
+
import { installSettingsSection, settingsNamespace as settingsNamespace2 } from "@deepseek-ai/dsh-settings";
|
|
1001
1219
|
|
|
1002
1220
|
// src/generated/host-settings-schema.ts
|
|
1003
1221
|
import z2 from "@deepseek-ai/schemastery";
|
|
@@ -1005,11 +1223,13 @@ var PatchSettingsSchema = z2.object({
|
|
|
1005
1223
|
"message-edit": z2.boolean().default(true),
|
|
1006
1224
|
"message-delete": z2.boolean().default(true),
|
|
1007
1225
|
"session-delete": z2.boolean().default(true),
|
|
1008
|
-
"conversation-markdown-export": z2.boolean().default(true)
|
|
1226
|
+
"conversation-markdown-export": z2.boolean().default(true),
|
|
1227
|
+
"model-reasoning-efforts": z2.boolean().default(true),
|
|
1228
|
+
"conversation-quick-navigation": z2.boolean().default(true)
|
|
1009
1229
|
});
|
|
1010
1230
|
|
|
1011
1231
|
// src/kernel/host/settings.ts
|
|
1012
|
-
var PATCH_SETTINGS_NAMESPACE2 =
|
|
1232
|
+
var PATCH_SETTINGS_NAMESPACE2 = settingsNamespace2(PATCH_SETTINGS_NAMESPACE);
|
|
1013
1233
|
function installPatchSettings(ctx, activation) {
|
|
1014
1234
|
let source = () => DEFAULT_PATCH_SETTINGS;
|
|
1015
1235
|
activation.apply(source());
|
|
@@ -4,9 +4,13 @@ export declare const PatchSettingsSchema: z<Schemastery.ObjectS<{
|
|
|
4
4
|
"message-delete": z<boolean, boolean>;
|
|
5
5
|
"session-delete": z<boolean, boolean>;
|
|
6
6
|
"conversation-markdown-export": z<boolean, boolean>;
|
|
7
|
+
"model-reasoning-efforts": z<boolean, boolean>;
|
|
8
|
+
"conversation-quick-navigation": z<boolean, boolean>;
|
|
7
9
|
}>, Schemastery.ObjectT<{
|
|
8
10
|
"message-edit": z<boolean, boolean>;
|
|
9
11
|
"message-delete": z<boolean, boolean>;
|
|
10
12
|
"session-delete": z<boolean, boolean>;
|
|
11
13
|
"conversation-markdown-export": z<boolean, boolean>;
|
|
14
|
+
"model-reasoning-efforts": z<boolean, boolean>;
|
|
15
|
+
"conversation-quick-navigation": z<boolean, boolean>;
|
|
12
16
|
}>>;
|
|
@@ -26,6 +26,20 @@ export declare const PATCH_CATALOG: readonly [{
|
|
|
26
26
|
readonly defaultEnabled: true;
|
|
27
27
|
readonly order: 400;
|
|
28
28
|
readonly clientKind: "standalone";
|
|
29
|
+
}, {
|
|
30
|
+
readonly id: "model-reasoning-efforts";
|
|
31
|
+
readonly name: "模型思考强度";
|
|
32
|
+
readonly description: "在模型配置界面为每个模型配置支持的思考强度并写入 settings.yaml 的 reasoningEfforts";
|
|
33
|
+
readonly defaultEnabled: true;
|
|
34
|
+
readonly order: 500;
|
|
35
|
+
readonly clientKind: "standalone";
|
|
36
|
+
}, {
|
|
37
|
+
readonly id: "conversation-quick-navigation";
|
|
38
|
+
readonly name: "对话快速导航";
|
|
39
|
+
readonly description: "自动加载完整记录,并用常驻目录快速定位当前会话中的每一轮提问";
|
|
40
|
+
readonly defaultEnabled: true;
|
|
41
|
+
readonly order: 600;
|
|
42
|
+
readonly clientKind: "standalone";
|
|
29
43
|
}];
|
|
30
44
|
export type PatchId = typeof PATCH_CATALOG[number]['id'];
|
|
31
45
|
export interface PatchSettings {
|
|
@@ -33,6 +47,8 @@ export interface PatchSettings {
|
|
|
33
47
|
"message-delete": boolean;
|
|
34
48
|
"session-delete": boolean;
|
|
35
49
|
"conversation-markdown-export": boolean;
|
|
50
|
+
"model-reasoning-efforts": boolean;
|
|
51
|
+
"conversation-quick-navigation": boolean;
|
|
36
52
|
}
|
|
37
53
|
export declare const DEFAULT_PATCH_SETTINGS: PatchSettings;
|
|
38
54
|
export declare function decodePatchSettings(value: unknown): PatchSettings | undefined;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
+
import type { PatchActivationSource } from '../../../kernel/client/activation.js';
|
|
3
|
+
import type { ClientPatch } from '../../../kernel/client/patch.js';
|
|
4
|
+
import { type ConversationTurnSummary } from './navigation.js';
|
|
5
|
+
type HeaderUtilityProps = PropsRuntime<'conversation.session.header.utilities'>;
|
|
6
|
+
export declare function ConversationNavigationMenu({ turns, activeKey, hasMore, loadingOlder, autoLoadPaused, collapsed, onRetry, onToggleCollapsed, onJump, listRef, }: {
|
|
7
|
+
turns: readonly ConversationTurnSummary[];
|
|
8
|
+
activeKey: string | null;
|
|
9
|
+
hasMore: boolean;
|
|
10
|
+
loadingOlder: boolean;
|
|
11
|
+
autoLoadPaused: boolean;
|
|
12
|
+
collapsed: boolean;
|
|
13
|
+
onRetry: () => void;
|
|
14
|
+
onToggleCollapsed: () => void;
|
|
15
|
+
onJump: (key: string) => void;
|
|
16
|
+
listRef: React.RefObject<HTMLDivElement>;
|
|
17
|
+
}): JSX.Element;
|
|
18
|
+
export declare function ConversationQuickNavigation(props: HeaderUtilityProps & {
|
|
19
|
+
activation: PatchActivationSource;
|
|
20
|
+
}): JSX.Element | null;
|
|
21
|
+
export declare const clientPatch: ClientPatch;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ConversationSnapshot } from '@deepseek-ai/dsh-client-runtime/client';
|
|
2
|
+
export interface ConversationTurnSummary {
|
|
3
|
+
key: string;
|
|
4
|
+
seq: number;
|
|
5
|
+
label: string;
|
|
6
|
+
}
|
|
7
|
+
export interface TurnPosition {
|
|
8
|
+
key: string;
|
|
9
|
+
top: number;
|
|
10
|
+
}
|
|
11
|
+
export interface AutoLoadOlderState {
|
|
12
|
+
enabled: boolean;
|
|
13
|
+
surfaceAvailable: boolean;
|
|
14
|
+
hasMore: boolean;
|
|
15
|
+
loadingOlder: boolean;
|
|
16
|
+
paused: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** Select stable user-authored turn summaries without observing assistant streaming frames. */
|
|
19
|
+
export declare function createConversationTurnSelector(): (snapshot: ConversationSnapshot) => readonly ConversationTurnSummary[];
|
|
20
|
+
/** Stable evidence that an older history page prepended visible conversation material. */
|
|
21
|
+
export declare function historyWindowSignature(snapshot: ConversationSnapshot): string;
|
|
22
|
+
export declare function shouldAutoLoadOlder(state: AutoLoadOlderState): boolean;
|
|
23
|
+
/** Pick the last turn at or above the reading line, falling back to the first turn. */
|
|
24
|
+
export declare function activeTurnAt(positions: readonly TurnPosition[], readingLine: number): string | null;
|
|
25
|
+
/** Translate a row's viewport coordinate into a bounded scrollport offset. */
|
|
26
|
+
export declare function scrollOffsetForRow(currentScrollTop: number, scrollportTop: number, rowTop: number, topInset?: number): number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const CONVERSATION_QUICK_NAVIGATION_PATCH_ID = "conversation-quick-navigation";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { SettingsScope } from '@deepseek-ai/dsh-client-runtime/client';
|
|
2
|
+
import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
3
|
+
import type { PatchActivationSource } from '../../../kernel/client/activation.js';
|
|
4
|
+
import type { ClientPatch } from '../../../kernel/client/patch.js';
|
|
5
|
+
import { type ThinkingLevel } from '../shared.js';
|
|
6
|
+
type OverlayProps = PropsRuntime<'shell.overlay'>;
|
|
7
|
+
/** One level's editing state inside a model's draft. */
|
|
8
|
+
interface LevelDraft {
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
wire: string;
|
|
11
|
+
}
|
|
12
|
+
/** One model's in-progress reasoning-effort draft. */
|
|
13
|
+
export interface ModelDraft {
|
|
14
|
+
nonReasoning: boolean;
|
|
15
|
+
levels: Partial<Record<ThinkingLevel, LevelDraft>>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The level toggles + wire-value inputs shared by the editor modal. Draft
|
|
19
|
+
* state lives in the caller so the modal survives models-page re-renders.
|
|
20
|
+
*/
|
|
21
|
+
export declare function EffortEditorBody({ draft, setDraft, writable, busy }: {
|
|
22
|
+
draft: ModelDraft;
|
|
23
|
+
setDraft: (updater: (current: ModelDraft) => ModelDraft) => void;
|
|
24
|
+
writable: boolean;
|
|
25
|
+
busy: boolean;
|
|
26
|
+
}): JSX.Element;
|
|
27
|
+
/**
|
|
28
|
+
* Persistent frame entry that drops a reasoning-effort button into every model
|
|
29
|
+
* row of the shipped Models page model catalog and owns the editor modal. The
|
|
30
|
+
* buttons are plain DOM (stateless) re-synced by a MutationObserver, so the
|
|
31
|
+
* models page can re-render freely; the modal's state lives in this component,
|
|
32
|
+
* which the slot system never unmounts.
|
|
33
|
+
*/
|
|
34
|
+
export declare function ModelsPageEffortPortal(props: OverlayProps & {
|
|
35
|
+
scope: SettingsScope<unknown>;
|
|
36
|
+
activation: PatchActivationSource;
|
|
37
|
+
}): JSX.Element | null;
|
|
38
|
+
export declare const clientPatch: ClientPatch;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ModelReasoningEfforts } from '../shared.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validate a client-supplied `reasoningEfforts` payload, mirroring the
|
|
4
|
+
* pi-ai profile rules the adapter enforces when it resolves a route:
|
|
5
|
+
* - `null`/`undefined` means "clear" (fall back to the installed catalog).
|
|
6
|
+
* - `false` means "this model does not reason".
|
|
7
|
+
* - otherwise a dict whose keys are known levels, whose non-`off` values are
|
|
8
|
+
* non-empty wire spellings, and which offers at least one level beyond `off`.
|
|
9
|
+
*
|
|
10
|
+
* Rejecting invalid payloads here refuses the `settings.mutate` that would
|
|
11
|
+
* otherwise store a profile the adapter would refuse on its next resolution.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateReasoningEfforts(raw: unknown): ModelReasoningEfforts | null;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export declare const MODEL_REASONING_EFFORTS_PATCH_ID = "model-reasoning-efforts";
|
|
2
|
+
/**
|
|
3
|
+
* The llm-pi-ai settings namespace this patch reads and writes. The shipped
|
|
4
|
+
* Models settings page writes custom providers into the same namespace, so a
|
|
5
|
+
* profile stored there is exactly what this patch annotates with
|
|
6
|
+
* `reasoningEfforts`.
|
|
7
|
+
*/
|
|
8
|
+
export declare const LLM_PI_AI_SETTINGS_NAMESPACE = "llm-pi-ai";
|
|
9
|
+
/**
|
|
10
|
+
* Every pi-ai thinking level a model may offer, in escalation order. Mirror of
|
|
11
|
+
* the `THINKING_LEVELS` the installed `dsh-llm-pi-ai` adapter accepts; a level
|
|
12
|
+
* absent from a model's dict is simply not offered.
|
|
13
|
+
*/
|
|
14
|
+
export declare const THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
15
|
+
export type ThinkingLevel = typeof THINKING_LEVELS[number];
|
|
16
|
+
/**
|
|
17
|
+
* The reasoning-effort set auto-filled onto a model that has none. DSH does
|
|
18
|
+
* not expose a model's true supported levels for custom providers (the pi-ai
|
|
19
|
+
* catalog lives behind the adapter, and `resolveModelInfo` does not surface
|
|
20
|
+
* reasoning for custom routes), so the patch fills a common default which the
|
|
21
|
+
* user can adjust per model. A model with no `reasoningEfforts` at all is
|
|
22
|
+
* treated as non-reasoning by the adapter, so this override is what makes a
|
|
23
|
+
* freshly fetched model think.
|
|
24
|
+
*/
|
|
25
|
+
export declare const DEFAULT_REASONING_EFFORTS: Partial<Record<ThinkingLevel, string>>;
|
|
26
|
+
/**
|
|
27
|
+
* One model's reasoning-effort capability as stored in `settings.yaml`:
|
|
28
|
+
* `false` means the model does not reason at all; a dict maps each offered
|
|
29
|
+
* level to the wire spelling dispatch should send for it (`off` may leave its
|
|
30
|
+
* spelling empty — "supported, send nothing").
|
|
31
|
+
*/
|
|
32
|
+
export type ModelReasoningEfforts = false | Partial<Record<ThinkingLevel, string | null>>;
|
|
33
|
+
/** One configured model's reasoning-effort state; `null` = not configured (falls back to the installed catalog). */
|
|
34
|
+
export interface ModelReasoningEffortsRow {
|
|
35
|
+
provider: string;
|
|
36
|
+
providerName: string;
|
|
37
|
+
modelId: string;
|
|
38
|
+
reasoningEfforts: ModelReasoningEfforts | null;
|
|
39
|
+
}
|
|
40
|
+
/** What the settings page renders from, returned by the `read` route. */
|
|
41
|
+
export interface ModelReasoningEffortsSnapshot {
|
|
42
|
+
rows: readonly ModelReasoningEffortsRow[];
|
|
43
|
+
writable: boolean;
|
|
44
|
+
documentPath: string | undefined;
|
|
45
|
+
}
|
|
46
|
+
/** The `save` route payload; `reasoningEfforts: null` clears the field. */
|
|
47
|
+
export interface SaveModelReasoningEffortsPayload {
|
|
48
|
+
provider: string;
|
|
49
|
+
modelId: string;
|
|
50
|
+
reasoningEfforts: ModelReasoningEfforts | null;
|
|
51
|
+
}
|
|
@@ -3,4 +3,6 @@ export declare class DshMoreApiError extends Error {
|
|
|
3
3
|
constructor(code: string, message: string);
|
|
4
4
|
}
|
|
5
5
|
export declare function callPatchApi<T>(patchId: string, action: string, payload: unknown): Promise<T>;
|
|
6
|
+
/** Fetch a large successful payload as a Blob, avoiding JSON stringify/parse copies. */
|
|
7
|
+
export declare function callPatchBlobApi(patchId: string, action: string, payload: unknown): Promise<Blob>;
|
|
6
8
|
export declare function apiErrorText(error: unknown): string;
|
|
@@ -1,2 +1,14 @@
|
|
|
1
|
+
import type { ConversationSnapshot } from '@deepseek-ai/dsh-client-runtime/client';
|
|
1
2
|
import type { ConversationHeaderProps, MessageTarget } from '../../../kernel/client/message-actions.js';
|
|
2
|
-
export
|
|
3
|
+
export interface MessageSurfaceRow {
|
|
4
|
+
key: string;
|
|
5
|
+
presentationSeq: number | undefined;
|
|
6
|
+
action: Omit<MessageTarget, 'key' | 'host'> | null;
|
|
7
|
+
}
|
|
8
|
+
export interface MessageSurfaceSnapshot {
|
|
9
|
+
rows: readonly MessageSurfaceRow[];
|
|
10
|
+
byKey: ReadonlyMap<string, MessageSurfaceRow>;
|
|
11
|
+
}
|
|
12
|
+
/** Select only facts used by message actions, retaining identity across unrelated stream frames. */
|
|
13
|
+
export declare function createMessageSurfaceSelector(active?: boolean): (snapshot: ConversationSnapshot) => MessageSurfaceSnapshot;
|
|
14
|
+
export declare function useMessageTargets(props: ConversationHeaderProps, hiddenSeqs: ReadonlySet<number>, hiddenTrajectoryKeys: ReadonlySet<string>, active?: boolean): readonly MessageTarget[];
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
/** Successful non-JSON payload that should pass through without serialization. */
|
|
3
|
+
export declare class RawPatchResponse {
|
|
4
|
+
readonly body: string;
|
|
5
|
+
readonly contentType: string;
|
|
6
|
+
constructor(body: string, contentType: string);
|
|
7
|
+
}
|
|
2
8
|
export declare function requireJsonContentType(req: IncomingMessage): void;
|
|
3
9
|
export declare function readJson(req: IncomingMessage): Promise<unknown>;
|
|
4
10
|
export declare function requireString(value: unknown, key: string): string;
|
package/dsh.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-more",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Practical patches for missing DeepSeek Harness Web context and history controls.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"release:patch": "node scripts/release.mjs patch",
|
|
81
81
|
"release:minor": "node scripts/release.mjs minor",
|
|
82
82
|
"release:major": "node scripts/release.mjs major",
|
|
83
|
-
"version": "node scripts/sync-plugin-version.mjs",
|
|
83
|
+
"version": "node scripts/sync-plugin-version.mjs && git add -- dsh.plugin.json",
|
|
84
84
|
"prepack": "npm run check"
|
|
85
85
|
},
|
|
86
86
|
"peerDependencies": {
|