@morlay/dsh-session-mode 0.0.7 → 0.0.9

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/dist/index.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { t as SessionModeCatalog } from "./catalog-DWxIg3qw.mjs";
1
2
  import { n as SESSION_MODE_PATH, t as POLICY_NAMES } from "./shared-DX2Giyh3.mjs";
2
3
  import { Service } from "@deepseek-ai/cordis";
3
4
  import { ReasoningEffortId } from "@deepseek-ai/dsh-llm";
@@ -24,14 +25,15 @@ const modelSchema = z$1.object({
24
25
  en: "Model id."
25
26
  })),
26
27
  reasoningEffort: z$1.string().description(localized({
27
- zh: "思考档位;省略就跟服务商自己的默认。",
28
- en: "Reasoning effort; unset keeps the provider's own default."
28
+ zh: "思考档位;默认跟服务商自己的默认。",
29
+ en: "Reasoning effort; the default is the provider's own."
29
30
  }))
30
31
  });
31
32
  const modeSchema = z$1.object({
32
- preset: z$1.string().default("").description(localized({
33
- zh: "这个模式挂哪个 agent preset(它的 id,官方或本部署自建的):行清单由那份 preset 提供,几个模式可以共享同一个。留空就是不绑——选这个模式不换 preset,会话保持当前挂着的那份,模式自己的提示词、工具收口与开关照常生效。",
34
- en: "Which agent preset this mode rides on (its id, shipped or deployment-owned): that preset supplies the row list, and several modes may share it. Leave it empty to bind none — selecting the mode then keeps whatever preset the session already has, while the mode's persona, tool narrowing, and switches still apply."
33
+ preset: z$1.string().hidden(),
34
+ presetsOnly: z$1.array(z$1.string()).role("select", { source: "agent-presets" }).default([]).description(localized({
35
+ zh: "这个模式只允许挂哪些 agent preset(它们的 id,官方或本部署自建的):行清单由挂着的那份提供,几个模式可以共享同一份名单。留空表示**允许全部**——哪份 preset 都行,选这个模式也不动会话当前挂着的那份;有值时当前的已经在名单里就不动,否则换成名单里的第一个。模式自己的提示词、工具收口与开关照常生效。",
36
+ en: "Which agent presets this mode may ride on (their ids, shipped or deployment-owned): that preset supplies the row list, and several modes may share one list. Empty means **every preset is allowed** — selecting the mode then leaves the session's current preset alone; when set, the current one stays if it is listed, otherwise the session switches to the first entry. The mode's persona, tool narrowing, and switches apply either way."
35
37
  })),
36
38
  name: z$1.string().required().description(localized({
37
39
  zh: "模式名(事实文案;选择面归官方 roster)。",
@@ -46,27 +48,27 @@ const modeSchema = z$1.object({
46
48
  en: "Who may use this mode: `main` (selectable in sessions) or `subagent` (inherited by subagents)."
47
49
  })),
48
50
  persona: personaSchema.default({}),
49
- allowTools: z$1.array(z$1.string()).default([]).description(localized({
51
+ allowTools: z$1.array(z$1.string()).role("select", { source: "catalog-tools" }).default([]).description(localized({
50
52
  zh: "这个会话能用的工具;其余既不进目录,调用也被拒。**留空就是不设收窄**:用这个会话挂着的 preset 提供的全部工具。",
51
53
  en: "Tools this session may use; everything else leaves the catalog and calls are refused. Leave it empty to narrow nothing: the session then uses every tool its preset provides."
52
54
  })),
53
- denyTools: z$1.array(z$1.string()).default([]).description(localized({
55
+ denyTools: z$1.array(z$1.string()).role("select", { source: "catalog-tools" }).default([]).description(localized({
54
56
  zh: "这个模式不用的工具(黑名单):从 `allowTools` 定下的那份里减掉(`allowTools` 留空就是从全部里减)。留空 = 一条都不禁;同时命中两份名单时以这里为准。",
55
57
  en: "Tools this mode must not use (deny list): subtracted from whatever `allowTools` settled on (with an empty `allowTools`, from everything). Empty denies nothing; a name in both lists is denied."
56
58
  })),
57
- allowSkills: z$1.array(z$1.string()).default([]).description(localized({
59
+ allowSkills: z$1.array(z$1.string()).role("select", { source: "catalog-skills" }).default([]).description(localized({
58
60
  zh: "这个模式能用的技能;其余既不进技能目录,`skill` 工具加载它也被拒。**留空就是不设收窄**:技能注册表里有什么就用什么。",
59
61
  en: "Skills this mode may use; everything else leaves the skill catalog and loading it through the `skill` tool is refused. Leave it empty to narrow nothing: the session then sees every skill the registry carries."
60
62
  })),
61
- denySkills: z$1.array(z$1.string()).default([]).description(localized({
63
+ denySkills: z$1.array(z$1.string()).role("select", { source: "catalog-skills" }).default([]).description(localized({
62
64
  zh: "这个模式不用的技能(黑名单):从 `allowSkills` 定下的那份里减掉(`allowSkills` 留空就是从全部里减)。留空 = 一条都不禁;同时命中两份名单时以这里为准。",
63
65
  en: "Skills this mode must not use (deny list): subtracted from whatever `allowSkills` settled on (with an empty `allowSkills`, from everything). Empty denies nothing; a name in both lists is denied."
64
66
  })),
65
- allowPolicies: z$1.array(z$1.string()).default([]).description(localized({
67
+ allowPolicies: z$1.array(z$1.string()).role("select", { source: "policies" }).default([]).description(localized({
66
68
  zh: "上游 policy 规则的生效白名单(`fs/write-intent` / `fs/edit-intent`):留空 = 全部规则照旧生效;有值 = 只有列出的生效,其余的被绕过。",
67
69
  en: "Allow list of upstream policy rules that stay in force (`fs/write-intent` / `fs/edit-intent`): empty keeps every rule; when set, only the listed ones stay, and the others are bypassed."
68
70
  })),
69
- denyPolicies: z$1.array(z$1.string()).default([]).description(localized({
71
+ denyPolicies: z$1.array(z$1.string()).role("select", { source: "policies" }).default([]).description(localized({
70
72
  zh: "上游 policy 规则的黑名单:列出的规则禁用(它的裁决连拒绝一起丢掉,调用按没有这条规则继续)。留空 = 一条都不禁;同时命中两份名单时以这里为准。",
71
73
  en: "Deny list of upstream policy rules: the listed ones are disabled — their verdict (rejection included) is dropped and the call proceeds as if the rule were absent. Empty denies nothing; a name in both lists is denied."
72
74
  })),
@@ -75,16 +77,16 @@ const modeSchema = z$1.object({
75
77
  en: "Whether instruction-class injections apply (workspace instructions, guidance): `false` drops the official `agent-instructions` injection and turns off the channel's own demoted delivery."
76
78
  })),
77
79
  skills: z$1.boolean().description(localized({
78
- zh: "是否要技能目录(官方 `skill-catalog` 的注入)。**不写就按这个模式自己的工具名单推导**:`(allowTools 留空 ? 全部 : allowTools) − denyTools` 里含 `skill` 就要;写 `false` 就丢掉官方 `skill-catalog` 的注入(`skill` 工具的可见性仍归 `allowTools`)。",
79
- en: "Whether the skill catalog applies (the official `skill-catalog` injection). Unset derives it from this mode's own tool lists: it applies when `(empty allowTools ? every tool : allowTools) − denyTools` contains `skill`; `false` drops the official `skill-catalog` injection (`skill` tool visibility still belongs to `allowTools`)."
80
+ zh: "是否要技能目录(官方 `skill-catalog` 的注入)。**默认就按这个模式自己的工具名单推导**:`(allowTools 留空 ? 全部 : allowTools) − denyTools` 里含 `skill` 就要;写 `false` 就丢掉官方 `skill-catalog` 的注入(`skill` 工具的可见性仍归 `allowTools`)。",
81
+ en: "Whether the skill catalog applies (the official `skill-catalog` injection). The default derives it from this mode's own tool lists: it applies when `(empty allowTools ? every tool : allowTools) − denyTools` contains `skill`; `false` drops the official `skill-catalog` injection (`skill` tool visibility still belongs to `allowTools`)."
80
82
  })),
81
83
  runtimeContext: z$1.boolean().default(true).description(localized({
82
- zh: "是否要动态快照(文件沙箱策略、审批策略)。",
83
- en: "Whether the runtime snapshot applies (sandbox and approval policy)."
84
+ zh: "是否要动态快照(文件沙箱策略、审批策略)与时钟注入(`standard` 那类 preset 声明的 `time-context`)。",
85
+ en: "Whether the runtime snapshot (sandbox and approval policy) and the clock injection (`time-context`, declared by presets such as `standard`) apply."
84
86
  })),
85
87
  defaultModel: modelSchema.default(null).description(localized({
86
- zh: "这个模式的默认模型;省略就跟全局默认模型。只在会话还没有模型事实时接管。",
87
- en: "Default model for this mode; unset follows the global default. Applies only while a session has no model fact yet."
88
+ zh: "这个模式的默认模型;不设就跟全局默认模型。只在会话还没有模型事实时接管。",
89
+ en: "Default model for this mode; empty follows the global default. Applies only while a session has no model fact yet."
88
90
  }))
89
91
  });
90
92
  const Config = z$1.object({
@@ -110,6 +112,8 @@ function configProblem(config) {
110
112
  const unknownPolicies = Object.entries(config.modes).flatMap(([id, mode]) => [...mode.allowPolicies ?? [], ...mode.denyPolicies ?? []].filter((policy) => !POLICY_NAME_SET.has(policy)).map((policy) => `${id}: ${policy}`));
111
113
  if (unknownPolicies.length > 0) return `session-mode: mode(s) ${unknownPolicies.join(", ")} name unknown policies; the known ones are ${POLICY_NAMES.join(", ")}`;
112
114
  if (Object.keys(config.models ?? {}).length > 0) return "session-mode: `models` has moved into each mode's `defaultModel`; move the entries there and drop the top-level `models`";
115
+ const retiredPresets = Object.entries(config.modes).filter(([, mode]) => mode.preset !== void 0).map(([id]) => id);
116
+ if (retiredPresets.length > 0) return `session-mode: mode(s) ${retiredPresets.join(", ")} still declare \`preset\`; it has moved to \`presetsOnly\` (the presets that mode may ride on)`;
113
117
  const partial = Object.entries(config.modes).filter(([, mode]) => {
114
118
  const model = mode.defaultModel;
115
119
  if (model === void 0) return false;
@@ -223,40 +227,6 @@ var SessionScope = class {
223
227
  tools: result.tools.filter((tool) => denialOf(gate, tool.name) === void 0)
224
228
  };
225
229
  });
226
- ctx.on("agent/pre-step", async (payload, next) => {
227
- const decision = await next();
228
- if (decision.kind !== "enter") return decision;
229
- const applied = this.applied.get(payload.agent);
230
- if (applied === void 0) return decision;
231
- let changed = false;
232
- const kept = [];
233
- for (const message of decision.messages) {
234
- const kind = kindOf(message);
235
- if (kind === "agent-instructions") {
236
- if (applied.instructions) kept.push(message);
237
- else changed = true;
238
- continue;
239
- }
240
- if (kind === "skill-catalog") {
241
- if (!applied.skills) {
242
- changed = true;
243
- continue;
244
- }
245
- const narrowed = applied.skillGate === void 0 ? void 0 : narrowCatalog(message, applied.skillGate, (line) => this.ctx.logger.warn(`session-mode: ${line}`));
246
- if (narrowed === void 0) kept.push(message);
247
- else {
248
- changed = true;
249
- kept.push(narrowed);
250
- }
251
- continue;
252
- }
253
- kept.push(message);
254
- }
255
- return changed ? {
256
- ...decision,
257
- messages: kept
258
- } : decision;
259
- }, { prepend: true });
260
230
  }
261
231
  apply(agent, definition) {
262
232
  const previous = this.applied.get(agent);
@@ -265,6 +235,15 @@ var SessionScope = class {
265
235
  const skillGate = gateOfNames(definition.allowSkills, definition.denySkills);
266
236
  const dispose = agent.ctx.effect(() => {
267
237
  const stoppers = [];
238
+ stoppers.push(agent.ctx.on("agent/pre-step", async (_payload, next) => {
239
+ const decision = await next();
240
+ if (decision.kind !== "enter") return decision;
241
+ const kept = this.suppress(decision.messages, definition, skillGate);
242
+ return kept === void 0 ? decision : {
243
+ ...decision,
244
+ messages: kept
245
+ };
246
+ }, { prepend: true }));
268
247
  if (definition.runtimeContext === false) stoppers.push(agent.ctx.systemPrompt.suppressRuntimeContext());
269
248
  const fiber = agent.ctx.inject(["tools"], (scope) => {
270
249
  if (gate === void 0 && skillGate === void 0) return;
@@ -283,12 +262,41 @@ var SessionScope = class {
283
262
  this.channel()?.setInstructions(agent, definition.instructions);
284
263
  this.applied.set(agent, {
285
264
  gate,
286
- skillGate,
287
- instructions: definition.instructions,
288
- skills: definition.skills,
289
265
  dispose
290
266
  });
291
267
  }
268
+ suppress(messages, definition, skillGate) {
269
+ let changed = false;
270
+ const kept = [];
271
+ for (const message of messages) {
272
+ const kind = kindOf(message);
273
+ if (kind === "agent-instructions") {
274
+ if (definition.instructions) kept.push(message);
275
+ else changed = true;
276
+ continue;
277
+ }
278
+ if (kind === "skill-catalog") {
279
+ if (!definition.skills) {
280
+ changed = true;
281
+ continue;
282
+ }
283
+ const narrowed = skillGate === void 0 ? void 0 : narrowCatalog(message, skillGate, (line) => this.ctx.logger.warn(`session-mode: ${line}`));
284
+ if (narrowed === void 0) kept.push(message);
285
+ else {
286
+ changed = true;
287
+ kept.push(narrowed);
288
+ }
289
+ continue;
290
+ }
291
+ if (kind === "time-context") {
292
+ if (definition.runtimeContext) kept.push(message);
293
+ else changed = true;
294
+ continue;
295
+ }
296
+ kept.push(message);
297
+ }
298
+ return changed ? kept : void 0;
299
+ }
292
300
  channel() {
293
301
  try {
294
302
  return this.ctx.get("contextAssembler");
@@ -423,13 +431,20 @@ var SessionModes = class extends Service {
423
431
  if (this.ctx.sessionProjections.stateOf(session, "sessionModeEditable") === false) throw new Error("这个会话已经开始,模式不能再改;要换模式请新开一个会话。");
424
432
  const agent = this.ctx.agents.get(sessionId);
425
433
  const registry = this.presetRegistry();
426
- if (agent !== void 0 && registry !== void 0 && definition.preset.length > 0) {
427
- if (this.presetOfAgent(registry, agent) !== definition.preset) await registry.select(agent, definition.preset);
434
+ if (agent !== void 0 && registry !== void 0) {
435
+ const target = this.presetTarget(definition.presetsOnly, this.presetOfAgent(registry, agent));
436
+ if (target !== void 0) await registry.select(agent, target);
428
437
  }
429
438
  if (this.ctx.sessionProjections.stateOf(session, "sessionMode") !== mode) session.append("session-mode/selected", { sessionMode: mode });
430
439
  if (agent !== void 0) this.installFor(agent);
431
440
  return mode;
432
441
  }
442
+ presetTarget(allowed, current) {
443
+ if (allowed.length === 0) return void 0;
444
+ if (current !== void 0 && allowed.includes(current)) return void 0;
445
+ const target = allowed[0];
446
+ return target === current ? void 0 : target;
447
+ }
433
448
  presetOfAgent(registry, agent) {
434
449
  const read = registry.composedPreset;
435
450
  if (typeof read !== "function") return void 0;
@@ -474,7 +489,7 @@ var SessionModes = class extends Service {
474
489
  }
475
490
  modeForPreset(preset) {
476
491
  if (preset === void 0) return void 0;
477
- const owners = Object.keys(this.config.modes).filter((id) => this.config.modes[id]?.preset === preset);
492
+ const owners = Object.keys(this.config.modes).filter((id) => this.config.modes[id]?.presetsOnly.includes(preset));
478
493
  return owners.length === 1 ? owners[0] : void 0;
479
494
  }
480
495
  inheritedModeId(agent) {
@@ -525,6 +540,7 @@ var SessionModes = class extends Service {
525
540
  };
526
541
  function apply(ctx, config) {
527
542
  registerHttpRoutes(ctx, new SessionModes(ctx, config));
543
+ ctx.plugin(SessionModeCatalog);
528
544
  }
529
545
  function respondJson(response, status, body) {
530
546
  response.writeHead(status, { "content-type": "application/json; charset=utf-8" });
package/dist/rows.cjs ADDED
@@ -0,0 +1,85 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/mode-sources.ts
3
+ const CODING_PERSONA = { prefix: ["你是一个经验丰富的编程专家,YAGNI 是你的编程哲学,PDCA 是你的行为规范。", "全程用中文(专有名词除外),包括但不限于思考,回答,工具描述,subagent 提示词;思考不要陷入重复循环,一旦循环立即退出;思考聚焦需求理解与方案设计,不预演具体代码实现,正确性由验证环节确认。"].join("\n") };
4
+ const CHAT_PERSONA = { prefix: "你是一个助手。全程用中文(专有名词除外),包括但不限于思考,回答,工具描述;思考不要陷入重复循环,一旦循环立即退出。" };
5
+ const NOOP_MODE_ID = "noop";
6
+ const DEFAULT_MODE = "coding";
7
+ const MODE_SOURCES = [
8
+ {
9
+ id: "coding",
10
+ name: "编码模式",
11
+ description: "功能完整的编码 Agent:文件、Shell、检索、联网等工具常驻,其余用法说明按需加载。",
12
+ persona: CODING_PERSONA,
13
+ role: ["main", "subagent"],
14
+ denyTools: ["load_workspace_dependencies"],
15
+ denySkills: [
16
+ "office-docx",
17
+ "office-pptx",
18
+ "office-xlsx"
19
+ ],
20
+ denyPolicies: ["fs/edit-intent", "fs/write-intent"]
21
+ },
22
+ {
23
+ id: "chat",
24
+ name: "对话模式",
25
+ description: "只做对话:提问与联网(搜索、抓取)三件工具,不注入系统提示词、工作区指令与技能目录。",
26
+ persona: CHAT_PERSONA,
27
+ role: ["main"],
28
+ allowTools: [
29
+ "ask_user_question",
30
+ "web_search",
31
+ "web_fetch"
32
+ ],
33
+ instructions: false,
34
+ runtimeContext: false
35
+ },
36
+ {
37
+ id: NOOP_MODE_ID,
38
+ name: "原样模式",
39
+ description: "与上游一致:不加人格提示词、不收窄工具与技能、policy 规则全开、官方注入面照旧。",
40
+ role: ["main", "subagent"]
41
+ }
42
+ ];
43
+ //#endregion
44
+ //#region src/rows.ts
45
+ function list(values) {
46
+ return values === void 0 || values.length === 0 ? void 0 : [...values];
47
+ }
48
+ function modeConfig(source) {
49
+ const presetsOnly = list(source.presetsOnly);
50
+ const allowTools = list(source.allowTools);
51
+ const denyTools = list(source.denyTools);
52
+ const allowSkills = list(source.allowSkills);
53
+ const denySkills = list(source.denySkills);
54
+ const allowPolicies = list(source.allowPolicies);
55
+ const denyPolicies = list(source.denyPolicies);
56
+ return {
57
+ ...presetsOnly === void 0 ? {} : { presetsOnly },
58
+ name: source.name,
59
+ description: source.description,
60
+ ...source.role === void 0 ? {} : { role: [...source.role] },
61
+ ...source.persona === void 0 ? {} : { persona: { ...source.persona } },
62
+ ...allowTools === void 0 ? {} : { allowTools },
63
+ ...denyTools === void 0 ? {} : { denyTools },
64
+ ...allowSkills === void 0 ? {} : { allowSkills },
65
+ ...denySkills === void 0 ? {} : { denySkills },
66
+ ...allowPolicies === void 0 ? {} : { allowPolicies },
67
+ ...denyPolicies === void 0 ? {} : { denyPolicies },
68
+ ...source.instructions === void 0 ? {} : { instructions: source.instructions },
69
+ ...source.skills === void 0 ? {} : { skills: source.skills },
70
+ ...source.runtimeContext === void 0 ? {} : { runtimeContext: source.runtimeContext },
71
+ ...source.defaultModel === void 0 ? {} : { defaultModel: { ...source.defaultModel } }
72
+ };
73
+ }
74
+ function sessionModeRows() {
75
+ return [{ insert: [{
76
+ id: "session-mode",
77
+ name: "@morlay/dsh-session-mode",
78
+ config: {
79
+ default: DEFAULT_MODE,
80
+ modes: Object.fromEntries(MODE_SOURCES.map((source) => [source.id, modeConfig(source)]))
81
+ }
82
+ }] }];
83
+ }
84
+ //#endregion
85
+ exports.sessionModeRows = sessionModeRows;
package/dist/rows.mjs CHANGED
@@ -1,43 +1,51 @@
1
1
  //#region src/mode-sources.ts
2
- const CODING_PERSONA = {
3
- prefix: ["你是一个经验丰富的编程专家,YAGNI 是你的编程哲学,PDCA 是你的行为规范。", "全程用中文(专有名词除外),包括但不限于思考,回答,工具描述,subagent 提示词;思考不要陷入重复循环,一旦循环立即退出;思考聚焦需求理解与方案设计,不预演具体代码实现,正确性由验证环节确认。"].join("\n"),
4
- suffix: "你的工作目录在 `{{cwd}}`"
5
- };
2
+ const CODING_PERSONA = { prefix: ["你是一个经验丰富的编程专家,YAGNI 是你的编程哲学,PDCA 是你的行为规范。", "全程用中文(专有名词除外),包括但不限于思考,回答,工具描述,subagent 提示词;思考不要陷入重复循环,一旦循环立即退出;思考聚焦需求理解与方案设计,不预演具体代码实现,正确性由验证环节确认。"].join("\n") };
6
3
  const CHAT_PERSONA = { prefix: "你是一个助手。全程用中文(专有名词除外),包括但不限于思考,回答,工具描述;思考不要陷入重复循环,一旦循环立即退出。" };
4
+ const NOOP_MODE_ID = "noop";
7
5
  const DEFAULT_MODE = "coding";
8
- const MODE_SOURCES = [{
9
- id: "coding",
10
- name: "编码模式",
11
- description: "功能完整的编码 Agent:文件、Shell、检索、联网等工具常驻,其余用法说明按需加载。",
12
- persona: CODING_PERSONA,
13
- role: ["main", "subagent"],
14
- denyTools: ["load_workspace_dependencies"],
15
- denySkills: [
16
- "office-docx",
17
- "office-pptx",
18
- "office-xlsx"
19
- ],
20
- denyPolicies: ["fs/edit-intent"]
21
- }, {
22
- id: "chat",
23
- name: "对话模式",
24
- description: "只做对话:提问与联网(搜索、抓取)三件工具,不注入系统提示词、工作区指令与技能目录。",
25
- persona: CHAT_PERSONA,
26
- role: ["main"],
27
- allowTools: [
28
- "ask_user_question",
29
- "web_search",
30
- "web_fetch"
31
- ],
32
- instructions: false,
33
- runtimeContext: false
34
- }];
6
+ const MODE_SOURCES = [
7
+ {
8
+ id: "coding",
9
+ name: "编码模式",
10
+ description: "功能完整的编码 Agent:文件、Shell、检索、联网等工具常驻,其余用法说明按需加载。",
11
+ persona: CODING_PERSONA,
12
+ role: ["main", "subagent"],
13
+ denyTools: ["load_workspace_dependencies"],
14
+ denySkills: [
15
+ "office-docx",
16
+ "office-pptx",
17
+ "office-xlsx"
18
+ ],
19
+ denyPolicies: ["fs/edit-intent", "fs/write-intent"]
20
+ },
21
+ {
22
+ id: "chat",
23
+ name: "对话模式",
24
+ description: "只做对话:提问与联网(搜索、抓取)三件工具,不注入系统提示词、工作区指令与技能目录。",
25
+ persona: CHAT_PERSONA,
26
+ role: ["main"],
27
+ allowTools: [
28
+ "ask_user_question",
29
+ "web_search",
30
+ "web_fetch"
31
+ ],
32
+ instructions: false,
33
+ runtimeContext: false
34
+ },
35
+ {
36
+ id: NOOP_MODE_ID,
37
+ name: "原样模式",
38
+ description: "与上游一致:不加人格提示词、不收窄工具与技能、policy 规则全开、官方注入面照旧。",
39
+ role: ["main", "subagent"]
40
+ }
41
+ ];
35
42
  //#endregion
36
43
  //#region src/rows.ts
37
44
  function list(values) {
38
45
  return values === void 0 || values.length === 0 ? void 0 : [...values];
39
46
  }
40
47
  function modeConfig(source) {
48
+ const presetsOnly = list(source.presetsOnly);
41
49
  const allowTools = list(source.allowTools);
42
50
  const denyTools = list(source.denyTools);
43
51
  const allowSkills = list(source.allowSkills);
@@ -45,7 +53,7 @@ function modeConfig(source) {
45
53
  const allowPolicies = list(source.allowPolicies);
46
54
  const denyPolicies = list(source.denyPolicies);
47
55
  return {
48
- ...source.preset === void 0 ? {} : { preset: source.preset },
56
+ ...presetsOnly === void 0 ? {} : { presetsOnly },
49
57
  name: source.name,
50
58
  description: source.description,
51
59
  ...source.role === void 0 ? {} : { role: [...source.role] },
@@ -0,0 +1,16 @@
1
+ //#region src/shared.ts
2
+ const SESSION_MODE_PATH = "/session-mode";
3
+ const POLICY_NAMES = ["fs/write-intent", "fs/edit-intent"];
4
+ //#endregion
5
+ Object.defineProperty(exports, "POLICY_NAMES", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return POLICY_NAMES;
9
+ }
10
+ });
11
+ Object.defineProperty(exports, "SESSION_MODE_PATH", {
12
+ enumerable: true,
13
+ get: function() {
14
+ return SESSION_MODE_PATH;
15
+ }
16
+ });
@@ -0,0 +1,6 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_catalog_remote = require("./catalog-remote-B7ZgYqun.cjs");
3
+ const require_catalog = require("./catalog-K5cESbqA.cjs");
4
+ exports.CATALOG_NS = require_catalog_remote.CATALOG_NS;
5
+ exports.SESSION_MODE_CATALOG_REMOTE = require_catalog_remote.SESSION_MODE_CATALOG_REMOTE;
6
+ exports.SessionModeCatalog = require_catalog.SessionModeCatalog;
@@ -0,0 +1,35 @@
1
+ import { Context } from "@deepseek-ai/cordis";
2
+ import { RemoteResult, TypertRemoteContribution, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
3
+ //#region src/catalog-remote.d.ts
4
+ export declare const CATALOG_NS = "sessionModeCatalog";
5
+ interface SessionModeCatalogValue {
6
+ readonly tools: readonly string[];
7
+ readonly skills: readonly string[];
8
+ }
9
+ interface SessionModeCatalogRemote {
10
+ list: () => Promise<RemoteResult<SessionModeCatalogValue>>;
11
+ }
12
+ declare module "@deepseek-ai/dsh-typert-protocol" {
13
+ interface TypertRemoteNamespaceMap {
14
+ sessionModeCatalog: SessionModeCatalogRemote;
15
+ }
16
+ }
17
+ export declare const SESSION_MODE_CATALOG_REMOTE: TypertRemoteContribution;
18
+ //#endregion
19
+ //#region src/catalog.d.ts
20
+ export declare class SessionModeCatalog extends TypertRemoteService {
21
+ /**
22
+ * @param ctx - owning context (the `session-mode` row).
23
+ */
24
+ constructor(ctx: Context);
25
+ /**
26
+ * List the tool and skill names this deployment currently shows.
27
+ * @returns tool names from the tool registry, and skill names from the skill registry.
28
+ */
29
+ remoteExportList(): Promise<SessionModeCatalogValue>;
30
+ private toolNames;
31
+ private skillNames;
32
+ private agents;
33
+ }
34
+ //#endregion
35
+ export {};
@@ -0,0 +1,3 @@
1
+ import { n as SESSION_MODE_CATALOG_REMOTE, t as CATALOG_NS } from "./catalog-remote-KXJjDaN6.mjs";
2
+ import { t as SessionModeCatalog } from "./catalog-DWxIg3qw.mjs";
3
+ export { CATALOG_NS, SESSION_MODE_CATALOG_REMOTE, SessionModeCatalog };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morlay/dsh-session-mode",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "Session modes for dsh: coding / chat as data — a mode is a persona plus its tool lists, its upstream policy lists, its instruction / skill-catalog / runtime-context switches and an optional default model. The host applies the current mode to each session, and the chip in the composer sits beside the official agent-preset entry, which stays.",
5
5
  "keywords": [
6
6
  "dsh",
@@ -22,76 +22,100 @@
22
22
  ],
23
23
  "type": "module",
24
24
  "exports": {
25
- ".": "./dist/index.mjs",
26
- "./rows": "./dist/rows.mjs",
25
+ ".": {
26
+ "types": "./dist/index.d.mts",
27
+ "default": "./dist/index.mjs"
28
+ },
29
+ "./rows": {
30
+ "types": "./dist/rows.d.mts",
31
+ "default": "./dist/rows.mjs"
32
+ },
33
+ "./testing": {
34
+ "types": "./dist/testing.d.mts",
35
+ "default": "./dist/testing.mjs"
36
+ },
27
37
  "./package.json": "./package.json",
28
38
  "./client": {
29
- "types": "./dist/client.d.cts",
30
- "default": "./dist/client.cjs"
39
+ "types": "./dist/client.d.mts",
40
+ "import": "./dist/client.mjs",
41
+ "default": "./dist/client.mjs"
31
42
  },
32
43
  "./locale/*.json": "./locale/*.json"
33
44
  },
34
45
  "dependencies": {
35
- "@deepseek-ai/schemastery": "^3.18.4",
36
- "zod": "4.6.5"
46
+ "zod": "4.4.3"
37
47
  },
38
48
  "devDependencies": {
39
- "@deepseek-ai/cordis": "4.0.4",
40
- "@deepseek-ai/cordis-plugin-group": "1.0.4",
41
- "@deepseek-ai/cordis-plugin-include": "1.0.9",
42
- "@deepseek-ai/cordis-plugin-loader": "1.0.5",
43
- "@deepseek-ai/cosmokit": "1.8.5",
44
- "@deepseek-ai/dsh-agent": "0.2.0-rc.2",
45
- "@deepseek-ai/dsh-agent-loop-testkit": "0.2.0-rc.2",
46
- "@deepseek-ai/dsh-agent-preset-registry": "0.2.0-rc.2",
47
- "@deepseek-ai/dsh-api-remotes": "0.2.0-rc.2",
48
- "@deepseek-ai/dsh-api-session-controller": "0.2.0-rc.2",
49
- "@deepseek-ai/dsh-client-locale": "0.2.0-rc.2",
50
- "@deepseek-ai/dsh-client-ui-conversation": "0.2.0-rc.2",
51
- "@deepseek-ai/dsh-client-ui-primitives": "0.2.0-rc.2",
52
- "@deepseek-ai/dsh-client-ui-renderer": "0.2.0-rc.2",
53
- "@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.2",
54
- "@deepseek-ai/dsh-fs": "0.2.0-rc.2",
55
- "@deepseek-ai/dsh-fs-local": "0.2.0-rc.2",
56
- "@deepseek-ai/dsh-fs-observation-policy": "0.2.0-rc.2",
57
- "@deepseek-ai/dsh-llm": "0.2.0-rc.2",
58
- "@deepseek-ai/dsh-session": "0.2.0-rc.2",
59
- "@deepseek-ai/dsh-session-projection": "0.2.0-rc.2",
60
- "@deepseek-ai/dsh-skill": "0.2.0-rc.2",
61
- "@deepseek-ai/dsh-system-prompt": "0.2.0-rc.2",
62
- "@deepseek-ai/dsh-tool-skill": "0.2.0-rc.2",
63
- "@deepseek-ai/dsh-tools": "0.2.0-rc.2",
64
- "@morlay/dsh-client-ui-primitives": "0.0.7",
65
- "@morlay/dsh-context-assembler": "0.0.5",
49
+ "@deepseek-ai/cordis": "4.0.5-alpha.2",
50
+ "@deepseek-ai/cordis-plugin-group": "1.0.5-alpha.2",
51
+ "@deepseek-ai/cordis-plugin-include": "1.0.10-alpha.2",
52
+ "@deepseek-ai/cordis-plugin-loader": "1.0.6-alpha.2",
53
+ "@deepseek-ai/cosmokit": "1.8.6-alpha.2",
54
+ "@deepseek-ai/dsh-agent": "0.2.1-alpha.5",
55
+ "@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-alpha.5",
56
+ "@deepseek-ai/dsh-agent-preset-registry": "0.2.1-alpha.5",
57
+ "@deepseek-ai/dsh-api-session-controller": "0.2.1-alpha.5",
58
+ "@deepseek-ai/dsh-client-locale": "0.2.1-alpha.5",
59
+ "@deepseek-ai/dsh-client-store": "0.2.1-alpha.5",
60
+ "@deepseek-ai/dsh-client-ui-conversation": "0.2.1-alpha.5",
61
+ "@deepseek-ai/dsh-client-ui-plugin-manager": "0.2.1-alpha.5",
62
+ "@deepseek-ai/dsh-client-ui-primitives": "0.2.1-alpha.5",
63
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.1-alpha.5",
64
+ "@deepseek-ai/dsh-client-ui-settings": "0.2.1-alpha.5",
65
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.1-alpha.5",
66
+ "@deepseek-ai/dsh-fs": "0.2.1-alpha.5",
67
+ "@deepseek-ai/dsh-fs-local": "0.2.1-alpha.5",
68
+ "@deepseek-ai/dsh-fs-observation-policy": "0.2.1-alpha.5",
69
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.5",
70
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.5",
71
+ "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.5",
72
+ "@deepseek-ai/dsh-settings": "0.2.1-alpha.5",
73
+ "@deepseek-ai/dsh-skill": "0.2.1-alpha.5",
74
+ "@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.5",
75
+ "@deepseek-ai/dsh-tools": "0.2.1-alpha.5",
76
+ "@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.5",
77
+ "@deepseek-ai/dsh-working-directory": "0.2.1-alpha.5",
66
78
  "@testing-library/react": "^16.3.0",
67
79
  "@types/js-yaml": "^4.0.9",
68
80
  "@types/react": "~18.3.1",
69
81
  "js-yaml": "^4.1.0",
70
- "react": "^18.2.0",
71
82
  "react-dom": "^18.2.0"
72
83
  },
73
84
  "peerDependencies": {
74
- "@deepseek-ai/cordis": "^4.0.4",
75
- "@deepseek-ai/cosmokit": "^1.8.5",
76
- "@deepseek-ai/dsh-agent": "^0.2.0-rc.2",
77
- "@deepseek-ai/dsh-agent-preset-registry": "^0.2.0-rc.2",
78
- "@deepseek-ai/dsh-api-session-controller": "^0.2.0-rc.2",
79
- "@deepseek-ai/dsh-client-locale": "^0.2.0-rc.2",
80
- "@deepseek-ai/dsh-client-ui-conversation": "^0.2.0-rc.2",
81
- "@deepseek-ai/dsh-client-ui-primitives": "^0.2.0-rc.2",
82
- "@deepseek-ai/dsh-client-ui-slots": "^0.2.0-rc.2",
83
- "@deepseek-ai/dsh-fs": "^0.2.0-rc.2",
84
- "@deepseek-ai/dsh-llm": "^0.2.0-rc.2",
85
- "@deepseek-ai/dsh-session": "^0.2.0-rc.2",
86
- "@deepseek-ai/dsh-session-projection": "^0.2.0-rc.2",
87
- "@deepseek-ai/dsh-system-prompt": "^0.2.0-rc.2",
88
- "@deepseek-ai/schemastery": "^3.18.4"
85
+ "@deepseek-ai/cordis": "^4.0.5-alpha.2",
86
+ "@deepseek-ai/cosmokit": "^1.8.6-alpha.2",
87
+ "@deepseek-ai/dsh-agent": "^0.2.1-alpha.5",
88
+ "@deepseek-ai/dsh-agent-preset-registry": "^0.2.1-alpha.5",
89
+ "@deepseek-ai/dsh-api-remotes": "0.2.1-alpha.5",
90
+ "@deepseek-ai/dsh-api-session-controller": "^0.2.1-alpha.5",
91
+ "@deepseek-ai/dsh-client-locale": "^0.2.1-alpha.5",
92
+ "@deepseek-ai/dsh-client-store": "^0.2.1-alpha.5",
93
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.2.1-alpha.5",
94
+ "@deepseek-ai/dsh-client-ui-plugin-manager": "^0.2.1-alpha.5",
95
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.2.1-alpha.5",
96
+ "@deepseek-ai/dsh-client-ui-settings": "^0.2.1-alpha.5",
97
+ "@deepseek-ai/dsh-client-ui-slots": "^0.2.1-alpha.5",
98
+ "@deepseek-ai/dsh-fs": "^0.2.1-alpha.5",
99
+ "@deepseek-ai/dsh-llm": "^0.2.1-alpha.5",
100
+ "@deepseek-ai/dsh-session": "^0.2.1-alpha.5",
101
+ "@deepseek-ai/dsh-session-projection": "^0.2.1-alpha.5",
102
+ "@deepseek-ai/dsh-skill": "^0.2.1-alpha.5",
103
+ "@deepseek-ai/dsh-system-prompt": "^0.2.1-alpha.5",
104
+ "@deepseek-ai/dsh-tool-skill": "0.2.1-alpha.5",
105
+ "@deepseek-ai/dsh-tools": "^0.2.1-alpha.5",
106
+ "@deepseek-ai/dsh-typert-protocol": "^0.2.1-alpha.5",
107
+ "@deepseek-ai/schemastery": "^3.18.5-alpha.2",
108
+ "@morlay/dsh-client-ui-primitives": "0.0.9",
109
+ "@morlay/dsh-context-assembler": "0.0.7",
110
+ "react": "^18.2.0"
89
111
  },
90
112
  "dsh": {
91
113
  "client": {
92
114
  "platform": "web",
93
115
  "inject": [
94
116
  "@deepseek-ai/dsh-client-locale",
117
+ "@deepseek-ai/dsh-client-ui-plugin-manager",
118
+ "@deepseek-ai/dsh-client-ui-settings",
95
119
  "@deepseek-ai/dsh-client-ui-slots"
96
120
  ]
97
121
  }