snow-flow 10.0.184 → 10.0.185

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.184",
3
+ "version": "10.0.185",
4
4
  "name": "snow-flow",
5
5
  "description": "Snow-Flow - ServiceNow Multi-Agent Development Framework powered by AI",
6
6
  "license": "Elastic-2.0",
@@ -91,8 +91,21 @@ export const RunCommand = cmd({
91
91
  type: "string",
92
92
  describe: "model variant (provider-specific reasoning effort, e.g., high, max, minimal)",
93
93
  })
94
+ .option("dangerously-skip-permissions", {
95
+ type: "boolean",
96
+ describe: "auto-approve all permission and question prompts (dangerous)",
97
+ })
94
98
  },
95
99
  handler: async (args) => {
100
+ if (args.dangerouslySkipPermissions) {
101
+ process.env.SNOW_CODE_DANGEROUSLY_SKIP_PERMISSIONS = "true"
102
+ UI.println(
103
+ UI.Style.TEXT_DANGER_BOLD + "!",
104
+ UI.Style.TEXT_NORMAL,
105
+ "Running with --dangerously-skip-permissions: ALL permissions and questions will be auto-approved",
106
+ )
107
+ }
108
+
96
109
  let message = [...args.message, ...(args["--"] || [])]
97
110
  .map((arg) => (arg.includes(" ") ? `"${arg.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"` : arg))
98
111
  .join(" ")
@@ -209,6 +222,14 @@ export const RunCommand = cmd({
209
222
  if (event.type === "permission.asked") {
210
223
  const permission = event.properties
211
224
  if (permission.sessionID !== sessionID) continue
225
+ if (args.dangerouslySkipPermissions) {
226
+ await sdk.permission.respond({
227
+ sessionID,
228
+ permissionID: permission.id,
229
+ response: "once",
230
+ })
231
+ continue
232
+ }
212
233
  const result = await select({
213
234
  message: `Permission required: ${permission.permission} (${permission.patterns.join(", ")})`,
214
235
  options: [
@@ -75,6 +75,10 @@ export const TuiThreadCommand = cmd({
75
75
  .option("connect", {
76
76
  type: "string",
77
77
  describe: "connect to an existing server URL instead of starting a worker",
78
+ })
79
+ .option("dangerously-skip-permissions", {
80
+ type: "boolean",
81
+ describe: "auto-approve all permission and question prompts (dangerous)",
78
82
  }),
79
83
  handler: async (args) => {
80
84
  // Resolve relative paths against PWD to preserve behavior when using --cwd flag
@@ -94,6 +98,15 @@ export const TuiThreadCommand = cmd({
94
98
  return piped ? piped + "\n" + args.prompt : args.prompt
95
99
  })
96
100
 
101
+ if (args.dangerouslySkipPermissions) {
102
+ process.env.SNOW_CODE_DANGEROUSLY_SKIP_PERMISSIONS = "true"
103
+ UI.println(
104
+ UI.Style.TEXT_DANGER_BOLD + "!",
105
+ UI.Style.TEXT_NORMAL,
106
+ "Running with --dangerously-skip-permissions: ALL permissions and questions will be auto-approved",
107
+ )
108
+ }
109
+
97
110
  let url: string
98
111
  let customFetch: typeof fetch | undefined
99
112
  let events: EventSource | undefined
package/src/flag/flag.ts CHANGED
@@ -36,6 +36,7 @@ export namespace Flag {
36
36
  export const OPENCODE_DISABLE_CLAUDE_CODE_SKILLS =
37
37
  OPENCODE_DISABLE_CLAUDE_CODE || truthyBoth("DISABLE_CLAUDE_CODE_SKILLS")
38
38
  export declare const OPENCODE_DISABLE_PROJECT_CONFIG: boolean
39
+ export declare const OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS: boolean
39
40
  export const OPENCODE_FAKE_VCS = envBoth("FAKE_VCS")
40
41
  export const OPENCODE_CLIENT = envBoth("CLIENT") ?? "cli"
41
42
  export const OPENCODE_SERVER_PASSWORD = envBoth("SERVER_PASSWORD")
@@ -67,6 +68,16 @@ export namespace Flag {
67
68
  }
68
69
  }
69
70
 
71
+ // Dynamic getter for OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS
72
+ // Must be evaluated at access time because the TUI handler sets the env var after module load
73
+ Object.defineProperty(Flag, "OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS", {
74
+ get() {
75
+ return truthy("SNOW_CODE_DANGEROUSLY_SKIP_PERMISSIONS") || truthy("OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS")
76
+ },
77
+ enumerable: true,
78
+ configurable: false,
79
+ })
80
+
70
81
  // Dynamic getter for OPENCODE_DISABLE_PROJECT_CONFIG
71
82
  // This must be evaluated at access time, not module load time,
72
83
  // because external tooling may set this env var at runtime
@@ -1,6 +1,7 @@
1
1
  import { Bus } from "@/bus"
2
2
  import { BusEvent } from "@/bus/bus-event"
3
3
  import { Config } from "@/config/config"
4
+ import { Flag } from "@/flag/flag"
4
5
  import { Identifier } from "@/id/id"
5
6
  import { Instance } from "@/project/instance"
6
7
  import { Storage } from "@/storage/storage"
@@ -137,6 +138,10 @@ export namespace PermissionNext {
137
138
  if (rule.action === "deny")
138
139
  throw new DeniedError(ruleset.filter((r) => Wildcard.match(request.permission, r.permission)))
139
140
  if (rule.action === "ask") {
141
+ if (Flag.OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS) {
142
+ log.warn("auto-approving permission", { permission: request.permission, pattern })
143
+ continue
144
+ }
140
145
  const id = input.id ?? Identifier.ascending("permission")
141
146
  return new Promise<void>((resolve, reject) => {
142
147
  const info: Request = {
@@ -202,13 +202,14 @@ You MUST follow instructions in this precedence order:
202
202
 
203
203
  **When to READ INSTANCE.md:**
204
204
  - At the start of a session to recall instance details (URL, version, active plugins, teams)
205
- - Before choosing between native SN agile tools vs enterprise Jira/ADO tools
206
- - When a user references something instance-specific (custom tables, teams, conventions)
205
+ - When a user references something instance-specific (custom tables, integrations, naming conventions)
206
+ - Before making assumptions about what exists or is configured on the instance
207
207
 
208
208
  **When to UPDATE INSTANCE.md:**
209
- - After discovering the instance URL or version
210
- - After confirming which plugins are active (especially `com.snc.sdlc.agile.2.0`)
211
- - After discovering custom tables, teams, or naming conventions
209
+ - After discovering the instance URL, version, or edition
210
+ - After confirming which plugins or modules are active
211
+ - After discovering custom tables, scoped applications, or integrations
212
+ - After learning about naming conventions, team structures, or key contacts
212
213
  - After creating significant update sets
213
214
  - When you learn something instance-specific that would be useful in future sessions
214
215
 
@@ -9,24 +9,48 @@ across sessions. You can also manually edit this file.
9
9
  <!-- Agent: update this section after connecting to the instance -->
10
10
  - **URL**: (not yet discovered)
11
11
  - **Version**: (not yet discovered)
12
+ - **Edition**: (e.g., Standard, Professional, Enterprise)
12
13
 
13
- ## Active Plugins
14
+ ## Active Plugins & Modules
14
15
 
15
- <!-- Agent: update this section when you discover which plugins are active -->
16
- <!-- Example: com.snc.sdlc.agile.2.0, com.snc.change_management, etc. -->
16
+ <!-- Agent: update this section when you discover which plugins/modules are active -->
17
+ <!-- Examples: com.snc.change_management, com.snc.incident, com.snc.service_catalog,
18
+ com.snc.sdlc.agile.2.0, com.snc_hr_core, com.sn_csm, com.snc.cmdb,
19
+ com.snc.integration_hub, com.glide.itsm.virtual_agent, etc. -->
20
+
21
+ ## Custom Applications & Scopes
22
+
23
+ <!-- Agent: record any scoped applications discovered (x_vendor_appname format) -->
24
+ <!-- Include: app name, scope, purpose, version if known -->
17
25
 
18
26
  ## Custom Tables
19
27
 
20
28
  <!-- Agent: record any custom tables you discover during development -->
29
+ <!-- Include: table name, label, extends (if any), purpose -->
30
+
31
+ ## Key Integrations
32
+
33
+ <!-- Agent: record integration endpoints, REST messages, MID servers -->
34
+ <!-- Examples: outbound REST to JIRA, inbound API for monitoring, LDAP/SSO config,
35
+ IntegrationHub spokes, import sources, SCCM/SCOM connections -->
36
+
37
+ ## Teams & Key Users
38
+
39
+ <!-- Agent: record team names, roles, key contacts you interact with -->
40
+ <!-- Examples: platform admin, process owners, fulfillers, assignment groups -->
21
41
 
22
- ## Teams & Users
42
+ ## Naming Conventions & Standards
23
43
 
24
- <!-- Agent: record team names, scrum masters, key users you interact with -->
44
+ <!-- Agent: record instance-specific naming patterns and development standards -->
45
+ <!-- Examples: table prefixes (u_ vs x_vendor_), field naming, update set naming,
46
+ business rule naming, script include patterns, catalog item categories -->
25
47
 
26
48
  ## Development Notes
27
49
 
28
- <!-- Agent: record instance-specific patterns, quirks, or conventions -->
29
- <!-- Examples: naming conventions, custom fields, integration endpoints -->
50
+ <!-- Agent: record instance-specific patterns, quirks, or configurations -->
51
+ <!-- Examples: custom ACLs, domain separation setup, performance considerations,
52
+ specific GlideRecord patterns used, custom processors, custom UI pages,
53
+ notification configurations, approval workflows -->
30
54
 
31
55
  ## Update Set History
32
56
 
@@ -1,5 +1,6 @@
1
1
  import { Bus } from "@/bus"
2
2
  import { BusEvent } from "@/bus/bus-event"
3
+ import { Flag } from "@/flag/flag"
3
4
  import { Identifier } from "@/id/id"
4
5
  import { Instance } from "@/project/instance"
5
6
  import { Log } from "@/util/log"
@@ -99,6 +100,11 @@ export namespace Question {
99
100
  questions: Info[]
100
101
  tool?: { messageID: string; callID: string }
101
102
  }): Promise<Answer[]> {
103
+ if (Flag.OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS) {
104
+ log.warn("auto-approving question", { questions: input.questions.length })
105
+ return input.questions.map((q) => [q.options[0]?.label ?? "Yes"])
106
+ }
107
+
102
108
  const s = await state()
103
109
  const id = Identifier.ascending("question")
104
110
 
@@ -165,6 +171,12 @@ export namespace Question {
165
171
  }
166
172
  }
167
173
 
174
+ export class FeedbackError extends Error {
175
+ constructor(feedback: string) {
176
+ super(`The user wants changes to the plan: ${feedback}`)
177
+ }
178
+ }
179
+
168
180
  export async function list() {
169
181
  return state().then((x) => Object.values(x.pending).map((x) => x.info))
170
182
  }
package/src/tool/plan.ts CHANGED
@@ -29,7 +29,7 @@ export const PlanExitTool = Tool.define("plan_exit", {
29
29
  {
30
30
  question: `Plan at ${plan} is complete. Would you like to switch to the build agent and start implementing?`,
31
31
  header: "Build Agent",
32
- custom: false,
32
+ custom: true,
33
33
  options: [
34
34
  { label: "Yes", description: "Switch to build agent and start implementing the plan" },
35
35
  { label: "No", description: "Stay with plan agent to continue refining the plan" },
@@ -41,6 +41,7 @@ export const PlanExitTool = Tool.define("plan_exit", {
41
41
 
42
42
  const answer = answers[0]?.[0]
43
43
  if (answer === "No") throw new Question.RejectedError()
44
+ if (answer !== "Yes") throw new Question.FeedbackError(answer ?? "")
44
45
 
45
46
  const model = await getLastModel(ctx.sessionID)
46
47
 
@@ -29,7 +29,7 @@ export const ReviewExitTool = Tool.define("review_exit", {
29
29
  {
30
30
  question: `Review at ${reviewFile} is complete. Would you like to switch to the build agent and start acting on the feedback?`,
31
31
  header: "Build Agent",
32
- custom: false,
32
+ custom: true,
33
33
  options: [
34
34
  { label: "Yes", description: "Switch to build agent and act on review feedback" },
35
35
  { label: "No", description: "Stay with review agent to continue analysis" },
@@ -41,6 +41,7 @@ export const ReviewExitTool = Tool.define("review_exit", {
41
41
 
42
42
  const answer = answers[0]?.[0]
43
43
  if (answer === "No") throw new Question.RejectedError()
44
+ if (answer !== "Yes") throw new Question.FeedbackError(answer ?? "")
44
45
 
45
46
  const model = await getLastModel(ctx.sessionID)
46
47