@whispering233/ai-editor-shared 0.0.57 → 0.0.58

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.
Files changed (47) hide show
  1. package/dist/authors/catalog.d.ts +14 -0
  2. package/dist/authors/catalog.d.ts.map +1 -0
  3. package/dist/authors/catalog.js +23 -0
  4. package/dist/authors/catalog.js.map +1 -0
  5. package/dist/authors/index.d.ts +4 -0
  6. package/dist/authors/index.d.ts.map +1 -0
  7. package/dist/authors/index.js +6 -0
  8. package/dist/authors/index.js.map +1 -0
  9. package/dist/authors/jiangnan.d.ts +3 -0
  10. package/dist/authors/jiangnan.d.ts.map +1 -0
  11. package/dist/authors/jiangnan.js +93 -0
  12. package/dist/authors/jiangnan.js.map +1 -0
  13. package/dist/authors/types.d.ts +18 -0
  14. package/dist/authors/types.d.ts.map +1 -0
  15. package/dist/authors/types.js +2 -0
  16. package/dist/authors/types.js.map +1 -0
  17. package/dist/constants/index.d.ts +2 -0
  18. package/dist/constants/index.d.ts.map +1 -1
  19. package/dist/constants/index.js +3 -1
  20. package/dist/constants/index.js.map +1 -1
  21. package/dist/constants/practice.d.ts +15 -0
  22. package/dist/constants/practice.d.ts.map +1 -0
  23. package/dist/constants/practice.js +21 -0
  24. package/dist/constants/practice.js.map +1 -0
  25. package/dist/constants/tool.d.ts +37 -2
  26. package/dist/constants/tool.d.ts.map +1 -1
  27. package/dist/constants/tool.js +58 -3
  28. package/dist/constants/tool.js.map +1 -1
  29. package/dist/constants/workspace.d.ts +22 -0
  30. package/dist/constants/workspace.d.ts.map +1 -0
  31. package/dist/constants/workspace.js +33 -0
  32. package/dist/constants/workspace.js.map +1 -0
  33. package/dist/index.d.ts +1 -0
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +1 -0
  36. package/dist/index.js.map +1 -1
  37. package/dist/types/api.d.ts +201 -1
  38. package/dist/types/api.d.ts.map +1 -1
  39. package/dist/types/api.js +174 -2
  40. package/dist/types/api.js.map +1 -1
  41. package/dist/types/project.d.ts +25 -0
  42. package/dist/types/project.d.ts.map +1 -1
  43. package/dist/utils/mapping.d.ts +3 -3
  44. package/dist/utils/mapping.d.ts.map +1 -1
  45. package/dist/utils/mapping.js +9 -3
  46. package/dist/utils/mapping.js.map +1 -1
  47. package/package.json +1 -1
@@ -0,0 +1,14 @@
1
+ import type { AuthorEntry, AuthorId, PracticeWork } from "./types.js";
2
+ /** 「其他」兜底文案:作品 id 未选 / 未知(预置被移除)时用;唯一定义处,客户端与服务端都取它 */
3
+ export declare const PRACTICE_OTHER_WORK_LABEL = "\u5176\u4ED6";
4
+ /** `satisfies` 而非类型标注:保住字面量键 ⇒ `AuthorId` 是 id 联合而非 `string` */
5
+ export declare const AUTHOR_CATALOG: {
6
+ jiangnan: AuthorEntry;
7
+ };
8
+ /** 全部预置作家 id(顺序 = 清单声明顺序;根首页练习分区按它排) */
9
+ export declare const AUTHOR_IDS: AuthorId[];
10
+ /** 按 id 解析预置作家:未知值 / 非字符串 / 原型键 → null(不做名字认领) */
11
+ export declare function resolveAuthor(value: unknown): AuthorEntry | null;
12
+ /** 按作家 id + 作品 id 解析作品:跨作者、未知 id 一律 null(列表按「其他」渲染) */
13
+ export declare function resolveWork(authorId: string, workId: string): PracticeWork | null;
14
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/authors/catalog.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAGtE,uDAAuD;AACvD,eAAO,MAAM,yBAAyB,iBAAO,CAAC;AAE9C,gEAAgE;AAChE,eAAO,MAAM,cAAc;;CAEY,CAAC;AAExC,wCAAwC;AACxC,eAAO,MAAM,UAAU,EAAkC,QAAQ,EAAE,CAAC;AAEpE,kDAAkD;AAClD,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,IAAI,CAGhE;AAED,uDAAuD;AACvD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAIjF"}
@@ -0,0 +1,23 @@
1
+ import { JIANGNAN } from "./jiangnan.js";
2
+ /** 「其他」兜底文案:作品 id 未选 / 未知(预置被移除)时用;唯一定义处,客户端与服务端都取它 */
3
+ export const PRACTICE_OTHER_WORK_LABEL = "其他";
4
+ /** `satisfies` 而非类型标注:保住字面量键 ⇒ `AuthorId` 是 id 联合而非 `string` */
5
+ export const AUTHOR_CATALOG = {
6
+ jiangnan: JIANGNAN,
7
+ };
8
+ /** 全部预置作家 id(顺序 = 清单声明顺序;根首页练习分区按它排) */
9
+ export const AUTHOR_IDS = Object.keys(AUTHOR_CATALOG);
10
+ /** 按 id 解析预置作家:未知值 / 非字符串 / 原型键 → null(不做名字认领) */
11
+ export function resolveAuthor(value) {
12
+ if (typeof value !== "string" || !Object.hasOwn(AUTHOR_CATALOG, value))
13
+ return null;
14
+ return AUTHOR_CATALOG[value] ?? null;
15
+ }
16
+ /** 按作家 id + 作品 id 解析作品:跨作者、未知 id 一律 null(列表按「其他」渲染) */
17
+ export function resolveWork(authorId, workId) {
18
+ const author = resolveAuthor(authorId);
19
+ if (author === null)
20
+ return null;
21
+ return author.works.find((work) => work.id === workId) ?? null;
22
+ }
23
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/authors/catalog.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,uDAAuD;AACvD,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,CAAC;AAE9C,gEAAgE;AAChE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,QAAQ,EAAE,QAAQ;CACmB,CAAC;AAExC,wCAAwC;AACxC,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAe,CAAC;AAEpE,kDAAkD;AAClD,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpF,OAAQ,cAA8C,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;AACxE,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,WAAW,CAAC,QAAgB,EAAE,MAAc;IAC1D,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC;AACjE,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from "./types.js";
2
+ export * from "./jiangnan.js";
3
+ export * from "./catalog.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/authors/index.ts"],"names":[],"mappings":"AAEA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,6 @@
1
+ // 预置作家素材聚合出口(作家介绍 / 作品清单 / 风格说明):
2
+ // 客户端页面与服务端 AI 侧读同一份常量(理由见 `docs/design/60-practice.md` §3)
3
+ export * from "./types.js";
4
+ export * from "./jiangnan.js";
5
+ export * from "./catalog.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/authors/index.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,4DAA4D;AAC5D,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AuthorEntry } from "./types.js";
2
+ export declare const JIANGNAN: AuthorEntry;
3
+ //# sourceMappingURL=jiangnan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jiangnan.d.ts","sourceRoot":"","sources":["../../src/authors/jiangnan.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,eAAO,MAAM,QAAQ,EAAE,WA2FtB,CAAC"}
@@ -0,0 +1,93 @@
1
+ export const JIANGNAN = {
2
+ id: "jiangnan",
3
+ name: "江南",
4
+ intro: `江南,中国当代幻想小说作家,作品横跨校园青春、东方奇幻、近未来科幻与历史演义式长篇。题材换了很多次,反复出现的却是同一类人:有才华、有骄傲、也有一点不服气的少年,被卷进远比他们宏大的局势,然后在失去里长大。他擅长把大开大合的设定压到具体的人身上——战场上有风沙和血,酒桌上有旧账,友情与背叛通常同时发生。他写成长,写得并不爽利:赢的人也在丢东西。他的句子抒情底色浓,情绪浓度高、记忆点强,代价是细节有时服务于情绪,被读者批评过「用力过猛」。对练习者来说,这是一片很好的练笔场:句子可长可短,视角能在战场与少年心事之间来回切换,适合练「如何把宏大设定落到具体的动作、气味和对话上」,也适合练「抒情到什么程度才不过界」。`,
5
+ works: [
6
+ {
7
+ id: "this-youth",
8
+ name: "此间的少年",
9
+ intro: "用武侠人物的名字写大学校园的青春故事,江湖换成了宿舍、球场和食堂。读起来很轻,落点却准:散伙那天才明白,有些人此后不会再见到。",
10
+ },
11
+ {
12
+ id: "novoland-eagle-flag",
13
+ name: "九州缥缈录",
14
+ intro: "东方奇幻长卷,少年被时局推着成为王者。写战场、写权谋、写两个原本并肩的人怎样走到对面;抒情与壮阔在他的长篇里最集中。",
15
+ },
16
+ {
17
+ id: "shanghai-fortress",
18
+ name: "上海堡垒",
19
+ intro: "科幻外壳下的暗恋故事:城市在倒计时,年轻人还在为一条没发出去的消息犹豫。末日是背景板,失落才是主角。",
20
+ },
21
+ {
22
+ id: "dragon-raja",
23
+ name: "龙族",
24
+ intro: "现代都市与神话混在一起的长篇系列:普通人被带进另一个更古老的世界。日常吐槽与悲壮并置,少年感和命运感互相拉扯。",
25
+ },
26
+ {
27
+ id: "zhuolu",
28
+ name: "涿鹿",
29
+ intro: "以远古传说为骨架的历史奇幻,重讲英雄与兄弟相残的旧事。基调比同类作品更沉、更悲,抒情也更直接。",
30
+ },
31
+ {
32
+ id: "assassin-dynasty-aoi",
33
+ name: "刺客王朝·葵",
34
+ intro: "短篇系列,写刺客与少年侍卫的相遇和告别。篇幅小、动作密,适合看他怎样在几千字里把一个人物立起来。",
35
+ },
36
+ {
37
+ id: "emperor-of-light",
38
+ name: "光明皇帝",
39
+ intro: "早期作品,架空东方背景下的奇诡故事。异象降临人间、人被自己的命运选中——后来长篇里的母题在这里已经有形状。",
40
+ },
41
+ {
42
+ id: "dragon-and-youth-travels",
43
+ name: "龙与少年游",
44
+ intro: "散文与随笔结集,谈写作、谈行走、谈年轻时的窘迫与念头。想学他的语气,这本比小说更直白:会看到他怎样解释自己那些抒情。",
45
+ },
46
+ ],
47
+ styleNotes: `# 江南风格说明
48
+
49
+ 按下面六个维度读他的小说,比笼统地「像不像江南」更好用。每一条都给可操作的动作。
50
+
51
+ ## 语言纹理
52
+
53
+ - 词汇偏口语与书面语混用:日常段落里有「吐槽」「哥们儿」这种松弛的词,情绪段落立刻收紧成书面语(「天色」「雪意」「说不出口」)。**转调靠词汇,不靠感叹号**。
54
+ - 动词优先于形容词。写紧张不写「十分紧张」,写「手在袖子里攥着」。
55
+ - 允许自我调侃,但调侃只出现在叙述者离人物较远的句子里;一旦靠近人物内心,玩笑要收。
56
+ - 少用生僻字和古语堆砌。他写东方奇幻,但语句的可读性按当代读者来的。
57
+
58
+ ## 句长与节奏
59
+
60
+ - 长短句交替,比例大致是「三短一长」。短句用来落点(一句一行也常见),长句用来铺铺环境与心绪。
61
+ - 段落常常只有一句。空行 = 情绪换气,不是排版装饰。
62
+ - 抒情段里长句可以套两层从句,但每句只推进一件事,不在一个句子里塞三个动作。
63
+ - 对话段落短、标签少,常靠单独成段的一句台词完成转折。
64
+
65
+ ## 叙述视角与距离
66
+
67
+ - 第三人称限知,贴着主角走;写到群像时换段换视角,但不在一段内部跳。
68
+ - 距离可伸缩:远景铺地势、天气、兵阵,中景写动作过程,近景直接给内心的一句判断。三段之间靠空行和短句切。
69
+ - 内心里最重的部分往往**不给**:让它变成没有寄出的信、没说完的话、回头时已经空了的位置。
70
+ - 大场面里持续盯一个小物件(酒杯、刀鞘、湿了的衣角),用它的不变衬局势的变。
71
+
72
+ ## 意象与用典
73
+
74
+ - 意象取自然物:雪、风、雨、酒、灯火、旧城墙。重复出现时保持同一件东西的同一质感(雪一直是冷的、湿的,不忽然变暖)。
75
+ - 用典点到为止:借一个历史或传说的结构(兄弟、末路英雄、帝王与臣子),不复述整段典故,读者不懂也不影响读。
76
+ - 抒情常落在「时间」上——「很多年以后」「那时候还不知道」。回忆插入要短,两三句就回正题。
77
+
78
+ ## 结构习惯
79
+
80
+ - 先给处境再给人:开篇常用一段场景把世界立住,再让主角进画。
81
+ - 章节收尾习惯留一个悬着的动作或一句短台词,不用总结句。
82
+ - 情感线用「缺席」推进:见面少、消息迟、承诺悬着。
83
+ - 高潮前有一次安静的对谈,把立场摊开;真正的爆发只用几段解决。
84
+
85
+ ## 常见瑕疵(模仿时要警惕的地方)
86
+
87
+ - **抒情过载**:情绪词和排比连用会盖住动作,读者只剩「很悲壮」的感觉。改法 = 删掉一半形容词,补一个具体动作。
88
+ - **设定抢戏**:架空名词、头衔、地名密集出现时,人物会退成背景。改法 = 每段只留一个专有名词,其余用通称。
89
+ - **金句惯性与口号化**:为了一句漂亮的话牺牲人物当时会说的话。改法 = 把那句删掉,看情节是否还能走;能走就别留。
90
+ - **视角越界**:抒情时顺手把别人的心理也交代了。改法 = 收回主角能看到、能推测的范围。
91
+ - **笑点与悲剧打架**:同一段里松弛的吐槽和沉重情绪争夺注意力。改法 = 分段落,别在同段混。`,
92
+ };
93
+ //# sourceMappingURL=jiangnan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jiangnan.js","sourceRoot":"","sources":["../../src/authors/jiangnan.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,QAAQ,GAAgB;IACnC,EAAE,EAAE,UAAU;IACd,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,sTAAsT;IAC7T,KAAK,EAAE;QACL;YACE,EAAE,EAAE,YAAY;YAChB,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,iEAAiE;SACzE;QACD;YACE,EAAE,EAAE,qBAAqB;YACzB,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,4DAA4D;SACpE;QACD;YACE,EAAE,EAAE,mBAAmB;YACvB,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,oDAAoD;SAC5D;QACD;YACE,EAAE,EAAE,aAAa;YACjB,IAAI,EAAE,IAAI;YACV,KAAK,EAAE,yDAAyD;SACjE;QACD;YACE,EAAE,EAAE,QAAQ;YACZ,IAAI,EAAE,IAAI;YACV,KAAK,EAAE,iDAAiD;SACzD;QACD;YACE,EAAE,EAAE,sBAAsB;YAC1B,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,kDAAkD;SAC1D;QACD;YACE,EAAE,EAAE,kBAAkB;YACtB,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,uDAAuD;SAC/D;QACD;YACE,EAAE,EAAE,0BAA0B;YAC9B,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,4DAA4D;SACpE;KACF;IACD,UAAU,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kDA4CoC;CACjD,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { AUTHOR_CATALOG } from "./catalog.js";
2
+ /** 一部预置作品:`id` = 稳定 slug(英文小写连字符,全局唯一),`name` = 中文显示名 */
3
+ export interface PracticeWork {
4
+ id: string;
5
+ name: string;
6
+ intro: string;
7
+ }
8
+ /** 一位预置作家:介绍与风格说明是给人读的 markdown */
9
+ export interface AuthorEntry {
10
+ id: string;
11
+ name: string;
12
+ intro: string;
13
+ works: readonly PracticeWork[];
14
+ styleNotes: string;
15
+ }
16
+ /** 预置作家 id(= 清单键;`工作区 project.json` 的 `author_id` / 素材包主键取它) */
17
+ export type AuthorId = keyof typeof AUTHOR_CATALOG;
18
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/authors/types.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,yDAAyD;AACzD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,mCAAmC;AACnC,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,gEAAgE;AAChE,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,cAAc,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/authors/types.ts"],"names":[],"mappings":""}
@@ -5,4 +5,6 @@ export * from "./outline.js";
5
5
  export * from "./backup.js";
6
6
  export * from "./delta.js";
7
7
  export * from "./ports.js";
8
+ export * from "./workspace.js";
9
+ export * from "./practice.js";
8
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAEA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAEA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC"}
@@ -1,5 +1,5 @@
1
1
  // 常量聚合出口
2
- // 文件划分见 (constants/:entity.ts / hook.ts / tool.ts / outline.ts / backup.ts / delta.ts / ports.ts)
2
+ // 文件划分见 (constants/:entity.ts / hook.ts / tool.ts / outline.ts / backup.ts / delta.ts / ports.ts / workspace.ts / practice.ts)
3
3
  export * from "./entity.js";
4
4
  export * from "./hook.js";
5
5
  export * from "./tool.js";
@@ -7,4 +7,6 @@ export * from "./outline.js";
7
7
  export * from "./backup.js";
8
8
  export * from "./delta.js";
9
9
  export * from "./ports.js";
10
+ export * from "./workspace.js";
11
+ export * from "./practice.js";
10
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,kGAAkG;AAClG,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,+HAA+H;AAC/H,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC"}
@@ -0,0 +1,15 @@
1
+ /** 片段说明(`practice_samples.excerpt_label`)长度上限 */
2
+ export declare const MAX_PRACTICE_EXCERPT_LABEL_CHARS = 100;
3
+ /** 范文快照(`practice_samples.text`)长度上限——样本是整篇范文,不是节选 */
4
+ export declare const MAX_PRACTICE_SAMPLE_CHARS = 100000;
5
+ /** 用户稿件长度上限:仿写稿与自由练习稿(`practice_samples.draft` / `practice_free_pieces.draft`)共用 */
6
+ export declare const MAX_PRACTICE_DRAFT_CHARS = 20000;
7
+ /** 自由练习题目(`practice_free_pieces.topic`)长度上限 */
8
+ export declare const MAX_PRACTICE_TOPIC_CHARS = 100;
9
+ /** 自由练习写作要求(`practice_free_pieces.brief`)长度上限 */
10
+ export declare const MAX_PRACTICE_BRIEF_CHARS = 500;
11
+ /** 风格说明素材包(`practice_style_packs.content`)长度上限——存的是整份风格说明,按长文留足 */
12
+ export declare const MAX_PRACTICE_STYLE_PACK_CHARS = 100000;
13
+ /** 点评卡维度数上限(`feedback.dimensions[]`;工具说明由该常量插值生成) */
14
+ export declare const MAX_FEEDBACK_DIMENSIONS = 6;
15
+ //# sourceMappingURL=practice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"practice.d.ts","sourceRoot":"","sources":["../../src/constants/practice.ts"],"names":[],"mappings":"AAOA,iDAAiD;AACjD,eAAO,MAAM,gCAAgC,MAAM,CAAC;AAEpD,sDAAsD;AACtD,eAAO,MAAM,yBAAyB,SAAS,CAAC;AAEhD,oFAAoF;AACpF,eAAO,MAAM,wBAAwB,QAAQ,CAAC;AAE9C,+CAA+C;AAC/C,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C,iDAAiD;AACjD,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C,mEAAmE;AACnE,eAAO,MAAM,6BAA6B,SAAS,CAAC;AAEpD,qDAAqD;AACrD,eAAO,MAAM,uBAAuB,IAAI,CAAC"}
@@ -0,0 +1,21 @@
1
+ // 文风练习上限常量(2026-10 改版)——唯一定义处
2
+ //
3
+ // 数值单源(AGENTS「数值单源」):REST schema(`docs/api/120-api-practice.md`)与
4
+ // 工具说明插值一律取这里,禁止在 schema 注释 / 散文 / 工具描述里复述数字。
5
+ // 字段语义见 `docs/db/schema.md`「练习三表」与 `docs/design/60-practice.md` §3 / §5。
6
+ // 长度口径 = JS 字符串长度(UTF-16 code unit),与既有文本分页常量同源。
7
+ /** 片段说明(`practice_samples.excerpt_label`)长度上限 */
8
+ export const MAX_PRACTICE_EXCERPT_LABEL_CHARS = 100;
9
+ /** 范文快照(`practice_samples.text`)长度上限——样本是整篇范文,不是节选 */
10
+ export const MAX_PRACTICE_SAMPLE_CHARS = 100000;
11
+ /** 用户稿件长度上限:仿写稿与自由练习稿(`practice_samples.draft` / `practice_free_pieces.draft`)共用 */
12
+ export const MAX_PRACTICE_DRAFT_CHARS = 20000;
13
+ /** 自由练习题目(`practice_free_pieces.topic`)长度上限 */
14
+ export const MAX_PRACTICE_TOPIC_CHARS = 100;
15
+ /** 自由练习写作要求(`practice_free_pieces.brief`)长度上限 */
16
+ export const MAX_PRACTICE_BRIEF_CHARS = 500;
17
+ /** 风格说明素材包(`practice_style_packs.content`)长度上限——存的是整份风格说明,按长文留足 */
18
+ export const MAX_PRACTICE_STYLE_PACK_CHARS = 100000;
19
+ /** 点评卡维度数上限(`feedback.dimensions[]`;工具说明由该常量插值生成) */
20
+ export const MAX_FEEDBACK_DIMENSIONS = 6;
21
+ //# sourceMappingURL=practice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"practice.js","sourceRoot":"","sources":["../../src/constants/practice.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,kEAAkE;AAClE,8CAA8C;AAC9C,yEAAyE;AACzE,iDAAiD;AAEjD,iDAAiD;AACjD,MAAM,CAAC,MAAM,gCAAgC,GAAG,GAAG,CAAC;AAEpD,sDAAsD;AACtD,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAEhD,oFAAoF;AACpF,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAC;AAE9C,+CAA+C;AAC/C,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAE5C,iDAAiD;AACjD,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAE5C,mEAAmE;AACnE,MAAM,CAAC,MAAM,6BAA6B,GAAG,MAAM,CAAC;AAEpD,qDAAqD;AACrD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC"}
@@ -1,3 +1,4 @@
1
+ import type { WorkspaceKind } from "./workspace.js";
1
2
  /**
2
3
  * 工具权限级别(「工具分级」两级:自动 / 提案确认)
3
4
  * 自动:直接执行,结果返回 LLM;提案确认:展示提案卡片,用户审阅确认后再执行
@@ -8,6 +9,26 @@ export declare const TOOL_PERMISSION: {
8
9
  };
9
10
  /** 工具权限级别 */
10
11
  export type ToolPermission = (typeof TOOL_PERMISSION)[keyof typeof TOOL_PERMISSION];
12
+ /**
13
+ * 工具作用域(2026-10):工具归哪个工作区类型可用——`novel` / `practice` 为各自专属,
14
+ * `common` = 两种工作区都注册。装配层按当前工作区 `kind` 过滤(见 `isToolScopeRegistered`),
15
+ * 语义与不变式见 `docs/design/architecture.md`「工作区类型(kind)与能力收窄」。
16
+ */
17
+ export declare const TOOL_SCOPES: readonly ["novel", "practice", "common"];
18
+ /** 工具作用域 */
19
+ export type ToolScope = (typeof TOOL_SCOPES)[number];
20
+ /**
21
+ * 工作区类型 → 允许注册的工具 `scope` 集合(**唯一定义处**):装配层只经
22
+ * `isToolScopeRegistered` 判定,任何消费方(agent / tools / server)不得复写这份映射。
23
+ * 不变式:非小说工作区不注册小说工具与提案工具(结构性边界,靠注册过滤,不靠提示词)。
24
+ */
25
+ export declare const WORKSPACE_TOOL_SCOPES: Record<WorkspaceKind, readonly ToolScope[]>;
26
+ /**
27
+ * 该 `scope` 的工具在指定工作区是否注册——**装配层唯一判定入口**。
28
+ * 未知 `kind`(类型层之外的值,如漏传参数)直接抛错:**不退化为「注册全量」**,
29
+ * 否则收窄会静默失效(工具集按 kind 收窄是结构性边界)。
30
+ */
31
+ export declare function isToolScopeRegistered(kind: WorkspaceKind, scope: ToolScope): boolean;
11
32
  /** 查询类工具(自动,「查询类」):默认过滤软删对象 */
12
33
  export declare const QUERY_TOOLS: readonly ["get_entity", "search_entities", "search_references", "query_relationships", "get_outline", "get_outline_path", "get_deduction_marks", "get_chapter_text", "compute_state", "get_delta_history", "get_entity_summary"];
13
34
  /** 分析类工具(自动,「分析类」):结构化分析,不操作数据 */
@@ -29,8 +50,22 @@ export declare const PROPOSAL_TOOLS: readonly ["propose_create_entity", "propose
29
50
  export declare const EXECUTOR_TOOLS: readonly ["create_entity", "update_entity", "delete_entity", "add_relation", "remove_relation", "add_delta", "create_outline_node", "move_node", "delete_node", "advance_hook", "resolve_hook", "abandon_hook", "reorder_timepoints"];
30
51
  /** 自动级工具(查询 11 + 分析 5 + 伏笔分析 5,共 21 个) */
31
52
  export declare const AUTO_TOOLS: readonly ["get_entity", "search_entities", "search_references", "query_relationships", "get_outline", "get_outline_path", "get_deduction_marks", "get_chapter_text", "compute_state", "get_delta_history", "get_entity_summary", "analyze_consistency", "detect_conflicts", "trace_plot_paths", "find_orphan_elements", "suggest_connections", "analyze_hook_health", "trace_hook_lifecycle", "suggest_hook_payoff", "find_hook_opportunities", "detect_hook_conflicts"];
32
- /** 全部工具名(自动 21 + 提案 16 + 执行 13 = 50 个) */
33
- export declare const TOOL_NAMES: readonly ["get_entity", "search_entities", "search_references", "query_relationships", "get_outline", "get_outline_path", "get_deduction_marks", "get_chapter_text", "compute_state", "get_delta_history", "get_entity_summary", "analyze_consistency", "detect_conflicts", "trace_plot_paths", "find_orphan_elements", "suggest_connections", "analyze_hook_health", "trace_hook_lifecycle", "suggest_hook_payoff", "find_hook_opportunities", "detect_hook_conflicts", "propose_create_entity", "propose_update_entity", "propose_delete_entity", "propose_add_relation", "propose_remove_relation", "propose_add_delta", "propose_outline_node", "propose_move_node", "propose_delete_node", "propose_create_hook", "propose_update_hook", "propose_advance_hook", "propose_resolve_hook", "propose_abandon_hook", "propose_reorder_timepoints", "propose_create_reference", "create_entity", "update_entity", "delete_entity", "add_relation", "remove_relation", "add_delta", "create_outline_node", "move_node", "delete_node", "advance_hook", "resolve_hook", "abandon_hook", "reorder_timepoints"];
53
+ /**
54
+ * 练习工具(自动级,「作家文风练习」,共 7 个 = 四只读 + 三写 AI 自己的产出)——
55
+ * **仅 `kind = "practice"` 工作区注册**(`scope = "practice"`,见 docs/api/tool-calling.md「按工作区类型收窄」):
56
+ * 四个只读分页工具(范文 / 仿写稿 / 自由稿 / 风格说明)与三个提交工具(仿写点评卡 / 自由练习点评卡 / 出题)。
57
+ * 工具面**不存在任何写用户稿的工具**——用户的稿只有用户能写(结构性边界)。
58
+ */
59
+ export declare const PRACTICE_TOOLS: readonly ["get_practice_sample", "get_practice_draft", "get_free_draft", "get_style_notes", "submit_style_feedback", "submit_free_feedback", "submit_practice_topic"];
60
+ /** 全部工具名(自动 21 + 练习 7 + 提案 16 + 执行 13 = 57 个) */
61
+ export declare const TOOL_NAMES: readonly ["get_entity", "search_entities", "search_references", "query_relationships", "get_outline", "get_outline_path", "get_deduction_marks", "get_chapter_text", "compute_state", "get_delta_history", "get_entity_summary", "analyze_consistency", "detect_conflicts", "trace_plot_paths", "find_orphan_elements", "suggest_connections", "analyze_hook_health", "trace_hook_lifecycle", "suggest_hook_payoff", "find_hook_opportunities", "detect_hook_conflicts", "get_practice_sample", "get_practice_draft", "get_free_draft", "get_style_notes", "submit_style_feedback", "submit_free_feedback", "submit_practice_topic", "propose_create_entity", "propose_update_entity", "propose_delete_entity", "propose_add_relation", "propose_remove_relation", "propose_add_delta", "propose_outline_node", "propose_move_node", "propose_delete_node", "propose_create_hook", "propose_update_hook", "propose_advance_hook", "propose_resolve_hook", "propose_abandon_hook", "propose_reorder_timepoints", "propose_create_reference", "create_entity", "update_entity", "delete_entity", "add_relation", "remove_relation", "add_delta", "create_outline_node", "move_node", "delete_node", "advance_hook", "resolve_hook", "abandon_hook", "reorder_timepoints"];
34
62
  /** 工具名(从 TOOL_NAMES 派生) */
35
63
  export type ToolName = (typeof TOOL_NAMES)[number];
64
+ /**
65
+ * `details` **随 SSE 帧下发**的工具(提案工具之外的部分)——**唯一定义处**(2026-10)。
66
+ * 契约 = docs/api/80-api-chat.md「过滤约定」:AUTO 工具的 `details` 一般不下发(与 `content` 重复、可能极大),
67
+ * 例外只给「details 是前端真实数据面」的工具;提案工具的 details(提案载荷)不在本集合里,
68
+ * 由 `PROPOSAL_TOOLS` 单独表达(投影层按两者并集放行,见 agent 包 `runtime/events.ts`)。
69
+ */
70
+ export declare const TOOL_DETAILS_TO_CLIENT: readonly ["submit_style_feedback", "submit_free_feedback", "submit_practice_topic"];
36
71
  //# sourceMappingURL=tool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/constants/tool.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,eAAe;;;CAGlB,CAAC;AAEX,aAAa;AACb,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;AAEpF,+BAA+B;AAC/B,eAAO,MAAM,WAAW,kOAYd,CAAC;AAEX,kCAAkC;AAClC,eAAO,MAAM,cAAc,yHAMjB,CAAC;AAEX,2BAA2B;AAC3B,eAAO,MAAM,mBAAmB,qIAMtB,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,cAAc,kZAiBjB,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,cAAc,uOAcjB,CAAC;AAEX,0CAA0C;AAC1C,eAAO,MAAM,UAAU,0cAAuE,CAAC;AAE/F,0CAA0C;AAC1C,eAAO,MAAM,UAAU,6iCAAiE,CAAC;AAEzF,2BAA2B;AAC3B,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/constants/tool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,eAAe;;;CAGlB,CAAC;AAEX,aAAa;AACb,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;AAEpF;;;;GAIG;AACH,eAAO,MAAM,WAAW,0CAA2C,CAAC;AAEpE,YAAY;AACZ,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,aAAa,EAAE,SAAS,SAAS,EAAE,CAG7E,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAMpF;AAED,+BAA+B;AAC/B,eAAO,MAAM,WAAW,kOAYd,CAAC;AAEX,kCAAkC;AAClC,eAAO,MAAM,cAAc,yHAMjB,CAAC;AAEX,2BAA2B;AAC3B,eAAO,MAAM,mBAAmB,qIAMtB,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,cAAc,kZAiBjB,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,cAAc,uOAcjB,CAAC;AAEX,0CAA0C;AAC1C,eAAO,MAAM,UAAU,0cAAuE,CAAC;AAE/F;;;;;GAKG;AACH,eAAO,MAAM,cAAc,uKAQjB,CAAC;AAEX,iDAAiD;AACjD,eAAO,MAAM,UAAU,ysCAAoF,CAAC;AAE5G,2BAA2B;AAC3B,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,qFAMK,CAAC"}
@@ -1,4 +1,4 @@
1
- // AI 工具常量:分级权限 + 全量工具名
1
+ // AI 工具常量:分级权限 + 工作区作用域 + 全量工具名
2
2
  /**
3
3
  * 工具权限级别(「工具分级」两级:自动 / 提案确认)
4
4
  * 自动:直接执行,结果返回 LLM;提案确认:展示提案卡片,用户审阅确认后再执行
@@ -7,6 +7,33 @@ export const TOOL_PERMISSION = {
7
7
  AUTO: "auto",
8
8
  PROPOSAL: "proposal",
9
9
  };
10
+ /**
11
+ * 工具作用域(2026-10):工具归哪个工作区类型可用——`novel` / `practice` 为各自专属,
12
+ * `common` = 两种工作区都注册。装配层按当前工作区 `kind` 过滤(见 `isToolScopeRegistered`),
13
+ * 语义与不变式见 `docs/design/architecture.md`「工作区类型(kind)与能力收窄」。
14
+ */
15
+ export const TOOL_SCOPES = ["novel", "practice", "common"];
16
+ /**
17
+ * 工作区类型 → 允许注册的工具 `scope` 集合(**唯一定义处**):装配层只经
18
+ * `isToolScopeRegistered` 判定,任何消费方(agent / tools / server)不得复写这份映射。
19
+ * 不变式:非小说工作区不注册小说工具与提案工具(结构性边界,靠注册过滤,不靠提示词)。
20
+ */
21
+ export const WORKSPACE_TOOL_SCOPES = {
22
+ novel: ["novel", "common"],
23
+ practice: ["practice", "common"],
24
+ };
25
+ /**
26
+ * 该 `scope` 的工具在指定工作区是否注册——**装配层唯一判定入口**。
27
+ * 未知 `kind`(类型层之外的值,如漏传参数)直接抛错:**不退化为「注册全量」**,
28
+ * 否则收窄会静默失效(工具集按 kind 收窄是结构性边界)。
29
+ */
30
+ export function isToolScopeRegistered(kind, scope) {
31
+ const allowed = WORKSPACE_TOOL_SCOPES[kind];
32
+ if (allowed === undefined) {
33
+ throw new Error(`未知工作区类型: ${String(kind)}`);
34
+ }
35
+ return allowed.includes(scope);
36
+ }
10
37
  /** 查询类工具(自动,「查询类」):默认过滤软删对象 */
11
38
  export const QUERY_TOOLS = [
12
39
  "get_entity",
@@ -83,6 +110,34 @@ export const EXECUTOR_TOOLS = [
83
110
  ];
84
111
  /** 自动级工具(查询 11 + 分析 5 + 伏笔分析 5,共 21 个) */
85
112
  export const AUTO_TOOLS = [...QUERY_TOOLS, ...ANALYSIS_TOOLS, ...HOOK_ANALYSIS_TOOLS];
86
- /** 全部工具名(自动 21 + 提案 16 + 执行 13 = 50 个) */
87
- export const TOOL_NAMES = [...AUTO_TOOLS, ...PROPOSAL_TOOLS, ...EXECUTOR_TOOLS];
113
+ /**
114
+ * 练习工具(自动级,「作家文风练习」,共 7 个 = 四只读 + 三写 AI 自己的产出)——
115
+ * **仅 `kind = "practice"` 工作区注册**(`scope = "practice"`,见 docs/api/tool-calling.md「按工作区类型收窄」):
116
+ * 四个只读分页工具(范文 / 仿写稿 / 自由稿 / 风格说明)与三个提交工具(仿写点评卡 / 自由练习点评卡 / 出题)。
117
+ * 工具面**不存在任何写用户稿的工具**——用户的稿只有用户能写(结构性边界)。
118
+ */
119
+ export const PRACTICE_TOOLS = [
120
+ "get_practice_sample", // 范文快照只读(分页)
121
+ "get_practice_draft", // 用户仿写稿只读(分页)
122
+ "get_free_draft", // 用户自由练习稿只读(分页)
123
+ "get_style_notes", // 作家风格说明只读(分页;自由练习点评的唯一依据)
124
+ "submit_style_feedback", // 提交仿写点评卡(只写 practice_samples.feedback)
125
+ "submit_free_feedback", // 提交自由练习点评卡(只写 practice_free_pieces.feedback)
126
+ "submit_practice_topic", // AI 出题(只写 practice_free_pieces.topic / brief)
127
+ ];
128
+ /** 全部工具名(自动 21 + 练习 7 + 提案 16 + 执行 13 = 57 个) */
129
+ export const TOOL_NAMES = [...AUTO_TOOLS, ...PRACTICE_TOOLS, ...PROPOSAL_TOOLS, ...EXECUTOR_TOOLS];
130
+ /**
131
+ * `details` **随 SSE 帧下发**的工具(提案工具之外的部分)——**唯一定义处**(2026-10)。
132
+ * 契约 = docs/api/80-api-chat.md「过滤约定」:AUTO 工具的 `details` 一般不下发(与 `content` 重复、可能极大),
133
+ * 例外只给「details 是前端真实数据面」的工具;提案工具的 details(提案载荷)不在本集合里,
134
+ * 由 `PROPOSAL_TOOLS` 单独表达(投影层按两者并集放行,见 agent 包 `runtime/events.ts`)。
135
+ */
136
+ export const TOOL_DETAILS_TO_CLIENT = [
137
+ // 点评卡:写库结果随帧下发,前端据此即时刷新卡片(卡片正体从 GET /practice/samples/:id 读)
138
+ "submit_style_feedback",
139
+ // 自由练习点评 / 出题:同上(写库结果随帧下发;前端据 `tool_execution_start` 的入参 piece_id 认领)
140
+ "submit_free_feedback",
141
+ "submit_practice_topic",
142
+ ];
88
143
  //# sourceMappingURL=tool.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/constants/tool.ts"],"names":[],"mappings":"AAAA,uBAAuB;AAEvB;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,UAAU;CACZ,CAAC;AAKX,+BAA+B;AAC/B,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,YAAY;IACZ,iBAAiB;IACjB,mBAAmB,EAAE,eAAe;IACpC,qBAAqB;IACrB,aAAa;IACb,kBAAkB;IAClB,qBAAqB,EAAE,eAAe;IACtC,kBAAkB,EAAE,qCAAqC;IACzD,eAAe;IACf,mBAAmB;IACnB,oBAAoB;CACZ,CAAC;AAEX,kCAAkC;AAClC,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,qBAAqB;IACrB,kBAAkB;IAClB,kBAAkB;IAClB,sBAAsB;IACtB,qBAAqB;CACb,CAAC;AAEX,2BAA2B;AAC3B,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,qBAAqB;IACrB,sBAAsB;IACtB,qBAAqB;IACrB,yBAAyB;IACzB,uBAAuB;CACf,CAAC;AAEX;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,uBAAuB;IACvB,uBAAuB;IACvB,uBAAuB;IACvB,sBAAsB;IACtB,yBAAyB;IACzB,mBAAmB;IACnB,sBAAsB;IACtB,mBAAmB;IACnB,qBAAqB;IACrB,qBAAqB;IACrB,qBAAqB;IACrB,sBAAsB;IACtB,sBAAsB;IACtB,sBAAsB;IACtB,4BAA4B,EAAE,wCAAwC;IACtE,0BAA0B,EAAE,yBAAyB;CAC7C,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,eAAe;IACf,eAAe;IACf,eAAe;IACf,cAAc;IACd,iBAAiB;IACjB,WAAW;IACX,qBAAqB;IACrB,WAAW;IACX,aAAa;IACb,cAAc;IACd,cAAc;IACd,cAAc;IACd,oBAAoB;CACZ,CAAC;AAEX,0CAA0C;AAC1C,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAG,WAAW,EAAE,GAAG,cAAc,EAAE,GAAG,mBAAmB,CAAU,CAAC;AAE/F,0CAA0C;AAC1C,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAG,UAAU,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,CAAU,CAAC"}
1
+ {"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/constants/tool.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAIhC;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,UAAU;CACZ,CAAC;AAKX;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAU,CAAC;AAKpE;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAgD;IAChF,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;IAC1B,QAAQ,EAAE,CAAC,UAAU,EAAE,QAAQ,CAAC;CACjC,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAmB,EAAE,KAAgB;IACzE,MAAM,OAAO,GAAqC,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC9E,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,YAAY,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,+BAA+B;AAC/B,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,YAAY;IACZ,iBAAiB;IACjB,mBAAmB,EAAE,eAAe;IACpC,qBAAqB;IACrB,aAAa;IACb,kBAAkB;IAClB,qBAAqB,EAAE,eAAe;IACtC,kBAAkB,EAAE,qCAAqC;IACzD,eAAe;IACf,mBAAmB;IACnB,oBAAoB;CACZ,CAAC;AAEX,kCAAkC;AAClC,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,qBAAqB;IACrB,kBAAkB;IAClB,kBAAkB;IAClB,sBAAsB;IACtB,qBAAqB;CACb,CAAC;AAEX,2BAA2B;AAC3B,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,qBAAqB;IACrB,sBAAsB;IACtB,qBAAqB;IACrB,yBAAyB;IACzB,uBAAuB;CACf,CAAC;AAEX;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,uBAAuB;IACvB,uBAAuB;IACvB,uBAAuB;IACvB,sBAAsB;IACtB,yBAAyB;IACzB,mBAAmB;IACnB,sBAAsB;IACtB,mBAAmB;IACnB,qBAAqB;IACrB,qBAAqB;IACrB,qBAAqB;IACrB,sBAAsB;IACtB,sBAAsB;IACtB,sBAAsB;IACtB,4BAA4B,EAAE,wCAAwC;IACtE,0BAA0B,EAAE,yBAAyB;CAC7C,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,eAAe;IACf,eAAe;IACf,eAAe;IACf,cAAc;IACd,iBAAiB;IACjB,WAAW;IACX,qBAAqB;IACrB,WAAW;IACX,aAAa;IACb,cAAc;IACd,cAAc;IACd,cAAc;IACd,oBAAoB;CACZ,CAAC;AAEX,0CAA0C;AAC1C,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAG,WAAW,EAAE,GAAG,cAAc,EAAE,GAAG,mBAAmB,CAAU,CAAC;AAE/F;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,qBAAqB,EAAE,aAAa;IACpC,oBAAoB,EAAE,cAAc;IACpC,gBAAgB,EAAE,gBAAgB;IAClC,iBAAiB,EAAE,2BAA2B;IAC9C,uBAAuB,EAAE,wCAAwC;IACjE,sBAAsB,EAAE,8CAA8C;IACtE,uBAAuB,EAAE,+CAA+C;CAChE,CAAC;AAEX,iDAAiD;AACjD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAG,UAAU,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,CAAU,CAAC;AAK5G;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,6DAA6D;IAC7D,uBAAuB;IACvB,sEAAsE;IACtE,sBAAsB;IACtB,uBAAuB;CACe,CAAC"}
@@ -0,0 +1,22 @@
1
+ /** 工作区类型:决定目录映射、AI 工具集与内核提示词、路由守卫与导航 */
2
+ export type WorkspaceKind = "novel" | "practice";
3
+ /** 缺省工作区类型(`kind` 缺失 / 未知值的读侧兜底) */
4
+ export declare const DEFAULT_WORKSPACE_KIND: WorkspaceKind;
5
+ /** 工作区类型 → 创作根下的顶层目录名(**唯一定义处**:服务端拼路径、客户端导航一律取这里) */
6
+ export declare const WORKSPACE_DIRS: Record<WorkspaceKind, string>;
7
+ /** 全部工作区类型(顺序 = 目录表键序;zod 枚举与 list 扫描同源) */
8
+ export declare const WORKSPACE_KINDS: WorkspaceKind[];
9
+ /**
10
+ * 工作区类型的**中文名**(用户可见文案的唯一定义处:服务端 `KIND_MISMATCH` 文案、客户端分区标题
11
+ * 都取这里)。程序设计侧词(`novel` / `practice`)**不得进用户侧文案**——它们是目录映射与
12
+ * 工具集收窄的实现词,用户看到的是「小说」/「文风练习」。
13
+ */
14
+ export declare const WORKSPACE_KIND_LABELS: Record<WorkspaceKind, string>;
15
+ /**
16
+ * 工作区类型**唯一兜底函数**:缺 `kind` / 非字符串 / 未知值 → 缺省 `novel`。
17
+ *
18
+ * 消费方(API 输出、目录映射、路由守卫)一律经它归一,禁止各处自写 `?? "novel"`;
19
+ * 归一结果只是**读侧口径**——写侧只写显式值(存量 project.json 不因读取被补上 `kind` 键)。
20
+ */
21
+ export declare function resolveWorkspaceKind(value: unknown): WorkspaceKind;
22
+ //# sourceMappingURL=workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/constants/workspace.ts"],"names":[],"mappings":"AAMA,wCAAwC;AACxC,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,UAAU,CAAC;AAEjD,oCAAoC;AACpC,eAAO,MAAM,sBAAsB,EAAE,aAAuB,CAAC;AAE7D,sDAAsD;AACtD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAGxD,CAAC;AAEF,4CAA4C;AAC5C,eAAO,MAAM,eAAe,EAAkC,aAAa,EAAE,CAAC;AAE9E;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAG/D,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAElE"}
@@ -0,0 +1,33 @@
1
+ // 工作区类型(project.json 的 `kind`)常量与兜底(2026-10)
2
+ //
3
+ // 语义与不变式见 `docs/design/architecture.md`「工作区类型(kind)与能力收窄」,
4
+ // 字段契约见 `docs/db/schema.md`「project.json」与 `docs/api/10-api-project.md`。
5
+ // **不 import zod**:纯常量 + 纯函数,客户端可安全经 shared 根入口打包。
6
+ /** 缺省工作区类型(`kind` 缺失 / 未知值的读侧兜底) */
7
+ export const DEFAULT_WORKSPACE_KIND = "novel";
8
+ /** 工作区类型 → 创作根下的顶层目录名(**唯一定义处**:服务端拼路径、客户端导航一律取这里) */
9
+ export const WORKSPACE_DIRS = {
10
+ novel: "books",
11
+ practice: "practice",
12
+ };
13
+ /** 全部工作区类型(顺序 = 目录表键序;zod 枚举与 list 扫描同源) */
14
+ export const WORKSPACE_KINDS = Object.keys(WORKSPACE_DIRS);
15
+ /**
16
+ * 工作区类型的**中文名**(用户可见文案的唯一定义处:服务端 `KIND_MISMATCH` 文案、客户端分区标题
17
+ * 都取这里)。程序设计侧词(`novel` / `practice`)**不得进用户侧文案**——它们是目录映射与
18
+ * 工具集收窄的实现词,用户看到的是「小说」/「文风练习」。
19
+ */
20
+ export const WORKSPACE_KIND_LABELS = {
21
+ novel: "小说",
22
+ practice: "文风练习",
23
+ };
24
+ /**
25
+ * 工作区类型**唯一兜底函数**:缺 `kind` / 非字符串 / 未知值 → 缺省 `novel`。
26
+ *
27
+ * 消费方(API 输出、目录映射、路由守卫)一律经它归一,禁止各处自写 `?? "novel"`;
28
+ * 归一结果只是**读侧口径**——写侧只写显式值(存量 project.json 不因读取被补上 `kind` 键)。
29
+ */
30
+ export function resolveWorkspaceKind(value) {
31
+ return WORKSPACE_KINDS.find((kind) => kind === value) ?? DEFAULT_WORKSPACE_KIND;
32
+ }
33
+ //# sourceMappingURL=workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/constants/workspace.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,2DAA2D;AAC3D,yEAAyE;AACzE,mDAAmD;AAKnD,oCAAoC;AACpC,MAAM,CAAC,MAAM,sBAAsB,GAAkB,OAAO,CAAC;AAE7D,sDAAsD;AACtD,MAAM,CAAC,MAAM,cAAc,GAAkC;IAC3D,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;CACrB,CAAC;AAEF,4CAA4C;AAC5C,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAoB,CAAC;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAkC;IAClE,KAAK,EAAE,IAAI;IACX,QAAQ,EAAE,MAAM;CACjB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,sBAAsB,CAAC;AAClF,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export type * from "./types/index.js";
2
2
  export * from "./constants/index.js";
3
3
  export * from "./utils/index.js";
4
+ export * from "./authors/index.js";
4
5
  export declare const SHARED_PKG_NAME = "@whispering233/ai-editor-shared";
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,mBAAmB,kBAAkB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AAEjC,eAAO,MAAM,eAAe,oCAAoC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,mBAAmB,kBAAkB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AAEnC,eAAO,MAAM,eAAe,oCAAoC,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./constants/index.js";
2
2
  export * from "./utils/index.js";
3
+ export * from "./authors/index.js";
3
4
  export const SHARED_PKG_NAME = "@whispering233/ai-editor-shared";
4
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AAEjC,MAAM,CAAC,MAAM,eAAe,GAAG,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AAEnC,MAAM,CAAC,MAAM,eAAe,GAAG,iCAAiC,CAAC"}