@jayyuen66/dsh-plugin-shared 0.2.3 → 0.2.5

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.
@@ -1 +1 @@
1
- import{defineConfig as e}from"vitest/config";const t={provider:`v8`,exclude:[`test/**`,`node_modules/**`,`**/test/**`,`**/node_modules/**`,`build-client*`,`client.js`,`agents/**`,`scripts/**`,`**/*.d.ts`,`**/*.d.mts`],reporter:[`text`,`json-summary`,`json`],reportsDirectory:`coverage`,thresholds:{lines:100,statements:100,functions:100,branches:100}};function n(n){let{coverageInclude:r,coverage:i,test:a}=n;if(r.length===0||r.some(e=>e.trim().length===0))throw Error(`coverageInclude 不能为空数组,也不能含空串:统计范围缺件后覆盖率阈值照样全部通过,缺的是测量对象不是覆盖。`);if(a&&`coverage`in a)throw Error(`test.coverage 会整块替换公共覆盖率配置(含四项 100% 阈值与排除表);覆盖率覆盖项请走 coverage 参数,逐键合并。`);return e({test:{include:[`test/**/*.{test,spec}.{ts,tsx,mts,cts}`],environment:`node`,testTimeout:2e4,coverage:{...t,...i,include:r,thresholds:{...t.thresholds,...i?.thresholds}},...a}})}export{n as definePackageConfig};
1
+ import{defineConfig as e}from"vitest/config";const t={provider:`v8`,exclude:[`test/**`,`node_modules/**`,`**/test/**`,`**/node_modules/**`,`build-client*`,`client.js`,`agents/**`,`scripts/**`,`**/*.d.ts`,`**/*.d.mts`],reporter:[`text`,`json-summary`,`json`],reportsDirectory:`coverage`,thresholds:{lines:100,statements:100,functions:100,branches:100}};function n(n){let{coverageInclude:r,coverage:i,test:a}=n;if(r.length===0||r.some(e=>e.trim().length===0))throw Error(`coverageInclude 不能为空数组,也不能含空串:统计范围缺件后覆盖率阈值照样全部通过,缺的是测量对象不是覆盖。`);if(a&&`coverage`in a)throw Error(`test.coverage 会整块替换公共覆盖率配置(含四项 100% 阈值与排除表);覆盖率覆盖项请走 coverage 参数,逐键合并。`);return e({resolve:{alias:{"@jayyuen66/dsh-plugin-shared/client":`@jayyuen66/dsh-plugin-shared/client-node`}},test:{include:[`test/**/*.{test,spec}.{ts,tsx,mts,cts}`],environment:`node`,testTimeout:2e4,coverage:{...t,...i,include:r,thresholds:{...t.thresholds,...i?.thresholds}},...a}})}export{n as definePackageConfig};
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{fieldOf as e,hasMethods as t,isRecord as n}from"./record.js";import{editPathOf as r,scanToolEvents as i,toolEventRowsOf as a}from"./tool-events.js";import{claimApply as o}from"./card-apply.js";import{diffTouched as s}from"./card-diff.js";import{deriveProjectKey as c}from"./project-key.js";import{DEFAULT_LOCALE as l,LOCALE_PREFERENCE_FIELD as u,LOCALE_SETTINGS_NAMESPACE as d,messagesFor as f,resolveLocale as p,resolveLocalePreference as m}from"./locale.js";import{settleLessonCall as h}from"./lesson-bus.js";import{truncateEnd as g,truncateStart as _}from"./text.js";import{errorText as v,isSettingsConflict as y}from"./errors.js";import{shrinkJsonlTail as b}from"./jsonl.js";import{jobOutcomeOf as x,killProc as S}from"./job-outcome.js";export{l as DEFAULT_LOCALE,u as LOCALE_PREFERENCE_FIELD,d as LOCALE_SETTINGS_NAMESPACE,o as claimApply,c as deriveProjectKey,s as diffTouched,r as editPathOf,v as errorText,e as fieldOf,t as hasMethods,n as isRecord,y as isSettingsConflict,x as jobOutcomeOf,S as killProc,f as messagesFor,p as resolveLocale,m as resolveLocalePreference,i as scanToolEvents,h as settleLessonCall,b as shrinkJsonlTail,a as toolEventRowsOf,g as truncateEnd,_ as truncateStart};
1
+ import{applyPatchTargetsOf as e,editPathOf as t,editPathsOf as n,scanToolEvents as r,toolEventRowsOf as i}from"./tool-events.js";import{claimApply as a}from"./card-apply.js";import{diffTouched as o}from"./card-diff.js";import{deriveProjectKey as s}from"./project-key.js";import{DEFAULT_LOCALE as c,LOCALE_PREFERENCE_FIELD as l,LOCALE_SETTINGS_NAMESPACE as u,messagesFor as d,resolveLocale as f,resolveLocalePreference as p}from"./locale.js";import{settleLessonCall as m}from"./lesson-bus.js";import{truncateEnd as h,truncateStart as g}from"./text.js";import{fieldOf as _,hasMethods as v,isRecord as y}from"./record.js";import{errorText as b,isSettingsConflict as x}from"./errors.js";import{shrinkJsonlTail as S}from"./jsonl.js";import{jobOutcomeOf as C,killProc as w}from"./job-outcome.js";export{c as DEFAULT_LOCALE,l as LOCALE_PREFERENCE_FIELD,u as LOCALE_SETTINGS_NAMESPACE,e as applyPatchTargetsOf,a as claimApply,s as deriveProjectKey,o as diffTouched,t as editPathOf,n as editPathsOf,b as errorText,_ as fieldOf,v as hasMethods,y as isRecord,x as isSettingsConflict,C as jobOutcomeOf,w as killProc,d as messagesFor,f as resolveLocale,p as resolveLocalePreference,r as scanToolEvents,m as settleLessonCall,S as shrinkJsonlTail,i as toolEventRowsOf,h as truncateEnd,g as truncateStart};
package/dist/plugin.js ADDED
@@ -0,0 +1 @@
1
+ import{fieldOf as e,hasMethods as t,isRecord as n}from"./record.js";import{applyPatchTargetsOf as r,editPathOf as i,editPathsOf as a,scanToolEvents as o,toolEventRowsOf as s}from"./tool-events.js";import{claimApply as c}from"./card-apply.js";import{diffTouched as l}from"./card-diff.js";import{deriveProjectKey as u}from"./project-key.js";import{DEFAULT_LOCALE as d,LOCALE_PREFERENCE_FIELD as f,LOCALE_SETTINGS_NAMESPACE as p,messagesFor as m,resolveLocale as h,resolveLocalePreference as g}from"./locale.js";import{settleLessonCall as _}from"./lesson-bus.js";import{truncateEnd as v,truncateStart as y}from"./text.js";import{errorText as b,isSettingsConflict as x}from"./errors.js";import{shrinkJsonlTail as S}from"./jsonl.js";import{jobOutcomeOf as C,killProc as w}from"./job-outcome.js";import"./index.js";const T=`@jayyuen66/dsh-plugin-shared`;function E(){}export{d as DEFAULT_LOCALE,f as LOCALE_PREFERENCE_FIELD,p as LOCALE_SETTINGS_NAMESPACE,E as apply,r as applyPatchTargetsOf,c as claimApply,u as deriveProjectKey,l as diffTouched,i as editPathOf,a as editPathsOf,b as errorText,e as fieldOf,t as hasMethods,n as isRecord,x as isSettingsConflict,C as jobOutcomeOf,w as killProc,m as messagesFor,T as name,h as resolveLocale,g as resolveLocalePreference,o as scanToolEvents,_ as settleLessonCall,S as shrinkJsonlTail,s as toolEventRowsOf,v as truncateEnd,y as truncateStart};
@@ -0,0 +1 @@
1
+ import{Remote as e}from"@deepseek-ai/dsh-typert-protocol";function t(t,n){let r={kind:`method`,name:n,static:!1,private:!1,addInitializer:e=>{Reflect.apply(e,Object.create(t),[])}},i=e(n);Reflect.apply(i,void 0,[Reflect.get(t,n),r])}export{t as markRemote};
@@ -1 +1 @@
1
- import{isRecord as e}from"./record.js";function t(t){return e(t)&&t.isError===!0}function n(e){return e===!0}function r(t){return e(t.data)}function i(e){return typeof e==`string`&&e.length>0?e:void 0}function a(e){return typeof e==`string`&&e.length>0?e:void 0}function o(t){if(typeof t==`string`)try{let n=JSON.parse(t);return{arguments:e(n)?n:{},badArguments:!1}}catch{return{arguments:{},badArguments:!0}}return{arguments:e(t)?t:{},badArguments:!1}}function s(e,t){let n;if(!r(e))return n;if(e.type===`tool/call`){let r=a(e.data.name);if(r!==void 0){let a=o(e.data.arguments);n={name:r,callId:i(e.data.callId),arguments:a.arguments,badArguments:a.badArguments,seq:t}}}else if(e.type===`tool/ptc-dispatch-start`){let r=i(e.data.subCallId),s=a(e.data.name);if(r!==void 0&&s!==void 0){let i=o(e.data.arguments);n={name:s,callId:r,arguments:i.arguments,badArguments:i.badArguments,seq:t}}}return n}function c(a,o){let s;if(!r(a))return s;if(a.type===`tool/result`){let n=a.data.message,r=e(n)?n.source:void 0;s={callId:e(r)?i(r.callId):void 0,isError:t(n),seq:o}}else if(a.type===`tool/ptc-dispatch`){let e=i(a.data.subCallId);e!==void 0&&(s={callId:e,isError:n(a.data.isError),seq:o})}return s}function l(e,t){return{call:s(e,t),result:c(e,t)}}function u(t){let n=[],r=[];for(let[i,a]of t.entries())if(e(a)){let{call:e,result:t}=l(a,i);e!==void 0&&n.push(e),t!==void 0&&r.push(t)}return{calls:n,results:r}}function d(e,t){let n=e[t];return typeof n==`string`?n:void 0}function f(e){let t=e.arguments;return e.name===`str_replace_editor`?t.command===`view`?{kind:`read-view`,path:d(t,`path`)}:{kind:`write`,path:d(t,`path`)}:{kind:`write`,path:d(t,`file_path`)}}export{f as editPathOf,u as scanToolEvents,l as toolEventRowsOf};
1
+ import{isRecord as e}from"./record.js";import{parsePatch as t}from"@deepseek-ai/dsh-fs-patch";function n(t){return e(t)&&t.isError===!0}function r(e){return e===!0}function i(t){return e(t.data)}function a(e){return typeof e==`string`&&e.length>0?e:void 0}function o(e){return typeof e==`string`&&e.length>0?e:void 0}function s(t){if(typeof t==`string`)try{let n=JSON.parse(t);return{arguments:e(n)?n:{},badArguments:!1}}catch{return{arguments:{},badArguments:!0}}return{arguments:e(t)?t:{},badArguments:!1}}function c(e,t){let n;if(!i(e))return n;if(e.type===`tool/call`){let r=o(e.data.name);if(r!==void 0){let i=s(e.data.arguments);n={name:r,callId:a(e.data.callId),arguments:i.arguments,badArguments:i.badArguments,seq:t}}}else if(e.type===`tool/ptc-dispatch-start`){let r=a(e.data.subCallId),i=o(e.data.name);if(r!==void 0&&i!==void 0){let a=s(e.data.arguments);n={name:i,callId:r,arguments:a.arguments,badArguments:a.badArguments,seq:t}}}return n}function l(t,o){let s;if(!i(t))return s;if(t.type===`tool/result`){let r=t.data.message,i=e(r)?r.source:void 0;s={callId:e(i)?a(i.callId):void 0,isError:n(r),seq:o}}else if(t.type===`tool/ptc-dispatch`){let e=a(t.data.subCallId);e!==void 0&&(s={callId:e,isError:r(t.data.isError),seq:o})}return s}function u(e,t){return{call:c(e,t),result:l(e,t)}}function d(t){let n=[],r=[];for(let[i,a]of t.entries())if(e(a)){let{call:e,result:t}=u(a,i);e!==void 0&&n.push(e),t!==void 0&&r.push(t)}return{calls:n,results:r}}function f(e,t){let n=e[t];return typeof n==`string`?n:void 0}function p(e){let n=e?.input;if(typeof n!=`string`||!n.includes(`*** Begin Patch`))return[];try{return t(n).map(e=>e.kind===`update`?e.moveTo===void 0?{kind:`update`,path:e.path}:{kind:`update`,path:e.path,moveTo:e.moveTo}:{kind:e.kind,path:e.path})}catch{return[]}}function m(e){let t=e.arguments;return e.name===`apply_patch`?{kind:`write`,path:p(t)[0]?.path}:e.name===`str_replace_editor`?t.command===`view`?{kind:`read-view`,path:f(t,`path`)}:{kind:`write`,path:f(t,`path`)}:{kind:`write`,path:f(t,`file_path`)}}function h(e){if(e.name===`apply_patch`){let t=p(e.arguments).flatMap(e=>e.kind===`update`&&e.moveTo!==void 0?[e.path,e.moveTo]:[e.path]);return t.filter((e,n)=>e.length>0&&t.indexOf(e)===n)}let t=m(e);return t.kind===`write`&&t.path!==void 0?[t.path]:[]}export{p as applyPatchTargetsOf,m as editPathOf,h as editPathsOf,d as scanToolEvents,u as toolEventRowsOf};
@@ -15,7 +15,7 @@ export declare function asRecord(raw: unknown): Record<string, unknown>;
15
15
  * 读包根的 package.json,带上下文的失败信息。
16
16
  *
17
17
  * 惰性(调用时才读)而不是在消费方模块顶层读:顶层一次 JSON 语法错误会以未捕获的顶层
18
- * await 错误 + 裸 SyntaxError 收场,读者看不出是哪个文件坏了;而测试 import 构建模块时
18
+ * await 错误 + 不带文件路径的 SyntaxError 收场,读者看不出是哪个文件坏了;而测试 import 构建模块时
19
19
  * 只为拿构建函数,不该连带做一次磁盘 I/O。
20
20
  * @param root - 包根绝对路径
21
21
  * @returns 解析后的 manifest
@@ -51,23 +51,49 @@ export interface OutputItem {
51
51
  export declare function singleEntryChunk(output: readonly OutputItem[], source: string): OutputItem & {
52
52
  code: string;
53
53
  };
54
+ /**
55
+ * rename 的 Windows 退避重试。
56
+ *
57
+ * POSIX 上 rename 换目录项是原子的,失败即真失败;Windows 上目标文件被其它进程持有
58
+ * (Electron / dev server 正 require 产物、杀毒或索引服务短暂占用)时会给 EPERM/EBUSY,
59
+ * 而占用通常在几十毫秒内释放。不重试的话这条失败是**间歇性**的:同一份安装里连着构建两次,
60
+ * 一次失败一次成功。其余错误码照旧立即抛出——真的没权限时重试只是拖慢失败。
61
+ * @param from - 草稿文件
62
+ * @param to - 目标文件
63
+ * @param attempt - 已重试次数
64
+ */
65
+ export declare function renameWithRetry(from: string, to: string, attempt?: number): Promise<void>;
54
66
  /**
55
67
  * 原子写入:目标目录下 `.tmp/` 草稿 + rename;失败时清掉草稿再抛。
56
68
  *
57
69
  * 草稿落在**目标文件所在目录**下的 `.tmp/`,不是 `os.tmpdir()`,也不是产物旁边的裸名:
58
70
  * - 不用 `os.tmpdir()`:rename 只在同一文件系统内原子,跨设备会以 EXDEV 失败,而系统临时
59
71
  * 目录常被挂到另一个分区/卷;
60
- * - 跟随目标目录而不是写死包根:本函数住在公共库里,产物落点由调用方决定;
72
+ * - 跟随目标目录而不是写死包根:本函数定义在公共库里,产物写到哪儿由调用方决定;
61
73
  * - 不用「产物名 + 后缀」直接落在产物旁边:那个名字通常不在 `.gitignore` 里,构建被中断
62
74
  * 时半份产物会以未跟踪文件出现在 `git status`,被误当成源码改动提交。`.tmp/` 是各包
63
75
  * 统一忽略的目录,不需要为构建残留单独扩忽略规则。
64
76
  *
65
- * 失败信息带上两个路径并保留 cause:裸 `ENOENT … open '…/<uuid>.tmp'` 把注意力引到草稿名上,
77
+ * 失败信息带上两个路径并保留 cause:只有 `ENOENT … open '…/<uuid>.tmp'` 把注意力引到草稿名上,
66
78
  * 读者还得自己从中找出真正的产物路径。
67
79
  * @param target - 目标文件绝对路径
68
80
  * @param text - 产物正文
69
81
  */
70
82
  export declare function writeArtifact(target: string, text: string): Promise<void>;
83
+ /**
84
+ * 把注释与字符串内容替换成空格,保留长度与换行;引号/反引号本身保留。
85
+ *
86
+ * 用途是给**形状判断**(装饰器语法、声明里的模块说明符)提供一份与原文逐字符对齐的
87
+ * “只看程序正文”文本:调用方拿同一套下标回到原文取值,既不误伤注释里的示例,也不会
88
+ * 把字面量类型里的 `from "./x.ts"` 当成真实说明符。
89
+ *
90
+ * 字符串里的转义对整体遮蔽;模板字面量的 `${}` 不做二次解析(本包不需要在表达式里
91
+ * 找装饰器或说明符)。正则字面量不做词法识别,里面的 `@` 可能造成一次多余的 tsc 调用
92
+ * ——方向是安全的(只多跑一次编译,不产出错字节)。
93
+ * @param code - 源文本
94
+ * @returns 与入参等长、换行位置不变的遮蔽文本
95
+ */
96
+ export declare function maskNonCode(code: string): string;
71
97
  /** 异常路径上释放 rolldown bundle 的最小接口。 */
72
98
  export interface CloseableBundle {
73
99
  readonly close: () => Promise<void>;
@@ -86,7 +112,7 @@ export interface RolldownBundle extends CloseableBundle {
86
112
  * 调用方注入的 rolldown 构造器。
87
113
  *
88
114
  * 注入而不是由本包声明依赖:rolldown 是各包构建期自己的 devDependency,本包作为库
89
- * 不该为构建工具声明运行期依赖面。参数类型借 rolldown 自己的 InputOptions(仅类型
115
+ * 不该为构建工具声明运行期依赖。参数类型借 rolldown 自己的 InputOptions(仅类型
90
116
  * 导入,产物里没有它)。
91
117
  */
92
118
  export type RolldownFactory = (options: InputOptions) => Promise<RolldownBundle>;
@@ -1,8 +1,8 @@
1
1
  import type { RolldownFactory } from "./build-artifacts.js";
2
2
  /**
3
- * 宿主 seed 表里 react 家族的全部说明符(客户端产物只外置宿主真给得出的模块)。
3
+ * 宿主 seed 表里 react 家族的全部模块说明符——客户端产物只外置宿主真给得出的模块。
4
4
  * 与宿主客户端自己的模块表同源:那张表里 react 家族只有这四条。外置清单更大的包
5
- * (宿主外壳基座扩容后)由调用方在 `externals` 里给全量清单。
5
+ * (宿主 外壳 的 PLATFORM_MODULES,即宿主平台模块表,扩容后)由调用方在 `externals` 里给全量清单。
6
6
  */
7
7
  export declare const REACT_RUNTIME_MODULES: readonly string[];
8
8
  /**
@@ -38,9 +38,9 @@ export declare function collapseStorePaths(code: string): string;
38
38
  * 判断材料在这里。
39
39
  */
40
40
  export interface ClientNameContext {
41
- /** package.json 的 name(外壳 id 的唯一来源)。 */
41
+ /** package.json 的 name(外壳 里 id 的唯一来源)。 */
42
42
  readonly pkgName: string;
43
- /** 改写后的 chunk 正文(未包外壳)。 */
43
+ /** 改写后的 chunk 正文(尚未包进 外壳)。 */
44
44
  readonly body: string;
45
45
  /** 读包根下一份源码文件。 */
46
46
  readonly readSource: (relative: string) => Promise<string>;
@@ -68,9 +68,9 @@ export interface ClientBuildOptions {
68
68
  /**
69
69
  * 客户端外置规则:登记过的精确说明符外置,react 家族里**没登记**的说明符当场失败。
70
70
  *
71
- * 为什么既不静默内联也不前缀放行:外壳注入的 require 只在宿主模块表里查键。前缀放行会
72
- * 得到一条表里没有的 require(加载期 not in the module table,整张卡片静默不渲染);而
73
- * 静默内联会把 node_modules 里那份 React 打进产物、与宿主那份并存,页面里两个 React
71
+ * 为什么既不悄悄内联也不按前缀放行:外壳 注入的 require 只在宿主模块表里查键。按前缀放行会
72
+ * 得到一条表里没有的 require(加载期 not in the module table,整张卡片不渲染也不给提示);而
73
+ * 悄悄内联会把 node_modules 里那份 React 打进产物、与宿主那份并存,页面里两个 React
74
74
  * 实例, hooks 直接报错。两种失败都不在构建期报错,所以这里没有可观察的中间态。
75
75
  * 导出给各包的构建脚本复用与测试直接驱动,与构建走同一份判断。
76
76
  * @param externals - 外置说明符全量清单(精确匹配)
@@ -6,16 +6,22 @@ export interface TypesBuildOptions {
6
6
  readonly tscEntry: string;
7
7
  /** tsconfig 项目名(相对包根)。缺省 `tsconfig.types.json`。 */
8
8
  readonly tsconfig?: string;
9
- /** 草稿目录绝对路径。缺省 `<root>/.tmp/types`(该目录在各包统一被 git 忽略,
9
+ /** scratch 临时目录的绝对路径。缺省 `<root>/.tmp/types`(该目录在各包统一被 git 忽略,
10
10
  * 且与 types/ 同一文件系统,最后一步 rename 原子且不跨设备)。 */
11
11
  readonly scratch?: string;
12
12
  /** 产物目录绝对路径。缺省 `<root>/types`。 */
13
13
  readonly outDir?: string;
14
+ /** 目录换入用的 rename(缺省走 Windows 退避重试)。注入点供测试制造换入失败,
15
+ * 以及让不支持 rename 的宿主替换实现。 */
16
+ readonly rename?: (from: string, to: string) => Promise<void>;
14
17
  }
15
18
  /**
16
- * 把一段声明正文里的相对源码后缀说明符改写成对侧产物后缀。
19
+ * 把一段声明正文里带源码后缀的相对说明符改写成对侧产物后缀。
17
20
  *
18
21
  * 三处 replace 各自收一种句法位置,互不依赖;同一个文件里三种都出现时不漏也不重。
22
+ * 三处正则都会在**注释与字符串内部**命中,所以替换前先用 {@link maskNonCode} 取一份
23
+ * 等长的正文遮蔽文本,只有“说明符起始引号在正文位置上”的命中才改写:JSDoc 示例里的
24
+ * `from "./x.ts"` 与字面量类型 `type P = 'from "./x.ts"'` 因此原样保留。
19
25
  * @param text - 声明文件正文
20
26
  * @returns 改写后的正文
21
27
  */
@@ -1,2 +1,2 @@
1
1
  /** 设置卡统一样式。颜色/圆角全部走宿主主题令牌。 */
2
- export declare const CARD_UI_CSS = "\n.dsu-form{display:flex;flex-direction:column}\n.dsu-section{margin-top:24px;padding-top:24px;border-top:.5px solid var(--dsw-alias-border-l1)}\n.dsu-form>.dsu-section:first-child{margin-top:0;padding-top:0;border-top:0}\n.dsu-sectionTitle{margin:0;font-size:15px;font-weight:600;line-height:1.4;color:var(--dsw-alias-label-primary)}\n.dsu-sectionHint{margin:4px 0 0;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}\n.dsu-statusbar{display:flex;flex-wrap:wrap;gap:4px 8px;margin-top:8px;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}\n.dsu-field{display:grid;grid-template-columns:minmax(0,1fr) minmax(240px,360px);column-gap:32px;align-items:center;padding:12px 0;border-top:.5px solid var(--dsw-alias-border-l2)}\n.dsu-fieldMeta{display:flex;flex-direction:column;gap:4px;min-width:0}\n.dsu-labelRow{display:flex;align-items:center;gap:6px;min-width:0}\n.dsu-label{font-size:13px;font-weight:500;line-height:1.5;color:var(--dsw-alias-label-primary)}\n.dsu-labelMono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px}\n.dsu-hint{margin:0;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}\n.dsu-control{min-width:0;display:flex;align-items:center;gap:8px}\n.dsu-fieldWide{grid-template-columns:minmax(0,1fr);align-items:start}\n.dsu-fieldWide .dsu-control{width:100%;max-width:720px;margin-top:2px}\n.dsu-help{display:inline-flex;align-items:center;gap:6px;min-width:0}\n.dsu-helpBtn{appearance:none;border:0;background:transparent;padding:0;width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center;color:var(--dsw-alias-label-tertiary);cursor:help;border-radius:50%;flex:none}\n.dsu-help:hover .dsu-helpBtn,.dsu-helpBtn:focus-visible{color:var(--dsw-alias-label-primary)}\n.dsu-helpBtn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}\n.dsu-tip{position:fixed;z-index:60;box-sizing:border-box;max-width:min(340px,calc(100vw - 16px));max-height:calc(100vh - 16px);overflow:auto;overflow-wrap:anywhere;padding:10px 12px;border-radius:10px;background:var(--dsw-alias-bg-layer-2);border:.5px solid var(--dsw-alias-border-l3);box-shadow:0 12px 32px rgb(0 0 0 / 45%);font-size:12px;line-height:1.6;font-weight:400;color:var(--dsw-alias-label-secondary)}\n.dsu-input{width:100%;height:34px;padding:0 12px;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px}\n.dsu-input:focus-visible{outline:none;border-color:var(--dsw-alias-state-business-primary)}\n.dsu-input[aria-invalid=\"true\"]{border-color:var(--dsw-alias-state-error-primary)}\n.dsu-input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}\n.dsu-input::placeholder{color:var(--dsw-alias-label-tertiary)}\n.dsu-textarea{height:auto;min-height:96px;padding:8px 12px;line-height:1.6;resize:vertical}\n.dsu-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}\n.dsu-numberWrap{display:flex;flex-direction:column;gap:4px;width:100%;min-width:0}\n.dsu-number{display:flex;align-items:center;gap:8px;min-width:0}\n.dsu-number .dsu-input{min-width:0}\n.dsu-unit{flex:none;font-size:12px;color:var(--dsw-alias-label-tertiary)}\n.dsu-error{margin:0;font-size:12px;line-height:1.5;color:var(--dsw-alias-state-error-primary)}\n.dsu-switch{appearance:none;width:36px;height:20px;border-radius:999px;border:0;padding:2px;background:var(--dsw-alias-border-l3);display:flex;align-items:center;cursor:pointer;flex:none;transition:background-color .16s}\n.dsu-knob{width:16px;height:16px;border-radius:50%;background:var(--dsw-alias-label-primary);transition:transform .16s,background-color .16s}\n.dsu-switch[aria-checked=\"true\"]{background:var(--dsw-alias-label-primary)}\n.dsu-switch[aria-checked=\"true\"] .dsu-knob{transform:translateX(16px);background:var(--dsw-alias-label-primary-foreground)}\n.dsu-switch:disabled{opacity:.4;cursor:not-allowed}\n.dsu-switch:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}\n.dsu-selectWrap{position:relative;width:100%;min-width:0}\n.dsu-select{display:flex;align-items:center;justify-content:space-between;gap:8px;text-align:left;cursor:pointer}\n.dsu-select[aria-expanded=\"true\"]{border-color:var(--dsw-alias-state-business-primary)}\n.dsu-selectValue{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dsu-chevron{flex:none;color:var(--dsw-alias-label-tertiary);transition:transform .16s}\n.dsu-select[aria-expanded=\"true\"] .dsu-chevron{transform:rotate(180deg)}\n.dsu-menu{position:fixed;z-index:70;padding:4px;background:var(--dsw-alias-bg-layer-2);border:.5px solid var(--dsw-alias-border-l3);border-radius:12px;box-shadow:0 12px 32px rgb(0 0 0 / 50%);max-height:280px;overflow:auto}\n.dsu-option{appearance:none;border:0;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:1.4;width:100%;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 10px;border-radius:8px;cursor:pointer;text-align:left}\n.dsu-option:hover,.dsu-option[data-active=\"true\"]{background:var(--dsw-alias-bg-layer-3)}\n.dsu-option:disabled{color:var(--dsw-alias-label-tertiary);cursor:not-allowed}\n.dsu-option:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px}\n.dsu-optionGroup{padding:6px 10px 2px;font-size:11px;font-weight:600;color:var(--dsw-alias-label-tertiary)}\n.dsu-check{opacity:0;flex:none}\n.dsu-option[aria-selected=\"true\"] .dsu-check{opacity:1}\n.dsu-savebar{display:flex;align-items:center;gap:8px;padding:12px 0;margin-top:24px;border-top:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base)}\n.dsu-savebar[data-dirty=\"true\"]{position:sticky;bottom:0;z-index:2;box-shadow:0 -12px 24px rgb(0 0 0 / 35%)}\n.dsu-btn{appearance:none;border:.5px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:1.5;border-radius:var(--dsw-radius-md);padding:5px 14px;cursor:pointer;transition:background-color .12s,border-color .12s,color .12s,filter .12s}\n.dsu-btn:hover:not(:disabled){background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-border-l3)}\n.dsu-btn:active:not(:disabled){background:var(--dsw-alias-bg-layer-1)}\n.dsu-btn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}\n.dsu-btn:disabled{opacity:.4;cursor:not-allowed}\n.dsu-btnPrimary{background:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}\n.dsu-btnPrimary:hover:not(:disabled){background:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-primary);filter:brightness(.9)}\n.dsu-btnPrimary:active:not(:disabled){background:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-primary);filter:brightness(.84)}\n.dsu-btnDanger{color:var(--dsw-alias-state-error-primary)}\n.dsu-btnDanger:hover:not(:disabled){color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-bg-layer-2)}\n.dsu-status{margin-left:auto;font-size:12px;color:var(--dsw-alias-label-tertiary)}\n.dsu-statusError{color:var(--dsw-alias-state-error-primary)}\n.dsu-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(200px,100%),1fr));gap:0 24px}\n.dsu-grid>.dsu-field{display:flex;flex-direction:column;align-items:stretch;gap:6px;padding:10px 0;border-top:.5px solid var(--dsw-alias-border-l1)}\n.dsu-grid>.dsu-field .dsu-control{width:100%}\n@media (max-width:640px){\n .dsu-field{grid-template-columns:minmax(0,1fr);align-items:start}\n .dsu-control{width:100%;max-width:720px}\n .dsu-section{margin-top:20px;padding-top:20px}\n}\n@media (prefers-reduced-motion:reduce){\n .dsu-switch,.dsu-knob,.dsu-chevron,.dsu-btn{transition:none}\n}\n";
2
+ export declare const CARD_UI_CSS = "\n.dsu-form{display:flex;flex-direction:column}\n.dsu-section{margin-top:24px;padding-top:24px;border-top:.5px solid var(--dsw-alias-border-l1)}\n.dsu-form>.dsu-section:first-child{margin-top:0;padding-top:0;border-top:0}\n.dsu-sectionTitle{margin:0;font-size:15px;font-weight:600;line-height:1.4;color:var(--dsw-alias-label-primary)}\n.dsu-sectionHint{margin:4px 0 0;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}\n.dsu-statusbar{display:flex;flex-wrap:wrap;gap:4px 8px;margin-top:8px;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}\n.dsu-field{display:grid;grid-template-columns:minmax(0,1fr) minmax(240px,360px);column-gap:32px;align-items:center;padding:12px 0;border-top:.5px solid var(--dsw-alias-border-l2)}\n.dsu-fieldMeta{display:flex;flex-direction:column;gap:4px;min-width:0}\n.dsu-labelRow{display:flex;align-items:center;gap:6px;min-width:0}\n.dsu-label{font-size:13px;font-weight:500;line-height:1.5;color:var(--dsw-alias-label-primary)}\n.dsu-labelMono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px}\n.dsu-hint{margin:0;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}\n.dsu-control{min-width:0;display:flex;align-items:center;gap:8px}\n.dsu-fieldWide{grid-template-columns:minmax(0,1fr);align-items:start}\n.dsu-fieldWide .dsu-control{width:100%;max-width:720px;margin-top:2px}\n.dsu-help{display:inline-flex;align-items:center;gap:6px;min-width:0}\n.dsu-helpBtn{appearance:none;border:0;background:transparent;padding:0;width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center;color:var(--dsw-alias-label-tertiary);cursor:help;border-radius:50%;flex:none}\n.dsu-help:hover .dsu-helpBtn,.dsu-helpBtn:focus-visible{color:var(--dsw-alias-label-primary)}\n.dsu-helpBtn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}\n.dsu-tip{position:fixed;z-index:60;box-sizing:border-box;max-width:min(340px,calc(100vw - 16px));max-height:calc(100vh - 16px);overflow:auto;overflow-wrap:anywhere;padding:10px 12px;border-radius:10px;background:var(--dsw-alias-bg-layer-2);border:.5px solid var(--dsw-alias-border-l3);box-shadow:0 12px 32px rgb(0 0 0 / 45%);font-size:12px;line-height:1.6;font-weight:400;color:var(--dsw-alias-label-secondary)}\n.dsu-input{width:100%;height:34px;padding:0 12px;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px}\n.dsu-input:focus-visible{outline:none;border-color:var(--dsw-alias-state-business-primary)}\n.dsu-input[aria-invalid=\"true\"]{border-color:var(--dsw-alias-state-error-primary)}\n.dsu-input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}\n.dsu-input::placeholder{color:var(--dsw-alias-label-tertiary)}\n.dsu-textarea{height:auto;min-height:96px;padding:8px 12px;line-height:1.6;resize:vertical}\n.dsu-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}\n.dsu-numberWrap{display:flex;flex-direction:column;gap:4px;width:100%;min-width:0}\n.dsu-number{display:flex;align-items:center;gap:8px;min-width:0}\n.dsu-number .dsu-input{min-width:0}\n.dsu-unit{flex:none;font-size:12px;color:var(--dsw-alias-label-tertiary)}\n.dsu-error{margin:0;font-size:12px;line-height:1.5;color:var(--dsw-alias-state-error-primary)}\n.dsu-switch{appearance:none;width:36px;height:20px;border-radius:999px;border:0;padding:2px;background:var(--dsw-alias-border-l3);display:flex;align-items:center;cursor:pointer;flex:none;transition:background-color .16s}\n.dsu-knob{width:16px;height:16px;border-radius:50%;background:var(--dsw-alias-label-primary);transition:transform .16s,background-color .16s}\n.dsu-switch[aria-checked=\"true\"]{background:var(--dsw-alias-label-primary)}\n.dsu-switch[aria-checked=\"true\"] .dsu-knob{transform:translateX(16px);background:var(--dsw-alias-label-primary-foreground)}\n.dsu-switch:disabled{opacity:.4;cursor:not-allowed}\n.dsu-switch:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}\n.dsu-selectWrap{position:relative;width:100%;min-width:0}\n.dsu-select{display:flex;align-items:center;justify-content:space-between;gap:8px;text-align:left;cursor:pointer}\n.dsu-select[aria-expanded=\"true\"]{border-color:var(--dsw-alias-state-business-primary)}\n.dsu-selectValue{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dsu-chevron{flex:none;color:var(--dsw-alias-label-tertiary);transition:transform .16s}\n.dsu-select[aria-expanded=\"true\"] .dsu-chevron{transform:rotate(180deg)}\n.dsu-menu{position:fixed;position-area:block-end span-inline-start;justify-self:start;margin-top:6px;z-index:70;padding:4px;background:var(--dsw-alias-bg-layer-2);border:.5px solid var(--dsw-alias-border-l3);border-radius:12px;box-shadow:0 12px 32px rgb(0 0 0 / 50%);max-height:280px;overflow:auto}\n.dsu-option{appearance:none;border:0;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:1.4;width:100%;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 10px;border-radius:8px;cursor:pointer;text-align:left}\n.dsu-option:hover,.dsu-option[data-active=\"true\"]{background:var(--dsw-alias-bg-layer-3)}\n.dsu-option:disabled{color:var(--dsw-alias-label-tertiary);cursor:not-allowed}\n.dsu-option:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px}\n.dsu-optionGroup{padding:6px 10px 2px;font-size:11px;font-weight:600;color:var(--dsw-alias-label-tertiary)}\n.dsu-check{opacity:0;flex:none}\n.dsu-option[aria-selected=\"true\"] .dsu-check{opacity:1}\n.dsu-savebar{display:flex;align-items:center;gap:8px;padding:12px 0;margin-top:24px;border-top:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base)}\n.dsu-savebar[data-dirty=\"true\"]{position:sticky;bottom:0;z-index:2;box-shadow:0 -12px 24px rgb(0 0 0 / 35%)}\n.dsu-btn{appearance:none;border:.5px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:1.5;border-radius:var(--dsw-radius-md);padding:5px 14px;cursor:pointer;transition:background-color .12s,border-color .12s,color .12s,filter .12s}\n.dsu-btn:hover:not(:disabled){background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-border-l3)}\n.dsu-btn:active:not(:disabled){background:var(--dsw-alias-bg-layer-1)}\n.dsu-btn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}\n.dsu-btn:disabled{opacity:.4;cursor:not-allowed}\n.dsu-btnPrimary{background:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}\n.dsu-btnPrimary:hover:not(:disabled){background:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-primary);filter:brightness(.9)}\n.dsu-btnPrimary:active:not(:disabled){background:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-primary);filter:brightness(.84)}\n.dsu-btnDanger{color:var(--dsw-alias-state-error-primary)}\n.dsu-btnDanger:hover:not(:disabled){color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-bg-layer-2)}\n.dsu-status{margin-left:auto;font-size:12px;color:var(--dsw-alias-label-tertiary)}\n.dsu-statusError{color:var(--dsw-alias-state-error-primary)}\n.dsu-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(200px,100%),1fr));gap:0 24px}\n.dsu-grid>.dsu-field{display:flex;flex-direction:column;align-items:stretch;gap:6px;padding:10px 0;border-top:.5px solid var(--dsw-alias-border-l1)}\n.dsu-grid>.dsu-field .dsu-control{width:100%}\n@media (max-width:640px){\n .dsu-field{grid-template-columns:minmax(0,1fr);align-items:start}\n .dsu-control{width:100%;max-width:720px}\n .dsu-section{margin-top:20px;padding-top:20px}\n}\n@media (prefers-reduced-motion:reduce){\n .dsu-switch,.dsu-knob,.dsu-chevron,.dsu-btn{transition:none}\n}\n";
@@ -0,0 +1,10 @@
1
+ export declare const name = "@jayyuen66/dsh-plugin-shared";
2
+ /** 客户端行只提供组件与工具函数;这个入口只让 Cordis 客户端把行当作插件装载。 */
3
+ export declare function apply(): void;
4
+ export { CARD_UI_CSS, CardForm, Field, FieldGrid, FieldLabel, InfoTip, ListField, NumberField, SaveBar, Section, SelectField, StatusBar, TextField, ToggleField, splitHint, } from "./card-ui.js";
5
+ export type { FieldBase, SelectOption } from "./card-ui.js";
6
+ export { diffTouched } from "./card-diff.js";
7
+ export { claimApply } from "./card-apply.js";
8
+ export { fieldOf, isRecord } from "./record.js";
9
+ export { errorText } from "./errors.js";
10
+ export type { MessagesCatalog } from "./locale.js";
@@ -41,7 +41,7 @@ export declare const OFF_JUSTIFICATIONS: Record<string, OffJustification>;
41
41
  * override 层的 off(这个测量方法见本文件头),所以一条规则可以同时是「TS 侧零命中、保持开启」
42
42
  * 与「`scripts/` 的无类型 .mjs 里有命中、按文体收窄」——`eslint/no-continue` 正是这一类,
43
43
  * 它的收窄在 SCRIPTS_OVERRIDES 里,不在这里。`eslint/no-await-in-loop` 则两侧都开着
44
- * (实测探针对 .mjs 照样报),两边都按代码写到位,没有收窄层。
44
+ * (实测探测对 .mjs 照样报),两边都按代码写到位,没有收窄层。
45
45
  */
46
46
  export declare const RETIRED_OFFS: string[];
47
47
  export declare const READONLY_SYNC_ALLOWLIST: string[];
@@ -88,7 +88,7 @@ export declare function resolveBundledJsPlugins(callerPlugins: NonNullable<Oxlin
88
88
  /**
89
89
  * `eslint-plugin-regexp` recommended 里带 `regexp/` 前缀的全部规则(63 条)。
90
90
  *
91
- * 不带它同 preset 的 4 条裸 eslint 规则(no-control-regex / no-misleading-character-class /
91
+ * 不带它同 preset 的 4 条不带插件前缀的 eslint 规则(no-control-regex / no-misleading-character-class /
92
92
  * no-regex-spaces / prefer-regex-literals):oxlint 的内建 eslint 插件已有同名规则,重复挂只会
93
93
  * 把同一个缺陷报两遍。
94
94
  *
@@ -110,10 +110,10 @@ export declare const REGEXP_RULES: RuleTable;
110
110
  * - `no-number-schema-with-int` 5 条(`z.number().int()` → `z.int()`,fixer 可修)。
111
111
  * - `require-error-message` 5 条待按代码补错误文案。
112
112
  * - `consistent-schema-var-name` 71 条**不挂**:本仓的 schema 常量是大写词(`MAX_DENIES_SCHEMA`、
113
- * `STATS_SNAPSHOT_SCHEMA`),规则的默认口径是把 `Schema` 后缀再拼一次,得到
113
+ * `STATS_SNAPSHOT_SCHEMA`),规则的默认做法是把 `Schema` 后缀再拼一次,得到
114
114
  * `MAX_DENIES_SCHEMASchema` 这类坏名字;把它当命名缺陷改 71 处只是风格迁移,不指向缺陷。
115
115
  *
116
- * 该插件只对真的 import zod 的文件生效;本仓九个包都声明了 zod,规则面不会空转。
116
+ * 该插件只对真的 import zod 的文件生效;本仓九个包都声明了 zod,这些规则不会没有实际校验作用。
117
117
  */
118
118
  export declare const ZOD_RULES: RuleTable;
119
119
  /**
@@ -160,7 +160,7 @@ export declare const BASE_RULES: RuleTable;
160
160
  */
161
161
  export declare const TEST_OVERRIDES: OxlintOverride;
162
162
  /**
163
- * 生产代码面的 override:目前只有 `e18e/prefer-static-regex`。
163
+ * 针对生产代码的 override:目前只有 `e18e/prefer-static-regex`。
164
164
  *
165
165
  * 该规则在全仓 1778 条(生产 78、测试 1672、其余 28),没有 fixer;全局 off、这里 on,
166
166
  * 既保住「生产代码里的内联正则提到模块作用域」这条要求,又不把测试断言与构建脚本逼成
@@ -18,7 +18,7 @@ type CoverageOverride = Omit<Partial<CoverageConfig>, "include">;
18
18
  export interface PackageVitestOptions {
19
19
  /** `coverage.include` —— 本包该被统计的源文件(各包只有这里不同);空数组/空串在工厂即抛。 */
20
20
  coverageInclude: string[];
21
- /** 覆盖率覆盖项:逐键合并到公共面。要例外就在这里写,不要在 `test` 里塞 `coverage`。 */
21
+ /** 覆盖率覆盖项:逐键合并到公共配置。要例外就在这里写,不要在 `test` 里塞 `coverage`。 */
22
22
  coverage?: CoverageOverride;
23
23
  /** 追加/覆盖 test 字段(少用;出现即应在包内配置里写明为什么)。 */
24
24
  test?: PackageConfig["test"];
@@ -0,0 +1,45 @@
1
+ /** 预转换的入参。 */
2
+ export interface DecoratorLoweringOptions {
3
+ /** tsc 入口脚本的绝对路径(用 `process.execPath` 跑它,跨平台且不经 PATH / npx)。 */
4
+ readonly tscEntry: string;
5
+ }
6
+ /**
7
+ * 这个文件需要预转换吗(声明文件、后缀与装饰器形状三道筛)。
8
+ * @param id - 模块 id(可能带 query,调用方负责剥)
9
+ * @param code - 源文本
10
+ * @returns 需要预转换时为真
11
+ */
12
+ export declare function needsDecoratorLowering(id: string, code: string): boolean;
13
+ /** 源映射形状(`mappings` 是逐行映射那一串,可选)。 */
14
+ interface SourceMapText {
15
+ sources?: string[];
16
+ sourcesContent?: string[];
17
+ mappings?: string;
18
+ }
19
+ /** tsc 产物与源映射(`map` 为 null 表示源映射缺席,不算致命)。 */
20
+ export interface LoweredDecorators {
21
+ readonly code: string;
22
+ readonly map: SourceMapText | null;
23
+ }
24
+ /**
25
+ * 把一个带装饰器的 TS 文件编译成 JS。
26
+ * @param code - 源文本(只进源映射的 `sourcesContent`;编译交给 tsc 读盘上的原文)
27
+ * @param file - 源文件的**绝对路径**(tsc 按它定位产物名)
28
+ * @param options - tsc 入口
29
+ * @param coverageHints - 把注入的调用从源映射里摘掉(只有测试流水线要,见上)
30
+ * @returns 编译后的代码与源映射
31
+ */
32
+ export declare function lowerStandardDecorators(code: string, file: string, options: DecoratorLoweringOptions, coverageHints?: boolean): LoweredDecorators;
33
+ /** rolldown 插件:在它的解析器看到源码之前把标准装饰器编译掉。 */
34
+ export declare function rolldownDecorators(options: DecoratorLoweringOptions): {
35
+ readonly name: string;
36
+ readonly transform: (code: string, id: string) => LoweredDecorators | null;
37
+ };
38
+ /** Vite 插件(测试流水线):与上面同源,只是挂到 Vite 的钩子上(`enforce: "pre"` 保证在它前面)。
39
+ * 第三个实参 = 覆盖率提示:**只有测试流水线要**(构建产物的字节不该带它,见 pruneInjectedPlumbing)。 */
40
+ export declare function viteDecorators(options: DecoratorLoweringOptions): {
41
+ readonly name: string;
42
+ readonly enforce: "pre";
43
+ readonly transform: (code: string, id: string) => LoweredDecorators | undefined;
44
+ };
45
+ export {};
@@ -6,7 +6,7 @@
6
6
  * - `0` 与负数**照样收缩**到 ≤2 行为止——「0 = 永不截断」是某消费方在**调用前**
7
7
  * `maxBytes > 0` 那道触发策略的承诺,不是本函数的语义(见它自己的 jsonl-fuse 头注)。
8
8
  * 把 0 当成「不裁」会把这个承诺写成一个假象。
9
- * - `NaN` 与 `+Infinity` 让 `字节数 > maxBytes` 恒假 ⇒ 循环一次都不进,整份原样返回,
9
+ * - `NaN` 与 `+Infinity` 让 `字节数 > maxBytes` 永远不成立 ⇒ 循环一次都不进,整份原样返回,
10
10
  * 即**静默关掉收缩**。现存两个消费方都不会把这种值传进来:一个用固定常量作默认实参,
11
11
  另一个在调用前就把非有限值与负数归一成 0。但那道归一在**消费方**,本包并不强制——
12
12
  新增消费方时没有任何东西会提醒它。
@@ -0,0 +1,14 @@
1
+ /**
2
+ * 把 {@link Remote} 的标记程序化地打到 `prototype[methodName]` 上。
3
+ *
4
+ * 官方 `Remote` 的运行时只读 `name` / `private` / `static` 与 `addInitializer`(TC39 的
5
+ * `access` 与 `metadata` 它一概不读),故这里只给这四位到底。初始器只做
6
+ * `Object.getPrototypeOf(this)` 后落标记,所以用原型造一枚替身实例即可。
7
+ *
8
+ * `Reflect.apply` 让装饰器工厂保持未类型化的调用签名 —— `Remote(name)` 的类型是
9
+ * `RemoteMethodDecorator`,它要求第二个参数是真 `ClassMethodDecoratorContext`,而这里喂的是
10
+ * 同形状的手写对象(平台类型不可构造)。
11
+ * @param prototype - 目标类原型(`X.prototype`)
12
+ * @param methodName - 要标记的实例方法名
13
+ */
14
+ export declare function markRemote(prototype: object, methodName: string): void;
@@ -11,11 +11,11 @@ export interface PtcDispatchStartEventData {
11
11
  name: string;
12
12
  arguments: unknown;
13
13
  }
14
- /** 一枚 PTC 子调度**结算**时记下的载荷:结算面沿用 `tool/result` 自己的词表。 */
14
+ /** 一枚 PTC 子调度**结算**时记下的载荷:结算沿用 `tool/result` 自己的词表。 */
15
15
  export interface PtcDispatchEventData extends PtcDispatchStartEventData {
16
16
  isError: boolean;
17
17
  content: ContentBlock[];
18
- /** 可重放的工具侧呈现元数据,与模型可见内容分开记账。 */
18
+ /** 可重放的工具侧呈现元数据,与模型可见内容分开记录。 */
19
19
  meta?: JsonValue;
20
20
  /** 可选的失败身份与原始用户可见细节,不在模型可见内容里。 */
21
21
  error?: {
@@ -48,7 +48,7 @@ export interface ToolCallRecord {
48
48
  * 只读判定、检查侧的 EDIT_TOOLS 与 refSearchTools 名单——而 editPathOf 的回退分支会把任何
49
49
  * 非 str_replace_editor 的调用一律判成 write。无名调用一旦进了记录,只要它的 arguments
50
50
  * 里有 file_path 就算成写操作。现在是靠三个消费方各自记得先判一次才没出事——那是同一条
51
- * 不变式的三份手抄,漏一份就出事。
51
+ * 不变式的三份抄本,漏一份就出事。
52
52
  *
53
53
  * 与 callId 的差别是**为什么一个必选、一个可空**:callId 由 usableCallId 回退,且它有
54
54
  * `nc:<seq>` 回退值(消费方的 noCallId 组专门收那种行),缺了不影响归类;name 一旦缺了
@@ -115,8 +115,29 @@ export type EditTarget = {
115
115
  readonly kind: "read-view";
116
116
  readonly path: string | undefined;
117
117
  };
118
+ /**
119
+ * 一条 `apply_patch` 补丁操作的目标。`moveTo` 只出现在 update 上;源路径与目的路径
120
+ * 都是文件效应,调用方需要分别记录。
121
+ */
122
+ export interface ApplyPatchTarget {
123
+ readonly kind: "add" | "update" | "delete";
124
+ readonly path: string;
125
+ readonly moveTo?: string;
126
+ }
127
+ /**
128
+ * 从 `apply_patch` 的 `{ input }` 解析有序操作。解析器是官方 `dsh-fs-patch` 的同一份
129
+ * `parsePatch`:host 执行什么语法,这里就认什么,不另写一套会与宿主漂移的补丁文法。
130
+ * 非补丁输入、或宿主解析器拒绝的补丁一律交回空数组;调用方按工具名决定是否 fail-closed。
131
+ */
132
+ export declare function applyPatchTargetsOf(args: Record<string, unknown> | undefined | null): readonly ApplyPatchTarget[];
118
133
  /**
119
134
  * 由 tool/call 记录推导被编辑的文件路径;str_replace_editor 的 view 只读不算写。
135
+ * `apply_patch` 取第一条操作路径,多目标调用请走 {@link editPathsOf}。
120
136
  * @returns `write` = 写操作;`read-view` = 只读视图。取不到路径时 `path` 为 `undefined`。
121
137
  */
122
138
  export declare function editPathOf(call: ToolCallRecord): EditTarget;
139
+ /**
140
+ * 一次 tool/call 的全部写目标(去重、保持补丁顺序)。`apply_patch` 的 move 同时交回
141
+ * 源路径与目的路径:前者被删除、后者被创建,两处都必须能被下游看见。
142
+ */
143
+ export declare function editPathsOf(call: ToolCallRecord): readonly string[];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jayyuen66/dsh-plugin-shared",
3
- "version": "0.2.3",
4
- "description": "dsh 自研插件的共享工具库:tool 事件流记账扫描 + 卡片 apply/差异骨架 + 统一设置卡 UI 组件 + 官方作业结局映射 + 项目键派生 + 代理对安全截断。作为库包被 import,不由用户启用",
3
+ "version": "0.2.5",
4
+ "description": "dsh 自研插件的共享工具库:tool 事件流记账扫描 + 卡片 apply/差异骨架 + 统一设置卡 UI 组件 + 官方作业结局映射 + 项目键派生 + 代理对安全截断。宿主半由各插件 import;客户端半以 ./client 共享行由插件 patch 启用,不由用户单独停用",
5
5
  "keywords": [
6
6
  "cordis",
7
7
  "dsh",
@@ -27,12 +27,22 @@
27
27
  ],
28
28
  "type": "module",
29
29
  "sideEffects": false,
30
- "main": "./dist/index.js",
30
+ "main": "./dist/plugin.js",
31
31
  "types": "./dist/index.d.ts",
32
32
  "exports": {
33
33
  ".": {
34
34
  "types": "./dist/index.d.ts",
35
- "default": "./dist/index.js"
35
+ "default": "./dist/plugin.js"
36
+ },
37
+ "./client": {
38
+ "types": "./dist/types/client-entry.d.ts",
39
+ "node": "./dist/client-entry.js",
40
+ "import": "./dist/client-entry.js",
41
+ "default": "./dist/client.js"
42
+ },
43
+ "./client-node": {
44
+ "types": "./dist/types/client-entry.d.ts",
45
+ "default": "./dist/client-entry.js"
36
46
  },
37
47
  "./lib/tool-events": {
38
48
  "types": "./dist/types/tool-events.d.ts",
@@ -82,6 +92,10 @@
82
92
  "types": "./dist/types/job-outcome.d.ts",
83
93
  "default": "./dist/job-outcome.js"
84
94
  },
95
+ "./lib/remote-marker": {
96
+ "types": "./dist/types/remote-marker.d.ts",
97
+ "default": "./dist/remote-marker.js"
98
+ },
85
99
  "./lib/canonicalize-region-paths": {
86
100
  "types": "./dist/types/canonicalize-region-paths.d.ts",
87
101
  "default": "./dist/canonicalize-region-paths.js"
@@ -102,6 +116,10 @@
102
116
  "types": "./dist/types/build-types.d.ts",
103
117
  "default": "./dist/build/build-types.js"
104
118
  },
119
+ "./lib/decorator-lowering": {
120
+ "types": "./dist/types/decorator-lowering.d.ts",
121
+ "default": "./dist/build/decorator-lowering.js"
122
+ },
105
123
  "./config/oxlint": {
106
124
  "types": "./dist/types/config/oxlint.base.d.ts",
107
125
  "default": "./dist/config/oxlint.base.js"
@@ -118,48 +136,54 @@
118
136
  "access": "public",
119
137
  "registry": "https://registry.npmjs.org"
120
138
  },
139
+ "dependencies": {
140
+ "@deepseek-ai/dsh-fs-patch": "0.2.2-rc.2"
141
+ },
121
142
  "devDependencies": {
122
- "@deepseek-ai/cordis": "4.0.6-alpha.2",
123
- "@deepseek-ai/dsh-brand": "0.2.2-alpha.3",
124
- "@deepseek-ai/dsh-client-locale": "0.2.2-alpha.3",
125
- "@deepseek-ai/dsh-jobs": "0.2.2-alpha.3",
126
- "@deepseek-ai/dsh-llm": "0.2.2-alpha.3",
127
- "@deepseek-ai/dsh-output-retention": "0.2.2-alpha.3",
128
- "@deepseek-ai/dsh-scope": "0.2.2-alpha.3",
129
- "@deepseek-ai/dsh-session": "0.2.2-alpha.3",
130
- "@deepseek-ai/dsh-shell": "0.2.2-alpha.3",
131
- "@deepseek-ai/dsh-tool-executor-ptc": "0.2.2-alpha.3",
132
- "@deepseek-ai/dsh-tools": "0.2.2-alpha.3",
133
- "@deepseek-ai/dsh-util-values": "0.2.2-alpha.3",
143
+ "@deepseek-ai/cordis": "4.1.0",
144
+ "@deepseek-ai/dsh-brand": "0.2.2-rc.2",
145
+ "@deepseek-ai/dsh-client-locale": "0.2.2-rc.2",
146
+ "@deepseek-ai/dsh-error": "0.2.2-rc.2",
147
+ "@deepseek-ai/dsh-jobs": "0.2.2-rc.2",
148
+ "@deepseek-ai/dsh-llm": "0.2.2-rc.2",
149
+ "@deepseek-ai/dsh-output-retention": "0.2.2-rc.2",
150
+ "@deepseek-ai/dsh-scope": "0.2.2-rc.2",
151
+ "@deepseek-ai/dsh-session": "0.2.2-rc.2",
152
+ "@deepseek-ai/dsh-shell": "0.2.2-rc.2",
153
+ "@deepseek-ai/dsh-tool-executor-ptc": "0.2.2-rc.2",
154
+ "@deepseek-ai/dsh-tools": "0.2.2-rc.2",
155
+ "@deepseek-ai/dsh-typert-protocol": "0.2.2-rc.2",
156
+ "@deepseek-ai/dsh-util-values": "0.2.2-rc.2",
134
157
  "@e18e/eslint-plugin": "0.8.1",
135
158
  "@types/node": "26.6.6",
136
159
  "@types/react": "19.3.0",
137
160
  "@types/react-dom": "19.3.0",
138
- "@vitest/coverage-v8": "5.0.5",
139
- "eslint-plugin-regexp": "3.3.2",
161
+ "@vitest/coverage-v8": "5.1.0",
162
+ "eslint-plugin-regexp": "3.3.3",
140
163
  "eslint-plugin-sonarjs": "4.2.2",
141
164
  "eslint-plugin-zod": "5.2.2",
142
165
  "fast-check": "4.10.2",
143
166
  "happy-dom": "21.0.4",
144
- "oxfmt": "0.75.0",
145
- "oxlint": "1.90.0",
146
- "oxlint-tsgolint": "7.0.2005",
167
+ "oxfmt": "0.78.0",
168
+ "oxlint": "1.93.0",
169
+ "oxlint-tsgolint": "7.0.2006",
147
170
  "react": "^19.3.0",
148
171
  "react-dom": "^19.3.1",
149
- "rolldown": "1.2.15",
172
+ "rolldown": "1.3.2",
150
173
  "typescript": "7.0.2",
151
- "vite": "8.3.5",
152
- "vitest": "5.0.5"
174
+ "vite": "8.3.8",
175
+ "vitest": "5.1.0"
153
176
  },
154
177
  "peerDependencies": {
155
178
  "@deepseek-ai/cordis": "^4.0.5||^4.0.6-alpha.1",
156
- "@deepseek-ai/dsh": "^0.2.1-rc.3 || ^0.2.2-alpha.2",
157
- "@deepseek-ai/dsh-client-locale": "^0.2.1-rc.3 || ^0.2.2-alpha.2",
158
- "@deepseek-ai/dsh-jobs": "^0.2.1-rc.3 || ^0.2.2-alpha.2",
159
- "@deepseek-ai/dsh-output-retention": "^0.2.1-rc.3 || ^0.2.2-alpha.2",
160
- "@deepseek-ai/dsh-session": "^0.2.1-rc.3 || ^0.2.2-alpha.2",
161
- "@deepseek-ai/dsh-shell": "^0.2.1-rc.3 || ^0.2.2-alpha.2",
162
- "@deepseek-ai/dsh-tools": "^0.2.1-rc.3 || ^0.2.2-alpha.2",
179
+ "@deepseek-ai/dsh": "^0.2.2-rc.1",
180
+ "@deepseek-ai/dsh-client-locale": "^0.2.2-rc.1",
181
+ "@deepseek-ai/dsh-jobs": "^0.2.2-rc.1",
182
+ "@deepseek-ai/dsh-output-retention": "^0.2.2-rc.1",
183
+ "@deepseek-ai/dsh-session": "^0.2.2-rc.1",
184
+ "@deepseek-ai/dsh-shell": "^0.2.2-rc.1",
185
+ "@deepseek-ai/dsh-tools": "^0.2.2-rc.1",
186
+ "@deepseek-ai/dsh-typert-protocol": "^0.2.2-rc.1",
163
187
  "react": "^19.3.0"
164
188
  },
165
189
  "peerDependenciesMeta": {
@@ -187,18 +211,28 @@
187
211
  "@deepseek-ai/dsh-tools": {
188
212
  "optional": true
189
213
  },
214
+ "@deepseek-ai/dsh-typert-protocol": {
215
+ "optional": true
216
+ },
190
217
  "react": {
191
218
  "optional": true
192
219
  }
193
220
  },
194
221
  "icon": "icon.svg",
195
222
  "engines": {
196
- "dsh": "^0.2.1-rc.3 || ^0.2.2-alpha.2",
197
- "node": ">=22.12.0"
223
+ "dsh": "^0.2.2-rc.1",
224
+ "node": ">=24.9.0"
225
+ },
226
+ "dsh": {
227
+ "client": {
228
+ "platform": "web",
229
+ "immediately": true
230
+ }
198
231
  },
199
232
  "scripts": {
200
233
  "prebuild": "node build-clean.mjs",
201
- "build": "node build-host.mjs && node build-config.mjs && tsc -p tsconfig.build.json && tsc -p tsconfig.build.config.json && node build-types-check.mjs",
234
+ "build": "node build-host.mjs && node build-config.mjs && tsc -p tsconfig.build.json && tsc -p tsconfig.build.config.json && node build-types-check.mjs && node build-client.mjs",
235
+ "build:client": "node build-client.mjs",
202
236
  "typecheck": "tsc --noEmit -p tsconfig.json",
203
237
  "lint": "oxlint .",
204
238
  "test": "vitest run --coverage",