snow-flow 10.0.76 → 10.0.78
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 +1 -1
- package/src/agent/agent.ts +39 -0
- package/src/agent/prompt/review.txt +99 -0
- package/src/session/prompt/anthropic.txt +14 -0
- package/src/session/prompt/review-switch.txt +6 -0
- package/src/session/prompt.ts +28 -27
- package/src/tool/plan-enter.txt +25 -10
- package/src/tool/registry.ts +2 -1
- package/src/tool/review-enter.txt +13 -0
- package/src/tool/review-exit.txt +13 -0
- package/src/tool/review.ts +147 -0
package/package.json
CHANGED
package/src/agent/agent.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { ProviderTransform } from "../provider/transform"
|
|
|
11
11
|
import PROMPT_GENERATE from "./generate.txt"
|
|
12
12
|
import PROMPT_COMPACTION from "./prompt/compaction.txt"
|
|
13
13
|
import PROMPT_EXPLORE from "./prompt/explore.txt"
|
|
14
|
+
import PROMPT_REVIEW from "./prompt/review.txt"
|
|
14
15
|
import PROMPT_SUMMARY from "./prompt/summary.txt"
|
|
15
16
|
import PROMPT_TITLE from "./prompt/title.txt"
|
|
16
17
|
import { PermissionNext } from "@/permission/next"
|
|
@@ -60,6 +61,8 @@ export namespace Agent {
|
|
|
60
61
|
question: "deny",
|
|
61
62
|
plan_enter: "deny",
|
|
62
63
|
plan_exit: "deny",
|
|
64
|
+
review_enter: "deny",
|
|
65
|
+
review_exit: "deny",
|
|
63
66
|
// mirrors github.com/github/gitignore Node.gitignore pattern for .env files
|
|
64
67
|
read: {
|
|
65
68
|
"*": "allow",
|
|
@@ -80,6 +83,7 @@ export namespace Agent {
|
|
|
80
83
|
PermissionNext.fromConfig({
|
|
81
84
|
question: "allow",
|
|
82
85
|
plan_enter: "allow",
|
|
86
|
+
review_enter: "allow",
|
|
83
87
|
}),
|
|
84
88
|
user,
|
|
85
89
|
),
|
|
@@ -109,6 +113,33 @@ export namespace Agent {
|
|
|
109
113
|
mode: "primary",
|
|
110
114
|
native: true,
|
|
111
115
|
},
|
|
116
|
+
review: {
|
|
117
|
+
name: "review",
|
|
118
|
+
description: "Code reuse review mode. Analyzes ServiceNow artifacts for reuse opportunities. Enterprise only.",
|
|
119
|
+
options: {},
|
|
120
|
+
temperature: 0.3,
|
|
121
|
+
color: "#a855f7",
|
|
122
|
+
permission: PermissionNext.merge(
|
|
123
|
+
defaults,
|
|
124
|
+
PermissionNext.fromConfig({
|
|
125
|
+
"*": "deny",
|
|
126
|
+
grep: "allow",
|
|
127
|
+
glob: "allow",
|
|
128
|
+
list: "allow",
|
|
129
|
+
read: "allow",
|
|
130
|
+
bash: { "*": "deny", "git log*": "allow", "git diff*": "allow", "git status*": "allow" },
|
|
131
|
+
webfetch: "allow",
|
|
132
|
+
websearch: "allow",
|
|
133
|
+
codesearch: "allow",
|
|
134
|
+
review_exit: "allow",
|
|
135
|
+
}),
|
|
136
|
+
user,
|
|
137
|
+
),
|
|
138
|
+
prompt: PROMPT_REVIEW,
|
|
139
|
+
mode: "primary",
|
|
140
|
+
native: true,
|
|
141
|
+
hidden: true,
|
|
142
|
+
},
|
|
112
143
|
general: {
|
|
113
144
|
name: "general",
|
|
114
145
|
description: `General-purpose agent for researching complex questions and executing multi-step tasks. Use this agent to execute multiple units of work in parallel.`,
|
|
@@ -227,6 +258,14 @@ export namespace Agent {
|
|
|
227
258
|
item.permission = PermissionNext.merge(item.permission, PermissionNext.fromConfig(value.permission ?? {}))
|
|
228
259
|
}
|
|
229
260
|
|
|
261
|
+
// Unhide review agent for enterprise users
|
|
262
|
+
const enterpriseAuth = await Auth.all().then((all) =>
|
|
263
|
+
Object.values(all).find((e) => e.type === "enterprise" && (e.licenseKey || e.token)),
|
|
264
|
+
)
|
|
265
|
+
if (enterpriseAuth && result.review) {
|
|
266
|
+
result.review.hidden = false
|
|
267
|
+
}
|
|
268
|
+
|
|
230
269
|
// Ensure Truncate.DIR is allowed unless explicitly configured
|
|
231
270
|
for (const name in result) {
|
|
232
271
|
const agent = result[name]
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
You are the Code Reuse Reviewer Agent for Snow-Flow. Your role is to analyze ServiceNow artifacts created or modified during development activities and identify opportunities for code reuse and standardization.
|
|
2
|
+
|
|
3
|
+
IMPORTANT: You are in READ-ONLY analysis mode. You cannot and should not modify any code. Your role is purely analysis and feedback.
|
|
4
|
+
|
|
5
|
+
## Review Process
|
|
6
|
+
|
|
7
|
+
### Step 1: Gather Activity Context
|
|
8
|
+
- Read the activity details to understand what was created/modified
|
|
9
|
+
- Identify the artifacts by their sys_id and type
|
|
10
|
+
- Note the Update Set associated with this activity
|
|
11
|
+
|
|
12
|
+
### Step 2: Analyze Created/Modified Code
|
|
13
|
+
For each artifact in the activity:
|
|
14
|
+
1. Use `snow_analyze_artifact` to understand its structure and dependencies
|
|
15
|
+
2. Extract key functions and patterns from the code
|
|
16
|
+
3. Identify GlideRecord queries and business logic
|
|
17
|
+
|
|
18
|
+
### Step 3: Search for Reuse Opportunities
|
|
19
|
+
1. Use `snow_find_artifact` to find existing Script Includes with similar functionality
|
|
20
|
+
2. Use `snow_comprehensive_search` to search for patterns matching the implemented functionality
|
|
21
|
+
3. Check for common naming conventions: *Utils, *Helper, *Service, *API
|
|
22
|
+
|
|
23
|
+
### Step 4: Code Pattern Analysis
|
|
24
|
+
Look for these common reuse opportunities:
|
|
25
|
+
- GlideRecord utilities: Common query patterns, field value getters
|
|
26
|
+
- Validation functions: Input validation, business rule conditions
|
|
27
|
+
- Transformation logic: Data mapping, format conversion
|
|
28
|
+
- Integration helpers: REST calls, web service wrappers
|
|
29
|
+
- Date/time utilities: Duration calculations, timezone handling
|
|
30
|
+
- User/group utilities: Role checks, assignment logic
|
|
31
|
+
|
|
32
|
+
### Step 5: Generate Review Report
|
|
33
|
+
Structure your findings as JSON:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"activityId": "string",
|
|
38
|
+
"reviewStatus": "approved" | "needs_revision",
|
|
39
|
+
"summary": "Brief summary of findings",
|
|
40
|
+
"artifactsReviewed": [
|
|
41
|
+
{
|
|
42
|
+
"sys_id": "string",
|
|
43
|
+
"type": "widget|business_rule|client_script|etc",
|
|
44
|
+
"name": "artifact name"
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"reuseOpportunities": [
|
|
48
|
+
{
|
|
49
|
+
"type": "existing_script_include" | "duplicate_pattern" | "refactor_suggestion",
|
|
50
|
+
"severity": "high" | "medium" | "low",
|
|
51
|
+
"description": "What was found",
|
|
52
|
+
"existingArtifact": {
|
|
53
|
+
"sys_id": "optional - sys_id of existing Script Include",
|
|
54
|
+
"name": "optional - name of existing artifact"
|
|
55
|
+
},
|
|
56
|
+
"recommendation": "Specific action to take",
|
|
57
|
+
"codeLocation": "Where in the new code this applies"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"approved": true | false,
|
|
61
|
+
"feedback": "If not approved, explanation for the developer"
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Decision Criteria
|
|
66
|
+
|
|
67
|
+
### Approve when:
|
|
68
|
+
- No existing Script Includes provide equivalent functionality
|
|
69
|
+
- Code patterns are unique to this use case
|
|
70
|
+
- Minor optimizations possible but not blocking
|
|
71
|
+
- Low-severity suggestions only (informational)
|
|
72
|
+
|
|
73
|
+
### Request Revision when:
|
|
74
|
+
- Existing Script Include provides >80% of needed functionality
|
|
75
|
+
- Duplicate code detected that should be consolidated
|
|
76
|
+
- High-severity code smell or anti-pattern detected
|
|
77
|
+
- Business logic should be extracted to Script Include for reuse
|
|
78
|
+
|
|
79
|
+
## MCP Tools Available
|
|
80
|
+
|
|
81
|
+
1. **snow_analyze_artifact** - Analyze artifact structure and dependencies
|
|
82
|
+
2. **snow_find_artifact** - Find existing artifacts by name/type
|
|
83
|
+
3. **snow_comprehensive_search** - Deep search across all tables
|
|
84
|
+
4. **snow_query_table** - Query any ServiceNow table
|
|
85
|
+
|
|
86
|
+
## Important Guidelines
|
|
87
|
+
|
|
88
|
+
1. READ-ONLY: You cannot modify any code. Your role is purely analysis and feedback.
|
|
89
|
+
2. ES5 Awareness: ServiceNow uses ES5. If you see ES6+ syntax, flag it as a concern.
|
|
90
|
+
3. Be Constructive: When requesting revision, provide specific, actionable feedback with examples.
|
|
91
|
+
4. Consider Context: Not all code needs to be in Script Includes. Consider frequency of reuse, complexity, and scope.
|
|
92
|
+
5. Document Reasoning: Always explain WHY you made your decision, not just WHAT you decided.
|
|
93
|
+
|
|
94
|
+
## Completing Your Review
|
|
95
|
+
|
|
96
|
+
After completing your review, call `review_exit` with your JSON review report.
|
|
97
|
+
|
|
98
|
+
- If APPROVED: Include any low-severity suggestions as informational notes in the report.
|
|
99
|
+
- If NEEDS REVISION: Provide detailed feedback explaining what needs to change. The build agent will address the feedback.
|
|
@@ -68,6 +68,20 @@ You are allowed to be proactive, but only when the user asks you to do something
|
|
|
68
68
|
- Not surprising the user with actions you take without asking
|
|
69
69
|
For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.
|
|
70
70
|
|
|
71
|
+
# Plan Mode
|
|
72
|
+
You have access to a plan_enter tool that switches to a read-only planning agent.
|
|
73
|
+
Use this tool PROACTIVELY when the user's request is complex enough to benefit from
|
|
74
|
+
planning before implementation. You do NOT need to wait for the user to ask for planning.
|
|
75
|
+
|
|
76
|
+
Consider using plan mode when:
|
|
77
|
+
- The task involves multiple files or architectural decisions
|
|
78
|
+
- You would need significant codebase exploration before implementing
|
|
79
|
+
- There are multiple valid approaches and the user should weigh in
|
|
80
|
+
- The task is large enough that mistakes would be costly to undo
|
|
81
|
+
|
|
82
|
+
Do NOT use plan mode for simple, straightforward tasks. When in doubt, prefer planning.
|
|
83
|
+
The plan_enter tool will ask the user for confirmation, so there is no risk in suggesting it.
|
|
84
|
+
|
|
71
85
|
# Professional objectivity
|
|
72
86
|
Prioritize technical accuracy and truthfulness over validating the user's beliefs. Focus on facts and problem-solving, providing direct, objective technical info without any unnecessary superlatives, praise, or emotional validation. It is best for the user if Claude honestly applies the same rigorous standards to all ideas and disagrees when necessary, even if it may not be what the user wants to hear. Objective guidance and respectful correction are more valuable than false agreement. Whenever there is uncertainty, it's best to investigate to find the truth first rather than instinctively confirming the user's beliefs.
|
|
73
87
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<system-reminder>
|
|
2
|
+
Your operational mode has changed from review to build.
|
|
3
|
+
You are no longer in read-only analysis mode.
|
|
4
|
+
The code review results have been provided. Act on the review feedback.
|
|
5
|
+
If approved, proceed with activity_complete. If revision needed, address the feedback.
|
|
6
|
+
</system-reminder>
|
package/src/session/prompt.ts
CHANGED
|
@@ -19,6 +19,7 @@ import { InstructionPrompt } from "./instruction"
|
|
|
19
19
|
import { Plugin } from "../plugin"
|
|
20
20
|
import PROMPT_PLAN from "../session/prompt/plan.txt"
|
|
21
21
|
import BUILD_SWITCH from "../session/prompt/build-switch.txt"
|
|
22
|
+
import REVIEW_SWITCH from "../session/prompt/review-switch.txt"
|
|
22
23
|
import MAX_STEPS from "../session/prompt/max-steps.txt"
|
|
23
24
|
import { defer } from "../util/defer"
|
|
24
25
|
import { ToolRegistry } from "../tool/registry"
|
|
@@ -1223,33 +1224,6 @@ export namespace SessionPrompt {
|
|
|
1223
1224
|
const clonedUser: MessageV2.WithParts = { info: userMessage.info, parts: [...userMessage.parts] }
|
|
1224
1225
|
const replaceUser = () => input.messages.map((m) => (m === userMessage ? clonedUser : m))
|
|
1225
1226
|
|
|
1226
|
-
// Original logic when experimental plan mode is disabled
|
|
1227
|
-
if (!Flag.OPENCODE_EXPERIMENTAL_PLAN_MODE) {
|
|
1228
|
-
if (input.agent.name === "plan") {
|
|
1229
|
-
clonedUser.parts.push({
|
|
1230
|
-
id: Identifier.ascending("part"),
|
|
1231
|
-
messageID: userMessage.info.id,
|
|
1232
|
-
sessionID: userMessage.info.sessionID,
|
|
1233
|
-
type: "text",
|
|
1234
|
-
text: PROMPT_PLAN,
|
|
1235
|
-
synthetic: true,
|
|
1236
|
-
})
|
|
1237
|
-
}
|
|
1238
|
-
const wasPlan = input.messages.some((msg) => msg.info.role === "assistant" && msg.info.agent === "plan")
|
|
1239
|
-
if (wasPlan && input.agent.name === "build") {
|
|
1240
|
-
clonedUser.parts.push({
|
|
1241
|
-
id: Identifier.ascending("part"),
|
|
1242
|
-
messageID: userMessage.info.id,
|
|
1243
|
-
sessionID: userMessage.info.sessionID,
|
|
1244
|
-
type: "text",
|
|
1245
|
-
text: BUILD_SWITCH,
|
|
1246
|
-
synthetic: true,
|
|
1247
|
-
})
|
|
1248
|
-
}
|
|
1249
|
-
return replaceUser()
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1252
|
-
// New plan mode logic when flag is enabled
|
|
1253
1227
|
const assistantMessage = input.messages.findLast((msg) => msg.info.role === "assistant")
|
|
1254
1228
|
|
|
1255
1229
|
// Switching from plan mode to build mode
|
|
@@ -1356,6 +1330,33 @@ NOTE: At any point in time through this workflow you should feel free to ask the
|
|
|
1356
1330
|
clonedUser.parts.push(part)
|
|
1357
1331
|
return replaceUser()
|
|
1358
1332
|
}
|
|
1333
|
+
|
|
1334
|
+
// Switching from review to build
|
|
1335
|
+
if (input.agent.name === "build" && assistantMessage?.info.agent === "review") {
|
|
1336
|
+
clonedUser.parts.push({
|
|
1337
|
+
id: Identifier.ascending("part"),
|
|
1338
|
+
messageID: userMessage.info.id,
|
|
1339
|
+
sessionID: userMessage.info.sessionID,
|
|
1340
|
+
type: "text",
|
|
1341
|
+
text: REVIEW_SWITCH,
|
|
1342
|
+
synthetic: true,
|
|
1343
|
+
})
|
|
1344
|
+
return replaceUser()
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
// Entering review mode
|
|
1348
|
+
if (input.agent.name === "review" && assistantMessage?.info.agent !== "review") {
|
|
1349
|
+
clonedUser.parts.push({
|
|
1350
|
+
id: Identifier.ascending("part"),
|
|
1351
|
+
messageID: userMessage.info.id,
|
|
1352
|
+
sessionID: userMessage.info.sessionID,
|
|
1353
|
+
type: "text",
|
|
1354
|
+
text: `<system-reminder>\nReview mode is active. You are in READ-ONLY analysis mode.\nYour role is to analyze ServiceNow artifacts for code reuse opportunities.\nUse snow_analyze_artifact, snow_find_artifact, snow_comprehensive_search, and snow_query_table.\nCall review_exit when your review is complete with a JSON review report.\n</system-reminder>`,
|
|
1355
|
+
synthetic: true,
|
|
1356
|
+
})
|
|
1357
|
+
return replaceUser()
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1359
1360
|
return replaceUser()
|
|
1360
1361
|
}
|
|
1361
1362
|
|
package/src/tool/plan-enter.txt
CHANGED
|
@@ -1,14 +1,29 @@
|
|
|
1
|
-
Use this tool
|
|
1
|
+
Use this tool proactively when you're about to start a non-trivial implementation task.
|
|
2
|
+
Getting user sign-off on your approach before writing code prevents wasted effort.
|
|
3
|
+
This tool asks the user if they want to switch to plan mode.
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
## When to Use This Tool
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
**Prefer using plan mode** for implementation tasks unless they're simple.
|
|
8
|
+
Use it when ANY of these conditions apply:
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
|
|
10
|
+
1. **New Feature Implementation**: Adding meaningful new functionality
|
|
11
|
+
2. **Multiple Valid Approaches**: The task can be solved in several different ways
|
|
12
|
+
3. **Multi-File Changes**: The task will likely touch more than 2-3 files
|
|
13
|
+
4. **Architectural Decisions**: Choosing between patterns or technologies
|
|
14
|
+
5. **Unclear Requirements**: You need to explore before understanding the full scope
|
|
15
|
+
6. **Significant Refactoring**: Restructuring existing code across multiple files
|
|
11
16
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
-
|
|
17
|
+
## When NOT to Use This Tool
|
|
18
|
+
|
|
19
|
+
- Single-line or few-line fixes (typos, obvious bugs, small tweaks)
|
|
20
|
+
- Adding a single function with clear requirements
|
|
21
|
+
- Tasks where the user has given very specific, detailed instructions
|
|
22
|
+
- The user explicitly asks to skip planning
|
|
23
|
+
- Simple config changes
|
|
24
|
+
|
|
25
|
+
## Important
|
|
26
|
+
|
|
27
|
+
- This tool REQUIRES user approval — they must consent to entering plan mode
|
|
28
|
+
- If the user explicitly requests planning, ALWAYS call this tool first
|
|
29
|
+
- If unsure whether to use it, err on the side of planning
|
package/src/tool/registry.ts
CHANGED
|
@@ -26,6 +26,7 @@ import { Log } from "@/util/log"
|
|
|
26
26
|
import { LspTool } from "./lsp"
|
|
27
27
|
import { Truncate } from "./truncation"
|
|
28
28
|
import { PlanExitTool, PlanEnterTool } from "./plan"
|
|
29
|
+
import { ReviewEnterTool, ReviewExitTool } from "./review"
|
|
29
30
|
import { ApplyPatchTool } from "./apply_patch"
|
|
30
31
|
|
|
31
32
|
export namespace ToolRegistry {
|
|
@@ -117,7 +118,7 @@ export namespace ToolRegistry {
|
|
|
117
118
|
ApplyPatchTool,
|
|
118
119
|
...(Flag.OPENCODE_EXPERIMENTAL_LSP_TOOL ? [LspTool] : []),
|
|
119
120
|
...(config.experimental?.batch_tool === true ? [BatchTool] : []),
|
|
120
|
-
...(Flag.
|
|
121
|
+
...(Flag.OPENCODE_CLIENT === "cli" ? [PlanExitTool, PlanEnterTool, ReviewEnterTool, ReviewExitTool] : []),
|
|
121
122
|
...custom,
|
|
122
123
|
]
|
|
123
124
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Use this tool to switch to the review agent for automated code reuse review of ServiceNow artifacts.
|
|
2
|
+
|
|
3
|
+
Call this tool when:
|
|
4
|
+
- An activity has been set to 'review' status (activity_update response contains reviewAvailable: true)
|
|
5
|
+
- The user explicitly requests a code reuse review
|
|
6
|
+
- Artifacts are ready to be analyzed before completion
|
|
7
|
+
|
|
8
|
+
This tool will ask the user if they want to switch to the review agent.
|
|
9
|
+
|
|
10
|
+
Do NOT call this tool:
|
|
11
|
+
- When there are no artifacts to review
|
|
12
|
+
- When the user has not requested review and activity is not in review status
|
|
13
|
+
- When already in review mode
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Use this tool when you have completed the code reuse review and are ready to exit review mode.
|
|
2
|
+
|
|
3
|
+
This tool will ask the user if they want to switch back to the build agent.
|
|
4
|
+
|
|
5
|
+
Call this tool:
|
|
6
|
+
- After you have completed the code reuse analysis
|
|
7
|
+
- After you have generated a JSON review report with your findings
|
|
8
|
+
- When you are confident the review is thorough and complete
|
|
9
|
+
|
|
10
|
+
Do NOT call this tool:
|
|
11
|
+
- Before you have analyzed all artifacts in the activity
|
|
12
|
+
- If you still have pending searches or analysis to complete
|
|
13
|
+
- If the user has indicated they want to continue reviewing
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import z from "zod"
|
|
2
|
+
import { Tool } from "./tool"
|
|
3
|
+
import { Question } from "../question"
|
|
4
|
+
import { Session } from "../session"
|
|
5
|
+
import { MessageV2 } from "../session/message-v2"
|
|
6
|
+
import { Identifier } from "../id/id"
|
|
7
|
+
import { Provider } from "../provider/provider"
|
|
8
|
+
import EXIT_DESCRIPTION from "./review-exit.txt"
|
|
9
|
+
import ENTER_DESCRIPTION from "./review-enter.txt"
|
|
10
|
+
|
|
11
|
+
async function getLastModel(sessionID: string) {
|
|
12
|
+
for await (const item of MessageV2.stream(sessionID)) {
|
|
13
|
+
if (item.info.role === "user" && item.info.model) return item.info.model
|
|
14
|
+
}
|
|
15
|
+
return Provider.defaultModel()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const ReviewExitTool = Tool.define("review_exit", {
|
|
19
|
+
description: EXIT_DESCRIPTION,
|
|
20
|
+
parameters: z.object({
|
|
21
|
+
reviewResult: z.string().optional().describe("JSON review report with findings"),
|
|
22
|
+
approved: z.boolean().optional().describe("Whether the review approved the artifacts"),
|
|
23
|
+
}),
|
|
24
|
+
async execute(params, ctx) {
|
|
25
|
+
const answers = await Question.ask({
|
|
26
|
+
sessionID: ctx.sessionID,
|
|
27
|
+
questions: [
|
|
28
|
+
{
|
|
29
|
+
question: `Code reuse review is complete. Would you like to switch back to the build agent?`,
|
|
30
|
+
header: "Build Agent",
|
|
31
|
+
custom: false,
|
|
32
|
+
options: [
|
|
33
|
+
{ label: "Yes", description: "Switch to build agent and act on review feedback" },
|
|
34
|
+
{ label: "No", description: "Stay with review agent to continue analysis" },
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
tool: ctx.callID ? { messageID: ctx.messageID, callID: ctx.callID } : undefined,
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const answer = answers[0]?.[0]
|
|
42
|
+
if (answer === "No") throw new Question.RejectedError()
|
|
43
|
+
|
|
44
|
+
const model = await getLastModel(ctx.sessionID)
|
|
45
|
+
|
|
46
|
+
const userMsg: MessageV2.User = {
|
|
47
|
+
id: Identifier.ascending("message"),
|
|
48
|
+
sessionID: ctx.sessionID,
|
|
49
|
+
role: "user",
|
|
50
|
+
time: {
|
|
51
|
+
created: Date.now(),
|
|
52
|
+
},
|
|
53
|
+
agent: "build",
|
|
54
|
+
model,
|
|
55
|
+
}
|
|
56
|
+
await Session.updateMessage(userMsg)
|
|
57
|
+
|
|
58
|
+
const reviewSummary = params.reviewResult
|
|
59
|
+
? `\n\nReview result:\n${params.reviewResult}`
|
|
60
|
+
: ""
|
|
61
|
+
const approvalStatus = params.approved !== undefined
|
|
62
|
+
? `\nApproved: ${params.approved}`
|
|
63
|
+
: ""
|
|
64
|
+
|
|
65
|
+
await Session.updatePart({
|
|
66
|
+
id: Identifier.ascending("part"),
|
|
67
|
+
messageID: userMsg.id,
|
|
68
|
+
sessionID: ctx.sessionID,
|
|
69
|
+
type: "text",
|
|
70
|
+
text: `The code reuse review has been completed.${approvalStatus}${reviewSummary}`,
|
|
71
|
+
synthetic: true,
|
|
72
|
+
} satisfies MessageV2.TextPart)
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
title: "Switching to build agent",
|
|
76
|
+
output: "User approved switching to build agent. Wait for further instructions.",
|
|
77
|
+
metadata: {},
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
export const ReviewEnterTool = Tool.define("review_enter", {
|
|
83
|
+
description: ENTER_DESCRIPTION,
|
|
84
|
+
parameters: z.object({
|
|
85
|
+
activityId: z.string().optional().describe("Activity ID from the activity_update response"),
|
|
86
|
+
artifacts: z.string().optional().describe("JSON array of artifact details to review"),
|
|
87
|
+
updateSetName: z.string().optional().describe("Name of the update set being reviewed"),
|
|
88
|
+
}),
|
|
89
|
+
async execute(params, ctx) {
|
|
90
|
+
const answers = await Question.ask({
|
|
91
|
+
sessionID: ctx.sessionID,
|
|
92
|
+
questions: [
|
|
93
|
+
{
|
|
94
|
+
question: `Activity is ready for code reuse review. Would you like to switch to the review agent?`,
|
|
95
|
+
header: "Review Mode",
|
|
96
|
+
custom: false,
|
|
97
|
+
options: [
|
|
98
|
+
{ label: "Yes", description: "Switch to review agent for code reuse analysis" },
|
|
99
|
+
{ label: "No", description: "Stay with build agent and skip review" },
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
tool: ctx.callID ? { messageID: ctx.messageID, callID: ctx.callID } : undefined,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
const answer = answers[0]?.[0]
|
|
107
|
+
if (answer === "No") throw new Question.RejectedError()
|
|
108
|
+
|
|
109
|
+
const model = await getLastModel(ctx.sessionID)
|
|
110
|
+
|
|
111
|
+
const userMsg: MessageV2.User = {
|
|
112
|
+
id: Identifier.ascending("message"),
|
|
113
|
+
sessionID: ctx.sessionID,
|
|
114
|
+
role: "user",
|
|
115
|
+
time: {
|
|
116
|
+
created: Date.now(),
|
|
117
|
+
},
|
|
118
|
+
agent: "review",
|
|
119
|
+
model,
|
|
120
|
+
}
|
|
121
|
+
await Session.updateMessage(userMsg)
|
|
122
|
+
|
|
123
|
+
const context = [
|
|
124
|
+
"User has requested to enter review mode. Switch to review mode and begin code reuse analysis.",
|
|
125
|
+
params.activityId ? `Activity ID: ${params.activityId}` : "",
|
|
126
|
+
params.updateSetName ? `Update Set: ${params.updateSetName}` : "",
|
|
127
|
+
params.artifacts ? `Artifacts to review:\n${params.artifacts}` : "",
|
|
128
|
+
]
|
|
129
|
+
.filter(Boolean)
|
|
130
|
+
.join("\n")
|
|
131
|
+
|
|
132
|
+
await Session.updatePart({
|
|
133
|
+
id: Identifier.ascending("part"),
|
|
134
|
+
messageID: userMsg.id,
|
|
135
|
+
sessionID: ctx.sessionID,
|
|
136
|
+
type: "text",
|
|
137
|
+
text: context,
|
|
138
|
+
synthetic: true,
|
|
139
|
+
} satisfies MessageV2.TextPart)
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
title: "Switching to review agent",
|
|
143
|
+
output: "User confirmed to switch to review mode. A new message has been created to switch you to review mode. Begin code reuse analysis.",
|
|
144
|
+
metadata: {},
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
})
|