
























@@ -13,10 +13,6 @@ export default definePluginEntry({
1313description:
1414"Captures repeatable workflows as workspace skills, with pending review and safe writes.",
1515register(api) {
16-const startupConfig = resolveConfig(api.pluginConfig);
17-if (!startupConfig.enabled) {
18-return;
19-}
2016const resolveCurrentConfig = () => {
2117const runtimePluginConfig = resolveLivePluginConfigObject(
2218api.runtime.config?.loadConfig,
@@ -49,97 +45,94 @@ export default definePluginEntry({
4945};
5046});
514752-if (startupConfig.autoCapture && startupConfig.reviewMode !== "off") {
53-api.on("agent_end", async (event, ctx) => {
54-const config = resolveCurrentConfig();
55-if (!config.enabled || !config.autoCapture || config.reviewMode === "off") {
56-return;
57-}
58-if (!event.success) {
59-return;
60-}
61-if (ctx.sessionId?.startsWith("skill-workshop-review-")) {
62-return;
63-}
64-const agentId = ctx.agentId ?? resolveDefaultAgentId(api.config);
65-const workspaceDir =
66-ctx.workspaceDir || api.runtime.agent.resolveAgentWorkspaceDir(api.config, agentId);
67-const store = createStoreForContext({ api, ctx: { ...ctx, workspaceDir }, config });
68-const heuristicProposal = createProposalFromMessages({
69-messages: event.messages,
70- workspaceDir,
71- agentId,
72-sessionId: ctx.sessionId,
73-});
74-const heuristicEnabled =
75-config.reviewMode === "heuristic" || config.reviewMode === "hybrid";
76-if (heuristicEnabled && heuristicProposal) {
77-try {
78-const result = await applyOrStoreProposal({
79-proposal: heuristicProposal,
80- store,
81- config,
82- workspaceDir,
83-});
84-if (result.status === "applied") {
85-api.logger.info(`skill-workshop: applied ${heuristicProposal.skillName}`);
86-} else if (result.status === "quarantined") {
87-api.logger.warn(`skill-workshop: quarantined ${heuristicProposal.skillName}`);
88-} else {
89-api.logger.info(`skill-workshop: queued ${heuristicProposal.skillName}`);
90-}
91-} catch (error) {
92-api.logger.warn(`skill-workshop: heuristic capture skipped: ${String(error)}`);
93-}
94-}
95-96-const llmEnabled = config.reviewMode === "llm" || config.reviewMode === "hybrid";
97-if (!llmEnabled) {
98-return;
99-}
100-const reviewState = await store.recordReviewTurn(countToolCalls(event.messages));
101-const thresholdMet =
102-reviewState.turnsSinceReview >= config.reviewInterval ||
103-reviewState.toolCallsSinceReview >= config.reviewMinToolCalls;
104-const shouldReview =
105-thresholdMet || (config.reviewMode === "llm" && heuristicProposal !== undefined);
106-if (!shouldReview) {
107-return;
108-}
109-await store.markReviewed();
48+api.on("agent_end", async (event, ctx) => {
49+const config = resolveCurrentConfig();
50+if (!config.enabled || !config.autoCapture || config.reviewMode === "off") {
51+return;
52+}
53+if (!event.success) {
54+return;
55+}
56+if (ctx.sessionId?.startsWith("skill-workshop-review-")) {
57+return;
58+}
59+const agentId = ctx.agentId ?? resolveDefaultAgentId(api.config);
60+const workspaceDir =
61+ctx.workspaceDir || api.runtime.agent.resolveAgentWorkspaceDir(api.config, agentId);
62+const store = createStoreForContext({ api, ctx: { ...ctx, workspaceDir }, config });
63+const heuristicProposal = createProposalFromMessages({
64+messages: event.messages,
65+ workspaceDir,
66+ agentId,
67+sessionId: ctx.sessionId,
68+});
69+const heuristicEnabled = config.reviewMode === "heuristic" || config.reviewMode === "hybrid";
70+if (heuristicEnabled && heuristicProposal) {
11071try {
111-const proposal = await reviewTranscriptForProposal({
112- api,
72+const result = await applyOrStoreProposal({
73+proposal: heuristicProposal,
74+ store,
11375 config,
114-messages: event.messages,
115-ctx: {
116- agentId,
117-sessionId: ctx.sessionId,
118-sessionKey: ctx.sessionKey,
119- workspaceDir,
120-modelProviderId: ctx.modelProviderId,
121-modelId: ctx.modelId,
122-messageProvider: ctx.messageProvider,
123-channelId: ctx.channelId,
124-},
76+ workspaceDir,
12577});
126-if (!proposal) {
127-api.logger.debug?.("skill-workshop: reviewer found no update");
128-return;
129-}
130-const result = await applyOrStoreProposal({ proposal, store, config, workspaceDir });
13178if (result.status === "applied") {
132-api.logger.info(`skill-workshop: applied ${proposal.skillName}`);
79+api.logger.info(`skill-workshop: applied ${heuristicProposal.skillName}`);
13380} else if (result.status === "quarantined") {
134-api.logger.warn(`skill-workshop: quarantined ${proposal.skillName}`);
81+api.logger.warn(`skill-workshop: quarantined ${heuristicProposal.skillName}`);
13582} else {
136-api.logger.info(`skill-workshop: queued ${proposal.skillName}`);
83+api.logger.info(`skill-workshop: queued ${heuristicProposal.skillName}`);
13784}
13885} catch (error) {
139-api.logger.warn(`skill-workshop: reviewer skipped: ${String(error)}`);
86+api.logger.warn(`skill-workshop: heuristic capture skipped: ${String(error)}`);
14087}
141-});
142-}
88+}
89+90+const llmEnabled = config.reviewMode === "llm" || config.reviewMode === "hybrid";
91+if (!llmEnabled) {
92+return;
93+}
94+const reviewState = await store.recordReviewTurn(countToolCalls(event.messages));
95+const thresholdMet =
96+reviewState.turnsSinceReview >= config.reviewInterval ||
97+reviewState.toolCallsSinceReview >= config.reviewMinToolCalls;
98+const shouldReview =
99+thresholdMet || (config.reviewMode === "llm" && heuristicProposal !== undefined);
100+if (!shouldReview) {
101+return;
102+}
103+await store.markReviewed();
104+try {
105+const proposal = await reviewTranscriptForProposal({
106+ api,
107+ config,
108+messages: event.messages,
109+ctx: {
110+ agentId,
111+sessionId: ctx.sessionId,
112+sessionKey: ctx.sessionKey,
113+ workspaceDir,
114+modelProviderId: ctx.modelProviderId,
115+modelId: ctx.modelId,
116+messageProvider: ctx.messageProvider,
117+channelId: ctx.channelId,
118+},
119+});
120+if (!proposal) {
121+api.logger.debug?.("skill-workshop: reviewer found no update");
122+return;
123+}
124+const result = await applyOrStoreProposal({ proposal, store, config, workspaceDir });
125+if (result.status === "applied") {
126+api.logger.info(`skill-workshop: applied ${proposal.skillName}`);
127+} else if (result.status === "quarantined") {
128+api.logger.warn(`skill-workshop: quarantined ${proposal.skillName}`);
129+} else {
130+api.logger.info(`skill-workshop: queued ${proposal.skillName}`);
131+}
132+} catch (error) {
133+api.logger.warn(`skill-workshop: reviewer skipped: ${String(error)}`);
134+}
135+});
143136},
144137});
145138此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。