@downcity/plugins 1.0.57 → 1.0.60

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 (145) hide show
  1. package/bin/BuiltinPlugins.d.ts +24 -2
  2. package/bin/BuiltinPlugins.d.ts.map +1 -1
  3. package/bin/BuiltinPlugins.js +18 -5
  4. package/bin/BuiltinPlugins.js.map +1 -1
  5. package/bin/auth/types/AuthPlugin.d.ts +12 -16
  6. package/bin/auth/types/AuthPlugin.d.ts.map +1 -1
  7. package/bin/auth/types/AuthPlugin.js +9 -13
  8. package/bin/auth/types/AuthPlugin.js.map +1 -1
  9. package/bin/chat/ChatPlugin.d.ts +37 -6
  10. package/bin/chat/ChatPlugin.d.ts.map +1 -1
  11. package/bin/chat/ChatPlugin.js +58 -80
  12. package/bin/chat/ChatPlugin.js.map +1 -1
  13. package/bin/chat/Index.d.ts +4 -1
  14. package/bin/chat/Index.d.ts.map +1 -1
  15. package/bin/chat/Index.js +2 -1
  16. package/bin/chat/Index.js.map +1 -1
  17. package/bin/chat/channels/Configuration.d.ts +1 -1
  18. package/bin/chat/channels/Configuration.js +1 -1
  19. package/bin/chat/channels/RuntimeChannel.d.ts +145 -0
  20. package/bin/chat/channels/RuntimeChannel.d.ts.map +1 -0
  21. package/bin/chat/channels/RuntimeChannel.js +148 -0
  22. package/bin/chat/channels/RuntimeChannel.js.map +1 -0
  23. package/bin/chat/runtime/ChatAuthorizationRuntime.d.ts +22 -0
  24. package/bin/chat/runtime/ChatAuthorizationRuntime.d.ts.map +1 -0
  25. package/bin/chat/runtime/ChatAuthorizationRuntime.js +189 -0
  26. package/bin/chat/runtime/ChatAuthorizationRuntime.js.map +1 -0
  27. package/bin/chat/runtime/ChatChannelActions.d.ts.map +1 -1
  28. package/bin/chat/runtime/ChatChannelActions.js +19 -9
  29. package/bin/chat/runtime/ChatChannelActions.js.map +1 -1
  30. package/bin/chat/runtime/ChatChannelConfig.d.ts +2 -18
  31. package/bin/chat/runtime/ChatChannelConfig.d.ts.map +1 -1
  32. package/bin/chat/runtime/ChatChannelConfig.js +2 -73
  33. package/bin/chat/runtime/ChatChannelConfig.js.map +1 -1
  34. package/bin/chat/runtime/ChatChannelCore.d.ts +22 -1
  35. package/bin/chat/runtime/ChatChannelCore.d.ts.map +1 -1
  36. package/bin/chat/runtime/ChatChannelCore.js +5 -5
  37. package/bin/chat/runtime/ChatChannelCore.js.map +1 -1
  38. package/bin/chat/runtime/ChatPluginActionRegistry.js +1 -1
  39. package/bin/chat/runtime/ChatPluginActionRegistry.js.map +1 -1
  40. package/bin/chat/runtime/PluginPoints.d.ts +3 -3
  41. package/bin/chat/runtime/PluginPoints.js +3 -3
  42. package/bin/chat/types/ChannelStatus.d.ts +1 -1
  43. package/bin/chat/types/ChatPluginOptions.d.ts +76 -0
  44. package/bin/chat/types/ChatPluginOptions.d.ts.map +1 -0
  45. package/bin/chat/types/ChatPluginOptions.js +10 -0
  46. package/bin/chat/types/ChatPluginOptions.js.map +1 -0
  47. package/bin/contact/ContactPlugin.d.ts +6 -1
  48. package/bin/contact/ContactPlugin.d.ts.map +1 -1
  49. package/bin/contact/ContactPlugin.js +9 -8
  50. package/bin/contact/ContactPlugin.js.map +1 -1
  51. package/bin/contact/types/ContactPluginOptions.d.ts +29 -0
  52. package/bin/contact/types/ContactPluginOptions.d.ts.map +1 -0
  53. package/bin/contact/types/ContactPluginOptions.js +9 -0
  54. package/bin/contact/types/ContactPluginOptions.js.map +1 -0
  55. package/bin/index.d.ts +7 -4
  56. package/bin/index.d.ts.map +1 -1
  57. package/bin/index.js +3 -2
  58. package/bin/index.js.map +1 -1
  59. package/bin/skill/Action.d.ts.map +1 -1
  60. package/bin/skill/Action.js +2 -2
  61. package/bin/skill/Action.js.map +1 -1
  62. package/bin/skill/Command.js +5 -5
  63. package/bin/skill/Command.js.map +1 -1
  64. package/bin/skill/Plugin.js +1 -1
  65. package/bin/skill/Plugin.js.map +1 -1
  66. package/bin/skill/runtime/Discovery.d.ts +4 -4
  67. package/bin/skill/runtime/Discovery.d.ts.map +1 -1
  68. package/bin/skill/runtime/Discovery.js +5 -5
  69. package/bin/skill/runtime/Discovery.js.map +1 -1
  70. package/bin/skill/runtime/Paths.d.ts +1 -5
  71. package/bin/skill/runtime/Paths.d.ts.map +1 -1
  72. package/bin/skill/runtime/Paths.js +1 -9
  73. package/bin/skill/runtime/Paths.js.map +1 -1
  74. package/bin/skill/runtime/Prompt.d.ts +2 -2
  75. package/bin/skill/runtime/Prompt.d.ts.map +1 -1
  76. package/bin/skill/runtime/Prompt.js +3 -3
  77. package/bin/skill/runtime/Prompt.js.map +1 -1
  78. package/bin/skill/runtime/Store.d.ts +2 -2
  79. package/bin/skill/runtime/Store.d.ts.map +1 -1
  80. package/bin/skill/runtime/Store.js.map +1 -1
  81. package/bin/skill/runtime/SystemProvider.js +4 -4
  82. package/bin/skill/runtime/SystemProvider.js.map +1 -1
  83. package/bin/skill/runtime/Types.d.ts +3 -3
  84. package/bin/skill/runtime/Types.d.ts.map +1 -1
  85. package/bin/skill/types/{ClaudeSkill.d.ts → SkillDefinition.d.ts} +4 -4
  86. package/bin/skill/types/SkillDefinition.d.ts.map +1 -0
  87. package/bin/skill/types/{ClaudeSkill.js → SkillDefinition.js} +2 -2
  88. package/bin/skill/types/SkillDefinition.js.map +1 -0
  89. package/bin/skill/types/SkillPlugin.d.ts +2 -2
  90. package/bin/skill/types/SkillPlugin.d.ts.map +1 -1
  91. package/bin/web/Plugin.js +1 -1
  92. package/bin/web/Plugin.js.map +1 -1
  93. package/bin/web/runtime/Install.js +2 -2
  94. package/bin/web/runtime/Install.js.map +1 -1
  95. package/bin/web/types/WebPlugin.d.ts +2 -1
  96. package/bin/web/types/WebPlugin.d.ts.map +1 -1
  97. package/bin/workboard/Plugin.d.ts +23 -3
  98. package/bin/workboard/Plugin.d.ts.map +1 -1
  99. package/bin/workboard/Plugin.js +66 -85
  100. package/bin/workboard/Plugin.js.map +1 -1
  101. package/package.json +2 -2
  102. package/src/BuiltinPlugins.ts +41 -5
  103. package/src/auth/types/AuthPlugin.ts +12 -17
  104. package/src/chat/ChatPlugin.ts +92 -89
  105. package/src/chat/Index.ts +18 -1
  106. package/src/chat/channels/Configuration.ts +1 -1
  107. package/src/chat/channels/RuntimeChannel.ts +264 -0
  108. package/src/chat/runtime/ChatAuthorizationRuntime.ts +229 -0
  109. package/src/chat/runtime/ChatChannelActions.ts +24 -9
  110. package/src/chat/runtime/ChatChannelConfig.ts +2 -100
  111. package/src/chat/runtime/ChatChannelCore.ts +20 -8
  112. package/src/chat/runtime/ChatPluginActionRegistry.ts +1 -1
  113. package/src/chat/runtime/PluginPoints.ts +3 -3
  114. package/src/chat/types/ChannelStatus.ts +1 -1
  115. package/src/chat/types/ChatPluginOptions.ts +79 -0
  116. package/src/contact/ContactPlugin.ts +17 -9
  117. package/src/contact/types/ContactPluginOptions.ts +30 -0
  118. package/src/index.ts +23 -7
  119. package/src/skill/Action.ts +10 -7
  120. package/src/skill/Command.ts +5 -5
  121. package/src/skill/Plugin.ts +1 -1
  122. package/src/skill/runtime/Discovery.ts +14 -11
  123. package/src/skill/runtime/Paths.ts +1 -13
  124. package/src/skill/runtime/Prompt.ts +5 -5
  125. package/src/skill/runtime/Store.ts +6 -3
  126. package/src/skill/runtime/SystemProvider.ts +4 -4
  127. package/src/skill/runtime/Types.ts +3 -3
  128. package/src/skill/types/{ClaudeSkill.ts → SkillDefinition.ts} +3 -3
  129. package/src/skill/types/SkillPlugin.ts +2 -2
  130. package/src/web/Plugin.ts +1 -1
  131. package/src/web/runtime/Install.ts +3 -3
  132. package/src/web/types/WebPlugin.ts +2 -2
  133. package/src/workboard/Plugin.ts +80 -95
  134. package/bin/auth/Plugin.d.ts +0 -17
  135. package/bin/auth/Plugin.d.ts.map +0 -1
  136. package/bin/auth/Plugin.js +0 -199
  137. package/bin/auth/Plugin.js.map +0 -1
  138. package/bin/chat/ChatPluginTypes.d.ts +0 -122
  139. package/bin/chat/ChatPluginTypes.d.ts.map +0 -1
  140. package/bin/chat/ChatPluginTypes.js +0 -10
  141. package/bin/chat/ChatPluginTypes.js.map +0 -1
  142. package/bin/skill/types/ClaudeSkill.d.ts.map +0 -1
  143. package/bin/skill/types/ClaudeSkill.js.map +0 -1
  144. package/src/auth/Plugin.ts +0 -237
  145. package/src/chat/ChatPluginTypes.ts +0 -126
@@ -0,0 +1,30 @@
1
+ /**
2
+ * ContactPluginOptions:ContactPlugin 构造参数。
3
+ *
4
+ * 关键点(中文)
5
+ * - 这里只保留 agent 运行时真正需要的显式配置。
6
+ * - contact token、link secret 等协议密钥都由运行时自动生成,不从 constructor 传入。
7
+ */
8
+
9
+ /**
10
+ * ContactPlugin 构造参数。
11
+ */
12
+ export interface ContactPluginOptions {
13
+ /**
14
+ * 当前 agent 对外可访问的 HTTP endpoint。
15
+ *
16
+ * 说明(中文)
17
+ * - 传入后会优先写入 `contact link` 生成的一次性联系码。
18
+ * - 适合反向代理、tunnel、公网域名等自动探测不可靠的环境。
19
+ */
20
+ endpoint?: string;
21
+
22
+ /**
23
+ * 默认 link 有效秒数。
24
+ *
25
+ * 说明(中文)
26
+ * - `contact link` action 没有显式传 `ttlSeconds` 时使用该值。
27
+ * - 最终运行时仍会强制不少于 60 秒,避免生成过短的人工转交 code。
28
+ */
29
+ ttlSeconds?: number;
30
+ }
package/src/index.ts CHANGED
@@ -11,11 +11,19 @@ export {
11
11
  BUILTIN_PLUGIN_CLASSES,
12
12
  createBuiltinPlugins,
13
13
  } from "./BuiltinPlugins.js";
14
- export type { BuiltinPluginClass } from "./BuiltinPlugins.js";
14
+ export type {
15
+ BuiltinPluginClass,
16
+ BuiltinPluginOptions,
17
+ } from "./BuiltinPlugins.js";
15
18
  export { ChatPlugin } from "./chat/ChatPlugin.js";
19
+ export { ContactPlugin } from "./contact/ContactPlugin.js";
20
+ export {
21
+ FeishuChannel,
22
+ QqChannel,
23
+ TelegramChannel,
24
+ } from "./chat/channels/RuntimeChannel.js";
16
25
  export { ImagePlugin } from "./image/ImagePlugin.js";
17
26
  export { ChatChannelAccountManager } from "./chat/accounts/ChannelAccountManager.js";
18
- export { ChatAuthorizationPlugin } from "./auth/Plugin.js";
19
27
  export { SkillPlugin } from "./skill/Plugin.js";
20
28
  export { WebPlugin } from "./web/Plugin.js";
21
29
  export { AsrPlugin } from "./asr/Plugin.js";
@@ -28,8 +36,9 @@ export {
28
36
  } from "./auth/runtime/AuthorizationConfig.js";
29
37
  export { resolveAuthorizedUserRole } from "./auth/runtime/AuthorizationPolicy.js";
30
38
  export {
39
+ CHAT_AUTHORIZATION_ACTIONS,
31
40
  CHAT_AUTHORIZATION_CHANNELS,
32
- CHAT_AUTHORIZATION_PLUGIN_NAME,
41
+ CHAT_AUTHORIZATION_POINTS,
33
42
  createDefaultChatAuthorizationRoles,
34
43
  isChatAuthorizationChannel,
35
44
  } from "./auth/types/AuthPlugin.js";
@@ -38,11 +47,18 @@ export type {
38
47
  ChatChannelAccountListItem,
39
48
  } from "./chat/types/ChannelAccount.js";
40
49
  export type {
41
- ChatPluginFeishuOptions,
50
+ BaseChatChannelOptions,
51
+ ChatChannelEnv,
52
+ FeishuChannelOptions,
53
+ QqChannelOptions,
54
+ TelegramChannelOptions,
55
+ } from "./chat/channels/RuntimeChannel.js";
56
+ export type {
57
+ ChatChannel,
58
+ ChatChannelRuntimePatch,
42
59
  ChatPluginOptions,
43
- ChatPluginQqOptions,
44
- ChatPluginTelegramOptions,
45
- } from "./chat/ChatPluginTypes.js";
60
+ } from "./chat/types/ChatPluginOptions.js";
61
+ export type { ContactPluginOptions } from "./contact/types/ContactPluginOptions.js";
46
62
  export type {
47
63
  AsrPluginInput,
48
64
  AsrPluginOptions,
@@ -8,8 +8,8 @@
8
8
 
9
9
  import fs from "fs-extra";
10
10
  import path from "node:path";
11
- import { discoverClaudeSkillsSync } from "@/skill/runtime/Discovery.js";
12
- import type { ClaudeSkill } from "@/skill/types/ClaudeSkill.js";
11
+ import { discoverSkillsSync } from "@/skill/runtime/Discovery.js";
12
+ import type { SkillDefinition } from "@/skill/types/SkillDefinition.js";
13
13
  import type { JsonValue } from "@downcity/agent/internal/types/common/Json.js";
14
14
  import type {
15
15
  SkillListResponse,
@@ -30,7 +30,7 @@ function normalizeAllowedTools(input: JsonValue | undefined): string[] {
30
30
  return Array.from(new Set(values));
31
31
  }
32
32
 
33
- function toSkillSummary(skill: ClaudeSkill): SkillSummary {
33
+ function toSkillSummary(skill: SkillDefinition): SkillSummary {
34
34
  return {
35
35
  id: skill.id,
36
36
  name: skill.name,
@@ -41,7 +41,10 @@ function toSkillSummary(skill: ClaudeSkill): SkillSummary {
41
41
  };
42
42
  }
43
43
 
44
- function findSkillExact(skills: ClaudeSkill[], name: string): ClaudeSkill | null {
44
+ function findSkillExact(
45
+ skills: SkillDefinition[],
46
+ name: string,
47
+ ): SkillDefinition | null {
45
48
  const q = String(name || "").trim().toLowerCase();
46
49
  if (!q) return null;
47
50
 
@@ -52,7 +55,7 @@ function findSkillExact(skills: ClaudeSkill[], name: string): ClaudeSkill | null
52
55
  );
53
56
  }
54
57
 
55
- function findSkill(skills: ClaudeSkill[], name: string): ClaudeSkill | null {
58
+ function findSkill(skills: SkillDefinition[], name: string): SkillDefinition | null {
56
59
  const q = String(name || "").trim().toLowerCase();
57
60
  if (!q) return null;
58
61
 
@@ -67,9 +70,9 @@ function findSkill(skills: ClaudeSkill[], name: string): ClaudeSkill | null {
67
70
  function getSkills(
68
71
  projectRoot: string,
69
72
  options?: SkillPluginOptions | null,
70
- ): ClaudeSkill[] {
73
+ ): SkillDefinition[] {
71
74
  const root = path.resolve(projectRoot);
72
- return discoverClaudeSkillsSync(root, options);
75
+ return discoverSkillsSync(root, options);
73
76
  }
74
77
 
75
78
  /**
@@ -8,8 +8,8 @@
8
8
 
9
9
  import path from "node:path";
10
10
  import { execa } from "execa";
11
- import { discoverClaudeSkillsSync } from "@/skill/runtime/Discovery.js";
12
- import { getClaudeSkillSearchRoots } from "@/skill/runtime/Paths.js";
11
+ import { discoverSkillsSync } from "@/skill/runtime/Discovery.js";
12
+ import { getSkillSearchRoots } from "@/skill/runtime/Paths.js";
13
13
 
14
14
  async function runNpxSkills(args: string[], opts?: { yes?: boolean }): Promise<number> {
15
15
  const yes = opts?.yes !== false;
@@ -57,7 +57,7 @@ export async function skillInstallCommand(
57
57
  if (!s) throw new Error("Missing spec");
58
58
 
59
59
  const args: string[] = ["add", s];
60
- const agent = String(options.agent || "claude-code").trim();
60
+ const agent = String(options.agent || "").trim();
61
61
  if (agent) args.push("--agent", agent);
62
62
 
63
63
  const yes = options.yes !== false;
@@ -74,8 +74,8 @@ export async function skillInstallCommand(
74
74
  */
75
75
  export async function skillListCommand(cwd: string = "."): Promise<void> {
76
76
  const projectRoot = path.resolve(String(cwd || "."));
77
- const roots = getClaudeSkillSearchRoots(projectRoot);
78
- const skills = discoverClaudeSkillsSync(projectRoot);
77
+ const roots = getSkillSearchRoots(projectRoot);
78
+ const skills = discoverSkillsSync(projectRoot);
79
79
 
80
80
  console.log("Skill roots:");
81
81
  for (const root of roots) console.log(`- [${root.source}] ${root.display}`);
@@ -166,7 +166,7 @@ function createSkillPluginDefinition(options: SkillPluginOptions): Plugin {
166
166
  .argument("<spec>")
167
167
  .option("-g, --global", "全局安装(默认 true)", true)
168
168
  .option("-y, --yes", "跳过确认(默认 true)", true)
169
- .option("--agent <agent>", "指定 agent", "claude-code");
169
+ .option("--agent <agent>", "指定 agent");
170
170
  },
171
171
  mapInput({ args, opts }): SkillPluginInstallPayload {
172
172
  const spec = String(args[0] || "").trim();
@@ -12,15 +12,18 @@ import path from "path";
12
12
  import type { Dirent, Stats } from "node:fs";
13
13
  import { resolveSkillPluginOptions } from "../Config.js";
14
14
  import { parseFrontMatter } from "./Frontmatter.js";
15
- import { getClaudeSkillSearchRoots } from "./Paths.js";
16
- import type { ClaudeSkill } from "@/skill/types/ClaudeSkill.js";
15
+ import { getSkillSearchRoots } from "./Paths.js";
16
+ import type { SkillDefinition } from "@/skill/types/SkillDefinition.js";
17
17
  import type {
18
18
  SkillPluginIgnoreRule,
19
19
  SkillPluginOptions,
20
20
  } from "@/skill/types/SkillPlugin.js";
21
21
  import type { JsonObject, JsonValue } from "@downcity/agent/internal/types/common/Json.js";
22
22
 
23
- function matchesIgnoreRule(skill: ClaudeSkill, rule: SkillPluginIgnoreRule): boolean {
23
+ function matchesIgnoreRule(
24
+ skill: SkillDefinition,
25
+ rule: SkillPluginIgnoreRule,
26
+ ): boolean {
24
27
  if (typeof rule === "string") {
25
28
  const value = rule.trim().toLowerCase();
26
29
  if (!value) return false;
@@ -41,7 +44,7 @@ function matchesIgnoreRule(skill: ClaudeSkill, rule: SkillPluginIgnoreRule): boo
41
44
  }
42
45
 
43
46
  function shouldIgnoreSkill(
44
- skill: ClaudeSkill,
47
+ skill: SkillDefinition,
45
48
  rules: SkillPluginIgnoreRule[],
46
49
  ): boolean {
47
50
  for (const rule of rules) {
@@ -51,7 +54,7 @@ function shouldIgnoreSkill(
51
54
  }
52
55
 
53
56
  /**
54
- * 扫描并发现 Claude Code-compatible skills。
57
+ * 扫描并发现本地 skills。
55
58
  *
56
59
  * 关键点(中文)
57
60
  * - skills 的扫描根目录与 projectRoot 强相关(默认 `.agents/skills`)
@@ -61,19 +64,19 @@ function shouldIgnoreSkill(
61
64
  * 发现技能算法(中文)
62
65
  * 1) 计算扫描根目录列表
63
66
  * 2) 逐目录读取 `SKILL.md` 与 frontmatter
64
- * 3) 按 id 去重并构造 ClaudeSkill
67
+ * 3) 按 id 去重并构造 SkillDefinition
65
68
  * 4) 最终按 name 排序,保证输出稳定
66
69
  */
67
- export function discoverClaudeSkillsSync(
70
+ export function discoverSkillsSync(
68
71
  projectRoot: string,
69
72
  options?: SkillPluginOptions | null,
70
- ): ClaudeSkill[] {
73
+ ): SkillDefinition[] {
71
74
  const root = String(projectRoot || "").trim();
72
75
  if (!root) return [];
73
76
  const resolvedOptions = resolveSkillPluginOptions(options);
74
- const roots = getClaudeSkillSearchRoots(root, resolvedOptions);
77
+ const roots = getSkillSearchRoots(root, resolvedOptions);
75
78
 
76
- const outById = new Map<string, ClaudeSkill>();
79
+ const outById = new Map<string, SkillDefinition>();
77
80
 
78
81
  for (const r of roots) {
79
82
  const sourceRoot = r.resolved;
@@ -146,7 +149,7 @@ export function discoverClaudeSkillsSync(
146
149
  const allowedTools =
147
150
  meta?.["allowed-tools"] ?? meta?.allowedTools ?? meta?.allowed_tools;
148
151
 
149
- const skill: ClaudeSkill = {
152
+ const skill: SkillDefinition = {
150
153
  id,
151
154
  name,
152
155
  description,
@@ -36,7 +36,7 @@ function resolveSkillRootPath(projectRoot: string, raw: string): string {
36
36
  : path.resolve(projectRoot, expanded);
37
37
  }
38
38
 
39
- export function getClaudeSkillSearchRoots(
39
+ export function getSkillSearchRoots(
40
40
  projectRoot: string,
41
41
  options?: SkillPluginOptions | null,
42
42
  ): SkillRoot[] {
@@ -105,15 +105,3 @@ export function getClaudeSkillSearchRoots(
105
105
 
106
106
  return Array.from(byResolved.values()).sort((a, b) => a.priority - b.priority);
107
107
  }
108
-
109
- // Back-compat(内部仅用于 prompt 展示):保留旧 API 形状,避免外部 import 立刻断裂。
110
- export function getClaudeSkillSearchPaths(
111
- projectRoot: string,
112
- options?: SkillPluginOptions | null,
113
- ): { raw: string[]; resolved: string[] } {
114
- const roots = getClaudeSkillSearchRoots(projectRoot, options);
115
- return {
116
- raw: roots.map((r) => r.display),
117
- resolved: roots.map((r) => r.resolved),
118
- };
119
- }
@@ -7,8 +7,8 @@
7
7
  * - 仅做字符串渲染,不做文件 IO。
8
8
  */
9
9
 
10
- import { getClaudeSkillSearchRoots } from "./Paths.js";
11
- import type { ClaudeSkill } from "@/skill/types/ClaudeSkill.js";
10
+ import { getSkillSearchRoots } from "./Paths.js";
11
+ import type { SkillDefinition } from "@/skill/types/SkillDefinition.js";
12
12
  import type { SkillPluginOptions } from "@/skill/types/SkillPlugin.js";
13
13
 
14
14
  /**
@@ -18,12 +18,12 @@ import type { SkillPluginOptions } from "@/skill/types/SkillPlugin.js";
18
18
  * - 为控制 token 成本,最多展示前 40 个 skill。
19
19
  * - roots 会按扫描顺序输出,便于排查冲突覆盖。
20
20
  */
21
- export function renderClaudeSkillsPromptSection(
21
+ export function renderSkillsPromptSection(
22
22
  projectRoot: string,
23
23
  options: SkillPluginOptions | null | undefined,
24
- skills: ClaudeSkill[],
24
+ skills: SkillDefinition[],
25
25
  ): string {
26
- const roots = getClaudeSkillSearchRoots(projectRoot, options);
26
+ const roots = getSkillSearchRoots(projectRoot, options);
27
27
 
28
28
  const skillsSection =
29
29
  skills.length > 0
@@ -6,7 +6,7 @@
6
6
  * - core 不负责也不感知 skill/memory 业务状态
7
7
  */
8
8
 
9
- import type { ClaudeSkill } from "@/skill/types/ClaudeSkill.js";
9
+ import type { SkillDefinition } from "@/skill/types/SkillDefinition.js";
10
10
  import type {
11
11
  SessionSkillStateInternal,
12
12
  SessionSkillStateSnapshot,
@@ -50,9 +50,12 @@ function getOrCreateState(sessionId: string): SessionSkillStateInternal {
50
50
  * 算法(中文)
51
51
  * - 以 id 归一化后整体替换,避免残留脏状态。
52
52
  */
53
- export function setSessionAvailableSkills(sessionId: string, skills: ClaudeSkill[]): void {
53
+ export function setSessionAvailableSkills(
54
+ sessionId: string,
55
+ skills: SkillDefinition[],
56
+ ): void {
54
57
  const state = getOrCreateState(sessionId);
55
- const next = new Map<string, ClaudeSkill>();
58
+ const next = new Map<string, SkillDefinition>();
56
59
 
57
60
  for (const skill of Array.isArray(skills) ? skills : []) {
58
61
  const id = String(skill?.id || "").trim();
@@ -8,8 +8,8 @@
8
8
  */
9
9
 
10
10
  import { getSessionRunContext } from "@downcity/agent/internal/executor/SessionRunScope.js";
11
- import { discoverClaudeSkillsSync } from "./Discovery.js";
12
- import { renderClaudeSkillsPromptSection } from "./Prompt.js";
11
+ import { discoverSkillsSync } from "./Discovery.js";
12
+ import { renderSkillsPromptSection } from "./Prompt.js";
13
13
  import { setSessionAvailableSkills } from "./Store.js";
14
14
  import type { SkillPluginOptions } from "@/skill/types/SkillPlugin.js";
15
15
 
@@ -35,7 +35,7 @@ export async function buildSkillsSystemText(
35
35
  runtime: SkillSystemRuntime,
36
36
  ): Promise<string> {
37
37
  const sessionId = getCurrentSessionId();
38
- const discoveredSkills = discoverClaudeSkillsSync(
38
+ const discoveredSkills = discoverSkillsSync(
39
39
  runtime.rootPath,
40
40
  runtime.options,
41
41
  );
@@ -44,7 +44,7 @@ export async function buildSkillsSystemText(
44
44
  setSessionAvailableSkills(sessionId, discoveredSkills);
45
45
  }
46
46
 
47
- return renderClaudeSkillsPromptSection(
47
+ return renderSkillsPromptSection(
48
48
  runtime.rootPath,
49
49
  runtime.options,
50
50
  discoveredSkills,
@@ -1,4 +1,4 @@
1
- import type { ClaudeSkill } from "@/skill/types/ClaudeSkill.js";
1
+ import type { SkillDefinition } from "@/skill/types/SkillDefinition.js";
2
2
 
3
3
  /**
4
4
  * Session skills state 对外快照。
@@ -9,7 +9,7 @@ import type { ClaudeSkill } from "@/skill/types/ClaudeSkill.js";
9
9
  */
10
10
  export type SessionSkillStateSnapshot = {
11
11
  sessionId: string;
12
- allSkills: ClaudeSkill[];
12
+ allSkills: SkillDefinition[];
13
13
  updatedAt: number;
14
14
  };
15
15
 
@@ -17,6 +17,6 @@ export type SessionSkillStateSnapshot = {
17
17
  * Session skills state 内部结构。
18
18
  */
19
19
  export type SessionSkillStateInternal = {
20
- allSkillsById: Map<string, ClaudeSkill>;
20
+ allSkillsById: Map<string, SkillDefinition>;
21
21
  updatedAt: number;
22
22
  };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Claude Code-compatible skill 模型。
2
+ * Skill 定义模型。
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - skill 最小单元目录为 `<root>/<skill-id>/SKILL.md`。
@@ -11,9 +11,9 @@ import type { SkillRootSource } from "@/skill/types/SkillRoot.js";
11
11
  import type { JsonValue } from "@downcity/agent/internal/types/common/Json.js";
12
12
 
13
13
  /**
14
- * Claude Code-compatible skill
14
+ * 可被 agent 发现与读取的 skill 定义。
15
15
  */
16
- export interface ClaudeSkill {
16
+ export interface SkillDefinition {
17
17
  /**
18
18
  * skill 稳定标识。
19
19
  *
@@ -7,7 +7,7 @@
7
7
  * - 该文件只描述插件协议,不承载发现、安装或 system 组装逻辑。
8
8
  */
9
9
 
10
- import type { ClaudeSkill } from "@/skill/types/ClaudeSkill.js";
10
+ import type { SkillDefinition } from "@/skill/types/SkillDefinition.js";
11
11
  import type { SkillRootSource } from "@/skill/types/SkillRoot.js";
12
12
 
13
13
  /**
@@ -80,7 +80,7 @@ export type SkillPluginLookupPayload = {
80
80
  export type SkillPluginIgnoreRule =
81
81
  | string
82
82
  | RegExp
83
- | ((skill: ClaudeSkill) => boolean);
83
+ | ((skill: SkillDefinition) => boolean);
84
84
 
85
85
  /**
86
86
  * SkillPlugin 构造参数。
package/src/web/Plugin.ts CHANGED
@@ -145,7 +145,7 @@ export class WebPlugin extends BasePlugin {
145
145
  .option("--target <target>", "web-access、agent-browser 或 all")
146
146
  .option("--scope <scope>", "安装位置:user 或 project")
147
147
  .option("-y, --yes", "跳过确认(默认 true)", true)
148
- .option("--agent <agent>", "skill installer 目标 agent", "claude-code");
148
+ .option("--agent <agent>", "skill installer 目标 agent");
149
149
  },
150
150
  mapInput({ opts }): JsonObject {
151
151
  return {
@@ -145,7 +145,7 @@ async function install_skill(params: {
145
145
  spec: string;
146
146
  scope: WebPluginInstallScope;
147
147
  yes: boolean;
148
- agent: string;
148
+ agent?: string;
149
149
  steps: WebPluginInstallStep[];
150
150
  }): Promise<void> {
151
151
  await skillInstallCommand(params.spec, {
@@ -207,7 +207,7 @@ export async function installWebPluginTargets(params: {
207
207
  const target = resolve_install_target(payload.target);
208
208
  const scope = resolve_install_scope(payload.scope);
209
209
  const yes = read_boolean(payload.yes) ?? true;
210
- const agent = read_string(payload.agent) || "claude-code";
210
+ const agent = read_string(payload.agent);
211
211
  const targets =
212
212
  target === "all" ? (["web-access", "agent-browser"] as const) : ([target] as const);
213
213
  const steps: WebPluginInstallStep[] = [];
@@ -233,7 +233,7 @@ export async function installWebPluginTargets(params: {
233
233
  return {
234
234
  target,
235
235
  scope,
236
- agent,
236
+ ...(agent ? { agent } : {}),
237
237
  steps: serialize_steps(steps),
238
238
  nextAction:
239
239
  "Use SkillPlugin lookup/list to inspect installed skills, then let the agent choose the concrete web path during task execution.",
@@ -54,7 +54,8 @@ export interface WebPluginInstallPayload {
54
54
  * skill installer 的目标 agent 名称。
55
55
  *
56
56
  * 说明(中文)
57
- * - 默认使用 `claude-code`,与现有 SkillPlugin 安装行为保持一致。
57
+ * - 留空时不向底层 skill installer 传递 `--agent`。
58
+ * - 只有需要显式指定 installer 目标时才传入。
58
59
  */
59
60
  agent?: string;
60
61
  /**
@@ -62,4 +63,3 @@ export interface WebPluginInstallPayload {
62
63
  */
63
64
  [key: string]: JsonValue | undefined;
64
65
  }
65
-
@@ -2,105 +2,33 @@
2
2
  * Workboard Plugin。
3
3
  *
4
4
  * 关键点(中文)
5
- * - workboard 是一个 runtime 观测面板插件,负责提供结构化工作快照。
6
- * - 当前同时通过 plugin action 与 HTTP 注入提供快照,供 Town RPC 与 Town HTTP gateway 复用。
5
+ * - workboard runtime 观测面板插件,负责提供结构化工作快照。
6
+ * - plugin action 与 HTTP route 共享同一份快照读取逻辑。
7
+ * - 是否启用由是否注册该 plugin 决定,不再读取项目配置做二次开关。
7
8
  */
8
9
 
9
10
  import { BasePlugin } from "@downcity/agent/internal/plugin/core/BasePlugin.js";
10
- import type { Plugin } from "@downcity/agent/internal/plugin/types/Plugin.js";
11
+ import type {
12
+ PluginActions,
13
+ PluginHttpDefinition,
14
+ } from "@downcity/agent/internal/plugin/types/Plugin.js";
15
+ import type { AgentContext } from "@downcity/agent/internal/types/runtime/agent/AgentContext.js";
11
16
  import type { JsonValue } from "@downcity/agent/internal/types/common/Json.js";
12
- import { isPluginEnabled } from "@downcity/agent/internal/plugin/core/Activation.js";
13
17
  import { getWorkboardSnapshotStore } from "@/workboard/runtime/Store.js";
14
18
  import type { WorkboardSnapshotResponse } from "@/workboard/types/Workboard.js";
15
19
 
16
- function createWorkboardPluginDefinition(plugin: Plugin): Plugin {
20
+ /**
21
+ * 读取 workboard 快照。
22
+ */
23
+ async function readWorkboardSnapshot(
24
+ context: AgentContext,
25
+ ): Promise<WorkboardSnapshotResponse> {
26
+ const snapshot = await getWorkboardSnapshotStore({
27
+ contextResolver: () => context,
28
+ }).readSnapshot();
17
29
  return {
18
- name: "workboard",
19
- title: "Workboard Snapshot",
20
- description:
21
- "Collects structured runtime activity snapshots so console surfaces can show what the current agent is doing now and what it recently worked on.",
22
- availability(context) {
23
- if (!isPluginEnabled({ plugin, context })) {
24
- return {
25
- enabled: false,
26
- available: false,
27
- reasons: ["workboard plugin disabled in project config"],
28
- };
29
- }
30
- return {
31
- enabled: true,
32
- available: true,
33
- reasons: [],
34
- };
35
- },
36
- actions: {
37
- snapshot: {
38
- execute: async ({ context }) => {
39
- const availability = await plugin.availability?.(context);
40
- if (availability && availability.available !== true) {
41
- return {
42
- success: false,
43
- error: availability.reasons.join("; ") || "workboard unavailable",
44
- };
45
- }
46
-
47
- const snapshot = await getWorkboardSnapshotStore({
48
- contextResolver: () => context,
49
- }).readSnapshot();
50
- return {
51
- success: true,
52
- data: {
53
- snapshot,
54
- } as unknown as JsonValue,
55
- };
56
- },
57
- },
58
- },
59
- http: {
60
- server: {
61
- authPolicies: [
62
- {
63
- path: "/api/workboard/*",
64
- method: "GET",
65
- requireAuth: true,
66
- anyPermissions: ["agent.read"],
67
- },
68
- ],
69
- register({ app, getContext }) {
70
- app.get("/api/workboard/snapshot", async (c) => {
71
- try {
72
- const availability = await plugin.availability?.(getContext());
73
- if (availability && availability.available !== true) {
74
- return c.json(
75
- {
76
- success: false,
77
- error: availability.reasons.join("; ") || "workboard unavailable",
78
- },
79
- 503,
80
- );
81
- }
82
-
83
- const snapshot = await getWorkboardSnapshotStore({
84
- contextResolver: getContext,
85
- }).readSnapshot();
86
- const payload: WorkboardSnapshotResponse = {
87
- success: true,
88
- snapshot,
89
- };
90
- return c.json(payload);
91
- } catch (error) {
92
- return c.json(
93
- {
94
- success: false,
95
- error: error instanceof Error ? error.message : String(error),
96
- },
97
- 500,
98
- );
99
- }
100
- });
101
- },
102
- },
103
- },
30
+ success: true,
31
+ snapshot,
104
32
  };
105
33
  }
106
34
 
@@ -108,10 +36,67 @@ function createWorkboardPluginDefinition(plugin: Plugin): Plugin {
108
36
  * WorkboardPlugin:运行态观测面板插件。
109
37
  */
110
38
  export class WorkboardPlugin extends BasePlugin {
39
+ /**
40
+ * 当前 plugin 稳定名称。
41
+ */
111
42
  readonly name = "workboard";
112
43
 
113
- constructor() {
114
- super();
115
- Object.assign(this, createWorkboardPluginDefinition(this));
116
- }
44
+ /**
45
+ * 插件标题。
46
+ */
47
+ readonly title = "Workboard Snapshot";
48
+
49
+ /**
50
+ * 插件说明。
51
+ */
52
+ readonly description =
53
+ "Collects structured runtime activity snapshots so console surfaces can show what the current agent is doing now and what it recently worked on.";
54
+
55
+ /**
56
+ * Workboard 对外 action。
57
+ */
58
+ readonly actions: PluginActions = {
59
+ snapshot: {
60
+ execute: async ({ context }) => {
61
+ const response = await readWorkboardSnapshot(context);
62
+ return {
63
+ success: true,
64
+ data: {
65
+ snapshot: response.snapshot,
66
+ } as unknown as JsonValue,
67
+ };
68
+ },
69
+ },
70
+ };
71
+
72
+ /**
73
+ * Workboard HTTP route。
74
+ */
75
+ readonly http: PluginHttpDefinition = {
76
+ server: {
77
+ authPolicies: [
78
+ {
79
+ path: "/api/workboard/*",
80
+ method: "GET",
81
+ requireAuth: true,
82
+ anyPermissions: ["agent.read"],
83
+ },
84
+ ],
85
+ register({ app, getContext }) {
86
+ app.get("/api/workboard/snapshot", async (c) => {
87
+ try {
88
+ return c.json(await readWorkboardSnapshot(getContext()));
89
+ } catch (error) {
90
+ return c.json(
91
+ {
92
+ success: false,
93
+ error: error instanceof Error ? error.message : String(error),
94
+ },
95
+ 500,
96
+ );
97
+ }
98
+ });
99
+ },
100
+ },
101
+ };
117
102
  }