@eduwork/dsh-mail 0.1.1 → 0.2.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/CHANGELOG.en.md +6 -0
- package/CHANGELOG.md +6 -0
- package/CODE_OF_CONDUCT.en.md +1 -1
- package/CODE_OF_CONDUCT.md +1 -1
- package/MAINTAINERS.en.md +1 -1
- package/MAINTAINERS.md +1 -1
- package/README.md +11 -13
- package/{README.en.md → README_EN.md} +11 -13
- package/SECURITY.en.md +1 -1
- package/SECURITY.md +1 -1
- package/SUPPORT.en.md +1 -1
- package/SUPPORT.md +1 -1
- package/THIRD_PARTY_NOTICES.en.md +2 -0
- package/THIRD_PARTY_NOTICES.md +2 -0
- package/docs/EDUWORK-MIGRATION.en.md +2 -6
- package/docs/EDUWORK-MIGRATION.md +2 -6
- package/docs/architecture.en.md +3 -3
- package/docs/architecture.md +3 -3
- package/docs/compatibility.en.md +5 -6
- package/docs/compatibility.md +5 -6
- package/docs/getting-started.en.md +8 -8
- package/docs/getting-started.md +8 -8
- package/docs/release-checklist.en.md +7 -49
- package/docs/release-checklist.md +7 -49
- package/docs/security-model.en.md +4 -0
- package/docs/security-model.md +4 -0
- package/lib/client.js +167 -157
- package/lib/index.js +171 -36
- package/package.json +26 -17
package/lib/index.js
CHANGED
|
@@ -78,6 +78,43 @@ function pick(source, keys, forced) {
|
|
|
78
78
|
for (const key of keys) if (forced || source[key] !== void 0) result[key] = source[key];
|
|
79
79
|
return result;
|
|
80
80
|
}
|
|
81
|
+
/** Shared config references used by schema validators and plugin runtimes. */
|
|
82
|
+
const write = Symbol.for("cosmokit.volatile.write");
|
|
83
|
+
function snapshot(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
84
|
+
if (typeof value === "function") throw new TypeError("volatile config cannot contain functions");
|
|
85
|
+
if (value === null || typeof value !== "object") return value;
|
|
86
|
+
if (ancestors.has(value)) throw new TypeError("volatile config cannot contain cycles");
|
|
87
|
+
ancestors.add(value);
|
|
88
|
+
try {
|
|
89
|
+
if (Array.isArray(value)) return Object.freeze(value.map((item) => snapshot(item, ancestors)));
|
|
90
|
+
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) throw new TypeError("volatile config objects must be plain objects or arrays");
|
|
91
|
+
return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [key, snapshot(item, ancestors)])));
|
|
92
|
+
} finally {
|
|
93
|
+
ancestors.delete(value);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Create a detached reference containing an immutable copy of the supplied data.
|
|
98
|
+
* @param value - validated config data; class instances and functions are unsupported.
|
|
99
|
+
* @returns a reference whose value is updated only by its owning runtime.
|
|
100
|
+
*/
|
|
101
|
+
function createVolatile(value) {
|
|
102
|
+
let current = snapshot(value);
|
|
103
|
+
return Object.freeze({
|
|
104
|
+
get: () => current,
|
|
105
|
+
[write]: (value) => {
|
|
106
|
+
current = value;
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Identify references across ESM/CJS copies of the shared library.
|
|
112
|
+
* @param value - a parsed config value.
|
|
113
|
+
* @returns whether the value implements the shared reference protocol.
|
|
114
|
+
*/
|
|
115
|
+
function isVolatile(value) {
|
|
116
|
+
return typeof value === "object" && value !== null && write in value;
|
|
117
|
+
}
|
|
81
118
|
/** Test values using `instanceof` with a `toStringTag` fallback. */
|
|
82
119
|
function is(type, value) {
|
|
83
120
|
if (arguments.length === 1) return (value) => is(type, value);
|
|
@@ -158,26 +195,47 @@ function clone(source, refs = /* @__PURE__ */ new Map()) {
|
|
|
158
195
|
}
|
|
159
196
|
return result;
|
|
160
197
|
}
|
|
161
|
-
/**
|
|
198
|
+
/**
|
|
199
|
+
* Compare values recursively, treating two volatile references as equal regardless of value.
|
|
200
|
+
* Strict comparison distinguishes null/undefined, treats opaque objects by identity,
|
|
201
|
+
* compares URLs by normalized href, treats array holes as undefined, and considers distinct cyclic structures unequal.
|
|
202
|
+
* @param a - first value.
|
|
203
|
+
* @param b - second value.
|
|
204
|
+
* @param strict - whether to require strict data equality outside volatile references.
|
|
205
|
+
* @returns whether the values compare equal.
|
|
206
|
+
*/
|
|
162
207
|
function deepEqual(a, b, strict) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
208
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
209
|
+
function compare(a, b) {
|
|
210
|
+
if (a === b) return true;
|
|
211
|
+
if (isVolatile(a) || isVolatile(b)) return isVolatile(a) && isVolatile(b);
|
|
212
|
+
if (!strict && isNullable(a) && isNullable(b)) return true;
|
|
213
|
+
if (typeof a !== typeof b || typeof a !== "object" || !a || !b) return false;
|
|
214
|
+
if (ancestors.has(a)) return false;
|
|
215
|
+
function check(test, then) {
|
|
216
|
+
return test(a) ? test(b) ? then(a, b) : false : test(b) ? false : void 0;
|
|
217
|
+
}
|
|
218
|
+
ancestors.add(a);
|
|
219
|
+
try {
|
|
220
|
+
return check(Array.isArray, (a, b) => {
|
|
221
|
+
if (a.length !== b.length) return false;
|
|
222
|
+
for (let index = 0; index < a.length; index++) if (!compare(a[index], b[index])) return false;
|
|
223
|
+
return true;
|
|
224
|
+
}) ?? check(is("Date"), (a, b) => a.valueOf() === b.valueOf()) ?? check(is("URL"), (a, b) => a.href === b.href) ?? check(is("RegExp"), (a, b) => a.source === b.source && a.flags === b.flags) ?? check(isArrayBufferLike, (a, b) => {
|
|
225
|
+
if (a.byteLength !== b.byteLength) return false;
|
|
226
|
+
const viewA = new Uint8Array(a);
|
|
227
|
+
const viewB = new Uint8Array(b);
|
|
228
|
+
for (let i = 0; i < viewA.length; i++) if (viewA[i] !== viewB[i]) return false;
|
|
229
|
+
return true;
|
|
230
|
+
}) ?? ((!strict || [a, b].every((value) => Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) && Object.keys({
|
|
231
|
+
...a,
|
|
232
|
+
...b
|
|
233
|
+
}).every((key) => compare(a[key], b[key])));
|
|
234
|
+
} finally {
|
|
235
|
+
ancestors.delete(a);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return compare(a, b);
|
|
181
239
|
}
|
|
182
240
|
/** Time constants plus parsing and formatting helpers. */
|
|
183
241
|
var Time;
|
|
@@ -426,6 +484,7 @@ Schema.prototype.pattern = function pattern(regexp) {
|
|
|
426
484
|
return schema;
|
|
427
485
|
};
|
|
428
486
|
Schema.prototype.simplify = function simplify(value) {
|
|
487
|
+
if (isVolatile(value)) value = value.get();
|
|
429
488
|
if (deepEqual(value, this.meta.default, this.type === "dict")) return null;
|
|
430
489
|
if (isNullable(value)) return value;
|
|
431
490
|
if (this.type === "object" || this.type === "dict") {
|
|
@@ -482,12 +541,49 @@ for (const key of [
|
|
|
482
541
|
};
|
|
483
542
|
return schema;
|
|
484
543
|
} });
|
|
544
|
+
Schema.prototype.volatile = function volatile() {
|
|
545
|
+
if (this.meta.volatile) throw new TypeError("volatile schema is already wrapped");
|
|
546
|
+
return this.extra("volatile", true);
|
|
547
|
+
};
|
|
485
548
|
const resolvers = {};
|
|
549
|
+
const checkedVolatile = Symbol("checked-volatile-schema");
|
|
550
|
+
function validateVolatileSchema(schema, path = [], blocked = false, seen = /* @__PURE__ */ new Map()) {
|
|
551
|
+
const states = seen.get(schema) ?? /* @__PURE__ */ new Set();
|
|
552
|
+
if (states.has(blocked)) return;
|
|
553
|
+
states.add(blocked);
|
|
554
|
+
seen.set(schema, states);
|
|
555
|
+
if (schema.meta?.volatile && blocked) throw new ValidationError("volatile fields require a fixed object path without an enclosing volatile field", { path });
|
|
556
|
+
const nested = blocked || !!schema.meta?.volatile;
|
|
557
|
+
if (schema.dict) for (const [key, child] of Object.entries(schema.dict)) validateVolatileSchema(child, [...path, key], nested, seen);
|
|
558
|
+
if (schema.sKey) validateVolatileSchema(schema.sKey, [...path, "<key>"], true, seen);
|
|
559
|
+
if (schema.inner && (schema.type !== "lazy" || schema.inner[kSchema])) validateVolatileSchema(schema.inner, [...path, "*"], true, seen);
|
|
560
|
+
if (schema.list) for (let index = 0; index < schema.list.length; index++) validateVolatileSchema(schema.list[index], [...path, String(index)], true, seen);
|
|
561
|
+
}
|
|
486
562
|
Schema.extend = function extend(type, resolve) {
|
|
487
563
|
resolvers[type] = resolve;
|
|
488
564
|
};
|
|
489
565
|
Schema.resolve = function resolve(data, schema, options = {}, strict = false) {
|
|
490
566
|
if (!schema) return [data];
|
|
567
|
+
if (!options[checkedVolatile]) {
|
|
568
|
+
validateVolatileSchema(schema, options.path);
|
|
569
|
+
options = {
|
|
570
|
+
...options,
|
|
571
|
+
[checkedVolatile]: true
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
if (schema.meta?.volatile) {
|
|
575
|
+
const inner = Schema(schema);
|
|
576
|
+
inner.meta = {
|
|
577
|
+
...schema.meta,
|
|
578
|
+
volatile: false
|
|
579
|
+
};
|
|
580
|
+
const [value, adapted] = Schema.resolve(data, inner, options, strict);
|
|
581
|
+
try {
|
|
582
|
+
return [createVolatile(value), adapted];
|
|
583
|
+
} catch (error) {
|
|
584
|
+
throw new ValidationError(error instanceof Error ? error.message : String(error), options);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
491
587
|
if (options.ignore?.(data, schema)) return [data];
|
|
492
588
|
if (isNullable(data) && schema.type !== "lazy") {
|
|
493
589
|
if (schema.meta.required) throw new ValidationError(`missing required value`, options);
|
|
@@ -590,6 +686,7 @@ Schema.extend("lazy", (data, schema, options, strict) => {
|
|
|
590
686
|
...schema.meta,
|
|
591
687
|
...schema.inner.meta
|
|
592
688
|
};
|
|
689
|
+
validateVolatileSchema(schema.inner, options.path, true);
|
|
593
690
|
}
|
|
594
691
|
return Schema.resolve(data, schema.inner, options, strict);
|
|
595
692
|
});
|
|
@@ -689,7 +786,7 @@ function property(data, key, schema, options) {
|
|
|
689
786
|
} catch (e) {
|
|
690
787
|
if (!options?.autofix) throw e;
|
|
691
788
|
delete data[key];
|
|
692
|
-
return schema.meta.default;
|
|
789
|
+
return schema.meta.volatile ? createVolatile(schema.meta.default) : schema.meta.default;
|
|
693
790
|
}
|
|
694
791
|
}
|
|
695
792
|
Schema.extend("array", (data, { inner, meta }, options) => {
|
|
@@ -848,20 +945,21 @@ defineMethod("transform", [
|
|
|
848
945
|
const MailSettingsSchema = Schema.object({
|
|
849
946
|
readEnabled: Schema.boolean().default(DEFAULTS.readEnabled),
|
|
850
947
|
sendEnabled: Schema.boolean().default(DEFAULTS.sendEnabled),
|
|
851
|
-
email: Schema.string().default(DEFAULTS.email),
|
|
852
|
-
username: Schema.string().default(DEFAULTS.username),
|
|
853
|
-
fromName: Schema.string().default(DEFAULTS.fromName),
|
|
854
|
-
inboxFolder: Schema.string().default(DEFAULTS.inboxFolder),
|
|
855
|
-
imapHost: Schema.string().default(DEFAULTS.imapHost),
|
|
856
|
-
imapPort: Schema.number().default(DEFAULTS.imapPort),
|
|
948
|
+
email: Schema.string().pattern(/^[^\r\n\u0000]*$/u).default(DEFAULTS.email),
|
|
949
|
+
username: Schema.string().pattern(/^[^\r\n\u0000]*$/u).default(DEFAULTS.username),
|
|
950
|
+
fromName: Schema.string().pattern(/^[^\r\n\u0000]*$/u).default(DEFAULTS.fromName),
|
|
951
|
+
inboxFolder: Schema.string().pattern(/^[^\r\n\u0000]*$/u).default(DEFAULTS.inboxFolder),
|
|
952
|
+
imapHost: Schema.string().pattern(/^[^\r\n\u0000]*$/u).default(DEFAULTS.imapHost),
|
|
953
|
+
imapPort: Schema.number().step(1).min(1).max(65535).default(DEFAULTS.imapPort),
|
|
857
954
|
imapTls: Schema.union(["implicit", "starttls"]).default(DEFAULTS.imapTls),
|
|
858
|
-
smtpHost: Schema.string().default(DEFAULTS.smtpHost),
|
|
859
|
-
smtpPort: Schema.number().default(DEFAULTS.smtpPort),
|
|
955
|
+
smtpHost: Schema.string().pattern(/^[^\r\n\u0000]*$/u).default(DEFAULTS.smtpHost),
|
|
956
|
+
smtpPort: Schema.number().step(1).min(1).max(65535).default(DEFAULTS.smtpPort),
|
|
860
957
|
smtpTls: Schema.union(["implicit", "starttls"]).default(DEFAULTS.smtpTls),
|
|
861
|
-
maxBodyChars: Schema.number().default(DEFAULTS.maxBodyChars),
|
|
862
|
-
maxMessageBytes: Schema.number().default(DEFAULTS.maxMessageBytes),
|
|
863
|
-
maxAttachmentBytes: Schema.number().default(DEFAULTS.maxAttachmentBytes)
|
|
958
|
+
maxBodyChars: Schema.number().step(1).min(1e3).max(2e5).default(DEFAULTS.maxBodyChars),
|
|
959
|
+
maxMessageBytes: Schema.number().step(1).min(1048576).max(104857600).default(DEFAULTS.maxMessageBytes),
|
|
960
|
+
maxAttachmentBytes: Schema.number().step(1).min(1024).max(104857600).default(DEFAULTS.maxAttachmentBytes)
|
|
864
961
|
});
|
|
962
|
+
const Config = typeof Schema.string().volatile === "function" ? Schema.object(Object.fromEntries(Object.entries(MailSettingsSchema.dict).map(([key, field]) => [key, field.volatile()]))) : void 0;
|
|
865
963
|
function settingsBase(config = {}) {
|
|
866
964
|
const base = { ...DEFAULTS };
|
|
867
965
|
for (const key of Object.keys(DEFAULTS)) if (config[key] !== void 0) base[key] = config[key];
|
|
@@ -910,6 +1008,7 @@ const SEND_APPROVAL_REASON = "Send this email through the configured SMTP accoun
|
|
|
910
1008
|
* after the user has explicitly enabled sending in Mail assistant settings.
|
|
911
1009
|
*/
|
|
912
1010
|
function decideMailPermission(ctx, exec, next) {
|
|
1011
|
+
if (exec.name === TOOL_NAMES.attachment) return decideAttachmentWrite(ctx, exec, next);
|
|
913
1012
|
if (exec.name !== TOOL_NAMES.send) return next();
|
|
914
1013
|
const agent = exec.agent;
|
|
915
1014
|
if (agent === void 0) return Promise.resolve({
|
|
@@ -922,6 +1021,38 @@ function decideMailPermission(ctx, exec, next) {
|
|
|
922
1021
|
reason: SEND_APPROVAL_REASON
|
|
923
1022
|
});
|
|
924
1023
|
}
|
|
1024
|
+
async function decideAttachmentWrite(ctx, exec, next) {
|
|
1025
|
+
if (!exec.agent) return {
|
|
1026
|
+
kind: "deny",
|
|
1027
|
+
reason: "Attachment downloads require an Agent-backed session"
|
|
1028
|
+
};
|
|
1029
|
+
if (!exec.agent.session.header?.cwd) return {
|
|
1030
|
+
kind: "deny",
|
|
1031
|
+
reason: "Attachment downloads require a session workspace"
|
|
1032
|
+
};
|
|
1033
|
+
const resolver = ctx.get?.("sandboxPolicy");
|
|
1034
|
+
const policy = resolver ? resolver.resolve({ session: exec.agent.session }) : { mode: ctx.permissionPresets.current(exec.agent.session) };
|
|
1035
|
+
if (policy?.mode === "danger-full-access") return next();
|
|
1036
|
+
if (policy?.mode === "workspace-write") {
|
|
1037
|
+
if (policy.workspaceRoot !== void 0) {
|
|
1038
|
+
const options = {
|
|
1039
|
+
cwd: exec.agent.session.header.cwd,
|
|
1040
|
+
signal: exec.signal
|
|
1041
|
+
};
|
|
1042
|
+
const root = await ctx.fs.resolve(".", options);
|
|
1043
|
+
const allowed = await ctx.fs.resolve(policy.workspaceRoot, options);
|
|
1044
|
+
if (!ctx.fs.contains(allowed, root)) return {
|
|
1045
|
+
kind: "deny",
|
|
1046
|
+
reason: "Attachment workspace is outside the allowed write root"
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
return next();
|
|
1050
|
+
}
|
|
1051
|
+
return {
|
|
1052
|
+
kind: "ask",
|
|
1053
|
+
reason: "Save this mail attachment in the current workspace"
|
|
1054
|
+
};
|
|
1055
|
+
}
|
|
925
1056
|
Object.freeze({ SEND_APPROVAL_REASON });
|
|
926
1057
|
//#endregion
|
|
927
1058
|
//#region node_modules/pino-std-serializers/lib/err-helpers.js
|
|
@@ -101893,11 +102024,12 @@ async function readWorkspaceAttachments(ctx, paths, exec, maxBytes) {
|
|
|
101893
102024
|
if (!Array.isArray(paths) || paths.length > 10 || paths.some((path) => typeof path !== "string" || path.trim() === "")) throw new Error("attachments must be an array of at most 10 non-empty workspace paths");
|
|
101894
102025
|
const workspace = workspaceOf(exec);
|
|
101895
102026
|
const workspaceTarget = await ctx.fs.resolve(workspace, { signal: exec.signal });
|
|
102027
|
+
const cwd = ctx.get?.("workingDirectory")?.get(exec.agent.session) ?? workspace;
|
|
101896
102028
|
const attachments = [];
|
|
101897
102029
|
let total = 0;
|
|
101898
102030
|
for (const raw of paths) {
|
|
101899
102031
|
const target = await ctx.fs.resolve(raw.trim(), {
|
|
101900
|
-
cwd
|
|
102032
|
+
cwd,
|
|
101901
102033
|
signal: exec.signal
|
|
101902
102034
|
});
|
|
101903
102035
|
if (!ctx.fs.contains(workspaceTarget, target)) throw new Error(`Attachment is outside the session workspace: ${raw}`);
|
|
@@ -102412,14 +102544,16 @@ const inject = [
|
|
|
102412
102544
|
"permissionPresets"
|
|
102413
102545
|
];
|
|
102414
102546
|
function apply(ctx, config = {}) {
|
|
102415
|
-
const
|
|
102547
|
+
const native = typeof ctx.settings.register !== "function";
|
|
102548
|
+
const readLive = () => Object.fromEntries(Object.keys(DEFAULTS).map((key) => [key, config[key].get()]));
|
|
102549
|
+
const base = native ? readLive() : settingsBase(config);
|
|
102416
102550
|
validateSettings(base);
|
|
102417
|
-
const scope = ctx.settings.register(SETTINGS_NAMESPACE, MailSettingsSchema, {
|
|
102551
|
+
const scope = native ? { get: readLive } : ctx.settings.register(SETTINGS_NAMESPACE, MailSettingsSchema, {
|
|
102418
102552
|
base,
|
|
102419
102553
|
applies: "live",
|
|
102420
102554
|
validate: validateSettings
|
|
102421
102555
|
});
|
|
102422
|
-
const getSettings = () => currentSettings(ctx, scope, config);
|
|
102556
|
+
const getSettings = () => currentSettings(ctx, scope, native ? {} : config);
|
|
102423
102557
|
ctx.on("tools/pre-execute", (exec, next) => decideMailPermission(ctx, exec, next));
|
|
102424
102558
|
installTools(ctx, getSettings);
|
|
102425
102559
|
ctx.tools.guard((exec) => {
|
|
@@ -102453,9 +102587,10 @@ function apply(ctx, config = {}) {
|
|
|
102453
102587
|
var host_default = {
|
|
102454
102588
|
name,
|
|
102455
102589
|
inject,
|
|
102590
|
+
Config,
|
|
102456
102591
|
apply
|
|
102457
102592
|
};
|
|
102458
102593
|
//#endregion
|
|
102459
|
-
export { DEFAULTS, MailSettingsSchema, PASSWORD_REF_NAME, SETTINGS_NAMESPACE, TOOL_NAMES, apply, host_default as default, inject, name, validateSettings };
|
|
102594
|
+
export { Config, DEFAULTS, MailSettingsSchema, PASSWORD_REF_NAME, SETTINGS_NAMESPACE, TOOL_NAMES, apply, host_default as default, inject, name, validateSettings };
|
|
102460
102595
|
|
|
102461
102596
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eduwork/dsh-mail",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Standards-based IMAP/SMTP mail assistant for DeepSeek Harness with explicit read/send controls and approval-aware delivery",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"lib/**/*.js",
|
|
24
24
|
"docs/**/*.md",
|
|
25
25
|
"README.md",
|
|
26
|
-
"
|
|
26
|
+
"README_EN.md",
|
|
27
27
|
"CHANGELOG.md",
|
|
28
28
|
"CHANGELOG.en.md",
|
|
29
29
|
"CODE_OF_CONDUCT.md",
|
|
@@ -50,7 +50,8 @@
|
|
|
50
50
|
"inject": [
|
|
51
51
|
"@deepseek-ai/dsh-api-remotes",
|
|
52
52
|
"@deepseek-ai/dsh-client-ui-renderer",
|
|
53
|
-
"@deepseek-ai/dsh-client-ui-settings"
|
|
53
|
+
"@deepseek-ai/dsh-client-ui-settings",
|
|
54
|
+
"@deepseek-ai/dsh-client-locale"
|
|
54
55
|
],
|
|
55
56
|
"platform": "web",
|
|
56
57
|
"immediately": true
|
|
@@ -78,7 +79,7 @@
|
|
|
78
79
|
"prepare": "npm run build"
|
|
79
80
|
},
|
|
80
81
|
"engines": {
|
|
81
|
-
"node": ">=
|
|
82
|
+
"node": ">=24.18.0"
|
|
82
83
|
},
|
|
83
84
|
"license": "MIT",
|
|
84
85
|
"publishConfig": {
|
|
@@ -86,21 +87,23 @@
|
|
|
86
87
|
},
|
|
87
88
|
"repository": {
|
|
88
89
|
"type": "git",
|
|
89
|
-
"url": "git+https://github.com/
|
|
90
|
+
"url": "git+https://github.com/ECNU/EduWork.git",
|
|
91
|
+
"directory": "packages/dsh-mail"
|
|
90
92
|
},
|
|
91
93
|
"bugs": {
|
|
92
|
-
"url": "https://github.com/
|
|
94
|
+
"url": "https://github.com/ECNU/EduWork/issues"
|
|
93
95
|
},
|
|
94
|
-
"homepage": "https://github.com/
|
|
96
|
+
"homepage": "https://github.com/ECNU/EduWork/tree/main/packages/dsh-mail#readme",
|
|
95
97
|
"peerDependencies": {
|
|
96
|
-
"@deepseek-ai/cordis": "4.0.
|
|
97
|
-
"@deepseek-ai/dsh-api-remotes": "0.
|
|
98
|
-
"@deepseek-ai/dsh-client-ui-renderer": "0.
|
|
99
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.
|
|
100
|
-
"@deepseek-ai/dsh-credentials": "0.
|
|
101
|
-
"@deepseek-ai/dsh-permission-presets": "0.
|
|
102
|
-
"@deepseek-ai/dsh-tools": "0.
|
|
103
|
-
"react": "^18.2.0"
|
|
98
|
+
"@deepseek-ai/cordis": ">=4.0.5 <4.1.0",
|
|
99
|
+
"@deepseek-ai/dsh-api-remotes": ">=0.2.1-rc.2 <0.3.0-0",
|
|
100
|
+
"@deepseek-ai/dsh-client-ui-renderer": ">=0.2.1-rc.2 <0.3.0-0",
|
|
101
|
+
"@deepseek-ai/dsh-client-ui-settings": ">=0.2.1-rc.2 <0.3.0-0",
|
|
102
|
+
"@deepseek-ai/dsh-credentials": ">=0.2.1-rc.2 <0.3.0-0",
|
|
103
|
+
"@deepseek-ai/dsh-permission-presets": ">=0.2.1-rc.2 <0.3.0-0",
|
|
104
|
+
"@deepseek-ai/dsh-tools": ">=0.2.1-rc.2 <0.3.0-0",
|
|
105
|
+
"react": "^18.2.0",
|
|
106
|
+
"@deepseek-ai/dsh-client-locale": ">=0.2.1-rc.2 <0.3.0-0"
|
|
104
107
|
},
|
|
105
108
|
"peerDependenciesMeta": {
|
|
106
109
|
"@deepseek-ai/cordis": {
|
|
@@ -126,10 +129,13 @@
|
|
|
126
129
|
},
|
|
127
130
|
"react": {
|
|
128
131
|
"optional": true
|
|
132
|
+
},
|
|
133
|
+
"@deepseek-ai/dsh-client-locale": {
|
|
134
|
+
"optional": true
|
|
129
135
|
}
|
|
130
136
|
},
|
|
131
137
|
"devDependencies": {
|
|
132
|
-
"@deepseek-ai/schemastery": "3.18.
|
|
138
|
+
"@deepseek-ai/schemastery": "3.18.5",
|
|
133
139
|
"@types/node": "^26.0.0",
|
|
134
140
|
"@types/react": "^18.3.28",
|
|
135
141
|
"imapflow": "^1.7.0",
|
|
@@ -137,7 +143,10 @@
|
|
|
137
143
|
"nodemailer": "^9.1.0",
|
|
138
144
|
"react": "^18.3.1",
|
|
139
145
|
"tsdown": "0.22.14",
|
|
140
|
-
"typescript": "^5.9.3"
|
|
146
|
+
"typescript": "^5.9.3",
|
|
147
|
+
"@deepseek-ai/dsh": "0.2.1-rc.2",
|
|
148
|
+
"@deepseek-ai/cordis": "4.0.5",
|
|
149
|
+
"semver": "7.7.4"
|
|
141
150
|
},
|
|
142
151
|
"directories": {
|
|
143
152
|
"doc": "docs",
|