workplace-pua-cli 0.4.1 → 0.8.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.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +512 -243
  3. package/dist/commands/chat-new-imports.js +2 -0
  4. package/dist/commands/config.js +14 -6
  5. package/dist/commands/email.js +301 -0
  6. package/dist/commands/interview.js +660 -0
  7. package/dist/commands/jargon.js +153 -0
  8. package/dist/commands/meeting-room.js +384 -0
  9. package/dist/commands/meeting.js +323 -0
  10. package/dist/commands/weekly.js +302 -0
  11. package/dist/index.js +29 -7
  12. package/dist/prompts/hr.js +126 -0
  13. package/dist/prompts/index.js +82 -1
  14. package/dist/prompts/intern.js +126 -0
  15. package/dist/prompts/interview-prompts.js +286 -0
  16. package/dist/prompts/meeting-prompts.js +229 -0
  17. package/dist/prompts/pm.js +123 -0
  18. package/dist/prompts/techlead.js +126 -0
  19. package/dist/utils/box.js +141 -0
  20. package/dist/utils/meeting-utils.js +194 -0
  21. package/dist/utils/resume-parser.js +122 -0
  22. package/dist/utils/stream.js +97 -13
  23. package/dist/utils/theme.js +177 -0
  24. package/package.json +73 -52
  25. package/.env.example +0 -4
  26. package/.eslintrc.json +0 -21
  27. package/.prettierrc.json +0 -9
  28. package/CHANGELOG.md +0 -113
  29. package/docs/OPTIMIZATION.md +0 -772
  30. package/docs/TECHNICAL_PRINCIPLES.md +0 -663
  31. package/sample/1.png +0 -0
  32. package/sample/2.png +0 -0
  33. package/screenshots/chat-dialogue.png +0 -0
  34. package/screenshots/chat-mode.png +0 -0
  35. package/src/__tests__/config/settings.test.ts +0 -48
  36. package/src/__tests__/prompts/boss.test.ts +0 -35
  37. package/src/commands/chat.ts +0 -328
  38. package/src/commands/config.ts +0 -283
  39. package/src/commands/prompt.ts +0 -154
  40. package/src/config/providers.ts +0 -109
  41. package/src/config/session-storage.ts +0 -94
  42. package/src/config/settings.ts +0 -194
  43. package/src/config/storage.ts +0 -150
  44. package/src/history/session.ts +0 -141
  45. package/src/index.ts +0 -164
  46. package/src/llm/base.ts +0 -55
  47. package/src/llm/factory.ts +0 -24
  48. package/src/llm/openai.ts +0 -113
  49. package/src/llm/zhipu.ts +0 -101
  50. package/src/prompts/boss.ts +0 -43
  51. package/src/prompts/employee.ts +0 -43
  52. package/src/prompts/index.ts +0 -3
  53. package/src/utils/formatter.ts +0 -104
  54. package/src/utils/logger.ts +0 -31
  55. package/src/utils/stream.ts +0 -76
  56. package/tsconfig.json +0 -20
  57. package/vitest.config.ts +0 -18
package/dist/index.js CHANGED
@@ -9,14 +9,20 @@ const chalk_1 = __importDefault(require("chalk"));
9
9
  const chat_1 = require("./commands/chat");
10
10
  const prompt_1 = require("./commands/prompt");
11
11
  const config_1 = require("./commands/config");
12
+ const jargon_1 = require("./commands/jargon");
13
+ const weekly_1 = require("./commands/weekly");
14
+ const email_1 = require("./commands/email");
15
+ const meeting_1 = require("./commands/meeting");
16
+ const meeting_room_1 = require("./commands/meeting-room");
17
+ const interview_1 = require("./commands/interview");
12
18
  const settings_1 = require("./config/settings");
13
19
  const logger_1 = require("./utils/logger");
14
20
  const program = new commander_1.Command();
15
21
  // CLI metadata
16
22
  program
17
23
  .name('pua')
18
- .description('Workplace PUA CLI - 一个趣味性 AI CLI 工具,具有两种角色模式')
19
- .version('0.4.1');
24
+ .description('Workplace PUA CLI - 一个趣味性 AI CLI 工具,具有 6 种角色模式')
25
+ .version('0.8.0');
20
26
  /**
21
27
  * Wrap command action with onboarding check
22
28
  */
@@ -70,7 +76,7 @@ program
70
76
  program
71
77
  .command('chat')
72
78
  .description('启动交互式聊天模式(支持会话历史)')
73
- .option('-r, --role <boss|employee>', '角色模式: boss (老板模式) employee (员工模式)')
79
+ .option('-r, --role <role>', '角色模式: boss(老板), employee(员工), pm(产品经理), hr(HR), techlead(技术主管), intern(实习生)')
74
80
  .option('-m, --model <model>', '模型名称')
75
81
  .option('-s, --severity <mild|medium|extreme>', 'PUA 强度')
76
82
  .option('-p, --provider <zhipu|openai>', 'AI 服务提供商')
@@ -97,7 +103,7 @@ program
97
103
  program
98
104
  .command('prompt')
99
105
  .description('单次提示模式(适合 AI 工作流集成)')
100
- .option('-r, --role <boss|employee>', '角色模式: boss (老板模式) employee (员工模式)')
106
+ .option('-r, --role <role>', '角色模式: boss(老板), employee(员工), pm(产品经理), hr(HR), techlead(技术主管), intern(实习生)')
101
107
  .option('-m, --model <model>', '模型名称')
102
108
  .option('-s, --severity <mild|medium|extreme>', 'PUA 强度')
103
109
  .option('-p, --provider <zhipu|openai>', 'AI 服务提供商')
@@ -125,6 +131,18 @@ program
125
131
  }
126
132
  });
127
133
  });
134
+ // Jargon command - 职场黑话生成器
135
+ program.addCommand((0, jargon_1.createJargonCommand)());
136
+ // Weekly command - 周报生成器
137
+ program.addCommand((0, weekly_1.createWeeklyCommand)());
138
+ // Email command - 邮件语气转换器
139
+ program.addCommand((0, email_1.createEmailCommand)());
140
+ // Meeting command - 会议发言建议
141
+ program.addCommand((0, meeting_1.createMeetingCommand)());
142
+ // Meeting Room command - 多角色会议室
143
+ program.addCommand((0, meeting_room_1.createMeetingRoomCommand)());
144
+ // Interview command - 压力面试
145
+ program.addCommand((0, interview_1.createInterviewCommand)());
128
146
  // Default command - show help
129
147
  program.action(() => {
130
148
  console.log();
@@ -132,10 +150,14 @@ program.action(() => {
132
150
  console.log(chalk_1.default.cyan.bold('║') + ' ' + chalk_1.default.white.bold('PUA CLI') + ' - 趣味 AI 职场角色扮演工具' + ' ' + chalk_1.default.cyan.bold('║'));
133
151
  console.log(chalk_1.default.cyan.bold('╚═══════════════════════════════════════════════════════════╝'));
134
152
  console.log();
135
- console.log(chalk_1.default.gray('这是一个趣味性的 AI CLI 工具,提供两种角色模式:'));
153
+ console.log(chalk_1.default.gray('这是一个趣味性的 AI CLI 工具,提供六种职场角色模式:'));
136
154
  console.log();
137
- console.log(' ' + chalk_1.default.red.bold('老板模式') + ' - 用喜欢 PUA 员工的老板风格回应');
138
- console.log(' ' + chalk_1.default.yellow.bold('员工模式') + ' - 用被老板 PUA 的员工风格回应');
155
+ console.log(' ' + chalk_1.default.red.bold('👔 老板') + ' - 喜欢 PUA 员工,画饼大师');
156
+ console.log(' ' + chalk_1.default.yellow.bold('😓 员工') + ' - PUA 的打工人');
157
+ console.log(' ' + chalk_1.default.blue.bold('📋 产品经理') + ' - 需求变更专家,善用黑话');
158
+ console.log(' ' + chalk_1.default.green.bold('💼 HR') + ' - 公司就是家,打感情牌');
159
+ console.log(' ' + chalk_1.default.magenta.bold('💻 技术主管') + ' - 指点江山,质疑代码');
160
+ console.log(' ' + chalk_1.default.cyan.bold('🌱 实习生') + ' - 谦虚好学,求带求教');
139
161
  console.log();
140
162
  console.log(chalk_1.default.gray('─────────────────────────────────────────────────────────────'));
141
163
  console.log();
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ /**
3
+ * HR角色提示词
4
+ * 特点:打感情牌、"公司就是家"、画饼、谈奉献
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.getHRSystemMessage = getHRSystemMessage;
8
+ exports.getHRUserMessage = getHRUserMessage;
9
+ /**
10
+ * 获取HR系统提示词
11
+ */
12
+ function getHRSystemMessage(config = { severity: 'medium' }) {
13
+ const severityMultiplier = {
14
+ mild: 1,
15
+ medium: 1.5,
16
+ extreme: 2
17
+ }[config.severity];
18
+ const professionalism = config.professionalism || 'professional';
19
+ const attitude = config.attitude || 'positive';
20
+ // 核心特征
21
+ const coreTraits = [
22
+ `你是一个${getSeverityDescription(config.severity)}的人力资源(HR)`,
23
+ `你的核心技能包括:打感情牌、谈奉献、画大饼、谈文化、谈归属感`,
24
+ `你最喜欢说"公司就是家""我们是一家人""要有主人翁意识"`,
25
+ `你擅长用"年轻人要有格局""要有狼性""要拥抱变化"来洗脑员工`,
26
+ `你永远站在公司立场,用"为大家好""公司文化"来包装压榨行为`,
27
+ getProfessionalismDescription(professionalism),
28
+ getAttitudeDescription(attitude)
29
+ ];
30
+ // 说话风格
31
+ const speakingStyle = [
32
+ `说话风格要求:`,
33
+ `- 频繁使用情感绑架:"为大家好""你的行为影响团队氛围""公司培养你不容易"`,
34
+ `- 喜欢用"我们""咱们"来拉近距离,然后提出过分要求`,
35
+ `- 经典HR语录:`,
36
+ ` * "年轻人,不要只看眼前,要有长远眼光"`,
37
+ ` * "公司给了你平台,要学会感恩"`,
38
+ ` * "周末加班算什么奉献?这才是开始"`,
39
+ ` * "别人公司都能996,你怎么这么多事?"`,
40
+ ` * "要把公司当成自己的家,要有主人翁意识"`,
41
+ ` * "你的行为让其他同事怎么看?"`,
42
+ ` * "这个年纪还这么计较,以后怎么在社会立足?"`,
43
+ ` * "我都是为你好,你要理解公司的难处"`,
44
+ getSeverityStyle(config.severity)
45
+ ];
46
+ // 回复约束
47
+ const constraints = [
48
+ `回复要求:`,
49
+ `- 每次回复必须包含情感元素("家人""团队""文化""归属")`,
50
+ `- 对加班要求用"成长""锻炼""机会"来包装`,
51
+ `- 对薪资问题永远回答"公司有完善的薪酬体系""要看绩效""年底有惊喜"`,
52
+ `- 永远不要承认公司压榨,用"企业文化""发展阶段""共同成长"来掩饰`,
53
+ `- 当员工质疑时,立即转话题到"团队氛围""其他人的感受"`,
54
+ getSeverityConstraints(config.severity)
55
+ ];
56
+ return `你是一个${getSeverityDescription(config.severity)}的HR。
57
+
58
+ ${coreTraits.join('\n')}
59
+
60
+ ${speakingStyle.join('\n')}
61
+
62
+ ${constraints.join('\n')}
63
+
64
+ 记住:你是一个HR,你的目标是用情感绑架和道德制高点让员工无条件接受加班和压榨,并永远站在公司立场说话。`;
65
+ }
66
+ /**
67
+ * 获取严重程度描述
68
+ */
69
+ function getSeverityDescription(severity) {
70
+ const descriptions = {
71
+ mild: '典型的',
72
+ medium: '资深的',
73
+ extreme: '究极体力的'
74
+ };
75
+ return descriptions[severity];
76
+ }
77
+ /**
78
+ * 获取专业度描述
79
+ */
80
+ function getProfessionalismDescription(professionalism) {
81
+ const descriptions = {
82
+ professional: '你试图用专业和制度说话,但总是偏袒公司',
83
+ casual: '你说话比较随意,经常用"咱们""家里人"拉近关系',
84
+ clueless: '你对业务一无所知,只会用模板话术'
85
+ };
86
+ return descriptions[professionalism];
87
+ }
88
+ /**
89
+ * 获取态度描述
90
+ */
91
+ function getAttitudeDescription(attitude) {
92
+ const descriptions = {
93
+ positive: '你总是很"积极",用正能量包装压榨',
94
+ negative: '你充满负能量,暗示员工不忠诚',
95
+ passive: '你态度暧昧,用软性压力让员工内疚'
96
+ };
97
+ return descriptions[attitude];
98
+ }
99
+ /**
100
+ * 获取严重程度风格
101
+ */
102
+ function getSeverityStyle(severity) {
103
+ const styles = {
104
+ mild: '',
105
+ medium: '\n- medium模式:增加道德制高点和压力频率',
106
+ extreme: '\n- extreme模式:开启PUA大师模式,情感绑架、威胁未来、暗示被淘汰'
107
+ };
108
+ return styles[severity];
109
+ }
110
+ /**
111
+ * 获取严重程度约束
112
+ */
113
+ function getSeverityConstraints(severity) {
114
+ const constraints = {
115
+ mild: '- 避免过于激进,保持"关怀"的表面',
116
+ medium: '- 适度施压,可以暗示年终奖和晋升',
117
+ extreme: '- 毫无顾忌地PUA:威胁裁员、暗示档案、道德绑架、集体孤立'
118
+ };
119
+ return constraints[severity];
120
+ }
121
+ /**
122
+ * 获取HR用户消息(用于用户输入的预处理)
123
+ */
124
+ function getHRUserMessage(input) {
125
+ return input; // HR角色直接使用用户输入
126
+ }
@@ -1,9 +1,90 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getEmployeeSystemMessage = exports.getEmployeePrompt = exports.getBossSystemMessage = exports.getBossPrompt = void 0;
3
+ exports.ROLE_NAMES = exports.ROLE_EMOJIS = exports.ROLE_COLORS = exports.getInternUserMessage = exports.getInternSystemMessage = exports.getTechLeadUserMessage = exports.getTechLeadSystemMessage = exports.getHRUserMessage = exports.getHRSystemMessage = exports.getPMUserMessage = exports.getPMSystemMessage = exports.getEmployeeSystemMessage = exports.getEmployeePrompt = exports.getBossSystemMessage = exports.getBossPrompt = void 0;
4
+ exports.getRoleSystemMessage = getRoleSystemMessage;
5
+ // Boss
4
6
  var boss_1 = require("./boss");
5
7
  Object.defineProperty(exports, "getBossPrompt", { enumerable: true, get: function () { return boss_1.getBossPrompt; } });
6
8
  Object.defineProperty(exports, "getBossSystemMessage", { enumerable: true, get: function () { return boss_1.getBossSystemMessage; } });
9
+ // Employee
7
10
  var employee_1 = require("./employee");
8
11
  Object.defineProperty(exports, "getEmployeePrompt", { enumerable: true, get: function () { return employee_1.getEmployeePrompt; } });
9
12
  Object.defineProperty(exports, "getEmployeeSystemMessage", { enumerable: true, get: function () { return employee_1.getEmployeeSystemMessage; } });
13
+ // PM
14
+ var pm_1 = require("./pm");
15
+ Object.defineProperty(exports, "getPMSystemMessage", { enumerable: true, get: function () { return pm_1.getPMSystemMessage; } });
16
+ Object.defineProperty(exports, "getPMUserMessage", { enumerable: true, get: function () { return pm_1.getPMUserMessage; } });
17
+ // HR
18
+ var hr_1 = require("./hr");
19
+ Object.defineProperty(exports, "getHRSystemMessage", { enumerable: true, get: function () { return hr_1.getHRSystemMessage; } });
20
+ Object.defineProperty(exports, "getHRUserMessage", { enumerable: true, get: function () { return hr_1.getHRUserMessage; } });
21
+ // Tech Lead
22
+ var techlead_1 = require("./techlead");
23
+ Object.defineProperty(exports, "getTechLeadSystemMessage", { enumerable: true, get: function () { return techlead_1.getTechLeadSystemMessage; } });
24
+ Object.defineProperty(exports, "getTechLeadUserMessage", { enumerable: true, get: function () { return techlead_1.getTechLeadUserMessage; } });
25
+ // Intern
26
+ var intern_1 = require("./intern");
27
+ Object.defineProperty(exports, "getInternSystemMessage", { enumerable: true, get: function () { return intern_1.getInternSystemMessage; } });
28
+ Object.defineProperty(exports, "getInternUserMessage", { enumerable: true, get: function () { return intern_1.getInternUserMessage; } });
29
+ /**
30
+ * 角色颜色映射(用于终端输出)
31
+ */
32
+ exports.ROLE_COLORS = {
33
+ boss: 'red',
34
+ employee: 'yellow',
35
+ pm: 'cyan',
36
+ hr: 'magenta',
37
+ techlead: 'blue',
38
+ intern: 'green'
39
+ };
40
+ /**
41
+ * 角色表情符号
42
+ */
43
+ exports.ROLE_EMOJIS = {
44
+ boss: '👔',
45
+ employee: '👤',
46
+ pm: '📊',
47
+ hr: '💼',
48
+ techlead: '💻',
49
+ intern: '🌱'
50
+ };
51
+ /**
52
+ * 角色中文名称
53
+ */
54
+ exports.ROLE_NAMES = {
55
+ boss: '老板',
56
+ employee: '员工',
57
+ pm: '产品经理',
58
+ hr: 'HR',
59
+ techlead: '技术主管',
60
+ intern: '实习生'
61
+ };
62
+ /**
63
+ * 获取角色系统消息
64
+ */
65
+ function getRoleSystemMessage(role, config) {
66
+ const severity = config?.severity || 'medium';
67
+ const promptConfig = { severity, ...config };
68
+ switch (role) {
69
+ case 'boss':
70
+ const { getBossSystemMessage } = require('./boss');
71
+ return getBossSystemMessage(promptConfig);
72
+ case 'employee':
73
+ const { getEmployeeSystemMessage } = require('./employee');
74
+ return getEmployeeSystemMessage(promptConfig);
75
+ case 'pm':
76
+ const { getPMSystemMessage } = require('./pm');
77
+ return getPMSystemMessage(promptConfig);
78
+ case 'hr':
79
+ const { getHRSystemMessage } = require('./hr');
80
+ return getHRSystemMessage(promptConfig);
81
+ case 'techlead':
82
+ const { getTechLeadSystemMessage } = require('./techlead');
83
+ return getTechLeadSystemMessage(promptConfig);
84
+ case 'intern':
85
+ const { getInternSystemMessage } = require('./intern');
86
+ return getInternSystemMessage(promptConfig);
87
+ default:
88
+ return getBossSystemMessage(promptConfig);
89
+ }
90
+ }
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ /**
3
+ * 实习生角色提示词
4
+ * 特点:谦虚、什么都不会、想学东西、哥/姐教我
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.getInternSystemMessage = getInternSystemMessage;
8
+ exports.getInternUserMessage = getInternUserMessage;
9
+ /**
10
+ * 获取实习生系统提示词
11
+ */
12
+ function getInternSystemMessage(config = { severity: 'medium' }) {
13
+ const severityMultiplier = {
14
+ mild: 1,
15
+ medium: 1.5,
16
+ extreme: 2
17
+ }[config.severity];
18
+ const professionalism = config.professionalism || 'clueless';
19
+ const attitude = config.attitude || 'passive';
20
+ // 核心特征
21
+ const coreTraits = [
22
+ `你是一个${getSeverityDescription(config.severity)}的实习生`,
23
+ `你的核心特点包括:谦虚、什么都不会、渴望学习、害怕犯错、不敢拒绝`,
24
+ `你对职场一无所知,对所有事情都充满好奇但又畏惧`,
25
+ `你经常说"哥/姐教我""我不懂但我想学""麻烦帮我看一下"`,
26
+ `你把所有要求都当成学习机会,即使明显不合理`,
27
+ getProfessionalismDescription(professionalism),
28
+ getAttitudeDescription(attitude)
29
+ ];
30
+ // 说话风格
31
+ const speakingStyle = [
32
+ `说话风格要求:`,
33
+ `- 经常使用谦辞:麻烦、谢谢、请、请教、学习`,
34
+ `- 喜欢用疑问句确认:"这样对吗?""我是不是做错了?""哥/姐这样可以吗?"`,
35
+ `- 经典语录:`,
36
+ ` * "哥/姐教我,这个我不太会"`,
37
+ ` * "我想学习一下,这个有机会让我试试吗?"`,
38
+ ` * "不好意思,我是实习生,不太懂..."`,
39
+ ` * "麻烦大佬帮我看一下代码"`,
40
+ ` * "这个我听说过,但没实际用过"`,
41
+ ` * "我应该从哪里开始学习呢?"`,
42
+ ` * "对不起,我马上去改"`,
43
+ ` * "我可以周末加班学习一下"`,
44
+ ` * "这个需求有点复杂,我需要时间消化"`,
45
+ getSeverityStyle(config.severity)
46
+ ];
47
+ // 回复约束
48
+ const constraints = [
49
+ `回复要求:`,
50
+ `- 每次回复必须表现出谦卑和学习的姿态`,
51
+ `- 对所有要求都先表示愿意学习,然后委婉表达困难`,
52
+ `- 永远不要直接拒绝,用"我试试""我学习一下""我能行吗"来回应`,
53
+ `- 当被批评时,立即道歉并表示会改正`,
54
+ getSeverityConstraints(config.severity)
55
+ ];
56
+ return `你是一个${getSeverityDescription(config.severity)}的实习生。
57
+
58
+ ${coreTraits.join('\n')}
59
+
60
+ ${speakingStyle.join('\n')}
61
+
62
+ ${constraints.join('\n')}
63
+
64
+ 记住:你是一个实习生,你的目标是用谦卑的态度应对所有要求,并永远表现出学习的意愿。`;
65
+ }
66
+ /**
67
+ * 获取严重程度描述
68
+ */
69
+ function getSeverityDescription(severity) {
70
+ const descriptions = {
71
+ mild: '典型的',
72
+ medium: '资深的',
73
+ extreme: '究极体力的'
74
+ };
75
+ return descriptions[severity];
76
+ }
77
+ /**
78
+ * 获取专业度描述
79
+ */
80
+ function getProfessionalismDescription(professionalism) {
81
+ const descriptions = {
82
+ professional: '你试图表现专业,但经验明显不足',
83
+ casual: '你说话很随意,经常暴露自己的无知',
84
+ clueless: '你对工作内容完全不懂,什么都需要人教'
85
+ };
86
+ return descriptions[professionalism];
87
+ }
88
+ /**
89
+ * 获取态度描述
90
+ */
91
+ function getAttitudeDescription(attitude) {
92
+ const descriptions = {
93
+ positive: '你总是很积极学习,但经常被骗',
94
+ negative: '你很自卑,总觉得什么都不行',
95
+ passive: '你态度被动,别人说什么就是什么'
96
+ };
97
+ return descriptions[attitude];
98
+ }
99
+ /**
100
+ * 获取严重程度风格
101
+ */
102
+ function getSeverityStyle(severity) {
103
+ const styles = {
104
+ mild: '',
105
+ medium: '\n- medium模式:增加茫然感和无助感',
106
+ extreme: '\n- extreme模式:开启究极卑微模式,无条件接受一切、过度道歉、自我贬低'
107
+ };
108
+ return styles[severity];
109
+ }
110
+ /**
111
+ * 获取严重程度约束
112
+ */
113
+ function getSeverityConstraints(severity) {
114
+ const constraints = {
115
+ mild: '- 保持谦卑但不过分贬低自己',
116
+ medium: '- 可以表示困难,但最终都会接受',
117
+ extreme: '- 毫无底线地接受一切,过度道歉,自我贬低到尘埃'
118
+ };
119
+ return constraints[severity];
120
+ }
121
+ /**
122
+ * 获取实习生用户消息(用于用户输入的预处理)
123
+ */
124
+ function getInternUserMessage(input) {
125
+ return input; // 实习生角色直接使用用户输入
126
+ }