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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
- "version": "10.0.76",
3
+ "version": "10.0.78",
4
4
  "name": "snow-flow",
5
5
  "description": "Snow-Flow - ServiceNow Multi-Agent Development Framework powered by AI",
6
6
  "license": "Elastic-2.0",
@@ -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>
@@ -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
 
@@ -1,14 +1,29 @@
1
- Use this tool to suggest switching to plan agent when the user's request would benefit from planning before implementation.
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
- If they explicitly mention wanting to create a plan ALWAYS call this tool first.
5
+ ## When to Use This Tool
4
6
 
5
- This tool will ask the user if they want to switch to plan agent.
7
+ **Prefer using plan mode** for implementation tasks unless they're simple.
8
+ Use it when ANY of these conditions apply:
6
9
 
7
- Call this tool when:
8
- - The user's request is complex and would benefit from planning first
9
- - You want to research and design before making changes
10
- - The task involves multiple files or significant architectural decisions
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
- Do NOT call this tool:
13
- - For simple, straightforward tasks
14
- - When the user explicitly wants immediate implementation
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
@@ -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.OPENCODE_EXPERIMENTAL_PLAN_MODE && Flag.OPENCODE_CLIENT === "cli" ? [PlanExitTool, PlanEnterTool] : []),
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
+ })