@lmzhen/dsh-evolution-commands 0.32.4 → 0.32.6
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 +5 -28
- package/lib/index.js +149 -3
- package/lib/types/command-fallback.d.ts +1 -1
- package/lib/types/settings-route.d.ts +27 -0
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,34 +1,11 @@
|
|
|
1
1
|
# @lmzhen/dsh-evolution-commands
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
and its help text, and drives the other rows from a command. It adds no automatic
|
|
5
|
-
background behaviour of its own.
|
|
3
|
+
Host command surface for the `/evolution` namespace: diagnostics, pending approvals, curator operations, maintenance, skill history, parameters, merge dispatch, migration, and preset installation.
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
The canonical user command reference is [docs/commands.md](../../docs/commands.md); the package map and preset-install spelling live in [packages/README.md](../README.md). Do not maintain a second command table here.
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
- **Prompt prefix / KV cache:** independent of request-prefix construction — it does not alter the assembled prompt or tool list; family rules: `packages/README.md` §"Model-visible prompt prefix and the KV cache".
|
|
11
|
-
- **Mount it?** yes — the `evolution-commands` row, carried by the `evolution-host`, `evolution-all` and `evolution-preset` bundles.
|
|
7
|
+
The command row ships with `all`, `host`, and `preset`. If the platform `commands` service is absent, the `/evolution` namespace is not registered.
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
Under a layered/variant installation, original-preset sessions still see the management commands even though they do not carry the family model rows. That accepted difference and the mutual-exclusion rules are single-sourced in [INSTALL.md](../INSTALL.md).
|
|
14
10
|
|
|
15
|
-
The
|
|
16
|
-
|
|
17
|
-
## Known limitations
|
|
18
|
-
|
|
19
|
-
- No known durable consumer gaps at this time. Runtime contracts are covered by package and boundary tests.
|
|
20
|
-
- **`/evolution maintain` runs in the BACKGROUND (0.19.0).** The command answers with a run id and the scan keeps working: read it with `/evolution maintain report [<id>]` (a run that produced nothing answers "no result" instead of an empty plan) or `/evolution maintain status [<id>]` (in flight plus the recent terminal states). Since 0.20.0 the id may be **omitted** on `report`, `cancel` and `handoff`: it then means the newest run in this home, and an unreadable `runs.json` answers "the run index is not readable" for that form rather than guessing. The run's lifetime belongs to this plugin through `evolution-core`'s run registry, **not** to the request that started it: the desktop shell ends a request at ~305 s (measured four times) while the same scan completes in 949.7 s on the web plane, and `maintainTimeoutMs` (default 600000) bounds the run itself. **Cancelling the request no longer stops the scan** — use `/evolution maintain cancel <id>`, or unmount the row. The plan is written once at settle to `<evolutionHome>/reports/maintain-<runId>.{json,md}`, under the same per-home reports window the curator's reports use.
|
|
21
|
-
- **`maintain handoff` is a SOFT gate (0.20.0, accepted).** The injected protocol asks the model to report and wait for the user's reply, and "what was approved" lives only in that conversation — the family keeps no approval record of its own. Escalate to the existing `evolution-approval` channel when unattended bulk skill edits, a multi-person audit trail, or non-repudiation become requirements.
|
|
22
|
-
- **`maintain handoff` reports a run whose state is not `succeeded` as "ready" when a report file exists (0.20.0, accepted).** A failed or cancelled run writes the same `.json`/`.md` pair (the failure text is the report), so the injection fires and the protocol's first line — read the file — is what tells the model what happened. Tightening it to `succeeded` only is a behavior choice, not a defect fix.
|
|
23
|
-
- **The injected pointer names the `.md` digest without re-probing it (0.20.0, accepted).** `reportDigestPath` swaps the `.json` suffix; the writer emits both files in one settle, so a hand-deleted `.md` beside a live `.json` would name a missing file.
|
|
24
|
-
- **The id-less forms repeat the same resolve skeleton three times (0.20.0, recorded).** `report`, `cancel` and `handoff` each run `syncRuns` → id-less `newestRun` → three-state error reporting; the wording is shared through `unreadableIndex`/`unreadableForId`, the skeleton is not. Extracting one resolver is the next batch's refactor.
|
|
25
|
-
- **Cross-plane run state is eventual, and the shared index is the truth for runs this process does not own (0.19.1).** Two hosts sharing one `DSH_HOME` (the desktop app and a `dsh web` plane) read and write `evolution/runs.json` together. `begin()` resolves only after its row is in that index, so a plane reading the answer "started" finds the run; a run another plane owns is re-read at this plane's **next** read, and it stops being live in exactly two ways — its owner settled it (that terminal state is adopted) or its owner died (converged to `failed(orphan)`, with the reason spelled out). Runs this process owns keep memory as the truth. No timer and no heartbeat sits behind this: 0.19.0 skipped ids it already knew, which left an observing plane reporting `running` forever and refusing its own `maintain` until it restarted. The rule is monotonic on BOTH sides (0.19.2): the read side adopts a terminal row, and the write side never puts a row this process does not own back to `running` over the terminal state its owner wrote — so a settled run cannot be resurrected by this plane's own later write. Two hosts sharing one home must be on the SAME machine: `isProcessAlive(pid)` does not cross machines. Structurally (0.19.3) a row has **exactly one writer — the process that started it**: this process's rows live in its own map, every other row is whatever the index says (rebuilt on each read), and a settled row is **never** shown as running again — a stale writer that puts `running` back is refused on read and repaired on the next write.
|
|
26
|
-
- **① variant form: the `/evolution …` command face is visible in every session** (accepted, not fixed). Commands are registered in scope layers, and the family registers once on the host plane, so a session on a platform original preset still lists the management-only subcommands even though no automatic family behaviour reaches it. The difference and its reasoning are single-sourced in `INSTALL.md` ("Known difference").
|
|
27
|
-
|
|
28
|
-
**Runtime invariant:** No companion is published. The platform auto-assembles nothing and the family mounts no `<pkg>/invariant` cordis row, so a companion here would never execute (v37 S2.1 / I-3).
|
|
29
|
-
|
|
30
|
-
## Notes and history
|
|
31
|
-
|
|
32
|
-
- P2-22 (v11) correction: this package's direct model-visible tokens are the `/evolution learn` injection (the full learning guidance) and — since 0.20.0 — the `maintain handoff` injection (a report pointer plus the report-only protocol). Both are injected as user messages in this session; see **Model surface** above for the current count.
|
|
33
|
-
- **① variant form: the `/evolution …` command face is visible in every session** (accepted, not fixed: 0.3.78).
|
|
34
|
-
- The injection goes through the agent's waking primitive (`followup`, falling back to `inject` when the host lacks it), **called on the agent instance**: the platform's `Agent.followup` is a prototype method (`this.send(...)`), so a detached reference throws and queues nothing (0.3.73 fix; the same shape is pinned by rule N13b in `packages/scripts/verify-arch-guards.mjs`, which masks comments and string literals before matching and self-tests its detector at startup).
|
|
11
|
+
The old `consolidate` command is retired; use `merge` for skill merging.
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
-
import { DEFAULT_SKILL_LIMITS, DIAGNOSTICS_FACT_KEYS, DIAGNOSTICS_RUNTIME_KEYS, DIAGNOSTICS_VIEW_SCHEMA_VERSION, EVOLUTION_PRESET_IDS, MAINTAINER_PRESET_ID, MAX_TIMER_DELAY_MS, PARAM_EXPOSURE, PARAM_GROUP_LABELS, PLATFORM_LINE, REVIEWER_PRESET_ID, absentHostServices, appendEvolutionEvent, applyNamespaceMigration, asRecord, assertSkillsRootAliasRetired, atomicWriteFiles, authorityFrom, buildExtractPlanFromLibrary, buildLearnPrompt, canonicalWriteId, clampedNumber, classifyNamespaceMigration, classifySessionEvent, createSubagentChannel, elapsedSince, errorText, eventsFile, evolutionHome, evolutionRoot, hostSurface, isDeprecatedParamId, isPresent, isRecord, isUnknown, liveBool, newRunRegistry, newSkillLibrary, ownerDecisionText, paramSettingsId, partitionVersions, planNamespaceMigration, policyStageLimits, probeMtime, probeText, proposalFromPlan, reportsSweepLockTarget, resolveParamId, resolveRootConfig, scopedPackageName, scopedProbeReport, sweepReports, transactIo, writeProposalReport } from "@lmzhen/dsh-evolution-core";
|
|
2
|
+
import { DEFAULT_SKILL_LIMITS, DIAGNOSTICS_FACT_KEYS, DIAGNOSTICS_RUNTIME_KEYS, DIAGNOSTICS_VIEW_SCHEMA_VERSION, EVOLUTION_PRESET_IDS, MAINTAINER_PRESET_ID, MAX_TIMER_DELAY_MS, PARAM_EXPOSURE, PARAM_GROUP_LABELS, PARAM_NAMESPACES, PLATFORM_LINE, REVIEWER_PRESET_ID, absentHostServices, appendEvolutionEvent, applyNamespaceMigration, asRecord, assertSkillsRootAliasRetired, atomicWriteFiles, authorityFrom, buildExtractPlanFromLibrary, buildLearnPrompt, canonicalWriteId, clampedNumber, classifyNamespaceMigration, classifySessionEvent, createSubagentChannel, elapsedSince, errorText, eventsFile, evolutionHome, evolutionRoot, hostSurface, isDeprecatedParamId, isPresent, isRecord, isUnknown, liveBool, newRunRegistry, newSkillLibrary, ownerDecisionText, paramSettingsId, partitionVersions, planNamespaceMigration, policyStageLimits, probeMtime, probeText, proposalFromPlan, registerOwnerSettings, reportsSweepLockTarget, resolveParamId, resolveRootConfig, scopedPackageName, scopedProbeReport, sweepReports, transactIo, unwrapLive, writeProposalReport } from "@lmzhen/dsh-evolution-core";
|
|
3
3
|
import { HOST_ROUTES, json, methodNotAllowed, registerHostRoutes } from "@lmzhen/dsh-evolution-core/http-routes";
|
|
4
4
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
5
5
|
import { dirname, join } from "node:path";
|
|
@@ -29,9 +29,10 @@ import { processScopeViolations } from "@lmzhen/dsh-evolution-state-storage";
|
|
|
29
29
|
*/
|
|
30
30
|
const COMMAND_FALLBACKS = {
|
|
31
31
|
approval: { command: "/evolution pending … /evolution approve <id> … /evolution reject <id> … /evolution release <id>" },
|
|
32
|
-
"skill-history": { command: "/evolution
|
|
32
|
+
"skill-history": { command: "/evolution skill undo <name> [--to v<N>](查看:/evolution skill history <name>)" },
|
|
33
33
|
"skill-health": { command: "/evolution skills refresh(健康行:/evolution doctor)" },
|
|
34
34
|
merge: { command: "/evolution merge status / pending / approve <id> / report" },
|
|
35
|
+
settings: { command: "/evolution policy set <id> <value>(查看:/evolution policy)" },
|
|
35
36
|
diagnostics: {
|
|
36
37
|
command: "/evolution doctor",
|
|
37
38
|
platformCli: "dsh --json /evolution doctor"
|
|
@@ -486,6 +487,150 @@ function makeDiagnosticsRoutes(getInputs) {
|
|
|
486
487
|
}];
|
|
487
488
|
}
|
|
488
489
|
//#endregion
|
|
490
|
+
//#region lib/types/settings-route.js
|
|
491
|
+
/**
|
|
492
|
+
* Family settings data plane.
|
|
493
|
+
*
|
|
494
|
+
* The platform RPC only serves its own namespace allowlist, so the browser cannot
|
|
495
|
+
* reach family namespaces through /api/settings.* even though the underlying
|
|
496
|
+
* settings service has them registered. These exact routes reuse the SAME
|
|
497
|
+
* provider (describe/mutate), so storage, schema validation, revision conflicts
|
|
498
|
+
* and redaction stay platform-owned; only the transport is family-scoped.
|
|
499
|
+
* @module @lmzhen/dsh-evolution-commands/settings-route
|
|
500
|
+
*/
|
|
501
|
+
const FAMILY_NAMESPACES = new Set(Object.keys(PARAM_NAMESPACES));
|
|
502
|
+
function normaliseValue(value) {
|
|
503
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return value;
|
|
504
|
+
const out = {};
|
|
505
|
+
for (const [key, field] of Object.entries(value)) {
|
|
506
|
+
const live = unwrapLive(field);
|
|
507
|
+
out[key] = live === void 0 ? field : live;
|
|
508
|
+
}
|
|
509
|
+
return out;
|
|
510
|
+
}
|
|
511
|
+
function snapshotOf(provider, descriptor) {
|
|
512
|
+
if (descriptor === void 0) return {
|
|
513
|
+
status: "unavailable",
|
|
514
|
+
writable: false,
|
|
515
|
+
value: void 0,
|
|
516
|
+
user: void 0,
|
|
517
|
+
base: void 0,
|
|
518
|
+
revision: void 0,
|
|
519
|
+
reason: "not-served"
|
|
520
|
+
};
|
|
521
|
+
return {
|
|
522
|
+
status: "ready",
|
|
523
|
+
writable: provider.writable,
|
|
524
|
+
value: normaliseValue(descriptor.value),
|
|
525
|
+
user: descriptor.user,
|
|
526
|
+
base: descriptor.base,
|
|
527
|
+
revision: descriptor.revision
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
function providerOf(getProvider) {
|
|
531
|
+
return getProvider();
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* @param getProvider - resolves the live platform settings provider per request.
|
|
535
|
+
* @returns exact routes for family settings describe/mutate.
|
|
536
|
+
*/
|
|
537
|
+
function makeSettingsRoutes(getProvider) {
|
|
538
|
+
return [{
|
|
539
|
+
path: HOST_ROUTES.settings.describe,
|
|
540
|
+
methods: ["GET"],
|
|
541
|
+
requestBody: "buffered",
|
|
542
|
+
fetch: async (request) => {
|
|
543
|
+
if (request.method !== "GET") return methodNotAllowed(["GET"]);
|
|
544
|
+
const provider = providerOf(getProvider);
|
|
545
|
+
if (provider === void 0) return json(503, {
|
|
546
|
+
ok: false,
|
|
547
|
+
error: "settings-service-unavailable"
|
|
548
|
+
});
|
|
549
|
+
try {
|
|
550
|
+
const namespaces = provider.describe({ redactSecrets: true }).filter((item) => FAMILY_NAMESPACES.has(item.ns)).map((item) => ({
|
|
551
|
+
ns: item.ns,
|
|
552
|
+
...snapshotOf(provider, item)
|
|
553
|
+
}));
|
|
554
|
+
return json(200, {
|
|
555
|
+
ok: true,
|
|
556
|
+
data: {
|
|
557
|
+
writable: provider.writable,
|
|
558
|
+
namespaces
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
} catch (error) {
|
|
562
|
+
return json(500, {
|
|
563
|
+
ok: false,
|
|
564
|
+
error: error instanceof Error ? error.message : String(error)
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}, {
|
|
569
|
+
path: HOST_ROUTES.settings.mutate,
|
|
570
|
+
methods: ["POST"],
|
|
571
|
+
requestBody: "buffered",
|
|
572
|
+
fetch: async (request) => {
|
|
573
|
+
if (request.method !== "POST") return methodNotAllowed(["POST"]);
|
|
574
|
+
const provider = providerOf(getProvider);
|
|
575
|
+
if (provider === void 0) return json(503, {
|
|
576
|
+
ok: false,
|
|
577
|
+
error: "settings-service-unavailable"
|
|
578
|
+
});
|
|
579
|
+
let body;
|
|
580
|
+
try {
|
|
581
|
+
body = await request.json();
|
|
582
|
+
} catch {
|
|
583
|
+
return json(400, {
|
|
584
|
+
ok: false,
|
|
585
|
+
error: "invalid-json"
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
if (typeof body !== "object" || body === null) return json(400, {
|
|
589
|
+
ok: false,
|
|
590
|
+
error: "invalid-body"
|
|
591
|
+
});
|
|
592
|
+
const { ns, ops, expectedRevision } = body;
|
|
593
|
+
if (typeof ns !== "string" || !FAMILY_NAMESPACES.has(ns)) return json(400, {
|
|
594
|
+
ok: false,
|
|
595
|
+
error: "namespace-not-allowed"
|
|
596
|
+
});
|
|
597
|
+
if (!Array.isArray(ops) || ops.length === 0) return json(400, {
|
|
598
|
+
ok: false,
|
|
599
|
+
error: "ops-required"
|
|
600
|
+
});
|
|
601
|
+
if (expectedRevision !== void 0 && typeof expectedRevision !== "number") return json(400, {
|
|
602
|
+
ok: false,
|
|
603
|
+
error: "invalid-revision"
|
|
604
|
+
});
|
|
605
|
+
try {
|
|
606
|
+
await provider.mutate(ns, ops, expectedRevision);
|
|
607
|
+
const descriptor = provider.describe({ redactSecrets: true }).find((item) => item.ns === ns);
|
|
608
|
+
return json(200, {
|
|
609
|
+
ok: true,
|
|
610
|
+
data: {
|
|
611
|
+
writable: provider.writable,
|
|
612
|
+
namespaces: [{
|
|
613
|
+
ns,
|
|
614
|
+
...snapshotOf(provider, descriptor)
|
|
615
|
+
}]
|
|
616
|
+
}
|
|
617
|
+
});
|
|
618
|
+
} catch (error) {
|
|
619
|
+
if (error?.code === "SETTINGS_CONFLICT") return json(409, {
|
|
620
|
+
ok: false,
|
|
621
|
+
error: "settings-conflict",
|
|
622
|
+
actual: error.actual,
|
|
623
|
+
expected: error.expected
|
|
624
|
+
});
|
|
625
|
+
return json(400, {
|
|
626
|
+
ok: false,
|
|
627
|
+
error: error instanceof Error ? error.message : String(error)
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}];
|
|
632
|
+
}
|
|
633
|
+
//#endregion
|
|
489
634
|
//#region lib/types/migration.js
|
|
490
635
|
/**
|
|
491
636
|
* G3 (caller half): find the legacy settings document and run the namespace migration.
|
|
@@ -2512,6 +2657,7 @@ async function readRunReport(io, record) {
|
|
|
2512
2657
|
}
|
|
2513
2658
|
}
|
|
2514
2659
|
function apply(ctx, rawConfig = {}) {
|
|
2660
|
+
registerOwnerSettings(ctx, "evolution-commands", Config);
|
|
2515
2661
|
const config = rawConfig;
|
|
2516
2662
|
assertSkillsRootAliasRetired(rawConfig);
|
|
2517
2663
|
const skillsRootValue = resolveRootConfig(rawConfig).root;
|
|
@@ -3529,7 +3675,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
3529
3675
|
ctx.inject(["settings"], () => {
|
|
3530
3676
|
runMigrationOnce();
|
|
3531
3677
|
});
|
|
3532
|
-
registerHostRoutes(ctx, () => makeDiagnosticsRoutes(() => assembleDoctorInputs(ctx, { runs: doctorRuns() })));
|
|
3678
|
+
registerHostRoutes(ctx, () => [...makeDiagnosticsRoutes(() => assembleDoctorInputs(ctx, { runs: doctorRuns() })), ...makeSettingsRoutes(() => ctx.get("settings"))]);
|
|
3533
3679
|
(async () => {
|
|
3534
3680
|
const loader = ctx.root.loader;
|
|
3535
3681
|
try {
|
|
@@ -16,7 +16,7 @@ export interface CommandFallbackHint {
|
|
|
16
16
|
readonly platformCli?: string;
|
|
17
17
|
}
|
|
18
18
|
/** The four Host surfaces (keyed exactly like the frozen `COMMAND_FALLBACK_SURFACES`). */
|
|
19
|
-
export type CommandFallbackSurface = 'approval' | 'skill-history' | 'skill-health' | 'merge' | 'diagnostics';
|
|
19
|
+
export type CommandFallbackSurface = 'approval' | 'skill-history' | 'skill-health' | 'merge' | 'diagnostics' | 'settings';
|
|
20
20
|
/**
|
|
21
21
|
* One entry per Host surface. The command column names the same service methods the routes call,
|
|
22
22
|
* so the answers (and refusal sentences) match the panel.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ConnectionFetchRouteLike } from '@lmzhen/dsh-evolution-core/http-routes';
|
|
2
|
+
interface SettingsDescriptorLike {
|
|
3
|
+
ns: string;
|
|
4
|
+
value?: unknown;
|
|
5
|
+
user?: Record<string, unknown>;
|
|
6
|
+
base?: unknown;
|
|
7
|
+
revision?: number;
|
|
8
|
+
applies?: 'live' | 'restart';
|
|
9
|
+
}
|
|
10
|
+
interface SettingsProviderLike {
|
|
11
|
+
readonly writable: boolean;
|
|
12
|
+
describe(options?: {
|
|
13
|
+
redactSecrets?: boolean;
|
|
14
|
+
}): SettingsDescriptorLike[];
|
|
15
|
+
mutate(ns: string, ops: readonly {
|
|
16
|
+
op: 'set' | 'unset';
|
|
17
|
+
path: readonly string[];
|
|
18
|
+
value?: unknown;
|
|
19
|
+
}[], expectedRevision?: number): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* @param getProvider - resolves the live platform settings provider per request.
|
|
23
|
+
* @returns exact routes for family settings describe/mutate.
|
|
24
|
+
*/
|
|
25
|
+
export declare function makeSettingsRoutes(getProvider: () => SettingsProviderLike | undefined): ConnectionFetchRouteLike[];
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=settings-route.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-commands",
|
|
3
3
|
"description": "Human commands for the evolution family (/evolution pending|curator|maintain|doctor) (community build)",
|
|
4
|
-
"version": "0.32.
|
|
4
|
+
"version": "0.32.6",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@deepseek-ai/schemastery": "^3.18.5",
|
|
30
|
-
"@lmzhen/dsh-evolution-approval": "^0.32.
|
|
31
|
-
"@lmzhen/dsh-evolution-core": "^0.32.
|
|
32
|
-
"@lmzhen/dsh-evolution-maintenance": "^0.32.
|
|
33
|
-
"@lmzhen/dsh-evolution-state-storage": "^0.32.
|
|
30
|
+
"@lmzhen/dsh-evolution-approval": "^0.32.6",
|
|
31
|
+
"@lmzhen/dsh-evolution-core": "^0.32.6",
|
|
32
|
+
"@lmzhen/dsh-evolution-maintenance": "^0.32.6",
|
|
33
|
+
"@lmzhen/dsh-evolution-state-storage": "^0.32.6"
|
|
34
34
|
},
|
|
35
35
|
"optionalDependencies": {
|
|
36
|
-
"@lmzhen/dsh-evolution-agent-preset": "^0.32.
|
|
36
|
+
"@lmzhen/dsh-evolution-agent-preset": "^0.32.6"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@deepseek-ai/cordis": "^4.0.5",
|