@myclaw163/clawclaw-cli 0.6.69 → 0.6.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myclaw163/clawclaw-cli",
3
- "version": "0.6.69",
3
+ "version": "0.6.70",
4
4
  "type": "module",
5
5
  "description": "ClawClaw social deduction game CLI",
6
6
  "bin": {
@@ -8,10 +8,12 @@
8
8
  ccl strategy --list
9
9
  ```
10
10
 
11
- `--list` 返回当前实际加载到的策略 `id` 和 `description`,包括内置策略、Hub 策略和本地自定义策略;如果用户用同名策略覆盖官方策略,也以这里显示的结果为准。
11
+ `--list` 返回当前实际加载到的策略 `id`、`name` 和 `description`,包括内置策略、Hub 策略和本地自定义策略;如果用户用同名策略覆盖官方策略,也以这里显示的结果为准。
12
12
 
13
13
  `description` 是策略选择的第一入口。它应说明策略做什么、是否需要参数、参数怎么传,以及是否读取 `ccl knowledge`。
14
14
 
15
+ `name` 是策略的中文代词(如「守尸」「武士虾」),是玩家和你口头沟通时用的称呼。玩家说「切到守尸」时,你据此映射回对应 `id`。`id` 仍是规范选择器,但 `ccl strategy <name>`(中文名)与 `ccl strategy <id>` 等价,两者都能启动。
16
+
15
17
  ## 策略选择流程
16
18
 
17
19
  1. 先确认当前策略:从 `ccl game start` 短通知、`ccl events` 返回的 state / 事件,或最近一次 `ccl strategy <id>` 的启动结果里,看现在正在跑什么策略。
@@ -25,7 +27,7 @@ ccl strategy --info <id>
25
27
  ```
26
28
 
27
29
  6. 如需让当前策略对特定玩家或事实做出反应,使用 `ccl knowledge` 写入判断;如果是整体目标变化,则切换策略。
28
- 7. 启动策略:
30
+ 7. 启动策略(`<id>` 处也可填中文 `name`):
29
31
 
30
32
  ```bash
31
33
  ccl strategy <id> [args...]
@@ -54,4 +56,4 @@ ccl strategy --info <id>
54
56
 
55
57
  ## 能力边界说明
56
58
 
57
- > **策略是有限集合——不要暗示它们无所不能。** `ccl strategy --list` 是当前实际可用策略目录。**当用户要求的玩法超出这些策略能力时,直说——告诉用户当前策略不支持。** 不要拖延、不要假装某个策略能做到、不要沉默忽略请求。然后提供最接近的方案:让现有策略覆盖能做的部分,其余用 `ccl do`(发言/投票/思考)、手动 `ccl strategy` 切换或手动移动来处理——明确指出哪些是策略自动化的、哪些是你手动操作的、哪些确实无法实现。当差距真实存在——请求需要当前策略都不支持的自动化行为时——主动引导用户到 clawclawhub:`ccl hub search` 浏览社区策略,`ccl hub install <type>/<id>` 安装用户选中的。安装后用 `ccl strategy --list` 确认策略可用。如果那里也不适合,建议创建自定义策略:在 `<workspace>/strategies/` 下放 `.ts` / `.js` 文件,导出 `strategy`(id / description / create),从 `clawclaw-cli` 导入辅助函数。主动提出为他们编写——API 和示例见 `ccl strategy -h` 和 `docs/自定义策略.md`。
59
+ > **策略是有限集合——不要暗示它们无所不能。** `ccl strategy --list` 是当前实际可用策略目录。**当用户要求的玩法超出这些策略能力时,直说——告诉用户当前策略不支持。** 不要拖延、不要假装某个策略能做到、不要沉默忽略请求。然后提供最接近的方案:让现有策略覆盖能做的部分,其余用 `ccl do`(发言/投票/思考)、手动 `ccl strategy` 切换或手动移动来处理——明确指出哪些是策略自动化的、哪些是你手动操作的、哪些确实无法实现。当差距真实存在——请求需要当前策略都不支持的自动化行为时——主动引导用户到 clawclawhub:`ccl hub search` 浏览社区策略,`ccl hub install <type>/<id>` 安装用户选中的。安装后用 `ccl strategy --list` 确认策略可用。如果那里也不适合,建议创建自定义策略:在 `<workspace>/strategies/` 下放 `.ts` / `.js` 文件,导出 `strategy`(id / name / description / create),从 `clawclaw-cli` 导入辅助函数。主动提出为他们编写——API 和示例见 `ccl strategy -h` 和 `docs/自定义策略.md`。
@@ -109,6 +109,15 @@ describe('strategy command', () => {
109
109
  // knowledge might be null if no .knowledge.md file exists
110
110
  });
111
111
 
112
+ it('should resolve a Chinese name and show its knowledge contract', async () => {
113
+ await run(['--info', '武士虾']);
114
+
115
+ const output = JSON.parse(logs[0]);
116
+ expect(output.id).toBe('warrior-memory');
117
+ expect(output.name).toBe('武士虾');
118
+ expect(output.knowledge).toContain('warrior-memory');
119
+ });
120
+
112
121
  it('should reject non-existent strategies', async () => {
113
122
  await expect(run(['--info', 'non-existent'])).rejects.toThrow('process.exit');
114
123
 
@@ -129,6 +138,7 @@ describe('strategy command', () => {
129
138
  // Check that task-only is in the list
130
139
  const taskOnly = output.strategies.find((s: any) => s.id === 'task-only');
131
140
  expect(taskOnly).toBeDefined();
141
+ expect(taskOnly.name).toBe('纯任务');
132
142
  expect(taskOnly.description).toBeDefined();
133
143
  });
134
144
  });
@@ -31,7 +31,7 @@ export function createStrategyCommand(): Command {
31
31
  Custom strategies:
32
32
  Place .ts or .js files in ${strategiesDir}
33
33
  (or $CLAWCLAW_WORKSPACE_DIR/strategies/)
34
- Each file must export a 'strategy' object with id, description, and create() function.
34
+ Each file must export a 'strategy' object with id, name (中文别名), description, and create() function.
35
35
  Use 'import { ... } from "@myclaw163/clawclaw-cli"' to access Action, GameState, and utilities.
36
36
  See docs/自定义策略.md for full API reference and examples.
37
37
  `;
@@ -49,8 +49,8 @@ Custom strategies:
49
49
  }, null, 2));
50
50
  process.exit(1);
51
51
  }
52
- const knowledge = await getStrategyKnowledgeDoc(opts.info);
53
- console.log(JSON.stringify({ id: opts.info, description: entry.description, knowledge: knowledge ?? null }, null, 2));
52
+ const knowledge = await getStrategyKnowledgeDoc(entry.id);
53
+ console.log(JSON.stringify({ id: entry.id, name: entry.name ?? entry.id, description: entry.description, knowledge: knowledge ?? null }, null, 2));
54
54
  return;
55
55
  }
56
56
 
@@ -87,7 +87,7 @@ Custom strategies:
87
87
  return;
88
88
  }
89
89
  console.log(JSON.stringify({
90
- strategies: entries.map(e => ({ id: e.id, description: e.description })),
90
+ strategies: entries.map(e => ({ id: e.id, name: e.name ?? e.id, description: e.description })),
91
91
  }, null, 2));
92
92
  return;
93
93
  }
@@ -120,7 +120,7 @@ Custom strategies:
120
120
  console.error(JSON.stringify({
121
121
  error: 'unknown_strategy',
122
122
  message: `Unknown strategy '${name}'.`,
123
- available: available.map(e => ({ id: e.id, description: e.description })),
123
+ available: available.map(e => ({ id: e.id, name: e.name ?? e.id, description: e.description })),
124
124
  }, null, 2));
125
125
  process.exit(1);
126
126
  }
@@ -136,7 +136,7 @@ Custom strategies:
136
136
  process.exit(1);
137
137
  }
138
138
 
139
- if (KILL_STRATEGIES.has(name)) {
139
+ if (KILL_STRATEGIES.has(entry.id)) {
140
140
  try {
141
141
  const client = GameClient.fromAuth();
142
142
  await client.discoverGameServer();
@@ -146,8 +146,8 @@ Custom strategies:
146
146
  if (role && !KILL_CAPABLE_ROLES.has(role)) {
147
147
  console.error(JSON.stringify({
148
148
  error: 'role_incompatible',
149
- message: `Strategy '${name}' requires kill ability, but your role '${displayName}' (${role}) cannot kill. Use a non-kill strategy like task-report, patrol, or report-patrol.`,
150
- strategy: name,
149
+ message: `Strategy '${entry.id}' requires kill ability, but your role '${displayName}' (${role}) cannot kill. Use a non-kill strategy like task-report, patrol, or report-patrol.`,
150
+ strategy: entry.id,
151
151
  role,
152
152
  }, null, 2));
153
153
  process.exit(1);
@@ -158,7 +158,7 @@ Custom strategies:
158
158
  const profile = new AuthStore().getActive();
159
159
  const response = profile
160
160
  ? await sendOwnerControlRequest(getProfileStateDir(profile), 'switch_strategy', {
161
- strategy: name,
161
+ strategy: entry.id,
162
162
  args: args.length > 0 ? args : undefined,
163
163
  })
164
164
  : null;
@@ -170,7 +170,8 @@ Custom strategies:
170
170
  process.exit(1);
171
171
  }
172
172
  console.log(JSON.stringify({
173
- message: `Strategy started: ${name}`,
173
+ message: `Strategy started: ${entry.id}`,
174
+ name: entry.name ?? entry.id,
174
175
  description: entry.description,
175
176
  pid: response.pid,
176
177
  }, null, 2));
@@ -4,6 +4,7 @@ import { AvoidLoneTop } from './goals/avoid-lone-top.js';
4
4
 
5
5
  export const strategy: StrategyEntry = {
6
6
  id: 'avoid-lone',
7
+ name: '结伴',
7
8
  description: '避免落单。视野里只有一个人时寻路躲避主动避开(推演逃点、持续远离);视野里有两人以上时跟住次近的玩家、把可见人数维持在 ≥2(最近的人本就贴着不会丢,次近的人才是跌回一对一的临界);持续无人或没有当前目标时巡逻。',
8
9
  create() {
9
10
  return new GoalRootStrategy('avoid-lone', () => new AvoidLoneTop(), { resetOnMeetingResume: false });
@@ -5,6 +5,7 @@ import { parseTargetArgs } from './player-targets.js';
5
5
 
6
6
  export const strategy: StrategyEntry = {
7
7
  id: 'avoid-players',
8
+ name: '避人',
8
9
  description: '回避玩家:按房间顺序巡逻,视野里出现回避目标就寻路躲避(推演逃点、持续远离),威胁消失后恢复巡逻。回避名单 = 启动参数(座位号或名字,可多人,可省略)∪ 知识库中标记为 hostile(坏人)的玩家;trusted 与未标记的被怀疑者都不自动回避(要躲就标 hostile 或用启动参数点名)。Agent 可用 `ccl knowledge mark` 动态改判,免重启。',
9
10
  create(args?: string[]) {
10
11
  const targets = args ? parseTargetArgs(args) : [];
@@ -15,6 +15,7 @@ class CorpsePatrolStrategy extends GoalRootStrategy {
15
15
 
16
16
  export const strategy: StrategyEntry = {
17
17
  id: 'corpse-patrol',
18
+ name: '守尸',
18
19
  description: '发现尸体就在附近40至100距离内随机游荡,但不报告——故意在尸体旁出没制造嫌疑感。没有尸体时巡逻各房间。传入打招呼话术时,视野内出现人就随机发送一条,之后120秒内不再发言。不做任务,不杀人;但残局(已知存活≤6)出现紧急维修任务时例外,会最高优先级抢着去做,阻止蟹靠破坏倒计时取胜。(天堂鱼默认;进阶版见 paradise-fish)参数:可选:1~3 条打招呼话术。',
19
20
  create(args?: string[]) {
20
21
  return new CorpsePatrolStrategy(parseGreetingArgs(args, 'corpse-patrol'));
@@ -6,6 +6,7 @@ import { SpeechModule, getSpeechConfigForRole } from './speech-module.js';
6
6
 
7
7
  export const strategy: StrategyEntry = {
8
8
  id: 'crab-sabotage',
9
+ name: '破坏蟹',
9
10
  description: '优先完成蟹的真实破坏任务(破坏点紧挨已知尸体时会跳过);做完立刻触发紧急警报;警报期照样会被举报、不乱杀,只清真正落单的目标。有紧急事件时跳过破坏流程。视野里只有一个非队友且冷却可用就靠近,进入50距离就立刻出刀,即使正在做破坏任务;刀在冷却时不追不等、改做低优先级任务伪装,冷却好且目标仍落单可见再出刀;正在做任务时不会撇下任务去追猎(贴脸且刀好仍会立刻出刀)。发现尸体且附近有非队友、但当前不能原地出刀时,会靠近并报告尸体。视野里出现两人以上时,暂停攻击10秒并做任务伪装,先做真实任务再做虾的伪装任务;选任务时会跳过紧挨已知尸体(含看见过、已离开视野的)的任务。没有可做任务时按房间巡逻,绝不停在原地。(普通蟹默认)',
10
11
  create(args?: string[]) {
11
12
  const role = args?.[0] ?? 'crab_generic';
@@ -73,6 +73,7 @@ class TestCustomModuleStrategy implements Strategy {
73
73
 
74
74
  const testEntry: StrategyEntry = {
75
75
  id: 'test-custom-module',
76
+ name: 'test-custom-module',
76
77
  description: 'Internal test strategy for CustomModule verification.',
77
78
  create() {
78
79
  return new TestCustomModuleStrategy();
@@ -5,6 +5,7 @@ import { parseTargetArgs } from './player-targets.js';
5
5
 
6
6
  export const strategy: StrategyEntry = {
7
7
  id: 'find-player',
8
+ name: '盯人',
8
9
  description: '全力寻找并贴身跟踪一个指定目标(座位号或名字,单个)。看到就贴上去近距离尾随(约40距离);跟丢就先奔向最后出现的位置,再按房间顺序不停巡逻直到目标重新出现,绝不放弃。只跟踪、不出刀、不做任务、不报告;目标死亡即停。',
9
10
  create(args?: string[]) {
10
11
  const targets = args ? parseTargetArgs(args) : [];
@@ -14,6 +14,7 @@ export function parseHideKillArg(args?: string[]): boolean | null {
14
14
 
15
15
  export const strategy: StrategyEntry = {
16
16
  id: 'hide',
17
+ name: '躲藏',
17
18
  description:
18
19
  '躲藏策略:在离线从地图算好的若干「非走廊、≥2 出口可逃、远离任务点/出生点」的藏身角落里,选测地最近且不挨威胁的一个潜伏不动;视野里一出现非队友,就像 shrimp-memory 那样保持距离甩开(KeepAway),并边逃边重算排除该威胁的新藏点,逃完落到新点继续潜伏。蟹不躲队友。可选参数 kill / nokill 控制「被单个对手逼进出刀距离且无路可逃时是否出刀自保」——缺省按角色:蟹/章鱼默认开,武士虾/枪虾(及无刀角色)默认关。',
19
20
  create(args?: string[]) {
@@ -4,6 +4,7 @@ import { KillFrenzyTop } from './goals/kill-frenzy-top.js';
4
4
 
5
5
  export const strategy: StrategyEntry = {
6
6
  id: 'kill-frenzy',
7
+ name: '屠夫',
7
8
  description:
8
9
  '疯狂砍人:见谁杀谁(除队友外所有可见玩家),多人在场也照杀。按房间顺序巡逻,视野里只要有非队友就冲向最近的那个,50内且冷却好就出刀,冷却中保持10距离贴身跟随等冷却。与 kill-lone 不同,不会因为周围人多而暂停攻击。永不停手。',
9
10
  create() {
@@ -5,6 +5,7 @@ import { parseTargetArgs } from './player-targets.js';
5
5
 
6
6
  export const strategy: StrategyEntry = {
7
7
  id: 'kill-lone',
8
+ name: '猎独',
8
9
  description: '按照房间顺序进行巡逻,巡逻时遇到人会判断。可传入避免击杀的座位号或名字列表。视野里只有一个非队友且不在避免名单内就靠近,进入50距离就出刀;冷却中贴在10距离附近等。视野里出现两人以上时,暂停攻击10秒并继续巡逻。',
9
10
  create(args?: string[]) {
10
11
  const protectedTargets = args ? parseTargetArgs(args) : [];
@@ -5,6 +5,7 @@ import { parseTargetArgs } from './player-targets.js';
5
5
 
6
6
  export const strategy: StrategyEntry = {
7
7
  id: 'kill-target',
8
+ name: '追杀',
8
9
  description: '专门追杀指定目标(传入座位号或名字,可多人)。按照房间顺序进行巡逻,目标进入视野就冲上去,50内且冷却好就出刀;冷却中保持10距离贴身跟随等待。找目标时路过其他玩家不会停步。所有目标死亡后停止。',
9
10
  create(args?: string[]) {
10
11
  const targets = args ? parseTargetArgs(args) : [];
@@ -136,9 +136,16 @@ async function ensureLoaded(): Promise<void> {
136
136
  if (userDir) await loadFromDir(userDir, false);
137
137
  }
138
138
 
139
- export async function getStrategyEntry(id: string): Promise<StrategyEntry | undefined> {
139
+ export async function getStrategyEntry(idOrName: string): Promise<StrategyEntry | undefined> {
140
140
  await ensureLoaded();
141
- return strategyMap.get(id);
141
+ const byId = strategyMap.get(idOrName);
142
+ if (byId) return byId;
143
+ // Fall back to the Chinese display name (StrategyEntry.name). id always wins,
144
+ // so this only resolves an alias when no id matched.
145
+ for (const entry of strategyMap.values()) {
146
+ if (entry.name === idOrName) return entry;
147
+ }
148
+ return undefined;
142
149
  }
143
150
 
144
151
  export async function listStrategyEntries(): Promise<StrategyEntry[]> {
@@ -6,6 +6,7 @@ import { SpeechModule, getSpeechConfigForRole } from './speech-module.js';
6
6
 
7
7
  export const strategy: StrategyEntry = {
8
8
  id: 'lone-kill-task',
9
+ name: '潜伏猎手',
9
10
  description: '视野里只有一个非队友且冷却可用就靠近,进入50距离就立刻出刀;刀在冷却时不追不等、改做低优先级任务伪装,冷却好且目标仍落单可见再出刀(贴脸且刀好仍会立刻出刀)。发现尸体且附近有非队友、但当前不能原地出刀时,会靠近并报告尸体。视野里出现两人以上时,暂停攻击10秒并做任意阵营的真实任务伪装;选任务时会跳过紧挨已知尸体(含看见过、已离开视野的)的任务,不在命案现场做任务。没有可做任务时按房间巡逻,绝不停在原地。残局(已知存活≤6)出现紧急维修任务时,会高优先级抢着去做(仍低于击杀落单),阻止蟹靠破坏倒计时取胜。(章鱼默认)',
10
11
  create(args?: string[]) {
11
12
  const role = args?.[0] ?? 'neutral_octopus';
@@ -4,6 +4,7 @@ import { MoveRoomGoal } from './goals/move-room-goal.js';
4
4
 
5
5
  export const strategy: StrategyEntry = {
6
6
  id: 'move-room',
7
+ name: '前往',
7
8
  description: '前往指定房间,到达后停下。参数为目标房间名(如 酒吧)。单纯走位,不做任务、不打人、不报告。',
8
9
  create(args?: string[]) {
9
10
  const targetRoom = args?.join(' ').trim() ?? '';
@@ -17,6 +17,7 @@ class ParadiseFishStrategy extends GoalRootStrategy {
17
17
 
18
18
  export const strategy: StrategyEntry = {
19
19
  id: 'paradise-fish',
20
+ name: '天堂鱼',
20
21
  description:
21
22
  '天堂鱼·进阶版(中立,不报警、不做任务,靠被投票出局取胜;corpse-patrol 的带记忆升级)。读取 ccl knowledge 两档标记(hostile=坏人 / trusted=好人),未标记的一律默认被怀疑:hostile 视为危险硬寻路远离,被怀疑者按目击者规则保持距离,trusted 视为可抱团的可信同伴。发现尸体绝不报警,贴着尸体游走制造嫌疑;附近有人时远离那人但仍在尸体附近活动。残局(已知存活≤6)出现紧急维修任务时,会在没有带刀坏人需要躲避时优先抢着去做(先于对陌生人保持距离/贴尸/抱团),阻止蟹靠破坏倒计时取胜。传入打招呼话术时,视野内出现人就随机发送一条,之后120秒内不再发言。',
22
23
  create(args?: string[]) {
@@ -4,6 +4,7 @@ import { PatrolTop } from './goals/patrol-top.js';
4
4
 
5
5
  export const strategy: StrategyEntry = {
6
6
  id: 'patrol',
7
+ name: '巡逻',
7
8
  description: '按地图房间顺序依次游走,到达一个房间后自动前往下一个,循环往复。卡路时会跳过当前目标换下一个房间。纯游走,不做任务、不打人、不报告尸体。',
8
9
  create() {
9
10
  return new GoalRootStrategy('patrol', () => new PatrolTop(), { resetOnMeetingResume: false });
@@ -4,6 +4,7 @@ import { ReportPatrolTop } from './goals/report-patrol-top.js';
4
4
 
5
5
  export const strategy: StrategyEntry = {
6
6
  id: 'report-patrol',
7
+ name: '报警',
7
8
  description: '专门找尸体:达到报告距离立刻报告,看到尸体就靠近;没有尸体就巡逻各房间。不做任何任务,不打人,目标是让会议尽快开起来。',
8
9
  create() {
9
10
  return new GoalRootStrategy('report-patrol', () => new ReportPatrolTop(), { resetOnMeetingResume: false });
@@ -17,6 +17,7 @@ class ShrimpMemoryStrategy extends GoalRootStrategy {
17
17
 
18
18
  export const strategy: StrategyEntry = {
19
19
  id: 'shrimp-memory',
20
+ name: '精英虾',
20
21
  description:
21
22
  '普通虾·记忆进阶版(好人、不带刀;task-report 的带记忆升级)。读取 ccl knowledge 两档标记(hostile=坏人 / trusted=好人),未标记的一律默认被怀疑:hostile 硬寻路远离,trusted 视为可信同伴,被怀疑者按目击者规则保持距离。发现尸体最优先报警,并提示复核尸体旁身份不明者;无可信同伴且单个被怀疑者贴近270内时先拉开距离到300再做任务;再处理紧急任务,最后做任务/巡逻(选测地最近、跳过威胁旁或必经威胁的任务)。永不出刀。传入打招呼话术时,视野内出现人就随机发送一条,之后120秒内不再发言。',
22
23
  create(args?: string[]) {
@@ -33,6 +33,7 @@ export function parseSocialArgs(args: string[]): SocialTarget[] {
33
33
 
34
34
  export const strategy: StrategyEntry = {
35
35
  id: 'social-task',
36
+ name: '社交',
36
37
  description: '针对指定玩家社交(参数格式 座位=话术 或纯座位,可多人)。视野内出现目标就靠近,没打过招呼先发一次招呼;对方说话就停下等你回复,10秒没回应就转去做任务。全程见到可报告的尸体就报、见到尸体就靠近。不打人。参数:座位=话术 / 座位(可多人)。',
37
38
  create(args?: string[]) {
38
39
  if (!args || args.length === 0) {
@@ -4,6 +4,7 @@ import { TaskKillReportTop } from './goals/task-kill-report-top.js';
4
4
 
5
5
  export const strategy: StrategyEntry = {
6
6
  id: 'task-kill-report',
7
+ name: '任务刺客',
7
8
  description: '需传入嫌疑目标(座位号或名字,可多人)。看到目标且冷却好,50内就出刀,否则追上去;冷却中贴身跟随。目标不在视野时,遇到尸体就报告;没尸体就做普通任务。',
8
9
  create(args?: string[]) {
9
10
  if (!args || args.length === 0) {
@@ -4,6 +4,7 @@ import { TaskOnlyTop } from './goals/task-only-top.js';
4
4
 
5
5
  export const strategy: StrategyEntry = {
6
6
  id: 'task-only',
7
+ name: '纯任务',
7
8
  description: '专心做任务。紧急任务出现时优先处理,其次按顺序完成普通任务,如果是蟹,则蟹的伪装任务也会做。没有尸体报告和战斗行为。',
8
9
  create() {
9
10
  return new GoalRootStrategy('task-only', () => new TaskOnlyTop(), { resetOnMeetingResume: false });
@@ -15,6 +15,7 @@ class TaskReportStrategy extends GoalRootStrategy {
15
15
 
16
16
  export const strategy: StrategyEntry = {
17
17
  id: 'task-report',
18
+ name: '尽责虾',
18
19
  description: '遇尸体最优先:达到报告距离立刻报告,没达到距离就靠近准备报告。紧急任务出现时优先处理,其次按顺序完成普通任务。传入打招呼话术时,视野内出现人就随机发送一条,之后120秒内不再发言。(普通虾默认;进阶版见 shrimp-memory)参数:可选:1~3 条打招呼话术。',
19
20
  create(args?: string[]) {
20
21
  return new TaskReportStrategy(parseGreetingArgs(args, 'task-report'));
@@ -45,6 +45,13 @@ export interface Strategy {
45
45
 
46
46
  export interface StrategyEntry {
47
47
  readonly id: string;
48
+ /**
49
+ * 中文展示名/代词,玩家与 agent 沟通时使用(如「守尸」「武士虾」)。会出现在
50
+ * `ccl strategy --list`/`--info` 输出里,并可作为 `ccl strategy <名>` 的输入。
51
+ * 注意:这与 `Strategy.name`(`create()` 返回对象的内部 id 名)不是一回事。
52
+ * 须全局唯一。
53
+ */
54
+ readonly name: string;
48
55
  readonly description: string;
49
56
  create(args?: string[]): Strategy;
50
57
  }
@@ -5,6 +5,7 @@ import { parseTargetArgs } from './player-targets.js';
5
5
 
6
6
  export const strategy: StrategyEntry = {
7
7
  id: 'warrior-memory',
8
+ name: '武士虾',
8
9
  description:
9
10
  '带刀虾·记忆进阶版(武士虾/枪虾通用,好人带刀;kill-lone 的带记忆升级)。读取 ccl knowledge 两档标记(hostile=坏人 / trusted=好人),未标记的一律默认被怀疑:hostile 刀好时主动追杀、刀不好时硬回避,trusted 视为可信同伴且绝不攻击。**只对【已确认 hostile / 启动猎杀目标】出刀**——被怀疑者一律只回避、绝不出刀(无可信同伴且单个被怀疑者贴近270内时先拉开到300再做任务,多人互为目击者则照常做任务);不再有任何贴身追击判定/诱饵试探/绝境自卫(几何上分不开"贴身跟我观察的好人"和"贴身追我的凶手",自卫迟早误杀同阵营好人触发武士虾自爆,整套已删除)。发现尸体优先报警;尸体旁若是 hostile/启动猎杀目标且刀可用会现场先手击杀,但绝不会因尸体旁有未报警的身份不明者就灭口(已根治该误杀);无危险时优先紧急任务,否则做任务/巡逻。枪虾会尊重剩余出刀次数。',
10
11
  create(args?: string[]) {