@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/README.md +27 -15
- package/dist/catalog-DWxIg3qw.mjs +131 -0
- package/dist/catalog-K5cESbqA.cjs +136 -0
- package/dist/catalog-remote-B7ZgYqun.cjs +28 -0
- package/dist/catalog-remote-KXJjDaN6.mjs +17 -0
- package/dist/client.cjs +1364 -16751
- package/dist/client.d.cts +149 -3
- package/dist/client.d.mts +149 -3
- package/dist/client.mjs +1612 -0
- package/dist/index.cjs +635 -0
- package/dist/index.d.mts +5 -3
- package/dist/index.mjs +73 -57
- package/dist/rows.cjs +85 -0
- package/dist/rows.mjs +40 -32
- package/dist/shared-sy45ixVR.cjs +16 -0
- package/dist/testing.cjs +6 -0
- package/dist/testing.d.mts +35 -0
- package/dist/testing.mjs +3 -0
- package/package.json +74 -50
- package/src/catalog-remote.ts +45 -0
- package/src/catalog.ts +75 -0
- package/src/client/BundleConfigPage.tsx +631 -0
- package/src/client/SessionModeSeat.tsx +21 -19
- package/src/client/bundle-config.ts +701 -0
- package/src/client/bundle-locales.ts +216 -0
- package/src/client/index.ts +178 -74
- package/src/client/llm-directory.ts +149 -0
- package/src/client/locales.ts +2 -2
- package/src/index.ts +28 -11
- package/src/mode-sources.ts +31 -14
- package/src/modes.ts +51 -25
- package/src/rows.ts +3 -2
- package/src/scope.ts +74 -65
- package/src/testing.ts +3 -0
- package/dist/index.d.cts +0 -144
- package/dist/rows.d.cts +0 -11
- package/src/client/SessionModeSeat.module.css +0 -74
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// 配置页要的"全局目录"(工具名 / 技能名)走一条**本包自己开的 Remote 面**:工具清单只在 host(`ctx.tools`),技能面
|
|
2
|
+
// 在客户端只有按会话的 `remote.skills.list({ sessionId })`——而这个配置页是全局设置面,没有会话。官方没有现成的 api,
|
|
3
|
+
// 所以这条面由本包自己注册:host 半提供服务([`./catalog.ts`](./catalog.ts) 的 `@Remote('list')`),client 半把下面这份
|
|
4
|
+
// 贡献 mount 上去([`./client/index.ts`](./client/index.ts))。
|
|
5
|
+
//
|
|
6
|
+
// 本文件只有类型与那份贡献常量(不带 host 依赖),两半都能 import。
|
|
7
|
+
|
|
8
|
+
import type { RemoteResult, TypertRemoteContribution } from "@deepseek-ai/dsh-typert-protocol";
|
|
9
|
+
|
|
10
|
+
// 线上命名空间与它的 Cordis 服务键:客户端 mount 之后按 `remote.<这个名字>` 取服务。
|
|
11
|
+
export const CATALOG_NS = "sessionModeCatalog";
|
|
12
|
+
|
|
13
|
+
// 部署里可用的工具名与技能名。
|
|
14
|
+
export interface SessionModeCatalogValue {
|
|
15
|
+
readonly tools: readonly string[];
|
|
16
|
+
readonly skills: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 这条 Remote 面的读侧。
|
|
20
|
+
export interface SessionModeCatalogRemote {
|
|
21
|
+
list: () => Promise<RemoteResult<SessionModeCatalogValue>>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
declare module "@deepseek-ai/dsh-typert-protocol" {
|
|
25
|
+
interface TypertRemoteNamespaceMap {
|
|
26
|
+
sessionModeCatalog: SessionModeCatalogRemote;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 客户端挂载用的贡献:`result` 用 `src-json`(结果就是普通 JSON,不走严格解码)。
|
|
31
|
+
export const SESSION_MODE_CATALOG_REMOTE: TypertRemoteContribution = {
|
|
32
|
+
package: "@morlay/dsh-session-mode",
|
|
33
|
+
descriptors: [
|
|
34
|
+
{
|
|
35
|
+
id: "@morlay/dsh-session-mode#sessionModeCatalog/list",
|
|
36
|
+
service: CATALOG_NS,
|
|
37
|
+
namespace: CATALOG_NS,
|
|
38
|
+
method: "list",
|
|
39
|
+
implementation: "remoteExportList",
|
|
40
|
+
invocation: { kind: "direct" },
|
|
41
|
+
parameters: [],
|
|
42
|
+
result: { mode: "src-json" },
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
};
|
package/src/catalog.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// 全局目录的 host 半:把部署里**当前可见**的工具名与技能名列出来,供配置页当候选(工具 / 技能名单字段)。
|
|
2
|
+
//
|
|
3
|
+
// 为什么要有这一层:这两份清单只有 host 侧读得到(工具面在 `ctx.tools`、技能面在 `ctx.skills`),而客户端只有按会话的
|
|
4
|
+
// `remote.skills.list`——bundle 配置页却是全局设置面。所以本包自己开一条 Remote 命名空间(贡献常量在
|
|
5
|
+
// [`./catalog-remote.ts`](./catalog-remote.ts),由 client 半自己 mount)。
|
|
6
|
+
//
|
|
7
|
+
// 清单的范围是"**部署里当前可见的那些**",不是某一份静态名单:
|
|
8
|
+
// - 工具按 agent 收口——实测本部署的工具注册都发生在 agent 层,全局视图(`schemas()` 不传 scope)是空的;
|
|
9
|
+
// - 技能按 agent 的收口与工作目录扫——工作区技能要 `cwd` 才看得到,而本行没有自己的工作区上下文。
|
|
10
|
+
// 所以两份都按当前活跃 agent 逐个读、去重合并;没有活跃 agent(刚启动、会话一个都没开)时只剩全局层那份。
|
|
11
|
+
//
|
|
12
|
+
// 不按 preset 分别取:preset 到工具名的映射没有任何服务暴露(工具名由各自的行注册进 agent 层,行清单里只有包名),
|
|
13
|
+
// 要"按 preset 分别取"就得为每个 preset 各起一个探针 agent;而候选在页面上是一维标签输入,分组也没有落点。
|
|
14
|
+
|
|
15
|
+
import type { Context } from "@deepseek-ai/cordis";
|
|
16
|
+
import type { Agent } from "@deepseek-ai/dsh-agent";
|
|
17
|
+
import type {} from "@deepseek-ai/dsh-skill";
|
|
18
|
+
import type {} from "@deepseek-ai/dsh-tools";
|
|
19
|
+
import { Remote, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
20
|
+
import { CATALOG_NS, type SessionModeCatalogValue } from "./catalog-remote.ts";
|
|
21
|
+
|
|
22
|
+
// 一个 agent 的工作目录:技能面按 `cwd` 才会扫工作区技能。
|
|
23
|
+
function cwdOf(agent: Agent): string | undefined {
|
|
24
|
+
const session = (agent as unknown as { session?: { header?: { cwd?: unknown } } }).session;
|
|
25
|
+
const cwd = session?.header?.cwd;
|
|
26
|
+
return typeof cwd === "string" ? cwd : undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 部署当前可见的工具与技能。
|
|
30
|
+
export class SessionModeCatalog extends TypertRemoteService {
|
|
31
|
+
/**
|
|
32
|
+
* @param ctx - owning context (the `session-mode` row).
|
|
33
|
+
*/
|
|
34
|
+
constructor(ctx: Context) {
|
|
35
|
+
super(ctx, CATALOG_NS);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* List the tool and skill names this deployment currently shows.
|
|
40
|
+
* @returns tool names from the tool registry, and skill names from the skill registry.
|
|
41
|
+
*/
|
|
42
|
+
@Remote("list")
|
|
43
|
+
async remoteExportList(): Promise<SessionModeCatalogValue> {
|
|
44
|
+
return { tools: this.toolNames(), skills: await this.skillNames() };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 工具名:全局层 + 每个活跃 agent 的可见面(同一名字只留一次)。
|
|
48
|
+
private toolNames(): readonly string[] {
|
|
49
|
+
const tools = this.ctx.get("tools");
|
|
50
|
+
if (tools === undefined) return [];
|
|
51
|
+
const names = new Set(tools.schemas().map((schema) => String(schema.name)));
|
|
52
|
+
for (const agent of this.agents()) {
|
|
53
|
+
for (const schema of tools.schemas(agent)) names.add(String(schema.name));
|
|
54
|
+
}
|
|
55
|
+
return [...names];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// 技能名:全局层 + 每个活跃 agent 按其收口与工作目录看到的那份。
|
|
59
|
+
private async skillNames(): Promise<readonly string[]> {
|
|
60
|
+
const skills = this.ctx.get("skills");
|
|
61
|
+
if (skills === undefined) return [];
|
|
62
|
+
const names = new Set((await skills.list()).map((row) => row.name));
|
|
63
|
+
for (const agent of this.agents()) {
|
|
64
|
+
for (const row of await skills.list({ scope: agent, cwd: cwdOf(agent) })) {
|
|
65
|
+
names.add(row.name);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return [...names];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 当前活跃的 agent:清单按它们逐个读。服务缺席(极简装配)时按没有处理。
|
|
72
|
+
private agents(): readonly Agent[] {
|
|
73
|
+
return this.ctx.get("agents")?.list() ?? [];
|
|
74
|
+
}
|
|
75
|
+
}
|