@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.
- package/bin/BuiltinPlugins.d.ts +24 -2
- package/bin/BuiltinPlugins.d.ts.map +1 -1
- package/bin/BuiltinPlugins.js +18 -5
- package/bin/BuiltinPlugins.js.map +1 -1
- package/bin/auth/types/AuthPlugin.d.ts +12 -16
- package/bin/auth/types/AuthPlugin.d.ts.map +1 -1
- package/bin/auth/types/AuthPlugin.js +9 -13
- package/bin/auth/types/AuthPlugin.js.map +1 -1
- package/bin/chat/ChatPlugin.d.ts +37 -6
- package/bin/chat/ChatPlugin.d.ts.map +1 -1
- package/bin/chat/ChatPlugin.js +58 -80
- package/bin/chat/ChatPlugin.js.map +1 -1
- package/bin/chat/Index.d.ts +4 -1
- package/bin/chat/Index.d.ts.map +1 -1
- package/bin/chat/Index.js +2 -1
- package/bin/chat/Index.js.map +1 -1
- package/bin/chat/channels/Configuration.d.ts +1 -1
- package/bin/chat/channels/Configuration.js +1 -1
- package/bin/chat/channels/RuntimeChannel.d.ts +145 -0
- package/bin/chat/channels/RuntimeChannel.d.ts.map +1 -0
- package/bin/chat/channels/RuntimeChannel.js +148 -0
- package/bin/chat/channels/RuntimeChannel.js.map +1 -0
- package/bin/chat/runtime/ChatAuthorizationRuntime.d.ts +22 -0
- package/bin/chat/runtime/ChatAuthorizationRuntime.d.ts.map +1 -0
- package/bin/chat/runtime/ChatAuthorizationRuntime.js +189 -0
- package/bin/chat/runtime/ChatAuthorizationRuntime.js.map +1 -0
- package/bin/chat/runtime/ChatChannelActions.d.ts.map +1 -1
- package/bin/chat/runtime/ChatChannelActions.js +19 -9
- package/bin/chat/runtime/ChatChannelActions.js.map +1 -1
- package/bin/chat/runtime/ChatChannelConfig.d.ts +2 -18
- package/bin/chat/runtime/ChatChannelConfig.d.ts.map +1 -1
- package/bin/chat/runtime/ChatChannelConfig.js +2 -73
- package/bin/chat/runtime/ChatChannelConfig.js.map +1 -1
- package/bin/chat/runtime/ChatChannelCore.d.ts +22 -1
- package/bin/chat/runtime/ChatChannelCore.d.ts.map +1 -1
- package/bin/chat/runtime/ChatChannelCore.js +5 -5
- package/bin/chat/runtime/ChatChannelCore.js.map +1 -1
- package/bin/chat/runtime/ChatPluginActionRegistry.js +1 -1
- package/bin/chat/runtime/ChatPluginActionRegistry.js.map +1 -1
- package/bin/chat/runtime/PluginPoints.d.ts +3 -3
- package/bin/chat/runtime/PluginPoints.js +3 -3
- package/bin/chat/types/ChannelStatus.d.ts +1 -1
- package/bin/chat/types/ChatPluginOptions.d.ts +76 -0
- package/bin/chat/types/ChatPluginOptions.d.ts.map +1 -0
- package/bin/chat/types/ChatPluginOptions.js +10 -0
- package/bin/chat/types/ChatPluginOptions.js.map +1 -0
- package/bin/contact/ContactPlugin.d.ts +6 -1
- package/bin/contact/ContactPlugin.d.ts.map +1 -1
- package/bin/contact/ContactPlugin.js +9 -8
- package/bin/contact/ContactPlugin.js.map +1 -1
- package/bin/contact/types/ContactPluginOptions.d.ts +29 -0
- package/bin/contact/types/ContactPluginOptions.d.ts.map +1 -0
- package/bin/contact/types/ContactPluginOptions.js +9 -0
- package/bin/contact/types/ContactPluginOptions.js.map +1 -0
- package/bin/index.d.ts +7 -4
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js +3 -2
- package/bin/index.js.map +1 -1
- package/bin/skill/Action.d.ts.map +1 -1
- package/bin/skill/Action.js +2 -2
- package/bin/skill/Action.js.map +1 -1
- package/bin/skill/Command.js +5 -5
- package/bin/skill/Command.js.map +1 -1
- package/bin/skill/Plugin.js +1 -1
- package/bin/skill/Plugin.js.map +1 -1
- package/bin/skill/runtime/Discovery.d.ts +4 -4
- package/bin/skill/runtime/Discovery.d.ts.map +1 -1
- package/bin/skill/runtime/Discovery.js +5 -5
- package/bin/skill/runtime/Discovery.js.map +1 -1
- package/bin/skill/runtime/Paths.d.ts +1 -5
- package/bin/skill/runtime/Paths.d.ts.map +1 -1
- package/bin/skill/runtime/Paths.js +1 -9
- package/bin/skill/runtime/Paths.js.map +1 -1
- package/bin/skill/runtime/Prompt.d.ts +2 -2
- package/bin/skill/runtime/Prompt.d.ts.map +1 -1
- package/bin/skill/runtime/Prompt.js +3 -3
- package/bin/skill/runtime/Prompt.js.map +1 -1
- package/bin/skill/runtime/Store.d.ts +2 -2
- package/bin/skill/runtime/Store.d.ts.map +1 -1
- package/bin/skill/runtime/Store.js.map +1 -1
- package/bin/skill/runtime/SystemProvider.js +4 -4
- package/bin/skill/runtime/SystemProvider.js.map +1 -1
- package/bin/skill/runtime/Types.d.ts +3 -3
- package/bin/skill/runtime/Types.d.ts.map +1 -1
- package/bin/skill/types/{ClaudeSkill.d.ts → SkillDefinition.d.ts} +4 -4
- package/bin/skill/types/SkillDefinition.d.ts.map +1 -0
- package/bin/skill/types/{ClaudeSkill.js → SkillDefinition.js} +2 -2
- package/bin/skill/types/SkillDefinition.js.map +1 -0
- package/bin/skill/types/SkillPlugin.d.ts +2 -2
- package/bin/skill/types/SkillPlugin.d.ts.map +1 -1
- package/bin/web/Plugin.js +1 -1
- package/bin/web/Plugin.js.map +1 -1
- package/bin/web/runtime/Install.js +2 -2
- package/bin/web/runtime/Install.js.map +1 -1
- package/bin/web/types/WebPlugin.d.ts +2 -1
- package/bin/web/types/WebPlugin.d.ts.map +1 -1
- package/bin/workboard/Plugin.d.ts +23 -3
- package/bin/workboard/Plugin.d.ts.map +1 -1
- package/bin/workboard/Plugin.js +66 -85
- package/bin/workboard/Plugin.js.map +1 -1
- package/package.json +2 -2
- package/src/BuiltinPlugins.ts +41 -5
- package/src/auth/types/AuthPlugin.ts +12 -17
- package/src/chat/ChatPlugin.ts +92 -89
- package/src/chat/Index.ts +18 -1
- package/src/chat/channels/Configuration.ts +1 -1
- package/src/chat/channels/RuntimeChannel.ts +264 -0
- package/src/chat/runtime/ChatAuthorizationRuntime.ts +229 -0
- package/src/chat/runtime/ChatChannelActions.ts +24 -9
- package/src/chat/runtime/ChatChannelConfig.ts +2 -100
- package/src/chat/runtime/ChatChannelCore.ts +20 -8
- package/src/chat/runtime/ChatPluginActionRegistry.ts +1 -1
- package/src/chat/runtime/PluginPoints.ts +3 -3
- package/src/chat/types/ChannelStatus.ts +1 -1
- package/src/chat/types/ChatPluginOptions.ts +79 -0
- package/src/contact/ContactPlugin.ts +17 -9
- package/src/contact/types/ContactPluginOptions.ts +30 -0
- package/src/index.ts +23 -7
- package/src/skill/Action.ts +10 -7
- package/src/skill/Command.ts +5 -5
- package/src/skill/Plugin.ts +1 -1
- package/src/skill/runtime/Discovery.ts +14 -11
- package/src/skill/runtime/Paths.ts +1 -13
- package/src/skill/runtime/Prompt.ts +5 -5
- package/src/skill/runtime/Store.ts +6 -3
- package/src/skill/runtime/SystemProvider.ts +4 -4
- package/src/skill/runtime/Types.ts +3 -3
- package/src/skill/types/{ClaudeSkill.ts → SkillDefinition.ts} +3 -3
- package/src/skill/types/SkillPlugin.ts +2 -2
- package/src/web/Plugin.ts +1 -1
- package/src/web/runtime/Install.ts +3 -3
- package/src/web/types/WebPlugin.ts +2 -2
- package/src/workboard/Plugin.ts +80 -95
- package/bin/auth/Plugin.d.ts +0 -17
- package/bin/auth/Plugin.d.ts.map +0 -1
- package/bin/auth/Plugin.js +0 -199
- package/bin/auth/Plugin.js.map +0 -1
- package/bin/chat/ChatPluginTypes.d.ts +0 -122
- package/bin/chat/ChatPluginTypes.d.ts.map +0 -1
- package/bin/chat/ChatPluginTypes.js +0 -10
- package/bin/chat/ChatPluginTypes.js.map +0 -1
- package/bin/skill/types/ClaudeSkill.d.ts.map +0 -1
- package/bin/skill/types/ClaudeSkill.js.map +0 -1
- package/src/auth/Plugin.ts +0 -237
- 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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
44
|
-
|
|
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,
|
package/src/skill/Action.ts
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
import fs from "fs-extra";
|
|
10
10
|
import path from "node:path";
|
|
11
|
-
import {
|
|
12
|
-
import type {
|
|
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:
|
|
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(
|
|
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:
|
|
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
|
-
):
|
|
73
|
+
): SkillDefinition[] {
|
|
71
74
|
const root = path.resolve(projectRoot);
|
|
72
|
-
return
|
|
75
|
+
return discoverSkillsSync(root, options);
|
|
73
76
|
}
|
|
74
77
|
|
|
75
78
|
/**
|
package/src/skill/Command.ts
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import { execa } from "execa";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
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 || "
|
|
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 =
|
|
78
|
-
const skills =
|
|
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}`);
|
package/src/skill/Plugin.ts
CHANGED
|
@@ -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"
|
|
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 {
|
|
16
|
-
import type {
|
|
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(
|
|
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:
|
|
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
|
-
*
|
|
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 去重并构造
|
|
67
|
+
* 3) 按 id 去重并构造 SkillDefinition
|
|
65
68
|
* 4) 最终按 name 排序,保证输出稳定
|
|
66
69
|
*/
|
|
67
|
-
export function
|
|
70
|
+
export function discoverSkillsSync(
|
|
68
71
|
projectRoot: string,
|
|
69
72
|
options?: SkillPluginOptions | null,
|
|
70
|
-
):
|
|
73
|
+
): SkillDefinition[] {
|
|
71
74
|
const root = String(projectRoot || "").trim();
|
|
72
75
|
if (!root) return [];
|
|
73
76
|
const resolvedOptions = resolveSkillPluginOptions(options);
|
|
74
|
-
const roots =
|
|
77
|
+
const roots = getSkillSearchRoots(root, resolvedOptions);
|
|
75
78
|
|
|
76
|
-
const outById = new Map<string,
|
|
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:
|
|
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
|
|
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 {
|
|
11
|
-
import type {
|
|
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
|
|
21
|
+
export function renderSkillsPromptSection(
|
|
22
22
|
projectRoot: string,
|
|
23
23
|
options: SkillPluginOptions | null | undefined,
|
|
24
|
-
skills:
|
|
24
|
+
skills: SkillDefinition[],
|
|
25
25
|
): string {
|
|
26
|
-
const roots =
|
|
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 {
|
|
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(
|
|
53
|
+
export function setSessionAvailableSkills(
|
|
54
|
+
sessionId: string,
|
|
55
|
+
skills: SkillDefinition[],
|
|
56
|
+
): void {
|
|
54
57
|
const state = getOrCreateState(sessionId);
|
|
55
|
-
const next = new Map<string,
|
|
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 {
|
|
12
|
-
import {
|
|
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 =
|
|
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
|
|
47
|
+
return renderSkillsPromptSection(
|
|
48
48
|
runtime.rootPath,
|
|
49
49
|
runtime.options,
|
|
50
50
|
discoveredSkills,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
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:
|
|
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,
|
|
20
|
+
allSkillsById: Map<string, SkillDefinition>;
|
|
21
21
|
updatedAt: number;
|
|
22
22
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
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
|
-
*
|
|
14
|
+
* 可被 agent 发现与读取的 skill 定义。
|
|
15
15
|
*/
|
|
16
|
-
export interface
|
|
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 {
|
|
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:
|
|
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"
|
|
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
|
|
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)
|
|
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
|
-
* -
|
|
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
|
-
|
package/src/workboard/Plugin.ts
CHANGED
|
@@ -2,105 +2,33 @@
|
|
|
2
2
|
* Workboard Plugin。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* - workboard
|
|
6
|
-
* -
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
19
|
-
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
}
|