@t4r71/dsh-dual-axis-ui 0.1.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.
@@ -0,0 +1,112 @@
1
+ /**
2
+ * 双轴配置页的纯函数层:把设置节里的一条轴收成可编辑的草稿、把草稿收成一条
3
+ * 轴值、把一条轴渲染成一句话。这里不碰 React、不碰 DOM,也不碰宿主 —— 界面
4
+ * 半边每次挂载与每次保存都走这几个函数,因此"页面上能改的形状"与"宿主接受
5
+ * 的形状"只有这一份定义。
6
+ *
7
+ * @module @t4r71/dsh-dual-axis-ui/client/axes
8
+ */
9
+ /** 四种轴取值,与宿主 `dsh-sandbox` 的 `AxisScopeKind` 同一套字面量。 */
10
+ export type AxisKind = 'deny' | 'workspace' | 'all' | 'custom';
11
+ /** `custom` 可叠加的三个底座。 */
12
+ export type AxisBase = 'deny' | 'workspace' | 'all';
13
+ /** 一条轴值;`custom` 时带底座与两个路径列表。 */
14
+ export type AxisValue = {
15
+ kind: Exclude<AxisKind, 'custom'>;
16
+ } | {
17
+ kind: 'custom';
18
+ base: AxisBase;
19
+ allow: readonly string[];
20
+ deny: readonly string[];
21
+ };
22
+ /** 界面上的四条轴取值,顺序即下拉顺序:从最窄到最宽,custom 排在最后。 */
23
+ export declare const AXIS_KINDS: readonly AxisKind[];
24
+ /** 界面上的三个底座,顺序即下拉顺序。 */
25
+ export declare const AXIS_BASES: readonly AxisBase[];
26
+ /**
27
+ * 一条轴在界面上的草稿:四条取值都收在同一种形状里,切到 custom 时已经打好的
28
+ * 路径不会因为来回切换取值而丢失(切回非 custom 时它们只是不再参与保存)。
29
+ */
30
+ export interface AxisDraft {
31
+ /** 选中的轴取值。 */
32
+ kind: AxisKind;
33
+ /** custom 的底座;非 custom 时保留上一次的选择。 */
34
+ base: AxisBase;
35
+ /** 额外允许的绝对路径,每行一条。 */
36
+ allow: string;
37
+ /** 排除的绝对路径,每行一条;与底座取并后再减去它们。 */
38
+ deny: string;
39
+ /** 一个默认值或一份已保存的值读取失败时的说明;空串表示这份草稿可用。 */
40
+ problem: string;
41
+ }
42
+ /**
43
+ * 一条绝对路径写法(POSIX 或 Windows)。与宿主半边的同名校验同一条规则:相对
44
+ * 路径只能相对宿主进程的 cwd 解析,不可能是写配置的人想说的位置。
45
+ * @param value - 待检查的路径写法。
46
+ * @returns 该写法是否为绝对路径。
47
+ */
48
+ export declare function isAbsolutePath(value: string): boolean;
49
+ /**
50
+ * 把一个未信任的值收成一条轴值。
51
+ * @param value - 设置节里的取值,或 `undefined`。
52
+ * @returns 一条轴值;形状不对时返回 undefined,由调用方决定用什么兜底。
53
+ */
54
+ export declare function axisValueOf(value: unknown): AxisValue | undefined;
55
+ /**
56
+ * 把一条轴值收成界面草稿。
57
+ * @param value - 设置节里的取值。
58
+ * @param fallback - 取值缺失或读不懂时使用的兜底轴(组合层声明的默认值)。
59
+ * @returns 一份可编辑的草稿。
60
+ */
61
+ export declare function draftOf(value: unknown, fallback: AxisValue): AxisDraft;
62
+ /**
63
+ * 把一条已经收好的轴值转成草稿。
64
+ * @param axis - 一条轴值。
65
+ * @param problem - 直接带上的说明;不传即没有内容可说明。
66
+ * @returns 一份可编辑的草稿。
67
+ */
68
+ export declare function draftOfAxis(axis: AxisValue, problem?: string): AxisDraft;
69
+ /**
70
+ * 把草稿收成一条可以写回设置的轴值。非 custom 的草稿只带取值本身 —— 界面上
71
+ * 留着的历史路径不会被写进另一条取值里,否则切一次取值就等于做了一次没人要求
72
+ * 的授权。
73
+ * @param draft - 界面上的草稿。
74
+ * @returns 一条轴值,或一条说明这份草稿为什么还不能保存的话。
75
+ */
76
+ export declare function scopeOf(draft: AxisDraft): {
77
+ ok: true;
78
+ value: AxisValue;
79
+ } | {
80
+ ok: false;
81
+ problem: string;
82
+ };
83
+ /**
84
+ * 把一个多行文本框读成路径列表:忽略空行与首尾空白。
85
+ * @param text - 文本框里的原文。
86
+ * @returns 其中每一行作为一条路径。
87
+ */
88
+ export declare function pathLines(text: string): string[];
89
+ /**
90
+ * 两条轴是否描述同一个边界。逐成员比较:custom 的两个路径列表连顺序都是它取值
91
+ * 的一部分,而每次重解析都会新建轴对象。
92
+ * @param left - 一条轴。
93
+ * @param right - 另一条轴。
94
+ * @returns 两者是否描述同一条轴。
95
+ */
96
+ export declare function sameAxis(left: AxisValue, right: AxisValue): boolean;
97
+ /** 一条轴的一句话说明所用的文案表:由调用方按当前语言传入。 */
98
+ export interface AxisText {
99
+ /** 一条取值的中文/英文名字。 */
100
+ kind: (kind: AxisKind) => string;
101
+ /** 底座的名字。 */
102
+ base: (base: AxisBase) => string;
103
+ /** 模板:`{paths}` 会被替换成路径列表。 */
104
+ custom: (base: string, paths: string) => string;
105
+ }
106
+ /**
107
+ * 把一条轴渲染成一句话,供配置页的摘要行与草稿预览使用。
108
+ * @param axis - 一条轴值。
109
+ * @param text - 当前语言的文案表。
110
+ * @returns 一句话说明。
111
+ */
112
+ export declare function describeAxis(axis: AxisValue, text: AxisText): string;
@@ -0,0 +1,150 @@
1
+ /**
2
+ * 双轴配置页的规则组纯函数层:把设置节里的 `groups` / `defaultGroups` 收成可编辑
3
+ * 草稿、把草稿收成宿主解析器接受的组库。这里不碰 React、不碰 DOM、也不碰宿主 ——
4
+ * 界面每次挂载与每次保存都走这几个函数,因此「页面上能编的形状」与「宿主
5
+ * `parseLibrary` 接受的形状」只有这一份定义。
6
+ *
7
+ * 组体只在设置页这一份:会话按 id 引用它,判定时现取(规格 §「为什么对话里绝不能
8
+ * 存组体」)。所以这里的编辑结果写回的是**定义**,不是任何一条会话。
9
+ *
10
+ * @module @t4r71/dsh-dual-axis-ui/client/row/groups
11
+ */
12
+ /** 一个组在一条轴上的规则草稿:两个多行文本,每行一条绝对路径。 */
13
+ export interface GroupAxisDraft {
14
+ /** 额外放行的绝对路径,每行一条。 */
15
+ readonly allow: string;
16
+ /** 排除的绝对路径,每行一条;与放行同时命中时排除优先。 */
17
+ readonly deny: string;
18
+ }
19
+ /**
20
+ * 一个规则组在界面上的草稿。
21
+ *
22
+ * `default` 是 {@link defaultGroups} 的界面形式:勾上的组会被新建的对话默认加载。
23
+ * 它跟着草稿行走,所以改一个组的 id 不会把「默认加载」这件事丢在旧 id 上。
24
+ */
25
+ export interface RuleGroupDraft {
26
+ /** 稳定标识:会话按它引用这个组。 */
27
+ readonly id: string;
28
+ /** 人读的名字;可以为空,宿主会用 id 顶上。 */
29
+ readonly name: string;
30
+ /** 这个组给读轴的规则。 */
31
+ readonly read: GroupAxisDraft;
32
+ /** 这个组给写轴的规则。 */
33
+ readonly write: GroupAxisDraft;
34
+ /** 新对话是否默认加载这个组。 */
35
+ readonly default: boolean;
36
+ }
37
+ /** 一条轴在设置文档里的规则取值;两侧都空即这一侧整个缺席。 */
38
+ export interface RuleGroupAxisValue {
39
+ /** 该轴额外放行的绝对路径。 */
40
+ readonly allow: readonly string[];
41
+ /** 该轴排除的绝对路径。 */
42
+ readonly deny: readonly string[];
43
+ }
44
+ /** 写回设置文档的规则组取值,与宿主 `RuleGroup` 同一形状。 */
45
+ export interface RuleGroupValue {
46
+ /** 稳定标识。 */
47
+ readonly id: string;
48
+ /** 人读的名字。 */
49
+ readonly name: string;
50
+ /** 读侧规则;两侧都不填时为 undefined(这个组不覆盖读轴)。 */
51
+ readonly read?: RuleGroupAxisValue;
52
+ /** 写侧规则;两侧都不填时为 undefined(这个组不覆盖写轴)。 */
53
+ readonly write?: RuleGroupAxisValue;
54
+ }
55
+ /** 一条规则在界面上读不懂时用的说明键。 */
56
+ export type GroupProblemKey = 'idEmpty' | 'idDuplicate' | 'notAbsolute';
57
+ /**
58
+ * 生成一个说明键对应的文案;由调用方按当前语言取用(界面文案不在这里出现)。
59
+ * @param key - 说明键。
60
+ * @param params - 填进文案里的具名参数。
61
+ * @returns 一句话说明。
62
+ */
63
+ export type GroupProblemText = (key: GroupProblemKey, params: Record<string, string>) => string;
64
+ /**
65
+ * 把设置文档里的组库与默认加载清单读成界面草稿。
66
+ *
67
+ * 读取是**宽容**的:这个函数的产物要能渲染出来让人修,所以读不懂的成员按空值处理,
68
+ * 而不是抛出去让整页打不开。挡住保存的是 {@link groupLibraryOf},那里才拒绝坏取值。
69
+ * @param groups - 设置文档里的 `groups`,未信任。
70
+ * @param defaultGroups - 设置文档里的 `defaultGroups`,未信任。
71
+ * @returns 每个组一份草稿,顺序与文档一致。
72
+ */
73
+ export declare function groupDraftsOf(groups: unknown, defaultGroups: unknown): RuleGroupDraft[];
74
+ /**
75
+ * 把一份组草稿收成可以写回设置的组库。
76
+ *
77
+ * 校验与宿主 `parseLibrary` / `groupAt` 逐条对齐:id 非空且唯一,每条路径必须是
78
+ * 绝对路径。宿主在库读不懂时会让**每一次判定**都响亮失败,所以这里必须在写入之前
79
+ * 就挡住坏取值,而不是把一份宿主读不懂的库保存下去。
80
+ * @param drafts - 界面上的草稿。
81
+ * @param problemOf - 把说明键转成当前语言文案的回调。
82
+ * @returns 组库取值,或一句说明这份草稿为什么还不能保存的话。
83
+ */
84
+ export declare function groupLibraryOf(drafts: readonly RuleGroupDraft[], problemOf: GroupProblemText): {
85
+ ok: true;
86
+ value: RuleGroupValue[];
87
+ } | {
88
+ ok: false;
89
+ problem: string;
90
+ };
91
+ /**
92
+ * 草稿里被勾上「新对话默认加载」的组 id。
93
+ *
94
+ * 只在 {@link groupLibraryOf} 通过之后取用:那时 id 非空且唯一,所以这份清单本身
95
+ * 也是合法的 `defaultGroups`。
96
+ * @param drafts - 界面上的草稿。
97
+ * @returns 勾选顺序即文档顺序的 id 清单。
98
+ */
99
+ export declare function defaultGroupIdsOf(drafts: readonly RuleGroupDraft[]): string[];
100
+ /**
101
+ * 给新加的一个组起一个还没有被占用的 id。
102
+ *
103
+ * 默认名 `g1`、`g2`…:id 是会话引用的东西,先给出一个能用的,再由人改。
104
+ * @param drafts - 当前已有的草稿。
105
+ * @returns 一个没有被占用的 id。
106
+ */
107
+ export declare function nextGroupId(drafts: readonly RuleGroupDraft[]): string;
108
+ /**
109
+ * 一个空组的草稿:id 未被占用、名字留空(保存时用 id 顶上)、两侧规则都空、
110
+ * 默认不加载。空组是合法的 —— 组的内容随时可改,先建出来再填是正常用法。
111
+ * @param drafts - 当前已有的草稿。
112
+ * @returns 一份可以加进列表的草稿。
113
+ */
114
+ export declare function emptyGroupDraft(drafts: readonly RuleGroupDraft[]): RuleGroupDraft;
115
+ /**
116
+ * 两份组库是否描述同一份定义。
117
+ *
118
+ * 与轴的 `sameAxis` 同一个用法:保存时比对「现在的草稿」与「文档里已生效的值」,
119
+ * 相同就不发写入。逐成员比较而不是引用比较,因为每次重解析都会新建对象。
120
+ * @param left - 一份组库取值。
121
+ * @param right - 另一份组库取值。
122
+ * @returns 两者是否描述同一份组库。
123
+ */
124
+ export declare function sameGroupLibrary(left: readonly RuleGroupValue[], right: readonly RuleGroupValue[]): boolean;
125
+ /**
126
+ * 把一份已经收好的组库摊成设置文档接受的 JSON。
127
+ *
128
+ * 取值里的列表是 `readonly string[]`,而文档取值是可变的 JSON 数组:传只读数组会被
129
+ * 线上格式挡住,所以写入前摊平一层(与轴的 `jsonAxis` 同因)。
130
+ * @param library - 一份校验过的组库。
131
+ * @returns 同一份取值的可变副本。
132
+ */
133
+ export declare function jsonGroupLibrary(library: readonly RuleGroupValue[]): Array<{
134
+ id: string;
135
+ name: string;
136
+ read?: {
137
+ allow: string[];
138
+ deny: string[];
139
+ };
140
+ write?: {
141
+ allow: string[];
142
+ deny: string[];
143
+ };
144
+ }>;
145
+ /**
146
+ * 默认加载清单的 JSON 形式(可变数组)。
147
+ * @param ids - 被勾选的组 id。
148
+ * @returns 同一份清单的可变副本。
149
+ */
150
+ export declare function jsonDefaultGroupIds(ids: readonly string[]): string[];
@@ -0,0 +1,104 @@
1
+ /**
2
+ * 双轴访问模式组合包的浏览器半边:General 设置页上这一行自己的配置。
3
+ * 宿主半边在 `@t4r71/dsh-dual-axis`(注册设置节、新会话钉轴),这一半只负责改那份设置。
4
+ *
5
+ * 页面只表达一件事 —— 新会话从哪两条轴开始:读轴与写轴,每条都能选
6
+ * deny / workspace / all / custom,选 custom 时再给底座与两个绝对路径列表
7
+ * (放行、排除,排除优先),再加上组库与「新对话默认加载哪些组」。取值只写进
8
+ * 宿主注册的 `dual-axis` 设置节(节名就是这一行在条目树里的行 id),页面上不另存一份。
9
+ *
10
+ * 0.1.7 起,设置页的表单由**页面下发**:这一行不再自持 `ctx.settingsScope`
11
+ * (该服务已整块删除),而是消费 `props.form` —— owner 渲染时算好的
12
+ * `{ state: ConfigFormSnapshot, mutate }`。state 里的 `value` / `user` / `writable`
13
+ * 与 0.1.6 的 scope 快照同义,因此草稿层原样保留;写入从逐字段的
14
+ * `set` / `unset` 改成一次 `mutate`,两条轴共用同一个 revision fence。
15
+ *
16
+ * @module @t4r71/dsh-dual-axis-ui/client
17
+ */
18
+ import { type ReactNode } from 'react';
19
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
20
+ import type { ConfigForm, ConfigFormSnapshot } from '@deepseek-ai/dsh-client-ui-settings/client';
21
+ import type { PluginConfigViewProps } from '@deepseek-ai/dsh-client-ui-plugin-manager/client';
22
+ import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
23
+ import { type AxisValue } from './axes.ts';
24
+ import { DUAL_AXIS_LOCALE_NS, type DualAxisLocaleKey } from './locales.ts';
25
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
26
+ interface LocaleNamespaceMap {
27
+ /** 本包配置页自己的词典命名空间。 */
28
+ 'sandbox-axis': DualAxisLocaleKey;
29
+ }
30
+ }
31
+ /** 设置节里的未信任取值,读取时由 {@link draftOf} / {@link groupDraftsOf} 收窄。 */
32
+ export interface DualAxisSection {
33
+ /** 新会话起步的读轴。 */
34
+ read?: unknown;
35
+ /** 新会话起步的写轴。 */
36
+ write?: unknown;
37
+ /** 组库:会话按 id 引用的具名规则片段。 */
38
+ groups?: unknown;
39
+ /** 新会话默认加载哪些组。 */
40
+ defaultGroups?: unknown;
41
+ }
42
+ /** 两条轴的字段名。逐个处理而不是复制两段代码:加一条轴不会漏掉另一条。 */
43
+ declare const AXES: readonly ["read", "write"];
44
+ /** 一条轴的字段名。 */
45
+ export type AxisField = typeof AXES[number];
46
+ /**
47
+ * 这一行在组合包 `cordis.patch.yml` 里的行 id。
48
+ *
49
+ * 宿主半边 `@t4r71/dsh-dual-axis` 的补丁里那一行就叫 `dual-axis`
50
+ * (`packages/bundle/dual-axis/cordis.patch.yml:11`)。**这个 id 不能自造**:
51
+ * 插件页是拿它去条目树里查那一条 entry 的。
52
+ */
53
+ export declare const DUAL_AXIS_ROW_ID = "dual-axis";
54
+ /**
55
+ * 承载这一行的组合包包名。
56
+ *
57
+ * 配置页的键由**组合包的包名**与行 id 拼成(`rowConfigKey(bundle, rowId)`,
58
+ * ui-plugin-manager/src/client/config-ledger.ts:36-38),而不是由本包的包名拼成:
59
+ * `dual-axis` 这一行写在 `@t4r71/dsh-dual-axis` 的 `cordis.patch.yml` 里,
60
+ * 所以插件页拿那个组合包的名字去查键。写成别的名字(例如插件的发布 scope)
61
+ * 拼出来的键永远匹配不上,页面于是**静默地**不渲染这一行。
62
+ */
63
+ export declare const DUAL_AXIS_BUNDLE = "@t4r71/dsh-dual-axis";
64
+ /** 这一行的配置页在插件页上注册的键:`<组合包名>#<行 id>`。 */
65
+ export declare const DUAL_AXIS_ROW_KEY = "@t4r71/dsh-dual-axis#dual-axis";
66
+ /** 这份配置行需要的服务:page 由 ui-settings-general 的 General 分栏声明。 */
67
+ export declare const inject: string[];
68
+ /**
69
+ * 页面在这一行的渲染点下发的表单面:当前快照与一次原子提交。
70
+ *
71
+ * 成员取自 ui-plugin-manager 发布的 owner props 契约
72
+ * (\`slot-contract.ts:23-28,125-130\`),不在这里重抄一份字段表
73
+ * —— 上游改了 owner props,这里跟着改,而不是悄悄漂移成第二份定义。
74
+ */
75
+ export type DualAxisRowForm = NonNullable<PluginConfigViewProps['form']>;
76
+ /** 表单快照:与 0.1.6 的 \`SettingsScopeSnapshot\` 同名同义(value / user / status / writable)。 */
77
+ export type DualAxisRowSnapshot = ConfigFormSnapshot<DualAxisSection>;
78
+ /** 表单面的写动作与快照,供组件内取用。 */
79
+ export type DualAxisRowMutate = ConfigForm<DualAxisSection>['mutate'];
80
+ /**
81
+ * 配置行的完整 props。页面把这一行当作 \`plugins.row.config\` 的一个 entry 渲染,
82
+ * owner props 因此就是那份契约里的 \`PluginConfigViewProps\`:表单随它一起来。
83
+ */
84
+ export type DualAxisRowProps = PropsRuntime<'plugins.row.config'> & PropsLocale<typeof DUAL_AXIS_LOCALE_NS>;
85
+ /**
86
+ * 组合层声明的兜底轴:设置节里缺一条轴时,页面按这一条显示。
87
+ * @param field - 轴字段名。
88
+ * @returns 该字段的兜底轴值。
89
+ */
90
+ export declare function fallbackOf(field: AxisField): AxisValue;
91
+ /**
92
+ * 配置行本体:两条轴各一组控件,加一个保存、一个放弃、以及每条轴自己的
93
+ * 「恢复默认」。
94
+ * @param props - 页面在 \`plugins.row.config\` 渲染点下发的 \`view\` 与表单面,加当前语言的翻译。
95
+ * @returns 摘要行,或带控件的表单。
96
+ */
97
+ export declare function DualAxisRow(props: DualAxisRowProps): ReactNode;
98
+ /**
99
+ * 挂载配置行:注册词典,再把这一行注册到插件页的 \`plugins.row.config\`。
100
+ * 表单由页面下发,这里不再自持任何 scope。
101
+ * @param ctx - 浏览器插件上下文。
102
+ */
103
+ export declare function apply(ctx: ClientContext): void;
104
+ export {};
@@ -0,0 +1,59 @@
1
+ /**
2
+ * 双轴配置页自己的词典。界面文案只在这里出现一份,配置页按当前语言取用。
3
+ *
4
+ * @module @t4r71/dsh-dual-axis-ui/client/locales
5
+ */
6
+ /** 词典命名空间:与配置页注册到 slot 上的 `locale` 一致。 */
7
+ export declare const DUAL_AXIS_LOCALE_NS = "sandbox-axis";
8
+ /** 这份词典的键集合。 */
9
+ export type DualAxisLocaleKey = keyof typeof zh;
10
+ /** 中文文案。 */
11
+ export declare const zh: {
12
+ readonly rowSummary: "文件沙箱的两条访问轴:新会话按这里的读轴与写轴执行。";
13
+ readonly titleRead: "读轴";
14
+ readonly titleWrite: "写轴";
15
+ readonly hintRead: "这条轴界定的是一条读操作能碰到的路径范围;它压在所有读取之上。";
16
+ readonly hintWrite: "这条轴界定的是一条写操作能碰到的路径范围;它比读轴更严:读轴放行、写轴不放行,仍然写不了。";
17
+ readonly kindLabel: "取值";
18
+ readonly baseLabel: "底座";
19
+ readonly allowLabel: "额外放行的绝对路径(每行一条)";
20
+ readonly denyLabel: "排除的绝对路径(每行一条,优先于放行)";
21
+ readonly kindDeny: "概不允许";
22
+ readonly kindWorkspace: "仅会话工作区";
23
+ readonly kindAll: "整台主机";
24
+ readonly kindCustom: "自定义(底座 + 放行 - 排除)";
25
+ readonly baseDeny: "概不允许";
26
+ readonly baseWorkspace: "会话工作区";
27
+ readonly baseAll: "整台主机";
28
+ readonly customTemplate: "在「{base}」之上放行 {paths}";
29
+ readonly save: "保存";
30
+ readonly saving: "保存中…";
31
+ readonly discard: "放弃改动";
32
+ readonly reset: "恢复默认";
33
+ readonly overridden: "已自定义";
34
+ readonly failed: "保存失败:宿主拒绝了这次写入,草稿已保留";
35
+ readonly readOnly: "当前设置文档不可写,改动无法保存";
36
+ readonly loading: "正在读取双轴设置…";
37
+ readonly unavailable: "宿主没有提供 {ns} 这个设置命名空间,因此这里没有可改的值。";
38
+ readonly groupsTitle: "规则组库";
39
+ readonly groupsHint: "规则组是具名的规则片段:对话按 id 引用它,判定时现取定义。改这里的内容会立刻作用于所有引用它的对话。";
40
+ readonly groupsEmpty: "还没有定义规则组。";
41
+ readonly groupsAdd: "新增规则组";
42
+ readonly groupsRemove: "删除这个组";
43
+ readonly groupIdLabel: "id";
44
+ readonly groupNameLabel: "名称";
45
+ readonly groupDefaultLoad: "新对话默认加载";
46
+ readonly groupSideRead: "读侧规则";
47
+ readonly groupSideWrite: "写侧规则";
48
+ readonly entryAllow: "放行";
49
+ readonly entryDeny: "排除";
50
+ readonly groupAxesHint: "两侧都可以留空:留空表示这个组不覆盖那一根轴。";
51
+ readonly groupsDefaultHint: "勾上的组是新对话的初始组;已经在跑的对话按它自己的预设走,不受这里影响。";
52
+ readonly groupsDefaultHintCustom: "只挂在本节取值选为「自定义」的那条轴上;两条轴都是闭合取值时,这个勾选不起作用。";
53
+ readonly groupsProblemIdEmpty: "规则组的 id 不能为空。";
54
+ readonly groupsProblemIdDuplicate: "规则组的 id 必须唯一:{id} 出现了多次。";
55
+ readonly groupsProblemNotAbsolute: "规则组 {id} 的{side}{entry}列表里,{path} 不是绝对路径。";
56
+ readonly live: "保存后对之后创建的会话生效;当前会话仍由输入框上方的两个下拉控制。";
57
+ };
58
+ /** 英文文案:键集合与中文一致。 */
59
+ export declare const en: Record<DualAxisLocaleKey, string>;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * 本包的宿主半边。这个包的实质内容全在浏览器半边,但 0.1.7 的客户端扫描只处理
3
+ * 「有活动 Loader 行」的包:包名没有行,`dsh.client` 就不会被采集成客户端行,
4
+ * 浏览器半边永远不会下发。这个空插件就是那一行的落点。
5
+ * @module @t4r71/dsh-dual-axis-ui
6
+ */
7
+ /** 插件名,loader 诊断用。 */
8
+ export declare const name = "dual-axis-ui";
9
+ /** 不做任何事:两个界面面都由 ./client 那半边承担。 */
10
+ export default function apply(): Promise<void>;
package/package.json ADDED
@@ -0,0 +1,111 @@
1
+ {
2
+ "name": "@t4r71/dsh-dual-axis-ui",
3
+ "version": "0.1.0",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "description": "双轴访问模式组合包的浏览器半边:设置页的配置行 + 输入框上方的读/写两个下拉,两面共用一个客户端插件。",
8
+ "type": "module",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./lib/types/index.d.ts",
12
+ "default": "./lib/index.js"
13
+ },
14
+ "./client": {
15
+ "types": "./lib/types/client/index.d.ts",
16
+ "default": "./lib/client.js"
17
+ },
18
+ "./package.json": "./package.json"
19
+ },
20
+ "dsh": {
21
+ "client": {
22
+ "inject": [
23
+ "@deepseek-ai/dsh-api-session-controller",
24
+ "@deepseek-ai/dsh-client-connection",
25
+ "@deepseek-ai/dsh-client-locale",
26
+ "@deepseek-ai/dsh-client-ui-commands",
27
+ "@deepseek-ai/dsh-client-ui-conversation",
28
+ "@deepseek-ai/dsh-api-remotes",
29
+ "@deepseek-ai/dsh-client-ui-settings",
30
+ "@deepseek-ai/dsh-client-ui-settings-general"
31
+ ],
32
+ "platform": "web"
33
+ }
34
+ },
35
+ "files": [
36
+ "lib/index.js",
37
+ "lib/client.js",
38
+ "lib/types/**/*.d.ts"
39
+ ],
40
+ "scripts": {
41
+ "build": "tsc -b tsconfig.json && tsdown",
42
+ "test": "node --import tsx/esm --test tests/rule-groups.spec.ts tests/axis-editor-groups.spec.ts tests/session-axes.spec.ts tests/axis-submit.spec.ts tests/axis-narrowing.spec.ts"
43
+ },
44
+ "license": "MIT",
45
+ "author": "T4R71 <T4R71@outlook.com>",
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/T4R71/dsh-dual-axis.git",
49
+ "directory": "packages/dual-axis-ui"
50
+ },
51
+ "homepage": "https://github.com/T4R71/dsh-dual-axis#readme",
52
+ "bugs": "https://github.com/T4R71/dsh-dual-axis/issues",
53
+ "keywords": [
54
+ "dsh",
55
+ "deepseek-harness",
56
+ "cordis",
57
+ "client-plugin",
58
+ "sandbox",
59
+ "access-control"
60
+ ],
61
+ "peerDependencies": {
62
+ "@deepseek-ai/cordis": "^4.0.4",
63
+ "@deepseek-ai/dsh-api-remotes": "0.1.7-rc.2",
64
+ "@deepseek-ai/dsh-api-session-controller": "0.1.7-rc.2",
65
+ "@deepseek-ai/dsh-api-settings-controller": "0.1.7-rc.2",
66
+ "@deepseek-ai/dsh-client-connection": "0.1.7-rc.2",
67
+ "@deepseek-ai/dsh-client-locale": "0.1.7-rc.2",
68
+ "@deepseek-ai/dsh-client-store": "0.1.7-rc.2",
69
+ "@deepseek-ai/dsh-client-ui-commands": "0.1.7-rc.2",
70
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.2",
71
+ "@deepseek-ai/dsh-client-ui-input-trigger": "0.1.7-rc.2",
72
+ "@deepseek-ai/dsh-client-ui-plugin-manager": "0.1.7-rc.2",
73
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.2",
74
+ "@deepseek-ai/dsh-client-ui-renderer": "0.1.7-rc.2",
75
+ "@deepseek-ai/dsh-client-ui-session": "0.1.7-rc.2",
76
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.7-rc.2",
77
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.7-rc.2",
78
+ "@deepseek-ai/dsh-permission-presets": "0.1.7-rc.2"
79
+ },
80
+ "devDependencies": {
81
+ "@deepseek-ai/cordis": "^4.0.4",
82
+ "@deepseek-ai/dsh-api-remotes": "0.1.7-rc.2",
83
+ "@deepseek-ai/dsh-api-session-controller": "0.1.7-rc.2",
84
+ "@deepseek-ai/dsh-api-settings-controller": "0.1.7-rc.2",
85
+ "@deepseek-ai/dsh-client-connection": "0.1.7-rc.2",
86
+ "@deepseek-ai/dsh-client-locale": "0.1.7-rc.2",
87
+ "@deepseek-ai/dsh-client-store": "0.1.7-rc.2",
88
+ "@deepseek-ai/dsh-client-ui-commands": "0.1.7-rc.2",
89
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.2",
90
+ "@deepseek-ai/dsh-client-ui-input-trigger": "0.1.7-rc.2",
91
+ "@deepseek-ai/dsh-client-ui-plugin-manager": "0.1.7-rc.2",
92
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.2",
93
+ "@deepseek-ai/dsh-client-ui-renderer": "0.1.7-rc.2",
94
+ "@deepseek-ai/dsh-client-ui-session": "0.1.7-rc.2",
95
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.7-rc.2",
96
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.7-rc.2",
97
+ "@deepseek-ai/dsh-permission-presets": "0.1.7-rc.2",
98
+ "@deepseek-ai/dsh-session": "0.1.7-rc.2",
99
+ "@deepseek-ai/dsh-session-projection": "0.1.7-rc.2",
100
+ "@types/node": "^24.0.0",
101
+ "@types/react": "~18.3.1",
102
+ "clsx": "^2.0.0",
103
+ "lightningcss": "^1.30.0",
104
+ "react": "^18.2.0",
105
+ "tsdown": "^0.22.2",
106
+ "tsx": "^4.22.4",
107
+ "typescript": "^6.0.3"
108
+ },
109
+ "main": "lib/index.js",
110
+ "types": "lib/types/index.d.ts"
111
+ }